From 7cb1d9e2dbbe5bf4652be5d78cdd68e956fa3d63 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 22 Jan 2017 16:42:36 +0100 Subject: [PATCH 0001/2557] build: Fine-grained link-time dependency settings Previously, all link-time dependencies were added for all libraries, resulting in bogus link-time dependencies since not all dependencies are shared across libraries. Also, in some cases like libavutil, not all dependencies were taken into account, resulting in some cases of underlinking. To address all this mess a machinery is added for tracking which dependency belongs to which library component and then leveraged to determine correct dependencies for all individual libraries. --- Makefile | 2 +- avbuild/common.mak | 2 +- avbuild/library.mak | 2 +- configure | 156 +++++++++++++++++++++++++++++----------- tests/checkasm/Makefile | 2 +- 5 files changed, 119 insertions(+), 45 deletions(-) diff --git a/Makefile b/Makefile index a3cd0846e1433..80d50d82534a4 100644 --- a/Makefile +++ b/Makefile @@ -97,7 +97,7 @@ FF_DEP_LIBS := $(DEP_LIBS) FF_STATIC_DEP_LIBS := $(STATIC_DEP_LIBS) $(TOOLS): %$(EXESUF): %.o - $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(EXTRALIBS) $(ELIBS) + $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(EXTRALIBS-$(*F)) $(EXTRALIBS) $(ELIBS) CONFIGURABLE_COMPONENTS = \ $(wildcard $(FFLIBS:%=$(SRC_PATH)/lib%/all*.c)) \ diff --git a/avbuild/common.mak b/avbuild/common.mak index 236380effcd28..a627dc0ccf93c 100644 --- a/avbuild/common.mak +++ b/avbuild/common.mak @@ -8,7 +8,7 @@ OBJS += $(OBJS-yes) FFLIBS := $($(NAME)_FFLIBS) $(FFLIBS-yes) $(FFLIBS) TESTPROGS += $(TESTPROGS-yes) -FFEXTRALIBS := $(FFLIBS:%=$(LD_LIB)) $(EXTRALIBS) +FFEXTRALIBS := $(FFLIBS:%=$(LD_LIB)) $(foreach lib,EXTRALIBS-$(NAME) $(FFLIBS:%=EXTRALIBS-%),$($(lib))) $(EXTRALIBS) OBJS := $(sort $(OBJS:%=$(SUBDIR)%)) TESTOBJS := $(TESTOBJS:%=$(SUBDIR)tests/%) $(TESTPROGS:%=$(SUBDIR)tests/%.o) diff --git a/avbuild/library.mak b/avbuild/library.mak index e5f6d7d288aa5..be6098c9ffeb7 100644 --- a/avbuild/library.mak +++ b/avbuild/library.mak @@ -30,7 +30,7 @@ $(TOOLS): THISLIB = $(NAME:%=$(LD_LIB)) $(TESTPROGS): THISLIB = $(SUBDIR)$(LIBNAME) $(TESTPROGS) $(TOOLS): %$(EXESUF): %.o - $$(LD) $(LDFLAGS) $(LDEXEFLAGS) $$(LD_O) $$(filter %.o,$$^) $$(THISLIB) $(FFEXTRALIBS) $$(ELIBS) + $$(LD) $(LDFLAGS) $(LDEXEFLAGS) $$(LD_O) $$(filter %.o,$$^) $$(THISLIB) $(FFEXTRALIBS) $$(EXTRALIBS-$$(*F)) $$(ELIBS) $(SUBDIR)lib$(NAME).version: $(SUBDIR)version.h | $(SUBDIR) $$(M) $$(SRC_PATH)/avbuild/libversion.sh $(NAME) $$< > $$@ diff --git a/configure b/configure index 85ce5f581f89c..5af7df3057fc1 100755 --- a/configure +++ b/configure @@ -610,7 +610,7 @@ is_in(){ return 1 } -do_check_deps(){ +check_deps(){ for cfg; do enabled ${cfg}_checking && die "Circular dependency for $cfg." disabled ${cfg}_checking && continue @@ -626,7 +626,7 @@ do_check_deps(){ eval dep_ifn="\$${cfg}_if_any" pushvar cfg dep_all dep_any dep_con dep_sel dep_sgs dep_ifa dep_ifn - do_check_deps $dep_all $dep_any $dep_con $dep_sel $dep_sgs $dep_ifa $dep_ifn + check_deps $dep_all $dep_any $dep_con $dep_sel $dep_sgs $dep_ifa $dep_ifn popvar cfg dep_all dep_any dep_con dep_sel dep_sgs dep_ifa dep_ifn [ -n "$dep_ifa" ] && { enabled_all $dep_ifa && enable_weak $cfg; } @@ -639,24 +639,17 @@ do_check_deps(){ if enabled $cfg; then enable_deep $dep_sel enable_deep_weak $dep_sgs + for dep in $dep_all $dep_any $dep_sgs; do + # filter out library deps, these do not belong in extralibs + is_in $dep $LIBRARY_LIST && continue + enabled $dep && eval append ${cfg}_extralibs ${dep}_extralibs + done fi disable ${cfg}_checking done } -check_deps(){ - unset allopts - - do_check_deps "$@" - - for cfg in $allopts; do - enabled $cfg || continue - eval dep_extralibs="\$${cfg}_extralibs" - test -n "$dep_extralibs" && add_extralibs $dep_extralibs - done -} - print_config(){ pfx=$1 files=$2 @@ -711,6 +704,15 @@ unique(){ eval "$var=\"${uniq_list}\"" } +resolve(){ + var=$1 + tmpvar= + for entry in $(eval echo \$$var); do + tmpvar="$tmpvar $(eval echo \$${entry})" + done + eval "$var=\"${tmpvar}\"" +} + add_cppflags(){ append CPPFLAGS "$@" } @@ -1015,7 +1017,7 @@ check_lib(){ shift 3 disable $name check_func_headers "$headers" "$funcs" "$@" && - enable $name && add_extralibs "$@" + enable $name && eval ${name}_extralibs="\$@" } check_pkg_config(){ @@ -1033,7 +1035,7 @@ check_pkg_config(){ check_func_headers "$headers" "$funcs" $pkg_cflags $pkg_libs "$@" && enable $name && add_cflags "$pkg_cflags" && - add_extralibs "$pkg_libs" + eval $(sanitize_var_name ${name}_extralibs)="\$pkg_libs" } check_exec(){ @@ -1252,6 +1254,12 @@ EXAMPLE_LIST=" transcode_aac_example " +# catchall list of things that require external libs to link +EXTRALIBS_LIST=" + cpu_init + cws2fws +" + HWACCEL_LIBRARY_NONFREE_LIST=" cuda libnpp @@ -2497,6 +2505,10 @@ output_example_deps="avcodec avformat avresample avutil swscale" qsvdec_example_deps="avcodec avutil libmfx h264_qsv_decoder" transcode_aac_example_deps="avcodec avformat avresample" +# EXTRALIBS_LIST +cpu_init_extralibs="pthreads_extralibs" +cws2fws_extralibs="zlib_extralibs" + # libraries, in linking order avcodec_deps="avutil" avcodec_select="null_bsf" @@ -2507,15 +2519,25 @@ avformat_suggest="network" avresample_deps="avutil" swscale_deps="avutil" +avcodec_extralibs="pthreads_extralibs libm_extralibs" +avdevice_extralibs="libm_extralibs" +avformat_extralibs="libm_extralibs" +avfilter_extralibs="pthreads_extralibs libm_extralibs" +avresample_extralibs="libm_extralibs" +avutil_extralibs="clock_gettime_extralibs cuda_extralibs libm_extralibs libmfx_extralibs nanosleep_extralibs user32_extralibs vaapi_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs wincrypt_extralibs" +swscale_extralibs="libm_extralibs" + # programs avconv_deps="avcodec avfilter avformat avresample swscale" avconv_select="aformat_filter anull_filter asyncts_filter atrim_filter format_filter fps_filter null_filter resample_filter scale_filter trim_filter" +avconv_suggest="dxva2_lib ole32 psapi shell32" avplay_deps="avcodec avfilter avformat avresample sdl" -avplay_extralibs='$sdl_extralibs' avplay_select="rdft format_filter transpose_filter hflip_filter vflip_filter" +avplay_suggest="shell32" avprobe_deps="avcodec avformat" +avprobe_suggest="shell32" # documentation pod2man_deps="doc" @@ -2573,6 +2595,9 @@ enable valgrind_backtrace # By default, enable only those hwaccels that have no external dependencies. enable d3d11va dxva2 vda vdpau +# internal components are enabled by default +enable $EXTRALIBS_LIST + # Avoid external, non-system, libraries getting enabled by dependency resolution disable $EXTERNAL_LIBRARY_LIST @@ -2669,20 +2694,36 @@ find_things_extern(){ BSF_LIST=$(find_things_extern bsf AVBitStreamFilter libavcodec/bitstream_filters.c) PROTOCOL_LIST=$(find_things_extern protocol URLProtocol libavformat/protocols.c) -ALL_COMPONENTS=" +AVCODEC_COMPONENTS_LIST=" $BSF_LIST $DECODER_LIST - $DEMUXER_LIST $ENCODER_LIST - $FILTER_LIST $HWACCEL_LIST + $PARSER_LIST +" + +AVDEVICE_COMPONENTS_LIST=" $INDEV_LIST - $MUXER_LIST $OUTDEV_LIST - $PARSER_LIST +" + +AVFILTER_COMPONENTS_LIST=" + $FILTER_LIST +" + +AVFORMAT_COMPONENTS_LIST=" + $DEMUXER_LIST + $MUXER_LIST $PROTOCOL_LIST " +ALL_COMPONENTS=" + $AVCODEC_COMPONENTS_LIST + $AVDEVICE_COMPONENTS_LIST + $AVFILTER_COMPONENTS_LIST + $AVFORMAT_COMPONENTS_LIST +" + for n in $COMPONENT_LIST; do v=$(toupper ${n%s})_LIST eval enable \$$v @@ -4525,7 +4566,7 @@ check_func ${malloc_prefix}posix_memalign && enable posix_memalign check_cpp_condition unistd.h "defined(_POSIX_MONOTONIC_CLOCK)" && check_func_headers time.h clock_gettime || - { check_lib clock_gettime time.h clock_gettime -lrt && LIBRT="-lrt"; } + check_lib clock_gettime time.h clock_gettime -lrt check_func fcntl check_func fork @@ -4638,14 +4679,14 @@ disabled bzlib || check_lib bzlib bzlib.h BZ2_bzlibVersion -lbz2 # On some systems dynamic loading requires no extra linker flags check_lib libdl dlfcn.h dlopen || check_lib libdl dlfcn.h dlopen -ldl -check_lib libm math.h sin -lm && LIBM="-lm" +check_lib libm math.h sin -lm atan2f_args=2 ldexpf_args=2 powf_args=2 for func in $MATH_FUNCS; do - eval check_mathfunc $func \${${func}_args:-1} $LIBM + eval check_mathfunc $func \${${func}_args:-1} $libm_extralibs done # these are off by default, so fail if requested and not available @@ -4716,10 +4757,10 @@ enabled mmal && { check_lib mmal interface/mmal/mmal.h mmal_port_co check_lib mmal interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host; } || die "ERROR: mmal not found" && check_func_headers interface/mmal/mmal.h "MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS"; } +enabled omx && require_header OMX_Core.h enabled omx_rpi && { check_header OMX_Core.h || { ! enabled cross_compile && add_cflags -isystem/opt/vc/include/IL && check_header OMX_Core.h ; } || - die "ERROR: OpenMAX IL headers not found"; } -enabled omx && require_header OMX_Core.h + die "ERROR: OpenMAX IL headers not found"; } && enable omx enabled openssl && { { check_pkg_config openssl openssl openssl/ssl.h OPENSSL_init_ssl || check_pkg_config openssl openssl openssl/ssl.h SSL_library_init; } || check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto || @@ -5069,6 +5110,43 @@ check_deps $CONFIG_LIST \ $HAVE_LIST \ $ALL_COMPONENTS \ +flatten_extralibs(){ + unset nested_entries + list_name=$1 + eval list=\$${1} + for entry in $list; do + entry_copy=$entry + resolve entry_copy + append nested_entries $(filter '*_extralibs' $entry_copy) + flat_entries=$(filter_out '*_extralibs' $entry_copy) + eval $entry="\$flat_entries" + done + append $list_name "$nested_entries" + + resolve nested_entries + if test -n "$(filter '*_extralibs' $nested_entries)"; then + flatten_extralibs $list_name + fi +} + +for linkunit in $LIBRARY_LIST; do + unset current_extralibs + eval components=\$$(toupper ${linkunit})_COMPONENTS_LIST + for comp in ${components}; do + enabled $comp || continue + comp_extralibs="${comp}_extralibs" + append current_extralibs $comp_extralibs + done + eval prepend ${linkunit}_extralibs $current_extralibs +done + +for linkunit in $LIBRARY_LIST $PROGRAM_LIST $EXTRALIBS_LIST; do + flatten_extralibs ${linkunit}_extralibs + unique ${linkunit}_extralibs + resolve ${linkunit}_extralibs + eval ${linkunit}_extralibs=\$\(\$ldflags_filter \$${linkunit}_extralibs\) +done + map 'enabled $v && intrinsics=${v#intrinsics_}' $INTRINSICS_LIST for thread in $THREADS_LIST; do @@ -5313,7 +5391,6 @@ TARGET_PATH=$target_path TARGET_SAMPLES=${target_samples:-\$(SAMPLES)} CFLAGS-avplay=$sdl_cflags CFLAGS_HEADERS=$CFLAGS_HEADERS -ZLIB=$($ldflags_filter -lz) LIB_INSTALL_EXTRA_CMD=$LIB_INSTALL_EXTRA_CMD EXTRALIBS=$extralibs COMPAT_OBJS=$compat_objs @@ -5335,12 +5412,9 @@ EOF map 'eval echo "${v}_FFLIBS=\$${v}_deps" >> avbuild/config.mak' $LIBRARY_LIST -print_program_extralibs(){ - eval "program_extralibs=\$${1}_extralibs" - eval echo "EXTRALIBS-${1}=${program_extralibs}" >> avbuild/config.mak -} - -map 'print_program_extralibs $v' $PROGRAM_LIST +for entry in $LIBRARY_LIST $PROGRAM_LIST $EXTRALIBS_LIST; do + eval echo "EXTRALIBS-${entry}=\$${entry}_extralibs" >> avbuild/config.mak +done cat > $TMPH < Date: Tue, 28 Feb 2017 18:35:10 +0100 Subject: [PATCH 0002/2557] x86: hevc: Add missing colons after assembly labels This fixes several warnings of the sort warning: label alone on a line without a colon might be in error --- libavcodec/x86/hevc_add_res.asm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/x86/hevc_add_res.asm b/libavcodec/x86/hevc_add_res.asm index 66b929c594712..4701e9d45d6b5 100644 --- a/libavcodec/x86/hevc_add_res.asm +++ b/libavcodec/x86/hevc_add_res.asm @@ -330,7 +330,7 @@ cglobal hevc_add_residual_32_10, 3, 5, 6 mova m5, [max_pixels_10] mov r4d, 32 -.loop +.loop: ADD_RES_SSE_32_10 r0, r1 lea r0, [r0+r2] add r1, 64 @@ -346,7 +346,7 @@ cglobal hevc_add_residual_16_10, 3, 5, 6 lea r3, [r2*3] mov r4d, 4 -.loop +.loop: ADD_RES_AVX2_16_10 r0, r2, r3, r1 lea r0, [r0+r2*4] add r1, 128 @@ -359,7 +359,7 @@ cglobal hevc_add_residual_32_10, 3, 5, 6 mova m5, [max_pixels_10] mov r4d, 16 -.loop +.loop: ADD_RES_AVX2_32_10 r0, r2, r1 lea r0, [r0+r2*2] add r1, 128 From 58407b4d74c99e30dbd40fe468c69dbd25ea4255 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 28 Feb 2017 19:01:28 +0100 Subject: [PATCH 0003/2557] configure: Fix typo in objcc default setting Also drop stray duplicate OBJCC config.mak entry. --- configure | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure b/configure index 5af7df3057fc1..d3921da31ce9f 100755 --- a/configure +++ b/configure @@ -2991,7 +2991,7 @@ fi ar_default="${cross_prefix}${ar_default}" cc_default="${cross_prefix}${cc_default}" -occ_default="${cross_prefix}${occ_default}" +objcc_default="${cross_prefix}${objcc_default}" nm_default="${cross_prefix}${nm_default}" pkg_config_default="${cross_prefix}${pkg_config_default}" ranlib="${cross_prefix}${ranlib}" @@ -5321,7 +5321,6 @@ CC_IDENT=$cc_ident ARCH=$arch INTRINSICS=$intrinsics CC=$cc -OBJCC=$cc AS=$as OBJCC=$objcc LD=$ld From 4d1f7e8bc7516e6b7b15f754af4a665b3f8af79e Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 28 Feb 2017 22:12:18 +0100 Subject: [PATCH 0004/2557] build: Skip generating .version files when cleaning --- avbuild/library.mak | 2 ++ 1 file changed, 2 insertions(+) diff --git a/avbuild/library.mak b/avbuild/library.mak index be6098c9ffeb7..227e4d5d481ca 100644 --- a/avbuild/library.mak +++ b/avbuild/library.mak @@ -1,6 +1,8 @@ include $(SRC_PATH)/avbuild/common.mak +ifeq (,$(filter %clean,$(MAKECMDGOALS))) -include $(SUBDIR)lib$(NAME).version +endif LIBVERSION := $(lib$(NAME)_VERSION) LIBMAJOR := $(lib$(NAME)_VERSION_MAJOR) From d1d6230ea3dd2c34bcd121f958706f3177f8d8c5 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 28 Feb 2017 22:11:39 +0100 Subject: [PATCH 0005/2557] build: Add "build" shorthand target that depends on all compile targets --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 80d50d82534a4..dc4b0add9f917 100644 --- a/Makefile +++ b/Makefile @@ -179,6 +179,7 @@ distclean:: config: $(SRC_PATH)/configure $(value LIBAV_CONFIGURATION) +build: all alltools checkheaders examples testprogs check: all alltools checkheaders examples testprogs fate include $(SRC_PATH)/tests/Makefile @@ -194,4 +195,5 @@ $(sort $(OBJDIRS)): # so this saves some time on slow systems. .SUFFIXES: -.PHONY: all all-yes alltools check *clean config install* testprogs uninstall* +.PHONY: all all-yes alltools build check config testprogs +.PHONY: *clean install* uninstall* From 39e208f4d4756367c7cd2d581847e0c1b8a429c1 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 8 Oct 2016 16:18:33 +0200 Subject: [PATCH 0006/2557] build: Generalize yasm/nasm-related variable names None of them are specific to the YASM assembler. --- Makefile | 12 +++--- avbuild/arch.mak | 2 +- configure | 65 +++++++++++++++------------- libavcodec/x86/Makefile | 72 +++++++++++++++---------------- libavcodec/x86/dcadsp_init.c | 8 ++-- libavcodec/x86/fmtconvert_init.c | 8 ++-- libavcodec/x86/h264_qpel.c | 6 +-- libavcodec/x86/hpeldsp_init.c | 4 +- libavcodec/x86/mpegaudiodsp.c | 8 ++-- libavcodec/x86/qpeldsp_init.c | 4 +- libavcodec/x86/rv40dsp_init.c | 8 ++-- libavcodec/x86/vc1dsp_init.c | 8 ++-- libavcodec/x86/videodsp_init.c | 8 ++-- libavcodec/x86/vp8dsp_init.c | 12 +++--- libavcodec/x86/vp9dsp_init.c | 8 ++-- libavfilter/x86/Makefile | 10 ++--- libavfilter/x86/vf_gradfun_init.c | 8 ++-- libavfilter/x86/vf_hqdn3d_init.c | 4 +- libavresample/x86/Makefile | 6 +-- libavutil/x86/Makefile | 10 ++--- libavutil/x86/cpu.c | 4 +- libswscale/x86/Makefile | 2 +- libswscale/x86/rgb2rgb_template.c | 4 +- tests/checkasm/Makefile | 2 +- tests/checkasm/checkasm.h | 2 +- 25 files changed, 145 insertions(+), 140 deletions(-) diff --git a/Makefile b/Makefile index dc4b0add9f917..d140ac392f2c2 100644 --- a/Makefile +++ b/Makefile @@ -11,8 +11,8 @@ vpath %.texi $(SRC_PATH) ifndef V Q = @ ECHO = printf "$(1)\t%s\n" $(2) -BRIEF = CC HOSTCC HOSTLD AS YASM AR LD -SILENT = DEPCC DEPHOSTCC DEPAS DEPYASM RANLIB RM STRIP +BRIEF = CC HOSTCC HOSTLD AS X86ASM AR LD +SILENT = DEPCC DEPHOSTCC DEPAS DEPX86ASM RANLIB RM STRIP MSG = $@ M = @$(call ECHO,$(TAG),$@); $(foreach VAR,$(BRIEF), \ @@ -30,7 +30,7 @@ CCFLAGS = $(CPPFLAGS) $(CFLAGS) OBJCFLAGS += $(EOBJCFLAGS) OBJCCFLAGS = $(CPPFLAGS) $(CFLAGS) $(OBJCFLAGS) ASFLAGS := $(CPPFLAGS) $(ASFLAGS) -YASMFLAGS += $(IFLAGS:%=%/) -Pconfig.asm +X86ASMFLAGS += $(IFLAGS:%=%/) -Pconfig.asm HOSTCCFLAGS = $(IFLAGS) $(HOSTCPPFLAGS) $(HOSTCFLAGS) LDFLAGS := $(ALLFFLIBS:%=$(LD_PATH)lib%) $(LDFLAGS) @@ -57,8 +57,8 @@ COMPILE_HOSTC = $(call COMPILE,HOSTCC) $(COMPILE_HOSTC) %.o: %.asm - $(DEPYASM) $(YASMFLAGS) -I $( $(@:.o=.d) - $(YASM) $(YASMFLAGS) -I $( $(@:.o=.d) + $(X86ASM) $(X86ASMFLAGS) -I $( $TMPS log_file $TMPS shift 1 - check_cmd $yasmexe $YASMFLAGS "$@" -o $TMPO $TMPS + check_cmd $x86asmexe $X86ASMFLAGS "$@" -o $TMPO $TMPS } ld_o(){ @@ -1533,7 +1533,7 @@ BUILTIN_LIST=" HAVE_LIST_CMDLINE=" inline_asm symver - yasm + x86asm " HAVE_LIST_PUB=" @@ -1912,7 +1912,7 @@ fma3_deps="avx" fma4_deps="avx" avx2_deps="avx" -mmx_external_deps="yasm" +mmx_external_deps="x86asm" mmx_inline_deps="inline_asm" mmx_suggest="mmx_external mmx_inline" @@ -2568,7 +2568,7 @@ pkg_config_default=pkg-config ranlib="ranlib" strip="strip" version_script='--version-script' -yasmexe="yasm" +x86asmexe="yasm" # machine arch_default=$(uname -m) @@ -2817,6 +2817,11 @@ for opt do warn "avserver has been removed, the ${opt} option is only"\ "provided for compatibility and will be removed in the future" ;; + --enable-yasm|--disable-yasm) + warn "The ${opt} option is only provided for compatibility and will be\n"\ + "removed in the future. Use --enable-x86asm / --disable-x86asm instead." + test $opt = --enable-yasm && x86asm=yes || x86asm=no + ;; --enable-?*|--disable-?*) eval $(echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g') if is_in $option $COMPONENT_LIST; then @@ -4467,30 +4472,30 @@ EOF enabled ssse3 && check_inline_asm ssse3_inline '"pabsw %xmm0, %xmm0"' enabled mmxext && check_inline_asm mmxext_inline '"pmaxub %mm0, %mm1"' - if ! disabled_any asm mmx yasm; then - if check_cmd $yasmexe --version; then - enabled x86_64 && yasm_extra="-m amd64" - yasm_debug="-g dwarf2" + if ! disabled_any asm mmx x86asm; then + if check_cmd $x86asmexe --version; then + enabled x86_64 && x86asm_extra="-m amd64" + x86asm_debug="-g dwarf2" elif check_cmd nasm -v; then - yasmexe=nasm - yasm_debug="-g -F dwarf" + x86asmexe=nasm + x86asm_debug="-g -F dwarf" enabled x86_64 && test "$objformat" = elf && objformat=elf64 fi - YASMFLAGS="-f $objformat $yasm_extra" - enabled pic && append YASMFLAGS "-DPIC" - test -n "$extern_prefix" && append YASMFLAGS "-DPREFIX" + X86ASMFLAGS="-f $objformat $x86asm_extra" + enabled pic && append X86ASMFLAGS "-DPIC" + test -n "$extern_prefix" && append X86ASMFLAGS "-DPREFIX" case "$objformat" in - elf*) enabled debug && append YASMFLAGS $yasm_debug ;; + elf*) enabled debug && append X86ASMFLAGS $x86asm_debug ;; esac - check_yasm "movbe ecx, [5]" && enable yasm || - die "yasm/nasm not found or too old. Use --disable-yasm for a crippled build." - check_yasm "vextracti128 xmm0, ymm0, 0" || disable avx2_external - check_yasm "vpmacsdd xmm0, xmm1, xmm2, xmm3" || disable xop_external - check_yasm "vfmadd132ps ymm0, ymm1, ymm2" || disable fma3_external - check_yasm "vfmaddps ymm0, ymm1, ymm2, ymm3" || disable fma4_external - check_yasm "CPU amdnop" || disable cpunop + check_x86asm "movbe ecx, [5]" && enable x86asm || + die "yasm/nasm not found or too old. Use --disable-x86asm for a crippled build." + check_x86asm "vextracti128 xmm0, ymm0, 0" || disable avx2_external + check_x86asm "vpmacsdd xmm0, xmm1, xmm2, xmm3" || disable xop_external + check_x86asm "vfmadd132ps ymm0, ymm1, ymm2" || disable fma3_external + check_x86asm "vfmaddps ymm0, ymm1, ymm2, ymm3" || disable fma4_external + check_x86asm "CPU amdnop" || disable cpunop fi case "$cpu" in @@ -5209,7 +5214,7 @@ fi echo "big-endian ${bigendian-no}" echo "runtime cpu detection ${runtime_cpudetect-no}" if enabled x86; then - echo "${yasmexe} ${yasm-no}" + echo "standalone assembly ${x86asm-no}" echo "MMX enabled ${mmx-no}" echo "MMXEXT enabled ${mmxext-no}" echo "3DNow! enabled ${amd3dnow-no}" @@ -5328,8 +5333,8 @@ DEPCC=$dep_cc DEPCCFLAGS=$DEPCCFLAGS \$(CPPFLAGS) DEPAS=$as DEPASFLAGS=$DEPASFLAGS \$(CPPFLAGS) -YASM=$yasmexe -DEPYASM=$yasmexe +X86ASM=$x86asmexe +DEPX86ASM=$x86asmexe AR=$ar ARFLAGS=$arflags AR_O=$ar_o @@ -5356,7 +5361,7 @@ LDFLAGS=$LDFLAGS LDEXEFLAGS=$LDEXEFLAGS SHFLAGS=$(echo $($ldflags_filter $SHFLAGS)) STRIPFLAGS=$STRIPFLAGS -YASMFLAGS=$YASMFLAGS +X86ASMFLAGS=$X86ASMFLAGS LIBPREF=$LIBPREF LIBSUF=$LIBSUF LIBNAME=$LIBNAME @@ -5432,7 +5437,7 @@ EOF test -n "$malloc_prefix" && echo "#define MALLOC_PREFIX $malloc_prefix" >>$TMPH -if enabled yasm; then +if enabled x86asm; then append config_files $TMPASM printf '' >$TMPASM fi @@ -5451,7 +5456,7 @@ echo "#endif /* LIBAV_CONFIG_H */" >> $TMPH cp_if_changed $TMPH config.h touch avbuild/.config -enabled yasm && cp_if_changed $TMPASM config.asm +enabled x86asm && cp_if_changed $TMPASM config.asm cat > $TMPH <synth_filter_float = synth_filter_fma3; } -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ } diff --git a/libavcodec/x86/fmtconvert_init.c b/libavcodec/x86/fmtconvert_init.c index 2f10db4fc1140..6306c8bfcb788 100644 --- a/libavcodec/x86/fmtconvert_init.c +++ b/libavcodec/x86/fmtconvert_init.c @@ -27,16 +27,16 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/fmtconvert.h" -#if HAVE_YASM +#if HAVE_X86ASM void ff_int32_to_float_fmul_scalar_sse (float *dst, const int32_t *src, float mul, int len); void ff_int32_to_float_fmul_scalar_sse2(float *dst, const int32_t *src, float mul, int len); -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ av_cold void ff_fmt_convert_init_x86(FmtConvertContext *c, AVCodecContext *avctx) { -#if HAVE_YASM +#if HAVE_X86ASM int cpu_flags = av_get_cpu_flags(); if (EXTERNAL_SSE(cpu_flags)) { @@ -45,5 +45,5 @@ av_cold void ff_fmt_convert_init_x86(FmtConvertContext *c, AVCodecContext *avctx if (EXTERNAL_SSE2(cpu_flags)) { c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_sse2; } -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ } diff --git a/libavcodec/x86/h264_qpel.c b/libavcodec/x86/h264_qpel.c index 74458259a6014..4062e9608515e 100644 --- a/libavcodec/x86/h264_qpel.c +++ b/libavcodec/x86/h264_qpel.c @@ -28,7 +28,7 @@ #include "libavcodec/pixels.h" #include "fpel.h" -#if HAVE_YASM +#if HAVE_X86ASM void ff_put_pixels4_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); void ff_avg_pixels4_mmxext(uint8_t *block, const uint8_t *pixels, @@ -503,7 +503,7 @@ QPEL16_OP(mc33, MMX) QPEL16(mmxext) #endif -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ #define SET_QPEL_FUNCS(PFX, IDX, SIZE, CPU, PREFIX) \ do { \ @@ -543,7 +543,7 @@ QPEL16(mmxext) av_cold void ff_h264qpel_init_x86(H264QpelContext *c, int bit_depth) { -#if HAVE_YASM +#if HAVE_X86ASM int high_bit_depth = bit_depth > 8; int cpu_flags = av_get_cpu_flags(); diff --git a/libavcodec/x86/hpeldsp_init.c b/libavcodec/x86/hpeldsp_init.c index 6a8d4205fa8bb..d47e7883dfdd3 100644 --- a/libavcodec/x86/hpeldsp_init.c +++ b/libavcodec/x86/hpeldsp_init.c @@ -134,7 +134,7 @@ CALL_2X_PIXELS_EXPORT(ff_put_pixels16_xy2_mmx, ff_put_pixels8_xy2_mmx, 8) #endif /* HAVE_INLINE_ASM */ -#if HAVE_YASM +#if HAVE_X86ASM #define HPELDSP_AVG_PIXELS16(CPUEXT) \ CALL_2X_PIXELS(put_no_rnd_pixels16_x2 ## CPUEXT, ff_put_no_rnd_pixels8_x2 ## CPUEXT, 8) \ @@ -148,7 +148,7 @@ CALL_2X_PIXELS_EXPORT(ff_put_pixels16_xy2_mmx, ff_put_pixels8_xy2_mmx, 8) HPELDSP_AVG_PIXELS16(_3dnow) HPELDSP_AVG_PIXELS16(_mmxext) -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ #define SET_HPEL_FUNCS(PFX, IDX, SIZE, CPU) \ do { \ diff --git a/libavcodec/x86/mpegaudiodsp.c b/libavcodec/x86/mpegaudiodsp.c index 591f5270bdd02..ffdcf1fbb77db 100644 --- a/libavcodec/x86/mpegaudiodsp.c +++ b/libavcodec/x86/mpegaudiodsp.c @@ -184,7 +184,7 @@ static void apply_window_mp3(float *in, float *win, int *unused, float *out, #endif /* HAVE_SSE2_INLINE */ -#if HAVE_YASM +#if HAVE_X86ASM #define DECL_IMDCT_BLOCKS(CPU1, CPU2) \ static void imdct36_blocks_ ## CPU1(float *out, float *buf, float *in, \ int count, int switch_point, int block_type) \ @@ -222,7 +222,7 @@ DECL_IMDCT_BLOCKS(sse2,sse) DECL_IMDCT_BLOCKS(sse3,sse) DECL_IMDCT_BLOCKS(ssse3,sse) DECL_IMDCT_BLOCKS(avx,avx) -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ av_cold void ff_mpadsp_init_x86(MPADSPContext *s) { @@ -248,7 +248,7 @@ av_cold void ff_mpadsp_init_x86(MPADSPContext *s) } #endif /* HAVE_SSE2_INLINE */ -#if HAVE_YASM +#if HAVE_X86ASM if (EXTERNAL_SSE(cpu_flags)) { s->imdct36_blocks_float = imdct36_blocks_sse; } @@ -264,5 +264,5 @@ av_cold void ff_mpadsp_init_x86(MPADSPContext *s) if (EXTERNAL_AVX(cpu_flags)) { s->imdct36_blocks_float = imdct36_blocks_avx; } -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ } diff --git a/libavcodec/x86/qpeldsp_init.c b/libavcodec/x86/qpeldsp_init.c index cdefe50a3c250..e280c82f3de74 100644 --- a/libavcodec/x86/qpeldsp_init.c +++ b/libavcodec/x86/qpeldsp_init.c @@ -80,7 +80,7 @@ void ff_put_no_rnd_mpeg4_qpel8_v_lowpass_mmxext(uint8_t *dst, #define ff_put_no_rnd_pixels16_mmxext ff_put_pixels16_mmxext #define ff_put_no_rnd_pixels8_mmxext ff_put_pixels8_mmxext -#if HAVE_YASM +#if HAVE_X86ASM CALL_2X_PIXELS(ff_avg_pixels16_mmxext, ff_avg_pixels8_mmxext, 8) CALL_2X_PIXELS(ff_put_pixels16_mmxext, ff_put_pixels8_mmxext, 8) @@ -502,7 +502,7 @@ QPEL_OP(put_, _, mmxext) QPEL_OP(avg_, _, mmxext) QPEL_OP(put_no_rnd_, _no_rnd_, mmxext) -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ #define SET_QPEL_FUNCS(PFX, IDX, SIZE, CPU, PREFIX) \ do { \ diff --git a/libavcodec/x86/rv40dsp_init.c b/libavcodec/x86/rv40dsp_init.c index f6d4165452e13..5ba0aa5fde862 100644 --- a/libavcodec/x86/rv40dsp_init.c +++ b/libavcodec/x86/rv40dsp_init.c @@ -32,7 +32,7 @@ #include "libavutil/x86/cpu.h" #include "hpeldsp.h" -#if HAVE_YASM +#if HAVE_X86ASM void ff_put_rv40_chroma_mc8_mmx (uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); void ff_avg_rv40_chroma_mc8_mmxext(uint8_t *dst, uint8_t *src, @@ -186,7 +186,7 @@ QPEL_FUNCS_SET (OP, 3, 1, OPT) \ QPEL_FUNCS_SET (OP, 3, 2, OPT) /** @} */ -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ #if HAVE_MMX_INLINE static void put_rv40_qpel8_mc33_mmx(uint8_t *dst, const uint8_t *src, @@ -224,7 +224,7 @@ av_cold void ff_rv40dsp_init_x86(RV34DSPContext *c) } #endif /* HAVE_MMX_INLINE */ -#if HAVE_YASM +#if HAVE_X86ASM if (EXTERNAL_MMX(cpu_flags)) { c->put_chroma_pixels_tab[0] = ff_put_rv40_chroma_mc8_mmx; c->put_chroma_pixels_tab[1] = ff_put_rv40_chroma_mc4_mmx; @@ -266,5 +266,5 @@ av_cold void ff_rv40dsp_init_x86(RV34DSPContext *c) QPEL_MC_SET(put_, _ssse3) QPEL_MC_SET(avg_, _ssse3) } -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ } diff --git a/libavcodec/x86/vc1dsp_init.c b/libavcodec/x86/vc1dsp_init.c index 8982ff908af0b..46bb906a76610 100644 --- a/libavcodec/x86/vc1dsp_init.c +++ b/libavcodec/x86/vc1dsp_init.c @@ -50,7 +50,7 @@ static void vc1_h_loop_filter16_ ## EXT(uint8_t *src, int stride, int pq) \ ff_vc1_h_loop_filter8_ ## EXT(src+8*stride, stride, pq); \ } -#if HAVE_YASM +#if HAVE_X86ASM LOOP_FILTER(mmxext) LOOP_FILTER(sse2) LOOP_FILTER(ssse3) @@ -68,7 +68,7 @@ static void avg_vc1_mspel_mc00_mmxext(uint8_t *dst, const uint8_t *src, { ff_avg_pixels8_mmxext(dst, src, stride, 8); } -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ void ff_put_vc1_chroma_mc8_nornd_mmx (uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); @@ -100,7 +100,7 @@ av_cold void ff_vc1dsp_init_x86(VC1DSPContext *dsp) dsp->vc1_v_loop_filter16 = vc1_v_loop_filter16_ ## EXT; \ dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_ ## EXT -#if HAVE_YASM +#if HAVE_X86ASM if (EXTERNAL_MMX(cpu_flags)) { dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_vc1_chroma_mc8_nornd_mmx; } @@ -128,5 +128,5 @@ av_cold void ff_vc1dsp_init_x86(VC1DSPContext *dsp) dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_sse4; dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_sse4; } -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ } diff --git a/libavcodec/x86/videodsp_init.c b/libavcodec/x86/videodsp_init.c index d5bfe010f77e6..e7f24a9a2c7a5 100644 --- a/libavcodec/x86/videodsp_init.c +++ b/libavcodec/x86/videodsp_init.c @@ -27,7 +27,7 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/videodsp.h" -#if HAVE_YASM +#if HAVE_X86ASM typedef void emu_edge_vfix_func(uint8_t *dst, const uint8_t *src, x86_reg dst_stride, x86_reg src_stride, x86_reg start_y, x86_reg end_y, x86_reg bh); @@ -235,14 +235,14 @@ static av_noinline void emulated_edge_mc_sse2(uint8_t *buf, const uint8_t *src, src_y, w, h, vfixtbl_sse, &ff_emu_edge_vvar_sse, hfixtbl_sse2, &ff_emu_edge_hvar_sse2); } -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ void ff_prefetch_mmxext(uint8_t *buf, ptrdiff_t stride, int h); void ff_prefetch_3dnow(uint8_t *buf, ptrdiff_t stride, int h); av_cold void ff_videodsp_init_x86(VideoDSPContext *ctx, int bpc) { -#if HAVE_YASM +#if HAVE_X86ASM int cpu_flags = av_get_cpu_flags(); #if ARCH_X86_32 @@ -264,5 +264,5 @@ av_cold void ff_videodsp_init_x86(VideoDSPContext *ctx, int bpc) if (EXTERNAL_SSE2(cpu_flags) && bpc <= 8) { ctx->emulated_edge_mc = emulated_edge_mc_sse2; } -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ } diff --git a/libavcodec/x86/vp8dsp_init.c b/libavcodec/x86/vp8dsp_init.c index 3e84bed424ed7..8702c5933d0fd 100644 --- a/libavcodec/x86/vp8dsp_init.c +++ b/libavcodec/x86/vp8dsp_init.c @@ -26,7 +26,7 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/vp8dsp.h" -#if HAVE_YASM +#if HAVE_X86ASM /* * MC functions @@ -288,7 +288,7 @@ DECLARE_LOOP_FILTER(sse2) DECLARE_LOOP_FILTER(ssse3) DECLARE_LOOP_FILTER(sse4) -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ #define VP8_LUMA_MC_FUNC(IDX, SIZE, OPT) \ c->put_vp8_epel_pixels_tab[IDX][0][2] = ff_put_vp8_epel ## SIZE ## _h6_ ## OPT; \ @@ -316,7 +316,7 @@ DECLARE_LOOP_FILTER(sse4) av_cold void ff_vp78dsp_init_x86(VP8DSPContext *c) { -#if HAVE_YASM +#if HAVE_X86ASM int cpu_flags = av_get_cpu_flags(); if (EXTERNAL_MMX(cpu_flags)) { @@ -361,12 +361,12 @@ av_cold void ff_vp78dsp_init_x86(VP8DSPContext *c) VP8_BILINEAR_MC_FUNC(1, 8, ssse3); VP8_BILINEAR_MC_FUNC(2, 4, ssse3); } -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ } av_cold void ff_vp8dsp_init_x86(VP8DSPContext *c) { -#if HAVE_YASM +#if HAVE_X86ASM int cpu_flags = av_get_cpu_flags(); if (EXTERNAL_MMX(cpu_flags)) { @@ -460,5 +460,5 @@ av_cold void ff_vp8dsp_init_x86(VP8DSPContext *c) c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_sse4; c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_sse4; } -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ } diff --git a/libavcodec/x86/vp9dsp_init.c b/libavcodec/x86/vp9dsp_init.c index 59cde79d89cb8..fbd68db90ddcc 100644 --- a/libavcodec/x86/vp9dsp_init.c +++ b/libavcodec/x86/vp9dsp_init.c @@ -27,7 +27,7 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/vp9.h" -#if HAVE_YASM +#if HAVE_X86ASM #define fpel_func(avg, sz, opt) \ void ff_vp9_ ## avg ## sz ## _ ## opt(uint8_t *dst, ptrdiff_t dst_stride, \ @@ -241,11 +241,11 @@ lpf_funcs(88, 16, avx); #undef lpf_funcs -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp) { -#if HAVE_YASM +#if HAVE_X86ASM int cpu_flags = av_get_cpu_flags(); #define init_fpel(idx1, idx2, sz, type, opt) \ @@ -345,5 +345,5 @@ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp) #undef init_subpel2 #undef init_subpel3 -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ } diff --git a/libavfilter/x86/Makefile b/libavfilter/x86/Makefile index 13b5d318ec944..6b27ddc40bacc 100644 --- a/libavfilter/x86/Makefile +++ b/libavfilter/x86/Makefile @@ -4,8 +4,8 @@ OBJS-$(CONFIG_INTERLACE_FILTER) += x86/vf_interlace_init.o OBJS-$(CONFIG_VOLUME_FILTER) += x86/af_volume_init.o OBJS-$(CONFIG_YADIF_FILTER) += x86/vf_yadif_init.o -YASM-OBJS-$(CONFIG_GRADFUN_FILTER) += x86/vf_gradfun.o -YASM-OBJS-$(CONFIG_HQDN3D_FILTER) += x86/vf_hqdn3d.o -YASM-OBJS-$(CONFIG_INTERLACE_FILTER) += x86/vf_interlace.o -YASM-OBJS-$(CONFIG_VOLUME_FILTER) += x86/af_volume.o -YASM-OBJS-$(CONFIG_YADIF_FILTER) += x86/vf_yadif.o +X86ASM-OBJS-$(CONFIG_GRADFUN_FILTER) += x86/vf_gradfun.o +X86ASM-OBJS-$(CONFIG_HQDN3D_FILTER) += x86/vf_hqdn3d.o +X86ASM-OBJS-$(CONFIG_INTERLACE_FILTER) += x86/vf_interlace.o +X86ASM-OBJS-$(CONFIG_VOLUME_FILTER) += x86/af_volume.o +X86ASM-OBJS-$(CONFIG_YADIF_FILTER) += x86/vf_yadif.o diff --git a/libavfilter/x86/vf_gradfun_init.c b/libavfilter/x86/vf_gradfun_init.c index f8d85c7120adc..0f074d731067d 100644 --- a/libavfilter/x86/vf_gradfun_init.c +++ b/libavfilter/x86/vf_gradfun_init.c @@ -40,7 +40,7 @@ void ff_gradfun_blur_line_movdqu_sse2(intptr_t x, uint16_t *buf, uint16_t *buf1, uint16_t *dc, uint8_t *src1, uint8_t *src2); -#if HAVE_YASM +#if HAVE_X86ASM static void gradfun_filter_line(uint8_t *dst, uint8_t *src, uint16_t *dc, int width, int thresh, const uint16_t *dithers, int alignment) @@ -84,11 +84,11 @@ static void gradfun_blur_line_sse2(uint16_t *dc, uint16_t *buf, uint16_t *buf1, dc + width, src + width * 2, src + width * 2 + src_linesize); } -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ av_cold void ff_gradfun_init_x86(GradFunContext *gf) { -#if HAVE_YASM +#if HAVE_X86ASM int cpu_flags = av_get_cpu_flags(); if (EXTERNAL_MMXEXT(cpu_flags)) @@ -98,5 +98,5 @@ av_cold void ff_gradfun_init_x86(GradFunContext *gf) if (EXTERNAL_SSE2(cpu_flags)) gf->blur_line = gradfun_blur_line_sse2; -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ } diff --git a/libavfilter/x86/vf_hqdn3d_init.c b/libavfilter/x86/vf_hqdn3d_init.c index 06f9e00ec92a7..5a01a58b97250 100644 --- a/libavfilter/x86/vf_hqdn3d_init.c +++ b/libavfilter/x86/vf_hqdn3d_init.c @@ -38,10 +38,10 @@ void ff_hqdn3d_row_16_x86(uint8_t *src, uint8_t *dst, uint16_t *line_ant, av_cold void ff_hqdn3d_init_x86(HQDN3DContext *hqdn3d) { -#if HAVE_YASM +#if HAVE_X86ASM hqdn3d->denoise_row[8] = ff_hqdn3d_row_8_x86; hqdn3d->denoise_row[9] = ff_hqdn3d_row_9_x86; hqdn3d->denoise_row[10] = ff_hqdn3d_row_10_x86; hqdn3d->denoise_row[16] = ff_hqdn3d_row_16_x86; -#endif /* HAVE_YASM */ +#endif /* HAVE_X86ASM */ } diff --git a/libavresample/x86/Makefile b/libavresample/x86/Makefile index 0ca2d79045df9..2faf87fb82b2f 100644 --- a/libavresample/x86/Makefile +++ b/libavresample/x86/Makefile @@ -4,6 +4,6 @@ OBJS += x86/audio_convert_init.o \ OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o -YASM-OBJS += x86/audio_convert.o \ - x86/audio_mix.o \ - x86/dither.o \ +X86ASM-OBJS += x86/audio_convert.o \ + x86/audio_mix.o \ + x86/dither.o \ diff --git a/libavutil/x86/Makefile b/libavutil/x86/Makefile index ffee43b1ad649..b619478610f0d 100644 --- a/libavutil/x86/Makefile +++ b/libavutil/x86/Makefile @@ -3,8 +3,8 @@ OBJS += x86/cpu.o \ x86/imgutils_init.o \ x86/lls_init.o \ -YASM-OBJS += x86/cpuid.o \ - x86/emms.o \ - x86/float_dsp.o \ - x86/imgutils.o \ - x86/lls.o \ +X86ASM-OBJS += x86/cpuid.o \ + x86/emms.o \ + x86/float_dsp.o \ + x86/imgutils.o \ + x86/lls.o \ diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index 3b085e71f5ece..7c50fe38e26be 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -28,7 +28,7 @@ #include "libavutil/cpu.h" #include "libavutil/cpu_internal.h" -#if HAVE_YASM +#if HAVE_X86ASM #define cpuid(index, eax, ebx, ecx, edx) \ ff_cpu_cpuid(index, &eax, &ebx, &ecx, &edx) @@ -66,7 +66,7 @@ #define cpuid_test() 1 -#elif HAVE_YASM +#elif HAVE_X86ASM #define cpuid_test ff_cpu_cpuid_test diff --git a/libswscale/x86/Makefile b/libswscale/x86/Makefile index b94b14abbb513..642ce564844a9 100644 --- a/libswscale/x86/Makefile +++ b/libswscale/x86/Makefile @@ -4,6 +4,6 @@ OBJS += x86/rgb2rgb.o \ OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o -YASM-OBJS += x86/input.o \ +X86ASM-OBJS += x86/input.o \ x86/output.o \ x86/scale.o \ diff --git a/libswscale/x86/rgb2rgb_template.c b/libswscale/x86/rgb2rgb_template.c index 3b9c82b2edd9e..5b8ba1244f8c9 100644 --- a/libswscale/x86/rgb2rgb_template.c +++ b/libswscale/x86/rgb2rgb_template.c @@ -1945,7 +1945,7 @@ static void RENAME(interleaveBytes)(const uint8_t *src1, const uint8_t *src2, ui } #endif /* !COMPILE_TEMPLATE_AMD3DNOW && !COMPILE_TEMPLATE_AVX */ -#if !COMPILE_TEMPLATE_AMD3DNOW && (ARCH_X86_32 || COMPILE_TEMPLATE_SSE2) && COMPILE_TEMPLATE_MMXEXT == COMPILE_TEMPLATE_SSE2 && HAVE_YASM +#if !COMPILE_TEMPLATE_AMD3DNOW && (ARCH_X86_32 || COMPILE_TEMPLATE_SSE2) && COMPILE_TEMPLATE_MMXEXT == COMPILE_TEMPLATE_SSE2 && HAVE_X86ASM void RENAME(ff_nv12ToUV)(uint8_t *dstU, uint8_t *dstV, const uint8_t *src, const uint8_t *unused, int w, uint32_t *unused2); @@ -2538,7 +2538,7 @@ static av_cold void RENAME(rgb2rgb_init)(void) #if !COMPILE_TEMPLATE_AMD3DNOW && !COMPILE_TEMPLATE_AVX interleaveBytes = RENAME(interleaveBytes); #endif /* !COMPILE_TEMPLATE_AMD3DNOW && !COMPILE_TEMPLATE_AVX */ -#if !COMPILE_TEMPLATE_AMD3DNOW && (ARCH_X86_32 || COMPILE_TEMPLATE_SSE2) && COMPILE_TEMPLATE_MMXEXT == COMPILE_TEMPLATE_SSE2 && HAVE_YASM +#if !COMPILE_TEMPLATE_AMD3DNOW && (ARCH_X86_32 || COMPILE_TEMPLATE_SSE2) && COMPILE_TEMPLATE_MMXEXT == COMPILE_TEMPLATE_SSE2 && HAVE_X86ASM deinterleaveBytes = RENAME(deinterleaveBytes); #endif } diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 87f92f4a89243..d5febec74ccbf 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -21,7 +21,7 @@ CHECKASMOBJS-$(CONFIG_AVCODEC) += $(AVCODECOBJS-yes) CHECKASMOBJS-$(ARCH_AARCH64) += aarch64/checkasm.o CHECKASMOBJS-$(HAVE_ARMV5TE_EXTERNAL) += arm/checkasm.o -CHECKASMOBJS-$(HAVE_YASM) += x86/checkasm.o +CHECKASMOBJS-$(HAVE_X86ASM) += x86/checkasm.o CHECKASMOBJS += $(CHECKASMOBJS-yes) checkasm.o CHECKASMOBJS := $(sort $(CHECKASMOBJS:%=tests/checkasm/%)) diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 462c908417bfd..db71382ac3661 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -89,7 +89,7 @@ static av_unused void *func_ref, *func_new; /* Call the reference function */ #define call_ref(...) ((func_type *)func_ref)(__VA_ARGS__) -#if ARCH_X86 && HAVE_YASM +#if ARCH_X86 && HAVE_X86ASM /* Verifies that clobbered callee-saved registers are properly saved and restored * and that either no MMX registers are touched or emms is issued */ void checkasm_checked_call(void *func, ...); From 3c0efbd03349ae68d3a25a082222652a102e3fd4 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Thu, 13 Oct 2016 02:45:09 +0200 Subject: [PATCH 0007/2557] build: Allow generating dependencies as a side-effect of assembling --- Makefile | 6 +++--- configure | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index d140ac392f2c2..6ea835931885f 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ CCFLAGS = $(CPPFLAGS) $(CFLAGS) OBJCFLAGS += $(EOBJCFLAGS) OBJCCFLAGS = $(CPPFLAGS) $(CFLAGS) $(OBJCFLAGS) ASFLAGS := $(CPPFLAGS) $(ASFLAGS) -X86ASMFLAGS += $(IFLAGS:%=%/) -Pconfig.asm +X86ASMFLAGS += $(IFLAGS:%=%/) -I$( $(@:.o=.d) - $(X86ASM) $(X86ASMFLAGS) -I $( Date: Fri, 5 Oct 2012 14:46:38 +0200 Subject: [PATCH 0008/2557] fate: Add build-only targets to FATE --- tests/Makefile | 1 + tests/fate-run.sh | 4 ++++ tests/fate/build.mak | 17 +++++++++++++++++ 3 files changed, 22 insertions(+) create mode 100644 tests/fate/build.mak diff --git a/tests/Makefile b/tests/Makefile index 30e06e8fdd312..d3f11efaaabe3 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -72,6 +72,7 @@ include $(SRC_PATH)/tests/fate/amrwb.mak include $(SRC_PATH)/tests/fate/atrac.mak include $(SRC_PATH)/tests/fate/audio.mak include $(SRC_PATH)/tests/fate/bmp.mak +include $(SRC_PATH)/tests/fate/build.mak include $(SRC_PATH)/tests/fate/canopus.mak include $(SRC_PATH)/tests/fate/cdxl.mak include $(SRC_PATH)/tests/fate/checkasm.mak diff --git a/tests/fate-run.sh b/tests/fate-run.sh index 21111403a60f2..8de749d4a75ec 100755 --- a/tests/fate-run.sh +++ b/tests/fate-run.sh @@ -192,6 +192,10 @@ pixfmts(){ test=$outertest } +null(){ + : +} + mkdir -p "$outdir" exec 3>&2 diff --git a/tests/fate/build.mak b/tests/fate/build.mak new file mode 100644 index 0000000000000..ba9768e78677a --- /dev/null +++ b/tests/fate/build.mak @@ -0,0 +1,17 @@ +FATE_BUILD += fate-build-alltools +fate-build-alltools: alltools + +FATE_BUILD += fate-build-checkheaders +fate-build-checkheaders: checkheaders + +FATE_BUILD += fate-build-examples +fate-build-examples: examples + +FATE_BUILD += fate-build-testprogs +fate-build-testprogs: testprogs + +$(FATE_BUILD): CMD = null +$(FATE_BUILD): CMP = null + +FATE += $(FATE_BUILD) +fate-build: $(FATE_BUILD) From 5ff3b5cafcc685b6936d16602b0f80aa09a95870 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 1 Mar 2017 12:02:11 +0100 Subject: [PATCH 0009/2557] build: Add pthreads to list of avutil extralibs libavutil uses pthreads in the buffer code (abstracted through a header). --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index cdeae9a7b36c9..7e788befc953b 100755 --- a/configure +++ b/configure @@ -2524,7 +2524,7 @@ avdevice_extralibs="libm_extralibs" avformat_extralibs="libm_extralibs" avfilter_extralibs="pthreads_extralibs libm_extralibs" avresample_extralibs="libm_extralibs" -avutil_extralibs="clock_gettime_extralibs cuda_extralibs libm_extralibs libmfx_extralibs nanosleep_extralibs user32_extralibs vaapi_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs wincrypt_extralibs" +avutil_extralibs="clock_gettime_extralibs cuda_extralibs libm_extralibs libmfx_extralibs nanosleep_extralibs pthreads_extralibs user32_extralibs vaapi_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs wincrypt_extralibs" swscale_extralibs="libm_extralibs" # programs From 7bfda7d157eb6f7a2df908addd60221a7a6f5eb0 Mon Sep 17 00:00:00 2001 From: Ganesh Ajjanagadde Date: Wed, 22 Feb 2017 12:53:33 -0500 Subject: [PATCH 0010/2557] intmath: add faster clz support --- libavutil/intmath.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libavutil/intmath.h b/libavutil/intmath.h index a5ee6525ee314..780bbab03946a 100644 --- a/libavutil/intmath.h +++ b/libavutil/intmath.h @@ -44,6 +44,10 @@ # endif #endif /* ff_log2 */ +#ifndef ff_clz +# define ff_clz(v) __builtin_clz(v) +#endif /* ff_clz */ + #endif /* AV_GCC_VERSION_AT_LEAST(3,4) */ extern const uint8_t ff_log2_tab[256]; @@ -132,6 +136,21 @@ static av_always_inline av_const int ff_ctz_c(int v) } #endif +#ifndef ff_clz +#define ff_clz ff_clz_c +static av_always_inline av_const unsigned ff_clz_c(unsigned x) +{ + unsigned i = sizeof(x) * 8; + + while (x) { + x >>= 1; + i--; + } + + return i; +} +#endif + /** * Trailing zero bit count. * From 19d57ca62e7134cb3cd5e937443501c417ceb79a Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 22 Feb 2017 12:53:34 -0500 Subject: [PATCH 0011/2557] libavutil: add av_mod_uintp2 Signed-off-by: James Almer --- libavutil/common.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libavutil/common.h b/libavutil/common.h index d2ddcba9ede73..3832f107bad22 100644 --- a/libavutil/common.h +++ b/libavutil/common.h @@ -182,6 +182,17 @@ static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p) else return a; } +/** + * Clear high bits from an unsigned integer starting with specific bit position + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const unsigned av_mod_uintp2_c(unsigned a, unsigned p) +{ + return a & ((1 << p) - 1); +} + /** * Add two signed 32-bit values with saturation. * @@ -410,6 +421,9 @@ static av_always_inline av_const int av_popcount64_c(uint64_t x) #ifndef av_clip_uintp2 # define av_clip_uintp2 av_clip_uintp2_c #endif +#ifndef av_mod_uintp2 +# define av_mod_uintp2 av_mod_uintp2_c +#endif #ifndef av_sat_add32 # define av_sat_add32 av_sat_add32_c #endif From aba5b94859ef1cb8f517dc64bce86a3021316ae8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 19 Sep 2016 08:53:03 -0400 Subject: [PATCH 0012/2557] Add Apple Pixlet decoder Signed-off-by: Vittorio Giovara --- Changelog | 1 + doc/general.texi | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/codec_desc.c | 7 + libavcodec/pixlet.c | 688 ++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- libavformat/isom.c | 2 + tests/fate/video.mak | 3 + tests/ref/fate/pixlet | 2 + 11 files changed, 708 insertions(+), 1 deletion(-) create mode 100644 libavcodec/pixlet.c create mode 100644 tests/ref/fate/pixlet diff --git a/Changelog b/Changelog index 713883d5f5eb4..8e8bbcbf52f75 100644 --- a/Changelog +++ b/Changelog @@ -8,6 +8,7 @@ version : - VAAPI-accelerated deinterlacing - config.log and other configuration files moved into avbuild/ directory - VAAPI-accelerated MPEG-2 and VP8 encoding +- Apple Pixlet decoder version 12: diff --git a/doc/general.texi b/doc/general.texi index d232300028bf0..54e319f1ad86f 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -590,6 +590,7 @@ following image formats are supported: @item ANSI/ASCII art @tab @tab X @item Apple Intermediate Codec @tab @tab X @item Apple MJPEG-B @tab @tab X +@item Apple Pixlet @tab @tab X @item Apple ProRes @tab X @tab X @item Apple QuickDraw @tab @tab X @tab fourcc: qdrw diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 7d28d6685e0b4..7f295dc6438fd 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -375,6 +375,7 @@ OBJS-$(CONFIG_PGMYUV_DECODER) += pnmdec.o pnm.o OBJS-$(CONFIG_PGMYUV_ENCODER) += pnmenc.o OBJS-$(CONFIG_PGSSUB_DECODER) += pgssubdec.o OBJS-$(CONFIG_PICTOR_DECODER) += pictordec.o cga_data.o +OBJS-$(CONFIG_PIXLET_DECODER) += pixlet.o OBJS-$(CONFIG_PNG_DECODER) += png.o pngdec.o pngdsp.o OBJS-$(CONFIG_PNG_ENCODER) += png.o pngenc.o OBJS-$(CONFIG_PPM_DECODER) += pnmdec.o pnm.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 46c42c578a7aa..1bfddb0ca6548 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -231,6 +231,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (PGM, pgm); REGISTER_ENCDEC (PGMYUV, pgmyuv); REGISTER_DECODER(PICTOR, pictor); + REGISTER_DECODER(PIXLET, pixlet); REGISTER_ENCDEC (PNG, png); REGISTER_ENCDEC (PPM, ppm); REGISTER_ENCDEC (PRORES, prores); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index b7bf85a041d37..489a618cbbda1 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -392,6 +392,7 @@ enum AVCodecID { AV_CODEC_ID_MAGICYUV, AV_CODEC_ID_TRUEMOTION2RT, AV_CODEC_ID_AV1, + AV_CODEC_ID_PIXLET, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 18568c96227f0..ab2018b41bb69 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1212,6 +1212,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Alliance for Open Media AV1"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_PIXLET, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pixlet", + .long_name = NULL_IF_CONFIG_SMALL("Apple Pixlet"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, /* image codecs */ { diff --git a/libavcodec/pixlet.c b/libavcodec/pixlet.c new file mode 100644 index 0000000000000..3b4ff42365a39 --- /dev/null +++ b/libavcodec/pixlet.c @@ -0,0 +1,688 @@ +/* + * Apple Pixlet decoder + * Copyright (c) 2016 Paul B Mahol + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/imgutils.h" +#include "libavutil/intmath.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "bitstream.h" +#include "bytestream.h" +#include "internal.h" +#include "thread.h" +#include "unary.h" + +#define NB_LEVELS 4 + +#define PIXLET_MAGIC 0xDEADBEEF + +#define H 0 +#define V 1 + +#define SQR(x) ((x) * (x)) + +typedef struct SubBand { + size_t width, height; + size_t size; + size_t x, y; +} SubBand; + +typedef struct PixletContext { + AVClass *class; + + GetByteContext gb; + BitstreamContext bc; + + int levels; + int depth; + size_t w, h; + + int16_t *filter[2]; + int16_t *prediction; + float scaling[4][2][NB_LEVELS]; + SubBand band[4][NB_LEVELS * 3 + 1]; +} PixletContext; + +static av_cold int pixlet_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV420P16; + avctx->color_range = AVCOL_RANGE_JPEG; + return 0; +} + +static av_cold int pixlet_close(AVCodecContext *avctx) +{ + PixletContext *ctx = avctx->priv_data; + + av_freep(&ctx->filter[0]); + av_freep(&ctx->filter[1]); + av_freep(&ctx->prediction); + + return 0; +} + +static int init_decoder(AVCodecContext *avctx) +{ + PixletContext *ctx = avctx->priv_data; + int i, plane; + + ctx->filter[0] = av_malloc_array(ctx->h, sizeof(int16_t)); + ctx->filter[1] = av_malloc_array(FFMAX(ctx->h, ctx->w) + 16, sizeof(int16_t)); + ctx->prediction = av_malloc_array((ctx->w >> NB_LEVELS), sizeof(int16_t)); + if (!ctx->filter[0] || !ctx->filter[1] || !ctx->prediction) + return AVERROR(ENOMEM); + + for (plane = 0; plane < 3; plane++) { + unsigned shift = plane > 0; + size_t w = ctx->w >> shift; + size_t h = ctx->h >> shift; + + ctx->band[plane][0].width = w >> NB_LEVELS; + ctx->band[plane][0].height = h >> NB_LEVELS; + ctx->band[plane][0].size = (w >> NB_LEVELS) * (h >> NB_LEVELS); + + for (i = 0; i < NB_LEVELS * 3; i++) { + unsigned scale = ctx->levels - (i / 3); + + ctx->band[plane][i + 1].width = w >> scale; + ctx->band[plane][i + 1].height = h >> scale; + ctx->band[plane][i + 1].size = (w >> scale) * (h >> scale); + + ctx->band[plane][i + 1].x = (w >> scale) * (((i + 1) % 3) != 2); + ctx->band[plane][i + 1].y = (h >> scale) * (((i + 1) % 3) != 1); + } + } + + return 0; +} + +static int read_low_coeffs(AVCodecContext *avctx, int16_t *dst, size_t size, + size_t width, ptrdiff_t stride) +{ + PixletContext *ctx = avctx->priv_data; + BitstreamContext *bc = &ctx->bc; + unsigned cnt1, nbits, k, j = 0, i = 0; + int64_t value, state = 3; + int rlen, escape, flag = 0; + + while (i < size) { + nbits = FFMIN(ff_clz((state >> 8) + 3) ^ 0x1F, 14); + + cnt1 = get_unary(bc, 0, 8); + if (cnt1 < 8) { + value = bitstream_read(bc, nbits); + if (value <= 1) { + bitstream_unget(bc, value & 1, 1); + value = 1; + } + escape = value + ((1 << nbits) - 1) * cnt1 - 1; + } else { + escape = bitstream_read(bc, 16); + } + + value = -((escape + flag) & 1) | 1; + dst[j++] = value * ((escape + flag + 1) >> 1); + i++; + if (j == width) { + j = 0; + dst += stride; + } + state = 120 * (escape + flag) + state - (120 * state >> 8); + flag = 0; + + if (state * 4 > 0xFF || i >= size) + continue; + + nbits = ((state + 8) >> 5) + (state ? ff_clz(state) : 32) - 24; + escape = av_mod_uintp2(16383, nbits); + cnt1 = get_unary(bc, 0, 8); + if (cnt1 > 7) { + rlen = bitstream_read(bc, 16); + } else { + value = bitstream_read(bc, nbits); + if (value <= 1) { + bitstream_unget(bc, value & 1, 1); + value = 1; + } + rlen = value + escape * cnt1 - 1; + } + + if (i + rlen > size) + return AVERROR_INVALIDDATA; + i += rlen; + + for (k = 0; k < rlen; k++) { + dst[j++] = 0; + if (j == width) { + j = 0; + dst += stride; + } + } + + state = 0; + flag = rlen < 0xFFFF ? 1 : 0; + } + + bitstream_align(bc); + return bitstream_tell(bc) >> 3; +} + +static int read_high_coeffs(AVCodecContext *avctx, uint8_t *src, int16_t *dst, + int size, int64_t c, int a, int64_t d, + int width, ptrdiff_t stride) +{ + PixletContext *ctx = avctx->priv_data; + BitstreamContext *bc = &ctx->bc; + unsigned cnt1, shbits, rlen, nbits, length, i = 0, j = 0, k; + int ret, escape, pfx, cthulu, yflag, xflag, flag = 0; + int64_t state = 3, value, tmp; + + ret = bitstream_init8(bc, src, bytestream2_get_bytes_left(&ctx->gb)); + if (ret < 0) + return ret; + + cthulu = (a >= 0) + (a ^ (a >> 31)) - (a >> 31); + if (cthulu != 1) { + nbits = 33 - ff_clz(cthulu - 1); + if (nbits > 16) + return AVERROR_INVALIDDATA; + } else { + nbits = 1; + } + + length = 25 - nbits; + + while (i < size) { + if (state >> 8 != -3) + value = ff_clz((state >> 8) + 3) ^ 0x1F; + else + value = -1; + + cnt1 = get_unary(bc, 0, length); + if (cnt1 >= length) { + cnt1 = bitstream_read(bc, nbits); + } else { + pfx = 14 + (((value - 14) >> 32) & (value - 14)); + cnt1 *= (1 << pfx) - 1; + + shbits = bitstream_read(bc, pfx); + if (shbits <= 1) { + bitstream_unget(bc, shbits & 1, 1); + shbits = 1; + } + cnt1 += shbits - 1; + } + + xflag = flag + cnt1; + yflag = xflag; + + if (flag + cnt1 == 0) { + value = 0; + } else { + xflag &= 1u; + tmp = c * ((yflag + 1) >> 1) + (c >> 1); + value = xflag + (tmp ^ -xflag); + } + + i++; + dst[j++] = value; + if (j == width) { + j = 0; + dst += stride; + } + state += d * yflag - (d * state >> 8); + + flag = 0; + + if (state * 4 > 0xFF || i >= size) + continue; + + pfx = ((state + 8) >> 5) + (state ? ff_clz(state) : 32) - 24; + escape = av_mod_uintp2(16383, pfx); + cnt1 = get_unary(bc, 0, 8); + if (cnt1 < 8) { + if (pfx < 1 || pfx > 25) + return AVERROR_INVALIDDATA; + + value = bitstream_read(bc, pfx); + if (value <= 1) { + bitstream_unget(bc, value & 1, 1); + value = 1; + } + rlen = value + escape * cnt1 - 1; + } else { + if (bitstream_read_bit(bc)) + value = bitstream_read(bc, 16); + else + value = bitstream_read(bc, 8); + + rlen = value + 8 * escape; + } + + if (rlen > 0xFFFF || i + rlen > size) + return AVERROR_INVALIDDATA; + i += rlen; + + for (k = 0; k < rlen; k++) { + dst[j++] = 0; + if (j == width) { + j = 0; + dst += stride; + } + } + + state = 0; + flag = rlen < 0xFFFF ? 1 : 0; + } + + bitstream_align(bc); + return bitstream_tell(bc) >> 3; +} + +static int read_highpass(AVCodecContext *avctx, uint8_t *ptr, + int plane, AVFrame *frame) +{ + PixletContext *ctx = avctx->priv_data; + ptrdiff_t stride = frame->linesize[plane] / 2; + int i, ret; + + for (i = 0; i < ctx->levels * 3; i++) { + int32_t a = bytestream2_get_be32(&ctx->gb); + int32_t b = bytestream2_get_be32(&ctx->gb); + int32_t c = bytestream2_get_be32(&ctx->gb); + int32_t d = bytestream2_get_be32(&ctx->gb); + int16_t *dest = (int16_t *)frame->data[plane] + + ctx->band[plane][i + 1].x + + ctx->band[plane][i + 1].y * stride; + size_t size = ctx->band[plane][i + 1].size; + uint32_t magic = bytestream2_get_be32(&ctx->gb); + + if (magic != PIXLET_MAGIC) { + av_log(avctx, AV_LOG_ERROR, + "wrong magic number: 0x%"PRIX32" for plane %d, band %d\n", + magic, plane, i); + return AVERROR_INVALIDDATA; + } + + ret = read_high_coeffs(avctx, ptr + bytestream2_tell(&ctx->gb), dest, + size, c, (b >= FFABS(a)) ? b : a, d, + ctx->band[plane][i + 1].width, stride); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "error in highpass coefficients for plane %d, band %d\n", + plane, i); + return ret; + } + bytestream2_skip(&ctx->gb, ret); + } + + return 0; +} + +static void line_add_sat_s16(int16_t *dst, const int16_t *src, size_t len) +{ + int i; + for (i = 0; i < len; i++) { + int val = dst[i] + src[i]; + dst[i] = av_clip_int16(val); + } +} + +static void lowpass_prediction(int16_t *dst, int16_t *pred, + size_t width, size_t height, ptrdiff_t stride) +{ + int i, j; + + memset(pred, 0, width * sizeof(*pred)); + + for (i = 0; i < height; i++) { + line_add_sat_s16(pred, dst, width); + dst[0] = pred[0]; + for (j = 1; j < width; j++) + dst[j] = pred[j] + dst[j - 1]; + dst += stride; + } +} + +static void filterfn(int16_t *dest, int16_t *tmp, size_t size, float SCALE) +{ + int16_t *low, *high, *ll, *lh, *hl, *hh; + int hsize, i, j; + float value; + + hsize = size >> 1; + low = tmp + 4; + high = &low[hsize + 8]; + + memcpy(low, dest, size); + memcpy(high, dest + hsize, size); + + ll = &low[hsize]; + lh = &low[hsize]; + hl = &high[hsize]; + hh = hl; + for (i = 4, j = 2; i; i--, j++, ll--, hh++, lh++, hl--) { + low[i - 5] = low[j - 1]; + lh[0] = ll[-1]; + high[i - 5] = high[j - 2]; + hh[0] = hl[-2]; + } + + for (i = 0; i < hsize; i++) { + value = low [i + 1] * -0.07576144003329376f + + low [i + 0] * 0.8586296626673486f + + low [i - 1] * -0.07576144003329376f + + high[i + 0] * 0.3535533905932737f + + high[i - 1] * 0.3535533905932737f; + dest[i * 2] = av_clipf(value * SCALE, INT16_MIN, INT16_MAX); + } + + for (i = 0; i < hsize; i++) { + value = low [i + 2] * -0.01515228715813062f + + low [i + 1] * 0.3687056777514043f + + low [i + 0] * 0.3687056777514043f + + low [i - 1] * -0.01515228715813062f + + high[i + 1] * 0.07071067811865475f + + high[i + 0] * -0.8485281374238569f + + high[i - 1] * 0.07071067811865475f; + dest[i * 2 + 1] = av_clipf(value * SCALE, INT16_MIN, INT16_MAX); + } +} + +static void reconstruction(AVCodecContext *avctx, int16_t *dest, + size_t width, size_t height, ptrdiff_t stride, + float *scaling_h, float *scaling_v) +{ + PixletContext *ctx = avctx->priv_data; + unsigned scaled_width, scaled_height; + int16_t *ptr, *tmp; + int i, j, k; + + scaled_width = width >> NB_LEVELS; + scaled_height = height >> NB_LEVELS; + tmp = ctx->filter[0]; + + for (i = 0; i < NB_LEVELS; i++) { + float scale_v = scaling_v[i]; + float scale_h = scaling_h[i]; + scaled_width <<= 1; + scaled_height <<= 1; + + ptr = dest; + for (j = 0; j < scaled_height; j++) { + filterfn(ptr, ctx->filter[1], scaled_width, scale_v); + ptr += stride; + } + + for (j = 0; j < scaled_width; j++) { + ptr = dest + j; + for (k = 0; k < scaled_height; k++) { + tmp[k] = *ptr; + ptr += stride; + } + + filterfn(tmp, ctx->filter[1], scaled_height, scale_h); + + ptr = dest + j; + for (k = 0; k < scaled_height; k++) { + *ptr = tmp[k]; + ptr += stride; + } + } + } +} + +static void postprocess_luma(AVFrame *frame, size_t w, size_t h, int depth) +{ + uint16_t *dsty = (uint16_t *)frame->data[0]; + int16_t *srcy = (int16_t *)frame->data[0]; + ptrdiff_t stridey = frame->linesize[0] / 2; + const float factor = 1.0f / ((1 << depth) - 1); + int i, j; + + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) + dsty[i] = SQR(FFMAX(srcy[i], 0) * factor) * 65535; + dsty += stridey; + srcy += stridey; + } +} + +static void postprocess_chroma(AVFrame *frame, int w, int h, int depth) +{ + uint16_t *dstu = (uint16_t *)frame->data[1]; + uint16_t *dstv = (uint16_t *)frame->data[2]; + int16_t *srcu = (int16_t *)frame->data[1]; + int16_t *srcv = (int16_t *)frame->data[2]; + ptrdiff_t strideu = frame->linesize[1] / 2; + ptrdiff_t stridev = frame->linesize[2] / 2; + const unsigned add = 1 << (depth - 1); + const unsigned shift = 16 - depth; + int i, j; + + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) { + dstu[i] = av_clip_uintp2_c(add + srcu[i], depth) << shift; + dstv[i] = av_clip_uintp2_c(add + srcv[i], depth) << shift; + } + dstu += strideu; + dstv += stridev; + srcu += strideu; + srcv += stridev; + } +} + +static int decode_plane(AVCodecContext *avctx, int plane, + AVPacket *avpkt, AVFrame *frame) +{ + PixletContext *ctx = avctx->priv_data; + ptrdiff_t stride = frame->linesize[plane] / 2; + unsigned shift = plane > 0; + int16_t *dst; + int i, ret; + + for (i = ctx->levels - 1; i >= 0; i--) { + int32_t h = sign_extend(bytestream2_get_be32(&ctx->gb), 32); + int32_t v = sign_extend(bytestream2_get_be32(&ctx->gb), 32); + + if (!h || !v) + return AVERROR_INVALIDDATA; + + ctx->scaling[plane][H][i] = 1000000.0f / h; + ctx->scaling[plane][V][i] = 1000000.0f / v; + } + + bytestream2_skip(&ctx->gb, 4); + + dst = (int16_t *)frame->data[plane]; + dst[0] = sign_extend(bytestream2_get_be16(&ctx->gb), 16); + + ret = bitstream_init8(&ctx->bc, avpkt->data + bytestream2_tell(&ctx->gb), + bytestream2_get_bytes_left(&ctx->gb)); + if (ret < 0) + return ret; + + ret = read_low_coeffs(avctx, dst + 1, ctx->band[plane][0].width - 1, + ctx->band[plane][0].width - 1, 0); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "error in lowpass coefficients for plane %d, top row\n", plane); + return ret; + } + + ret = read_low_coeffs(avctx, dst + stride, + ctx->band[plane][0].height - 1, 1, stride); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "error in lowpass coefficients for plane %d, left column\n", + plane); + return ret; + } + + ret = read_low_coeffs(avctx, dst + stride + 1, + (ctx->band[plane][0].width - 1) * (ctx->band[plane][0].height - 1), + ctx->band[plane][0].width - 1, stride); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "error in lowpass coefficients for plane %d, rest\n", plane); + return ret; + } + + bytestream2_skip(&ctx->gb, ret); + if (bytestream2_get_bytes_left(&ctx->gb) <= 0) { + av_log(avctx, AV_LOG_ERROR, "no bytes left\n"); + return AVERROR_INVALIDDATA; + } + + ret = read_highpass(avctx, avpkt->data, plane, frame); + if (ret < 0) + return ret; + + lowpass_prediction(dst, ctx->prediction, ctx->band[plane][0].width, + ctx->band[plane][0].height, stride); + + reconstruction(avctx, (int16_t *)frame->data[plane], ctx->w >> shift, + ctx->h >> shift, stride, ctx->scaling[plane][H], + ctx->scaling[plane][V]); + + return 0; +} + +static int pixlet_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + PixletContext *ctx = avctx->priv_data; + int i, w, h, width, height, ret, version; + AVFrame *p = data; + ThreadFrame frame = { .f = data }; + uint32_t pktsize; + + bytestream2_init(&ctx->gb, avpkt->data, avpkt->size); + + pktsize = bytestream2_get_be32(&ctx->gb); + if (pktsize <= 44 || pktsize - 4 > bytestream2_get_bytes_left(&ctx->gb)) { + av_log(avctx, AV_LOG_ERROR, "Invalid packet size %"PRIu32".\n", pktsize); + return AVERROR_INVALIDDATA; + } + + version = bytestream2_get_le32(&ctx->gb); + if (version != 1) + avpriv_request_sample(avctx, "Version %d", version); + + bytestream2_skip(&ctx->gb, 4); + if (bytestream2_get_be32(&ctx->gb) != 1) + return AVERROR_INVALIDDATA; + bytestream2_skip(&ctx->gb, 4); + + width = bytestream2_get_be32(&ctx->gb); + height = bytestream2_get_be32(&ctx->gb); + + w = FFALIGN(width, 1 << (NB_LEVELS + 1)); + h = FFALIGN(height, 1 << (NB_LEVELS + 1)); + + ctx->levels = bytestream2_get_be32(&ctx->gb); + if (ctx->levels != NB_LEVELS) + return AVERROR_INVALIDDATA; + ctx->depth = bytestream2_get_be32(&ctx->gb); + if (ctx->depth < 8 || ctx->depth > 15) { + avpriv_request_sample(avctx, "Depth %d", ctx->depth); + return AVERROR_INVALIDDATA; + } + + ret = ff_set_dimensions(avctx, w, h); + if (ret < 0) + return ret; + avctx->width = width; + avctx->height = height; + + /* reinit should dimensions change */ + if (ctx->w != w || ctx->h != h) { + pixlet_close(avctx); + ctx->w = w; + ctx->h = h; + + ret = init_decoder(avctx); + if (ret < 0) { + pixlet_close(avctx); + ctx->w = 0; + ctx->h = 0; + return ret; + } + } + + bytestream2_skip(&ctx->gb, 8); + + ret = ff_thread_get_buffer(avctx, &frame, 0); + if (ret < 0) + return ret; + + for (i = 0; i < 3; i++) { + ret = decode_plane(avctx, i, avpkt, frame.f); + if (ret < 0) + return ret; + if (avctx->flags & AV_CODEC_FLAG_GRAY) + break; + } + + postprocess_luma(frame.f, ctx->w, ctx->h, ctx->depth); + postprocess_chroma(frame.f, ctx->w >> 1, ctx->h >> 1, ctx->depth); + + p->pict_type = AV_PICTURE_TYPE_I; + p->color_range = AVCOL_RANGE_JPEG; + p->key_frame = 1; + + *got_frame = 1; + + return pktsize; +} + +#if HAVE_THREADS +static int pixlet_init_thread_copy(AVCodecContext *avctx) +{ + PixletContext *ctx = avctx->priv_data; + + ctx->filter[0] = NULL; + ctx->filter[1] = NULL; + ctx->prediction = NULL; + ctx->w = 0; + ctx->h = 0; + + return 0; +} +#endif /* HAVE_THREADS */ + +AVCodec ff_pixlet_decoder = { + .name = "pixlet", + .long_name = NULL_IF_CONFIG_SMALL("Apple Pixlet"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PIXLET, + .init = pixlet_init, + .init_thread_copy = ONLY_IF_THREADS_ENABLED(pixlet_init_thread_copy), + .close = pixlet_close, + .decode = pixlet_decode_frame, + .priv_data_size = sizeof(PixletContext), + .capabilities = AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_FRAME_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index a6eda6a691197..5c25b3e4ec175 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 57 -#define LIBAVCODEC_VERSION_MINOR 34 +#define LIBAVCODEC_VERSION_MINOR 35 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/isom.c b/libavformat/isom.c index 018356311f70c..931c438d871a1 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -265,6 +265,8 @@ const AVCodecTag ff_codec_movvideo_tags[] = { { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '4') }, { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', 'A') }, + { AV_CODEC_ID_PIXLET, MKTAG('p', 'x', 'l', 't') }, + { AV_CODEC_ID_NONE, 0 }, }; diff --git a/tests/fate/video.mak b/tests/fate/video.mak index fd15e83c39f5f..e35199f6c2fbd 100644 --- a/tests/fate/video.mak +++ b/tests/fate/video.mak @@ -246,6 +246,9 @@ fate-nuv: $(FATE_NUV) FATE_SAMPLES_AVCONV-$(call DEMDEC, PAF, PAF_VIDEO) += fate-paf-video fate-paf-video: CMD = framecrc -i $(TARGET_SAMPLES)/paf/hod1-partial.paf -pix_fmt rgb24 -an +FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, PIXLET) += fate-pixlet +fate-pixlet: CMD = framecrc -i $(TARGET_SAMPLES)/pxlt/pixlet.mov -an + FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, QPEG) += fate-qpeg fate-qpeg: CMD = framecrc -i $(TARGET_SAMPLES)/qpeg/Clock.avi -an -pix_fmt rgb24 diff --git a/tests/ref/fate/pixlet b/tests/ref/fate/pixlet new file mode 100644 index 0000000000000..dd34382ffc859 --- /dev/null +++ b/tests/ref/fate/pixlet @@ -0,0 +1,2 @@ +#tb 0: 1/25 +0, 0, 0, 1, 2764800, 0xd0b6bf48 From 3303f86467efa99f23c670707f5be094cc9ce547 Mon Sep 17 00:00:00 2001 From: Ganapathy Kasi Date: Wed, 1 Mar 2017 15:04:47 -0800 Subject: [PATCH 0013/2557] nvenc: Remove qmin and qmax constraints for nvenc vbr qmin and qmax are not necessary for nvenc vbr. Also fix for using 2 pass vbr mode for slow preset through ctx->flag NVENC_TWO_PASSES. Signed-off-by: Luca Barbato --- libavcodec/nvenc.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index fcd496b93f1d5..738a77ebc2648 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -559,12 +559,8 @@ static void nvenc_override_rate_control(AVCodecContext *avctx, return; case NV_ENC_PARAMS_RC_2_PASS_VBR: case NV_ENC_PARAMS_RC_VBR: - if (avctx->qmin < 0 && avctx->qmax < 0) { - av_log(avctx, AV_LOG_WARNING, - "The variable bitrate rate-control requires " - "the 'qmin' and/or 'qmax' option set.\n"); - return; - } + set_vbr(avctx, rc); + break; case NV_ENC_PARAMS_RC_VBR_MINQP: if (avctx->qmin < 0) { av_log(avctx, AV_LOG_WARNING, @@ -606,8 +602,11 @@ static void nvenc_setup_rate_control(AVCodecContext *avctx) set_lossless(avctx, rc); } else if (avctx->global_quality > 0) { set_constqp(avctx, rc); - } else if (avctx->qmin >= 0 && avctx->qmax >= 0) { - rc->rateControlMode = NV_ENC_PARAMS_RC_VBR; + } else { + if (ctx->flags & NVENC_TWO_PASSES) + rc->rateControlMode = NV_ENC_PARAMS_RC_2_PASS_VBR; + else + rc->rateControlMode = NV_ENC_PARAMS_RC_VBR; set_vbr(avctx, rc); } From 6eef263aca281fb582e1fa3d841ac20ef747a252 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 1 Mar 2017 19:04:03 +0100 Subject: [PATCH 0014/2557] x86: Merge align directives into SECTION_RODATA declarations where possible --- libavcodec/x86/dct32.asm | 6 ++---- libavcodec/x86/fft.asm | 3 +-- libavcodec/x86/imdct36.asm | 3 +-- libavcodec/x86/rv40dsp.asm | 3 +-- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/libavcodec/x86/dct32.asm b/libavcodec/x86/dct32.asm index 2c4c32eb11f9e..cfd5f52ba817c 100644 --- a/libavcodec/x86/dct32.asm +++ b/libavcodec/x86/dct32.asm @@ -23,7 +23,8 @@ SECTION_RODATA 32 -align 32 +ps_p1p1m1m1: dd 0, 0, 0x80000000, 0x80000000, 0, 0, 0x80000000, 0x80000000 + ps_cos_vec: dd 0.500603, 0.505471, 0.515447, 0.531043 dd 0.553104, 0.582935, 0.622504, 0.674808 dd -10.190008, -3.407609, -2.057781, -1.484165 @@ -38,9 +39,6 @@ ps_cos_vec: dd 0.500603, 0.505471, 0.515447, 0.531043 dd 1.000000, 0.707107, 1.000000, -0.707107 dd 0.707107, 0.707107, 0.707107, 0.707107 -align 32 -ps_p1p1m1m1: dd 0, 0, 0x80000000, 0x80000000, 0, 0, 0x80000000, 0x80000000 - %macro BUTTERFLY 4 subps %4, %1, %2 addps %2, %2, %1 diff --git a/libavcodec/x86/fft.asm b/libavcodec/x86/fft.asm index ef007f4eec17a..2c7438134c3ce 100644 --- a/libavcodec/x86/fft.asm +++ b/libavcodec/x86/fft.asm @@ -51,13 +51,12 @@ struc FFTContext .imdcthalf:pointer 1 endstruc -SECTION_RODATA +SECTION_RODATA 32 %define M_SQRT1_2 0.70710678118654752440 %define M_COS_PI_1_8 0.923879532511287 %define M_COS_PI_3_8 0.38268343236509 -align 32 ps_cos16_1: dd 1.0, M_COS_PI_1_8, M_SQRT1_2, M_COS_PI_3_8, 1.0, M_COS_PI_1_8, M_SQRT1_2, M_COS_PI_3_8 ps_cos16_2: dd 0, M_COS_PI_3_8, M_SQRT1_2, M_COS_PI_1_8, 0, -M_COS_PI_3_8, -M_SQRT1_2, -M_COS_PI_1_8 diff --git a/libavcodec/x86/imdct36.asm b/libavcodec/x86/imdct36.asm index f85e2e4cc36be..ddb71749a51d6 100644 --- a/libavcodec/x86/imdct36.asm +++ b/libavcodec/x86/imdct36.asm @@ -21,9 +21,8 @@ %include "libavutil/x86/x86util.asm" -SECTION_RODATA +SECTION_RODATA 16 -align 16 ps_mask: dd 0, ~0, ~0, ~0 ps_mask2: dd 0, ~0, 0, ~0 ps_mask3: dd 0, 0, 0, ~0 diff --git a/libavcodec/x86/rv40dsp.asm b/libavcodec/x86/rv40dsp.asm index 77f6ddb25db55..4949842e8f13a 100644 --- a/libavcodec/x86/rv40dsp.asm +++ b/libavcodec/x86/rv40dsp.asm @@ -23,9 +23,8 @@ %include "libavutil/x86/x86util.asm" -SECTION_RODATA +SECTION_RODATA 16 -align 16 pw_1024: times 8 dw 1 << (16 - 6) ; pw_1024 sixtap_filter_hb_m: times 8 db 1, -5 From 808ef43597b1e3d6e69a5b9abe2237c8ddb97b44 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 1 Mar 2017 19:42:21 +0100 Subject: [PATCH 0015/2557] build: Explicitly set 32-bit/64-bit object formats for nasm/yasm Consistently use object format names with "32" suffix and set object format to "win64" on Windows x86_64, which fixes assembling with nasm. --- configure | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/configure b/configure index 7e788befc953b..397d19c923183 100755 --- a/configure +++ b/configure @@ -2563,7 +2563,6 @@ cc_default="gcc" host_cc_default="gcc" ln_s="ln -s -f" nm_default="nm -g" -objformat="elf" pkg_config_default=pkg-config ranlib="ranlib" strip="strip" @@ -3883,6 +3882,8 @@ esac enable $subarch enabled spic && enable_weak pic +enabled x86_64 && objformat=elf64 || objformat="elf32" + # OS specific case $target_os in aix) @@ -3947,8 +3948,7 @@ case $target_os in SLIBSUF=".dylib" SLIBNAME_WITH_VERSION='$(SLIBPREF)$(NAME).$(LIBVERSION)$(SLIBSUF)' SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(NAME).$(LIBMAJOR)$(SLIBSUF)' - objformat="macho" - enabled x86_64 && objformat="macho64" + enabled x86_64 && objformat="macho64" || objformat="macho32" enabled_any pic shared || { check_cflags -mdynamic-no-pic && add_asflags -mdynamic-no-pic; } check_header dispatch/dispatch.h && @@ -3982,7 +3982,7 @@ case $target_os in SLIB_INSTALL_EXTRA_SHLIB='$(SLIBNAME:$(SLIBSUF)=.lib)' SLIB_INSTALL_EXTRA_LIB='lib$(SLIBNAME:$(SLIBSUF)=.dll.a) $(SLIBNAME_WITH_MAJOR:$(SLIBSUF)=.def)' SHFLAGS='-shared -Wl,--output-def,$$(@:$(SLIBSUF)=.orig.def) -Wl,--out-implib,$(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a) -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-auto-image-base' - objformat="win32" + enabled x86_64 && objformat="win64" || objformat="win32" dlltool="${cross_prefix}dlltool" ranlib=: enable dos_paths @@ -4007,7 +4007,7 @@ case $target_os in SLIB_INSTALL_EXTRA_SHLIB='$(SLIBNAME:$(SLIBSUF)=.lib)' SLIB_INSTALL_EXTRA_LIB='$(SLIBNAME_WITH_MAJOR:$(SLIBSUF)=.def)' SHFLAGS='-dll -def:$$(@:$(SLIBSUF)=.def) -implib:$(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib)' - objformat="win32" + enabled x86_64 && objformat="win64" || objformat="win32" ranlib=: enable dos_paths ;; @@ -4022,7 +4022,7 @@ case $target_os in SLIB_INSTALL_LINKS= SLIB_INSTALL_EXTRA_LIB='lib$(NAME).dll.a' SHFLAGS='-shared -Wl,--out-implib,$(SUBDIR)lib$(NAME).dll.a' - objformat="win32" + enabled x86_64 && objformat="win64" || objformat="win32" enable dos_paths ;; *-dos|freedos|opendos) @@ -4376,7 +4376,8 @@ EOF EOF # llvm's integrated assembler supports .object_arch from llvm 3.5 - [ "$objformat" = elf ] && check_as < Date: Wed, 1 Mar 2017 19:45:31 -0500 Subject: [PATCH 0016/2557] pixlet: Fix architecture-dependent code and values The constants used in the decoder used floating point precision, and this caused different values to be generated on different architectures. Additionally on big endian machines, the fate test would output bytes in native order, which is different from the one hardcoded in the test. So, eradicate floating point numbers and use fixed point (32.32) arithmetics everywhere, replacing constants with precomputed integer values, and force the pixel format output to be the same in the fate test. Signed-off-by: Vittorio Giovara --- libavcodec/pixlet.c | 58 +++++++++++++++++++++++-------------------- tests/fate/video.mak | 2 +- tests/ref/fate/pixlet | 2 +- 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/libavcodec/pixlet.c b/libavcodec/pixlet.c index 3b4ff42365a39..9f7d082fbed17 100644 --- a/libavcodec/pixlet.c +++ b/libavcodec/pixlet.c @@ -39,8 +39,6 @@ #define H 0 #define V 1 -#define SQR(x) ((x) * (x)) - typedef struct SubBand { size_t width, height; size_t size; @@ -59,7 +57,7 @@ typedef struct PixletContext { int16_t *filter[2]; int16_t *prediction; - float scaling[4][2][NB_LEVELS]; + int64_t scaling[4][2][NB_LEVELS]; SubBand band[4][NB_LEVELS * 3 + 1]; } PixletContext; @@ -364,11 +362,11 @@ static void lowpass_prediction(int16_t *dst, int16_t *pred, } } -static void filterfn(int16_t *dest, int16_t *tmp, size_t size, float SCALE) +static void filterfn(int16_t *dest, int16_t *tmp, size_t size, int64_t scale) { int16_t *low, *high, *ll, *lh, *hl, *hh; int hsize, i, j; - float value; + int64_t value; hsize = size >> 1; low = tmp + 4; @@ -389,29 +387,29 @@ static void filterfn(int16_t *dest, int16_t *tmp, size_t size, float SCALE) } for (i = 0; i < hsize; i++) { - value = low [i + 1] * -0.07576144003329376f + - low [i + 0] * 0.8586296626673486f + - low [i - 1] * -0.07576144003329376f + - high[i + 0] * 0.3535533905932737f + - high[i - 1] * 0.3535533905932737f; - dest[i * 2] = av_clipf(value * SCALE, INT16_MIN, INT16_MAX); + value = (int64_t) low [i + 1] * -INT64_C(325392907) + + (int64_t) low [i + 0] * INT64_C(3687786320) + + (int64_t) low [i - 1] * -INT64_C(325392907) + + (int64_t) high[i + 0] * INT64_C(1518500249) + + (int64_t) high[i - 1] * INT64_C(1518500249); + dest[i * 2] = av_clip_int16(((value >> 32) * scale) >> 32); } for (i = 0; i < hsize; i++) { - value = low [i + 2] * -0.01515228715813062f + - low [i + 1] * 0.3687056777514043f + - low [i + 0] * 0.3687056777514043f + - low [i - 1] * -0.01515228715813062f + - high[i + 1] * 0.07071067811865475f + - high[i + 0] * -0.8485281374238569f + - high[i - 1] * 0.07071067811865475f; - dest[i * 2 + 1] = av_clipf(value * SCALE, INT16_MIN, INT16_MAX); + value = (int64_t) low [i + 2] * -INT64_C(65078576) + + (int64_t) low [i + 1] * INT64_C(1583578880) + + (int64_t) low [i + 0] * INT64_C(1583578880) + + (int64_t) low [i - 1] * -INT64_C(65078576) + + (int64_t) high[i + 1] * INT64_C(303700064) + + (int64_t) high[i + 0] * -INT64_C(3644400640) + + (int64_t) high[i - 1] * INT64_C(303700064); + dest[i * 2 + 1] = av_clip_int16(((value >> 32) * scale) >> 32); } } static void reconstruction(AVCodecContext *avctx, int16_t *dest, size_t width, size_t height, ptrdiff_t stride, - float *scaling_h, float *scaling_v) + int64_t *scaling_h, int64_t *scaling_v) { PixletContext *ctx = avctx->priv_data; unsigned scaled_width, scaled_height; @@ -423,8 +421,8 @@ static void reconstruction(AVCodecContext *avctx, int16_t *dest, tmp = ctx->filter[0]; for (i = 0; i < NB_LEVELS; i++) { - float scale_v = scaling_v[i]; - float scale_h = scaling_h[i]; + int64_t scale_v = scaling_v[i]; + int64_t scale_h = scaling_h[i]; scaled_width <<= 1; scaled_height <<= 1; @@ -457,12 +455,18 @@ static void postprocess_luma(AVFrame *frame, size_t w, size_t h, int depth) uint16_t *dsty = (uint16_t *)frame->data[0]; int16_t *srcy = (int16_t *)frame->data[0]; ptrdiff_t stridey = frame->linesize[0] / 2; - const float factor = 1.0f / ((1 << depth) - 1); int i, j; for (j = 0; j < h; j++) { - for (i = 0; i < w; i++) - dsty[i] = SQR(FFMAX(srcy[i], 0) * factor) * 65535; + for (i = 0; i < w; i++) { + if (srcy[i] <= 0) + dsty[i] = 0; + else if (srcy[i] > ((1 << depth) - 1)) + dsty[i] = 65535; + else + dsty[i] = ((int64_t) srcy[i] * srcy[i] * 65535) / + ((1 << depth) - 1) / ((1 << depth) - 1); + } dsty += stridey; srcy += stridey; } @@ -508,8 +512,8 @@ static int decode_plane(AVCodecContext *avctx, int plane, if (!h || !v) return AVERROR_INVALIDDATA; - ctx->scaling[plane][H][i] = 1000000.0f / h; - ctx->scaling[plane][V][i] = 1000000.0f / v; + ctx->scaling[plane][H][i] = (1000000ULL << 32) / h; + ctx->scaling[plane][V][i] = (1000000ULL << 32) / v; } bytestream2_skip(&ctx->gb, 4); diff --git a/tests/fate/video.mak b/tests/fate/video.mak index e35199f6c2fbd..01108f8d9d523 100644 --- a/tests/fate/video.mak +++ b/tests/fate/video.mak @@ -247,7 +247,7 @@ FATE_SAMPLES_AVCONV-$(call DEMDEC, PAF, PAF_VIDEO) += fate-paf-video fate-paf-video: CMD = framecrc -i $(TARGET_SAMPLES)/paf/hod1-partial.paf -pix_fmt rgb24 -an FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, PIXLET) += fate-pixlet -fate-pixlet: CMD = framecrc -i $(TARGET_SAMPLES)/pxlt/pixlet.mov -an +fate-pixlet: CMD = framecrc -i $(TARGET_SAMPLES)/pxlt/pixlet.mov -an -pix_fmt yuv420p16le FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, QPEG) += fate-qpeg fate-qpeg: CMD = framecrc -i $(TARGET_SAMPLES)/qpeg/Clock.avi -an -pix_fmt rgb24 diff --git a/tests/ref/fate/pixlet b/tests/ref/fate/pixlet index dd34382ffc859..0c10fca1deaf1 100644 --- a/tests/ref/fate/pixlet +++ b/tests/ref/fate/pixlet @@ -1,2 +1,2 @@ #tb 0: 1/25 -0, 0, 0, 1, 2764800, 0xd0b6bf48 +0, 0, 0, 1, 2764800, 0xe8eff295 From 51411eb7ffba1437c1019f992990914f60232c39 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Thu, 2 Mar 2017 14:54:28 +0100 Subject: [PATCH 0017/2557] build: Special-case handling of SDL CFLAGS SDL adds some "special" CFLAGS that interfere with building normal binaries. Capture those CFLAGS separately and avoid adding them to the general CFLAGS. --- configure | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/configure b/configure index a8e3926b70aa6..9f339e6af654d 100755 --- a/configure +++ b/configure @@ -4782,7 +4782,13 @@ if enabled nvenc; then require_cpp_condition nvEncodeAPI.h "NVENCAPI_MAJOR_VERSION >= 6" fi -check_pkg_config sdl "sdl >= 1.2.1 sdl < 1.3.0" SDL_events.h SDL_PollEvent +# SDL is "special" and adds some CFLAGS that should not pollute anything else. +if enabled avplay; then + CFLAGS_SAVE=$CFLAGS + check_pkg_config sdl "sdl >= 1.2.1 sdl < 1.3.0" SDL_events.h SDL_PollEvent && + sdl_cflags=$pkg_cflags + CFLAGS=$CFLAGS_SAVE +fi ! disabled pod2man && check_cmd pod2man --help && enable pod2man || disable pod2man ! disabled texi2html && check_cmd texi2html -version && enable texi2html || disable texi2html From f54037da8af2f2aeb5e5633b48434211e6a97fe5 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 28 Feb 2017 19:32:37 +0100 Subject: [PATCH 0018/2557] build: Make x86 assembler commandline-selectable --- configure | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 9f339e6af654d..77b74dd40868b 100755 --- a/configure +++ b/configure @@ -268,6 +268,7 @@ Toolchain options: --objcc=OCC use ObjC compiler OCC [$cc_default] --dep-cc=DEPCC use dependency generator DEPCC [$cc_default] --ld=LD use linker LD + --x86asmexe=X86ASM use x86 assembler X86ASM --pkg-config=PKGCONFIG use pkg-config tool PKGCONFIG [$pkg_config_default] --pkg-config-flags=FLAGS pass additional flags to pkgconf [] --host-cc=HOSTCC use host C compiler HOSTCC @@ -1863,6 +1864,7 @@ CMDLINE_SET=" target_path target_samples toolchain + x86asmexe " CMDLINE_APPEND=" @@ -2561,13 +2563,13 @@ shlibdir_default="$libdir_default" ar_default="ar" cc_default="gcc" host_cc_default="gcc" +x86asmexe_default="yasm" ln_s="ln -s -f" nm_default="nm -g" pkg_config_default=pkg-config ranlib="ranlib" strip="strip" version_script='--version-script' -x86asmexe="yasm" # machine arch_default=$(uname -m) @@ -2997,6 +2999,7 @@ fi ar_default="${cross_prefix}${ar_default}" cc_default="${cross_prefix}${cc_default}" objcc_default="${cross_prefix}${objcc_default}" +x86asmexe_default="${cross_prefix}${x86asmexe_default}" nm_default="${cross_prefix}${nm_default}" pkg_config_default="${cross_prefix}${pkg_config_default}" ranlib="${cross_prefix}${ranlib}" @@ -3004,7 +3007,7 @@ strip="${cross_prefix}${strip}" sysinclude_default="${sysroot}/usr/include" -set_default arch cc pkg_config sysinclude target_exec target_os +set_default arch cc pkg_config sysinclude target_exec target_os x86asmexe enabled cross_compile || host_cc_default=$cc set_default host_cc @@ -4474,16 +4477,26 @@ EOF enabled ssse3 && check_inline_asm ssse3_inline '"pabsw %xmm0, %xmm0"' enabled mmxext && check_inline_asm mmxext_inline '"pmaxub %mm0, %mm1"' - if ! disabled_any asm mmx x86asm; then - if check_cmd $x86asmexe --version; then - x86asm_debug="-g dwarf2" - X86ASMDEP='$(DEPX86ASM) $(X86ASMFLAGS) -M $(X86ASM_O) $< > $(@:.o=.d)' - elif check_cmd nasm -v; then - x86asmexe=nasm + probe_x86asm(){ + x86asmexe_probe=$1 + if check_cmd $x86asmexe_probe -v; then + x86asmexe=$x86asmexe_probe + x86asm_type=nasm x86asm_debug="-g -F dwarf" X86ASM_DEPFLAGS='-MD $(@:.o=.d)' + elif check_cmd $x86asmexe_probe --version; then + x86asmexe=$x86asmexe_probe + x86asm_type=yasm + x86asm_debug="-g dwarf2" + X86ASMDEP='$(DEPX86ASM) $(X86ASMFLAGS) -M $(X86ASM_O) $< > $(@:.o=.d)' fi + } + if ! disabled_any asm mmx x86asm; then + for program in $x86asmexe yasm nasm; do + probe_x86asm $program + test -n "$x86asm_type" && break + done X86ASMFLAGS="-f $objformat" enabled pic && append X86ASMFLAGS "-DPIC" test -n "$extern_prefix" && append X86ASMFLAGS "-DPREFIX" @@ -5223,6 +5236,7 @@ echo "big-endian ${bigendian-no}" echo "runtime cpu detection ${runtime_cpudetect-no}" if enabled x86; then echo "standalone assembly ${x86asm-no}" + echo "x86 assembler ${x86asmexe}" echo "MMX enabled ${mmx-no}" echo "MMXEXT enabled ${mmxext-no}" echo "3DNow! enabled ${amd3dnow-no}" From 003124ebf4a05f1347c74104216887ddd2e5aad4 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 6 Mar 2017 19:35:12 +0100 Subject: [PATCH 0019/2557] build: Fix logic of clock_gettime() check We should only check for clock_gettime() if _POSIX_MONOTONIC_CLOCK is available and do a full link check for clock_gettime() in all cases. --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 397d19c923183..a8e3926b70aa6 100755 --- a/configure +++ b/configure @@ -4572,8 +4572,8 @@ check_func ${malloc_prefix}memalign && enable memalign check_func ${malloc_prefix}posix_memalign && enable posix_memalign check_cpp_condition unistd.h "defined(_POSIX_MONOTONIC_CLOCK)" && - check_func_headers time.h clock_gettime || - check_lib clock_gettime time.h clock_gettime -lrt + { check_lib clock_gettime time.h clock_gettime || + check_lib clock_gettime time.h clock_gettime -lrt; } check_func fcntl check_func fork From 57b753b445e23363c997a8ec1c556e0b0f6e9da3 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Thu, 13 Oct 2016 20:33:15 +0200 Subject: [PATCH 0020/2557] build: Prefer NASM assembler over YASM NASM is more actively maintained and permits generating dependency information as a sideeffect of assembling, thus cutting build times in half. --- .travis.yml | 4 ++-- Changelog | 2 ++ configure | 6 +++--- doc/optimization.txt | 8 ++++---- doc/platform.texi | 12 ++++++------ 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8e9629a8ddd76..6f9647a70134b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ os: addons: apt: packages: - - yasm + - nasm - diffutils compiler: - clang @@ -17,7 +17,7 @@ cache: before_install: - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update --all; fi install: - - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install yasm; fi + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install nasm; fi script: - mkdir -p libav-samples - ./configure --samples=libav-samples --cc=$CC diff --git a/Changelog b/Changelog index 8e8bbcbf52f75..cdf073b799b1d 100644 --- a/Changelog +++ b/Changelog @@ -9,6 +9,8 @@ version : - config.log and other configuration files moved into avbuild/ directory - VAAPI-accelerated MPEG-2 and VP8 encoding - Apple Pixlet decoder +- The x86 assembler default switched from yasm to nasm, pass + --x86asmexe=yasm to configure to restore the old behavior. version 12: diff --git a/configure b/configure index 77b74dd40868b..587b2186cf14b 100755 --- a/configure +++ b/configure @@ -2563,7 +2563,7 @@ shlibdir_default="$libdir_default" ar_default="ar" cc_default="gcc" host_cc_default="gcc" -x86asmexe_default="yasm" +x86asmexe_default="nasm" ln_s="ln -s -f" nm_default="nm -g" pkg_config_default=pkg-config @@ -4493,7 +4493,7 @@ EOF } if ! disabled_any asm mmx x86asm; then - for program in $x86asmexe yasm nasm; do + for program in $x86asmexe nasm yasm; do probe_x86asm $program test -n "$x86asm_type" && break done @@ -4505,7 +4505,7 @@ EOF esac check_x86asm "movbe ecx, [5]" && enable x86asm || - die "yasm/nasm not found or too old. Use --disable-x86asm for a crippled build." + die "nasm/yasm not found or too old. Use --disable-x86asm for a crippled build." check_x86asm "vextracti128 xmm0, ymm0, 0" || disable avx2_external check_x86asm "vpmacsdd xmm0, xmm1, xmm2, xmm3" || disable xop_external check_x86asm "vfmadd132ps ymm0, ymm1, ymm2" || disable fma3_external diff --git a/doc/optimization.txt b/doc/optimization.txt index be12d85545025..3277b9b721bd6 100644 --- a/doc/optimization.txt +++ b/doc/optimization.txt @@ -161,8 +161,8 @@ do{ For x86, mark registers that are clobbered in your asm. This means both general x86 registers (e.g. eax) as well as XMM registers. This last one is particularly important on Win64, where xmm6-15 are callee-save, and not -restoring their contents leads to undefined results. In external asm (e.g. -yasm), you do this by using: +restoring their contents leads to undefined results. In external asm, +you do this by using: cglobal function_name, num_args, num_regs, num_xmm_regs In inline asm, you specify clobbered registers at the end of your asm: __asm__(".." ::: "%eax"). @@ -194,12 +194,12 @@ The latter requires a good optimizing compiler which gcc is not. Inline asm vs. external asm --------------------------- Both inline asm (__asm__("..") in a .c file, handled by a compiler such as gcc) -and external asm (.s or .asm files, handled by an assembler such as yasm/nasm) +and external asm (.s or .asm files, handled by an assembler such as nasm/yasm) are accepted in Libav. Which one to use differs per specific case. - if your code is intended to be inlined in a C function, inline asm is always better, because external asm cannot be inlined -- if your code calls external functions, yasm is always better +- if your code calls external functions, external asm is always better - if your code takes huge and complex structs as function arguments (e.g. MpegEncContext; note that this is not ideal and is discouraged if there are alternatives), then inline asm is always better, because predicting diff --git a/doc/platform.texi b/doc/platform.texi index 74b014e138aab..dc20d67bb74c3 100644 --- a/doc/platform.texi +++ b/doc/platform.texi @@ -69,9 +69,9 @@ OS X on PowerPC or ARM (iPhone) requires a preprocessor from assembly functions. Put the Perl script somewhere in your PATH, Libav's configure will pick it up automatically. -OS X on AMD64 and x86 requires @command{yasm} to build most of the +OS X on AMD64 and x86 requires @command{nasm} to build most of the optimized assembly functions @url{http://mxcl.github.com/homebrew/, Homebrew}, -@url{http://www.gentoo.org/proj/en/gentoo-alt/prefix/bootstrap-macos.xml, Gentoo Prefix} +@url{https://wiki.gentoo.org/wiki/Project:Prefix, Gentoo Prefix} or @url{http://www.macports.org, MacPorts} can easily provide it. @@ -134,7 +134,7 @@ them under @command{MinGW-w64 Win64 Shell} and @command{MinGW-w64 Win32 Shell}. pacman -S make pkgconf diffutils # mingw-w64 packages and toolchains -pacman -S mingw-w64-x86_64-yasm mingw-w64-x86_64-gcc mingw-w64-x86_64-SDL +pacman -S mingw-w64-x86_64-nasm mingw-w64-x86_64-gcc mingw-w64-x86_64-SDL @end example To target 32 bits replace @code{x86_64} with @code{i686} in the command above. @@ -152,14 +152,14 @@ You will need the following prerequisites: @item @uref{http://code.google.com/p/msinttypes/, msinttypes} (if using MSVC 2012 or earlier) @item @uref{http://msys2.github.io/, MSYS2} -@item @uref{http://yasm.tortall.net/, YASM} +@item @uref{http://www.nasm.us/, NASM} (Also available via MSYS2's package manager.) @end itemize To set up a proper environment in MSYS2, you need to run @code{msys_shell.bat} from the Visual Studio or Intel Compiler command prompt. -Place @code{yasm.exe} somewhere in your @code{PATH}. If using MSVC 2012 or +Place @code{nasm.exe} somewhere in your @code{PATH}. If using MSVC 2012 or earlier, place @code{c99wrap.exe} and @code{c99conv.exe} somewhere in your @code{PATH} as well. @@ -307,7 +307,7 @@ These library packages are only available from @uref{http://sourceware.org/cygwinports/, Cygwin Ports}: @example -yasm, libSDL-devel, libfaac-devel, libgsm-devel, libmp3lame-devel, +nasm, libSDL-devel, libfaac-devel, libgsm-devel, libmp3lame-devel, libschroedinger1.0-devel, speex-devel, libtheora-devel, libxvidcore-devel @end example From 81bffae368f331b6cd386a814f225a58e3f32f40 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 6 Mar 2017 20:21:19 +0100 Subject: [PATCH 0021/2557] configure: Check for -no_weak_imports in ldflags on macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recent versions of macOS provide more POSIX API (in particular, clock_gettime) than previous versions and recent Apple toolchains provide all that API, even when targeting older releases without said API. Disallow linking to functions which might not be available at runtime. To actually have an effect, either add --extra-cflags="-mmacosx-version-min=10.11" (or any other version prior to 10.12) or set MACOSX_DEPLOYMENT_TARGET=10.11 when running configure. As a workaround for libav versions without this fix, one can also add --extra-cflags="-mmacosx-version-min=10.11 -Werror=partial-availability" while running configure. The -no_weak_imports flag is new in Xcode 8; in Xcode 7 it is not supported. This is not an issue since Xcode 7 only ships with the 10.11 macOS SDK, which lacks clock_gettime. Bug-Id: 1033 CC: libav-stable@libav.org Signed-off-by: Martin Storsjö --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 587b2186cf14b..f915871b5cc1e 100755 --- a/configure +++ b/configure @@ -3948,6 +3948,7 @@ case $target_os in SHFLAGS='-dynamiclib -Wl,-single_module -Wl,-install_name,$(SHLIBDIR)/$(SLIBNAME_WITH_MAJOR),-current_version,$(LIBVERSION),-compatibility_version,$(LIBMAJOR)' enabled x86_32 && append SHFLAGS -Wl,-read_only_relocs,suppress add_ldflags -Wl,-dynamic,-search_paths_first + check_ldflags -Wl,-no_weak_imports SLIBSUF=".dylib" SLIBNAME_WITH_VERSION='$(SLIBPREF)$(NAME).$(LIBVERSION)$(SLIBSUF)' SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(NAME).$(LIBMAJOR)$(SLIBSUF)' From 17adcc40adf1f30cba55c9727dabc1365944d32b Mon Sep 17 00:00:00 2001 From: Aaron Colwell Date: Fri, 27 Jan 2017 09:33:29 -0800 Subject: [PATCH 0022/2557] mov: Fix spherical metadata_source parsing Signed-off-by: James Almer --- libavformat/mov.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 5c9f85c738da6..d5de5d6b1390d 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3252,7 +3252,7 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) } size = avio_rb32(pb); - if (size > atom.size) + if (size <= 12 || size > atom.size) return AVERROR_INVALIDDATA; tag = avio_rl32(pb); @@ -3261,7 +3261,7 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } avio_skip(pb, 4); /* version + flags */ - avio_skip(pb, avio_r8(pb)); /* metadata_source */ + avio_skip(pb, size - 12); /* metadata_source */ size = avio_rb32(pb); if (size > atom.size) From 114324b9e04505c71d9a3ffd854f25062fa3678f Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Tue, 28 Feb 2017 11:27:02 -0500 Subject: [PATCH 0023/2557] mov: Validate cubemap layout --- libavformat/mov.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index f406831457b8d..2bd48079ecb64 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3235,7 +3235,7 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; MOVStreamContext *sc; - int size, version; + int size, version, layout; int32_t yaw, pitch, roll; uint32_t tag; enum AVSphericalProjection projection; @@ -3315,6 +3315,12 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_skip(pb, 3); /* flags */ switch (tag) { case MKTAG('c','b','m','p'): + layout = avio_rb32(pb); + if (layout) { + av_log(c->fc, AV_LOG_WARNING, + "Unsupported cubemap layout %d\n", layout); + return 0; + } projection = AV_SPHERICAL_CUBEMAP; break; case MKTAG('e','q','u','i'): From 6bce6aa17d7f22bf46fde0d4610a41d2af0c0e48 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Fri, 10 Feb 2017 15:26:55 -0500 Subject: [PATCH 0024/2557] spherical: Add tiled equirectangular type and projection-specific properties Signed-off-by: Vittorio Giovara --- avtools/avprobe.c | 18 +++++++++-- doc/APIchanges | 5 +++ libavformat/dump.c | 15 +++++++-- libavutil/spherical.c | 18 +++++++++++ libavutil/spherical.h | 74 +++++++++++++++++++++++++++++++++++++++++++ libavutil/version.h | 2 +- 6 files changed, 126 insertions(+), 6 deletions(-) diff --git a/avtools/avprobe.c b/avtools/avprobe.c index 613e090be6e8b..68f19220c8f34 100644 --- a/avtools/avprobe.c +++ b/avtools/avprobe.c @@ -792,11 +792,23 @@ static void show_stream(InputFile *ifile, InputStream *ist) spherical = (AVSphericalMapping *)sd->data; probe_object_header("spherical"); - if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR) + if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR) { probe_str("projection", "equirectangular"); - else if (spherical->projection == AV_SPHERICAL_CUBEMAP) + } else if (spherical->projection == AV_SPHERICAL_CUBEMAP) { probe_str("projection", "cubemap"); - else + probe_int("padding", spherical->padding); + } else if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) { + size_t l, t, r, b; + av_spherical_tile_bounds(spherical, par->width, par->height, + &l, &t, &r, &b); + probe_str("projection", "tiled equirectangular"); + probe_object_header("bounding"); + probe_int("left", l); + probe_int("top", t); + probe_int("right", r); + probe_int("bottom", b); + probe_object_footer("bounding"); + } else probe_str("projection", "unknown"); probe_object_header("orientation"); diff --git a/doc/APIchanges b/doc/APIchanges index a919ffb2bf302..9367a5fc41785 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,11 @@ libavutil: 2015-08-28 API changes, most recent first: +2017-02-10 - xxxxxxx - lavu 55.33.0 - spherical.h + Add AV_SPHERICAL_EQUIRECTANGULAR_TILE, av_spherical_tile_bounds(), + and projection-specific properties (bound_left, bound_top, bound_right, + bound_bottom, padding) to AVSphericalMapping. + 2017-xx-xx - xxxxxxx - lavc 57.34.0 - avcodec.h Add AVCodecContext.hw_device_ctx. diff --git a/libavformat/dump.c b/libavformat/dump.c index 660df0a533f44..7514aee7ac71c 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -307,7 +307,7 @@ static void dump_cpb(void *ctx, AVPacketSideData *sd) cpb->vbv_delay); } -static void dump_spherical(void *ctx, AVPacketSideData *sd) +static void dump_spherical(void *ctx, AVCodecParameters *par, AVPacketSideData *sd) { AVSphericalMapping *spherical = (AVSphericalMapping *)sd->data; double yaw, pitch, roll; @@ -321,6 +321,8 @@ static void dump_spherical(void *ctx, AVPacketSideData *sd) av_log(ctx, AV_LOG_INFO, "equirectangular "); else if (spherical->projection == AV_SPHERICAL_CUBEMAP) av_log(ctx, AV_LOG_INFO, "cubemap "); + else if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) + av_log(ctx, AV_LOG_INFO, "tiled equirectangular "); else { av_log(ctx, AV_LOG_WARNING, "unknown"); return; @@ -330,6 +332,15 @@ static void dump_spherical(void *ctx, AVPacketSideData *sd) pitch = ((double)spherical->pitch) / (1 << 16); roll = ((double)spherical->roll) / (1 << 16); av_log(ctx, AV_LOG_INFO, "(%f/%f/%f) ", yaw, pitch, roll); + + if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) { + size_t l, t, r, b; + av_spherical_tile_bounds(spherical, par->width, par->height, + &l, &t, &r, &b); + av_log(ctx, AV_LOG_INFO, "[%zu, %zu, %zu, %zu] ", l, t, r, b); + } else if (spherical->projection == AV_SPHERICAL_CUBEMAP) { + av_log(ctx, AV_LOG_INFO, "[pad %zu] ", spherical->padding); + } } static void dump_sidedata(void *ctx, AVStream *st, const char *indent) @@ -382,7 +393,7 @@ static void dump_sidedata(void *ctx, AVStream *st, const char *indent) break; case AV_PKT_DATA_SPHERICAL: av_log(ctx, AV_LOG_INFO, "spherical: "); - dump_spherical(ctx, &sd); + dump_spherical(ctx, st->codecpar, &sd); break; default: av_log(ctx, AV_LOG_WARNING, diff --git a/libavutil/spherical.c b/libavutil/spherical.c index f6e53d1bd2f14..f5accc487d831 100644 --- a/libavutil/spherical.c +++ b/libavutil/spherical.c @@ -32,3 +32,21 @@ AVSphericalMapping *av_spherical_alloc(size_t *size) return spherical; } + +void av_spherical_tile_bounds(AVSphericalMapping *map, + size_t width, size_t height, + size_t *left, size_t *top, + size_t *right, size_t *bottom) +{ + /* conversion from 0.32 coordinates to pixels */ + uint64_t orig_width = (uint64_t) width * UINT32_MAX / + (UINT32_MAX - map->bound_right - map->bound_left); + uint64_t orig_height = (uint64_t) height * UINT32_MAX / + (UINT32_MAX - map->bound_bottom - map->bound_top); + + /* add a (UINT32_MAX - 1) to round up integer division */ + *left = (orig_width * map->bound_left + UINT32_MAX - 1) / UINT32_MAX; + *top = (orig_height * map->bound_top + UINT32_MAX - 1) / UINT32_MAX; + *right = orig_width - width - *left; + *bottom = orig_height - height - *top; +} diff --git a/libavutil/spherical.h b/libavutil/spherical.h index 0045eb974aef7..e7fc1d69fb1d9 100644 --- a/libavutil/spherical.h +++ b/libavutil/spherical.h @@ -63,6 +63,13 @@ enum AVSphericalProjection { * to the back. */ AV_SPHERICAL_CUBEMAP, + + /** + * Video represents a portion of a sphere mapped on a flat surface + * using equirectangular projection. The @ref bounding fields indicate + * the position of the current video in a larger surface. + */ + AV_SPHERICAL_EQUIRECTANGULAR_TILE, }; /** @@ -122,6 +129,57 @@ typedef struct AVSphericalMapping { /** * @} */ + + /** + * @name Bounding rectangle + * @anchor bounding + * @{ + * These fields indicate the location of the current tile, and where + * it should be mapped relative to the original surface. They are + * exported as 0.32 fixed point, and can be converted to classic + * pixel values with av_spherical_bounds(). + * + * @code{.unparsed} + * +----------------+----------+ + * | |bound_top | + * | +--------+ | + * | bound_left |tile | | + * +<---------->| |<--->+bound_right + * | +--------+ | + * | | | + * | bound_bottom| | + * +----------------+----------+ + * @endcode + * + * If needed, the original video surface dimensions can be derived + * by adding the current stream or frame size to the related bounds, + * like in the following example: + * + * @code{c} + * original_width = tile->width + bound_left + bound_right; + * original_height = tile->height + bound_top + bound_bottom; + * @endcode + * + * @note These values are valid only for the tiled equirectangular + * projection type (@ref AV_SPHERICAL_EQUIRECTANGULAR_TILE), + * and should be ignored in all other cases. + */ + size_t bound_left; ///< Distance from the left edge + size_t bound_top; ///< Distance from the top edge + size_t bound_right; ///< Distance from the right edge + size_t bound_bottom; ///< Distance from the bottom edge + /** + * @} + */ + + /** + * Number of pixels to pad from the edge of each cube face. + * + * @note This value is valid for only for the cubemap projection type + * (@ref AV_SPHERICAL_CUBEMAP), and should be ignored in all other + * cases. + */ + size_t padding; } AVSphericalMapping; /** @@ -132,6 +190,22 @@ typedef struct AVSphericalMapping { */ AVSphericalMapping *av_spherical_alloc(size_t *size); +/** + * Convert the @ref bounding fields from an AVSphericalVideo + * from 0.32 fixed point to pixels. + * + * @param map The AVSphericalVideo map to read bound values from. + * @param width Width of the current frame or stream. + * @param height Height of the current frame or stream. + * @param left Pixels from the left edge. + * @param top Pixels from the top edge. + * @param right Pixels from the right edge. + * @param bottom Pixels from the bottom edge. + */ +void av_spherical_tile_bounds(AVSphericalMapping *map, + size_t width, size_t height, + size_t *left, size_t *top, + size_t *right, size_t *bottom); /** * @} * @} diff --git a/libavutil/version.h b/libavutil/version.h index 5dbc57cc1b475..0f2b684fa8fc4 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -54,7 +54,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 55 -#define LIBAVUTIL_VERSION_MINOR 32 +#define LIBAVUTIL_VERSION_MINOR 33 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 236577230051ad61ec67fa2d68e817d54232d2a0 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Tue, 28 Feb 2017 10:54:36 -0500 Subject: [PATCH 0025/2557] mov: Ignore old spherical metadata when newer version is present --- libavformat/mov.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index d5de5d6b1390d..f1ff6ad5b5997 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3335,7 +3335,8 @@ static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_ goto out; /* Check for mandatory keys and values, try to support XML as best-effort */ - if (av_stristr(buffer, "") && + if (!sc->spherical && + av_stristr(buffer, "") && (val = av_stristr(buffer, "")) && av_stristr(val, "true") && (val = av_stristr(buffer, "")) && @@ -3348,7 +3349,7 @@ static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_ sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR; - if (av_stristr(buffer, "")) { + if (av_stristr(buffer, "") && !sc->stereo3d) { enum AVStereo3DType mode; if (av_stristr(buffer, "left-right")) From 0f8512c4a87b89b4694053d8ffda48066ee1da62 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 15 Feb 2017 10:40:16 -0500 Subject: [PATCH 0026/2557] mov: Validate spherical metadata version --- libavformat/mov.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index f1ff6ad5b5997..f406831457b8d 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3235,7 +3235,7 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; MOVStreamContext *sc; - int size; + int size, version; int32_t yaw, pitch, roll; uint32_t tag; enum AVSphericalProjection projection; @@ -3260,7 +3260,13 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n"); return 0; } - avio_skip(pb, 4); /* version + flags */ + version = avio_r8(pb); + if (version != 0) { + av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n", + version); + return 0; + } + avio_skip(pb, 3); /* flags */ avio_skip(pb, size - 12); /* metadata_source */ size = avio_rb32(pb); @@ -3282,7 +3288,13 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n"); return 0; } - avio_skip(pb, 4); /* version + flags */ + version = avio_r8(pb); + if (version != 0) { + av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n", + version); + return 0; + } + avio_skip(pb, 3); /* flags */ /* 16.16 fixed point */ yaw = avio_rb32(pb); @@ -3294,7 +3306,13 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR_INVALIDDATA; tag = avio_rl32(pb); - avio_skip(pb, 4); /* version + flags */ + version = avio_r8(pb); + if (version != 0) { + av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n", + version); + return 0; + } + avio_skip(pb, 3); /* flags */ switch (tag) { case MKTAG('c','b','m','p'): projection = AV_SPHERICAL_CUBEMAP; From a825980f9f93af32c719497f9aab1e14248ab471 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Fri, 10 Feb 2017 15:36:56 -0500 Subject: [PATCH 0027/2557] mov: Export bounds and padding from spherical metadata Update the fate test as needed. Signed-off-by: Vittorio Giovara --- libavformat/mov.c | 27 ++++++++++++++++++++++++++- libavformat/version.h | 2 +- tests/fate/mov.mak | 2 +- tests/ref/fate/mov-spherical | 6 +++++- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 2bd48079ecb64..c6e7a38398d3a 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3237,6 +3237,8 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) MOVStreamContext *sc; int size, version, layout; int32_t yaw, pitch, roll; + size_t l = 0, t = 0, r = 0, b = 0; + size_t padding = 0; uint32_t tag; enum AVSphericalProjection projection; @@ -3322,9 +3324,25 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } projection = AV_SPHERICAL_CUBEMAP; + padding = avio_rb32(pb); break; case MKTAG('e','q','u','i'): - projection = AV_SPHERICAL_EQUIRECTANGULAR; + t = avio_rb32(pb); + b = avio_rb32(pb); + l = avio_rb32(pb); + r = avio_rb32(pb); + + if (b >= UINT_MAX - t || r >= UINT_MAX - l) { + av_log(c->fc, AV_LOG_ERROR, + "Invalid bounding rectangle coordinates " + "%zu,%zu,%zu,%zu\n", l, t, r, b); + return AVERROR_INVALIDDATA; + } + + if (l || t || r || b) + projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE; + else + projection = AV_SPHERICAL_EQUIRECTANGULAR; break; default: av_log(c->fc, AV_LOG_ERROR, "Unknown projection type\n"); @@ -3341,6 +3359,13 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->spherical->pitch = pitch; sc->spherical->roll = roll; + sc->spherical->padding = padding; + + sc->spherical->bound_left = l; + sc->spherical->bound_top = t; + sc->spherical->bound_right = r; + sc->spherical->bound_bottom = b; + return 0; } diff --git a/libavformat/version.h b/libavformat/version.h index 92f3407909678..98faff77c0780 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 57 #define LIBAVFORMAT_VERSION_MINOR 11 -#define LIBAVFORMAT_VERSION_MICRO 0 +#define LIBAVFORMAT_VERSION_MICRO 1 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 57cbb1cac0e72..9d64fd3a4adb2 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -11,7 +11,7 @@ FATE_MOV += fate-mov-sar fate-mov-sar: CMD = probestream sample_aspect_ratio $(TARGET_SAMPLES)/mov/displaymatrix.mov FATE_MOV += fate-mov-spherical -fate-mov-spherical: CMD = probestream projection,yaw,pitch,roll $(TARGET_SAMPLES)/mov/spherical.mov +fate-mov-spherical: CMD = probestream projection,yaw,pitch,roll,left,top,right,bottom $(TARGET_SAMPLES)/mov/spherical.mov FATE_MOV += fate-mov-stereo3d fate-mov-stereo3d: CMD = probestream type $(TARGET_SAMPLES)/mov/spherical.mov diff --git a/tests/ref/fate/mov-spherical b/tests/ref/fate/mov-spherical index 760ae880e8817..a3f8cdfa608d9 100644 --- a/tests/ref/fate/mov-spherical +++ b/tests/ref/fate/mov-spherical @@ -1,4 +1,8 @@ -equirectangular +tiled equirectangular +148 +73 +147 +72 45 30 15 From 251849f06ce36ce8dc076e0fca2922119fa7e39e Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 6 Dec 2016 14:48:45 -0300 Subject: [PATCH 0028/2557] mkv: Add support for Spherical Video elements Signed-off-by: James Almer Signed-off-by: Vittorio Giovara --- libavformat/matroska.h | 14 ++++++++ libavformat/matroskadec.c | 69 +++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/libavformat/matroska.h b/libavformat/matroska.h index 91bb978422658..4e9f96e5304ef 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -118,6 +118,13 @@ #define MATROSKA_ID_VIDEOASPECTRATIO 0x54B3 #define MATROSKA_ID_VIDEOCOLORSPACE 0x2EB524 +#define MATROSKA_ID_VIDEOPROJECTION 0x7670 +#define MATROSKA_ID_VIDEOPROJECTIONTYPE 0x7671 +#define MATROSKA_ID_VIDEOPROJECTIONPRIVATE 0x7672 +#define MATROSKA_ID_VIDEOPROJECTIONPOSEYAW 0x7673 +#define MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH 0x7674 +#define MATROSKA_ID_VIDEOPROJECTIONPOSEROLL 0x7675 + /* IDs in the trackaudio master */ #define MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5 #define MATROSKA_ID_AUDIOOUTSAMPLINGFREQ 0x78B5 @@ -256,6 +263,13 @@ typedef enum { MATROSKA_VIDEO_STEREOMODE_TYPE_NB, } MatroskaVideoStereoModeType; +typedef enum { + MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR = 0, + MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR = 1, + MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP = 2, + MATROSKA_VIDEO_PROJECTION_TYPE_MESH = 3, +} MatroskaVideoProjectionType; + /* * Matroska Codec IDs, strings */ diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 4e121b6afe3e2..3dd54ebdf6df7 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -45,6 +45,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/lzo.h" #include "libavutil/mathematics.h" +#include "libavutil/spherical.h" #include "libavcodec/bytestream.h" #include "libavcodec/flac.h" @@ -116,6 +117,14 @@ typedef struct MatroskaTrackEncoding { MatroskaTrackCompression compression; } MatroskaTrackEncoding; +typedef struct MatroskaTrackVideoProjection { + uint64_t type; + EbmlBin private; + double yaw; + double pitch; + double roll; +} MatroskaTrackVideoProjection; + typedef struct MatroskaTrackVideo { double frame_rate; uint64_t display_width; @@ -126,6 +135,7 @@ typedef struct MatroskaTrackVideo { uint64_t interlaced; uint64_t field_order; uint64_t stereo_mode; + MatroskaTrackVideoProjection projection; } MatroskaTrackVideo; typedef struct MatroskaTrackAudio { @@ -309,6 +319,15 @@ static EbmlSyntax matroska_info[] = { { 0 } }; +static const EbmlSyntax matroska_track_video_projection[] = { + { MATROSKA_ID_VIDEOPROJECTIONTYPE, EBML_UINT, 0, offsetof(MatroskaTrackVideoProjection, type), { .u = MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR } }, + { MATROSKA_ID_VIDEOPROJECTIONPRIVATE, EBML_BIN, 0, offsetof(MatroskaTrackVideoProjection, private) }, + { MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, EBML_FLOAT, 0, offsetof(MatroskaTrackVideoProjection, yaw), { .f=0.0 } }, + { MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, EBML_FLOAT, 0, offsetof(MatroskaTrackVideoProjection, pitch), { .f=0.0 } }, + { MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, EBML_FLOAT, 0, offsetof(MatroskaTrackVideoProjection, roll), { .f=0.0 } }, + { 0 } +}; + static EbmlSyntax matroska_track_video[] = { { MATROSKA_ID_VIDEOFRAMERATE, EBML_FLOAT, 0, offsetof(MatroskaTrackVideo, frame_rate) }, { MATROSKA_ID_VIDEODISPLAYWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo, display_width) }, @@ -316,6 +335,7 @@ static EbmlSyntax matroska_track_video[] = { { MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo, pixel_width) }, { MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo, pixel_height) }, { MATROSKA_ID_VIDEOCOLORSPACE, EBML_UINT, 0, offsetof(MatroskaTrackVideo, fourcc) }, + { MATROSKA_ID_VIDEOPROJECTION, EBML_NEST, 0, offsetof(MatroskaTrackVideo, projection), { .n = matroska_track_video_projection } }, { MATROSKA_ID_VIDEOPIXELCROPB, EBML_NONE }, { MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE }, { MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE }, @@ -1576,6 +1596,51 @@ static void mkv_stereo_mode_display_mul(int stereo_mode, } } +static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) +{ + AVSphericalMapping *spherical; + enum AVSphericalProjection projection; + size_t spherical_size; + int ret; + + switch (track->video.projection.type) { + case MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR: + projection = AV_SPHERICAL_EQUIRECTANGULAR; + break; + case MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP: + if (track->video.projection.private.size < 4) { + av_log(NULL, AV_LOG_ERROR, "Missing projection private properties\n"); + return AVERROR_INVALIDDATA; + } + projection = AV_SPHERICAL_CUBEMAP; + break; + default: + av_log(NULL, AV_LOG_WARNING, + "Unknown spherical metadata type %"PRIu64"\n", + track->video.projection.type); + return 0; + } + + spherical = av_spherical_alloc(&spherical_size); + if (!spherical) + return AVERROR(ENOMEM); + + spherical->projection = projection; + + spherical->yaw = (int32_t) (track->video.projection.yaw * (1 << 16)); + spherical->pitch = (int32_t) (track->video.projection.pitch * (1 << 16)); + spherical->roll = (int32_t) (track->video.projection.roll * (1 << 16)); + + ret = av_stream_add_side_data(st, AV_PKT_DATA_SPHERICAL, (uint8_t *)spherical, + spherical_size); + if (ret < 0) { + av_free(spherical); + return ret; + } + + return 0; +} + static int matroska_parse_tracks(AVFormatContext *s) { MatroskaDemuxContext *matroska = s->priv_data; @@ -1908,6 +1973,10 @@ static int matroska_parse_tracks(AVFormatContext *s) if (ret < 0) return ret; } + + ret = mkv_parse_video_projection(st, track); + if (ret < 0) + return ret; } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) { st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->sample_rate = track->audio.out_samplerate; diff --git a/libavformat/version.h b/libavformat/version.h index 98faff77c0780..fdf3e30851f15 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 57 #define LIBAVFORMAT_VERSION_MINOR 11 -#define LIBAVFORMAT_VERSION_MICRO 1 +#define LIBAVFORMAT_VERSION_MICRO 2 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From 0429f01e4722b8e0c3576a4810a16ca8f6dbc4d4 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Fri, 10 Feb 2017 16:02:22 -0500 Subject: [PATCH 0029/2557] mkv: Export bounds and padding from spherical metadata Signed-off-by: Vittorio Giovara --- libavformat/matroskadec.c | 55 +++++++++++++++++++++++++++++++++++++-- libavformat/version.h | 2 +- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 3dd54ebdf6df7..4fbf4b9a96526 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -1601,18 +1601,62 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) AVSphericalMapping *spherical; enum AVSphericalProjection projection; size_t spherical_size; + size_t l = 0, t = 0, r = 0, b = 0; + size_t padding = 0; int ret; + GetByteContext gb; + + bytestream2_init(&gb, track->video.projection.private.data, + track->video.projection.private.size); + + if (bytestream2_get_byte(&gb) != 0) { + av_log(NULL, AV_LOG_WARNING, "Unknown spherical metadata\n"); + return 0; + } + + bytestream2_skip(&gb, 3); // flags switch (track->video.projection.type) { case MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR: - projection = AV_SPHERICAL_EQUIRECTANGULAR; + if (track->video.projection.private.size == 20) { + t = bytestream2_get_be32(&gb); + b = bytestream2_get_be32(&gb); + l = bytestream2_get_be32(&gb); + r = bytestream2_get_be32(&gb); + + if (b >= UINT_MAX - t || r >= UINT_MAX - l) { + av_log(NULL, AV_LOG_ERROR, + "Invalid bounding rectangle coordinates " + "%zu,%zu,%zu,%zu\n", l, t, r, b); + return AVERROR_INVALIDDATA; + } + } else if (track->video.projection.private.size != 0) { + av_log(NULL, AV_LOG_ERROR, "Unknown spherical metadata\n"); + return AVERROR_INVALIDDATA; + } + + if (l || t || r || b) + projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE; + else + projection = AV_SPHERICAL_EQUIRECTANGULAR; break; case MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP: if (track->video.projection.private.size < 4) { av_log(NULL, AV_LOG_ERROR, "Missing projection private properties\n"); return AVERROR_INVALIDDATA; + } else if (track->video.projection.private.size == 12) { + uint32_t layout = bytestream2_get_be32(&gb); + if (layout) { + av_log(NULL, AV_LOG_WARNING, + "Unknown spherical cubemap layout %"PRIu32"\n", layout); + return 0; + } + projection = AV_SPHERICAL_CUBEMAP; + padding = bytestream2_get_be32(&gb); + } else { + av_log(NULL, AV_LOG_ERROR, "Unknown spherical metadata\n"); + return AVERROR_INVALIDDATA; } - projection = AV_SPHERICAL_CUBEMAP; break; default: av_log(NULL, AV_LOG_WARNING, @@ -1631,6 +1675,13 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) spherical->pitch = (int32_t) (track->video.projection.pitch * (1 << 16)); spherical->roll = (int32_t) (track->video.projection.roll * (1 << 16)); + spherical->padding = padding; + + spherical->bound_left = l; + spherical->bound_top = t; + spherical->bound_right = r; + spherical->bound_bottom = b; + ret = av_stream_add_side_data(st, AV_PKT_DATA_SPHERICAL, (uint8_t *)spherical, spherical_size); if (ret < 0) { diff --git a/libavformat/version.h b/libavformat/version.h index fdf3e30851f15..3e28cc2804b75 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 57 #define LIBAVFORMAT_VERSION_MINOR 11 -#define LIBAVFORMAT_VERSION_MICRO 2 +#define LIBAVFORMAT_VERSION_MICRO 3 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From 8a60bba0aef77015111570058d5a72f0428dc748 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 6 Mar 2017 11:34:20 +0100 Subject: [PATCH 0030/2557] avcodec: clarify some decoding/encoding API details Make it clear that there is no timing-dependent behavior. In particular, there is no state in which both input and output are denied, and where you have to wait for a while yourself to make progress (apparently some hardware decoders like to do this). Avoid wording that makes references to time. It shouldn't be mistaken for some kind of asynchronous API (like POSIX read() can return EAGAIN if there is no new input yet). It's a state machine, so try to use appropriate terms. Signed-off-by: Diego Biurrun --- libavcodec/avcodec.h | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 489a618cbbda1..c03754695f284 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -114,6 +114,12 @@ * are filled. This situation is handled transparently if you follow the steps * outlined above. * + * In theory, sending input can result in EAGAIN - this should happen only if + * not all output was received. You can use this to structure alternative decode + * or encode loops other than the one suggested above. For example, you could + * try sending new input on each iteration, and try to receive output if that + * returns EAGAIN. + * * End of stream situations. These require "flushing" (aka draining) the codec, * as the codec might buffer multiple frames or packets internally for * performance or out of necessity (consider B-frames). @@ -148,7 +154,8 @@ * Unlike with the old video decoding API, multiple frames might result from * a packet. For audio, splitting the input packet into frames by partially * decoding packets becomes transparent to the API user. You never need to - * feed an AVPacket to the API twice. + * feed an AVPacket to the API twice (unless it is rejected with EAGAIN - then + * no data was read from the packet). * Additionally, sending a flush/draining packet is required only once. * - avcodec_encode_video2()/avcodec_encode_audio2(): * Use avcodec_send_frame() to feed input to the encoder, then use @@ -161,7 +168,22 @@ * and will result in arbitrary behavior. * * Some codecs might require using the new API; using the old API will return - * an error when calling it. + * an error when calling it. All codecs support the new API. + * + * A codec is not allowed to return EAGAIN for both sending and receiving. This + * would be an invalid state, which could put the codec user into an endless + * loop. The API has no concept of time either: it cannot happen that trying to + * do avcodec_send_packet() results in EAGAIN, but a repeated call 1 second + * later accepts the packet (with no other receive/flush API calls involved). + * The API is a strict state machine, and the passage of time is not supposed + * to influence it. Some timing-dependent behavior might still be deemed + * acceptable in certain cases. But it must never result in both send/receive + * returning EAGAIN at the same time at any point. It must also absolutely be + * avoided that the current state is "unstable" and can "flip-flop" between + * the send/receive APIs allowing progress. For example, it's not allowed that + * the codec randomly decides that it actually wants to consume a packet now + * instead of returning a frame, after it just returned EAGAIN on an + * avcodec_send_packet() call. * @} */ @@ -4339,8 +4361,10 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, * a flush packet. * * @return 0 on success, otherwise negative error code: - * AVERROR(EAGAIN): input is not accepted right now - the packet must be - * resent after trying to read output + * AVERROR(EAGAIN): input is not accepted in the current state - user + * must read output with avcodec_receive_frame() (once + * all output is read, the packet should be resent, and + * the call will not fail with EAGAIN). * AVERROR_EOF: the decoder has been flushed, and no new packets can * be sent to it (also returned if more than 1 flush * packet is sent) @@ -4361,7 +4385,7 @@ int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); * * @return * 0: success, a frame was returned - * AVERROR(EAGAIN): output is not available right now - user must try + * AVERROR(EAGAIN): output is not available in this state - user must try * to send new input * AVERROR_EOF: the decoder has been fully flushed, and there will be * no more output frames @@ -4394,8 +4418,10 @@ int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame); * avctx->frame_size for all frames except the last. * The final frame may be smaller than avctx->frame_size. * @return 0 on success, otherwise negative error code: - * AVERROR(EAGAIN): input is not accepted right now - the frame must be - * resent after trying to read output packets + * AVERROR(EAGAIN): input is not accepted in the current state - user + * must read output with avcodec_receive_packet() (once + * all output is read, the packet should be resent, and + * the call will not fail with EAGAIN). * AVERROR_EOF: the encoder has been flushed, and no new frames can * be sent to it * AVERROR(EINVAL): codec not opened, refcounted_frames not set, it is a @@ -4413,8 +4439,8 @@ int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); * encoder. Note that the function will always call * av_frame_unref(frame) before doing anything else. * @return 0 on success, otherwise negative error code: - * AVERROR(EAGAIN): output is not available right now - user must try - * to send input + * AVERROR(EAGAIN): output is not available in the current state - user + * must try to send input * AVERROR_EOF: the encoder has been fully flushed, and there will be * no more output packets * AVERROR(EINVAL): codec not opened, or it is an encoder From f6790b5e1075133ee39be91105f1135db7afd259 Mon Sep 17 00:00:00 2001 From: Konda Raju Date: Tue, 7 Mar 2017 12:02:14 +0530 Subject: [PATCH 0031/2557] add initial QP value options Signed-off-by: Diego Biurrun --- libavcodec/nvenc.c | 26 ++++++++++++++++++++++++++ libavcodec/nvenc.h | 3 +++ libavcodec/nvenc_h264.c | 3 +++ libavcodec/nvenc_hevc.c | 3 +++ 4 files changed, 35 insertions(+) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 738a77ebc2648..2e76ee870d495 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -519,6 +519,8 @@ static void set_constqp(AVCodecContext *avctx, NV_ENC_RC_PARAMS *rc) static void set_vbr(AVCodecContext *avctx, NV_ENC_RC_PARAMS *rc) { + NVENCContext *ctx = avctx->priv_data; + if (avctx->qmin >= 0) { rc->enableMinQP = 1; rc->minQP.qpInterB = avctx->qmin; @@ -532,6 +534,30 @@ static void set_vbr(AVCodecContext *avctx, NV_ENC_RC_PARAMS *rc) rc->maxQP.qpInterP = avctx->qmax; rc->maxQP.qpIntra = avctx->qmax; } + + if (ctx->init_qp_p >= 0) { + rc->enableInitialRCQP = 1; + rc->initialRCQP.qpInterP = ctx->init_qp_p; + if (ctx->init_qp_i < 0) { + if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) { + rc->initialRCQP.qpIntra = av_clip(rc->initialRCQP.qpInterP * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, 51); + } else { + rc->initialRCQP.qpIntra = rc->initialRCQP.qpInterP; + } + } else { + rc->initialRCQP.qpIntra = ctx->init_qp_i; + } + + if (ctx->init_qp_b < 0) { + if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) { + rc->initialRCQP.qpInterB = av_clip(rc->initialRCQP.qpInterP * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, 51); + } else { + rc->initialRCQP.qpInterB = rc->initialRCQP.qpInterP; + } + } else { + rc->initialRCQP.qpInterB = ctx->init_qp_b; + } + } } static void set_lossless(AVCodecContext *avctx, NV_ENC_RC_PARAMS *rc) diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 6df45480a9429..3602f16e83b14 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -183,6 +183,9 @@ typedef struct NVENCContext { int strict_gop; int aq_strength; int quality; + int init_qp_p; + int init_qp_b; + int init_qp_i; } NVENCContext; int ff_nvenc_encode_init(AVCodecContext *avctx); diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index faeafe92849a3..1419c867aa641 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -89,6 +89,9 @@ static const AVOption options[] = { { "aq-strength", "When Spatial AQ is enabled, this field is used to specify AQ strength. AQ strength scale is from 1 (low) - 15 (aggressive)", OFFSET(aq_strength), AV_OPT_TYPE_INT, { .i64 = 8 }, 1, 15, VE }, { "cq", "Set target quality level (0 to 51, 0 means automatic) for constant quality mode in VBR rate control", OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 51, VE }, #endif /* NVENCAPI_MAJOR_VERSION >= 7 */ + { "init_qpP", "Initial QP value for P-frames", OFFSET(init_qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "init_qpB", "Initial QP value for B-frames", OFFSET(init_qp_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "init_qpI", "Initial QP value for I-frames", OFFSET(init_qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, { NULL } }; diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index de9af6151f50e..62f969847a5dd 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -87,6 +87,9 @@ static const AVOption options[] = { { "aq-strength", "When Spatial AQ is enabled, this field is used to specify AQ strength. AQ strength scale is from 1 (low) - 15 (aggressive)", OFFSET(aq_strength), AV_OPT_TYPE_INT, { .i64 = 8 }, 1, 15, VE }, { "cq", "Set target quality level (0 to 51, 0 means automatic) for constant quality mode in VBR rate control", OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 51, VE }, #endif /* NVENCAPI_MAJOR_VERSION >= 7 */ + { "init_qpP", "Initial QP value for P-frames", OFFSET(init_qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "init_qpB", "Initial QP value for B-frames", OFFSET(init_qp_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "init_qpI", "Initial QP value for I-frames", OFFSET(init_qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, { NULL } }; From 5f794aa1653aa04c1da7397e9ccacad947fadf5f Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Sat, 30 Jan 2016 17:39:48 +0000 Subject: [PATCH 0032/2557] Add Cineform HD Decoder Decodes YUV 4:2:2 10-bit and RGB 12-bit files. Older files with more subbands, skips, Bayer, alpha not supported. Further fixes and refactorings by Anton Khirnov , Diego Biurrun , Vittorio Giovara Signed-off-by: Diego Biurrun --- Changelog | 1 + doc/general.texi | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/cfhd.c | 770 ++++++++++++++++++++++++++++++++++++++++ libavcodec/cfhd.h | 108 ++++++ libavcodec/cfhddata.c | 337 ++++++++++++++++++ libavcodec/codec_desc.c | 7 + libavcodec/version.h | 2 +- libavformat/riff.c | 1 + 11 files changed, 1229 insertions(+), 1 deletion(-) create mode 100644 libavcodec/cfhd.c create mode 100644 libavcodec/cfhd.h create mode 100644 libavcodec/cfhddata.c diff --git a/Changelog b/Changelog index cdf073b799b1d..04972399fd095 100644 --- a/Changelog +++ b/Changelog @@ -11,6 +11,7 @@ version : - Apple Pixlet decoder - The x86 assembler default switched from yasm to nasm, pass --x86asmexe=yasm to configure to restore the old behavior. +- Cineform HD decoder version 12: diff --git a/doc/general.texi b/doc/general.texi index 54e319f1ad86f..b21195bde2faa 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -626,6 +626,7 @@ following image formats are supported: @tab Amiga CD video codec @item Chinese AVS video @tab E @tab X @tab AVS1-P2, JiZhun profile, encoding through external library libxavs +@item Cineform HD @tab @tab X @item Delphine Software International CIN video @tab @tab X @tab Codec used in Delphine Software International games. @item Discworld II BMV Video @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 7f295dc6438fd..d586dbd01418c 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -180,6 +180,7 @@ OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ cavsdata.o mpeg12data.o OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o +OBJS-$(CONFIG_CFHD_DECODER) += cfhd.o cfhddata.o OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o OBJS-$(CONFIG_CLJR_DECODER) += cljrdec.o OBJS-$(CONFIG_CLJR_ENCODER) += cljrenc.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 1bfddb0ca6548..b9936c57f7496 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -127,6 +127,7 @@ void avcodec_register_all(void) REGISTER_DECODER(CAVS, cavs); REGISTER_DECODER(CDGRAPHICS, cdgraphics); REGISTER_DECODER(CDXL, cdxl); + REGISTER_DECODER(CFHD, cfhd); REGISTER_DECODER(CINEPAK, cinepak); REGISTER_ENCDEC (CLJR, cljr); REGISTER_DECODER(CLLC, cllc); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index c03754695f284..62a4fab8f93aa 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -415,6 +415,7 @@ enum AVCodecID { AV_CODEC_ID_TRUEMOTION2RT, AV_CODEC_ID_AV1, AV_CODEC_ID_PIXLET, + AV_CODEC_ID_CFHD, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/cfhd.c b/libavcodec/cfhd.c new file mode 100644 index 0000000000000..e122deb7a4a44 --- /dev/null +++ b/libavcodec/cfhd.c @@ -0,0 +1,770 @@ +/* + * Copyright (c) 2015-2016 Kieran Kunhya + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Cineform HD video decoder + */ + +#include "libavutil/attributes.h" +#include "libavutil/buffer.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "bitstream.h" +#include "bytestream.h" +#include "internal.h" +#include "thread.h" +#include "cfhd.h" + +enum CFHDParam { + ChannelCount = 12, + SubbandCount = 14, + ImageWidth = 20, + ImageHeight = 21, + LowpassPrecision = 35, + SubbandNumber = 48, + Quantization = 53, + ChannelNumber = 62, + BitsPerComponent = 101, + ChannelWidth = 104, + ChannelHeight = 105, + PrescaleShift = 109, +}; + +static av_cold int cfhd_init(AVCodecContext *avctx) +{ + CFHDContext *s = avctx->priv_data; + + memset(s, 0, sizeof(*s)); + + s->avctx = avctx; + avctx->bits_per_raw_sample = 10; + + return ff_cfhd_init_vlcs(s); +} + +static void init_plane_defaults(CFHDContext *s) +{ + s->subband_num = 0; + s->level = 0; + s->subband_num_actual = 0; +} + +static void init_frame_defaults(CFHDContext *s) +{ + s->coded_format = AV_PIX_FMT_YUV422P10; + s->coded_width = 0; + s->coded_height = 0; + s->cropped_height = 0; + s->bpc = 10; + s->channel_cnt = 4; + s->subband_cnt = SUBBAND_COUNT; + s->channel_num = 0; + s->lowpass_precision = 16; + s->quantisation = 1; + s->prescale_shift[0] = 0; + s->prescale_shift[1] = 0; + s->prescale_shift[2] = 0; + s->wavelet_depth = 3; + s->pshift = 1; + s->codebook = 0; + init_plane_defaults(s); +} + +/* TODO: merge with VLC tables or use LUT */ +static inline int dequant_and_decompand(int level, int quantisation) +{ + int64_t abslevel = abs(level); + return (abslevel + ((768 * abslevel * abslevel * abslevel) / (255 * 255 * 255))) * + FFSIGN(level) * quantisation; +} + +static inline void filter(int16_t *output, ptrdiff_t out_stride, + int16_t *low, ptrdiff_t low_stride, + int16_t *high, ptrdiff_t high_stride, + int len, int clip) +{ + int16_t tmp; + int i; + + for (i = 0; i < len; i++) { + if (i == 0) { + tmp = (11 * low[0 * low_stride] - 4 * low[1 * low_stride] + low[2 * low_stride] + 4) >> 3; + output[(2 * i + 0) * out_stride] = (tmp + high[0 * high_stride]) >> 1; + } else if (i == len - 1) { + tmp = (5 * low[i * low_stride] + 4 * low[(i - 1) * low_stride] - low[(i - 2) * low_stride] + 4) >> 3; + output[(2 * i + 0) * out_stride] = (tmp + high[i * high_stride]) >> 1; + } else { + tmp = (low[(i - 1) * low_stride] - low[(i + 1) * low_stride] + 4) >> 3; + output[(2 * i + 0) * out_stride] = (tmp + low[i * low_stride] + high[i * high_stride]) >> 1; + } + if (clip) + output[(2 * i + 0) * out_stride] = av_clip_uintp2_c(output[(2 * i + 0) * out_stride], clip); + + if (i == 0) { + tmp = (5 * low[0 * low_stride] + 4 * low[1 * low_stride] - low[2 * low_stride] + 4) >> 3; + output[(2 * i + 1) * out_stride] = (tmp - high[0 * high_stride]) >> 1; + } else if (i == len - 1) { + tmp = (11 * low[i * low_stride] - 4 * low[(i - 1) * low_stride] + low[(i - 2) * low_stride] + 4) >> 3; + output[(2 * i + 1) * out_stride] = (tmp - high[i * high_stride]) >> 1; + } else { + tmp = (low[(i + 1) * low_stride] - low[(i - 1) * low_stride] + 4) >> 3; + output[(2 * i + 1) * out_stride] = (tmp + low[i * low_stride] - high[i * high_stride]) >> 1; + } + if (clip) + output[(2 * i + 1) * out_stride] = av_clip_uintp2_c(output[(2 * i + 1) * out_stride], clip); + } +} + +static void horiz_filter(int16_t *output, int16_t *low, int16_t *high, + int width) +{ + filter(output, 1, low, 1, high, 1, width, 0); +} + +static void horiz_filter_clip(int16_t *output, int16_t *low, int16_t *high, + int width, int clip) +{ + filter(output, 1, low, 1, high, 1, width, clip); +} + +static void vert_filter(int16_t *output, ptrdiff_t out_stride, + int16_t *low, ptrdiff_t low_stride, + int16_t *high, ptrdiff_t high_stride, int len) +{ + filter(output, out_stride, low, low_stride, high, high_stride, len, 0); +} + +static void free_buffers(CFHDContext *s) +{ + unsigned i; + + for (i = 0; i < FF_ARRAY_ELEMS(s->plane); i++) { + av_freep(&s->plane[i].idwt_buf); + av_freep(&s->plane[i].idwt_tmp); + } + s->a_height = 0; + s->a_width = 0; +} + +static int alloc_buffers(CFHDContext *s) +{ + int i, j, ret, planes; + int chroma_x_shift, chroma_y_shift; + unsigned k; + + if ((ret = av_pix_fmt_get_chroma_sub_sample(s->coded_format, + &chroma_x_shift, + &chroma_y_shift)) < 0) + return ret; + planes = av_pix_fmt_count_planes(s->coded_format); + + for (i = 0; i < planes; i++) { + int w8, h8, w4, h4, w2, h2; + int width = i ? s->coded_width >> chroma_x_shift : s->coded_width; + int height = i ? s->coded_height >> chroma_y_shift : s->coded_height; + ptrdiff_t stride = FFALIGN(width / 8, 8) * 8; + height = FFALIGN(height / 8, 2) * 8; + s->plane[i].width = width; + s->plane[i].height = height; + s->plane[i].stride = stride; + + w8 = FFALIGN(s->plane[i].width / 8, 8); + h8 = FFALIGN(s->plane[i].height / 8, 2); + w4 = w8 * 2; + h4 = h8 * 2; + w2 = w4 * 2; + h2 = h4 * 2; + + s->plane[i].idwt_buf = + av_malloc_array(height * stride, sizeof(*s->plane[i].idwt_buf)); + s->plane[i].idwt_tmp = + av_malloc_array(height * stride, sizeof(*s->plane[i].idwt_tmp)); + if (!s->plane[i].idwt_buf || !s->plane[i].idwt_tmp) + return AVERROR(ENOMEM); + + s->plane[i].subband[0] = s->plane[i].idwt_buf; + s->plane[i].subband[1] = s->plane[i].idwt_buf + 2 * w8 * h8; + s->plane[i].subband[2] = s->plane[i].idwt_buf + 1 * w8 * h8; + s->plane[i].subband[3] = s->plane[i].idwt_buf + 3 * w8 * h8; + s->plane[i].subband[4] = s->plane[i].idwt_buf + 2 * w4 * h4; + s->plane[i].subband[5] = s->plane[i].idwt_buf + 1 * w4 * h4; + s->plane[i].subband[6] = s->plane[i].idwt_buf + 3 * w4 * h4; + s->plane[i].subband[7] = s->plane[i].idwt_buf + 2 * w2 * h2; + s->plane[i].subband[8] = s->plane[i].idwt_buf + 1 * w2 * h2; + s->plane[i].subband[9] = s->plane[i].idwt_buf + 3 * w2 * h2; + + for (j = 0; j < DWT_LEVELS; j++) { + for (k = 0; k < FF_ARRAY_ELEMS(s->plane[i].band[j]); k++) { + s->plane[i].band[j][k].a_width = w8 << j; + s->plane[i].band[j][k].a_height = h8 << j; + } + } + + /* ll2 and ll1 commented out because they are done in-place */ + s->plane[i].l_h[0] = s->plane[i].idwt_tmp; + s->plane[i].l_h[1] = s->plane[i].idwt_tmp + 2 * w8 * h8; + // s->plane[i].l_h[2] = ll2; + s->plane[i].l_h[3] = s->plane[i].idwt_tmp; + s->plane[i].l_h[4] = s->plane[i].idwt_tmp + 2 * w4 * h4; + // s->plane[i].l_h[5] = ll1; + s->plane[i].l_h[6] = s->plane[i].idwt_tmp; + s->plane[i].l_h[7] = s->plane[i].idwt_tmp + 2 * w2 * h2; + } + + s->a_height = s->coded_height; + s->a_width = s->coded_width; + s->a_format = s->coded_format; + + return 0; +} + +static int parse_tag(CFHDContext *s, GetByteContext *gb, + int16_t *tag_, uint16_t *value, int *planes) +{ + /* Bit weird but implement the tag parsing as the spec says */ + uint16_t tagu = bytestream2_get_be16(gb); + int16_t tag = tagu; + int8_t tag8 = tagu >> 8; + uint16_t abstag = abs(tag); + int8_t abs_tag8 = abs(tag8); + uint16_t data = bytestream2_get_be16(gb); + *tag_ = tag; + *value = data; + + if (abs_tag8 >= 0x60 && abs_tag8 <= 0x6F) { + av_log(s->avctx, AV_LOG_DEBUG, "large len %"PRIX16"\n", + ((tagu & 0xFF) << 16) | data); + return 0; + } else if (abstag >= 0x4000 && abstag <= 0x40FF) { + av_log(s->avctx, AV_LOG_DEBUG, "Small chunk length %"PRIu16" %s\n", + data * 4, tag < 0 ? "optional" : "required"); + bytestream2_skipu(gb, data * 4); + return 0; + } + + switch (tag) { + case 1: + av_log(s->avctx, AV_LOG_DEBUG, "Sample type? %"PRIu16"\n", data); + break; + case 2: + { + int i; + av_log(s->avctx, AV_LOG_DEBUG, + "tag=2 header - skipping %"PRIu16" tag/value pairs\n", data); + if (data > bytestream2_get_bytes_left(gb) / 4) { + av_log(s->avctx, AV_LOG_ERROR, + "Too many tag/value pairs (%"PRIu16")\n", data); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < data; i++) { + uint16_t tag2 = bytestream2_get_be16(gb); + uint16_t val2 = bytestream2_get_be16(gb); + av_log(s->avctx, AV_LOG_DEBUG, "Tag/Value = %"PRIX16" %"PRIX16"\n", + tag2, val2); + } + break; + } + case 10: + if (data != 0) { + avpriv_report_missing_feature(s->avctx, "Transform type %"PRIu16, data); + return AVERROR_PATCHWELCOME; + } + av_log(s->avctx, AV_LOG_DEBUG, "Transform-type? %"PRIu16"\n", data); + break; + case ChannelCount: + av_log(s->avctx, AV_LOG_DEBUG, "Channel count: %"PRIu16"\n", data); + if (data > 4) { + avpriv_report_missing_feature(s->avctx, "Channel count %"PRIu16, data); + return AVERROR_PATCHWELCOME; + } + s->channel_cnt = data; + break; + case SubbandCount: + av_log(s->avctx, AV_LOG_DEBUG, "Subband count: %"PRIu16"\n", data); + if (data != SUBBAND_COUNT) { + avpriv_report_missing_feature(s->avctx, "Subband count %"PRIu16, data); + return AVERROR_PATCHWELCOME; + } + break; + case ImageWidth: + av_log(s->avctx, AV_LOG_DEBUG, "Width %"PRIu16"\n", data); + s->coded_width = data; + break; + case ImageHeight: + av_log(s->avctx, AV_LOG_DEBUG, "Height %"PRIu16"\n", data); + s->coded_height = data; + break; + case 23: + avpriv_report_missing_feature(s->avctx, "Skip frame"); + return AVERROR_PATCHWELCOME; + case 27: + av_log(s->avctx, AV_LOG_DEBUG, "Lowpass width %"PRIu16"\n", data); + if (data < 2 || data > s->plane[s->channel_num].band[0][0].a_width) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid lowpass width\n"); + return AVERROR_INVALIDDATA; + } + s->plane[s->channel_num].band[0][0].width = data; + s->plane[s->channel_num].band[0][0].stride = data; + break; + case 28: + av_log(s->avctx, AV_LOG_DEBUG, "Lowpass height %"PRIu16"\n", data); + if (data < 2 || data > s->plane[s->channel_num].band[0][0].a_height) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid lowpass height\n"); + return AVERROR_INVALIDDATA; + } + s->plane[s->channel_num].band[0][0].height = data; + break; + case LowpassPrecision: + av_log(s->avctx, AV_LOG_DEBUG, "Lowpass precision bits: %"PRIu16"\n", data); + break; + case 41: + case 49: + av_log(s->avctx, AV_LOG_DEBUG, + "Highpass width%s %"PRIu16" channel %i level %i subband %i\n", + tag == 49 ? "2" : "", data, + s->channel_num, s->level, s->subband_num); + if (data < 2) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid highpass width%s\n", tag == 49 ? "2" : ""); + return AVERROR_INVALIDDATA; + } + s->plane[s->channel_num].band[s->level][s->subband_num].width = data; + s->plane[s->channel_num].band[s->level][s->subband_num].stride = FFALIGN(data, 8); + break; + case 42: + case 50: + av_log(s->avctx, AV_LOG_DEBUG, "Highpass height%s %"PRIu16"\n", tag == 50 ? "2" : "", data); + if (data < 2) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid highpass height%s\n", tag == 50 ? "2" : ""); + return AVERROR_INVALIDDATA; + } + s->plane[s->channel_num].band[s->level][s->subband_num].height = data; + break; + case SubbandNumber: + av_log(s->avctx, AV_LOG_DEBUG, "Subband number %"PRIu16"\n", data); + if (data > 3) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid subband number\n"); + return AVERROR_INVALIDDATA; + } + if (s->subband_num != 0 && data == 1) { + if (s->level + 1 >= DWT_LEVELS) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid level\n"); + return AVERROR_INVALIDDATA; + } + + s->level++; + } + s->subband_num = data; + break; + case 51: + av_log(s->avctx, AV_LOG_DEBUG, "Subband number actual %"PRIu16"\n", data); + if (data >= SUBBAND_COUNT) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid subband number actual\n"); + return AVERROR_INVALIDDATA; + } + s->subband_num_actual = data; + break; + case Quantization: + s->quantisation = data; + av_log(s->avctx, AV_LOG_DEBUG, "Quantisation: %"PRIu16"\n", data); + break; + case ChannelNumber: + av_log(s->avctx, AV_LOG_DEBUG, "Channel number %"PRIu16"\n", data); + if (data >= *planes) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid channel number\n"); + return AVERROR_INVALIDDATA; + } + s->channel_num = data; + init_plane_defaults(s); + break; + case 70: + av_log(s->avctx, AV_LOG_DEBUG, + "Subsampling or bit-depth flag? %"PRIu16"\n", data); + if (!(data == 10 || data == 12)) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid bits per channel\n"); + return AVERROR_INVALIDDATA; + } + s->bpc = data; + break; + case 71: + s->codebook = data; + av_log(s->avctx, AV_LOG_DEBUG, "Codebook %i\n", s->codebook); + break; + case 72: + s->codebook = data; + av_log(s->avctx, AV_LOG_DEBUG, "Other codebook? %i\n", s->codebook); + break; + case 84: + av_log(s->avctx, AV_LOG_DEBUG, "Sample format? %"PRIu16"\n", data); + switch (data) { + case 1: + s->coded_format = AV_PIX_FMT_YUV422P10; + break; + case 3: + s->coded_format = AV_PIX_FMT_GBRP12; + break; + case 4: + s->coded_format = AV_PIX_FMT_GBRAP12; + break; + default: + avpriv_report_missing_feature(s->avctx, "Sample format %"PRIu16, data); + return AVERROR_PATCHWELCOME; + } + *planes = av_pix_fmt_count_planes(s->coded_format); + break; + case -85: + av_log(s->avctx, AV_LOG_DEBUG, "Cropped height %"PRIu16"\n", data); + s->cropped_height = data; + break; + case 101: + av_log(s->avctx, AV_LOG_DEBUG, "Bits per component: %"PRIu16"\n", data); + s->bpc = data; + break; + case PrescaleShift: + s->prescale_shift[0] = (data >> 0) & 0x7; + s->prescale_shift[1] = (data >> 3) & 0x7; + s->prescale_shift[2] = (data >> 6) & 0x7; + av_log(s->avctx, AV_LOG_DEBUG, "Prescale shift (VC-5): %"PRIX16"\n", data); + break; + default: + av_log(s->avctx, AV_LOG_DEBUG, "Unknown tag %"PRIu16" data %"PRIX16"\n", + tag, data); + } + + return 0; +} + +static int read_lowpass_coeffs(CFHDContext *s, GetByteContext *gb, + int16_t *coeff_data) +{ + int i, j; + int lowpass_height = s->plane[s->channel_num].band[0][0].height; + int lowpass_width = s->plane[s->channel_num].band[0][0].width; + int lowpass_a_height = s->plane[s->channel_num].band[0][0].a_height; + int lowpass_a_width = s->plane[s->channel_num].band[0][0].a_width; + + if (lowpass_height > lowpass_a_height || + lowpass_width > lowpass_a_width || + lowpass_a_width * lowpass_a_height * sizeof(*coeff_data) > bytestream2_get_bytes_left(gb)) { + av_log(s->avctx, AV_LOG_ERROR, "Too many lowpass coefficients\n"); + return AVERROR_INVALIDDATA; + } + + av_log(s->avctx, AV_LOG_DEBUG, + "Start of lowpass coeffs component %d height:%d, width:%d\n", + s->channel_num, lowpass_height, lowpass_width); + for (i = 0; i < lowpass_height; i++) { + for (j = 0; j < lowpass_width; j++) + coeff_data[j] = bytestream2_get_be16u(gb); + + coeff_data += lowpass_width; + } + + /* Align to mod-4 position to continue reading tags */ + bytestream2_seek(gb, bytestream2_tell(gb) & 3, SEEK_CUR); + + /* Copy last coefficient line if height is odd. */ + if (lowpass_height & 1) { + int16_t *last_line = &coeff_data[lowpass_height * lowpass_width]; + memcpy(last_line, &last_line[-lowpass_width], + lowpass_width * sizeof(*coeff_data)); + } + + av_log(s->avctx, AV_LOG_DEBUG, "Lowpass coefficients %i\n", + lowpass_width * lowpass_height); + + return 0; +} + +#define DECODE_SUBBAND_COEFFS(TABLE, COND) \ + while (1) { \ + int level, run, coeff; \ + BITSTREAM_RL_VLC(level, run, &s->bc, s->TABLE, VLC_BITS, 3); \ + \ + /* escape */ \ + if (COND) \ + break; \ + \ + count += run; \ + \ + if (count > expected) { \ + av_log(s->avctx, AV_LOG_ERROR, "Escape codeword not found, " \ + "probably corrupt data\n"); \ + return AVERROR_INVALIDDATA; \ + } \ + \ + coeff = dequant_and_decompand(level, s->quantisation); \ + for (i = 0; i < run; i++) \ + *coeff_data++ = coeff; \ + } \ + +static int read_highpass_coeffs(CFHDContext *s, GetByteContext *gb, + int16_t *coeff_data) +{ + int i, ret; + int highpass_height = s->plane[s->channel_num].band[s->level][s->subband_num].height; + int highpass_width = s->plane[s->channel_num].band[s->level][s->subband_num].width; + int highpass_a_width = s->plane[s->channel_num].band[s->level][s->subband_num].a_width; + int highpass_a_height = s->plane[s->channel_num].band[s->level][s->subband_num].a_height; + ptrdiff_t highpass_stride = s->plane[s->channel_num].band[s->level][s->subband_num].stride; + int expected = highpass_height * highpass_stride; + int a_expected = highpass_a_height * highpass_a_width; + int count = 0; + unsigned bytes; + + if (highpass_height > highpass_a_height || + highpass_width > highpass_a_width || + a_expected < expected) { + av_log(s->avctx, AV_LOG_ERROR, "Too many highpass coefficients\n"); + return AVERROR_INVALIDDATA; + } + + av_log(s->avctx, AV_LOG_DEBUG, + "Start subband coeffs plane %i level %i codebook %i expected %i\n", + s->channel_num, s->level, s->codebook, expected); + + if ((ret = bitstream_init8(&s->bc, gb->buffer, + bytestream2_get_bytes_left(gb))) < 0) + return ret; + if (!s->codebook) { + DECODE_SUBBAND_COEFFS(table_9_rl_vlc, level == 64) + } else { + DECODE_SUBBAND_COEFFS(table_18_rl_vlc, level == 255 && run == 2) + } + + bytes = FFALIGN(AV_CEIL_RSHIFT(bitstream_tell(&s->bc), 3), 4); + if (bytes > bytestream2_get_bytes_left(gb)) { + av_log(s->avctx, AV_LOG_ERROR, "Bitstream overread error\n"); + return AVERROR_INVALIDDATA; + } else + bytestream2_seek(gb, bytes, SEEK_CUR); + + av_log(s->avctx, AV_LOG_DEBUG, "End subband coeffs %i extra %i\n", + count, count - expected); + s->codebook = 0; + + /* Copy last coefficient line if height is odd. */ + if (highpass_height & 1) { + int16_t *last_line = &coeff_data[expected]; + memcpy(last_line, &last_line[-highpass_stride], + highpass_stride * sizeof(*coeff_data)); + } + + return 0; +} + +static int reconstruct_level(CFHDContext *s, AVFrame *pic, int plane, int level) +{ + int i, j, idx = level - 1, idx2 = level > 1 ? 1 : 0; + int16_t *low, *high, *output, *dst; + int lowpass_height = s->plane[plane].band[idx][idx2].height; + int lowpass_width = s->plane[plane].band[idx][idx2].width; + ptrdiff_t highpass_stride = s->plane[plane].band[idx][1].stride; + + if (lowpass_height > s->plane[plane].band[idx][idx2].a_height || + lowpass_width > s->plane[plane].band[idx][idx2].a_width || + s->plane[plane].band[idx][1].width > s->plane[plane].band[idx][1].a_width || + !highpass_stride) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid plane dimensions\n"); + return AVERROR_INVALIDDATA; + } + + av_log(s->avctx, AV_LOG_DEBUG, "Level %d plane %i %i %i %ti\n", + level, plane, lowpass_height, lowpass_width, highpass_stride); + + low = s->plane[plane].subband[0]; + high = s->plane[plane].subband[2 + 3 * idx]; + output = s->plane[plane].l_h[3 * idx]; + for (i = 0; i < lowpass_width; i++) { + vert_filter(output, lowpass_width, low, lowpass_width, high, + highpass_stride, lowpass_height); + low++; + high++; + output++; + } + + low = s->plane[plane].subband[1 + 3 * idx]; + high = s->plane[plane].subband[3 + 3 * idx]; + output = s->plane[plane].l_h[1 + 3 * idx]; + for (i = 0; i < lowpass_width; i++) { + // note the stride of "low" is highpass_stride + vert_filter(output, lowpass_width, low, highpass_stride, high, + highpass_stride, lowpass_height); + low++; + high++; + output++; + } + + low = s->plane[plane].l_h[0 + 3 * idx]; + high = s->plane[plane].l_h[1 + 3 * idx]; + + if (level != 3) { + output = s->plane[plane].subband[0]; + for (i = 0; i < lowpass_height * 2; i++) { + horiz_filter(output, low, high, lowpass_width); + low += lowpass_width; + high += lowpass_width; + output += lowpass_width * 2; + } + if (s->bpc == 12 || level == 2) { + output = s->plane[plane].subband[0]; + for (i = 0; i < lowpass_height * 2; i++) { + for (j = 0; j < lowpass_width * 2; j++) + output[j] <<= 2; + + output += lowpass_width * 2; + } + } + } else { + int act_plane = plane == 1 ? 2 : plane == 2 ? 1 : plane; + dst = (int16_t *)pic->data[act_plane]; + for (i = 0; i < lowpass_height * 2; i++) { + horiz_filter_clip(dst, low, high, lowpass_width, s->bpc); + low += lowpass_width; + high += lowpass_width; + dst += pic->linesize[act_plane] / 2; + } + } + + return 0; +} + +static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + CFHDContext *s = avctx->priv_data; + GetByteContext gb; + ThreadFrame frame = { .f = data }; + int ret = 0, planes, plane; + int16_t tag; + uint16_t value; + + init_frame_defaults(s); + planes = av_pix_fmt_count_planes(s->coded_format); + + bytestream2_init(&gb, avpkt->data, avpkt->size); + + while (bytestream2_get_bytes_left(&gb) > 4) { + if ((ret = parse_tag(s, &gb, &tag, &value, &planes)) < 0) + return ret; + + /* Some kind of end of header tag */ + if (tag == 4 && value == 0x1A4A) + break; + } + + if (s->coded_width <= 0 || s->coded_height <= 0 || s->coded_format == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Video dimensions/format missing or invalid\n"); + return AVERROR_INVALIDDATA; + } + + ret = ff_set_dimensions(s->avctx, s->coded_width, s->coded_height); + if (ret < 0) + return ret; + if (s->cropped_height) + s->avctx->height = s->cropped_height; + + s->avctx->pix_fmt = s->coded_format; + + if (s->a_width != s->coded_width || s->a_height != s->coded_height || + s->a_format != s->coded_format) { + free_buffers(s); + if ((ret = alloc_buffers(s)) < 0) { + free_buffers(s); + return ret; + } + } + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + s->coded_width = 0; + s->coded_height = 0; + s->coded_format = AV_PIX_FMT_NONE; + + while (bytestream2_get_bytes_left(&gb) > 4) { + int16_t *coeff_data; + + if ((ret = parse_tag(s, &gb, &tag, &value, &planes)) < 0) + return ret; + + coeff_data = s->plane[s->channel_num].subband[s->subband_num_actual]; + if (tag == 4 && value == 0x0F0F) { + if ((ret = read_lowpass_coeffs(s, &gb, coeff_data)) < 0) + return ret; + } else if (tag == 55 && s->subband_num_actual != 255) { + if ((ret = read_highpass_coeffs(s, &gb, coeff_data)) < 0) + return ret; + } + } + + if (s->coded_width || s->coded_height || s->coded_format != AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Invalid dimensions\n"); + return AVERROR_INVALIDDATA; + } + + planes = av_pix_fmt_count_planes(avctx->pix_fmt); + for (plane = 0; plane < planes; plane++) { + /* level 1 */ + if ((ret = reconstruct_level(s, data, plane, 1)) < 0) + return ret; + + /* level 2 */ + if ((ret = reconstruct_level(s, data, plane, 2)) < 0) + return ret; + + /* level 3 */ + if ((ret = reconstruct_level(s, data, plane, 3)) < 0) + return ret; + } + + *got_frame = 1; + return avpkt->size; +} + +static av_cold int cfhd_close(AVCodecContext *avctx) +{ + CFHDContext *s = avctx->priv_data; + + free_buffers(s); + + ff_free_vlc(&s->vlc_9); + ff_free_vlc(&s->vlc_18); + + return 0; +} + +AVCodec ff_cfhd_decoder = { + .name = "cfhd", + .long_name = NULL_IF_CONFIG_SMALL("Cineform HD"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CFHD, + .priv_data_size = sizeof(CFHDContext), + .init = cfhd_init, + .init_thread_copy = ONLY_IF_THREADS_ENABLED(cfhd_init), + .close = cfhd_close, + .decode = cfhd_decode, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/cfhd.h b/libavcodec/cfhd.h new file mode 100644 index 0000000000000..c5da0b6ec7ff3 --- /dev/null +++ b/libavcodec/cfhd.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015 Kieran Kunhya + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CFHD_H +#define AVCODEC_CFHD_H + +#include + +#include "avcodec.h" +#include "bitstream.h" + +#define VLC_BITS 9 +#define SUBBAND_COUNT 10 + +typedef struct CFHD_RL_VLC_ELEM { + int16_t level; + int8_t len; + uint16_t run; +} CFHD_RL_VLC_ELEM; + +#define DWT_LEVELS 3 + +typedef struct SubBand { + int level; + int orientation; + ptrdiff_t stride; + int a_width; + int width; + int a_height; + int height; + int pshift; + int quant; + uint8_t *ibuf; +} SubBand; + +typedef struct Plane { + int width; + int height; + ptrdiff_t stride; + + int16_t *idwt_buf; + int16_t *idwt_tmp; + + /* TODO: merge this into SubBand structure */ + int16_t *subband[SUBBAND_COUNT]; + int16_t *l_h[8]; + + SubBand band[DWT_LEVELS][4]; +} Plane; + +typedef struct CFHDContext { + AVCodecContext *avctx; + + CFHD_RL_VLC_ELEM table_9_rl_vlc[2088]; + VLC vlc_9; + + CFHD_RL_VLC_ELEM table_18_rl_vlc[4572]; + VLC vlc_18; + + BitstreamContext bc; + + int coded_width; + int coded_height; + int cropped_height; + enum AVPixelFormat coded_format; + + int a_width; + int a_height; + int a_format; + + int bpc; // bits per channel/component + int channel_cnt; + int subband_cnt; + int channel_num; + uint8_t lowpass_precision; + uint16_t quantisation; + int wavelet_depth; + int pshift; + + int codebook; + int subband_num; + int level; + int subband_num_actual; + + uint8_t prescale_shift[3]; + Plane plane[4]; +} CFHDContext; + +int ff_cfhd_init_vlcs(CFHDContext *s); + +#endif /* AVCODEC_CFHD_H */ diff --git a/libavcodec/cfhddata.c b/libavcodec/cfhddata.c new file mode 100644 index 0000000000000..3a9d6bdfb9b07 --- /dev/null +++ b/libavcodec/cfhddata.c @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2015 Kieran Kunhya + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" + +#include "cfhd.h" + +#define NB_VLC_TABLE_9 (71 + 3) +#define NB_VLC_TABLE_18 (263 + 1) + +static const uint32_t table_9_vlc_bits[NB_VLC_TABLE_9] = { + 0, 0x2, 0xc, 0x1a, + 0x1d, 0x1e, 0x39, 0x3e, + 0x37, 0x7e, 0x6c, 0xe2, + 0xfe, 0xdb, 0xe0, 0x1c3, + 0x1c6, 0x1ff, 0x1fe, 0x1b5, + 0x369, 0x385, 0x71d, 0x6d0, + 0x708, 0x71f, 0xe3d, 0xe39, + 0xe13, 0xe12, 0x1c71, 0x1b45, + 0x1b47, 0x3689, 0x38f2, 0x38e1, + 0x38e0, 0x38f1, 0x3688, 0x6d1b, + 0x71e0, 0x6d19, 0x71e7, 0xe3cd, + 0xda35, 0xda30, 0xe3c3, 0x1b469, + 0x1b462, 0x1c798, 0x1b463, 0x1c799, + 0x38f08, 0x38f09, 0x38f0a, 0x6d1a0, + 0x6d1a3, 0x6d1a1, 0xda345, 0xda344, + 0xe3c2d, 0xe3c2f, 0xe3c2e, 0x38f0b2, + 0x71e160, 0x71e162, 0x71e166, 0x71e161, + 0xe3c2ce, 0xe3c2c6, 0xe3c2c7, 0x1C7859E, + 0x38F0B3F, 0x38F0B3E, +}; + +static const uint8_t table_9_vlc_len[NB_VLC_TABLE_9] = { + 1, 2, 4, 5, 5, 5, 6, 6, + 6, 7, 7, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 10, 10, 11, 11, + 11, 11, 12, 12, 12, 12, 13, 13, + 13, 14, 14, 14, 14, 14, 14, 15, + 15, 15, 15, 16, 16, 16, 16, 17, + 17, 17, 17, 17, 18, 18, 18, 19, + 19, 19, 20, 20, 20, 20, 20, 22, + 23, 23, 23, 23, 24, 24, 24, 25, + 26, 26, +}; + +static const uint16_t table_9_vlc_run[NB_VLC_TABLE_9] = { + 1, 1, 1, 1, 12, 1, 32, 160, + 1, 1, 1, 320, 1, 1, 80, 120, + 1, 1, 100, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1 +}; + +static const uint8_t table_9_vlc_level[NB_VLC_TABLE_9] = { + 0, 1, 2, 3, 0, 4, 0, 0, + 5, 7, 6, 0, 9, 8, 0, 0, + 11, 12, 0, 10, 13, 14, 17, 15, + 16, 18, 22, 21, 20, 19, 25, 23, + 24, 27, 31, 29, 28, 30, 26, 33, + 34, 32, 35, 39, 37, 36, 38, 42, + 40, 43, 41, 44, 45, 46, 47, 48, + 50, 49, 52, 51, 53, 55, 54, 56, + 57, 59, 60, 58, 61, 62, 63, 64, + 64, 64, +}; + +static const uint32_t table_18_vlc_bits[NB_VLC_TABLE_18] = { + 0, 0x2, 0x7, 0x19, + 0x30, 0x36, 0x6f, 0x63, + 0x69, 0x6b, 0xd1, 0xd4, + 0xdc, 0x189, 0x18a, 0x1a0, + 0x1ab, 0x377, 0x310, 0x316, + 0x343, 0x354, 0x375, 0x623, + 0x684, 0x685, 0x6ab, 0x6ec, + 0xddb, 0xc5c, 0xc5e, 0xc44, + 0xd55, 0xdd1, 0xdd3, 0x1bb5, + 0x188b, 0x18bb, 0x18bf, 0x1aa8, + 0x1ba0, 0x1ba5, 0x1ba4, 0x3115, + 0x3175, 0x317d, 0x3553, 0x3768, + 0x6e87, 0x6ed3, 0x62e8, 0x62f8, + 0x6228, 0x6aa4, 0x6e85, 0xc453, + 0xc5d3, 0xc5f3, 0xdda4, 0xdd08, + 0xdd0c, 0x1bb4b, 0x1bb4a, 0x18ba5, + 0x18be5, 0x1aa95, 0x1aa97, 0x188a4, + 0x1ba13, 0x31748, 0x317c8, 0x35528, + 0x3552c, 0x37424, 0x37434, 0x37436, + 0x62294, 0x62e92, 0x62f92, 0x6aa52, + 0x6aa5a, 0x6e86a, 0x6e86e, 0x6e84a, + 0xc452a, 0xc5d27, 0xc5f26, 0xd54a6, + 0xd54b6, 0xdd096, 0xdd0d6, 0xdd0de, + 0x188a56, 0x18ba4d, 0x18be4e, 0x18be4f, + 0x1aa96e, 0x1ba12e, 0x1ba12f, 0x1ba1af, + 0x1ba1bf, 0x37435d, 0x37437d, 0x317498, + 0x35529c, 0x35529d, 0x3552de, 0x3552df, + 0x62e933, 0x62295d, 0x6aa53d, 0x6aa53f, + 0x6aa53e, 0x6e86b9, 0x6e86f8, 0xd54a79, + 0xc5d265, 0xc452b8, 0xdd0d71, 0xd54a78, + 0xdd0d70, 0xdd0df2, 0xdd0df3, 0x188a5f6, + 0x188a5f5, 0x188a5f4, 0x188a5f3, 0x188a5f2, + 0x188a5f1, 0x188a5f0, 0x188a5ef, 0x188a5ee, + 0x188a5ed, 0x188a5aa, 0x188a5e3, 0x188a5df, + 0x188a589, 0x188a5dd, 0x188a578, 0x188a5e0, + 0x188a588, 0x188a5d6, 0x188a5db, 0x188a5e1, + 0x188a587, 0x188a59a, 0x188a5c4, 0x188a5ec, + 0x188a586, 0x188a573, 0x188a59c, 0x188a5c8, + 0x188a5fb, 0x188a5a1, 0x188a5eb, 0x188a5a8, + 0x188a584, 0x188a5d2, 0x188a599, 0x188a598, + 0x188a583, 0x18ba4c9, 0x188a5d0, 0x188a594, + 0x188a582, 0x188a5cb, 0x188a5d8, 0x188a5e7, + 0x188a581, 0x188a5ea, 0x188a5a9, 0x188a5a6, + 0x188a580, 0x188a5a0, 0x188a59d, 0x188a5c3, + 0x188a57f, 0x188a5c0, 0x188a5de, 0x188a5d4, + 0x188a57e, 0x188a5c2, 0x188a592, 0x188a5cd, + 0x188a57d, 0x188a5a3, 0x188a5e8, 0x188a5a2, + 0x188a57c, 0x188a58e, 0x188a5b3, 0x188a5b2, + 0x188a5b1, 0x188a5b0, 0x188a5af, 0x188a5ae, + 0x188a5ad, 0x188a5ac, 0x188a5ab, 0x188a5da, + 0x188a5e4, 0x188a5e5, 0x188a5d9, 0x188a5b5, + 0x188a5bc, 0x188a5bd, 0x188a5e9, 0x188a5cc, + 0x188a585, 0x188a5d3, 0x188a5e2, 0x188a595, + 0x188a596, 0x188a5b8, 0x188a590, 0x188a5c9, + 0x188a5a4, 0x188a5e6, 0x188a5a5, 0x188a5ce, + 0x188a5bf, 0x188a572, 0x188a59b, 0x188a5be, + 0x188a5c7, 0x188a5ca, 0x188a5d5, 0x188a57b, + 0x188a58d, 0x188a58c, 0x188a58b, 0x188a58a, + 0x18ba4c8, 0x188a5c5, 0x188a5fa, 0x188a5bb, + 0x188a5c1, 0x188a5cf, 0x188a5b9, 0x188a5b6, + 0x188a597, 0x188a5fe, 0x188a5d7, 0x188a5ba, + 0x188a591, 0x188a5c6, 0x188a5dc, 0x188a57a, + 0x188a59f, 0x188a5f9, 0x188a5b4, 0x188a5a7, + 0x188a58f, 0x188a5fd, 0x188a5b7, 0x188a593, + 0x188a59e, 0x188a5f8, 0x188a5ff, 0x188a5fc, + 0x188a579, 0x188a5f7, 0x3114ba2, 0x3114ba3, +}; + +static const uint8_t table_18_vlc_len[NB_VLC_TABLE_18] = { + 1, 2, 3, 5, 6, 6, 7, 7, + 7, 7, 8, 8, 8, 9, 9, 9, + 9, 10, 10, 10, 10, 10, 10, 11, + 11, 11, 11, 11, 12, 12, 12, 12, + 12, 12, 12, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 16, + 16, 16, 16, 16, 16, 17, 17, 17, + 17, 17, 17, 17, 17, 18, 18, 18, + 18, 18, 18, 18, 19, 19, 19, 19, + 19, 19, 19, 19, 20, 20, 20, 20, + 20, 20, 20, 20, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 22, 22, 22, + 22, 22, 22, 22, 23, 23, 23, 23, + 23, 23, 23, 24, 24, 24, 24, 24, + 24, 24, 24, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 26, 26, +}; + +static const uint16_t table_18_vlc_run[NB_VLC_TABLE_18] = { + 1, 1, 1, 1, 1, 1, 1, 1, + 12, 1, 20, 1, 1, 1, 32, 1, + 1, 1, 1, 1, 60, 1, 1, 1, + 1, 100, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 180, 1, + 1, 320, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, +}; + +static const uint8_t table_18_vlc_level[NB_VLC_TABLE_18] = { + 0, 1, 2, 3, 4, 5, 8, 6, + 0, 7, 0, 9, 10, 11, 0, 12, + 13, 18, 14, 15, 0, 16, 17, 19, + 20, 0, 21, 22, 29, 24, 25, 23, + 26, 27, 28, 35, 30, 31, 0, 32, + 33, 0, 34, 36, 37, 38, 39, 40, + 46, 47, 42, 43, 41, 44, 45, 48, + 49, 50, 53, 51, 52, 61, 60, 55, + 56, 57, 58, 54, 59, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, + 73, 75, 76, 74, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 99, 100, 94, + 95, 96, 97, 98, 102, 101, 103, 105, + 104, 106, 107, 111, 109, 108, 113, 110, + 112, 114, 115, 225, 189, 188, 203, 202, + 197, 207, 169, 223, 159, 235, 152, 192, + 179, 201, 172, 149, 178, 120, 219, 150, + 127, 211, 125, 158, 247, 238, 163, 228, + 183, 217, 168, 122, 128, 249, 187, 186, + 136, 181, 255, 230, 135, 233, 222, 145, + 134, 167, 248, 209, 243, 216, 164, 140, + 157, 239, 191, 251, 156, 139, 242, 133, + 162, 213, 165, 212, 227, 198, 236, 234, + 117, 215, 124, 123, 254, 253, 148, 218, + 146, 147, 224, 143, 184, 185, 166, 132, + 129, 250, 151, 119, 193, 176, 245, 229, + 206, 144, 208, 137, 241, 237, 190, 240, + 131, 232, 252, 171, 205, 204, 118, 214, + 180, 126, 182, 175, 141, 138, 177, 153, + 194, 160, 121, 174, 246, 130, 200, 170, + 221, 196, 142, 210, 199, 155, 154, 244, + 220, 195, 161, 231, 173, 226, 116, 255, +}; + +static int init_vlc_signed(VLC *vlc, CFHD_RL_VLC_ELEM table_rl_vlc[], + unsigned bound, + const uint32_t table_vlc_bits[], + const uint8_t table_vlc_len[], + const uint16_t table_vlc_run[], + const uint8_t table_vlc_level[]) +{ + uint32_t vlc_bits[NB_VLC_TABLE_18 * 2]; + uint8_t vlc_len[NB_VLC_TABLE_18 * 2]; + uint16_t vlc_run[NB_VLC_TABLE_18 * 2]; + int16_t vlc_level[NB_VLC_TABLE_18 * 2]; + unsigned i, j; + int ret; + + for (i = 0, j = 0; i < bound; i++, j++) { + vlc_bits[j] = table_vlc_bits[i]; + vlc_len[j] = table_vlc_len[i]; + vlc_run[j] = table_vlc_run[i]; + vlc_level[j] = table_vlc_level[i]; + + /* Don't include the zero level nor escape bits */ + if (table_vlc_level[i] && + vlc_bits[j] != table_vlc_bits[bound - 1]) { + vlc_bits[j] <<= 1; + vlc_len[j]++; + j++; + vlc_bits[j] = (table_vlc_bits[i] << 1) | 1; + vlc_len[j] = table_vlc_len[i] + 1; + vlc_run[j] = table_vlc_run[i]; + vlc_level[j] = -table_vlc_level[i]; + } + } + + if ((ret = init_vlc(vlc, VLC_BITS, j, vlc_len, 1, 1, vlc_bits, 4, 4, 0)) < 0) + return ret; + + for (i = 0; i < (*vlc).table_size; i++) { + int code = (*vlc).table[i][0]; + int len = (*vlc).table[i][1]; + int level, run; + + if (len < 0) { // more bits needed + run = 0; + level = code; + } else { + run = vlc_run[code]; + level = vlc_level[code]; + } + table_rl_vlc[i].len = len; + table_rl_vlc[i].level = level; + table_rl_vlc[i].run = run; + } + + return 0; +} + +av_cold int ff_cfhd_init_vlcs(CFHDContext *s) +{ + /** Similar to dv.c, generate signed VLC tables **/ + + int ret = init_vlc_signed(&s->vlc_9, s->table_9_rl_vlc, NB_VLC_TABLE_9, + table_9_vlc_bits, table_9_vlc_len, + table_9_vlc_run, table_9_vlc_level); + if (ret < 0) + return ret; + + return init_vlc_signed(&s->vlc_18, s->table_18_rl_vlc, NB_VLC_TABLE_18, + table_18_vlc_bits, table_18_vlc_len, + table_18_vlc_run, table_18_vlc_level); +} diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index ab2018b41bb69..dd243c2f0cd57 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1428,6 +1428,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_CFHD, + .type = AVMEDIA_TYPE_VIDEO, + .name = "cfhd", + .long_name = NULL_IF_CONFIG_SMALL("Cineform HD"), + .props = AV_CODEC_PROP_LOSSY, + }, /* various PCM "codecs" */ { diff --git a/libavcodec/version.h b/libavcodec/version.h index 5c25b3e4ec175..443cc8204aa50 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 57 -#define LIBAVCODEC_VERSION_MINOR 35 +#define LIBAVCODEC_VERSION_MINOR 36 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/riff.c b/libavformat/riff.c index 54bef835ba41c..6de400720262c 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -368,6 +368,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_RSCC, MKTAG('I', 'S', 'C', 'C') }, { AV_CODEC_ID_MAGICYUV, MKTAG('M', 'A', 'G', 'Y') }, { AV_CODEC_ID_AV1, MKTAG('A', 'V', '0', '1') }, + { AV_CODEC_ID_CFHD, MKTAG('C', 'F', 'H', 'D') }, { AV_CODEC_ID_NONE, 0 } }; From b57a95d0147beae746db1c1223d100447f42dced Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 29 Feb 2016 15:39:27 +0100 Subject: [PATCH 0033/2557] cfhd: Add FATE tests --- tests/fate/video.mak | 12 ++++++++++++ tests/ref/fate/cfhd-1 | 11 +++++++++++ tests/ref/fate/cfhd-2 | 11 +++++++++++ tests/ref/fate/cfhd-3 | 11 +++++++++++ 4 files changed, 45 insertions(+) create mode 100644 tests/ref/fate/cfhd-1 create mode 100644 tests/ref/fate/cfhd-2 create mode 100644 tests/ref/fate/cfhd-3 diff --git a/tests/fate/video.mak b/tests/fate/video.mak index 01108f8d9d523..379eb2b0b3f0f 100644 --- a/tests/fate/video.mak +++ b/tests/fate/video.mak @@ -61,6 +61,18 @@ fate-cavs: CMD = framecrc -i $(TARGET_SAMPLES)/cavs/cavs.mpg -an FATE_SAMPLES_AVCONV-$(call DEMDEC, CDG, CDGRAPHICS) += fate-cdgraphics fate-cdgraphics: CMD = framecrc -i $(TARGET_SAMPLES)/cdgraphics/BrotherJohn.cdg -pix_fmt rgb24 -t 1 +FATE_CFHD-$(CONFIG_AVI_DEMUXER) += fate-cfhd-1 +fate-cfhd-1: CMD = framecrc -i $(TARGET_SAMPLES)/cfhd/cfhd_422.avi -pix_fmt yuv422p10le + +FATE_CFHD-$(CONFIG_AVI_DEMUXER) += fate-cfhd-2 +fate-cfhd-2: CMD = framecrc -i $(TARGET_SAMPLES)/cfhd/cfhd_444.avi -pix_fmt yuv422p10le + +FATE_CFHD-$(CONFIG_MOV_DEMUXER) += fate-cfhd-3 +fate-cfhd-3: CMD = framecrc -i $(TARGET_SAMPLES)/cfhd/cfhd_odd.mov -pix_fmt yuv422p10le + +FATE_SAMPLES_AVCONV-$(CONFIG_CFHD_DECODER) += $(FATE_CFHD-yes) +fate-cfhd: $(FATE_CFHD-yes) + FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, CLJR) += fate-cljr fate-cljr: CMD = framecrc -i $(TARGET_SAMPLES)/cljr/testcljr-partial.avi diff --git a/tests/ref/fate/cfhd-1 b/tests/ref/fate/cfhd-1 new file mode 100644 index 0000000000000..cccfc8b8602c5 --- /dev/null +++ b/tests/ref/fate/cfhd-1 @@ -0,0 +1,11 @@ +#tb 0: 1001/30000 +0, 0, 0, 1, 1382400, 0xa3e49817 +0, 1, 1, 1, 1382400, 0x544fdfac +0, 2, 2, 1, 1382400, 0x84964e11 +0, 3, 3, 1, 1382400, 0xc608c8d1 +0, 4, 4, 1, 1382400, 0xf2f1404f +0, 5, 5, 1, 1382400, 0x5a3100ba +0, 6, 6, 1, 1382400, 0x3727baa9 +0, 7, 7, 1, 1382400, 0x894f07db +0, 8, 8, 1, 1382400, 0x3ef27d46 +0, 9, 9, 1, 1382400, 0x1f90880d diff --git a/tests/ref/fate/cfhd-2 b/tests/ref/fate/cfhd-2 new file mode 100644 index 0000000000000..1af92d0668b1e --- /dev/null +++ b/tests/ref/fate/cfhd-2 @@ -0,0 +1,11 @@ +#tb 0: 1001/30000 +0, 0, 0, 1, 1382400, 0xe1c2201d +0, 1, 1, 1, 1382400, 0x13e5bc81 +0, 2, 2, 1, 1382400, 0x3062ca82 +0, 3, 3, 1, 1382400, 0x1c71624f +0, 4, 4, 1, 1382400, 0xf286c080 +0, 5, 5, 1, 1382400, 0xd517d824 +0, 6, 6, 1, 1382400, 0xe571ffd5 +0, 7, 7, 1, 1382400, 0x94a523ff +0, 8, 8, 1, 1382400, 0x85c58fca +0, 9, 9, 1, 1382400, 0x6b3278b0 diff --git a/tests/ref/fate/cfhd-3 b/tests/ref/fate/cfhd-3 new file mode 100644 index 0000000000000..61698482fd43a --- /dev/null +++ b/tests/ref/fate/cfhd-3 @@ -0,0 +1,11 @@ +#tb 0: 1/14587 +0, 0, 0, 0, 478144, 0x6ed01dcd +0, 1000, 1000, 0, 478144, 0x6ed01dcd +0, 2000, 2000, 0, 478144, 0x6ed01dcd +0, 3000, 3000, 0, 478144, 0xb1b4a74b +0, 4000, 4000, 0, 478144, 0x94c345c3 +0, 5000, 5000, 0, 478144, 0x05e0388d +0, 6000, 6000, 0, 478144, 0xe747476a +0, 7000, 7000, 0, 478144, 0x8c1561f1 +0, 8000, 8000, 0, 478144, 0x8c1561f1 +0, 9000, 9000, 0, 478144, 0x8c1561f1 From 98ee855ae0cc118bd1d20921d6bdb14731832462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sun, 26 Feb 2017 14:02:35 +0200 Subject: [PATCH 0034/2557] arm: vp9itxfm: Template the quarter/half idct32 function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reduces the number of lines and reduces the duplication. Also simplify the eob check for the half case. If we are in the half case, we know we at least will need to do the first three slices, we only need to check eob for the fourth one, so we can hardcode the value to check against instead of loading from the min_eob array. Since at most one slice can be skipped in the first pass, we can unroll the loop for filling zeros completely, as it was done for the quarter case before. This allows skipping loading the min_eob pointer when using the quarter/half cases. Signed-off-by: Martin Storsjö --- libavcodec/arm/vp9itxfm_neon.S | 57 ++++++++++++---------------------- 1 file changed, 20 insertions(+), 37 deletions(-) diff --git a/libavcodec/arm/vp9itxfm_neon.S b/libavcodec/arm/vp9itxfm_neon.S index a612b25f4f65c..49c4e171ce51f 100644 --- a/libavcodec/arm/vp9itxfm_neon.S +++ b/libavcodec/arm/vp9itxfm_neon.S @@ -1575,7 +1575,6 @@ function ff_vp9_idct_idct_32x32_add_neon, export=1 beq idct32x32_dc_add_neon push {r4-r8,lr} vpush {q4-q6} - movrel r8, min_eob_idct_idct_32 + 2 @ Align the stack, allocate a temp buffer T mov r7, sp @@ -1597,6 +1596,8 @@ A and r7, sp, #15 cmp r3, #135 ble idct32x32_half_add_neon + movrel r8, min_eob_idct_idct_32 + 2 + .irp i, 0, 4, 8, 12, 16, 20, 24, 28 add r0, sp, #(\i*64) .if \i > 0 @@ -1634,72 +1635,54 @@ A and r7, sp, #15 pop {r4-r8,pc} endfunc -function idct32x32_quarter_add_neon +.macro idct32_partial size +function idct32x32_\size\()_add_neon .irp i, 0, 4 add r0, sp, #(\i*64) +.ifc \size,quarter .if \i == 4 cmp r3, #9 ble 1f +.endif .endif add r2, r6, #(\i*2) - bl idct32_1d_4x32_pass1_quarter_neon -.endr - b 3f - -1: - @ Write zeros to the temp buffer for pass 2 - vmov.i16 q14, #0 - vmov.i16 q15, #0 -.rept 8 - vst1.16 {q14-q15}, [r0,:128]! -.endr -3: -.irp i, 0, 4, 8, 12, 16, 20, 24, 28 - add r0, r4, #(\i) - mov r1, r5 - add r2, sp, #(\i*2) - bl idct32_1d_4x32_pass2_quarter_neon + bl idct32_1d_4x32_pass1_\size\()_neon .endr - add sp, sp, r7 - vpop {q4-q6} - pop {r4-r8,pc} -endfunc - -function idct32x32_half_add_neon -.irp i, 0, 4, 8, 12 +.ifc \size,half +.irp i, 8, 12 add r0, sp, #(\i*64) -.if \i > 0 - ldrh_post r1, r8, #2 - cmp r3, r1 - it le - movle r1, #(16 - \i)/2 +.if \i == 12 + cmp r3, #70 ble 1f .endif add r2, r6, #(\i*2) - bl idct32_1d_4x32_pass1_half_neon + bl idct32_1d_4x32_pass1_\size\()_neon .endr +.endif b 3f 1: @ Write zeros to the temp buffer for pass 2 vmov.i16 q14, #0 vmov.i16 q15, #0 -2: - subs r1, r1, #1 -.rept 4 +.rept 8 vst1.16 {q14-q15}, [r0,:128]! .endr - bne 2b + 3: .irp i, 0, 4, 8, 12, 16, 20, 24, 28 add r0, r4, #(\i) mov r1, r5 add r2, sp, #(\i*2) - bl idct32_1d_4x32_pass2_half_neon + bl idct32_1d_4x32_pass2_\size\()_neon .endr add sp, sp, r7 vpop {q4-q6} pop {r4-r8,pc} endfunc +.endm + +idct32_partial quarter +idct32_partial half From 3a0d5e206d24d41d87a25ba16a79b2ea04c39d4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sun, 26 Feb 2017 22:13:10 +0200 Subject: [PATCH 0035/2557] arm/aarch64: vp9itxfm: Skip loading the min_eob pointer when it won't be used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the half/quarter cases where we don't use the min_eob array, defer loading the pointer until we know it will be needed. Signed-off-by: Martin Storsjö --- libavcodec/aarch64/vp9itxfm_neon.S | 3 ++- libavcodec/arm/vp9itxfm_neon.S | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libavcodec/aarch64/vp9itxfm_neon.S b/libavcodec/aarch64/vp9itxfm_neon.S index 93dc736f01fed..539899dae0165 100644 --- a/libavcodec/aarch64/vp9itxfm_neon.S +++ b/libavcodec/aarch64/vp9itxfm_neon.S @@ -1483,7 +1483,6 @@ function ff_vp9_idct_idct_32x32_add_neon, export=1 b.eq idct32x32_dc_add_neon movrel x10, idct_coeffs - movrel x12, min_eob_idct_idct_32, 2 mov x15, x30 @@ -1508,6 +1507,8 @@ function ff_vp9_idct_idct_32x32_add_neon, export=1 cmp w3, #135 b.le idct32x32_half_add_neon + movrel x12, min_eob_idct_idct_32, 2 + .irp i, 0, 8, 16, 24 add x0, sp, #(\i*64) .if \i > 0 diff --git a/libavcodec/arm/vp9itxfm_neon.S b/libavcodec/arm/vp9itxfm_neon.S index 49c4e171ce51f..ab9433ff0fd95 100644 --- a/libavcodec/arm/vp9itxfm_neon.S +++ b/libavcodec/arm/vp9itxfm_neon.S @@ -889,8 +889,6 @@ function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1 push {r4-r8,lr} .ifnc \txfm1\()_\txfm2,idct_idct vpush {q4-q7} -.else - movrel r8, min_eob_idct_idct_16 + 2 .endif @ Align the stack, allocate a temp buffer @@ -914,6 +912,8 @@ A and r7, sp, #15 ble idct16x16_quarter_add_neon cmp r3, #38 ble idct16x16_half_add_neon + + movrel r8, min_eob_idct_idct_16 + 2 .endif .irp i, 0, 4, 8, 12 From b76f6a76c6312dc551d7c37c6ded36bea7973c74 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 28 Dec 2016 11:05:25 +0100 Subject: [PATCH 0036/2557] h264dec: initialize field_started to 0 on each decode call It might be incorrectly set to 1 if the previous call exited with an error. Bug-Id: 1019 CC: libav-stable@libav.org --- libavcodec/h264dec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 6d7aa7b53ca4f..2a532a7ef7404 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -523,6 +523,7 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size) if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS)) { h->current_slice = 0; + h->field_started = 0; if (!h->first_field) h->cur_pic_ptr = NULL; ff_h264_sei_uninit(&h->sei); From 83b2b34d06e74cc8775ba3d833f9782505e17539 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 28 Dec 2016 11:27:56 +0100 Subject: [PATCH 0037/2557] h2645_parse: use the bytestream2 API for packet splitting The code does some nontrivial jumping around in the buffer, so it is safer to use a checked API rather than do everything manually. Fixes a bug in nalff parsing, where the length field is currently not counted in the buffer size check, resulting in possible overreads with invalid files. CC: libav-stable@libav.org Bug-Id: 1002 Found-By: Kamil Frankowicz --- libavcodec/h2645_parse.c | 43 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c index 8492425e44896..b507b19ecb5f0 100644 --- a/libavcodec/h2645_parse.c +++ b/libavcodec/h2645_parse.c @@ -26,6 +26,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" +#include "bytestream.h" #include "h2645_parse.h" int ff_h2645_extract_rbsp(const uint8_t *src, int length, @@ -214,11 +215,14 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, void *logctx, int is_nalff, int nal_length_size, enum AVCodecID codec_id) { + GetByteContext bc; int consumed, ret = 0; - const uint8_t *next_avc = buf + (is_nalff ? 0 : length); + size_t next_avc = is_nalff ? 0 : length; + + bytestream2_init(&bc, buf, length); pkt->nb_nals = 0; - while (length >= 4) { + while (bytestream2_get_bytes_left(&bc) >= 4) { H2645NAL *nal; int extract_length = 0; int skip_trailing_zeros = 1; @@ -231,40 +235,37 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, * correctly and consumes only the first NAL unit. The additional NAL * units are handled here in the Annex B parsing code. */ - if (buf == next_avc) { + if (bytestream2_tell(&bc) == next_avc) { int i; for (i = 0; i < nal_length_size; i++) - extract_length = (extract_length << 8) | buf[i]; + extract_length = (extract_length << 8) | bytestream2_get_byte(&bc); - if (extract_length > length) { + if (extract_length > bytestream2_get_bytes_left(&bc)) { av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit size (%d > %d).\n", - extract_length, length); + extract_length, bytestream2_get_bytes_left(&bc)); return AVERROR_INVALIDDATA; } - buf += nal_length_size; - length -= nal_length_size; // keep track of the next AVC1 length field - next_avc = buf + extract_length; + next_avc = bytestream2_tell(&bc) + extract_length; } else { /* * expected to return immediately except for streams with mixed * NAL unit coding */ - int buf_index = find_next_start_code(buf, next_avc); + int buf_index = find_next_start_code(bc.buffer, buf + next_avc); - buf += buf_index; - length -= buf_index; + bytestream2_skip(&bc, buf_index); /* * break if an AVC1 length field is expected at the current buffer * position */ - if (buf == next_avc) + if (bytestream2_tell(&bc) == next_avc) continue; - if (length > 0) { - extract_length = length; + if (bytestream2_get_bytes_left(&bc) > 0) { + extract_length = bytestream2_get_bytes_left(&bc); } else if (pkt->nb_nals == 0) { av_log(logctx, AV_LOG_ERROR, "No NAL unit found\n"); return AVERROR_INVALIDDATA; @@ -286,14 +287,15 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, } nal = &pkt->nals[pkt->nb_nals++]; - consumed = ff_h2645_extract_rbsp(buf, extract_length, nal); + consumed = ff_h2645_extract_rbsp(bc.buffer, extract_length, nal); if (consumed < 0) return consumed; + bytestream2_skip(&bc, consumed); + /* see commit 3566042a0 */ - if (consumed < length - 3 && - buf[consumed] == 0x00 && buf[consumed + 1] == 0x00 && - buf[consumed + 2] == 0x01 && buf[consumed + 3] == 0xE0) + if (bytestream2_get_bytes_left(&bc) >= 4 && + bytestream2_peek_be32(&bc) == 0x000001E0) skip_trailing_zeros = 0; nal->size_bits = get_bit_length(nal, skip_trailing_zeros); @@ -313,9 +315,6 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, } pkt->nb_nals--; } - - buf += consumed; - length -= consumed; } return 0; From 522d850e68ec4b77d3477b3c8f55b1ba00a9d69a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 28 Dec 2016 13:02:02 +0100 Subject: [PATCH 0038/2557] h264_cavlc: check the value of run_before Section 9.2.3.2 of the spec implies that run_before must not be larger than zeros_left. Fixes invalid reads with corrupted files. CC: libav-stable@libav.org Bug-Id: 1000 Found-By: Kamil Frankowicz --- libavcodec/h264_cavlc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/h264_cavlc.c b/libavcodec/h264_cavlc.c index 9b950ede20a04..c11e211bd894b 100644 --- a/libavcodec/h264_cavlc.c +++ b/libavcodec/h264_cavlc.c @@ -579,8 +579,10 @@ static int decode_residual(const H264Context *h, H264SliceContext *sl, for(i=1;i 0;i++) { \ if(zeros_left < 7) \ run_before= get_vlc2(gb, run_vlc[zeros_left - 1].table, RUN_VLC_BITS, 1); \ - else \ + else {\ run_before= get_vlc2(gb, run7_vlc.table, RUN7_VLC_BITS, 2); \ + run_before = FFMIN(zeros_left, run_before);\ + }\ zeros_left -= run_before; \ scantable -= 1 + run_before; \ ((type*)block)[*scantable]= level[i]; \ @@ -594,8 +596,10 @@ static int decode_residual(const H264Context *h, H264SliceContext *sl, for(i=1;i 0;i++) { \ if(zeros_left < 7) \ run_before= get_vlc2(gb, run_vlc[zeros_left - 1].table, RUN_VLC_BITS, 1); \ - else \ + else {\ run_before= get_vlc2(gb, run7_vlc.table, RUN7_VLC_BITS, 2); \ + run_before = FFMIN(zeros_left, run_before);\ + }\ zeros_left -= run_before; \ scantable -= 1 + run_before; \ ((type*)block)[*scantable]= ((int)(level[i] * qmul[*scantable] + 32))>>6; \ From 994c4bc10751e39c7ed9f67ffd0c0dea5223daf2 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 15 Jul 2012 18:01:10 +0200 Subject: [PATCH 0039/2557] x86util: Port all macros to cpuflags Also do some small cosmetic changes: Drop pointless _MMX suffix from ABSD2 macro name, drop pointless check for MMX support, we always assume MMX is available in our SIMD code, fix spelling. --- libavcodec/x86/audiodsp.asm | 5 +--- libavutil/x86/x86util.asm | 52 ++++++++++++++++++++++--------------- libswscale/x86/scale.asm | 10 +------ 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/libavcodec/x86/audiodsp.asm b/libavcodec/x86/audiodsp.asm index e038c18bd8371..0f183c5e1d915 100644 --- a/libavcodec/x86/audiodsp.asm +++ b/libavcodec/x86/audiodsp.asm @@ -66,7 +66,7 @@ SCALARPRODUCT ; %1 = number of xmm registers used ; %2 = number of inline load/process/store loops per asm loop ; %3 = process 4*mmsize (%3=0) or 8*mmsize (%3=1) bytes per loop -; %4 = CLIPD function takes min/max as float instead of int (CLIPD_SSE2) +; %4 = CLIPD function takes min/max as float instead of int (SSE2 version) ; %5 = suffix %macro VECTOR_CLIP_INT32 4-5 cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len @@ -122,14 +122,11 @@ cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len %endmacro INIT_MMX mmx -%define CLIPD CLIPD_MMX VECTOR_CLIP_INT32 0, 1, 0, 0 INIT_XMM sse2 VECTOR_CLIP_INT32 6, 1, 0, 0, _int -%define CLIPD CLIPD_SSE2 VECTOR_CLIP_INT32 6, 2, 0, 1 INIT_XMM sse4 -%define CLIPD CLIPD_SSE41 %ifdef m8 VECTOR_CLIP_INT32 11, 1, 1, 0 %else diff --git a/libavutil/x86/x86util.asm b/libavutil/x86/x86util.asm index bba958ebfc9c4..81a3ada6e6f87 100644 --- a/libavutil/x86/x86util.asm +++ b/libavutil/x86/x86util.asm @@ -174,13 +174,13 @@ %endif %endmacro -%macro PSIGNW_MMX 2 +%macro PSIGNW 2 +%if cpuflag(ssse3) + psignw %1, %2 +%else pxor %1, %2 psubw %1, %2 -%endmacro - -%macro PSIGNW_SSSE3 2 - psignw %1, %2 +%endif %endmacro %macro ABS1 2 @@ -221,7 +221,7 @@ %endif %endmacro -%macro ABSB 2 ; source mmreg, temp mmreg (unused for ssse3) +%macro ABSB 2 ; source mmreg, temp mmreg (unused for SSSE3) %if cpuflag(ssse3) pabsb %1, %1 %else @@ -245,7 +245,7 @@ %endif %endmacro -%macro ABSD2_MMX 4 +%macro ABSD2 4 pxor %3, %3 pxor %4, %4 pcmpgtd %3, %1 @@ -290,7 +290,7 @@ %else palignr %1, %2, %3 %endif -%elif cpuflag(mmx) ; [dst,] src1, src2, imm, tmp +%else ; [dst,] src1, src2, imm, tmp %define %%dst %1 %if %0==5 %ifnidn %1, %2 @@ -606,37 +606,47 @@ pminsw %1, %3 %endmacro -%macro PMINSD_MMX 3 ; dst, src, tmp +%macro PMINSD 3 ; dst, src, tmp/unused +%if cpuflag(sse4) + pminsd %1, %2 +%elif cpuflag(sse2) + cvtdq2ps %1, %1 + minps %1, %2 + cvtps2dq %1, %1 +%else mova %3, %2 pcmpgtd %3, %1 pxor %1, %2 pand %1, %3 pxor %1, %2 +%endif %endmacro -%macro PMAXSD_MMX 3 ; dst, src, tmp +%macro PMAXSD 3 ; dst, src, tmp/unused +%if cpuflag(sse4) + pmaxsd %1, %2 +%else mova %3, %1 pcmpgtd %3, %2 pand %1, %3 pandn %3, %2 por %1, %3 +%endif %endmacro -%macro CLIPD_MMX 3-4 ; src/dst, min, max, tmp - PMINSD_MMX %1, %3, %4 - PMAXSD_MMX %1, %2, %4 -%endmacro - -%macro CLIPD_SSE2 3-4 ; src/dst, min (float), max (float), unused +%macro CLIPD 3-4 +%if cpuflag(sse4); src/dst, min, max, unused + pminsd %1, %3 + pmaxsd %1, %2 +%elif cpuflag(sse2) ; src/dst, min (float), max (float), unused cvtdq2ps %1, %1 minps %1, %3 maxps %1, %2 cvtps2dq %1, %1 -%endmacro - -%macro CLIPD_SSE41 3-4 ; src/dst, min, max, unused - pminsd %1, %3 - pmaxsd %1, %2 +%else ; src/dst, min, max, tmp + PMINSD %1, %3, %4 + PMAXSD %1, %2, %4 +%endif %endmacro %macro VBROADCASTSS 2 ; dst xmm/ymm, src m32 diff --git a/libswscale/x86/scale.asm b/libswscale/x86/scale.asm index 982b4320473f0..61709f47cb3ac 100644 --- a/libswscale/x86/scale.asm +++ b/libswscale/x86/scale.asm @@ -364,15 +364,7 @@ cglobal hscale%1to%2_%4, %5, 10, %6, pos0, dst, w, srcmem, filter, fltpos, fltsi movd [dstq+wq*2], m0 %endif ; %3 ==/!= X %else ; %2 == 19 -%if mmsize == 8 - PMINSD_MMX m0, m2, m4 -%elif cpuflag(sse4) - pminsd m0, m2 -%else ; sse2/ssse3 - cvtdq2ps m0, m0 - minps m0, m2 - cvtps2dq m0, m0 -%endif ; mmx/sse2/ssse3/sse4 + PMINSD m0, m2, m4 %ifnidn %3, X mova [dstq+wq*(4>>wshr)], m0 %else ; %3 == X From 307eb1a8ee363db1fcf869e427a8deb6d9538881 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 27 Jul 2012 12:09:17 +0200 Subject: [PATCH 0040/2557] x86: vp8dsp: port FILTER_BILINEAR macro to cpuflags --- libavcodec/x86/vp8dsp.asm | 143 ++++++++++++++++++-------------------- 1 file changed, 66 insertions(+), 77 deletions(-) diff --git a/libavcodec/x86/vp8dsp.asm b/libavcodec/x86/vp8dsp.asm index b0f6b83767e40..4270cdd64470c 100644 --- a/libavcodec/x86/vp8dsp.asm +++ b/libavcodec/x86/vp8dsp.asm @@ -664,6 +664,37 @@ INIT_XMM sse2 FILTER_V 8 %macro FILTER_BILINEAR 1 +%if cpuflag(ssse3) +cglobal put_vp8_bilinear%1_v, 7, 7, 5, dst, dststride, src, srcstride, height, picreg, my + shl myd, 4 +%ifdef PIC + lea picregq, [bilinear_filter_vb_m] +%endif + pxor m4, m4 + mova m3, [bilinear_filter_vb+myq-16] +.nextrow: + movh m0, [srcq+srcstrideq*0] + movh m1, [srcq+srcstrideq*1] + movh m2, [srcq+srcstrideq*2] + punpcklbw m0, m1 + punpcklbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m3 + psraw m0, 2 + psraw m1, 2 + pavgw m0, m4 + pavgw m1, m4 +%if mmsize==8 + packuswb m0, m0 + packuswb m1, m1 + movh [dstq+dststrideq*0], m0 + movh [dstq+dststrideq*1], m1 +%else + packuswb m0, m1 + movh [dstq+dststrideq*0], m0 + movhps [dstq+dststrideq*1], m0 +%endif +%else ; cpuflag(ssse3) cglobal put_vp8_bilinear%1_v, 7, 7, 7, dst, dststride, src, srcstride, height, picreg, my shl myd, 4 %ifdef PIC @@ -701,6 +732,7 @@ cglobal put_vp8_bilinear%1_v, 7, 7, 7, dst, dststride, src, srcstride, height, p movh [dstq+dststrideq*0], m0 movhps [dstq+dststrideq*1], m0 %endif +%endif ; cpuflag(ssse3) lea dstq, [dstq+dststrideq*2] lea srcq, [srcq+srcstrideq*2] @@ -708,6 +740,37 @@ cglobal put_vp8_bilinear%1_v, 7, 7, 7, dst, dststride, src, srcstride, height, p jg .nextrow REP_RET +%if cpuflag(ssse3) +cglobal put_vp8_bilinear%1_h, 6, 6 + npicregs, 5, dst, dststride, src, srcstride, height, mx, picreg + shl mxd, 4 +%ifdef PIC + lea picregq, [bilinear_filter_vb_m] +%endif + pxor m4, m4 + mova m2, [filter_h2_shuf] + mova m3, [bilinear_filter_vb+mxq-16] +.nextrow: + movu m0, [srcq+srcstrideq*0] + movu m1, [srcq+srcstrideq*1] + pshufb m0, m2 + pshufb m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m3 + psraw m0, 2 + psraw m1, 2 + pavgw m0, m4 + pavgw m1, m4 +%if mmsize==8 + packuswb m0, m0 + packuswb m1, m1 + movh [dstq+dststrideq*0], m0 + movh [dstq+dststrideq*1], m1 +%else + packuswb m0, m1 + movh [dstq+dststrideq*0], m0 + movhps [dstq+dststrideq*1], m0 +%endif +%else ; cpuflag(ssse3) cglobal put_vp8_bilinear%1_h, 6, 6 + npicregs, 7, dst, dststride, src, srcstride, height, mx, picreg shl mxd, 4 %ifdef PIC @@ -746,6 +809,7 @@ cglobal put_vp8_bilinear%1_h, 6, 6 + npicregs, 7, dst, dststride, src, srcstride movh [dstq+dststrideq*0], m0 movhps [dstq+dststrideq*1], m0 %endif +%endif ; cpuflag(ssse3) lea dstq, [dstq+dststrideq*2] lea srcq, [srcq+srcstrideq*2] @@ -758,85 +822,10 @@ INIT_MMX mmxext FILTER_BILINEAR 4 INIT_XMM sse2 FILTER_BILINEAR 8 - -%macro FILTER_BILINEAR_SSSE3 1 -cglobal put_vp8_bilinear%1_v, 7, 7, 5, dst, dststride, src, srcstride, height, picreg, my - shl myd, 4 -%ifdef PIC - lea picregq, [bilinear_filter_vb_m] -%endif - pxor m4, m4 - mova m3, [bilinear_filter_vb+myq-16] -.nextrow: - movh m0, [srcq+srcstrideq*0] - movh m1, [srcq+srcstrideq*1] - movh m2, [srcq+srcstrideq*2] - punpcklbw m0, m1 - punpcklbw m1, m2 - pmaddubsw m0, m3 - pmaddubsw m1, m3 - psraw m0, 2 - psraw m1, 2 - pavgw m0, m4 - pavgw m1, m4 -%if mmsize==8 - packuswb m0, m0 - packuswb m1, m1 - movh [dstq+dststrideq*0], m0 - movh [dstq+dststrideq*1], m1 -%else - packuswb m0, m1 - movh [dstq+dststrideq*0], m0 - movhps [dstq+dststrideq*1], m0 -%endif - - lea dstq, [dstq+dststrideq*2] - lea srcq, [srcq+srcstrideq*2] - sub heightd, 2 - jg .nextrow - REP_RET - -cglobal put_vp8_bilinear%1_h, 6, 6 + npicregs, 5, dst, dststride, src, srcstride, height, mx, picreg - shl mxd, 4 -%ifdef PIC - lea picregq, [bilinear_filter_vb_m] -%endif - pxor m4, m4 - mova m2, [filter_h2_shuf] - mova m3, [bilinear_filter_vb+mxq-16] -.nextrow: - movu m0, [srcq+srcstrideq*0] - movu m1, [srcq+srcstrideq*1] - pshufb m0, m2 - pshufb m1, m2 - pmaddubsw m0, m3 - pmaddubsw m1, m3 - psraw m0, 2 - psraw m1, 2 - pavgw m0, m4 - pavgw m1, m4 -%if mmsize==8 - packuswb m0, m0 - packuswb m1, m1 - movh [dstq+dststrideq*0], m0 - movh [dstq+dststrideq*1], m1 -%else - packuswb m0, m1 - movh [dstq+dststrideq*0], m0 - movhps [dstq+dststrideq*1], m0 -%endif - - lea dstq, [dstq+dststrideq*2] - lea srcq, [srcq+srcstrideq*2] - sub heightd, 2 - jg .nextrow - REP_RET -%endmacro - INIT_MMX ssse3 -FILTER_BILINEAR_SSSE3 4 +FILTER_BILINEAR 4 INIT_XMM ssse3 -FILTER_BILINEAR_SSSE3 8 +FILTER_BILINEAR 8 INIT_MMX mmx cglobal put_vp8_pixels8, 5, 5, 0, dst, dststride, src, srcstride, height From e9bb77fb1012cba1951a82136df7071f71bce8fb Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 8 Mar 2017 19:49:15 +0100 Subject: [PATCH 0041/2557] x86: h264: Simplify DEQUANT macro with cpuflags --- libavcodec/x86/h264_idct.asm | 52 +++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/libavcodec/x86/h264_idct.asm b/libavcodec/x86/h264_idct.asm index eb99476a85f1b..73631ffa2bb2e 100644 --- a/libavcodec/x86/h264_idct.asm +++ b/libavcodec/x86/h264_idct.asm @@ -958,7 +958,30 @@ cglobal h264_idct_add8_8, 5, 7 + ARCH_X86_64, 8 SWAP %1, %4, %3 %endmacro -%macro DEQUANT_MMX 3 +%macro DEQUANT 1-3 +%if cpuflag(sse2) + movd xmm4, t3d + movq xmm5, [pw_1] + pshufd xmm4, xmm4, 0 + movq2dq xmm0, m0 + movq2dq xmm1, m1 + movq2dq xmm2, m2 + movq2dq xmm3, m3 + punpcklwd xmm0, xmm5 + punpcklwd xmm1, xmm5 + punpcklwd xmm2, xmm5 + punpcklwd xmm3, xmm5 + pmaddwd xmm0, xmm4 + pmaddwd xmm1, xmm4 + pmaddwd xmm2, xmm4 + pmaddwd xmm3, xmm4 + psrad xmm0, %1 + psrad xmm1, %1 + psrad xmm2, %1 + psrad xmm3, %1 + packssdw xmm0, xmm1 + packssdw xmm2, xmm3 +%else mova m7, [pw_1] mova m4, %1 punpcklwd %1, m7 @@ -978,6 +1001,7 @@ cglobal h264_idct_add8_8, 5, 7 + ARCH_X86_64, 8 psrad m5, %3 packssdw %1, m4 packssdw %2, m5 +%endif %endmacro %macro STORE_WORDS 5-9 @@ -1016,35 +1040,15 @@ cglobal h264_idct_add8_8, 5, 7 + ARCH_X86_64, 8 %macro DEQUANT_STORE 1 %if cpuflag(sse2) - movd xmm4, t3d - movq xmm5, [pw_1] - pshufd xmm4, xmm4, 0 - movq2dq xmm0, m0 - movq2dq xmm1, m1 - movq2dq xmm2, m2 - movq2dq xmm3, m3 - punpcklwd xmm0, xmm5 - punpcklwd xmm1, xmm5 - punpcklwd xmm2, xmm5 - punpcklwd xmm3, xmm5 - pmaddwd xmm0, xmm4 - pmaddwd xmm1, xmm4 - pmaddwd xmm2, xmm4 - pmaddwd xmm3, xmm4 - psrad xmm0, %1 - psrad xmm1, %1 - psrad xmm2, %1 - psrad xmm3, %1 - packssdw xmm0, xmm1 - packssdw xmm2, xmm3 + DEQUANT %1 STORE_WORDS xmm0, 0, 1, 4, 5, 2, 3, 6, 7 STORE_WORDS xmm2, 8, 9, 12, 13, 10, 11, 14, 15 %else - DEQUANT_MMX m0, m1, %1 + DEQUANT m0, m1, %1 STORE_WORDS m0, 0, 1, 4, 5 STORE_WORDS m1, 2, 3, 6, 7 - DEQUANT_MMX m2, m3, %1 + DEQUANT m2, m3, %1 STORE_WORDS m2, 8, 9, 12, 13 STORE_WORDS m3, 10, 11, 14, 15 %endif From 681a86aba6cb09b98ad716d986182060c7795d20 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 15 Jul 2012 20:11:55 +0200 Subject: [PATCH 0042/2557] x86: fft: Port to cpuflags --- libavcodec/x86/fft.asm | 94 +++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/libavcodec/x86/fft.asm b/libavcodec/x86/fft.asm index 2c7438134c3ce..63e92f7159dd7 100644 --- a/libavcodec/x86/fft.asm +++ b/libavcodec/x86/fft.asm @@ -190,6 +190,23 @@ SECTION .text addps %2, %2, %5 ; {i0,i1,i2,i3} %endmacro +%macro INTERL 5 +%if cpuflag(avx) + vunpckhps %3, %2, %1 + vunpcklps %2, %2, %1 + vextractf128 %4(%5), %2, 0 + vextractf128 %4 %+ H(%5), %3, 0 + vextractf128 %4(%5 + 1), %2, 1 + vextractf128 %4 %+ H(%5 + 1), %3, 1 +%elif cpuflag(sse) + mova %3, %2 + unpcklps %2, %1 + unpckhps %3, %1 + mova %4(%5), %2 + mova %4(%5+1), %3 +%endif +%endmacro + ; scheduled for cpu-bound sizes %macro PASS_SMALL 3 ; (to load m4-m7), wre, wim IF%1 mova m4, Z(4) @@ -536,17 +553,6 @@ DEFINE_ARGS zc, w, n, o1, o3 INIT_YMM avx -%macro INTERL_AVX 5 - vunpckhps %3, %2, %1 - vunpcklps %2, %2, %1 - vextractf128 %4(%5), %2, 0 - vextractf128 %4 %+ H(%5), %3, 0 - vextractf128 %4(%5 + 1), %2, 1 - vextractf128 %4 %+ H(%5 + 1), %3, 1 -%endmacro - -%define INTERL INTERL_AVX - DECL_PASS pass_avx, PASS_BIG 1 DECL_PASS pass_interleave_avx, PASS_BIG 0 @@ -560,16 +566,6 @@ cglobal fft_calc, 2,5,8 INIT_XMM sse -%macro INTERL_SSE 5 - mova %3, %2 - unpcklps %2, %1 - unpckhps %3, %1 - mova %4(%5), %2 - mova %4(%5+1), %3 -%endmacro - -%define INTERL INTERL_SSE - DECL_PASS pass_sse, PASS_BIG 1 DECL_PASS pass_interleave_sse, PASS_BIG 0 @@ -855,16 +851,30 @@ INIT_XMM sse %endmacro %macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5 +%if cpuflag(sse) mulps m6, %3, [%5+%1] mulps m7, %2, [%5+%1] mulps %2, %2, [%6+%1] mulps %3, %3, [%6+%1] subps %2, %2, m6 addps %3, %3, m7 +%elif cpuflag(3dnow) + mova m6, [%1+%2*2] + mova %3, [%1+%2*2+8] + mova %4, m6 + mova m7, %3 + pfmul m6, [%5+%2] + pfmul %3, [%6+%2] + pfmul %4, [%6+%2] + pfmul m7, [%5+%2] + pfsub %3, m6 + pfadd %4, m7 +%endif %endmacro -%macro POSROTATESHUF_AVX 5 ;j, k, z+n8, tcos+n8, tsin+n8 +%macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8 .post: +%if cpuflag(avx) vmovaps ymm1, [%3+%1*2] vmovaps ymm0, [%3+%1*2+0x20] vmovaps ymm3, [%3+%2*2] @@ -893,10 +903,7 @@ INIT_XMM sse sub %2, 0x20 add %1, 0x20 jl .post -%endmacro - -%macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8 -.post: +%elif cpuflag(sse) movaps xmm1, [%3+%1*2] movaps xmm0, [%3+%1*2+0x10] CMUL %1, xmm0, xmm1, %3, %4, %5 @@ -918,25 +925,9 @@ INIT_XMM sse sub %2, 0x10 add %1, 0x10 jl .post -%endmacro - -%macro CMUL_3DNOW 6 - mova m6, [%1+%2*2] - mova %3, [%1+%2*2+8] - mova %4, m6 - mova m7, %3 - pfmul m6, [%5+%2] - pfmul %3, [%6+%2] - pfmul %4, [%6+%2] - pfmul m7, [%5+%2] - pfsub %3, m6 - pfadd %4, m7 -%endmacro - -%macro POSROTATESHUF_3DNOW 5 ;j, k, z+n8, tcos+n8, tsin+n8 -.post: - CMUL_3DNOW %3, %1, m0, m1, %4, %5 - CMUL_3DNOW %3, %2, m2, m3, %4, %5 +%elif cpuflag(3dnow) + CMUL %3, %1, m0, m1, %4, %5 + CMUL %3, %2, m2, m3, %4, %5 movd [%3+%1*2+ 0], m0 movd [%3+%2*2+12], m1 movd [%3+%2*2+ 0], m2 @@ -952,9 +943,10 @@ INIT_XMM sse sub %2, 8 add %1, 8 jl .post +%endif %endmacro -%macro DECL_IMDCT 1 +%macro DECL_IMDCT 0 cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *input %if ARCH_X86_64 %define rrevtab r7 @@ -1060,7 +1052,7 @@ cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *i neg r0 mov r1, -mmsize sub r1, r0 - %1 r0, r1, r6, rtcos, rtsin + POSROTATESHUF r0, r1, r6, rtcos, rtsin %if ARCH_X86_64 == 0 add esp, 12 %endif @@ -1070,17 +1062,17 @@ cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *i RET %endmacro -DECL_IMDCT POSROTATESHUF +DECL_IMDCT %if ARCH_X86_32 INIT_MMX 3dnow -DECL_IMDCT POSROTATESHUF_3DNOW +DECL_IMDCT INIT_MMX 3dnowext -DECL_IMDCT POSROTATESHUF_3DNOW +DECL_IMDCT %endif INIT_YMM avx -DECL_IMDCT POSROTATESHUF_AVX +DECL_IMDCT %endif ; CONFIG_MDCT From 0d8013b88b1cb7d65da891a8819d3beebafb9bb5 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Wed, 15 Mar 2017 00:07:23 +0100 Subject: [PATCH 0043/2557] configure: Replace -no_weak_symbols with -Werror=partial-availability Jack uses weak symbols on purpose. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index f915871b5cc1e..665df2762192f 100755 --- a/configure +++ b/configure @@ -3948,7 +3948,7 @@ case $target_os in SHFLAGS='-dynamiclib -Wl,-single_module -Wl,-install_name,$(SHLIBDIR)/$(SLIBNAME_WITH_MAJOR),-current_version,$(LIBVERSION),-compatibility_version,$(LIBMAJOR)' enabled x86_32 && append SHFLAGS -Wl,-read_only_relocs,suppress add_ldflags -Wl,-dynamic,-search_paths_first - check_ldflags -Wl,-no_weak_imports + check_cflags -Werror=partial-availability SLIBSUF=".dylib" SLIBNAME_WITH_VERSION='$(SLIBPREF)$(NAME).$(LIBVERSION)$(SLIBSUF)' SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(NAME).$(LIBMAJOR)$(SLIBSUF)' From 827a05eaa9482e9ac2a17f7f2e42ead07c1d7574 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 9 Mar 2017 15:11:49 -0300 Subject: [PATCH 0044/2557] matroskaenc: add support for Spherical Video elements Signed-off-by: James Almer Minor cosmetic changes by committer. Signed-off-by: Vittorio Giovara --- libavformat/matroskaenc.c | 84 +++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 2fe6e0ed4991b..34d983324bd6a 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -24,6 +24,7 @@ #include "avc.h" #include "hevc.h" #include "avformat.h" +#include "avio_internal.h" #include "avlanguage.h" #include "flacenc.h" #include "internal.h" @@ -44,6 +45,7 @@ #include "libavutil/random_seed.h" #include "libavutil/samplefmt.h" #include "libavutil/stereo3d.h" +#include "libavutil/spherical.h" #include "libavcodec/xiph.h" #include "libavcodec/mpeg4audio.h" @@ -646,6 +648,85 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, return ret; } +static int mkv_write_video_projection(AVFormatContext *s, AVIOContext *pb, + AVStream *st) +{ + AVIOContext b; + AVIOContext *dyn_cp; + int side_data_size = 0; + int ret, projection_size; + uint8_t *projection_ptr; + uint8_t private[20]; + + const AVSphericalMapping *spherical = + (const AVSphericalMapping *)av_stream_get_side_data(st, AV_PKT_DATA_SPHERICAL, + &side_data_size); + + if (!side_data_size) { + av_log(NULL, AV_LOG_WARNING, "Unknown spherical metadata\n"); + return 0; + } + + ret = avio_open_dyn_buf(&dyn_cp); + if (ret < 0) + return ret; + + switch (spherical->projection) { + case AV_SPHERICAL_EQUIRECTANGULAR: + put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONTYPE, + MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR); + break; + case AV_SPHERICAL_EQUIRECTANGULAR_TILE: + ffio_init_context(&b, private, 20, 1, NULL, NULL, NULL, NULL); + put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONTYPE, + MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR); + avio_wb32(&b, 0); // version + flags + avio_wb32(&b, spherical->bound_top); + avio_wb32(&b, spherical->bound_bottom); + avio_wb32(&b, spherical->bound_left); + avio_wb32(&b, spherical->bound_right); + put_ebml_binary(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONPRIVATE, + private, sizeof(private)); + break; + case AV_SPHERICAL_CUBEMAP: + ffio_init_context(&b, private, 12, 1, NULL, NULL, NULL, NULL); + put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONTYPE, + MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP); + avio_wb32(&b, 0); // version + flags + avio_wb32(&b, 0); // layout + avio_wb32(&b, spherical->padding); + put_ebml_binary(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONPRIVATE, + private, sizeof(private)); + break; + default: + av_log(s, AV_LOG_WARNING, "Unknown projection type\n"); + goto end; + } + + if (spherical->yaw) + put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, + (double) spherical->yaw / (1 << 16)); + if (spherical->pitch) + put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, + (double) spherical->pitch / (1 << 16)); + if (spherical->roll) + put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, + (double) spherical->roll / (1 << 16)); + +end: + projection_size = avio_close_dyn_buf(dyn_cp, &projection_ptr); + if (projection_size) { + ebml_master projection = start_ebml_master(pb, + MATROSKA_ID_VIDEOPROJECTION, + projection_size); + avio_write(pb, projection_ptr, projection_size); + end_ebml_master(pb, projection); + } + av_freep(&projection_ptr); + + return 0; +} + static void mkv_write_field_order(AVIOContext *pb, enum AVFieldOrder field_order) { @@ -895,6 +976,9 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, // check both side data and metadata for stereo information, // write the result to the bitstream if any is found ret = mkv_write_stereo_mode(s, pb, st, mkv->mode); + if (ret < 0) + return ret; + ret = mkv_write_video_projection(s, pb, st); if (ret < 0) return ret; diff --git a/libavformat/version.h b/libavformat/version.h index 3e28cc2804b75..34650f6ec34e8 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 57 #define LIBAVFORMAT_VERSION_MINOR 11 -#define LIBAVFORMAT_VERSION_MICRO 3 +#define LIBAVFORMAT_VERSION_MICRO 4 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From 7995ebfad12002033c73feed422a1cfc62081e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 9 Jan 2017 00:04:19 +0200 Subject: [PATCH 0045/2557] arm/aarch64: vp9: Fix vertical alignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align the second/third operands as they usually are. Due to the wildly varying sizes of the written out operands in aarch64 assembly, the column alignment is usually not as clear as in arm assembly. Signed-off-by: Martin Storsjö --- libavcodec/aarch64/vp9itxfm_neon.S | 36 +++++++++++++++--------------- libavcodec/arm/vp9itxfm_neon.S | 14 ++++++------ libavcodec/arm/vp9lpf_neon.S | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/libavcodec/aarch64/vp9itxfm_neon.S b/libavcodec/aarch64/vp9itxfm_neon.S index 539899dae0165..97226d11807ff 100644 --- a/libavcodec/aarch64/vp9itxfm_neon.S +++ b/libavcodec/aarch64/vp9itxfm_neon.S @@ -380,7 +380,7 @@ function ff_vp9_\txfm1\()_\txfm2\()_8x8_add_neon, export=1 .ifc \txfm1\()_\txfm2,idct_idct movrel x4, idct_coeffs .else - movrel x4, iadst8_coeffs + movrel x4, iadst8_coeffs ld1 {v1.8h}, [x4], #16 .endif ld1 {v0.8h}, [x4] @@ -480,23 +480,23 @@ itxfm_func8x8 iadst, iadst function idct16x16_dc_add_neon - movrel x4, idct_coeffs + movrel x4, idct_coeffs ld1 {v0.4h}, [x4] - movi v1.4h, #0 + movi v1.4h, #0 ld1 {v2.h}[0], [x2] - smull v2.4s, v2.4h, v0.h[0] - rshrn v2.4h, v2.4s, #14 - smull v2.4s, v2.4h, v0.h[0] - rshrn v2.4h, v2.4s, #14 + smull v2.4s, v2.4h, v0.h[0] + rshrn v2.4h, v2.4s, #14 + smull v2.4s, v2.4h, v0.h[0] + rshrn v2.4h, v2.4s, #14 dup v2.8h, v2.h[0] st1 {v1.h}[0], [x2] - srshr v2.8h, v2.8h, #6 + srshr v2.8h, v2.8h, #6 - mov x3, x0 - mov x4, #16 + mov x3, x0 + mov x4, #16 1: // Loop to add the constant from v2 into all 16x16 outputs subs x4, x4, #2 @@ -869,7 +869,7 @@ function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1 .ifc \txfm1,idct ld1 {v0.8h,v1.8h}, [x10] .endif - mov x9, #32 + mov x9, #32 .ifc \txfm1\()_\txfm2,idct_idct cmp w3, #10 @@ -1046,10 +1046,10 @@ idct16_partial quarter idct16_partial half function idct32x32_dc_add_neon - movrel x4, idct_coeffs + movrel x4, idct_coeffs ld1 {v0.4h}, [x4] - movi v1.4h, #0 + movi v1.4h, #0 ld1 {v2.h}[0], [x2] smull v2.4s, v2.4h, v0.h[0] @@ -1059,10 +1059,10 @@ function idct32x32_dc_add_neon dup v2.8h, v2.h[0] st1 {v1.h}[0], [x2] - srshr v0.8h, v2.8h, #6 + srshr v0.8h, v2.8h, #6 - mov x3, x0 - mov x4, #32 + mov x3, x0 + mov x4, #32 1: // Loop to add the constant v0 into all 32x32 outputs subs x4, x4, #2 @@ -1230,7 +1230,7 @@ endfunc // x9 = double input stride function idct32_1d_8x32_pass1\suffix\()_neon mov x14, x30 - movi v2.8h, #0 + movi v2.8h, #0 // v16 = IN(0), v17 = IN(2) ... v31 = IN(30) .ifb \suffix @@ -1295,7 +1295,7 @@ function idct32_1d_8x32_pass1\suffix\()_neon .endif add x2, x2, #64 - movi v2.8h, #0 + movi v2.8h, #0 // v16 = IN(1), v17 = IN(3) ... v31 = IN(31) .ifb \suffix .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 diff --git a/libavcodec/arm/vp9itxfm_neon.S b/libavcodec/arm/vp9itxfm_neon.S index ab9433ff0fd95..67a4754ce7f35 100644 --- a/libavcodec/arm/vp9itxfm_neon.S +++ b/libavcodec/arm/vp9itxfm_neon.S @@ -530,7 +530,7 @@ function idct16x16_dc_add_neon movrel r12, idct_coeffs vld1.16 {d0}, [r12,:64] - vmov.i16 q2, #0 + vmov.i16 q2, #0 vld1.16 {d16[]}, [r2,:16] vmull.s16 q8, d16, d0[0] @@ -793,7 +793,7 @@ function \txfm\()16_1d_4x16_pass1_neon push {lr} mov r12, #32 - vmov.s16 q2, #0 + vmov.s16 q2, #0 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 vld1.16 {d\i}, [r2,:64] vst1.16 {d4}, [r2,:64], r12 @@ -1142,7 +1142,7 @@ function idct32x32_dc_add_neon movrel r12, idct_coeffs vld1.16 {d0}, [r12,:64] - vmov.i16 q2, #0 + vmov.i16 q2, #0 vld1.16 {d16[]}, [r2,:16] vmull.s16 q8, d16, d0[0] @@ -1330,7 +1330,7 @@ function idct32_1d_4x32_pass1\suffix\()_neon @ Double stride of the input, since we only read every other line mov r12, #128 - vmov.s16 d4, #0 + vmov.s16 d4, #0 @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30) .ifb \suffix @@ -1394,7 +1394,7 @@ function idct32_1d_4x32_pass1\suffix\()_neon .endif add r2, r2, #64 - vmov.s16 d8, #0 + vmov.s16 d8, #0 @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31) .ifb \suffix .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 @@ -1533,9 +1533,9 @@ function idct32_1d_4x32_pass2\suffix\()_neon .endif vld1.32 {d12[]}, [r0,:32], r1 vld1.32 {d12[1]}, [r0,:32], r1 - vrshr.s16 q4, q4, #6 + vrshr.s16 q4, q4, #6 vld1.32 {d13[]}, [r0,:32], r1 - vrshr.s16 q5, q5, #6 + vrshr.s16 q5, q5, #6 vld1.32 {d13[1]}, [r0,:32], r1 sub r0, r0, r1, lsl #2 vaddw.u8 q4, q4, d12 diff --git a/libavcodec/arm/vp9lpf_neon.S b/libavcodec/arm/vp9lpf_neon.S index 12984a900c0a4..ae782b2ed0ec4 100644 --- a/libavcodec/arm/vp9lpf_neon.S +++ b/libavcodec/arm/vp9lpf_neon.S @@ -828,7 +828,7 @@ function ff_vp9_loop_filter_v_16_16_neon, export=1 endfunc function vp9_loop_filter_h_16_neon - sub r12, r0, #8 + sub r12, r0, #8 vld1.8 {d16}, [r12,:64], r1 vld1.8 {d24}, [r0, :64], r1 vld1.8 {d17}, [r12,:64], r1 From cfee5e1a0fa892fadd19b8848545d62f2386a6e7 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 14 Mar 2017 15:31:04 +0100 Subject: [PATCH 0046/2557] build: Add missing object dependency for extract_extradata bitstream filter --- libavcodec/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index d586dbd01418c..2b1e2212489ed 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -762,7 +762,8 @@ OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o aacadtsdec.o \ mpeg4audio.o OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o -OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o +OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \ + h2645_parse.o OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o From b864230c49089b087eef56988a3d6a784f6f9827 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 14 Mar 2017 16:38:38 +0100 Subject: [PATCH 0047/2557] rtmp: Move RTMP digest calculation to a separate file The rtmpcrypt protocol requires it. --- libavformat/Makefile | 14 ++++----- libavformat/rtmpdigest.c | 67 ++++++++++++++++++++++++++++++++++++++++ libavformat/rtmpproto.c | 36 --------------------- 3 files changed, 74 insertions(+), 43 deletions(-) create mode 100644 libavformat/rtmpdigest.c diff --git a/libavformat/Makefile b/libavformat/Makefile index f363955e0e3a2..c55538018979d 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -386,7 +386,7 @@ OBJS-$(CONFIG_LIBRTMP) += librtmp.o OBJS-$(CONFIG_APPLEHTTP_PROTOCOL) += hlsproto.o OBJS-$(CONFIG_CONCAT_PROTOCOL) += concat.o OBJS-$(CONFIG_CRYPTO_PROTOCOL) += crypto.o -OBJS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpcrypt.o rtmpdh.o +OBJS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpcrypt.o rtmpdigest.o rtmpdh.o OBJS-$(CONFIG_FFRTMPHTTP_PROTOCOL) += rtmphttp.o OBJS-$(CONFIG_FILE_PROTOCOL) += file.o OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o @@ -399,12 +399,12 @@ OBJS-$(CONFIG_MD5_PROTOCOL) += md5proto.o OBJS-$(CONFIG_MMSH_PROTOCOL) += mmsh.o mms.o asf.o OBJS-$(CONFIG_MMST_PROTOCOL) += mmst.o mms.o asf.o OBJS-$(CONFIG_PIPE_PROTOCOL) += file.o -OBJS-$(CONFIG_RTMP_PROTOCOL) += rtmpproto.o rtmppkt.o -OBJS-$(CONFIG_RTMPE_PROTOCOL) += rtmpproto.o rtmppkt.o -OBJS-$(CONFIG_RTMPS_PROTOCOL) += rtmpproto.o rtmppkt.o -OBJS-$(CONFIG_RTMPT_PROTOCOL) += rtmpproto.o rtmppkt.o -OBJS-$(CONFIG_RTMPTE_PROTOCOL) += rtmpproto.o rtmppkt.o -OBJS-$(CONFIG_RTMPTS_PROTOCOL) += rtmpproto.o rtmppkt.o +OBJS-$(CONFIG_RTMP_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o +OBJS-$(CONFIG_RTMPE_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o +OBJS-$(CONFIG_RTMPS_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o +OBJS-$(CONFIG_RTMPT_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o +OBJS-$(CONFIG_RTMPTE_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o +OBJS-$(CONFIG_RTMPTS_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o OBJS-$(CONFIG_SCTP_PROTOCOL) += sctp.o OBJS-$(CONFIG_SRTP_PROTOCOL) += srtpproto.o srtp.o diff --git a/libavformat/rtmpdigest.c b/libavformat/rtmpdigest.c new file mode 100644 index 0000000000000..e7645d35f6921 --- /dev/null +++ b/libavformat/rtmpdigest.c @@ -0,0 +1,67 @@ +/* + * RTMP network protocol + * Copyright (c) 2009 Konstantin Shishkov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * RTMP protocol digest + */ + +#include + +#include "libavutil/error.h" +#include "libavutil/hmac.h" + +#include "rtmp.h" + +int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap, + const uint8_t *key, int keylen, uint8_t *dst) +{ + AVHMAC *hmac; + + hmac = av_hmac_alloc(AV_HMAC_SHA256); + if (!hmac) + return AVERROR(ENOMEM); + + av_hmac_init(hmac, key, keylen); + if (gap <= 0) { + av_hmac_update(hmac, src, len); + } else { //skip 32 bytes used for storing digest + av_hmac_update(hmac, src, gap); + av_hmac_update(hmac, src + gap + 32, len - gap - 32); + } + av_hmac_final(hmac, dst, 32); + + av_hmac_free(hmac); + + return 0; +} + +int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val, + int add_val) +{ + int i, digest_pos = 0; + + for (i = 0; i < 4; i++) + digest_pos += buf[i + off]; + digest_pos = digest_pos % mod_val + add_val; + + return digest_pos; +} diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 8e036961a6da7..7d402276323df 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -27,7 +27,6 @@ #include "libavcodec/bytestream.h" #include "libavutil/avstring.h" #include "libavutil/base64.h" -#include "libavutil/hmac.h" #include "libavutil/intfloat.h" #include "libavutil/lfg.h" #include "libavutil/md5.h" @@ -957,41 +956,6 @@ static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt, return rtmp_send_packet(rt, &pkt, 1); } -int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap, - const uint8_t *key, int keylen, uint8_t *dst) -{ - AVHMAC *hmac; - - hmac = av_hmac_alloc(AV_HMAC_SHA256); - if (!hmac) - return AVERROR(ENOMEM); - - av_hmac_init(hmac, key, keylen); - if (gap <= 0) { - av_hmac_update(hmac, src, len); - } else { //skip 32 bytes used for storing digest - av_hmac_update(hmac, src, gap); - av_hmac_update(hmac, src + gap + 32, len - gap - 32); - } - av_hmac_final(hmac, dst, 32); - - av_hmac_free(hmac); - - return 0; -} - -int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val, - int add_val) -{ - int i, digest_pos = 0; - - for (i = 0; i < 4; i++) - digest_pos += buf[i + off]; - digest_pos = digest_pos % mod_val + add_val; - - return digest_pos; -} - /** * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest * will be stored) into that packet. From b266ad56fe0e4ce5bb70118ba2e2b1dabfaf76ce Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:28 +0000 Subject: [PATCH 0048/2557] hwcontext: Add device derivation Creates a new device context from another of a different type which refers to the same underlying hardware. --- doc/APIchanges | 3 ++ libavutil/hwcontext.c | 65 ++++++++++++++++++++++++++++++++++ libavutil/hwcontext.h | 26 ++++++++++++++ libavutil/hwcontext_internal.h | 8 +++++ libavutil/version.h | 2 +- 5 files changed, 103 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 9367a5fc41785..335c1634793e1 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2015-08-28 API changes, most recent first: +2017-03-xx - xxxxxxx - lavu 55.34.0 - hwcontext.h + Add av_hwdevice_ctx_create_derived(). + 2017-02-10 - xxxxxxx - lavu 55.33.0 - spherical.h Add AV_SPHERICAL_EQUIRECTANGULAR_TILE, av_spherical_tile_bounds(), and projection-specific properties (bound_left, bound_top, bound_right, diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index 608da6872761f..252dd32e38355 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -65,6 +65,8 @@ static void hwdevice_ctx_free(void *opaque, uint8_t *data) if (ctx->free) ctx->free(ctx); + av_buffer_unref(&ctx->internal->source_device); + av_freep(&ctx->hwctx); av_freep(&ctx->internal->priv); av_freep(&ctx->internal); @@ -535,6 +537,69 @@ int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, return ret; } +int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, + enum AVHWDeviceType type, + AVBufferRef *src_ref, int flags) +{ + AVBufferRef *dst_ref = NULL, *tmp_ref; + AVHWDeviceContext *dst_ctx, *tmp_ctx; + int ret = 0; + + tmp_ref = src_ref; + while (tmp_ref) { + tmp_ctx = (AVHWDeviceContext*)tmp_ref->data; + if (tmp_ctx->type == type) { + dst_ref = av_buffer_ref(tmp_ref); + if (!dst_ref) { + ret = AVERROR(ENOMEM); + goto fail; + } + goto done; + } + tmp_ref = tmp_ctx->internal->source_device; + } + + dst_ref = av_hwdevice_ctx_alloc(type); + if (!dst_ref) { + ret = AVERROR(ENOMEM); + goto fail; + } + dst_ctx = (AVHWDeviceContext*)dst_ref->data; + + tmp_ref = src_ref; + while (tmp_ref) { + tmp_ctx = (AVHWDeviceContext*)tmp_ref->data; + if (dst_ctx->internal->hw_type->device_derive) { + ret = dst_ctx->internal->hw_type->device_derive(dst_ctx, + tmp_ctx, + flags); + if (ret == 0) { + dst_ctx->internal->source_device = av_buffer_ref(src_ref); + if (!dst_ctx->internal->source_device) { + ret = AVERROR(ENOMEM); + goto fail; + } + goto done; + } + if (ret != AVERROR(ENOSYS)) + goto fail; + } + tmp_ref = tmp_ctx->internal->source_device; + } + + ret = AVERROR(ENOSYS); + goto fail; + +done: + *dst_ref_ptr = dst_ref; + return 0; + +fail: + av_buffer_unref(&dst_ref); + *dst_ref_ptr = NULL; + return ret; +} + static void ff_hwframe_unmap(void *opaque, uint8_t *data) { HWMapDescriptor *hwmap = (HWMapDescriptor*)data; diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h index 037ca64224d23..49c7a21c1e748 100644 --- a/libavutil/hwcontext.h +++ b/libavutil/hwcontext.h @@ -268,6 +268,32 @@ int av_hwdevice_ctx_init(AVBufferRef *ref); int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags); +/** + * Create a new device of the specified type from an existing device. + * + * If the source device is a device of the target type or was originally + * derived from such a device (possibly through one or more intermediate + * devices of other types), then this will return a reference to the + * existing device of the same type as is requested. + * + * Otherwise, it will attempt to derive a new device from the given source + * device. If direct derivation to the new type is not implemented, it will + * attempt the same derivation from each ancestor of the source device in + * turn looking for an implemented derivation method. + * + * @param dst_ctx On success, a reference to the newly-created + * AVHWDeviceContext. + * @param type The type of the new device to create. + * @param src_ctx A reference to an existing AVHWDeviceContext which will be + * used to create the new device. + * @param flags Currently unused; should be set to zero. + * @return Zero on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ctx, + enum AVHWDeviceType type, + AVBufferRef *src_ctx, int flags); + + /** * Allocate an AVHWFramesContext tied to a given device context. * diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h index 11e3a68e4cf70..66f54142e8ef6 100644 --- a/libavutil/hwcontext_internal.h +++ b/libavutil/hwcontext_internal.h @@ -66,6 +66,8 @@ typedef struct HWContextType { int (*device_create)(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags); + int (*device_derive)(AVHWDeviceContext *dst_ctx, + AVHWDeviceContext *src_ctx, int flags); int (*device_init)(AVHWDeviceContext *ctx); void (*device_uninit)(AVHWDeviceContext *ctx); @@ -95,6 +97,12 @@ typedef struct HWContextType { struct AVHWDeviceInternal { const HWContextType *hw_type; void *priv; + + /** + * For a derived device, a reference to the original device + * context it was derived from. + */ + AVBufferRef *source_device; }; struct AVHWFramesInternal { diff --git a/libavutil/version.h b/libavutil/version.h index 0f2b684fa8fc4..7c0e852498cb2 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -54,7 +54,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 55 -#define LIBAVUTIL_VERSION_MINOR 33 +#define LIBAVUTIL_VERSION_MINOR 34 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From b7487f4f3c39b4b202e1ea7bb2de13902f2dee45 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:29 +0000 Subject: [PATCH 0049/2557] hwcontext: Make it easier to work with device types Adds functions to convert to/from strings and a function to iterate over all supported device types. Also adds a new invalid type AV_HWDEVICE_TYPE_NONE, which acts as a sentinel value. --- doc/APIchanges | 4 ++++ libavutil/hwcontext.c | 41 +++++++++++++++++++++++++++++++++++++++++ libavutil/hwcontext.h | 28 ++++++++++++++++++++++++++++ libavutil/version.h | 2 +- 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 335c1634793e1..70b3391988eb2 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,10 @@ libavutil: 2015-08-28 API changes, most recent first: +2017-03-xx - xxxxxxx - lavu 55.35.0 - hwcontext.h + Add AV_HWDEVICE_TYPE_NONE, av_hwdevice_find_type_by_name(), + av_hwdevice_get_type_name() and av_hwdevice_iterate_types(). + 2017-03-xx - xxxxxxx - lavu 55.34.0 - hwcontext.h Add av_hwdevice_ctx_create_derived(). diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index 252dd32e38355..2c6d51ee55df7 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -47,6 +47,47 @@ static const HWContextType * const hw_table[] = { NULL, }; +const char *hw_type_names[] = { + [AV_HWDEVICE_TYPE_CUDA] = "cuda", + [AV_HWDEVICE_TYPE_DXVA2] = "dxva2", + [AV_HWDEVICE_TYPE_QSV] = "qsv", + [AV_HWDEVICE_TYPE_VAAPI] = "vaapi", + [AV_HWDEVICE_TYPE_VDPAU] = "vdpau", +}; + +enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name) +{ + int type; + for (type = 0; type < FF_ARRAY_ELEMS(hw_type_names); type++) { + if (hw_type_names[type] && !strcmp(hw_type_names[type], name)) + return type; + } + return AV_HWDEVICE_TYPE_NONE; +} + +const char *av_hwdevice_get_type_name(enum AVHWDeviceType type) +{ + if (type >= 0 && type < FF_ARRAY_ELEMS(hw_type_names)) + return hw_type_names[type]; + else + return NULL; +} + +enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev) +{ + enum AVHWDeviceType next; + int i, set = 0; + for (i = 0; hw_table[i]; i++) { + if (prev != AV_HWDEVICE_TYPE_NONE && hw_table[i]->type <= prev) + continue; + if (!set || hw_table[i]->type < next) { + next = hw_table[i]->type; + set = 1; + } + } + return set ? next : AV_HWDEVICE_TYPE_NONE; +} + static const AVClass hwdevice_ctx_class = { .class_name = "AVHWDeviceContext", .item_name = av_default_item_name, diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h index 49c7a21c1e748..040e010b30865 100644 --- a/libavutil/hwcontext.h +++ b/libavutil/hwcontext.h @@ -30,6 +30,7 @@ enum AVHWDeviceType { AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_DXVA2, AV_HWDEVICE_TYPE_QSV, + AV_HWDEVICE_TYPE_NONE, }; typedef struct AVHWDeviceInternal AVHWDeviceInternal; @@ -222,6 +223,33 @@ typedef struct AVHWFramesContext { int width, height; } AVHWFramesContext; +/** + * Look up an AVHWDeviceType by name. + * + * @param name String name of the device type (case-insensitive). + * @return The type from enum AVHWDeviceType, or AV_HWDEVICE_TYPE_NONE if + * not found. + */ +enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name); + +/** Get the string name of an AVHWDeviceType. + * + * @param type Type from enum AVHWDeviceType. + * @return Pointer to a static string containing the name, or NULL if the type + * is not valid. + */ +const char *av_hwdevice_get_type_name(enum AVHWDeviceType type); + +/** + * Iterate over supported device types. + * + * @param type AV_HWDEVICE_TYPE_NONE initially, then the previous type + * returned by this function in subsequent iterations. + * @return The next usable device type from enum AVHWDeviceType, or + * AV_HWDEVICE_TYPE_NONE if there are no more. + */ +enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev); + /** * Allocate an AVHWDeviceContext for a given pixel format. * diff --git a/libavutil/version.h b/libavutil/version.h index 7c0e852498cb2..f952cc48dd250 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -54,7 +54,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 55 -#define LIBAVUTIL_VERSION_MINOR 34 +#define LIBAVUTIL_VERSION_MINOR 35 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From d2e6dd32a445b5744a51d090c0822dbd7e434592 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:30 +0000 Subject: [PATCH 0050/2557] avconv: Generic device setup Not yet enabled for any hwaccels. --- avtools/Makefile | 3 +- avtools/avconv.c | 22 +++ avtools/avconv.h | 17 ++ avtools/avconv_hw.c | 383 +++++++++++++++++++++++++++++++++++++++++++ avtools/avconv_opt.c | 33 +++- 5 files changed, 452 insertions(+), 6 deletions(-) create mode 100644 avtools/avconv_hw.c diff --git a/avtools/Makefile b/avtools/Makefile index d6d609f54414b..8effa995da246 100644 --- a/avtools/Makefile +++ b/avtools/Makefile @@ -8,7 +8,8 @@ PROGS += $(AVPROGS) AVBASENAMES = avconv avplay avprobe ALLAVPROGS = $(AVBASENAMES:%=%$(EXESUF)) -OBJS-avconv += avtools/avconv_opt.o avtools/avconv_filter.o +OBJS-avconv += avtools/avconv_opt.o avtools/avconv_filter.o \ + avtools/avconv_hw.o OBJS-avconv-$(CONFIG_LIBMFX) += avtools/avconv_qsv.o OBJS-avconv-$(CONFIG_VAAPI) += avtools/avconv_vaapi.o OBJS-avconv-$(CONFIG_VDA) += avtools/avconv_vda.o diff --git a/avtools/avconv.c b/avtools/avconv.c index 5c36761c1d14e..3f5806788eb50 100644 --- a/avtools/avconv.c +++ b/avtools/avconv.c @@ -1704,6 +1704,17 @@ static int init_input_stream(int ist_index, char *error, int error_len) if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0)) av_dict_set(&ist->decoder_opts, "threads", "auto", 0); + + ret = hw_device_setup_for_decode(ist); + if (ret < 0) { + char errbuf[128]; + av_strerror(ret, errbuf, sizeof(errbuf)); + snprintf(error, error_len, "Device setup failed for " + "decoder on input stream #%d:%d : %s", + ist->file_index, ist->st->index, errbuf); + return ret; + } + if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) { char errbuf[128]; if (ret == AVERROR_EXPERIMENTAL) @@ -2046,6 +2057,16 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len) ost->enc_ctx->hw_frames_ctx = av_buffer_ref(ost->filter->filter->inputs[0]->hw_frames_ctx); if (!ost->enc_ctx->hw_frames_ctx) return AVERROR(ENOMEM); + } else { + ret = hw_device_setup_for_encode(ost); + if (ret < 0) { + char errbuf[128]; + av_strerror(ret, errbuf, sizeof(errbuf)); + snprintf(error, error_len, "Device setup failed for " + "encoder on output stream #%d:%d : %s", + ost->file_index, ost->index, errbuf); + return ret; + } } if ((ret = avcodec_open2(ost->enc_ctx, codec, &ost->encoder_opts)) < 0) { @@ -2795,6 +2816,7 @@ static int transcode(void) } av_buffer_unref(&hw_device_ctx); + hw_device_free_all(); /* finished ! */ ret = 0; diff --git a/avtools/avconv.h b/avtools/avconv.h index 3c3f0ef659558..c578e2074b489 100644 --- a/avtools/avconv.h +++ b/avtools/avconv.h @@ -40,6 +40,7 @@ #include "libavutil/avutil.h" #include "libavutil/dict.h" #include "libavutil/fifo.h" +#include "libavutil/hwcontext.h" #include "libavutil/pixfmt.h" #include "libavutil/rational.h" @@ -63,8 +64,15 @@ typedef struct HWAccel { int (*init)(AVCodecContext *s); enum HWAccelID id; enum AVPixelFormat pix_fmt; + enum AVHWDeviceType device_type; } HWAccel; +typedef struct HWDevice { + char *name; + enum AVHWDeviceType type; + AVBufferRef *device_ref; +} HWDevice; + /* select an input stream for an output stream */ typedef struct StreamMap { int disabled; /* 1 is this mapping is disabled by a negative map */ @@ -510,4 +518,13 @@ int qsv_transcode_init(OutputStream *ost); int vaapi_decode_init(AVCodecContext *avctx); int vaapi_device_init(const char *device); +HWDevice *hw_device_get_by_name(const char *name); +int hw_device_init_from_string(const char *arg, HWDevice **dev); +void hw_device_free_all(void); + +int hw_device_setup_for_decode(InputStream *ist); +int hw_device_setup_for_encode(OutputStream *ost); + +int hwaccel_decode_init(AVCodecContext *avctx); + #endif /* AVCONV_H */ diff --git a/avtools/avconv_hw.c b/avtools/avconv_hw.c new file mode 100644 index 0000000000000..fd1618389b8a4 --- /dev/null +++ b/avtools/avconv_hw.c @@ -0,0 +1,383 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "avconv.h" + +static int nb_hw_devices; +static HWDevice **hw_devices; + +static HWDevice *hw_device_get_by_type(enum AVHWDeviceType type) +{ + HWDevice *found = NULL; + int i; + for (i = 0; i < nb_hw_devices; i++) { + if (hw_devices[i]->type == type) { + if (found) + return NULL; + found = hw_devices[i]; + } + } + return found; +} + +HWDevice *hw_device_get_by_name(const char *name) +{ + int i; + for (i = 0; i < nb_hw_devices; i++) { + if (!strcmp(hw_devices[i]->name, name)) + return hw_devices[i]; + } + return NULL; +} + +static HWDevice *hw_device_add(void) +{ + int err; + err = av_reallocp_array(&hw_devices, nb_hw_devices + 1, + sizeof(*hw_devices)); + if (err) { + nb_hw_devices = 0; + return NULL; + } + hw_devices[nb_hw_devices] = av_mallocz(sizeof(HWDevice)); + if (!hw_devices[nb_hw_devices]) + return NULL; + return hw_devices[nb_hw_devices++]; +} + +int hw_device_init_from_string(const char *arg, HWDevice **dev_out) +{ + // "type=name:device,key=value,key2=value2" + // "type:device,key=value,key2=value2" + // -> av_hwdevice_ctx_create() + // "type=name@name" + // "type@name" + // -> av_hwdevice_ctx_create_derived() + + AVDictionary *options = NULL; + char *type_name = NULL, *name = NULL, *device = NULL; + enum AVHWDeviceType type; + HWDevice *dev, *src; + AVBufferRef *device_ref; + int err; + const char *errmsg, *p, *q; + size_t k; + + k = strcspn(arg, ":=@"); + p = arg + k; + + type_name = av_strndup(arg, k); + if (!type_name) { + err = AVERROR(ENOMEM); + goto fail; + } + type = av_hwdevice_find_type_by_name(type_name); + if (type == AV_HWDEVICE_TYPE_NONE) { + errmsg = "unknown device type"; + goto invalid; + } + + if (*p == '=') { + k = strcspn(p + 1, ":@"); + + name = av_strndup(p + 1, k); + if (!name) { + err = AVERROR(ENOMEM); + goto fail; + } + if (hw_device_get_by_name(name)) { + errmsg = "named device already exists"; + goto invalid; + } + + p += 1 + k; + } else { + // Give the device an automatic name of the form "type%d". + // We arbitrarily limit at 1000 anonymous devices of the same + // type - there is probably something else very wrong if you + // get to this limit. + size_t index_pos; + int index, index_limit = 1000; + index_pos = strlen(type_name); + name = av_malloc(index_pos + 4); + if (!name) { + err = AVERROR(ENOMEM); + goto fail; + } + for (index = 0; index < index_limit; index++) { + snprintf(name, index_pos + 4, "%s%d", type_name, index); + if (!hw_device_get_by_name(name)) + break; + } + if (index >= index_limit) { + errmsg = "too many devices"; + goto invalid; + } + } + + if (!*p) { + // New device with no parameters. + err = av_hwdevice_ctx_create(&device_ref, type, + NULL, NULL, 0); + if (err < 0) + goto fail; + + } else if (*p == ':') { + // New device with some parameters. + ++p; + q = strchr(p, ','); + if (q) { + device = av_strndup(p, q - p); + if (!device) { + err = AVERROR(ENOMEM); + goto fail; + } + err = av_dict_parse_string(&options, q + 1, "=", ",", 0); + if (err < 0) { + errmsg = "failed to parse options"; + goto invalid; + } + } + + err = av_hwdevice_ctx_create(&device_ref, type, + device ? device : p, options, 0); + if (err < 0) + goto fail; + + } else if (*p == '@') { + // Derive from existing device. + + src = hw_device_get_by_name(p + 1); + if (!src) { + errmsg = "invalid source device name"; + goto invalid; + } + + err = av_hwdevice_ctx_create_derived(&device_ref, type, + src->device_ref, 0); + if (err < 0) + goto fail; + } else { + errmsg = "parse error"; + goto invalid; + } + + dev = hw_device_add(); + if (!dev) { + err = AVERROR(ENOMEM); + goto fail; + } + + dev->name = name; + dev->type = type; + dev->device_ref = device_ref; + + if (dev_out) + *dev_out = dev; + + name = NULL; + err = 0; +done: + av_freep(&type_name); + av_freep(&name); + av_freep(&device); + av_dict_free(&options); + return err; +invalid: + av_log(NULL, AV_LOG_ERROR, + "Invalid device specification \"%s\": %s\n", arg, errmsg); + err = AVERROR(EINVAL); + goto done; +fail: + av_log(NULL, AV_LOG_ERROR, + "Device creation failed: %d.\n", err); + goto done; +} + +void hw_device_free_all(void) +{ + int i; + for (i = 0; i < nb_hw_devices; i++) { + av_freep(&hw_devices[i]->name); + av_buffer_unref(&hw_devices[i]->device_ref); + av_freep(&hw_devices[i]); + } + av_freep(&hw_devices); + nb_hw_devices = 0; +} + +static enum AVHWDeviceType hw_device_match_type_by_hwaccel(enum HWAccelID hwaccel_id) +{ + int i; + if (hwaccel_id == HWACCEL_NONE) + return AV_HWDEVICE_TYPE_NONE; + for (i = 0; hwaccels[i].name; i++) { + if (hwaccels[i].id == hwaccel_id) + return hwaccels[i].device_type; + } + return AV_HWDEVICE_TYPE_NONE; +} + +static enum AVHWDeviceType hw_device_match_type_in_name(const char *codec_name) +{ + const char *type_name; + enum AVHWDeviceType type; + for (type = av_hwdevice_iterate_types(AV_HWDEVICE_TYPE_NONE); + type != AV_HWDEVICE_TYPE_NONE; + type = av_hwdevice_iterate_types(type)) { + type_name = av_hwdevice_get_type_name(type); + if (strstr(codec_name, type_name)) + return type; + } + return AV_HWDEVICE_TYPE_NONE; +} + +int hw_device_setup_for_decode(InputStream *ist) +{ + enum AVHWDeviceType type; + HWDevice *dev; + const char *type_name; + int err; + + if (ist->hwaccel_device) { + dev = hw_device_get_by_name(ist->hwaccel_device); + if (!dev) { + char *tmp; + size_t len; + type = hw_device_match_type_by_hwaccel(ist->hwaccel_id); + if (type == AV_HWDEVICE_TYPE_NONE) { + // No match - this isn't necessarily invalid, though, + // because an explicit device might not be needed or + // the hwaccel setup could be handled elsewhere. + return 0; + } + type_name = av_hwdevice_get_type_name(type); + len = strlen(type_name) + 1 + + strlen(ist->hwaccel_device) + 1; + tmp = av_malloc(len); + if (!tmp) + return AVERROR(ENOMEM); + snprintf(tmp, len, "%s:%s", type_name, ist->hwaccel_device); + err = hw_device_init_from_string(tmp, &dev); + av_free(tmp); + if (err < 0) + return err; + } + } else { + if (ist->hwaccel_id != HWACCEL_NONE) + type = hw_device_match_type_by_hwaccel(ist->hwaccel_id); + else + type = hw_device_match_type_in_name(ist->dec->name); + if (type != AV_HWDEVICE_TYPE_NONE) { + dev = hw_device_get_by_type(type); + } else { + // No device required. + return 0; + } + } + + if (!dev) { + av_log(ist->dec_ctx, AV_LOG_WARNING, "No device available " + "for decoder (device type %s for codec %s).\n", + av_hwdevice_get_type_name(type), ist->dec->name); + return 0; + } + + ist->dec_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); + if (!ist->dec_ctx->hw_device_ctx) + return AVERROR(ENOMEM); + + return 0; +} + +int hw_device_setup_for_encode(OutputStream *ost) +{ + enum AVHWDeviceType type; + HWDevice *dev; + + type = hw_device_match_type_in_name(ost->enc->name); + if (type != AV_HWDEVICE_TYPE_NONE) { + dev = hw_device_get_by_type(type); + if (!dev) { + av_log(ost->enc_ctx, AV_LOG_WARNING, "No device available " + "for encoder (device type %s for codec %s).\n", + av_hwdevice_get_type_name(type), ost->enc->name); + return 0; + } + ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); + if (!ost->enc_ctx->hw_device_ctx) + return AVERROR(ENOMEM); + return 0; + } else { + // No device required. + return 0; + } +} + +static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input) +{ + InputStream *ist = avctx->opaque; + AVFrame *output = NULL; + enum AVPixelFormat output_format = ist->hwaccel_output_format; + int err; + + if (input->format == output_format) { + // Nothing to do. + return 0; + } + + output = av_frame_alloc(); + if (!output) + return AVERROR(ENOMEM); + + output->format = output_format; + + err = av_hwframe_transfer_data(output, input, 0); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to transfer data to " + "output frame: %d.\n", err); + goto fail; + } + + err = av_frame_copy_props(output, input); + if (err < 0) { + av_frame_unref(output); + goto fail; + } + + av_frame_unref(input); + av_frame_move_ref(input, output); + av_frame_free(&output); + + return 0; + +fail: + av_frame_free(&output); + return err; +} + +int hwaccel_decode_init(AVCodecContext *avctx) +{ + InputStream *ist = avctx->opaque; + + ist->hwaccel_retrieve_data = &hwaccel_retrieve_data; + + return 0; +} diff --git a/avtools/avconv_opt.c b/avtools/avconv_opt.c index e078a0b89ddae..c17bc15895903 100644 --- a/avtools/avconv_opt.c +++ b/avtools/avconv_opt.c @@ -57,19 +57,24 @@ const HWAccel hwaccels[] = { #if HAVE_VDPAU_X11 - { "vdpau", vdpau_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU }, + { "vdpau", vdpau_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU, + AV_HWDEVICE_TYPE_NONE }, #endif #if HAVE_DXVA2_LIB - { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD }, + { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD, + AV_HWDEVICE_TYPE_NONE }, #endif #if CONFIG_VDA - { "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA }, + { "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA, + AV_HWDEVICE_TYPE_NONE }, #endif #if CONFIG_LIBMFX - { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV }, + { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV, + AV_HWDEVICE_TYPE_NONE }, #endif #if CONFIG_VAAPI - { "vaapi", vaapi_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI }, + { "vaapi", vaapi_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI, + AV_HWDEVICE_TYPE_NONE }, #endif { 0 }, }; @@ -337,6 +342,21 @@ static int opt_vaapi_device(void *optctx, const char *opt, const char *arg) } #endif +static int opt_init_hw_device(void *optctx, const char *opt, const char *arg) +{ + if (!strcmp(arg, "list")) { + enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE; + printf("Supported hardware device types:\n"); + while ((type = av_hwdevice_iterate_types(type)) != + AV_HWDEVICE_TYPE_NONE) + printf("%s\n", av_hwdevice_get_type_name(type)); + printf("\n"); + exit_program(0); + } else { + return hw_device_init_from_string(arg, NULL); + } +} + /** * Parse a metadata specifier passed as 'arg' parameter. * @param arg metadata string to parse @@ -2741,5 +2761,8 @@ const OptionDef options[] = { "set VAAPI hardware device (DRM path or X11 display name)", "device" }, #endif + { "init_hw_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_init_hw_device }, + "initialise hardware device", "args" }, + { NULL, }, }; From 62a1ef9f26c654a3e988aa465c4ac1d776c4c356 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:31 +0000 Subject: [PATCH 0051/2557] avconv: Enable generic hwaccel support for VAAPI --- avtools/Makefile | 1 - avtools/avconv.h | 2 - avtools/avconv_opt.c | 20 +++- avtools/avconv_vaapi.c | 231 ----------------------------------------- 4 files changed, 16 insertions(+), 238 deletions(-) delete mode 100644 avtools/avconv_vaapi.c diff --git a/avtools/Makefile b/avtools/Makefile index 8effa995da246..09233dea7e068 100644 --- a/avtools/Makefile +++ b/avtools/Makefile @@ -11,7 +11,6 @@ ALLAVPROGS = $(AVBASENAMES:%=%$(EXESUF)) OBJS-avconv += avtools/avconv_opt.o avtools/avconv_filter.o \ avtools/avconv_hw.o OBJS-avconv-$(CONFIG_LIBMFX) += avtools/avconv_qsv.o -OBJS-avconv-$(CONFIG_VAAPI) += avtools/avconv_vaapi.o OBJS-avconv-$(CONFIG_VDA) += avtools/avconv_vda.o OBJS-avconv-$(HAVE_DXVA2_LIB) += avtools/avconv_dxva2.o OBJS-avconv-$(HAVE_VDPAU_X11) += avtools/avconv_vdpau.o diff --git a/avtools/avconv.h b/avtools/avconv.h index c578e2074b489..4cd846134f145 100644 --- a/avtools/avconv.h +++ b/avtools/avconv.h @@ -515,8 +515,6 @@ int dxva2_init(AVCodecContext *s); int vda_init(AVCodecContext *s); int qsv_init(AVCodecContext *s); int qsv_transcode_init(OutputStream *ost); -int vaapi_decode_init(AVCodecContext *avctx); -int vaapi_device_init(const char *device); HWDevice *hw_device_get_by_name(const char *name); int hw_device_init_from_string(const char *arg, HWDevice **dev); diff --git a/avtools/avconv_opt.c b/avtools/avconv_opt.c index c17bc15895903..09edc1f161ea9 100644 --- a/avtools/avconv_opt.c +++ b/avtools/avconv_opt.c @@ -73,8 +73,8 @@ const HWAccel hwaccels[] = { AV_HWDEVICE_TYPE_NONE }, #endif #if CONFIG_VAAPI - { "vaapi", vaapi_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI, - AV_HWDEVICE_TYPE_NONE }, + { "vaapi", hwaccel_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI, + AV_HWDEVICE_TYPE_VAAPI }, #endif { 0 }, }; @@ -334,10 +334,22 @@ static int opt_attach(void *optctx, const char *opt, const char *arg) #if CONFIG_VAAPI static int opt_vaapi_device(void *optctx, const char *opt, const char *arg) { + HWDevice *dev; + const char *prefix = "vaapi:"; + char *tmp; int err; - err = vaapi_device_init(arg); + tmp = av_malloc(strlen(prefix) + strlen(arg) + 1); + if (!tmp) + return AVERROR(ENOMEM); + strcpy(tmp, prefix); + strcat(tmp, arg); + err = hw_device_init_from_string(tmp, &dev); + av_free(tmp); if (err < 0) - exit_program(1); + return err; + hw_device_ctx = av_buffer_ref(dev->device_ref); + if (!hw_device_ctx) + return AVERROR(ENOMEM); return 0; } #endif diff --git a/avtools/avconv_vaapi.c b/avtools/avconv_vaapi.c deleted file mode 100644 index 584b8b4df0ffe..0000000000000 --- a/avtools/avconv_vaapi.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#include "libavutil/avassert.h" -#include "libavutil/frame.h" -#include "libavutil/hwcontext.h" -#include "libavutil/log.h" - -#include "avconv.h" - - -static AVClass vaapi_class = { - .class_name = "vaapi", - .item_name = av_default_item_name, - .version = LIBAVUTIL_VERSION_INT, -}; - -#define DEFAULT_SURFACES 20 - -typedef struct VAAPIDecoderContext { - const AVClass *class; - - AVBufferRef *device_ref; - AVHWDeviceContext *device; - AVBufferRef *frames_ref; - AVHWFramesContext *frames; - - // The output need not have the same format, width and height as the - // decoded frames - the copy for non-direct-mapped access is actually - // a whole vpp instance which can do arbitrary scaling and format - // conversion. - enum AVPixelFormat output_format; -} VAAPIDecoderContext; - - -static int vaapi_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) -{ - InputStream *ist = avctx->opaque; - VAAPIDecoderContext *ctx = ist->hwaccel_ctx; - int err; - - err = av_hwframe_get_buffer(ctx->frames_ref, frame, 0); - if (err < 0) { - av_log(ctx, AV_LOG_ERROR, "Failed to allocate decoder surface.\n"); - } else { - av_log(ctx, AV_LOG_DEBUG, "Decoder given surface %#x.\n", - (unsigned int)(uintptr_t)frame->data[3]); - } - return err; -} - -static int vaapi_retrieve_data(AVCodecContext *avctx, AVFrame *input) -{ - InputStream *ist = avctx->opaque; - VAAPIDecoderContext *ctx = ist->hwaccel_ctx; - AVFrame *output = 0; - int err; - - av_assert0(input->format == AV_PIX_FMT_VAAPI); - - if (ctx->output_format == AV_PIX_FMT_VAAPI) { - // Nothing to do. - return 0; - } - - av_log(ctx, AV_LOG_DEBUG, "Retrieve data from surface %#x.\n", - (unsigned int)(uintptr_t)input->data[3]); - - output = av_frame_alloc(); - if (!output) - return AVERROR(ENOMEM); - - output->format = ctx->output_format; - - err = av_hwframe_transfer_data(output, input, 0); - if (err < 0) { - av_log(ctx, AV_LOG_ERROR, "Failed to transfer data to " - "output frame: %d.\n", err); - goto fail; - } - - err = av_frame_copy_props(output, input); - if (err < 0) { - av_frame_unref(output); - goto fail; - } - - av_frame_unref(input); - av_frame_move_ref(input, output); - av_frame_free(&output); - - return 0; - -fail: - if (output) - av_frame_free(&output); - return err; -} - -static void vaapi_decode_uninit(AVCodecContext *avctx) -{ - InputStream *ist = avctx->opaque; - VAAPIDecoderContext *ctx = ist->hwaccel_ctx; - - if (ctx) { - av_buffer_unref(&ctx->frames_ref); - av_buffer_unref(&ctx->device_ref); - av_free(ctx); - } - - av_buffer_unref(&ist->hw_frames_ctx); - - ist->hwaccel_ctx = NULL; - ist->hwaccel_uninit = NULL; - ist->hwaccel_get_buffer = NULL; - ist->hwaccel_retrieve_data = NULL; -} - -int vaapi_decode_init(AVCodecContext *avctx) -{ - InputStream *ist = avctx->opaque; - VAAPIDecoderContext *ctx; - int err; - int loglevel = (ist->hwaccel_id != HWACCEL_VAAPI ? AV_LOG_VERBOSE - : AV_LOG_ERROR); - - if (ist->hwaccel_ctx) - vaapi_decode_uninit(avctx); - - // We have -hwaccel without -vaapi_device, so just initialise here with - // the device passed as -hwaccel_device (if -vaapi_device was passed, it - // will always have been called before now). - if (!hw_device_ctx) { - err = vaapi_device_init(ist->hwaccel_device); - if (err < 0) - return err; - } - - ctx = av_mallocz(sizeof(*ctx)); - if (!ctx) - return AVERROR(ENOMEM); - ctx->class = &vaapi_class; - - ctx->device_ref = av_buffer_ref(hw_device_ctx); - ctx->device = (AVHWDeviceContext*)ctx->device_ref->data; - - ctx->output_format = ist->hwaccel_output_format; - avctx->pix_fmt = ctx->output_format; - - ctx->frames_ref = av_hwframe_ctx_alloc(ctx->device_ref); - if (!ctx->frames_ref) { - av_log(ctx, loglevel, "Failed to create VAAPI frame context.\n"); - err = AVERROR(ENOMEM); - goto fail; - } - - ctx->frames = (AVHWFramesContext*)ctx->frames_ref->data; - - ctx->frames->format = AV_PIX_FMT_VAAPI; - ctx->frames->width = avctx->coded_width; - ctx->frames->height = avctx->coded_height; - - // It would be nice if we could query the available formats here, - // but unfortunately we don't have a VAConfigID to do it with. - // For now, just assume an NV12 format (or P010 if 10-bit). - ctx->frames->sw_format = (avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? - AV_PIX_FMT_P010 : AV_PIX_FMT_NV12); - - // For frame-threaded decoding, at least one additional surface - // is needed for each thread. - ctx->frames->initial_pool_size = DEFAULT_SURFACES; - if (avctx->active_thread_type & FF_THREAD_FRAME) - ctx->frames->initial_pool_size += avctx->thread_count; - - err = av_hwframe_ctx_init(ctx->frames_ref); - if (err < 0) { - av_log(ctx, loglevel, "Failed to initialise VAAPI frame " - "context: %d\n", err); - goto fail; - } - - ist->hw_frames_ctx = av_buffer_ref(ctx->frames_ref); - if (!ist->hw_frames_ctx) { - err = AVERROR(ENOMEM); - goto fail; - } - - ist->hwaccel_ctx = ctx; - ist->hwaccel_uninit = &vaapi_decode_uninit; - ist->hwaccel_get_buffer = &vaapi_get_buffer; - ist->hwaccel_retrieve_data = &vaapi_retrieve_data; - - return 0; - -fail: - vaapi_decode_uninit(avctx); - return err; -} - -static AVClass *vaapi_log = &vaapi_class; - -av_cold int vaapi_device_init(const char *device) -{ - int err; - - err = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI, - device, NULL, 0); - if (err < 0) { - av_log(&vaapi_log, AV_LOG_ERROR, "Failed to create a VAAPI device\n"); - return err; - } - - return 0; -} From 16a163b55a6558ed05702b91cc0777987295ef21 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 4 Mar 2017 23:57:32 +0000 Subject: [PATCH 0052/2557] lavc: Add hwaccel_flags field to AVCodecContext This "reuses" the flags introduced for the av_vdpau_bind_context() API function, and makes them available to all hwaccels. This does not affect the current vdpau API, as av_vdpau_bind_context() should obviously override the AVCodecContext.hwaccel_flags flags for the sake of compatibility. --- doc/APIchanges | 4 ++++ libavcodec/avcodec.h | 9 +++++++++ libavcodec/pthread_frame.c | 2 ++ libavcodec/version.h | 2 +- 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 70b3391988eb2..c6a5d82b99136 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,10 @@ libavutil: 2015-08-28 API changes, most recent first: +2017-03-xx - xxxxxxx - lavc 57.37.0 - avcodec.h + Add AVCodecContext.hwaccel_flags field. This will control some hwaccels at + a later point. + 2017-03-xx - xxxxxxx - lavu 55.35.0 - hwcontext.h Add AV_HWDEVICE_TYPE_NONE, av_hwdevice_find_type_by_name(), av_hwdevice_get_type_name() and av_hwdevice_iterate_types(). diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 62a4fab8f93aa..1e2b13e0d79b6 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3186,6 +3186,15 @@ typedef struct AVCodecContext { * contexts used must be created on the same device. */ AVBufferRef *hw_device_ctx; + + /** + * Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated + * decoding (if active). + * - encoding: unused + * - decoding: Set by user (either before avcodec_open2(), or in the + * AVCodecContext.get_format callback) + */ + int hwaccel_flags; } AVCodecContext; /** diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index f3a74c0bd84da..65a04d8e90949 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -270,6 +270,8 @@ FF_ENABLE_DEPRECATION_WARNINGS return AVERROR(ENOMEM); } } + + dst->hwaccel_flags = src->hwaccel_flags; } if (for_user) { diff --git a/libavcodec/version.h b/libavcodec/version.h index 443cc8204aa50..349b2e9f6a887 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 57 -#define LIBAVCODEC_VERSION_MINOR 36 +#define LIBAVCODEC_VERSION_MINOR 37 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From 1a7ddba5762b6c31d1338140550cd594b6d7d48b Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 4 Mar 2017 23:57:33 +0000 Subject: [PATCH 0053/2557] lavc: vdpau: add support for new hw_frames_ctx and hw_device_ctx API This supports retrieving the device from a provided hw_frames_ctx, and automatically creating a hw_frames_ctx if hw_device_ctx is set. The old API is not deprecated yet. The user can still use av_vdpau_bind_context() (with or without setting hw_frames_ctx), or use the API before that by allocating and setting hwaccel_context manually. --- libavcodec/vdpau.c | 85 ++++++++++++++++++++++++++++--------- libavcodec/vdpau_internal.h | 2 + libavcodec/version.h | 2 +- 3 files changed, 69 insertions(+), 20 deletions(-) diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c index d3cb188d7422d..68d0813f658d9 100644 --- a/libavcodec/vdpau.c +++ b/libavcodec/vdpau.c @@ -118,29 +118,76 @@ int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile, vdctx->width = UINT32_MAX; vdctx->height = UINT32_MAX; - hwctx->reset = 0; - if (hwctx->context.decoder != VDP_INVALID_HANDLE) { - vdctx->decoder = hwctx->context.decoder; - vdctx->render = hwctx->context.render; - vdctx->device = VDP_INVALID_HANDLE; - return 0; /* Decoder created by user */ - } + if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height)) + return AVERROR(ENOSYS); - vdctx->device = hwctx->device; - vdctx->get_proc_address = hwctx->get_proc_address; + if (hwctx) { + hwctx->reset = 0; - if (hwctx->flags & AV_HWACCEL_FLAG_IGNORE_LEVEL) - level = 0; - else if (level < 0) - return AVERROR(ENOTSUP); + if (hwctx->context.decoder != VDP_INVALID_HANDLE) { + vdctx->decoder = hwctx->context.decoder; + vdctx->render = hwctx->context.render; + vdctx->device = VDP_INVALID_HANDLE; + return 0; /* Decoder created by user */ + } - if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height)) - return AVERROR(ENOSYS); + vdctx->device = hwctx->device; + vdctx->get_proc_address = hwctx->get_proc_address; + + if (hwctx->flags & AV_HWACCEL_FLAG_IGNORE_LEVEL) + level = 0; + + if (!(hwctx->flags & AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH) && + type != VDP_CHROMA_TYPE_420) + return AVERROR(ENOSYS); + } else { + AVHWFramesContext *frames_ctx = NULL; + AVVDPAUDeviceContext *dev_ctx; + + // We assume the hw_frames_ctx always survives until ff_vdpau_common_uninit + // is called. This holds true as the user is not allowed to touch + // hw_device_ctx, or hw_frames_ctx after get_format (and ff_get_format + // itself also uninits before unreffing hw_frames_ctx). + if (avctx->hw_frames_ctx) { + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + } else if (avctx->hw_device_ctx) { + int ret; + + avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); + if (!avctx->hw_frames_ctx) + return AVERROR(ENOMEM); + + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + frames_ctx->format = AV_PIX_FMT_VDPAU; + frames_ctx->sw_format = avctx->sw_pix_fmt; + frames_ctx->width = avctx->coded_width; + frames_ctx->height = avctx->coded_height; + + ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); + if (ret < 0) { + av_buffer_unref(&avctx->hw_frames_ctx); + return ret; + } + } - if (!(hwctx->flags & AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH) && - type != VDP_CHROMA_TYPE_420) - return AVERROR(ENOSYS); + if (!frames_ctx) { + av_log(avctx, AV_LOG_ERROR, "A hardware frames context is " + "required for VDPAU decoding.\n"); + return AVERROR(EINVAL); + } + + dev_ctx = frames_ctx->device_ctx->hwctx; + + vdctx->device = dev_ctx->device; + vdctx->get_proc_address = dev_ctx->get_proc_address; + + if (avctx->hwaccel_flags & AV_HWACCEL_FLAG_IGNORE_LEVEL) + level = 0; + } + + if (level < 0) + return AVERROR(ENOTSUP); status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, @@ -238,7 +285,7 @@ static int ff_vdpau_common_reinit(AVCodecContext *avctx) if (vdctx->device == VDP_INVALID_HANDLE) return 0; /* Decoder created by user */ if (avctx->coded_width == vdctx->width && - avctx->coded_height == vdctx->height && !hwctx->reset) + avctx->coded_height == vdctx->height && (!hwctx || !hwctx->reset)) return 0; avctx->hwaccel->uninit(avctx); diff --git a/libavcodec/vdpau_internal.h b/libavcodec/vdpau_internal.h index c7281a6b5e6d7..a0eb46c48ed35 100644 --- a/libavcodec/vdpau_internal.h +++ b/libavcodec/vdpau_internal.h @@ -28,6 +28,8 @@ #include #include "libavutil/frame.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_vdpau.h" #include "avcodec.h" #include "vdpau.h" diff --git a/libavcodec/version.h b/libavcodec/version.h index 349b2e9f6a887..f169793c15c30 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 57 #define LIBAVCODEC_VERSION_MINOR 37 -#define LIBAVCODEC_VERSION_MICRO 0 +#define LIBAVCODEC_VERSION_MICRO 1 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From aa6b2e081c504cb99f5e2e0ceb45295ef24bdac2 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:34 +0000 Subject: [PATCH 0054/2557] avconv: Enable generic hwaccel support for VDPAU --- avtools/Makefile | 1 - avtools/avconv.h | 1 - avtools/avconv_opt.c | 4 +- avtools/avconv_vdpau.c | 159 ----------------------------------------- 4 files changed, 2 insertions(+), 163 deletions(-) delete mode 100644 avtools/avconv_vdpau.c diff --git a/avtools/Makefile b/avtools/Makefile index 09233dea7e068..c23a605a5522e 100644 --- a/avtools/Makefile +++ b/avtools/Makefile @@ -13,7 +13,6 @@ OBJS-avconv += avtools/avconv_opt.o avtools/avconv_filter.o \ OBJS-avconv-$(CONFIG_LIBMFX) += avtools/avconv_qsv.o OBJS-avconv-$(CONFIG_VDA) += avtools/avconv_vda.o OBJS-avconv-$(HAVE_DXVA2_LIB) += avtools/avconv_dxva2.o -OBJS-avconv-$(HAVE_VDPAU_X11) += avtools/avconv_vdpau.o define DOAVTOOL OBJS-$(1) += avtools/cmdutils.o avtools/$(1).o $(OBJS-$(1)-yes) diff --git a/avtools/avconv.h b/avtools/avconv.h index 4cd846134f145..9415b208be42e 100644 --- a/avtools/avconv.h +++ b/avtools/avconv.h @@ -510,7 +510,6 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); int avconv_parse_options(int argc, char **argv); -int vdpau_init(AVCodecContext *s); int dxva2_init(AVCodecContext *s); int vda_init(AVCodecContext *s); int qsv_init(AVCodecContext *s); diff --git a/avtools/avconv_opt.c b/avtools/avconv_opt.c index 09edc1f161ea9..e970c8e46c305 100644 --- a/avtools/avconv_opt.c +++ b/avtools/avconv_opt.c @@ -57,8 +57,8 @@ const HWAccel hwaccels[] = { #if HAVE_VDPAU_X11 - { "vdpau", vdpau_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU, - AV_HWDEVICE_TYPE_NONE }, + { "vdpau", hwaccel_decode_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU, + AV_HWDEVICE_TYPE_VDPAU }, #endif #if HAVE_DXVA2_LIB { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD, diff --git a/avtools/avconv_vdpau.c b/avtools/avconv_vdpau.c deleted file mode 100644 index 5fedceef9556b..0000000000000 --- a/avtools/avconv_vdpau.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "avconv.h" - -#include "libavcodec/vdpau.h" - -#include "libavutil/buffer.h" -#include "libavutil/frame.h" -#include "libavutil/hwcontext.h" -#include "libavutil/hwcontext_vdpau.h" -#include "libavutil/pixfmt.h" - -typedef struct VDPAUContext { - AVBufferRef *hw_frames_ctx; - AVFrame *tmp_frame; -} VDPAUContext; - -static void vdpau_uninit(AVCodecContext *s) -{ - InputStream *ist = s->opaque; - VDPAUContext *ctx = ist->hwaccel_ctx; - - ist->hwaccel_uninit = NULL; - ist->hwaccel_get_buffer = NULL; - ist->hwaccel_retrieve_data = NULL; - - av_buffer_unref(&ctx->hw_frames_ctx); - av_frame_free(&ctx->tmp_frame); - - av_freep(&ist->hwaccel_ctx); - av_freep(&s->hwaccel_context); -} - -static int vdpau_get_buffer(AVCodecContext *s, AVFrame *frame, int flags) -{ - InputStream *ist = s->opaque; - VDPAUContext *ctx = ist->hwaccel_ctx; - - return av_hwframe_get_buffer(ctx->hw_frames_ctx, frame, 0); -} - -static int vdpau_retrieve_data(AVCodecContext *s, AVFrame *frame) -{ - InputStream *ist = s->opaque; - VDPAUContext *ctx = ist->hwaccel_ctx; - int ret; - - ret = av_hwframe_transfer_data(ctx->tmp_frame, frame, 0); - if (ret < 0) - return ret; - - ret = av_frame_copy_props(ctx->tmp_frame, frame); - if (ret < 0) { - av_frame_unref(ctx->tmp_frame); - return ret; - } - - av_frame_unref(frame); - av_frame_move_ref(frame, ctx->tmp_frame); - - return 0; -} - -static int vdpau_alloc(AVCodecContext *s) -{ - InputStream *ist = s->opaque; - int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; - VDPAUContext *ctx; - int ret; - - AVBufferRef *device_ref = NULL; - AVHWDeviceContext *device_ctx; - AVVDPAUDeviceContext *device_hwctx; - AVHWFramesContext *frames_ctx; - - ctx = av_mallocz(sizeof(*ctx)); - if (!ctx) - return AVERROR(ENOMEM); - - ist->hwaccel_ctx = ctx; - ist->hwaccel_uninit = vdpau_uninit; - ist->hwaccel_get_buffer = vdpau_get_buffer; - ist->hwaccel_retrieve_data = vdpau_retrieve_data; - - ctx->tmp_frame = av_frame_alloc(); - if (!ctx->tmp_frame) - goto fail; - - ret = av_hwdevice_ctx_create(&device_ref, AV_HWDEVICE_TYPE_VDPAU, - ist->hwaccel_device, NULL, 0); - if (ret < 0) - goto fail; - device_ctx = (AVHWDeviceContext*)device_ref->data; - device_hwctx = device_ctx->hwctx; - - ctx->hw_frames_ctx = av_hwframe_ctx_alloc(device_ref); - if (!ctx->hw_frames_ctx) - goto fail; - av_buffer_unref(&device_ref); - - frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; - frames_ctx->format = AV_PIX_FMT_VDPAU; - frames_ctx->sw_format = s->sw_pix_fmt; - frames_ctx->width = s->coded_width; - frames_ctx->height = s->coded_height; - - ret = av_hwframe_ctx_init(ctx->hw_frames_ctx); - if (ret < 0) - goto fail; - - if (av_vdpau_bind_context(s, device_hwctx->device, device_hwctx->get_proc_address, 0)) - goto fail; - - av_log(NULL, AV_LOG_VERBOSE, "Using VDPAU to decode input stream #%d:%d.\n", - ist->file_index, ist->st->index); - - return 0; - -fail: - av_log(NULL, loglevel, "VDPAU init failed for stream #%d:%d.\n", - ist->file_index, ist->st->index); - av_buffer_unref(&device_ref); - vdpau_uninit(s); - return AVERROR(EINVAL); -} - -int vdpau_init(AVCodecContext *s) -{ - InputStream *ist = s->opaque; - - if (!ist->hwaccel_ctx) { - int ret = vdpau_alloc(s); - if (ret < 0) - return ret; - } - - ist->hwaccel_get_buffer = vdpau_get_buffer; - ist->hwaccel_retrieve_data = vdpau_retrieve_data; - - return 0; -} From 303fadf5963e01b8edf4ba2701e45f7e9e586aeb Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 19 Mar 2017 16:25:37 +0000 Subject: [PATCH 0055/2557] avconv: Document the -init_hw_device option --- doc/avconv.texi | 85 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/doc/avconv.texi b/doc/avconv.texi index 6f1fbc79b2ff7..7bcb7879795bc 100644 --- a/doc/avconv.texi +++ b/doc/avconv.texi @@ -594,6 +594,56 @@ The timestamps must be specified in ascending order. When doing stream copy, copy also non-key frames found at the beginning. +@item -init_hw_device @var{type}[=@var{name}][:@var{device}[,@var{key=value}...]] +Initialise a new hardware device of type @var{type} called @var{name}, using the +given device parameters. +If no name is specified it will receive a default name of the form "@var{type}%d". + +The meaning of @var{device} and the following arguments depends on the +device type: +@table @option + +@item cuda +@var{device} is the number of the CUDA device. + +@item dxva2 +@var{device} is the number of the Direct3D 9 display adapter. + +@item vaapi +@var{device} is either an X11 display name or a DRM render node. +If not specified, it will attempt to open the default X11 display (@emph{$DISPLAY}) +and then the first DRM render node (@emph{/dev/dri/renderD128}). + +@item vdpau +@var{device} is an X11 display name. +If not specified, it will attempt to open the default X11 display (@emph{$DISPLAY}). + +@item qsv +@var{device} selects a value in @samp{MFX_IMPL_*}. Allowed values are: +@table @option +@item auto +@item sw +@item hw +@item auto_any +@item hw_any +@item hw2 +@item hw3 +@item hw4 +@end table +If not specified, @samp{auto_any} is used. +(Note that it may be easier to achieve the desired result for QSV by creating the +platform-appropriate subdevice (@samp{dxva2} or @samp{vaapi}) and then deriving a +QSV device from that.) + +@end table + +@item -init_hw_device @var{type}[=@var{name}]@@@var{source} +Initialise a new hardware device of type @var{type} called @var{name}, +deriving it from the existing device with the name @var{source}. + +@item -init_hw_device list +List all hardware device types supported in this build of avconv. + @item -hwaccel[:@var{stream_specifier}] @var{hwaccel} (@emph{input,per-stream}) Use hardware acceleration to decode the matching stream(s). The allowed values of @var{hwaccel} are: @@ -613,6 +663,9 @@ Use VDPAU (Video Decode and Presentation API for Unix) hardware acceleration. @item dxva2 Use DXVA2 (DirectX Video Acceleration) hardware acceleration. +@item vaapi +Use VAAPI (Video Acceleration API) hardware acceleration. + @item qsv Use the Intel QuickSync Video acceleration for video transcoding. @@ -636,33 +689,11 @@ useful for testing. @item -hwaccel_device[:@var{stream_specifier}] @var{hwaccel_device} (@emph{input,per-stream}) Select a device to use for hardware acceleration. -This option only makes sense when the @option{-hwaccel} option is also -specified. Its exact meaning depends on the specific hardware acceleration -method chosen. - -@table @option -@item vdpau -For VDPAU, this option specifies the X11 display/screen to use. If this option -is not specified, the value of the @var{DISPLAY} environment variable is used - -@item dxva2 -For DXVA2, this option should contain the number of the display adapter to use. -If this option is not specified, the default adapter is used. - -@item qsv -For QSV, this option corresponds to the values of MFX_IMPL_* . Allowed values -are: -@table @option -@item auto -@item sw -@item hw -@item auto_any -@item hw_any -@item hw2 -@item hw3 -@item hw4 -@end table -@end table +This option only makes sense when the @option{-hwaccel} option is also specified. +It can either refer to an existing device created with @option{-init_hw_device} +by name, or it can create a new device as if +@samp{-init_hw_device} @var{type}:@var{hwaccel_device} +were called immediately before. @item -hwaccels List all hardware acceleration methods supported in this build of avconv. From bd805964f40f7af83da64645ba83d1e8060a1214 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 14 Mar 2017 23:42:37 +0100 Subject: [PATCH 0056/2557] configure: Do not treat JACK as a system library JACK is not commonly installed and should not be picked up as a dependency unless specifically requested. --- configure | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 665df2762192f..1c7887209ed2e 100755 --- a/configure +++ b/configure @@ -203,6 +203,7 @@ External library support: --enable-libgsm GSM audio encoding/decoding --enable-libhdcd HDCD decoding filter --enable-libilbc ILBC audio encoding/decoding + --enable-libjack JACK audio sound server --enable-libkvazaar HEVC video encoding --enable-libmp3lame MP3 audio encoding --enable-libopencore-amrnb AMR-NB audio encoding/decoding @@ -1315,6 +1316,7 @@ EXTERNAL_LIBRARY_LIST=" libgsm libhdcd libilbc + libjack libkvazaar libmp3lame libopencv @@ -2418,7 +2420,7 @@ bktr_indev_deps_any="dev_bktr_ioctl_bt848_h machine_ioctl_bt848_h dev_video_bktr dv1394_indev_deps="dv1394" dv1394_indev_select="dv_demuxer" fbdev_indev_deps="linux_fb_h" -jack_indev_deps="jack" +jack_indev_deps="libjack" jack_indev_deps_any="sem_timedwait dispatch_dispatch_h" libcdio_indev_deps="libcdio" libdc1394_indev_deps="libdc1394" @@ -4836,8 +4838,10 @@ check_header soundcard.h enabled_any alsa_indev alsa_outdev && check_lib alsa alsa/asoundlib.h snd_pcm_htimestamp -lasound -enabled jack_indev && check_lib jack jack/jack.h jack_client_open -ljack && - check_func jack_port_get_latency_range -ljack +if enabled libjack; then + check_pkg_config libjack jack jack/jack.h jack_port_get_latency_range || + require_pkg_config libjack jack jack/jack.h jack_client_open +fi enabled_any sndio_indev sndio_outdev && check_lib sndio sndio.h sio_open -lsndio From ca960161f087ca38267b88ce90592010c59584f1 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 14 Mar 2017 17:44:45 +0100 Subject: [PATCH 0057/2557] rtsp: Move message parsing to a separate function Make easier to handle the polling function before we implement full threading support. --- libavformat/rtsp.c | 57 ++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 141477bbbfee4..fb6203d585912 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1907,12 +1907,39 @@ int ff_rtsp_connect(AVFormatContext *s) #endif /* CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER */ #if CONFIG_RTPDEC +static int parse_rtsp_message(AVFormatContext *s) +{ + RTSPState *rt = s->priv_data; + int ret; + + if (rt->rtsp_flags & RTSP_FLAG_LISTEN) { + if (rt->state == RTSP_STATE_STREAMING) { + if (!ff_rtsp_parse_streaming_commands(s)) + return AVERROR_EOF; + else + av_log(s, AV_LOG_WARNING, + "Unable to answer to TEARDOWN\n"); + } else + return 0; + } else { + RTSPMessageHeader reply; + ret = ff_rtsp_read_reply(s, &reply, NULL, 0, NULL); + if (ret < 0) + return ret; + /* XXX: parse message */ + if (rt->state != RTSP_STATE_STREAMING) + return 0; + } + + return 0; +} + static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, uint8_t *buf, int buf_size, int64_t wait_end) { RTSPState *rt = s->priv_data; RTSPStream *rtsp_st; - int n, i, ret, tcp_fd, timeout_cnt = 0; + int n, i, ret, timeout_cnt = 0; struct pollfd *p = rt->p; int *fds = NULL, fdsnum, fdsidx; @@ -1922,11 +1949,8 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, return AVERROR(ENOMEM); if (rt->rtsp_hd) { - tcp_fd = ffurl_get_file_handle(rt->rtsp_hd); - p[rt->max_p].fd = tcp_fd; + p[rt->max_p].fd = ffurl_get_file_handle(rt->rtsp_hd); p[rt->max_p++].events = POLLIN; - } else { - tcp_fd = -1; } for (i = 0; i < rt->nb_rtsp_streams; i++) { rtsp_st = rt->rtsp_streams[i]; @@ -1957,7 +1981,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, return AVERROR(EAGAIN); n = poll(p, rt->max_p, POLL_TIMEOUT_MS); if (n > 0) { - int j = 1 - (tcp_fd == -1); + int j = rt->rtsp_hd ? 1 : 0; timeout_cnt = 0; for (i = 0; i < rt->nb_rtsp_streams; i++) { rtsp_st = rt->rtsp_streams[i]; @@ -1973,25 +1997,8 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, } } #if CONFIG_RTSP_DEMUXER - if (tcp_fd != -1 && p[0].revents & POLLIN) { - if (rt->rtsp_flags & RTSP_FLAG_LISTEN) { - if (rt->state == RTSP_STATE_STREAMING) { - if (!ff_rtsp_parse_streaming_commands(s)) - return AVERROR_EOF; - else - av_log(s, AV_LOG_WARNING, - "Unable to answer to TEARDOWN\n"); - } else - return 0; - } else { - RTSPMessageHeader reply; - ret = ff_rtsp_read_reply(s, &reply, NULL, 0, NULL); - if (ret < 0) - return ret; - /* XXX: parse message */ - if (rt->state != RTSP_STATE_STREAMING) - return 0; - } + if (rt->rtsp_hd && p[0].revents & POLLIN) { + return parse_rtsp_message(s); } #endif } else if (n == 0 && ++timeout_cnt >= MAX_TIMEOUTS) { From 3df77b58e35a30ed550f99936a308f6bd2f47a20 Mon Sep 17 00:00:00 2001 From: Konda Raju Date: Fri, 17 Mar 2017 09:40:05 +0530 Subject: [PATCH 0058/2557] nvenc: Allow different const qps for I, P and B frames Signed-off-by: Luca Barbato --- libavcodec/nvenc.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 2e76ee870d495..f16e509df35ea 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -511,10 +511,26 @@ static int nvenc_map_preset(NVENCContext *ctx) static void set_constqp(AVCodecContext *avctx, NV_ENC_RC_PARAMS *rc) { + NVENCContext *ctx = avctx->priv_data; rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP; - rc->constQP.qpInterB = avctx->global_quality; - rc->constQP.qpInterP = avctx->global_quality; - rc->constQP.qpIntra = avctx->global_quality; + + if (ctx->init_qp_p >= 0) { + rc->constQP.qpInterP = ctx->init_qp_p; + if (ctx->init_qp_i >= 0 && ctx->init_qp_b >= 0) { + rc->constQP.qpIntra = ctx->init_qp_i; + rc->constQP.qpInterB = ctx->init_qp_b; + } else if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) { + rc->constQP.qpIntra = av_clip(rc->constQP.qpInterP * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, 51); + rc->constQP.qpInterB = av_clip(rc->constQP.qpInterP * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, 51); + } else { + rc->constQP.qpIntra = rc->constQP.qpInterP; + rc->constQP.qpInterB = rc->constQP.qpInterP; + } + } else if (avctx->global_quality >= 0) { + rc->constQP.qpInterP = avctx->global_quality; + rc->constQP.qpInterB = avctx->global_quality; + rc->constQP.qpIntra = avctx->global_quality; + } } static void set_vbr(AVCodecContext *avctx, NV_ENC_RC_PARAMS *rc) @@ -575,12 +591,6 @@ static void nvenc_override_rate_control(AVCodecContext *avctx, switch (ctx->rc) { case NV_ENC_PARAMS_RC_CONSTQP: - if (avctx->global_quality < 0) { - av_log(avctx, AV_LOG_WARNING, - "The constant quality rate-control requires " - "the 'global_quality' option set.\n"); - return; - } set_constqp(avctx, rc); return; case NV_ENC_PARAMS_RC_2_PASS_VBR: From e245d4f45ca5e2b97daef5944d63323c07d545bc Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 14 Mar 2017 09:15:29 +0000 Subject: [PATCH 0059/2557] dca: Validate the channel map Having a mismatch between the number of channels in the stream and those in the channel map will lead to a segfault or worse. Bug-Id: 1016 CC: libav-stable@libav.org Signed-off-by: Luca Barbato --- libavcodec/dcadec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c index cd4432368c195..af26dceafdc47 100644 --- a/libavcodec/dcadec.c +++ b/libavcodec/dcadec.c @@ -1297,6 +1297,9 @@ static int set_channel_layout(AVCodecContext *avctx, int channels, int num_core_ s->channel_order_tab = ff_dca_channel_reorder_nolfe[s->amode]; } + if (channels < ff_dca_channels[s->amode]) + return AVERROR_INVALIDDATA; + if (channels > !!s->lfe && s->channel_order_tab[channels - 1 - !!s->lfe] < 0) return AVERROR_INVALIDDATA; From a46a4f722d2fac07c57990f0f548777622599f59 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 14 Mar 2017 09:15:30 +0000 Subject: [PATCH 0060/2557] dca: Refactor dca_filter_channels() a little Signed-off-by: Luca Barbato --- libavcodec/dcadec.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c index af26dceafdc47..fa2a2400feaa1 100644 --- a/libavcodec/dcadec.c +++ b/libavcodec/dcadec.c @@ -947,15 +947,16 @@ static int dca_filter_channels(DCAContext *s, int block_index, int upsample) /* 64 subbands QMF */ for (k = 0; k < s->audio_header.prim_channels; k++) { + int channel = s->channel_order_tab[k]; int32_t (*subband_samples)[SAMPLES_PER_SUBBAND] = s->dca_chan[k].subband_samples[block_index]; s->fmt_conv.int32_to_float(samples[0], subband_samples[0], DCA_SUBBANDS_X96K * SAMPLES_PER_SUBBAND); - if (s->channel_order_tab[k] >= 0) + if (channel >= 0) qmf_64_subbands(s, k, samples, - s->samples_chanptr[s->channel_order_tab[k]], + s->samples_chanptr[channel], /* Upsampling needs a factor 2 here. */ M_SQRT2 / 32768.0); } @@ -964,15 +965,16 @@ static int dca_filter_channels(DCAContext *s, int block_index, int upsample) LOCAL_ALIGNED(32, float, samples, [DCA_SUBBANDS], [SAMPLES_PER_SUBBAND]); for (k = 0; k < s->audio_header.prim_channels; k++) { + int channel = s->channel_order_tab[k]; int32_t (*subband_samples)[SAMPLES_PER_SUBBAND] = s->dca_chan[k].subband_samples[block_index]; s->fmt_conv.int32_to_float(samples[0], subband_samples[0], DCA_SUBBANDS * SAMPLES_PER_SUBBAND); - if (s->channel_order_tab[k] >= 0) + if (channel >= 0) qmf_32_subbands(s, k, samples, - s->samples_chanptr[s->channel_order_tab[k]], + s->samples_chanptr[channel], M_SQRT1_2 / 32768.0); } } From 3aa9c523e9cf4f4a5e239ac737281e096c884907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 21 Mar 2017 14:26:27 +0200 Subject: [PATCH 0061/2557] libavutil: Define the noreturn attribute for clang in MSVC mode as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a follow-up to f637046d313. Without the noreturn attribute set, avconv_opt.c fails to build after d2e6dd32a44 with the error "control may reach end of non-void function". By making sure the noreturn attribute is set properly, this compiles as intended. Signed-off-by: Martin Storsjö --- libavutil/attributes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/attributes.h b/libavutil/attributes.h index c770f52a432de..cd4e299531a8c 100644 --- a/libavutil/attributes.h +++ b/libavutil/attributes.h @@ -117,7 +117,7 @@ # define av_printf_format(fmtpos, attrpos) #endif -#if AV_GCC_VERSION_AT_LEAST(2,5) +#if AV_GCC_VERSION_AT_LEAST(2,5) || defined(__clang__) # define av_noreturn __attribute__((noreturn)) #else # define av_noreturn From 8e2346154e6d58b733fd20326ce706f82fd91b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 21 Mar 2017 14:36:33 +0200 Subject: [PATCH 0062/2557] libavutil: Hook up the rest of the gcc specific attributes to clang as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hook up all attributes that don't have a MSVC specific version at the moment. See f637046d313 for details. These don't seem to be critical for building with clang in MSVC mode though, and thus haven't been hooked up until now. These seem to build fine with as old clang as 3.3 at least. (clang 3.3 disguises itself as gcc 4.2 normally, so all of these have been used for clang before, except for av_cold.) The clang version numbers themselves are useless for detecting what attributes are available, since Apple's clang builds use a completely different versioning (presenting itself as e.g. clang 8.0 instead of 3.8). Signed-off-by: Martin Storsjö --- libavutil/attributes.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavutil/attributes.h b/libavutil/attributes.h index cd4e299531a8c..053acd02e67c2 100644 --- a/libavutil/attributes.h +++ b/libavutil/attributes.h @@ -48,19 +48,19 @@ # define av_noinline #endif -#if AV_GCC_VERSION_AT_LEAST(3,1) +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) # define av_pure __attribute__((pure)) #else # define av_pure #endif -#if AV_GCC_VERSION_AT_LEAST(2,6) +#if AV_GCC_VERSION_AT_LEAST(2,6) || defined(__clang__) # define av_const __attribute__((const)) #else # define av_const #endif -#if AV_GCC_VERSION_AT_LEAST(4,3) +#if AV_GCC_VERSION_AT_LEAST(4,3) || defined(__clang__) # define av_cold __attribute__((cold)) #else # define av_cold @@ -97,19 +97,19 @@ # define av_used #endif -#if AV_GCC_VERSION_AT_LEAST(3,3) +#if AV_GCC_VERSION_AT_LEAST(3,3) || defined(__clang__) # define av_alias __attribute__((may_alias)) #else # define av_alias #endif -#if defined(__GNUC__) && !defined(__ICC) +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__ICC) # define av_uninit(x) x=x #else # define av_uninit(x) x #endif -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) # define av_builtin_constant_p __builtin_constant_p # define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos))) #else From 628ce8b8b6b80cb3985d39e195b71b9d7fad9008 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Fri, 25 Nov 2016 11:06:14 +0100 Subject: [PATCH 0063/2557] flvdec: Set avg_frame_rate for video streams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/flvdec.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index b82ea3303bfe8..693c859ebfa70 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -58,6 +58,7 @@ typedef struct FLVContext { int validate_next; int validate_count; int searched_for_end; + AVRational framerate; } FLVContext; static int flv_probe(AVProbeData *p) @@ -77,10 +78,14 @@ static int flv_probe(AVProbeData *p) static AVStream *create_stream(AVFormatContext *s, int codec_type) { + FLVContext *flv = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); if (!st) return NULL; st->codecpar->codec_type = codec_type; + if (codec_type == AVMEDIA_TYPE_VIDEO) + st->avg_frame_rate = flv->framerate; + avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */ return st; } @@ -460,6 +465,10 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, if (!st) return AVERROR(ENOMEM); st->codecpar->codec_id = AV_CODEC_ID_TEXT; + } else if (!strcmp(key, "framerate")) { + flv->framerate = av_d2q(num_val, 1000); + if (vstream) + vstream->avg_frame_rate = flv->framerate; } else if (flv->trust_metadata) { if (!strcmp(key, "videocodecid") && vpar) { flv_set_video_codec(s, vstream, num_val, 0); From 07a2b155949eb267cdfc7805f42c7b3375f9c7c5 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Thu, 16 Mar 2017 15:37:51 -0400 Subject: [PATCH 0064/2557] Bump major versions of all libraries This disables everything that was deprecated at least 18 months ago. Readjust the minimum API version as needed, postponing any API-incompatible changes until the next bump. Signed-off-by: Vittorio Giovara --- libavcodec/version.h | 22 +++++++++++----------- libavdevice/version.h | 4 ++-- libavfilter/version.h | 4 ++-- libavformat/version.h | 12 ++++++------ libavresample/version.h | 2 +- libavutil/version.h | 12 ++++++------ libswscale/version.h | 2 +- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index f169793c15c30..2b9290316c0f9 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -27,9 +27,9 @@ #include "libavutil/version.h" -#define LIBAVCODEC_VERSION_MAJOR 57 -#define LIBAVCODEC_VERSION_MINOR 37 -#define LIBAVCODEC_VERSION_MICRO 1 +#define LIBAVCODEC_VERSION_MAJOR 58 +#define LIBAVCODEC_VERSION_MINOR 0 +#define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ @@ -141,28 +141,28 @@ #define FF_API_AUDIOENC_DELAY (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_AVCTX_TIMEBASE -#define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 59) +#define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_MPV_OPT -#define FF_API_MPV_OPT (LIBAVCODEC_VERSION_MAJOR < 59) +#define FF_API_MPV_OPT (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_STREAM_CODEC_TAG -#define FF_API_STREAM_CODEC_TAG (LIBAVCODEC_VERSION_MAJOR < 59) +#define FF_API_STREAM_CODEC_TAG (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_QUANT_BIAS -#define FF_API_QUANT_BIAS (LIBAVCODEC_VERSION_MAJOR < 59) +#define FF_API_QUANT_BIAS (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_RC_STRATEGY -#define FF_API_RC_STRATEGY (LIBAVCODEC_VERSION_MAJOR < 59) +#define FF_API_RC_STRATEGY (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_CODED_FRAME -#define FF_API_CODED_FRAME (LIBAVCODEC_VERSION_MAJOR < 59) +#define FF_API_CODED_FRAME (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_MOTION_EST -#define FF_API_MOTION_EST (LIBAVCODEC_VERSION_MAJOR < 59) +#define FF_API_MOTION_EST (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_WITHOUT_PREFIX -#define FF_API_WITHOUT_PREFIX (LIBAVCODEC_VERSION_MAJOR < 59) +#define FF_API_WITHOUT_PREFIX (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_SIDEDATA_ONLY_PKT #define FF_API_SIDEDATA_ONLY_PKT (LIBAVCODEC_VERSION_MAJOR < 59) diff --git a/libavdevice/version.h b/libavdevice/version.h index a5297320daa76..1bcb32c4c9055 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -27,8 +27,8 @@ #include "libavutil/version.h" -#define LIBAVDEVICE_VERSION_MAJOR 56 -#define LIBAVDEVICE_VERSION_MINOR 1 +#define LIBAVDEVICE_VERSION_MAJOR 57 +#define LIBAVDEVICE_VERSION_MINOR 0 #define LIBAVDEVICE_VERSION_MICRO 0 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ diff --git a/libavfilter/version.h b/libavfilter/version.h index 969f8101cd688..9a0a2c90ad84a 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -29,8 +29,8 @@ #include "libavutil/version.h" -#define LIBAVFILTER_VERSION_MAJOR 6 -#define LIBAVFILTER_VERSION_MINOR 9 +#define LIBAVFILTER_VERSION_MAJOR 7 +#define LIBAVFILTER_VERSION_MINOR 0 #define LIBAVFILTER_VERSION_MICRO 0 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavformat/version.h b/libavformat/version.h index 34650f6ec34e8..7103b5d969ac3 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -29,9 +29,9 @@ #include "libavutil/version.h" -#define LIBAVFORMAT_VERSION_MAJOR 57 -#define LIBAVFORMAT_VERSION_MINOR 11 -#define LIBAVFORMAT_VERSION_MICRO 4 +#define LIBAVFORMAT_VERSION_MAJOR 58 +#define LIBAVFORMAT_VERSION_MINOR 0 +#define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ @@ -58,13 +58,13 @@ #define FF_API_LAVF_CODEC_TB (LIBAVFORMAT_VERSION_MAJOR < 58) #endif #ifndef FF_API_LAVF_FMT_RAWPICTURE -#define FF_API_LAVF_FMT_RAWPICTURE (LIBAVFORMAT_VERSION_MAJOR < 58) +#define FF_API_LAVF_FMT_RAWPICTURE (LIBAVFORMAT_VERSION_MAJOR < 59) #endif #ifndef FF_API_COMPUTE_PKT_FIELDS2 -#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 58) +#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 59) #endif #ifndef FF_API_LAVF_AVCTX -#define FF_API_LAVF_AVCTX (LIBAVFORMAT_VERSION_MAJOR < 58) +#define FF_API_LAVF_AVCTX (LIBAVFORMAT_VERSION_MAJOR < 59) #endif #endif /* AVFORMAT_VERSION_H */ diff --git a/libavresample/version.h b/libavresample/version.h index 2f204e0476188..a6a5d67317789 100644 --- a/libavresample/version.h +++ b/libavresample/version.h @@ -27,7 +27,7 @@ #include "libavutil/version.h" -#define LIBAVRESAMPLE_VERSION_MAJOR 3 +#define LIBAVRESAMPLE_VERSION_MAJOR 4 #define LIBAVRESAMPLE_VERSION_MINOR 0 #define LIBAVRESAMPLE_VERSION_MICRO 0 diff --git a/libavutil/version.h b/libavutil/version.h index f952cc48dd250..93f471f99ba66 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -53,8 +53,8 @@ * @{ */ -#define LIBAVUTIL_VERSION_MAJOR 55 -#define LIBAVUTIL_VERSION_MINOR 35 +#define LIBAVUTIL_VERSION_MAJOR 56 +#define LIBAVUTIL_VERSION_MINOR 0 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ @@ -91,7 +91,7 @@ #define FF_API_DLOG (LIBAVUTIL_VERSION_MAJOR < 56) #endif #ifndef FF_API_CRYPTO_CONTEXT -#define FF_API_CRYPTO_CONTEXT (LIBAVUTIL_VERSION_MAJOR < 56) +#define FF_API_CRYPTO_CONTEXT (LIBAVUTIL_VERSION_MAJOR < 57) #endif #ifndef FF_API_PLUS1_MINUS1 #define FF_API_PLUS1_MINUS1 (LIBAVUTIL_VERSION_MAJOR < 56) @@ -100,13 +100,13 @@ #define FF_API_ERROR_FRAME (LIBAVUTIL_VERSION_MAJOR < 56) #endif #ifndef FF_API_VAAPI -#define FF_API_VAAPI (LIBAVUTIL_VERSION_MAJOR < 56) +#define FF_API_VAAPI (LIBAVUTIL_VERSION_MAJOR < 57) #endif #ifndef FF_API_PKT_PTS -#define FF_API_PKT_PTS (LIBAVUTIL_VERSION_MAJOR < 56) +#define FF_API_PKT_PTS (LIBAVUTIL_VERSION_MAJOR < 57) #endif #ifndef FF_API_CRYPTO_SIZE_T -#define FF_API_CRYPTO_SIZE_T (LIBAVUTIL_VERSION_MAJOR < 56) +#define FF_API_CRYPTO_SIZE_T (LIBAVUTIL_VERSION_MAJOR < 57) #endif diff --git a/libswscale/version.h b/libswscale/version.h index 701ce1b60bc93..5badd3d3218a3 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -26,7 +26,7 @@ #include "libavutil/version.h" -#define LIBSWSCALE_VERSION_MAJOR 4 +#define LIBSWSCALE_VERSION_MAJOR 5 #define LIBSWSCALE_VERSION_MINOR 0 #define LIBSWSCALE_VERSION_MICRO 0 From 88fd836a015a5f3380df74592e440e7d1e5b8000 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 12:38:32 -0500 Subject: [PATCH 0065/2557] lavfi: Drop deprecated way of passing options for a few filters Deprecated in 02/2013. --- libavfilter/af_channelmap.c | 7 ---- libavfilter/af_join.c | 8 ---- libavfilter/avfilter.c | 76 ------------------------------------- libavfilter/buffersrc.c | 8 ---- libavfilter/version.h | 3 -- libavfilter/vf_aspect.c | 46 ---------------------- 6 files changed, 148 deletions(-) diff --git a/libavfilter/af_channelmap.c b/libavfilter/af_channelmap.c index 572549808f945..e214bdbcc17b8 100644 --- a/libavfilter/af_channelmap.c +++ b/libavfilter/af_channelmap.c @@ -150,13 +150,6 @@ static av_cold int channelmap_init(AVFilterContext *ctx) else mode = MAP_PAIR_STR_STR; } -#if FF_API_OLD_FILTER_OPTS - if (strchr(mapping, ',')) { - av_log(ctx, AV_LOG_WARNING, "This syntax is deprecated, use " - "'|' to separate the mappings.\n"); - separator = ','; - } -#endif } if (mode != MAP_NONE) { diff --git a/libavfilter/af_join.c b/libavfilter/af_join.c index 4d86c8b3574ba..b61033f7a2a2e 100644 --- a/libavfilter/af_join.c +++ b/libavfilter/af_join.c @@ -104,14 +104,6 @@ static int parse_maps(AVFilterContext *ctx) char separator = '|'; char *cur = s->map; -#if FF_API_OLD_FILTER_OPTS - if (cur && strchr(cur, ',')) { - av_log(ctx, AV_LOG_WARNING, "This syntax is deprecated, use '|' to " - "separate the mappings.\n"); - separator = ','; - } -#endif - while (cur && *cur) { char *sep, *next, *p; uint64_t in_channel = 0, out_channel = 0; diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 99531e5690a72..d9c204e7660f5 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -624,87 +624,11 @@ int avfilter_init_str(AVFilterContext *filter, const char *args) return AVERROR(EINVAL); } -#if FF_API_OLD_FILTER_OPTS - if (!strcmp(filter->filter->name, "scale") && - strchr(args, ':') && strchr(args, ':') < strchr(args, '=')) { - /* old w:h:flags= syntax */ - char *copy = av_strdup(args); - char *p; - - av_log(filter, AV_LOG_WARNING, "The ::flags= option " - "syntax is deprecated. Use either :: or " - "w=:h=:flags=.\n"); - - if (!copy) { - ret = AVERROR(ENOMEM); - goto fail; - } - - p = strrchr(copy, ':'); - if (p) { - *p++ = 0; - ret = av_dict_parse_string(&options, p, "=", ":", 0); - } - if (ret >= 0) - ret = process_unnamed_options(filter, &options, copy); - av_freep(©); - - if (ret < 0) - goto fail; - } else -#endif - if (strchr(args, '=')) { /* assume a list of key1=value1:key2=value2:... */ ret = av_dict_parse_string(&options, args, "=", ":", 0); if (ret < 0) goto fail; -#if FF_API_OLD_FILTER_OPTS - } else if (!strcmp(filter->filter->name, "format") || - !strcmp(filter->filter->name, "noformat") || - !strcmp(filter->filter->name, "frei0r") || - !strcmp(filter->filter->name, "frei0r_src") || - !strcmp(filter->filter->name, "ocv")) { - /* a hack for compatibility with the old syntax - * replace colons with |s */ - char *copy = av_strdup(args); - char *p = copy; - int nb_leading = 0; // number of leading colons to skip - - if (!copy) { - ret = AVERROR(ENOMEM); - goto fail; - } - - if (!strcmp(filter->filter->name, "frei0r") || - !strcmp(filter->filter->name, "ocv")) - nb_leading = 1; - else if (!strcmp(filter->filter->name, "frei0r_src")) - nb_leading = 3; - - while (nb_leading--) { - p = strchr(p, ':'); - if (!p) { - p = copy + strlen(copy); - break; - } - p++; - } - - if (strchr(p, ':')) { - av_log(filter, AV_LOG_WARNING, "This syntax is deprecated. Use " - "'|' to separate the list items.\n"); - } - - while ((p = strchr(p, ':'))) - *p++ = '|'; - - ret = process_unnamed_options(filter, &options, copy); - av_freep(©); - - if (ret < 0) - goto fail; -#endif } else { ret = process_unnamed_options(filter, &options, args); if (ret < 0) diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index f553508cf10bb..df0097151479d 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -244,14 +244,6 @@ static const AVOption video_options[] = { { "width", NULL, OFFSET(w), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, V }, { "height", NULL, OFFSET(h), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, V }, { "pix_fmt", NULL, OFFSET(pix_fmt_str), AV_OPT_TYPE_STRING, .flags = V }, -#if FF_API_OLD_FILTER_OPTS - /* those 4 are for compatibility with the old option passing system where each filter - * did its own parsing */ - { "time_base_num", "deprecated, do not use", OFFSET(time_base.num), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, V }, - { "time_base_den", "deprecated, do not use", OFFSET(time_base.den), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, V }, - { "sar_num", "deprecated, do not use", OFFSET(pixel_aspect.num), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, V }, - { "sar_den", "deprecated, do not use", OFFSET(pixel_aspect.den), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, V }, -#endif { "sar", "sample aspect ratio", OFFSET(pixel_aspect), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V }, { "time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V }, { "frame_rate", NULL, OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V }, diff --git a/libavfilter/version.h b/libavfilter/version.h index 9a0a2c90ad84a..bb437efa02dd8 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -49,9 +49,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_OLD_FILTER_OPTS -#define FF_API_OLD_FILTER_OPTS (LIBAVFILTER_VERSION_MAJOR < 7) -#endif #ifndef FF_API_AVFILTER_OPEN #define FF_API_AVFILTER_OPEN (LIBAVFILTER_VERSION_MAJOR < 7) #endif diff --git a/libavfilter/vf_aspect.c b/libavfilter/vf_aspect.c index 2c2821318eac4..6a6430f2dbb59 100644 --- a/libavfilter/vf_aspect.c +++ b/libavfilter/vf_aspect.c @@ -66,27 +66,9 @@ typedef struct AspectContext { const AVClass *class; AVRational dar; AVRational sar; -#if FF_API_OLD_FILTER_OPTS - float aspect_num, aspect_den; -#endif char *ratio_expr; } AspectContext; -#if FF_API_OLD_FILTER_OPTS -static av_cold int init(AVFilterContext *ctx) -{ - AspectContext *s = ctx->priv; - - if (s->aspect_num > 0 && s->aspect_den > 0) { - av_log(ctx, AV_LOG_WARNING, "This syntax is deprecated, use " - "dar= or dar=num/den.\n"); - s->sar = s->dar = av_d2q(s->aspect_num / s->aspect_den, INT_MAX); - } - - return 0; -} -#endif - static int filter_frame(AVFilterLink *link, AVFrame *frame) { AspectContext *s = link->dst->priv; @@ -138,14 +120,8 @@ static int setdar_config_props(AVFilterLink *inlink) AVRational dar; int ret; -#if FF_API_OLD_FILTER_OPTS - if (!(s->aspect_num > 0 && s->aspect_den > 0)) { -#endif if ((ret = get_aspect_ratio(inlink, &s->dar))) return ret; -#if FF_API_OLD_FILTER_OPTS - } -#endif if (s->dar.num && s->dar.den) { av_reduce(&s->sar.num, &s->sar.den, @@ -166,10 +142,6 @@ static int setdar_config_props(AVFilterLink *inlink) } static const AVOption setdar_options[] = { -#if FF_API_OLD_FILTER_OPTS - { "dar_num", NULL, OFFSET(aspect_num), AV_OPT_TYPE_FLOAT, { .dbl = 0 }, 0, FLT_MAX, FLAGS }, - { "dar_den", NULL, OFFSET(aspect_den), AV_OPT_TYPE_FLOAT, { .dbl = 0 }, 0, FLT_MAX, FLAGS }, -#endif { "dar", "display aspect ratio", OFFSET(ratio_expr), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS }, { NULL }, }; @@ -204,10 +176,6 @@ AVFilter ff_vf_setdar = { .name = "setdar", .description = NULL_IF_CONFIG_SMALL("Set the frame display aspect ratio."), -#if FF_API_OLD_FILTER_OPTS - .init = init, -#endif - .priv_size = sizeof(AspectContext), .priv_class = &setdar_class, @@ -224,14 +192,8 @@ static int setsar_config_props(AVFilterLink *inlink) AspectContext *s = inlink->dst->priv; int ret; -#if FF_API_OLD_FILTER_OPTS - if (!(s->aspect_num > 0 && s->aspect_den > 0)) { -#endif if ((ret = get_aspect_ratio(inlink, &s->sar))) return ret; -#if FF_API_OLD_FILTER_OPTS - } -#endif inlink->sample_aspect_ratio = s->sar; @@ -239,10 +201,6 @@ static int setsar_config_props(AVFilterLink *inlink) } static const AVOption setsar_options[] = { -#if FF_API_OLD_FILTER_OPTS - { "sar_num", NULL, OFFSET(aspect_num), AV_OPT_TYPE_FLOAT, { .dbl = 0 }, 0, FLT_MAX, FLAGS }, - { "sar_den", NULL, OFFSET(aspect_den), AV_OPT_TYPE_FLOAT, { .dbl = 0 }, 0, FLT_MAX, FLAGS }, -#endif { "sar", "sample (pixel) aspect ratio", OFFSET(ratio_expr), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS }, { NULL }, }; @@ -277,10 +235,6 @@ AVFilter ff_vf_setsar = { .name = "setsar", .description = NULL_IF_CONFIG_SMALL("Set the pixel sample aspect ratio."), -#if FF_API_OLD_FILTER_OPTS - .init = init, -#endif - .priv_size = sizeof(AspectContext), .priv_class = &setsar_class, From c5c7cfd5e80d4c36568c01cc40abfde341657ad9 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 12:41:49 -0500 Subject: [PATCH 0066/2557] lavfi: Drop deprecated functions to open a filter or a filterchain Deprecated in 03/2013. --- libavfilter/avfilter.c | 8 -------- libavfilter/avfilter.h | 30 ------------------------------ libavfilter/avfiltergraph.c | 17 ----------------- libavfilter/version.h | 3 --- 4 files changed, 58 deletions(-) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index d9c204e7660f5..d6bddef4a04e6 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -475,14 +475,6 @@ AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name) return NULL; } -#if FF_API_AVFILTER_OPEN -int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *inst_name) -{ - *filter_ctx = ff_filter_alloc(filter, inst_name); - return *filter_ctx ? 0 : AVERROR(ENOMEM); -} -#endif - static void free_link(AVFilterLink *link) { if (!link) diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 568480dd3e4d4..babcec66f2ca1 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -479,22 +479,6 @@ attribute_deprecated AVFilter **av_filter_next(AVFilter **filter); #endif -#if FF_API_AVFILTER_OPEN -/** - * Create a filter instance. - * - * @param filter_ctx put here a pointer to the created filter context - * on success, NULL on failure - * @param filter the filter to create an instance of - * @param inst_name Name to give to the new instance. Can be NULL for none. - * @return >= 0 in case of success, a negative error code otherwise - * @deprecated use avfilter_graph_alloc_filter() instead - */ -attribute_deprecated -int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *inst_name); -#endif - - #if FF_API_AVFILTER_INIT_FILTER /** * Initialize a filter. @@ -691,20 +675,6 @@ AVFilterContext *avfilter_graph_alloc_filter(AVFilterGraph *graph, */ AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name); -#if FF_API_AVFILTER_OPEN -/** - * Add an existing filter instance to a filter graph. - * - * @param graphctx the filter graph - * @param filter the filter to be added - * - * @deprecated use avfilter_graph_alloc_filter() to allocate a filter in a - * filter graph - */ -attribute_deprecated -int avfilter_graph_add_filter(AVFilterGraph *graphctx, AVFilterContext *filter); -#endif - /** * Create and add a filter instance into an existing graph. * The filter instance is created from the filter filt and inited diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index 5053e3c37a8dd..58ede68a316b1 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -116,23 +116,6 @@ void avfilter_graph_free(AVFilterGraph **graph) av_freep(graph); } -#if FF_API_AVFILTER_OPEN -int avfilter_graph_add_filter(AVFilterGraph *graph, AVFilterContext *filter) -{ - AVFilterContext **filters = av_realloc(graph->filters, - sizeof(*filters) * (graph->nb_filters + 1)); - if (!filters) - return AVERROR(ENOMEM); - - graph->filters = filters; - graph->filters[graph->nb_filters++] = filter; - - filter->graph = graph; - - return 0; -} -#endif - int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt, const char *name, const char *args, void *opaque, AVFilterGraph *graph_ctx) diff --git a/libavfilter/version.h b/libavfilter/version.h index bb437efa02dd8..540ac48f9b5dd 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -49,9 +49,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_AVFILTER_OPEN -#define FF_API_AVFILTER_OPEN (LIBAVFILTER_VERSION_MAJOR < 7) -#endif #ifndef FF_API_AVFILTER_INIT_FILTER #define FF_API_AVFILTER_INIT_FILTER (LIBAVFILTER_VERSION_MAJOR < 7) #endif From 52067b3c0e5ddbcf7021a093420798420351a9e2 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 12:43:19 -0500 Subject: [PATCH 0067/2557] lavfi: Drop deprecated filter initialization Deprecated in 03/2013. --- libavfilter/avfilter.c | 7 ------- libavfilter/avfilter.h | 15 --------------- libavfilter/version.h | 3 --- 3 files changed, 25 deletions(-) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index d6bddef4a04e6..439eee4dd460d 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -561,13 +561,6 @@ static int process_unnamed_options(AVFilterContext *ctx, AVDictionary **options, return 0; } -#if FF_API_AVFILTER_INIT_FILTER -int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque) -{ - return avfilter_init_str(filter, args); -} -#endif - int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options) { int ret = 0; diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index babcec66f2ca1..6537a83407f09 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -479,21 +479,6 @@ attribute_deprecated AVFilter **av_filter_next(AVFilter **filter); #endif -#if FF_API_AVFILTER_INIT_FILTER -/** - * Initialize a filter. - * - * @param filter the filter to initialize - * @param args A string of parameters to use when initializing the filter. - * The format and meaning of this string varies by filter. - * @param opaque Any extra non-string data needed by the filter. The meaning - * of this parameter varies by filter. - * @return zero on success - */ -attribute_deprecated -int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque); -#endif - /** * Initialize a filter with the supplied parameters. * diff --git a/libavfilter/version.h b/libavfilter/version.h index 540ac48f9b5dd..ef2b34cc6f7c5 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -49,9 +49,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_AVFILTER_INIT_FILTER -#define FF_API_AVFILTER_INIT_FILTER (LIBAVFILTER_VERSION_MAJOR < 7) -#endif #ifndef FF_API_OLD_FILTER_REGISTER #define FF_API_OLD_FILTER_REGISTER (LIBAVFILTER_VERSION_MAJOR < 7) #endif From 8e18328b18e69b38a5feae5d10ad01b403a205b6 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 13:42:27 -0500 Subject: [PATCH 0068/2557] lavfi: Drop deprecated filter registration Deprecated in 04/2013. --- libavfilter/avfilter.c | 11 ----------- libavfilter/avfilter.h | 18 ------------------ libavfilter/version.h | 3 --- 3 files changed, 32 deletions(-) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 439eee4dd460d..3ae7a591db2c0 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -324,17 +324,6 @@ const AVFilter *avfilter_next(const AVFilter *prev) return prev ? prev->next : first_filter; } -#if FF_API_OLD_FILTER_REGISTER -AVFilter **av_filter_next(AVFilter **filter) -{ - return filter ? &(*filter)->next : &first_filter; -} - -void avfilter_uninit(void) -{ -} -#endif - int avfilter_pad_count(const AVFilterPad *pads) { int count; diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 6537a83407f09..96d3e318637f1 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -430,12 +430,6 @@ int avfilter_config_links(AVFilterContext *filter); /** Initialize the filter system. Register all builtin filters. */ void avfilter_register_all(void); -#if FF_API_OLD_FILTER_REGISTER -/** Uninitialize the filter system. Unregister all filters. */ -attribute_deprecated -void avfilter_uninit(void); -#endif - /** * Register a filter. This is only needed if you plan to use * avfilter_get_by_name later to lookup the AVFilter structure by name. A @@ -467,18 +461,6 @@ AVFilter *avfilter_get_by_name(const char *name); */ const AVFilter *avfilter_next(const AVFilter *prev); -#if FF_API_OLD_FILTER_REGISTER -/** - * If filter is NULL, returns a pointer to the first registered filter pointer, - * if filter is non-NULL, returns the next pointer after filter. - * If the returned pointer points to NULL, the last registered filter - * was already reached. - * @deprecated use avfilter_next() - */ -attribute_deprecated -AVFilter **av_filter_next(AVFilter **filter); -#endif - /** * Initialize a filter with the supplied parameters. * diff --git a/libavfilter/version.h b/libavfilter/version.h index ef2b34cc6f7c5..4f3da2bd106c2 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -49,9 +49,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_OLD_FILTER_REGISTER -#define FF_API_OLD_FILTER_REGISTER (LIBAVFILTER_VERSION_MAJOR < 7) -#endif #ifndef FF_API_NOCONST_GET_NAME #define FF_API_NOCONST_GET_NAME (LIBAVFILTER_VERSION_MAJOR < 7) #endif From 96a47364d1cf346a5d0437e054b1b10d44d8d969 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 13:58:30 -0500 Subject: [PATCH 0069/2557] lavfi: Drop deprecated non-const filter retrieval Deprecated in 10/2013. --- libavfilter/avfilter.c | 5 +---- libavfilter/avfilter.h | 5 +---- libavfilter/avfiltergraph.c | 4 ++-- libavfilter/graphparser.c | 2 +- libavfilter/version.h | 4 ---- 5 files changed, 5 insertions(+), 15 deletions(-) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 3ae7a591db2c0..83c1a7c20d5ff 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -292,10 +292,7 @@ int ff_poll_frame(AVFilterLink *link) static AVFilter *first_filter; -#if !FF_API_NOCONST_GET_NAME -const -#endif -AVFilter *avfilter_get_by_name(const char *name) +const AVFilter *avfilter_get_by_name(const char *name) { const AVFilter *f = NULL; diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 96d3e318637f1..6df69dbbbf1bc 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -449,10 +449,7 @@ int avfilter_register(AVFilter *filter); * @return the filter definition, if any matching one is registered. * NULL if none found. */ -#if !FF_API_NOCONST_GET_NAME -const -#endif -AVFilter *avfilter_get_by_name(const char *name); +const AVFilter *avfilter_get_by_name(const char *name); /** * Iterate over all registered filters. diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index 58ede68a316b1..a0f797e283f80 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -293,7 +293,7 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) if (convert_needed) { AVFilterContext *convert; - AVFilter *filter; + const AVFilter *filter; AVFilterLink *inlink, *outlink; char scale_args[256]; char inst_name[30]; @@ -759,7 +759,7 @@ static int graph_insert_fifos(AVFilterGraph *graph, AVClass *log_ctx) for (j = 0; j < f->nb_inputs; j++) { AVFilterLink *link = f->inputs[j]; AVFilterContext *fifo_ctx; - AVFilter *fifo; + const AVFilter *fifo; char name[32]; if (!link->dstpad->needs_fifo) diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index da499b52c93aa..4c75c045f1ba0 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -131,7 +131,7 @@ static void append_sws_flags(const char **args, const char *sws_opts, char *tmp) static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int index, const char *filt_name, const char *args, void *log_ctx) { - AVFilter *filt; + const AVFilter *filt; char inst_name[30]; char tmp_args[TMP_ARGS_SIZE]; int ret; diff --git a/libavfilter/version.h b/libavfilter/version.h index 4f3da2bd106c2..62fc97dd27897 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -49,8 +49,4 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_NOCONST_GET_NAME -#define FF_API_NOCONST_GET_NAME (LIBAVFILTER_VERSION_MAJOR < 7) -#endif - #endif /* AVFILTER_VERSION_H */ From 5e71299758d3aa7c93c3cca618a8e048a9483794 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 14:11:14 -0500 Subject: [PATCH 0070/2557] lavf: Drop deprecated bitexact functionality Deprecated in 05/2014. --- libavformat/mux.c | 7 ------- libavformat/version.h | 3 --- 2 files changed, 10 deletions(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index a85c3c79db09d..dfda89d983b8c 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -99,13 +99,6 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) if ((ret = av_opt_set_dict(s, &tmp)) < 0) goto fail; -#if FF_API_LAVF_BITEXACT && FF_API_LAVF_AVCTX -FF_DISABLE_DEPRECATION_WARNINGS - if (s->nb_streams && s->streams[0]->codec->flags & AV_CODEC_FLAG_BITEXACT) - s->flags |= AVFMT_FLAG_BITEXACT; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - // some sanity checks if (s->nb_streams == 0 && !(of->flags & AVFMT_NOSTREAMS)) { av_log(s, AV_LOG_ERROR, "no streams\n"); diff --git a/libavformat/version.h b/libavformat/version.h index 7103b5d969ac3..26f5c759910d6 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -48,9 +48,6 @@ * dropped at a future version bump. The defines themselves are not part of * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_LAVF_BITEXACT -#define FF_API_LAVF_BITEXACT (LIBAVFORMAT_VERSION_MAJOR < 58) -#endif #ifndef FF_API_LAVF_FRAC #define FF_API_LAVF_FRAC (LIBAVFORMAT_VERSION_MAJOR < 58) #endif From 263358e0c9e7ffaa965fdbe986c8b18381d2b24a Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 14:13:58 -0500 Subject: [PATCH 0071/2557] lavf: Drop deprecated AVFract type and related field Deprecated in 05/2014. --- libavformat/avformat.h | 21 --------------------- libavformat/version.h | 3 --- 2 files changed, 24 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 547b88b2f1c14..1bf66b15d1b6a 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -374,19 +374,6 @@ int av_get_packet(AVIOContext *s, AVPacket *pkt, int size); */ int av_append_packet(AVIOContext *s, AVPacket *pkt, int size); -#if FF_API_LAVF_FRAC -/*************************************************/ -/* fractional numbers for exact pts handling */ - -/** - * The exact value of the fractional number is: 'val + num / den'. - * num is assumed to be 0 <= num < den. - */ -typedef struct AVFrac { - int64_t val, num, den; -} AVFrac; -#endif - /*************************************************/ /* input/output formats */ @@ -713,14 +700,6 @@ typedef struct AVStream { #endif void *priv_data; -#if FF_API_LAVF_FRAC - /** - * @deprecated this field is unused - */ - attribute_deprecated - struct AVFrac pts; -#endif - /** * This is the fundamental unit of time (in seconds) in terms * of which frame timestamps are represented. diff --git a/libavformat/version.h b/libavformat/version.h index 26f5c759910d6..dad38d1180616 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -48,9 +48,6 @@ * dropped at a future version bump. The defines themselves are not part of * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_LAVF_FRAC -#define FF_API_LAVF_FRAC (LIBAVFORMAT_VERSION_MAJOR < 58) -#endif #ifndef FF_API_LAVF_CODEC_TB #define FF_API_LAVF_CODEC_TB (LIBAVFORMAT_VERSION_MAJOR < 58) #endif From 63fe79a3368cc53e6faf7fa265a9a1a8bec46a88 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 14:16:21 -0500 Subject: [PATCH 0072/2557] lavf: Drop deprecated hint to set muxer timebase Deprecated in 05/2014. --- libavformat/mux.c | 11 ----------- libavformat/version.h | 4 +--- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index dfda89d983b8c..cc92f2a960a78 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -110,17 +110,6 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) st = s->streams[i]; par = st->codecpar; -#if FF_API_LAVF_CODEC_TB && FF_API_LAVF_AVCTX -FF_DISABLE_DEPRECATION_WARNINGS - if (!st->time_base.num && st->codec->time_base.num) { - av_log(s, AV_LOG_WARNING, "Using AVStream.codec.time_base as a " - "timebase hint to the muxer is deprecated. Set " - "AVStream.time_base instead.\n"); - avpriv_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den); - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif - #if FF_API_LAVF_AVCTX FF_DISABLE_DEPRECATION_WARNINGS if (st->codecpar->codec_type == AVMEDIA_TYPE_UNKNOWN && diff --git a/libavformat/version.h b/libavformat/version.h index dad38d1180616..7060375c1aa6c 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -48,9 +48,7 @@ * dropped at a future version bump. The defines themselves are not part of * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_LAVF_CODEC_TB -#define FF_API_LAVF_CODEC_TB (LIBAVFORMAT_VERSION_MAJOR < 58) -#endif + #ifndef FF_API_LAVF_FMT_RAWPICTURE #define FF_API_LAVF_FMT_RAWPICTURE (LIBAVFORMAT_VERSION_MAJOR < 59) #endif From bc143ce1ac3f8cd851a7e6be69d9a1fbe6b633b6 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 14:24:57 -0500 Subject: [PATCH 0073/2557] lavc: Drop deprecated chroma subsample function Deprecated in 11/2012. --- libavcodec/avcodec.h | 6 ------ libavcodec/imgconvert.c | 9 --------- libavcodec/version.h | 3 --- 3 files changed, 18 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 1e2b13e0d79b6..5f83a36ea0f61 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -4899,12 +4899,6 @@ int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, * @{ */ -/** - * @deprecated Use av_pix_fmt_get_chroma_sub_sample - */ - -void attribute_deprecated avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift); - /** * Return a value representing the fourCC code associated to the * pixel format pix_fmt, or 0 if no associated fourCC code can be diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c index 4667a4fb52f9c..9c8fab59a305e 100644 --- a/libavcodec/imgconvert.c +++ b/libavcodec/imgconvert.c @@ -33,15 +33,6 @@ #include "libavutil/internal.h" #include "libavutil/imgutils.h" -#if FF_API_GETCHROMA -void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - *h_shift = desc->log2_chroma_w; - *v_shift = desc->log2_chroma_h; -} -#endif - static int is_gray(const AVPixFmtDescriptor *desc) { return desc->nb_components - (desc->flags & AV_PIX_FMT_FLAG_ALPHA) == 1; diff --git a/libavcodec/version.h b/libavcodec/version.h index 2b9290316c0f9..98c93d3bc647c 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_GETCHROMA -#define FF_API_GETCHROMA (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_MISSING_SAMPLE #define FF_API_MISSING_SAMPLE (LIBAVCODEC_VERSION_MAJOR < 58) #endif From 0337adfab5d14a17bf4d5060aa0425e4049a9862 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 14:27:30 -0500 Subject: [PATCH 0074/2557] lavc: Drop deprecated missing sample log function Deprecated in 01/2013. --- libavcodec/avcodec.h | 30 ------------------------------ libavcodec/utils.c | 29 ----------------------------- libavcodec/version.h | 3 --- 3 files changed, 62 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 5f83a36ea0f61..9f7057e840ca7 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -5310,36 +5310,6 @@ void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size); */ unsigned int av_xiphlacing(unsigned char *s, unsigned int v); -#if FF_API_MISSING_SAMPLE -/** - * Log a generic warning message about a missing feature. This function is - * intended to be used internally by Libav (libavcodec, libavformat, etc.) - * only, and would normally not be used by applications. - * @param[in] avc a pointer to an arbitrary struct of which the first field is - * a pointer to an AVClass struct - * @param[in] feature string containing the name of the missing feature - * @param[in] want_sample indicates if samples are wanted which exhibit this feature. - * If want_sample is non-zero, additional verbiage will be added to the log - * message which tells the user how to report samples to the development - * mailing list. - * @deprecated Use avpriv_report_missing_feature() instead. - */ -attribute_deprecated -void av_log_missing_feature(void *avc, const char *feature, int want_sample); - -/** - * Log a generic warning message asking for a sample. This function is - * intended to be used internally by Libav (libavcodec, libavformat, etc.) - * only, and would normally not be used by applications. - * @param[in] avc a pointer to an arbitrary struct of which the first field is - * a pointer to an AVClass struct - * @param[in] msg string containing an optional message, or NULL if no message - * @deprecated Use avpriv_request_sample() instead. - */ -attribute_deprecated -void av_log_ask_for_sample(void *avc, const char *msg, ...) av_printf_format(2, 3); -#endif /* FF_API_MISSING_SAMPLE */ - /** * Register the hardware accelerator hwaccel. */ diff --git a/libavcodec/utils.c b/libavcodec/utils.c index ea4d5fa3129ee..8a481dd025c32 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -1359,35 +1359,6 @@ int ff_match_2uint16(const uint16_t(*tab)[2], int size, int a, int b) return i; } -#if FF_API_MISSING_SAMPLE -FF_DISABLE_DEPRECATION_WARNINGS -void av_log_missing_feature(void *avc, const char *feature, int want_sample) -{ - av_log(avc, AV_LOG_WARNING, "%s is not implemented. Update your Libav " - "version to the newest one from Git. If the problem still " - "occurs, it means that your file has a feature which has not " - "been implemented.\n", feature); - if(want_sample) - av_log_ask_for_sample(avc, NULL); -} - -void av_log_ask_for_sample(void *avc, const char *msg, ...) -{ - va_list argument_list; - - va_start(argument_list, msg); - - if (msg) - av_vlog(avc, AV_LOG_WARNING, msg, argument_list); - av_log(avc, AV_LOG_WARNING, "If you want to help, upload a sample " - "of this file to ftp://upload.libav.org/incoming/ " - "and contact the libav-devel mailing list.\n"); - - va_end(argument_list); -} -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_MISSING_SAMPLE */ - static AVHWAccel *first_hwaccel = NULL; void av_register_hwaccel(AVHWAccel *hwaccel) diff --git a/libavcodec/version.h b/libavcodec/version.h index 98c93d3bc647c..95b8ed6391383 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_MISSING_SAMPLE -#define FF_API_MISSING_SAMPLE (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_LOWRES #define FF_API_LOWRES (LIBAVCODEC_VERSION_MAJOR < 58) #endif From b748c280e59cac468ed36cbbe5e71d5ebd434020 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 14:28:30 -0500 Subject: [PATCH 0075/2557] lavc: Drop deprecated lowres option Deprecated in 04/2013. --- libavcodec/avcodec.h | 14 -------------- libavcodec/version.h | 3 --- 2 files changed, 17 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 9f7057e840ca7..35051313fab74 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2810,17 +2810,6 @@ typedef struct AVCodecContext { */ int bits_per_raw_sample; -#if FF_API_LOWRES - /** - * low resolution decoding, 1-> 1/2 size, 2->1/4 size - * - encoding: unused - * - decoding: Set by user. - * - * @deprecated use decoder private options instead - */ - attribute_deprecated int lowres; -#endif - #if FF_API_CODED_FRAME /** * the picture in the bitstream @@ -3237,9 +3226,6 @@ typedef struct AVCodec { const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 -#if FF_API_LOWRES - attribute_deprecated uint8_t max_lowres; ///< maximum value for lowres supported by the decoder -#endif const AVClass *priv_class; ///< AVClass for the private context const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN} diff --git a/libavcodec/version.h b/libavcodec/version.h index 95b8ed6391383..e720012088afc 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_LOWRES -#define FF_API_LOWRES (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_CAP_VDPAU #define FF_API_CAP_VDPAU (LIBAVCODEC_VERSION_MAJOR < 58) #endif From 7b917041184874e7d7cba4450813de7e0bb28a33 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 14:30:09 -0500 Subject: [PATCH 0076/2557] lavc: Drop deprecated VDPAU codec capability Deprecated in 07/2013. --- libavcodec/avcodec.h | 6 ------ libavcodec/vdpau.h | 34 ---------------------------------- libavcodec/version.h | 3 --- 3 files changed, 43 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 35051313fab74..f5711baa350f5 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1046,12 +1046,6 @@ typedef struct RcOverride{ * This can be used to prevent truncation of the last audio samples. */ #define CODEC_CAP_SMALL_LAST_FRAME 0x0040 -#if FF_API_CAP_VDPAU -/** - * Codec can export data for HW decoding (VDPAU). - */ -#define CODEC_CAP_HWACCEL_VDPAU 0x0080 -#endif /** * Codec can output multiple frames per AVPacket * Normally demuxers return one frame at a time, demuxers which do not do diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h index acd63ccfafb74..2f4fa86ba4401 100644 --- a/libavcodec/vdpau.h +++ b/libavcodec/vdpau.h @@ -194,40 +194,6 @@ attribute_deprecated int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile); #endif -#if FF_API_CAP_VDPAU -/** @brief The videoSurface is used for rendering. */ -#define FF_VDPAU_STATE_USED_FOR_RENDER 1 - -/** - * @brief The videoSurface is needed for reference/prediction. - * The codec manipulates this. - */ -#define FF_VDPAU_STATE_USED_FOR_REFERENCE 2 - -/** - * @brief This structure is used as a callback between the Libav - * decoder (vd_) and presentation (vo_) module. - * This is used for defining a video frame containing surface, - * picture parameter, bitstream information etc which are passed - * between the Libav decoder and its clients. - */ -struct vdpau_render_state { - VdpVideoSurface surface; ///< Used as rendered surface, never changed. - - int state; ///< Holds FF_VDPAU_STATE_* values. - - /** picture parameter information for all supported codecs */ - union AVVDPAUPictureInfo info; - - /** Describe size/location of the compressed video data. - Set to 0 when freeing bitstream_buffers. */ - int bitstream_buffers_allocated; - int bitstream_buffers_used; - /** The user is responsible for freeing this buffer using av_freep(). */ - VdpBitstreamBuffer *bitstream_buffers; -}; -#endif - /* @}*/ #endif /* AVCODEC_VDPAU_H */ diff --git a/libavcodec/version.h b/libavcodec/version.h index e720012088afc..3d7e47c729003 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_CAP_VDPAU -#define FF_API_CAP_VDPAU (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_BUFS_VDPAU #define FF_API_BUFS_VDPAU (LIBAVCODEC_VERSION_MAJOR < 58) #endif From 5c1585c4c3b5281835d784c5daef0069915ccd57 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 14:31:25 -0500 Subject: [PATCH 0077/2557] lavc: Drop deprecated VDPAU buffer fields Deprecated in 07/2013. --- libavcodec/vdpau.h | 44 -------------------------------------------- libavcodec/version.h | 3 --- 2 files changed, 47 deletions(-) diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h index 2f4fa86ba4401..a5d31cb37b9db 100644 --- a/libavcodec/vdpau.h +++ b/libavcodec/vdpau.h @@ -56,15 +56,6 @@ #include "avcodec.h" #include "version.h" -#if FF_API_BUFS_VDPAU -union AVVDPAUPictureInfo { - VdpPictureInfoH264 h264; - VdpPictureInfoMPEG1Or2 mpeg; - VdpPictureInfoVC1 vc1; - VdpPictureInfoMPEG4Part2 mpeg4; -}; -#endif - /** * This structure is used to share data between the libavcodec library and * the client video application. @@ -92,41 +83,6 @@ typedef struct AVVDPAUContext { * Set by the user. */ VdpDecoderRender *render; - -#if FF_API_BUFS_VDPAU - /** - * VDPAU picture information - * - * Set by libavcodec. - */ - attribute_deprecated - union AVVDPAUPictureInfo info; - - /** - * Allocated size of the bitstream_buffers table. - * - * Set by libavcodec. - */ - attribute_deprecated - int bitstream_buffers_allocated; - - /** - * Useful bitstream buffers in the bitstream buffers table. - * - * Set by libavcodec. - */ - attribute_deprecated - int bitstream_buffers_used; - - /** - * Table of bitstream buffers. - * The user is responsible for freeing this buffer using av_freep(). - * - * Set by libavcodec. - */ - attribute_deprecated - VdpBitstreamBuffer *bitstream_buffers; -#endif } AVVDPAUContext; /** diff --git a/libavcodec/version.h b/libavcodec/version.h index 3d7e47c729003..033909a1e403d 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_BUFS_VDPAU -#define FF_API_BUFS_VDPAU (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_VOXWARE #define FF_API_VOXWARE (LIBAVCODEC_VERSION_MAJOR < 58) #endif From 1146bb3babca3973e88005d267cd06210d6ac075 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 14:33:00 -0500 Subject: [PATCH 0078/2557] lavc: Drop deprecated voxware codec entry Deprecated in 08/2013. --- libavcodec/avcodec.h | 3 --- libavcodec/codec_desc.c | 9 --------- libavcodec/version.h | 3 --- 3 files changed, 15 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index f5711baa350f5..3a007fad1aac0 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -531,9 +531,6 @@ enum AVCodecID { AV_CODEC_ID_MLP, AV_CODEC_ID_GSM_MS, /* as found in WAV */ AV_CODEC_ID_ATRAC3, -#if FF_API_VOXWARE - AV_CODEC_ID_VOXWARE, -#endif AV_CODEC_ID_APE, AV_CODEC_ID_NELLYMOSER, AV_CODEC_ID_MUSEPACK8, diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index dd243c2f0cd57..8b9ec40e598ee 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2161,15 +2161,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("ATRAC3 (Adaptive TRansform Acoustic Coding 3)"), .props = AV_CODEC_PROP_LOSSY, }, -#if FF_API_VOXWARE - { - .id = AV_CODEC_ID_VOXWARE, - .type = AVMEDIA_TYPE_AUDIO, - .name = "voxware", - .long_name = NULL_IF_CONFIG_SMALL("Voxware RT29 Metasound"), - .props = AV_CODEC_PROP_LOSSY, - }, -#endif { .id = AV_CODEC_ID_APE, .type = AVMEDIA_TYPE_AUDIO, diff --git a/libavcodec/version.h b/libavcodec/version.h index 033909a1e403d..1f064832114ac 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_VOXWARE -#define FF_API_VOXWARE (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_SET_DIMENSIONS #define FF_API_SET_DIMENSIONS (LIBAVCODEC_VERSION_MAJOR < 58) #endif From 6dca24cd1d570b806b5a3fdaef9d3c8608942a81 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 15:11:06 -0500 Subject: [PATCH 0079/2557] lavc: Drop deprecated way of setting codec dimensions Deprecated in 10/2013. --- libavcodec/avcodec.h | 8 -------- libavcodec/utils.c | 7 ------- libavcodec/version.h | 3 --- 3 files changed, 18 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 3a007fad1aac0..11a3280eb8da6 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -4937,14 +4937,6 @@ enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const en * @} */ -#if FF_API_SET_DIMENSIONS -/** - * @deprecated this function is not supposed to be used from outside of lavc - */ -attribute_deprecated -void avcodec_set_dimensions(AVCodecContext *s, int width, int height); -#endif - /** * Put a string representing the codec tag codec_tag in buf. * diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 8a481dd025c32..6cef65083d7ba 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -125,13 +125,6 @@ unsigned avcodec_get_edge_width(void) } #endif -#if FF_API_SET_DIMENSIONS -void avcodec_set_dimensions(AVCodecContext *s, int width, int height) -{ - ff_set_dimensions(s, width, height); -} -#endif - int ff_set_dimensions(AVCodecContext *s, int width, int height) { int ret = av_image_check_size(width, height, 0, s); diff --git a/libavcodec/version.h b/libavcodec/version.h index 1f064832114ac..a12c322f49eb2 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_SET_DIMENSIONS -#define FF_API_SET_DIMENSIONS (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_DEBUG_MV #define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 58) #endif From 8933ac2079644fb09916f1875c569103aefe84b1 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 15:13:43 -0500 Subject: [PATCH 0080/2557] lavc: Drop deprecated debug mv functionality Deprecated in 10/2013. --- libavcodec/avcodec.h | 21 --------------------- libavcodec/options_table.h | 13 ------------- libavcodec/version.h | 3 --- 3 files changed, 37 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 11a3280eb8da6..b77f940d30b33 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2655,12 +2655,6 @@ typedef struct AVCodecContext { #define FF_DEBUG_BITSTREAM 4 #define FF_DEBUG_MB_TYPE 8 #define FF_DEBUG_QP 16 -#if FF_API_DEBUG_MV -/** - * @deprecated this option does nothing - */ -#define FF_DEBUG_MV 32 -#endif #define FF_DEBUG_DCT_COEFF 0x00000040 #define FF_DEBUG_SKIP 0x00000080 #define FF_DEBUG_STARTCODE 0x00000100 @@ -2670,24 +2664,9 @@ typedef struct AVCodecContext { #define FF_DEBUG_ER 0x00000400 #define FF_DEBUG_MMCO 0x00000800 #define FF_DEBUG_BUGS 0x00001000 -#if FF_API_DEBUG_MV -#define FF_DEBUG_VIS_QP 0x00002000 -#define FF_DEBUG_VIS_MB_TYPE 0x00004000 -#endif #define FF_DEBUG_BUFFERS 0x00008000 #define FF_DEBUG_THREADS 0x00010000 -#if FF_API_DEBUG_MV - /** - * @deprecated this option does not have any effect - */ - attribute_deprecated - int debug_mv; -#define FF_DEBUG_VIS_MV_P_FOR 0x00000001 // visualize forward predicted MVs of P-frames -#define FF_DEBUG_VIS_MV_B_FOR 0x00000002 // visualize forward predicted MVs of B-frames -#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 // visualize backward predicted MVs of B-frames -#endif - /** * Error recognition; may misdetect some more or less valid parts as errors. * - encoding: unused diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 3ac53fb748b5e..445515f0ee091 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -247,9 +247,6 @@ static const AVOption avcodec_options[] = { {"bitstream", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BITSTREAM }, INT_MIN, INT_MAX, V|D, "debug"}, {"mb_type", "macroblock (MB) type", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_MB_TYPE }, INT_MIN, INT_MAX, V|D, "debug"}, {"qp", "per-block quantization parameter (QP)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_QP }, INT_MIN, INT_MAX, V|D, "debug"}, -#if FF_API_DEBUG_MV -{"mv", "motion vector", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_MV }, INT_MIN, INT_MAX, V|D, "debug"}, -#endif {"dct_coeff", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_DCT_COEFF }, INT_MIN, INT_MAX, V|D, "debug"}, {"skip", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_SKIP }, INT_MIN, INT_MAX, V|D, "debug"}, {"startcode", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_STARTCODE }, INT_MIN, INT_MAX, V|D, "debug"}, @@ -259,18 +256,8 @@ static const AVOption avcodec_options[] = { {"er", "error recognition", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_ER }, INT_MIN, INT_MAX, V|D, "debug"}, {"mmco", "memory management control operations (H.264)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_MMCO }, INT_MIN, INT_MAX, V|D, "debug"}, {"bugs", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BUGS }, INT_MIN, INT_MAX, V|D, "debug"}, -#if FF_API_DEBUG_MV -{"vis_qp", "visualize quantization parameter (QP), lower QP are tinted greener", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_QP }, INT_MIN, INT_MAX, V|D, "debug"}, -{"vis_mb_type", "visualize block types", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MB_TYPE }, INT_MIN, INT_MAX, V|D, "debug"}, -#endif {"buffers", "picture buffer allocations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BUFFERS }, INT_MIN, INT_MAX, V|D, "debug"}, {"thread_ops", "threading operations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_THREADS }, INT_MIN, INT_MAX, V|D, "debug"}, -#if FF_API_DEBUG_MV -{"vismv", "visualize motion vectors (MVs)", OFFSET(debug_mv), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, V|D, "debug_mv"}, -{"pf", "forward predicted MVs of P-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_P_FOR }, INT_MIN, INT_MAX, V|D, "debug_mv"}, -{"bf", "forward predicted MVs of B-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_B_FOR }, INT_MIN, INT_MAX, V|D, "debug_mv"}, -{"bb", "backward predicted MVs of B-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_B_BACK }, INT_MIN, INT_MAX, V|D, "debug_mv"}, -#endif {"cmp", "full-pel ME compare function", OFFSET(me_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"}, {"subcmp", "sub-pel ME compare function", OFFSET(me_sub_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"}, {"mbcmp", "macroblock compare function", OFFSET(mb_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"}, diff --git a/libavcodec/version.h b/libavcodec/version.h index a12c322f49eb2..1f738a778aed4 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_DEBUG_MV -#define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_AC_VLC #define FF_API_AC_VLC (LIBAVCODEC_VERSION_MAJOR < 58) #endif From 0c7986df444273b0e53d3992ba9cc1108bd6a386 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 15:19:58 -0500 Subject: [PATCH 0081/2557] lavc: Drop deprecated workaround bugs options Illegal ac_vlc and old msmpeg4 detection deprecated in 10/2013. --- libavcodec/avcodec.h | 6 ------ libavcodec/options_table.h | 6 ------ libavcodec/version.h | 6 ------ 3 files changed, 18 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index b77f940d30b33..5ed3801d75ff8 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2596,16 +2596,10 @@ typedef struct AVCodecContext { */ int workaround_bugs; #define FF_BUG_AUTODETECT 1 ///< autodetection -#if FF_API_OLD_MSMPEG4 -#define FF_BUG_OLD_MSMPEG4 2 -#endif #define FF_BUG_XVID_ILACE 4 #define FF_BUG_UMP4 8 #define FF_BUG_NO_PADDING 16 #define FF_BUG_AMV 32 -#if FF_API_AC_VLC -#define FF_BUG_AC_VLC 0 ///< Will be removed, libavcodec can now handle these non-compliant files by default. -#endif #define FF_BUG_QPEL_CHROMA 64 #define FF_BUG_STD_QPEL 128 #define FF_BUG_QPEL_CHROMA2 256 diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 445515f0ee091..92fad60969914 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -135,16 +135,10 @@ static const AVOption avcodec_options[] = { {"codec_tag", NULL, OFFSET(codec_tag), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"bug", "work around not autodetected encoder bugs", OFFSET(workaround_bugs), AV_OPT_TYPE_FLAGS, {.i64 = FF_BUG_AUTODETECT }, INT_MIN, INT_MAX, V|D, "bug"}, {"autodetect", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_AUTODETECT }, INT_MIN, INT_MAX, V|D, "bug"}, -#if FF_API_OLD_MSMPEG4 -{"old_msmpeg4", "some old lavc-generated MSMPEG4v3 files (no autodetection)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_OLD_MSMPEG4 }, INT_MIN, INT_MAX, V|D, "bug"}, -#endif {"xvid_ilace", "Xvid interlacing bug (autodetected if FOURCC == XVIX)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_XVID_ILACE }, INT_MIN, INT_MAX, V|D, "bug"}, {"ump4", "(autodetected if FOURCC == UMP4)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_UMP4 }, INT_MIN, INT_MAX, V|D, "bug"}, {"no_padding", "padding bug (autodetected)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_NO_PADDING }, INT_MIN, INT_MAX, V|D, "bug"}, {"amv", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_AMV }, INT_MIN, INT_MAX, V|D, "bug"}, -#if FF_API_AC_VLC -{"ac_vlc", "illegal VLC bug (autodetected per FOURCC)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_AC_VLC }, INT_MIN, INT_MAX, V|D, "bug"}, -#endif {"qpel_chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_QPEL_CHROMA }, INT_MIN, INT_MAX, V|D, "bug"}, {"std_qpel", "old standard qpel (autodetected per FOURCC/version)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_STD_QPEL }, INT_MIN, INT_MAX, V|D, "bug"}, {"qpel_chroma2", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_QPEL_CHROMA2 }, INT_MIN, INT_MAX, V|D, "bug"}, diff --git a/libavcodec/version.h b/libavcodec/version.h index 1f738a778aed4..225ee52a64a3f 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,12 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_AC_VLC -#define FF_API_AC_VLC (LIBAVCODEC_VERSION_MAJOR < 58) -#endif -#ifndef FF_API_OLD_MSMPEG4 -#define FF_API_OLD_MSMPEG4 (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_ASPECT_EXTENDED #define FF_API_ASPECT_EXTENDED (LIBAVCODEC_VERSION_MAJOR < 58) #endif From c06e73929199c4bdbb32ffb3d81c27ea57dd1458 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 15:22:05 -0500 Subject: [PATCH 0082/2557] lavc: Drop deprecated extended aspect ratio symbol Deprecated in 10/2013. --- libavcodec/avcodec.h | 4 ---- libavcodec/h263.h | 2 -- libavcodec/version.h | 3 --- 3 files changed, 9 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 5ed3801d75ff8..76c86eb6bacfe 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1620,10 +1620,6 @@ typedef struct AVCodecContext { */ int coded_width, coded_height; -#if FF_API_ASPECT_EXTENDED -#define FF_ASPECT_EXTENDED 15 -#endif - /** * the number of pictures in a group of pictures, or 0 for intra_only * - encoding: Set by user. diff --git a/libavcodec/h263.h b/libavcodec/h263.h index 3e54204f0fcb6..ce697da20e68c 100644 --- a/libavcodec/h263.h +++ b/libavcodec/h263.h @@ -31,9 +31,7 @@ #include "h263data.h" #include "rl.h" -#if !FF_API_ASPECT_EXTENDED #define FF_ASPECT_EXTENDED 15 -#endif #define INT_BIT (CHAR_BIT * sizeof(int)) // The defines below define the number of bits that are read at once for diff --git a/libavcodec/version.h b/libavcodec/version.h index 225ee52a64a3f..bc8bdad0f4070 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_ASPECT_EXTENDED -#define FF_API_ASPECT_EXTENDED (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_ARCH_ALPHA #define FF_API_ARCH_ALPHA (LIBAVCODEC_VERSION_MAJOR < 58) #endif From 0871e2337777d9161e7f3554bcad19dabc9e15e1 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 15:27:16 -0500 Subject: [PATCH 0083/2557] lavc: Drop deprecated architectures symbols Alpha deprecated in 11/2013. Sh4 and sparc deprecated in 01/2014. --- libavcodec/avcodec.h | 9 --------- libavcodec/options_table.h | 6 ------ libavcodec/version.h | 9 --------- 3 files changed, 24 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 76c86eb6bacfe..1eb3ac6f4a5a9 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2734,9 +2734,6 @@ typedef struct AVCodecContext { #define FF_IDCT_SIMPLEMMX 3 #define FF_IDCT_ARM 7 #define FF_IDCT_ALTIVEC 8 -#if FF_API_ARCH_SH4 -#define FF_IDCT_SH4 9 -#endif #define FF_IDCT_SIMPLEARM 10 #if FF_API_UNUSED_MEMBERS #define FF_IDCT_IPP 13 @@ -2747,14 +2744,8 @@ typedef struct AVCodecContext { #endif /* FF_API_IDCT_XVIDMMX */ #define FF_IDCT_SIMPLEARMV5TE 16 #define FF_IDCT_SIMPLEARMV6 17 -#if FF_API_ARCH_SPARC -#define FF_IDCT_SIMPLEVIS 18 -#endif #define FF_IDCT_FAAN 20 #define FF_IDCT_SIMPLENEON 22 -#if FF_API_ARCH_ALPHA -#define FF_IDCT_SIMPLEALPHA 23 -#endif /** * bits per sample/pixel from the demuxer (needed for huffyuv). diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 92fad60969914..725779129234f 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -205,16 +205,10 @@ static const AVOption avcodec_options[] = { {"simplemmx", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEMMX }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"arm", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ARM }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"altivec", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ALTIVEC }, INT_MIN, INT_MAX, V|E|D, "idct"}, -#if FF_API_ARCH_SH4 -{"sh4", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SH4 }, INT_MIN, INT_MAX, V|E|D, "idct"}, -#endif {"simplearm", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARM }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"simplearmv5te", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV5TE }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"simplearmv6", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV6 }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"simpleneon", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLENEON }, INT_MIN, INT_MAX, V|E|D, "idct"}, -#if FF_API_ARCH_ALPHA -{"simplealpha", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEALPHA }, INT_MIN, INT_MAX, V|E|D, "idct"}, -#endif #if FF_API_UNUSED_MEMBERS {"ipp", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_IPP }, INT_MIN, INT_MAX, V|E|D, "idct"}, #endif /* FF_API_UNUSED_MEMBERS */ diff --git a/libavcodec/version.h b/libavcodec/version.h index bc8bdad0f4070..6f69f2d59cdfa 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_ARCH_ALPHA -#define FF_API_ARCH_ALPHA (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_XVMC #define FF_API_XVMC (LIBAVCODEC_VERSION_MAJOR < 58) #endif @@ -74,12 +71,6 @@ #ifndef FF_API_EMU_EDGE #define FF_API_EMU_EDGE (LIBAVCODEC_VERSION_MAJOR < 58) #endif -#ifndef FF_API_ARCH_SH4 -#define FF_API_ARCH_SH4 (LIBAVCODEC_VERSION_MAJOR < 58) -#endif -#ifndef FF_API_ARCH_SPARC -#define FF_API_ARCH_SPARC (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_UNUSED_MEMBERS #define FF_API_UNUSED_MEMBERS (LIBAVCODEC_VERSION_MAJOR < 58) #endif From dcc39ee10e82833ce24aa57926c00ffeb1948198 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 7 Dec 2016 08:18:41 +0100 Subject: [PATCH 0084/2557] lavc: Remove deprecated XvMC support hacks Deprecated in 11/2013. --- configure | 3 - libavcodec/4xm.c | 2 +- libavcodec/Makefile | 3 - libavcodec/allcodecs.c | 3 - libavcodec/asvdec.c | 2 +- libavcodec/avcodec.h | 17 -- libavcodec/bink.c | 2 +- libavcodec/blockdsp.c | 10 +- libavcodec/blockdsp.h | 10 +- libavcodec/cavs.c | 2 +- libavcodec/codec_desc.c | 11 +- libavcodec/dnxhddec.c | 2 +- libavcodec/dnxhdenc.c | 2 +- libavcodec/eamad.c | 2 +- libavcodec/eatqi.c | 2 +- libavcodec/error_resilience.c | 21 --- libavcodec/g2meet.c | 2 +- libavcodec/intrax8.c | 2 +- libavcodec/jvdec.c | 2 +- libavcodec/mdec.c | 2 +- libavcodec/mimic.c | 2 +- libavcodec/mjpegdec.c | 2 +- libavcodec/mpeg12dec.c | 103 ----------- libavcodec/mpegvideo.c | 29 +-- libavcodec/mpegvideo_xvmc.c | 337 ---------------------------------- libavcodec/options_table.h | 3 - libavcodec/vc1dec.c | 2 +- libavcodec/version.h | 3 - libavcodec/wmv2.c | 2 +- libavcodec/x86/blockdsp.c | 16 +- libavcodec/xvmc.h | 174 ------------------ libavcodec/xvmc_internal.h | 38 ---- libavutil/pixdesc.c | 10 - libavutil/pixfmt.h | 4 - libavutil/version.h | 3 - tests/checkasm/blockdsp.c | 4 +- 36 files changed, 25 insertions(+), 809 deletions(-) delete mode 100644 libavcodec/mpegvideo_xvmc.c delete mode 100644 libavcodec/xvmc.h delete mode 100644 libavcodec/xvmc_internal.h diff --git a/configure b/configure index 1c7887209ed2e..366520cf96b41 100755 --- a/configure +++ b/configure @@ -2073,8 +2073,6 @@ mp3on4_decoder_select="mpegaudio" mp3on4float_decoder_select="mpegaudio" mpc7_decoder_select="bswapdsp mpegaudiodsp" mpc8_decoder_select="mpegaudiodsp" -mpeg_xvmc_decoder_deps="X11_extensions_XvMClib_h" -mpeg_xvmc_decoder_select="mpeg2video_decoder" mpeg1video_decoder_select="error_resilience mpeg_er mpegvideo" mpeg1video_encoder_select="aandcttables mpegvideoenc" mpeg2video_decoder_select="error_resilience mpeg_er mpegvideo" @@ -4645,7 +4643,6 @@ check_header unistd.h check_header valgrind/valgrind.h check_header VideoDecodeAcceleration/VDADecoder.h check_header windows.h -check_header X11/extensions/XvMClib.h # it seems there are versions of clang in some distros that try to use the # gcc headers, which explodes for stdatomic diff --git a/libavcodec/4xm.c b/libavcodec/4xm.c index 28f839165e645..b419bfa268f10 100644 --- a/libavcodec/4xm.c +++ b/libavcodec/4xm.c @@ -960,7 +960,7 @@ static av_cold int decode_init(AVCodecContext *avctx) } f->version = AV_RL32(avctx->extradata) >> 16; - ff_blockdsp_init(&f->bdsp, avctx); + ff_blockdsp_init(&f->bdsp); ff_bswapdsp_init(&f->bbdsp); f->avctx = avctx; init_vlcs(f); diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2b1e2212489ed..3a55a28e27b30 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -13,7 +13,6 @@ HEADERS = avcodec.h \ vdpau.h \ version.h \ vorbis_parser.h \ - xvmc.h \ OBJS = allcodecs.o \ avpacket.o \ @@ -330,7 +329,6 @@ OBJS-$(CONFIG_MP3ON4_DECODER) += mpegaudiodec_fixed.o mpeg4audio.o OBJS-$(CONFIG_MP3ON4FLOAT_DECODER) += mpegaudiodec_float.o mpeg4audio.o OBJS-$(CONFIG_MPC7_DECODER) += mpc7.o mpc.o OBJS-$(CONFIG_MPC8_DECODER) += mpc8.o mpc.o -OBJS-$(CONFIG_MPEG_XVMC_DECODER) += mpegvideo_xvmc.o OBJS-$(CONFIG_MPEG1VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpeg12.o OBJS-$(CONFIG_MPEG2_QSV_DECODER) += qsvdec_other.o @@ -791,7 +789,6 @@ SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h SKIPHEADERS-$(CONFIG_LIBVPX) += libvpx.h -SKIPHEADERS-$(CONFIG_MPEG_XVMC_DECODER) += xvmc.h SKIPHEADERS-$(CONFIG_NVENC) += nvenc.h SKIPHEADERS-$(CONFIG_QSV) += qsv.h qsv_internal.h SKIPHEADERS-$(CONFIG_QSVDEC) += qsvdec.h diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index b9936c57f7496..556bdb43f3e84 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -203,9 +203,6 @@ void avcodec_register_all(void) REGISTER_DECODER(MJPEGB, mjpegb); REGISTER_DECODER(MMVIDEO, mmvideo); REGISTER_DECODER(MOTIONPIXELS, motionpixels); -#if FF_API_XVMC - REGISTER_DECODER(MPEG_XVMC, mpeg_xvmc); -#endif /* FF_API_XVMC */ REGISTER_ENCDEC (MPEG1VIDEO, mpeg1video); REGISTER_ENCDEC (MPEG2VIDEO, mpeg2video); REGISTER_DECODER(MPEG2_MMAL, mpeg2_mmal); diff --git a/libavcodec/asvdec.c b/libavcodec/asvdec.c index bd87512d131c8..7aa16f02db4ec 100644 --- a/libavcodec/asvdec.c +++ b/libavcodec/asvdec.c @@ -282,7 +282,7 @@ static av_cold int decode_init(AVCodecContext *avctx) } ff_asv_common_init(avctx); - ff_blockdsp_init(&a->bdsp, avctx); + ff_blockdsp_init(&a->bdsp); ff_idctdsp_init(&a->idsp, avctx); init_vlcs(a); ff_init_scantable(a->idsp.idct_permutation, &a->scantable, ff_asv_scantab); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 1eb3ac6f4a5a9..8567c8b28f210 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -218,9 +218,6 @@ enum AVCodecID { /* video codecs */ AV_CODEC_ID_MPEG1VIDEO, AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding -#if FF_API_XVMC - AV_CODEC_ID_MPEG2VIDEO_XVMC, -#endif /* FF_API_XVMC */ AV_CODEC_ID_H261, AV_CODEC_ID_H263, AV_CODEC_ID_RV10, @@ -1010,10 +1007,6 @@ typedef struct RcOverride{ */ #define CODEC_CAP_DR1 0x0002 #define CODEC_CAP_TRUNCATED 0x0008 -#if FF_API_XVMC -/* Codec can export data for HW decoding (XvMC). */ -#define CODEC_CAP_HWACCEL 0x0010 -#endif /* FF_API_XVMC */ /** * Encoder or decoder requires flushing with NULL input at the end in order to * give the complete and correct output. @@ -1957,16 +1950,6 @@ typedef struct AVCodecContext { #define SLICE_FLAG_ALLOW_FIELD 0x0002 ///< allow draw_horiz_band() with field slices (MPEG-2 field pics) #define SLICE_FLAG_ALLOW_PLANE 0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1) -#if FF_API_XVMC - /** - * XVideo Motion Acceleration - * - encoding: forbidden - * - decoding: set by decoder - * @deprecated XvMC support is slated for removal. - */ - attribute_deprecated int xvmc_acceleration; -#endif /* FF_API_XVMC */ - /** * macroblock decision mode * - encoding: Set by user. diff --git a/libavcodec/bink.c b/libavcodec/bink.c index 74db80a2be597..84388b86aa7fc 100644 --- a/libavcodec/bink.c +++ b/libavcodec/bink.c @@ -1309,7 +1309,7 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->pix_fmt = c->has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P; - ff_blockdsp_init(&c->bdsp, avctx); + ff_blockdsp_init(&c->bdsp); ff_hpeldsp_init(&c->hdsp, avctx->flags); ff_binkdsp_init(&c->binkdsp); diff --git a/libavcodec/blockdsp.c b/libavcodec/blockdsp.c index 2c396f1f610ea..a2c0e579cf193 100644 --- a/libavcodec/blockdsp.c +++ b/libavcodec/blockdsp.c @@ -20,10 +20,10 @@ #include #include "config.h" + #include "libavutil/attributes.h" -#include "avcodec.h" + #include "blockdsp.h" -#include "version.h" static void clear_block_8_c(int16_t *block) { @@ -57,7 +57,7 @@ static void fill_block8_c(uint8_t *block, uint8_t value, ptrdiff_t line_size, } } -av_cold void ff_blockdsp_init(BlockDSPContext *c, AVCodecContext *avctx) +av_cold void ff_blockdsp_init(BlockDSPContext *c) { c->clear_block = clear_block_8_c; c->clear_blocks = clear_blocks_8_c; @@ -70,9 +70,5 @@ av_cold void ff_blockdsp_init(BlockDSPContext *c, AVCodecContext *avctx) if (ARCH_PPC) ff_blockdsp_init_ppc(c); if (ARCH_X86) -#if FF_API_XVMC - ff_blockdsp_init_x86(c, avctx); -#else ff_blockdsp_init_x86(c); -#endif /* FF_API_XVMC */ } diff --git a/libavcodec/blockdsp.h b/libavcodec/blockdsp.h index e555d29b6032f..ecce2c3076d9e 100644 --- a/libavcodec/blockdsp.h +++ b/libavcodec/blockdsp.h @@ -22,9 +22,6 @@ #include #include -#include "avcodec.h" -#include "version.h" - /* add and put pixel (decoding) * Block sizes for op_pixels_func are 8x4,8x8 16x8 16x16. * h for op_pixels_func is limited to { width / 2, width }, @@ -39,15 +36,10 @@ typedef struct BlockDSPContext { op_fill_func fill_block_tab[2]; } BlockDSPContext; -void ff_blockdsp_init(BlockDSPContext *c, AVCodecContext *avctx); +void ff_blockdsp_init(BlockDSPContext *c); void ff_blockdsp_init_arm(BlockDSPContext *c); void ff_blockdsp_init_ppc(BlockDSPContext *c); -#if FF_API_XVMC -void ff_blockdsp_init_x86(BlockDSPContext *c, - AVCodecContext *avctx); -#else void ff_blockdsp_init_x86(BlockDSPContext *c); -#endif /* FF_API_XVMC */ #endif /* AVCODEC_BLOCKDSP_H */ diff --git a/libavcodec/cavs.c b/libavcodec/cavs.c index 6959f54404635..323091324a132 100644 --- a/libavcodec/cavs.c +++ b/libavcodec/cavs.c @@ -760,7 +760,7 @@ av_cold int ff_cavs_init(AVCodecContext *avctx) { AVSContext *h = avctx->priv_data; - ff_blockdsp_init(&h->bdsp, avctx); + ff_blockdsp_init(&h->bdsp); ff_h264chroma_init(&h->h264chroma, 8); ff_idctdsp_init(&h->idsp, avctx); ff_videodsp_init(&h->vdsp, 8); diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 8b9ec40e598ee..7103b5890a994 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -20,9 +20,9 @@ #include "libavutil/common.h" #include "libavutil/internal.h" + #include "avcodec.h" #include "profiles.h" -#include "version.h" static const AVCodecDescriptor codec_descriptors[] = { /* video codecs */ @@ -41,15 +41,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg2_video_profiles), }, -#if FF_API_XVMC - { - .id = AV_CODEC_ID_MPEG2VIDEO_XVMC, - .type = AVMEDIA_TYPE_VIDEO, - .name = "mpegvideo_xvmc", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-1/2 video XvMC (X-Video Motion Compensation)"), - .props = AV_CODEC_PROP_LOSSY, - }, -#endif /* FF_API_XVMC */ { .id = AV_CODEC_ID_H261, .type = AVMEDIA_TYPE_VIDEO, diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c index 75247eaff439f..fd58795de3d24 100644 --- a/libavcodec/dnxhddec.c +++ b/libavcodec/dnxhddec.c @@ -162,7 +162,7 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, return AVERROR_INVALIDDATA; } if (ctx->bit_depth != old_bit_depth) { - ff_blockdsp_init(&ctx->bdsp, ctx->avctx); + ff_blockdsp_init(&ctx->bdsp); ff_idctdsp_init(&ctx->idsp, ctx->avctx); } diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c index 0c6c59cec8627..f5fd9e9a38197 100644 --- a/libavcodec/dnxhdenc.c +++ b/libavcodec/dnxhdenc.c @@ -313,7 +313,7 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) avctx->bits_per_raw_sample = ctx->cid_table->bit_depth; - ff_blockdsp_init(&ctx->bdsp, avctx); + ff_blockdsp_init(&ctx->bdsp); ff_fdctdsp_init(&ctx->m.fdsp, avctx); ff_mpv_idct_init(&ctx->m); ff_mpegvideoencdsp_init(&ctx->m.mpvencdsp, avctx); diff --git a/libavcodec/eamad.c b/libavcodec/eamad.c index 7509c2ddd430b..0f8a4d0e23d76 100644 --- a/libavcodec/eamad.c +++ b/libavcodec/eamad.c @@ -67,7 +67,7 @@ static av_cold int decode_init(AVCodecContext *avctx) MadContext *s = avctx->priv_data; s->avctx = avctx; avctx->pix_fmt = AV_PIX_FMT_YUV420P; - ff_blockdsp_init(&s->bdsp, avctx); + ff_blockdsp_init(&s->bdsp); ff_bswapdsp_init(&s->bbdsp); ff_idctdsp_init(&s->idsp, avctx); ff_init_scantable_permutation(s->idsp.idct_permutation, FF_IDCT_PERM_NONE); diff --git a/libavcodec/eatqi.c b/libavcodec/eatqi.c index cb70cda7fedbf..1ae4d3fb701cf 100644 --- a/libavcodec/eatqi.c +++ b/libavcodec/eatqi.c @@ -57,7 +57,7 @@ static av_cold int tqi_decode_init(AVCodecContext *avctx) { TqiContext *t = avctx->priv_data; - ff_blockdsp_init(&t->bdsp, avctx); + ff_blockdsp_init(&t->bdsp); ff_bswapdsp_init(&t->bsdsp); ff_idctdsp_init(&t->idsp, avctx); ff_init_scantable_permutation(t->idsp.idct_permutation, FF_IDCT_PERM_NONE); diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index bf3a6882c729d..54b7b3cc0fe83 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -35,7 +35,6 @@ #include "mpegvideo.h" #include "rectangle.h" #include "thread.h" -#include "version.h" /** * @param stride the number of MVs to get to the next row @@ -677,16 +676,6 @@ static int is_intra_more_likely(ERContext *s) if (undamaged_count < 5) return 0; // almost all MBs damaged -> use temporal prediction -#if FF_API_XVMC -FF_DISABLE_DEPRECATION_WARNINGS - // prevent dsp.sad() check, that requires access to the image - if (CONFIG_MPEG_XVMC_DECODER && - s->avctx->xvmc_acceleration && - s->cur_pic.f->pict_type == AV_PICTURE_TYPE_I) - return 1; -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_XVMC */ - skip_amount = FFMAX(undamaged_count / 50, 1); // check only up to 50 MBs is_intra_likely = 0; @@ -1102,13 +1091,6 @@ void ff_er_frame_end(ERContext *s) } else guess_mv(s); -#if FF_API_XVMC -FF_DISABLE_DEPRECATION_WARNINGS - /* the filters below are not XvMC compatible, skip them */ - if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) - goto ec_clean; -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_XVMC */ /* fill DC for inter blocks */ for (mb_y = 0; mb_y < s->mb_height; mb_y++) { for (mb_x = 0; mb_x < s->mb_width; mb_x++) { @@ -1202,9 +1184,6 @@ FF_ENABLE_DEPRECATION_WARNINGS s->mb_height, linesize[2], 0); } -#if FF_API_XVMC -ec_clean: -#endif /* clean a few tables */ for (i = 0; i < s->mb_num; i++) { const int mb_xy = s->mb_index2xy[i]; diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index 511ea534b8830..d7dc97615360f 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -199,7 +199,7 @@ static av_cold int jpg_init(AVCodecContext *avctx, JPGContext *c) if (ret) return ret; - ff_blockdsp_init(&c->bdsp, avctx); + ff_blockdsp_init(&c->bdsp); ff_idctdsp_init(&c->idsp, avctx); ff_init_scantable(c->idsp.idct_permutation, &c->scantable, ff_zigzag_direct); diff --git a/libavcodec/intrax8.c b/libavcodec/intrax8.c index 2a73a072dbfe1..d32bb059e17aa 100644 --- a/libavcodec/intrax8.c +++ b/libavcodec/intrax8.c @@ -759,7 +759,7 @@ av_cold int ff_intrax8_common_init(AVCodecContext *avctx, ff_wmv1_scantable[3]); ff_intrax8dsp_init(&w->dsp); - ff_blockdsp_init(&w->bdsp, avctx); + ff_blockdsp_init(&w->bdsp); return 0; } diff --git a/libavcodec/jvdec.c b/libavcodec/jvdec.c index 5f5a825cd703e..3a92b584c3615 100644 --- a/libavcodec/jvdec.c +++ b/libavcodec/jvdec.c @@ -55,7 +55,7 @@ static av_cold int decode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); avctx->pix_fmt = AV_PIX_FMT_PAL8; - ff_blockdsp_init(&s->bdsp, avctx); + ff_blockdsp_init(&s->bdsp); return 0; } diff --git a/libavcodec/mdec.c b/libavcodec/mdec.c index 4b6056e15cffe..c0db368ca6153 100644 --- a/libavcodec/mdec.c +++ b/libavcodec/mdec.c @@ -220,7 +220,7 @@ static av_cold int decode_init(AVCodecContext *avctx) a->avctx = avctx; - ff_blockdsp_init(&a->bdsp, avctx); + ff_blockdsp_init(&a->bdsp); ff_idctdsp_init(&a->idsp, avctx); ff_mpeg12_init_vlcs(); ff_init_scantable(a->idsp.idct_permutation, &a->scantable, diff --git a/libavcodec/mimic.c b/libavcodec/mimic.c index 1ec27b292668f..31d07ecd5024a 100644 --- a/libavcodec/mimic.c +++ b/libavcodec/mimic.c @@ -148,7 +148,7 @@ static av_cold int mimic_decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "error initializing vlc table\n"); return ret; } - ff_blockdsp_init(&ctx->bdsp, avctx); + ff_blockdsp_init(&ctx->bdsp); ff_bswapdsp_init(&ctx->bbdsp); ff_hpeldsp_init(&ctx->hdsp, avctx->flags); ff_idctdsp_init(&ctx->idsp, avctx); diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index f6e903853901a..13d3e8cb02864 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -113,7 +113,7 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) } s->avctx = avctx; - ff_blockdsp_init(&s->bdsp, avctx); + ff_blockdsp_init(&s->bdsp); ff_hpeldsp_init(&s->hdsp, avctx->flags); ff_idctdsp_init(&s->idsp, avctx); ff_init_scantable(s->idsp.idct_permutation, &s->scantable, diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index afdd652b6afee..528a4ed16db09 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -45,7 +45,6 @@ #include "profiles.h" #include "thread.h" #include "version.h" -#include "xvmc_internal.h" typedef struct Mpeg1Context { MpegEncContext mpeg_enc_ctx; @@ -763,13 +762,6 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) memset(s->last_mv, 0, sizeof(s->last_mv)); } s->mb_intra = 1; -#if FF_API_XVMC -FF_DISABLE_DEPRECATION_WARNINGS - // if 1, we memcpy blocks in xvmcvideo - if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration > 1) - ff_xvmc_pack_pblocks(s, -1); // inter are always full blocks -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_XVMC */ if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { if (s->avctx->flags2 & AV_CODEC_FLAG2_FAST) { @@ -992,14 +984,6 @@ FF_ENABLE_DEPRECATION_WARNINGS return AVERROR_INVALIDDATA; } -#if FF_API_XVMC -FF_DISABLE_DEPRECATION_WARNINGS - // if 1, we memcpy blocks in xvmcvideo - if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration > 1) - ff_xvmc_pack_pblocks(s, cbp); -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_XVMC */ - if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { if (s->avctx->flags2 & AV_CODEC_FLAG2_FAST) { for (i = 0; i < 6; i++) { @@ -1121,14 +1105,6 @@ static void quant_matrix_rebuild(uint16_t *matrix, const uint8_t *old_perm, matrix[new_perm[i]] = temp_matrix[old_perm[i]]; } -#if FF_API_XVMC -static const enum AVPixelFormat pixfmt_xvmc_mpg2_420[] = { - AV_PIX_FMT_XVMC_MPEG2_IDCT, - AV_PIX_FMT_XVMC_MPEG2_MC, - AV_PIX_FMT_NONE -}; -#endif /* FF_API_XVMC */ - static const enum AVPixelFormat mpeg12_hwaccel_pixfmt_list_420[] = { #if CONFIG_MPEG2_DXVA2_HWACCEL AV_PIX_FMT_DXVA2_VLD, @@ -1162,13 +1138,6 @@ static enum AVPixelFormat mpeg_get_pixelformat(AVCodecContext *avctx) MpegEncContext *s = &s1->mpeg_enc_ctx; const enum AVPixelFormat *pix_fmts; -#if FF_API_XVMC -FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->xvmc_acceleration) - return ff_get_format(avctx, pixfmt_xvmc_mpg2_420); -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_XVMC */ - if (s->chroma_format < 2) pix_fmts = mpeg12_hwaccel_pixfmt_list_420; else if (s->chroma_format == 2) @@ -1273,12 +1242,7 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) avctx->pix_fmt = mpeg_get_pixelformat(avctx); // until then pix_fmt may be changed right after codec init -#if FF_API_XVMC - if ((avctx->pix_fmt == AV_PIX_FMT_XVMC_MPEG2_IDCT || - avctx->hwaccel) && avctx->idct_algo == FF_IDCT_AUTO) -#else if (avctx->hwaccel && avctx->idct_algo == FF_IDCT_AUTO) -#endif /* FF_API_XVMC */ avctx->idct_algo = FF_IDCT_SIMPLE; /* Quantization matrices may need reordering @@ -1661,16 +1625,6 @@ static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size) return ret; } -#if FF_API_XVMC -FF_DISABLE_DEPRECATION_WARNINGS -// ff_mpv_frame_start will call this function too, -// but we need to call it on every field - if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) - if (ff_xvmc_field_start(s, avctx) < 0) - return -1; -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_XVMC */ - return 0; } @@ -1779,14 +1733,6 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y, } for (;;) { -#if FF_API_XVMC -FF_DISABLE_DEPRECATION_WARNINGS - // If 1, we memcpy blocks in xvmcvideo. - if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration > 1) - ff_xvmc_init_block(s); // set s->block -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_XVMC */ - if ((ret = mpeg_decode_mb(s, s->block)) < 0) return ret; @@ -1991,13 +1937,6 @@ static int slice_end(AVCodecContext *avctx, AVFrame *pict) "hardware accelerator failed to decode picture\n"); } -#if FF_API_XVMC -FF_DISABLE_DEPRECATION_WARNINGS - if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) - ff_xvmc_field_end(s); -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_XVMC */ - /* end of slice reached */ if (/* s->mb_y << field_pic == s->mb_height && */ !s->first_field) { /* end of image */ @@ -2135,12 +2074,7 @@ static int vcr2_init_sequence(AVCodecContext *avctx) avctx->pix_fmt = mpeg_get_pixelformat(avctx); -#if FF_API_XVMC - if ((avctx->pix_fmt == AV_PIX_FMT_XVMC_MPEG2_IDCT || avctx->hwaccel) && - avctx->idct_algo == FF_IDCT_AUTO) -#else if (avctx->hwaccel && avctx->idct_algo == FF_IDCT_AUTO) -#endif /* FF_API_XVMC */ avctx->idct_algo = FF_IDCT_SIMPLE; ff_mpv_idct_init(s); @@ -2682,40 +2616,3 @@ AVCodec ff_mpeg2video_decoder = { .flush = flush, .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg2_video_profiles), }; - -#if FF_API_XVMC -#if CONFIG_MPEG_XVMC_DECODER -static av_cold int mpeg_mc_decode_init(AVCodecContext *avctx) -{ - if (avctx->active_thread_type & FF_THREAD_SLICE) - return -1; - if (!(avctx->slice_flags & SLICE_FLAG_CODED_ORDER)) - return -1; - if (!(avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD)) { - ff_dlog(avctx, "mpeg12.c: XvMC decoder will work better if SLICE_FLAG_ALLOW_FIELD is set\n"); - } - mpeg_decode_init(avctx); - - avctx->pix_fmt = AV_PIX_FMT_XVMC_MPEG2_IDCT; - avctx->xvmc_acceleration = 2; // 2 - the blocks are packed! - - return 0; -} - -AVCodec ff_mpeg_xvmc_decoder = { - .name = "mpegvideo_xvmc", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-1/2 video XvMC (X-Video Motion Compensation)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO_XVMC, - .priv_data_size = sizeof(Mpeg1Context), - .init = mpeg_mc_decode_init, - .close = mpeg_decode_end, - .decode = mpeg_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | - AV_CODEC_CAP_TRUNCATED | CODEC_CAP_HWACCEL | - AV_CODEC_CAP_DELAY, - .flush = flush, -}; - -#endif -#endif /* FF_API_XVMC */ diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 379b690b4dd1e..ca3cd2e799b58 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -44,7 +44,6 @@ #include "mjpegenc.h" #include "msmpeg4.h" #include "qpeldsp.h" -#include "xvmc_internal.h" #include "thread.h" #include "wmv2.h" #include @@ -270,7 +269,7 @@ static void dct_unquantize_h263_inter_c(MpegEncContext *s, /* init common dct for both encoder and decoder */ static av_cold int dct_init(MpegEncContext *s) { - ff_blockdsp_init(&s->bdsp, s->avctx); + ff_blockdsp_init(&s->bdsp); ff_hpeldsp_init(&s->hdsp, s->avctx->flags); ff_mpegvideodsp_init(&s->mdsp); ff_videodsp_init(&s->vdsp, s->avctx->bits_per_raw_sample); @@ -1249,29 +1248,12 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) s->dct_unquantize_inter = s->dct_unquantize_mpeg1_inter; } -#if FF_API_XVMC -FF_DISABLE_DEPRECATION_WARNINGS - if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) - return ff_xvmc_field_start(s, avctx); -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_XVMC */ - return 0; } /* called after a frame has been decoded. */ void ff_mpv_frame_end(MpegEncContext *s) { -#if FF_API_XVMC -FF_DISABLE_DEPRECATION_WARNINGS - /* redraw edges for the frame if decoding didn't complete */ - // just to make sure that all data is rendered. - if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) { - ff_xvmc_field_end(s); - } else -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_XVMC */ - emms_c(); if (s->current_picture.reference) @@ -1492,15 +1474,6 @@ void mpv_decode_mb_internal(MpegEncContext *s, int16_t block[12][64], { const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; -#if FF_API_XVMC -FF_DISABLE_DEPRECATION_WARNINGS - if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration){ - ff_xvmc_decode_mb(s);//xvmc uses pblocks - return; - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_XVMC */ - if(s->avctx->debug&FF_DEBUG_DCT_COEFF) { /* print DCT coefficients */ int i,j; diff --git a/libavcodec/mpegvideo_xvmc.c b/libavcodec/mpegvideo_xvmc.c deleted file mode 100644 index b7de79c583247..0000000000000 --- a/libavcodec/mpegvideo_xvmc.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * XVideo Motion Compensation - * Copyright (c) 2003 Ivan Kalvachev - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#include "avcodec.h" -#include "mpegutils.h" -#include "mpegvideo.h" - -#undef NDEBUG -#include - -#include "xvmc.h" -#include "xvmc_internal.h" -#include "version.h" - -#if FF_API_XVMC - -/** - * Initialize the block field of the MpegEncContext pointer passed as - * parameter after making sure that the data is not corrupted. - * In order to implement something like direct rendering instead of decoding - * coefficients in s->blocks and then copying them, copy them directly - * into the data_blocks array provided by xvmc. - */ -void ff_xvmc_init_block(MpegEncContext *s) -{ - struct xvmc_pix_fmt *render = (struct xvmc_pix_fmt*)s->current_picture.f->data[2]; - assert(render && render->xvmc_id == AV_XVMC_ID); - - s->block = (int16_t (*)[64])(render->data_blocks + render->next_free_data_block_num * 64); -} - -/** - * Fill individual block pointers, so there are no gaps in the data_block array - * in case not all blocks in the macroblock are coded. - */ -void ff_xvmc_pack_pblocks(MpegEncContext *s, int cbp) -{ - int i, j = 0; - const int mb_block_count = 4 + (1 << s->chroma_format); - - cbp <<= 12-mb_block_count; - for (i = 0; i < mb_block_count; i++) { - if (cbp & (1 << 11)) - s->pblocks[i] = &s->block[j++]; - else - s->pblocks[i] = NULL; - cbp += cbp; - } -} - -/** - * Find and store the surfaces that are used as reference frames. - * This function should be called for every new field and/or frame. - * It should be safe to call the function a few times for the same field. - */ -int ff_xvmc_field_start(MpegEncContext *s, AVCodecContext *avctx) -{ - struct xvmc_pix_fmt *last, *next, *render = (struct xvmc_pix_fmt*)s->current_picture.f->data[2]; - const int mb_block_count = 4 + (1 << s->chroma_format); - - assert(avctx); - if (!render || render->xvmc_id != AV_XVMC_ID || - !render->data_blocks || !render->mv_blocks || - (unsigned int)render->allocated_mv_blocks > INT_MAX/(64*6) || - (unsigned int)render->allocated_data_blocks > INT_MAX/64 || - !render->p_surface) { - av_log(avctx, AV_LOG_ERROR, - "Render token doesn't look as expected.\n"); - return -1; // make sure that this is a render packet - } - - if (render->filled_mv_blocks_num) { - av_log(avctx, AV_LOG_ERROR, - "Rendering surface contains %i unprocessed blocks.\n", - render->filled_mv_blocks_num); - return -1; - } - if (render->allocated_mv_blocks < 1 || - render->allocated_data_blocks < render->allocated_mv_blocks*mb_block_count || - render->start_mv_blocks_num >= render->allocated_mv_blocks || - render->next_free_data_block_num > - render->allocated_data_blocks - - mb_block_count*(render->allocated_mv_blocks-render->start_mv_blocks_num)) { - av_log(avctx, AV_LOG_ERROR, - "Rendering surface doesn't provide enough block structures to work with.\n"); - return -1; - } - - render->picture_structure = s->picture_structure; - render->flags = s->first_field ? 0 : XVMC_SECOND_FIELD; - render->p_future_surface = NULL; - render->p_past_surface = NULL; - - switch(s->pict_type) { - case AV_PICTURE_TYPE_I: - return 0; // no prediction from other frames - case AV_PICTURE_TYPE_B: - next = (struct xvmc_pix_fmt*)s->next_picture.f->data[2]; - if (!next) - return -1; - if (next->xvmc_id != AV_XVMC_ID) - return -1; - render->p_future_surface = next->p_surface; - // no return here, going to set forward prediction - case AV_PICTURE_TYPE_P: - last = (struct xvmc_pix_fmt*)s->last_picture.f->data[2]; - if (!last) - last = render; // predict second field from the first - if (last->xvmc_id != AV_XVMC_ID) - return -1; - render->p_past_surface = last->p_surface; - return 0; - } - -return -1; -} - -/** - * Complete frame/field rendering by passing any remaining blocks. - * Normally ff_draw_horiz_band() is called for each slice, however, - * some leftover blocks, for example from error_resilience(), may remain. - * It should be safe to call the function a few times for the same field. - */ -void ff_xvmc_field_end(MpegEncContext *s) -{ - struct xvmc_pix_fmt *render = (struct xvmc_pix_fmt*)s->current_picture.f->data[2]; - assert(render); - - if (render->filled_mv_blocks_num > 0) - ff_mpeg_draw_horiz_band(s, 0, 0); -} - -/** - * Synthesize the data needed by XvMC to render one macroblock of data. - * Fill all relevant fields, if necessary do IDCT. - */ -void ff_xvmc_decode_mb(MpegEncContext *s) -{ - XvMCMacroBlock *mv_block; - struct xvmc_pix_fmt *render; - int i, cbp, blocks_per_mb; - - const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; - - - if (s->encoding) { - av_log(s->avctx, AV_LOG_ERROR, "XVMC doesn't support encoding!!!\n"); - return; - } - - // from ff_mpv_decode_mb(), update DC predictors for P macroblocks - if (!s->mb_intra) { - s->last_dc[0] = - s->last_dc[1] = - s->last_dc[2] = 128 << s->intra_dc_precision; - } - - // MC doesn't skip blocks - s->mb_skipped = 0; - - - // Do I need to export quant when I could not perform postprocessing? - // Anyway, it doesn't hurt. - s->current_picture.qscale_table[mb_xy] = s->qscale; - - // start of XVMC-specific code - render = (struct xvmc_pix_fmt*)s->current_picture.f->data[2]; - assert(render); - assert(render->xvmc_id == AV_XVMC_ID); - assert(render->mv_blocks); - - // take the next free macroblock - mv_block = &render->mv_blocks[render->start_mv_blocks_num + - render->filled_mv_blocks_num]; - - mv_block->x = s->mb_x; - mv_block->y = s->mb_y; - mv_block->dct_type = s->interlaced_dct; // XVMC_DCT_TYPE_FRAME/FIELD; - if (s->mb_intra) { - mv_block->macroblock_type = XVMC_MB_TYPE_INTRA; // no MC, all done - } else { - mv_block->macroblock_type = XVMC_MB_TYPE_PATTERN; - - if (s->mv_dir & MV_DIR_FORWARD) { - mv_block->macroblock_type |= XVMC_MB_TYPE_MOTION_FORWARD; - // PMV[n][dir][xy] = mv[dir][n][xy] - mv_block->PMV[0][0][0] = s->mv[0][0][0]; - mv_block->PMV[0][0][1] = s->mv[0][0][1]; - mv_block->PMV[1][0][0] = s->mv[0][1][0]; - mv_block->PMV[1][0][1] = s->mv[0][1][1]; - } - if (s->mv_dir & MV_DIR_BACKWARD) { - mv_block->macroblock_type |= XVMC_MB_TYPE_MOTION_BACKWARD; - mv_block->PMV[0][1][0] = s->mv[1][0][0]; - mv_block->PMV[0][1][1] = s->mv[1][0][1]; - mv_block->PMV[1][1][0] = s->mv[1][1][0]; - mv_block->PMV[1][1][1] = s->mv[1][1][1]; - } - - switch(s->mv_type) { - case MV_TYPE_16X16: - mv_block->motion_type = XVMC_PREDICTION_FRAME; - break; - case MV_TYPE_16X8: - mv_block->motion_type = XVMC_PREDICTION_16x8; - break; - case MV_TYPE_FIELD: - mv_block->motion_type = XVMC_PREDICTION_FIELD; - if (s->picture_structure == PICT_FRAME) { - mv_block->PMV[0][0][1] <<= 1; - mv_block->PMV[1][0][1] <<= 1; - mv_block->PMV[0][1][1] <<= 1; - mv_block->PMV[1][1][1] <<= 1; - } - break; - case MV_TYPE_DMV: - mv_block->motion_type = XVMC_PREDICTION_DUAL_PRIME; - if (s->picture_structure == PICT_FRAME) { - - mv_block->PMV[0][0][0] = s->mv[0][0][0]; // top from top - mv_block->PMV[0][0][1] = s->mv[0][0][1] << 1; - - mv_block->PMV[0][1][0] = s->mv[0][0][0]; // bottom from bottom - mv_block->PMV[0][1][1] = s->mv[0][0][1] << 1; - - mv_block->PMV[1][0][0] = s->mv[0][2][0]; // dmv00, top from bottom - mv_block->PMV[1][0][1] = s->mv[0][2][1] << 1; // dmv01 - - mv_block->PMV[1][1][0] = s->mv[0][3][0]; // dmv10, bottom from top - mv_block->PMV[1][1][1] = s->mv[0][3][1] << 1; // dmv11 - - } else { - mv_block->PMV[0][1][0] = s->mv[0][2][0]; // dmv00 - mv_block->PMV[0][1][1] = s->mv[0][2][1]; // dmv01 - } - break; - default: - assert(0); - } - - mv_block->motion_vertical_field_select = 0; - - // set correct field references - if (s->mv_type == MV_TYPE_FIELD || s->mv_type == MV_TYPE_16X8) { - mv_block->motion_vertical_field_select |= s->field_select[0][0]; - mv_block->motion_vertical_field_select |= s->field_select[1][0] << 1; - mv_block->motion_vertical_field_select |= s->field_select[0][1] << 2; - mv_block->motion_vertical_field_select |= s->field_select[1][1] << 3; - } - } // !intra - // time to handle data blocks - mv_block->index = render->next_free_data_block_num; - - blocks_per_mb = 6; - if (s->chroma_format >= 2) { - blocks_per_mb = 4 + (1 << s->chroma_format); - } - - // calculate cbp - cbp = 0; - for (i = 0; i < blocks_per_mb; i++) { - cbp += cbp; - if (s->block_last_index[i] >= 0) - cbp++; - } - - if (s->avctx->flags & AV_CODEC_FLAG_GRAY) { - if (s->mb_intra) { // intra frames are always full chroma blocks - for (i = 4; i < blocks_per_mb; i++) { - memset(s->pblocks[i], 0, sizeof(*s->pblocks[i])); // so we need to clear them - if (!render->unsigned_intra) - *s->pblocks[i][0] = 1 << 10; - } - } else { - cbp &= 0xf << (blocks_per_mb - 4); - blocks_per_mb = 4; // luminance blocks only - } - } - mv_block->coded_block_pattern = cbp; - if (cbp == 0) - mv_block->macroblock_type &= ~XVMC_MB_TYPE_PATTERN; - - for (i = 0; i < blocks_per_mb; i++) { - if (s->block_last_index[i] >= 0) { - // I do not have unsigned_intra MOCO to test, hope it is OK. - if (s->mb_intra && (render->idct || !render->unsigned_intra)) - *s->pblocks[i][0] -= 1 << 10; - if (!render->idct) { - s->idsp.idct(*s->pblocks[i]); - /* It is unclear if MC hardware requires pixel diff values to be - * in the range [-255;255]. TODO: Clipping if such hardware is - * ever found. As of now it would only be an unnecessary - * slowdown. */ - } - // copy blocks only if the codec doesn't support pblocks reordering - if (s->avctx->xvmc_acceleration == 1) { - memcpy(&render->data_blocks[render->next_free_data_block_num*64], - s->pblocks[i], sizeof(*s->pblocks[i])); - } - render->next_free_data_block_num++; - } - } - render->filled_mv_blocks_num++; - - assert(render->filled_mv_blocks_num <= render->allocated_mv_blocks); - assert(render->next_free_data_block_num <= render->allocated_data_blocks); - /* The above conditions should not be able to fail as long as this function - * is used and the following 'if ()' automatically calls a callback to free - * blocks. */ - - - if (render->filled_mv_blocks_num == render->allocated_mv_blocks) - ff_mpeg_draw_horiz_band(s, 0, 0); -} - -#endif /* FF_API_XVMC */ diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 725779129234f..5e3540d2ddccb 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -294,9 +294,6 @@ static const AVOption avcodec_options[] = { {"context", "context model", OFFSET(context_model), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, #endif {"slice_flags", NULL, OFFSET(slice_flags), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, -#if FF_API_XVMC -{"xvmc_acceleration", NULL, OFFSET(xvmc_acceleration), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, -#endif /* FF_API_XVMC */ {"mbd", "macroblock decision algorithm (high quality mode)", OFFSET(mb_decision), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "mbd"}, {"simple", "use mbcmp (default)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_SIMPLE }, INT_MIN, INT_MAX, V|E, "mbd"}, {"bits", "use fewest bits", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_BITS }, INT_MIN, INT_MAX, V|E, "mbd"}, diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index b26fbf2efffce..89b4f4bdce298 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -431,7 +431,7 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) if (ff_vc1_init_common(v) < 0) return -1; - ff_blockdsp_init(&s->bdsp, avctx); + ff_blockdsp_init(&s->bdsp); ff_h264chroma_init(&v->h264chroma, 8); ff_qpeldsp_init(&s->qdsp); diff --git a/libavcodec/version.h b/libavcodec/version.h index 6f69f2d59cdfa..986e697bc9c92 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_XVMC -#define FF_API_XVMC (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_ERROR_RATE #define FF_API_ERROR_RATE (LIBAVCODEC_VERSION_MAJOR < 58) #endif diff --git a/libavcodec/wmv2.c b/libavcodec/wmv2.c index 6542d31e9df58..93bb6427609f2 100644 --- a/libavcodec/wmv2.c +++ b/libavcodec/wmv2.c @@ -32,7 +32,7 @@ av_cold void ff_wmv2_common_init(Wmv2Context *w) { MpegEncContext *const s = &w->s; - ff_blockdsp_init(&s->bdsp, s->avctx); + ff_blockdsp_init(&s->bdsp); ff_wmv2dsp_init(&w->wdsp); s->idsp.perm_type = w->wdsp.idct_perm; ff_init_scantable_permutation(s->idsp.idct_permutation, diff --git a/libavcodec/x86/blockdsp.c b/libavcodec/x86/blockdsp.c index 9bb5185b890d6..b047e19ab5d66 100644 --- a/libavcodec/x86/blockdsp.c +++ b/libavcodec/x86/blockdsp.c @@ -19,13 +19,14 @@ #include #include "config.h" + #include "libavutil/attributes.h" #include "libavutil/internal.h" #include "libavutil/cpu.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" + #include "libavcodec/blockdsp.h" -#include "libavcodec/version.h" #if HAVE_INLINE_ASM @@ -87,12 +88,7 @@ static void clear_blocks_sse(int16_t *blocks) #endif /* HAVE_INLINE_ASM */ -#if FF_API_XVMC -av_cold void ff_blockdsp_init_x86(BlockDSPContext *c, - AVCodecContext *avctx) -#else av_cold void ff_blockdsp_init_x86(BlockDSPContext *c) -#endif /* FF_API_XVMC */ { #if HAVE_INLINE_ASM int cpu_flags = av_get_cpu_flags(); @@ -102,14 +98,6 @@ av_cold void ff_blockdsp_init_x86(BlockDSPContext *c) c->clear_blocks = clear_blocks_mmx; } -#if FF_API_XVMC -FF_DISABLE_DEPRECATION_WARNINGS - /* XvMCCreateBlocks() may not allocate 16-byte aligned blocks */ - if (CONFIG_MPEG_XVMC_DECODER && avctx->xvmc_acceleration > 1) - return; -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_XVMC */ - if (INLINE_SSE(cpu_flags)) { c->clear_block = clear_block_sse; c->clear_blocks = clear_blocks_sse; diff --git a/libavcodec/xvmc.h b/libavcodec/xvmc.h deleted file mode 100644 index 91027b9c2f15b..0000000000000 --- a/libavcodec/xvmc.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2003 Ivan Kalvachev - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVCODEC_XVMC_H -#define AVCODEC_XVMC_H - -/** - * @file - * @ingroup lavc_codec_hwaccel_xvmc - * Public libavcodec XvMC header. - */ - -#include - -#include "libavutil/attributes.h" -#include "version.h" -#include "avcodec.h" - -#if FF_API_XVMC - -/** - * @defgroup lavc_codec_hwaccel_xvmc XvMC - * @ingroup lavc_codec_hwaccel - * - * @{ - */ - -#define AV_XVMC_ID 0x1DC711C0 /**< special value to ensure that regular pixel routines haven't corrupted the struct - the number is 1337 speak for the letters IDCT MCo (motion compensation) */ - -struct attribute_deprecated xvmc_pix_fmt { - /** The field contains the special constant value AV_XVMC_ID. - It is used as a test that the application correctly uses the API, - and that there is no corruption caused by pixel routines. - - application - set during initialization - - libavcodec - unchanged - */ - int xvmc_id; - - /** Pointer to the block array allocated by XvMCCreateBlocks(). - The array has to be freed by XvMCDestroyBlocks(). - Each group of 64 values represents one data block of differential - pixel information (in MoCo mode) or coefficients for IDCT. - - application - set the pointer during initialization - - libavcodec - fills coefficients/pixel data into the array - */ - short* data_blocks; - - /** Pointer to the macroblock description array allocated by - XvMCCreateMacroBlocks() and freed by XvMCDestroyMacroBlocks(). - - application - set the pointer during initialization - - libavcodec - fills description data into the array - */ - XvMCMacroBlock* mv_blocks; - - /** Number of macroblock descriptions that can be stored in the mv_blocks - array. - - application - set during initialization - - libavcodec - unchanged - */ - int allocated_mv_blocks; - - /** Number of blocks that can be stored at once in the data_blocks array. - - application - set during initialization - - libavcodec - unchanged - */ - int allocated_data_blocks; - - /** Indicate that the hardware would interpret data_blocks as IDCT - coefficients and perform IDCT on them. - - application - set during initialization - - libavcodec - unchanged - */ - int idct; - - /** In MoCo mode it indicates that intra macroblocks are assumed to be in - unsigned format; same as the XVMC_INTRA_UNSIGNED flag. - - application - set during initialization - - libavcodec - unchanged - */ - int unsigned_intra; - - /** Pointer to the surface allocated by XvMCCreateSurface(). - It has to be freed by XvMCDestroySurface() on application exit. - It identifies the frame and its state on the video hardware. - - application - set during initialization - - libavcodec - unchanged - */ - XvMCSurface* p_surface; - -/** Set by the decoder before calling ff_draw_horiz_band(), - needed by the XvMCRenderSurface function. */ -//@{ - /** Pointer to the surface used as past reference - - application - unchanged - - libavcodec - set - */ - XvMCSurface* p_past_surface; - - /** Pointer to the surface used as future reference - - application - unchanged - - libavcodec - set - */ - XvMCSurface* p_future_surface; - - /** top/bottom field or frame - - application - unchanged - - libavcodec - set - */ - unsigned int picture_structure; - - /** XVMC_SECOND_FIELD - 1st or 2nd field in the sequence - - application - unchanged - - libavcodec - set - */ - unsigned int flags; -//}@ - - /** Number of macroblock descriptions in the mv_blocks array - that have already been passed to the hardware. - - application - zeroes it on get_buffer(). - A successful ff_draw_horiz_band() may increment it - with filled_mb_block_num or zero both. - - libavcodec - unchanged - */ - int start_mv_blocks_num; - - /** Number of new macroblock descriptions in the mv_blocks array (after - start_mv_blocks_num) that are filled by libavcodec and have to be - passed to the hardware. - - application - zeroes it on get_buffer() or after successful - ff_draw_horiz_band(). - - libavcodec - increment with one of each stored MB - */ - int filled_mv_blocks_num; - - /** Number of the next free data block; one data block consists of - 64 short values in the data_blocks array. - All blocks before this one have already been claimed by placing their - position into the corresponding block description structure field, - that are part of the mv_blocks array. - - application - zeroes it on get_buffer(). - A successful ff_draw_horiz_band() may zero it together - with start_mb_blocks_num. - - libavcodec - each decoded macroblock increases it by the number - of coded blocks it contains. - */ - int next_free_data_block_num; -}; - -/** - * @} - */ - -#endif /* FF_API_XVMC */ - -#endif /* AVCODEC_XVMC_H */ diff --git a/libavcodec/xvmc_internal.h b/libavcodec/xvmc_internal.h deleted file mode 100644 index 9018e4a40a499..0000000000000 --- a/libavcodec/xvmc_internal.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * XVideo Motion Compensation internal functions - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVCODEC_XVMC_INTERNAL_H -#define AVCODEC_XVMC_INTERNAL_H - -#include "avcodec.h" -#include "mpegvideo.h" -#include "version.h" - -#if FF_API_XVMC - -void ff_xvmc_init_block(MpegEncContext *s); -void ff_xvmc_pack_pblocks(MpegEncContext *s, int cbp); -int ff_xvmc_field_start(MpegEncContext*s, AVCodecContext *avctx); -void ff_xvmc_field_end(MpegEncContext *s); -void ff_xvmc_decode_mb(MpegEncContext *s); - -#endif /* FF_API_XVMC */ - -#endif /* AVCODEC_XVMC_INTERNAL_H */ diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index d69eeea9de7bd..e4e5674a66a50 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -313,16 +313,6 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, -#if FF_API_XVMC - [AV_PIX_FMT_XVMC_MPEG2_MC] = { - .name = "xvmcmc", - .flags = AV_PIX_FMT_FLAG_HWACCEL, - }, - [AV_PIX_FMT_XVMC_MPEG2_IDCT] = { - .name = "xvmcidct", - .flags = AV_PIX_FMT_FLAG_HWACCEL, - }, -#endif /* FF_API_XVMC */ [AV_PIX_FMT_UYVY422] = { .name = "uyvy422", .nb_components = 3, diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 41498ccef7691..0b7582576bfb8 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -71,10 +71,6 @@ enum AVPixelFormat { AV_PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range AV_PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range AV_PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range -#if FF_API_XVMC - AV_PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing - AV_PIX_FMT_XVMC_MPEG2_IDCT, -#endif /* FF_API_XVMC */ AV_PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 AV_PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) diff --git a/libavutil/version.h b/libavutil/version.h index 93f471f99ba66..904d3874116c7 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -81,9 +81,6 @@ #ifndef FF_API_VDPAU #define FF_API_VDPAU (LIBAVUTIL_VERSION_MAJOR < 56) #endif -#ifndef FF_API_XVMC -#define FF_API_XVMC (LIBAVUTIL_VERSION_MAJOR < 56) -#endif #ifndef FF_API_OPT_TYPE_METADATA #define FF_API_OPT_TYPE_METADATA (LIBAVUTIL_VERSION_MAJOR < 56) #endif diff --git a/tests/checkasm/blockdsp.c b/tests/checkasm/blockdsp.c index 6b4bc804fc6f4..f10e2ff57857e 100644 --- a/tests/checkasm/blockdsp.c +++ b/tests/checkasm/blockdsp.c @@ -55,11 +55,9 @@ void checkasm_check_blockdsp(void) { LOCAL_ALIGNED_16(uint16_t, buf0, [6 * 8 * 8]); LOCAL_ALIGNED_16(uint16_t, buf1, [6 * 8 * 8]); - - AVCodecContext avctx = { 0 }; BlockDSPContext h; - ff_blockdsp_init(&h, &avctx); + ff_blockdsp_init(&h); check_clear(clear_block, 8 * 8); check_clear(clear_blocks, 8 * 8 * 6); From 72dc7ddd18fe54ee68aec71590c3202ad009a8fc Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 15:41:20 -0500 Subject: [PATCH 0085/2557] lavc: Drop deprecated error rate option Deprecated in 10/2013. --- libavcodec/avcodec.h | 9 --------- libavcodec/mpegvideo_enc.c | 7 ------- libavcodec/options_table.h | 3 --- libavcodec/version.h | 3 --- 4 files changed, 22 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 8567c8b28f210..f596ad30516a1 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2958,15 +2958,6 @@ typedef struct AVCodecContext { uint8_t *subtitle_header; int subtitle_header_size; -#if FF_API_ERROR_RATE - /** - * @deprecated use the 'error_rate' private AVOption of the mpegvideo - * encoders - */ - attribute_deprecated - int error_rate; -#endif - #if FF_API_VBV_DELAY /** * VBV delay coded in the last frame (in periods of a 27 MHz clock). diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 40c044d703271..4d72c01ec9e68 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -874,13 +874,6 @@ FF_ENABLE_DEPRECATION_WARNINGS if (ff_rate_control_init(s) < 0) return -1; -#if FF_API_ERROR_RATE - FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->error_rate) - s->error_rate = avctx->error_rate; - FF_ENABLE_DEPRECATION_WARNINGS; -#endif - #if FF_API_NORMALIZE_AQP FF_DISABLE_DEPRECATION_WARNINGS if (avctx->flags & CODEC_FLAG_NORMALIZE_AQP) diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 5e3540d2ddccb..7531af0471c53 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -313,9 +313,6 @@ static const AVOption avcodec_options[] = { #endif {"rc_init_occupancy", "number of bits which should be loaded into the rc buffer before decoding starts", OFFSET(rc_initial_buffer_occupancy), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, {"flags2", NULL, OFFSET(flags2), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT}, 0, UINT_MAX, V|A|E|D, "flags2"}, -#if FF_API_ERROR_RATE -{"error", NULL, OFFSET(error_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, -#endif {"threads", NULL, OFFSET(thread_count), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, INT_MAX, V|E|D, "threads"}, {"auto", "autodetect a suitable number of threads to use", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, INT_MIN, INT_MAX, V|E|D, "threads"}, #if FF_API_MPV_OPT diff --git a/libavcodec/version.h b/libavcodec/version.h index 986e697bc9c92..cfed83160f473 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_ERROR_RATE -#define FF_API_ERROR_RATE (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_QSCALE_TYPE #define FF_API_QSCALE_TYPE (LIBAVCODEC_VERSION_MAJOR < 58) #endif From cbebc3251bc2544b469e0dcb176bc04779d8866c Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 15:42:00 -0500 Subject: [PATCH 0086/2557] lavc: Drop deprecated public symbols qscale types and maximum number of bframes deprecated in 10/2013. Negative linesizes deprecated in 11/2013. xvidmmx deprecated in 08/2014. --- libavcodec/avcodec.h | 23 ----------------------- libavcodec/options_table.h | 3 --- libavcodec/version.h | 12 ------------ 3 files changed, 38 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index f596ad30516a1..6311acf628ad4 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -730,13 +730,6 @@ typedef struct RcOverride{ float quality_factor; } RcOverride; -#if FF_API_MAX_BFRAMES -/** - * @deprecated there is no libavcodec-wide limit on the number of B-frames - */ -#define FF_MAX_B_FRAMES 16 -#endif - /* encoding support These flags can be passed in AVCodecContext.flags before initialization. Note: Not everything is supported yet. @@ -1057,12 +1050,6 @@ typedef struct RcOverride{ * Codec should fill in channel configuration and samplerate instead of container */ #define CODEC_CAP_CHANNEL_CONF 0x0400 -#if FF_API_NEG_LINESIZES -/** - * @deprecated no codecs use this capability - */ -#define CODEC_CAP_NEG_LINESIZES 0x0800 -#endif /** * Codec supports frame-level multithreading. */ @@ -1178,13 +1165,6 @@ typedef struct AVCPBProperties { uint64_t vbv_delay; } AVCPBProperties; -#if FF_API_QSCALE_TYPE -#define FF_QSCALE_TYPE_MPEG1 0 -#define FF_QSCALE_TYPE_MPEG2 1 -#define FF_QSCALE_TYPE_H264 2 -#define FF_QSCALE_TYPE_VP56 3 -#endif - /** * The decoder will keep a reference to the frame and may reuse it later. */ @@ -2722,9 +2702,6 @@ typedef struct AVCodecContext { #define FF_IDCT_IPP 13 #endif /* FF_API_UNUSED_MEMBERS */ #define FF_IDCT_XVID 14 -#if FF_API_IDCT_XVIDMMX -#define FF_IDCT_XVIDMMX 14 -#endif /* FF_API_IDCT_XVIDMMX */ #define FF_IDCT_SIMPLEARMV5TE 16 #define FF_IDCT_SIMPLEARMV6 17 #define FF_IDCT_FAAN 20 diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 7531af0471c53..c95e55265f5d1 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -213,9 +213,6 @@ static const AVOption avcodec_options[] = { {"ipp", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_IPP }, INT_MIN, INT_MAX, V|E|D, "idct"}, #endif /* FF_API_UNUSED_MEMBERS */ {"xvid", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_XVID }, INT_MIN, INT_MAX, V|E|D, "idct"}, -#if FF_API_IDCT_XVIDMMX -{"xvidmmx", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_XVID }, INT_MIN, INT_MAX, V|E|D, "idct"}, -#endif /* FF_API_IDCT_XVIDMMX */ {"faani", "floating point AAN IDCT", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_FAAN }, INT_MIN, INT_MAX, V|D|E, "idct"}, {"slice_count", NULL, OFFSET(slice_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"ec", "set error concealment strategy", OFFSET(error_concealment), AV_OPT_TYPE_FLAGS, {.i64 = 3 }, INT_MIN, INT_MAX, V|D, "ec"}, diff --git a/libavcodec/version.h b/libavcodec/version.h index cfed83160f473..db14d7bf97d59 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,30 +47,18 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_QSCALE_TYPE -#define FF_API_QSCALE_TYPE (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_MB_TYPE #define FF_API_MB_TYPE (LIBAVCODEC_VERSION_MAJOR < 58) #endif -#ifndef FF_API_MAX_BFRAMES -#define FF_API_MAX_BFRAMES (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_FAST_MALLOC #define FF_API_FAST_MALLOC (LIBAVCODEC_VERSION_MAJOR < 58) #endif -#ifndef FF_API_NEG_LINESIZES -#define FF_API_NEG_LINESIZES (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_EMU_EDGE #define FF_API_EMU_EDGE (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_UNUSED_MEMBERS #define FF_API_UNUSED_MEMBERS (LIBAVCODEC_VERSION_MAJOR < 58) #endif -#ifndef FF_API_IDCT_XVIDMMX -#define FF_API_IDCT_XVIDMMX (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_INPUT_PRESERVED #define FF_API_INPUT_PRESERVED (LIBAVCODEC_VERSION_MAJOR < 58) #endif From da5ba26b9e25f408e8d2f9428c9eca699f11a7db Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 15:43:14 -0500 Subject: [PATCH 0087/2557] lavc: Drop deprecated macroblock type symbols Deprecated in 10/2013. --- libavcodec/avcodec.h | 26 -------------------------- libavcodec/mpegutils.h | 2 -- libavcodec/version.h | 3 --- 3 files changed, 31 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 6311acf628ad4..6fd76b5329b03 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1072,32 +1072,6 @@ typedef struct RcOverride{ #define CODEC_CAP_VARIABLE_FRAME_SIZE 0x10000 #endif /* FF_API_WITHOUT_PREFIX */ -#if FF_API_MB_TYPE -//The following defines may change, don't expect compatibility if you use them. -#define MB_TYPE_INTRA4x4 0x0001 -#define MB_TYPE_INTRA16x16 0x0002 //FIXME H.264-specific -#define MB_TYPE_INTRA_PCM 0x0004 //FIXME H.264-specific -#define MB_TYPE_16x16 0x0008 -#define MB_TYPE_16x8 0x0010 -#define MB_TYPE_8x16 0x0020 -#define MB_TYPE_8x8 0x0040 -#define MB_TYPE_INTERLACED 0x0080 -#define MB_TYPE_DIRECT2 0x0100 //FIXME -#define MB_TYPE_ACPRED 0x0200 -#define MB_TYPE_GMC 0x0400 -#define MB_TYPE_SKIP 0x0800 -#define MB_TYPE_P0L0 0x1000 -#define MB_TYPE_P1L0 0x2000 -#define MB_TYPE_P0L1 0x4000 -#define MB_TYPE_P1L1 0x8000 -#define MB_TYPE_L0 (MB_TYPE_P0L0 | MB_TYPE_P1L0) -#define MB_TYPE_L1 (MB_TYPE_P0L1 | MB_TYPE_P1L1) -#define MB_TYPE_L0L1 (MB_TYPE_L0 | MB_TYPE_L1) -#define MB_TYPE_QUANT 0x00010000 -#define MB_TYPE_CBP 0x00020000 -// Note bits 24-31 are reserved for codec specific use (H.264 ref0, MPEG-1 0mv, ...) -#endif - /** * Pan Scan area. * This specifies the area which should be displayed. diff --git a/libavcodec/mpegutils.h b/libavcodec/mpegutils.h index 60f971222ef52..960999c9283d7 100644 --- a/libavcodec/mpegutils.h +++ b/libavcodec/mpegutils.h @@ -48,7 +48,6 @@ #define MAX_FCODE 7 /* MB types */ -#if !FF_API_MB_TYPE #define MB_TYPE_INTRA4x4 (1 << 0) #define MB_TYPE_INTRA16x16 (1 << 1) // FIXME H.264-specific #define MB_TYPE_INTRA_PCM (1 << 2) // FIXME H.264-specific @@ -70,7 +69,6 @@ #define MB_TYPE_L0L1 (MB_TYPE_L0 | MB_TYPE_L1) #define MB_TYPE_QUANT (1 << 16) #define MB_TYPE_CBP (1 << 17) -#endif #define MB_TYPE_INTRA MB_TYPE_INTRA4x4 // default mb_type if there is just one type diff --git a/libavcodec/version.h b/libavcodec/version.h index db14d7bf97d59..da2d5e5328002 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_MB_TYPE -#define FF_API_MB_TYPE (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_FAST_MALLOC #define FF_API_FAST_MALLOC (LIBAVCODEC_VERSION_MAJOR < 58) #endif From 06c20d3e32c33c4da6d9fbc43aebaeb38c45b859 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 15:45:20 -0500 Subject: [PATCH 0088/2557] lavc: Drop deprecated av_fast_malloc() compatibility Deprecated in 10/2013. --- libavcodec/avcodec.h | 5 ----- libavcodec/version.h | 3 --- 2 files changed, 8 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 6fd76b5329b03..86632f28b86d8 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -41,11 +41,6 @@ #include "version.h" -#if FF_API_FAST_MALLOC -// to provide fast_*alloc -#include "libavutil/mem.h" -#endif - /** * @defgroup libavc Encoding/Decoding Library * @{ diff --git a/libavcodec/version.h b/libavcodec/version.h index da2d5e5328002..3fca559fc003d 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_FAST_MALLOC -#define FF_API_FAST_MALLOC (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_EMU_EDGE #define FF_API_EMU_EDGE (LIBAVCODEC_VERSION_MAJOR < 58) #endif From b3739599bda740ac12d3dde31a331b744df99123 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 15:47:35 -0500 Subject: [PATCH 0089/2557] lavc: Drop deprecated emu edge functionality Deprecated in 01/2014. --- libavcodec/avcodec.h | 22 ---------------------- libavcodec/options_table.h | 3 --- libavcodec/utils.c | 7 ------- libavcodec/version.h | 3 --- 4 files changed, 35 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 86632f28b86d8..a5f0dade724f8 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -947,13 +947,6 @@ typedef struct RcOverride{ #define CODEC_FLAG_PASS1 0x0200 ///< Use internal 2pass ratecontrol in first pass mode. #define CODEC_FLAG_PASS2 0x0400 ///< Use internal 2pass ratecontrol in second pass mode. #define CODEC_FLAG_GRAY 0x2000 ///< Only decode/encode grayscale. -#if FF_API_EMU_EDGE -/** - * @deprecated edges are not used/required anymore. I.e. this flag is now always - * set. - */ -#define CODEC_FLAG_EMU_EDGE 0x4000 -#endif #define CODEC_FLAG_PSNR 0x8000 ///< error[?] variables will be set during encoding. #define CODEC_FLAG_TRUNCATED 0x00010000 /** Input bitstream might be truncated at a random location instead of only at frame boundaries. */ @@ -4025,21 +4018,6 @@ AVCodec *avcodec_find_decoder_by_name(const char *name); */ int avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int flags); -#if FF_API_EMU_EDGE -/** - * Return the amount of padding in pixels which the get_buffer callback must - * provide around the edge of the image for codecs which do not have the - * CODEC_FLAG_EMU_EDGE flag. - * - * @return Required padding in pixels. - * - * @deprecated CODEC_FLAG_EMU_EDGE is deprecated, so this function is no longer - * needed - */ -attribute_deprecated -unsigned avcodec_get_edge_width(void); -#endif - /** * Modify width and height values so that they will result in a memory * buffer that is acceptable for the codec if you do not use any horizontal diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index c95e55265f5d1..ebd77d4c8032c 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -62,9 +62,6 @@ static const AVOption avcodec_options[] = { {"pass1", "use internal 2-pass ratecontrol in first pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS1 }, INT_MIN, INT_MAX, 0, "flags"}, {"pass2", "use internal 2-pass ratecontrol in second pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS2 }, INT_MIN, INT_MAX, 0, "flags"}, {"gray", "only decode/encode grayscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GRAY }, INT_MIN, INT_MAX, V|E|D, "flags"}, -#if FF_API_EMU_EDGE -{"emu_edge", "do not draw edges", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_EMU_EDGE }, INT_MIN, INT_MAX, 0, "flags"}, -#endif {"psnr", "error[?] variables will be set during encoding", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PSNR }, INT_MIN, INT_MAX, V|E, "flags"}, {"truncated", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_TRUNCATED }, INT_MIN, INT_MAX, 0, "flags"}, #if FF_API_NORMALIZE_AQP diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 6cef65083d7ba..61bb09b0313d7 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -118,13 +118,6 @@ av_cold void avcodec_register(AVCodec *codec) codec->init_static_data(codec); } -#if FF_API_EMU_EDGE -unsigned avcodec_get_edge_width(void) -{ - return EDGE_WIDTH; -} -#endif - int ff_set_dimensions(AVCodecContext *s, int width, int height) { int ret = av_image_check_size(width, height, 0, s); diff --git a/libavcodec/version.h b/libavcodec/version.h index 3fca559fc003d..cafc6e8ba0f70 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_EMU_EDGE -#define FF_API_EMU_EDGE (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_UNUSED_MEMBERS #define FF_API_UNUSED_MEMBERS (LIBAVCODEC_VERSION_MAJOR < 58) #endif From 302554835e39b79b977ed60c9afe81b44590dfef Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 15:55:32 -0500 Subject: [PATCH 0090/2557] lavc: Drop deprecated unused public members Deprecated in 07/2014. --- libavcodec/avcodec.h | 18 ------------------ libavcodec/options_table.h | 12 ------------ libavcodec/version.h | 3 --- 3 files changed, 33 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index a5f0dade724f8..f8ab537104e1f 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2023,15 +2023,6 @@ typedef struct AVCodecContext { int chromaoffset; #endif -#if FF_API_UNUSED_MEMBERS - /** - * Multiplied by qscale for each frame and added to scene_change_score. - * - encoding: Set by user. - * - decoding: unused - */ - attribute_deprecated int scenechange_factor; -#endif - /** * Note: Value depends upon the compare function used for fullpel ME. * - encoding: Set by user. @@ -2377,9 +2368,6 @@ typedef struct AVCodecContext { #define FF_CODER_TYPE_AC 1 #define FF_CODER_TYPE_RAW 2 #define FF_CODER_TYPE_RLE 3 -#if FF_API_UNUSED_MEMBERS -#define FF_CODER_TYPE_DEFLATE 4 -#endif /* FF_API_UNUSED_MEMBERS */ /** * @deprecated use encoder private options instead */ @@ -2573,9 +2561,6 @@ typedef struct AVCodecContext { #define FF_DEBUG_DCT_COEFF 0x00000040 #define FF_DEBUG_SKIP 0x00000080 #define FF_DEBUG_STARTCODE 0x00000100 -#if FF_API_UNUSED_MEMBERS -#define FF_DEBUG_PTS 0x00000200 -#endif /* FF_API_UNUSED_MEMBERS */ #define FF_DEBUG_ER 0x00000400 #define FF_DEBUG_MMCO 0x00000800 #define FF_DEBUG_BUGS 0x00001000 @@ -2660,9 +2645,6 @@ typedef struct AVCodecContext { #define FF_IDCT_ARM 7 #define FF_IDCT_ALTIVEC 8 #define FF_IDCT_SIMPLEARM 10 -#if FF_API_UNUSED_MEMBERS -#define FF_IDCT_IPP 13 -#endif /* FF_API_UNUSED_MEMBERS */ #define FF_IDCT_XVID 14 #define FF_IDCT_SIMPLEARMV5TE 16 #define FF_IDCT_SIMPLEARMV6 17 diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index ebd77d4c8032c..e29440e59738d 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -206,9 +206,6 @@ static const AVOption avcodec_options[] = { {"simplearmv5te", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV5TE }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"simplearmv6", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV6 }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"simpleneon", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLENEON }, INT_MIN, INT_MAX, V|E|D, "idct"}, -#if FF_API_UNUSED_MEMBERS -{"ipp", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_IPP }, INT_MIN, INT_MAX, V|E|D, "idct"}, -#endif /* FF_API_UNUSED_MEMBERS */ {"xvid", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_XVID }, INT_MIN, INT_MAX, V|E|D, "idct"}, {"faani", "floating point AAN IDCT", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_FAAN }, INT_MIN, INT_MAX, V|D|E, "idct"}, {"slice_count", NULL, OFFSET(slice_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, @@ -232,9 +229,6 @@ static const AVOption avcodec_options[] = { {"dct_coeff", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_DCT_COEFF }, INT_MIN, INT_MAX, V|D, "debug"}, {"skip", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_SKIP }, INT_MIN, INT_MAX, V|D, "debug"}, {"startcode", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_STARTCODE }, INT_MIN, INT_MAX, V|D, "debug"}, -#if FF_API_UNUSED_MEMBERS -{"pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_PTS }, INT_MIN, INT_MAX, V|D, "debug"}, -#endif /* FF_API_UNUSED_MEMBERS */ {"er", "error recognition", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_ER }, INT_MIN, INT_MAX, V|D, "debug"}, {"mmco", "memory management control operations (H.264)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_MMCO }, INT_MIN, INT_MAX, V|D, "debug"}, {"bugs", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BUGS }, INT_MIN, INT_MAX, V|D, "debug"}, @@ -280,9 +274,6 @@ static const AVOption avcodec_options[] = { {"ac", "arithmetic coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_AC }, INT_MIN, INT_MAX, V|E, "coder"}, {"raw", "raw (no encoding)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_RAW }, INT_MIN, INT_MAX, V|E, "coder"}, {"rle", "run-length coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_RLE }, INT_MIN, INT_MAX, V|E, "coder"}, -#if FF_API_UNUSED_MEMBERS -{"deflate", "deflate-based coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_DEFLATE }, INT_MIN, INT_MAX, V|E, "coder"}, -#endif /* FF_API_UNUSED_MEMBERS */ #endif /* FF_API_CODER_TYPE */ #if FF_API_PRIVATE_OPT {"context", "context model", OFFSET(context_model), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, @@ -370,9 +361,6 @@ static const AVOption avcodec_options[] = { {"chromaoffset", "chroma QP offset from luma", OFFSET(chromaoffset), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, #endif {"trellis", "rate-distortion optimal quantization", OFFSET(trellis), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, -#if FF_API_UNUSED_MEMBERS -{"sc_factor", "multiplied by qscale for each frame and added to scene_change_score", OFFSET(scenechange_factor), AV_OPT_TYPE_INT, {.i64 = 6 }, 0, INT_MAX, V|E}, -#endif /* FF_API_UNUSED_MEMBERS */ {"mv0_threshold", NULL, OFFSET(mv0_threshold), AV_OPT_TYPE_INT, {.i64 = 256 }, 0, INT_MAX, V|E}, #if FF_API_PRIVATE_OPT {"b_sensitivity", "adjust sensitivity of b_frame_strategy 1", OFFSET(b_sensitivity), AV_OPT_TYPE_INT, {.i64 = 40 }, 1, INT_MAX, V|E}, diff --git a/libavcodec/version.h b/libavcodec/version.h index cafc6e8ba0f70..0bab4548c26e9 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_UNUSED_MEMBERS -#define FF_API_UNUSED_MEMBERS (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_INPUT_PRESERVED #define FF_API_INPUT_PRESERVED (LIBAVCODEC_VERSION_MAJOR < 58) #endif From bb45d11282d93af0e8d4c8fd6bc6405f7439a940 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 15:57:18 -0500 Subject: [PATCH 0091/2557] lavc: Drop deprecated codec flags Deprecated between 04/2014 - 05/2015. --- libavcodec/avcodec.h | 158 ------------------------------------- libavcodec/libxvid.c | 6 -- libavcodec/mpegvideo_enc.c | 14 ---- libavcodec/options_table.h | 12 --- libavcodec/version.h | 15 ---- 5 files changed, 205 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index f8ab537104e1f..f7c879604e9fa 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -657,18 +657,6 @@ typedef struct AVCodecDescriptor { */ #define AV_INPUT_BUFFER_MIN_SIZE 16384 -#if FF_API_WITHOUT_PREFIX -/** - * @deprecated use AV_INPUT_BUFFER_PADDING_SIZE instead - */ -#define FF_INPUT_BUFFER_PADDING_SIZE 8 - -/** - * @deprecated use AV_INPUT_BUFFER_MIN_SIZE instead - */ -#define FF_MIN_BUFFER_SIZE 16384 -#endif /* FF_API_WITHOUT_PREFIX */ - /** * @ingroup lavc_encoding * motion estimation type. @@ -914,152 +902,6 @@ typedef struct RcOverride{ */ #define AV_CODEC_CAP_VARIABLE_FRAME_SIZE (1 << 16) -#if FF_API_WITHOUT_PREFIX -/** - * Allow decoders to produce frames with data planes that are not aligned - * to CPU requirements (e.g. due to cropping). - */ -#define CODEC_FLAG_UNALIGNED 0x0001 -#define CODEC_FLAG_QSCALE 0x0002 ///< Use fixed qscale. -#define CODEC_FLAG_4MV 0x0004 ///< 4 MV per MB allowed / advanced prediction for H.263. -#define CODEC_FLAG_OUTPUT_CORRUPT 0x0008 ///< Output even those frames that might be corrupted -#define CODEC_FLAG_QPEL 0x0010 ///< Use qpel MC. -#if FF_API_GMC -/** - * @deprecated use the "gmc" private option of the libxvid encoder - */ -#define CODEC_FLAG_GMC 0x0020 ///< Use GMC. -#endif -#if FF_API_MV0 -/** - * @deprecated use the flag "mv0" in the "mpv_flags" private option of the - * mpegvideo encoders - */ -#define CODEC_FLAG_MV0 0x0040 -#endif -#if FF_API_INPUT_PRESERVED -/** - * @deprecated passing reference-counted frames to the encoders replaces this - * flag - */ -#define CODEC_FLAG_INPUT_PRESERVED 0x0100 -#endif -#define CODEC_FLAG_PASS1 0x0200 ///< Use internal 2pass ratecontrol in first pass mode. -#define CODEC_FLAG_PASS2 0x0400 ///< Use internal 2pass ratecontrol in second pass mode. -#define CODEC_FLAG_GRAY 0x2000 ///< Only decode/encode grayscale. -#define CODEC_FLAG_PSNR 0x8000 ///< error[?] variables will be set during encoding. -#define CODEC_FLAG_TRUNCATED 0x00010000 /** Input bitstream might be truncated at a random - location instead of only at frame boundaries. */ -#if FF_API_NORMALIZE_AQP -/** - * @deprecated use the flag "naq" in the "mpv_flags" private option of the - * mpegvideo encoders - */ -#define CODEC_FLAG_NORMALIZE_AQP 0x00020000 -#endif -#define CODEC_FLAG_INTERLACED_DCT 0x00040000 ///< Use interlaced DCT. -#define CODEC_FLAG_LOW_DELAY 0x00080000 ///< Force low delay. -#define CODEC_FLAG_GLOBAL_HEADER 0x00400000 ///< Place global headers in extradata instead of every keyframe. -#define CODEC_FLAG_BITEXACT 0x00800000 ///< Use only bitexact stuff (except (I)DCT). -/* Fx : Flag for H.263+ extra options */ -#define CODEC_FLAG_AC_PRED 0x01000000 ///< H.263 advanced intra coding / MPEG-4 AC prediction -#define CODEC_FLAG_LOOP_FILTER 0x00000800 ///< loop filter -#define CODEC_FLAG_INTERLACED_ME 0x20000000 ///< interlaced motion estimation -#define CODEC_FLAG_CLOSED_GOP 0x80000000 -#define CODEC_FLAG2_FAST 0x00000001 ///< Allow non spec compliant speedup tricks. -#define CODEC_FLAG2_NO_OUTPUT 0x00000004 ///< Skip bitstream encoding. -#define CODEC_FLAG2_LOCAL_HEADER 0x00000008 ///< Place global headers at every keyframe instead of in extradata. -#define CODEC_FLAG2_IGNORE_CROP 0x00010000 ///< Discard cropping information from SPS. - -#define CODEC_FLAG2_CHUNKS 0x00008000 ///< Input bitstream might be truncated at a packet boundaries instead of only at frame boundaries. - -/* Unsupported options : - * Syntax Arithmetic coding (SAC) - * Reference Picture Selection - * Independent Segment Decoding */ -/* /Fx */ -/* codec capabilities */ - -#define CODEC_CAP_DRAW_HORIZ_BAND 0x0001 ///< Decoder can use draw_horiz_band callback. -/** - * Codec uses get_buffer() for allocating buffers and supports custom allocators. - * If not set, it might not use get_buffer() at all or use operations that - * assume the buffer was allocated by avcodec_default_get_buffer. - */ -#define CODEC_CAP_DR1 0x0002 -#define CODEC_CAP_TRUNCATED 0x0008 -/** - * Encoder or decoder requires flushing with NULL input at the end in order to - * give the complete and correct output. - * - * NOTE: If this flag is not set, the codec is guaranteed to never be fed with - * with NULL data. The user can still send NULL data to the public encode - * or decode function, but libavcodec will not pass it along to the codec - * unless this flag is set. - * - * Decoders: - * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, - * avpkt->size=0 at the end to get the delayed data until the decoder no longer - * returns frames. - * - * Encoders: - * The encoder needs to be fed with NULL data at the end of encoding until the - * encoder no longer returns data. - * - * NOTE: For encoders implementing the AVCodec.encode2() function, setting this - * flag also means that the encoder must set the pts and duration for - * each output packet. If this flag is not set, the pts and duration will - * be determined by libavcodec from the input frame. - */ -#define CODEC_CAP_DELAY 0x0020 -/** - * Codec can be fed a final frame with a smaller size. - * This can be used to prevent truncation of the last audio samples. - */ -#define CODEC_CAP_SMALL_LAST_FRAME 0x0040 -/** - * Codec can output multiple frames per AVPacket - * Normally demuxers return one frame at a time, demuxers which do not do - * are connected to a parser to split what they return into proper frames. - * This flag is reserved to the very rare category of codecs which have a - * bitstream that cannot be split into frames without timeconsuming - * operations like full decoding. Demuxers carrying such bitstreams thus - * may return multiple frames in a packet. This has many disadvantages like - * prohibiting stream copy in many cases thus it should only be considered - * as a last resort. - */ -#define CODEC_CAP_SUBFRAMES 0x0100 -/** - * Codec is experimental and is thus avoided in favor of non experimental - * encoders - */ -#define CODEC_CAP_EXPERIMENTAL 0x0200 -/** - * Codec should fill in channel configuration and samplerate instead of container - */ -#define CODEC_CAP_CHANNEL_CONF 0x0400 -/** - * Codec supports frame-level multithreading. - */ -#define CODEC_CAP_FRAME_THREADS 0x1000 -/** - * Codec supports slice-based (or partition-based) multithreading. - */ -#define CODEC_CAP_SLICE_THREADS 0x2000 -/** - * Codec supports changed parameters at any point. - */ -#define CODEC_CAP_PARAM_CHANGE 0x4000 -/** - * Codec supports avctx->thread_count == 0 (auto). - */ -#define CODEC_CAP_AUTO_THREADS 0x8000 -/** - * Audio encoder supports receiving a different number of samples in each call. - */ -#define CODEC_CAP_VARIABLE_FRAME_SIZE 0x10000 -#endif /* FF_API_WITHOUT_PREFIX */ - /** * Pan Scan area. * This specifies the area which should be displayed. diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c index 1e8dc5d01b799..dce62a0dba144 100644 --- a/libavcodec/libxvid.c +++ b/libavcodec/libxvid.c @@ -475,12 +475,6 @@ FF_ENABLE_DEPRECATION_WARNINGS break; } - /* Bring in VOL flags from avconv command-line */ -#if FF_API_GMC - if (avctx->flags & CODEC_FLAG_GMC) - x->gmc = 1; -#endif - x->vol_flags = 0; if (x->gmc) { x->vol_flags |= XVID_VOL_GMC; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 4d72c01ec9e68..a0c479ff4e533 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -874,20 +874,6 @@ FF_ENABLE_DEPRECATION_WARNINGS if (ff_rate_control_init(s) < 0) return -1; -#if FF_API_NORMALIZE_AQP - FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->flags & CODEC_FLAG_NORMALIZE_AQP) - s->mpv_flags |= FF_MPV_FLAG_NAQ; - FF_ENABLE_DEPRECATION_WARNINGS; -#endif - -#if FF_API_MV0 - FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->flags & CODEC_FLAG_MV0) - s->mpv_flags |= FF_MPV_FLAG_MV0; - FF_ENABLE_DEPRECATION_WARNINGS -#endif - #if FF_API_MPV_OPT FF_DISABLE_DEPRECATION_WARNINGS if (avctx->rc_qsquish != 0.0) diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index e29440e59738d..1d15422a11589 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -50,23 +50,11 @@ static const AVOption avcodec_options[] = { {"qpel", "use 1/4-pel motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_QPEL }, INT_MIN, INT_MAX, V|E, "flags"}, {"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"}, {"qscale", "use fixed qscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_QSCALE }, INT_MIN, INT_MAX, 0, "flags"}, -#if FF_API_GMC -{"gmc", "use gmc", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_GMC }, INT_MIN, INT_MAX, V|E, "flags"}, -#endif -#if FF_API_MV0 -{"mv0", "always try a mb with mv=<0,0>", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_MV0 }, INT_MIN, INT_MAX, V|E, "flags"}, -#endif -#if FF_API_INPUT_PRESERVED -{"input_preserved", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_INPUT_PRESERVED }, INT_MIN, INT_MAX, 0, "flags"}, -#endif {"pass1", "use internal 2-pass ratecontrol in first pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS1 }, INT_MIN, INT_MAX, 0, "flags"}, {"pass2", "use internal 2-pass ratecontrol in second pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS2 }, INT_MIN, INT_MAX, 0, "flags"}, {"gray", "only decode/encode grayscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GRAY }, INT_MIN, INT_MAX, V|E|D, "flags"}, {"psnr", "error[?] variables will be set during encoding", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PSNR }, INT_MIN, INT_MAX, V|E, "flags"}, {"truncated", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_TRUNCATED }, INT_MIN, INT_MAX, 0, "flags"}, -#if FF_API_NORMALIZE_AQP -{"naq", "normalize adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_NORMALIZE_AQP }, INT_MIN, INT_MAX, V|E, "flags"}, -#endif {"ildct", "use interlaced DCT", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_INTERLACED_DCT }, INT_MIN, INT_MAX, V|E, "flags"}, {"low_delay", "force low delay", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_LOW_DELAY }, INT_MIN, INT_MAX, V|D|E, "flags"}, {"global_header", "place global headers in extradata instead of every keyframe", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GLOBAL_HEADER }, INT_MIN, INT_MAX, V|A|E, "flags"}, diff --git a/libavcodec/version.h b/libavcodec/version.h index 0bab4548c26e9..04f701430ebbd 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,18 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_INPUT_PRESERVED -#define FF_API_INPUT_PRESERVED (LIBAVCODEC_VERSION_MAJOR < 58) -#endif -#ifndef FF_API_NORMALIZE_AQP -#define FF_API_NORMALIZE_AQP (LIBAVCODEC_VERSION_MAJOR < 58) -#endif -#ifndef FF_API_GMC -#define FF_API_GMC (LIBAVCODEC_VERSION_MAJOR < 58) -#endif -#ifndef FF_API_MV0 -#define FF_API_MV0 (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_CODEC_NAME #define FF_API_CODEC_NAME (LIBAVCODEC_VERSION_MAJOR < 58) #endif @@ -89,9 +77,6 @@ #ifndef FF_API_MOTION_EST #define FF_API_MOTION_EST (LIBAVCODEC_VERSION_MAJOR < 58) #endif -#ifndef FF_API_WITHOUT_PREFIX -#define FF_API_WITHOUT_PREFIX (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_SIDEDATA_ONLY_PKT #define FF_API_SIDEDATA_ONLY_PKT (LIBAVCODEC_VERSION_MAJOR < 59) #endif From 4476027d93680cd88d2f75ef1cef5b0c276a8704 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 17:08:15 -0500 Subject: [PATCH 0092/2557] lavc: Drop deprecated avctx codec name Deprecated in 04/2014. --- libavcodec/avcodec.h | 7 ------- libavcodec/version.h | 3 --- 2 files changed, 10 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index f7c879604e9fa..e1f5d8ff6e9d1 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1219,13 +1219,6 @@ typedef struct AVCodecContext { enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ const struct AVCodec *codec; -#if FF_API_CODEC_NAME - /** - * @deprecated this field is not used for anything in libavcodec - */ - attribute_deprecated - char codec_name[32]; -#endif enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ /** diff --git a/libavcodec/version.h b/libavcodec/version.h index 04f701430ebbd..99aa9bf8ccf63 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_CODEC_NAME -#define FF_API_CODEC_NAME (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_AFD #define FF_API_AFD (LIBAVCODEC_VERSION_MAJOR < 58) #endif From 5182a28b5de060c51c21b36053ab205bfbbbbe31 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Thu, 16 Mar 2017 15:51:56 -0400 Subject: [PATCH 0093/2557] lavc: Drop deprecated global afd field Deprecated in 08/2014. --- libavcodec/avcodec.h | 20 -------------------- libavcodec/mpeg12dec.c | 5 ----- libavcodec/options_table.h | 3 --- libavcodec/pthread_frame.c | 5 ----- libavcodec/version.h | 3 --- 5 files changed, 36 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index e1f5d8ff6e9d1..2366acf93c506 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1675,26 +1675,6 @@ typedef struct AVCodecContext { */ int me_subpel_quality; -#if FF_API_AFD - /** - * DTG active format information (additional aspect ratio - * information only used in DVB MPEG-2 transport streams) - * 0 if not set. - * - * - encoding: unused - * - decoding: Set by decoder. - * @deprecated Deprecated in favor of AVSideData - */ - attribute_deprecated int dtg_active_format; -#define FF_DTG_AFD_SAME 8 -#define FF_DTG_AFD_4_3 9 -#define FF_DTG_AFD_16_9 10 -#define FF_DTG_AFD_14_9 11 -#define FF_DTG_AFD_4_3_SP_14_9 13 -#define FF_DTG_AFD_16_9_SP_14_9 14 -#define FF_DTG_AFD_SP_4_3 15 -#endif /* FF_API_AFD */ - /** * maximum motion estimation search range in subpel units * If 0 then no limit. diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 528a4ed16db09..6702ad1ed73c8 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -2176,11 +2176,6 @@ static void mpeg_decode_user_data(AVCodecContext *avctx, if (flags & 0x40) { if (buf_end - p < 1) return; -#if FF_API_AFD -FF_DISABLE_DEPRECATION_WARNINGS - avctx->dtg_active_format = p[0] & 0x0f; -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_AFD */ s1->has_afd = 1; s1->afd = p[0] & 0x0f; } diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 1d15422a11589..7a8ef3d4a92c8 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -247,9 +247,6 @@ static const AVOption avcodec_options[] = { {"chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_CHROMA }, INT_MIN, INT_MAX, V|E, "cmp_func"}, {"pre_dia_size", "diamond type & size for motion estimation pre-pass", OFFSET(pre_dia_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, {"subq", "sub-pel motion estimation quality", OFFSET(me_subpel_quality), AV_OPT_TYPE_INT, {.i64 = 8 }, INT_MIN, INT_MAX, V|E}, -#if FF_API_AFD -{"dtg_active_format", NULL, OFFSET(dtg_active_format), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, -#endif {"me_range", "limit motion vectors range (1023 for DivX player)", OFFSET(me_range), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, #if FF_API_QUANT_BIAS {"ibias", "intra quant bias", OFFSET(intra_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, V|E}, diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 65a04d8e90949..6d14a878a442d 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -238,11 +238,6 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, dst->bits_per_coded_sample = src->bits_per_coded_sample; dst->sample_aspect_ratio = src->sample_aspect_ratio; -#if FF_API_AFD -FF_DISABLE_DEPRECATION_WARNINGS - dst->dtg_active_format = src->dtg_active_format; -FF_ENABLE_DEPRECATION_WARNINGS -#endif /* FF_API_AFD */ dst->profile = src->profile; dst->level = src->level; diff --git a/libavcodec/version.h b/libavcodec/version.h index 99aa9bf8ccf63..45c2dbd56092a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_AFD -#define FF_API_AFD (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_AUDIOENC_DELAY #define FF_API_AUDIOENC_DELAY (LIBAVCODEC_VERSION_MAJOR < 58) #endif From 48bb0da050329e5111b00a12dfc154b7e78fb3a3 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Thu, 16 Mar 2017 15:55:18 -0400 Subject: [PATCH 0094/2557] lavc: Drop deprecated way of setting audio delay on encode Deprecated in 08/2014. --- libavcodec/encode.c | 4 ---- libavcodec/utils.c | 5 ----- libavcodec/version.h | 3 --- 3 files changed, 12 deletions(-) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index fc27a070e1650..9bb7ae5bde068 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -194,10 +194,6 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, end: av_frame_free(&padded_frame); -#if FF_API_AUDIOENC_DELAY - avctx->delay = avctx->initial_padding; -#endif - return ret; } diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 61bb09b0313d7..a6408cecbb5e2 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -646,11 +646,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } } -#if FF_API_AUDIOENC_DELAY - if (av_codec_is_encoder(avctx->codec)) - avctx->delay = avctx->initial_padding; -#endif - if (av_codec_is_decoder(avctx->codec)) { /* validate channel layout from the decoder */ if (avctx->channel_layout) { diff --git a/libavcodec/version.h b/libavcodec/version.h index 45c2dbd56092a..b60e9715aaa78 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_AUDIOENC_DELAY -#define FF_API_AUDIOENC_DELAY (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_AVCTX_TIMEBASE #define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 58) #endif From c43a96fe16e6a6ea091e64ca271f0788f4a0bea9 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Thu, 16 Mar 2017 15:56:59 -0400 Subject: [PATCH 0095/2557] lavc: Drop deprecated time_base variable for decoding Deprecated in 10/2015. --- libavcodec/decode.c | 5 ----- libavcodec/mpegvideo_parser.c | 5 ----- libavcodec/utils.c | 5 ----- libavcodec/version.h | 3 --- 4 files changed, 18 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index f4088cdae8d6a..e4f6a0d7270d8 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -354,11 +354,6 @@ static int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame) if (ret >= 0 && avctx->codec->type == AVMEDIA_TYPE_VIDEO) ret = pkt->size; -#if FF_API_AVCTX_TIMEBASE - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) - avctx->time_base = av_inv_q(avctx->framerate); -#endif - if (avctx->internal->draining && !got_frame) avci->draining_done = 1; diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c index 500d1240efa1f..f883b5f819c8e 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -163,11 +163,6 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, s->coded_width = FFALIGN(pc->width, 16); s->coded_height = FFALIGN(pc->height, 16); } - -#if FF_API_AVCTX_TIMEBASE - if (avctx->framerate.num) - avctx->time_base = av_inv_q(avctx->framerate); -#endif } static int mpegvideo_parse(AVCodecParserContext *s, diff --git a/libavcodec/utils.c b/libavcodec/utils.c index a6408cecbb5e2..bc421f67f8141 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -663,11 +663,6 @@ FF_ENABLE_DEPRECATION_WARNINGS ret = AVERROR(EINVAL); goto free_and_end; } - -#if FF_API_AVCTX_TIMEBASE - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) - avctx->time_base = av_inv_q(avctx->framerate); -#endif } end: if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) { diff --git a/libavcodec/version.h b/libavcodec/version.h index b60e9715aaa78..f53bdb5ccc0fc 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,9 +47,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_AVCTX_TIMEBASE -#define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_MPV_OPT #define FF_API_MPV_OPT (LIBAVCODEC_VERSION_MAJOR < 58) #endif From 94eed68ace9f2416af8457fcbf142b175928c06b Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Thu, 16 Mar 2017 16:03:38 -0400 Subject: [PATCH 0096/2557] lavc: Drop deprecated options moved to private contexts Deprecated in 10/2014 and 07/2015. --- libavcodec/avcodec.h | 114 ------------------------------------- libavcodec/dnxhdenc.c | 6 -- libavcodec/internal.h | 2 - libavcodec/libvpxenc.c | 9 --- libavcodec/libx264.c | 21 +------ libavcodec/libxavs.c | 26 --------- libavcodec/libxvid.c | 24 -------- libavcodec/motion_est.c | 19 ------- libavcodec/mpegvideo.h | 3 - libavcodec/mpegvideo_enc.c | 48 ---------------- libavcodec/options.c | 15 ----- libavcodec/options_table.h | 46 --------------- libavcodec/svq1enc.c | 13 ----- libavcodec/version.h | 12 ---- 14 files changed, 1 insertion(+), 357 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 2366acf93c506..4bcead7106210 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -657,25 +657,6 @@ typedef struct AVCodecDescriptor { */ #define AV_INPUT_BUFFER_MIN_SIZE 16384 -/** - * @ingroup lavc_encoding - * motion estimation type. - * @deprecated use codec private option instead - */ -#if FF_API_MOTION_EST -enum Motion_Est_ID { - ME_ZERO = 1, ///< no search, that is use 0,0 vector whenever one is needed - ME_FULL, - ME_LOG, - ME_PHODS, - ME_EPZS, ///< enhanced predictive zonal search - ME_X1, ///< reserved for experiments - ME_HEX, ///< hexagon based search - ME_UMH, ///< uneven multi-hexagon search - ME_TESA, ///< transformed exhaustive search algorithm -}; -#endif - /** * @ingroup lavc_decoding */ @@ -1412,14 +1393,6 @@ typedef struct AVCodecContext { */ enum AVPixelFormat pix_fmt; -#if FF_API_MOTION_EST - /** - * This option does nothing - * @deprecated use codec private options instead - */ - attribute_deprecated int me_method; -#endif - /** * If non NULL, 'draw_horiz_band' is called by the libavcodec * decoder to draw a horizontal band. It improves cache usage. Not @@ -1479,12 +1452,6 @@ typedef struct AVCodecContext { */ float b_quant_factor; -#if FF_API_RC_STRATEGY - /** @deprecated use codec private option instead */ - attribute_deprecated int rc_strategy; -#define FF_RC_STRATEGY_XVID 1 -#endif - #if FF_API_PRIVATE_OPT /** @deprecated use encoder private options instead */ attribute_deprecated @@ -1684,19 +1651,6 @@ typedef struct AVCodecContext { */ int me_range; -#if FF_API_QUANT_BIAS - /** - * @deprecated use encoder private option instead - */ - attribute_deprecated int intra_quant_bias; -#define FF_DEFAULT_QUANT_BIAS 999999 - - /** - * @deprecated use encoder private option instead - */ - attribute_deprecated int inter_quant_bias; -#endif - /** * slice flags * - encoding: unused @@ -1741,20 +1695,6 @@ typedef struct AVCodecContext { int noise_reduction; #endif -#if FF_API_MPV_OPT - /** - * @deprecated this field is unused - */ - attribute_deprecated - int me_threshold; - - /** - * @deprecated this field is unused - */ - attribute_deprecated - int mb_threshold; -#endif - /** * precision of the intra DC coefficient - 8 * - encoding: Set by user. @@ -1776,14 +1716,6 @@ typedef struct AVCodecContext { */ int skip_bottom; -#if FF_API_MPV_OPT - /** - * @deprecated use encoder private options instead - */ - attribute_deprecated - float border_masking; -#endif - /** * minimum MB Lagrange multiplier * - encoding: Set by user. @@ -2096,19 +2028,6 @@ typedef struct AVCodecContext { */ int max_qdiff; -#if FF_API_MPV_OPT - /** - * @deprecated use encoder private options instead - */ - attribute_deprecated - float rc_qsquish; - - attribute_deprecated - float rc_qmod_amp; - attribute_deprecated - int rc_qmod_freq; -#endif - /** * decoder bitstream buffer size * - encoding: Set by user. @@ -2124,14 +2043,6 @@ typedef struct AVCodecContext { int rc_override_count; RcOverride *rc_override; -#if FF_API_MPV_OPT - /** - * @deprecated use encoder private options instead - */ - attribute_deprecated - const char *rc_eq; -#endif - /** * maximum bitrate * - encoding: Set by user. @@ -2146,17 +2057,6 @@ typedef struct AVCodecContext { */ int rc_min_rate; -#if FF_API_MPV_OPT - /** - * @deprecated use encoder private options instead - */ - attribute_deprecated - float rc_buffer_aggressivity; - - attribute_deprecated - float rc_initial_cplx; -#endif - /** * Ratecontrol attempt to use, at maximum, of what can be used without an underflow. * - encoding: Set by user. @@ -2196,20 +2096,6 @@ typedef struct AVCodecContext { int context_model; #endif -#if FF_API_MPV_OPT - /** - * @deprecated use encoder private options instead - */ - attribute_deprecated - int lmin; - - /** - * @deprecated use encoder private options instead - */ - attribute_deprecated - int lmax; -#endif - #if FF_API_PRIVATE_OPT /** @deprecated use encoder private options instead */ attribute_deprecated diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c index f5fd9e9a38197..9d4b05292a663 100644 --- a/libavcodec/dnxhdenc.c +++ b/libavcodec/dnxhdenc.c @@ -343,12 +343,6 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) ctx->m.mb_num = ctx->m.mb_height * ctx->m.mb_width; -#if FF_API_QUANT_BIAS -FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->intra_quant_bias != FF_DEFAULT_QUANT_BIAS) - ctx->intra_quant_bias = avctx->intra_quant_bias; -FF_ENABLE_DEPRECATION_WARNINGS -#endif // XXX tune lbias/cbias if ((ret = dnxhd_init_qmat(ctx, ctx->intra_quant_bias, 0)) < 0) return ret; diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 5b82504bfb37b..403fb4a090bcc 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -73,9 +73,7 @@ #endif -#if !FF_API_QUANT_BIAS #define FF_DEFAULT_QUANT_BIAS 999999 -#endif #define FF_SANE_NB_CHANNELS 63U diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index bb4c98fea5655..7e971fd97f184 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -362,15 +362,6 @@ FF_ENABLE_DEPRECATION_WARNINGS codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, ctx->noise_sensitivity); codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS, av_log2(avctx->slices)); } -#if FF_API_MPV_OPT - FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->mb_threshold) { - av_log(avctx, AV_LOG_WARNING, "The mb_threshold option is deprecated, " - "use the static-thresh private option instead.\n"); - ctx->static_thresh = avctx->mb_threshold; - } - FF_ENABLE_DEPRECATION_WARNINGS -#endif codecctl_int(avctx, VP8E_SET_STATIC_THRESHOLD, ctx->static_thresh); codecctl_int(avctx, VP8E_SET_CQ_LEVEL, ctx->crf); diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index fddf1b38282be..4448d977cf9bd 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -547,24 +547,8 @@ FF_ENABLE_DEPRECATION_WARNINGS if (x4->nal_hrd >= 0) x4->params.i_nal_hrd = x4->nal_hrd; - if (x4->motion_est >= 0) { + if (x4->motion_est >= 0) x4->params.analyse.i_me_method = x4->motion_est; -#if FF_API_MOTION_EST -FF_DISABLE_DEPRECATION_WARNINGS - } else { - if (avctx->me_method == ME_EPZS) - x4->params.analyse.i_me_method = X264_ME_DIA; - else if (avctx->me_method == ME_HEX) - x4->params.analyse.i_me_method = X264_ME_HEX; - else if (avctx->me_method == ME_UMH) - x4->params.analyse.i_me_method = X264_ME_UMH; - else if (avctx->me_method == ME_FULL) - x4->params.analyse.i_me_method = X264_ME_ESA; - else if (avctx->me_method == ME_TESA) - x4->params.analyse.i_me_method = X264_ME_TESA; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - } if (x4->coder >= 0) x4->params.b_cabac = x4->coder; @@ -803,9 +787,6 @@ static const AVCodecDefault x264_defaults[] = { { "nr", "-1" }, #endif { "me_range", "-1" }, -#if FF_API_MOTION_EST - { "me_method", "-1" }, -#endif { "subq", "-1" }, #if FF_API_PRIVATE_OPT { "b_strategy", "-1" }, diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c index b7a6c416660e7..24ddd22e5fd87 100644 --- a/libavcodec/libxavs.c +++ b/libavcodec/libxavs.c @@ -285,32 +285,6 @@ static av_cold int XAVS_init(AVCodecContext *avctx) if (x4->cplxblur >= 0) x4->params.rc.f_complexity_blur = x4->cplxblur; -#if FF_API_MOTION_EST -FF_DISABLE_DEPRECATION_WARNINGS - if (x4->motion_est < 0) { - switch (avctx->me_method) { - case ME_EPZS: - x4->params.analyse.i_me_method = XAVS_ME_DIA; - break; - case ME_HEX: - x4->params.analyse.i_me_method = XAVS_ME_HEX; - break; - case ME_UMH: - x4->params.analyse.i_me_method = XAVS_ME_UMH; - break; - case ME_FULL: - x4->params.analyse.i_me_method = XAVS_ME_ESA; - break; - case ME_TESA: - x4->params.analyse.i_me_method = XAVS_ME_TESA; - break; - default: - x4->params.analyse.i_me_method = XAVS_ME_HEX; - } - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif - x4->params.i_bframe = avctx->max_b_frames; /* cabac is not included in AVS JiZhun Profile */ x4->params.b_cabac = 0; diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c index dce62a0dba144..896935d31eee8 100644 --- a/libavcodec/libxvid.c +++ b/libavcodec/libxvid.c @@ -432,30 +432,6 @@ static av_cold int xvid_encode_init(AVCodecContext *avctx) case 1: x->me_flags |= XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16; -#if FF_API_MOTION_EST -FF_DISABLE_DEPRECATION_WARNINGS - break; - default: - switch (avctx->me_method) { - case ME_FULL: /* Quality 6 */ - x->me_flags |= XVID_ME_EXTSEARCH16 | - XVID_ME_EXTSEARCH8; - case ME_EPZS: /* Quality 4 */ - x->me_flags |= XVID_ME_ADVANCEDDIAMOND8 | - XVID_ME_HALFPELREFINE8 | - XVID_ME_CHROMA_PVOP | - XVID_ME_CHROMA_BVOP; - case ME_LOG: /* Quality 2 */ - case ME_PHODS: - case ME_X1: - x->me_flags |= XVID_ME_ADVANCEDDIAMOND16 | - XVID_ME_HALFPELREFINE16; - case ME_ZERO: /* Quality 0 */ - default: - break; - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif } /* Decide how we should decide blocks */ diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c index 1c0116c754102..c6dd3b86afb2b 100644 --- a/libavcodec/motion_est.c +++ b/libavcodec/motion_est.c @@ -310,25 +310,6 @@ int ff_init_me(MpegEncContext *s){ return -1; } -#if FF_API_MOTION_EST -FF_DISABLE_DEPRECATION_WARNINGS - if (s->motion_est == FF_ME_EPZS) { - if (s->me_method == ME_ZERO) - s->motion_est = FF_ME_ZERO; - else if (s->me_method == ME_EPZS) - s->motion_est = FF_ME_EPZS; - else if (s->me_method == ME_X1) - s->motion_est = FF_ME_XONE; - else { - av_log(s->avctx, AV_LOG_ERROR, - "me_method is only allowed to be set to zero and epzs; " - "for hex,umh,full and others see dia_size\n"); - return -1; - } - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif - c->avctx= s->avctx; if(cache_size < 2*dia_size && !c->stride){ diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 5d8c31ce02add..e7835e1ae36e3 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -247,9 +247,6 @@ typedef struct MpegEncContext { int16_t (*b_field_mv_table[2][2][2])[2];///< MV table (4MV per MB) interlaced B-frame encoding uint8_t (*p_field_select_table[2]); uint8_t (*b_field_select_table[2][2]); -#if FF_API_MOTION_EST - int me_method; ///< ME algorithm -#endif int motion_est; ///< ME algorithm int me_penalty_compensation; int me_pre; ///< prepass for motion estimation diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index a0c479ff4e533..84de157d1094d 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -335,22 +335,9 @@ FF_ENABLE_DEPRECATION_WARNINGS s->intra_only = 0; } -#if FF_API_MOTION_EST -FF_DISABLE_DEPRECATION_WARNINGS - s->me_method = avctx->me_method; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - /* Fixed QSCALE */ s->fixed_qscale = !!(avctx->flags & AV_CODEC_FLAG_QSCALE); -#if FF_API_MPV_OPT - FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->border_masking != 0.0) - s->border_masking = avctx->border_masking; - FF_ENABLE_DEPRECATION_WARNINGS -#endif - s->adaptive_quant = (s->avctx->lumi_masking || s->avctx->dark_masking || s->avctx->temporal_cplx_masking || @@ -583,15 +570,6 @@ FF_ENABLE_DEPRECATION_WARNINGS s->inter_quant_bias = -(1 << (QUANT_BIAS_SHIFT - 2)); } -#if FF_API_QUANT_BIAS -FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->intra_quant_bias != FF_DEFAULT_QUANT_BIAS) - s->intra_quant_bias = avctx->intra_quant_bias; - if (avctx->inter_quant_bias != FF_DEFAULT_QUANT_BIAS) - s->inter_quant_bias = avctx->inter_quant_bias; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - if (avctx->codec_id == AV_CODEC_ID_MPEG4 && s->avctx->time_base.den > (1 << 16) - 1) { av_log(avctx, AV_LOG_ERROR, @@ -874,32 +852,6 @@ FF_ENABLE_DEPRECATION_WARNINGS if (ff_rate_control_init(s) < 0) return -1; -#if FF_API_MPV_OPT - FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->rc_qsquish != 0.0) - s->rc_qsquish = avctx->rc_qsquish; - if (avctx->rc_qmod_amp != 0.0) - s->rc_qmod_amp = avctx->rc_qmod_amp; - if (avctx->rc_qmod_freq) - s->rc_qmod_freq = avctx->rc_qmod_freq; - if (avctx->rc_buffer_aggressivity != 1.0) - s->rc_buffer_aggressivity = avctx->rc_buffer_aggressivity; - if (avctx->rc_initial_cplx != 0.0) - s->rc_initial_cplx = avctx->rc_initial_cplx; - if (avctx->lmin) - s->lmin = avctx->lmin; - if (avctx->lmax) - s->lmax = avctx->lmax; - - if (avctx->rc_eq) { - av_freep(&s->rc_eq); - s->rc_eq = av_strdup(avctx->rc_eq); - if (!s->rc_eq) - return AVERROR(ENOMEM); - } - FF_ENABLE_DEPRECATION_WARNINGS -#endif - #if FF_API_PRIVATE_OPT FF_DISABLE_DEPRECATION_WARNINGS if (avctx->brd_scale) diff --git a/libavcodec/options.c b/libavcodec/options.c index 00921fbec3856..765bcb7730f7a 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -192,16 +192,6 @@ int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) dest->rc_override = NULL; dest->subtitle_header = NULL; dest->hw_frames_ctx = NULL; -#if FF_API_MPV_OPT - FF_DISABLE_DEPRECATION_WARNINGS - dest->rc_eq = NULL; - if (src->rc_eq) { - dest->rc_eq = av_strdup(src->rc_eq); - if (!dest->rc_eq) - return AVERROR(ENOMEM); - } - FF_ENABLE_DEPRECATION_WARNINGS -#endif #define alloc_and_copy_or_fail(obj, size, pad) \ if (src->obj && size > 0) { \ @@ -236,11 +226,6 @@ int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) av_freep(&dest->inter_matrix); av_freep(&dest->extradata); av_buffer_unref(&dest->hw_frames_ctx); -#if FF_API_MPV_OPT - FF_DISABLE_DEPRECATION_WARNINGS - av_freep(&dest->rc_eq); - FF_ENABLE_DEPRECATION_WARNINGS -#endif return AVERROR(ENOMEM); } #endif diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 7a8ef3d4a92c8..8868cea5e3b77 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -67,20 +67,6 @@ static const AVOption avcodec_options[] = { {"noout", "skip bitstream encoding", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_NO_OUTPUT }, INT_MIN, INT_MAX, V|E, "flags2"}, {"ignorecrop", "ignore cropping information from sps", 1, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_IGNORE_CROP }, INT_MIN, INT_MAX, V|D, "flags2"}, {"local_header", "place global headers at every keyframe instead of in extradata", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_LOCAL_HEADER }, INT_MIN, INT_MAX, V|E, "flags2"}, -#if FF_API_MOTION_EST -{"me_method", "set motion estimation method", OFFSET(me_method), AV_OPT_TYPE_INT, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method"}, -{"zero", "zero motion estimation (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_ZERO }, INT_MIN, INT_MAX, V|E, "me_method" }, -{"full", "full motion estimation (slowest)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_FULL }, INT_MIN, INT_MAX, V|E, "me_method" }, -{"epzs", "EPZS motion estimation (default)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method" }, -{"esa", "esa motion estimation (alias for full)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_FULL }, INT_MIN, INT_MAX, V|E, "me_method" }, -{"tesa", "tesa motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_TESA }, INT_MIN, INT_MAX, V|E, "me_method" }, -{"dia", "diamond motion estimation (alias for EPZS)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method" }, -{"log", "log motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_LOG }, INT_MIN, INT_MAX, V|E, "me_method" }, -{"phods", "phods motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_PHODS }, INT_MIN, INT_MAX, V|E, "me_method" }, -{"x1", "X1 motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_X1 }, INT_MIN, INT_MAX, V|E, "me_method" }, -{"hex", "hex motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_HEX }, INT_MIN, INT_MAX, V|E, "me_method" }, -{"umh", "umh motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_UMH }, INT_MIN, INT_MAX, V|E, "me_method" }, -#endif {"extradata_size", NULL, OFFSET(extradata_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, {"time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, INT_MIN, INT_MAX}, {"g", "set the group of picture (GOP) size", OFFSET(gop_size), AV_OPT_TYPE_INT, {.i64 = 12 }, INT_MIN, INT_MAX, V|E}, @@ -99,9 +85,6 @@ static const AVOption avcodec_options[] = { {"qdiff", "maximum difference between the quantizer scales (VBR)", OFFSET(max_qdiff), AV_OPT_TYPE_INT, {.i64 = 3 }, INT_MIN, INT_MAX, V|E}, {"bf", "use 'frames' B-frames", OFFSET(max_b_frames), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, -1, INT_MAX, V|E}, {"b_qfactor", "QP factor between P- and B-frames", OFFSET(b_quant_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1.25 }, -FLT_MAX, FLT_MAX, V|E}, -#if FF_API_RC_STRATEGY -{"rc_strategy", "ratecontrol method", OFFSET(rc_strategy), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, -#endif #if FF_API_PRIVATE_OPT {"b_strategy", "strategy to choose between I/P/B-frames", OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, V|E}, {"ps", "RTP payload size in bytes", OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, @@ -150,27 +133,13 @@ static const AVOption avcodec_options[] = { #if FF_API_PRIVATE_OPT {"mpeg_quant", "use MPEG quantizers instead of H.263", OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, #endif -#if FF_API_MPV_OPT -{"qsquish", "deprecated, use encoder private options instead", OFFSET(rc_qsquish), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, 0, 99, V|E}, -{"rc_qmod_amp", "deprecated, use encoder private options instead", OFFSET(rc_qmod_amp), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E}, -{"rc_qmod_freq", "deprecated, use encoder private options instead", OFFSET(rc_qmod_freq), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, -#endif {"rc_override_count", NULL, OFFSET(rc_override_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, -#if FF_API_MPV_OPT -{"rc_eq", "deprecated, use encoder private options instead", OFFSET(rc_eq), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, V|E}, -#endif {"maxrate", "Set maximum bitrate tolerance (in bits/s). Requires bufsize to be set.", OFFSET(rc_max_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, {"minrate", "Set minimum bitrate tolerance (in bits/s). Most useful in setting up a CBR encode. It is of little use otherwise.", OFFSET(rc_min_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, {"bufsize", "set ratecontrol buffer size (in bits)", OFFSET(rc_buffer_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|V|E}, -#if FF_API_MPV_OPT -{"rc_buf_aggressivity", "deprecated, use encoder private options instead", OFFSET(rc_buffer_aggressivity), AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, -FLT_MAX, FLT_MAX, V|E}, -#endif {"i_qfactor", "QP factor between P- and I-frames", OFFSET(i_quant_factor), AV_OPT_TYPE_FLOAT, {.dbl = -0.8 }, -FLT_MAX, FLT_MAX, V|E}, {"i_qoffset", "QP offset between P- and I-frames", OFFSET(i_quant_offset), AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, -FLT_MAX, FLT_MAX, V|E}, -#if FF_API_MPV_OPT -{"rc_init_cplx", "deprecated, use encoder private options instead", OFFSET(rc_initial_cplx), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E}, -#endif {"dct", "DCT algorithm", OFFSET(dct_algo), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, V|E, "dct"}, {"auto", "autoselect a good one (default)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_AUTO }, INT_MIN, INT_MAX, V|E, "dct"}, {"fastint", "fast integer", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_FASTINT }, INT_MIN, INT_MAX, V|E, "dct"}, @@ -248,10 +217,6 @@ static const AVOption avcodec_options[] = { {"pre_dia_size", "diamond type & size for motion estimation pre-pass", OFFSET(pre_dia_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, {"subq", "sub-pel motion estimation quality", OFFSET(me_subpel_quality), AV_OPT_TYPE_INT, {.i64 = 8 }, INT_MIN, INT_MAX, V|E}, {"me_range", "limit motion vectors range (1023 for DivX player)", OFFSET(me_range), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, -#if FF_API_QUANT_BIAS -{"ibias", "intra quant bias", OFFSET(intra_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, V|E}, -{"pbias", "inter quant bias", OFFSET(inter_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, V|E}, -#endif {"global_quality", NULL, OFFSET(global_quality), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, #if FF_API_CODER_TYPE {"coder", NULL, OFFSET(coder_type), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "coder"}, @@ -274,10 +239,6 @@ static const AVOption avcodec_options[] = { #if FF_API_PRIVATE_OPT {"sc_threshold", "scene change threshold", OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, #endif -#if FF_API_MPV_OPT -{"lmin", "deprecated, use encoder private options instead", OFFSET(lmin), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|E}, -{"lmax", "deprecated, use encoder private options instead", OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|E}, -#endif #if FF_API_PRIVATE_OPT {"nr", "noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, #endif @@ -285,10 +246,6 @@ static const AVOption avcodec_options[] = { {"flags2", NULL, OFFSET(flags2), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT}, 0, UINT_MAX, V|A|E|D, "flags2"}, {"threads", NULL, OFFSET(thread_count), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, INT_MAX, V|E|D, "threads"}, {"auto", "autodetect a suitable number of threads to use", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, INT_MIN, INT_MAX, V|E|D, "threads"}, -#if FF_API_MPV_OPT -{"me_threshold", "motion estimation threshold", OFFSET(me_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, -{"mb_threshold", "macroblock threshold", OFFSET(mb_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, -#endif {"dc", "intra_dc_precision", OFFSET(intra_dc_precision), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, V|E}, {"nssew", "nsse weight", OFFSET(nsse_weight), AV_OPT_TYPE_INT, {.i64 = 8 }, INT_MIN, INT_MAX, V|E}, {"skip_top", "number of macroblock rows at the top which are skipped", OFFSET(skip_top), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|D}, @@ -319,9 +276,6 @@ static const AVOption avcodec_options[] = { {"skip_exp", "frame skip exponent", OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, {"skipcmp", "frame skip compare function", OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, V|E, "cmp_func"}, #endif -#if FF_API_MPV_OPT -{"border_mask", "deprecated, use encoder private options instead", OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E}, -#endif {"mblmin", "minimum macroblock Lagrange factor (VBR)", OFFSET(mb_lmin), AV_OPT_TYPE_INT, {.i64 = FF_QP2LAMBDA * 2 }, 1, FF_LAMBDA_MAX, V|E}, {"mblmax", "maximum macroblock Lagrange factor (VBR)", OFFSET(mb_lmax), AV_OPT_TYPE_INT, {.i64 = FF_QP2LAMBDA * 31 }, 1, FF_LAMBDA_MAX, V|E}, #if FF_API_PRIVATE_OPT diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c index 12a23d06122c4..963fbe4401437 100644 --- a/libavcodec/svq1enc.c +++ b/libavcodec/svq1enc.c @@ -272,19 +272,6 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane, s->m.b8_stride = 2 * s->m.mb_width + 1; s->m.f_code = 1; s->m.pict_type = s->pict_type; -#if FF_API_MOTION_EST -FF_DISABLE_DEPRECATION_WARNINGS - s->m.me_method = s->avctx->me_method; - if (s->motion_est == FF_ME_EPZS) { - if (s->avctx->me_method == ME_ZERO) - s->motion_est = FF_ME_ZERO; - else if (s->avctx->me_method == ME_EPZS) - s->motion_est = FF_ME_EPZS; - else if (s->avctx->me_method == ME_X1) - s->motion_est = FF_ME_XONE; - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif s->m.motion_est = s->motion_est; s->m.me.scene_change_score = 0; // s->m.out_format = FMT_H263; diff --git a/libavcodec/version.h b/libavcodec/version.h index f53bdb5ccc0fc..e79701ecaafb5 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,24 +47,12 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_MPV_OPT -#define FF_API_MPV_OPT (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_STREAM_CODEC_TAG #define FF_API_STREAM_CODEC_TAG (LIBAVCODEC_VERSION_MAJOR < 58) #endif -#ifndef FF_API_QUANT_BIAS -#define FF_API_QUANT_BIAS (LIBAVCODEC_VERSION_MAJOR < 58) -#endif -#ifndef FF_API_RC_STRATEGY -#define FF_API_RC_STRATEGY (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_CODED_FRAME #define FF_API_CODED_FRAME (LIBAVCODEC_VERSION_MAJOR < 58) #endif -#ifndef FF_API_MOTION_EST -#define FF_API_MOTION_EST (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_SIDEDATA_ONLY_PKT #define FF_API_SIDEDATA_ONLY_PKT (LIBAVCODEC_VERSION_MAJOR < 59) #endif From 0648dec19db83bc8c87814d195e32cbad5698a40 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Thu, 16 Mar 2017 16:21:54 -0400 Subject: [PATCH 0097/2557] lavc: Drop deprecated stream codec tag Deprecated in 07/2015. --- libavcodec/avcodec.h | 8 -------- libavcodec/options_table.h | 3 --- libavcodec/version.h | 5 +---- libavutil/version.h | 4 ++-- 4 files changed, 3 insertions(+), 17 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 4bcead7106210..1c58fe2d689c1 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1217,14 +1217,6 @@ typedef struct AVCodecContext { */ unsigned int codec_tag; -#if FF_API_STREAM_CODEC_TAG - /** - * @deprecated this field is unused - */ - attribute_deprecated - unsigned int stream_codec_tag; -#endif - void *priv_data; /** diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 8868cea5e3b77..925ef376f3953 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -233,9 +233,6 @@ static const AVOption avcodec_options[] = { {"simple", "use mbcmp (default)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_SIMPLE }, INT_MIN, INT_MAX, V|E, "mbd"}, {"bits", "use fewest bits", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_BITS }, INT_MIN, INT_MAX, V|E, "mbd"}, {"rd", "use best rate distortion", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_RD }, INT_MIN, INT_MAX, V|E, "mbd"}, -#if FF_API_STREAM_CODEC_TAG -{"stream_codec_tag", NULL, OFFSET(stream_codec_tag), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, -#endif #if FF_API_PRIVATE_OPT {"sc_threshold", "scene change threshold", OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, #endif diff --git a/libavcodec/version.h b/libavcodec/version.h index e79701ecaafb5..4fb0a97a2714a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -47,11 +47,8 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_STREAM_CODEC_TAG -#define FF_API_STREAM_CODEC_TAG (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_CODED_FRAME -#define FF_API_CODED_FRAME (LIBAVCODEC_VERSION_MAJOR < 58) +#define FF_API_CODED_FRAME (LIBAVCODEC_VERSION_MAJOR < 59) #endif #ifndef FF_API_SIDEDATA_ONLY_PKT #define FF_API_SIDEDATA_ONLY_PKT (LIBAVCODEC_VERSION_MAJOR < 59) diff --git a/libavutil/version.h b/libavutil/version.h index 904d3874116c7..5ac2c831eda20 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -91,10 +91,10 @@ #define FF_API_CRYPTO_CONTEXT (LIBAVUTIL_VERSION_MAJOR < 57) #endif #ifndef FF_API_PLUS1_MINUS1 -#define FF_API_PLUS1_MINUS1 (LIBAVUTIL_VERSION_MAJOR < 56) +#define FF_API_PLUS1_MINUS1 (LIBAVUTIL_VERSION_MAJOR < 57) #endif #ifndef FF_API_ERROR_FRAME -#define FF_API_ERROR_FRAME (LIBAVUTIL_VERSION_MAJOR < 56) +#define FF_API_ERROR_FRAME (LIBAVUTIL_VERSION_MAJOR < 57) #endif #ifndef FF_API_VAAPI #define FF_API_VAAPI (LIBAVUTIL_VERSION_MAJOR < 57) From dd343fd986459f467a2d1d70c26101dff1d47d68 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 17:13:33 -0500 Subject: [PATCH 0098/2557] lavu: Drop deprecated VDPAU pixel formats Deprecated in 07/2013. --- libavutil/pixdesc.c | 38 -------------------------------------- libavutil/pixfmt.h | 10 ---------- libavutil/version.h | 3 --- 3 files changed, 51 deletions(-) diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index e4e5674a66a50..815e084155f29 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -822,44 +822,6 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, -#if FF_API_VDPAU - [AV_PIX_FMT_VDPAU_H264] = { - .name = "vdpau_h264", - .log2_chroma_w = 1, - .log2_chroma_h = 1, - .flags = AV_PIX_FMT_FLAG_HWACCEL, - }, - [AV_PIX_FMT_VDPAU_MPEG1] = { - .name = "vdpau_mpeg1", - .log2_chroma_w = 1, - .log2_chroma_h = 1, - .flags = AV_PIX_FMT_FLAG_HWACCEL, - }, - [AV_PIX_FMT_VDPAU_MPEG2] = { - .name = "vdpau_mpeg2", - .log2_chroma_w = 1, - .log2_chroma_h = 1, - .flags = AV_PIX_FMT_FLAG_HWACCEL, - }, - [AV_PIX_FMT_VDPAU_WMV3] = { - .name = "vdpau_wmv3", - .log2_chroma_w = 1, - .log2_chroma_h = 1, - .flags = AV_PIX_FMT_FLAG_HWACCEL, - }, - [AV_PIX_FMT_VDPAU_VC1] = { - .name = "vdpau_vc1", - .log2_chroma_w = 1, - .log2_chroma_h = 1, - .flags = AV_PIX_FMT_FLAG_HWACCEL, - }, - [AV_PIX_FMT_VDPAU_MPEG4] = { - .name = "vdpau_mpeg4", - .log2_chroma_w = 1, - .log2_chroma_h = 1, - .flags = AV_PIX_FMT_FLAG_HWACCEL, - }, -#endif [AV_PIX_FMT_RGB48BE] = { .name = "rgb48be", .nb_components = 3, diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 0b7582576bfb8..3c670fc9d45c2 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -92,13 +92,6 @@ enum AVPixelFormat { AV_PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) AV_PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range AV_PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) -#if FF_API_VDPAU - AV_PIX_FMT_VDPAU_H264,///< H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - AV_PIX_FMT_VDPAU_MPEG1,///< MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - AV_PIX_FMT_VDPAU_MPEG2,///< MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - AV_PIX_FMT_VDPAU_WMV3,///< WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - AV_PIX_FMT_VDPAU_VC1, ///< VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers -#endif AV_PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian AV_PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian @@ -127,9 +120,6 @@ enum AVPixelFormat { AV_PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian AV_PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian AV_PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian -#if FF_API_VDPAU - AV_PIX_FMT_VDPAU_MPEG4, ///< MPEG-4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers -#endif AV_PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer AV_PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0 diff --git a/libavutil/version.h b/libavutil/version.h index 5ac2c831eda20..3b2280cecd562 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -78,9 +78,6 @@ * @{ */ -#ifndef FF_API_VDPAU -#define FF_API_VDPAU (LIBAVUTIL_VERSION_MAJOR < 56) -#endif #ifndef FF_API_OPT_TYPE_METADATA #define FF_API_OPT_TYPE_METADATA (LIBAVUTIL_VERSION_MAJOR < 56) #endif From 619a433eca2c5655c41b799e0b06380020fb1498 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 5 Dec 2016 17:22:49 -0500 Subject: [PATCH 0099/2557] lavu: Drop deprecated option type Deprecated in 02/2014. --- libavutil/opt.h | 3 --- libavutil/version.h | 3 --- 2 files changed, 6 deletions(-) diff --git a/libavutil/opt.h b/libavutil/opt.h index a65c4f41ba71a..b68a396da7143 100644 --- a/libavutil/opt.h +++ b/libavutil/opt.h @@ -263,9 +263,6 @@ typedef struct AVOption { int flags; #define AV_OPT_FLAG_ENCODING_PARAM 1 ///< a generic parameter which can be set by the user for muxing or encoding #define AV_OPT_FLAG_DECODING_PARAM 2 ///< a generic parameter which can be set by the user for demuxing or decoding -#if FF_API_OPT_TYPE_METADATA -#define AV_OPT_FLAG_METADATA 4 ///< some data extracted or inserted into the file like title, comment, ... -#endif #define AV_OPT_FLAG_AUDIO_PARAM 8 #define AV_OPT_FLAG_VIDEO_PARAM 16 #define AV_OPT_FLAG_SUBTITLE_PARAM 32 diff --git a/libavutil/version.h b/libavutil/version.h index 3b2280cecd562..d11e8d10f2980 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -78,9 +78,6 @@ * @{ */ -#ifndef FF_API_OPT_TYPE_METADATA -#define FF_API_OPT_TYPE_METADATA (LIBAVUTIL_VERSION_MAJOR < 56) -#endif #ifndef FF_API_DLOG #define FF_API_DLOG (LIBAVUTIL_VERSION_MAJOR < 56) #endif From 35cf146a33ce41a1adb6c9bd5a0827eacb1b6bfc Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Thu, 16 Mar 2017 15:30:58 -0400 Subject: [PATCH 0100/2557] lavu: Drop deprecated av_dlog macro Deprecated in 05/2015. --- libavutil/log.h | 14 -------------- libavutil/version.h | 3 --- 2 files changed, 17 deletions(-) diff --git a/libavutil/log.h b/libavutil/log.h index d4daea9c1a47b..ce00bccc7bb43 100644 --- a/libavutil/log.h +++ b/libavutil/log.h @@ -249,20 +249,6 @@ void av_log_default_callback(void *avcl, int level, const char *fmt, */ const char* av_default_item_name(void* ctx); -#if FF_API_DLOG -/** - * av_dlog macros - * @deprecated unused - * Useful to print debug messages that shouldn't get compiled in normally. - */ - -#ifdef DEBUG -# define av_dlog(pctx, ...) av_log(pctx, AV_LOG_DEBUG, __VA_ARGS__) -#else -# define av_dlog(pctx, ...) -#endif -#endif /* FF_API_DLOG */ - /** * Skip repeated messages, this requires the user app to use av_log() instead of * (f)printf as the 2 would otherwise interfere and lead to diff --git a/libavutil/version.h b/libavutil/version.h index d11e8d10f2980..b8425ea2c839e 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -78,9 +78,6 @@ * @{ */ -#ifndef FF_API_DLOG -#define FF_API_DLOG (LIBAVUTIL_VERSION_MAJOR < 56) -#endif #ifndef FF_API_CRYPTO_CONTEXT #define FF_API_CRYPTO_CONTEXT (LIBAVUTIL_VERSION_MAJOR < 57) #endif From 5f90ad99bb7e53383fefab5107b861e4c4600700 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Tue, 14 Mar 2017 17:50:48 -0400 Subject: [PATCH 0101/2557] spherical: Change types of bounding and pad to uint32_t These values are defined to be 32bit in the specification, so it makes more sense to store them as fixed width. Based on a patch by Micahel Niedermayer . Signed-off-by: Vittorio Giovara --- libavformat/dump.c | 2 +- libavformat/matroskadec.c | 6 +++--- libavformat/mov.c | 7 +++---- libavutil/spherical.h | 10 +++++----- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/libavformat/dump.c b/libavformat/dump.c index 7514aee7ac71c..c56895628d754 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -339,7 +339,7 @@ static void dump_spherical(void *ctx, AVCodecParameters *par, AVPacketSideData * &l, &t, &r, &b); av_log(ctx, AV_LOG_INFO, "[%zu, %zu, %zu, %zu] ", l, t, r, b); } else if (spherical->projection == AV_SPHERICAL_CUBEMAP) { - av_log(ctx, AV_LOG_INFO, "[pad %zu] ", spherical->padding); + av_log(ctx, AV_LOG_INFO, "[pad %"PRIu32"] ", spherical->padding); } } diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 4fbf4b9a96526..c6e1a190a8e8b 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -1601,8 +1601,8 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) AVSphericalMapping *spherical; enum AVSphericalProjection projection; size_t spherical_size; - size_t l = 0, t = 0, r = 0, b = 0; - size_t padding = 0; + uint32_t l = 0, t = 0, r = 0, b = 0; + uint32_t padding = 0; int ret; GetByteContext gb; @@ -1627,7 +1627,7 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) if (b >= UINT_MAX - t || r >= UINT_MAX - l) { av_log(NULL, AV_LOG_ERROR, "Invalid bounding rectangle coordinates " - "%zu,%zu,%zu,%zu\n", l, t, r, b); + "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b); return AVERROR_INVALIDDATA; } } else if (track->video.projection.private.size != 0) { diff --git a/libavformat/mov.c b/libavformat/mov.c index c6e7a38398d3a..1c1857eaf99b1 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3237,9 +3237,8 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) MOVStreamContext *sc; int size, version, layout; int32_t yaw, pitch, roll; - size_t l = 0, t = 0, r = 0, b = 0; - size_t padding = 0; - uint32_t tag; + uint32_t l = 0, t = 0, r = 0, b = 0; + uint32_t tag, padding = 0; enum AVSphericalProjection projection; if (c->fc->nb_streams < 1) @@ -3335,7 +3334,7 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (b >= UINT_MAX - t || r >= UINT_MAX - l) { av_log(c->fc, AV_LOG_ERROR, "Invalid bounding rectangle coordinates " - "%zu,%zu,%zu,%zu\n", l, t, r, b); + "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b); return AVERROR_INVALIDDATA; } diff --git a/libavutil/spherical.h b/libavutil/spherical.h index e7fc1d69fb1d9..fd662cf676021 100644 --- a/libavutil/spherical.h +++ b/libavutil/spherical.h @@ -164,10 +164,10 @@ typedef struct AVSphericalMapping { * projection type (@ref AV_SPHERICAL_EQUIRECTANGULAR_TILE), * and should be ignored in all other cases. */ - size_t bound_left; ///< Distance from the left edge - size_t bound_top; ///< Distance from the top edge - size_t bound_right; ///< Distance from the right edge - size_t bound_bottom; ///< Distance from the bottom edge + uint32_t bound_left; ///< Distance from the left edge + uint32_t bound_top; ///< Distance from the top edge + uint32_t bound_right; ///< Distance from the right edge + uint32_t bound_bottom; ///< Distance from the bottom edge /** * @} */ @@ -179,7 +179,7 @@ typedef struct AVSphericalMapping { * (@ref AV_SPHERICAL_CUBEMAP), and should be ignored in all other * cases. */ - size_t padding; + uint32_t padding; } AVSphericalMapping; /** From 3f128fc4a3fa1ef8a87974eb5484a997a84868fe Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 15 Mar 2017 17:39:53 -0400 Subject: [PATCH 0102/2557] vf_showinfo: Simplify reporting stereo3d information --- libavfilter/vf_showinfo.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index 204ff7a857d49..b44f3d2bf28af 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -51,19 +51,7 @@ static void dump_stereo3d(AVFilterContext *ctx, AVFrameSideData *sd) stereo = (AVStereo3D *)sd->data; - av_log(ctx, AV_LOG_INFO, "type - "); - switch (stereo->type) { - case AV_STEREO3D_2D: av_log(ctx, AV_LOG_INFO, "2D"); break; - case AV_STEREO3D_SIDEBYSIDE: av_log(ctx, AV_LOG_INFO, "side by side"); break; - case AV_STEREO3D_TOPBOTTOM: av_log(ctx, AV_LOG_INFO, "top and bottom"); break; - case AV_STEREO3D_FRAMESEQUENCE: av_log(ctx, AV_LOG_INFO, "frame alternate"); break; - case AV_STEREO3D_CHECKERBOARD: av_log(ctx, AV_LOG_INFO, "checkerboard"); break; - case AV_STEREO3D_LINES: av_log(ctx, AV_LOG_INFO, "interleaved lines"); break; - case AV_STEREO3D_COLUMNS: av_log(ctx, AV_LOG_INFO, "interleaved columns"); break; - case AV_STEREO3D_SIDEBYSIDE_QUINCUNX: av_log(ctx, AV_LOG_INFO, "side by side " - "(quincunx subsampling)"); break; - default: av_log(ctx, AV_LOG_WARNING, "unknown"); break; - } + av_log(ctx, AV_LOG_INFO, "type - %s", av_stereo3d_type_name(stereo->type)); if (stereo->flags & AV_STEREO3D_FLAG_INVERT) av_log(ctx, AV_LOG_INFO, " (inverted)"); From 883ce264d9ffc5bdaf477e09ee155b03339c46a6 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 15 Mar 2017 17:55:18 -0400 Subject: [PATCH 0103/2557] vf_showinfo: Display spherical properties --- libavfilter/vf_showinfo.c | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index b44f3d2bf28af..d5605e6922d64 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -29,6 +29,7 @@ #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/pixdesc.h" +#include "libavutil/spherical.h" #include "libavutil/stereo3d.h" #include "avfilter.h" @@ -39,6 +40,43 @@ typedef struct ShowInfoContext { unsigned int frame; } ShowInfoContext; +static void dump_spherical(AVFilterContext *ctx, AVFrame *frame, AVFrameSideData *sd) +{ + AVSphericalMapping *spherical = (AVSphericalMapping *)sd->data; + double yaw, pitch, roll; + + av_log(ctx, AV_LOG_INFO, "spherical information: "); + if (sd->size < sizeof(*spherical)) { + av_log(ctx, AV_LOG_INFO, "invalid data"); + return; + } + + if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR) + av_log(ctx, AV_LOG_INFO, "equirectangular "); + else if (spherical->projection == AV_SPHERICAL_CUBEMAP) + av_log(ctx, AV_LOG_INFO, "cubemap "); + else if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) + av_log(ctx, AV_LOG_INFO, "tiled equirectangular "); + else { + av_log(ctx, AV_LOG_WARNING, "unknown"); + return; + } + + yaw = ((double)spherical->yaw) / (1 << 16); + pitch = ((double)spherical->pitch) / (1 << 16); + roll = ((double)spherical->roll) / (1 << 16); + av_log(ctx, AV_LOG_INFO, "(%f/%f/%f) ", yaw, pitch, roll); + + if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) { + size_t l, t, r, b; + av_spherical_tile_bounds(spherical, frame->width, frame->height, + &l, &t, &r, &b); + av_log(ctx, AV_LOG_INFO, "[%zu, %zu, %zu, %zu] ", l, t, r, b); + } else if (spherical->projection == AV_SPHERICAL_CUBEMAP) { + av_log(ctx, AV_LOG_INFO, "[pad %"PRIu32"] ", spherical->padding); + } +} + static void dump_stereo3d(AVFilterContext *ctx, AVFrameSideData *sd) { AVStereo3D *stereo; @@ -105,6 +143,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) case AV_FRAME_DATA_A53_CC: av_log(ctx, AV_LOG_INFO, "A/53 closed captions (%d bytes)", sd->size); break; + case AV_FRAME_DATA_SPHERICAL: + dump_spherical(ctx, frame, sd); + break; case AV_FRAME_DATA_STEREO3D: dump_stereo3d(ctx, sd); break; From 8c616b3b8996bd4f9b117496b66b16cc625d7d24 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Thu, 23 Mar 2017 12:20:50 +0100 Subject: [PATCH 0104/2557] avplay: Use the named syntax for buffersrc arguments Avoid confusion. --- avtools/avplay.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/avtools/avplay.c b/avtools/avplay.c index 18879e16bcc53..26279e857d989 100644 --- a/avtools/avplay.c +++ b/avtools/avplay.c @@ -1441,7 +1441,8 @@ static int configure_video_filters(AVFilterGraph *graph, PlayerState *is, const snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%"PRId64, sws_flags); graph->scale_sws_opts = av_strdup(sws_flags_str); - snprintf(buffersrc_args, sizeof(buffersrc_args), "%d:%d:%d:%d:%d:%d:%d", + snprintf(buffersrc_args, sizeof(buffersrc_args), + "width=%d:height=%d:pix_fmt=%d:time_base=%d/%d:sar=%d/%d", codec->width, codec->height, codec->pix_fmt, is->video_st->time_base.num, is->video_st->time_base.den, codec->sample_aspect_ratio.num, codec->sample_aspect_ratio.den); From 083ea8768121ee800893e124b08483011b798919 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Thu, 23 Mar 2017 10:39:11 +0100 Subject: [PATCH 0105/2557] APIchanges: Update bump dates --- doc/APIchanges | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index c6a5d82b99136..a0ca3b7ac0001 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,13 +2,13 @@ Never assume the API of libav* to be stable unless at least 1 month has passed since the last major version increase. The last version increases were: -libavcodec: 2015-08-28 -libavdevice: 2015-08-28 -libavfilter: 2015-08-28 -libavformat: 2015-08-28 -libavresample: 2015-08-28 -libswscale: 2015-08-28 -libavutil: 2015-08-28 +libavcodec: 2017-03-23 +libavdevice: 2017-03-23 +libavfilter: 2017-03-23 +libavformat: 2017-03-23 +libavresample: 2017-03-23 +libswscale: 2017-03-23 +libavutil: 2017-03-23 API changes, most recent first: From d6390090c4dbd766b77353553d9cb4fb4fb41ebd Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 24 Mar 2017 20:24:08 +0100 Subject: [PATCH 0106/2557] configure: Skip check for inline assembly capabilities when explicitly disabled Otherwise inline assembly may get enabled when disabled on the command line. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 366520cf96b41..d9609fc51a9a2 100755 --- a/configure +++ b/configure @@ -4251,7 +4251,7 @@ EOF sym=$($nm $TMPO | awk '/ff_extern/{ print substr($0, match($0, /[^ \t]*ff_extern/)) }') extern_prefix=${sym%%ff_extern*} -check_inline_asm inline_asm '"" ::' +! disabled inline_asm && check_inline_asm inline_asm '"" ::' _restrict= for restrict_keyword in restrict __restrict__ __restrict; do From d4f3c26b700ae847433ba3c67dc99c32bc1fd4a1 Mon Sep 17 00:00:00 2001 From: Ricardo Constantino Date: Mon, 20 Mar 2017 20:28:09 +0000 Subject: [PATCH 0107/2557] rtmpproto: send swfverify value as swfurl if latter is unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replicates lavf/librtmp.c behavior in L145-152 and rtmpdump's behavior with "--swfVfy " passing the url to swfUrl. Fixes bug 943. Signed-off-by: Martin Storsjö --- libavformat/rtmpproto.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 7d402276323df..115c335974615 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -339,9 +339,12 @@ static int gen_connect(URLContext *s, RTMPContext *rt) ff_amf_write_field_name(&p, "flashVer"); ff_amf_write_string(&p, rt->flashver); - if (rt->swfurl) { + if (rt->swfurl || rt->swfverify) { ff_amf_write_field_name(&p, "swfUrl"); - ff_amf_write_string(&p, rt->swfurl); + if (rt->swfurl) + ff_amf_write_string(&p, rt->swfurl); + else + ff_amf_write_string(&p, rt->swfverify); } ff_amf_write_field_name(&p, "tcUrl"); From fe6eea99efac66839052af547426518efd970b24 Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Fri, 24 Mar 2017 13:36:51 -0400 Subject: [PATCH 0108/2557] nsvdec: don't ignore the return value of av_get_packet() Fixes invalid reads with corrupted files. CC: libav-stable@libav.org Bug-Id: 1039 --- libavformat/nsvdec.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavformat/nsvdec.c b/libavformat/nsvdec.c index c91d2a15dd985..924c8694b1368 100644 --- a/libavformat/nsvdec.c +++ b/libavformat/nsvdec.c @@ -520,6 +520,7 @@ static int nsv_read_chunk(AVFormatContext *s, int fill_header) uint32_t vsize; uint16_t asize; uint16_t auxsize; + int ret; if (nsv->ahead[0].data || nsv->ahead[1].data) return 0; //-1; /* hey! eat what you've in your plate first! */ @@ -571,7 +572,8 @@ static int nsv_read_chunk(AVFormatContext *s, int fill_header) if (vsize && st[NSV_ST_VIDEO]) { nst = st[NSV_ST_VIDEO]->priv_data; pkt = &nsv->ahead[NSV_ST_VIDEO]; - av_get_packet(pb, pkt, vsize); + if ((ret = av_get_packet(pb, pkt, vsize)) < 0) + return ret; pkt->stream_index = st[NSV_ST_VIDEO]->index;//NSV_ST_VIDEO; pkt->dts = nst->frame_offset; pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */ @@ -615,7 +617,8 @@ static int nsv_read_chunk(AVFormatContext *s, int fill_header) bps, channels, samplerate); } } - av_get_packet(pb, pkt, asize); + if ((ret = av_get_packet(pb, pkt, asize)) < 0) + return ret; pkt->stream_index = st[NSV_ST_AUDIO]->index;//NSV_ST_AUDIO; pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */ if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) { From 75ef91543422049a01b594925fcdb182ea12eb09 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 24 Mar 2017 20:30:22 +0100 Subject: [PATCH 0109/2557] configure: Disable inline assembly for PathScale compilers These compilers pass the inline assembly check, but fail to compile our inline assembly in various ways. --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index d9609fc51a9a2..2d84700fc7d1b 100755 --- a/configure +++ b/configure @@ -5074,6 +5074,7 @@ elif enabled tms470; then disable inline_asm elif enabled pathscale; then add_cflags -fstrict-overflow -OPT:wrap_around_unsafe_opt=OFF + disable inline_asm elif enabled_any msvc icl; then enabled x86_32 && disable aligned_stack enabled_all x86_32 debug && add_cflags -Oy- From 0b9a237b2386ff84a6f99716bd58fa27a1b767e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= Date: Mon, 27 Mar 2017 09:52:55 +0200 Subject: [PATCH 0110/2557] hevc: Add NEON 4x4 and 8x8 IDCT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Optimized by Martin Storsjö . The speedup vs C code is around 3.2-4.4x. Signed-off-by: Martin Storsjö --- libavcodec/arm/Makefile | 2 + libavcodec/arm/hevc_idct.S | 228 ++++++++++++++++++++++++++++++ libavcodec/arm/hevcdsp_init_arm.c | 47 ++++++ libavcodec/hevcdsp.c | 2 + libavcodec/hevcdsp.h | 1 + 5 files changed, 280 insertions(+) create mode 100644 libavcodec/arm/hevc_idct.S create mode 100644 libavcodec/arm/hevcdsp_init_arm.c diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile index 77452b126dd15..555de160e4f45 100644 --- a/libavcodec/arm/Makefile +++ b/libavcodec/arm/Makefile @@ -134,6 +134,8 @@ NEON-OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_neon.o \ NEON-OBJS-$(CONFIG_APE_DECODER) += arm/apedsp_neon.o NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_neon.o \ arm/synth_filter_neon.o +NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevc_idct.o \ + arm/hevcdsp_init_arm.o NEON-OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_neon.o NEON-OBJS-$(CONFIG_RV40_DECODER) += arm/rv34dsp_neon.o \ arm/rv40dsp_neon.o diff --git a/libavcodec/arm/hevc_idct.S b/libavcodec/arm/hevc_idct.S new file mode 100644 index 0000000000000..4124fc8226b0e --- /dev/null +++ b/libavcodec/arm/hevc_idct.S @@ -0,0 +1,228 @@ +/* + * ARM NEON optimised IDCT functions for HEVC decoding + * Copyright (c) 2017 Alexandra Hájková + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +const trans, align=4 + .short 64, 83, 64, 36 + .short 89, 75, 50, 18 + .short 90, 87, 80, 70 + .short 57, 43, 25, 9 +endconst + +.macro sum_sub out, in, c, op + .ifc \op, + + vmlal.s16 \out, \in, \c + .else + vmlsl.s16 \out, \in, \c + .endif +.endm + +.macro tr_4x4 in0, in1, in2, in3, out0, out1, out2, out3, shift, tmp0, tmp1, tmp2, tmp3, tmp4 + vshll.s16 \tmp0, \in0, #6 + vmull.s16 \tmp2, \in1, d4[1] + vmov \tmp1, \tmp0 + vmull.s16 \tmp3, \in1, d4[3] + vmlal.s16 \tmp0, \in2, d4[0] @e0 + vmlsl.s16 \tmp1, \in2, d4[0] @e1 + vmlal.s16 \tmp2, \in3, d4[3] @o0 + vmlsl.s16 \tmp3, \in3, d4[1] @o1 + + vadd.s32 \tmp4, \tmp0, \tmp2 + vsub.s32 \tmp0, \tmp0, \tmp2 + vadd.s32 \tmp2, \tmp1, \tmp3 + vsub.s32 \tmp1, \tmp1, \tmp3 + vqrshrn.s32 \out0, \tmp4, #\shift + vqrshrn.s32 \out3, \tmp0, #\shift + vqrshrn.s32 \out1, \tmp2, #\shift + vqrshrn.s32 \out2, \tmp1, #\shift +.endm + +.macro tr_4x4_8 in0, in1, in2, in3, out0, out1, out2, out3, tmp0, tmp1, tmp2, tmp3 + vshll.s16 \tmp0, \in0, #6 + vld1.s16 {\in0}, [r1, :64]! + vmov \tmp1, \tmp0 + vmull.s16 \tmp2, \in1, \in0[1] + vmull.s16 \tmp3, \in1, \in0[3] + vmlal.s16 \tmp0, \in2, \in0[0] @e0 + vmlsl.s16 \tmp1, \in2, \in0[0] @e1 + vmlal.s16 \tmp2, \in3, \in0[3] @o0 + vmlsl.s16 \tmp3, \in3, \in0[1] @o1 + + vld1.s16 {\in0}, [r1, :64] + + vadd.s32 \out0, \tmp0, \tmp2 + vadd.s32 \out1, \tmp1, \tmp3 + vsub.s32 \out2, \tmp1, \tmp3 + vsub.s32 \out3, \tmp0, \tmp2 + + sub r1, r1, #8 +.endm + +@ Do a 4x4 transpose, using q registers for the subtransposes that don't +@ need to address the indiviudal d registers. +@ r0,r1 == rq0, r2,r3 == rq1 +.macro transpose_4x4 rq0, rq1, r0, r1, r2, r3 + vtrn.32 \rq0, \rq1 + vtrn.16 \r0, \r1 + vtrn.16 \r2, \r3 +.endm + +.macro idct_4x4 bitdepth +function ff_hevc_idct_4x4_\bitdepth\()_neon, export=1 +@r0 - coeffs + vld1.s16 {q0-q1}, [r0, :128] + + movrel r1, trans + vld1.s16 {d4}, [r1, :64] + + tr_4x4 d0, d1, d2, d3, d16, d17, d18, d19, 7, q10, q11, q12, q13, q0 + transpose_4x4 q8, q9, d16, d17, d18, d19 + + tr_4x4 d16, d17, d18, d19, d0, d1, d2, d3, 20 - \bitdepth, q10, q11, q12, q13, q0 + transpose_4x4 q0, q1, d0, d1, d2, d3 + vst1.s16 {d0-d3}, [r0, :128] + bx lr +endfunc +.endm + +.macro transpose8_4x4 r0, r1, r2, r3 + vtrn.16 \r0, \r1 + vtrn.16 \r2, \r3 + vtrn.32 \r0, \r2 + vtrn.32 \r1, \r3 +.endm + +.macro transpose_8x8 r0, r1, r2, r3, r4, r5, r6, r7, l0, l1, l2, l3, l4, l5, l6, l7 + transpose8_4x4 \r0, \r1, \r2, \r3 + transpose8_4x4 \r4, \r5, \r6, \r7 + + transpose8_4x4 \l0, \l1, \l2, \l3 + transpose8_4x4 \l4, \l5, \l6, \l7 +.endm + +.macro tr_8x4 shift, in0, in1, in2, in3, in4, in5, in6, in7 + tr_4x4_8 \in0, \in2, \in4, \in6, q8, q9, q10, q11, q12, q13, q14, q15 + + vmull.s16 q14, \in1, \in0[2] + vmull.s16 q12, \in1, \in0[0] + vmull.s16 q13, \in1, \in0[1] + sum_sub q14, \in3, \in0[0], - + sum_sub q12, \in3, \in0[1], + + sum_sub q13, \in3, \in0[3], - + + sum_sub q14, \in5, \in0[3], + + sum_sub q12, \in5, \in0[2], + + sum_sub q13, \in5, \in0[0], - + + sum_sub q14, \in7, \in0[1], + + sum_sub q12, \in7, \in0[3], + + sum_sub q13, \in7, \in0[2], - + + vadd.s32 q15, q10, q14 + vsub.s32 q10, q10, q14 + vqrshrn.s32 \in2, q15, \shift + + vmull.s16 q15, \in1, \in0[3] + sum_sub q15, \in3, \in0[2], - + sum_sub q15, \in5, \in0[1], + + sum_sub q15, \in7, \in0[0], - + + vqrshrn.s32 \in5, q10, \shift + + vadd.s32 q10, q8, q12 + vsub.s32 q8, q8, q12 + vadd.s32 q12, q9, q13 + vsub.s32 q9, q9, q13 + vadd.s32 q14, q11, q15 + vsub.s32 q11, q11, q15 + + vqrshrn.s32 \in0, q10, \shift + vqrshrn.s32 \in7, q8, \shift + vqrshrn.s32 \in1, q12, \shift + vqrshrn.s32 \in6, q9, \shift + vqrshrn.s32 \in3, q14, \shift + vqrshrn.s32 \in4, q11, \shift +.endm + +.macro idct_8x8 bitdepth +function ff_hevc_idct_8x8_\bitdepth\()_neon, export=1 +@r0 - coeffs + vpush {q4-q7} + + mov r1, r0 + mov r2, #64 + add r3, r0, #32 + vld1.s16 {q0-q1}, [r1,:128], r2 + vld1.s16 {q2-q3}, [r3,:128], r2 + vld1.s16 {q4-q5}, [r1,:128], r2 + vld1.s16 {q6-q7}, [r3,:128], r2 + + movrel r1, trans + + tr_8x4 7, d0, d2, d4, d6, d8, d10, d12, d14 + tr_8x4 7, d1, d3, d5, d7, d9, d11, d13, d15 + + @ Transpose each 4x4 block, and swap how d4-d7 and d8-d11 are used. + @ Layout before: + @ d0 d1 + @ d2 d3 + @ d4 d5 + @ d6 d7 + @ d8 d9 + @ d10 d11 + @ d12 d13 + @ d14 d15 + transpose_8x8 d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15 + @ Now the layout is: + @ d0 d8 + @ d2 d10 + @ d4 d12 + @ d6 d14 + @ d1 d9 + @ d3 d11 + @ d5 d13 + @ d7 d15 + + tr_8x4 20 - \bitdepth, d0, d2, d4, d6, d1, d3, d5, d7 + vswp d0, d8 + tr_8x4 20 - \bitdepth, d0, d10, d12, d14, d9, d11, d13, d15 + vswp d0, d8 + + transpose_8x8 d0, d2, d4, d6, d8, d10, d12, d14, d1, d3, d5, d7, d9, d11, d13, d15 + + mov r1, r0 + mov r2, #64 + add r3, r0, #32 + vst1.s16 {q0-q1}, [r1,:128], r2 + vst1.s16 {q2-q3}, [r3,:128], r2 + vst1.s16 {q4-q5}, [r1,:128], r2 + vst1.s16 {q6-q7}, [r3,:128], r2 + + vpop {q4-q7} + bx lr +endfunc +.endm + +idct_4x4 8 +idct_4x4 10 +idct_8x8 8 +idct_8x8 10 diff --git a/libavcodec/arm/hevcdsp_init_arm.c b/libavcodec/arm/hevcdsp_init_arm.c new file mode 100644 index 0000000000000..1e984e61886c8 --- /dev/null +++ b/libavcodec/arm/hevcdsp_init_arm.c @@ -0,0 +1,47 @@ +/* + * ARM NEON optimised HEVC IDCT + * Copyright (c) 2017 Alexandra Hájková + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" + +#include "libavcodec/hevcdsp.h" + +void ff_hevc_idct_4x4_8_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_8x8_8_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_4x4_10_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_8x8_10_neon(int16_t *coeffs, int col_limit); + +av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, int bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + if (bit_depth == 8) { + c->idct[0] = ff_hevc_idct_4x4_8_neon; + c->idct[1] = ff_hevc_idct_8x8_8_neon; + } + if (bit_depth == 10) { + c->idct[0] = ff_hevc_idct_4x4_10_neon; + c->idct[1] = ff_hevc_idct_8x8_10_neon; + } + } +} diff --git a/libavcodec/hevcdsp.c b/libavcodec/hevcdsp.c index 8ae023b49826f..81db9e29a513f 100644 --- a/libavcodec/hevcdsp.c +++ b/libavcodec/hevcdsp.c @@ -245,6 +245,8 @@ void ff_hevc_dsp_init(HEVCDSPContext *hevcdsp, int bit_depth) break; } + if (ARCH_ARM) + ff_hevc_dsp_init_arm(hevcdsp, bit_depth); if (ARCH_PPC) ff_hevc_dsp_init_ppc(hevcdsp, bit_depth); if (ARCH_X86) diff --git a/libavcodec/hevcdsp.h b/libavcodec/hevcdsp.h index 2f4ff0111f5d9..7fc6f9cf8a213 100644 --- a/libavcodec/hevcdsp.h +++ b/libavcodec/hevcdsp.h @@ -115,6 +115,7 @@ typedef struct HEVCDSPContext { void ff_hevc_dsp_init(HEVCDSPContext *hpc, int bit_depth); +void ff_hevc_dsp_init_arm(HEVCDSPContext *c, const int bit_depth); void ff_hevc_dsp_init_ppc(HEVCDSPContext *c, const int bit_depth); void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth); From 1bd986ed4b0e95ded368a8eeb5c044853c090f9b Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 23 Mar 2017 19:49:39 +0000 Subject: [PATCH 0111/2557] hwcontext: Move NONE to the be the first member of AVHWDeviceType Also use that to fix a warning in av_hwdevice_get_type_name(). --- libavutil/hwcontext.c | 3 ++- libavutil/hwcontext.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index 2c6d51ee55df7..ff9fe99abae21 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -67,7 +67,8 @@ enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name) const char *av_hwdevice_get_type_name(enum AVHWDeviceType type) { - if (type >= 0 && type < FF_ARRAY_ELEMS(hw_type_names)) + if (type > AV_HWDEVICE_TYPE_NONE && + type < FF_ARRAY_ELEMS(hw_type_names)) return hw_type_names[type]; else return NULL; diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h index 040e010b30865..889e30365ee13 100644 --- a/libavutil/hwcontext.h +++ b/libavutil/hwcontext.h @@ -25,12 +25,12 @@ #include "pixfmt.h" enum AVHWDeviceType { + AV_HWDEVICE_TYPE_NONE, AV_HWDEVICE_TYPE_VDPAU, AV_HWDEVICE_TYPE_CUDA, AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_DXVA2, AV_HWDEVICE_TYPE_QSV, - AV_HWDEVICE_TYPE_NONE, }; typedef struct AVHWDeviceInternal AVHWDeviceInternal; From 5a969f64b9cf40bad923c73b66c3031b0018e848 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 21 Mar 2017 12:10:40 +0100 Subject: [PATCH 0112/2557] jack: Drop support for old (2012) JACK versions --- configure | 7 ++----- libavdevice/jack.c | 4 ---- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/configure b/configure index 2d84700fc7d1b..f1488cf4943aa 100755 --- a/configure +++ b/configure @@ -1638,7 +1638,6 @@ SYSTEM_FUNCS=" gmtime_r inet_aton isatty - jack_port_get_latency_range LoadLibrary localtime_r mach_absolute_time @@ -4835,10 +4834,8 @@ check_header soundcard.h enabled_any alsa_indev alsa_outdev && check_lib alsa alsa/asoundlib.h snd_pcm_htimestamp -lasound -if enabled libjack; then - check_pkg_config libjack jack jack/jack.h jack_port_get_latency_range || - require_pkg_config libjack jack jack/jack.h jack_client_open -fi +enabled libjack && + require_pkg_config libjack jack jack/jack.h jack_port_get_latency_range enabled_any sndio_indev sndio_outdev && check_lib sndio sndio.h sio_open -lsndio diff --git a/libavdevice/jack.c b/libavdevice/jack.c index 0b4deee01cf32..c31c4ce5b3e23 100644 --- a/libavdevice/jack.c +++ b/libavdevice/jack.c @@ -93,13 +93,9 @@ static int process_callback(jack_nframes_t nframes, void *arg) /* Copy and interleave audio data from the JACK buffer into the packet */ for (i = 0; i < self->nports; i++) { - #if HAVE_JACK_PORT_GET_LATENCY_RANGE jack_latency_range_t range; jack_port_get_latency_range(self->ports[i], JackCaptureLatency, &range); latency += range.max; - #else - latency += jack_port_get_total_latency(self->client, self->ports[i]); - #endif buffer = jack_port_get_buffer(self->ports[i], self->buffer_size); for (j = 0; j < self->buffer_size; j++) pkt_data[j * self->nports + i] = buffer[j]; From fbc6f190a61810a4f3c5181822c2da1027cda154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 28 Mar 2017 11:05:53 +0300 Subject: [PATCH 0113/2557] arm: Always build the hevcdsp_init_arm.c file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The main hevcdsp.c file calls this init function if HAVE_ARM is set, regardless of whether neon support is available or not. This fixes builds where neon isn't supported by the build tools at all. Signed-off-by: Martin Storsjö --- libavcodec/arm/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile index 555de160e4f45..b48745ad40aca 100644 --- a/libavcodec/arm/Makefile +++ b/libavcodec/arm/Makefile @@ -41,6 +41,7 @@ OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_init_arm.o \ arm/sbrdsp_init_arm.o OBJS-$(CONFIG_APE_DECODER) += arm/apedsp_init_arm.o OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_init_arm.o +OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_arm.o OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_init_arm.o OBJS-$(CONFIG_RV40_DECODER) += arm/rv40dsp_init_arm.o OBJS-$(CONFIG_VORBIS_DECODER) += arm/vorbisdsp_init_arm.o @@ -134,8 +135,7 @@ NEON-OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_neon.o \ NEON-OBJS-$(CONFIG_APE_DECODER) += arm/apedsp_neon.o NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_neon.o \ arm/synth_filter_neon.o -NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevc_idct.o \ - arm/hevcdsp_init_arm.o +NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevc_idct.o NEON-OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_neon.o NEON-OBJS-$(CONFIG_RV40_DECODER) += arm/rv34dsp_neon.o \ arm/rv40dsp_neon.o From e788ca05a796c97b84758189c83183f5ffa808f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 28 Mar 2017 12:53:58 +0300 Subject: [PATCH 0114/2557] hevcdec: Use LOCAL_ALIGNED_* for declaring local variables with alignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not all compilers can do alignment larger than the normal stack alignment for variables on the stack. In these cases, the LOCAL_ALIGNED_* macros produce the workaround alignment wrapper consisting of a padded array and a pointer variable. This fixes the hevc fate tests on RVCT/ARMCC after adding IDCT assembly that actually assumes/relies on this alignment. Signed-off-by: Martin Storsjö --- libavcodec/hevcdec.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index e24ce1e3c092f..6a04858587f90 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -917,8 +917,8 @@ static void hls_residual_coding(HEVCContext *s, int x0, int y0, int vshift = s->ps.sps->vshift[c_idx]; uint8_t *dst = &s->frame->data[c_idx][(y0 >> vshift) * stride + ((x0 >> hshift) << s->ps.sps->pixel_shift)]; - DECLARE_ALIGNED(32, int16_t, coeffs[MAX_TB_SIZE * MAX_TB_SIZE]) = { 0 }; - DECLARE_ALIGNED(8, uint8_t, significant_coeff_group_flag[8][8]) = { { 0 } }; + LOCAL_ALIGNED_32(int16_t, coeffs, [MAX_TB_SIZE * MAX_TB_SIZE]); + LOCAL_ALIGNED_8(uint8_t, significant_coeff_group_flag, [8], [8]); int trafo_size = 1 << log2_trafo_size; int i, qp, shift, add, scale, scale_m; @@ -926,6 +926,8 @@ static void hls_residual_coding(HEVCContext *s, int x0, int y0, const uint8_t *scale_matrix; uint8_t dc_scale; + memset(coeffs, 0, sizeof(int16_t) * MAX_TB_SIZE * MAX_TB_SIZE); + memset(significant_coeff_group_flag, 0, sizeof(uint8_t) * 8 * 8); // Derive QP for dequant if (!lc->cu.cu_transquant_bypass_flag) { static const int qp_c[] = { @@ -1755,8 +1757,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, } if (current_mv.pred_flag[0] && !current_mv.pred_flag[1]) { - DECLARE_ALIGNED(16, int16_t, tmp[MAX_PB_SIZE * MAX_PB_SIZE]); - DECLARE_ALIGNED(16, int16_t, tmp2[MAX_PB_SIZE * MAX_PB_SIZE]); + LOCAL_ALIGNED_16(int16_t, tmp, [MAX_PB_SIZE * MAX_PB_SIZE]); + LOCAL_ALIGNED_16(int16_t, tmp2, [MAX_PB_SIZE * MAX_PB_SIZE]); luma_mc(s, tmp, tmpstride, ref0->frame, ¤t_mv.mv[0], x0, y0, nPbW, nPbH, pred_idx); @@ -1789,8 +1791,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, s->hevcdsp.put_unweighted_pred_chroma[pred_idx](dst2, s->frame->linesize[2], tmp2, tmpstride, nPbH / 2); } } else if (!current_mv.pred_flag[0] && current_mv.pred_flag[1]) { - DECLARE_ALIGNED(16, int16_t, tmp [MAX_PB_SIZE * MAX_PB_SIZE]); - DECLARE_ALIGNED(16, int16_t, tmp2[MAX_PB_SIZE * MAX_PB_SIZE]); + LOCAL_ALIGNED_16(int16_t, tmp, [MAX_PB_SIZE * MAX_PB_SIZE]); + LOCAL_ALIGNED_16(int16_t, tmp2, [MAX_PB_SIZE * MAX_PB_SIZE]); luma_mc(s, tmp, tmpstride, ref1->frame, ¤t_mv.mv[1], x0, y0, nPbW, nPbH, pred_idx); @@ -1822,10 +1824,10 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, s->hevcdsp.put_unweighted_pred_chroma[pred_idx](dst2, s->frame->linesize[2], tmp2, tmpstride, nPbH / 2); } } else if (current_mv.pred_flag[0] && current_mv.pred_flag[1]) { - DECLARE_ALIGNED(16, int16_t, tmp [MAX_PB_SIZE * MAX_PB_SIZE]); - DECLARE_ALIGNED(16, int16_t, tmp2[MAX_PB_SIZE * MAX_PB_SIZE]); - DECLARE_ALIGNED(16, int16_t, tmp3[MAX_PB_SIZE * MAX_PB_SIZE]); - DECLARE_ALIGNED(16, int16_t, tmp4[MAX_PB_SIZE * MAX_PB_SIZE]); + LOCAL_ALIGNED_16(int16_t, tmp, [MAX_PB_SIZE * MAX_PB_SIZE]); + LOCAL_ALIGNED_16(int16_t, tmp2, [MAX_PB_SIZE * MAX_PB_SIZE]); + LOCAL_ALIGNED_16(int16_t, tmp3, [MAX_PB_SIZE * MAX_PB_SIZE]); + LOCAL_ALIGNED_16(int16_t, tmp4, [MAX_PB_SIZE * MAX_PB_SIZE]); luma_mc(s, tmp, tmpstride, ref0->frame, ¤t_mv.mv[0], x0, y0, nPbW, nPbH, pred_idx); From 6a9e331d79f8f78ba7642004ac13d744d033b98e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 29 Mar 2017 12:04:46 +0200 Subject: [PATCH 0115/2557] dcadec: remove extra indirection num_core_channels is always equal to s->audio_header.prim_channels, neither one of those variables ever get changed. Signed-off-by: Luca Barbato --- libavcodec/dcadec.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c index fa2a2400feaa1..ed1ed2d5f338d 100644 --- a/libavcodec/dcadec.c +++ b/libavcodec/dcadec.c @@ -1263,9 +1263,10 @@ static int scan_for_extensions(AVCodecContext *avctx) return ret; } -static int set_channel_layout(AVCodecContext *avctx, int channels, int num_core_channels) +static int set_channel_layout(AVCodecContext *avctx, int channels) { DCAContext *s = avctx->priv_data; + int num_core_channels = s->audio_header.prim_channels; int i; if (s->amode < 16) { @@ -1372,7 +1373,6 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, int buf_size = avpkt->size; int lfe_samples; - int num_core_channels = 0; int i, ret; float **samples_flt; DCAContext *s = avctx->priv_data; @@ -1406,9 +1406,6 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, } } - /* record number of core channels incase less than max channels are requested */ - num_core_channels = s->audio_header.prim_channels; - if (s->ext_coding) s->core_ext_mask = dca_ext_audio_descr_mask[s->ext_descr]; else @@ -1420,7 +1417,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, full_channels = channels = s->audio_header.prim_channels + !!s->lfe; - ret = set_channel_layout(avctx, channels, num_core_channels); + ret = set_channel_layout(avctx, channels); if (ret < 0) return ret; avctx->channels = channels; From 163cc67beb3ed28aeb500c9a09df47c8df613025 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 24 Mar 2017 17:35:06 +0100 Subject: [PATCH 0116/2557] takdec: Use ISO C printf conversion specifiers where appropriate libavformat/takdec.c:144:20: warning: format '%X' expects argument of type 'unsigned int', but argument 4 has type 'uint32_t' --- libavformat/takdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/takdec.c b/libavformat/takdec.c index 4b3037d9ca8e3..b3739e446e637 100644 --- a/libavformat/takdec.c +++ b/libavformat/takdec.c @@ -140,7 +140,7 @@ static int tak_read_header(AVFormatContext *s) bitstream_read(&bc, TAK_LAST_FRAME_SIZE_BITS); av_freep(&buffer); } else if (type == TAK_METADATA_ENCODER) { - av_log(s, AV_LOG_VERBOSE, "encoder version: %0X\n", + av_log(s, AV_LOG_VERBOSE, "encoder version: %0"PRIX32"\n", bitstream_read(&bc, TAK_ENCODER_VERSION_BITS)); av_freep(&buffer); } From 26d9b60373bf45bc4f91ff6815f5fa36764d4d7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 29 Mar 2017 13:43:40 +0300 Subject: [PATCH 0117/2557] hevc: Avoid using LOCAL_ALIGNED for 4 byte alignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The data types within the MvField struct themselves imply 4 byte alignment. Signed-off-by: Martin Storsjö --- libavcodec/hevc_mvs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/hevc_mvs.c b/libavcodec/hevc_mvs.c index be32e6cd40f58..27df7c1527649 100644 --- a/libavcodec/hevc_mvs.c +++ b/libavcodec/hevc_mvs.c @@ -550,7 +550,7 @@ void ff_hevc_luma_mv_merge_mode(HEVCContext *s, int x0, int y0, int nPbW, { int singleMCLFlag = 0; int nCS = 1 << log2_cb_size; - LOCAL_ALIGNED(4, MvField, mergecand_list, [MRG_MAX_NUM_CANDS]); + MvField mergecand_list[MRG_MAX_NUM_CANDS]; int nPbW2 = nPbW; int nPbH2 = nPbH; HEVCLocalContext *lc = &s->HEVClc; From 10f4511f14a4e830c0ed471df4cd1cc2a18a481a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 29 Mar 2017 13:44:28 +0300 Subject: [PATCH 0118/2557] libavutil: Make LOCAL_ALIGNED(xx be equal to LOCAL_ALIGNED_xx( MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the former form always produced a manually aligned, padded buffer, while the latter can use DECLARE_ALIGNED, if that amount of stack alignment is supported. libavutil/internal.h needs to include mem.h, since it uses the DECLARE_ALIGNED macro. Signed-off-by: Martin Storsjö --- libavutil/internal.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavutil/internal.h b/libavutil/internal.h index d96762c75db8a..8a0076f985058 100644 --- a/libavutil/internal.h +++ b/libavutil/internal.h @@ -38,6 +38,7 @@ #include "attributes.h" #include "dict.h" #include "macros.h" +#include "mem.h" #include "pixfmt.h" #if ARCH_X86 @@ -97,24 +98,24 @@ DECLARE_ALIGNED(a, t, la_##v) s o; \ t (*v) o = la_##v -#define LOCAL_ALIGNED(a, t, v, ...) E1(LOCAL_ALIGNED_A(a, t, v, __VA_ARGS__,,)) +#define LOCAL_ALIGNED(a, t, v, ...) LOCAL_ALIGNED_##a(t, v, __VA_ARGS__) #if HAVE_LOCAL_ALIGNED_8 # define LOCAL_ALIGNED_8(t, v, ...) E1(LOCAL_ALIGNED_D(8, t, v, __VA_ARGS__,,)) #else -# define LOCAL_ALIGNED_8(t, v, ...) LOCAL_ALIGNED(8, t, v, __VA_ARGS__) +# define LOCAL_ALIGNED_8(t, v, ...) E1(LOCAL_ALIGNED_A(8, t, v, __VA_ARGS__,,)) #endif #if HAVE_LOCAL_ALIGNED_16 # define LOCAL_ALIGNED_16(t, v, ...) E1(LOCAL_ALIGNED_D(16, t, v, __VA_ARGS__,,)) #else -# define LOCAL_ALIGNED_16(t, v, ...) LOCAL_ALIGNED(16, t, v, __VA_ARGS__) +# define LOCAL_ALIGNED_16(t, v, ...) E1(LOCAL_ALIGNED_A(16, t, v, __VA_ARGS__,,)) #endif #if HAVE_LOCAL_ALIGNED_32 # define LOCAL_ALIGNED_32(t, v, ...) E1(LOCAL_ALIGNED_D(32, t, v, __VA_ARGS__,,)) #else -# define LOCAL_ALIGNED_32(t, v, ...) LOCAL_ALIGNED(32, t, v, __VA_ARGS__) +# define LOCAL_ALIGNED_32(t, v, ...) E1(LOCAL_ALIGNED_A(32, t, v, __VA_ARGS__,,)) #endif #define FF_ALLOC_OR_GOTO(ctx, p, size, label)\ From c2bebfc8012821a2a22b64cae9e3cdea0f15792c Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 30 Mar 2017 22:58:59 +0100 Subject: [PATCH 0119/2557] pthread_frame: Propagate sw_pix_fmt across threads --- libavcodec/pthread_frame.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 6d14a878a442d..a72391ba36749 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -229,6 +229,7 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, dst->width = src->width; dst->height = src->height; dst->pix_fmt = src->pix_fmt; + dst->sw_pix_fmt = src->sw_pix_fmt; dst->coded_width = src->coded_width; dst->coded_height = src->coded_height; From 9aa251c98ce60e5ee83156e5292547a7671ced3a Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 27 Feb 2017 21:29:46 +0000 Subject: [PATCH 0120/2557] vf_deinterlace_vaapi: Add support for field rate output In order to work correctly with the i965 driver, this also fixes the direction of forward/backward references - forward references are intended to be those from the past to the current frame, not from the current frame to the future. --- libavfilter/vf_deinterlace_vaapi.c | 283 +++++++++++++++++------------ 1 file changed, 166 insertions(+), 117 deletions(-) diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c index ab2a43291454f..f3afcc4f754ae 100644 --- a/libavfilter/vf_deinterlace_vaapi.c +++ b/libavfilter/vf_deinterlace_vaapi.c @@ -22,6 +22,7 @@ #include #include "libavutil/avassert.h" +#include "libavutil/common.h" #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_vaapi.h" #include "libavutil/mem.h" @@ -42,6 +43,8 @@ typedef struct DeintVAAPIContext { AVBufferRef *device_ref; int mode; + int field_rate; + int auto_enable; int valid_ids; VAConfigID va_config; @@ -63,6 +66,7 @@ typedef struct DeintVAAPIContext { int queue_depth; int queue_count; AVFrame *frame_queue[MAX_REFERENCES]; + int extra_delay_for_timestamps; VABufferID filter_buffer; } DeintVAAPIContext; @@ -208,8 +212,12 @@ static int deint_vaapi_build_filter_params(AVFilterContext *avctx) return AVERROR(EIO); } + ctx->extra_delay_for_timestamps = ctx->field_rate == 2 && + ctx->pipeline_caps.num_backward_references == 0; + ctx->queue_depth = ctx->pipeline_caps.num_backward_references + - ctx->pipeline_caps.num_forward_references + 1; + ctx->pipeline_caps.num_forward_references + + ctx->extra_delay_for_timestamps + 1; if (ctx->queue_depth > MAX_REFERENCES) { av_log(avctx, AV_LOG_ERROR, "Pipeline requires too many " "references (%u forward, %u back).\n", @@ -224,6 +232,7 @@ static int deint_vaapi_build_filter_params(AVFilterContext *avctx) static int deint_vaapi_config_output(AVFilterLink *outlink) { AVFilterContext *avctx = outlink->src; + AVFilterLink *inlink = avctx->inputs[0]; DeintVAAPIContext *ctx = avctx->priv; AVVAAPIHWConfig *hwconfig = NULL; AVHWFramesConstraints *constraints = NULL; @@ -323,8 +332,13 @@ static int deint_vaapi_config_output(AVFilterLink *outlink) if (err < 0) goto fail; - outlink->w = ctx->output_width; - outlink->h = ctx->output_height; + outlink->w = inlink->w; + outlink->h = inlink->h; + + outlink->time_base = av_mul_q(inlink->time_base, + (AVRational) { 1, ctx->field_rate }); + outlink->frame_rate = av_mul_q(inlink->frame_rate, + (AVRational) { ctx->field_rate, 1 }); outlink->hw_frames_ctx = av_buffer_ref(ctx->output_frames_ref); if (!outlink->hw_frames_ctx) { @@ -372,7 +386,7 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) VABufferID params_id; VAStatus vas; void *filter_params_addr = NULL; - int err, i; + int err, i, field, current_frame_index; av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", av_get_pix_fmt_name(input_frame->format), @@ -391,17 +405,16 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) ctx->frame_queue[i] = input_frame; } - input_frame = - ctx->frame_queue[ctx->pipeline_caps.num_backward_references]; + current_frame_index = ctx->pipeline_caps.num_forward_references; + + input_frame = ctx->frame_queue[current_frame_index]; input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3]; - for (i = 0; i < ctx->pipeline_caps.num_backward_references; i++) - backward_references[i] = (VASurfaceID)(uintptr_t) - ctx->frame_queue[ctx->pipeline_caps.num_backward_references - - i - 1]->data[3]; for (i = 0; i < ctx->pipeline_caps.num_forward_references; i++) forward_references[i] = (VASurfaceID)(uintptr_t) - ctx->frame_queue[ctx->pipeline_caps.num_backward_references + - i + 1]->data[3]; + ctx->frame_queue[current_frame_index - i - 1]->data[3]; + for (i = 0; i < ctx->pipeline_caps.num_backward_references; i++) + backward_references[i] = (VASurfaceID)(uintptr_t) + ctx->frame_queue[current_frame_index + i + 1]->data[3]; av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for " "deinterlace input.\n", input_surface); @@ -414,123 +427,148 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) av_log(avctx, AV_LOG_DEBUG, " %#x", forward_references[i]); av_log(avctx, AV_LOG_DEBUG, "\n"); - output_frame = ff_get_video_buffer(outlink, ctx->output_width, - ctx->output_height); - if (!output_frame) { - err = AVERROR(ENOMEM); - goto fail; - } - - output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3]; - av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for " - "deinterlace output.\n", output_surface); - - memset(¶ms, 0, sizeof(params)); - - input_region = (VARectangle) { - .x = 0, - .y = 0, - .width = input_frame->width, - .height = input_frame->height, - }; + for (field = 0; field < ctx->field_rate; field++) { + output_frame = ff_get_video_buffer(outlink, ctx->output_width, + ctx->output_height); + if (!output_frame) { + err = AVERROR(ENOMEM); + goto fail; + } - params.surface = input_surface; - params.surface_region = &input_region; - params.surface_color_standard = - vaapi_proc_colour_standard(input_frame->colorspace); + output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3]; + av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for " + "deinterlace output.\n", output_surface); + + memset(¶ms, 0, sizeof(params)); + + input_region = (VARectangle) { + .x = 0, + .y = 0, + .width = input_frame->width, + .height = input_frame->height, + }; + + params.surface = input_surface; + params.surface_region = &input_region; + params.surface_color_standard = + vaapi_proc_colour_standard(input_frame->colorspace); + + params.output_region = NULL; + params.output_background_color = 0xff000000; + params.output_color_standard = params.surface_color_standard; + + params.pipeline_flags = 0; + params.filter_flags = VA_FRAME_PICTURE; + + if (!ctx->auto_enable || input_frame->interlaced_frame) { + vas = vaMapBuffer(ctx->hwctx->display, ctx->filter_buffer, + &filter_params_addr); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to map filter parameter " + "buffer: %d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + filter_params = filter_params_addr; + filter_params->flags = 0; + if (input_frame->top_field_first) { + filter_params->flags |= field ? VA_DEINTERLACING_BOTTOM_FIELD : 0; + } else { + filter_params->flags |= VA_DEINTERLACING_BOTTOM_FIELD_FIRST; + filter_params->flags |= field ? 0 : VA_DEINTERLACING_BOTTOM_FIELD; + } + filter_params_addr = NULL; + vas = vaUnmapBuffer(ctx->hwctx->display, ctx->filter_buffer); + if (vas != VA_STATUS_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to unmap filter parameter " + "buffer: %d (%s).\n", vas, vaErrorStr(vas)); + + params.filters = &ctx->filter_buffer; + params.num_filters = 1; + + params.forward_references = forward_references; + params.num_forward_references = + ctx->pipeline_caps.num_forward_references; + params.backward_references = backward_references; + params.num_backward_references = + ctx->pipeline_caps.num_backward_references; + + } else { + params.filters = NULL; + params.num_filters = 0; + } - params.output_region = NULL; - params.output_background_color = 0xff000000; - params.output_color_standard = params.surface_color_standard; + vas = vaBeginPicture(ctx->hwctx->display, + ctx->va_context, output_surface); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to attach new picture: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } - params.pipeline_flags = 0; - params.filter_flags = VA_FRAME_PICTURE; + vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, + VAProcPipelineParameterBufferType, + sizeof(params), 1, ¶ms, ¶ms_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail_after_begin; + } + av_log(avctx, AV_LOG_DEBUG, "Pipeline parameter buffer is %#x.\n", + params_id); - vas = vaMapBuffer(ctx->hwctx->display, ctx->filter_buffer, - &filter_params_addr); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to map filter parameter " - "buffer: %d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail; - } - filter_params = filter_params_addr; - filter_params->flags = 0; - if (input_frame->interlaced_frame && !input_frame->top_field_first) - filter_params->flags |= VA_DEINTERLACING_BOTTOM_FIELD_FIRST; - filter_params_addr = NULL; - vas = vaUnmapBuffer(ctx->hwctx->display, ctx->filter_buffer); - if (vas != VA_STATUS_SUCCESS) - av_log(avctx, AV_LOG_ERROR, "Failed to unmap filter parameter " - "buffer: %d (%s).\n", vas, vaErrorStr(vas)); - - params.filters = &ctx->filter_buffer; - params.num_filters = 1; - - params.forward_references = forward_references; - params.num_forward_references = - ctx->pipeline_caps.num_forward_references; - params.backward_references = backward_references; - params.num_backward_references = - ctx->pipeline_caps.num_backward_references; - - vas = vaBeginPicture(ctx->hwctx->display, - ctx->va_context, output_surface); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to attach new picture: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail; - } + vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, + ¶ms_id, 1); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to render parameter buffer: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail_after_begin; + } - vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, - VAProcPipelineParameterBufferType, - sizeof(params), 1, ¶ms, ¶ms_id); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_begin; - } - av_log(avctx, AV_LOG_DEBUG, "Pipeline parameter buffer is %#x.\n", - params_id); + vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to start picture processing: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail_after_render; + } - vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, - ¶ms_id, 1); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to render parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_begin; - } + if (ctx->hwctx->driver_quirks & + AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) { + vas = vaDestroyBuffer(ctx->hwctx->display, params_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to free parameter buffer: " + "%d (%s).\n", vas, vaErrorStr(vas)); + // And ignore. + } + } - vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to start picture processing: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_render; - } + err = av_frame_copy_props(output_frame, input_frame); + if (err < 0) + goto fail; - if (ctx->hwctx->driver_quirks & - AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) { - vas = vaDestroyBuffer(ctx->hwctx->display, params_id); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to free parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - // And ignore. + if (ctx->field_rate == 2) { + if (field == 0) + output_frame->pts = 2 * input_frame->pts; + else + output_frame->pts = input_frame->pts + + ctx->frame_queue[current_frame_index + 1]->pts; } - } + output_frame->interlaced_frame = 0; - err = av_frame_copy_props(output_frame, input_frame); - if (err < 0) - goto fail; + av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(output_frame->format), + output_frame->width, output_frame->height, output_frame->pts); - av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", - av_get_pix_fmt_name(output_frame->format), - output_frame->width, output_frame->height, output_frame->pts); + err = ff_filter_frame(outlink, output_frame); + if (err < 0) + break; + } - return ff_filter_frame(outlink, output_frame); + return err; fail_after_begin: vaRenderPicture(ctx->hwctx->display, ctx->va_context, ¶ms_id, 1); @@ -583,6 +621,17 @@ static const AVOption deint_vaapi_options[] = { 0, AV_OPT_TYPE_CONST, { .i64 = VAProcDeinterlacingMotionAdaptive }, .unit = "mode" }, { "motion_compensated", "Use the motion compensated deinterlacing algorithm", 0, AV_OPT_TYPE_CONST, { .i64 = VAProcDeinterlacingMotionCompensated }, .unit = "mode" }, + + { "rate", "Generate output at frame rate or field rate", + OFFSET(field_rate), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 2, FLAGS, "rate" }, + { "frame", "Output at frame rate (one frame of output for each field-pair)", + 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .unit = "rate" }, + { "field", "Output at field rate (one frame of output for each field)", + 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, .unit = "rate" }, + + { "auto", "Only deinterlace fields, passing frames through unchanged", + OFFSET(auto_enable), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, + { NULL }, }; From f64d1100a54d12c78ce436181bb64229c56da6b3 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 14 Mar 2017 00:39:57 +0000 Subject: [PATCH 0121/2557] avconv: Flush output BSFs when encode reaches EOF Before this, output bitstream filters would never see EOF and therefore would not be able to flush any delayed packets. --- avtools/avconv.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/avtools/avconv.c b/avtools/avconv.c index 3f5806788eb50..2e218e96c75cb 100644 --- a/avtools/avconv.c +++ b/avtools/avconv.c @@ -359,7 +359,8 @@ static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) } } -static void output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) +static void output_packet(OutputFile *of, AVPacket *pkt, + OutputStream *ost, int eof) { int ret = 0; @@ -367,10 +368,11 @@ static void output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) if (ost->nb_bitstream_filters) { int idx; - ret = av_bsf_send_packet(ost->bsf_ctx[0], pkt); + ret = av_bsf_send_packet(ost->bsf_ctx[0], eof ? NULL : pkt); if (ret < 0) goto finish; + eof = 0; idx = 1; while (idx) { /* get a packet from the previous filter up the chain */ @@ -379,19 +381,24 @@ static void output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) ret = 0; idx--; continue; + } else if (ret == AVERROR_EOF) { + eof = 1; } else if (ret < 0) goto finish; /* send it to the next filter down the chain or to the muxer */ if (idx < ost->nb_bitstream_filters) { - ret = av_bsf_send_packet(ost->bsf_ctx[idx], pkt); + ret = av_bsf_send_packet(ost->bsf_ctx[idx], eof ? NULL : pkt); if (ret < 0) goto finish; idx++; - } else + eof = 0; + } else if (eof) + goto finish; + else write_packet(of, pkt, ost); } - } else + } else if (!eof) write_packet(of, pkt, ost); finish: @@ -444,7 +451,7 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, if (ret < 0) goto error; - output_packet(of, &pkt, ost); + output_packet(of, &pkt, ost, 0); } return; @@ -518,7 +525,7 @@ static void do_subtitle_out(OutputFile *of, else pkt.pts += 90 * sub->end_display_time; } - output_packet(of, &pkt, ost); + output_packet(of, &pkt, ost, 0); } } @@ -594,7 +601,7 @@ static void do_video_out(OutputFile *of, if (ret < 0) goto error; - output_packet(of, &pkt, ost); + output_packet(of, &pkt, ost, 0); *frame_size = pkt.size; /* if two pass, output log */ @@ -1082,11 +1089,11 @@ static void flush_encoders(void) if (ost->logfile && enc->stats_out) { fprintf(ost->logfile, "%s", enc->stats_out); } + output_packet(of, &pkt, ost, ret == AVERROR_EOF); if (ret == AVERROR_EOF) { stop_encoding = 1; break; } - output_packet(of, &pkt, ost); } if (stop_encoding) @@ -1179,7 +1186,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt.size = pkt->size; } - output_packet(of, &opkt, ost); + output_packet(of, &opkt, ost, 0); } static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) From 0cf949a01193dcf6f83fd95d46792dd94479b4e4 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Mon, 29 Feb 2016 09:43:07 -0500 Subject: [PATCH 0122/2557] vp9: Add bsf to merge superframes From ffmpeg commit 2e6636aa87303d37b112e79f093ca39500f92364. --- Changelog | 1 + doc/bitstream_filters.texi | 4 + libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/vp9_superframe_bsf.c | 207 ++++++++++++++++++++++++++++++++ 5 files changed, 214 insertions(+) create mode 100644 libavcodec/vp9_superframe_bsf.c diff --git a/Changelog b/Changelog index 04972399fd095..b3aed3cd7e578 100644 --- a/Changelog +++ b/Changelog @@ -12,6 +12,7 @@ version : - The x86 assembler default switched from yasm to nasm, pass --x86asmexe=yasm to configure to restore the old behavior. - Cineform HD decoder +- VP9 superframe split/merge bitstream filters version 12: diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 49b8a645d0bb6..ddadd7653e376 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -95,6 +95,10 @@ This bitstream filter passes the packets through unchanged. @section remove_extradata +@section vp9_superframe + +Combine VP9 frames into superframes. + @section vp9_superframe_split Split VP9 superframes into single frames. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3a55a28e27b30..80c572c7c4090 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -772,6 +772,7 @@ OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o OBJS-$(CONFIG_NULL_BSF) += null_bsf.o OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o +OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF) += vp9_superframe_split_bsf.o # thread libraries diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 1cea6d77afe9a..d46fdad81b309 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -38,6 +38,7 @@ extern const AVBitStreamFilter ff_null_bsf; extern const AVBitStreamFilter ff_text2movsub_bsf; extern const AVBitStreamFilter ff_noise_bsf; extern const AVBitStreamFilter ff_remove_extradata_bsf; +extern const AVBitStreamFilter ff_vp9_superframe_bsf; extern const AVBitStreamFilter ff_vp9_superframe_split_bsf; #include "libavcodec/bsf_list.c" diff --git a/libavcodec/vp9_superframe_bsf.c b/libavcodec/vp9_superframe_bsf.c new file mode 100644 index 0000000000000..be83ba3e75be3 --- /dev/null +++ b/libavcodec/vp9_superframe_bsf.c @@ -0,0 +1,207 @@ +/* + * VP9 invisible (alt-ref) frame to superframe merge bitstream filter + * Copyright (c) 2016 Ronald S. Bultje + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "bsf.h" +#include "get_bits.h" + +#define MAX_CACHE 8 +typedef struct VP9BSFContext { + int n_cache; + struct CachedBuf { + uint8_t *data; + int size; + } cache[MAX_CACHE]; +} VP9BSFContext; + +static void stats(const struct CachedBuf *in, int n_in, + unsigned *_max, unsigned *_sum) +{ + int n; + unsigned max = 0, sum = 0; + + for (n = 0; n < n_in; n++) { + unsigned sz = in[n].size; + + if (sz > max) + max = sz; + sum += sz; + } + + *_max = max; + *_sum = sum; +} + +static int merge_superframe(const struct CachedBuf *in, int n_in, AVPacket *out) +{ + unsigned max, sum, mag, marker, n, sz; + uint8_t *ptr; + int res; + + stats(in, n_in, &max, &sum); + mag = av_log2(max) >> 3; + marker = 0xC0 + (mag << 3) + (n_in - 1); + sz = sum + 2 + (mag + 1) * n_in; + res = av_new_packet(out, sz); + if (res < 0) + return res; + ptr = out->data; + for (n = 0; n < n_in; n++) { + memcpy(ptr, in[n].data, in[n].size); + ptr += in[n].size; + } + +#define wloop(mag, wr) do { \ + for (n = 0; n < n_in; n++) { \ + wr; \ + ptr += mag + 1; \ + } \ + } while (0) + + // write superframe with marker 110[mag:2][nframes:3] + *ptr++ = marker; + switch (mag) { + case 0: + wloop(mag, *ptr = in[n].size); + break; + case 1: + wloop(mag, AV_WL16(ptr, in[n].size)); + break; + case 2: + wloop(mag, AV_WL24(ptr, in[n].size)); + break; + case 3: + wloop(mag, AV_WL32(ptr, in[n].size)); + break; + } + *ptr++ = marker; + av_assert0(ptr == &out->data[out->size]); + + return 0; +} + +static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out) +{ + GetBitContext gb; + VP9BSFContext *s = ctx->priv_data; + AVPacket *in; + int res, invisible, profile, marker, uses_superframe_syntax = 0, n; + + res = ff_bsf_get_packet(ctx, &in); + if (res < 0) + return res; + + marker = in->data[in->size - 1]; + if ((marker & 0xe0) == 0xc0) { + int nbytes = 1 + ((marker >> 3) & 0x3); + int n_frames = 1 + (marker & 0x7), idx_sz = 2 + n_frames * nbytes; + + uses_superframe_syntax = in->size >= idx_sz && in->data[in->size - idx_sz] == marker; + } + + if ((res = init_get_bits8(&gb, in->data, in->size)) < 0) + goto done; + + get_bits(&gb, 2); // frame marker + profile = get_bits1(&gb); + profile |= get_bits1(&gb) << 1; + if (profile == 3) profile += get_bits1(&gb); + + if (get_bits1(&gb)) { + invisible = 0; + } else { + get_bits1(&gb); // keyframe + invisible = !get_bits1(&gb); + } + + if (uses_superframe_syntax && s->n_cache > 0) { + av_log(ctx, AV_LOG_ERROR, + "Mixing of superframe syntax and naked VP9 frames not supported"); + res = AVERROR(ENOSYS); + goto done; + } else if ((!invisible || uses_superframe_syntax) && !s->n_cache) { + // passthrough + av_packet_move_ref(out, in); + goto done; + } else if (s->n_cache + 1 >= MAX_CACHE) { + av_log(ctx, AV_LOG_ERROR, + "Too many invisible frames"); + res = AVERROR_INVALIDDATA; + goto done; + } + + if (invisible) { + s->cache[s->n_cache].data = av_malloc(in->size); + if (!s->cache[s->n_cache].data) { + res = AVERROR(ENOMEM); + goto done; + } + memcpy(s->cache[s->n_cache].data, in->data, in->size); + s->cache[s->n_cache++].size = in->size; + res = AVERROR(EAGAIN); + goto done; + } + av_assert0(s->n_cache > 0); + + s->cache[s->n_cache].data = in->data; + s->cache[s->n_cache].size = in->size; + + // build superframe + if ((res = merge_superframe(s->cache, s->n_cache + 1, out)) < 0) + goto done; + + for (n = 0; n < s->n_cache; n++) + av_freep(&s->cache[n].data); + s->n_cache = 0; + + res = av_packet_copy_props(out, in); + if (res < 0) + goto done; + +done: + if (res < 0) + av_packet_unref(out); + av_packet_free(&in); + return res; +} + +static void vp9_superframe_close(AVBSFContext *ctx) +{ + VP9BSFContext *s = ctx->priv_data; + int n; + + // free cached data + for (n = 0; n < s->n_cache; n++) + av_freep(&s->cache[n].data); +} + +static const enum AVCodecID codec_ids[] = { + AV_CODEC_ID_VP9, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_vp9_superframe_bsf = { + .name = "vp9_superframe", + .priv_data_size = sizeof(VP9BSFContext), + .filter = vp9_superframe_filter, + .close = vp9_superframe_close, + .codec_ids = codec_ids, +}; From 34e051d16850701694410a0e72e0e4ff3a5ec293 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 9 Jan 2017 23:08:49 +0000 Subject: [PATCH 0123/2557] vp9: Add bsf to fix reordering in raw streams Takes a raw input stream containing frames with correct timestamps but possibly out of order and inserts additional show-existing-frame packets to correct the ordering. --- doc/bitstream_filters.texi | 5 + libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/vp9_raw_reorder_bsf.c | 411 +++++++++++++++++++++++++++++++ 4 files changed, 418 insertions(+) create mode 100644 libavcodec/vp9_raw_reorder_bsf.c diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index ddadd7653e376..64f91f4b5417b 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -103,4 +103,9 @@ Combine VP9 frames into superframes. Split VP9 superframes into single frames. +@section vp9_raw_reorder + +Given a VP9 stream with correct timestamps but possibly out of order, +insert additional show-existing-frame packets to correct the ordering. + @c man end BITSTREAM FILTERS diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 80c572c7c4090..674c8d0445988 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -772,6 +772,7 @@ OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o OBJS-$(CONFIG_NULL_BSF) += null_bsf.o OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o +OBJS-$(CONFIG_VP9_RAW_REORDER_BSF) += vp9_raw_reorder_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF) += vp9_superframe_split_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index d46fdad81b309..79ce40f9eda2a 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -38,6 +38,7 @@ extern const AVBitStreamFilter ff_null_bsf; extern const AVBitStreamFilter ff_text2movsub_bsf; extern const AVBitStreamFilter ff_noise_bsf; extern const AVBitStreamFilter ff_remove_extradata_bsf; +extern const AVBitStreamFilter ff_vp9_raw_reorder_bsf; extern const AVBitStreamFilter ff_vp9_superframe_bsf; extern const AVBitStreamFilter ff_vp9_superframe_split_bsf; diff --git a/libavcodec/vp9_raw_reorder_bsf.c b/libavcodec/vp9_raw_reorder_bsf.c new file mode 100644 index 0000000000000..7f00f5f10391d --- /dev/null +++ b/libavcodec/vp9_raw_reorder_bsf.c @@ -0,0 +1,411 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/intmath.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" + +#include "bitstream.h" +#include "bsf.h" +#include "put_bits.h" + +#define FRAME_SLOTS 8 + +typedef struct VP9RawReorderFrame { + AVPacket *packet; + int needs_output; + int needs_display; + + int64_t pts; + int64_t sequence; + unsigned int slots; + + unsigned int profile; + + unsigned int show_existing_frame; + unsigned int frame_to_show; + + unsigned int frame_type; + unsigned int show_frame; + unsigned int refresh_frame_flags; +} VP9RawReorderFrame; + +typedef struct VP9RawReorderContext { + int64_t sequence; + VP9RawReorderFrame *slot[FRAME_SLOTS]; + VP9RawReorderFrame *next_frame; +} VP9RawReorderContext; + +static void vp9_raw_reorder_frame_free(VP9RawReorderFrame **frame) +{ + if (*frame) + av_packet_free(&(*frame)->packet); + av_freep(frame); +} + +static void vp9_raw_reorder_clear_slot(VP9RawReorderContext *ctx, int s) +{ + if (ctx->slot[s]) { + ctx->slot[s]->slots &= ~(1 << s); + if (ctx->slot[s]->slots == 0) + vp9_raw_reorder_frame_free(&ctx->slot[s]); + else + ctx->slot[s] = NULL; + } +} + +static int vp9_raw_reorder_frame_parse(AVBSFContext *bsf, VP9RawReorderFrame *frame) +{ + BitstreamContext bc; + int err; + + unsigned int frame_marker; + unsigned int profile_low_bit, profile_high_bit, reserved_zero; + unsigned int error_resilient_mode; + unsigned int frame_sync_code; + + err = bitstream_init8(&bc, frame->packet->data, frame->packet->size); + if (err) + return err; + + frame_marker = bitstream_read(&bc, 2); + if (frame_marker != 2) { + av_log(bsf, AV_LOG_ERROR, "Invalid frame marker: %u.\n", + frame_marker); + return AVERROR_INVALIDDATA; + } + + profile_low_bit = bitstream_read_bit(&bc); + profile_high_bit = bitstream_read_bit(&bc); + frame->profile = (profile_high_bit << 1) | profile_low_bit; + if (frame->profile == 3) { + reserved_zero = bitstream_read_bit(&bc); + if (reserved_zero != 0) { + av_log(bsf, AV_LOG_ERROR, "Profile reserved_zero bit set: " + "unsupported profile or invalid bitstream.\n"); + return AVERROR_INVALIDDATA; + } + } + + frame->show_existing_frame = bitstream_read_bit(&bc); + if (frame->show_existing_frame) { + frame->frame_to_show = bitstream_read(&bc, 3); + return 0; + } + + frame->frame_type = bitstream_read_bit(&bc); + frame->show_frame = bitstream_read_bit(&bc); + error_resilient_mode = bitstream_read_bit(&bc); + + if (frame->frame_type == 0) { + frame_sync_code = bitstream_read(&bc, 24); + if (frame_sync_code != 0x498342) { + av_log(bsf, AV_LOG_ERROR, "Invalid frame sync code: %06x.\n", + frame_sync_code); + return AVERROR_INVALIDDATA; + } + frame->refresh_frame_flags = 0xff; + } else { + unsigned int intra_only; + + if (frame->show_frame == 0) + intra_only = bitstream_read_bit(&bc); + else + intra_only = 0; + if (error_resilient_mode == 0) { + // reset_frame_context + bitstream_skip(&bc, 2); + } + if (intra_only) { + frame_sync_code = bitstream_read(&bc, 24); + if (frame_sync_code != 0x498342) { + av_log(bsf, AV_LOG_ERROR, "Invalid frame sync code: " + "%06x.\n", frame_sync_code); + return AVERROR_INVALIDDATA; + } + if (frame->profile > 0) { + unsigned int color_space; + if (frame->profile >= 2) { + // ten_or_twelve_bit + bitstream_skip(&bc, 1); + } + color_space = bitstream_read(&bc, 3); + if (color_space != 7 /* CS_RGB */) { + // color_range + bitstream_skip(&bc, 1); + if (frame->profile == 1 || frame->profile == 3) { + // subsampling + bitstream_skip(&bc, 3); + } + } else { + if (frame->profile == 1 || frame->profile == 3) + bitstream_skip(&bc, 1); + } + } + frame->refresh_frame_flags = bitstream_read(&bc, 8); + } else { + frame->refresh_frame_flags = bitstream_read(&bc, 8); + } + } + + return 0; +} + +static int vp9_raw_reorder_make_output(AVBSFContext *bsf, + AVPacket *out, + VP9RawReorderFrame *last_frame) +{ + VP9RawReorderContext *ctx = bsf->priv_data; + VP9RawReorderFrame *next_output = last_frame, + *next_display = last_frame, *frame; + int s, err; + + for (s = 0; s < FRAME_SLOTS; s++) { + frame = ctx->slot[s]; + if (!frame) + continue; + if (frame->needs_output && (!next_output || + frame->sequence < next_output->sequence)) + next_output = frame; + if (frame->needs_display && (!next_display || + frame->pts < next_display->pts)) + next_display = frame; + } + + if (!next_output && !next_display) + return AVERROR_EOF; + + if (!next_display || (next_output && + next_output->sequence < next_display->sequence)) + frame = next_output; + else + frame = next_display; + + if (frame->needs_output && frame->needs_display && + next_output == next_display) { + av_log(bsf, AV_LOG_DEBUG, "Output and display frame " + "%"PRId64" (%"PRId64") in order.\n", + frame->sequence, frame->pts); + + av_packet_move_ref(out, frame->packet); + + frame->needs_output = frame->needs_display = 0; + } else if (frame->needs_output) { + if (frame->needs_display) { + av_log(bsf, AV_LOG_DEBUG, "Output frame %"PRId64" " + "(%"PRId64") for later display.\n", + frame->sequence, frame->pts); + } else { + av_log(bsf, AV_LOG_DEBUG, "Output unshown frame " + "%"PRId64" (%"PRId64") to keep order.\n", + frame->sequence, frame->pts); + } + + av_packet_move_ref(out, frame->packet); + out->pts = out->dts; + + frame->needs_output = 0; + } else { + PutBitContext pb; + + av_assert0(!frame->needs_output && frame->needs_display); + + if (frame->slots == 0) { + av_log(bsf, AV_LOG_ERROR, "Attempting to display frame " + "which is no longer available?\n"); + frame->needs_display = 0; + return AVERROR_INVALIDDATA; + } + + s = ff_ctz(frame->slots); + av_assert0(s < FRAME_SLOTS); + + av_log(bsf, AV_LOG_DEBUG, "Display frame %"PRId64" " + "(%"PRId64") from slot %d.\n", + frame->sequence, frame->pts, s); + + frame->packet = av_packet_alloc(); + if (!frame->packet) + return AVERROR(ENOMEM); + + err = av_new_packet(out, 2); + if (err < 0) + return err; + + init_put_bits(&pb, out->data, 2); + + // frame_marker + put_bits(&pb, 2, 2); + // profile_low_bit + put_bits(&pb, 1, frame->profile & 1); + // profile_high_bit + put_bits(&pb, 1, (frame->profile >> 1) & 1); + if (frame->profile == 3) { + // reserved_zero + put_bits(&pb, 1, 0); + } + // show_existing_frame + put_bits(&pb, 1, 1); + // frame_to_show_map_idx + put_bits(&pb, 3, s); + + while (put_bits_count(&pb) < 16) + put_bits(&pb, 1, 0); + + flush_put_bits(&pb); + out->pts = out->dts = frame->pts; + + frame->needs_display = 0; + } + + return 0; +} + +static int vp9_raw_reorder_filter(AVBSFContext *bsf, AVPacket *out) +{ + VP9RawReorderContext *ctx = bsf->priv_data; + VP9RawReorderFrame *frame; + AVPacket *in; + int err, s; + + if (ctx->next_frame) { + frame = ctx->next_frame; + + } else { + err = ff_bsf_get_packet(bsf, &in); + if (err < 0) { + if (err == AVERROR_EOF) + return vp9_raw_reorder_make_output(bsf, out, NULL); + return err; + } + + if (in->data[in->size - 1] & 0xe0 == 0xc0) { + av_log(bsf, AV_LOG_ERROR, "Input in superframes is not " + "supported.\n"); + av_packet_free(&in); + return AVERROR(ENOSYS); + } + + frame = av_mallocz(sizeof(*frame)); + if (!frame) { + av_packet_free(&in); + return AVERROR(ENOMEM); + } + + frame->packet = in; + frame->pts = in->pts; + frame->sequence = ++ctx->sequence; + err = vp9_raw_reorder_frame_parse(bsf, frame); + if (err) { + av_log(bsf, AV_LOG_ERROR, "Failed to parse input " + "frame: %d.\n", err); + goto fail; + } + + frame->needs_output = 1; + frame->needs_display = frame->pts != AV_NOPTS_VALUE; + + if (frame->show_existing_frame) + av_log(bsf, AV_LOG_DEBUG, "Show frame %"PRId64" " + "(%"PRId64"): show %u.\n", frame->sequence, + frame->pts, frame->frame_to_show); + else + av_log(bsf, AV_LOG_DEBUG, "New frame %"PRId64" " + "(%"PRId64"): type %u show %u refresh %02x.\n", + frame->sequence, frame->pts, frame->frame_type, + frame->show_frame, frame->refresh_frame_flags); + + ctx->next_frame = frame; + } + + for (s = 0; s < FRAME_SLOTS; s++) { + if (!(frame->refresh_frame_flags & (1 << s))) + continue; + if (ctx->slot[s] && ctx->slot[s]->needs_display && + ctx->slot[s]->slots == (1 << s)) { + // We are overwriting this slot, which is last reference + // to the frame previously present in it. In order to be + // a valid stream, that frame must already have been + // displayed before the pts of the current frame. + err = vp9_raw_reorder_make_output(bsf, out, ctx->slot[s]); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to create " + "output overwriting slot %d: %d.\n", + s, err); + // Clear the slot anyway, so we don't end up + // in an infinite loop. + vp9_raw_reorder_clear_slot(ctx, s); + return AVERROR_INVALIDDATA; + } + return 0; + } + vp9_raw_reorder_clear_slot(ctx, s); + } + + for (s = 0; s < FRAME_SLOTS; s++) { + if (!(frame->refresh_frame_flags & (1 << s))) + continue; + ctx->slot[s] = frame; + } + frame->slots = frame->refresh_frame_flags; + + if (!frame->refresh_frame_flags) { + err = vp9_raw_reorder_make_output(bsf, out, frame); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to create output " + "for transient frame.\n"); + ctx->next_frame = NULL; + return AVERROR_INVALIDDATA; + } + if (!frame->needs_display) { + vp9_raw_reorder_frame_free(&frame); + ctx->next_frame = NULL; + } + return 0; + } + + ctx->next_frame = NULL; + return AVERROR(EAGAIN); + +fail: + vp9_raw_reorder_frame_free(&frame); + return err; +} + +static void vp9_raw_reorder_close(AVBSFContext *bsf) +{ + VP9RawReorderContext *ctx = bsf->priv_data; + int s; + + for (s = 0; s < FRAME_SLOTS; s++) + vp9_raw_reorder_clear_slot(ctx, s); +} + +static const enum AVCodecID vp9_raw_reorder_codec_ids[] = { + AV_CODEC_ID_VP9, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_vp9_raw_reorder_bsf = { + .name = "vp9_raw_reorder", + .priv_data_size = sizeof(VP9RawReorderContext), + .close = &vp9_raw_reorder_close, + .filter = &vp9_raw_reorder_filter, + .codec_ids = vp9_raw_reorder_codec_ids, +}; From 0fd91e4bfc00a6609b59d1ce3a9f152184e62601 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 28 Nov 2016 23:54:57 +0000 Subject: [PATCH 0124/2557] vaapi_encode: Add VP9 support --- configure | 3 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/vaapi_encode_vp9.c | 311 ++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 5 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 libavcodec/vaapi_encode_vp9.c diff --git a/configure b/configure index f1488cf4943aa..30eba73c2168e 100755 --- a/configure +++ b/configure @@ -2273,6 +2273,8 @@ vp8_qsv_decoder_deps="libmfx" vp8_qsv_decoder_select="qsvdec vp8_qsv_hwaccel vp8_parser" vp8_vaapi_encoder_deps="VAEncPictureParameterBufferVP8" vp8_vaapi_encoder_select="vaapi_encode" +vp9_vaapi_encoder_deps="VAEncPictureParameterBufferVP9" +vp9_vaapi_encoder_select="vaapi_encode" nvenc_h264_encoder_select="h264_nvenc_encoder" nvenc_hevc_encoder_select="hevc_nvenc_encoder" @@ -4666,6 +4668,7 @@ check_type "va/va.h va/va_enc_hevc.h" "VAEncPictureParameterBufferHEVC" check_type "va/va.h va/va_enc_jpeg.h" "VAEncPictureParameterBufferJPEG" check_type "va/va.h va/va_enc_mpeg2.h" "VAEncPictureParameterBufferMPEG2" check_type "va/va.h va/va_enc_vp8.h" "VAEncPictureParameterBufferVP8" +check_type "va/va.h va/va_enc_vp9.h" "VAEncPictureParameterBufferVP9" check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 674c8d0445988..ec62f514a77db 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -485,6 +485,7 @@ OBJS-$(CONFIG_VP8_QSV_DECODER) += qsvdec_other.o OBJS-$(CONFIG_VP8_VAAPI_ENCODER) += vaapi_encode_vp8.o OBJS-$(CONFIG_VP9_DECODER) += vp9.o vp9data.o vp9dsp.o \ vp9block.o vp9prob.o vp9mvs.o vp56rac.o +OBJS-$(CONFIG_VP9_VAAPI_ENCODER) += vaapi_encode_vp9.o OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o OBJS-$(CONFIG_WEBP_DECODER) += webp.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 556bdb43f3e84..36f839c852e22 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -511,6 +511,7 @@ void avcodec_register_all(void) REGISTER_ENCODER(NVENC_HEVC, nvenc_hevc); #endif REGISTER_ENCODER(VP8_VAAPI, vp8_vaapi); + REGISTER_ENCODER(VP9_VAAPI, vp9_vaapi); /* parsers */ REGISTER_PARSER(AAC, aac); diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c new file mode 100644 index 0000000000000..5d3eec1775dcc --- /dev/null +++ b/libavcodec/vaapi_encode_vp9.c @@ -0,0 +1,311 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "libavutil/pixfmt.h" + +#include "avcodec.h" +#include "internal.h" +#include "vaapi_encode.h" + + +typedef struct VAAPIEncodeVP9Context { + int q_idx_idr; + int q_idx_p; + int q_idx_b; + + // Reference direction for B-like frames: + // 0 - most recent P/IDR frame is last. + // 1 - most recent P frame is golden. + int last_ref_dir; +} VAAPIEncodeVP9Context; + +typedef struct VAAPIEncodeVP9Options { + int loop_filter_level; + int loop_filter_sharpness; +} VAAPIEncodeVP9Options; + + +#define vseq_var(name) vseq->name, name +#define vseq_field(name) vseq->seq_fields.bits.name, name +#define vpic_var(name) vpic->name, name +#define vpic_field(name) vpic->pic_fields.bits.name, name + + +static int vaapi_encode_vp9_init_sequence_params(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAEncSequenceParameterBufferVP9 *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferVP9 *vpic = ctx->codec_picture_params; + + vseq->max_frame_width = avctx->width; + vseq->max_frame_height = avctx->height; + + vseq->kf_auto = 0; + + if (!(ctx->va_rc_mode & VA_RC_CQP)) { + vseq->bits_per_second = avctx->bit_rate; + vseq->intra_period = avctx->gop_size; + } + + vpic->frame_width_src = avctx->width; + vpic->frame_height_src = avctx->height; + vpic->frame_width_dst = avctx->width; + vpic->frame_height_dst = avctx->height; + + return 0; +} + +static int vaapi_encode_vp9_init_picture_params(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAEncPictureParameterBufferVP9 *vpic = pic->codec_picture_params; + VAAPIEncodeVP9Context *priv = ctx->priv_data; + VAAPIEncodeVP9Options *opt = ctx->codec_options; + int i; + + vpic->reconstructed_frame = pic->recon_surface; + vpic->coded_buf = pic->output_buffer; + + switch (pic->type) { + case PICTURE_TYPE_IDR: + av_assert0(pic->nb_refs == 0); + vpic->ref_flags.bits.force_kf = 1; + vpic->refresh_frame_flags = 0x01; + priv->last_ref_dir = 0; + break; + case PICTURE_TYPE_P: + av_assert0(pic->nb_refs == 1); + if (avctx->max_b_frames > 0) { + if (priv->last_ref_dir) { + vpic->ref_flags.bits.ref_frame_ctrl_l0 = 2; + vpic->ref_flags.bits.ref_gf_idx = 1; + vpic->ref_flags.bits.ref_gf_sign_bias = 1; + vpic->refresh_frame_flags = 0x01; + } else { + vpic->ref_flags.bits.ref_frame_ctrl_l0 = 1; + vpic->ref_flags.bits.ref_last_idx = 0; + vpic->ref_flags.bits.ref_last_sign_bias = 1; + vpic->refresh_frame_flags = 0x02; + } + } else { + vpic->ref_flags.bits.ref_frame_ctrl_l0 = 1; + vpic->ref_flags.bits.ref_last_idx = 0; + vpic->ref_flags.bits.ref_last_sign_bias = 1; + vpic->refresh_frame_flags = 0x01; + } + break; + case PICTURE_TYPE_B: + av_assert0(pic->nb_refs == 2); + if (priv->last_ref_dir) { + vpic->ref_flags.bits.ref_frame_ctrl_l0 = 1; + vpic->ref_flags.bits.ref_frame_ctrl_l1 = 2; + vpic->ref_flags.bits.ref_last_idx = 0; + vpic->ref_flags.bits.ref_last_sign_bias = 1; + vpic->ref_flags.bits.ref_gf_idx = 1; + vpic->ref_flags.bits.ref_gf_sign_bias = 0; + } else { + vpic->ref_flags.bits.ref_frame_ctrl_l0 = 2; + vpic->ref_flags.bits.ref_frame_ctrl_l1 = 1; + vpic->ref_flags.bits.ref_last_idx = 0; + vpic->ref_flags.bits.ref_last_sign_bias = 0; + vpic->ref_flags.bits.ref_gf_idx = 1; + vpic->ref_flags.bits.ref_gf_sign_bias = 1; + } + vpic->refresh_frame_flags = 0x00; + break; + default: + av_assert0(0 && "invalid picture type"); + } + + for (i = 0; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++) + vpic->reference_frames[i] = VA_INVALID_SURFACE; + if (pic->type == PICTURE_TYPE_P) { + av_assert0(pic->refs[0]); + vpic->reference_frames[priv->last_ref_dir] = + pic->refs[0]->recon_surface; + } else if (pic->type == PICTURE_TYPE_B) { + av_assert0(pic->refs[0] && pic->refs[1]); + vpic->reference_frames[!priv->last_ref_dir] = + pic->refs[0]->recon_surface; + vpic->reference_frames[priv->last_ref_dir] = + pic->refs[1]->recon_surface; + } + + vpic->pic_flags.bits.frame_type = (pic->type != PICTURE_TYPE_IDR); + vpic->pic_flags.bits.show_frame = pic->display_order <= pic->encode_order; + + if (pic->type == PICTURE_TYPE_IDR) + vpic->luma_ac_qindex = priv->q_idx_idr; + else if (pic->type == PICTURE_TYPE_P) + vpic->luma_ac_qindex = priv->q_idx_p; + else + vpic->luma_ac_qindex = priv->q_idx_b; + vpic->luma_dc_qindex_delta = 0; + vpic->chroma_ac_qindex_delta = 0; + vpic->chroma_dc_qindex_delta = 0; + + vpic->filter_level = opt->loop_filter_level; + vpic->sharpness_level = opt->loop_filter_sharpness; + + if (avctx->max_b_frames > 0 && pic->type == PICTURE_TYPE_P) + priv->last_ref_dir = !priv->last_ref_dir; + + return 0; +} + +static av_cold int vaapi_encode_vp9_configure(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeVP9Context *priv = ctx->priv_data; + + priv->q_idx_p = av_clip(avctx->global_quality, 0, 255); + if (avctx->i_quant_factor > 0.0) + priv->q_idx_idr = av_clip((avctx->global_quality * + avctx->i_quant_factor + + avctx->i_quant_offset) + 0.5, + 0, 255); + else + priv->q_idx_idr = priv->q_idx_p; + if (avctx->b_quant_factor > 0.0) + priv->q_idx_b = av_clip((avctx->global_quality * + avctx->b_quant_factor + + avctx->b_quant_offset) + 0.5, + 0, 255); + else + priv->q_idx_b = priv->q_idx_p; + + return 0; +} + +static const VAAPIEncodeType vaapi_encode_type_vp9 = { + .configure = &vaapi_encode_vp9_configure, + + .priv_data_size = sizeof(VAAPIEncodeVP9Context), + + .sequence_params_size = sizeof(VAEncSequenceParameterBufferVP9), + .init_sequence_params = &vaapi_encode_vp9_init_sequence_params, + + .picture_params_size = sizeof(VAEncPictureParameterBufferVP9), + .init_picture_params = &vaapi_encode_vp9_init_picture_params, +}; + +static av_cold int vaapi_encode_vp9_init(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + + ctx->codec = &vaapi_encode_type_vp9; + + switch (avctx->profile) { + case FF_PROFILE_VP9_0: + case FF_PROFILE_UNKNOWN: + ctx->va_profile = VAProfileVP9Profile0; + ctx->va_rt_format = VA_RT_FORMAT_YUV420; + break; + case FF_PROFILE_VP9_1: + av_log(avctx, AV_LOG_ERROR, "VP9 profile 1 is not " + "supported.\n"); + return AVERROR_PATCHWELCOME; + case FF_PROFILE_VP9_2: + ctx->va_profile = VAProfileVP9Profile2; + ctx->va_rt_format = VA_RT_FORMAT_YUV420_10BPP; + break; + case FF_PROFILE_VP9_3: + av_log(avctx, AV_LOG_ERROR, "VP9 profile 3 is not " + "supported.\n"); + return AVERROR_PATCHWELCOME; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown VP9 profile %d.\n", + avctx->profile); + return AVERROR(EINVAL); + } + ctx->va_entrypoint = VAEntrypointEncSlice; + + if (avctx->flags & AV_CODEC_FLAG_QSCALE) { + ctx->va_rc_mode = VA_RC_CQP; + } else if (avctx->bit_rate > 0) { + if (avctx->bit_rate == avctx->rc_max_rate) + ctx->va_rc_mode = VA_RC_CBR; + else + ctx->va_rc_mode = VA_RC_VBR; + } else { + ctx->va_rc_mode = VA_RC_CQP; + } + + // Packed headers are not currently supported. + ctx->va_packed_headers = 0; + + // Surfaces must be aligned to superblock boundaries. + ctx->surface_width = FFALIGN(avctx->width, 64); + ctx->surface_height = FFALIGN(avctx->height, 64); + + return ff_vaapi_encode_init(avctx); +} + +#define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \ + offsetof(VAAPIEncodeVP9Options, x)) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) +static const AVOption vaapi_encode_vp9_options[] = { + { "loop_filter_level", "Loop filter level", + OFFSET(loop_filter_level), AV_OPT_TYPE_INT, { .i64 = 16 }, 0, 63, FLAGS }, + { "loop_filter_sharpness", "Loop filter sharpness", + OFFSET(loop_filter_sharpness), AV_OPT_TYPE_INT, { .i64 = 4 }, 0, 15, FLAGS }, + { NULL }, +}; + +static const AVCodecDefault vaapi_encode_vp9_defaults[] = { + { "profile", "0" }, + { "b", "0" }, + { "bf", "0" }, + { "g", "250" }, + { "global_quality", "100" }, + { NULL }, +}; + +static const AVClass vaapi_encode_vp9_class = { + .class_name = "vp9_vaapi", + .item_name = av_default_item_name, + .option = vaapi_encode_vp9_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_vp9_vaapi_encoder = { + .name = "vp9_vaapi", + .long_name = NULL_IF_CONFIG_SMALL("VP9 (VAAPI)"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP9, + .priv_data_size = (sizeof(VAAPIEncodeContext) + + sizeof(VAAPIEncodeVP9Options)), + .init = &vaapi_encode_vp9_init, + .encode2 = &ff_vaapi_encode2, + .close = &ff_vaapi_encode_close, + .priv_class = &vaapi_encode_vp9_class, + .capabilities = AV_CODEC_CAP_DELAY, + .defaults = vaapi_encode_vp9_defaults, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_VAAPI, + AV_PIX_FMT_NONE, + }, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 4fb0a97a2714a..8943ef3d0f691 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 0 +#define LIBAVCODEC_VERSION_MINOR 1 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From 41dda860870fb1566b17f6b0b61922f0ef89be47 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 19 Mar 2017 17:30:52 +0000 Subject: [PATCH 0125/2557] doc: Add VAAPI encoders --- doc/encoders.texi | 96 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index 41b839812727a..7cebe39c18d28 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -922,4 +922,100 @@ encoder use CAVLC instead of CABAC. @end itemize +@section VAAPI encoders + +Wrappers for hardware encoders accessible via VAAPI. + +These encoders only accept input in VAAPI hardware surfaces. If you have input +in software frames, use the @option{hwupload} filter to upload them to the GPU. + +The following standard libavcodec options are used: +@itemize +@item +@option{g} / @option{gop_size} +@item +@option{bf} / @option{max_b_frames} +@item +@option{profile} +@item +@option{level} +@item +@option{b} / @option{bit_rate} +@item +@option{maxrate} / @option{rc_max_rate} +@item +@option{bufsize} / @option{rc_buffer_size} +@item +@option{rc_init_occupancy} / @option{rc_initial_buffer_occupancy} +@item +@option{q} / @option{global_quality} +@item +@option{qmin} +(only: @option{qmax} is not supported) +@item +@option{i_qfactor} / @option{i_quant_factor} +@item +@option{i_qoffset} / @option{i_quant_offset} +@item +@option{b_qfactor} / @option{b_quant_factor} +@item +@option{b_qoffset} / @option{b_quant_offset} +@end itemize + +@table @option + +@item vaapi_h264 +@option{profile} sets the value of @emph{profile_idc} and the @emph{constraint_set*_flag}s. +@option{level} sets the value of @emph{level_idc}. + +@table @option +@item quality +Set the local encoding quality/speed tradeoff (range 1-8, higher values are faster; not all +systems implement all levels). +@item low_power +Use low-power encoding mode. +@end table + +@item vaapi_hevc +@option{profile} and @option{level} set the values of +@emph{general_profile_idc} and @emph{general_level_idc} respectively. + +@item vaapi_mjpeg +Always encodes using the standard quantisation and huffman tables - +@option{global_quality} scales the standard quantisation table (range 1-100). + +@item vaapi_mpeg2 +@option{profile} and @option{level} set the value of @emph{profile_and_level_indication}. + +No rate control is supported. + +@item vaapi_vp8 +B-frames are not supported. + +@option{global_quality} sets the @emph{q_idx} used for non-key frames (range 0-127). + +@table @option +@item loop_filter_level +@item loop_filter_sharpness +Manually set the loop filter parameters. +@end table + +@item vaapi_vp9 +@option{global_quality} sets the @emph{q_idx} used for P-frames (range 0-255). + +@table @option +@item loop_filter_level +@item loop_filter_sharpness +Manually set the loop filter parameters. +@end table + +B-frames are supported, but the output stream is always in encode order rather than display +order. If B-frames are enabled, it may be necessary to use the @option{vp9_raw_reorder} +bitstream filter to modify the output stream to display frames in the correct order. + +Only normal frames are produced - the @option{vp9_superframe} bitstream filter may be +required to produce a stream usable with all decoders. + +@end table + @c man end VIDEO ENCODERS From 4936a48b1e6fc2147599541f8b25f43a8a9d1f16 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:35 +0000 Subject: [PATCH 0126/2557] qsv: Add ability to create a session from a device --- libavcodec/qsv.c | 49 +++++++++++++++++++++++++++------------ libavcodec/qsv_internal.h | 9 ++++--- libavcodec/qsvdec.c | 6 ++--- libavcodec/qsvenc.c | 6 ++--- 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index 735e1536f8406..30d612f0e1dac 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -537,27 +537,16 @@ static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) return MFX_ERR_NONE; } -int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *psession, - QSVFramesContext *qsv_frames_ctx, - const char *load_plugins, int opaque) +int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, + AVBufferRef *device_ref, const char *load_plugins) { static const mfxHandleType handle_types[] = { MFX_HANDLE_VA_DISPLAY, MFX_HANDLE_D3D9_DEVICE_MANAGER, MFX_HANDLE_D3D11_DEVICE, }; - mfxFrameAllocator frame_allocator = { - .pthis = qsv_frames_ctx, - .Alloc = qsv_frame_alloc, - .Lock = qsv_frame_lock, - .Unlock = qsv_frame_unlock, - .GetHDL = qsv_frame_get_hdl, - .Free = qsv_frame_free, - }; - - AVHWFramesContext *frames_ctx = (AVHWFramesContext*)qsv_frames_ctx->hw_frames_ctx->data; - AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; - AVQSVDeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; + AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref->data; + AVQSVDeviceContext *device_hwctx = device_ctx->hwctx; mfxSession parent_session = device_hwctx->session; mfxSession session; @@ -607,6 +596,36 @@ int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *psession, return ret; } + *psession = session; + return 0; +} + +int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *psession, + QSVFramesContext *qsv_frames_ctx, + const char *load_plugins, int opaque) +{ + mfxFrameAllocator frame_allocator = { + .pthis = qsv_frames_ctx, + .Alloc = qsv_frame_alloc, + .Lock = qsv_frame_lock, + .Unlock = qsv_frame_unlock, + .GetHDL = qsv_frame_get_hdl, + .Free = qsv_frame_free, + }; + + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)qsv_frames_ctx->hw_frames_ctx->data; + AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; + + mfxSession session; + mfxStatus err; + + int ret; + + ret = ff_qsv_init_session_device(avctx, &session, + frames_ctx->device_ref, load_plugins); + if (ret < 0) + return ret; + if (!opaque) { qsv_frames_ctx->logctx = avctx; diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index 7ac347ea2118c..975c8de44164f 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -87,9 +87,12 @@ int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc); int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, const char *load_plugins); -int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *session, - QSVFramesContext *qsv_frames_ctx, - const char *load_plugins, int opaque); +int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, + AVBufferRef *device_ref, const char *load_plugins); + +int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *session, + QSVFramesContext *qsv_frames_ctx, + const char *load_plugins, int opaque); int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame); diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 0cbe5094c76ae..96526a100ae4b 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -59,9 +59,9 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses if (!q->frames_ctx.hw_frames_ctx) return AVERROR(ENOMEM); - ret = ff_qsv_init_session_hwcontext(avctx, &q->internal_session, - &q->frames_ctx, q->load_plugins, - q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY); + ret = ff_qsv_init_session_frames(avctx, &q->internal_session, + &q->frames_ctx, q->load_plugins, + q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY); if (ret < 0) { av_buffer_unref(&q->frames_ctx.hw_frames_ctx); return ret; diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 85af146ad8169..b2f2b4db711ff 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -684,9 +684,9 @@ static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q) if (!q->frames_ctx.hw_frames_ctx) return AVERROR(ENOMEM); - ret = ff_qsv_init_session_hwcontext(avctx, &q->internal_session, - &q->frames_ctx, q->load_plugins, - q->param.IOPattern == MFX_IOPATTERN_IN_OPAQUE_MEMORY); + ret = ff_qsv_init_session_frames(avctx, &q->internal_session, + &q->frames_ctx, q->load_plugins, + q->param.IOPattern == MFX_IOPATTERN_IN_OPAQUE_MEMORY); if (ret < 0) { av_buffer_unref(&q->frames_ctx.hw_frames_ctx); return ret; From 8848ba0bd6b035af77d4f13aa0d8aaaad9806fe8 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:36 +0000 Subject: [PATCH 0127/2557] qsvdec: Allow use of hw_device_ctx to make the internal session --- libavcodec/qsvdec.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 96526a100ae4b..2c90436a177cd 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -42,7 +42,7 @@ #include "qsvdec.h" static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session, - AVBufferRef *hw_frames_ref) + AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref) { int ret; @@ -67,6 +67,18 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses return ret; } + q->session = q->internal_session; + } else if (hw_device_ref) { + if (q->internal_session) { + MFXClose(q->internal_session); + q->internal_session = NULL; + } + + ret = ff_qsv_init_session_device(avctx, &q->internal_session, + hw_device_ref, q->load_plugins); + if (ret < 0) + return ret; + q->session = q->internal_session; } else { if (!q->internal_session) { @@ -133,7 +145,7 @@ static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q) iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; q->iopattern = iopattern; - ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx); + ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx, avctx->hw_device_ctx); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error initializing an MFX session\n"); return ret; From 3d197514e613ccd9eab43180c0a7c8b09a307606 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:37 +0000 Subject: [PATCH 0128/2557] qsvenc: Allow use of hw_device_ctx to make the internal session --- libavcodec/qsvenc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index b2f2b4db711ff..bd8c24321ed05 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -692,6 +692,13 @@ static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q) return ret; } + q->session = q->internal_session; + } else if (avctx->hw_device_ctx) { + ret = ff_qsv_init_session_device(avctx, &q->internal_session, + avctx->hw_device_ctx, q->load_plugins); + if (ret < 0) + return ret; + q->session = q->internal_session; } else { ret = ff_qsv_init_internal_session(avctx, &q->internal_session, From 604fbb3132e88727e496c96c92cfe02748c25a1a Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 14 Mar 2017 16:43:29 +0100 Subject: [PATCH 0129/2557] mov: Move code shared with CAF to a separate file --- libavformat/Makefile | 5 ++--- libavformat/isom.h | 15 ++++++++++++++- libavformat/mov.c | 36 ----------------------------------- libavformat/mov_esds.c | 43 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 40 deletions(-) create mode 100644 libavformat/mov_esds.c diff --git a/libavformat/Makefile b/libavformat/Makefile index c55538018979d..7b1df9342c727 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -93,8 +93,7 @@ OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o OBJS-$(CONFIG_BINK_DEMUXER) += bink.o OBJS-$(CONFIG_BMV_DEMUXER) += bmv.o OBJS-$(CONFIG_C93_DEMUXER) += c93.o voc_packet.o voc.o -OBJS-$(CONFIG_CAF_DEMUXER) += cafdec.o caf.o mov.o mov_chan.o \ - replaygain.o +OBJS-$(CONFIG_CAF_DEMUXER) += cafdec.o caf.o mov_chan.o mov_esds.o OBJS-$(CONFIG_CAVSVIDEO_DEMUXER) += cavsvideodec.o rawdec.o OBJS-$(CONFIG_CAVSVIDEO_MUXER) += rawenc.o OBJS-$(CONFIG_CDG_DEMUXER) += cdg.o @@ -193,7 +192,7 @@ OBJS-$(CONFIG_MLP_MUXER) += rawenc.o OBJS-$(CONFIG_MM_DEMUXER) += mm.o OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o pcm.o OBJS-$(CONFIG_MMF_MUXER) += mmf.o -OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o replaygain.o +OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o mov_esds.o replaygain.o OBJS-$(CONFIG_MOV_MUXER) += movenc.o avc.o hevc.o \ movenchint.o mov_chan.o OBJS-$(CONFIG_MP2_MUXER) += rawenc.o diff --git a/libavformat/isom.h b/libavformat/isom.h index 8cc5ab744df83..2a7486d7bab7c 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -239,8 +239,21 @@ void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id); int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb); -enum AVCodecID ff_mov_get_lpcm_codec_id(int bps, int flags); int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries); +/** + * Compute codec id for 'lpcm' tag. + * See CoreAudioTypes and AudioStreamBasicDescription at Apple. + */ +static inline enum AVCodecID ff_mov_get_lpcm_codec_id(int bps, int flags) +{ + /* lpcm flags: + * 0x1 = float + * 0x2 = big-endian + * 0x4 = signed + */ + return ff_get_pcm_codec_id(bps, flags & 1, flags & 2, flags & 4 ? -1 : 0); +} + #endif /* AVFORMAT_ISOM_H */ diff --git a/libavformat/mov.c b/libavformat/mov.c index 1c1857eaf99b1..bf68fbd46affb 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -674,28 +674,6 @@ static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } -int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb) -{ - AVStream *st; - int tag; - - if (fc->nb_streams < 1) - return 0; - st = fc->streams[fc->nb_streams-1]; - - avio_rb32(pb); /* version + flags */ - ff_mp4_read_descr(fc, pb, &tag); - if (tag == MP4ESDescrTag) { - ff_mp4_parse_es_descr(pb, NULL); - } else - avio_rb16(pb); /* ID */ - - ff_mp4_read_descr(fc, pb, &tag); - if (tag == MP4DecConfigDescrTag) - ff_mp4_read_dec_config_descr(fc, st, pb); - return 0; -} - static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom) { return ff_mov_read_esds(c->fc, pb); @@ -1377,20 +1355,6 @@ static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } -/** - * Compute codec id for 'lpcm' tag. - * See CoreAudioTypes and AudioStreamBasicDescription at Apple. - */ -enum AVCodecID ff_mov_get_lpcm_codec_id(int bps, int flags) -{ - /* lpcm flags: - * 0x1 = float - * 0x2 = big-endian - * 0x4 = signed - */ - return ff_get_pcm_codec_id(bps, flags & 1, flags & 2, flags & 4 ? -1 : 0); -} - static int mov_codec_id(AVStream *st, uint32_t format) { int id = ff_codec_get_id(ff_codec_movaudio_tags, format); diff --git a/libavformat/mov_esds.c b/libavformat/mov_esds.c new file mode 100644 index 0000000000000..b195f1ae7a0fb --- /dev/null +++ b/libavformat/mov_esds.c @@ -0,0 +1,43 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" +#include "avio.h" +#include "isom.h" + +int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb) +{ + AVStream *st; + int tag; + + if (fc->nb_streams < 1) + return 0; + st = fc->streams[fc->nb_streams-1]; + + avio_rb32(pb); /* version + flags */ + ff_mp4_read_descr(fc, pb, &tag); + if (tag == MP4ESDescrTag) { + ff_mp4_parse_es_descr(pb, NULL); + } else + avio_rb16(pb); /* ID */ + + ff_mp4_read_descr(fc, pb, &tag); + if (tag == MP4DecConfigDescrTag) + ff_mp4_read_dec_config_descr(fc, st, pb); + return 0; +} From b62ed6873821c8fce8f7e2c2927ae54f86afeb22 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 21 Mar 2017 12:22:23 +0100 Subject: [PATCH 0130/2557] configure: Better names for functions that sanitize input --- configure | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 30eba73c2168e..ecc77842ff09e 100755 --- a/configure +++ b/configure @@ -477,13 +477,13 @@ sanitize_var_name(){ echo $@ | sed 's/[^A-Za-z0-9_]/_/g' } -set_safe(){ +set_sanitized(){ var=$1 shift eval $(sanitize_var_name "$var")='$*' } -get_safe(){ +get_sanitized(){ eval echo \$$(sanitize_var_name "$1") } @@ -522,13 +522,13 @@ disable_weak(){ set_weak no $* } -enable_safe(){ +enable_sanitized(){ for var; do enable $(echo "$var" | sed 's/[^A-Za-z0-9_]/_/g') done } -disable_safe(){ +disable_sanitized(){ for var; do disable $(echo "$var" | sed 's/[^A-Za-z0-9_]/_/g') done @@ -937,8 +937,8 @@ check_header(){ log check_header "$@" header=$1 shift - disable_safe $header - check_cpp "$@" < int x; EOF @@ -982,7 +982,7 @@ check_func_headers(){ echo "long check_$func(void) { return (long) $func; }" done echo "int main(void) { return 0; }" - } | check_ld "$@" && enable $funcs && enable_safe $headers + } | check_ld "$@" && enable $funcs && enable_sanitized $headers } check_cpp_condition(){ @@ -1080,8 +1080,8 @@ check_type(){ headers=$1 type=$2 shift 2 - disable_safe "$type" - check_code cc "$headers" "$type v" "$@" && enable_safe "$type" + disable_sanitized "$type" + check_code cc "$headers" "$type v" "$@" && enable_sanitized "$type" } check_struct(){ @@ -1090,9 +1090,9 @@ check_struct(){ struct=$2 member=$3 shift 3 - disable_safe "${struct}_${member}" + disable_sanitized "${struct}_${member}" check_code cc "$headers" "const void *p = &(($struct *)0)->$member" "$@" && - enable_safe "${struct}_${member}" + enable_sanitized "${struct}_${member}" } check_builtin(){ From 6ac0e7818399a57e4684202bac79f35b3561ad1e Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Thu, 30 Mar 2017 16:21:38 -0400 Subject: [PATCH 0131/2557] mpeg4videodec: raise an error if sprite_trajectory.table is NULL CC: libav-stable@libav.org Bug-Id: 1012 --- libavcodec/mpeg4videodec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 8891ec1bb7912..eb1b67273bc9c 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -186,6 +186,10 @@ static int mpeg4_decode_sprite_trajectory(Mpeg4DecContext *ctx, GetBitContext *g if (w <= 0 || h <= 0) return AVERROR_INVALIDDATA; + /* the decoder was not properly initialized and we cannot continue */ + if (sprite_trajectory.table == NULL) + return AVERROR_INVALIDDATA; + for (i = 0; i < ctx->num_sprite_warping_points; i++) { int length; int x = 0, y = 0; From d32d59bc977b43031007bb2ab21e232f96d2ebcb Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 7 Apr 2017 11:41:27 +0200 Subject: [PATCH 0132/2557] matroska: Read only the data written in the scratch buffer The private buffer is 20bytes but depending on the type only 12 bytes are actually filled. --- libavformat/matroskaenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 34d983324bd6a..b8c434a664593 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -686,7 +686,7 @@ static int mkv_write_video_projection(AVFormatContext *s, AVIOContext *pb, avio_wb32(&b, spherical->bound_left); avio_wb32(&b, spherical->bound_right); put_ebml_binary(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONPRIVATE, - private, sizeof(private)); + private, avio_tell(&b)); break; case AV_SPHERICAL_CUBEMAP: ffio_init_context(&b, private, 12, 1, NULL, NULL, NULL, NULL); @@ -696,7 +696,7 @@ static int mkv_write_video_projection(AVFormatContext *s, AVIOContext *pb, avio_wb32(&b, 0); // layout avio_wb32(&b, spherical->padding); put_ebml_binary(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONPRIVATE, - private, sizeof(private)); + private, avio_tell(&b)); break; default: av_log(s, AV_LOG_WARNING, "Unknown projection type\n"); From 839010aca9713b5cd6ebe7a1db7e805c3625b168 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Tue, 4 Apr 2017 17:56:34 +0200 Subject: [PATCH 0133/2557] filtfmts-test: Mark filter as const libavfilter/tests/filtfmts.c:57:18: warning: assigning to 'AVFilter *' (aka 'struct AVFilter *') from 'const AVFilter *' (aka 'const struct AVFilter *') discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers] --- libavfilter/tests/filtfmts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/tests/filtfmts.c b/libavfilter/tests/filtfmts.c index cc046542223ff..6bd8237e31a65 100644 --- a/libavfilter/tests/filtfmts.c +++ b/libavfilter/tests/filtfmts.c @@ -28,7 +28,7 @@ int main(int argc, char **argv) { - AVFilter *filter; + const AVFilter *filter; AVFilterContext *filter_ctx; AVFilterGraph *graph_ctx; const char *filter_name; From f5950b8fd61ec85e0ad8790bea56b37ceea19436 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 5 Apr 2017 15:35:26 +0200 Subject: [PATCH 0134/2557] lavfi: Drop unused and empty header file This header was public but deprecated on 2013-04-11 (lavfi 3.8.0). --- libavfilter/Makefile | 1 - libavfilter/avfiltergraph.h | 29 ----------------------------- 2 files changed, 30 deletions(-) delete mode 100644 libavfilter/avfiltergraph.h diff --git a/libavfilter/Makefile b/libavfilter/Makefile index c8d1515d2c9e0..348ad92116759 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -2,7 +2,6 @@ NAME = avfilter DESC = Libav video filtering library HEADERS = avfilter.h \ - avfiltergraph.h \ buffersink.h \ buffersrc.h \ version.h \ diff --git a/libavfilter/avfiltergraph.h b/libavfilter/avfiltergraph.h deleted file mode 100644 index 47174efc6ce89..0000000000000 --- a/libavfilter/avfiltergraph.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Filter graphs - * copyright (c) 2007 Bobby Bingham - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVFILTER_AVFILTERGRAPH_H -#define AVFILTER_AVFILTERGRAPH_H - -#include "avfilter.h" -#include "libavutil/log.h" - - -#endif /* AVFILTER_AVFILTERGRAPH_H */ From efddf2c09aed7400c73ecf327f86a4d0452b94b5 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 3 Apr 2017 21:58:15 +0200 Subject: [PATCH 0135/2557] decode: Initialize ret before using it libavcodec/decode.c:608:9: warning: variable 'ret' is used uninitialized whenever 'if' condition is false --- libavcodec/decode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index e4f6a0d7270d8..8aa27095b63b9 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -590,7 +590,7 @@ static int compat_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt) { AVCodecInternal *avci = avctx->internal; - int ret; + int ret = 0; av_assert0(avci->compat_decode_consumed == 0); From b200a2c8da403b5a5c8b50f8cb4a75fd4f0131b1 Mon Sep 17 00:00:00 2001 From: Andreas Unterweger Date: Mon, 10 Apr 2017 13:06:18 +0200 Subject: [PATCH 0136/2557] examples: Fixed and extended Doxygen documentation Added parameter descriptions for all functions and converted in-function comments into regular (non-Doxygen) comments. Signed-off-by: Vittorio Giovara --- doc/examples/transcode_aac.c | 378 ++++++++++++++++++++--------------- 1 file changed, 215 insertions(+), 163 deletions(-) diff --git a/doc/examples/transcode_aac.c b/doc/examples/transcode_aac.c index d547b326ab284..44d5af6b0481d 100644 --- a/doc/examples/transcode_aac.c +++ b/doc/examples/transcode_aac.c @@ -1,4 +1,6 @@ /* + * Copyright (c) 2013-2017 Andreas Unterweger + * * This file is part of Libav. * * Libav is free software; you can redistribute it and/or @@ -8,7 +10,7 @@ * * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public @@ -18,10 +20,11 @@ /** * @file - * simple audio converter + * Simple audio converter * * @example transcode_aac.c * Convert an input audio file to AAC in an MP4 container using Libav. + * Formats other than MP4 are supported based on the output file extension. * @author Andreas Unterweger (dustsigns@gmail.com) */ @@ -39,9 +42,9 @@ #include "libavresample/avresample.h" -/** The output bit rate in kbit/s */ +/* The output bit rate in bit/s */ #define OUTPUT_BIT_RATE 96000 -/** The number of output channels */ +/* The number of output channels */ #define OUTPUT_CHANNELS 2 /** @@ -56,7 +59,13 @@ static char *get_error_text(const int error) return error_buffer; } -/** Open an input file and the required decoder. */ +/** + * Open an input file and the required decoder. + * @param filename File to be opened + * @param[out] input_format_context Format context of opened file + * @param[out] input_codec_context Codec context of opened file + * @return Error code (0 if successful) + */ static int open_input_file(const char *filename, AVFormatContext **input_format_context, AVCodecContext **input_codec_context) @@ -65,7 +74,7 @@ static int open_input_file(const char *filename, AVCodec *input_codec; int error; - /** Open the input file to read from it. */ + /* Open the input file to read from it. */ if ((error = avformat_open_input(input_format_context, filename, NULL, NULL)) < 0) { fprintf(stderr, "Could not open input file '%s' (error '%s')\n", @@ -74,7 +83,7 @@ static int open_input_file(const char *filename, return error; } - /** Get information on the input file (number of streams etc.). */ + /* Get information on the input file (number of streams etc.). */ if ((error = avformat_find_stream_info(*input_format_context, NULL)) < 0) { fprintf(stderr, "Could not open find stream info (error '%s')\n", get_error_text(error)); @@ -82,7 +91,7 @@ static int open_input_file(const char *filename, return error; } - /** Make sure that there is only one stream in the input file. */ + /* Make sure that there is only one stream in the input file. */ if ((*input_format_context)->nb_streams != 1) { fprintf(stderr, "Expected one audio input stream, but found %d\n", (*input_format_context)->nb_streams); @@ -90,14 +99,14 @@ static int open_input_file(const char *filename, return AVERROR_EXIT; } - /** Find a decoder for the audio stream. */ + /* Find a decoder for the audio stream. */ if (!(input_codec = avcodec_find_decoder((*input_format_context)->streams[0]->codecpar->codec_id))) { fprintf(stderr, "Could not find input codec\n"); avformat_close_input(input_format_context); return AVERROR_EXIT; } - /** allocate a new decoding context */ + /* Allocate a new decoding context. */ avctx = avcodec_alloc_context3(input_codec); if (!avctx) { fprintf(stderr, "Could not allocate a decoding context\n"); @@ -105,7 +114,7 @@ static int open_input_file(const char *filename, return AVERROR(ENOMEM); } - /** initialize the stream parameters with demuxer information */ + /* Initialize the stream parameters with demuxer information. */ error = avcodec_parameters_to_context(avctx, (*input_format_context)->streams[0]->codecpar); if (error < 0) { avformat_close_input(input_format_context); @@ -113,7 +122,7 @@ static int open_input_file(const char *filename, return error; } - /** Open the decoder for the audio stream to use it later. */ + /* Open the decoder for the audio stream to use it later. */ if ((error = avcodec_open2(avctx, input_codec, NULL)) < 0) { fprintf(stderr, "Could not open input codec (error '%s')\n", get_error_text(error)); @@ -122,7 +131,7 @@ static int open_input_file(const char *filename, return error; } - /** Save the decoder context for easier access later. */ + /* Save the decoder context for easier access later. */ *input_codec_context = avctx; return 0; @@ -132,6 +141,11 @@ static int open_input_file(const char *filename, * Open an output file and the required encoder. * Also set some basic encoder parameters. * Some of these parameters are based on the input file's parameters. + * @param filename File to be opened + * @param input_codec_context Codec context of input file + * @param[out] output_format_context Format context of output file + * @param[out] output_codec_context Codec context of output file + * @return Error code (0 if successful) */ static int open_output_file(const char *filename, AVCodecContext *input_codec_context, @@ -144,7 +158,7 @@ static int open_output_file(const char *filename, AVCodec *output_codec = NULL; int error; - /** Open the output file to write to it. */ + /* Open the output file to write to it. */ if ((error = avio_open(&output_io_context, filename, AVIO_FLAG_WRITE)) < 0) { fprintf(stderr, "Could not open output file '%s' (error '%s')\n", @@ -152,16 +166,16 @@ static int open_output_file(const char *filename, return error; } - /** Create a new format context for the output container format. */ + /* Create a new format context for the output container format. */ if (!(*output_format_context = avformat_alloc_context())) { fprintf(stderr, "Could not allocate output format context\n"); return AVERROR(ENOMEM); } - /** Associate the output file (pointer) with the container format context. */ + /* Associate the output file (pointer) with the container format context. */ (*output_format_context)->pb = output_io_context; - /** Guess the desired container format based on the file extension. */ + /* Guess the desired container format based on the file extension. */ if (!((*output_format_context)->oformat = av_guess_format(NULL, filename, NULL))) { fprintf(stderr, "Could not find output file format\n"); @@ -171,13 +185,13 @@ static int open_output_file(const char *filename, av_strlcpy((*output_format_context)->filename, filename, sizeof((*output_format_context)->filename)); - /** Find the encoder to be used by its name. */ + /* Find the encoder to be used by its name. */ if (!(output_codec = avcodec_find_encoder(AV_CODEC_ID_AAC))) { fprintf(stderr, "Could not find an AAC encoder.\n"); goto cleanup; } - /** Create a new audio stream in the output file container. */ + /* Create a new audio stream in the output file container. */ if (!(stream = avformat_new_stream(*output_format_context, NULL))) { fprintf(stderr, "Could not create new stream\n"); error = AVERROR(ENOMEM); @@ -191,31 +205,27 @@ static int open_output_file(const char *filename, goto cleanup; } - /** - * Set the basic encoder parameters. - * The input file's sample rate is used to avoid a sample rate conversion. - */ + /* Set the basic encoder parameters. + * The input file's sample rate is used to avoid a sample rate conversion. */ avctx->channels = OUTPUT_CHANNELS; avctx->channel_layout = av_get_default_channel_layout(OUTPUT_CHANNELS); avctx->sample_rate = input_codec_context->sample_rate; avctx->sample_fmt = output_codec->sample_fmts[0]; avctx->bit_rate = OUTPUT_BIT_RATE; - /** Allow the use of the experimental AAC encoder */ + /* Allow the use of the experimental AAC encoder. */ avctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; - /** Set the sample rate for the container. */ + /* Set the sample rate for the container. */ stream->time_base.den = input_codec_context->sample_rate; stream->time_base.num = 1; - /** - * Some container formats (like MP4) require global headers to be present - * Mark the encoder so that it behaves accordingly. - */ + /* Some container formats (like MP4) require global headers to be present. + * Mark the encoder so that it behaves accordingly. */ if ((*output_format_context)->oformat->flags & AVFMT_GLOBALHEADER) avctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; - /** Open the encoder for the audio stream to use it later. */ + /* Open the encoder for the audio stream to use it later. */ if ((error = avcodec_open2(avctx, output_codec, NULL)) < 0) { fprintf(stderr, "Could not open output codec (error '%s')\n", get_error_text(error)); @@ -228,7 +238,7 @@ static int open_output_file(const char *filename, goto cleanup; } - /** Save the encoder context for easier access later. */ + /* Save the encoder context for easier access later. */ *output_codec_context = avctx; return 0; @@ -241,16 +251,23 @@ static int open_output_file(const char *filename, return error < 0 ? error : AVERROR_EXIT; } -/** Initialize one data packet for reading or writing. */ +/** + * Initialize one data packet for reading or writing. + * @param packet Packet to be initialized + */ static void init_packet(AVPacket *packet) { av_init_packet(packet); - /** Set the packet data and size so that it is recognized as being empty. */ + /* Set the packet data and size so that it is recognized as being empty. */ packet->data = NULL; packet->size = 0; } -/** Initialize one audio frame for reading from the input file */ +/** + * Initialize one audio frame for reading from the input file. + * @param[out] frame Frame to be initialized + * @return Error code (0 if successful) + */ static int init_input_frame(AVFrame **frame) { if (!(*frame = av_frame_alloc())) { @@ -264,27 +281,28 @@ static int init_input_frame(AVFrame **frame) * Initialize the audio resampler based on the input and output codec settings. * If the input and output sample formats differ, a conversion is required * libavresample takes care of this, but requires initialization. + * @param input_codec_context Codec context of the input file + * @param output_codec_context Codec context of the output file + * @param[out] resample_context Resample context for the required conversion + * @return Error code (0 if successful) */ static int init_resampler(AVCodecContext *input_codec_context, AVCodecContext *output_codec_context, AVAudioResampleContext **resample_context) { - /** - * Only initialize the resampler if it is necessary, i.e., - * if and only if the sample formats differ. - */ + /* Only initialize the resampler if it is necessary, i.e., + * if and only if the sample formats differ. */ if (input_codec_context->sample_fmt != output_codec_context->sample_fmt || input_codec_context->channels != output_codec_context->channels) { int error; - /** Create a resampler context for the conversion. */ + /* Create a resampler context for the conversion. */ if (!(*resample_context = avresample_alloc_context())) { fprintf(stderr, "Could not allocate resample context\n"); return AVERROR(ENOMEM); } - /** - * Set the conversion parameters. + /* Set the conversion parameters. * Default channel layouts based on the number of channels * are assumed for simplicity (they are sometimes not detected * properly by the demuxer and/or decoder). @@ -302,7 +320,7 @@ static int init_resampler(AVCodecContext *input_codec_context, av_opt_set_int(*resample_context, "out_sample_fmt", output_codec_context->sample_fmt, 0); - /** Open the resampler with the specified parameters. */ + /* Open the resampler with the specified parameters. */ if ((error = avresample_open(*resample_context)) < 0) { fprintf(stderr, "Could not open resample context\n"); avresample_free(resample_context); @@ -312,10 +330,15 @@ static int init_resampler(AVCodecContext *input_codec_context, return 0; } -/** Initialize a FIFO buffer for the audio samples to be encoded. */ +/** + * Initialize a FIFO buffer for the audio samples to be encoded. + * @param[out] fifo Sample buffer + * @param output_codec_context Codec context of the output file + * @return Error code (0 if successful) + */ static int init_fifo(AVAudioFifo **fifo, AVCodecContext *output_codec_context) { - /** Create the FIFO buffer based on the specified output sample format. */ + /* Create the FIFO buffer based on the specified output sample format. */ if (!(*fifo = av_audio_fifo_alloc(output_codec_context->sample_fmt, output_codec_context->channels, 1))) { fprintf(stderr, "Could not allocate FIFO\n"); @@ -324,7 +347,11 @@ static int init_fifo(AVAudioFifo **fifo, AVCodecContext *output_codec_context) return 0; } -/** Write the header of the output file container. */ +/** + * Write the header of the output file container. + * @param output_format_context Format context of the output file + * @return Error code (0 if successful) + */ static int write_output_file_header(AVFormatContext *output_format_context) { int error; @@ -336,20 +363,32 @@ static int write_output_file_header(AVFormatContext *output_format_context) return 0; } -/** Decode one audio frame from the input file. */ +/** + * Decode one audio frame from the input file. + * @param frame Audio frame to be decoded + * @param input_format_context Format context of the input file + * @param input_codec_context Codec context of the input file + * @param[out] data_present Indicates whether data has been decoded + * @param[out] finished Indicates whether the end of file has + * been reached and all data has been + * decoded. If this flag is false, there + * is more data to be decoded, i.e., this + * function has to be called again. + * @return Error code (0 if successful) + */ static int decode_audio_frame(AVFrame *frame, AVFormatContext *input_format_context, AVCodecContext *input_codec_context, int *data_present, int *finished) { - /** Packet used for temporary storage. */ + /* Packet used for temporary storage. */ AVPacket input_packet; int error; init_packet(&input_packet); - /** Read one audio frame from the input file into a temporary packet. */ + /* Read one audio frame from the input file into a temporary packet. */ if ((error = av_read_frame(input_format_context, &input_packet)) < 0) { - /** If we are the the end of the file, flush the decoder below. */ + /* If we are the the end of the file, flush the decoder below. */ if (error == AVERROR_EOF) *finished = 1; else { @@ -359,12 +398,10 @@ static int decode_audio_frame(AVFrame *frame, } } - /** - * Decode the audio frame stored in the temporary packet. + /* Decode the audio frame stored in the temporary packet. * The input audio stream decoder is used to do this. * If we are at the end of the file, pass an empty packet to the decoder - * to flush it. - */ + * to flush it. */ if ((error = avcodec_decode_audio4(input_codec_context, frame, data_present, &input_packet)) < 0) { fprintf(stderr, "Could not decode frame (error '%s')\n", @@ -373,10 +410,8 @@ static int decode_audio_frame(AVFrame *frame, return error; } - /** - * If the decoder has not been flushed completely, we are not finished, - * so that this function has to be called again. - */ + /* If the decoder has not been flushed completely, we are not finished, + * so that this function has to be called again. */ if (*finished && *data_present) *finished = 0; av_packet_unref(&input_packet); @@ -387,6 +422,13 @@ static int decode_audio_frame(AVFrame *frame, * Initialize a temporary storage for the specified number of audio samples. * The conversion requires temporary storage due to the different format. * The number of audio samples to be allocated is specified in frame_size. + * @param[out] converted_input_samples Array of converted samples. The + * dimensions are reference, channel + * (for multi-channel audio), sample. + * @param output_codec_context Codec context of the output file + * @param frame_size Number of samples to be converted in + * each round + * @return Error code (0 if successful) */ static int init_converted_samples(uint8_t ***converted_input_samples, AVCodecContext *output_codec_context, @@ -394,8 +436,7 @@ static int init_converted_samples(uint8_t ***converted_input_samples, { int error; - /** - * Allocate as many pointers as there are audio channels. + /* Allocate as many pointers as there are audio channels. * Each pointer will later point to the audio samples of the corresponding * channels (although it may be NULL for interleaved formats). */ @@ -405,10 +446,8 @@ static int init_converted_samples(uint8_t ***converted_input_samples, return AVERROR(ENOMEM); } - /** - * Allocate memory for the samples of all channels in one consecutive - * block for convenience. - */ + /* Allocate memory for the samples of all channels in one consecutive + * block for convenience. */ if ((error = av_samples_alloc(*converted_input_samples, NULL, output_codec_context->channels, frame_size, @@ -425,8 +464,15 @@ static int init_converted_samples(uint8_t ***converted_input_samples, /** * Convert the input audio samples into the output sample format. - * The conversion happens on a per-frame basis, the size of which is specified - * by frame_size. + * The conversion happens on a per-frame basis, the size of which is + * specified by frame_size. + * @param input_data Samples to be decoded. The dimensions are + * channel (for multi-channel audio), sample. + * @param[out] converted_data Converted samples. The dimensions are channel + * (for multi-channel audio), sample. + * @param frame_size Number of samples to be converted + * @param resample_context Resample context for the conversion + * @return Error code (0 if successful) */ static int convert_samples(uint8_t **input_data, uint8_t **converted_data, const int frame_size, @@ -434,7 +480,7 @@ static int convert_samples(uint8_t **input_data, { int error; - /** Convert the samples using the resampler. */ + /* Convert the samples using the resampler. */ if ((error = avresample_convert(resample_context, converted_data, 0, frame_size, input_data, 0, frame_size)) < 0) { fprintf(stderr, "Could not convert input samples (error '%s')\n", @@ -442,11 +488,9 @@ static int convert_samples(uint8_t **input_data, return error; } - /** - * Perform a sanity check so that the number of converted samples is + /* Perform a sanity check so that the number of converted samples is * not greater than the number of samples to be converted. - * If the sample rates differ, this case has to be handled differently - */ + * If the sample rates differ, this case has to be handled differently. */ if (avresample_available(resample_context)) { fprintf(stderr, "Converted samples left over\n"); return AVERROR_EXIT; @@ -455,23 +499,28 @@ static int convert_samples(uint8_t **input_data, return 0; } -/** Add converted input audio samples to the FIFO buffer for later processing. */ +/** + * Add converted input audio samples to the FIFO buffer for later processing. + * @param fifo Buffer to add the samples to + * @param converted_input_samples Samples to be added. The dimensions are channel + * (for multi-channel audio), sample. + * @param frame_size Number of samples to be converted + * @return Error code (0 if successful) + */ static int add_samples_to_fifo(AVAudioFifo *fifo, uint8_t **converted_input_samples, const int frame_size) { int error; - /** - * Make the FIFO as large as it needs to be to hold both, - * the old and the new samples. - */ + /* Make the FIFO as large as it needs to be to hold both, + * the old and the new samples. */ if ((error = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame_size)) < 0) { fprintf(stderr, "Could not reallocate FIFO\n"); return error; } - /** Store the new samples in the FIFO buffer. */ + /* Store the new samples in the FIFO buffer. */ if (av_audio_fifo_write(fifo, (void **)converted_input_samples, frame_size) < frame_size) { fprintf(stderr, "Could not write data to FIFO\n"); @@ -481,55 +530,63 @@ static int add_samples_to_fifo(AVAudioFifo *fifo, } /** - * Read one audio frame from the input file, decodes, converts and stores + * Read one audio frame from the input file, decode, convert and store * it in the FIFO buffer. + * @param fifo Buffer used for temporary storage + * @param input_format_context Format context of the input file + * @param input_codec_context Codec context of the input file + * @param output_codec_context Codec context of the output file + * @param resample_context Resample context for the conversion + * @param[out] finished Indicates whether the end of file has + * been reached and all data has been + * decoded. If this flag is false, + * there is more data to be decoded, + * i.e., this function has to be called + * again. + * @return Error code (0 if successful) */ static int read_decode_convert_and_store(AVAudioFifo *fifo, AVFormatContext *input_format_context, AVCodecContext *input_codec_context, AVCodecContext *output_codec_context, - AVAudioResampleContext *resampler_context, + AVAudioResampleContext *resample_context, int *finished) { - /** Temporary storage of the input samples of the frame read from the file. */ + /* Temporary storage of the input samples of the frame read from the file. */ AVFrame *input_frame = NULL; - /** Temporary storage for the converted input samples. */ + /* Temporary storage for the converted input samples. */ uint8_t **converted_input_samples = NULL; int data_present; int ret = AVERROR_EXIT; - /** Initialize temporary storage for one input frame. */ + /* Initialize temporary storage for one input frame. */ if (init_input_frame(&input_frame)) goto cleanup; - /** Decode one frame worth of audio samples. */ + /* Decode one frame worth of audio samples. */ if (decode_audio_frame(input_frame, input_format_context, input_codec_context, &data_present, finished)) goto cleanup; - /** - * If we are at the end of the file and there are no more samples + /* If we are at the end of the file and there are no more samples * in the decoder which are delayed, we are actually finished. - * This must not be treated as an error. - */ + * This must not be treated as an error. */ if (*finished && !data_present) { ret = 0; goto cleanup; } - /** If there is decoded data, convert and store it */ + /* If there is decoded data, convert and store it. */ if (data_present) { - /** Initialize the temporary storage for the converted input samples. */ + /* Initialize the temporary storage for the converted input samples. */ if (init_converted_samples(&converted_input_samples, output_codec_context, input_frame->nb_samples)) goto cleanup; - /** - * Convert the input samples to the desired output sample format. - * This requires a temporary storage provided by converted_input_samples. - */ + /* Convert the input samples to the desired output sample format. + * This requires a temporary storage provided by converted_input_samples. */ if (convert_samples(input_frame->extended_data, converted_input_samples, - input_frame->nb_samples, resampler_context)) + input_frame->nb_samples, resample_context)) goto cleanup; - /** Add the converted input samples to the FIFO buffer for later processing. */ + /* Add the converted input samples to the FIFO buffer for later processing. */ if (add_samples_to_fifo(fifo, converted_input_samples, input_frame->nb_samples)) goto cleanup; @@ -550,6 +607,10 @@ static int read_decode_convert_and_store(AVAudioFifo *fifo, /** * Initialize one input frame for writing to the output file. * The frame will be exactly frame_size samples large. + * @param[out] frame Frame to be initialized + * @param output_codec_context Codec context of the output file + * @param frame_size Size of the frame + * @return Error code (0 if successful) */ static int init_output_frame(AVFrame **frame, AVCodecContext *output_codec_context, @@ -557,28 +618,24 @@ static int init_output_frame(AVFrame **frame, { int error; - /** Create a new frame to store the audio samples. */ + /* Create a new frame to store the audio samples. */ if (!(*frame = av_frame_alloc())) { fprintf(stderr, "Could not allocate output frame\n"); return AVERROR_EXIT; } - /** - * Set the frame's parameters, especially its size and format. + /* Set the frame's parameters, especially its size and format. * av_frame_get_buffer needs this to allocate memory for the * audio samples of the frame. * Default channel layouts based on the number of channels - * are assumed for simplicity. - */ + * are assumed for simplicity. */ (*frame)->nb_samples = frame_size; (*frame)->channel_layout = output_codec_context->channel_layout; (*frame)->format = output_codec_context->sample_fmt; (*frame)->sample_rate = output_codec_context->sample_rate; - /** - * Allocate the samples of the created frame. This call will make - * sure that the audio frame can hold as many samples as specified. - */ + /* Allocate the samples of the created frame. This call will make + * sure that the audio frame can hold as many samples as specified. */ if ((error = av_frame_get_buffer(*frame, 0)) < 0) { fprintf(stderr, "Could not allocate output frame samples (error '%s')\n", get_error_text(error)); @@ -589,30 +646,36 @@ static int init_output_frame(AVFrame **frame, return 0; } -/** Global timestamp for the audio frames */ +/* Global timestamp for the audio frames. */ static int64_t pts = 0; -/** Encode one frame worth of audio to the output file. */ +/** + * Encode one frame worth of audio to the output file. + * @param frame Samples to be encoded + * @param output_format_context Format context of the output file + * @param output_codec_context Codec context of the output file + * @param[out] data_present Indicates whether data has been + * decoded + * @return Error code (0 if successful) + */ static int encode_audio_frame(AVFrame *frame, AVFormatContext *output_format_context, AVCodecContext *output_codec_context, int *data_present) { - /** Packet used for temporary storage. */ + /* Packet used for temporary storage. */ AVPacket output_packet; int error; init_packet(&output_packet); - /** Set a timestamp based on the sample rate for the container. */ + /* Set a timestamp based on the sample rate for the container. */ if (frame) { frame->pts = pts; pts += frame->nb_samples; } - /** - * Encode the audio frame and store it in the temporary packet. - * The output audio stream encoder is used to do this. - */ + /* Encode the audio frame and store it in the temporary packet. + * The output audio stream encoder is used to do this. */ if ((error = avcodec_encode_audio2(output_codec_context, &output_packet, frame, data_present)) < 0) { fprintf(stderr, "Could not encode frame (error '%s')\n", @@ -621,7 +684,7 @@ static int encode_audio_frame(AVFrame *frame, return error; } - /** Write one audio frame from the temporary packet to the output file. */ + /* Write one audio frame from the temporary packet to the output file. */ if (*data_present) { if ((error = av_write_frame(output_format_context, &output_packet)) < 0) { fprintf(stderr, "Could not write frame (error '%s')\n", @@ -639,37 +702,37 @@ static int encode_audio_frame(AVFrame *frame, /** * Load one audio frame from the FIFO buffer, encode and write it to the * output file. + * @param fifo Buffer used for temporary storage + * @param output_format_context Format context of the output file + * @param output_codec_context Codec context of the output file + * @return Error code (0 if successful) */ static int load_encode_and_write(AVAudioFifo *fifo, AVFormatContext *output_format_context, AVCodecContext *output_codec_context) { - /** Temporary storage of the output samples of the frame written to the file. */ + /* Temporary storage of the output samples of the frame written to the file. */ AVFrame *output_frame; - /** - * Use the maximum number of possible samples per frame. + /* Use the maximum number of possible samples per frame. * If there is less than the maximum possible frame size in the FIFO - * buffer use this number. Otherwise, use the maximum possible frame size - */ + * buffer use this number. Otherwise, use the maximum possible frame size. */ const int frame_size = FFMIN(av_audio_fifo_size(fifo), output_codec_context->frame_size); int data_written; - /** Initialize temporary storage for one output frame. */ + /* Initialize temporary storage for one output frame. */ if (init_output_frame(&output_frame, output_codec_context, frame_size)) return AVERROR_EXIT; - /** - * Read as many samples from the FIFO buffer as required to fill the frame. - * The samples are stored in the frame temporarily. - */ + /* Read as many samples from the FIFO buffer as required to fill the frame. + * The samples are stored in the frame temporarily. */ if (av_audio_fifo_read(fifo, (void **)output_frame->data, frame_size) < frame_size) { fprintf(stderr, "Could not read data from FIFO\n"); av_frame_free(&output_frame); return AVERROR_EXIT; } - /** Encode one frame worth of audio samples. */ + /* Encode one frame worth of audio samples. */ if (encode_audio_frame(output_frame, output_format_context, output_codec_context, &data_written)) { av_frame_free(&output_frame); @@ -679,7 +742,11 @@ static int load_encode_and_write(AVAudioFifo *fifo, return 0; } -/** Write the trailer of the output file container. */ +/** + * Write the trailer of the output file container. + * @param output_format_context Format context of the output file + * @return Error code (0 if successful) + */ static int write_output_file_trailer(AVFormatContext *output_format_context) { int error; @@ -691,7 +758,6 @@ static int write_output_file_trailer(AVFormatContext *output_format_context) return 0; } -/** Convert an audio file to an AAC file in an MP4 container. */ int main(int argc, char **argv) { AVFormatContext *input_format_context = NULL, *output_format_context = NULL; @@ -700,89 +766,75 @@ int main(int argc, char **argv) AVAudioFifo *fifo = NULL; int ret = AVERROR_EXIT; - if (argc < 3) { + if (argc != 3) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); } - /** Register all codecs and formats so that they can be used. */ + /* Register all codecs and formats so that they can be used. */ av_register_all(); - /** Open the input file for reading. */ + /* Open the input file for reading. */ if (open_input_file(argv[1], &input_format_context, &input_codec_context)) goto cleanup; - /** Open the output file for writing. */ + /* Open the output file for writing. */ if (open_output_file(argv[2], input_codec_context, &output_format_context, &output_codec_context)) goto cleanup; - /** Initialize the resampler to be able to convert audio sample formats. */ + /* Initialize the resampler to be able to convert audio sample formats. */ if (init_resampler(input_codec_context, output_codec_context, &resample_context)) goto cleanup; - /** Initialize the FIFO buffer to store audio samples to be encoded. */ + /* Initialize the FIFO buffer to store audio samples to be encoded. */ if (init_fifo(&fifo, output_codec_context)) goto cleanup; - /** Write the header of the output file container. */ + /* Write the header of the output file container. */ if (write_output_file_header(output_format_context)) goto cleanup; - /** - * Loop as long as we have input samples to read or output samples - * to write; abort as soon as we have neither. - */ + /* Loop as long as we have input samples to read or output samples + * to write; abort as soon as we have neither. */ while (1) { - /** Use the encoder's desired frame size for processing. */ + /* Use the encoder's desired frame size for processing. */ const int output_frame_size = output_codec_context->frame_size; int finished = 0; - /** - * Make sure that there is one frame worth of samples in the FIFO + /* Make sure that there is one frame worth of samples in the FIFO * buffer so that the encoder can do its work. * Since the decoder's and the encoder's frame size may differ, we * need to FIFO buffer to store as many frames worth of input samples - * that they make up at least one frame worth of output samples. - */ + * that they make up at least one frame worth of output samples. */ while (av_audio_fifo_size(fifo) < output_frame_size) { - /** - * Decode one frame worth of audio samples, convert it to the - * output sample format and put it into the FIFO buffer. - */ + /* Decode one frame worth of audio samples, convert it to the + * output sample format and put it into the FIFO buffer. */ if (read_decode_convert_and_store(fifo, input_format_context, input_codec_context, output_codec_context, resample_context, &finished)) goto cleanup; - /** - * If we are at the end of the input file, we continue - * encoding the remaining audio samples to the output file. - */ + /* If we are at the end of the input file, we continue + * encoding the remaining audio samples to the output file. */ if (finished) break; } - /** - * If we have enough samples for the encoder, we encode them. + /* If we have enough samples for the encoder, we encode them. * At the end of the file, we pass the remaining samples to - * the encoder. - */ + * the encoder. */ while (av_audio_fifo_size(fifo) >= output_frame_size || (finished && av_audio_fifo_size(fifo) > 0)) - /** - * Take one frame worth of audio samples from the FIFO buffer, - * encode it and write it to the output file. - */ + /* Take one frame worth of audio samples from the FIFO buffer, + * encode it and write it to the output file. */ if (load_encode_and_write(fifo, output_format_context, output_codec_context)) goto cleanup; - /** - * If we are at the end of the input file and have encoded - * all remaining samples, we can exit this loop and finish. - */ + /* If we are at the end of the input file and have encoded + * all remaining samples, we can exit this loop and finish. */ if (finished) { int data_written; - /** Flush the encoder as it may have delayed frames. */ + /* Flush the encoder as it may have delayed frames. */ do { if (encode_audio_frame(NULL, output_format_context, output_codec_context, &data_written)) @@ -792,7 +844,7 @@ int main(int argc, char **argv) } } - /** Write the trailer of the output file container. */ + /* Write the trailer of the output file container. */ if (write_output_file_trailer(output_format_context)) goto cleanup; ret = 0; From 193b09189004ede4a6998e69192d1a9f63602088 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 31 Mar 2017 19:04:56 +0200 Subject: [PATCH 0137/2557] thread: Define ff_mutex_* macros as stub functions when threads are disabled Silences a bunch of "statement with no effect" warnings with threads disabled. --- libavutil/thread.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavutil/thread.h b/libavutil/thread.h index cf0fbdda5f347..ac76bb88e29aa 100644 --- a/libavutil/thread.h +++ b/libavutil/thread.h @@ -48,10 +48,10 @@ #define AVMutex char -#define ff_mutex_init(mutex, attr) (0) -#define ff_mutex_lock(mutex) (0) -#define ff_mutex_unlock(mutex) (0) -#define ff_mutex_destroy(mutex) (0) +static inline int ff_mutex_init(AVMutex *mutex, const void *attr){ return 0; } +static inline int ff_mutex_lock(AVMutex *mutex){ return 0; } +static inline int ff_mutex_unlock(AVMutex *mutex){ return 0; } +static inline int ff_mutex_destroy(AVMutex *mutex){ return 0; } #define AVOnce char #define AV_ONCE_INIT 0 From 50a1c66cf6ab7eb683daaa9e2da3869fa3a54609 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 30 Mar 2017 16:56:28 +0200 Subject: [PATCH 0138/2557] ac3_parser: add a public function for parsing the data required by the demuxer Make the current semi-public avpriv_ac3_parse_header() private to lavc. Signed-off-by: Diego Biurrun --- libavcodec/Makefile | 9 ++++---- libavcodec/ac3_parser.c | 35 ++++++++++++++++++++++++++-- libavcodec/ac3_parser.h | 17 +++++--------- libavcodec/ac3_parser_internal.h | 39 ++++++++++++++++++++++++++++++++ libavcodec/ac3dec.c | 4 ++-- libavcodec/eac3dec.c | 1 - libavformat/ac3dec.c | 19 +++++++++------- 7 files changed, 96 insertions(+), 28 deletions(-) create mode 100644 libavcodec/ac3_parser_internal.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index ec62f514a77db..a82210d89fe51 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1,7 +1,8 @@ NAME = avcodec DESC = Libav codec library -HEADERS = avcodec.h \ +HEADERS = ac3_parser.h \ + avcodec.h \ avfft.h \ d3d11va.h \ dirac.h \ @@ -14,7 +15,8 @@ HEADERS = avcodec.h \ version.h \ vorbis_parser.h \ -OBJS = allcodecs.o \ +OBJS = ac3_parser.o \ + allcodecs.o \ avpacket.o \ avpicture.o \ bitstream.o \ @@ -719,8 +721,7 @@ OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \ aacadtsdec.o mpeg4audio.o -OBJS-$(CONFIG_AC3_PARSER) += ac3_parser.o ac3tab.o \ - aac_ac3_parser.o +OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o diff --git a/libavcodec/ac3_parser.c b/libavcodec/ac3_parser.c index 970484810b4cc..53189e0d4ed79 100644 --- a/libavcodec/ac3_parser.c +++ b/libavcodec/ac3_parser.c @@ -20,15 +20,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + #include "libavutil/channel_layout.h" #include "parser.h" #include "ac3_parser.h" +#include "ac3_parser_internal.h" #include "aac_ac3_parser.h" #include "get_bits.h" #define AC3_HEADER_SIZE 7 +#if CONFIG_AC3_PARSER static const uint8_t eac3_blocks[4] = { 1, 2, 3, 6 @@ -47,7 +51,7 @@ static const uint8_t center_levels[4] = { 4, 5, 6, 5 }; static const uint8_t surround_levels[4] = { 4, 6, 7, 6 }; -int avpriv_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr) +int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr) { int frame_size_code; @@ -144,6 +148,24 @@ int avpriv_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr) return 0; } +int av_ac3_parse_header(const uint8_t *buf, size_t size, + uint8_t *bitstream_id, uint16_t *frame_size) +{ + GetBitContext gb; + AC3HeaderInfo hdr; + int err; + + init_get_bits8(&gb, buf, size); + err = ff_ac3_parse_header(&gb, &hdr); + if (err < 0) + return AVERROR_INVALIDDATA; + + *bitstream_id = hdr.bitstream_id; + *frame_size = hdr.frame_size; + + return 0; +} + static int ac3_sync(uint64_t state, AACAC3ParseContext *hdr_info, int *need_next_header, int *new_frame_start) { @@ -156,7 +178,7 @@ static int ac3_sync(uint64_t state, AACAC3ParseContext *hdr_info, GetBitContext gbc; init_get_bits(&gbc, tmp.u8+8-AC3_HEADER_SIZE, 54); - err = avpriv_ac3_parse_header(&gbc, &hdr); + err = ff_ac3_parse_header(&gbc, &hdr); if(err < 0) return 0; @@ -195,3 +217,12 @@ AVCodecParser ff_ac3_parser = { .parser_parse = ff_aac_ac3_parse, .parser_close = ff_parse_close, }; + +#else + +int av_ac3_parse_header(const uint8_t *buf, size_t size, + uint8_t *bitstream_id, uint16_t *frame_size) +{ + return AVERROR(ENOSYS); +} +#endif diff --git a/libavcodec/ac3_parser.h b/libavcodec/ac3_parser.h index 9322550ea5f15..f78c461041a50 100644 --- a/libavcodec/ac3_parser.h +++ b/libavcodec/ac3_parser.h @@ -23,19 +23,14 @@ #ifndef AVCODEC_AC3_PARSER_H #define AVCODEC_AC3_PARSER_H -#include "ac3.h" -#include "get_bits.h" +#include +#include /** - * Parse AC-3 frame header. - * Parse the header up to the lfeon element, which is the first 52 or 54 bits - * depending on the audio coding mode. - * @param[in] gbc BitContext containing the first 54 bits of the frame. - * @param[out] hdr Pointer to struct where header info is written. - * @return Returns 0 on success, -1 if there is a sync word mismatch, - * -2 if the bsid (version) element is invalid, -3 if the fscod (sample rate) - * element is invalid, or -4 if the frmsizecod (bit rate) element is invalid. + * Extract the bitstream ID and the frame size from AC-3 data. */ -int avpriv_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr); +int av_ac3_parse_header(const uint8_t *buf, size_t size, + uint8_t *bitstream_id, uint16_t *frame_size); + #endif /* AVCODEC_AC3_PARSER_H */ diff --git a/libavcodec/ac3_parser_internal.h b/libavcodec/ac3_parser_internal.h new file mode 100644 index 0000000000000..5e305e8352a17 --- /dev/null +++ b/libavcodec/ac3_parser_internal.h @@ -0,0 +1,39 @@ +/* + * AC-3 parser internal code + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AC3_PARSER_INTERNAL_H +#define AVCODEC_AC3_PARSER_INTERNAL_H + +#include "ac3.h" +#include "get_bits.h" + +/** + * Parse AC-3 frame header. + * Parse the header up to the lfeon element, which is the first 52 or 54 bits + * depending on the audio coding mode. + * @param[in] gbc BitContext containing the first 54 bits of the frame. + * @param[out] hdr Pointer to struct where header info is written. + * @return Returns 0 on success, -1 if there is a sync word mismatch, + * -2 if the bsid (version) element is invalid, -3 if the fscod (sample rate) + * element is invalid, or -4 if the frmsizecod (bit rate) element is invalid. + */ +int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr); + +#endif /* AVCODEC_AC3_PARSER_INTERNAL_H */ diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index ad50552ec1b09..4be0f1f4117b4 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -36,7 +36,7 @@ #include "bswapdsp.h" #include "internal.h" #include "aac_ac3_parser.h" -#include "ac3_parser.h" +#include "ac3_parser_internal.h" #include "ac3dec.h" #include "ac3dec_data.h" #include "kbdwin.h" @@ -270,7 +270,7 @@ static int parse_frame_header(AC3DecodeContext *s) AC3HeaderInfo hdr; int err; - err = avpriv_ac3_parse_header(&s->gbc, &hdr); + err = ff_ac3_parse_header(&s->gbc, &hdr); if (err) return err; diff --git a/libavcodec/eac3dec.c b/libavcodec/eac3dec.c index fe52d27123667..89db7d38bca10 100644 --- a/libavcodec/eac3dec.c +++ b/libavcodec/eac3dec.c @@ -48,7 +48,6 @@ #include "internal.h" #include "aac_ac3_parser.h" #include "ac3.h" -#include "ac3_parser.h" #include "ac3dec.h" #include "ac3dec_data.h" #include "eac3_data.h" diff --git a/libavformat/ac3dec.c b/libavformat/ac3dec.c index 4ceffa54ddbf8..7a868056c70b7 100644 --- a/libavformat/ac3dec.c +++ b/libavformat/ac3dec.c @@ -28,8 +28,6 @@ static int ac3_eac3_probe(AVProbeData *p, enum AVCodecID expected_codec_id) { int max_frames, first_frames = 0, frames; uint8_t *buf, *buf2, *end; - AC3HeaderInfo hdr; - GetBitContext gbc; enum AVCodecID codec_id = AV_CODEC_ID_AC3; max_frames = 0; @@ -40,15 +38,20 @@ static int ac3_eac3_probe(AVProbeData *p, enum AVCodecID expected_codec_id) buf2 = buf; for(frames = 0; buf2 < end; frames++) { - init_get_bits(&gbc, buf2, 54); - if(avpriv_ac3_parse_header(&gbc, &hdr) < 0) + uint8_t bitstream_id; + uint16_t frame_size; + int ret; + + ret = av_ac3_parse_header(buf2, end - buf2, &bitstream_id, + &frame_size); + if (ret < 0) break; - if(buf2 + hdr.frame_size > end || - av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, buf2 + 2, hdr.frame_size - 2)) + if (buf2 + frame_size > end || + av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, buf2 + 2, frame_size - 2)) break; - if (hdr.bitstream_id > 10) + if (bitstream_id > 10) codec_id = AV_CODEC_ID_EAC3; - buf2 += hdr.frame_size; + buf2 += frame_size; } max_frames = FFMAX(max_frames, frames); if(buf == p->buf) From 89d9869d2491d4209d707a8e7f29c58227ae5a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= Date: Wed, 12 Apr 2017 09:29:44 +0200 Subject: [PATCH 0139/2557] hevc: Add NEON 16x16 IDCT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The speedup vs C code is around 6-13x. Signed-off-by: Martin Storsjö --- libavcodec/arm/hevc_idct.S | 197 ++++++++++++++++++++++++++++++ libavcodec/arm/hevcdsp_init_arm.c | 4 + 2 files changed, 201 insertions(+) diff --git a/libavcodec/arm/hevc_idct.S b/libavcodec/arm/hevc_idct.S index 4124fc8226b0e..156d4765f0dbd 100644 --- a/libavcodec/arm/hevc_idct.S +++ b/libavcodec/arm/hevc_idct.S @@ -222,7 +222,204 @@ function ff_hevc_idct_8x8_\bitdepth\()_neon, export=1 endfunc .endm +.macro butterfly e, o, tmp_p, tmp_m + vadd.s32 \tmp_p, \e, \o + vsub.s32 \tmp_m, \e, \o +.endm + +.macro tr16_8x4 in0, in1, in2, in3, in4, in5, in6, in7 + tr_4x4_8 \in0, \in2, \in4, \in6, q8, q9, q10, q11, q12, q13, q14, q15 + + vmull.s16 q12, \in1, \in0[0] + vmull.s16 q13, \in1, \in0[1] + vmull.s16 q14, \in1, \in0[2] + vmull.s16 q15, \in1, \in0[3] + sum_sub q12, \in3, \in0[1], + + sum_sub q13, \in3, \in0[3], - + sum_sub q14, \in3, \in0[0], - + sum_sub q15, \in3, \in0[2], - + + sum_sub q12, \in5, \in0[2], + + sum_sub q13, \in5, \in0[0], - + sum_sub q14, \in5, \in0[3], + + sum_sub q15, \in5, \in0[1], + + + sum_sub q12, \in7, \in0[3], + + sum_sub q13, \in7, \in0[2], - + sum_sub q14, \in7, \in0[1], + + sum_sub q15, \in7, \in0[0], - + + butterfly q8, q12, q0, q7 + butterfly q9, q13, q1, q6 + butterfly q10, q14, q2, q5 + butterfly q11, q15, q3, q4 + add r4, sp, #512 + vst1.s16 {q0-q1}, [r4, :128]! + vst1.s16 {q2-q3}, [r4, :128]! + vst1.s16 {q4-q5}, [r4, :128]! + vst1.s16 {q6-q7}, [r4, :128] +.endm + +.macro load16 in0, in1, in2, in3, in4, in5, in6, in7 + vld1.s16 {\in0}, [r1, :64], r2 + vld1.s16 {\in1}, [r3, :64], r2 + vld1.s16 {\in2}, [r1, :64], r2 + vld1.s16 {\in3}, [r3, :64], r2 + vld1.s16 {\in4}, [r1, :64], r2 + vld1.s16 {\in5}, [r3, :64], r2 + vld1.s16 {\in6}, [r1, :64], r2 + vld1.s16 {\in7}, [r3, :64], r2 +.endm + +.macro add_member in, t0, t1, t2, t3, t4, t5, t6, t7, op0, op1, op2, op3, op4, op5, op6, op7 + sum_sub q5, \in, \t0, \op0 + sum_sub q6, \in, \t1, \op1 + sum_sub q7, \in, \t2, \op2 + sum_sub q8, \in, \t3, \op3 + sum_sub q9, \in, \t4, \op4 + sum_sub q10, \in, \t5, \op5 + sum_sub q11, \in, \t6, \op6 + sum_sub q12, \in, \t7, \op7 +.endm + +.macro butterfly16 in0, in1, in2, in3, in4, in5, in6, in7 + vadd.s32 q4, \in0, \in1 + vsub.s32 \in0, \in0, \in1 + vadd.s32 \in1, \in2, \in3 + vsub.s32 \in2, \in2, \in3 + vadd.s32 \in3, \in4, \in5 + vsub.s32 \in4, \in4, \in5 + vadd.s32 \in5, \in6, \in7 + vsub.s32 \in6, \in6, \in7 +.endm + +.macro store16 in0, in1, in2, in3, in4, in5, in6, in7 + vst1.s16 \in0, [r1, :64], r2 + vst1.s16 \in1, [r3, :64], r4 + vst1.s16 \in2, [r1, :64], r2 + vst1.s16 \in3, [r3, :64], r4 + vst1.s16 \in4, [r1, :64], r2 + vst1.s16 \in5, [r3, :64], r4 + vst1.s16 \in6, [r1, :64], r2 + vst1.s16 \in7, [r3, :64], r4 +.endm + +.macro scale out0, out1, out2, out3, out4, out5, out6, out7, in0, in1, in2, in3, in4, in5, in6, in7, shift + vqrshrn.s32 \out0, \in0, \shift + vqrshrn.s32 \out1, \in1, \shift + vqrshrn.s32 \out2, \in2, \shift + vqrshrn.s32 \out3, \in3, \shift + vqrshrn.s32 \out4, \in4, \shift + vqrshrn.s32 \out5, \in5, \shift + vqrshrn.s32 \out6, \in6, \shift + vqrshrn.s32 \out7, \in7, \shift +.endm + +.macro tr_16x4 name, shift +function func_tr_16x4_\name + mov r1, r5 + add r3, r5, #64 + mov r2, #128 + load16 d0, d1, d2, d3, d4, d5, d6, d7 + movrel r1, trans + + tr16_8x4 d0, d1, d2, d3, d4, d5, d6, d7 + + add r1, r5, #32 + add r3, r5, #(64 + 32) + mov r2, #128 + load16 d8, d9, d2, d3, d4, d5, d6, d7 + movrel r1, trans + 16 + vld1.s16 {q0}, [r1, :128] + vmull.s16 q5, d8, d0[0] + vmull.s16 q6, d8, d0[1] + vmull.s16 q7, d8, d0[2] + vmull.s16 q8, d8, d0[3] + vmull.s16 q9, d8, d1[0] + vmull.s16 q10, d8, d1[1] + vmull.s16 q11, d8, d1[2] + vmull.s16 q12, d8, d1[3] + + add_member d9, d0[1], d1[0], d1[3], d1[1], d0[2], d0[0], d0[3], d1[2], +, +, +, -, -, -, -, - + add_member d2, d0[2], d1[3], d0[3], d0[1], d1[2], d1[0], d0[0], d1[1], +, +, -, -, -, +, +, + + add_member d3, d0[3], d1[1], d0[1], d1[3], d0[0], d1[2], d0[2], d1[0], +, -, -, +, +, +, -, - + add_member d4, d1[0], d0[2], d1[2], d0[0], d1[3], d0[1], d1[1], d0[3], +, -, -, +, -, -, +, + + add_member d5, d1[1], d0[0], d1[0], d1[2], d0[1], d0[3], d1[3], d0[2], +, -, +, +, -, +, +, - + add_member d6, d1[2], d0[3], d0[0], d0[2], d1[1], d1[3], d1[0], d0[1], +, -, +, -, +, +, -, + + add_member d7, d1[3], d1[2], d1[1], d1[0], d0[3], d0[2], d0[1], d0[0], +, -, +, -, +, -, +, - + + add r4, sp, #512 + vld1.s16 {q0-q1}, [r4, :128]! + vld1.s16 {q2-q3}, [r4, :128]! + + butterfly16 q0, q5, q1, q6, q2, q7, q3, q8 + scale d26, d27, d28, d29, d30, d31, d16, d17, q4, q0, q5, q1, q6, q2, q7, q3, \shift + transpose8_4x4 d26, d28, d30, d16 + transpose8_4x4 d17, d31, d29, d27 + mov r1, r6 + add r3, r6, #(24 +3*32) + mov r2, #32 + mov r4, #-32 + store16 d26, d27, d28, d29, d30, d31, d16, d17 + + add r4, sp, #576 + vld1.s16 {q0-q1}, [r4, :128]! + vld1.s16 {q2-q3}, [r4, :128] + butterfly16 q0, q9, q1, q10, q2, q11, q3, q12 + scale d26, d27, d28, d29, d30, d31, d8, d9, q4, q0, q9, q1, q10, q2, q11, q3, \shift + transpose8_4x4 d26, d28, d30, d8 + transpose8_4x4 d9, d31, d29, d27 + + add r1, r6, #8 + add r3, r6, #(16 + 3 * 32) + mov r2, #32 + mov r4, #-32 + store16 d26, d27, d28, d29, d30, d31, d8, d9 + + bx lr +endfunc +.endm + +.macro idct_16x16 bitdepth +function ff_hevc_idct_16x16_\bitdepth\()_neon, export=1 +@r0 - coeffs + push {r4-r7, lr} + vpush {q4-q7} + + @ Align the stack, allocate a temp buffer +T mov r7, sp +T and r7, r7, #15 +A and r7, sp, #15 + add r7, r7, #640 + sub sp, sp, r7 + +.irp i, 0, 1, 2, 3 + add r5, r0, #(8 * \i) + add r6, sp, #(8 * \i * 16) + bl func_tr_16x4_firstpass +.endr + +.irp i, 0, 1, 2, 3 + add r5, sp, #(8 * \i) + add r6, r0, #(8 * \i * 16) + bl func_tr_16x4_secondpass_\bitdepth +.endr + + add sp, sp, r7 + + vpop {q4-q7} + pop {r4-r7, pc} +endfunc +.endm + +tr_16x4 firstpass, 7 +tr_16x4 secondpass_8, 20 - 8 +tr_16x4 secondpass_10, 20 - 10 +.ltorg + idct_4x4 8 idct_4x4 10 idct_8x8 8 idct_8x8 10 +idct_16x16 8 +idct_16x16 10 diff --git a/libavcodec/arm/hevcdsp_init_arm.c b/libavcodec/arm/hevcdsp_init_arm.c index 1e984e61886c8..e61587f4e3e46 100644 --- a/libavcodec/arm/hevcdsp_init_arm.c +++ b/libavcodec/arm/hevcdsp_init_arm.c @@ -27,8 +27,10 @@ void ff_hevc_idct_4x4_8_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_8x8_8_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_16x16_8_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_4x4_10_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_8x8_10_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_16x16_10_neon(int16_t *coeffs, int col_limit); av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, int bit_depth) { @@ -38,10 +40,12 @@ av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, int bit_depth) if (bit_depth == 8) { c->idct[0] = ff_hevc_idct_4x4_8_neon; c->idct[1] = ff_hevc_idct_8x8_8_neon; + c->idct[2] = ff_hevc_idct_16x16_8_neon; } if (bit_depth == 10) { c->idct[0] = ff_hevc_idct_4x4_10_neon; c->idct[1] = ff_hevc_idct_8x8_10_neon; + c->idct[2] = ff_hevc_idct_16x16_10_neon; } } } From 95a8a03a191204c3ca5c8cf6b69ab166765d5ff3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 6 Feb 2017 09:17:29 +0100 Subject: [PATCH 0140/2557] Add FM Screen Capture Codec decoder Signed-off-by: Paul B Mahol Signed-off-by: Diego Biurrun --- Changelog | 1 + doc/general.texi | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/codec_desc.c | 7 + libavcodec/fmvc.c | 636 ++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- libavformat/riff.c | 1 + 9 files changed, 650 insertions(+), 1 deletion(-) create mode 100644 libavcodec/fmvc.c diff --git a/Changelog b/Changelog index b3aed3cd7e578..dccf173741fee 100644 --- a/Changelog +++ b/Changelog @@ -13,6 +13,7 @@ version : --x86asmexe=yasm to configure to restore the old behavior. - Cineform HD decoder - VP9 superframe split/merge bitstream filters +- FM Screen Capture Codec decoder version 12: diff --git a/doc/general.texi b/doc/general.texi index b21195bde2faa..b1a42c50f8fd6 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -667,6 +667,7 @@ following image formats are supported: @item Flash Screen Video v2 @tab @tab X @item Flash Video (FLV) @tab X @tab X @tab Sorenson H.263 used in Flash +@item FM Screen Capture Codec @tab @tab X @item Forward Uncompressed @tab @tab X @item Fraps @tab @tab X @item Go2Meeting @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index a82210d89fe51..e835133842867 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -235,6 +235,7 @@ OBJS-$(CONFIG_FLASHSV_DECODER) += flashsv.o OBJS-$(CONFIG_FLASHSV_ENCODER) += flashsvenc.o OBJS-$(CONFIG_FLASHSV2_DECODER) += flashsv.o OBJS-$(CONFIG_FLIC_DECODER) += flicvideo.o +OBJS-$(CONFIG_FMVC_DECODER) += fmvc.o OBJS-$(CONFIG_FOURXM_DECODER) += 4xm.o OBJS-$(CONFIG_FRAPS_DECODER) += fraps.o OBJS-$(CONFIG_FRWU_DECODER) += frwu.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 36f839c852e22..20b3b35b9094b 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -161,6 +161,7 @@ void avcodec_register_all(void) REGISTER_DECODER(FLASHSV2, flashsv2); REGISTER_DECODER(FLIC, flic); REGISTER_ENCDEC (FLV, flv); + REGISTER_DECODER(FMVC, fmvc); REGISTER_DECODER(FOURXM, fourxm); REGISTER_DECODER(FRAPS, fraps); REGISTER_DECODER(FRWU, frwu); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 1c58fe2d689c1..4cf446faf923d 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -408,6 +408,7 @@ enum AVCodecID { AV_CODEC_ID_AV1, AV_CODEC_ID_PIXLET, AV_CODEC_ID_CFHD, + AV_CODEC_ID_FMVC, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 7103b5890a994..ed97420d4209c 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1210,6 +1210,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Apple Pixlet"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_FMVC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "fmvc", + .long_name = NULL_IF_CONFIG_SMALL("FM Screen Capture Codec"), + .props = AV_CODEC_PROP_LOSSLESS, + }, /* image codecs */ { diff --git a/libavcodec/fmvc.c b/libavcodec/fmvc.c new file mode 100644 index 0000000000000..64136e392dc9e --- /dev/null +++ b/libavcodec/fmvc.c @@ -0,0 +1,636 @@ +/* + * FM Screen Capture Codec decoder + * + * Copyright (c) 2017 Paul B Mahol + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +#define BLOCK_HEIGHT 112u +#define BLOCK_WIDTH 84u + +typedef struct InterBlock { + int w, h; + int size; + int xor; +} InterBlock; + +typedef struct FMVCContext { + GetByteContext gb; + PutByteContext pb; + uint8_t *buffer; + size_t buffer_size; + uint8_t *pbuffer; + size_t pbuffer_size; + ptrdiff_t stride; + int bpp; + int yb, xb; + InterBlock *blocks; + unsigned nb_blocks; +} FMVCContext; + +static int decode_type2(GetByteContext *gb, PutByteContext *pb) +{ + unsigned repeat = 0, first = 1, opcode; + int i, len, pos; + + while (bytestream2_get_bytes_left(gb) > 0) { + GetByteContext gbc; + + while (bytestream2_get_bytes_left(gb) > 0) { + if (first) { + first = 0; + if (bytestream2_peek_byte(gb) > 17) { + len = bytestream2_get_byte(gb) - 17; + if (len < 4) { + do { + bytestream2_put_byte(pb, bytestream2_get_byte(gb)); + --len; + } while (len); + opcode = bytestream2_peek_byte(gb); + continue; + } else { + do { + bytestream2_put_byte(pb, bytestream2_get_byte(gb)); + --len; + } while (len); + opcode = bytestream2_peek_byte(gb); + if (opcode < 0x10) { + bytestream2_skip(gb, 1); + pos = - (opcode >> 2) - 4 * bytestream2_get_byte(gb) - 2049; + + bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start); + bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET); + + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + len = opcode & 3; + if (!len) { + repeat = 1; + } else { + do { + bytestream2_put_byte(pb, bytestream2_get_byte(gb)); + --len; + } while (len); + opcode = bytestream2_peek_byte(gb); + } + continue; + } + } + repeat = 0; + } + repeat = 1; + } + if (repeat) { + repeat = 0; + opcode = bytestream2_peek_byte(gb); + if (opcode < 0x10) { + bytestream2_skip(gb, 1); + if (!opcode) { + if (!bytestream2_peek_byte(gb)) { + do { + bytestream2_skip(gb, 1); + opcode += 255; + } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0); + } + opcode += bytestream2_get_byte(gb) + 15; + } + bytestream2_put_le32(pb, bytestream2_get_le32(gb)); + for (i = opcode - 1; i > 0; --i) + bytestream2_put_byte(pb, bytestream2_get_byte(gb)); + opcode = bytestream2_peek_byte(gb); + if (opcode < 0x10) { + bytestream2_skip(gb, 1); + pos = - (opcode >> 2) - 4 * bytestream2_get_byte(gb) - 2049; + + bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start); + bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET); + + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + len = opcode & 3; + if (!len) { + repeat = 1; + } else { + do { + bytestream2_put_byte(pb, bytestream2_get_byte(gb)); + --len; + } while (len); + opcode = bytestream2_peek_byte(gb); + } + continue; + } + } + } + + if (opcode >= 0x40) { + bytestream2_skip(gb, 1); + pos = - ((opcode >> 2) & 7) - 1 - 8 * bytestream2_get_byte(gb); + len = (opcode >> 5) - 1; + + bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start); + bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET); + + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + do { + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + --len; + } while (len); + + len = opcode & 3; + + if (!len) { + repeat = 1; + } else { + do { + bytestream2_put_byte(pb, bytestream2_get_byte(gb)); + --len; + } while (len); + opcode = bytestream2_peek_byte(gb); + } + continue; + } else if (opcode < 0x20) { + break; + } + len = opcode & 0x1F; + bytestream2_skip(gb, 1); + if (!len) { + if (!bytestream2_peek_byte(gb)) { + do { + bytestream2_skip(gb, 1); + len += 255; + } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0); + } + len += bytestream2_get_byte(gb) + 31; + } + i = bytestream2_get_le16(gb); + pos = - (i >> 2) - 1; + + bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start); + bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET); + + if (len < 6 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) { + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + do { + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + --len; + } while (len); + } else { + bytestream2_put_le32(pb, bytestream2_get_le32(&gbc)); + for (len = len - 2; len; --len) + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + } + len = i & 3; + if (!len) { + repeat = 1; + } else { + do { + bytestream2_put_byte(pb, bytestream2_get_byte(gb)); + --len; + } while (len); + opcode = bytestream2_peek_byte(gb); + } + } + bytestream2_skip(gb, 1); + if (opcode < 0x10) { + pos = -(opcode >> 2) - 1 - 4 * bytestream2_get_byte(gb); + + bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start); + bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET); + + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + len = opcode & 3; + if (!len) { + repeat = 1; + } else { + do { + bytestream2_put_byte(pb, bytestream2_get_byte(gb)); + --len; + } while (len); + opcode = bytestream2_peek_byte(gb); + } + continue; + } + len = opcode & 7; + if (!len) { + if (!bytestream2_peek_byte(gb)) { + do { + bytestream2_skip(gb, 1); + len += 255; + } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0); + } + len += bytestream2_get_byte(gb) + 7; + } + i = bytestream2_get_le16(gb); + pos = bytestream2_tell_p(pb) - 2048 * (opcode & 8); + pos = pos - (i >> 2); + if (pos == bytestream2_tell_p(pb)) + break; + + pos = pos - 0x4000; + bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start); + bytestream2_seek(&gbc, pos, SEEK_SET); + + if (len < 6 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) { + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + do { + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + --len; + } while (len); + } else { + bytestream2_put_le32(pb, bytestream2_get_le32(&gbc)); + for (len = len - 2; len; --len) + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + } + + len = i & 3; + if (!len) { + repeat = 1; + } else { + do { + bytestream2_put_byte(pb, bytestream2_get_byte(gb)); + --len; + } while (len); + opcode = bytestream2_peek_byte(gb); + } + } + + return 0; +} + +static int decode_type1(GetByteContext *gb, PutByteContext *pb) +{ + unsigned opcode, len; + int high = 0; + int i, pos; + + while (bytestream2_get_bytes_left(gb) > 0) { + GetByteContext gbc; + + while (bytestream2_get_bytes_left(gb) > 0) { + while (bytestream2_get_bytes_left(gb) > 0) { + opcode = bytestream2_get_byte(gb); + high = opcode >= 0x20; + if (high) + break; + if (opcode) + break; + opcode = bytestream2_get_byte(gb); + if (opcode < 0xF8) { + opcode += 32; + break; + } + i = opcode - 0xF8; + if (i) { + len = 256; + do { + len *= 2; + --i; + } while (i); + } else { + len = 280; + } + do { + bytestream2_put_le32(pb, bytestream2_get_le32(gb)); + bytestream2_put_le32(pb, bytestream2_get_le32(gb)); + len -= 8; + } while (len && bytestream2_get_bytes_left(gb) > 0); + } + + if (!high) { + do { + bytestream2_put_byte(pb, bytestream2_get_byte(gb)); + --opcode; + } while (opcode && bytestream2_get_bytes_left(gb) > 0); + + while (bytestream2_get_bytes_left(gb) > 0) { + GetByteContext gbc; + + opcode = bytestream2_get_byte(gb); + if (opcode >= 0x20) + break; + bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start); + + pos = -(opcode | 32 * bytestream2_get_byte(gb)) - 1; + bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(gb)); + } + } + high = 0; + if (opcode < 0x40) + break; + bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start); + pos = (-((opcode & 0x1F) | 32 * bytestream2_get_byte(gb)) - 1); + bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + len = (opcode >> 5) - 1; + do { + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + --len; + } while (len && bytestream2_get_bytes_left(&gbc) > 0); + } + len = opcode & 0x1F; + if (!len) { + if (!bytestream2_peek_byte(gb)) { + do { + bytestream2_skip(gb, 1); + len += 255; + } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0); + } + len += bytestream2_get_byte(gb) + 31; + } + pos = -bytestream2_get_byte(gb); + bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start); + bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos - (bytestream2_get_byte(gb) << 8), SEEK_SET); + if (bytestream2_tell_p(pb) == bytestream2_tell(&gbc)) + break; + if (len < 5 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) { + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + } else { + bytestream2_put_le32(pb, bytestream2_get_le32(&gbc)); + len--; + } + do { + bytestream2_put_byte(pb, bytestream2_get_byte(&gbc)); + len--; + } while (len && bytestream2_get_bytes_left(&gbc) > 0); + } + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + FMVCContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + PutByteContext *pb = &s->pb; + AVFrame *frame = data; + int ret, y, x; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + bytestream2_init(gb, avpkt->data, avpkt->size); + bytestream2_skip(gb, 2); + + frame->key_frame = !!bytestream2_get_le16(gb); + frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + + if (frame->key_frame) { + const uint8_t *src; + unsigned type, size; + uint8_t *dst; + + type = bytestream2_get_le16(gb); + size = bytestream2_get_le16(gb); + if (size > bytestream2_get_bytes_left(gb)) + return AVERROR_INVALIDDATA; + + bytestream2_init_writer(pb, s->buffer, s->buffer_size); + if (type == 1) { + decode_type1(gb, pb); + } else if (type == 2){ + decode_type2(gb, pb); + } else { + avpriv_report_missing_feature(avctx, "Compression type %d", type); + return AVERROR_PATCHWELCOME; + } + + src = s->buffer; + dst = frame->data[0] + (avctx->height - 1) * frame->linesize[0]; + for (y = 0; y < avctx->height; y++) { + memcpy(dst, src, avctx->width * s->bpp); + dst -= frame->linesize[0]; + src += avctx->width * s->bpp; + } + } else { + unsigned block, nb_blocks; + int type, k, l; + uint8_t *ssrc, *ddst; + const uint32_t *src; + uint32_t *dst; + + for (block = 0; block < s->nb_blocks; block++) + s->blocks[block].xor = 0; + + nb_blocks = bytestream2_get_le16(gb); + if (nb_blocks > s->nb_blocks) + return AVERROR_INVALIDDATA; + + bytestream2_init_writer(pb, s->pbuffer, s->pbuffer_size); + + type = bytestream2_get_le16(gb); + for (block = 0; block < nb_blocks; block++) { + unsigned size, offset; + int start = 0; + + offset = bytestream2_get_le16(gb); + if (offset > s->nb_blocks) + return AVERROR_INVALIDDATA; + + size = bytestream2_get_le16(gb); + if (size > bytestream2_get_bytes_left(gb)) + return AVERROR_INVALIDDATA; + + start = bytestream2_tell_p(pb); + if (type == 1) { + decode_type1(gb, pb); + } else if (type == 2){ + decode_type2(gb, pb); + } else { + avpriv_report_missing_feature(avctx, "Compression type %d", type); + return AVERROR_PATCHWELCOME; + } + + if (s->blocks[offset].size * 4 != bytestream2_tell_p(pb) - start) + return AVERROR_INVALIDDATA; + + s->blocks[offset].xor = 1; + } + + src = (const uint32_t *)s->pbuffer; + dst = (uint32_t *)s->buffer; + + for (block = 0, y = 0; y < s->yb; y++) { + int block_h = s->blocks[block].h; + uint32_t *rect = dst; + + for (x = 0; x < s->xb; x++) { + int block_w = s->blocks[block].w; + uint32_t *row = dst; + + block_h = s->blocks[block].h; + if (s->blocks[block].xor) { + for (k = 0; k < block_h; k++) { + uint32_t *column = dst; + for (l = 0; l < block_w; l++) + *dst++ ^= *src++; + dst = &column[s->stride]; + } + } + dst = &row[block_w]; + ++block; + } + dst = &rect[block_h * s->stride]; + } + + ssrc = s->buffer; + ddst = frame->data[0] + (avctx->height - 1) * frame->linesize[0]; + for (y = 0; y < avctx->height; y++) { + memcpy(ddst, ssrc, avctx->width * s->bpp); + ddst -= frame->linesize[0]; + ssrc += avctx->width * s->bpp; + } + } + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + FMVCContext *s = avctx->priv_data; + int i, j, m, block = 0, h = BLOCK_HEIGHT, w = BLOCK_WIDTH; + + switch (avctx->bits_per_coded_sample) { + case 16: + avctx->pix_fmt = AV_PIX_FMT_RGB555; + break; + case 24: + avctx->pix_fmt = AV_PIX_FMT_BGR24; + break; + case 32: + avctx->pix_fmt = AV_PIX_FMT_BGRA; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", + avctx->bits_per_coded_sample); + return AVERROR_INVALIDDATA; + } + + s->stride = (avctx->width * avctx->bits_per_coded_sample + 31) / 32; + s->xb = s->stride / BLOCK_WIDTH; + m = s->stride % BLOCK_WIDTH; + if (m) { + if (m < 37) { + w = m + BLOCK_WIDTH; + } else { + w = m; + s->xb++; + } + } + + s->yb = avctx->height / BLOCK_HEIGHT; + m = avctx->height % BLOCK_HEIGHT; + if (m) { + if (m < 49) { + h = m + BLOCK_HEIGHT; + } else { + h = m; + s->yb++; + } + } + + s->nb_blocks = s->xb * s->yb; + if (!s->nb_blocks) + return AVERROR_INVALIDDATA; + s->blocks = av_mallocz(s->nb_blocks * sizeof(*s->blocks)); + if (!s->blocks) + return AVERROR(ENOMEM); + + for (i = 0; i < s->yb; i++) { + for (j = 0; j < s->xb; j++) { + if (i != (s->yb - 1) || j != (s->xb - 1)) { + if (i == s->yb - 1) { + s->blocks[block].w = BLOCK_WIDTH; + s->blocks[block].h = h; + s->blocks[block].size = BLOCK_WIDTH * h; + } else if (j == s->xb - 1) { + s->blocks[block].w = w; + s->blocks[block].h = BLOCK_HEIGHT; + s->blocks[block].size = BLOCK_HEIGHT * w; + } else { + s->blocks[block].w = BLOCK_WIDTH; + s->blocks[block].h = BLOCK_HEIGHT; + s->blocks[block].size = BLOCK_WIDTH * BLOCK_HEIGHT; + } + } else { + s->blocks[block].w = w; + s->blocks[block].h = h; + s->blocks[block].size = w * h; + } + block++; + } + } + + s->bpp = avctx->bits_per_coded_sample >> 3; + s->buffer_size = avctx->width * avctx->height * 4; + s->pbuffer_size = avctx->width * avctx->height * 4; + s->buffer = av_malloc(s->buffer_size); + s->pbuffer = av_malloc(s->pbuffer_size); + if (!s->buffer || !s->pbuffer) + return AVERROR(ENOMEM); + + return 0; +} + +static av_cold int decode_close(AVCodecContext *avctx) +{ + FMVCContext *s = avctx->priv_data; + + av_freep(&s->buffer); + av_freep(&s->pbuffer); + av_freep(&s->blocks); + + return 0; +} + +AVCodec ff_fmvc_decoder = { + .name = "fmvc", + .long_name = NULL_IF_CONFIG_SMALL("FM Screen Capture Codec"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FMVC, + .priv_data_size = sizeof(FMVCContext), + .init = decode_init, + .close = decode_close, + .decode = decode_frame, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 8943ef3d0f691..63c9a1f634232 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 1 +#define LIBAVCODEC_VERSION_MINOR 2 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/riff.c b/libavformat/riff.c index 6de400720262c..49b8c762d6267 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -369,6 +369,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_MAGICYUV, MKTAG('M', 'A', 'G', 'Y') }, { AV_CODEC_ID_AV1, MKTAG('A', 'V', '0', '1') }, { AV_CODEC_ID_CFHD, MKTAG('C', 'F', 'H', 'D') }, + { AV_CODEC_ID_FMVC, MKTAG('F', 'M', 'V', 'C') }, { AV_CODEC_ID_NONE, 0 } }; From 4d4d7cf9d539a053f531f662a972b23d335738eb Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 21 Mar 2017 12:16:00 +0100 Subject: [PATCH 0141/2557] fmvc: Add FATE tests --- tests/fate/screen.mak | 9 +++++++++ tests/ref/fate/fmvc-type1 | 7 +++++++ tests/ref/fate/fmvc-type2 | 29 +++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 tests/ref/fate/fmvc-type1 create mode 100644 tests/ref/fate/fmvc-type2 diff --git a/tests/fate/screen.mak b/tests/fate/screen.mak index 7d2f7909b7418..575d217d5a569 100644 --- a/tests/fate/screen.mak +++ b/tests/fate/screen.mak @@ -8,6 +8,15 @@ fate-dxtory: CMD = framecrc -i $(TARGET_SAMPLES)/dxtory/dxtory_mic.avi -an FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, FIC) += fate-fic-avi fate-fic-avi: CMD = framecrc -i $(TARGET_SAMPLES)/fic/fic-partial-2MB.avi -an +FATE_FMVC += fate-fmvc-type1 +fate-fmvc-type1: CMD = framecrc -i $(TARGET_SAMPLES)/fmvc/6-methyl-5-hepten-2-one-CC-db_small.avi + +FATE_FMVC += fate-fmvc-type2 +fate-fmvc-type2: CMD = framecrc -i $(TARGET_SAMPLES)/fmvc/fmvcVirtualDub_small.avi + +FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, FMVC) += $(FATE_FMVC) +fate-fmvc: $(FATE_FMVC) + FATE_FRAPS += fate-fraps-v0 fate-fraps-v0: CMD = framecrc -i $(TARGET_SAMPLES)/fraps/Griffin_Ragdoll01-partial.avi diff --git a/tests/ref/fate/fmvc-type1 b/tests/ref/fate/fmvc-type1 new file mode 100644 index 0000000000000..821866da7d94b --- /dev/null +++ b/tests/ref/fate/fmvc-type1 @@ -0,0 +1,7 @@ +#tb 0: 1/15 +0, 0, 0, 1, 760944, 0x2feb1453 +0, 1, 1, 1, 760944, 0x9677ebf8 +0, 2, 2, 1, 760944, 0x83d2ed49 +0, 3, 3, 1, 760944, 0x9ab6c63d +0, 4, 4, 1, 760944, 0x1820189c +0, 5, 5, 1, 760944, 0x4b94f521 diff --git a/tests/ref/fate/fmvc-type2 b/tests/ref/fate/fmvc-type2 new file mode 100644 index 0000000000000..32a307ea4f4a2 --- /dev/null +++ b/tests/ref/fate/fmvc-type2 @@ -0,0 +1,29 @@ +#tb 0: 1/10 +0, 0, 0, 1, 1327104, 0xa73c232d +0, 1, 1, 1, 1327104, 0xa73c232d +0, 2, 2, 1, 1327104, 0xa73c232d +0, 3, 3, 1, 1327104, 0xf14e05be +0, 4, 4, 1, 1327104, 0xd8c03726 +0, 5, 5, 1, 1327104, 0x16e8447a +0, 6, 6, 1, 1327104, 0x8dfd94d2 +0, 7, 7, 1, 1327104, 0x3550833b +0, 8, 8, 1, 1327104, 0x74bd2959 +0, 9, 9, 1, 1327104, 0xc2b4505c +0, 10, 10, 1, 1327104, 0x7c6999cd +0, 11, 11, 1, 1327104, 0xb6562711 +0, 12, 12, 1, 1327104, 0x50993565 +0, 13, 13, 1, 1327104, 0x579549d2 +0, 14, 14, 1, 1327104, 0xb17170f6 +0, 15, 15, 1, 1327104, 0xc7d87708 +0, 16, 16, 1, 1327104, 0xdb3879da +0, 17, 17, 1, 1327104, 0xdb3879da +0, 18, 18, 1, 1327104, 0xdb3879da +0, 19, 19, 1, 1327104, 0x6f1c5c01 +0, 20, 20, 1, 1327104, 0xd9d15c01 +0, 21, 21, 1, 1327104, 0x826f0bab +0, 22, 22, 1, 1327104, 0xf25b041d +0, 23, 23, 1, 1327104, 0xc85a041d +0, 24, 24, 1, 1327104, 0xc85a041d +0, 25, 25, 1, 1327104, 0xc85a041d +0, 26, 26, 1, 1327104, 0xc85a041d +0, 27, 27, 1, 1327104, 0xc54cc6ae From 1fe858136b315796dd5349f3b4448a29d1bd6fa1 Mon Sep 17 00:00:00 2001 From: Ganesh Ajjanagadde Date: Mon, 22 Feb 2016 23:21:58 -0500 Subject: [PATCH 0142/2557] utvideodec: Prevent possible signed overflow Doing slice_end - slice_start is unsafe and can lead to undefined behavior until slice_end has been properly sanitized. Reviewed-by: Ronald S. Bultje Signed-off-by: Ganesh Ajjanagadde Signed-off-by: Luca Barbato --- libavcodec/utvideodec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 808e3be0676d5..2aaf861e627c6 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -361,12 +361,12 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, slice_end = 0; for (j = 0; j < c->slices; j++) { slice_end = bytestream2_get_le32u(&gb); - slice_size = slice_end - slice_start; - if (slice_end < 0 || slice_size < 0 || + if (slice_end < 0 || slice_end < slice_start || bytestream2_get_bytes_left(&gb) < slice_end) { av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n"); return AVERROR_INVALIDDATA; } + slice_size = slice_end - slice_start; slice_start = slice_end; max_slice_size = FFMAX(max_slice_size, slice_size); } From 19c5fa9eea47d45b5eedce3bff4edeaf83fb3942 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 11 Apr 2017 12:11:59 +0200 Subject: [PATCH 0143/2557] golomb: Simplify get_ur_golomb_jpegls The loop always consumes the bit read and the new bitstream reader can read 0 bits just fine. --- libavcodec/golomb.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libavcodec/golomb.h b/libavcodec/golomb.h index 648f9243fc4a6..cff7e42e51abf 100644 --- a/libavcodec/golomb.h +++ b/libavcodec/golomb.h @@ -290,16 +290,12 @@ static inline int get_ur_golomb_jpegls(BitstreamContext *bc, int k, int limit, return buf; } else { int i; - for (i = 0; i < limit && bitstream_peek(bc, 1) == 0 && bitstream_bits_left(bc) > 0; i++) - bitstream_skip(bc, 1); - bitstream_skip(bc, 1); + for (i = 0; + i < limit && bitstream_read_bit(bc) == 0 && bitstream_bits_left(bc) > 0; + i++); if (i < limit - 1) { - if (k) { - buf = bitstream_read(bc, k); - } else { - buf = 0; - } + buf = bitstream_read(bc, k); return buf + (i << k); } else if (i == limit - 1) { From 9e4a5eb51b9f3b2bff0ef08e0074b7fe4893075d Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Wed, 12 Apr 2017 01:46:30 +0200 Subject: [PATCH 0144/2557] avformat: Free the internal codec context at the end Avoid a use after free in avformat_find_stream_info. CC: libav-stable@libav.org --- libavformat/utils.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index 8fa89eb790991..eaba47391401d 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2466,11 +2466,6 @@ FF_ENABLE_DEPRECATION_WARNINGS count++; } - // close codecs which were opened in try_decode_frame() - for (i = 0; i < ic->nb_streams; i++) { - st = ic->streams[i]; - avcodec_close(st->internal->avctx); - } for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; avctx = st->internal->avctx; @@ -2570,6 +2565,7 @@ FF_ENABLE_DEPRECATION_WARNINGS find_stream_info_err: for (i = 0; i < ic->nb_streams; i++) { + avcodec_close(ic->streams[i]->internal->avctx); av_freep(&ic->streams[i]->info); av_bsf_free(&ic->streams[i]->internal->extract_extradata.bsf); av_packet_free(&ic->streams[i]->internal->extract_extradata.pkt); From c5230955640cb65101a5f8add83abee0410583eb Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 10 Apr 2017 11:08:44 +0200 Subject: [PATCH 0145/2557] utvideodec: Support UQY2 Signed-off-by: Luca Barbato --- libavcodec/utvideo.c | 6 + libavcodec/utvideo.h | 4 +- libavcodec/utvideodec.c | 282 ++++++++++++++++++++++++++++++++++------ libavformat/riff.c | 1 + 4 files changed, 253 insertions(+), 40 deletions(-) diff --git a/libavcodec/utvideo.c b/libavcodec/utvideo.c index 35e927ca2d30f..556b4de602293 100644 --- a/libavcodec/utvideo.c +++ b/libavcodec/utvideo.c @@ -39,3 +39,9 @@ int ff_ut_huff_cmp_len(const void *a, const void *b) const HuffEntry *aa = a, *bb = b; return (aa->len - bb->len)*256 + aa->sym - bb->sym; } + +int ff_ut10_huff_cmp_len(const void *a, const void *b) +{ + const HuffEntry *aa = a, *bb = b; + return (aa->len - bb->len) * 1024 + aa->sym - bb->sym; +} diff --git a/libavcodec/utvideo.h b/libavcodec/utvideo.h index c7f54145f114a..bc83a28d43645 100644 --- a/libavcodec/utvideo.h +++ b/libavcodec/utvideo.h @@ -76,6 +76,7 @@ typedef struct UtvideoContext { int compression; int interlaced; int frame_pred; + int pro; ptrdiff_t slice_stride; uint8_t *slice_bits, *slice_buffer[4]; @@ -83,12 +84,13 @@ typedef struct UtvideoContext { } UtvideoContext; typedef struct HuffEntry { - uint8_t sym; + uint16_t sym; uint8_t len; uint32_t code; } HuffEntry; /* Compare huffman tree nodes */ int ff_ut_huff_cmp_len(const void *a, const void *b); +int ff_ut10_huff_cmp_len(const void *a, const void *b); #endif /* AVCODEC_UTVIDEO_H */ diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 2aaf861e627c6..47f9de86c4bc4 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -37,6 +37,50 @@ #include "thread.h" #include "utvideo.h" +static int build_huff10(const uint8_t *src, VLC *vlc, int *fsym) +{ + int i; + HuffEntry he[1024]; + int last; + uint32_t codes[1024]; + uint8_t bits[1024]; + uint16_t syms[1024]; + uint32_t code; + + *fsym = -1; + for (i = 0; i < 1024; i++) { + he[i].sym = i; + he[i].len = *src++; + } + qsort(he, 1024, sizeof(*he), ff_ut10_huff_cmp_len); + + if (!he[0].len) { + *fsym = he[0].sym; + return 0; + } + + last = 1023; + while (he[last].len == 255 && last) + last--; + + if (he[last].len > 32) { + return -1; + } + + code = 1; + for (i = last; i >= 0; i--) { + codes[i] = code >> (32 - he[i].len); + bits[i] = he[i].len; + syms[i] = he[i].sym; + code += 0x80000000u >> (he[i].len - 1); + } + + return ff_init_vlc_sparse(vlc, FFMIN(he[last].len, 11), last + 1, + bits, sizeof(*bits), sizeof(*bits), + codes, sizeof(*codes), sizeof(*codes), + syms, sizeof(*syms), sizeof(*syms), 0); +} + static int build_huff(const uint8_t *src, VLC *vlc, int *fsym) { int i; @@ -79,6 +123,111 @@ static int build_huff(const uint8_t *src, VLC *vlc, int *fsym) syms, sizeof(*syms), sizeof(*syms), 0); } +static int decode_plane10(UtvideoContext *c, int plane_no, + uint16_t *dst, int step, int stride, + int width, int height, + const uint8_t *src, const uint8_t *huff, + int use_pred) +{ + BitstreamContext bc; + int i, j, slice, pix, ret; + int sstart, send; + VLC vlc; + int prev, fsym; + + if ((ret = build_huff10(huff, &vlc, &fsym)) < 0) { + av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); + return ret; + } + if (fsym >= 0) { // build_huff reported a symbol to fill slices with + send = 0; + for (slice = 0; slice < c->slices; slice++) { + uint16_t *dest; + + sstart = send; + send = (height * (slice + 1) / c->slices); + dest = dst + sstart * stride; + + prev = 0x200; + for (j = sstart; j < send; j++) { + for (i = 0; i < width * step; i += step) { + pix = fsym; + if (use_pred) { + prev += pix; + prev &= 0x3FF; + pix = prev; + } + dest[i] = pix; + } + dest += stride; + } + } + return 0; + } + + send = 0; + for (slice = 0; slice < c->slices; slice++) { + uint16_t *dest; + int slice_data_start, slice_data_end, slice_size; + + sstart = send; + send = (height * (slice + 1) / c->slices); + dest = dst + sstart * stride; + + // slice offset and size validation was done earlier + slice_data_start = slice ? AV_RL32(src + slice * 4 - 4) : 0; + slice_data_end = AV_RL32(src + slice * 4); + slice_size = slice_data_end - slice_data_start; + + if (!slice_size) { + av_log(c->avctx, AV_LOG_ERROR, "Plane has more than one symbol " + "yet a slice has a length of zero.\n"); + goto fail; + } + + memcpy(c->slice_bits, src + slice_data_start + c->slices * 4, + slice_size); + memset(c->slice_bits + slice_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + c->bdsp.bswap_buf((uint32_t *) c->slice_bits, + (uint32_t *) c->slice_bits, + (slice_data_end - slice_data_start + 3) >> 2); + bitstream_init8(&bc, c->slice_bits, slice_size); + + prev = 0x200; + for (j = sstart; j < send; j++) { + for (i = 0; i < width * step; i += step) { + if (bitstream_bits_left(&bc) <= 0) { + av_log(c->avctx, AV_LOG_ERROR, + "Slice decoding ran out of bits\n"); + goto fail; + } + pix = bitstream_read_vlc(&bc, vlc.table, vlc.bits, 3); + if (pix < 0) { + av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n"); + goto fail; + } + if (use_pred) { + prev += pix; + prev &= 0x3FF; + pix = prev; + } + dest[i] = pix; + } + dest += stride; + } + if (bitstream_bits_left(&bc) > 32) + av_log(c->avctx, AV_LOG_WARNING, + "%d bits left after decoding slice\n", bitstream_bits_left(&bc)); + } + + ff_free_vlc(&vlc); + + return 0; +fail: + ff_free_vlc(&vlc); + return AVERROR_INVALIDDATA; +} + static int decode_plane(UtvideoContext *c, int plane_no, uint8_t *dst, int step, ptrdiff_t stride, int width, int height, @@ -350,35 +499,68 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, /* parse plane structure to get frame flags and validate slice offsets */ bytestream2_init(&gb, buf, buf_size); - for (i = 0; i < c->planes; i++) { - plane_start[i] = gb.buffer; - if (bytestream2_get_bytes_left(&gb) < 256 + 4 * c->slices) { - av_log(avctx, AV_LOG_ERROR, "Insufficient data for a plane\n"); + if (c->pro) { + if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) { + av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n"); return AVERROR_INVALIDDATA; } - bytestream2_skipu(&gb, 256); - slice_start = 0; - slice_end = 0; - for (j = 0; j < c->slices; j++) { - slice_end = bytestream2_get_le32u(&gb); - if (slice_end < 0 || slice_end < slice_start || - bytestream2_get_bytes_left(&gb) < slice_end) { - av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n"); + c->frame_info = bytestream2_get_le32u(&gb); + c->slices = ((c->frame_info >> 16) & 0xff) + 1; + for (i = 0; i < c->planes; i++) { + plane_start[i] = gb.buffer; + if (bytestream2_get_bytes_left(&gb) < 1024 + 4 * c->slices) { + av_log(avctx, AV_LOG_ERROR, "Insufficient data for a plane\n"); + return AVERROR_INVALIDDATA; + } + slice_start = 0; + slice_end = 0; + for (j = 0; j < c->slices; j++) { + slice_end = bytestream2_get_le32u(&gb); + if (slice_end < 0 || slice_end < slice_start || + bytestream2_get_bytes_left(&gb) < slice_end) { + av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n"); + return AVERROR_INVALIDDATA; + } + slice_size = slice_end - slice_start; + slice_start = slice_end; + max_slice_size = FFMAX(max_slice_size, slice_size); + } + plane_size = slice_end; + bytestream2_skipu(&gb, plane_size); + bytestream2_skipu(&gb, 1024); + } + plane_start[c->planes] = gb.buffer; + } else { + for (i = 0; i < c->planes; i++) { + plane_start[i] = gb.buffer; + if (bytestream2_get_bytes_left(&gb) < 256 + 4 * c->slices) { + av_log(avctx, AV_LOG_ERROR, "Insufficient data for a plane\n"); return AVERROR_INVALIDDATA; } - slice_size = slice_end - slice_start; - slice_start = slice_end; - max_slice_size = FFMAX(max_slice_size, slice_size); + bytestream2_skipu(&gb, 256); + slice_start = 0; + slice_end = 0; + for (j = 0; j < c->slices; j++) { + slice_end = bytestream2_get_le32u(&gb); + if (slice_end < 0 || slice_end < slice_start || + bytestream2_get_bytes_left(&gb) < slice_end) { + av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n"); + return AVERROR_INVALIDDATA; + } + slice_size = slice_end - slice_start; + slice_start = slice_end; + max_slice_size = FFMAX(max_slice_size, slice_size); + } + plane_size = slice_end; + bytestream2_skipu(&gb, plane_size); } - plane_size = slice_end; - bytestream2_skipu(&gb, plane_size); - } - plane_start[c->planes] = gb.buffer; - if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) { - av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n"); - return AVERROR_INVALIDDATA; + plane_start[c->planes] = gb.buffer; + if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) { + av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n"); + return AVERROR_INVALIDDATA; + } + c->frame_info = bytestream2_get_le32u(&gb); } - c->frame_info = bytestream2_get_le32u(&gb); av_log(avctx, AV_LOG_DEBUG, "frame information flags %"PRIX32"\n", c->frame_info); @@ -464,6 +646,15 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } } break; + case AV_PIX_FMT_YUV422P10: + for (i = 0; i < 3; i++) { + ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i], 1, frame.f->linesize[i] / 2, + avctx->width >> !!i, avctx->height, + plane_start[i], plane_start[i + 1] - 1024, c->frame_pred == PRED_LEFT); + if (ret) + return ret; + } + break; } frame.f->key_frame = 1; @@ -484,28 +675,37 @@ static av_cold int decode_init(AVCodecContext *avctx) ff_bswapdsp_init(&c->bdsp); - if (avctx->extradata_size < 16) { + if (avctx->extradata_size >= 16) { + av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", + avctx->extradata[3], avctx->extradata[2], + avctx->extradata[1], avctx->extradata[0]); + av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", + AV_RB32(avctx->extradata + 4)); + c->frame_info_size = AV_RL32(avctx->extradata + 8); + c->flags = AV_RL32(avctx->extradata + 12); + + if (c->frame_info_size != 4) + avpriv_request_sample(avctx, "Frame info not 4 bytes"); + av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08"PRIX32"\n", c->flags); + c->slices = (c->flags >> 24) + 1; + c->compression = c->flags & 1; + c->interlaced = c->flags & 0x800; + } else if (avctx->extradata_size == 8) { + av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", + avctx->extradata[3], avctx->extradata[2], + avctx->extradata[1], avctx->extradata[0]); + av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", + AV_RB32(avctx->extradata + 4)); + c->interlaced = 0; + c->pro = 1; + c->frame_info_size = 4; + } else { av_log(avctx, AV_LOG_ERROR, "Insufficient extradata size %d, should be at least 16\n", avctx->extradata_size); return AVERROR_INVALIDDATA; } - av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", - avctx->extradata[3], avctx->extradata[2], - avctx->extradata[1], avctx->extradata[0]); - av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", - AV_RB32(avctx->extradata + 4)); - c->frame_info_size = AV_RL32(avctx->extradata + 8); - c->flags = AV_RL32(avctx->extradata + 12); - - if (c->frame_info_size != 4) - avpriv_request_sample(avctx, "Frame info not 4 bytes"); - av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08"PRIX32"\n", c->flags); - c->slices = (c->flags >> 24) + 1; - c->compression = c->flags & 1; - c->interlaced = c->flags & 0x800; - c->slice_bits_size = 0; switch (avctx->codec_tag) { @@ -527,6 +727,10 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->pix_fmt = AV_PIX_FMT_YUV422P; avctx->colorspace = AVCOL_SPC_BT470BG; break; + case MKTAG('U', 'Q', 'Y', '2'): + c->planes = 3; + avctx->pix_fmt = AV_PIX_FMT_YUV422P10; + break; case MKTAG('U', 'L', 'H', '0'): c->planes = 3; avctx->pix_fmt = AV_PIX_FMT_YUV420P; diff --git a/libavformat/riff.c b/libavformat/riff.c index 49b8c762d6267..69dabc0d523fc 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -342,6 +342,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'Y', '2') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'H', '0') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'H', '2') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'Y', '2') }, { AV_CODEC_ID_VBLE, MKTAG('V', 'B', 'L', 'E') }, { AV_CODEC_ID_ESCAPE130, MKTAG('E', '1', '3', '0') }, { AV_CODEC_ID_DXTORY, MKTAG('x', 't', 'o', 'r') }, From 030c8be7a2c0f3ce0440ef37fe5207c0288b8c9e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 10 Jun 2016 12:48:09 +0200 Subject: [PATCH 0146/2557] pixfmt: Add gbrap10 pixel format Signed-off-by: Paul B Mahol Signed-off-by: Luca Barbato --- libavutil/pixdesc.c | 28 ++++++++++++++++++++++++++++ libavutil/pixfmt.h | 4 ++++ 2 files changed, 32 insertions(+) diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 815e084155f29..fb2e1a12f369d 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -1683,6 +1683,34 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, }, + [AV_PIX_FMT_GBRAP10LE] = { + .name = "gbrap10le", + .nb_components = 4, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* R */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* G */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* B */ + { 3, 2, 0, 0, 10, 1, 9, 1 }, /* A */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | + AV_PIX_FMT_FLAG_ALPHA, + }, + [AV_PIX_FMT_GBRAP10BE] = { + .name = "gbrap10be", + .nb_components = 4, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 2, 2, 0, 0, 10, 1, 9, 1 }, /* R */ + { 0, 2, 0, 0, 10, 1, 9, 1 }, /* G */ + { 1, 2, 0, 0, 10, 1, 9, 1 }, /* B */ + { 3, 2, 0, 0, 10, 1, 9, 1 }, /* A */ + }, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | + AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, + }, [AV_PIX_FMT_GBRAP12LE] = { .name = "gbrap12le", .nb_components = 4, diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 3c670fc9d45c2..fc1969ef12613 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -234,6 +234,9 @@ enum AVPixelFormat { AV_PIX_FMT_GRAY12BE, ///< Y , 12bpp, big-endian AV_PIX_FMT_GRAY12LE, ///< Y , 12bpp, little-endian + AV_PIX_FMT_GBRAP10BE, ///< planar GBR 4:4:4:4 40bpp, big-endian + AV_PIX_FMT_GBRAP10LE, ///< planar GBR 4:4:4:4 40bpp, little-endian + AV_PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions }; @@ -280,6 +283,7 @@ enum AVPixelFormat { #define AV_PIX_FMT_GBRP12 AV_PIX_FMT_NE(GBRP12BE, GBRP12LE) #define AV_PIX_FMT_GBRP16 AV_PIX_FMT_NE(GBRP16BE, GBRP16LE) +#define AV_PIX_FMT_GBRAP10 AV_PIX_FMT_NE(GBRAP10BE, GBRAP10LE) #define AV_PIX_FMT_GBRAP12 AV_PIX_FMT_NE(GBRAP12BE, GBRAP12LE) #define AV_PIX_FMT_GBRAP16 AV_PIX_FMT_NE(GBRAP16BE, GBRAP16LE) From f6a9c20a52d67df2cd1cdbe3d2c58f336666b7d4 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 10 Jun 2016 13:01:26 +0200 Subject: [PATCH 0147/2557] swscale: Add input support for gbrap10 pixel format Signed-off-by: Paul B Mahol --- libswscale/input.c | 16 ++++++++++++++++ libswscale/utils.c | 3 +++ 2 files changed, 19 insertions(+) diff --git a/libswscale/input.c b/libswscale/input.c index d8560a1f2b4c0..761776c1ceff1 100644 --- a/libswscale/input.c +++ b/libswscale/input.c @@ -699,11 +699,21 @@ static void planar_rgb10le_to_y(uint8_t *dst, const uint8_t *src[4], int w) planar_rgb16_to_y(dst, src, w, 10, 0); } +static void planar_rgb10le_to_a(uint8_t *dst, const uint8_t *src[4], int w) +{ + planar_rgb16_to_a(dst, src, w, 10, 0); +} + static void planar_rgb10be_to_y(uint8_t *dst, const uint8_t *src[4], int w) { planar_rgb16_to_y(dst, src, w, 10, 1); } +static void planar_rgb10be_to_a(uint8_t *dst, const uint8_t *src[4], int w) +{ + planar_rgb16_to_a(dst, src, w, 10, 1); +} + static void planar_rgb12le_to_y(uint8_t *dst, const uint8_t *src[4], int w) { planar_rgb16_to_y(dst, src, w, 12, 0); @@ -842,6 +852,7 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_GBRP9LE: c->readChrPlanar = planar_rgb9le_to_uv; break; + case AV_PIX_FMT_GBRAP10LE: case AV_PIX_FMT_GBRP10LE: c->readChrPlanar = planar_rgb10le_to_uv; break; @@ -856,6 +867,7 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_GBRP9BE: c->readChrPlanar = planar_rgb9be_to_uv; break; + case AV_PIX_FMT_GBRAP10BE: case AV_PIX_FMT_GBRP10BE: c->readChrPlanar = planar_rgb10be_to_uv; break; @@ -1073,6 +1085,8 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_GBRP9LE: c->readLumPlanar = planar_rgb9le_to_y; break; + case AV_PIX_FMT_GBRAP10LE: + c->readAlpPlanar = planar_rgb10le_to_a; case AV_PIX_FMT_GBRP10LE: c->readLumPlanar = planar_rgb10le_to_y; break; @@ -1089,6 +1103,8 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_GBRP9BE: c->readLumPlanar = planar_rgb9be_to_y; break; + case AV_PIX_FMT_GBRAP10BE: + c->readAlpPlanar = planar_rgb10be_to_a; case AV_PIX_FMT_GBRP10BE: c->readLumPlanar = planar_rgb10be_to_y; break; diff --git a/libswscale/utils.c b/libswscale/utils.c index 6034b704658d1..3a5c779ea3620 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -191,6 +191,8 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = { [AV_PIX_FMT_GBRP16LE] = { 1, 0 }, [AV_PIX_FMT_GBRP16BE] = { 1, 0 }, [AV_PIX_FMT_GBRAP] = { 1, 1 }, + [AV_PIX_FMT_GBRAP10LE] = { 1, 0 }, + [AV_PIX_FMT_GBRAP10BE] = { 1, 0 }, [AV_PIX_FMT_GBRAP12LE] = { 1, 1 }, [AV_PIX_FMT_GBRAP12BE] = { 1, 1 }, [AV_PIX_FMT_GBRAP16LE] = { 1, 0 }, @@ -1021,6 +1023,7 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, srcFormat != AV_PIX_FMT_RGB4_BYTE && srcFormat != AV_PIX_FMT_BGR4_BYTE && srcFormat != AV_PIX_FMT_GBRP9BE && srcFormat != AV_PIX_FMT_GBRP9LE && srcFormat != AV_PIX_FMT_GBRP10BE && srcFormat != AV_PIX_FMT_GBRP10LE && + srcFormat != AV_PIX_FMT_GBRAP10BE && srcFormat != AV_PIX_FMT_GBRAP10LE && srcFormat != AV_PIX_FMT_GBRP12BE && srcFormat != AV_PIX_FMT_GBRP12LE && srcFormat != AV_PIX_FMT_GBRP16BE && srcFormat != AV_PIX_FMT_GBRP16LE && ((dstW >> c->chrDstHSubSample) <= (srcW >> 1) || From ac29b82ec596c19c649b43f9988cbcc56f83b9e8 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 10 Nov 2016 00:02:50 +0100 Subject: [PATCH 0148/2557] swscale: Add gbrap10 output Signed-off-by: Michael Niedermayer Signed-off-by: Luca Barbato --- libswscale/output.c | 2 ++ libswscale/utils.c | 4 ++-- tests/ref/fate/filter-pixdesc-gbrap10be | 1 + tests/ref/fate/filter-pixdesc-gbrap10le | 1 + tests/ref/fate/filter-pixfmts-copy | 2 ++ tests/ref/fate/filter-pixfmts-null | 2 ++ tests/ref/fate/filter-pixfmts-scale | 2 ++ tests/ref/fate/filter-pixfmts-vflip | 2 ++ 8 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tests/ref/fate/filter-pixdesc-gbrap10be create mode 100644 tests/ref/fate/filter-pixdesc-gbrap10le diff --git a/libswscale/output.c b/libswscale/output.c index d0c303c3a8327..cfb204300a535 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -1457,6 +1457,8 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, case AV_PIX_FMT_GBRP10LE: case AV_PIX_FMT_GBRP12BE: case AV_PIX_FMT_GBRP12LE: + case AV_PIX_FMT_GBRAP10BE: + case AV_PIX_FMT_GBRAP10LE: case AV_PIX_FMT_GBRAP12BE: case AV_PIX_FMT_GBRAP12LE: case AV_PIX_FMT_GBRP16BE: diff --git a/libswscale/utils.c b/libswscale/utils.c index 3a5c779ea3620..248a8081ff634 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -191,8 +191,8 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = { [AV_PIX_FMT_GBRP16LE] = { 1, 0 }, [AV_PIX_FMT_GBRP16BE] = { 1, 0 }, [AV_PIX_FMT_GBRAP] = { 1, 1 }, - [AV_PIX_FMT_GBRAP10LE] = { 1, 0 }, - [AV_PIX_FMT_GBRAP10BE] = { 1, 0 }, + [AV_PIX_FMT_GBRAP10LE] = { 1, 1 }, + [AV_PIX_FMT_GBRAP10BE] = { 1, 1 }, [AV_PIX_FMT_GBRAP12LE] = { 1, 1 }, [AV_PIX_FMT_GBRAP12BE] = { 1, 1 }, [AV_PIX_FMT_GBRAP16LE] = { 1, 0 }, diff --git a/tests/ref/fate/filter-pixdesc-gbrap10be b/tests/ref/fate/filter-pixdesc-gbrap10be new file mode 100644 index 0000000000000..de31be676d7c4 --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-gbrap10be @@ -0,0 +1 @@ +pixdesc-gbrap10be 555c0acf80a24fbe2cac7e1babf90e05 diff --git a/tests/ref/fate/filter-pixdesc-gbrap10le b/tests/ref/fate/filter-pixdesc-gbrap10le new file mode 100644 index 0000000000000..7e355e2cf0bbf --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-gbrap10le @@ -0,0 +1 @@ +pixdesc-gbrap10le 7745a3c869fd7dbc1d8fd9db28bd2f89 diff --git a/tests/ref/fate/filter-pixfmts-copy b/tests/ref/fate/filter-pixfmts-copy index bd16f110757c4..c23187c5957d9 100644 --- a/tests/ref/fate/filter-pixfmts-copy +++ b/tests/ref/fate/filter-pixfmts-copy @@ -13,6 +13,8 @@ bgr565le 6a0d182c7165103b2613d1805c822f9f bgr8 36b9ef72c87da36ac547202d85a5805f bgra 56e6e1bfde40aaa27473e01b46345c82 gbrap 57cb1a02d6f015a4329fe367f3bdfe49 +gbrap10be 56d152356064bce059f85be97f548d68 +gbrap10le 30e9fdb568a60eb3f8dcd55497425fa2 gbrap12be df4b550099df0702f602a8b305702a8c gbrap12le f947c43e494ab87410dfb2547e7e22f2 gbrp d5f73b5d3ba7f6cadbc9b4ecbc161005 diff --git a/tests/ref/fate/filter-pixfmts-null b/tests/ref/fate/filter-pixfmts-null index bd16f110757c4..c23187c5957d9 100644 --- a/tests/ref/fate/filter-pixfmts-null +++ b/tests/ref/fate/filter-pixfmts-null @@ -13,6 +13,8 @@ bgr565le 6a0d182c7165103b2613d1805c822f9f bgr8 36b9ef72c87da36ac547202d85a5805f bgra 56e6e1bfde40aaa27473e01b46345c82 gbrap 57cb1a02d6f015a4329fe367f3bdfe49 +gbrap10be 56d152356064bce059f85be97f548d68 +gbrap10le 30e9fdb568a60eb3f8dcd55497425fa2 gbrap12be df4b550099df0702f602a8b305702a8c gbrap12le f947c43e494ab87410dfb2547e7e22f2 gbrp d5f73b5d3ba7f6cadbc9b4ecbc161005 diff --git a/tests/ref/fate/filter-pixfmts-scale b/tests/ref/fate/filter-pixfmts-scale index e1737f0b206e7..0c73ec827a081 100644 --- a/tests/ref/fate/filter-pixfmts-scale +++ b/tests/ref/fate/filter-pixfmts-scale @@ -13,6 +13,8 @@ bgr565le 34438643c183ff1748cf7d71453f981c bgr8 e731ba3dbec294e1daa7313e08e88034 bgra 6e1f417ae41636f631de1cfe39ce1778 gbrap eefdbfd1426765ce5e9790022533db0d +gbrap10be 27453716362dda9ebf43c0f6992eff48 +gbrap10le 253139dcb985b9d7c2e583595596dfa0 gbrap12be af4acb3ad0a6630f6ec4534e4d2e869a gbrap12le 90ca5271960dc1ebd6ebe14189223e36 gbrp 5d14768d2ab6cbf3879966b5d5c6befb diff --git a/tests/ref/fate/filter-pixfmts-vflip b/tests/ref/fate/filter-pixfmts-vflip index 11a48c7c71506..184793000a9f5 100644 --- a/tests/ref/fate/filter-pixfmts-vflip +++ b/tests/ref/fate/filter-pixfmts-vflip @@ -13,6 +13,8 @@ bgr565le 6f98ccb05e608863ef0912b9a6fd960b bgr8 1f916a75563e6be42c056e7d973a7356 bgra dd8eaea69683884ea45bf2fb635ce415 gbrap 38e04cbd4dc5566586d58ffed0c6b20d +gbrap10be 1c2ddca8b0404ff80e6761c816536b0e +gbrap10le 16382a4276c0c30b90d52d206ad9da32 gbrap12be c53126e45593f2e49451c9c9f58cffac gbrap12le 6d5b3a8f8aae74f3542a63bcd1179a6c gbrp 37954476d089b5b74b06891e64ad6b9e From a93faf30d688b872e0ecc453b2dfc36470683ed6 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 10 Apr 2017 11:35:00 +0200 Subject: [PATCH 0149/2557] utvideodec: Support UQRA and UQRG --- libavcodec/utvideodec.c | 43 +++++++++++++++++++++++++++++++++++++++++ libavformat/riff.c | 2 ++ 2 files changed, 45 insertions(+) diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 47f9de86c4bc4..cc18e3dc95323 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -351,6 +351,28 @@ static void restore_rgb_planes(uint8_t *src, int step, ptrdiff_t stride, } } +static void restore_rgb_planes10(AVFrame *frame, int width, int height) +{ + uint16_t *src_r = (uint16_t *)frame->data[2]; + uint16_t *src_g = (uint16_t *)frame->data[0]; + uint16_t *src_b = (uint16_t *)frame->data[1]; + int r, g, b; + int i, j; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + r = src_r[i]; + g = src_g[i]; + b = src_b[i]; + src_r[i] = (r + g - 0x200) & 0x3FF; + src_b[i] = (b + g - 0x200) & 0x3FF; + } + src_r += frame->linesize[2] / 2; + src_g += frame->linesize[0] / 2; + src_b += frame->linesize[1] / 2; + } +} + static void restore_median(uint8_t *src, int step, ptrdiff_t stride, int width, int height, int slices, int rmode) { @@ -605,6 +627,19 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, restore_rgb_planes(frame.f->data[0], c->planes, frame.f->linesize[0], avctx->width, avctx->height); break; + case AV_PIX_FMT_GBRAP10: + case AV_PIX_FMT_GBRP10: + for (i = 0; i < c->planes; i++) { + ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i], 1, + frame.f->linesize[i] / 2, avctx->width, + avctx->height, plane_start[i], + plane_start[i + 1] - 1024, + c->frame_pred == PRED_LEFT); + if (ret) + return ret; + } + restore_rgb_planes10(frame.f, avctx->width, avctx->height); + break; case AV_PIX_FMT_YUV420P: for (i = 0; i < 3; i++) { ret = decode_plane(c, i, frame.f->data[i], 1, frame.f->linesize[i], @@ -731,6 +766,14 @@ static av_cold int decode_init(AVCodecContext *avctx) c->planes = 3; avctx->pix_fmt = AV_PIX_FMT_YUV422P10; break; + case MKTAG('U', 'Q', 'R', 'G'): + c->planes = 3; + avctx->pix_fmt = AV_PIX_FMT_GBRP10; + break; + case MKTAG('U', 'Q', 'R', 'A'): + c->planes = 4; + avctx->pix_fmt = AV_PIX_FMT_GBRAP10; + break; case MKTAG('U', 'L', 'H', '0'): c->planes = 3; avctx->pix_fmt = AV_PIX_FMT_YUV420P; diff --git a/libavformat/riff.c b/libavformat/riff.c index 69dabc0d523fc..9cd330b344a40 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -343,6 +343,8 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'H', '0') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'H', '2') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'Y', '2') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'R', 'A') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'R', 'G') }, { AV_CODEC_ID_VBLE, MKTAG('V', 'B', 'L', 'E') }, { AV_CODEC_ID_ESCAPE130, MKTAG('E', '1', '3', '0') }, { AV_CODEC_ID_DXTORY, MKTAG('x', 't', 'o', 'r') }, From 4f33d9d41a03981adff0a9a95ef034fd14625e95 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 4 Sep 2016 01:56:02 +0200 Subject: [PATCH 0150/2557] utvideodec: Support ULY4 and ULH4 Signed-off-by: Paul B Mahol Signed-off-by: Luca Barbato --- libavcodec/utvideodec.c | 30 ++++++++++++++++++++++++++++++ libavformat/riff.c | 2 ++ 2 files changed, 32 insertions(+) diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index cc18e3dc95323..f5fae8ba44e6e 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -681,6 +681,26 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } } break; + case AV_PIX_FMT_YUV444P: + for (i = 0; i < 3; i++) { + ret = decode_plane(c, i, frame.f->data[i], 1, frame.f->linesize[i], + avctx->width, avctx->height, + plane_start[i], c->frame_pred == PRED_LEFT); + if (ret) + return ret; + if (c->frame_pred == PRED_MEDIAN) { + if (!c->interlaced) { + restore_median(frame.f->data[i], 1, frame.f->linesize[i], + avctx->width, avctx->height, + c->slices, 0); + } else { + restore_median_il(frame.f->data[i], 1, frame.f->linesize[i], + avctx->width, avctx->height, + c->slices, 0); + } + } + } + break; case AV_PIX_FMT_YUV422P10: for (i = 0; i < 3; i++) { ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i], 1, frame.f->linesize[i] / 2, @@ -762,6 +782,11 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->pix_fmt = AV_PIX_FMT_YUV422P; avctx->colorspace = AVCOL_SPC_BT470BG; break; + case MKTAG('U', 'L', 'Y', '4'): + c->planes = 3; + avctx->pix_fmt = AV_PIX_FMT_YUV444P; + avctx->colorspace = AVCOL_SPC_BT470BG; + break; case MKTAG('U', 'Q', 'Y', '2'): c->planes = 3; avctx->pix_fmt = AV_PIX_FMT_YUV422P10; @@ -784,6 +809,11 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->pix_fmt = AV_PIX_FMT_YUV422P; avctx->colorspace = AVCOL_SPC_BT709; break; + case MKTAG('U', 'L', 'H', '4'): + c->planes = 3; + avctx->pix_fmt = AV_PIX_FMT_YUV444P; + avctx->colorspace = AVCOL_SPC_BT709; + break; default: av_log(avctx, AV_LOG_ERROR, "Unknown Ut Video FOURCC provided (%08X)\n", avctx->codec_tag); diff --git a/libavformat/riff.c b/libavformat/riff.c index 9cd330b344a40..a6734f2789824 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -340,8 +340,10 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'R', 'G') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'Y', '0') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'Y', '2') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'Y', '4') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'H', '0') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'H', '2') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'H', '4') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'Y', '2') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'R', 'A') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'R', 'G') }, From 9227bd8ac2f22cfad2ee5bc3122d407196a0ba15 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 23 Dec 2016 15:41:51 +0100 Subject: [PATCH 0151/2557] utvideodec: Reuse the huffyuv add_left ~10% faster when simd is available. Signed-off-by: Paul B Mahol Signed-off-by: Luca Barbato --- configure | 2 +- libavcodec/utvideo.h | 2 + libavcodec/utvideodec.c | 164 ++++++++++++++++++++++++++++++++-------- 3 files changed, 137 insertions(+), 31 deletions(-) diff --git a/configure b/configure index ecc77842ff09e..e83a4cf69707b 100755 --- a/configure +++ b/configure @@ -2129,7 +2129,7 @@ truespeech_decoder_select="bswapdsp" tscc_decoder_deps="zlib" txd_decoder_select="texturedsp" twinvq_decoder_select="mdct lsp sinewin" -utvideo_decoder_select="bswapdsp" +utvideo_decoder_select="bswapdsp huffyuvdsp" utvideo_encoder_select="bswapdsp huffman huffyuvencdsp" vble_decoder_select="huffyuvdsp" vc1_decoder_select="blockdsp error_resilience h263_decoder h264qpel intrax8 mpeg_er mpegvideo vc1dsp" diff --git a/libavcodec/utvideo.h b/libavcodec/utvideo.h index bc83a28d43645..2fa2b7cb93599 100644 --- a/libavcodec/utvideo.h +++ b/libavcodec/utvideo.h @@ -30,6 +30,7 @@ #include "libavutil/common.h" #include "avcodec.h" #include "bswapdsp.h" +#include "huffyuvdsp.h" #include "huffyuvencdsp.h" enum { @@ -68,6 +69,7 @@ typedef struct UtvideoContext { const AVClass *class; AVCodecContext *avctx; BswapDSPContext bdsp; + HuffYUVDSPContext hdspdec; HuffYUVEncDSPContext hdsp; uint32_t frame_info_size, flags, frame_info; diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index f5fae8ba44e6e..67ffe6f253803 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -373,8 +373,110 @@ static void restore_rgb_planes10(AVFrame *frame, int width, int height) } } -static void restore_median(uint8_t *src, int step, ptrdiff_t stride, - int width, int height, int slices, int rmode) +static void restore_median_planar(UtvideoContext *c, uint8_t *src, + ptrdiff_t stride, int width, int height, + int slices, int rmode) +{ + int i, j, slice; + int A, B, C; + uint8_t *bsrc; + int slice_start, slice_height; + const int cmask = ~rmode; + + for (slice = 0; slice < slices; slice++) { + slice_start = ((slice * height) / slices) & cmask; + slice_height = ((((slice + 1) * height) / slices) & cmask) - + slice_start; + + if (!slice_height) + continue; + bsrc = src + slice_start * stride; + + // first line - left neighbour prediction + bsrc[0] += 0x80; + c->hdspdec.add_hfyu_left_pred(bsrc, bsrc, width, 0); + bsrc += stride; + if (slice_height <= 1) + continue; + // second line - first element has top prediction, the rest uses median + C = bsrc[-stride]; + bsrc[0] += C; + A = bsrc[0]; + for (i = 1; i < width; i++) { + B = bsrc[i - stride]; + bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C)); + C = B; + A = bsrc[i]; + } + bsrc += stride; + // the rest of lines use continuous median prediction + for (j = 2; j < slice_height; j++) { + c->hdspdec.add_hfyu_median_pred(bsrc, bsrc - stride, + bsrc, width, &A, &B); + bsrc += stride; + } + } +} + +/* UtVideo interlaced mode treats every two lines as a single one, + * so restoring function should take care of possible padding between + * two parts of the same "line". + */ +static void restore_median_planar_il(UtvideoContext *c, uint8_t *src, + ptrdiff_t stride, int width, int height, + int slices, int rmode) +{ + int i, j, slice; + int A, B, C; + uint8_t *bsrc; + int slice_start, slice_height; + const int cmask = ~(rmode ? 3 : 1); + const int stride2 = stride << 1; + + for (slice = 0; slice < slices; slice++) { + slice_start = ((slice * height) / slices) & cmask; + slice_height = ((((slice + 1) * height) / slices) & cmask) - + slice_start; + slice_height >>= 1; + if (!slice_height) + continue; + + bsrc = src + slice_start * stride; + + // first line - left neighbour prediction + bsrc[0] += 0x80; + A = c->hdspdec.add_hfyu_left_pred(bsrc, bsrc, width, 0); + c->hdspdec.add_hfyu_left_pred(bsrc + stride, bsrc + stride, width, A); + bsrc += stride2; + if (slice_height <= 1) + continue; + // second line - first element has top prediction, the rest uses median + C = bsrc[-stride2]; + bsrc[0] += C; + A = bsrc[0]; + for (i = 1; i < width; i++) { + B = bsrc[i - stride2]; + bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C)); + C = B; + A = bsrc[i]; + } + c->hdspdec.add_hfyu_median_pred(bsrc + stride, bsrc - stride, + bsrc + stride, width, &A, &B); + bsrc += stride2; + // the rest of lines use continuous median prediction + for (j = 2; j < slice_height; j++) { + c->hdspdec.add_hfyu_median_pred(bsrc, bsrc - stride2, + bsrc, width, &A, &B); + c->hdspdec.add_hfyu_median_pred(bsrc + stride, bsrc - stride, + bsrc + stride, width, &A, &B); + bsrc += stride2; + } + } +} + +static void restore_median_packed(uint8_t *src, int step, ptrdiff_t stride, + int width, int height, + int slices, int rmode) { int i, j, slice; int A, B, C; @@ -429,8 +531,9 @@ static void restore_median(uint8_t *src, int step, ptrdiff_t stride, * so restoring function should take care of possible padding between * two parts of the same "line". */ -static void restore_median_il(uint8_t *src, int step, ptrdiff_t stride, - int width, int height, int slices, int rmode) +static void restore_median_packed_il(uint8_t *src, int step, ptrdiff_t stride, + int width, int height, + int slices, int rmode) { int i, j, slice; int A, B, C; @@ -613,14 +716,14 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return ret; if (c->frame_pred == PRED_MEDIAN) { if (!c->interlaced) { - restore_median(frame.f->data[0] + ff_ut_rgb_order[i], - c->planes, frame.f->linesize[0], avctx->width, - avctx->height, c->slices, 0); + restore_median_packed(frame.f->data[0] + ff_ut_rgb_order[i], + c->planes, frame.f->linesize[0], avctx->width, + avctx->height, c->slices, 0); } else { - restore_median_il(frame.f->data[0] + ff_ut_rgb_order[i], - c->planes, frame.f->linesize[0], - avctx->width, avctx->height, c->slices, - 0); + restore_median_packed_il(frame.f->data[0] + ff_ut_rgb_order[i], + c->planes, frame.f->linesize[0], + avctx->width, avctx->height, c->slices, + 0); } } } @@ -649,14 +752,14 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return ret; if (c->frame_pred == PRED_MEDIAN) { if (!c->interlaced) { - restore_median(frame.f->data[i], 1, frame.f->linesize[i], - avctx->width >> !!i, avctx->height >> !!i, - c->slices, !i); + restore_median_planar(c, frame.f->data[i], frame.f->linesize[i], + avctx->width >> !!i, avctx->height >> !!i, + c->slices, !i); } else { - restore_median_il(frame.f->data[i], 1, frame.f->linesize[i], - avctx->width >> !!i, - avctx->height >> !!i, - c->slices, !i); + restore_median_planar_il(c, frame.f->data[i], frame.f->linesize[i], + avctx->width >> !!i, + avctx->height >> !!i, + c->slices, !i); } } } @@ -670,13 +773,13 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return ret; if (c->frame_pred == PRED_MEDIAN) { if (!c->interlaced) { - restore_median(frame.f->data[i], 1, frame.f->linesize[i], - avctx->width >> !!i, avctx->height, - c->slices, 0); + restore_median_planar(c, frame.f->data[i], frame.f->linesize[i], + avctx->width >> !!i, avctx->height, + c->slices, 0); } else { - restore_median_il(frame.f->data[i], 1, frame.f->linesize[i], - avctx->width >> !!i, avctx->height, - c->slices, 0); + restore_median_planar_il(c, frame.f->data[i], frame.f->linesize[i], + avctx->width >> !!i, avctx->height, + c->slices, 0); } } } @@ -690,13 +793,13 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return ret; if (c->frame_pred == PRED_MEDIAN) { if (!c->interlaced) { - restore_median(frame.f->data[i], 1, frame.f->linesize[i], - avctx->width, avctx->height, - c->slices, 0); + restore_median_planar(c, frame.f->data[i], frame.f->linesize[i], + avctx->width, avctx->height, + c->slices, 0); } else { - restore_median_il(frame.f->data[i], 1, frame.f->linesize[i], - avctx->width, avctx->height, - c->slices, 0); + restore_median_planar_il(c, frame.f->data[i], frame.f->linesize[i], + avctx->width, avctx->height, + c->slices, 0); } } } @@ -729,6 +832,7 @@ static av_cold int decode_init(AVCodecContext *avctx) c->avctx = avctx; ff_bswapdsp_init(&c->bdsp); + ff_huffyuvdsp_init(&c->hdspdec); if (avctx->extradata_size >= 16) { av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", From 378460fef1e563704bc5a307ba748a2b819cc09d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 7 Apr 2017 20:09:22 +0200 Subject: [PATCH 0152/2557] utvideodec: Support for gradient prediction Introduced with utvideo 18. Signed-off-by: Paul B Mahol Signed-off-by: Luca Barbato --- libavcodec/utvideodec.c | 232 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 227 insertions(+), 5 deletions(-) diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 67ffe6f253803..910d64b57e192 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -602,6 +602,189 @@ static void restore_median_packed_il(uint8_t *src, int step, ptrdiff_t stride, } } +static void restore_gradient_planar(UtvideoContext *c, uint8_t *src, ptrdiff_t stride, + int width, int height, int slices, int rmode) +{ + int i, j, slice; + int A, B, C; + uint8_t *bsrc; + int slice_start, slice_height; + const int cmask = ~rmode; + + for (slice = 0; slice < slices; slice++) { + slice_start = ((slice * height) / slices) & cmask; + slice_height = ((((slice + 1) * height) / slices) & cmask) - + slice_start; + + if (!slice_height) + continue; + bsrc = src + slice_start * stride; + + // first line - left neighbour prediction + bsrc[0] += 0x80; + c->hdspdec.add_hfyu_left_pred(bsrc, bsrc, width, 0); + bsrc += stride; + if (slice_height <= 1) + continue; + for (j = 1; j < slice_height; j++) { + // second line - first element has top prediction, the rest uses gradient + bsrc[0] = (bsrc[0] + bsrc[-stride]) & 0xFF; + for (i = 1; i < width; i++) { + A = bsrc[i - stride]; + B = bsrc[i - (stride + 1)]; + C = bsrc[i - 1]; + bsrc[i] = (A - B + C + bsrc[i]) & 0xFF; + } + bsrc += stride; + } + } +} + +static void restore_gradient_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_t stride, + int width, int height, int slices, int rmode) +{ + int i, j, slice; + int A, B, C; + uint8_t *bsrc; + int slice_start, slice_height; + const int cmask = ~(rmode ? 3 : 1); + const ptrdiff_t stride2 = stride << 1; + + for (slice = 0; slice < slices; slice++) { + slice_start = ((slice * height) / slices) & cmask; + slice_height = ((((slice + 1) * height) / slices) & cmask) - + slice_start; + slice_height >>= 1; + if (!slice_height) + continue; + + bsrc = src + slice_start * stride; + + // first line - left neighbour prediction + bsrc[0] += 0x80; + A = c->hdspdec.add_hfyu_left_pred(bsrc, bsrc, width, 0); + c->hdspdec.add_hfyu_left_pred(bsrc + stride, bsrc + stride, width, A); + bsrc += stride2; + if (slice_height <= 1) + continue; + for (j = 1; j < slice_height; j++) { + // second line - first element has top prediction, the rest uses gradient + bsrc[0] = (bsrc[0] + bsrc[-stride2]) & 0xFF; + for (i = 1; i < width; i++) { + A = bsrc[i - stride2]; + B = bsrc[i - (stride2 + 1)]; + C = bsrc[i - 1]; + bsrc[i] = (A - B + C + bsrc[i]) & 0xFF; + } + for (i = 0; i < width; i++) { + A = bsrc[i - stride]; + B = bsrc[i - (1 + stride)]; + C = bsrc[i - 1 + stride]; + bsrc[i + stride] = (A - B + C + bsrc[i + stride]) & 0xFF; + } + bsrc += stride2; + } + } +} + +static void restore_gradient_packed(uint8_t *src, int step, ptrdiff_t stride, + int width, int height, int slices, int rmode) +{ + int i, j, slice; + int A, B, C; + uint8_t *bsrc; + int slice_start, slice_height; + const int cmask = ~rmode; + + for (slice = 0; slice < slices; slice++) { + slice_start = ((slice * height) / slices) & cmask; + slice_height = ((((slice + 1) * height) / slices) & cmask) - + slice_start; + + if (!slice_height) + continue; + bsrc = src + slice_start * stride; + + // first line - left neighbour prediction + bsrc[0] += 0x80; + A = bsrc[0]; + for (i = step; i < width * step; i += step) { + bsrc[i] += A; + A = bsrc[i]; + } + bsrc += stride; + if (slice_height <= 1) + continue; + for (j = 1; j < slice_height; j++) { + // second line - first element has top prediction, the rest uses gradient + C = bsrc[-stride]; + bsrc[0] += C; + for (i = step; i < width * step; i += step) { + A = bsrc[i - stride]; + B = bsrc[i - (stride + step)]; + C = bsrc[i - step]; + bsrc[i] = (A - B + C + bsrc[i]) & 0xFF; + } + bsrc += stride; + } + } +} + +static void restore_gradient_packed_il(uint8_t *src, int step, ptrdiff_t stride, + int width, int height, int slices, int rmode) +{ + int i, j, slice; + int A, B, C; + uint8_t *bsrc; + int slice_start, slice_height; + const int cmask = ~(rmode ? 3 : 1); + const ptrdiff_t stride2 = stride << 1; + + for (slice = 0; slice < slices; slice++) { + slice_start = ((slice * height) / slices) & cmask; + slice_height = ((((slice + 1) * height) / slices) & cmask) - + slice_start; + slice_height >>= 1; + if (!slice_height) + continue; + + bsrc = src + slice_start * stride; + + // first line - left neighbour prediction + bsrc[0] += 0x80; + A = bsrc[0]; + for (i = step; i < width * step; i += step) { + bsrc[i] += A; + A = bsrc[i]; + } + for (i = 0; i < width * step; i += step) { + bsrc[stride + i] += A; + A = bsrc[stride + i]; + } + bsrc += stride2; + if (slice_height <= 1) + continue; + for (j = 1; j < slice_height; j++) { + // second line - first element has top prediction, the rest uses gradient + C = bsrc[-stride2]; + bsrc[0] += C; + for (i = step; i < width * step; i += step) { + A = bsrc[i - stride2]; + B = bsrc[i - (stride2 + step)]; + C = bsrc[i - step]; + bsrc[i] = (A - B + C + bsrc[i]) & 0xFF; + } + for (i = 0; i < width * step; i += step) { + A = bsrc[i - stride]; + B = bsrc[i - (step + stride)]; + C = bsrc[i - step + stride]; + bsrc[i + stride] = (A - B + C + bsrc[i + stride]) & 0xFF; + } + bsrc += stride2; + } + } +} + static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { @@ -691,11 +874,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, c->frame_pred = (c->frame_info >> 8) & 3; - if (c->frame_pred == PRED_GRADIENT) { - avpriv_request_sample(avctx, "Frame with gradient prediction"); - return AVERROR_PATCHWELCOME; - } - av_fast_malloc(&c->slice_bits, &c->slice_bits_size, max_slice_size + AV_INPUT_BUFFER_PADDING_SIZE); @@ -725,6 +903,18 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, avctx->width, avctx->height, c->slices, 0); } + } else if (c->frame_pred == PRED_GRADIENT) { + if (!c->interlaced) { + restore_gradient_packed(frame.f->data[0] + ff_ut_rgb_order[i], + c->planes, frame.f->linesize[0], + avctx->width, avctx->height, + c->slices, 0); + } else { + restore_gradient_packed_il(frame.f->data[0] + ff_ut_rgb_order[i], + c->planes, frame.f->linesize[0], + avctx->width, avctx->height, + c->slices, 0); + } } } restore_rgb_planes(frame.f->data[0], c->planes, frame.f->linesize[0], @@ -761,6 +951,18 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, avctx->height >> !!i, c->slices, !i); } + } else if (c->frame_pred == PRED_GRADIENT) { + if (!c->interlaced) { + restore_gradient_planar(c, frame.f->data[i], frame.f->linesize[i], + avctx->width >> !!i, + avctx->height >> !!i, + c->slices, !i); + } else { + restore_gradient_planar_il(c, frame.f->data[i], frame.f->linesize[i], + avctx->width >> !!i, + avctx->height >> !!i, + c->slices, !i); + } } } break; @@ -781,6 +983,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, avctx->width >> !!i, avctx->height, c->slices, 0); } + } else if (c->frame_pred == PRED_GRADIENT) { + if (!c->interlaced) { + restore_gradient_planar(c, frame.f->data[i], frame.f->linesize[i], + avctx->width >> !!i, avctx->height, + c->slices, 0); + } else { + restore_gradient_planar_il(c, frame.f->data[i], frame.f->linesize[i], + avctx->width >> !!i, avctx->height, + c->slices, 0); + } } } break; @@ -801,6 +1013,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, avctx->width, avctx->height, c->slices, 0); } + } else if (c->frame_pred == PRED_GRADIENT) { + if (!c->interlaced) { + restore_gradient_planar(c, frame.f->data[i], frame.f->linesize[i], + avctx->width, avctx->height, + c->slices, 0); + } else { + restore_gradient_planar_il(c, frame.f->data[i], frame.f->linesize[i], + avctx->width, avctx->height, + c->slices, 0); + } } } break; From f56fa95cd13f627891a1bfb66bf61b971b9e0238 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sat, 15 Apr 2017 14:39:45 +0200 Subject: [PATCH 0153/2557] swscale: Do not shift negative values directly It is undefined in C as reported: warning: shifting a negative signed value is undefined --- libswscale/output.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/libswscale/output.c b/libswscale/output.c index cfb204300a535..07edcfd4cc45b 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -130,6 +130,9 @@ DECLARE_ALIGNED(8, const uint8_t, ff_dither_8x8_220)[8][8] = { AV_WL16(pos, bias + av_clip_ ## signedness ## 16(val >> shift)); \ } +// Shifting negative amounts is undefined in C +#define SHIFT_LEFT(val, shift) ((val) * (1 << (shift))) + static av_always_inline void yuv2plane1_16_c_template(const int32_t *src, uint16_t *dest, int dstW, int big_endian, int output_bits) @@ -601,8 +604,8 @@ yuv2rgb48_X_c_template(SwsContext *c, const int16_t *lumFilter, int j; int Y1 = -0x40000000; int Y2 = -0x40000000; - int U = -128 << 23; // 19 - int V = -128 << 23; + int U = SHIFT_LEFT(-128, 23); // 19 + int V = SHIFT_LEFT(-128, 23); int R, G, B; for (j = 0; j < lumFilterSize; j++) { @@ -663,8 +666,8 @@ yuv2rgb48_2_c_template(SwsContext *c, const int32_t *buf[2], for (i = 0; i < ((dstW + 1) >> 1); i++) { int Y1 = (buf0[i * 2] * yalpha1 + buf1[i * 2] * yalpha) >> 14; int Y2 = (buf0[i * 2 + 1] * yalpha1 + buf1[i * 2 + 1] * yalpha) >> 14; - int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha + (-128 << 23)) >> 14; - int V = (vbuf0[i] * uvalpha1 + vbuf1[i] * uvalpha + (-128 << 23)) >> 14; + int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha + SHIFT_LEFT(-128, 23)) >> 14; + int V = (vbuf0[i] * uvalpha1 + vbuf1[i] * uvalpha + SHIFT_LEFT(-128, 23)) >> 14; int R, G, B; Y1 -= c->yuv2rgb_y_offset; @@ -701,8 +704,8 @@ yuv2rgb48_1_c_template(SwsContext *c, const int32_t *buf0, for (i = 0; i < ((dstW + 1) >> 1); i++) { int Y1 = (buf0[i * 2] ) >> 2; int Y2 = (buf0[i * 2 + 1]) >> 2; - int U = (ubuf0[i] + (-128 << 11)) >> 2; - int V = (vbuf0[i] + (-128 << 11)) >> 2; + int U = (ubuf0[i] + SHIFT_LEFT(-128, 11)) >> 2; + int V = (vbuf0[i] + SHIFT_LEFT(-128, 11)) >> 2; int R, G, B; Y1 -= c->yuv2rgb_y_offset; @@ -729,8 +732,8 @@ yuv2rgb48_1_c_template(SwsContext *c, const int32_t *buf0, for (i = 0; i < ((dstW + 1) >> 1); i++) { int Y1 = (buf0[i * 2] ) >> 2; int Y2 = (buf0[i * 2 + 1]) >> 2; - int U = (ubuf0[i] + ubuf1[i] + (-128 << 12)) >> 3; - int V = (vbuf0[i] + vbuf1[i] + (-128 << 12)) >> 3; + int U = (ubuf0[i] + ubuf1[i] + SHIFT_LEFT(-128, 12)) >> 3; + int V = (vbuf0[i] + vbuf1[i] + SHIFT_LEFT(-128, 12)) >> 3; int R, G, B; Y1 -= c->yuv2rgb_y_offset; @@ -1172,8 +1175,8 @@ yuv2rgb_full_X_c_template(SwsContext *c, const int16_t *lumFilter, for (i = 0; i < dstW; i++) { int j; int Y = 0; - int U = -128 << 19; - int V = -128 << 19; + int U = SHIFT_LEFT(-128, 19); + int V = SHIFT_LEFT(-128, 19); int R, G, B, A; for (j = 0; j < lumFilterSize; j++) { From 37f573543c4fd7f44339e04d8d15b95118493ddd Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sat, 15 Apr 2017 14:55:33 +0200 Subject: [PATCH 0154/2557] swscale: Convert the check check_image_pointers helper to a macro Avoid warnings about types mismatch and make the code a little simpler. --- libswscale/swscale_unscaled.c | 37 ++++++++++++++--------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index d3863bba1089e..f130ac58cb47c 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -1190,20 +1190,19 @@ static void reset_ptr(const uint8_t *src[], enum AVPixelFormat format) } } -static int check_image_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, - const int linesizes[4]) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - int i; - - for (i = 0; i < 4; i++) { - int plane = desc->comp[i].plane; - if (!data[plane] || !linesizes[plane]) - return 0; - } - - return 1; -} +#define CHECK_IMAGE_POINTERS(data, pix_fmt, linesizes, msg) \ + do { \ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); \ + int i; \ + \ + for (i = 0; i < 4; i++) { \ + int plane = desc->comp[i].plane; \ + if (!data[plane] || !linesizes[plane]) { \ + av_log(c, AV_LOG_ERROR, msg); \ + return 0; \ + } \ + } \ + } while (0) /** * swscale wrapper, so we don't need to export the SwsContext. @@ -1223,14 +1222,8 @@ int attribute_align_arg sws_scale(struct SwsContext *c, if (srcSliceH == 0) return 0; - if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) { - av_log(c, AV_LOG_ERROR, "bad src image pointers\n"); - return 0; - } - if (!check_image_pointers(dst, c->dstFormat, dstStride)) { - av_log(c, AV_LOG_ERROR, "bad dst image pointers\n"); - return 0; - } + CHECK_IMAGE_POINTERS(srcSlice, c->srcFormat, srcStride, "bad src image pointers\n"); + CHECK_IMAGE_POINTERS(dst, c->dstFormat, dstStride, "bad dst image pointers\n"); if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) { av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n"); From 5352802da81f2083e65d466612e639a4e6e5530e Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 17 Apr 2017 12:53:14 +0000 Subject: [PATCH 0155/2557] dca: Account for lfe when checking for the channel count Bug-Id: 1037 CC: libav-stable@libav.org --- libavcodec/dcadec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c index ed1ed2d5f338d..3fe46cdc5cc32 100644 --- a/libavcodec/dcadec.c +++ b/libavcodec/dcadec.c @@ -1300,7 +1300,7 @@ static int set_channel_layout(AVCodecContext *avctx, int channels) s->channel_order_tab = ff_dca_channel_reorder_nolfe[s->amode]; } - if (channels < ff_dca_channels[s->amode]) + if (channels < ff_dca_channels[s->amode] + !!s->lfe) return AVERROR_INVALIDDATA; if (channels > !!s->lfe && From 4809781586d1c956005f72946a2aab5915eab350 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 18 Apr 2017 20:21:35 +0200 Subject: [PATCH 0156/2557] travis: Exclude gcc for the macOS target On a normal macOS setup, 'gcc' is a symlink to clang. Therefore there is little point in running the tests twice, with CC=gcc and CC=clang. --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6f9647a70134b..5aa2802636f14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,10 @@ addons: compiler: - clang - gcc +matrix: + exclude: + - os: osx + compiler: gcc cache: directories: - libav-samples From 279e3aaa14daba6b7a37d75f3fb6e29c732d123f Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 17 Apr 2017 14:10:52 +0000 Subject: [PATCH 0157/2557] flv: Validate the packet size Size can be negative at that point. Bug-Id: 1041 CC: libav-stable@libav.org --- libavformat/flvdec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 693c859ebfa70..1b29740f41b11 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -912,6 +912,12 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) st->codecpar->codec_id == AV_CODEC_ID_H264) { int type = avio_r8(s->pb); size--; + + if (size < 0) { + ret = AVERROR_INVALIDDATA; + goto leave; + } + if (st->codecpar->codec_id == AV_CODEC_ID_H264) { // sign extension int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000; From f2c469b73f8ac3dd6a98d38281f61b68ea6dd336 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 17 Apr 2017 19:11:57 +0000 Subject: [PATCH 0158/2557] mjpeg: Report non-3 component rgb lossless as not supported Bug-Id: 1043 CC: libav-stable@libav.org --- libavcodec/mjpegdec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 13d3e8cb02864..296ca59018807 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -1129,6 +1129,12 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, for (i = s->mjpb_skiptosod; i > 0; i--) skip_bits(&s->gb, 8); + if (s->lossless && s->rgb && nb_components != 3) { + avpriv_request_sample(s->avctx, + "Lossless RGB image without 3 components"); + return AVERROR_PATCHWELCOME; + } + next_field: for (i = 0; i < nb_components; i++) s->last_dc[i] = 1024; From 1731c3530bffb876deb9e00dfffdf9841a8412cd Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 17 Apr 2017 19:25:35 +0000 Subject: [PATCH 0159/2557] mm: Skip unexpected audio packets Bug-Id: 1046 CC: libav-stable@libav.org --- libavformat/mm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavformat/mm.c b/libavformat/mm.c index 16505502fde9c..a94d2611a211b 100644 --- a/libavformat/mm.c +++ b/libavformat/mm.c @@ -174,6 +174,12 @@ static int read_packet(AVFormatContext *s, return 0; case MM_TYPE_AUDIO : + if (s->nb_streams != 2) { + av_log(s, AV_LOG_ERROR, + "Unexpected audio packet, skipping\n"); + avio_skip(pb, length); + return AVERROR_INVALIDDATA; + } if (av_get_packet(s->pb, pkt, length)<0) return AVERROR(ENOMEM); pkt->size = length; From e00db9f78bb475ed5103364f61892f4e75ef89ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 19 Apr 2017 10:37:51 +0300 Subject: [PATCH 0160/2557] checkasm: hevc: Add a hevc_ prefix to the add_residual functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it easier to group them with the rest when running e.g. --bench=hevc. Signed-off-by: Martin Storsjö --- tests/checkasm/hevc_add_res.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/checkasm/hevc_add_res.c b/tests/checkasm/hevc_add_res.c index 2cd97eaf362af..c9ed86b5cc43a 100644 --- a/tests/checkasm/hevc_add_res.c +++ b/tests/checkasm/hevc_add_res.c @@ -61,7 +61,7 @@ static void check_add_res(HEVCDSPContext h, int bit_depth) memcpy(res1, res0, sizeof(*res0) * size); memcpy(dst1, dst0, size); - if (check_func(h.add_residual[i - 2], "add_res_%dx%d_%d", block_size, block_size, bit_depth)) { + if (check_func(h.add_residual[i - 2], "hevc_add_res_%dx%d_%d", block_size, block_size, bit_depth)) { call_ref(dst0, res0, stride); call_new(dst1, res1, stride); if (memcmp(dst0, dst1, size)) From b22094d74901fb3ac203c8322f8d84aded470bfb Mon Sep 17 00:00:00 2001 From: Aaron Levinson Date: Sun, 16 Apr 2017 18:07:42 -0700 Subject: [PATCH 0161/2557] qsvenc: Use MFXVideoENCODE_Query() to update the parameters Fill out the default/unset parameters with ones actually in use. Matches the current MediaSDK example code. Signed-off-by: Luca Barbato --- libavcodec/qsvenc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index bd8c24321ed05..6ac5ca1340e85 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -757,10 +757,18 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) if (ret < 0) return ret; + ret = MFXVideoENCODE_Query(q->session, &q->param, &q->param); + if (ret == MFX_WRN_PARTIAL_ACCELERATION) { + av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n"); + } else if (ret < 0) { + return ff_qsv_print_error(avctx, ret, + "Error querying encoder params"); + } + ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req); if (ret < 0) return ff_qsv_print_error(avctx, ret, - "Error querying the encoding parameters"); + "Error querying (IOSurf) the encoding parameters"); if (opaque_alloc) { ret = qsv_init_opaque_alloc(avctx, q); From 8fd8f91e47f33cd82371a97ac81afc476144964f Mon Sep 17 00:00:00 2001 From: Aaron Levinson Date: Sun, 16 Apr 2017 18:06:37 -0700 Subject: [PATCH 0162/2557] qsvenc: Make sure the interlaced encoding works And reduce the vertical alignment constraint when possible to reduce the memory usage. Signed-off-by: Luca Barbato --- libavcodec/qsvenc.c | 29 +++++++++++++++++++++++------ libavcodec/qsvenc.h | 1 + 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 6ac5ca1340e85..7c6ad09dda450 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -366,8 +366,6 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) return AVERROR_BUG; q->param.mfx.CodecId = ret; - q->width_align = avctx->codec_id == AV_CODEC_ID_HEVC ? 32 : 16; - if (avctx->level > 0) q->param.mfx.CodecLevel = avctx->level; @@ -389,20 +387,39 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); - q->param.mfx.FrameInfo.Width = FFALIGN(avctx->width, q->width_align); - q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, 32); q->param.mfx.FrameInfo.CropX = 0; q->param.mfx.FrameInfo.CropY = 0; q->param.mfx.FrameInfo.CropW = avctx->width; q->param.mfx.FrameInfo.CropH = avctx->height; q->param.mfx.FrameInfo.AspectRatioW = avctx->sample_aspect_ratio.num; q->param.mfx.FrameInfo.AspectRatioH = avctx->sample_aspect_ratio.den; - q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; q->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; q->param.mfx.FrameInfo.BitDepthLuma = desc->comp[0].depth; q->param.mfx.FrameInfo.BitDepthChroma = desc->comp[0].depth; q->param.mfx.FrameInfo.Shift = desc->comp[0].depth > 8; + // TODO: detect version of MFX--if the minor version is greater than + // or equal to 19, then can use the same alignment settings as H.264 + // for HEVC + q->width_align = avctx->codec_id == AV_CODEC_ID_HEVC ? 32 : 16; + q->param.mfx.FrameInfo.Width = FFALIGN(avctx->width, q->width_align); + + if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { + // it is important that PicStruct be setup correctly from the + // start--otherwise, encoding doesn't work and results in a bunch + // of incompatible video parameter errors + q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_FIELD_TFF; + // height alignment always must be 32 for interlaced video + q->height_align = 32; + } else { + q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; + // for progressive video, the height should be aligned to 16 for + // H.264. For HEVC, depending on the version of MFX, it should be + // either 32 or 16. The lower number is better if possible. + q->height_align = avctx->codec_id == AV_CODEC_ID_HEVC ? 32 : 16; + } + q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, q->height_align); + if (avctx->hw_frames_ctx) { AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; @@ -898,7 +915,7 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, } else { /* make a copy if the input is not padded as libmfx requires */ if (frame->height & 31 || frame->linesize[0] & (q->width_align - 1)) { - qf->frame->height = FFALIGN(frame->height, 32); + qf->frame->height = FFALIGN(frame->height, q->height_align); qf->frame->width = FFALIGN(frame->width, q->width_align); ret = ff_get_buffer(q->avctx, qf->frame, AV_GET_BUFFER_FLAG_REF); diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 13e4c47481b86..a6399040e91ce 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -79,6 +79,7 @@ typedef struct QSVEncContext { int packet_size; int width_align; + int height_align; mfxVideoParam param; mfxFrameAllocRequest req; From 0fd0d4fd0a518e30ff23972828ad7cf7f35cfb9d Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 19 Apr 2017 11:11:09 +0200 Subject: [PATCH 0163/2557] swscale-test: const correctness --- libswscale/tests/swscale.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/libswscale/tests/swscale.c b/libswscale/tests/swscale.c index 364e2a75eb41c..ece0757f7b181 100644 --- a/libswscale/tests/swscale.c +++ b/libswscale/tests/swscale.c @@ -54,8 +54,8 @@ (x) == AV_PIX_FMT_RGB32_1 || \ (x) == AV_PIX_FMT_YUVA420P) -static uint64_t getSSD(uint8_t *src1, uint8_t *src2, int stride1, - int stride2, int w, int h) +static uint64_t getSSD(const uint8_t * const src1, const uint8_t * const src2, + int stride1, int stride2, int w, int h) { int x, y; uint64_t ssd = 0; @@ -79,7 +79,7 @@ struct Results { // test by ref -> src -> dst -> out & compare out against ref // ref & out are YV12 -static int doTest(uint8_t *ref[4], int refStride[4], int w, int h, +static int doTest(const uint8_t * const ref[4], int refStride[4], int w, int h, enum AVPixelFormat srcFormat, enum AVPixelFormat dstFormat, int srcW, int srcH, int dstW, int dstH, int flags, struct Results *r) @@ -89,7 +89,7 @@ static int doTest(uint8_t *ref[4], int refStride[4], int w, int h, const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(dstFormat); static enum AVPixelFormat cur_srcFormat; static int cur_srcW, cur_srcH; - static uint8_t *src[4]; + static const uint8_t *src[4]; static int srcStride[4]; uint8_t *dst[4] = { 0 }; uint8_t *out[4] = { 0 }; @@ -126,7 +126,8 @@ static int doTest(uint8_t *ref[4], int refStride[4], int w, int h, res = -1; goto end; } - sws_scale(srcContext, ref, refStride, 0, h, src, srcStride); + sws_scale(srcContext, ref, refStride, 0, h, + (uint8_t * const *) src, srcStride); sws_freeContext(srcContext); cur_srcFormat = srcFormat; @@ -198,7 +199,8 @@ static int doTest(uint8_t *ref[4], int refStride[4], int w, int h, res = -1; goto end; } - sws_scale(outContext, dst, dstStride, 0, dstH, out, refStride); + sws_scale(outContext, (const uint8_t * const *) dst, dstStride, 0, dstH, + out, refStride); ssdY = getSSD(ref[0], out[0], refStride[0], refStride[0], w, h); if (hasChroma(srcFormat) && hasChroma(dstFormat)) { @@ -236,7 +238,8 @@ static int doTest(uint8_t *ref[4], int refStride[4], int w, int h, return res; } -static void selfTest(uint8_t *ref[4], int refStride[4], int w, int h, +static void selfTest(const uint8_t * const ref[4], int refStride[4], + int w, int h, enum AVPixelFormat srcFormat_in, enum AVPixelFormat dstFormat_in) { @@ -286,7 +289,8 @@ static void selfTest(uint8_t *ref[4], int refStride[4], int w, int h, } } -static int fileTest(uint8_t *ref[4], int refStride[4], int w, int h, FILE *fp, +static int fileTest(const uint8_t * const ref[4], int refStride[4], + int w, int h, FILE *fp, enum AVPixelFormat srcFormat_in, enum AVPixelFormat dstFormat_in) { @@ -348,7 +352,7 @@ int main(int argc, char **argv) const uint8_t *rgb_src[4] = { rgb_data, NULL, NULL, NULL }; int rgb_stride[4] = { 4 * W, 0, 0, 0 }; uint8_t *data = av_malloc(4 * W * H); - uint8_t *src[4] = { data, data + W * H, data + W * H * 2, data + W * H * 3 }; + const uint8_t * const src[4] = { data, data + W * H, data + W * H * 2, data + W * H * 3 }; int stride[4] = { W, W, W, W }; int x, y; struct SwsContext *sws; @@ -367,7 +371,7 @@ int main(int argc, char **argv) for (y = 0; y < H; y++) for (x = 0; x < W * 4; x++) rgb_data[ x + y * 4 * W] = av_lfg_get(&rand); - sws_scale(sws, rgb_src, rgb_stride, 0, H, src, stride); + sws_scale(sws, rgb_src, rgb_stride, 0, H, (uint8_t * const *) src, stride); sws_freeContext(sws); av_free(rgb_data); From f25609ff06b093d82548c92fc2031cd2e66c20d3 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 22 Apr 2017 13:12:29 +0200 Subject: [PATCH 0164/2557] doc/examples/filter_audio: const correctness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit doc/examples/filter_audio.c:168:17: warning: assignment discards ‘const’ qualifier from pointer target type --- doc/examples/filter_audio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/examples/filter_audio.c b/doc/examples/filter_audio.c index 60fe107dda486..458004355ff44 100644 --- a/doc/examples/filter_audio.c +++ b/doc/examples/filter_audio.c @@ -64,13 +64,13 @@ static int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src, { AVFilterGraph *filter_graph; AVFilterContext *abuffer_ctx; - AVFilter *abuffer; + const AVFilter *abuffer; AVFilterContext *volume_ctx; - AVFilter *volume; + const AVFilter *volume; AVFilterContext *aformat_ctx; - AVFilter *aformat; + const AVFilter *aformat; AVFilterContext *abuffersink_ctx; - AVFilter *abuffersink; + const AVFilter *abuffersink; AVDictionary *options_dict = NULL; uint8_t options_str[1024]; From ecc5c4db2dd3a0f328d95df89daa59f78b4b2810 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 22 Apr 2017 13:19:04 +0200 Subject: [PATCH 0165/2557] doc/examples/output: Cast pointer to the right (const) type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit doc/examples/output.c:512:33: warning: passing argument 2 of ‘sws_scale’ from incompatible pointer type --- doc/examples/output.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/examples/output.c b/doc/examples/output.c index bb0da30041cb2..59e7b95d177c5 100644 --- a/doc/examples/output.c +++ b/doc/examples/output.c @@ -509,8 +509,9 @@ static AVFrame *get_video_frame(OutputStream *ost) } } fill_yuv_image(ost->tmp_frame, ost->next_pts, c->width, c->height); - sws_scale(ost->sws_ctx, ost->tmp_frame->data, ost->tmp_frame->linesize, - 0, c->height, ost->frame->data, ost->frame->linesize); + sws_scale(ost->sws_ctx, (const uint8_t * const *) ost->tmp_frame->data, + ost->tmp_frame->linesize, 0, c->height, ost->frame->data, + ost->frame->linesize); } else { fill_yuv_image(ost->frame, ost->next_pts, c->width, c->height); } From 2e1ab6a67dd5d9a30558d008aa6e541c68d76221 Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Sat, 22 Apr 2017 19:16:34 -0400 Subject: [PATCH 0166/2557] vc1dec: raise an error if sprite picture data is missing Bug-Id: 1013 CC: libav-stable@libav.org --- libavcodec/vc1dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 89b4f4bdce298..51745c12ec1e1 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -270,7 +270,7 @@ static int vc1_decode_sprites(VC1Context *v, GetBitContext* gb) vc1_parse_sprites(v, gb, &sd); - if (!s->current_picture.f->data[0]) { + if (!s->current_picture.f || !s->current_picture.f->data[0]) { av_log(avctx, AV_LOG_ERROR, "Got no sprites\n"); return -1; } From 3889dfde9c0284b008c5cfcbc921c1d137fb81e2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 24 Apr 2017 22:39:32 +0200 Subject: [PATCH 0167/2557] dca: Move the downmix request check outside the loop --- libavcodec/dcadec.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c index 3fe46cdc5cc32..9c1f878239a8a 100644 --- a/libavcodec/dcadec.c +++ b/libavcodec/dcadec.c @@ -932,7 +932,7 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index) return 0; } -static int dca_filter_channels(DCAContext *s, int block_index, int upsample) +static int dca_filter_channels(DCAContext *s, int block_index, int upsample, int downmix) { int k; @@ -1000,8 +1000,7 @@ static int dca_filter_channels(DCAContext *s, int block_index, int upsample) /* FIXME: This downmixing is probably broken with upsample. * Probably totally broken also with XLL in general. */ /* Downmixing to Stereo */ - if (s->audio_header.prim_channels + !!s->lfe > 2 && - s->avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) { + if (downmix) { dca_downmix(s->samples_chanptr, s->amode, !!s->lfe, s->downmix_coef, s->channel_order_tab); } @@ -1378,6 +1377,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, DCAContext *s = avctx->priv_data; int channels, full_channels; int upsample = 0; + int downmix; s->exss_ext_mask = 0; s->xch_present = 0; @@ -1488,6 +1488,9 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, return ret; } + downmix = s->audio_header.prim_channels > 2 && + avctx->request_channel_layout == AV_CH_LAYOUT_STEREO; + /* filter to get final output */ for (i = 0; i < (s->sample_blocks / SAMPLES_PER_SUBBAND); i++) { int ch; @@ -1497,7 +1500,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, for (; ch < full_channels; ch++) s->samples_chanptr[ch] = s->extra_channels[ch - channels] + i * block; - dca_filter_channels(s, i, upsample); + dca_filter_channels(s, i, upsample, downmix); /* If this was marked as a DTS-ES stream we need to subtract back- */ /* channel from SL & SR to remove matrixed back-channel signal */ From 44aafa3325ec09a120bdb81b8579b8dfd65b1693 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Thu, 6 Apr 2017 18:14:29 +0200 Subject: [PATCH 0168/2557] configure: Properly escape arguments in filter/filter_out helper functions The arguments may contain '$', which gets interpreted by the shell. Signed-off-by: Luca Barbato --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index e83a4cf69707b..967d7d9a102c4 100755 --- a/configure +++ b/configure @@ -433,7 +433,7 @@ filter(){ pat=$1 shift for v; do - eval "case $v in $pat) printf '%s ' $v ;; esac" + eval "case '$v' in $pat) printf '%s ' '$v' ;; esac" done } @@ -441,7 +441,7 @@ filter_out(){ pat=$1 shift for v; do - eval "case $v in $pat) ;; *) printf '%s ' $v ;; esac" + eval "case '$v' in $pat) ;; *) printf '%s ' '$v' ;; esac" done } From 41262498ff89ef48e5ce4823b2fc2dc514a3eb0c Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sun, 23 Apr 2017 14:10:20 +0000 Subject: [PATCH 0169/2557] configure: Fix sem_timedwait probe It requires pthreads. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 967d7d9a102c4..c7d03636189cb 100755 --- a/configure +++ b/configure @@ -4693,7 +4693,7 @@ if ! disabled pthreads && ! enabled w32threads; then fi enabled pthreads && - check_builtin sem_timedwait semaphore.h "sem_t *s; sem_init(s,0,0); sem_timedwait(s,0); sem_destroy(s)" + check_builtin sem_timedwait semaphore.h "sem_t *s; sem_init(s,0,0); sem_timedwait(s,0); sem_destroy(s)" $pthreads_extralibs disabled zlib || check_lib zlib zlib.h zlibVersion -lz disabled bzlib || check_lib bzlib bzlib.h BZ2_bzlibVersion -lbz2 From 8c0cadd17e98547d84e82111550caca4fb40ff8d Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 17 Apr 2017 22:22:17 +0000 Subject: [PATCH 0170/2557] avplay: Do not try to allocate new frames when the player is closing The allocation event can trigger while the decoding thread is already closing. Bug-Id: 1052 CC: libav-stable@libav.org --- avtools/avplay.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/avtools/avplay.c b/avtools/avplay.c index 26279e857d989..b6dbc52cf7222 100644 --- a/avtools/avplay.c +++ b/avtools/avplay.c @@ -213,6 +213,7 @@ typedef struct PlayerState { AVFilterContext *in_video_filter; // the first filter in the video chain AVFilterContext *out_video_filter; // the last filter in the video chain + SDL_mutex *video_filter_mutex; float skip_frames; float skip_frames_index; @@ -1201,6 +1202,7 @@ static void player_close(PlayerState *is) vp->bmp = NULL; } } + SDL_DestroyMutex(is->video_filter_mutex); SDL_DestroyMutex(is->pictq_mutex); SDL_DestroyCond(is->pictq_cond); SDL_DestroyMutex(is->subpq_mutex); @@ -1617,6 +1619,9 @@ static int video_thread(void *arg) stream_pause(player); } the_end: + SDL_LockMutex(is->video_filter_mutex); + is->out_video_filter = NULL; + SDL_UnlockMutex(is->video_filter_mutex); av_freep(&vfilters); avfilter_graph_free(&graph); av_packet_unref(&pkt); @@ -2552,6 +2557,8 @@ static int stream_open(PlayerState *is, return ret; } + is->video_filter_mutex = SDL_CreateMutex(); + /* start video display */ is->pictq_mutex = SDL_CreateMutex(); is->pictq_cond = SDL_CreateCond(); @@ -2827,8 +2834,12 @@ static void event_loop(void) do_exit(); break; case FF_ALLOC_EVENT: - video_open(event.user.data1); - alloc_picture(event.user.data1); + SDL_LockMutex(player->video_filter_mutex); + if (player->out_video_filter) { + video_open(event.user.data1); + alloc_picture(event.user.data1); + } + SDL_UnlockMutex(player->video_filter_mutex); break; case FF_REFRESH_EVENT: video_refresh_timer(event.user.data1); From 7c25523cc8e618e77dc84d960e41e9644eaf8c33 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 21 Apr 2017 12:27:17 +0200 Subject: [PATCH 0171/2557] utvideodec: Fix decoding odd sizes with interlaced video with some formats Signed-off-by: Paul B Mahol Signed-off-by: Luca Barbato --- libavcodec/utvideodec.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 910d64b57e192..0f58c83979e93 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -228,6 +228,16 @@ static int decode_plane10(UtvideoContext *c, int plane_no, return AVERROR_INVALIDDATA; } +static int compute_cmask(int plane_no, int interlaced, int pix_fmt) +{ + const int is_luma = (pix_fmt == AV_PIX_FMT_YUV420P) && !plane_no; + + if (interlaced) + return ~(1 + 2 * is_luma); + + return ~is_luma; +} + static int decode_plane(UtvideoContext *c, int plane_no, uint8_t *dst, int step, ptrdiff_t stride, int width, int height, @@ -238,7 +248,7 @@ static int decode_plane(UtvideoContext *c, int plane_no, VLC vlc; BitstreamContext bc; int prev, fsym; - const int cmask = ~(!plane_no && c->avctx->pix_fmt == AV_PIX_FMT_YUV420P); + const int cmask = compute_cmask(plane_no, c->interlaced, c->avctx->pix_fmt); if (build_huff(src, &vlc, &fsym)) { av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); From b812db66af160bfac2f64aef2ade4aed7eb76b12 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 21 Apr 2017 21:44:28 +0200 Subject: [PATCH 0172/2557] utvideodec: Fix gradient prediction when stride does not match width Signed-off-by: Paul B Mahol Signed-off-by: Luca Barbato --- libavcodec/utvideodec.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 0f58c83979e93..ed6368e4cd821 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -686,7 +686,11 @@ static void restore_gradient_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_ C = bsrc[i - 1]; bsrc[i] = (A - B + C + bsrc[i]) & 0xFF; } - for (i = 0; i < width; i++) { + A = bsrc[-stride]; + B = bsrc[-(1 + stride + stride - width)]; + C = bsrc[width - 1]; + bsrc[stride] = (A - B + C + bsrc[stride]) & 0xFF; + for (i = 1; i < width; i++) { A = bsrc[i - stride]; B = bsrc[i - (1 + stride)]; C = bsrc[i - 1 + stride]; @@ -784,7 +788,11 @@ static void restore_gradient_packed_il(uint8_t *src, int step, ptrdiff_t stride, C = bsrc[i - step]; bsrc[i] = (A - B + C + bsrc[i]) & 0xFF; } - for (i = 0; i < width * step; i += step) { + A = bsrc[-stride]; + B = bsrc[-(step + stride + stride - width * step)]; + C = bsrc[width * step - step]; + bsrc[stride] = (A - B + C + bsrc[stride]) & 0xFF; + for (i = step; i < width * step; i += step) { A = bsrc[i - stride]; B = bsrc[i - (step + stride)]; C = bsrc[i - step + stride]; From c55f2ae2b8d4de473f945aebd6a7a89b6b83e87a Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 17 Apr 2017 13:48:54 +0000 Subject: [PATCH 0173/2557] avprobe: Handle unknown values for the color description print_str() cannot print NULL. Bug-Id: 1040 CC: libav-stable@libav.org Signed-off-by: Luca Barbato --- avtools/avprobe.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/avtools/avprobe.c b/avtools/avprobe.c index 68f19220c8f34..5f5e670f1b60b 100644 --- a/avtools/avprobe.c +++ b/avtools/avprobe.c @@ -609,6 +609,12 @@ static char *tag_string(char *buf, int buf_size, int tag) return buf; } +static char *unknown_string(char *buf, int buf_size, int val) +{ + snprintf(buf, buf_size, "Unknown (%d)", val); + return buf; +} + static void show_packet(AVFormatContext *fmt_ctx, AVPacket *pkt) { char val_str[128]; @@ -660,6 +666,7 @@ static void show_stream(InputFile *ifile, InputStream *ist) char val_str[128]; AVRational display_aspect_ratio, *sar = NULL; const AVPixFmtDescriptor *desc; + const char *val; probe_object_header("stream"); @@ -718,11 +725,30 @@ static void show_stream(InputFile *ifile, InputStream *ist) probe_str("pix_fmt", desc ? desc->name : "unknown"); probe_int("level", par->level); - probe_str("color_range", av_color_range_name (par->color_range)); - probe_str("color_space", av_color_space_name (par->color_space)); - probe_str("color_trc", av_color_transfer_name (par->color_trc)); - probe_str("color_pri", av_color_primaries_name(par->color_primaries)); - probe_str("chroma_loc", av_chroma_location_name (par->chroma_location)); + val = av_color_range_name(par->color_range); + if (!val) + val = unknown_string(val_str, sizeof(val_str), par->color_range); + probe_str("color_range", val); + + val = av_color_space_name(par->color_space); + if (!val) + val = unknown_string(val_str, sizeof(val_str), par->color_space); + probe_str("color_space", val); + + val = av_color_transfer_name(par->color_trc); + if (!val) + val = unknown_string(val_str, sizeof(val_str), par->color_trc); + probe_str("color_trc", val); + + val = av_color_primaries_name(par->color_primaries); + if (!val) + val = unknown_string(val_str, sizeof(val_str), par->color_primaries); + probe_str("color_pri", val); + + val = av_chroma_location_name(par->chroma_location); + if (!val) + val = unknown_string(val_str, sizeof(val_str), par->chroma_location); + probe_str("chroma_loc", val); break; case AVMEDIA_TYPE_AUDIO: From 189157c3fc8eeb691e3684b09d971eb5ddb47d5b Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Thu, 2 Mar 2017 11:21:48 +0100 Subject: [PATCH 0174/2557] Add ClearVideo decoder Only I-frames are decoded for now. Signed-off-by: Diego Biurrun --- Changelog | 1 + doc/general.texi | 2 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/clearvideo.c | 391 ++++++++++++++++++++++++++++++++++++++++ libavcodec/codec_desc.c | 7 + libavcodec/version.h | 2 +- libavformat/riff.c | 2 + libavformat/rm.c | 1 + 10 files changed, 408 insertions(+), 1 deletion(-) create mode 100644 libavcodec/clearvideo.c diff --git a/Changelog b/Changelog index dccf173741fee..6fd30fddb92fc 100644 --- a/Changelog +++ b/Changelog @@ -14,6 +14,7 @@ version : - Cineform HD decoder - VP9 superframe split/merge bitstream filters - FM Screen Capture Codec decoder +- ClearVideo decoder (I-frames only) version 12: diff --git a/doc/general.texi b/doc/general.texi index b1a42c50f8fd6..905e2d1810dfe 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -703,6 +703,8 @@ following image formats are supported: @tab Used in the game Cyberia from Interplay. @item Interplay MVE video @tab @tab X @tab Used in Interplay .MVE files. +@item Iterated Systems ClearVideo @tab @tab X + @tab I-frames only @item Karl Morton's video codec @tab @tab X @tab Codec used in Worms games. @item Kega Game Video (KGV1) @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index e835133842867..b60ba5ef9633c 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -183,6 +183,7 @@ OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o OBJS-$(CONFIG_CFHD_DECODER) += cfhd.o cfhddata.o OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o +OBJS-$(CONFIG_CLEARVIDEO_DECODER) += clearvideo.o OBJS-$(CONFIG_CLJR_DECODER) += cljrdec.o OBJS-$(CONFIG_CLJR_ENCODER) += cljrenc.o OBJS-$(CONFIG_CLLC_DECODER) += cllc.o canopus.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 20b3b35b9094b..dc9a9614406cb 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -129,6 +129,7 @@ void avcodec_register_all(void) REGISTER_DECODER(CDXL, cdxl); REGISTER_DECODER(CFHD, cfhd); REGISTER_DECODER(CINEPAK, cinepak); + REGISTER_DECODER(CLEARVIDEO, clearvideo); REGISTER_ENCDEC (CLJR, cljr); REGISTER_DECODER(CLLC, cllc); REGISTER_ENCDEC (COMFORTNOISE, comfortnoise); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 4cf446faf923d..3118b10e9b963 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -409,6 +409,7 @@ enum AVCodecID { AV_CODEC_ID_PIXLET, AV_CODEC_ID_CFHD, AV_CODEC_ID_FMVC, + AV_CODEC_ID_CLEARVIDEO, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/clearvideo.c b/libavcodec/clearvideo.c new file mode 100644 index 0000000000000..a0ce68638584f --- /dev/null +++ b/libavcodec/clearvideo.c @@ -0,0 +1,391 @@ +/* + * ClearVideo decoder + * Copyright (c) 2012 Konstantin Shishkov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * ClearVideo decoder + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "get_bits.h" +#include "idctdsp.h" +#include "internal.h" + +#define NUM_DC_CODES 127 +#define NUM_AC_CODES 103 + +static const uint8_t clv_dc_codes[NUM_DC_CODES] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x07, 0x0B, + 0x0C, 0x08, 0x08, 0x09, 0x04, 0x06, 0x07, 0x05, + 0x04, 0x05, 0x04, 0x06, 0x05, 0x06, 0x07, 0x05, + 0x06, 0x07, 0x06, 0x07, 0x08, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x07, 0x08, 0x09, 0x07, 0x08, + 0x06, 0x07, 0x08, 0x06, 0x04, 0x05, 0x02, 0x01, + 0x03, 0x06, 0x07, 0x07, 0x09, 0x0A, 0x0B, 0x09, + 0x0A, 0x0B, 0x0A, 0x0B, 0x0C, 0x0D, 0x0C, 0x09, + 0x0D, 0x0A, 0x0B, 0x08, 0x09, 0x0A, 0x0B, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x06, 0x07, 0x06, 0x08, + 0x07, 0x09, 0x0A, 0x0B, 0x09, 0x0A, 0x0B, 0x0C, + 0x14, 0x0D, 0x0D, 0x0E, 0x0F, 0x15, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, + 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, +}; + +static const uint8_t clv_dc_bits[NUM_DC_CODES] = { + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 21, 22, 22, 19, 20, + 20, 19, 18, 18, 15, 17, 17, 16, + 14, 15, 12, 13, 14, 14, 14, 12, + 12, 12, 11, 11, 11, 10, 10, 10, + 10, 10, 10, 9, 9, 9, 8, 8, + 7, 7, 7, 6, 5, 5, 3, 1, + 3, 5, 5, 6, 7, 7, 7, 8, + 8, 8, 9, 9, 9, 9, 10, 11, + 10, 11, 11, 12, 12, 12, 12, 13, + 14, 14, 14, 14, 15, 15, 16, 17, + 16, 17, 18, 18, 19, 19, 19, 19, + 21, 19, 20, 19, 19, 21, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, +}; + +static const uint16_t clv_ac_syms[NUM_AC_CODES] = { + 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, + 0x0009, 0x000A, 0x000B, 0x000C, 0x0011, 0x0012, 0x0013, 0x0014, + 0x0015, 0x0016, 0x0021, 0x0022, 0x0023, 0x0024, 0x0031, 0x0032, + 0x0033, 0x0041, 0x0042, 0x0043, 0x0051, 0x0052, 0x0053, 0x0061, + 0x0062, 0x0063, 0x0071, 0x0072, 0x0081, 0x0082, 0x0091, 0x0092, + 0x00A1, 0x00A2, 0x00B1, 0x00C1, 0x00D1, 0x00E1, 0x00F1, 0x0101, + 0x0111, 0x0121, 0x0131, 0x0141, 0x0151, 0x0161, 0x0171, 0x0181, + 0x0191, 0x01A1, 0x1001, 0x1002, 0x1003, 0x1011, 0x1012, 0x1021, + 0x1031, 0x1041, 0x1051, 0x1061, 0x1071, 0x1081, 0x1091, 0x10A1, + 0x10B1, 0x10C1, 0x10D1, 0x10E1, 0x10F1, 0x1101, 0x1111, 0x1121, + 0x1131, 0x1141, 0x1151, 0x1161, 0x1171, 0x1181, 0x1191, 0x11A1, + 0x11B1, 0x11C1, 0x11D1, 0x11E1, 0x11F1, 0x1201, 0x1211, 0x1221, + 0x1231, 0x1241, 0x1251, 0x1261, 0x1271, 0x1281, 0x1BFF, +}; + +static const uint8_t clv_ac_codes[NUM_AC_CODES] = { + 0x02, 0x0F, 0x15, 0x17, 0x1F, 0x25, 0x24, 0x21, + 0x20, 0x07, 0x06, 0x20, 0x06, 0x14, 0x1E, 0x0F, + 0x21, 0x50, 0x0E, 0x1D, 0x0E, 0x51, 0x0D, 0x23, + 0x0D, 0x0C, 0x22, 0x52, 0x0B, 0x0C, 0x53, 0x13, + 0x0B, 0x54, 0x12, 0x0A, 0x11, 0x09, 0x10, 0x08, + 0x16, 0x55, 0x15, 0x14, 0x1C, 0x1B, 0x21, 0x20, + 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x22, 0x23, + 0x56, 0x57, 0x07, 0x19, 0x05, 0x0F, 0x04, 0x0E, + 0x0D, 0x0C, 0x13, 0x12, 0x11, 0x10, 0x1A, 0x19, + 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x18, 0x17, + 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x07, 0x06, + 0x05, 0x04, 0x24, 0x25, 0x26, 0x27, 0x58, 0x59, + 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x03, +}; + +static const uint8_t clv_ac_bits[NUM_AC_CODES] = { + 2, 4, 6, 7, 8, 9, 9, 10, + 10, 11, 11, 11, 3, 6, 8, 10, + 11, 12, 4, 8, 10, 12, 5, 9, + 10, 5, 9, 12, 5, 10, 12, 6, + 10, 12, 6, 10, 6, 10, 6, 10, + 7, 12, 7, 7, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 11, 11, + 12, 12, 4, 9, 11, 6, 11, 6, + 6, 6, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 10, 10, + 10, 10, 11, 11, 11, 11, 12, 12, + 12, 12, 12, 12, 12, 12, 7, +}; + +typedef struct CLVContext { + AVCodecContext *avctx; + IDCTDSPContext idsp; + AVFrame *pic; + GetBitContext gb; + int mb_width, mb_height; + VLC dc_vlc, ac_vlc; + int luma_dc_quant, chroma_dc_quant, ac_quant; + DECLARE_ALIGNED(16, int16_t, block)[64]; + int top_dc[3], left_dc[4]; + int iframes_warning; +} CLVContext; + +static inline int decode_block(CLVContext *ctx, int16_t *blk, int has_ac, + int ac_quant) +{ + GetBitContext *gb = &ctx->gb; + int idx = 1, last = 0, val, skip; + + memset(blk, 0, sizeof(*blk) * 64); + blk[0] = get_vlc2(gb, ctx->dc_vlc.table, 9, 3); + if (blk[0] < 0) + return AVERROR_INVALIDDATA; + blk[0] -= 63; + + if (!has_ac) + return 0; + + while (idx < 64 && !last) { + val = get_vlc2(gb, ctx->ac_vlc.table, 9, 2); + if (val < 0) + return AVERROR_INVALIDDATA; + if (val != 0x1BFF) { + last = val >> 12; + skip = (val >> 4) & 0xFF; + val &= 0xF; + if (get_bits1(gb)) + val = -val; + } else { + last = get_bits1(gb); + skip = get_bits(gb, 6); + val = get_sbits(gb, 8); + } + if (val) { + int aval = FFABS(val), sign = val < 0; + val = ac_quant * (2 * aval + 1); + if (!(ac_quant & 1)) + val--; + if (sign) + val = -val; + } + idx += skip; + if (idx >= 64) + return AVERROR_INVALIDDATA; + blk[ff_zigzag_direct[idx++]] = val; + } + + return (idx <= 64 && last) ? 0 : -1; +} + +#define DCT_TEMPLATE(blk, step, bias, shift, dshift, OP) \ + const int t0 = OP(2841 * blk[1 * step] + 565 * blk[7 * step]); \ + const int t1 = OP( 565 * blk[1 * step] - 2841 * blk[7 * step]); \ + const int t2 = OP(1609 * blk[5 * step] + 2408 * blk[3 * step]); \ + const int t3 = OP(2408 * blk[5 * step] - 1609 * blk[3 * step]); \ + const int t4 = OP(1108 * blk[2 * step] - 2676 * blk[6 * step]); \ + const int t5 = OP(2676 * blk[2 * step] + 1108 * blk[6 * step]); \ + const int t6 = ((blk[0 * step] + blk[4 * step]) << dshift) + bias; \ + const int t7 = ((blk[0 * step] - blk[4 * step]) << dshift) + bias; \ + const int t8 = t0 + t2; \ + const int t9 = t0 - t2; \ + const int tA = 181 * (t9 + (t1 - t3)) + 0x80 >> 8; \ + const int tB = 181 * (t9 - (t1 - t3)) + 0x80 >> 8; \ + const int tC = t1 + t3; \ + \ + blk[0 * step] = (t6 + t5 + t8) >> shift; \ + blk[1 * step] = (t7 + t4 + tA) >> shift; \ + blk[2 * step] = (t7 - t4 + tB) >> shift; \ + blk[3 * step] = (t6 - t5 + tC) >> shift; \ + blk[4 * step] = (t6 - t5 - tC) >> shift; \ + blk[5 * step] = (t7 - t4 - tB) >> shift; \ + blk[6 * step] = (t7 + t4 - tA) >> shift; \ + blk[7 * step] = (t6 + t5 - t8) >> shift; \ + +#define ROP(x) x +#define COP(x) (((x) + 4) >> 3) + +static void clv_dct(int16_t *block) +{ + int i; + int16_t *ptr; + + ptr = block; + for (i = 0; i < 8; i++) { + DCT_TEMPLATE(ptr, 1, 0x80, 8, 11, ROP); + ptr += 8; + } + + ptr = block; + for (i = 0; i < 8; i++) { + DCT_TEMPLATE(ptr, 8, 0x2000, 14, 8, COP); + ptr++; + } +} + +static int decode_mb(CLVContext *c, int x, int y) +{ + int i, has_ac[6], off; + + for (i = 0; i < 6; i++) + has_ac[i] = get_bits1(&c->gb); + + off = x * 16 + y * 16 * c->pic->linesize[0]; + for (i = 0; i < 4; i++) { + if (decode_block(c, c->block, has_ac[i], c->ac_quant) < 0) + return AVERROR_INVALIDDATA; + if (!x && !(i & 1)) { + c->block[0] += c->top_dc[0]; + c->top_dc[0] = c->block[0]; + } else { + c->block[0] += c->left_dc[(i & 2) >> 1]; + } + c->left_dc[(i & 2) >> 1] = c->block[0]; + c->block[0] *= c->luma_dc_quant; + clv_dct(c->block); + if (i == 2) + off += c->pic->linesize[0] * 8; + c->idsp.put_pixels_clamped(c->block, + c->pic->data[0] + off + (i & 1) * 8, + c->pic->linesize[0]); + } + + off = x * 8 + y * 8 * c->pic->linesize[1]; + for (i = 1; i < 3; i++) { + if (decode_block(c, c->block, has_ac[i + 3], c->ac_quant) < 0) + return AVERROR_INVALIDDATA; + if (!x) { + c->block[0] += c->top_dc[i]; + c->top_dc[i] = c->block[0]; + } else { + c->block[0] += c->left_dc[i + 1]; + } + c->left_dc[i + 1] = c->block[0]; + c->block[0] *= c->chroma_dc_quant; + clv_dct(c->block); + c->idsp.put_pixels_clamped(c->block, c->pic->data[i] + off, + c->pic->linesize[i]); + } + + return 0; +} + +static int clv_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + CLVContext *c = avctx->priv_data; + GetByteContext gb; + uint32_t frame_type; + int i, j, ret; + + bytestream2_init(&gb, buf, buf_size); + if (avctx->codec_tag == MKTAG('C', 'L', 'V', '1')) { + int skip = bytestream2_get_byte(&gb); + bytestream2_skip(&gb, (skip + 1) * 8); + } + + frame_type = bytestream2_get_byte(&gb); + if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) + return ret; + + c->pic->key_frame = frame_type & 0x20 ? 1 : 0; + c->pic->pict_type = frame_type & 0x20 ? AV_PICTURE_TYPE_I + : AV_PICTURE_TYPE_P; + + if (frame_type & 0x2) { + bytestream2_get_be32(&gb); // frame size; + c->ac_quant = bytestream2_get_byte(&gb); + c->luma_dc_quant = 32; + c->chroma_dc_quant = 32; + + if ((ret = init_get_bits8(&c->gb, buf + bytestream2_tell(&gb), + buf_size - bytestream2_tell(&gb))) < 0) + return ret; + + for (i = 0; i < 3; i++) + c->top_dc[i] = 32; + for (i = 0; i < 4; i++) + c->left_dc[i] = 32; + + for (j = 0; j < c->mb_height; j++) { + for (i = 0; i < c->mb_width; i++) { + ret |= decode_mb(c, i, j); + } + } + } else { + if (!c->iframes_warning) + avpriv_report_missing_feature(avctx, "Non-I-frames in Clearvideo"); + c->iframes_warning = 1; + return AVERROR_PATCHWELCOME; + } + + if ((ret = av_frame_ref(data, c->pic)) < 0) + return ret; + + *got_frame = 1; + + return ret < 0 ? ret : buf_size; +} + +static av_cold int clv_decode_init(AVCodecContext *avctx) +{ + CLVContext *const c = avctx->priv_data; + int ret; + + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + c->avctx = avctx; + c->mb_width = FFALIGN(avctx->width, 16) >> 4; + c->mb_height = FFALIGN(avctx->height, 16) >> 4; + c->iframes_warning = 0; + c->pic = av_frame_alloc(); + if (!c->pic) + return AVERROR(ENOMEM); + + ff_idctdsp_init(&c->idsp, avctx); + ret = init_vlc(&c->dc_vlc, 9, NUM_DC_CODES, + clv_dc_bits, 1, 1, + clv_dc_codes, 1, 1, 0); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Error initialising DC VLC\n"); + return ret; + } + ret = ff_init_vlc_sparse(&c->ac_vlc, 9, NUM_AC_CODES, + clv_ac_bits, 1, 1, + clv_ac_codes, 1, 1, + clv_ac_syms, 2, 2, 0); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Error initialising AC VLC\n"); + return ret; + } + + return 0; +} + +static av_cold int clv_decode_end(AVCodecContext *avctx) +{ + CLVContext *const c = avctx->priv_data; + + av_frame_free(&c->pic); + + ff_free_vlc(&c->dc_vlc); + ff_free_vlc(&c->ac_vlc); + + return 0; +} + +AVCodec ff_clearvideo_decoder = { + .name = "clearvideo", + .long_name = NULL_IF_CONFIG_SMALL("Iterated Systems ClearVideo"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CLEARVIDEO, + .priv_data_size = sizeof(CLVContext), + .init = clv_decode_init, + .close = clv_decode_end, + .decode = clv_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index ed97420d4209c..5061b78c9834f 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1217,6 +1217,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("FM Screen Capture Codec"), .props = AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_CLEARVIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "clearvideo", + .long_name = NULL_IF_CONFIG_SMALL("Iterated Systems ClearVideo"), + .props = AV_CODEC_PROP_LOSSY, + }, /* image codecs */ { diff --git a/libavcodec/version.h b/libavcodec/version.h index 63c9a1f634232..2a61bbd7185ac 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 2 +#define LIBAVCODEC_VERSION_MINOR 3 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/riff.c b/libavformat/riff.c index a6734f2789824..8690960b1ef87 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -375,6 +375,8 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_AV1, MKTAG('A', 'V', '0', '1') }, { AV_CODEC_ID_CFHD, MKTAG('C', 'F', 'H', 'D') }, { AV_CODEC_ID_FMVC, MKTAG('F', 'M', 'V', 'C') }, + { AV_CODEC_ID_CLEARVIDEO, MKTAG('U', 'C', 'O', 'D') }, + { AV_CODEC_ID_NONE, 0 } }; diff --git a/libavformat/rm.c b/libavformat/rm.c index 761be3f55665e..a38b036548e1d 100644 --- a/libavformat/rm.c +++ b/libavformat/rm.c @@ -43,5 +43,6 @@ const AVCodecTag ff_rm_codec_tags[] = { { AV_CODEC_ID_AAC, MKTAG('r','a','a','c') }, { AV_CODEC_ID_AAC, MKTAG('r','a','c','p') }, { AV_CODEC_ID_RALF, MKTAG('L','S','D',':') }, + { AV_CODEC_ID_CLEARVIDEO, MKTAG('C','L','V','1') }, { AV_CODEC_ID_NONE }, }; From d0ce0634e09403eecaea4283cf82a2c5cea7d1e1 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 14 Apr 2017 20:42:47 +0200 Subject: [PATCH 0175/2557] clearvideo: Convert to the new bitstream reader --- libavcodec/clearvideo.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libavcodec/clearvideo.c b/libavcodec/clearvideo.c index a0ce68638584f..08bf2cb6dae0a 100644 --- a/libavcodec/clearvideo.c +++ b/libavcodec/clearvideo.c @@ -25,8 +25,8 @@ */ #include "avcodec.h" +#include "bitstream.h" #include "bytestream.h" -#include "get_bits.h" #include "idctdsp.h" #include "internal.h" @@ -123,7 +123,7 @@ typedef struct CLVContext { AVCodecContext *avctx; IDCTDSPContext idsp; AVFrame *pic; - GetBitContext gb; + BitstreamContext bc; int mb_width, mb_height; VLC dc_vlc, ac_vlc; int luma_dc_quant, chroma_dc_quant, ac_quant; @@ -135,11 +135,11 @@ typedef struct CLVContext { static inline int decode_block(CLVContext *ctx, int16_t *blk, int has_ac, int ac_quant) { - GetBitContext *gb = &ctx->gb; + BitstreamContext *bc = &ctx->bc; int idx = 1, last = 0, val, skip; memset(blk, 0, sizeof(*blk) * 64); - blk[0] = get_vlc2(gb, ctx->dc_vlc.table, 9, 3); + blk[0] = bitstream_read_vlc(bc, ctx->dc_vlc.table, 9, 3); if (blk[0] < 0) return AVERROR_INVALIDDATA; blk[0] -= 63; @@ -148,19 +148,19 @@ static inline int decode_block(CLVContext *ctx, int16_t *blk, int has_ac, return 0; while (idx < 64 && !last) { - val = get_vlc2(gb, ctx->ac_vlc.table, 9, 2); + val = bitstream_read_vlc(bc, ctx->ac_vlc.table, 9, 2); if (val < 0) return AVERROR_INVALIDDATA; if (val != 0x1BFF) { last = val >> 12; skip = (val >> 4) & 0xFF; val &= 0xF; - if (get_bits1(gb)) + if (bitstream_read_bit(bc)) val = -val; } else { - last = get_bits1(gb); - skip = get_bits(gb, 6); - val = get_sbits(gb, 8); + last = bitstream_read_bit(bc); + skip = bitstream_read(bc, 6); + val = bitstream_read_signed(bc, 8); } if (val) { int aval = FFABS(val), sign = val < 0; @@ -229,7 +229,7 @@ static int decode_mb(CLVContext *c, int x, int y) int i, has_ac[6], off; for (i = 0; i < 6; i++) - has_ac[i] = get_bits1(&c->gb); + has_ac[i] = bitstream_read_bit(&c->bc); off = x * 16 + y * 16 * c->pic->linesize[0]; for (i = 0; i < 4; i++) { @@ -301,8 +301,8 @@ static int clv_decode_frame(AVCodecContext *avctx, void *data, c->luma_dc_quant = 32; c->chroma_dc_quant = 32; - if ((ret = init_get_bits8(&c->gb, buf + bytestream2_tell(&gb), - buf_size - bytestream2_tell(&gb))) < 0) + if ((ret = bitstream_init8(&c->bc, buf + bytestream2_tell(&gb), + buf_size - bytestream2_tell(&gb))) < 0) return ret; for (i = 0; i < 3; i++) From 358adef0305618219522858e471edf7e0cb4043e Mon Sep 17 00:00:00 2001 From: Seppo Tomperi Date: Tue, 25 Apr 2017 19:41:29 +0200 Subject: [PATCH 0176/2557] hevc: Add NEON IDCT DC functions for bitdepth 8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Alexandra Hájková Signed-off-by: Martin Storsjö --- libavcodec/arm/hevc_idct.S | 78 +++++++++++++++++++++++++++++++ libavcodec/arm/hevcdsp_init_arm.c | 10 ++++ 2 files changed, 88 insertions(+) diff --git a/libavcodec/arm/hevc_idct.S b/libavcodec/arm/hevc_idct.S index 156d4765f0dbd..ceded7a45fee2 100644 --- a/libavcodec/arm/hevc_idct.S +++ b/libavcodec/arm/hevc_idct.S @@ -1,5 +1,7 @@ /* * ARM NEON optimised IDCT functions for HEVC decoding + * + * Copyright (c) 2014 Seppo Tomperi * Copyright (c) 2017 Alexandra Hájková * * This file is part of Libav. @@ -28,6 +30,82 @@ const trans, align=4 .short 57, 43, 25, 9 endconst +function ff_hevc_idct_4x4_dc_8_neon, export=1 + ldrsh r1, [r0] + ldr r2, =0x20 + add r1, #1 + asr r1, #1 + add r1, r2 + asr r1, #6 + vdup.16 q0, r1 + vdup.16 q1, r1 + vst1.16 {q0, q1}, [r0, :128] + bx lr +endfunc + +function ff_hevc_idct_8x8_dc_8_neon, export=1 + ldrsh r1, [r0] + ldr r2, =0x20 + add r1, #1 + asr r1, #1 + add r1, r2 + asr r1, #6 + vdup.16 q8, r1 + vdup.16 q9, r1 + vmov.16 q10, q8 + vmov.16 q11, q8 + vmov.16 q12, q8 + vmov.16 q13, q8 + vmov.16 q14, q8 + vmov.16 q15, q8 + vstm r0, {q8-q15} + bx lr +endfunc + +function ff_hevc_idct_16x16_dc_8_neon, export=1 + ldrsh r1, [r0] + ldr r2, =0x20 + add r1, #1 + asr r1, #1 + add r1, r2 + asr r1, #6 + vdup.16 q8, r1 + vdup.16 q9, r1 + vmov.16 q10, q8 + vmov.16 q11, q8 + vmov.16 q12, q8 + vmov.16 q13, q8 + vmov.16 q14, q8 + vmov.16 q15, q8 + vstm r0!, {q8-q15} + vstm r0!, {q8-q15} + vstm r0!, {q8-q15} + vstm r0, {q8-q15} + bx lr +endfunc + +function ff_hevc_idct_32x32_dc_8_neon, export=1 + ldrsh r1, [r0] + ldr r2, =0x20 + add r1, #1 + asr r1, #1 + add r1, r2 + asr r1, #6 + mov r3, #16 + vdup.16 q8, r1 + vdup.16 q9, r1 + vmov.16 q10, q8 + vmov.16 q11, q8 + vmov.16 q12, q8 + vmov.16 q13, q8 + vmov.16 q14, q8 + vmov.16 q15, q8 +1: subs r3, #1 + vstm r0!, {q8-q15} + bne 1b + bx lr +endfunc + .macro sum_sub out, in, c, op .ifc \op, + vmlal.s16 \out, \in, \c diff --git a/libavcodec/arm/hevcdsp_init_arm.c b/libavcodec/arm/hevcdsp_init_arm.c index e61587f4e3e46..fa2e7ad1e10d4 100644 --- a/libavcodec/arm/hevcdsp_init_arm.c +++ b/libavcodec/arm/hevcdsp_init_arm.c @@ -25,6 +25,11 @@ #include "libavcodec/hevcdsp.h" +void ff_hevc_idct_4x4_dc_8_neon(int16_t *coeffs); +void ff_hevc_idct_8x8_dc_8_neon(int16_t *coeffs); +void ff_hevc_idct_16x16_dc_8_neon(int16_t *coeffs); +void ff_hevc_idct_32x32_dc_8_neon(int16_t *coeffs); + void ff_hevc_idct_4x4_8_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_8x8_8_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_16x16_8_neon(int16_t *coeffs, int col_limit); @@ -38,6 +43,11 @@ av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, int bit_depth) if (have_neon(cpu_flags)) { if (bit_depth == 8) { + c->idct_dc[0] = ff_hevc_idct_4x4_dc_8_neon; + c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_neon; + c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_neon; + c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_neon; + c->idct[0] = ff_hevc_idct_4x4_8_neon; c->idct[1] = ff_hevc_idct_8x8_8_neon; c->idct[2] = ff_hevc_idct_16x16_8_neon; From 3d69dd65c6771c28d3bf4e8e53a905aa8cd01fd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= Date: Tue, 25 Apr 2017 19:43:41 +0200 Subject: [PATCH 0177/2557] hevc: Add support for bitdepth 10 for IDCT DC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/arm/hevc_idct.S | 40 +++++++++++++++++++++---------- libavcodec/arm/hevcdsp_init_arm.c | 9 +++++++ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/libavcodec/arm/hevc_idct.S b/libavcodec/arm/hevc_idct.S index ceded7a45fee2..41b1b290bf49a 100644 --- a/libavcodec/arm/hevc_idct.S +++ b/libavcodec/arm/hevc_idct.S @@ -30,26 +30,29 @@ const trans, align=4 .short 57, 43, 25, 9 endconst -function ff_hevc_idct_4x4_dc_8_neon, export=1 +.macro idct_4x4_dc bitdepth +function ff_hevc_idct_4x4_dc_\bitdepth\()_neon, export=1 ldrsh r1, [r0] - ldr r2, =0x20 + ldr r2, =(1 << (13 - \bitdepth)) add r1, #1 asr r1, #1 add r1, r2 - asr r1, #6 + asr r1, #(14 - \bitdepth) vdup.16 q0, r1 vdup.16 q1, r1 vst1.16 {q0, q1}, [r0, :128] bx lr endfunc +.endm -function ff_hevc_idct_8x8_dc_8_neon, export=1 +.macro idct_8x8_dc bitdepth +function ff_hevc_idct_8x8_dc_\bitdepth\()_neon, export=1 ldrsh r1, [r0] - ldr r2, =0x20 + ldr r2, =(1 << (13 - \bitdepth)) add r1, #1 asr r1, #1 add r1, r2 - asr r1, #6 + asr r1, #(14 - \bitdepth) vdup.16 q8, r1 vdup.16 q9, r1 vmov.16 q10, q8 @@ -61,14 +64,16 @@ function ff_hevc_idct_8x8_dc_8_neon, export=1 vstm r0, {q8-q15} bx lr endfunc +.endm -function ff_hevc_idct_16x16_dc_8_neon, export=1 +.macro idct_16x16_dc bitdepth +function ff_hevc_idct_16x16_dc_\bitdepth\()_neon, export=1 ldrsh r1, [r0] - ldr r2, =0x20 + ldr r2, =(1 << (13 - \bitdepth)) add r1, #1 asr r1, #1 add r1, r2 - asr r1, #6 + asr r1, #(14 - \bitdepth) vdup.16 q8, r1 vdup.16 q9, r1 vmov.16 q10, q8 @@ -83,14 +88,16 @@ function ff_hevc_idct_16x16_dc_8_neon, export=1 vstm r0, {q8-q15} bx lr endfunc +.endm -function ff_hevc_idct_32x32_dc_8_neon, export=1 +.macro idct_32x32_dc bitdepth +function ff_hevc_idct_32x32_dc_\bitdepth\()_neon, export=1 ldrsh r1, [r0] - ldr r2, =0x20 + ldr r2, =(1 << (13 - \bitdepth)) add r1, #1 asr r1, #1 add r1, r2 - asr r1, #6 + asr r1, #(14 - \bitdepth) mov r3, #16 vdup.16 q8, r1 vdup.16 q9, r1 @@ -105,6 +112,7 @@ function ff_hevc_idct_32x32_dc_8_neon, export=1 bne 1b bx lr endfunc +.endm .macro sum_sub out, in, c, op .ifc \op, + @@ -496,8 +504,16 @@ tr_16x4 secondpass_10, 20 - 10 .ltorg idct_4x4 8 +idct_4x4_dc 8 idct_4x4 10 +idct_4x4_dc 10 idct_8x8 8 +idct_8x8_dc 8 idct_8x8 10 +idct_8x8_dc 10 idct_16x16 8 +idct_16x16_dc 8 idct_16x16 10 +idct_16x16_dc 10 +idct_32x32_dc 8 +idct_32x32_dc 10 diff --git a/libavcodec/arm/hevcdsp_init_arm.c b/libavcodec/arm/hevcdsp_init_arm.c index fa2e7ad1e10d4..3d8d06b136245 100644 --- a/libavcodec/arm/hevcdsp_init_arm.c +++ b/libavcodec/arm/hevcdsp_init_arm.c @@ -29,6 +29,10 @@ void ff_hevc_idct_4x4_dc_8_neon(int16_t *coeffs); void ff_hevc_idct_8x8_dc_8_neon(int16_t *coeffs); void ff_hevc_idct_16x16_dc_8_neon(int16_t *coeffs); void ff_hevc_idct_32x32_dc_8_neon(int16_t *coeffs); +void ff_hevc_idct_4x4_dc_10_neon(int16_t *coeffs); +void ff_hevc_idct_8x8_dc_10_neon(int16_t *coeffs); +void ff_hevc_idct_16x16_dc_10_neon(int16_t *coeffs); +void ff_hevc_idct_32x32_dc_10_neon(int16_t *coeffs); void ff_hevc_idct_4x4_8_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_8x8_8_neon(int16_t *coeffs, int col_limit); @@ -53,6 +57,11 @@ av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, int bit_depth) c->idct[2] = ff_hevc_idct_16x16_8_neon; } if (bit_depth == 10) { + c->idct_dc[0] = ff_hevc_idct_4x4_dc_10_neon; + c->idct_dc[1] = ff_hevc_idct_8x8_dc_10_neon; + c->idct_dc[2] = ff_hevc_idct_16x16_dc_10_neon; + c->idct_dc[3] = ff_hevc_idct_32x32_dc_10_neon; + c->idct[0] = ff_hevc_idct_4x4_10_neon; c->idct[1] = ff_hevc_idct_8x8_10_neon; c->idct[2] = ff_hevc_idct_16x16_10_neon; From 04b0f0e371ff81b682274b574fb465ba4395c09f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 30 Mar 2017 17:02:39 +0200 Subject: [PATCH 0178/2557] mem: uninline av_malloc(z)_array() Inlining public functions hardcodes their implementation into the ABI, so it should be avoided unless there is a very good reason for it. No such reason exists in this case. --- libavutil/mem.c | 14 ++++++++++++++ libavutil/mem.h | 14 ++------------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/libavutil/mem.c b/libavutil/mem.c index 0f506d360468c..fd0ffd988c925 100644 --- a/libavutil/mem.c +++ b/libavutil/mem.c @@ -138,6 +138,20 @@ int av_reallocp(void *ptr, size_t size) return 0; } +void *av_malloc_array(size_t nmemb, size_t size) +{ + if (!size || nmemb >= INT_MAX / size) + return NULL; + return av_malloc(nmemb * size); +} + +void *av_mallocz_array(size_t nmemb, size_t size) +{ + if (!size || nmemb >= INT_MAX / size) + return NULL; + return av_mallocz(nmemb * size); +} + void *av_realloc_array(void *ptr, size_t nmemb, size_t size) { if (!size || nmemb >= INT_MAX / size) diff --git a/libavutil/mem.h b/libavutil/mem.h index f3cf56c498f45..a03ba2f528b9a 100644 --- a/libavutil/mem.h +++ b/libavutil/mem.h @@ -89,12 +89,7 @@ void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1); * be allocated. * @see av_malloc() */ -av_alloc_size(1, 2) static inline void *av_malloc_array(size_t nmemb, size_t size) -{ - if (!size || nmemb >= INT_MAX / size) - return NULL; - return av_malloc(nmemb * size); -} +av_alloc_size(1, 2) void *av_malloc_array(size_t nmemb, size_t size); /** * Allocate or reallocate a block of memory. @@ -202,12 +197,7 @@ void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1); * @see av_mallocz() * @see av_malloc_array() */ -av_alloc_size(1, 2) static inline void *av_mallocz_array(size_t nmemb, size_t size) -{ - if (!size || nmemb >= INT_MAX / size) - return NULL; - return av_mallocz(nmemb * size); -} +av_alloc_size(1, 2) void *av_mallocz_array(size_t nmemb, size_t size); /** * Duplicate the string s. From bee89ed3ec61a4a0e72255ae6f4a4274d25b5ccd Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 14 Apr 2017 13:06:35 -0300 Subject: [PATCH 0179/2557] matroskaenc: don't warn about unknown spherical metadata when there isn't any The same warning is issued when actual unknown spherical metadata is found further down in the function. Signed-off-by: James Almer Signed-off-by: Anton Khirnov --- libavformat/matroskaenc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index b8c434a664593..ab83acfffbf4c 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -662,10 +662,8 @@ static int mkv_write_video_projection(AVFormatContext *s, AVIOContext *pb, (const AVSphericalMapping *)av_stream_get_side_data(st, AV_PKT_DATA_SPHERICAL, &side_data_size); - if (!side_data_size) { - av_log(NULL, AV_LOG_WARNING, "Unknown spherical metadata\n"); + if (!side_data_size) return 0; - } ret = avio_open_dyn_buf(&dyn_cp); if (ret < 0) From 1f6e5dd4d4dd9c02371ad211049d27edb6d95286 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Tue, 25 Apr 2017 16:26:56 -0400 Subject: [PATCH 0180/2557] mlp: Rename the channel layout variable Purely cosmetic change, will make code more readable once the new channel layout takes over. --- libavcodec/mlpdec.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index a606213f97a73..9ce32c832e338 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -67,7 +67,7 @@ typedef struct SubStream { /// For each channel output by the matrix, the output channel to map it to uint8_t ch_assign[MAX_CHANNELS]; /// The channel layout for this substream - uint64_t ch_layout; + uint64_t mask; /// The matrix encoding mode for this substream enum AVMatrixEncoding matrix_encoding; @@ -383,17 +383,17 @@ static int read_major_sync(MLPDecodeContext *m, BitstreamContext *bc) * major sync. */ if (m->avctx->codec_id == AV_CODEC_ID_MLP) { if ((substr = (mh.num_substreams > 1))) - m->substream[0].ch_layout = AV_CH_LAYOUT_STEREO; - m->substream[substr].ch_layout = mh.channel_layout_mlp; + m->substream[0].mask = AV_CH_LAYOUT_STEREO; + m->substream[substr].mask = mh.channel_layout_mlp; } else { if ((substr = (mh.num_substreams > 1))) - m->substream[0].ch_layout = AV_CH_LAYOUT_STEREO; + m->substream[0].mask = AV_CH_LAYOUT_STEREO; if (mh.num_substreams > 2) if (mh.channel_layout_thd_stream2) - m->substream[2].ch_layout = mh.channel_layout_thd_stream2; + m->substream[2].mask = mh.channel_layout_thd_stream2; else - m->substream[2].ch_layout = mh.channel_layout_thd_stream1; - m->substream[substr].ch_layout = mh.channel_layout_thd_stream1; + m->substream[2].mask = mh.channel_layout_thd_stream1; + m->substream[substr].mask = mh.channel_layout_thd_stream1; } /* Parse the TrueHD decoder channel modifiers and set each substream's @@ -511,12 +511,12 @@ static int read_restart_header(MLPDecodeContext *m, BitstreamContext *bc, s->max_channel = max_channel; s->max_matrix_channel = max_matrix_channel; - if (m->avctx->request_channel_layout && (s->ch_layout & m->avctx->request_channel_layout) == + if (m->avctx->request_channel_layout && (s->mask & m->avctx->request_channel_layout) == m->avctx->request_channel_layout && m->max_decoded_substream > substr) { av_log(m->avctx, AV_LOG_DEBUG, "Extracting %d-channel downmix (0x%"PRIx64") from substream %d. " "Further substreams will be skipped.\n", - s->max_channel + 1, s->ch_layout, substr); + s->max_channel + 1, s->mask, substr); m->max_decoded_substream = substr; } @@ -543,9 +543,9 @@ static int read_restart_header(MLPDecodeContext *m, BitstreamContext *bc, for (ch = 0; ch <= s->max_matrix_channel; ch++) { int ch_assign = bitstream_read(bc, 6); if (m->avctx->codec_id == AV_CODEC_ID_TRUEHD) { - uint64_t channel = thd_channel_layout_extract_channel(s->ch_layout, + uint64_t channel = thd_channel_layout_extract_channel(s->mask, ch_assign); - ch_assign = av_get_channel_layout_channel_index(s->ch_layout, + ch_assign = av_get_channel_layout_channel_index(s->mask, channel); } if (ch_assign < 0 || ch_assign > s->max_matrix_channel) { @@ -587,7 +587,7 @@ static int read_restart_header(MLPDecodeContext *m, BitstreamContext *bc, if (substr == m->max_decoded_substream) { m->avctx->channels = s->max_matrix_channel + 1; - m->avctx->channel_layout = s->ch_layout; + m->avctx->channel_layout = s->mask; m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(s->ch_assign, s->output_shift, s->max_matrix_channel, From cea7fd9afb8488a6c48f7d7ee38602e1fd3dd425 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Tue, 25 Apr 2017 16:26:57 -0400 Subject: [PATCH 0181/2557] mlp: Drop ff_ prefix from a static function --- libavcodec/mlp_parser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index e9ba840200a67..fb9ede87022b1 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -120,7 +120,7 @@ static uint64_t truehd_layout(int chanmap) return layout; } -static int ff_mlp_get_major_sync_size(const uint8_t * buf, int bufsize) +static int mlp_get_major_sync_size(const uint8_t * buf, int bufsize) { int has_extension, extensions = 0; int size = 28; @@ -150,7 +150,7 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, BitstreamContext *bc) assert(bitstream_tell(bc) == 0); - header_size = ff_mlp_get_major_sync_size(bc->buffer, bc->size_in_bits >> 3); + header_size = mlp_get_major_sync_size(bc->buffer, bc->size_in_bits >> 3); if (header_size < 0 || bc->size_in_bits < header_size << 3) { av_log(log, AV_LOG_ERROR, "packet too short, unable to read major sync\n"); return -1; From 94c54d97e7f4fe90570c323803f2bdf6246c1010 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Tue, 25 Apr 2017 16:26:58 -0400 Subject: [PATCH 0182/2557] mlp: Factor out channel layout subset checks --- libavcodec/mlp_parser.c | 22 +++++++++++----------- libavcodec/mlp_parser.h | 2 ++ libavcodec/mlpdec.c | 4 ++-- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index fb9ede87022b1..7d73058e4cf12 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -120,6 +120,11 @@ static uint64_t truehd_layout(int chanmap) return layout; } +int ff_mlp_channel_layout_subset(uint64_t channel_layout, uint64_t mask) +{ + return channel_layout && ((channel_layout & mask) == channel_layout); +} + static int mlp_get_major_sync_size(const uint8_t * buf, int bufsize) { int has_extension, extensions = 0; @@ -331,6 +336,8 @@ static int mlp_parse(AVCodecParserContext *s, } else { BitstreamContext bc; MLPHeaderInfo mh; + int stereo_requested = ff_mlp_channel_layout_subset(avctx->request_channel_layout, + AV_CH_LAYOUT_STEREO); bitstream_init8(&bc, buf + 4, buf_size - 4); if (ff_mlp_read_major_sync(avctx, &mh, &bc) < 0) @@ -346,10 +353,7 @@ static int mlp_parse(AVCodecParserContext *s, if (mh.stream_type == 0xbb) { /* MLP stream */ - if (avctx->request_channel_layout && - (avctx->request_channel_layout & AV_CH_LAYOUT_STEREO) == - avctx->request_channel_layout && - mh.num_substreams > 1) { + if (stereo_requested && mh.num_substreams > 1) { avctx->channels = 2; avctx->channel_layout = AV_CH_LAYOUT_STEREO; } else { @@ -358,16 +362,12 @@ static int mlp_parse(AVCodecParserContext *s, } } else { /* mh.stream_type == 0xba */ /* TrueHD stream */ - if (avctx->request_channel_layout && - (avctx->request_channel_layout & AV_CH_LAYOUT_STEREO) == - avctx->request_channel_layout && - mh.num_substreams > 1) { + if (stereo_requested && mh.num_substreams > 1) { avctx->channels = 2; avctx->channel_layout = AV_CH_LAYOUT_STEREO; } else if (!mh.channels_thd_stream2 || - (avctx->request_channel_layout && - (avctx->request_channel_layout & mh.channel_layout_thd_stream1) == - avctx->request_channel_layout)) { + ff_mlp_channel_layout_subset(avctx->request_channel_layout, + mh.channel_layout_thd_stream1)) { avctx->channels = mh.channels_thd_stream1; avctx->channel_layout = mh.channel_layout_thd_stream1; } else { diff --git a/libavcodec/mlp_parser.h b/libavcodec/mlp_parser.h index 871b96db20486..946f4d240c0bd 100644 --- a/libavcodec/mlp_parser.h +++ b/libavcodec/mlp_parser.h @@ -63,4 +63,6 @@ typedef struct MLPHeaderInfo int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, BitstreamContext *bc); +int ff_mlp_channel_layout_subset(uint64_t channel_layout, uint64_t mask); + #endif /* AVCODEC_MLP_PARSER_H */ diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 9ce32c832e338..fa94f6f5b4f21 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -511,8 +511,8 @@ static int read_restart_header(MLPDecodeContext *m, BitstreamContext *bc, s->max_channel = max_channel; s->max_matrix_channel = max_matrix_channel; - if (m->avctx->request_channel_layout && (s->mask & m->avctx->request_channel_layout) == - m->avctx->request_channel_layout && m->max_decoded_substream > substr) { + if (ff_mlp_channel_layout_subset(m->avctx->request_channel_layout, s->mask) && + m->max_decoded_substream > substr) { av_log(m->avctx, AV_LOG_DEBUG, "Extracting %d-channel downmix (0x%"PRIx64") from substream %d. " "Further substreams will be skipped.\n", From 85c2bf9d2cc7dad3d5c6dc79f802a74efa8d8fce Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 26 Apr 2017 11:31:28 -0400 Subject: [PATCH 0183/2557] avfoundation: update to use AVCodecParameters --- libavdevice/avfoundation_dec.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavdevice/avfoundation_dec.m b/libavdevice/avfoundation_dec.m index f01484c48fad3..e87f3a502e57d 100644 --- a/libavdevice/avfoundation_dec.m +++ b/libavdevice/avfoundation_dec.m @@ -449,11 +449,11 @@ static int get_video_config(AVFormatContext *s) image_buffer = ctx->current_frame; image_buffer_size = CVImageBufferGetEncodedSize(image_buffer); - stream->codec->codec_id = AV_CODEC_ID_RAWVIDEO; - stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; - stream->codec->width = (int)image_buffer_size.width; - stream->codec->height = (int)image_buffer_size.height; - stream->codec->pix_fmt = av_get_pix_fmt(ctx->pixel_format); + stream->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + stream->codecpar->width = (int)image_buffer_size.width; + stream->codecpar->height = (int)image_buffer_size.height; + stream->codecpar->format = av_get_pix_fmt(ctx->pixel_format); CFRelease(ctx->current_frame); ctx->current_frame = nil; From 6af014f4028238b4c50f1731b3369a41d65fa9c4 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 2 Apr 2017 23:05:13 +0100 Subject: [PATCH 0184/2557] vaapi_encode: Use gop_size consistently in RC parameters The non-H.26[45] codecs already use this form. Since we don't currently generate I frames for codecs which support them separately to IDR, the p_per_i variable is set to infinity by default so that it doesn't interfere with any other calculation. (All the code for I frames still exists, and it works for H.264 if set manually.) --- libavcodec/vaapi_encode.c | 3 +-- libavcodec/vaapi_encode_h264.c | 4 ++-- libavcodec/vaapi_encode_h265.c | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 411d8790919dc..62051841903b4 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1429,8 +1429,7 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) ctx->output_order = - ctx->output_delay - 1; // Currently we never generate I frames, only IDR. - ctx->p_per_i = ((avctx->gop_size + avctx->max_b_frames) / - (avctx->max_b_frames + 1)); + ctx->p_per_i = INT_MAX; ctx->b_per_p = avctx->max_b_frames; if (ctx->codec->sequence_params_size > 0) { diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index b918e0d75e88e..0c3ac34411db7 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -905,8 +905,8 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) mseq->nal_hrd_parameters_present_flag = 0; } - vseq->intra_period = ctx->p_per_i * (ctx->b_per_p + 1); - vseq->intra_idr_period = vseq->intra_period; + vseq->intra_period = avctx->gop_size; + vseq->intra_idr_period = avctx->gop_size; vseq->ip_period = ctx->b_per_p + 1; } diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index e9133b4313db7..9b029e2e20bfb 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -832,8 +832,8 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) vseq->vui_time_scale = avctx->time_base.den; } - vseq->intra_period = ctx->p_per_i * (ctx->b_per_p + 1); - vseq->intra_idr_period = vseq->intra_period; + vseq->intra_period = avctx->gop_size; + vseq->intra_idr_period = avctx->gop_size; vseq->ip_period = ctx->b_per_p + 1; } From 64a5260c695dd8051509d3270295fd64eac56587 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 27 Mar 2017 20:45:21 +0100 Subject: [PATCH 0185/2557] lavc: Add flag to allow profile mismatch with hardware decoding --- doc/APIchanges | 3 +++ libavcodec/avcodec.h | 14 ++++++++++++++ libavcodec/version.h | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index a0ca3b7ac0001..58d59dd08ca1f 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2017-03-23 API changes, most recent first: +2017-04-26 - xxxxxxx - lavc 58.3.1 - avcodec.h + Add AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH. + 2017-03-xx - xxxxxxx - lavc 57.37.0 - avcodec.h Add AVCodecContext.hwaccel_flags field. This will control some hwaccels at a later point. diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 3118b10e9b963..162f1abe4b78f 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3005,6 +3005,20 @@ typedef struct AVHWAccel { */ #define AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH (1 << 1) +/** + * Hardware acceleration should still be attempted for decoding when the + * codec profile does not match the reported capabilities of the hardware. + * + * For example, this can be used to try to decode baseline profile H.264 + * streams in hardware - it will often succeed, because many streams marked + * as baseline profile actually conform to constrained baseline profile. + * + * @warning If the stream is actually not supported then the behaviour is + * undefined, and may include returning entirely incorrect output + * while indicating success. + */ +#define AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH (1 << 2) + /** * @} */ diff --git a/libavcodec/version.h b/libavcodec/version.h index 2a61bbd7185ac..88f17a1f78097 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 3 -#define LIBAVCODEC_VERSION_MICRO 0 +#define LIBAVCODEC_VERSION_MICRO 1 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 7acb90333a187b0e847b66f9d3511245423dc0ce Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 27 Mar 2017 20:46:11 +0100 Subject: [PATCH 0186/2557] vaapi: Add external control of allow-profile-mismatch Uses the just-added ALLOW_PROFILE_MISMATCH flag. --- libavcodec/vaapi_decode.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index 0db79d401db99..a63c4c62ec97f 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -283,14 +283,6 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) int profile_count, exact_match, alt_profile; const AVPixFmtDescriptor *sw_desc, *desc; - // Allowing a profile mismatch can be useful because streams may - // over-declare their required capabilities - in particular, many - // H.264 baseline profile streams (notably some of those in FATE) - // only use the feature set of constrained baseline. This flag - // would have to be be set by some external means in order to - // actually be useful. (AV_HWACCEL_FLAG_IGNORE_PROFILE?) - int allow_profile_mismatch = 0; - codec_desc = avcodec_descriptor_get(avctx->codec_id); if (!codec_desc) { err = AVERROR(EINVAL); @@ -346,7 +338,8 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) goto fail; } if (!exact_match) { - if (allow_profile_mismatch) { + if (avctx->hwaccel_flags & + AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH) { av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not " "supported for hardware decode.\n", codec_desc->name, avctx->profile); From ad52eef997dce374b4c7f3d1cdedf382935fea5e Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 20 Apr 2017 11:40:48 -0400 Subject: [PATCH 0187/2557] spherical: add functions to retrieve and request projection names Signed-off-by: James Almer Signed-off-by: Vittorio Giovara --- doc/APIchanges | 3 +++ libavutil/spherical.c | 28 ++++++++++++++++++++++++++++ libavutil/spherical.h | 18 ++++++++++++++++++ libavutil/version.h | 2 +- 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 58d59dd08ca1f..34d788a706f8f 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2017-03-23 API changes, most recent first: +2017-04-xx - xxxxxxx - lavu 56.1.0 - spherical.h + Add av_spherical_projection_name() and av_spherical_from_name(). + 2017-04-26 - xxxxxxx - lavc 58.3.1 - avcodec.h Add AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH. diff --git a/libavutil/spherical.c b/libavutil/spherical.c index f5accc487d831..b37db93b23b67 100644 --- a/libavutil/spherical.c +++ b/libavutil/spherical.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "common.h" #include "mem.h" #include "spherical.h" @@ -50,3 +51,30 @@ void av_spherical_tile_bounds(AVSphericalMapping *map, *right = orig_width - width - *left; *bottom = orig_height - height - *top; } + +static const char *spherical_projection_names[] = { + [AV_SPHERICAL_EQUIRECTANGULAR] = "equirectangular", + [AV_SPHERICAL_CUBEMAP] = "cubemap", + [AV_SPHERICAL_EQUIRECTANGULAR_TILE] = "tiled equirectangular", +}; + +const char *av_spherical_projection_name(enum AVSphericalProjection projection) +{ + if ((unsigned) projection >= FF_ARRAY_ELEMS(spherical_projection_names)) + return "unknown"; + + return spherical_projection_names[projection]; +} + +int av_spherical_from_name(const char *name) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(spherical_projection_names); i++) { + size_t len = strlen(spherical_projection_names[i]); + if (!strncmp(spherical_projection_names[i], name, len)) + return i; + } + + return AVERROR(EINVAL); +} diff --git a/libavutil/spherical.h b/libavutil/spherical.h index fd662cf676021..51ef22421ea20 100644 --- a/libavutil/spherical.h +++ b/libavutil/spherical.h @@ -206,6 +206,24 @@ void av_spherical_tile_bounds(AVSphericalMapping *map, size_t width, size_t height, size_t *left, size_t *top, size_t *right, size_t *bottom); + +/** + * Provide a human-readable name of a given AVSphericalProjection. + * + * @param projection The input AVSphericalProjection. + * + * @return The name of the AVSphericalProjection, or "unknown". + */ +const char *av_spherical_projection_name(enum AVSphericalProjection projection); + +/** + * Get the AVSphericalProjection form a human-readable name. + * + * @param name The input string. + * + * @return The AVSphericalProjection value, or AVERROR if not found. + */ +int av_spherical_from_name(const char *name); /** * @} * @} diff --git a/libavutil/version.h b/libavutil/version.h index b8425ea2c839e..fd72ff431d7fd 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -54,7 +54,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 0 +#define LIBAVUTIL_VERSION_MINOR 1 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 498864fe800a1b4d4db804aa7e5ebbc7867df6ce Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 4 Apr 2017 17:24:18 -0300 Subject: [PATCH 0188/2557] dump: use av_spherical_projection_name() to print spherical projection names Signed-off-by: James Almer --- libavformat/dump.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/libavformat/dump.c b/libavformat/dump.c index c56895628d754..261e21efd3536 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -317,16 +317,7 @@ static void dump_spherical(void *ctx, AVCodecParameters *par, AVPacketSideData * return; } - if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR) - av_log(ctx, AV_LOG_INFO, "equirectangular "); - else if (spherical->projection == AV_SPHERICAL_CUBEMAP) - av_log(ctx, AV_LOG_INFO, "cubemap "); - else if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) - av_log(ctx, AV_LOG_INFO, "tiled equirectangular "); - else { - av_log(ctx, AV_LOG_WARNING, "unknown"); - return; - } + av_log(ctx, AV_LOG_INFO, "%s ", av_spherical_projection_name(spherical->projection)); yaw = ((double)spherical->yaw) / (1 << 16); pitch = ((double)spherical->pitch) / (1 << 16); From c7bf98d4372e9217c8d75d2ca1f298385909e4da Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 4 Apr 2017 17:24:19 -0300 Subject: [PATCH 0189/2557] avprobe: use av_spherical_projection_name() to print spherical projection names Signed-off-by: James Almer --- avtools/avprobe.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/avtools/avprobe.c b/avtools/avprobe.c index 5f5e670f1b60b..a9ca1934ca574 100644 --- a/avtools/avprobe.c +++ b/avtools/avprobe.c @@ -817,25 +817,21 @@ static void show_stream(InputFile *ifile, InputStream *ist) case AV_PKT_DATA_SPHERICAL: spherical = (AVSphericalMapping *)sd->data; probe_object_header("spherical"); + probe_str("projection", av_spherical_projection_name(spherical->projection)); - if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR) { - probe_str("projection", "equirectangular"); - } else if (spherical->projection == AV_SPHERICAL_CUBEMAP) { - probe_str("projection", "cubemap"); + if (spherical->projection == AV_SPHERICAL_CUBEMAP) { probe_int("padding", spherical->padding); } else if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) { size_t l, t, r, b; av_spherical_tile_bounds(spherical, par->width, par->height, &l, &t, &r, &b); - probe_str("projection", "tiled equirectangular"); probe_object_header("bounding"); probe_int("left", l); probe_int("top", t); probe_int("right", r); probe_int("bottom", b); probe_object_footer("bounding"); - } else - probe_str("projection", "unknown"); + } probe_object_header("orientation"); probe_int("yaw", (double) spherical->yaw / (1 << 16)); From dd3aa85b68c017c419acb0c39ff6aa890ce89e87 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 26 Apr 2017 11:08:17 -0400 Subject: [PATCH 0190/2557] aac_ac3_parser: Drop in-parser downmix functionality request_channel_layout is a decoder option and it makes no sense to have it in a parser. This feature was needed in the past when the decoder was allowed to reuse the avctx from the demuxer. Nowadays the decoder receives only the parameters from it, already containing the real channel layout (and the correct request_channel_layout option). After initialization the decoder overwrites the channel layout with the downmixed one that is actually output, so there is no need to preserve this functionality in the parser. Signed-off-by: Vittorio Giovara --- libavcodec/aac_ac3_parser.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/libavcodec/aac_ac3_parser.c b/libavcodec/aac_ac3_parser.c index 806a826ea0f5a..a754f4a9579ab 100644 --- a/libavcodec/aac_ac3_parser.c +++ b/libavcodec/aac_ac3_parser.c @@ -82,20 +82,8 @@ int ff_aac_ac3_parse(AVCodecParserContext *s1, seconds is still correct (as is the number of bits in the frame). */ if (avctx->codec_id != AV_CODEC_ID_AAC) { avctx->sample_rate = s->sample_rate; - - /* (E-)AC-3: allow downmixing to stereo or mono */ - if (s->channels > 1 && - avctx->request_channel_layout == AV_CH_LAYOUT_MONO) { - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; - } else if (s->channels > 2 && - avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) { - avctx->channels = 2; - avctx->channel_layout = AV_CH_LAYOUT_STEREO; - } else { - avctx->channels = s->channels; - avctx->channel_layout = s->channel_layout; - } + avctx->channels = s->channels; + avctx->channel_layout = s->channel_layout; s1->duration = s->samples; avctx->audio_service_type = s->service_type; } From 970c76f32283bddf3a5afd24fe52db7a96186244 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 26 Apr 2017 11:08:17 -0400 Subject: [PATCH 0191/2557] mlp_parser: Drop in-parser downmix functionality request_channel_layout is a decoder option and it makes no sense to have it in a parser. This feature was needed in the past when the decoder was allowed to reuse the avctx from the demuxer. Nowadays the decoder receives only the parameters from it, already containing the real channel layout (and the correct request_channel_layout option). After initialization the decoder overwrites the channel layout with the downmixed one that is actually output, so there is no need to preserve this functionality in the parser. Signed-off-by: Vittorio Giovara --- libavcodec/mlp_parser.c | 23 +++-------------------- libavcodec/mlp_parser.h | 2 -- libavcodec/mlpdec.c | 7 ++++++- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index 7d73058e4cf12..bff6258cbaf70 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -120,11 +120,6 @@ static uint64_t truehd_layout(int chanmap) return layout; } -int ff_mlp_channel_layout_subset(uint64_t channel_layout, uint64_t mask) -{ - return channel_layout && ((channel_layout & mask) == channel_layout); -} - static int mlp_get_major_sync_size(const uint8_t * buf, int bufsize) { int has_extension, extensions = 0; @@ -336,8 +331,6 @@ static int mlp_parse(AVCodecParserContext *s, } else { BitstreamContext bc; MLPHeaderInfo mh; - int stereo_requested = ff_mlp_channel_layout_subset(avctx->request_channel_layout, - AV_CH_LAYOUT_STEREO); bitstream_init8(&bc, buf + 4, buf_size - 4); if (ff_mlp_read_major_sync(avctx, &mh, &bc) < 0) @@ -353,21 +346,11 @@ static int mlp_parse(AVCodecParserContext *s, if (mh.stream_type == 0xbb) { /* MLP stream */ - if (stereo_requested && mh.num_substreams > 1) { - avctx->channels = 2; - avctx->channel_layout = AV_CH_LAYOUT_STEREO; - } else { - avctx->channels = mh.channels_mlp; - avctx->channel_layout = mh.channel_layout_mlp; - } + avctx->channels = mh.channels_mlp; + avctx->channel_layout = mh.channel_layout_mlp; } else { /* mh.stream_type == 0xba */ /* TrueHD stream */ - if (stereo_requested && mh.num_substreams > 1) { - avctx->channels = 2; - avctx->channel_layout = AV_CH_LAYOUT_STEREO; - } else if (!mh.channels_thd_stream2 || - ff_mlp_channel_layout_subset(avctx->request_channel_layout, - mh.channel_layout_thd_stream1)) { + if (!mh.channels_thd_stream2) { avctx->channels = mh.channels_thd_stream1; avctx->channel_layout = mh.channel_layout_thd_stream1; } else { diff --git a/libavcodec/mlp_parser.h b/libavcodec/mlp_parser.h index 946f4d240c0bd..871b96db20486 100644 --- a/libavcodec/mlp_parser.h +++ b/libavcodec/mlp_parser.h @@ -63,6 +63,4 @@ typedef struct MLPHeaderInfo int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, BitstreamContext *bc); -int ff_mlp_channel_layout_subset(uint64_t channel_layout, uint64_t mask); - #endif /* AVCODEC_MLP_PARSER_H */ diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index fa94f6f5b4f21..4f6675a3cad06 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -178,6 +178,11 @@ static const uint64_t thd_channel_order[] = { AV_CH_LOW_FREQUENCY_2, // LFE2 }; +static int mlp_channel_layout_subset(uint64_t channel_layout, uint64_t mask) +{ + return channel_layout && ((channel_layout & mask) == channel_layout); +} + static uint64_t thd_channel_layout_extract_channel(uint64_t channel_layout, int index) { @@ -511,7 +516,7 @@ static int read_restart_header(MLPDecodeContext *m, BitstreamContext *bc, s->max_channel = max_channel; s->max_matrix_channel = max_matrix_channel; - if (ff_mlp_channel_layout_subset(m->avctx->request_channel_layout, s->mask) && + if (mlp_channel_layout_subset(m->avctx->request_channel_layout, s->mask) && m->max_decoded_substream > substr) { av_log(m->avctx, AV_LOG_DEBUG, "Extracting %d-channel downmix (0x%"PRIx64") from substream %d. " From 0d4d43513786f1df4d561e1fac924fb0722c6700 Mon Sep 17 00:00:00 2001 From: Seppo Tomperi Date: Thu, 27 Apr 2017 21:05:29 +0200 Subject: [PATCH 0192/2557] hevc: Add NEON add_residual for bitdepth 8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Optimized by Alexandra Hájková. Signed-off-by: Martin Storsjö --- libavcodec/arm/hevc_idct.S | 88 +++++++++++++++++++++++++++++++ libavcodec/arm/hevcdsp_init_arm.c | 15 ++++++ 2 files changed, 103 insertions(+) diff --git a/libavcodec/arm/hevc_idct.S b/libavcodec/arm/hevc_idct.S index 41b1b290bf49a..3966e93d857f3 100644 --- a/libavcodec/arm/hevc_idct.S +++ b/libavcodec/arm/hevc_idct.S @@ -30,6 +30,94 @@ const trans, align=4 .short 57, 43, 25, 9 endconst +function ff_hevc_add_residual_4x4_8_neon, export=1 + vld1.16 {q0-q1}, [r1, :128] + vld1.32 d4[0], [r0, :32], r2 + vld1.32 d4[1], [r0, :32], r2 + vld1.32 d5[0], [r0, :32], r2 + vld1.32 d5[1], [r0, :32], r2 + sub r0, r0, r2, lsl #2 + vmovl.u8 q8, d4 + vmovl.u8 q9, d5 + vqadd.s16 q0, q0, q8 + vqadd.s16 q1, q1, q9 + vqmovun.s16 d0, q0 + vqmovun.s16 d1, q1 + vst1.32 d0[0], [r0, :32], r2 + vst1.32 d0[1], [r0, :32], r2 + vst1.32 d1[0], [r0, :32], r2 + vst1.32 d1[1], [r0, :32], r2 + bx lr +endfunc + +function ff_hevc_add_residual_8x8_8_neon, export=1 + mov r3, #8 +1: subs r3, #2 + vld1.16 {q0-q1}, [r1, :128]! + vld1.8 {d16}, [r0, :64] + add r12, r0, r2 + vld1.8 {d17}, [r12, :64] + vmovl.u8 q9, d16 + vmovl.u8 q8, d17 + vqadd.s16 q0, q9 + vqadd.s16 q1, q8 + vqmovun.s16 d0, q0 + vqmovun.s16 d1, q1 + vst1.8 d0, [r0, :64], r2 + vst1.8 d1, [r0, :64], r2 + bne 1b + bx lr +endfunc + +function ff_hevc_add_residual_16x16_8_neon, export=1 + mov r3, #16 + add r12, r0, r2 + add r2, r2, r2 +1: subs r3, #2 + vld1.8 {q8}, [r0, :128] + vld1.16 {q0, q1}, [r1, :128]! + vld1.8 {q11}, [r12, :128] + vld1.16 {q2, q3}, [r1, :128]! + vmovl.u8 q9, d16 + vmovl.u8 q10, d17 + vmovl.u8 q12, d22 + vmovl.u8 q13, d23 + vqadd.s16 q0, q9 + vqadd.s16 q1, q10 + vqadd.s16 q2, q12 + vqadd.s16 q3, q13 + vqmovun.s16 d0, q0 + vqmovun.s16 d1, q1 + vqmovun.s16 d2, q2 + vqmovun.s16 d3, q3 + vst1.8 {q0}, [r0, :128], r2 + vst1.8 {q1}, [r12, :128], r2 + bne 1b + bx lr +endfunc + +function ff_hevc_add_residual_32x32_8_neon, export=1 + mov r3, #32 +1: subs r3, #1 + vldm r1!, {q0-q3} + vld1.8 {q8, q9}, [r0, :128] + vmovl.u8 q10, d16 + vmovl.u8 q11, d17 + vmovl.u8 q12, d18 + vmovl.u8 q13, d19 + vqadd.s16 q0, q10 + vqadd.s16 q1, q11 + vqadd.s16 q2, q12 + vqadd.s16 q3, q13 + vqmovun.s16 d0, q0 + vqmovun.s16 d1, q1 + vqmovun.s16 d2, q2 + vqmovun.s16 d3, q3 + vst1.8 {q0, q1}, [r0, :128], r2 + bne 1b + bx lr +endfunc + .macro idct_4x4_dc bitdepth function ff_hevc_idct_4x4_dc_\bitdepth\()_neon, export=1 ldrsh r1, [r0] diff --git a/libavcodec/arm/hevcdsp_init_arm.c b/libavcodec/arm/hevcdsp_init_arm.c index 3d8d06b136245..817c1572108ad 100644 --- a/libavcodec/arm/hevcdsp_init_arm.c +++ b/libavcodec/arm/hevcdsp_init_arm.c @@ -25,6 +25,16 @@ #include "libavcodec/hevcdsp.h" + +void ff_hevc_add_residual_4x4_8_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); +void ff_hevc_add_residual_8x8_8_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); +void ff_hevc_add_residual_16x16_8_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); +void ff_hevc_add_residual_32x32_8_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); + void ff_hevc_idct_4x4_dc_8_neon(int16_t *coeffs); void ff_hevc_idct_8x8_dc_8_neon(int16_t *coeffs); void ff_hevc_idct_16x16_dc_8_neon(int16_t *coeffs); @@ -47,6 +57,11 @@ av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, int bit_depth) if (have_neon(cpu_flags)) { if (bit_depth == 8) { + c->add_residual[0] = ff_hevc_add_residual_4x4_8_neon; + c->add_residual[1] = ff_hevc_add_residual_8x8_8_neon; + c->add_residual[2] = ff_hevc_add_residual_16x16_8_neon; + c->add_residual[3] = ff_hevc_add_residual_32x32_8_neon; + c->idct_dc[0] = ff_hevc_idct_4x4_dc_8_neon; c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_neon; c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_neon; From e1c2453a4fac1f7116244d0d05310935c20887e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 28 Apr 2017 00:36:40 +0300 Subject: [PATCH 0193/2557] arm: hevc_idct: Tune the add_res_8x8 and add_res_32x32 functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before: Cortex A7 A8 A9 A53 hevc_add_res_8x8_8_neon: 116.0 58.7 80.2 90.7 hevc_add_res_32x32_8_neon: 1230.0 737.5 1187.5 974.4 After: hevc_add_res_8x8_8_neon: 97.7 57.0 73.7 80.0 hevc_add_res_32x32_8_neon: 1216.0 698.7 1127.5 827.1 Signed-off-by: Martin Storsjö --- libavcodec/arm/hevc_idct.S | 51 ++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/libavcodec/arm/hevc_idct.S b/libavcodec/arm/hevc_idct.S index 3966e93d857f3..b3ce00b7fdd7e 100644 --- a/libavcodec/arm/hevc_idct.S +++ b/libavcodec/arm/hevc_idct.S @@ -51,20 +51,21 @@ function ff_hevc_add_residual_4x4_8_neon, export=1 endfunc function ff_hevc_add_residual_8x8_8_neon, export=1 + add r12, r0, r2 + add r2, r2, r2 mov r3, #8 1: subs r3, #2 - vld1.16 {q0-q1}, [r1, :128]! - vld1.8 {d16}, [r0, :64] - add r12, r0, r2 + vld1.8 {d16}, [r0, :64] vld1.8 {d17}, [r12, :64] vmovl.u8 q9, d16 + vld1.16 {q0-q1}, [r1, :128]! vmovl.u8 q8, d17 vqadd.s16 q0, q9 vqadd.s16 q1, q8 vqmovun.s16 d0, q0 vqmovun.s16 d1, q1 - vst1.8 d0, [r0, :64], r2 - vst1.8 d1, [r0, :64], r2 + vst1.8 d0, [r0, :64], r2 + vst1.8 d1, [r12, :64], r2 bne 1b bx lr endfunc @@ -97,24 +98,42 @@ function ff_hevc_add_residual_16x16_8_neon, export=1 endfunc function ff_hevc_add_residual_32x32_8_neon, export=1 + vpush {q4-q7} + add r12, r0, r2 + add r2, r2, r2 mov r3, #32 -1: subs r3, #1 - vldm r1!, {q0-q3} - vld1.8 {q8, q9}, [r0, :128] - vmovl.u8 q10, d16 - vmovl.u8 q11, d17 - vmovl.u8 q12, d18 - vmovl.u8 q13, d19 - vqadd.s16 q0, q10 - vqadd.s16 q1, q11 - vqadd.s16 q2, q12 - vqadd.s16 q3, q13 +1: subs r3, #2 + vld1.8 {q12, q13}, [r0, :128] + vmovl.u8 q8, d24 + vmovl.u8 q9, d25 + vld1.8 {q14, q15}, [r12, :128] + vmovl.u8 q10, d26 + vmovl.u8 q11, d27 + vmovl.u8 q12, d28 + vldm r1!, {q0-q7} + vmovl.u8 q13, d29 + vmovl.u8 q14, d30 + vmovl.u8 q15, d31 + vqadd.s16 q0, q8 + vqadd.s16 q1, q9 + vqadd.s16 q2, q10 + vqadd.s16 q3, q11 + vqadd.s16 q4, q12 + vqadd.s16 q5, q13 + vqadd.s16 q6, q14 + vqadd.s16 q7, q15 vqmovun.s16 d0, q0 vqmovun.s16 d1, q1 vqmovun.s16 d2, q2 vqmovun.s16 d3, q3 + vqmovun.s16 d4, q4 + vqmovun.s16 d5, q5 vst1.8 {q0, q1}, [r0, :128], r2 + vqmovun.s16 d6, q6 + vqmovun.s16 d7, q7 + vst1.8 {q2, q3}, [r12, :128], r2 bne 1b + vpop {q4-q7} bx lr endfunc From 831018b0bbe26a603802a9022472f714a59293be Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 16 Mar 2017 17:34:12 +0100 Subject: [PATCH 0194/2557] mpeg4audio: Make avpriv_copy_pce_data() inline The function currently accepts a PutBitContext and a GetBitContext, which hardcodes their sizes into the lavc ABI. Since the function is quite small and only called in a few places, the simplest solution is making it inline, thus avoiding a runtime dependency completely. Signed-off-by: Diego Biurrun --- libavcodec/aac_adtstoasc_bsf.c | 2 +- libavcodec/mpeg4audio.c | 40 ------------------------------- libavcodec/mpeg4audio.h | 43 +++++++++++++++++++++++++++++++++- libavformat/adtsenc.c | 2 +- libavformat/latmenc.c | 2 +- 5 files changed, 45 insertions(+), 44 deletions(-) diff --git a/libavcodec/aac_adtstoasc_bsf.c b/libavcodec/aac_adtstoasc_bsf.c index 08d60eb06ffcb..3a83d488c4507 100644 --- a/libavcodec/aac_adtstoasc_bsf.c +++ b/libavcodec/aac_adtstoasc_bsf.c @@ -91,7 +91,7 @@ static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out) goto fail; } init_put_bits(&pb, pce_data, MAX_PCE_SIZE); - pce_size = avpriv_copy_pce_data(&pb, &gb)/8; + pce_size = ff_copy_pce_data(&pb, &gb) / 8; flush_put_bits(&pb); in->size -= get_bits_count(&gb)/8; in->data += get_bits_count(&gb)/8; diff --git a/libavcodec/mpeg4audio.c b/libavcodec/mpeg4audio.c index af8e6552ffb99..e321bcca83d86 100644 --- a/libavcodec/mpeg4audio.c +++ b/libavcodec/mpeg4audio.c @@ -145,43 +145,3 @@ int avpriv_mpeg4audio_get_config(MPEG4AudioConfig *c, const uint8_t *buf, return specific_config_bitindex; } - -static av_always_inline unsigned int copy_bits(PutBitContext *pb, - GetBitContext *gb, - int bits) -{ - unsigned int el = get_bits(gb, bits); - put_bits(pb, bits, el); - return el; -} - -int avpriv_copy_pce_data(PutBitContext *pb, GetBitContext *gb) -{ - int five_bit_ch, four_bit_ch, comment_size, bits; - int offset = put_bits_count(pb); - - copy_bits(pb, gb, 10); //Tag, Object Type, Frequency - five_bit_ch = copy_bits(pb, gb, 4); //Front - five_bit_ch += copy_bits(pb, gb, 4); //Side - five_bit_ch += copy_bits(pb, gb, 4); //Back - four_bit_ch = copy_bits(pb, gb, 2); //LFE - four_bit_ch += copy_bits(pb, gb, 3); //Data - five_bit_ch += copy_bits(pb, gb, 4); //Coupling - if (copy_bits(pb, gb, 1)) //Mono Mixdown - copy_bits(pb, gb, 4); - if (copy_bits(pb, gb, 1)) //Stereo Mixdown - copy_bits(pb, gb, 4); - if (copy_bits(pb, gb, 1)) //Matrix Mixdown - copy_bits(pb, gb, 3); - for (bits = five_bit_ch*5+four_bit_ch*4; bits > 16; bits -= 16) - copy_bits(pb, gb, 16); - if (bits) - copy_bits(pb, gb, bits); - avpriv_align_put_bits(pb); - align_get_bits(gb); - comment_size = copy_bits(pb, gb, 8); - for (; comment_size > 0; comment_size--) - copy_bits(pb, gb, 8); - - return put_bits_count(pb) - offset; -} diff --git a/libavcodec/mpeg4audio.h b/libavcodec/mpeg4audio.h index 2eef2205bd651..01f30c6ca7097 100644 --- a/libavcodec/mpeg4audio.h +++ b/libavcodec/mpeg4audio.h @@ -23,6 +23,9 @@ #define AVCODEC_MPEG4AUDIO_H #include + +#include "libavutil/attributes.h" + #include "get_bits.h" #include "put_bits.h" @@ -105,6 +108,44 @@ enum AudioObjectType { #define MAX_PCE_SIZE 304 /// 16; bits -= 16) + ff_pce_copy_bits(pb, gb, 16); + if (bits) + ff_pce_copy_bits(pb, gb, bits); + avpriv_align_put_bits(pb); + align_get_bits(gb); + comment_size = ff_pce_copy_bits(pb, gb, 8); + for (; comment_size > 0; comment_size--) + ff_pce_copy_bits(pb, gb, 8); + + return put_bits_count(pb) - offset; +} #endif /* AVCODEC_MPEG4AUDIO_H */ diff --git a/libavformat/adtsenc.c b/libavformat/adtsenc.c index e7c72d8c026ac..eac6e7f8836a5 100644 --- a/libavformat/adtsenc.c +++ b/libavformat/adtsenc.c @@ -79,7 +79,7 @@ static int adts_decode_extradata(AVFormatContext *s, ADTSContext *adts, uint8_t init_put_bits(&pb, adts->pce_data, MAX_PCE_SIZE); put_bits(&pb, 3, 5); //ID_PCE - adts->pce_size = (avpriv_copy_pce_data(&pb, &gb) + 3) / 8; + adts->pce_size = (ff_copy_pce_data(&pb, &gb) + 3) / 8; flush_put_bits(&pb); } diff --git a/libavformat/latmenc.c b/libavformat/latmenc.c index a98a6ff6b02e2..ea13a8a38cc87 100644 --- a/libavformat/latmenc.c +++ b/libavformat/latmenc.c @@ -111,7 +111,7 @@ static int latm_write_frame_header(AVFormatContext *s, PutBitContext *bs) avpriv_copy_bits(bs, par->extradata, ctx->off + 3); if (!ctx->channel_conf) { - avpriv_copy_pce_data(bs, &gb); + ff_copy_pce_data(bs, &gb); } } From b43b95f4789b6e60f9684918fd3c0a5f3f18aef6 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 26 Apr 2017 21:39:54 +0100 Subject: [PATCH 0195/2557] vp9_raw_reorder_bsf: Remove a redundant allocation This was left over from an earlier version which created the new packet inside the current frame structure. Now it just leaks an unused packet, so remove the allocation entirely. --- libavcodec/vp9_raw_reorder_bsf.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavcodec/vp9_raw_reorder_bsf.c b/libavcodec/vp9_raw_reorder_bsf.c index 7f00f5f10391d..f5a5e49edaf29 100644 --- a/libavcodec/vp9_raw_reorder_bsf.c +++ b/libavcodec/vp9_raw_reorder_bsf.c @@ -241,10 +241,6 @@ static int vp9_raw_reorder_make_output(AVBSFContext *bsf, "(%"PRId64") from slot %d.\n", frame->sequence, frame->pts, s); - frame->packet = av_packet_alloc(); - if (!frame->packet) - return AVERROR(ENOMEM); - err = av_new_packet(out, 2); if (err < 0) return err; From 9203aac22874c7259e155b7d00f1f33bb1355129 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 30 Apr 2017 14:11:51 +0100 Subject: [PATCH 0196/2557] avconv_hw: Add implicit device creation with default parameters If -hwaccel foo is supplied without any other device options, and the foo hwaccel is meant to have a device, try to make such a device with default parameters for the hwaccel to use. --- avtools/avconv_hw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/avtools/avconv_hw.c b/avtools/avconv_hw.c index fd1618389b8a4..94be7233041cf 100644 --- a/avtools/avconv_hw.c +++ b/avtools/avconv_hw.c @@ -287,6 +287,10 @@ int hw_device_setup_for_decode(InputStream *ist) type = hw_device_match_type_in_name(ist->dec->name); if (type != AV_HWDEVICE_TYPE_NONE) { dev = hw_device_get_by_type(type); + if (!dev) { + hw_device_init_from_string(av_hwdevice_get_type_name(type), + &dev); + } } else { // No device required. return 0; From e669db76108de8d7a36c2274c99da82cc94d1dd1 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:38 +0000 Subject: [PATCH 0197/2557] avconv: Support setting the hardware device to use when filtering This only supports one device globally, but more can be used by passing them with input streams in hw_frames_ctx or by deriving new devices inside a filter graph with hwmap. --- avtools/avconv.h | 1 + avtools/avconv_filter.c | 10 ++++++++-- avtools/avconv_opt.c | 17 +++++++++++++++++ doc/avconv.texi | 14 ++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/avtools/avconv.h b/avtools/avconv.h index 9415b208be42e..3354c50444a4e 100644 --- a/avtools/avconv.h +++ b/avtools/avconv.h @@ -489,6 +489,7 @@ extern const OptionDef options[]; extern const HWAccel hwaccels[]; extern int hwaccel_lax_profile_check; extern AVBufferRef *hw_device_ctx; +extern HWDevice *filter_hw_device; void reset_options(OptionsContext *o); void show_usage(void); diff --git a/avtools/avconv_filter.c b/avtools/avconv_filter.c index e53dcd271c32e..884478da274c8 100644 --- a/avtools/avconv_filter.c +++ b/avtools/avconv_filter.c @@ -711,9 +711,15 @@ int configure_filtergraph(FilterGraph *fg) if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) goto fail; - if (hw_device_ctx) { + if (filter_hw_device || hw_device_ctx) { + AVBufferRef *device = filter_hw_device ? filter_hw_device->device_ref + : hw_device_ctx; for (i = 0; i < fg->graph->nb_filters; i++) { - fg->graph->filters[i]->hw_device_ctx = av_buffer_ref(hw_device_ctx); + fg->graph->filters[i]->hw_device_ctx = av_buffer_ref(device); + if (!fg->graph->filters[i]->hw_device_ctx) { + ret = AVERROR(ENOMEM); + goto fail; + } } } diff --git a/avtools/avconv_opt.c b/avtools/avconv_opt.c index e970c8e46c305..9839a2269e15f 100644 --- a/avtools/avconv_opt.c +++ b/avtools/avconv_opt.c @@ -80,6 +80,7 @@ const HWAccel hwaccels[] = { }; int hwaccel_lax_profile_check = 0; AVBufferRef *hw_device_ctx; +HWDevice *filter_hw_device; char *vstats_filename; @@ -369,6 +370,20 @@ static int opt_init_hw_device(void *optctx, const char *opt, const char *arg) } } +static int opt_filter_hw_device(void *optctx, const char *opt, const char *arg) +{ + if (filter_hw_device) { + av_log(NULL, AV_LOG_ERROR, "Only one filter device can be used.\n"); + return AVERROR(EINVAL); + } + filter_hw_device = hw_device_get_by_name(arg); + if (!filter_hw_device) { + av_log(NULL, AV_LOG_ERROR, "Invalid filter device %s.\n", arg); + return AVERROR(EINVAL); + } + return 0; +} + /** * Parse a metadata specifier passed as 'arg' parameter. * @param arg metadata string to parse @@ -2775,6 +2790,8 @@ const OptionDef options[] = { { "init_hw_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_init_hw_device }, "initialise hardware device", "args" }, + { "filter_hw_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_hw_device }, + "set hardware device used when filtering", "device" }, { NULL, }, }; diff --git a/doc/avconv.texi b/doc/avconv.texi index 7bcb7879795bc..d8eb44864b569 100644 --- a/doc/avconv.texi +++ b/doc/avconv.texi @@ -644,6 +644,20 @@ deriving it from the existing device with the name @var{source}. @item -init_hw_device list List all hardware device types supported in this build of avconv. +@item -filter_hw_device @var{name} +Pass the hardware device called @var{name} to all filters in any filter graph. +This can be used to set the device to upload to with the @code{hwupload} filter, +or the device to map to with the @code{hwmap} filter. Other filters may also +make use of this parameter when they require a hardware device. Note that this +is typically only required when the input is not already in hardware frames - +when it is, filters will derive the device they require from the context of the +frames they receive as input. + +This is a global setting, so all filters will receive the same device. + +Do not use this option in scripts that should remain functional in future +avconv versions. + @item -hwaccel[:@var{stream_specifier}] @var{hwaccel} (@emph{input,per-stream}) Use hardware acceleration to decode the matching stream(s). The allowed values of @var{hwaccel} are: From aa51bb3d2756ed912ee40645efccf5f4a9609696 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:43 +0000 Subject: [PATCH 0198/2557] hwcontext_qsv: Support derivation from child devices --- libavutil/hwcontext_qsv.c | 113 ++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 29 deletions(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 3409e9b976184..46636ef9eb929 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -792,21 +792,96 @@ static mfxIMPL choose_implementation(const char *device) return impl; } -static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, - AVDictionary *opts, int flags) +static int qsv_device_derive_from_child(AVHWDeviceContext *ctx, + mfxIMPL implementation, + AVHWDeviceContext *child_device_ctx, + int flags) { AVQSVDeviceContext *hwctx = ctx->hwctx; - QSVDevicePriv *priv; - enum AVHWDeviceType child_device_type; - AVDictionaryEntry *e; + QSVDeviceContext *s = ctx->internal->priv; mfxVersion ver = { { 3, 1 } }; - mfxIMPL impl; mfxHDL handle; mfxHandleType handle_type; mfxStatus err; int ret; + switch (child_device_ctx->type) { +#if CONFIG_VAAPI + case AV_HWDEVICE_TYPE_VAAPI: + { + AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx; + handle_type = MFX_HANDLE_VA_DISPLAY; + handle = (mfxHDL)child_device_hwctx->display; + } + break; +#endif +#if CONFIG_DXVA2 + case AV_HWDEVICE_TYPE_DXVA2: + { + AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx; + handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER; + handle = (mfxHDL)child_device_hwctx->devmgr; + } + break; +#endif + default: + ret = AVERROR(ENOSYS); + goto fail; + } + + err = MFXInit(implementation, &ver, &hwctx->session); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session: " + "%d.\n", err); + ret = AVERROR_UNKNOWN; + goto fail; + } + + err = MFXVideoCORE_SetHandle(hwctx->session, handle_type, handle); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Error setting child device handle: " + "%d\n", err); + ret = AVERROR_UNKNOWN; + goto fail; + } + + ret = qsv_device_init(ctx); + if (ret < 0) + goto fail; + if (s->handle_type != handle_type) { + av_log(ctx, AV_LOG_ERROR, "Error in child device handle setup: " + "type mismatch (%d != %d).\n", s->handle_type, handle_type); + err = AVERROR_UNKNOWN; + goto fail; + } + + return 0; + +fail: + if (hwctx->session) + MFXClose(hwctx->session); + return ret; +} + +static int qsv_device_derive(AVHWDeviceContext *ctx, + AVHWDeviceContext *child_device_ctx, int flags) +{ + return qsv_device_derive_from_child(ctx, MFX_IMPL_HARDWARE_ANY, + child_device_ctx, flags); +} + +static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, + AVDictionary *opts, int flags) +{ + QSVDevicePriv *priv; + enum AVHWDeviceType child_device_type; + AVHWDeviceContext *child_device; + AVDictionaryEntry *e; + + mfxIMPL impl; + int ret; + priv = av_mallocz(sizeof(*priv)); if (!priv) return AVERROR(ENOMEM); @@ -830,32 +905,11 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, if (ret < 0) return ret; - { - AVHWDeviceContext *child_device_ctx = (AVHWDeviceContext*)priv->child_device_ctx->data; -#if CONFIG_VAAPI - AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx; - handle_type = MFX_HANDLE_VA_DISPLAY; - handle = (mfxHDL)child_device_hwctx->display; -#elif CONFIG_DXVA2 - AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx; - handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER; - handle = (mfxHDL)child_device_hwctx->devmgr; -#endif - } + child_device = (AVHWDeviceContext*)priv->child_device_ctx->data; impl = choose_implementation(device); - err = MFXInit(impl, &ver, &hwctx->session); - if (err != MFX_ERR_NONE) { - av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session\n"); - return AVERROR_UNKNOWN; - } - - err = MFXVideoCORE_SetHandle(hwctx->session, handle_type, handle); - if (err != MFX_ERR_NONE) - return AVERROR_UNKNOWN; - - return 0; + return qsv_device_derive_from_child(ctx, impl, child_device, 0); } const HWContextType ff_hwcontext_type_qsv = { @@ -868,6 +922,7 @@ const HWContextType ff_hwcontext_type_qsv = { .frames_priv_size = sizeof(QSVFramesContext), .device_create = qsv_device_create, + .device_derive = qsv_device_derive, .device_init = qsv_device_init, .frames_get_constraints = qsv_frames_get_constraints, .frames_init = qsv_frames_init, From 27978155bc661eec9f22bcf82c9cfc099cff4365 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:39 +0000 Subject: [PATCH 0199/2557] hwcontext: Add frame context mapping for nontrivial contexts Some frames contexts are not usable without additional format-specific state in hwctx. This change adds new functions frames_derive_from and frames_derive_to to initialise this state appropriately when deriving a frames context which will require it to be set. --- libavutil/hwcontext.c | 9 ++++++++- libavutil/hwcontext_internal.h | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index ff9fe99abae21..a6d88421d8bb9 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -816,7 +816,14 @@ int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, goto fail; } - ret = av_hwframe_ctx_init(dst_ref); + ret = AVERROR(ENOSYS); + if (src->internal->hw_type->frames_derive_from) + ret = src->internal->hw_type->frames_derive_from(dst, src, flags); + if (ret == AVERROR(ENOSYS) && + dst->internal->hw_type->frames_derive_to) + ret = dst->internal->hw_type->frames_derive_to(dst, src, flags); + if (ret == AVERROR(ENOSYS)) + ret = 0; if (ret) goto fail; diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h index 66f54142e8ef6..87b32e191e9f3 100644 --- a/libavutil/hwcontext_internal.h +++ b/libavutil/hwcontext_internal.h @@ -92,6 +92,11 @@ typedef struct HWContextType { const AVFrame *src, int flags); int (*map_from)(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, int flags); + + int (*frames_derive_to)(AVHWFramesContext *dst_ctx, + AVHWFramesContext *src_ctx, int flags); + int (*frames_derive_from)(AVHWFramesContext *dst_ctx, + AVHWFramesContext *src_ctx, int flags); } HWContextType; struct AVHWDeviceInternal { From eaa5e0710496db50fc164806e5f49eaaccc83bb5 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:44 +0000 Subject: [PATCH 0200/2557] hwcontext_qsv: Implement mapping frames from the child device type Factorises out existing surface initialisation code to reuse. --- libavutil/hwcontext_qsv.c | 174 +++++++++++++++++++++++++++++++------- 1 file changed, 142 insertions(+), 32 deletions(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 46636ef9eb929..ca50bcd948aac 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -94,6 +94,16 @@ static const struct { { AV_PIX_FMT_PAL8, MFX_FOURCC_P8 }, }; +static uint32_t qsv_fourcc_from_pix_fmt(enum AVPixelFormat pix_fmt) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++) { + if (supported_pixel_formats[i].pix_fmt == pix_fmt) + return supported_pixel_formats[i].fourcc; + } + return 0; +} + static int qsv_device_init(AVHWDeviceContext *ctx) { AVQSVDeviceContext *hwctx = ctx->hwctx; @@ -272,18 +282,48 @@ static int qsv_init_child_ctx(AVHWFramesContext *ctx) return ret; } +static int qsv_init_surface(AVHWFramesContext *ctx, mfxFrameSurface1 *surf) +{ + const AVPixFmtDescriptor *desc; + uint32_t fourcc; + + desc = av_pix_fmt_desc_get(ctx->sw_format); + if (!desc) + return AVERROR(EINVAL); + + fourcc = qsv_fourcc_from_pix_fmt(ctx->sw_format); + if (!fourcc) + return AVERROR(EINVAL); + + surf->Info.BitDepthLuma = desc->comp[0].depth; + surf->Info.BitDepthChroma = desc->comp[0].depth; + surf->Info.Shift = desc->comp[0].depth > 8; + + if (desc->log2_chroma_w && desc->log2_chroma_h) + surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420; + else if (desc->log2_chroma_w) + surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV422; + else + surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV444; + + surf->Info.FourCC = fourcc; + surf->Info.Width = ctx->width; + surf->Info.CropW = ctx->width; + surf->Info.Height = ctx->height; + surf->Info.CropH = ctx->height; + surf->Info.FrameRateExtN = 25; + surf->Info.FrameRateExtD = 1; + + return 0; +} + static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc) { QSVFramesContext *s = ctx->internal->priv; AVQSVFramesContext *frames_hwctx = ctx->hwctx; - const AVPixFmtDescriptor *desc; int i, ret = 0; - desc = av_pix_fmt_desc_get(ctx->sw_format); - if (!desc) - return AVERROR_BUG; - if (ctx->initial_pool_size <= 0) { av_log(ctx, AV_LOG_ERROR, "QSV requires a fixed frame pool size\n"); return AVERROR(EINVAL); @@ -295,26 +335,9 @@ static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc) return AVERROR(ENOMEM); for (i = 0; i < ctx->initial_pool_size; i++) { - mfxFrameSurface1 *surf = &s->surfaces_internal[i]; - - surf->Info.BitDepthLuma = desc->comp[0].depth; - surf->Info.BitDepthChroma = desc->comp[0].depth; - surf->Info.Shift = desc->comp[0].depth > 8; - - if (desc->log2_chroma_w && desc->log2_chroma_h) - surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420; - else if (desc->log2_chroma_w) - surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV422; - else - surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV444; - - surf->Info.FourCC = fourcc; - surf->Info.Width = ctx->width; - surf->Info.CropW = ctx->width; - surf->Info.Height = ctx->height; - surf->Info.CropH = ctx->height; - surf->Info.FrameRateExtN = 25; - surf->Info.FrameRateExtD = 1; + ret = qsv_init_surface(ctx, &s->surfaces_internal[i]); + if (ret < 0) + return ret; } if (!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)) { @@ -466,15 +489,10 @@ static int qsv_frames_init(AVHWFramesContext *ctx) int opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME); - uint32_t fourcc = 0; + uint32_t fourcc; int i, ret; - for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++) { - if (supported_pixel_formats[i].pix_fmt == ctx->sw_format) { - fourcc = supported_pixel_formats[i].fourcc; - break; - } - } + fourcc = qsv_fourcc_from_pix_fmt(ctx->sw_format); if (!fourcc) { av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format\n"); return AVERROR(ENOSYS); @@ -723,6 +741,96 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, return 0; } +static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx, + AVHWFramesContext *src_ctx, int flags) +{ + QSVFramesContext *s = dst_ctx->internal->priv; + AVQSVFramesContext *dst_hwctx = dst_ctx->hwctx; + int i; + + switch (src_ctx->device_ctx->type) { +#if CONFIG_VAAPI + case AV_HWDEVICE_TYPE_VAAPI: + { + AVVAAPIFramesContext *src_hwctx = src_ctx->hwctx; + s->surfaces_internal = av_mallocz_array(src_hwctx->nb_surfaces, + sizeof(*s->surfaces_internal)); + if (!s->surfaces_internal) + return AVERROR(ENOMEM); + for (i = 0; i < src_hwctx->nb_surfaces; i++) { + qsv_init_surface(dst_ctx, &s->surfaces_internal[i]); + s->surfaces_internal[i].Data.MemId = src_hwctx->surface_ids + i; + } + dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces; + dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; + } + break; +#endif +#if CONFIG_DXVA2 + case AV_HWDEVICE_TYPE_DXVA2: + { + AVDXVA2FramesContext *src_hwctx = src_ctx->hwctx; + s->surfaces_internal = av_mallocz_array(src_hwctx->nb_surfaces, + sizeof(*s->surfaces_internal)); + if (!s->surfaces_internal) + return AVERROR(ENOMEM); + for (i = 0; i < src_hwctx->nb_surfaces; i++) { + qsv_init_surface(dst_ctx, &s->surfaces_internal[i]); + s->surfaces_internal[i].Data.MemId = (mfxMemId)src_hwctx->surfaces[i]; + } + dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces; + if (src_hwctx->surface_type == DXVA2_VideoProcessorRenderTarget) + dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET; + else + dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; + } + break; +#endif + default: + return AVERROR(ENOSYS); + } + + dst_hwctx->surfaces = s->surfaces_internal; + + return 0; +} + +static int qsv_map_to(AVHWFramesContext *dst_ctx, + AVFrame *dst, const AVFrame *src, int flags) +{ + AVQSVFramesContext *hwctx = dst_ctx->hwctx; + int i, err; + + for (i = 0; i < hwctx->nb_surfaces; i++) { +#if CONFIG_VAAPI + if (*(VASurfaceID*)hwctx->surfaces[i].Data.MemId == + (VASurfaceID)(uintptr_t)src->data[3]) + break; +#endif +#if CONFIG_DXVA2 + if ((IDirect3DSurface9*)hwctx->surfaces[i].Data.MemId == + (IDirect3DSurface9*)(uintptr_t)src->data[3]) + break; +#endif + } + if (i >= hwctx->nb_surfaces) { + av_log(dst_ctx, AV_LOG_ERROR, "Trying to map from a surface which " + "is not in the mapped frames context.\n"); + return AVERROR(EINVAL); + } + + err = ff_hwframe_map_create(dst->hw_frames_ctx, + dst, src, NULL, NULL); + if (err) + return err; + + dst->width = src->width; + dst->height = src->height; + dst->data[3] = (uint8_t*)&hwctx->surfaces[i]; + + return 0; +} + static int qsv_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints) @@ -931,7 +1039,9 @@ const HWContextType ff_hwcontext_type_qsv = { .transfer_get_formats = qsv_transfer_get_formats, .transfer_data_to = qsv_transfer_data_to, .transfer_data_from = qsv_transfer_data_from, + .map_to = qsv_map_to, .map_from = qsv_map_from, + .frames_derive_to = qsv_frames_derive_to, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, }; From e1c5d56b18b82e3fb42382b1b1f972e8b371fc38 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:45 +0000 Subject: [PATCH 0201/2557] hwcontext_qsv: Implement mapping frames to the child device type --- libavutil/hwcontext_qsv.c | 88 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index ca50bcd948aac..e0f6875b40c87 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -577,13 +577,62 @@ static int qsv_transfer_get_formats(AVHWFramesContext *ctx, return 0; } +static int qsv_frames_derive_from(AVHWFramesContext *dst_ctx, + AVHWFramesContext *src_ctx, int flags) +{ + AVQSVFramesContext *src_hwctx = src_ctx->hwctx; + int i; + + switch (dst_ctx->device_ctx->type) { +#if CONFIG_VAAPI + case AV_HWDEVICE_TYPE_VAAPI: + { + AVVAAPIFramesContext *dst_hwctx = dst_ctx->hwctx; + dst_hwctx->surface_ids = av_mallocz_array(src_hwctx->nb_surfaces, + sizeof(*dst_hwctx->surface_ids)); + if (!dst_hwctx->surface_ids) + return AVERROR(ENOMEM); + for (i = 0; i < src_hwctx->nb_surfaces; i++) + dst_hwctx->surface_ids[i] = + *(VASurfaceID*)src_hwctx->surfaces[i].Data.MemId; + dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces; + } + break; +#endif +#if CONFIG_DXVA2 + case AV_HWDEVICE_TYPE_DXVA2: + { + AVDXVA2FramesContext *dst_hwctx = dst_ctx->hwctx; + dst_hwctx->surfaces = av_mallocz_array(src_hwctx->nb_surfaces, + sizeof(*dst_hwctx->surfaces)); + if (!dst_hwctx->surfaces) + return AVERROR(ENOMEM); + for (i = 0; i < src_hwctx->nb_surfaces; i++) + dst_hwctx->surfaces[i] = + (IDirect3DSurface9*)src_hwctx->surfaces[i].Data.MemId; + dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces; + if (src_hwctx->frame_type == MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET) + dst_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget; + else + dst_hwctx->surface_type = DXVA2_VideoProcessorRenderTarget; + } + break; +#endif + default: + return AVERROR(ENOSYS); + } + + return 0; +} + static int qsv_map_from(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, int flags) { QSVFramesContext *s = ctx->internal->priv; mfxFrameSurface1 *surf = (mfxFrameSurface1*)src->data[3]; AVHWFramesContext *child_frames_ctx; - + const AVPixFmtDescriptor *desc; + uint8_t *child_data; AVFrame *dummy; int ret = 0; @@ -591,6 +640,40 @@ static int qsv_map_from(AVHWFramesContext *ctx, return AVERROR(ENOSYS); child_frames_ctx = (AVHWFramesContext*)s->child_frames_ref->data; + switch (child_frames_ctx->device_ctx->type) { +#if CONFIG_VAAPI + case AV_HWDEVICE_TYPE_VAAPI: + child_data = (uint8_t*)(intptr_t)*(VASurfaceID*)surf->Data.MemId; + break; +#endif +#if CONFIG_DXVA2 + case AV_HWDEVICE_TYPE_DXVA2: + child_data = surf->Data.MemId; + break; +#endif + default: + return AVERROR(ENOSYS); + } + + if (dst->format == child_frames_ctx->format) { + ret = ff_hwframe_map_create(s->child_frames_ref, + dst, src, NULL, NULL); + if (ret < 0) + return ret; + + dst->width = src->width; + dst->height = src->height; + dst->data[3] = child_data; + + return 0; + } + + desc = av_pix_fmt_desc_get(dst->format); + if (desc && desc->flags & AV_PIX_FMT_FLAG_HWACCEL) { + // This only supports mapping to software. + return AVERROR(ENOSYS); + } + dummy = av_frame_alloc(); if (!dummy) return AVERROR(ENOMEM); @@ -603,7 +686,7 @@ static int qsv_map_from(AVHWFramesContext *ctx, dummy->format = child_frames_ctx->format; dummy->width = src->width; dummy->height = src->height; - dummy->data[3] = surf->Data.MemId; + dummy->data[3] = child_data; ret = av_hwframe_map(dst, dummy, flags); @@ -1042,6 +1125,7 @@ const HWContextType ff_hwcontext_type_qsv = { .map_to = qsv_map_to, .map_from = qsv_map_from, .frames_derive_to = qsv_frames_derive_to, + .frames_derive_from = qsv_frames_derive_from, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, }; From c5714b51aad41fef56dddac1d542e7fc6b984627 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:40 +0000 Subject: [PATCH 0202/2557] hwcontext: Improve allocation in derived contexts Use the flags argument of av_hwframe_ctx_create_derived() to pass the mapping flags which will be used on allocation. Also, set the format and hardware context on the allocated frame automatically - the user should not be required to do this themselves. --- doc/APIchanges | 4 ++++ libavutil/hwcontext.c | 14 +++++++++++++- libavutil/hwcontext.h | 4 +++- libavutil/hwcontext_internal.h | 5 +++++ libavutil/version.h | 2 +- 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 34d788a706f8f..a251c4ca82a65 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,10 @@ libavutil: 2017-03-23 API changes, most recent first: +2017-04-30 - xxxxxxx - lavu 56.1.1 - hwcontext.h + av_hwframe_ctx_create_derived() now takes some AV_HWFRAME_MAP_* combination + as its flags argument (which was previously unused). + 2017-04-xx - xxxxxxx - lavu 56.1.0 - spherical.h Add av_spherical_projection_name() and av_spherical_from_name(). diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index a6d88421d8bb9..360b01205c286 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -455,6 +455,11 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags) // and map the frame immediately. AVFrame *src_frame; + frame->format = ctx->format; + frame->hw_frames_ctx = av_buffer_ref(hwframe_ref); + if (!frame->hw_frames_ctx) + return AVERROR(ENOMEM); + src_frame = av_frame_alloc(); if (!src_frame) return AVERROR(ENOMEM); @@ -464,7 +469,8 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags) if (ret < 0) return ret; - ret = av_hwframe_map(frame, src_frame, 0); + ret = av_hwframe_map(frame, src_frame, + ctx->internal->source_allocation_map_flags); if (ret) { av_log(ctx, AV_LOG_ERROR, "Failed to map frame into derived " "frame context: %d.\n", ret); @@ -816,6 +822,12 @@ int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, goto fail; } + dst->internal->source_allocation_map_flags = + flags & (AV_HWFRAME_MAP_READ | + AV_HWFRAME_MAP_WRITE | + AV_HWFRAME_MAP_OVERWRITE | + AV_HWFRAME_MAP_DIRECT); + ret = AVERROR(ENOSYS); if (src->internal->hw_type->frames_derive_from) ret = src->internal->hw_type->frames_derive_from(dst, src, flags); diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h index 889e30365ee13..eaf40c46f1654 100644 --- a/libavutil/hwcontext.h +++ b/libavutil/hwcontext.h @@ -564,7 +564,9 @@ int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags); * AVHWFramesContext on. * @param source_frame_ctx A reference to an existing AVHWFramesContext * which will be mapped to the derived context. - * @param flags Currently unused; should be set to zero. + * @param flags Some combination of AV_HWFRAME_MAP_* flags, defining the + * mapping parameters to apply to frames which are allocated + * in the derived device. * @return Zero on success, negative AVERROR code on failure. */ int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h index 87b32e191e9f3..7cf6cb07c7145 100644 --- a/libavutil/hwcontext_internal.h +++ b/libavutil/hwcontext_internal.h @@ -121,6 +121,11 @@ struct AVHWFramesInternal { * context it was derived from. */ AVBufferRef *source_frames; + /** + * Flags to apply to the mapping from the source to the derived + * frame context when trying to allocate in the derived context. + */ + int source_allocation_map_flags; }; typedef struct HWMapDescriptor { diff --git a/libavutil/version.h b/libavutil/version.h index fd72ff431d7fd..7779755870ae2 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -55,7 +55,7 @@ #define LIBAVUTIL_VERSION_MAJOR 56 #define LIBAVUTIL_VERSION_MINOR 1 -#define LIBAVUTIL_VERSION_MICRO 0 +#define LIBAVUTIL_VERSION_MICRO 1 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ From 38cb05f1c89cae1862b360d4e7e3f0cd2b5bbb67 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:41 +0000 Subject: [PATCH 0203/2557] vf_hwmap: Add device derivation Also refactor a little and improve error messages to make failure cases easier to understand. --- libavfilter/vf_hwmap.c | 67 ++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c index 11595bd6ca565..f19d10f2c26e7 100644 --- a/libavfilter/vf_hwmap.c +++ b/libavfilter/vf_hwmap.c @@ -30,10 +30,10 @@ typedef struct HWMapContext { const AVClass *class; - AVBufferRef *hwdevice_ref; AVBufferRef *hwframes_ref; int mode; + char *derive_device_type; int map_backwards; } HWMapContext; @@ -52,6 +52,7 @@ static int hwmap_config_output(AVFilterLink *outlink) HWMapContext *ctx = avctx->priv; AVFilterLink *inlink = avctx->inputs[0]; AVHWFramesContext *hwfc; + AVBufferRef *device; const AVPixFmtDescriptor *desc; int err; @@ -59,30 +60,58 @@ static int hwmap_config_output(AVFilterLink *outlink) av_get_pix_fmt_name(inlink->format), av_get_pix_fmt_name(outlink->format)); + av_buffer_unref(&ctx->hwframes_ref); + + device = avctx->hw_device_ctx; + if (inlink->hw_frames_ctx) { hwfc = (AVHWFramesContext*)inlink->hw_frames_ctx->data; + if (ctx->derive_device_type) { + enum AVHWDeviceType type; + + type = av_hwdevice_find_type_by_name(ctx->derive_device_type); + if (type == AV_HWDEVICE_TYPE_NONE) { + av_log(avctx, AV_LOG_ERROR, "Invalid device type.\n"); + goto fail; + } + + err = av_hwdevice_ctx_create_derived(&device, type, + hwfc->device_ref, 0); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to created derived " + "device context: %d.\n", err); + goto fail; + } + } + desc = av_pix_fmt_desc_get(outlink->format); - if (!desc) - return AVERROR(EINVAL); + if (!desc) { + err = AVERROR(EINVAL); + goto fail; + } if (inlink->format == hwfc->format && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { // Map between two hardware formats (including the case of // undoing an existing mapping). - ctx->hwdevice_ref = av_buffer_ref(avctx->hw_device_ctx); - if (!ctx->hwdevice_ref) { - err = AVERROR(ENOMEM); + if (!device) { + av_log(avctx, AV_LOG_ERROR, "A device reference is " + "required to map to a hardware format.\n"); + err = AVERROR(EINVAL); goto fail; } err = av_hwframe_ctx_create_derived(&ctx->hwframes_ref, outlink->format, - ctx->hwdevice_ref, + device, inlink->hw_frames_ctx, 0); - if (err < 0) + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to create derived " + "frames context: %d.\n", err); goto fail; + } } else if ((outlink->format == hwfc->format && inlink->format == hwfc->sw_format) || @@ -90,8 +119,6 @@ static int hwmap_config_output(AVFilterLink *outlink) // Map from a hardware format to a software format, or // undo an existing such mapping. - ctx->hwdevice_ref = NULL; - ctx->hwframes_ref = av_buffer_ref(inlink->hw_frames_ctx); if (!ctx->hwframes_ref) { err = AVERROR(ENOMEM); @@ -115,15 +142,17 @@ static int hwmap_config_output(AVFilterLink *outlink) // returns frames mapped from that to the previous link in // order to fill them without an additional copy. - ctx->map_backwards = 1; - - ctx->hwdevice_ref = av_buffer_ref(avctx->hw_device_ctx); - if (!ctx->hwdevice_ref) { - err = AVERROR(ENOMEM); + if (!device) { + av_log(avctx, AV_LOG_ERROR, "A device reference is " + "required to create new frames with backwards " + "mapping.\n"); + err = AVERROR(EINVAL); goto fail; } - ctx->hwframes_ref = av_hwframe_ctx_alloc(ctx->hwdevice_ref); + ctx->map_backwards = 1; + + ctx->hwframes_ref = av_hwframe_ctx_alloc(device); if (!ctx->hwframes_ref) { err = AVERROR(ENOMEM); goto fail; @@ -161,7 +190,6 @@ static int hwmap_config_output(AVFilterLink *outlink) fail: av_buffer_unref(&ctx->hwframes_ref); - av_buffer_unref(&ctx->hwdevice_ref); return err; } @@ -269,7 +297,6 @@ static av_cold void hwmap_uninit(AVFilterContext *avctx) HWMapContext *ctx = avctx->priv; av_buffer_unref(&ctx->hwframes_ref); - av_buffer_unref(&ctx->hwdevice_ref); } #define OFFSET(x) offsetof(HWMapContext, x) @@ -293,6 +320,10 @@ static const AVOption hwmap_options[] = { 0, AV_OPT_TYPE_CONST, { .i64 = AV_HWFRAME_MAP_DIRECT }, INT_MIN, INT_MAX, FLAGS, "mode" }, + { "derive_device", "Derive a new device of this type", + OFFSET(derive_device_type), AV_OPT_TYPE_STRING, + { .str = NULL }, 0, 0, FLAGS }, + { NULL }, }; From 81a4cb8e58636d4efd200c2b4fec786a7e948d8b Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:42 +0000 Subject: [PATCH 0204/2557] vf_hwmap: Add reverse mapping for hardware frames This is something of a hack. It allocates a new hwframe context for the target format, then maps it back to the source link and overwrites the input link hw_frames_ctx so that the previous filter will receive the frames we want from ff_get_video_buffer(). It may fail if the previous filter imposes any additional constraints on the frames it wants to use as output. --- libavfilter/vf_hwmap.c | 68 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c index f19d10f2c26e7..2983528ea05da 100644 --- a/libavfilter/vf_hwmap.c +++ b/libavfilter/vf_hwmap.c @@ -34,7 +34,7 @@ typedef struct HWMapContext { int mode; char *derive_device_type; - int map_backwards; + int reverse; } HWMapContext; static int hwmap_query_formats(AVFilterContext *avctx) @@ -92,7 +92,8 @@ static int hwmap_config_output(AVFilterLink *outlink) } if (inlink->format == hwfc->format && - (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { + (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) && + !ctx->reverse) { // Map between two hardware formats (including the case of // undoing an existing mapping). @@ -113,6 +114,56 @@ static int hwmap_config_output(AVFilterLink *outlink) goto fail; } + } else if (inlink->format == hwfc->format && + (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) && + ctx->reverse) { + // Map between two hardware formats, but do it in reverse. + // Make a new hwframe context for the target type, and then + // overwrite the input hwframe context with a derived context + // mapped from that back to the source type. + AVBufferRef *source; + AVHWFramesContext *frames; + + ctx->hwframes_ref = av_hwframe_ctx_alloc(device); + if (!ctx->hwframes_ref) { + err = AVERROR(ENOMEM); + goto fail; + } + frames = (AVHWFramesContext*)ctx->hwframes_ref->data; + + frames->format = outlink->format; + frames->sw_format = hwfc->sw_format; + frames->width = hwfc->width; + frames->height = hwfc->height; + frames->initial_pool_size = 64; + + err = av_hwframe_ctx_init(ctx->hwframes_ref); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to initialise " + "target frames context: %d.\n", err); + goto fail; + } + + err = av_hwframe_ctx_create_derived(&source, + inlink->format, + hwfc->device_ref, + ctx->hwframes_ref, + ctx->mode); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to create " + "derived source frames context: %d.\n", err); + goto fail; + } + + // Here is the naughty bit. This overwriting changes what + // ff_get_video_buffer() in the previous filter returns - + // it will now give a frame allocated here mapped back to + // the format it expects. If there were any additional + // constraints on the output frames there then this may + // break nastily. + av_buffer_unref(&inlink->hw_frames_ctx); + inlink->hw_frames_ctx = source; + } else if ((outlink->format == hwfc->format && inlink->format == hwfc->sw_format) || inlink->format == hwfc->format) { @@ -144,13 +195,13 @@ static int hwmap_config_output(AVFilterLink *outlink) if (!device) { av_log(avctx, AV_LOG_ERROR, "A device reference is " - "required to create new frames with backwards " + "required to create new frames with reverse " "mapping.\n"); err = AVERROR(EINVAL); goto fail; } - ctx->map_backwards = 1; + ctx->reverse = 1; ctx->hwframes_ref = av_hwframe_ctx_alloc(device); if (!ctx->hwframes_ref) { @@ -167,7 +218,7 @@ static int hwmap_config_output(AVFilterLink *outlink) err = av_hwframe_ctx_init(ctx->hwframes_ref); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to create frame " - "context for backward mapping: %d.\n", err); + "context for reverse mapping: %d.\n", err); goto fail; } @@ -199,7 +250,7 @@ static AVFrame *hwmap_get_buffer(AVFilterLink *inlink, int w, int h) AVFilterLink *outlink = avctx->outputs[0]; HWMapContext *ctx = avctx->priv; - if (ctx->map_backwards) { + if (ctx->reverse && !inlink->hw_frames_ctx) { AVFrame *src, *dst; int err; @@ -257,7 +308,7 @@ static int hwmap_filter_frame(AVFilterLink *link, AVFrame *input) goto fail; } - if (ctx->map_backwards && !input->hw_frames_ctx) { + if (ctx->reverse && !input->hw_frames_ctx) { // If we mapped backwards from hardware to software, we need // to attach the hardware frame context to the input frame to // make the mapping visible to av_hwframe_map(). @@ -323,6 +374,9 @@ static const AVOption hwmap_options[] = { { "derive_device", "Derive a new device of this type", OFFSET(derive_device_type), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS }, + { "reverse", "Map in reverse (create and allocate in the sink)", + OFFSET(reverse), AV_OPT_TYPE_INT, + { .i64 = 0 }, 0, 1, FLAGS }, { NULL }, }; From edbf0fffb15dde7a1de70b05855529d5fc769f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= Date: Mon, 1 May 2017 20:16:02 +0200 Subject: [PATCH 0205/2557] hevc: Add NEON add_residual for bitdepth 10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/arm/hevc_idct.S | 89 +++++++++++++++++++++++++++++++ libavcodec/arm/hevcdsp_init_arm.c | 13 +++++ 2 files changed, 102 insertions(+) diff --git a/libavcodec/arm/hevc_idct.S b/libavcodec/arm/hevc_idct.S index b3ce00b7fdd7e..fac575818ba96 100644 --- a/libavcodec/arm/hevc_idct.S +++ b/libavcodec/arm/hevc_idct.S @@ -30,6 +30,13 @@ const trans, align=4 .short 57, 43, 25, 9 endconst +.macro clip10 in1, in2, c1, c2 + vmax.s16 \in1, \in1, \c1 + vmax.s16 \in2, \in2, \c1 + vmin.s16 \in1, \in1, \c2 + vmin.s16 \in2, \in2, \c2 +.endm + function ff_hevc_add_residual_4x4_8_neon, export=1 vld1.16 {q0-q1}, [r1, :128] vld1.32 d4[0], [r0, :32], r2 @@ -50,6 +57,25 @@ function ff_hevc_add_residual_4x4_8_neon, export=1 bx lr endfunc +function ff_hevc_add_residual_4x4_10_neon, export=1 + mov r12, r0 + vld1.16 {q0-q1}, [r1, :128] + vld1.16 d4, [r12, :64], r2 + vld1.16 d5, [r12, :64], r2 + vld1.16 d6, [r12, :64], r2 + vqadd.s16 q0, q2 + vld1.16 d7, [r12, :64], r2 + vmov.s16 q12, #0 + vqadd.s16 q1, q3 + vmvn.s16 q13, #0xFC00 @ vmov.s16 #0x3FF + clip10 q0, q1, q12, q13 + vst1.16 d0, [r0, :64], r2 + vst1.16 d1, [r0, :64], r2 + vst1.16 d2, [r0, :64], r2 + vst1.16 d3, [r0, :64], r2 + bx lr +endfunc + function ff_hevc_add_residual_8x8_8_neon, export=1 add r12, r0, r2 add r2, r2, r2 @@ -70,6 +96,25 @@ function ff_hevc_add_residual_8x8_8_neon, export=1 bx lr endfunc +function ff_hevc_add_residual_8x8_10_neon, export=1 + add r12, r0, r2 + add r2, r2, r2 + mov r3, #8 + vmov.s16 q12, #0 + vmvn.s16 q13, #0xFC00 @ vmov.s16 #0x3FF +1: subs r3, #2 + vld1.16 {q0-q1}, [r1, :128]! + vld1.16 {q8}, [r0, :128] + vqadd.s16 q0, q8 + vld1.16 {q9}, [r12, :128] + vqadd.s16 q1, q9 + clip10 q0, q1, q12, q13 + vst1.16 {q0}, [r0, :128], r2 + vst1.16 {q1}, [r12, :128], r2 + bne 1b + bx lr +endfunc + function ff_hevc_add_residual_16x16_8_neon, export=1 mov r3, #16 add r12, r0, r2 @@ -97,6 +142,29 @@ function ff_hevc_add_residual_16x16_8_neon, export=1 bx lr endfunc +function ff_hevc_add_residual_16x16_10_neon, export=1 + mov r3, #16 + vmov.s16 q12, #0 + vmvn.s16 q13, #0xFC00 @ vmov.s16 #0x3FF + add r12, r0, r2 + add r2, r2, r2 +1: subs r3, #2 + vld1.16 {q8-q9}, [r0, :128] + vld1.16 {q0, q1}, [r1, :128]! + vqadd.s16 q0, q8 + vld1.16 {q10-q11}, [r12, :128] + vqadd.s16 q1, q9 + vld1.16 {q2, q3}, [r1, :128]! + vqadd.s16 q2, q10 + vqadd.s16 q3, q11 + clip10 q0, q1, q12, q13 + clip10 q2, q3, q12, q13 + vst1.16 {q0-q1}, [r0, :128], r2 + vst1.16 {q2-q3}, [r12, :128], r2 + bne 1b + bx lr +endfunc + function ff_hevc_add_residual_32x32_8_neon, export=1 vpush {q4-q7} add r12, r0, r2 @@ -137,6 +205,27 @@ function ff_hevc_add_residual_32x32_8_neon, export=1 bx lr endfunc +function ff_hevc_add_residual_32x32_10_neon, export=1 + mov r3, #32 + add r12, r0, #32 + vmov.s16 q12, #0 + vmvn.s16 q13, #0xFC00 @ vmov.s16 #0x3FF +1: subs r3, #1 + vldm r1!, {q0-q3} + vld1.16 {q8, q9}, [r0, :128] + vld1.16 {q10, q11}, [r12, :128] + vqadd.s16 q0, q8 + vqadd.s16 q1, q9 + vqadd.s16 q2, q10 + vqadd.s16 q3, q11 + clip10 q0, q1, q12, q13 + clip10 q2, q3, q12, q13 + vst1.16 {q0-q1}, [r0, :128], r2 + vst1.16 {q2-q3}, [r12, :128], r2 + bne 1b + bx lr +endfunc + .macro idct_4x4_dc bitdepth function ff_hevc_idct_4x4_dc_\bitdepth\()_neon, export=1 ldrsh r1, [r0] diff --git a/libavcodec/arm/hevcdsp_init_arm.c b/libavcodec/arm/hevcdsp_init_arm.c index 817c1572108ad..e3d4e4eb756f2 100644 --- a/libavcodec/arm/hevcdsp_init_arm.c +++ b/libavcodec/arm/hevcdsp_init_arm.c @@ -28,12 +28,20 @@ void ff_hevc_add_residual_4x4_8_neon(uint8_t *_dst, int16_t *coeffs, ptrdiff_t stride); +void ff_hevc_add_residual_4x4_10_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); void ff_hevc_add_residual_8x8_8_neon(uint8_t *_dst, int16_t *coeffs, ptrdiff_t stride); +void ff_hevc_add_residual_8x8_10_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); void ff_hevc_add_residual_16x16_8_neon(uint8_t *_dst, int16_t *coeffs, ptrdiff_t stride); +void ff_hevc_add_residual_16x16_10_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); void ff_hevc_add_residual_32x32_8_neon(uint8_t *_dst, int16_t *coeffs, ptrdiff_t stride); +void ff_hevc_add_residual_32x32_10_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); void ff_hevc_idct_4x4_dc_8_neon(int16_t *coeffs); void ff_hevc_idct_8x8_dc_8_neon(int16_t *coeffs); @@ -72,6 +80,11 @@ av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, int bit_depth) c->idct[2] = ff_hevc_idct_16x16_8_neon; } if (bit_depth == 10) { + c->add_residual[0] = ff_hevc_add_residual_4x4_10_neon; + c->add_residual[1] = ff_hevc_add_residual_8x8_10_neon; + c->add_residual[2] = ff_hevc_add_residual_16x16_10_neon; + c->add_residual[3] = ff_hevc_add_residual_32x32_10_neon; + c->idct_dc[0] = ff_hevc_idct_4x4_dc_10_neon; c->idct_dc[1] = ff_hevc_idct_8x8_dc_10_neon; c->idct_dc[2] = ff_hevc_idct_16x16_dc_10_neon; From 73fc82f3434d9b68f0948700c4fd8f5056ae5afe Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sat, 29 Apr 2017 00:34:11 +0000 Subject: [PATCH 0206/2557] vlc: Add header #include when the types are used Do not rely on indirectly including it from bitstream.h. Signed-off-by: Diego Biurrun --- libavcodec/4xm.c | 1 + libavcodec/atrac3.c | 1 + libavcodec/atrac3plus.c | 1 + libavcodec/bink.c | 1 + libavcodec/cfhd.h | 1 + libavcodec/clearvideo.c | 1 + libavcodec/cook.c | 1 + libavcodec/faxcompr.c | 1 + libavcodec/g2meet.c | 1 + libavcodec/hqx.h | 1 + libavcodec/imc.c | 1 + libavcodec/indeo2.c | 1 + libavcodec/indeo4.c | 1 + libavcodec/indeo5.c | 1 + libavcodec/ivi.h | 1 + libavcodec/mimic.c | 1 + libavcodec/mlpdec.c | 1 + libavcodec/motionpixels.c | 1 + libavcodec/mpc7.c | 1 + libavcodec/mpc8.c | 1 + libavcodec/qdm2.c | 1 + libavcodec/smacker.c | 1 + libavcodec/truemotion2.c | 1 + libavcodec/tscc2.c | 1 + libavcodec/utvideodec.c | 1 + libavcodec/vorbisdec.c | 1 + libavcodec/wma.h | 1 + libavcodec/wmavoice.c | 1 + libavcodec/wnv1.c | 1 + 29 files changed, 29 insertions(+) diff --git a/libavcodec/4xm.c b/libavcodec/4xm.c index b419bfa268f10..4a9a14a79b954 100644 --- a/libavcodec/4xm.c +++ b/libavcodec/4xm.c @@ -36,6 +36,7 @@ #include "bswapdsp.h" #include "bytestream.h" #include "internal.h" +#include "vlc.h" #define BLOCK_TYPE_VLC_BITS 5 #define ACDC_VLC_BITS 9 diff --git a/libavcodec/atrac3.c b/libavcodec/atrac3.c index 2a703ca46ef0d..d0661c83fcdb0 100644 --- a/libavcodec/atrac3.c +++ b/libavcodec/atrac3.c @@ -44,6 +44,7 @@ #include "bytestream.h" #include "fft.h" #include "internal.h" +#include "vlc.h" #include "atrac.h" #include "atrac3data.h" diff --git a/libavcodec/atrac3plus.c b/libavcodec/atrac3plus.c index e3c2504178ac2..9b7b28bb9b0d5 100644 --- a/libavcodec/atrac3plus.c +++ b/libavcodec/atrac3plus.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "bitstream.h" +#include "vlc.h" #include "atrac3plus.h" #include "atrac3plus_data.h" diff --git a/libavcodec/bink.c b/libavcodec/bink.c index 84388b86aa7fc..011d2d8e2282c 100644 --- a/libavcodec/bink.c +++ b/libavcodec/bink.c @@ -33,6 +33,7 @@ #include "hpeldsp.h" #include "internal.h" #include "mathops.h" +#include "vlc.h" #define BINK_FLAG_ALPHA 0x00100000 #define BINK_FLAG_GRAY 0x00020000 diff --git a/libavcodec/cfhd.h b/libavcodec/cfhd.h index c5da0b6ec7ff3..27f047d3e8f71 100644 --- a/libavcodec/cfhd.h +++ b/libavcodec/cfhd.h @@ -25,6 +25,7 @@ #include "avcodec.h" #include "bitstream.h" +#include "vlc.h" #define VLC_BITS 9 #define SUBBAND_COUNT 10 diff --git a/libavcodec/clearvideo.c b/libavcodec/clearvideo.c index 08bf2cb6dae0a..7c5143937fcb9 100644 --- a/libavcodec/clearvideo.c +++ b/libavcodec/clearvideo.c @@ -29,6 +29,7 @@ #include "bytestream.h" #include "idctdsp.h" #include "internal.h" +#include "vlc.h" #define NUM_DC_CODES 127 #define NUM_AC_CODES 103 diff --git a/libavcodec/cook.c b/libavcodec/cook.c index c3304eae2e3dc..bd8ad1d1da62f 100644 --- a/libavcodec/cook.c +++ b/libavcodec/cook.c @@ -52,6 +52,7 @@ #include "fft.h" #include "internal.h" #include "sinewin.h" +#include "vlc.h" #include "cookdata.h" diff --git a/libavcodec/faxcompr.c b/libavcodec/faxcompr.c index 9eb4e379999c0..0a079fc9925e3 100644 --- a/libavcodec/faxcompr.c +++ b/libavcodec/faxcompr.c @@ -27,6 +27,7 @@ #include "avcodec.h" #include "bitstream.h" #include "put_bits.h" +#include "vlc.h" #include "faxcompr.h" #define CCITT_SYMS 104 diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index d7dc97615360f..93befb48093df 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -39,6 +39,7 @@ #include "internal.h" #include "jpegtables.h" #include "mjpeg.h" +#include "vlc.h" #define EPIC_PIX_STACK_SIZE 1024 #define EPIC_PIX_STACK_MAX (EPIC_PIX_STACK_SIZE - 1) diff --git a/libavcodec/hqx.h b/libavcodec/hqx.h index e8f7c627fb70a..f35721a06cd30 100644 --- a/libavcodec/hqx.h +++ b/libavcodec/hqx.h @@ -28,6 +28,7 @@ #include "bitstream.h" #include "hqxdsp.h" +#include "vlc.h" enum HQXACMode { HQX_AC_Q0 = 0, diff --git a/libavcodec/imc.c b/libavcodec/imc.c index 145b2d56fc865..100e6f89412d7 100644 --- a/libavcodec/imc.c +++ b/libavcodec/imc.c @@ -44,6 +44,7 @@ #include "fft.h" #include "internal.h" #include "sinewin.h" +#include "vlc.h" #include "imcdata.h" diff --git a/libavcodec/indeo2.c b/libavcodec/indeo2.c index 811056dbfc365..64e92d760f930 100644 --- a/libavcodec/indeo2.c +++ b/libavcodec/indeo2.c @@ -32,6 +32,7 @@ #include "indeo2data.h" #include "internal.h" #include "mathops.h" +#include "vlc.h" typedef struct Ir2Context{ AVCodecContext *avctx; diff --git a/libavcodec/indeo4.c b/libavcodec/indeo4.c index 4b3f903e3b67e..37b5da85081df 100644 --- a/libavcodec/indeo4.c +++ b/libavcodec/indeo4.c @@ -34,6 +34,7 @@ #include "internal.h" #include "ivi.h" #include "ivi_dsp.h" +#include "vlc.h" #define IVI4_PIC_SIZE_ESC 7 diff --git a/libavcodec/indeo5.c b/libavcodec/indeo5.c index 70ae1d324b506..38907eb056b3e 100644 --- a/libavcodec/indeo5.c +++ b/libavcodec/indeo5.c @@ -33,6 +33,7 @@ #include "ivi.h" #include "ivi_dsp.h" #include "indeo5data.h" +#include "vlc.h" /** * Indeo5 frame types. diff --git a/libavcodec/ivi.h b/libavcodec/ivi.h index bbc88423409c3..6fde8a671aaad 100644 --- a/libavcodec/ivi.h +++ b/libavcodec/ivi.h @@ -33,6 +33,7 @@ #include "avcodec.h" #include "bitstream.h" +#include "vlc.h" /** * Indeo 4 frame types. diff --git a/libavcodec/mimic.c b/libavcodec/mimic.c index 31d07ecd5024a..da8289e4111cf 100644 --- a/libavcodec/mimic.c +++ b/libavcodec/mimic.c @@ -32,6 +32,7 @@ #include "hpeldsp.h" #include "idctdsp.h" #include "thread.h" +#include "vlc.h" #define MIMIC_HEADER_SIZE 20 diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 4f6675a3cad06..b377fd7e2b1ad 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -39,6 +39,7 @@ #include "mlpdsp.h" #include "mlp.h" #include "config.h" +#include "vlc.h" /** number of bits used for VLC lookup - longest Huffman code is 9 */ #if ARCH_ARM diff --git a/libavcodec/motionpixels.c b/libavcodec/motionpixels.c index da4c141db6d7e..66ec5f50097e3 100644 --- a/libavcodec/motionpixels.c +++ b/libavcodec/motionpixels.c @@ -23,6 +23,7 @@ #include "bitstream.h" #include "bswapdsp.h" #include "internal.h" +#include "vlc.h" #define MAX_HUFF_CODES 16 diff --git a/libavcodec/mpc7.c b/libavcodec/mpc7.c index 66a6162ec5d5f..ebc3f5293b2fb 100644 --- a/libavcodec/mpc7.c +++ b/libavcodec/mpc7.c @@ -33,6 +33,7 @@ #include "bitstream.h" #include "internal.h" #include "mpegaudiodsp.h" +#include "vlc.h" #include "mpc.h" #include "mpc7data.h" diff --git a/libavcodec/mpc8.c b/libavcodec/mpc8.c index f55fd5782400b..649eb02e2efc5 100644 --- a/libavcodec/mpc8.c +++ b/libavcodec/mpc8.c @@ -32,6 +32,7 @@ #include "bitstream.h" #include "internal.h" #include "mpegaudiodsp.h" +#include "vlc.h" #include "mpc.h" #include "mpc8data.h" diff --git a/libavcodec/qdm2.c b/libavcodec/qdm2.c index 00c952d51a279..668e513a661fb 100644 --- a/libavcodec/qdm2.c +++ b/libavcodec/qdm2.c @@ -44,6 +44,7 @@ #include "mpegaudio.h" #include "mpegaudiodsp.h" #include "rdft.h" +#include "vlc.h" #include "qdm2data.h" #include "qdm2_tablegen.h" diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index 2abf7c1c5af4f..c4b4bc735d2ea 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -39,6 +39,7 @@ #include "bytestream.h" #include "internal.h" #include "mathops.h" +#include "vlc.h" #define SMKTREE_BITS 9 #define SMK_NODE 0x80000000 diff --git a/libavcodec/truemotion2.c b/libavcodec/truemotion2.c index 333451cb7c91c..cc3b0b76e0149 100644 --- a/libavcodec/truemotion2.c +++ b/libavcodec/truemotion2.c @@ -31,6 +31,7 @@ #include "bswapdsp.h" #include "bytestream.h" #include "internal.h" +#include "vlc.h" #define TM2_ESCAPE 0x80000000 #define TM2_DELTAS 64 diff --git a/libavcodec/tscc2.c b/libavcodec/tscc2.c index 6081c72c301c8..28d6464258354 100644 --- a/libavcodec/tscc2.c +++ b/libavcodec/tscc2.c @@ -33,6 +33,7 @@ #include "internal.h" #include "mathops.h" #include "tscc2data.h" +#include "vlc.h" typedef struct TSCC2Context { AVCodecContext *avctx; diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index ed6368e4cd821..26b991ca7b56d 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -36,6 +36,7 @@ #include "internal.h" #include "thread.h" #include "utvideo.h" +#include "vlc.h" static int build_huff10(const uint8_t *src, VLC *vlc, int *fsym) { diff --git a/libavcodec/vorbisdec.c b/libavcodec/vorbisdec.c index 9289c82cf449a..cc0f6f4a3ec0d 100644 --- a/libavcodec/vorbisdec.c +++ b/libavcodec/vorbisdec.c @@ -32,6 +32,7 @@ #include "fft.h" #include "get_bits.h" #include "internal.h" +#include "vlc.h" #include "vorbis.h" #include "vorbisdsp.h" #include "xiph.h" diff --git a/libavcodec/wma.h b/libavcodec/wma.h index 6d14fc66c6d3b..80b82867a5641 100644 --- a/libavcodec/wma.h +++ b/libavcodec/wma.h @@ -28,6 +28,7 @@ #include "bitstream.h" #include "fft.h" #include "put_bits.h" +#include "vlc.h" /* size of blocks */ #define BLOCK_MIN_BITS 7 diff --git a/libavcodec/wmavoice.c b/libavcodec/wmavoice.c index cf9884108c115..8c7ec7b3d6e46 100644 --- a/libavcodec/wmavoice.c +++ b/libavcodec/wmavoice.c @@ -43,6 +43,7 @@ #include "dct.h" #include "rdft.h" #include "sinewin.h" +#include "vlc.h" #define MAX_BLOCKS 8 ///< maximum number of blocks per frame #define MAX_LSPS 16 ///< maximum filter order diff --git a/libavcodec/wnv1.c b/libavcodec/wnv1.c index e973f7ecc5314..f498c20b47fc5 100644 --- a/libavcodec/wnv1.c +++ b/libavcodec/wnv1.c @@ -28,6 +28,7 @@ #include "bitstream.h" #include "internal.h" #include "mathops.h" +#include "vlc.h" typedef struct WNV1Context { From 0ac1fec1c3dacedabbf3dd4122ef4bf8523e688c Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sat, 29 Apr 2017 00:34:12 +0000 Subject: [PATCH 0207/2557] bitstream: Move VLC reading functions into the vlc.h header This makes the bitstream.h header leaner. Signed-off-by: Diego Biurrun --- libavcodec/bitstream.h | 73 ----------------------------------------- libavcodec/vlc.h | 74 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 73 deletions(-) diff --git a/libavcodec/bitstream.h b/libavcodec/bitstream.h index 894a13e348e30..d6dd2b94118f5 100644 --- a/libavcodec/bitstream.h +++ b/libavcodec/bitstream.h @@ -33,7 +33,6 @@ #include "libavutil/log.h" #include "mathops.h" -#include "vlc.h" typedef struct BitstreamContext { uint64_t bits; // stores bits read from the buffer @@ -287,78 +286,6 @@ static inline int bitstream_read_xbits(BitstreamContext *bc, unsigned length) return ((((uint32_t)(sign ^ cache)) >> (32 - length)) ^ sign) - sign; } -/* Return the LUT element for the given bitstream configuration. */ -static inline int set_idx(BitstreamContext *bc, int code, int *n, int *nb_bits, - VLC_TYPE (*table)[2]) -{ - unsigned idx; - - *nb_bits = -*n; - idx = bitstream_peek(bc, *nb_bits) + code; - *n = table[idx][1]; - - return table[idx][0]; -} - -/** - * Parse a VLC code. - * @param bits is the number of bits which will be read at once, must be - * identical to nb_bits in init_vlc() - * @param max_depth is the number of times bits bits must be read to completely - * read the longest VLC code - * = (max_vlc_length + bits - 1) / bits - * If the VLC code is invalid and max_depth = 1, then no bits will be removed. - * If the VLC code is invalid and max_depth > 1, then the number of bits removed - * is undefined. */ -static inline int bitstream_read_vlc(BitstreamContext *bc, VLC_TYPE (*table)[2], - int bits, int max_depth) -{ - int nb_bits; - unsigned idx = bitstream_peek(bc, bits); - int code = table[idx][0]; - int n = table[idx][1]; - - if (max_depth > 1 && n < 0) { - skip_remaining(bc, bits); - code = set_idx(bc, code, &n, &nb_bits, table); - if (max_depth > 2 && n < 0) { - skip_remaining(bc, nb_bits); - code = set_idx(bc, code, &n, &nb_bits, table); - } - } - skip_remaining(bc, n); - - return code; -} - -#define BITSTREAM_RL_VLC(level, run, bc, table, bits, max_depth) \ - do { \ - int n, nb_bits; \ - unsigned index = bitstream_peek(bc, bits); \ - level = table[index].level; \ - n = table[index].len; \ - \ - if (max_depth > 1 && n < 0) { \ - bitstream_skip(bc, bits); \ - \ - nb_bits = -n; \ - \ - index = bitstream_peek(bc, nb_bits) + level; \ - level = table[index].level; \ - n = table[index].len; \ - if (max_depth > 2 && n < 0) { \ - bitstream_skip(bc, nb_bits); \ - nb_bits = -n; \ - \ - index = bitstream_peek(bc, nb_bits) + level; \ - level = table[index].level; \ - n = table[index].len; \ - } \ - } \ - run = table[index].run; \ - bitstream_skip(bc, n); \ - } while (0) - /* Return decoded truncated unary code for the values 0, 1, 2. */ static inline int bitstream_decode012(BitstreamContext *bc) { diff --git a/libavcodec/vlc.h b/libavcodec/vlc.h index 4ade824391d97..8ac52381b936f 100644 --- a/libavcodec/vlc.h +++ b/libavcodec/vlc.h @@ -21,6 +21,8 @@ #include +#include "bitstream.h" + #define VLC_TYPE int16_t typedef struct VLC { @@ -62,4 +64,76 @@ void ff_free_vlc(VLC *vlc); init_vlc(vlc, bits, a, b, c, d, e, f, g, INIT_VLC_USE_NEW_STATIC); \ } while (0) +/* Return the LUT element for the given bitstream configuration. */ +static inline int set_idx(BitstreamContext *bc, int code, int *n, int *nb_bits, + VLC_TYPE (*table)[2]) +{ + unsigned idx; + + *nb_bits = -*n; + idx = bitstream_peek(bc, *nb_bits) + code; + *n = table[idx][1]; + + return table[idx][0]; +} + +/** + * Parse a VLC code. + * @param bits is the number of bits which will be read at once, must be + * identical to nb_bits in init_vlc() + * @param max_depth is the number of times bits bits must be read to completely + * read the longest VLC code + * = (max_vlc_length + bits - 1) / bits + * If the VLC code is invalid and max_depth = 1, then no bits will be removed. + * If the VLC code is invalid and max_depth > 1, then the number of bits removed + * is undefined. */ +static inline int bitstream_read_vlc(BitstreamContext *bc, VLC_TYPE (*table)[2], + int bits, int max_depth) +{ + int nb_bits; + unsigned idx = bitstream_peek(bc, bits); + int code = table[idx][0]; + int n = table[idx][1]; + + if (max_depth > 1 && n < 0) { + skip_remaining(bc, bits); + code = set_idx(bc, code, &n, &nb_bits, table); + if (max_depth > 2 && n < 0) { + skip_remaining(bc, nb_bits); + code = set_idx(bc, code, &n, &nb_bits, table); + } + } + skip_remaining(bc, n); + + return code; +} + +#define BITSTREAM_RL_VLC(level, run, bc, table, bits, max_depth) \ + do { \ + int n, nb_bits; \ + unsigned index = bitstream_peek(bc, bits); \ + level = table[index].level; \ + n = table[index].len; \ + \ + if (max_depth > 1 && n < 0) { \ + bitstream_skip(bc, bits); \ + \ + nb_bits = -n; \ + \ + index = bitstream_peek(bc, nb_bits) + level; \ + level = table[index].level; \ + n = table[index].len; \ + if (max_depth > 2 && n < 0) { \ + bitstream_skip(bc, nb_bits); \ + nb_bits = -n; \ + \ + index = bitstream_peek(bc, nb_bits) + level; \ + level = table[index].level; \ + n = table[index].len; \ + } \ + } \ + run = table[index].run; \ + bitstream_skip(bc, n); \ + } while (0) + #endif /* AVCODEC_VLC_H */ From b5f19f7478492307e4b4763aeac3180faf50e17f Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 26 Apr 2017 18:57:54 +0200 Subject: [PATCH 0208/2557] aac: Split function to parse ADTS header data into public and private part This makes the currently semi-public avpriv_aac_parse_header() function private to libavcodec and adds a proper public API function to return the parts of the ADTS header required in libavformat. --- configure | 8 +++- doc/developer.texi | 2 +- libavcodec/Makefile | 11 +++--- libavcodec/aac_adtstoasc_bsf.c | 13 ++++--- libavcodec/aac_parser.c | 10 +++-- libavcodec/aacdec.c | 4 +- libavcodec/{aacadtsdec.c => adts_header.c} | 7 ++-- libavcodec/{aacadtsdec.h => adts_header.h} | 12 ++---- libavcodec/adts_parser.c | 44 ++++++++++++++++++++++ libavcodec/adts_parser.h | 37 ++++++++++++++++++ libavformat/spdifdec.c | 24 +++++++----- libavformat/spdifenc.c | 17 ++++----- 12 files changed, 139 insertions(+), 50 deletions(-) rename libavcodec/{aacadtsdec.c => adts_header.c} (93%) rename libavcodec/{aacadtsdec.h => adts_header.h} (86%) create mode 100644 libavcodec/adts_parser.c create mode 100644 libavcodec/adts_parser.h diff --git a/configure b/configure index c7d03636189cb..6f696c9ab5edb 100755 --- a/configure +++ b/configure @@ -1728,6 +1728,7 @@ HAVE_LIST=" CONFIG_EXTRA=" aandcttables ac3dsp + adts_header audio_frame_queue audiodsp blockdsp @@ -1966,7 +1967,7 @@ mpegvideoenc_select="me_cmp mpegvideo pixblockdsp qpeldsp" vc1dsp_select="h264chroma qpeldsp startcode" # decoders / encoders -aac_decoder_select="imdct15 mdct sinewin" +aac_decoder_select="adts_header imdct15 mdct sinewin" aac_encoder_select="audio_frame_queue iirfilter mdct sinewin" aac_latm_decoder_select="aac_decoder aac_latm_parser" ac3_decoder_select="ac3_parser ac3dsp bswapdsp fmtconvert mdct" @@ -2280,6 +2281,7 @@ nvenc_h264_encoder_select="h264_nvenc_encoder" nvenc_hevc_encoder_select="hevc_nvenc_encoder" # parsers +aac_parser_select="adts_header" h264_parser_select="golomb h264dsp h264parse" hevc_parser_select="hevc_ps" mpegaudio_parser_select="mpegaudioheader" @@ -2288,6 +2290,7 @@ mpeg4video_parser_select="error_resilience h263dsp mpegvideo qpeldsp" vc1_parser_select="vc1dsp" # bitstream_filters +aac_adtstoasc_bsf_select="adts_header" mjpeg2jpeg_bsf_select="jpegtables" # external libraries @@ -2396,7 +2399,8 @@ sap_demuxer_select="sdp_demuxer" sap_muxer_select="rtp_muxer rtp_protocol rtpenc_chain" sdp_demuxer_select="rtpdec" smoothstreaming_muxer_select="ismv_muxer" -spdif_muxer_select="aac_parser" +spdif_demuxer_select="adts_header" +spdif_muxer_select="adts_header" spx_muxer_select="ogg_muxer" swf_demuxer_suggest="zlib" tak_demuxer_select="tak_parser" diff --git a/doc/developer.texi b/doc/developer.texi index 31c2bafbe4b65..824fba459180b 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -218,7 +218,7 @@ e.g. @samp{ff_w64_demuxer}. @item For variables and functions visible outside of file scope, used internally across multiple libraries, use @code{avpriv_} as prefix, for example, -@samp{avpriv_aac_parse_header}. +@samp{avpriv_report_missing_feature}. @item For externally visible symbols, each library has its own prefix. Check diff --git a/libavcodec/Makefile b/libavcodec/Makefile index b60ba5ef9633c..a1bb4b5950592 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -2,6 +2,7 @@ NAME = avcodec DESC = Libav codec library HEADERS = ac3_parser.h \ + adts_parser.h \ avcodec.h \ avfft.h \ d3d11va.h \ @@ -16,6 +17,7 @@ HEADERS = ac3_parser.h \ vorbis_parser.h \ OBJS = ac3_parser.o \ + adts_parser.o \ allcodecs.o \ avpacket.o \ avpicture.o \ @@ -45,6 +47,7 @@ OBJS = ac3_parser.o \ # subsystems OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o OBJS-$(CONFIG_AC3DSP) += ac3dsp.o +OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio.o OBJS-$(CONFIG_AUDIO_FRAME_QUEUE) += audio_frame_queue.o OBJS-$(CONFIG_AUDIODSP) += audiodsp.o OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o @@ -126,7 +129,7 @@ OBJS-$(CONFIG_WMV2DSP) += wmv2dsp.o OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o aacsbr.o aacps.o \ - aacadtsdec.o mpeg4audio.o kbdwin.o \ + mpeg4audio.o kbdwin.o \ sbrdsp.o aacpsdsp.o OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o \ aacpsy.o aactab.o \ @@ -666,7 +669,6 @@ OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MOV_DEMUXER) += ac3tab.o OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o -OBJS-$(CONFIG_SPDIF_DEMUXER) += aacadtsdec.o mpeg4audio.o OBJS-$(CONFIG_SPDIF_MUXER) += dca.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o @@ -722,7 +724,7 @@ OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o # parsers OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \ - aacadtsdec.o mpeg4audio.o + mpeg4audio.o OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o @@ -760,8 +762,7 @@ OBJS-$(CONFIG_VP3_PARSER) += vp3_parser.o OBJS-$(CONFIG_VP8_PARSER) += vp8_parser.o # bitstream filters -OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o aacadtsdec.o \ - mpeg4audio.o +OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o mpeg4audio.o OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \ diff --git a/libavcodec/aac_adtstoasc_bsf.c b/libavcodec/aac_adtstoasc_bsf.c index 3a83d488c4507..778387cabb0f2 100644 --- a/libavcodec/aac_adtstoasc_bsf.c +++ b/libavcodec/aac_adtstoasc_bsf.c @@ -19,8 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "adts_header.h" +#include "adts_parser.h" #include "avcodec.h" -#include "aacadtsdec.h" #include "bsf.h" #include "put_bits.h" #include "get_bits.h" @@ -49,15 +50,15 @@ static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out) if (ret < 0) return ret; - if (in->size < AAC_ADTS_HEADER_SIZE) + if (in->size < AV_AAC_ADTS_HEADER_SIZE) goto packet_too_small; - init_get_bits(&gb, in->data, AAC_ADTS_HEADER_SIZE * 8); + init_get_bits(&gb, in->data, AV_AAC_ADTS_HEADER_SIZE * 8); if (bsfc->par_in->extradata && show_bits(&gb, 12) != 0xfff) goto finish; - if (avpriv_aac_parse_header(&gb, &hdr) < 0) { + if (ff_adts_header_parse(&gb, &hdr) < 0) { av_log(bsfc, AV_LOG_ERROR, "Error parsing ADTS frame header!\n"); ret = AVERROR_INVALIDDATA; goto fail; @@ -70,10 +71,10 @@ static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out) goto fail; } - in->size -= AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent; + in->size -= AV_AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent; if (in->size <= 0) goto packet_too_small; - in->data += AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent; + in->data += AV_AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent; if (!ctx->first_frame_done) { int pce_size = 0; diff --git a/libavcodec/aac_parser.c b/libavcodec/aac_parser.c index eae120a249be6..41b301ca17465 100644 --- a/libavcodec/aac_parser.c +++ b/libavcodec/aac_parser.c @@ -22,7 +22,8 @@ #include "parser.h" #include "aac_ac3_parser.h" -#include "aacadtsdec.h" +#include "adts_header.h" +#include "adts_parser.h" #include "get_bits.h" #include "mpeg4audio.h" @@ -38,9 +39,10 @@ static int aac_sync(uint64_t state, AACAC3ParseContext *hdr_info, } tmp; tmp.u64 = av_be2ne64(state); - init_get_bits(&bits, tmp.u8+8-AAC_ADTS_HEADER_SIZE, AAC_ADTS_HEADER_SIZE * 8); + init_get_bits(&bits, tmp.u8 + 8 - AV_AAC_ADTS_HEADER_SIZE, + AV_AAC_ADTS_HEADER_SIZE * 8); - if ((size = avpriv_aac_parse_header(&bits, &hdr)) < 0) + if ((size = ff_adts_header_parse(&bits, &hdr)) < 0) return 0; *need_next_header = 0; *new_frame_start = 1; @@ -54,7 +56,7 @@ static int aac_sync(uint64_t state, AACAC3ParseContext *hdr_info, static av_cold int aac_parse_init(AVCodecParserContext *s1) { AACAC3ParseContext *s = s1->priv_data; - s->header_size = AAC_ADTS_HEADER_SIZE; + s->header_size = AV_AAC_ADTS_HEADER_SIZE; s->sync = aac_sync; return 0; } diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c index 4ba346ac48710..e436b4f2f7485 100644 --- a/libavcodec/aacdec.c +++ b/libavcodec/aacdec.c @@ -93,11 +93,11 @@ #include "aac.h" #include "aactab.h" #include "aacdectab.h" +#include "adts_header.h" #include "cbrt_tablegen.h" #include "sbr.h" #include "aacsbr.h" #include "mpeg4audio.h" -#include "aacadtsdec.h" #include "libavutil/intfloat.h" #include @@ -2705,7 +2705,7 @@ static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb) uint8_t layout_map[MAX_ELEM_ID*4][3]; int layout_map_tags, ret; - size = avpriv_aac_parse_header(gb, &hdr_info); + size = ff_adts_header_parse(gb, &hdr_info); if (size > 0) { if (hdr_info.num_aac_frames != 1) { avpriv_report_missing_feature(ac->avctx, diff --git a/libavcodec/aacadtsdec.c b/libavcodec/adts_header.c similarity index 93% rename from libavcodec/aacadtsdec.c rename to libavcodec/adts_header.c index 2994bce243e35..3b845058ffac5 100644 --- a/libavcodec/aacadtsdec.c +++ b/libavcodec/adts_header.c @@ -22,11 +22,12 @@ */ #include "aac_ac3_parser.h" -#include "aacadtsdec.h" +#include "adts_header.h" +#include "adts_parser.h" #include "get_bits.h" #include "mpeg4audio.h" -int avpriv_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr) +int ff_adts_header_parse(GetBitContext *gbc, AACADTSHeaderInfo *hdr) { int size, rdb, ch, sr; int aot, crc_abs; @@ -51,7 +52,7 @@ int avpriv_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr) skip_bits1(gbc); /* copyright_identification_bit */ skip_bits1(gbc); /* copyright_identification_start */ size = get_bits(gbc, 13); /* aac_frame_length */ - if (size < AAC_ADTS_HEADER_SIZE) + if (size < AV_AAC_ADTS_HEADER_SIZE) return AAC_AC3_PARSE_ERROR_FRAME_SIZE; skip_bits(gbc, 11); /* adts_buffer_fullness */ diff --git a/libavcodec/aacadtsdec.h b/libavcodec/adts_header.h similarity index 86% rename from libavcodec/aacadtsdec.h rename to libavcodec/adts_header.h index 6319efcea389e..386aa0a33127b 100644 --- a/libavcodec/aacadtsdec.h +++ b/libavcodec/adts_header.h @@ -20,14 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVCODEC_AACADTSDEC_H -#define AVCODEC_AACADTSDEC_H +#ifndef AVCODEC_ADTS_HEADER_H +#define AVCODEC_ADTS_HEADER_H -#include #include "get_bits.h" -#define AAC_ADTS_HEADER_SIZE 7 - typedef struct AACADTSHeaderInfo { uint32_t sample_rate; uint32_t samples; @@ -40,7 +37,6 @@ typedef struct AACADTSHeaderInfo { } AACADTSHeaderInfo; /** - * Parse AAC frame header. * Parse the ADTS frame header to the end of the variable header, which is * the first 54 bits. * @param[in] gbc BitContext containing the first 54 bits of the frame. @@ -49,6 +45,6 @@ typedef struct AACADTSHeaderInfo { * -2 if the version element is invalid, -3 if the sample rate * element is invalid, or -4 if the bit rate element is invalid. */ -int avpriv_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr); +int ff_adts_header_parse(GetBitContext *gbc, AACADTSHeaderInfo *hdr); -#endif /* AVCODEC_AACADTSDEC_H */ +#endif /* AVCODEC_ADTS_HEADER_H */ diff --git a/libavcodec/adts_parser.c b/libavcodec/adts_parser.c new file mode 100644 index 0000000000000..5821e6fb790ed --- /dev/null +++ b/libavcodec/adts_parser.c @@ -0,0 +1,44 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include +#include + +#include "adts_header.h" +#include "adts_parser.h" + +int av_adts_header_parse(const uint8_t *buf, uint32_t *samples, uint8_t *frames) +{ +#if CONFIG_ADTS_HEADER + GetBitContext gb; + AACADTSHeaderInfo hdr; + int err = init_get_bits8(&gb, buf, AV_AAC_ADTS_HEADER_SIZE); + if (err < 0) + return err; + err = ff_adts_header_parse(&gb, &hdr); + if (err < 0) + return err; + *samples = hdr.samples; + *frames = hdr.num_aac_frames; + return 0; +#else + return AVERROR(ENOSYS); +#endif +} diff --git a/libavcodec/adts_parser.h b/libavcodec/adts_parser.h new file mode 100644 index 0000000000000..1a3328f10e4e4 --- /dev/null +++ b/libavcodec/adts_parser.h @@ -0,0 +1,37 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_ADTS_PARSER_H +#define AVCODEC_ADTS_PARSER_H + +#include +#include + +#define AV_AAC_ADTS_HEADER_SIZE 7 + +/** + * Extract the number of samples and frames from AAC data. + * @param[in] buf pointer to AAC data buffer + * @param[out] samples Pointer to where number of samples is written + * @param[out] frames Pointer to where number of frames is written + * @return Returns 0 on success, error code on failure. + */ +int av_adts_header_parse(const uint8_t *buf, uint32_t *samples, + uint8_t *frames); + +#endif /* AVCODEC_ADTS_PARSER_H */ diff --git a/libavformat/spdifdec.c b/libavformat/spdifdec.c index 7c212353f174d..38692c27e6988 100644 --- a/libavformat/spdifdec.c +++ b/libavformat/spdifdec.c @@ -25,18 +25,22 @@ * @author Anssi Hannula */ +#include "libavutil/bswap.h" + +#include "libavcodec/ac3.h" +#include "libavcodec/adts_parser.h" + #include "avformat.h" #include "spdif.h" -#include "libavcodec/ac3.h" -#include "libavcodec/aacadtsdec.h" static int spdif_get_offset_and_codec(AVFormatContext *s, enum IEC61937DataType data_type, const char *buf, int *offset, enum AVCodecID *codec) { - AACADTSHeaderInfo aac_hdr; - GetBitContext gbc; + uint32_t samples; + uint8_t frames; + int ret; switch (data_type & 0xff) { case IEC61937_AC3: @@ -56,13 +60,13 @@ static int spdif_get_offset_and_codec(AVFormatContext *s, *codec = AV_CODEC_ID_MP3; break; case IEC61937_MPEG2_AAC: - init_get_bits(&gbc, buf, AAC_ADTS_HEADER_SIZE * 8); - if (avpriv_aac_parse_header(&gbc, &aac_hdr)) { + ret = av_adts_header_parse(buf, &samples, &frames); + if (ret < 0) { if (s) /* be silent during a probe */ av_log(s, AV_LOG_ERROR, "Invalid AAC packet in IEC 61937\n"); - return AVERROR_INVALIDDATA; + return ret; } - *offset = aac_hdr.samples << 2; + *offset = samples << 2; *codec = AV_CODEC_ID_AAC; break; case IEC61937_MPEG2_LAYER1_LSF: @@ -100,7 +104,7 @@ static int spdif_get_offset_and_codec(AVFormatContext *s, } /* Largest offset between bursts we currently handle, i.e. AAC with - aac_hdr.samples = 4096 */ + samples = 4096 */ #define SPDIF_MAX_OFFSET 16384 static int spdif_probe(AVProbeData *p) @@ -127,7 +131,7 @@ static int spdif_probe(AVProbeData *p) } else consecutive_codes = 0; - if (buf + 4 + AAC_ADTS_HEADER_SIZE > p->buf + p->buf_size) + if (buf + 4 + AV_AAC_ADTS_HEADER_SIZE > p->buf + p->buf_size) break; /* continue probing to find more sync codes */ diff --git a/libavformat/spdifenc.c b/libavformat/spdifenc.c index a9b3b522b3bb0..6497a8273489d 100644 --- a/libavformat/spdifenc.c +++ b/libavformat/spdifenc.c @@ -50,9 +50,9 @@ #include "avio_internal.h" #include "spdif.h" #include "libavcodec/ac3.h" +#include "libavcodec/adts_parser.h" #include "libavcodec/dca.h" #include "libavcodec/dca_syncwords.h" -#include "libavcodec/aacadtsdec.h" #include "libavutil/opt.h" typedef struct IEC61937Context { @@ -349,19 +349,18 @@ static int spdif_header_mpeg(AVFormatContext *s, AVPacket *pkt) static int spdif_header_aac(AVFormatContext *s, AVPacket *pkt) { IEC61937Context *ctx = s->priv_data; - AACADTSHeaderInfo hdr; - GetBitContext gbc; + uint32_t samples; + uint8_t frames; int ret; - init_get_bits(&gbc, pkt->data, AAC_ADTS_HEADER_SIZE * 8); - ret = avpriv_aac_parse_header(&gbc, &hdr); + ret = av_adts_header_parse(pkt->data, &samples, &frames); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Wrong AAC file format\n"); - return AVERROR_INVALIDDATA; + return ret; } - ctx->pkt_offset = hdr.samples << 2; - switch (hdr.num_aac_frames) { + ctx->pkt_offset = samples << 2; + switch (frames) { case 1: ctx->data_type = IEC61937_MPEG2_AAC; break; @@ -373,7 +372,7 @@ static int spdif_header_aac(AVFormatContext *s, AVPacket *pkt) break; default: av_log(s, AV_LOG_ERROR, - "%"PRIu32" samples in AAC frame not supported\n", hdr.samples); + "%"PRIu32" samples in AAC frame not supported\n", samples); return AVERROR(EINVAL); } //TODO Data type dependent info (LC profile/SBR) From 504403ab28688588fb85817ad58964482f67f29f Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Mon, 20 Mar 2017 12:44:42 -0700 Subject: [PATCH 0209/2557] aacsbr: Turnoff in the event of over read. Aliased compressed AAC bytes are almost certainly not meaningful SBR data. In the wild this causes harsh artifacts switching HE-AAC streams that don't have SBR headers aligned with segment boundaries. Turning off SBR falls back to a default set of upsampling parameters that can function as a sort of error concealment. This is consistent with how the decoder handles other sorts of errors. Bug-Id: 1047 CC: libav-stable@libav.org Signed-off-by: Sean McGovern --- libavcodec/aacsbr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/aacsbr.c b/libavcodec/aacsbr.c index 99f7b0829c4bd..d9bbe5eacc6e5 100644 --- a/libavcodec/aacsbr.c +++ b/libavcodec/aacsbr.c @@ -1097,6 +1097,7 @@ int ff_decode_sbr_extension(AACContext *ac, SpectralBandReplication *sbr, if (bytes_read > cnt) { av_log(ac->avctx, AV_LOG_ERROR, "Expected to read %d SBR bytes actually read %d.\n", cnt, bytes_read); + sbr_turnoff(sbr); } return cnt; } From 118dd4a321a2d67f67c21b076abd0b4d939ab642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= Date: Thu, 4 May 2017 10:49:16 +0200 Subject: [PATCH 0210/2557] hevc: 16x16 NEON idct: Use the right element size for loads/stores MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This doesn't change the actual behaviour of the code but improves readability. Signed-off-by: Martin Storsjö --- libavcodec/arm/hevc_idct.S | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/arm/hevc_idct.S b/libavcodec/arm/hevc_idct.S index fac575818ba96..eeb81e388e436 100644 --- a/libavcodec/arm/hevc_idct.S +++ b/libavcodec/arm/hevc_idct.S @@ -536,10 +536,10 @@ endfunc butterfly q10, q14, q2, q5 butterfly q11, q15, q3, q4 add r4, sp, #512 - vst1.s16 {q0-q1}, [r4, :128]! - vst1.s16 {q2-q3}, [r4, :128]! - vst1.s16 {q4-q5}, [r4, :128]! - vst1.s16 {q6-q7}, [r4, :128] + vst1.s32 {q0-q1}, [r4, :128]! + vst1.s32 {q2-q3}, [r4, :128]! + vst1.s32 {q4-q5}, [r4, :128]! + vst1.s32 {q6-q7}, [r4, :128] .endm .macro load16 in0, in1, in2, in3, in4, in5, in6, in7 @@ -631,8 +631,8 @@ function func_tr_16x4_\name add_member d7, d1[3], d1[2], d1[1], d1[0], d0[3], d0[2], d0[1], d0[0], +, -, +, -, +, -, +, - add r4, sp, #512 - vld1.s16 {q0-q1}, [r4, :128]! - vld1.s16 {q2-q3}, [r4, :128]! + vld1.s32 {q0-q1}, [r4, :128]! + vld1.s32 {q2-q3}, [r4, :128]! butterfly16 q0, q5, q1, q6, q2, q7, q3, q8 scale d26, d27, d28, d29, d30, d31, d16, d17, q4, q0, q5, q1, q6, q2, q7, q3, \shift @@ -645,8 +645,8 @@ function func_tr_16x4_\name store16 d26, d27, d28, d29, d30, d31, d16, d17 add r4, sp, #576 - vld1.s16 {q0-q1}, [r4, :128]! - vld1.s16 {q2-q3}, [r4, :128] + vld1.s32 {q0-q1}, [r4, :128]! + vld1.s32 {q2-q3}, [r4, :128] butterfly16 q0, q9, q1, q10, q2, q11, q3, q12 scale d26, d27, d28, d29, d30, d31, d8, d9, q4, q0, q9, q1, q10, q2, q11, q3, \shift transpose8_4x4 d26, d28, d30, d8 From ce080f47b8b55ab3d41eb00487b138d9906d114d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= Date: Thu, 4 May 2017 10:52:52 +0200 Subject: [PATCH 0211/2557] hevc: Add NEON 32x32 IDCT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/arm/hevc_idct.S | 311 ++++++++++++++++++++++++++++-- libavcodec/arm/hevcdsp_init_arm.c | 4 + 2 files changed, 294 insertions(+), 21 deletions(-) diff --git a/libavcodec/arm/hevc_idct.S b/libavcodec/arm/hevc_idct.S index eeb81e388e436..79799b24ffecd 100644 --- a/libavcodec/arm/hevc_idct.S +++ b/libavcodec/arm/hevc_idct.S @@ -28,6 +28,10 @@ const trans, align=4 .short 89, 75, 50, 18 .short 90, 87, 80, 70 .short 57, 43, 25, 9 + .short 90, 90, 88, 85 + .short 82, 78, 73, 67 + .short 61, 54, 46, 38 + .short 31, 22, 13, 4 endconst .macro clip10 in1, in2, c1, c2 @@ -509,7 +513,7 @@ endfunc vsub.s32 \tmp_m, \e, \o .endm -.macro tr16_8x4 in0, in1, in2, in3, in4, in5, in6, in7 +.macro tr16_8x4 in0, in1, in2, in3, in4, in5, in6, in7, offset tr_4x4_8 \in0, \in2, \in4, \in6, q8, q9, q10, q11, q12, q13, q14, q15 vmull.s16 q12, \in1, \in0[0] @@ -535,7 +539,7 @@ endfunc butterfly q9, q13, q1, q6 butterfly q10, q14, q2, q5 butterfly q11, q15, q3, q4 - add r4, sp, #512 + add r4, sp, #\offset vst1.s32 {q0-q1}, [r4, :128]! vst1.s32 {q2-q3}, [r4, :128]! vst1.s32 {q4-q5}, [r4, :128]! @@ -575,15 +579,15 @@ endfunc vsub.s32 \in6, \in6, \in7 .endm -.macro store16 in0, in1, in2, in3, in4, in5, in6, in7 +.macro store16 in0, in1, in2, in3, in4, in5, in6, in7, rx vst1.s16 \in0, [r1, :64], r2 - vst1.s16 \in1, [r3, :64], r4 + vst1.s16 \in1, [r3, :64], \rx vst1.s16 \in2, [r1, :64], r2 - vst1.s16 \in3, [r3, :64], r4 + vst1.s16 \in3, [r3, :64], \rx vst1.s16 \in4, [r1, :64], r2 - vst1.s16 \in5, [r3, :64], r4 + vst1.s16 \in5, [r3, :64], \rx vst1.s16 \in6, [r1, :64], r2 - vst1.s16 \in7, [r3, :64], r4 + vst1.s16 \in7, [r3, :64], \rx .endm .macro scale out0, out1, out2, out3, out4, out5, out6, out7, in0, in1, in2, in3, in4, in5, in6, in7, shift @@ -597,19 +601,35 @@ endfunc vqrshrn.s32 \out7, \in7, \shift .endm -.macro tr_16x4 name, shift +@stores in1, in2, in4, in6 ascending from off1 and +@stores in1, in3, in5, in7 descending from off2 +.macro store_to_stack off1, off2, in0, in2, in4, in6, in7, in5, in3, in1 + add r1, sp, #\off1 + add r3, sp, #\off2 + mov r2, #-16 + vst1.s32 {\in0}, [r1, :128]! + vst1.s32 {\in1}, [r3, :128], r2 + vst1.s32 {\in2}, [r1, :128]! + vst1.s32 {\in3}, [r3, :128], r2 + vst1.s32 {\in4}, [r1, :128]! + vst1.s32 {\in5}, [r3, :128], r2 + vst1.s32 {\in6}, [r1, :128] + vst1.s32 {\in7}, [r3, :128] +.endm + +.macro tr_16x4 name, shift, offset, step function func_tr_16x4_\name mov r1, r5 - add r3, r5, #64 - mov r2, #128 + add r3, r5, #(\step * 64) + mov r2, #(\step * 128) load16 d0, d1, d2, d3, d4, d5, d6, d7 movrel r1, trans - tr16_8x4 d0, d1, d2, d3, d4, d5, d6, d7 + tr16_8x4 d0, d1, d2, d3, d4, d5, d6, d7, \offset - add r1, r5, #32 - add r3, r5, #(64 + 32) - mov r2, #128 + add r1, r5, #(\step * 32) + add r3, r5, #(\step * 3 *32) + mov r2, #(\step * 128) load16 d8, d9, d2, d3, d4, d5, d6, d7 movrel r1, trans + 16 vld1.s16 {q0}, [r1, :128] @@ -630,11 +650,12 @@ function func_tr_16x4_\name add_member d6, d1[2], d0[3], d0[0], d0[2], d1[1], d1[3], d1[0], d0[1], +, -, +, -, +, +, -, + add_member d7, d1[3], d1[2], d1[1], d1[0], d0[3], d0[2], d0[1], d0[0], +, -, +, -, +, -, +, - - add r4, sp, #512 + add r4, sp, #\offset vld1.s32 {q0-q1}, [r4, :128]! vld1.s32 {q2-q3}, [r4, :128]! butterfly16 q0, q5, q1, q6, q2, q7, q3, q8 + .if \shift > 0 scale d26, d27, d28, d29, d30, d31, d16, d17, q4, q0, q5, q1, q6, q2, q7, q3, \shift transpose8_4x4 d26, d28, d30, d16 transpose8_4x4 d17, d31, d29, d27 @@ -642,12 +663,16 @@ function func_tr_16x4_\name add r3, r6, #(24 +3*32) mov r2, #32 mov r4, #-32 - store16 d26, d27, d28, d29, d30, d31, d16, d17 + store16 d26, d27, d28, d29, d30, d31, d16, d17, r4 + .else + store_to_stack \offset, (\offset + 240), q4, q5, q6, q7, q3, q2, q1, q0 + .endif - add r4, sp, #576 + add r4, sp, #(\offset + 64) vld1.s32 {q0-q1}, [r4, :128]! vld1.s32 {q2-q3}, [r4, :128] butterfly16 q0, q9, q1, q10, q2, q11, q3, q12 + .if \shift > 0 scale d26, d27, d28, d29, d30, d31, d8, d9, q4, q0, q9, q1, q10, q2, q11, q3, \shift transpose8_4x4 d26, d28, d30, d8 transpose8_4x4 d9, d31, d29, d27 @@ -656,7 +681,10 @@ function func_tr_16x4_\name add r3, r6, #(16 + 3 * 32) mov r2, #32 mov r4, #-32 - store16 d26, d27, d28, d29, d30, d31, d8, d9 + store16 d26, d27, d28, d29, d30, d31, d8, d9, r4 + .else + store_to_stack (\offset + 64), (\offset + 176), q4, q9, q10, q11, q3, q2, q1, q0 + .endif bx lr endfunc @@ -694,9 +722,248 @@ A and r7, sp, #15 endfunc .endm -tr_16x4 firstpass, 7 -tr_16x4 secondpass_8, 20 - 8 -tr_16x4 secondpass_10, 20 - 10 +.macro load32 + add r1, r5, #64 + add r3, r1, #128 + mov r2, #256 + vld1.s16 {d4}, [r1, :64], r2 + vld1.s16 {d5}, [r3, :64], r2 + vld1.s16 {d6}, [r1, :64], r2 + vld1.s16 {d7}, [r3, :64], r2 + vld1.s16 {d8}, [r1, :64], r2 + vld1.s16 {d9}, [r3, :64], r2 + vld1.s16 {d10}, [r1, :64], r2 + vld1.s16 {d11}, [r3, :64], r2 + vld1.s16 {d12}, [r1, :64], r2 + vld1.s16 {d13}, [r3, :64], r2 + vld1.s16 {d14}, [r1, :64], r2 + vld1.s16 {d15}, [r3, :64], r2 + vld1.s16 {d16}, [r1, :64], r2 + vld1.s16 {d17}, [r3, :64], r2 + vld1.s16 {d18}, [r1, :64], r2 + vld1.s16 {d19}, [r3, :64], r2 +.endm + +.macro add_member32 in, t0, t1, t2, t3, op0, op1, op2, op3 + sum_sub q10, \in, \t0, \op0 + sum_sub q11, \in, \t1, \op1 + sum_sub q12, \in, \t2, \op2 + sum_sub q13, \in, \t3, \op3 +.endm + +.macro butterfly32 in0, in1, in2, in3 + vadd.s32 q1, \in0, \in1 + vsub.s32 \in0, \in0, \in1 + vadd.s32 \in1, \in2, \in3 + vsub.s32 \in2, \in2, \in3 +.endm + +.macro scale32 out0, out1, out2, out3, in0, in1, in2, in3, shift + vqrshrn.s32 \out0, \in0, \shift + vqrshrn.s32 \out1, \in1, \shift + vqrshrn.s32 \out2, \in2, \shift + vqrshrn.s32 \out3, \in3, \shift +.endm + +.macro multiply in + vmull.s16 q10, d4, \in[0] + vmull.s16 q11, d4, \in[1] + vmull.s16 q12, d4, \in[2] + vmull.s16 q13, d4, \in[3] +.endm + +.macro scale_store shift + vld1.s16 {q14-q15}, [r4, :128]! + butterfly32 q14, q10, q15, q11 + scale32 d22, d23, d20, d21, q1, q14, q10, q15, \shift + + vld1.s16 {q14-q15}, [r4, :128]! + butterfly32 q14, q12, q15, q13 + scale32 d2, d3, d28, d29, q1, q14, q12, q15, \shift + transpose8_4x4 d22, d20, d2, d28 + transpose8_4x4 d29, d3, d21, d23 + store16 d22, d23, d20, d21, d2, d3, d28, d29, r8 + + @ reload multiplication coefficiens to q1 + vld1.s16 {q1}, [r9, :128] +.endm + +function tr_block1 + multiply d0 + add_member32 d5, d0[1], d1[0], d1[3], d2[2], +, +, +, + + add_member32 d6, d0[2], d1[3], d3[0], d3[2], +, +, +, - + add_member32 d7, d0[3], d2[2], d3[2], d1[3], +, +, -, - + add_member32 d8, d1[0], d3[1], d2[1], d0[0], +, +, -, - + add_member32 d9, d1[1], d3[3], d1[0], d1[2], +, -, -, - + add_member32 d10, d1[2], d3[0], d0[0], d3[1], +, -, -, - + add_member32 d11, d1[3], d2[1], d1[1], d2[3], +, -, -, + + add_member32 d12, d2[0], d1[2], d2[2], d1[0], +, -, -, + + add_member32 d13, d2[1], d0[3], d3[3], d0[2], +, -, -, + + add_member32 d14, d2[2], d0[1], d2[3], d2[1], +, -, +, + + add_member32 d15, d2[3], d0[2], d1[2], d3[3], +, -, +, - + add_member32 d16, d3[0], d1[1], d0[1], d2[0], +, -, +, - + add_member32 d17, d3[1], d2[0], d0[3], d0[1], +, -, +, - + add_member32 d18, d3[2], d2[3], d2[0], d1[1], +, -, +, - + add_member32 d19, d3[3], d3[2], d3[1], d3[0], +, -, +, - + bx lr +endfunc + +function tr_block2 + multiply d1 + add_member32 d5, d3[1], d3[3], d3[0], d2[1], +, -, -, - + add_member32 d6, d2[1], d1[0], d0[0], d1[1], -, -, -, - + add_member32 d7, d0[0], d1[2], d3[1], d2[3], -, -, -, + + add_member32 d8, d2[0], d3[2], d1[1], d0[3], -, +, +, + + add_member32 d9, d3[2], d0[3], d1[3], d3[1], +, +, +, - + add_member32 d10, d1[1], d1[3], d2[3], d0[0], +, +, -, - + add_member32 d11, d0[3], d3[1], d0[1], d3[3], +, -, -, + + add_member32 d12, d3[0], d0[2], d3[2], d0[1], +, -, -, + + add_member32 d13, d2[2], d2[0], d1[0], d3[2], -, -, +, + + add_member32 d14, d0[1], d3[0], d2[0], d0[2], -, +, +, - + add_member32 d15, d1[3], d0[1], d2[2], d3[0], -, +, -, - + add_member32 d16, d3[3], d2[1], d0[2], d1[0], +, +, -, + + add_member32 d17, d1[2], d2[3], d3[3], d2[2], +, -, -, + + add_member32 d18, d0[2], d0[1], d0[3], d1[2], +, -, +, - + add_member32 d19, d2[3], d2[2], d2[1], d2[0], +, -, +, - + bx lr +endfunc + +function tr_block3 + multiply d2 + add_member32 d5, d1[2], d0[3], d0[0], d0[2], -, -, -, - + add_member32 d6, d2[2], d3[3], d2[3], d1[2], -, -, +, + + add_member32 d7, d1[0], d0[2], d2[1], d3[3], +, +, +, - + add_member32 d8, d3[0], d2[2], d0[1], d1[3], +, -, -, - + add_member32 d9, d0[2], d2[0], d3[0], d0[0], -, -, +, + + add_member32 d10, d3[2], d1[0], d2[0], d2[2], -, +, +, - + add_member32 d11, d0[0], d3[2], d0[2], d3[0], +, +, -, - + add_member32 d12, d3[3], d0[1], d3[1], d0[3], -, -, +, + + add_member32 d13, d0[1], d2[3], d1[3], d1[1], -, +, +, - + add_member32 d14, d3[1], d1[3], d0[3], d3[2], +, +, -, + + add_member32 d15, d0[3], d1[1], d3[2], d2[0], +, -, +, + + add_member32 d16, d2[3], d3[1], d1[2], d0[1], -, -, +, - + add_member32 d17, d1[1], d0[0], d1[0], d2[1], -, +, -, + + add_member32 d18, d2[1], d3[0], d3[3], d3[1], +, -, +, + + add_member32 d19, d1[3], d1[2], d1[1], d1[0], +, -, +, - + bx lr +endfunc + +function tr_block4 + multiply d3 + add_member32 d5, d1[1], d2[0], d2[3], d3[2], -, -, -, - + add_member32 d6, d0[0], d0[3], d2[0], d3[1], +, +, +, + + add_member32 d7, d2[0], d0[0], d1[1], d3[0], -, -, -, - + add_member32 d8, d3[3], d1[2], d0[2], d2[3], +, +, +, + + add_member32 d9, d2[1], d2[3], d0[0], d2[2], +, -, -, - + add_member32 d10, d0[2], d3[3], d0[3], d2[1], -, -, +, + + add_member32 d11, d1[0], d2[2], d1[2], d2[0], +, +, -, - + add_member32 d12, d2[3], d1[1], d2[1], d1[3], -, -, +, + + add_member32 d13, d3[1], d0[1], d3[0], d1[2], -, +, -, - + add_member32 d14, d1[2], d1[0], d3[3], d1[1], +, -, +, + + add_member32 d15, d0[1], d2[1], d3[1], d1[0], -, +, +, - + add_member32 d16, d1[3], d3[2], d2[2], d0[3], +, -, -, + + add_member32 d17, d3[2], d3[0], d1[3], d0[2], -, -, +, - + add_member32 d18, d2[2], d1[3], d1[0], d0[1], -, +, -, + + add_member32 d19, d0[3], d0[2], d0[1], d0[0], +, -, +, - + bx lr +endfunc + +.macro tr_32x4 name, shift +function func_tr_32x4_\name + mov r10, lr + bl func_tr_16x4_noscale + + load32 + movrel r9, trans + 32 + vld1.s16 {q0}, [r9, :128]! + vld1.s16 {q1}, [r9, :128] + + bl tr_block1 + + add r4, sp, #2048 + vld1.s16 {q14-q15}, [r4, :128]! + butterfly32 q14, q10, q15, q11 + scale32 d22, d23, d20, d21, q1, q14, q10, q15, \shift + + vld1.s16 {q14-q15}, [r4, :128]! + butterfly32 q14, q12, q15, q13 + scale32 d2, d3, d28, d29, q1, q14, q12, q15, \shift + + transpose8_4x4 d22, d20, d2, d28 + transpose8_4x4 d29, d3, d21, d23 + mov r1, r11 + mov r2, #64 + mov r8, #-64 + add r3, r11, #(56 + 3 * 64) + store16 d22, d23, d20, d21, d2, d3, d28, d29, r8 + + @ reload multiplication coefficiens to q1 + vld1.s16 {q1}, [r9, :128] + + bl tr_block2 + add r1, r11, #8 + add r3, r11, #(48 + 3 * 64) + mov r2, #64 + mov r8, #-64 + scale_store \shift + + bl tr_block3 + add r1, r11, #16 + add r3, r11, #(40 + 3 * 64) + mov r2, #64 + mov r8, #-64 + scale_store \shift + + bl tr_block4 + add r1, r11, #24 + add r3, r11, #(32 + 3 * 64) + mov r2, #64 + mov r8, #-64 + scale_store \shift + + bx r10 +endfunc +.endm + +.macro idct_32x32 bitdepth +function ff_hevc_idct_32x32_\bitdepth\()_neon, export=1 +@r0 - coeffs + push {r4-r11, lr} + vpush {q4-q7} + + @ Align the stack, allocate a temp buffer +T mov r7, sp +T and r7, r7, #15 +A and r7, sp, #15 + add r7, r7, #2432 + sub sp, sp, r7 + +.irp i, 0, 1, 2, 3, 4, 5, 6, 7 + add r5, r0, #(8 * \i) + add r11, sp, #(8 * \i * 32) + bl func_tr_32x4_firstpass +.endr + +.irp i, 0, 1, 2, 3, 4, 5, 6, 7 + add r5, sp, #(8 * \i) + add r11, r0, #(8 * \i * 32) + bl func_tr_32x4_secondpass_\bitdepth +.endr + + add sp, sp, r7 + vpop {q4-q7} + pop {r4-r11, pc} +endfunc +.endm + +tr_16x4 firstpass, 7, 512, 1 +tr_16x4 secondpass_8, 20 - 8, 512, 1 +tr_16x4 secondpass_10, 20 - 10, 512, 1 +tr_16x4 noscale, 0, 2048, 4 +.ltorg +tr_32x4 firstpass, 7 +tr_32x4 secondpass_8, 20 - 8 +tr_32x4 secondpass_10, 20 - 10 .ltorg idct_4x4 8 @@ -711,5 +978,7 @@ idct_16x16 8 idct_16x16_dc 8 idct_16x16 10 idct_16x16_dc 10 +idct_32x32 8 idct_32x32_dc 8 +idct_32x32 10 idct_32x32_dc 10 diff --git a/libavcodec/arm/hevcdsp_init_arm.c b/libavcodec/arm/hevcdsp_init_arm.c index e3d4e4eb756f2..a8b03eb3567ba 100644 --- a/libavcodec/arm/hevcdsp_init_arm.c +++ b/libavcodec/arm/hevcdsp_init_arm.c @@ -55,9 +55,11 @@ void ff_hevc_idct_32x32_dc_10_neon(int16_t *coeffs); void ff_hevc_idct_4x4_8_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_8x8_8_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_16x16_8_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_32x32_8_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_4x4_10_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_8x8_10_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_16x16_10_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_32x32_10_neon(int16_t *coeffs, int col_limit); av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, int bit_depth) { @@ -78,6 +80,7 @@ av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, int bit_depth) c->idct[0] = ff_hevc_idct_4x4_8_neon; c->idct[1] = ff_hevc_idct_8x8_8_neon; c->idct[2] = ff_hevc_idct_16x16_8_neon; + c->idct[3] = ff_hevc_idct_32x32_8_neon; } if (bit_depth == 10) { c->add_residual[0] = ff_hevc_add_residual_4x4_10_neon; @@ -93,6 +96,7 @@ av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, int bit_depth) c->idct[0] = ff_hevc_idct_4x4_10_neon; c->idct[1] = ff_hevc_idct_8x8_10_neon; c->idct[2] = ff_hevc_idct_16x16_10_neon; + c->idct[3] = ff_hevc_idct_32x32_10_neon; } } } From 59cee42d7d22530e66a155305389e29679b11f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 3 May 2017 11:18:51 +0300 Subject: [PATCH 0212/2557] arm: Check for the .arch directive in configure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When targeting windows, the .arch directive isn't available. So far, when building for windows, we've always used gas-preprocessor, both when using msvc's armasm and when using clang. Lately, clang/llvm has implemented the last missing piece (altmacro support) for building our assembly without gas-preprocessor. This means that we now build for arm/windows with clang without any extra compatibility layer. Signed-off-by: Martin Storsjö --- configure | 4 ++++ libavutil/arm/asm.S | 2 ++ 2 files changed, 6 insertions(+) diff --git a/configure b/configure index 6f696c9ab5edb..d70e61593ab5d 100755 --- a/configure +++ b/configure @@ -1661,6 +1661,7 @@ SYSTEM_FUNCS=" " TOOLCHAIN_FEATURES=" + as_arch_directive as_dn_directive as_fpu_directive as_func @@ -4376,6 +4377,9 @@ EOF check_inline_asm asm_mod_q '"add r0, %Q0, %R0" :: "r"((long long)0)' + check_as < Date: Sun, 7 May 2017 10:51:58 -0300 Subject: [PATCH 0213/2557] hevcdec: remove HEVCContext usage from hevc_sei Based on the H264 SEI implementation. This will be mainly useful once support for SEI messages that can be used by the hevc parser are implemented, like Picture Timing. Signed-off-by: James Almer Signed-off-by: Luca Barbato --- libavcodec/hevc_sei.c | 71 +++++++++++++++++++------------------------ libavcodec/hevcdec.c | 49 +++++++++++++++-------------- libavcodec/hevcdec.h | 45 ++++++++++++++++----------- 3 files changed, 86 insertions(+), 79 deletions(-) diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 1f8554ad5fe52..b2a0d67882b68 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -53,10 +53,9 @@ enum HEVC_SEI_TYPE { SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO = 144, }; -static int decode_nal_sei_decoded_picture_hash(HEVCContext *s) +static int decode_nal_sei_decoded_picture_hash(HEVCSEIPictureHash *s, GetBitContext *gb) { int cIdx, i; - GetBitContext *gb = &s->HEVClc.gb; uint8_t hash_type = get_bits(gb, 8); for (cIdx = 0; cIdx < 3; cIdx++) { @@ -75,15 +74,13 @@ static int decode_nal_sei_decoded_picture_hash(HEVCContext *s) return 0; } -static int decode_nal_sei_frame_packing_arrangement(HEVCContext *s) +static int decode_nal_sei_frame_packing_arrangement(HEVCSEIFramePacking *s, GetBitContext *gb) { - GetBitContext *gb = &s->HEVClc.gb; - get_ue_golomb(gb); // frame_packing_arrangement_id - s->sei_frame_packing_present = !get_bits1(gb); + s->present = !get_bits1(gb); - if (s->sei_frame_packing_present) { - s->frame_packing_arrangement_type = get_bits(gb, 7); + if (s->present) { + s->arrangement_type = get_bits(gb, 7); s->quincunx_subsampling = get_bits1(gb); s->content_interpretation_type = get_bits(gb, 6); @@ -92,7 +89,7 @@ static int decode_nal_sei_frame_packing_arrangement(HEVCContext *s) // frame0_self_contained_flag frame1_self_contained_flag skip_bits(gb, 6); - if (!s->quincunx_subsampling && s->frame_packing_arrangement_type != 5) + if (!s->quincunx_subsampling && s->arrangement_type != 5) skip_bits(gb, 16); // frame[01]_grid_position_[xy] skip_bits(gb, 8); // frame_packing_arrangement_reserved_byte skip_bits1(gb); // frame_packing_arrangement_persistence_flag @@ -101,63 +98,58 @@ static int decode_nal_sei_frame_packing_arrangement(HEVCContext *s) return 0; } -static int decode_nal_sei_display_orientation(HEVCContext *s) +static int decode_nal_sei_display_orientation(HEVCSEIDisplayOrientation *s, GetBitContext *gb) { - GetBitContext *gb = &s->HEVClc.gb; - - s->sei_display_orientation_present = !get_bits1(gb); + s->present = !get_bits1(gb); - if (s->sei_display_orientation_present) { - s->sei_hflip = get_bits1(gb); // hor_flip - s->sei_vflip = get_bits1(gb); // ver_flip + if (s->present) { + s->hflip = get_bits1(gb); // hor_flip + s->vflip = get_bits1(gb); // ver_flip - s->sei_anticlockwise_rotation = get_bits(gb, 16); + s->anticlockwise_rotation = get_bits(gb, 16); skip_bits1(gb); // display_orientation_persistence_flag } return 0; } -static int decode_nal_sei_prefix(HEVCContext *s, int type, int size) +static int decode_nal_sei_prefix(GetBitContext *gb, void *logctx, HEVCSEI *s, + int type, int size) { - GetBitContext *gb = &s->HEVClc.gb; - switch (type) { case 256: // Mismatched value from HM 8.1 - return decode_nal_sei_decoded_picture_hash(s); + return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gb); case SEI_TYPE_FRAME_PACKING: - return decode_nal_sei_frame_packing_arrangement(s); + return decode_nal_sei_frame_packing_arrangement(&s->frame_packing, gb); case SEI_TYPE_DISPLAY_ORIENTATION: - return decode_nal_sei_display_orientation(s); + return decode_nal_sei_display_orientation(&s->display_orientation, gb); default: - av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type); + av_log(logctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type); skip_bits_long(gb, 8 * size); return 0; } } -static int decode_nal_sei_suffix(HEVCContext *s, int type, int size) +static int decode_nal_sei_suffix(GetBitContext *gb, void *logctx, HEVCSEI *s, + int type, int size) { - GetBitContext *gb = &s->HEVClc.gb; - switch (type) { case SEI_TYPE_DECODED_PICTURE_HASH: - return decode_nal_sei_decoded_picture_hash(s); + return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gb); default: - av_log(s->avctx, AV_LOG_DEBUG, "Skipped SUFFIX SEI %d\n", type); + av_log(logctx, AV_LOG_DEBUG, "Skipped SUFFIX SEI %d\n", type); skip_bits_long(gb, 8 * size); return 0; } } -static int decode_nal_sei_message(HEVCContext *s) +static int decode_nal_sei_message(GetBitContext *gb, void *logctx, HEVCSEI *s, + int type) { - GetBitContext *gb = &s->HEVClc.gb; - int payload_type = 0; int payload_size = 0; int byte = 0xFF; - av_log(s->avctx, AV_LOG_DEBUG, "Decoding SEI\n"); + av_log(logctx, AV_LOG_DEBUG, "Decoding SEI\n"); while (byte == 0xFF) { byte = get_bits(gb, 8); @@ -168,10 +160,10 @@ static int decode_nal_sei_message(HEVCContext *s) byte = get_bits(gb, 8); payload_size += byte; } - if (s->nal_unit_type == HEVC_NAL_SEI_PREFIX) { - return decode_nal_sei_prefix(s, payload_type, payload_size); + if (type == HEVC_NAL_SEI_PREFIX) { + return decode_nal_sei_prefix(gb, logctx, s, payload_type, payload_size); } else { /* nal_unit_type == NAL_SEI_SUFFIX */ - return decode_nal_sei_suffix(s, payload_type, payload_size); + return decode_nal_sei_suffix(gb, logctx, s, payload_type, payload_size); } } @@ -180,10 +172,11 @@ static int more_rbsp_data(GetBitContext *gb) return get_bits_left(gb) > 0 && show_bits(gb, 8) != 0x80; } -int ff_hevc_decode_nal_sei(HEVCContext *s) +int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, + int type) { do { - decode_nal_sei_message(s); - } while (more_rbsp_data(&s->HEVClc.gb)); + decode_nal_sei_message(gb, logctx, s, type); + } while (more_rbsp_data(gb)); return 0; } diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 6a04858587f90..96e47cd1875d0 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2362,18 +2362,18 @@ static int set_side_data(HEVCContext *s) { AVFrame *out = s->ref->frame; - if (s->sei_frame_packing_present && - s->frame_packing_arrangement_type >= 3 && - s->frame_packing_arrangement_type <= 5 && - s->content_interpretation_type > 0 && - s->content_interpretation_type < 3) { + if (s->sei.frame_packing.present && + s->sei.frame_packing.arrangement_type >= 3 && + s->sei.frame_packing.arrangement_type <= 5 && + s->sei.frame_packing.content_interpretation_type > 0 && + s->sei.frame_packing.content_interpretation_type < 3) { AVStereo3D *stereo = av_stereo3d_create_side_data(out); if (!stereo) return AVERROR(ENOMEM); - switch (s->frame_packing_arrangement_type) { + switch (s->sei.frame_packing.arrangement_type) { case 3: - if (s->quincunx_subsampling) + if (s->sei.frame_packing.quincunx_subsampling) stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX; else stereo->type = AV_STEREO3D_SIDEBYSIDE; @@ -2386,13 +2386,14 @@ static int set_side_data(HEVCContext *s) break; } - if (s->content_interpretation_type == 2) + if (s->sei.frame_packing.content_interpretation_type == 2) stereo->flags = AV_STEREO3D_FLAG_INVERT; } - if (s->sei_display_orientation_present && - (s->sei_anticlockwise_rotation || s->sei_hflip || s->sei_vflip)) { - double angle = s->sei_anticlockwise_rotation * 360 / (double) (1 << 16); + if (s->sei.display_orientation.present && + (s->sei.display_orientation.anticlockwise_rotation || + s->sei.display_orientation.hflip || s->sei.display_orientation.vflip)) { + double angle = s->sei.display_orientation.anticlockwise_rotation * 360 / (double) (1 << 16); AVFrameSideData *rotation = av_frame_new_side_data(out, AV_FRAME_DATA_DISPLAYMATRIX, sizeof(int32_t) * 9); @@ -2401,7 +2402,8 @@ static int set_side_data(HEVCContext *s) av_display_rotation_set((int32_t *)rotation->data, angle); av_display_matrix_flip((int32_t *)rotation->data, - s->sei_hflip, s->sei_vflip); + s->sei.display_orientation.hflip, + s->sei.display_orientation.vflip); } return 0; @@ -2486,7 +2488,8 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) break; case HEVC_NAL_SEI_PREFIX: case HEVC_NAL_SEI_SUFFIX: - ret = ff_hevc_decode_nal_sei(s); + ret = ff_hevc_decode_nal_sei(gb, s->avctx, &s->sei, + s->nal_unit_type); if (ret < 0) goto fail; break; @@ -2680,7 +2683,7 @@ static int verify_md5(HEVCContext *s, AVFrame *frame) int h = (i == 1 || i == 2) ? (height >> desc->log2_chroma_h) : height; uint8_t md5[16]; - av_md5_init(s->md5_ctx); + av_md5_init(s->sei.picture_hash.md5_ctx); for (j = 0; j < h; j++) { const uint8_t *src = frame->data[i] + j * frame->linesize[i]; #if HAVE_BIGENDIAN @@ -2690,11 +2693,11 @@ static int verify_md5(HEVCContext *s, AVFrame *frame) src = s->checksum_buf; } #endif - av_md5_update(s->md5_ctx, src, w << pixel_shift); + av_md5_update(s->sei.picture_hash.md5_ctx, src, w << pixel_shift); } - av_md5_final(s->md5_ctx, md5); + av_md5_final(s->sei.picture_hash.md5_ctx, md5); - if (!memcmp(md5, s->md5[i], 16)) { + if (!memcmp(md5, s->sei.picture_hash.md5[i], 16)) { av_log (s->avctx, AV_LOG_DEBUG, "plane %d - correct ", i); print_md5(s->avctx, AV_LOG_DEBUG, md5); av_log (s->avctx, AV_LOG_DEBUG, "; "); @@ -2702,7 +2705,7 @@ static int verify_md5(HEVCContext *s, AVFrame *frame) av_log (s->avctx, AV_LOG_ERROR, "mismatching checksum of plane %d - ", i); print_md5(s->avctx, AV_LOG_ERROR, md5); av_log (s->avctx, AV_LOG_ERROR, " != "); - print_md5(s->avctx, AV_LOG_ERROR, s->md5[i]); + print_md5(s->avctx, AV_LOG_ERROR, s->sei.picture_hash.md5[i]); av_log (s->avctx, AV_LOG_ERROR, "\n"); return AVERROR_INVALIDDATA; } @@ -2822,7 +2825,7 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, } else { /* verify the SEI checksum */ if (avctx->err_recognition & AV_EF_CRCCHECK && s->is_decoded && - s->is_md5) { + s->sei.picture_hash.is_md5) { ret = verify_md5(s, s->ref->frame); if (ret < 0 && avctx->err_recognition & AV_EF_EXPLODE) { ff_hevc_unref_frame(s, s->ref, ~0); @@ -2830,7 +2833,7 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, } } } - s->is_md5 = 0; + s->sei.picture_hash.is_md5 = 0; if (s->is_decoded) { av_log(avctx, AV_LOG_DEBUG, "Decoded frame with POC %d.\n", s->poc); @@ -2890,7 +2893,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) pic_arrays_free(s); - av_freep(&s->md5_ctx); + av_freep(&s->sei.picture_hash.md5_ctx); av_frame_free(&s->tmp_frame); av_frame_free(&s->output_frame); @@ -2936,8 +2939,8 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) s->max_ra = INT_MAX; - s->md5_ctx = av_md5_alloc(); - if (!s->md5_ctx) + s->sei.picture_hash.md5_ctx = av_md5_alloc(); + if (!s->sei.picture_hash.md5_ctx) goto fail; ff_bswapdsp_init(&s->bdsp); diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index ff192f67aeb90..68ccfb743abdf 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -444,6 +444,31 @@ typedef struct HEVCLocalContext { int boundary_flags; } HEVCLocalContext; +typedef struct HEVCSEIPictureHash { + struct AVMD5 *md5_ctx; + uint8_t md5[3][16]; + uint8_t is_md5; +} HEVCSEIPictureHash; + +typedef struct HEVCSEIFramePacking { + int present; + int arrangement_type; + int content_interpretation_type; + int quincunx_subsampling; +} HEVCSEIFramePacking; + +typedef struct HEVCSEIDisplayOrientation { + int present; + int anticlockwise_rotation; + int hflip, vflip; +} HEVCSEIDisplayOrientation; + +typedef struct HEVCSEI { + HEVCSEIPictureHash picture_hash; + HEVCSEIFramePacking frame_packing; + HEVCSEIDisplayOrientation display_orientation; +} HEVCSEI; + typedef struct HEVCContext { const AVClass *c; // needed by private avoptions AVCodecContext *avctx; @@ -461,6 +486,7 @@ typedef struct HEVCContext { AVFrame *output_frame; HEVCParamSets ps; + HEVCSEI sei; AVBufferPool *tab_mvf_pool; AVBufferPool *rpl_tab_pool; @@ -522,11 +548,6 @@ typedef struct HEVCContext { // type of the first VCL NAL of the current frame enum HEVCNALUnitType first_nal_type; - // for checking the frame checksums - struct AVMD5 *md5_ctx; - uint8_t md5[3][16]; - uint8_t is_md5; - uint8_t context_initialized; uint8_t is_nalff; ///< this flag is != 0 if bitstream is encapsulated ///< as a format defined in 14496-15 @@ -534,20 +555,10 @@ typedef struct HEVCContext { int nal_length_size; ///< Number of bytes used for nal length (1, 2 or 4) int nuh_layer_id; - - /** frame packing arrangement variables */ - int sei_frame_packing_present; - int frame_packing_arrangement_type; - int content_interpretation_type; - int quincunx_subsampling; - - /** display orientation */ - int sei_display_orientation_present; - int sei_anticlockwise_rotation; - int sei_hflip, sei_vflip; } HEVCContext; -int ff_hevc_decode_nal_sei(HEVCContext *s); +int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, + int type); /** * Mark all frames in DPB as unused for reference. From cfd25488bf35123bdd38ecbe1107a21df2e03c2f Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 7 May 2017 10:51:59 -0300 Subject: [PATCH 0214/2557] hevcdec: move SEI message parsing into a separate header It doesn't depend on hevcdec anymore. Signed-off-by: James Almer Signed-off-by: Luca Barbato --- libavcodec/hevc_sei.c | 37 +++--------------- libavcodec/hevc_sei.h | 89 +++++++++++++++++++++++++++++++++++++++++++ libavcodec/hevcdec.h | 30 +-------------- 3 files changed, 95 insertions(+), 61 deletions(-) create mode 100644 libavcodec/hevc_sei.h diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index b2a0d67882b68..153d211b4b135 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -23,35 +23,8 @@ */ #include "golomb_legacy.h" -#include "hevcdec.h" - -enum HEVC_SEI_TYPE { - SEI_TYPE_BUFFERING_PERIOD = 0, - SEI_TYPE_PICTURE_TIMING = 1, - SEI_TYPE_PAN_SCAN_RECT = 2, - SEI_TYPE_FILLER_PAYLOAD = 3, - SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35 = 4, - SEI_TYPE_USER_DATA_UNREGISTERED = 5, - SEI_TYPE_RECOVERY_POINT = 6, - SEI_TYPE_SCENE_INFO = 9, - SEI_TYPE_FULL_FRAME_SNAPSHOT = 15, - SEI_TYPE_PROGRESSIVE_REFINEMENT_SEGMENT_START = 16, - SEI_TYPE_PROGRESSIVE_REFINEMENT_SEGMENT_END = 17, - SEI_TYPE_FILM_GRAIN_CHARACTERISTICS = 19, - SEI_TYPE_POST_FILTER_HINT = 22, - SEI_TYPE_TONE_MAPPING_INFO = 23, - SEI_TYPE_FRAME_PACKING = 45, - SEI_TYPE_DISPLAY_ORIENTATION = 47, - SEI_TYPE_SOP_DESCRIPTION = 128, - SEI_TYPE_ACTIVE_PARAMETER_SETS = 129, - SEI_TYPE_DECODING_UNIT_INFO = 130, - SEI_TYPE_TEMPORAL_LEVEL0_INDEX = 131, - SEI_TYPE_DECODED_PICTURE_HASH = 132, - SEI_TYPE_SCALABLE_NESTING = 133, - SEI_TYPE_REGION_REFRESH_INFO = 134, - SEI_TYPE_MASTERING_DISPLAY_INFO = 137, - SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO = 144, -}; +#include "hevc.h" +#include "hevc_sei.h" static int decode_nal_sei_decoded_picture_hash(HEVCSEIPictureHash *s, GetBitContext *gb) { @@ -119,9 +92,9 @@ static int decode_nal_sei_prefix(GetBitContext *gb, void *logctx, HEVCSEI *s, switch (type) { case 256: // Mismatched value from HM 8.1 return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gb); - case SEI_TYPE_FRAME_PACKING: + case HEVC_SEI_TYPE_FRAME_PACKING: return decode_nal_sei_frame_packing_arrangement(&s->frame_packing, gb); - case SEI_TYPE_DISPLAY_ORIENTATION: + case HEVC_SEI_TYPE_DISPLAY_ORIENTATION: return decode_nal_sei_display_orientation(&s->display_orientation, gb); default: av_log(logctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type); @@ -134,7 +107,7 @@ static int decode_nal_sei_suffix(GetBitContext *gb, void *logctx, HEVCSEI *s, int type, int size) { switch (type) { - case SEI_TYPE_DECODED_PICTURE_HASH: + case HEVC_SEI_TYPE_DECODED_PICTURE_HASH: return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gb); default: av_log(logctx, AV_LOG_DEBUG, "Skipped SUFFIX SEI %d\n", type); diff --git a/libavcodec/hevc_sei.h b/libavcodec/hevc_sei.h new file mode 100644 index 0000000000000..bdc283adb48fd --- /dev/null +++ b/libavcodec/hevc_sei.h @@ -0,0 +1,89 @@ +/* + * HEVC Supplementary Enhancement Information messages + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HEVC_SEI_H +#define AVCODEC_HEVC_SEI_H + +#include + +#include "libavutil/md5.h" + +#include "get_bits.h" + +/** + * SEI message types + */ +typedef enum { + HEVC_SEI_TYPE_BUFFERING_PERIOD = 0, + HEVC_SEI_TYPE_PICTURE_TIMING = 1, + HEVC_SEI_TYPE_PAN_SCAN_RECT = 2, + HEVC_SEI_TYPE_FILLER_PAYLOAD = 3, + HEVC_SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35 = 4, + HEVC_SEI_TYPE_USER_DATA_UNREGISTERED = 5, + HEVC_SEI_TYPE_RECOVERY_POINT = 6, + HEVC_SEI_TYPE_SCENE_INFO = 9, + HEVC_SEI_TYPE_FULL_FRAME_SNAPSHOT = 15, + HEVC_SEI_TYPE_PROGRESSIVE_REFINEMENT_SEGMENT_START = 16, + HEVC_SEI_TYPE_PROGRESSIVE_REFINEMENT_SEGMENT_END = 17, + HEVC_SEI_TYPE_FILM_GRAIN_CHARACTERISTICS = 19, + HEVC_SEI_TYPE_POST_FILTER_HINT = 22, + HEVC_SEI_TYPE_TONE_MAPPING_INFO = 23, + HEVC_SEI_TYPE_FRAME_PACKING = 45, + HEVC_SEI_TYPE_DISPLAY_ORIENTATION = 47, + HEVC_SEI_TYPE_SOP_DESCRIPTION = 128, + HEVC_SEI_TYPE_ACTIVE_PARAMETER_SETS = 129, + HEVC_SEI_TYPE_DECODING_UNIT_INFO = 130, + HEVC_SEI_TYPE_TEMPORAL_LEVEL0_INDEX = 131, + HEVC_SEI_TYPE_DECODED_PICTURE_HASH = 132, + HEVC_SEI_TYPE_SCALABLE_NESTING = 133, + HEVC_SEI_TYPE_REGION_REFRESH_INFO = 134, + HEVC_SEI_TYPE_MASTERING_DISPLAY_INFO = 137, + HEVC_SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO = 144, +} HEVC_SEI_Type; + +typedef struct HEVCSEIPictureHash { + struct AVMD5 *md5_ctx; + uint8_t md5[3][16]; + uint8_t is_md5; +} HEVCSEIPictureHash; + +typedef struct HEVCSEIFramePacking { + int present; + int arrangement_type; + int content_interpretation_type; + int quincunx_subsampling; +} HEVCSEIFramePacking; + +typedef struct HEVCSEIDisplayOrientation { + int present; + int anticlockwise_rotation; + int hflip, vflip; +} HEVCSEIDisplayOrientation; + +typedef struct HEVCSEI { + HEVCSEIPictureHash picture_hash; + HEVCSEIFramePacking frame_packing; + HEVCSEIDisplayOrientation display_orientation; +} HEVCSEI; + +int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, + int type); + +#endif /* AVCODEC_HEVC_SEI_H */ diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 68ccfb743abdf..f2c589217f1f6 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -27,7 +27,6 @@ #include #include "libavutil/buffer.h" -#include "libavutil/md5.h" #include "avcodec.h" #include "bswapdsp.h" @@ -36,6 +35,7 @@ #include "h2645_parse.h" #include "hevc.h" #include "hevc_ps.h" +#include "hevc_sei.h" #include "hevcdsp.h" #include "internal.h" #include "thread.h" @@ -444,31 +444,6 @@ typedef struct HEVCLocalContext { int boundary_flags; } HEVCLocalContext; -typedef struct HEVCSEIPictureHash { - struct AVMD5 *md5_ctx; - uint8_t md5[3][16]; - uint8_t is_md5; -} HEVCSEIPictureHash; - -typedef struct HEVCSEIFramePacking { - int present; - int arrangement_type; - int content_interpretation_type; - int quincunx_subsampling; -} HEVCSEIFramePacking; - -typedef struct HEVCSEIDisplayOrientation { - int present; - int anticlockwise_rotation; - int hflip, vflip; -} HEVCSEIDisplayOrientation; - -typedef struct HEVCSEI { - HEVCSEIPictureHash picture_hash; - HEVCSEIFramePacking frame_packing; - HEVCSEIDisplayOrientation display_orientation; -} HEVCSEI; - typedef struct HEVCContext { const AVClass *c; // needed by private avoptions AVCodecContext *avctx; @@ -557,9 +532,6 @@ typedef struct HEVCContext { int nuh_layer_id; } HEVCContext; -int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, - int type); - /** * Mark all frames in DPB as unused for reference. */ From cb167f2947f1a2c446bd8db196d0e64ef4a6d06b Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Sun, 7 May 2017 17:11:59 -0400 Subject: [PATCH 0215/2557] h264_refs: validate the SPS pointer in ff_h264_execute_ref_pic_marking() Bug-Id: 1036 CC: libav-stable@libav.org --- libavcodec/h264_refs.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/h264_refs.c b/libavcodec/h264_refs.c index b4dc49cc41452..9536c4beaa957 100644 --- a/libavcodec/h264_refs.c +++ b/libavcodec/h264_refs.c @@ -557,6 +557,12 @@ int ff_h264_execute_ref_pic_marking(H264Context *h) int current_ref_assigned = 0, err = 0; H264Picture *av_uninit(pic); + if (!h->ps.sps) { + av_log(h->avctx, AV_LOG_ERROR, "SPS is unset\n"); + err = AVERROR_INVALIDDATA; + goto out; + } + if (!h->explicit_ref_marking) generate_sliding_window_mmcos(h); mmco_count = h->nb_mmco; @@ -725,6 +731,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h) print_short_term(h); print_long_term(h); +out: return (h->avctx->err_recognition & AV_EF_EXPLODE) ? err : 0; } From 6ccf76aec73b2cd598bb1e65d126d8a12540c411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 10 May 2017 23:57:20 +0300 Subject: [PATCH 0216/2557] mpjpeg: Use proper CR/LF in multipart headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is more correct. Signed-off-by: Martin Storsjö --- libavformat/mpjpeg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavformat/mpjpeg.c b/libavformat/mpjpeg.c index 1a78c32274c85..3b78cab22538d 100644 --- a/libavformat/mpjpeg.c +++ b/libavformat/mpjpeg.c @@ -26,7 +26,7 @@ static int mpjpeg_write_header(AVFormatContext *s) { - avio_printf(s->pb, "--%s\n", BOUNDARY_TAG); + avio_printf(s->pb, "--%s\r\n", BOUNDARY_TAG); avio_flush(s->pb); return 0; } @@ -34,12 +34,12 @@ static int mpjpeg_write_header(AVFormatContext *s) static int mpjpeg_write_packet(AVFormatContext *s, AVPacket *pkt) { avio_printf(s->pb, - "Content-length: %i\n" - "Content-type: image/jpeg\n\n", + "Content-length: %i\r\n" + "Content-type: image/jpeg\r\n\r\n", pkt->size); avio_write(s->pb, pkt->data, pkt->size); - avio_printf(s->pb, "\n--%s\n", BOUNDARY_TAG); + avio_printf(s->pb, "\r\n--%s\r\n", BOUNDARY_TAG); return 0; } From d7320ca3ed10f0d35b3740fa03341161e74275ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 9 May 2017 10:25:44 +0300 Subject: [PATCH 0217/2557] arm: Avoid using .dn register aliases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit clang now (in the upcoming 5.0 version) is capable of building our arm assembly without relying on gas-preprocessor, although clang/LLVM doesn't support .dn register aliases. The VC1 MC assembly was only built and used if the chosen assembler supported the .dn directives though. This was supported as long as gas-preprocessor was used. This means that VC1 decoding got a speed regression on clang 5.0, unless the user manually chose using gas-preprocessor again. By avoiding using the .dn register aliases, we can build the VC1 MC assembly with the latest clang version. Support for the .dn/.qn directives in clang/LLVM isn't actively planned, see https://bugs.llvm.org/show_bug.cgi?id=18199. This partially reverts 896a5bff64264f4d01ed98eacc97a67260c1e17e. Signed-off-by: Martin Storsjö --- configure | 5 ----- libavcodec/arm/vc1dsp_init_neon.c | 4 ---- libavcodec/arm/vc1dsp_neon.S | 21 +++++---------------- 3 files changed, 5 insertions(+), 25 deletions(-) diff --git a/configure b/configure index d70e61593ab5d..d6c44cf89e332 100755 --- a/configure +++ b/configure @@ -1662,7 +1662,6 @@ SYSTEM_FUNCS=" TOOLCHAIN_FEATURES=" as_arch_directive - as_dn_directive as_fpu_directive as_func as_object_arch @@ -4379,10 +4378,6 @@ EOF check_as <vc1_inv_trans_4x4_dc = ff_vc1_inv_trans_4x4_dc_neon; dsp->put_vc1_mspel_pixels_tab[ 0] = ff_put_pixels8x8_neon; - if (HAVE_AS_DN_DIRECTIVE) { dsp->put_vc1_mspel_pixels_tab[ 1] = ff_put_vc1_mspel_mc10_neon; dsp->put_vc1_mspel_pixels_tab[ 2] = ff_put_vc1_mspel_mc20_neon; dsp->put_vc1_mspel_pixels_tab[ 3] = ff_put_vc1_mspel_mc30_neon; @@ -109,7 +106,6 @@ av_cold void ff_vc1dsp_init_neon(VC1DSPContext *dsp) dsp->put_vc1_mspel_pixels_tab[13] = ff_put_vc1_mspel_mc13_neon; dsp->put_vc1_mspel_pixels_tab[14] = ff_put_vc1_mspel_mc23_neon; dsp->put_vc1_mspel_pixels_tab[15] = ff_put_vc1_mspel_mc33_neon; - } dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_vc1_chroma_mc8_neon; dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_neon; diff --git a/libavcodec/arm/vc1dsp_neon.S b/libavcodec/arm/vc1dsp_neon.S index 1653a4c5adb35..ff88fe23c7307 100644 --- a/libavcodec/arm/vc1dsp_neon.S +++ b/libavcodec/arm/vc1dsp_neon.S @@ -663,7 +663,6 @@ function ff_vc1_inv_trans_4x4_neon, export=1 bx lr endfunc -#if HAVE_AS_DN_DIRECTIVE @ The absolute value of multiplication constants from vc1_mspel_filter and vc1_mspel_{ver,hor}_filter_16bits. @ The sign is embedded in the code below that carries out the multiplication (mspel_filter{,.16}). #define MSPEL_MODE_1_MUL_CONSTANTS 4 53 18 3 @@ -689,22 +688,18 @@ endfunc @ Setup constants in registers for a subsequent use of mspel_filter{,.16}. .macro mspel_constants typesize reg_a reg_b reg_c reg_d filter_a filter_b filter_c filter_d reg_add filter_add_register - @ Define double-word register aliases. Typesize should be i8 or i16. - ra .dn \reg_a\().\typesize - rb .dn \reg_b\().\typesize - rc .dn \reg_c\().\typesize - rd .dn \reg_d\().\typesize + @ Typesize should be i8 or i16. @ Only set the register if the value is not 1 and unique .if \filter_a != 1 - vmov ra, #\filter_a @ ra = filter_a + vmov.\typesize \reg_a, #\filter_a @ reg_a = filter_a .endif - vmov rb, #\filter_b @ rb = filter_b + vmov.\typesize \reg_b, #\filter_b @ reg_b = filter_b .if \filter_b != \filter_c - vmov rc, #\filter_c @ rc = filter_c + vmov.\typesize \reg_c, #\filter_c @ reg_c = filter_c .endif .if \filter_d != 1 - vmov rd, #\filter_d @ rd = filter_d + vmov.\typesize \reg_d, #\filter_d @ reg_d = filter_d .endif @ vdup to double the size of typesize .ifc \typesize,i8 @@ -712,11 +707,6 @@ endfunc .else vdup.32 \reg_add, \filter_add_register @ reg_add = filter_add_register .endif - - .unreq ra - .unreq rb - .unreq rc - .unreq rd .endm @ After mspel_constants has been used, do the filtering. @@ -987,7 +977,6 @@ PUT_VC1_MSPEL_MC_V_ONLY(2) PUT_VC1_MSPEL_MC_V_ONLY(3) #undef PUT_VC1_MSPEL_MC_V_ONLY -#endif function ff_put_pixels8x8_neon, export=1 vld1.64 {d0}, [r1], r2 From d05c9cde0e87c23ca42957646bea483dfc09d6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 4 May 2017 20:45:34 +0200 Subject: [PATCH 0218/2557] checkasm: aarch64: Specify alignment for the register_init const array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Loads from this strictly doesn't require alignment, but specify it just for consistency with the arm version. Signed-off-by: Martin Storsjö --- tests/checkasm/aarch64/checkasm.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/checkasm/aarch64/checkasm.S b/tests/checkasm/aarch64/checkasm.S index bc5ed9ea094a2..327dfc0802738 100644 --- a/tests/checkasm/aarch64/checkasm.S +++ b/tests/checkasm/aarch64/checkasm.S @@ -22,7 +22,7 @@ #include "libavutil/aarch64/asm.S" -const register_init +const register_init, align=4 .quad 0x21f86d66c8ca00ce .quad 0x75b6ba21077c48ad .quad 0xed56bb2dcb3c7736 From c380a0d7f7a2c7411aae60463e25d916541f0388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 7 Apr 2016 15:45:37 +0300 Subject: [PATCH 0219/2557] movenc: Add an option for enabling negative CTS offsets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reduces the need for an edit list; streams that start with e.g. dts=-1, pts=0 can be encoded as dts=0, pts=0 (which is valid in mov/mp4) by shifting the dts values of all packets forward. This avoids the need for edit lists for such streams (while they still are needed for audio streams with encoder delay). This eases conformance with the DASH-IF interoperability guidelines. Signed-off-by: Martin Storsjö --- libavformat/movenc.c | 28 ++++++++++++++++++++++++---- libavformat/movenc.h | 2 ++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 840190dbfa906..356d1d6b717d8 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -62,6 +62,7 @@ static const AVOption options[] = { { "delay_moov", "Delay writing the initial moov until the first fragment is cut, or until the first fragment flush", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DELAY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "global_sidx", "Write a global sidx index at the start of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_GLOBAL_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "skip_trailer", "Skip writing the mfra/tfra/mfro trailer for fragmented files", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SKIP_TRAILER}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "negative_cts_offsets", "Use negative CTS offsets (reducing the need for edit lists)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags), { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM}, @@ -1163,8 +1164,9 @@ static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra return update_size(pb, pos); } -static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { + MOVMuxContext *mov = s->priv_data; MOVStts *ctts_entries; uint32_t entries = 0; uint32_t atom_size; @@ -1188,7 +1190,11 @@ static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track) atom_size = 16 + (entries * 8); avio_wb32(pb, atom_size); /* size */ ffio_wfourcc(pb, "ctts"); - avio_wb32(pb, 0); /* version & flags */ + if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) + avio_w8(pb, 1); /* version */ + else + avio_w8(pb, 0); /* version */ + avio_wb24(pb, 0); /* flags */ avio_wb32(pb, entries); /* entry count */ for (i = 0; i < entries; i++) { avio_wb32(pb, ctts_entries[i].count); @@ -1273,7 +1279,7 @@ static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE); if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->flags & MOV_TRACK_CTTS && track->entry) - mov_write_ctts_tag(pb, track); + mov_write_ctts_tag(s, pb, track); mov_write_stsc_tag(pb, track); mov_write_stsz_tag(pb, track); mov_write_stco_tag(pb, track); @@ -2594,7 +2600,10 @@ static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov, avio_wb32(pb, 0); /* size placeholder */ ffio_wfourcc(pb, "trun"); - avio_w8(pb, 0); /* version */ + if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) + avio_w8(pb, 1); /* version */ + else + avio_w8(pb, 0); /* version */ avio_wb24(pb, flags); avio_wb32(pb, end - first); /* sample count */ @@ -3040,6 +3049,8 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) ffio_wfourcc(pb, "MSNV"); else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof + else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) + ffio_wfourcc(pb, "iso4"); else if (mov->mode == MODE_MP4) ffio_wfourcc(pb, "isom"); else if (mov->mode == MODE_IPOD) @@ -3288,6 +3299,8 @@ static int mov_flush_fragment(AVFormatContext *s, int force) if (!track->end_reliable) { AVPacket pkt; if (!ff_interleaved_peek(s, i, &pkt, 1)) { + if (track->dts_shift != AV_NOPTS_VALUE) + pkt.dts += track->dts_shift; track->track_duration = pkt.dts - track->start_dts; if (pkt.pts != AV_NOPTS_VALUE) track->end_pts = pkt.pts; @@ -3729,6 +3742,12 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT; } + if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) { + if (trk->dts_shift == AV_NOPTS_VALUE) + trk->dts_shift = pkt->pts - pkt->dts; + pkt->dts += trk->dts_shift; + } + if (!pkt->size) { if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) { trk->start_dts = pkt->dts; @@ -4095,6 +4114,7 @@ static int mov_write_header(AVFormatContext *s) track->start_dts = AV_NOPTS_VALUE; track->start_cts = AV_NOPTS_VALUE; track->end_pts = AV_NOPTS_VALUE; + track->dts_shift = AV_NOPTS_VALUE; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') || track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') || diff --git a/libavformat/movenc.h b/libavformat/movenc.h index f4ed188c385ee..008f4671c62cc 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -107,6 +107,7 @@ typedef struct MOVTrack { int64_t start_cts; int64_t end_pts; int end_reliable; + int64_t dts_shift; int hint_track; ///< the track that hints this track, -1 if no hint track is set int src_track; ///< the track that this hint track describes @@ -195,6 +196,7 @@ typedef struct MOVMuxContext { #define FF_MOV_FLAG_DELAY_MOOV (1 << 13) #define FF_MOV_FLAG_GLOBAL_SIDX (1 << 14) #define FF_MOV_FLAG_SKIP_TRAILER (1 << 15) +#define FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS (1 << 16) int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt); From c415c8104c46f5a75306fff1235124b189e86d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 7 Apr 2016 15:47:31 +0300 Subject: [PATCH 0220/2557] movenc: Don't write any edit list if the start offset is zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In these cases, the CTTS flag is set, but no edit list is necessary. Signed-off-by: Martin Storsjö --- libavformat/movenc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 356d1d6b717d8..e3890296c6376 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1811,8 +1811,7 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov, ffio_wfourcc(pb, "trak"); mov_write_tkhd_tag(pb, mov, track, st); if (track->start_dts != AV_NOPTS_VALUE && - (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS || - track->start_dts || is_clcp_track(track))) { + (track->mode == MODE_PSP || track->start_dts || is_clcp_track(track))) { if (mov->use_editlist) mov_write_edts_tag(pb, mov, track); // PSP Movies require edts box else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track)) From 7c35bee0251efc271c8f7900ce816fcb8ec25d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 7 Apr 2016 16:16:27 +0300 Subject: [PATCH 0221/2557] movenc-test: Add tests for negative cts offsets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/tests/movenc.c | 19 +++++++++++++++++++ tests/ref/fate/movenc | 11 +++++++++++ 2 files changed, 30 insertions(+) diff --git a/libavformat/tests/movenc.c b/libavformat/tests/movenc.c index 583a8d9ca4336..f2aa662b3c102 100644 --- a/libavformat/tests/movenc.c +++ b/libavformat/tests/movenc.c @@ -741,6 +741,25 @@ int main(int argc, char **argv) clear_duration = 0; do_interleave = 0; + // Write a fragmented file with b-frames and audio preroll, + // with negative cts values, removing the edit list for the + // video track. + init_out("delay-moov-elst-neg-cts"); + av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov+negative_cts_offsets", 0); + init(1, 1); + mux_gops(2); + finish(); + close_out(); + + // Write a fragmented file with b-frames without audio preroll, + // with negative cts values, avoiding any edit lists, allowing + // to use empty_moov instead of delay_moov. + init_out("empty-moov-neg-cts"); + av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov+negative_cts_offsets", 0); + init(1, 0); + mux_gops(2); + finish(); + close_out(); av_free(md5); diff --git a/tests/ref/fate/movenc b/tests/ref/fate/movenc index a0a170080dcb8..0fc43dc7d8f24 100644 --- a/tests/ref/fate/movenc +++ b/tests/ref/fate/movenc @@ -133,3 +133,14 @@ write_data len 476, time 1566667, type sync atom moof write_data len 340, time 2233333, type boundary atom moof write_data len 262, time nopts, type trailer atom - a4280bdc23af2c4334ec2da3fa946d3a 3541 vfr-noduration-interleave +write_data len 1219, time nopts, type header atom ftyp +write_data len 620, time 0, type sync atom moof +write_data len 616, time 1000000, type sync atom moof +write_data len 148, time nopts, type trailer atom - +35bc6a836b76484daa366b0284cf8c23 2603 delay-moov-elst-neg-cts +write_data len 36, time nopts, type header atom ftyp +write_data len 1147, time nopts, type header atom - +write_data len 900, time 0, type sync atom moof +write_data len 616, time 1033333, type sync atom moof +write_data len 148, time nopts, type trailer atom - +af285c1617bfd4799aa7280447f1947d 2847 empty-moov-neg-cts From 66aa9b94dae217a0fc5acfb704490707629d95ed Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 30 Apr 2017 22:11:54 +0100 Subject: [PATCH 0222/2557] doc: Document hwupload, hwdownload and hwmap filters --- doc/filters.texi | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 947fd7915c04a..bd2205a9bd06d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1657,6 +1657,104 @@ A floating point number which specifies chroma temporal strength. It defaults to @var{luma_tmp}*@var{chroma_spatial}/@var{luma_spatial}. @end table +@section hwdownload + +Download hardware frames to system memory. + +The input must be in hardware frames, and the output a non-hardware format. +Not all formats will be supported on the output - it may be necessary to insert +an additional @option{format} filter immediately following in the graph to get +the output in a supported format. + +@section hwmap + +Map hardware frames to system memory or to another device. + +This filter has several different modes of operation; which one is used depends +on the input and output formats: +@itemize +@item +Hardware frame input, normal frame output + +Map the input frames to system memory and pass them to the output. If the +original hardware frame is later required (for example, after overlaying +something else on part of it), the @option{hwmap} filter can be used again +in the next mode to retrieve it. +@item +Normal frame input, hardware frame output + +If the input is actually a software-mapped hardware frame, then unmap it - +that is, return the original hardware frame. + +Otherwise, a device must be provided. Create new hardware surfaces on that +device for the output, then map them back to the software format at the input +and give those frames to the preceding filter. This will then act like the +@option{hwupload} filter, but may be able to avoid an additional copy when +the input is already in a compatible format. +@item +Hardware frame input and output + +A device must be supplied for the output, either directly or with the +@option{derive_device} option. The input and output devices must be of +different types and compatible - the exact meaning of this is +system-dependent, but typically it means that they must refer to the same +underlying hardware context (for example, refer to the same graphics card). + +If the input frames were originally created on the output device, then unmap +to retrieve the original frames. + +Otherwise, map the frames to the output device - create new hardware frames +on the output corresponding to the frames on the input. +@end itemize + +The following additional parameters are accepted: + +@table @option +@item mode +Set the frame mapping mode. Some combination of: +@table @var +@item read +The mapped frame should be readable. +@item write +The mapped frame should be writeable. +@item overwrite +The mapping will always overwrite the entire frame. + +This may improve performance in some cases, as the original contents of the +frame need not be loaded. +@item direct +The mapping must not involve any copying. + +Indirect mappings to copies of frames are created in some cases where either +direct mapping is not possible or it would have unexpected properties. +Setting this flag ensures that the mapping is direct and will fail if that is +not possible. +@end table +Defaults to @var{read+write} if not specified. + +@item derive_device @var{type} +Rather than using the device supplied at initialisation, instead derive a new +device of type @var{type} from the device the input frames exist on. + +@item reverse +In a hardware to hardware mapping, map in reverse - create frames in the sink +and map them back to the source. This may be necessary in some cases where +a mapping in one direction is required but only the opposite direction is +supported by the devices being used. + +This option is dangerous - it may break the preceding filter in undefined +ways if there are any additional constraints on that filter's output. +Do not use it without fully understanding the implications of its use. +@end table + +@section hwupload + +Upload system memory frames to hardware surfaces. + +The device to upload to must be supplied when the filter is initialised. If +using avconv, select the appropriate device with the @option{-filter_hw_device} +option. + @section hwupload_cuda Upload system memory frames to a CUDA device. From 6ea220cbeec8863e2006a03b73bed52db2b13ee7 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 15 May 2017 22:42:14 +0100 Subject: [PATCH 0223/2557] h264_sei: Add namespace prefix to all SEI values This avoids confusion with equivalent H.265 SEI values when both are being used at the same time. --- libavcodec/h264_parser.c | 26 +++++++++++------------ libavcodec/h264_sei.c | 16 +++++++------- libavcodec/h264_sei.h | 39 +++++++++++++++++----------------- libavcodec/h264_slice.c | 24 ++++++++++----------- libavcodec/vaapi_encode_h264.c | 6 +++--- 5 files changed, 56 insertions(+), 55 deletions(-) diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index 22153bd4e0207..0bb78e09c8cbc 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -404,23 +404,23 @@ static inline int parse_nal_units(AVCodecParserContext *s, if (sps->pic_struct_present_flag && p->sei.picture_timing.present) { switch (p->sei.picture_timing.pic_struct) { - case SEI_PIC_STRUCT_TOP_FIELD: - case SEI_PIC_STRUCT_BOTTOM_FIELD: + case H264_SEI_PIC_STRUCT_TOP_FIELD: + case H264_SEI_PIC_STRUCT_BOTTOM_FIELD: s->repeat_pict = 0; break; - case SEI_PIC_STRUCT_FRAME: - case SEI_PIC_STRUCT_TOP_BOTTOM: - case SEI_PIC_STRUCT_BOTTOM_TOP: + case H264_SEI_PIC_STRUCT_FRAME: + case H264_SEI_PIC_STRUCT_TOP_BOTTOM: + case H264_SEI_PIC_STRUCT_BOTTOM_TOP: s->repeat_pict = 1; break; - case SEI_PIC_STRUCT_TOP_BOTTOM_TOP: - case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: + case H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP: + case H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: s->repeat_pict = 2; break; - case SEI_PIC_STRUCT_FRAME_DOUBLING: + case H264_SEI_PIC_STRUCT_FRAME_DOUBLING: s->repeat_pict = 3; break; - case SEI_PIC_STRUCT_FRAME_TRIPLING: + case H264_SEI_PIC_STRUCT_FRAME_TRIPLING: s->repeat_pict = 5; break; default: @@ -435,12 +435,12 @@ static inline int parse_nal_units(AVCodecParserContext *s, s->picture_structure = AV_PICTURE_STRUCTURE_FRAME; if (sps->pic_struct_present_flag && p->sei.picture_timing.present) { switch (p->sei.picture_timing.pic_struct) { - case SEI_PIC_STRUCT_TOP_BOTTOM: - case SEI_PIC_STRUCT_TOP_BOTTOM_TOP: + case H264_SEI_PIC_STRUCT_TOP_BOTTOM: + case H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP: s->field_order = AV_FIELD_TT; break; - case SEI_PIC_STRUCT_BOTTOM_TOP: - case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: + case H264_SEI_PIC_STRUCT_BOTTOM_TOP: + case H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: s->field_order = AV_FIELD_BB; break; default: diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c index 17f89cec61606..3ca2b7a6cd730 100644 --- a/libavcodec/h264_sei.c +++ b/libavcodec/h264_sei.c @@ -71,7 +71,7 @@ static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb, h->pic_struct = get_bits(gb, 4); h->ct_type = 0; - if (h->pic_struct > SEI_PIC_STRUCT_FRAME_TRIPLING) + if (h->pic_struct > H264_SEI_PIC_STRUCT_FRAME_TRIPLING) return AVERROR_INVALIDDATA; num_clock_ts = sei_num_clock_ts_table[h->pic_struct]; @@ -375,25 +375,25 @@ int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb, } switch (type) { - case SEI_TYPE_PIC_TIMING: // Picture timing SEI + case H264_SEI_TYPE_PIC_TIMING: // Picture timing SEI ret = decode_picture_timing(&h->picture_timing, gb, ps->sps, logctx); break; - case SEI_TYPE_USER_DATA_REGISTERED: + case H264_SEI_TYPE_USER_DATA_REGISTERED: ret = decode_registered_user_data(h, gb, logctx, size); break; - case SEI_TYPE_USER_DATA_UNREGISTERED: + case H264_SEI_TYPE_USER_DATA_UNREGISTERED: ret = decode_unregistered_user_data(&h->unregistered, gb, logctx, size); break; - case SEI_TYPE_RECOVERY_POINT: + case H264_SEI_TYPE_RECOVERY_POINT: ret = decode_recovery_point(&h->recovery_point, gb); break; - case SEI_TYPE_BUFFERING_PERIOD: + case H264_SEI_TYPE_BUFFERING_PERIOD: ret = decode_buffering_period(&h->buffering_period, gb, ps, logctx); break; - case SEI_TYPE_FRAME_PACKING: + case H264_SEI_TYPE_FRAME_PACKING: ret = decode_frame_packing_arrangement(&h->frame_packing, gb); break; - case SEI_TYPE_DISPLAY_ORIENTATION: + case H264_SEI_TYPE_DISPLAY_ORIENTATION: ret = decode_display_orientation(&h->display_orientation, gb); break; default: diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h index 8815aa3899ff0..ce9768ec3de32 100644 --- a/libavcodec/h264_sei.h +++ b/libavcodec/h264_sei.h @@ -25,33 +25,34 @@ * SEI message types */ typedef enum { - SEI_TYPE_BUFFERING_PERIOD = 0, ///< buffering period (H.264, D.1.1) - SEI_TYPE_PIC_TIMING = 1, ///< picture timing - SEI_TYPE_USER_DATA_REGISTERED = 4, ///< registered user data as specified by Rec. ITU-T T.35 - SEI_TYPE_USER_DATA_UNREGISTERED = 5, ///< unregistered user data - SEI_TYPE_RECOVERY_POINT = 6, ///< recovery point (frame # to decoder sync) - SEI_TYPE_FRAME_PACKING = 45, ///< frame packing arrangement - SEI_TYPE_DISPLAY_ORIENTATION = 47, ///< display orientation -} SEI_Type; + H264_SEI_TYPE_BUFFERING_PERIOD = 0, ///< buffering period (H.264, D.1.1) + H264_SEI_TYPE_PIC_TIMING = 1, ///< picture timing + H264_SEI_TYPE_FILLER_PAYLOAD = 3, ///< filler data + H264_SEI_TYPE_USER_DATA_REGISTERED = 4, ///< registered user data as specified by Rec. ITU-T T.35 + H264_SEI_TYPE_USER_DATA_UNREGISTERED = 5, ///< unregistered user data + H264_SEI_TYPE_RECOVERY_POINT = 6, ///< recovery point (frame # to decoder sync) + H264_SEI_TYPE_FRAME_PACKING = 45, ///< frame packing arrangement + H264_SEI_TYPE_DISPLAY_ORIENTATION = 47, ///< display orientation +} H264_SEI_Type; /** * pic_struct in picture timing SEI message */ typedef enum { - SEI_PIC_STRUCT_FRAME = 0, ///< 0: %frame - SEI_PIC_STRUCT_TOP_FIELD = 1, ///< 1: top field - SEI_PIC_STRUCT_BOTTOM_FIELD = 2, ///< 2: bottom field - SEI_PIC_STRUCT_TOP_BOTTOM = 3, ///< 3: top field, bottom field, in that order - SEI_PIC_STRUCT_BOTTOM_TOP = 4, ///< 4: bottom field, top field, in that order - SEI_PIC_STRUCT_TOP_BOTTOM_TOP = 5, ///< 5: top field, bottom field, top field repeated, in that order - SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM = 6, ///< 6: bottom field, top field, bottom field repeated, in that order - SEI_PIC_STRUCT_FRAME_DOUBLING = 7, ///< 7: %frame doubling - SEI_PIC_STRUCT_FRAME_TRIPLING = 8 ///< 8: %frame tripling -} SEI_PicStructType; + H264_SEI_PIC_STRUCT_FRAME = 0, ///< 0: %frame + H264_SEI_PIC_STRUCT_TOP_FIELD = 1, ///< 1: top field + H264_SEI_PIC_STRUCT_BOTTOM_FIELD = 2, ///< 2: bottom field + H264_SEI_PIC_STRUCT_TOP_BOTTOM = 3, ///< 3: top field, bottom field, in that order + H264_SEI_PIC_STRUCT_BOTTOM_TOP = 4, ///< 4: bottom field, top field, in that order + H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP = 5, ///< 5: top field, bottom field, top field repeated, in that order + H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM = 6, ///< 6: bottom field, top field, bottom field repeated, in that order + H264_SEI_PIC_STRUCT_FRAME_DOUBLING = 7, ///< 7: %frame doubling + H264_SEI_PIC_STRUCT_FRAME_TRIPLING = 8 ///< 8: %frame tripling +} H264_SEI_PicStructType; typedef struct H264SEIPictureTiming { int present; - SEI_PicStructType pic_struct; + H264_SEI_PicStructType pic_struct; /** * Bit set of clock types for fields/frames in picture timing SEI message. diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 427cbe618c8eb..95e366605c2cd 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1007,37 +1007,37 @@ static int h264_export_frame_props(H264Context *h) if (sps->pic_struct_present_flag && h->sei.picture_timing.present) { H264SEIPictureTiming *pt = &h->sei.picture_timing; switch (pt->pic_struct) { - case SEI_PIC_STRUCT_FRAME: + case H264_SEI_PIC_STRUCT_FRAME: break; - case SEI_PIC_STRUCT_TOP_FIELD: - case SEI_PIC_STRUCT_BOTTOM_FIELD: + case H264_SEI_PIC_STRUCT_TOP_FIELD: + case H264_SEI_PIC_STRUCT_BOTTOM_FIELD: cur->f->interlaced_frame = 1; break; - case SEI_PIC_STRUCT_TOP_BOTTOM: - case SEI_PIC_STRUCT_BOTTOM_TOP: + case H264_SEI_PIC_STRUCT_TOP_BOTTOM: + case H264_SEI_PIC_STRUCT_BOTTOM_TOP: if (FIELD_OR_MBAFF_PICTURE(h)) cur->f->interlaced_frame = 1; else // try to flag soft telecine progressive cur->f->interlaced_frame = h->prev_interlaced_frame; break; - case SEI_PIC_STRUCT_TOP_BOTTOM_TOP: - case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: + case H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP: + case H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: /* Signal the possibility of telecined film externally * (pic_struct 5,6). From these hints, let the applications * decide if they apply deinterlacing. */ cur->f->repeat_pict = 1; break; - case SEI_PIC_STRUCT_FRAME_DOUBLING: + case H264_SEI_PIC_STRUCT_FRAME_DOUBLING: cur->f->repeat_pict = 2; break; - case SEI_PIC_STRUCT_FRAME_TRIPLING: + case H264_SEI_PIC_STRUCT_FRAME_TRIPLING: cur->f->repeat_pict = 4; break; } if ((pt->ct_type & 3) && - pt->pic_struct <= SEI_PIC_STRUCT_BOTTOM_TOP) + pt->pic_struct <= H264_SEI_PIC_STRUCT_BOTTOM_TOP) cur->f->interlaced_frame = (pt->ct_type & (1 << 1)) != 0; } else { /* Derive interlacing flag from used decoding process. */ @@ -1053,8 +1053,8 @@ static int h264_export_frame_props(H264Context *h) (sps->pic_struct_present_flag && h->sei.picture_timing.present)) { /* Use picture timing SEI information. Even if it is a * information of a past frame, better than nothing. */ - if (h->sei.picture_timing.pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM || - h->sei.picture_timing.pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM_TOP) + if (h->sei.picture_timing.pic_struct == H264_SEI_PIC_STRUCT_TOP_BOTTOM || + h->sei.picture_timing.pic_struct == H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP) cur->f->top_field_first = 1; else cur->f->top_field_first = 0; diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 0c3ac34411db7..7583a20c149c6 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -650,18 +650,18 @@ static void vaapi_encode_h264_write_sei(PutBitContext *pbc, for (payload_type = 0; payload_type < 64; payload_type++) { switch (payload_type) { - case SEI_TYPE_BUFFERING_PERIOD: + case H264_SEI_TYPE_BUFFERING_PERIOD: if (!priv->send_timing_sei || pic->type != PICTURE_TYPE_IDR) continue; write_payload = &vaapi_encode_h264_write_buffering_period; break; - case SEI_TYPE_PIC_TIMING: + case H264_SEI_TYPE_PIC_TIMING: if (!priv->send_timing_sei) continue; write_payload = &vaapi_encode_h264_write_pic_timing; break; - case SEI_TYPE_USER_DATA_UNREGISTERED: + case H264_SEI_TYPE_USER_DATA_UNREGISTERED: if (pic->encode_order != 0) continue; write_payload = &vaapi_encode_h264_write_identifier; From 4d56f7ab8f627aa140c1ede1bb61305f01cefcdd Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 4 May 2017 23:01:23 +0100 Subject: [PATCH 0224/2557] avconv: Flush output BSFs when stream copy reaches EOF Same as f64d1100a54d12c78ce436181bb64229c56da6b3, for stream copy rather than encode. --- avtools/avconv.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/avtools/avconv.c b/avtools/avconv.c index 2e218e96c75cb..719d289ff9b29 100644 --- a/avtools/avconv.c +++ b/avtools/avconv.c @@ -1127,6 +1127,12 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); AVPacket opkt; + // EOF: flush output bitstream filters. + if (!pkt) { + output_packet(of, &opkt, ost, 1); + return; + } + av_init_packet(&opkt); if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && @@ -1590,7 +1596,7 @@ static void process_input_packet(InputStream *ist, const AVPacket *pkt, int no_e break; } } - for (i = 0; pkt && i < nb_output_streams; i++) { + for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; if (!check_output_constraints(ist, ost) || ost->encoding_needed) @@ -2779,7 +2785,7 @@ static int transcode(void) /* at the end of stream, we must flush the decoder buffers */ for (i = 0; i < nb_input_streams; i++) { ist = input_streams[i]; - if (!input_files[ist->file_index]->eof_reached && ist->decoding_needed) { + if (!input_files[ist->file_index]->eof_reached) { process_input_packet(ist, NULL, 0); } } From 3daaa4417317ca732fb00476fdb3308d784f87e4 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 14 May 2017 15:47:36 +0100 Subject: [PATCH 0225/2557] hevc: Add names for reserved NAL unit types While not yet used, these NAL units do already have some defined semantics and are referred to elsewhere. --- libavcodec/hevc.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index bb4f6605866a2..9d956d0838206 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -35,12 +35,28 @@ enum HEVCNALUnitType { HEVC_NAL_RADL_R = 7, HEVC_NAL_RASL_N = 8, HEVC_NAL_RASL_R = 9, + HEVC_NAL_VCL_N10 = 10, + HEVC_NAL_VCL_R11 = 11, + HEVC_NAL_VCL_N12 = 12, + HEVC_NAL_VCL_R13 = 13, + HEVC_NAL_VCL_N14 = 14, + HEVC_NAL_VCL_R15 = 15, HEVC_NAL_BLA_W_LP = 16, HEVC_NAL_BLA_W_RADL = 17, HEVC_NAL_BLA_N_LP = 18, HEVC_NAL_IDR_W_RADL = 19, HEVC_NAL_IDR_N_LP = 20, HEVC_NAL_CRA_NUT = 21, + HEVC_NAL_IRAP_VCL22 = 22, + HEVC_NAL_IRAP_VCL23 = 23, + HEVC_NAL_RSV_VCL24 = 24, + HEVC_NAL_RSV_VCL25 = 25, + HEVC_NAL_RSV_VCL26 = 26, + HEVC_NAL_RSV_VCL27 = 27, + HEVC_NAL_RSV_VCL28 = 28, + HEVC_NAL_RSV_VCL29 = 29, + HEVC_NAL_RSV_VCL30 = 30, + HEVC_NAL_RSV_VCL31 = 31, HEVC_NAL_VPS = 32, HEVC_NAL_SPS = 33, HEVC_NAL_PPS = 34, From 8652a2c24836ce5546b398f12b7fed45000050e1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 19 May 2017 11:47:21 +0200 Subject: [PATCH 0226/2557] decode: fix the code reducing cropping to preserve alignment Currently it does not work at all. Bug-Id: 1058 --- libavcodec/decode.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 8aa27095b63b9..bb58dfc561941 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -525,6 +525,7 @@ static int apply_cropping(AVCodecContext *avctx, AVFrame *frame) /* adjust the offsets to avoid breaking alignment */ if (!(avctx->flags & AV_CODEC_FLAG_UNALIGNED)) { + int log2_crop_align = frame->crop_left ? av_ctz(frame->crop_left) : INT_MAX; int min_log2_align = INT_MAX; for (i = 0; frame->data[i]; i++) { @@ -532,8 +533,13 @@ static int apply_cropping(AVCodecContext *avctx, AVFrame *frame) min_log2_align = FFMIN(log2_align, min_log2_align); } + /* we assume, and it should always be true, that the data alignment is + * related to the cropping alignment by a constant power-of-2 factor */ + if (log2_crop_align < min_log2_align) + return AVERROR_BUG; + if (min_log2_align < 5) { - frame->crop_left &= ~((1 << min_log2_align) - 1); + frame->crop_left &= ~((1 << (5 + log2_crop_align - min_log2_align)) - 1); calc_cropping_offsets(offsets, frame, desc); } } From 126bc2c33b79c36bc23f43719d20f55b9b6771e9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 26 Apr 2017 09:25:05 +0200 Subject: [PATCH 0227/2557] vp9_superframe_bsf: convert to the new bitstream reader --- libavcodec/vp9_superframe_bsf.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/libavcodec/vp9_superframe_bsf.c b/libavcodec/vp9_superframe_bsf.c index be83ba3e75be3..869d7d4360f93 100644 --- a/libavcodec/vp9_superframe_bsf.c +++ b/libavcodec/vp9_superframe_bsf.c @@ -21,8 +21,8 @@ #include "libavutil/avassert.h" #include "avcodec.h" +#include "bitstream.h" #include "bsf.h" -#include "get_bits.h" #define MAX_CACHE 8 typedef struct VP9BSFContext { @@ -101,7 +101,7 @@ static int merge_superframe(const struct CachedBuf *in, int n_in, AVPacket *out) static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out) { - GetBitContext gb; + BitstreamContext bc; VP9BSFContext *s = ctx->priv_data; AVPacket *in; int res, invisible, profile, marker, uses_superframe_syntax = 0, n; @@ -118,19 +118,21 @@ static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out) uses_superframe_syntax = in->size >= idx_sz && in->data[in->size - idx_sz] == marker; } - if ((res = init_get_bits8(&gb, in->data, in->size)) < 0) + res = bitstream_init8(&bc, in->data, in->size); + if (res < 0) goto done; - get_bits(&gb, 2); // frame marker - profile = get_bits1(&gb); - profile |= get_bits1(&gb) << 1; - if (profile == 3) profile += get_bits1(&gb); + bitstream_read(&bc, 2); // frame marker + profile = bitstream_read(&bc, 1); + profile |= bitstream_read(&bc, 1) << 1; + if (profile == 3) + profile += bitstream_read(&bc, 1); - if (get_bits1(&gb)) { + if (bitstream_read(&bc, 1)) { invisible = 0; } else { - get_bits1(&gb); // keyframe - invisible = !get_bits1(&gb); + bitstream_read(&bc, 1); // keyframe + invisible = !bitstream_read(&bc, 1); } if (uses_superframe_syntax && s->n_cache > 0) { From 3fb6b98b5e247434456916c35ba7e08efa03e85d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 26 Apr 2017 09:42:32 +0200 Subject: [PATCH 0228/2557] vp9_superframe_bsf: cache input packets directly Avoids unnecessary allocs+copies and makes the code slightly simpler. --- libavcodec/vp9_superframe_bsf.c | 49 +++++++++++++-------------------- 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/libavcodec/vp9_superframe_bsf.c b/libavcodec/vp9_superframe_bsf.c index 869d7d4360f93..3669216009d7a 100644 --- a/libavcodec/vp9_superframe_bsf.c +++ b/libavcodec/vp9_superframe_bsf.c @@ -27,20 +27,17 @@ #define MAX_CACHE 8 typedef struct VP9BSFContext { int n_cache; - struct CachedBuf { - uint8_t *data; - int size; - } cache[MAX_CACHE]; + AVPacket *cache[MAX_CACHE]; } VP9BSFContext; -static void stats(const struct CachedBuf *in, int n_in, +static void stats(AVPacket * const *in, int n_in, unsigned *_max, unsigned *_sum) { int n; unsigned max = 0, sum = 0; for (n = 0; n < n_in; n++) { - unsigned sz = in[n].size; + unsigned sz = in[n]->size; if (sz > max) max = sz; @@ -51,7 +48,7 @@ static void stats(const struct CachedBuf *in, int n_in, *_sum = sum; } -static int merge_superframe(const struct CachedBuf *in, int n_in, AVPacket *out) +static int merge_superframe(AVPacket * const *in, int n_in, AVPacket *out) { unsigned max, sum, mag, marker, n, sz; uint8_t *ptr; @@ -66,8 +63,8 @@ static int merge_superframe(const struct CachedBuf *in, int n_in, AVPacket *out) return res; ptr = out->data; for (n = 0; n < n_in; n++) { - memcpy(ptr, in[n].data, in[n].size); - ptr += in[n].size; + memcpy(ptr, in[n]->data, in[n]->size); + ptr += in[n]->size; } #define wloop(mag, wr) do { \ @@ -81,16 +78,16 @@ static int merge_superframe(const struct CachedBuf *in, int n_in, AVPacket *out) *ptr++ = marker; switch (mag) { case 0: - wloop(mag, *ptr = in[n].size); + wloop(mag, *ptr = in[n]->size); break; case 1: - wloop(mag, AV_WL16(ptr, in[n].size)); + wloop(mag, AV_WL16(ptr, in[n]->size)); break; case 2: - wloop(mag, AV_WL24(ptr, in[n].size)); + wloop(mag, AV_WL24(ptr, in[n]->size)); break; case 3: - wloop(mag, AV_WL32(ptr, in[n].size)); + wloop(mag, AV_WL32(ptr, in[n]->size)); break; } *ptr++ = marker; @@ -151,34 +148,26 @@ static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out) goto done; } + s->cache[s->n_cache++] = in; + in = NULL; if (invisible) { - s->cache[s->n_cache].data = av_malloc(in->size); - if (!s->cache[s->n_cache].data) { - res = AVERROR(ENOMEM); - goto done; - } - memcpy(s->cache[s->n_cache].data, in->data, in->size); - s->cache[s->n_cache++].size = in->size; res = AVERROR(EAGAIN); goto done; } av_assert0(s->n_cache > 0); - s->cache[s->n_cache].data = in->data; - s->cache[s->n_cache].size = in->size; - // build superframe - if ((res = merge_superframe(s->cache, s->n_cache + 1, out)) < 0) + if ((res = merge_superframe(s->cache, s->n_cache, out)) < 0) goto done; - for (n = 0; n < s->n_cache; n++) - av_freep(&s->cache[n].data); - s->n_cache = 0; - - res = av_packet_copy_props(out, in); + res = av_packet_copy_props(out, s->cache[s->n_cache - 1]); if (res < 0) goto done; + for (n = 0; n < s->n_cache; n++) + av_packet_free(&s->cache[n]); + s->n_cache = 0; + done: if (res < 0) av_packet_unref(out); @@ -193,7 +182,7 @@ static void vp9_superframe_close(AVBSFContext *ctx) // free cached data for (n = 0; n < s->n_cache; n++) - av_freep(&s->cache[n].data); + av_packet_free(&s->cache[n]); } static const enum AVCodecID codec_ids[] = { From d7dcd825dea3681c69a35b3147a3b42f1bf078dd Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 14 Apr 2017 10:53:52 -0300 Subject: [PATCH 0229/2557] extract_extradata_bsf: make sure all needed parameter set NALUs were found This mimics the behavior of the now unused h264/hevc parser's split() function and fixes decoding some files when extract_extradata bsf is enabled. Signed-off-by: James Almer Signed-off-by: Anton Khirnov --- libavcodec/extract_extradata_bsf.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c index 20b30803b8c76..20840bd6af629 100644 --- a/libavcodec/extract_extradata_bsf.c +++ b/libavcodec/extract_extradata_bsf.c @@ -65,7 +65,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, int extradata_size = 0; const int *extradata_nal_types; int nb_extradata_nal_types; - int i, ret = 0; + int i, has_sps = 0, has_vps = 0, ret = 0; if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { extradata_nal_types = extradata_nal_types_hevc; @@ -82,11 +82,20 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, for (i = 0; i < h2645_pkt.nb_nals; i++) { H2645NAL *nal = &h2645_pkt.nals[i]; - if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) + if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { extradata_size += nal->raw_size + 3; + if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { + if (nal->type == HEVC_NAL_SPS) has_sps = 1; + if (nal->type == HEVC_NAL_VPS) has_vps = 1; + } else { + if (nal->type == H264_NAL_SPS) has_sps = 1; + } + } } - if (extradata_size) { + if (extradata_size && + ((ctx->par_in->codec_id == AV_CODEC_ID_HEVC && has_sps && has_vps) || + (ctx->par_in->codec_id == AV_CODEC_ID_H264 && has_sps))) { AVBufferRef *filtered_buf; uint8_t *extradata, *filtered_data; From c3f0357bdf7d3c542aad2c58b94184b9f56edc41 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 12 May 2017 16:36:41 +0200 Subject: [PATCH 0230/2557] hevcdec: move the MD5 context out of HEVCSEIPictureHash back into HEVCContext HEVCSEIPictureHash should store only the information extracted from the bitstream and exported to the higher layer (the decoder or the parser). The MD5 context is allocated, used and freed by this higher layer, so it makes more sense for it to also be stored there. --- libavcodec/hevc_sei.h | 3 --- libavcodec/hevcdec.c | 12 ++++++------ libavcodec/hevcdec.h | 2 ++ 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/libavcodec/hevc_sei.h b/libavcodec/hevc_sei.h index bdc283adb48fd..b699fef45dc22 100644 --- a/libavcodec/hevc_sei.h +++ b/libavcodec/hevc_sei.h @@ -23,8 +23,6 @@ #include -#include "libavutil/md5.h" - #include "get_bits.h" /** @@ -59,7 +57,6 @@ typedef enum { } HEVC_SEI_Type; typedef struct HEVCSEIPictureHash { - struct AVMD5 *md5_ctx; uint8_t md5[3][16]; uint8_t is_md5; } HEVCSEIPictureHash; diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 96e47cd1875d0..69d5908551949 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2683,7 +2683,7 @@ static int verify_md5(HEVCContext *s, AVFrame *frame) int h = (i == 1 || i == 2) ? (height >> desc->log2_chroma_h) : height; uint8_t md5[16]; - av_md5_init(s->sei.picture_hash.md5_ctx); + av_md5_init(s->md5_ctx); for (j = 0; j < h; j++) { const uint8_t *src = frame->data[i] + j * frame->linesize[i]; #if HAVE_BIGENDIAN @@ -2693,9 +2693,9 @@ static int verify_md5(HEVCContext *s, AVFrame *frame) src = s->checksum_buf; } #endif - av_md5_update(s->sei.picture_hash.md5_ctx, src, w << pixel_shift); + av_md5_update(s->md5_ctx, src, w << pixel_shift); } - av_md5_final(s->sei.picture_hash.md5_ctx, md5); + av_md5_final(s->md5_ctx, md5); if (!memcmp(md5, s->sei.picture_hash.md5[i], 16)) { av_log (s->avctx, AV_LOG_DEBUG, "plane %d - correct ", i); @@ -2893,7 +2893,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) pic_arrays_free(s); - av_freep(&s->sei.picture_hash.md5_ctx); + av_freep(&s->md5_ctx); av_frame_free(&s->tmp_frame); av_frame_free(&s->output_frame); @@ -2939,8 +2939,8 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) s->max_ra = INT_MAX; - s->sei.picture_hash.md5_ctx = av_md5_alloc(); - if (!s->sei.picture_hash.md5_ctx) + s->md5_ctx = av_md5_alloc(); + if (!s->md5_ctx) goto fail; ff_bswapdsp_init(&s->bdsp); diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index f2c589217f1f6..7adb826e722a8 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -27,6 +27,7 @@ #include #include "libavutil/buffer.h" +#include "libavutil/md5.h" #include "avcodec.h" #include "bswapdsp.h" @@ -462,6 +463,7 @@ typedef struct HEVCContext { HEVCParamSets ps; HEVCSEI sei; + struct AVMD5 *md5_ctx; AVBufferPool *tab_mvf_pool; AVBufferPool *rpl_tab_pool; From 3d040513a1de4797a4f81dde4984395f51db76b7 Mon Sep 17 00:00:00 2001 From: Aaron Levinson Date: Tue, 16 May 2017 14:23:27 -0700 Subject: [PATCH 0231/2557] avutil/hwcontext_dxva2: Don't improperly free IDirect3DSurface9 objects Add dxva2_pool_release_dummy() and use it in call to av_buffer_create() in dxva2_pool_alloc(). Prior to this change, av_buffer_create() was called with NULL for the third argument, which indicates that av_buffer_default_free() should be used to free the buffer's data. Eventually, it gets to buffer_pool_free() and calls buf->free() on a surface object (which is av_buffer_default_free()). This can result in a crash when the debug version of the C-runtime is used on Windows. While it doesn't appear to result in a crash when the release version of the C-runtime is used on Windows, it likely results in memory corruption, since av_free() is being called on memory that was allocated using IDirectXVideoAccelerationService::CreateSurface(). Signed-off-by: Aaron Levinson Reviewed-by: wm4 Reviewed-by: Steven Liu Reviewed-by: Mark Thompson Signed-off-by: Anton Khirnov --- libavutil/hwcontext_dxva2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_dxva2.c b/libavutil/hwcontext_dxva2.c index 3790bed4b748a..d1b19ab237faa 100644 --- a/libavutil/hwcontext_dxva2.c +++ b/libavutil/hwcontext_dxva2.c @@ -119,6 +119,13 @@ static void dxva2_frames_uninit(AVHWFramesContext *ctx) } } +static void dxva2_pool_release_dummy(void *opaque, uint8_t *data) +{ + // important not to free anything here--data is a surface object + // associated with the call to CreateSurface(), and these surfaces are + // released in dxva2_frames_uninit() +} + static AVBufferRef *dxva2_pool_alloc(void *opaque, int size) { AVHWFramesContext *ctx = (AVHWFramesContext*)opaque; @@ -128,7 +135,7 @@ static AVBufferRef *dxva2_pool_alloc(void *opaque, int size) if (s->nb_surfaces_used < hwctx->nb_surfaces) { s->nb_surfaces_used++; return av_buffer_create((uint8_t*)s->surfaces_internal[s->nb_surfaces_used - 1], - sizeof(*hwctx->surfaces), NULL, 0, 0); + sizeof(*hwctx->surfaces), dxva2_pool_release_dummy, 0, 0); } return NULL; From 6a7e928555d081ff86c867867ebce74fdc4c87d6 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Wed, 10 May 2017 17:18:48 +0200 Subject: [PATCH 0232/2557] configure: Do not check for the __builtin_vec_vsx_ld Clang support for Altivec/VSX uses a different approach. --- configure | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/configure b/configure index d6c44cf89e332..be52d4df92cd4 100755 --- a/configure +++ b/configure @@ -4447,7 +4447,14 @@ EOF if enabled vsx; then check_cflags -mvsx && - check_builtin vec_vsx_ld "altivec.h" "__builtin_vec_vsx_ld" || disable vsx + check_cc < Date: Wed, 24 May 2017 14:33:08 +0200 Subject: [PATCH 0233/2557] vaapi: Add ABGR map only if VA_FOURCC_ABGR is defined Signed-off-by: Luca Barbato --- libavutil/hwcontext_vaapi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 23bce76605025..2260518ca6e4a 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -107,8 +107,10 @@ static const struct { //MAP(BGRX, RGB32, BGR0), MAP(RGBA, RGB32, RGBA), //MAP(RGBX, RGB32, RGB0), +#ifdef VA_FOURCC_ABGR MAP(ABGR, RGB32, ABGR), //MAP(XBGR, RGB32, 0BGR), +#endif MAP(ARGB, RGB32, ARGB), //MAP(XRGB, RGB32, 0RGB), }; From 427f7a1f9ec1977bcb57cb4d6e6f7228dc1e858b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 31 May 2017 12:53:32 +0300 Subject: [PATCH 0234/2557] configure: Fix the msvcrt version check for mingw32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was actually broken when committed in 46e3936fb04; the test never succeeded, and thus, _aligned_malloc wasn't actually used on legacy mingw. Signed-off-by: Martin Storsjö --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index be52d4df92cd4..fb3920a26156e 100755 --- a/configure +++ b/configure @@ -4131,7 +4131,7 @@ probe_libc(){ (__MINGW32_MAJOR_VERSION == 3 && __MINGW32_MINOR_VERSION >= 15)" || die "ERROR: MinGW32 runtime version must be >= 3.15." add_${pfx}cppflags -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO=1 - check_${pfx}cpp_condition _mingw.h "__MSVCRT_VERSION__ < 0x0700__" && + check_${pfx}cpp_condition _mingw.h "__MSVCRT_VERSION__ < 0x0700" && add_${pfx}cppflags -D__MSVCRT_VERSION__=0x0700 eval test \$${pfx_no_}cc_type = "gcc" && add_${pfx}cppflags -D__printf__=__gnu_printf__ From 91622f6446b463abe6507ad2cd5d1fbf7e49c424 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 29 May 2017 13:55:28 +0200 Subject: [PATCH 0235/2557] avconv: Always initialize the opkt struct on streamcopy --- avtools/avconv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/avtools/avconv.c b/avtools/avconv.c index 719d289ff9b29..8dd11bb5fc47d 100644 --- a/avtools/avconv.c +++ b/avtools/avconv.c @@ -1125,7 +1125,9 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p InputFile *f = input_files [ist->file_index]; int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); - AVPacket opkt; + AVPacket opkt = { 0 }; + + av_init_packet(&opkt); // EOF: flush output bitstream filters. if (!pkt) { @@ -1133,8 +1135,6 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p return; } - av_init_packet(&opkt); - if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !ost->copy_initial_nonkeyframes) return; From 16cb06bb30390c3d74312fc6aead818e19bfd8e4 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 19 May 2017 20:32:47 +0200 Subject: [PATCH 0236/2557] hlsenc: Support recovery from an already present playlist Parse the playlist to recover the start sequence and previously generated segments and continue muxing from there. Mainly useful for near-seamless recovery in live scenarios. --- libavformat/hlsenc.c | 95 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 10 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 7aef02b80549d..c84dd82e7da53 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -119,7 +119,7 @@ static int setup_encryption(AVFormatContext *s) AVIOContext *out = NULL; int len, ret; uint8_t buf[16]; - uint8_t *k; + uint8_t *k = NULL; len = strlen(hls->basename) + 4 + 1; hls->key_basename = av_mallocz(len); @@ -141,9 +141,22 @@ static int setup_encryption(AVFormatContext *s) return ret; k = hls->key; } else { - if ((ret = randomize(buf, sizeof(buf))) < 0) { - av_log(s, AV_LOG_ERROR, "Cannot generate a strong random key\n"); - return ret; + if (hls->start_sequence < 0) { + ret = s->io_open(s, &out, hls->key_basename, AVIO_FLAG_READ, NULL); + if (ret < 0) { + av_log(s, AV_LOG_WARNING, + "Cannot recover the key, generating a new one.\n"); + } else { + avio_read(out, buf, 16); + k = buf; + avio_close(out); + } + } + if (!k) { + if ((ret = randomize(buf, sizeof(buf))) < 0) { + av_log(s, AV_LOG_ERROR, "Cannot generate a strong random key\n"); + return ret; + } } if ((ret = dict_set_bin(&hls->enc_opts, "key", buf, sizeof(buf))) < 0) @@ -201,14 +214,14 @@ static int hls_mux_init(AVFormatContext *s) return 0; } -static int append_entry(HLSContext *hls, int64_t duration) +static int append_entry(HLSContext *hls, int64_t duration, const char *name) { ListEntry *en = av_malloc(sizeof(*en)); if (!en) return AVERROR(ENOMEM); - av_strlcpy(en->name, av_basename(hls->avf->filename), sizeof(en->name)); + av_strlcpy(en->name, name, sizeof(en->name)); en->duration = duration; en->next = NULL; @@ -356,12 +369,67 @@ static int hls_start(AVFormatContext *s) return err; } +static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) +{ + int len = ff_get_line(s, buf, maxlen); + while (len > 0 && av_isspace(buf[len - 1])) + buf[--len] = '\0'; + return len; +} + +static int hls_recover(AVFormatContext *s) +{ + HLSContext *hls = s->priv_data; + char line[1024]; + AVIOContext *io; + const char *ptr; + int ret, is_segment = 0; + int64_t duration = 0; + + ret = s->io_open(s, &io, s->filename, AVIO_FLAG_READ, NULL); + if (ret < 0) { + av_log(s, AV_LOG_WARNING, + "Cannot recover the playlist, generating a new one.\n"); + hls->start_sequence = 0; + hls->sequence = 0; + return 0; + } + + read_chomp_line(io, line, sizeof(line)); + if (strcmp(line, "#EXTM3U")) { + av_log(s, AV_LOG_ERROR, + "The playlist file is present but unparsable." + " Please remove it.\n"); + return AVERROR_INVALIDDATA; + } + + while (!io->eof_reached) { + read_chomp_line(io, line, sizeof(line)); + if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) { + hls->sequence = hls->start_sequence = atoi(ptr); + } else if (av_strstart(line, "#EXTINF:", &ptr)) { + is_segment = 1; + duration = atof(ptr) * AV_TIME_BASE; + } else if (av_strstart(line, "#", NULL)) { + continue; + } else if (line[0]) { + if (is_segment) { + append_entry(hls, duration, av_basename(line)); + is_segment = 0; + } + } + } + + return 0; +} + static int hls_setup(AVFormatContext *s) { HLSContext *hls = s->priv_data; const char *pattern = "%d.ts"; int basename_size = strlen(s->filename) + strlen(pattern) + 1; char *p; + int ret; if (hls->encrypt) basename_size += 7; @@ -382,7 +450,13 @@ static int hls_setup(AVFormatContext *s) *p = '\0'; if (hls->encrypt) { - int ret = setup_encryption(s); + ret = setup_encryption(s); + if (ret < 0) + return ret; + } + + if (hls->start_sequence < 0) { + ret = hls_recover(s); if (ret < 0) return ret; } @@ -465,7 +539,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) hls->duration = pts - hls->end_pts; if (can_split && pts - hls->start_pts >= end_pts) { - ret = append_entry(hls, hls->duration); + ret = append_entry(hls, hls->duration, av_basename(hls->avf->filename)); if (ret) return ret; @@ -500,7 +574,7 @@ static int hls_write_trailer(struct AVFormatContext *s) ff_format_io_close(s, &oc->pb); avformat_free_context(oc); av_free(hls->basename); - append_entry(hls, hls->duration); + append_entry(hls, hls->duration, av_basename(hls->avf->filename)); hls_window(s, 1); free_entries(hls); @@ -511,7 +585,8 @@ static int hls_write_trailer(struct AVFormatContext *s) #define OFFSET(x) offsetof(HLSContext, x) #define E AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - {"start_number", "first number in the sequence", OFFSET(start_sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E}, + {"start_number", "first number in the sequence", OFFSET(start_sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, -1, INT64_MAX, E, "start_number"}, + {"recover", "If there is already a m3u8 file in the path, populate the sequence from it", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, E, "start_number"}, {"hls_time", "segment length in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E}, {"hls_list_size", "maximum number of playlist entries", OFFSET(size), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E}, {"hls_wrap", "number after which the index wraps", OFFSET(wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E}, From 4d444d04c1e19cd02ac836d411433906a9f32613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 31 May 2017 13:07:04 +0300 Subject: [PATCH 0237/2557] configure: Default to _WIN32_WINNT=0x0502 (XP) as minimum, for legacy mingw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes the getaddrinfo functions visible, which aren't normally by default on legacy mingw. We already force __MSVCRT_VERSION__ to an XP version. Signed-off-by: Martin Storsjö --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index fb3920a26156e..f86ca158c9430 100755 --- a/configure +++ b/configure @@ -4133,6 +4133,8 @@ probe_libc(){ add_${pfx}cppflags -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO=1 check_${pfx}cpp_condition _mingw.h "__MSVCRT_VERSION__ < 0x0700" && add_${pfx}cppflags -D__MSVCRT_VERSION__=0x0700 + check_${pfx}cpp_condition windows.h "defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0502" && + add_${pfx}cppflags -D_WIN32_WINNT=0x0502 eval test \$${pfx_no_}cc_type = "gcc" && add_${pfx}cppflags -D__printf__=__gnu_printf__ elif check_${pfx}cpp_condition crtversion.h "defined _VC_CRT_MAJOR_VERSION"; then From 2ca759657bcda328acc312e5882a940333a3e268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 31 May 2017 13:08:29 +0300 Subject: [PATCH 0238/2557] os_support: Remove the dynamic loading of getaddrinfo from the fallback getaddrinfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we for some unexplicable reason didn't pick up getaddrinfo at configure, the default, IPv4-only, fallback should be good enough. This effectively reverts 6023d84a2b7. Signed-off-by: Martin Storsjö --- libavformat/os_support.c | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/libavformat/os_support.c b/libavformat/os_support.c index e9b1f88fb8efe..6a0c1fa7fcc7e 100644 --- a/libavformat/os_support.c +++ b/libavformat/os_support.c @@ -74,16 +74,6 @@ int ff_getaddrinfo(const char *node, const char *service, struct addrinfo *ai; struct sockaddr_in *sin; -#if HAVE_WINSOCK2_H - int (WSAAPI *win_getaddrinfo)(const char *node, const char *service, - const struct addrinfo *hints, - struct addrinfo **res); - HMODULE ws2mod = GetModuleHandle("ws2_32.dll"); - win_getaddrinfo = GetProcAddress(ws2mod, "getaddrinfo"); - if (win_getaddrinfo) - return win_getaddrinfo(node, service, hints, res); -#endif /* HAVE_WINSOCK2_H */ - *res = NULL; sin = av_mallocz(sizeof(struct sockaddr_in)); if (!sin) @@ -147,17 +137,6 @@ int ff_getaddrinfo(const char *node, const char *service, void ff_freeaddrinfo(struct addrinfo *res) { -#if HAVE_WINSOCK2_H - void (WSAAPI *win_freeaddrinfo)(struct addrinfo *res); - HMODULE ws2mod = GetModuleHandle("ws2_32.dll"); - win_freeaddrinfo = (void (WSAAPI *)(struct addrinfo *res)) - GetProcAddress(ws2mod, "freeaddrinfo"); - if (win_freeaddrinfo) { - win_freeaddrinfo(res); - return; - } -#endif /* HAVE_WINSOCK2_H */ - av_free(res->ai_canonname); av_free(res->ai_addr); av_free(res); @@ -169,16 +148,6 @@ int ff_getnameinfo(const struct sockaddr *sa, int salen, { const struct sockaddr_in *sin = (const struct sockaddr_in *)sa; -#if HAVE_WINSOCK2_H - int (WSAAPI *win_getnameinfo)(const struct sockaddr *sa, socklen_t salen, - char *host, DWORD hostlen, - char *serv, DWORD servlen, int flags); - HMODULE ws2mod = GetModuleHandle("ws2_32.dll"); - win_getnameinfo = GetProcAddress(ws2mod, "getnameinfo"); - if (win_getnameinfo) - return win_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); -#endif /* HAVE_WINSOCK2_H */ - if (sa->sa_family != AF_INET) return EAI_FAMILY; if (!host && !serv) From b98f082d8ddc0a0d8317114d8414ab51de60ef02 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 15 Nov 2015 14:52:08 +0100 Subject: [PATCH 0239/2557] smacker: Check that the data size is a multiple of a sample vector Fixes out of array access Fixes: ce19e41f0ef1e52a23edc488faecdb58/asan_heap-oob_2504e97_4202_ffa0df1baed14022b9bfd4f8ac23d0cb.smk Bug-Id: CVE-2015-8365 CC: libav-stable@libav.org Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind Signed-off-by: Michael Niedermayer (cherry picked from commit 4a9af07a49295e014b059c1ab624c40345af5892) Signed-off-by: Diego Biurrun --- libavcodec/smacker.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index c4b4bc735d2ea..d42347ccdc061 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -636,6 +636,11 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, av_log(avctx, AV_LOG_ERROR, "sample format mismatch\n"); return AVERROR(EINVAL); } + if (unp_size % (avctx->channels * (bits + 1))) { + av_log(avctx, AV_LOG_ERROR, + "The buffer does not contain an integer number of samples\n"); + return AVERROR(EINVAL); + } /* get output buffer */ frame->nb_samples = unp_size / (avctx->channels * (bits + 1)); From 5edded9df31bc4712a023f89941b4c278f1bd6f5 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 30 May 2017 18:12:48 +0200 Subject: [PATCH 0240/2557] smacker: Improve error handling Return sensible error values and forward error codes. --- libavcodec/smacker.c | 47 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index d42347ccdc061..0e057a1c2a882 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -100,7 +100,7 @@ static int smacker_decode_tree(BitstreamContext *bc, HuffContext *hc, if (!bitstream_read_bit(bc)) { // Leaf if(hc->current >= 256){ av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); - return -1; + return AVERROR_INVALIDDATA; } if(length){ hc->bits[hc->current] = prefix; @@ -132,14 +132,14 @@ static int smacker_decode_bigtree(BitstreamContext *bc, HuffContext *hc, { if (hc->current + 1 >= hc->length) { av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); - return -1; + return AVERROR_INVALIDDATA; } if (!bitstream_read_bit(bc)) { // Leaf int val, i1, i2; i1 = ctx->v1->table ? bitstream_read_vlc(bc, ctx->v1->table, SMKTREE_BITS, 3) : 0; i2 = ctx->v2->table ? bitstream_read_vlc(bc, ctx->v2->table, SMKTREE_BITS, 3) : 0; if (i1 < 0 || i2 < 0) - return -1; + return AVERROR_INVALIDDATA; val = ctx->recode1[i1] | (ctx->recode2[i2] << 8); if(val == ctx->escapes[0]) { ctx->last[0] = hc->current; @@ -186,7 +186,7 @@ static int smacker_decode_header_tree(SmackVContext *smk, BitstreamContext *bc, if(size >= UINT_MAX>>4){ // (((size + 3) >> 2) + 3) << 2 must not overflow av_log(smk->avctx, AV_LOG_ERROR, "size too large\n"); - return -1; + return AVERROR_INVALIDDATA; } tmp1.length = 256; @@ -264,8 +264,8 @@ static int smacker_decode_header_tree(SmackVContext *smk, BitstreamContext *bc, goto error; } - if (smacker_decode_bigtree(bc, &huff, &ctx) < 0) - err = -1; + if ((res = smacker_decode_bigtree(bc, &huff, &ctx)) < 0) + err = res; bitstream_skip(bc, 1); if(ctx.last[0] == -1) ctx.last[0] = huff.current++; if(ctx.last[1] == -1) ctx.last[1] = huff.current++; @@ -296,7 +296,7 @@ static int smacker_decode_header_tree(SmackVContext *smk, BitstreamContext *bc, static int decode_header_trees(SmackVContext *smk) { BitstreamContext bc; - int mmap_size, mclr_size, full_size, type_size; + int mmap_size, mclr_size, full_size, type_size, ret; mmap_size = AV_RL32(smk->avctx->extradata); mclr_size = AV_RL32(smk->avctx->extradata + 4); @@ -313,8 +313,8 @@ static int decode_header_trees(SmackVContext *smk) { smk->mmap_tbl[0] = 0; smk->mmap_last[0] = smk->mmap_last[1] = smk->mmap_last[2] = 1; } else { - if (smacker_decode_header_tree(smk, &bc, &smk->mmap_tbl, smk->mmap_last, mmap_size)) - return -1; + if ((ret = smacker_decode_header_tree(smk, &bc, &smk->mmap_tbl, smk->mmap_last, mmap_size)) < 0) + return ret; } if (!bitstream_read_bit(&bc)) { av_log(smk->avctx, AV_LOG_INFO, "Skipping MCLR tree\n"); @@ -324,8 +324,8 @@ static int decode_header_trees(SmackVContext *smk) { smk->mclr_tbl[0] = 0; smk->mclr_last[0] = smk->mclr_last[1] = smk->mclr_last[2] = 1; } else { - if (smacker_decode_header_tree(smk, &bc, &smk->mclr_tbl, smk->mclr_last, mclr_size)) - return -1; + if ((ret = smacker_decode_header_tree(smk, &bc, &smk->mclr_tbl, smk->mclr_last, mclr_size)) < 0) + return ret; } if (!bitstream_read_bit(&bc)) { av_log(smk->avctx, AV_LOG_INFO, "Skipping FULL tree\n"); @@ -335,8 +335,8 @@ static int decode_header_trees(SmackVContext *smk) { smk->full_tbl[0] = 0; smk->full_last[0] = smk->full_last[1] = smk->full_last[2] = 1; } else { - if (smacker_decode_header_tree(smk, &bc, &smk->full_tbl, smk->full_last, full_size)) - return -1; + if ((ret = smacker_decode_header_tree(smk, &bc, &smk->full_tbl, smk->full_last, full_size)) < 0) + return ret; } if (!bitstream_read_bit(&bc)) { av_log(smk->avctx, AV_LOG_INFO, "Skipping TYPE tree\n"); @@ -346,8 +346,8 @@ static int decode_header_trees(SmackVContext *smk) { smk->type_tbl[0] = 0; smk->type_last[0] = smk->type_last[1] = smk->type_last[2] = 1; } else { - if (smacker_decode_header_tree(smk, &bc, &smk->type_tbl, smk->type_last, type_size)) - return -1; + if ((ret = smacker_decode_header_tree(smk, &bc, &smk->type_tbl, smk->type_last, type_size)) < 0) + return ret; } return 0; @@ -555,6 +555,7 @@ static av_cold int decode_end(AVCodecContext *avctx) static av_cold int decode_init(AVCodecContext *avctx) { SmackVContext * const c = avctx->priv_data; + int ret; c->avctx = avctx; @@ -567,12 +568,12 @@ static av_cold int decode_init(AVCodecContext *avctx) /* decode huffman trees from extradata */ if(avctx->extradata_size < 16){ av_log(avctx, AV_LOG_ERROR, "Extradata missing!\n"); - return -1; + return AVERROR_INVALIDDATA; } - if (decode_header_trees(c)) { + if ((ret = decode_header_trees(c))) { decode_end(avctx); - return -1; + return ret; } return 0; @@ -584,7 +585,7 @@ static av_cold int smka_decode_init(AVCodecContext *avctx) { if (avctx->channels < 1 || avctx->channels > 2) { av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; } avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; avctx->sample_fmt = avctx->bits_per_coded_sample == 8 ? AV_SAMPLE_FMT_U8 : AV_SAMPLE_FMT_S16; @@ -614,7 +615,7 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, if (buf_size <= 4) { av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; } unp_size = AV_RL32(buf); @@ -630,16 +631,16 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, bits = bitstream_read_bit(&bc); if (stereo ^ (avctx->channels != 1)) { av_log(avctx, AV_LOG_ERROR, "channels mismatch\n"); - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; } if (bits && avctx->sample_fmt == AV_SAMPLE_FMT_U8) { av_log(avctx, AV_LOG_ERROR, "sample format mismatch\n"); - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; } if (unp_size % (avctx->channels * (bits + 1))) { av_log(avctx, AV_LOG_ERROR, "The buffer does not contain an integer number of samples\n"); - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; } /* get output buffer */ From 61cec5adaacb358783c18aa07362f15824c1b274 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 23 May 2017 10:15:28 +0200 Subject: [PATCH 0241/2557] tls: Hide backend implementation details from users TLS is currently implemented over either OpenSSL or GnuTLS, with more backends likely to appear in the future. Currently, those backend libraries are part of the protocol names used during e.g. the configure stage of a build. Hide those details behind a generically-named declaration for the TLS protocol to avoid leaking those details into the configuration stage. --- configure | 8 ++------ libavformat/Makefile | 5 +++-- libavformat/network.c | 12 ++++++++---- libavformat/protocols.c | 3 +-- libavformat/tls.h | 2 -- libavformat/tls_gnutls.c | 2 +- libavformat/tls_openssl.c | 2 +- 7 files changed, 16 insertions(+), 18 deletions(-) diff --git a/configure b/configure index f86ca158c9430..90760fe39ea1c 100755 --- a/configure +++ b/configure @@ -2468,12 +2468,8 @@ sctp_protocol_deps="struct_sctp_event_subscribe" sctp_protocol_select="network" srtp_protocol_select="rtp_protocol srtp" tcp_protocol_select="network" -tls_gnutls_protocol_deps="gnutls" -tls_gnutls_protocol_select="tcp_protocol" -tls_openssl_protocol_conflict="tls_gnutls_protocol" -tls_openssl_protocol_deps="openssl" -tls_openssl_protocol_select="tcp_protocol" -tls_protocol_deps_any="tls_gnutls_protocol tls_openssl_protocol" +tls_protocol_deps_any="gnutls openssl" +tls_protocol_select="tcp_protocol" udp_protocol_select="network" unix_protocol_deps="sys_un_h" unix_protocol_select="network" diff --git a/libavformat/Makefile b/libavformat/Makefile index 7b1df9342c727..2c1c0f6d7fc91 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -408,8 +408,9 @@ OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o OBJS-$(CONFIG_SCTP_PROTOCOL) += sctp.o OBJS-$(CONFIG_SRTP_PROTOCOL) += srtpproto.o srtp.o OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o -OBJS-$(CONFIG_TLS_GNUTLS_PROTOCOL) += tls_gnutls.o tls.o -OBJS-$(CONFIG_TLS_OPENSSL_PROTOCOL) += tls_openssl.o tls.o +TLS-OBJS-$(CONFIG_GNUTLS) += tls_gnutls.o +TLS-OBJS-$(CONFIG_OPENSSL) += tls_openssl.o +OBJS-$(CONFIG_TLS_PROTOCOL) += tls.o $(TLS-OBJS-yes) OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o OBJS-$(CONFIG_UNIX_PROTOCOL) += unix.o diff --git a/libavformat/network.c b/libavformat/network.c index 2c34b4a14bfac..86d79553f7d77 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -27,22 +27,26 @@ void ff_tls_init(void) { -#if CONFIG_TLS_OPENSSL_PROTOCOL +#if CONFIG_TLS_PROTOCOL +#if CONFIG_OPENSSL ff_openssl_init(); #endif -#if CONFIG_TLS_GNUTLS_PROTOCOL +#if CONFIG_GNUTLS ff_gnutls_init(); #endif +#endif } void ff_tls_deinit(void) { -#if CONFIG_TLS_OPENSSL_PROTOCOL +#if CONFIG_TLS_PROTOCOL +#if CONFIG_OPENSSL ff_openssl_deinit(); #endif -#if CONFIG_TLS_GNUTLS_PROTOCOL +#if CONFIG_GNUTLS ff_gnutls_deinit(); #endif +#endif } int ff_network_inited_globally; diff --git a/libavformat/protocols.c b/libavformat/protocols.c index d25454021ff2a..8ea5c0e75765a 100644 --- a/libavformat/protocols.c +++ b/libavformat/protocols.c @@ -48,8 +48,7 @@ extern const URLProtocol ff_rtp_protocol; extern const URLProtocol ff_sctp_protocol; extern const URLProtocol ff_srtp_protocol; extern const URLProtocol ff_tcp_protocol; -extern const URLProtocol ff_tls_gnutls_protocol; -extern const URLProtocol ff_tls_openssl_protocol; +extern const URLProtocol ff_tls_protocol; extern const URLProtocol ff_udp_protocol; extern const URLProtocol ff_unix_protocol; extern const URLProtocol ff_librtmp_protocol; diff --git a/libavformat/tls.h b/libavformat/tls.h index 22cb6250b4c61..94f30ab854bc1 100644 --- a/libavformat/tls.h +++ b/libavformat/tls.h @@ -26,8 +26,6 @@ #include "url.h" #include "libavutil/opt.h" -#define CONFIG_TLS_PROTOCOL (CONFIG_TLS_GNUTLS_PROTOCOL | CONFIG_TLS_OPENSSL_PROTOCOL) - typedef struct TLSShared { char *ca_file; int verify; diff --git a/libavformat/tls_gnutls.c b/libavformat/tls_gnutls.c index f8a612ad9b8c0..1ae7656dcb071 100644 --- a/libavformat/tls_gnutls.c +++ b/libavformat/tls_gnutls.c @@ -233,7 +233,7 @@ static const AVClass tls_class = { .version = LIBAVUTIL_VERSION_INT, }; -const URLProtocol ff_tls_gnutls_protocol = { +const URLProtocol ff_tls_protocol = { .name = "tls", .url_open2 = tls_open, .url_read = tls_read, diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c index 0abccf00a9dbe..71fa96871dfba 100644 --- a/libavformat/tls_openssl.c +++ b/libavformat/tls_openssl.c @@ -323,7 +323,7 @@ static const AVClass tls_class = { .version = LIBAVUTIL_VERSION_INT, }; -const URLProtocol ff_tls_openssl_protocol = { +const URLProtocol ff_tls_protocol = { .name = "tls", .url_open2 = tls_open, .url_read = tls_read, From a876958d0fdd8bf10d315175daff12cd7d768053 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 3 Mar 2017 00:25:54 -0300 Subject: [PATCH 0242/2557] avutil/md5: fix misaligned reads This makes ubsan happy and also considerably increases performance on big endian systems. Tested on an IBM POWER7 3.55 GHz Before: 2.24user 0.14system 0:02.39elapsed 99%CPU (0avgtext+0avgdata 2624maxresident)k 2.26user 0.11system 0:02.38elapsed 99%CPU (0avgtext+0avgdata 2688maxresident)k 2.23user 0.15system 0:02.38elapsed 99%CPU (0avgtext+0avgdata 2624maxresident)k 2.25user 0.12system 0:02.38elapsed 100%CPU (0avgtext+0avgdata 2624maxresident)k 2.20user 0.15system 0:02.36elapsed 99%CPU (0avgtext+0avgdata 2624maxresident)k After: 1.86user 0.13system 0:02.00elapsed 99%CPU (0avgtext+0avgdata 2624maxresident)k 1.89user 0.11system 0:02.01elapsed 99%CPU (0avgtext+0avgdata 2624maxresident)k 1.85user 0.14system 0:02.00elapsed 99%CPU (0avgtext+0avgdata 2624maxresident)k 1.84user 0.15system 0:01.99elapsed 99%CPU (0avgtext+0avgdata 2624maxresident)k 1.89user 0.13system 0:02.02elapsed 99%CPU (0avgtext+0avgdata 2688maxresident)k Tested-by: Nicolas George Reviewed-by: Michael Niedermayer Signed-off-by: James Almer Signed-off-by: Sean McGovern --- libavutil/md5.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/libavutil/md5.c b/libavutil/md5.c index 1946d783172ac..0ddde56b676e5 100644 --- a/libavutil/md5.c +++ b/libavutil/md5.c @@ -83,15 +83,15 @@ static const uint32_t T[64] = { // T[i]= fabs(sin(i+1)<<32) a += T[i]; \ \ if (i < 32) { \ - if (i < 16) \ - a += (d ^ (b & (c ^ d))) + X[i & 15]; \ - else \ - a += (c ^ (d & (c ^ b))) + X[(1 + 5 * i) & 15]; \ + if (i < 16) \ + a += (d ^ (b & (c ^ d))) + AV_RL32(X + (i & 15)); \ + else \ + a += (c ^ (d & (c ^ b))) + AV_RL32(X + ((1 + 5 * i) & 15)); \ } else { \ if (i < 48) \ - a += (b ^ c ^ d) + X[(5 + 3 * i) & 15]; \ + a += (b ^ c ^ d) + AV_RL32(X + ((5 + 3 * i) & 15)); \ else \ - a += (c ^ (b | ~d)) + X[(7 * i) & 15]; \ + a += (c ^ (b | ~d)) + AV_RL32(X + ((7 * i) & 15)); \ } \ a = b + (a << t | a >> (32 - t)); \ } while (0) @@ -99,18 +99,14 @@ static const uint32_t T[64] = { // T[i]= fabs(sin(i+1)<<32) static void body(uint32_t ABCD[4], uint32_t X[16]) { int t; - int i av_unused; unsigned int a = ABCD[3]; unsigned int b = ABCD[2]; unsigned int c = ABCD[1]; unsigned int d = ABCD[0]; -#if HAVE_BIGENDIAN - for (i = 0; i < 16; i++) - X[i] = av_bswap32(X[i]); -#endif - #if CONFIG_SMALL + int i; + for (i = 0; i < 64; i++) { CORE(i, a, b, c, d); t = d; From 5e27ef800bfa2be17a6353ddedac6b7400e4624f Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 14 Mar 2017 16:44:24 +0100 Subject: [PATCH 0243/2557] build: Add missing zlib dependencies for several protocols --- configure | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/configure b/configure index 90760fe39ea1c..2913bad0de5cc 100755 --- a/configure +++ b/configure @@ -2445,8 +2445,11 @@ ffrtmphttp_protocol_conflict="librtmp_protocol" ffrtmphttp_protocol_select="http_protocol" gopher_protocol_select="network" http_protocol_select="tcp_protocol" +http_protocol_suggest="zlib" httpproxy_protocol_select="tcp_protocol" +httpproxy_protocol_suggest="zlib" https_protocol_select="tls_protocol" +https_protocol_suggest="zlib" icecast_protocol_select="http_protocol" librtmp_protocol_deps="librtmp" librtmpe_protocol_deps="librtmp" @@ -2457,12 +2460,18 @@ mmsh_protocol_select="http_protocol" mmst_protocol_select="network" rtmp_protocol_conflict="librtmp_protocol" rtmp_protocol_select="tcp_protocol" +rtmp_protocol_suggest="zlib" rtmpe_protocol_select="ffrtmpcrypt_protocol" +rtmpe_protocol_suggest="zlib" rtmps_protocol_conflict="librtmp_protocol" rtmps_protocol_select="tls_protocol" +rtmps_protocol_suggest="zlib" rtmpt_protocol_select="ffrtmphttp_protocol" +rtmpt_protocol_suggest="zlib" rtmpte_protocol_select="ffrtmpcrypt_protocol ffrtmphttp_protocol" +rtmpte_protocol_suggest="zlib" rtmpts_protocol_select="ffrtmphttp_protocol https_protocol" +rtmpts_protocol_suggest="zlib" rtp_protocol_select="udp_protocol" sctp_protocol_deps="struct_sctp_event_subscribe" sctp_protocol_select="network" From adfd7892e3b8b40e7a1620f7254459d8e096a9a1 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 22 May 2017 14:48:15 +0200 Subject: [PATCH 0244/2557] configure: Move x86 assembler sanity check into assembler probe function This allows for more graceful fallback from NASM to Yasm if the available NASM version is too old. --- configure | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 2913bad0de5cc..cf10e54a89235 100755 --- a/configure +++ b/configure @@ -4509,13 +4509,15 @@ EOF x86asm_debug="-g dwarf2" X86ASMDEP='$(DEPX86ASM) $(X86ASMFLAGS) -M $(X86ASM_O) $< > $(@:.o=.d)' fi + check_x86asm "movbe ecx, [5]" && enable x86asm } if ! disabled_any asm mmx x86asm; then + disable x86asm for program in $x86asmexe nasm yasm; do - probe_x86asm $program - test -n "$x86asm_type" && break + probe_x86asm $program && break done + disabled x86asm && die "nasm/yasm not found or too old. Use --disable-x86asm for a crippled build." X86ASMFLAGS="-f $objformat" enabled pic && append X86ASMFLAGS "-DPIC" test -n "$extern_prefix" && append X86ASMFLAGS "-DPREFIX" @@ -4523,8 +4525,6 @@ EOF elf*) enabled debug && append X86ASMFLAGS $x86asm_debug ;; esac - check_x86asm "movbe ecx, [5]" && enable x86asm || - die "nasm/yasm not found or too old. Use --disable-x86asm for a crippled build." check_x86asm "vextracti128 xmm0, ymm0, 0" || disable avx2_external check_x86asm "vpmacsdd xmm0, xmm1, xmm2, xmm3" || disable xop_external check_x86asm "vfmadd132ps ymm0, ymm1, ymm2" || disable fma3_external From f960fd2fb1218d49866d0bf47cbf839233fb9904 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 15 Mar 2017 17:36:16 +0100 Subject: [PATCH 0245/2557] build: Skip generating .version files when reconfiguring The .version files are only relevant during an actual build. --- avbuild/library.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avbuild/library.mak b/avbuild/library.mak index 227e4d5d481ca..2095f61d807ad 100644 --- a/avbuild/library.mak +++ b/avbuild/library.mak @@ -1,6 +1,6 @@ include $(SRC_PATH)/avbuild/common.mak -ifeq (,$(filter %clean,$(MAKECMDGOALS))) +ifeq (,$(filter %clean config,$(MAKECMDGOALS))) -include $(SUBDIR)lib$(NAME).version endif From 908f737d6c2900b5d34319ca6ea1d1cb71221463 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 22 May 2017 16:27:51 +0200 Subject: [PATCH 0246/2557] cmdutils: Mark conditionally used variable as av_unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit avtools/cmdutils.c:1234:28: warning: unused variable ‘pix_fmt’ [-Wunused-variable] --- avtools/cmdutils.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/avtools/cmdutils.c b/avtools/cmdutils.c index b0445eb85b1b6..727e2835eb3ae 100644 --- a/avtools/cmdutils.c +++ b/avtools/cmdutils.c @@ -35,6 +35,7 @@ #include "libavdevice/avdevice.h" #include "libavresample/avresample.h" #include "libswscale/swscale.h" +#include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/mathematics.h" @@ -1231,7 +1232,7 @@ int show_pix_fmts(void *optctx, const char *opt, const char *arg) #endif while ((pix_desc = av_pix_fmt_desc_next(pix_desc))) { - enum AVPixelFormat pix_fmt = av_pix_fmt_desc_get_id(pix_desc); + enum AVPixelFormat av_unused pix_fmt = av_pix_fmt_desc_get_id(pix_desc); printf("%c%c%c%c%c %-16s %d %2d\n", sws_isSupportedInput (pix_fmt) ? 'I' : '.', sws_isSupportedOutput(pix_fmt) ? 'O' : '.', From ed434be106a4615e0419b3ac7664220741afda2d Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 26 May 2017 13:05:12 +0200 Subject: [PATCH 0247/2557] configure: Bail out if both GnuTLS and OpenSSL are enabled Both libraries provide similar functionality and cannot be used together. When both are enabled one is used and the other ignored arbitrarily. Error out instead and have the user choose which library to use. --- configure | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure b/configure index cf10e54a89235..0281f545057a7 100755 --- a/configure +++ b/configure @@ -2887,6 +2887,9 @@ map "die_license_disabled version3" $EXTERNAL_LIBRARY_VERSION3_LIST enabled version3 && { enabled gpl && enable gplv3 || enable lgplv3; } +enabled_all gnutls openssl && + die "GnuTLS and OpenSSL must not be enabled at the same time." + # Disable all the library-specific components if the library itself # is disabled, see AVCODEC_LIST and following _LIST variables. From fff90422d181744cd75dbf011687ee7095f02875 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 6 Jun 2017 18:51:07 +0200 Subject: [PATCH 0248/2557] lavu: add new D3D11 pixfmt and hwcontext To be used with the new d3d11 hwaccel decode API. With the new hwaccel API, we don't want surfaces to depend on the decoder (other than the required dimension and format). The old D3D11VA pixfmt uses ID3D11VideoDecoderOutputView pointers, which include the decoder configuration, and thus is incompatible with the new hwaccel API. This patch introduces AV_PIX_FMT_D3D11, which uses ID3D11Texture2D and an index. It's simpler and compatible with the new hwaccel API. The introduced hwcontext supports only the new pixfmt. Frame upload code untested. Significantly based on work by Steve Lhomme , but with heavy changes/rewrites. Signed-off-by: Diego Biurrun --- doc/APIchanges | 3 + libavutil/Makefile | 3 + libavutil/hwcontext.c | 4 + libavutil/hwcontext.h | 1 + libavutil/hwcontext_d3d11va.c | 490 +++++++++++++++++++++++++++++++++ libavutil/hwcontext_d3d11va.h | 160 +++++++++++ libavutil/hwcontext_internal.h | 1 + libavutil/pixdesc.c | 4 + libavutil/pixfmt.h | 14 +- libavutil/version.h | 4 +- 10 files changed, 681 insertions(+), 3 deletions(-) create mode 100644 libavutil/hwcontext_d3d11va.c create mode 100644 libavutil/hwcontext_d3d11va.h diff --git a/doc/APIchanges b/doc/APIchanges index a251c4ca82a65..a81e41833de4c 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2017-03-23 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavu 56.2.0 - hwcontext.h + Add AV_HWDEVICE_TYPE_D3D11VA and AV_PIX_FMT_D3D11. + 2017-04-30 - xxxxxxx - lavu 56.1.1 - hwcontext.h av_hwframe_ctx_create_derived() now takes some AV_HWFRAME_MAP_* combination as its flags argument (which was previously unused). diff --git a/libavutil/Makefile b/libavutil/Makefile index 60e180c79d940..6fb24db678b92 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -27,6 +27,7 @@ HEADERS = adler32.h \ hmac.h \ hwcontext.h \ hwcontext_cuda.h \ + hwcontext_d3d11va.h \ hwcontext_dxva2.h \ hwcontext_qsv.h \ hwcontext_vaapi.h \ @@ -112,6 +113,7 @@ OBJS = adler32.o \ xtea.o \ OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o +OBJS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.o OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o OBJS-$(CONFIG_LIBMFX) += hwcontext_qsv.o OBJS-$(CONFIG_LZO) += lzo.o @@ -121,6 +123,7 @@ OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o OBJS += $(COMPAT_OBJS:%=../compat/%) SKIPHEADERS-$(CONFIG_CUDA) += hwcontext_cuda.h +SKIPHEADERS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.h SKIPHEADERS-$(CONFIG_DXVA2) += hwcontext_dxva2.h SKIPHEADERS-$(CONFIG_LIBMFX) += hwcontext_qsv.h SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index 360b01205c286..d82df56abf157 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -32,6 +32,9 @@ static const HWContextType * const hw_table[] = { #if CONFIG_CUDA &ff_hwcontext_type_cuda, #endif +#if CONFIG_D3D11VA + &ff_hwcontext_type_d3d11va, +#endif #if CONFIG_DXVA2 &ff_hwcontext_type_dxva2, #endif @@ -50,6 +53,7 @@ static const HWContextType * const hw_table[] = { const char *hw_type_names[] = { [AV_HWDEVICE_TYPE_CUDA] = "cuda", [AV_HWDEVICE_TYPE_DXVA2] = "dxva2", + [AV_HWDEVICE_TYPE_D3D11VA] = "d3d11va", [AV_HWDEVICE_TYPE_QSV] = "qsv", [AV_HWDEVICE_TYPE_VAAPI] = "vaapi", [AV_HWDEVICE_TYPE_VDPAU] = "vdpau", diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h index eaf40c46f1654..203ea510ec629 100644 --- a/libavutil/hwcontext.h +++ b/libavutil/hwcontext.h @@ -31,6 +31,7 @@ enum AVHWDeviceType { AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_DXVA2, AV_HWDEVICE_TYPE_QSV, + AV_HWDEVICE_TYPE_D3D11VA, }; typedef struct AVHWDeviceInternal AVHWDeviceInternal; diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c new file mode 100644 index 0000000000000..3940502868c65 --- /dev/null +++ b/libavutil/hwcontext_d3d11va.c @@ -0,0 +1,490 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#endif +#define COBJMACROS + +#include +#include +#include + +#include "avassert.h" +#include "common.h" +#include "hwcontext.h" +#include "hwcontext_d3d11va.h" +#include "hwcontext_internal.h" +#include "imgutils.h" +#include "pixdesc.h" +#include "pixfmt.h" + +typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory); + +typedef struct D3D11VAFramesContext { + int nb_surfaces_used; + + DXGI_FORMAT format; + + ID3D11Texture2D *staging_texture; +} D3D11VAFramesContext; + +static const struct { + DXGI_FORMAT d3d_format; + enum AVPixelFormat pix_fmt; +} supported_formats[] = { + { DXGI_FORMAT_NV12, AV_PIX_FMT_NV12 }, + { DXGI_FORMAT_P010, AV_PIX_FMT_P010 }, +}; + +static void d3d11va_default_lock(void *ctx) +{ + WaitForSingleObjectEx(ctx, INFINITE, FALSE); +} + +static void d3d11va_default_unlock(void *ctx) +{ + ReleaseMutex(ctx); +} + +static void d3d11va_frames_uninit(AVHWFramesContext *ctx) +{ + AVD3D11VAFramesContext *frames_hwctx = ctx->hwctx; + D3D11VAFramesContext *s = ctx->internal->priv; + + if (frames_hwctx->texture) + ID3D11Texture2D_Release(frames_hwctx->texture); + + if (s->staging_texture) + ID3D11Texture2D_Release(s->staging_texture); +} + +static void free_texture(void *opaque, uint8_t *data) +{ + ID3D11Texture2D_Release((ID3D11Texture2D *)opaque); +} + +static AVBufferRef *wrap_texture_buf(ID3D11Texture2D *tex, int index) +{ + AVBufferRef *buf; + AVD3D11FrameDescriptor *desc = av_mallocz(sizeof(*desc)); + if (!desc) { + ID3D11Texture2D_Release(tex); + return NULL; + } + + desc->texture = tex; + desc->index = index; + + buf = av_buffer_create((uint8_t *)desc, sizeof(desc), free_texture, tex, 0); + if (!buf) { + ID3D11Texture2D_Release(tex); + av_free(desc); + return NULL; + } + + return buf; +} + +static AVBufferRef *d3d11va_alloc_single(AVHWFramesContext *ctx) +{ + D3D11VAFramesContext *s = ctx->internal->priv; + AVD3D11VAFramesContext *hwctx = ctx->hwctx; + AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx; + HRESULT hr; + ID3D11Texture2D *tex; + D3D11_TEXTURE2D_DESC texDesc = { + .Width = ctx->width, + .Height = ctx->height, + .MipLevels = 1, + .Format = s->format, + .SampleDesc = { .Count = 1 }, + .ArraySize = 1, + .Usage = D3D11_USAGE_DEFAULT, + .BindFlags = hwctx->BindFlags, + .MiscFlags = hwctx->MiscFlags, + }; + + hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &tex); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr); + return NULL; + } + + return wrap_texture_buf(tex, 0); +} + +static AVBufferRef *d3d11va_pool_alloc(void *opaque, int size) +{ + AVHWFramesContext *ctx = (AVHWFramesContext*)opaque; + D3D11VAFramesContext *s = ctx->internal->priv; + AVD3D11VAFramesContext *hwctx = ctx->hwctx; + D3D11_TEXTURE2D_DESC texDesc; + + if (!hwctx->texture) + return d3d11va_alloc_single(ctx); + + ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc); + + if (s->nb_surfaces_used >= texDesc.ArraySize) { + av_log(ctx, AV_LOG_ERROR, "Static surface pool size exceeded.\n"); + return NULL; + } + + ID3D11Texture2D_AddRef(hwctx->texture); + return wrap_texture_buf(hwctx->texture, s->nb_surfaces_used++); +} + +static int d3d11va_frames_init(AVHWFramesContext *ctx) +{ + AVD3D11VAFramesContext *hwctx = ctx->hwctx; + AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx; + D3D11VAFramesContext *s = ctx->internal->priv; + + int i; + HRESULT hr; + D3D11_TEXTURE2D_DESC texDesc; + + for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) { + if (ctx->sw_format == supported_formats[i].pix_fmt) { + s->format = supported_formats[i].d3d_format; + break; + } + } + if (i == FF_ARRAY_ELEMS(supported_formats)) { + av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n", + av_get_pix_fmt_name(ctx->sw_format)); + return AVERROR(EINVAL); + } + + texDesc = (D3D11_TEXTURE2D_DESC){ + .Width = ctx->width, + .Height = ctx->height, + .MipLevels = 1, + .Format = s->format, + .SampleDesc = { .Count = 1 }, + .ArraySize = ctx->initial_pool_size, + .Usage = D3D11_USAGE_DEFAULT, + .BindFlags = hwctx->BindFlags, + .MiscFlags = hwctx->MiscFlags, + }; + + if (hwctx->texture) { + D3D11_TEXTURE2D_DESC texDesc2; + ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc2); + + if (texDesc.Width != texDesc2.Width || + texDesc.Height != texDesc2.Height || + texDesc.Format != texDesc2.Format) { + av_log(ctx, AV_LOG_ERROR, "User-provided texture has mismatching parameters\n"); + return AVERROR(EINVAL); + } + } else if (texDesc.ArraySize > 0) { + hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &hwctx->texture); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr); + return AVERROR_UNKNOWN; + } + } + + texDesc.ArraySize = 1; + texDesc.Usage = D3D11_USAGE_STAGING; + texDesc.BindFlags = 0; + texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + texDesc.MiscFlags = 0; + hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &s->staging_texture); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Could not create the staging texture (%lx)\n", (long)hr); + return AVERROR_UNKNOWN; + } + + ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(AVD3D11FrameDescriptor), + ctx, d3d11va_pool_alloc, NULL); + if (!ctx->internal->pool_internal) + return AVERROR(ENOMEM); + + return 0; +} + +static int d3d11va_get_buffer(AVHWFramesContext *ctx, AVFrame *frame) +{ + AVD3D11FrameDescriptor *desc; + + frame->buf[0] = av_buffer_pool_get(ctx->pool); + if (!frame->buf[0]) + return AVERROR(ENOMEM); + + desc = (AVD3D11FrameDescriptor *)frame->buf[0]->data; + + frame->data[0] = (uint8_t *)desc->texture; + frame->data[1] = (uint8_t *)desc->index; + frame->format = AV_PIX_FMT_D3D11; + frame->width = ctx->width; + frame->height = ctx->height; + + return 0; +} + +static int d3d11va_transfer_get_formats(AVHWFramesContext *ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats) +{ + enum AVPixelFormat *fmts; + + fmts = av_malloc_array(2, sizeof(*fmts)); + if (!fmts) + return AVERROR(ENOMEM); + + fmts[0] = ctx->sw_format; + fmts[1] = AV_PIX_FMT_NONE; + + *formats = fmts; + + return 0; +} + +static void fill_texture_ptrs(uint8_t *data[4], int linesize[4], + AVHWFramesContext *ctx, + D3D11_TEXTURE2D_DESC *desc, + D3D11_MAPPED_SUBRESOURCE *map) +{ + int i; + + for (i = 0; i < 4; i++) + linesize[i] = map->RowPitch; + + av_image_fill_pointers(data, ctx->sw_format, desc->Height, + (uint8_t*)map->pData, linesize); +} + +static int d3d11va_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, + const AVFrame *src) +{ + AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx; + D3D11VAFramesContext *s = ctx->internal->priv; + int download = src->format == AV_PIX_FMT_D3D11; + const AVFrame *frame = download ? src : dst; + const AVFrame *other = download ? dst : src; + // (The interface types are compatible.) + ID3D11Resource *texture = (ID3D11Resource *)(ID3D11Texture2D *)frame->data[0]; + int index = (intptr_t)frame->data[1]; + ID3D11Resource *staging = (ID3D11Resource *)s->staging_texture; + int w = FFMIN(dst->width, src->width); + int h = FFMIN(dst->height, src->height); + uint8_t *map_data[4]; + int map_linesize[4]; + D3D11_TEXTURE2D_DESC desc; + D3D11_MAPPED_SUBRESOURCE map; + HRESULT hr; + + if (frame->hw_frames_ctx->data != (uint8_t *)ctx || other->format != ctx->sw_format) + return AVERROR(EINVAL); + + device_hwctx->lock(device_hwctx->lock_ctx); + + ID3D11Texture2D_GetDesc(s->staging_texture, &desc); + + if (download) { + ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context, + staging, 0, 0, 0, 0, + texture, index, NULL); + + hr = ID3D11DeviceContext_Map(device_hwctx->device_context, + staging, 0, D3D11_MAP_READ, 0, &map); + if (FAILED(hr)) + goto map_failed; + + fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map); + + av_image_copy(dst->data, dst->linesize, map_data, map_linesize, + ctx->sw_format, w, h); + + ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0); + } else { + hr = ID3D11DeviceContext_Map(device_hwctx->device_context, + staging, 0, D3D11_MAP_WRITE, 0, &map); + if (FAILED(hr)) + goto map_failed; + + fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map); + + av_image_copy(map_data, map_linesize, src->data, src->linesize, + ctx->sw_format, w, h); + + ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0); + + ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context, + texture, index, 0, 0, 0, + staging, 0, NULL); + } + + device_hwctx->unlock(device_hwctx->lock_ctx); + return 0; + +map_failed: + av_log(ctx, AV_LOG_ERROR, "Unable to lock D3D11VA surface (%lx)\n", (long)hr); + device_hwctx->unlock(device_hwctx->lock_ctx); + return AVERROR_UNKNOWN; +} + +static int d3d11va_device_init(AVHWDeviceContext *hwdev) +{ + AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx; + HRESULT hr; + + if (!device_hwctx->lock) { + device_hwctx->lock_ctx = CreateMutex(NULL, 0, NULL); + if (device_hwctx->lock_ctx == INVALID_HANDLE_VALUE) { + av_log(NULL, AV_LOG_ERROR, "Failed to create a mutex\n"); + return AVERROR(EINVAL); + } + device_hwctx->lock = d3d11va_default_lock; + device_hwctx->unlock = d3d11va_default_unlock; + } + + if (!device_hwctx->device_context) { + ID3D11Device_GetImmediateContext(device_hwctx->device, &device_hwctx->device_context); + if (!device_hwctx->device_context) + return AVERROR_UNKNOWN; + } + + if (!device_hwctx->video_device) { + hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device, &IID_ID3D11VideoDevice, + (void **)&device_hwctx->video_device); + if (FAILED(hr)) + return AVERROR_UNKNOWN; + } + + if (!device_hwctx->video_context) { + hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device_context, &IID_ID3D11VideoContext, + (void **)&device_hwctx->video_context); + if (FAILED(hr)) + return AVERROR_UNKNOWN; + } + + return 0; +} + +static void d3d11va_device_uninit(AVHWDeviceContext *hwdev) +{ + AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx; + + if (device_hwctx->device) + ID3D11Device_Release(device_hwctx->device); + + if (device_hwctx->device_context) + ID3D11DeviceContext_Release(device_hwctx->device_context); + + if (device_hwctx->video_device) + ID3D11VideoDevice_Release(device_hwctx->video_device); + + if (device_hwctx->video_context) + ID3D11VideoContext_Release(device_hwctx->video_context); + + if (device_hwctx->lock == d3d11va_default_lock) + CloseHandle(device_hwctx->lock_ctx); +} + +static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, + AVDictionary *opts, int flags) +{ + AVD3D11VADeviceContext *device_hwctx = ctx->hwctx; + HANDLE d3dlib; + + HRESULT hr; + PFN_D3D11_CREATE_DEVICE createD3D; + IDXGIAdapter *pAdapter = NULL; + ID3D10Multithread *pMultithread; + UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT; + + if (device) { + PFN_CREATE_DXGI_FACTORY mCreateDXGIFactory; + HMODULE dxgilib = LoadLibrary("dxgi.dll"); + if (!dxgilib) + return AVERROR_UNKNOWN; + + mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) GetProcAddress(dxgilib, "CreateDXGIFactory"); + if (mCreateDXGIFactory) { + IDXGIFactory2 *pDXGIFactory; + hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&pDXGIFactory); + if (SUCCEEDED(hr)) { + int adapter = atoi(device); + if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, &pAdapter))) + pAdapter = NULL; + IDXGIFactory2_Release(pDXGIFactory); + } + } + FreeLibrary(dxgilib); + } + + // We let this "leak" - this is fine, as unloading has no great benefit, and + // Windows will mark a DLL as loaded forever if its internal refcount overflows + // from too many LoadLibrary calls. + d3dlib = LoadLibrary("d3d11.dll"); + if (!d3dlib) { + av_log(ctx, AV_LOG_ERROR, "Failed to load D3D11 library\n"); + return AVERROR_UNKNOWN; + } + + createD3D = (PFN_D3D11_CREATE_DEVICE) GetProcAddress(d3dlib, "D3D11CreateDevice"); + if (!createD3D) { + av_log(ctx, AV_LOG_ERROR, "Failed to locate D3D11CreateDevice\n"); + return AVERROR_UNKNOWN; + } + + hr = createD3D(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0, + D3D11_SDK_VERSION, &device_hwctx->device, NULL, NULL); + if (pAdapter) + IDXGIAdapter_Release(pAdapter); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device (%lx)\n", (long)hr); + return AVERROR_UNKNOWN; + } + + hr = ID3D11Device_QueryInterface(device_hwctx->device, &IID_ID3D10Multithread, (void **)&pMultithread); + if (SUCCEEDED(hr)) { + ID3D10Multithread_SetMultithreadProtected(pMultithread, TRUE); + ID3D10Multithread_Release(pMultithread); + } + + return 0; +} + +const HWContextType ff_hwcontext_type_d3d11va = { + .type = AV_HWDEVICE_TYPE_D3D11VA, + .name = "D3D11VA", + + .device_hwctx_size = sizeof(AVD3D11VADeviceContext), + .frames_hwctx_size = sizeof(AVD3D11VAFramesContext), + .frames_priv_size = sizeof(D3D11VAFramesContext), + + .device_create = d3d11va_device_create, + .device_init = d3d11va_device_init, + .device_uninit = d3d11va_device_uninit, + .frames_init = d3d11va_frames_init, + .frames_uninit = d3d11va_frames_uninit, + .frames_get_buffer = d3d11va_get_buffer, + .transfer_get_formats = d3d11va_transfer_get_formats, + .transfer_data_to = d3d11va_transfer_data, + .transfer_data_from = d3d11va_transfer_data, + + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_D3D11, AV_PIX_FMT_NONE }, +}; diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h new file mode 100644 index 0000000000000..676349d7b81a4 --- /dev/null +++ b/libavutil/hwcontext_d3d11va.h @@ -0,0 +1,160 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_D3D11VA_H +#define AVUTIL_HWCONTEXT_D3D11VA_H + +/** + * @file + * An API-specific header for AV_HWDEVICE_TYPE_D3D11VA. + * + * The default pool implementation will be fixed-size if initial_pool_size is + * set (and allocate elements from an array texture). Otherwise it will allocate + * individual textures. Be aware that decoding requires a single array texture. + */ + +#include + +/** + * This struct is allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVD3D11VADeviceContext { + /** + * Device used for texture creation and access. This can also be used to + * set the libavcodec decoding device. + * + * Must be set by the user. This is the only mandatory field - the other + * device context fields are set from this and are available for convenience. + * + * Deallocating the AVHWDeviceContext will always release this interface, + * and it does not matter whether it was user-allocated. + */ + ID3D11Device *device; + + /** + * If unset, this will be set from the device field on init. + * + * Deallocating the AVHWDeviceContext will always release this interface, + * and it does not matter whether it was user-allocated. + */ + ID3D11DeviceContext *device_context; + + /** + * If unset, this will be set from the device field on init. + * + * Deallocating the AVHWDeviceContext will always release this interface, + * and it does not matter whether it was user-allocated. + */ + ID3D11VideoDevice *video_device; + + /** + * If unset, this will be set from the device_context field on init. + * + * Deallocating the AVHWDeviceContext will always release this interface, + * and it does not matter whether it was user-allocated. + */ + ID3D11VideoContext *video_context; + + /** + * Callbacks for locking. They protect accesses to device_context and + * video_context calls. They also protect access to the internal staging + * texture (for av_hwframe_transfer_data() calls). They do NOT protect + * access to hwcontext or decoder state in general. + * + * If unset on init, the hwcontext implementation will set them to use an + * internal mutex. + * + * The underlying lock must be recursive. lock_ctx is for free use by the + * locking implementation. + */ + void (*lock)(void *lock_ctx); + void (*unlock)(void *lock_ctx); + void *lock_ctx; +} AVD3D11VADeviceContext; + +/** + * D3D11 frame descriptor for pool allocation. + * + * In user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs + * with the data pointer pointing at an object of this type describing the + * planes of the frame. + * + * This has no use outside of custom allocation, and AVFrame AVBufferRef do not + * necessarily point to an instance of this struct. + */ +typedef struct AVD3D11FrameDescriptor { + /** + * The texture in which the frame is located. The reference count is + * managed by the AVBufferRef, and destroying the reference will release + * the interface. + * + * Normally stored in AVFrame.data[0]. + */ + ID3D11Texture2D *texture; + + /** + * The index into the array texture element representing the frame, or 0 + * if the texture is not an array texture. + * + * Normally stored in AVFrame.data[1] (cast from intptr_t). + */ + intptr_t index; +} AVD3D11FrameDescriptor; + +/** + * This struct is allocated as AVHWFramesContext.hwctx + */ +typedef struct AVD3D11VAFramesContext { + /** + * The canonical texture used for pool allocation. If this is set to NULL + * on init, the hwframes implementation will allocate and set an array + * texture if initial_pool_size > 0. + * + * The only situation when the API user should set this is: + * - the user wants to do manual pool allocation (setting + * AVHWFramesContext.pool), instead of letting AVHWFramesContext + * allocate the pool + * - of an array texture + * - and wants it to use it for decoding + * - this has to be done before calling av_hwframe_ctx_init() + * + * Deallocating the AVHWFramesContext will always release this interface, + * and it does not matter whether it was user-allocated. + * + * This is in particular used by the libavcodec D3D11VA hwaccel, which + * requires a single array texture. It will create ID3D11VideoDecoderOutputView + * objects for each array texture element on decoder initialization. + */ + ID3D11Texture2D *texture; + + /** + * D3D11_TEXTURE2D_DESC.BindFlags used for texture creation. The user must + * at least set D3D11_BIND_DECODER if the frames context is to be used for + * video decoding. + * This field is ignored/invalid if a user-allocated texture is provided. + */ + UINT BindFlags; + + /** + * D3D11_TEXTURE2D_DESC.MiscFlags used for texture creation. + * This field is ignored/invalid if a user-allocated texture is provided. + */ + UINT MiscFlags; +} AVD3D11VAFramesContext; + +#endif /* AVUTIL_HWCONTEXT_D3D11VA_H */ diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h index 7cf6cb07c7145..99612931f2c12 100644 --- a/libavutil/hwcontext_internal.h +++ b/libavutil/hwcontext_internal.h @@ -158,6 +158,7 @@ int ff_hwframe_map_create(AVBufferRef *hwframe_ref, extern const HWContextType ff_hwcontext_type_cuda; +extern const HWContextType ff_hwcontext_type_d3d11va; extern const HWContextType ff_hwcontext_type_dxva2; extern const HWContextType ff_hwcontext_type_qsv; extern const HWContextType ff_hwcontext_type_vaapi; diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index fb2e1a12f369d..7fa6dd7c0b878 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -1739,6 +1739,10 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, + [AV_PIX_FMT_D3D11] = { + .name = "d3d11", + .flags = AV_PIX_FMT_FLAG_HWACCEL, + }, }; #if FF_API_PLUS1_MINUS1 FF_ENABLE_DEPRECATION_WARNINGS diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index fc1969ef12613..2ba7ad1c88c05 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -205,7 +205,7 @@ enum AVPixelFormat { */ AV_PIX_FMT_MMAL, - AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer + AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer /** * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers @@ -237,6 +237,18 @@ enum AVPixelFormat { AV_PIX_FMT_GBRAP10BE, ///< planar GBR 4:4:4:4 40bpp, big-endian AV_PIX_FMT_GBRAP10LE, ///< planar GBR 4:4:4:4 40bpp, little-endian + /** + * Hardware surfaces for Direct3D11. + * + * This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11 + * hwaccel API and filtering support AV_PIX_FMT_D3D11 only. + * + * data[0] contains a ID3D11Texture2D pointer, and data[1] contains the + * texture array index of the frame as intptr_t if the ID3D11Texture2D is + * an array texture (or always 0 if it's a normal texture). + */ + AV_PIX_FMT_D3D11, + AV_PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions }; diff --git a/libavutil/version.h b/libavutil/version.h index 7779755870ae2..2c85120b642f0 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -54,8 +54,8 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 1 -#define LIBAVUTIL_VERSION_MICRO 1 +#define LIBAVUTIL_VERSION_MINOR 2 +#define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ From bd747b9226414007f0207fa201976af7217e3b77 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 6 Jun 2017 18:51:08 +0200 Subject: [PATCH 0249/2557] lavc: set avctx->hwaccel before init So a hwaccel can access avctx->hwaccel in init for whatever reason. This is for the new d3d hwaccel API. We could create separate entrypoints for each of the 3 hwaccel types (dxva2, d3d11va, new d3d11va), but this seems nicer. Signed-off-by: Diego Biurrun --- libavcodec/decode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index bb58dfc561941..ae2c715677a85 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -746,16 +746,16 @@ static int setup_hwaccel(AVCodecContext *avctx, return AVERROR(ENOMEM); } + avctx->hwaccel = hwa; if (hwa->init) { ret = hwa->init(avctx); if (ret < 0) { av_freep(&avctx->internal->hwaccel_priv_data); + avctx->hwaccel = NULL; return ret; } } - avctx->hwaccel = hwa; - return 0; } From 4dec101acc393fbfe9a8ce0237b9efbae3f20139 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 6 Jun 2017 18:51:09 +0200 Subject: [PATCH 0250/2557] dxva: preparations for new hwaccel API The actual hwaccel code will need to access an internal context instead of avctx->hwaccel_context, so add a new DXVA_CONTEXT() macro, that will dispatch between the "old" external and the new internal context. Also, the new API requires a new D3D11 pixfmt, so all places which check for the pixfmt need to be adjusted. Introduce a ff_dxva2_is_d3d11() function, which does the check. Signed-off-by: Diego Biurrun --- libavcodec/dxva2.c | 32 ++++++++++++++++++++------------ libavcodec/dxva2_h264.c | 14 +++++++------- libavcodec/dxva2_hevc.c | 10 +++++----- libavcodec/dxva2_internal.h | 22 +++++++++++++--------- libavcodec/dxva2_mpeg2.c | 10 +++++----- libavcodec/dxva2_vc1.c | 10 +++++----- 6 files changed, 55 insertions(+), 43 deletions(-) diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index b0452b6a9ade6..fe6dbbc030a70 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -71,7 +71,7 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx, HRESULT hr; #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (ff_dxva2_is_d3d11(avctx)) hr = ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type, @@ -91,7 +91,7 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx, memcpy(dxva_data, data, size); #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = dsc; memset(dsc11, 0, sizeof(*dsc11)); dsc11->BufferType = type; @@ -116,7 +116,7 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx, } #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (ff_dxva2_is_d3d11(avctx)) hr = ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type); #endif #if CONFIG_DXVA2 @@ -139,7 +139,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, DECODER_BUFFER_DESC *bs, DECODER_BUFFER_DESC *slice)) { - AVDXVAContext *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); unsigned buffer_count = 0; #if CONFIG_D3D11VA D3D11_VIDEO_DECODER_BUFFER_DESC buffer11[4]; @@ -154,7 +154,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, do { #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) WaitForSingleObjectEx(D3D11VA_CONTEXT(ctx)->context_mutex, INFINITE, FALSE); hr = ID3D11VideoContext_DecoderBeginFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, @@ -171,7 +171,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, if (hr != E_PENDING || ++runs > 50) break; #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (ff_dxva2_is_d3d11(avctx)) if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex); #endif @@ -181,7 +181,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, if (FAILED(hr)) { av_log(avctx, AV_LOG_ERROR, "Failed to begin frame: 0x%x\n", hr); #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (ff_dxva2_is_d3d11(avctx)) if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex); #endif @@ -189,7 +189,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, } #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { buffer = &buffer11[buffer_count]; type = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS; } @@ -212,7 +212,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, if (qm_size > 0) { #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { buffer = &buffer11[buffer_count]; type = D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX; } @@ -235,7 +235,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, } #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { buffer = &buffer11[buffer_count + 0]; buffer_slice = &buffer11[buffer_count + 1]; } @@ -262,7 +262,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, assert(buffer_count == 1 + (qm_size > 0) + 2); #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (ff_dxva2_is_d3d11(avctx)) hr = ID3D11VideoContext_SubmitDecoderBuffers(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, buffer_count, buffer11); @@ -284,7 +284,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, end: #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { hr = ID3D11VideoContext_DecoderEndFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder); if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex); @@ -301,3 +301,11 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, return result; } + +int ff_dxva2_is_d3d11(const AVCodecContext *avctx) +{ + if (CONFIG_D3D11VA) + return avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD; + else + return 0; +} diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c index 84959c532dafa..f58a45807ff3f 100644 --- a/libavcodec/dxva2_h264.c +++ b/libavcodec/dxva2_h264.c @@ -220,7 +220,7 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, { const H264Context *h = avctx->priv_data; H264SliceContext *sl = &h->slice_ctx[0]; - AVDXVAContext *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); unsigned list; memset(slice, 0, sizeof(*slice)); @@ -302,7 +302,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, { const H264Context *h = avctx->priv_data; const unsigned mb_count = h->mb_width * h->mb_height; - AVDXVAContext *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); const H264Picture *current_picture = h->cur_pic_ptr; struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; DXVA_Slice_H264_Short *slice = NULL; @@ -317,7 +317,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, /* Create an annex B bitstream buffer with only slice NAL and finalize slice */ #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, @@ -388,7 +388,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, slice->SliceBytesInBuffer += padding; } #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (ff_dxva2_is_d3d11(avctx)) if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type))) return -1; #endif @@ -401,7 +401,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, return -1; #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs; memset(dsc11, 0, sizeof(*dsc11)); dsc11->BufferType = type; @@ -442,7 +442,7 @@ static int dxva2_h264_start_frame(AVCodecContext *avctx, av_unused uint32_t size) { const H264Context *h = avctx->priv_data; - AVDXVAContext *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); struct dxva2_picture_context *ctx_pic = h->cur_pic_ptr->hwaccel_picture_private; if (!DXVA_CONTEXT_VALID(avctx, ctx)) @@ -467,7 +467,7 @@ static int dxva2_h264_decode_slice(AVCodecContext *avctx, { const H264Context *h = avctx->priv_data; const H264SliceContext *sl = &h->slice_ctx[0]; - AVDXVAContext *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); const H264Picture *current_picture = h->cur_pic_ptr; struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; unsigned position; diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c index 17548d25bb381..f2bb8b26a5103 100644 --- a/libavcodec/dxva2_hevc.c +++ b/libavcodec/dxva2_hevc.c @@ -243,7 +243,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, DECODER_BUFFER_DESC *sc) { const HEVCContext *h = avctx->priv_data; - AVDXVAContext *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); const HEVCFrame *current_picture = h->ref; struct hevc_dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; DXVA_Slice_HEVC_Short *slice = NULL; @@ -258,7 +258,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, /* Create an annex B bitstream buffer with only slice NAL and finalize slice */ #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, @@ -312,7 +312,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, slice->SliceBytesInBuffer += padding; } #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (ff_dxva2_is_d3d11(avctx)) if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type))) return -1; #endif @@ -325,7 +325,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, return -1; #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs; memset(dsc11, 0, sizeof(*dsc11)); dsc11->BufferType = type; @@ -362,7 +362,7 @@ static int dxva2_hevc_start_frame(AVCodecContext *avctx, av_unused uint32_t size) { const HEVCContext *h = avctx->priv_data; - AVDXVAContext *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); struct hevc_dxva2_picture_context *ctx_pic = h->ref->hwaccel_picture_private; if (!DXVA_CONTEXT_VALID(avctx, ctx)) diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h index 8b774b14f31e6..af0d607487fc3 100644 --- a/libavcodec/dxva2_internal.h +++ b/libavcodec/dxva2_internal.h @@ -59,21 +59,23 @@ typedef union { #endif } AVDXVAContext; +#define DXVA_CONTEXT(avctx) ((AVDXVAContext *)(avctx)->hwaccel_context) + #define D3D11VA_CONTEXT(ctx) (&ctx->d3d11va) #define DXVA2_CONTEXT(ctx) (&ctx->dxva2) #if CONFIG_D3D11VA && CONFIG_DXVA2 -#define DXVA_CONTEXT_WORKAROUND(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.workaround : ctx->dxva2.workaround) -#define DXVA_CONTEXT_COUNT(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.surface_count : ctx->dxva2.surface_count) -#define DXVA_CONTEXT_DECODER(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.decoder : ctx->dxva2.decoder) -#define DXVA_CONTEXT_REPORT_ID(avctx, ctx) (*(avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? &ctx->d3d11va.report_id : &ctx->dxva2.report_id)) -#define DXVA_CONTEXT_CFG(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.cfg : ctx->dxva2.cfg) -#define DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.cfg->ConfigBitstreamRaw : ctx->dxva2.cfg->ConfigBitstreamRaw) -#define DXVA_CONTEXT_CFG_INTRARESID(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.cfg->ConfigIntraResidUnsigned : ctx->dxva2.cfg->ConfigIntraResidUnsigned) -#define DXVA_CONTEXT_CFG_RESIDACCEL(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.cfg->ConfigResidDiffAccelerator : ctx->dxva2.cfg->ConfigResidDiffAccelerator) +#define DXVA_CONTEXT_WORKAROUND(avctx, ctx) (ff_dxva2_is_d3d11(avctx) ? ctx->d3d11va.workaround : ctx->dxva2.workaround) +#define DXVA_CONTEXT_COUNT(avctx, ctx) (ff_dxva2_is_d3d11(avctx) ? ctx->d3d11va.surface_count : ctx->dxva2.surface_count) +#define DXVA_CONTEXT_DECODER(avctx, ctx) (ff_dxva2_is_d3d11(avctx) ? ctx->d3d11va.decoder : ctx->dxva2.decoder) +#define DXVA_CONTEXT_REPORT_ID(avctx, ctx) (*(ff_dxva2_is_d3d11(avctx) ? &ctx->d3d11va.report_id : &ctx->dxva2.report_id)) +#define DXVA_CONTEXT_CFG(avctx, ctx) (ff_dxva2_is_d3d11(avctx) ? ctx->d3d11va.cfg : ctx->dxva2.cfg) +#define DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) (ff_dxva2_is_d3d11(avctx) ? ctx->d3d11va.cfg->ConfigBitstreamRaw : ctx->dxva2.cfg->ConfigBitstreamRaw) +#define DXVA_CONTEXT_CFG_INTRARESID(avctx, ctx) (ff_dxva2_is_d3d11(avctx) ? ctx->d3d11va.cfg->ConfigIntraResidUnsigned : ctx->dxva2.cfg->ConfigIntraResidUnsigned) +#define DXVA_CONTEXT_CFG_RESIDACCEL(avctx, ctx) (ff_dxva2_is_d3d11(avctx) ? ctx->d3d11va.cfg->ConfigResidDiffAccelerator : ctx->dxva2.cfg->ConfigResidDiffAccelerator) #define DXVA_CONTEXT_VALID(avctx, ctx) (DXVA_CONTEXT_DECODER(avctx, ctx) && \ DXVA_CONTEXT_CFG(avctx, ctx) && \ - (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD || ctx->dxva2.surface_count)) + (ff_dxva2_is_d3d11(avctx) || ctx->dxva2.surface_count)) #elif CONFIG_DXVA2 #define DXVA_CONTEXT_WORKAROUND(avctx, ctx) (ctx->dxva2.workaround) #define DXVA_CONTEXT_COUNT(avctx, ctx) (ctx->dxva2.surface_count) @@ -113,4 +115,6 @@ int ff_dxva2_common_end_frame(AVCodecContext *, AVFrame *, DECODER_BUFFER_DESC *bs, DECODER_BUFFER_DESC *slice)); +int ff_dxva2_is_d3d11(const AVCodecContext *avctx); + #endif /* AVCODEC_DXVA2_INTERNAL_H */ diff --git a/libavcodec/dxva2_mpeg2.c b/libavcodec/dxva2_mpeg2.c index a45904963c101..6ae30a5773fcf 100644 --- a/libavcodec/dxva2_mpeg2.c +++ b/libavcodec/dxva2_mpeg2.c @@ -156,7 +156,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, DECODER_BUFFER_DESC *sc) { const struct MpegEncContext *s = avctx->priv_data; - AVDXVAContext *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); struct dxva2_picture_context *ctx_pic = s->current_picture_ptr->hwaccel_picture_private; const int is_field = s->picture_structure != PICT_FRAME; @@ -168,7 +168,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, unsigned type; #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, @@ -212,7 +212,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, current += size; } #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (ff_dxva2_is_d3d11(avctx)) if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type))) return -1; #endif @@ -225,7 +225,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, return -1; #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs; memset(dsc11, 0, sizeof(*dsc11)); dsc11->BufferType = type; @@ -259,7 +259,7 @@ static int dxva2_mpeg2_start_frame(AVCodecContext *avctx, av_unused uint32_t size) { const struct MpegEncContext *s = avctx->priv_data; - AVDXVAContext *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); struct dxva2_picture_context *ctx_pic = s->current_picture_ptr->hwaccel_picture_private; diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c index 0672c97a48e09..b63580ed2ebf7 100644 --- a/libavcodec/dxva2_vc1.c +++ b/libavcodec/dxva2_vc1.c @@ -165,7 +165,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, DECODER_BUFFER_DESC *sc) { const VC1Context *v = avctx->priv_data; - AVDXVAContext *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); const MpegEncContext *s = &v->s; struct dxva2_picture_context *ctx_pic = s->current_picture_ptr->hwaccel_picture_private; @@ -184,7 +184,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, unsigned type; #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, @@ -215,7 +215,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, slice->dwSliceBitsInBuffer = 8 * data_size; } #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (ff_dxva2_is_d3d11(avctx)) if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type))) return -1; #endif @@ -228,7 +228,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, return result; #if CONFIG_D3D11VA - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (ff_dxva2_is_d3d11(avctx)) { D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs; memset(dsc11, 0, sizeof(*dsc11)); dsc11->BufferType = type; @@ -261,7 +261,7 @@ static int dxva2_vc1_start_frame(AVCodecContext *avctx, av_unused uint32_t size) { const VC1Context *v = avctx->priv_data; - AVDXVAContext *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private; if (!DXVA_CONTEXT_VALID(avctx, ctx)) From 831cfe10b40414915fe7b6088158421fe02e2b2d Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 6 Jun 2017 18:51:10 +0200 Subject: [PATCH 0251/2557] dxva: move d3d11 locking/unlocking to functions I want to make it non-mandatory to set a mutex in the D3D11 device context, and replacing it with user callbacks seems like the best solution. This is preparation for it. Also makes the code slightly more readable. Signed-off-by: Diego Biurrun --- libavcodec/dxva2.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index fe6dbbc030a70..5bc9b30653117 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -29,6 +29,28 @@ #include "avcodec.h" #include "dxva2_internal.h" +static void ff_dxva2_lock(AVCodecContext *avctx) +{ +#if CONFIG_D3D11VA + if (ff_dxva2_is_d3d11(avctx)) { + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); + if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) + WaitForSingleObjectEx(D3D11VA_CONTEXT(ctx)->context_mutex, INFINITE, FALSE); + } +#endif +} + +static void ff_dxva2_unlock(AVCodecContext *avctx) +{ +#if CONFIG_D3D11VA + if (ff_dxva2_is_d3d11(avctx)) { + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); + if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) + ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex); + } +#endif +} + static void *get_surface(const AVFrame *frame) { return frame->data[3]; @@ -153,14 +175,12 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, unsigned type; do { + ff_dxva2_lock(avctx); #if CONFIG_D3D11VA - if (ff_dxva2_is_d3d11(avctx)) { - if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) - WaitForSingleObjectEx(D3D11VA_CONTEXT(ctx)->context_mutex, INFINITE, FALSE); + if (ff_dxva2_is_d3d11(avctx)) hr = ID3D11VideoContext_DecoderBeginFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, get_surface(frame), 0, NULL); - } #endif #if CONFIG_DXVA2 if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) @@ -170,21 +190,13 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, #endif if (hr != E_PENDING || ++runs > 50) break; -#if CONFIG_D3D11VA - if (ff_dxva2_is_d3d11(avctx)) - if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) - ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex); -#endif + ff_dxva2_unlock(avctx); av_usleep(2000); } while(1); if (FAILED(hr)) { av_log(avctx, AV_LOG_ERROR, "Failed to begin frame: 0x%x\n", hr); -#if CONFIG_D3D11VA - if (ff_dxva2_is_d3d11(avctx)) - if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) - ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex); -#endif + ff_dxva2_unlock(avctx); return -1; } @@ -284,16 +296,14 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, end: #if CONFIG_D3D11VA - if (ff_dxva2_is_d3d11(avctx)) { + if (ff_dxva2_is_d3d11(avctx)) hr = ID3D11VideoContext_DecoderEndFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder); - if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) - ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex); - } #endif #if CONFIG_DXVA2 if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) hr = IDirectXVideoDecoder_EndFrame(DXVA2_CONTEXT(ctx)->decoder, NULL); #endif + ff_dxva2_unlock(avctx); if (FAILED(hr)) { av_log(avctx, AV_LOG_ERROR, "Failed to end frame: 0x%x\n", hr); result = -1; From f9e7a2f95a7194a8736cc1416a03a1a0155a3e9f Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 7 Jun 2017 17:11:17 +0200 Subject: [PATCH 0252/2557] dxva: add support for new dxva2 and d3d11 hwaccel APIs This also adds support to avconv (which is trivial due to the new hwaccel API being generic enough). The new decoder setup code in dxva2.c is significantly based on work by Steve Lhomme , but with heavy changes/rewrites. Signed-off-by: Diego Biurrun --- Changelog | 1 + avtools/Makefile | 1 - avtools/avconv.h | 1 + avtools/avconv_dxva2.c | 440 ------------------------ avtools/avconv_opt.c | 10 +- configure | 19 +- doc/APIchanges | 6 + libavcodec/allcodecs.c | 5 + libavcodec/dxva2.c | 663 +++++++++++++++++++++++++++++++++++- libavcodec/dxva2_h264.c | 22 ++ libavcodec/dxva2_hevc.c | 22 ++ libavcodec/dxva2_internal.h | 43 ++- libavcodec/dxva2_mpeg2.c | 22 ++ libavcodec/dxva2_vc1.c | 44 +++ libavcodec/h264_slice.c | 3 +- libavcodec/hevcdec.c | 3 +- libavcodec/mpeg12dec.c | 1 + libavcodec/vc1dec.c | 1 + libavcodec/version.h | 4 +- libavutil/hwcontext_dxva2.h | 3 + 20 files changed, 853 insertions(+), 461 deletions(-) delete mode 100644 avtools/avconv_dxva2.c diff --git a/Changelog b/Changelog index 6fd30fddb92fc..e44df54c93d47 100644 --- a/Changelog +++ b/Changelog @@ -15,6 +15,7 @@ version : - VP9 superframe split/merge bitstream filters - FM Screen Capture Codec decoder - ClearVideo decoder (I-frames only) +- support for decoding through D3D11VA in avconv version 12: diff --git a/avtools/Makefile b/avtools/Makefile index c23a605a5522e..d95e2d9fc203f 100644 --- a/avtools/Makefile +++ b/avtools/Makefile @@ -12,7 +12,6 @@ OBJS-avconv += avtools/avconv_opt.o avtools/avconv_filter.o \ avtools/avconv_hw.o OBJS-avconv-$(CONFIG_LIBMFX) += avtools/avconv_qsv.o OBJS-avconv-$(CONFIG_VDA) += avtools/avconv_vda.o -OBJS-avconv-$(HAVE_DXVA2_LIB) += avtools/avconv_dxva2.o define DOAVTOOL OBJS-$(1) += avtools/cmdutils.o avtools/$(1).o $(OBJS-$(1)-yes) diff --git a/avtools/avconv.h b/avtools/avconv.h index 3354c50444a4e..4c699333a5a44 100644 --- a/avtools/avconv.h +++ b/avtools/avconv.h @@ -57,6 +57,7 @@ enum HWAccelID { HWACCEL_VDA, HWACCEL_QSV, HWACCEL_VAAPI, + HWACCEL_D3D11VA, }; typedef struct HWAccel { diff --git a/avtools/avconv_dxva2.c b/avtools/avconv_dxva2.c deleted file mode 100644 index 7578c3f632804..0000000000000 --- a/avtools/avconv_dxva2.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#ifdef _WIN32_WINNT -#undef _WIN32_WINNT -#endif -#define _WIN32_WINNT 0x0600 -#define DXVA2API_USE_BITFIELDS -#define COBJMACROS - -#include - -#include -#include - -#include "avconv.h" - -#include "libavcodec/dxva2.h" - -#include "libavutil/avassert.h" -#include "libavutil/buffer.h" -#include "libavutil/frame.h" -#include "libavutil/imgutils.h" -#include "libavutil/pixfmt.h" - -#include "libavutil/hwcontext.h" -#include "libavutil/hwcontext_dxva2.h" - -/* define all the GUIDs used directly here, - to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */ -#include -DEFINE_GUID(IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02); - -DEFINE_GUID(DXVA2_ModeMPEG2_VLD, 0xee27417f, 0x5e28,0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9); -DEFINE_GUID(DXVA2_ModeMPEG2and1_VLD, 0x86695f12, 0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60); -DEFINE_GUID(DXVA2_ModeH264_E, 0x1b81be68, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); -DEFINE_GUID(DXVA2_ModeH264_F, 0x1b81be69, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); -DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68, 0x4951,0x4C54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6); -DEFINE_GUID(DXVA2_ModeVC1_D, 0x1b81beA3, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); -DEFINE_GUID(DXVA2_ModeVC1_D2010, 0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); -DEFINE_GUID(DXVA2_ModeHEVC_VLD_Main, 0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0); -DEFINE_GUID(DXVA2_ModeHEVC_VLD_Main10,0x107af0e0, 0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13); -DEFINE_GUID(DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); -DEFINE_GUID(GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00); - -typedef struct dxva2_mode { - const GUID *guid; - enum AVCodecID codec; -} dxva2_mode; - -static const dxva2_mode dxva2_modes[] = { - /* MPEG-2 */ - { &DXVA2_ModeMPEG2_VLD, AV_CODEC_ID_MPEG2VIDEO }, - { &DXVA2_ModeMPEG2and1_VLD, AV_CODEC_ID_MPEG2VIDEO }, - - /* H.264 */ - { &DXVA2_ModeH264_F, AV_CODEC_ID_H264 }, - { &DXVA2_ModeH264_E, AV_CODEC_ID_H264 }, - /* Intel specific H.264 mode */ - { &DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264 }, - - /* VC-1 / WMV3 */ - { &DXVA2_ModeVC1_D2010, AV_CODEC_ID_VC1 }, - { &DXVA2_ModeVC1_D2010, AV_CODEC_ID_WMV3 }, - { &DXVA2_ModeVC1_D, AV_CODEC_ID_VC1 }, - { &DXVA2_ModeVC1_D, AV_CODEC_ID_WMV3 }, - - /* HEVC/H.265 */ - { &DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC }, - { &DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC }, - - { NULL, 0 }, -}; - -typedef struct DXVA2Context { - IDirectXVideoDecoder *decoder; - - GUID decoder_guid; - DXVA2_ConfigPictureDecode decoder_config; - IDirectXVideoDecoderService *decoder_service; - - AVFrame *tmp_frame; - - AVBufferRef *hw_device_ctx; - AVBufferRef *hw_frames_ctx; -} DXVA2Context; - -static void dxva2_uninit(AVCodecContext *s) -{ - InputStream *ist = s->opaque; - DXVA2Context *ctx = ist->hwaccel_ctx; - - ist->hwaccel_uninit = NULL; - ist->hwaccel_get_buffer = NULL; - ist->hwaccel_retrieve_data = NULL; - - if (ctx->decoder_service) - IDirectXVideoDecoderService_Release(ctx->decoder_service); - - av_buffer_unref(&ctx->hw_frames_ctx); - av_buffer_unref(&ctx->hw_device_ctx); - - av_frame_free(&ctx->tmp_frame); - - av_freep(&ist->hwaccel_ctx); - av_freep(&s->hwaccel_context); -} - -static int dxva2_get_buffer(AVCodecContext *s, AVFrame *frame, int flags) -{ - InputStream *ist = s->opaque; - DXVA2Context *ctx = ist->hwaccel_ctx; - - return av_hwframe_get_buffer(ctx->hw_frames_ctx, frame, 0); -} - -static int dxva2_retrieve_data(AVCodecContext *s, AVFrame *frame) -{ - InputStream *ist = s->opaque; - DXVA2Context *ctx = ist->hwaccel_ctx; - int ret; - - ret = av_hwframe_transfer_data(ctx->tmp_frame, frame, 0); - if (ret < 0) - return ret; - - ret = av_frame_copy_props(ctx->tmp_frame, frame); - if (ret < 0) { - av_frame_unref(ctx->tmp_frame); - return ret; - } - - av_frame_unref(frame); - av_frame_move_ref(frame, ctx->tmp_frame); - - return 0; -} - -static int dxva2_alloc(AVCodecContext *s) -{ - InputStream *ist = s->opaque; - int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; - DXVA2Context *ctx; - HANDLE device_handle; - HRESULT hr; - - AVHWDeviceContext *device_ctx; - AVDXVA2DeviceContext *device_hwctx; - int ret; - - ctx = av_mallocz(sizeof(*ctx)); - if (!ctx) - return AVERROR(ENOMEM); - - ist->hwaccel_ctx = ctx; - ist->hwaccel_uninit = dxva2_uninit; - ist->hwaccel_get_buffer = dxva2_get_buffer; - ist->hwaccel_retrieve_data = dxva2_retrieve_data; - - ret = av_hwdevice_ctx_create(&ctx->hw_device_ctx, AV_HWDEVICE_TYPE_DXVA2, - ist->hwaccel_device, NULL, 0); - if (ret < 0) - goto fail; - device_ctx = (AVHWDeviceContext*)ctx->hw_device_ctx->data; - device_hwctx = device_ctx->hwctx; - - hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr, - &device_handle); - if (FAILED(hr)) { - av_log(NULL, loglevel, "Failed to open a device handle\n"); - goto fail; - } - - hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr, device_handle, - &IID_IDirectXVideoDecoderService, - (void **)&ctx->decoder_service); - IDirect3DDeviceManager9_CloseDeviceHandle(device_hwctx->devmgr, device_handle); - if (FAILED(hr)) { - av_log(NULL, loglevel, "Failed to create IDirectXVideoDecoderService\n"); - goto fail; - } - - ctx->tmp_frame = av_frame_alloc(); - if (!ctx->tmp_frame) - goto fail; - - s->hwaccel_context = av_mallocz(sizeof(struct dxva_context)); - if (!s->hwaccel_context) - goto fail; - - return 0; -fail: - dxva2_uninit(s); - return AVERROR(EINVAL); -} - -static int dxva2_get_decoder_configuration(AVCodecContext *s, const GUID *device_guid, - const DXVA2_VideoDesc *desc, - DXVA2_ConfigPictureDecode *config) -{ - InputStream *ist = s->opaque; - int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; - DXVA2Context *ctx = ist->hwaccel_ctx; - unsigned cfg_count = 0, best_score = 0; - DXVA2_ConfigPictureDecode *cfg_list = NULL; - DXVA2_ConfigPictureDecode best_cfg = {{0}}; - HRESULT hr; - int i; - - hr = IDirectXVideoDecoderService_GetDecoderConfigurations(ctx->decoder_service, device_guid, desc, NULL, &cfg_count, &cfg_list); - if (FAILED(hr)) { - av_log(NULL, loglevel, "Unable to retrieve decoder configurations\n"); - return AVERROR(EINVAL); - } - - for (i = 0; i < cfg_count; i++) { - DXVA2_ConfigPictureDecode *cfg = &cfg_list[i]; - - unsigned score; - if (cfg->ConfigBitstreamRaw == 1) - score = 1; - else if (s->codec_id == AV_CODEC_ID_H264 && cfg->ConfigBitstreamRaw == 2) - score = 2; - else - continue; - if (IsEqualGUID(&cfg->guidConfigBitstreamEncryption, &DXVA2_NoEncrypt)) - score += 16; - if (score > best_score) { - best_score = score; - best_cfg = *cfg; - } - } - CoTaskMemFree(cfg_list); - - if (!best_score) { - av_log(NULL, loglevel, "No valid decoder configuration available\n"); - return AVERROR(EINVAL); - } - - *config = best_cfg; - return 0; -} - -static int dxva2_create_decoder(AVCodecContext *s) -{ - InputStream *ist = s->opaque; - int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; - DXVA2Context *ctx = ist->hwaccel_ctx; - struct dxva_context *dxva_ctx = s->hwaccel_context; - GUID *guid_list = NULL; - unsigned guid_count = 0, i, j; - GUID device_guid = GUID_NULL; - const D3DFORMAT surface_format = s->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? - MKTAG('P', '0', '1', '0') : MKTAG('N', 'V', '1', '2'); - D3DFORMAT target_format = 0; - DXVA2_VideoDesc desc = { 0 }; - DXVA2_ConfigPictureDecode config; - HRESULT hr; - int surface_alignment, num_surfaces; - int ret; - - AVDXVA2FramesContext *frames_hwctx; - AVHWFramesContext *frames_ctx; - - hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(ctx->decoder_service, &guid_count, &guid_list); - if (FAILED(hr)) { - av_log(NULL, loglevel, "Failed to retrieve decoder device GUIDs\n"); - goto fail; - } - - for (i = 0; dxva2_modes[i].guid; i++) { - D3DFORMAT *target_list = NULL; - unsigned target_count = 0; - const dxva2_mode *mode = &dxva2_modes[i]; - if (mode->codec != s->codec_id) - continue; - - for (j = 0; j < guid_count; j++) { - if (IsEqualGUID(mode->guid, &guid_list[j])) - break; - } - if (j == guid_count) - continue; - - hr = IDirectXVideoDecoderService_GetDecoderRenderTargets(ctx->decoder_service, mode->guid, &target_count, &target_list); - if (FAILED(hr)) { - continue; - } - for (j = 0; j < target_count; j++) { - const D3DFORMAT format = target_list[j]; - if (format == surface_format) { - target_format = format; - break; - } - } - CoTaskMemFree(target_list); - if (target_format) { - device_guid = *mode->guid; - break; - } - } - CoTaskMemFree(guid_list); - - if (IsEqualGUID(&device_guid, &GUID_NULL)) { - av_log(NULL, loglevel, "No decoder device for codec found\n"); - goto fail; - } - - desc.SampleWidth = s->coded_width; - desc.SampleHeight = s->coded_height; - desc.Format = target_format; - - ret = dxva2_get_decoder_configuration(s, &device_guid, &desc, &config); - if (ret < 0) { - goto fail; - } - - /* decoding MPEG-2 requires additional alignment on some Intel GPUs, - but it causes issues for H.264 on certain AMD GPUs..... */ - if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) - surface_alignment = 32; - /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure - all coding features have enough room to work with */ - else if (s->codec_id == AV_CODEC_ID_HEVC) - surface_alignment = 128; - else - surface_alignment = 16; - - /* 4 base work surfaces */ - num_surfaces = 4; - - /* add surfaces based on number of possible refs */ - if (s->codec_id == AV_CODEC_ID_H264 || s->codec_id == AV_CODEC_ID_HEVC) - num_surfaces += 16; - else - num_surfaces += 2; - - /* add extra surfaces for frame threading */ - if (s->active_thread_type & FF_THREAD_FRAME) - num_surfaces += s->thread_count; - - ctx->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->hw_device_ctx); - if (!ctx->hw_frames_ctx) - goto fail; - frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; - frames_hwctx = frames_ctx->hwctx; - - frames_ctx->format = AV_PIX_FMT_DXVA2_VLD; - frames_ctx->sw_format = s->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? - AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; - frames_ctx->width = FFALIGN(s->coded_width, surface_alignment); - frames_ctx->height = FFALIGN(s->coded_height, surface_alignment); - frames_ctx->initial_pool_size = num_surfaces; - - frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget; - - ret = av_hwframe_ctx_init(ctx->hw_frames_ctx); - if (ret < 0) { - av_log(NULL, loglevel, "Failed to initialize the HW frames context\n"); - goto fail; - } - - hr = IDirectXVideoDecoderService_CreateVideoDecoder(ctx->decoder_service, &device_guid, - &desc, &config, frames_hwctx->surfaces, - frames_hwctx->nb_surfaces, &frames_hwctx->decoder_to_release); - if (FAILED(hr)) { - av_log(NULL, loglevel, "Failed to create DXVA2 video decoder\n"); - goto fail; - } - - ctx->decoder_guid = device_guid; - ctx->decoder_config = config; - - dxva_ctx->cfg = &ctx->decoder_config; - dxva_ctx->decoder = frames_hwctx->decoder_to_release; - dxva_ctx->surface = frames_hwctx->surfaces; - dxva_ctx->surface_count = frames_hwctx->nb_surfaces; - - if (IsEqualGUID(&ctx->decoder_guid, &DXVADDI_Intel_ModeH264_E)) - dxva_ctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO; - - return 0; -fail: - av_buffer_unref(&ctx->hw_frames_ctx); - return AVERROR(EINVAL); -} - -int dxva2_init(AVCodecContext *s) -{ - InputStream *ist = s->opaque; - int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; - DXVA2Context *ctx; - int ret; - - if (!ist->hwaccel_ctx) { - ret = dxva2_alloc(s); - if (ret < 0) - return ret; - } - ctx = ist->hwaccel_ctx; - - if (s->codec_id == AV_CODEC_ID_H264 && - (s->profile & ~FF_PROFILE_H264_CONSTRAINED) > FF_PROFILE_H264_HIGH) { - av_log(NULL, loglevel, "Unsupported H.264 profile for DXVA2 HWAccel: %d\n", s->profile); - return AVERROR(EINVAL); - } - - if (s->codec_id == AV_CODEC_ID_HEVC && - s->profile != FF_PROFILE_HEVC_MAIN && s->profile != FF_PROFILE_HEVC_MAIN_10) { - av_log(NULL, loglevel, "Unsupported HEVC profile for DXVA2 HWAccel: %d\n", s->profile); - return AVERROR(EINVAL); - } - - av_buffer_unref(&ctx->hw_frames_ctx); - - ret = dxva2_create_decoder(s); - if (ret < 0) { - av_log(NULL, loglevel, "Error creating the DXVA2 decoder\n"); - return ret; - } - - return 0; -} diff --git a/avtools/avconv_opt.c b/avtools/avconv_opt.c index 9839a2269e15f..575ce120dd0ee 100644 --- a/avtools/avconv_opt.c +++ b/avtools/avconv_opt.c @@ -60,9 +60,13 @@ const HWAccel hwaccels[] = { { "vdpau", hwaccel_decode_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU, AV_HWDEVICE_TYPE_VDPAU }, #endif -#if HAVE_DXVA2_LIB - { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD, - AV_HWDEVICE_TYPE_NONE }, +#if CONFIG_D3D11VA + { "d3d11va", hwaccel_decode_init, HWACCEL_D3D11VA, AV_PIX_FMT_D3D11, + AV_HWDEVICE_TYPE_D3D11VA }, +#endif +#if CONFIG_DXVA2 + { "dxva2", hwaccel_decode_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD, + AV_HWDEVICE_TYPE_DXVA2 }, #endif #if CONFIG_VDA { "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA, diff --git a/configure b/configure index 0281f545057a7..019902cee6b12 100755 --- a/configure +++ b/configure @@ -1713,7 +1713,6 @@ HAVE_LIST=" $TOOLCHAIN_FEATURES $TYPES_LIST dos_paths - dxva2_lib libc_msvcrt MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS sdl @@ -2166,8 +2165,7 @@ zmbv_encoder_deps="zlib" # hardware accelerators d3d11va_deps="d3d11_h dxva_h ID3D11VideoDecoder" -dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode" -dxva2_lib_deps="dxva2" +dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32" vda_deps="VideoDecodeAcceleration_VDADecoder_h blocks_extension pthreads" vda_extralibs="-framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore" @@ -2175,6 +2173,8 @@ h263_vaapi_hwaccel_deps="vaapi" h263_vaapi_hwaccel_select="h263_decoder" h264_d3d11va_hwaccel_deps="d3d11va" h264_d3d11va_hwaccel_select="h264_decoder" +h264_d3d11va2_hwaccel_deps="d3d11va" +h264_d3d11va2_hwaccel_select="h264_decoder" h264_dxva2_hwaccel_deps="dxva2" h264_dxva2_hwaccel_select="h264_decoder" h264_mmal_hwaccel_deps="mmal" @@ -2189,6 +2189,8 @@ h264_vdpau_hwaccel_deps="vdpau" h264_vdpau_hwaccel_select="h264_decoder" hevc_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" hevc_d3d11va_hwaccel_select="hevc_decoder" +hevc_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" +hevc_d3d11va2_hwaccel_select="hevc_decoder" hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC" hevc_dxva2_hwaccel_select="hevc_decoder" hevc_qsv_hwaccel_deps="libmfx" @@ -2200,6 +2202,8 @@ mpeg1_vdpau_hwaccel_deps="vdpau" mpeg1_vdpau_hwaccel_select="mpeg1video_decoder" mpeg2_d3d11va_hwaccel_deps="d3d11va" mpeg2_d3d11va_hwaccel_select="mpeg2video_decoder" +mpeg2_d3d11va2_hwaccel_deps="d3d11va" +mpeg2_d3d11va2_hwaccel_select="mpeg2video_decoder" mpeg2_dxva2_hwaccel_deps="dxva2" mpeg2_dxva2_hwaccel_select="mpeg2video_decoder" mpeg2_mmal_hwaccel_deps="mmal" @@ -2214,6 +2218,8 @@ mpeg4_vdpau_hwaccel_deps="vdpau" mpeg4_vdpau_hwaccel_select="mpeg4_decoder" vc1_d3d11va_hwaccel_deps="d3d11va" vc1_d3d11va_hwaccel_select="vc1_decoder" +vc1_d3d11va2_hwaccel_deps="d3d11va" +vc1_d3d11va2_hwaccel_select="vc1_decoder" vc1_dxva2_hwaccel_deps="dxva2" vc1_dxva2_hwaccel_select="vc1_decoder" vc1_mmal_hwaccel_deps="mmal" @@ -2226,6 +2232,7 @@ vp8_qsv_hwaccel_deps="libmfx" vp8_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferVP8" vp8_vaapi_hwaccel_select="vp8_decoder" wmv3_d3d11va_hwaccel_select="vc1_d3d11va_hwaccel" +wmv3_d3d11va2_hwaccel_select="vc1_d3d11va2_hwaccel" wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel" wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" @@ -2544,7 +2551,7 @@ avconv_deps="avcodec avfilter avformat avresample swscale" avconv_select="aformat_filter anull_filter asyncts_filter atrim_filter format_filter fps_filter null_filter resample_filter scale_filter trim_filter" -avconv_suggest="dxva2_lib ole32 psapi shell32" +avconv_suggest="psapi shell32" avplay_deps="avcodec avfilter avformat avresample sdl" avplay_select="rdft format_filter transpose_filter hflip_filter vflip_filter" avplay_suggest="shell32" @@ -4670,6 +4677,7 @@ check_header windows.h # so we also check that atomics actually work here check_builtin stdatomic_h stdatomic.h "atomic_int foo; atomic_store(&foo, 0)" +check_lib ole32 "windows.h" CoTaskMemFree -lole32 check_lib shell32 "windows.h shellapi.h" CommandLineToArgvW -lshell32 check_lib wincrypt "windows.h wincrypt.h" CryptGenRandom -ladvapi32 check_lib psapi "windows.h psapi.h" GetProcessMemoryInfo -lpsapi @@ -4877,9 +4885,6 @@ if enabled libxcb; then check_pkg_config libxcb_xfixes xcb-xfixes xcb/xfixes.h xcb_xfixes_get_cursor_image fi -enabled dxva2 && - check_lib dxva2_lib windows.h CoTaskMemFree -lole32 - enabled vaapi && require vaapi va/va.h vaInitialize -lva enabled vaapi && diff --git a/doc/APIchanges b/doc/APIchanges index a81e41833de4c..0f7c839573e9c 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,12 @@ libavutil: 2017-03-23 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavc 58.4.0 - avcodec.h + DXVA2 and D3D11 hardware accelerated decoding now supports the new hwaccel API, + which can create the decoder context and allocate hardware frame automatically. + See AVCodecContext.hw_device_ctx and AVCodecContext.hw_frames_ctx. For D3D11, + the new AV_PIX_FMT_D3D11 pixfmt must be used with the new API. + 2017-xx-xx - xxxxxxx - lavu 56.2.0 - hwcontext.h Add AV_HWDEVICE_TYPE_D3D11VA and AV_PIX_FMT_D3D11. diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index dc9a9614406cb..70c35e9b4d789 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -69,6 +69,7 @@ void avcodec_register_all(void) /* hardware accelerators */ REGISTER_HWACCEL(H263_VAAPI, h263_vaapi); REGISTER_HWACCEL(H264_D3D11VA, h264_d3d11va); + REGISTER_HWACCEL(H264_D3D11VA2, h264_d3d11va2); REGISTER_HWACCEL(H264_DXVA2, h264_dxva2); REGISTER_HWACCEL(H264_MMAL, h264_mmal); REGISTER_HWACCEL(H264_QSV, h264_qsv); @@ -77,12 +78,14 @@ void avcodec_register_all(void) REGISTER_HWACCEL(H264_VDA_OLD, h264_vda_old); REGISTER_HWACCEL(H264_VDPAU, h264_vdpau); REGISTER_HWACCEL(HEVC_D3D11VA, hevc_d3d11va); + REGISTER_HWACCEL(HEVC_D3D11VA2, hevc_d3d11va2); REGISTER_HWACCEL(HEVC_DXVA2, hevc_dxva2); REGISTER_HWACCEL(HEVC_QSV, hevc_qsv); REGISTER_HWACCEL(HEVC_VAAPI, hevc_vaapi); REGISTER_HWACCEL(HEVC_VDPAU, hevc_vdpau); REGISTER_HWACCEL(MPEG1_VDPAU, mpeg1_vdpau); REGISTER_HWACCEL(MPEG2_D3D11VA, mpeg2_d3d11va); + REGISTER_HWACCEL(MPEG2_D3D11VA2, mpeg2_d3d11va2); REGISTER_HWACCEL(MPEG2_DXVA2, mpeg2_dxva2); REGISTER_HWACCEL(MPEG2_MMAL, mpeg2_mmal); REGISTER_HWACCEL(MPEG2_QSV, mpeg2_qsv); @@ -91,6 +94,7 @@ void avcodec_register_all(void) REGISTER_HWACCEL(MPEG4_VAAPI, mpeg4_vaapi); REGISTER_HWACCEL(MPEG4_VDPAU, mpeg4_vdpau); REGISTER_HWACCEL(VC1_D3D11VA, vc1_d3d11va); + REGISTER_HWACCEL(VC1_D3D11VA2, vc1_d3d11va2); REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2); REGISTER_HWACCEL(VC1_QSV, vc1_qsv); REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi); @@ -99,6 +103,7 @@ void avcodec_register_all(void) REGISTER_HWACCEL(VP8_QSV, vp8_qsv); REGISTER_HWACCEL(VP8_VAAPI, vp8_vaapi); REGISTER_HWACCEL(WMV3_D3D11VA, wmv3_d3d11va); + REGISTER_HWACCEL(WMV3_D3D11VA2, wmv3_d3d11va2); REGISTER_HWACCEL(WMV3_DXVA2, wmv3_dxva2); REGISTER_HWACCEL(WMV3_VAAPI, wmv3_vaapi); REGISTER_HWACCEL(WMV3_VDPAU, wmv3_vdpau); diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index 5bc9b30653117..e0c54068d6e81 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -22,20 +22,446 @@ #include #include +#include +#include "libavutil/common.h" #include "libavutil/log.h" #include "libavutil/time.h" #include "avcodec.h" #include "dxva2_internal.h" +/* define all the GUIDs used directly here, + to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */ +DEFINE_GUID(ff_DXVA2_ModeMPEG2_VLD, 0xee27417f, 0x5e28,0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9); +DEFINE_GUID(ff_DXVA2_ModeMPEG2and1_VLD, 0x86695f12, 0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60); +DEFINE_GUID(ff_DXVA2_ModeH264_E, 0x1b81be68, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); +DEFINE_GUID(ff_DXVA2_ModeH264_F, 0x1b81be69, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); +DEFINE_GUID(ff_DXVADDI_Intel_ModeH264_E, 0x604F8E68, 0x4951,0x4C54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6); +DEFINE_GUID(ff_DXVA2_ModeVC1_D, 0x1b81beA3, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); +DEFINE_GUID(ff_DXVA2_ModeVC1_D2010, 0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); +DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main, 0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0); +DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main10,0x107af0e0, 0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13); +DEFINE_GUID(ff_DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); +DEFINE_GUID(ff_GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00); +DEFINE_GUID(ff_IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02); + +typedef struct dxva_mode { + const GUID *guid; + enum AVCodecID codec; +} dxva_mode; + +static const dxva_mode dxva_modes[] = { + /* MPEG-2 */ + { &ff_DXVA2_ModeMPEG2_VLD, AV_CODEC_ID_MPEG2VIDEO }, + { &ff_DXVA2_ModeMPEG2and1_VLD, AV_CODEC_ID_MPEG2VIDEO }, + + /* H.264 */ + { &ff_DXVA2_ModeH264_F, AV_CODEC_ID_H264 }, + { &ff_DXVA2_ModeH264_E, AV_CODEC_ID_H264 }, + /* Intel specific H.264 mode */ + { &ff_DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264 }, + + /* VC-1 / WMV3 */ + { &ff_DXVA2_ModeVC1_D2010, AV_CODEC_ID_VC1 }, + { &ff_DXVA2_ModeVC1_D2010, AV_CODEC_ID_WMV3 }, + { &ff_DXVA2_ModeVC1_D, AV_CODEC_ID_VC1 }, + { &ff_DXVA2_ModeVC1_D, AV_CODEC_ID_WMV3 }, + + /* HEVC/H.265 */ + { &ff_DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC }, + { &ff_DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC }, + + { NULL, 0 }, +}; + +static int dxva_get_decoder_configuration(AVCodecContext *avctx, + const void *cfg_list, + unsigned cfg_count) +{ + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); + unsigned i, best_score = 0; + int best_cfg = -1; + + for (i = 0; i < cfg_count; i++) { + unsigned score; + UINT ConfigBitstreamRaw; + GUID guidConfigBitstreamEncryption; + +#if CONFIG_D3D11VA + if (sctx->pix_fmt == AV_PIX_FMT_D3D11) { + D3D11_VIDEO_DECODER_CONFIG *cfg = &((D3D11_VIDEO_DECODER_CONFIG *)cfg_list)[i]; + ConfigBitstreamRaw = cfg->ConfigBitstreamRaw; + guidConfigBitstreamEncryption = cfg->guidConfigBitstreamEncryption; + } +#endif +#if CONFIG_DXVA2 + if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + DXVA2_ConfigPictureDecode *cfg = &((DXVA2_ConfigPictureDecode *)cfg_list)[i]; + ConfigBitstreamRaw = cfg->ConfigBitstreamRaw; + guidConfigBitstreamEncryption = cfg->guidConfigBitstreamEncryption; + } +#endif + + if (ConfigBitstreamRaw == 1) + score = 1; + else if (avctx->codec_id == AV_CODEC_ID_H264 && ConfigBitstreamRaw == 2) + score = 2; + else + continue; + if (IsEqualGUID(&guidConfigBitstreamEncryption, &ff_DXVA2_NoEncrypt)) + score += 16; + if (score > best_score) { + best_score = score; + best_cfg = i; + } + } + + if (!best_score) { + av_log(avctx, AV_LOG_VERBOSE, "No valid decoder configuration available\n"); + return AVERROR(EINVAL); + } + + return best_cfg; +} + +#if CONFIG_D3D11VA +static int d3d11va_validate_output(void *service, GUID guid, void *surface_format) +{ + HRESULT hr; + BOOL is_supported = FALSE; + hr = ID3D11VideoDevice_CheckVideoDecoderFormat((ID3D11VideoDevice *)service, + &guid, + *(DXGI_FORMAT *)surface_format, + &is_supported); + return SUCCEEDED(hr) && is_supported; +} +#endif + +#if CONFIG_DXVA2 +static int dxva2_validate_output(void *decoder_service, GUID guid, void *surface_format) +{ + HRESULT hr; + int ret = 0; + unsigned j, target_count; + D3DFORMAT *target_list; + hr = IDirectXVideoDecoderService_GetDecoderRenderTargets((IDirectXVideoDecoderService *)decoder_service, &guid, &target_count, &target_list); + if (SUCCEEDED(hr)) { + for (j = 0; j < target_count; j++) { + const D3DFORMAT format = target_list[j]; + if (format == *(D3DFORMAT *)surface_format) { + ret = 1; + break; + } + } + CoTaskMemFree(target_list); + } + return ret; +} +#endif + +static int dxva_get_decoder_guid(AVCodecContext *avctx, void *service, void *surface_format, + unsigned guid_count, const GUID *guid_list, GUID *decoder_guid) +{ + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); + unsigned i, j; + + *decoder_guid = ff_GUID_NULL; + for (i = 0; dxva_modes[i].guid; i++) { + const dxva_mode *mode = &dxva_modes[i]; + int validate; + if (mode->codec != avctx->codec_id) + continue; + + for (j = 0; j < guid_count; j++) { + if (IsEqualGUID(mode->guid, &guid_list[j])) + break; + } + if (j == guid_count) + continue; + +#if CONFIG_D3D11VA + if (sctx->pix_fmt == AV_PIX_FMT_D3D11) + validate = d3d11va_validate_output(service, *mode->guid, surface_format); +#endif +#if CONFIG_DXVA2 + if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) + validate = dxva2_validate_output(service, *mode->guid, surface_format); +#endif + if (validate) { + *decoder_guid = *mode->guid; + break; + } + } + + if (IsEqualGUID(decoder_guid, &ff_GUID_NULL)) { + av_log(avctx, AV_LOG_VERBOSE, "No decoder device for codec found\n"); + return AVERROR(EINVAL); + } + + if (IsEqualGUID(decoder_guid, &ff_DXVADDI_Intel_ModeH264_E)) + sctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO; + + return 0; +} + +static void bufref_free_interface(void *opaque, uint8_t *data) +{ + IUnknown_Release((IUnknown *)opaque); +} + +static AVBufferRef *bufref_wrap_interface(IUnknown *iface) +{ + return av_buffer_create((uint8_t*)iface, 1, bufref_free_interface, iface, 0); +} + +#if CONFIG_DXVA2 + +static int dxva2_get_decoder_configuration(AVCodecContext *avctx, const GUID *device_guid, + const DXVA2_VideoDesc *desc, + DXVA2_ConfigPictureDecode *config) +{ + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); + unsigned cfg_count; + DXVA2_ConfigPictureDecode *cfg_list; + HRESULT hr; + int ret; + + hr = IDirectXVideoDecoderService_GetDecoderConfigurations(sctx->dxva2_service, device_guid, desc, NULL, &cfg_count, &cfg_list); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "Unable to retrieve decoder configurations\n"); + return AVERROR(EINVAL); + } + + ret = dxva_get_decoder_configuration(avctx, cfg_list, cfg_count); + if (ret >= 0) + *config = cfg_list[ret]; + CoTaskMemFree(cfg_list); + return ret; +} + +static int dxva2_create_decoder(AVCodecContext *avctx) +{ + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); + GUID *guid_list; + unsigned guid_count; + GUID device_guid; + D3DFORMAT surface_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? + MKTAG('P', '0', '1', '0') : MKTAG('N', 'V', '1', '2'); + DXVA2_VideoDesc desc = { 0 }; + DXVA2_ConfigPictureDecode config; + HRESULT hr; + int ret; + HANDLE device_handle; + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx; + AVDXVA2DeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; + + hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr, + &device_handle); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "Failed to open a device handle\n"); + goto fail; + } + + hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr, device_handle, + &ff_IID_IDirectXVideoDecoderService, + (void **)&sctx->dxva2_service); + IDirect3DDeviceManager9_CloseDeviceHandle(device_hwctx->devmgr, device_handle); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "Failed to create IDirectXVideoDecoderService\n"); + goto fail; + } + + hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(sctx->dxva2_service, &guid_count, &guid_list); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "Failed to retrieve decoder device GUIDs\n"); + goto fail; + } + + ret = dxva_get_decoder_guid(avctx, sctx->dxva2_service, &surface_format, + guid_count, guid_list, &device_guid); + CoTaskMemFree(guid_list); + if (ret < 0) { + goto fail; + } + + desc.SampleWidth = avctx->coded_width; + desc.SampleHeight = avctx->coded_height; + desc.Format = surface_format; + + ret = dxva2_get_decoder_configuration(avctx, &device_guid, &desc, &config); + if (ret < 0) { + goto fail; + } + + hr = IDirectXVideoDecoderService_CreateVideoDecoder(sctx->dxva2_service, &device_guid, + &desc, &config, frames_hwctx->surfaces, + frames_hwctx->nb_surfaces, &sctx->dxva2_decoder); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "Failed to create DXVA2 video decoder\n"); + goto fail; + } + + sctx->dxva2_config = config; + + sctx->decoder_ref = bufref_wrap_interface((IUnknown *)sctx->dxva2_decoder); + if (!sctx->decoder_ref) + return AVERROR(ENOMEM); + + return 0; +fail: + return AVERROR(EINVAL); +} + +#endif + +#if CONFIG_D3D11VA + +static int d3d11va_get_decoder_configuration(AVCodecContext *avctx, + ID3D11VideoDevice *video_device, + const D3D11_VIDEO_DECODER_DESC *desc, + D3D11_VIDEO_DECODER_CONFIG *config) +{ + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); + unsigned cfg_count = 0; + D3D11_VIDEO_DECODER_CONFIG *cfg_list = NULL; + HRESULT hr; + int i, ret; + + hr = ID3D11VideoDevice_GetVideoDecoderConfigCount(video_device, desc, &cfg_count); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "Unable to retrieve decoder configurations\n"); + return AVERROR(EINVAL); + } + + cfg_list = av_malloc_array(cfg_count, sizeof(D3D11_VIDEO_DECODER_CONFIG)); + if (cfg_list == NULL) + return AVERROR(ENOMEM); + for (i = 0; i < cfg_count; i++) { + hr = ID3D11VideoDevice_GetVideoDecoderConfig(video_device, desc, i, &cfg_list[i]); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "Unable to retrieve decoder configurations. (hr=0x%lX)\n", hr); + av_free(cfg_list); + return AVERROR(EINVAL); + } + } + + ret = dxva_get_decoder_configuration(avctx, cfg_list, cfg_count); + if (ret >= 0) + *config = cfg_list[ret]; + av_free(cfg_list); + return ret; +} + +static int d3d11va_create_decoder(AVCodecContext *avctx) +{ + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); + GUID *guid_list; + unsigned guid_count, i; + GUID decoder_guid; + DXGI_FORMAT surface_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? + DXGI_FORMAT_P010 : DXGI_FORMAT_NV12; + D3D11_VIDEO_DECODER_DESC desc = { 0 }; + D3D11_VIDEO_DECODER_CONFIG config; + AVHWFramesContext *frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; + AVD3D11VADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; + AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx; + D3D11_TEXTURE2D_DESC texdesc; + HRESULT hr; + int ret; + + if (!frames_hwctx->texture) { + av_log(avctx, AV_LOG_ERROR, "AVD3D11VAFramesContext.texture not set.\n"); + return AVERROR(EINVAL); + } + ID3D11Texture2D_GetDesc(frames_hwctx->texture, &texdesc); + + guid_count = ID3D11VideoDevice_GetVideoDecoderProfileCount(device_hwctx->video_device); + guid_list = av_malloc_array(guid_count, sizeof(*guid_list)); + if (guid_list == NULL || guid_count == 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to get the decoder GUIDs\n"); + av_free(guid_list); + return AVERROR(EINVAL); + } + for (i = 0; i < guid_count; i++) { + hr = ID3D11VideoDevice_GetVideoDecoderProfile(device_hwctx->video_device, i, &guid_list[i]); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "Failed to retrieve decoder GUID %d\n", i); + av_free(guid_list); + return AVERROR(EINVAL); + } + } + + ret = dxva_get_decoder_guid(avctx, device_hwctx->video_device, &surface_format, + guid_count, guid_list, &decoder_guid); + av_free(guid_list); + if (ret < 0) + return AVERROR(EINVAL); + + desc.SampleWidth = avctx->coded_width; + desc.SampleHeight = avctx->coded_height; + desc.OutputFormat = surface_format; + desc.Guid = decoder_guid; + + ret = d3d11va_get_decoder_configuration(avctx, device_hwctx->video_device, &desc, &config); + if (ret < 0) + return AVERROR(EINVAL); + + sctx->d3d11_views = av_mallocz_array(texdesc.ArraySize, sizeof(sctx->d3d11_views[0])); + if (!sctx->d3d11_views) + return AVERROR(ENOMEM); + sctx->nb_d3d11_views = texdesc.ArraySize; + + for (i = 0; i < sctx->nb_d3d11_views; i++) { + D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc = { + .DecodeProfile = decoder_guid, + .ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D, + .Texture2D = { + .ArraySlice = i, + } + }; + hr = ID3D11VideoDevice_CreateVideoDecoderOutputView(device_hwctx->video_device, + (ID3D11Resource*) frames_hwctx->texture, + &viewDesc, + (ID3D11VideoDecoderOutputView**) &sctx->d3d11_views[i]); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "Could not create the decoder output view %d\n", i); + return AVERROR_UNKNOWN; + } + } + + hr = ID3D11VideoDevice_CreateVideoDecoder(device_hwctx->video_device, &desc, + &config, &sctx->d3d11_decoder); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "Failed to create D3D11VA video decoder\n"); + return AVERROR(EINVAL); + } + + sctx->d3d11_config = config; + sctx->d3d11_texture = frames_hwctx->texture; + + sctx->decoder_ref = bufref_wrap_interface((IUnknown *)sctx->d3d11_decoder); + if (!sctx->decoder_ref) + return AVERROR(ENOMEM); + + return 0; +} + +#endif + static void ff_dxva2_lock(AVCodecContext *avctx) { #if CONFIG_D3D11VA if (ff_dxva2_is_d3d11(avctx)) { + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); AVDXVAContext *ctx = DXVA_CONTEXT(avctx); if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) WaitForSingleObjectEx(D3D11VA_CONTEXT(ctx)->context_mutex, INFINITE, FALSE); + if (sctx->device_ctx) { + AVD3D11VADeviceContext *hwctx = sctx->device_ctx->hwctx; + hwctx->lock(hwctx->lock_ctx); + } } #endif } @@ -44,15 +470,216 @@ static void ff_dxva2_unlock(AVCodecContext *avctx) { #if CONFIG_D3D11VA if (ff_dxva2_is_d3d11(avctx)) { + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); AVDXVAContext *ctx = DXVA_CONTEXT(avctx); if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex); + if (sctx->device_ctx) { + AVD3D11VADeviceContext *hwctx = sctx->device_ctx->hwctx; + hwctx->unlock(hwctx->lock_ctx); + } + } +#endif +} + +// This must work before the decoder is created. +// This somehow needs to be exported to the user. +static void dxva_adjust_hwframes(AVCodecContext *avctx, AVHWFramesContext *frames_ctx) +{ + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); + int surface_alignment, num_surfaces; + + frames_ctx->format = sctx->pix_fmt; + + /* decoding MPEG-2 requires additional alignment on some Intel GPUs, + but it causes issues for H.264 on certain AMD GPUs..... */ + if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO) + surface_alignment = 32; + /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure + all coding features have enough room to work with */ + else if (avctx->codec_id == AV_CODEC_ID_HEVC) + surface_alignment = 128; + else + surface_alignment = 16; + + /* 4 base work surfaces */ + num_surfaces = 4; + + /* add surfaces based on number of possible refs */ + if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC) + num_surfaces += 16; + else + num_surfaces += 2; + + /* add extra surfaces for frame threading */ + if (avctx->active_thread_type & FF_THREAD_FRAME) + num_surfaces += avctx->thread_count; + + frames_ctx->sw_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? + AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; + frames_ctx->width = FFALIGN(avctx->coded_width, surface_alignment); + frames_ctx->height = FFALIGN(avctx->coded_height, surface_alignment); + frames_ctx->initial_pool_size = num_surfaces; + + +#if CONFIG_DXVA2 + if (frames_ctx->format == AV_PIX_FMT_DXVA2_VLD) { + AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx; + + frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget; + } +#endif + +#if CONFIG_D3D11VA + if (frames_ctx->format == AV_PIX_FMT_D3D11) { + AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx; + + frames_hwctx->BindFlags |= D3D11_BIND_DECODER; } #endif } -static void *get_surface(const AVFrame *frame) +int ff_dxva2_decode_init(AVCodecContext *avctx) { + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); + AVHWFramesContext *frames_ctx = NULL; + int ret = 0; + + // Old API. + if (avctx->hwaccel_context) + return 0; + + // (avctx->pix_fmt is not updated yet at this point) + sctx->pix_fmt = avctx->hwaccel->pix_fmt; + + if (avctx->codec_id == AV_CODEC_ID_H264 && + (avctx->profile & ~FF_PROFILE_H264_CONSTRAINED) > FF_PROFILE_H264_HIGH) { + av_log(avctx, AV_LOG_VERBOSE, "Unsupported H.264 profile for DXVA HWAccel: %d\n",avctx->profile); + return AVERROR(ENOTSUP); + } + + if (avctx->codec_id == AV_CODEC_ID_HEVC && + avctx->profile != FF_PROFILE_HEVC_MAIN && avctx->profile != FF_PROFILE_HEVC_MAIN_10) { + av_log(avctx, AV_LOG_VERBOSE, "Unsupported HEVC profile for DXVA HWAccel: %d\n", avctx->profile); + return AVERROR(ENOTSUP); + } + + if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) { + av_log(avctx, AV_LOG_ERROR, "Either a hw_frames_ctx or a hw_device_ctx needs to be set for hardware decoding.\n"); + return AVERROR(EINVAL); + } + + if (avctx->hw_frames_ctx) { + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + } else { + avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); + if (!avctx->hw_frames_ctx) + return AVERROR(ENOMEM); + + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + + dxva_adjust_hwframes(avctx, frames_ctx); + + ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); + if (ret < 0) + goto fail; + } + + sctx->device_ctx = frames_ctx->device_ctx; + + if (frames_ctx->format != sctx->pix_fmt || + !((sctx->pix_fmt == AV_PIX_FMT_D3D11 && CONFIG_D3D11VA) || + (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && CONFIG_DXVA2))) { + av_log(avctx, AV_LOG_ERROR, "Invalid pixfmt for hwaccel!\n"); + ret = AVERROR(EINVAL); + goto fail; + } + +#if CONFIG_D3D11VA + if (sctx->pix_fmt == AV_PIX_FMT_D3D11) { + AVD3D11VADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; + AVD3D11VAContext *d3d11_ctx = &sctx->ctx.d3d11va; + HRESULT hr; + + ff_dxva2_lock(avctx); + ret = d3d11va_create_decoder(avctx); + ff_dxva2_unlock(avctx); + if (ret < 0) + goto fail; + + d3d11_ctx->decoder = sctx->d3d11_decoder; + d3d11_ctx->video_context = device_hwctx->video_context; + d3d11_ctx->cfg = &sctx->d3d11_config; + d3d11_ctx->surface_count = sctx->nb_d3d11_views; + d3d11_ctx->surface = sctx->d3d11_views; + d3d11_ctx->workaround = sctx->workaround; + d3d11_ctx->context_mutex = INVALID_HANDLE_VALUE; + } +#endif + +#if CONFIG_DXVA2 + if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx; + struct dxva_context *dxva_ctx = &sctx->ctx.dxva2; + + ff_dxva2_lock(avctx); + ret = dxva2_create_decoder(avctx); + ff_dxva2_unlock(avctx); + if (ret < 0) + goto fail; + + dxva_ctx->decoder = sctx->dxva2_decoder; + dxva_ctx->cfg = &sctx->dxva2_config; + dxva_ctx->surface = frames_hwctx->surfaces; + dxva_ctx->surface_count = frames_hwctx->nb_surfaces; + dxva_ctx->workaround = sctx->workaround; + } +#endif + + return 0; + +fail: + ff_dxva2_decode_uninit(avctx); + return ret; +} + +int ff_dxva2_decode_uninit(AVCodecContext *avctx) +{ + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); + int i; + + av_buffer_unref(&sctx->decoder_ref); + +#if CONFIG_D3D11VA + for (i = 0; i < sctx->nb_d3d11_views; i++) { + if (sctx->d3d11_views[i]) + ID3D11VideoDecoderOutputView_Release(sctx->d3d11_views[i]); + } + av_freep(&sctx->d3d11_views); +#endif + +#if CONFIG_DXVA2 + if (sctx->dxva2_service) + IDirectXVideoDecoderService_Release(sctx->dxva2_service); +#endif + + return 0; +} + +static void *get_surface(AVCodecContext *avctx, const AVFrame *frame) +{ +#if CONFIG_D3D11VA + if (frame->format == AV_PIX_FMT_D3D11) { + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); + intptr_t index = (intptr_t)frame->data[1]; + if (index < 0 || index >= sctx->nb_d3d11_views || + sctx->d3d11_texture != (ID3D11Texture2D *)frame->data[0]) { + av_log(avctx, AV_LOG_ERROR, "get_buffer frame is invalid!\n"); + return NULL; + } + return sctx->d3d11_views[index]; + } +#endif return frame->data[3]; } @@ -60,10 +687,12 @@ unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx, const AVDXVAContext *ctx, const AVFrame *frame) { - void *surface = get_surface(frame); + void *surface = get_surface(avctx, frame); unsigned i; #if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11) + return (intptr_t)frame->data[1]; if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc; ID3D11VideoDecoderOutputView_GetDesc((ID3D11VideoDecoderOutputView*) surface, &viewDesc); @@ -154,6 +783,22 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx, return result; } +static int frame_add_buf(AVFrame *frame, AVBufferRef *ref) +{ + int i; + + for (i = 0; i < AV_NUM_DATA_POINTERS; i++) { + if (!frame->buf[i]) { + frame->buf[i] = av_buffer_ref(ref); + return frame->buf[i] ? 0 : AVERROR(ENOMEM); + } + } + + // For now we expect that the caller does not use more than + // AV_NUM_DATA_POINTERS-1 buffers if the user uses a custom pool. + return AVERROR(EINVAL); +} + int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, const void *pp, unsigned pp_size, const void *qm, unsigned qm_size, @@ -173,19 +818,26 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, int result, runs = 0; HRESULT hr; unsigned type; + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); + + if (sctx->decoder_ref) { + result = frame_add_buf(frame, sctx->decoder_ref); + if (result < 0) + return result; + } do { ff_dxva2_lock(avctx); #if CONFIG_D3D11VA if (ff_dxva2_is_d3d11(avctx)) hr = ID3D11VideoContext_DecoderBeginFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, - get_surface(frame), + get_surface(avctx, frame), 0, NULL); #endif #if CONFIG_DXVA2 if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) hr = IDirectXVideoDecoder_BeginFrame(DXVA2_CONTEXT(ctx)->decoder, - get_surface(frame), + get_surface(avctx, frame), NULL); #endif if (hr != E_PENDING || ++runs > 50) @@ -315,7 +967,8 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, int ff_dxva2_is_d3d11(const AVCodecContext *avctx) { if (CONFIG_D3D11VA) - return avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD; + return avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD || + avctx->pix_fmt == AV_PIX_FMT_D3D11; else return 0; } diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c index f58a45807ff3f..de0885058ad2f 100644 --- a/libavcodec/dxva2_h264.c +++ b/libavcodec/dxva2_h264.c @@ -518,10 +518,13 @@ AVHWAccel ff_h264_dxva2_hwaccel = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, .pix_fmt = AV_PIX_FMT_DXVA2_VLD, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, .start_frame = dxva2_h264_start_frame, .decode_slice = dxva2_h264_decode_slice, .end_frame = dxva2_h264_end_frame, .frame_priv_data_size = sizeof(struct dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), }; #endif @@ -531,9 +534,28 @@ AVHWAccel ff_h264_d3d11va_hwaccel = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, .start_frame = dxva2_h264_start_frame, .decode_slice = dxva2_h264_decode_slice, .end_frame = dxva2_h264_end_frame, .frame_priv_data_size = sizeof(struct dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), +}; +#endif + +#if CONFIG_H264_D3D11VA2_HWACCEL +AVHWAccel ff_h264_d3d11va2_hwaccel = { + .name = "h264_d3d11va2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .pix_fmt = AV_PIX_FMT_D3D11, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, + .start_frame = dxva2_h264_start_frame, + .decode_slice = dxva2_h264_decode_slice, + .end_frame = dxva2_h264_end_frame, + .frame_priv_data_size = sizeof(struct dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), }; #endif diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c index f2bb8b26a5103..4bff26d6a8e4f 100644 --- a/libavcodec/dxva2_hevc.c +++ b/libavcodec/dxva2_hevc.c @@ -427,10 +427,13 @@ AVHWAccel ff_hevc_dxva2_hwaccel = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, .pix_fmt = AV_PIX_FMT_DXVA2_VLD, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, .start_frame = dxva2_hevc_start_frame, .decode_slice = dxva2_hevc_decode_slice, .end_frame = dxva2_hevc_end_frame, .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), }; #endif @@ -440,9 +443,28 @@ AVHWAccel ff_hevc_d3d11va_hwaccel = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, .start_frame = dxva2_hevc_start_frame, .decode_slice = dxva2_hevc_decode_slice, .end_frame = dxva2_hevc_end_frame, .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), +}; +#endif + +#if CONFIG_HEVC_D3D11VA2_HWACCEL +AVHWAccel ff_hevc_d3d11va2_hwaccel = { + .name = "hevc_d3d11va2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .pix_fmt = AV_PIX_FMT_D3D11, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, + .start_frame = dxva2_hevc_start_frame, + .decode_slice = dxva2_hevc_decode_slice, + .end_frame = dxva2_hevc_end_frame, + .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), }; #endif diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h index af0d607487fc3..901cc1114489a 100644 --- a/libavcodec/dxva2_internal.h +++ b/libavcodec/dxva2_internal.h @@ -32,9 +32,11 @@ #if CONFIG_DXVA2 #include "dxva2.h" +#include "libavutil/hwcontext_dxva2.h" #endif #if CONFIG_D3D11VA #include "d3d11va.h" +#include "libavutil/hwcontext_d3d11va.h" #endif #if HAVE_DXVA_H /* When targeting WINAPI_FAMILY_PHONE_APP or WINAPI_FAMILY_APP, dxva.h @@ -46,7 +48,10 @@ #include #endif +#include "libavutil/hwcontext.h" + #include "avcodec.h" +#include "internal.h" typedef void DECODER_BUFFER_DESC; @@ -59,7 +64,39 @@ typedef union { #endif } AVDXVAContext; -#define DXVA_CONTEXT(avctx) ((AVDXVAContext *)(avctx)->hwaccel_context) +typedef struct FFDXVASharedContext { + AVBufferRef *decoder_ref; + + // FF_DXVA2_WORKAROUND_* flags + uint64_t workaround; + + // E.g. AV_PIX_FMT_D3D11 (same as AVCodecContext.pix_fmt, except during init) + enum AVPixelFormat pix_fmt; + + AVHWDeviceContext *device_ctx; + +#if CONFIG_D3D11VA + ID3D11VideoDecoder *d3d11_decoder; + D3D11_VIDEO_DECODER_CONFIG d3d11_config; + ID3D11VideoDecoderOutputView **d3d11_views; + int nb_d3d11_views; + ID3D11Texture2D *d3d11_texture; +#endif + +#if CONFIG_DXVA2 + IDirectXVideoDecoder *dxva2_decoder; + IDirectXVideoDecoderService *dxva2_service; + DXVA2_ConfigPictureDecode dxva2_config; +#endif + + // Legacy (but used by code outside of setup) + // In generic mode, DXVA_CONTEXT() will return a pointer to this. + AVDXVAContext ctx; +} FFDXVASharedContext; + +#define DXVA_SHARED_CONTEXT(avctx) ((FFDXVASharedContext *)((avctx)->internal->hwaccel_priv_data)) + +#define DXVA_CONTEXT(avctx) (AVDXVAContext *)((avctx)->hwaccel_context ? (avctx)->hwaccel_context : (&(DXVA_SHARED_CONTEXT(avctx)->ctx))) #define D3D11VA_CONTEXT(ctx) (&ctx->d3d11va) #define DXVA2_CONTEXT(ctx) (&ctx->dxva2) @@ -115,6 +152,10 @@ int ff_dxva2_common_end_frame(AVCodecContext *, AVFrame *, DECODER_BUFFER_DESC *bs, DECODER_BUFFER_DESC *slice)); +int ff_dxva2_decode_init(AVCodecContext *avctx); + +int ff_dxva2_decode_uninit(AVCodecContext *avctx); + int ff_dxva2_is_d3d11(const AVCodecContext *avctx); #endif /* AVCODEC_DXVA2_INTERNAL_H */ diff --git a/libavcodec/dxva2_mpeg2.c b/libavcodec/dxva2_mpeg2.c index 6ae30a5773fcf..ab80ca300a117 100644 --- a/libavcodec/dxva2_mpeg2.c +++ b/libavcodec/dxva2_mpeg2.c @@ -323,10 +323,13 @@ AVHWAccel ff_mpeg2_dxva2_hwaccel = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, .pix_fmt = AV_PIX_FMT_DXVA2_VLD, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, .start_frame = dxva2_mpeg2_start_frame, .decode_slice = dxva2_mpeg2_decode_slice, .end_frame = dxva2_mpeg2_end_frame, .frame_priv_data_size = sizeof(struct dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), }; #endif @@ -336,9 +339,28 @@ AVHWAccel ff_mpeg2_d3d11va_hwaccel = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, .start_frame = dxva2_mpeg2_start_frame, .decode_slice = dxva2_mpeg2_decode_slice, .end_frame = dxva2_mpeg2_end_frame, .frame_priv_data_size = sizeof(struct dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), +}; +#endif + +#if CONFIG_MPEG2_D3D11VA2_HWACCEL +AVHWAccel ff_mpeg2_d3d11va2_hwaccel = { + .name = "mpeg2_d3d11va2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .pix_fmt = AV_PIX_FMT_D3D11, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, + .start_frame = dxva2_mpeg2_start_frame, + .decode_slice = dxva2_mpeg2_decode_slice, + .end_frame = dxva2_mpeg2_end_frame, + .frame_priv_data_size = sizeof(struct dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), }; #endif diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c index b63580ed2ebf7..22d3d299b6cf0 100644 --- a/libavcodec/dxva2_vc1.c +++ b/libavcodec/dxva2_vc1.c @@ -323,10 +323,13 @@ AVHWAccel ff_wmv3_dxva2_hwaccel = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, .pix_fmt = AV_PIX_FMT_DXVA2_VLD, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, .start_frame = dxva2_vc1_start_frame, .decode_slice = dxva2_vc1_decode_slice, .end_frame = dxva2_vc1_end_frame, .frame_priv_data_size = sizeof(struct dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), }; #endif @@ -336,10 +339,13 @@ AVHWAccel ff_vc1_dxva2_hwaccel = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, .pix_fmt = AV_PIX_FMT_DXVA2_VLD, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, .start_frame = dxva2_vc1_start_frame, .decode_slice = dxva2_vc1_decode_slice, .end_frame = dxva2_vc1_end_frame, .frame_priv_data_size = sizeof(struct dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), }; #endif @@ -349,10 +355,29 @@ AVHWAccel ff_wmv3_d3d11va_hwaccel = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, .start_frame = dxva2_vc1_start_frame, .decode_slice = dxva2_vc1_decode_slice, .end_frame = dxva2_vc1_end_frame, .frame_priv_data_size = sizeof(struct dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), +}; +#endif + +#if CONFIG_WMV3_D3D11VA2_HWACCEL +AVHWAccel ff_wmv3_d3d11va2_hwaccel = { + .name = "wmv3_d3d11va2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV3, + .pix_fmt = AV_PIX_FMT_D3D11, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, + .start_frame = dxva2_vc1_start_frame, + .decode_slice = dxva2_vc1_decode_slice, + .end_frame = dxva2_vc1_end_frame, + .frame_priv_data_size = sizeof(struct dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), }; #endif @@ -362,9 +387,28 @@ AVHWAccel ff_vc1_d3d11va_hwaccel = { .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, + .start_frame = dxva2_vc1_start_frame, + .decode_slice = dxva2_vc1_decode_slice, + .end_frame = dxva2_vc1_end_frame, + .frame_priv_data_size = sizeof(struct dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), +}; +#endif + +#if CONFIG_VC1_D3D11VA2_HWACCEL +AVHWAccel ff_vc1_d3d11va2_hwaccel = { + .name = "vc1_d3d11va2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VC1, + .pix_fmt = AV_PIX_FMT_D3D11, + .init = ff_dxva2_decode_init, + .uninit = ff_dxva2_decode_uninit, .start_frame = dxva2_vc1_start_frame, .decode_slice = dxva2_vc1_decode_slice, .end_frame = dxva2_vc1_end_frame, .frame_priv_data_size = sizeof(struct dxva2_picture_context), + .priv_data_size = sizeof(FFDXVASharedContext), }; #endif diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 95e366605c2cd..c9f1dbb86f97f 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -717,7 +717,7 @@ static void init_scan_tables(H264Context *h) static enum AVPixelFormat get_pixel_format(H264Context *h) { #define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \ - CONFIG_H264_D3D11VA_HWACCEL + \ + (CONFIG_H264_D3D11VA_HWACCEL * 2) + \ CONFIG_H264_VAAPI_HWACCEL + \ (CONFIG_H264_VDA_HWACCEL * 2) + \ CONFIG_H264_VDPAU_HWACCEL) @@ -769,6 +769,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h) #endif #if CONFIG_H264_D3D11VA_HWACCEL *fmt++ = AV_PIX_FMT_D3D11VA_VLD; + *fmt++ = AV_PIX_FMT_D3D11; #endif #if CONFIG_H264_VAAPI_HWACCEL *fmt++ = AV_PIX_FMT_VAAPI; diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 69d5908551949..7a9182af9bfe7 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -383,7 +383,7 @@ static void export_stream_params(AVCodecContext *avctx, const HEVCParamSets *ps, static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) { - #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + CONFIG_HEVC_D3D11VA_HWACCEL + \ + #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \ CONFIG_HEVC_VAAPI_HWACCEL + CONFIG_HEVC_VDPAU_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts; @@ -391,6 +391,7 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) sps->pix_fmt == AV_PIX_FMT_YUV420P10) { #if CONFIG_HEVC_D3D11VA_HWACCEL *fmt++ = AV_PIX_FMT_D3D11VA_VLD; + *fmt++ = AV_PIX_FMT_D3D11; #endif #if CONFIG_HEVC_DXVA2_HWACCEL *fmt++ = AV_PIX_FMT_DXVA2_VLD; diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 6702ad1ed73c8..9a9a92701a824 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -1111,6 +1111,7 @@ static const enum AVPixelFormat mpeg12_hwaccel_pixfmt_list_420[] = { #endif #if CONFIG_MPEG2_D3D11VA_HWACCEL AV_PIX_FMT_D3D11VA_VLD, + AV_PIX_FMT_D3D11, #endif #if CONFIG_MPEG2_VAAPI_HWACCEL AV_PIX_FMT_VAAPI, diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 51745c12ec1e1..5e00a33e3d929 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -962,6 +962,7 @@ static const enum AVPixelFormat vc1_hwaccel_pixfmt_list_420[] = { #endif #if CONFIG_VC1_D3D11VA_HWACCEL AV_PIX_FMT_D3D11VA_VLD, + AV_PIX_FMT_D3D11, #endif #if CONFIG_VC1_VAAPI_HWACCEL AV_PIX_FMT_VAAPI, diff --git a/libavcodec/version.h b/libavcodec/version.h index 88f17a1f78097..bc5b8304bd16e 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 3 -#define LIBAVCODEC_VERSION_MICRO 1 +#define LIBAVCODEC_VERSION_MINOR 4 +#define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h index 2290c2606679e..c8e7a5c97847a 100644 --- a/libavutil/hwcontext_dxva2.h +++ b/libavutil/hwcontext_dxva2.h @@ -65,6 +65,9 @@ typedef struct AVDXVA2FramesContext { * * If it is non-NULL, libavutil will call IDirectXVideoDecoder_Release() on * it just before the internal surface pool is freed. + * + * This is for convenience only. Some code uses other methods to manage the + * decoder reference. */ IDirectXVideoDecoder *decoder_to_release; } AVDXVA2FramesContext; From 98ea98069b40c34aa7b762096f8f380012a7dd84 Mon Sep 17 00:00:00 2001 From: Srinath K R Date: Thu, 8 Jun 2017 14:43:54 +0530 Subject: [PATCH 0253/2557] nvenc: Add default value for AVCodecContext::refs AVCodecContext::refs is used to control the DPB size to be used by the encoder. The default value for AVCodecContext::refs as set in libavcodec/options_table.h is 1. This patch sets AVCodecContext::refs to 0 for h264_nvenc and hevc_nvenc in order to let the driver take the decision of the correct DPB size to use in all cases. Signed-off-by: Srinath K R Signed-off-by: Luca Barbato --- libavcodec/nvenc_h264.c | 1 + libavcodec/nvenc_hevc.c | 1 + 2 files changed, 2 insertions(+) diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index 1419c867aa641..f7e5cd05dcd37 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -109,6 +109,7 @@ static const AVCodecDefault defaults[] = { { "qdiff", "-1" }, { "qblur", "-1" }, { "qcomp", "-1" }, + { "refs", "0" }, { NULL }, }; diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index 62f969847a5dd..9102d8a3b32d9 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -107,6 +107,7 @@ static const AVCodecDefault defaults[] = { { "qdiff", "-1" }, { "qblur", "-1" }, { "qcomp", "-1" }, + { "refs", "0" }, { NULL }, }; From 97cfe1d8bd1968143e2ba9aa46ebe9504a835e24 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 10 Jun 2017 16:45:06 +0200 Subject: [PATCH 0254/2557] Convert all AVClass struct declarations to designated initializers. --- libavcodec/aacenc.c | 8 ++++---- libavcodec/ac3enc_fixed.c | 9 +++++++-- libavcodec/ac3enc_float.c | 9 +++++++-- libavcodec/dnxhdenc.c | 8 ++++---- libavcodec/eac3enc.c | 9 +++++++-- libavcodec/flacenc.c | 8 ++++---- libavcodec/libfdk-aacdec.c | 5 ++++- libavcodec/libfdk-aacenc.c | 5 ++++- libavcodec/libilbc.c | 10 ++++++++-- libavcodec/libopencore-amr.c | 5 ++++- libavcodec/libopenh264enc.c | 5 ++++- libavcodec/libvo-amrwbenc.c | 5 ++++- libavcodec/libvorbis.c | 7 ++++++- libavfilter/vf_drawtext.c | 6 +++--- libavfilter/vsrc_movie.c | 6 +++--- libavutil/eval.c | 9 ++++++++- libavutil/file.c | 8 ++++++-- libavutil/imgutils.c | 9 ++++++++- libavutil/tests/opt.c | 6 +++--- 19 files changed, 98 insertions(+), 39 deletions(-) diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index 9b0e99b28d0bd..b7f60fb87283c 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -803,10 +803,10 @@ static const AVOption aacenc_options[] = { }; static const AVClass aacenc_class = { - "AAC encoder", - av_default_item_name, - aacenc_options, - LIBAVUTIL_VERSION_INT, + .class_name = "AAC encoder", + .item_name = av_default_item_name, + .option = aacenc_options, + .version = LIBAVUTIL_VERSION_INT, }; AVCodec ff_aac_encoder = { diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c index cb1c58d578080..a4ab5dfde2c16 100644 --- a/libavcodec/ac3enc_fixed.c +++ b/libavcodec/ac3enc_fixed.c @@ -35,8 +35,13 @@ #define AC3ENC_TYPE AC3ENC_TYPE_AC3_FIXED #include "ac3enc_opts_template.c" -static const AVClass ac3enc_class = { "Fixed-Point AC-3 Encoder", av_default_item_name, - ac3_options, LIBAVUTIL_VERSION_INT }; + +static const AVClass ac3enc_class = { + .class_name = "Fixed-Point AC-3 Encoder", + .item_name = av_default_item_name, + .option = ac3_options, + .version = LIBAVUTIL_VERSION_INT, +}; /* * Normalize the input samples to use the maximum available precision. diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c index 249f9edd11c62..95acea77704ae 100644 --- a/libavcodec/ac3enc_float.c +++ b/libavcodec/ac3enc_float.c @@ -36,8 +36,13 @@ #define AC3ENC_TYPE AC3ENC_TYPE_AC3 #include "ac3enc_opts_template.c" -static const AVClass ac3enc_class = { "AC-3 Encoder", av_default_item_name, - ac3_options, LIBAVUTIL_VERSION_INT }; + +static const AVClass ac3enc_class = { + .class_name = "AC-3 Encoder", + .item_name = av_default_item_name, + .option = ac3_options, + .version = LIBAVUTIL_VERSION_INT, +}; /* diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c index 9d4b05292a663..639debfa06eac 100644 --- a/libavcodec/dnxhdenc.c +++ b/libavcodec/dnxhdenc.c @@ -52,10 +52,10 @@ static const AVOption options[] = { }; static const AVClass class = { - "dnxhd", - av_default_item_name, - options, - LIBAVUTIL_VERSION_INT + .class_name = "dnxhd", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, }; static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *restrict block, diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c index 3aa2d54013fb1..17757bebefb58 100644 --- a/libavcodec/eac3enc.c +++ b/libavcodec/eac3enc.c @@ -34,8 +34,13 @@ #define AC3ENC_TYPE AC3ENC_TYPE_EAC3 #include "ac3enc_opts_template.c" -static const AVClass eac3enc_class = { "E-AC-3 Encoder", av_default_item_name, - ac3_options, LIBAVUTIL_VERSION_INT }; + +static const AVClass eac3enc_class = { + .class_name = "E-AC-3 Encoder", + .item_name = av_default_item_name, + .option = ac3_options, + .version = LIBAVUTIL_VERSION_INT, +}; /** diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c index 0c1e6b7673a97..2745b17a1cb03 100644 --- a/libavcodec/flacenc.c +++ b/libavcodec/flacenc.c @@ -1359,10 +1359,10 @@ static const AVOption options[] = { }; static const AVClass flac_encoder_class = { - "FLAC encoder", - av_default_item_name, - options, - LIBAVUTIL_VERSION_INT, + .class_name = "FLAC encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, }; AVCodec ff_flac_encoder = { diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c index cdf7a0571fd81..637d1352a0a83 100644 --- a/libavcodec/libfdk-aacdec.c +++ b/libavcodec/libfdk-aacdec.c @@ -79,7 +79,10 @@ static const AVOption fdk_aac_dec_options[] = { }; static const AVClass fdk_aac_dec_class = { - "libfdk-aac decoder", av_default_item_name, fdk_aac_dec_options, LIBAVUTIL_VERSION_INT + .class_name = "libfdk-aac decoder", + .item_name = av_default_item_name, + .option = fdk_aac_dec_options, + .version = LIBAVUTIL_VERSION_INT }; static int get_stream_info(AVCodecContext *avctx) diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c index 2cea58f152e11..03879bbf5adbc 100644 --- a/libavcodec/libfdk-aacenc.c +++ b/libavcodec/libfdk-aacenc.c @@ -54,7 +54,10 @@ static const AVOption aac_enc_options[] = { }; static const AVClass aac_enc_class = { - "libfdk_aac", av_default_item_name, aac_enc_options, LIBAVUTIL_VERSION_INT + .class_name = "libfdk_aac", + .item_name = av_default_item_name, + .option = aac_enc_options, + .version = LIBAVUTIL_VERSION_INT, }; static const char *aac_get_error(AACENC_ERROR err) diff --git a/libavcodec/libilbc.c b/libavcodec/libilbc.c index a5b2f3a18bdff..80b69a562cbf5 100644 --- a/libavcodec/libilbc.c +++ b/libavcodec/libilbc.c @@ -51,7 +51,10 @@ static const AVOption ilbc_dec_options[] = { }; static const AVClass ilbc_dec_class = { - "libilbc", av_default_item_name, ilbc_dec_options, LIBAVUTIL_VERSION_INT + .class_name = "libilbc", + .item_name = av_default_item_name, + .option = ilbc_dec_options, + .version = LIBAVUTIL_VERSION_INT, }; static av_cold int ilbc_decode_init(AVCodecContext *avctx) @@ -126,7 +129,10 @@ static const AVOption ilbc_enc_options[] = { }; static const AVClass ilbc_enc_class = { - "libilbc", av_default_item_name, ilbc_enc_options, LIBAVUTIL_VERSION_INT + .class_name = "libilbc", + .item_name = av_default_item_name, + .option = ilbc_enc_options, + .version = LIBAVUTIL_VERSION_INT, }; static av_cold int ilbc_encode_init(AVCodecContext *avctx) diff --git a/libavcodec/libopencore-amr.c b/libavcodec/libopencore-amr.c index 27ab7d202fbe5..8200f6719c647 100644 --- a/libavcodec/libopencore-amr.c +++ b/libavcodec/libopencore-amr.c @@ -184,7 +184,10 @@ static const AVOption options[] = { }; static const AVClass class = { - "libopencore_amrnb", av_default_item_name, options, LIBAVUTIL_VERSION_INT + .class_name = "libopencore_amrnb", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, }; static av_cold int amr_nb_encode_init(AVCodecContext *avctx) diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index b7c011893ea1a..3b32790bae5ee 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -75,7 +75,10 @@ static const AVOption options[] = { }; static const AVClass class = { - "libopenh264enc", av_default_item_name, options, LIBAVUTIL_VERSION_INT + .class_name = "libopenh264enc", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, }; static av_cold int svc_encode_close(AVCodecContext *avctx) diff --git a/libavcodec/libvo-amrwbenc.c b/libavcodec/libvo-amrwbenc.c index 5fc904cd8f504..5439d661103d4 100644 --- a/libavcodec/libvo-amrwbenc.c +++ b/libavcodec/libvo-amrwbenc.c @@ -46,7 +46,10 @@ static const AVOption options[] = { }; static const AVClass class = { - "libvo_amrwbenc", av_default_item_name, options, LIBAVUTIL_VERSION_INT + .class_name = "libvo_amrwbenc", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, }; static int get_wb_bitrate_mode(int bitrate, void *log_ctx) diff --git a/libavcodec/libvorbis.c b/libavcodec/libvorbis.c index 86c1ed6a75a53..3dfd589476d16 100644 --- a/libavcodec/libvorbis.c +++ b/libavcodec/libvorbis.c @@ -72,7 +72,12 @@ static const AVCodecDefault defaults[] = { { NULL }, }; -static const AVClass class = { "libvorbis", av_default_item_name, options, LIBAVUTIL_VERSION_INT }; +static const AVClass class = { + .class_name = "libvorbis", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; static int vorbis_error_to_averror(int ov_err) diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 5668c8e8e0b23..a5e3f911b4aef 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -209,9 +209,9 @@ static const char *drawtext_get_name(void *ctx) } static const AVClass drawtext_class = { - "DrawTextContext", - drawtext_get_name, - drawtext_options + .class_name = "DrawTextContext", + .item_name = drawtext_get_name, + .option = drawtext_options, }; #undef __FTERRORS_H__ diff --git a/libavfilter/vsrc_movie.c b/libavfilter/vsrc_movie.c index 7fc99258488b5..aff6e620ff1af 100644 --- a/libavfilter/vsrc_movie.c +++ b/libavfilter/vsrc_movie.c @@ -81,9 +81,9 @@ static const char *movie_get_name(void *ctx) } static const AVClass movie_class = { - "MovieContext", - movie_get_name, - movie_options + .class_name = "MovieContext", + .item_name = movie_get_name, + .option = movie_options, }; static av_cold int movie_init(AVFilterContext *ctx) diff --git a/libavutil/eval.c b/libavutil/eval.c index b5d71c6000e44..7d7c16e927a4d 100644 --- a/libavutil/eval.c +++ b/libavutil/eval.c @@ -52,7 +52,14 @@ typedef struct Parser { double var[VARS]; } Parser; -static const AVClass class = { "Eval", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, offsetof(Parser,log_offset), offsetof(Parser,log_ctx) }; +static const AVClass class = { + .class_name = "Eval", + .item_name = av_default_item_name, + .option = NULL, + .version = LIBAVUTIL_VERSION_INT, + .log_level_offset_offset = offsetof(Parser, log_offset), + .parent_log_context_offset = offsetof(Parser, log_ctx), +}; static const int8_t si_prefixes['z' - 'E' + 1] = { ['y'-'E']= -24, diff --git a/libavutil/file.c b/libavutil/file.c index 18a110aeeb4ac..05ed2479a248d 100644 --- a/libavutil/file.c +++ b/libavutil/file.c @@ -42,8 +42,12 @@ typedef struct FileLogContext { } FileLogContext; static const AVClass file_log_ctx_class = { - "FILE", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, - offsetof(FileLogContext, log_offset), offsetof(FileLogContext, log_ctx) + .class_name = "FILE", + .item_name = av_default_item_name, + .option = NULL, + .version = LIBAVUTIL_VERSION_INT, + .log_level_offset_offset = offsetof(FileLogContext, log_offset), + .parent_log_context_offset = offsetof(FileLogContext, log_ctx), }; int av_file_map(const char *filename, uint8_t **bufptr, size_t *size, diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c index 20d06ec1759e9..84abb11656e99 100644 --- a/libavutil/imgutils.c +++ b/libavutil/imgutils.c @@ -219,7 +219,14 @@ typedef struct ImgUtils { void *log_ctx; } ImgUtils; -static const AVClass imgutils_class = { "IMGUTILS", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, offsetof(ImgUtils, log_offset), offsetof(ImgUtils, log_ctx) }; +static const AVClass imgutils_class = { + .class_name = "IMGUTILS", + .item_name = av_default_item_name, + .option = NULL, + .version = LIBAVUTIL_VERSION_INT, + .log_level_offset_offset = offsetof(ImgUtils, log_offset), + .parent_log_context_offset = offsetof(ImgUtils, log_ctx), +}; int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx) { diff --git a/libavutil/tests/opt.c b/libavutil/tests/opt.c index 350ce3d8202f4..9ed9d2b6b1fd4 100644 --- a/libavutil/tests/opt.c +++ b/libavutil/tests/opt.c @@ -59,9 +59,9 @@ static const char *test_get_name(void *ctx) } static const AVClass test_class = { - "TestContext", - test_get_name, - test_options + .class_name = "TestContext", + .item_name = test_get_name, + .option = test_options, }; int main(void) From d76479c5020ca43e67d47ba3767146b192dc4782 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 12 Jun 2017 11:48:57 +0200 Subject: [PATCH 0255/2557] ppc: Drop support for Apple GCC Apple GCC has not been a thing anymore on PowerPC since many years. --- configure | 10 +++------- libavutil/ppc/util_altivec.h | 5 +---- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 019902cee6b12..b0be55a66ea3d 100755 --- a/configure +++ b/configure @@ -1547,7 +1547,6 @@ HAVE_LIST_PUB=" HEADERS_LIST=" AVFoundation_AVFoundation_h alsa_asoundlib_h - altivec_h arpa_inet_h cdio_paranoia_h cdio_paranoia_paranoia_h @@ -4442,15 +4441,12 @@ elif enabled ppc; then check_inline_asm ppc4xx '"maclhw r10, r11, r12"' check_inline_asm xform_asm '"lwzx %1, %y0" :: "Z"(*(int*)0), "r"(0)' - # AltiVec flags: The FSF version of GCC differs from the Apple version if enabled altivec; then - check_cflags -maltivec -mabi=altivec && - { check_header altivec.h && inc_altivec_h="#include " ; } || - check_cflags -faltivec + check_cflags -maltivec -mabi=altivec # check if our compiler supports Motorola AltiVec C API check_cc < int main(void) { vector signed int v1 = (vector signed int) { 0 }; vector signed int v2 = (vector signed int) { 1 }; @@ -4465,7 +4461,7 @@ EOF if enabled vsx; then check_cflags -mvsx && check_cc < int main(void) { int v[4] = { 0 }; vector signed int v1 = vec_vsx_ld(0, v); diff --git a/libavutil/ppc/util_altivec.h b/libavutil/ppc/util_altivec.h index 5a16e8de13ca5..3cb473b73472f 100644 --- a/libavutil/ppc/util_altivec.h +++ b/libavutil/ppc/util_altivec.h @@ -28,10 +28,6 @@ #include "config.h" -#if HAVE_ALTIVEC_H -#include -#endif - /*********************************************************************** * Vector types **********************************************************************/ @@ -56,6 +52,7 @@ #define zero_s32v (vec_s32) zerov #if HAVE_ALTIVEC +#include // used to build registers permutation vectors (vcprm) // the 's' are for words in the _s_econd vector From e2edf1529cb35eaf043e3f8e5cba498ed06e2563 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 26 May 2017 19:04:51 +0200 Subject: [PATCH 0256/2557] configure: Simplify AltiVec/VSX check with a helper function --- configure | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/configure b/configure index b0be55a66ea3d..7e38f0d92b15c 100755 --- a/configure +++ b/configure @@ -4445,29 +4445,19 @@ elif enabled ppc; then check_cflags -maltivec -mabi=altivec # check if our compiler supports Motorola AltiVec C API - check_cc < -int main(void) { - vector signed int v1 = (vector signed int) { 0 }; - vector signed int v2 = (vector signed int) { 1 }; - v1 = vec_add(v1, v2); - return 0; -} -EOF + check_code cc altivec.h "vector signed int v1 = (vector signed int) { 0 }; + vector signed int v2 = (vector signed int) { 1 }; + v1 = vec_add(v1, v2);" || + disable altivec enabled altivec || warn "Altivec disabled, possibly missing --cpu flag" fi if enabled vsx; then check_cflags -mvsx && - check_cc < -int main(void) { - int v[4] = { 0 }; - vector signed int v1 = vec_vsx_ld(0, v); - return 0; -} -EOF + check_code cc altivec.h "int v[4] = { 0 }; + vector signed int v1 = vec_vsx_ld(0, v);" || + disable vsx fi if enabled power8; then From 04f691cd4fb7d226e54df886a21ba201cb5019f4 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 12 Jun 2017 11:01:14 +0200 Subject: [PATCH 0257/2557] mmal: Add missing .item_name to AVClass declaration --- libavcodec/mmaldec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index e64ddbabce13d..023ebe80de564 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -817,6 +817,7 @@ static const AVOption options[]={ #define FFMMAL_DEC_CLASS(NAME) \ static const AVClass ffmmal_##NAME##_dec_class = { \ .class_name = "mmal_" #NAME "_dec", \ + .item_name = av_default_item_name, \ .option = options, \ .version = LIBAVUTIL_VERSION_INT, \ }; From f61265571d68c410f5307c240a7f9c95c247fb54 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 25 May 2017 03:21:50 +0200 Subject: [PATCH 0258/2557] libfdk-aacdec: Correct buffer_size parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The timeDataSize argument to aacDecoder_DecodeFrame() seems undocumented and until 2016 04 (203e3f28fbebec7011342017fafc2a0bda0ce530) unused. After that commit libfdk-aacdec interprets it as size in sample units and memsets that on error. FFmpeg as well as others (like GStreamer) did interpret it as size in bytes. Fixes: 1442/clusterfuzz-testcase-minimized-4540199973421056 (This requires recent libfdk to reproduce) Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Martin Storsjö --- libavcodec/libfdk-aacdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c index 637d1352a0a83..aa30f93ef6dc1 100644 --- a/libavcodec/libfdk-aacdec.c +++ b/libavcodec/libfdk-aacdec.c @@ -328,7 +328,7 @@ static int fdk_aac_decode_frame(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; } - err = aacDecoder_DecodeFrame(s->handle, (INT_PCM *) s->decoder_buffer, s->decoder_buffer_size, 0); + err = aacDecoder_DecodeFrame(s->handle, (INT_PCM *) s->decoder_buffer, s->decoder_buffer_size / sizeof(INT_PCM), 0); if (err == AAC_DEC_NOT_ENOUGH_BITS) { ret = avpkt->size - valid; goto end; From 4993a68f0f9285f92a42a54305dc0244665b7db4 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 13 Jun 2017 22:27:31 +0100 Subject: [PATCH 0259/2557] hwcontext: Mark local table static const --- libavutil/hwcontext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index d82df56abf157..6dc95bba15988 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -50,7 +50,7 @@ static const HWContextType * const hw_table[] = { NULL, }; -const char *hw_type_names[] = { +static const char *const hw_type_names[] = { [AV_HWDEVICE_TYPE_CUDA] = "cuda", [AV_HWDEVICE_TYPE_DXVA2] = "dxva2", [AV_HWDEVICE_TYPE_D3D11VA] = "d3d11va", From de099641d55627ef3755f05e0364bdec356a0076 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 11 Jun 2017 23:50:24 +0200 Subject: [PATCH 0260/2557] build: Add missing mpeg4audio dependency for RTP muxer --- libavcodec/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index a1bb4b5950592..240f7d83a173b 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -669,6 +669,7 @@ OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MOV_DEMUXER) += ac3tab.o OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o +OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o OBJS-$(CONFIG_SPDIF_MUXER) += dca.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o From 2f792cb6703b5b12f2e873bee13f33da8aa9940a Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 7 Jun 2017 12:48:00 +0200 Subject: [PATCH 0261/2557] build: Add missing idctdsp dependency for clearvideo --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 7e38f0d92b15c..50ae3093e8226 100755 --- a/configure +++ b/configure @@ -1991,6 +1991,7 @@ bink_decoder_select="blockdsp hpeldsp" binkaudio_dct_decoder_select="mdct rdft dct sinewin wma_freqs" binkaudio_rdft_decoder_select="mdct rdft sinewin wma_freqs" cavs_decoder_select="blockdsp golomb h264chroma idctdsp qpeldsp videodsp" +clearvideo_decoder_select="idctdsp" cllc_decoder_select="bswapdsp" comfortnoise_encoder_select="lpc" cook_decoder_select="audiodsp mdct sinewin" From 9d12dd6fa84d9f6094bdf0fdae62527ecec0bbb6 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 6 Jun 2017 18:56:24 +0200 Subject: [PATCH 0262/2557] configure: Add x86 dependency for mmx_internal This ensures that mmx_internal is only ever enabled on x86. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 50ae3093e8226..c99b397ba4b1c 100755 --- a/configure +++ b/configure @@ -1915,7 +1915,7 @@ fma4_deps="avx" avx2_deps="avx" mmx_external_deps="x86asm" -mmx_inline_deps="inline_asm" +mmx_inline_deps="inline_asm x86" mmx_suggest="mmx_external mmx_inline" for ext in $(filter_out mmx $ARCH_EXT_LIST_X86_SIMD); do From d9da7151eef7fc469787e7298196cea291acfd82 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 24 May 2017 17:59:59 +0200 Subject: [PATCH 0263/2557] configure: Fix handling of _select dependencies The handling of _select dependencies had two issues: 1) extralibs from _select dependencies of a component were not added to the list of extralibs for that component. 2) extralibs from dependencies were only added to the extralibs of a component if the component was enabled. This led to incorrect results if that component was enabled by another component later in the dependency resolution process. Instead, always generate the full list of component extralibs for use later in the dependency resolution process. Also remove a leftover unused variable. --- configure | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/configure b/configure index 4450ce418d112..fd879bc9d1502 100755 --- a/configure +++ b/configure @@ -617,7 +617,6 @@ check_deps(){ enabled ${cfg}_checking && die "Circular dependency for $cfg." disabled ${cfg}_checking && continue enable ${cfg}_checking - append allopts $cfg eval dep_all="\$${cfg}_deps" eval dep_any="\$${cfg}_deps_any" @@ -638,15 +637,13 @@ check_deps(){ disabled_all $dep_con || disable $cfg disabled_any $dep_sel && disable $cfg - if enabled $cfg; then - enable_deep $dep_sel - enable_deep_weak $dep_sgs - for dep in $dep_all $dep_any $dep_sgs; do - # filter out library deps, these do not belong in extralibs - is_in $dep $LIBRARY_LIST && continue - enabled $dep && eval append ${cfg}_extralibs ${dep}_extralibs - done - fi + enabled $cfg && enable_deep_weak $dep_sel $dep_sgs + + for dep in $dep_all $dep_any $dep_sel $dep_sgs; do + # filter out library deps, these do not belong in extralibs + is_in $dep $LIBRARY_LIST && continue + enabled $dep && eval append ${cfg}_extralibs ${dep}_extralibs + done disable ${cfg}_checking done From c599c43fa147d7a001cdbf8f3b7da0a965f2e285 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 6 Jun 2017 19:06:10 +0200 Subject: [PATCH 0264/2557] configure: Add missing arch dependencies for arch extensions --- configure | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/configure b/configure index c99b397ba4b1c..995928069e369 100755 --- a/configure +++ b/configure @@ -1889,10 +1889,22 @@ vfpv3_deps="vfp" map 'eval ${v}_inline_deps=inline_asm' $ARCH_EXT_LIST_ARM altivec_deps="ppc" +dcbzl_deps="ppc" +ldbrx_deps="ppc" ppc4xx_deps="ppc" vsx_deps="altivec" power8_deps="vsx" +loongson_deps="mips" +mips32r1_deps="mips32" +mips32r2_deps="mips32" +mips32r6_deps="mips32" +mips64r1_deps="mips64" +mips64r2_deps="mips64" +mips64r6_deps="mips64" + +vis_deps="sparc" + cpunop_deps="i686" x86_64_select="i686" x86_64_suggest="fast_cmov" From 635897ac78ef29869f0321ab921c91b3e1aad453 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 6 Jun 2017 17:41:11 +0200 Subject: [PATCH 0265/2557] configure: Factorize qsv dependencies --- configure | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/configure b/configure index 995928069e369..39157b6ec5598 100755 --- a/configure +++ b/configure @@ -2253,6 +2253,7 @@ wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" nvenc_deps_any="libdl LoadLibrary" omx_deps="libdl pthreads" omx_rpi_select="omx" +qsv_deps="libmfx" qsvdec_select="qsv" qsvenc_select="qsv" vaapi_encode_deps="vaapi" @@ -2263,33 +2264,25 @@ scale_npp_filter_deps="cuda libnpp" h264_mmal_decoder_deps="mmal" h264_nvenc_encoder_deps="nvenc" h264_omx_encoder_deps="omx" -h264_qsv_decoder_deps="libmfx" h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec h264_qsv_hwaccel" -h264_qsv_encoder_deps="libmfx" h264_qsv_encoder_select="qsvenc" h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" h264_vaapi_encoder_select="vaapi_encode golomb" hevc_nvenc_encoder_deps="nvenc" -hevc_qsv_decoder_deps="libmfx" hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser hevc_qsv_hwaccel qsvdec" -hevc_qsv_encoder_deps="libmfx" hevc_qsv_encoder_select="hevc_ps qsvenc" hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" hevc_vaapi_encoder_select="vaapi_encode golomb" mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG" mjpeg_vaapi_encoder_select="vaapi_encode jpegtables" mpeg2_mmal_decoder_deps="mmal" -mpeg2_qsv_decoder_deps="libmfx" mpeg2_qsv_decoder_select="qsvdec mpeg2_qsv_hwaccel mpegvideo_parser" -mpeg2_qsv_encoder_deps="libmfx" mpeg2_qsv_encoder_select="qsvenc" mpeg2_vaapi_encoder_deps="VAEncPictureParameterBufferMPEG2" mpeg2_vaapi_encoder_select="vaapi_encode" mpeg4_omx_encoder_deps="omx" vc1_mmal_decoder_deps="mmal" -vc1_qsv_decoder_deps="libmfx" vc1_qsv_decoder_select="qsvdec vc1_qsv_hwaccel vc1_parser" -vp8_qsv_decoder_deps="libmfx" vp8_qsv_decoder_select="qsvdec vp8_qsv_hwaccel vp8_parser" vp8_vaapi_encoder_deps="VAEncPictureParameterBufferVP8" vp8_vaapi_encoder_select="vaapi_encode" From 7b1f9873be2f9d5aea2762c9197ff46df82768dc Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 12 Jun 2017 21:33:35 +0200 Subject: [PATCH 0266/2557] build: Adjust dependencies for faan(i)dct components --- configure | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 39157b6ec5598..4450ce418d112 100755 --- a/configure +++ b/configure @@ -1961,8 +1961,10 @@ threads_if_any="$THREADS_LIST" dct_select="rdft" dirac_parse_select="golomb" error_resilience_select="me_cmp" -faandct_deps="faan fdctdsp" -faanidct_deps="faan idctdsp" +faandct_deps="faan" +faandct_select="fdctdsp" +faanidct_deps="faan" +faanidct_select="idctdsp" h264dsp_select="startcode" hevc_ps_select="golomb" intrax8_select="blockdsp idctdsp" From 5635c80bf59d90e63ede473e2c014647850a8446 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Fri, 16 Jun 2017 23:08:47 +0100 Subject: [PATCH 0267/2557] vf_hwmap: Add missing error code --- libavfilter/vf_hwmap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c index 2983528ea05da..48ebbb6bd678d 100644 --- a/libavfilter/vf_hwmap.c +++ b/libavfilter/vf_hwmap.c @@ -73,6 +73,7 @@ static int hwmap_config_output(AVFilterLink *outlink) type = av_hwdevice_find_type_by_name(ctx->derive_device_type); if (type == AV_HWDEVICE_TYPE_NONE) { av_log(avctx, AV_LOG_ERROR, "Invalid device type.\n"); + err = AVERROR(EINVAL); goto fail; } From a670eea56087d0ecd4fbeccf3a9beb9110b7031f Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Fri, 16 Jun 2017 23:11:51 +0100 Subject: [PATCH 0268/2557] vf_hwmap: Properly free a locally derived device --- libavfilter/vf_hwmap.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c index 48ebbb6bd678d..b28cb214565cd 100644 --- a/libavfilter/vf_hwmap.c +++ b/libavfilter/vf_hwmap.c @@ -54,7 +54,7 @@ static int hwmap_config_output(AVFilterLink *outlink) AVHWFramesContext *hwfc; AVBufferRef *device; const AVPixFmtDescriptor *desc; - int err; + int err, device_is_derived; av_log(avctx, AV_LOG_DEBUG, "Configure hwmap %s -> %s.\n", av_get_pix_fmt_name(inlink->format), @@ -63,6 +63,7 @@ static int hwmap_config_output(AVFilterLink *outlink) av_buffer_unref(&ctx->hwframes_ref); device = avctx->hw_device_ctx; + device_is_derived = 0; if (inlink->hw_frames_ctx) { hwfc = (AVHWFramesContext*)inlink->hw_frames_ctx->data; @@ -84,6 +85,7 @@ static int hwmap_config_output(AVFilterLink *outlink) "device context: %d.\n", err); goto fail; } + device_is_derived = 1; } desc = av_pix_fmt_desc_get(outlink->format); @@ -238,9 +240,13 @@ static int hwmap_config_output(AVFilterLink *outlink) outlink->w = inlink->w; outlink->h = inlink->h; + if (device_is_derived) + av_buffer_unref(&device); return 0; fail: + if (device_is_derived) + av_buffer_unref(&device); av_buffer_unref(&ctx->hwframes_ref); return err; } From c2b0bea40f1fd4399ff6184a2df4f397c0f4b3ab Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Fri, 16 Jun 2017 23:18:55 +0100 Subject: [PATCH 0269/2557] avconv_hw: Free device on initialisation failure --- avtools/avconv_hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/avtools/avconv_hw.c b/avtools/avconv_hw.c index 94be7233041cf..36ef86692778c 100644 --- a/avtools/avconv_hw.c +++ b/avtools/avconv_hw.c @@ -75,7 +75,7 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out) char *type_name = NULL, *name = NULL, *device = NULL; enum AVHWDeviceType type; HWDevice *dev, *src; - AVBufferRef *device_ref; + AVBufferRef *device_ref = NULL; int err; const char *errmsg, *p, *q; size_t k; @@ -208,6 +208,7 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out) fail: av_log(NULL, AV_LOG_ERROR, "Device creation failed: %d.\n", err); + av_buffer_unref(&device_ref); goto done; } From fd1ffa1f10e940165035ccb79d4a6523da196062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 9 Jun 2017 12:05:00 +0300 Subject: [PATCH 0270/2557] d3d11va: Link directly to dxgi.dll and d3d11.dll functions if LoadLibrary is unavailable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When targeting the UWP API subset, the LoadLibrary function is not available (and the fallback, LoadPackagedLibrary, can't be used to load system DLLs). In these cases, link directly to the functions in the DLLs instead of trying to load them dynamically at runtime. Signed-off-by: Martin Storsjö --- configure | 4 ++ libavutil/hwcontext_d3d11va.c | 80 ++++++++++++++++++++--------------- 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/configure b/configure index fd879bc9d1502..22de1b358e24b 100755 --- a/configure +++ b/configure @@ -4876,6 +4876,10 @@ if enabled libxcb; then check_pkg_config libxcb_xfixes xcb-xfixes xcb/xfixes.h xcb_xfixes_get_cursor_image fi +# d3d11va requires linking directly to dxgi and d3d11 if not building for +# the desktop api partition +enabled LoadLibrary || d3d11va_extralibs="-ldxgi -ld3d11" + enabled vaapi && require vaapi va/va.h vaInitialize -lva enabled vaapi && diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 3940502868c65..5432dd8b51b87 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -18,6 +18,10 @@ #include +// Include thread.h before redefining _WIN32_WINNT, to get +// the right implementation for AVOnce +#include "thread.h" + #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 @@ -39,6 +43,34 @@ typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory); +static AVOnce functions_loaded = AV_ONCE_INIT; + +static PFN_CREATE_DXGI_FACTORY mCreateDXGIFactory; +static PFN_D3D11_CREATE_DEVICE mD3D11CreateDevice; + +static av_cold void load_functions(void) +{ +#if HAVE_LOADLIBRARY + // We let these "leak" - this is fine, as unloading has no great benefit, and + // Windows will mark a DLL as loaded forever if its internal refcount overflows + // from too many LoadLibrary calls. + HANDLE d3dlib, dxgilib; + + d3dlib = LoadLibrary("d3d11.dll"); + dxgilib = LoadLibrary("dxgi.dll"); + if (!d3dlib || !dxgilib) + return; + + mD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE) GetProcAddress(d3dlib, "D3D11CreateDevice"); + mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) GetProcAddress(dxgilib, "CreateDXGIFactory"); +#else + // In UWP (which lacks LoadLibrary), CreateDXGIFactory isn't available, + // only CreateDXGIFactory1 + mD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE) D3D11CreateDevice; + mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) CreateDXGIFactory1; +#endif +} + typedef struct D3D11VAFramesContext { int nb_surfaces_used; @@ -407,50 +439,32 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags) { AVD3D11VADeviceContext *device_hwctx = ctx->hwctx; - HANDLE d3dlib; HRESULT hr; - PFN_D3D11_CREATE_DEVICE createD3D; IDXGIAdapter *pAdapter = NULL; ID3D10Multithread *pMultithread; UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT; + int ret; - if (device) { - PFN_CREATE_DXGI_FACTORY mCreateDXGIFactory; - HMODULE dxgilib = LoadLibrary("dxgi.dll"); - if (!dxgilib) - return AVERROR_UNKNOWN; - - mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) GetProcAddress(dxgilib, "CreateDXGIFactory"); - if (mCreateDXGIFactory) { - IDXGIFactory2 *pDXGIFactory; - hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&pDXGIFactory); - if (SUCCEEDED(hr)) { - int adapter = atoi(device); - if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, &pAdapter))) - pAdapter = NULL; - IDXGIFactory2_Release(pDXGIFactory); - } - } - FreeLibrary(dxgilib); - } - - // We let this "leak" - this is fine, as unloading has no great benefit, and - // Windows will mark a DLL as loaded forever if its internal refcount overflows - // from too many LoadLibrary calls. - d3dlib = LoadLibrary("d3d11.dll"); - if (!d3dlib) { - av_log(ctx, AV_LOG_ERROR, "Failed to load D3D11 library\n"); + if ((ret = ff_thread_once(&functions_loaded, load_functions)) != 0) + return AVERROR_UNKNOWN; + if (!mD3D11CreateDevice || !mCreateDXGIFactory) { + av_log(ctx, AV_LOG_ERROR, "Failed to load D3D11 library or its functions\n"); return AVERROR_UNKNOWN; } - createD3D = (PFN_D3D11_CREATE_DEVICE) GetProcAddress(d3dlib, "D3D11CreateDevice"); - if (!createD3D) { - av_log(ctx, AV_LOG_ERROR, "Failed to locate D3D11CreateDevice\n"); - return AVERROR_UNKNOWN; + if (device) { + IDXGIFactory2 *pDXGIFactory; + hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&pDXGIFactory); + if (SUCCEEDED(hr)) { + int adapter = atoi(device); + if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, &pAdapter))) + pAdapter = NULL; + IDXGIFactory2_Release(pDXGIFactory); + } } - hr = createD3D(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0, + hr = mD3D11CreateDevice(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0, D3D11_SDK_VERSION, &device_hwctx->device, NULL, NULL); if (pAdapter) IDXGIAdapter_Release(pAdapter); From c5c76370ae240b5e451c4a00a7ab485c0c0e0e98 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Wed, 14 Jun 2017 01:40:40 +0200 Subject: [PATCH 0271/2557] doc: Drop the legacy symlink to README Windows does not like symlinks and README.md is pretty common nowadays. --- README | 1 - 1 file changed, 1 deletion(-) delete mode 120000 README diff --git a/README b/README deleted file mode 120000 index 42061c01a1c70..0000000000000 --- a/README +++ /dev/null @@ -1 +0,0 @@ -README.md \ No newline at end of file From a970f9de865c84ed5360dd0398baee7d48d04620 Mon Sep 17 00:00:00 2001 From: Memphiz Date: Sun, 18 Jun 2017 12:30:16 +0200 Subject: [PATCH 0272/2557] aarch64: vp9: Fix assembling with Xcode 6.2 and older MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Properly use the b.eq/b.ge forms instead of the nonstandard forms (which both gas and newer clang accept though), and expand the register list that used a range (which the Xcode 6.2 clang, based on clang 3.5 svn, didn't support). Signed-off-by: Martin Storsjö --- libavcodec/aarch64/vp9itxfm_neon.S | 2 +- libavcodec/aarch64/vp9mc_neon.S | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/aarch64/vp9itxfm_neon.S b/libavcodec/aarch64/vp9itxfm_neon.S index 97226d11807ff..3ffb4189637a1 100644 --- a/libavcodec/aarch64/vp9itxfm_neon.S +++ b/libavcodec/aarch64/vp9itxfm_neon.S @@ -1531,7 +1531,7 @@ function ff_vp9_idct_idct_32x32_add_neon, export=1 2: subs x1, x1, #1 .rept 4 - st1 {v16.8h-v19.8h}, [x0], #64 + st1 {v16.8h,v17.8h,v18.8h,v19.8h}, [x0], #64 .endr b.ne 2b 3: diff --git a/libavcodec/aarch64/vp9mc_neon.S b/libavcodec/aarch64/vp9mc_neon.S index 95ed26c2325ed..584c114269039 100644 --- a/libavcodec/aarch64/vp9mc_neon.S +++ b/libavcodec/aarch64/vp9mc_neon.S @@ -342,7 +342,7 @@ function \type\()_8tap_\size\()h_\idx1\idx2 subs x9, x9, #16 st1 {v1.16b}, [x0], #16 st1 {v24.16b}, [x6], #16 - beq 3f + b.eq 3f mov v4.16b, v6.16b mov v16.16b, v18.16b ld1 {v6.16b}, [x2], #16 @@ -389,10 +389,10 @@ function ff_vp9_\type\()_\filter\()\size\()_h_neon, export=1 add x9, x6, w5, uxtw #3 mov x5, #\size .if \size >= 16 - bge \type\()_8tap_16h_34 + b.ge \type\()_8tap_16h_34 b \type\()_8tap_16h_43 .else - bge \type\()_8tap_\size\()h_34 + b.ge \type\()_8tap_\size\()h_34 b \type\()_8tap_\size\()h_43 .endif endfunc From 713efb2c0d013a42be4051adb7cd90a7c2cbbb4f Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Thu, 15 Jun 2017 11:20:48 -0700 Subject: [PATCH 0273/2557] movenc: use correct tag list for AVOutputFormat.codec_tag ff_mp4_obj_type contains the wrong type of tags for AVOutputFormat.codec_tag. AVOutputFormat.codec_tag is used to validate AVCodecParameters.codec_tag so needs to be the same type of tag. Creates new tag lists for mp4 and ismv. New tag lists support same list of codecs found in ff_mp4_obj_type. psp uses the same tag list as mp4 since these both use mp4_get_codec_tag to look up tags. --- libavformat/movenc.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index e3890296c6376..a5c5e8ad943e3 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -4444,6 +4444,36 @@ static int mov_write_trailer(AVFormatContext *s) return res; } +const AVCodecTag codec_mp4_tags[] = { + { AV_CODEC_ID_MPEG4 , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_H264 , MKTAG('a', 'v', 'c', '1') }, + { AV_CODEC_ID_HEVC , MKTAG('h', 'e', 'v', '1') }, + { AV_CODEC_ID_MPEG2VIDEO , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_MPEG1VIDEO , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_MJPEG , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_PNG , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_JPEG2000 , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_VC1 , MKTAG('v', 'c', '-', '1') }, + { AV_CODEC_ID_DIRAC , MKTAG('d', 'r', 'a', 'c') }, + { AV_CODEC_ID_TSCC2 , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_AAC , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_MP4ALS , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_MP3 , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_MP2 , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_AC3 , MKTAG('a', 'c', '-', '3') }, + { AV_CODEC_ID_DTS , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_VORBIS , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_QCELP , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') }, + { AV_CODEC_ID_MOV_TEXT , MKTAG('t', 'x', '3', 'g') }, + { AV_CODEC_ID_NONE , 0 }, +}; + +const AVCodecTag codec_ism_tags[] = { + { AV_CODEC_ID_WMAPRO , MKTAG('w', 'm', 'a', ' ') }, + { AV_CODEC_ID_NONE , 0 }, +}; + #if CONFIG_MOV_MUXER MOV_CLASS(mov) AVOutputFormat ff_mov_muxer = { @@ -4496,7 +4526,7 @@ AVOutputFormat ff_mp4_muxer = { .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, + .codec_tag = (const AVCodecTag* const []){ codec_mp4_tags, 0 }, .priv_class = &mp4_muxer_class, }; #endif @@ -4514,7 +4544,7 @@ AVOutputFormat ff_psp_muxer = { .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, + .codec_tag = (const AVCodecTag* const []){ codec_mp4_tags, 0 }, .priv_class = &psp_muxer_class, }; #endif @@ -4567,7 +4597,8 @@ AVOutputFormat ff_ismv_muxer = { .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, + .codec_tag = (const AVCodecTag* const []){ + codec_mp4_tags, codec_ism_tags, 0 }, .priv_class = &ismv_muxer_class, }; #endif From f6f86f432fe51526a7aad2bdb025d6a45d239883 Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Mon, 19 Jun 2017 07:46:48 -0700 Subject: [PATCH 0274/2557] movenc: simplify codec_tag lookup mux.c init_muxer() already sets codec_tag correctly in the cases simplified here. This also adds the capability to support alternative tags for the same codec_id. --- libavformat/movenc.c | 60 ++++++++++---------------------------------- 1 file changed, 13 insertions(+), 47 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index a5c5e8ad943e3..13e6b4ff4b313 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -32,6 +32,7 @@ #include "isom.h" #include "avc.h" +#include "libavcodec/internal.h" #include "libavcodec/bitstream.h" #include "libavcodec/put_bits.h" #include "libavcodec/vc1_common.h" @@ -778,26 +779,6 @@ static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track) return 0; } -static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track) -{ - int tag = track->par->codec_tag; - - if (!ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id)) - return 0; - - if (track->par->codec_id == AV_CODEC_ID_H264) tag = MKTAG('a','v','c','1'); - else if (track->par->codec_id == AV_CODEC_ID_HEVC) tag = MKTAG('h','e','v','1'); - else if (track->par->codec_id == AV_CODEC_ID_AC3) tag = MKTAG('a','c','-','3'); - else if (track->par->codec_id == AV_CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c'); - else if (track->par->codec_id == AV_CODEC_ID_MOV_TEXT) tag = MKTAG('t','x','3','g'); - else if (track->par->codec_id == AV_CODEC_ID_VC1) tag = MKTAG('v','c','-','1'); - else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v'); - else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a'); - else if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE) tag = MKTAG('m','p','4','s'); - - return tag; -} - static const AVCodecTag codec_ipod_tags[] = { { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, @@ -809,23 +790,6 @@ static const AVCodecTag codec_ipod_tags[] = { { AV_CODEC_ID_NONE, 0 }, }; -static int ipod_get_codec_tag(AVFormatContext *s, MOVTrack *track) -{ - int tag = track->par->codec_tag; - - // keep original tag for subs, ipod supports both formats - if (!(track->par->codec_type == AVMEDIA_TYPE_SUBTITLE && - (tag == MKTAG('t', 'x', '3', 'g') || - tag == MKTAG('t', 'e', 'x', 't')))) - tag = ff_codec_get_tag(codec_ipod_tags, track->par->codec_id); - - if (!av_match_ext(s->filename, "m4a") && !av_match_ext(s->filename, "m4v")) - av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v " - "Quicktime/Ipod might not play the file\n"); - - return tag; -} - static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track) { int tag; @@ -951,17 +915,19 @@ static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track) int tag; if (track->mode == MODE_MP4 || track->mode == MODE_PSP) - tag = mp4_get_codec_tag(s, track); - else if (track->mode == MODE_ISM) { - tag = mp4_get_codec_tag(s, track); - if (!tag && track->par->codec_id == AV_CODEC_ID_WMAPRO) - tag = MKTAG('w', 'm', 'a', ' '); - } else if (track->mode == MODE_IPOD) - tag = ipod_get_codec_tag(s, track); - else if (track->mode & MODE_3GP) - tag = ff_codec_get_tag(codec_3gp_tags, track->par->codec_id); + tag = track->par->codec_tag; + else if (track->mode == MODE_ISM) + tag = track->par->codec_tag; + else if (track->mode == MODE_IPOD) { + if (!av_match_ext(s->filename, "m4a") && + !av_match_ext(s->filename, "m4v")) + av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v " + "Quicktime/Ipod might not play the file\n"); + tag = track->par->codec_tag; + } else if (track->mode & MODE_3GP) + tag = track->par->codec_tag; else if (track->mode == MODE_F4V) - tag = ff_codec_get_tag(codec_f4v_tags, track->par->codec_id); + tag = track->par->codec_tag; else tag = mov_get_codec_tag(s, track); From 1c64bae648eeb39c8d8a8d81ee142b9eec9fae7b Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Mon, 19 Jun 2017 07:53:45 -0700 Subject: [PATCH 0275/2557] movenc: move tags definitions to where they are used --- libavformat/movenc.c | 62 ++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 13e6b4ff4b313..7791007b09ee2 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -779,17 +779,6 @@ static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track) return 0; } -static const AVCodecTag codec_ipod_tags[] = { - { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, - { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, - { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, - { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') }, - { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') }, - { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, - { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') }, - { AV_CODEC_ID_NONE, 0 }, -}; - static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track) { int tag; @@ -890,26 +879,6 @@ static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track) return tag; } -static const AVCodecTag codec_3gp_tags[] = { - { AV_CODEC_ID_H263, MKTAG('s','2','6','3') }, - { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, - { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, - { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, - { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') }, - { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') }, - { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, - { AV_CODEC_ID_NONE, 0 }, -}; - -static const AVCodecTag codec_f4v_tags[] = { - { AV_CODEC_ID_MP3, MKTAG('.','m','p','3') }, - { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, - { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, - { AV_CODEC_ID_VP6A, MKTAG('V','P','6','A') }, - { AV_CODEC_ID_VP6F, MKTAG('V','P','6','F') }, - { AV_CODEC_ID_NONE, 0 }, -}; - static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track) { int tag; @@ -4410,6 +4379,17 @@ static int mov_write_trailer(AVFormatContext *s) return res; } +static const AVCodecTag codec_3gp_tags[] = { + { AV_CODEC_ID_H263, MKTAG('s','2','6','3') }, + { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, + { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, + { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, + { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') }, + { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') }, + { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, + { AV_CODEC_ID_NONE, 0 }, +}; + const AVCodecTag codec_mp4_tags[] = { { AV_CODEC_ID_MPEG4 , MKTAG('m', 'p', '4', 'v') }, { AV_CODEC_ID_H264 , MKTAG('a', 'v', 'c', '1') }, @@ -4440,6 +4420,26 @@ const AVCodecTag codec_ism_tags[] = { { AV_CODEC_ID_NONE , 0 }, }; +static const AVCodecTag codec_ipod_tags[] = { + { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, + { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, + { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, + { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') }, + { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') }, + { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, + { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') }, + { AV_CODEC_ID_NONE, 0 }, +}; + +static const AVCodecTag codec_f4v_tags[] = { + { AV_CODEC_ID_MP3, MKTAG('.','m','p','3') }, + { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, + { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, + { AV_CODEC_ID_VP6A, MKTAG('V','P','6','A') }, + { AV_CODEC_ID_VP6F, MKTAG('V','P','6','F') }, + { AV_CODEC_ID_NONE, 0 }, +}; + #if CONFIG_MOV_MUXER MOV_CLASS(mov) AVOutputFormat ff_mov_muxer = { From 1ea9b7fdf99b60c0db95a2ce97b2108469bbb245 Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Thu, 15 Jun 2017 11:41:15 -0700 Subject: [PATCH 0276/2557] movenc: write correct format hvcc when tag is hvc1 --- libavformat/movenc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 7791007b09ee2..f63750890a46b 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -727,7 +727,10 @@ static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, 0); ffio_wfourcc(pb, "hvcC"); - ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0); + if (track->tag == MKTAG('h','v','c','1')) + ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 1); + else + ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0); return update_size(pb, pos); } From 84ab1cc437fa47a00532f305b9fe15b5b66c8c5e Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Thu, 15 Jun 2017 11:47:16 -0700 Subject: [PATCH 0277/2557] movenc: allow alternative hvc1 h.265 codec tag If AVCodecParameters.codec_tag is 'hvc1' use it instead of 'hev1' for h.265 streams. QuickTime (and other Apple software) requires 'hvc1'. --- libavformat/movenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index f63750890a46b..a546fdfeadb6f 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -4397,6 +4397,7 @@ const AVCodecTag codec_mp4_tags[] = { { AV_CODEC_ID_MPEG4 , MKTAG('m', 'p', '4', 'v') }, { AV_CODEC_ID_H264 , MKTAG('a', 'v', 'c', '1') }, { AV_CODEC_ID_HEVC , MKTAG('h', 'e', 'v', '1') }, + { AV_CODEC_ID_HEVC , MKTAG('h', 'v', 'c', '1') }, { AV_CODEC_ID_MPEG2VIDEO , MKTAG('m', 'p', '4', 'v') }, { AV_CODEC_ID_MPEG1VIDEO , MKTAG('m', 'p', '4', 'v') }, { AV_CODEC_ID_MJPEG , MKTAG('m', 'p', '4', 'v') }, From 0671eb2346c17e8fb13784cf90ce416661fdea1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 19 Jun 2017 15:45:08 +0300 Subject: [PATCH 0278/2557] tls_openssl: Readd support for nonblocking operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rtmp protocol uses nonblocking reads, to poll for incoming messages from the server while publishing a stream. Prior to 94599a6de3822b13c94096d764868128f388ba28 and d13b124eaf452b267480074b2e6946538ed03a6e, the tls protocol handled the nonblocking flag, mostly as a side effect from not using custom IO callbacks for reading from the socket. When custom IO callbacks were taken into use in d15eec4d6bdfa3bd4c4b5b7dd2dbd699ba253d02, the handling of a nonblocking socket wasn't necessary for the default blocking mode any longer. The code was simplified, since it was overlooked that other code within libavformat actually used the tls protocol in nonblocking mode. This fixes publishing over rtmps, with the openssl backend. Signed-off-by: Martin Storsjö --- libavformat/tls_openssl.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c index 71fa96871dfba..f0b325ae98035 100644 --- a/libavformat/tls_openssl.c +++ b/libavformat/tls_openssl.c @@ -109,6 +109,12 @@ void ff_openssl_deinit(void) static int print_tls_error(URLContext *h, int ret) { + TLSContext *c = h->priv_data; + if (h->flags & AVIO_FLAG_NONBLOCK) { + int err = SSL_get_error(c->ssl, ret); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_READ) + return AVERROR(EAGAIN); + } av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); return AVERROR(EIO); } @@ -164,6 +170,8 @@ static int url_bio_bread(BIO *b, char *buf, int len) if (ret >= 0) return ret; BIO_clear_retry_flags(b); + if (ret == AVERROR(EAGAIN)) + BIO_set_retry_read(b); if (ret == AVERROR_EXIT) return 0; return -1; @@ -176,6 +184,8 @@ static int url_bio_bwrite(BIO *b, const char *buf, int len) if (ret >= 0) return ret; BIO_clear_retry_flags(b); + if (ret == AVERROR(EAGAIN)) + BIO_set_retry_write(b); if (ret == AVERROR_EXIT) return 0; return -1; @@ -292,7 +302,11 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op static int tls_read(URLContext *h, uint8_t *buf, int size) { TLSContext *c = h->priv_data; - int ret = SSL_read(c->ssl, buf, size); + int ret; + // Set or clear the AVIO_FLAG_NONBLOCK on c->tls_shared.tcp + c->tls_shared.tcp->flags &= ~AVIO_FLAG_NONBLOCK; + c->tls_shared.tcp->flags |= h->flags & AVIO_FLAG_NONBLOCK; + ret = SSL_read(c->ssl, buf, size); if (ret > 0) return ret; if (ret == 0) @@ -303,7 +317,11 @@ static int tls_read(URLContext *h, uint8_t *buf, int size) static int tls_write(URLContext *h, const uint8_t *buf, int size) { TLSContext *c = h->priv_data; - int ret = SSL_write(c->ssl, buf, size); + int ret; + // Set or clear the AVIO_FLAG_NONBLOCK on c->tls_shared.tcp + c->tls_shared.tcp->flags &= ~AVIO_FLAG_NONBLOCK; + c->tls_shared.tcp->flags |= h->flags & AVIO_FLAG_NONBLOCK; + ret = SSL_write(c->ssl, buf, size); if (ret > 0) return ret; if (ret == 0) From eb061ad6fd0e3cea7cf7cfbff0749bc90dd7d888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 19 Jun 2017 15:49:25 +0300 Subject: [PATCH 0279/2557] tls_gnutls: Readd support for nonblocking operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rtmp protocol uses nonblocking reads, to poll for incoming messages from the server while publishing a stream. Prior to 94599a6de3822b13c94096d764868128f388ba28 and d13b124eaf452b267480074b2e6946538ed03a6e, the tls protocol handled the nonblocking flag, mostly as a side effect from not using custom IO callbacks for reading from the socket. When custom IO callbacks were taken into use in d15eec4d6bdfa3bd4c4b5b7dd2dbd699ba253d02, the handling of a nonblocking socket wasn't necessary for the default blocking mode any longer. The code was simplified, since it was overlooked that other code within libavformat actually used the tls protocol in nonblocking mode. This fixes publishing over rtmps, with the gnutls backend. Signed-off-by: Martin Storsjö --- libavformat/tls_gnutls.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/libavformat/tls_gnutls.c b/libavformat/tls_gnutls.c index 1ae7656dcb071..7bfe02deb0fb4 100644 --- a/libavformat/tls_gnutls.c +++ b/libavformat/tls_gnutls.c @@ -61,6 +61,7 @@ static int print_tls_error(URLContext *h, int ret) { switch (ret) { case GNUTLS_E_AGAIN: + return AVERROR(EAGAIN); case GNUTLS_E_INTERRUPTED: break; case GNUTLS_E_WARNING_ALERT_RECEIVED: @@ -97,7 +98,10 @@ static ssize_t gnutls_url_pull(gnutls_transport_ptr_t transport, return ret; if (ret == AVERROR_EXIT) return 0; - errno = EIO; + if (ret == AVERROR(EAGAIN)) + errno = EAGAIN; + else + errno = EIO; return -1; } @@ -110,7 +114,10 @@ static ssize_t gnutls_url_push(gnutls_transport_ptr_t transport, return ret; if (ret == AVERROR_EXIT) return 0; - errno = EIO; + if (ret == AVERROR(EAGAIN)) + errno = EAGAIN; + else + errno = EIO; return -1; } @@ -202,7 +209,11 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op static int tls_read(URLContext *h, uint8_t *buf, int size) { TLSContext *c = h->priv_data; - int ret = gnutls_record_recv(c->session, buf, size); + int ret; + // Set or clear the AVIO_FLAG_NONBLOCK on c->tls_shared.tcp + c->tls_shared.tcp->flags &= ~AVIO_FLAG_NONBLOCK; + c->tls_shared.tcp->flags |= h->flags & AVIO_FLAG_NONBLOCK; + ret = gnutls_record_recv(c->session, buf, size); if (ret > 0) return ret; if (ret == 0) @@ -213,7 +224,11 @@ static int tls_read(URLContext *h, uint8_t *buf, int size) static int tls_write(URLContext *h, const uint8_t *buf, int size) { TLSContext *c = h->priv_data; - int ret = gnutls_record_send(c->session, buf, size); + int ret; + // Set or clear the AVIO_FLAG_NONBLOCK on c->tls_shared.tcp + c->tls_shared.tcp->flags &= ~AVIO_FLAG_NONBLOCK; + c->tls_shared.tcp->flags |= h->flags & AVIO_FLAG_NONBLOCK; + ret = gnutls_record_send(c->session, buf, size); if (ret > 0) return ret; if (ret == 0) From f519e131c101ae3948dabf1f7f598efbff5fb536 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 12 Jun 2017 22:12:17 +0200 Subject: [PATCH 0280/2557] af_bs2b: Add missing casts to complex pointer assignments Fixes several warnings of the type: libavfilter/af_bs2b.c:171:22: warning: assignment from incompatible pointer type --- libavfilter/af_bs2b.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libavfilter/af_bs2b.c b/libavfilter/af_bs2b.c index 25e786761f0ec..0468333a87734 100644 --- a/libavfilter/af_bs2b.c +++ b/libavfilter/af_bs2b.c @@ -32,6 +32,8 @@ #include "formats.h" #include "internal.h" +typedef void (*filter_func)(t_bs2bdp bs2bdp, uint8_t *sample, int n); + typedef struct Bs2bContext { const AVClass *class; @@ -41,7 +43,7 @@ typedef struct Bs2bContext { t_bs2bdp bs2bp; - void (*filter)(t_bs2bdp bs2bdp, uint8_t *sample, int n); + filter_func filter; } Bs2bContext; #define OFFSET(x) offsetof(Bs2bContext, x) @@ -165,19 +167,19 @@ static int config_output(AVFilterLink *outlink) switch (inlink->format) { case AV_SAMPLE_FMT_U8: - bs2b->filter = bs2b_cross_feed_u8; + bs2b->filter = (filter_func) bs2b_cross_feed_u8; break; case AV_SAMPLE_FMT_S16: - bs2b->filter = bs2b_cross_feed_s16; + bs2b->filter = (filter_func) bs2b_cross_feed_s16; break; case AV_SAMPLE_FMT_S32: - bs2b->filter = bs2b_cross_feed_s32; + bs2b->filter = (filter_func) bs2b_cross_feed_s32; break; case AV_SAMPLE_FMT_FLT: - bs2b->filter = bs2b_cross_feed_f; + bs2b->filter = (filter_func) bs2b_cross_feed_f; break; case AV_SAMPLE_FMT_DBL: - bs2b->filter = bs2b_cross_feed_d; + bs2b->filter = (filter_func) bs2b_cross_feed_d; break; default: return AVERROR_BUG; From 333a34da3a6d13155de480e7d16ec5fec7f4cd6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 21 Jun 2017 16:54:22 +0300 Subject: [PATCH 0281/2557] configure: Automatically add -isysroot for darwin if --sysroot is specified MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check the existing flags in the cc/cflags/cppflags/ldflags for occurrances of -isysroot; if none is found but --sysroot was specified, set -isysroot to the same value as --sysroot. This simplifies configuring cross-builds for iOS, if the global environment variable SDKROOT isn't set. Signed-off-by: Martin Storsjö --- configure | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure b/configure index 22de1b358e24b..bbed2258b97d8 100755 --- a/configure +++ b/configure @@ -3981,6 +3981,10 @@ case $target_os in { check_cflags -mdynamic-no-pic && add_asflags -mdynamic-no-pic; } check_header dispatch/dispatch.h && add_cppflags '-I\$(SRC_PATH)/compat/dispatch_semaphore' + if test -n "$sysroot"; then + is_in -isysroot $cc $CPPFLAGS $CFLAGS || check_cppflags -isysroot $sysroot + is_in -isysroot $ld $LDFLAGS || check_ldflags -isysroot $sysroot + fi ;; msys*) die "Native MSYS builds are discouraged, please use the MINGW environment." From 857e26b655a769e5a56bada1a0d9adb44cc176b7 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Tue, 20 Jun 2017 19:25:43 +0200 Subject: [PATCH 0282/2557] build: Add an option for passing linker flags to the shared library build Also employ this mechanism to pass $libdir to the runtime library search path if rpath is enabled. This fixes underlinking of some test binaries on some systems. --- avbuild/library.mak | 2 +- configure | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/avbuild/library.mak b/avbuild/library.mak index 2095f61d807ad..30757546fdd94 100644 --- a/avbuild/library.mak +++ b/avbuild/library.mak @@ -48,7 +48,7 @@ $(SUBDIR)$(SLIBNAME): $(SUBDIR)$(SLIBNAME_WITH_MAJOR) $(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SUBDIR)lib$(NAME).ver $(DEP_LIBS) $(SLIB_CREATE_DEF_CMD) - $$(LD) $(SHFLAGS) $(LDFLAGS) $$(LD_O) $$(filter %.o,$$^) $(FFEXTRALIBS) + $$(LD) $(SHFLAGS) $(LDFLAGS) $(LDSOFLAGS) $$(LD_O) $$(filter %.o,$$^) $(FFEXTRALIBS) $(SLIB_EXTRA_CMD) clean:: diff --git a/configure b/configure index bbed2258b97d8..ce0f6c919e041 100755 --- a/configure +++ b/configure @@ -283,6 +283,7 @@ Toolchain options: --extra-objcflags=FLAGS add FLAGS to OBJCFLAGS [$CFLAGS] --extra-ldflags=ELDFLAGS add ELDFLAGS to LDFLAGS [$LDFLAGS] --extra-ldexeflags=ELDFLAGS add ELDFLAGS to LDEXEFLAGS [$LDEXEFLAGS] + --extra-ldsoflags=ELDFLAGS add ELDFLAGS to LDSOFLAGS [$LDSOFLAGS] --extra-libs=ELIBS add ELIBS [$ELIBS] --extra-version=STRING version string suffix [] --optflags=OPTFLAGS override optimization-related compiler flags @@ -740,6 +741,10 @@ add_ldexeflags(){ append LDEXEFLAGS $($ldflags_filter "$@") } +add_ldsoflags(){ + append LDSOFLAGS $($ldflags_filter "$@") +} + add_stripflags(){ append STRIPFLAGS "$@" } @@ -2802,6 +2807,9 @@ for opt do --extra-ldexeflags=*) add_ldexeflags $optval ;; + --extra-ldsoflags=*) + add_ldsoflags $optval + ;; --extra-libs=*) add_extralibs $optval ;; @@ -4950,7 +4958,7 @@ EOF # add some linker flags check_ldflags -Wl,--warn-common check_ldflags -Wl,-rpath-link=libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil:libavresample -enabled rpath && add_ldexeflags -Wl,-rpath,$libdir +enabled rpath && add_ldexeflags -Wl,-rpath,$libdir && add_ldsoflags -Wl,-rpath,$libdir test_ldflags -Wl,-Bsymbolic && append SHFLAGS -Wl,-Bsymbolic # add some strip flags @@ -5410,6 +5418,7 @@ LD_PATH=$LD_PATH DLLTOOL=$dlltool LDFLAGS=$LDFLAGS LDEXEFLAGS=$LDEXEFLAGS +LDSOFLAGS=$LDSOFLAGS SHFLAGS=$(echo $($ldflags_filter $SHFLAGS)) STRIPFLAGS=$STRIPFLAGS X86ASMFLAGS=$X86ASMFLAGS From bb65eb62991e5165b9fad2702a8954a1fe3c6f1f Mon Sep 17 00:00:00 2001 From: Ben Chang Date: Sat, 24 Jun 2017 12:10:10 +0000 Subject: [PATCH 0283/2557] nvenc: Add an explicit auto alias --- libavcodec/nvenc_h264.c | 1 + libavcodec/nvenc_hevc.c | 1 + 2 files changed, 2 insertions(+) diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index f7e5cd05dcd37..1c9e07a776abb 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -47,6 +47,7 @@ static const AVOption options[] = { { "high_444", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_HIGH_444 }, 0, 0, VE, "profile" }, { "constrained_high", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_CONSTRAINED_HIGH }, 0, 0, VE, "profile" }, { "level", "Set the encoding level restriction", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, NV_ENC_LEVEL_AUTOSELECT, NV_ENC_LEVEL_H264_51, VE, "level" }, + { "auto", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, 0, 0, VE, "level" }, { "1.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_1 }, 0, 0, VE, "level" }, { "1.b", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_1b }, 0, 0, VE, "level" }, { "1.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_11 }, 0, 0, VE, "level" }, diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index 9102d8a3b32d9..a13db98356f36 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -47,6 +47,7 @@ static const AVOption options[] = { { "rext", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_HEVC_PROFILE_REXT }, 0, 0, VE, "profile" }, #endif /* NVENCAPI_MAJOR_VERSION >= 7 */ { "level", "Set the encoding level restriction", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, NV_ENC_LEVEL_AUTOSELECT, NV_ENC_LEVEL_HEVC_62, VE, "level" }, + { "auto", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, 0, 0, VE, "level" }, { "1.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_1 }, 0, 0, VE, "level" }, { "2.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_2 }, 0, 0, VE, "level" }, { "2.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_21 }, 0, 0, VE, "level" }, From 2e8d88ad5281ab923e1d9772eb99fdfb483435c2 Mon Sep 17 00:00:00 2001 From: Ben Chang Date: Sat, 24 Jun 2017 12:14:22 +0000 Subject: [PATCH 0284/2557] nvenc: Use a fifo to manage the free surface pool Previously, if a session allocates x surfaces, only x-1 surfaces are used (due to combination of output delay and lock toggle logic). --- libavcodec/nvenc.c | 23 ++++++++++++++--------- libavcodec/nvenc.h | 3 +-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index f16e509df35ea..7b30ad768e95f 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -986,6 +986,7 @@ static int nvenc_alloc_surface(AVCodecContext *avctx, int idx) { NVENCContext *ctx = avctx->priv_data; NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; + NVENCFrame *tmp_surface = &ctx->frames[idx]; int ret; NV_ENC_CREATE_BITSTREAM_BUFFER out_buffer = { 0 }; @@ -1046,6 +1047,8 @@ static int nvenc_alloc_surface(AVCodecContext *avctx, int idx) ctx->frames[idx].out = out_buffer.bitstreamBuffer; + av_fifo_generic_write(ctx->unused_surface_queue, &tmp_surface, sizeof(tmp_surface), NULL); + return 0; } @@ -1066,6 +1069,9 @@ static int nvenc_setup_surfaces(AVCodecContext *avctx) ctx->timestamps = av_fifo_alloc(ctx->nb_surfaces * sizeof(int64_t)); if (!ctx->timestamps) return AVERROR(ENOMEM); + ctx->unused_surface_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(NVENCFrame*)); + if (!ctx->unused_surface_queue) + return AVERROR(ENOMEM); ctx->pending = av_fifo_alloc(ctx->nb_surfaces * sizeof(*ctx->frames)); if (!ctx->pending) return AVERROR(ENOMEM); @@ -1123,6 +1129,7 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) av_fifo_free(ctx->timestamps); av_fifo_free(ctx->pending); av_fifo_free(ctx->ready); + av_fifo_free(ctx->unused_surface_queue); if (ctx->frames) { for (i = 0; i < ctx->nb_surfaces; ++i) { @@ -1201,16 +1208,14 @@ av_cold int ff_nvenc_encode_init(AVCodecContext *avctx) static NVENCFrame *get_free_frame(NVENCContext *ctx) { - int i; + NVENCFrame *tmp_surf; - for (i = 0; i < ctx->nb_surfaces; i++) { - if (!ctx->frames[i].locked) { - ctx->frames[i].locked = 1; - return &ctx->frames[i]; - } - } + if (!(av_fifo_size(ctx->unused_surface_queue) > 0)) + // queue empty + return NULL; - return NULL; + av_fifo_generic_read(ctx->unused_surface_queue, &tmp_surf, sizeof(tmp_surf), NULL); + return tmp_surf; } static int nvenc_copy_frame(NV_ENC_LOCK_INPUT_BUFFER *in, const AVFrame *frame) @@ -1510,7 +1515,7 @@ static int nvenc_get_output(AVCodecContext *avctx, AVPacket *pkt) frame->in = NULL; } - frame->locked = 0; + av_fifo_generic_write(ctx->unused_surface_queue, &frame, sizeof(frame), NULL); ret = nvenc_set_timestamp(avctx, ¶ms, pkt); if (ret < 0) diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 3602f16e83b14..b42b930920634 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -56,7 +56,6 @@ typedef struct NVENCFrame { NV_ENC_OUTPUT_PTR out; NV_ENC_BUFFER_FORMAT format; - int locked; } NVENCFrame; typedef CUresult(CUDAAPI *PCUINIT)(unsigned int Flags); @@ -145,7 +144,7 @@ typedef struct NVENCContext { int nb_surfaces; NVENCFrame *frames; AVFifoBuffer *timestamps; - AVFifoBuffer *pending, *ready; + AVFifoBuffer *pending, *ready, *unused_surface_queue; struct { CUdeviceptr ptr; From 7cb053e4ddf258e2dbf52ccc586548680742d758 Mon Sep 17 00:00:00 2001 From: Ben Chang Date: Sat, 24 Jun 2017 12:17:14 +0000 Subject: [PATCH 0285/2557] nvenc: Minimize the surface allocation The previous default sets the allocated surfaces to 32 unless it is user-overridden or the lookahead parameter is set. Change the surfaces calculation for default, B-frames and lookahead scenario. --- libavcodec/nvenc.c | 45 ++++++++++++++++++++++++++++++++++++----- libavcodec/nvenc_h264.c | 4 ++-- libavcodec/nvenc_hevc.c | 4 ++-- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 7b30ad768e95f..884b344b96dae 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -874,6 +874,44 @@ static int nvenc_setup_codec_config(AVCodecContext *avctx) return 0; } +static int nvenc_recalc_surfaces(AVCodecContext *avctx) +{ + NVENCContext *ctx = avctx->priv_data; + // default minimum of 4 surfaces + // multiply by 2 for number of NVENCs on gpu (hardcode to 2) + // another multiply by 2 to avoid blocking next PBB group + int nb_surfaces = FFMAX(4, ctx->config.frameIntervalP * 2 * 2); + + // lookahead enabled + if (ctx->rc_lookahead > 0) { + // +1 is to account for lkd_bound calculation later + // +4 is to allow sufficient pipelining with lookahead + nb_surfaces = FFMAX(1, FFMAX(nb_surfaces, ctx->rc_lookahead + ctx->config.frameIntervalP + 1 + 4)); + if (nb_surfaces > ctx->nb_surfaces && ctx->nb_surfaces > 0) { + av_log(avctx, AV_LOG_WARNING, + "Defined rc_lookahead requires more surfaces, " + "increasing used surfaces %d -> %d\n", + ctx->nb_surfaces, nb_surfaces); + } + ctx->nb_surfaces = FFMAX(nb_surfaces, ctx->nb_surfaces); + } else { + if (ctx->config.frameIntervalP > 1 && + ctx->nb_surfaces < nb_surfaces && ctx->nb_surfaces > 0) { + av_log(avctx, AV_LOG_WARNING, + "Defined b-frame requires more surfaces, " + "increasing used surfaces %d -> %d\n", + ctx->nb_surfaces, nb_surfaces); + ctx->nb_surfaces = FFMAX(ctx->nb_surfaces, nb_surfaces); + } else if (ctx->nb_surfaces <= 0) + ctx->nb_surfaces = nb_surfaces; + // otherwise use user specified value + } + + ctx->nb_surfaces = FFMAX(1, FFMIN(MAX_REGISTERED_FRAMES, ctx->nb_surfaces)); + ctx->async_depth = FFMIN(ctx->async_depth, ctx->nb_surfaces - 1); + return 0; +} + static int nvenc_setup_encoder(AVCodecContext *avctx) { NVENCContext *ctx = avctx->priv_data; @@ -956,6 +994,8 @@ static int nvenc_setup_encoder(AVCodecContext *avctx) ctx->initial_pts[0] = AV_NOPTS_VALUE; ctx->initial_pts[1] = AV_NOPTS_VALUE; + nvenc_recalc_surfaces(avctx); + nvenc_setup_rate_control(avctx); if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { @@ -1057,11 +1097,6 @@ static int nvenc_setup_surfaces(AVCodecContext *avctx) NVENCContext *ctx = avctx->priv_data; int i, ret; - ctx->nb_surfaces = FFMAX(4 + avctx->max_b_frames, - ctx->nb_surfaces); - ctx->async_depth = FFMIN(ctx->async_depth, ctx->nb_surfaces - 1); - - ctx->frames = av_mallocz_array(ctx->nb_surfaces, sizeof(*ctx->frames)); if (!ctx->frames) return AVERROR(ENOMEM); diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index 1c9e07a776abb..bf983265df1a7 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -72,14 +72,14 @@ static const AVOption options[] = { { "ll_2pass_quality", "Multi-pass optimized for image quality (only for low-latency presets)", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_2_PASS_QUALITY }, 0, 0, VE, "rc" }, { "ll_2pass_size", "Multi-pass optimized for constant frame size (only for low-latency presets)", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP }, 0, 0, VE, "rc" }, { "vbr_2pass", "Multi-pass variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_2_PASS_VBR }, 0, 0, VE, "rc" }, - { "surfaces", "Number of concurrent surfaces", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 32 }, 0, INT_MAX, VE }, + { "surfaces", "Number of concurrent surfaces", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_REGISTERED_FRAMES, VE }, { "device", "Select a specific NVENC device", OFFSET(device), AV_OPT_TYPE_INT, { .i64 = -1 }, -2, INT_MAX, VE, "device" }, { "any", "Pick the first device available", 0, AV_OPT_TYPE_CONST, { .i64 = ANY_DEVICE }, 0, 0, VE, "device" }, { "list", "List the available devices", 0, AV_OPT_TYPE_CONST, { .i64 = LIST_DEVICES }, 0, 0, VE, "device" }, { "async_depth", "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE }, { "delay", "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE }, #if NVENCAPI_MAJOR_VERSION >= 7 - { "rc-lookahead", "Number of frames to look ahead for rate-control", OFFSET(rc_lookahead), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, + { "rc-lookahead", "Number of frames to look ahead for rate-control", OFFSET(rc_lookahead), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT_MAX, VE }, { "no-scenecut", "When lookahead is enabled, set this to 1 to disable adaptive I-frame insertion at scene cuts", OFFSET(no_scenecut), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, { "b_adapt", "When lookahead is enabled, set this to 0 to disable adaptive B-frame decision", OFFSET(b_adapt), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, { "spatial-aq", "set to 1 to enable Spatial AQ", OFFSET(aq), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index a13db98356f36..caf7c4add9969 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -72,14 +72,14 @@ static const AVOption options[] = { { "ll_2pass_quality", "Multi-pass optimized for image quality (only for low-latency presets)", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_2_PASS_QUALITY }, 0, 0, VE, "rc" }, { "ll_2pass_size", "Multi-pass optimized for constant frame size (only for low-latency presets)", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP }, 0, 0, VE, "rc" }, { "vbr_2pass", "Multi-pass variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_2_PASS_VBR }, 0, 0, VE, "rc" }, - { "surfaces", "Number of concurrent surfaces", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 32 }, 0, INT_MAX, VE }, + { "surfaces", "Number of concurrent surfaces", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_REGISTERED_FRAMES, VE }, { "device", "Select a specific NVENC device", OFFSET(device), AV_OPT_TYPE_INT, { .i64 = -1 }, -2, INT_MAX, VE, "device" }, { "any", "Pick the first device available", 0, AV_OPT_TYPE_CONST, { .i64 = ANY_DEVICE }, 0, 0, VE, "device" }, { "list", "List the available devices", 0, AV_OPT_TYPE_CONST, { .i64 = LIST_DEVICES }, 0, 0, VE, "device" }, { "async_depth", "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE }, { "delay", "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE }, #if NVENCAPI_MAJOR_VERSION >= 7 - { "rc-lookahead", "Number of frames to look ahead for rate-control", OFFSET(rc_lookahead), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, + { "rc-lookahead", "Number of frames to look ahead for rate-control", OFFSET(rc_lookahead), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT_MAX, VE }, { "no-scenecut", "When lookahead is enabled, set this to 1 to disable adaptive I-frame insertion at scene cuts", OFFSET(no_scenecut), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, { "spatial_aq", "set to 1 to enable Spatial AQ", OFFSET(aq), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, { "zerolatency", "Set 1 to indicate zero latency operation (no reordering delay)", OFFSET(zerolatency), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, From 0e83e95c60892747f2f1bd8382f915f2397f99a5 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 24 Jun 2017 17:51:02 +0200 Subject: [PATCH 0286/2557] configure: Reset X86ASM_DEP(FLAGS) when probing for the assembler program These variables might be set from a previous probe run, but one or the other program that is probed for may not grok the flags, resulting in errors during assembling when the values of those variables are passed to the assembler. --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index ce0f6c919e041..ab183745a72a1 100755 --- a/configure +++ b/configure @@ -4515,12 +4515,14 @@ EOF x86asmexe=$x86asmexe_probe x86asm_type=nasm x86asm_debug="-g -F dwarf" + X86ASMDEP= X86ASM_DEPFLAGS='-MD $(@:.o=.d)' elif check_cmd $x86asmexe_probe --version; then x86asmexe=$x86asmexe_probe x86asm_type=yasm x86asm_debug="-g dwarf2" X86ASMDEP='$(DEPX86ASM) $(X86ASMFLAGS) -M $(X86ASM_O) $< > $(@:.o=.d)' + X86ASM_DEPFLAGS= fi check_x86asm "movbe ecx, [5]" && enable x86asm } From 70e5e7c02232d1e51c362d5572c567a9e2a8dcc2 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 22 Jun 2017 14:52:52 +0200 Subject: [PATCH 0287/2557] dxva: add declarative profile checks Make supported codec profiles part of each dxva_modes entry. Every DXVA2 mode is representative for a codec with a subset of supported profiles, so reflecting that in dxva_modes seems appropriate. In practice, this will more strictly check MPEG2 profiles, will stop relying on the surface format checks for selecting the correct HEVC profile, and remove the verbose messages for mismatching H264/HEVC profiles. Instead of the latter, it will now print the more nebulous "No decoder device for codec found" verbose message. This also respects AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH. Move the Main10 HEVC entry before the normal one to make this work better. Originally inspired by VLC's code. Signed-off-by: Luca Barbato --- libavcodec/dxva2.c | 64 +++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index e0c54068d6e81..9f4a5294a451f 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -49,18 +49,34 @@ DEFINE_GUID(ff_IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x typedef struct dxva_mode { const GUID *guid; enum AVCodecID codec; + // List of supported profiles, terminated by a FF_PROFILE_UNKNOWN entry. + // If NULL, don't check profile. + const int *profiles; } dxva_mode; +static const int prof_mpeg2_main[] = {FF_PROFILE_MPEG2_SIMPLE, + FF_PROFILE_MPEG2_MAIN, + FF_PROFILE_UNKNOWN}; +static const int prof_h264_high[] = {FF_PROFILE_H264_CONSTRAINED_BASELINE, + FF_PROFILE_H264_MAIN, + FF_PROFILE_H264_HIGH, + FF_PROFILE_UNKNOWN}; +static const int prof_hevc_main[] = {FF_PROFILE_HEVC_MAIN, + FF_PROFILE_UNKNOWN}; +static const int prof_hevc_main10[] = {FF_PROFILE_HEVC_MAIN, + FF_PROFILE_HEVC_MAIN_10, + FF_PROFILE_UNKNOWN}; + static const dxva_mode dxva_modes[] = { /* MPEG-2 */ - { &ff_DXVA2_ModeMPEG2_VLD, AV_CODEC_ID_MPEG2VIDEO }, - { &ff_DXVA2_ModeMPEG2and1_VLD, AV_CODEC_ID_MPEG2VIDEO }, + { &ff_DXVA2_ModeMPEG2_VLD, AV_CODEC_ID_MPEG2VIDEO, prof_mpeg2_main }, + { &ff_DXVA2_ModeMPEG2and1_VLD, AV_CODEC_ID_MPEG2VIDEO, prof_mpeg2_main }, /* H.264 */ - { &ff_DXVA2_ModeH264_F, AV_CODEC_ID_H264 }, - { &ff_DXVA2_ModeH264_E, AV_CODEC_ID_H264 }, + { &ff_DXVA2_ModeH264_F, AV_CODEC_ID_H264, prof_h264_high }, + { &ff_DXVA2_ModeH264_E, AV_CODEC_ID_H264, prof_h264_high }, /* Intel specific H.264 mode */ - { &ff_DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264 }, + { &ff_DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264, prof_h264_high }, /* VC-1 / WMV3 */ { &ff_DXVA2_ModeVC1_D2010, AV_CODEC_ID_VC1 }, @@ -69,8 +85,8 @@ static const dxva_mode dxva_modes[] = { { &ff_DXVA2_ModeVC1_D, AV_CODEC_ID_WMV3 }, /* HEVC/H.265 */ - { &ff_DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC }, - { &ff_DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC }, + { &ff_DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC, prof_hevc_main10 }, + { &ff_DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC, prof_hevc_main }, { NULL, 0 }, }; @@ -160,6 +176,26 @@ static int dxva2_validate_output(void *decoder_service, GUID guid, void *surface } #endif +static int dxva_check_codec_compatibility(AVCodecContext *avctx, const dxva_mode *mode) +{ + if (mode->codec != avctx->codec_id) + return 0; + + if (mode->profiles && !(avctx->hwaccel_flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH)) { + int i, found = 0; + for (i = 0; mode->profiles[i] != FF_PROFILE_UNKNOWN; i++) { + if (avctx->profile == mode->profiles[i]) { + found = 1; + break; + } + } + if (!found) + return 0; + } + + return 1; +} + static int dxva_get_decoder_guid(AVCodecContext *avctx, void *service, void *surface_format, unsigned guid_count, const GUID *guid_list, GUID *decoder_guid) { @@ -170,7 +206,7 @@ static int dxva_get_decoder_guid(AVCodecContext *avctx, void *service, void *sur for (i = 0; dxva_modes[i].guid; i++) { const dxva_mode *mode = &dxva_modes[i]; int validate; - if (mode->codec != avctx->codec_id) + if (!dxva_check_codec_compatibility(avctx, mode)) continue; for (j = 0; j < guid_count; j++) { @@ -552,18 +588,6 @@ int ff_dxva2_decode_init(AVCodecContext *avctx) // (avctx->pix_fmt is not updated yet at this point) sctx->pix_fmt = avctx->hwaccel->pix_fmt; - if (avctx->codec_id == AV_CODEC_ID_H264 && - (avctx->profile & ~FF_PROFILE_H264_CONSTRAINED) > FF_PROFILE_H264_HIGH) { - av_log(avctx, AV_LOG_VERBOSE, "Unsupported H.264 profile for DXVA HWAccel: %d\n",avctx->profile); - return AVERROR(ENOTSUP); - } - - if (avctx->codec_id == AV_CODEC_ID_HEVC && - avctx->profile != FF_PROFILE_HEVC_MAIN && avctx->profile != FF_PROFILE_HEVC_MAIN_10) { - av_log(avctx, AV_LOG_VERBOSE, "Unsupported HEVC profile for DXVA HWAccel: %d\n", avctx->profile); - return AVERROR(ENOTSUP); - } - if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) { av_log(avctx, AV_LOG_ERROR, "Either a hw_frames_ctx or a hw_device_ctx needs to be set for hardware decoding.\n"); return AVERROR(EINVAL); From 752ddb45569ffe278393cd853b70f18ae017219e Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 22 Jun 2017 14:52:53 +0200 Subject: [PATCH 0288/2557] dxva: fix some warnings Some existed since forever, some are new. The cast in get_surface() is silly, but unless we change the av_log function signature, or all callers of ff_dxva2_get_surface_index(), it's needed to remove the const warning. Signed-off-by: Luca Barbato --- libavcodec/dxva2.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index 9f4a5294a451f..23d96687dcd33 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -359,7 +359,6 @@ static int d3d11va_get_decoder_configuration(AVCodecContext *avctx, const D3D11_VIDEO_DECODER_DESC *desc, D3D11_VIDEO_DECODER_CONFIG *config) { - FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); unsigned cfg_count = 0; D3D11_VIDEO_DECODER_CONFIG *cfg_list = NULL; HRESULT hr; @@ -623,7 +622,6 @@ int ff_dxva2_decode_init(AVCodecContext *avctx) if (sctx->pix_fmt == AV_PIX_FMT_D3D11) { AVD3D11VADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; AVD3D11VAContext *d3d11_ctx = &sctx->ctx.d3d11va; - HRESULT hr; ff_dxva2_lock(avctx); ret = d3d11va_create_decoder(avctx); @@ -690,7 +688,7 @@ int ff_dxva2_decode_uninit(AVCodecContext *avctx) return 0; } -static void *get_surface(AVCodecContext *avctx, const AVFrame *frame) +static void *get_surface(const AVCodecContext *avctx, const AVFrame *frame) { #if CONFIG_D3D11VA if (frame->format == AV_PIX_FMT_D3D11) { @@ -698,7 +696,7 @@ static void *get_surface(AVCodecContext *avctx, const AVFrame *frame) intptr_t index = (intptr_t)frame->data[1]; if (index < 0 || index >= sctx->nb_d3d11_views || sctx->d3d11_texture != (ID3D11Texture2D *)frame->data[0]) { - av_log(avctx, AV_LOG_ERROR, "get_buffer frame is invalid!\n"); + av_log((void *)avctx, AV_LOG_ERROR, "get_buffer frame is invalid!\n"); return NULL; } return sctx->d3d11_views[index]; @@ -759,7 +757,7 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx, #endif if (FAILED(hr)) { av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %u: 0x%x\n", - type, hr); + type, (unsigned)hr); return -1; } if (size <= dxva_size) { @@ -801,7 +799,7 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx, if (FAILED(hr)) { av_log(avctx, AV_LOG_ERROR, "Failed to release buffer type %u: 0x%x\n", - type, hr); + type, (unsigned)hr); result = -1; } return result; @@ -871,7 +869,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, } while(1); if (FAILED(hr)) { - av_log(avctx, AV_LOG_ERROR, "Failed to begin frame: 0x%x\n", hr); + av_log(avctx, AV_LOG_ERROR, "Failed to begin frame: 0x%x\n", (unsigned)hr); ff_dxva2_unlock(avctx); return -1; } @@ -966,7 +964,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, } #endif if (FAILED(hr)) { - av_log(avctx, AV_LOG_ERROR, "Failed to execute: 0x%x\n", hr); + av_log(avctx, AV_LOG_ERROR, "Failed to execute: 0x%x\n", (unsigned)hr); result = -1; } @@ -981,7 +979,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, #endif ff_dxva2_unlock(avctx); if (FAILED(hr)) { - av_log(avctx, AV_LOG_ERROR, "Failed to end frame: 0x%x\n", hr); + av_log(avctx, AV_LOG_ERROR, "Failed to end frame: 0x%x\n", (unsigned)hr); result = -1; } From 086321c612185469ebb85a1887527c8915b488b7 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 22 Jun 2017 14:52:54 +0200 Subject: [PATCH 0289/2557] hwcontext_d3d11va: fix crash on frames_init failure It appears in this case, frames_ininit is called twice (once by av_hwframe_ctx_init(), and again by unreffing the frames ctx ref). Signed-off-by: Luca Barbato --- libavutil/hwcontext_d3d11va.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 5432dd8b51b87..0b36a563f13b8 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -104,9 +104,11 @@ static void d3d11va_frames_uninit(AVHWFramesContext *ctx) if (frames_hwctx->texture) ID3D11Texture2D_Release(frames_hwctx->texture); + frames_hwctx->texture = NULL; if (s->staging_texture) ID3D11Texture2D_Release(s->staging_texture); + s->staging_texture = NULL; } static void free_texture(void *opaque, uint8_t *data) From 98d73e4174333b37d961b79e1182be5a02156c02 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 22 Jun 2017 14:52:55 +0200 Subject: [PATCH 0290/2557] hwcontext_d3d11va: allocate staging texture lazily Makes dealing with formats that can not be used for staging textures easier (DXGI_FORMAT_420_OPAQUE). It also saves memory if the staging texture is never needed, so this is a good thing. Signed-off-by: Luca Barbato --- libavutil/hwcontext_d3d11va.c | 46 ++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 0b36a563f13b8..523a6d2dc6bfa 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -239,17 +239,6 @@ static int d3d11va_frames_init(AVHWFramesContext *ctx) } } - texDesc.ArraySize = 1; - texDesc.Usage = D3D11_USAGE_STAGING; - texDesc.BindFlags = 0; - texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - texDesc.MiscFlags = 0; - hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &s->staging_texture); - if (FAILED(hr)) { - av_log(ctx, AV_LOG_ERROR, "Could not create the staging texture (%lx)\n", (long)hr); - return AVERROR_UNKNOWN; - } - ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(AVD3D11FrameDescriptor), ctx, d3d11va_pool_alloc, NULL); if (!ctx->internal->pool_internal) @@ -295,6 +284,31 @@ static int d3d11va_transfer_get_formats(AVHWFramesContext *ctx, return 0; } +static int d3d11va_create_staging_texture(AVHWFramesContext *ctx) +{ + AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx; + D3D11VAFramesContext *s = ctx->internal->priv; + HRESULT hr; + D3D11_TEXTURE2D_DESC texDesc = { + .Width = ctx->width, + .Height = ctx->height, + .MipLevels = 1, + .Format = s->format, + .SampleDesc = { .Count = 1 }, + .ArraySize = 1, + .Usage = D3D11_USAGE_STAGING, + .CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE, + }; + + hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &s->staging_texture); + if (FAILED(hr)) { + av_log(ctx, AV_LOG_ERROR, "Could not create the staging texture (%lx)\n", (long)hr); + return AVERROR_UNKNOWN; + } + + return 0; +} + static void fill_texture_ptrs(uint8_t *data[4], int linesize[4], AVHWFramesContext *ctx, D3D11_TEXTURE2D_DESC *desc, @@ -320,7 +334,7 @@ static int d3d11va_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, // (The interface types are compatible.) ID3D11Resource *texture = (ID3D11Resource *)(ID3D11Texture2D *)frame->data[0]; int index = (intptr_t)frame->data[1]; - ID3D11Resource *staging = (ID3D11Resource *)s->staging_texture; + ID3D11Resource *staging; int w = FFMIN(dst->width, src->width); int h = FFMIN(dst->height, src->height); uint8_t *map_data[4]; @@ -334,6 +348,14 @@ static int d3d11va_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, device_hwctx->lock(device_hwctx->lock_ctx); + if (!s->staging_texture) { + int res = d3d11va_create_staging_texture(ctx); + if (res < 0) + return res; + } + + staging = (ID3D11Resource *)s->staging_texture; + ID3D11Texture2D_GetDesc(s->staging_texture, &desc); if (download) { From 5030e3856c2126fb829edb828f5aae011d178eb4 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 22 Jun 2017 14:52:56 +0200 Subject: [PATCH 0291/2557] dxva: support DXGI_FORMAT_420_OPAQUE decoding Some devices (some phones, apparently) will support only this opaque format. Of course this won't work with CLI, because copying data directly is not supported. Automatic frame allocation (setting AVCodecContext.hw_device_ctx) does not support this mode, even if it's the only supported mode. But since opaque surfaces are generally less useful, that's probably ok. Signed-off-by: Luca Barbato --- libavcodec/dxva2.c | 13 +++++++++++-- libavutil/hwcontext_d3d11va.c | 12 ++++++++++-- libavutil/hwcontext_d3d11va.h | 4 ++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index 23d96687dcd33..79b77150d08d4 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -389,19 +389,28 @@ static int d3d11va_get_decoder_configuration(AVCodecContext *avctx, return ret; } +static DXGI_FORMAT d3d11va_map_sw_to_hw_format(enum AVPixelFormat pix_fmt) +{ + switch (pix_fmt) { + case AV_PIX_FMT_NV12: return DXGI_FORMAT_NV12; + case AV_PIX_FMT_P010: return DXGI_FORMAT_P010; + case AV_PIX_FMT_YUV420P: return DXGI_FORMAT_420_OPAQUE; + default: return DXGI_FORMAT_UNKNOWN; + } +} + static int d3d11va_create_decoder(AVCodecContext *avctx) { FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); GUID *guid_list; unsigned guid_count, i; GUID decoder_guid; - DXGI_FORMAT surface_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? - DXGI_FORMAT_P010 : DXGI_FORMAT_NV12; D3D11_VIDEO_DECODER_DESC desc = { 0 }; D3D11_VIDEO_DECODER_CONFIG config; AVHWFramesContext *frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; AVD3D11VADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx; + DXGI_FORMAT surface_format = d3d11va_map_sw_to_hw_format(frames_ctx->sw_format); D3D11_TEXTURE2D_DESC texdesc; HRESULT hr; int ret; diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 523a6d2dc6bfa..376c76e5cfd54 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -83,8 +83,11 @@ static const struct { DXGI_FORMAT d3d_format; enum AVPixelFormat pix_fmt; } supported_formats[] = { - { DXGI_FORMAT_NV12, AV_PIX_FMT_NV12 }, - { DXGI_FORMAT_P010, AV_PIX_FMT_P010 }, + { DXGI_FORMAT_NV12, AV_PIX_FMT_NV12 }, + { DXGI_FORMAT_P010, AV_PIX_FMT_P010 }, + // Special opaque formats. The pix_fmt is merely a place holder, as the + // opaque format cannot be accessed directly. + { DXGI_FORMAT_420_OPAQUE, AV_PIX_FMT_YUV420P }, }; static void d3d11va_default_lock(void *ctx) @@ -270,6 +273,7 @@ static int d3d11va_transfer_get_formats(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats) { + D3D11VAFramesContext *s = ctx->internal->priv; enum AVPixelFormat *fmts; fmts = av_malloc_array(2, sizeof(*fmts)); @@ -279,6 +283,10 @@ static int d3d11va_transfer_get_formats(AVHWFramesContext *ctx, fmts[0] = ctx->sw_format; fmts[1] = AV_PIX_FMT_NONE; + // Don't signal support for opaque formats. Actual access would fail. + if (s->format == DXGI_FORMAT_420_OPAQUE) + fmts[0] = AV_PIX_FMT_NONE; + *formats = fmts; return 0; diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h index 676349d7b81a4..d41451580eae7 100644 --- a/libavutil/hwcontext_d3d11va.h +++ b/libavutil/hwcontext_d3d11va.h @@ -26,6 +26,10 @@ * The default pool implementation will be fixed-size if initial_pool_size is * set (and allocate elements from an array texture). Otherwise it will allocate * individual textures. Be aware that decoding requires a single array texture. + * + * Using sw_format==AV_PIX_FMT_YUV420P has special semantics, and maps to + * DXGI_FORMAT_420_OPAQUE. av_hwframe_transfer_data() is not supported for + * this format. Refer to MSDN for details. */ #include From cfc9e7c94eafa33e7f109099664ec4fb57ac5ca3 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 22 Jun 2017 14:52:57 +0200 Subject: [PATCH 0292/2557] hwcontext_d3d11va: add option to enable debug mode Basically copied from VLC (LGPL): http://git.videolan.org/?p=vlc.git;a=blob;f=modules/video_output/win32/direct3d11.c;h=e9fcb83dcabfe778f26e63d19f218caf06a7c3ae;hb=HEAD#l1482 http://git.videolan.org/?p=vlc.git;a=blob;f=modules/codec/avcodec/d3d11va.c;h=85e7d25caebc059a9770da2ef4bb8fe90816d76d;hb=HEAD#l599 Signed-off-by: Luca Barbato --- configure | 2 ++ libavutil/hwcontext_d3d11va.c | 32 ++++++++++++++++++++++++++++++++ libavutil/hwcontext_d3d11va.h | 4 ++++ 3 files changed, 38 insertions(+) diff --git a/configure b/configure index ab183745a72a1..96bc5ab559063 100755 --- a/configure +++ b/configure @@ -1561,6 +1561,7 @@ HEADERS_LIST=" dev_video_meteor_ioctl_meteor_h direct_h dlfcn_h + dxgidebug_h dxva_h gsm_h io_h @@ -4660,6 +4661,7 @@ check_struct windows.h "CONDITION_VARIABLE" Ptr check_header d3d11.h check_header direct.h check_header dlfcn.h +check_header dxgidebug.h check_header dxva.h check_header dxva2api.h check_header io.h diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 376c76e5cfd54..75f78d86690b7 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + #include // Include thread.h before redefining _WIN32_WINNT, to get @@ -32,6 +34,10 @@ #include #include +#if HAVE_DXGIDEBUG_H +#include +#endif + #include "avassert.h" #include "common.h" #include "hwcontext.h" @@ -476,8 +482,18 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, IDXGIAdapter *pAdapter = NULL; ID3D10Multithread *pMultithread; UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT; + int is_debug = !!av_dict_get(opts, "debug", NULL, 0); int ret; + // (On UWP we can't check this.) +#if HAVE_LOADLIBRARY + if (!LoadLibrary("d3d11_1sdklayers.dll")) + is_debug = 0; +#endif + + if (is_debug) + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; + if ((ret = ff_thread_once(&functions_loaded, load_functions)) != 0) return AVERROR_UNKNOWN; if (!mD3D11CreateDevice || !mCreateDXGIFactory) { @@ -511,6 +527,22 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, ID3D10Multithread_Release(pMultithread); } +#if HAVE_LOADLIBRARY && HAVE_DXGIDEBUG_H + if (is_debug) { + HANDLE dxgidebug_dll = LoadLibrary("dxgidebug.dll"); + if (dxgidebug_dll) { + HRESULT (WINAPI * pf_DXGIGetDebugInterface)(const GUID *riid, void **ppDebug) + = (void *)GetProcAddress(dxgidebug_dll, "DXGIGetDebugInterface"); + if (pf_DXGIGetDebugInterface) { + IDXGIDebug *dxgi_debug = NULL; + hr = pf_DXGIGetDebugInterface(&IID_IDXGIDebug, (void**)&dxgi_debug); + if (SUCCEEDED(hr) && dxgi_debug) + IDXGIDebug_ReportLiveObjects(dxgi_debug, DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL); + } + } + } +#endif + return 0; } diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h index d41451580eae7..0ed303345294e 100644 --- a/libavutil/hwcontext_d3d11va.h +++ b/libavutil/hwcontext_d3d11va.h @@ -30,6 +30,10 @@ * Using sw_format==AV_PIX_FMT_YUV420P has special semantics, and maps to * DXGI_FORMAT_420_OPAQUE. av_hwframe_transfer_data() is not supported for * this format. Refer to MSDN for details. + * + * av_hwdevice_ctx_create() for this device type supports a key named "debug" + * for the AVDictionary entry. If this is set to any value, the device creation + * code will try to load various supported D3D debugging layers. */ #include From 068eaa534e7ddb2155e2830818d5c3f1069c68d8 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 22 Jun 2017 14:52:59 +0200 Subject: [PATCH 0293/2557] dxva: verbose-log decoder GUID list Helpful for debugging. Signed-off-by: Luca Barbato --- libavcodec/dxva2.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index 79b77150d08d4..a60604a84f36d 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -196,12 +196,59 @@ static int dxva_check_codec_compatibility(AVCodecContext *avctx, const dxva_mode return 1; } +static void dxva_list_guids_debug(AVCodecContext *avctx, void *service, + unsigned guid_count, const GUID *guid_list) +{ + FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); + int i; + + av_log(avctx, AV_LOG_VERBOSE, "Decoder GUIDs reported as supported:\n"); + + for (i = 0; i < guid_count; i++) { + const GUID *guid = &guid_list[i]; + + av_log(avctx, AV_LOG_VERBOSE, + "{%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}", + (unsigned) guid->Data1, guid->Data2, guid->Data3, + guid->Data4[0], guid->Data4[1], + guid->Data4[2], guid->Data4[3], + guid->Data4[4], guid->Data4[5], + guid->Data4[6], guid->Data4[7]); + +#if CONFIG_D3D11VA + if (sctx->pix_fmt == AV_PIX_FMT_D3D11) { + DXGI_FORMAT format; + // We don't know the maximum valid DXGI_FORMAT, so use 200 as + // arbitrary upper bound (that could become outdated). + for (format = 0; format < 200; format++) { + if (d3d11va_validate_output(service, *guid, &format)) + av_log(avctx, AV_LOG_VERBOSE, " %d", (int)format); + } + } +#endif +#if CONFIG_DXVA2 + if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + const D3DFORMAT formats[] = {MKTAG('N', 'V', '1', '2'), + MKTAG('P', '0', '1', '0')}; + int i; + for (i = 0; i < FF_ARRAY_ELEMS(formats); i++) { + if (dxva2_validate_output(service, *guid, &formats[i])) + av_log(avctx, AV_LOG_VERBOSE, " %d", i); + } + } +#endif + av_log(avctx, AV_LOG_VERBOSE, "\n"); + } +} + static int dxva_get_decoder_guid(AVCodecContext *avctx, void *service, void *surface_format, unsigned guid_count, const GUID *guid_list, GUID *decoder_guid) { FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); unsigned i, j; + dxva_list_guids_debug(avctx, service, guid_count, guid_list); + *decoder_guid = ff_GUID_NULL; for (i = 0; dxva_modes[i].guid; i++) { const dxva_mode *mode = &dxva_modes[i]; From 3fdf50f9e864c88da2139cf066832944de81acaa Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 22 Jun 2017 20:05:12 +0200 Subject: [PATCH 0294/2557] hwframe: Allow hwaccel frame allocators to align surface sizes Hardware accelerated decoding generally uses AVHWFramesContext for pool allocation of hardware surfaces. These are setup to allocate surfaces aligned to hardware and hwaccel API requirements. Due to the architecture, av_hwframe_get_buffer() will return AVFrames with the dimensions set to the aligned sizes. This causes some decoders (like hevc) return these aligned size as final frame size, instead of cropping them to the video's actual dimensions. To make sure this doesn't happen, crop the frame to the size the decoder expects when ff_get_buffer() is called. Signed-off-by: Luca Barbato --- libavcodec/decode.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index ae2c715677a85..175a6fae4c568 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1006,8 +1006,12 @@ int avcodec_default_get_buffer2(AVCodecContext *avctx, AVFrame *frame, int flags { int ret; - if (avctx->hw_frames_ctx) - return av_hwframe_get_buffer(avctx->hw_frames_ctx, frame, 0); + if (avctx->hw_frames_ctx) { + ret = av_hwframe_get_buffer(avctx->hw_frames_ctx, frame, 0); + frame->width = avctx->coded_width; + frame->height = avctx->coded_height; + return ret; + } if ((ret = update_frame_pool(avctx, frame)) < 0) return ret; From 1cfd566324f4a9be066ea400685b81c0695e64d9 Mon Sep 17 00:00:00 2001 From: Lorenz Brun Date: Fri, 21 Oct 2016 22:51:37 +0200 Subject: [PATCH 0295/2557] dvbsubdec: Fixed segfault when decoding subtitles This fixes a segfault (originally found in Movian, but traced to libav) when decoding subtitles because only an array of rects is allocated, but not the actual structs it contains. The issue was probably introduced in commit 2383323 where the loop to allocate the rects in the array was thrown away. Signed-off-by: Vittorio Giovara --- libavcodec/dvbsubdec.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c index 6530847dff1ad..63523b765e735 100644 --- a/libavcodec/dvbsubdec.c +++ b/libavcodec/dvbsubdec.c @@ -1285,13 +1285,18 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, } sub->num_rects = ctx->display_list_size; - if (sub->num_rects <= 0) - return AVERROR_INVALIDDATA; - sub->rects = av_mallocz_array(sub->num_rects * sub->num_rects, - sizeof(*sub->rects)); - if (!sub->rects) - return AVERROR(ENOMEM); + if (sub->num_rects > 0) { + sub->rects = av_mallocz(sizeof(*sub->rects) * sub->num_rects); + if (!sub->rects) + return AVERROR(ENOMEM); + for (i = 0; i < sub->num_rects; i++) { + sub->rects[i] = av_mallocz(sizeof(*sub->rects[i])); + if (!sub->rects[i]) { + return AVERROR(ENOMEM); + } + } + } i = 0; From 969f215957b25ec014aeed6e440ecb450e6927c1 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Fri, 9 Jun 2017 17:27:22 -0400 Subject: [PATCH 0296/2557] hevc: Add support for alternative transfer characterics SEI The use of this SEI is for backward compatibility in HLG HDR systems: older devices that cannot interpret the "arib-std-b67" transfer will get the compatible transfer (usually bt709 or bt2020) from the VUI, while newer devices that can interpret HDR will read the SEI and use its value instead. Signed-off-by: Vittorio Giovara --- libavcodec/hevc_sei.c | 9 +++++++++ libavcodec/hevc_sei.h | 7 +++++++ libavcodec/hevcdec.c | 6 ++++++ 3 files changed, 22 insertions(+) diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 153d211b4b135..0a5d4440bf4fb 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -86,6 +86,13 @@ static int decode_nal_sei_display_orientation(HEVCSEIDisplayOrientation *s, GetB return 0; } +static int decode_nal_sei_alternative_transfer(HEVCSEIAlternativeTransfer *s, GetBitContext *gb) +{ + s->present = 1; + s->preferred_transfer_characteristics = get_bits(gb, 8); + return 0; +} + static int decode_nal_sei_prefix(GetBitContext *gb, void *logctx, HEVCSEI *s, int type, int size) { @@ -96,6 +103,8 @@ static int decode_nal_sei_prefix(GetBitContext *gb, void *logctx, HEVCSEI *s, return decode_nal_sei_frame_packing_arrangement(&s->frame_packing, gb); case HEVC_SEI_TYPE_DISPLAY_ORIENTATION: return decode_nal_sei_display_orientation(&s->display_orientation, gb); + case HEVC_SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS: + return decode_nal_sei_alternative_transfer(&s->alternative_transfer, gb); default: av_log(logctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type); skip_bits_long(gb, 8 * size); diff --git a/libavcodec/hevc_sei.h b/libavcodec/hevc_sei.h index b699fef45dc22..e4aeac1fbe02e 100644 --- a/libavcodec/hevc_sei.h +++ b/libavcodec/hevc_sei.h @@ -54,6 +54,7 @@ typedef enum { HEVC_SEI_TYPE_REGION_REFRESH_INFO = 134, HEVC_SEI_TYPE_MASTERING_DISPLAY_INFO = 137, HEVC_SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO = 144, + HEVC_SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS = 147, } HEVC_SEI_Type; typedef struct HEVCSEIPictureHash { @@ -74,10 +75,16 @@ typedef struct HEVCSEIDisplayOrientation { int hflip, vflip; } HEVCSEIDisplayOrientation; +typedef struct HEVCSEIAlternativeTransfer { + int present; + int preferred_transfer_characteristics; +} HEVCSEIAlternativeTransfer; + typedef struct HEVCSEI { HEVCSEIPictureHash picture_hash; HEVCSEIFramePacking frame_packing; HEVCSEIDisplayOrientation display_orientation; + HEVCSEIAlternativeTransfer alternative_transfer; } HEVCSEI; int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 7a9182af9bfe7..ac0b1a3c1d151 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2407,6 +2407,12 @@ static int set_side_data(HEVCContext *s) s->sei.display_orientation.vflip); } + if (s->sei.alternative_transfer.present && + av_color_transfer_name(s->sei.alternative_transfer.preferred_transfer_characteristics) && + s->sei.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) { + s->avctx->color_trc = s->sei.alternative_transfer.preferred_transfer_characteristics; + } + return 0; } From a594f17f83a1ffdc1eec18818208fe39487dd5d7 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Tue, 13 Jun 2017 11:35:16 -0400 Subject: [PATCH 0297/2557] dvbsubdec: Free subrect memory on allocation error Signed-off-by: Vittorio Giovara --- libavcodec/dvbsubdec.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c index 63523b765e735..b97ff8027b4c8 100644 --- a/libavcodec/dvbsubdec.c +++ b/libavcodec/dvbsubdec.c @@ -1293,6 +1293,10 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, for (i = 0; i < sub->num_rects; i++) { sub->rects[i] = av_mallocz(sizeof(*sub->rects[i])); if (!sub->rects[i]) { + int j; + for (j = 0; j < i; j ++) + av_free(sub->rects[j]); + av_free(sub->rects); return AVERROR(ENOMEM); } } @@ -1335,6 +1339,8 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, rect->data[1] = av_mallocz(AVPALETTE_SIZE); if (!rect->data[1]) { + for (i = 0; i < sub->num_rects; i++) + av_free(sub->rects[i]); av_free(sub->rects); return AVERROR(ENOMEM); } @@ -1343,6 +1349,8 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, rect->data[0] = av_malloc(region->buf_size); if (!rect->data[0]) { av_free(rect->data[1]); + for (i = 0; i < sub->num_rects; i++) + av_free(sub->rects[i]); av_free(sub->rects); return AVERROR(ENOMEM); } From 61f589e31e84ae02d7ac6837f30f19c437b1fc2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 30 Jun 2017 12:49:49 +0300 Subject: [PATCH 0298/2557] lavf: Remove codec_tag from dashenc and smoothstreamingenc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the tags enforced and set on the segmenter muxer level mismatch what the mp4/ismv muxer uses (since 713efb2c0d013). Skip the codec_tag altogether here, to let the user (try to) set whichever codec/tag is preferred; the individual chained muxer will reject invalid codecs anyway. Signed-off-by: Martin Storsjö --- libavformat/dashenc.c | 1 - libavformat/smoothstreamingenc.c | 1 - 2 files changed, 2 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 7134af4978b2c..336cea24ec33b 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1272,6 +1272,5 @@ AVOutputFormat ff_dash_muxer = { .write_header = dash_write_header, .write_packet = dash_write_packet, .write_trailer = dash_write_trailer, - .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, .priv_class = &dash_class, }; diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c index 997b9e636cc2b..9a6682465ba87 100644 --- a/libavformat/smoothstreamingenc.c +++ b/libavformat/smoothstreamingenc.c @@ -662,6 +662,5 @@ AVOutputFormat ff_smoothstreaming_muxer = { .write_header = ism_write_header, .write_packet = ism_write_packet, .write_trailer = ism_write_trailer, - .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, .priv_class = &ism_class, }; From 1912973a2d0a4d7f8e323eb23ee4e0e29d5852ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 4 Jul 2017 20:03:00 +0300 Subject: [PATCH 0299/2557] d3d11va: Check WINAPI_FAMILY instead of HAVE_LOADLIBRARY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If using the winstore compat library, a fallback LoadLibrary function does exist, that only calls LoadPackagedLibrary though (which doesn't work for dynamically loading d3d11 DLLs). Therefore explicitly check the targeted API family instead. Make this check a reusable HAVE_* component which other parts of the libraries can check when necessary as well. Signed-off-by: Martin Storsjö --- configure | 14 +++++++++++++- libavutil/hwcontext_d3d11va.c | 6 +++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 96bc5ab559063..d92ce33e6d1b3 100755 --- a/configure +++ b/configure @@ -1720,6 +1720,7 @@ HAVE_LIST=" sdl section_data_rel_ro threads + uwp vaapi_drm vaapi_x11 vdpau_x11 @@ -4894,7 +4895,18 @@ fi # d3d11va requires linking directly to dxgi and d3d11 if not building for # the desktop api partition -enabled LoadLibrary || d3d11va_extralibs="-ldxgi -ld3d11" +check_cpp < +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#error desktop, not uwp +#else +// WINAPI_FAMILY_APP, WINAPI_FAMILY_PHONE_APP => UWP +#endif +#else +#error no family set +#endif +EOF enabled vaapi && require vaapi va/va.h vaInitialize -lva diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 75f78d86690b7..0a8cc5bc21f84 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -56,7 +56,7 @@ static PFN_D3D11_CREATE_DEVICE mD3D11CreateDevice; static av_cold void load_functions(void) { -#if HAVE_LOADLIBRARY +#if !HAVE_UWP // We let these "leak" - this is fine, as unloading has no great benefit, and // Windows will mark a DLL as loaded forever if its internal refcount overflows // from too many LoadLibrary calls. @@ -486,7 +486,7 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, int ret; // (On UWP we can't check this.) -#if HAVE_LOADLIBRARY +#if !HAVE_UWP if (!LoadLibrary("d3d11_1sdklayers.dll")) is_debug = 0; #endif @@ -527,7 +527,7 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, ID3D10Multithread_Release(pMultithread); } -#if HAVE_LOADLIBRARY && HAVE_DXGIDEBUG_H +#if !HAVE_UWP && HAVE_DXGIDEBUG_H if (is_debug) { HANDLE dxgidebug_dll = LoadLibrary("dxgidebug.dll"); if (dxgidebug_dll) { From 4d330da006fe48178a4c8047f06270925eaedf63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 5 Jul 2017 12:36:03 +0300 Subject: [PATCH 0300/2557] os_support: Use HAVE_UWP instead of manually checking WINAPI_FAMILY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/os_support.h | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/libavformat/os_support.h b/libavformat/os_support.h index 965e16fa5e937..55c2fdb1f10fe 100644 --- a/libavformat/os_support.h +++ b/libavformat/os_support.h @@ -129,18 +129,6 @@ int ff_poll(struct pollfd *fds, nfds_t numfds, int timeout); #include #include "libavutil/wchar_filename.h" -#ifdef WINAPI_FAMILY -#include -// If a WINAPI_FAMILY is defined, check that the desktop API subset -// is enabled -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -#define USE_MOVEFILEEXA -#endif -#else -// If no WINAPI_FAMILY is defined, assume the full API subset -#define USE_MOVEFILEEXA -#endif - #define DEF_FS_FUNCTION(name, wfunc, afunc) \ static inline int win32_##name(const char *filename_utf8) \ { \ @@ -192,7 +180,7 @@ static inline int win32_rename(const char *src_utf8, const char *dest_utf8) fallback: /* filename may be be in CP_ACP */ -#ifdef USE_MOVEFILEEXA +#if !HAVE_UWP ret = MoveFileExA(src_utf8, dest_utf8, MOVEFILE_REPLACE_EXISTING); if (ret) errno = EPERM; From 89e632de9b3acb05938d0d1ce7d74590c0ac65f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Wed, 28 Jun 2017 00:27:11 +0200 Subject: [PATCH 0301/2557] Add Cinepak encoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With permission of Tomas Härdin applied by Rl aetey.se Signed-off-by: Diego Biurrun --- Changelog | 1 + doc/general.texi | 2 +- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 2 +- libavcodec/cinepakenc.c | 822 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 826 insertions(+), 2 deletions(-) create mode 100644 libavcodec/cinepakenc.c diff --git a/Changelog b/Changelog index e44df54c93d47..adcca3fcc5381 100644 --- a/Changelog +++ b/Changelog @@ -16,6 +16,7 @@ version : - FM Screen Capture Codec decoder - ClearVideo decoder (I-frames only) - support for decoding through D3D11VA in avconv +- Cinepak encoder version 12: diff --git a/doc/general.texi b/doc/general.texi index 905e2d1810dfe..adf5b4eabfd04 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -631,7 +631,7 @@ following image formats are supported: @tab Codec used in Delphine Software International games. @item Discworld II BMV Video @tab @tab X @item Canopus Lossless Codec @tab @tab X -@item Cinepak @tab @tab X +@item Cinepak @tab X @tab X @item Cirrus Logic AccuPak @tab X @tab X @tab fourcc: CLJR @item Creative YUV (CYUV) @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 240f7d83a173b..2b9158822dddb 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -186,6 +186,7 @@ OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o OBJS-$(CONFIG_CFHD_DECODER) += cfhd.o cfhddata.o OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o +OBJS-$(CONFIG_CINEPAK_ENCODER) += cinepakenc.o OBJS-$(CONFIG_CLEARVIDEO_DECODER) += clearvideo.o OBJS-$(CONFIG_CLJR_DECODER) += cljrdec.o OBJS-$(CONFIG_CLJR_ENCODER) += cljrenc.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 70c35e9b4d789..5635ae150c96a 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -133,7 +133,7 @@ void avcodec_register_all(void) REGISTER_DECODER(CDGRAPHICS, cdgraphics); REGISTER_DECODER(CDXL, cdxl); REGISTER_DECODER(CFHD, cfhd); - REGISTER_DECODER(CINEPAK, cinepak); + REGISTER_ENCDEC (CINEPAK, cinepak); REGISTER_DECODER(CLEARVIDEO, clearvideo); REGISTER_ENCDEC (CLJR, cljr); REGISTER_DECODER(CLLC, cllc); diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c new file mode 100644 index 0000000000000..2809295d461fb --- /dev/null +++ b/libavcodec/cinepakenc.c @@ -0,0 +1,822 @@ +/* + * Cinepak encoder (c) 2011 Tomas Härdin + * http://titan.codemill.se/~tomhar/cinepakenc.patch + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + + */ + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "libavutil/lfg.h" +#include "elbg.h" + +#define CVID_HEADER_SIZE 10 +#define STRIP_HEADER_SIZE 12 +#define CHUNK_HEADER_SIZE 4 + +#define MB_SIZE 4 //4x4 MBs +#define MB_AREA (MB_SIZE*MB_SIZE) + +#define VECTOR_MAX 6 //six or four entries per vector depending on format +#define CODEBOOK_MAX 256 +#define CODEBOOK_NUM 5 //five potential codebooks (1, 4, 16, 64, 256) for V1 and V4 + +#define MAX_STRIPS 1 //Note: having fewer choices regarding the number of strip speeds up encoding (obviously) +#define MIN_STRIPS 1 //Note: having more strips speeds up encoding the frame (this is less obvious) + +typedef enum { + MODE_V1_ONLY = 0, + MODE_V1_V4, + MODE_MC, + + MODE_COUNT, +} CinepakMode; + +typedef enum { + ENC_V1, + ENC_V4, + ENC_SKIP +} mb_encoding; + +typedef struct { + int v1_vector; //index into v1 codebook + int v1_error; //error when using V1 encoding + int v4_vector[CODEBOOK_NUM][4]; //indices into v4 codebooks + int v4_error[CODEBOOK_NUM]; //error when using V4 encodings + int skip_error; //error when block is skipped (aka copied from last frame) + mb_encoding best_encoding; //last result from calculate_mode_score() +} mb_info; + +typedef struct { + int v1_codebook[CODEBOOK_MAX*VECTOR_MAX]; + int *v4_codebook; +} strip_info; + +typedef struct { + AVCodecContext *avctx; + unsigned char *pict_bufs[3], *strip_buf, *frame_buf; + AVFrame last_frame; + AVFrame best_frame; + AVFrame scratch_frame; + enum AVPixelFormat pix_fmt; + int w, h; + int curframe, keyint; + AVLFG randctx; + uint64_t lambda; + int *codebook_input; + int *codebook_closest; + mb_info *mb; //MB RD state +#ifdef CINEPAKENC_DEBUG + mb_info *best_mb; //TODO: remove. only used for printing stats +#endif + int num_v1_mode, num_v4_mode, num_mc_mode; + int num_v1_encs, num_v4_encs, num_skips; +} CinepakEncContext; + +static av_cold int cinepak_encode_init(AVCodecContext *avctx) +{ + CinepakEncContext *s = avctx->priv_data; + int x, mb_count, strip_buf_size, frame_buf_size; + + if (avctx->width & 3 || avctx->height & 3) { + av_log(avctx, AV_LOG_ERROR, "width and height must be multiples of four (got %ix%i)\n", + avctx->width, avctx->height); + return AVERROR(EINVAL); + } + + if (!(s->codebook_input = av_malloc(sizeof(int) * (avctx->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4) * (avctx->width * avctx->height) >> 2))) + return AVERROR(ENOMEM); + + if (!(s->codebook_closest = av_malloc(sizeof(int) * (avctx->width * avctx->height) >> 2))) + goto enomem; + + for(x = 0; x < 3; x++) + if(!(s->pict_bufs[x] = av_malloc((avctx->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4) * (avctx->width * avctx->height) >> 2))) + goto enomem; + + mb_count = avctx->width * avctx->height / MB_AREA; + + //the largest possible chunk is 0x31 with all MBs encoded in V4 mode, which is 34 bits per MB + strip_buf_size = STRIP_HEADER_SIZE + 3 * CHUNK_HEADER_SIZE + 2 * VECTOR_MAX * CODEBOOK_MAX + 4 * (mb_count + (mb_count + 15) / 16); + + frame_buf_size = CVID_HEADER_SIZE + MAX_STRIPS * strip_buf_size; + + if (!(s->strip_buf = av_malloc(strip_buf_size))) + goto enomem; + + if (!(s->frame_buf = av_malloc(frame_buf_size))) + goto enomem; + + if (!(s->mb = av_malloc(mb_count*sizeof(mb_info)))) + goto enomem; + +#ifdef CINEPAKENC_DEBUG + if (!(s->best_mb = av_malloc(mb_count*sizeof(mb_info)))) + goto enomem; +#endif + + av_lfg_init(&s->randctx, 1); + s->avctx = avctx; + s->w = avctx->width; + s->h = avctx->height; + s->curframe = 0; + s->keyint = avctx->keyint_min; + s->pix_fmt = avctx->pix_fmt; + + //set up AVFrames + s->last_frame.data[0] = s->pict_bufs[0]; + s->last_frame.linesize[0] = s->w; + s->best_frame.data[0] = s->pict_bufs[1]; + s->best_frame.linesize[0] = s->w; + s->scratch_frame.data[0] = s->pict_bufs[2]; + s->scratch_frame.linesize[0] = s->w; + + if(s->pix_fmt == AV_PIX_FMT_YUV420P) { + s->last_frame.data[1] = s->last_frame.data[0] + s->w * s->h; + s->last_frame.data[2] = s->last_frame.data[1] + ((s->w * s->h) >> 2); + s->last_frame.linesize[1] = s->last_frame.linesize[2] = s->w >> 1; + + s->best_frame.data[1] = s->best_frame.data[0] + s->w * s->h; + s->best_frame.data[2] = s->best_frame.data[1] + ((s->w * s->h) >> 2); + s->best_frame.linesize[1] = s->best_frame.linesize[2] = s->w >> 1; + + s->scratch_frame.data[1] = s->scratch_frame.data[0] + s->w * s->h; + s->scratch_frame.data[2] = s->scratch_frame.data[1] + ((s->w * s->h) >> 2); + s->scratch_frame.linesize[1] = s->scratch_frame.linesize[2] = s->w >> 1; + } + + s->num_v1_mode = s->num_v4_mode = s->num_mc_mode = s->num_v1_encs = s->num_v4_encs = s->num_skips = 0; + + return 0; + +enomem: + av_free(s->codebook_input); + av_free(s->codebook_closest); + av_free(s->strip_buf); + av_free(s->frame_buf); + av_free(s->mb); +#ifdef CINEPAKENC_DEBUG + av_free(s->best_mb); +#endif + + for(x = 0; x < 3; x++) + av_free(s->pict_bufs[x]); + + return AVERROR(ENOMEM); +} + +static int64_t calculate_mode_score(CinepakEncContext *s, CinepakMode mode, int h, int v1_size, int v4_size, int v4, strip_info *info) +{ + //score = FF_LAMBDA_SCALE * error + lambda * bits + int x; + int entry_size = s->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4; + int mb_count = s->w * h / MB_AREA; + mb_info *mb; + int64_t score1, score2, score3; + int64_t ret = s->lambda * ((v1_size ? CHUNK_HEADER_SIZE + v1_size * entry_size : 0) + + (v4_size ? CHUNK_HEADER_SIZE + v4_size * entry_size : 0) + + CHUNK_HEADER_SIZE) << 3; + + //av_log(s->avctx, AV_LOG_INFO, "sizes %3i %3i -> %9li score mb_count %i", v1_size, v4_size, ret, mb_count); + + switch(mode) { + case MODE_V1_ONLY: + //one byte per MB + ret += s->lambda * 8 * mb_count; + + for(x = 0; x < mb_count; x++) { + mb = &s->mb[x]; + ret += FF_LAMBDA_SCALE * mb->v1_error; + mb->best_encoding = ENC_V1; + } + + break; + case MODE_V1_V4: + //9 or 33 bits per MB + for(x = 0; x < mb_count; x++) { + mb = &s->mb[x]; + score1 = s->lambda * 9 + FF_LAMBDA_SCALE * mb->v1_error; + score2 = s->lambda * 33 + FF_LAMBDA_SCALE * mb->v4_error[v4]; + + if(score1 <= score2) { + ret += score1; + mb->best_encoding = ENC_V1; + } else { + ret += score2; + mb->best_encoding = ENC_V4; + } + } + + break; + case MODE_MC: + //1, 10 or 34 bits per MB + for(x = 0; x < mb_count; x++) { + mb = &s->mb[x]; + score1 = s->lambda * 1 + FF_LAMBDA_SCALE * mb->skip_error; + score2 = s->lambda * 10 + FF_LAMBDA_SCALE * mb->v1_error; + score3 = s->lambda * 34 + FF_LAMBDA_SCALE * mb->v4_error[v4]; + + + if(score1 <= score2 && score1 <= score3) { + ret += score1; + mb->best_encoding = ENC_SKIP; + } else if(score2 <= score1 && score2 <= score3) { + ret += score2; + mb->best_encoding = ENC_V1; + } else { + ret += score3; + mb->best_encoding = ENC_V4; + } + } + + break; + } + + return ret; +} + +static int write_chunk_header(unsigned char *buf, int chunk_type, int chunk_size) +{ + buf[0] = chunk_type; + AV_WB24(&buf[1], chunk_size + CHUNK_HEADER_SIZE); + return CHUNK_HEADER_SIZE; +} + +static int encode_codebook(CinepakEncContext *s, int *codebook, int size, int chunk_type_yuv, int chunk_type_gray, unsigned char *buf) +{ + int x, y, ret, entry_size = s->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4; + + ret = write_chunk_header(buf, s->pix_fmt == AV_PIX_FMT_YUV420P ? chunk_type_yuv : chunk_type_gray, entry_size * size); + + for(x = 0; x < size; x++) + for(y = 0; y < entry_size; y++) + buf[ret++] = codebook[y + x*entry_size] ^ (y >= 4 ? 0x80 : 0); + + return ret; +} + +//sets out to the sub picture starting at (x,y) in in +static void get_sub_picture(CinepakEncContext *s, int x, int y, AVPicture *in, AVPicture *out) +{ + out->data[0] = in->data[0] + x + y * in->linesize[0]; + out->linesize[0] = in->linesize[0]; + + if(s->pix_fmt == AV_PIX_FMT_YUV420P) { + out->data[1] = in->data[1] + (x >> 1) + (y >> 1) * in->linesize[1]; + out->linesize[1] = in->linesize[1]; + + out->data[2] = in->data[2] + (x >> 1) + (y >> 1) * in->linesize[2]; + out->linesize[2] = in->linesize[2]; + } +} + +//decodes the V1 vector in mb into the 4x4 MB pointed to by sub_pict +static void decode_v1_vector(CinepakEncContext *s, AVPicture *sub_pict, mb_info *mb, strip_info *info) +{ + int entry_size = s->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4; + + sub_pict->data[0][0] = + sub_pict->data[0][1] = + sub_pict->data[0][ sub_pict->linesize[0]] = + sub_pict->data[0][1+ sub_pict->linesize[0]] = info->v1_codebook[mb->v1_vector*entry_size]; + + sub_pict->data[0][2] = + sub_pict->data[0][3] = + sub_pict->data[0][2+ sub_pict->linesize[0]] = + sub_pict->data[0][3+ sub_pict->linesize[0]] = info->v1_codebook[mb->v1_vector*entry_size+1]; + + sub_pict->data[0][2*sub_pict->linesize[0]] = + sub_pict->data[0][1+2*sub_pict->linesize[0]] = + sub_pict->data[0][ 3*sub_pict->linesize[0]] = + sub_pict->data[0][1+3*sub_pict->linesize[0]] = info->v1_codebook[mb->v1_vector*entry_size+2]; + + sub_pict->data[0][2+2*sub_pict->linesize[0]] = + sub_pict->data[0][3+2*sub_pict->linesize[0]] = + sub_pict->data[0][2+3*sub_pict->linesize[0]] = + sub_pict->data[0][3+3*sub_pict->linesize[0]] = info->v1_codebook[mb->v1_vector*entry_size+3]; + + if(s->pix_fmt == AV_PIX_FMT_YUV420P) { + sub_pict->data[1][0] = + sub_pict->data[1][1] = + sub_pict->data[1][ sub_pict->linesize[1]] = + sub_pict->data[1][1+ sub_pict->linesize[1]] = info->v1_codebook[mb->v1_vector*entry_size+4]; + + sub_pict->data[2][0] = + sub_pict->data[2][1] = + sub_pict->data[2][ sub_pict->linesize[2]] = + sub_pict->data[2][1+ sub_pict->linesize[2]] = info->v1_codebook[mb->v1_vector*entry_size+5]; + } +} + +//decodes the V4 vectors in mb into the 4x4 MB pointed to by sub_pict +static void decode_v4_vector(CinepakEncContext *s, AVPicture *sub_pict, int *v4_vector, strip_info *info) +{ + int i, x, y, entry_size = s->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4; + + for(i = y = 0; y < 4; y += 2) { + for(x = 0; x < 4; x += 2, i++) { + sub_pict->data[0][x + y*sub_pict->linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size]; + sub_pict->data[0][x+1 + y*sub_pict->linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+1]; + sub_pict->data[0][x + (y+1)*sub_pict->linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+2]; + sub_pict->data[0][x+1 + (y+1)*sub_pict->linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+3]; + + if(s->pix_fmt == AV_PIX_FMT_YUV420P) { + sub_pict->data[1][(x>>1) + (y>>1)*sub_pict->linesize[1]] = info->v4_codebook[v4_vector[i]*entry_size+4]; + sub_pict->data[2][(x>>1) + (y>>1)*sub_pict->linesize[2]] = info->v4_codebook[v4_vector[i]*entry_size+5]; + } + } + } +} + +static int encode_mode(CinepakEncContext *s, CinepakMode mode, int h, int v1_size, int v4_size, int v4, AVPicture *scratch_pict, strip_info *info, unsigned char *buf) +{ + int x, y, z, flags, bits, temp_size, header_ofs, ret = 0, mb_count = s->w * h / MB_AREA; + int needs_extra_bit, should_write_temp; + unsigned char temp[64]; //32/2 = 16 V4 blocks at 4 B each -> 64 B + mb_info *mb; + AVPicture sub_scratch; + + //encode codebooks + if(v1_size) + ret += encode_codebook(s, info->v1_codebook, v1_size, 0x22, 0x26, buf + ret); + + if(v4_size) + ret += encode_codebook(s, info->v4_codebook, v4_size, 0x20, 0x24, buf + ret); + + //update scratch picture + for(z = y = 0; y < h; y += MB_SIZE) { + for(x = 0; x < s->w; x += MB_SIZE, z++) { + mb = &s->mb[z]; + + if(mode == MODE_MC && mb->best_encoding == ENC_SKIP) + continue; + + get_sub_picture(s, x, y, scratch_pict, &sub_scratch); + + if(mode == MODE_V1_ONLY || mb->best_encoding == ENC_V1) + decode_v1_vector(s, &sub_scratch, mb, info); + else if(mode != MODE_V1_ONLY && mb->best_encoding == ENC_V4) + decode_v4_vector(s, &sub_scratch, mb->v4_vector[v4], info); + } + } + + switch(mode) { + case MODE_V1_ONLY: + //av_log(s->avctx, AV_LOG_INFO, "mb_count = %i\n", mb_count); + ret += write_chunk_header(buf + ret, 0x32, mb_count); + + for(x = 0; x < mb_count; x++) + buf[ret++] = s->mb[x].v1_vector; + + break; + case MODE_V1_V4: + //remember header position + header_ofs = ret; + ret += CHUNK_HEADER_SIZE; + + for(x = 0; x < mb_count; x += 32) { + flags = 0; + for(y = x; y < FFMIN(x+32, mb_count); y++) + if(s->mb[y].best_encoding == ENC_V4) + flags |= 1 << (31 - y + x); + + AV_WB32(&buf[ret], flags); + ret += 4; + + for(y = x; y < FFMIN(x+32, mb_count); y++) { + mb = &s->mb[y]; + + if(mb->best_encoding == ENC_V1) + buf[ret++] = mb->v1_vector; + else + for(z = 0; z < 4; z++) + buf[ret++] = mb->v4_vector[v4][z]; + } + } + + write_chunk_header(buf + header_ofs, 0x30, ret - header_ofs - CHUNK_HEADER_SIZE); + + break; + case MODE_MC: + //remember header position + header_ofs = ret; + ret += CHUNK_HEADER_SIZE; + flags = bits = temp_size = 0; + + for(x = 0; x < mb_count; x++) { + mb = &s->mb[x]; + flags |= (mb->best_encoding != ENC_SKIP) << (31 - bits++); + needs_extra_bit = 0; + should_write_temp = 0; + + if(mb->best_encoding != ENC_SKIP) { + if(bits < 32) + flags |= (mb->best_encoding == ENC_V4) << (31 - bits++); + else + needs_extra_bit = 1; + } + + if(bits == 32) { + AV_WB32(&buf[ret], flags); + ret += 4; + flags = bits = 0; + + if(mb->best_encoding == ENC_SKIP || needs_extra_bit) { + memcpy(&buf[ret], temp, temp_size); + ret += temp_size; + temp_size = 0; + } else + should_write_temp = 1; + } + + if(needs_extra_bit) { + flags = (mb->best_encoding == ENC_V4) << 31; + bits = 1; + } + + if(mb->best_encoding == ENC_V1) + temp[temp_size++] = mb->v1_vector; + else if(mb->best_encoding == ENC_V4) + for(z = 0; z < 4; z++) + temp[temp_size++] = mb->v4_vector[v4][z]; + + if(should_write_temp) { + memcpy(&buf[ret], temp, temp_size); + ret += temp_size; + temp_size = 0; + } + } + + if(bits > 0) { + AV_WB32(&buf[ret], flags); + ret += 4; + memcpy(&buf[ret], temp, temp_size); + ret += temp_size; + } + + write_chunk_header(buf + header_ofs, 0x31, ret - header_ofs - CHUNK_HEADER_SIZE); + + break; + } + + return ret; +} + +//computes distortion of 4x4 MB in b compared to a +static int compute_mb_distortion(CinepakEncContext *s, AVPicture *a, AVPicture *b) +{ + int x, y, p, d, ret = 0; + + for(y = 0; y < MB_SIZE; y++) { + for(x = 0; x < MB_SIZE; x++) { + d = a->data[0][x + y*a->linesize[0]] - b->data[0][x + y*b->linesize[0]]; + ret += d*d; + } + } + + if(s->pix_fmt == AV_PIX_FMT_YUV420P) { + for(p = 1; p <= 2; p++) { + for(y = 0; y < MB_SIZE/2; y++) { + for(x = 0; x < MB_SIZE/2; x++) { + d = a->data[p][x + y*a->linesize[p]] - b->data[p][x + y*b->linesize[p]]; + ret += d*d; + } + } + } + } + + return ret; +} + +static int quantize(CinepakEncContext *s, int h, AVPicture *pict, int v1mode, int size, int v4, strip_info *info) +{ + int x, y, i, j, k, x2, y2, x3, y3, plane, shift; + int entry_size = s->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4; + int *codebook = v1mode ? info->v1_codebook : info->v4_codebook; + int64_t total_error = 0; + uint8_t vq_pict_buf[(MB_AREA*3)/2]; + AVPicture sub_pict, vq_pict; + + for(i = y = 0; y < h; y += MB_SIZE) { + for(x = 0; x < s->w; x += MB_SIZE, i += v1mode ? 1 : 4) { + int *base = s->codebook_input + i*entry_size; + + if(v1mode) { + //subsample + for(j = y2 = 0; y2 < entry_size; y2 += 2) { + for(x2 = 0; x2 < 4; x2 += 2, j++) { + plane = y2 < 4 ? 0 : 1 + (x2 >> 1); + shift = y2 < 4 ? 0 : 1; + x3 = shift ? 0 : x2; + y3 = shift ? 0 : y2; + base[j] = (pict->data[plane][((x+x3) >> shift) + ((y+y3) >> shift) * pict->linesize[plane]] + + pict->data[plane][((x+x3) >> shift) + 1 + ((y+y3) >> shift) * pict->linesize[plane]] + + pict->data[plane][((x+x3) >> shift) + (((y+y3) >> shift) + 1) * pict->linesize[plane]] + + pict->data[plane][((x+x3) >> shift) + 1 + (((y+y3) >> shift) + 1) * pict->linesize[plane]]) >> 2; + } + } + } else { + //copy + for(j = y2 = 0; y2 < MB_SIZE; y2 += 2) { + for(x2 = 0; x2 < MB_SIZE; x2 += 2) { + for(k = 0; k < entry_size; k++, j++) { + plane = k >= 4 ? k - 3 : 0; + + if(k >= 4) { + x3 = (x+x2) >> 1; + y3 = (y+y2) >> 1; + } else { + x3 = x + x2 + (k & 1); + y3 = y + y2 + (k >> 1); + } + + base[j] = pict->data[plane][x3 + y3*pict->linesize[plane]]; + } + } + } + } + } + } + + ff_init_elbg(s->codebook_input, entry_size, i, codebook, size, 1, s->codebook_closest, &s->randctx); + ff_do_elbg(s->codebook_input, entry_size, i, codebook, size, 1, s->codebook_closest, &s->randctx); + + //setup vq_pict, which contains a single MB + vq_pict.data[0] = vq_pict_buf; + vq_pict.linesize[0] = MB_SIZE; + vq_pict.data[1] = &vq_pict_buf[MB_AREA]; + vq_pict.data[2] = vq_pict.data[1] + (MB_AREA >> 2); + vq_pict.linesize[1] = vq_pict.linesize[2] = MB_SIZE >> 1; + + //copy indices + for(i = j = y = 0; y < h; y += MB_SIZE) { + for(x = 0; x < s->w; x += MB_SIZE, j++, i += v1mode ? 1 : 4) { + mb_info *mb = &s->mb[j]; + + //point sub_pict to current MB + get_sub_picture(s, x, y, pict, &sub_pict); + + if(v1mode) { + mb->v1_vector = s->codebook_closest[i]; + + //fill in vq_pict with V1 data + decode_v1_vector(s, &vq_pict, mb, info); + + mb->v1_error = compute_mb_distortion(s, &sub_pict, &vq_pict); + total_error += mb->v1_error; + } else { + for(k = 0; k < 4; k++) + mb->v4_vector[v4][k] = s->codebook_closest[i+k]; + + //fill in vq_pict with V4 data + decode_v4_vector(s, &vq_pict, mb->v4_vector[v4], info); + + mb->v4_error[v4] = compute_mb_distortion(s, &sub_pict, &vq_pict); + total_error += mb->v4_error[v4]; + } + } + } + + //av_log(s->avctx, AV_LOG_INFO, "mode %i size %i i %i error %li\n", v1mode, size, i, total_error); + + return 0; +} + +static void calculate_skip_errors(CinepakEncContext *s, int h, AVPicture *last_pict, AVPicture *pict, strip_info *info) +{ + int x, y, i; + AVPicture sub_last, sub_pict; + + for(i = y = 0; y < h; y += MB_SIZE) { + for(x = 0; x < s->w; x += MB_SIZE, i++) { + get_sub_picture(s, x, y, last_pict, &sub_last); + get_sub_picture(s, x, y, pict, &sub_pict); + + s->mb[i].skip_error = compute_mb_distortion(s, &sub_last, &sub_pict); + } + } +} + +static void write_strip_header(CinepakEncContext *s, int y, int h, int keyframe, unsigned char *buf, int strip_size) +{ + buf[0] = keyframe ? 0x11: 0x10; + AV_WB24(&buf[1], strip_size + STRIP_HEADER_SIZE); + AV_WB16(&buf[4], y); + AV_WB16(&buf[6], 0); + AV_WB16(&buf[8], h); + AV_WB16(&buf[10], s->w); +} + +static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture *last_pict, AVPicture *pict, AVPicture *scratch_pict, unsigned char *buf, int64_t *best_score) +{ + int64_t score = 0; + int best_size = 0, v1_size, v4_size, v4, mb_count = s->w * h / MB_AREA; + strip_info info; + CinepakMode best_mode; + int v4_codebooks[CODEBOOK_NUM][CODEBOOK_MAX*VECTOR_MAX]; + + if(!keyframe) + calculate_skip_errors(s, h, last_pict, pict, &info); + + //precompute V4 codebooks + for(v4_size = 1, v4 = 0; v4_size <= 256; v4_size <<= 2, v4++) { + info.v4_codebook = v4_codebooks[v4]; + quantize(s, h, pict, 0, v4_size, v4, &info); + } + + //try all powers of 4 for the size of the codebooks + //constraint the v4 codebook to be no bigger than the v1 codebook + for(v1_size = 1; v1_size <= 256; v1_size <<= 2) { + //compute V1 codebook + quantize(s, h, pict, 1, v1_size, -1, &info); + + for(v4_size = 0, v4 = -1; v4_size <= v1_size; v4_size = v4_size ? v4_size << 2 : v1_size >= 4 ? v1_size >> 2 : 1, v4++) { + //try all modes + for(CinepakMode mode = 0; mode < MODE_COUNT; mode++) { + //don't allow MODE_MC in inter frames + if(keyframe && mode == MODE_MC) + continue; + + //only allow V1-only mode if v4 codebook is empty + if(!v4_size && mode != MODE_V1_ONLY) + continue; + + info.v4_codebook = v4 >= 0 ? v4_codebooks[v4] : NULL; + score = calculate_mode_score(s, mode, h, v1_size, v4_size, v4, &info); + + //av_log(s->avctx, AV_LOG_INFO, "%3i %3i score = %li\n", v1_size, v4_size, score); + + if(best_size == 0 || score < *best_score) { + *best_score = score; + best_size = encode_mode(s, mode, h, v1_size, v4_size, v4, scratch_pict, &info, s->strip_buf + STRIP_HEADER_SIZE); + best_mode = mode; + + av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: %18li %i B\n", mode, v1_size, v4_size, score, best_size); + +#ifdef CINEPAKENC_DEBUG + //save MB encoding choices + memcpy(s->best_mb, s->mb, mb_count*sizeof(mb_info)); +#endif + + //memcpy(strip_temp + STRIP_HEADER_SIZE, strip_temp, best_size); + write_strip_header(s, y, h, keyframe, s->strip_buf, best_size); + } + } + } + } + +#ifdef CINEPAKENC_DEBUG + //gather stats. this will only work properly of MAX_STRIPS == 1 + if(best_mode == MODE_V1_ONLY) { + s->num_v1_mode++; + s->num_v1_encs += s->w*h/MB_AREA; + } else { + if(best_mode == MODE_V1_V4) + s->num_v4_mode++; + else + s->num_mc_mode++; + + int x; + for(x = 0; x < s->w*h/MB_AREA; x++) + if(s->best_mb[x].best_encoding == ENC_V1) + s->num_v1_encs++; + else if(s->best_mb[x].best_encoding == ENC_V4) + s->num_v4_encs++; + else + s->num_skips++; + } +#endif + + best_size += STRIP_HEADER_SIZE; + memcpy(buf, s->strip_buf, best_size); + + + return best_size; +} + +static int write_cvid_header(CinepakEncContext *s, unsigned char *buf, int num_strips, int data_size) +{ + buf[0] = 0; + AV_WB24(&buf[1], data_size + CVID_HEADER_SIZE); + AV_WB16(&buf[4], s->w); + AV_WB16(&buf[6], s->h); + AV_WB16(&buf[8], num_strips); + + return CVID_HEADER_SIZE; +} + +static int rd_frame(CinepakEncContext *s, AVFrame *frame, unsigned char *buf, int buf_size) +{ + int num_strips, strip, h, i, y, size, temp_size, best_size; + AVPicture last_pict, pict, scratch_pict; + int64_t best_score = 0, score, score_temp; + + //TODO: support encoding zero strips (meaning skip the whole frame) + for(num_strips = MIN_STRIPS; num_strips <= MAX_STRIPS && num_strips <= s->h / MB_SIZE; num_strips++) { + score = 0; + size = 0; + h = s->h / num_strips; + //make h into next multiple of 4 + h += 4 - (h & 3); + + for(strip = 0; strip < num_strips; strip++) { + y = strip*h; + + get_sub_picture(s, 0, y, (AVPicture*)frame, &pict); + get_sub_picture(s, 0, y, (AVPicture*)&s->last_frame, &last_pict); + get_sub_picture(s, 0, y, (AVPicture*)&s->scratch_frame, &scratch_pict); + + if((temp_size = rd_strip(s, y, FFMIN(h, s->h - y), frame->key_frame, &last_pict, &pict, &scratch_pict, s->frame_buf + CVID_HEADER_SIZE, &score_temp)) < 0) + return temp_size; + + score += score_temp; + size += temp_size; + } + + if(best_score == 0 || score < best_score) { + best_score = score; + best_size = size + write_cvid_header(s, s->frame_buf, num_strips, size); + av_log(s->avctx, AV_LOG_INFO, "best number of strips so far: %2i, %12li, %i B\n", num_strips, score, best_size); + + FFSWAP(AVFrame, s->best_frame, s->scratch_frame); + } + } + + memcpy(buf, s->frame_buf, best_size); + + return best_size; +} + +static int cinepak_encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data) +{ + CinepakEncContext *s = avctx->priv_data; + AVFrame *frame = data; + int ret; + + s->lambda = frame->quality ? frame->quality - 1 : 2 * FF_LAMBDA_SCALE; + + frame->key_frame = s->curframe == 0; + frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + + ret = rd_frame(s, frame, buf, buf_size); + + FFSWAP(AVFrame, s->last_frame, s->best_frame); + + if (++s->curframe >= s->keyint) + s->curframe = 0; + + return ret; +} + +static av_cold int cinepak_encode_end(AVCodecContext *avctx) +{ + CinepakEncContext *s = avctx->priv_data; + int x; + + av_free(s->codebook_input); + av_free(s->codebook_closest); + av_free(s->strip_buf); + av_free(s->frame_buf); + av_free(s->mb); +#ifdef CINEPAKENC_DEBUG + av_free(s->best_mb); +#endif + + for(x = 0; x < 3; x++) + av_free(s->pict_bufs[x]); + + av_log(avctx, AV_LOG_INFO, "strip coding stats: %i V1 mode, %i V4 mode, %i MC mode (%i V1 encs, %i V4 encs, %i skips)\n", + s->num_v1_mode, s->num_v4_mode, s->num_mc_mode, s->num_v1_encs, s->num_v4_encs, s->num_skips); + + return 0; +} + +AVCodec ff_cinepak_encoder = { + .name = "cinepak", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CINEPAK, + .priv_data_size = sizeof(CinepakEncContext), + .init = cinepak_encode_init, + .encode2 = cinepak_encode_frame, + .close = cinepak_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_RGB24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, + .long_name = NULL_IF_CONFIG_SMALL("Cinepak"), +}; From 7da9f4523159670d577a2808d4481e64008a8894 Mon Sep 17 00:00:00 2001 From: "addr-see-the-website@aetey.se" Date: Wed, 28 Jun 2017 00:27:12 +0200 Subject: [PATCH 0302/2557] cinepakenc: fixes and improvements version 2013-02-08 Rl - fixes/optimization in multistrip encoding and codebook size choice, quality/bitrate is now better than that of the binary proprietary encoder version 2013-02-12 Rl - separated codebook training sets, avoided the transfer of wasted bytes, which yields both better quality and smaller files - now using the correct colorspace (TODO: move conversion to libswscale) version 2013-02-14 Rl "Valentine's Day" version: - made strip division more robust - minimized bruteforcing the number of strips, (costs some R/D but speeds up compession a lot), the heuristic assumption is that score as a function of the number of strips has one wide minimum which moves slowly, of course not fully true - simplified codebook generation, the old code was meant for other optimizations than we actually do - optimized the codebook generation / error estimation for MODE_MC version 2013-04-28 Rl - bugfixed codebook optimization logic version 2014-01-20 Rl - made the encoder compatible with vintage decoders and added some yet unused code for possible future incremental codebook updates - fixed a small memory leak version 2014-01-21 Rl - believe it or not, now we get even smaller files, with better quality (which means I missed an optimization earlier :) Signed-off-by: Diego Biurrun --- libavcodec/cinepakenc.c | 834 ++++++++++++++++++++++++++++++---------- 1 file changed, 640 insertions(+), 194 deletions(-) diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index 2809295d461fb..1b63260e4d985 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -1,6 +1,9 @@ /* * Cinepak encoder (c) 2011 Tomas Härdin * http://titan.codemill.se/~tomhar/cinepakenc.patch + * + * Fixes and improvements, vintage decoders compatibility + * (c) 2013, 2014 Rl, Aetey Global Technologies AB Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -20,13 +23,27 @@ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * TODO: + * - optimize: color space conversion (move conversion to libswscale), ... + * - implement options to set the min/max number of strips? + * MAYBE: + * - "optimally" split the frame into several non-regular areas + * using a separate codebook pair for each area and approximating + * the area by several rectangular strips (generally not full width ones) + * (use quadtree splitting? a simple fixed-granularity grid?) */ +#include + #include "libavutil/common.h" +#include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "libavutil/lfg.h" #include "elbg.h" +#include "internal.h" + +#include "libavutil/avassert.h" #define CVID_HEADER_SIZE 10 #define STRIP_HEADER_SIZE 12 @@ -36,11 +53,20 @@ OTHER DEALINGS IN THE SOFTWARE. #define MB_AREA (MB_SIZE*MB_SIZE) #define VECTOR_MAX 6 //six or four entries per vector depending on format -#define CODEBOOK_MAX 256 -#define CODEBOOK_NUM 5 //five potential codebooks (1, 4, 16, 64, 256) for V1 and V4 +#define CODEBOOK_MAX 256 //size of a codebook -#define MAX_STRIPS 1 //Note: having fewer choices regarding the number of strip speeds up encoding (obviously) +//#define MAX_STRIPS 32 //Note: having fewer choices regarding the number of strips speeds up encoding (obviously) +#define MAX_STRIPS 3 // This seems to be max for vintage players! -- rl +// TODO: we might want to have a "vintage compatibilty" switch #define MIN_STRIPS 1 //Note: having more strips speeds up encoding the frame (this is less obvious) +// MAX_STRIPS limits the maximum quality you can reach +// when you want high quality on high resolutions, +// MIN_STRIPS limits the minimum efficiently encodable bit rate +// on low resolutions +// the numbers are only used for brute force optimization for the first frame, +// for the following frames they are adaptively readjusted +// NOTE the decoder in ffmpeg has its own arbitrary limitation on the number +// of strips, currently 32 typedef enum { MODE_V1_ONLY = 0, @@ -53,42 +79,51 @@ typedef enum { typedef enum { ENC_V1, ENC_V4, - ENC_SKIP + ENC_SKIP, + + ENC_UNCERTAIN } mb_encoding; typedef struct { int v1_vector; //index into v1 codebook int v1_error; //error when using V1 encoding - int v4_vector[CODEBOOK_NUM][4]; //indices into v4 codebooks - int v4_error[CODEBOOK_NUM]; //error when using V4 encodings + int v4_vector[4]; //indices into v4 codebook + int v4_error; //error when using V4 encoding int skip_error; //error when block is skipped (aka copied from last frame) mb_encoding best_encoding; //last result from calculate_mode_score() } mb_info; typedef struct { int v1_codebook[CODEBOOK_MAX*VECTOR_MAX]; - int *v4_codebook; + int v4_codebook[CODEBOOK_MAX*VECTOR_MAX]; + int v1_size; + int v4_size; + CinepakMode mode; } strip_info; typedef struct { AVCodecContext *avctx; - unsigned char *pict_bufs[3], *strip_buf, *frame_buf; - AVFrame last_frame; - AVFrame best_frame; - AVFrame scratch_frame; + unsigned char *pict_bufs[4], *strip_buf, *frame_buf; + AVFrame *last_frame; + AVFrame *best_frame; + AVFrame *scratch_frame; + AVFrame *input_frame; enum AVPixelFormat pix_fmt; int w, h; + int frame_buf_size; int curframe, keyint; AVLFG randctx; uint64_t lambda; int *codebook_input; int *codebook_closest; mb_info *mb; //MB RD state + int min_strips; //the current limit + int max_strips; //the current limit #ifdef CINEPAKENC_DEBUG mb_info *best_mb; //TODO: remove. only used for printing stats -#endif int num_v1_mode, num_v4_mode, num_mc_mode; int num_v1_encs, num_v4_encs, num_skips; +#endif } CinepakEncContext; static av_cold int cinepak_encode_init(AVCodecContext *avctx) @@ -102,20 +137,33 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (!(s->codebook_input = av_malloc(sizeof(int) * (avctx->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4) * (avctx->width * avctx->height) >> 2))) + if (!(s->last_frame = av_frame_alloc())) return AVERROR(ENOMEM); + if (!(s->best_frame = av_frame_alloc())) + goto enomem; + if (!(s->scratch_frame = av_frame_alloc())) + goto enomem; + if (avctx->pix_fmt == AV_PIX_FMT_RGB24) + if (!(s->input_frame = av_frame_alloc())) + goto enomem; + + if (!(s->codebook_input = av_malloc(sizeof(int) * (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4) * (avctx->width * avctx->height) >> 2))) + goto enomem; if (!(s->codebook_closest = av_malloc(sizeof(int) * (avctx->width * avctx->height) >> 2))) goto enomem; - for(x = 0; x < 3; x++) - if(!(s->pict_bufs[x] = av_malloc((avctx->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4) * (avctx->width * avctx->height) >> 2))) + for(x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) + if(!(s->pict_bufs[x] = av_malloc((avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4) * (avctx->width * avctx->height) >> 2))) goto enomem; mb_count = avctx->width * avctx->height / MB_AREA; - //the largest possible chunk is 0x31 with all MBs encoded in V4 mode, which is 34 bits per MB - strip_buf_size = STRIP_HEADER_SIZE + 3 * CHUNK_HEADER_SIZE + 2 * VECTOR_MAX * CODEBOOK_MAX + 4 * (mb_count + (mb_count + 15) / 16); + //the largest possible chunk is 0x31 with all MBs encoded in V4 mode + //and full codebooks being replaced in INTER mode, + // which is 34 bits per MB + //and 2*256 extra flag bits per strip + strip_buf_size = STRIP_HEADER_SIZE + 3 * CHUNK_HEADER_SIZE + 2 * VECTOR_MAX * CODEBOOK_MAX + 4 * (mb_count + (mb_count + 15) / 16) + (2 * CODEBOOK_MAX)/8; frame_buf_size = CVID_HEADER_SIZE + MAX_STRIPS * strip_buf_size; @@ -137,113 +185,221 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) s->avctx = avctx; s->w = avctx->width; s->h = avctx->height; + s->frame_buf_size = frame_buf_size; s->curframe = 0; s->keyint = avctx->keyint_min; s->pix_fmt = avctx->pix_fmt; //set up AVFrames - s->last_frame.data[0] = s->pict_bufs[0]; - s->last_frame.linesize[0] = s->w; - s->best_frame.data[0] = s->pict_bufs[1]; - s->best_frame.linesize[0] = s->w; - s->scratch_frame.data[0] = s->pict_bufs[2]; - s->scratch_frame.linesize[0] = s->w; - - if(s->pix_fmt == AV_PIX_FMT_YUV420P) { - s->last_frame.data[1] = s->last_frame.data[0] + s->w * s->h; - s->last_frame.data[2] = s->last_frame.data[1] + ((s->w * s->h) >> 2); - s->last_frame.linesize[1] = s->last_frame.linesize[2] = s->w >> 1; - - s->best_frame.data[1] = s->best_frame.data[0] + s->w * s->h; - s->best_frame.data[2] = s->best_frame.data[1] + ((s->w * s->h) >> 2); - s->best_frame.linesize[1] = s->best_frame.linesize[2] = s->w >> 1; - - s->scratch_frame.data[1] = s->scratch_frame.data[0] + s->w * s->h; - s->scratch_frame.data[2] = s->scratch_frame.data[1] + ((s->w * s->h) >> 2); - s->scratch_frame.linesize[1] = s->scratch_frame.linesize[2] = s->w >> 1; + s->last_frame->data[0] = s->pict_bufs[0]; + s->last_frame->linesize[0] = s->w; + s->best_frame->data[0] = s->pict_bufs[1]; + s->best_frame->linesize[0] = s->w; + s->scratch_frame->data[0] = s->pict_bufs[2]; + s->scratch_frame->linesize[0] = s->w; + + if (s->pix_fmt == AV_PIX_FMT_RGB24) { + s->last_frame->data[1] = s->last_frame->data[0] + s->w * s->h; + s->last_frame->data[2] = s->last_frame->data[1] + ((s->w * s->h) >> 2); + s->last_frame->linesize[1] = s->last_frame->linesize[2] = s->w >> 1; + + s->best_frame->data[1] = s->best_frame->data[0] + s->w * s->h; + s->best_frame->data[2] = s->best_frame->data[1] + ((s->w * s->h) >> 2); + s->best_frame->linesize[1] = s->best_frame->linesize[2] = s->w >> 1; + + s->scratch_frame->data[1] = s->scratch_frame->data[0] + s->w * s->h; + s->scratch_frame->data[2] = s->scratch_frame->data[1] + ((s->w * s->h) >> 2); + s->scratch_frame->linesize[1] = s->scratch_frame->linesize[2] = s->w >> 1; + + s->input_frame->data[0] = s->pict_bufs[3]; + s->input_frame->linesize[0] = s->w; + s->input_frame->data[1] = s->input_frame->data[0] + s->w * s->h; + s->input_frame->data[2] = s->input_frame->data[1] + ((s->w * s->h) >> 2); + s->input_frame->linesize[1] = s->input_frame->linesize[2] = s->w >> 1; } + s->min_strips = MIN_STRIPS; + s->max_strips = MAX_STRIPS; + +#ifdef CINEPAKENC_DEBUG s->num_v1_mode = s->num_v4_mode = s->num_mc_mode = s->num_v1_encs = s->num_v4_encs = s->num_skips = 0; +#endif return 0; enomem: - av_free(s->codebook_input); - av_free(s->codebook_closest); - av_free(s->strip_buf); - av_free(s->frame_buf); - av_free(s->mb); + av_frame_free(&s->last_frame); + av_frame_free(&s->best_frame); + av_frame_free(&s->scratch_frame); + if (avctx->pix_fmt == AV_PIX_FMT_RGB24) + av_frame_free(&s->input_frame); + av_freep(&s->codebook_input); + av_freep(&s->codebook_closest); + av_freep(&s->strip_buf); + av_freep(&s->frame_buf); + av_freep(&s->mb); #ifdef CINEPAKENC_DEBUG - av_free(s->best_mb); + av_freep(&s->best_mb); #endif - for(x = 0; x < 3; x++) - av_free(s->pict_bufs[x]); + for(x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) + av_freep(&s->pict_bufs[x]); return AVERROR(ENOMEM); } -static int64_t calculate_mode_score(CinepakEncContext *s, CinepakMode mode, int h, int v1_size, int v4_size, int v4, strip_info *info) +static int64_t calculate_mode_score(CinepakEncContext *s, int h, strip_info *info, int report, int *training_set_v1_shrunk, int *training_set_v4_shrunk +#ifdef CINEPAK_REPORT_SERR +, int64_t *serr +#endif +) { //score = FF_LAMBDA_SCALE * error + lambda * bits int x; - int entry_size = s->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4; + int entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; int mb_count = s->w * h / MB_AREA; mb_info *mb; int64_t score1, score2, score3; - int64_t ret = s->lambda * ((v1_size ? CHUNK_HEADER_SIZE + v1_size * entry_size : 0) + - (v4_size ? CHUNK_HEADER_SIZE + v4_size * entry_size : 0) + + int64_t ret = s->lambda * ((info->v1_size ? CHUNK_HEADER_SIZE + info->v1_size * entry_size : 0) + + (info->v4_size ? CHUNK_HEADER_SIZE + info->v4_size * entry_size : 0) + CHUNK_HEADER_SIZE) << 3; - //av_log(s->avctx, AV_LOG_INFO, "sizes %3i %3i -> %9li score mb_count %i", v1_size, v4_size, ret, mb_count); + //av_log(s->avctx, AV_LOG_INFO, "sizes %3i %3i -> %9lli score mb_count %i", info->v1_size, info->v4_size, (long long int)ret, mb_count); + +#ifdef CINEPAK_REPORT_SERR + *serr = 0; +#endif - switch(mode) { + switch(info->mode) { case MODE_V1_ONLY: //one byte per MB ret += s->lambda * 8 * mb_count; +// while calculating we assume all blocks are ENC_V1 for(x = 0; x < mb_count; x++) { mb = &s->mb[x]; ret += FF_LAMBDA_SCALE * mb->v1_error; +#ifdef CINEPAK_REPORT_SERR + *serr += mb->v1_error; +#endif +// this function is never called for report in MODE_V1_ONLY +// if(!report) mb->best_encoding = ENC_V1; } break; case MODE_V1_V4: //9 or 33 bits per MB - for(x = 0; x < mb_count; x++) { - mb = &s->mb[x]; - score1 = s->lambda * 9 + FF_LAMBDA_SCALE * mb->v1_error; - score2 = s->lambda * 33 + FF_LAMBDA_SCALE * mb->v4_error[v4]; - - if(score1 <= score2) { + if(report) { +// no moves between the corresponding training sets are allowed + *training_set_v1_shrunk = *training_set_v4_shrunk = 0; + for(x = 0; x < mb_count; x++) { + int mberr; + mb = &s->mb[x]; + if(mb->best_encoding == ENC_V1) + score1 = s->lambda * 9 + FF_LAMBDA_SCALE * (mberr=mb->v1_error); + else + score1 = s->lambda * 33 + FF_LAMBDA_SCALE * (mberr=mb->v4_error); ret += score1; - mb->best_encoding = ENC_V1; - } else { - ret += score2; - mb->best_encoding = ENC_V4; +#ifdef CINEPAK_REPORT_SERR + *serr += mberr; +#endif + } + } else { // find best mode per block + for(x = 0; x < mb_count; x++) { + mb = &s->mb[x]; + score1 = s->lambda * 9 + FF_LAMBDA_SCALE * mb->v1_error; + score2 = s->lambda * 33 + FF_LAMBDA_SCALE * mb->v4_error; + + if(score1 <= score2) { + ret += score1; +#ifdef CINEPAK_REPORT_SERR + *serr += mb->v1_error; +#endif + mb->best_encoding = ENC_V1; + } else { + ret += score2; +#ifdef CINEPAK_REPORT_SERR + *serr += mb->v4_error; +#endif + mb->best_encoding = ENC_V4; + } } } break; case MODE_MC: //1, 10 or 34 bits per MB - for(x = 0; x < mb_count; x++) { - mb = &s->mb[x]; - score1 = s->lambda * 1 + FF_LAMBDA_SCALE * mb->skip_error; - score2 = s->lambda * 10 + FF_LAMBDA_SCALE * mb->v1_error; - score3 = s->lambda * 34 + FF_LAMBDA_SCALE * mb->v4_error[v4]; - - - if(score1 <= score2 && score1 <= score3) { - ret += score1; - mb->best_encoding = ENC_SKIP; - } else if(score2 <= score1 && score2 <= score3) { - ret += score2; - mb->best_encoding = ENC_V1; - } else { - ret += score3; - mb->best_encoding = ENC_V4; + if(report) { + int v1_shrunk = 0, v4_shrunk = 0; + for(x = 0; x < mb_count; x++) { + mb = &s->mb[x]; +// it is OK to move blocks to ENC_SKIP here +// but not to any codebook encoding! + score1 = s->lambda * 1 + FF_LAMBDA_SCALE * mb->skip_error; + if(mb->best_encoding == ENC_SKIP) { + ret += score1; +#ifdef CINEPAK_REPORT_SERR + *serr += mb->skip_error; +#endif + } else if(mb->best_encoding == ENC_V1) { + if((score2=s->lambda * 10 + FF_LAMBDA_SCALE * mb->v1_error) >= score1) { + mb->best_encoding = ENC_SKIP; + ++v1_shrunk; + ret += score1; +#ifdef CINEPAK_REPORT_SERR + *serr += mb->skip_error; +#endif + } else { + ret += score2; +#ifdef CINEPAK_REPORT_SERR + *serr += mb->v1_error; +#endif + } + } else { + if((score3=s->lambda * 34 + FF_LAMBDA_SCALE * mb->v4_error) >= score1) { + mb->best_encoding = ENC_SKIP; + ++v4_shrunk; + ret += score1; +#ifdef CINEPAK_REPORT_SERR + *serr += mb->skip_error; +#endif + } else { + ret += score3; +#ifdef CINEPAK_REPORT_SERR + *serr += mb->v4_error; +#endif + } + } + } + *training_set_v1_shrunk = v1_shrunk; + *training_set_v4_shrunk = v4_shrunk; + } else { // find best mode per block + for(x = 0; x < mb_count; x++) { + mb = &s->mb[x]; + score1 = s->lambda * 1 + FF_LAMBDA_SCALE * mb->skip_error; + score2 = s->lambda * 10 + FF_LAMBDA_SCALE * mb->v1_error; + score3 = s->lambda * 34 + FF_LAMBDA_SCALE * mb->v4_error; + + if(score1 <= score2 && score1 <= score3) { + ret += score1; +#ifdef CINEPAK_REPORT_SERR + *serr += mb->skip_error; +#endif + mb->best_encoding = ENC_SKIP; + } else if(score2 <= score3) { + ret += score2; +#ifdef CINEPAK_REPORT_SERR + *serr += mb->v1_error; +#endif + mb->best_encoding = ENC_V1; + } else { + ret += score3; +#ifdef CINEPAK_REPORT_SERR + *serr += mb->v4_error; +#endif + mb->best_encoding = ENC_V4; + } } } @@ -262,13 +418,45 @@ static int write_chunk_header(unsigned char *buf, int chunk_type, int chunk_size static int encode_codebook(CinepakEncContext *s, int *codebook, int size, int chunk_type_yuv, int chunk_type_gray, unsigned char *buf) { - int x, y, ret, entry_size = s->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4; - - ret = write_chunk_header(buf, s->pix_fmt == AV_PIX_FMT_YUV420P ? chunk_type_yuv : chunk_type_gray, entry_size * size); - - for(x = 0; x < size; x++) - for(y = 0; y < entry_size; y++) - buf[ret++] = codebook[y + x*entry_size] ^ (y >= 4 ? 0x80 : 0); + int x, y, ret, entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; + int incremental_codebook_replacement_mode = 0; // hardcoded here, + // the compiler should notice that this is a constant -- rl + + ret = write_chunk_header(buf, + s->pix_fmt == AV_PIX_FMT_RGB24 ? + chunk_type_yuv+(incremental_codebook_replacement_mode?1:0) : + chunk_type_gray+(incremental_codebook_replacement_mode?1:0), + entry_size * size + + (incremental_codebook_replacement_mode?(size+31)/32*4:0) ); + +// we do codebook encoding according to the "intra" mode +// but we keep the "dead" code for reference in case we will want +// to use incremental codebook updates (which actually would give us +// "kind of" motion compensation, especially in 1 strip/frame case) -- rl +// (of course, the code will be not useful as-is) + if(incremental_codebook_replacement_mode) { + int flags = 0; + int flagsind; + for(x = 0; x < size; x++) { + if(flags == 0) { + flagsind = ret; + ret += 4; + flags = 0x80000000; + } else + flags = ((flags>>1) | 0x80000000); + for(y = 0; y < entry_size; y++) + buf[ret++] = codebook[y + x*entry_size] ^ (y >= 4 ? 0x80 : 0); + if((flags&0xffffffff) == 0xffffffff) { + AV_WB32(&buf[flagsind], flags); + flags = 0; + } + } + if(flags) + AV_WB32(&buf[flagsind], flags); + } else + for(x = 0; x < size; x++) + for(y = 0; y < entry_size; y++) + buf[ret++] = codebook[y + x*entry_size] ^ (y >= 4 ? 0x80 : 0); return ret; } @@ -279,7 +467,7 @@ static void get_sub_picture(CinepakEncContext *s, int x, int y, AVPicture *in, A out->data[0] = in->data[0] + x + y * in->linesize[0]; out->linesize[0] = in->linesize[0]; - if(s->pix_fmt == AV_PIX_FMT_YUV420P) { + if(s->pix_fmt == AV_PIX_FMT_RGB24) { out->data[1] = in->data[1] + (x >> 1) + (y >> 1) * in->linesize[1]; out->linesize[1] = in->linesize[1]; @@ -289,47 +477,47 @@ static void get_sub_picture(CinepakEncContext *s, int x, int y, AVPicture *in, A } //decodes the V1 vector in mb into the 4x4 MB pointed to by sub_pict -static void decode_v1_vector(CinepakEncContext *s, AVPicture *sub_pict, mb_info *mb, strip_info *info) +static void decode_v1_vector(CinepakEncContext *s, AVPicture *sub_pict, int v1_vector, strip_info *info) { - int entry_size = s->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4; + int entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; sub_pict->data[0][0] = sub_pict->data[0][1] = sub_pict->data[0][ sub_pict->linesize[0]] = - sub_pict->data[0][1+ sub_pict->linesize[0]] = info->v1_codebook[mb->v1_vector*entry_size]; + sub_pict->data[0][1+ sub_pict->linesize[0]] = info->v1_codebook[v1_vector*entry_size]; sub_pict->data[0][2] = sub_pict->data[0][3] = sub_pict->data[0][2+ sub_pict->linesize[0]] = - sub_pict->data[0][3+ sub_pict->linesize[0]] = info->v1_codebook[mb->v1_vector*entry_size+1]; + sub_pict->data[0][3+ sub_pict->linesize[0]] = info->v1_codebook[v1_vector*entry_size+1]; sub_pict->data[0][2*sub_pict->linesize[0]] = sub_pict->data[0][1+2*sub_pict->linesize[0]] = sub_pict->data[0][ 3*sub_pict->linesize[0]] = - sub_pict->data[0][1+3*sub_pict->linesize[0]] = info->v1_codebook[mb->v1_vector*entry_size+2]; + sub_pict->data[0][1+3*sub_pict->linesize[0]] = info->v1_codebook[v1_vector*entry_size+2]; sub_pict->data[0][2+2*sub_pict->linesize[0]] = sub_pict->data[0][3+2*sub_pict->linesize[0]] = sub_pict->data[0][2+3*sub_pict->linesize[0]] = - sub_pict->data[0][3+3*sub_pict->linesize[0]] = info->v1_codebook[mb->v1_vector*entry_size+3]; + sub_pict->data[0][3+3*sub_pict->linesize[0]] = info->v1_codebook[v1_vector*entry_size+3]; - if(s->pix_fmt == AV_PIX_FMT_YUV420P) { + if(s->pix_fmt == AV_PIX_FMT_RGB24) { sub_pict->data[1][0] = sub_pict->data[1][1] = sub_pict->data[1][ sub_pict->linesize[1]] = - sub_pict->data[1][1+ sub_pict->linesize[1]] = info->v1_codebook[mb->v1_vector*entry_size+4]; + sub_pict->data[1][1+ sub_pict->linesize[1]] = info->v1_codebook[v1_vector*entry_size+4]; sub_pict->data[2][0] = sub_pict->data[2][1] = sub_pict->data[2][ sub_pict->linesize[2]] = - sub_pict->data[2][1+ sub_pict->linesize[2]] = info->v1_codebook[mb->v1_vector*entry_size+5]; + sub_pict->data[2][1+ sub_pict->linesize[2]] = info->v1_codebook[v1_vector*entry_size+5]; } } //decodes the V4 vectors in mb into the 4x4 MB pointed to by sub_pict static void decode_v4_vector(CinepakEncContext *s, AVPicture *sub_pict, int *v4_vector, strip_info *info) { - int i, x, y, entry_size = s->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4; + int i, x, y, entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; for(i = y = 0; y < 4; y += 2) { for(x = 0; x < 4; x += 2, i++) { @@ -338,7 +526,7 @@ static void decode_v4_vector(CinepakEncContext *s, AVPicture *sub_pict, int *v4_ sub_pict->data[0][x + (y+1)*sub_pict->linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+2]; sub_pict->data[0][x+1 + (y+1)*sub_pict->linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+3]; - if(s->pix_fmt == AV_PIX_FMT_YUV420P) { + if(s->pix_fmt == AV_PIX_FMT_RGB24) { sub_pict->data[1][(x>>1) + (y>>1)*sub_pict->linesize[1]] = info->v4_codebook[v4_vector[i]*entry_size+4]; sub_pict->data[2][(x>>1) + (y>>1)*sub_pict->linesize[2]] = info->v4_codebook[v4_vector[i]*entry_size+5]; } @@ -346,39 +534,62 @@ static void decode_v4_vector(CinepakEncContext *s, AVPicture *sub_pict, int *v4_ } } -static int encode_mode(CinepakEncContext *s, CinepakMode mode, int h, int v1_size, int v4_size, int v4, AVPicture *scratch_pict, strip_info *info, unsigned char *buf) +static void copy_mb(CinepakEncContext *s, AVPicture *a, AVPicture *b) +{ + int y, p; + + for(y = 0; y < MB_SIZE; y++) { + memcpy(a->data[0]+y*a->linesize[0], b->data[0]+y*b->linesize[0], + MB_SIZE); + } + + if(s->pix_fmt == AV_PIX_FMT_RGB24) { + for(p = 1; p <= 2; p++) { + for(y = 0; y < MB_SIZE/2; y++) { + memcpy(a->data[p] + y*a->linesize[p], + b->data[p] + y*b->linesize[p], + MB_SIZE/2); + } + } + } +} + +static int encode_mode(CinepakEncContext *s, int h, AVPicture *scratch_pict, AVPicture *last_pict, strip_info *info, unsigned char *buf) { int x, y, z, flags, bits, temp_size, header_ofs, ret = 0, mb_count = s->w * h / MB_AREA; int needs_extra_bit, should_write_temp; unsigned char temp[64]; //32/2 = 16 V4 blocks at 4 B each -> 64 B mb_info *mb; - AVPicture sub_scratch; + AVPicture sub_scratch, sub_last; //encode codebooks - if(v1_size) - ret += encode_codebook(s, info->v1_codebook, v1_size, 0x22, 0x26, buf + ret); +////// MacOS vintage decoder compatibility dictates the presence of +////// the codebook chunk even when the codebook is empty - pretty dumb... +////// and also the certain order of the codebook chunks -- rl +// if(info->v4_size) + ret += encode_codebook(s, info->v4_codebook, info->v4_size, 0x20, 0x24, buf + ret); - if(v4_size) - ret += encode_codebook(s, info->v4_codebook, v4_size, 0x20, 0x24, buf + ret); +// if(info->v1_size) + ret += encode_codebook(s, info->v1_codebook, info->v1_size, 0x22, 0x26, buf + ret); //update scratch picture for(z = y = 0; y < h; y += MB_SIZE) { for(x = 0; x < s->w; x += MB_SIZE, z++) { mb = &s->mb[z]; - if(mode == MODE_MC && mb->best_encoding == ENC_SKIP) - continue; - get_sub_picture(s, x, y, scratch_pict, &sub_scratch); - if(mode == MODE_V1_ONLY || mb->best_encoding == ENC_V1) - decode_v1_vector(s, &sub_scratch, mb, info); - else if(mode != MODE_V1_ONLY && mb->best_encoding == ENC_V4) - decode_v4_vector(s, &sub_scratch, mb->v4_vector[v4], info); + if(info->mode == MODE_MC && mb->best_encoding == ENC_SKIP) { + get_sub_picture(s, x, y, last_pict, &sub_last); + copy_mb(s, &sub_scratch, &sub_last); + } else if(info->mode == MODE_V1_ONLY || mb->best_encoding == ENC_V1) + decode_v1_vector(s, &sub_scratch, mb->v1_vector, info); + else + decode_v4_vector(s, &sub_scratch, mb->v4_vector, info); } } - switch(mode) { + switch(info->mode) { case MODE_V1_ONLY: //av_log(s->avctx, AV_LOG_INFO, "mb_count = %i\n", mb_count); ret += write_chunk_header(buf + ret, 0x32, mb_count); @@ -408,7 +619,7 @@ static int encode_mode(CinepakEncContext *s, CinepakMode mode, int h, int v1_siz buf[ret++] = mb->v1_vector; else for(z = 0; z < 4; z++) - buf[ret++] = mb->v4_vector[v4][z]; + buf[ret++] = mb->v4_vector[z]; } } @@ -456,7 +667,7 @@ static int encode_mode(CinepakEncContext *s, CinepakMode mode, int h, int v1_siz temp[temp_size++] = mb->v1_vector; else if(mb->best_encoding == ENC_V4) for(z = 0; z < 4; z++) - temp[temp_size++] = mb->v4_vector[v4][z]; + temp[temp_size++] = mb->v4_vector[z]; if(should_write_temp) { memcpy(&buf[ret], temp, temp_size); @@ -492,7 +703,7 @@ static int compute_mb_distortion(CinepakEncContext *s, AVPicture *a, AVPicture * } } - if(s->pix_fmt == AV_PIX_FMT_YUV420P) { + if(s->pix_fmt == AV_PIX_FMT_RGB24) { for(p = 1; p <= 2; p++) { for(y = 0; y < MB_SIZE/2; y++) { for(x = 0; x < MB_SIZE/2; x++) { @@ -506,19 +717,30 @@ static int compute_mb_distortion(CinepakEncContext *s, AVPicture *a, AVPicture * return ret; } -static int quantize(CinepakEncContext *s, int h, AVPicture *pict, int v1mode, int size, int v4, strip_info *info) +// return the possibly adjusted size of the codebook +#define CERTAIN(x) ((x)!=ENC_UNCERTAIN) +static int quantize(CinepakEncContext *s, int h, AVPicture *pict, + int v1mode, strip_info *info, + mb_encoding encoding) { - int x, y, i, j, k, x2, y2, x3, y3, plane, shift; - int entry_size = s->pix_fmt == AV_PIX_FMT_YUV420P ? 6 : 4; + int x, y, i, j, k, x2, y2, x3, y3, plane, shift, mbn; + int entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; int *codebook = v1mode ? info->v1_codebook : info->v4_codebook; + int size = v1mode ? info->v1_size : info->v4_size; int64_t total_error = 0; uint8_t vq_pict_buf[(MB_AREA*3)/2]; AVPicture sub_pict, vq_pict; - for(i = y = 0; y < h; y += MB_SIZE) { - for(x = 0; x < s->w; x += MB_SIZE, i += v1mode ? 1 : 4) { - int *base = s->codebook_input + i*entry_size; + for(mbn = i = y = 0; y < h; y += MB_SIZE) { + for(x = 0; x < s->w; x += MB_SIZE, ++mbn) { + int *base; + if(CERTAIN(encoding)) { +// use for the training only the blocks known to be to be encoded [sic:-] + if(s->mb[mbn].best_encoding != encoding) continue; + } + + base = s->codebook_input + i*entry_size; if(v1mode) { //subsample for(j = y2 = 0; y2 < entry_size; y2 += 2) { @@ -553,8 +775,19 @@ static int quantize(CinepakEncContext *s, int h, AVPicture *pict, int v1mode, in } } } + i += v1mode ? 1 : 4; } } +// if(i < mbn*(v1mode ? 1 : 4)) { +// av_log(s->avctx, AV_LOG_INFO, "reducing training set for %s from %i to %i (encoding %i)\n", v1mode?"v1":"v4", mbn*(v1mode ? 1 : 4), i, encoding); +// } + + if(i == 0) // empty training set, nothing to do + return 0; + if(i < size) { + //av_log(s->avctx, (CERTAIN(encoding) ? AV_LOG_ERROR : AV_LOG_INFO), "WOULD WASTE: %s cbsize %i bigger than training set size %i (encoding %i)\n", v1mode?"v1":"v4", size, i, encoding); + size = i; + } ff_init_elbg(s->codebook_input, entry_size, i, codebook, size, 1, s->codebook_closest, &s->randctx); ff_do_elbg(s->codebook_input, entry_size, i, codebook, size, 1, s->codebook_closest, &s->randctx); @@ -568,8 +801,11 @@ static int quantize(CinepakEncContext *s, int h, AVPicture *pict, int v1mode, in //copy indices for(i = j = y = 0; y < h; y += MB_SIZE) { - for(x = 0; x < s->w; x += MB_SIZE, j++, i += v1mode ? 1 : 4) { + for(x = 0; x < s->w; x += MB_SIZE, j++) { mb_info *mb = &s->mb[j]; +// skip uninteresting blocks if we know their preferred encoding + if(CERTAIN(encoding) && mb->best_encoding != encoding) + continue; //point sub_pict to current MB get_sub_picture(s, x, y, pict, &sub_pict); @@ -578,26 +814,29 @@ static int quantize(CinepakEncContext *s, int h, AVPicture *pict, int v1mode, in mb->v1_vector = s->codebook_closest[i]; //fill in vq_pict with V1 data - decode_v1_vector(s, &vq_pict, mb, info); + decode_v1_vector(s, &vq_pict, mb->v1_vector, info); mb->v1_error = compute_mb_distortion(s, &sub_pict, &vq_pict); total_error += mb->v1_error; } else { for(k = 0; k < 4; k++) - mb->v4_vector[v4][k] = s->codebook_closest[i+k]; + mb->v4_vector[k] = s->codebook_closest[i+k]; //fill in vq_pict with V4 data - decode_v4_vector(s, &vq_pict, mb->v4_vector[v4], info); + decode_v4_vector(s, &vq_pict, mb->v4_vector, info); - mb->v4_error[v4] = compute_mb_distortion(s, &sub_pict, &vq_pict); - total_error += mb->v4_error[v4]; + mb->v4_error = compute_mb_distortion(s, &sub_pict, &vq_pict); + total_error += mb->v4_error; } + i += v1mode ? 1 : 4; } } +// check that we did it right in the beginning of the function + av_assert0(i >= size); // training set is no smaller than the codebook - //av_log(s->avctx, AV_LOG_INFO, "mode %i size %i i %i error %li\n", v1mode, size, i, total_error); + //av_log(s->avctx, AV_LOG_INFO, "isv1 %i size= %i i= %i error %lli\n", v1mode, size, i, (long long int)total_error); - return 0; + return size; } static void calculate_skip_errors(CinepakEncContext *s, int h, AVPicture *last_pict, AVPicture *pict, strip_info *info) @@ -617,59 +856,151 @@ static void calculate_skip_errors(CinepakEncContext *s, int h, AVPicture *last_p static void write_strip_header(CinepakEncContext *s, int y, int h, int keyframe, unsigned char *buf, int strip_size) { - buf[0] = keyframe ? 0x11: 0x10; +// actually we are exclusively using intra strip coding (how much can we win +// otherwise? how to choose which part of a codebook to update?), +// keyframes are different only because we disallow ENC_SKIP on them -- rl +// (besides, the logic here used to be inverted: ) +// buf[0] = keyframe ? 0x11: 0x10; + buf[0] = keyframe ? 0x10: 0x11; AV_WB24(&buf[1], strip_size + STRIP_HEADER_SIZE); - AV_WB16(&buf[4], y); +// AV_WB16(&buf[4], y); /* using absolute y values works -- rl */ + AV_WB16(&buf[4], 0); /* using relative values works as well -- rl */ AV_WB16(&buf[6], 0); - AV_WB16(&buf[8], h); +// AV_WB16(&buf[8], y+h); /* using absolute y values works -- rl */ + AV_WB16(&buf[8], h); /* using relative values works as well -- rl */ AV_WB16(&buf[10], s->w); + //av_log(s->avctx, AV_LOG_INFO, "write_strip_header() %x keyframe=%d\n", buf[0], keyframe); } -static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture *last_pict, AVPicture *pict, AVPicture *scratch_pict, unsigned char *buf, int64_t *best_score) +static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture *last_pict, AVPicture *pict, AVPicture *scratch_pict, unsigned char *buf, int64_t *best_score +#ifdef CINEPAK_REPORT_SERR +, int64_t *best_serr +#endif +) { int64_t score = 0; - int best_size = 0, v1_size, v4_size, v4, mb_count = s->w * h / MB_AREA; +#ifdef CINEPAK_REPORT_SERR + int64_t serr; +#endif + int best_size = 0; strip_info info; - CinepakMode best_mode; - int v4_codebooks[CODEBOOK_NUM][CODEBOOK_MAX*VECTOR_MAX]; +// for codebook optimization: + int v1enough, v1_size, v4enough, v4_size; + int new_v1_size, new_v4_size; + int v1shrunk, v4shrunk; if(!keyframe) calculate_skip_errors(s, h, last_pict, pict, &info); - //precompute V4 codebooks - for(v4_size = 1, v4 = 0; v4_size <= 256; v4_size <<= 2, v4++) { - info.v4_codebook = v4_codebooks[v4]; - quantize(s, h, pict, 0, v4_size, v4, &info); - } - - //try all powers of 4 for the size of the codebooks - //constraint the v4 codebook to be no bigger than the v1 codebook - for(v1_size = 1; v1_size <= 256; v1_size <<= 2) { - //compute V1 codebook - quantize(s, h, pict, 1, v1_size, -1, &info); - - for(v4_size = 0, v4 = -1; v4_size <= v1_size; v4_size = v4_size ? v4_size << 2 : v1_size >= 4 ? v1_size >> 2 : 1, v4++) { + //try some powers of 4 for the size of the codebooks + //constraint the v4 codebook to be no bigger than v1 one, + //(and no less than v1_size/4) + //thus making v1 preferable and possibly losing small details? should be ok +#define SMALLEST_CODEBOOK 1 + for(v1enough = 0, v1_size = SMALLEST_CODEBOOK; v1_size <= CODEBOOK_MAX && !v1enough; v1_size <<= 2) { + for(v4enough = 0, v4_size = 0; v4_size <= v1_size && !v4enough; v4_size = v4_size ? v4_size << 2 : v1_size >= SMALLEST_CODEBOOK << 2 ? v1_size >> 2 : SMALLEST_CODEBOOK) { //try all modes for(CinepakMode mode = 0; mode < MODE_COUNT; mode++) { - //don't allow MODE_MC in inter frames + //don't allow MODE_MC in intra frames if(keyframe && mode == MODE_MC) continue; - //only allow V1-only mode if v4 codebook is empty - if(!v4_size && mode != MODE_V1_ONLY) - continue; + if(mode == MODE_V1_ONLY) { + info.v1_size = v1_size; +// the size may shrink even before optimizations if the input is short: + info.v1_size = quantize(s, h, pict, 1, &info, ENC_UNCERTAIN); + if(info.v1_size < v1_size) +// too few eligible blocks, no sense in trying bigger sizes + v1enough = 1; + + info.v4_size = 0; + } else { // mode != MODE_V1_ONLY + // if v4 codebook is empty then only allow V1-only mode + if(!v4_size) + continue; + + if(mode == MODE_V1_V4) { + info.v4_size = v4_size; + info.v4_size = quantize(s, h, pict, 0, &info, ENC_UNCERTAIN); + if(info.v4_size < v4_size) +// too few eligible blocks, no sense in trying bigger sizes + v4enough = 1; + } + } - info.v4_codebook = v4 >= 0 ? v4_codebooks[v4] : NULL; - score = calculate_mode_score(s, mode, h, v1_size, v4_size, v4, &info); + info.mode = mode; +// choose the best encoding per block, based on current experience + score = calculate_mode_score(s, h, &info, 0, + &v1shrunk, &v4shrunk +#ifdef CINEPAK_REPORT_SERR +, &serr +#endif +); + + if(mode != MODE_V1_ONLY){ +// recompute the codebooks, omitting the extra blocks +// we assume we _may_ come here with more blocks to encode than before + info.v1_size = v1_size; + new_v1_size = quantize(s, h, pict, 1, &info, ENC_V1); + if(new_v1_size < info.v1_size){ + //av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: cut v1 codebook to %i entries\n", mode, v1_size, v4_size, new_v1_size); + info.v1_size = new_v1_size; + } +// we assume we _may_ come here with more blocks to encode than before + info.v4_size = v4_size; + new_v4_size = quantize(s, h, pict, 0, &info, ENC_V4); + if(new_v4_size < info.v4_size) { + //av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: cut v4 codebook to %i entries at first iteration\n", mode, v1_size, v4_size, new_v4_size); + info.v4_size = new_v4_size; + } +// calculate the resulting score +// (do not move blocks to codebook encodings now, as some blocks may have +// got bigger errors despite a smaller training set - but we do not +// ever grow the training sets back) + for(;;) { + score = calculate_mode_score(s, h, &info, 1, + &v1shrunk, &v4shrunk +#ifdef CINEPAK_REPORT_SERR +, &serr +#endif +); +// do we have a reason to reiterate? + if(!v1shrunk && !v4shrunk) break; +// recompute the codebooks, omitting the extra blocks + if(v1shrunk) { + info.v1_size = v1_size; + new_v1_size = quantize(s, h, pict, 1, &info, ENC_V1); + if(new_v1_size < info.v1_size){ + //av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: cut v1 codebook to %i entries\n", mode, v1_size, v4_size, new_v1_size); + info.v1_size = new_v1_size; + } + } + if(v4shrunk) { + info.v4_size = v4_size; + new_v4_size = quantize(s, h, pict, 0, &info, ENC_V4); + if(new_v4_size < info.v4_size) { + //av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: cut v4 codebook to %i entries\n", mode, v1_size, v4_size, new_v4_size); + info.v4_size = new_v4_size; + } + } + } + } - //av_log(s->avctx, AV_LOG_INFO, "%3i %3i score = %li\n", v1_size, v4_size, score); + //av_log(s->avctx, AV_LOG_INFO, "%3i %3i score = %lli\n", v1_size, v4_size, (long long int)score); if(best_size == 0 || score < *best_score) { + *best_score = score; - best_size = encode_mode(s, mode, h, v1_size, v4_size, v4, scratch_pict, &info, s->strip_buf + STRIP_HEADER_SIZE); - best_mode = mode; +#ifdef CINEPAK_REPORT_SERR + *best_serr = serr; +#endif + best_size = encode_mode(s, h, scratch_pict, last_pict, &info, s->strip_buf + STRIP_HEADER_SIZE); - av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: %18li %i B\n", mode, v1_size, v4_size, score, best_size); + //av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: %18lli %i B", mode, info.v1_size, info.v4_size, (long long int)score, best_size); + //av_log(s->avctx, AV_LOG_INFO, "\n"); +#ifdef CINEPAK_REPORT_SERR + av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: %18lli %i B\n", mode, v1_size, v4_size, (long long int)serr, best_size); +#endif #ifdef CINEPAKENC_DEBUG //save MB encoding choices @@ -678,6 +1009,7 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture //memcpy(strip_temp + STRIP_HEADER_SIZE, strip_temp, best_size); write_strip_header(s, y, h, keyframe, s->strip_buf, best_size); + } } } @@ -685,11 +1017,11 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture #ifdef CINEPAKENC_DEBUG //gather stats. this will only work properly of MAX_STRIPS == 1 - if(best_mode == MODE_V1_ONLY) { + if(best_info.mode == MODE_V1_ONLY) { s->num_v1_mode++; s->num_v1_encs += s->w*h/MB_AREA; } else { - if(best_mode == MODE_V1_V4) + if(best_info.mode == MODE_V1_V4) s->num_v4_mode++; else s->num_mc_mode++; @@ -708,13 +1040,12 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture best_size += STRIP_HEADER_SIZE; memcpy(buf, s->strip_buf, best_size); - return best_size; } -static int write_cvid_header(CinepakEncContext *s, unsigned char *buf, int num_strips, int data_size) +static int write_cvid_header(CinepakEncContext *s, unsigned char *buf, int num_strips, int data_size, int isakeyframe) { - buf[0] = 0; + buf[0] = isakeyframe ? 0 : 1; AV_WB24(&buf[1], data_size + CVID_HEADER_SIZE); AV_WB16(&buf[4], s->w); AV_WB16(&buf[6], s->h); @@ -723,67 +1054,175 @@ static int write_cvid_header(CinepakEncContext *s, unsigned char *buf, int num_s return CVID_HEADER_SIZE; } -static int rd_frame(CinepakEncContext *s, AVFrame *frame, unsigned char *buf, int buf_size) +static int rd_frame(CinepakEncContext *s, AVFrame *frame, int isakeyframe, unsigned char *buf, int buf_size) { - int num_strips, strip, h, i, y, size, temp_size, best_size; + int num_strips, strip, i, y, nexty, size, temp_size, best_size; AVPicture last_pict, pict, scratch_pict; int64_t best_score = 0, score, score_temp; +#ifdef CINEPAK_REPORT_SERR + int64_t best_serr = 0, serr, serr_temp; +#endif - //TODO: support encoding zero strips (meaning skip the whole frame) - for(num_strips = MIN_STRIPS; num_strips <= MAX_STRIPS && num_strips <= s->h / MB_SIZE; num_strips++) { + int best_nstrips; + + if(s->pix_fmt == AV_PIX_FMT_RGB24) { + int x; +// build a copy of the given frame in the correct colorspace + for(y = 0; y < s->h; y += 2) { + for(x = 0; x < s->w; x += 2) { + uint8_t *ir[2]; int32_t r, g, b, rr, gg, bb; + ir[0] = ((AVPicture*)frame)->data[0] + x*3 + y*((AVPicture*)frame)->linesize[0]; + ir[1] = ir[0] + ((AVPicture*)frame)->linesize[0]; + get_sub_picture(s, x, y, (AVPicture*)s->input_frame, &scratch_pict); + r = g = b = 0; + for(i=0; i<4; ++i) { + int i1, i2; + i1 = (i&1); i2 = (i>=2); + rr = ir[i2][i1*3+0]; + gg = ir[i2][i1*3+1]; + bb = ir[i2][i1*3+2]; + r += rr; g += gg; b += bb; +// using fixed point arithmetic for portable repeatability, scaling by 2^23 +// "Y" +// rr = 0.2857*rr + 0.5714*gg + 0.1429*bb; + rr = (2396625*rr + 4793251*gg + 1198732*bb) >> 23; + if( rr < 0) rr = 0; + else if (rr > 255) rr = 255; + scratch_pict.data[0][i1 + i2*scratch_pict.linesize[0]] = rr; + } +// let us scale down as late as possible +// r /= 4; g /= 4; b /= 4; +// "U" +// rr = -0.1429*r - 0.2857*g + 0.4286*b; + rr = (-299683*r - 599156*g + 898839*b) >> 23; + if( rr < -128) rr = -128; + else if (rr > 127) rr = 127; + scratch_pict.data[1][0] = rr + 128; // quantize needs unsigned +// "V" +// rr = 0.3571*r - 0.2857*g - 0.0714*b; + rr = (748893*r - 599156*g - 149737*b) >> 23; + if( rr < -128) rr = -128; + else if (rr > 127) rr = 127; + scratch_pict.data[2][0] = rr + 128; // quantize needs unsigned + } + } + } + + //would be nice but quite certainly incompatible with vintage players: + // support encoding zero strips (meaning skip the whole frame) + for(num_strips = s->min_strips; num_strips <= s->max_strips && num_strips <= s->h / MB_SIZE; num_strips++) { score = 0; size = 0; - h = s->h / num_strips; - //make h into next multiple of 4 - h += 4 - (h & 3); +#ifdef CINEPAK_REPORT_SERR + serr = 0; +#endif + + for(y = 0, strip = 1; y < s->h; strip++, y = nexty) { + int strip_height; - for(strip = 0; strip < num_strips; strip++) { - y = strip*h; + nexty = strip * s->h / num_strips; // <= s->h + //make nexty the next multiple of 4 if not already there + if(nexty & 3) + nexty += 4 - (nexty & 3); - get_sub_picture(s, 0, y, (AVPicture*)frame, &pict); - get_sub_picture(s, 0, y, (AVPicture*)&s->last_frame, &last_pict); - get_sub_picture(s, 0, y, (AVPicture*)&s->scratch_frame, &scratch_pict); + strip_height = nexty - y; + if(strip_height <= 0) { // can this ever happen? + av_log(s->avctx, AV_LOG_INFO, "skipping zero height strip %i of %i\n", strip, num_strips); + continue; + } + + if(s->pix_fmt == AV_PIX_FMT_RGB24) + get_sub_picture(s, 0, y, (AVPicture*)s->input_frame, &pict); + else + get_sub_picture(s, 0, y, (AVPicture*)frame, &pict); + get_sub_picture(s, 0, y, (AVPicture*)s->last_frame, &last_pict); + get_sub_picture(s, 0, y, (AVPicture*)s->scratch_frame, &scratch_pict); - if((temp_size = rd_strip(s, y, FFMIN(h, s->h - y), frame->key_frame, &last_pict, &pict, &scratch_pict, s->frame_buf + CVID_HEADER_SIZE, &score_temp)) < 0) + if((temp_size = rd_strip(s, y, strip_height, isakeyframe, &last_pict, &pict, &scratch_pict, s->frame_buf + size + CVID_HEADER_SIZE, &score_temp +#ifdef CINEPAK_REPORT_SERR +, &serr_temp +#endif +)) < 0) return temp_size; score += score_temp; +#ifdef CINEPAK_REPORT_SERR + serr += serr_temp; +#endif size += temp_size; + //av_log(s->avctx, AV_LOG_INFO, "strip %d, isakeyframe=%d", strip, isakeyframe); + //av_log(s->avctx, AV_LOG_INFO, "\n"); } if(best_score == 0 || score < best_score) { best_score = score; - best_size = size + write_cvid_header(s, s->frame_buf, num_strips, size); - av_log(s->avctx, AV_LOG_INFO, "best number of strips so far: %2i, %12li, %i B\n", num_strips, score, best_size); +#ifdef CINEPAK_REPORT_SERR + best_serr = serr; +#endif + best_size = size + write_cvid_header(s, s->frame_buf, num_strips, size, isakeyframe); + //av_log(s->avctx, AV_LOG_INFO, "best number of strips so far: %2i, %12lli, %i B\n", num_strips, (long long int)score, best_size); +#ifdef CINEPAK_REPORT_SERR + av_log(s->avctx, AV_LOG_INFO, "best number of strips so far: %2i, %12lli, %i B\n", num_strips, (long long int)serr, best_size); +#endif - FFSWAP(AVFrame, s->best_frame, s->scratch_frame); + FFSWAP(AVFrame *, s->best_frame, s->scratch_frame); + memcpy(buf, s->frame_buf, best_size); + best_nstrips = num_strips; } +// avoid trying too many strip numbers without a real reason +// (this makes the processing of the very first frame faster) + if(num_strips - best_nstrips > 4) + break; } - memcpy(buf, s->frame_buf, best_size); +// let the number of strips slowly adapt to the changes in the contents, +// compared to full bruteforcing every time this will occasionally lead +// to some r/d performance loss but makes encoding up to several times faster +#ifdef CINEPAK_AGGRESSIVE_STRIP_NUMBER_ADAPTIVITY + s->max_strips = best_nstrips + 4; + if(s->max_strips >= MAX_STRIPS) + s->max_strips = MAX_STRIPS; + s->min_strips = best_nstrips - 4; + if(s->min_strips < MIN_STRIPS) + s->min_strips = MIN_STRIPS; +#else + if(best_nstrips == s->max_strips) { // let us try to step up + s->max_strips = best_nstrips + 1; + if(s->max_strips >= MAX_STRIPS) + s->max_strips = MAX_STRIPS; + } else { // try to step down + s->max_strips = best_nstrips; + } + s->min_strips = s->max_strips - 1; + if(s->min_strips < MIN_STRIPS) + s->min_strips = MIN_STRIPS; +#endif return best_size; } -static int cinepak_encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data) +static int cinepak_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) { CinepakEncContext *s = avctx->priv_data; - AVFrame *frame = data; int ret; s->lambda = frame->quality ? frame->quality - 1 : 2 * FF_LAMBDA_SCALE; - frame->key_frame = s->curframe == 0; - frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + if ((ret = ff_alloc_packet(pkt, s->frame_buf_size)) < 0) + return ret; + ret = rd_frame(s, frame, (s->curframe == 0), pkt->data, s->frame_buf_size); + pkt->size = ret; + if (s->curframe == 0) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; - ret = rd_frame(s, frame, buf, buf_size); - - FFSWAP(AVFrame, s->last_frame, s->best_frame); + FFSWAP(AVFrame *, s->last_frame, s->best_frame); if (++s->curframe >= s->keyint) s->curframe = 0; - return ret; + return 0; } static av_cold int cinepak_encode_end(AVCodecContext *avctx) @@ -791,20 +1230,27 @@ static av_cold int cinepak_encode_end(AVCodecContext *avctx) CinepakEncContext *s = avctx->priv_data; int x; - av_free(s->codebook_input); - av_free(s->codebook_closest); - av_free(s->strip_buf); - av_free(s->frame_buf); - av_free(s->mb); + av_frame_free(&s->last_frame); + av_frame_free(&s->best_frame); + av_frame_free(&s->scratch_frame); + if (avctx->pix_fmt == AV_PIX_FMT_RGB24) + av_frame_free(&s->input_frame); + av_freep(&s->codebook_input); + av_freep(&s->codebook_closest); + av_freep(&s->strip_buf); + av_freep(&s->frame_buf); + av_freep(&s->mb); #ifdef CINEPAKENC_DEBUG - av_free(s->best_mb); + av_freep(&s->best_mb); #endif - for(x = 0; x < 3; x++) - av_free(s->pict_bufs[x]); + for(x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) + av_freep(&s->pict_bufs[x]); +#ifdef CINEPAKENC_DEBUG av_log(avctx, AV_LOG_INFO, "strip coding stats: %i V1 mode, %i V4 mode, %i MC mode (%i V1 encs, %i V4 encs, %i skips)\n", s->num_v1_mode, s->num_v4_mode, s->num_mc_mode, s->num_v1_encs, s->num_v4_encs, s->num_skips); +#endif return 0; } From 158d2e15454a7f7e2db72204697b2fa0e6e75a52 Mon Sep 17 00:00:00 2001 From: "addr-see-the-website@aetey.se" Date: Wed, 28 Jun 2017 00:27:13 +0200 Subject: [PATCH 0303/2557] cinepakenc: add option handling for flexibility Now it is possible to adjust compression speed vs R/D when needed and also skip vintage player compatibility at will. Signed-off-by: Diego Biurrun --- libavcodec/cinepakenc.c | 92 +++++++++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index 1b63260e4d985..74d965eab411f 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -25,7 +25,6 @@ OTHER DEALINGS IN THE SOFTWARE. * TODO: * - optimize: color space conversion (move conversion to libswscale), ... - * - implement options to set the min/max number of strips? * MAYBE: * - "optimally" split the frame into several non-regular areas * using a separate codebook pair for each area and approximating @@ -38,6 +37,8 @@ OTHER DEALINGS IN THE SOFTWARE. #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" + #include "avcodec.h" #include "libavutil/lfg.h" #include "elbg.h" @@ -55,9 +56,7 @@ OTHER DEALINGS IN THE SOFTWARE. #define VECTOR_MAX 6 //six or four entries per vector depending on format #define CODEBOOK_MAX 256 //size of a codebook -//#define MAX_STRIPS 32 //Note: having fewer choices regarding the number of strips speeds up encoding (obviously) -#define MAX_STRIPS 3 // This seems to be max for vintage players! -- rl -// TODO: we might want to have a "vintage compatibilty" switch +#define MAX_STRIPS 32 //Note: having fewer choices regarding the number of strips speeds up encoding (obviously) #define MIN_STRIPS 1 //Note: having more strips speeds up encoding the frame (this is less obvious) // MAX_STRIPS limits the maximum quality you can reach // when you want high quality on high resolutions, @@ -102,6 +101,7 @@ typedef struct { } strip_info; typedef struct { + const AVClass *class; AVCodecContext *avctx; unsigned char *pict_bufs[4], *strip_buf, *frame_buf; AVFrame *last_frame; @@ -124,8 +124,32 @@ typedef struct { int num_v1_mode, num_v4_mode, num_mc_mode; int num_v1_encs, num_v4_encs, num_skips; #endif +// options + int max_extra_cb_iterations; + int skip_empty_cb; + int min_min_strips; + int max_max_strips; + int strip_number_delta_range; } CinepakEncContext; +#define OFFSET(x) offsetof(CinepakEncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "max_extra_cb_iterations", "Max extra codebook recalculation passes, more is better and slower", OFFSET(max_extra_cb_iterations), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, INT_MAX, VE }, + { "skip_empty_cb", "Avoid wasting bytes, ignore vintage MacOS decoder", OFFSET(skip_empty_cb), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "max_strips", "Limit strips/frame, vintage compatible is 1..3, otherwise the more the better", OFFSET(max_max_strips), AV_OPT_TYPE_INT, { .i64 = 3 }, MIN_STRIPS, MAX_STRIPS, VE }, + { "min_strips", "Enforce min strips/frame, more is worse and faster, must be <= max_strips", OFFSET(min_min_strips), AV_OPT_TYPE_INT, { .i64 = MIN_STRIPS }, MIN_STRIPS, MAX_STRIPS, VE }, + { "strip_number_adaptivity", "How fast the strip number adapts, more is slightly better, much slower", OFFSET(strip_number_delta_range), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_STRIPS-MIN_STRIPS, VE }, + { NULL }, +}; + +static const AVClass cinepak_class = { + .class_name = "cinepak", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + static av_cold int cinepak_encode_init(AVCodecContext *avctx) { CinepakEncContext *s = avctx->priv_data; @@ -137,6 +161,12 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } + if (s->min_min_strips > s->max_max_strips) { + av_log(avctx, AV_LOG_ERROR, "minimal number of strips can not exceed maximal (got %i and %i)\n", + s->min_min_strips, s->max_max_strips); + return AVERROR(EINVAL); + } + if (!(s->last_frame = av_frame_alloc())) return AVERROR(ENOMEM); if (!(s->best_frame = av_frame_alloc())) @@ -165,7 +195,7 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) //and 2*256 extra flag bits per strip strip_buf_size = STRIP_HEADER_SIZE + 3 * CHUNK_HEADER_SIZE + 2 * VECTOR_MAX * CODEBOOK_MAX + 4 * (mb_count + (mb_count + 15) / 16) + (2 * CODEBOOK_MAX)/8; - frame_buf_size = CVID_HEADER_SIZE + MAX_STRIPS * strip_buf_size; + frame_buf_size = CVID_HEADER_SIZE + s->max_max_strips * strip_buf_size; if (!(s->strip_buf = av_malloc(strip_buf_size))) goto enomem; @@ -218,8 +248,8 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) s->input_frame->linesize[1] = s->input_frame->linesize[2] = s->w >> 1; } - s->min_strips = MIN_STRIPS; - s->max_strips = MAX_STRIPS; + s->min_strips = s->min_min_strips; + s->max_strips = s->max_max_strips; #ifdef CINEPAKENC_DEBUG s->num_v1_mode = s->num_v4_mode = s->num_mc_mode = s->num_v1_encs = s->num_v4_encs = s->num_skips = 0; @@ -566,10 +596,10 @@ static int encode_mode(CinepakEncContext *s, int h, AVPicture *scratch_pict, AVP ////// MacOS vintage decoder compatibility dictates the presence of ////// the codebook chunk even when the codebook is empty - pretty dumb... ////// and also the certain order of the codebook chunks -- rl -// if(info->v4_size) + if(info->v4_size || !s->skip_empty_cb) ret += encode_codebook(s, info->v4_codebook, info->v4_size, 0x20, 0x24, buf + ret); -// if(info->v1_size) + if(info->v1_size || !s->skip_empty_cb) ret += encode_codebook(s, info->v1_codebook, info->v1_size, 0x22, 0x26, buf + ret); //update scratch picture @@ -938,6 +968,7 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture ); if(mode != MODE_V1_ONLY){ + int extra_iterations_limit = s->max_extra_cb_iterations; // recompute the codebooks, omitting the extra blocks // we assume we _may_ come here with more blocks to encode than before info.v1_size = v1_size; @@ -964,8 +995,8 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture , &serr #endif ); -// do we have a reason to reiterate? - if(!v1shrunk && !v4shrunk) break; +// do we have a reason to reiterate? if so, have we reached the limit? + if((!v1shrunk && !v4shrunk) || !extra_iterations_limit--) break; // recompute the codebooks, omitting the extra blocks if(v1shrunk) { info.v1_size = v1_size; @@ -1054,7 +1085,7 @@ static int write_cvid_header(CinepakEncContext *s, unsigned char *buf, int num_s return CVID_HEADER_SIZE; } -static int rd_frame(CinepakEncContext *s, AVFrame *frame, int isakeyframe, unsigned char *buf, int buf_size) +static int rd_frame(CinepakEncContext *s, const AVFrame *frame, int isakeyframe, unsigned char *buf, int buf_size) { int num_strips, strip, i, y, nexty, size, temp_size, best_size; AVPicture last_pict, pict, scratch_pict; @@ -1178,25 +1209,25 @@ static int rd_frame(CinepakEncContext *s, AVFrame *frame, int isakeyframe, unsig // let the number of strips slowly adapt to the changes in the contents, // compared to full bruteforcing every time this will occasionally lead // to some r/d performance loss but makes encoding up to several times faster -#ifdef CINEPAK_AGGRESSIVE_STRIP_NUMBER_ADAPTIVITY - s->max_strips = best_nstrips + 4; - if(s->max_strips >= MAX_STRIPS) - s->max_strips = MAX_STRIPS; - s->min_strips = best_nstrips - 4; - if(s->min_strips < MIN_STRIPS) - s->min_strips = MIN_STRIPS; -#else - if(best_nstrips == s->max_strips) { // let us try to step up - s->max_strips = best_nstrips + 1; - if(s->max_strips >= MAX_STRIPS) - s->max_strips = MAX_STRIPS; - } else { // try to step down - s->max_strips = best_nstrips; + if(!s->strip_number_delta_range) { + if(best_nstrips == s->max_strips) { // let us try to step up + s->max_strips = best_nstrips + 1; + if(s->max_strips >= s->max_max_strips) + s->max_strips = s->max_max_strips; + } else { // try to step down + s->max_strips = best_nstrips; + } + s->min_strips = s->max_strips - 1; + if(s->min_strips < s->min_min_strips) + s->min_strips = s->min_min_strips; + } else { + s->max_strips = best_nstrips + s->strip_number_delta_range; + if(s->max_strips >= s->max_max_strips) + s->max_strips = s->max_max_strips; + s->min_strips = best_nstrips - s->strip_number_delta_range; + if(s->min_strips < s->min_min_strips) + s->min_strips = s->min_min_strips; } - s->min_strips = s->max_strips - 1; - if(s->min_strips < MIN_STRIPS) - s->min_strips = MIN_STRIPS; -#endif return best_size; } @@ -1265,4 +1296,5 @@ AVCodec ff_cinepak_encoder = { .close = cinepak_encode_end, .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_RGB24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("Cinepak"), + .priv_class = &cinepak_class, }; From b40236d954c3283995d196bfd28ac4f4528c17ab Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 28 Jun 2017 00:27:14 +0200 Subject: [PATCH 0304/2557] cinepakenc: Drop broken debug code --- libavcodec/cinepakenc.c | 185 +++------------------------------------- 1 file changed, 10 insertions(+), 175 deletions(-) diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index 74d965eab411f..c4b980b2f823f 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -119,11 +119,6 @@ typedef struct { mb_info *mb; //MB RD state int min_strips; //the current limit int max_strips; //the current limit -#ifdef CINEPAKENC_DEBUG - mb_info *best_mb; //TODO: remove. only used for printing stats - int num_v1_mode, num_v4_mode, num_mc_mode; - int num_v1_encs, num_v4_encs, num_skips; -#endif // options int max_extra_cb_iterations; int skip_empty_cb; @@ -206,11 +201,6 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) if (!(s->mb = av_malloc(mb_count*sizeof(mb_info)))) goto enomem; -#ifdef CINEPAKENC_DEBUG - if (!(s->best_mb = av_malloc(mb_count*sizeof(mb_info)))) - goto enomem; -#endif - av_lfg_init(&s->randctx, 1); s->avctx = avctx; s->w = avctx->width; @@ -251,10 +241,6 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) s->min_strips = s->min_min_strips; s->max_strips = s->max_max_strips; -#ifdef CINEPAKENC_DEBUG - s->num_v1_mode = s->num_v4_mode = s->num_mc_mode = s->num_v1_encs = s->num_v4_encs = s->num_skips = 0; -#endif - return 0; enomem: @@ -268,9 +254,6 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) av_freep(&s->strip_buf); av_freep(&s->frame_buf); av_freep(&s->mb); -#ifdef CINEPAKENC_DEBUG - av_freep(&s->best_mb); -#endif for(x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) av_freep(&s->pict_bufs[x]); @@ -278,11 +261,7 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); } -static int64_t calculate_mode_score(CinepakEncContext *s, int h, strip_info *info, int report, int *training_set_v1_shrunk, int *training_set_v4_shrunk -#ifdef CINEPAK_REPORT_SERR -, int64_t *serr -#endif -) +static int64_t calculate_mode_score(CinepakEncContext *s, int h, strip_info *info, int report, int *training_set_v1_shrunk, int *training_set_v4_shrunk) { //score = FF_LAMBDA_SCALE * error + lambda * bits int x; @@ -294,12 +273,6 @@ static int64_t calculate_mode_score(CinepakEncContext *s, int h, strip_info *inf (info->v4_size ? CHUNK_HEADER_SIZE + info->v4_size * entry_size : 0) + CHUNK_HEADER_SIZE) << 3; - //av_log(s->avctx, AV_LOG_INFO, "sizes %3i %3i -> %9lli score mb_count %i", info->v1_size, info->v4_size, (long long int)ret, mb_count); - -#ifdef CINEPAK_REPORT_SERR - *serr = 0; -#endif - switch(info->mode) { case MODE_V1_ONLY: //one byte per MB @@ -309,9 +282,6 @@ static int64_t calculate_mode_score(CinepakEncContext *s, int h, strip_info *inf for(x = 0; x < mb_count; x++) { mb = &s->mb[x]; ret += FF_LAMBDA_SCALE * mb->v1_error; -#ifdef CINEPAK_REPORT_SERR - *serr += mb->v1_error; -#endif // this function is never called for report in MODE_V1_ONLY // if(!report) mb->best_encoding = ENC_V1; @@ -331,9 +301,6 @@ static int64_t calculate_mode_score(CinepakEncContext *s, int h, strip_info *inf else score1 = s->lambda * 33 + FF_LAMBDA_SCALE * (mberr=mb->v4_error); ret += score1; -#ifdef CINEPAK_REPORT_SERR - *serr += mberr; -#endif } } else { // find best mode per block for(x = 0; x < mb_count; x++) { @@ -343,15 +310,9 @@ static int64_t calculate_mode_score(CinepakEncContext *s, int h, strip_info *inf if(score1 <= score2) { ret += score1; -#ifdef CINEPAK_REPORT_SERR - *serr += mb->v1_error; -#endif mb->best_encoding = ENC_V1; } else { ret += score2; -#ifdef CINEPAK_REPORT_SERR - *serr += mb->v4_error; -#endif mb->best_encoding = ENC_V4; } } @@ -369,36 +330,21 @@ static int64_t calculate_mode_score(CinepakEncContext *s, int h, strip_info *inf score1 = s->lambda * 1 + FF_LAMBDA_SCALE * mb->skip_error; if(mb->best_encoding == ENC_SKIP) { ret += score1; -#ifdef CINEPAK_REPORT_SERR - *serr += mb->skip_error; -#endif } else if(mb->best_encoding == ENC_V1) { if((score2=s->lambda * 10 + FF_LAMBDA_SCALE * mb->v1_error) >= score1) { mb->best_encoding = ENC_SKIP; ++v1_shrunk; ret += score1; -#ifdef CINEPAK_REPORT_SERR - *serr += mb->skip_error; -#endif } else { ret += score2; -#ifdef CINEPAK_REPORT_SERR - *serr += mb->v1_error; -#endif } } else { if((score3=s->lambda * 34 + FF_LAMBDA_SCALE * mb->v4_error) >= score1) { mb->best_encoding = ENC_SKIP; ++v4_shrunk; ret += score1; -#ifdef CINEPAK_REPORT_SERR - *serr += mb->skip_error; -#endif } else { ret += score3; -#ifdef CINEPAK_REPORT_SERR - *serr += mb->v4_error; -#endif } } } @@ -413,21 +359,12 @@ static int64_t calculate_mode_score(CinepakEncContext *s, int h, strip_info *inf if(score1 <= score2 && score1 <= score3) { ret += score1; -#ifdef CINEPAK_REPORT_SERR - *serr += mb->skip_error; -#endif mb->best_encoding = ENC_SKIP; } else if(score2 <= score3) { ret += score2; -#ifdef CINEPAK_REPORT_SERR - *serr += mb->v1_error; -#endif mb->best_encoding = ENC_V1; } else { ret += score3; -#ifdef CINEPAK_REPORT_SERR - *serr += mb->v4_error; -#endif mb->best_encoding = ENC_V4; } } @@ -808,16 +745,11 @@ static int quantize(CinepakEncContext *s, int h, AVPicture *pict, i += v1mode ? 1 : 4; } } -// if(i < mbn*(v1mode ? 1 : 4)) { -// av_log(s->avctx, AV_LOG_INFO, "reducing training set for %s from %i to %i (encoding %i)\n", v1mode?"v1":"v4", mbn*(v1mode ? 1 : 4), i, encoding); -// } if(i == 0) // empty training set, nothing to do return 0; - if(i < size) { - //av_log(s->avctx, (CERTAIN(encoding) ? AV_LOG_ERROR : AV_LOG_INFO), "WOULD WASTE: %s cbsize %i bigger than training set size %i (encoding %i)\n", v1mode?"v1":"v4", size, i, encoding); + if (i < size) size = i; - } ff_init_elbg(s->codebook_input, entry_size, i, codebook, size, 1, s->codebook_closest, &s->randctx); ff_do_elbg(s->codebook_input, entry_size, i, codebook, size, 1, s->codebook_closest, &s->randctx); @@ -864,8 +796,6 @@ static int quantize(CinepakEncContext *s, int h, AVPicture *pict, // check that we did it right in the beginning of the function av_assert0(i >= size); // training set is no smaller than the codebook - //av_log(s->avctx, AV_LOG_INFO, "isv1 %i size= %i i= %i error %lli\n", v1mode, size, i, (long long int)total_error); - return size; } @@ -899,19 +829,11 @@ static void write_strip_header(CinepakEncContext *s, int y, int h, int keyframe, // AV_WB16(&buf[8], y+h); /* using absolute y values works -- rl */ AV_WB16(&buf[8], h); /* using relative values works as well -- rl */ AV_WB16(&buf[10], s->w); - //av_log(s->avctx, AV_LOG_INFO, "write_strip_header() %x keyframe=%d\n", buf[0], keyframe); } -static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture *last_pict, AVPicture *pict, AVPicture *scratch_pict, unsigned char *buf, int64_t *best_score -#ifdef CINEPAK_REPORT_SERR -, int64_t *best_serr -#endif -) +static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture *last_pict, AVPicture *pict, AVPicture *scratch_pict, unsigned char *buf, int64_t *best_score) { int64_t score = 0; -#ifdef CINEPAK_REPORT_SERR - int64_t serr; -#endif int best_size = 0; strip_info info; // for codebook optimization: @@ -961,11 +883,7 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture info.mode = mode; // choose the best encoding per block, based on current experience score = calculate_mode_score(s, h, &info, 0, - &v1shrunk, &v4shrunk -#ifdef CINEPAK_REPORT_SERR -, &serr -#endif -); + &v1shrunk, &v4shrunk); if(mode != MODE_V1_ONLY){ int extra_iterations_limit = s->max_extra_cb_iterations; @@ -973,72 +891,42 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture // we assume we _may_ come here with more blocks to encode than before info.v1_size = v1_size; new_v1_size = quantize(s, h, pict, 1, &info, ENC_V1); - if(new_v1_size < info.v1_size){ - //av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: cut v1 codebook to %i entries\n", mode, v1_size, v4_size, new_v1_size); + if (new_v1_size < info.v1_size) info.v1_size = new_v1_size; - } // we assume we _may_ come here with more blocks to encode than before info.v4_size = v4_size; new_v4_size = quantize(s, h, pict, 0, &info, ENC_V4); - if(new_v4_size < info.v4_size) { - //av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: cut v4 codebook to %i entries at first iteration\n", mode, v1_size, v4_size, new_v4_size); + if (new_v4_size < info.v4_size) info.v4_size = new_v4_size; - } // calculate the resulting score // (do not move blocks to codebook encodings now, as some blocks may have // got bigger errors despite a smaller training set - but we do not // ever grow the training sets back) for(;;) { score = calculate_mode_score(s, h, &info, 1, - &v1shrunk, &v4shrunk -#ifdef CINEPAK_REPORT_SERR -, &serr -#endif -); + &v1shrunk, &v4shrunk); // do we have a reason to reiterate? if so, have we reached the limit? if((!v1shrunk && !v4shrunk) || !extra_iterations_limit--) break; // recompute the codebooks, omitting the extra blocks if(v1shrunk) { info.v1_size = v1_size; new_v1_size = quantize(s, h, pict, 1, &info, ENC_V1); - if(new_v1_size < info.v1_size){ - //av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: cut v1 codebook to %i entries\n", mode, v1_size, v4_size, new_v1_size); + if (new_v1_size < info.v1_size) info.v1_size = new_v1_size; - } } if(v4shrunk) { info.v4_size = v4_size; new_v4_size = quantize(s, h, pict, 0, &info, ENC_V4); - if(new_v4_size < info.v4_size) { - //av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: cut v4 codebook to %i entries\n", mode, v1_size, v4_size, new_v4_size); + if (new_v4_size < info.v4_size) info.v4_size = new_v4_size; - } } } } - //av_log(s->avctx, AV_LOG_INFO, "%3i %3i score = %lli\n", v1_size, v4_size, (long long int)score); - if(best_size == 0 || score < *best_score) { *best_score = score; -#ifdef CINEPAK_REPORT_SERR - *best_serr = serr; -#endif best_size = encode_mode(s, h, scratch_pict, last_pict, &info, s->strip_buf + STRIP_HEADER_SIZE); - - //av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: %18lli %i B", mode, info.v1_size, info.v4_size, (long long int)score, best_size); - //av_log(s->avctx, AV_LOG_INFO, "\n"); -#ifdef CINEPAK_REPORT_SERR - av_log(s->avctx, AV_LOG_INFO, "mode %i, %3i, %3i: %18lli %i B\n", mode, v1_size, v4_size, (long long int)serr, best_size); -#endif - -#ifdef CINEPAKENC_DEBUG - //save MB encoding choices - memcpy(s->best_mb, s->mb, mb_count*sizeof(mb_info)); -#endif - - //memcpy(strip_temp + STRIP_HEADER_SIZE, strip_temp, best_size); write_strip_header(s, y, h, keyframe, s->strip_buf, best_size); } @@ -1046,28 +934,6 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture } } -#ifdef CINEPAKENC_DEBUG - //gather stats. this will only work properly of MAX_STRIPS == 1 - if(best_info.mode == MODE_V1_ONLY) { - s->num_v1_mode++; - s->num_v1_encs += s->w*h/MB_AREA; - } else { - if(best_info.mode == MODE_V1_V4) - s->num_v4_mode++; - else - s->num_mc_mode++; - - int x; - for(x = 0; x < s->w*h/MB_AREA; x++) - if(s->best_mb[x].best_encoding == ENC_V1) - s->num_v1_encs++; - else if(s->best_mb[x].best_encoding == ENC_V4) - s->num_v4_encs++; - else - s->num_skips++; - } -#endif - best_size += STRIP_HEADER_SIZE; memcpy(buf, s->strip_buf, best_size); @@ -1090,10 +956,6 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, int isakeyframe, int num_strips, strip, i, y, nexty, size, temp_size, best_size; AVPicture last_pict, pict, scratch_pict; int64_t best_score = 0, score, score_temp; -#ifdef CINEPAK_REPORT_SERR - int64_t best_serr = 0, serr, serr_temp; -#endif - int best_nstrips; if(s->pix_fmt == AV_PIX_FMT_RGB24) { @@ -1144,9 +1006,6 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, int isakeyframe, for(num_strips = s->min_strips; num_strips <= s->max_strips && num_strips <= s->h / MB_SIZE; num_strips++) { score = 0; size = 0; -#ifdef CINEPAK_REPORT_SERR - serr = 0; -#endif for(y = 0, strip = 1; y < s->h; strip++, y = nexty) { int strip_height; @@ -1169,32 +1028,16 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, int isakeyframe, get_sub_picture(s, 0, y, (AVPicture*)s->last_frame, &last_pict); get_sub_picture(s, 0, y, (AVPicture*)s->scratch_frame, &scratch_pict); - if((temp_size = rd_strip(s, y, strip_height, isakeyframe, &last_pict, &pict, &scratch_pict, s->frame_buf + size + CVID_HEADER_SIZE, &score_temp -#ifdef CINEPAK_REPORT_SERR -, &serr_temp -#endif -)) < 0) + if((temp_size = rd_strip(s, y, strip_height, isakeyframe, &last_pict, &pict, &scratch_pict, s->frame_buf + size + CVID_HEADER_SIZE, &score_temp)) < 0) return temp_size; score += score_temp; -#ifdef CINEPAK_REPORT_SERR - serr += serr_temp; -#endif size += temp_size; - //av_log(s->avctx, AV_LOG_INFO, "strip %d, isakeyframe=%d", strip, isakeyframe); - //av_log(s->avctx, AV_LOG_INFO, "\n"); } if(best_score == 0 || score < best_score) { best_score = score; -#ifdef CINEPAK_REPORT_SERR - best_serr = serr; -#endif best_size = size + write_cvid_header(s, s->frame_buf, num_strips, size, isakeyframe); - //av_log(s->avctx, AV_LOG_INFO, "best number of strips so far: %2i, %12lli, %i B\n", num_strips, (long long int)score, best_size); -#ifdef CINEPAK_REPORT_SERR - av_log(s->avctx, AV_LOG_INFO, "best number of strips so far: %2i, %12lli, %i B\n", num_strips, (long long int)serr, best_size); -#endif FFSWAP(AVFrame *, s->best_frame, s->scratch_frame); memcpy(buf, s->frame_buf, best_size); @@ -1271,18 +1114,10 @@ static av_cold int cinepak_encode_end(AVCodecContext *avctx) av_freep(&s->strip_buf); av_freep(&s->frame_buf); av_freep(&s->mb); -#ifdef CINEPAKENC_DEBUG - av_freep(&s->best_mb); -#endif for(x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) av_freep(&s->pict_bufs[x]); -#ifdef CINEPAKENC_DEBUG - av_log(avctx, AV_LOG_INFO, "strip coding stats: %i V1 mode, %i V4 mode, %i MC mode (%i V1 encs, %i V4 encs, %i skips)\n", - s->num_v1_mode, s->num_v4_mode, s->num_mc_mode, s->num_v1_encs, s->num_v4_encs, s->num_skips); -#endif - return 0; } From 1e12730e5df21f5bf9911f9c444f5614fd7ea522 Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Wed, 28 Jun 2017 00:27:15 +0200 Subject: [PATCH 0305/2557] cinepakenc: Stop using AVPicture --- libavcodec/cinepakenc.c | 268 ++++++++++++++++++++++++---------------- 1 file changed, 162 insertions(+), 106 deletions(-) diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index c4b980b2f823f..674d0298dcc8d 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -429,105 +429,115 @@ static int encode_codebook(CinepakEncContext *s, int *codebook, int size, int ch } //sets out to the sub picture starting at (x,y) in in -static void get_sub_picture(CinepakEncContext *s, int x, int y, AVPicture *in, AVPicture *out) +static void get_sub_picture(CinepakEncContext *s, int x, int y, + uint8_t * in_data[4], int in_linesize[4], + uint8_t *out_data[4], int out_linesize[4]) { - out->data[0] = in->data[0] + x + y * in->linesize[0]; - out->linesize[0] = in->linesize[0]; + out_data[0] = in_data[0] + x + y * in_linesize[0]; + out_linesize[0] = in_linesize[0]; if(s->pix_fmt == AV_PIX_FMT_RGB24) { - out->data[1] = in->data[1] + (x >> 1) + (y >> 1) * in->linesize[1]; - out->linesize[1] = in->linesize[1]; + out_data[1] = in_data[1] + (x >> 1) + (y >> 1) * in_linesize[1]; + out_linesize[1] = in_linesize[1]; - out->data[2] = in->data[2] + (x >> 1) + (y >> 1) * in->linesize[2]; - out->linesize[2] = in->linesize[2]; + out_data[2] = in_data[2] + (x >> 1) + (y >> 1) * in_linesize[2]; + out_linesize[2] = in_linesize[2]; } } -//decodes the V1 vector in mb into the 4x4 MB pointed to by sub_pict -static void decode_v1_vector(CinepakEncContext *s, AVPicture *sub_pict, int v1_vector, strip_info *info) +//decodes the V1 vector in mb into the 4x4 MB pointed to by data +static void decode_v1_vector(CinepakEncContext *s, uint8_t *data[4], + int linesize[4], int v1_vector, strip_info *info) { int entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; - sub_pict->data[0][0] = - sub_pict->data[0][1] = - sub_pict->data[0][ sub_pict->linesize[0]] = - sub_pict->data[0][1+ sub_pict->linesize[0]] = info->v1_codebook[v1_vector*entry_size]; + data[0][0] = + data[0][1] = + data[0][ linesize[0]] = + data[0][1+ linesize[0]] = info->v1_codebook[v1_vector*entry_size]; - sub_pict->data[0][2] = - sub_pict->data[0][3] = - sub_pict->data[0][2+ sub_pict->linesize[0]] = - sub_pict->data[0][3+ sub_pict->linesize[0]] = info->v1_codebook[v1_vector*entry_size+1]; + data[0][2] = + data[0][3] = + data[0][2+ linesize[0]] = + data[0][3+ linesize[0]] = info->v1_codebook[v1_vector*entry_size+1]; - sub_pict->data[0][2*sub_pict->linesize[0]] = - sub_pict->data[0][1+2*sub_pict->linesize[0]] = - sub_pict->data[0][ 3*sub_pict->linesize[0]] = - sub_pict->data[0][1+3*sub_pict->linesize[0]] = info->v1_codebook[v1_vector*entry_size+2]; + data[0][2*linesize[0]] = + data[0][1+2*linesize[0]] = + data[0][ 3*linesize[0]] = + data[0][1+3*linesize[0]] = info->v1_codebook[v1_vector*entry_size+2]; - sub_pict->data[0][2+2*sub_pict->linesize[0]] = - sub_pict->data[0][3+2*sub_pict->linesize[0]] = - sub_pict->data[0][2+3*sub_pict->linesize[0]] = - sub_pict->data[0][3+3*sub_pict->linesize[0]] = info->v1_codebook[v1_vector*entry_size+3]; + data[0][2+2*linesize[0]] = + data[0][3+2*linesize[0]] = + data[0][2+3*linesize[0]] = + data[0][3+3*linesize[0]] = info->v1_codebook[v1_vector*entry_size+3]; if(s->pix_fmt == AV_PIX_FMT_RGB24) { - sub_pict->data[1][0] = - sub_pict->data[1][1] = - sub_pict->data[1][ sub_pict->linesize[1]] = - sub_pict->data[1][1+ sub_pict->linesize[1]] = info->v1_codebook[v1_vector*entry_size+4]; - - sub_pict->data[2][0] = - sub_pict->data[2][1] = - sub_pict->data[2][ sub_pict->linesize[2]] = - sub_pict->data[2][1+ sub_pict->linesize[2]] = info->v1_codebook[v1_vector*entry_size+5]; + data[1][0] = + data[1][1] = + data[1][ linesize[1]] = + data[1][1+ linesize[1]] = info->v1_codebook[v1_vector*entry_size+4]; + + data[2][0] = + data[2][1] = + data[2][ linesize[2]] = + data[2][1+ linesize[2]] = info->v1_codebook[v1_vector*entry_size+5]; } } -//decodes the V4 vectors in mb into the 4x4 MB pointed to by sub_pict -static void decode_v4_vector(CinepakEncContext *s, AVPicture *sub_pict, int *v4_vector, strip_info *info) +//decodes the V4 vectors in mb into the 4x4 MB pointed to by data +static void decode_v4_vector(CinepakEncContext *s, uint8_t *data[4], + int linesize[4], int *v4_vector, strip_info *info) { int i, x, y, entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; for(i = y = 0; y < 4; y += 2) { for(x = 0; x < 4; x += 2, i++) { - sub_pict->data[0][x + y*sub_pict->linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size]; - sub_pict->data[0][x+1 + y*sub_pict->linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+1]; - sub_pict->data[0][x + (y+1)*sub_pict->linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+2]; - sub_pict->data[0][x+1 + (y+1)*sub_pict->linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+3]; + data[0][x + y*linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size]; + data[0][x+1 + y*linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+1]; + data[0][x + (y+1)*linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+2]; + data[0][x+1 + (y+1)*linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+3]; if(s->pix_fmt == AV_PIX_FMT_RGB24) { - sub_pict->data[1][(x>>1) + (y>>1)*sub_pict->linesize[1]] = info->v4_codebook[v4_vector[i]*entry_size+4]; - sub_pict->data[2][(x>>1) + (y>>1)*sub_pict->linesize[2]] = info->v4_codebook[v4_vector[i]*entry_size+5]; + data[1][(x>>1) + (y>>1)*linesize[1]] = info->v4_codebook[v4_vector[i]*entry_size+4]; + data[2][(x>>1) + (y>>1)*linesize[2]] = info->v4_codebook[v4_vector[i]*entry_size+5]; } } } } -static void copy_mb(CinepakEncContext *s, AVPicture *a, AVPicture *b) +static void copy_mb(CinepakEncContext *s, + uint8_t *a_data[4], int a_linesize[4], + uint8_t *b_data[4], int b_linesize[4]) { int y, p; for(y = 0; y < MB_SIZE; y++) { - memcpy(a->data[0]+y*a->linesize[0], b->data[0]+y*b->linesize[0], + memcpy(a_data[0]+y*a_linesize[0], b_data[0]+y*b_linesize[0], MB_SIZE); } if(s->pix_fmt == AV_PIX_FMT_RGB24) { for(p = 1; p <= 2; p++) { for(y = 0; y < MB_SIZE/2; y++) { - memcpy(a->data[p] + y*a->linesize[p], - b->data[p] + y*b->linesize[p], + memcpy(a_data[p] + y*a_linesize[p], + b_data[p] + y*b_linesize[p], MB_SIZE/2); } } } } -static int encode_mode(CinepakEncContext *s, int h, AVPicture *scratch_pict, AVPicture *last_pict, strip_info *info, unsigned char *buf) +static int encode_mode(CinepakEncContext *s, int h, + uint8_t *scratch_data[4], int scratch_linesize[4], + uint8_t *last_data[4], int last_linesize[4], + strip_info *info, unsigned char *buf) { int x, y, z, flags, bits, temp_size, header_ofs, ret = 0, mb_count = s->w * h / MB_AREA; int needs_extra_bit, should_write_temp; unsigned char temp[64]; //32/2 = 16 V4 blocks at 4 B each -> 64 B mb_info *mb; - AVPicture sub_scratch, sub_last; + uint8_t *sub_scratch_data[4] = {0}, *sub_last_data[4] = {0}; + int sub_scratch_linesize[4] = {0}, sub_last_linesize[4] = {0}; //encode codebooks ////// MacOS vintage decoder compatibility dictates the presence of @@ -544,15 +554,21 @@ static int encode_mode(CinepakEncContext *s, int h, AVPicture *scratch_pict, AVP for(x = 0; x < s->w; x += MB_SIZE, z++) { mb = &s->mb[z]; - get_sub_picture(s, x, y, scratch_pict, &sub_scratch); + get_sub_picture(s, x, y, scratch_data, scratch_linesize, + sub_scratch_data, sub_scratch_linesize); if(info->mode == MODE_MC && mb->best_encoding == ENC_SKIP) { - get_sub_picture(s, x, y, last_pict, &sub_last); - copy_mb(s, &sub_scratch, &sub_last); + get_sub_picture(s, x, y, + last_data, last_linesize, + sub_last_data, sub_last_linesize); + copy_mb(s, sub_scratch_data, sub_scratch_linesize, + sub_last_data, sub_last_linesize); } else if(info->mode == MODE_V1_ONLY || mb->best_encoding == ENC_V1) - decode_v1_vector(s, &sub_scratch, mb->v1_vector, info); + decode_v1_vector(s, sub_scratch_data, sub_scratch_linesize, + mb->v1_vector, info); else - decode_v4_vector(s, &sub_scratch, mb->v4_vector, info); + decode_v4_vector(s, sub_scratch_data, sub_scratch_linesize, + mb->v4_vector, info); } } @@ -659,13 +675,15 @@ static int encode_mode(CinepakEncContext *s, int h, AVPicture *scratch_pict, AVP } //computes distortion of 4x4 MB in b compared to a -static int compute_mb_distortion(CinepakEncContext *s, AVPicture *a, AVPicture *b) +static int compute_mb_distortion(CinepakEncContext *s, + uint8_t *a_data[4], int a_linesize[4], + uint8_t *b_data[4], int b_linesize[4]) { int x, y, p, d, ret = 0; for(y = 0; y < MB_SIZE; y++) { for(x = 0; x < MB_SIZE; x++) { - d = a->data[0][x + y*a->linesize[0]] - b->data[0][x + y*b->linesize[0]]; + d = a_data[0][x + y*a_linesize[0]] - b_data[0][x + y*b_linesize[0]]; ret += d*d; } } @@ -674,7 +692,7 @@ static int compute_mb_distortion(CinepakEncContext *s, AVPicture *a, AVPicture * for(p = 1; p <= 2; p++) { for(y = 0; y < MB_SIZE/2; y++) { for(x = 0; x < MB_SIZE/2; x++) { - d = a->data[p][x + y*a->linesize[p]] - b->data[p][x + y*b->linesize[p]]; + d = a_data[p][x + y*a_linesize[p]] - b_data[p][x + y*b_linesize[p]]; ret += d*d; } } @@ -686,7 +704,8 @@ static int compute_mb_distortion(CinepakEncContext *s, AVPicture *a, AVPicture * // return the possibly adjusted size of the codebook #define CERTAIN(x) ((x)!=ENC_UNCERTAIN) -static int quantize(CinepakEncContext *s, int h, AVPicture *pict, +static int quantize(CinepakEncContext *s, int h, + uint8_t *data[4], int linesize[4], int v1mode, strip_info *info, mb_encoding encoding) { @@ -696,7 +715,8 @@ static int quantize(CinepakEncContext *s, int h, AVPicture *pict, int size = v1mode ? info->v1_size : info->v4_size; int64_t total_error = 0; uint8_t vq_pict_buf[(MB_AREA*3)/2]; - AVPicture sub_pict, vq_pict; + uint8_t *sub_data [4], *vq_data [4]; + int sub_linesize[4], vq_linesize[4]; for(mbn = i = y = 0; y < h; y += MB_SIZE) { for(x = 0; x < s->w; x += MB_SIZE, ++mbn) { @@ -716,10 +736,10 @@ static int quantize(CinepakEncContext *s, int h, AVPicture *pict, shift = y2 < 4 ? 0 : 1; x3 = shift ? 0 : x2; y3 = shift ? 0 : y2; - base[j] = (pict->data[plane][((x+x3) >> shift) + ((y+y3) >> shift) * pict->linesize[plane]] + - pict->data[plane][((x+x3) >> shift) + 1 + ((y+y3) >> shift) * pict->linesize[plane]] + - pict->data[plane][((x+x3) >> shift) + (((y+y3) >> shift) + 1) * pict->linesize[plane]] + - pict->data[plane][((x+x3) >> shift) + 1 + (((y+y3) >> shift) + 1) * pict->linesize[plane]]) >> 2; + base[j] = (data[plane][((x+x3) >> shift) + ((y+y3) >> shift) * linesize[plane]] + + data[plane][((x+x3) >> shift) + 1 + ((y+y3) >> shift) * linesize[plane]] + + data[plane][((x+x3) >> shift) + (((y+y3) >> shift) + 1) * linesize[plane]] + + data[plane][((x+x3) >> shift) + 1 + (((y+y3) >> shift) + 1) * linesize[plane]]) >> 2; } } } else { @@ -737,7 +757,7 @@ static int quantize(CinepakEncContext *s, int h, AVPicture *pict, y3 = y + y2 + (k >> 1); } - base[j] = pict->data[plane][x3 + y3*pict->linesize[plane]]; + base[j] = data[plane][x3 + y3*linesize[plane]]; } } } @@ -754,12 +774,12 @@ static int quantize(CinepakEncContext *s, int h, AVPicture *pict, ff_init_elbg(s->codebook_input, entry_size, i, codebook, size, 1, s->codebook_closest, &s->randctx); ff_do_elbg(s->codebook_input, entry_size, i, codebook, size, 1, s->codebook_closest, &s->randctx); - //setup vq_pict, which contains a single MB - vq_pict.data[0] = vq_pict_buf; - vq_pict.linesize[0] = MB_SIZE; - vq_pict.data[1] = &vq_pict_buf[MB_AREA]; - vq_pict.data[2] = vq_pict.data[1] + (MB_AREA >> 2); - vq_pict.linesize[1] = vq_pict.linesize[2] = MB_SIZE >> 1; + //setup vq_data, which contains a single MB + vq_data[0] = vq_pict_buf; + vq_linesize[0] = MB_SIZE; + vq_data[1] = &vq_pict_buf[MB_AREA]; + vq_data[2] = vq_data[1] + (MB_AREA >> 2); + vq_linesize[1] = vq_linesize[2] = MB_SIZE >> 1; //copy indices for(i = j = y = 0; y < h; y += MB_SIZE) { @@ -769,25 +789,27 @@ static int quantize(CinepakEncContext *s, int h, AVPicture *pict, if(CERTAIN(encoding) && mb->best_encoding != encoding) continue; - //point sub_pict to current MB - get_sub_picture(s, x, y, pict, &sub_pict); + //point sub_data to current MB + get_sub_picture(s, x, y, data, linesize, sub_data, sub_linesize); if(v1mode) { mb->v1_vector = s->codebook_closest[i]; - //fill in vq_pict with V1 data - decode_v1_vector(s, &vq_pict, mb->v1_vector, info); + //fill in vq_data with V1 data + decode_v1_vector(s, vq_data, vq_linesize, mb->v1_vector, info); - mb->v1_error = compute_mb_distortion(s, &sub_pict, &vq_pict); + mb->v1_error = compute_mb_distortion(s, sub_data, sub_linesize, + vq_data, vq_linesize); total_error += mb->v1_error; } else { for(k = 0; k < 4; k++) mb->v4_vector[k] = s->codebook_closest[i+k]; - //fill in vq_pict with V4 data - decode_v4_vector(s, &vq_pict, mb->v4_vector, info); + //fill in vq_data with V4 data + decode_v4_vector(s, vq_data, vq_linesize, mb->v4_vector, info); - mb->v4_error = compute_mb_distortion(s, &sub_pict, &vq_pict); + mb->v4_error = compute_mb_distortion(s, sub_data, sub_linesize, + vq_data, vq_linesize); total_error += mb->v4_error; } i += v1mode ? 1 : 4; @@ -799,17 +821,25 @@ static int quantize(CinepakEncContext *s, int h, AVPicture *pict, return size; } -static void calculate_skip_errors(CinepakEncContext *s, int h, AVPicture *last_pict, AVPicture *pict, strip_info *info) +static void calculate_skip_errors(CinepakEncContext *s, int h, + uint8_t *last_data[4], int last_linesize[4], + uint8_t *data[4], int linesize[4], + strip_info *info) { int x, y, i; - AVPicture sub_last, sub_pict; + uint8_t *sub_last_data [4], *sub_pict_data [4]; + int sub_last_linesize[4], sub_pict_linesize[4]; for(i = y = 0; y < h; y += MB_SIZE) { for(x = 0; x < s->w; x += MB_SIZE, i++) { - get_sub_picture(s, x, y, last_pict, &sub_last); - get_sub_picture(s, x, y, pict, &sub_pict); - - s->mb[i].skip_error = compute_mb_distortion(s, &sub_last, &sub_pict); + get_sub_picture(s, x, y, last_data, last_linesize, + sub_last_data, sub_last_linesize); + get_sub_picture(s, x, y, data, linesize, + sub_pict_data, sub_pict_linesize); + + s->mb[i].skip_error = compute_mb_distortion(s, + sub_last_data, sub_last_linesize, + sub_pict_data, sub_pict_linesize); } } } @@ -831,7 +861,11 @@ static void write_strip_header(CinepakEncContext *s, int y, int h, int keyframe, AV_WB16(&buf[10], s->w); } -static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture *last_pict, AVPicture *pict, AVPicture *scratch_pict, unsigned char *buf, int64_t *best_score) +static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, + uint8_t *last_data[4], int last_linesize[4], + uint8_t *data[4], int linesize[4], + uint8_t *scratch_data[4], int scratch_linesize[4], + unsigned char *buf, int64_t *best_score) { int64_t score = 0; int best_size = 0; @@ -842,7 +876,8 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture int v1shrunk, v4shrunk; if(!keyframe) - calculate_skip_errors(s, h, last_pict, pict, &info); + calculate_skip_errors(s, h, last_data, last_linesize, data, linesize, + &info); //try some powers of 4 for the size of the codebooks //constraint the v4 codebook to be no bigger than v1 one, @@ -860,7 +895,8 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture if(mode == MODE_V1_ONLY) { info.v1_size = v1_size; // the size may shrink even before optimizations if the input is short: - info.v1_size = quantize(s, h, pict, 1, &info, ENC_UNCERTAIN); + info.v1_size = quantize(s, h, data, linesize, 1, + &info, ENC_UNCERTAIN); if(info.v1_size < v1_size) // too few eligible blocks, no sense in trying bigger sizes v1enough = 1; @@ -873,7 +909,8 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture if(mode == MODE_V1_V4) { info.v4_size = v4_size; - info.v4_size = quantize(s, h, pict, 0, &info, ENC_UNCERTAIN); + info.v4_size = quantize(s, h, data, linesize, 0, + &info, ENC_UNCERTAIN); if(info.v4_size < v4_size) // too few eligible blocks, no sense in trying bigger sizes v4enough = 1; @@ -890,12 +927,12 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture // recompute the codebooks, omitting the extra blocks // we assume we _may_ come here with more blocks to encode than before info.v1_size = v1_size; - new_v1_size = quantize(s, h, pict, 1, &info, ENC_V1); + new_v1_size = quantize(s, h, data, linesize, 1, &info, ENC_V1); if (new_v1_size < info.v1_size) info.v1_size = new_v1_size; // we assume we _may_ come here with more blocks to encode than before info.v4_size = v4_size; - new_v4_size = quantize(s, h, pict, 0, &info, ENC_V4); + new_v4_size = quantize(s, h, data, linesize, 0, &info, ENC_V4); if (new_v4_size < info.v4_size) info.v4_size = new_v4_size; // calculate the resulting score @@ -910,13 +947,13 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture // recompute the codebooks, omitting the extra blocks if(v1shrunk) { info.v1_size = v1_size; - new_v1_size = quantize(s, h, pict, 1, &info, ENC_V1); + new_v1_size = quantize(s, h, data, linesize, 1, &info, ENC_V1); if (new_v1_size < info.v1_size) info.v1_size = new_v1_size; } if(v4shrunk) { info.v4_size = v4_size; - new_v4_size = quantize(s, h, pict, 0, &info, ENC_V4); + new_v4_size = quantize(s, h, data, linesize, 0, &info, ENC_V4); if (new_v4_size < info.v4_size) info.v4_size = new_v4_size; } @@ -926,7 +963,11 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, AVPicture if(best_size == 0 || score < *best_score) { *best_score = score; - best_size = encode_mode(s, h, scratch_pict, last_pict, &info, s->strip_buf + STRIP_HEADER_SIZE); + best_size = encode_mode(s, h, + scratch_data, scratch_linesize, + last_data, last_linesize, &info, + s->strip_buf + STRIP_HEADER_SIZE); + write_strip_header(s, y, h, keyframe, s->strip_buf, best_size); } @@ -951,10 +992,12 @@ static int write_cvid_header(CinepakEncContext *s, unsigned char *buf, int num_s return CVID_HEADER_SIZE; } -static int rd_frame(CinepakEncContext *s, const AVFrame *frame, int isakeyframe, unsigned char *buf, int buf_size) +static int rd_frame(CinepakEncContext *s, const AVFrame *frame, + int isakeyframe, unsigned char *buf, int buf_size) { int num_strips, strip, i, y, nexty, size, temp_size, best_size; - AVPicture last_pict, pict, scratch_pict; + uint8_t *last_data [4], *data [4], *scratch_data [4]; + int last_linesize[4], linesize[4], scratch_linesize[4]; int64_t best_score = 0, score, score_temp; int best_nstrips; @@ -964,9 +1007,11 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, int isakeyframe, for(y = 0; y < s->h; y += 2) { for(x = 0; x < s->w; x += 2) { uint8_t *ir[2]; int32_t r, g, b, rr, gg, bb; - ir[0] = ((AVPicture*)frame)->data[0] + x*3 + y*((AVPicture*)frame)->linesize[0]; - ir[1] = ir[0] + ((AVPicture*)frame)->linesize[0]; - get_sub_picture(s, x, y, (AVPicture*)s->input_frame, &scratch_pict); + ir[0] = frame->data[0] + x*3 + y*frame->linesize[0]; + ir[1] = ir[0] + frame->linesize[0]; + get_sub_picture(s, x, y, + s->input_frame->data, s->input_frame->linesize, + scratch_data, scratch_linesize); r = g = b = 0; for(i=0; i<4; ++i) { int i1, i2; @@ -981,7 +1026,7 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, int isakeyframe, rr = (2396625*rr + 4793251*gg + 1198732*bb) >> 23; if( rr < 0) rr = 0; else if (rr > 255) rr = 255; - scratch_pict.data[0][i1 + i2*scratch_pict.linesize[0]] = rr; + scratch_data[0][i1 + i2*scratch_linesize[0]] = rr; } // let us scale down as late as possible // r /= 4; g /= 4; b /= 4; @@ -990,13 +1035,13 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, int isakeyframe, rr = (-299683*r - 599156*g + 898839*b) >> 23; if( rr < -128) rr = -128; else if (rr > 127) rr = 127; - scratch_pict.data[1][0] = rr + 128; // quantize needs unsigned + scratch_data[1][0] = rr + 128; // quantize needs unsigned // "V" // rr = 0.3571*r - 0.2857*g - 0.0714*b; rr = (748893*r - 599156*g - 149737*b) >> 23; if( rr < -128) rr = -128; else if (rr > 127) rr = 127; - scratch_pict.data[2][0] = rr + 128; // quantize needs unsigned + scratch_data[2][0] = rr + 128; // quantize needs unsigned } } } @@ -1022,13 +1067,24 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, int isakeyframe, } if(s->pix_fmt == AV_PIX_FMT_RGB24) - get_sub_picture(s, 0, y, (AVPicture*)s->input_frame, &pict); + get_sub_picture(s, 0, y, + s->input_frame->data, s->input_frame->linesize, + data, linesize); else - get_sub_picture(s, 0, y, (AVPicture*)frame, &pict); - get_sub_picture(s, 0, y, (AVPicture*)s->last_frame, &last_pict); - get_sub_picture(s, 0, y, (AVPicture*)s->scratch_frame, &scratch_pict); - - if((temp_size = rd_strip(s, y, strip_height, isakeyframe, &last_pict, &pict, &scratch_pict, s->frame_buf + size + CVID_HEADER_SIZE, &score_temp)) < 0) + get_sub_picture(s, 0, y, + (uint8_t **)frame->data, (int*)frame->linesize, + data, linesize); + get_sub_picture(s, 0, y, + s->last_frame->data, s->last_frame->linesize, + last_data, last_linesize); + get_sub_picture(s, 0, y, + s->scratch_frame->data, s->scratch_frame->linesize, + scratch_data, scratch_linesize); + + if((temp_size = rd_strip(s, y, strip_height, isakeyframe, + last_data, last_linesize, data, linesize, + scratch_data, scratch_linesize, + s->frame_buf + size + CVID_HEADER_SIZE, &score_temp)) < 0) return temp_size; score += score_temp; From 47cde2eabc1ae21b03a4cde52affeb516b60f3f3 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 28 Jun 2017 00:27:17 +0200 Subject: [PATCH 0306/2557] cinepakenc: K&R formatting cosmetics --- libavcodec/cinepakenc.c | 871 ++++++++++++++++++++-------------------- 1 file changed, 444 insertions(+), 427 deletions(-) diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index 674d0298dcc8d..51f79a43c3554 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -4,25 +4,27 @@ * * Fixes and improvements, vintage decoders compatibility * (c) 2013, 2014 Rl, Aetey Global Technologies AB + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - +/* * TODO: * - optimize: color space conversion (move conversion to libswscale), ... * MAYBE: @@ -34,30 +36,29 @@ OTHER DEALINGS IN THE SOFTWARE. #include +#include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/lfg.h" #include "libavutil/opt.h" #include "avcodec.h" -#include "libavutil/lfg.h" #include "elbg.h" #include "internal.h" -#include "libavutil/avassert.h" - #define CVID_HEADER_SIZE 10 #define STRIP_HEADER_SIZE 12 #define CHUNK_HEADER_SIZE 4 #define MB_SIZE 4 //4x4 MBs -#define MB_AREA (MB_SIZE*MB_SIZE) +#define MB_AREA (MB_SIZE * MB_SIZE) -#define VECTOR_MAX 6 //six or four entries per vector depending on format -#define CODEBOOK_MAX 256 //size of a codebook +#define VECTOR_MAX 6 // six or four entries per vector depending on format +#define CODEBOOK_MAX 256 // size of a codebook -#define MAX_STRIPS 32 //Note: having fewer choices regarding the number of strips speeds up encoding (obviously) -#define MIN_STRIPS 1 //Note: having more strips speeds up encoding the frame (this is less obvious) +#define MAX_STRIPS 32 // Note: having fewer choices regarding the number of strips speeds up encoding (obviously) +#define MIN_STRIPS 1 // Note: having more strips speeds up encoding the frame (this is less obvious) // MAX_STRIPS limits the maximum quality you can reach // when you want high quality on high resolutions, // MIN_STRIPS limits the minimum efficiently encodable bit rate @@ -84,17 +85,17 @@ typedef enum { } mb_encoding; typedef struct { - int v1_vector; //index into v1 codebook - int v1_error; //error when using V1 encoding - int v4_vector[4]; //indices into v4 codebook - int v4_error; //error when using V4 encoding - int skip_error; //error when block is skipped (aka copied from last frame) - mb_encoding best_encoding; //last result from calculate_mode_score() + int v1_vector; // index into v1 codebook + int v1_error; // error when using V1 encoding + int v4_vector[4]; // indices into v4 codebook + int v4_error; // error when using V4 encoding + int skip_error; // error when block is skipped (aka copied from last frame) + mb_encoding best_encoding; // last result from calculate_mode_score() } mb_info; typedef struct { - int v1_codebook[CODEBOOK_MAX*VECTOR_MAX]; - int v4_codebook[CODEBOOK_MAX*VECTOR_MAX]; + int v1_codebook[CODEBOOK_MAX * VECTOR_MAX]; + int v4_codebook[CODEBOOK_MAX * VECTOR_MAX]; int v1_size; int v4_size; CinepakMode mode; @@ -116,10 +117,10 @@ typedef struct { uint64_t lambda; int *codebook_input; int *codebook_closest; - mb_info *mb; //MB RD state - int min_strips; //the current limit - int max_strips; //the current limit -// options + mb_info *mb; // MB RD state + int min_strips; // the current limit + int max_strips; // the current limit + // options int max_extra_cb_iterations; int skip_empty_cb; int min_min_strips; @@ -130,11 +131,16 @@ typedef struct { #define OFFSET(x) offsetof(CinepakEncContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "max_extra_cb_iterations", "Max extra codebook recalculation passes, more is better and slower", OFFSET(max_extra_cb_iterations), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, INT_MAX, VE }, - { "skip_empty_cb", "Avoid wasting bytes, ignore vintage MacOS decoder", OFFSET(skip_empty_cb), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, - { "max_strips", "Limit strips/frame, vintage compatible is 1..3, otherwise the more the better", OFFSET(max_max_strips), AV_OPT_TYPE_INT, { .i64 = 3 }, MIN_STRIPS, MAX_STRIPS, VE }, - { "min_strips", "Enforce min strips/frame, more is worse and faster, must be <= max_strips", OFFSET(min_min_strips), AV_OPT_TYPE_INT, { .i64 = MIN_STRIPS }, MIN_STRIPS, MAX_STRIPS, VE }, - { "strip_number_adaptivity", "How fast the strip number adapts, more is slightly better, much slower", OFFSET(strip_number_delta_range), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_STRIPS-MIN_STRIPS, VE }, + { "max_extra_cb_iterations", "Max extra codebook recalculation passes, more is better and slower", + OFFSET(max_extra_cb_iterations), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, INT_MAX, VE }, + { "skip_empty_cb", "Avoid wasting bytes, ignore vintage MacOS decoder", + OFFSET(skip_empty_cb), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "max_strips", "Limit strips/frame, vintage compatible is 1..3, otherwise the more the better", + OFFSET(max_max_strips), AV_OPT_TYPE_INT, { .i64 = 3 }, MIN_STRIPS, MAX_STRIPS, VE }, + { "min_strips", "Enforce min strips/frame, more is worse and faster, must be <= max_strips", + OFFSET(min_min_strips), AV_OPT_TYPE_INT, { .i64 = MIN_STRIPS }, MIN_STRIPS, MAX_STRIPS, VE }, + { "strip_number_adaptivity", "How fast the strip number adapts, more is slightly better, much slower", + OFFSET(strip_number_delta_range), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_STRIPS - MIN_STRIPS, VE }, { NULL }, }; @@ -152,13 +158,13 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) if (avctx->width & 3 || avctx->height & 3) { av_log(avctx, AV_LOG_ERROR, "width and height must be multiples of four (got %ix%i)\n", - avctx->width, avctx->height); + avctx->width, avctx->height); return AVERROR(EINVAL); } if (s->min_min_strips > s->max_max_strips) { av_log(avctx, AV_LOG_ERROR, "minimal number of strips can not exceed maximal (got %i and %i)\n", - s->min_min_strips, s->max_max_strips); + s->min_min_strips, s->max_max_strips); return AVERROR(EINVAL); } @@ -178,17 +184,17 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) if (!(s->codebook_closest = av_malloc(sizeof(int) * (avctx->width * avctx->height) >> 2))) goto enomem; - for(x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) - if(!(s->pict_bufs[x] = av_malloc((avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4) * (avctx->width * avctx->height) >> 2))) + for (x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) + if (!(s->pict_bufs[x] = av_malloc((avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4) * (avctx->width * avctx->height) >> 2))) goto enomem; mb_count = avctx->width * avctx->height / MB_AREA; - //the largest possible chunk is 0x31 with all MBs encoded in V4 mode - //and full codebooks being replaced in INTER mode, + // the largest possible chunk is 0x31 with all MBs encoded in V4 mode + // and full codebooks being replaced in INTER mode, // which is 34 bits per MB - //and 2*256 extra flag bits per strip - strip_buf_size = STRIP_HEADER_SIZE + 3 * CHUNK_HEADER_SIZE + 2 * VECTOR_MAX * CODEBOOK_MAX + 4 * (mb_count + (mb_count + 15) / 16) + (2 * CODEBOOK_MAX)/8; + // and 2*256 extra flag bits per strip + strip_buf_size = STRIP_HEADER_SIZE + 3 * CHUNK_HEADER_SIZE + 2 * VECTOR_MAX * CODEBOOK_MAX + 4 * (mb_count + (mb_count + 15) / 16) + (2 * CODEBOOK_MAX) / 8; frame_buf_size = CVID_HEADER_SIZE + s->max_max_strips * strip_buf_size; @@ -198,19 +204,19 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) if (!(s->frame_buf = av_malloc(frame_buf_size))) goto enomem; - if (!(s->mb = av_malloc(mb_count*sizeof(mb_info)))) + if (!(s->mb = av_malloc(mb_count * sizeof(mb_info)))) goto enomem; av_lfg_init(&s->randctx, 1); - s->avctx = avctx; - s->w = avctx->width; - s->h = avctx->height; + s->avctx = avctx; + s->w = avctx->width; + s->h = avctx->height; s->frame_buf_size = frame_buf_size; - s->curframe = 0; - s->keyint = avctx->keyint_min; - s->pix_fmt = avctx->pix_fmt; + s->curframe = 0; + s->keyint = avctx->keyint_min; + s->pix_fmt = avctx->pix_fmt; - //set up AVFrames + // set up AVFrames s->last_frame->data[0] = s->pict_bufs[0]; s->last_frame->linesize[0] = s->w; s->best_frame->data[0] = s->pict_bufs[1]; @@ -219,23 +225,27 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) s->scratch_frame->linesize[0] = s->w; if (s->pix_fmt == AV_PIX_FMT_RGB24) { - s->last_frame->data[1] = s->last_frame->data[0] + s->w * s->h; - s->last_frame->data[2] = s->last_frame->data[1] + ((s->w * s->h) >> 2); - s->last_frame->linesize[1] = s->last_frame->linesize[2] = s->w >> 1; + s->last_frame->data[1] = s->last_frame->data[0] + s->w * s->h; + s->last_frame->data[2] = s->last_frame->data[1] + ((s->w * s->h) >> 2); + s->last_frame->linesize[1] = + s->last_frame->linesize[2] = s->w >> 1; - s->best_frame->data[1] = s->best_frame->data[0] + s->w * s->h; - s->best_frame->data[2] = s->best_frame->data[1] + ((s->w * s->h) >> 2); - s->best_frame->linesize[1] = s->best_frame->linesize[2] = s->w >> 1; + s->best_frame->data[1] = s->best_frame->data[0] + s->w * s->h; + s->best_frame->data[2] = s->best_frame->data[1] + ((s->w * s->h) >> 2); + s->best_frame->linesize[1] = + s->best_frame->linesize[2] = s->w >> 1; - s->scratch_frame->data[1] = s->scratch_frame->data[0] + s->w * s->h; + s->scratch_frame->data[1] = s->scratch_frame->data[0] + s->w * s->h; s->scratch_frame->data[2] = s->scratch_frame->data[1] + ((s->w * s->h) >> 2); - s->scratch_frame->linesize[1] = s->scratch_frame->linesize[2] = s->w >> 1; - - s->input_frame->data[0] = s->pict_bufs[3]; - s->input_frame->linesize[0] = s->w; - s->input_frame->data[1] = s->input_frame->data[0] + s->w * s->h; - s->input_frame->data[2] = s->input_frame->data[1] + ((s->w * s->h) >> 2); - s->input_frame->linesize[1] = s->input_frame->linesize[2] = s->w >> 1; + s->scratch_frame->linesize[1] = + s->scratch_frame->linesize[2] = s->w >> 1; + + s->input_frame->data[0] = s->pict_bufs[3]; + s->input_frame->linesize[0] = s->w; + s->input_frame->data[1] = s->input_frame->data[0] + s->w * s->h; + s->input_frame->data[2] = s->input_frame->data[1] + ((s->w * s->h) >> 2); + s->input_frame->linesize[1] = + s->input_frame->linesize[2] = s->w >> 1; } s->min_strips = s->min_min_strips; @@ -255,60 +265,63 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) av_freep(&s->frame_buf); av_freep(&s->mb); - for(x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) + for (x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) av_freep(&s->pict_bufs[x]); return AVERROR(ENOMEM); } -static int64_t calculate_mode_score(CinepakEncContext *s, int h, strip_info *info, int report, int *training_set_v1_shrunk, int *training_set_v4_shrunk) +static int64_t calculate_mode_score(CinepakEncContext *s, int h, + strip_info *info, int report, + int *training_set_v1_shrunk, + int *training_set_v4_shrunk) { - //score = FF_LAMBDA_SCALE * error + lambda * bits + // score = FF_LAMBDA_SCALE * error + lambda * bits int x; int entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; - int mb_count = s->w * h / MB_AREA; + int mb_count = s->w * h / MB_AREA; mb_info *mb; int64_t score1, score2, score3; int64_t ret = s->lambda * ((info->v1_size ? CHUNK_HEADER_SIZE + info->v1_size * entry_size : 0) + - (info->v4_size ? CHUNK_HEADER_SIZE + info->v4_size * entry_size : 0) + - CHUNK_HEADER_SIZE) << 3; + (info->v4_size ? CHUNK_HEADER_SIZE + info->v4_size * entry_size : 0) + + CHUNK_HEADER_SIZE) << 3; - switch(info->mode) { + switch (info->mode) { case MODE_V1_ONLY: - //one byte per MB + // one byte per MB ret += s->lambda * 8 * mb_count; -// while calculating we assume all blocks are ENC_V1 - for(x = 0; x < mb_count; x++) { - mb = &s->mb[x]; + // while calculating we assume all blocks are ENC_V1 + for (x = 0; x < mb_count; x++) { + mb = &s->mb[x]; ret += FF_LAMBDA_SCALE * mb->v1_error; -// this function is never called for report in MODE_V1_ONLY -// if(!report) + // this function is never called for report in MODE_V1_ONLY + // if (!report) mb->best_encoding = ENC_V1; } break; case MODE_V1_V4: - //9 or 33 bits per MB - if(report) { -// no moves between the corresponding training sets are allowed + // 9 or 33 bits per MB + if (report) { + // no moves between the corresponding training sets are allowed *training_set_v1_shrunk = *training_set_v4_shrunk = 0; - for(x = 0; x < mb_count; x++) { + for (x = 0; x < mb_count; x++) { int mberr; mb = &s->mb[x]; - if(mb->best_encoding == ENC_V1) - score1 = s->lambda * 9 + FF_LAMBDA_SCALE * (mberr=mb->v1_error); + if (mb->best_encoding == ENC_V1) + score1 = s->lambda * 9 + FF_LAMBDA_SCALE * (mberr = mb->v1_error); else - score1 = s->lambda * 33 + FF_LAMBDA_SCALE * (mberr=mb->v4_error); + score1 = s->lambda * 33 + FF_LAMBDA_SCALE * (mberr = mb->v4_error); ret += score1; } } else { // find best mode per block - for(x = 0; x < mb_count; x++) { - mb = &s->mb[x]; - score1 = s->lambda * 9 + FF_LAMBDA_SCALE * mb->v1_error; + for (x = 0; x < mb_count; x++) { + mb = &s->mb[x]; + score1 = s->lambda * 9 + FF_LAMBDA_SCALE * mb->v1_error; score2 = s->lambda * 33 + FF_LAMBDA_SCALE * mb->v4_error; - if(score1 <= score2) { + if (score1 <= score2) { ret += score1; mb->best_encoding = ENC_V1; } else { @@ -320,18 +333,18 @@ static int64_t calculate_mode_score(CinepakEncContext *s, int h, strip_info *inf break; case MODE_MC: - //1, 10 or 34 bits per MB - if(report) { + // 1, 10 or 34 bits per MB + if (report) { int v1_shrunk = 0, v4_shrunk = 0; - for(x = 0; x < mb_count; x++) { + for (x = 0; x < mb_count; x++) { mb = &s->mb[x]; -// it is OK to move blocks to ENC_SKIP here -// but not to any codebook encoding! - score1 = s->lambda * 1 + FF_LAMBDA_SCALE * mb->skip_error; - if(mb->best_encoding == ENC_SKIP) { + // it is OK to move blocks to ENC_SKIP here + // but not to any codebook encoding! + score1 = s->lambda * 1 + FF_LAMBDA_SCALE * mb->skip_error; + if (mb->best_encoding == ENC_SKIP) { ret += score1; - } else if(mb->best_encoding == ENC_V1) { - if((score2=s->lambda * 10 + FF_LAMBDA_SCALE * mb->v1_error) >= score1) { + } else if (mb->best_encoding == ENC_V1) { + if ((score2 = s->lambda * 10 + FF_LAMBDA_SCALE * mb->v1_error) >= score1) { mb->best_encoding = ENC_SKIP; ++v1_shrunk; ret += score1; @@ -339,7 +352,7 @@ static int64_t calculate_mode_score(CinepakEncContext *s, int h, strip_info *inf ret += score2; } } else { - if((score3=s->lambda * 34 + FF_LAMBDA_SCALE * mb->v4_error) >= score1) { + if ((score3 = s->lambda * 34 + FF_LAMBDA_SCALE * mb->v4_error) >= score1) { mb->best_encoding = ENC_SKIP; ++v4_shrunk; ret += score1; @@ -351,16 +364,16 @@ static int64_t calculate_mode_score(CinepakEncContext *s, int h, strip_info *inf *training_set_v1_shrunk = v1_shrunk; *training_set_v4_shrunk = v4_shrunk; } else { // find best mode per block - for(x = 0; x < mb_count; x++) { - mb = &s->mb[x]; - score1 = s->lambda * 1 + FF_LAMBDA_SCALE * mb->skip_error; + for (x = 0; x < mb_count; x++) { + mb = &s->mb[x]; + score1 = s->lambda * 1 + FF_LAMBDA_SCALE * mb->skip_error; score2 = s->lambda * 10 + FF_LAMBDA_SCALE * mb->v1_error; score3 = s->lambda * 34 + FF_LAMBDA_SCALE * mb->v4_error; - if(score1 <= score2 && score1 <= score3) { + if (score1 <= score2 && score1 <= score3) { ret += score1; mb->best_encoding = ENC_SKIP; - } else if(score2 <= score3) { + } else if (score2 <= score3) { ret += score2; mb->best_encoding = ENC_V1; } else { @@ -383,123 +396,125 @@ static int write_chunk_header(unsigned char *buf, int chunk_type, int chunk_size return CHUNK_HEADER_SIZE; } -static int encode_codebook(CinepakEncContext *s, int *codebook, int size, int chunk_type_yuv, int chunk_type_gray, unsigned char *buf) +static int encode_codebook(CinepakEncContext *s, int *codebook, int size, + int chunk_type_yuv, int chunk_type_gray, + unsigned char *buf) { int x, y, ret, entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; int incremental_codebook_replacement_mode = 0; // hardcoded here, - // the compiler should notice that this is a constant -- rl + // the compiler should notice that this is a constant -- rl ret = write_chunk_header(buf, - s->pix_fmt == AV_PIX_FMT_RGB24 ? - chunk_type_yuv+(incremental_codebook_replacement_mode?1:0) : - chunk_type_gray+(incremental_codebook_replacement_mode?1:0), - entry_size * size - + (incremental_codebook_replacement_mode?(size+31)/32*4:0) ); - -// we do codebook encoding according to the "intra" mode -// but we keep the "dead" code for reference in case we will want -// to use incremental codebook updates (which actually would give us -// "kind of" motion compensation, especially in 1 strip/frame case) -- rl -// (of course, the code will be not useful as-is) - if(incremental_codebook_replacement_mode) { + s->pix_fmt == AV_PIX_FMT_RGB24 ? + chunk_type_yuv + (incremental_codebook_replacement_mode ? 1 : 0) : + chunk_type_gray + (incremental_codebook_replacement_mode ? 1 : 0), + entry_size * size + + (incremental_codebook_replacement_mode ? (size + 31) / 32 * 4 : 0)); + + // we do codebook encoding according to the "intra" mode + // but we keep the "dead" code for reference in case we will want + // to use incremental codebook updates (which actually would give us + // "kind of" motion compensation, especially in 1 strip/frame case) -- rl + // (of course, the code will be not useful as-is) + if (incremental_codebook_replacement_mode) { int flags = 0; int flagsind; - for(x = 0; x < size; x++) { - if(flags == 0) { + for (x = 0; x < size; x++) { + if (flags == 0) { flagsind = ret; - ret += 4; - flags = 0x80000000; + ret += 4; + flags = 0x80000000; } else - flags = ((flags>>1) | 0x80000000); - for(y = 0; y < entry_size; y++) - buf[ret++] = codebook[y + x*entry_size] ^ (y >= 4 ? 0x80 : 0); - if((flags&0xffffffff) == 0xffffffff) { + flags = ((flags >> 1) | 0x80000000); + for (y = 0; y < entry_size; y++) + buf[ret++] = codebook[y + x * entry_size] ^ (y >= 4 ? 0x80 : 0); + if ((flags & 0xffffffff) == 0xffffffff) { AV_WB32(&buf[flagsind], flags); flags = 0; } } - if(flags) + if (flags) AV_WB32(&buf[flagsind], flags); } else - for(x = 0; x < size; x++) - for(y = 0; y < entry_size; y++) - buf[ret++] = codebook[y + x*entry_size] ^ (y >= 4 ? 0x80 : 0); + for (x = 0; x < size; x++) + for (y = 0; y < entry_size; y++) + buf[ret++] = codebook[y + x * entry_size] ^ (y >= 4 ? 0x80 : 0); return ret; } -//sets out to the sub picture starting at (x,y) in in +// sets out to the sub picture starting at (x,y) in in static void get_sub_picture(CinepakEncContext *s, int x, int y, uint8_t * in_data[4], int in_linesize[4], uint8_t *out_data[4], int out_linesize[4]) { - out_data[0] = in_data[0] + x + y * in_linesize[0]; + out_data[0] = in_data[0] + x + y * in_linesize[0]; out_linesize[0] = in_linesize[0]; - if(s->pix_fmt == AV_PIX_FMT_RGB24) { - out_data[1] = in_data[1] + (x >> 1) + (y >> 1) * in_linesize[1]; + if (s->pix_fmt == AV_PIX_FMT_RGB24) { + out_data[1] = in_data[1] + (x >> 1) + (y >> 1) * in_linesize[1]; out_linesize[1] = in_linesize[1]; - out_data[2] = in_data[2] + (x >> 1) + (y >> 1) * in_linesize[2]; + out_data[2] = in_data[2] + (x >> 1) + (y >> 1) * in_linesize[2]; out_linesize[2] = in_linesize[2]; } } -//decodes the V1 vector in mb into the 4x4 MB pointed to by data +// decodes the V1 vector in mb into the 4x4 MB pointed to by data static void decode_v1_vector(CinepakEncContext *s, uint8_t *data[4], int linesize[4], int v1_vector, strip_info *info) { int entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; data[0][0] = - data[0][1] = - data[0][ linesize[0]] = - data[0][1+ linesize[0]] = info->v1_codebook[v1_vector*entry_size]; + data[0][1] = + data[0][ linesize[0]] = + data[0][1 + linesize[0]] = info->v1_codebook[v1_vector * entry_size]; data[0][2] = - data[0][3] = - data[0][2+ linesize[0]] = - data[0][3+ linesize[0]] = info->v1_codebook[v1_vector*entry_size+1]; + data[0][3] = + data[0][2 + linesize[0]] = + data[0][3 + linesize[0]] = info->v1_codebook[v1_vector * entry_size + 1]; - data[0][2*linesize[0]] = - data[0][1+2*linesize[0]] = - data[0][ 3*linesize[0]] = - data[0][1+3*linesize[0]] = info->v1_codebook[v1_vector*entry_size+2]; + data[0][ 2 * linesize[0]] = + data[0][1 + 2 * linesize[0]] = + data[0][ 3 * linesize[0]] = + data[0][1 + 3 * linesize[0]] = info->v1_codebook[v1_vector * entry_size + 2]; - data[0][2+2*linesize[0]] = - data[0][3+2*linesize[0]] = - data[0][2+3*linesize[0]] = - data[0][3+3*linesize[0]] = info->v1_codebook[v1_vector*entry_size+3]; + data[0][2 + 2 * linesize[0]] = + data[0][3 + 2 * linesize[0]] = + data[0][2 + 3 * linesize[0]] = + data[0][3 + 3 * linesize[0]] = info->v1_codebook[v1_vector * entry_size + 3]; - if(s->pix_fmt == AV_PIX_FMT_RGB24) { + if (s->pix_fmt == AV_PIX_FMT_RGB24) { data[1][0] = - data[1][1] = - data[1][ linesize[1]] = - data[1][1+ linesize[1]] = info->v1_codebook[v1_vector*entry_size+4]; + data[1][1] = + data[1][ linesize[1]] = + data[1][1 + linesize[1]] = info->v1_codebook[v1_vector * entry_size + 4]; data[2][0] = - data[2][1] = - data[2][ linesize[2]] = - data[2][1+ linesize[2]] = info->v1_codebook[v1_vector*entry_size+5]; + data[2][1] = + data[2][ linesize[2]] = + data[2][1 + linesize[2]] = info->v1_codebook[v1_vector * entry_size + 5]; } } -//decodes the V4 vectors in mb into the 4x4 MB pointed to by data +// decodes the V4 vectors in mb into the 4x4 MB pointed to by data static void decode_v4_vector(CinepakEncContext *s, uint8_t *data[4], int linesize[4], int *v4_vector, strip_info *info) { int i, x, y, entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; - for(i = y = 0; y < 4; y += 2) { - for(x = 0; x < 4; x += 2, i++) { - data[0][x + y*linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size]; - data[0][x+1 + y*linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+1]; - data[0][x + (y+1)*linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+2]; - data[0][x+1 + (y+1)*linesize[0]] = info->v4_codebook[v4_vector[i]*entry_size+3]; + for (i = y = 0; y < 4; y += 2) { + for (x = 0; x < 4; x += 2, i++) { + data[0][x + y * linesize[0]] = info->v4_codebook[v4_vector[i] * entry_size]; + data[0][x + 1 + y * linesize[0]] = info->v4_codebook[v4_vector[i] * entry_size + 1]; + data[0][x + (y + 1) * linesize[0]] = info->v4_codebook[v4_vector[i] * entry_size + 2]; + data[0][x + 1 + (y + 1) * linesize[0]] = info->v4_codebook[v4_vector[i] * entry_size + 3]; - if(s->pix_fmt == AV_PIX_FMT_RGB24) { - data[1][(x>>1) + (y>>1)*linesize[1]] = info->v4_codebook[v4_vector[i]*entry_size+4]; - data[2][(x>>1) + (y>>1)*linesize[2]] = info->v4_codebook[v4_vector[i]*entry_size+5]; + if (s->pix_fmt == AV_PIX_FMT_RGB24) { + data[1][(x >> 1) + (y >> 1) * linesize[1]] = info->v4_codebook[v4_vector[i] * entry_size + 4]; + data[2][(x >> 1) + (y >> 1) * linesize[2]] = info->v4_codebook[v4_vector[i] * entry_size + 5]; } } } @@ -511,19 +526,16 @@ static void copy_mb(CinepakEncContext *s, { int y, p; - for(y = 0; y < MB_SIZE; y++) { - memcpy(a_data[0]+y*a_linesize[0], b_data[0]+y*b_linesize[0], + for (y = 0; y < MB_SIZE; y++) + memcpy(a_data[0] + y * a_linesize[0], b_data[0] + y * b_linesize[0], MB_SIZE); - } - if(s->pix_fmt == AV_PIX_FMT_RGB24) { - for(p = 1; p <= 2; p++) { - for(y = 0; y < MB_SIZE/2; y++) { - memcpy(a_data[p] + y*a_linesize[p], - b_data[p] + y*b_linesize[p], - MB_SIZE/2); - } - } + if (s->pix_fmt == AV_PIX_FMT_RGB24) { + for (p = 1; p <= 2; p++) + for (y = 0; y < MB_SIZE / 2; y++) + memcpy(a_data[p] + y * a_linesize[p], + b_data[p] + y * b_linesize[p], + MB_SIZE / 2); } } @@ -534,74 +546,72 @@ static int encode_mode(CinepakEncContext *s, int h, { int x, y, z, flags, bits, temp_size, header_ofs, ret = 0, mb_count = s->w * h / MB_AREA; int needs_extra_bit, should_write_temp; - unsigned char temp[64]; //32/2 = 16 V4 blocks at 4 B each -> 64 B + unsigned char temp[64]; // 32/2 = 16 V4 blocks at 4 B each -> 64 B mb_info *mb; - uint8_t *sub_scratch_data[4] = {0}, *sub_last_data[4] = {0}; - int sub_scratch_linesize[4] = {0}, sub_last_linesize[4] = {0}; - - //encode codebooks -////// MacOS vintage decoder compatibility dictates the presence of -////// the codebook chunk even when the codebook is empty - pretty dumb... -////// and also the certain order of the codebook chunks -- rl - if(info->v4_size || !s->skip_empty_cb) + uint8_t *sub_scratch_data[4] = { 0 }, *sub_last_data[4] = { 0 }; + int sub_scratch_linesize[4] = { 0 }, sub_last_linesize[4] = { 0 }; + + // encode codebooks + ////// MacOS vintage decoder compatibility dictates the presence of + ////// the codebook chunk even when the codebook is empty - pretty dumb... + ////// and also the certain order of the codebook chunks -- rl + if (info->v4_size || !s->skip_empty_cb) ret += encode_codebook(s, info->v4_codebook, info->v4_size, 0x20, 0x24, buf + ret); - if(info->v1_size || !s->skip_empty_cb) + if (info->v1_size || !s->skip_empty_cb) ret += encode_codebook(s, info->v1_codebook, info->v1_size, 0x22, 0x26, buf + ret); - //update scratch picture - for(z = y = 0; y < h; y += MB_SIZE) { - for(x = 0; x < s->w; x += MB_SIZE, z++) { + // update scratch picture + for (z = y = 0; y < h; y += MB_SIZE) + for (x = 0; x < s->w; x += MB_SIZE, z++) { mb = &s->mb[z]; get_sub_picture(s, x, y, scratch_data, scratch_linesize, sub_scratch_data, sub_scratch_linesize); - if(info->mode == MODE_MC && mb->best_encoding == ENC_SKIP) { - get_sub_picture(s, x, y, - last_data, last_linesize, + if (info->mode == MODE_MC && mb->best_encoding == ENC_SKIP) { + get_sub_picture(s, x, y, last_data, last_linesize, sub_last_data, sub_last_linesize); copy_mb(s, sub_scratch_data, sub_scratch_linesize, sub_last_data, sub_last_linesize); - } else if(info->mode == MODE_V1_ONLY || mb->best_encoding == ENC_V1) + } else if (info->mode == MODE_V1_ONLY || mb->best_encoding == ENC_V1) decode_v1_vector(s, sub_scratch_data, sub_scratch_linesize, mb->v1_vector, info); else decode_v4_vector(s, sub_scratch_data, sub_scratch_linesize, mb->v4_vector, info); } - } - switch(info->mode) { + switch (info->mode) { case MODE_V1_ONLY: - //av_log(s->avctx, AV_LOG_INFO, "mb_count = %i\n", mb_count); + av_log(s->avctx, AV_LOG_INFO, "mb_count = %i\n", mb_count); ret += write_chunk_header(buf + ret, 0x32, mb_count); - for(x = 0; x < mb_count; x++) + for (x = 0; x < mb_count; x++) buf[ret++] = s->mb[x].v1_vector; break; case MODE_V1_V4: - //remember header position + // remember header position header_ofs = ret; - ret += CHUNK_HEADER_SIZE; + ret += CHUNK_HEADER_SIZE; - for(x = 0; x < mb_count; x += 32) { + for (x = 0; x < mb_count; x += 32) { flags = 0; - for(y = x; y < FFMIN(x+32, mb_count); y++) - if(s->mb[y].best_encoding == ENC_V4) + for (y = x; y < FFMIN(x + 32, mb_count); y++) + if (s->mb[y].best_encoding == ENC_V4) flags |= 1 << (31 - y + x); AV_WB32(&buf[ret], flags); ret += 4; - for(y = x; y < FFMIN(x+32, mb_count); y++) { + for (y = x; y < FFMIN(x + 32, mb_count); y++) { mb = &s->mb[y]; - if(mb->best_encoding == ENC_V1) + if (mb->best_encoding == ENC_V1) buf[ret++] = mb->v1_vector; else - for(z = 0; z < 4; z++) + for (z = 0; z < 4; z++) buf[ret++] = mb->v4_vector[z]; } } @@ -610,56 +620,56 @@ static int encode_mode(CinepakEncContext *s, int h, break; case MODE_MC: - //remember header position + // remember header position header_ofs = ret; - ret += CHUNK_HEADER_SIZE; - flags = bits = temp_size = 0; + ret += CHUNK_HEADER_SIZE; + flags = bits = temp_size = 0; - for(x = 0; x < mb_count; x++) { - mb = &s->mb[x]; - flags |= (mb->best_encoding != ENC_SKIP) << (31 - bits++); - needs_extra_bit = 0; + for (x = 0; x < mb_count; x++) { + mb = &s->mb[x]; + flags |= (mb->best_encoding != ENC_SKIP) << (31 - bits++); + needs_extra_bit = 0; should_write_temp = 0; - if(mb->best_encoding != ENC_SKIP) { - if(bits < 32) + if (mb->best_encoding != ENC_SKIP) { + if (bits < 32) flags |= (mb->best_encoding == ENC_V4) << (31 - bits++); else needs_extra_bit = 1; } - if(bits == 32) { + if (bits == 32) { AV_WB32(&buf[ret], flags); - ret += 4; + ret += 4; flags = bits = 0; - if(mb->best_encoding == ENC_SKIP || needs_extra_bit) { + if (mb->best_encoding == ENC_SKIP || needs_extra_bit) { memcpy(&buf[ret], temp, temp_size); - ret += temp_size; + ret += temp_size; temp_size = 0; } else should_write_temp = 1; } - if(needs_extra_bit) { + if (needs_extra_bit) { flags = (mb->best_encoding == ENC_V4) << 31; - bits = 1; + bits = 1; } - if(mb->best_encoding == ENC_V1) + if (mb->best_encoding == ENC_V1) temp[temp_size++] = mb->v1_vector; - else if(mb->best_encoding == ENC_V4) - for(z = 0; z < 4; z++) + else if (mb->best_encoding == ENC_V4) + for (z = 0; z < 4; z++) temp[temp_size++] = mb->v4_vector[z]; - if(should_write_temp) { + if (should_write_temp) { memcpy(&buf[ret], temp, temp_size); - ret += temp_size; + ret += temp_size; temp_size = 0; } } - if(bits > 0) { + if (bits > 0) { AV_WB32(&buf[ret], flags); ret += 4; memcpy(&buf[ret], temp, temp_size); @@ -674,28 +684,26 @@ static int encode_mode(CinepakEncContext *s, int h, return ret; } -//computes distortion of 4x4 MB in b compared to a +// computes distortion of 4x4 MB in b compared to a static int compute_mb_distortion(CinepakEncContext *s, uint8_t *a_data[4], int a_linesize[4], uint8_t *b_data[4], int b_linesize[4]) { int x, y, p, d, ret = 0; - for(y = 0; y < MB_SIZE; y++) { - for(x = 0; x < MB_SIZE; x++) { - d = a_data[0][x + y*a_linesize[0]] - b_data[0][x + y*b_linesize[0]]; - ret += d*d; + for (y = 0; y < MB_SIZE; y++) + for (x = 0; x < MB_SIZE; x++) { + d = a_data[0][x + y * a_linesize[0]] - b_data[0][x + y * b_linesize[0]]; + ret += d * d; } - } - if(s->pix_fmt == AV_PIX_FMT_RGB24) { - for(p = 1; p <= 2; p++) { - for(y = 0; y < MB_SIZE/2; y++) { - for(x = 0; x < MB_SIZE/2; x++) { - d = a_data[p][x + y*a_linesize[p]] - b_data[p][x + y*b_linesize[p]]; - ret += d*d; + if (s->pix_fmt == AV_PIX_FMT_RGB24) { + for (p = 1; p <= 2; p++) { + for (y = 0; y < MB_SIZE / 2; y++) + for (x = 0; x < MB_SIZE / 2; x++) { + d = a_data[p][x + y * a_linesize[p]] - b_data[p][x + y * b_linesize[p]]; + ret += d * d; } - } } } @@ -703,70 +711,68 @@ static int compute_mb_distortion(CinepakEncContext *s, } // return the possibly adjusted size of the codebook -#define CERTAIN(x) ((x)!=ENC_UNCERTAIN) -static int quantize(CinepakEncContext *s, int h, - uint8_t *data[4], int linesize[4], - int v1mode, strip_info *info, +#define CERTAIN(x) ((x) != ENC_UNCERTAIN) +static int quantize(CinepakEncContext *s, int h, uint8_t *data[4], + int linesize[4], int v1mode, strip_info *info, mb_encoding encoding) { int x, y, i, j, k, x2, y2, x3, y3, plane, shift, mbn; - int entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; - int *codebook = v1mode ? info->v1_codebook : info->v4_codebook; - int size = v1mode ? info->v1_size : info->v4_size; + int entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; + int *codebook = v1mode ? info->v1_codebook : info->v4_codebook; + int size = v1mode ? info->v1_size : info->v4_size; int64_t total_error = 0; - uint8_t vq_pict_buf[(MB_AREA*3)/2]; - uint8_t *sub_data [4], *vq_data [4]; + uint8_t vq_pict_buf[(MB_AREA * 3) / 2]; + uint8_t *sub_data[4], *vq_data[4]; int sub_linesize[4], vq_linesize[4]; - for(mbn = i = y = 0; y < h; y += MB_SIZE) { - for(x = 0; x < s->w; x += MB_SIZE, ++mbn) { + for (mbn = i = y = 0; y < h; y += MB_SIZE) { + for (x = 0; x < s->w; x += MB_SIZE, ++mbn) { int *base; - if(CERTAIN(encoding)) { -// use for the training only the blocks known to be to be encoded [sic:-] - if(s->mb[mbn].best_encoding != encoding) continue; + if (CERTAIN(encoding)) { + // use for the training only the blocks known to be to be encoded [sic:-] + if (s->mb[mbn].best_encoding != encoding) + continue; } - base = s->codebook_input + i*entry_size; - if(v1mode) { - //subsample - for(j = y2 = 0; y2 < entry_size; y2 += 2) { - for(x2 = 0; x2 < 4; x2 += 2, j++) { - plane = y2 < 4 ? 0 : 1 + (x2 >> 1); - shift = y2 < 4 ? 0 : 1; - x3 = shift ? 0 : x2; - y3 = shift ? 0 : y2; - base[j] = (data[plane][((x+x3) >> shift) + ((y+y3) >> shift) * linesize[plane]] + - data[plane][((x+x3) >> shift) + 1 + ((y+y3) >> shift) * linesize[plane]] + - data[plane][((x+x3) >> shift) + (((y+y3) >> shift) + 1) * linesize[plane]] + - data[plane][((x+x3) >> shift) + 1 + (((y+y3) >> shift) + 1) * linesize[plane]]) >> 2; + base = s->codebook_input + i * entry_size; + if (v1mode) { + // subsample + for (j = y2 = 0; y2 < entry_size; y2 += 2) + for (x2 = 0; x2 < 4; x2 += 2, j++) { + plane = y2 < 4 ? 0 : 1 + (x2 >> 1); + shift = y2 < 4 ? 0 : 1; + x3 = shift ? 0 : x2; + y3 = shift ? 0 : y2; + base[j] = (data[plane][((x + x3) >> shift) + ((y + y3) >> shift) * linesize[plane]] + + data[plane][((x + x3) >> shift) + 1 + ((y + y3) >> shift) * linesize[plane]] + + data[plane][((x + x3) >> shift) + (((y + y3) >> shift) + 1) * linesize[plane]] + + data[plane][((x + x3) >> shift) + 1 + (((y + y3) >> shift) + 1) * linesize[plane]]) >> 2; } - } } else { - //copy - for(j = y2 = 0; y2 < MB_SIZE; y2 += 2) { - for(x2 = 0; x2 < MB_SIZE; x2 += 2) { - for(k = 0; k < entry_size; k++, j++) { + // copy + for (j = y2 = 0; y2 < MB_SIZE; y2 += 2) { + for (x2 = 0; x2 < MB_SIZE; x2 += 2) + for (k = 0; k < entry_size; k++, j++) { plane = k >= 4 ? k - 3 : 0; - if(k >= 4) { - x3 = (x+x2) >> 1; - y3 = (y+y2) >> 1; + if (k >= 4) { + x3 = (x + x2) >> 1; + y3 = (y + y2) >> 1; } else { x3 = x + x2 + (k & 1); y3 = y + y2 + (k >> 1); } - base[j] = data[plane][x3 + y3*linesize[plane]]; + base[j] = data[plane][x3 + y3 * linesize[plane]]; } - } } } i += v1mode ? 1 : 4; } } - if(i == 0) // empty training set, nothing to do + if (i == 0) // empty training set, nothing to do return 0; if (i < size) size = i; @@ -774,38 +780,39 @@ static int quantize(CinepakEncContext *s, int h, ff_init_elbg(s->codebook_input, entry_size, i, codebook, size, 1, s->codebook_closest, &s->randctx); ff_do_elbg(s->codebook_input, entry_size, i, codebook, size, 1, s->codebook_closest, &s->randctx); - //setup vq_data, which contains a single MB - vq_data[0] = vq_pict_buf; + // set up vq_data, which contains a single MB + vq_data[0] = vq_pict_buf; vq_linesize[0] = MB_SIZE; - vq_data[1] = &vq_pict_buf[MB_AREA]; - vq_data[2] = vq_data[1] + (MB_AREA >> 2); - vq_linesize[1] = vq_linesize[2] = MB_SIZE >> 1; - - //copy indices - for(i = j = y = 0; y < h; y += MB_SIZE) { - for(x = 0; x < s->w; x += MB_SIZE, j++) { + vq_data[1] = &vq_pict_buf[MB_AREA]; + vq_data[2] = vq_data[1] + (MB_AREA >> 2); + vq_linesize[1] = + vq_linesize[2] = MB_SIZE >> 1; + + // copy indices + for (i = j = y = 0; y < h; y += MB_SIZE) + for (x = 0; x < s->w; x += MB_SIZE, j++) { mb_info *mb = &s->mb[j]; -// skip uninteresting blocks if we know their preferred encoding - if(CERTAIN(encoding) && mb->best_encoding != encoding) + // skip uninteresting blocks if we know their preferred encoding + if (CERTAIN(encoding) && mb->best_encoding != encoding) continue; - //point sub_data to current MB + // point sub_data to current MB get_sub_picture(s, x, y, data, linesize, sub_data, sub_linesize); - if(v1mode) { + if (v1mode) { mb->v1_vector = s->codebook_closest[i]; - //fill in vq_data with V1 data + // fill in vq_data with V1 data decode_v1_vector(s, vq_data, vq_linesize, mb->v1_vector, info); mb->v1_error = compute_mb_distortion(s, sub_data, sub_linesize, vq_data, vq_linesize); total_error += mb->v1_error; } else { - for(k = 0; k < 4; k++) - mb->v4_vector[k] = s->codebook_closest[i+k]; + for (k = 0; k < 4; k++) + mb->v4_vector[k] = s->codebook_closest[i + k]; - //fill in vq_data with V4 data + // fill in vq_data with V4 data decode_v4_vector(s, vq_data, vq_linesize, mb->v4_vector, info); mb->v4_error = compute_mb_distortion(s, sub_data, sub_linesize, @@ -814,8 +821,7 @@ static int quantize(CinepakEncContext *s, int h, } i += v1mode ? 1 : 4; } - } -// check that we did it right in the beginning of the function + // check that we did it right in the beginning of the function av_assert0(i >= size); // training set is no smaller than the codebook return size; @@ -830,33 +836,34 @@ static void calculate_skip_errors(CinepakEncContext *s, int h, uint8_t *sub_last_data [4], *sub_pict_data [4]; int sub_last_linesize[4], sub_pict_linesize[4]; - for(i = y = 0; y < h; y += MB_SIZE) { - for(x = 0; x < s->w; x += MB_SIZE, i++) { - get_sub_picture(s, x, y, last_data, last_linesize, - sub_last_data, sub_last_linesize); - get_sub_picture(s, x, y, data, linesize, - sub_pict_data, sub_pict_linesize); - - s->mb[i].skip_error = compute_mb_distortion(s, - sub_last_data, sub_last_linesize, - sub_pict_data, sub_pict_linesize); + for (i = y = 0; y < h; y += MB_SIZE) + for (x = 0; x < s->w; x += MB_SIZE, i++) { + get_sub_picture(s, x, y, last_data, last_linesize, + sub_last_data, sub_last_linesize); + get_sub_picture(s, x, y, data, linesize, + sub_pict_data, sub_pict_linesize); + + s->mb[i].skip_error = + compute_mb_distortion(s, + sub_last_data, sub_last_linesize, + sub_pict_data, sub_pict_linesize); } - } } -static void write_strip_header(CinepakEncContext *s, int y, int h, int keyframe, unsigned char *buf, int strip_size) +static void write_strip_header(CinepakEncContext *s, int y, int h, int keyframe, + unsigned char *buf, int strip_size) { -// actually we are exclusively using intra strip coding (how much can we win -// otherwise? how to choose which part of a codebook to update?), -// keyframes are different only because we disallow ENC_SKIP on them -- rl -// (besides, the logic here used to be inverted: ) -// buf[0] = keyframe ? 0x11: 0x10; - buf[0] = keyframe ? 0x10: 0x11; + // actually we are exclusively using intra strip coding (how much can we win + // otherwise? how to choose which part of a codebook to update?), + // keyframes are different only because we disallow ENC_SKIP on them -- rl + // (besides, the logic here used to be inverted: ) + // buf[0] = keyframe ? 0x11: 0x10; + buf[0] = keyframe ? 0x10 : 0x11; AV_WB24(&buf[1], strip_size + STRIP_HEADER_SIZE); -// AV_WB16(&buf[4], y); /* using absolute y values works -- rl */ + // AV_WB16(&buf[4], y); /* using absolute y values works -- rl */ AV_WB16(&buf[4], 0); /* using relative values works as well -- rl */ AV_WB16(&buf[6], 0); -// AV_WB16(&buf[8], y+h); /* using absolute y values works -- rl */ + // AV_WB16(&buf[8], y + h); /* using absolute y values works -- rl */ AV_WB16(&buf[8], h); /* using relative values works as well -- rl */ AV_WB16(&buf[10], s->w); } @@ -870,88 +877,89 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, int64_t score = 0; int best_size = 0; strip_info info; -// for codebook optimization: + // for codebook optimization: int v1enough, v1_size, v4enough, v4_size; int new_v1_size, new_v4_size; int v1shrunk, v4shrunk; - if(!keyframe) + if (!keyframe) calculate_skip_errors(s, h, last_data, last_linesize, data, linesize, &info); - //try some powers of 4 for the size of the codebooks - //constraint the v4 codebook to be no bigger than v1 one, - //(and no less than v1_size/4) - //thus making v1 preferable and possibly losing small details? should be ok + // try some powers of 4 for the size of the codebooks + // constraint the v4 codebook to be no bigger than v1 one, + // (and no less than v1_size/4) + // thus making v1 preferable and possibly losing small details? should be ok #define SMALLEST_CODEBOOK 1 - for(v1enough = 0, v1_size = SMALLEST_CODEBOOK; v1_size <= CODEBOOK_MAX && !v1enough; v1_size <<= 2) { - for(v4enough = 0, v4_size = 0; v4_size <= v1_size && !v4enough; v4_size = v4_size ? v4_size << 2 : v1_size >= SMALLEST_CODEBOOK << 2 ? v1_size >> 2 : SMALLEST_CODEBOOK) { - //try all modes - for(CinepakMode mode = 0; mode < MODE_COUNT; mode++) { - //don't allow MODE_MC in intra frames - if(keyframe && mode == MODE_MC) + for (v1enough = 0, v1_size = SMALLEST_CODEBOOK; v1_size <= CODEBOOK_MAX && !v1enough; v1_size <<= 2) { + for (v4enough = 0, v4_size = 0; v4_size <= v1_size && !v4enough; v4_size = v4_size ? v4_size << 2 : v1_size >= SMALLEST_CODEBOOK << 2 ? v1_size >> 2 : SMALLEST_CODEBOOK) { + // try all modes + for (CinepakMode mode = 0; mode < MODE_COUNT; mode++) { + // don't allow MODE_MC in intra frames + if (keyframe && mode == MODE_MC) continue; - if(mode == MODE_V1_ONLY) { + if (mode == MODE_V1_ONLY) { info.v1_size = v1_size; -// the size may shrink even before optimizations if the input is short: + // the size may shrink even before optimizations if the input is short: info.v1_size = quantize(s, h, data, linesize, 1, &info, ENC_UNCERTAIN); - if(info.v1_size < v1_size) -// too few eligible blocks, no sense in trying bigger sizes + if (info.v1_size < v1_size) + // too few eligible blocks, no sense in trying bigger sizes v1enough = 1; info.v4_size = 0; } else { // mode != MODE_V1_ONLY // if v4 codebook is empty then only allow V1-only mode - if(!v4_size) + if (!v4_size) continue; - if(mode == MODE_V1_V4) { + if (mode == MODE_V1_V4) { info.v4_size = v4_size; info.v4_size = quantize(s, h, data, linesize, 0, &info, ENC_UNCERTAIN); - if(info.v4_size < v4_size) -// too few eligible blocks, no sense in trying bigger sizes + if (info.v4_size < v4_size) + // too few eligible blocks, no sense in trying bigger sizes v4enough = 1; } } info.mode = mode; -// choose the best encoding per block, based on current experience + // choose the best encoding per block, based on current experience score = calculate_mode_score(s, h, &info, 0, &v1shrunk, &v4shrunk); - if(mode != MODE_V1_ONLY){ + if (mode != MODE_V1_ONLY) { int extra_iterations_limit = s->max_extra_cb_iterations; -// recompute the codebooks, omitting the extra blocks -// we assume we _may_ come here with more blocks to encode than before + // recompute the codebooks, omitting the extra blocks + // we assume we _may_ come here with more blocks to encode than before info.v1_size = v1_size; new_v1_size = quantize(s, h, data, linesize, 1, &info, ENC_V1); if (new_v1_size < info.v1_size) info.v1_size = new_v1_size; -// we assume we _may_ come here with more blocks to encode than before + // we assume we _may_ come here with more blocks to encode than before info.v4_size = v4_size; new_v4_size = quantize(s, h, data, linesize, 0, &info, ENC_V4); if (new_v4_size < info.v4_size) info.v4_size = new_v4_size; -// calculate the resulting score -// (do not move blocks to codebook encodings now, as some blocks may have -// got bigger errors despite a smaller training set - but we do not -// ever grow the training sets back) - for(;;) { + // calculate the resulting score + // (do not move blocks to codebook encodings now, as some blocks may have + // got bigger errors despite a smaller training set - but we do not + // ever grow the training sets back) + for (;;) { score = calculate_mode_score(s, h, &info, 1, &v1shrunk, &v4shrunk); -// do we have a reason to reiterate? if so, have we reached the limit? - if((!v1shrunk && !v4shrunk) || !extra_iterations_limit--) break; -// recompute the codebooks, omitting the extra blocks - if(v1shrunk) { + // do we have a reason to reiterate? if so, have we reached the limit? + if ((!v1shrunk && !v4shrunk) || !extra_iterations_limit--) + break; + // recompute the codebooks, omitting the extra blocks + if (v1shrunk) { info.v1_size = v1_size; new_v1_size = quantize(s, h, data, linesize, 1, &info, ENC_V1); if (new_v1_size < info.v1_size) info.v1_size = new_v1_size; } - if(v4shrunk) { + if (v4shrunk) { info.v4_size = v4_size; new_v4_size = quantize(s, h, data, linesize, 0, &info, ENC_V4); if (new_v4_size < info.v4_size) @@ -960,8 +968,7 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, } } - if(best_size == 0 || score < *best_score) { - + if (best_size == 0 || score < *best_score) { *best_score = score; best_size = encode_mode(s, h, scratch_data, scratch_linesize, @@ -969,7 +976,6 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, s->strip_buf + STRIP_HEADER_SIZE); write_strip_header(s, y, h, keyframe, s->strip_buf, best_size); - } } } @@ -981,7 +987,8 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, return best_size; } -static int write_cvid_header(CinepakEncContext *s, unsigned char *buf, int num_strips, int data_size, int isakeyframe) +static int write_cvid_header(CinepakEncContext *s, unsigned char *buf, + int num_strips, int data_size, int isakeyframe) { buf[0] = isakeyframe ? 0 : 1; AV_WB24(&buf[1], data_size + CVID_HEADER_SIZE); @@ -1001,78 +1008,87 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, int64_t best_score = 0, score, score_temp; int best_nstrips; - if(s->pix_fmt == AV_PIX_FMT_RGB24) { + if (s->pix_fmt == AV_PIX_FMT_RGB24) { int x; -// build a copy of the given frame in the correct colorspace - for(y = 0; y < s->h; y += 2) { - for(x = 0; x < s->w; x += 2) { - uint8_t *ir[2]; int32_t r, g, b, rr, gg, bb; - ir[0] = frame->data[0] + x*3 + y*frame->linesize[0]; + // build a copy of the given frame in the correct colorspace + for (y = 0; y < s->h; y += 2) + for (x = 0; x < s->w; x += 2) { + uint8_t *ir[2]; + int32_t r, g, b, rr, gg, bb; + ir[0] = frame->data[0] + x * 3 + y * frame->linesize[0]; ir[1] = ir[0] + frame->linesize[0]; get_sub_picture(s, x, y, s->input_frame->data, s->input_frame->linesize, scratch_data, scratch_linesize); r = g = b = 0; - for(i=0; i<4; ++i) { + for (i = 0; i < 4; ++i) { int i1, i2; - i1 = (i&1); i2 = (i>=2); - rr = ir[i2][i1*3+0]; - gg = ir[i2][i1*3+1]; - bb = ir[i2][i1*3+2]; - r += rr; g += gg; b += bb; -// using fixed point arithmetic for portable repeatability, scaling by 2^23 -// "Y" -// rr = 0.2857*rr + 0.5714*gg + 0.1429*bb; - rr = (2396625*rr + 4793251*gg + 1198732*bb) >> 23; - if( rr < 0) rr = 0; - else if (rr > 255) rr = 255; - scratch_data[0][i1 + i2*scratch_linesize[0]] = rr; + i1 = (i & 1); + i2 = (i >= 2); + rr = ir[i2][i1 * 3 + 0]; + gg = ir[i2][i1 * 3 + 1]; + bb = ir[i2][i1 * 3 + 2]; + r += rr; + g += gg; + b += bb; + // using fixed point arithmetic for portable repeatability, scaling by 2^23 + // "Y" + // rr = 0.2857 * rr + 0.5714 * gg + 0.1429 * bb; + rr = (2396625 * rr + 4793251 * gg + 1198732 * bb) >> 23; + if (rr < 0) + rr = 0; + else if (rr > 255) + rr = 255; + scratch_data[0][i1 + i2 * scratch_linesize[0]] = rr; } -// let us scale down as late as possible -// r /= 4; g /= 4; b /= 4; -// "U" -// rr = -0.1429*r - 0.2857*g + 0.4286*b; - rr = (-299683*r - 599156*g + 898839*b) >> 23; - if( rr < -128) rr = -128; - else if (rr > 127) rr = 127; + // let us scale down as late as possible + // r /= 4; g /= 4; b /= 4; + // "U" + // rr = -0.1429 * r - 0.2857 * g + 0.4286 * b; + rr = (-299683 * r - 599156 * g + 898839 * b) >> 23; + if (rr < -128) + rr = -128; + else if (rr > 127) + rr = 127; scratch_data[1][0] = rr + 128; // quantize needs unsigned -// "V" -// rr = 0.3571*r - 0.2857*g - 0.0714*b; - rr = (748893*r - 599156*g - 149737*b) >> 23; - if( rr < -128) rr = -128; - else if (rr > 127) rr = 127; + // "V" + // rr = 0.3571 * r - 0.2857 * g - 0.0714 * b; + rr = (748893 * r - 599156 * g - 149737 * b) >> 23; + if (rr < -128) + rr = -128; + else if (rr > 127) + rr = 127; scratch_data[2][0] = rr + 128; // quantize needs unsigned } - } } - //would be nice but quite certainly incompatible with vintage players: + // would be nice but quite certainly incompatible with vintage players: // support encoding zero strips (meaning skip the whole frame) - for(num_strips = s->min_strips; num_strips <= s->max_strips && num_strips <= s->h / MB_SIZE; num_strips++) { + for (num_strips = s->min_strips; num_strips <= s->max_strips && num_strips <= s->h / MB_SIZE; num_strips++) { score = 0; - size = 0; + size = 0; - for(y = 0, strip = 1; y < s->h; strip++, y = nexty) { + for (y = 0, strip = 1; y < s->h; strip++, y = nexty) { int strip_height; nexty = strip * s->h / num_strips; // <= s->h - //make nexty the next multiple of 4 if not already there - if(nexty & 3) + // make nexty the next multiple of 4 if not already there + if (nexty & 3) nexty += 4 - (nexty & 3); strip_height = nexty - y; - if(strip_height <= 0) { // can this ever happen? + if (strip_height <= 0) { // can this ever happen? av_log(s->avctx, AV_LOG_INFO, "skipping zero height strip %i of %i\n", strip, num_strips); continue; } - if(s->pix_fmt == AV_PIX_FMT_RGB24) + if (s->pix_fmt == AV_PIX_FMT_RGB24) get_sub_picture(s, 0, y, s->input_frame->data, s->input_frame->linesize, data, linesize); else get_sub_picture(s, 0, y, - (uint8_t **)frame->data, (int*)frame->linesize, + (uint8_t **)frame->data, (int *)frame->linesize, data, linesize); get_sub_picture(s, 0, y, s->last_frame->data, s->last_frame->linesize, @@ -1081,17 +1097,18 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, s->scratch_frame->data, s->scratch_frame->linesize, scratch_data, scratch_linesize); - if((temp_size = rd_strip(s, y, strip_height, isakeyframe, - last_data, last_linesize, data, linesize, - scratch_data, scratch_linesize, - s->frame_buf + size + CVID_HEADER_SIZE, &score_temp)) < 0) + if ((temp_size = rd_strip(s, y, strip_height, isakeyframe, + last_data, last_linesize, data, linesize, + scratch_data, scratch_linesize, + s->frame_buf + size + CVID_HEADER_SIZE, + &score_temp)) < 0) return temp_size; score += score_temp; size += temp_size; } - if(best_score == 0 || score < best_score) { + if (best_score == 0 || score < best_score) { best_score = score; best_size = size + write_cvid_header(s, s->frame_buf, num_strips, size, isakeyframe); @@ -1099,32 +1116,32 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, memcpy(buf, s->frame_buf, best_size); best_nstrips = num_strips; } -// avoid trying too many strip numbers without a real reason -// (this makes the processing of the very first frame faster) - if(num_strips - best_nstrips > 4) + // avoid trying too many strip numbers without a real reason + // (this makes the processing of the very first frame faster) + if (num_strips - best_nstrips > 4) break; } -// let the number of strips slowly adapt to the changes in the contents, -// compared to full bruteforcing every time this will occasionally lead -// to some r/d performance loss but makes encoding up to several times faster - if(!s->strip_number_delta_range) { - if(best_nstrips == s->max_strips) { // let us try to step up + // let the number of strips slowly adapt to the changes in the contents, + // compared to full bruteforcing every time this will occasionally lead + // to some r/d performance loss but makes encoding up to several times faster + if (!s->strip_number_delta_range) { + if (best_nstrips == s->max_strips) { // let us try to step up s->max_strips = best_nstrips + 1; - if(s->max_strips >= s->max_max_strips) + if (s->max_strips >= s->max_max_strips) s->max_strips = s->max_max_strips; } else { // try to step down s->max_strips = best_nstrips; } s->min_strips = s->max_strips - 1; - if(s->min_strips < s->min_min_strips) + if (s->min_strips < s->min_min_strips) s->min_strips = s->min_min_strips; } else { s->max_strips = best_nstrips + s->strip_number_delta_range; - if(s->max_strips >= s->max_max_strips) + if (s->max_strips >= s->max_max_strips) s->max_strips = s->max_max_strips; s->min_strips = best_nstrips - s->strip_number_delta_range; - if(s->min_strips < s->min_min_strips) + if (s->min_strips < s->min_min_strips) s->min_strips = s->min_min_strips; } @@ -1141,7 +1158,7 @@ static int cinepak_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if ((ret = ff_alloc_packet(pkt, s->frame_buf_size)) < 0) return ret; - ret = rd_frame(s, frame, (s->curframe == 0), pkt->data, s->frame_buf_size); + ret = rd_frame(s, frame, (s->curframe == 0), pkt->data, s->frame_buf_size); pkt->size = ret; if (s->curframe == 0) pkt->flags |= AV_PKT_FLAG_KEY; @@ -1171,7 +1188,7 @@ static av_cold int cinepak_encode_end(AVCodecContext *avctx) av_freep(&s->frame_buf); av_freep(&s->mb); - for(x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) + for (x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) av_freep(&s->pict_bufs[x]); return 0; @@ -1179,13 +1196,13 @@ static av_cold int cinepak_encode_end(AVCodecContext *avctx) AVCodec ff_cinepak_encoder = { .name = "cinepak", + .long_name = NULL_IF_CONFIG_SMALL("Cinepak"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_CINEPAK, .priv_data_size = sizeof(CinepakEncContext), .init = cinepak_encode_init, .encode2 = cinepak_encode_frame, .close = cinepak_encode_end, - .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_RGB24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, - .long_name = NULL_IF_CONFIG_SMALL("Cinepak"), + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }, .priv_class = &cinepak_class, }; From ed3b2a999d189771c9b0ada9a9200117595fa474 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 28 Jun 2017 00:27:18 +0200 Subject: [PATCH 0307/2557] cinepakenc: misc small changes Avoid anonymously typedeffed structs and enums, drop an unused context member, fix a small wording mishap, sizeof(type) ---> sizeof(*variable), drop a needlessly verbose log message, use av_malloc_array() where appropriate. --- libavcodec/cinepakenc.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index 51f79a43c3554..00b3e75e4cc04 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -68,7 +68,7 @@ // NOTE the decoder in ffmpeg has its own arbitrary limitation on the number // of strips, currently 32 -typedef enum { +typedef enum CinepakMode { MODE_V1_ONLY = 0, MODE_V1_V4, MODE_MC, @@ -76,7 +76,7 @@ typedef enum { MODE_COUNT, } CinepakMode; -typedef enum { +typedef enum mb_encoding { ENC_V1, ENC_V4, ENC_SKIP, @@ -84,7 +84,7 @@ typedef enum { ENC_UNCERTAIN } mb_encoding; -typedef struct { +typedef struct mb_info { int v1_vector; // index into v1 codebook int v1_error; // error when using V1 encoding int v4_vector[4]; // indices into v4 codebook @@ -93,7 +93,7 @@ typedef struct { mb_encoding best_encoding; // last result from calculate_mode_score() } mb_info; -typedef struct { +typedef struct strip_info { int v1_codebook[CODEBOOK_MAX * VECTOR_MAX]; int v4_codebook[CODEBOOK_MAX * VECTOR_MAX]; int v1_size; @@ -101,8 +101,7 @@ typedef struct { CinepakMode mode; } strip_info; -typedef struct { - const AVClass *class; +typedef struct CinepakEncContext { AVCodecContext *avctx; unsigned char *pict_bufs[4], *strip_buf, *frame_buf; AVFrame *last_frame; @@ -163,7 +162,7 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) } if (s->min_min_strips > s->max_max_strips) { - av_log(avctx, AV_LOG_ERROR, "minimal number of strips can not exceed maximal (got %i and %i)\n", + av_log(avctx, AV_LOG_ERROR, "minimum number of strips must not exceed maximum (got %i and %i)\n", s->min_min_strips, s->max_max_strips); return AVERROR(EINVAL); } @@ -178,10 +177,10 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) if (!(s->input_frame = av_frame_alloc())) goto enomem; - if (!(s->codebook_input = av_malloc(sizeof(int) * (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4) * (avctx->width * avctx->height) >> 2))) + if (!(s->codebook_input = av_malloc_array((avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4) * (avctx->width * avctx->height) >> 2, sizeof(*s->codebook_input)))) goto enomem; - if (!(s->codebook_closest = av_malloc(sizeof(int) * (avctx->width * avctx->height) >> 2))) + if (!(s->codebook_closest = av_malloc_array((avctx->width * avctx->height) >> 2, sizeof(*s->codebook_closest)))) goto enomem; for (x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) @@ -204,7 +203,7 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) if (!(s->frame_buf = av_malloc(frame_buf_size))) goto enomem; - if (!(s->mb = av_malloc(mb_count * sizeof(mb_info)))) + if (!(s->mb = av_malloc_array(mb_count, sizeof(mb_info)))) goto enomem; av_lfg_init(&s->randctx, 1); @@ -584,7 +583,6 @@ static int encode_mode(CinepakEncContext *s, int h, switch (info->mode) { case MODE_V1_ONLY: - av_log(s->avctx, AV_LOG_INFO, "mb_count = %i\n", mb_count); ret += write_chunk_header(buf + ret, 0x32, mb_count); for (x = 0; x < mb_count; x++) From 5be9939b46a6a4d3860a1b1a872aa50897095970 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 28 Jun 2017 00:27:19 +0200 Subject: [PATCH 0308/2557] fate: Add cinepak encoder vsynth tests --- tests/fate/vcodec.mak | 4 ++++ tests/ref/vsynth/vsynth1-cinepak | 4 ++++ tests/ref/vsynth/vsynth2-cinepak | 4 ++++ 3 files changed, 12 insertions(+) create mode 100644 tests/ref/vsynth/vsynth1-cinepak create mode 100644 tests/ref/vsynth/vsynth2-cinepak diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak index e195254a481e8..490da55511719 100644 --- a/tests/fate/vcodec.mak +++ b/tests/fate/vcodec.mak @@ -12,6 +12,10 @@ fate-vsynth%-asv1: ENCOPTS = -qscale 10 FATE_VCODEC-$(call ENCDEC, ASV2, AVI) += asv2 fate-vsynth%-asv2: ENCOPTS = -qscale 10 +FATE_VCODEC-$(call ENCDEC, CINEPAK, AVI) += cinepak +fate-vsynth%-cinepak: ENCOPTS = -s sqcif -strip_number_adaptivity 1 +fate-vsynth%-cinepak: DECOPTS = -s sqcif + FATE_VCODEC-$(call ENCDEC, CLJR, AVI) += cljr FATE_VCODEC-$(call ENCDEC, DNXHD, DNXHD) += dnxhd-720p \ diff --git a/tests/ref/vsynth/vsynth1-cinepak b/tests/ref/vsynth/vsynth1-cinepak new file mode 100644 index 0000000000000..09ba81aef3039 --- /dev/null +++ b/tests/ref/vsynth/vsynth1-cinepak @@ -0,0 +1,4 @@ +c2198279f3ccf18eb029875c98231073 *tests/data/fate/vsynth1-cinepak.avi +408612 tests/data/fate/vsynth1-cinepak.avi +fdcc7e515ff0bea5203d1ed9bfa7514c *tests/data/fate/vsynth1-cinepak.out.rawvideo +stddev: 64.04 PSNR: 12.00 MAXDIFF: 238 bytes: 7603200/ 921600 diff --git a/tests/ref/vsynth/vsynth2-cinepak b/tests/ref/vsynth/vsynth2-cinepak new file mode 100644 index 0000000000000..c1ff48d10900d --- /dev/null +++ b/tests/ref/vsynth/vsynth2-cinepak @@ -0,0 +1,4 @@ +722bab34b13b33e46dbbdd47985049f3 *tests/data/fate/vsynth2-cinepak.avi +400398 tests/data/fate/vsynth2-cinepak.avi +c59f0419068f0071476d037abd2ccde2 *tests/data/fate/vsynth2-cinepak.out.rawvideo +stddev: 87.20 PSNR: 9.32 MAXDIFF: 247 bytes: 7603200/ 921600 From fd92dafaff8844b5fedf94679b93d953939a7f7b Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 5 Jul 2017 15:03:56 +0200 Subject: [PATCH 0309/2557] bink: Split read_dct_coeffs() This works around type aliasing violations and related warnings. Also add some missing error checking. --- libavcodec/bink.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/libavcodec/bink.c b/libavcodec/bink.c index 011d2d8e2282c..98fc46e0266ac 100644 --- a/libavcodec/bink.c +++ b/libavcodec/bink.c @@ -595,17 +595,15 @@ static inline int binkb_get_value(BinkContext *c, int bundle_num) * @return 0 for success, negative value in other cases */ static int read_dct_coeffs(BitstreamContext *bc, int32_t block[64], - const uint8_t *scan, - const int32_t quant_matrices[16][64], int q) + const uint8_t *scan, int *coef_count_, + int coef_idx[64], int q) { int coef_list[128]; int mode_list[128]; int i, t, bits, ccoef, mode; int list_start = 64, list_end = 64, list_pos; int coef_count = 0; - int coef_idx[64]; int quant_idx; - const int32_t *quant; coef_list[list_end] = 4; mode_list[list_end++] = 0; coef_list[list_end] = 24; mode_list[list_end++] = 0; @@ -681,15 +679,21 @@ static int read_dct_coeffs(BitstreamContext *bc, int32_t block[64], if (quant_idx >= 16) return AVERROR_INVALIDDATA; - quant = quant_matrices[quant_idx]; + *coef_count_ = coef_count; + return quant_idx; +} + +static void unquantize_dct_coeffs(int32_t block[64], const int32_t quant[64], + int coef_count, int coef_idx[64], + const uint8_t *scan) +{ + int i; block[0] = (block[0] * quant[0]) >> 11; for (i = 0; i < coef_count; i++) { int idx = coef_idx[i]; block[scan[idx]] = (block[scan[idx]] * quant[idx]) >> 11; } - - return 0; } /** @@ -806,7 +810,7 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, BitstreamContext * LOCAL_ALIGNED_16(int32_t, dctblock, [64]); int coordmap[64]; int ybias = is_key ? -15 : 0; - int qp; + int qp, quant_idx, coef_count, coef_idx[64]; const int stride = frame->linesize[plane_idx]; int bw = is_chroma ? (c->avctx->width + 15) >> 4 : (c->avctx->width + 7) >> 3; @@ -859,7 +863,9 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, BitstreamContext * memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = binkb_get_value(c, BINKB_SRC_INTRA_DC); qp = binkb_get_value(c, BINKB_SRC_INTRA_Q); - read_dct_coeffs(bc, dctblock, bink_scan, binkb_intra_quant, qp); + if ((quant_idx = read_dct_coeffs(bc, dctblock, bink_scan, &coef_count, coef_idx, qp)) < 0) + return quant_idx; + unquantize_dct_coeffs(dctblock, binkb_intra_quant[quant_idx], coef_count, coef_idx, bink_scan); c->binkdsp.idct_put(dst, stride, dctblock); break; case 3: @@ -892,7 +898,9 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, BitstreamContext * memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = binkb_get_value(c, BINKB_SRC_INTER_DC); qp = binkb_get_value(c, BINKB_SRC_INTER_Q); - read_dct_coeffs(bc, dctblock, bink_scan, binkb_inter_quant, qp); + if ((quant_idx = read_dct_coeffs(bc, dctblock, bink_scan, &coef_count, coef_idx, qp)) < 0) + return quant_idx; + unquantize_dct_coeffs(dctblock, binkb_inter_quant[quant_idx], coef_count, coef_idx, bink_scan); c->binkdsp.idct_add(dst, stride, dctblock); break; case 5: @@ -966,7 +974,7 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, BitstreamContext *b LOCAL_ALIGNED_16(int16_t, block, [64]); LOCAL_ALIGNED_16(uint8_t, ublock, [64]); LOCAL_ALIGNED_16(int32_t, dctblock, [64]); - int coordmap[64]; + int coordmap[64], quant_idx, coef_count, coef_idx[64]; const int stride = frame->linesize[plane_idx]; int bw = is_chroma ? (c->avctx->width + 15) >> 4 : (c->avctx->width + 7) >> 3; @@ -1052,7 +1060,9 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, BitstreamContext *b case INTRA_BLOCK: memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = get_value(c, BINK_SRC_INTRA_DC); - read_dct_coeffs(bc, dctblock, bink_scan, bink_intra_quant, -1); + if ((quant_idx = read_dct_coeffs(bc, dctblock, bink_scan, &coef_count, coef_idx, -1)) < 0) + return quant_idx; + unquantize_dct_coeffs(dctblock, bink_intra_quant[quant_idx], coef_count, coef_idx, bink_scan); c->binkdsp.idct_put(ublock, 8, dctblock); break; case FILL_BLOCK: @@ -1125,7 +1135,9 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, BitstreamContext *b case INTRA_BLOCK: memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = get_value(c, BINK_SRC_INTRA_DC); - read_dct_coeffs(bc, dctblock, bink_scan, bink_intra_quant, -1); + if ((quant_idx = read_dct_coeffs(bc, dctblock, bink_scan, &coef_count, coef_idx, -1)) < 0) + return quant_idx; + unquantize_dct_coeffs(dctblock, bink_intra_quant[quant_idx], coef_count, coef_idx, bink_scan); c->binkdsp.idct_put(dst, stride, dctblock); break; case FILL_BLOCK: @@ -1139,7 +1151,9 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, BitstreamContext *b return ret; memset(dctblock, 0, sizeof(*dctblock) * 64); dctblock[0] = get_value(c, BINK_SRC_INTER_DC); - read_dct_coeffs(bc, dctblock, bink_scan, bink_inter_quant, -1); + if ((quant_idx = read_dct_coeffs(bc, dctblock, bink_scan, &coef_count, coef_idx, -1)) < 0) + return quant_idx; + unquantize_dct_coeffs(dctblock, bink_inter_quant[quant_idx], coef_count, coef_idx, bink_scan); c->binkdsp.idct_add(dst, stride, dctblock); break; case PATTERN_BLOCK: From 79f64f7ebc2b2b7030c6219914bc141cc03fd377 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sat, 8 Jul 2017 21:04:44 +0200 Subject: [PATCH 0310/2557] bitstream: Avoid undefined behavior in bitstream_skip() Do not use skip_remaining() to fully wipe the cache, as this could do a 64-bit shift of a 64-bit variable which is undefined behavior in C. Instead set the related variables to zero directly. Thanks to Uoti for pointing out the problem. CC: libav-stable@libav.org --- libavcodec/bitstream.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/bitstream.h b/libavcodec/bitstream.h index d6dd2b94118f5..1b23cb2fa7d0f 100644 --- a/libavcodec/bitstream.h +++ b/libavcodec/bitstream.h @@ -239,11 +239,13 @@ static inline void skip_remaining(BitstreamContext *bc, unsigned n) /* Skip n bits in the buffer. */ static inline void bitstream_skip(BitstreamContext *bc, unsigned n) { - if (n <= bc->bits_left) + if (n < bc->bits_left) skip_remaining(bc, n); else { n -= bc->bits_left; - skip_remaining(bc, bc->bits_left); + bc->bits = 0; + bc->bits_left = 0; + if (n >= 64) { unsigned skip = n / 8; From 9c1e111406bd4cbb04d8e8611b71bebf203bec5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= Date: Sat, 29 Apr 2017 02:15:30 +0000 Subject: [PATCH 0311/2557] flac: Convert to the new bitstream reader Signed-off-by: Diego Biurrun --- libavcodec/flac.c | 68 ++++++++++++++++++++-------------------- libavcodec/flac.h | 6 ++-- libavcodec/flac_parser.c | 6 ++-- libavcodec/flacdec.c | 58 +++++++++++++++++----------------- libavcodec/flacenc.c | 2 +- 5 files changed, 70 insertions(+), 70 deletions(-) diff --git a/libavcodec/flac.c b/libavcodec/flac.c index 3e51fdeb98885..5062c1e0db560 100644 --- a/libavcodec/flac.c +++ b/libavcodec/flac.c @@ -22,8 +22,9 @@ #include "libavutil/channel_layout.h" #include "libavutil/crc.h" #include "libavutil/log.h" + +#include "bitstream.h" #include "bytestream.h" -#include "get_bits.h" #include "flac.h" #include "flacdata.h" @@ -40,33 +41,33 @@ static const uint64_t flac_channel_layouts[8] = { AV_CH_LAYOUT_7POINT1 }; -static int64_t get_utf8(GetBitContext *gb) +static int64_t get_utf8(BitstreamContext *bc) { int64_t val; - GET_UTF8(val, get_bits(gb, 8), return -1;) + GET_UTF8(val, bitstream_read(bc, 8), return -1;) return val; } -int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, +int ff_flac_decode_frame_header(AVCodecContext *avctx, BitstreamContext *bc, FLACFrameInfo *fi, int log_level_offset) { int bs_code, sr_code, bps_code; /* frame sync code */ - if ((get_bits(gb, 15) & 0x7FFF) != 0x7FFC) { + if ((bitstream_read(bc, 15) & 0x7FFF) != 0x7FFC) { av_log(avctx, AV_LOG_ERROR + log_level_offset, "invalid sync code\n"); return AVERROR_INVALIDDATA; } /* variable block size stream code */ - fi->is_var_size = get_bits1(gb); + fi->is_var_size = bitstream_read_bit(bc); /* block size and sample rate codes */ - bs_code = get_bits(gb, 4); - sr_code = get_bits(gb, 4); + bs_code = bitstream_read(bc, 4); + sr_code = bitstream_read(bc, 4); /* channels and decorrelation */ - fi->ch_mode = get_bits(gb, 4); + fi->ch_mode = bitstream_read(bc, 4); if (fi->ch_mode < FLAC_MAX_CHANNELS) { fi->channels = fi->ch_mode + 1; fi->ch_mode = FLAC_CHMODE_INDEPENDENT; @@ -80,7 +81,7 @@ int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, } /* bits per sample */ - bps_code = get_bits(gb, 3); + bps_code = bitstream_read(bc, 3); if (bps_code == 3 || bps_code == 7) { av_log(avctx, AV_LOG_ERROR + log_level_offset, "invalid sample size code (%d)\n", @@ -90,14 +91,14 @@ int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, fi->bps = sample_size_table[bps_code]; /* reserved bit */ - if (get_bits1(gb)) { + if (bitstream_read_bit(bc)) { av_log(avctx, AV_LOG_ERROR + log_level_offset, "broken stream, invalid padding\n"); return AVERROR_INVALIDDATA; } /* sample or frame count */ - fi->frame_or_sample_num = get_utf8(gb); + fi->frame_or_sample_num = get_utf8(bc); if (fi->frame_or_sample_num < 0) { av_log(avctx, AV_LOG_ERROR + log_level_offset, "sample/frame number invalid; utf8 fscked\n"); @@ -110,9 +111,9 @@ int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, "reserved blocksize code: 0\n"); return AVERROR_INVALIDDATA; } else if (bs_code == 6) { - fi->blocksize = get_bits(gb, 8) + 1; + fi->blocksize = bitstream_read(bc, 8) + 1; } else if (bs_code == 7) { - fi->blocksize = get_bits(gb, 16) + 1; + fi->blocksize = bitstream_read(bc, 16) + 1; } else { fi->blocksize = ff_flac_blocksize_table[bs_code]; } @@ -121,11 +122,11 @@ int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, if (sr_code < 12) { fi->samplerate = ff_flac_sample_rate_table[sr_code]; } else if (sr_code == 12) { - fi->samplerate = get_bits(gb, 8) * 1000; + fi->samplerate = bitstream_read(bc, 8) * 1000; } else if (sr_code == 13) { - fi->samplerate = get_bits(gb, 16); + fi->samplerate = bitstream_read(bc, 16); } else if (sr_code == 14) { - fi->samplerate = get_bits(gb, 16) * 10; + fi->samplerate = bitstream_read(bc, 16) * 10; } else { av_log(avctx, AV_LOG_ERROR + log_level_offset, "illegal sample rate code %d\n", @@ -134,9 +135,9 @@ int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, } /* header CRC-8 check */ - skip_bits(gb, 8); - if (av_crc(av_crc_get_table(AV_CRC_8_ATM), 0, gb->buffer, - get_bits_count(gb)/8)) { + bitstream_skip(bc, 8); + if (av_crc(av_crc_get_table(AV_CRC_8_ATM), 0, bc->buffer, + bitstream_tell(bc) / 8)) { av_log(avctx, AV_LOG_ERROR + log_level_offset, "header crc mismatch\n"); return AVERROR_INVALIDDATA; @@ -204,23 +205,22 @@ void ff_flac_set_channel_layout(AVCodecContext *avctx) void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s, const uint8_t *buffer) { - GetBitContext gb; - init_get_bits(&gb, buffer, FLAC_STREAMINFO_SIZE*8); + BitstreamContext bc; + bitstream_init8(&bc, buffer, FLAC_STREAMINFO_SIZE); - skip_bits(&gb, 16); /* skip min blocksize */ - s->max_blocksize = get_bits(&gb, 16); + bitstream_skip(&bc, 16); /* skip min blocksize */ + s->max_blocksize = bitstream_read(&bc, 16); if (s->max_blocksize < FLAC_MIN_BLOCKSIZE) { av_log(avctx, AV_LOG_WARNING, "invalid max blocksize: %d\n", s->max_blocksize); s->max_blocksize = 16; } - skip_bits(&gb, 24); /* skip min frame size */ - s->max_framesize = get_bits_long(&gb, 24); - - s->samplerate = get_bits_long(&gb, 20); - s->channels = get_bits(&gb, 3) + 1; - s->bps = get_bits(&gb, 5) + 1; + bitstream_skip(&bc, 24); /* skip min frame size */ + s->max_framesize = bitstream_read(&bc, 24); + s->samplerate = bitstream_read(&bc, 20); + s->channels = bitstream_read(&bc, 3) + 1; + s->bps = bitstream_read(&bc, 5) + 1; avctx->channels = s->channels; avctx->sample_rate = s->samplerate; @@ -230,11 +230,11 @@ void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s, av_get_channel_layout_nb_channels(avctx->channel_layout) != avctx->channels) ff_flac_set_channel_layout(avctx); - s->samples = get_bits_long(&gb, 32) << 4; - s->samples |= get_bits(&gb, 4); + s->samples = bitstream_read(&bc, 32) << 4; + s->samples |= bitstream_read(&bc, 4); - skip_bits_long(&gb, 64); /* md5 sum */ - skip_bits_long(&gb, 64); /* md5 sum */ + bitstream_skip(&bc, 64); /* md5 sum */ + bitstream_skip(&bc, 64); /* md5 sum */ } #if LIBAVCODEC_VERSION_MAJOR < 57 diff --git a/libavcodec/flac.h b/libavcodec/flac.h index 32296820471a7..d050717fac922 100644 --- a/libavcodec/flac.h +++ b/libavcodec/flac.h @@ -28,8 +28,8 @@ #define AVCODEC_FLAC_H #include "avcodec.h" +#include "bitstream.h" #include "bytestream.h" -#include "get_bits.h" #define FLAC_STREAMINFO_SIZE 34 #define FLAC_MAX_CHANNELS 8 @@ -129,12 +129,12 @@ int ff_flac_get_max_frame_size(int blocksize, int ch, int bps); /** * Validate and decode a frame header. * @param avctx AVCodecContext to use as av_log() context - * @param gb GetBitContext from which to read frame header + * @param bc BitstreamContext from which to read frame header * @param[out] fi frame information * @param log_level_offset log level offset. can be used to silence error messages. * @return non-zero on error, 0 if ok */ -int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, +int ff_flac_decode_frame_header(AVCodecContext *avctx, BitstreamContext *bc, FLACFrameInfo *fi, int log_level_offset); void ff_flac_set_channel_layout(AVCodecContext *avctx); diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c index cb394f2bdb374..8150ec4d11314 100644 --- a/libavcodec/flac_parser.c +++ b/libavcodec/flac_parser.c @@ -92,9 +92,9 @@ typedef struct FLACParseContext { static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf, FLACFrameInfo *fi) { - GetBitContext gb; - init_get_bits(&gb, buf, MAX_FRAME_HEADER_SIZE * 8); - return !ff_flac_decode_frame_header(avctx, &gb, fi, 127); + BitstreamContext bc; + bitstream_init8(&bc, buf, MAX_FRAME_HEADER_SIZE); + return !ff_flac_decode_frame_header(avctx, &bc, fi, 127); } /** diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c index 78be2adab3baa..10e1c488b5fb1 100644 --- a/libavcodec/flacdec.c +++ b/libavcodec/flacdec.c @@ -34,10 +34,10 @@ #include #include "avcodec.h" +#include "bitstream.h" #include "internal.h" -#include "get_bits.h" #include "bytestream.h" -#include "golomb_legacy.h" +#include "golomb.h" #include "flac.h" #include "flacdata.h" #include "flacdsp.h" @@ -46,7 +46,7 @@ typedef struct FLACContext { FLACSTREAMINFO AVCodecContext *avctx; ///< parent AVCodecContext - GetBitContext gb; ///< GetBitContext initialized to start at the current frame + BitstreamContext bc; ///< BitstreamContext initialized to start at the current frame int blocksize; ///< number of samples in the current frame int sample_shift; ///< shift required to make output samples 16-bit or 32-bit @@ -203,14 +203,14 @@ static int decode_residuals(FLACContext *s, int32_t *decoded, int pred_order) int rice_bits, rice_esc; int samples; - method_type = get_bits(&s->gb, 2); + method_type = bitstream_read(&s->bc, 2); if (method_type > 1) { av_log(s->avctx, AV_LOG_ERROR, "illegal residual coding method %d\n", method_type); return AVERROR_INVALIDDATA; } - rice_order = get_bits(&s->gb, 4); + rice_order = bitstream_read(&s->bc, 4); samples= s->blocksize >> rice_order; if (pred_order > samples) { @@ -225,14 +225,14 @@ static int decode_residuals(FLACContext *s, int32_t *decoded, int pred_order) decoded += pred_order; i= pred_order; for (partition = 0; partition < (1 << rice_order); partition++) { - tmp = get_bits(&s->gb, rice_bits); + tmp = bitstream_read(&s->bc, rice_bits); if (tmp == rice_esc) { - tmp = get_bits(&s->gb, 5); + tmp = bitstream_read(&s->bc, 5); for (; i < samples; i++) - *decoded++ = get_sbits_long(&s->gb, tmp); + *decoded++ = bitstream_read_signed(&s->bc, tmp); } else { for (; i < samples; i++) { - *decoded++ = get_sr_golomb_flac(&s->gb, tmp, INT_MAX, 0); + *decoded++ = get_sr_golomb_flac(&s->bc, tmp, INT_MAX, 0); } } i= 0; @@ -249,7 +249,7 @@ static int decode_subframe_fixed(FLACContext *s, int32_t *decoded, /* warm up samples */ for (i = 0; i < pred_order; i++) { - decoded[i] = get_sbits_long(&s->gb, bps); + decoded[i] = bitstream_read_signed(&s->bc, bps); } if ((ret = decode_residuals(s, decoded, pred_order)) < 0) @@ -300,15 +300,15 @@ static int decode_subframe_lpc(FLACContext *s, int32_t *decoded, int pred_order, /* warm up samples */ for (i = 0; i < pred_order; i++) { - decoded[i] = get_sbits_long(&s->gb, bps); + decoded[i] = bitstream_read_signed(&s->bc, bps); } - coeff_prec = get_bits(&s->gb, 4) + 1; + coeff_prec = bitstream_read(&s->bc, 4) + 1; if (coeff_prec == 16) { av_log(s->avctx, AV_LOG_ERROR, "invalid coeff precision\n"); return AVERROR_INVALIDDATA; } - qlevel = get_sbits(&s->gb, 5); + qlevel = bitstream_read_signed(&s->bc, 5); if (qlevel < 0) { av_log(s->avctx, AV_LOG_ERROR, "qlevel %d not supported, maybe buggy stream\n", qlevel); @@ -316,7 +316,7 @@ static int decode_subframe_lpc(FLACContext *s, int32_t *decoded, int pred_order, } for (i = 0; i < pred_order; i++) { - coeffs[pred_order - i - 1] = get_sbits(&s->gb, coeff_prec); + coeffs[pred_order - i - 1] = bitstream_read_signed(&s->bc, coeff_prec); } if ((ret = decode_residuals(s, decoded, pred_order)) < 0) @@ -342,24 +342,24 @@ static inline int decode_subframe(FLACContext *s, int channel) bps++; } - if (get_bits1(&s->gb)) { + if (bitstream_read_bit(&s->bc)) { av_log(s->avctx, AV_LOG_ERROR, "invalid subframe padding\n"); return AVERROR_INVALIDDATA; } - type = get_bits(&s->gb, 6); + type = bitstream_read(&s->bc, 6); - if (get_bits1(&s->gb)) { - int left = get_bits_left(&s->gb); + if (bitstream_read_bit(&s->bc)) { + int left = bitstream_bits_left(&s->bc); wasted = 1; if ( left < 0 || - (left < bps && !show_bits_long(&s->gb, left)) || - !show_bits_long(&s->gb, bps)) { + (left < bps && !bitstream_peek(&s->bc, left)) || + !bitstream_peek(&s->bc, bps)) { av_log(s->avctx, AV_LOG_ERROR, "Invalid number of wasted bits > available bits (%d) - left=%d\n", bps, left); return AVERROR_INVALIDDATA; } - while (!get_bits1(&s->gb)) + while (!bitstream_read_bit(&s->bc)) wasted++; bps -= wasted; } @@ -370,12 +370,12 @@ static inline int decode_subframe(FLACContext *s, int channel) //FIXME use av_log2 for types if (type == 0) { - tmp = get_sbits_long(&s->gb, bps); + tmp = bitstream_read_signed(&s->bc, bps); for (i = 0; i < s->blocksize; i++) decoded[i] = tmp; } else if (type == 1) { for (i = 0; i < s->blocksize; i++) - decoded[i] = get_sbits_long(&s->gb, bps); + decoded[i] = bitstream_read_signed(&s->bc, bps); } else if ((type >= 8) && (type <= 12)) { if ((ret = decode_subframe_fixed(s, decoded, type & ~0x8, bps)) < 0) return ret; @@ -399,10 +399,10 @@ static inline int decode_subframe(FLACContext *s, int channel) static int decode_frame(FLACContext *s) { int i, ret; - GetBitContext *gb = &s->gb; + BitstreamContext *bc = &s->bc; FLACFrameInfo fi; - if ((ret = ff_flac_decode_frame_header(s->avctx, gb, &fi, 0)) < 0) { + if ((ret = ff_flac_decode_frame_header(s->avctx, bc, &fi, 0)) < 0) { av_log(s->avctx, AV_LOG_ERROR, "invalid frame header\n"); return ret; } @@ -471,10 +471,10 @@ static int decode_frame(FLACContext *s) return ret; } - align_get_bits(gb); + bitstream_align(bc); /* frame footer */ - skip_bits(gb, 16); /* data crc */ + bitstream_skip(bc, 16); /* data crc */ return 0; } @@ -513,12 +513,12 @@ static int flac_decode_frame(AVCodecContext *avctx, void *data, } /* decode frame */ - init_get_bits(&s->gb, buf, buf_size*8); + bitstream_init8(&s->bc, buf, buf_size); if ((ret = decode_frame(s)) < 0) { av_log(s->avctx, AV_LOG_ERROR, "decode_frame() failed\n"); return ret; } - bytes_read = (get_bits_count(&s->gb)+7)/8; + bytes_read = (bitstream_tell(&s->bc) + 7) / 8; /* get output buffer */ frame->nb_samples = s->blocksize; diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c index 2745b17a1cb03..631f02f0dba24 100644 --- a/libavcodec/flacenc.c +++ b/libavcodec/flacenc.c @@ -26,7 +26,7 @@ #include "avcodec.h" #include "bswapdsp.h" -#include "golomb_legacy.h" +#include "golomb.h" #include "internal.h" #include "lpc.h" #include "flac.h" From 15f1cc09a406cf6296818d475a256902235eefc4 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sat, 29 Apr 2017 02:15:31 +0000 Subject: [PATCH 0312/2557] flac: Postpone unlikely condition checks About 2% speedup on gcc-6.3. Signed-off-by: Diego Biurrun --- libavcodec/flacdec.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c index 10e1c488b5fb1..1caed9151f107 100644 --- a/libavcodec/flacdec.c +++ b/libavcodec/flacdec.c @@ -204,26 +204,27 @@ static int decode_residuals(FLACContext *s, int32_t *decoded, int pred_order) int samples; method_type = bitstream_read(&s->bc, 2); + rice_order = bitstream_read(&s->bc, 4); + + samples = s->blocksize >> rice_order; + rice_bits = 4 + method_type; + rice_esc = (1 << rice_bits) - 1; + + decoded += pred_order; + i = pred_order; + if (method_type > 1) { av_log(s->avctx, AV_LOG_ERROR, "illegal residual coding method %d\n", method_type); return AVERROR_INVALIDDATA; } - rice_order = bitstream_read(&s->bc, 4); - - samples= s->blocksize >> rice_order; if (pred_order > samples) { av_log(s->avctx, AV_LOG_ERROR, "invalid predictor order: %i > %i\n", pred_order, samples); return AVERROR_INVALIDDATA; } - rice_bits = 4 + method_type; - rice_esc = (1 << rice_bits) - 1; - - decoded += pred_order; - i= pred_order; for (partition = 0; partition < (1 << rice_order); partition++) { tmp = bitstream_read(&s->bc, rice_bits); if (tmp == rice_esc) { From 0f5ad12ba2b538cb329c507ecc914e06bfa70194 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sat, 29 Apr 2017 02:15:32 +0000 Subject: [PATCH 0313/2557] flac: Use a local cache for decode_residual() About an additional 4% speedup. Signed-off-by: Diego Biurrun --- libavcodec/flacdec.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c index 1caed9151f107..87ab2e5bfbdc8 100644 --- a/libavcodec/flacdec.c +++ b/libavcodec/flacdec.c @@ -199,12 +199,13 @@ static int get_metadata_size(const uint8_t *buf, int buf_size) static int decode_residuals(FLACContext *s, int32_t *decoded, int pred_order) { + BitstreamContext bc = s->bc; int i, tmp, partition, method_type, rice_order; int rice_bits, rice_esc; int samples; - method_type = bitstream_read(&s->bc, 2); - rice_order = bitstream_read(&s->bc, 4); + method_type = bitstream_read(&bc, 2); + rice_order = bitstream_read(&bc, 4); samples = s->blocksize >> rice_order; rice_bits = 4 + method_type; @@ -226,19 +227,21 @@ static int decode_residuals(FLACContext *s, int32_t *decoded, int pred_order) } for (partition = 0; partition < (1 << rice_order); partition++) { - tmp = bitstream_read(&s->bc, rice_bits); + tmp = bitstream_read(&bc, rice_bits); if (tmp == rice_esc) { - tmp = bitstream_read(&s->bc, 5); + tmp = bitstream_read(&bc, 5); for (; i < samples; i++) - *decoded++ = bitstream_read_signed(&s->bc, tmp); + *decoded++ = bitstream_read_signed(&bc, tmp); } else { for (; i < samples; i++) { - *decoded++ = get_sr_golomb_flac(&s->bc, tmp, INT_MAX, 0); + *decoded++ = get_sr_golomb_flac(&bc, tmp, INT_MAX, 0); } } i= 0; } + s->bc = bc; + return 0; } From 825e463a170c7004c63030dc484b2b2de869227b Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 8 Jul 2017 13:18:39 +0200 Subject: [PATCH 0314/2557] build: Add feature test macros for glibc 2.19+ glibc introduced _DEFAULT_SOURCE in version 2.19 to replace _BSD_SOURCE and _SVID_SOURCE, which were deprecated in version 2.20. Add _DEFAULT_SOURCE where the latter two are used to be forwards-compatible and avoid warnings about the use of deprecated definitions. --- libavformat/os_support.c | 1 + libavformat/udp.c | 1 + libswscale/utils.c | 1 + 3 files changed, 3 insertions(+) diff --git a/libavformat/os_support.c b/libavformat/os_support.c index 6a0c1fa7fcc7e..c125dbe9ba3aa 100644 --- a/libavformat/os_support.c +++ b/libavformat/os_support.c @@ -21,6 +21,7 @@ */ /* needed by inet_aton() */ +#define _DEFAULT_SOURCE #define _SVID_SOURCE #include "config.h" diff --git a/libavformat/udp.c b/libavformat/udp.c index 9d4c130e5bd70..a29eb1bd33179 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -24,6 +24,7 @@ * UDP protocol */ +#define _DEFAULT_SOURCE #define _BSD_SOURCE /* Needed for using struct ip_mreq with recent glibc */ #include "avformat.h" diff --git a/libswscale/utils.c b/libswscale/utils.c index 248a8081ff634..6b17955f5447d 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -20,6 +20,7 @@ #include "config.h" +#define _DEFAULT_SOURCE #define _SVID_SOURCE // needed for MAP_ANONYMOUS #include #include From 95ce02b35d3d1bb16111031df1d82a6e4d894d36 Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Wed, 12 Jul 2017 19:45:46 -0400 Subject: [PATCH 0315/2557] rmdec: don't ignore the return value of av_get_packet() --- libavformat/rmdec.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index 2e93f1d4e86f0..b8ba24e928597 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -722,6 +722,7 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, int *seq, int flags, int64_t timestamp) { RMDemuxContext *rm = s->priv_data; + int ret; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { rm->current_stream= st->id; @@ -778,11 +779,15 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, } else return -1; } else { - av_get_packet(pb, pkt, len); + ret = av_get_packet(pb, pkt, len); + if (ret < 0) + return ret; rm_ac3_swap_bytes(st, pkt); } } else - av_get_packet(pb, pkt, len); + ret = av_get_packet(pb, pkt, len); + if (ret < 0) + return ret; pkt->stream_index = st->index; @@ -798,14 +803,18 @@ ff_rm_retrieve_cache (AVFormatContext *s, AVIOContext *pb, AVStream *st, RMStream *ast, AVPacket *pkt) { RMDemuxContext *rm = s->priv_data; + int ret; assert (rm->audio_pkt_cnt > 0); if (ast->deint_id == DEINT_ID_VBRF || - ast->deint_id == DEINT_ID_VBRS) - av_get_packet(pb, pkt, ast->sub_packet_lengths[ast->sub_packet_cnt - rm->audio_pkt_cnt]); + ast->deint_id == DEINT_ID_VBRS) { + ret = av_get_packet(pb, pkt, ast->sub_packet_lengths[ast->sub_packet_cnt - rm->audio_pkt_cnt]); + if (ret < 0) + return ret; + } else { - int ret = av_new_packet(pkt, st->codecpar->block_align); + ret = av_new_packet(pkt, st->codecpar->block_align); if (ret < 0) return ret; memcpy(pkt->data, ast->pkt.data + st->codecpar->block_align * //FIXME avoid this From ce1a99d870c05b639512920cd3a1dee3e41d323f Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Thu, 20 Jul 2017 14:43:53 +0200 Subject: [PATCH 0316/2557] hevc: Make sure to update the current frame transfer characteristic Otherwise the first decoded frame will still be tagged with the original transfer instead of the alternative one. Signed-off-by: Vittorio Giovara --- libavcodec/hevcdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index ac0b1a3c1d151..f6bbb7051e3fa 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2410,7 +2410,7 @@ static int set_side_data(HEVCContext *s) if (s->sei.alternative_transfer.present && av_color_transfer_name(s->sei.alternative_transfer.preferred_transfer_characteristics) && s->sei.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) { - s->avctx->color_trc = s->sei.alternative_transfer.preferred_transfer_characteristics; + s->avctx->color_trc = out->color_trc = s->sei.alternative_transfer.preferred_transfer_characteristics; } return 0; From 48a5c35346aeded1c65b8709bbb085fa4e705c91 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 1 Jul 2017 10:49:58 +0200 Subject: [PATCH 0317/2557] caf: add an Opus tag CC: libav-stable@libav.org --- libavformat/caf.c | 1 + libavformat/cafdec.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/libavformat/caf.c b/libavformat/caf.c index cf128d56242e1..c299cad01ba89 100644 --- a/libavformat/caf.c +++ b/libavformat/caf.c @@ -49,6 +49,7 @@ const AVCodecTag ff_codec_caf_tags[] = { { AV_CODEC_ID_QCELP, MKBETAG('Q','c','l','p') }, { AV_CODEC_ID_QDM2, MKBETAG('Q','D','M','2') }, { AV_CODEC_ID_QDM2, MKBETAG('Q','D','M','C') }, + { AV_CODEC_ID_OPUS, MKBETAG('o','p','u','s') }, /* currently unsupported codecs */ /*{ AC-3 over S/PDIF MKBETAG('c','a','c','3') },*/ /*{ MPEG4CELP MKBETAG('c','e','l','p') },*/ diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c index efc8c49c4a877..d6b6007a1dcda 100644 --- a/libavformat/cafdec.c +++ b/libavformat/cafdec.c @@ -156,6 +156,14 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size) avio_skip(pb, size - ALAC_NEW_KUKI); } st->codecpar->extradata_size = ALAC_HEADER; + } else if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) { + // The data layout for Opus is currently unknown, so we do not export + // extradata at all. Multichannel streams are not supported. + if (st->codecpar->channels > 2) { + avpriv_request_sample(s, "multichannel Opus in CAF"); + return AVERROR_PATCHWELCOME; + } + avio_skip(pb, size); } else { st->codecpar->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!st->codecpar->extradata) From 9b9285bbf18e3bca87ec4969f661a4b321756cd5 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 10 Jul 2017 15:59:38 +0200 Subject: [PATCH 0318/2557] dxva: DXVA2_ModeHEVC_VLD_Main10 does not support Main This mode apparently does not support decoding of HEVC Main (8 bit). With D3D11 and Intel drivers on Windows 10 I get green corruption, while using DXVA2_ModeHEVC_VLD_Main works. Signed-off-by: Anton Khirnov --- libavcodec/dxva2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index a60604a84f36d..9ceb6236d4eef 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -63,8 +63,7 @@ static const int prof_h264_high[] = {FF_PROFILE_H264_CONSTRAINED_BASELINE, FF_PROFILE_UNKNOWN}; static const int prof_hevc_main[] = {FF_PROFILE_HEVC_MAIN, FF_PROFILE_UNKNOWN}; -static const int prof_hevc_main10[] = {FF_PROFILE_HEVC_MAIN, - FF_PROFILE_HEVC_MAIN_10, +static const int prof_hevc_main10[] = {FF_PROFILE_HEVC_MAIN_10, FF_PROFILE_UNKNOWN}; static const dxva_mode dxva_modes[] = { From 2b1324bd167553f49736e4eaa94f96da9982925e Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 16 Jul 2017 12:43:09 +0200 Subject: [PATCH 0319/2557] lavf: allow avformat_close_input() with NULL This is consistent with how other destructors behave. Signed-off-by: Anton Khirnov --- libavformat/utils.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index eaba47391401d..bbdc2cdb8aba5 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2733,7 +2733,12 @@ void avformat_free_context(AVFormatContext *s) void avformat_close_input(AVFormatContext **ps) { AVFormatContext *s = *ps; - AVIOContext *pb = s->pb; + AVIOContext *pb; + + if (!*ps) + return; + + pb = s->pb; if ((s->iformat && s->iformat->flags & AVFMT_NOFILE) || (s->flags & AVFMT_FLAG_CUSTOM_IO)) From 2fd6e7d077f590e4d7195356f9baeb271f8b9ae2 Mon Sep 17 00:00:00 2001 From: "Huang, Zhengxu" Date: Fri, 21 Jul 2017 12:12:44 +0800 Subject: [PATCH 0320/2557] libavcodec/mjpeg_qsv: Add QSV MJPEG encoder usage: -hwaccel qsv -c:v h264_qsv -i in -c:v mjpeg_qsv -global_quality 80 -f mjpeg out Signed-off-by: ChaoX A Liu Signed-off-by: Zhengxu Huang Signed-off-by: Andrew Zhang --- Changelog | 1 + configure | 2 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/qsv.c | 3 ++ libavcodec/qsvenc.c | 95 +++++++++++++++++++++++++++++++++++++++- libavcodec/qsvenc_jpeg.c | 91 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 libavcodec/qsvenc_jpeg.c diff --git a/Changelog b/Changelog index adcca3fcc5381..82e3e3a0ef31e 100644 --- a/Changelog +++ b/Changelog @@ -17,6 +17,7 @@ version : - ClearVideo decoder (I-frames only) - support for decoding through D3D11VA in avconv - Cinepak encoder +- Intel QSV-accelerated MJPEG encoding version 12: diff --git a/configure b/configure index d92ce33e6d1b3..35ae03182a6a5 100755 --- a/configure +++ b/configure @@ -2279,6 +2279,8 @@ hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser hevc_qsv_hwaccel qsvde hevc_qsv_encoder_select="hevc_ps qsvenc" hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" hevc_vaapi_encoder_select="vaapi_encode golomb" +mjpeg_qsv_encoder_deps="libmfx" +mjpeg_qsv_encoder_select="qsvenc" mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG" mjpeg_vaapi_encoder_select="vaapi_encode jpegtables" mpeg2_mmal_decoder_deps="mmal" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2b9158822dddb..12bf8fecb740b 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -319,6 +319,7 @@ OBJS-$(CONFIG_MIMIC_DECODER) += mimic.o OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpegenc_common.o OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o +OBJS-$(CONFIG_MJPEG_QSV_ENCODER) += qsvenc_jpeg.o OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER) += vaapi_encode_mjpeg.o OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 5635ae150c96a..3fcea5be0dd87 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -509,6 +509,7 @@ void avcodec_register_all(void) REGISTER_ENCODER(HEVC_NVENC, hevc_nvenc); REGISTER_ENCODER(HEVC_QSV, hevc_qsv); REGISTER_ENCODER(HEVC_VAAPI, hevc_vaapi); + REGISTER_ENCODER(MJPEG_QSV, mjpeg_qsv); REGISTER_ENCODER(MJPEG_VAAPI, mjpeg_vaapi); REGISTER_ENCODER(MPEG2_QSV, mpeg2_qsv); REGISTER_ENCODER(MPEG2_VAAPI, mpeg2_vaapi); diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index 30d612f0e1dac..a8ae65622c915 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -56,6 +57,8 @@ int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id) case AV_CODEC_ID_VP8: return MFX_CODEC_VP8; #endif + case AV_CODEC_ID_MJPEG: + return MFX_CODEC_JPEG; default: break; } diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 7c6ad09dda450..c7e5947361d9e 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -353,6 +353,64 @@ static int rc_supported(QSVEncContext *q) return 1; } +static int init_video_param_jpeg(AVCodecContext *avctx, QSVEncContext *q) +{ + enum AVPixelFormat sw_format = avctx->pix_fmt == AV_PIX_FMT_QSV ? + avctx->sw_pix_fmt : avctx->pix_fmt; + const AVPixFmtDescriptor *desc; + int ret; + + ret = ff_qsv_codec_id_to_mfx(avctx->codec_id); + if (ret < 0) + return AVERROR_BUG; + q->param.mfx.CodecId = ret; + + if (avctx->level > 0) + q->param.mfx.CodecLevel = avctx->level; + q->param.mfx.CodecProfile = q->profile; + + desc = av_pix_fmt_desc_get(sw_format); + if (!desc) + return AVERROR_BUG; + + ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); + + q->param.mfx.FrameInfo.CropX = 0; + q->param.mfx.FrameInfo.CropY = 0; + q->param.mfx.FrameInfo.CropW = avctx->width; + q->param.mfx.FrameInfo.CropH = avctx->height; + q->param.mfx.FrameInfo.AspectRatioW = avctx->sample_aspect_ratio.num; + q->param.mfx.FrameInfo.AspectRatioH = avctx->sample_aspect_ratio.den; + q->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; + q->param.mfx.FrameInfo.BitDepthLuma = desc->comp[0].depth; + q->param.mfx.FrameInfo.BitDepthChroma = desc->comp[0].depth; + q->param.mfx.FrameInfo.Shift = desc->comp[0].depth > 8; + + q->param.mfx.FrameInfo.Width = FFALIGN(avctx->width, 16); + q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, 16); + + if (avctx->hw_frames_ctx) { + AVHWFramesContext *frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; + AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; + q->param.mfx.FrameInfo.Width = frames_hwctx->surfaces[0].Info.Width; + q->param.mfx.FrameInfo.Height = frames_hwctx->surfaces[0].Info.Height; + } + + if (avctx->framerate.den > 0 && avctx->framerate.num > 0) { + q->param.mfx.FrameInfo.FrameRateExtN = avctx->framerate.num; + q->param.mfx.FrameInfo.FrameRateExtD = avctx->framerate.den; + } else { + q->param.mfx.FrameInfo.FrameRateExtN = avctx->time_base.den; + q->param.mfx.FrameInfo.FrameRateExtD = avctx->time_base.num; + } + + q->param.mfx.Interleaved = 1; + q->param.mfx.Quality = av_clip(avctx->global_quality, 1, 100); + q->param.mfx.RestartInterval = 0; + + return 0; +} + static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) { enum AVPixelFormat sw_format = avctx->pix_fmt == AV_PIX_FMT_QSV ? @@ -568,6 +626,24 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; } +static int qsv_retrieve_enc_jpeg_params(AVCodecContext *avctx, QSVEncContext *q) +{ + int ret = 0; + + ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param); + if (ret < 0) + return ff_qsv_print_error(avctx, ret, + "Error calling GetVideoParam"); + + q->packet_size = q->param.mfx.BufferSizeInKB * 1000; + + // for qsv mjpeg the return value maybe 0 so alloc the buffer + if (q->packet_size == 0) + q->packet_size = q->param.mfx.FrameInfo.Height * q->param.mfx.FrameInfo.Width * 4; + + return 0; +} + static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) { AVCPBProperties *cpb_props; @@ -770,7 +846,15 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) if (ret < 0) return ret; - ret = init_video_param(avctx, q); + // in the mfxInfoMFX struct, JPEG is different from other codecs + switch (avctx->codec_id) { + case AV_CODEC_ID_MJPEG: + ret = init_video_param_jpeg(avctx, q); + break; + default: + ret = init_video_param(avctx, q); + break; + } if (ret < 0) return ret; @@ -830,7 +914,14 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) ff_qsv_print_warning(avctx, ret, "Warning in encoder initialization"); - ret = qsv_retrieve_enc_params(avctx, q); + switch (avctx->codec_id) { + case AV_CODEC_ID_MJPEG: + ret = qsv_retrieve_enc_jpeg_params(avctx, q); + break; + default: + ret = qsv_retrieve_enc_params(avctx, q); + break; + } if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error retrieving encoding parameters.\n"); return ret; diff --git a/libavcodec/qsvenc_jpeg.c b/libavcodec/qsvenc_jpeg.c new file mode 100644 index 0000000000000..3fa17f13abb68 --- /dev/null +++ b/libavcodec/qsvenc_jpeg.c @@ -0,0 +1,91 @@ +/* + * Intel MediaSDK QSV based MJPEG encoder + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include + +#include + +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "internal.h" +#include "h264.h" +#include "qsv.h" +#include "qsv_internal.h" +#include "qsvenc.h" + +typedef struct QSVMJPEGEncContext { + AVClass *class; + QSVEncContext qsv; +} QSVMJPEGEncContext; + +static av_cold int qsv_enc_init(AVCodecContext *avctx) +{ + QSVMJPEGEncContext *q = avctx->priv_data; + + return ff_qsv_enc_init(avctx, &q->qsv); +} + +static int qsv_enc_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + QSVMJPEGEncContext *q = avctx->priv_data; + + return ff_qsv_encode(avctx, &q->qsv, pkt, frame, got_packet); +} + +static av_cold int qsv_enc_close(AVCodecContext *avctx) +{ + QSVMJPEGEncContext *q = avctx->priv_data; + + return ff_qsv_enc_close(avctx, &q->qsv); +} + +#define OFFSET(x) offsetof(QSVMJPEGEncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { NULL }, +}; + +static const AVClass class = { + .class_name = "mjpeg_qsv encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_mjpeg_qsv_encoder = { + .name = "mjpeg_qsv", + .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Intel Quick Sync Video acceleration)"), + .priv_data_size = sizeof(QSVMJPEGEncContext), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MJPEG, + .init = qsv_enc_init, + .encode2 = qsv_enc_frame, + .close = qsv_enc_close, + .capabilities = AV_CODEC_CAP_DELAY, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE }, + .priv_class = &class, +}; From 550cb6a85d0f7211289f7a789527d48cb29460ff Mon Sep 17 00:00:00 2001 From: "Huang, Zhengxu" Date: Thu, 20 Jul 2017 16:16:44 +0800 Subject: [PATCH 0321/2557] lavf/vf_deinterlace_qsv: Enable the qsv deinterlace vpp The current qsv deinterlace module does not work at all because MSDK needs user to pass extra parameters to enable hint functions,such as denoise,deinterlace,composition and so on. Usage:-hwaccel qsv -r 25 -c:v h264_qsv -i in -vf deinterlace_qsv=bob -b 2M -maxrate 3M -c:v h264_qsv -y out.h264 Signed-off-by: ChaoX A Liu Signed-off-by: Zhengxu Huang Signed-off-by: Andrew Zhang Change-Id: I9e7ddcf884f2788c2820f6c98affacfb9d8f3287 Signed-off-by: Maxym Dmytrychenko --- libavfilter/vf_deinterlace_qsv.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/libavfilter/vf_deinterlace_qsv.c b/libavfilter/vf_deinterlace_qsv.c index 5cda2868395f2..2360491d3f794 100644 --- a/libavfilter/vf_deinterlace_qsv.c +++ b/libavfilter/vf_deinterlace_qsv.c @@ -68,7 +68,9 @@ typedef struct QSVDeintContext { int nb_surface_ptrs; mfxExtOpaqueSurfaceAlloc opaque_alloc; - mfxExtBuffer *ext_buffers[1]; + mfxExtVPPDeinterlacing deint_conf; + mfxExtBuffer *ext_buffers[2]; + int num_ext_buffers; QSVFrame *work_frames; @@ -76,6 +78,9 @@ typedef struct QSVDeintContext { int got_output_frame; int eof; + + /* option for Deinterlacing algorithm to be used */ + int mode; } QSVDeintContext; static void qsvdeint_uninit(AVFilterContext *ctx) @@ -211,6 +216,12 @@ static int init_out_session(AVFilterContext *ctx) memset(&par, 0, sizeof(par)); + s->deint_conf.Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING; + s->deint_conf.Header.BufferSz = sizeof(s->deint_conf); + s->deint_conf.Mode = s->mode; + + s->ext_buffers[s->num_ext_buffers++] = (mfxExtBuffer *)&s->deint_conf; + if (opaque) { s->surface_ptrs = av_mallocz_array(hw_frames_hwctx->nb_surfaces, sizeof(*s->surface_ptrs)); @@ -229,10 +240,7 @@ static int init_out_session(AVFilterContext *ctx) s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION; s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc); - s->ext_buffers[0] = (mfxExtBuffer*)&s->opaque_alloc; - - par.ExtParam = s->ext_buffers; - par.NumExtParam = FF_ARRAY_ELEMS(s->ext_buffers); + s->ext_buffers[s->num_ext_buffers++] = (mfxExtBuffer *)&s->opaque_alloc; par.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY | MFX_IOPATTERN_OUT_OPAQUE_MEMORY; } else { @@ -260,6 +268,9 @@ static int init_out_session(AVFilterContext *ctx) par.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY; } + par.ExtParam = s->ext_buffers; + par.NumExtParam = s->num_ext_buffers; + par.AsyncDepth = 1; // TODO async par.vpp.In = hw_frames_hwctx->surfaces[0].Info; @@ -534,6 +545,9 @@ static int qsvdeint_request_frame(AVFilterLink *outlink) #define OFFSET(x) offsetof(QSVDeintContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM static const AVOption options[] = { + { "mode", "set deinterlace mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MFX_DEINTERLACING_ADVANCED}, MFX_DEINTERLACING_BOB, MFX_DEINTERLACING_ADVANCED, FLAGS, "mode"}, + { "bob", "bob algorithm", 0, AV_OPT_TYPE_CONST, {.i64 = MFX_DEINTERLACING_BOB}, MFX_DEINTERLACING_BOB, MFX_DEINTERLACING_ADVANCED, FLAGS, "mode"}, + { "advanced", "Motion adaptive algorithm", 0, AV_OPT_TYPE_CONST, {.i64 = MFX_DEINTERLACING_ADVANCED}, MFX_DEINTERLACING_BOB, MFX_DEINTERLACING_ADVANCED, FLAGS, "mode"}, { NULL }, }; From 80e919b17435da18c0f2be6403a0315cf4b40a1a Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Tue, 25 Jul 2017 18:04:32 -0400 Subject: [PATCH 0322/2557] rmdec: add missing brackets to compound statement Accidentally left out of 95ce02b35d3d1bb16111031df1d82a6e4d894d36. --- libavformat/rmdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index b8ba24e928597..1d7df544a11bf 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -784,10 +784,11 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, return ret; rm_ac3_swap_bytes(st, pkt); } - } else + } else { ret = av_get_packet(pb, pkt, len); if (ret < 0) return ret; + } pkt->stream_index = st->index; From 47399ccdfd93d337c96c76fbf591f0e3637131ef Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 22 Jul 2017 23:05:13 +0200 Subject: [PATCH 0323/2557] lavc, lavu: move frame cropping to a convenience function Signed-off-by: Anton Khirnov --- doc/APIchanges | 3 ++ libavcodec/decode.c | 89 +-------------------------------------- libavutil/frame.c | 100 ++++++++++++++++++++++++++++++++++++++++++++ libavutil/frame.h | 34 +++++++++++++++ libavutil/version.h | 2 +- 5 files changed, 140 insertions(+), 88 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 0f7c839573e9c..30a8f809d1ddb 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2017-03-23 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavu 56.3.0 - frame.h + Add av_frame_apply_cropping(). + 2017-xx-xx - xxxxxxx - lavc 58.4.0 - avcodec.h DXVA2 and D3D11 hardware accelerated decoding now supports the new hwaccel API, which can create the decoder context and allocate hardware frame automatically. diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 175a6fae4c568..9644e89f48524 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -446,44 +446,8 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke return 0; } -static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame, - const AVPixFmtDescriptor *desc) -{ - int i, j; - - for (i = 0; frame->data[i]; i++) { - const AVComponentDescriptor *comp = NULL; - int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0; - int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; - - if (desc->flags & (AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_PSEUDOPAL) && i == 1) { - offsets[i] = 0; - break; - } - - /* find any component descriptor for this plane */ - for (j = 0; j < desc->nb_components; j++) { - if (desc->comp[j].plane == i) { - comp = &desc->comp[j]; - break; - } - } - if (!comp) - return AVERROR_BUG; - - offsets[i] = (frame->crop_top >> shift_y) * frame->linesize[i] + - (frame->crop_left >> shift_x) * comp->step; - } - - return 0; -} - static int apply_cropping(AVCodecContext *avctx, AVFrame *frame) { - const AVPixFmtDescriptor *desc; - size_t offsets[4]; - int i; - /* make sure we are noisy about decoders returning invalid cropping data */ if (frame->crop_left >= INT_MAX - frame->crop_right || frame->crop_top >= INT_MAX - frame->crop_bottom || @@ -504,57 +468,8 @@ static int apply_cropping(AVCodecContext *avctx, AVFrame *frame) if (!avctx->apply_cropping) return 0; - desc = av_pix_fmt_desc_get(frame->format); - if (!desc) - return AVERROR_BUG; - - /* Apply just the right/bottom cropping for hwaccel formats. Bitstream - * formats cannot be easily handled here either (and corresponding decoders - * should not export any cropping anyway), so do the same for those as well. - * */ - if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) { - frame->width -= frame->crop_right; - frame->height -= frame->crop_bottom; - frame->crop_right = 0; - frame->crop_bottom = 0; - return 0; - } - - /* calculate the offsets for each plane */ - calc_cropping_offsets(offsets, frame, desc); - - /* adjust the offsets to avoid breaking alignment */ - if (!(avctx->flags & AV_CODEC_FLAG_UNALIGNED)) { - int log2_crop_align = frame->crop_left ? av_ctz(frame->crop_left) : INT_MAX; - int min_log2_align = INT_MAX; - - for (i = 0; frame->data[i]; i++) { - int log2_align = offsets[i] ? av_ctz(offsets[i]) : INT_MAX; - min_log2_align = FFMIN(log2_align, min_log2_align); - } - - /* we assume, and it should always be true, that the data alignment is - * related to the cropping alignment by a constant power-of-2 factor */ - if (log2_crop_align < min_log2_align) - return AVERROR_BUG; - - if (min_log2_align < 5) { - frame->crop_left &= ~((1 << (5 + log2_crop_align - min_log2_align)) - 1); - calc_cropping_offsets(offsets, frame, desc); - } - } - - for (i = 0; frame->data[i]; i++) - frame->data[i] += offsets[i]; - - frame->width -= (frame->crop_left + frame->crop_right); - frame->height -= (frame->crop_top + frame->crop_bottom); - frame->crop_left = 0; - frame->crop_right = 0; - frame->crop_top = 0; - frame->crop_bottom = 0; - - return 0; + return av_frame_apply_cropping(frame, avctx->flags & AV_CODEC_FLAG_UNALIGNED ? + AV_FRAME_CROP_UNALIGNED : 0); } int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame) diff --git a/libavutil/frame.c b/libavutil/frame.c index 9cd5f9ab37cb5..db3897c2992bd 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -596,3 +596,103 @@ void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type) } } } + +static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame, + const AVPixFmtDescriptor *desc) +{ + int i, j; + + for (i = 0; frame->data[i]; i++) { + const AVComponentDescriptor *comp = NULL; + int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0; + int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; + + if (desc->flags & (AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_PSEUDOPAL) && i == 1) { + offsets[i] = 0; + break; + } + + /* find any component descriptor for this plane */ + for (j = 0; j < desc->nb_components; j++) { + if (desc->comp[j].plane == i) { + comp = &desc->comp[j]; + break; + } + } + if (!comp) + return AVERROR_BUG; + + offsets[i] = (frame->crop_top >> shift_y) * frame->linesize[i] + + (frame->crop_left >> shift_x) * comp->step; + } + + return 0; +} + +int av_frame_apply_cropping(AVFrame *frame, int flags) +{ + const AVPixFmtDescriptor *desc; + size_t offsets[4]; + int i; + + if (!(frame->width > 0 && frame->height > 0)) + return AVERROR(EINVAL); + + if (frame->crop_left >= INT_MAX - frame->crop_right || + frame->crop_top >= INT_MAX - frame->crop_bottom || + (frame->crop_left + frame->crop_right) >= frame->width || + (frame->crop_top + frame->crop_bottom) >= frame->height) + return AVERROR(ERANGE); + + desc = av_pix_fmt_desc_get(frame->format); + if (!desc) + return AVERROR_BUG; + + /* Apply just the right/bottom cropping for hwaccel formats. Bitstream + * formats cannot be easily handled here either (and corresponding decoders + * should not export any cropping anyway), so do the same for those as well. + * */ + if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) { + frame->width -= frame->crop_right; + frame->height -= frame->crop_bottom; + frame->crop_right = 0; + frame->crop_bottom = 0; + return 0; + } + + /* calculate the offsets for each plane */ + calc_cropping_offsets(offsets, frame, desc); + + /* adjust the offsets to avoid breaking alignment */ + if (!(flags & AV_FRAME_CROP_UNALIGNED)) { + int log2_crop_align = frame->crop_left ? av_ctz(frame->crop_left) : INT_MAX; + int min_log2_align = INT_MAX; + + for (i = 0; frame->data[i]; i++) { + int log2_align = offsets[i] ? av_ctz(offsets[i]) : INT_MAX; + min_log2_align = FFMIN(log2_align, min_log2_align); + } + + /* we assume, and it should always be true, that the data alignment is + * related to the cropping alignment by a constant power-of-2 factor */ + if (log2_crop_align < min_log2_align) + return AVERROR_BUG; + + if (min_log2_align < 5) { + frame->crop_left &= ~((1 << (5 + log2_crop_align - min_log2_align)) - 1); + calc_cropping_offsets(offsets, frame, desc); + } + } + + for (i = 0; frame->data[i]; i++) + frame->data[i] += offsets[i]; + + frame->width -= (frame->crop_left + frame->crop_right); + frame->height -= (frame->crop_top + frame->crop_bottom); + frame->crop_left = 0; + frame->crop_right = 0; + frame->crop_top = 0; + frame->crop_bottom = 0; + + return 0; +} diff --git a/libavutil/frame.h b/libavutil/frame.h index f9ffb5bbbf852..ff3fe46dd6d28 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -580,6 +580,40 @@ AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, */ void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type); + +/** + * Flags for frame cropping. + */ +enum { + /** + * Apply the maximum possible cropping, even if it requires setting the + * AVFrame.data[] entries to unaligned pointers. Passing unaligned data + * to Libav API is generally not allowed, and causes undefined behavior + * (such as crashes). You can pass unaligned data only to Libav APIs that + * are explicitly documented to accept it. Use this flag only if you + * absolutely know what you are doing. + */ + AV_FRAME_CROP_UNALIGNED = 1 << 0, +}; + +/** + * Crop the given video AVFrame according to its crop_left/crop_top/crop_right/ + * crop_bottom fields. If cropping is successful, the function will adjust the + * data pointers and the width/height fields, and set the crop fields to 0. + * + * In all cases, the cropping boundaries will be rounded to the inherent + * alignment of the pixel format. In some cases, such as for opaque hwaccel + * formats, the left/top cropping is ignored. The crop fields are set to 0 even + * if the cropping was rounded or ignored. + * + * @param frame the frame which should be cropped + * @param flags Some combination of AV_FRAME_CROP_* flags, or 0. + * + * @return >= 0 on success, a negative AVERROR on error. If the cropping fields + * were invalid, AVERROR(ERANGE) is returned, and nothing is changed. + */ +int av_frame_apply_cropping(AVFrame *frame, int flags); + /** * @} */ diff --git a/libavutil/version.h b/libavutil/version.h index 2c85120b642f0..53bf72efdda16 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -54,7 +54,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 2 +#define LIBAVUTIL_VERSION_MINOR 3 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 45df7adc1d9b7e8fbae5af9328baa6ab3562002b Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 22 Jul 2017 23:05:14 +0200 Subject: [PATCH 0324/2557] imgutils: add function to clear an image to black Black isn't always just memset(ptr, 0, size). Limited YUV in particular requires relatively non-obvious values, and filling a frame with repeating 0 bytes is disallowed in some contexts. With component sizes larger than 8 or packed YUV, this can become relatively complicated. So having a generic function for this seems helpful. In order to handle the complex cases in a generic way without destroying performance, this code attempts to compute a black pixel, and then uses that value to clear the image data quickly by using a function like memset. Common cases like yuv410p10 or rgba can't be handled with a simple memset, so there is some code to fill memory with 2/4/8 byte patterns. For the remaining cases, a generic slow fallback is used. Signed-off-by: Anton Khirnov --- doc/APIchanges | 3 + libavutil/imgutils.c | 167 +++++++++++++++++++++++++++++++++++++++++++ libavutil/imgutils.h | 27 +++++++ libavutil/version.h | 2 +- 4 files changed, 198 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 30a8f809d1ddb..463247f48ed80 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2017-03-23 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavu 56.4.0 - imgutils.h + Add av_image_fill_black(). + 2017-xx-xx - xxxxxxx - lavu 56.3.0 - frame.h Add av_frame_apply_cropping(). diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c index 84abb11656e99..662962252b22d 100644 --- a/libavutil/imgutils.c +++ b/libavutil/imgutils.c @@ -435,3 +435,170 @@ int av_image_copy_to_buffer(uint8_t *dst, int dst_size, return size; } + +// Fill dst[0..dst_size] with the bytes in clear[0..clear_size]. The clear +// bytes are repeated until dst_size is reached. If dst_size is unaligned (i.e. +// dst_size%clear_size!=0), the remaining data will be filled with the beginning +// of the clear data only. +static void memset_bytes(uint8_t *dst, size_t dst_size, uint8_t *clear, + size_t clear_size) +{ + size_t pos = 0; + int same = 1; + int i; + + if (!clear_size) + return; + + // Reduce to memset() if possible. + for (i = 0; i < clear_size; i++) { + if (clear[i] != clear[0]) { + same = 0; + break; + } + } + if (same) + clear_size = 1; + + if (clear_size == 1) { + memset(dst, clear[0], dst_size); + dst_size = 0; + } else if (clear_size == 2) { + uint16_t val = AV_RN16(clear); + for (; dst_size >= 2; dst_size -= 2) { + AV_WN16(dst, val); + dst += 2; + } + } else if (clear_size == 4) { + uint32_t val = AV_RN32(clear); + for (; dst_size >= 4; dst_size -= 4) { + AV_WN32(dst, val); + dst += 4; + } + } else if (clear_size == 8) { + uint32_t val = AV_RN64(clear); + for (; dst_size >= 8; dst_size -= 8) { + AV_WN64(dst, val); + dst += 8; + } + } + + for (; dst_size; dst_size--) + *dst++ = clear[pos++ % clear_size]; +} + +// Maximum size in bytes of a plane element (usually a pixel, or multiple pixels +// if it's a subsampled packed format). +#define MAX_BLOCK_SIZE 32 + +int av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t dst_linesize[4], + enum AVPixelFormat pix_fmt, enum AVColorRange range, + int width, int height) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + int nb_planes = av_pix_fmt_count_planes(pix_fmt); + // A pixel or a group of pixels on each plane, with a value that represents black. + // Consider e.g. AV_PIX_FMT_UYVY422 for non-trivial cases. + uint8_t clear_block[4][MAX_BLOCK_SIZE] = {0}; // clear padding with 0 + int clear_block_size[4] = {0}; + ptrdiff_t plane_line_bytes[4] = {0}; + int rgb, limited; + int plane, c; + + if (!desc || nb_planes < 1 || nb_planes > 4 || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) + return AVERROR(EINVAL); + + rgb = !!(desc->flags & AV_PIX_FMT_FLAG_RGB); + limited = !rgb && range != AVCOL_RANGE_JPEG; + + if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) { + ptrdiff_t bytewidth = av_image_get_linesize(pix_fmt, width, 0); + uint8_t *data; + int mono = pix_fmt == AV_PIX_FMT_MONOWHITE || pix_fmt == AV_PIX_FMT_MONOBLACK; + int fill = pix_fmt == AV_PIX_FMT_MONOWHITE ? 0xFF : 0; + if (nb_planes != 1 || !(rgb || mono) || bytewidth < 1) + return AVERROR(EINVAL); + + if (!dst_data) + return 0; + + data = dst_data[0]; + + // (Bitstream + alpha will be handled incorrectly - it'll remain transparent.) + for (;height > 0; height--) { + memset(data, fill, bytewidth); + data += dst_linesize[0]; + } + return 0; + } + + for (c = 0; c < desc->nb_components; c++) { + const AVComponentDescriptor comp = desc->comp[c]; + + // We try to operate on entire non-subsampled pixel groups (for + // AV_PIX_FMT_UYVY422 this would mean two consecutive pixels). + clear_block_size[comp.plane] = FFMAX(clear_block_size[comp.plane], comp.step); + + if (clear_block_size[comp.plane] > MAX_BLOCK_SIZE) + return AVERROR(EINVAL); + } + + // Create a byte array for clearing 1 pixel (sometimes several pixels). + for (c = 0; c < desc->nb_components; c++) { + const AVComponentDescriptor comp = desc->comp[c]; + // (Multiple pixels happen e.g. with AV_PIX_FMT_UYVY422.) + int w = clear_block_size[comp.plane] / comp.step; + uint8_t *c_data[4]; + const int c_linesize[4] = {0}; + uint16_t src_array[MAX_BLOCK_SIZE]; + uint16_t src = 0; + int x; + + if (comp.depth > 16) + return AVERROR(EINVAL); + if (!rgb && comp.depth < 8) + return AVERROR(EINVAL); + if (w < 1) + return AVERROR(EINVAL); + + if (c == 0 && limited) { + src = 16 << (comp.depth - 8); + } else if ((c == 1 || c == 2) && !rgb) { + src = 128 << (comp.depth - 8); + } else if (c == 3) { + // (Assume even limited YUV uses full range alpha.) + src = (1 << comp.depth) - 1; + } + + for (x = 0; x < w; x++) + src_array[x] = src; + + for (x = 0; x < 4; x++) + c_data[x] = &clear_block[x][0]; + + av_write_image_line(src_array, c_data, c_linesize, desc, 0, 0, c, w); + } + + for (plane = 0; plane < nb_planes; plane++) { + plane_line_bytes[plane] = av_image_get_linesize(pix_fmt, width, plane); + if (plane_line_bytes[plane] < 0) + return AVERROR(EINVAL); + } + + if (!dst_data) + return 0; + + for (plane = 0; plane < nb_planes; plane++) { + size_t bytewidth = plane_line_bytes[plane]; + uint8_t *data = dst_data[plane]; + int chroma_div = plane == 1 || plane == 2 ? desc->log2_chroma_h : 0; + int plane_h = ((height + ( 1 << chroma_div) - 1)) >> chroma_div; + + for (; plane_h > 0; plane_h--) { + memset_bytes(data, bytewidth, &clear_block[plane][0], clear_block_size[plane]); + data += dst_linesize[plane]; + } + } + + return 0; +} diff --git a/libavutil/imgutils.h b/libavutil/imgutils.h index fafabc48caf7d..ae2e6287ebdb4 100644 --- a/libavutil/imgutils.h +++ b/libavutil/imgutils.h @@ -224,6 +224,33 @@ int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *lo */ int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar); +/** + * Overwrite the image data with black. This is suitable for filling a + * sub-rectangle of an image, meaning the padding between the right most pixel + * and the left most pixel on the next line will not be overwritten. For some + * formats, the image size might be rounded up due to inherent alignment. + * + * If the pixel format has alpha, the alpha is cleared to opaque. + * + * This can return an error if the pixel format is not supported. Normally, all + * non-hwaccel pixel formats should be supported. + * + * Passing NULL for dst_data is allowed. Then the function returns whether the + * operation would have succeeded. (It can return an error if the pix_fmt is + * not supported.) + * + * @param dst_data data pointers to destination image + * @param dst_linesize linesizes for the destination image + * @param pix_fmt the pixel format of the image + * @param range the color range of the image (important for colorspaces such as YUV) + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @return 0 if the image data was cleared, a negative AVERROR code otherwise + */ +int av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t dst_linesize[4], + enum AVPixelFormat pix_fmt, enum AVColorRange range, + int width, int height); + /** * @} */ diff --git a/libavutil/version.h b/libavutil/version.h index 53bf72efdda16..62fb38a27aae7 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -54,7 +54,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 3 +#define LIBAVUTIL_VERSION_MINOR 4 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 45c4bf3df03ef53ae61fa1473424d4ae024f22e4 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 22 Jul 2017 14:52:27 +0200 Subject: [PATCH 0325/2557] h264dec: track the last seen value of x264_build Do not use the one in the SEI directly as that is reset at certain points. Inspired by patches from Michael Niedermayer and Anton Mitrofanov . CC: libav-stable@libav.org --- libavcodec/h264_direct.c | 4 ++-- libavcodec/h264_slice.c | 6 +++++- libavcodec/h264dec.c | 1 + libavcodec/h264dec.h | 1 + 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libavcodec/h264_direct.c b/libavcodec/h264_direct.c index 7ec49b67f3e42..abac259cce67f 100644 --- a/libavcodec/h264_direct.c +++ b/libavcodec/h264_direct.c @@ -391,7 +391,7 @@ static void pred_spatial_direct_motion(const H264Context *const h, H264SliceCont (l1ref0[0] < 0 && !l1ref1[0] && FFABS(l1mv1[0][0]) <= 1 && FFABS(l1mv1[0][1]) <= 1 && - h->sei.unregistered.x264_build > 33U))) { + h->x264_build > 33U))) { a = b = 0; if (ref[0] > 0) a = mv[0]; @@ -426,7 +426,7 @@ static void pred_spatial_direct_motion(const H264Context *const h, H264SliceCont (l1ref0[i8] == 0 || (l1ref0[i8] < 0 && l1ref1[i8] == 0 && - h->sei.unregistered.x264_build > 33U))) { + h->x264_build > 33U))) { const int16_t (*l1mv)[2] = l1ref0[i8] == 0 ? l1mv0 : l1mv1; if (IS_SUB_8X8(sub_mb_type)) { const int16_t *mv_col = l1mv[x8 * 3 + y8 * 3 * b4_stride]; diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index c9f1dbb86f97f..e7408b24b5de5 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -403,6 +403,7 @@ int ff_h264_update_thread_context(AVCodecContext *dst, h->enable_er = h1->enable_er; h->workaround_bugs = h1->workaround_bugs; + h->x264_build = h1->x264_build; h->droppable = h1->droppable; // extradata/NAL handling @@ -509,6 +510,9 @@ static int h264_frame_start(H264Context *h) h->mb_aff_frame = h->ps.sps->mb_aff && (h->picture_structure == PICT_FRAME); + if (h->sei.unregistered.x264_build >= 0) + h->x264_build = h->sei.unregistered.x264_build; + assert(h->cur_pic_ptr->long_ref == 0); return 0; @@ -847,7 +851,7 @@ static int h264_slice_header_init(H264Context *h) if (sps->timing_info_present_flag) { int64_t den = sps->time_scale; - if (h->sei.unregistered.x264_build < 44U) + if (h->x264_build < 44U) den *= 2; av_reduce(&h->avctx->framerate.den, &h->avctx->framerate.num, sps->num_units_in_tick, den, 1 << 30); diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 2a532a7ef7404..7a8293efa5f8a 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -293,6 +293,7 @@ static int h264_init_context(AVCodecContext *avctx, H264Context *h) h->flags = avctx->flags; h->poc.prev_poc_msb = 1 << 16; h->recovery_frame = -1; + h->x264_build = -1; h->frame_recovered = 0; h->next_outputed_poc = INT_MIN; diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h index fc7beeb9944e8..ddfe224e93d27 100644 --- a/libavcodec/h264dec.h +++ b/libavcodec/h264dec.h @@ -361,6 +361,7 @@ typedef struct H264Context { int context_initialized; int flags; int workaround_bugs; + int x264_build; /* Set when slice threading is used and at least one slice uses deblocking * mode 1 (i.e. across slice boundaries). Then we disable the loop filter * during normal MB decoding and execute it serially at the end. From 79c6477c2abd8cfa41eef0c4ac39779dd8a9ec8e Mon Sep 17 00:00:00 2001 From: Yogender Kumar Gupta Date: Thu, 15 Jun 2017 18:56:13 -0400 Subject: [PATCH 0326/2557] h264dec: fix Lossless Decoding (Profile 244) for 8x8 Intra Prediction CC: libav-stable@libav.org Signed-off-by: Anton Khirnov --- libavcodec/h264_mb.c | 7 +++- libavcodec/h264pred.c | 2 + libavcodec/h264pred.h | 3 ++ libavcodec/h264pred_template.c | 73 ++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/libavcodec/h264_mb.c b/libavcodec/h264_mb.c index f037bd5163d00..51d73ce7107db 100644 --- a/libavcodec/h264_mb.c +++ b/libavcodec/h264_mb.c @@ -636,7 +636,12 @@ static av_always_inline void hl_decode_mb_predict_luma(const H264Context *h, uint8_t *const ptr = dest_y + block_offset[i]; const int dir = sl->intra4x4_pred_mode_cache[scan8[i]]; if (transform_bypass && h->ps.sps->profile_idc == 244 && dir <= 1) { - h->hpc.pred8x8l_add[dir](ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize); + if (h->x264_build < 151U) { + h->hpc.pred8x8l_add[dir](ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize); + } else + h->hpc.pred8x8l_filter_add[dir](ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), + (sl-> topleft_samples_available << i) & 0x8000, + (sl->topright_samples_available << i) & 0x4000, linesize); } else { const int nnz = sl->non_zero_count_cache[scan8[i + p * 16]]; h->hpc.pred8x8l[dir](ptr, (sl->topleft_samples_available << i) & 0x8000, diff --git a/libavcodec/h264pred.c b/libavcodec/h264pred.c index 7627eb076d7f8..135babcab4529 100644 --- a/libavcodec/h264pred.c +++ b/libavcodec/h264pred.c @@ -552,6 +552,8 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred4x4_add [ HOR_PRED ]= FUNCC(pred4x4_horizontal_add , depth);\ h->pred8x8l_add [VERT_PRED ]= FUNCC(pred8x8l_vertical_add , depth);\ h->pred8x8l_add [ HOR_PRED ]= FUNCC(pred8x8l_horizontal_add , depth);\ + h->pred8x8l_filter_add [VERT_PRED ]= FUNCC(pred8x8l_vertical_filter_add , depth);\ + h->pred8x8l_filter_add [ HOR_PRED ]= FUNCC(pred8x8l_horizontal_filter_add , depth);\ if (chroma_format_idc <= 1) {\ h->pred8x8_add [VERT_PRED8x8]= FUNCC(pred8x8_vertical_add , depth);\ h->pred8x8_add [ HOR_PRED8x8]= FUNCC(pred8x8_horizontal_add , depth);\ diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h index 60e74349c9a28..795d8f3eff6b4 100644 --- a/libavcodec/h264pred.h +++ b/libavcodec/h264pred.h @@ -101,6 +101,9 @@ typedef struct H264PredContext { int16_t *block /*align 16*/, ptrdiff_t stride); void(*pred8x8l_add[2])(uint8_t *pix /*align 8*/, int16_t *block /*align 16*/, ptrdiff_t stride); + void(*pred8x8l_filter_add[2])(uint8_t *pix /*align 8*/, + int16_t *block /*align 16*/, + int topleft, int topright, ptrdiff_t stride); void(*pred8x8_add[3])(uint8_t *pix /*align 8*/, const int *block_offset, int16_t *block /*align 16*/, ptrdiff_t stride); diff --git a/libavcodec/h264pred_template.c b/libavcodec/h264pred_template.c index 8492b2b0a2f66..02494aaff91cc 100644 --- a/libavcodec/h264pred_template.c +++ b/libavcodec/h264pred_template.c @@ -1123,6 +1123,79 @@ static void FUNCC(pred8x8l_horizontal_up)(uint8_t *_src, int has_topleft, SRC(5,6)=SRC(5,7)=SRC(6,4)=SRC(6,5)=SRC(6,6)= SRC(6,7)=SRC(7,4)=SRC(7,5)=SRC(7,6)=SRC(7,7)= l7; } + +static void FUNCC(pred8x8l_vertical_filter_add)(uint8_t *_src, int16_t *_block, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + int i; + pixel *src = (pixel*)_src; + const dctcoef *block = (const dctcoef*)_block; + pixel pix[8]; + int stride = _stride/sizeof(pixel); + PREDICT_8x8_LOAD_TOP; + + pix[0] = t0; + pix[1] = t1; + pix[2] = t2; + pix[3] = t3; + pix[4] = t4; + pix[5] = t5; + pix[6] = t6; + pix[7] = t7; + + for (i = 0; i < 8; i++) { + pixel v = pix[i]; + src[0 * stride] = v += block[0]; + src[1 * stride] = v += block[8]; + src[2 * stride] = v += block[16]; + src[3 * stride] = v += block[24]; + src[4 * stride] = v += block[32]; + src[5 * stride] = v += block[40]; + src[6 * stride] = v += block[48]; + src[7 * stride] = v + block[56]; + src++; + block++; + } + + memset(_block, 0, sizeof(dctcoef) * 64); +} + +static void FUNCC(pred8x8l_horizontal_filter_add)(uint8_t *_src, int16_t *_block, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + int i; + pixel *src = (pixel*)_src; + const dctcoef *block = (const dctcoef*)_block; + pixel pix[8]; + int stride = _stride/sizeof(pixel); + PREDICT_8x8_LOAD_LEFT; + + pix[0] = l0; + pix[1] = l1; + pix[2] = l2; + pix[3] = l3; + pix[4] = l4; + pix[5] = l5; + pix[6] = l6; + pix[7] = l7; + + for (i = 0; i < 8; i++) { + pixel v = pix[i]; + src[0] = v += block[0]; + src[1] = v += block[1]; + src[2] = v += block[2]; + src[3] = v += block[3]; + src[4] = v += block[4]; + src[5] = v += block[5]; + src[6] = v += block[6]; + src[7] = v + block[7]; + src += stride; + block += 8; + } + + memset(_block, 0, sizeof(dctcoef) * 64); +} + #undef PREDICT_8x8_LOAD_LEFT #undef PREDICT_8x8_LOAD_TOP #undef PREDICT_8x8_LOAD_TOPLEFT From 18d3f36d3c4d0f2c3e702f970ff8b457d7d5e39c Mon Sep 17 00:00:00 2001 From: Anton Mitrofanov Date: Thu, 15 Jun 2017 18:56:14 -0400 Subject: [PATCH 0327/2557] h264_cabac: Fix CABAC+8x8dct in 4:4:4 Use the correct ctxIdxInc calculation for coded_block_flag. Keep old behavior for old versions of x264 for backward compatibility. CC: libav-stable@libav.org Signed-off-by: Anton Khirnov --- libavcodec/h264_cabac.c | 47 +++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c index b28e486e52e96..5dd285c3ea850 100644 --- a/libavcodec/h264_cabac.c +++ b/libavcodec/h264_cabac.c @@ -2329,21 +2329,40 @@ int ff_h264_decode_mb_cabac(const H264Context *h, H264SliceContext *sl) if (CHROMA444(h) && IS_8x8DCT(mb_type)){ int i; uint8_t *nnz_cache = sl->non_zero_count_cache; - for (i = 0; i < 2; i++){ - if (sl->left_type[LEFT(i)] && !IS_8x8DCT(sl->left_type[LEFT(i)])) { - nnz_cache[3+8* 1 + 2*8*i]= - nnz_cache[3+8* 2 + 2*8*i]= - nnz_cache[3+8* 6 + 2*8*i]= - nnz_cache[3+8* 7 + 2*8*i]= - nnz_cache[3+8*11 + 2*8*i]= - nnz_cache[3+8*12 + 2*8*i]= IS_INTRA(mb_type) ? 64 : 0; + if (h->x264_build < 151U) { + for (i = 0; i < 2; i++){ + if (sl->left_type[LEFT(i)] && !IS_8x8DCT(sl->left_type[LEFT(i)])) { + nnz_cache[3+8* 1 + 2*8*i]= + nnz_cache[3+8* 2 + 2*8*i]= + nnz_cache[3+8* 6 + 2*8*i]= + nnz_cache[3+8* 7 + 2*8*i]= + nnz_cache[3+8*11 + 2*8*i]= + nnz_cache[3+8*12 + 2*8*i]= IS_INTRA(mb_type) ? 64 : 0; + } + } + if (sl->top_type && !IS_8x8DCT(sl->top_type)){ + uint32_t top_empty = !IS_INTRA(mb_type) ? 0 : 0x40404040; + AV_WN32A(&nnz_cache[4+8* 0], top_empty); + AV_WN32A(&nnz_cache[4+8* 5], top_empty); + AV_WN32A(&nnz_cache[4+8*10], top_empty); + } + } else { + for (i = 0; i < 2; i++){ + if (sl->left_type[LEFT(i)] && !IS_8x8DCT(sl->left_type[LEFT(i)])) { + nnz_cache[3+8* 1 + 2*8*i]= + nnz_cache[3+8* 2 + 2*8*i]= + nnz_cache[3+8* 6 + 2*8*i]= + nnz_cache[3+8* 7 + 2*8*i]= + nnz_cache[3+8*11 + 2*8*i]= + nnz_cache[3+8*12 + 2*8*i]= !IS_INTRA_PCM(sl->left_type[LEFT(i)]) ? 0 : 64; + } + } + if (sl->top_type && !IS_8x8DCT(sl->top_type)){ + uint32_t top_empty = !IS_INTRA_PCM(sl->top_type) ? 0 : 0x40404040; + AV_WN32A(&nnz_cache[4+8* 0], top_empty); + AV_WN32A(&nnz_cache[4+8* 5], top_empty); + AV_WN32A(&nnz_cache[4+8*10], top_empty); } - } - if (sl->top_type && !IS_8x8DCT(sl->top_type)){ - uint32_t top_empty = !IS_INTRA(mb_type) ? 0 : 0x40404040; - AV_WN32A(&nnz_cache[4+8* 0], top_empty); - AV_WN32A(&nnz_cache[4+8* 5], top_empty); - AV_WN32A(&nnz_cache[4+8*10], top_empty); } } h->cur_pic.mb_type[mb_xy] = mb_type; From 70946e605924e2108c39f96faa369c220177f301 Mon Sep 17 00:00:00 2001 From: Anton Mitrofanov Date: Thu, 15 Jun 2017 18:56:16 -0400 Subject: [PATCH 0328/2557] h264dec: Fix mix of lossless and lossy MBs decoding CC: libav-stable@libav.org Signed-off-by: Anton Khirnov --- libavcodec/h264_cabac.c | 16 ++++++++-------- libavcodec/h264_cavlc.c | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c index 5dd285c3ea850..c0b9e30e61a34 100644 --- a/libavcodec/h264_cabac.c +++ b/libavcodec/h264_cabac.c @@ -2371,14 +2371,6 @@ int ff_h264_decode_mb_cabac(const H264Context *h, H264SliceContext *sl) const uint8_t *scan, *scan8x8; const uint32_t *qmul; - if(IS_INTERLACED(mb_type)){ - scan8x8 = sl->qscale ? h->field_scan8x8 : h->field_scan8x8_q0; - scan = sl->qscale ? h->field_scan : h->field_scan_q0; - }else{ - scan8x8 = sl->qscale ? h->zigzag_scan8x8 : h->zigzag_scan8x8_q0; - scan = sl->qscale ? h->zigzag_scan : h->zigzag_scan_q0; - } - // decode_cabac_mb_dqp if(get_cabac_noinline( &sl->cabac, &sl->cabac_state[60 + (sl->last_qscale_diff != 0)])){ int val = 1; @@ -2409,6 +2401,14 @@ int ff_h264_decode_mb_cabac(const H264Context *h, H264SliceContext *sl) }else sl->last_qscale_diff=0; + if(IS_INTERLACED(mb_type)){ + scan8x8 = sl->qscale ? h->field_scan8x8 : h->field_scan8x8_q0; + scan = sl->qscale ? h->field_scan : h->field_scan_q0; + }else{ + scan8x8 = sl->qscale ? h->zigzag_scan8x8 : h->zigzag_scan8x8_q0; + scan = sl->qscale ? h->zigzag_scan : h->zigzag_scan_q0; + } + decode_cabac_luma_residual(h, sl, scan, scan8x8, pixel_shift, mb_type, cbp, 0); if (CHROMA444(h)) { decode_cabac_luma_residual(h, sl, scan, scan8x8, pixel_shift, mb_type, cbp, 1); diff --git a/libavcodec/h264_cavlc.c b/libavcodec/h264_cavlc.c index c11e211bd894b..d57062bc569ff 100644 --- a/libavcodec/h264_cavlc.c +++ b/libavcodec/h264_cavlc.c @@ -1093,14 +1093,6 @@ int ff_h264_decode_mb_cavlc(const H264Context *h, H264SliceContext *sl) const uint8_t *scan, *scan8x8; const int max_qp = 51 + 6 * (h->ps.sps->bit_depth_luma - 8); - if(IS_INTERLACED(mb_type)){ - scan8x8 = sl->qscale ? h->field_scan8x8_cavlc : h->field_scan8x8_cavlc_q0; - scan = sl->qscale ? h->field_scan : h->field_scan_q0; - }else{ - scan8x8 = sl->qscale ? h->zigzag_scan8x8_cavlc : h->zigzag_scan8x8_cavlc_q0; - scan = sl->qscale ? h->zigzag_scan : h->zigzag_scan_q0; - } - dquant= get_se_golomb(&sl->gb); sl->qscale += dquant; @@ -1117,6 +1109,14 @@ int ff_h264_decode_mb_cavlc(const H264Context *h, H264SliceContext *sl) sl->chroma_qp[0] = get_chroma_qp(h->ps.pps, 0, sl->qscale); sl->chroma_qp[1] = get_chroma_qp(h->ps.pps, 1, sl->qscale); + if(IS_INTERLACED(mb_type)){ + scan8x8 = sl->qscale ? h->field_scan8x8_cavlc : h->field_scan8x8_cavlc_q0; + scan = sl->qscale ? h->field_scan : h->field_scan_q0; + }else{ + scan8x8 = sl->qscale ? h->zigzag_scan8x8_cavlc : h->zigzag_scan8x8_cavlc_q0; + scan = sl->qscale ? h->zigzag_scan : h->zigzag_scan_q0; + } + if ((ret = decode_luma_residual(h, sl, gb, scan, scan8x8, pixel_shift, mb_type, cbp, 0)) < 0 ) { return -1; } From de77671438c24ffea93398c8dc885d4dd04477de Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 1 Jul 2017 11:32:56 +0200 Subject: [PATCH 0329/2557] decode: avoid leaks on failure in ff_get_buffer() If the get_buffer() call fails, the frame might have some side data already set. Make sure it gets freed. CC: libav-stable@libav.org --- libavcodec/decode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 9644e89f48524..f7cd7f6870684 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1069,6 +1069,9 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) frame->height = avctx->height; } + if (ret < 0) + av_frame_unref(frame); + return ret; } From 359a8a3e2d1194b52b6c386f94fd0929567dfb67 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 1 Jul 2017 11:12:44 +0200 Subject: [PATCH 0330/2557] decode: add a method for attaching lavc-internal data to frames Use the AVFrame.opaque_ref field. The original user's opaque_ref is wrapped in the lavc struct and then unwrapped before the frame is returned to the caller. This new struct will be useful in the following commits. --- libavcodec/decode.c | 57 +++++++++++++++++++++++++++++++++++++++++++++ libavcodec/decode.h | 13 +++++++++++ 2 files changed, 70 insertions(+) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index f7cd7f6870684..bcc119c829724 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -406,6 +406,26 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) if (ret == AVERROR_EOF) avci->draining_done = 1; + /* unwrap the per-frame decode data and restore the original opaque_ref*/ + if (!ret) { + /* the only case where decode data is not set should be decoders + * that do not call ff_get_buffer() */ + av_assert0((frame->opaque_ref && frame->opaque_ref->size == sizeof(FrameDecodeData)) || + !(avctx->codec->capabilities & AV_CODEC_CAP_DR1)); + + if (frame->opaque_ref) { + FrameDecodeData *fdd; + AVBufferRef *user_opaque_ref; + + fdd = (FrameDecodeData*)frame->opaque_ref->data; + + user_opaque_ref = fdd->user_opaque_ref; + fdd->user_opaque_ref = NULL; + av_buffer_unref(&frame->opaque_ref); + frame->opaque_ref = user_opaque_ref; + } + } + return ret; } @@ -988,6 +1008,37 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; } +static void decode_data_free(void *opaque, uint8_t *data) +{ + FrameDecodeData *fdd = (FrameDecodeData*)data; + + av_buffer_unref(&fdd->user_opaque_ref); + + av_freep(&fdd); +} + +static int attach_decode_data(AVFrame *frame) +{ + AVBufferRef *fdd_buf; + FrameDecodeData *fdd; + + fdd = av_mallocz(sizeof(*fdd)); + if (!fdd) + return AVERROR(ENOMEM); + + fdd_buf = av_buffer_create((uint8_t*)fdd, sizeof(*fdd), decode_data_free, + NULL, AV_BUFFER_FLAG_READONLY); + if (!fdd_buf) { + av_freep(&fdd); + return AVERROR(ENOMEM); + } + + fdd->user_opaque_ref = frame->opaque_ref; + frame->opaque_ref = fdd_buf; + + return 0; +} + int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) { const AVHWAccel *hwaccel = avctx->hwaccel; @@ -1061,6 +1112,12 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) avctx->sw_pix_fmt = avctx->pix_fmt; ret = avctx->get_buffer2(avctx, frame, flags); + if (ret < 0) + goto end; + + ret = attach_decode_data(frame); + if (ret < 0) + goto end; end: if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions && diff --git a/libavcodec/decode.h b/libavcodec/decode.h index 2f29cf61070cc..61b53b2445030 100644 --- a/libavcodec/decode.h +++ b/libavcodec/decode.h @@ -21,8 +21,21 @@ #ifndef AVCODEC_DECODE_H #define AVCODEC_DECODE_H +#include "libavutil/buffer.h" + #include "avcodec.h" +/** + * This struct stores per-frame lavc-internal data and is attached to it via + * opaque_ref. + */ +typedef struct FrameDecodeData { + /** + * The original user-set opaque_ref. + */ + AVBufferRef *user_opaque_ref; +} FrameDecodeData; + /** * Called by decoders to get the next packet for decoding. * From badf0951f54c1332e77455dc40398f3512540c1b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 1 Jul 2017 12:09:58 +0200 Subject: [PATCH 0331/2557] decode: add a mechanism for performing delayed processing on the decoded frames This will be useful in the CUVID hwaccel. --- libavcodec/decode.c | 11 +++++++++++ libavcodec/decode.h | 15 +++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index bcc119c829724..9050b57b0b805 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -419,6 +419,14 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) fdd = (FrameDecodeData*)frame->opaque_ref->data; + if (fdd->post_process) { + ret = fdd->post_process(avctx, frame); + if (ret < 0) { + av_frame_unref(frame); + return ret; + } + } + user_opaque_ref = fdd->user_opaque_ref; fdd->user_opaque_ref = NULL; av_buffer_unref(&frame->opaque_ref); @@ -1014,6 +1022,9 @@ static void decode_data_free(void *opaque, uint8_t *data) av_buffer_unref(&fdd->user_opaque_ref); + if (fdd->post_process_opaque_free) + fdd->post_process_opaque_free(fdd->post_process_opaque); + av_freep(&fdd); } diff --git a/libavcodec/decode.h b/libavcodec/decode.h index 61b53b2445030..72052f1de541f 100644 --- a/libavcodec/decode.h +++ b/libavcodec/decode.h @@ -22,6 +22,7 @@ #define AVCODEC_DECODE_H #include "libavutil/buffer.h" +#include "libavutil/frame.h" #include "avcodec.h" @@ -34,6 +35,20 @@ typedef struct FrameDecodeData { * The original user-set opaque_ref. */ AVBufferRef *user_opaque_ref; + + /** + * The callback to perform some delayed processing on the frame right + * before it is returned to the caller. + * + * @note This code is called at some unspecified point after the frame is + * returned from the decoder's decode/receive_frame call. Therefore it cannot rely + * on AVCodecContext being in any specific state, so it does not get to + * access AVCodecContext directly at all. All the state it needs must be + * stored in the post_process_opaque object. + */ + int (*post_process)(void *logctx, AVFrame *frame); + void *post_process_opaque; + void (*post_process_opaque_free)(void *opaque); } FrameDecodeData; /** From 704311b2946d74a80f65906961cd9baaa18683a3 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 1 Jul 2017 12:09:58 +0200 Subject: [PATCH 0332/2557] decode: add a per-frame private data for hwaccel use This will be useful in the CUVID hwaccel. It should also eventually replace current decoder-specific mechanisms used by various other hwaccels. --- libavcodec/decode.c | 3 +++ libavcodec/decode.h | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 9050b57b0b805..c76ee6696aeee 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1025,6 +1025,9 @@ static void decode_data_free(void *opaque, uint8_t *data) if (fdd->post_process_opaque_free) fdd->post_process_opaque_free(fdd->post_process_opaque); + if (fdd->hwaccel_priv_free) + fdd->hwaccel_priv_free(fdd->hwaccel_priv); + av_freep(&fdd); } diff --git a/libavcodec/decode.h b/libavcodec/decode.h index 72052f1de541f..235f355f823ee 100644 --- a/libavcodec/decode.h +++ b/libavcodec/decode.h @@ -49,6 +49,12 @@ typedef struct FrameDecodeData { int (*post_process)(void *logctx, AVFrame *frame); void *post_process_opaque; void (*post_process_opaque_free)(void *opaque); + + /** + * Per-frame private data for hwaccels. + */ + void *hwaccel_priv; + void (*hwaccel_priv_free)(void *priv); } FrameDecodeData; /** From b9129ec4668c511e0a79e25c6f25d748cee172c9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Feb 2017 16:49:34 +0100 Subject: [PATCH 0333/2557] h264dec: add a CUVID hwaccel Some parts of the code are based on a patch by Timo Rothenpieler --- Changelog | 1 + avtools/avconv.h | 1 + avtools/avconv_opt.c | 4 + configure | 11 +- libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 1 + libavcodec/cuvid.c | 425 ++++++++++++++++++++++++++++++++++++++++ libavcodec/cuvid.h | 61 ++++++ libavcodec/cuvid_h264.c | 177 +++++++++++++++++ libavcodec/h264_slice.c | 6 +- 10 files changed, 687 insertions(+), 2 deletions(-) create mode 100644 libavcodec/cuvid.c create mode 100644 libavcodec/cuvid.h create mode 100644 libavcodec/cuvid_h264.c diff --git a/Changelog b/Changelog index 82e3e3a0ef31e..711506624feb9 100644 --- a/Changelog +++ b/Changelog @@ -18,6 +18,7 @@ version : - support for decoding through D3D11VA in avconv - Cinepak encoder - Intel QSV-accelerated MJPEG encoding +- NVIDIA CUVID-accelerated H.264 decoding version 12: diff --git a/avtools/avconv.h b/avtools/avconv.h index 4c699333a5a44..b5843fbc039f4 100644 --- a/avtools/avconv.h +++ b/avtools/avconv.h @@ -58,6 +58,7 @@ enum HWAccelID { HWACCEL_QSV, HWACCEL_VAAPI, HWACCEL_D3D11VA, + HWACCEL_CUVID, }; typedef struct HWAccel { diff --git a/avtools/avconv_opt.c b/avtools/avconv_opt.c index 575ce120dd0ee..df693360a776f 100644 --- a/avtools/avconv_opt.c +++ b/avtools/avconv_opt.c @@ -79,6 +79,10 @@ const HWAccel hwaccels[] = { #if CONFIG_VAAPI { "vaapi", hwaccel_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI, AV_HWDEVICE_TYPE_VAAPI }, +#endif +#if CONFIG_CUVID + { "cuvid", hwaccel_decode_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA, + AV_HWDEVICE_TYPE_CUDA }, #endif { 0 }, }; diff --git a/configure b/configure index 35ae03182a6a5..7a7fbb290661d 100755 --- a/configure +++ b/configure @@ -237,6 +237,7 @@ External library support: The following libraries provide various hardware acceleration features: --enable-cuda Nvidia CUDA (dynamically linked) + --enable-cuvid Nvidia CUVID video decode acceleration --enable-d3d11va Microsoft Direct3D 11 video acceleration [auto] --enable-dxva2 Microsoft DirectX 9 video acceleration [auto] --enable-libmfx Intel MediaSDK (AKA Quick Sync Video) @@ -1266,6 +1267,7 @@ EXTRALIBS_LIST=" HWACCEL_LIBRARY_NONFREE_LIST=" cuda + cuvid libnpp " HWACCEL_LIBRARY_LIST=" @@ -1686,6 +1688,7 @@ TOOLCHAIN_FEATURES=" TYPES_LIST=" CONDITION_VARIABLE_Ptr + CUVIDDECODECREATEINFO_bitDepthMinus8 socklen_t struct_addrinfo struct_group_source_req @@ -2189,6 +2192,8 @@ vda_extralibs="-framework CoreFoundation -framework VideoDecodeAcceleration -fra h263_vaapi_hwaccel_deps="vaapi" h263_vaapi_hwaccel_select="h263_decoder" +h264_cuvid_hwaccel_deps="cuvid CUVIDH264PICPARAMS" +h264_cuvid_hwaccel_select="h264_decoder" h264_d3d11va_hwaccel_deps="d3d11va" h264_d3d11va_hwaccel_select="h264_decoder" h264_d3d11va2_hwaccel_deps="d3d11va" @@ -2556,7 +2561,7 @@ avdevice_extralibs="libm_extralibs" avformat_extralibs="libm_extralibs" avfilter_extralibs="pthreads_extralibs libm_extralibs" avresample_extralibs="libm_extralibs" -avutil_extralibs="clock_gettime_extralibs cuda_extralibs libm_extralibs libmfx_extralibs nanosleep_extralibs pthreads_extralibs user32_extralibs vaapi_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs wincrypt_extralibs" +avutil_extralibs="clock_gettime_extralibs cuda_extralibs cuvid_extralibs libm_extralibs libmfx_extralibs nanosleep_extralibs pthreads_extralibs user32_extralibs vaapi_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs wincrypt_extralibs" swscale_extralibs="libm_extralibs" # programs @@ -4694,6 +4699,9 @@ check_lib psapi "windows.h psapi.h" GetProcessMemoryInfo -lpsapi check_struct "sys/time.h sys/resource.h" "struct rusage" ru_maxrss +check_type "cuviddec.h" "CUVIDH264PICPARAMS" +check_struct "cuviddec.h" "CUVIDDECODECREATEINFO" bitDepthMinus8 + check_type "windows.h dxva.h" "DXVA_PicParams_HEVC" -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -D_CRT_BUILD_DESKTOP_APP=0 check_type "windows.h d3d11.h" "ID3D11VideoDecoder" check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602 @@ -4753,6 +4761,7 @@ done enabled avisynth && require_header avisynth/avisynth_c.h enabled avxsynth && require_header avxsynth/avxsynth_c.h enabled cuda && require cuda cuda.h cuInit -lcuda +enabled cuvid && require cuvid cuviddec.h cuvidCreateDecoder -lnvcuvid enabled frei0r && require_header frei0r.h enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init enabled libbs2b && require_pkg_config libbs2b libbs2b bs2b.h bs2b_open diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 12bf8fecb740b..ac13166891f98 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -626,6 +626,7 @@ OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o # hardware accelerators +OBJS-$(CONFIG_CUVID) += cuvid.o OBJS-$(CONFIG_D3D11VA) += dxva2.o OBJS-$(CONFIG_DXVA2) += dxva2.o OBJS-$(CONFIG_VAAPI) += vaapi_decode.o @@ -633,6 +634,7 @@ OBJS-$(CONFIG_VDA) += vda.o OBJS-$(CONFIG_VDPAU) += vdpau.o OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o +OBJS-$(CONFIG_H264_CUVID_HWACCEL) += cuvid_h264.o OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec_h2645.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 3fcea5be0dd87..ea3a6b9702162 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -68,6 +68,7 @@ void avcodec_register_all(void) /* hardware accelerators */ REGISTER_HWACCEL(H263_VAAPI, h263_vaapi); + REGISTER_HWACCEL(H264_CUVID, h264_cuvid); REGISTER_HWACCEL(H264_D3D11VA, h264_d3d11va); REGISTER_HWACCEL(H264_D3D11VA2, h264_d3d11va2); REGISTER_HWACCEL(H264_DXVA2, h264_dxva2); diff --git a/libavcodec/cuvid.c b/libavcodec/cuvid.c new file mode 100644 index 0000000000000..69f624c373777 --- /dev/null +++ b/libavcodec/cuvid.c @@ -0,0 +1,425 @@ +/* + * HW decode acceleration through CUVID + * + * Copyright (c) 2016 Anton Khirnov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "config.h" + +#include "libavutil/common.h" +#include "libavutil/error.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_cuda.h" +#include "libavutil/pixdesc.h" +#include "libavutil/pixfmt.h" + +#include "avcodec.h" +#include "decode.h" +#include "cuvid.h" +#include "internal.h" + +typedef struct CUVIDDecoder { + CUvideodecoder decoder; + + AVBufferRef *hw_device_ref; + CUcontext cuda_ctx; +} CUVIDDecoder; + +typedef struct CUVIDFramePool { + unsigned int dpb_size; + unsigned int nb_allocated; +} CUVIDFramePool; + +static int map_avcodec_id(enum AVCodecID id) +{ + switch (id) { + case AV_CODEC_ID_H264: return cudaVideoCodec_H264; + } + return -1; +} + +static int map_chroma_format(enum AVPixelFormat pix_fmt) +{ + int shift_h = 0, shift_v = 0; + + av_pix_fmt_get_chroma_sub_sample(pix_fmt, &shift_h, &shift_v); + + if (shift_h == 1 && shift_v == 1) + return cudaVideoChromaFormat_420; + else if (shift_h == 1 && shift_v == 0) + return cudaVideoChromaFormat_422; + else if (shift_h == 0 && shift_v == 0) + return cudaVideoChromaFormat_444; + + return -1; +} + +static void cuvid_decoder_free(void *opaque, uint8_t *data) +{ + CUVIDDecoder *decoder = (CUVIDDecoder*)data; + + if (decoder->decoder) + cuvidDestroyDecoder(decoder->decoder); + + av_buffer_unref(&decoder->hw_device_ref); + + av_freep(&decoder); +} + +static int cuvid_decoder_create(AVBufferRef **out, AVBufferRef *hw_device_ref, + CUVIDDECODECREATEINFO *params, void *logctx) +{ + AVHWDeviceContext *hw_device_ctx = (AVHWDeviceContext*)hw_device_ref->data; + AVCUDADeviceContext *device_hwctx = hw_device_ctx->hwctx; + + AVBufferRef *decoder_ref; + CUVIDDecoder *decoder; + + CUcontext dummy; + CUresult err; + int ret; + + decoder = av_mallocz(sizeof(*decoder)); + if (!decoder) + return AVERROR(ENOMEM); + + decoder_ref = av_buffer_create((uint8_t*)decoder, sizeof(*decoder), + cuvid_decoder_free, NULL, AV_BUFFER_FLAG_READONLY); + if (!decoder_ref) { + av_freep(&decoder); + return AVERROR(ENOMEM); + } + + decoder->hw_device_ref = av_buffer_ref(hw_device_ref); + if (!decoder->hw_device_ref) { + ret = AVERROR(ENOMEM); + goto fail; + } + decoder->cuda_ctx = device_hwctx->cuda_ctx; + + err = cuCtxPushCurrent(decoder->cuda_ctx); + if (err != CUDA_SUCCESS) { + ret = AVERROR_UNKNOWN; + goto fail; + } + + err = cuvidCreateDecoder(&decoder->decoder, params); + + cuCtxPopCurrent(&dummy); + + if (err != CUDA_SUCCESS) { + av_log(logctx, AV_LOG_ERROR, "Error creating a CUVID decoder: %d\n", err); + ret = AVERROR_UNKNOWN; + goto fail; + } + + *out = decoder_ref; + + return 0; +fail: + av_buffer_unref(&decoder_ref); + return ret; +} + +static AVBufferRef *cuvid_decoder_frame_alloc(void *opaque, int size) +{ + CUVIDFramePool *pool = opaque; + AVBufferRef *ret; + + if (pool->nb_allocated >= pool->dpb_size) + return NULL; + + ret = av_buffer_alloc(sizeof(unsigned int)); + if (!ret) + return NULL; + + *(unsigned int*)ret->data = pool->nb_allocated++; + + return ret; +} + +int ff_cuvid_decode_uninit(AVCodecContext *avctx) +{ + CUVIDContext *ctx = avctx->internal->hwaccel_priv_data; + + av_freep(&ctx->bitstream); + ctx->bitstream_len = 0; + ctx->bitstream_allocated = 0; + + av_freep(&ctx->slice_offsets); + ctx->nb_slices = 0; + ctx->slice_offsets_allocated = 0; + + av_buffer_unref(&ctx->decoder_ref); + av_buffer_pool_uninit(&ctx->decoder_pool); + + return 0; +} + +int ff_cuvid_decode_init(AVCodecContext *avctx, unsigned int dpb_size) +{ + CUVIDContext *ctx = avctx->internal->hwaccel_priv_data; + + CUVIDFramePool *pool; + AVHWFramesContext *frames_ctx; + const AVPixFmtDescriptor *sw_desc; + + CUVIDDECODECREATEINFO params = { 0 }; + + int cuvid_codec_type, cuvid_chroma_format; + int ret = 0; + + sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); + if (!sw_desc) + return AVERROR_BUG; + + cuvid_codec_type = map_avcodec_id(avctx->codec_id); + if (cuvid_codec_type < 0) { + av_log(avctx, AV_LOG_ERROR, "Unsupported codec ID\n"); + return AVERROR_BUG; + } + + cuvid_chroma_format = map_chroma_format(avctx->sw_pix_fmt); + if (cuvid_chroma_format < 0) { + av_log(avctx, AV_LOG_ERROR, "Unsupported chroma format\n"); + return AVERROR(ENOSYS); + } + + if (avctx->thread_type & FF_THREAD_FRAME) + dpb_size += avctx->thread_count; + + if (!avctx->hw_frames_ctx) { + AVHWFramesContext *frames_ctx; + + if (!avctx->hw_device_ctx) { + av_log(avctx, AV_LOG_ERROR, "A hardware device or frames context " + "is required for CUVID decoding.\n"); + return AVERROR(EINVAL); + } + + avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); + if (!avctx->hw_frames_ctx) + return AVERROR(ENOMEM); + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + + frames_ctx->format = AV_PIX_FMT_CUDA; + frames_ctx->width = avctx->coded_width; + frames_ctx->height = avctx->coded_height; + frames_ctx->sw_format = AV_PIX_FMT_NV12; + frames_ctx->sw_format = sw_desc->comp[0].depth > 8 && HAVE_CUVIDDECODECREATEINFO_BITDEPTHMINUS8 ? + AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; + frames_ctx->initial_pool_size = dpb_size; + + ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error initializing internal frames context\n"); + return ret; + } + } + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + + params.ulWidth = avctx->coded_width; + params.ulHeight = avctx->coded_height; + params.ulTargetWidth = avctx->coded_width; + params.ulTargetHeight = avctx->coded_height; +#if HAVE_CUVIDDECODECREATEINFO_BITDEPTHMINUS8 + params.bitDepthMinus8 = sw_desc->comp[0].depth - 8; + params.OutputFormat = params.bitDepthMinus8 ? + cudaVideoSurfaceFormat_P016 : cudaVideoSurfaceFormat_NV12; +#else + params.OutputFormat = cudaVideoSurfaceFormat_NV12; +#endif + params.CodecType = cuvid_codec_type; + params.ChromaFormat = cuvid_chroma_format; + params.ulNumDecodeSurfaces = dpb_size; + params.ulNumOutputSurfaces = 1; + + ret = cuvid_decoder_create(&ctx->decoder_ref, frames_ctx->device_ref, ¶ms, avctx); + if (ret < 0) + return ret; + + pool = av_mallocz(sizeof(*pool)); + if (!pool) { + ret = AVERROR(ENOMEM); + goto fail; + } + pool->dpb_size = dpb_size; + + ctx->decoder_pool = av_buffer_pool_init2(sizeof(int), pool, + cuvid_decoder_frame_alloc, av_free); + if (!ctx->decoder_pool) { + ret = AVERROR(ENOMEM); + goto fail; + } + + return 0; +fail: + ff_cuvid_decode_uninit(avctx); + return ret; +} + +static void cuvid_fdd_priv_free(void *priv) +{ + CUVIDFrame *cf = priv; + + if (!cf) + return; + + av_buffer_unref(&cf->idx_ref); + av_buffer_unref(&cf->decoder_ref); + + av_freep(&priv); +} + +static int cuvid_retrieve_data(void *logctx, AVFrame *frame) +{ + FrameDecodeData *fdd = (FrameDecodeData*)frame->opaque_ref->data; + CUVIDFrame *cf = (CUVIDFrame*)fdd->hwaccel_priv; + CUVIDDecoder *decoder = (CUVIDDecoder*)cf->decoder_ref->data; + + CUVIDPROCPARAMS vpp = { .progressive_frame = 1 }; + + CUresult err; + CUcontext dummy; + CUdeviceptr devptr; + + unsigned int pitch, i; + unsigned int offset = 0; + int ret = 0; + + err = cuCtxPushCurrent(decoder->cuda_ctx); + if (err != CUDA_SUCCESS) + return AVERROR_UNKNOWN; + + err = cuvidMapVideoFrame(decoder->decoder, cf->idx, &devptr, &pitch, &vpp); + if (err != CUDA_SUCCESS) { + av_log(logctx, AV_LOG_ERROR, "Error mapping a picture with CUVID: %d\n", + err); + ret = AVERROR_UNKNOWN; + goto finish; + } + + for (i = 0; frame->data[i]; i++) { + CUDA_MEMCPY2D cpy = { + .srcMemoryType = CU_MEMORYTYPE_DEVICE, + .dstMemoryType = CU_MEMORYTYPE_DEVICE, + .srcDevice = devptr, + .dstDevice = (CUdeviceptr)frame->data[i], + .srcPitch = pitch, + .dstPitch = frame->linesize[i], + .srcY = offset, + .WidthInBytes = FFMIN(pitch, frame->linesize[i]), + .Height = frame->height >> (i ? 1 : 0), + }; + + err = cuMemcpy2D(&cpy); + if (err != CUDA_SUCCESS) { + av_log(logctx, AV_LOG_ERROR, "Error copying decoded frame: %d\n", + err); + ret = AVERROR_UNKNOWN; + goto copy_fail; + } + + offset += cpy.Height; + } + +copy_fail: + cuvidUnmapVideoFrame(decoder->decoder, devptr); + +finish: + cuCtxPopCurrent(&dummy); + return ret; +} + +int ff_cuvid_start_frame(AVCodecContext *avctx, AVFrame *frame) +{ + CUVIDContext *ctx = avctx->internal->hwaccel_priv_data; + FrameDecodeData *fdd = (FrameDecodeData*)frame->opaque_ref->data; + CUVIDFrame *cf = NULL; + int ret; + + ctx->bitstream_len = 0; + ctx->nb_slices = 0; + + if (fdd->hwaccel_priv) + return 0; + + cf = av_mallocz(sizeof(*cf)); + if (!cf) + return AVERROR(ENOMEM); + + cf->decoder_ref = av_buffer_ref(ctx->decoder_ref); + if (!cf->decoder_ref) + goto fail; + + cf->idx_ref = av_buffer_pool_get(ctx->decoder_pool); + if (!cf->idx_ref) { + av_log(avctx, AV_LOG_ERROR, "No decoder surfaces left\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + cf->idx = *(unsigned int*)cf->idx_ref->data; + + fdd->hwaccel_priv = cf; + fdd->hwaccel_priv_free = cuvid_fdd_priv_free; + fdd->post_process = cuvid_retrieve_data; + + return 0; +fail: + cuvid_fdd_priv_free(cf); + return ret; + +} + +int ff_cuvid_end_frame(AVCodecContext *avctx) +{ + CUVIDContext *ctx = avctx->internal->hwaccel_priv_data; + CUVIDDecoder *decoder = (CUVIDDecoder*)ctx->decoder_ref->data; + CUVIDPICPARAMS *pp = &ctx->pic_params; + + CUresult err; + CUcontext dummy; + + int ret = 0; + + pp->nBitstreamDataLen = ctx->bitstream_len; + pp->pBitstreamData = ctx->bitstream; + pp->nNumSlices = ctx->nb_slices; + pp->pSliceDataOffsets = ctx->slice_offsets; + + err = cuCtxPushCurrent(decoder->cuda_ctx); + if (err != CUDA_SUCCESS) + return AVERROR_UNKNOWN; + + err = cuvidDecodePicture(decoder->decoder, &ctx->pic_params); + if (err != CUDA_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Error decoding a picture with CUVID: %d\n", + err); + ret = AVERROR_UNKNOWN; + goto finish; + } + +finish: + cuCtxPopCurrent(&dummy); + + return ret; +} diff --git a/libavcodec/cuvid.h b/libavcodec/cuvid.h new file mode 100644 index 0000000000000..62e376bca28bf --- /dev/null +++ b/libavcodec/cuvid.h @@ -0,0 +1,61 @@ +/* + * HW decode acceleration through CUVID + * + * Copyright (c) 2016 Anton Khirnov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CUVID_H +#define AVCODEC_CUVID_H + +#include +#include + +#include "libavutil/buffer.h" +#include "libavutil/frame.h" + +#include "avcodec.h" + +typedef struct CUVIDFrame { + unsigned int idx; + AVBufferRef *idx_ref; + AVBufferRef *decoder_ref; +} CUVIDFrame; + +typedef struct CUVIDContext { + CUVIDPICPARAMS pic_params; + + AVBufferPool *decoder_pool; + + AVBufferRef *decoder_ref; + + uint8_t *bitstream; + int bitstream_len; + unsigned int bitstream_allocated; + + unsigned *slice_offsets; + int nb_slices; + unsigned int slice_offsets_allocated; +} CUVIDContext; + +int ff_cuvid_decode_init(AVCodecContext *avctx, unsigned int dpb_size); +int ff_cuvid_decode_uninit(AVCodecContext *avctx); +int ff_cuvid_start_frame(AVCodecContext *avctx, AVFrame *frame); +int ff_cuvid_end_frame(AVCodecContext *avctx); + +#endif /* AVCODEC_CUVID_H */ diff --git a/libavcodec/cuvid_h264.c b/libavcodec/cuvid_h264.c new file mode 100644 index 0000000000000..a83e4ffba0bdc --- /dev/null +++ b/libavcodec/cuvid_h264.c @@ -0,0 +1,177 @@ +/* + * MPEG-4 Part 10 / AVC / H.264 HW decode acceleration through CUVID + * + * Copyright (c) 2016 Anton Khirnov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "avcodec.h" +#include "cuvid.h" +#include "decode.h" +#include "internal.h" +#include "h264dec.h" + +static void dpb_add(const H264Context *h, CUVIDH264DPBENTRY *dst, const H264Picture *src, + int frame_idx) +{ + FrameDecodeData *fdd = (FrameDecodeData*)src->f->opaque_ref->data; + const CUVIDFrame *cf = fdd->hwaccel_priv; + + dst->PicIdx = cf ? cf->idx : -1; + dst->FrameIdx = frame_idx; + dst->is_long_term = src->long_ref; + dst->not_existing = 0; + dst->used_for_reference = src->reference & 3; + dst->FieldOrderCnt[0] = src->field_poc[0]; + dst->FieldOrderCnt[1] = src->field_poc[1]; +} + +static int cuvid_h264_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + const H264Context *h = avctx->priv_data; + const PPS *pps = h->ps.pps; + const SPS *sps = h->ps.sps; + + CUVIDContext *ctx = avctx->internal->hwaccel_priv_data; + CUVIDPICPARAMS *pp = &ctx->pic_params; + CUVIDH264PICPARAMS *ppc = &pp->CodecSpecific.h264; + FrameDecodeData *fdd; + CUVIDFrame *cf; + + int i, dpb_size, ret; + + ret = ff_cuvid_start_frame(avctx, h->cur_pic_ptr->f); + if (ret < 0) + return ret; + + fdd = (FrameDecodeData*)h->cur_pic_ptr->f->opaque_ref->data; + cf = (CUVIDFrame*)fdd->hwaccel_priv; + + *pp = (CUVIDPICPARAMS) { + .PicWidthInMbs = h->mb_width, + .FrameHeightInMbs = h->mb_height, + .CurrPicIdx = cf->idx, + .field_pic_flag = FIELD_PICTURE(h), + .bottom_field_flag = h->picture_structure == PICT_BOTTOM_FIELD, + .second_field = FIELD_PICTURE(h) && !h->first_field, + .ref_pic_flag = h->nal_ref_idc != 0, + .intra_pic_flag = 0, + + .CodecSpecific.h264 = { + .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4, + .pic_order_cnt_type = sps->poc_type, + .log2_max_pic_order_cnt_lsb_minus4 = FFMAX(sps->log2_max_poc_lsb - 4, 0), + .delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag, + .frame_mbs_only_flag = sps->frame_mbs_only_flag, + .direct_8x8_inference_flag = sps->direct_8x8_inference_flag, + .num_ref_frames = sps->ref_frame_count, + .residual_colour_transform_flag = sps->residual_color_transform_flag, + .bit_depth_luma_minus8 = sps->bit_depth_luma - 8, + .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8, + .qpprime_y_zero_transform_bypass_flag = sps->transform_bypass, + + .entropy_coding_mode_flag = pps->cabac, + .pic_order_present_flag = pps->pic_order_present, + .num_ref_idx_l0_active_minus1 = pps->ref_count[0] - 1, + .num_ref_idx_l1_active_minus1 = pps->ref_count[1] - 1, + .weighted_pred_flag = pps->weighted_pred, + .weighted_bipred_idc = pps->weighted_bipred_idc, + .pic_init_qp_minus26 = pps->init_qp - 26, + .deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present, + .redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present, + .transform_8x8_mode_flag = pps->transform_8x8_mode, + .MbaffFrameFlag = sps->mb_aff && !FIELD_PICTURE(h), + .constrained_intra_pred_flag = pps->constrained_intra_pred, + .chroma_qp_index_offset = pps->chroma_qp_index_offset[0], + .second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1], + .ref_pic_flag = h->nal_ref_idc != 0, + .frame_num = h->poc.frame_num, + .CurrFieldOrderCnt[0] = h->cur_pic_ptr->field_poc[0], + .CurrFieldOrderCnt[1] = h->cur_pic_ptr->field_poc[1], + }, + }; + + memcpy(ppc->WeightScale4x4, pps->scaling_matrix4, sizeof(ppc->WeightScale4x4)); + memcpy(ppc->WeightScale8x8[0], pps->scaling_matrix8[0], sizeof(ppc->WeightScale8x8[0])); + memcpy(ppc->WeightScale8x8[1], pps->scaling_matrix8[3], sizeof(ppc->WeightScale8x8[0])); + + dpb_size = 0; + for (i = 0; i < h->short_ref_count; i++) + dpb_add(h, &ppc->dpb[dpb_size++], h->short_ref[i], h->short_ref[i]->frame_num); + for (i = 0; i < 16; i++) { + if (h->long_ref[i]) + dpb_add(h, &ppc->dpb[dpb_size++], h->long_ref[i], i); + } + + for (i = dpb_size; i < FF_ARRAY_ELEMS(ppc->dpb); i++) + ppc->dpb[i].PicIdx = -1; + + return 0; +} + +static int cuvid_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, + uint32_t size) +{ + CUVIDContext *ctx = avctx->internal->hwaccel_priv_data; + void *tmp; + + tmp = av_fast_realloc(ctx->bitstream, &ctx->bitstream_allocated, + ctx->bitstream_len + size + 3); + if (!tmp) + return AVERROR(ENOMEM); + ctx->bitstream = tmp; + + tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated, + (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets)); + if (!tmp) + return AVERROR(ENOMEM); + ctx->slice_offsets = tmp; + + AV_WB24(ctx->bitstream + ctx->bitstream_len, 1); + memcpy(ctx->bitstream + ctx->bitstream_len + 3, buffer, size); + ctx->slice_offsets[ctx->nb_slices] = ctx->bitstream_len ; + ctx->bitstream_len += size + 3; + ctx->nb_slices++; + + return 0; +} + +static int cuvid_h264_decode_init(AVCodecContext *avctx) +{ + const H264Context *h = avctx->priv_data; + const SPS *sps = h->ps.sps; + return ff_cuvid_decode_init(avctx, sps->ref_frame_count + sps->num_reorder_frames); +} + +AVHWAccel ff_h264_cuvid_hwaccel = { + .name = "h264_cuvid", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .pix_fmt = AV_PIX_FMT_CUDA, + .start_frame = cuvid_h264_start_frame, + .end_frame = ff_cuvid_end_frame, + .decode_slice = cuvid_h264_decode_slice, + .init = cuvid_h264_decode_init, + .uninit = ff_cuvid_decode_uninit, + .priv_data_size = sizeof(CUVIDContext), +}; diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index e7408b24b5de5..c6309b298c28a 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -724,7 +724,8 @@ static enum AVPixelFormat get_pixel_format(H264Context *h) (CONFIG_H264_D3D11VA_HWACCEL * 2) + \ CONFIG_H264_VAAPI_HWACCEL + \ (CONFIG_H264_VDA_HWACCEL * 2) + \ - CONFIG_H264_VDPAU_HWACCEL) + CONFIG_H264_VDPAU_HWACCEL + \ + CONFIG_H264_CUVID_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts; const enum AVPixelFormat *choices = pix_fmts; @@ -754,6 +755,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h) case 8: #if CONFIG_H264_VDPAU_HWACCEL *fmt++ = AV_PIX_FMT_VDPAU; +#endif +#if CONFIG_H264_CUVID_HWACCEL + *fmt++ = AV_PIX_FMT_CUDA; #endif if (CHROMA444(h)) { if (h->avctx->colorspace == AVCOL_SPC_RGB) From 004ea63714e31ed43326ad00d7420d104f0dab38 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 27 Jul 2017 12:42:03 +0200 Subject: [PATCH 0334/2557] cuvid: add cuvid.h to SKIPHEADERS --- libavcodec/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index ac13166891f98..eba651fc241a0 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -797,6 +797,7 @@ SKIPHEADERS += %_tablegen.h \ tableprint.h \ $(ARCH)/vp56_arith.h \ +SKIPHEADERS-$(CONFIG_CUVID) += cuvid.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h From a58873b11198d04670b7f98f5a8a749d742db7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Gro=C3=9Fe?= Date: Fri, 30 Jun 2017 17:28:53 +0200 Subject: [PATCH 0335/2557] avconv: when using -loop option bail out if seek to start fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes an infinite loop when a demuxer fails to seek to the start of the input. Signed-off-by: Peter Große Signed-off-by: Anton Khirnov --- avtools/avconv.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/avtools/avconv.c b/avtools/avconv.c index 8dd11bb5fc47d..4e3ffecdefe90 100644 --- a/avtools/avconv.c +++ b/avtools/avconv.c @@ -2615,9 +2615,11 @@ static int process_input(void) return ret; } if (ret < 0 && ifile->loop) { - if ((ret = seek_to_start(ifile, is)) < 0) - return ret; - ret = get_input_packet(ifile, &pkt); + ret = seek_to_start(ifile, is); + if(ret < 0) + av_log(NULL, AV_LOG_WARNING, "Seek to start failed.\n"); + else + ret = get_input_packet(ifile, &pkt); } if (ret < 0) { if (ret != AVERROR_EOF) { From 00fd914d4912322212e924c15f325cebf2fde8d3 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 24 Jul 2017 11:41:31 +0200 Subject: [PATCH 0336/2557] hevcdec: set the active SPS before calling get_format() This way the SPS is available to the hwaccel init code. --- libavcodec/hevcdec.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index f6bbb7051e3fa..664e4ac14b7c5 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -490,13 +490,14 @@ static int hls_slice_header(HEVCContext *s) ff_hevc_clear_refs(s); + ret = set_sps(s, sps, sps->pix_fmt); + if (ret < 0) + return ret; + pix_fmt = get_format(s, sps); if (pix_fmt < 0) return pix_fmt; - - ret = set_sps(s, sps, pix_fmt); - if (ret < 0) - return ret; + s->avctx->pix_fmt = pix_fmt; s->seq_decode = (s->seq_decode + 1) & 0xff; s->max_ra = INT_MAX; From 770cf1dbc2c8fe9b84300439ad0cd85036480388 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 24 Jul 2017 11:42:09 +0200 Subject: [PATCH 0337/2557] fate/hevc: specify output pixel format explicitly This allows running those tests with hwaccel. --- tests/fate/hevc.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak index 5446969a7d72e..fe3ef26c77575 100644 --- a/tests/fate/hevc.mak +++ b/tests/fate/hevc.mak @@ -144,7 +144,7 @@ HEVC_SAMPLES_10BIT = \ define FATE_HEVC_TEST FATE_HEVC += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -vsync 0 -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit +fate-hevc-conformance-$(1): CMD = framecrc -vsync 0 -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv420p endef define FATE_HEVC_TEST_10BIT From b90fdb2c7199cc8b0e8d994fafba1fb4dc181d88 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Feb 2017 16:49:34 +0100 Subject: [PATCH 0338/2557] hevcdec: add a CUVID hwaccel --- Changelog | 2 +- configure | 3 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/cuvid.c | 1 + libavcodec/cuvid_hevc.c | 280 ++++++++++++++++++++++++++++++++++++++++ libavcodec/hevcdec.c | 9 +- 7 files changed, 295 insertions(+), 2 deletions(-) create mode 100644 libavcodec/cuvid_hevc.c diff --git a/Changelog b/Changelog index 711506624feb9..92a72490a9929 100644 --- a/Changelog +++ b/Changelog @@ -18,7 +18,7 @@ version : - support for decoding through D3D11VA in avconv - Cinepak encoder - Intel QSV-accelerated MJPEG encoding -- NVIDIA CUVID-accelerated H.264 decoding +- NVIDIA CUVID-accelerated H.264 and HEVC decoding version 12: diff --git a/configure b/configure index 7a7fbb290661d..4510100f3845a 100755 --- a/configure +++ b/configure @@ -2210,6 +2210,8 @@ h264_vda_old_hwaccel_deps="vda" h264_vda_old_hwaccel_select="h264_decoder" h264_vdpau_hwaccel_deps="vdpau" h264_vdpau_hwaccel_select="h264_decoder" +hevc_cuvid_hwaccel_deps="cuvid CUVIDHEVCPICPARAMS" +hevc_cuvid_hwaccel_select="hevc_decoder" hevc_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" hevc_d3d11va_hwaccel_select="hevc_decoder" hevc_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" @@ -4700,6 +4702,7 @@ check_lib psapi "windows.h psapi.h" GetProcessMemoryInfo -lpsapi check_struct "sys/time.h sys/resource.h" "struct rusage" ru_maxrss check_type "cuviddec.h" "CUVIDH264PICPARAMS" +check_type "cuviddec.h" "CUVIDHEVCPICPARAMS" check_struct "cuviddec.h" "CUVIDDECODECREATEINFO" bitDepthMinus8 check_type "windows.h dxva.h" "DXVA_PicParams_HEVC" -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -D_CRT_BUILD_DESKTOP_APP=0 diff --git a/libavcodec/Makefile b/libavcodec/Makefile index eba651fc241a0..bb568ddbe46a5 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -641,6 +641,7 @@ OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec_h2645.o OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o +OBJS-$(CONFIG_HEVC_CUVID_HWACCEL) += cuvid_hevc.o OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec_h2645.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index ea3a6b9702162..4ece4307a09d9 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -78,6 +78,7 @@ void avcodec_register_all(void) REGISTER_HWACCEL(H264_VDA, h264_vda); REGISTER_HWACCEL(H264_VDA_OLD, h264_vda_old); REGISTER_HWACCEL(H264_VDPAU, h264_vdpau); + REGISTER_HWACCEL(HEVC_CUVID, hevc_cuvid); REGISTER_HWACCEL(HEVC_D3D11VA, hevc_d3d11va); REGISTER_HWACCEL(HEVC_D3D11VA2, hevc_d3d11va2); REGISTER_HWACCEL(HEVC_DXVA2, hevc_dxva2); diff --git a/libavcodec/cuvid.c b/libavcodec/cuvid.c index 69f624c373777..2d35e92a612d0 100644 --- a/libavcodec/cuvid.c +++ b/libavcodec/cuvid.c @@ -53,6 +53,7 @@ static int map_avcodec_id(enum AVCodecID id) { switch (id) { case AV_CODEC_ID_H264: return cudaVideoCodec_H264; + case AV_CODEC_ID_HEVC: return cudaVideoCodec_HEVC; } return -1; } diff --git a/libavcodec/cuvid_hevc.c b/libavcodec/cuvid_hevc.c new file mode 100644 index 0000000000000..5de9bca4836c1 --- /dev/null +++ b/libavcodec/cuvid_hevc.c @@ -0,0 +1,280 @@ +/* + * HEVC HW decode acceleration through CUVID + * + * Copyright (c) 2017 Anton Khirnov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "avcodec.h" +#include "cuvid.h" +#include "decode.h" +#include "internal.h" +#include "hevcdec.h" +#include "hevc_data.h" + +static void dpb_add(CUVIDHEVCPICPARAMS *pp, int idx, const HEVCFrame *src) +{ + FrameDecodeData *fdd = (FrameDecodeData*)src->frame->opaque_ref->data; + const CUVIDFrame *cf = fdd->hwaccel_priv; + + pp->RefPicIdx[idx] = cf ? cf->idx : -1; + pp->PicOrderCntVal[idx] = src->poc; + pp->IsLongTerm[idx] = !!(src->flags & HEVC_FRAME_FLAG_LONG_REF); +} + +static void fill_scaling_lists(CUVIDHEVCPICPARAMS *ppc, const HEVCContext *s) +{ + const ScalingList *sl = s->ps.pps->scaling_list_data_present_flag ? + &s->ps.pps->scaling_list : &s->ps.sps->scaling_list; + int i, j, pos; + + for (i = 0; i < 6; i++) { + for (j = 0; j < 16; j++) { + pos = 4 * ff_hevc_diag_scan4x4_y[j] + ff_hevc_diag_scan4x4_x[j]; + ppc->ScalingList4x4[i][j] = sl->sl[0][i][pos]; + } + + for (j = 0; j < 64; j++) { + pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j]; + ppc->ScalingList8x8[i][j] = sl->sl[1][i][pos]; + ppc->ScalingList16x16[i][j] = sl->sl[2][i][pos]; + + if (i < 2) + ppc->ScalingList32x32[i][j] = sl->sl[3][i][pos]; + } + } + + memcpy(ppc->ScalingListDCCoeff16x16, sl->sl_dc[0], sizeof(ppc->ScalingListDCCoeff16x16)); + memcpy(ppc->ScalingListDCCoeff32x32, sl->sl_dc[1], sizeof(ppc->ScalingListDCCoeff32x32)); +} + +static int cuvid_hevc_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + const HEVCContext *s = avctx->priv_data; + const HEVCPPS *pps = s->ps.pps; + const HEVCSPS *sps = s->ps.sps; + + CUVIDContext *ctx = avctx->internal->hwaccel_priv_data; + CUVIDPICPARAMS *pp = &ctx->pic_params; + CUVIDHEVCPICPARAMS *ppc = &pp->CodecSpecific.hevc; + FrameDecodeData *fdd; + CUVIDFrame *cf; + + int i, j, dpb_size, ret; + + ret = ff_cuvid_start_frame(avctx, s->ref->frame); + if (ret < 0) + return ret; + + fdd = (FrameDecodeData*)s->ref->frame->opaque_ref->data; + cf = (CUVIDFrame*)fdd->hwaccel_priv; + + *pp = (CUVIDPICPARAMS) { + .PicWidthInMbs = sps->width / 16, + .FrameHeightInMbs = sps->height / 16, + .CurrPicIdx = cf->idx, + .ref_pic_flag = 1, + .intra_pic_flag = 0, + + .CodecSpecific.hevc = { + .pic_width_in_luma_samples = sps->width, + .pic_height_in_luma_samples = sps->height, + .log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3, + .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size, + .log2_min_transform_block_size_minus2 = sps->log2_min_tb_size - 2, + .log2_diff_max_min_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size, + .pcm_enabled_flag = sps->pcm_enabled_flag, + .log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm_enabled_flag ? sps->pcm.log2_min_pcm_cb_size - 3 : 0, + .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size, + .pcm_sample_bit_depth_luma_minus1 = sps->pcm_enabled_flag ? sps->pcm.bit_depth - 1 : 0, + .pcm_sample_bit_depth_chroma_minus1 = sps->pcm_enabled_flag ? sps->pcm.bit_depth_chroma - 1 : 0, + .pcm_loop_filter_disabled_flag = sps->pcm.loop_filter_disable_flag, + .strong_intra_smoothing_enabled_flag = sps->sps_strong_intra_smoothing_enable_flag, + .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra, + .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter, + .amp_enabled_flag = sps->amp_enabled_flag, + .separate_colour_plane_flag = sps->separate_colour_plane_flag, + .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4, + .num_short_term_ref_pic_sets = sps->nb_st_rps, + .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag, + .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps, + .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag, + .sample_adaptive_offset_enabled_flag = sps->sao_enabled, + .scaling_list_enable_flag = sps->scaling_list_enable_flag, + .IrapPicFlag = IS_IRAP(s), + .IdrPicFlag = IS_IDR(s), + .bit_depth_luma_minus8 = sps->bit_depth - 8, + .bit_depth_chroma_minus8 = sps->bit_depth - 8, + + .dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag, + .slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag, + .sign_data_hiding_enabled_flag = pps->sign_data_hiding_flag, + .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag, + .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth, + .init_qp_minus26 = pps->pic_init_qp_minus26, + .pps_cb_qp_offset = pps->cb_qp_offset, + .pps_cr_qp_offset = pps->cr_qp_offset, + .constrained_intra_pred_flag = pps->constrained_intra_pred_flag, + .weighted_pred_flag = pps->weighted_pred_flag, + .weighted_bipred_flag = pps->weighted_bipred_flag, + .transform_skip_enabled_flag = pps->transform_skip_enabled_flag, + .transquant_bypass_enabled_flag = pps->transquant_bypass_enable_flag, + .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag, + .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2, + .num_extra_slice_header_bits = pps->num_extra_slice_header_bits, + .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag, + .loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag, + .output_flag_present_flag = pps->output_flag_present_flag, + .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1, + .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1, + .lists_modification_present_flag = pps->lists_modification_present_flag, + .cabac_init_present_flag = pps->cabac_init_present_flag, + .pps_slice_chroma_qp_offsets_present_flag = pps->pic_slice_level_chroma_qp_offsets_present_flag, + .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag, + .pps_deblocking_filter_disabled_flag = pps->disable_dbf, + .pps_beta_offset_div2 = pps->beta_offset / 2, + .pps_tc_offset_div2 = pps->tc_offset / 2, + .tiles_enabled_flag = pps->tiles_enabled_flag, + .uniform_spacing_flag = pps->uniform_spacing_flag, + .num_tile_columns_minus1 = pps->num_tile_columns - 1, + .num_tile_rows_minus1 = pps->num_tile_rows - 1, + + .NumBitsForShortTermRPSInSlice = s->sh.short_term_rps ? s->sh.short_term_ref_pic_set_size : 0, + .NumDeltaPocsOfRefRpsIdx = s->sh.short_term_rps ? s->sh.short_term_rps->rps_idx_num_delta_pocs : 0, + .NumPocTotalCurr = s->rps[ST_CURR_BEF].nb_refs + s->rps[ST_CURR_AFT].nb_refs + + s->rps[LT_CURR].nb_refs, + .NumPocStCurrBefore = s->rps[ST_CURR_BEF].nb_refs, + .NumPocStCurrAfter = s->rps[ST_CURR_AFT].nb_refs, + .NumPocLtCurr = s->rps[LT_CURR].nb_refs, + .CurrPicOrderCntVal = s->ref->poc, + }, + }; + + if (pps->num_tile_columns > FF_ARRAY_ELEMS(ppc->column_width_minus1) || + pps->num_tile_rows > FF_ARRAY_ELEMS(ppc->row_height_minus1)) { + av_log(avctx, AV_LOG_ERROR, "Too many tiles\n"); + return AVERROR(ENOSYS); + } + for (i = 0; i < pps->num_tile_columns; i++) + ppc->column_width_minus1[i] = pps->column_width[i] - 1; + for (i = 0; i < pps->num_tile_rows; i++) + ppc->row_height_minus1[i] = pps->row_height[i] - 1; + + if (s->rps[LT_CURR].nb_refs > FF_ARRAY_ELEMS(ppc->RefPicSetLtCurr) || + s->rps[ST_CURR_BEF].nb_refs > FF_ARRAY_ELEMS(ppc->RefPicSetStCurrBefore) || + s->rps[ST_CURR_AFT].nb_refs > FF_ARRAY_ELEMS(ppc->RefPicSetStCurrAfter)) { + av_log(avctx, AV_LOG_ERROR, "Too many reference frames\n"); + return AVERROR(ENOSYS); + } + + dpb_size = 0; + for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { + const HEVCFrame *ref = &s->DPB[i]; + if (!(ref->flags & (HEVC_FRAME_FLAG_SHORT_REF | HEVC_FRAME_FLAG_LONG_REF))) + continue; + if (dpb_size >= FF_ARRAY_ELEMS(ppc->RefPicIdx)) { + av_log(avctx, AV_LOG_ERROR, "Too many reference frames\n"); + return AVERROR_INVALIDDATA; + } + dpb_add(ppc, dpb_size++, ref); + + } + for (i = dpb_size; i < FF_ARRAY_ELEMS(ppc->RefPicIdx); i++) + ppc->RefPicIdx[i] = -1; + + for (i = 0; i < s->rps[ST_CURR_BEF].nb_refs; i++) { + for (j = 0; j < dpb_size; j++) { + if (ppc->PicOrderCntVal[j] == s->rps[ST_CURR_BEF].list[i]) { + ppc->RefPicSetStCurrBefore[i] = j; + break; + } + } + } + for (i = 0; i < s->rps[ST_CURR_AFT].nb_refs; i++) { + for (j = 0; j < dpb_size; j++) { + if (ppc->PicOrderCntVal[j] == s->rps[ST_CURR_AFT].list[i]) { + ppc->RefPicSetStCurrAfter[i] = j; + break; + } + } + } + for (i = 0; i < s->rps[LT_CURR].nb_refs; i++) { + for (j = 0; j < dpb_size; j++) { + if (ppc->PicOrderCntVal[j] == s->rps[LT_CURR].list[i]) { + ppc->RefPicSetLtCurr[i] = j; + break; + } + } + } + + fill_scaling_lists(ppc, s); + + return 0; +} + +static int cuvid_hevc_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, + uint32_t size) +{ + CUVIDContext *ctx = avctx->internal->hwaccel_priv_data; + void *tmp; + + tmp = av_fast_realloc(ctx->bitstream, &ctx->bitstream_allocated, + ctx->bitstream_len + size + 3); + if (!tmp) + return AVERROR(ENOMEM); + ctx->bitstream = tmp; + + tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated, + (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets)); + if (!tmp) + return AVERROR(ENOMEM); + ctx->slice_offsets = tmp; + + AV_WB24(ctx->bitstream + ctx->bitstream_len, 1); + memcpy(ctx->bitstream + ctx->bitstream_len + 3, buffer, size); + ctx->slice_offsets[ctx->nb_slices] = ctx->bitstream_len ; + ctx->bitstream_len += size + 3; + ctx->nb_slices++; + + return 0; +} + +static int cuvid_hevc_decode_init(AVCodecContext *avctx) +{ + const HEVCContext *s = avctx->priv_data; + const HEVCSPS *sps = s->ps.sps; + return ff_cuvid_decode_init(avctx, sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering + 1); +} + +AVHWAccel ff_hevc_cuvid_hwaccel = { + .name = "hevc_cuvid", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .pix_fmt = AV_PIX_FMT_CUDA, + .start_frame = cuvid_hevc_start_frame, + .end_frame = ff_cuvid_end_frame, + .decode_slice = cuvid_hevc_decode_slice, + .init = cuvid_hevc_decode_init, + .uninit = ff_cuvid_decode_uninit, + .priv_data_size = sizeof(CUVIDContext), +}; diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 664e4ac14b7c5..a1619cf4bd944 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -384,7 +384,8 @@ static void export_stream_params(AVCodecContext *avctx, const HEVCParamSets *ps, static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) { #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \ - CONFIG_HEVC_VAAPI_HWACCEL + CONFIG_HEVC_VDPAU_HWACCEL) + CONFIG_HEVC_VAAPI_HWACCEL + CONFIG_HEVC_VDPAU_HWACCEL + \ + CONFIG_HEVC_CUVID_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts; if (sps->pix_fmt == AV_PIX_FMT_YUV420P || sps->pix_fmt == AV_PIX_FMT_YUVJ420P || @@ -398,9 +399,15 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #endif #if CONFIG_HEVC_VAAPI_HWACCEL *fmt++ = AV_PIX_FMT_VAAPI; +#endif +#if CONFIG_HEVC_CUVID_HWACCEL && HAVE_CUVIDDECODECREATEINFO_BITDEPTHMINUS8 + *fmt++ = AV_PIX_FMT_CUDA; #endif } if (sps->pix_fmt == AV_PIX_FMT_YUV420P || sps->pix_fmt == AV_PIX_FMT_YUVJ420P) { +#if CONFIG_HEVC_CUVID_HWACCEL && !HAVE_CUVIDDECODECREATEINFO_BITDEPTHMINUS8 + *fmt++ = AV_PIX_FMT_CUDA; +#endif #if CONFIG_HEVC_VDPAU_HWACCEL *fmt++ = AV_PIX_FMT_VDPAU; #endif From d7bdab1ad78ef582ba8c96dc7b79ec9fdbeeb94f Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Fri, 28 Jul 2017 16:17:33 -0400 Subject: [PATCH 0339/2557] mov: log and return early on non-positive stsd entry counts Based on an FFmpeg patch by Michael Niedermayer --- libavformat/mov.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index bf68fbd46affb..8ff60222efb91 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1875,6 +1875,11 @@ static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_rb24(pb); /* flags */ entries = avio_rb32(pb); + if (entries <= 0) { + av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries); + return AVERROR_INVALIDDATA; + } + if (sc->extradata) { av_log(c->fc, AV_LOG_ERROR, "Duplicate stsd found in this track.\n"); From 3050dabaa9a337ad077ec60bba664ad9861e1aa6 Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Fri, 28 Jul 2017 16:29:35 -0400 Subject: [PATCH 0340/2557] mov: Do not set stsd_count if mov_read_stsd() fails Based on an FFmpeg patch by Michael Niedermayer --- libavformat/mov.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 8ff60222efb91..2134bd17436c2 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1891,24 +1891,33 @@ static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (!sc->extradata) return AVERROR(ENOMEM); - sc->stsd_count = entries; - sc->extradata_size = av_mallocz_array(sc->stsd_count, sizeof(*sc->extradata_size)); - if (!sc->extradata_size) - return AVERROR(ENOMEM); + sc->extradata_size = av_mallocz_array(entries, sizeof(*sc->extradata_size)); + if (!sc->extradata_size) { + ret = AVERROR(ENOMEM); + goto fail; + } - ret = ff_mov_read_stsd_entries(c, pb, sc->stsd_count); + ret = ff_mov_read_stsd_entries(c, pb, entries); if (ret < 0) - return ret; + goto fail; + + sc->stsd_count = entries; /* Restore back the primary extradata. */ av_free(st->codecpar->extradata); st->codecpar->extradata_size = sc->extradata_size[0]; st->codecpar->extradata = av_mallocz(sc->extradata_size[0] + AV_INPUT_BUFFER_PADDING_SIZE); - if (!st->codecpar->extradata) - return AVERROR(ENOMEM); + if (!st->codecpar->extradata) { + ret = AVERROR(ENOMEM); + goto fail; + } memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]); return 0; +fail: + av_freep(&sc->extradata); + av_freep(&sc->extradata_size); + return ret; } static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom) From defe307fb22beca60a632e976ab97e5edd4aee25 Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Sat, 29 Jul 2017 19:17:16 -0400 Subject: [PATCH 0341/2557] mov: move stsd finalization to an appropriate place mov_finalize_stsd_codec() parses stream information from the ALAC extradata, so run it after the extradata processing is completed in mov_read_stsd(). Fixes playback of 96kHz ALAC streams muxed by qaac or the reference alac encoder. Adapted from an FFmpeg patch by Hendrik Leppkes Bug-Id: 1072 --- libavformat/mov.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 2134bd17436c2..6711d8e11ebbe 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1857,7 +1857,7 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) if (pb->eof_reached) return AVERROR_EOF; - return mov_finalize_stsd_codec(c, pb, st, sc); + return 0; } static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom) @@ -1913,7 +1913,7 @@ static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom) } memcpy(st->codecpar->extradata, sc->extradata[0], sc->extradata_size[0]); - return 0; + return mov_finalize_stsd_codec(c, pb, st, sc); fail: av_freep(&sc->extradata); av_freep(&sc->extradata_size); From aaf441465080b9bc57f5ca8dea656f9b2c5dc821 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 24 Jun 2017 00:30:20 +0100 Subject: [PATCH 0342/2557] h264: Add stream constraint values to the common header With comments describing the derivation of each value. --- libavcodec/h264.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/libavcodec/h264.h b/libavcodec/h264.h index eb3805c0678d9..aa137b5b54230 100644 --- a/libavcodec/h264.h +++ b/libavcodec/h264.h @@ -44,4 +44,49 @@ enum { H264_NAL_AUXILIARY_SLICE = 19, }; + +enum { + // 7.4.2.1.1: seq_parameter_set_id is in [0, 31]. + H264_MAX_SPS_COUNT = 32, + // 7.4.2.2: pic_parameter_set_id is in [0, 255]. + H264_MAX_PPS_COUNT = 256, + + // A.3: MaxDpbFrames is bounded above by 16. + H264_MAX_DPB_FRAMES = 16, + // 7.4.2.1.1: max_num_ref_frames is in [0, MaxDpbFrames], and + // each reference frame can have two fields. + H264_MAX_REFS = 2 * H264_MAX_DPB_FRAMES, + + // 7.4.3.1: modification_of_pic_nums_idc is not equal to 3 at most + // num_ref_idx_lN_active_minus1 + 1 times (that is, once for each + // possible reference), then equal to 3 once. + H264_MAX_RPLM_COUNT = H264_MAX_REFS + 1, + + // 7.4.3.3: in the worst case, we begin with a full short-term + // reference picture list. Each picture in turn is moved to the + // long-term list (type 3) and then discarded from there (type 2). + // Then, we set the length of the long-term list (type 4), mark + // the current picture as long-term (type 6) and terminate the + // process (type 0). + H264_MAX_MMCO_COUNT = H264_MAX_REFS * 2 + 3, + + // A.2.1, A.2.3: profiles supporting FMO constrain + // num_slice_groups_minus1 to be in [0, 7]. + H264_MAX_SLICE_GROUPS = 8, + + // E.2.2: cpb_cnt_minus1 is in [0, 31]. + H264_MAX_CPB_CNT = 32, + + // A.3: in table A-1 the highest level allows a MaxFS of 139264. + H264_MAX_MB_PIC_SIZE = 139264, + // A.3.1, A.3.2: PicWidthInMbs and PicHeightInMbs are constrained + // to be not greater than sqrt(MaxFS * 8). Hence height/width are + // bounded above by sqrt(139264 * 8) = 1055.5 macroblocks. + H264_MAX_MB_WIDTH = 1055, + H264_MAX_MB_HEIGHT = 1055, + H264_MAX_WIDTH = H264_MAX_MB_WIDTH * 16, + H264_MAX_HEIGHT = H264_MAX_MB_HEIGHT * 16, +}; + + #endif /* AVCODEC_H264_H */ From b88da98b34809dedf8882d43ed543632ed233538 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 24 Jun 2017 00:29:02 +0100 Subject: [PATCH 0343/2557] hevc: Improve stream constraint values in common header Add comments to describe the sources of the constraint values expressed here, and add some more related values which will be used in following patches. Fix the incorrect values for SPS and PPS count (they are not the same as those used for H.264), and remove HEVC_MAX_CU_SIZE because it is not used anywhere. --- libavcodec/hevc.h | 65 ++++++++++++++++++++++++++++++++++++-------- libavcodec/hevc_ps.c | 2 +- libavcodec/hevc_ps.h | 6 ++-- libavformat/hevc.c | 6 ++-- 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index 9d956d0838206..77bd6a6373d59 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -74,19 +74,60 @@ enum HEVCSliceType { HEVC_SLICE_I = 2, }; -/** - * 7.4.2.1 - */ -#define HEVC_MAX_SUB_LAYERS 7 -#define HEVC_MAX_VPS_COUNT 16 -#define HEVC_MAX_SPS_COUNT 32 -#define HEVC_MAX_PPS_COUNT 256 -#define HEVC_MAX_SHORT_TERM_RPS_COUNT 64 -#define HEVC_MAX_CU_SIZE 128 +enum { + // 7.4.3.1: vps_max_layers_minus1 is in [0, 62]. + HEVC_MAX_LAYERS = 63, + // 7.4.3.1: vps_max_sub_layers_minus1 is in [0, 6]. + HEVC_MAX_SUB_LAYERS = 7, + // 7.4.3.1: vps_num_layer_sets_minus1 is in [0, 1023]. + HEVC_MAX_LAYER_SETS = 1024, + + // 7.4.2.1: vps_video_parameter_set_id is u(4). + HEVC_MAX_VPS_COUNT = 16, + // 7.4.3.2.1: sps_seq_parameter_set_id is in [0, 15]. + HEVC_MAX_SPS_COUNT = 16, + // 7.4.3.3.1: pps_pic_parameter_set_id is in [0, 63]. + HEVC_MAX_PPS_COUNT = 64, + + // A.4.2: MaxDpbSize is bounded above by 16. + HEVC_MAX_DPB_SIZE = 16, + // 7.4.3.1: vps_max_dec_pic_buffering_minus1[i] is in [0, MaxDpbSize - 1]. + HEVC_MAX_REFS = HEVC_MAX_DPB_SIZE, + + // 7.4.3.2.1: num_short_term_ref_pic_sets is in [0, 64]. + HEVC_MAX_SHORT_TERM_REF_PIC_SETS = 64, + // 7.4.3.2.1: num_long_term_ref_pics_sps is in [0, 32]. + HEVC_MAX_LONG_TERM_REF_PICS = 32, -#define HEVC_MAX_REFS 16 -#define HEVC_MAX_DPB_SIZE 16 // A.4.1 + // A.3: all profiles require that CtbLog2SizeY is in [4, 6]. + HEVC_MIN_LOG2_CTB_SIZE = 4, + HEVC_MAX_LOG2_CTB_SIZE = 6, + + // E.3.2: cpb_cnt_minus1[i] is in [0, 31]. + HEVC_MAX_CPB_CNT = 32, + + // A.4.1: in table A.6 the highest level allows a MaxLumaPs of 35 651 584. + HEVC_MAX_LUMA_PS = 35651584, + // A.4.1: pic_width_in_luma_samples and pic_height_in_luma_samples are + // constrained to be not greater than sqrt(MaxLumaPs * 8). Hence height/ + // width are bounded above by sqrt(8 * 35651584) = 16888.2 samples. + HEVC_MAX_WIDTH = 16888, + HEVC_MAX_HEIGHT = 16888, + + // A.4.1: table A.6 allows at most 22 tile rows for any level. + HEVC_MAX_TILE_ROWS = 22, + // A.4.1: table A.6 allows at most 20 tile columns for any level. + HEVC_MAX_TILE_COLUMNS = 20, + + // 7.4.7.1: in the worst case (tiles_enabled_flag and + // entropy_coding_sync_enabled_flag are both set), entry points can be + // placed at the beginning of every Ctb row in every tile, giving an + // upper bound of (num_tile_columns_minus1 + 1) * PicHeightInCtbsY - 1. + // Only a stream with very high resolution and perverse parameters could + // get near that, though, so set a lower limit here with the maximum + // possible value for 4K video (at most 135 16x16 Ctb rows). + HEVC_MAX_ENTRY_POINT_OFFSETS = HEVC_MAX_TILE_COLUMNS * 135, +}; -#define HEVC_MAX_LOG2_CTB_SIZE 6 #endif /* AVCODEC_HEVC_H */ diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 3c98e4ce443a2..74906fd71b081 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -868,7 +868,7 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, } sps->nb_st_rps = get_ue_golomb_long(gb); - if (sps->nb_st_rps > HEVC_MAX_SHORT_TERM_RPS_COUNT) { + if (sps->nb_st_rps > HEVC_MAX_SHORT_TERM_REF_PIC_SETS) { av_log(avctx, AV_LOG_ERROR, "Too many short term RPS: %d.\n", sps->nb_st_rps); ret = AVERROR_INVALIDDATA; diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 89a481ba8e756..6e2b527773666 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -166,14 +166,14 @@ typedef struct HEVCSPS { ScalingList scaling_list; unsigned int nb_st_rps; - ShortTermRPS st_rps[HEVC_MAX_SHORT_TERM_RPS_COUNT]; + ShortTermRPS st_rps[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]; uint8_t amp_enabled_flag; uint8_t sao_enabled; uint8_t long_term_ref_pics_present_flag; - uint16_t lt_ref_pic_poc_lsb_sps[32]; - uint8_t used_by_curr_pic_lt_sps_flag[32]; + uint16_t lt_ref_pic_poc_lsb_sps[HEVC_MAX_LONG_TERM_REF_PICS]; + uint8_t used_by_curr_pic_lt_sps_flag[HEVC_MAX_LONG_TERM_REF_PICS]; uint8_t num_long_term_ref_pics_sps; struct { diff --git a/libavformat/hevc.c b/libavformat/hevc.c index 057f6517ffe7e..f8bfeebd31130 100644 --- a/libavformat/hevc.c +++ b/libavformat/hevc.c @@ -412,7 +412,7 @@ static void skip_scaling_list_data(GetBitContext *gb) static int parse_rps(GetBitContext *gb, unsigned int rps_idx, unsigned int num_rps, - unsigned int num_delta_pocs[HEVC_MAX_SHORT_TERM_RPS_COUNT]) + unsigned int num_delta_pocs[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]) { unsigned int i; @@ -478,7 +478,7 @@ static int hvcc_parse_sps(GetBitContext *gb, HEVCDecoderConfigurationRecord *hvcc) { unsigned int i, sps_max_sub_layers_minus1, log2_max_pic_order_cnt_lsb_minus4; - unsigned int num_short_term_ref_pic_sets, num_delta_pocs[HEVC_MAX_SHORT_TERM_RPS_COUNT]; + unsigned int num_short_term_ref_pic_sets, num_delta_pocs[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]; skip_bits(gb, 4); // sps_video_parameter_set_id @@ -548,7 +548,7 @@ static int hvcc_parse_sps(GetBitContext *gb, } num_short_term_ref_pic_sets = get_ue_golomb_long(gb); - if (num_short_term_ref_pic_sets > HEVC_MAX_SHORT_TERM_RPS_COUNT) + if (num_short_term_ref_pic_sets > HEVC_MAX_SHORT_TERM_REF_PIC_SETS) return AVERROR_INVALIDDATA; for (i = 0; i < num_short_term_ref_pic_sets; i++) { From 1329c08ad6d2ddb304858f2972c67b508e8b0f0e Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 24 Jun 2017 00:29:14 +0100 Subject: [PATCH 0344/2557] hevc: Validate the number of long term reference pictures This would overflow if the stream contained a value greater than the maximum allowed by the standard (32). --- libavcodec/hevc_ps.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 74906fd71b081..2603e6d99fab9 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -883,6 +883,12 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, sps->long_term_ref_pics_present_flag = get_bits1(gb); if (sps->long_term_ref_pics_present_flag) { sps->num_long_term_ref_pics_sps = get_ue_golomb_long(gb); + if (sps->num_long_term_ref_pics_sps > HEVC_MAX_LONG_TERM_REF_PICS) { + av_log(avctx, AV_LOG_ERROR, "Too many long term ref pics: %d.\n", + sps->num_long_term_ref_pics_sps); + ret = AVERROR_INVALIDDATA; + goto err; + } for (i = 0; i < sps->num_long_term_ref_pics_sps; i++) { sps->lt_ref_pic_poc_lsb_sps[i] = get_bits(gb, sps->log2_max_poc_lsb); sps->used_by_curr_pic_lt_sps_flag[i] = get_bits1(gb); From 19388a7200e5d99c703271f05dba1c806720e808 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 30 Apr 2017 19:27:54 +0100 Subject: [PATCH 0345/2557] vaapi_encode: Move quality option to common code Use AVCodecContext.compression_level rather than a private option, replacing the H.264-specific quality option (which stays only for compatibility). This now works with the H.265 encoder in the i965 driver, as well as the existing cases with the H.264 encoder. --- doc/encoders.texi | 9 ++++++--- libavcodec/vaapi_encode.c | 35 ++++++++++++++++++++++++++++++++++ libavcodec/vaapi_encode.h | 6 ++++++ libavcodec/vaapi_encode_h264.c | 25 ++---------------------- 4 files changed, 49 insertions(+), 26 deletions(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index 7cebe39c18d28..c369e03bfd33c 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -948,7 +948,13 @@ The following standard libavcodec options are used: @item @option{rc_init_occupancy} / @option{rc_initial_buffer_occupancy} @item +@option{compression_level} + +Speed / quality tradeoff: higher values are faster / worse quality. +@item @option{q} / @option{global_quality} + +Size / quality tradeoff: higher values are smaller / worse quality. @item @option{qmin} (only: @option{qmax} is not supported) @@ -969,9 +975,6 @@ The following standard libavcodec options are used: @option{level} sets the value of @emph{level_idc}. @table @option -@item quality -Set the local encoding quality/speed tradeoff (range 1-8, higher values are faster; not all -systems implement all levels). @item low_power Use low-power encoding mode. @end table diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 62051841903b4..462ec7a8e7ae8 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1423,6 +1423,41 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) goto fail; } + if (avctx->compression_level >= 0) { +#if VA_CHECK_VERSION(0, 36, 0) + VAConfigAttrib attr = { VAConfigAttribEncQualityRange }; + + vas = vaGetConfigAttributes(ctx->hwctx->display, + ctx->va_profile, + ctx->va_entrypoint, + &attr, 1); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_WARNING, "Failed to query quality " + "attribute: will use default compression level.\n"); + } else { + if (avctx->compression_level > attr.value) { + av_log(avctx, AV_LOG_WARNING, "Invalid compression " + "level: valid range is 0-%d, using %d.\n", + attr.value, attr.value); + avctx->compression_level = attr.value; + } + + ctx->quality_params.misc.type = + VAEncMiscParameterTypeQualityLevel; + ctx->quality_params.quality.quality_level = + avctx->compression_level; + + ctx->global_params[ctx->nb_global_params] = + &ctx->quality_params.misc; + ctx->global_params_size[ctx->nb_global_params++] = + sizeof(ctx->quality_params); + } +#else + av_log(avctx, AV_LOG_WARNING, "The encode compression level " + "option is not supported with this VAAPI version.\n"); +#endif + } + ctx->input_order = 0; ctx->output_delay = avctx->max_b_frames; ctx->decode_delay = 1; diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index fc62365148c79..1b0fed80e449a 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -159,6 +159,12 @@ typedef struct VAAPIEncodeContext { VAEncMiscParameterBuffer misc; VAEncMiscParameterFrameRate fr; } fr_params; +#if VA_CHECK_VERSION(0, 36, 0) + struct { + VAEncMiscParameterBuffer misc; + VAEncMiscParameterBufferQualityLevel quality; + } quality_params; +#endif // Per-sequence parameter structure (VAEncSequenceParameterBuffer*). void *codec_sequence_params; diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 7583a20c149c6..e08cf61167c35 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -154,14 +154,6 @@ typedef struct VAAPIEncodeH264Context { // Rate control configuration. int send_timing_sei; - -#if VA_CHECK_VERSION(0, 36, 0) - // Speed-quality tradeoff setting. - struct { - VAEncMiscParameterBuffer misc; - VAEncMiscParameterBufferQualityLevel quality; - } quality_params; -#endif } VAAPIEncodeH264Context; typedef struct VAAPIEncodeH264Options { @@ -1141,21 +1133,8 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx) av_assert0(0 && "Invalid RC mode."); } - if (opt->quality > 0) { -#if VA_CHECK_VERSION(0, 36, 0) - priv->quality_params.misc.type = - VAEncMiscParameterTypeQualityLevel; - priv->quality_params.quality.quality_level = opt->quality; - - ctx->global_params[ctx->nb_global_params] = - &priv->quality_params.misc; - ctx->global_params_size[ctx->nb_global_params++] = - sizeof(priv->quality_params); -#else - av_log(avctx, AV_LOG_WARNING, "The encode quality option is not " - "supported with this VAAPI version.\n"); -#endif - } + if (avctx->compression_level == FF_COMPRESSION_DEFAULT) + avctx->compression_level = opt->quality; return 0; } From ebf3b9e8a875eb12312460aee505118791ef805f Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Tue, 8 Aug 2017 16:06:29 +0200 Subject: [PATCH 0346/2557] h264: Add support for alternative transfer characterics SEI The use of this SEI is for backward compatibility in HLG HDR systems: older devices that cannot interpret the "arib-std-b67" transfer will get the compatible transfer (usually bt709 or bt2020) from the VUI, while newer devices that can interpret HDR will read the SEI and use its value instead. Signed-off-by: Vittorio Giovara --- libavcodec/h264_sei.c | 11 +++++++++++ libavcodec/h264_sei.h | 7 +++++++ libavcodec/h264_slice.c | 6 ++++++ 3 files changed, 24 insertions(+) diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c index 3ca2b7a6cd730..03fca9017f9d1 100644 --- a/libavcodec/h264_sei.c +++ b/libavcodec/h264_sei.c @@ -346,6 +346,14 @@ static int decode_display_orientation(H264SEIDisplayOrientation *h, return 0; } +static int decode_alternative_transfer(H264SEIAlternativeTransfer *h, + GetBitContext *gb) +{ + h->present = 1; + h->preferred_transfer_characteristics = get_bits(gb, 8); + return 0; +} + int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb, const H264ParamSets *ps, void *logctx) { @@ -396,6 +404,9 @@ int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb, case H264_SEI_TYPE_DISPLAY_ORIENTATION: ret = decode_display_orientation(&h->display_orientation, gb); break; + case H264_SEI_TYPE_ALTERNATIVE_TRANSFER: + ret = decode_alternative_transfer(&h->alternative_transfer, gb); + break; default: av_log(logctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type); skip_bits(gb, 8 * size); diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h index ce9768ec3de32..f6ac6034daac1 100644 --- a/libavcodec/h264_sei.h +++ b/libavcodec/h264_sei.h @@ -33,6 +33,7 @@ typedef enum { H264_SEI_TYPE_RECOVERY_POINT = 6, ///< recovery point (frame # to decoder sync) H264_SEI_TYPE_FRAME_PACKING = 45, ///< frame packing arrangement H264_SEI_TYPE_DISPLAY_ORIENTATION = 47, ///< display orientation + H264_SEI_TYPE_ALTERNATIVE_TRANSFER = 147, ///< alternative transfer } H264_SEI_Type; /** @@ -115,6 +116,11 @@ typedef struct H264SEIDisplayOrientation { int hflip, vflip; } H264SEIDisplayOrientation; +typedef struct H264SEIAlternativeTransfer { + int present; + int preferred_transfer_characteristics; +} H264SEIAlternativeTransfer; + typedef struct H264SEIContext { H264SEIPictureTiming picture_timing; H264SEIAFD afd; @@ -124,6 +130,7 @@ typedef struct H264SEIContext { H264SEIBufferingPeriod buffering_period; H264SEIFramePacking frame_packing; H264SEIDisplayOrientation display_orientation; + H264SEIAlternativeTransfer alternative_transfer; } H264SEIContext; struct H264ParamSets; diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index c6309b298c28a..5dd01d836e95b 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1154,6 +1154,12 @@ static int h264_export_frame_props(H264Context *h) a53->a53_caption_size = 0; } + if (h->sei.alternative_transfer.present && + av_color_transfer_name(h->sei.alternative_transfer.preferred_transfer_characteristics) && + h->sei.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) { + h->avctx->color_trc = cur->f->color_trc = h->sei.alternative_transfer.preferred_transfer_characteristics; + } + return 0; } From 538e50875105c9d4a04bc4ed4a217e87f422137e Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Tue, 8 Aug 2017 16:30:32 +0200 Subject: [PATCH 0347/2557] pixfmt: Support chroma-derived and ictcp color matrices Signed-off-by: Vittorio Giovara --- libavutil/pixdesc.c | 3 +++ libavutil/pixfmt.h | 3 +++ libavutil/version.h | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 7fa6dd7c0b878..b168ac7d0b26a 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -1806,6 +1806,9 @@ static const char * const color_space_names[] = { [AVCOL_SPC_BT2020_NCL] = "bt2020nc", [AVCOL_SPC_BT2020_CL] = "bt2020c", [AVCOL_SPC_SMPTE2085] = "smpte2085", + [AVCOL_SPC_CHROMA_DERIVED_NCL] = "chroma-derived-nc", + [AVCOL_SPC_CHROMA_DERIVED_CL] = "chroma-derived-c", + [AVCOL_SPC_ICTCP] = "ictcp", }; static const char * const chroma_location_names[] = { diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 2ba7ad1c88c05..bcbb378378ef8 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -384,6 +384,9 @@ enum AVColorSpace { AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system AVCOL_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x + AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system + AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system + AVCOL_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp AVCOL_SPC_NB, ///< Not part of ABI }; diff --git a/libavutil/version.h b/libavutil/version.h index 62fb38a27aae7..5d0bb611244d4 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -54,7 +54,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 4 +#define LIBAVUTIL_VERSION_MINOR 5 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 18f1706f331bf5dd565774eae680508c8d3a97ad Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 4 May 2017 23:01:51 +0100 Subject: [PATCH 0348/2557] lavc: Add coded bitstream read/write API --- configure | 1 + libavcodec/Makefile | 1 + libavcodec/cbs.c | 460 ++++++++++++++++++++++++++++++++++++++ libavcodec/cbs.h | 274 +++++++++++++++++++++++ libavcodec/cbs_internal.h | 83 +++++++ 5 files changed, 819 insertions(+) create mode 100644 libavcodec/cbs.c create mode 100644 libavcodec/cbs.h create mode 100644 libavcodec/cbs_internal.h diff --git a/configure b/configure index 4510100f3845a..befaed1e58a61 100755 --- a/configure +++ b/configure @@ -1739,6 +1739,7 @@ CONFIG_EXTRA=" blockdsp bswapdsp cabac + cbs dirac_parse dvprofile faandct diff --git a/libavcodec/Makefile b/libavcodec/Makefile index bb568ddbe46a5..41da3ca7ba2f1 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -53,6 +53,7 @@ OBJS-$(CONFIG_AUDIODSP) += audiodsp.o OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o OBJS-$(CONFIG_CABAC) += cabac.o +OBJS-$(CONFIG_CBS) += cbs.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o OBJS-$(CONFIG_FAANDCT) += faandct.o diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c new file mode 100644 index 0000000000000..3a205c393d92f --- /dev/null +++ b/libavcodec/cbs.c @@ -0,0 +1,460 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" + +#include "libavutil/avassert.h" +#include "libavutil/common.h" + +#include "cbs.h" +#include "cbs_internal.h" + + +static const CodedBitstreamType *cbs_type_table[] = { +}; + +int ff_cbs_init(CodedBitstreamContext *ctx, + enum AVCodecID codec_id, void *log_ctx) +{ + const CodedBitstreamType *type; + int i; + + type = NULL; + for (i = 0; i < FF_ARRAY_ELEMS(cbs_type_table); i++) { + if (cbs_type_table[i]->codec_id == codec_id) { + type = cbs_type_table[i]; + break; + } + } + if (!type) + return AVERROR(EINVAL); + + ctx->log_ctx = log_ctx; + ctx->codec = type; + + ctx->priv_data = av_mallocz(ctx->codec->priv_data_size); + if (!ctx->priv_data) + return AVERROR(ENOMEM); + + ctx->decompose_unit_types = NULL; + + ctx->trace_enable = 0; + ctx->trace_level = AV_LOG_TRACE; + + return 0; +} + +void ff_cbs_close(CodedBitstreamContext *ctx) +{ + if (ctx->codec && ctx->codec->close) + ctx->codec->close(ctx); + + av_freep(&ctx->priv_data); +} + +static void cbs_unit_uninit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + if (ctx->codec->free_unit && unit->content && !unit->content_external) + ctx->codec->free_unit(unit); + + av_freep(&unit->data); + unit->data_size = 0; + unit->data_bit_padding = 0; +} + +void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag) +{ + int i; + + for (i = 0; i < frag->nb_units; i++) + cbs_unit_uninit(ctx, &frag->units[i]); + av_freep(&frag->units); + frag->nb_units = 0; + + av_freep(&frag->data); + frag->data_size = 0; + frag->data_bit_padding = 0; +} + +static int cbs_read_fragment_content(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag) +{ + int err, i, j; + + for (i = 0; i < frag->nb_units; i++) { + if (ctx->decompose_unit_types) { + for (j = 0; j < ctx->nb_decompose_unit_types; j++) { + if (ctx->decompose_unit_types[j] == frag->units[i].type) + break; + } + if (j >= ctx->nb_decompose_unit_types) + continue; + } + + err = ctx->codec->read_unit(ctx, &frag->units[i]); + if (err == AVERROR(ENOSYS)) { + av_log(ctx->log_ctx, AV_LOG_WARNING, + "Decomposition unimplemented for unit %d " + "(type %d).\n", i, frag->units[i].type); + } else if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d " + "(type %d).\n", i, frag->units[i].type); + return err; + } + } + + return 0; +} + +int ff_cbs_read_extradata(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const AVCodecParameters *par) +{ + int err; + + memset(frag, 0, sizeof(*frag)); + + frag->data = par->extradata; + frag->data_size = par->extradata_size; + + err = ctx->codec->split_fragment(ctx, frag, 1); + if (err < 0) + return err; + + frag->data = NULL; + frag->data_size = 0; + + return cbs_read_fragment_content(ctx, frag); +} + +int ff_cbs_read_packet(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const AVPacket *pkt) +{ + int err; + + memset(frag, 0, sizeof(*frag)); + + frag->data = pkt->data; + frag->data_size = pkt->size; + + err = ctx->codec->split_fragment(ctx, frag, 0); + if (err < 0) + return err; + + frag->data = NULL; + frag->data_size = 0; + + return cbs_read_fragment_content(ctx, frag); +} + +int ff_cbs_read(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const uint8_t *data, size_t size) +{ + int err; + + memset(frag, 0, sizeof(*frag)); + + // (We won't write to this during split.) + frag->data = (uint8_t*)data; + frag->data_size = size; + + err = ctx->codec->split_fragment(ctx, frag, 0); + if (err < 0) + return err; + + frag->data = NULL; + frag->data_size = 0; + + return cbs_read_fragment_content(ctx, frag); +} + + +int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag) +{ + int err, i; + + for (i = 0; i < frag->nb_units; i++) { + if (!frag->units[i].content) + continue; + + err = ctx->codec->write_unit(ctx, &frag->units[i]); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d " + "(type %d).\n", i, frag->units[i].type); + return err; + } + } + + err = ctx->codec->assemble_fragment(ctx, frag); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n"); + return err; + } + + return 0; +} + +int ff_cbs_write_extradata(CodedBitstreamContext *ctx, + AVCodecParameters *par, + CodedBitstreamFragment *frag) +{ + int err; + + err = ff_cbs_write_fragment_data(ctx, frag); + if (err < 0) + return err; + + av_freep(&par->extradata); + + par->extradata = av_malloc(frag->data_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!par->extradata) + return AVERROR(ENOMEM); + + memcpy(par->extradata, frag->data, frag->data_size); + memset(par->extradata + frag->data_size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); + par->extradata_size = frag->data_size; + + return 0; +} + +int ff_cbs_write_packet(CodedBitstreamContext *ctx, + AVPacket *pkt, + CodedBitstreamFragment *frag) +{ + int err; + + err = ff_cbs_write_fragment_data(ctx, frag); + if (err < 0) + return err; + + av_new_packet(pkt, frag->data_size); + if (err < 0) + return err; + + memcpy(pkt->data, frag->data, frag->data_size); + pkt->size = frag->data_size; + + return 0; +} + + +void ff_cbs_trace_header(CodedBitstreamContext *ctx, + const char *name) +{ + if (!ctx->trace_enable) + return; + + av_log(ctx->log_ctx, ctx->trace_level, "%s\n", name); +} + +void ff_cbs_trace_syntax_element(CodedBitstreamContext *ctx, int position, + const char *name, const char *bits, + int64_t value) +{ + size_t name_len, bits_len; + int pad; + + if (!ctx->trace_enable) + return; + + av_assert0(value >= INT_MIN && value <= UINT32_MAX); + + name_len = strlen(name); + bits_len = strlen(bits); + + if (name_len + bits_len > 60) + pad = bits_len + 2; + else + pad = 61 - name_len; + + av_log(ctx->log_ctx, ctx->trace_level, "%-10d %s%*s = %"PRId64"\n", + position, name, pad, bits, value); +} + +int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, BitstreamContext *bc, + int width, const char *name, uint32_t *write_to, + uint32_t range_min, uint32_t range_max) +{ + uint32_t value; + int position; + + av_assert0(width <= 32); + + if (ctx->trace_enable) + position = bitstream_tell(bc); + + value = bitstream_read(bc, width); + + if (ctx->trace_enable) { + char bits[33]; + int i; + for (i = 0; i < width; i++) + bits[i] = value >> (width - i - 1) & 1 ? '1' : '0'; + bits[i] = 0; + + ff_cbs_trace_syntax_element(ctx, position, name, bits, value); + } + + if (value < range_min || value > range_max) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " + "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n", + name, value, range_min, range_max); + return AVERROR_INVALIDDATA; + } + + *write_to = value; + return 0; +} + +int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc, + int width, const char *name, uint32_t value, + uint32_t range_min, uint32_t range_max) +{ + av_assert0(width <= 32); + + if (value < range_min || value > range_max) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " + "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n", + name, value, range_min, range_max); + return AVERROR_INVALIDDATA; + } + + if (put_bits_left(pbc) < width) + return AVERROR(ENOSPC); + + if (ctx->trace_enable) { + char bits[33]; + int i; + for (i = 0; i < width; i++) + bits[i] = value >> (width - i - 1) & 1 ? '1' : '0'; + bits[i] = 0; + + ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), name, bits, value); + } + + if (width < 32) + put_bits(pbc, width, value); + else + put_bits32(pbc, value); + + return 0; +} + + +static int cbs_insert_unit(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position) +{ + CodedBitstreamUnit *units; + + units = av_malloc_array(frag->nb_units + 1, sizeof(*units)); + if (!units) + return AVERROR(ENOMEM); + + if (position > 0) + memcpy(units, frag->units, position * sizeof(*units)); + if (position < frag->nb_units) + memcpy(units + position + 1, frag->units + position, + (frag->nb_units - position) * sizeof(*units)); + + memset(units + position, 0, sizeof(*units)); + + av_freep(&frag->units); + frag->units = units; + ++frag->nb_units; + + return 0; +} + +int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position, uint32_t type, + void *content) +{ + int err; + + if (position == -1) + position = frag->nb_units; + av_assert0(position >= 0 && position <= frag->nb_units); + + err = cbs_insert_unit(ctx, frag, position); + if (err < 0) + return err; + + frag->units[position].type = type; + frag->units[position].content = content; + frag->units[position].content_external = 1; + + return 0; +} + +int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position, uint32_t type, + uint8_t *data, size_t data_size) +{ + int err; + + if (position == -1) + position = frag->nb_units; + av_assert0(position >= 0 && position <= frag->nb_units); + + err = cbs_insert_unit(ctx, frag, position); + if (err < 0) + return err; + + frag->units[position].type = type; + frag->units[position].data = data; + frag->units[position].data_size = data_size; + + return 0; +} + +int ff_cbs_delete_unit(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position) +{ + if (position < 0 || position >= frag->nb_units) + return AVERROR(EINVAL); + + cbs_unit_uninit(ctx, &frag->units[position]); + + --frag->nb_units; + + if (frag->nb_units == 0) { + av_freep(&frag->units); + + } else { + memmove(frag->units + position, + frag->units + position + 1, + (frag->nb_units - position) * sizeof(*frag->units)); + + // Don't bother reallocating the unit array. + } + + return 0; +} diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h new file mode 100644 index 0000000000000..01b2239b7b1b0 --- /dev/null +++ b/libavcodec/cbs.h @@ -0,0 +1,274 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_H +#define AVCODEC_CBS_H + +#include +#include + +#include "avcodec.h" + + +struct CodedBitstreamType; + +/** + * Coded bitstream unit structure. + * + * A bitstream unit the the smallest element of a bitstream which + * is meaningful on its own. For example, an H.264 NAL unit. + * + * See the codec-specific header for the meaning of this for any + * particular codec. + */ +typedef struct CodedBitstreamUnit { + /** + * Codec-specific type of this unit. + */ + uint32_t type; + + /** + * Pointer to the bitstream form of this unit. + * + * May be NULL if the unit currently only exists in decomposed form. + */ + uint8_t *data; + /** + * The number of bytes in the bitstream (including any padding bits + * in the final byte). + */ + size_t data_size; + /** + * The number of bits which should be ignored in the final byte. + * + * This supports non-byte-aligned bitstreams. + */ + size_t data_bit_padding; + + /** + * Pointer to the decomposed form of this unit. + * + * The type of this structure depends on both the codec and the + * type of this unit. May be NULL if the unit only exists in + * bitstream form. + */ + void *content; + /** + * Whether the content was supplied externally. + * + * If so, it should not be freed when freeing the unit. + */ + int content_external; +} CodedBitstreamUnit; + +/** + * Coded bitstream fragment structure, combining one or more units. + * + * This is any sequence of units. It need not form some greater whole, + * though in many cases it will. For example, an H.264 access unit, + * which is composed of a sequence of H.264 NAL units. + */ +typedef struct CodedBitstreamFragment { + /** + * Pointer to the bitstream form of this fragment. + * + * May be NULL if the fragment only exists as component units. + */ + uint8_t *data; + /** + * The number of bytes in the bitstream. + * + * The number of bytes in the bitstream (including any padding bits + * in the final byte). + */ + size_t data_size; + /** + * The number of bits which should be ignored in the final byte. + */ + size_t data_bit_padding; + + /** + * Number of units in this fragment. + * + * This may be zero if the fragment only exists in bistream form + * and has not been decomposed. + */ + int nb_units; + /** + * Pointer to an array of units of length nb_units. + * + * Must be NULL if nb_units is zero. + */ + CodedBitstreamUnit *units; +} CodedBitstreamFragment; + +/** + * Context structure for coded bitstream operations. + */ +typedef struct CodedBitstreamContext { + /** + * Logging context to be passed to all av_log() calls associated + * with this context. + */ + void *log_ctx; + + /** + * Internal codec-specific hooks. + */ + const struct CodedBitstreamType *codec; + + /** + * Internal codec-specific data. + * + * This contains any information needed when reading/writing + * bitsteams which will not necessarily be present in a fragment. + * For example, for H.264 it contains all currently visible + * parameter sets - they are required to determine the bitstream + * syntax but need not be present in every access unit. + */ + void *priv_data; + + /** + * Array of unit types which should be decomposed when reading. + * + * Types not in this list will be available in bitstream form only. + * If NULL, all supported types will be decomposed. + */ + uint32_t *decompose_unit_types; + /** + * Length of the decompose_unit_types array. + */ + int nb_decompose_unit_types; + + /** + * Enable trace output during read/write operations. + */ + int trace_enable; + /** + * Log level to use for trace output. + * + * From AV_LOG_*; defaults to AV_LOG_TRACE. + */ + int trace_level; +} CodedBitstreamContext; + + +/** + * Initialise a new context for the given codec. + */ +int ff_cbs_init(CodedBitstreamContext *ctx, + enum AVCodecID codec_id, void *log_ctx); + +/** + * Close a context and free all internal state. + */ +void ff_cbs_close(CodedBitstreamContext *ctx); + + +/** + * Read the extradata bitstream found in codec parameters into a + * fragment, then split into units and decompose. + * + * This also updates the internal state, so will need to be called for + * codecs with extradata to read parameter sets necessary for further + * parsing even if the fragment itself is not desired. + */ +int ff_cbs_read_extradata(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const AVCodecParameters *par); + +/** + * Read the data bitstream from a packet into a fragment, then + * split into units and decompose. + */ +int ff_cbs_read_packet(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const AVPacket *pkt); + +/** + * Read a bitstream from a memory region into a fragment, then + * split into units and decompose. + */ +int ff_cbs_read(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const uint8_t *data, size_t size); + + +/** + * Write the content of the fragment to its own internal buffer. + * + * Writes the content of all units and then assembles them into a new + * data buffer. When modifying the content of decomposed units, this + * can be used to regenerate the bitstream form of units or the whole + * fragment so that it can be extracted for other use. + */ +int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag); + +/** + * Write the bitstream of a fragment to the extradata in codec parameters. + */ +int ff_cbs_write_extradata(CodedBitstreamContext *ctx, + AVCodecParameters *par, + CodedBitstreamFragment *frag); + +/** + * Write the bitstream of a fragment to a packet. + */ +int ff_cbs_write_packet(CodedBitstreamContext *ctx, + AVPacket *pkt, + CodedBitstreamFragment *frag); + + +/** + * Free all allocated memory in a fragment. + */ +void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag); + + +/** + * Insert a new unit into a fragment with the given content. + * + * The content structure continues to be owned by the caller, and + * will not be freed when the unit is. + */ +int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position, uint32_t type, + void *content); + +/** + * Insert a new unit into a fragment with the given data bitstream. + * + * The data buffer will be owned by the unit after this operation. + */ +int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position, uint32_t type, + uint8_t *data, size_t data_size); + +/** + * Delete a unit from a fragment and free all memory it uses. + */ +int ff_cbs_delete_unit(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position); + + +#endif /* AVCODEC_CBS_H */ diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h new file mode 100644 index 0000000000000..a691790b705e4 --- /dev/null +++ b/libavcodec/cbs_internal.h @@ -0,0 +1,83 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_INTERNAL_H +#define AVCODEC_CBS_INTERNAL_H + +#include "avcodec.h" +#include "bitstream.h" +#include "cbs.h" +#include "put_bits.h" + + +typedef struct CodedBitstreamType { + enum AVCodecID codec_id; + + size_t priv_data_size; + + // Split frag->data into coded bitstream units, creating the + // frag->units array. Fill data but not content on each unit. + int (*split_fragment)(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int header); + + // Read the unit->data bitstream and decompose it, creating + // unit->content. + int (*read_unit)(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit); + + // Write the unit->data bitstream from unit->content. + int (*write_unit)(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit); + + // Read the data from all of frag->units and assemble it into + // a bitstream for the whole fragment. + int (*assemble_fragment)(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag); + + // Free the content and data of a single unit. + void (*free_unit)(CodedBitstreamUnit *unit); + + // Free the codec internal state. + void (*close)(CodedBitstreamContext *ctx); +} CodedBitstreamType; + + +// Helper functions for trace output. + +void ff_cbs_trace_header(CodedBitstreamContext *ctx, + const char *name); + +void ff_cbs_trace_syntax_element(CodedBitstreamContext *ctx, + int position, const char *name, + const char *bitstring, int64_t value); + + +// Helper functions for read/write of common bitstream elements, including +// generation of trace output. + +int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, BitstreamContext *bc, + int width, const char *name, uint32_t *write_to, + uint32_t range_min, uint32_t range_max); + +int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc, + int width, const char *name, uint32_t value, + uint32_t range_min, uint32_t range_max); + + +#endif /* AVCODEC_CBS_INTERNAL_H */ From acf06f45441be24c5cbae0920579cd69427326a1 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 14 May 2017 16:18:25 +0100 Subject: [PATCH 0349/2557] lavc: Add coded bitstream read/write support for H.264 --- configure | 2 + libavcodec/Makefile | 1 + libavcodec/cbs.c | 3 + libavcodec/cbs_h264.h | 427 +++++++++ libavcodec/cbs_h2645.c | 997 ++++++++++++++++++++ libavcodec/cbs_h2645.h | 43 + libavcodec/cbs_h264_syntax_template.c | 1230 +++++++++++++++++++++++++ libavcodec/cbs_internal.h | 3 + 8 files changed, 2706 insertions(+) create mode 100644 libavcodec/cbs_h264.h create mode 100644 libavcodec/cbs_h2645.c create mode 100644 libavcodec/cbs_h2645.h create mode 100644 libavcodec/cbs_h264_syntax_template.c diff --git a/configure b/configure index befaed1e58a61..54af2e0cb560a 100755 --- a/configure +++ b/configure @@ -1740,6 +1740,7 @@ CONFIG_EXTRA=" bswapdsp cabac cbs + cbs_h264 dirac_parse dvprofile faandct @@ -1966,6 +1967,7 @@ w32threads_deps="atomics_native" threads_if_any="$THREADS_LIST" # subsystems +cbs_h264_select="cbs golomb" dct_select="rdft" dirac_parse_select="golomb" error_resilience_select="me_cmp" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 41da3ca7ba2f1..30fc388f8c2c7 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -54,6 +54,7 @@ OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o OBJS-$(CONFIG_CABAC) += cabac.o OBJS-$(CONFIG_CBS) += cbs.o +OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o h2645_parse.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o OBJS-$(CONFIG_FAANDCT) += faandct.o diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index 3a205c393d92f..9352b535b2512 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -28,6 +28,9 @@ static const CodedBitstreamType *cbs_type_table[] = { +#if CONFIG_CBS_H264 + &ff_cbs_type_h264, +#endif }; int ff_cbs_init(CodedBitstreamContext *ctx, diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h new file mode 100644 index 0000000000000..b58f19f17ea52 --- /dev/null +++ b/libavcodec/cbs_h264.h @@ -0,0 +1,427 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_H264_H +#define AVCODEC_CBS_H264_H + +#include +#include + +#include "cbs_h2645.h" +#include "h264.h" + + +enum { + // This limit is arbitrary - it is sufficient for one message of each + // type plus some repeats, and will therefore easily cover all sane + // streams. However, it is possible to make technically-valid streams + // for which it will fail (for example, by including a large number of + // user-data-unregistered messages). + H264_MAX_SEI_PAYLOADS = 64, +}; + + +typedef struct H264RawNALUnitHeader { + uint8_t forbidden_zero_bit; + uint8_t nal_ref_idc; + uint8_t nal_unit_type; + + uint8_t svc_extension_flag; + uint8_t avc_3d_extension_flag; +} H264RawNALUnitHeader; + +typedef struct H264RawScalingList { + int8_t delta_scale[64]; +} H264RawScalingList; + +typedef struct H264RawHRD { + uint8_t cpb_cnt_minus1; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + + uint32_t bit_rate_value_minus1[H264_MAX_CPB_CNT]; + uint32_t cpb_size_value_minus1[H264_MAX_CPB_CNT]; + uint8_t cbr_flag[H264_MAX_CPB_CNT]; + + uint8_t initial_cpb_removal_delay_length_minus1; + uint8_t cpb_removal_delay_length_minus1; + uint8_t dpb_output_delay_length_minus1; + uint8_t time_offset_length; +} H264RawHRD; + +typedef struct H264RawVUI { + uint8_t aspect_ratio_info_present_flag; + uint8_t aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + + uint8_t overscan_info_present_flag; + uint8_t overscan_appropriate_flag; + + uint8_t video_signal_type_present_flag; + uint8_t video_format; + uint8_t video_full_range_flag; + uint8_t colour_description_present_flag; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; + + uint8_t chroma_loc_info_present_flag; + uint8_t chroma_sample_loc_type_top_field; + uint8_t chroma_sample_loc_type_bottom_field; + + uint8_t timing_info_present_flag; + uint32_t num_units_in_tick; + uint32_t time_scale; + uint8_t fixed_frame_rate_flag; + + uint8_t nal_hrd_parameters_present_flag; + H264RawHRD nal_hrd_parameters; + uint8_t vcl_hrd_parameters_present_flag; + H264RawHRD vcl_hrd_parameters; + uint8_t low_delay_hrd_flag; + + uint8_t pic_struct_present_flag; + + uint8_t bitstream_restriction_flag; + uint8_t motion_vectors_over_pic_boundaries_flag; + uint8_t max_bytes_per_pic_denom; + uint8_t max_bits_per_mb_denom; + uint8_t log2_max_mv_length_horizontal; + uint8_t log2_max_mv_length_vertical; + uint8_t max_num_reorder_frames; + uint8_t max_dec_frame_buffering; +} H264RawVUI; + +typedef struct H264RawSPS { + H264RawNALUnitHeader nal_unit_header; + + uint8_t profile_idc; + uint8_t constraint_set0_flag; + uint8_t constraint_set1_flag; + uint8_t constraint_set2_flag; + uint8_t constraint_set3_flag; + uint8_t constraint_set4_flag; + uint8_t constraint_set5_flag; + uint8_t reserved_zero_2bits; + uint8_t level_idc; + + uint8_t seq_parameter_set_id; + + uint8_t chroma_format_idc; + uint8_t separate_colour_plane_flag; + uint8_t bit_depth_luma_minus8; + uint8_t bit_depth_chroma_minus8; + uint8_t qpprime_y_zero_transform_bypass_flag; + + uint8_t seq_scaling_matrix_present_flag; + uint8_t seq_scaling_list_present_flag[12]; + H264RawScalingList scaling_list_4x4[6]; + H264RawScalingList scaling_list_8x8[6]; + + uint8_t log2_max_frame_num_minus4; + uint8_t pic_order_cnt_type; + uint8_t log2_max_pic_order_cnt_lsb_minus4; + uint8_t delta_pic_order_always_zero_flag; + int32_t offset_for_non_ref_pic; + int32_t offset_for_top_to_bottom_field; + uint8_t num_ref_frames_in_pic_order_cnt_cycle; + int32_t offset_for_ref_frame[256]; + + uint8_t max_num_ref_frames; + uint8_t gaps_in_frame_num_allowed_flag; + + uint16_t pic_width_in_mbs_minus1; + uint16_t pic_height_in_map_units_minus1; + + uint8_t frame_mbs_only_flag; + uint8_t mb_adaptive_frame_field_flag; + uint8_t direct_8x8_inference_flag; + + uint8_t frame_cropping_flag; + uint16_t frame_crop_left_offset; + uint16_t frame_crop_right_offset; + uint16_t frame_crop_top_offset; + uint16_t frame_crop_bottom_offset; + + uint8_t vui_parameters_present_flag; + H264RawVUI vui; +} H264RawSPS; + +typedef struct H264RawSPSExtension { + H264RawNALUnitHeader nal_unit_header; + + uint8_t seq_parameter_set_id; + + uint8_t aux_format_idc; + uint8_t bit_depth_aux_minus8; + uint8_t alpha_incr_flag; + uint16_t alpha_opaque_value; + uint16_t alpha_transparent_value; + + uint8_t additional_extension_flag; +} H264RawSPSExtension; + +typedef struct H264RawPPS { + H264RawNALUnitHeader nal_unit_header; + + uint8_t pic_parameter_set_id; + uint8_t seq_parameter_set_id; + + uint8_t entropy_coding_mode_flag; + uint8_t bottom_field_pic_order_in_frame_present_flag; + + uint8_t num_slice_groups_minus1; + uint8_t slice_group_map_type; + uint16_t run_length_minus1[H264_MAX_SLICE_GROUPS]; + uint16_t top_left[H264_MAX_SLICE_GROUPS]; + uint16_t bottom_right[H264_MAX_SLICE_GROUPS]; + uint8_t slice_group_change_direction_flag; + uint16_t slice_group_change_rate_minus1; + uint16_t pic_size_in_map_units_minus1; + uint8_t slice_group_id[H264_MAX_MB_PIC_SIZE]; + + uint8_t num_ref_idx_l0_default_active_minus1; + uint8_t num_ref_idx_l1_default_active_minus1; + + uint8_t weighted_pred_flag; + uint8_t weighted_bipred_idc; + + int8_t pic_init_qp_minus26; + int8_t pic_init_qs_minus26; + int8_t chroma_qp_index_offset; + + uint8_t deblocking_filter_control_present_flag; + uint8_t constrained_intra_pred_flag; + + uint8_t more_rbsp_data; + + uint8_t redundant_pic_cnt_present_flag; + uint8_t transform_8x8_mode_flag; + + uint8_t pic_scaling_matrix_present_flag; + uint8_t pic_scaling_list_present_flag[12]; + H264RawScalingList scaling_list_4x4[6]; + H264RawScalingList scaling_list_8x8[6]; + + int8_t second_chroma_qp_index_offset; +} H264RawPPS; + +typedef struct H264RawAUD { + H264RawNALUnitHeader nal_unit_header; + + uint8_t primary_pic_type; +} H264RawAUD; + +typedef struct H264RawSEIBufferingPeriod { + uint8_t seq_parameter_set_id; + struct { + uint32_t initial_cpb_removal_delay[H264_MAX_CPB_CNT]; + uint32_t initial_cpb_removal_delay_offset[H264_MAX_CPB_CNT]; + } nal, vcl; +} H264RawSEIBufferingPeriod; + +typedef struct H264RawSEIPicTimestamp { + uint8_t ct_type; + uint8_t nuit_field_based_flag; + uint8_t counting_type; + uint8_t full_timestamp_flag; + uint8_t discontinuity_flag; + uint8_t cnt_dropped_flag; + uint8_t n_frames; + uint8_t seconds_flag; + uint8_t seconds_value; + uint8_t minutes_flag; + uint8_t minutes_value; + uint8_t hours_flag; + uint8_t hours_value; + uint32_t time_offset; +} H264RawSEIPicTimestamp; + +typedef struct H264RawSEIPicTiming { + uint32_t cpb_removal_delay; + uint32_t dpb_output_delay; + uint8_t pic_struct; + uint8_t clock_timestamp_flag[3]; + H264RawSEIPicTimestamp timestamp[3]; +} H264RawSEIPicTiming; + +typedef struct H264RawSEIUserDataRegistered { + uint8_t itu_t_t35_country_code; + uint8_t itu_t_t35_country_code_extension_byte; + uint8_t *data; + size_t data_length; +} H264RawSEIUserDataRegistered; + +typedef struct H264RawSEIUserDataUnregistered { + uint8_t uuid_iso_iec_11578[16]; + uint8_t *data; + size_t data_length; +} H264RawSEIUserDataUnregistered; + +typedef struct H264RawSEIRecoveryPoint { + uint16_t recovery_frame_cnt; + uint8_t exact_match_flag; + uint8_t broken_link_flag; + uint8_t changing_slice_group_idc; +} H264RawSEIRecoveryPoint; + +typedef struct H264RawSEIDisplayOrientation { + uint8_t display_orientation_cancel_flag; + uint8_t hor_flip; + uint8_t ver_flip; + uint16_t anticlockwise_rotation; + uint16_t display_orientation_repetition_period; + uint8_t display_orientation_extension_flag; +} H264RawSEIDisplayOrientation; + +typedef struct H264RawSEIPayload { + uint32_t payload_type; + uint32_t payload_size; + union { + H264RawSEIBufferingPeriod buffering_period; + H264RawSEIPicTiming pic_timing; + // H264RawSEIFiller filler -> no fields. + H264RawSEIUserDataRegistered user_data_registered; + H264RawSEIUserDataUnregistered user_data_unregistered; + H264RawSEIRecoveryPoint recovery_point; + H264RawSEIDisplayOrientation display_orientation; + struct { + uint8_t *data; + size_t data_length; + } other; + } payload; +} H264RawSEIPayload; + +typedef struct H264RawSEI { + H264RawNALUnitHeader nal_unit_header; + + H264RawSEIPayload payload[H264_MAX_SEI_PAYLOADS]; + uint8_t payload_count; +} H264RawSEI; + +typedef struct H264RawSliceHeader { + H264RawNALUnitHeader nal_unit_header; + + uint32_t first_mb_in_slice; + uint8_t slice_type; + + uint8_t pic_parameter_set_id; + + uint8_t colour_plane_id; + + uint16_t frame_num; + uint8_t field_pic_flag; + uint8_t bottom_field_flag; + + uint16_t idr_pic_id; + + uint16_t pic_order_cnt_lsb; + int32_t delta_pic_order_cnt_bottom; + int32_t delta_pic_order_cnt[2]; + + uint8_t redundant_pic_cnt; + uint8_t direct_spatial_mv_pred_flag; + + uint8_t num_ref_idx_active_override_flag; + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; + + uint8_t ref_pic_list_modification_flag_l0; + uint8_t ref_pic_list_modification_flag_l1; + struct { + uint8_t modification_of_pic_nums_idc; + int32_t abs_diff_pic_num_minus1; + uint8_t long_term_pic_num; + } rplm_l0[H264_MAX_RPLM_COUNT], rplm_l1[H264_MAX_RPLM_COUNT]; + + uint8_t luma_log2_weight_denom; + uint8_t chroma_log2_weight_denom; + + uint8_t luma_weight_l0_flag[H264_MAX_REFS]; + int8_t luma_weight_l0[H264_MAX_REFS]; + int8_t luma_offset_l0[H264_MAX_REFS]; + uint8_t chroma_weight_l0_flag[H264_MAX_REFS]; + int8_t chroma_weight_l0[H264_MAX_REFS][2]; + int8_t chroma_offset_l0[H264_MAX_REFS][2]; + + uint8_t luma_weight_l1_flag[H264_MAX_REFS]; + int8_t luma_weight_l1[H264_MAX_REFS]; + int8_t luma_offset_l1[H264_MAX_REFS]; + uint8_t chroma_weight_l1_flag[H264_MAX_REFS]; + int8_t chroma_weight_l1[H264_MAX_REFS][2]; + int8_t chroma_offset_l1[H264_MAX_REFS][2]; + + uint8_t no_output_of_prior_pics_flag; + uint8_t long_term_reference_flag; + + uint8_t adaptive_ref_pic_marking_mode_flag; + struct { + uint8_t memory_management_control_operation; + int32_t difference_of_pic_nums_minus1; + uint8_t long_term_pic_num; + uint8_t long_term_frame_idx; + uint8_t max_long_term_frame_idx_plus1; + } mmco[H264_MAX_MMCO_COUNT]; + + uint8_t cabac_init_idc; + + int8_t slice_qp_delta; + + uint8_t sp_for_switch_flag; + int8_t slice_qs_delta; + + uint8_t disable_deblocking_filter_idc; + int8_t slice_alpha_c0_offset_div2; + int8_t slice_beta_offset_div2; + + uint16_t slice_group_change_cycle; +} H264RawSliceHeader; + +typedef struct H264RawSlice { + H264RawSliceHeader header; + + uint8_t *data; + size_t data_size; + int data_bit_start; +} H264RawSlice; + + +typedef struct CodedBitstreamH264Context { + // Reader/writer context in common with the H.265 implementation. + CodedBitstreamH2645Context common; + + // All currently available parameter sets. These are updated when + // any parameter set NAL unit is read/written with this context. + H264RawSPS *sps[H264_MAX_SPS_COUNT]; + H264RawPPS *pps[H264_MAX_PPS_COUNT]; + + // The currently active parameter sets. These are updated when any + // NAL unit refers to the relevant parameter set. These pointers + // must also be present in the arrays above. + const H264RawSPS *active_sps; + const H264RawPPS *active_pps; + + // The NAL unit type of the most recent normal slice. This is required + // to be able to read/write auxiliary slices, because IdrPicFlag is + // otherwise unknown. + uint8_t last_slice_nal_unit_type; +} CodedBitstreamH264Context; + + +#endif /* AVCODEC_CBS_H264_H */ diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c new file mode 100644 index 0000000000000..2350f039fa3bf --- /dev/null +++ b/libavcodec/cbs_h2645.c @@ -0,0 +1,997 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/avassert.h" + +#include "bytestream.h" +#include "cbs.h" +#include "cbs_internal.h" +#include "cbs_h264.h" +#include "golomb.h" +#include "h264.h" +#include "h264_sei.h" +#include "h2645_parse.h" + + +static int cbs_read_ue_golomb(CodedBitstreamContext *ctx, BitstreamContext *bc, + const char *name, uint32_t *write_to, + uint32_t range_min, uint32_t range_max) +{ + uint32_t value; + int position; + + if (ctx->trace_enable) { + char bits[65]; + unsigned int k; + int i, j; + + position = bitstream_tell(bc); + + for (i = 0; i < 32; i++) { + k = bitstream_read_bit(bc); + bits[i] = k ? '1' : '0'; + if (k) + break; + } + if (i >= 32) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid ue-golomb " + "code found while reading %s: " + "more than 31 zeroes.\n", name); + return AVERROR_INVALIDDATA; + } + value = 1; + for (j = 0; j < i; j++) { + k = bitstream_read_bit(bc); + bits[i + j + 1] = k ? '1' : '0'; + value = value << 1 | k; + } + bits[i + j + 1] = 0; + --value; + + ff_cbs_trace_syntax_element(ctx, position, name, bits, value); + } else { + value = get_ue_golomb_long(bc); + } + + if (value < range_min || value > range_max) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " + "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n", + name, value, range_min, range_max); + return AVERROR_INVALIDDATA; + } + + *write_to = value; + return 0; +} + +static int cbs_read_se_golomb(CodedBitstreamContext *ctx, BitstreamContext *bc, + const char *name, int32_t *write_to, + int32_t range_min, int32_t range_max) +{ + int32_t value; + int position; + + if (ctx->trace_enable) { + char bits[65]; + uint32_t v; + unsigned int k; + int i, j; + + position = bitstream_tell(bc); + + for (i = 0; i < 32; i++) { + k = bitstream_read_bit(bc); + bits[i] = k ? '1' : '0'; + if (k) + break; + } + if (i >= 32) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid se-golomb " + "code found while reading %s: " + "more than 31 zeroes.\n", name); + return AVERROR_INVALIDDATA; + } + v = 1; + for (j = 0; j < i; j++) { + k = bitstream_read_bit(bc); + bits[i + j + 1] = k ? '1' : '0'; + v = v << 1 | k; + } + bits[i + j + 1] = 0; + if (v & 1) + value = -(int32_t)(v / 2); + else + value = v / 2; + + ff_cbs_trace_syntax_element(ctx, position, name, bits, value); + } else { + value = get_se_golomb_long(bc); + } + + if (value < range_min || value > range_max) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " + "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n", + name, value, range_min, range_max); + return AVERROR_INVALIDDATA; + } + + *write_to = value; + return 0; +} + +static int cbs_write_ue_golomb(CodedBitstreamContext *ctx, PutBitContext *pbc, + const char *name, uint32_t value, + uint32_t range_min, uint32_t range_max) +{ + int len; + + if (value < range_min || value > range_max) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " + "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n", + name, value, range_min, range_max); + return AVERROR_INVALIDDATA; + } + av_assert0(value != UINT32_MAX); + + len = av_log2(value + 1); + if (put_bits_left(pbc) < 2 * len + 1) + return AVERROR(ENOSPC); + + if (ctx->trace_enable) { + char bits[65]; + int i; + + for (i = 0; i < len; i++) + bits[i] = '0'; + bits[len] = '1'; + for (i = 0; i < len; i++) + bits[len + i + 1] = (value + 1) >> (len - i - 1) & 1 ? '1' : '0'; + bits[len + len + 1] = 0; + + ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), name, bits, value); + } + + put_bits(pbc, len, 0); + if (len + 1 < 32) + put_bits(pbc, len + 1, value + 1); + else + put_bits32(pbc, value + 1); + + return 0; +} + +static int cbs_write_se_golomb(CodedBitstreamContext *ctx, PutBitContext *pbc, + const char *name, int32_t value, + int32_t range_min, int32_t range_max) +{ + int len; + uint32_t uvalue; + + if (value < range_min || value > range_max) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " + "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n", + name, value, range_min, range_max); + return AVERROR_INVALIDDATA; + } + av_assert0(value != INT32_MIN); + + if (value == 0) + uvalue = 0; + else if (value > 0) + uvalue = 2 * (uint32_t)value - 1; + else + uvalue = 2 * (uint32_t)-value; + + len = av_log2(uvalue + 1); + if (put_bits_left(pbc) < 2 * len + 1) + return AVERROR(ENOSPC); + + if (ctx->trace_enable) { + char bits[65]; + int i; + + for (i = 0; i < len; i++) + bits[i] = '0'; + bits[len] = '1'; + for (i = 0; i < len; i++) + bits[len + i + 1] = (uvalue + 1) >> (len - i - 1) & 1 ? '1' : '0'; + bits[len + len + 1] = 0; + + ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), name, bits, value); + } + + put_bits(pbc, len, 0); + if (len + 1 < 32) + put_bits(pbc, len + 1, uvalue + 1); + else + put_bits32(pbc, uvalue + 1); + + return 0; +} + +#define HEADER(name) do { \ + ff_cbs_trace_header(ctx, name); \ + } while (0) + +#define CHECK(call) do { \ + err = (call); \ + if (err < 0) \ + return err; \ + } while (0) + +#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name +#define FUNC_H264(rw, name) FUNC_NAME(rw, h264, name) + + +#define READ +#define READWRITE read +#define RWContext BitstreamContext + +#define xu(width, name, var, range_min, range_max) do { \ + uint32_t value = range_min; \ + CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \ + &value, range_min, range_max)); \ + var = value; \ + } while (0) +#define xue(name, var, range_min, range_max) do { \ + uint32_t value = range_min; \ + CHECK(cbs_read_ue_golomb(ctx, rw, #name, \ + &value, range_min, range_max)); \ + var = value; \ + } while (0) +#define xse(name, var, range_min, range_max) do { \ + int32_t value = range_min; \ + CHECK(cbs_read_se_golomb(ctx, rw, #name, \ + &value, range_min, range_max)); \ + var = value; \ + } while (0) + + +#define u(width, name, range_min, range_max) \ + xu(width, name, current->name, range_min, range_max) +#define flag(name) u(1, name, 0, 1) +#define ue(name, range_min, range_max) \ + xue(name, current->name, range_min, range_max) +#define se(name, range_min, range_max) \ + xse(name, current->name, range_min, range_max) + +#define infer(name, value) do { \ + current->name = value; \ + } while (0) + +static int cbs_h2645_read_more_rbsp_data(BitstreamContext *bc) +{ + int bits_left = bitstream_bits_left(bc); + if (bits_left > 8) + return 1; + if (bitstream_peek(bc, bits_left) == 1 << (bits_left - 1)) + return 0; + return 1; +} + +#define more_rbsp_data(var) ((var) = cbs_h2645_read_more_rbsp_data(rw)) + +#define byte_alignment(rw) (bitstream_tell(rw) % 8) + +#define allocate(name, size) do { \ + name = av_mallocz(size); \ + if (!name) \ + return AVERROR(ENOMEM); \ + } while (0) + +#define FUNC(name) FUNC_H264(READWRITE, name) +#include "cbs_h264_syntax_template.c" +#undef FUNC + +#undef READ +#undef READWRITE +#undef RWContext +#undef xu +#undef xue +#undef xse +#undef u +#undef flag +#undef ue +#undef se +#undef infer +#undef more_rbsp_data +#undef byte_alignment +#undef allocate + + +#define WRITE +#define READWRITE write +#define RWContext PutBitContext + +#define xu(width, name, var, range_min, range_max) do { \ + uint32_t value = var; \ + CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \ + value, range_min, range_max)); \ + } while (0) +#define xue(name, var, range_min, range_max) do { \ + uint32_t value = var; \ + CHECK(cbs_write_ue_golomb(ctx, rw, #name, \ + value, range_min, range_max)); \ + } while (0) +#define xse(name, var, range_min, range_max) do { \ + int32_t value = var; \ + CHECK(cbs_write_se_golomb(ctx, rw, #name, \ + value, range_min, range_max)); \ + } while (0) + +#define u(width, name, range_min, range_max) \ + xu(width, name, current->name, range_min, range_max) +#define flag(name) u(1, name, 0, 1) +#define ue(name, range_min, range_max) \ + xue(name, current->name, range_min, range_max) +#define se(name, range_min, range_max) \ + xse(name, current->name, range_min, range_max) + +#define infer(name, value) do { \ + if (current->name != (value)) { \ + av_log(ctx->log_ctx, AV_LOG_WARNING, "Warning: " \ + "%s does not match inferred value: " \ + "%"PRId64", but should be %"PRId64".\n", \ + #name, (int64_t)current->name, (int64_t)(value)); \ + } \ + } while (0) + +#define more_rbsp_data(var) (var) + +#define byte_alignment(rw) (put_bits_count(rw) % 8) + +#define allocate(name, size) do { \ + if (!name) { \ + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s must be set " \ + "for writing.\n", #name); \ + return AVERROR_INVALIDDATA; \ + } \ + } while (0) + +#define FUNC(name) FUNC_H264(READWRITE, name) +#include "cbs_h264_syntax_template.c" +#undef FUNC + +#undef WRITE +#undef READWRITE +#undef RWContext +#undef xu +#undef xue +#undef xse +#undef u +#undef flag +#undef ue +#undef se +#undef infer +#undef more_rbsp_data +#undef byte_alignment +#undef allocate + + +static void cbs_h264_free_sei(H264RawSEI *sei) +{ + int i; + for (i = 0; i < sei->payload_count; i++) { + H264RawSEIPayload *payload = &sei->payload[i]; + + switch (payload->payload_type) { + case H264_SEI_TYPE_BUFFERING_PERIOD: + case H264_SEI_TYPE_PIC_TIMING: + case H264_SEI_TYPE_RECOVERY_POINT: + case H264_SEI_TYPE_DISPLAY_ORIENTATION: + break; + case H264_SEI_TYPE_USER_DATA_REGISTERED: + av_freep(&payload->payload.user_data_registered.data); + break; + case H264_SEI_TYPE_USER_DATA_UNREGISTERED: + av_freep(&payload->payload.user_data_unregistered.data); + break; + default: + av_freep(&payload->payload.other.data); + break; + } + } +} + +static void cbs_h264_free_slice(H264RawSlice *slice) +{ + av_freep(&slice->data); +} + +static void cbs_h264_free_nal_unit(CodedBitstreamUnit *unit) +{ + switch (unit->type) { + case H264_NAL_SEI: + cbs_h264_free_sei(unit->content); + break; + case H264_NAL_IDR_SLICE: + case H264_NAL_SLICE: + cbs_h264_free_slice(unit->content); + break; + } + av_freep(&unit->content); +} + +static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const H2645Packet *packet) +{ + int err, i; + + for (i = 0; i < packet->nb_nals; i++) { + const H2645NAL *nal = &packet->nals[i]; + uint8_t *data; + + data = av_malloc(nal->size); + if (!data) + return AVERROR(ENOMEM); + memcpy(data, nal->data, nal->size); + + err = ff_cbs_insert_unit_data(ctx, frag, -1, nal->type, + data, nal->size); + if (err < 0) { + av_freep(&data); + return err; + } + } + + return 0; +} + +static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int header) +{ + enum AVCodecID codec_id = ctx->codec->codec_id; + CodedBitstreamH2645Context *priv = ctx->priv_data; + GetByteContext gbc; + int err; + + av_assert0(frag->data && frag->nb_units == 0); + if (frag->data_size == 0) + return 0; + + if (header && frag->data[0] && codec_id == AV_CODEC_ID_H264) { + // AVCC header. + size_t size, start, end; + int i, count, version; + + priv->mp4 = 1; + + bytestream2_init(&gbc, frag->data, frag->data_size); + + if (bytestream2_get_bytes_left(&gbc) < 6) + return AVERROR_INVALIDDATA; + + version = bytestream2_get_byte(&gbc); + if (version != 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid AVCC header: " + "first byte %u.", version); + return AVERROR_INVALIDDATA; + } + + bytestream2_skip(&gbc, 3); + priv->nal_length_size = (bytestream2_get_byte(&gbc) & 3) + 1; + + // SPS array. + count = bytestream2_get_byte(&gbc) & 0x1f; + start = bytestream2_tell(&gbc); + for (i = 0; i < count; i++) { + if (bytestream2_get_bytes_left(&gbc) < 2 * (count - i)) + return AVERROR_INVALIDDATA; + size = bytestream2_get_be16(&gbc); + if (bytestream2_get_bytes_left(&gbc) < size) + return AVERROR_INVALIDDATA; + bytestream2_skip(&gbc, size); + } + end = bytestream2_tell(&gbc); + + err = ff_h2645_packet_split(&priv->read_packet, + frag->data + start, end - start, + ctx->log_ctx, 1, 2, AV_CODEC_ID_H264); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split AVCC SPS array.\n"); + return err; + } + err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet); + if (err < 0) + return err; + + // PPS array. + count = bytestream2_get_byte(&gbc); + start = bytestream2_tell(&gbc); + for (i = 0; i < count; i++) { + if (bytestream2_get_bytes_left(&gbc) < 2 * (count - i)) + return AVERROR_INVALIDDATA; + size = bytestream2_get_be16(&gbc); + if (bytestream2_get_bytes_left(&gbc) < size) + return AVERROR_INVALIDDATA; + bytestream2_skip(&gbc, size); + } + end = bytestream2_tell(&gbc); + + err = ff_h2645_packet_split(&priv->read_packet, + frag->data + start, end - start, + ctx->log_ctx, 1, 2, AV_CODEC_ID_H264); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split AVCC PPS array.\n"); + return err; + } + err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet); + if (err < 0) + return err; + + if (bytestream2_get_bytes_left(&gbc) > 0) { + av_log(ctx->log_ctx, AV_LOG_WARNING, "%u bytes left at end of AVCC " + "header.\n", bytestream2_get_bytes_left(&gbc)); + } + + } else { + // Annex B, or later MP4 with already-known parameters. + + err = ff_h2645_packet_split(&priv->read_packet, + frag->data, frag->data_size, + ctx->log_ctx, + priv->mp4, priv->nal_length_size, + codec_id); + if (err < 0) + return err; + + err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet); + if (err < 0) + return err; + } + + return 0; +} + +#define cbs_h2645_replace_ps(h26n, ps_name, ps_var, id_element) \ +static int cbs_h26 ## h26n ## _replace_ ## ps_var(CodedBitstreamContext *ctx, \ + const H26 ## h26n ## Raw ## ps_name *ps_var) \ +{ \ + CodedBitstreamH26 ## h26n ## Context *priv = ctx->priv_data; \ + unsigned int id = ps_var->id_element; \ + if (id > FF_ARRAY_ELEMS(priv->ps_var)) { \ + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid " #ps_name \ + " id : %d.\n", id); \ + return AVERROR_INVALIDDATA; \ + } \ + av_freep(&priv->ps_var[id]); \ + priv->ps_var[id] = av_malloc(sizeof(*ps_var)); \ + if (!priv->ps_var[id]) \ + return AVERROR(ENOMEM); \ + memcpy(priv->ps_var[id], ps_var, sizeof(*ps_var)); \ + return 0; \ +} + +cbs_h2645_replace_ps(4, SPS, sps, seq_parameter_set_id) +cbs_h2645_replace_ps(4, PPS, pps, pic_parameter_set_id) + +static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + BitstreamContext bc; + int err; + + err = bitstream_init(&bc, unit->data, 8 * unit->data_size); + if (err < 0) + return err; + + switch (unit->type) { + case H264_NAL_SPS: + { + H264RawSPS *sps; + + sps = av_mallocz(sizeof(*sps)); + if (!sps) + return AVERROR(ENOMEM); + err = cbs_h264_read_sps(ctx, &bc, sps); + if (err >= 0) + err = cbs_h264_replace_sps(ctx, sps); + if (err < 0) { + av_free(sps); + return err; + } + + unit->content = sps; + } + break; + + case H264_NAL_SPS_EXT: + { + H264RawSPSExtension *sps_ext; + + sps_ext = av_mallocz(sizeof(*sps_ext)); + if (!sps_ext) + return AVERROR(ENOMEM); + err = cbs_h264_read_sps_extension(ctx, &bc, sps_ext); + if (err < 0) { + av_free(sps_ext); + return err; + } + + unit->content = sps_ext; + } + break; + + case H264_NAL_PPS: + { + H264RawPPS *pps; + + pps = av_mallocz(sizeof(*pps)); + if (!pps) + return AVERROR(ENOMEM); + err = cbs_h264_read_pps(ctx, &bc, pps); + if (err >= 0) + err = cbs_h264_replace_pps(ctx, pps); + if (err < 0) { + av_free(pps); + return err; + } + + unit->content = pps; + } + break; + + case H264_NAL_SLICE: + case H264_NAL_IDR_SLICE: + case H264_NAL_AUXILIARY_SLICE: + { + H264RawSlice *slice; + int pos, len; + + slice = av_mallocz(sizeof(*slice)); + if (!slice) + return AVERROR(ENOMEM); + err = cbs_h264_read_slice_header(ctx, &bc, &slice->header); + if (err < 0) { + av_free(slice); + return err; + } + + pos = bitstream_tell(&bc); + len = unit->data_size; + if (!unit->data[len - 1]) { + int z; + for (z = 0; z < len && !unit->data[len - z - 1]; z++); + av_log(ctx->log_ctx, AV_LOG_DEBUG, "Deleted %d trailing zeroes " + "from slice data.\n", z); + len -= z; + } + + slice->data_size = len - pos / 8; + slice->data = av_malloc(slice->data_size); + if (!slice->data) { + av_free(slice); + return AVERROR(ENOMEM); + } + memcpy(slice->data, + unit->data + pos / 8, slice->data_size); + slice->data_bit_start = pos % 8; + + unit->content = slice; + } + break; + + case H264_NAL_AUD: + { + H264RawAUD *aud; + + aud = av_mallocz(sizeof(*aud)); + if (!aud) + return AVERROR(ENOMEM); + err = cbs_h264_read_aud(ctx, &bc, aud); + if (err < 0) { + av_free(aud); + return err; + } + + unit->content = aud; + } + break; + + case H264_NAL_SEI: + { + H264RawSEI *sei; + + sei = av_mallocz(sizeof(*sei)); + if (!sei) + return AVERROR(ENOMEM); + err = cbs_h264_read_sei(ctx, &bc, sei); + if (err < 0) { + cbs_h264_free_sei(sei); + return err; + } + + unit->content = sei; + } + break; + + default: + return AVERROR(ENOSYS); + } + + return 0; +} + +static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + PutBitContext *pbc) +{ + int err; + + switch (unit->type) { + case H264_NAL_SPS: + { + H264RawSPS *sps = unit->content; + + err = cbs_h264_write_sps(ctx, pbc, sps); + if (err < 0) + return err; + + err = cbs_h264_replace_sps(ctx, sps); + if (err < 0) + return err; + } + break; + + case H264_NAL_SPS_EXT: + { + H264RawSPSExtension *sps_ext; + + err = cbs_h264_write_sps_extension(ctx, pbc, sps_ext); + if (err < 0) + return err; + } + break; + + case H264_NAL_PPS: + { + H264RawPPS *pps = unit->content; + + err = cbs_h264_write_pps(ctx, pbc, pps); + if (err < 0) + return err; + + err = cbs_h264_replace_pps(ctx, pps); + if (err < 0) + return err; + } + break; + + case H264_NAL_SLICE: + case H264_NAL_IDR_SLICE: + { + H264RawSlice *slice = unit->content; + BitstreamContext bc; + int bits_left, end, zeroes; + + err = cbs_h264_write_slice_header(ctx, pbc, &slice->header); + if (err < 0) + return err; + + if (slice->data) { + if (slice->data_size * 8 + 8 > put_bits_left(pbc)) + return AVERROR(ENOSPC); + + bitstream_init(&bc, slice->data, slice->data_size * 8); + bitstream_skip(&bc, slice->data_bit_start); + + // Copy in two-byte blocks, but stop before copying the + // rbsp_stop_one_bit in the final byte. + while (bitstream_bits_left(&bc) > 23) + put_bits(pbc, 16, bitstream_read(&bc, 16)); + + bits_left = bitstream_bits_left(&bc); + end = bitstream_read(&bc, bits_left); + + // rbsp_stop_one_bit must be present here. + av_assert0(end); + zeroes = ff_ctz(end); + if (bits_left > zeroes + 1) + put_bits(pbc, bits_left - zeroes - 1, + end >> (zeroes + 1)); + put_bits(pbc, 1, 1); + while (put_bits_count(pbc) % 8 != 0) + put_bits(pbc, 1, 0); + } else { + // No slice data - that was just the header. + // (Bitstream may be unaligned!) + } + } + break; + + case H264_NAL_AUD: + { + err = cbs_h264_write_aud(ctx, pbc, unit->content); + if (err < 0) + return err; + } + break; + + case H264_NAL_SEI: + { + err = cbs_h264_write_sei(ctx, pbc, unit->content); + if (err < 0) + return err; + } + break; + + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for " + "NAL unit type %"PRIu32".\n", unit->type); + return AVERROR_PATCHWELCOME; + } + + return 0; +} + +static int cbs_h2645_write_nal_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + CodedBitstreamH2645Context *priv = ctx->priv_data; + enum AVCodecID codec_id = ctx->codec->codec_id; + PutBitContext pbc; + int err; + + if (!priv->write_buffer) { + // Initial write buffer size is 1MB. + priv->write_buffer_size = 1024 * 1024; + + reallocate_and_try_again: + err = av_reallocp(&priv->write_buffer, priv->write_buffer_size); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a " + "sufficiently large write buffer (last attempt " + "%zu bytes).\n", priv->write_buffer_size); + return err; + } + } + + init_put_bits(&pbc, priv->write_buffer, priv->write_buffer_size); + + err = cbs_h264_write_nal_unit(ctx, unit, &pbc); + + if (err == AVERROR(ENOSPC)) { + // Overflow. + priv->write_buffer_size *= 2; + goto reallocate_and_try_again; + } + // Overflow but we didn't notice. + av_assert0(put_bits_count(&pbc) <= 8 * priv->write_buffer_size); + + if (put_bits_count(&pbc) % 8) + unit->data_bit_padding = 8 - put_bits_count(&pbc) % 8; + else + unit->data_bit_padding = 0; + + unit->data_size = (put_bits_count(&pbc) + 7) / 8; + flush_put_bits(&pbc); + + err = av_reallocp(&unit->data, unit->data_size); + if (err < 0) + return err; + + memcpy(unit->data, priv->write_buffer, unit->data_size); + + return 0; +} + +static int cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag) +{ + uint8_t *data; + size_t max_size, dp, sp; + int err, i, zero_run; + + for (i = 0; i < frag->nb_units; i++) { + // Data should already all have been written when we get here. + av_assert0(frag->units[i].data); + } + + max_size = 0; + for (i = 0; i < frag->nb_units; i++) { + // Start code + content with worst-case emulation prevention. + max_size += 3 + frag->units[i].data_size * 3 / 2; + } + + data = av_malloc(max_size); + if (!data) + return AVERROR(ENOMEM); + + dp = 0; + for (i = 0; i < frag->nb_units; i++) { + CodedBitstreamUnit *unit = &frag->units[i]; + + if (unit->data_bit_padding > 0) { + if (i < frag->nb_units - 1) + av_log(ctx->log_ctx, AV_LOG_WARNING, "Probably invalid " + "unaligned padding on non-final NAL unit.\n"); + else + frag->data_bit_padding = unit->data_bit_padding; + } + + if (unit->type == H264_NAL_SPS || + unit->type == H264_NAL_PPS || + i == 0 /* (Assume this is the start of an access unit.) */) { + // zero_byte + data[dp++] = 0; + } + // start_code_prefix_one_3bytes + data[dp++] = 0; + data[dp++] = 0; + data[dp++] = 1; + + zero_run = 0; + for (sp = 0; sp < unit->data_size; sp++) { + if (zero_run < 2) { + if (unit->data[sp] == 0) + ++zero_run; + else + zero_run = 0; + } else { + if ((unit->data[sp] & ~3) == 0) { + // emulation_prevention_three_byte + data[dp++] = 3; + } + zero_run = unit->data[sp] == 0; + } + data[dp++] = unit->data[sp]; + } + } + + av_assert0(dp <= max_size); + err = av_reallocp(&data, dp); + if (err) + return err; + + frag->data = data; + frag->data_size = dp; + + return 0; +} + +static void cbs_h264_close(CodedBitstreamContext *ctx) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + int i; + + ff_h2645_packet_uninit(&h264->common.read_packet); + + av_freep(&h264->common.write_buffer); + + for (i = 0; i < FF_ARRAY_ELEMS(h264->sps); i++) + av_freep(&h264->sps[i]); + for (i = 0; i < FF_ARRAY_ELEMS(h264->pps); i++) + av_freep(&h264->pps[i]); +} + +const CodedBitstreamType ff_cbs_type_h264 = { + .codec_id = AV_CODEC_ID_H264, + + .priv_data_size = sizeof(CodedBitstreamH264Context), + + .split_fragment = &cbs_h2645_split_fragment, + .read_unit = &cbs_h264_read_nal_unit, + .write_unit = &cbs_h2645_write_nal_unit, + .assemble_fragment = &cbs_h2645_assemble_fragment, + + .free_unit = &cbs_h264_free_nal_unit, + .close = &cbs_h264_close, +}; diff --git a/libavcodec/cbs_h2645.h b/libavcodec/cbs_h2645.h new file mode 100644 index 0000000000000..750247b6ade8b --- /dev/null +++ b/libavcodec/cbs_h2645.h @@ -0,0 +1,43 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_H2645_H +#define AVCODEC_CBS_H2645_H + +#include +#include + +#include "h2645_parse.h" + + +typedef struct CodedBitstreamH2645Context { + // If set, the stream being read is in MP4 (AVCC/HVCC) format. If not + // set, the stream is assumed to be in annex B format. + int mp4; + // Size in bytes of the NAL length field for MP4 format. + int nal_length_size; + // Packet reader. + H2645Packet read_packet; + + // Write buffer + uint8_t *write_buffer; + size_t write_buffer_size; +} CodedBitstreamH2645Context; + + +#endif /* AVCODEC_CBS_H2645_H */ diff --git a/libavcodec/cbs_h264_syntax_template.c b/libavcodec/cbs_h264_syntax_template.c new file mode 100644 index 0000000000000..0fe18441c03ac --- /dev/null +++ b/libavcodec/cbs_h264_syntax_template.c @@ -0,0 +1,1230 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static int FUNC(rbsp_trailing_bits)(CodedBitstreamContext *ctx, RWContext *rw) +{ + int err; + av_unused int one = 1, zero = 0; + xu(1, rbsp_stop_one_bit, one, 1, 1); + while (byte_alignment(rw) != 0) + xu(1, rbsp_alignment_zero_bit, zero, 0, 0); + + return 0; +} + +static int FUNC(nal_unit_header)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawNALUnitHeader *current, + uint32_t valid_type_mask) +{ + int err; + + u(1, forbidden_zero_bit, 0, 0); + u(2, nal_ref_idc, 0, 3); + u(5, nal_unit_type, 0, 31); + + if (!(1 << current->nal_unit_type & valid_type_mask)) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid NAL unit type %d.\n", + current->nal_unit_type); + return AVERROR_INVALIDDATA; + } + + if (current->nal_unit_type == 14 || + current->nal_unit_type == 20 || + current->nal_unit_type == 21) { + if (current->nal_unit_type != 21) + flag(svc_extension_flag); + else + flag(avc_3d_extension_flag); + + if (current->svc_extension_flag) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SVC not supported.\n"); + return AVERROR_PATCHWELCOME; + + } else if (current->avc_3d_extension_flag) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "3DAVC not supported.\n"); + return AVERROR_PATCHWELCOME; + + } else { + av_log(ctx->log_ctx, AV_LOG_ERROR, "MVC not supported.\n"); + return AVERROR_PATCHWELCOME; + } + } + + return 0; +} + +static int FUNC(scaling_list)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawScalingList *current, + int size_of_scaling_list) +{ + int err, i, scale; + + scale = 8; + for (i = 0; i < size_of_scaling_list; i++) { + xse(delta_scale, current->delta_scale[i], -128, +127); + scale = (scale + current->delta_scale[i] + 256) % 256; + if (scale == 0) + break; + } + + return 0; +} + +static int FUNC(hrd_parameters)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawHRD *current) +{ + int err, i; + + ue(cpb_cnt_minus1, 0, 31); + u(4, bit_rate_scale, 0, 15); + u(4, cpb_size_scale, 0, 15); + + for (i = 0; i <= current->cpb_cnt_minus1; i++) { + ue(bit_rate_value_minus1[i], 0, UINT32_MAX - 1); + ue(cpb_size_value_minus1[i], 0, UINT32_MAX - 1); + flag(cbr_flag[i]); + } + + u(5, initial_cpb_removal_delay_length_minus1, 0, 31); + u(5, cpb_removal_delay_length_minus1, 0, 31); + u(5, dpb_output_delay_length_minus1, 0, 31); + u(5, time_offset_length, 0, 31); + + return 0; +} + +static int FUNC(vui_parameters)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawVUI *current, H264RawSPS *sps) +{ + int err; + + flag(aspect_ratio_info_present_flag); + if (current->aspect_ratio_info_present_flag) { + u(8, aspect_ratio_idc, 0, 255); + if (current->aspect_ratio_idc == 255) { + u(16, sar_width, 0, 65535); + u(16, sar_height, 0, 65535); + } + } else { + infer(aspect_ratio_idc, 0); + } + + flag(overscan_info_present_flag); + if (current->overscan_info_present_flag) + flag(overscan_appropriate_flag); + + flag(video_signal_type_present_flag); + if (current->video_signal_type_present_flag) { + u(3, video_format, 0, 7); + flag(video_full_range_flag); + flag(colour_description_present_flag); + if (current->colour_description_present_flag) { + u(8, colour_primaries, 0, 255); + u(8, transfer_characteristics, 0, 255); + u(8, matrix_coefficients, 0, 255); + } + } else { + infer(video_format, 5); + infer(video_full_range_flag, 0); + infer(colour_primaries, 2); + infer(transfer_characteristics, 2); + infer(matrix_coefficients, 2); + } + + flag(chroma_loc_info_present_flag); + if (current->chroma_loc_info_present_flag) { + ue(chroma_sample_loc_type_top_field, 0, 5); + ue(chroma_sample_loc_type_bottom_field, 0, 5); + } else { + infer(chroma_sample_loc_type_top_field, 0); + infer(chroma_sample_loc_type_bottom_field, 0); + } + + flag(timing_info_present_flag); + if (current->timing_info_present_flag) { + u(32, num_units_in_tick, 1, UINT32_MAX); + u(32, time_scale, 1, UINT32_MAX); + flag(fixed_frame_rate_flag); + } else { + infer(fixed_frame_rate_flag, 0); + } + + flag(nal_hrd_parameters_present_flag); + if (current->nal_hrd_parameters_present_flag) + CHECK(FUNC(hrd_parameters)(ctx, rw, ¤t->nal_hrd_parameters)); + + flag(vcl_hrd_parameters_present_flag); + if (current->vcl_hrd_parameters_present_flag) + CHECK(FUNC(hrd_parameters)(ctx, rw, ¤t->vcl_hrd_parameters)); + + if (current->nal_hrd_parameters_present_flag || + current->vcl_hrd_parameters_present_flag) + flag(low_delay_hrd_flag); + else + infer(low_delay_hrd_flag, 1 - current->fixed_frame_rate_flag); + + flag(pic_struct_present_flag); + + flag(bitstream_restriction_flag); + if (current->bitstream_restriction_flag) { + flag(motion_vectors_over_pic_boundaries_flag); + ue(max_bytes_per_pic_denom, 0, 16); + ue(max_bits_per_mb_denom, 0, 16); + ue(log2_max_mv_length_horizontal, 0, 16); + ue(log2_max_mv_length_vertical, 0, 16); + ue(max_num_reorder_frames, 0, H264_MAX_DPB_FRAMES); + ue(max_dec_frame_buffering, 0, H264_MAX_DPB_FRAMES); + } else { + infer(motion_vectors_over_pic_boundaries_flag, 1); + infer(max_bytes_per_pic_denom, 2); + infer(max_bits_per_mb_denom, 1); + infer(log2_max_mv_length_horizontal, 16); + infer(log2_max_mv_length_vertical, 16); + + if ((sps->profile_idc == 44 || sps->profile_idc == 86 || + sps->profile_idc == 110 || sps->profile_idc == 110 || + sps->profile_idc == 122 || sps->profile_idc == 244) && + sps->constraint_set3_flag) { + infer(max_num_reorder_frames, 0); + infer(max_dec_frame_buffering, 0); + } else { + infer(max_num_reorder_frames, H264_MAX_DPB_FRAMES); + infer(max_dec_frame_buffering, H264_MAX_DPB_FRAMES); + } + } + + return 0; +} + +static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSPS *current) +{ + int err, i; + + HEADER("Sequence Parameter Set"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + 1 << H264_NAL_SPS)); + + u(8, profile_idc, 0, 255); + + flag(constraint_set0_flag); + flag(constraint_set1_flag); + flag(constraint_set2_flag); + flag(constraint_set3_flag); + flag(constraint_set4_flag); + flag(constraint_set5_flag); + + u(2, reserved_zero_2bits, 0, 0); + + u(8, level_idc, 0, 255); + + ue(seq_parameter_set_id, 0, 31); + + if (current->profile_idc == 100 || current->profile_idc == 110 || + current->profile_idc == 122 || current->profile_idc == 244 || + current->profile_idc == 44 || current->profile_idc == 83 || + current->profile_idc == 86 || current->profile_idc == 118 || + current->profile_idc == 128 || current->profile_idc == 138) { + ue(chroma_format_idc, 0, 3); + + if (current->chroma_format_idc == 3) + flag(separate_colour_plane_flag); + else + infer(separate_colour_plane_flag, 0); + + ue(bit_depth_luma_minus8, 0, 6); + ue(bit_depth_chroma_minus8, 0, 6); + + flag(qpprime_y_zero_transform_bypass_flag); + + flag(seq_scaling_matrix_present_flag); + if (current->seq_scaling_matrix_present_flag) { + for (i = 0; i < ((current->chroma_format_idc != 3) ? 8 : 12); i++) { + flag(seq_scaling_list_present_flag[i]); + if (current->seq_scaling_list_present_flag[i]) { + if (i < 6) + CHECK(FUNC(scaling_list)(ctx, rw, + ¤t->scaling_list_4x4[i], + 16)); + else + CHECK(FUNC(scaling_list)(ctx, rw, + ¤t->scaling_list_8x8[i - 6], + 64)); + } + } + } + } else { + infer(chroma_format_idc, current->profile_idc == 183 ? 0 : 1); + + infer(separate_colour_plane_flag, 0); + infer(bit_depth_luma_minus8, 0); + infer(bit_depth_chroma_minus8, 0); + } + + ue(log2_max_frame_num_minus4, 0, 12); + ue(pic_order_cnt_type, 0, 2); + + if (current->pic_order_cnt_type == 0) { + ue(log2_max_pic_order_cnt_lsb_minus4, 0, 12); + } else if (current->pic_order_cnt_type == 1) { + flag(delta_pic_order_always_zero_flag); + se(offset_for_non_ref_pic, INT32_MIN + 1, INT32_MAX); + se(offset_for_top_to_bottom_field, INT32_MIN + 1, INT32_MAX); + ue(num_ref_frames_in_pic_order_cnt_cycle, 0, 255); + + for (i = 0; i < current->num_ref_frames_in_pic_order_cnt_cycle; i++) + se(offset_for_ref_frame[i], INT32_MIN + 1, INT32_MAX); + } + + ue(max_num_ref_frames, 0, H264_MAX_DPB_FRAMES); + flag(gaps_in_frame_num_allowed_flag); + + ue(pic_width_in_mbs_minus1, 0, H264_MAX_MB_WIDTH); + ue(pic_height_in_map_units_minus1, 0, H264_MAX_MB_HEIGHT); + + flag(frame_mbs_only_flag); + if (!current->frame_mbs_only_flag) + flag(mb_adaptive_frame_field_flag); + + flag(direct_8x8_inference_flag); + + flag(frame_cropping_flag); + if (current->frame_cropping_flag) { + ue(frame_crop_left_offset, 0, H264_MAX_WIDTH); + ue(frame_crop_right_offset, 0, H264_MAX_WIDTH); + ue(frame_crop_top_offset, 0, H264_MAX_HEIGHT); + ue(frame_crop_bottom_offset, 0, H264_MAX_HEIGHT); + } + + flag(vui_parameters_present_flag); + if (current->vui_parameters_present_flag) + CHECK(FUNC(vui_parameters)(ctx, rw, ¤t->vui, current)); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(sps_extension)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSPSExtension *current) +{ + int err; + + HEADER("Sequence Parameter Set Extension"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + 1 << H264_NAL_SPS_EXT)); + + ue(seq_parameter_set_id, 0, 31); + + ue(aux_format_idc, 0, 3); + + if (current->aux_format_idc != 0) { + int bits; + + ue(bit_depth_aux_minus8, 0, 4); + flag(alpha_incr_flag); + + bits = current->bit_depth_aux_minus8 + 9; + u(bits, alpha_opaque_value, 0, (1 << bits) - 1); + u(bits, alpha_transparent_value, 0, (1 << bits) - 1); + } + + flag(additional_extension_flag); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(pps)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawPPS *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps; + int err, i; + + HEADER("Picture Parameter Set"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + 1 << H264_NAL_PPS)); + + ue(pic_parameter_set_id, 0, 255); + ue(seq_parameter_set_id, 0, 31); + + sps = h264->sps[current->seq_parameter_set_id]; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SPS id %d not available.\n", + current->seq_parameter_set_id); + return AVERROR_INVALIDDATA; + } + + flag(entropy_coding_mode_flag); + flag(bottom_field_pic_order_in_frame_present_flag); + + ue(num_slice_groups_minus1, 0, 7); + if (current->num_slice_groups_minus1 > 0) { + unsigned int pic_size; + int iGroup; + + pic_size = (sps->pic_width_in_mbs_minus1 + 1) * + (sps->pic_height_in_map_units_minus1 + 1); + + ue(slice_group_map_type, 0, 6); + + if (current->slice_group_map_type == 0) { + for (iGroup = 0; iGroup <= current->num_slice_groups_minus1; iGroup++) + ue(run_length_minus1[iGroup], 0, pic_size - 1); + + } else if (current->slice_group_map_type == 2) { + for (iGroup = 0; iGroup < current->num_slice_groups_minus1; iGroup++) { + ue(top_left[iGroup], 0, pic_size - 1); + ue(bottom_right[iGroup], current->top_left[iGroup], pic_size - 1); + } + } else if (current->slice_group_map_type == 3 || + current->slice_group_map_type == 4 || + current->slice_group_map_type == 5) { + flag(slice_group_change_direction_flag); + ue(slice_group_change_rate_minus1, 0, pic_size - 1); + } else if (current->slice_group_map_type == 6) { + ue(pic_size_in_map_units_minus1, pic_size - 1, pic_size - 1); + for (i = 0; i <= current->pic_size_in_map_units_minus1; i++) + u(av_log2(2 * current->num_slice_groups_minus1 + 1), + slice_group_id[i], 0, current->num_slice_groups_minus1); + } + } + + ue(num_ref_idx_l0_default_active_minus1, 0, 31); + ue(num_ref_idx_l1_default_active_minus1, 0, 31); + + flag(weighted_pred_flag); + u(2, weighted_bipred_idc, 0, 2); + + se(pic_init_qp_minus26, -26 - 6 * sps->bit_depth_luma_minus8, +25); + se(pic_init_qs_minus26, -26, +25); + se(chroma_qp_index_offset, -12, +12); + + flag(deblocking_filter_control_present_flag); + flag(constrained_intra_pred_flag); + flag(redundant_pic_cnt_present_flag); + + if (more_rbsp_data(current->more_rbsp_data)) + { + flag(transform_8x8_mode_flag); + + flag(pic_scaling_matrix_present_flag); + if (current->pic_scaling_matrix_present_flag) { + for (i = 0; i < 6 + (((sps->chroma_format_idc != 3) ? 2 : 6) * + current->transform_8x8_mode_flag); i++) { + flag(pic_scaling_list_present_flag[i]); + if (current->pic_scaling_list_present_flag[i]) { + if (i < 6) + CHECK(FUNC(scaling_list)(ctx, rw, + ¤t->scaling_list_4x4[i], + 16)); + else + CHECK(FUNC(scaling_list)(ctx, rw, + ¤t->scaling_list_8x8[i - 6], + 64)); + } + } + } + + se(second_chroma_qp_index_offset, -12, +12); + } else { + infer(transform_8x8_mode_flag, 0); + infer(pic_scaling_matrix_present_flag, 0); + infer(second_chroma_qp_index_offset, current->chroma_qp_index_offset); + } + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIBufferingPeriod *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps; + int err, i, length; + + ue(seq_parameter_set_id, 0, 31); + + sps = h264->sps[current->seq_parameter_set_id]; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SPS id %d not available.\n", + current->seq_parameter_set_id); + return AVERROR_INVALIDDATA; + } + h264->active_sps = sps; + + if (sps->vui.nal_hrd_parameters_present_flag) { + for (i = 0; i <= sps->vui.nal_hrd_parameters.cpb_cnt_minus1; i++) { + length = sps->vui.nal_hrd_parameters.initial_cpb_removal_delay_length_minus1 + 1; + xu(length, initial_cpb_removal_delay[SchedSelIdx], + current->nal.initial_cpb_removal_delay[i], + 0, (1 << (uint64_t)length) - 1); + xu(length, initial_cpb_removal_delay_offset[SchedSelIdx], + current->nal.initial_cpb_removal_delay_offset[i], + 0, (1 << (uint64_t)length) - 1); + } + } + + if (sps->vui.vcl_hrd_parameters_present_flag) { + for (i = 0; i <= sps->vui.vcl_hrd_parameters.cpb_cnt_minus1; i++) { + length = sps->vui.vcl_hrd_parameters.initial_cpb_removal_delay_length_minus1 + 1; + xu(length, initial_cpb_removal_delay[SchedSelIdx], + current->vcl.initial_cpb_removal_delay[i], + 0, (1 << (uint64_t)length) - 1); + xu(length, initial_cpb_removal_delay_offset[SchedSelIdx], + current->vcl.initial_cpb_removal_delay_offset[i], + 0, (1 << (uint64_t)length) - 1); + } + } + + return 0; +} + +static int FUNC(sei_pic_timestamp)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIPicTimestamp *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps; + uint8_t time_offset_length; + int err; + + u(2, ct_type, 0, 2); + flag(nuit_field_based_flag); + u(5, counting_type, 0, 6); + flag(full_timestamp_flag); + flag(discontinuity_flag); + flag(cnt_dropped_flag); + u(8, n_frames, 0, 255); + if (current->full_timestamp_flag) { + u(6, seconds_value, 0, 59); + u(6, minutes_value, 0, 59); + u(5, hours_value, 0, 23); + } else { + flag(seconds_flag); + if (current->seconds_flag) { + u(6, seconds_value, 0, 59); + flag(minutes_flag); + if (current->minutes_flag) { + u(6, minutes_value, 0, 59); + flag(hours_flag); + if (current->hours_flag) + u(5, hours_value, 0, 23); + } + } + } + + sps = h264->active_sps; + if (sps->vui.nal_hrd_parameters_present_flag) + time_offset_length = sps->vui.nal_hrd_parameters.time_offset_length; + else if (sps->vui.vcl_hrd_parameters_present_flag) + time_offset_length = sps->vui.vcl_hrd_parameters.time_offset_length; + else + time_offset_length = 24; + + if (time_offset_length > 0) + u(time_offset_length, time_offset, + 0, (1 << (uint64_t)time_offset_length) - 1); + else + infer(time_offset, 0); + + return 0; +} + +static int FUNC(sei_pic_timing)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIPicTiming *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps; + int err; + + sps = h264->active_sps; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "No active SPS for pic_timing.\n"); + return AVERROR_INVALIDDATA; + } + + if (sps->vui.nal_hrd_parameters_present_flag || + sps->vui.vcl_hrd_parameters_present_flag) { + const H264RawHRD *hrd; + + if (sps->vui.nal_hrd_parameters_present_flag) + hrd = &sps->vui.nal_hrd_parameters; + else if (sps->vui.vcl_hrd_parameters_present_flag) + hrd = &sps->vui.vcl_hrd_parameters; + else { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "No HRD parameters for pic_timing.\n"); + return AVERROR_INVALIDDATA; + } + + u(hrd->cpb_removal_delay_length_minus1 + 1, cpb_removal_delay, + 0, (1 << (uint64_t)hrd->cpb_removal_delay_length_minus1) + 1); + u(hrd->dpb_output_delay_length_minus1 + 1, dpb_output_delay, + 0, (1 << (uint64_t)hrd->dpb_output_delay_length_minus1) + 1); + } + + if (sps->vui.pic_struct_present_flag) { + static const int num_clock_ts[9] = { + 1, 1, 1, 2, 2, 3, 3, 2, 3 + }; + int i; + + u(4, pic_struct, 0, 8); + if (current->pic_struct > 8) + return AVERROR_INVALIDDATA; + + for (i = 0; i < num_clock_ts[current->pic_struct]; i++) { + flag(clock_timestamp_flag[i]); + if (current->clock_timestamp_flag[i]) + CHECK(FUNC(sei_pic_timestamp)(ctx, rw, ¤t->timestamp[i])); + } + } + + return 0; +} + +static int FUNC(sei_user_data_registered)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIUserDataRegistered *current, + uint32_t *payload_size) +{ + int err, i, j; + + u(8, itu_t_t35_country_code, 0x00, 0xff); + if (current->itu_t_t35_country_code != 0xff) + i = 1; + else { + u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff); + i = 2; + } + +#ifdef READ + if (*payload_size < i) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Invalid SEI user data registered payload.\n"); + return AVERROR_INVALIDDATA; + } + current->data_length = *payload_size - i; +#else + *payload_size = i + current->data_length; +#endif + + allocate(current->data, current->data_length); + for (j = 0; j < current->data_length; j++) + xu(8, itu_t_t35_payload_byte, current->data[j], 0x00, 0xff); + + return 0; +} + +static int FUNC(sei_user_data_unregistered)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIUserDataUnregistered *current, + uint32_t *payload_size) +{ + int err, i; + +#ifdef READ + if (*payload_size < 16) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Invalid SEI user data unregistered payload.\n"); + return AVERROR_INVALIDDATA; + } + current->data_length = *payload_size - 16; +#else + *payload_size = 16 + current->data_length; +#endif + + for (i = 0; i < 16; i++) { + xu(8, uuid_iso_iec_11578, + current->uuid_iso_iec_11578[i], 0x00, 0xff); + } + + allocate(current->data, current->data_length); + + for (i = 0; i < current->data_length; i++) + xu(8, user_data_payload_byte, current->data[i], 0x00, 0xff); + + return 0; +} + +static int FUNC(sei_recovery_point)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIRecoveryPoint *current) +{ + int err; + + ue(recovery_frame_cnt, 0, 65535); + flag(exact_match_flag); + flag(broken_link_flag); + u(2, changing_slice_group_idc, 0, 2); + + return 0; +} + +static int FUNC(sei_display_orientation)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIDisplayOrientation *current) +{ + int err; + + flag(display_orientation_cancel_flag); + if (!current->display_orientation_cancel_flag) { + flag(hor_flip); + flag(ver_flip); + u(16, anticlockwise_rotation, 0, 65535); + ue(display_orientation_repetition_period, 0, 16384); + flag(display_orientation_extension_flag); + } + + return 0; +} + +static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIPayload *current) +{ + int err, i; + int start_position, end_position; + +#ifdef READ + start_position = bitstream_tell(rw); +#else + start_position = put_bits_count(rw); +#endif + + switch (current->payload_type) { + case H264_SEI_TYPE_BUFFERING_PERIOD: + CHECK(FUNC(sei_buffering_period) + (ctx, rw, ¤t->payload.buffering_period)); + break; + case H264_SEI_TYPE_PIC_TIMING: + CHECK(FUNC(sei_pic_timing) + (ctx, rw, ¤t->payload.pic_timing)); + break; + case H264_SEI_TYPE_FILLER_PAYLOAD: + { + av_unused int ff_byte = 0xff; + for (i = 0; i < current->payload_size; i++) + xu(8, ff_byte, ff_byte, 0xff, 0xff); + } + break; + case H264_SEI_TYPE_USER_DATA_REGISTERED: + CHECK(FUNC(sei_user_data_registered) + (ctx, rw, ¤t->payload.user_data_registered, ¤t->payload_size)); + break; + case H264_SEI_TYPE_USER_DATA_UNREGISTERED: + CHECK(FUNC(sei_user_data_unregistered) + (ctx, rw, ¤t->payload.user_data_unregistered, ¤t->payload_size)); + break; + case H264_SEI_TYPE_RECOVERY_POINT: + CHECK(FUNC(sei_recovery_point) + (ctx, rw, ¤t->payload.recovery_point)); + break; + case H264_SEI_TYPE_DISPLAY_ORIENTATION: + CHECK(FUNC(sei_display_orientation) + (ctx, rw, ¤t->payload.display_orientation)); + break; + default: + { + allocate(current->payload.other.data, current->payload_size); + for (i = 0; i < current->payload_size; i++) + xu(8, payload_byte, current->payload.other.data[i], 0, 255); + } + } + + if (byte_alignment(rw)) { + av_unused int one = 1, zero = 0; + xu(1, bit_equal_to_one, one, 1, 1); + while (byte_alignment(rw)) + xu(1, bit_equal_to_zero, zero, 0, 0); + } + +#ifdef READ + end_position = bitstream_tell(rw); + if (end_position < start_position + 8 * current->payload_size) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Incorrect SEI payload length: " + "header %d bits, actually %d bits.\n", + 8 * current->payload_size, + end_position - start_position); + return AVERROR_INVALIDDATA; + } +#else + end_position = put_bits_count(rw); + current->payload_size = (end_position - start_position) / 8; +#endif + + return 0; +} + +static int FUNC(sei)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEI *current) +{ + int err, k; + + HEADER("Supplemental Enhancement Information"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + 1 << H264_NAL_SEI)); + +#ifdef READ + for (k = 0; k < H264_MAX_SEI_PAYLOADS; k++) { + uint32_t payload_type = 0; + uint32_t payload_size = 0; + uint32_t tmp; + + while (bitstream_peek(rw, 8) == 0xff) { + xu(8, ff_byte, tmp, 0xff, 0xff); + payload_type += 255; + } + xu(8, last_payload_type_byte, tmp, 0, 254); + payload_type += tmp; + + while (bitstream_peek(rw, 8) == 0xff) { + xu(8, ff_byte, tmp, 0xff, 0xff); + payload_size += 255; + } + xu(8, last_payload_size_byte, tmp, 0, 254); + payload_size += tmp; + + current->payload[k].payload_type = payload_type; + current->payload[k].payload_size = payload_size; + + CHECK(FUNC(sei_payload)(ctx, rw, ¤t->payload[k])); + + if (!cbs_h2645_read_more_rbsp_data(rw)) + break; + } + if (k >= H264_MAX_SEI_PAYLOADS) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many payloads in " + "SEI message: found %d.\n", k); + return AVERROR_INVALIDDATA; + } + current->payload_count = k + 1; +#else + for (k = 0; k < current->payload_count; k++) { + PutBitContext start_state; + uint32_t tmp; + int need_size, i; + + // Somewhat clumsy: we write the payload twice when + // we don't know the size in advance. This will mess + // with trace output, but is otherwise harmless. + start_state = *rw; + need_size = !current->payload[k].payload_size; + for (i = 0; i < 1 + need_size; i++) { + *rw = start_state; + + tmp = current->payload[k].payload_type; + while (tmp >= 255) { + xu(8, ff_byte, 0xff, 0xff, 0xff); + tmp -= 255; + } + xu(8, last_payload_type_byte, tmp, 0, 254); + + tmp = current->payload[k].payload_size; + while (tmp >= 255) { + xu(8, ff_byte, 0xff, 0xff, 0xff); + tmp -= 255; + } + xu(8, last_payload_size_byte, tmp, 0, 254); + + CHECK(FUNC(sei_payload)(ctx, rw, ¤t->payload[k])); + } + } +#endif + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(aud)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawAUD *current) +{ + int err; + + HEADER("Access Unit Delimiter"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + 1 << H264_NAL_AUD)); + + u(3, primary_pic_type, 0, 7); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(ref_pic_list_modification)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSliceHeader *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps = h264->active_sps; + int err, i, mopn; + + if (current->slice_type % 5 != 2 && + current->slice_type % 5 != 4) { + flag(ref_pic_list_modification_flag_l0); + if (current->ref_pic_list_modification_flag_l0) { + for (i = 0; i < H264_MAX_RPLM_COUNT; i++) { + xue(modification_of_pic_nums_idc, + current->rplm_l0[i].modification_of_pic_nums_idc, 0, 3); + + mopn = current->rplm_l0[i].modification_of_pic_nums_idc; + if (mopn == 3) + break; + + if (mopn == 0 || mopn == 1) + xue(abs_diff_pic_num_minus1, + current->rplm_l0[i].abs_diff_pic_num_minus1, + 0, (1 + current->field_pic_flag) * + (1 << (sps->log2_max_frame_num_minus4 + 4))); + else if (mopn == 2) + xue(long_term_pic_num, + current->rplm_l0[i].long_term_pic_num, + 0, sps->max_num_ref_frames - 1); + } + } + } + + if (current->slice_type % 5 == 1) { + flag(ref_pic_list_modification_flag_l1); + if (current->ref_pic_list_modification_flag_l1) { + for (i = 0; i < H264_MAX_RPLM_COUNT; i++) { + xue(modification_of_pic_nums_idc, + current->rplm_l1[i].modification_of_pic_nums_idc, 0, 3); + + mopn = current->rplm_l1[i].modification_of_pic_nums_idc; + if (mopn == 3) + break; + + if (mopn == 0 || mopn == 1) + xue(abs_diff_pic_num_minus1, + current->rplm_l1[i].abs_diff_pic_num_minus1, + 0, (1 + current->field_pic_flag) * + (1 << (sps->log2_max_frame_num_minus4 + 4))); + else if (mopn == 2) + xue(long_term_pic_num, + current->rplm_l1[i].long_term_pic_num, + 0, sps->max_num_ref_frames - 1); + } + } + } + + return 0; +} + +static int FUNC(pred_weight_table)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSliceHeader *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps = h264->active_sps; + int chroma; + int err, i, j; + + ue(luma_log2_weight_denom, 0, 7); + + chroma = !sps->separate_colour_plane_flag && sps->chroma_format_idc != 0; + if (chroma) + ue(chroma_log2_weight_denom, 0, 7); + + for (i = 0; i <= current->num_ref_idx_l0_active_minus1; i++) { + flag(luma_weight_l0_flag[i]); + if (current->luma_weight_l0_flag[i]) { + se(luma_weight_l0[i], -128, +127); + se(luma_offset_l0[i], -128, +127); + } + if (chroma) { + flag(chroma_weight_l0_flag[i]); + if (current->chroma_weight_l0_flag[i]) { + for (j = 0; j < 2; j++) { + se(chroma_weight_l0[i][j], -128, +127); + se(chroma_offset_l0[i][j], -128, +127); + } + } + } + } + + if (current->slice_type % 5 == 1) { + for (i = 0; i <= current->num_ref_idx_l1_active_minus1; i++) { + flag(luma_weight_l1_flag[i]); + if (current->luma_weight_l1_flag[i]) { + se(luma_weight_l1[i], -128, +127); + se(luma_offset_l1[i], -128, +127); + } + if (chroma) { + flag(chroma_weight_l1_flag[i]); + if (current->chroma_weight_l1_flag[i]) { + for (j = 0; j < 2; j++) { + se(chroma_weight_l1[i][j], -128, +127); + se(chroma_offset_l1[i][j], -128, +127); + } + } + } + } + } + + return 0; +} + +static int FUNC(dec_ref_pic_marking)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSliceHeader *current, int idr_pic_flag) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps = h264->active_sps; + int err, i; + uint32_t mmco; + + if (idr_pic_flag) { + flag(no_output_of_prior_pics_flag); + flag(long_term_reference_flag); + } else { + flag(adaptive_ref_pic_marking_mode_flag); + if (current->adaptive_ref_pic_marking_mode_flag) { + for (i = 0; i < H264_MAX_MMCO_COUNT; i++) { + xue(memory_management_control_operation, + current->mmco[i].memory_management_control_operation, + 0, 6); + + mmco = current->mmco[i].memory_management_control_operation; + if (mmco == 0) + break; + + if (mmco == 1 || mmco == 3) + xue(difference_of_pic_nums_minus1, + current->mmco[i].difference_of_pic_nums_minus1, + 0, INT32_MAX); + if (mmco == 2) + xue(long_term_pic_num, + current->mmco[i].long_term_pic_num, + 0, sps->max_num_ref_frames - 1); + if (mmco == 3 || mmco == 6) + xue(long_term_frame_idx, + current->mmco[i].long_term_frame_idx, + 0, sps->max_num_ref_frames - 1); + if (mmco == 4) + xue(max_long_term_frame_idx_plus1, + current->mmco[i].max_long_term_frame_idx_plus1, + 0, sps->max_num_ref_frames); + } + if (i == H264_MAX_MMCO_COUNT) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many " + "memory management control operations.\n"); + return AVERROR_INVALIDDATA; + } + } + } + + return 0; +} + +static int FUNC(slice_header)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSliceHeader *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps; + const H264RawPPS *pps; + int err; + int idr_pic_flag; + int slice_type_i, slice_type_p, slice_type_b; + int slice_type_si, slice_type_sp; + + HEADER("Slice Header"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + 1 << H264_NAL_SLICE | + 1 << H264_NAL_IDR_SLICE | + 1 << H264_NAL_AUXILIARY_SLICE)); + + if (current->nal_unit_header.nal_unit_type == H264_NAL_AUXILIARY_SLICE) { + if (!h264->last_slice_nal_unit_type) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Auxiliary slice " + "is not decodable without the main picture " + "in the same access unit.\n"); + return AVERROR_INVALIDDATA; + } + } else { + h264->last_slice_nal_unit_type = + current->nal_unit_header.nal_unit_type; + } + idr_pic_flag = h264->last_slice_nal_unit_type == H264_NAL_IDR_SLICE; + + ue(first_mb_in_slice, 0, H264_MAX_MB_PIC_SIZE - 1); + ue(slice_type, 0, 9); + + slice_type_i = current->slice_type % 5 == 2; + slice_type_p = current->slice_type % 5 == 0; + slice_type_b = current->slice_type % 5 == 1; + slice_type_si = current->slice_type % 5 == 4; + slice_type_sp = current->slice_type % 5 == 3; + + if (idr_pic_flag && !(slice_type_i || slice_type_si)) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid slice type %d " + "for IDR picture.\n", current->slice_type); + return AVERROR_INVALIDDATA; + } + + ue(pic_parameter_set_id, 0, 255); + + pps = h264->pps[current->pic_parameter_set_id]; + if (!pps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "PPS id %d not available.\n", + current->pic_parameter_set_id); + return AVERROR_INVALIDDATA; + } + h264->active_pps = pps; + + sps = h264->sps[pps->seq_parameter_set_id]; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SPS id %d not available.\n", + pps->seq_parameter_set_id); + return AVERROR_INVALIDDATA; + } + h264->active_sps = sps; + + if (sps->separate_colour_plane_flag) + u(2, colour_plane_id, 0, 2); + + u(sps->log2_max_frame_num_minus4 + 4, frame_num, + 0, (1 << (sps->log2_max_frame_num_minus4 + 4)) - 1); + + if (!sps->frame_mbs_only_flag) { + flag(field_pic_flag); + if (current->field_pic_flag) + flag(bottom_field_flag); + else + infer(bottom_field_flag, 0); + } else { + infer(field_pic_flag, 0); + infer(bottom_field_flag, 0); + } + + if (idr_pic_flag) + ue(idr_pic_id, 0, 65535); + + if (sps->pic_order_cnt_type == 0) { + u(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, pic_order_cnt_lsb, + 0, (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1); + if (pps->bottom_field_pic_order_in_frame_present_flag && + !current->field_pic_flag) + se(delta_pic_order_cnt_bottom, INT32_MIN + 1, INT32_MAX); + + } else if (sps->pic_order_cnt_type == 1) { + if (!sps->delta_pic_order_always_zero_flag) { + se(delta_pic_order_cnt[0], INT32_MIN + 1, INT32_MAX); + if (pps->bottom_field_pic_order_in_frame_present_flag && + !current->field_pic_flag) + se(delta_pic_order_cnt[1], INT32_MIN + 1, INT32_MAX); + else + infer(delta_pic_order_cnt[1], 0); + } else { + infer(delta_pic_order_cnt[0], 0); + infer(delta_pic_order_cnt[1], 0); + } + } + + if (pps->redundant_pic_cnt_present_flag) + ue(redundant_pic_cnt, 0, 127); + + if (slice_type_b) + flag(direct_spatial_mv_pred_flag); + + if (slice_type_p || slice_type_sp || slice_type_b) { + flag(num_ref_idx_active_override_flag); + if (current->num_ref_idx_active_override_flag) { + ue(num_ref_idx_l0_active_minus1, 0, 31); + if (slice_type_b) + ue(num_ref_idx_l1_active_minus1, 0, 31); + } else { + infer(num_ref_idx_l0_active_minus1, + pps->num_ref_idx_l0_default_active_minus1); + infer(num_ref_idx_l1_active_minus1, + pps->num_ref_idx_l1_default_active_minus1); + } + } + + if (current->nal_unit_header.nal_unit_type == 20 || + current->nal_unit_header.nal_unit_type == 21) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "MVC / 3DAVC not supported.\n"); + return AVERROR_PATCHWELCOME; + } else { + CHECK(FUNC(ref_pic_list_modification)(ctx, rw, current)); + } + + if ((pps->weighted_pred_flag && (slice_type_p || slice_type_sp)) || + (pps->weighted_bipred_idc == 1 && slice_type_b)) { + CHECK(FUNC(pred_weight_table)(ctx, rw, current)); + } + + if (current->nal_unit_header.nal_ref_idc != 0) { + CHECK(FUNC(dec_ref_pic_marking)(ctx, rw, current, idr_pic_flag)); + } + + if (pps->entropy_coding_mode_flag && + !slice_type_i && !slice_type_si) { + ue(cabac_init_idc, 0, 2); + } + + se(slice_qp_delta, - 51 - 6 * sps->bit_depth_luma_minus8, + + 51 + 6 * sps->bit_depth_luma_minus8); + if (slice_type_sp || slice_type_si) { + if (slice_type_sp) + flag(sp_for_switch_flag); + se(slice_qs_delta, -51, +51); + } + + if (pps->deblocking_filter_control_present_flag) { + ue(disable_deblocking_filter_idc, 0, 2); + if (current->disable_deblocking_filter_idc != 1) { + se(slice_alpha_c0_offset_div2, -6, +6); + se(slice_beta_offset_div2, -6, +6); + } else { + infer(slice_alpha_c0_offset_div2, 0); + infer(slice_beta_offset_div2, 0); + } + } else { + infer(disable_deblocking_filter_idc, 0); + infer(slice_alpha_c0_offset_div2, 0); + infer(slice_beta_offset_div2, 0); + } + + if (pps->num_slice_groups_minus1 > 0 && + pps->slice_group_map_type >= 3 && + pps->slice_group_map_type <= 5) { + unsigned int pic_size, max, bits; + + pic_size = (sps->pic_width_in_mbs_minus1 + 1) * + (sps->pic_height_in_map_units_minus1 + 1); + max = (pic_size + pps->slice_group_change_rate_minus1) / + (pps->slice_group_change_rate_minus1 + 1); + bits = av_log2(2 * max - 1); + + u(bits, slice_group_change_cycle, 0, max); + } + + if (pps->entropy_coding_mode_flag) { + av_unused int one = 1; + while (byte_alignment(rw)) + xu(1, cabac_alignment_one_bit, one, 1, 1); + } + + return 0; +} diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index a691790b705e4..e87a43970f37f 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -80,4 +80,7 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc, uint32_t range_min, uint32_t range_max); +extern const CodedBitstreamType ff_cbs_type_h264; + + #endif /* AVCODEC_CBS_INTERNAL_H */ From 867381b8b51fa21fa2b8f071f508f3d39cc9c1f0 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 14 May 2017 16:32:00 +0100 Subject: [PATCH 0350/2557] lavc: Add coded bitstream read/write support for H.265 --- configure | 2 + libavcodec/Makefile | 1 + libavcodec/cbs.c | 3 + libavcodec/cbs_h2645.c | 410 ++++++- libavcodec/cbs_h265.h | 537 +++++++++ libavcodec/cbs_h265_syntax_template.c | 1502 +++++++++++++++++++++++++ libavcodec/cbs_internal.h | 1 + 7 files changed, 2453 insertions(+), 3 deletions(-) create mode 100644 libavcodec/cbs_h265.h create mode 100644 libavcodec/cbs_h265_syntax_template.c diff --git a/configure b/configure index 54af2e0cb560a..535862fcafcec 100755 --- a/configure +++ b/configure @@ -1741,6 +1741,7 @@ CONFIG_EXTRA=" cabac cbs cbs_h264 + cbs_h265 dirac_parse dvprofile faandct @@ -1968,6 +1969,7 @@ threads_if_any="$THREADS_LIST" # subsystems cbs_h264_select="cbs golomb" +cbs_h265_select="cbs golomb" dct_select="rdft" dirac_parse_select="golomb" error_resilience_select="me_cmp" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 30fc388f8c2c7..9791fb342e4db 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -55,6 +55,7 @@ OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o OBJS-$(CONFIG_CABAC) += cabac.o OBJS-$(CONFIG_CBS) += cbs.o OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o h2645_parse.o +OBJS-$(CONFIG_CBS_H265) += cbs_h2645.o h2645_parse.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o OBJS-$(CONFIG_FAANDCT) += faandct.o diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index 9352b535b2512..b5d5dfd2fd053 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -31,6 +31,9 @@ static const CodedBitstreamType *cbs_type_table[] = { #if CONFIG_CBS_H264 &ff_cbs_type_h264, #endif +#if CONFIG_CBS_H265 + &ff_cbs_type_h265, +#endif }; int ff_cbs_init(CodedBitstreamContext *ctx, diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 2350f039fa3bf..23556f47f8466 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -23,10 +23,12 @@ #include "cbs.h" #include "cbs_internal.h" #include "cbs_h264.h" +#include "cbs_h265.h" #include "golomb.h" #include "h264.h" #include "h264_sei.h" #include "h2645_parse.h" +#include "hevc.h" static int cbs_read_ue_golomb(CodedBitstreamContext *ctx, BitstreamContext *bc, @@ -237,6 +239,7 @@ static int cbs_write_se_golomb(CodedBitstreamContext *ctx, PutBitContext *pbc, #define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name #define FUNC_H264(rw, name) FUNC_NAME(rw, h264, name) +#define FUNC_H265(rw, name) FUNC_NAME(rw, h265, name) #define READ @@ -299,6 +302,10 @@ static int cbs_h2645_read_more_rbsp_data(BitstreamContext *bc) #include "cbs_h264_syntax_template.c" #undef FUNC +#define FUNC(name) FUNC_H265(READWRITE, name) +#include "cbs_h265_syntax_template.c" +#undef FUNC + #undef READ #undef READWRITE #undef RWContext @@ -368,6 +375,10 @@ static int cbs_h2645_read_more_rbsp_data(BitstreamContext *bc) #include "cbs_h264_syntax_template.c" #undef FUNC +#define FUNC(name) FUNC_H265(READWRITE, name) +#include "cbs_h265_syntax_template.c" +#undef FUNC + #undef WRITE #undef READWRITE #undef RWContext @@ -428,6 +439,40 @@ static void cbs_h264_free_nal_unit(CodedBitstreamUnit *unit) av_freep(&unit->content); } +static void cbs_h265_free_nal_unit(CodedBitstreamUnit *unit) +{ + switch (unit->type) { + case HEVC_NAL_VPS: + av_freep(&((H265RawVPS*)unit->content)->extension_data.data); + break; + case HEVC_NAL_SPS: + av_freep(&((H265RawSPS*)unit->content)->extension_data.data); + break; + case HEVC_NAL_PPS: + av_freep(&((H265RawPPS*)unit->content)->extension_data.data); + break; + case HEVC_NAL_TRAIL_N: + case HEVC_NAL_TRAIL_R: + case HEVC_NAL_TSA_N: + case HEVC_NAL_TSA_R: + case HEVC_NAL_STSA_N: + case HEVC_NAL_STSA_R: + case HEVC_NAL_RADL_N: + case HEVC_NAL_RADL_R: + case HEVC_NAL_RASL_N: + case HEVC_NAL_RASL_R: + case HEVC_NAL_BLA_W_LP: + case HEVC_NAL_BLA_W_RADL: + case HEVC_NAL_BLA_N_LP: + case HEVC_NAL_IDR_W_RADL: + case HEVC_NAL_IDR_N_LP: + case HEVC_NAL_CRA_NUT: + av_freep(&((H265RawSlice*)unit->content)->data); + break; + } + av_freep(&unit->content); +} + static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, const H2645Packet *packet) @@ -542,6 +587,58 @@ static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx, "header.\n", bytestream2_get_bytes_left(&gbc)); } + } else if (header && frag->data[0] && codec_id == AV_CODEC_ID_HEVC) { + // HVCC header. + size_t size, start, end; + int i, j, nb_arrays, nal_unit_type, nb_nals, version; + + priv->mp4 = 1; + + bytestream2_init(&gbc, frag->data, frag->data_size); + + if (bytestream2_get_bytes_left(&gbc) < 23) + return AVERROR_INVALIDDATA; + + version = bytestream2_get_byte(&gbc); + if (version != 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid HVCC header: " + "first byte %u.", version); + return AVERROR_INVALIDDATA; + } + + bytestream2_skip(&gbc, 20); + priv->nal_length_size = (bytestream2_get_byte(&gbc) & 3) + 1; + + nb_arrays = bytestream2_get_byte(&gbc); + for (i = 0; i < nb_arrays; i++) { + nal_unit_type = bytestream2_get_byte(&gbc) & 0x3f; + nb_nals = bytestream2_get_be16(&gbc); + + start = bytestream2_tell(&gbc); + for (j = 0; j < nb_nals; j++) { + if (bytestream2_get_bytes_left(&gbc) < 2) + return AVERROR_INVALIDDATA; + size = bytestream2_get_be16(&gbc); + if (bytestream2_get_bytes_left(&gbc) < size) + return AVERROR_INVALIDDATA; + bytestream2_skip(&gbc, size); + } + end = bytestream2_tell(&gbc); + + err = ff_h2645_packet_split(&priv->read_packet, + frag->data + start, end - start, + ctx->log_ctx, 1, 2, AV_CODEC_ID_HEVC); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split " + "HVCC array %d (%d NAL units of type %d).\n", + i, nb_nals, nal_unit_type); + return err; + } + err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet); + if (err < 0) + return err; + } + } else { // Annex B, or later MP4 with already-known parameters. @@ -582,6 +679,9 @@ static int cbs_h26 ## h26n ## _replace_ ## ps_var(CodedBitstreamContext *ctx, \ cbs_h2645_replace_ps(4, SPS, sps, seq_parameter_set_id) cbs_h2645_replace_ps(4, PPS, pps, pic_parameter_set_id) +cbs_h2645_replace_ps(5, VPS, vps, vps_video_parameter_set_id) +cbs_h2645_replace_ps(5, SPS, sps, sps_seq_parameter_set_id) +cbs_h2645_replace_ps(5, PPS, pps, pps_pic_parameter_set_id) static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit) @@ -730,6 +830,150 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, return 0; } +static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + BitstreamContext bc; + int err; + + err = bitstream_init(&bc, unit->data, 8 * unit->data_size); + if (err < 0) + return err; + + switch (unit->type) { + case HEVC_NAL_VPS: + { + H265RawVPS *vps; + + vps = av_mallocz(sizeof(*vps)); + if (!vps) + return AVERROR(ENOMEM); + err = cbs_h265_read_vps(ctx, &bc, vps); + if (err >= 0) + err = cbs_h265_replace_vps(ctx, vps); + if (err < 0) { + av_free(vps); + return err; + } + + unit->content = vps; + } + break; + case HEVC_NAL_SPS: + { + H265RawSPS *sps; + + sps = av_mallocz(sizeof(*sps)); + if (!sps) + return AVERROR(ENOMEM); + err = cbs_h265_read_sps(ctx, &bc, sps); + if (err >= 0) + err = cbs_h265_replace_sps(ctx, sps); + if (err < 0) { + av_free(sps); + return err; + } + + unit->content = sps; + } + break; + + case HEVC_NAL_PPS: + { + H265RawPPS *pps; + + pps = av_mallocz(sizeof(*pps)); + if (!pps) + return AVERROR(ENOMEM); + err = cbs_h265_read_pps(ctx, &bc, pps); + if (err >= 0) + err = cbs_h265_replace_pps(ctx, pps); + if (err < 0) { + av_free(pps); + return err; + } + + unit->content = pps; + } + break; + + case HEVC_NAL_TRAIL_N: + case HEVC_NAL_TRAIL_R: + case HEVC_NAL_TSA_N: + case HEVC_NAL_TSA_R: + case HEVC_NAL_STSA_N: + case HEVC_NAL_STSA_R: + case HEVC_NAL_RADL_N: + case HEVC_NAL_RADL_R: + case HEVC_NAL_RASL_N: + case HEVC_NAL_RASL_R: + case HEVC_NAL_BLA_W_LP: + case HEVC_NAL_BLA_W_RADL: + case HEVC_NAL_BLA_N_LP: + case HEVC_NAL_IDR_W_RADL: + case HEVC_NAL_IDR_N_LP: + case HEVC_NAL_CRA_NUT: + { + H265RawSlice *slice; + int pos, len; + + slice = av_mallocz(sizeof(*slice)); + if (!slice) + return AVERROR(ENOMEM); + err = cbs_h265_read_slice_segment_header(ctx, &bc, &slice->header); + if (err < 0) { + av_free(slice); + return err; + } + + pos = bitstream_tell(&bc); + len = unit->data_size; + if (!unit->data[len - 1]) { + int z; + for (z = 0; z < len && !unit->data[len - z - 1]; z++); + av_log(ctx->log_ctx, AV_LOG_DEBUG, "Deleted %d trailing zeroes " + "from slice data.\n", z); + len -= z; + } + + slice->data_size = len - pos / 8; + slice->data = av_malloc(slice->data_size); + if (!slice->data) { + av_free(slice); + return AVERROR(ENOMEM); + } + memcpy(slice->data, + unit->data + pos / 8, slice->data_size); + slice->data_bit_start = pos % 8; + + unit->content = slice; + } + break; + + case HEVC_NAL_AUD: + { + H265RawAUD *aud; + + aud = av_mallocz(sizeof(*aud)); + if (!aud) + return AVERROR(ENOMEM); + err = cbs_h265_read_aud(ctx, &bc, aud); + if (err < 0) { + av_free(aud); + return err; + } + + unit->content = aud; + } + break; + + default: + return AVERROR(ENOSYS); + } + + return 0; +} + static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit, PutBitContext *pbc) @@ -842,6 +1086,127 @@ static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx, return 0; } +static int cbs_h265_write_nal_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + PutBitContext *pbc) +{ + int err; + + switch (unit->type) { + case HEVC_NAL_VPS: + { + H265RawVPS *vps = unit->content; + + err = cbs_h265_write_vps(ctx, pbc, vps); + if (err < 0) + return err; + + err = cbs_h265_replace_vps(ctx, vps); + if (err < 0) + return err; + } + break; + + case HEVC_NAL_SPS: + { + H265RawSPS *sps = unit->content; + + err = cbs_h265_write_sps(ctx, pbc, sps); + if (err < 0) + return err; + + err = cbs_h265_replace_sps(ctx, sps); + if (err < 0) + return err; + } + break; + + case HEVC_NAL_PPS: + { + H265RawPPS *pps = unit->content; + + err = cbs_h265_write_pps(ctx, pbc, pps); + if (err < 0) + return err; + + err = cbs_h265_replace_pps(ctx, pps); + if (err < 0) + return err; + } + break; + + case HEVC_NAL_TRAIL_N: + case HEVC_NAL_TRAIL_R: + case HEVC_NAL_TSA_N: + case HEVC_NAL_TSA_R: + case HEVC_NAL_STSA_N: + case HEVC_NAL_STSA_R: + case HEVC_NAL_RADL_N: + case HEVC_NAL_RADL_R: + case HEVC_NAL_RASL_N: + case HEVC_NAL_RASL_R: + case HEVC_NAL_BLA_W_LP: + case HEVC_NAL_BLA_W_RADL: + case HEVC_NAL_BLA_N_LP: + case HEVC_NAL_IDR_W_RADL: + case HEVC_NAL_IDR_N_LP: + case HEVC_NAL_CRA_NUT: + { + H265RawSlice *slice = unit->content; + BitstreamContext bc; + int bits_left, end, zeroes; + + err = cbs_h265_write_slice_segment_header(ctx, pbc, &slice->header); + if (err < 0) + return err; + + if (slice->data) { + if (slice->data_size * 8 + 8 > put_bits_left(pbc)) + return AVERROR(ENOSPC); + + bitstream_init(&bc, slice->data, slice->data_size * 8); + bitstream_skip(&bc, slice->data_bit_start); + + // Copy in two-byte blocks, but stop before copying the + // rbsp_stop_one_bit in the final byte. + while (bitstream_bits_left(&bc) > 23) + put_bits(pbc, 16, bitstream_read(&bc, 16)); + + bits_left = bitstream_bits_left(&bc); + end = bitstream_read(&bc, bits_left); + + // rbsp_stop_one_bit must be present here. + av_assert0(end); + zeroes = ff_ctz(end); + if (bits_left > zeroes + 1) + put_bits(pbc, bits_left - zeroes - 1, + end >> (zeroes + 1)); + put_bits(pbc, 1, 1); + while (put_bits_count(pbc) % 8 != 0) + put_bits(pbc, 1, 0); + } else { + // No slice data - that was just the header. + } + } + break; + + case HEVC_NAL_AUD: + { + err = cbs_h265_write_aud(ctx, pbc, unit->content); + if (err < 0) + return err; + } + break; + + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for " + "NAL unit type %d.\n", unit->type); + return AVERROR_PATCHWELCOME; + } + + return 0; +} + static int cbs_h2645_write_nal_unit(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit) { @@ -866,7 +1231,10 @@ static int cbs_h2645_write_nal_unit(CodedBitstreamContext *ctx, init_put_bits(&pbc, priv->write_buffer, priv->write_buffer_size); - err = cbs_h264_write_nal_unit(ctx, unit, &pbc); + if (codec_id == AV_CODEC_ID_H264) + err = cbs_h264_write_nal_unit(ctx, unit, &pbc); + else + err = cbs_h265_write_nal_unit(ctx, unit, &pbc); if (err == AVERROR(ENOSPC)) { // Overflow. @@ -927,8 +1295,13 @@ static int cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx, frag->data_bit_padding = unit->data_bit_padding; } - if (unit->type == H264_NAL_SPS || - unit->type == H264_NAL_PPS || + if ((ctx->codec->codec_id == AV_CODEC_ID_H264 && + (unit->type == H264_NAL_SPS || + unit->type == H264_NAL_PPS)) || + (ctx->codec->codec_id == AV_CODEC_ID_HEVC && + (unit->type == HEVC_NAL_VPS || + unit->type == HEVC_NAL_SPS || + unit->type == HEVC_NAL_PPS)) || i == 0 /* (Assume this is the start of an access unit.) */) { // zero_byte data[dp++] = 0; @@ -982,6 +1355,23 @@ static void cbs_h264_close(CodedBitstreamContext *ctx) av_freep(&h264->pps[i]); } +static void cbs_h265_close(CodedBitstreamContext *ctx) +{ + CodedBitstreamH265Context *h265 = ctx->priv_data; + int i; + + ff_h2645_packet_uninit(&h265->common.read_packet); + + av_freep(&h265->common.write_buffer); + + for (i = 0; i < FF_ARRAY_ELEMS(h265->vps); i++) + av_freep(&h265->vps[i]); + for (i = 0; i < FF_ARRAY_ELEMS(h265->sps); i++) + av_freep(&h265->sps[i]); + for (i = 0; i < FF_ARRAY_ELEMS(h265->pps); i++) + av_freep(&h265->pps[i]); +} + const CodedBitstreamType ff_cbs_type_h264 = { .codec_id = AV_CODEC_ID_H264, @@ -995,3 +1385,17 @@ const CodedBitstreamType ff_cbs_type_h264 = { .free_unit = &cbs_h264_free_nal_unit, .close = &cbs_h264_close, }; + +const CodedBitstreamType ff_cbs_type_h265 = { + .codec_id = AV_CODEC_ID_HEVC, + + .priv_data_size = sizeof(CodedBitstreamH265Context), + + .split_fragment = &cbs_h2645_split_fragment, + .read_unit = &cbs_h265_read_nal_unit, + .write_unit = &cbs_h2645_write_nal_unit, + .assemble_fragment = &cbs_h2645_assemble_fragment, + + .free_unit = &cbs_h265_free_nal_unit, + .close = &cbs_h265_close, +}; diff --git a/libavcodec/cbs_h265.h b/libavcodec/cbs_h265.h new file mode 100644 index 0000000000000..6ee07259333d4 --- /dev/null +++ b/libavcodec/cbs_h265.h @@ -0,0 +1,537 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_H265_H +#define AVCODEC_CBS_H265_H + +#include +#include + +#include "cbs_h2645.h" +#include "hevc.h" + + +typedef struct H265RawNALUnitHeader { + uint8_t forbidden_zero_bit; + uint8_t nal_unit_type; + uint8_t nuh_layer_id; + uint8_t nuh_temporal_id_plus1; +} H265RawNALUnitHeader; + +typedef struct H265RawProfileTierLevel { + uint8_t general_profile_space; + uint8_t general_tier_flag; + uint8_t general_profile_idc; + + uint8_t general_profile_compatibility_flag[32]; + + uint8_t general_progressive_source_flag; + uint8_t general_interlaced_source_flag; + uint8_t general_non_packed_constraint_flag; + uint8_t general_frame_only_constraint_flag; + + uint8_t general_max_12bit_constraint_flag; + uint8_t general_max_10bit_constraint_flag; + uint8_t general_max_8bit_constraint_flag; + uint8_t general_max_422chroma_constraint_flag; + uint8_t general_max_420chroma_constraint_flag; + uint8_t general_max_monochrome_constraint_flag; + uint8_t general_intra_constraint_flag; + uint8_t general_one_picture_only_constraint_flag; + uint8_t general_lower_bit_rate_constraint_flag; + uint8_t general_max_14bit_constraint_flag; + + uint8_t general_inbld_flag; + + uint8_t general_level_idc; + + uint8_t sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS]; + uint8_t sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS]; + + // TODO: much of that again for each sub-layer. +} H265RawProfileTierLevel; + +typedef struct H265RawSubLayerHRDParameters { + uint32_t bit_rate_value_minus1[HEVC_MAX_CPB_CNT]; + uint32_t cpb_size_value_minus1[HEVC_MAX_CPB_CNT]; + uint32_t cpb_size_du_value_minus1[HEVC_MAX_CPB_CNT]; + uint32_t bit_rate_du_value_minus1[HEVC_MAX_CPB_CNT]; + uint8_t cbr_flag[HEVC_MAX_CPB_CNT]; +} H265RawSubLayerHRDParameters; + +typedef struct H265RawHRDParameters { + uint8_t nal_hrd_parameters_present_flag; + uint8_t vcl_hrd_parameters_present_flag; + + uint8_t sub_pic_hrd_params_present_flag; + uint8_t tick_divisor_minus2; + uint8_t du_cpb_removal_delay_increment_length_minus1; + uint8_t sub_pic_cpb_params_in_pic_timing_sei_flag; + uint8_t dpb_output_delay_du_length_minus1; + + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + uint8_t cpb_size_du_scale; + + uint8_t initial_cpb_removal_delay_length_minus1; + uint8_t au_cpb_removal_delay_length_minus1; + uint8_t dpb_output_delay_length_minus1; + + uint8_t fixed_pic_rate_general_flag[HEVC_MAX_SUB_LAYERS]; + uint8_t fixed_pic_rate_within_cvs_flag[HEVC_MAX_SUB_LAYERS]; + uint16_t elemental_duration_in_tc_minus1[HEVC_MAX_SUB_LAYERS]; + uint8_t low_delay_hrd_flag[HEVC_MAX_SUB_LAYERS]; + uint8_t cpb_cnt_minus1[HEVC_MAX_SUB_LAYERS]; + H265RawSubLayerHRDParameters nal_sub_layer_hrd_parameters[HEVC_MAX_SUB_LAYERS]; + H265RawSubLayerHRDParameters vcl_sub_layer_hrd_parameters[HEVC_MAX_SUB_LAYERS]; +} H265RawHRDParameters; + +typedef struct H265RawVUI { + uint8_t aspect_ratio_info_present_flag; + uint8_t aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + + uint8_t overscan_info_present_flag; + uint8_t overscan_appropriate_flag; + + uint8_t video_signal_type_present_flag; + uint8_t video_format; + uint8_t video_full_range_flag; + uint8_t colour_description_present_flag; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; + + uint8_t chroma_loc_info_present_flag; + uint8_t chroma_sample_loc_type_top_field; + uint8_t chroma_sample_loc_type_bottom_field; + + uint8_t neutral_chroma_indication_flag; + uint8_t field_seq_flag; + uint8_t frame_field_info_present_flag; + + uint8_t default_display_window_flag; + uint16_t def_disp_win_left_offset; + uint16_t def_disp_win_right_offset; + uint16_t def_disp_win_top_offset; + uint16_t def_disp_win_bottom_offset; + + uint8_t vui_timing_info_present_flag; + uint32_t vui_num_units_in_tick; + uint32_t vui_time_scale; + uint8_t vui_poc_proportional_to_timing_flag; + uint32_t vui_num_ticks_poc_diff_one_minus1; + uint8_t vui_hrd_parameters_present_flag; + H265RawHRDParameters hrd_parameters; + + uint8_t bitstream_restriction_flag; + uint8_t tiles_fixed_structure_flag; + uint8_t motion_vectors_over_pic_boundaries_flag; + uint8_t restricted_ref_pic_lists_flag; + uint16_t min_spatial_segmentation_idc; + uint8_t max_bytes_per_pic_denom; + uint8_t max_bits_per_min_cu_denom; + uint8_t log2_max_mv_length_horizontal; + uint8_t log2_max_mv_length_vertical; +} H265RawVUI; + +typedef struct H265RawPSExtensionData { + uint8_t *data; + size_t bit_length; +} H265RawPSExtensionData; + +typedef struct H265RawVPS { + H265RawNALUnitHeader nal_unit_header; + + uint8_t vps_video_parameter_set_id; + + uint8_t vps_base_layer_internal_flag; + uint8_t vps_base_layer_available_flag; + uint8_t vps_max_layers_minus1; + uint8_t vps_max_sub_layers_minus1; + uint8_t vps_temporal_id_nesting_flag; + + H265RawProfileTierLevel profile_tier_level; + + uint8_t vps_sub_layer_ordering_info_present_flag; + uint8_t vps_max_dec_pic_buffering_minus1[HEVC_MAX_SUB_LAYERS]; + uint8_t vps_max_num_reorder_pics[HEVC_MAX_SUB_LAYERS]; + uint32_t vps_max_latency_increase_plus1[HEVC_MAX_SUB_LAYERS]; + + uint8_t vps_max_layer_id; + uint16_t vps_num_layer_sets_minus1; + uint8_t layer_id_included_flag[HEVC_MAX_LAYER_SETS][HEVC_MAX_LAYERS]; + + uint8_t vps_timing_info_present_flag; + uint32_t vps_num_units_in_tick; + uint32_t vps_time_scale; + uint8_t vps_poc_proportional_to_timing_flag; + uint32_t vps_num_ticks_poc_diff_one_minus1; + uint16_t vps_num_hrd_parameters; + uint16_t hrd_layer_set_idx[HEVC_MAX_LAYER_SETS]; + uint8_t cprms_present_flag[HEVC_MAX_LAYER_SETS]; + H265RawHRDParameters hrd_parameters[HEVC_MAX_LAYER_SETS]; + + uint8_t vps_extension_flag; + H265RawPSExtensionData extension_data; +} H265RawVPS; + +typedef struct H265RawSTRefPicSet { + uint8_t inter_ref_pic_set_prediction_flag; + + uint8_t delta_idx_minus1; + uint8_t delta_rps_sign; + uint16_t abs_delta_rps_minus1; + + uint8_t used_by_curr_pic_flag[HEVC_MAX_REFS]; + uint8_t use_delta_flag[HEVC_MAX_REFS]; + + uint8_t num_negative_pics; + uint8_t num_positive_pics; + uint16_t delta_poc_s0_minus1[HEVC_MAX_REFS]; + uint8_t used_by_curr_pic_s0_flag[HEVC_MAX_REFS]; + uint16_t delta_poc_s1_minus1[HEVC_MAX_REFS]; + uint8_t used_by_curr_pic_s1_flag[HEVC_MAX_REFS]; +} H265RawSTRefPicSet; + +typedef struct H265RawScalingList { + uint8_t scaling_list_pred_mode_flag[4][6]; + uint8_t scaling_list_pred_matrix_id_delta[4][6]; + int16_t scaling_list_dc_coef_minus8[4][6]; + int8_t scaling_list_delta_coeff[4][6][64]; +} H265RawScalingList; + +typedef struct H265RawSPS { + H265RawNALUnitHeader nal_unit_header; + + uint8_t sps_video_parameter_set_id; + + uint8_t sps_max_sub_layers_minus1; + uint8_t sps_temporal_id_nesting_flag; + + H265RawProfileTierLevel profile_tier_level; + + uint8_t sps_seq_parameter_set_id; + + uint8_t chroma_format_idc; + uint8_t separate_colour_plane_flag; + + uint16_t pic_width_in_luma_samples; + uint16_t pic_height_in_luma_samples; + + uint8_t conformance_window_flag; + uint16_t conf_win_left_offset; + uint16_t conf_win_right_offset; + uint16_t conf_win_top_offset; + uint16_t conf_win_bottom_offset; + + uint8_t bit_depth_luma_minus8; + uint8_t bit_depth_chroma_minus8; + + uint8_t log2_max_pic_order_cnt_lsb_minus4; + + uint8_t sps_sub_layer_ordering_info_present_flag; + uint8_t sps_max_dec_pic_buffering_minus1[HEVC_MAX_SUB_LAYERS]; + uint8_t sps_max_num_reorder_pics[HEVC_MAX_SUB_LAYERS]; + uint32_t sps_max_latency_increase_plus1[HEVC_MAX_SUB_LAYERS]; + + uint8_t log2_min_luma_coding_block_size_minus3; + uint8_t log2_diff_max_min_luma_coding_block_size; + uint8_t log2_min_luma_transform_block_size_minus2; + uint8_t log2_diff_max_min_luma_transform_block_size; + uint8_t max_transform_hierarchy_depth_inter; + uint8_t max_transform_hierarchy_depth_intra; + + uint8_t scaling_list_enabled_flag; + uint8_t sps_scaling_list_data_present_flag; + H265RawScalingList scaling_list; + + uint8_t amp_enabled_flag; + uint8_t sample_adaptive_offset_enabled_flag; + + uint8_t pcm_enabled_flag; + uint8_t pcm_sample_bit_depth_luma_minus1; + uint8_t pcm_sample_bit_depth_chroma_minus1; + uint8_t log2_min_pcm_luma_coding_block_size_minus3; + uint8_t log2_diff_max_min_pcm_luma_coding_block_size; + uint8_t pcm_loop_filter_disabled_flag; + + uint8_t num_short_term_ref_pic_sets; + H265RawSTRefPicSet st_ref_pic_set[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]; + + uint8_t long_term_ref_pics_present_flag; + uint8_t num_long_term_ref_pics_sps; + uint16_t lt_ref_pic_poc_lsb_sps[HEVC_MAX_LONG_TERM_REF_PICS]; + uint8_t used_by_curr_pic_lt_sps_flag[HEVC_MAX_LONG_TERM_REF_PICS]; + + uint8_t sps_temporal_mvp_enabled_flag; + uint8_t strong_intra_smoothing_enabled_flag; + + uint8_t vui_parameters_present_flag; + H265RawVUI vui; + + uint8_t sps_extension_present_flag; + uint8_t sps_range_extension_flag; + uint8_t sps_multilayer_extension_flag; + uint8_t sps_3d_extension_flag; + uint8_t sps_scc_extension_flag; + uint8_t sps_extension_4bits; + + H265RawPSExtensionData extension_data; + + // Range extension. + uint8_t transform_skip_rotation_enabled_flag; + uint8_t transform_skip_context_enabled_flag; + uint8_t implicit_rdpcm_enabled_flag; + uint8_t explicit_rdpcm_enabled_flag; + uint8_t extended_precision_processing_flag; + uint8_t intra_smoothing_disabled_flag; + uint8_t high_precision_offsets_enabled_flag; + uint8_t persistent_rice_adaptation_enabled_flag; + uint8_t cabac_bypass_alignment_enabled_flag; + + // Screen content coding extension. + uint8_t sps_curr_pic_ref_enabled_flag; + uint8_t palette_mode_enabled_flag; + uint8_t palette_max_size; + uint8_t delta_palette_max_predictor_size; + uint8_t sps_palette_predictor_initializer_present_flag; + uint8_t sps_num_palette_predictor_initializer_minus1; + uint16_t sps_palette_predictor_initializers[3][128]; + + uint8_t motion_vector_resolution_control_idc; + uint8_t intra_boundary_filtering_disable_flag; +} H265RawSPS; + +typedef struct H265RawPPS { + H265RawNALUnitHeader nal_unit_header; + + uint8_t pps_pic_parameter_set_id; + uint8_t pps_seq_parameter_set_id; + + uint8_t dependent_slice_segments_enabled_flag; + uint8_t output_flag_present_flag; + uint8_t num_extra_slice_header_bits; + uint8_t sign_data_hiding_enabled_flag; + uint8_t cabac_init_present_flag; + + uint8_t num_ref_idx_l0_default_active_minus1; + uint8_t num_ref_idx_l1_default_active_minus1; + + int8_t init_qp_minus26; + + uint8_t constrained_intra_pred_flag; + uint8_t transform_skip_enabled_flag; + uint8_t cu_qp_delta_enabled_flag; + uint8_t diff_cu_qp_delta_depth; + + int8_t pps_cb_qp_offset; + int8_t pps_cr_qp_offset; + uint8_t pps_slice_chroma_qp_offsets_present_flag; + + uint8_t weighted_pred_flag; + uint8_t weighted_bipred_flag; + + uint8_t transquant_bypass_enabled_flag; + uint8_t tiles_enabled_flag; + uint8_t entropy_coding_sync_enabled_flag; + + uint8_t num_tile_columns_minus1; + uint8_t num_tile_rows_minus1; + uint8_t uniform_spacing_flag; + uint16_t column_width_minus1[HEVC_MAX_TILE_COLUMNS]; + uint16_t row_height_minus1[HEVC_MAX_TILE_ROWS]; + uint8_t loop_filter_across_tiles_enabled_flag; + + uint8_t pps_loop_filter_across_slices_enabled_flag; + uint8_t deblocking_filter_control_present_flag; + uint8_t deblocking_filter_override_enabled_flag; + uint8_t pps_deblocking_filter_disabled_flag; + int8_t pps_beta_offset_div2; + int8_t pps_tc_offset_div2; + + uint8_t pps_scaling_list_data_present_flag; + H265RawScalingList scaling_list; + + uint8_t lists_modification_present_flag; + uint8_t log2_parallel_merge_level_minus2; + + uint8_t slice_segment_header_extension_present_flag; + + uint8_t pps_extension_present_flag; + uint8_t pps_range_extension_flag; + uint8_t pps_multilayer_extension_flag; + uint8_t pps_3d_extension_flag; + uint8_t pps_scc_extension_flag; + uint8_t pps_extension_4bits; + + H265RawPSExtensionData extension_data; + + // Range extension. + uint8_t log2_max_transform_skip_block_size_minus2; + uint8_t cross_component_prediction_enabled_flag; + uint8_t chroma_qp_offset_list_enabled_flag; + uint8_t diff_cu_chroma_qp_offset_depth; + uint8_t chroma_qp_offset_list_len_minus1; + int8_t cb_qp_offset_list[6]; + int8_t cr_qp_offset_list[6]; + uint8_t log2_sao_offset_scale_luma; + uint8_t log2_sao_offset_scale_chroma; + + // Screen content coding extension. + uint8_t pps_curr_pic_ref_enabled_flag; + uint8_t residual_adaptive_colour_transform_enabled_flag; + uint8_t pps_slice_act_qp_offsets_present_flag; + int8_t pps_act_y_qp_offset_plus5; + int8_t pps_act_cb_qp_offset_plus5; + int8_t pps_act_cr_qp_offset_plus3; + + uint8_t pps_palette_predictor_initializer_present_flag; + uint8_t pps_num_palette_predictor_initializer; + uint8_t monochrome_palette_flag; + uint8_t luma_bit_depth_entry_minus8; + uint8_t chroma_bit_depth_entry_minus8; + uint16_t pps_palette_predictor_initializers[3][128]; +} H265RawPPS; + +typedef struct H265RawAUD { + H265RawNALUnitHeader nal_unit_header; + + uint8_t pic_type; +} H265RawAUD; + +typedef struct H265RawSliceHeader { + H265RawNALUnitHeader nal_unit_header; + + uint8_t first_slice_segment_in_pic_flag; + uint8_t no_output_of_prior_pics_flag; + uint8_t slice_pic_parameter_set_id; + + uint8_t dependent_slice_segment_flag; + uint16_t slice_segment_address; + + uint8_t slice_reserved_flag[8]; + uint8_t slice_type; + + uint8_t pic_output_flag; + uint8_t colour_plane_id; + + uint16_t slice_pic_order_cnt_lsb; + + uint8_t short_term_ref_pic_set_sps_flag; + H265RawSTRefPicSet short_term_ref_pic_set; + uint8_t short_term_ref_pic_set_idx; + + uint8_t num_long_term_sps; + uint8_t num_long_term_pics; + uint8_t lt_idx_sps[HEVC_MAX_REFS]; + uint8_t poc_lsb_lt[HEVC_MAX_REFS]; + uint8_t used_by_curr_pic_lt_flag[HEVC_MAX_REFS]; + uint8_t delta_poc_msb_present_flag[HEVC_MAX_REFS]; + uint32_t delta_poc_msb_cycle_lt[HEVC_MAX_REFS]; + + uint8_t slice_temporal_mvp_enabled_flag; + + uint8_t slice_sao_luma_flag; + uint8_t slice_sao_chroma_flag; + + uint8_t num_ref_idx_active_override_flag; + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; + + uint8_t ref_pic_list_modification_flag_l0; + uint8_t list_entry_l0[HEVC_MAX_REFS]; + uint8_t ref_pic_list_modification_flag_l1; + uint8_t list_entry_l1[HEVC_MAX_REFS]; + + uint8_t mvd_l1_zero_flag; + uint8_t cabac_init_flag; + uint8_t collocated_from_l0_flag; + uint8_t collocated_ref_idx; + + uint8_t luma_log2_weight_denom; + int8_t delta_chroma_log2_weight_denom; + uint8_t luma_weight_l0_flag[HEVC_MAX_REFS]; + uint8_t chroma_weight_l0_flag[HEVC_MAX_REFS]; + int8_t delta_luma_weight_l0[HEVC_MAX_REFS]; + int16_t luma_offset_l0[HEVC_MAX_REFS]; + int8_t delta_chroma_weight_l0[HEVC_MAX_REFS][2]; + int16_t chroma_offset_l0[HEVC_MAX_REFS][2]; + uint8_t luma_weight_l1_flag[HEVC_MAX_REFS]; + uint8_t chroma_weight_l1_flag[HEVC_MAX_REFS]; + int8_t delta_luma_weight_l1[HEVC_MAX_REFS]; + int16_t luma_offset_l1[HEVC_MAX_REFS]; + int8_t delta_chroma_weight_l1[HEVC_MAX_REFS][2]; + int16_t chroma_offset_l1[HEVC_MAX_REFS][2]; + + uint8_t five_minus_max_num_merge_cand; + uint8_t use_integer_mv_flag; + + int8_t slice_qp_delta; + int8_t slice_cb_qp_offset; + int8_t slice_cr_qp_offset; + int8_t slice_act_y_qp_offset; + int8_t slice_act_cb_qp_offset; + int8_t slice_act_cr_qp_offset; + uint8_t cu_chroma_qp_offset_enabled_flag; + + uint8_t deblocking_filter_override_flag; + uint8_t slice_deblocking_filter_disabled_flag; + int8_t slice_beta_offset_div2; + int8_t slice_tc_offset_div2; + uint8_t slice_loop_filter_across_slices_enabled_flag; + + uint16_t num_entry_point_offsets; + uint8_t offset_len_minus1; + uint32_t entry_point_offset_minus1[HEVC_MAX_ENTRY_POINT_OFFSETS]; + + uint16_t slice_segment_header_extension_length; + uint8_t slice_segment_header_extension_data_byte[256]; +} H265RawSliceHeader; + + +typedef struct H265RawSlice { + H265RawSliceHeader header; + + uint8_t *data; + size_t data_size; + int data_bit_start; +} H265RawSlice; + + +typedef struct CodedBitstreamH265Context { + // Reader/writer context in common with the H.264 implementation. + CodedBitstreamH2645Context common; + + // All currently available parameter sets. These are updated when + // any parameter set NAL unit is read/written with this context. + H265RawVPS *vps[HEVC_MAX_VPS_COUNT]; + H265RawSPS *sps[HEVC_MAX_SPS_COUNT]; + H265RawPPS *pps[HEVC_MAX_PPS_COUNT]; + + // The currently active parameter sets. These are updated when any + // NAL unit refers to the relevant parameter set. These pointers + // must also be present in the arrays above. + const H265RawVPS *active_vps; + const H265RawSPS *active_sps; + const H265RawPPS *active_pps; +} CodedBitstreamH265Context; + + +#endif /* AVCODEC_CBS_H265_H */ diff --git a/libavcodec/cbs_h265_syntax_template.c b/libavcodec/cbs_h265_syntax_template.c new file mode 100644 index 0000000000000..40fdaf8a900b0 --- /dev/null +++ b/libavcodec/cbs_h265_syntax_template.c @@ -0,0 +1,1502 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static int FUNC(rbsp_trailing_bits)(CodedBitstreamContext *ctx, RWContext *rw) +{ + int err; + av_unused int one = 1, zero = 0; + xu(1, rbsp_stop_one_bit, one, 1, 1); + while (byte_alignment(rw) != 0) + xu(1, rbsp_alignment_zero_bit, zero, 0, 0); + + return 0; +} + +static int FUNC(nal_unit_header)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawNALUnitHeader *current, + int expected_nal_unit_type) +{ + int err; + + u(1, forbidden_zero_bit, 0, 0); + + if (expected_nal_unit_type >= 0) + u(6, nal_unit_type, expected_nal_unit_type, + expected_nal_unit_type); + else + u(6, nal_unit_type, 0, 63); + + u(6, nuh_layer_id, 0, 62); + u(3, nuh_temporal_id_plus1, 1, 7); + + return 0; +} + +static int FUNC(byte_alignment)(CodedBitstreamContext *ctx, RWContext *rw) +{ + int err; + av_unused int one = 1, zero = 0; + xu(1, alignment_bit_equal_to_one, one, 1, 1); + while (byte_alignment(rw) != 0) + xu(1, alignment_bit_equal_to_zero, zero, 0, 0); + + return 0; +} + +static int FUNC(extension_data)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawPSExtensionData *current) +{ + int err; + size_t k; +#ifdef READ + BitstreamContext start; + uint8_t bit; + start = *rw; + for (k = 0; cbs_h2645_read_more_rbsp_data(rw); k++); + current->bit_length = k; + if (k > 0) { + *rw = start; + allocate(current->data, (current->bit_length + 7) / 8); + for (k = 0; k < current->bit_length; k++) { + xu(1, extension_data, bit, 0, 1); + current->data[k / 8] |= bit << (7 - k % 8); + } + } +#else + for (k = 0; k < current->bit_length; k++) + xu(1, extension_data, current->data[k / 8] >> (7 - k % 8), 0, 1); +#endif + return 0; +} + +static int FUNC(profile_tier_level)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawProfileTierLevel *current, + int profile_present_flag, + int max_num_sub_layers_minus1) +{ + av_unused unsigned int zero = 0; + int err, i, j; + + if (profile_present_flag) { + u(2, general_profile_space, 0, 0); + flag(general_tier_flag); + u(5, general_profile_idc, 0, 31); + + for (j = 0; j < 32; j++) + flag(general_profile_compatibility_flag[j]); + + flag(general_progressive_source_flag); + flag(general_interlaced_source_flag); + flag(general_non_packed_constraint_flag); + flag(general_frame_only_constraint_flag); + +#define profile_compatible(x) (current->general_profile_idc == (x) || \ + current->general_profile_compatibility_flag[x]) + if (profile_compatible(4) || profile_compatible(5) || + profile_compatible(6) || profile_compatible(7) || + profile_compatible(8) || profile_compatible(9) || + profile_compatible(10)) { + flag(general_max_12bit_constraint_flag); + flag(general_max_10bit_constraint_flag); + flag(general_max_8bit_constraint_flag); + flag(general_max_422chroma_constraint_flag); + flag(general_max_420chroma_constraint_flag); + flag(general_max_monochrome_constraint_flag); + flag(general_intra_constraint_flag); + flag(general_one_picture_only_constraint_flag); + flag(general_lower_bit_rate_constraint_flag); + + if (profile_compatible(5) || profile_compatible(9) || + profile_compatible(10)) { + flag(general_max_14bit_constraint_flag); + xu(24, general_reserved_zero_33bits, zero, 0, 0); + xu(9, general_reserved_zero_33bits, zero, 0, 0); + } else { + xu(24, general_reserved_zero_34bits, zero, 0, 0); + xu(10, general_reserved_zero_34bits, zero, 0, 0); + } + } else { + xu(24, general_reserved_zero_43bits, zero, 0, 0); + xu(19, general_reserved_zero_43bits, zero, 0, 0); + } + + if (profile_compatible(1) || profile_compatible(2) || + profile_compatible(3) || profile_compatible(4) || + profile_compatible(5) || profile_compatible(9)) { + flag(general_inbld_flag); + } else { + xu(1, general_reserved_zero_bit, zero, 0, 0); + } +#undef profile_compatible + } + + u(8, general_level_idc, 0, 255); + + for (i = 0; i < max_num_sub_layers_minus1; i++) { + flag(sub_layer_profile_present_flag[i]); + flag(sub_layer_level_present_flag[i]); + } + + if (max_num_sub_layers_minus1 > 0) { + for (i = max_num_sub_layers_minus1; i < 8; i++) { + av_unused int zero = 0; + xu(2, reserved_zero_2bits, zero, 0, 0); + } + } + + for (i = 0; i < max_num_sub_layers_minus1; i++) { + if (current->sub_layer_profile_present_flag[i]) + return AVERROR_PATCHWELCOME; + if (current->sub_layer_level_present_flag[i]) + return AVERROR_PATCHWELCOME; + } + + return 0; +} + +static int FUNC(sub_layer_hrd_parameters)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawHRDParameters *hrd, + int nal, int sub_layer_id) +{ + H265RawSubLayerHRDParameters *current; + int err, i; + + if (nal) + current = &hrd->nal_sub_layer_hrd_parameters[sub_layer_id]; + else + current = &hrd->vcl_sub_layer_hrd_parameters[sub_layer_id]; + + for (i = 0; i <= hrd->cpb_cnt_minus1[sub_layer_id]; i++) { + ue(bit_rate_value_minus1[i], 0, UINT32_MAX - 1); + ue(cpb_size_value_minus1[i], 0, UINT32_MAX - 1); + if (hrd->sub_pic_hrd_params_present_flag) { + ue(cpb_size_du_value_minus1[i], 0, UINT32_MAX - 1); + ue(bit_rate_du_value_minus1[i], 0, UINT32_MAX - 1); + } + flag(cbr_flag[i]); + } + + return 0; +} + +static int FUNC(hrd_parameters)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawHRDParameters *current, int common_inf_present_flag, + int max_num_sub_layers_minus1) +{ + int err, i; + + if (common_inf_present_flag) { + flag(nal_hrd_parameters_present_flag); + flag(vcl_hrd_parameters_present_flag); + + if (current->nal_hrd_parameters_present_flag || + current->vcl_hrd_parameters_present_flag) { + flag(sub_pic_hrd_params_present_flag); + if (current->sub_pic_hrd_params_present_flag) { + u(8, tick_divisor_minus2, 0, 255); + u(5, du_cpb_removal_delay_increment_length_minus1, 0, 31); + flag(sub_pic_cpb_params_in_pic_timing_sei_flag); + u(5, dpb_output_delay_du_length_minus1, 0, 31); + } + + u(4, bit_rate_scale, 0, 15); + u(4, cpb_size_scale, 0, 15); + if (current->sub_pic_hrd_params_present_flag) + u(4, cpb_size_du_scale, 0, 15); + + u(5, initial_cpb_removal_delay_length_minus1, 0, 31); + u(5, au_cpb_removal_delay_length_minus1, 0, 31); + u(5, dpb_output_delay_length_minus1, 0, 31); + } else { + infer(sub_pic_hrd_params_present_flag, 0); + + infer(initial_cpb_removal_delay_length_minus1, 23); + infer(au_cpb_removal_delay_length_minus1, 23); + infer(dpb_output_delay_length_minus1, 23); + } + } + + for (i = 0; i <= max_num_sub_layers_minus1; i++) { + flag(fixed_pic_rate_general_flag[i]); + + if (!current->fixed_pic_rate_general_flag[i]) + flag(fixed_pic_rate_within_cvs_flag[i]); + else + infer(fixed_pic_rate_within_cvs_flag[i], 1); + + if (current->fixed_pic_rate_within_cvs_flag[i]) { + ue(elemental_duration_in_tc_minus1[i], 0, 2047); + infer(low_delay_hrd_flag[i], 0); + } else + flag(low_delay_hrd_flag[i]); + + if (!current->low_delay_hrd_flag[i]) + ue(cpb_cnt_minus1[i], 0, 31); + else + infer(cpb_cnt_minus1[i], 0); + + if (current->nal_hrd_parameters_present_flag) + CHECK(FUNC(sub_layer_hrd_parameters)(ctx, rw, current, 0, i)); + if (current->vcl_hrd_parameters_present_flag) + CHECK(FUNC(sub_layer_hrd_parameters)(ctx, rw, current, 1, i)); + } + + return 0; +} + +static int FUNC(vui_parameters)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawVUI *current, const H265RawSPS *sps) +{ + int err; + + flag(aspect_ratio_info_present_flag); + if (current->aspect_ratio_info_present_flag) { + u(8, aspect_ratio_idc, 0, 255); + if (current->aspect_ratio_idc == 255) { + u(16, sar_width, 0, 65535); + u(16, sar_height, 0, 65535); + } + } else { + infer(aspect_ratio_idc, 0); + } + + flag(overscan_info_present_flag); + if (current->overscan_info_present_flag) + flag(overscan_appropriate_flag); + + flag(video_signal_type_present_flag); + if (current->video_signal_type_present_flag) { + u(3, video_format, 0, 7); + flag(video_full_range_flag); + flag(colour_description_present_flag); + if (current->colour_description_present_flag) { + u(8, colour_primaries, 0, 255); + u(8, transfer_characteristics, 0, 255); + u(8, matrix_coefficients, 0, 255); + } else { + infer(colour_primaries, 2); + infer(transfer_characteristics, 2); + infer(matrix_coefficients, 2); + } + } else { + infer(video_format, 5); + infer(video_full_range_flag, 0); + infer(colour_primaries, 2); + infer(transfer_characteristics, 2); + infer(matrix_coefficients, 2); + } + + flag(chroma_loc_info_present_flag); + if (current->chroma_loc_info_present_flag) { + ue(chroma_sample_loc_type_top_field, 0, 5); + ue(chroma_sample_loc_type_bottom_field, 0, 5); + } else { + infer(chroma_sample_loc_type_top_field, 0); + infer(chroma_sample_loc_type_bottom_field, 0); + } + + flag(neutral_chroma_indication_flag); + flag(field_seq_flag); + flag(frame_field_info_present_flag); + + flag(default_display_window_flag); + if (current->default_display_window_flag) { + ue(def_disp_win_left_offset, 0, 16384); + ue(def_disp_win_right_offset, 0, 16384); + ue(def_disp_win_top_offset, 0, 16384); + ue(def_disp_win_bottom_offset, 0, 16384); + } + + flag(vui_timing_info_present_flag); + if (current->vui_timing_info_present_flag) { + u(32, vui_num_units_in_tick, 1, UINT32_MAX); + u(32, vui_time_scale, 1, UINT32_MAX); + flag(vui_poc_proportional_to_timing_flag); + if (current->vui_poc_proportional_to_timing_flag) + ue(vui_num_ticks_poc_diff_one_minus1, 0, UINT32_MAX - 1); + + flag(vui_hrd_parameters_present_flag); + if (current->vui_hrd_parameters_present_flag) { + CHECK(FUNC(hrd_parameters)(ctx, rw, ¤t->hrd_parameters, + 1, sps->sps_max_sub_layers_minus1)); + } + } + + flag(bitstream_restriction_flag); + if (current->bitstream_restriction_flag) { + flag(tiles_fixed_structure_flag); + flag(motion_vectors_over_pic_boundaries_flag); + flag(restricted_ref_pic_lists_flag); + ue(min_spatial_segmentation_idc, 0, 4095); + ue(max_bytes_per_pic_denom, 0, 16); + ue(max_bits_per_min_cu_denom, 0, 16); + ue(log2_max_mv_length_horizontal, 0, 16); + ue(log2_max_mv_length_vertical, 0, 16); + } else { + infer(tiles_fixed_structure_flag, 0); + infer(motion_vectors_over_pic_boundaries_flag, 1); + infer(min_spatial_segmentation_idc, 0); + infer(max_bytes_per_pic_denom, 2); + infer(max_bits_per_min_cu_denom, 1); + infer(log2_max_mv_length_horizontal, 15); + infer(log2_max_mv_length_vertical, 15); + } + + return 0; +} + +static int FUNC(vps)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawVPS *current) +{ + int err, i, j; + + HEADER("Video Parameter Set"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, HEVC_NAL_VPS)); + + u(4, vps_video_parameter_set_id, 0, 15); + + flag(vps_base_layer_internal_flag); + flag(vps_base_layer_available_flag); + u(6, vps_max_layers_minus1, 0, HEVC_MAX_LAYERS - 1); + u(3, vps_max_sub_layers_minus1, 0, HEVC_MAX_SUB_LAYERS - 1); + flag(vps_temporal_id_nesting_flag); + + if (current->vps_max_sub_layers_minus1 == 0 && + current->vps_temporal_id_nesting_flag != 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid stream: " + "vps_temporal_id_nesting_flag must be 1 if " + "vps_max_sub_layers_minus1 is 0.\n"); + return AVERROR_INVALIDDATA; + } + + { + av_unused uint16_t ffff = 0xffff; + xu(16, vps_reserved_0xffff_16bits, ffff, 0xffff, 0xffff); + } + + CHECK(FUNC(profile_tier_level)(ctx, rw, ¤t->profile_tier_level, + 1, current->vps_max_sub_layers_minus1)); + + flag(vps_sub_layer_ordering_info_present_flag); + for (i = (current->vps_sub_layer_ordering_info_present_flag ? + 0 : current->vps_max_sub_layers_minus1); + i <= current->vps_max_sub_layers_minus1; i++) { + ue(vps_max_dec_pic_buffering_minus1[i], 0, HEVC_MAX_DPB_SIZE - 1); + ue(vps_max_num_reorder_pics[i], 0, current->vps_max_dec_pic_buffering_minus1[i]); + ue(vps_max_latency_increase_plus1[i], 0, UINT32_MAX - 1); + } + if (!current->vps_sub_layer_ordering_info_present_flag) { + for (i = 0; i < current->vps_max_sub_layers_minus1; i++) { + infer(vps_max_dec_pic_buffering_minus1[i], + current->vps_max_dec_pic_buffering_minus1[current->vps_max_sub_layers_minus1]); + infer(vps_max_num_reorder_pics[i], + current->vps_max_num_reorder_pics[current->vps_max_sub_layers_minus1]); + infer(vps_max_latency_increase_plus1[i], + current->vps_max_latency_increase_plus1[current->vps_max_sub_layers_minus1]); + } + } + + u(6, vps_max_layer_id, 0, HEVC_MAX_LAYERS - 1); + ue(vps_num_layer_sets_minus1, 0, HEVC_MAX_LAYER_SETS - 1); + for (i = 1; i <= current->vps_num_layer_sets_minus1; i++) { + for (j = 0; j <= current->vps_max_layer_id; j++) + flag(layer_id_included_flag[i][j]); + } + for (j = 0; j <= current->vps_max_layer_id; j++) + infer(layer_id_included_flag[0][j], j == 0); + + flag(vps_timing_info_present_flag); + if (current->vps_timing_info_present_flag) { + u(32, vps_num_units_in_tick, 1, UINT32_MAX); + u(32, vps_time_scale, 1, UINT32_MAX); + flag(vps_poc_proportional_to_timing_flag); + if (current->vps_poc_proportional_to_timing_flag) + ue(vps_num_ticks_poc_diff_one_minus1, 0, UINT32_MAX - 1); + ue(vps_num_hrd_parameters, 0, current->vps_num_layer_sets_minus1 + 1); + for (i = 0; i < current->vps_num_hrd_parameters; i++) { + ue(hrd_layer_set_idx[i], + current->vps_base_layer_internal_flag ? 0 : 1, + current->vps_num_layer_sets_minus1); + if (i > 0) + flag(cprms_present_flag[i]); + else + infer(cprms_present_flag[0], 1); + + CHECK(FUNC(hrd_parameters)(ctx, rw, ¤t->hrd_parameters[i], + current->cprms_present_flag[i], + current->vps_max_sub_layers_minus1)); + } + } + + flag(vps_extension_flag); + if (current->vps_extension_flag) + CHECK(FUNC(extension_data)(ctx, rw, ¤t->extension_data)); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(st_ref_pic_set)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSTRefPicSet *current, int st_rps_idx, + const H265RawSPS *sps) +{ + int err, i, j; + + if (st_rps_idx != 0) + flag(inter_ref_pic_set_prediction_flag); + else + infer(inter_ref_pic_set_prediction_flag, 0); + + if (current->inter_ref_pic_set_prediction_flag) { + unsigned int ref_rps_idx, num_delta_pocs; + const H265RawSTRefPicSet *ref; + int delta_rps, d_poc; + int ref_delta_poc_s0[HEVC_MAX_REFS], ref_delta_poc_s1[HEVC_MAX_REFS]; + int delta_poc_s0[HEVC_MAX_REFS], delta_poc_s1[HEVC_MAX_REFS]; + uint8_t used_by_curr_pic_s0[HEVC_MAX_REFS], + used_by_curr_pic_s1[HEVC_MAX_REFS]; + + if (st_rps_idx == sps->num_short_term_ref_pic_sets) + ue(delta_idx_minus1, 0, st_rps_idx - 1); + else + infer(delta_idx_minus1, 0); + + ref_rps_idx = st_rps_idx - (current->delta_idx_minus1 + 1); + ref = &sps->st_ref_pic_set[ref_rps_idx]; + num_delta_pocs = ref->num_negative_pics + ref->num_positive_pics; + + flag(delta_rps_sign); + ue(abs_delta_rps_minus1, 0, INT16_MAX); + delta_rps = (1 - 2 * current->delta_rps_sign) * + (current->abs_delta_rps_minus1 + 1); + + for (j = 0; j <= num_delta_pocs; j++) { + flag(used_by_curr_pic_flag[j]); + if (!current->used_by_curr_pic_flag[j]) + flag(use_delta_flag[j]); + else + infer(use_delta_flag[j], 1); + } + + // Since the stored form of an RPS here is actually the delta-step + // form used when inter_ref_pic_set_prediction_flag is not set, we + // need to reconstruct that here in order to be able to refer to + // the RPS later (which is required for parsing, because we don't + // even know what syntax elements appear without it). Therefore, + // this code takes the delta-step form of the reference set, turns + // it into the delta-array form, applies the prediction process of + // 7.4.8, converts the result back to the delta-step form, and + // stores that as the current set for future use. Note that the + // inferences here mean that writers using prediction will need + // to fill in the delta-step values correctly as well - since the + // whole RPS prediction process is somewhat overly sophisticated, + // this hopefully forms a useful check for them to ensure their + // predicted form actually matches what was intended rather than + // an onerous additional requirement. + + d_poc = 0; + for (i = 0; i < ref->num_negative_pics; i++) { + d_poc -= ref->delta_poc_s0_minus1[i] + 1; + ref_delta_poc_s0[i] = d_poc; + } + d_poc = 0; + for (i = 0; i < ref->num_positive_pics; i++) { + d_poc += ref->delta_poc_s1_minus1[i] + 1; + ref_delta_poc_s1[i] = d_poc; + } + + i = 0; + for (j = ref->num_positive_pics - 1; j >= 0; j--) { + d_poc = ref_delta_poc_s1[j] + delta_rps; + if (d_poc < 0 && current->use_delta_flag[ref->num_negative_pics + j]) { + delta_poc_s0[i] = d_poc; + used_by_curr_pic_s0[i++] = + current->used_by_curr_pic_flag[ref->num_negative_pics + j]; + } + } + if (delta_rps < 0 && current->use_delta_flag[num_delta_pocs]) { + delta_poc_s0[i] = delta_rps; + used_by_curr_pic_s0[i++] = + current->used_by_curr_pic_flag[num_delta_pocs]; + } + for (j = 0; j < ref->num_negative_pics; j++) { + d_poc = ref_delta_poc_s0[j] + delta_rps; + if (d_poc < 0 && current->use_delta_flag[j]) { + delta_poc_s0[i] = d_poc; + used_by_curr_pic_s0[i++] = current->used_by_curr_pic_flag[j]; + } + } + + infer(num_negative_pics, i); + for (i = 0; i < current->num_negative_pics; i++) { + infer(delta_poc_s0_minus1[i], + -(delta_poc_s0[i] - (i == 0 ? 0 : delta_poc_s0[i - 1])) - 1); + infer(used_by_curr_pic_s0_flag[i], used_by_curr_pic_s0[i]); + } + + i = 0; + for (j = ref->num_negative_pics - 1; j >= 0; j--) { + d_poc = ref_delta_poc_s0[j] + delta_rps; + if (d_poc > 0 && current->use_delta_flag[j]) { + delta_poc_s1[i] = d_poc; + used_by_curr_pic_s1[i++] = current->used_by_curr_pic_flag[j]; + } + } + if (delta_rps > 0 && current->use_delta_flag[num_delta_pocs]) { + delta_poc_s1[i] = delta_rps; + used_by_curr_pic_s1[i++] = + current->used_by_curr_pic_flag[num_delta_pocs]; + } + for (j = 0; j < ref->num_positive_pics; j++) { + d_poc = ref_delta_poc_s1[j] + delta_rps; + if (d_poc > 0 && current->use_delta_flag[ref->num_negative_pics + j]) { + delta_poc_s1[i] = d_poc; + used_by_curr_pic_s1[i++] = + current->used_by_curr_pic_flag[ref->num_negative_pics + j]; + } + } + + infer(num_positive_pics, i); + for (i = 0; i < current->num_positive_pics; i++) { + infer(delta_poc_s1_minus1[i], + delta_poc_s1[i] - (i == 0 ? 0 : delta_poc_s1[i - 1]) - 1); + infer(used_by_curr_pic_s1_flag[i], used_by_curr_pic_s1[i]); + } + + } else { + ue(num_negative_pics, 0, 15); + ue(num_positive_pics, 0, 15 - current->num_negative_pics); + + for (i = 0; i < current->num_negative_pics; i++) { + ue(delta_poc_s0_minus1[i], 0, INT16_MAX); + flag(used_by_curr_pic_s0_flag[i]); + } + + for (i = 0; i < current->num_positive_pics; i++) { + ue(delta_poc_s1_minus1[i], 0, INT16_MAX); + flag(used_by_curr_pic_s1_flag[i]); + } + } + + return 0; +} + +static int FUNC(scaling_list_data)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawScalingList *current) +{ + int sizeId, matrixId; + int err, n, i; + + for (sizeId = 0; sizeId < 4; sizeId++) { + for (matrixId = 0; matrixId < 6; matrixId += (sizeId == 3 ? 3 : 1)) { + flag(scaling_list_pred_mode_flag[sizeId][matrixId]); + if (!current->scaling_list_pred_mode_flag[sizeId][matrixId]) { + ue(scaling_list_pred_matrix_id_delta[sizeId][matrixId], + 0, sizeId == 3 ? matrixId / 3 : matrixId); + } else { + n = FFMIN(64, 1 << (4 + (sizeId << 1))); + if (sizeId > 1) + se(scaling_list_dc_coef_minus8[sizeId - 2][matrixId], -7, +247); + for (i = 0; i < n; i++) { + xse(scaling_list_delta_coeff, + current->scaling_list_delta_coeff[sizeId][matrixId][i], + -128, +127); + } + } + } + } + + return 0; +} + +static int FUNC(sps_range_extension)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSPS *current) +{ + int err; + + flag(transform_skip_rotation_enabled_flag); + flag(transform_skip_context_enabled_flag); + flag(implicit_rdpcm_enabled_flag); + flag(explicit_rdpcm_enabled_flag); + flag(extended_precision_processing_flag); + flag(intra_smoothing_disabled_flag); + flag(high_precision_offsets_enabled_flag); + flag(persistent_rice_adaptation_enabled_flag); + flag(cabac_bypass_alignment_enabled_flag); + + return 0; +} + +static int FUNC(sps_scc_extension)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSPS *current) +{ + int err, comp, i; + + flag(sps_curr_pic_ref_enabled_flag); + + flag(palette_mode_enabled_flag); + if (current->palette_mode_enabled_flag) { + ue(palette_max_size, 0, 64); + ue(delta_palette_max_predictor_size, 0, 128); + + flag(sps_palette_predictor_initializer_present_flag); + if (current->sps_palette_predictor_initializer_present_flag) { + ue(sps_num_palette_predictor_initializer_minus1, 0, 128); + for (comp = 0; comp < (current->chroma_format_idc ? 3 : 1); comp++) { + int bit_depth = comp == 0 ? current->bit_depth_luma_minus8 + 8 + : current->bit_depth_chroma_minus8 + 8; + for (i = 0; i <= current->sps_num_palette_predictor_initializer_minus1; i++) + u(bit_depth, sps_palette_predictor_initializers[comp][i], + 0, (1 << bit_depth) - 1); + } + } + } + + u(2, motion_vector_resolution_control_idc, 0, 2); + flag(intra_boundary_filtering_disable_flag); + + return 0; +} + +static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSPS *current) +{ + CodedBitstreamH265Context *h265 = ctx->priv_data; + const H265RawVPS *vps; + int err, i; + unsigned int min_cb_log2_size_y, ctb_log2_size_y, + min_cb_size_y, min_tb_log2_size_y; + + HEADER("Sequence Parameter Set"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, HEVC_NAL_SPS)); + + u(4, sps_video_parameter_set_id, 0, 15); + h265->active_vps = vps = h265->vps[current->sps_video_parameter_set_id]; + + u(3, sps_max_sub_layers_minus1, 0, HEVC_MAX_SUB_LAYERS - 1); + flag(sps_temporal_id_nesting_flag); + if (vps) { + if (vps->vps_max_sub_layers_minus1 > current->sps_max_sub_layers_minus1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid stream: " + "sps_max_sub_layers_minus1 (%d) must be less than or equal to " + "vps_max_sub_layers_minus1 (%d).\n", + vps->vps_max_sub_layers_minus1, + current->sps_max_sub_layers_minus1); + return AVERROR_INVALIDDATA; + } + if (vps->vps_temporal_id_nesting_flag && + !current->sps_temporal_id_nesting_flag) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid stream: " + "sps_temporal_id_nesting_flag must be 1 if " + "vps_temporal_id_nesting_flag is 1.\n"); + return AVERROR_INVALIDDATA; + } + } + + CHECK(FUNC(profile_tier_level)(ctx, rw, ¤t->profile_tier_level, + 1, current->sps_max_sub_layers_minus1)); + + ue(sps_seq_parameter_set_id, 0, 15); + + ue(chroma_format_idc, 0, 3); + if (current->chroma_format_idc == 3) + flag(separate_colour_plane_flag); + else + infer(separate_colour_plane_flag, 0); + + ue(pic_width_in_luma_samples, 1, HEVC_MAX_WIDTH); + ue(pic_height_in_luma_samples, 1, HEVC_MAX_HEIGHT); + + flag(conformance_window_flag); + if (current->conformance_window_flag) { + ue(conf_win_left_offset, 0, current->pic_width_in_luma_samples); + ue(conf_win_right_offset, 0, current->pic_width_in_luma_samples); + ue(conf_win_top_offset, 0, current->pic_height_in_luma_samples); + ue(conf_win_bottom_offset, 0, current->pic_height_in_luma_samples); + } else { + infer(conf_win_left_offset, 0); + infer(conf_win_right_offset, 0); + infer(conf_win_top_offset, 0); + infer(conf_win_bottom_offset, 0); + } + + ue(bit_depth_luma_minus8, 0, 8); + ue(bit_depth_chroma_minus8, 0, 8); + + ue(log2_max_pic_order_cnt_lsb_minus4, 0, 12); + + flag(sps_sub_layer_ordering_info_present_flag); + for (i = (current->sps_sub_layer_ordering_info_present_flag ? + 0 : current->sps_max_sub_layers_minus1); + i <= current->sps_max_sub_layers_minus1; i++) { + ue(sps_max_dec_pic_buffering_minus1[i], 0, HEVC_MAX_DPB_SIZE - 1); + ue(sps_max_num_reorder_pics[i], 0, current->sps_max_dec_pic_buffering_minus1[i]); + ue(sps_max_latency_increase_plus1[i], 0, UINT32_MAX - 1); + } + if (!current->sps_sub_layer_ordering_info_present_flag) { + for (i = 0; i < current->sps_max_sub_layers_minus1; i++) { + infer(sps_max_dec_pic_buffering_minus1[i], + current->sps_max_dec_pic_buffering_minus1[current->sps_max_sub_layers_minus1]); + infer(sps_max_num_reorder_pics[i], + current->sps_max_num_reorder_pics[current->sps_max_sub_layers_minus1]); + infer(sps_max_latency_increase_plus1[i], + current->sps_max_latency_increase_plus1[current->sps_max_sub_layers_minus1]); + } + } + + ue(log2_min_luma_coding_block_size_minus3, 0, 3); + min_cb_log2_size_y = current->log2_min_luma_coding_block_size_minus3 + 3; + + ue(log2_diff_max_min_luma_coding_block_size, 0, 3); + ctb_log2_size_y = min_cb_log2_size_y + + current->log2_diff_max_min_luma_coding_block_size; + + min_cb_size_y = 1 << min_cb_log2_size_y; + if (current->pic_width_in_luma_samples % min_cb_size_y || + current->pic_height_in_luma_samples % min_cb_size_y) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid dimensions: %ux%u not divisible " + "by MinCbSizeY = %u.\n", current->pic_width_in_luma_samples, + current->pic_height_in_luma_samples, min_cb_size_y); + return AVERROR_INVALIDDATA; + } + + ue(log2_min_luma_transform_block_size_minus2, 0, min_cb_log2_size_y - 3); + min_tb_log2_size_y = current->log2_min_luma_transform_block_size_minus2 + 2; + + ue(log2_diff_max_min_luma_transform_block_size, + 0, FFMIN(ctb_log2_size_y, 5) - min_tb_log2_size_y); + + ue(max_transform_hierarchy_depth_inter, + 0, ctb_log2_size_y - min_tb_log2_size_y); + ue(max_transform_hierarchy_depth_intra, + 0, ctb_log2_size_y - min_tb_log2_size_y); + + flag(scaling_list_enabled_flag); + if (current->scaling_list_enabled_flag) { + flag(sps_scaling_list_data_present_flag); + if (current->sps_scaling_list_data_present_flag) + CHECK(FUNC(scaling_list_data)(ctx, rw, ¤t->scaling_list)); + } else { + infer(sps_scaling_list_data_present_flag, 0); + } + + flag(amp_enabled_flag); + flag(sample_adaptive_offset_enabled_flag); + + flag(pcm_enabled_flag); + if (current->pcm_enabled_flag) { + u(4, pcm_sample_bit_depth_luma_minus1, + 0, current->bit_depth_luma_minus8 + 8 - 1); + u(4, pcm_sample_bit_depth_chroma_minus1, + 0, current->bit_depth_chroma_minus8 + 8 - 1); + + ue(log2_min_pcm_luma_coding_block_size_minus3, + FFMIN(min_cb_log2_size_y, 5) - 3, FFMIN(ctb_log2_size_y, 5) - 3); + ue(log2_diff_max_min_pcm_luma_coding_block_size, + 0, FFMIN(ctb_log2_size_y, 5) - (current->log2_min_pcm_luma_coding_block_size_minus3 + 3)); + + flag(pcm_loop_filter_disabled_flag); + } + + ue(num_short_term_ref_pic_sets, 0, HEVC_MAX_SHORT_TERM_REF_PIC_SETS); + for (i = 0; i < current->num_short_term_ref_pic_sets; i++) + CHECK(FUNC(st_ref_pic_set)(ctx, rw, ¤t->st_ref_pic_set[i], i, current)); + + flag(long_term_ref_pics_present_flag); + if (current->long_term_ref_pics_present_flag) { + ue(num_long_term_ref_pics_sps, 0, HEVC_MAX_LONG_TERM_REF_PICS); + for (i = 0; i < current->num_long_term_ref_pics_sps; i++) { + u(current->log2_max_pic_order_cnt_lsb_minus4 + 4, + lt_ref_pic_poc_lsb_sps[i], + 0, (1 << (current->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1); + flag(used_by_curr_pic_lt_sps_flag[i]); + } + } + + flag(sps_temporal_mvp_enabled_flag); + flag(strong_intra_smoothing_enabled_flag); + + flag(vui_parameters_present_flag); + if (current->vui_parameters_present_flag) + CHECK(FUNC(vui_parameters)(ctx, rw, ¤t->vui, current)); + + flag(sps_extension_present_flag); + if (current->sps_extension_present_flag) { + flag(sps_range_extension_flag); + flag(sps_multilayer_extension_flag); + flag(sps_3d_extension_flag); + flag(sps_scc_extension_flag); + u(4, sps_extension_4bits, 0, (1 << 4) - 1); + } + + if (current->sps_range_extension_flag) + CHECK(FUNC(sps_range_extension)(ctx, rw, current)); + if (current->sps_multilayer_extension_flag) + return AVERROR_PATCHWELCOME; + if (current->sps_3d_extension_flag) + return AVERROR_PATCHWELCOME; + if (current->sps_scc_extension_flag) + CHECK(FUNC(sps_scc_extension)(ctx, rw, current)); + if (current->sps_extension_4bits) + CHECK(FUNC(extension_data)(ctx, rw, ¤t->extension_data)); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(pps_range_extension)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawPPS *current) +{ + CodedBitstreamH265Context *h265 = ctx->priv_data; + const H265RawSPS *sps = h265->active_sps; + int err, i; + + if (current->transform_skip_enabled_flag) + ue(log2_max_transform_skip_block_size_minus2, 0, 4); + flag(cross_component_prediction_enabled_flag); + + flag(chroma_qp_offset_list_enabled_flag); + if (current->chroma_qp_offset_list_enabled_flag) { + ue(diff_cu_chroma_qp_offset_depth, + 0, sps->log2_diff_max_min_luma_coding_block_size); + ue(chroma_qp_offset_list_len_minus1, 0, 5); + for (i = 0; i <= current->chroma_qp_offset_list_len_minus1; i++) { + se(cb_qp_offset_list[i], -12, +12); + se(cr_qp_offset_list[i], -12, +12); + } + } + + ue(log2_sao_offset_scale_luma, 0, FFMAX(0, sps->bit_depth_luma_minus8 - 2)); + ue(log2_sao_offset_scale_chroma, 0, FFMAX(0, sps->bit_depth_chroma_minus8 - 2)); + + return 0; +} + +static int FUNC(pps_scc_extension)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawPPS *current) +{ + int err, comp, i; + + flag(pps_curr_pic_ref_enabled_flag); + + flag(residual_adaptive_colour_transform_enabled_flag); + if (current->residual_adaptive_colour_transform_enabled_flag) { + flag(pps_slice_act_qp_offsets_present_flag); + se(pps_act_y_qp_offset_plus5, -7, +17); + se(pps_act_cb_qp_offset_plus5, -7, +17); + se(pps_act_cr_qp_offset_plus3, -9, +15); + } else { + infer(pps_slice_act_qp_offsets_present_flag, 0); + infer(pps_act_y_qp_offset_plus5, 0); + infer(pps_act_cb_qp_offset_plus5, 0); + infer(pps_act_cr_qp_offset_plus3, 0); + } + + flag(pps_palette_predictor_initializer_present_flag); + if (current->pps_palette_predictor_initializer_present_flag) { + ue(pps_num_palette_predictor_initializer, 0, 128); + if (current->pps_num_palette_predictor_initializer > 0) { + flag(monochrome_palette_flag); + ue(luma_bit_depth_entry_minus8, 0, 8); + if (!current->monochrome_palette_flag) + ue(chroma_bit_depth_entry_minus8, 0, 8); + for (comp = 0; comp < (current->monochrome_palette_flag ? 1 : 3); comp++) { + int bit_depth = comp == 0 ? current->luma_bit_depth_entry_minus8 + 8 + : current->chroma_bit_depth_entry_minus8 + 8; + for (i = 0; i < current->pps_num_palette_predictor_initializer; i++) + u(bit_depth, pps_palette_predictor_initializers[comp][i], + 0, (1 << bit_depth) - 1); + } + } + } + + return 0; +} + +static int FUNC(pps)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawPPS *current) +{ + CodedBitstreamH265Context *h265 = ctx->priv_data; + const H265RawSPS *sps; + int err, i; + + HEADER("Picture Parameter Set"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, HEVC_NAL_PPS)); + + ue(pps_pic_parameter_set_id, 0, 63); + ue(pps_seq_parameter_set_id, 0, 15); + sps = h265->sps[current->pps_seq_parameter_set_id]; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SPS id %d not available.\n", + current->pps_seq_parameter_set_id); + return AVERROR_INVALIDDATA; + } + h265->active_sps = sps; + + flag(dependent_slice_segments_enabled_flag); + flag(output_flag_present_flag); + u(3, num_extra_slice_header_bits, 0, 7); + flag(sign_data_hiding_enabled_flag); + flag(cabac_init_present_flag); + + ue(num_ref_idx_l0_default_active_minus1, 0, 14); + ue(num_ref_idx_l1_default_active_minus1, 0, 14); + + se(init_qp_minus26, -(26 + 6 * sps->bit_depth_luma_minus8), +25); + + flag(constrained_intra_pred_flag); + flag(transform_skip_enabled_flag); + flag(cu_qp_delta_enabled_flag); + if (current->cu_qp_delta_enabled_flag) + ue(diff_cu_qp_delta_depth, + 0, sps->log2_diff_max_min_luma_coding_block_size); + else + infer(diff_cu_qp_delta_depth, 0); + + se(pps_cb_qp_offset, -12, +12); + se(pps_cr_qp_offset, -12, +12); + flag(pps_slice_chroma_qp_offsets_present_flag); + + flag(weighted_pred_flag); + flag(weighted_bipred_flag); + + flag(transquant_bypass_enabled_flag); + flag(tiles_enabled_flag); + flag(entropy_coding_sync_enabled_flag); + + if (current->tiles_enabled_flag) { + ue(num_tile_columns_minus1, 0, HEVC_MAX_TILE_COLUMNS); + ue(num_tile_rows_minus1, 0, HEVC_MAX_TILE_ROWS); + flag(uniform_spacing_flag); + if (!current->uniform_spacing_flag) { + for (i = 0; i < current->num_tile_columns_minus1; i++) + ue(column_width_minus1[i], 0, sps->pic_width_in_luma_samples); + for (i = 0; i < current->num_tile_rows_minus1; i++) + ue(row_height_minus1[i], 0, sps->pic_height_in_luma_samples); + } + flag(loop_filter_across_tiles_enabled_flag); + } else { + infer(num_tile_columns_minus1, 0); + infer(num_tile_rows_minus1, 0); + } + + flag(pps_loop_filter_across_slices_enabled_flag); + flag(deblocking_filter_control_present_flag); + if (current->deblocking_filter_control_present_flag) { + flag(deblocking_filter_override_enabled_flag); + flag(pps_deblocking_filter_disabled_flag); + if (!current->pps_deblocking_filter_disabled_flag) { + se(pps_beta_offset_div2, -6, +6); + se(pps_tc_offset_div2, -6, +6); + } else { + infer(pps_beta_offset_div2, 0); + infer(pps_tc_offset_div2, 0); + } + } else { + infer(deblocking_filter_override_enabled_flag, 0); + infer(pps_deblocking_filter_disabled_flag, 0); + infer(pps_beta_offset_div2, 0); + infer(pps_tc_offset_div2, 0); + } + + flag(pps_scaling_list_data_present_flag); + if (current->pps_scaling_list_data_present_flag) + CHECK(FUNC(scaling_list_data)(ctx, rw, ¤t->scaling_list)); + + flag(lists_modification_present_flag); + + ue(log2_parallel_merge_level_minus2, + 0, (sps->log2_min_luma_coding_block_size_minus3 + 3 + + sps->log2_diff_max_min_luma_coding_block_size - 2)); + + flag(slice_segment_header_extension_present_flag); + + flag(pps_extension_present_flag); + if (current->pps_extension_present_flag) { + flag(pps_range_extension_flag); + flag(pps_multilayer_extension_flag); + flag(pps_3d_extension_flag); + flag(pps_scc_extension_flag); + u(4, pps_extension_4bits, 0, (1 << 4) - 1); + } + if (current->pps_range_extension_flag) + CHECK(FUNC(pps_range_extension)(ctx, rw, current)); + if (current->pps_multilayer_extension_flag) + return AVERROR_PATCHWELCOME; + if (current->pps_3d_extension_flag) + return AVERROR_PATCHWELCOME; + if (current->pps_scc_extension_flag) + CHECK(FUNC(pps_scc_extension)(ctx, rw, current)); + if (current->pps_extension_4bits) + CHECK(FUNC(extension_data)(ctx, rw, ¤t->extension_data)); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(aud)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawAUD *current) +{ + int err; + + HEADER("Access Unit Delimiter"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, HEVC_NAL_AUD)); + + u(3, pic_type, 0, 2); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(ref_pic_lists_modification)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSliceHeader *current, + unsigned int num_pic_total_curr) +{ + unsigned int entry_size; + int err, i; + + entry_size = av_log2(num_pic_total_curr - 1) + 1; + + flag(ref_pic_list_modification_flag_l0); + if (current->ref_pic_list_modification_flag_l0) { + for (i = 0; i <= current->num_ref_idx_l0_active_minus1; i++) + u(entry_size, list_entry_l0[i], 0, num_pic_total_curr - 1); + } + + if (current->slice_type == HEVC_SLICE_B) { + flag(ref_pic_list_modification_flag_l1); + if (current->ref_pic_list_modification_flag_l1) { + for (i = 0; i <= current->num_ref_idx_l1_active_minus1; i++) + u(entry_size, list_entry_l1[i], 0, num_pic_total_curr - 1); + } + } + + return 0; +} + +static int FUNC(pred_weight_table)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSliceHeader *current) +{ + CodedBitstreamH265Context *h265 = ctx->priv_data; + const H265RawSPS *sps = h265->active_sps; + int err, i, j; + int chroma = !sps->separate_colour_plane_flag && + sps->chroma_format_idc != 0; + + ue(luma_log2_weight_denom, 0, 7); + if (chroma) + se(delta_chroma_log2_weight_denom, -7, 7); + else + infer(delta_chroma_log2_weight_denom, 0); + + for (i = 0; i <= current->num_ref_idx_l0_active_minus1; i++) { + if (1 /* is not same POC and same layer_id */) + flag(luma_weight_l0_flag[i]); + else + infer(luma_weight_l0_flag[i], 0); + } + if (chroma) { + for (i = 0; i <= current->num_ref_idx_l0_active_minus1; i++) { + if (1 /* is not same POC and same layer_id */) + flag(chroma_weight_l0_flag[i]); + else + infer(chroma_weight_l0_flag[i], 0); + } + } + + for (i = 0; i <= current->num_ref_idx_l0_active_minus1; i++) { + if (current->luma_weight_l0_flag[i]) { + se(delta_luma_weight_l0[i], -128, +127); + se(luma_offset_l0[i], + -(1 << (sps->bit_depth_luma_minus8 + 8 - 1)), + +(1 << (sps->bit_depth_luma_minus8 + 8 - 1) - 1)); + } else { + infer(delta_luma_weight_l0[i], 0); + infer(luma_offset_l0[i], 0); + } + if (current->chroma_weight_l0_flag[i]) { + for (j = 0; j < 2; j++) { + se(delta_chroma_weight_l0[i][j], -128, +127); + se(chroma_offset_l0[i][j], + -(4 << (sps->bit_depth_chroma_minus8 + 8 - 1)), + +(4 << (sps->bit_depth_chroma_minus8 + 8 - 1) - 1)); + } + } else { + for (j = 0; j < 2; j++) { + infer(delta_chroma_weight_l0[i][j], 0); + infer(chroma_offset_l0[i][j], 0); + } + } + } + + if (current->slice_type == HEVC_SLICE_B) { + for (i = 0; i <= current->num_ref_idx_l1_active_minus1; i++) { + if (1 /* RefPicList1[i] is not CurrPic, nor is it in a different layer */) + flag(luma_weight_l1_flag[i]); + else + infer(luma_weight_l1_flag[i], 0); + } + if (chroma) { + for (i = 0; i <= current->num_ref_idx_l1_active_minus1; i++) { + if (1 /* RefPicList1[i] is not CurrPic, nor is it in a different layer */) + flag(chroma_weight_l1_flag[i]); + else + infer(chroma_weight_l1_flag[i], 0); + } + } + + for (i = 0; i <= current->num_ref_idx_l1_active_minus1; i++) { + if (current->luma_weight_l1_flag[i]) { + se(delta_luma_weight_l1[i], -128, +127); + se(luma_offset_l1[i], + - 1 << (sps->bit_depth_luma_minus8 + 8 - 1), + + 1 << (sps->bit_depth_luma_minus8 + 8 - 1) - 1); + } else { + infer(delta_luma_weight_l1[i], 0); + infer(luma_offset_l1[i], 0); + } + if (current->chroma_weight_l1_flag[i]) { + for (j = 0; j < 2; j++) { + se(delta_chroma_weight_l1[i][j], -128, +127); + se(chroma_offset_l1[i][j], + - 4 << (sps->bit_depth_chroma_minus8 + 8 - 1), + + 4 << (sps->bit_depth_chroma_minus8 + 8 - 1) - 1); + } + } else { + for (j = 0; j < 2; j++) { + infer(delta_chroma_weight_l1[i][j], 0); + infer(chroma_offset_l1[i][j], 0); + } + } + } + } + + return 0; +} + +static int FUNC(slice_segment_header)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSliceHeader *current) +{ + CodedBitstreamH265Context *h265 = ctx->priv_data; + const H265RawSPS *sps; + const H265RawPPS *pps; + unsigned int min_cb_log2_size_y, ctb_log2_size_y, ctb_size_y; + unsigned int pic_width_in_ctbs_y, pic_height_in_ctbs_y, pic_size_in_ctbs_y; + unsigned int num_pic_total_curr = 0; + int err, i; + + HEADER("Slice Segment Header"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, -1)); + + flag(first_slice_segment_in_pic_flag); + + if (current->nal_unit_header.nal_unit_type >= HEVC_NAL_BLA_W_LP && + current->nal_unit_header.nal_unit_type <= HEVC_NAL_IRAP_VCL23) + flag(no_output_of_prior_pics_flag); + + ue(slice_pic_parameter_set_id, 0, 63); + + pps = h265->pps[current->slice_pic_parameter_set_id]; + if (!pps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "PPS id %d not available.\n", + current->slice_pic_parameter_set_id); + return AVERROR_INVALIDDATA; + } + h265->active_pps = pps; + + sps = h265->sps[pps->pps_seq_parameter_set_id]; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SPS id %d not available.\n", + pps->pps_seq_parameter_set_id); + return AVERROR_INVALIDDATA; + } + h265->active_sps = sps; + + min_cb_log2_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3; + ctb_log2_size_y = min_cb_log2_size_y + sps->log2_diff_max_min_luma_coding_block_size; + ctb_size_y = 1 << ctb_log2_size_y; + pic_width_in_ctbs_y = + (sps->pic_width_in_luma_samples + ctb_size_y - 1) / ctb_size_y; + pic_height_in_ctbs_y = + (sps->pic_height_in_luma_samples + ctb_size_y - 1) / ctb_size_y; + pic_size_in_ctbs_y = pic_width_in_ctbs_y * pic_height_in_ctbs_y; + + if (!current->first_slice_segment_in_pic_flag) { + unsigned int address_size = av_log2(pic_size_in_ctbs_y - 1) + 1; + if (pps->dependent_slice_segments_enabled_flag) + flag(dependent_slice_segment_flag); + else + infer(dependent_slice_segment_flag, 0); + u(address_size, slice_segment_address, 0, pic_size_in_ctbs_y - 1); + } else { + infer(dependent_slice_segment_flag, 0); + } + + if (!current->dependent_slice_segment_flag) { + for (i = 0; i < pps->num_extra_slice_header_bits; i++) + flag(slice_reserved_flag[i]); + + ue(slice_type, 0, 2); + + if (pps->output_flag_present_flag) + flag(pic_output_flag); + + if (sps->separate_colour_plane_flag) + u(2, colour_plane_id, 0, 2); + + if (current->nal_unit_header.nal_unit_type != HEVC_NAL_IDR_W_RADL && + current->nal_unit_header.nal_unit_type != HEVC_NAL_IDR_N_LP) { + const H265RawSTRefPicSet *rps; + + u(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, slice_pic_order_cnt_lsb, + 0, (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1); + + flag(short_term_ref_pic_set_sps_flag); + if (!current->short_term_ref_pic_set_sps_flag) { + CHECK(FUNC(st_ref_pic_set)(ctx, rw, ¤t->short_term_ref_pic_set, + sps->num_short_term_ref_pic_sets, sps)); + rps = ¤t->short_term_ref_pic_set; + } else if (sps->num_short_term_ref_pic_sets > 1) { + unsigned int idx_size = av_log2(sps->num_short_term_ref_pic_sets - 1) + 1; + u(idx_size, short_term_ref_pic_set_idx, + 0, sps->num_short_term_ref_pic_sets - 1); + rps = &sps->st_ref_pic_set[current->short_term_ref_pic_set_idx]; + } else { + infer(short_term_ref_pic_set_idx, 0); + rps = &sps->st_ref_pic_set[0]; + } + + num_pic_total_curr = 0; + for (i = 0; i < rps->num_negative_pics; i++) + if (rps->used_by_curr_pic_s0_flag[i]) + ++num_pic_total_curr; + for (i = 0; i < rps->num_positive_pics; i++) + if (rps->used_by_curr_pic_s1_flag[i]) + ++num_pic_total_curr; + + if (sps->long_term_ref_pics_present_flag) { + unsigned int idx_size; + + if (sps->num_long_term_ref_pics_sps > 0) { + ue(num_long_term_sps, 0, sps->num_long_term_ref_pics_sps); + idx_size = av_log2(sps->num_long_term_ref_pics_sps - 1) + 1; + } else { + infer(num_long_term_sps, 0); + idx_size = 0; + } + ue(num_long_term_pics, 0, HEVC_MAX_LONG_TERM_REF_PICS); + + for (i = 0; i < current->num_long_term_sps + + current->num_long_term_pics; i++) { + if (i < current->num_long_term_sps) { + if (sps->num_long_term_ref_pics_sps > 1) + u(idx_size, lt_idx_sps[i], + 0, sps->num_long_term_ref_pics_sps - 1); + if (sps->used_by_curr_pic_lt_sps_flag[current->lt_idx_sps[i]]) + ++num_pic_total_curr; + } else { + u(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, poc_lsb_lt[i], + 0, (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1); + flag(used_by_curr_pic_lt_flag[i]); + if (current->used_by_curr_pic_lt_flag[i]) + ++num_pic_total_curr; + } + flag(delta_poc_msb_present_flag[i]); + if (current->delta_poc_msb_present_flag[i]) + ue(delta_poc_msb_cycle_lt[i], 0, UINT32_MAX - 1); + else + infer(delta_poc_msb_cycle_lt[i], 0); + } + } + + if (sps->sps_temporal_mvp_enabled_flag) + flag(slice_temporal_mvp_enabled_flag); + else + infer(slice_temporal_mvp_enabled_flag, 0); + + if (pps->pps_curr_pic_ref_enabled_flag) + ++num_pic_total_curr; + } + + if (sps->sample_adaptive_offset_enabled_flag) { + flag(slice_sao_luma_flag); + if (!sps->separate_colour_plane_flag && sps->chroma_format_idc != 0) + flag(slice_sao_chroma_flag); + else + infer(slice_sao_chroma_flag, 0); + } else { + infer(slice_sao_luma_flag, 0); + infer(slice_sao_chroma_flag, 0); + } + + if (current->slice_type == HEVC_SLICE_P || + current->slice_type == HEVC_SLICE_B) { + flag(num_ref_idx_active_override_flag); + if (current->num_ref_idx_active_override_flag) { + ue(num_ref_idx_l0_active_minus1, 0, 14); + if (current->slice_type == HEVC_SLICE_B) + ue(num_ref_idx_l1_active_minus1, 0, 14); + else + infer(num_ref_idx_l1_active_minus1, pps->num_ref_idx_l1_default_active_minus1); + } else { + infer(num_ref_idx_l0_active_minus1, pps->num_ref_idx_l0_default_active_minus1); + infer(num_ref_idx_l1_active_minus1, pps->num_ref_idx_l1_default_active_minus1); + } + + if (pps->lists_modification_present_flag && num_pic_total_curr > 1) + CHECK(FUNC(ref_pic_lists_modification)(ctx, rw, current, + num_pic_total_curr)); + + if (current->slice_type == HEVC_SLICE_B) + flag(mvd_l1_zero_flag); + if (pps->cabac_init_present_flag) + flag(cabac_init_flag); + else + infer(cabac_init_flag, 0); + if (current->slice_temporal_mvp_enabled_flag) { + if (current->slice_type == HEVC_SLICE_B) + flag(collocated_from_l0_flag); + else + infer(collocated_from_l0_flag, 1); + if (current->collocated_from_l0_flag) { + if (current->num_ref_idx_l0_active_minus1 > 0) + ue(collocated_ref_idx, 0, current->num_ref_idx_l0_active_minus1); + else + infer(collocated_ref_idx, 0); + } else { + if (current->num_ref_idx_l1_active_minus1 > 0) + ue(collocated_ref_idx, 0, current->num_ref_idx_l1_active_minus1); + else + infer(collocated_ref_idx, 0); + } + } + + if ((pps->weighted_pred_flag && current->slice_type == HEVC_SLICE_P) || + (pps->weighted_bipred_flag && current->slice_type == HEVC_SLICE_B)) + CHECK(FUNC(pred_weight_table)(ctx, rw, current)); + + ue(five_minus_max_num_merge_cand, 0, 4); + if (sps->motion_vector_resolution_control_idc == 2) + flag(use_integer_mv_flag); + else + infer(use_integer_mv_flag, sps->motion_vector_resolution_control_idc); + } + + se(slice_qp_delta, + - 6 * sps->bit_depth_luma_minus8 - (pps->init_qp_minus26 + 26), + + 51 - (pps->init_qp_minus26 + 26)); + if (pps->pps_slice_chroma_qp_offsets_present_flag) { + se(slice_cb_qp_offset, -12, +12); + se(slice_cr_qp_offset, -12, +12); + } else { + infer(slice_cb_qp_offset, 0); + infer(slice_cr_qp_offset, 0); + } + if (pps->pps_slice_act_qp_offsets_present_flag) { + se(slice_act_y_qp_offset, + -12 - (pps->pps_act_y_qp_offset_plus5 - 5), + +12 - (pps->pps_act_y_qp_offset_plus5 - 5)); + se(slice_act_cb_qp_offset, + -12 - (pps->pps_act_cb_qp_offset_plus5 - 5), + +12 - (pps->pps_act_cb_qp_offset_plus5 - 5)); + se(slice_act_cr_qp_offset, + -12 - (pps->pps_act_cr_qp_offset_plus3 - 3), + +12 - (pps->pps_act_cr_qp_offset_plus3 - 3)); + } else { + infer(slice_act_y_qp_offset, 0); + infer(slice_act_cb_qp_offset, 0); + infer(slice_act_cr_qp_offset, 0); + } + if (pps->chroma_qp_offset_list_enabled_flag) + flag(cu_chroma_qp_offset_enabled_flag); + else + infer(cu_chroma_qp_offset_enabled_flag, 0); + + if (pps->deblocking_filter_override_enabled_flag) + flag(deblocking_filter_override_flag); + else + infer(deblocking_filter_override_flag, 0); + if (current->deblocking_filter_override_flag) { + flag(slice_deblocking_filter_disabled_flag); + if (!current->slice_deblocking_filter_disabled_flag) { + se(slice_beta_offset_div2, -6, +6); + se(slice_tc_offset_div2, -6, +6); + } else { + infer(slice_beta_offset_div2, pps->pps_beta_offset_div2); + infer(slice_tc_offset_div2, pps->pps_tc_offset_div2); + } + } else { + infer(slice_deblocking_filter_disabled_flag, + pps->pps_deblocking_filter_disabled_flag); + infer(slice_beta_offset_div2, pps->pps_beta_offset_div2); + infer(slice_tc_offset_div2, pps->pps_tc_offset_div2); + } + if (pps->pps_loop_filter_across_slices_enabled_flag && + (current->slice_sao_luma_flag || current->slice_sao_chroma_flag || + !current->slice_deblocking_filter_disabled_flag)) + flag(slice_loop_filter_across_slices_enabled_flag); + else + infer(slice_loop_filter_across_slices_enabled_flag, + pps->pps_loop_filter_across_slices_enabled_flag); + } + + if (pps->tiles_enabled_flag || pps->entropy_coding_sync_enabled_flag) { + unsigned int num_entry_point_offsets_limit; + if (!pps->tiles_enabled_flag && pps->entropy_coding_sync_enabled_flag) + num_entry_point_offsets_limit = pic_height_in_ctbs_y - 1; + else if (pps->tiles_enabled_flag && !pps->entropy_coding_sync_enabled_flag) + num_entry_point_offsets_limit = + (pps->num_tile_columns_minus1 + 1) * (pps->num_tile_rows_minus1 + 1); + else + num_entry_point_offsets_limit = + (pps->num_tile_columns_minus1 + 1) * pic_height_in_ctbs_y - 1; + ue(num_entry_point_offsets, 0, num_entry_point_offsets_limit); + + if (current->num_entry_point_offsets > HEVC_MAX_ENTRY_POINT_OFFSETS) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many entry points: " + "%"PRIu16".\n", current->num_entry_point_offsets); + return AVERROR_PATCHWELCOME; + } + + if (current->num_entry_point_offsets > 0) { + ue(offset_len_minus1, 0, 31); + for (i = 0; i < current->num_entry_point_offsets; i++) + u(current->offset_len_minus1 + 1, entry_point_offset_minus1[i], + 0, (1 << (current->offset_len_minus1 + 1)) - 1); + } + } + + if (pps->slice_segment_header_extension_present_flag) { + ue(slice_segment_header_extension_length, 0, 256); + for (i = 0; i < current->slice_segment_header_extension_length; i++) + u(8, slice_segment_header_extension_data_byte[i], 0x00, 0xff); + } + + CHECK(FUNC(byte_alignment)(ctx, rw)); + + return 0; +} diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index e87a43970f37f..0457f4ab9e1b6 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -81,6 +81,7 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc, extern const CodedBitstreamType ff_cbs_type_h264; +extern const CodedBitstreamType ff_cbs_type_h265; #endif /* AVCODEC_CBS_INTERNAL_H */ From f11d8a5e8b185340cc50fcbc8a1437b0fbe7e931 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 4 May 2017 23:06:20 +0100 Subject: [PATCH 0351/2557] lavc: Add trace_headers bitstream filter Supports all streams that the coded bitstream infrastructure does (currently H.264 and H.265). --- configure | 1 + doc/bitstream_filters.texi | 8 +++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/trace_headers_bsf.c | 125 +++++++++++++++++++++++++++++++++ 5 files changed, 136 insertions(+) create mode 100644 libavcodec/trace_headers_bsf.c diff --git a/configure b/configure index 535862fcafcec..13dd7f54e23d1 100755 --- a/configure +++ b/configure @@ -2324,6 +2324,7 @@ vc1_parser_select="vc1dsp" # bitstream_filters aac_adtstoasc_bsf_select="adts_header" mjpeg2jpeg_bsf_select="jpegtables" +trace_headers_bsf_select="cbs_h264 cbs_h265" # external libraries avisynth_deps="LoadLibrary" diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 64f91f4b5417b..119a2267af6ab 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -95,6 +95,14 @@ This bitstream filter passes the packets through unchanged. @section remove_extradata +@section trace_headers + +Log trace output containing all syntax elements in the coded stream +headers (everything above the level of individual coded blocks). +This can be useful for debugging low-level stream issues. + +Supports H.264 and H.265. + @section vp9_superframe Combine VP9 frames into superframes. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 9791fb342e4db..09772a85f7c99 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -786,6 +786,7 @@ OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o OBJS-$(CONFIG_NULL_BSF) += null_bsf.o OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o +OBJS-$(CONFIG_TRACE_HEADERS_BSF) += trace_headers_bsf.o OBJS-$(CONFIG_VP9_RAW_REORDER_BSF) += vp9_raw_reorder_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF) += vp9_superframe_split_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 79ce40f9eda2a..2e423acaf07e6 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -38,6 +38,7 @@ extern const AVBitStreamFilter ff_null_bsf; extern const AVBitStreamFilter ff_text2movsub_bsf; extern const AVBitStreamFilter ff_noise_bsf; extern const AVBitStreamFilter ff_remove_extradata_bsf; +extern const AVBitStreamFilter ff_trace_headers_bsf; extern const AVBitStreamFilter ff_vp9_raw_reorder_bsf; extern const AVBitStreamFilter ff_vp9_superframe_bsf; extern const AVBitStreamFilter ff_vp9_superframe_split_bsf; diff --git a/libavcodec/trace_headers_bsf.c b/libavcodec/trace_headers_bsf.c new file mode 100644 index 0000000000000..2d1fe636c2397 --- /dev/null +++ b/libavcodec/trace_headers_bsf.c @@ -0,0 +1,125 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/log.h" + +#include "bsf.h" +#include "cbs.h" + + +typedef struct TraceHeadersContext { + CodedBitstreamContext cbc; +} TraceHeadersContext; + + +static int trace_headers_init(AVBSFContext *bsf) +{ + TraceHeadersContext *ctx = bsf->priv_data; + int err; + + err = ff_cbs_init(&ctx->cbc, bsf->par_in->codec_id, bsf); + if (err < 0) + return err; + + ctx->cbc.trace_enable = 1; + ctx->cbc.trace_level = AV_LOG_INFO; + + if (bsf->par_in->extradata) { + CodedBitstreamFragment ps; + + av_log(bsf, AV_LOG_INFO, "Extradata\n"); + + err = ff_cbs_read_extradata(&ctx->cbc, &ps, bsf->par_in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); + return err; + } + + ff_cbs_fragment_uninit(&ctx->cbc, &ps); + } + + return 0; +} + +static void trace_headers_close(AVBSFContext *bsf) +{ + TraceHeadersContext *ctx = bsf->priv_data; + + ff_cbs_close(&ctx->cbc); +} + +static int trace_headers(AVBSFContext *bsf, AVPacket *out) +{ + TraceHeadersContext *ctx = bsf->priv_data; + CodedBitstreamFragment au; + AVPacket *in; + char tmp[256] = { 0 }; + int err; + + err = ff_bsf_get_packet(bsf, &in); + if (err < 0) + return err; + + if (in->flags & AV_PKT_FLAG_KEY) + av_strlcat(tmp, ", key frame", sizeof(tmp)); + if (in->flags & AV_PKT_FLAG_CORRUPT) + av_strlcat(tmp, ", corrupt", sizeof(tmp)); + + if (in->pts != AV_NOPTS_VALUE) + av_strlcatf(tmp, sizeof(tmp), ", pts %"PRId64, in->pts); + else + av_strlcat(tmp, ", no pts", sizeof(tmp)); + if (in->dts != AV_NOPTS_VALUE) + av_strlcatf(tmp, sizeof(tmp), ", dts %"PRId64, in->dts); + else + av_strlcat(tmp, ", no dts", sizeof(tmp)); + if (in->duration > 0) + av_strlcatf(tmp, sizeof(tmp), ", duration %"PRId64, in->duration); + + av_log(bsf, AV_LOG_INFO, "Packet: %d bytes%s.\n", in->size, tmp); + + err = ff_cbs_read_packet(&ctx->cbc, &au, in); + if (err < 0) + return err; + + ff_cbs_fragment_uninit(&ctx->cbc, &au); + + av_packet_move_ref(out, in); + av_packet_free(&in); + + return 0; +} + +static const enum AVCodecID trace_headers_codec_ids[] = { + AV_CODEC_ID_H264, + AV_CODEC_ID_HEVC, + AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_trace_headers_bsf = { + .name = "trace_headers", + .priv_data_size = sizeof(TraceHeadersContext), + .init = &trace_headers_init, + .close = &trace_headers_close, + .filter = &trace_headers, + .codec_ids = trace_headers_codec_ids, +}; From 9e93001b6135a23fe4e200196c08fb4fbffed6fc Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 4 May 2017 23:09:02 +0100 Subject: [PATCH 0352/2557] lavc: Add h264_metadata bitstream filter This is able to modify some header metadata found in the SPS/VUI, and can also add/remove AUDs and insert user data in SEI NAL units. --- configure | 1 + doc/bitstream_filters.texi | 63 ++++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/h264_metadata_bsf.c | 512 +++++++++++++++++++++++++++++++++ 5 files changed, 578 insertions(+) create mode 100644 libavcodec/h264_metadata_bsf.c diff --git a/configure b/configure index 13dd7f54e23d1..f3d616800a778 100755 --- a/configure +++ b/configure @@ -2323,6 +2323,7 @@ vc1_parser_select="vc1dsp" # bitstream_filters aac_adtstoasc_bsf_select="adts_header" +h264_metadata_bsf_select="cbs_h264" mjpeg2jpeg_bsf_select="jpegtables" trace_headers_bsf_select="cbs_h264 cbs_h265" diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 119a2267af6ab..08f2f390cb003 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -39,6 +39,69 @@ When this option is enabled, the long-term headers are removed from the bitstream after extraction. @end table +@section h264_metadata + +Modify metadata embedded in an H.264 stream. + +@table @option +@item aud +Insert or remove AUD NAL units in all access units of the stream. + +@table @samp +@item insert +@item remove +@end table + +@item sample_aspect_ratio +Set the sample aspect ratio of the stream in the VUI parameters. + +@item video_format +@item video_full_range_flag +Set the video format in the stream (see H.264 section E.2.1 and +table E-2). + +@item colour_primaries +@item transfer_characteristics +@item matrix_coefficients +Set the colour description in the stream (see H.264 section E.2.1 +and tables E-3, E-4 and E-5). + +@item chroma_sample_loc_type +Set the chroma sample location in the stream (see H.264 section +E.2.1 and figure E-1). + +@item tick_rate +Set the tick rate (num_units_in_tick / time_scale) in the VUI +parameters. This is the smallest time unit representable in the +stream, and in many cases represents the field rate of the stream +(double the frame rate). +@item fixed_frame_rate_flag +Set whether the stream has fixed framerate - typically this indicates +that the framerate is exactly half the tick rate, but the exact +meaning is dependent on interlacing and the picture structure (see +H.264 section E.2.1 and table E-6). + +@item crop_left +@item crop_right +@item crop_top +@item crop_bottom +Set the frame cropping offsets in the SPS. These values will replace +the current ones if the stream is already cropped. + +These fields are set in pixels. Note that some sizes may not be +representable if the chroma is subsampled or the stream is interlaced +(see H.264 section 7.4.2.1.1). + +@item sei_user_data +Insert a string as SEI unregistered user data. The argument must +be of the form @emph{UUID+string}, where the UUID is as hex digits +possibly separated by hyphens, and the string can be anything. + +For example, @samp{086f3693-b7b3-4f2c-9653-21492feee5b8+hello} will +insert the string ``hello'' associated with the given UUID. + +@end table + @section h264_mp4toannexb @section imx_dump_header diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 09772a85f7c99..c76dffe0589a3 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -776,6 +776,7 @@ OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \ h2645_parse.o +OBJS-$(CONFIG_H264_METADATA_BSF) += h264_metadata_bsf.o OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 2e423acaf07e6..4ad50508cb5cd 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -28,6 +28,7 @@ extern const AVBitStreamFilter ff_aac_adtstoasc_bsf; extern const AVBitStreamFilter ff_chomp_bsf; extern const AVBitStreamFilter ff_dump_extradata_bsf; extern const AVBitStreamFilter ff_extract_extradata_bsf; +extern const AVBitStreamFilter ff_h264_metadata_bsf; extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf; extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf; extern const AVBitStreamFilter ff_imx_dump_header_bsf; diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c new file mode 100644 index 0000000000000..9bf96b397d678 --- /dev/null +++ b/libavcodec/h264_metadata_bsf.c @@ -0,0 +1,512 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "bsf.h" +#include "cbs.h" +#include "cbs_h264.h" +#include "h264.h" +#include "h264_sei.h" + +enum { + PASS, + INSERT, + REMOVE, +}; + +typedef struct H264MetadataContext { + const AVClass *class; + + CodedBitstreamContext cbc; + CodedBitstreamFragment access_unit; + + H264RawAUD aud_nal; + H264RawSEI sei_nal; + + int aud; + + AVRational sample_aspect_ratio; + + int video_format; + int video_full_range_flag; + int colour_primaries; + int transfer_characteristics; + int matrix_coefficients; + + int chroma_sample_loc_type; + + AVRational tick_rate; + int fixed_frame_rate_flag; + + int crop_left; + int crop_right; + int crop_top; + int crop_bottom; + + const char *sei_user_data; +} H264MetadataContext; + + +static int h264_metadata_update_sps(AVBSFContext *bsf, + H264RawSPS *sps) +{ + H264MetadataContext *ctx = bsf->priv_data; + int need_vui = 0; + int crop_unit_x, crop_unit_y; + + if (ctx->sample_aspect_ratio.num && ctx->sample_aspect_ratio.den) { + // Table E-1. + static const AVRational sar_idc[] = { + { 0, 0 }, // Unspecified (never written here). + { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, + { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, + { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, + { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, + }; + int num, den, i; + + av_reduce(&num, &den, ctx->sample_aspect_ratio.num, + ctx->sample_aspect_ratio.den, 65535); + + for (i = 1; i < FF_ARRAY_ELEMS(sar_idc); i++) { + if (num == sar_idc[i].num && + den == sar_idc[i].den) + break; + } + if (i == FF_ARRAY_ELEMS(sar_idc)) { + sps->vui.aspect_ratio_idc = 255; + sps->vui.sar_width = num; + sps->vui.sar_height = den; + } else { + sps->vui.aspect_ratio_idc = i; + } + sps->vui.aspect_ratio_info_present_flag = 1; + need_vui = 1; + } + +#define SET_OR_INFER(field, value, present_flag, infer) do { \ + if (value >= 0) { \ + field = value; \ + need_vui = 1; \ + } else if (!present_flag) \ + field = infer; \ + } while (0) + + if (ctx->video_format >= 0 || + ctx->video_full_range_flag >= 0 || + ctx->colour_primaries >= 0 || + ctx->transfer_characteristics >= 0 || + ctx->matrix_coefficients >= 0) { + + SET_OR_INFER(sps->vui.video_format, ctx->video_format, + sps->vui.video_signal_type_present_flag, 5); + + SET_OR_INFER(sps->vui.video_full_range_flag, + ctx->video_full_range_flag, + sps->vui.video_signal_type_present_flag, 0); + + if (ctx->colour_primaries >= 0 || + ctx->transfer_characteristics >= 0 || + ctx->matrix_coefficients >= 0) { + + SET_OR_INFER(sps->vui.colour_primaries, + ctx->colour_primaries, + sps->vui.colour_description_present_flag, 2); + + SET_OR_INFER(sps->vui.transfer_characteristics, + ctx->transfer_characteristics, + sps->vui.colour_description_present_flag, 2); + + SET_OR_INFER(sps->vui.matrix_coefficients, + ctx->matrix_coefficients, + sps->vui.colour_description_present_flag, 2); + + sps->vui.colour_description_present_flag = 1; + } + sps->vui.video_signal_type_present_flag = 1; + need_vui = 1; + } + + if (ctx->chroma_sample_loc_type >= 0) { + sps->vui.chroma_sample_loc_type_top_field = + ctx->chroma_sample_loc_type; + sps->vui.chroma_sample_loc_type_bottom_field = + ctx->chroma_sample_loc_type; + sps->vui.chroma_loc_info_present_flag = 1; + need_vui = 1; + } + + if (ctx->tick_rate.num && ctx->tick_rate.den) { + int num, den; + + av_reduce(&num, &den, ctx->tick_rate.num, ctx->tick_rate.den, + UINT32_MAX > INT_MAX ? UINT32_MAX : INT_MAX); + + sps->vui.time_scale = num; + sps->vui.num_units_in_tick = den; + + sps->vui.timing_info_present_flag = 1; + need_vui = 1; + } + SET_OR_INFER(sps->vui.fixed_frame_rate_flag, + ctx->fixed_frame_rate_flag, + sps->vui.timing_info_present_flag, 0); + + if (sps->separate_colour_plane_flag || sps->chroma_format_idc == 0) { + crop_unit_x = 1; + crop_unit_y = 2 - sps->frame_mbs_only_flag; + } else { + crop_unit_x = 1 + (sps->chroma_format_idc < 3); + crop_unit_y = (1 + (sps->chroma_format_idc < 2)) * + (2 - sps->frame_mbs_only_flag); + } +#define CROP(border, unit) do { \ + if (ctx->crop_ ## border >= 0) { \ + if (ctx->crop_ ## border % unit != 0) { \ + av_log(bsf, AV_LOG_ERROR, "Invalid value for crop_%s: " \ + "must be a multiple of %d.\n", #border, unit); \ + return AVERROR(EINVAL); \ + } \ + sps->frame_crop_ ## border ## _offset = \ + ctx->crop_ ## border / unit; \ + sps->frame_cropping_flag = 1; \ + } \ + } while (0) + CROP(left, crop_unit_x); + CROP(right, crop_unit_x); + CROP(top, crop_unit_y); + CROP(bottom, crop_unit_y); +#undef CROP + + if (need_vui) + sps->vui_parameters_present_flag = 1; + + return 0; +} + +static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) +{ + H264MetadataContext *ctx = bsf->priv_data; + AVPacket *in = NULL; + CodedBitstreamFragment *au = &ctx->access_unit; + int err, i, j, has_sps; + char *sei_udu_string = NULL; + + err = ff_bsf_get_packet(bsf, &in); + if (err < 0) + goto fail; + + err = ff_cbs_read_packet(&ctx->cbc, au, in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); + goto fail; + } + + if (au->nb_units == 0) { + av_log(bsf, AV_LOG_ERROR, "No NAL units in packet.\n"); + err = AVERROR_INVALIDDATA; + goto fail; + } + + // If an AUD is present, it must be the first NAL unit. + if (au->units[0].type == H264_NAL_AUD) { + if (ctx->aud == REMOVE) + ff_cbs_delete_unit(&ctx->cbc, au, 0); + } else { + if (ctx->aud == INSERT) { + static const int primary_pic_type_table[] = { + 0x084, // 2, 7 + 0x0a5, // 0, 2, 5, 7 + 0x0e7, // 0, 1, 2, 5, 6, 7 + 0x210, // 4, 9 + 0x318, // 3, 4, 8, 9 + 0x294, // 2, 4, 7, 9 + 0x3bd, // 0, 2, 3, 4, 5, 7, 8, 9 + 0x3ff, // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + }; + int primary_pic_type_mask = 0xff; + H264RawAUD *aud = &ctx->aud_nal; + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_SLICE || + au->units[i].type == H264_NAL_IDR_SLICE) { + H264RawSlice *slice = au->units[i].content; + for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++) { + if (!(primary_pic_type_table[j] & + (1 << slice->header.slice_type))) + primary_pic_type_mask &= ~(1 << j); + } + } + } + for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++) + if (primary_pic_type_mask & (1 << j)) + break; + if (j >= FF_ARRAY_ELEMS(primary_pic_type_table)) { + av_log(bsf, AV_LOG_ERROR, "No usable primary_pic_type: " + "invalid slice types?\n"); + err = AVERROR_INVALIDDATA; + goto fail; + } + + aud->nal_unit_header.nal_unit_type = H264_NAL_AUD; + aud->primary_pic_type = j; + + err = ff_cbs_insert_unit_content(&ctx->cbc, au, + 0, H264_NAL_AUD, aud); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n"); + goto fail; + } + } + } + + has_sps = 0; + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_SPS) { + err = h264_metadata_update_sps(bsf, au->units[i].content); + if (err < 0) + goto fail; + has_sps = 1; + } + } + + // Only insert the SEI in access units containing SPSs. + if (has_sps && ctx->sei_user_data) { + H264RawSEI *sei; + H264RawSEIPayload *payload; + H264RawSEIUserDataUnregistered *udu; + int sei_pos; + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_SEI || + au->units[i].type == H264_NAL_SLICE || + au->units[i].type == H264_NAL_IDR_SLICE) + break; + } + sei_pos = i; + + if (sei_pos < au->nb_units && + au->units[sei_pos].type == H264_NAL_SEI) { + sei = au->units[sei_pos].content; + } else { + sei = &ctx->sei_nal; + memset(sei, 0, sizeof(*sei)); + + sei->nal_unit_header.nal_unit_type = H264_NAL_SEI; + + err = ff_cbs_insert_unit_content(&ctx->cbc, au, + sei_pos, H264_NAL_SEI, sei); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to insert SEI.\n"); + goto fail; + } + } + + payload = &sei->payload[sei->payload_count]; + + payload->payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED; + udu = &payload->payload.user_data_unregistered; + + for (i = j = 0; j < 32 && ctx->sei_user_data[i]; i++) { + int c, v; + c = ctx->sei_user_data[i]; + if (c == '-') { + continue; + } else if (av_isxdigit(c)) { + c = av_tolower(c); + v = (c <= '9' ? c - '0' : c - 'a' + 10); + } else { + goto invalid_user_data; + } + if (i & 1) + udu->uuid_iso_iec_11578[j / 2] |= v; + else + udu->uuid_iso_iec_11578[j / 2] = v << 4; + ++j; + } + if (j == 32 && ctx->sei_user_data[i] == '+') { + sei_udu_string = av_strdup(ctx->sei_user_data + i + 1); + if (!sei_udu_string) { + err = AVERROR(ENOMEM); + goto sei_fail; + } + + udu->data = sei_udu_string; + udu->data_length = strlen(sei_udu_string); + + payload->payload_size = 16 + udu->data_length; + + } else { + invalid_user_data: + av_log(bsf, AV_LOG_ERROR, "Invalid user data: " + "must be \"UUID+string\".\n"); + err = AVERROR(EINVAL); + sei_fail: + memset(payload, 0, sizeof(&payload)); + goto fail; + } + + ++sei->payload_count; + } + + err = ff_cbs_write_packet(&ctx->cbc, out, au); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); + goto fail; + } + + err = av_packet_copy_props(out, in); + if (err < 0) + goto fail; + + err = 0; +fail: + ff_cbs_fragment_uninit(&ctx->cbc, au); + av_freep(&sei_udu_string); + + av_packet_free(&in); + + return err; +} + +static int h264_metadata_init(AVBSFContext *bsf) +{ + H264MetadataContext *ctx = bsf->priv_data; + CodedBitstreamFragment *au = &ctx->access_unit; + int err, i; + + err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_H264, bsf); + if (err < 0) + return err; + + if (bsf->par_in->extradata) { + err = ff_cbs_read_extradata(&ctx->cbc, au, bsf->par_in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); + goto fail; + } + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_SPS) { + err = h264_metadata_update_sps(bsf, au->units[i].content); + if (err < 0) + goto fail; + } + } + + err = ff_cbs_write_extradata(&ctx->cbc, bsf->par_out, au); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); + goto fail; + } + } + + err = 0; +fail: + ff_cbs_fragment_uninit(&ctx->cbc, au); + return err; +} + +static void h264_metadata_close(AVBSFContext *bsf) +{ + H264MetadataContext *ctx = bsf->priv_data; + ff_cbs_close(&ctx->cbc); +} + +#define OFFSET(x) offsetof(H264MetadataContext, x) +static const AVOption h264_metadata_options[] = { + { "aud", "Access Unit Delimiter NAL units", + OFFSET(aud), AV_OPT_TYPE_INT, + { .i64 = PASS }, PASS, REMOVE, 0, "aud" }, + { "pass", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PASS }, .unit = "aud" }, + { "insert", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = INSERT }, .unit = "aud" }, + { "remove", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE }, .unit = "aud" }, + + { "sample_aspect_ratio", "Set sample aspect ratio (table E-1)", + OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, + { .i64 = 0 }, 0, 65535 }, + + { "video_format", "Set video format (table E-2)", + OFFSET(video_format), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 7 }, + { "video_full_range_flag", "Set video full range flag", + OFFSET(video_full_range_flag), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 1 }, + { "colour_primaries", "Set colour primaries (table E-3)", + OFFSET(colour_primaries), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + { "transfer_characteristics", "Set transfer characteristics (table E-4)", + OFFSET(transfer_characteristics), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + { "matrix_coefficients", "Set matrix coefficients (table E-5)", + OFFSET(matrix_coefficients), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + + { "chroma_sample_loc_type", "Set chroma sample location type (figure E-1)", + OFFSET(chroma_sample_loc_type), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 6 }, + + { "tick_rate", "Set VUI tick rate (num_units_in_tick / time_scale)", + OFFSET(tick_rate), AV_OPT_TYPE_RATIONAL, + { .i64 = 0 }, 0, UINT_MAX }, + { "fixed_frame_rate_flag", "Set VUI fixed frame rate flag", + OFFSET(fixed_frame_rate_flag), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 1 }, + + { "crop_left", "Set left border crop offset", + OFFSET(crop_left), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, H264_MAX_WIDTH }, + { "crop_right", "Set right border crop offset", + OFFSET(crop_right), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, H264_MAX_WIDTH }, + { "crop_top", "Set top border crop offset", + OFFSET(crop_top), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, H264_MAX_HEIGHT }, + { "crop_bottom", "Set bottom border crop offset", + OFFSET(crop_bottom), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, H264_MAX_HEIGHT }, + + { "sei_user_data", "Insert SEI user data (UUID+string)", + OFFSET(sei_user_data), AV_OPT_TYPE_STRING, { .str = NULL } }, + + { NULL } +}; + +static const AVClass h264_metadata_class = { + .class_name = "h264_metadata_bsf", + .item_name = av_default_item_name, + .option = h264_metadata_options, + .version = LIBAVCODEC_VERSION_MAJOR, +}; + +static const enum AVCodecID h264_metadata_codec_ids[] = { + AV_CODEC_ID_H264, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_h264_metadata_bsf = { + .name = "h264_metadata", + .priv_data_size = sizeof(H264MetadataContext), + .priv_class = &h264_metadata_class, + .init = &h264_metadata_init, + .close = &h264_metadata_close, + .filter = &h264_metadata_filter, + .codec_ids = h264_metadata_codec_ids, +}; From e6874bc3af2f09af39b5d91b9c5f9ded67459696 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 4 May 2017 23:10:19 +0100 Subject: [PATCH 0353/2557] lavc: Add h264_redundant_pps bitstream filter This applies a specific fixup to some Bluray streams which contain redundant PPSs modifying irrelevant parameters of the stream which confuse other transformations which require correct extradata. A new single global PPS is created, and all of the redundant PPSs within the stream are removed. --- configure | 1 + doc/bitstream_filters.texi | 9 ++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/h264_redundant_pps_bsf.c | 178 ++++++++++++++++++++++++++++ 5 files changed, 190 insertions(+) create mode 100644 libavcodec/h264_redundant_pps_bsf.c diff --git a/configure b/configure index f3d616800a778..bd4555dc87d31 100755 --- a/configure +++ b/configure @@ -2324,6 +2324,7 @@ vc1_parser_select="vc1dsp" # bitstream_filters aac_adtstoasc_bsf_select="adts_header" h264_metadata_bsf_select="cbs_h264" +h264_redundant_pps_bsf_select="cbs_h264" mjpeg2jpeg_bsf_select="jpegtables" trace_headers_bsf_select="cbs_h264 cbs_h265" diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 08f2f390cb003..e1de3035effb3 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -104,6 +104,15 @@ insert the string ``hello'' associated with the given UUID. @section h264_mp4toannexb +@section h264_redundant_pps + +This applies a specific fixup to some Bluray streams which contain +redundant PPSs modifying irrelevant parameters of the stream which +confuse other transformations which require correct extradata. + +A new single global PPS is created, and all of the redundant PPSs +within the stream are removed. + @section imx_dump_header @section mjpeg2jpeg diff --git a/libavcodec/Makefile b/libavcodec/Makefile index c76dffe0589a3..b37a3aa0915c1 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -778,6 +778,7 @@ OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \ h2645_parse.o OBJS-$(CONFIG_H264_METADATA_BSF) += h264_metadata_bsf.o OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o +OBJS-$(CONFIG_H264_REDUNDANT_PPS_BSF) += h264_redundant_pps_bsf.o OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 4ad50508cb5cd..8fd46a734c044 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -30,6 +30,7 @@ extern const AVBitStreamFilter ff_dump_extradata_bsf; extern const AVBitStreamFilter ff_extract_extradata_bsf; extern const AVBitStreamFilter ff_h264_metadata_bsf; extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf; +extern const AVBitStreamFilter ff_h264_redundant_pps_bsf; extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf; extern const AVBitStreamFilter ff_imx_dump_header_bsf; extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf; diff --git a/libavcodec/h264_redundant_pps_bsf.c b/libavcodec/h264_redundant_pps_bsf.c new file mode 100644 index 0000000000000..abc7af788a449 --- /dev/null +++ b/libavcodec/h264_redundant_pps_bsf.c @@ -0,0 +1,178 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/mem.h" + +#include "bsf.h" +#include "cbs.h" +#include "cbs_h264.h" +#include "h264.h" + + +typedef struct H264RedundantPPSContext { + CodedBitstreamContext input; + CodedBitstreamContext output; + + CodedBitstreamFragment access_unit; + + int global_pic_init_qp; + int current_pic_init_qp; +} H264RedundantPPSContext; + + +static int h264_redundant_pps_fixup_pps(H264RedundantPPSContext *ctx, + H264RawPPS *pps) +{ + // Record the current value of pic_init_qp in order to fix up + // following slices, then overwrite with the global value. + ctx->current_pic_init_qp = pps->pic_init_qp_minus26 + 26; + pps->pic_init_qp_minus26 = ctx->global_pic_init_qp - 26; + + // Some PPSs have this set, so it must be set in all of them. + // (Slices which do not use such a PPS on input will still have + // *_weight_l*flag as zero and therefore write equivalently.) + pps->weighted_pred_flag = 1; + + return 0; +} + +static int h264_redundant_pps_fixup_slice(H264RedundantPPSContext *ctx, + H264RawSliceHeader *slice) +{ + int qp; + + qp = ctx->current_pic_init_qp + slice->slice_qp_delta; + slice->slice_qp_delta = qp - ctx->global_pic_init_qp; + + return 0; +} + +static int h264_redundant_pps_filter(AVBSFContext *bsf, AVPacket *out) +{ + H264RedundantPPSContext *ctx = bsf->priv_data; + AVPacket *in; + CodedBitstreamFragment *au = &ctx->access_unit; + int au_has_sps; + int err, i; + + err = ff_bsf_get_packet(bsf, &in); + if (err < 0) + return err; + + err = ff_cbs_read_packet(&ctx->input, au, in); + if (err < 0) + return err; + + au_has_sps = 0; + for (i = 0; i < au->nb_units; i++) { + CodedBitstreamUnit *nal = &au->units[i]; + + if (nal->type == H264_NAL_SPS) + au_has_sps = 1; + if (nal->type == H264_NAL_PPS) { + h264_redundant_pps_fixup_pps(ctx, nal->content); + if (!au_has_sps) { + av_log(ctx, AV_LOG_VERBOSE, "Deleting redundant PPS " + "at %"PRId64".\n", in->pts); + ff_cbs_delete_unit(&ctx->input, au, i); + } + } + if (nal->type == H264_NAL_SLICE || + nal->type == H264_NAL_IDR_SLICE) { + H264RawSlice *slice = nal->content; + h264_redundant_pps_fixup_slice(ctx, &slice->header); + } + } + + err = ff_cbs_write_packet(&ctx->output, out, au); + if (err < 0) + return err; + + ff_cbs_fragment_uninit(&ctx->output, au); + + err = av_packet_copy_props(out, in); + if (err < 0) + return err; + + av_packet_free(&in); + + return 0; +} + +static int h264_redundant_pps_init(AVBSFContext *bsf) +{ + H264RedundantPPSContext *ctx = bsf->priv_data; + CodedBitstreamFragment *au = &ctx->access_unit; + int err, i; + + err = ff_cbs_init(&ctx->input, AV_CODEC_ID_H264, bsf); + if (err < 0) + return err; + + err = ff_cbs_init(&ctx->output, AV_CODEC_ID_H264, bsf); + if (err < 0) + return err; + + ctx->global_pic_init_qp = 26; + + if (bsf->par_in->extradata) { + err = ff_cbs_read_extradata(&ctx->input, au, bsf->par_in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); + return err; + } + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_PPS) + h264_redundant_pps_fixup_pps(ctx, au->units[i].content); + } + + err = ff_cbs_write_extradata(&ctx->output, bsf->par_out, au); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); + return err; + } + + ff_cbs_fragment_uninit(&ctx->output, au); + } + + return 0; +} + +static void h264_redundant_pps_close(AVBSFContext *bsf) +{ + H264RedundantPPSContext *ctx = bsf->priv_data; + ff_cbs_close(&ctx->input); + ff_cbs_close(&ctx->output); +} + +static const enum AVCodecID h264_redundant_pps_codec_ids[] = { + AV_CODEC_ID_H264, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_h264_redundant_pps_bsf = { + .name = "h264_redundant_pps", + .priv_data_size = sizeof(H264RedundantPPSContext), + .init = &h264_redundant_pps_init, + .close = &h264_redundant_pps_close, + .filter = &h264_redundant_pps_filter, + .codec_ids = h264_redundant_pps_codec_ids, +}; From b31a9eae0233325c4b382c657f4b687d5d8b0812 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 23 Jul 2017 16:23:51 +0100 Subject: [PATCH 0354/2557] lavc: Add hevc_metadata bitstream filter This is able to modify some header metadata found in the VPS/SPS/VUI, and can also add/remove AUDs. --- configure | 1 + doc/bitstream_filters.texi | 54 ++++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/h265_metadata_bsf.c | 458 +++++++++++++++++++++++++++++++++ 5 files changed, 515 insertions(+) create mode 100644 libavcodec/h265_metadata_bsf.c diff --git a/configure b/configure index bd4555dc87d31..dfa3867ac08b8 100755 --- a/configure +++ b/configure @@ -2325,6 +2325,7 @@ vc1_parser_select="vc1dsp" aac_adtstoasc_bsf_select="adts_header" h264_metadata_bsf_select="cbs_h264" h264_redundant_pps_bsf_select="cbs_h264" +hevc_metadata_bsf_select="cbs_h265" mjpeg2jpeg_bsf_select="jpegtables" trace_headers_bsf_select="cbs_h264 cbs_h265" diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index e1de3035effb3..21371ea9a6c1c 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -113,6 +113,60 @@ confuse other transformations which require correct extradata. A new single global PPS is created, and all of the redundant PPSs within the stream are removed. +@section hevc_metadata + +Modify metadata embedded in an HEVC stream. + +@table @option +@item aud +Insert or remove AUD NAL units in all access units of the stream. + +@table @samp +@item insert +@item remove +@end table + +@item sample_aspect_ratio +Set the sample aspect ratio in the stream in the VUI parameters. + +@item video_format +@item video_full_range_flag +Set the video format in the stream (see H.265 section E.3.1 and +table E.2). + +@item colour_primaries +@item transfer_characteristics +@item matrix_coefficients +Set the colour description in the stream (see H.265 section E.3.1 +and tables E.3, E.4 and E.5). + +@item chroma_sample_loc_type +Set the chroma sample location in the stream (see H.265 section +E.3.1 and figure E.1). + +@item tick_rate +Set the tick rate in the VPS and VUI parameters (num_units_in_tick / +time_scale). Combined with @option{num_ticks_poc_diff_one}, this can +set a constant framerate in the stream. Note that it is likely to be +overridden by container parameters when the stream is in a container. + +@item num_ticks_poc_diff_one +Set poc_proportional_to_timing_flag in VPS and VUI and use this value +to set num_ticks_poc_diff_one_minus1 (see H.265 sections 7.4.3.1 and +E.3.1). Ignored if @option{tick_rate} is not also set. + +@item crop_left +@item crop_right +@item crop_top +@item crop_bottom +Set the conformance window cropping offsets in the SPS. These values +will replace the current ones if the stream is already cropped. + +These fields are set in pixels. Note that some sizes may not be +representable if the chroma is subsampled (H.265 section 7.4.3.2.1). + +@end table + @section imx_dump_header @section mjpeg2jpeg diff --git a/libavcodec/Makefile b/libavcodec/Makefile index b37a3aa0915c1..e1ae1e4519d74 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -779,6 +779,7 @@ OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \ OBJS-$(CONFIG_H264_METADATA_BSF) += h264_metadata_bsf.o OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o OBJS-$(CONFIG_H264_REDUNDANT_PPS_BSF) += h264_redundant_pps_bsf.o +OBJS-$(CONFIG_HEVC_METADATA_BSF) += h265_metadata_bsf.o OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 8fd46a734c044..e90919f6028b3 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -31,6 +31,7 @@ extern const AVBitStreamFilter ff_extract_extradata_bsf; extern const AVBitStreamFilter ff_h264_metadata_bsf; extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf; extern const AVBitStreamFilter ff_h264_redundant_pps_bsf; +extern const AVBitStreamFilter ff_hevc_metadata_bsf; extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf; extern const AVBitStreamFilter ff_imx_dump_header_bsf; extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf; diff --git a/libavcodec/h265_metadata_bsf.c b/libavcodec/h265_metadata_bsf.c new file mode 100644 index 0000000000000..aef4a55fb7e54 --- /dev/null +++ b/libavcodec/h265_metadata_bsf.c @@ -0,0 +1,458 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "bsf.h" +#include "cbs.h" +#include "cbs_h265.h" +#include "hevc.h" + +enum { + PASS, + INSERT, + REMOVE, +}; + +typedef struct H265MetadataContext { + const AVClass *class; + + CodedBitstreamContext cbc; + CodedBitstreamFragment access_unit; + + H265RawAUD aud_nal; + + int aud; + + AVRational sample_aspect_ratio; + + int video_format; + int video_full_range_flag; + int colour_primaries; + int transfer_characteristics; + int matrix_coefficients; + + int chroma_sample_loc_type; + + AVRational tick_rate; + int poc_proportional_to_timing_flag; + int num_ticks_poc_diff_one; + + int crop_left; + int crop_right; + int crop_top; + int crop_bottom; +} H265MetadataContext; + + +static int h265_metadata_update_vps(AVBSFContext *bsf, + H265RawVPS *vps) +{ + H265MetadataContext *ctx = bsf->priv_data; + + if (ctx->tick_rate.num && ctx->tick_rate.den) { + int num, den; + + av_reduce(&num, &den, ctx->tick_rate.num, ctx->tick_rate.den, + UINT32_MAX > INT_MAX ? UINT32_MAX : INT_MAX); + + vps->vps_time_scale = num; + vps->vps_num_units_in_tick = den; + + vps->vps_timing_info_present_flag = 1; + + if (ctx->num_ticks_poc_diff_one > 0) { + vps->vps_num_ticks_poc_diff_one_minus1 = + ctx->num_ticks_poc_diff_one - 1; + vps->vps_poc_proportional_to_timing_flag = 1; + } else if (ctx->num_ticks_poc_diff_one == 0) { + vps->vps_poc_proportional_to_timing_flag = 0; + } + } + + return 0; +} + +static int h265_metadata_update_sps(AVBSFContext *bsf, + H265RawSPS *sps) +{ + H265MetadataContext *ctx = bsf->priv_data; + int need_vui = 0; + int crop_unit_x, crop_unit_y; + + if (ctx->sample_aspect_ratio.num && ctx->sample_aspect_ratio.den) { + // Table E-1. + static const AVRational sar_idc[] = { + { 0, 0 }, // Unspecified (never written here). + { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, + { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, + { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, + { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, + }; + int num, den, i; + + av_reduce(&num, &den, ctx->sample_aspect_ratio.num, + ctx->sample_aspect_ratio.den, 65535); + + for (i = 1; i < FF_ARRAY_ELEMS(sar_idc); i++) { + if (num == sar_idc[i].num && + den == sar_idc[i].den) + break; + } + if (i == FF_ARRAY_ELEMS(sar_idc)) { + sps->vui.aspect_ratio_idc = 255; + sps->vui.sar_width = num; + sps->vui.sar_height = den; + } else { + sps->vui.aspect_ratio_idc = i; + } + sps->vui.aspect_ratio_info_present_flag = 1; + need_vui = 1; + } + +#define SET_OR_INFER(field, value, present_flag, infer) do { \ + if (value >= 0) { \ + field = value; \ + need_vui = 1; \ + } else if (!present_flag) \ + field = infer; \ + } while (0) + + if (ctx->video_format >= 0 || + ctx->video_full_range_flag >= 0 || + ctx->colour_primaries >= 0 || + ctx->transfer_characteristics >= 0 || + ctx->matrix_coefficients >= 0) { + + SET_OR_INFER(sps->vui.video_format, ctx->video_format, + sps->vui.video_signal_type_present_flag, 5); + + SET_OR_INFER(sps->vui.video_full_range_flag, + ctx->video_full_range_flag, + sps->vui.video_signal_type_present_flag, 0); + + if (ctx->colour_primaries >= 0 || + ctx->transfer_characteristics >= 0 || + ctx->matrix_coefficients >= 0) { + + SET_OR_INFER(sps->vui.colour_primaries, + ctx->colour_primaries, + sps->vui.colour_description_present_flag, 2); + + SET_OR_INFER(sps->vui.transfer_characteristics, + ctx->transfer_characteristics, + sps->vui.colour_description_present_flag, 2); + + SET_OR_INFER(sps->vui.matrix_coefficients, + ctx->matrix_coefficients, + sps->vui.colour_description_present_flag, 2); + + sps->vui.colour_description_present_flag = 1; + } + sps->vui.video_signal_type_present_flag = 1; + need_vui = 1; + } + + if (ctx->chroma_sample_loc_type >= 0) { + sps->vui.chroma_sample_loc_type_top_field = + ctx->chroma_sample_loc_type; + sps->vui.chroma_sample_loc_type_bottom_field = + ctx->chroma_sample_loc_type; + sps->vui.chroma_loc_info_present_flag = 1; + need_vui = 1; + } + + if (ctx->tick_rate.num && ctx->tick_rate.den) { + int num, den; + + av_reduce(&num, &den, ctx->tick_rate.num, ctx->tick_rate.den, + UINT32_MAX > INT_MAX ? UINT32_MAX : INT_MAX); + + sps->vui.vui_time_scale = num; + sps->vui.vui_num_units_in_tick = den; + + sps->vui.vui_timing_info_present_flag = 1; + need_vui = 1; + + if (ctx->num_ticks_poc_diff_one > 0) { + sps->vui.vui_num_ticks_poc_diff_one_minus1 = + ctx->num_ticks_poc_diff_one - 1; + sps->vui.vui_poc_proportional_to_timing_flag = 1; + } else if (ctx->num_ticks_poc_diff_one == 0) { + sps->vui.vui_poc_proportional_to_timing_flag = 0; + } + } + + if (sps->separate_colour_plane_flag || sps->chroma_format_idc == 0) { + crop_unit_x = 1; + crop_unit_y = 1; + } else { + crop_unit_x = 1 + (sps->chroma_format_idc < 3); + crop_unit_y = 1 + (sps->chroma_format_idc < 2); + } +#define CROP(border, unit) do { \ + if (ctx->crop_ ## border >= 0) { \ + if (ctx->crop_ ## border % unit != 0) { \ + av_log(bsf, AV_LOG_ERROR, "Invalid value for crop_%s: " \ + "must be a multiple of %d.\n", #border, unit); \ + return AVERROR(EINVAL); \ + } \ + sps->conf_win_ ## border ## _offset = \ + ctx->crop_ ## border / unit; \ + sps->conformance_window_flag = 1; \ + } \ + } while (0) + CROP(left, crop_unit_x); + CROP(right, crop_unit_x); + CROP(top, crop_unit_y); + CROP(bottom, crop_unit_y); +#undef CROP + + if (need_vui) + sps->vui_parameters_present_flag = 1; + + return 0; +} + +static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *out) +{ + H265MetadataContext *ctx = bsf->priv_data; + AVPacket *in = NULL; + CodedBitstreamFragment *au = &ctx->access_unit; + int err, i; + + err = ff_bsf_get_packet(bsf, &in); + if (err < 0) + goto fail; + + err = ff_cbs_read_packet(&ctx->cbc, au, in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); + goto fail; + } + + if (au->nb_units == 0) { + av_log(bsf, AV_LOG_ERROR, "No NAL units in packet.\n"); + err = AVERROR_INVALIDDATA; + goto fail; + } + + // If an AUD is present, it must be the first NAL unit. + if (au->units[0].type == HEVC_NAL_AUD) { + if (ctx->aud == REMOVE) + ff_cbs_delete_unit(&ctx->cbc, au, 0); + } else { + if (ctx->aud == INSERT) { + H265RawAUD *aud = &ctx->aud_nal; + int pic_type = 0, temporal_id = 8, layer_id = 0; + + for (i = 0; i < au->nb_units; i++) { + const H265RawNALUnitHeader *nal = au->units[i].content; + if (!nal) + continue; + if (nal->nuh_temporal_id_plus1 < temporal_id + 1) + temporal_id = nal->nuh_temporal_id_plus1 - 1; + + if (au->units[i].type <= HEVC_NAL_RSV_VCL31) { + const H265RawSlice *slice = au->units[i].content; + layer_id = nal->nuh_layer_id; + if (slice->header.slice_type == HEVC_SLICE_B && + pic_type < 2) + pic_type = 2; + if (slice->header.slice_type == HEVC_SLICE_P && + pic_type < 1) + pic_type = 1; + } + } + + aud->nal_unit_header = (H265RawNALUnitHeader) { + .nal_unit_type = HEVC_NAL_AUD, + .nuh_layer_id = layer_id, + .nuh_temporal_id_plus1 = temporal_id + 1, + }; + aud->pic_type = pic_type; + + err = ff_cbs_insert_unit_content(&ctx->cbc, au, + 0, HEVC_NAL_AUD, aud); + if (err) { + av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n"); + goto fail; + } + } + } + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == HEVC_NAL_VPS) { + err = h265_metadata_update_vps(bsf, au->units[i].content); + if (err < 0) + goto fail; + } + if (au->units[i].type == HEVC_NAL_SPS) { + err = h265_metadata_update_sps(bsf, au->units[i].content); + if (err < 0) + goto fail; + } + } + + err = ff_cbs_write_packet(&ctx->cbc, out, au); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); + goto fail; + } + + err = av_packet_copy_props(out, in); + if (err < 0) + goto fail; + + err = 0; +fail: + ff_cbs_fragment_uninit(&ctx->cbc, au); + + av_packet_free(&in); + + return err; +} + +static int h265_metadata_init(AVBSFContext *bsf) +{ + H265MetadataContext *ctx = bsf->priv_data; + CodedBitstreamFragment *au = &ctx->access_unit; + int err, i; + + err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_HEVC, bsf); + if (err < 0) + return err; + + if (bsf->par_in->extradata) { + err = ff_cbs_read_extradata(&ctx->cbc, au, bsf->par_in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); + goto fail; + } + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == HEVC_NAL_VPS) { + err = h265_metadata_update_vps(bsf, au->units[i].content); + if (err < 0) + goto fail; + } + if (au->units[i].type == HEVC_NAL_SPS) { + err = h265_metadata_update_sps(bsf, au->units[i].content); + if (err < 0) + goto fail; + } + } + + err = ff_cbs_write_extradata(&ctx->cbc, bsf->par_out, au); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); + goto fail; + } + } + + err = 0; +fail: + ff_cbs_fragment_uninit(&ctx->cbc, au); + return err; +} + +static void h265_metadata_close(AVBSFContext *bsf) +{ + H265MetadataContext *ctx = bsf->priv_data; + ff_cbs_close(&ctx->cbc); +} + +#define OFFSET(x) offsetof(H265MetadataContext, x) +static const AVOption h265_metadata_options[] = { + { "aud", "Access Unit Delimiter NAL units", + OFFSET(aud), AV_OPT_TYPE_INT, + { .i64 = PASS }, PASS, REMOVE, 0, "aud" }, + { "pass", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PASS }, .unit = "aud" }, + { "insert", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = INSERT }, .unit = "aud" }, + { "remove", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE }, .unit = "aud" }, + + { "sample_aspect_ratio", "Set sample aspect ratio (table E-1)", + OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, + { .i64 = 0 }, 0, 65535 }, + + { "video_format", "Set video format (table E-2)", + OFFSET(video_format), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 7 }, + { "video_full_range_flag", "Set video full range flag", + OFFSET(video_full_range_flag), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 1 }, + { "colour_primaries", "Set colour primaries (table E-3)", + OFFSET(colour_primaries), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + { "transfer_characteristics", "Set transfer characteristics (table E-4)", + OFFSET(transfer_characteristics), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + { "matrix_coefficients", "Set matrix coefficients (table E-5)", + OFFSET(matrix_coefficients), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + + { "chroma_sample_loc_type", "Set chroma sample location type (figure E-1)", + OFFSET(chroma_sample_loc_type), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 6 }, + + { "tick_rate", + "Set VPS and VUI tick rate (num_units_in_tick / time_scale)", + OFFSET(tick_rate), AV_OPT_TYPE_RATIONAL, + { .i64 = 0 }, 0, UINT_MAX }, + { "num_ticks_poc_diff_one", + "Set VPS and VUI number of ticks per POC increment", + OFFSET(num_ticks_poc_diff_one), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, INT_MAX }, + + { "crop_left", "Set left border crop offset", + OFFSET(crop_left), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, HEVC_MAX_WIDTH }, + { "crop_right", "Set right border crop offset", + OFFSET(crop_right), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, HEVC_MAX_WIDTH }, + { "crop_top", "Set top border crop offset", + OFFSET(crop_top), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, HEVC_MAX_HEIGHT }, + { "crop_bottom", "Set bottom border crop offset", + OFFSET(crop_bottom), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, HEVC_MAX_HEIGHT }, + + { NULL } +}; + +static const AVClass h265_metadata_class = { + .class_name = "h265_metadata_bsf", + .item_name = av_default_item_name, + .option = h265_metadata_options, + .version = LIBAVCODEC_VERSION_MAJOR, +}; + +static const enum AVCodecID h265_metadata_codec_ids[] = { + AV_CODEC_ID_HEVC, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_hevc_metadata_bsf = { + .name = "hevc_metadata", + .priv_data_size = sizeof(H265MetadataContext), + .priv_class = &h265_metadata_class, + .init = &h265_metadata_init, + .close = &h265_metadata_close, + .filter = &h265_metadata_filter, + .codec_ids = h265_metadata_codec_ids, +}; From 7a4fac5e91789b73e07bd4ad20493cfde028df76 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 7 May 2017 15:01:42 +0100 Subject: [PATCH 0355/2557] vaapi_h264: Convert to use coded bitstream infrastructure --- configure | 2 +- libavcodec/Makefile | 2 +- libavcodec/vaapi_encode_h264.c | 1421 ++++++++++++-------------------- 3 files changed, 549 insertions(+), 876 deletions(-) diff --git a/configure b/configure index dfa3867ac08b8..b6fa8f6827a99 100755 --- a/configure +++ b/configure @@ -2285,7 +2285,7 @@ h264_omx_encoder_deps="omx" h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec h264_qsv_hwaccel" h264_qsv_encoder_select="qsvenc" h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" -h264_vaapi_encoder_select="vaapi_encode golomb" +h264_vaapi_encoder_select="cbs_h264 vaapi_encode" hevc_nvenc_encoder_deps="nvenc" hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser hevc_qsv_hwaccel qsvdec" hevc_qsv_encoder_select="hevc_ps qsvenc" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index e1ae1e4519d74..456ee9bb0306b 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -275,7 +275,7 @@ OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o OBJS-$(CONFIG_H264_OMX_ENCODER) += omx.o OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec_h2645.o OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.o -OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o vaapi_encode_h26x.o +OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o OBJS-$(CONFIG_HAP_DECODER) += hapdec.o hap.o OBJS-$(CONFIG_HAP_ENCODER) += hapenc.o hap.o OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o hevc_sei.o \ diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index e08cf61167c35..b48070c950da2 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -16,128 +16,36 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include #include #include "libavutil/avassert.h" +#include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/opt.h" -#include "libavutil/pixfmt.h" #include "avcodec.h" +#include "cbs.h" +#include "cbs_h264.h" #include "h264.h" #include "h264_sei.h" #include "internal.h" #include "vaapi_encode.h" -#include "vaapi_encode_h26x.h" enum { - SLICE_TYPE_P = 0, - SLICE_TYPE_B = 1, - SLICE_TYPE_I = 2, - SLICE_TYPE_SP = 3, - SLICE_TYPE_SI = 4, + SEI_TIMING = 0x01, + SEI_IDENTIFIER = 0x02, }; -// This structure contains all possibly-useful per-sequence syntax elements -// which are not already contained in the various VAAPI structures. -typedef struct VAAPIEncodeH264MiscSequenceParams { - unsigned int profile_idc; - char constraint_set0_flag; - char constraint_set1_flag; - char constraint_set2_flag; - char constraint_set3_flag; - char constraint_set4_flag; - char constraint_set5_flag; - - char separate_colour_plane_flag; - char qpprime_y_zero_transform_bypass_flag; - - char gaps_in_frame_num_allowed_flag; - char delta_pic_order_always_zero_flag; - char bottom_field_pic_order_in_frame_present_flag; - - unsigned int num_slice_groups_minus1; - unsigned int slice_group_map_type; - - int pic_init_qs_minus26; - - char overscan_info_present_flag; - char overscan_appropriate_flag; - - char video_signal_type_present_flag; - unsigned int video_format; - char video_full_range_flag; - char colour_description_present_flag; - unsigned int colour_primaries; - unsigned int transfer_characteristics; - unsigned int matrix_coefficients; - - char chroma_loc_info_present_flag; - unsigned int chroma_sample_loc_type_top_field; - unsigned int chroma_sample_loc_type_bottom_field; - - // Some timing elements are in VAEncSequenceParameterBufferH264. - char fixed_frame_rate_flag; - - char nal_hrd_parameters_present_flag; - char vcl_hrd_parameters_present_flag; - char low_delay_hrd_flag; - char pic_struct_present_flag; - - char motion_vectors_over_pic_boundaries_flag; - unsigned int max_bytes_per_pic_denom; - unsigned int max_bits_per_mb_denom; - unsigned int max_num_reorder_frames; - unsigned int max_dec_pic_buffering; - - unsigned int cpb_cnt_minus1; - unsigned int bit_rate_scale; - unsigned int cpb_size_scale; - unsigned int bit_rate_value_minus1[32]; - unsigned int cpb_size_value_minus1[32]; - char cbr_flag[32]; - unsigned int initial_cpb_removal_delay_length_minus1; - unsigned int cpb_removal_delay_length_minus1; - unsigned int dpb_output_delay_length_minus1; - unsigned int time_offset_length; - - unsigned int initial_cpb_removal_delay; - unsigned int initial_cpb_removal_delay_offset; - - unsigned int pic_struct; -} VAAPIEncodeH264MiscSequenceParams; - -// This structure contains all possibly-useful per-slice syntax elements -// which are not already contained in the various VAAPI structures. -typedef struct VAAPIEncodeH264MiscSliceParams { - unsigned int nal_unit_type; - unsigned int nal_ref_idc; - - unsigned int colour_plane_id; - char field_pic_flag; - char bottom_field_flag; - - unsigned int redundant_pic_cnt; - - char sp_for_switch_flag; - int slice_qs_delta; - - char ref_pic_list_modification_flag_l0; - char ref_pic_list_modification_flag_l1; - - char no_output_of_prior_pics_flag; - char long_term_reference_flag; - char adaptive_ref_pic_marking_mode_flag; -} VAAPIEncodeH264MiscSliceParams; - -typedef struct VAAPIEncodeH264Slice { - VAAPIEncodeH264MiscSliceParams misc_slice_params; -} VAAPIEncodeH264Slice; +// Random (version 4) ISO 11578 UUID. +static const uint8_t vaapi_encode_h264_sei_identifier_uuid[16] = { + 0x59, 0x94, 0x8b, 0x28, 0x11, 0xec, 0x45, 0xaf, + 0x96, 0x75, 0x19, 0xd4, 0x1f, 0xea, 0xa9, 0x4d, +}; typedef struct VAAPIEncodeH264Context { - VAAPIEncodeH264MiscSequenceParams misc_sequence_params; - int mb_width; int mb_height; @@ -145,582 +53,108 @@ typedef struct VAAPIEncodeH264Context { int fixed_qp_p; int fixed_qp_b; + H264RawSPS sps; + H264RawPPS pps; + H264RawSEI sei; + H264RawSlice slice; + + H264RawSEIBufferingPeriod buffering_period; + H264RawSEIPicTiming pic_timing; + H264RawSEIUserDataUnregistered identifier; + char *identifier_string; + + int frame_num; + int pic_order_cnt; int next_frame_num; int64_t last_idr_frame; int64_t idr_pic_count; + int primary_pic_type; + int slice_type; + int cpb_delay; int dpb_delay; - // Rate control configuration. - int send_timing_sei; + CodedBitstreamContext cbc; + CodedBitstreamFragment current_access_unit; + int sei_needed; } VAAPIEncodeH264Context; typedef struct VAAPIEncodeH264Options { int qp; int quality; int low_power; + int sei; } VAAPIEncodeH264Options; -#define vseq_var(name) vseq->name, name -#define vseq_field(name) vseq->seq_fields.bits.name, name -#define vvui_field(name) vseq->vui_fields.bits.name, name -#define vpic_var(name) vpic->name, name -#define vpic_field(name) vpic->pic_fields.bits.name, name -#define vslice_var(name) vslice->name, name -#define vslice_field(name) vslice->slice_fields.bits.name, name -#define mseq_var(name) mseq->name, name -#define mslice_var(name) mslice->name, name - -static void vaapi_encode_h264_write_nal_header(PutBitContext *pbc, - int nal_unit_type, int nal_ref_idc) -{ - u(1, 0, forbidden_zero_bit); - u(2, nal_ref_idc, nal_ref_idc); - u(5, nal_unit_type, nal_unit_type); -} - -static void vaapi_encode_h264_write_trailing_rbsp(PutBitContext *pbc) -{ - u(1, 1, rbsp_stop_one_bit); - while (put_bits_count(pbc) & 7) - u(1, 0, rbsp_alignment_zero_bit); -} - -static void vaapi_encode_h264_write_vui(PutBitContext *pbc, - VAAPIEncodeContext *ctx) -{ - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - int i; - - u(1, vvui_field(aspect_ratio_info_present_flag)); - if (vseq->vui_fields.bits.aspect_ratio_info_present_flag) { - u(8, vseq_var(aspect_ratio_idc)); - if (vseq->aspect_ratio_idc == 255) { - u(16, vseq_var(sar_width)); - u(16, vseq_var(sar_height)); - } - } - - u(1, mseq_var(overscan_info_present_flag)); - if (mseq->overscan_info_present_flag) - u(1, mseq_var(overscan_appropriate_flag)); - - u(1, mseq_var(video_signal_type_present_flag)); - if (mseq->video_signal_type_present_flag) { - u(3, mseq_var(video_format)); - u(1, mseq_var(video_full_range_flag)); - u(1, mseq_var(colour_description_present_flag)); - if (mseq->colour_description_present_flag) { - u(8, mseq_var(colour_primaries)); - u(8, mseq_var(transfer_characteristics)); - u(8, mseq_var(matrix_coefficients)); - } - } - - u(1, mseq_var(chroma_loc_info_present_flag)); - if (mseq->chroma_loc_info_present_flag) { - ue(mseq_var(chroma_sample_loc_type_top_field)); - ue(mseq_var(chroma_sample_loc_type_bottom_field)); - } - - u(1, vvui_field(timing_info_present_flag)); - if (vseq->vui_fields.bits.timing_info_present_flag) { - u(32, vseq_var(num_units_in_tick)); - u(32, vseq_var(time_scale)); - u(1, mseq_var(fixed_frame_rate_flag)); - } - - u(1, mseq_var(nal_hrd_parameters_present_flag)); - if (mseq->nal_hrd_parameters_present_flag) { - ue(mseq_var(cpb_cnt_minus1)); - u(4, mseq_var(bit_rate_scale)); - u(4, mseq_var(cpb_size_scale)); - for (i = 0; i <= mseq->cpb_cnt_minus1; i++) { - ue(mseq_var(bit_rate_value_minus1[i])); - ue(mseq_var(cpb_size_value_minus1[i])); - u(1, mseq_var(cbr_flag[i])); - } - u(5, mseq_var(initial_cpb_removal_delay_length_minus1)); - u(5, mseq_var(cpb_removal_delay_length_minus1)); - u(5, mseq_var(dpb_output_delay_length_minus1)); - u(5, mseq_var(time_offset_length)); - } - u(1, mseq_var(vcl_hrd_parameters_present_flag)); - if (mseq->vcl_hrd_parameters_present_flag) { - av_assert0(0 && "vcl hrd parameters not supported"); - } - - if (mseq->nal_hrd_parameters_present_flag || - mseq->vcl_hrd_parameters_present_flag) - u(1, mseq_var(low_delay_hrd_flag)); - u(1, mseq_var(pic_struct_present_flag)); - - u(1, vvui_field(bitstream_restriction_flag)); - if (vseq->vui_fields.bits.bitstream_restriction_flag) { - u(1, mseq_var(motion_vectors_over_pic_boundaries_flag)); - ue(mseq_var(max_bytes_per_pic_denom)); - ue(mseq_var(max_bits_per_mb_denom)); - ue(vvui_field(log2_max_mv_length_horizontal)); - ue(vvui_field(log2_max_mv_length_vertical)); - ue(mseq_var(max_num_reorder_frames)); - ue(mseq_var(max_dec_pic_buffering)); - } -} - -static void vaapi_encode_h264_write_sps(PutBitContext *pbc, - VAAPIEncodeContext *ctx) -{ - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - int i; - - vaapi_encode_h264_write_nal_header(pbc, H264_NAL_SPS, 3); - - u(8, mseq_var(profile_idc)); - u(1, mseq_var(constraint_set0_flag)); - u(1, mseq_var(constraint_set1_flag)); - u(1, mseq_var(constraint_set2_flag)); - u(1, mseq_var(constraint_set3_flag)); - u(1, mseq_var(constraint_set4_flag)); - u(1, mseq_var(constraint_set5_flag)); - u(2, 0, reserved_zero_2bits); - - u(8, vseq_var(level_idc)); - - ue(vseq_var(seq_parameter_set_id)); - - if (mseq->profile_idc == 100 || mseq->profile_idc == 110 || - mseq->profile_idc == 122 || mseq->profile_idc == 244 || - mseq->profile_idc == 44 || mseq->profile_idc == 83 || - mseq->profile_idc == 86 || mseq->profile_idc == 118 || - mseq->profile_idc == 128 || mseq->profile_idc == 138) { - ue(vseq_field(chroma_format_idc)); - - if (vseq->seq_fields.bits.chroma_format_idc == 3) - u(1, mseq_var(separate_colour_plane_flag)); - - ue(vseq_var(bit_depth_luma_minus8)); - ue(vseq_var(bit_depth_chroma_minus8)); - - u(1, mseq_var(qpprime_y_zero_transform_bypass_flag)); - - u(1, vseq_field(seq_scaling_matrix_present_flag)); - if (vseq->seq_fields.bits.seq_scaling_matrix_present_flag) { - av_assert0(0 && "scaling matrices not supported"); - } - } - - ue(vseq_field(log2_max_frame_num_minus4)); - ue(vseq_field(pic_order_cnt_type)); - - if (vseq->seq_fields.bits.pic_order_cnt_type == 0) { - ue(vseq_field(log2_max_pic_order_cnt_lsb_minus4)); - } else if (vseq->seq_fields.bits.pic_order_cnt_type == 1) { - u(1, mseq_var(delta_pic_order_always_zero_flag)); - se(vseq_var(offset_for_non_ref_pic)); - se(vseq_var(offset_for_top_to_bottom_field)); - ue(vseq_var(num_ref_frames_in_pic_order_cnt_cycle)); - - for (i = 0; i < vseq->num_ref_frames_in_pic_order_cnt_cycle; i++) - se(vseq_var(offset_for_ref_frame[i])); - } - - ue(vseq_var(max_num_ref_frames)); - u(1, mseq_var(gaps_in_frame_num_allowed_flag)); - - ue(vseq->picture_width_in_mbs - 1, pic_width_in_mbs_minus1); - ue(vseq->picture_height_in_mbs - 1, pic_height_in_mbs_minus1); - - u(1, vseq_field(frame_mbs_only_flag)); - if (!vseq->seq_fields.bits.frame_mbs_only_flag) - u(1, vseq_field(mb_adaptive_frame_field_flag)); - - u(1, vseq_field(direct_8x8_inference_flag)); - - u(1, vseq_var(frame_cropping_flag)); - if (vseq->frame_cropping_flag) { - ue(vseq_var(frame_crop_left_offset)); - ue(vseq_var(frame_crop_right_offset)); - ue(vseq_var(frame_crop_top_offset)); - ue(vseq_var(frame_crop_bottom_offset)); - } - - u(1, vseq_var(vui_parameters_present_flag)); - if (vseq->vui_parameters_present_flag) - vaapi_encode_h264_write_vui(pbc, ctx); - - vaapi_encode_h264_write_trailing_rbsp(pbc); -} - -static void vaapi_encode_h264_write_pps(PutBitContext *pbc, - VAAPIEncodeContext *ctx) +static int vaapi_encode_h264_write_access_unit(AVCodecContext *avctx, + char *data, size_t *data_len, + CodedBitstreamFragment *au) { - VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - - vaapi_encode_h264_write_nal_header(pbc, H264_NAL_PPS, 3); - - ue(vpic_var(pic_parameter_set_id)); - ue(vpic_var(seq_parameter_set_id)); - - u(1, vpic_field(entropy_coding_mode_flag)); - u(1, mseq_var(bottom_field_pic_order_in_frame_present_flag)); - - ue(mseq_var(num_slice_groups_minus1)); - if (mseq->num_slice_groups_minus1 > 0) { - ue(mseq_var(slice_group_map_type)); - av_assert0(0 && "slice groups not supported"); - } - - ue(vpic_var(num_ref_idx_l0_active_minus1)); - ue(vpic_var(num_ref_idx_l1_active_minus1)); - - u(1, vpic_field(weighted_pred_flag)); - u(2, vpic_field(weighted_bipred_idc)); - - se(vpic->pic_init_qp - 26, pic_init_qp_minus26); - se(mseq_var(pic_init_qs_minus26)); - se(vpic_var(chroma_qp_index_offset)); - - u(1, vpic_field(deblocking_filter_control_present_flag)); - u(1, vpic_field(constrained_intra_pred_flag)); - u(1, vpic_field(redundant_pic_cnt_present_flag)); - u(1, vpic_field(transform_8x8_mode_flag)); - - u(1, vpic_field(pic_scaling_matrix_present_flag)); - if (vpic->pic_fields.bits.pic_scaling_matrix_present_flag) { - av_assert0(0 && "scaling matrices not supported"); - } - - se(vpic_var(second_chroma_qp_index_offset)); - - vaapi_encode_h264_write_trailing_rbsp(pbc); -} - -static void vaapi_encode_h264_write_slice_header2(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic, - VAAPIEncodeSlice *slice) -{ - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; - VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - VAAPIEncodeH264Slice *pslice = slice->priv_data; - VAAPIEncodeH264MiscSliceParams *mslice = &pslice->misc_slice_params; - - vaapi_encode_h264_write_nal_header(pbc, mslice->nal_unit_type, - mslice->nal_ref_idc); - - ue(vslice->macroblock_address, first_mb_in_slice); - ue(vslice_var(slice_type)); - ue(vpic_var(pic_parameter_set_id)); - - if (mseq->separate_colour_plane_flag) { - u(2, mslice_var(colour_plane_id)); - } - - u(4 + vseq->seq_fields.bits.log2_max_frame_num_minus4, - (vpic->frame_num & - ((1 << (4 + vseq->seq_fields.bits.log2_max_frame_num_minus4)) - 1)), - frame_num); - - if (!vseq->seq_fields.bits.frame_mbs_only_flag) { - u(1, mslice_var(field_pic_flag)); - if (mslice->field_pic_flag) - u(1, mslice_var(bottom_field_flag)); - } - - if (vpic->pic_fields.bits.idr_pic_flag) { - ue(vslice_var(idr_pic_id)); - } - - if (vseq->seq_fields.bits.pic_order_cnt_type == 0) { - u(4 + vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4, - vslice_var(pic_order_cnt_lsb)); - if (mseq->bottom_field_pic_order_in_frame_present_flag && - !mslice->field_pic_flag) { - se(vslice_var(delta_pic_order_cnt_bottom)); - } - } - - if (vseq->seq_fields.bits.pic_order_cnt_type == 1 && - !vseq->seq_fields.bits.delta_pic_order_always_zero_flag) { - se(vslice_var(delta_pic_order_cnt[0])); - if (mseq->bottom_field_pic_order_in_frame_present_flag && - !mslice->field_pic_flag) { - se(vslice_var(delta_pic_order_cnt[1])); - } - } - - if (vpic->pic_fields.bits.redundant_pic_cnt_present_flag) { - ue(mslice_var(redundant_pic_cnt)); - } - - if (vslice->slice_type == SLICE_TYPE_B) { - u(1, vslice_var(direct_spatial_mv_pred_flag)); - } - - if (vslice->slice_type == SLICE_TYPE_P || - vslice->slice_type == SLICE_TYPE_SP || - vslice->slice_type == SLICE_TYPE_B) { - u(1, vslice_var(num_ref_idx_active_override_flag)); - if (vslice->num_ref_idx_active_override_flag) { - ue(vslice_var(num_ref_idx_l0_active_minus1)); - if (vslice->slice_type == SLICE_TYPE_B) - ue(vslice_var(num_ref_idx_l1_active_minus1)); - } - } - - if (mslice->nal_unit_type == 20 || mslice->nal_unit_type == 21) { - av_assert0(0 && "no MVC support"); - } else { - if (vslice->slice_type % 5 != 2 && vslice->slice_type % 5 != 4) { - u(1, mslice_var(ref_pic_list_modification_flag_l0)); - if (mslice->ref_pic_list_modification_flag_l0) { - av_assert0(0 && "ref pic list modification"); - } - } - if (vslice->slice_type % 5 == 1) { - u(1, mslice_var(ref_pic_list_modification_flag_l1)); - if (mslice->ref_pic_list_modification_flag_l1) { - av_assert0(0 && "ref pic list modification"); - } - } - } - - if ((vpic->pic_fields.bits.weighted_pred_flag && - (vslice->slice_type == SLICE_TYPE_P || - vslice->slice_type == SLICE_TYPE_SP)) || - (vpic->pic_fields.bits.weighted_bipred_idc == 1 && - vslice->slice_type == SLICE_TYPE_B)) { - av_assert0(0 && "prediction weights not supported"); - } - - av_assert0(mslice->nal_ref_idc > 0 == - vpic->pic_fields.bits.reference_pic_flag); - if (mslice->nal_ref_idc != 0) { - if (vpic->pic_fields.bits.idr_pic_flag) { - u(1, mslice_var(no_output_of_prior_pics_flag)); - u(1, mslice_var(long_term_reference_flag)); - } else { - u(1, mslice_var(adaptive_ref_pic_marking_mode_flag)); - if (mslice->adaptive_ref_pic_marking_mode_flag) { - av_assert0(0 && "MMCOs not supported"); - } - } - } - - if (vpic->pic_fields.bits.entropy_coding_mode_flag && - vslice->slice_type != SLICE_TYPE_I && - vslice->slice_type != SLICE_TYPE_SI) { - ue(vslice_var(cabac_init_idc)); - } - - se(vslice_var(slice_qp_delta)); - if (vslice->slice_type == SLICE_TYPE_SP || - vslice->slice_type == SLICE_TYPE_SI) { - if (vslice->slice_type == SLICE_TYPE_SP) - u(1, mslice_var(sp_for_switch_flag)); - se(mslice_var(slice_qs_delta)); - } - - if (vpic->pic_fields.bits.deblocking_filter_control_present_flag) { - ue(vslice_var(disable_deblocking_filter_idc)); - if (vslice->disable_deblocking_filter_idc != 1) { - se(vslice_var(slice_alpha_c0_offset_div2)); - se(vslice_var(slice_beta_offset_div2)); - } - } - - if (mseq->num_slice_groups_minus1 > 0 && - mseq->slice_group_map_type >= 3 && mseq->slice_group_map_type <= 5) { - av_assert0(0 && "slice groups not supported"); - } - - // No alignment - this need not be a byte boundary. -} - -static void vaapi_encode_h264_write_buffering_period(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic) -{ - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; - int i; - - ue(vpic_var(seq_parameter_set_id)); + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + int err; - if (mseq->nal_hrd_parameters_present_flag) { - for (i = 0; i <= mseq->cpb_cnt_minus1; i++) { - u(mseq->initial_cpb_removal_delay_length_minus1 + 1, - mseq_var(initial_cpb_removal_delay)); - u(mseq->initial_cpb_removal_delay_length_minus1 + 1, - mseq_var(initial_cpb_removal_delay_offset)); - } - } - if (mseq->vcl_hrd_parameters_present_flag) { - av_assert0(0 && "vcl hrd parameters not supported"); + err = ff_cbs_write_fragment_data(&priv->cbc, au); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); + return err; } -} -static void vaapi_encode_h264_write_pic_timing(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic) -{ - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - int i, num_clock_ts; - - if (mseq->nal_hrd_parameters_present_flag || - mseq->vcl_hrd_parameters_present_flag) { - u(mseq->cpb_removal_delay_length_minus1 + 1, - 2 * vseq->num_units_in_tick * priv->cpb_delay, - cpb_removal_delay); - u(mseq->dpb_output_delay_length_minus1 + 1, - 2 * vseq->num_units_in_tick * priv->dpb_delay, - dpb_output_delay); - } - if (mseq->pic_struct_present_flag) { - u(4, mseq_var(pic_struct)); - num_clock_ts = (mseq->pic_struct <= 2 ? 1 : - mseq->pic_struct <= 4 ? 2 : - mseq->pic_struct <= 8 ? 3 : 0); - for (i = 0; i < num_clock_ts; i++) { - u(1, 0, clock_timestamp_flag[i]); - // No full timestamp information. - } + if (*data_len < 8 * au->data_size - au->data_bit_padding) { + av_log(avctx, AV_LOG_ERROR, "Access unit too large: " + "%zu < %zu.\n", *data_len, + 8 * au->data_size - au->data_bit_padding); + return AVERROR(ENOSPC); } -} -static void vaapi_encode_h264_write_identifier(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic) -{ - const char *lavc = LIBAVCODEC_IDENT; - const char *vaapi = VA_VERSION_S; - const char *driver = vaQueryVendorString(ctx->hwctx->display); - char tmp[256]; - int i; - - // Random (version 4) ISO 11578 UUID. - uint8_t uuid[16] = { - 0x59, 0x94, 0x8b, 0x28, 0x11, 0xec, 0x45, 0xaf, - 0x96, 0x75, 0x19, 0xd4, 0x1f, 0xea, 0xa9, 0x4d, - }; - - for (i = 0; i < 16; i++) - u(8, uuid[i], uuid_iso_iec_11578); + memcpy(data, au->data, au->data_size); + *data_len = 8 * au->data_size - au->data_bit_padding; - snprintf(tmp, sizeof(tmp), "%s / VAAPI %s / %s", lavc, vaapi, driver); - for (i = 0; i < sizeof(tmp) && tmp[i]; i++) - u(8, tmp[i], user_data_payload_byte); + return 0; } -static void vaapi_encode_h264_write_sei(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic) +static int vaapi_encode_h264_add_nal(AVCodecContext *avctx, + CodedBitstreamFragment *au, + void *nal_unit) { + VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH264Context *priv = ctx->priv_data; - PutBitContext payload_bits; - char payload[256]; - int payload_type, payload_size, i; - void (*write_payload)(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic) = NULL; - - vaapi_encode_h264_write_nal_header(pbc, H264_NAL_SEI, 0); - - for (payload_type = 0; payload_type < 64; payload_type++) { - switch (payload_type) { - case H264_SEI_TYPE_BUFFERING_PERIOD: - if (!priv->send_timing_sei || - pic->type != PICTURE_TYPE_IDR) - continue; - write_payload = &vaapi_encode_h264_write_buffering_period; - break; - case H264_SEI_TYPE_PIC_TIMING: - if (!priv->send_timing_sei) - continue; - write_payload = &vaapi_encode_h264_write_pic_timing; - break; - case H264_SEI_TYPE_USER_DATA_UNREGISTERED: - if (pic->encode_order != 0) - continue; - write_payload = &vaapi_encode_h264_write_identifier; - break; - default: - continue; - } - - init_put_bits(&payload_bits, payload, sizeof(payload)); - write_payload(&payload_bits, ctx, pic); - if (put_bits_count(&payload_bits) & 7) { - write_u(&payload_bits, 1, 1, bit_equal_to_one); - while (put_bits_count(&payload_bits) & 7) - write_u(&payload_bits, 1, 0, bit_equal_to_zero); - } - payload_size = put_bits_count(&payload_bits) / 8; - flush_put_bits(&payload_bits); + H264RawNALUnitHeader *header = nal_unit; + int err; - u(8, payload_type, last_payload_type_byte); - u(8, payload_size, last_payload_size_byte); - for (i = 0; i < payload_size; i++) - u(8, payload[i] & 0xff, sei_payload); + err = ff_cbs_insert_unit_content(&priv->cbc, au, -1, + header->nal_unit_type, nal_unit); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " + "type = %d.\n", header->nal_unit_type); + return err; } - vaapi_encode_h264_write_trailing_rbsp(pbc); + return 0; } static int vaapi_encode_h264_write_sequence_header(AVCodecContext *avctx, char *data, size_t *data_len) { - VAAPIEncodeContext *ctx = avctx->priv_data; - PutBitContext pbc; - char tmp[256]; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + CodedBitstreamFragment *au = &priv->current_access_unit; int err; - size_t nal_len, bit_len, bit_pos, next_len; - - bit_len = *data_len; - bit_pos = 0; - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h264_write_sps(&pbc, ctx); - nal_len = put_bits_count(&pbc); - flush_put_bits(&pbc); - - next_len = bit_len - bit_pos; - err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, - &next_len, - tmp, nal_len); + err = vaapi_encode_h264_add_nal(avctx, au, &priv->sps); if (err < 0) - return err; - bit_pos += next_len; - - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h264_write_pps(&pbc, ctx); - nal_len = put_bits_count(&pbc); - flush_put_bits(&pbc); + goto fail; - next_len = bit_len - bit_pos; - err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, - &next_len, - tmp, nal_len); + err = vaapi_encode_h264_add_nal(avctx, au, &priv->pps); if (err < 0) - return err; - bit_pos += next_len; + goto fail; - *data_len = bit_pos; - return 0; + err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au); +fail: + ff_cbs_fragment_uninit(&priv->cbc, au); + return err; } static int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx, @@ -728,18 +162,19 @@ static int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx, VAAPIEncodeSlice *slice, char *data, size_t *data_len) { - VAAPIEncodeContext *ctx = avctx->priv_data; - PutBitContext pbc; - char tmp[256]; - size_t header_len; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + CodedBitstreamFragment *au = &priv->current_access_unit; + int err; - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h264_write_slice_header2(&pbc, ctx, pic, slice); - header_len = put_bits_count(&pbc); - flush_put_bits(&pbc); + err = vaapi_encode_h264_add_nal(avctx, au, &priv->slice); + if (err < 0) + goto fail; - return ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data, data_len, - tmp, header_len); + err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au); +fail: + ff_cbs_fragment_uninit(&priv->cbc, au); + return err; } static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, @@ -747,196 +182,342 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, int index, int *type, char *data, size_t *data_len) { - VAAPIEncodeContext *ctx = avctx->priv_data; - PutBitContext pbc; - char tmp[256]; - size_t header_len; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264Options *opt = ctx->codec_options; + CodedBitstreamFragment *au = &priv->current_access_unit; + int err, i; + + if (priv->sei_needed) { + memset(&priv->sei, 0, sizeof(priv->sei)); + priv->sei.nal_unit_header.nal_unit_type = H264_NAL_SEI; + + i = 0; + if (pic->encode_order == 0 && opt->sei & SEI_IDENTIFIER) { + priv->sei.payload[i].payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED; + priv->sei.payload[i].payload.user_data_unregistered = priv->identifier; + ++i; + } + if (opt->sei & SEI_TIMING) { + if (pic->type == PICTURE_TYPE_IDR) { + priv->sei.payload[i].payload_type = H264_SEI_TYPE_BUFFERING_PERIOD; + priv->sei.payload[i].payload.buffering_period = priv->buffering_period; + ++i; + } + priv->sei.payload[i].payload_type = H264_SEI_TYPE_PIC_TIMING; + priv->sei.payload[i].payload.pic_timing = priv->pic_timing; + ++i; + } - if (index == 0 && ctx->va_rc_mode == VA_RC_CBR) { - *type = VAEncPackedHeaderH264_SEI; + priv->sei.payload_count = i; + av_assert0(priv->sei.payload_count > 0); + + err = vaapi_encode_h264_add_nal(avctx, au, &priv->sei); + if (err < 0) + goto fail; + priv->sei_needed = 0; - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h264_write_sei(&pbc, ctx, pic); - header_len = put_bits_count(&pbc); - flush_put_bits(&pbc); + err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au); + if (err < 0) + goto fail; - return ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data, data_len, - tmp, header_len); + ff_cbs_fragment_uninit(&priv->cbc, au); + *type = VAEncPackedHeaderH264_SEI; + return 0; } else { return AVERROR_EOF; } + +fail: + ff_cbs_fragment_uninit(&priv->cbc, au); + return err; } static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) { - VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - int i; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264Options *opt = ctx->codec_options; + H264RawSPS *sps = &priv->sps; + H264RawPPS *pps = &priv->pps; + VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params; - { - vseq->seq_parameter_set_id = 0; + memset(&priv->current_access_unit, 0, + sizeof(priv->current_access_unit)); - vseq->level_idc = avctx->level; + memset(sps, 0, sizeof(*sps)); + memset(pps, 0, sizeof(*pps)); - vseq->max_num_ref_frames = 1 + (avctx->max_b_frames > 0); + sps->nal_unit_header.nal_ref_idc = 3; + sps->nal_unit_header.nal_unit_type = H264_NAL_SPS; - vseq->picture_width_in_mbs = priv->mb_width; - vseq->picture_height_in_mbs = priv->mb_height; + sps->profile_idc = avctx->profile & 0xff; + sps->constraint_set1_flag = + !!(avctx->profile & FF_PROFILE_H264_CONSTRAINED); + sps->constraint_set3_flag = + !!(avctx->profile & FF_PROFILE_H264_INTRA); - vseq->seq_fields.bits.chroma_format_idc = 1; - vseq->seq_fields.bits.frame_mbs_only_flag = 1; - vseq->seq_fields.bits.direct_8x8_inference_flag = 1; - vseq->seq_fields.bits.log2_max_frame_num_minus4 = 4; - vseq->seq_fields.bits.pic_order_cnt_type = 0; - vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = - av_clip(av_log2(avctx->max_b_frames + 1) - 2, 0, 12); + sps->level_idc = avctx->level; - if (avctx->width != ctx->surface_width || - avctx->height != ctx->surface_height) { - vseq->frame_cropping_flag = 1; + sps->seq_parameter_set_id = 0; + sps->chroma_format_idc = 1; - vseq->frame_crop_left_offset = 0; - vseq->frame_crop_right_offset = - (ctx->surface_width - avctx->width) / 2; - vseq->frame_crop_top_offset = 0; - vseq->frame_crop_bottom_offset = - (ctx->surface_height - avctx->height) / 2; - } else { - vseq->frame_cropping_flag = 0; - } + sps->log2_max_frame_num_minus4 = 4; + sps->pic_order_cnt_type = 0; + sps->log2_max_pic_order_cnt_lsb_minus4 = + av_clip(av_log2(ctx->b_per_p + 1) - 2, 0, 12); + + sps->max_num_ref_frames = + (avctx->profile & FF_PROFILE_H264_INTRA) ? 0 : + 1 + (ctx->b_per_p > 0); + + sps->pic_width_in_mbs_minus1 = priv->mb_width - 1; + sps->pic_height_in_map_units_minus1 = priv->mb_height - 1; + + sps->frame_mbs_only_flag = 1; + sps->direct_8x8_inference_flag = 1; - vseq->vui_parameters_present_flag = 1; - if (avctx->sample_aspect_ratio.num != 0) { - vseq->vui_fields.bits.aspect_ratio_info_present_flag = 1; - // There is a large enum of these which we could support - // individually rather than using the generic X/Y form? - if (avctx->sample_aspect_ratio.num == - avctx->sample_aspect_ratio.den) { - vseq->aspect_ratio_idc = 1; - } else { - vseq->aspect_ratio_idc = 255; // Extended SAR. - vseq->sar_width = avctx->sample_aspect_ratio.num; - vseq->sar_height = avctx->sample_aspect_ratio.den; + if (avctx->width != 16 * priv->mb_width || + avctx->height != 16 * priv->mb_height) { + sps->frame_cropping_flag = 1; + + sps->frame_crop_left_offset = 0; + sps->frame_crop_right_offset = + (16 * priv->mb_width - avctx->width) / 2; + sps->frame_crop_top_offset = 0; + sps->frame_crop_bottom_offset = + (16 * priv->mb_height - avctx->height) / 2; + } else { + sps->frame_cropping_flag = 0; + } + + sps->vui_parameters_present_flag = 1; + + if (avctx->sample_aspect_ratio.num != 0 && + avctx->sample_aspect_ratio.den != 0) { + static const AVRational sar_idc[] = { + { 0, 0 }, + { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, + { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, + { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, + { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, + }; + int i; + for (i = 0; i < FF_ARRAY_ELEMS(sar_idc); i++) { + if (avctx->sample_aspect_ratio.num == sar_idc[i].num && + avctx->sample_aspect_ratio.den == sar_idc[i].den) { + sps->vui.aspect_ratio_idc = i; + break; } } + if (i >= FF_ARRAY_ELEMS(sar_idc)) { + sps->vui.aspect_ratio_idc = 255; + sps->vui.sar_width = avctx->sample_aspect_ratio.num; + sps->vui.sar_height = avctx->sample_aspect_ratio.den; + } + sps->vui.aspect_ratio_info_present_flag = 1; + } + + if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || + avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED || + avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { + sps->vui.video_signal_type_present_flag = 1; + sps->vui.video_format = 5; // Unspecified. + sps->vui.video_full_range_flag = + avctx->color_range == AVCOL_RANGE_JPEG; + if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || avctx->color_trc != AVCOL_TRC_UNSPECIFIED || avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { - mseq->video_signal_type_present_flag = 1; - mseq->video_format = 5; // Unspecified. - mseq->video_full_range_flag = 0; - mseq->colour_description_present_flag = 1; - // These enums are derived from the standard and hence - // we can just use the values directly. - mseq->colour_primaries = avctx->color_primaries; - mseq->transfer_characteristics = avctx->color_trc; - mseq->matrix_coefficients = avctx->colorspace; + sps->vui.colour_description_present_flag = 1; + sps->vui.colour_primaries = avctx->color_primaries; + sps->vui.transfer_characteristics = avctx->color_trc; + sps->vui.matrix_coefficients = avctx->colorspace; } + } else { + sps->vui.video_format = 5; + sps->vui.video_full_range_flag = 0; + sps->vui.colour_primaries = avctx->color_primaries; + sps->vui.transfer_characteristics = avctx->color_trc; + sps->vui.matrix_coefficients = avctx->colorspace; + } - vseq->vui_fields.bits.bitstream_restriction_flag = 1; - mseq->motion_vectors_over_pic_boundaries_flag = 1; - mseq->max_bytes_per_pic_denom = 0; - mseq->max_bits_per_mb_denom = 0; - vseq->vui_fields.bits.log2_max_mv_length_horizontal = 16; - vseq->vui_fields.bits.log2_max_mv_length_vertical = 16; - - mseq->max_num_reorder_frames = (avctx->max_b_frames > 0); - mseq->max_dec_pic_buffering = vseq->max_num_ref_frames; - - vseq->bits_per_second = avctx->bit_rate; + if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) { + sps->vui.chroma_loc_info_present_flag = 1; + sps->vui.chroma_sample_loc_type_top_field = + sps->vui.chroma_sample_loc_type_bottom_field = + avctx->chroma_sample_location - 1; + } - vseq->vui_fields.bits.timing_info_present_flag = 1; - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { - vseq->num_units_in_tick = avctx->framerate.den; - vseq->time_scale = 2 * avctx->framerate.num; - mseq->fixed_frame_rate_flag = 1; - } else { - vseq->num_units_in_tick = avctx->time_base.num; - vseq->time_scale = 2 * avctx->time_base.den; - mseq->fixed_frame_rate_flag = 0; - } + sps->vui.timing_info_present_flag = 1; + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + sps->vui.num_units_in_tick = avctx->framerate.den; + sps->vui.time_scale = 2 * avctx->framerate.num; + sps->vui.fixed_frame_rate_flag = 1; + } else { + sps->vui.num_units_in_tick = avctx->time_base.num; + sps->vui.time_scale = 2 * avctx->time_base.den; + sps->vui.fixed_frame_rate_flag = 0; + } - if (ctx->va_rc_mode == VA_RC_CBR) { - priv->send_timing_sei = 1; - mseq->nal_hrd_parameters_present_flag = 1; + if (opt->sei & SEI_TIMING) { + H264RawHRD *hrd = &sps->vui.nal_hrd_parameters; - mseq->cpb_cnt_minus1 = 0; + sps->vui.nal_hrd_parameters_present_flag = 1; - // Try to scale these to a sensible range so that the - // golomb encode of the value is not overlong. - mseq->bit_rate_scale = - av_clip_uintp2(av_log2(avctx->bit_rate) - 15 - 6, 4); - mseq->bit_rate_value_minus1[0] = - (avctx->bit_rate >> mseq->bit_rate_scale + 6) - 1; + hrd->cpb_cnt_minus1 = 0; - mseq->cpb_size_scale = - av_clip_uintp2(av_log2(ctx->hrd_params.hrd.buffer_size) - 15 - 4, 4); - mseq->cpb_size_value_minus1[0] = - (ctx->hrd_params.hrd.buffer_size >> mseq->cpb_size_scale + 4) - 1; + // Try to scale these to a sensible range so that the + // golomb encode of the value is not overlong. + hrd->bit_rate_scale = + av_clip_uintp2(av_log2(avctx->bit_rate) - 15 - 6, 4); + hrd->bit_rate_value_minus1[0] = + (avctx->bit_rate >> hrd->bit_rate_scale + 6) - 1; - // CBR mode isn't actually available here, despite naming. - mseq->cbr_flag[0] = 0; + hrd->cpb_size_scale = + av_clip_uintp2(av_log2(ctx->hrd_params.hrd.buffer_size) - 15 - 4, 4); + hrd->cpb_size_value_minus1[0] = + (ctx->hrd_params.hrd.buffer_size >> hrd->cpb_size_scale + 4) - 1; - mseq->initial_cpb_removal_delay_length_minus1 = 23; - mseq->cpb_removal_delay_length_minus1 = 23; - mseq->dpb_output_delay_length_minus1 = 7; - mseq->time_offset_length = 0; + // CBR mode as defined for the HRD cannot be achieved without filler + // data, so this flag cannot be set even with VAAPI CBR modes. + hrd->cbr_flag[0] = 0; - // This calculation can easily overflow 32 bits. - mseq->initial_cpb_removal_delay = 90000 * - (uint64_t)ctx->hrd_params.hrd.initial_buffer_fullness / - ctx->hrd_params.hrd.buffer_size; + hrd->initial_cpb_removal_delay_length_minus1 = 23; + hrd->cpb_removal_delay_length_minus1 = 23; + hrd->dpb_output_delay_length_minus1 = 7; + hrd->time_offset_length = 0; - mseq->initial_cpb_removal_delay_offset = 0; - } else { - priv->send_timing_sei = 0; - mseq->nal_hrd_parameters_present_flag = 0; - } + priv->buffering_period.seq_parameter_set_id = sps->seq_parameter_set_id; - vseq->intra_period = avctx->gop_size; - vseq->intra_idr_period = avctx->gop_size; - vseq->ip_period = ctx->b_per_p + 1; + // This calculation can easily overflow 32 bits. + priv->buffering_period.nal.initial_cpb_removal_delay[0] = 90000 * + (uint64_t)ctx->hrd_params.hrd.initial_buffer_fullness / + ctx->hrd_params.hrd.buffer_size; + priv->buffering_period.nal.initial_cpb_removal_delay_offset[0] = 0; + } else { + sps->vui.nal_hrd_parameters_present_flag = 0; + sps->vui.low_delay_hrd_flag = 1 - sps->vui.fixed_frame_rate_flag; } - { - vpic->CurrPic.picture_id = VA_INVALID_ID; - vpic->CurrPic.flags = VA_PICTURE_H264_INVALID; - - for (i = 0; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) { - vpic->ReferenceFrames[i].picture_id = VA_INVALID_ID; - vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID; - } + sps->vui.bitstream_restriction_flag = 1; + sps->vui.motion_vectors_over_pic_boundaries_flag = 1; + sps->vui.log2_max_mv_length_horizontal = 16; + sps->vui.log2_max_mv_length_vertical = 16; + sps->vui.max_num_reorder_frames = (ctx->b_per_p > 0); + sps->vui.max_dec_frame_buffering = vseq->max_num_ref_frames; - vpic->coded_buf = VA_INVALID_ID; + pps->nal_unit_header.nal_ref_idc = 3; + pps->nal_unit_header.nal_unit_type = H264_NAL_PPS; - vpic->pic_parameter_set_id = 0; - vpic->seq_parameter_set_id = 0; + pps->pic_parameter_set_id = 0; + pps->seq_parameter_set_id = 0; - vpic->num_ref_idx_l0_active_minus1 = 0; - vpic->num_ref_idx_l1_active_minus1 = 0; + pps->entropy_coding_mode_flag = + !(sps->profile_idc == FF_PROFILE_H264_BASELINE || + sps->profile_idc == FF_PROFILE_H264_EXTENDED || + sps->profile_idc == FF_PROFILE_H264_CAVLC_444); - vpic->pic_fields.bits.entropy_coding_mode_flag = - ((avctx->profile & 0xff) != 66); - vpic->pic_fields.bits.weighted_pred_flag = 0; - vpic->pic_fields.bits.weighted_bipred_idc = 0; - vpic->pic_fields.bits.transform_8x8_mode_flag = - ((avctx->profile & 0xff) >= 100); + pps->num_ref_idx_l0_default_active_minus1 = 0; + pps->num_ref_idx_l1_default_active_minus1 = 0; - vpic->pic_init_qp = priv->fixed_qp_idr; - } + pps->pic_init_qp_minus26 = priv->fixed_qp_idr - 26; - { - mseq->profile_idc = avctx->profile & 0xff; + if (sps->profile_idc == FF_PROFILE_H264_BASELINE || + sps->profile_idc == FF_PROFILE_H264_EXTENDED || + sps->profile_idc == FF_PROFILE_H264_MAIN) { + pps->more_rbsp_data = 0; + } else { + pps->more_rbsp_data = 1; + + pps->transform_8x8_mode_flag = 1; + } + + *vseq = (VAEncSequenceParameterBufferH264) { + .seq_parameter_set_id = sps->seq_parameter_set_id, + .level_idc = sps->level_idc, + .intra_period = avctx->gop_size, + .intra_idr_period = avctx->gop_size, + .ip_period = ctx->b_per_p + 1, + + .bits_per_second = avctx->bit_rate, + .max_num_ref_frames = sps->max_num_ref_frames, + .picture_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1, + .picture_height_in_mbs = sps->pic_height_in_map_units_minus1 + 1, + + .seq_fields.bits = { + .chroma_format_idc = sps->chroma_format_idc, + .frame_mbs_only_flag = sps->frame_mbs_only_flag, + .mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag, + .seq_scaling_matrix_present_flag = sps->seq_scaling_matrix_present_flag, + .direct_8x8_inference_flag = sps->direct_8x8_inference_flag, + .log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4, + .pic_order_cnt_type = sps->pic_order_cnt_type, + .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4, + .delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag, + }, + + .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8, + .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8, + + .frame_cropping_flag = sps->frame_cropping_flag, + .frame_crop_left_offset = sps->frame_crop_left_offset, + .frame_crop_right_offset = sps->frame_crop_right_offset, + .frame_crop_top_offset = sps->frame_crop_top_offset, + .frame_crop_bottom_offset = sps->frame_crop_bottom_offset, + + .vui_parameters_present_flag = sps->vui_parameters_present_flag, + + .vui_fields.bits = { + .aspect_ratio_info_present_flag = sps->vui.aspect_ratio_info_present_flag, + .timing_info_present_flag = sps->vui.timing_info_present_flag, + .bitstream_restriction_flag = sps->vui.bitstream_restriction_flag, + .log2_max_mv_length_horizontal = sps->vui.log2_max_mv_length_horizontal, + .log2_max_mv_length_vertical = sps->vui.log2_max_mv_length_vertical, + }, + + .aspect_ratio_idc = sps->vui.aspect_ratio_idc, + .sar_width = sps->vui.sar_width, + .sar_height = sps->vui.sar_height, + .num_units_in_tick = sps->vui.num_units_in_tick, + .time_scale = sps->vui.time_scale, + }; - if (avctx->profile & FF_PROFILE_H264_CONSTRAINED) - mseq->constraint_set1_flag = 1; - if (avctx->profile & FF_PROFILE_H264_INTRA) - mseq->constraint_set3_flag = 1; - } + *vpic = (VAEncPictureParameterBufferH264) { + .CurrPic = { + .picture_id = VA_INVALID_ID, + .flags = VA_PICTURE_H264_INVALID, + }, + + .coded_buf = VA_INVALID_ID, + + .pic_parameter_set_id = pps->pic_parameter_set_id, + .seq_parameter_set_id = pps->seq_parameter_set_id, + + .pic_init_qp = pps->pic_init_qp_minus26 + 26, + .num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1, + .num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1, + + .chroma_qp_index_offset = pps->chroma_qp_index_offset, + .second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset, + + .pic_fields.bits = { + .entropy_coding_mode_flag = pps->entropy_coding_mode_flag, + .weighted_pred_flag = pps->weighted_pred_flag, + .weighted_bipred_idc = pps->weighted_bipred_idc, + .constrained_intra_pred_flag = pps->constrained_intra_pred_flag, + .transform_8x8_mode_flag = pps->transform_8x8_mode_flag, + .deblocking_filter_control_present_flag = + pps->deblocking_filter_control_present_flag, + .redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag, + .pic_order_present_flag = + pps->bottom_field_pic_order_in_frame_present_flag, + .pic_scaling_matrix_present_flag = pps->pic_scaling_matrix_present_flag, + }, + }; return 0; } @@ -944,54 +525,99 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, VAAPIEncodePicture *pic) { - VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264Options *opt = ctx->codec_options; + H264RawSPS *sps = &priv->sps; + VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; int i; + memset(&priv->current_access_unit, 0, + sizeof(priv->current_access_unit)); + if (pic->type == PICTURE_TYPE_IDR) { av_assert0(pic->display_order == pic->encode_order); - vpic->frame_num = 0; + priv->frame_num = 0; priv->next_frame_num = 1; - priv->cpb_delay = 0; + priv->cpb_delay = 0; priv->last_idr_frame = pic->display_order; + ++priv->idr_pic_count; + + priv->slice_type = 7; + priv->primary_pic_type = 0; } else { - vpic->frame_num = priv->next_frame_num; + priv->frame_num = priv->next_frame_num; + if (pic->type != PICTURE_TYPE_B) { - // nal_ref_idc != 0 - ++priv->next_frame_num; + // Reference picture, so frame_num advances. + priv->next_frame_num = (priv->frame_num + 1) & + ((1 << (4 + sps->log2_max_frame_num_minus4)) - 1); } ++priv->cpb_delay; + + if (pic->type == PICTURE_TYPE_I) { + priv->slice_type = 7; + priv->primary_pic_type = 0; + } else if (pic->type == PICTURE_TYPE_P) { + priv->slice_type = 5; + priv->primary_pic_type = 1; + } else { + priv->slice_type = 6; + priv->primary_pic_type = 2; + } } - priv->dpb_delay = pic->display_order - pic->encode_order + 1; + priv->pic_order_cnt = pic->display_order - priv->last_idr_frame; + priv->dpb_delay = pic->display_order - pic->encode_order + 1; - vpic->frame_num = vpic->frame_num & - ((1 << (4 + vseq->seq_fields.bits.log2_max_frame_num_minus4)) - 1); + if (opt->sei & SEI_IDENTIFIER && pic->encode_order == 0) + priv->sei_needed = 1; + + if (opt->sei & SEI_TIMING) { + memset(&priv->pic_timing, 0, sizeof(priv->pic_timing)); + + priv->pic_timing.cpb_removal_delay = + 2 * sps->vui.num_units_in_tick * priv->cpb_delay; + priv->pic_timing.dpb_output_delay = + 2 * sps->vui.num_units_in_tick * priv->dpb_delay; + + priv->sei_needed = 1; + } - vpic->CurrPic.picture_id = pic->recon_surface; - vpic->CurrPic.frame_idx = vpic->frame_num; - vpic->CurrPic.flags = 0; - vpic->CurrPic.TopFieldOrderCnt = pic->display_order - priv->last_idr_frame; - vpic->CurrPic.BottomFieldOrderCnt = pic->display_order - priv->last_idr_frame; + vpic->CurrPic = (VAPictureH264) { + .picture_id = pic->recon_surface, + .frame_idx = priv->frame_num, + .flags = 0, + .TopFieldOrderCnt = priv->pic_order_cnt, + .BottomFieldOrderCnt = priv->pic_order_cnt, + }; for (i = 0; i < pic->nb_refs; i++) { VAAPIEncodePicture *ref = pic->refs[i]; + unsigned int frame_num = (ref->encode_order - priv->last_idr_frame) & + ((1 << (4 + sps->log2_max_frame_num_minus4)) - 1); + unsigned int pic_order_cnt = ref->display_order - priv->last_idr_frame; + av_assert0(ref && ref->encode_order < pic->encode_order); - vpic->ReferenceFrames[i].picture_id = ref->recon_surface; - vpic->ReferenceFrames[i].frame_idx = ref->encode_order; - vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE; - vpic->ReferenceFrames[i].TopFieldOrderCnt = ref->display_order - priv->last_idr_frame; - vpic->ReferenceFrames[i].BottomFieldOrderCnt = ref->display_order - priv->last_idr_frame; + vpic->ReferenceFrames[i] = (VAPictureH264) { + .picture_id = ref->recon_surface, + .frame_idx = frame_num, + .flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE, + .TopFieldOrderCnt = pic_order_cnt, + .BottomFieldOrderCnt = pic_order_cnt, + }; } for (; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) { - vpic->ReferenceFrames[i].picture_id = VA_INVALID_ID; - vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID; + vpic->ReferenceFrames[i] = (VAPictureH264) { + .picture_id = VA_INVALID_ID, + .flags = VA_PICTURE_H264_INVALID, + }; } vpic->coded_buf = pic->output_buffer; - vpic->pic_fields.bits.idr_pic_flag = (pic->type == PICTURE_TYPE_IDR); + vpic->frame_num = priv->frame_num; + + vpic->pic_fields.bits.idr_pic_flag = (pic->type == PICTURE_TYPE_IDR); vpic->pic_fields.bits.reference_pic_flag = (pic->type != PICTURE_TYPE_B); pic->nb_slices = 1; @@ -1003,58 +629,57 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx, VAAPIEncodePicture *pic, VAAPIEncodeSlice *slice) { - VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; - VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264Slice *pslice; - VAAPIEncodeH264MiscSliceParams *mslice; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + H264RawSPS *sps = &priv->sps; + H264RawPPS *pps = &priv->pps; + H264RawSliceHeader *sh = &priv->slice.header; + VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; + VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params; int i; - slice->priv_data = av_mallocz(sizeof(*pslice)); - if (!slice->priv_data) - return AVERROR(ENOMEM); - pslice = slice->priv_data; - mslice = &pslice->misc_slice_params; + if (pic->type == PICTURE_TYPE_IDR) { + sh->nal_unit_header.nal_unit_type = H264_NAL_IDR_SLICE; + sh->nal_unit_header.nal_ref_idc = 3; + } else { + sh->nal_unit_header.nal_unit_type = H264_NAL_SLICE; + sh->nal_unit_header.nal_ref_idc = pic->type != PICTURE_TYPE_B; + } + + // Only one slice per frame. + sh->first_mb_in_slice = 0; + sh->slice_type = priv->slice_type; + + sh->pic_parameter_set_id = pps->pic_parameter_set_id; - if (pic->type == PICTURE_TYPE_IDR) - mslice->nal_unit_type = H264_NAL_IDR_SLICE; + sh->frame_num = priv->frame_num; + sh->idr_pic_id = priv->idr_pic_count; + + sh->pic_order_cnt_lsb = priv->pic_order_cnt & + ((1 << (4 + sps->log2_max_pic_order_cnt_lsb_minus4)) - 1); + + sh->direct_spatial_mv_pred_flag = 1; + + if (pic->type == PICTURE_TYPE_B) + sh->slice_qp_delta = priv->fixed_qp_b - (pps->pic_init_qp_minus26 + 26); + else if (pic->type == PICTURE_TYPE_P) + sh->slice_qp_delta = priv->fixed_qp_p - (pps->pic_init_qp_minus26 + 26); else - mslice->nal_unit_type = H264_NAL_SLICE; + sh->slice_qp_delta = priv->fixed_qp_idr - (pps->pic_init_qp_minus26 + 26); - switch (pic->type) { - case PICTURE_TYPE_IDR: - vslice->slice_type = SLICE_TYPE_I; - mslice->nal_ref_idc = 3; - break; - case PICTURE_TYPE_I: - vslice->slice_type = SLICE_TYPE_I; - mslice->nal_ref_idc = 2; - break; - case PICTURE_TYPE_P: - vslice->slice_type = SLICE_TYPE_P; - mslice->nal_ref_idc = 1; - break; - case PICTURE_TYPE_B: - vslice->slice_type = SLICE_TYPE_B; - mslice->nal_ref_idc = 0; - break; - default: - av_assert0(0 && "invalid picture type"); - } - // Only one slice per frame. - vslice->macroblock_address = 0; - vslice->num_macroblocks = priv->mb_width * priv->mb_height; + vslice->macroblock_address = sh->first_mb_in_slice; + vslice->num_macroblocks = priv->mb_width * priv->mb_height; vslice->macroblock_info = VA_INVALID_ID; - vslice->pic_parameter_set_id = vpic->pic_parameter_set_id; - vslice->idr_pic_id = priv->idr_pic_count++; + vslice->slice_type = sh->slice_type % 5; + vslice->pic_parameter_set_id = sh->pic_parameter_set_id; + vslice->idr_pic_id = sh->idr_pic_id; + + vslice->pic_order_cnt_lsb = sh->pic_order_cnt_lsb; - vslice->pic_order_cnt_lsb = (pic->display_order - priv->last_idr_frame) & - ((1 << (4 + vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4)) - 1); + vslice->direct_spatial_mv_pred_flag = sh->direct_spatial_mv_pred_flag; for (i = 0; i < FF_ARRAY_ELEMS(vslice->RefPicList0); i++) { vslice->RefPicList0[i].picture_id = VA_INVALID_ID; @@ -1068,26 +693,15 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx, // Backward reference for P- or B-frame. av_assert0(pic->type == PICTURE_TYPE_P || pic->type == PICTURE_TYPE_B); - - vslice->num_ref_idx_l0_active_minus1 = 0; vslice->RefPicList0[0] = vpic->ReferenceFrames[0]; } if (pic->nb_refs >= 2) { // Forward reference for B-frame. av_assert0(pic->type == PICTURE_TYPE_B); - - vslice->num_ref_idx_l1_active_minus1 = 0; vslice->RefPicList1[0] = vpic->ReferenceFrames[1]; } - if (pic->type == PICTURE_TYPE_B) - vslice->slice_qp_delta = priv->fixed_qp_b - vpic->pic_init_qp; - else if (pic->type == PICTURE_TYPE_P) - vslice->slice_qp_delta = priv->fixed_qp_p - vpic->pic_init_qp; - else - vslice->slice_qp_delta = priv->fixed_qp_idr - vpic->pic_init_qp; - - vslice->direct_spatial_mv_pred_flag = 1; + vslice->slice_qp_delta = sh->slice_qp_delta; return 0; } @@ -1097,6 +711,11 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx) VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH264Context *priv = ctx->priv_data; VAAPIEncodeH264Options *opt = ctx->codec_options; + int err; + + err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_H264, avctx); + if (err < 0) + return err; priv->mb_width = FFALIGN(avctx->width, 16) / 16; priv->mb_height = FFALIGN(avctx->height, 16) / 16; @@ -1114,6 +733,8 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx) else priv->fixed_qp_b = priv->fixed_qp_p; + opt->sei &= ~SEI_TIMING; + av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = " "%d / %d / %d for IDR- / P- / B-frames.\n", priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b); @@ -1136,6 +757,34 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx) if (avctx->compression_level == FF_COMPRESSION_DEFAULT) avctx->compression_level = opt->quality; + if (opt->sei & SEI_IDENTIFIER) { + const char *lavc = LIBAVCODEC_IDENT; + const char *vaapi = VA_VERSION_S; + const char *driver; + int len; + + memcpy(priv->identifier.uuid_iso_iec_11578, + vaapi_encode_h264_sei_identifier_uuid, + sizeof(priv->identifier.uuid_iso_iec_11578)); + + driver = vaQueryVendorString(ctx->hwctx->display); + if (!driver) + driver = "unknown driver"; + + len = snprintf(NULL, 0, "%s / VAAPI %s / %s", lavc, vaapi, driver); + if (len >= 0) { + priv->identifier_string = av_malloc(len + 1); + if (!priv->identifier_string) + return AVERROR(ENOMEM); + + snprintf(priv->identifier_string, len + 1, + "%s / VAAPI %s / %s", lavc, vaapi, driver); + + priv->identifier.data = priv->identifier_string; + priv->identifier.data_length = len + 1; + } + } + return 0; } @@ -1241,6 +890,19 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx) return ff_vaapi_encode_init(avctx); } +static av_cold int vaapi_encode_h264_close(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + + if (priv) { + ff_cbs_close(&priv->cbc); + av_freep(&priv->identifier_string); + } + + return ff_vaapi_encode_close(avctx); +} + #define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \ offsetof(VAAPIEncodeH264Options, x)) #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) @@ -1252,6 +914,17 @@ static const AVOption vaapi_encode_h264_options[] = { { "low_power", "Use low-power encoding mode (experimental: only supported " "on some platforms, does not support all features)", OFFSET(low_power), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, + + { "sei", "Set SEI to include", + OFFSET(sei), AV_OPT_TYPE_FLAGS, + { .i64 = SEI_IDENTIFIER | SEI_TIMING }, + 0, INT_MAX, FLAGS, "sei" }, + { "identifier", "Include encoder version identifier", + 0, AV_OPT_TYPE_CONST, { .i64 = SEI_IDENTIFIER }, + INT_MIN, INT_MAX, FLAGS, "sei" }, + { "timing", "Include timing parameters (buffering_period and pic_timing)", + 0, AV_OPT_TYPE_CONST, { .i64 = SEI_TIMING }, + INT_MIN, INT_MAX, FLAGS, "sei" }, { NULL }, }; @@ -1285,7 +958,7 @@ AVCodec ff_h264_vaapi_encoder = { sizeof(VAAPIEncodeH264Options)), .init = &vaapi_encode_h264_init, .encode2 = &ff_vaapi_encode2, - .close = &ff_vaapi_encode_close, + .close = &vaapi_encode_h264_close, .priv_class = &vaapi_encode_h264_class, .capabilities = AV_CODEC_CAP_DELAY, .defaults = vaapi_encode_h264_defaults, From 820a4483af13cf6fd51f13638e57bcd1c3f629d4 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 7 May 2017 22:58:56 +0100 Subject: [PATCH 0356/2557] vaapi_h264: Add support for AUD NAL units Adds a new private option to enable them (off by default). --- libavcodec/vaapi_encode_h264.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index b48070c950da2..4f0e879e9b268 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -53,6 +53,7 @@ typedef struct VAAPIEncodeH264Context { int fixed_qp_p; int fixed_qp_b; + H264RawAUD aud; H264RawSPS sps; H264RawPPS pps; H264RawSEI sei; @@ -77,6 +78,7 @@ typedef struct VAAPIEncodeH264Context { CodedBitstreamContext cbc; CodedBitstreamFragment current_access_unit; + int aud_needed; int sei_needed; } VAAPIEncodeH264Context; @@ -84,6 +86,7 @@ typedef struct VAAPIEncodeH264Options { int qp; int quality; int low_power; + int aud; int sei; } VAAPIEncodeH264Options; @@ -143,6 +146,13 @@ static int vaapi_encode_h264_write_sequence_header(AVCodecContext *avctx, CodedBitstreamFragment *au = &priv->current_access_unit; int err; + if (priv->aud_needed) { + err = vaapi_encode_h264_add_nal(avctx, au, &priv->aud); + if (err < 0) + goto fail; + priv->aud_needed = 0; + } + err = vaapi_encode_h264_add_nal(avctx, au, &priv->sps); if (err < 0) goto fail; @@ -167,6 +177,13 @@ static int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx, CodedBitstreamFragment *au = &priv->current_access_unit; int err; + if (priv->aud_needed) { + err = vaapi_encode_h264_add_nal(avctx, au, &priv->aud); + if (err < 0) + goto fail; + priv->aud_needed = 0; + } + err = vaapi_encode_h264_add_nal(avctx, au, &priv->slice); if (err < 0) goto fail; @@ -189,6 +206,11 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, int err, i; if (priv->sei_needed) { + if (priv->aud_needed) { + vaapi_encode_h264_add_nal(avctx, au, &priv->aud); + priv->aud_needed = 0; + } + memset(&priv->sei, 0, sizeof(priv->sei)); priv->sei.nal_unit_header.nal_unit_type = H264_NAL_SEI; @@ -569,6 +591,14 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, priv->pic_order_cnt = pic->display_order - priv->last_idr_frame; priv->dpb_delay = pic->display_order - pic->encode_order + 1; + if (opt->aud) { + priv->aud_needed = 1; + priv->aud.nal_unit_header.nal_unit_type = H264_NAL_AUD; + priv->aud.primary_pic_type = priv->primary_pic_type; + } else { + priv->aud_needed = 0; + } + if (opt->sei & SEI_IDENTIFIER && pic->encode_order == 0) priv->sei_needed = 1; @@ -915,6 +945,9 @@ static const AVOption vaapi_encode_h264_options[] = { "on some platforms, does not support all features)", OFFSET(low_power), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, + { "aud", "Include AUD", + OFFSET(aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, + { "sei", "Set SEI to include", OFFSET(sei), AV_OPT_TYPE_FLAGS, { .i64 = SEI_IDENTIFIER | SEI_TIMING }, From a49ee60d5fdbdae1706a44cfbb814abb9793815f Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 7 May 2017 23:02:09 +0100 Subject: [PATCH 0357/2557] vaapi_h264: Add support for SEI recovery points Included by default with non-IDR intra frames. --- libavcodec/vaapi_encode_h264.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 4f0e879e9b268..271644ebbeebc 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -37,6 +37,7 @@ enum { SEI_TIMING = 0x01, SEI_IDENTIFIER = 0x02, + SEI_RECOVERY_POINT = 0x04, }; // Random (version 4) ISO 11578 UUID. @@ -61,6 +62,7 @@ typedef struct VAAPIEncodeH264Context { H264RawSEIBufferingPeriod buffering_period; H264RawSEIPicTiming pic_timing; + H264RawSEIRecoveryPoint recovery_point; H264RawSEIUserDataUnregistered identifier; char *identifier_string; @@ -230,6 +232,11 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, priv->sei.payload[i].payload.pic_timing = priv->pic_timing; ++i; } + if (opt->sei & SEI_RECOVERY_POINT && pic->type == PICTURE_TYPE_I) { + priv->sei.payload[i].payload_type = H264_SEI_TYPE_RECOVERY_POINT; + priv->sei.payload[i].payload.recovery_point = priv->recovery_point; + ++i; + } priv->sei.payload_count = i; av_assert0(priv->sei.payload_count > 0); @@ -613,6 +620,14 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, priv->sei_needed = 1; } + if (opt->sei & SEI_RECOVERY_POINT && pic->type == PICTURE_TYPE_I) { + priv->recovery_point.recovery_frame_cnt = 0; + priv->recovery_point.exact_match_flag = 1; + priv->recovery_point.broken_link_flag = ctx->b_per_p > 0; + + priv->sei_needed = 1; + } + vpic->CurrPic = (VAPictureH264) { .picture_id = pic->recon_surface, .frame_idx = priv->frame_num, @@ -950,7 +965,7 @@ static const AVOption vaapi_encode_h264_options[] = { { "sei", "Set SEI to include", OFFSET(sei), AV_OPT_TYPE_FLAGS, - { .i64 = SEI_IDENTIFIER | SEI_TIMING }, + { .i64 = SEI_IDENTIFIER | SEI_TIMING | SEI_RECOVERY_POINT }, 0, INT_MAX, FLAGS, "sei" }, { "identifier", "Include encoder version identifier", 0, AV_OPT_TYPE_CONST, { .i64 = SEI_IDENTIFIER }, @@ -958,6 +973,9 @@ static const AVOption vaapi_encode_h264_options[] = { { "timing", "Include timing parameters (buffering_period and pic_timing)", 0, AV_OPT_TYPE_CONST, { .i64 = SEI_TIMING }, INT_MIN, INT_MAX, FLAGS, "sei" }, + { "recovery_point", "Include recovery points where appropriate", + 0, AV_OPT_TYPE_CONST, { .i64 = SEI_RECOVERY_POINT }, + INT_MIN, INT_MAX, FLAGS, "sei" }, { NULL }, }; From ac12486714b48f9bd5d9167f90b77c936751d6ef Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 14 May 2017 21:36:24 +0100 Subject: [PATCH 0358/2557] vaapi_h265: Convert to use coded bitstream infrastructure Also improves the metadata and generally makes the configuration a bit cleaner. --- configure | 2 +- libavcodec/Makefile | 2 +- libavcodec/vaapi_encode_h265.c | 1537 ++++++++++++-------------------- libavcodec/vaapi_encode_h26x.c | 68 -- libavcodec/vaapi_encode_h26x.h | 45 - 5 files changed, 585 insertions(+), 1069 deletions(-) delete mode 100644 libavcodec/vaapi_encode_h26x.c delete mode 100644 libavcodec/vaapi_encode_h26x.h diff --git a/configure b/configure index b6fa8f6827a99..9704b9316a3d6 100755 --- a/configure +++ b/configure @@ -2290,7 +2290,7 @@ hevc_nvenc_encoder_deps="nvenc" hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser hevc_qsv_hwaccel qsvdec" hevc_qsv_encoder_select="hevc_ps qsvenc" hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" -hevc_vaapi_encoder_select="vaapi_encode golomb" +hevc_vaapi_encoder_select="cbs_h265 vaapi_encode" mjpeg_qsv_encoder_deps="libmfx" mjpeg_qsv_encoder_select="qsvenc" mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 456ee9bb0306b..ffd17c9cf0802 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -285,7 +285,7 @@ OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec_h2645.o OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \ h2645_parse.o hevc_data.o -OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o vaapi_encode_h26x.o +OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadata.o hq_hqadsp.o \ canopus.o diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 9b029e2e20bfb..f61dfaa1a932f 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -16,164 +16,25 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include #include #include "libavutil/avassert.h" -#include "libavutil/internal.h" +#include "libavutil/common.h" #include "libavutil/opt.h" -#include "libavutil/pixfmt.h" #include "avcodec.h" +#include "cbs.h" +#include "cbs_h265.h" #include "hevc.h" #include "internal.h" #include "put_bits.h" #include "vaapi_encode.h" -#include "vaapi_encode_h26x.h" - - -#define MAX_ST_REF_PIC_SETS 32 -#define MAX_DPB_PICS 16 -#define MAX_LAYERS 1 - - -typedef struct VAAPIEncodeH265STRPS { - char inter_ref_pic_set_prediction_flag; - - unsigned int num_negative_pics; - unsigned int num_positive_pics; - - unsigned int delta_poc_s0_minus1[MAX_DPB_PICS]; - char used_by_curr_pic_s0_flag[MAX_DPB_PICS]; - - unsigned int delta_poc_s1_minus1[MAX_DPB_PICS]; - char used_by_curr_pic_s1_flag[MAX_DPB_PICS]; -} VAAPIEncodeH265STRPS; - -// This structure contains all possibly-useful per-sequence syntax elements -// which are not already contained in the various VAAPI structures. -typedef struct VAAPIEncodeH265MiscSequenceParams { - - // Parameter set IDs. - unsigned int video_parameter_set_id; - unsigned int seq_parameter_set_id; - - // Layering. - unsigned int vps_max_layers_minus1; - unsigned int vps_max_sub_layers_minus1; - char vps_temporal_id_nesting_flag; - unsigned int vps_max_layer_id; - unsigned int vps_num_layer_sets_minus1; - unsigned int sps_max_sub_layers_minus1; - char sps_temporal_id_nesting_flag; - char layer_id_included_flag[MAX_LAYERS][64]; - - // Profile/tier/level parameters. - char general_profile_compatibility_flag[32]; - char general_progressive_source_flag; - char general_interlaced_source_flag; - char general_non_packed_constraint_flag; - char general_frame_only_constraint_flag; - char general_inbld_flag; - - // Decode/display ordering parameters. - unsigned int log2_max_pic_order_cnt_lsb_minus4; - char vps_sub_layer_ordering_info_present_flag; - unsigned int vps_max_dec_pic_buffering_minus1[MAX_LAYERS]; - unsigned int vps_max_num_reorder_pics[MAX_LAYERS]; - unsigned int vps_max_latency_increase_plus1[MAX_LAYERS]; - char sps_sub_layer_ordering_info_present_flag; - unsigned int sps_max_dec_pic_buffering_minus1[MAX_LAYERS]; - unsigned int sps_max_num_reorder_pics[MAX_LAYERS]; - unsigned int sps_max_latency_increase_plus1[MAX_LAYERS]; - - // Timing information. - char vps_timing_info_present_flag; - unsigned int vps_num_units_in_tick; - unsigned int vps_time_scale; - char vps_poc_proportional_to_timing_flag; - unsigned int vps_num_ticks_poc_diff_minus1; - - // Cropping information. - char conformance_window_flag; - unsigned int conf_win_left_offset; - unsigned int conf_win_right_offset; - unsigned int conf_win_top_offset; - unsigned int conf_win_bottom_offset; - - // Short-term reference picture sets. - unsigned int num_short_term_ref_pic_sets; - VAAPIEncodeH265STRPS st_ref_pic_set[MAX_ST_REF_PIC_SETS]; - - // Long-term reference pictures. - char long_term_ref_pics_present_flag; - unsigned int num_long_term_ref_pics_sps; - struct { - unsigned int lt_ref_pic_poc_lsb_sps; - char used_by_curr_pic_lt_sps_flag; - } lt_ref_pic; - - // Deblocking filter control. - char deblocking_filter_control_present_flag; - char deblocking_filter_override_enabled_flag; - char pps_deblocking_filter_disabled_flag; - int pps_beta_offset_div2; - int pps_tc_offset_div2; - - // Video Usability Information. - char vui_parameters_present_flag; - char aspect_ratio_info_present_flag; - unsigned int aspect_ratio_idc; - unsigned int sar_width; - unsigned int sar_height; - char video_signal_type_present_flag; - unsigned int video_format; - char video_full_range_flag; - char colour_description_present_flag; - unsigned int colour_primaries; - unsigned int transfer_characteristics; - unsigned int matrix_coeffs; - - // Oddments. - char uniform_spacing_flag; - char output_flag_present_flag; - char cabac_init_present_flag; - unsigned int num_extra_slice_header_bits; - char lists_modification_present_flag; - char pps_slice_chroma_qp_offsets_present_flag; - char pps_slice_chroma_offset_list_enabled_flag; -} VAAPIEncodeH265MiscSequenceParams; - -// This structure contains all possibly-useful per-slice syntax elements -// which are not already contained in the various VAAPI structures. -typedef struct VAAPIEncodeH265MiscSliceParams { - // Slice segments. - char first_slice_segment_in_pic_flag; - unsigned int slice_segment_address; - - // Short-term reference picture sets. - char short_term_ref_pic_set_sps_flag; - unsigned int short_term_ref_pic_idx; - VAAPIEncodeH265STRPS st_ref_pic_set; - - // Deblocking filter. - char deblocking_filter_override_flag; - - // Oddments. - char slice_reserved_flag[8]; - char no_output_of_prior_pics_flag; - char pic_output_flag; -} VAAPIEncodeH265MiscSliceParams; - -typedef struct VAAPIEncodeH265Slice { - VAAPIEncodeH265MiscSliceParams misc_slice_params; - - int64_t pic_order_cnt; -} VAAPIEncodeH265Slice; -typedef struct VAAPIEncodeH265Context { - VAAPIEncodeH265MiscSequenceParams misc_sequence_params; +typedef struct VAAPIEncodeH265Context { unsigned int ctu_width; unsigned int ctu_height; @@ -181,17 +42,19 @@ typedef struct VAAPIEncodeH265Context { int fixed_qp_p; int fixed_qp_b; + H265RawVPS vps; + H265RawSPS sps; + H265RawPPS pps; + H265RawSlice slice; + int64_t last_idr_frame; + int pic_order_cnt; - // Rate control configuration. - struct { - VAEncMiscParameterBuffer misc; - VAEncMiscParameterRateControl rc; - } rc_params; - struct { - VAEncMiscParameterBuffer misc; - VAEncMiscParameterHRD hrd; - } hrd_params; + int slice_nal_unit; + int slice_type; + + CodedBitstreamContext cbc; + CodedBitstreamFragment current_access_unit; } VAAPIEncodeH265Context; typedef struct VAAPIEncodeH265Options { @@ -199,564 +62,77 @@ typedef struct VAAPIEncodeH265Options { } VAAPIEncodeH265Options; -#define vseq_var(name) vseq->name, name -#define vseq_field(name) vseq->seq_fields.bits.name, name -#define vpic_var(name) vpic->name, name -#define vpic_field(name) vpic->pic_fields.bits.name, name -#define vslice_var(name) vslice->name, name -#define vslice_field(name) vslice->slice_fields.bits.name, name -#define mseq_var(name) mseq->name, name -#define mslice_var(name) mslice->name, name -#define mstrps_var(name) mstrps->name, name - -static void vaapi_encode_h265_write_nal_unit_header(PutBitContext *pbc, - int nal_unit_type) -{ - u(1, 0, forbidden_zero_bit); - u(6, nal_unit_type, nal_unit_type); - u(6, 0, nuh_layer_id); - u(3, 1, nuh_temporal_id_plus1); -} - -static void vaapi_encode_h265_write_rbsp_trailing_bits(PutBitContext *pbc) -{ - u(1, 1, rbsp_stop_one_bit); - while (put_bits_count(pbc) & 7) - u(1, 0, rbsp_alignment_zero_bit); -} - -static void vaapi_encode_h265_write_profile_tier_level(PutBitContext *pbc, - VAAPIEncodeContext *ctx) -{ - VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; - int j; - - if (1) { - u(2, 0, general_profile_space); - u(1, vseq_var(general_tier_flag)); - u(5, vseq_var(general_profile_idc)); - - for (j = 0; j < 32; j++) { - u(1, mseq_var(general_profile_compatibility_flag[j])); - } - - u(1, mseq_var(general_progressive_source_flag)); - u(1, mseq_var(general_interlaced_source_flag)); - u(1, mseq_var(general_non_packed_constraint_flag)); - u(1, mseq_var(general_frame_only_constraint_flag)); - - if (0) { - // Not main profile. - // Lots of extra constraint flags. - } else { - // put_bits only handles up to 31 bits. - u(23, 0, general_reserved_zero_43bits); - u(20, 0, general_reserved_zero_43bits); - } - - if (vseq->general_profile_idc >= 1 && vseq->general_profile_idc <= 5) { - u(1, mseq_var(general_inbld_flag)); - } else { - u(1, 0, general_reserved_zero_bit); - } - } - - u(8, vseq_var(general_level_idc)); - - // No sublayers. -} - -static void vaapi_encode_h265_write_vps(PutBitContext *pbc, - VAAPIEncodeContext *ctx) -{ - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; - int i, j; - - vaapi_encode_h265_write_nal_unit_header(pbc, HEVC_NAL_VPS); - - u(4, mseq->video_parameter_set_id, vps_video_parameter_set_id); - - u(1, 1, vps_base_layer_internal_flag); - u(1, 1, vps_base_layer_available_flag); - u(6, mseq_var(vps_max_layers_minus1)); - u(3, mseq_var(vps_max_sub_layers_minus1)); - u(1, mseq_var(vps_temporal_id_nesting_flag)); - - u(16, 0xffff, vps_reserved_0xffff_16bits); - - vaapi_encode_h265_write_profile_tier_level(pbc, ctx); - - u(1, mseq_var(vps_sub_layer_ordering_info_present_flag)); - for (i = (mseq->vps_sub_layer_ordering_info_present_flag ? - 0 : mseq->vps_max_sub_layers_minus1); - i <= mseq->vps_max_sub_layers_minus1; i++) { - ue(mseq_var(vps_max_dec_pic_buffering_minus1[i])); - ue(mseq_var(vps_max_num_reorder_pics[i])); - ue(mseq_var(vps_max_latency_increase_plus1[i])); - } - - u(6, mseq_var(vps_max_layer_id)); - ue(mseq_var(vps_num_layer_sets_minus1)); - for (i = 1; i <= mseq->vps_num_layer_sets_minus1; i++) { - for (j = 0; j < mseq->vps_max_layer_id; j++) - u(1, mseq_var(layer_id_included_flag[i][j])); - } - - u(1, mseq_var(vps_timing_info_present_flag)); - if (mseq->vps_timing_info_present_flag) { - u(1, 0, put_bits_hack_zero_bit); - u(31, mseq_var(vps_num_units_in_tick)); - u(1, 0, put_bits_hack_zero_bit); - u(31, mseq_var(vps_time_scale)); - u(1, mseq_var(vps_poc_proportional_to_timing_flag)); - if (mseq->vps_poc_proportional_to_timing_flag) { - ue(mseq_var(vps_num_ticks_poc_diff_minus1)); - } - ue(0, vps_num_hrd_parameters); - } - - u(1, 0, vps_extension_flag); - - vaapi_encode_h265_write_rbsp_trailing_bits(pbc); -} - -static void vaapi_encode_h265_write_st_ref_pic_set(PutBitContext *pbc, - int st_rps_idx, - VAAPIEncodeH265STRPS *mstrps) -{ - int i; - - if (st_rps_idx != 0) - u(1, mstrps_var(inter_ref_pic_set_prediction_flag)); - - if (mstrps->inter_ref_pic_set_prediction_flag) { - av_assert0(0 && "inter ref pic set prediction not supported"); - } else { - ue(mstrps_var(num_negative_pics)); - ue(mstrps_var(num_positive_pics)); - - for (i = 0; i < mstrps->num_negative_pics; i++) { - ue(mstrps_var(delta_poc_s0_minus1[i])); - u(1, mstrps_var(used_by_curr_pic_s0_flag[i])); - } - for (i = 0; i < mstrps->num_positive_pics; i++) { - ue(mstrps_var(delta_poc_s1_minus1[i])); - u(1, mstrps_var(used_by_curr_pic_s1_flag[i])); - } - } -} - -static void vaapi_encode_h265_write_vui_parameters(PutBitContext *pbc, - VAAPIEncodeContext *ctx) -{ - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; - - u(1, mseq_var(aspect_ratio_info_present_flag)); - if (mseq->aspect_ratio_info_present_flag) { - u(8, mseq_var(aspect_ratio_idc)); - if (mseq->aspect_ratio_idc == 255) { - u(16, mseq_var(sar_width)); - u(16, mseq_var(sar_height)); - } - } - - u(1, 0, overscan_info_present_flag); - - u(1, mseq_var(video_signal_type_present_flag)); - if (mseq->video_signal_type_present_flag) { - u(3, mseq_var(video_format)); - u(1, mseq_var(video_full_range_flag)); - u(1, mseq_var(colour_description_present_flag)); - if (mseq->colour_description_present_flag) { - u(8, mseq_var(colour_primaries)); - u(8, mseq_var(transfer_characteristics)); - u(8, mseq_var(matrix_coeffs)); - } - } - - u(1, 0, chroma_loc_info_present_flag); - u(1, 0, neutral_chroma_indication_flag); - u(1, 0, field_seq_flag); - u(1, 0, frame_field_info_present_flag); - u(1, 0, default_display_window_flag); - u(1, 0, vui_timing_info_present_flag); - u(1, 0, bitstream_restriction_flag_flag); -} - -static void vaapi_encode_h265_write_sps(PutBitContext *pbc, - VAAPIEncodeContext *ctx) -{ - VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; - int i; - - vaapi_encode_h265_write_nal_unit_header(pbc, HEVC_NAL_SPS); - - u(4, mseq->video_parameter_set_id, sps_video_parameter_set_id); - - u(3, mseq_var(sps_max_sub_layers_minus1)); - u(1, mseq_var(sps_temporal_id_nesting_flag)); - - vaapi_encode_h265_write_profile_tier_level(pbc, ctx); - - ue(mseq->seq_parameter_set_id, sps_seq_parameter_set_id); - ue(vseq_field(chroma_format_idc)); - if (vseq->seq_fields.bits.chroma_format_idc == 3) - u(1, 0, separate_colour_plane_flag); - - ue(vseq_var(pic_width_in_luma_samples)); - ue(vseq_var(pic_height_in_luma_samples)); - - u(1, mseq_var(conformance_window_flag)); - if (mseq->conformance_window_flag) { - ue(mseq_var(conf_win_left_offset)); - ue(mseq_var(conf_win_right_offset)); - ue(mseq_var(conf_win_top_offset)); - ue(mseq_var(conf_win_bottom_offset)); - } - - ue(vseq_field(bit_depth_luma_minus8)); - ue(vseq_field(bit_depth_chroma_minus8)); - - ue(mseq_var(log2_max_pic_order_cnt_lsb_minus4)); - - u(1, mseq_var(sps_sub_layer_ordering_info_present_flag)); - for (i = (mseq->sps_sub_layer_ordering_info_present_flag ? - 0 : mseq->sps_max_sub_layers_minus1); - i <= mseq->sps_max_sub_layers_minus1; i++) { - ue(mseq_var(sps_max_dec_pic_buffering_minus1[i])); - ue(mseq_var(sps_max_num_reorder_pics[i])); - ue(mseq_var(sps_max_latency_increase_plus1[i])); - } - - ue(vseq_var(log2_min_luma_coding_block_size_minus3)); - ue(vseq_var(log2_diff_max_min_luma_coding_block_size)); - ue(vseq_var(log2_min_transform_block_size_minus2)); - ue(vseq_var(log2_diff_max_min_transform_block_size)); - ue(vseq_var(max_transform_hierarchy_depth_inter)); - ue(vseq_var(max_transform_hierarchy_depth_intra)); - - u(1, vseq_field(scaling_list_enabled_flag)); - if (vseq->seq_fields.bits.scaling_list_enabled_flag) { - u(1, 0, sps_scaling_list_data_present_flag); - } - - u(1, vseq_field(amp_enabled_flag)); - u(1, vseq_field(sample_adaptive_offset_enabled_flag)); - - u(1, vseq_field(pcm_enabled_flag)); - if (vseq->seq_fields.bits.pcm_enabled_flag) { - u(4, vseq_var(pcm_sample_bit_depth_luma_minus1)); - u(4, vseq_var(pcm_sample_bit_depth_chroma_minus1)); - ue(vseq_var(log2_min_pcm_luma_coding_block_size_minus3)); - ue(vseq->log2_max_pcm_luma_coding_block_size_minus3 - - vseq->log2_min_pcm_luma_coding_block_size_minus3, - log2_diff_max_min_pcm_luma_coding_block_size); - u(1, vseq_field(pcm_loop_filter_disabled_flag)); - } - - ue(mseq_var(num_short_term_ref_pic_sets)); - for (i = 0; i < mseq->num_short_term_ref_pic_sets; i++) - vaapi_encode_h265_write_st_ref_pic_set(pbc, i, - &mseq->st_ref_pic_set[i]); - - u(1, mseq_var(long_term_ref_pics_present_flag)); - if (mseq->long_term_ref_pics_present_flag) { - ue(0, num_long_term_ref_pics_sps); - } - - u(1, vseq_field(sps_temporal_mvp_enabled_flag)); - u(1, vseq_field(strong_intra_smoothing_enabled_flag)); - - u(1, mseq_var(vui_parameters_present_flag)); - if (mseq->vui_parameters_present_flag) { - vaapi_encode_h265_write_vui_parameters(pbc, ctx); - } - - u(1, 0, sps_extension_present_flag); - - vaapi_encode_h265_write_rbsp_trailing_bits(pbc); -} - -static void vaapi_encode_h265_write_pps(PutBitContext *pbc, - VAAPIEncodeContext *ctx) +static int vaapi_encode_h265_write_access_unit(AVCodecContext *avctx, + char *data, size_t *data_len, + CodedBitstreamFragment *au) { - VAEncPictureParameterBufferHEVC *vpic = ctx->codec_picture_params; - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; - int i; - - vaapi_encode_h265_write_nal_unit_header(pbc, HEVC_NAL_PPS); - - ue(vpic->slice_pic_parameter_set_id, pps_pic_parameter_set_id); - ue(mseq->seq_parameter_set_id, pps_seq_parameter_set_id); - - u(1, vpic_field(dependent_slice_segments_enabled_flag)); - u(1, mseq_var(output_flag_present_flag)); - u(3, mseq_var(num_extra_slice_header_bits)); - u(1, vpic_field(sign_data_hiding_enabled_flag)); - u(1, mseq_var(cabac_init_present_flag)); - - ue(vpic_var(num_ref_idx_l0_default_active_minus1)); - ue(vpic_var(num_ref_idx_l1_default_active_minus1)); - - se(vpic->pic_init_qp - 26, init_qp_minus26); - - u(1, vpic_field(constrained_intra_pred_flag)); - u(1, vpic_field(transform_skip_enabled_flag)); - - u(1, vpic_field(cu_qp_delta_enabled_flag)); - if (vpic->pic_fields.bits.cu_qp_delta_enabled_flag) - ue(vpic_var(diff_cu_qp_delta_depth)); - - se(vpic_var(pps_cb_qp_offset)); - se(vpic_var(pps_cr_qp_offset)); - - u(1, mseq_var(pps_slice_chroma_qp_offsets_present_flag)); - u(1, vpic_field(weighted_pred_flag)); - u(1, vpic_field(weighted_bipred_flag)); - u(1, vpic_field(transquant_bypass_enabled_flag)); - u(1, vpic_field(tiles_enabled_flag)); - u(1, vpic_field(entropy_coding_sync_enabled_flag)); + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + int err; - if (vpic->pic_fields.bits.tiles_enabled_flag) { - ue(vpic_var(num_tile_columns_minus1)); - ue(vpic_var(num_tile_rows_minus1)); - u(1, mseq_var(uniform_spacing_flag)); - if (!mseq->uniform_spacing_flag) { - for (i = 0; i < vpic->num_tile_columns_minus1; i++) - ue(vpic_var(column_width_minus1[i])); - for (i = 0; i < vpic->num_tile_rows_minus1; i++) - ue(vpic_var(row_height_minus1[i])); - } - u(1, vpic_field(loop_filter_across_tiles_enabled_flag)); + err = ff_cbs_write_fragment_data(&priv->cbc, au); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); + return err; } - u(1, vpic_field(pps_loop_filter_across_slices_enabled_flag)); - u(1, mseq_var(deblocking_filter_control_present_flag)); - if (mseq->deblocking_filter_control_present_flag) { - u(1, mseq_var(deblocking_filter_override_enabled_flag)); - u(1, mseq_var(pps_deblocking_filter_disabled_flag)); - if (!mseq->pps_deblocking_filter_disabled_flag) { - se(mseq_var(pps_beta_offset_div2)); - se(mseq_var(pps_tc_offset_div2)); - } + if (*data_len < 8 * au->data_size - au->data_bit_padding) { + av_log(avctx, AV_LOG_ERROR, "Access unit too large: " + "%zu < %zu.\n", *data_len, + 8 * au->data_size - au->data_bit_padding); + return AVERROR(ENOSPC); } - u(1, 0, pps_scaling_list_data_present_flag); - // No scaling list data. + memcpy(data, au->data, au->data_size); + *data_len = 8 * au->data_size - au->data_bit_padding; - u(1, mseq_var(lists_modification_present_flag)); - ue(vpic_var(log2_parallel_merge_level_minus2)); - u(1, 0, slice_segment_header_extension_present_flag); - u(1, 0, pps_extension_present_flag); - - vaapi_encode_h265_write_rbsp_trailing_bits(pbc); + return 0; } -static void vaapi_encode_h265_write_slice_header2(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic, - VAAPIEncodeSlice *slice) +static int vaapi_encode_h265_add_nal(AVCodecContext *avctx, + CodedBitstreamFragment *au, + void *nal_unit) { - VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; - VAEncSliceParameterBufferHEVC *vslice = slice->codec_slice_params; - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; - VAAPIEncodeH265Slice *pslice = slice->priv_data; - VAAPIEncodeH265MiscSliceParams *mslice = &pslice->misc_slice_params; - int i; - - vaapi_encode_h265_write_nal_unit_header(pbc, vpic->nal_unit_type); - - u(1, mslice_var(first_slice_segment_in_pic_flag)); - if (vpic->nal_unit_type >= HEVC_NAL_BLA_W_LP && - vpic->nal_unit_type <= 23) - u(1, mslice_var(no_output_of_prior_pics_flag)); - - ue(vslice_var(slice_pic_parameter_set_id)); - - if (!mslice->first_slice_segment_in_pic_flag) { - if (vpic->pic_fields.bits.dependent_slice_segments_enabled_flag) - u(1, vslice_field(dependent_slice_segment_flag)); - u(av_log2((priv->ctu_width * priv->ctu_height) - 1) + 1, - mslice_var(slice_segment_address)); - } - if (!vslice->slice_fields.bits.dependent_slice_segment_flag) { - for (i = 0; i < mseq->num_extra_slice_header_bits; i++) - u(1, mslice_var(slice_reserved_flag[i])); - - ue(vslice_var(slice_type)); - if (mseq->output_flag_present_flag) - u(1, 1, pic_output_flag); - if (vseq->seq_fields.bits.separate_colour_plane_flag) - u(2, vslice_field(colour_plane_id)); - if (vpic->nal_unit_type != HEVC_NAL_IDR_W_RADL && - vpic->nal_unit_type != HEVC_NAL_IDR_N_LP) { - u(4 + mseq->log2_max_pic_order_cnt_lsb_minus4, - (pslice->pic_order_cnt & - ((1 << (mseq->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1)), - slice_pic_order_cnt_lsb); - - u(1, mslice_var(short_term_ref_pic_set_sps_flag)); - if (!mslice->short_term_ref_pic_set_sps_flag) { - vaapi_encode_h265_write_st_ref_pic_set(pbc, mseq->num_short_term_ref_pic_sets, - &mslice->st_ref_pic_set); - } else if (mseq->num_short_term_ref_pic_sets > 1) { - u(av_log2(mseq->num_short_term_ref_pic_sets - 1) + 1, - mslice_var(short_term_ref_pic_idx)); - } - - if (mseq->long_term_ref_pics_present_flag) { - av_assert0(0); - } - } - - if (vseq->seq_fields.bits.sps_temporal_mvp_enabled_flag) { - u(1, vslice_field(slice_temporal_mvp_enabled_flag)); - } - - if (vseq->seq_fields.bits.sample_adaptive_offset_enabled_flag) { - u(1, vslice_field(slice_sao_luma_flag)); - if (!vseq->seq_fields.bits.separate_colour_plane_flag && - vseq->seq_fields.bits.chroma_format_idc != 0) { - u(1, vslice_field(slice_sao_chroma_flag)); - } - } - - if (vslice->slice_type == HEVC_SLICE_P || vslice->slice_type == HEVC_SLICE_B) { - u(1, vslice_field(num_ref_idx_active_override_flag)); - if (vslice->slice_fields.bits.num_ref_idx_active_override_flag) { - ue(vslice_var(num_ref_idx_l0_active_minus1)); - if (vslice->slice_type == HEVC_SLICE_B) { - ue(vslice_var(num_ref_idx_l1_active_minus1)); - } - } - - if (mseq->lists_modification_present_flag) { - av_assert0(0); - // ref_pic_lists_modification() - } - if (vslice->slice_type == HEVC_SLICE_B) { - u(1, vslice_field(mvd_l1_zero_flag)); - } - if (mseq->cabac_init_present_flag) { - u(1, vslice_field(cabac_init_flag)); - } - if (vslice->slice_fields.bits.slice_temporal_mvp_enabled_flag) { - if (vslice->slice_type == HEVC_SLICE_B) - u(1, vslice_field(collocated_from_l0_flag)); - ue(vpic->collocated_ref_pic_index, collocated_ref_idx); - } - if ((vpic->pic_fields.bits.weighted_pred_flag && - vslice->slice_type == HEVC_SLICE_P) || - (vpic->pic_fields.bits.weighted_bipred_flag && - vslice->slice_type == HEVC_SLICE_B)) { - av_assert0(0); - // pred_weight_table() - } - ue(5 - vslice->max_num_merge_cand, five_minus_max_num_merge_cand); - } - - se(vslice_var(slice_qp_delta)); - if (mseq->pps_slice_chroma_qp_offsets_present_flag) { - se(vslice_var(slice_cb_qp_offset)); - se(vslice_var(slice_cr_qp_offset)); - } - if (mseq->pps_slice_chroma_offset_list_enabled_flag) { - u(1, 0, cu_chroma_qp_offset_enabled_flag); - } - if (mseq->deblocking_filter_override_enabled_flag) { - u(1, mslice_var(deblocking_filter_override_flag)); - } - if (mslice->deblocking_filter_override_flag) { - u(1, vslice_field(slice_deblocking_filter_disabled_flag)); - if (!vslice->slice_fields.bits.slice_deblocking_filter_disabled_flag) { - se(vslice_var(slice_beta_offset_div2)); - se(vslice_var(slice_tc_offset_div2)); - } - } - if (vpic->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag && - (vslice->slice_fields.bits.slice_sao_luma_flag || - vslice->slice_fields.bits.slice_sao_chroma_flag || - vslice->slice_fields.bits.slice_deblocking_filter_disabled_flag)) { - u(1, vslice_field(slice_loop_filter_across_slices_enabled_flag)); - } - - if (vpic->pic_fields.bits.tiles_enabled_flag || - vpic->pic_fields.bits.entropy_coding_sync_enabled_flag) { - // num_entry_point_offsets - } + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + H265RawNALUnitHeader *header = nal_unit; + int err; - if (0) { - // slice_segment_header_extension_length - } + err = ff_cbs_insert_unit_content(&priv->cbc, au, -1, + header->nal_unit_type, nal_unit); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " + "type = %d.\n", header->nal_unit_type); + return err; } - u(1, 1, alignment_bit_equal_to_one); - while (put_bits_count(pbc) & 7) - u(1, 0, alignment_bit_equal_to_zero); + return 0; } static int vaapi_encode_h265_write_sequence_header(AVCodecContext *avctx, char *data, size_t *data_len) { - VAAPIEncodeContext *ctx = avctx->priv_data; - PutBitContext pbc; - char tmp[256]; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + CodedBitstreamFragment *au = &priv->current_access_unit; int err; - size_t nal_len, bit_len, bit_pos, next_len; - - bit_len = *data_len; - bit_pos = 0; - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h265_write_vps(&pbc, ctx); - nal_len = put_bits_count(&pbc); - flush_put_bits(&pbc); - - next_len = bit_len - bit_pos; - err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, - &next_len, - tmp, nal_len); + err = vaapi_encode_h265_add_nal(avctx, au, &priv->vps); if (err < 0) - return err; - bit_pos += next_len; + goto fail; - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h265_write_sps(&pbc, ctx); - nal_len = put_bits_count(&pbc); - flush_put_bits(&pbc); - - next_len = bit_len - bit_pos; - err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, - &next_len, - tmp, nal_len); + err = vaapi_encode_h265_add_nal(avctx, au, &priv->sps); if (err < 0) - return err; - bit_pos += next_len; + goto fail; - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h265_write_pps(&pbc, ctx); - nal_len = put_bits_count(&pbc); - flush_put_bits(&pbc); - - next_len = bit_len - bit_pos; - err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, - &next_len, - tmp, nal_len); + err = vaapi_encode_h265_add_nal(avctx, au, &priv->pps); if (err < 0) - return err; - bit_pos += next_len; + goto fail; - *data_len = bit_pos; - return 0; + err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); +fail: + ff_cbs_fragment_uninit(&priv->cbc, au); + return err; } static int vaapi_encode_h265_write_slice_header(AVCodecContext *avctx, @@ -764,195 +140,377 @@ static int vaapi_encode_h265_write_slice_header(AVCodecContext *avctx, VAAPIEncodeSlice *slice, char *data, size_t *data_len) { - VAAPIEncodeContext *ctx = avctx->priv_data; - PutBitContext pbc; - char tmp[256]; - size_t header_len; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + CodedBitstreamFragment *au = &priv->current_access_unit; + int err; - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h265_write_slice_header2(&pbc, ctx, pic, slice); - header_len = put_bits_count(&pbc); - flush_put_bits(&pbc); + err = vaapi_encode_h265_add_nal(avctx, au, &priv->slice); + if (err < 0) + goto fail; - return ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data, data_len, - tmp, header_len); + err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); +fail: + ff_cbs_fragment_uninit(&priv->cbc, au); + return err; } static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) { - VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferHEVC *vpic = ctx->codec_picture_params; - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + H265RawVPS *vps = &priv->vps; + H265RawSPS *sps = &priv->sps; + H265RawPPS *pps = &priv->pps; + H265RawVUI *vui = &sps->vui; + VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferHEVC *vpic = ctx->codec_picture_params; int i; - { - // general_profile_space == 0. - vseq->general_profile_idc = 1; // Main profile (ctx->codec_profile?) - vseq->general_tier_flag = 0; - - vseq->general_level_idc = avctx->level * 3; - - vseq->intra_period = 0; - vseq->intra_idr_period = 0; - vseq->ip_period = 0; - - vseq->pic_width_in_luma_samples = ctx->surface_width; - vseq->pic_height_in_luma_samples = ctx->surface_height; - - vseq->seq_fields.bits.chroma_format_idc = 1; // 4:2:0. - vseq->seq_fields.bits.separate_colour_plane_flag = 0; - vseq->seq_fields.bits.bit_depth_luma_minus8 = - avctx->profile == FF_PROFILE_HEVC_MAIN_10 ? 2 : 0; - vseq->seq_fields.bits.bit_depth_chroma_minus8 = - avctx->profile == FF_PROFILE_HEVC_MAIN_10 ? 2 : 0; - // Other misc flags all zero. - - // These have to come from the capabilities of the encoder. We have - // no way to query it, so just hardcode ones which worked for me... - // CTB size from 8x8 to 32x32. - vseq->log2_min_luma_coding_block_size_minus3 = 0; - vseq->log2_diff_max_min_luma_coding_block_size = 2; - // Transform size from 4x4 to 32x32. - vseq->log2_min_transform_block_size_minus2 = 0; - vseq->log2_diff_max_min_transform_block_size = 3; - // Full transform hierarchy allowed (2-5). - vseq->max_transform_hierarchy_depth_inter = 3; - vseq->max_transform_hierarchy_depth_intra = 3; - - vseq->vui_parameters_present_flag = 0; - - vseq->bits_per_second = avctx->bit_rate; - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { - vseq->vui_num_units_in_tick = avctx->framerate.den; - vseq->vui_time_scale = avctx->framerate.num; - } else { - vseq->vui_num_units_in_tick = avctx->time_base.num; - vseq->vui_time_scale = avctx->time_base.den; - } + memset(&priv->current_access_unit, 0, + sizeof(priv->current_access_unit)); - vseq->intra_period = avctx->gop_size; - vseq->intra_idr_period = avctx->gop_size; - vseq->ip_period = ctx->b_per_p + 1; - } + memset(vps, 0, sizeof(*vps)); + memset(sps, 0, sizeof(*sps)); + memset(pps, 0, sizeof(*pps)); - { - vpic->decoded_curr_pic.picture_id = VA_INVALID_ID; - vpic->decoded_curr_pic.flags = VA_PICTURE_HEVC_INVALID; - for (i = 0; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++) { - vpic->reference_frames[i].picture_id = VA_INVALID_ID; - vpic->reference_frames[i].flags = VA_PICTURE_HEVC_INVALID; - } + // VPS - vpic->collocated_ref_pic_index = 0xff; + vps->nal_unit_header = (H265RawNALUnitHeader) { + .nal_unit_type = HEVC_NAL_VPS, + .nuh_layer_id = 0, + .nuh_temporal_id_plus1 = 1, + }; - vpic->last_picture = 0; + vps->vps_video_parameter_set_id = 0; - vpic->pic_init_qp = priv->fixed_qp_idr; + vps->vps_base_layer_internal_flag = 1; + vps->vps_base_layer_available_flag = 1; + vps->vps_max_layers_minus1 = 0; + vps->vps_max_sub_layers_minus1 = 0; + vps->vps_temporal_id_nesting_flag = 1; - vpic->diff_cu_qp_delta_depth = 0; - vpic->pps_cb_qp_offset = 0; - vpic->pps_cr_qp_offset = 0; + vps->profile_tier_level = (H265RawProfileTierLevel) { + .general_profile_space = 0, + .general_profile_idc = avctx->profile, + .general_tier_flag = 0, - // tiles_enabled_flag == 0, so ignore num_tile_(rows|columns)_minus1. + .general_progressive_source_flag = 1, + .general_interlaced_source_flag = 0, + .general_non_packed_constraint_flag = 1, + .general_frame_only_constraint_flag = 1, - vpic->log2_parallel_merge_level_minus2 = 0; + .general_level_idc = avctx->level, + }; + vps->profile_tier_level.general_profile_compatibility_flag[avctx->profile & 31] = 1; - // No limit on size. - vpic->ctu_max_bitsize_allowed = 0; + vps->vps_sub_layer_ordering_info_present_flag = 0; + vps->vps_max_dec_pic_buffering_minus1[0] = (ctx->b_per_p > 0) + 1; + vps->vps_max_num_reorder_pics[0] = (ctx->b_per_p > 0); + vps->vps_max_latency_increase_plus1[0] = 0; - vpic->num_ref_idx_l0_default_active_minus1 = 0; - vpic->num_ref_idx_l1_default_active_minus1 = 0; + vps->vps_max_layer_id = 0; + vps->vps_num_layer_sets_minus1 = 0; + vps->layer_id_included_flag[0][0] = 1; - vpic->slice_pic_parameter_set_id = 0; + vps->vps_timing_info_present_flag = 1; + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + vps->vps_num_units_in_tick = avctx->framerate.den; + vps->vps_time_scale = avctx->framerate.num; + vps->vps_poc_proportional_to_timing_flag = 1; + vps->vps_num_ticks_poc_diff_one_minus1 = 0; + } else { + vps->vps_num_units_in_tick = avctx->time_base.num; + vps->vps_time_scale = avctx->time_base.den; + vps->vps_poc_proportional_to_timing_flag = 0; + } + vps->vps_num_hrd_parameters = 0; - vpic->pic_fields.bits.screen_content_flag = 0; - vpic->pic_fields.bits.enable_gpu_weighted_prediction = 0; - // Per-CU QP changes are required for non-constant-QP modes. - vpic->pic_fields.bits.cu_qp_delta_enabled_flag = - ctx->va_rc_mode != VA_RC_CQP; - } + // SPS - { - mseq->video_parameter_set_id = 5; - mseq->seq_parameter_set_id = 5; + sps->nal_unit_header = (H265RawNALUnitHeader) { + .nal_unit_type = HEVC_NAL_SPS, + .nuh_layer_id = 0, + .nuh_temporal_id_plus1 = 1, + }; - mseq->vps_max_layers_minus1 = 0; - mseq->vps_max_sub_layers_minus1 = 0; - mseq->vps_temporal_id_nesting_flag = 1; - mseq->sps_max_sub_layers_minus1 = 0; - mseq->sps_temporal_id_nesting_flag = 1; + sps->sps_video_parameter_set_id = vps->vps_video_parameter_set_id; - for (i = 0; i < 32; i++) { - mseq->general_profile_compatibility_flag[i] = - (i == vseq->general_profile_idc); - } + sps->sps_max_sub_layers_minus1 = vps->vps_max_sub_layers_minus1; + sps->sps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag; - mseq->general_progressive_source_flag = 1; - mseq->general_interlaced_source_flag = 0; - mseq->general_non_packed_constraint_flag = 0; - mseq->general_frame_only_constraint_flag = 1; - mseq->general_inbld_flag = 0; - - mseq->log2_max_pic_order_cnt_lsb_minus4 = 8; - mseq->vps_sub_layer_ordering_info_present_flag = 0; - mseq->vps_max_dec_pic_buffering_minus1[0] = (avctx->max_b_frames > 0) + 1; - mseq->vps_max_num_reorder_pics[0] = (avctx->max_b_frames > 0); - mseq->vps_max_latency_increase_plus1[0] = 0; - mseq->sps_sub_layer_ordering_info_present_flag = 0; - mseq->sps_max_dec_pic_buffering_minus1[0] = (avctx->max_b_frames > 0) + 1; - mseq->sps_max_num_reorder_pics[0] = (avctx->max_b_frames > 0); - mseq->sps_max_latency_increase_plus1[0] = 0; - - mseq->vps_timing_info_present_flag = 1; - mseq->vps_num_units_in_tick = avctx->time_base.num; - mseq->vps_time_scale = avctx->time_base.den; - mseq->vps_poc_proportional_to_timing_flag = 1; - mseq->vps_num_ticks_poc_diff_minus1 = 0; - - if (avctx->width != ctx->surface_width || - avctx->height != ctx->surface_height) { - mseq->conformance_window_flag = 1; - mseq->conf_win_left_offset = 0; - mseq->conf_win_right_offset = - (ctx->surface_width - avctx->width) / 2; - mseq->conf_win_top_offset = 0; - mseq->conf_win_bottom_offset = - (ctx->surface_height - avctx->height) / 2; - } else { - mseq->conformance_window_flag = 0; - } + sps->profile_tier_level = vps->profile_tier_level; - mseq->num_short_term_ref_pic_sets = 0; - // STRPSs should ideally be here rather than repeated in each slice. + sps->sps_seq_parameter_set_id = 0; - mseq->vui_parameters_present_flag = 1; - if (avctx->sample_aspect_ratio.num != 0) { - mseq->aspect_ratio_info_present_flag = 1; - if (avctx->sample_aspect_ratio.num == - avctx->sample_aspect_ratio.den) { - mseq->aspect_ratio_idc = 1; - } else { - mseq->aspect_ratio_idc = 255; // Extended SAR. - mseq->sar_width = avctx->sample_aspect_ratio.num; - mseq->sar_height = avctx->sample_aspect_ratio.den; + sps->chroma_format_idc = 1; // YUV 4:2:0. + sps->separate_colour_plane_flag = 0; + + sps->pic_width_in_luma_samples = ctx->surface_width; + sps->pic_height_in_luma_samples = ctx->surface_height; + + if (avctx->width != ctx->surface_width || + avctx->height != ctx->surface_height) { + sps->conformance_window_flag = 1; + sps->conf_win_left_offset = 0; + sps->conf_win_right_offset = + (ctx->surface_width - avctx->width) / 2; + sps->conf_win_top_offset = 0; + sps->conf_win_bottom_offset = + (ctx->surface_height - avctx->height) / 2; + } else { + sps->conformance_window_flag = 0; + } + + sps->bit_depth_luma_minus8 = + avctx->profile == FF_PROFILE_HEVC_MAIN_10 ? 2 : 0; + sps->bit_depth_chroma_minus8 = sps->bit_depth_luma_minus8; + + sps->log2_max_pic_order_cnt_lsb_minus4 = 8; + + sps->sps_sub_layer_ordering_info_present_flag = + vps->vps_sub_layer_ordering_info_present_flag; + for (i = 0; i <= sps->sps_max_sub_layers_minus1; i++) { + sps->sps_max_dec_pic_buffering_minus1[i] = + vps->vps_max_dec_pic_buffering_minus1[i]; + sps->sps_max_num_reorder_pics[i] = + vps->vps_max_num_reorder_pics[i]; + sps->sps_max_latency_increase_plus1[i] = + vps->vps_max_latency_increase_plus1[i]; + } + + // These have to come from the capabilities of the encoder. We have no + // way to query them, so just hardcode parameters which work on the Intel + // driver. + // CTB size from 8x8 to 32x32. + sps->log2_min_luma_coding_block_size_minus3 = 0; + sps->log2_diff_max_min_luma_coding_block_size = 2; + // Transform size from 4x4 to 32x32. + sps->log2_min_luma_transform_block_size_minus2 = 0; + sps->log2_diff_max_min_luma_transform_block_size = 3; + // Full transform hierarchy allowed (2-5). + sps->max_transform_hierarchy_depth_inter = 3; + sps->max_transform_hierarchy_depth_intra = 3; + // AMP works. + sps->amp_enabled_flag = 1; + // SAO and temporal MVP do not work. + sps->sample_adaptive_offset_enabled_flag = 0; + sps->sps_temporal_mvp_enabled_flag = 0; + + sps->pcm_enabled_flag = 0; + + // STRPSs should ideally be here rather than defined individually in + // each slice, but the structure isn't completely fixed so for now + // don't bother. + sps->num_short_term_ref_pic_sets = 0; + sps->long_term_ref_pics_present_flag = 0; + + sps->vui_parameters_present_flag = 1; + + if (avctx->sample_aspect_ratio.num != 0 && + avctx->sample_aspect_ratio.den != 0) { + static const AVRational sar_idc[] = { + { 0, 0 }, + { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, + { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, + { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, + { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, + }; + int i; + for (i = 0; i < FF_ARRAY_ELEMS(sar_idc); i++) { + if (avctx->sample_aspect_ratio.num == sar_idc[i].num && + avctx->sample_aspect_ratio.den == sar_idc[i].den) { + vui->aspect_ratio_idc = i; + break; } } - if (1) { - // Should this be conditional on some of these being set? - mseq->video_signal_type_present_flag = 1; - mseq->video_format = 5; // Unspecified. - mseq->video_full_range_flag = 0; - mseq->colour_description_present_flag = 1; - mseq->colour_primaries = avctx->color_primaries; - mseq->transfer_characteristics = avctx->color_trc; - mseq->matrix_coeffs = avctx->colorspace; + if (i >= FF_ARRAY_ELEMS(sar_idc)) { + vui->aspect_ratio_idc = 255; + vui->sar_width = avctx->sample_aspect_ratio.num; + vui->sar_height = avctx->sample_aspect_ratio.den; + } + vui->aspect_ratio_info_present_flag = 1; + } + + if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || + avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED || + avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { + vui->video_signal_type_present_flag = 1; + vui->video_format = 5; // Unspecified. + vui->video_full_range_flag = + avctx->color_range == AVCOL_RANGE_JPEG; + + if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED || + avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { + vui->colour_description_present_flag = 1; + vui->colour_primaries = avctx->color_primaries; + vui->transfer_characteristics = avctx->color_trc; + vui->matrix_coefficients = avctx->colorspace; } + } else { + vui->video_format = 5; + vui->video_full_range_flag = 0; + vui->colour_primaries = avctx->color_primaries; + vui->transfer_characteristics = avctx->color_trc; + vui->matrix_coefficients = avctx->colorspace; + } + + if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) { + vui->chroma_loc_info_present_flag = 1; + vui->chroma_sample_loc_type_top_field = + vui->chroma_sample_loc_type_bottom_field = + avctx->chroma_sample_location - 1; } + vui->vui_timing_info_present_flag = 1; + vui->vui_num_units_in_tick = vps->vps_num_units_in_tick; + vui->vui_time_scale = vps->vps_time_scale; + vui->vui_poc_proportional_to_timing_flag = vps->vps_poc_proportional_to_timing_flag; + vui->vui_num_ticks_poc_diff_one_minus1 = vps->vps_num_ticks_poc_diff_one_minus1; + vui->vui_hrd_parameters_present_flag = 0; + + vui->bitstream_restriction_flag = 1; + vui->motion_vectors_over_pic_boundaries_flag = 1; + vui->restricted_ref_pic_lists_flag = 1; + vui->max_bytes_per_pic_denom = 0; + vui->max_bits_per_min_cu_denom = 0; + vui->log2_max_mv_length_horizontal = 15; + vui->log2_max_mv_length_vertical = 15; + + + // PPS + + pps->nal_unit_header = (H265RawNALUnitHeader) { + .nal_unit_type = HEVC_NAL_PPS, + .nuh_layer_id = 0, + .nuh_temporal_id_plus1 = 1, + }; + + pps->pps_pic_parameter_set_id = 0; + pps->pps_seq_parameter_set_id = sps->sps_seq_parameter_set_id; + + pps->num_ref_idx_l0_default_active_minus1 = 0; + pps->num_ref_idx_l1_default_active_minus1 = 0; + + pps->init_qp_minus26 = priv->fixed_qp_idr - 26; + + pps->cu_qp_delta_enabled_flag = (ctx->va_rc_mode != VA_RC_CQP); + pps->diff_cu_qp_delta_depth = 0; + + pps->pps_loop_filter_across_slices_enabled_flag = 1; + + + // Fill VAAPI parameter buffers. + + *vseq = (VAEncSequenceParameterBufferHEVC) { + .general_profile_idc = vps->profile_tier_level.general_profile_idc, + .general_level_idc = vps->profile_tier_level.general_level_idc, + .general_tier_flag = vps->profile_tier_level.general_tier_flag, + + .intra_period = avctx->gop_size, + .intra_idr_period = avctx->gop_size, + .ip_period = ctx->b_per_p + 1, + .bits_per_second = avctx->bit_rate, + + .pic_width_in_luma_samples = sps->pic_width_in_luma_samples, + .pic_height_in_luma_samples = sps->pic_height_in_luma_samples, + + .seq_fields.bits = { + .chroma_format_idc = sps->chroma_format_idc, + .separate_colour_plane_flag = sps->separate_colour_plane_flag, + .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8, + .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8, + .scaling_list_enabled_flag = sps->scaling_list_enabled_flag, + .strong_intra_smoothing_enabled_flag = + sps->strong_intra_smoothing_enabled_flag, + .amp_enabled_flag = sps->amp_enabled_flag, + .sample_adaptive_offset_enabled_flag = + sps->sample_adaptive_offset_enabled_flag, + .pcm_enabled_flag = sps->pcm_enabled_flag, + .pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled_flag, + .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag, + }, + + .log2_min_luma_coding_block_size_minus3 = + sps->log2_min_luma_coding_block_size_minus3, + .log2_diff_max_min_luma_coding_block_size = + sps->log2_diff_max_min_luma_coding_block_size, + .log2_min_transform_block_size_minus2 = + sps->log2_min_luma_transform_block_size_minus2, + .log2_diff_max_min_transform_block_size = + sps->log2_diff_max_min_luma_transform_block_size, + .max_transform_hierarchy_depth_inter = + sps->max_transform_hierarchy_depth_inter, + .max_transform_hierarchy_depth_intra = + sps->max_transform_hierarchy_depth_intra, + + .pcm_sample_bit_depth_luma_minus1 = + sps->pcm_sample_bit_depth_luma_minus1, + .pcm_sample_bit_depth_chroma_minus1 = + sps->pcm_sample_bit_depth_chroma_minus1, + .log2_min_pcm_luma_coding_block_size_minus3 = + sps->log2_min_pcm_luma_coding_block_size_minus3, + .log2_max_pcm_luma_coding_block_size_minus3 = + sps->log2_min_pcm_luma_coding_block_size_minus3 + + sps->log2_diff_max_min_pcm_luma_coding_block_size, + + .vui_parameters_present_flag = 0, + }; + + *vpic = (VAEncPictureParameterBufferHEVC) { + .decoded_curr_pic = { + .picture_id = VA_INVALID_ID, + .flags = VA_PICTURE_HEVC_INVALID, + }, + + .coded_buf = VA_INVALID_ID, + + .collocated_ref_pic_index = 0xff, + + .last_picture = 0, + + .pic_init_qp = pps->init_qp_minus26 + 26, + .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth, + .pps_cb_qp_offset = pps->pps_cb_qp_offset, + .pps_cr_qp_offset = pps->pps_cr_qp_offset, + + .num_tile_columns_minus1 = pps->num_tile_columns_minus1, + .num_tile_rows_minus1 = pps->num_tile_rows_minus1, + + .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level_minus2, + .ctu_max_bitsize_allowed = 0, + + .num_ref_idx_l0_default_active_minus1 = + pps->num_ref_idx_l0_default_active_minus1, + .num_ref_idx_l1_default_active_minus1 = + pps->num_ref_idx_l1_default_active_minus1, + + .slice_pic_parameter_set_id = pps->pps_pic_parameter_set_id, + + .pic_fields.bits = { + .sign_data_hiding_enabled_flag = pps->sign_data_hiding_enabled_flag, + .constrained_intra_pred_flag = pps->constrained_intra_pred_flag, + .transform_skip_enabled_flag = pps->transform_skip_enabled_flag, + .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag, + .weighted_pred_flag = pps->weighted_pred_flag, + .weighted_bipred_flag = pps->weighted_bipred_flag, + .transquant_bypass_enabled_flag = pps->transquant_bypass_enabled_flag, + .tiles_enabled_flag = pps->tiles_enabled_flag, + .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag, + .loop_filter_across_tiles_enabled_flag = + pps->loop_filter_across_tiles_enabled_flag, + .scaling_list_data_present_flag = (sps->sps_scaling_list_data_present_flag | + pps->pps_scaling_list_data_present_flag), + .screen_content_flag = 0, + .enable_gpu_weighted_prediction = 0, + .no_output_of_prior_pics_flag = 0, + }, + }; + return 0; } @@ -960,65 +518,87 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx, VAAPIEncodePicture *pic) { VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; VAAPIEncodeH265Context *priv = ctx->priv_data; + VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; int i; if (pic->type == PICTURE_TYPE_IDR) { av_assert0(pic->display_order == pic->encode_order); + priv->last_idr_frame = pic->display_order; + + priv->slice_nal_unit = HEVC_NAL_IDR_W_RADL; + priv->slice_type = HEVC_SLICE_I; } else { av_assert0(pic->encode_order > priv->last_idr_frame); - // Display order need not be if we have RA[SD]L pictures, though. + + if (pic->type == PICTURE_TYPE_I) { + priv->slice_nal_unit = HEVC_NAL_CRA_NUT; + priv->slice_type = HEVC_SLICE_I; + } else if (pic->type == PICTURE_TYPE_P) { + av_assert0(pic->refs[0]); + priv->slice_nal_unit = HEVC_NAL_TRAIL_R; + priv->slice_type = HEVC_SLICE_P; + } else { + av_assert0(pic->refs[0] && pic->refs[1]); + if (pic->refs[1]->type == PICTURE_TYPE_I) + priv->slice_nal_unit = HEVC_NAL_RASL_N; + else + priv->slice_nal_unit = HEVC_NAL_TRAIL_N; + priv->slice_type = HEVC_SLICE_B; + } } + priv->pic_order_cnt = pic->display_order - priv->last_idr_frame; - vpic->decoded_curr_pic.picture_id = pic->recon_surface; - vpic->decoded_curr_pic.pic_order_cnt = - pic->display_order - priv->last_idr_frame; - vpic->decoded_curr_pic.flags = 0; + vpic->decoded_curr_pic = (VAPictureHEVC) { + .picture_id = pic->recon_surface, + .pic_order_cnt = priv->pic_order_cnt, + .flags = 0, + }; for (i = 0; i < pic->nb_refs; i++) { VAAPIEncodePicture *ref = pic->refs[i]; - av_assert0(ref); - vpic->reference_frames[i].picture_id = ref->recon_surface; - vpic->reference_frames[i].pic_order_cnt = - ref->display_order - priv->last_idr_frame; - vpic->reference_frames[i].flags = - (ref->display_order < pic->display_order ? - VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE : 0) | - (ref->display_order > pic->display_order ? - VA_PICTURE_HEVC_RPS_ST_CURR_AFTER : 0); + av_assert0(ref && ref->encode_order < pic->encode_order); + + vpic->reference_frames[i] = (VAPictureHEVC) { + .picture_id = ref->recon_surface, + .pic_order_cnt = ref->display_order - priv->last_idr_frame, + .flags = (ref->display_order < pic->display_order ? + VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE : 0) | + (ref->display_order > pic->display_order ? + VA_PICTURE_HEVC_RPS_ST_CURR_AFTER : 0), + }; } for (; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++) { - vpic->reference_frames[i].picture_id = VA_INVALID_ID; - vpic->reference_frames[i].flags = VA_PICTURE_HEVC_INVALID; + vpic->reference_frames[i] = (VAPictureHEVC) { + .picture_id = VA_INVALID_ID, + .flags = VA_PICTURE_HEVC_INVALID, + }; } vpic->coded_buf = pic->output_buffer; + vpic->nal_unit_type = priv->slice_nal_unit; + switch (pic->type) { case PICTURE_TYPE_IDR: - vpic->nal_unit_type = HEVC_NAL_IDR_W_RADL; - vpic->pic_fields.bits.idr_pic_flag = 1; - vpic->pic_fields.bits.coding_type = 1; + vpic->pic_fields.bits.idr_pic_flag = 1; + vpic->pic_fields.bits.coding_type = 1; vpic->pic_fields.bits.reference_pic_flag = 1; break; case PICTURE_TYPE_I: - vpic->nal_unit_type = HEVC_NAL_TRAIL_R; - vpic->pic_fields.bits.idr_pic_flag = 0; - vpic->pic_fields.bits.coding_type = 1; + vpic->pic_fields.bits.idr_pic_flag = 0; + vpic->pic_fields.bits.coding_type = 1; vpic->pic_fields.bits.reference_pic_flag = 1; break; case PICTURE_TYPE_P: - vpic->nal_unit_type = HEVC_NAL_TRAIL_R; - vpic->pic_fields.bits.idr_pic_flag = 0; - vpic->pic_fields.bits.coding_type = 2; + vpic->pic_fields.bits.idr_pic_flag = 0; + vpic->pic_fields.bits.coding_type = 2; vpic->pic_fields.bits.reference_pic_flag = 1; break; case PICTURE_TYPE_B: - vpic->nal_unit_type = HEVC_NAL_TRAIL_R; - vpic->pic_fields.bits.idr_pic_flag = 0; - vpic->pic_fields.bits.coding_type = 3; + vpic->pic_fields.bits.idr_pic_flag = 0; + vpic->pic_fields.bits.coding_type = 3; vpic->pic_fields.bits.reference_pic_flag = 0; break; default: @@ -1035,90 +615,40 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, VAAPIEncodeSlice *slice) { VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + const H265RawSPS *sps = &priv->sps; + const H265RawPPS *pps = &priv->pps; + H265RawSliceHeader *sh = &priv->slice.header; VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; VAEncSliceParameterBufferHEVC *vslice = slice->codec_slice_params; - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265Slice *pslice; - VAAPIEncodeH265MiscSliceParams *mslice; int i; - slice->priv_data = av_mallocz(sizeof(*pslice)); - if (!slice->priv_data) - return AVERROR(ENOMEM); - pslice = slice->priv_data; - mslice = &pslice->misc_slice_params; - - // Currently we only support one slice per frame. - vslice->slice_segment_address = 0; - vslice->num_ctu_in_slice = priv->ctu_width * priv->ctu_height; - - switch (pic->type) { - case PICTURE_TYPE_IDR: - case PICTURE_TYPE_I: - vslice->slice_type = HEVC_SLICE_I; - break; - case PICTURE_TYPE_P: - vslice->slice_type = HEVC_SLICE_P; - break; - case PICTURE_TYPE_B: - vslice->slice_type = HEVC_SLICE_B; - break; - default: - av_assert0(0 && "invalid picture type"); - } - - vslice->slice_pic_parameter_set_id = vpic->slice_pic_parameter_set_id; - - pslice->pic_order_cnt = pic->display_order - priv->last_idr_frame; - - for (i = 0; i < FF_ARRAY_ELEMS(vslice->ref_pic_list0); i++) { - vslice->ref_pic_list0[i].picture_id = VA_INVALID_ID; - vslice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID; - vslice->ref_pic_list1[i].picture_id = VA_INVALID_ID; - vslice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID; - } - - av_assert0(pic->nb_refs <= 2); - if (pic->nb_refs >= 1) { - // Backward reference for P- or B-frame. - av_assert0(pic->type == PICTURE_TYPE_P || - pic->type == PICTURE_TYPE_B); - - vslice->num_ref_idx_l0_active_minus1 = 0; - vslice->ref_pic_list0[0] = vpic->reference_frames[0]; - } - if (pic->nb_refs >= 2) { - // Forward reference for B-frame. - av_assert0(pic->type == PICTURE_TYPE_B); - - vslice->num_ref_idx_l1_active_minus1 = 0; - vslice->ref_pic_list1[0] = vpic->reference_frames[1]; - } + sh->nal_unit_header = (H265RawNALUnitHeader) { + .nal_unit_type = priv->slice_nal_unit, + .nuh_layer_id = 0, + .nuh_temporal_id_plus1 = 1, + }; - vslice->max_num_merge_cand = 5; + sh->slice_pic_parameter_set_id = pps->pps_pic_parameter_set_id; - if (pic->type == PICTURE_TYPE_B) - vslice->slice_qp_delta = priv->fixed_qp_b - vpic->pic_init_qp; - else if (pic->type == PICTURE_TYPE_P) - vslice->slice_qp_delta = priv->fixed_qp_p - vpic->pic_init_qp; - else - vslice->slice_qp_delta = priv->fixed_qp_idr - vpic->pic_init_qp; + // Currently we only support one slice per frame. + sh->first_slice_segment_in_pic_flag = 1; + sh->slice_segment_address = 0; - vslice->slice_fields.bits.last_slice_of_pic_flag = 1; + sh->slice_type = priv->slice_type; - mslice->first_slice_segment_in_pic_flag = 1; + sh->slice_pic_order_cnt_lsb = priv->pic_order_cnt & + (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1; - if (pic->type == PICTURE_TYPE_IDR) { - // No reference pictures. - } else if (0) { - mslice->short_term_ref_pic_set_sps_flag = 1; - mslice->short_term_ref_pic_idx = 0; - } else { + if (pic->type != PICTURE_TYPE_IDR) { + H265RawSTRefPicSet *rps; VAAPIEncodePicture *st; int used; - mslice->short_term_ref_pic_set_sps_flag = 0; - mslice->st_ref_pic_set.inter_ref_pic_set_prediction_flag = 0; + sh->short_term_ref_pic_set_sps_flag = 0; + + rps = &sh->short_term_ref_pic_set; + memset(rps, 0, sizeof(*rps)); for (st = ctx->pic_start; st; st = st->next) { if (st->encode_order >= pic->encode_order) { @@ -1131,28 +661,111 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, used = 1; } if (!used) { - // Currently true, but need not be. - continue; + // Usually each picture always uses all of the others in the + // DPB as references. The one case we have to treat here is + // a non-IDR IRAP picture, which may need to hold unused + // references across itself to be used for the decoding of + // following RASL pictures. This looks for such an RASL + // picture, and keeps the reference if there is one. + VAAPIEncodePicture *rp; + for (rp = ctx->pic_start; rp; rp = rp->next) { + if (rp->encode_order < pic->encode_order) + continue; + if (rp->type != PICTURE_TYPE_B) + continue; + if (rp->refs[0] == st && rp->refs[1] == pic) + break; + } + if (!rp) + continue; } // This only works for one instance of each (delta_poc_sN_minus1 // is relative to the previous frame in the list, not relative to // the current frame directly). if (st->display_order < pic->display_order) { - i = mslice->st_ref_pic_set.num_negative_pics; - mslice->st_ref_pic_set.delta_poc_s0_minus1[i] = + rps->delta_poc_s0_minus1[rps->num_negative_pics] = pic->display_order - st->display_order - 1; - mslice->st_ref_pic_set.used_by_curr_pic_s0_flag[i] = used; - ++mslice->st_ref_pic_set.num_negative_pics; + rps->used_by_curr_pic_s0_flag[rps->num_negative_pics] = used; + ++rps->num_negative_pics; } else { - i = mslice->st_ref_pic_set.num_positive_pics; - mslice->st_ref_pic_set.delta_poc_s1_minus1[i] = + rps->delta_poc_s1_minus1[rps->num_positive_pics] = st->display_order - pic->display_order - 1; - mslice->st_ref_pic_set.used_by_curr_pic_s1_flag[i] = used; - ++mslice->st_ref_pic_set.num_positive_pics; + rps->used_by_curr_pic_s1_flag[rps->num_positive_pics] = used; + ++rps->num_positive_pics; } } + + sh->num_long_term_sps = 0; + sh->num_long_term_pics = 0; + + sh->slice_temporal_mvp_enabled_flag = + sps->sps_temporal_mvp_enabled_flag; + if (sh->slice_temporal_mvp_enabled_flag) { + sh->collocated_from_l0_flag = sh->slice_type == HEVC_SLICE_B; + sh->collocated_ref_idx = 0; + } + + sh->num_ref_idx_active_override_flag = 0; + sh->num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1; + sh->num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1; } + sh->slice_sao_luma_flag = sh->slice_sao_chroma_flag = + sps->sample_adaptive_offset_enabled_flag; + + if (pic->type == PICTURE_TYPE_B) + sh->slice_qp_delta = priv->fixed_qp_b - (pps->init_qp_minus26 + 26); + else if (pic->type == PICTURE_TYPE_P) + sh->slice_qp_delta = priv->fixed_qp_p - (pps->init_qp_minus26 + 26); + else + sh->slice_qp_delta = priv->fixed_qp_idr - (pps->init_qp_minus26 + 26); + + + *vslice = (VAEncSliceParameterBufferHEVC) { + .slice_segment_address = sh->slice_segment_address, + .num_ctu_in_slice = priv->ctu_width * priv->ctu_height, + + .slice_type = sh->slice_type, + .slice_pic_parameter_set_id = sh->slice_pic_parameter_set_id, + + .num_ref_idx_l0_active_minus1 = sh->num_ref_idx_l0_active_minus1, + .num_ref_idx_l1_active_minus1 = sh->num_ref_idx_l1_active_minus1, + .ref_pic_list0[0] = vpic->reference_frames[0], + .ref_pic_list1[0] = vpic->reference_frames[1], + + .luma_log2_weight_denom = sh->luma_log2_weight_denom, + .delta_chroma_log2_weight_denom = sh->delta_chroma_log2_weight_denom, + + .max_num_merge_cand = 5 - sh->five_minus_max_num_merge_cand, + + .slice_qp_delta = sh->slice_qp_delta, + .slice_cb_qp_offset = sh->slice_cb_qp_offset, + .slice_cr_qp_offset = sh->slice_cr_qp_offset, + + .slice_beta_offset_div2 = sh->slice_beta_offset_div2, + .slice_tc_offset_div2 = sh->slice_tc_offset_div2, + + .slice_fields.bits = { + .last_slice_of_pic_flag = 1, + .dependent_slice_segment_flag = sh->dependent_slice_segment_flag, + .colour_plane_id = sh->colour_plane_id, + .slice_temporal_mvp_enabled_flag = + sh->slice_temporal_mvp_enabled_flag, + .slice_sao_luma_flag = sh->slice_sao_luma_flag, + .slice_sao_chroma_flag = sh->slice_sao_chroma_flag, + .num_ref_idx_active_override_flag = + sh->num_ref_idx_active_override_flag, + .mvd_l1_zero_flag = sh->mvd_l1_zero_flag, + .cabac_init_flag = sh->cabac_init_flag, + .slice_deblocking_filter_disabled_flag = + sh->slice_deblocking_filter_disabled_flag, + .slice_loop_filter_across_slices_enabled_flag = + sh->slice_loop_filter_across_slices_enabled_flag, + .collocated_from_l0_flag = sh->collocated_from_l0_flag, + }, + }; + + return 0; } @@ -1161,6 +774,11 @@ static av_cold int vaapi_encode_h265_configure(AVCodecContext *avctx) VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH265Context *priv = ctx->priv_data; VAAPIEncodeH265Options *opt = ctx->codec_options; + int err; + + err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_HEVC, avctx); + if (err < 0) + return err; priv->ctu_width = FFALIGN(ctx->surface_width, 32) / 32; priv->ctu_height = FFALIGN(ctx->surface_height, 32) / 32; @@ -1267,6 +885,17 @@ static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx) return ff_vaapi_encode_init(avctx); } +static av_cold int vaapi_encode_h265_close(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + + if (priv) + ff_cbs_close(&priv->cbc); + + return ff_vaapi_encode_close(avctx); +} + #define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \ offsetof(VAAPIEncodeH265Options, x)) #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) @@ -1305,7 +934,7 @@ AVCodec ff_hevc_vaapi_encoder = { sizeof(VAAPIEncodeH265Options)), .init = &vaapi_encode_h265_init, .encode2 = &ff_vaapi_encode2, - .close = &ff_vaapi_encode_close, + .close = &vaapi_encode_h265_close, .priv_class = &vaapi_encode_h265_class, .capabilities = AV_CODEC_CAP_DELAY, .defaults = vaapi_encode_h265_defaults, diff --git a/libavcodec/vaapi_encode_h26x.c b/libavcodec/vaapi_encode_h26x.c deleted file mode 100644 index bf9eb92135376..0000000000000 --- a/libavcodec/vaapi_encode_h26x.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "vaapi_encode_h26x.h" - -int ff_vaapi_encode_h26x_nal_unit_to_byte_stream(uint8_t *dst, size_t *dst_bit_len, - uint8_t *src, size_t src_bit_len) -{ - size_t dp, sp; - int zero_run = 0; - size_t dst_len = *dst_bit_len / 8; - size_t src_len = (src_bit_len + 7) / 8; - int trailing_zeroes = src_len * 8 - src_bit_len; - - if (dst_len < src_len + 4) { - // Definitely doesn't fit. - goto fail; - } - - // Start code. - dst[0] = dst[1] = dst[2] = 0; - dst[3] = 1; - dp = 4; - - for (sp = 0; sp < src_len; sp++) { - if (dp >= dst_len) - goto fail; - if (zero_run < 2) { - if (src[sp] == 0) - ++zero_run; - else - zero_run = 0; - } else { - if ((src[sp] & ~3) == 0) { - // emulation_prevention_three_byte - dst[dp++] = 3; - if (dp >= dst_len) - goto fail; - } - zero_run = src[sp] == 0; - } - dst[dp++] = src[sp]; - } - - *dst_bit_len = 8 * dp - trailing_zeroes; - return 0; - -fail: - *dst_bit_len = 0; - return AVERROR(ENOSPC); -} diff --git a/libavcodec/vaapi_encode_h26x.h b/libavcodec/vaapi_encode_h26x.h deleted file mode 100644 index d6db69a0eaf29..0000000000000 --- a/libavcodec/vaapi_encode_h26x.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVCODEC_VAAPI_ENCODE_H26X_H -#define AVCODEC_VAAPI_ENCODE_H26X_H - -#include -#include - -#include "golomb.h" -#include "put_bits.h" - - -// Debug code may be interested in the name of the syntax element being -// for tracing purposes. Here, it is just discarded. - -#define write_u(pbc, width, value, name) put_bits(pbc, width, value) -#define write_ue(pbc, value, name) set_ue_golomb(pbc, value) -#define write_se(pbc, value, name) set_se_golomb(pbc, value) - -#define u(width, ...) write_u(pbc, width, __VA_ARGS__) -#define ue(...) write_ue(pbc, __VA_ARGS__) -#define se(...) write_se(pbc, __VA_ARGS__) - - -// Copy from src to dst, applying emulation prevention. -int ff_vaapi_encode_h26x_nal_unit_to_byte_stream(uint8_t *dst, size_t *dst_len, - uint8_t *src, size_t src_len); - -#endif /* AVCODEC_VAAPI_ENCODE_H26X_H */ From e3e8eab359238486dc233f7aa89b7bb3cb19ec38 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 23 Jul 2017 23:22:54 +0100 Subject: [PATCH 0359/2557] vaapi_h265: Add support for AUD NAL units Matching the H.264 encoder. --- libavcodec/vaapi_encode_h265.c | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index f61dfaa1a932f..477065e2cee61 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -42,6 +42,7 @@ typedef struct VAAPIEncodeH265Context { int fixed_qp_p; int fixed_qp_b; + H265RawAUD aud; H265RawVPS vps; H265RawSPS sps; H265RawPPS pps; @@ -52,13 +53,16 @@ typedef struct VAAPIEncodeH265Context { int slice_nal_unit; int slice_type; + int pic_type; CodedBitstreamContext cbc; CodedBitstreamFragment current_access_unit; + int aud_needed; } VAAPIEncodeH265Context; typedef struct VAAPIEncodeH265Options { int qp; + int aud; } VAAPIEncodeH265Options; @@ -117,6 +121,13 @@ static int vaapi_encode_h265_write_sequence_header(AVCodecContext *avctx, CodedBitstreamFragment *au = &priv->current_access_unit; int err; + if (priv->aud_needed) { + err = vaapi_encode_h265_add_nal(avctx, au, &priv->aud); + if (err < 0) + goto fail; + priv->aud_needed = 0; + } + err = vaapi_encode_h265_add_nal(avctx, au, &priv->vps); if (err < 0) goto fail; @@ -145,6 +156,13 @@ static int vaapi_encode_h265_write_slice_header(AVCodecContext *avctx, CodedBitstreamFragment *au = &priv->current_access_unit; int err; + if (priv->aud_needed) { + err = vaapi_encode_h265_add_nal(avctx, au, &priv->aud); + if (err < 0) + goto fail; + priv->aud_needed = 0; + } + err = vaapi_encode_h265_add_nal(avctx, au, &priv->slice); if (err < 0) goto fail; @@ -519,6 +537,7 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx, { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH265Context *priv = ctx->priv_data; + VAAPIEncodeH265Options *opt = ctx->codec_options; VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; int i; @@ -529,16 +548,19 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx, priv->slice_nal_unit = HEVC_NAL_IDR_W_RADL; priv->slice_type = HEVC_SLICE_I; + priv->pic_type = 0; } else { av_assert0(pic->encode_order > priv->last_idr_frame); if (pic->type == PICTURE_TYPE_I) { priv->slice_nal_unit = HEVC_NAL_CRA_NUT; priv->slice_type = HEVC_SLICE_I; + priv->pic_type = 0; } else if (pic->type == PICTURE_TYPE_P) { av_assert0(pic->refs[0]); priv->slice_nal_unit = HEVC_NAL_TRAIL_R; priv->slice_type = HEVC_SLICE_P; + priv->pic_type = 1; } else { av_assert0(pic->refs[0] && pic->refs[1]); if (pic->refs[1]->type == PICTURE_TYPE_I) @@ -546,10 +568,23 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx, else priv->slice_nal_unit = HEVC_NAL_TRAIL_N; priv->slice_type = HEVC_SLICE_B; + priv->pic_type = 2; } } priv->pic_order_cnt = pic->display_order - priv->last_idr_frame; + if (opt->aud) { + priv->aud_needed = 1; + priv->aud.nal_unit_header = (H265RawNALUnitHeader) { + .nal_unit_type = HEVC_NAL_AUD, + .nuh_layer_id = 0, + .nuh_temporal_id_plus1 = 1, + }; + priv->aud.pic_type = priv->pic_type; + } else { + priv->aud_needed = 0; + } + vpic->decoded_curr_pic = (VAPictureHEVC) { .picture_id = pic->recon_surface, .pic_order_cnt = priv->pic_order_cnt, @@ -902,6 +937,10 @@ static av_cold int vaapi_encode_h265_close(AVCodecContext *avctx) static const AVOption vaapi_encode_h265_options[] = { { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)", OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 25 }, 0, 52, FLAGS }, + + { "aud", "Include AUD", + OFFSET(aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, + { NULL }, }; From a14a12ca137bf1526452b97bedfc9f7b301d4e04 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 12 Aug 2017 21:32:29 +0100 Subject: [PATCH 0360/2557] vaapi_h265: Reduce the amount of padding in the stream It is not necessary to pad to the CTU size. The CB size of 8x8 should be sufficient, but due to constraints in the Intel driver (the one usable implementation of this) it has to be padded to 16x16 like in H.264. --- libavcodec/vaapi_encode_h265.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 477065e2cee61..165b6ffde4934 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -815,8 +815,11 @@ static av_cold int vaapi_encode_h265_configure(AVCodecContext *avctx) if (err < 0) return err; - priv->ctu_width = FFALIGN(ctx->surface_width, 32) / 32; - priv->ctu_height = FFALIGN(ctx->surface_height, 32) / 32; + // This is an Intel driver constraint. Despite MinCbSizeY being 8, + // we are still required to encode at 16-pixel alignment and then + // crop back (so 1080 lines is still encoded as 1088 + cropping). + priv->ctu_width = FFALIGN(ctx->surface_width, 16) / 16; + priv->ctu_height = FFALIGN(ctx->surface_height, 16) / 16; av_log(avctx, AV_LOG_VERBOSE, "Input %ux%u -> Surface %ux%u -> CTU %ux%u.\n", avctx->width, avctx->height, ctx->surface_width, From a05c6e8c11b1a17b7c4529294751b917cf0d8e04 Mon Sep 17 00:00:00 2001 From: Piotr Bandurski Date: Sun, 24 Jun 2012 11:34:02 +0000 Subject: [PATCH 0361/2557] xwddec: support 8bpp grayscale (cherry picked from commit b9c94e826e7551027754ecfa60e3e487e0c28fcb) Signed-off-by: Diego Biurrun --- libavcodec/xwddec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/xwddec.c b/libavcodec/xwddec.c index 387b697491ed8..c43724e538ee5 100644 --- a/libavcodec/xwddec.c +++ b/libavcodec/xwddec.c @@ -155,10 +155,12 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, switch (vclass) { case XWD_STATIC_GRAY: case XWD_GRAY_SCALE: - if (bpp != 1) + if (bpp != 1 && bpp != 8 || bpp != pixdepth) return AVERROR_INVALIDDATA; if (pixdepth == 1) avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; + else if (pixdepth == 8) + avctx->pix_fmt = AV_PIX_FMT_GRAY8; break; case XWD_STATIC_COLOR: case XWD_PSEUDO_COLOR: From d34a133b78afe2793cd8537f3c7f42437f441e94 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 11 Aug 2017 19:15:20 +0200 Subject: [PATCH 0362/2557] dfa: Disallow odd width/height and add proper bounds check for DDS1 chunks DDS1 chunks are decoded in 2x2 blocks, odd chunk width or height is not allowed in that case. Also ensure that the decode buffer is big enough for all blocks being processed. Bug-Id: CVE-2017-9992 CC: libav-stable@libav.org --- libavcodec/dfa.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/dfa.c b/libavcodec/dfa.c index 2654118fad0c7..1682eb08cdba6 100644 --- a/libavcodec/dfa.c +++ b/libavcodec/dfa.c @@ -144,6 +144,8 @@ static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height int mask = 0x10000, bitbuf = 0; int i, v, offset, count, segments; + if ((width | height) & 1) + return AVERROR_INVALIDDATA; segments = bytestream2_get_le16(gb); while (segments--) { if (bytestream2_get_bytes_left(gb) < 2) @@ -171,7 +173,7 @@ static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height return AVERROR_INVALIDDATA; frame += v; } else { - if (frame_end - frame < width + 3) + if (width < 4 || frame_end - frame < width + 4) return AVERROR_INVALIDDATA; frame[0] = frame[1] = frame[width] = frame[width + 1] = bytestream2_get_byte(gb); From f70f71d60c7ae88c19078a48dc6e0789b78c7300 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 17 Aug 2017 12:15:58 +0200 Subject: [PATCH 0363/2557] h264dec: use a large enough field for reference list modification values pic_num can be at most 17-bit, so uint8_t is not sufficient. Found-By: Bradley Sepos CC: libav-stable@libav.org --- libavcodec/h264dec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h index ddfe224e93d27..cce5e198d9ab6 100644 --- a/libavcodec/h264dec.h +++ b/libavcodec/h264dec.h @@ -268,7 +268,7 @@ typedef struct H264SliceContext { * according to picture reordering in slice header */ struct { uint8_t op; - uint8_t val; + uint32_t val; } ref_modifications[2][32]; int nb_ref_modifications[2]; From 768eb9182e94a94bc2ef46f565a0dac7afef3b57 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 14 Aug 2017 16:46:32 +0100 Subject: [PATCH 0364/2557] cbs_h2645: Return error if writing fails --- libavcodec/cbs_h2645.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 23556f47f8466..4d8ba99b35331 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -1244,6 +1244,11 @@ static int cbs_h2645_write_nal_unit(CodedBitstreamContext *ctx, // Overflow but we didn't notice. av_assert0(put_bits_count(&pbc) <= 8 * priv->write_buffer_size); + if (err < 0) { + // Write failed for some other reason. + return err; + } + if (put_bits_count(&pbc) % 8) unit->data_bit_padding = 8 - put_bits_count(&pbc) % 8; else From 2bc9ba8d3c41f3a8e56484bd67b05040c7909a01 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 4 May 2017 23:03:03 +0100 Subject: [PATCH 0365/2557] lavc: Add coded bitstream read/write support for MPEG-2 Also enable MPEG-2 support in the trace_headers filter. --- configure | 4 +- doc/bitstream_filters.texi | 2 +- libavcodec/Makefile | 1 + libavcodec/cbs.c | 3 + libavcodec/cbs_internal.h | 1 + libavcodec/cbs_mpeg2.c | 409 +++++++++++++++++++++++++ libavcodec/cbs_mpeg2.h | 216 +++++++++++++ libavcodec/cbs_mpeg2_syntax_template.c | 340 ++++++++++++++++++++ libavcodec/trace_headers_bsf.c | 1 + 9 files changed, 975 insertions(+), 2 deletions(-) create mode 100644 libavcodec/cbs_mpeg2.c create mode 100644 libavcodec/cbs_mpeg2.h create mode 100644 libavcodec/cbs_mpeg2_syntax_template.c diff --git a/configure b/configure index 9704b9316a3d6..1e33ded01ed92 100755 --- a/configure +++ b/configure @@ -1742,6 +1742,7 @@ CONFIG_EXTRA=" cbs cbs_h264 cbs_h265 + cbs_mpeg2 dirac_parse dvprofile faandct @@ -1970,6 +1971,7 @@ threads_if_any="$THREADS_LIST" # subsystems cbs_h264_select="cbs golomb" cbs_h265_select="cbs golomb" +cbs_mpeg2_select="cbs" dct_select="rdft" dirac_parse_select="golomb" error_resilience_select="me_cmp" @@ -2327,7 +2329,7 @@ h264_metadata_bsf_select="cbs_h264" h264_redundant_pps_bsf_select="cbs_h264" hevc_metadata_bsf_select="cbs_h265" mjpeg2jpeg_bsf_select="jpegtables" -trace_headers_bsf_select="cbs_h264 cbs_h265" +trace_headers_bsf_select="cbs_h264 cbs_h265 cbs_mpeg2" # external libraries avisynth_deps="LoadLibrary" diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 21371ea9a6c1c..cacc0fc4a3ca7 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -227,7 +227,7 @@ Log trace output containing all syntax elements in the coded stream headers (everything above the level of individual coded blocks). This can be useful for debugging low-level stream issues. -Supports H.264 and H.265. +Supports H.264, H.265 and MPEG-2. @section vp9_superframe diff --git a/libavcodec/Makefile b/libavcodec/Makefile index ffd17c9cf0802..e5a54c9b66c65 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -56,6 +56,7 @@ OBJS-$(CONFIG_CABAC) += cabac.o OBJS-$(CONFIG_CBS) += cbs.o OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o h2645_parse.o OBJS-$(CONFIG_CBS_H265) += cbs_h2645.o h2645_parse.o +OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o OBJS-$(CONFIG_FAANDCT) += faandct.o diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index b5d5dfd2fd053..10943164da141 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -34,6 +34,9 @@ static const CodedBitstreamType *cbs_type_table[] = { #if CONFIG_CBS_H265 &ff_cbs_type_h265, #endif +#if CONFIG_CBS_MPEG2 + &ff_cbs_type_mpeg2, +#endif }; int ff_cbs_init(CodedBitstreamContext *ctx, diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index 0457f4ab9e1b6..dddeae9d5bd46 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -82,6 +82,7 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc, extern const CodedBitstreamType ff_cbs_type_h264; extern const CodedBitstreamType ff_cbs_type_h265; +extern const CodedBitstreamType ff_cbs_type_mpeg2; #endif /* AVCODEC_CBS_INTERNAL_H */ diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c new file mode 100644 index 0000000000000..fede3ff471bbd --- /dev/null +++ b/libavcodec/cbs_mpeg2.c @@ -0,0 +1,409 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" + +#include "cbs.h" +#include "cbs_internal.h" +#include "cbs_mpeg2.h" +#include "internal.h" + + +#define HEADER(name) do { \ + ff_cbs_trace_header(ctx, name); \ + } while (0) + +#define CHECK(call) do { \ + err = (call); \ + if (err < 0) \ + return err; \ + } while (0) + +#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name +#define FUNC_MPEG2(rw, name) FUNC_NAME(rw, mpeg2, name) +#define FUNC(name) FUNC_MPEG2(READWRITE, name) + + +#define READ +#define READWRITE read +#define RWContext BitstreamContext + +#define xui(width, name, var) do { \ + uint32_t value = 0; \ + CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \ + &value, 0, (1 << width) - 1)); \ + var = value; \ + } while (0) + +#define ui(width, name) \ + xui(width, name, current->name) + +#define marker_bit() do { \ + av_unused int one = 1; \ + CHECK(ff_cbs_read_unsigned(ctx, rw, 1, "marker_bit", &one, 1, 1)); \ + } while (0) + +#define nextbits(width, compare, var) (var = bitstream_peek(rw, width), \ + var == (compare)) + +#include "cbs_mpeg2_syntax_template.c" + +#undef READ +#undef READWRITE +#undef RWContext +#undef xui +#undef ui +#undef marker_bit +#undef nextbits + + +#define WRITE +#define READWRITE write +#define RWContext PutBitContext + +#define xui(width, name, var) do { \ + CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \ + var, 0, (1 << width) - 1)); \ + } while (0) + +#define ui(width, name) \ + xui(width, name, current->name) + +#define marker_bit() do { \ + CHECK(ff_cbs_write_unsigned(ctx, rw, 1, "marker_bit", 1, 1, 1)); \ + } while (0) + +#define nextbits(width, compare, var) (var) + +#include "cbs_mpeg2_syntax_template.c" + +#undef READ +#undef READWRITE +#undef RWContext +#undef xui +#undef ui +#undef marker_bit +#undef nextbits + + +static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int header) +{ + const uint8_t *start, *end; + uint8_t *unit_data; + uint32_t start_code = -1, next_start_code = -1; + size_t unit_size; + int err, i, unit_type; + + start = avpriv_find_start_code(frag->data, frag->data + frag->data_size, + &start_code); + for (i = 0;; i++) { + end = avpriv_find_start_code(start, frag->data + frag->data_size, + &next_start_code); + + unit_type = start_code & 0xff; + + // The start and end pointers point at to the byte following the + // start_code_identifier in the start code that they found. + if (end == frag->data + frag->data_size) { + // We didn't find a start code, so this is the final unit. + unit_size = end - (start - 1); + } else { + // Unit runs from start to the beginning of the start code + // pointed to by end (including any padding zeroes). + unit_size = (end - 4) - (start - 1); + } + + unit_data = av_malloc(unit_size); + if (!unit_data) + return AVERROR(ENOMEM); + memcpy(unit_data, start - 1, unit_size); + + err = ff_cbs_insert_unit_data(ctx, frag, i, unit_type, + unit_data, unit_size); + if (err < 0) { + av_freep(&unit_data); + return err; + } + + if (end == frag->data + frag->data_size) + break; + + start_code = next_start_code; + start = end; + } + + return 0; +} + +static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + BitstreamContext bc; + int err; + + err = bitstream_init(&bc, unit->data, 8 * unit->data_size); + if (err < 0) + return err; + + if (MPEG2_START_IS_SLICE(unit->type)) { + MPEG2RawSlice *slice; + int pos, len; + + slice = av_mallocz(sizeof(*slice)); + if (!slice) + return AVERROR(ENOMEM); + err = cbs_mpeg2_read_slice_header(ctx, &bc, &slice->header); + if (err < 0) { + av_free(slice); + return err; + } + + pos = bitstream_tell(&bc); + len = unit->data_size; + + slice->data_size = len - pos / 8; + slice->data = av_malloc(slice->data_size); + if (!slice->data) { + av_free(slice); + return AVERROR(ENOMEM); + } + + memcpy(slice->data, + unit->data + pos / 8, slice->data_size); + slice->data_bit_start = pos % 8; + + unit->content = slice; + + } else { + switch (unit->type) { +#define START(start_code, type, func) \ + case start_code: \ + { \ + type *header; \ + header = av_mallocz(sizeof(*header)); \ + if (!header) \ + return AVERROR(ENOMEM); \ + err = cbs_mpeg2_read_ ## func(ctx, &bc, header); \ + if (err < 0) { \ + av_free(header); \ + return err; \ + } \ + unit->content = header; \ + } \ + break; + START(0x00, MPEG2RawPictureHeader, picture_header); + START(0xb2, MPEG2RawUserData, user_data); + START(0xb3, MPEG2RawSequenceHeader, sequence_header); + START(0xb5, MPEG2RawExtensionData, extension_data); + START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header); +#undef START + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown start code %02x.\n", + unit->type); + return AVERROR_INVALIDDATA; + } + } + + return 0; +} + +static int cbs_mpeg2_write_header(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + PutBitContext *pbc) +{ + int err; + + switch (unit->type) { +#define START(start_code, type, func) \ + case start_code: \ + err = cbs_mpeg2_write_ ## func(ctx, pbc, unit->content); \ + break; + START(0x00, MPEG2RawPictureHeader, picture_header); + START(0xb2, MPEG2RawUserData, user_data); + START(0xb3, MPEG2RawSequenceHeader, sequence_header); + START(0xb5, MPEG2RawExtensionData, extension_data); + START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header); +#undef START + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for start " + "code %02x.\n", unit->type); + return AVERROR_PATCHWELCOME; + } + + return err; +} + +static int cbs_mpeg2_write_slice(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + PutBitContext *pbc) +{ + MPEG2RawSlice *slice = unit->content; + BitstreamContext bc; + size_t bits_left; + int err; + + err = cbs_mpeg2_write_slice_header(ctx, pbc, &slice->header); + if (err < 0) + return err; + + if (slice->data) { + if (slice->data_size * 8 + 8 > put_bits_left(pbc)) + return AVERROR(ENOSPC); + + bitstream_init(&bc, slice->data, slice->data_size * 8); + bitstream_skip(&bc, slice->data_bit_start); + + while (bitstream_bits_left(&bc) > 15) + put_bits(pbc, 16, bitstream_read(&bc, 16)); + + bits_left = bitstream_bits_left(&bc); + put_bits(pbc, bits_left, bitstream_read(&bc, bits_left)); + + // Align with zeroes. + while (put_bits_count(pbc) % 8 != 0) + put_bits(pbc, 1, 0); + } + + return 0; +} + +static int cbs_mpeg2_write_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + CodedBitstreamMPEG2Context *priv = ctx->priv_data; + PutBitContext pbc; + int err; + + if (!priv->write_buffer) { + // Initial write buffer size is 1MB. + priv->write_buffer_size = 1024 * 1024; + + reallocate_and_try_again: + err = av_reallocp(&priv->write_buffer, priv->write_buffer_size); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a " + "sufficiently large write buffer (last attempt " + "%zu bytes).\n", priv->write_buffer_size); + return err; + } + } + + init_put_bits(&pbc, priv->write_buffer, priv->write_buffer_size); + + if (unit->type >= 0x01 && unit->type <= 0xaf) + err = cbs_mpeg2_write_slice(ctx, unit, &pbc); + else + err = cbs_mpeg2_write_header(ctx, unit, &pbc); + + if (err == AVERROR(ENOSPC)) { + // Overflow. + priv->write_buffer_size *= 2; + goto reallocate_and_try_again; + } + if (err < 0) { + // Write failed for some other reason. + return err; + } + + if (put_bits_count(&pbc) % 8) + unit->data_bit_padding = 8 - put_bits_count(&pbc) % 8; + else + unit->data_bit_padding = 0; + + unit->data_size = (put_bits_count(&pbc) + 7) / 8; + flush_put_bits(&pbc); + + err = av_reallocp(&unit->data, unit->data_size); + if (err < 0) + return err; + + memcpy(unit->data, priv->write_buffer, unit->data_size); + + return 0; +} + +static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag) +{ + uint8_t *data; + size_t size, dp, sp; + int i; + + size = 0; + for (i = 0; i < frag->nb_units; i++) + size += 3 + frag->units[i].data_size; + + data = av_malloc(size); + if (!data) + return AVERROR(ENOMEM); + + dp = 0; + for (i = 0; i < frag->nb_units; i++) { + CodedBitstreamUnit *unit = &frag->units[i]; + + data[dp++] = 0; + data[dp++] = 0; + data[dp++] = 1; + + for (sp = 0; sp < unit->data_size; sp++) + data[dp++] = unit->data[sp]; + } + + av_assert0(dp == size); + + frag->data = data; + frag->data_size = size; + + return 0; +} + +static void cbs_mpeg2_free_unit(CodedBitstreamUnit *unit) +{ + if (MPEG2_START_IS_SLICE(unit->type)) { + MPEG2RawSlice *slice = unit->content; + av_freep(&slice->data); + av_freep(&slice->header.extra_information); + } else if (unit->type == MPEG2_START_USER_DATA) { + MPEG2RawUserData *user = unit->content; + av_freep(&user->user_data); + } + av_freep(&unit->content); +} + +static void cbs_mpeg2_close(CodedBitstreamContext *ctx) +{ + CodedBitstreamMPEG2Context *priv = ctx->priv_data; + + av_freep(&priv->write_buffer); +} + +const CodedBitstreamType ff_cbs_type_mpeg2 = { + .codec_id = AV_CODEC_ID_MPEG2VIDEO, + + .priv_data_size = sizeof(CodedBitstreamMPEG2Context), + + .split_fragment = &cbs_mpeg2_split_fragment, + .read_unit = &cbs_mpeg2_read_unit, + .write_unit = &cbs_mpeg2_write_unit, + .assemble_fragment = &cbs_mpeg2_assemble_fragment, + + .free_unit = &cbs_mpeg2_free_unit, + .close = &cbs_mpeg2_close, +}; diff --git a/libavcodec/cbs_mpeg2.h b/libavcodec/cbs_mpeg2.h new file mode 100644 index 0000000000000..32c4d4e2b10a9 --- /dev/null +++ b/libavcodec/cbs_mpeg2.h @@ -0,0 +1,216 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_MPEG2_H +#define AVCODEC_CBS_MPEG2_H + +#include +#include + + +enum { + MPEG2_START_PICTURE = 0x00, + MPEG2_START_SLICE_MIN = 0x01, + MPEG2_START_SLICE_MAX = 0xaf, + MPEG2_START_USER_DATA = 0xb2, + MPEG2_START_SEQUENCE_HEADER = 0xb3, + MPEG2_START_SEQUENCE_ERROR = 0xb4, + MPEG2_START_EXTENSION = 0xb5, + MPEG2_START_SEQUENCE_END = 0xb7, + MPEG2_START_GROUP = 0xb8, +}; + +#define MPEG2_START_IS_SLICE(type) \ + ((type) >= MPEG2_START_SLICE_MIN && \ + (type) <= MPEG2_START_SLICE_MAX) + +enum { + MPEG2_EXTENSION_SEQUENCE = 0x1, + MPEG2_EXTENSION_SEQUENCE_DISPLAY = 0x2, + MPEG2_EXTENSION_QUANT_MATRIX = 0x3, + MPEG2_EXTENSION_COPYRIGHT = 0x4, + MPEG2_EXTENSION_SEQUENCE_SCALABLE = 0x5, + MPEG2_EXTENSION_PICTURE_DISPLAY = 0x7, + MPEG2_EXTENSION_PICTURE_CODING = 0x8, + MPEG2_EXTENSION_PICTURE_SPATIAL_SCALABLE = 0x9, + MPEG2_EXTENSION_PICTURE_TEMPORAL_SCALABLE = 0xa, + MPEG2_EXTENSION_CAMAERA_PARAMETERS = 0xb, + MPEG2_EXTENSION_ITU_T = 0xc, +}; + + +typedef struct MPEG2RawSequenceHeader { + uint8_t sequence_header_code; + + uint16_t horizontal_size_value; + uint16_t vertical_size_value; + uint8_t aspect_ratio_information; + uint8_t frame_rate_code; + uint32_t bit_rate_value; + uint16_t vbv_buffer_size_value; + uint8_t constrained_parameters_flag; + + uint8_t load_intra_quantiser_matrix; + uint8_t intra_quantiser_matrix[64]; + uint8_t load_non_intra_quantiser_matrix; + uint8_t non_intra_quantiser_matrix[64]; +} MPEG2RawSequenceHeader; + +typedef struct MPEG2RawUserData { + uint8_t user_data_start_code; + + uint8_t *user_data; + size_t user_data_length; +} MPEG2RawUserData; + +typedef struct MPEG2RawSequenceExtension { + uint8_t profile_and_level_indication; + uint8_t progressive_sequence; + uint8_t chroma_format; + uint8_t horizontal_size_extension; + uint8_t vertical_size_extension; + uint16_t bit_rate_extension; + uint8_t vbv_buffer_size_extension; + uint8_t low_delay; + uint8_t frame_rate_extension_n; + uint8_t frame_rate_extension_d; +} MPEG2RawSequenceExtension; + +typedef struct MPEG2RawSequenceDisplayExtension { + uint8_t video_format; + + uint8_t colour_description; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; + + uint16_t display_horizontal_size; + uint16_t display_vertical_size; +} MPEG2RawSequenceDisplayExtension; + +typedef struct MPEG2RawGroupOfPicturesHeader { + uint8_t group_start_code; + + uint32_t time_code; + uint8_t closed_gop; + uint8_t broken_link; +} MPEG2RawGroupOfPicturesHeader; + +typedef struct MPEG2RawPictureHeader { + uint8_t picture_start_code; + + uint16_t temporal_reference; + uint8_t picture_coding_type; + uint16_t vbv_delay; + + uint8_t full_pel_forward_vector; + uint8_t forward_f_code; + uint8_t full_pel_backward_vector; + uint8_t backward_f_code; + + uint8_t extra_bit_picture; +} MPEG2RawPictureHeader; + +typedef struct MPEG2RawPictureCodingExtension { + uint8_t f_code[2][2]; + + uint8_t intra_dc_precision; + uint8_t picture_structure; + uint8_t top_field_first; + uint8_t frame_pred_frame_dct; + uint8_t concealment_motion_vectors; + uint8_t q_scale_type; + uint8_t intra_vlc_format; + uint8_t alternate_scan; + uint8_t repeat_first_field; + uint8_t chroma_420_type; + uint8_t progressive_frame; + + uint8_t composite_display_flag; + uint8_t v_axis; + uint8_t field_sequence; + uint8_t sub_carrier; + uint8_t burst_amplitude; + uint8_t sub_carrier_phase; +} MPEG2RawPictureCodingExtension; + +typedef struct MPEG2RawQuantMatrixExtension { + uint8_t load_intra_quantiser_matrix; + uint8_t intra_quantiser_matrix[64]; + uint8_t load_non_intra_quantiser_matrix; + uint8_t non_intra_quantiser_matrix[64]; + uint8_t load_chroma_intra_quantiser_matrix; + uint8_t chroma_intra_quantiser_matrix[64]; + uint8_t load_chroma_non_intra_quantiser_matrix; + uint8_t chroma_non_intra_quantiser_matrix[64]; +} MPEG2RawQuantMatrixExtension; + +typedef struct MPEG2RawExtensionData { + uint8_t extension_start_code; + uint8_t extension_start_code_identifier; + + union { + MPEG2RawSequenceExtension sequence; + MPEG2RawSequenceDisplayExtension sequence_display; + MPEG2RawQuantMatrixExtension quant_matrix; + MPEG2RawPictureCodingExtension picture_coding; + } data; +} MPEG2RawExtensionData; + +typedef struct MPEG2RawSliceHeader { + uint8_t slice_vertical_position; + + uint8_t slice_vertical_position_extension; + uint8_t priority_breakpoint; + + uint8_t quantiser_scale_code; + + uint8_t slice_extension_flag; + uint8_t intra_slice; + uint8_t slice_picture_id_enable; + uint8_t slice_picture_id; + + uint8_t extra_bit_slice; + + size_t extra_information_length; + uint8_t *extra_information; +} MPEG2RawSliceHeader; + +typedef struct MPEG2RawSlice { + MPEG2RawSliceHeader header; + + uint8_t *data; + size_t data_size; + int data_bit_start; +} MPEG2RawSlice; + + +typedef struct CodedBitstreamMPEG2Context { + // Elements stored in headers which are required for other decoding. + uint16_t horizontal_size; + uint16_t vertical_size; + uint8_t scalable; + uint8_t scalable_mode; + + // Write buffer. + uint8_t *write_buffer; + size_t write_buffer_size; +} CodedBitstreamMPEG2Context; + + +#endif /* AVCODEC_CBS_MPEG2_H */ diff --git a/libavcodec/cbs_mpeg2_syntax_template.c b/libavcodec/cbs_mpeg2_syntax_template.c new file mode 100644 index 0000000000000..b6dd42d2eebee --- /dev/null +++ b/libavcodec/cbs_mpeg2_syntax_template.c @@ -0,0 +1,340 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static int FUNC(sequence_header)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawSequenceHeader *current) +{ + CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; + int err, i; + + HEADER("Sequence Header"); + + ui(8, sequence_header_code); + + ui(12, horizontal_size_value); + ui(12, vertical_size_value); + + mpeg2->horizontal_size = current->horizontal_size_value; + mpeg2->vertical_size = current->vertical_size_value; + + ui(4, aspect_ratio_information); + ui(4, frame_rate_code); + ui(18, bit_rate_value); + + marker_bit(); + + ui(10, vbv_buffer_size_value); + ui(1, constrained_parameters_flag); + + ui(1, load_intra_quantiser_matrix); + if (current->load_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, intra_quantiser_matrix[i]); + } + + ui(1, load_non_intra_quantiser_matrix); + if (current->load_non_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, non_intra_quantiser_matrix[i]); + } + + return 0; +} + +static int FUNC(user_data)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawUserData *current) +{ + size_t k; + int err; + + HEADER("User Data"); + + ui(8, user_data_start_code); + +#ifdef READ + k = bitstream_bits_left(rw); + av_assert0(k % 8 == 0); + current->user_data_length = k /= 8; + if (k > 0) { + current->user_data = av_malloc(k); + if (!current->user_data) + return AVERROR(ENOMEM); + } +#endif + + for (k = 0; k < current->user_data_length; k++) + xui(8, user_data, current->user_data[k]); + + return 0; +} + +static int FUNC(sequence_extension)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawSequenceExtension *current) +{ + CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; + int err; + + HEADER("Sequence Extension"); + + ui(8, profile_and_level_indication); + ui(1, progressive_sequence); + ui(2, chroma_format); + ui(2, horizontal_size_extension); + ui(2, vertical_size_extension); + + mpeg2->horizontal_size = (mpeg2->horizontal_size & 0xfff) | + current->horizontal_size_extension << 12; + mpeg2->vertical_size = (mpeg2->vertical_size & 0xfff) | + current->vertical_size_extension << 12; + + ui(12, bit_rate_extension); + marker_bit(); + ui(8, vbv_buffer_size_extension); + ui(1, low_delay); + ui(2, frame_rate_extension_n); + ui(5, frame_rate_extension_d); + + return 0; +} + +static int FUNC(sequence_display_extension)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawSequenceDisplayExtension *current) +{ + int err; + + HEADER("Sequence Display Extension"); + + ui(3, video_format); + + ui(1, colour_description); + if (current->colour_description) { + ui(8, colour_primaries); + ui(8, transfer_characteristics); + ui(8, matrix_coefficients); + } + + ui(14, display_horizontal_size); + marker_bit(); + ui(14, display_vertical_size); + + return 0; +} + +static int FUNC(group_of_pictures_header)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawGroupOfPicturesHeader *current) +{ + int err; + + HEADER("Group of Pictures Header"); + + ui(8, group_start_code); + + ui(25, time_code); + ui(1, closed_gop); + ui(1, broken_link); + + return 0; +} + +static int FUNC(picture_header)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawPictureHeader *current) +{ + int err; + + HEADER("Picture Header"); + + ui(8, picture_start_code); + + ui(10, temporal_reference); + ui(3, picture_coding_type); + ui(16, vbv_delay); + + if (current->picture_coding_type == 2 || + current->picture_coding_type == 3) { + ui(1, full_pel_forward_vector); + ui(3, forward_f_code); + } + + if (current->picture_coding_type == 3) { + ui(1, full_pel_backward_vector); + ui(3, backward_f_code); + } + + ui(1, extra_bit_picture); + + return 0; +} + +static int FUNC(picture_coding_extension)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawPictureCodingExtension *current) +{ + int err; + + HEADER("Picture Coding Extension"); + + ui(4, f_code[0][0]); + ui(4, f_code[0][1]); + ui(4, f_code[1][0]); + ui(4, f_code[1][1]); + + ui(2, intra_dc_precision); + ui(2, picture_structure); + ui(1, top_field_first); + ui(1, frame_pred_frame_dct); + ui(1, concealment_motion_vectors); + ui(1, q_scale_type); + ui(1, intra_vlc_format); + ui(1, alternate_scan); + ui(1, repeat_first_field); + ui(1, chroma_420_type); + ui(1, progressive_frame); + + ui(1, composite_display_flag); + if (current->composite_display_flag) { + ui(1, v_axis); + ui(3, field_sequence); + ui(1, sub_carrier); + ui(7, burst_amplitude); + ui(8, sub_carrier_phase); + } + + return 0; +} + +static int FUNC(quant_matrix_extension)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawQuantMatrixExtension *current) +{ + int err, i; + + HEADER("Quant Matrix Extension"); + + ui(1, load_intra_quantiser_matrix); + if (current->load_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, intra_quantiser_matrix[i]); + } + + ui(1, load_non_intra_quantiser_matrix); + if (current->load_non_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, non_intra_quantiser_matrix[i]); + } + + ui(1, load_chroma_intra_quantiser_matrix); + if (current->load_chroma_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, intra_quantiser_matrix[i]); + } + + ui(1, load_chroma_non_intra_quantiser_matrix); + if (current->load_chroma_non_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, chroma_non_intra_quantiser_matrix[i]); + } + + return 0; +} + +static int FUNC(extension_data)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawExtensionData *current) +{ + int err; + + HEADER("Extension Data"); + + ui(8, extension_start_code); + ui(4, extension_start_code_identifier); + + switch (current->extension_start_code_identifier) { + case 1: + return FUNC(sequence_extension) + (ctx, rw, ¤t->data.sequence); + case 2: + return FUNC(sequence_display_extension) + (ctx, rw, ¤t->data.sequence_display); + case 3: + return FUNC(quant_matrix_extension) + (ctx, rw, ¤t->data.quant_matrix); + case 8: + return FUNC(picture_coding_extension) + (ctx, rw, ¤t->data.picture_coding); + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid extension ID %d.\n", + current->extension_start_code_identifier); + return AVERROR_INVALIDDATA; + } +} + +static int FUNC(slice_header)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawSliceHeader *current) +{ + CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; + int err; + + HEADER("Slice Header"); + + ui(8, slice_vertical_position); + + if (mpeg2->vertical_size > 2800) + ui(3, slice_vertical_position_extension); + if (mpeg2->scalable) { + if (mpeg2->scalable_mode == 0) + ui(7, priority_breakpoint); + } + + ui(5, quantiser_scale_code); + + if (nextbits(1, 1, current->slice_extension_flag)) { + ui(1, slice_extension_flag); + ui(1, intra_slice); + ui(1, slice_picture_id_enable); + ui(6, slice_picture_id); + + { + size_t k; +#ifdef READ + BitstreamContext start; + uint8_t bit; + start = *rw; + for (k = 0; nextbits(1, 1, bit); k++) + bitstream_skip(rw, 8); + current->extra_information_length = k; + if (k > 0) { + *rw = start; + current->extra_information = + av_malloc(current->extra_information_length); + if (!current->extra_information) + return AVERROR(ENOMEM); + for (k = 0; k < current->extra_information_length; k++) { + xui(1, extra_bit_slice, bit); + xui(8, extra_information_slice, + current->extra_information[k]); + } + } +#else + for (k = 0; k < current->extra_information_length; k++) { + xui(1, extra_bit_slice, 1); + xui(8, extra_information_slice, current->extra_information[k]); + } +#endif + } + } + ui(1, extra_bit_slice); + + return 0; +} diff --git a/libavcodec/trace_headers_bsf.c b/libavcodec/trace_headers_bsf.c index 2d1fe636c2397..2f1369e4dcce3 100644 --- a/libavcodec/trace_headers_bsf.c +++ b/libavcodec/trace_headers_bsf.c @@ -112,6 +112,7 @@ static int trace_headers(AVBSFContext *bsf, AVPacket *out) static const enum AVCodecID trace_headers_codec_ids[] = { AV_CODEC_ID_H264, AV_CODEC_ID_HEVC, + AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_NONE, }; From b78c30d7ec26af67c00ce2002709a189f6a87a7e Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 1 Aug 2017 15:35:14 +0100 Subject: [PATCH 0366/2557] lavc: Add mpeg2_metadata bitstream filter --- configure | 1 + doc/bitstream_filters.texi | 36 ++++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/mpeg2_metadata_bsf.c | 360 ++++++++++++++++++++++++++++++++ 5 files changed, 399 insertions(+) create mode 100644 libavcodec/mpeg2_metadata_bsf.c diff --git a/configure b/configure index 1e33ded01ed92..3e5784f851ded 100755 --- a/configure +++ b/configure @@ -2329,6 +2329,7 @@ h264_metadata_bsf_select="cbs_h264" h264_redundant_pps_bsf_select="cbs_h264" hevc_metadata_bsf_select="cbs_h265" mjpeg2jpeg_bsf_select="jpegtables" +mpeg2_metadata_bsf_select="cbs_mpeg2" trace_headers_bsf_select="cbs_h264 cbs_h265 cbs_mpeg2" # external libraries diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index cacc0fc4a3ca7..23ac2949572af 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -210,6 +210,42 @@ avconv -i frame_%d.jpg -c:v copy rotated.avi @section movsub +@section mpeg2_metadata + +Modify metadata embedded in an MPEG-2 stream. + +@table @option +@item display_aspect_ratio +Set the display aspect ratio in the stream. + +The following fixed values are supported: +@table @option +@item 4/3 +@item 16/9 +@item 221/100 +@end table +Any other value will result in square pixels being signalled instead +(see H.262 section 6.3.3 and table 6-3). + +@item frame_rate +Set the frame rate in the stream. This is constructed from a table +of known values combined with a small multiplier and divisor - if +the supplied value is not exactly representable, the nearest +representable value will be used instead (see H.262 section 6.3.3 +and table 6-4). + +@item video_format +Set the video format in the stream (see H.262 section 6.3.6 and +table 6-6). + +@item colour_primaries +@item transfer_characteristics +@item matrix_coefficients +Set the colour description in the stream (see H.262 section 6.3.6 +and tables 6-7, 6-8 and 6-9). + +@end table + @section mp3_header_compress @section mp3_header_decompress diff --git a/libavcodec/Makefile b/libavcodec/Makefile index e5a54c9b66c65..9c485b222ebcb 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -786,6 +786,7 @@ OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o OBJS-$(CONFIG_MJPEGA_DUMP_HEADER_BSF) += mjpega_dump_header_bsf.o OBJS-$(CONFIG_MOV2TEXTSUB_BSF) += movsub_bsf.o +OBJS-$(CONFIG_MPEG2_METADATA_BSF) += mpeg2_metadata_bsf.o OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o OBJS-$(CONFIG_NULL_BSF) += null_bsf.o OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index e90919f6028b3..784170543f95f 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -37,6 +37,7 @@ extern const AVBitStreamFilter ff_imx_dump_header_bsf; extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf; extern const AVBitStreamFilter ff_mjpega_dump_header_bsf; extern const AVBitStreamFilter ff_mov2textsub_bsf; +extern const AVBitStreamFilter ff_mpeg2_metadata_bsf; extern const AVBitStreamFilter ff_null_bsf; extern const AVBitStreamFilter ff_text2movsub_bsf; extern const AVBitStreamFilter ff_noise_bsf; diff --git a/libavcodec/mpeg2_metadata_bsf.c b/libavcodec/mpeg2_metadata_bsf.c new file mode 100644 index 0000000000000..80e946f58e7f6 --- /dev/null +++ b/libavcodec/mpeg2_metadata_bsf.c @@ -0,0 +1,360 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "bsf.h" +#include "cbs.h" +#include "cbs_mpeg2.h" + +typedef struct MPEG2MetadataContext { + const AVClass *class; + + CodedBitstreamContext cbc; + CodedBitstreamFragment fragment; + + MPEG2RawExtensionData sequence_display_extension; + + AVRational display_aspect_ratio; + + AVRational frame_rate; + + int video_format; + int colour_primaries; + int transfer_characteristics; + int matrix_coefficients; + + int mpeg1_warned; +} MPEG2MetadataContext; + + +static int mpeg2_metadata_update_fragment(AVBSFContext *bsf, + CodedBitstreamFragment *frag) +{ + MPEG2MetadataContext *ctx = bsf->priv_data; + MPEG2RawSequenceHeader *sh = NULL; + MPEG2RawSequenceExtension *se = NULL; + MPEG2RawSequenceDisplayExtension *sde = NULL; + int i, se_pos, add_sde = 0; + + for (i = 0; i < frag->nb_units; i++) { + if (frag->units[i].type == MPEG2_START_SEQUENCE_HEADER) { + sh = frag->units[i].content; + } else if (frag->units[i].type == MPEG2_START_EXTENSION) { + MPEG2RawExtensionData *ext = frag->units[i].content; + if (ext->extension_start_code_identifier == + MPEG2_EXTENSION_SEQUENCE) { + se = &ext->data.sequence; + se_pos = i; + } else if (ext->extension_start_code_identifier == + MPEG2_EXTENSION_SEQUENCE_DISPLAY) { + sde = &ext->data.sequence_display; + } + } + } + + if (!sh || !se) { + // No sequence header and sequence extension: not an MPEG-2 video + // sequence. + if (sh && !ctx->mpeg1_warned) { + av_log(bsf, AV_LOG_WARNING, "Stream contains a sequence " + "header but not a sequence extension: maybe it's " + "actually MPEG-1?\n"); + ctx->mpeg1_warned = 1; + } + return 0; + } + + if (ctx->display_aspect_ratio.num && ctx->display_aspect_ratio.den) { + int num, den; + + av_reduce(&num, &den, ctx->display_aspect_ratio.num, + ctx->display_aspect_ratio.den, 65535); + + if (num == 4 && den == 3) + sh->aspect_ratio_information = 2; + else if (num == 16 && den == 9) + sh->aspect_ratio_information = 3; + else if (num == 221 && den == 100) + sh->aspect_ratio_information = 4; + else + sh->aspect_ratio_information = 1; + } + + if (ctx->frame_rate.num && ctx->frame_rate.den) { + // Table 6-4. + static AVRational frame_rate_table[] = { + { 0, 0 }, + { 24000, 1001 }, + { 24, 1 }, + { 25, 1 }, + { 30000, 1001 }, + { 30, 1 }, + { 50, 1 }, + { 60000, 1001 }, + { 60, 1 }, + }; + int code, ext_n, ext_d; + AVRational best_error = { INT_MAX, 1 }; + + for (i = 1; i < FF_ARRAY_ELEMS(frame_rate_table); i++) { + if (av_cmp_q(ctx->frame_rate, frame_rate_table[i]) == 0) { + code = i; + ext_n = 1; + ext_d = 1; + goto found_frame_rate; + } + } + + for (i = 1; i < FF_ARRAY_ELEMS(frame_rate_table); i++) { + AVRational fr, error; + int n, d, cmp; + for (n = 1; n <= 4; n++) { + for (d = 1; d <= 32; d++) { + fr = av_mul_q(frame_rate_table[i], + (AVRational) { n, d }); + cmp = av_cmp_q(fr, ctx->frame_rate); + if (cmp == 0) { + code = i; + ext_n = n; + ext_d = d; + goto found_frame_rate; + } + if (cmp < 0) + error = av_div_q(ctx->frame_rate, fr); + else + error = av_div_q(fr, ctx->frame_rate); + cmp = av_cmp_q(error, best_error); + if (cmp < 0 || (cmp == 0 && n == 1 && d == 1)) { + code = i; + ext_n = n; + ext_d = d; + best_error = error; + } + } + } + } + + found_frame_rate: + sh->frame_rate_code = code; + se->frame_rate_extension_n = ext_n - 1; + se->frame_rate_extension_d = ext_d - 1; + } + + if (ctx->video_format >= 0 || + ctx->colour_primaries >= 0 || + ctx->transfer_characteristics >= 0 || + ctx->matrix_coefficients >= 0) { + if (!sde) { + add_sde = 1; + ctx->sequence_display_extension.extension_start_code = + MPEG2_START_EXTENSION; + ctx->sequence_display_extension.extension_start_code_identifier = + MPEG2_EXTENSION_SEQUENCE_DISPLAY; + sde = &ctx->sequence_display_extension.data.sequence_display; + + *sde = (MPEG2RawSequenceDisplayExtension) { + .video_format = 5, + + .colour_description = 0, + .colour_primaries = 2, + .transfer_characteristics = 2, + .matrix_coefficients = 2, + + .display_horizontal_size = + se->horizontal_size_extension << 12 | sh->horizontal_size_value, + .display_vertical_size = + se->vertical_size_extension << 12 | sh->vertical_size_value, + }; + } + + if (ctx->video_format >= 0) + sde->video_format = ctx->video_format; + + if (ctx->colour_primaries >= 0 || + ctx->transfer_characteristics >= 0 || + ctx->matrix_coefficients >= 0) { + sde->colour_description = 1; + + if (ctx->colour_primaries >= 0) + sde->colour_primaries = ctx->colour_primaries; + else if (add_sde) + sde->colour_primaries = 2; + + if (ctx->transfer_characteristics >= 0) + sde->transfer_characteristics = ctx->transfer_characteristics; + else if (add_sde) + sde->transfer_characteristics = 2; + + if (ctx->matrix_coefficients >= 0) + sde->matrix_coefficients = ctx->matrix_coefficients; + else if (add_sde) + sde->matrix_coefficients = 2; + } + } + + if (add_sde) { + int err; + + err = ff_cbs_insert_unit_content(&ctx->cbc, frag, se_pos + 1, + MPEG2_START_EXTENSION, + &ctx->sequence_display_extension); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to insert new sequence " + "display extension.\n"); + return err; + } + } + + return 0; +} + +static int mpeg2_metadata_filter(AVBSFContext *bsf, AVPacket *out) +{ + MPEG2MetadataContext *ctx = bsf->priv_data; + AVPacket *in = NULL; + CodedBitstreamFragment *frag = &ctx->fragment; + int err; + + err = ff_bsf_get_packet(bsf, &in); + if (err < 0) + goto fail; + + err = ff_cbs_read_packet(&ctx->cbc, frag, in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); + goto fail; + } + + err = mpeg2_metadata_update_fragment(bsf, frag); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to update frame fragment.\n"); + goto fail; + } + + err = ff_cbs_write_packet(&ctx->cbc, out, frag); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); + goto fail; + } + + err = av_packet_copy_props(out, in); + if (err < 0) { + av_packet_unref(out); + goto fail; + } + + err = 0; +fail: + ff_cbs_fragment_uninit(&ctx->cbc, frag); + + av_packet_free(&in); + + return err; +} + +static int mpeg2_metadata_init(AVBSFContext *bsf) +{ + MPEG2MetadataContext *ctx = bsf->priv_data; + CodedBitstreamFragment *frag = &ctx->fragment; + int err; + + err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_MPEG2VIDEO, bsf); + if (err < 0) + return err; + + if (bsf->par_in->extradata) { + err = ff_cbs_read_extradata(&ctx->cbc, frag, bsf->par_in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); + goto fail; + } + + err = mpeg2_metadata_update_fragment(bsf, frag); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to update metadata fragment.\n"); + goto fail; + } + + err = ff_cbs_write_extradata(&ctx->cbc, bsf->par_out, frag); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); + goto fail; + } + } + + err = 0; +fail: + ff_cbs_fragment_uninit(&ctx->cbc, frag); + return err; +} + +static void mpeg2_metadata_close(AVBSFContext *bsf) +{ + MPEG2MetadataContext *ctx = bsf->priv_data; + ff_cbs_close(&ctx->cbc); +} + +#define OFFSET(x) offsetof(MPEG2MetadataContext, x) +static const AVOption mpeg2_metadata_options[] = { + { "display_aspect_ratio", "Set display aspect ratio (table 6-3)", + OFFSET(display_aspect_ratio), AV_OPT_TYPE_RATIONAL, + { .i64 = 0 }, 0, 65535 }, + + { "frame_rate", "Set frame rate", + OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, + { .i64 = 0 }, 0, UINT_MAX }, + + { "video_format", "Set video format (table 6-6)", + OFFSET(video_format), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 7 }, + { "colour_primaries", "Set colour primaries (table 6-7)", + OFFSET(colour_primaries), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + { "transfer_characteristics", "Set transfer characteristics (table 6-8)", + OFFSET(transfer_characteristics), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + { "matrix_coefficients", "Set matrix coefficients (table 6-9)", + OFFSET(matrix_coefficients), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + + { NULL } +}; + +static const AVClass mpeg2_metadata_class = { + .class_name = "mpeg2_metadata_bsf", + .item_name = av_default_item_name, + .option = mpeg2_metadata_options, + .version = LIBAVCODEC_VERSION_MAJOR, +}; + +static const enum AVCodecID mpeg2_metadata_codec_ids[] = { + AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_mpeg2_metadata_bsf = { + .name = "mpeg2_metadata", + .priv_data_size = sizeof(MPEG2MetadataContext), + .priv_class = &mpeg2_metadata_class, + .init = &mpeg2_metadata_init, + .close = &mpeg2_metadata_close, + .filter = &mpeg2_metadata_filter, + .codec_ids = mpeg2_metadata_codec_ids, +}; From 4c0588b4562abad5540f6a5435c62828de9e4fdf Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 12 Aug 2017 22:16:13 +0100 Subject: [PATCH 0367/2557] mpeg2enc: Don't mark all streams as component video Since there is no information about the source format, "unspecified" is the correct value to write here. All tests using the MPEG-2 encoder are updated, as this changes the header on all outputs. --- libavcodec/mpeg12enc.c | 2 +- tests/ref/lavf/gxf | 2 +- tests/ref/lavf/mxf | 2 +- tests/ref/lavf/mxf_d10 | 2 +- tests/ref/lavf/ts | 2 +- tests/ref/vsynth/vsynth1-mpeg2 | 2 +- tests/ref/vsynth/vsynth1-mpeg2-422 | 2 +- tests/ref/vsynth/vsynth1-mpeg2-idct-int | 2 +- tests/ref/vsynth/vsynth1-mpeg2-ilace | 2 +- tests/ref/vsynth/vsynth1-mpeg2-ivlc-qprd | 2 +- tests/ref/vsynth/vsynth1-mpeg2-thread | 2 +- tests/ref/vsynth/vsynth1-mpeg2-thread-ivlc | 2 +- tests/ref/vsynth/vsynth2-mpeg2 | 2 +- tests/ref/vsynth/vsynth2-mpeg2-422 | 2 +- tests/ref/vsynth/vsynth2-mpeg2-idct-int | 2 +- tests/ref/vsynth/vsynth2-mpeg2-ilace | 2 +- tests/ref/vsynth/vsynth2-mpeg2-ivlc-qprd | 2 +- tests/ref/vsynth/vsynth2-mpeg2-thread | 2 +- tests/ref/vsynth/vsynth2-mpeg2-thread-ivlc | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 103f3aaa77146..406950901e144 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -297,7 +297,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) put_header(s, EXT_START_CODE); put_bits(&s->pb, 4, 2); // sequence display extension - put_bits(&s->pb, 3, 0); // video_format: 0 is components + put_bits(&s->pb, 3, 5); // video_format: 5 is unspecified put_bits(&s->pb, 1, 1); // colour_description put_bits(&s->pb, 8, s->avctx->color_primaries); // colour_primaries put_bits(&s->pb, 8, s->avctx->color_trc); // transfer_characteristics diff --git a/tests/ref/lavf/gxf b/tests/ref/lavf/gxf index 8dfd63d646057..a390a070fc157 100644 --- a/tests/ref/lavf/gxf +++ b/tests/ref/lavf/gxf @@ -1,3 +1,3 @@ -a1cf0a335ad64ec526bb69bbca0656c2 *./tests/data/lavf/lavf.gxf +bfc25e31136275aff0f9126610b8a7e4 *./tests/data/lavf/lavf.gxf 796428 ./tests/data/lavf/lavf.gxf ./tests/data/lavf/lavf.gxf CRC=0xd04c769f diff --git a/tests/ref/lavf/mxf b/tests/ref/lavf/mxf index 09e3c36bbc8f0..105e33a3e25fd 100644 --- a/tests/ref/lavf/mxf +++ b/tests/ref/lavf/mxf @@ -1,3 +1,3 @@ -051b982c1b5799eb107339735a090c70 *./tests/data/lavf/lavf.mxf +7c9efc1b6f5fc65bf39177887512fefd *./tests/data/lavf/lavf.mxf 525881 ./tests/data/lavf/lavf.mxf ./tests/data/lavf/lavf.mxf CRC=0x773f059a diff --git a/tests/ref/lavf/mxf_d10 b/tests/ref/lavf/mxf_d10 index 8a62bb092ad09..74991a5750fc7 100644 --- a/tests/ref/lavf/mxf_d10 +++ b/tests/ref/lavf/mxf_d10 @@ -1,3 +1,3 @@ -96f933913835a439dd97144303dc8929 *./tests/data/lavf/lavf.mxf_d10 +5fbb6252f6b146cd36d1491ca96ad8a3 *./tests/data/lavf/lavf.mxf_d10 5330989 ./tests/data/lavf/lavf.mxf_d10 ./tests/data/lavf/lavf.mxf_d10 CRC=0x4474d480 diff --git a/tests/ref/lavf/ts b/tests/ref/lavf/ts index caf08a85b7511..6846f700cc299 100644 --- a/tests/ref/lavf/ts +++ b/tests/ref/lavf/ts @@ -1,3 +1,3 @@ -f74d6f4d4073f4242cec3d5fee099779 *./tests/data/lavf/lavf.ts +7a479525b7dc9264291cb2fc3e1d28e5 *./tests/data/lavf/lavf.ts 406456 ./tests/data/lavf/lavf.ts ./tests/data/lavf/lavf.ts CRC=0xb4ca6cdc diff --git a/tests/ref/vsynth/vsynth1-mpeg2 b/tests/ref/vsynth/vsynth1-mpeg2 index d0baa0ac815c1..15b27ea15d72e 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2 +++ b/tests/ref/vsynth/vsynth1-mpeg2 @@ -1,4 +1,4 @@ -50c344f0e0e3c65001a68b2c899a283f *tests/data/fate/vsynth1-mpeg2.mpeg2video +080866b0a4570c672ccc7cf3e6e7bec7 *tests/data/fate/vsynth1-mpeg2.mpeg2video 728104 tests/data/fate/vsynth1-mpeg2.mpeg2video b41ca49c1a02e66ce64d262e2cdaec15 *tests/data/fate/vsynth1-mpeg2.out.rawvideo stddev: 7.65 PSNR: 30.45 MAXDIFF: 84 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2-422 b/tests/ref/vsynth/vsynth1-mpeg2-422 index 1209e8879f95b..80acf6146aa48 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2-422 +++ b/tests/ref/vsynth/vsynth1-mpeg2-422 @@ -1,4 +1,4 @@ -c2124749526d2d4d41398d52557fad1b *tests/data/fate/vsynth1-mpeg2-422.mpeg2video +e59f232030cd0fb7e7839e3f8cd6a1b7 *tests/data/fate/vsynth1-mpeg2-422.mpeg2video 728260 tests/data/fate/vsynth1-mpeg2-422.mpeg2video eb7fe83ce09af2d79ec16577c9d44e3c *tests/data/fate/vsynth1-mpeg2-422.out.rawvideo stddev: 10.29 PSNR: 27.88 MAXDIFF: 168 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2-idct-int b/tests/ref/vsynth/vsynth1-mpeg2-idct-int index cc789bbc286d3..b74256a069799 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2-idct-int +++ b/tests/ref/vsynth/vsynth1-mpeg2-idct-int @@ -1,4 +1,4 @@ -d0cc23c61c4afcfdf0fea53b31c6df38 *tests/data/fate/vsynth1-mpeg2-idct-int.mpeg2video +308f13d87d676c5c2964d25ee98fd58d *tests/data/fate/vsynth1-mpeg2-idct-int.mpeg2video 725728 tests/data/fate/vsynth1-mpeg2-idct-int.mpeg2video 8130f71a467315c9e7bd1a25a01dbb23 *tests/data/fate/vsynth1-mpeg2-idct-int.out.rawvideo stddev: 7.65 PSNR: 30.45 MAXDIFF: 80 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2-ilace b/tests/ref/vsynth/vsynth1-mpeg2-ilace index 81e43c5c920b0..bab678c4eb75e 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2-ilace +++ b/tests/ref/vsynth/vsynth1-mpeg2-ilace @@ -1,4 +1,4 @@ -c8e27cddb2da4d76816c258b6e3d1fab *tests/data/fate/vsynth1-mpeg2-ilace.mpeg2video +aad9db175e5737ab64a6615879cc7f45 *tests/data/fate/vsynth1-mpeg2-ilace.mpeg2video 737533 tests/data/fate/vsynth1-mpeg2-ilace.mpeg2video 97615390fdd69abfcbc7e02df863a7d2 *tests/data/fate/vsynth1-mpeg2-ilace.out.rawvideo stddev: 7.67 PSNR: 30.43 MAXDIFF: 84 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2-ivlc-qprd b/tests/ref/vsynth/vsynth1-mpeg2-ivlc-qprd index 647525dbb1214..d95a82aaec0a5 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2-ivlc-qprd +++ b/tests/ref/vsynth/vsynth1-mpeg2-ivlc-qprd @@ -1,4 +1,4 @@ -ba08be2c6209f6b88be97e6fe74911db *tests/data/fate/vsynth1-mpeg2-ivlc-qprd.mpeg2video +b8bcbf82af12bef19b62a65e1cd19ac4 *tests/data/fate/vsynth1-mpeg2-ivlc-qprd.mpeg2video 783612 tests/data/fate/vsynth1-mpeg2-ivlc-qprd.mpeg2video 98eb9da15f880978e7f2ee1e7ce476ef *tests/data/fate/vsynth1-mpeg2-ivlc-qprd.out.rawvideo stddev: 10.07 PSNR: 28.06 MAXDIFF: 165 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2-thread b/tests/ref/vsynth/vsynth1-mpeg2-thread index 1a479bcd90357..3cb9ba92fffcb 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2-thread +++ b/tests/ref/vsynth/vsynth1-mpeg2-thread @@ -1,4 +1,4 @@ -c17bee51286e13b0c95a504391632087 *tests/data/fate/vsynth1-mpeg2-thread.mpeg2video +e93f5d45ee16e5daa76f6fa670b93002 *tests/data/fate/vsynth1-mpeg2-thread.mpeg2video 801373 tests/data/fate/vsynth1-mpeg2-thread.mpeg2video d1658911ca83f5616c1d32abc40750de *tests/data/fate/vsynth1-mpeg2-thread.out.rawvideo stddev: 7.63 PSNR: 30.48 MAXDIFF: 110 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2-thread-ivlc b/tests/ref/vsynth/vsynth1-mpeg2-thread-ivlc index b211c94a9e546..f8ab2e19947bf 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2-thread-ivlc +++ b/tests/ref/vsynth/vsynth1-mpeg2-thread-ivlc @@ -1,4 +1,4 @@ -9f3991d18d5dc5240ca61b158ce76521 *tests/data/fate/vsynth1-mpeg2-thread-ivlc.mpeg2video +a6399b82227292955612b0917c7ef4ca *tests/data/fate/vsynth1-mpeg2-thread-ivlc.mpeg2video 791833 tests/data/fate/vsynth1-mpeg2-thread-ivlc.mpeg2video d1658911ca83f5616c1d32abc40750de *tests/data/fate/vsynth1-mpeg2-thread-ivlc.out.rawvideo stddev: 7.63 PSNR: 30.48 MAXDIFF: 110 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2 b/tests/ref/vsynth/vsynth2-mpeg2 index 7f441cb1f77b2..02071e0364ade 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2 +++ b/tests/ref/vsynth/vsynth2-mpeg2 @@ -1,4 +1,4 @@ -48d5feed5d7866457216577a75b60d59 *tests/data/fate/vsynth2-mpeg2.mpeg2video +0cf4cc4acbd5e19196890b66d88a428a *tests/data/fate/vsynth2-mpeg2.mpeg2video 268229 tests/data/fate/vsynth2-mpeg2.mpeg2video 5887392ff0a05babc480e9f29a1797a3 *tests/data/fate/vsynth2-mpeg2.out.rawvideo stddev: 5.55 PSNR: 33.23 MAXDIFF: 77 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2-422 b/tests/ref/vsynth/vsynth2-mpeg2-422 index ea30134fe8327..257101851c642 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2-422 +++ b/tests/ref/vsynth/vsynth2-mpeg2-422 @@ -1,4 +1,4 @@ -392cd150d65892060374ef0ca98b53c3 *tests/data/fate/vsynth2-mpeg2-422.mpeg2video +cf1ee8bc65f87fbe7b7ee76545bd45a9 *tests/data/fate/vsynth2-mpeg2-422.mpeg2video 379371 tests/data/fate/vsynth2-mpeg2-422.mpeg2video fa9fda9c92a455b39ae7e516b7de6919 *tests/data/fate/vsynth2-mpeg2-422.out.rawvideo stddev: 4.16 PSNR: 35.73 MAXDIFF: 70 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2-idct-int b/tests/ref/vsynth/vsynth2-mpeg2-idct-int index fe1ed8d3b0795..f5a075bad7a98 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2-idct-int +++ b/tests/ref/vsynth/vsynth2-mpeg2-idct-int @@ -1,4 +1,4 @@ -4fa4ce9e167fb1816522126d36acfd3c *tests/data/fate/vsynth2-mpeg2-idct-int.mpeg2video +5e121ff369249a98e080a50af2dadbbb *tests/data/fate/vsynth2-mpeg2-idct-int.mpeg2video 267430 tests/data/fate/vsynth2-mpeg2-idct-int.mpeg2video b750f48d58f157da94613fe92012e7a5 *tests/data/fate/vsynth2-mpeg2-idct-int.out.rawvideo stddev: 5.56 PSNR: 33.22 MAXDIFF: 77 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2-ilace b/tests/ref/vsynth/vsynth2-mpeg2-ilace index 565caf3d022fe..412d2827c0abc 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2-ilace +++ b/tests/ref/vsynth/vsynth2-mpeg2-ilace @@ -1,4 +1,4 @@ -be3bd3d5393320419e82afaaea6c6fb6 *tests/data/fate/vsynth2-mpeg2-ilace.mpeg2video +39c214a63ef520d00594ca1f37c5872a *tests/data/fate/vsynth2-mpeg2-ilace.mpeg2video 275014 tests/data/fate/vsynth2-mpeg2-ilace.mpeg2video fe069b1be5c6aa5808c0840008485912 *tests/data/fate/vsynth2-mpeg2-ilace.out.rawvideo stddev: 5.57 PSNR: 33.20 MAXDIFF: 77 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2-ivlc-qprd b/tests/ref/vsynth/vsynth2-mpeg2-ivlc-qprd index 58feb939433b5..3e49a38fa41da 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2-ivlc-qprd +++ b/tests/ref/vsynth/vsynth2-mpeg2-ivlc-qprd @@ -1,4 +1,4 @@ -5e938746a4b50f496db6faa10cbe98d6 *tests/data/fate/vsynth2-mpeg2-ivlc-qprd.mpeg2video +f6851fb214f3b5205362a32b06ab4917 *tests/data/fate/vsynth2-mpeg2-ivlc-qprd.mpeg2video 269774 tests/data/fate/vsynth2-mpeg2-ivlc-qprd.mpeg2video 91316e6e990ee20b4a8de33f9e6adc56 *tests/data/fate/vsynth2-mpeg2-ivlc-qprd.out.rawvideo stddev: 5.54 PSNR: 33.25 MAXDIFF: 94 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2-thread b/tests/ref/vsynth/vsynth2-mpeg2-thread index 9c44e9f2cdee0..d7f8bcdf0acb3 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2-thread +++ b/tests/ref/vsynth/vsynth2-mpeg2-thread @@ -1,4 +1,4 @@ -722c04a6a442e0ae716e879dff4b6639 *tests/data/fate/vsynth2-mpeg2-thread.mpeg2video +4f68b8830ee1ed90526fb543ea3b9573 *tests/data/fate/vsynth2-mpeg2-thread.mpeg2video 230678 tests/data/fate/vsynth2-mpeg2-thread.mpeg2video f35531461e7b31bfba66802954329f2e *tests/data/fate/vsynth2-mpeg2-thread.out.rawvideo stddev: 5.31 PSNR: 33.62 MAXDIFF: 73 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2-thread-ivlc b/tests/ref/vsynth/vsynth2-mpeg2-thread-ivlc index 6e6763ee1862f..bd2f527d44742 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2-thread-ivlc +++ b/tests/ref/vsynth/vsynth2-mpeg2-thread-ivlc @@ -1,4 +1,4 @@ -32abf166f7a6fdb8e4b46795a60761cc *tests/data/fate/vsynth2-mpeg2-thread-ivlc.mpeg2video +fdae42a7f9d5f5ed97ae134be1c991e7 *tests/data/fate/vsynth2-mpeg2-thread-ivlc.mpeg2video 227906 tests/data/fate/vsynth2-mpeg2-thread-ivlc.mpeg2video f35531461e7b31bfba66802954329f2e *tests/data/fate/vsynth2-mpeg2-thread-ivlc.out.rawvideo stddev: 5.31 PSNR: 33.62 MAXDIFF: 73 bytes: 7603200/ 7603200 From 9f5b77c16f4da6248b57f0601364d9c762c620c2 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sun, 16 Jul 2017 13:46:16 +0200 Subject: [PATCH 0368/2557] png: Report more details regarding unsupported pixel formats --- libavcodec/pngdec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 927248f2e3464..7dc5c283d48c9 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -521,6 +521,9 @@ static int decode_frame(AVCodecContext *avctx, s->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { avctx->pix_fmt = AV_PIX_FMT_YA16BE; } else { + avpriv_report_missing_feature(avctx, + "Bit depth %d color type %d", + s->bit_depth, s->color_type); goto fail; } From 0c99b900d874b60ce89b94742b2215f163c87a2b Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sun, 16 Jul 2017 14:35:40 +0200 Subject: [PATCH 0369/2557] png: Support RGBA64 pixel format --- libavcodec/pngdec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 7dc5c283d48c9..bc8c95235241f 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -520,6 +520,9 @@ static int decode_frame(AVCodecContext *avctx, } else if (s->bit_depth == 16 && s->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { avctx->pix_fmt = AV_PIX_FMT_YA16BE; + } else if (s->bit_depth == 16 && + s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { + avctx->pix_fmt = AV_PIX_FMT_RGBA64BE; } else { avpriv_report_missing_feature(avctx, "Bit depth %d color type %d", From 7b7760ad6efb7b96122aa7133ad21e22653ae222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sun, 9 Jul 2017 23:52:10 +0300 Subject: [PATCH 0370/2557] aarch64: Fix negative movrel offsets for windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On windows, the offset for the relocation doesn't get stored in the relocation itself, but as an unsigned immediate in the opcode. Therefore, negative offsets has to be handled via a separate sub instruction, just as on MachO. Signed-off-by: Martin Storsjö --- libavutil/aarch64/asm.S | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavutil/aarch64/asm.S b/libavutil/aarch64/asm.S index 86d36cd57fe2e..7e2af4df17e3c 100644 --- a/libavutil/aarch64/asm.S +++ b/libavutil/aarch64/asm.S @@ -82,6 +82,15 @@ ELF .size \name, . - \name adrp \rd, \val+(\offset)@PAGE add \rd, \rd, \val+(\offset)@PAGEOFF .endif +#elif CONFIG_PIC && defined(_WIN32) + .if \offset < 0 + adrp \rd, \val + add \rd, \rd, :lo12:\val + sub \rd, \rd, -(\offset) + .else + adrp \rd, \val+(\offset) + add \rd, \rd, :lo12:\val+(\offset) + .endif #elif CONFIG_PIC adrp \rd, \val+(\offset) add \rd, \rd, :lo12:\val+(\offset) From feed239021bad89743d5e7989b426ae594322eb7 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 21 Aug 2017 09:55:48 +0200 Subject: [PATCH 0371/2557] yadif: Account for the buffer alignment while processing the frame edges Avoid out of bound reads. Bug-Id: 1031 CC: libav-stable@libav.org Signed-off-by: Luca Barbato --- libavfilter/vf_yadif.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c index 75f2d177588fe..bef357b8cf53d 100644 --- a/libavfilter/vf_yadif.c +++ b/libavfilter/vf_yadif.c @@ -40,6 +40,8 @@ typedef struct ThreadData { int tff; } ThreadData; +#define MAX_ALIGN 8 + #define CHECK(j)\ { int score = FFABS(cur[mrefs - 1 + (j)] - cur[prefs - 1 - (j)])\ + FFABS(cur[mrefs +(j)] - cur[prefs -(j)])\ @@ -123,17 +125,20 @@ static void filter_edges(void *dst1, void *prev1, void *cur1, void *next1, uint8_t *prev2 = parity ? prev : cur ; uint8_t *next2 = parity ? cur : next; + const int edge = MAX_ALIGN - 1; + /* Only edge pixels need to be processed here. A constant value of false * for is_not_edge should let the compiler ignore the whole branch. */ FILTER(0, 3, 0) - dst = (uint8_t*)dst1 + w - 3; - prev = (uint8_t*)prev1 + w - 3; - cur = (uint8_t*)cur1 + w - 3; - next = (uint8_t*)next1 + w - 3; + dst = (uint8_t*)dst1 + w - edge; + prev = (uint8_t*)prev1 + w - edge; + cur = (uint8_t*)cur1 + w - edge; + next = (uint8_t*)next1 + w - edge; prev2 = (uint8_t*)(parity ? prev : cur); next2 = (uint8_t*)(parity ? cur : next); + FILTER(w - edge, w - 3, 1) FILTER(w - 3, w, 0) } @@ -166,18 +171,22 @@ static void filter_edges_16bit(void *dst1, void *prev1, void *cur1, void *next1, int x; uint16_t *prev2 = parity ? prev : cur ; uint16_t *next2 = parity ? cur : next; + + const int edge = MAX_ALIGN / 2 - 1; + mrefs /= 2; prefs /= 2; FILTER(0, 3, 0) - dst = (uint16_t*)dst1 + w - 3; - prev = (uint16_t*)prev1 + w - 3; - cur = (uint16_t*)cur1 + w - 3; - next = (uint16_t*)next1 + w - 3; + dst = (uint16_t*)dst1 + w - edge; + prev = (uint16_t*)prev1 + w - edge; + cur = (uint16_t*)cur1 + w - edge; + next = (uint16_t*)next1 + w - edge; prev2 = (uint16_t*)(parity ? prev : cur); next2 = (uint16_t*)(parity ? cur : next); + FILTER(w - edge, w - 3, 1) FILTER(w - 3, w, 0) } @@ -192,6 +201,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) int slice_start = jobnr * slice_h; int slice_end = (jobnr == nb_jobs - 1) ? td->h : (jobnr + 1) * slice_h; int y; + int edge = 3 + MAX_ALIGN / df - 1; /* filtering reads 3 pixels to the left/right; to avoid invalid reads, * we need to call the c variant which avoids this for border pixels @@ -204,7 +214,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) uint8_t *dst = &td->frame->data[td->plane][y * td->frame->linesize[td->plane]]; int mode = y == 1 || y + 2 == td->h ? 2 : s->mode; s->filter_line(dst + pix_3, prev + pix_3, cur + pix_3, - next + pix_3, td->w - 6, + next + pix_3, td->w - edge, y + 1 < td->h ? refs : -refs, y ? -refs : refs, td->parity ^ td->tff, mode); From 29ba1e60761fff569fb348fb776eec4ece05a07e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 24 Aug 2017 22:17:16 +0300 Subject: [PATCH 0372/2557] configure: Include d3d11va_extralibs in libavutil MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes shared WinRT/UWP builds with d3d11va enabled. Signed-off-by: Martin Storsjö --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 3e5784f851ded..6bbde1e743984 100755 --- a/configure +++ b/configure @@ -2575,7 +2575,7 @@ avdevice_extralibs="libm_extralibs" avformat_extralibs="libm_extralibs" avfilter_extralibs="pthreads_extralibs libm_extralibs" avresample_extralibs="libm_extralibs" -avutil_extralibs="clock_gettime_extralibs cuda_extralibs cuvid_extralibs libm_extralibs libmfx_extralibs nanosleep_extralibs pthreads_extralibs user32_extralibs vaapi_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs wincrypt_extralibs" +avutil_extralibs="clock_gettime_extralibs cuda_extralibs cuvid_extralibs d3d11va_extralibs libm_extralibs libmfx_extralibs nanosleep_extralibs pthreads_extralibs user32_extralibs vaapi_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs wincrypt_extralibs" swscale_extralibs="libm_extralibs" # programs From 5e3f6dc70198426fe0741e3017826b8bf3ee5ad8 Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Thu, 24 Aug 2017 21:04:13 +0100 Subject: [PATCH 0373/2557] swscale: Do not expand a macro with 'defined' in it Fixes: libswscale/utils.c:1632:5: warning: macro expansion producing 'defined' has undefined behavior [-Wexpansion-to-defined] #if USE_MMAP ^ libswscale/utils.c:1577:49: note: expanded from macro 'USE_MMAP' #define USE_MMAP (HAVE_MMAP && HAVE_MPROTECT && defined MAP_ANONYMOUS) ^ Signed-off-by: Derek Buitenhuis Signed-off-by: Luca Barbato --- libswscale/utils.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libswscale/utils.c b/libswscale/utils.c index 6b17955f5447d..786774f241618 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -1098,7 +1098,11 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, } } -#define USE_MMAP (HAVE_MMAP && HAVE_MPROTECT && defined MAP_ANONYMOUS) +#if HAVE_MMAP && HAVE_MPROTECT && defined(MAP_ANONYMOUS) +#define USE_MMAP 1 +#else +#define USE_MMAP 0 +#endif /* precalculate horizontal scaler filter coefficients */ { From 173b56218f39c6463be0e182259e2deead106936 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 17 Aug 2017 15:01:44 +0200 Subject: [PATCH 0374/2557] lavf: make avio_read_partial() public Main use-case is proxying avio through a foreign I/O layer and a custom AVIO context, without losing latency and performance characteristics. Signed-off-by: Luca Barbato --- doc/APIchanges | 3 +++ libavformat/avio.h | 9 +++++++++ libavformat/avio_internal.h | 8 -------- libavformat/aviobuf.c | 2 +- libavformat/rawdec.c | 2 +- libavformat/rtsp.c | 2 +- libavformat/version.h | 2 +- 7 files changed, 16 insertions(+), 12 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 463247f48ed80..ed90be890d22e 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2017-03-23 API changes, most recent first: +2016-xx-xx - xxxxxxx - lavf 58.1.0 - avio.h + Add avio_read_partial(). + 2017-xx-xx - xxxxxxx - lavu 56.4.0 - imgutils.h Add av_image_fill_black(). diff --git a/libavformat/avio.h b/libavformat/avio.h index e65135ed9988a..f604c4ad41828 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -331,6 +331,15 @@ void avio_flush(AVIOContext *s); */ int avio_read(AVIOContext *s, unsigned char *buf, int size); +/** + * Read size bytes from AVIOContext into buf. Unlike avio_read(), this is allowed + * to read fewer bytes than requested. The missing bytes can be read in the next + * call. This always tries to read at least 1 byte. + * Useful to reduce latency in certain cases. + * @return number of bytes read or AVERROR + */ +int avio_read_partial(AVIOContext *s, unsigned char *buf, int size); + /** * @name Functions for reading from AVIOContext * @{ diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h index 86164998676b6..dda1dad3dd8bd 100644 --- a/libavformat/avio_internal.h +++ b/libavformat/avio_internal.h @@ -53,14 +53,6 @@ int ffio_init_context(AVIOContext *s, */ int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsigned char **data); -/** - * Read size bytes from AVIOContext into buf. - * This reads at most 1 packet. If that is not enough fewer bytes will be - * returned. - * @return number of bytes read or AVERROR - */ -int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size); - void ffio_fill(AVIOContext *s, int b, int count); static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s) diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 31476d3f6d584..98e35f776c1b7 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -621,7 +621,7 @@ int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsig } } -int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size) +int avio_read_partial(AVIOContext *s, unsigned char *buf, int size) { int len; diff --git a/libavformat/rawdec.c b/libavformat/rawdec.c index 3b1bea642950f..a72a53d550e85 100644 --- a/libavformat/rawdec.c +++ b/libavformat/rawdec.c @@ -42,7 +42,7 @@ int ff_raw_read_partial_packet(AVFormatContext *s, AVPacket *pkt) pkt->pos= avio_tell(s->pb); pkt->stream_index = 0; - ret = ffio_read_partial(s->pb, pkt->data, size); + ret = avio_read_partial(s->pb, pkt->data, size); if (ret < 0) { av_packet_unref(pkt); return ret; diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index fb6203d585912..17a25a310ecd2 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -2077,7 +2077,7 @@ static int read_packet(AVFormatContext *s, wait_end && wait_end < av_gettime_relative()) len = AVERROR(EAGAIN); else - len = ffio_read_partial(s->pb, rt->recvbuf, RECVBUF_SIZE); + len = avio_read_partial(s->pb, rt->recvbuf, RECVBUF_SIZE); len = pick_stream(s, rtsp_st, rt->recvbuf, len); if (len > 0 && (*rtsp_st)->transport_priv && rt->transport == RTSP_TRANSPORT_RTP) ff_rtp_check_and_send_back_rr((*rtsp_st)->transport_priv, NULL, s->pb, len); diff --git a/libavformat/version.h b/libavformat/version.h index 7060375c1aa6c..28fb076a31bba 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 0 +#define LIBAVFORMAT_VERSION_MINOR 1 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From e41daa62465036ad36ad0bd14e4936e848d7f07e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 30 Aug 2017 22:04:30 +0300 Subject: [PATCH 0375/2557] Remove support for building for mingw32ce (Windows CE) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The toolchain for this target is unmaintained since many years. While it has been continuously build tested on fate, it hasn't actually been tested at runtime since many, many years (and back then, only a few codecs in libavcodec were tested). So far, keeping support for it has been mostly effortless, but the compiler does seem to have issues with dllimported data symbols, ending up as internal compiler errors in some cases. Instead of jumping through further hoops to work around that, just remove the target. Signed-off-by: Martin Storsjö --- configure | 8 +------- libavformat/os_support.h | 8 +++----- libavutil/file_open.c | 2 +- libavutil/wchar_filename.h | 2 +- tools/qt-faststart.c | 5 +---- 5 files changed, 7 insertions(+), 18 deletions(-) diff --git a/configure b/configure index 6bbde1e743984..b995235708cce 100755 --- a/configure +++ b/configure @@ -4021,16 +4021,10 @@ case $target_os in die "Native MSYS builds are discouraged, please use the MINGW environment." ;; mingw32*|mingw64*) - if test $target_os = "mingw32ce"; then - disable network - else - target_os=mingw32 - fi + target_os=mingw32 LIBTARGET=i386 if enabled x86_64; then LIBTARGET="i386:x86-64" - elif enabled arm; then - LIBTARGET=arm-wince fi check_ldflags -Wl,--nxcompat check_ldflags -Wl,--dynamicbase diff --git a/libavformat/os_support.h b/libavformat/os_support.h index 55c2fdb1f10fe..75a12960f3417 100644 --- a/libavformat/os_support.h +++ b/libavformat/os_support.h @@ -40,7 +40,7 @@ #endif #endif -#if defined(_WIN32) && !defined(__MINGW32CE__) +#ifdef _WIN32 # include # undef lseek # define lseek(f,p,w) _lseeki64((f), (p), (w)) @@ -48,7 +48,7 @@ # define stat _stati64 # undef fstat # define fstat(f,s) _fstati64((f), (s)) -#endif /* defined(_WIN32) && !defined(__MINGW32CE__) */ +#endif /* defined(_WIN32) */ static inline int is_dos_path(const char *path) { @@ -122,9 +122,7 @@ int ff_poll(struct pollfd *fds, nfds_t numfds, int timeout); #endif /* HAVE_POLL_H */ #endif /* CONFIG_NETWORK */ -#if defined(__MINGW32CE__) -#define mkdir(a, b) _mkdir(a) -#elif defined(_WIN32) +#ifdef _WIN32 #include #include #include "libavutil/wchar_filename.h" diff --git a/libavutil/file_open.c b/libavutil/file_open.c index f14ea70862366..dc666fe742897 100644 --- a/libavutil/file_open.c +++ b/libavutil/file_open.c @@ -29,7 +29,7 @@ #include #endif -#if defined(_WIN32) && !defined(__MINGW32CE__) +#ifdef _WIN32 #undef open #undef lseek #undef stat diff --git a/libavutil/wchar_filename.h b/libavutil/wchar_filename.h index 2781773deebe4..da1a0224ba2a7 100644 --- a/libavutil/wchar_filename.h +++ b/libavutil/wchar_filename.h @@ -19,7 +19,7 @@ #ifndef AVUTIL_WCHAR_FILENAME_H #define AVUTIL_WCHAR_FILENAME_H -#if defined(_WIN32) && !defined(__MINGW32CE__) +#ifdef _WIN32 #include #include "mem.h" diff --git a/tools/qt-faststart.c b/tools/qt-faststart.c index b798ccd4bf5c8..0db5ca21384c5 100644 --- a/tools/qt-faststart.c +++ b/tools/qt-faststart.c @@ -29,10 +29,7 @@ #include #include -#ifdef __MINGW32CE__ -#define fseeko(x, y, z) fseek(x, y, z) -#define ftello(x) ftell(x) -#elif defined(__MINGW32__) +#ifdef __MINGW32__ #undef fseeko #define fseeko(x, y, z) fseeko64(x, y, z) #undef ftello From abf1c058d1bd0ed1b820ea5e501a4484756f00b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 24 Aug 2017 22:07:04 +0300 Subject: [PATCH 0376/2557] msvc: Properly specify dllexport for data symbols shared across dll boundaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We currently only have exported data symbols within libavcodec, but the concept is easy to extend to other libraries if necessary. The attribute declaration needs to be in a private header though, since we can't use CONFIG_SHARED in public installed headers. Signed-off-by: Martin Storsjö --- avbuild/library.mak | 2 ++ libavcodec/ac3tab.h | 3 ++- libavcodec/dca.h | 4 ++-- libavcodec/internal.h | 10 ++++++++++ libavcodec/jpegtables.h | 16 ++++++++-------- libavcodec/mpeg4audio.h | 3 ++- libavcodec/mpegaudiodata.h | 6 +++--- libavutil/internal.h | 6 ------ 8 files changed, 29 insertions(+), 21 deletions(-) diff --git a/avbuild/library.mak b/avbuild/library.mak index 30757546fdd94..4e4b3f196d460 100644 --- a/avbuild/library.mak +++ b/avbuild/library.mak @@ -31,6 +31,8 @@ define RULES $(TOOLS): THISLIB = $(NAME:%=$(LD_LIB)) $(TESTPROGS): THISLIB = $(SUBDIR)$(LIBNAME) +$(LIBOBJS): CPPFLAGS += -DBUILDING_$(NAME) + $(TESTPROGS) $(TOOLS): %$(EXESUF): %.o $$(LD) $(LDFLAGS) $(LDEXEFLAGS) $$(LD_O) $$(filter %.o,$$^) $$(THISLIB) $(FFEXTRALIBS) $$(EXTRALIBS-$$(*F)) $$(ELIBS) diff --git a/libavcodec/ac3tab.h b/libavcodec/ac3tab.h index 83edec52d1c24..4c0122c39d2e1 100644 --- a/libavcodec/ac3tab.h +++ b/libavcodec/ac3tab.h @@ -26,6 +26,7 @@ #include "libavutil/internal.h" #include "ac3.h" +#include "internal.h" #if CONFIG_HARDCODED_TABLES # define HCONST const @@ -35,7 +36,7 @@ extern const uint16_t ff_ac3_frame_size_tab[38][3]; extern const uint8_t ff_ac3_channels_tab[8]; -extern av_export const uint16_t avpriv_ac3_channel_layout_tab[8]; +extern av_export_avcodec const uint16_t avpriv_ac3_channel_layout_tab[8]; extern const uint8_t ff_ac3_enc_channel_map[8][2][6]; extern const uint8_t ff_ac3_dec_channel_map[8][2][6]; extern const uint16_t ff_ac3_sample_rate_tab[3]; diff --git a/libavcodec/dca.h b/libavcodec/dca.h index 787a9c74deb9f..b2f5cbacf4304 100644 --- a/libavcodec/dca.h +++ b/libavcodec/dca.h @@ -28,12 +28,12 @@ #include #include "libavutil/float_dsp.h" -#include "libavutil/internal.h" #include "avcodec.h" #include "dcadsp.h" #include "fmtconvert.h" #include "get_bits.h" +#include "internal.h" #define DCA_PRIM_CHANNELS_MAX (7) #define DCA_ABITS_MAX (32) /* Should be 28 */ @@ -288,7 +288,7 @@ typedef struct DCAContext { FmtConvertContext fmt_conv; } DCAContext; -extern av_export const uint32_t avpriv_dca_sample_rates[16]; +extern av_export_avcodec const uint32_t avpriv_dca_sample_rates[16]; /** * Convert bitstream to one representation based on sync marker diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 403fb4a090bcc..0efe34f6674d5 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -285,4 +285,14 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame); */ AVCPBProperties *ff_add_cpb_side_data(AVCodecContext *avctx); +#if defined(_MSC_VER) && CONFIG_SHARED +#ifdef BUILDING_avcodec +# define av_export_avcodec __declspec(dllexport) +#else +# define av_export_avcodec __declspec(dllimport) +#endif +#else +# define av_export_avcodec +#endif + #endif /* AVCODEC_INTERNAL_H */ diff --git a/libavcodec/jpegtables.h b/libavcodec/jpegtables.h index 1a909bef7abde..44c2acabc4703 100644 --- a/libavcodec/jpegtables.h +++ b/libavcodec/jpegtables.h @@ -23,18 +23,18 @@ #include -#include "libavutil/internal.h" +#include "internal.h" -extern av_export const uint8_t avpriv_mjpeg_bits_dc_luminance[]; -extern av_export const uint8_t avpriv_mjpeg_val_dc[]; +extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_dc_luminance[]; +extern av_export_avcodec const uint8_t avpriv_mjpeg_val_dc[]; -extern av_export const uint8_t avpriv_mjpeg_bits_dc_chrominance[]; +extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_dc_chrominance[]; -extern av_export const uint8_t avpriv_mjpeg_bits_ac_luminance[]; -extern av_export const uint8_t avpriv_mjpeg_val_ac_luminance[]; +extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_ac_luminance[]; +extern av_export_avcodec const uint8_t avpriv_mjpeg_val_ac_luminance[]; -extern av_export const uint8_t avpriv_mjpeg_bits_ac_chrominance[]; -extern av_export const uint8_t avpriv_mjpeg_val_ac_chrominance[]; +extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_ac_chrominance[]; +extern av_export_avcodec const uint8_t avpriv_mjpeg_val_ac_chrominance[]; void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, const uint8_t *bits_table, diff --git a/libavcodec/mpeg4audio.h b/libavcodec/mpeg4audio.h index 01f30c6ca7097..0a0905888aec8 100644 --- a/libavcodec/mpeg4audio.h +++ b/libavcodec/mpeg4audio.h @@ -27,6 +27,7 @@ #include "libavutil/attributes.h" #include "get_bits.h" +#include "internal.h" #include "put_bits.h" typedef struct MPEG4AudioConfig { @@ -44,7 +45,7 @@ typedef struct MPEG4AudioConfig { int frame_length_short; } MPEG4AudioConfig; -extern av_export const int avpriv_mpeg4audio_sample_rates[16]; +extern av_export_avcodec const int avpriv_mpeg4audio_sample_rates[16]; extern const uint8_t ff_mpeg4audio_channels[8]; /** diff --git a/libavcodec/mpegaudiodata.h b/libavcodec/mpegaudiodata.h index 2b8ff6587fcc9..1609f48e433c8 100644 --- a/libavcodec/mpegaudiodata.h +++ b/libavcodec/mpegaudiodata.h @@ -29,13 +29,13 @@ #include -#include "libavutil/internal.h" +#include "internal.h" #define MODE_EXT_MS_STEREO 2 #define MODE_EXT_I_STEREO 1 -extern av_export const uint16_t avpriv_mpa_bitrate_tab[2][3][15]; -extern av_export const uint16_t avpriv_mpa_freq_tab[3]; +extern av_export_avcodec const uint16_t avpriv_mpa_bitrate_tab[2][3][15]; +extern av_export_avcodec const uint16_t avpriv_mpa_freq_tab[3]; extern const int ff_mpa_sblimit_table[5]; extern const int ff_mpa_quant_steps[17]; extern const int ff_mpa_quant_bits[17]; diff --git a/libavutil/internal.h b/libavutil/internal.h index 8a0076f985058..7071d2a587b18 100644 --- a/libavutil/internal.h +++ b/libavutil/internal.h @@ -57,12 +57,6 @@ #endif #endif -#if defined(_MSC_VER) && CONFIG_SHARED -# define av_export __declspec(dllimport) -#else -# define av_export -#endif - #if HAVE_PRAGMA_DEPRECATED # if defined(__ICL) # define FF_DISABLE_DEPRECATION_WARNINGS __pragma(warning(push)) __pragma(warning(disable:1478)) From 44aa9105c535471ca9e23796d7ca29b341f47636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 24 Aug 2017 23:04:38 +0300 Subject: [PATCH 0377/2557] makedef: Fold as much text transformations as possible into the initial dump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids redoing them for each expression in the list. Signed-off-by: Martin Storsjö --- compat/windows/makedef | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compat/windows/makedef b/compat/windows/makedef index fcaf108332c42..b3de99255c546 100755 --- a/compat/windows/makedef +++ b/compat/windows/makedef @@ -112,7 +112,10 @@ for line in $(cat ${vscript} | tr '\t' ' '); do ' done -dump=$(dumpbin -linkermember:1 ${libname}) +dump=$(dumpbin -linkermember:1 ${libname} | + sed -e '/public symbols/,$!d' -e '/^ \{1,\}Summary/,$d' -e "s/ \{1,\}${prefix}/ /" -e 's/ \{1,\}/ /g' | + tail -n +2 | + cut -d' ' -f3) rm ${libname} @@ -121,9 +124,6 @@ list="" for exp in ${regex}; do list="${list}"' '$(echo "${dump}" | - sed -e '/public symbols/,$!d' -e '/^ \{1,\}Summary/,$d' -e "s/ \{1,\}${prefix}/ /" -e 's/ \{1,\}/ /g' | - tail -n +2 | - cut -d' ' -f3 | grep "^${exp}" | sed -e 's/^/ /') done From 1a7bf48eed806beea7e835b31b06aa6bc94da5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 24 Aug 2017 23:05:21 +0300 Subject: [PATCH 0378/2557] makedef: Extend the script for use with mingw tools as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is invoked by setting the NM and AR variables to the names of those specific tools. The ARCH variable also needs to be provided, to choose the symbol prefix (nm doesn't provide any option that dumps the architecture easily). Signed-off-by: Martin Storsjö --- compat/windows/makedef | 55 ++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/compat/windows/makedef b/compat/windows/makedef index b3de99255c546..fd7959a745fff 100755 --- a/compat/windows/makedef +++ b/compat/windows/makedef @@ -45,7 +45,11 @@ libname=$(mktemp -u "library").lib trap 'rm -f -- $libname' EXIT -lib -out:${libname} $@ >/dev/null +if [ -n "$AR" ]; then + $AR rcs ${libname} $@ >/dev/null +else + lib -out:${libname} $@ >/dev/null +fi if [ $? != 0 ]; then echo "Could not create temporary library." >&2 exit 1 @@ -57,18 +61,28 @@ IFS=' # Determine if we're building for x86 or x86_64 and # set the symbol prefix accordingly. prefix="" -arch=$(dumpbin -headers ${libname} | - tr '\t' ' ' | - grep '^ \+.\+machine \+(.\+)' | - head -1 | - sed -e 's/^ \{1,\}.\{1,\} \{1,\}machine \{1,\}(\(...\)).*/\1/') - -if [ "${arch}" = "x86" ]; then - prefix="_" +if [ -n "$NM" ]; then + case $ARCH in + *86) + prefix="_" + ;; + *) + ;; + esac else - if [ "${arch}" != "ARM" ] && [ "${arch}" != "x64" ]; then - echo "Unknown machine type." >&2 - exit 1 + arch=$(dumpbin -headers ${libname} | + tr '\t' ' ' | + grep '^ \+.\+machine \+(.\+)' | + head -1 | + sed -e 's/^ \{1,\}.\{1,\} \{1,\}machine \{1,\}(\(...\)).*/\1/') + + if [ "${arch}" = "x86" ]; then + prefix="_" + else + if [ "${arch}" != "ARM" ] && [ "${arch}" != "x64" ]; then + echo "Unknown machine type." >&2 + exit 1 + fi fi fi @@ -112,10 +126,19 @@ for line in $(cat ${vscript} | tr '\t' ' '); do ' done -dump=$(dumpbin -linkermember:1 ${libname} | - sed -e '/public symbols/,$!d' -e '/^ \{1,\}Summary/,$d' -e "s/ \{1,\}${prefix}/ /" -e 's/ \{1,\}/ /g' | - tail -n +2 | - cut -d' ' -f3) +if [ -n "$NM" ]; then + # Use eval, since NM="nm -g" + dump=$(eval "$NM --defined-only -g ${libname}" | + grep -v : | + grep -v ^$ | + cut -d' ' -f3 | + sed -e "s/^${prefix}//") +else + dump=$(dumpbin -linkermember:1 ${libname} | + sed -e '/public symbols/,$!d' -e '/^ \{1,\}Summary/,$d' -e "s/ \{1,\}${prefix}/ /" -e 's/ \{1,\}/ /g' | + tail -n +2 | + cut -d' ' -f3) +fi rm ${libname} From accb06120c13a4ead442464d96f2fa318fa07a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 24 Aug 2017 23:27:16 +0300 Subject: [PATCH 0379/2557] configure: Use dllexport/dllimport for data symbols across DLLs with mingw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids having to use pseudo relocations. The version script used for exporting functions is skipped as soon as the set of object files contains symbols marked with dllexport, therefore we need to use makedef to produce the full list of symbols to be exported. Signed-off-by: Martin Storsjö --- configure | 11 +++++++++-- libavcodec/internal.h | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/configure b/configure index b995235708cce..c24cdd4f7e0be 100755 --- a/configure +++ b/configure @@ -4026,6 +4026,10 @@ case $target_os in if enabled x86_64; then LIBTARGET="i386:x86-64" fi + if enabled shared; then + # Cannot build both shared and static libs when using dllexport. + disable static + fi check_ldflags -Wl,--nxcompat check_ldflags -Wl,--dynamicbase shlibdir_default="$bindir_default" @@ -4033,12 +4037,13 @@ case $target_os in SLIBSUF=".dll" SLIBNAME_WITH_VERSION='$(SLIBPREF)$(NAME)-$(LIBVERSION)$(SLIBSUF)' SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(NAME)-$(LIBMAJOR)$(SLIBSUF)' - SLIB_EXTRA_CMD=-'sed -e "s/ @[^ ]*//" $$(@:$(SLIBSUF)=.orig.def) > $$(@:$(SLIBSUF)=.def); $(DLLTOOL) -m $(LIBTARGET) -d $$(@:$(SLIBSUF)=.def) -l $(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib) -D $(SLIBNAME_WITH_MAJOR)' + SLIB_EXTRA_CMD=-'$(DLLTOOL) -m $(LIBTARGET) -d $$(@:$(SLIBSUF)=.def) -l $(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib) -D $(SLIBNAME_WITH_MAJOR)' SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)' SLIB_INSTALL_LINKS= SLIB_INSTALL_EXTRA_SHLIB='$(SLIBNAME:$(SLIBSUF)=.lib)' SLIB_INSTALL_EXTRA_LIB='lib$(SLIBNAME:$(SLIBSUF)=.dll.a) $(SLIBNAME_WITH_MAJOR:$(SLIBSUF)=.def)' - SHFLAGS='-shared -Wl,--output-def,$$(@:$(SLIBSUF)=.orig.def) -Wl,--out-implib,$(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a) -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-auto-image-base' + SLIB_CREATE_DEF_CMD='ARCH="$(ARCH)" AR="$(AR_CMD)" NM="$(NM_CMD)" $(SRC_PATH)/compat/windows/makedef $(SUBDIR)lib$(NAME).ver $(OBJS) > $$(@:$(SLIBSUF)=.def)' + SHFLAGS='-shared -Wl,--out-implib,$(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a) -Wl,--enable-auto-image-base $$(@:$(SLIBSUF)=.def)' enabled x86_64 && objformat="win64" || objformat="win32" dlltool="${cross_prefix}dlltool" ranlib=: @@ -5432,6 +5437,8 @@ DEPX86ASMFLAGS=\$(X86ASMFLAGS) AR=$ar ARFLAGS=$arflags AR_O=$ar_o +AR_CMD=$ar +NM_CMD=$nm RANLIB=$ranlib STRIP=$strip LN_S=$ln_s diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 0efe34f6674d5..da1b2fa7d12a2 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -285,7 +285,7 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame); */ AVCPBProperties *ff_add_cpb_side_data(AVCodecContext *avctx); -#if defined(_MSC_VER) && CONFIG_SHARED +#if defined(_WIN32) && CONFIG_SHARED #ifdef BUILDING_avcodec # define av_export_avcodec __declspec(dllexport) #else From 39e16ee2289e4240a82597b97db5541bbbd2b996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 25 Aug 2017 09:42:15 +0300 Subject: [PATCH 0380/2557] Revert "fate: Skip the checkasm test if CONFIG_STATIC is disabled" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we use dllexport properly for shared libraries on windows, there's no longer any issue with linking the object files for e.g. libavcodec statically into checkasm. (It's still not possible to link the built object files for e.g. libavformat statically to libavcodec though, since libavformat exepcts to load av_export_* symbols from a DLL.) This reverts commit 4e62b57ee03928c12a3119dcaf78ffa1f4d6985f. Signed-off-by: Martin Storsjö --- tests/fate/checkasm.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index 5721f1f53c0d8..939eb567cda0a 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -19,5 +19,5 @@ $(FATE_CHECKASM): tests/checkasm/checkasm$(EXESUF) $(FATE_CHECKASM): CMD = run tests/checkasm/checkasm --test=$(@:fate-checkasm-%=%) $(FATE_CHECKASM): REF = /dev/null -FATE-$(CONFIG_STATIC) += $(FATE_CHECKASM) +FATE += $(FATE_CHECKASM) fate-checkasm: $(FATE_CHECKASM) From 547db1eaecd597031165a2bf637acaaacde52788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 29 Aug 2017 23:23:12 +0300 Subject: [PATCH 0381/2557] checkasm: Test more h264 idct variants --- tests/checkasm/h264dsp.c | 90 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/tests/checkasm/h264dsp.c b/tests/checkasm/h264dsp.c index c9ddd52a7fe61..8ce7c9332c3e6 100644 --- a/tests/checkasm/h264dsp.c +++ b/tests/checkasm/h264dsp.c @@ -22,6 +22,7 @@ #include "checkasm.h" #include "libavcodec/avcodec.h" #include "libavcodec/h264dsp.h" +#include "libavcodec/h264data.h" #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" @@ -223,10 +224,97 @@ static void check_idct(void) } } } - report("idct"); +} + +static void check_idct_multiple(void) +{ + LOCAL_ALIGNED_16(uint8_t, dst_full, [16 * 16 * 2]); + LOCAL_ALIGNED_16(int16_t, coef_full, [16 * 16 * 2]); + LOCAL_ALIGNED_16(uint8_t, dst0, [16 * 16 * 2]); + LOCAL_ALIGNED_16(uint8_t, dst1, [16 * 16 * 2]); + LOCAL_ALIGNED_16(int16_t, coef0, [16 * 16 * 2]); + LOCAL_ALIGNED_16(int16_t, coef1, [16 * 16 * 2]); + LOCAL_ALIGNED_16(uint8_t, nnzc, [15*8]); + H264DSPContext h; + int bit_depth, i, y, func; + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, const int *block_offset, int16_t *block, int stride, const uint8_t nnzc[15*8]); + + for (bit_depth = 8; bit_depth <= 10; bit_depth++) { + ff_h264dsp_init(&h, bit_depth, 1); + for (func = 0; func < 3; func++) { + void (*idct)(uint8_t *, const int *, int16_t *, int, const uint8_t[]) = NULL; + const char *name; + int sz = 4, intra = 0; + int block_offset[16] = { 0 }; + switch (func) { + case 0: + idct = h.h264_idct_add16; + name = "h264_idct_add16"; + break; + case 1: + idct = h.h264_idct_add16intra; + name = "h264_idct_add16intra"; + intra = 1; + break; + case 2: + idct = h.h264_idct8_add4; + name = "h264_idct8_add4"; + sz = 8; + break; + } + memset(nnzc, 0, 15 * 8); + memset(coef_full, 0, 16 * 16 * SIZEOF_COEF); + for (i = 0; i < 16 * 16; i += sz * sz) { + uint8_t src[8 * 8 * 2]; + uint8_t dst[8 * 8 * 2]; + int16_t coef[8 * 8 * 2]; + int index = i / sz; + int block_y = (index / 16) * sz; + int block_x = index % 16; + int offset = (block_y * 16 + block_x) * SIZEOF_PIXEL; + int nnz = rnd() % 3; + + randomize_buffers(); + if (sz == 4) + dct4x4(coef, bit_depth); + else + dct8x8(coef, bit_depth); + + for (y = 0; y < sz; y++) + memcpy(&dst_full[offset + y * 16 * SIZEOF_PIXEL], + &dst[PIXEL_STRIDE * y], sz * SIZEOF_PIXEL); + + if (nnz > 1) + nnz = sz*sz; + memcpy(&coef_full[i*SIZEOF_COEF/sizeof(coef[0])], + coef, nnz * SIZEOF_COEF); + + if (intra && nnz == 1) + nnz = 0; + + nnzc[scan8[i / 16]] = nnz; + block_offset[i / 16] = offset; + } + + if (check_func(idct, "%s_%dbpp", name, bit_depth)) { + memcpy(coef0, coef_full, 16 * 16 * SIZEOF_COEF); + memcpy(coef1, coef_full, 16 * 16 * SIZEOF_COEF); + memcpy(dst0, dst_full, 16 * 16 * SIZEOF_PIXEL); + memcpy(dst1, dst_full, 16 * 16 * SIZEOF_PIXEL); + call_ref(dst0, block_offset, coef0, 16 * SIZEOF_PIXEL, nnzc); + call_new(dst1, block_offset, coef1, 16 * SIZEOF_PIXEL, nnzc); + if (memcmp(dst0, dst1, 16 * 16 * SIZEOF_PIXEL) || + memcmp(coef0, coef1, 16 * 16 * SIZEOF_COEF)) + fail(); + bench_new(dst1, block_offset, coef1, 16 * SIZEOF_PIXEL, nnzc); + } + } + } } void checkasm_check_h264dsp(void) { check_idct(); + check_idct_multiple(); + report("idct"); } From 9dde6ab06c48f9447cd16f39bee33569cddb7be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 31 Aug 2017 12:06:44 +0300 Subject: [PATCH 0382/2557] arm: Fix SIGBUS on ARM when compiled with binutils 2.29 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In binutils 2.29, the behavior of the ADR instruction changed so that 1 is added to the address of a Thumb function (previously nothing was added). This allows the loaded address to be passed to a BLX instruction and the correct mode change will occur. See: https://sourceware.org/bugzilla/show_bug.cgi?id=21458 By using adr with a label that isn't annotated as a thumb function, we avoid the new behaviour in binutils 2.29 and get the same behaviour as in prior releases, and as in other assemblers (ms armasm.exe, clang's built in assembler) - an idea that Janne Grunau came up with. Signed-off-by: Martin Storsjö --- libavcodec/arm/h264idct_neon.S | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/libavcodec/arm/h264idct_neon.S b/libavcodec/arm/h264idct_neon.S index f588f3e74499b..b078cf25f92ff 100644 --- a/libavcodec/arm/h264idct_neon.S +++ b/libavcodec/arm/h264idct_neon.S @@ -21,6 +21,7 @@ #include "libavutil/arm/asm.S" function ff_h264_idct_add_neon, export=1 +h264_idct_add_neon_nothumb: vld1.64 {d0-d3}, [r1,:128] vmov.i16 q15, #0 @@ -73,6 +74,7 @@ function ff_h264_idct_add_neon, export=1 endfunc function ff_h264_idct_dc_add_neon, export=1 +h264_idct_dc_add_neon_nothumb: mov r3, #0 vld1.16 {d2[],d3[]}, [r1,:16] strh r3, [r1] @@ -113,8 +115,8 @@ function ff_h264_idct_add16_neon, export=1 movne lr, #0 cmp lr, #0 ite ne - adrne lr, X(ff_h264_idct_dc_add_neon) + CONFIG_THUMB - adreq lr, X(ff_h264_idct_add_neon) + CONFIG_THUMB + adrne lr, h264_idct_dc_add_neon_nothumb + CONFIG_THUMB + adreq lr, h264_idct_add_neon_nothumb + CONFIG_THUMB blx lr 2: subs ip, ip, #1 add r1, r1, #32 @@ -138,8 +140,8 @@ function ff_h264_idct_add16intra_neon, export=1 cmp r8, #0 ldrsh r8, [r1] iteet ne - adrne lr, X(ff_h264_idct_add_neon) + CONFIG_THUMB - adreq lr, X(ff_h264_idct_dc_add_neon) + CONFIG_THUMB + adrne lr, h264_idct_add_neon_nothumb + CONFIG_THUMB + adreq lr, h264_idct_dc_add_neon_nothumb + CONFIG_THUMB cmpeq r8, #0 blxne lr subs ip, ip, #1 @@ -166,8 +168,8 @@ function ff_h264_idct_add8_neon, export=1 cmp r8, #0 ldrsh r8, [r1] iteet ne - adrne lr, X(ff_h264_idct_add_neon) + CONFIG_THUMB - adreq lr, X(ff_h264_idct_dc_add_neon) + CONFIG_THUMB + adrne lr, h264_idct_add_neon_nothumb + CONFIG_THUMB + adreq lr, h264_idct_dc_add_neon_nothumb + CONFIG_THUMB cmpeq r8, #0 blxne lr add r12, r12, #1 @@ -267,6 +269,7 @@ endfunc .endm function ff_h264_idct8_add_neon, export=1 +h264_idct8_add_neon_nothumb: vmov.i16 q3, #0 vld1.16 {q8-q9}, [r1,:128] vst1.16 {q3}, [r1,:128]! @@ -328,6 +331,7 @@ function ff_h264_idct8_add_neon, export=1 endfunc function ff_h264_idct8_dc_add_neon, export=1 +h264_idct8_dc_add_neon_nothumb: mov r3, #0 vld1.16 {d30[],d31[]},[r1,:16] strh r3, [r1] @@ -388,8 +392,8 @@ function ff_h264_idct8_add4_neon, export=1 movne lr, #0 cmp lr, #0 ite ne - adrne lr, X(ff_h264_idct8_dc_add_neon) + CONFIG_THUMB - adreq lr, X(ff_h264_idct8_add_neon) + CONFIG_THUMB + adrne lr, h264_idct8_dc_add_neon_nothumb + CONFIG_THUMB + adreq lr, h264_idct8_add_neon_nothumb + CONFIG_THUMB blx lr 2: subs r12, r12, #4 add r1, r1, #128 From e12f1cd616573795681ce939113ac6cdad4c1f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 2 Sep 2017 22:22:59 +0300 Subject: [PATCH 0383/2557] Revert "checkasm: Test more h264 idct variants" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 547db1eaecd597031165a2bf637acaaacde52788. This commit wasn't supposed to be pushed (yet) since it hasn't been reviewed. Signed-off-by: Martin Storsjö --- tests/checkasm/h264dsp.c | 90 +--------------------------------------- 1 file changed, 1 insertion(+), 89 deletions(-) diff --git a/tests/checkasm/h264dsp.c b/tests/checkasm/h264dsp.c index 8ce7c9332c3e6..c9ddd52a7fe61 100644 --- a/tests/checkasm/h264dsp.c +++ b/tests/checkasm/h264dsp.c @@ -22,7 +22,6 @@ #include "checkasm.h" #include "libavcodec/avcodec.h" #include "libavcodec/h264dsp.h" -#include "libavcodec/h264data.h" #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" @@ -224,97 +223,10 @@ static void check_idct(void) } } } -} - -static void check_idct_multiple(void) -{ - LOCAL_ALIGNED_16(uint8_t, dst_full, [16 * 16 * 2]); - LOCAL_ALIGNED_16(int16_t, coef_full, [16 * 16 * 2]); - LOCAL_ALIGNED_16(uint8_t, dst0, [16 * 16 * 2]); - LOCAL_ALIGNED_16(uint8_t, dst1, [16 * 16 * 2]); - LOCAL_ALIGNED_16(int16_t, coef0, [16 * 16 * 2]); - LOCAL_ALIGNED_16(int16_t, coef1, [16 * 16 * 2]); - LOCAL_ALIGNED_16(uint8_t, nnzc, [15*8]); - H264DSPContext h; - int bit_depth, i, y, func; - declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, const int *block_offset, int16_t *block, int stride, const uint8_t nnzc[15*8]); - - for (bit_depth = 8; bit_depth <= 10; bit_depth++) { - ff_h264dsp_init(&h, bit_depth, 1); - for (func = 0; func < 3; func++) { - void (*idct)(uint8_t *, const int *, int16_t *, int, const uint8_t[]) = NULL; - const char *name; - int sz = 4, intra = 0; - int block_offset[16] = { 0 }; - switch (func) { - case 0: - idct = h.h264_idct_add16; - name = "h264_idct_add16"; - break; - case 1: - idct = h.h264_idct_add16intra; - name = "h264_idct_add16intra"; - intra = 1; - break; - case 2: - idct = h.h264_idct8_add4; - name = "h264_idct8_add4"; - sz = 8; - break; - } - memset(nnzc, 0, 15 * 8); - memset(coef_full, 0, 16 * 16 * SIZEOF_COEF); - for (i = 0; i < 16 * 16; i += sz * sz) { - uint8_t src[8 * 8 * 2]; - uint8_t dst[8 * 8 * 2]; - int16_t coef[8 * 8 * 2]; - int index = i / sz; - int block_y = (index / 16) * sz; - int block_x = index % 16; - int offset = (block_y * 16 + block_x) * SIZEOF_PIXEL; - int nnz = rnd() % 3; - - randomize_buffers(); - if (sz == 4) - dct4x4(coef, bit_depth); - else - dct8x8(coef, bit_depth); - - for (y = 0; y < sz; y++) - memcpy(&dst_full[offset + y * 16 * SIZEOF_PIXEL], - &dst[PIXEL_STRIDE * y], sz * SIZEOF_PIXEL); - - if (nnz > 1) - nnz = sz*sz; - memcpy(&coef_full[i*SIZEOF_COEF/sizeof(coef[0])], - coef, nnz * SIZEOF_COEF); - - if (intra && nnz == 1) - nnz = 0; - - nnzc[scan8[i / 16]] = nnz; - block_offset[i / 16] = offset; - } - - if (check_func(idct, "%s_%dbpp", name, bit_depth)) { - memcpy(coef0, coef_full, 16 * 16 * SIZEOF_COEF); - memcpy(coef1, coef_full, 16 * 16 * SIZEOF_COEF); - memcpy(dst0, dst_full, 16 * 16 * SIZEOF_PIXEL); - memcpy(dst1, dst_full, 16 * 16 * SIZEOF_PIXEL); - call_ref(dst0, block_offset, coef0, 16 * SIZEOF_PIXEL, nnzc); - call_new(dst1, block_offset, coef1, 16 * SIZEOF_PIXEL, nnzc); - if (memcmp(dst0, dst1, 16 * 16 * SIZEOF_PIXEL) || - memcmp(coef0, coef1, 16 * 16 * SIZEOF_COEF)) - fail(); - bench_new(dst1, block_offset, coef1, 16 * SIZEOF_PIXEL, nnzc); - } - } - } + report("idct"); } void checkasm_check_h264dsp(void) { check_idct(); - check_idct_multiple(); - report("idct"); } From 585dc1aecef0371ad6f16cb3750ae2a6da9cf00a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 2 Sep 2017 23:20:26 +0300 Subject: [PATCH 0384/2557] flvdec: Check the avio_seek return value after reading a metadata packet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the metadata packet is corrupted, flv_read_metabody can accidentally read past the start of the next packet. If the start of the next packet had been flushed out of the IO buffer, we would be unable to seek to the right position (on a nonseekable stream). Prefer to clearly error out instead of silently trying to read from a desynced stream which will only be interpreted as garbage. Signed-off-by: Martin Storsjö --- libavformat/flvdec.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 1b29740f41b11..81a71d39f4cb9 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -801,7 +801,13 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) type, size, flags); skip: - avio_seek(s->pb, next, SEEK_SET); + if (avio_seek(s->pb, next, SEEK_SET) != next) { + // This can happen if flv_read_metabody above read past + // next, on a non-seekable input, and the preceding data has + // been flushed out from the IO buffer. + av_log(s, AV_LOG_ERROR, "Unable to seek to the next packet\n"); + return AVERROR_INVALIDDATA; + } continue; } From f19fbfbdc637e08ad5c980807ede2d023f20c049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sun, 3 Sep 2017 00:02:54 +0300 Subject: [PATCH 0385/2557] aviocat: Check for output write errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- tools/aviocat.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/aviocat.c b/tools/aviocat.c index 3e49a61801555..73104da174970 100644 --- a/tools/aviocat.c +++ b/tools/aviocat.c @@ -107,6 +107,11 @@ int main(int argc, char **argv) if (n <= 0) break; avio_write(output, buf, n); + if (output->error) { + av_strerror(output->error, errbuf, sizeof(errbuf)); + fprintf(stderr, "Unable to write %s: %s\n", output_url, errbuf); + break; + } stream_pos += n; if (bps) { avio_flush(output); From b05128f3c953bd66483e697d60a2e7e45ee9cfa0 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Wed, 6 Sep 2017 13:07:40 +0000 Subject: [PATCH 0386/2557] qsv: Load the hw hevc plugin by default on Linux Only on Windows the software plugin is available. Signed-off-by: Luca Barbato --- libavcodec/qsvenc_hevc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index 27ff0c6feb7df..efed4d98f4631 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -209,12 +209,18 @@ static av_cold int qsv_enc_close(AVCodecContext *avctx) return ff_qsv_enc_close(avctx, &q->qsv); } +#if defined(_WIN32) +#define LOAD_PLUGIN_DEFAULT LOAD_PLUGIN_HEVC_SW +#else +#define LOAD_PLUGIN_DEFAULT LOAD_PLUGIN_HEVC_HW +#endif + #define OFFSET(x) offsetof(QSVHEVCEncContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { QSV_COMMON_OPTS - { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_HEVC_SW }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VE, "load_plugin" }, + { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_DEFAULT }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VE, "load_plugin" }, { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VE, "load_plugin" }, { "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VE, "load_plugin" }, { "hevc_hw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_HW }, 0, 0, VE, "load_plugin" }, From 44cde38c8acbef7d5250e6d1b52b1020871e093b Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 12 Sep 2017 22:11:41 +0100 Subject: [PATCH 0387/2557] cbs: Always check for bitstream end before reading --- libavcodec/cbs.c | 6 +++ libavcodec/cbs_h2645.c | 118 ++++++++++++++++++++--------------------- libavcodec/cbs_mpeg2.c | 5 +- 3 files changed, 67 insertions(+), 62 deletions(-) diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index 10943164da141..7440914939f6a 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -313,6 +313,12 @@ int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, BitstreamContext *bc, av_assert0(width <= 32); + if (bitstream_bits_left(bc) < width) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at " + "%s: bitstream ended.\n", name); + return AVERROR_INVALIDDATA; + } + if (ctx->trace_enable) position = bitstream_tell(bc); diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 4d8ba99b35331..c8a13f16796a2 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -36,40 +36,39 @@ static int cbs_read_ue_golomb(CodedBitstreamContext *ctx, BitstreamContext *bc, uint32_t range_min, uint32_t range_max) { uint32_t value; - int position; + int position, i, j; + unsigned int k; + char bits[65]; - if (ctx->trace_enable) { - char bits[65]; - unsigned int k; - int i, j; + position = bitstream_tell(bc); - position = bitstream_tell(bc); - - for (i = 0; i < 32; i++) { - k = bitstream_read_bit(bc); - bits[i] = k ? '1' : '0'; - if (k) - break; - } - if (i >= 32) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid ue-golomb " - "code found while reading %s: " - "more than 31 zeroes.\n", name); + for (i = 0; i < 32; i++) { + if (bitstream_bits_left(bc) < i + 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid ue-golomb code at " + "%s: bitstream ended.\n", name); return AVERROR_INVALIDDATA; } - value = 1; - for (j = 0; j < i; j++) { - k = bitstream_read_bit(bc); - bits[i + j + 1] = k ? '1' : '0'; - value = value << 1 | k; - } - bits[i + j + 1] = 0; - --value; + k = bitstream_read_bit(bc); + bits[i] = k ? '1' : '0'; + if (k) + break; + } + if (i >= 32) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid ue-golomb code at " + "%s: more than 31 zeroes.\n", name); + return AVERROR_INVALIDDATA; + } + value = 1; + for (j = 0; j < i; j++) { + k = bitstream_read_bit(bc); + bits[i + j + 1] = k ? '1' : '0'; + value = value << 1 | k; + } + bits[i + j + 1] = 0; + --value; + if (ctx->trace_enable) ff_cbs_trace_syntax_element(ctx, position, name, bits, value); - } else { - value = get_ue_golomb_long(bc); - } if (value < range_min || value > range_max) { av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " @@ -87,44 +86,43 @@ static int cbs_read_se_golomb(CodedBitstreamContext *ctx, BitstreamContext *bc, int32_t range_min, int32_t range_max) { int32_t value; - int position; + int position, i, j; + unsigned int k; + uint32_t v; + char bits[65]; - if (ctx->trace_enable) { - char bits[65]; - uint32_t v; - unsigned int k; - int i, j; - - position = bitstream_tell(bc); + position = bitstream_tell(bc); - for (i = 0; i < 32; i++) { - k = bitstream_read_bit(bc); - bits[i] = k ? '1' : '0'; - if (k) - break; - } - if (i >= 32) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid se-golomb " - "code found while reading %s: " - "more than 31 zeroes.\n", name); + for (i = 0; i < 32; i++) { + if (bitstream_bits_left(bc) < i + 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid se-golomb code at " + "%s: bitstream ended.\n", name); return AVERROR_INVALIDDATA; } - v = 1; - for (j = 0; j < i; j++) { - k = bitstream_read_bit(bc); - bits[i + j + 1] = k ? '1' : '0'; - v = v << 1 | k; - } - bits[i + j + 1] = 0; - if (v & 1) - value = -(int32_t)(v / 2); - else - value = v / 2; + k = bitstream_read_bit(bc); + bits[i] = k ? '1' : '0'; + if (k) + break; + } + if (i >= 32) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid se-golomb code at " + "%s: more than 31 zeroes.\n", name); + return AVERROR_INVALIDDATA; + } + v = 1; + for (j = 0; j < i; j++) { + k = bitstream_read_bit(bc); + bits[i + j + 1] = k ? '1' : '0'; + v = v << 1 | k; + } + bits[i + j + 1] = 0; + if (v & 1) + value = -(int32_t)(v / 2); + else + value = v / 2; + if (ctx->trace_enable) ff_cbs_trace_syntax_element(ctx, position, name, bits, value); - } else { - value = get_se_golomb_long(bc); - } if (value < range_min || value > range_max) { av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index fede3ff471bbd..cbee42e905816 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -58,8 +58,9 @@ CHECK(ff_cbs_read_unsigned(ctx, rw, 1, "marker_bit", &one, 1, 1)); \ } while (0) -#define nextbits(width, compare, var) (var = bitstream_peek(rw, width), \ - var == (compare)) +#define nextbits(width, compare, var) \ + (bitstream_bits_left(rw) >= width && \ + (var = bitstream_peek(rw, width)) == (compare)) #include "cbs_mpeg2_syntax_template.c" From e7f64191b27bcf37cbf7006606f0f439c6cdc24f Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 12 Sep 2017 22:11:47 +0100 Subject: [PATCH 0388/2557] cbs: Add buffer padding when splitting fragments Remove any trailing zeroes from H.26[45] NAL units at the same time. --- libavcodec/cbs_h2645.c | 11 +++++++++-- libavcodec/cbs_mpeg2.c | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index c8a13f16796a2..50a227da787e9 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -479,12 +479,19 @@ static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx, for (i = 0; i < packet->nb_nals; i++) { const H2645NAL *nal = &packet->nals[i]; + size_t size = nal->size; uint8_t *data; - data = av_malloc(nal->size); + // Remove trailing zeroes. + while (size > 0 && nal->data[size - 1] == 0) + --size; + av_assert0(size > 0); + + data = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!data) return AVERROR(ENOMEM); - memcpy(data, nal->data, nal->size); + memcpy(data, nal->data, size); + memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); err = ff_cbs_insert_unit_data(ctx, frag, -1, nal->type, data, nal->size); diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index cbee42e905816..3c09377df3f0e 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -131,10 +131,11 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, unit_size = (end - 4) - (start - 1); } - unit_data = av_malloc(unit_size); + unit_data = av_malloc(unit_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!unit_data) return AVERROR(ENOMEM); memcpy(unit_data, start - 1, unit_size); + memset(unit_data + unit_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); err = ff_cbs_insert_unit_data(ctx, frag, i, unit_type, unit_data, unit_size); From c42b62d1f9641f10ffc23cad9abbe47d8a4a165b Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 20 Aug 2017 22:46:17 +0100 Subject: [PATCH 0389/2557] h264_metadata: Fix double-free Whether the udu string should be freed depends on whether the SEI it gets added to was created internally by cbs or externally by the bsf. The current code frees it twice in the former case. --- libavcodec/h264_metadata_bsf.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 9bf96b397d678..1afa5014b37ef 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -293,7 +293,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) H264RawSEI *sei; H264RawSEIPayload *payload; H264RawSEIUserDataUnregistered *udu; - int sei_pos; + int sei_pos, sei_new; for (i = 0; i < au->nb_units; i++) { if (au->units[i].type == H264_NAL_SEI || @@ -305,8 +305,10 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) if (sei_pos < au->nb_units && au->units[sei_pos].type == H264_NAL_SEI) { + sei_new = 0; sei = au->units[sei_pos].content; } else { + sei_new = 1; sei = &ctx->sei_nal; memset(sei, 0, sizeof(*sei)); @@ -354,6 +356,12 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) payload->payload_size = 16 + udu->data_length; + if (!sei_new) { + // This will be freed by the existing internal + // reference in fragment_uninit(). + sei_udu_string = NULL; + } + } else { invalid_user_data: av_log(bsf, AV_LOG_ERROR, "Invalid user data: " From f940c859c23ae201b0170cf541ea8f6b7a52dd49 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 12 Sep 2017 22:11:52 +0100 Subject: [PATCH 0390/2557] Revert "vaapi_h265: Reduce the amount of padding in the stream" This reverts commit a14a12ca137bf1526452b97bedfc9f7b301d4e04. The CTU size is always 32x32; the surface size is what actually sets the desired property, and it is already correct. --- libavcodec/vaapi_encode_h265.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 165b6ffde4934..477065e2cee61 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -815,11 +815,8 @@ static av_cold int vaapi_encode_h265_configure(AVCodecContext *avctx) if (err < 0) return err; - // This is an Intel driver constraint. Despite MinCbSizeY being 8, - // we are still required to encode at 16-pixel alignment and then - // crop back (so 1080 lines is still encoded as 1088 + cropping). - priv->ctu_width = FFALIGN(ctx->surface_width, 16) / 16; - priv->ctu_height = FFALIGN(ctx->surface_height, 16) / 16; + priv->ctu_width = FFALIGN(ctx->surface_width, 32) / 32; + priv->ctu_height = FFALIGN(ctx->surface_height, 32) / 32; av_log(avctx, AV_LOG_VERBOSE, "Input %ux%u -> Surface %ux%u -> CTU %ux%u.\n", avctx->width, avctx->height, ctx->surface_width, From 30645174e333c7db1946ab09be769db9be9d7481 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 9 Sep 2017 22:49:14 +0100 Subject: [PATCH 0391/2557] vaapi_h264: Fix CPB/DPB delays This should be ticks, not time_scale steps - it was wrong for all framerates not a multiple of 1/2. --- libavcodec/vaapi_encode_h264.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 271644ebbeebc..1288249be7a87 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -612,10 +612,8 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, if (opt->sei & SEI_TIMING) { memset(&priv->pic_timing, 0, sizeof(priv->pic_timing)); - priv->pic_timing.cpb_removal_delay = - 2 * sps->vui.num_units_in_tick * priv->cpb_delay; - priv->pic_timing.dpb_output_delay = - 2 * sps->vui.num_units_in_tick * priv->dpb_delay; + priv->pic_timing.cpb_removal_delay = 2 * priv->cpb_delay; + priv->pic_timing.dpb_output_delay = 2 * priv->dpb_delay; priv->sei_needed = 1; } From f763489364416bb6866adc4f4a96012dd2ca1bd0 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 28 Aug 2017 17:06:14 +0100 Subject: [PATCH 0392/2557] cbs_h265: Fix reading of unknown parameter set extension data --- libavcodec/cbs_h265_syntax_template.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/cbs_h265_syntax_template.c b/libavcodec/cbs_h265_syntax_template.c index 40fdaf8a900b0..8564220d5304c 100644 --- a/libavcodec/cbs_h265_syntax_template.c +++ b/libavcodec/cbs_h265_syntax_template.c @@ -67,7 +67,8 @@ static int FUNC(extension_data)(CodedBitstreamContext *ctx, RWContext *rw, BitstreamContext start; uint8_t bit; start = *rw; - for (k = 0; cbs_h2645_read_more_rbsp_data(rw); k++); + for (k = 0; cbs_h2645_read_more_rbsp_data(rw); k++) + bitstream_skip(rw, 1); current->bit_length = k; if (k > 0) { *rw = start; From 067a9ddeb8feff1f724856f0054930c55219f76b Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 28 Aug 2017 17:07:01 +0100 Subject: [PATCH 0393/2557] cbs_h265: Fix ranges of prediction weight offsets The bracketing was wrong - '-' binds before '<<'. This would previously incorrectly reject the streams in the WP_A and WP_B conformance tests. --- libavcodec/cbs_h265_syntax_template.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavcodec/cbs_h265_syntax_template.c b/libavcodec/cbs_h265_syntax_template.c index 8564220d5304c..a194887d769f0 100644 --- a/libavcodec/cbs_h265_syntax_template.c +++ b/libavcodec/cbs_h265_syntax_template.c @@ -1133,7 +1133,7 @@ static int FUNC(pred_weight_table)(CodedBitstreamContext *ctx, RWContext *rw, se(delta_luma_weight_l0[i], -128, +127); se(luma_offset_l0[i], -(1 << (sps->bit_depth_luma_minus8 + 8 - 1)), - +(1 << (sps->bit_depth_luma_minus8 + 8 - 1) - 1)); + ((1 << (sps->bit_depth_luma_minus8 + 8 - 1)) - 1)); } else { infer(delta_luma_weight_l0[i], 0); infer(luma_offset_l0[i], 0); @@ -1143,7 +1143,7 @@ static int FUNC(pred_weight_table)(CodedBitstreamContext *ctx, RWContext *rw, se(delta_chroma_weight_l0[i][j], -128, +127); se(chroma_offset_l0[i][j], -(4 << (sps->bit_depth_chroma_minus8 + 8 - 1)), - +(4 << (sps->bit_depth_chroma_minus8 + 8 - 1) - 1)); + ((4 << (sps->bit_depth_chroma_minus8 + 8 - 1)) - 1)); } } else { for (j = 0; j < 2; j++) { @@ -1173,8 +1173,8 @@ static int FUNC(pred_weight_table)(CodedBitstreamContext *ctx, RWContext *rw, if (current->luma_weight_l1_flag[i]) { se(delta_luma_weight_l1[i], -128, +127); se(luma_offset_l1[i], - - 1 << (sps->bit_depth_luma_minus8 + 8 - 1), - + 1 << (sps->bit_depth_luma_minus8 + 8 - 1) - 1); + -(1 << (sps->bit_depth_luma_minus8 + 8 - 1)), + ((1 << (sps->bit_depth_luma_minus8 + 8 - 1)) - 1)); } else { infer(delta_luma_weight_l1[i], 0); infer(luma_offset_l1[i], 0); @@ -1183,8 +1183,8 @@ static int FUNC(pred_weight_table)(CodedBitstreamContext *ctx, RWContext *rw, for (j = 0; j < 2; j++) { se(delta_chroma_weight_l1[i][j], -128, +127); se(chroma_offset_l1[i][j], - - 4 << (sps->bit_depth_chroma_minus8 + 8 - 1), - + 4 << (sps->bit_depth_chroma_minus8 + 8 - 1) - 1); + -(4 << (sps->bit_depth_chroma_minus8 + 8 - 1)), + ((4 << (sps->bit_depth_chroma_minus8 + 8 - 1)) - 1)); } } else { for (j = 0; j < 2; j++) { From a41b69b5eb950c10d8ede472bcc4e88ce4246db9 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 9 Sep 2017 23:30:32 +0100 Subject: [PATCH 0394/2557] cbs_mpeg2: Add support for picture display extension --- libavcodec/cbs_mpeg2.h | 8 +++++ libavcodec/cbs_mpeg2_syntax_template.c | 44 ++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/libavcodec/cbs_mpeg2.h b/libavcodec/cbs_mpeg2.h index 32c4d4e2b10a9..0b6cb998dcd01 100644 --- a/libavcodec/cbs_mpeg2.h +++ b/libavcodec/cbs_mpeg2.h @@ -160,6 +160,11 @@ typedef struct MPEG2RawQuantMatrixExtension { uint8_t chroma_non_intra_quantiser_matrix[64]; } MPEG2RawQuantMatrixExtension; +typedef struct MPEG2RawPictureDisplayExtension { + uint16_t frame_centre_horizontal_offset[3]; + uint16_t frame_centre_vertical_offset[3]; +} MPEG2RawPictureDisplayExtension; + typedef struct MPEG2RawExtensionData { uint8_t extension_start_code; uint8_t extension_start_code_identifier; @@ -169,6 +174,7 @@ typedef struct MPEG2RawExtensionData { MPEG2RawSequenceDisplayExtension sequence_display; MPEG2RawQuantMatrixExtension quant_matrix; MPEG2RawPictureCodingExtension picture_coding; + MPEG2RawPictureDisplayExtension picture_display; } data; } MPEG2RawExtensionData; @@ -206,6 +212,8 @@ typedef struct CodedBitstreamMPEG2Context { uint16_t vertical_size; uint8_t scalable; uint8_t scalable_mode; + uint8_t progressive_sequence; + uint8_t number_of_frame_centre_offsets; // Write buffer. uint8_t *write_buffer; diff --git a/libavcodec/cbs_mpeg2_syntax_template.c b/libavcodec/cbs_mpeg2_syntax_template.c index b6dd42d2eebee..4aa1eb3c062c2 100644 --- a/libavcodec/cbs_mpeg2_syntax_template.c +++ b/libavcodec/cbs_mpeg2_syntax_template.c @@ -101,6 +101,7 @@ static int FUNC(sequence_extension)(CodedBitstreamContext *ctx, RWContext *rw, current->horizontal_size_extension << 12; mpeg2->vertical_size = (mpeg2->vertical_size & 0xfff) | current->vertical_size_extension << 12; + mpeg2->progressive_sequence = current->progressive_sequence; ui(12, bit_rate_extension); marker_bit(); @@ -183,6 +184,7 @@ static int FUNC(picture_header)(CodedBitstreamContext *ctx, RWContext *rw, static int FUNC(picture_coding_extension)(CodedBitstreamContext *ctx, RWContext *rw, MPEG2RawPictureCodingExtension *current) { + CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; int err; HEADER("Picture Coding Extension"); @@ -204,6 +206,27 @@ static int FUNC(picture_coding_extension)(CodedBitstreamContext *ctx, RWContext ui(1, chroma_420_type); ui(1, progressive_frame); + if (mpeg2->progressive_sequence) { + if (current->repeat_first_field) { + if (current->top_field_first) + mpeg2->number_of_frame_centre_offsets = 3; + else + mpeg2->number_of_frame_centre_offsets = 2; + } else { + mpeg2->number_of_frame_centre_offsets = 1; + } + } else { + if (current->picture_structure == 1 || // Top field. + current->picture_structure == 2) { // Bottom field. + mpeg2->number_of_frame_centre_offsets = 1; + } else { + if (current->repeat_first_field) + mpeg2->number_of_frame_centre_offsets = 3; + else + mpeg2->number_of_frame_centre_offsets = 2; + } + } + ui(1, composite_display_flag); if (current->composite_display_flag) { ui(1, v_axis); @@ -250,6 +273,24 @@ static int FUNC(quant_matrix_extension)(CodedBitstreamContext *ctx, RWContext *r return 0; } +static int FUNC(picture_display_extension)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawPictureDisplayExtension *current) +{ + CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; + int err, i; + + HEADER("Picture Display Extension"); + + for (i = 0; i < mpeg2->number_of_frame_centre_offsets; i++) { + ui(16, frame_centre_horizontal_offset[i]); + marker_bit(); + ui(16, frame_centre_vertical_offset[i]); + marker_bit(); + } + + return 0; +} + static int FUNC(extension_data)(CodedBitstreamContext *ctx, RWContext *rw, MPEG2RawExtensionData *current) { @@ -270,6 +311,9 @@ static int FUNC(extension_data)(CodedBitstreamContext *ctx, RWContext *rw, case 3: return FUNC(quant_matrix_extension) (ctx, rw, ¤t->data.quant_matrix); + case 7: + return FUNC(picture_display_extension) + (ctx, rw, ¤t->data.picture_display); case 8: return FUNC(picture_coding_extension) (ctx, rw, ¤t->data.picture_coding); From b5859e0b04bdbe12c97cb12ac10a45d51d2d73c9 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 12 Sep 2017 22:11:56 +0100 Subject: [PATCH 0395/2557] mpeg12: Move finding the best frame rate to common code Previously in the mpeg2_metadata filter. Also adds a test. --- libavcodec/Makefile | 1 + libavcodec/mpeg12.h | 4 ++ libavcodec/mpeg12framerate.c | 64 ++++++++++++++++++++++ libavcodec/mpeg2_metadata_bsf.c | 58 ++------------------ libavcodec/tests/mpeg12framerate.c | 87 ++++++++++++++++++++++++++++++ tests/fate/libavcodec.mak | 5 ++ 6 files changed, 166 insertions(+), 53 deletions(-) create mode 100644 libavcodec/tests/mpeg12framerate.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 9c485b222ebcb..c750abd2d3aff 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -824,6 +824,7 @@ TESTPROGS-$(CONFIG_FFT) += fft fft-fixed TESTPROGS-$(CONFIG_GOLOMB) += golomb TESTPROGS-$(CONFIG_IDCTDSP) += dct TESTPROGS-$(CONFIG_IIRFILTER) += iirfilter +TESTPROGS-$(CONFIG_MPEGVIDEO) += mpeg12framerate TESTPROGS-$(CONFIG_RANGECODER) += rangecoder TESTOBJS = dctref.o diff --git a/libavcodec/mpeg12.h b/libavcodec/mpeg12.h index 17f0b781e64f1..26de7a48a8ebd 100644 --- a/libavcodec/mpeg12.h +++ b/libavcodec/mpeg12.h @@ -64,4 +64,8 @@ void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], void ff_mpeg1_encode_init(MpegEncContext *s); void ff_mpeg1_encode_slice_header(MpegEncContext *s); +void ff_mpeg12_find_best_frame_rate(AVRational frame_rate, + int *code, int *ext_n, int *ext_d, + int nonstandard); + #endif /* AVCODEC_MPEG12_H */ diff --git a/libavcodec/mpeg12framerate.c b/libavcodec/mpeg12framerate.c index b11dd5e01d149..acfef09745f35 100644 --- a/libavcodec/mpeg12framerate.c +++ b/libavcodec/mpeg12framerate.c @@ -18,6 +18,9 @@ #include "libavutil/rational.h" +#include "mpeg12.h" +#include "mpeg12data.h" + const AVRational ff_mpeg12_frame_rate_tab[16] = { { 0, 0}, {24000, 1001}, @@ -37,3 +40,64 @@ const AVRational ff_mpeg12_frame_rate_tab[16] = { { 15, 1}, { 0, 0}, }; + +void ff_mpeg12_find_best_frame_rate(AVRational frame_rate, + int *code, int *ext_n, int *ext_d, + int nonstandard) +{ + int mpeg2 = ext_n && ext_d; + int max_code = nonstandard ? 12 : 8; + int c, n, d, best_c, best_n, best_d; + AVRational best_error = { INT_MAX, 1 }; + + // Default to NTSC if the inputs make no sense. + best_c = 4; + best_n = best_d = 1; + + for (c = 1; c <= max_code; c++) { + if (av_cmp_q(frame_rate, ff_mpeg12_frame_rate_tab[c]) == 0) { + best_c = c; + goto found; + } + } + + for (c = 1; c <= max_code; c++) { + for (n = 1; n <= (mpeg2 ? 4 : 1); n++) { + for (d = 1; d <= (mpeg2 ? 32 : 1); d++) { + AVRational test, error; + int cmp; + + test = av_mul_q(ff_mpeg12_frame_rate_tab[c], + (AVRational) { n, d }); + + cmp = av_cmp_q(test, frame_rate); + if (cmp == 0) { + best_c = c; + best_n = n; + best_d = d; + goto found; + } + + if (cmp < 0) + error = av_div_q(frame_rate, test); + else + error = av_div_q(test, frame_rate); + + cmp = av_cmp_q(error, best_error); + if (cmp < 0 || (cmp == 0 && n == 1 && d == 1)) { + best_c = c; + best_n = n; + best_d = d; + best_error = error; + } + } + } + } + +found: + *code = best_c; + if (mpeg2) { + *ext_n = best_n - 1; + *ext_d = best_d - 1; + } +} diff --git a/libavcodec/mpeg2_metadata_bsf.c b/libavcodec/mpeg2_metadata_bsf.c index 80e946f58e7f6..5dae481d3da3f 100644 --- a/libavcodec/mpeg2_metadata_bsf.c +++ b/libavcodec/mpeg2_metadata_bsf.c @@ -23,6 +23,7 @@ #include "bsf.h" #include "cbs.h" #include "cbs_mpeg2.h" +#include "mpeg12.h" typedef struct MPEG2MetadataContext { const AVClass *class; @@ -99,63 +100,14 @@ static int mpeg2_metadata_update_fragment(AVBSFContext *bsf, } if (ctx->frame_rate.num && ctx->frame_rate.den) { - // Table 6-4. - static AVRational frame_rate_table[] = { - { 0, 0 }, - { 24000, 1001 }, - { 24, 1 }, - { 25, 1 }, - { 30000, 1001 }, - { 30, 1 }, - { 50, 1 }, - { 60000, 1001 }, - { 60, 1 }, - }; int code, ext_n, ext_d; - AVRational best_error = { INT_MAX, 1 }; - - for (i = 1; i < FF_ARRAY_ELEMS(frame_rate_table); i++) { - if (av_cmp_q(ctx->frame_rate, frame_rate_table[i]) == 0) { - code = i; - ext_n = 1; - ext_d = 1; - goto found_frame_rate; - } - } - for (i = 1; i < FF_ARRAY_ELEMS(frame_rate_table); i++) { - AVRational fr, error; - int n, d, cmp; - for (n = 1; n <= 4; n++) { - for (d = 1; d <= 32; d++) { - fr = av_mul_q(frame_rate_table[i], - (AVRational) { n, d }); - cmp = av_cmp_q(fr, ctx->frame_rate); - if (cmp == 0) { - code = i; - ext_n = n; - ext_d = d; - goto found_frame_rate; - } - if (cmp < 0) - error = av_div_q(ctx->frame_rate, fr); - else - error = av_div_q(fr, ctx->frame_rate); - cmp = av_cmp_q(error, best_error); - if (cmp < 0 || (cmp == 0 && n == 1 && d == 1)) { - code = i; - ext_n = n; - ext_d = d; - best_error = error; - } - } - } - } + ff_mpeg12_find_best_frame_rate(ctx->frame_rate, + &code, &ext_n, &ext_d, 0); - found_frame_rate: sh->frame_rate_code = code; - se->frame_rate_extension_n = ext_n - 1; - se->frame_rate_extension_d = ext_d - 1; + se->frame_rate_extension_n = ext_n; + se->frame_rate_extension_d = ext_d; } if (ctx->video_format >= 0 || diff --git a/libavcodec/tests/mpeg12framerate.c b/libavcodec/tests/mpeg12framerate.c new file mode 100644 index 0000000000000..c493cd0f5bd6a --- /dev/null +++ b/libavcodec/tests/mpeg12framerate.c @@ -0,0 +1,87 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/mpeg12.h" +#include "libavcodec/mpeg12data.h" + +int main(void) +{ + int i; + +#define TEST_MATCH(frame_rate, code, ext_n, ext_d) do { \ + AVRational fr = frame_rate; \ + int c, n, d; \ + ff_mpeg12_find_best_frame_rate(fr, &c, &n, &d, 0); \ + if (c != code || n != ext_n || d != ext_d) { \ + av_log(NULL, AV_LOG_ERROR, "Failed to match %d/%d: " \ + "code = %d, ext_n = %d, ext_d = %d.\n", \ + fr.num, fr.den, c, n, d); \ + return 1; \ + } \ + } while (0) +#define TEST_EXACT(frn, frd) do { \ + AVRational fr = (AVRational) { frn, frd }; \ + int c, n, d; \ + ff_mpeg12_find_best_frame_rate(fr, &c, &n, &d, 0); \ + if (av_cmp_q(fr, av_mul_q(ff_mpeg12_frame_rate_tab[c], \ + (AVRational) { n + 1, d + 1 })) != 0) { \ + av_log(NULL, AV_LOG_ERROR, "Failed to find exact %d/%d: " \ + "code = %d, ext_n = %d, ext_d = %d.\n", \ + fr.num, fr.den, c, n, d); \ + return 1; \ + } \ + } while (0) + + // Framerates in the table must be chosen exactly. + for (i = 1; i <= 8; i++) + TEST_MATCH(ff_mpeg12_frame_rate_tab[i], i, 0, 0); + + // As should the same ones with small perturbations. + // (1/1000 used here to be smaller than half the difference + // between 24 and 24000/1001.) + for (i = 1; i <= 8; i++) { + TEST_MATCH(av_sub_q(ff_mpeg12_frame_rate_tab[i], + (AVRational) { 1, 1000 }), i, 0, 0); + TEST_MATCH(av_add_q(ff_mpeg12_frame_rate_tab[i], + (AVRational) { 1, 1000 }), i, 0, 0); + } + + // Exactly constructable framerates should be exact. Note that some + // values can be made in multiple ways (e.g. 12 = 24 / 2 == 60 / 5), + // and there is no reason to favour any particular choice. + TEST_EXACT( 1, 1); + TEST_EXACT( 2, 1); + TEST_EXACT( 12, 1); + TEST_EXACT( 15000, 1001); + TEST_EXACT( 15, 1); + TEST_EXACT( 120, 1); + TEST_EXACT(120000, 1001); + TEST_EXACT( 200, 1); + TEST_EXACT( 240, 1); + + // Values higher than 240 (the highest representable, as 60 * 4 / 1) + // should be mapped to 240. + for (i = 240; i < 1000; i += 10) + TEST_MATCH(((AVRational) { i, 1 }), 8, 3, 0); + // Values lower than 24000/32032 (the lowest representable, as + // 24000/1001 * 1 / 32) should be mapped to 24000/32032. + for (i = 74; i > 0; i--) + TEST_MATCH(((AVRational) { i, 100 }), 1, 0, 31); + + return 0; +} diff --git a/tests/fate/libavcodec.mak b/tests/fate/libavcodec.mak index 0bbe57223f06c..257016261d217 100644 --- a/tests/fate/libavcodec.mak +++ b/tests/fate/libavcodec.mak @@ -12,6 +12,11 @@ FATE_LIBAVCODEC-$(CONFIG_IIRFILTER) += fate-iirfilter fate-iirfilter: libavcodec/tests/iirfilter$(EXESUF) fate-iirfilter: CMD = run libavcodec/tests/iirfilter +FATE_LIBAVCODEC-$(CONFIG_MPEGVIDEO) += fate-mpeg12framerate +fate-mpeg12framerate: libavcodec/tests/mpeg12framerate$(EXESUF) +fate-mpeg12framerate: CMD = run libavcodec/tests/mpeg12framerate +fate-mpeg12framerate: CMP = null + FATE_LIBAVCODEC-$(CONFIG_RANGECODER) += fate-rangecoder fate-rangecoder: libavcodec/tests/rangecoder$(EXESUF) fate-rangecoder: CMD = run libavcodec/tests/rangecoder From 10eb496d9ae94df6f792b0e1d8750738eb3a0952 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 24 Jun 2017 00:29:32 +0100 Subject: [PATCH 0396/2557] vaapi_mpeg2: Convert to use coded bitstream infrastructure --- configure | 2 +- libavcodec/vaapi_encode_mpeg2.c | 638 +++++++++++++++++++++----------- 2 files changed, 424 insertions(+), 216 deletions(-) diff --git a/configure b/configure index c24cdd4f7e0be..7728cd6de6f74 100755 --- a/configure +++ b/configure @@ -2301,7 +2301,7 @@ mpeg2_mmal_decoder_deps="mmal" mpeg2_qsv_decoder_select="qsvdec mpeg2_qsv_hwaccel mpegvideo_parser" mpeg2_qsv_encoder_select="qsvenc" mpeg2_vaapi_encoder_deps="VAEncPictureParameterBufferMPEG2" -mpeg2_vaapi_encoder_select="vaapi_encode" +mpeg2_vaapi_encoder_select="cbs_mpeg2 vaapi_encode" mpeg4_omx_encoder_deps="omx" vc1_mmal_decoder_deps="mmal" vc1_qsv_decoder_select="qsvdec vc1_qsv_hwaccel vc1_parser" diff --git a/libavcodec/vaapi_encode_mpeg2.c b/libavcodec/vaapi_encode_mpeg2.c index 634178521f2f9..8b956eb3e0e38 100644 --- a/libavcodec/vaapi_encode_mpeg2.c +++ b/libavcodec/vaapi_encode_mpeg2.c @@ -20,15 +20,11 @@ #include #include "libavutil/avassert.h" -#include "libavutil/common.h" -#include "libavutil/internal.h" -#include "libavutil/opt.h" -#include "libavutil/pixfmt.h" #include "avcodec.h" -#include "internal.h" -#include "mpegvideo.h" -#include "put_bits.h" +#include "cbs.h" +#include "cbs_mpeg2.h" +#include "mpeg12.h" #include "vaapi_encode.h" typedef struct VAAPIEncodeMPEG2Context { @@ -39,79 +35,104 @@ typedef struct VAAPIEncodeMPEG2Context { int quant_p; int quant_b; + MPEG2RawSequenceHeader sequence_header; + MPEG2RawExtensionData sequence_extension; + MPEG2RawExtensionData sequence_display_extension; + MPEG2RawGroupOfPicturesHeader gop_header; + MPEG2RawPictureHeader picture_header; + MPEG2RawExtensionData picture_coding_extension; + int64_t last_i_frame; unsigned int bit_rate; unsigned int vbv_buffer_size; + + AVRational frame_rate; + + unsigned int f_code_horizontal; + unsigned int f_code_vertical; + + CodedBitstreamContext cbc; + CodedBitstreamFragment current_fragment; } VAAPIEncodeMPEG2Context; -#define vseq_var(name) vseq->name, name -#define vseqext_field(name) vseq->sequence_extension.bits.name, name -#define vgop_field(name) vseq->gop_header.bits.name, name -#define vpic_var(name) vpic->name, name -#define vpcext_field(name) vpic->picture_coding_extension.bits.name, name -#define vcomp_field(name) vpic->composite_display.bits.name, name +static int vaapi_encode_mpeg2_write_fragment(AVCodecContext *avctx, + char *data, size_t *data_len, + CodedBitstreamFragment *frag) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + int err; + + err = ff_cbs_write_fragment_data(&priv->cbc, frag); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); + return err; + } + + if (*data_len < 8 * frag->data_size - frag->data_bit_padding) { + av_log(avctx, AV_LOG_ERROR, "Access unit too large: " + "%zu < %zu.\n", *data_len, + 8 * frag->data_size - frag->data_bit_padding); + return AVERROR(ENOSPC); + } + + memcpy(data, frag->data, frag->data_size); + *data_len = 8 * frag->data_size - frag->data_bit_padding; + + return 0; +} + +static int vaapi_encode_mpeg2_add_header(AVCodecContext *avctx, + CodedBitstreamFragment *frag, + int type, void *header) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + int err; + + err = ff_cbs_insert_unit_content(&priv->cbc, frag, -1, type, header); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to add header: " + "type = %d.\n", type); + return err; + } -#define u2(width, value, name) put_bits(&pbc, width, value) -#define u(width, ...) u2(width, __VA_ARGS__) + return 0; +} static int vaapi_encode_mpeg2_write_sequence_header(AVCodecContext *avctx, char *data, size_t *data_len) { - VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncSequenceParameterBufferMPEG2 *vseq = ctx->codec_sequence_params; - VAAPIEncodeMPEG2Context *priv = ctx->priv_data; - PutBitContext pbc; - - init_put_bits(&pbc, data, 8 * *data_len); - - u(32, SEQ_START_CODE, sequence_header_code); - - u(12, vseq->picture_width, horizontal_size_value); - u(12, vseq->picture_height, vertical_size_value); - u(4, vseq_var(aspect_ratio_information)); - u(4, 8, frame_rate_code); - u(18, priv->bit_rate & 0x3fff, bit_rate_value); - u(1, 1, marker_bit); - u(10, priv->vbv_buffer_size & 0x3ff, vbv_buffer_size_value); - u(1, 0, constrained_parameters_flag); - u(1, 0, load_intra_quantiser_matrix); - // intra_quantiser_matrix[64] - u(1, 0, load_non_intra_quantiser_matrix); - // non_intra_quantiser_matrix[64] - - while (put_bits_count(&pbc) % 8) - u(1, 0, zero_bit); - - u(32, EXT_START_CODE, extension_start_code); - u(4, 1, extension_start_code_identifier); - u(8, vseqext_field(profile_and_level_indication)); - u(1, vseqext_field(progressive_sequence)); - u(2, vseqext_field(chroma_format)); - u(2, 0, horizontal_size_extension); - u(2, 0, vertical_size_extension); - u(12, priv->bit_rate >> 18, bit_rate_extension); - u(1, 1, marker_bit); - u(8, priv->vbv_buffer_size >> 10, vbv_buffer_size_extension); - u(1, vseqext_field(low_delay)); - u(2, vseqext_field(frame_rate_extension_n)); - u(2, vseqext_field(frame_rate_extension_d)); - - while (put_bits_count(&pbc) % 8) - u(1, 0, zero_bit); - - u(32, GOP_START_CODE, group_start_code); - u(25, vgop_field(time_code)); - u(1, vgop_field(closed_gop)); - u(1, vgop_field(broken_link)); - - while (put_bits_count(&pbc) % 8) - u(1, 0, zero_bit); - - *data_len = put_bits_count(&pbc); - flush_put_bits(&pbc); - + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + CodedBitstreamFragment *frag = &priv->current_fragment; + int err; + + err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_SEQUENCE_HEADER, + &priv->sequence_header); + if (err < 0) + goto fail; + + err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_EXTENSION, + &priv->sequence_extension); + if (err < 0) + goto fail; + + err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_EXTENSION, + &priv->sequence_display_extension); + if (err < 0) + goto fail; + + err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_GROUP, + &priv->gop_header); + if (err < 0) + goto fail; + + err = vaapi_encode_mpeg2_write_fragment(avctx, data, data_len, frag); +fail: + ff_cbs_fragment_uninit(&priv->cbc, frag); return 0; } @@ -119,139 +140,275 @@ static int vaapi_encode_mpeg2_write_picture_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, char *data, size_t *data_len) { - VAEncPictureParameterBufferMPEG2 *vpic = pic->codec_picture_params; - int picture_coding_type; - PutBitContext pbc; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + CodedBitstreamFragment *frag = &priv->current_fragment; + int err; + + err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_PICTURE, + &priv->picture_header); + if (err < 0) + goto fail; + + err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_EXTENSION, + &priv->picture_coding_extension); + if (err < 0) + goto fail; + + err = vaapi_encode_mpeg2_write_fragment(avctx, data, data_len, frag); +fail: + ff_cbs_fragment_uninit(&priv->cbc, frag); + return 0; +} - init_put_bits(&pbc, data, 8 * *data_len); +static int vaapi_encode_mpeg2_init_sequence_params(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + MPEG2RawSequenceHeader *sh = &priv->sequence_header; + MPEG2RawSequenceExtension *se = &priv->sequence_extension.data.sequence; + MPEG2RawSequenceDisplayExtension *sde = &priv->sequence_display_extension.data.sequence_display; + MPEG2RawGroupOfPicturesHeader *goph = &priv->gop_header; + MPEG2RawPictureHeader *ph = &priv->picture_header; + MPEG2RawPictureCodingExtension *pce = &priv->picture_coding_extension.data.picture_coding; + VAEncSequenceParameterBufferMPEG2 *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferMPEG2 *vpic = ctx->codec_picture_params; + int code, ext_n, ext_d; - u(32, PICTURE_START_CODE, picture_start_code); - u(10, vpic_var(temporal_reference)); + memset(sh, 0, sizeof(*sh)); + memset(se, 0, sizeof(*se)); + memset(sde, 0, sizeof(*sde)); + memset(goph, 0, sizeof(*goph)); + memset(ph, 0, sizeof(*ph)); + memset(pce, 0, sizeof(*pce)); - switch (vpic->picture_type) { - case VAEncPictureTypeIntra: - picture_coding_type = AV_PICTURE_TYPE_I; - break; - case VAEncPictureTypePredictive: - picture_coding_type = AV_PICTURE_TYPE_P; + + if (avctx->bit_rate > 0) { + priv->bit_rate = (avctx->bit_rate + 399) / 400; + } else { + // Unknown (not a bitrate-targetting mode), so just use the + // highest value. + priv->bit_rate = 0x3fffffff; + } + if (avctx->rc_buffer_size > 0) { + priv->vbv_buffer_size = (avctx->rc_buffer_size + (1 << 14) - 1) >> 14; + } else { + // Unknown, so guess a value from the bitrate. + priv->vbv_buffer_size = priv->bit_rate >> 14; + } + + switch (avctx->level) { + case 4: // High. + case 6: // High 1440. + priv->f_code_horizontal = 9; + priv->f_code_vertical = 5; break; - case VAEncPictureTypeBidirectional: - picture_coding_type = AV_PICTURE_TYPE_B; + case 8: // Main. + priv->f_code_horizontal = 8; + priv->f_code_vertical = 5; break; + case 10: // Low. default: - av_assert0(0 && "invalid picture_coding_type"); - } - u(3, picture_coding_type, picture_coding_type); - u(16, 0xffff, vbv_delay); - if (picture_coding_type == 2 || picture_coding_type == 3) { - u(1, 0, full_pel_forward_vector); - u(3, 7, forward_f_code); - } - if (picture_coding_type == 3) { - u(1, 0, full_pel_backward_vector); - u(3, 7, backward_f_code); + priv->f_code_horizontal = 7; + priv->f_code_vertical = 4; + break; } - u(1, 0, extra_bit_picture); - - while (put_bits_count(&pbc) % 8) - u(1, 0, zero_bit); - - u(32, EXT_START_CODE, extension_start_code); - u(4, 8, extension_start_code_identifier); - u(4, vpic_var(f_code[0][0])); - u(4, vpic_var(f_code[0][1])); - u(4, vpic_var(f_code[1][0])); - u(4, vpic_var(f_code[1][1])); - u(2, vpcext_field(intra_dc_precision)); - u(2, vpcext_field(picture_structure)); - u(1, vpcext_field(top_field_first)); - u(1, vpcext_field(frame_pred_frame_dct)); - u(1, vpcext_field(concealment_motion_vectors)); - u(1, vpcext_field(q_scale_type)); - u(1, vpcext_field(intra_vlc_format)); - u(1, vpcext_field(alternate_scan)); - u(1, vpcext_field(repeat_first_field)); - u(1, 1, chroma_420_type); - u(1, vpcext_field(progressive_frame)); - u(1, vpcext_field(composite_display_flag)); - if (vpic->picture_coding_extension.bits.composite_display_flag) { - u(1, vcomp_field(v_axis)); - u(3, vcomp_field(field_sequence)); - u(1, vcomp_field(sub_carrier)); - u(7, vcomp_field(burst_amplitude)); - u(8, vcomp_field(sub_carrier_phase)); + + + // Sequence header + + sh->sequence_header_code = MPEG2_START_SEQUENCE_HEADER; + + sh->horizontal_size_value = avctx->width & 0xfff; + sh->vertical_size_value = avctx->height & 0xfff; + + if (avctx->sample_aspect_ratio.num != 0 && + avctx->sample_aspect_ratio.den != 0) { + AVRational dar = av_div_q(avctx->sample_aspect_ratio, + (AVRational) { avctx->width, avctx->height }); + + if (av_cmp_q(avctx->sample_aspect_ratio, (AVRational) { 1, 1 }) == 0) { + sh->aspect_ratio_information = 1; + } else if (av_cmp_q(dar, (AVRational) { 3, 4 }) == 0) { + sh->aspect_ratio_information = 2; + } else if (av_cmp_q(dar, (AVRational) { 9, 16 }) == 0) { + sh->aspect_ratio_information = 3; + } else if (av_cmp_q(dar, (AVRational) { 100, 221 }) == 0) { + sh->aspect_ratio_information = 4; + } else { + av_log(avctx, AV_LOG_WARNING, "Sample aspect ratio %d:%d is not " + "representable, signalling square pixels instead.\n", + avctx->sample_aspect_ratio.num, + avctx->sample_aspect_ratio.den); + sh->aspect_ratio_information = 1; + } + } else { + // Unknown - assume square pixels. + sh->aspect_ratio_information = 1; } - while (put_bits_count(&pbc) % 8) - u(1, 0, zero_bit); + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) + priv->frame_rate = avctx->framerate; + else + priv->frame_rate = av_inv_q(avctx->time_base); + ff_mpeg12_find_best_frame_rate(priv->frame_rate, + &code, &ext_n, &ext_d, 0); + sh->frame_rate_code = code; - *data_len = put_bits_count(&pbc); - flush_put_bits(&pbc); + sh->bit_rate_value = priv->bit_rate & 0x3ffff; + sh->vbv_buffer_size_value = priv->vbv_buffer_size & 0x3ff; - return 0; -} + sh->constrained_parameters_flag = 0; + sh->load_intra_quantiser_matrix = 0; + sh->load_non_intra_quantiser_matrix = 0; -static int vaapi_encode_mpeg2_init_sequence_params(AVCodecContext *avctx) -{ - VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncSequenceParameterBufferMPEG2 *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferMPEG2 *vpic = ctx->codec_picture_params; - VAAPIEncodeMPEG2Context *priv = ctx->priv_data; - vseq->intra_period = avctx->gop_size; - vseq->ip_period = ctx->b_per_p + 1; + // Sequence extension - vseq->picture_width = avctx->width; - vseq->picture_height = avctx->height; + priv->sequence_extension.extension_start_code = MPEG2_START_EXTENSION; + priv->sequence_extension.extension_start_code_identifier = + MPEG2_EXTENSION_SEQUENCE; - vseq->bits_per_second = avctx->bit_rate; - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) - vseq->frame_rate = (float)avctx->framerate.num / avctx->framerate.den; - else - vseq->frame_rate = (float)avctx->time_base.num / avctx->time_base.den; - - vseq->aspect_ratio_information = 1; - vseq->vbv_buffer_size = avctx->rc_buffer_size / (16 * 1024); - - vseq->sequence_extension.bits.profile_and_level_indication = - avctx->profile << 4 | avctx->level; - vseq->sequence_extension.bits.progressive_sequence = 1; - vseq->sequence_extension.bits.chroma_format = 1; - vseq->sequence_extension.bits.low_delay = 0; - vseq->sequence_extension.bits.frame_rate_extension_n = 0; - vseq->sequence_extension.bits.frame_rate_extension_d = 0; - - vseq->new_gop_header = 0; - vseq->gop_header.bits.time_code = 0; - vseq->gop_header.bits.closed_gop = 1; - vseq->gop_header.bits.broken_link = 0; - - vpic->forward_reference_picture = VA_INVALID_ID; - vpic->backward_reference_picture = VA_INVALID_ID; - vpic->reconstructed_picture = VA_INVALID_ID; - - vpic->coded_buf = VA_INVALID_ID; - - vpic->temporal_reference = 0; - vpic->f_code[0][0] = 15; - vpic->f_code[0][1] = 15; - vpic->f_code[1][0] = 15; - vpic->f_code[1][1] = 15; - - vpic->picture_coding_extension.bits.intra_dc_precision = 0; - vpic->picture_coding_extension.bits.picture_structure = 3; - vpic->picture_coding_extension.bits.top_field_first = 0; - vpic->picture_coding_extension.bits.frame_pred_frame_dct = 1; - vpic->picture_coding_extension.bits.concealment_motion_vectors = 0; - vpic->picture_coding_extension.bits.q_scale_type = 0; - vpic->picture_coding_extension.bits.intra_vlc_format = 0; - vpic->picture_coding_extension.bits.alternate_scan = 0; - vpic->picture_coding_extension.bits.repeat_first_field = 0; - vpic->picture_coding_extension.bits.progressive_frame = 1; - vpic->picture_coding_extension.bits.composite_display_flag = 0; - - priv->bit_rate = (avctx->bit_rate + 399) / 400; - priv->vbv_buffer_size = avctx->rc_buffer_size / (16 * 1024); + se->profile_and_level_indication = avctx->profile << 4 | avctx->level; + se->progressive_sequence = 1; + se->chroma_format = 1; + + se->horizontal_size_extension = avctx->width >> 12; + se->vertical_size_extension = avctx->height >> 12; + + se->bit_rate_extension = priv->bit_rate >> 18; + se->vbv_buffer_size_extension = priv->vbv_buffer_size >> 10; + se->low_delay = ctx->b_per_p == 0; + + se->frame_rate_extension_n = ext_n; + se->frame_rate_extension_d = ext_d; + + + // Sequence display extension + + priv->sequence_display_extension.extension_start_code = + MPEG2_START_EXTENSION; + priv->sequence_display_extension.extension_start_code_identifier = + MPEG2_EXTENSION_SEQUENCE_DISPLAY; + + sde->video_format = 5; + if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED || + avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { + sde->colour_description = 1; + sde->colour_primaries = avctx->color_primaries; + sde->transfer_characteristics = avctx->color_trc; + sde->matrix_coefficients = avctx->colorspace; + } else { + sde->colour_description = 0; + } + + sde->display_horizontal_size = avctx->width; + sde->display_vertical_size = avctx->height; + + + // GOP header + + goph->group_start_code = MPEG2_START_GROUP; + + goph->time_code = 0; + goph->closed_gop = 1; + goph->broken_link = 0; + + + // Defaults for picture header + + ph->picture_start_code = MPEG2_START_PICTURE; + + ph->vbv_delay = 0xffff; // Not currently calculated. + + ph->full_pel_forward_vector = 0; + ph->forward_f_code = 7; + ph->full_pel_backward_vector = 0; + ph->forward_f_code = 7; + + + // Defaults for picture coding extension + + priv->picture_coding_extension.extension_start_code = + MPEG2_START_EXTENSION; + priv->picture_coding_extension.extension_start_code_identifier = + MPEG2_EXTENSION_PICTURE_CODING; + + pce->intra_dc_precision = 0; + pce->picture_structure = 3; + pce->top_field_first = 0; + pce->frame_pred_frame_dct = 1; + pce->concealment_motion_vectors = 0; + pce->q_scale_type = 0; + pce->intra_vlc_format = 0; + pce->alternate_scan = 0; + pce->repeat_first_field = 0; + pce->progressive_frame = 1; + pce->composite_display_flag = 0; + + + + *vseq = (VAEncSequenceParameterBufferMPEG2) { + .intra_period = avctx->gop_size, + .ip_period = ctx->b_per_p + 1, + + .picture_width = avctx->width, + .picture_height = avctx->height, + + .bits_per_second = avctx->bit_rate, + .frame_rate = av_q2d(priv->frame_rate), + .aspect_ratio_information = sh->aspect_ratio_information, + .vbv_buffer_size = priv->vbv_buffer_size, + + .sequence_extension.bits = { + .profile_and_level_indication = se->profile_and_level_indication, + .progressive_sequence = se->progressive_sequence, + .chroma_format = se->chroma_format, + .low_delay = se->low_delay, + .frame_rate_extension_n = se->frame_rate_extension_n, + .frame_rate_extension_d = se->frame_rate_extension_d, + }, + + .new_gop_header = 1, + .gop_header.bits = { + .time_code = goph->time_code, + .closed_gop = goph->closed_gop, + .broken_link = goph->broken_link, + }, + }; + + *vpic = (VAEncPictureParameterBufferMPEG2) { + .forward_reference_picture = VA_INVALID_ID, + .backward_reference_picture = VA_INVALID_ID, + .reconstructed_picture = VA_INVALID_ID, + .coded_buf = VA_INVALID_ID, + + .vbv_delay = 0xffff, + .f_code = { { 15, 15 }, { 15, 15 } }, + + .picture_coding_extension.bits = { + .intra_dc_precision = pce->intra_dc_precision, + .picture_structure = pce->picture_structure, + .top_field_first = pce->top_field_first, + .frame_pred_frame_dct = pce->frame_pred_frame_dct, + .concealment_motion_vectors = pce->concealment_motion_vectors, + .q_scale_type = pce->q_scale_type, + .intra_vlc_format = pce->intra_vlc_format, + .alternate_scan = pce->alternate_scan, + .repeat_first_field = pce->repeat_first_field, + .progressive_frame = pce->progressive_frame, + .composite_display_flag = pce->composite_display_flag, + }, + + .composite_display.bits = { + .v_axis = pce->v_axis, + .field_sequence = pce->field_sequence, + .sub_carrier = pce->sub_carrier, + .burst_amplitude = pce->burst_amplitude, + .sub_carrier_phase = pce->sub_carrier_phase, + }, + }; return 0; } @@ -260,56 +417,61 @@ static int vaapi_encode_mpeg2_init_picture_params(AVCodecContext *avctx, VAAPIEncodePicture *pic) { VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncPictureParameterBufferMPEG2 *vpic = pic->codec_picture_params; VAAPIEncodeMPEG2Context *priv = ctx->priv_data; - int fch, fcv; + MPEG2RawPictureHeader *ph = &priv->picture_header; + MPEG2RawPictureCodingExtension *pce = &priv->picture_coding_extension.data.picture_coding; + VAEncPictureParameterBufferMPEG2 *vpic = pic->codec_picture_params; - switch (avctx->level) { - case 4: // High. - case 6: // High 1440. - fch = 9; - fcv = 5; - break; - case 8: // Main. - fch = 8; - fcv = 5; - break; - case 10: // Low. - default: - fch = 7; - fcv = 4; - break; + if (pic->type == PICTURE_TYPE_IDR || pic->type == PICTURE_TYPE_I) { + ph->temporal_reference = 0; + ph->picture_coding_type = 1; + priv->last_i_frame = pic->display_order; + } else { + ph->temporal_reference = pic->display_order - priv->last_i_frame; + ph->picture_coding_type = pic->type == PICTURE_TYPE_B ? 3 : 2; + } + + if (pic->type == PICTURE_TYPE_P || pic->type == PICTURE_TYPE_B) { + pce->f_code[0][0] = priv->f_code_horizontal; + pce->f_code[0][1] = priv->f_code_vertical; + } else { + pce->f_code[0][0] = 15; + pce->f_code[0][1] = 15; + } + if (pic->type == PICTURE_TYPE_B) { + pce->f_code[1][0] = priv->f_code_horizontal; + pce->f_code[1][1] = priv->f_code_vertical; + } else { + pce->f_code[1][0] = 15; + pce->f_code[1][1] = 15; } + vpic->reconstructed_picture = pic->recon_surface; + vpic->coded_buf = pic->output_buffer; + switch (pic->type) { case PICTURE_TYPE_IDR: case PICTURE_TYPE_I: vpic->picture_type = VAEncPictureTypeIntra; - priv->last_i_frame = pic->display_order; break; case PICTURE_TYPE_P: vpic->picture_type = VAEncPictureTypePredictive; vpic->forward_reference_picture = pic->refs[0]->recon_surface; - vpic->f_code[0][0] = fch; - vpic->f_code[0][1] = fcv; break; case PICTURE_TYPE_B: vpic->picture_type = VAEncPictureTypeBidirectional; vpic->forward_reference_picture = pic->refs[0]->recon_surface; vpic->backward_reference_picture = pic->refs[1]->recon_surface; - vpic->f_code[0][0] = fch; - vpic->f_code[0][1] = fcv; - vpic->f_code[1][0] = fch; - vpic->f_code[1][1] = fcv; break; default: av_assert0(0 && "invalid picture type"); } - vpic->reconstructed_picture = pic->recon_surface; - vpic->coded_buf = pic->output_buffer; - - vpic->temporal_reference = pic->display_order - priv->last_i_frame; + vpic->temporal_reference = ph->temporal_reference; + vpic->f_code[0][0] = pce->f_code[0][0]; + vpic->f_code[0][1] = pce->f_code[0][1]; + vpic->f_code[1][0] = pce->f_code[1][0]; + vpic->f_code[1][1] = pce->f_code[1][1]; pic->nb_slices = priv->mb_height; @@ -354,6 +516,11 @@ static av_cold int vaapi_encode_mpeg2_configure(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + int err; + + err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_MPEG2VIDEO, avctx); + if (err < 0) + return err; priv->mb_width = FFALIGN(avctx->width, 16) / 16; priv->mb_height = FFALIGN(avctx->height, 16) / 16; @@ -420,11 +587,41 @@ static av_cold int vaapi_encode_mpeg2_init(AVCodecContext *avctx) case FF_PROFILE_MPEG2_MAIN: ctx->va_profile = VAProfileMPEG2Main; break; + case FF_PROFILE_MPEG2_422: + av_log(avctx, AV_LOG_ERROR, "MPEG-2 4:2:2 profile " + "is not supported.\n"); + return AVERROR_PATCHWELCOME; + case FF_PROFILE_MPEG2_HIGH: + av_log(avctx, AV_LOG_ERROR, "MPEG-2 high profile " + "is not supported.\n"); + return AVERROR_PATCHWELCOME; + case FF_PROFILE_MPEG2_SS: + case FF_PROFILE_MPEG2_SNR_SCALABLE: + av_log(avctx, AV_LOG_ERROR, "MPEG-2 scalable profiles " + "are not supported.\n"); + return AVERROR_PATCHWELCOME; default: av_log(avctx, AV_LOG_ERROR, "Unknown MPEG-2 profile %d.\n", avctx->profile); return AVERROR(EINVAL); } + switch (avctx->level) { + case 4: // High + case 6: // High 1440 + case 8: // Main + case 10: // Low + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown MPEG-2 level %d.\n", + avctx->level); + return AVERROR(EINVAL); + } + + if (avctx->height % 4096 == 0 || avctx->width % 4096 == 0) { + av_log(avctx, AV_LOG_ERROR, "MPEG-2 does not support picture " + "height or width divisible by 4096.\n"); + return AVERROR(EINVAL); + } ctx->va_entrypoint = VAEntrypointEncSlice; ctx->va_rt_format = VA_RT_FORMAT_YUV420; @@ -439,6 +636,17 @@ static av_cold int vaapi_encode_mpeg2_init(AVCodecContext *avctx) return ff_vaapi_encode_init(avctx); } +static av_cold int vaapi_encode_mpeg2_close(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + + if (priv) + ff_cbs_close(&priv->cbc); + + return ff_vaapi_encode_close(avctx); +} + static const AVCodecDefault vaapi_encode_mpeg2_defaults[] = { { "profile", "4" }, { "level", "4" }, @@ -460,7 +668,7 @@ AVCodec ff_mpeg2_vaapi_encoder = { .priv_data_size = sizeof(VAAPIEncodeContext), .init = &vaapi_encode_mpeg2_init, .encode2 = &ff_vaapi_encode2, - .close = &ff_vaapi_encode_close, + .close = &vaapi_encode_mpeg2_close, .capabilities = AV_CODEC_CAP_DELAY, .defaults = vaapi_encode_mpeg2_defaults, .pix_fmts = (const enum AVPixelFormat[]) { From ac6691ab9938107d818cd8066ce3ea329ad14d8d Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 1 Sep 2017 12:32:45 -0300 Subject: [PATCH 0397/2557] avio: update avio_alloc_context() doxy It must be freed using avio_context_free() starting with commit 99684f3ae752fc8bfb44a2dd1482f8d7a3d8536d. Signed-off-by: James Almer Signed-off-by: Luca Barbato --- libavformat/avio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/avio.h b/libavformat/avio.h index f604c4ad41828..818fbaa505fe7 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -195,7 +195,7 @@ int avio_check(const char *url, int flags); /** * Allocate and initialize an AVIOContext for buffered I/O. It must be later - * freed with av_free(). + * freed with avio_context_free(). * * @param buffer Memory block for input/output operations via AVIOContext. * The buffer must be allocated with av_malloc() and friends. From 8d3666c425602b2feb985be900c14edf82dc328a Mon Sep 17 00:00:00 2001 From: "Huang, Zhengxu" Date: Thu, 24 Aug 2017 10:16:28 +0800 Subject: [PATCH 0398/2557] libavfilter/vf_vpp: Add common filters of the qsv vpp Add common filters of the qsv vpp features including scale,denosie, deinterlace,frc,crop and procAmp. Performance will be significantly reduced in the test if using cascade mode just like qsv framerate + qsv scale + qsv deinterlace + qsv denoise in separated way no matter in system or video memmory cases. And the code is so redundant because so much the same just as session and surface's creation and management. So we add a common qsv filter. Usage: -hwaccel qsv -c:v h264_qsv -r 25 -i in -vf vpp_qsv=w=iw/2:h=400:deinterlace=1:framerate=60:detail=50:denoise=50 -b 2M -maxrate 3M -c:v h264_qsv -y out.h264 Signed-off-by: ChaoX A Liu Signed-off-by: Zhengxu Huang Signed-off-by: Andrew Zhang Change-Id: I130392ce722138c209ab658c5f03f0009b6e8024 Signed-off-by: Maxym Dmytrychenko --- configure | 2 + libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_vpp_qsv.c | 401 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 405 insertions(+) create mode 100644 libavfilter/vf_vpp_qsv.c diff --git a/configure b/configure index 7728cd6de6f74..ff3abdd403a53 100755 --- a/configure +++ b/configure @@ -2544,6 +2544,8 @@ resample_filter_deps="avresample" scale_filter_deps="swscale" scale_qsv_filter_deps="libmfx" scale_vaapi_filter_deps="vaapi VAProcPipelineParameterBuffer" +vpp_qsv_filter_deps="libmfx" +vpp_qsv_filter_select="qsvvpp" # examples decode_audio_example_deps="avcodec avutil" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 348ad92116759..2b7e283ab0a20 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -93,6 +93,7 @@ OBJS-$(CONFIG_TRANSPOSE_FILTER) += vf_transpose.o OBJS-$(CONFIG_TRIM_FILTER) += trim.o OBJS-$(CONFIG_UNSHARP_FILTER) += vf_unsharp.o OBJS-$(CONFIG_VFLIP_FILTER) += vf_vflip.o +OBJS-$(CONFIG_VPP_QSV_FILTER) += vf_vpp_qsv.o OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o OBJS-$(CONFIG_NULLSINK_FILTER) += vsink_nullsink.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 3f09f46bb974e..ef94516ebc242 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -116,6 +116,7 @@ void avfilter_register_all(void) REGISTER_FILTER(TRIM, trim, vf); REGISTER_FILTER(UNSHARP, unsharp, vf); REGISTER_FILTER(VFLIP, vflip, vf); + REGISTER_FILTER(VPP_QSV, vpp_qsv, vf); REGISTER_FILTER(YADIF, yadif, vf); REGISTER_FILTER(COLOR, color, vsrc); diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c new file mode 100644 index 0000000000000..610e821c1a720 --- /dev/null +++ b/libavfilter/vf_vpp_qsv.c @@ -0,0 +1,401 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + ** @file + ** Hardware accelerated common filters based on Intel Quick Sync Video VPP + **/ + +#include + +#include "libavutil/opt.h" +#include "libavutil/eval.h" +#include "libavutil/avassert.h" +#include "libavutil/pixdesc.h" + +#include "formats.h" +#include "internal.h" +#include "avfilter.h" +#include "libavcodec/avcodec.h" +#include "libavformat/avformat.h" + +#include "qsvvpp.h" + +#define OFFSET(x) offsetof(VPPContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM + +/* number of video enhancement filters */ +#define ENH_FILTERS_COUNT (5) + +typedef struct VPPContext{ + const AVClass *class; + + QSVVPPContext *qsv; + + /* Video Enhancement Algorithms */ + mfxExtVPPDeinterlacing deinterlace_conf; + mfxExtVPPFrameRateConversion frc_conf; + mfxExtVPPDenoise denoise_conf; + mfxExtVPPDetail detail_conf; + mfxExtVPPProcAmp procamp_conf; + + int out_width; + int out_height; + + AVRational framerate; /* target framerate */ + int use_frc; /* use framerate conversion */ + int deinterlace; /* deinterlace mode : 0=off, 1=bob, 2=advanced */ + int denoise; /* Enable Denoise algorithm. Value [0, 100] */ + int detail; /* Enable Detail Enhancement algorithm. */ + /* Level is the optional, value [0, 100] */ + int use_crop; /* 1 = use crop; 0=none */ + int crop_w; + int crop_h; + int crop_x; + int crop_y; + + /* param for the procamp */ + int procamp; /* enable procamp */ + float hue; + float saturation; + float contrast; + float brightness; + + char *cx, *cy, *cw, *ch; + char *ow, *oh; +} VPPContext; + +static const AVOption options[] = { + { "deinterlace", "deinterlace mode: 0=off, 1=bob, 2=advanced", OFFSET(deinterlace), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MFX_DEINTERLACING_ADVANCED, .flags = FLAGS, "deinterlace" }, + { "bob", "Bob deinterlace mode.", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_DEINTERLACING_BOB }, .flags = FLAGS, "deinterlace" }, + { "advanced", "Advanced deinterlace mode. ", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_DEINTERLACING_ADVANCED }, .flags = FLAGS, "deinterlace" }, + + { "denoise", "denoise level [0, 100]", OFFSET(denoise), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, .flags = FLAGS }, + { "detail", "enhancement level [0, 100]", OFFSET(detail), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, .flags = FLAGS }, + { "framerate", "output framerate", OFFSET(framerate), AV_OPT_TYPE_RATIONAL, { .dbl = 0.0 },0, DBL_MAX, .flags = FLAGS }, + { "procamp", "Enable ProcAmp", OFFSET(procamp), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = FLAGS}, + { "hue", "ProcAmp hue", OFFSET(hue), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, -180.0, 180.0, .flags = FLAGS}, + { "saturation", "ProcAmp saturation", OFFSET(saturation), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.0, 10.0, .flags = FLAGS}, + { "contrast", "ProcAmp contrast", OFFSET(contrast), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.0, 10.0, .flags = FLAGS}, + { "brightness", "ProcAmp brightness", OFFSET(brightness), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, -100.0, 100.0, .flags = FLAGS}, + + { "cw", "set the width crop area expression", OFFSET(cw), AV_OPT_TYPE_STRING, { .str = "iw" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "ch", "set the height crop area expression", OFFSET(ch), AV_OPT_TYPE_STRING, { .str = "ih" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "cx", "set the x crop area expression", OFFSET(cx), AV_OPT_TYPE_STRING, { .str = "(in_w-out_w)/2" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "cy", "set the y crop area expression", OFFSET(cy), AV_OPT_TYPE_STRING, { .str = "(in_h-out_h)/2" }, CHAR_MIN, CHAR_MAX, FLAGS }, + + { "w", "Output video width", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, + { "width", "Output video width", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, + { "h", "Output video height", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, + { "height", "Output video height", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, + { NULL } +}; + +static const char *const var_names[] = { + "iw", "in_w", + "ih", "in_h", + "ow", "out_w", "w", + "oh", "out_h", "h", + "cw", + "ch", + "cx", + "cy", + NULL +}; + +enum var_name { + VAR_iW, VAR_IN_W, + VAR_iH, VAR_IN_H, + VAR_oW, VAR_OUT_W, VAR_W, + VAR_oH, VAR_OUT_H, VAR_H, + CW, + CH, + CX, + CY, + VAR_VARS_NB +}; + +static int eval_expr(AVFilterContext *ctx) +{ +#define PASS_EXPR(e, s) {\ + ret = av_expr_parse(&e, s, var_names, NULL, NULL, NULL, NULL, 0, ctx); \ + if (ret < 0) {\ + av_log(ctx, AV_LOG_ERROR, "Error when passing '%s'.\n", s);\ + goto release;\ + }\ +} +#define CALC_EXPR(e, v, i) {\ + i = v = av_expr_eval(e, var_values, NULL); \ +} + VPPContext *vpp = ctx->priv; + double var_values[VAR_VARS_NB] = { NAN }; + AVExpr *w_expr = NULL, *h_expr = NULL; + AVExpr *cw_expr = NULL, *ch_expr = NULL; + AVExpr *cx_expr = NULL, *cy_expr = NULL; + int ret = 0; + + PASS_EXPR(cw_expr, vpp->cw); + PASS_EXPR(ch_expr, vpp->ch); + + PASS_EXPR(w_expr, vpp->ow); + PASS_EXPR(h_expr, vpp->oh); + + PASS_EXPR(cx_expr, vpp->cx); + PASS_EXPR(cy_expr, vpp->cy); + + var_values[VAR_iW] = + var_values[VAR_IN_W] = ctx->inputs[0]->w; + + var_values[VAR_iH] = + var_values[VAR_IN_H] = ctx->inputs[0]->h; + + /* crop params */ + CALC_EXPR(cw_expr, var_values[CW], vpp->crop_w); + CALC_EXPR(ch_expr, var_values[CH], vpp->crop_h); + + /* calc again in case cw is relative to ch */ + CALC_EXPR(cw_expr, var_values[CW], vpp->crop_w); + + CALC_EXPR(w_expr, + var_values[VAR_OUT_W] = var_values[VAR_oW] = var_values[VAR_W], + vpp->out_width); + CALC_EXPR(h_expr, + var_values[VAR_OUT_H] = var_values[VAR_oH] = var_values[VAR_H], + vpp->out_height); + + /* calc again in case ow is relative to oh */ + CALC_EXPR(w_expr, + var_values[VAR_OUT_W] = var_values[VAR_oW] = var_values[VAR_W], + vpp->out_width); + + + CALC_EXPR(cx_expr, var_values[CX], vpp->crop_x); + CALC_EXPR(cy_expr, var_values[CY], vpp->crop_y); + + /* calc again in case cx is relative to cy */ + CALC_EXPR(cx_expr, var_values[CX], vpp->crop_x); + + if ((vpp->crop_w != var_values[VAR_iW]) || (vpp->crop_h != var_values[VAR_iH])) + vpp->use_crop = 1; + +release: + av_expr_free(w_expr); + av_expr_free(h_expr); + av_expr_free(cw_expr); + av_expr_free(ch_expr); + av_expr_free(cx_expr); + av_expr_free(cy_expr); +#undef PASS_EXPR +#undef CALC_EXPR + + return ret; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + VPPContext *vpp = ctx->priv; + int ret; + + if (vpp->framerate.den == 0 || vpp->framerate.num == 0) + vpp->framerate = inlink->frame_rate; + + if (av_cmp_q(vpp->framerate, inlink->frame_rate)) + vpp->use_frc = 1; + + ret = eval_expr(ctx); + if (ret != 0) { + av_log(ctx, AV_LOG_ERROR, "Fail to eval expr.\n"); + return ret; + } + + if (vpp->out_height == 0 || vpp->out_width == 0) { + vpp->out_width = inlink->w; + vpp->out_height = inlink->h; + } + + if (vpp->use_crop) { + vpp->crop_x = FFMAX(vpp->crop_x, 0); + vpp->crop_y = FFMAX(vpp->crop_y, 0); + + if(vpp->crop_w + vpp->crop_x > inlink->w) + vpp->crop_x = inlink->w - vpp->crop_w; + if(vpp->crop_h + vpp->crop_y > inlink->h) + vpp->crop_y = inlink->h - vpp->crop_h; + } + + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + VPPContext *vpp = ctx->priv; + QSVVPPParam param = { NULL }; + QSVVPPCrop crop = { 0 }; + mfxExtBuffer *ext_buf[ENH_FILTERS_COUNT]; + + outlink->w = vpp->out_width; + outlink->h = vpp->out_height; + outlink->frame_rate = vpp->framerate; + outlink->time_base = av_inv_q(vpp->framerate); + + param.filter_frame = NULL; + param.out_sw_format = AV_PIX_FMT_NV12; + param.num_ext_buf = 0; + param.ext_buf = ext_buf; + + if (vpp->use_crop) { + crop.in_idx = 0; + crop.x = vpp->crop_x; + crop.y = vpp->crop_y; + crop.w = vpp->crop_w; + crop.h = vpp->crop_h; + + param.num_crop = 1; + param.crop = &crop; + } + + if (vpp->deinterlace) { + memset(&vpp->deinterlace_conf, 0, sizeof(mfxExtVPPDeinterlacing)); + vpp->deinterlace_conf.Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING; + vpp->deinterlace_conf.Header.BufferSz = sizeof(mfxExtVPPDeinterlacing); + vpp->deinterlace_conf.Mode = vpp->deinterlace == 1 ? + MFX_DEINTERLACING_BOB : MFX_DEINTERLACING_ADVANCED; + + param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->deinterlace_conf; + } + + if (vpp->use_frc) { + memset(&vpp->frc_conf, 0, sizeof(mfxExtVPPFrameRateConversion)); + vpp->frc_conf.Header.BufferId = MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION; + vpp->frc_conf.Header.BufferSz = sizeof(mfxExtVPPFrameRateConversion); + vpp->frc_conf.Algorithm = MFX_FRCALGM_DISTRIBUTED_TIMESTAMP; + + param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->frc_conf; + } + + if (vpp->denoise) { + memset(&vpp->denoise_conf, 0, sizeof(mfxExtVPPDenoise)); + vpp->denoise_conf.Header.BufferId = MFX_EXTBUFF_VPP_DENOISE; + vpp->denoise_conf.Header.BufferSz = sizeof(mfxExtVPPDenoise); + vpp->denoise_conf.DenoiseFactor = vpp->denoise; + + param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->denoise_conf; + } + + if (vpp->detail) { + memset(&vpp->detail_conf, 0, sizeof(mfxExtVPPDetail)); + vpp->detail_conf.Header.BufferId = MFX_EXTBUFF_VPP_DETAIL; + vpp->detail_conf.Header.BufferSz = sizeof(mfxExtVPPDetail); + vpp->detail_conf.DetailFactor = vpp->detail; + + param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->detail_conf; + } + + if (vpp->procamp) { + memset(&vpp->procamp_conf, 0, sizeof(mfxExtVPPProcAmp)); + vpp->procamp_conf.Header.BufferId = MFX_EXTBUFF_VPP_PROCAMP; + vpp->procamp_conf.Header.BufferSz = sizeof(mfxExtVPPProcAmp); + vpp->procamp_conf.Hue = vpp->hue; + vpp->procamp_conf.Saturation = vpp->saturation; + vpp->procamp_conf.Contrast = vpp->contrast; + vpp->procamp_conf.Brightness = vpp->brightness; + + param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->procamp_conf; + } + + return ff_qsvvpp_create(ctx, &vpp->qsv, ¶m); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *picref) +{ + VPPContext *vpp = inlink->dst->priv; + + return ff_qsvvpp_filter_frame(vpp->qsv, inlink, picref); +} + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *in_fmts, *out_fmts; + static const enum AVPixelFormat in_pix_fmts[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUYV422, + AV_PIX_FMT_RGB32, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE + }; + static const enum AVPixelFormat out_pix_fmts[] = { + AV_PIX_FMT_NV12, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE + }; + + in_fmts = ff_make_format_list(in_pix_fmts); + out_fmts = ff_make_format_list(out_pix_fmts); + ff_formats_ref(in_fmts, &ctx->inputs[0]->out_formats); + ff_formats_ref(out_fmts, &ctx->outputs[0]->in_formats); + + return 0; +} + +static av_cold void vpp_uninit(AVFilterContext *ctx) +{ + VPPContext *vpp = ctx->priv; + + ff_qsvvpp_free(&vpp->qsv); +} + +static const AVClass vpp_class = { + .class_name = "vpp_qsv", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVFilterPad vpp_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad vpp_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vf_vpp_qsv = { + .name = "vpp_qsv", + .description = NULL_IF_CONFIG_SMALL("Quick Sync Video VPP."), + .priv_size = sizeof(VPPContext), + .query_formats = query_formats, + .uninit = vpp_uninit, + .inputs = vpp_inputs, + .outputs = vpp_outputs, + .priv_class = &vpp_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From a5a6ac1a123a927e5bed984ed757a29b7ff87dab Mon Sep 17 00:00:00 2001 From: "Huang, Zhengxu" Date: Fri, 18 Aug 2017 09:40:47 +0800 Subject: [PATCH 0399/2557] libavfilter/overlay_qsv: Add QSV overlay vpp filter The filter supports two inputs and (implicitly) scaling the second input during composition, unlike the software overlay. The code has been separated into common interface and qsv overlay implementation. The common part mainly creates the qsv session and manages the surface which is nearly the same for all qsv filters. So the qsvvpp.c/qsvvpp.h API can be used by other QSV vpp filters to reduce code redundancy. Usage: -hwaccel qsv -c:v mpeg2_qsv -r 25 -i in.m2v -hwaccel qsv -c:v h264_qsv -i in.h264 -filter_complex "overlay_qsv=eof_action=repeat:x=(W-w)/2:y=(H-h)/2" -b 2M -maxrate 3M -c:v h264_qsv -y out.h264 Two inputs should have different sizes otherwise one will be completely covered or you need to scale the second input as follows: -hwaccel qsv -c:v mpeg2_qsv -r 25 -i in.m2v -hwaccel qsv -c:v h264_qsv -i in.h264 -filter_complex "overlay_qsv=w=720:h=576:x=(W-w)/2:y=(H-h)/2" -b 2M -maxrate 3M -c:v h264_qsv -y out.h264 Signed-off-by: ChaoX A Liu Signed-off-by: Zhengxu Huang Signed-off-by: Andrew Zhang Change-Id: I5c381febb0af6e2f9622c54ba00490ab99d48297 Signed-off-by: Maxym Dmytrychenko --- Changelog | 1 + configure | 4 + libavfilter/Makefile | 6 + libavfilter/allfilters.c | 1 + libavfilter/qsvvpp.c | 727 +++++++++++++++++++++++++++++++++++ libavfilter/qsvvpp.h | 66 ++++ libavfilter/vf_overlay_qsv.c | 487 +++++++++++++++++++++++ 7 files changed, 1292 insertions(+) create mode 100644 libavfilter/qsvvpp.c create mode 100644 libavfilter/qsvvpp.h create mode 100644 libavfilter/vf_overlay_qsv.c diff --git a/Changelog b/Changelog index 92a72490a9929..51c3f85a28f96 100644 --- a/Changelog +++ b/Changelog @@ -19,6 +19,7 @@ version : - Cinepak encoder - Intel QSV-accelerated MJPEG encoding - NVIDIA CUVID-accelerated H.264 and HEVC decoding +- Intel QSV-accelerated overlay filter version 12: diff --git a/configure b/configure index ff3abdd403a53..a3cfe376802b0 100755 --- a/configure +++ b/configure @@ -1790,6 +1790,7 @@ CONFIG_EXTRA=" qsv qsvdec qsvenc + qsvvpp rangecoder riffdec riffenc @@ -2276,6 +2277,7 @@ omx_rpi_select="omx" qsv_deps="libmfx" qsvdec_select="qsv" qsvenc_select="qsv" +qsvvpp_select="qsv" vaapi_encode_deps="vaapi" hwupload_cuda_filter_deps="cuda" @@ -2540,6 +2542,8 @@ hqdn3d_filter_deps="gpl" interlace_filter_deps="gpl" movie_filter_deps="avcodec avformat" ocv_filter_deps="libopencv" +overlay_qsv_filter_deps="libmfx" +overlay_qsv_filter_select="qsvvpp" resample_filter_deps="avresample" scale_filter_deps="swscale" scale_qsv_filter_deps="libmfx" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 2b7e283ab0a20..82776267705ba 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -20,6 +20,9 @@ OBJS = allfilters.o \ OBJS-$(HAVE_THREADS) += pthread.o +# subsystems +OBJS-$(CONFIG_QSVVPP) += qsvvpp.o + # audio filters OBJS-$(CONFIG_AFORMAT_FILTER) += af_aformat.o OBJS-$(CONFIG_AMIX_FILTER) += af_amix.o @@ -75,6 +78,7 @@ OBJS-$(CONFIG_NOFORMAT_FILTER) += vf_format.o OBJS-$(CONFIG_NULL_FILTER) += vf_null.o OBJS-$(CONFIG_OCV_FILTER) += vf_libopencv.o OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o +OBJS-$(CONFIG_OVERLAY_QSV_FILTER) += vf_overlay_qsv.o OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o OBJS-$(CONFIG_SCALE_FILTER) += vf_scale.o @@ -105,5 +109,7 @@ OBJS-$(CONFIG_NULLSRC_FILTER) += vsrc_nullsrc.o OBJS-$(CONFIG_RGBTESTSRC_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_TESTSRC_FILTER) += vsrc_testsrc.o +SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h + TOOLS = graph2dot TESTPROGS = filtfmts diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index ef94516ebc242..2b3a67244e83e 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -98,6 +98,7 @@ void avfilter_register_all(void) REGISTER_FILTER(NULL, null, vf); REGISTER_FILTER(OCV, ocv, vf); REGISTER_FILTER(OVERLAY, overlay, vf); + REGISTER_FILTER(OVERLAY_QSV, overlay_qsv, vf); REGISTER_FILTER(PAD, pad, vf); REGISTER_FILTER(PIXDESCTEST, pixdesctest, vf); REGISTER_FILTER(SCALE, scale, vf); diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c new file mode 100644 index 0000000000000..0b639c2d67660 --- /dev/null +++ b/libavfilter/qsvvpp.c @@ -0,0 +1,727 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Intel Quick Sync Video VPP base function + */ + +#include "libavutil/common.h" +#include "libavutil/mathematics.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_qsv.h" +#include "libavutil/time.h" +#include "libavutil/pixdesc.h" + +#include "internal.h" +#include "qsvvpp.h" +#include "video.h" + +#define IS_VIDEO_MEMORY(mode) (mode & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | \ + MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) +#define IS_OPAQUE_MEMORY(mode) (mode & MFX_MEMTYPE_OPAQUE_FRAME) +#define IS_SYSTEM_MEMORY(mode) (mode & MFX_MEMTYPE_SYSTEM_MEMORY) + +typedef struct QSVFrame { + AVFrame *frame; + mfxFrameSurface1 *surface; + mfxFrameSurface1 surface_internal; /* for system memory */ + struct QSVFrame *next; +} QSVFrame; + +/* abstract struct for all QSV filters */ +struct QSVVPPContext { + mfxSession session; + int (*filter_frame) (AVFilterLink *outlink, AVFrame *frame);/* callback */ + enum AVPixelFormat out_sw_format; /* Real output format */ + mfxVideoParam vpp_param; + mfxFrameInfo *frame_infos; /* frame info for each input */ + + /* members related to the input/output surface */ + int in_mem_mode; + int out_mem_mode; + QSVFrame *in_frame_list; + QSVFrame *out_frame_list; + int nb_surface_ptrs_in; + int nb_surface_ptrs_out; + mfxFrameSurface1 **surface_ptrs_in; + mfxFrameSurface1 **surface_ptrs_out; + + /* MFXVPP extern parameters */ + mfxExtOpaqueSurfaceAlloc opaque_alloc; + mfxExtBuffer **ext_buffers; + int nb_ext_buffers; +}; + +static const mfxHandleType handle_types[] = { + MFX_HANDLE_VA_DISPLAY, + MFX_HANDLE_D3D9_DEVICE_MANAGER, + MFX_HANDLE_D3D11_DEVICE, +}; + +static const AVRational default_tb = { 1, 90000 }; + +/* functions for frameAlloc */ +static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, + mfxFrameAllocResponse *resp) +{ + QSVVPPContext *s = pthis; + int i; + + if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) || + !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) || + !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME)) + return MFX_ERR_UNSUPPORTED; + + if (req->Type & MFX_MEMTYPE_FROM_VPPIN) { + resp->mids = av_mallocz(s->nb_surface_ptrs_in * sizeof(*resp->mids)); + if (!resp->mids) + return AVERROR(ENOMEM); + + for (i = 0; i < s->nb_surface_ptrs_in; i++) + resp->mids[i] = s->surface_ptrs_in[i]->Data.MemId; + + resp->NumFrameActual = s->nb_surface_ptrs_in; + } else { + resp->mids = av_mallocz(s->nb_surface_ptrs_out * sizeof(*resp->mids)); + if (!resp->mids) + return AVERROR(ENOMEM); + + for (i = 0; i < s->nb_surface_ptrs_out; i++) + resp->mids[i] = s->surface_ptrs_out[i]->Data.MemId; + + resp->NumFrameActual = s->nb_surface_ptrs_out; + } + + return MFX_ERR_NONE; +} + +static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp) +{ + av_freep(&resp->mids); + return MFX_ERR_NONE; +} + +static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) +{ + return MFX_ERR_UNSUPPORTED; +} + +static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) +{ + return MFX_ERR_UNSUPPORTED; +} + +static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) +{ + *hdl = mid; + return MFX_ERR_NONE; +} + +static int pix_fmt_to_mfx_fourcc(int format) +{ + switch (format) { + case AV_PIX_FMT_YUV420P: + return MFX_FOURCC_YV12; + case AV_PIX_FMT_NV12: + return MFX_FOURCC_NV12; + case AV_PIX_FMT_YUYV422: + return MFX_FOURCC_YUY2; + case AV_PIX_FMT_RGB32: + return MFX_FOURCC_RGB4; + } + + return MFX_FOURCC_NV12; +} + +static int map_frame_to_surface(AVFrame *frame, mfxFrameSurface1 *surface) +{ + switch (frame->format) { + case AV_PIX_FMT_NV12: + surface->Data.Y = frame->data[0]; + surface->Data.UV = frame->data[1]; + break; + case AV_PIX_FMT_YUV420P: + surface->Data.Y = frame->data[0]; + surface->Data.U = frame->data[1]; + surface->Data.V = frame->data[2]; + break; + case AV_PIX_FMT_YUYV422: + surface->Data.Y = frame->data[0]; + surface->Data.U = frame->data[0] + 1; + surface->Data.V = frame->data[0] + 3; + break; + case AV_PIX_FMT_RGB32: + surface->Data.B = frame->data[0]; + surface->Data.G = frame->data[0] + 1; + surface->Data.R = frame->data[0] + 2; + surface->Data.A = frame->data[0] + 3; + break; + default: + return MFX_ERR_UNSUPPORTED; + } + surface->Data.Pitch = frame->linesize[0]; + + return 0; +} + +/* fill the surface info */ +static int fill_frameinfo_by_link(mfxFrameInfo *frameinfo, AVFilterLink *link) +{ + enum AVPixelFormat pix_fmt; + AVHWFramesContext *frames_ctx; + AVQSVFramesContext *frames_hwctx; + const AVPixFmtDescriptor *desc; + + if (link->format == AV_PIX_FMT_QSV) { + if (!link->hw_frames_ctx) + return AVERROR(EINVAL); + + frames_ctx = (AVHWFramesContext *)link->hw_frames_ctx->data; + frames_hwctx = frames_ctx->hwctx; + *frameinfo = frames_hwctx->surfaces[0].Info; + } else { + pix_fmt = link->format; + desc = av_pix_fmt_desc_get(pix_fmt); + if (!desc) + return AVERROR_BUG; + + frameinfo->CropX = 0; + frameinfo->CropY = 0; + frameinfo->Width = FFALIGN(link->w, 32); + frameinfo->Height = FFALIGN(link->h, 32); + frameinfo->PicStruct = MFX_PICSTRUCT_PROGRESSIVE; + frameinfo->FourCC = pix_fmt_to_mfx_fourcc(pix_fmt); + frameinfo->BitDepthLuma = desc->comp[0].depth; + frameinfo->BitDepthChroma = desc->comp[0].depth; + frameinfo->Shift = desc->comp[0].depth > 8; + if (desc->log2_chroma_w && desc->log2_chroma_h) + frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV420; + else if (desc->log2_chroma_w) + frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV422; + else + frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV444; + } + + frameinfo->CropW = link->w; + frameinfo->CropH = link->h; + frameinfo->FrameRateExtN = link->frame_rate.num; + frameinfo->FrameRateExtD = link->frame_rate.den; + frameinfo->AspectRatioW = link->sample_aspect_ratio.num ? link->sample_aspect_ratio.num : 1; + frameinfo->AspectRatioH = link->sample_aspect_ratio.den ? link->sample_aspect_ratio.den : 1; + + return 0; +} + +static void clear_unused_frames(QSVFrame *list) +{ + while (list) { + if (list->surface && !list->surface->Data.Locked) { + list->surface = NULL; + av_frame_free(&list->frame); + } + list = list->next; + } +} + +static void clear_frame_list(QSVFrame **list) +{ + while (*list) { + QSVFrame *frame; + + frame = *list; + *list = (*list)->next; + av_frame_free(&frame->frame); + av_freep(&frame); + } +} + +static QSVFrame *get_free_frame(QSVFrame **list) +{ + QSVFrame *out = *list; + + for (; out; out = out->next) { + if (!out->surface) + break; + } + + if (!out) { + out = av_mallocz(sizeof(*out)); + if (!out) { + av_log(NULL, AV_LOG_ERROR, "Can't alloc new output frame.\n"); + return NULL; + } + out->next = *list; + *list = out; + } + + return out; +} + +/* get the input surface */ +static QSVFrame *submit_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picref) +{ + QSVFrame *qsv_frame; + AVFilterContext *ctx = inlink->dst; + + clear_unused_frames(s->in_frame_list); + + qsv_frame = get_free_frame(&s->in_frame_list); + if (!qsv_frame) + return NULL; + + /* Turn AVFrame into mfxFrameSurface1. + * For video/opaque memory mode, pix_fmt is AV_PIX_FMT_QSV, and + * mfxFrameSurface1 is stored in AVFrame->data[3]; + * for system memory mode, raw video data is stored in + * AVFrame, we should map it into mfxFrameSurface1. + */ + if (!IS_SYSTEM_MEMORY(s->in_mem_mode)) { + if (picref->format != AV_PIX_FMT_QSV) { + av_log(ctx, AV_LOG_ERROR, "QSVVPP gets a wrong frame.\n"); + return NULL; + } + qsv_frame->frame = picref; + qsv_frame->surface = (mfxFrameSurface1 *)qsv_frame->frame->data[3]; + } else { + /* make a copy if the input is not padded as libmfx requires */ + if (picref->height & 31 || picref->linesize[0] & 31) { + qsv_frame->frame = ff_get_video_buffer(inlink, + FFALIGN(inlink->w, 32), + FFALIGN(inlink->h, 32)); + if (!qsv_frame->frame) + return NULL; + + qsv_frame->frame->width = picref->width; + qsv_frame->frame->height = picref->height; + + if (av_frame_copy(qsv_frame->frame, picref) < 0) { + av_frame_free(&qsv_frame->frame); + return NULL; + } + + av_frame_copy_props(qsv_frame->frame, picref); + av_frame_free(&picref); + } else + qsv_frame->frame = picref; + + if (map_frame_to_surface(qsv_frame->frame, + &qsv_frame->surface_internal) < 0) { + av_log(ctx, AV_LOG_ERROR, "Unsupported frame.\n"); + return NULL; + } + qsv_frame->surface = &qsv_frame->surface_internal; + } + + qsv_frame->surface->Info = s->frame_infos[FF_INLINK_IDX(inlink)]; + qsv_frame->surface->Data.TimeStamp = av_rescale_q(qsv_frame->frame->pts, + inlink->time_base, default_tb); + + qsv_frame->surface->Info.PicStruct = + !qsv_frame->frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE : + (qsv_frame->frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF : + MFX_PICSTRUCT_FIELD_BFF); + if (qsv_frame->frame->repeat_pict == 1) + qsv_frame->surface->Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED; + else if (qsv_frame->frame->repeat_pict == 2) + qsv_frame->surface->Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING; + else if (qsv_frame->frame->repeat_pict == 4) + qsv_frame->surface->Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING; + + return qsv_frame; +} + +/* get the output surface */ +static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + QSVFrame *out_frame; + int ret; + + clear_unused_frames(s->out_frame_list); + + out_frame = get_free_frame(&s->out_frame_list); + if (!out_frame) + return NULL; + + /* For video memory, get a hw frame; + * For system memory, get a sw frame and map it into a mfx_surface. */ + if (!IS_SYSTEM_MEMORY(s->out_mem_mode)) { + out_frame->frame = av_frame_alloc(); + if (!out_frame->frame) + return NULL; + + ret = av_hwframe_get_buffer(outlink->hw_frames_ctx, out_frame->frame, 0); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Can't allocate a surface.\n"); + return NULL; + } + + out_frame->surface = (mfxFrameSurface1 *)out_frame->frame->data[3]; + } else { + /* Get a frame with aligned dimensions. + * Libmfx need system memory being 128x64 aligned */ + out_frame->frame = ff_get_video_buffer(outlink, + FFALIGN(outlink->w, 128), + FFALIGN(outlink->h, 64)); + if (!out_frame->frame) + return NULL; + + out_frame->frame->width = outlink->w; + out_frame->frame->height = outlink->h; + + ret = map_frame_to_surface(out_frame->frame, + &out_frame->surface_internal); + if (ret < 0) + return NULL; + + out_frame->surface = &out_frame->surface_internal; + } + + out_frame->surface->Info = s->vpp_param.vpp.Out; + + return out_frame; +} + +/* create the QSV session */ +static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s) +{ + AVFilterLink *inlink = avctx->inputs[0]; + AVFilterLink *outlink = avctx->outputs[0]; + AVQSVFramesContext *in_frames_hwctx = NULL; + AVQSVFramesContext *out_frames_hwctx = NULL; + + AVBufferRef *device_ref; + AVHWDeviceContext *device_ctx; + AVQSVDeviceContext *device_hwctx; + mfxHDL handle; + mfxHandleType handle_type; + mfxVersion ver; + mfxIMPL impl; + int ret, i; + + if (inlink->hw_frames_ctx) { + AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data; + + device_ref = frames_ctx->device_ref; + in_frames_hwctx = frames_ctx->hwctx; + + s->in_mem_mode = in_frames_hwctx->frame_type; + + s->surface_ptrs_in = av_mallocz_array(in_frames_hwctx->nb_surfaces, + sizeof(*s->surface_ptrs_in)); + if (!s->surface_ptrs_in) + return AVERROR(ENOMEM); + + for (i = 0; i < in_frames_hwctx->nb_surfaces; i++) + s->surface_ptrs_in[i] = in_frames_hwctx->surfaces + i; + + s->nb_surface_ptrs_in = in_frames_hwctx->nb_surfaces; + } else if (avctx->hw_device_ctx) { + device_ref = avctx->hw_device_ctx; + s->in_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY; + } else { + av_log(avctx, AV_LOG_ERROR, "No hw context provided.\n"); + return AVERROR(EINVAL); + } + + device_ctx = (AVHWDeviceContext *)device_ref->data; + device_hwctx = device_ctx->hwctx; + + if (outlink->format == AV_PIX_FMT_QSV) { + AVHWFramesContext *out_frames_ctx; + AVBufferRef *out_frames_ref = av_hwframe_ctx_alloc(device_ref); + if (!out_frames_ref) + return AVERROR(ENOMEM); + + s->out_mem_mode = IS_OPAQUE_MEMORY(s->in_mem_mode) ? + MFX_MEMTYPE_OPAQUE_FRAME : + MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; + + out_frames_ctx = (AVHWFramesContext *)out_frames_ref->data; + out_frames_hwctx = out_frames_ctx->hwctx; + + out_frames_ctx->format = AV_PIX_FMT_QSV; + out_frames_ctx->width = FFALIGN(outlink->w, 32); + out_frames_ctx->height = FFALIGN(outlink->h, 32); + out_frames_ctx->sw_format = s->out_sw_format; + out_frames_ctx->initial_pool_size = 64; + out_frames_hwctx->frame_type = s->out_mem_mode; + + ret = av_hwframe_ctx_init(out_frames_ref); + if (ret < 0) { + av_buffer_unref(&out_frames_ref); + av_log(avctx, AV_LOG_ERROR, "Error creating frames_ctx for output pad.\n"); + return ret; + } + + s->surface_ptrs_out = av_mallocz_array(out_frames_hwctx->nb_surfaces, + sizeof(*s->surface_ptrs_out)); + if (!s->surface_ptrs_out) { + av_buffer_unref(&out_frames_ref); + return AVERROR(ENOMEM); + } + + for (i = 0; i < out_frames_hwctx->nb_surfaces; i++) + s->surface_ptrs_out[i] = out_frames_hwctx->surfaces + i; + s->nb_surface_ptrs_out = out_frames_hwctx->nb_surfaces; + + av_buffer_unref(&outlink->hw_frames_ctx); + outlink->hw_frames_ctx = out_frames_ref; + } else + s->out_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY; + + /* extract the properties of the "master" session given to us */ + ret = MFXQueryIMPL(device_hwctx->session, &impl); + if (ret == MFX_ERR_NONE) + ret = MFXQueryVersion(device_hwctx->session, &ver); + if (ret != MFX_ERR_NONE) { + av_log(avctx, AV_LOG_ERROR, "Error querying the session attributes\n"); + return AVERROR_UNKNOWN; + } + + for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) { + ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_types[i], &handle); + if (ret == MFX_ERR_NONE) { + handle_type = handle_types[i]; + break; + } + } + + /* create a "slave" session with those same properties, to be used for vpp */ + ret = MFXInit(impl, &ver, &s->session); + if (ret != MFX_ERR_NONE) { + av_log(avctx, AV_LOG_ERROR, "Error initializing a session for scaling\n"); + return AVERROR_UNKNOWN; + } + + if (handle) { + ret = MFXVideoCORE_SetHandle(s->session, handle_type, handle); + if (ret != MFX_ERR_NONE) + return AVERROR_UNKNOWN; + } + + if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) { + s->opaque_alloc.In.Surfaces = s->surface_ptrs_in; + s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs_in; + s->opaque_alloc.In.Type = s->in_mem_mode; + + s->opaque_alloc.Out.Surfaces = s->surface_ptrs_out; + s->opaque_alloc.Out.NumSurface = s->nb_surface_ptrs_out; + s->opaque_alloc.Out.Type = s->out_mem_mode; + + s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION; + s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc); + } else if (IS_VIDEO_MEMORY(s->in_mem_mode) || IS_VIDEO_MEMORY(s->out_mem_mode)) { + mfxFrameAllocator frame_allocator = { + .pthis = s, + .Alloc = frame_alloc, + .Lock = frame_lock, + .Unlock = frame_unlock, + .GetHDL = frame_get_hdl, + .Free = frame_free, + }; + + ret = MFXVideoCORE_SetFrameAllocator(s->session, &frame_allocator); + if (ret != MFX_ERR_NONE) + return AVERROR_UNKNOWN; + } + + return 0; +} + +int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *param) +{ + int i; + int ret; + QSVVPPContext *s; + + s = av_mallocz(sizeof(*s)); + if (!s) + return AVERROR(ENOMEM); + + s->filter_frame = param->filter_frame; + if (!s->filter_frame) + s->filter_frame = ff_filter_frame; + s->out_sw_format = param->out_sw_format; + + /* create the vpp session */ + ret = init_vpp_session(avctx, s); + if (ret < 0) + goto failed; + + s->frame_infos = av_mallocz_array(avctx->nb_inputs, sizeof(*s->frame_infos)); + if (!s->frame_infos) { + ret = AVERROR(ENOMEM); + goto failed; + } + + /* Init each input's information */ + for (i = 0; i < avctx->nb_inputs; i++) { + ret = fill_frameinfo_by_link(&s->frame_infos[i], avctx->inputs[i]); + if (ret < 0) + goto failed; + } + + /* Update input's frame info according to crop */ + for (i = 0; i < param->num_crop; i++) { + QSVVPPCrop *crop = param->crop + i; + if (crop->in_idx > avctx->nb_inputs) { + ret = AVERROR(EINVAL); + goto failed; + } + s->frame_infos[crop->in_idx].CropX = crop->x; + s->frame_infos[crop->in_idx].CropY = crop->y; + s->frame_infos[crop->in_idx].CropW = crop->w; + s->frame_infos[crop->in_idx].CropH = crop->h; + } + + s->vpp_param.vpp.In = s->frame_infos[0]; + + ret = fill_frameinfo_by_link(&s->vpp_param.vpp.Out, avctx->outputs[0]); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Fail to get frame info from link.\n"); + goto failed; + } + + if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) { + s->nb_ext_buffers = param->num_ext_buf + 1; + s->ext_buffers = av_mallocz_array(s->nb_ext_buffers, sizeof(*s->ext_buffers)); + if (!s->ext_buffers) { + ret = AVERROR(ENOMEM); + goto failed; + } + + s->ext_buffers[0] = (mfxExtBuffer *)&s->opaque_alloc; + for (i = 1; i < param->num_ext_buf; i++) + s->ext_buffers[i] = param->ext_buf[i - 1]; + s->vpp_param.ExtParam = s->ext_buffers; + s->vpp_param.NumExtParam = s->nb_ext_buffers; + } else { + s->vpp_param.NumExtParam = param->num_ext_buf; + s->vpp_param.ExtParam = param->ext_buf; + } + + s->vpp_param.AsyncDepth = 1; + + if (IS_SYSTEM_MEMORY(s->in_mem_mode)) + s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_SYSTEM_MEMORY; + else if (IS_VIDEO_MEMORY(s->in_mem_mode)) + s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_VIDEO_MEMORY; + else if (IS_OPAQUE_MEMORY(s->in_mem_mode)) + s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_OPAQUE_MEMORY; + + if (IS_SYSTEM_MEMORY(s->out_mem_mode)) + s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_SYSTEM_MEMORY; + else if (IS_VIDEO_MEMORY(s->out_mem_mode)) + s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_VIDEO_MEMORY; + else if (IS_OPAQUE_MEMORY(s->out_mem_mode)) + s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_OPAQUE_MEMORY; + + ret = MFXVideoVPP_Init(s->session, &s->vpp_param); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to create a qsvvpp, ret = %d.\n", ret); + goto failed; + } + + *vpp = s; + return 0; + +failed: + ff_qsvvpp_free(&s); + + return ret; +} + +int ff_qsvvpp_free(QSVVPPContext **vpp) +{ + QSVVPPContext *s = *vpp; + + if (!s) + return 0; + + if (s->session) { + MFXVideoVPP_Close(s->session); + MFXClose(s->session); + } + + /* release all the resources */ + clear_frame_list(&s->in_frame_list); + clear_frame_list(&s->out_frame_list); + av_freep(&s->surface_ptrs_in); + av_freep(&s->surface_ptrs_out); + av_freep(&s->ext_buffers); + av_freep(&s->frame_infos); + av_freep(vpp); + + return 0; +} + +int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picref) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + mfxSyncPoint sync; + QSVFrame *in_frame, *out_frame; + int ret, filter_ret; + + in_frame = submit_frame(s, inlink, picref); + if (!in_frame) { + av_log(ctx, AV_LOG_ERROR, "Failed to submit frame on input[%d]\n", + FF_INLINK_IDX(inlink)); + return AVERROR(ENOMEM); + } + + do { + out_frame = query_frame(s, outlink); + if (!out_frame) { + av_log(ctx, AV_LOG_ERROR, "Failed to query an output frame.\n"); + return AVERROR(ENOMEM); + } + + do { + ret = MFXVideoVPP_RunFrameVPPAsync(s->session, in_frame->surface, + out_frame->surface, NULL, &sync); + if (ret == MFX_WRN_DEVICE_BUSY) + av_usleep(500); + } while (ret == MFX_WRN_DEVICE_BUSY); + + if (ret < 0 && ret != MFX_ERR_MORE_SURFACE) { + /* Ignore more_data error */ + if (ret == MFX_ERR_MORE_DATA) + ret = AVERROR(EAGAIN); + break; + } + + if (MFXVideoCORE_SyncOperation(s->session, sync, 1000) < 0) + av_log(ctx, AV_LOG_WARNING, "Sync failed.\n"); + + out_frame->frame->pts = av_rescale_q(out_frame->surface->Data.TimeStamp, + default_tb, outlink->time_base); + + filter_ret = s->filter_frame(outlink, out_frame->frame); + if (filter_ret < 0) { + av_frame_free(&out_frame->frame); + ret = filter_ret; + break; + } + out_frame->frame = NULL; + } while(ret == MFX_ERR_MORE_SURFACE); + + return ret; +} diff --git a/libavfilter/qsvvpp.h b/libavfilter/qsvvpp.h new file mode 100644 index 0000000000000..082c0a8994fda --- /dev/null +++ b/libavfilter/qsvvpp.h @@ -0,0 +1,66 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Intel Quick Sync Video VPP base function + */ + +#ifndef AVFILTER_QSVVPP_H +#define AVFILTER_QSVVPP_H + +#include + +#include "avfilter.h" + +#define FF_INLINK_IDX(link) ((int)((link)->dstpad - (link)->dst->input_pads)) +#define FF_OUTLINK_IDX(link) ((int)((link)->srcpad - (link)->src->output_pads)) + +typedef struct QSVVPPContext QSVVPPContext; + +typedef struct QSVVPPCrop { + int in_idx; ///< Input index + int x, y, w, h; ///< Crop rectangle +} QSVVPPCrop; + +typedef struct QSVVPPParam { + /* default is ff_filter_frame */ + int (*filter_frame)(AVFilterLink *outlink, AVFrame *frame); + + /* To fill with MFX enhanced filter configurations */ + int num_ext_buf; + mfxExtBuffer **ext_buf; + + /* Real output format */ + enum AVPixelFormat out_sw_format; + + /* Crop information for each input, if needed */ + int num_crop; + QSVVPPCrop *crop; +} QSVVPPParam; + +/* create and initialize the QSV session */ +int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *param); + +/* release the resources (eg.surfaces) */ +int ff_qsvvpp_free(QSVVPPContext **vpp); + +/* vpp filter frame and call the cb if needed */ +int ff_qsvvpp_filter_frame(QSVVPPContext *vpp, AVFilterLink *inlink, AVFrame *frame); + +#endif /* AVFILTER_QSVVPP_H */ diff --git a/libavfilter/vf_overlay_qsv.c b/libavfilter/vf_overlay_qsv.c new file mode 100644 index 0000000000000..89f2fb134dba2 --- /dev/null +++ b/libavfilter/vf_overlay_qsv.c @@ -0,0 +1,487 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * A hardware accelerated overlay filter based on Intel Quick Sync Video VPP + */ + +#include "libavutil/opt.h" +#include "libavutil/common.h" +#include "libavutil/pixdesc.h" +#include "libavutil/eval.h" +#include "libavutil/hwcontext.h" +#include "libavutil/avstring.h" +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "libavutil/mathematics.h" + +#include "internal.h" +#include "avfilter.h" +#include "formats.h" +#include "video.h" + +#include "qsvvpp.h" + +#define MAIN 0 +#define OVERLAY 1 + +#define OFFSET(x) offsetof(QSVOverlayContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM + +enum var_name { + VAR_MAIN_iW, VAR_MW, + VAR_MAIN_iH, VAR_MH, + VAR_OVERLAY_iW, + VAR_OVERLAY_iH, + VAR_OVERLAY_X, VAR_OX, + VAR_OVERLAY_Y, VAR_OY, + VAR_OVERLAY_W, VAR_OW, + VAR_OVERLAY_H, VAR_OH, + VAR_VARS_NB +}; + +enum EOFAction { + EOF_ACTION_REPEAT, + EOF_ACTION_ENDALL +}; + +typedef struct QSVOverlayContext { + const AVClass *class; + + QSVVPPContext *qsv; + QSVVPPParam qsv_param; + mfxExtVPPComposite comp_conf; + double var_values[VAR_VARS_NB]; + + char *overlay_ox, *overlay_oy, *overlay_ow, *overlay_oh; + uint16_t overlay_alpha, overlay_pixel_alpha; + + enum EOFAction eof_action; /* action to take on EOF from source */ + + AVFrame *main; + AVFrame *over_prev, *over_next; +} QSVOverlayContext; + +static const char *const var_names[] = { + "main_w", "W", /* input width of the main layer */ + "main_h", "H", /* input height of the main layer */ + "overlay_iw", /* input width of the overlay layer */ + "overlay_ih", /* input height of the overlay layer */ + "overlay_x", "x", /* x position of the overlay layer inside of main */ + "overlay_y", "y", /* y position of the overlay layer inside of main */ + "overlay_w", "w", /* output width of overlay layer */ + "overlay_h", "h", /* output height of overlay layer */ + NULL +}; + +static const AVOption options[] = { + { "x", "Overlay x position", OFFSET(overlay_ox), AV_OPT_TYPE_STRING, { .str="0"}, 0, 255, .flags = FLAGS}, + { "y", "Overlay y position", OFFSET(overlay_oy), AV_OPT_TYPE_STRING, { .str="0"}, 0, 255, .flags = FLAGS}, + { "w", "Overlay width", OFFSET(overlay_ow), AV_OPT_TYPE_STRING, { .str="overlay_iw"}, 0, 255, .flags = FLAGS}, + { "h", "Overlay height", OFFSET(overlay_oh), AV_OPT_TYPE_STRING, { .str="overlay_ih*w/overlay_iw"}, 0, 255, .flags = FLAGS}, + { "alpha", "Overlay global alpha", OFFSET(overlay_alpha), AV_OPT_TYPE_INT, { .i64 = 255}, 0, 255, .flags = FLAGS}, + { "eof_action", "Action to take when encountering EOF from secondary input ", + OFFSET(eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_REPEAT }, + EOF_ACTION_REPEAT, EOF_ACTION_ENDALL, .flags = FLAGS, "eof_action" }, + { "repeat", "Repeat the previous frame.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_REPEAT }, .flags = FLAGS, "eof_action" }, + { "endall", "End both streams.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_ENDALL }, .flags = FLAGS, "eof_action" }, + { NULL } +}; + +static int eval_expr(AVFilterContext *ctx) +{ + QSVOverlayContext *vpp = ctx->priv; + double *var_values = vpp->var_values; + int ret = 0; + AVExpr *ox_expr = NULL, *oy_expr = NULL; + AVExpr *ow_expr = NULL, *oh_expr = NULL; + +#define PASS_EXPR(e, s) {\ + ret = av_expr_parse(&e, s, var_names, NULL, NULL, NULL, NULL, 0, ctx); \ + if (ret < 0) {\ + av_log(ctx, AV_LOG_ERROR, "Error when passing '%s'.\n", s);\ + goto release;\ + }\ +} + PASS_EXPR(ox_expr, vpp->overlay_ox); + PASS_EXPR(oy_expr, vpp->overlay_oy); + PASS_EXPR(ow_expr, vpp->overlay_ow); + PASS_EXPR(oh_expr, vpp->overlay_oh); +#undef PASS_EXPR + + var_values[VAR_OVERLAY_W] = + var_values[VAR_OW] = av_expr_eval(ow_expr, var_values, NULL); + var_values[VAR_OVERLAY_H] = + var_values[VAR_OH] = av_expr_eval(oh_expr, var_values, NULL); + + /* calc again in case ow is relative to oh */ + var_values[VAR_OVERLAY_W] = + var_values[VAR_OW] = av_expr_eval(ow_expr, var_values, NULL); + + var_values[VAR_OVERLAY_X] = + var_values[VAR_OX] = av_expr_eval(ox_expr, var_values, NULL); + var_values[VAR_OVERLAY_Y] = + var_values[VAR_OY] = av_expr_eval(oy_expr, var_values, NULL); + + /* calc again in case ox is relative to oy */ + var_values[VAR_OVERLAY_X] = + var_values[VAR_OX] = av_expr_eval(ox_expr, var_values, NULL); + + /* calc overlay_w and overlay_h again incase relative to ox,oy */ + var_values[VAR_OVERLAY_W] = + var_values[VAR_OW] = av_expr_eval(ow_expr, var_values, NULL); + var_values[VAR_OVERLAY_H] = + var_values[VAR_OH] = av_expr_eval(oh_expr, var_values, NULL); + var_values[VAR_OVERLAY_W] = + var_values[VAR_OW] = av_expr_eval(ow_expr, var_values, NULL); + +release: + av_expr_free(ox_expr); + av_expr_free(oy_expr); + av_expr_free(ow_expr); + av_expr_free(oh_expr); + + return ret; +} + +static int have_alpha_planar(AVFilterLink *link) +{ + enum AVPixelFormat pix_fmt; + const AVPixFmtDescriptor *desc; + AVHWFramesContext *fctx; + + if (link->format == AV_PIX_FMT_QSV) { + fctx = (AVHWFramesContext *)link->hw_frames_ctx->data; + pix_fmt = fctx->sw_format; + } + + desc = av_pix_fmt_desc_get(pix_fmt); + if (!desc) + return 0; + + return !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA); +} + +static int config_main_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + QSVOverlayContext *vpp = ctx->priv; + mfxVPPCompInputStream *st = &vpp->comp_conf.InputStream[0]; + + av_log(ctx, AV_LOG_DEBUG, "Input[%d] is of %s.\n", FF_INLINK_IDX(inlink), + av_get_pix_fmt_name(inlink->format)); + + vpp->var_values[VAR_MAIN_iW] = + vpp->var_values[VAR_MW] = inlink->w; + vpp->var_values[VAR_MAIN_iH] = + vpp->var_values[VAR_MH] = inlink->h; + + st->DstX = 0; + st->DstY = 0; + st->DstW = inlink->w; + st->DstH = inlink->h; + st->GlobalAlphaEnable = 0; + st->PixelAlphaEnable = 0; + + return 0; +} + +static int config_overlay_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + QSVOverlayContext *vpp = ctx->priv; + mfxVPPCompInputStream *st = &vpp->comp_conf.InputStream[1]; + int ret = 0; + + av_log(ctx, AV_LOG_DEBUG, "Input[%d] is of %s.\n", FF_INLINK_IDX(inlink), + av_get_pix_fmt_name(inlink->format)); + + vpp->var_values[VAR_OVERLAY_iW] = inlink->w; + vpp->var_values[VAR_OVERLAY_iH] = inlink->h; + + ret = eval_expr(ctx); + if (ret < 0) + return ret; + + st->DstX = vpp->var_values[VAR_OX]; + st->DstY = vpp->var_values[VAR_OY]; + st->DstW = vpp->var_values[VAR_OW]; + st->DstH = vpp->var_values[VAR_OH]; + st->GlobalAlpha = vpp->overlay_alpha; + st->GlobalAlphaEnable = (st->GlobalAlpha < 255); + st->PixelAlphaEnable = have_alpha_planar(inlink); + + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + QSVOverlayContext *vpp = ctx->priv; + AVFilterLink *in0 = ctx->inputs[0]; + AVFilterLink *in1 = ctx->inputs[1]; + + av_log(ctx, AV_LOG_DEBUG, "Output is of %s.\n", av_get_pix_fmt_name(outlink->format)); + if ((in0->format == AV_PIX_FMT_QSV && in1->format != AV_PIX_FMT_QSV) || + (in0->format != AV_PIX_FMT_QSV && in1->format == AV_PIX_FMT_QSV)) { + av_log(ctx, AV_LOG_ERROR, "Mixing hardware and software pixel formats is not supported.\n"); + return AVERROR(EINVAL); + } else if (in0->format == AV_PIX_FMT_QSV) { + AVHWFramesContext *hw_frame0 = (AVHWFramesContext *)in0->hw_frames_ctx->data; + AVHWFramesContext *hw_frame1 = (AVHWFramesContext *)in1->hw_frames_ctx->data; + + if (hw_frame0->device_ctx != hw_frame1->device_ctx) { + av_log(ctx, AV_LOG_ERROR, "Inputs with different underlying QSV devices are forbidden.\n"); + return AVERROR(EINVAL); + } + } + + outlink->w = vpp->var_values[VAR_MW]; + outlink->h = vpp->var_values[VAR_MH]; + outlink->frame_rate = in0->frame_rate; + outlink->time_base = av_inv_q(outlink->frame_rate); + + return ff_qsvvpp_create(ctx, &vpp->qsv, &vpp->qsv_param); +} + +static int blend_frame(AVFilterContext *ctx, AVFrame *mpic, AVFrame *opic) +{ + int ret = 0; + QSVOverlayContext *vpp = ctx->priv; + AVFrame *opic_copy = NULL; + + ret = ff_qsvvpp_filter_frame(vpp->qsv, ctx->inputs[0], mpic); + if (ret == 0 || ret == AVERROR(EAGAIN)) { + /* Reference the overlay frame. Because: + * 1. ff_qsvvpp_filter_frame will take control of the given frame + * 2. We need to repeat the overlay frame when 2nd input goes into EOF + */ + opic_copy = av_frame_clone(opic); + if (!opic_copy) + return AVERROR(ENOMEM); + + ret = ff_qsvvpp_filter_frame(vpp->qsv, ctx->inputs[1], opic_copy); + } + + return ret; +} + +static int handle_overlay_eof(AVFilterContext *ctx) +{ + int ret = 0; + QSVOverlayContext *s = ctx->priv; + /* Repeat previous frame on secondary input */ + if (s->over_prev && s->eof_action == EOF_ACTION_REPEAT) + ret = blend_frame(ctx, s->main, s->over_prev); + /* End both streams */ + else if (s->eof_action == EOF_ACTION_ENDALL) + return AVERROR_EOF; + + s->main = NULL; + + return ret; +} + +static int request_frame(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + QSVOverlayContext *s = ctx->priv; + AVRational tb_main = ctx->inputs[MAIN]->time_base; + AVRational tb_over = ctx->inputs[OVERLAY]->time_base; + int ret = 0; + + /* get a frame on the main input */ + if (!s->main) { + ret = ff_request_frame(ctx->inputs[MAIN]); + if (ret < 0) + return ret; + } + + /* get a new frame on the overlay input, on EOF check setting 'eof_action' */ + if (!s->over_next) { + ret = ff_request_frame(ctx->inputs[OVERLAY]); + if (ret == AVERROR_EOF) + return handle_overlay_eof(ctx); + else if (ret < 0) + return ret; + } + + while (s->main->pts != AV_NOPTS_VALUE && + s->over_next->pts != AV_NOPTS_VALUE && + av_compare_ts(s->over_next->pts, tb_over, s->main->pts, tb_main) < 0) { + av_frame_free(&s->over_prev); + FFSWAP(AVFrame*, s->over_prev, s->over_next); + + ret = ff_request_frame(ctx->inputs[OVERLAY]); + if (ret == AVERROR_EOF) + return handle_overlay_eof(ctx); + else if (ret < 0) + return ret; + } + + if (s->main->pts == AV_NOPTS_VALUE || + s->over_next->pts == AV_NOPTS_VALUE || + !av_compare_ts(s->over_next->pts, tb_over, s->main->pts, tb_main)) { + ret = blend_frame(ctx, s->main, s->over_next); + av_frame_free(&s->over_prev); + FFSWAP(AVFrame*, s->over_prev, s->over_next); + } else if (s->over_prev) { + ret = blend_frame(ctx, s->main, s->over_prev); + } else { + av_frame_free(&s->main); + ret = AVERROR(EAGAIN); + } + + s->main = NULL; + + return ret; +} + +static int filter_frame_main(AVFilterLink *inlink, AVFrame *frame) +{ + QSVOverlayContext *s = inlink->dst->priv; + + av_assert0(!s->main); + s->main = frame; + + return 0; +} + +static int filter_frame_overlay(AVFilterLink *inlink, AVFrame *frame) +{ + QSVOverlayContext *s = inlink->dst->priv; + + av_assert0(!s->over_next); + s->over_next = frame; + + return 0; +} + +static int overlay_qsv_init(AVFilterContext *ctx) +{ + QSVOverlayContext *vpp = ctx->priv; + + /* fill composite config */ + vpp->comp_conf.Header.BufferId = MFX_EXTBUFF_VPP_COMPOSITE; + vpp->comp_conf.Header.BufferSz = sizeof(vpp->comp_conf); + vpp->comp_conf.NumInputStream = ctx->nb_inputs; + vpp->comp_conf.InputStream = av_mallocz_array(ctx->nb_inputs, + sizeof(*vpp->comp_conf.InputStream)); + if (!vpp->comp_conf.InputStream) + return AVERROR(ENOMEM); + + /* initialize QSVVPP params */ + vpp->qsv_param.filter_frame = NULL; + vpp->qsv_param.ext_buf = av_mallocz(sizeof(*vpp->qsv_param.ext_buf)); + if (!vpp->qsv_param.ext_buf) + return AVERROR(ENOMEM); + + vpp->qsv_param.ext_buf[0] = (mfxExtBuffer *)&vpp->comp_conf; + vpp->qsv_param.num_ext_buf = 1; + vpp->qsv_param.out_sw_format = AV_PIX_FMT_NV12; + vpp->qsv_param.num_crop = 0; + + return 0; +} + +static void overlay_qsv_uninit(AVFilterContext *ctx) +{ + QSVOverlayContext *vpp = ctx->priv; + + av_frame_free(&vpp->main); + av_frame_free(&vpp->over_prev); + av_frame_free(&vpp->over_next); + ff_qsvvpp_free(&vpp->qsv); + av_freep(&vpp->comp_conf.InputStream); + av_freep(&vpp->qsv_param.ext_buf); +} + +static int overlay_qsv_query_formats(AVFilterContext *ctx) +{ + int i; + + static const enum AVPixelFormat main_in_fmts[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUYV422, + AV_PIX_FMT_RGB32, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE + }; + static const enum AVPixelFormat out_pix_fmts[] = { + AV_PIX_FMT_NV12, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE + }; + + for (i = 0; i < ctx->nb_inputs; i++) + ff_formats_ref(ff_make_format_list(main_in_fmts), &ctx->inputs[i]->out_formats); + + ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats); + + return 0; +} + +static const AVClass overlay_qsv_class = { + .class_name = "overlay_qsv", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVFilterPad overlay_qsv_inputs[] = { + { + .name = "main", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame_main, + .config_props = config_main_input, + .needs_fifo = 1, + }, + { + .name = "overlay", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame_overlay, + .config_props = config_overlay_input, + .needs_fifo = 1, + }, + { NULL } +}; + +static const AVFilterPad overlay_qsv_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + .request_frame = request_frame, + }, + { NULL } +}; + +AVFilter ff_vf_overlay_qsv = { + .name = "overlay_qsv", + .description = NULL_IF_CONFIG_SMALL("Quick Sync Video overlay."), + .priv_size = sizeof(QSVOverlayContext), + .query_formats = overlay_qsv_query_formats, + .init = overlay_qsv_init, + .uninit = overlay_qsv_uninit, + .inputs = overlay_qsv_inputs, + .outputs = overlay_qsv_outputs, + .priv_class = &overlay_qsv_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From 2b50847e0f8f8894bfa74aa1c5a63e90a9867b45 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Thu, 21 Sep 2017 13:23:21 +0200 Subject: [PATCH 0400/2557] pixdesc: Add API to map color property names to enum values Signed-off-by: Vittorio Giovara --- doc/APIchanges | 5 ++++ libavutil/pixdesc.c | 64 +++++++++++++++++++++++++++++++++++++++++++++ libavutil/pixdesc.h | 25 ++++++++++++++++++ libavutil/version.h | 2 +- 4 files changed, 95 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index ed90be890d22e..fa27007f44ce8 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,11 @@ libavutil: 2017-03-23 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavu 56.6.0 - pixdesc.h + Add av_color_range_from_name(), av_color_primaries_from_name(), + av_color_transfer_from_name(), av_color_space_from_name(), and + av_chroma_location_from_name(). + 2016-xx-xx - xxxxxxx - lavf 58.1.0 - avio.h Add avio_read_partial(). diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index b168ac7d0b26a..957f99fdaac61 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -2013,27 +2013,91 @@ const char *av_color_range_name(enum AVColorRange range) color_range_names[range] : NULL; } +int av_color_range_from_name(const char *name) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(color_range_names); i++) { + size_t len = strlen(color_range_names[i]); + if (!strncmp(color_range_names[i], name, len)) + return i; + } + + return AVERROR(EINVAL); +} + const char *av_color_primaries_name(enum AVColorPrimaries primaries) { return (unsigned) primaries < AVCOL_PRI_NB ? color_primaries_names[primaries] : NULL; } +int av_color_primaries_from_name(const char *name) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(color_primaries_names); i++) { + size_t len = strlen(color_primaries_names[i]); + if (!strncmp(color_primaries_names[i], name, len)) + return i; + } + + return AVERROR(EINVAL); +} + const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer) { return (unsigned) transfer < AVCOL_TRC_NB ? color_transfer_names[transfer] : NULL; } +int av_color_transfer_from_name(const char *name) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(color_transfer_names); i++) { + size_t len = strlen(color_transfer_names[i]); + if (!strncmp(color_transfer_names[i], name, len)) + return i; + } + + return AVERROR(EINVAL); +} + const char *av_color_space_name(enum AVColorSpace space) { return (unsigned) space < AVCOL_SPC_NB ? color_space_names[space] : NULL; } +int av_color_space_from_name(const char *name) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(color_space_names); i++) { + size_t len = strlen(color_space_names[i]); + if (!strncmp(color_space_names[i], name, len)) + return i; + } + + return AVERROR(EINVAL); +} + const char *av_chroma_location_name(enum AVChromaLocation location) { return (unsigned) location < AVCHROMA_LOC_NB ? chroma_location_names[location] : NULL; } +int av_chroma_location_from_name(const char *name) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(chroma_location_names); i++) { + size_t len = strlen(chroma_location_names[i]); + if (!strncmp(chroma_location_names[i], name, len)) + return i; + } + + return AVERROR(EINVAL); +} diff --git a/libavutil/pixdesc.h b/libavutil/pixdesc.h index 3bb10f777a92f..4e8a29e60700b 100644 --- a/libavutil/pixdesc.h +++ b/libavutil/pixdesc.h @@ -297,24 +297,49 @@ enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt); */ const char *av_color_range_name(enum AVColorRange range); +/** + * @return the AVColorRange value for name or an AVError if not found. + */ +int av_color_range_from_name(const char *name); + /** * @return the name for provided color primaries or NULL if unknown. */ const char *av_color_primaries_name(enum AVColorPrimaries primaries); +/** + * @return the AVColorPrimaries value for name or an AVError if not found. + */ +int av_color_primaries_from_name(const char *name); + /** * @return the name for provided color transfer or NULL if unknown. */ const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer); +/** + * @return the AVColorTransferCharacteristic value for name or an AVError if not found. + */ +int av_color_transfer_from_name(const char *name); + /** * @return the name for provided color space or NULL if unknown. */ const char *av_color_space_name(enum AVColorSpace space); +/** + * @return the AVColorSpace value for name or an AVError if not found. + */ +int av_color_space_from_name(const char *name); + /** * @return the name for provided chroma location or NULL if unknown. */ const char *av_chroma_location_name(enum AVChromaLocation location); +/** + * @return the AVChromaLocation value for name or an AVError if not found. + */ +int av_chroma_location_from_name(const char *name); + #endif /* AVUTIL_PIXDESC_H */ diff --git a/libavutil/version.h b/libavutil/version.h index 5d0bb611244d4..c258968b8e2f6 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -54,7 +54,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 5 +#define LIBAVUTIL_VERSION_MINOR 6 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 9e361022782514d4d4ce97b9c9d5a7863a2de519 Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Sun, 24 Sep 2017 12:57:54 +0200 Subject: [PATCH 0401/2557] smacker: return meaningful error codes on failure --- libavformat/smacker.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavformat/smacker.c b/libavformat/smacker.c index eb4b63fdad606..56c909bc06c76 100644 --- a/libavformat/smacker.c +++ b/libavformat/smacker.c @@ -112,7 +112,7 @@ static int smacker_read_header(AVFormatContext *s) /* read and check header */ smk->magic = avio_rl32(pb); if (smk->magic != MKTAG('S', 'M', 'K', '2') && smk->magic != MKTAG('S', 'M', 'K', '4')) - return -1; + return AVERROR_INVALIDDATA; smk->width = avio_rl32(pb); smk->height = avio_rl32(pb); smk->frames = avio_rl32(pb); @@ -126,7 +126,7 @@ static int smacker_read_header(AVFormatContext *s) if(smk->treesize >= UINT_MAX/4){ // smk->treesize + 16 must not overflow (this check is probably redundant) av_log(s, AV_LOG_ERROR, "treesize too large\n"); - return -1; + return AVERROR_INVALIDDATA; } //FIXME remove extradata "rebuilding" @@ -142,7 +142,7 @@ static int smacker_read_header(AVFormatContext *s) /* setup data */ if(smk->frames > 0xFFFFFF) { av_log(s, AV_LOG_ERROR, "Too many frames: %"PRIu32"\n", smk->frames); - return -1; + return AVERROR_INVALIDDATA; } smk->frm_size = av_malloc(smk->frames * 4); smk->frm_flags = av_malloc(smk->frames); @@ -160,7 +160,7 @@ static int smacker_read_header(AVFormatContext *s) /* init video codec */ st = avformat_new_stream(s, NULL); if (!st) - return -1; + return AVERROR(ENOMEM); smk->videoindex = st->index; st->codecpar->width = smk->width; st->codecpar->height = smk->height; @@ -221,7 +221,7 @@ static int smacker_read_header(AVFormatContext *s) smk->treesize + 16); av_free(smk->frm_size); av_free(smk->frm_flags); - return -1; + return AVERROR(ENOMEM); } ret = avio_read(pb, st->codecpar->extradata + 16, st->codecpar->extradata_size - 16); if(ret != st->codecpar->extradata_size - 16){ From ec683ed527cef9aad208d1daeb10d0e7fb63e75e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 24 Sep 2017 12:58:42 +0200 Subject: [PATCH 0402/2557] smacker: fix integer overflow with pts_inc Bug-Id: 1073 Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind Signed-off-by: Sean McGovern --- libavformat/smacker.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavformat/smacker.c b/libavformat/smacker.c index 56c909bc06c76..304e746a91a83 100644 --- a/libavformat/smacker.c +++ b/libavformat/smacker.c @@ -117,6 +117,11 @@ static int smacker_read_header(AVFormatContext *s) smk->height = avio_rl32(pb); smk->frames = avio_rl32(pb); smk->pts_inc = (int32_t)avio_rl32(pb); + if (smk->pts_inc > INT_MAX / 100) { + av_log(s, AV_LOG_ERROR, "pts_inc %d is too large\n", smk->pts_inc); + return AVERROR_INVALIDDATA; + } + smk->flags = avio_rl32(pb); if(smk->flags & SMACKER_FLAG_RING_FRAME) smk->frames++; From 9ed18f302b09e444f5b1be01979cce62c4b2c04a Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 23 Sep 2017 16:46:11 +0100 Subject: [PATCH 0403/2557] cbs_h264: Fix writing streams with auxiliary pictures Tested with the alphaconformanceG sample. --- libavcodec/cbs_h2645.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 50a227da787e9..a1b887fd4c9f8 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -1002,7 +1002,7 @@ static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx, case H264_NAL_SPS_EXT: { - H264RawSPSExtension *sps_ext; + H264RawSPSExtension *sps_ext = unit->content; err = cbs_h264_write_sps_extension(ctx, pbc, sps_ext); if (err < 0) @@ -1026,6 +1026,7 @@ static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx, case H264_NAL_SLICE: case H264_NAL_IDR_SLICE: + case H264_NAL_AUXILIARY_SLICE: { H264RawSlice *slice = unit->content; BitstreamContext bc; From 9b1c0911146c0d7b4ede57ccfff6eac5b5304091 Mon Sep 17 00:00:00 2001 From: Jacek Jendrzej Date: Thu, 20 Jul 2017 13:46:46 +0200 Subject: [PATCH 0404/2557] http: Reset compressed header flag when starting to read a request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes redirects, where the original redirect response indicated support for compression, while the actual redirected content didn't. Signed-off-by: Martin Storsjö --- libavformat/http.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index 00cf29500151e..80c87f786aebf 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -682,6 +682,9 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, s->willclose = 0; s->end_chunked_post = 0; s->end_header = 0; +#if CONFIG_ZLIB + s->compressed = 0; +#endif if (post && !s->post_data && !send_expect_100) { /* Pretend that it did work. We didn't read any header yet, since * we've still to send the POST data, but the code calling this From 3cae7f8b9baaf43789490b676d8f5825f2e1bc2c Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 15 Aug 2017 18:14:32 +0100 Subject: [PATCH 0405/2557] cbs: Add some read/write tests Use the appropriate metadata filter for each codec - in the absence of any options to modify the stream, the output bitstream should be identical to the input (though the output file may differ in padding). All tests use conformance bitstreams, the MPEG-2 streams are newly added from the conformance test streams --- tests/Makefile | 1 + tests/fate/cbs.mak | 74 +++++++++++++++++++ tests/ref/fate/cbs-h264-AUD_MW_E | 1 + tests/ref/fate/cbs-h264-BASQP1_Sony_C | 1 + tests/ref/fate/cbs-h264-CABACI3_Sony_B | 1 + tests/ref/fate/cbs-h264-CVBS3_Sony_C | 1 + tests/ref/fate/cbs-h264-CVFC1_Sony_C | 1 + tests/ref/fate/cbs-h264-CVMANL1_TOSHIBA_B | 1 + tests/ref/fate/cbs-h264-CVNLFI1_Sony_C | 1 + tests/ref/fate/cbs-h264-CVSE2_Sony_B | 1 + tests/ref/fate/cbs-h264-CVWP1_TOSHIBA_E | 1 + tests/ref/fate/cbs-h264-FM1_BT_B | 1 + tests/ref/fate/cbs-h264-MR1_BT_A | 1 + tests/ref/fate/cbs-h264-SVA_Base_B | 1 + tests/ref/fate/cbs-h264-Sharp_MP_PAFF_1r2 | 1 + tests/ref/fate/cbs-h264-sp1_bt_a | 1 + tests/ref/fate/cbs-hevc-CAINIT_E_SHARP_3 | 1 + tests/ref/fate/cbs-hevc-CAINIT_H_SHARP_3 | 1 + tests/ref/fate/cbs-hevc-CONFWIN_A_Sony_1 | 1 + tests/ref/fate/cbs-hevc-HRD_A_Fujitsu_2 | 1 + tests/ref/fate/cbs-hevc-LTRPSPS_A_Qualcomm_1 | 1 + tests/ref/fate/cbs-hevc-NUT_A_ericsson_5 | 1 + tests/ref/fate/cbs-hevc-PICSIZE_A_Bossen_1 | 1 + tests/ref/fate/cbs-hevc-PICSIZE_B_Bossen_1 | 1 + tests/ref/fate/cbs-hevc-RPLM_A_qualcomm_4 | 1 + tests/ref/fate/cbs-hevc-RPS_A_docomo_4 | 1 + tests/ref/fate/cbs-hevc-RPS_E_qualcomm_5 | 1 + tests/ref/fate/cbs-hevc-SLIST_A_Sony_4 | 1 + tests/ref/fate/cbs-hevc-SLIST_D_Sony_9 | 1 + tests/ref/fate/cbs-hevc-STRUCT_A_Samsung_5 | 1 + tests/ref/fate/cbs-hevc-TILES_B_Cisco_1 | 1 + tests/ref/fate/cbs-hevc-WPP_A_ericsson_MAIN_2 | 1 + tests/ref/fate/cbs-hevc-WPP_F_ericsson_MAIN_2 | 1 + tests/ref/fate/cbs-hevc-WP_A_Toshiba_3 | 1 + tests/ref/fate/cbs-hevc-ipcm_E_NEC_2 | 1 + tests/ref/fate/cbs-mpeg2-hhi_burst_422_short | 1 + tests/ref/fate/cbs-mpeg2-sony-ct3 | 1 + tests/ref/fate/cbs-mpeg2-tcela-6 | 1 + 38 files changed, 111 insertions(+) create mode 100644 tests/fate/cbs.mak create mode 100644 tests/ref/fate/cbs-h264-AUD_MW_E create mode 100644 tests/ref/fate/cbs-h264-BASQP1_Sony_C create mode 100644 tests/ref/fate/cbs-h264-CABACI3_Sony_B create mode 100644 tests/ref/fate/cbs-h264-CVBS3_Sony_C create mode 100644 tests/ref/fate/cbs-h264-CVFC1_Sony_C create mode 100644 tests/ref/fate/cbs-h264-CVMANL1_TOSHIBA_B create mode 100644 tests/ref/fate/cbs-h264-CVNLFI1_Sony_C create mode 100644 tests/ref/fate/cbs-h264-CVSE2_Sony_B create mode 100644 tests/ref/fate/cbs-h264-CVWP1_TOSHIBA_E create mode 100644 tests/ref/fate/cbs-h264-FM1_BT_B create mode 100644 tests/ref/fate/cbs-h264-MR1_BT_A create mode 100644 tests/ref/fate/cbs-h264-SVA_Base_B create mode 100644 tests/ref/fate/cbs-h264-Sharp_MP_PAFF_1r2 create mode 100644 tests/ref/fate/cbs-h264-sp1_bt_a create mode 100644 tests/ref/fate/cbs-hevc-CAINIT_E_SHARP_3 create mode 100644 tests/ref/fate/cbs-hevc-CAINIT_H_SHARP_3 create mode 100644 tests/ref/fate/cbs-hevc-CONFWIN_A_Sony_1 create mode 100644 tests/ref/fate/cbs-hevc-HRD_A_Fujitsu_2 create mode 100644 tests/ref/fate/cbs-hevc-LTRPSPS_A_Qualcomm_1 create mode 100644 tests/ref/fate/cbs-hevc-NUT_A_ericsson_5 create mode 100644 tests/ref/fate/cbs-hevc-PICSIZE_A_Bossen_1 create mode 100644 tests/ref/fate/cbs-hevc-PICSIZE_B_Bossen_1 create mode 100644 tests/ref/fate/cbs-hevc-RPLM_A_qualcomm_4 create mode 100644 tests/ref/fate/cbs-hevc-RPS_A_docomo_4 create mode 100644 tests/ref/fate/cbs-hevc-RPS_E_qualcomm_5 create mode 100644 tests/ref/fate/cbs-hevc-SLIST_A_Sony_4 create mode 100644 tests/ref/fate/cbs-hevc-SLIST_D_Sony_9 create mode 100644 tests/ref/fate/cbs-hevc-STRUCT_A_Samsung_5 create mode 100644 tests/ref/fate/cbs-hevc-TILES_B_Cisco_1 create mode 100644 tests/ref/fate/cbs-hevc-WPP_A_ericsson_MAIN_2 create mode 100644 tests/ref/fate/cbs-hevc-WPP_F_ericsson_MAIN_2 create mode 100644 tests/ref/fate/cbs-hevc-WP_A_Toshiba_3 create mode 100644 tests/ref/fate/cbs-hevc-ipcm_E_NEC_2 create mode 100644 tests/ref/fate/cbs-mpeg2-hhi_burst_422_short create mode 100644 tests/ref/fate/cbs-mpeg2-sony-ct3 create mode 100644 tests/ref/fate/cbs-mpeg2-tcela-6 diff --git a/tests/Makefile b/tests/Makefile index d3f11efaaabe3..9fec13211f028 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -74,6 +74,7 @@ include $(SRC_PATH)/tests/fate/audio.mak include $(SRC_PATH)/tests/fate/bmp.mak include $(SRC_PATH)/tests/fate/build.mak include $(SRC_PATH)/tests/fate/canopus.mak +include $(SRC_PATH)/tests/fate/cbs.mak include $(SRC_PATH)/tests/fate/cdxl.mak include $(SRC_PATH)/tests/fate/checkasm.mak include $(SRC_PATH)/tests/fate/cover-art.mak diff --git a/tests/fate/cbs.mak b/tests/fate/cbs.mak new file mode 100644 index 0000000000000..afd5c5dd8fcc4 --- /dev/null +++ b/tests/fate/cbs.mak @@ -0,0 +1,74 @@ +# Read/write tests: this uses the codec metadata filter - with no +# arguments, it decomposes the stream fully and then recomposes it +# without making any changes. + +fate-cbs: fate-cbs-h264 fate-cbs-hevc fate-cbs-mpeg2 + +define FATE_CBS_TEST +# (codec, test_name, sample_file, output_format) +FATE_CBS_$(1) += fate-cbs-$(1)-$(2) +fate-cbs-$(1)-$(2): CMD = md5 -i $(TARGET_SAMPLES)/$(3) -c:v copy -bsf:v $(1)_metadata -f $(4) +endef + +# H.264 read/write + +FATE_CBS_H264_SAMPLES = \ + SVA_Base_B.264 \ + BASQP1_Sony_C.jsv \ + FM1_BT_B.h264 \ + CVFC1_Sony_C.jsv \ + AUD_MW_E.264 \ + CVBS3_Sony_C.jsv \ + MR1_BT_A.h264 \ + CVWP1_TOSHIBA_E.264 \ + CVNLFI1_Sony_C.jsv \ + Sharp_MP_PAFF_1r2.jvt \ + CVMANL1_TOSHIBA_B.264 \ + sp1_bt_a.h264 \ + CVSE2_Sony_B.jsv \ + CABACI3_Sony_B.jsv + +$(foreach N,$(FATE_CBS_H264_SAMPLES),$(eval $(call FATE_CBS_TEST,h264,$(basename $(N)),h264-conformance/$(N),h264))) + +FATE_SAMPLES_AVCONV += $(FATE_CBS_h264) +fate-cbs-h264: $(FATE_CBS_h264) + +# H.265 read/write + +FATE_CBS_HEVC_SAMPLES = \ + STRUCT_A_Samsung_5.bit \ + WP_A_Toshiba_3.bit \ + SLIST_A_Sony_4.bit \ + SLIST_D_Sony_9.bit \ + CAINIT_E_SHARP_3.bit \ + CAINIT_H_SHARP_3.bit \ + TILES_B_Cisco_1.bit \ + WPP_A_ericsson_MAIN_2.bit \ + WPP_F_ericsson_MAIN_2.bit \ + ipcm_E_NEC_2.bit \ + NUT_A_ericsson_5.bit \ + PICSIZE_A_Bossen_1.bit \ + PICSIZE_B_Bossen_1.bit \ + RPS_A_docomo_4.bit \ + RPS_E_qualcomm_5.bit \ + LTRPSPS_A_Qualcomm_1.bit \ + RPLM_A_qualcomm_4.bit \ + CONFWIN_A_Sony_1.bit \ + HRD_A_Fujitsu_2.bit + +$(foreach N,$(FATE_CBS_HEVC_SAMPLES),$(eval $(call FATE_CBS_TEST,hevc,$(basename $(N)),hevc-conformance/$(N),hevc))) + +FATE_SAMPLES_AVCONV += $(FATE_CBS_hevc) +fate-cbs-hevc: $(FATE_CBS_hevc) + +# MPEG-2 read/write + +FATE_CBS_MPEG2_SAMPLES = \ + hhi_burst_422_short.bits \ + sony-ct3.bs \ + tcela-6.bits + +$(foreach N,$(FATE_CBS_MPEG2_SAMPLES),$(eval $(call FATE_CBS_TEST,mpeg2,$(basename $(N)),mpeg2/$(N),mpeg2video))) + +FATE_SAMPLES_AVCONV += $(FATE_CBS_mpeg2) +fate-cbs-mpeg2: $(FATE_CBS_mpeg2) diff --git a/tests/ref/fate/cbs-h264-AUD_MW_E b/tests/ref/fate/cbs-h264-AUD_MW_E new file mode 100644 index 0000000000000..f204792416260 --- /dev/null +++ b/tests/ref/fate/cbs-h264-AUD_MW_E @@ -0,0 +1 @@ +9b8884667eda0b9853bec631458686ce diff --git a/tests/ref/fate/cbs-h264-BASQP1_Sony_C b/tests/ref/fate/cbs-h264-BASQP1_Sony_C new file mode 100644 index 0000000000000..c2185c770b08a --- /dev/null +++ b/tests/ref/fate/cbs-h264-BASQP1_Sony_C @@ -0,0 +1 @@ +00c52ae60bf9a41ae1145fbf5fea9838 diff --git a/tests/ref/fate/cbs-h264-CABACI3_Sony_B b/tests/ref/fate/cbs-h264-CABACI3_Sony_B new file mode 100644 index 0000000000000..59aeb721555ff --- /dev/null +++ b/tests/ref/fate/cbs-h264-CABACI3_Sony_B @@ -0,0 +1 @@ +2d94c80b858aec880530bad47afe3668 diff --git a/tests/ref/fate/cbs-h264-CVBS3_Sony_C b/tests/ref/fate/cbs-h264-CVBS3_Sony_C new file mode 100644 index 0000000000000..55f5e0b50e53a --- /dev/null +++ b/tests/ref/fate/cbs-h264-CVBS3_Sony_C @@ -0,0 +1 @@ +59ff1df9b25e80277cad4ad99e634df6 diff --git a/tests/ref/fate/cbs-h264-CVFC1_Sony_C b/tests/ref/fate/cbs-h264-CVFC1_Sony_C new file mode 100644 index 0000000000000..98004cf63c904 --- /dev/null +++ b/tests/ref/fate/cbs-h264-CVFC1_Sony_C @@ -0,0 +1 @@ +669f4f3d3ae35fa5a6f5c94e48776dcf diff --git a/tests/ref/fate/cbs-h264-CVMANL1_TOSHIBA_B b/tests/ref/fate/cbs-h264-CVMANL1_TOSHIBA_B new file mode 100644 index 0000000000000..14aa45300d839 --- /dev/null +++ b/tests/ref/fate/cbs-h264-CVMANL1_TOSHIBA_B @@ -0,0 +1 @@ +0c1d9694df747cc4697caf866bd3051a diff --git a/tests/ref/fate/cbs-h264-CVNLFI1_Sony_C b/tests/ref/fate/cbs-h264-CVNLFI1_Sony_C new file mode 100644 index 0000000000000..d5f5ad1931a3b --- /dev/null +++ b/tests/ref/fate/cbs-h264-CVNLFI1_Sony_C @@ -0,0 +1 @@ +7817d89bd749bc617a225978958a3af0 diff --git a/tests/ref/fate/cbs-h264-CVSE2_Sony_B b/tests/ref/fate/cbs-h264-CVSE2_Sony_B new file mode 100644 index 0000000000000..7845723edd80c --- /dev/null +++ b/tests/ref/fate/cbs-h264-CVSE2_Sony_B @@ -0,0 +1 @@ +ca8bdba497bd2f3b97c50d59692eb537 diff --git a/tests/ref/fate/cbs-h264-CVWP1_TOSHIBA_E b/tests/ref/fate/cbs-h264-CVWP1_TOSHIBA_E new file mode 100644 index 0000000000000..4cb9c475fcfbb --- /dev/null +++ b/tests/ref/fate/cbs-h264-CVWP1_TOSHIBA_E @@ -0,0 +1 @@ +01290611165b8d8ccba8468f3dae4c4d diff --git a/tests/ref/fate/cbs-h264-FM1_BT_B b/tests/ref/fate/cbs-h264-FM1_BT_B new file mode 100644 index 0000000000000..ce375b9080e60 --- /dev/null +++ b/tests/ref/fate/cbs-h264-FM1_BT_B @@ -0,0 +1 @@ +336a9b1373ee04af7b0b1de0da9a32f8 diff --git a/tests/ref/fate/cbs-h264-MR1_BT_A b/tests/ref/fate/cbs-h264-MR1_BT_A new file mode 100644 index 0000000000000..0532652e6cfc8 --- /dev/null +++ b/tests/ref/fate/cbs-h264-MR1_BT_A @@ -0,0 +1 @@ +699d37e66764ddb3b4265c299ca77dcd diff --git a/tests/ref/fate/cbs-h264-SVA_Base_B b/tests/ref/fate/cbs-h264-SVA_Base_B new file mode 100644 index 0000000000000..a591b811b12f8 --- /dev/null +++ b/tests/ref/fate/cbs-h264-SVA_Base_B @@ -0,0 +1 @@ +443e55dd5f63dccf9a62acbb48451b08 diff --git a/tests/ref/fate/cbs-h264-Sharp_MP_PAFF_1r2 b/tests/ref/fate/cbs-h264-Sharp_MP_PAFF_1r2 new file mode 100644 index 0000000000000..cc7d63931c79a --- /dev/null +++ b/tests/ref/fate/cbs-h264-Sharp_MP_PAFF_1r2 @@ -0,0 +1 @@ +fd01840ed6b086c3118b7c53c86d01f5 diff --git a/tests/ref/fate/cbs-h264-sp1_bt_a b/tests/ref/fate/cbs-h264-sp1_bt_a new file mode 100644 index 0000000000000..388c53aa5e756 --- /dev/null +++ b/tests/ref/fate/cbs-h264-sp1_bt_a @@ -0,0 +1 @@ +8405c5583d31d7015ed401b34b4ec93c diff --git a/tests/ref/fate/cbs-hevc-CAINIT_E_SHARP_3 b/tests/ref/fate/cbs-hevc-CAINIT_E_SHARP_3 new file mode 100644 index 0000000000000..f706e2b1dc5b6 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-CAINIT_E_SHARP_3 @@ -0,0 +1 @@ +52fc63c7b3e30c0550f4b708477846a5 diff --git a/tests/ref/fate/cbs-hevc-CAINIT_H_SHARP_3 b/tests/ref/fate/cbs-hevc-CAINIT_H_SHARP_3 new file mode 100644 index 0000000000000..6bd454ef3b588 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-CAINIT_H_SHARP_3 @@ -0,0 +1 @@ +c951f0cd30502cf3cebc9d700d3ed67e diff --git a/tests/ref/fate/cbs-hevc-CONFWIN_A_Sony_1 b/tests/ref/fate/cbs-hevc-CONFWIN_A_Sony_1 new file mode 100644 index 0000000000000..00445155d0a33 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-CONFWIN_A_Sony_1 @@ -0,0 +1 @@ +dce8104b2addbdd601eb280a88e18583 diff --git a/tests/ref/fate/cbs-hevc-HRD_A_Fujitsu_2 b/tests/ref/fate/cbs-hevc-HRD_A_Fujitsu_2 new file mode 100644 index 0000000000000..a30208dba4965 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-HRD_A_Fujitsu_2 @@ -0,0 +1 @@ +f150da624547ace5f7a983e714aa46be diff --git a/tests/ref/fate/cbs-hevc-LTRPSPS_A_Qualcomm_1 b/tests/ref/fate/cbs-hevc-LTRPSPS_A_Qualcomm_1 new file mode 100644 index 0000000000000..21dfa5763a83c --- /dev/null +++ b/tests/ref/fate/cbs-hevc-LTRPSPS_A_Qualcomm_1 @@ -0,0 +1 @@ +11b599202a4d25693123bea8bb003e54 diff --git a/tests/ref/fate/cbs-hevc-NUT_A_ericsson_5 b/tests/ref/fate/cbs-hevc-NUT_A_ericsson_5 new file mode 100644 index 0000000000000..6d4a7bf3d2076 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-NUT_A_ericsson_5 @@ -0,0 +1 @@ +e089d60eb3a4e0393954fca75dc9b362 diff --git a/tests/ref/fate/cbs-hevc-PICSIZE_A_Bossen_1 b/tests/ref/fate/cbs-hevc-PICSIZE_A_Bossen_1 new file mode 100644 index 0000000000000..13dc111b0d8d8 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-PICSIZE_A_Bossen_1 @@ -0,0 +1 @@ +df7bdc626044ff4a11644fd347219c0c diff --git a/tests/ref/fate/cbs-hevc-PICSIZE_B_Bossen_1 b/tests/ref/fate/cbs-hevc-PICSIZE_B_Bossen_1 new file mode 100644 index 0000000000000..4422ea3d3cfb3 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-PICSIZE_B_Bossen_1 @@ -0,0 +1 @@ +b7895403cc9f873eba468b54735cc481 diff --git a/tests/ref/fate/cbs-hevc-RPLM_A_qualcomm_4 b/tests/ref/fate/cbs-hevc-RPLM_A_qualcomm_4 new file mode 100644 index 0000000000000..bd8275e4cde50 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-RPLM_A_qualcomm_4 @@ -0,0 +1 @@ +7a6ca92743ed41e36d422025f639b229 diff --git a/tests/ref/fate/cbs-hevc-RPS_A_docomo_4 b/tests/ref/fate/cbs-hevc-RPS_A_docomo_4 new file mode 100644 index 0000000000000..772d16a192693 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-RPS_A_docomo_4 @@ -0,0 +1 @@ +97bd4fefd8cd95584f586027e244f283 diff --git a/tests/ref/fate/cbs-hevc-RPS_E_qualcomm_5 b/tests/ref/fate/cbs-hevc-RPS_E_qualcomm_5 new file mode 100644 index 0000000000000..f02190aa2b03d --- /dev/null +++ b/tests/ref/fate/cbs-hevc-RPS_E_qualcomm_5 @@ -0,0 +1 @@ +22199ff2b02e1cde89a2d8778a916c43 diff --git a/tests/ref/fate/cbs-hevc-SLIST_A_Sony_4 b/tests/ref/fate/cbs-hevc-SLIST_A_Sony_4 new file mode 100644 index 0000000000000..54ba416cb4a04 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-SLIST_A_Sony_4 @@ -0,0 +1 @@ +c589578c4d19daf6f1d001a60e694fae diff --git a/tests/ref/fate/cbs-hevc-SLIST_D_Sony_9 b/tests/ref/fate/cbs-hevc-SLIST_D_Sony_9 new file mode 100644 index 0000000000000..a29de5c8c93b7 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-SLIST_D_Sony_9 @@ -0,0 +1 @@ +49cd3af1ed065f2493e75986c81e48b6 diff --git a/tests/ref/fate/cbs-hevc-STRUCT_A_Samsung_5 b/tests/ref/fate/cbs-hevc-STRUCT_A_Samsung_5 new file mode 100644 index 0000000000000..6a4508b0c5c12 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-STRUCT_A_Samsung_5 @@ -0,0 +1 @@ +647eb851b935fd3bc6a98ce5ce45dbc7 diff --git a/tests/ref/fate/cbs-hevc-TILES_B_Cisco_1 b/tests/ref/fate/cbs-hevc-TILES_B_Cisco_1 new file mode 100644 index 0000000000000..d767e26d6839a --- /dev/null +++ b/tests/ref/fate/cbs-hevc-TILES_B_Cisco_1 @@ -0,0 +1 @@ +85a114def19cefbd0fb0daf8370d711c diff --git a/tests/ref/fate/cbs-hevc-WPP_A_ericsson_MAIN_2 b/tests/ref/fate/cbs-hevc-WPP_A_ericsson_MAIN_2 new file mode 100644 index 0000000000000..aadb0fe5587b7 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-WPP_A_ericsson_MAIN_2 @@ -0,0 +1 @@ +904128c902b6feed228215446db940ac diff --git a/tests/ref/fate/cbs-hevc-WPP_F_ericsson_MAIN_2 b/tests/ref/fate/cbs-hevc-WPP_F_ericsson_MAIN_2 new file mode 100644 index 0000000000000..024f132cbd1e3 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-WPP_F_ericsson_MAIN_2 @@ -0,0 +1 @@ +8fe3ada65124de5412886c892119c150 diff --git a/tests/ref/fate/cbs-hevc-WP_A_Toshiba_3 b/tests/ref/fate/cbs-hevc-WP_A_Toshiba_3 new file mode 100644 index 0000000000000..1507a2c446e9d --- /dev/null +++ b/tests/ref/fate/cbs-hevc-WP_A_Toshiba_3 @@ -0,0 +1 @@ +6ea47b7a46cd254b3348a86033a9aa56 diff --git a/tests/ref/fate/cbs-hevc-ipcm_E_NEC_2 b/tests/ref/fate/cbs-hevc-ipcm_E_NEC_2 new file mode 100644 index 0000000000000..cc68b6fb49deb --- /dev/null +++ b/tests/ref/fate/cbs-hevc-ipcm_E_NEC_2 @@ -0,0 +1 @@ +2e1f9c95364cfac2aa6e6ee3a52c43c4 diff --git a/tests/ref/fate/cbs-mpeg2-hhi_burst_422_short b/tests/ref/fate/cbs-mpeg2-hhi_burst_422_short new file mode 100644 index 0000000000000..c319fba7b3b09 --- /dev/null +++ b/tests/ref/fate/cbs-mpeg2-hhi_burst_422_short @@ -0,0 +1 @@ +e0c2fdd9baeba0c5ba5839a8cd7a72d3 diff --git a/tests/ref/fate/cbs-mpeg2-sony-ct3 b/tests/ref/fate/cbs-mpeg2-sony-ct3 new file mode 100644 index 0000000000000..b5b4b12f0737b --- /dev/null +++ b/tests/ref/fate/cbs-mpeg2-sony-ct3 @@ -0,0 +1 @@ +b1e15a09cfffbad801810af0928736ab diff --git a/tests/ref/fate/cbs-mpeg2-tcela-6 b/tests/ref/fate/cbs-mpeg2-tcela-6 new file mode 100644 index 0000000000000..530369d6728ac --- /dev/null +++ b/tests/ref/fate/cbs-mpeg2-tcela-6 @@ -0,0 +1 @@ +771b6756a63793e05b74e645794908a2 From 516c479172755c63063180b0c0953b68b670cdbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 29 Aug 2017 23:23:12 +0300 Subject: [PATCH 0406/2557] checkasm: Test more h264 idct variants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- tests/checkasm/h264dsp.c | 90 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/tests/checkasm/h264dsp.c b/tests/checkasm/h264dsp.c index c9ddd52a7fe61..f355a72a74a91 100644 --- a/tests/checkasm/h264dsp.c +++ b/tests/checkasm/h264dsp.c @@ -22,6 +22,7 @@ #include "checkasm.h" #include "libavcodec/avcodec.h" #include "libavcodec/h264dsp.h" +#include "libavcodec/h264data.h" #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" @@ -223,10 +224,97 @@ static void check_idct(void) } } } - report("idct"); +} + +static void check_idct_multiple(void) +{ + LOCAL_ALIGNED_16(uint8_t, dst_full, [16 * 16 * 2]); + LOCAL_ALIGNED_16(int16_t, coef_full, [16 * 16 * 2]); + LOCAL_ALIGNED_16(uint8_t, dst0, [16 * 16 * 2]); + LOCAL_ALIGNED_16(uint8_t, dst1, [16 * 16 * 2]); + LOCAL_ALIGNED_16(int16_t, coef0, [16 * 16 * 2]); + LOCAL_ALIGNED_16(int16_t, coef1, [16 * 16 * 2]); + LOCAL_ALIGNED_16(uint8_t, nnzc, [15 * 8]); + H264DSPContext h; + int bit_depth, i, y, func; + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, const int *block_offset, int16_t *block, int stride, const uint8_t nnzc[15*8]); + + for (bit_depth = 8; bit_depth <= 10; bit_depth++) { + ff_h264dsp_init(&h, bit_depth, 1); + for (func = 0; func < 3; func++) { + void (*idct)(uint8_t *, const int *, int16_t *, int, const uint8_t[]) = NULL; + const char *name; + int sz = 4, intra = 0; + int block_offset[16] = { 0 }; + switch (func) { + case 0: + idct = h.h264_idct_add16; + name = "h264_idct_add16"; + break; + case 1: + idct = h.h264_idct_add16intra; + name = "h264_idct_add16intra"; + intra = 1; + break; + case 2: + idct = h.h264_idct8_add4; + name = "h264_idct8_add4"; + sz = 8; + break; + } + memset(nnzc, 0, 15 * 8); + memset(coef_full, 0, 16 * 16 * SIZEOF_COEF); + for (i = 0; i < 16 * 16; i += sz * sz) { + uint8_t src[8 * 8 * 2]; + uint8_t dst[8 * 8 * 2]; + int16_t coef[8 * 8 * 2]; + int index = i / sz; + int block_y = (index / 16) * sz; + int block_x = index % 16; + int offset = (block_y * 16 + block_x) * SIZEOF_PIXEL; + int nnz = rnd() % 3; + + randomize_buffers(); + if (sz == 4) + dct4x4(coef, bit_depth); + else + dct8x8(coef, bit_depth); + + for (y = 0; y < sz; y++) + memcpy(&dst_full[offset + y * 16 * SIZEOF_PIXEL], + &dst[PIXEL_STRIDE * y], sz * SIZEOF_PIXEL); + + if (nnz > 1) + nnz = sz * sz; + memcpy(&coef_full[i * SIZEOF_COEF/sizeof(coef[0])], + coef, nnz * SIZEOF_COEF); + + if (intra && nnz == 1) + nnz = 0; + + nnzc[scan8[i / 16]] = nnz; + block_offset[i / 16] = offset; + } + + if (check_func(idct, "%s_%dbpp", name, bit_depth)) { + memcpy(coef0, coef_full, 16 * 16 * SIZEOF_COEF); + memcpy(coef1, coef_full, 16 * 16 * SIZEOF_COEF); + memcpy(dst0, dst_full, 16 * 16 * SIZEOF_PIXEL); + memcpy(dst1, dst_full, 16 * 16 * SIZEOF_PIXEL); + call_ref(dst0, block_offset, coef0, 16 * SIZEOF_PIXEL, nnzc); + call_new(dst1, block_offset, coef1, 16 * SIZEOF_PIXEL, nnzc); + if (memcmp(dst0, dst1, 16 * 16 * SIZEOF_PIXEL) || + memcmp(coef0, coef1, 16 * 16 * SIZEOF_COEF)) + fail(); + bench_new(dst1, block_offset, coef1, 16 * SIZEOF_PIXEL, nnzc); + } + } + } } void checkasm_check_h264dsp(void) { check_idct(); + check_idct_multiple(); + report("idct"); } From ccbb31c14b766ef666ef2daa8c467e478183a957 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 25 Sep 2017 09:57:30 +0000 Subject: [PATCH 0407/2557] qsv: Make sure the session is set with the latest version It is needed to have the calls to MFXJoinSession succeed. --- libavutil/hwcontext_qsv.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index e0f6875b40c87..5018a05b9aec5 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -1029,6 +1029,23 @@ static int qsv_device_derive_from_child(AVHWDeviceContext *ctx, goto fail; } + err = MFXQueryVersion(hwctx->session, &ver); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Error querying an MFX session: %d.\n", err); + ret = AVERROR_UNKNOWN; + goto fail; + } + + MFXClose(hwctx->session); + + err = MFXInit(implementation, &ver, &hwctx->session); + if (err != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, + "Error initializing an MFX session: %d.\n", err); + ret = AVERROR_UNKNOWN; + goto fail; + } + err = MFXVideoCORE_SetHandle(hwctx->session, handle_type, handle); if (err != MFX_ERR_NONE) { av_log(ctx, AV_LOG_ERROR, "Error setting child device handle: " From ea25ccd1b2a980df8d43cc1f86a23e3c094090a6 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sun, 24 Sep 2017 13:54:28 +0000 Subject: [PATCH 0408/2557] qsv: Join the derived session to the parent Should improve the performance on multiple transcoding from a single source. --- libavcodec/qsv.c | 5 +++++ libavfilter/qsvvpp.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index a8ae65622c915..96dca14e9ae24 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -593,6 +593,11 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, "Error setting a HW handle"); } + err = MFXJoinSession(parent_session, session); + if (err != MFX_ERR_NONE) + return ff_qsv_print_error(avctx, err, + "Error joining session"); + ret = qsv_load_plugins(session, load_plugins, avctx); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n"); diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index 0b639c2d67660..a96cfa65ded94 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -515,6 +515,9 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s) if (ret != MFX_ERR_NONE) return AVERROR_UNKNOWN; } + ret = MFXJoinSession(device_hwctx->session, s->session); + if (ret != MFX_ERR_NONE) + return AVERROR_UNKNOWN; if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) { s->opaque_alloc.In.Surfaces = s->surface_ptrs_in; From d41e10c1485ec34aa342f7bc2e5bf4f9b6e66414 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 27 Sep 2017 01:44:21 +0100 Subject: [PATCH 0409/2557] hevc: Fix aligned array declarations --- libavcodec/hevcdsp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/hevcdsp.c b/libavcodec/hevcdsp.c index 81db9e29a513f..558e9382da9a4 100644 --- a/libavcodec/hevcdsp.c +++ b/libavcodec/hevcdsp.c @@ -89,7 +89,7 @@ static const int8_t transform[32][32] = { 90, -90, 88, -85, 82, -78, 73, -67, 61, -54, 46, -38, 31, -22, 13, -4 }, }; -DECLARE_ALIGNED(16, const int16_t, ff_hevc_epel_coeffs[7][16]) = { +DECLARE_ALIGNED(16, const int16_t, ff_hevc_epel_coeffs)[7][16] = { { -2, 58, 10, -2, -2, 58, 10, -2, -2, 58, 10, -2, -2, 58, 10, -2 }, { -4, 54, 16, -2, -4, 54, 16, -2, -4, 54, 16, -2, -4, 54, 16, -2 }, { -6, 46, 28, -4, -6, 46, 28, -4, -6, 46, 28, -4, -6, 46, 28, -4 }, @@ -99,7 +99,7 @@ DECLARE_ALIGNED(16, const int16_t, ff_hevc_epel_coeffs[7][16]) = { { -2, 10, 58, -2, -2, 10, 58, -2, -2, 10, 58, -2, -2, 10, 58, -2 }, }; -DECLARE_ALIGNED(16, const int8_t, ff_hevc_epel_coeffs8[7][16]) = { +DECLARE_ALIGNED(16, const int8_t, ff_hevc_epel_coeffs8)[7][16] = { { -2, 58, 10, -2, -2, 58, 10, -2, -2, 58, 10, -2, -2, 58, 10, -2 }, { -4, 54, 16, -2, -4, 54, 16, -2, -4, 54, 16, -2, -4, 54, 16, -2 }, { -6, 46, 28, -4, -6, 46, 28, -4, -6, 46, 28, -4, -6, 46, 28, -4 }, @@ -109,13 +109,13 @@ DECLARE_ALIGNED(16, const int8_t, ff_hevc_epel_coeffs8[7][16]) = { { -2, 10, 58, -2, -2, 10, 58, -2, -2, 10, 58, -2, -2, 10, 58, -2 }, }; -DECLARE_ALIGNED(16, const int16_t, ff_hevc_qpel_coeffs[3][8]) = { +DECLARE_ALIGNED(16, const int16_t, ff_hevc_qpel_coeffs)[3][8] = { { -1, 4, -10, 58, 17, -5, 1, 0 }, { -1, 4, -11, 40, 40, -11, 4, -1 }, { 0, 1, -5, 17, 58, -10, 4, -1 }, }; -DECLARE_ALIGNED(16, const int8_t, ff_hevc_qpel_coeffs8[3][16]) = { +DECLARE_ALIGNED(16, const int8_t, ff_hevc_qpel_coeffs8)[3][16] = { { -1, 4, -10, 58, 17, -5, 1, 0, -1, 4, -10, 58, 17, -5, 1, 0 }, { -1, 4, -11, 40, 40, -11, 4, -1, -1, 4, -11, 40, 40, -11, 4, -1 }, { 0, 1, -5, 17, 58, -10, 4, -1, 0, 1, -5, 17, 58, -10, 4, -1 }, From 2068d116db9883c71cb00b76e7d371cc30164d08 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 27 Sep 2017 01:47:24 +0100 Subject: [PATCH 0410/2557] hapdec: Delete include for nonexistent file It exists as an alias for string.h in most C libraries, so usually this line is harmless. --- libavcodec/hapdec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/hapdec.c b/libavcodec/hapdec.c index 8f5365b269dfb..17707180c2d88 100644 --- a/libavcodec/hapdec.c +++ b/libavcodec/hapdec.c @@ -37,7 +37,6 @@ #include "bytestream.h" #include "hap.h" #include "internal.h" -#include "memory.h" #include "snappy.h" #include "texturedsp.h" #include "thread.h" From 92f0aceb36c6e4412d4cf346e70dc74b5a4069e9 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 27 Sep 2017 01:48:37 +0100 Subject: [PATCH 0411/2557] cinepakenc: Move declaration out of for initialisation statement --- libavcodec/cinepakenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index 00b3e75e4cc04..c323bde30f1b3 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -891,8 +891,9 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, #define SMALLEST_CODEBOOK 1 for (v1enough = 0, v1_size = SMALLEST_CODEBOOK; v1_size <= CODEBOOK_MAX && !v1enough; v1_size <<= 2) { for (v4enough = 0, v4_size = 0; v4_size <= v1_size && !v4enough; v4_size = v4_size ? v4_size << 2 : v1_size >= SMALLEST_CODEBOOK << 2 ? v1_size >> 2 : SMALLEST_CODEBOOK) { + CinepakMode mode; // try all modes - for (CinepakMode mode = 0; mode < MODE_COUNT; mode++) { + for (mode = 0; mode < MODE_COUNT; mode++) { // don't allow MODE_MC in intra frames if (keyframe && mode == MODE_MC) continue; From d66fe7ff53a5cade7a702100a9006dfe5ae1c473 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 29 Sep 2017 22:56:08 -0300 Subject: [PATCH 0412/2557] configure: Add test_pkg_config() This helper is split off check_pkg_config(), setting only the pkg CFLAGS and extralibs. This is useful for checks that do not require or do not benefit from setting global CFLAGS. Signed-off-by: James Almer Signed-off-by: Diego Biurrun --- configure | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/configure b/configure index a3cfe376802b0..aa87ac7279c4d 100755 --- a/configure +++ b/configure @@ -1025,8 +1025,8 @@ check_lib(){ enable $name && eval ${name}_extralibs="\$@" } -check_pkg_config(){ - log check_pkg_config "$@" +test_pkg_config(){ + log test_pkg_config "$@" name="$1" pkg_version="$2" pkg="${2%% *}" @@ -1039,8 +1039,15 @@ check_pkg_config(){ pkg_libs=$($pkg_config --libs $pkg_config_flags $pkg) check_func_headers "$headers" "$funcs" $pkg_cflags $pkg_libs "$@" && enable $name && - add_cflags "$pkg_cflags" && - eval $(sanitize_var_name ${name}_extralibs)="\$pkg_libs" + set_sanitized "${name}_cflags" $pkg_cflags && + set_sanitized "${name}_extralibs" $pkg_libs +} + +check_pkg_config(){ + log check_pkg_config "$@" + name="$1" + test_pkg_config "$@" && + eval add_cflags \$${name}_cflags } check_exec(){ From ebfcce16ac44b83f6e815c70e91231bed9fcbc97 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 29 Sep 2017 22:56:09 -0300 Subject: [PATCH 0413/2557] configure: Use test_pkg_config() for the SDL check Removes the extra code to preserve global CFLAGS. Signed-off-by: James Almer Signed-off-by: Diego Biurrun --- configure | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/configure b/configure index aa87ac7279c4d..4e91e318b09bb 100755 --- a/configure +++ b/configure @@ -4871,13 +4871,9 @@ if enabled nvenc; then require_cpp_condition nvEncodeAPI.h "NVENCAPI_MAJOR_VERSION >= 6" fi -# SDL is "special" and adds some CFLAGS that should not pollute anything else. -if enabled avplay; then - CFLAGS_SAVE=$CFLAGS - check_pkg_config sdl "sdl >= 1.2.1 sdl < 1.3.0" SDL_events.h SDL_PollEvent && - sdl_cflags=$pkg_cflags - CFLAGS=$CFLAGS_SAVE -fi +# SDL adds some CFLAGS that should not be part of the general CFLAGS. +enabled avplay && + test_pkg_config sdl "sdl >= 1.2.1 sdl < 1.3.0" SDL_events.h SDL_PollEvent ! disabled pod2man && check_cmd pod2man --help && enable pod2man || disable pod2man ! disabled texi2html && check_cmd texi2html -version && enable texi2html || disable texi2html From 3d828c9fd51aa8c348ff11241e212e5834b4f806 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 14 Sep 2017 16:51:26 -0300 Subject: [PATCH 0414/2557] cpu: split flag checks per arch in av_cpu_max_align() Signed-off-by: James Almer Signed-off-by: Luca Barbato --- libavutil/aarch64/cpu.c | 9 +++++++++ libavutil/arm/cpu.c | 9 +++++++++ libavutil/cpu.c | 15 ++++++++------- libavutil/cpu_internal.h | 5 +++++ libavutil/ppc/cpu.c | 9 +++++++++ libavutil/x86/cpu.c | 11 +++++++++++ 6 files changed, 51 insertions(+), 7 deletions(-) diff --git a/libavutil/aarch64/cpu.c b/libavutil/aarch64/cpu.c index 37a7d8defad8c..4718218255c5d 100644 --- a/libavutil/aarch64/cpu.c +++ b/libavutil/aarch64/cpu.c @@ -26,3 +26,12 @@ int ff_get_cpu_flags_aarch64(void) AV_CPU_FLAG_NEON * HAVE_NEON | AV_CPU_FLAG_VFP * HAVE_VFP; } + +size_t ff_get_cpu_max_align_aarch64(void) +{ + int flags = av_get_cpu_flags(); + + if (flags & AV_CPU_FLAG_NEON) + return 16; + return 8; +} diff --git a/libavutil/arm/cpu.c b/libavutil/arm/cpu.c index 2effb72610553..a29adf2761ff3 100644 --- a/libavutil/arm/cpu.c +++ b/libavutil/arm/cpu.c @@ -151,3 +151,12 @@ int ff_get_cpu_flags_arm(void) } #endif + +size_t ff_get_cpu_max_align_arm(void) +{ + int flags = av_get_cpu_flags(); + + if (flags & AV_CPU_FLAG_NEON) + return 16; + return 8; +} diff --git a/libavutil/cpu.c b/libavutil/cpu.c index 5aef6af217c98..fa76fecfc6232 100644 --- a/libavutil/cpu.c +++ b/libavutil/cpu.c @@ -184,12 +184,13 @@ int av_cpu_count(void) size_t av_cpu_max_align(void) { - int flags = av_get_cpu_flags(); - - if (flags & AV_CPU_FLAG_AVX) - return 32; - if (flags & (AV_CPU_FLAG_ALTIVEC | AV_CPU_FLAG_SSE | AV_CPU_FLAG_NEON)) - return 16; - + if (ARCH_AARCH64) + return ff_get_cpu_max_align_aarch64(); + if (ARCH_ARM) + return ff_get_cpu_max_align_arm(); + if (ARCH_PPC) + return ff_get_cpu_max_align_ppc(); + if (ARCH_X86) + return ff_get_cpu_max_align_x86(); return 8; } diff --git a/libavutil/cpu_internal.h b/libavutil/cpu_internal.h index 49c7b070e44a8..18c744a9837b4 100644 --- a/libavutil/cpu_internal.h +++ b/libavutil/cpu_internal.h @@ -41,4 +41,9 @@ int ff_get_cpu_flags_arm(void); int ff_get_cpu_flags_ppc(void); int ff_get_cpu_flags_x86(void); +size_t ff_get_cpu_max_align_aarch64(void); +size_t ff_get_cpu_max_align_arm(void); +size_t ff_get_cpu_max_align_ppc(void); +size_t ff_get_cpu_max_align_x86(void); + #endif /* AVUTIL_CPU_INTERNAL_H */ diff --git a/libavutil/ppc/cpu.c b/libavutil/ppc/cpu.c index 298185684b042..06ad370847c33 100644 --- a/libavutil/ppc/cpu.c +++ b/libavutil/ppc/cpu.c @@ -142,3 +142,12 @@ int ff_get_cpu_flags_ppc(void) #endif /* HAVE_ALTIVEC */ return 0; } + +size_t ff_get_cpu_max_align_ppc(void) +{ + int flags = av_get_cpu_flags(); + + if (flags & AV_CPU_FLAG_ALTIVEC) + return 16; + return 8; +} diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index 7c50fe38e26be..fa50eeb9dd88e 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -233,3 +233,14 @@ int ff_get_cpu_flags_x86(void) return rval; } + +size_t ff_get_cpu_max_align_x86(void) +{ + int flags = av_get_cpu_flags(); + + if (flags & AV_CPU_FLAG_AVX) + return 32; + if (flags & AV_CPU_FLAG_SSE) + return 16; + return 8; +} From 2014231039deeb6dccbf9f5368deb5f9e89d6cd0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 13 Sep 2017 17:07:19 -0300 Subject: [PATCH 0415/2557] extract_extradata: return an error when buffer allocation fails ret is 0 by default. Signed-off-by: James Almer Signed-off-by: Luca Barbato --- libavcodec/extract_extradata_bsf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c index 20840bd6af629..100c60d063bbf 100644 --- a/libavcodec/extract_extradata_bsf.c +++ b/libavcodec/extract_extradata_bsf.c @@ -101,14 +101,17 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, if (s->remove) { filtered_buf = av_buffer_alloc(pkt->size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!filtered_buf) + if (!filtered_buf) { + ret = AVERROR(ENOMEM); goto fail; + } filtered_data = filtered_buf->data; } extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!extradata) { av_buffer_unref(&filtered_buf); + ret = AVERROR(ENOMEM); goto fail; } From ab6422e1333e1c8b99e97ac61e3e9b2f6a2b4936 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 10 Oct 2017 13:56:46 -0300 Subject: [PATCH 0416/2557] configure: rename hevc_ps to hevcparse Build h2645_parse.o with it, as every hevc_ps dependency also needs it. This is more in line with h264's h264parse module. Signed-off-by: James Almer --- configure | 10 +++++----- libavcodec/Makefile | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/configure b/configure index 4e91e318b09bb..2333dafa4f9dc 100755 --- a/configure +++ b/configure @@ -1767,7 +1767,7 @@ CONFIG_EXTRA=" h264parse h264pred h264qpel - hevc_ps + hevcparse hpeldsp huffman huffyuvdsp @@ -1988,7 +1988,7 @@ faandct_select="fdctdsp" faanidct_deps="faan" faanidct_select="idctdsp" h264dsp_select="startcode" -hevc_ps_select="golomb" +hevcparse_select="golomb" intrax8_select="blockdsp idctdsp" mdct_select="fft" rdft_select="fft" @@ -2074,7 +2074,7 @@ h264_decoder_suggest="error_resilience" hap_decoder_select="snappy texturedsp" hap_encoder_deps="libsnappy" hap_encoder_select="texturedspenc" -hevc_decoder_select="bswapdsp cabac hevc_ps videodsp" +hevc_decoder_select="bswapdsp cabac hevcparse videodsp" huffyuv_decoder_select="bswapdsp huffyuvdsp" huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp" iac_decoder_select="imc_decoder" @@ -2299,7 +2299,7 @@ h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" h264_vaapi_encoder_select="cbs_h264 vaapi_encode" hevc_nvenc_encoder_deps="nvenc" hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser hevc_qsv_hwaccel qsvdec" -hevc_qsv_encoder_select="hevc_ps qsvenc" +hevc_qsv_encoder_select="hevcparse qsvenc" hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" hevc_vaapi_encoder_select="cbs_h265 vaapi_encode" mjpeg_qsv_encoder_deps="libmfx" @@ -2326,7 +2326,7 @@ nvenc_hevc_encoder_select="hevc_nvenc_encoder" # parsers aac_parser_select="adts_header" h264_parser_select="golomb h264dsp h264parse" -hevc_parser_select="hevc_ps" +hevc_parser_select="hevcparse" mpegaudio_parser_select="mpegaudioheader" mpegvideo_parser_select="mpegvideo" mpeg4video_parser_select="error_resilience h263dsp mpegvideo qpeldsp" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index c750abd2d3aff..d04902be08940 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -74,7 +74,7 @@ OBJS-$(CONFIG_H264DSP) += h264dsp.o h264idct.o OBJS-$(CONFIG_H264PARSE) += h264_parse.o h2645_parse.o h264_ps.o OBJS-$(CONFIG_H264PRED) += h264pred.o OBJS-$(CONFIG_H264QPEL) += h264qpel.o -OBJS-$(CONFIG_HEVC_PS) += hevc_ps.o +OBJS-$(CONFIG_HEVCPARSE) += h2645_parse.o hevc_ps.o OBJS-$(CONFIG_HPELDSP) += hpeldsp.o OBJS-$(CONFIG_HUFFMAN) += huffman.o OBJS-$(CONFIG_HUFFYUVDSP) += huffyuvdsp.o @@ -281,11 +281,11 @@ OBJS-$(CONFIG_HAP_DECODER) += hapdec.o hap.o OBJS-$(CONFIG_HAP_ENCODER) += hapenc.o hap.o OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o hevc_sei.o \ hevc_cabac.o hevc_refs.o hevcpred.o \ - hevcdsp.o hevc_filter.o h2645_parse.o hevc_data.o + hevcdsp.o hevc_filter.o hevc_data.o OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec_h2645.o OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \ - h2645_parse.o hevc_data.o + hevc_data.o OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadata.o hq_hqadsp.o \ @@ -751,7 +751,7 @@ OBJS-$(CONFIG_GSM_PARSER) += gsm_parser.o OBJS-$(CONFIG_H261_PARSER) += h261_parser.o OBJS-$(CONFIG_H263_PARSER) += h263_parser.o OBJS-$(CONFIG_H264_PARSER) += h264_parser.o h264_sei.o h264data.o -OBJS-$(CONFIG_HEVC_PARSER) += hevc_parser.o h2645_parse.o hevc_data.o +OBJS-$(CONFIG_HEVC_PARSER) += hevc_parser.o hevc_data.o OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o OBJS-$(CONFIG_MLP_PARSER) += mlp_parser.o mlp.o OBJS-$(CONFIG_MPEG4VIDEO_PARSER) += mpeg4video_parser.o h263.o \ From 09c98327b9f25c6c1716c0ee82ce09d8b484887a Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 24 Sep 2017 12:21:17 +0200 Subject: [PATCH 0417/2557] build: Drop support for Tru64 Unix (OSF/1) This proprietary Unix flavor dropped from the face of the earth more than a decade ago. Nothing of value was lost. --- configure | 42 ---------------------------------------- libavutil/intreadwrite.h | 5 ----- 2 files changed, 47 deletions(-) diff --git a/configure b/configure index 2333dafa4f9dc..ea303a0496de1 100755 --- a/configure +++ b/configure @@ -3158,24 +3158,6 @@ armasm_flags(){ done } -ccc_flags(){ - for flag; do - case $flag in - -std=c99) echo -c99 ;; - -mcpu=*) echo -arch ${flag#*=} ;; - -mieee) echo -ieee ;; - -O*|-fast) echo $flag ;; - -fno-math-errno) echo -assume nomath_errno ;; - -g) echo -g3 ;; - -Wall) echo -msg_enable level2 ;; - -Wno-pointer-sign) echo -msg_disable ptrmismatch1 ;; - -Wl,*) echo $flag ;; - -f*|-W*) ;; - *) echo $flag ;; - esac - done -} - cparser_flags(){ for flag; do case $flag in @@ -3358,13 +3340,6 @@ probe_cc(){ _ident=$($_cc -qversion 2>/dev/null | head -n1) _cflags_speed='-O5' _cflags_size='-O5 -qcompact' - elif $_cc -V 2>/dev/null | grep -q Compaq; then - _type=ccc - _ident=$($_cc -V | head -n1 | cut -d' ' -f1-3) - _DEPFLAGS='-M' - _cflags_speed='-fast' - _cflags_size='-O1' - _flags_filter=ccc_flags elif $_cc --vsn 2>/dev/null | grep -Eq "ARM (C/C\+\+ )?Compiler"; then test -d "$sysroot" || die "No valid sysroot specified." _type=armcc @@ -4156,9 +4131,6 @@ case $target_os in -l:drtaeabi.dso -l:scppnwdl.dso -lsupc++ -lgcc \ -l:libc.dso -l:libm.dso -l:euser.dso -l:libcrt0.lib ;; - osf1) - add_cppflags -D_OSF_SOURCE -D_POSIX_PII -D_REENTRANT - ;; minix) ;; none) @@ -4269,8 +4241,6 @@ case $libc_type in add_cppflags -D__builtin_memset=memset add_cppflags -D__gnuc_va_list=va_list -D_VA_LIST_DEFINED add_cflags -pds=48 # incompatible redefinition of macro - elif enabled ccc; then - add_ldflags -Wl,-z,now # calls to libots crash without this fi ;; esac @@ -5114,12 +5084,6 @@ if enabled icc; then check_cflags -falign-stack=maintain-16-byte || disable aligned_stack fi -elif enabled ccc; then - # disable some annoying warnings - add_cflags -msg_disable bitnotint - add_cflags -msg_disable mixfuncvoid - add_cflags -msg_disable nonstandcast - add_cflags -msg_disable unsupieee elif enabled gcc; then check_optflags -fno-tree-vectorize check_cflags -Werror=implicit-function-declaration @@ -5208,12 +5172,6 @@ case $ld_type in ;; esac -case $target_os in - osf1) - enabled ccc && add_ldflags '-Wl,-expect_unresolved,*' - ;; -esac - enabled asm || { arch=c; disable $ARCH_LIST $ARCH_EXT_LIST; } check_deps $CONFIG_LIST \ diff --git a/libavutil/intreadwrite.h b/libavutil/intreadwrite.h index fdb91d6bedff5..a9763172a812b 100644 --- a/libavutil/intreadwrite.h +++ b/libavutil/intreadwrite.h @@ -192,11 +192,6 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; # define AV_RN(s, p) (((const union unaligned_##s *) (p))->l) # define AV_WN(s, p, v) ((((union unaligned_##s *) (p))->l) = (v)) -#elif defined(__DECC) - -# define AV_RN(s, p) (*((const __unaligned uint##s##_t*)(p))) -# define AV_WN(s, p, v) (*((__unaligned uint##s##_t*)(p)) = (v)) - #elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_X64)) && AV_HAVE_FAST_UNALIGNED # define AV_RN(s, p) (*((const __unaligned uint##s##_t*)(p))) From fca9ca539c8c6e4fe0072486c7e0479a08a15e7c Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 24 Sep 2017 19:47:08 +0200 Subject: [PATCH 0418/2557] configure: Drop unused or internally-used entries from variable lists The variable lists are for variables whose values end up in output files. --- configure | 6 ------ 1 file changed, 6 deletions(-) diff --git a/configure b/configure index ea303a0496de1..b544fb8b91eed 100755 --- a/configure +++ b/configure @@ -1557,7 +1557,6 @@ HAVE_LIST_PUB=" HEADERS_LIST=" AVFoundation_AVFoundation_h - alsa_asoundlib_h arpa_inet_h cdio_paranoia_h cdio_paranoia_paranoia_h @@ -1579,7 +1578,6 @@ HEADERS_LIST=" machine_ioctl_meteor_h malloc_h poll_h - sndio_h soundcard_h stdatomic_h sys_mman_h @@ -1632,10 +1630,8 @@ SYSTEM_FUNCS=" clock_gettime closesocket CommandLineToArgvW - CoTaskMemFree CryptGenRandom fcntl - flt_lim fork getaddrinfo gethrtime @@ -1649,12 +1645,10 @@ SYSTEM_FUNCS=" gmtime_r inet_aton isatty - LoadLibrary localtime_r mach_absolute_time MapViewOfFile memalign - mkstemp mmap mprotect nanosleep From 4064f42889685e7122cfad4934b060098c147753 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 24 Sep 2017 19:39:29 +0200 Subject: [PATCH 0419/2557] build: Drop explicit check for dlfcn.h It is detected as a part of the libdl check. --- configure | 2 -- libavcodec/nvenc.c | 10 ++++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/configure b/configure index b544fb8b91eed..d0592347a1df4 100755 --- a/configure +++ b/configure @@ -1568,7 +1568,6 @@ HEADERS_LIST=" dev_video_bktr_ioctl_bt848_h dev_video_meteor_ioctl_meteor_h direct_h - dlfcn_h dxgidebug_h dxva_h gsm_h @@ -4658,7 +4657,6 @@ check_struct windows.h "CONDITION_VARIABLE" Ptr check_header d3d11.h check_header direct.h -check_header dlfcn.h check_header dxgidebug.h check_header dxva.h check_header dxva2api.h diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 884b344b96dae..a7171e4b1763e 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -28,12 +28,7 @@ #define CUDA_LIBNAME "libcuda.so" -#if HAVE_DLFCN_H -#include - -#define NVENC_LIBNAME "libnvidia-encode.so" - -#elif HAVE_WINDOWS_H +#if HAVE_WINDOWS_H #include #if ARCH_X86_64 @@ -45,6 +40,9 @@ #define dlopen(filename, flags) LoadLibrary((filename)) #define dlsym(handle, symbol) GetProcAddress(handle, symbol) #define dlclose(handle) FreeLibrary(handle) +#else +#include +#define NVENC_LIBNAME "libnvidia-encode.so" #endif #include "libavutil/common.h" From e7168d4c0cb279cf267690549ca92ad564572bc6 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 24 Sep 2017 19:55:25 +0200 Subject: [PATCH 0420/2557] configure: Drop redundant header check for d3d11.h It is detected as a part of the ID3D11VideoDecoder check. --- configure | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/configure b/configure index d0592347a1df4..16a5efa2ee6a5 100755 --- a/configure +++ b/configure @@ -1560,7 +1560,6 @@ HEADERS_LIST=" arpa_inet_h cdio_paranoia_h cdio_paranoia_paranoia_h - d3d11_h dispatch_dispatch_h dev_bktr_ioctl_bt848_h dev_bktr_ioctl_meteor_h @@ -2193,7 +2192,7 @@ zmbv_decoder_deps="zlib" zmbv_encoder_deps="zlib" # hardware accelerators -d3d11va_deps="d3d11_h dxva_h ID3D11VideoDecoder" +d3d11va_deps="dxva_h ID3D11VideoDecoder" dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32" vda_deps="VideoDecodeAcceleration_VDADecoder_h blocks_extension pthreads" vda_extralibs="-framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore" @@ -4655,7 +4654,6 @@ check_func_headers windows.h Sleep check_func_headers windows.h VirtualAlloc check_struct windows.h "CONDITION_VARIABLE" Ptr -check_header d3d11.h check_header direct.h check_header dxgidebug.h check_header dxva.h From 29ccc641b17afad058a5c24071ea827865a8b3a9 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 24 Sep 2017 20:13:40 +0200 Subject: [PATCH 0421/2557] build: Drop check for sys/mman.h in favor of mmap() check We already rely on just mmap() in other places. --- configure | 2 -- libswscale/utils.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/configure b/configure index 16a5efa2ee6a5..2f6f6e7fcadee 100755 --- a/configure +++ b/configure @@ -1578,7 +1578,6 @@ HEADERS_LIST=" poll_h soundcard_h stdatomic_h - sys_mman_h sys_param_h sys_resource_h sys_select_h @@ -4662,7 +4661,6 @@ check_header io.h check_header mach/mach_time.h check_header malloc.h check_header poll.h -check_header sys/mman.h check_header sys/param.h check_header sys/resource.h check_header sys/select.h diff --git a/libswscale/utils.c b/libswscale/utils.c index 786774f241618..d94be5a50ba42 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -27,7 +27,7 @@ #include #include #include -#if HAVE_SYS_MMAN_H +#if HAVE_MMAP #include #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) #define MAP_ANONYMOUS MAP_ANON From 8e97a8c69162afce47abea96c8c0914f3550e212 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 26 Sep 2017 12:13:07 +0200 Subject: [PATCH 0422/2557] build: Remove check for gsm/gsm.h for libgsm libgsm never installed more than a single header, the headers installed into the gsm/ subdirectory by some distros are private. Who started this nonsense is a mystery, but it got cargo-culted around ever since. --- configure | 5 +---- libavcodec/libgsmdec.c | 5 ----- libavcodec/libgsmenc.c | 5 ----- 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/configure b/configure index 2f6f6e7fcadee..45886edbc764e 100755 --- a/configure +++ b/configure @@ -1569,7 +1569,6 @@ HEADERS_LIST=" direct_h dxgidebug_h dxva_h - gsm_h io_h mach_mach_time_h machine_ioctl_bt848_h @@ -4756,9 +4755,7 @@ enabled libfaac && require libfaac "stdint.h faac.h" faacEncGetVersion enabled libfdk_aac && require_pkg_config libfdk_aac fdk-aac "fdk-aac/aacenc_lib.h" aacEncOpen enabled libfontconfig && require_pkg_config libfontconfig fontconfig "fontconfig/fontconfig.h" FcInit enabled libfreetype && require_pkg_config libfreetype freetype2 "ft2build.h FT_FREETYPE_H" FT_Init_FreeType -enabled libgsm && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do - check_lib libgsm "${gsm_hdr}" gsm_create -lgsm && break; - done || die "ERROR: libgsm not found"; } +enabled libgsm && require libgsm gsm._h gsm_create -lgsm enabled libhdcd && require_pkg_config libhdcd libhdcd "hdcd/hdcd_simple.h" hdcd_new enabled libilbc && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -lilbc enabled libkvazaar && require_pkg_config libkvazaar "kvazaar >= 0.8.1" kvazaar.h kvz_api_get diff --git a/libavcodec/libgsmdec.c b/libavcodec/libgsmdec.c index 4c21ff672858e..e06fe52762284 100644 --- a/libavcodec/libgsmdec.c +++ b/libavcodec/libgsmdec.c @@ -27,12 +27,7 @@ // The idiosyncrasies of GSM-in-WAV are explained at http://kbs.cs.tu-berlin.de/~jutta/toast.html -#include "config.h" -#if HAVE_GSM_H #include -#else -#include -#endif #include "libavutil/channel_layout.h" #include "libavutil/common.h" diff --git a/libavcodec/libgsmenc.c b/libavcodec/libgsmenc.c index 8f51321d468e7..4bb4075b2fdc3 100644 --- a/libavcodec/libgsmenc.c +++ b/libavcodec/libgsmenc.c @@ -27,12 +27,7 @@ // The idiosyncrasies of GSM-in-WAV are explained at http://kbs.cs.tu-berlin.de/~jutta/toast.html -#include "config.h" -#if HAVE_GSM_H #include -#else -#include -#endif #include "libavutil/common.h" From b586903ae1b89e2d8b99c79f33cabe9b3ca03784 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 26 Sep 2017 16:57:17 +0200 Subject: [PATCH 0423/2557] build: Drop redundant check for soundcard.h It should be sys/soundcard.h nowadays. --- configure | 6 ++---- libavdevice/oss.c | 8 +------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 45886edbc764e..37b3f20ba4848 100755 --- a/configure +++ b/configure @@ -1575,7 +1575,6 @@ HEADERS_LIST=" machine_ioctl_meteor_h malloc_h poll_h - soundcard_h stdatomic_h sys_param_h sys_resource_h @@ -2465,8 +2464,8 @@ jack_indev_deps="libjack" jack_indev_deps_any="sem_timedwait dispatch_dispatch_h" libcdio_indev_deps="libcdio" libdc1394_indev_deps="libdc1394" -oss_indev_deps_any="soundcard_h sys_soundcard_h" -oss_outdev_deps_any="soundcard_h sys_soundcard_h" +oss_indev_deps_any="sys_soundcard_h" +oss_outdev_deps_any="sys_soundcard_h" pulse_indev_deps="libpulse" sndio_indev_deps="sndio" sndio_outdev_deps="sndio" @@ -4857,7 +4856,6 @@ check_cpp_condition vfw.h "WM_CAP_DRIVER_CONNECT > WM_USER" && enable vfwcap_def check_header dev/ic/bt8xx.h check_header sys/soundcard.h -check_header soundcard.h enabled_any alsa_indev alsa_outdev && check_lib alsa alsa/asoundlib.h snd_pcm_htimestamp -lasound diff --git a/libavdevice/oss.c b/libavdevice/oss.c index eb8d4544223b4..e504438124f99 100644 --- a/libavdevice/oss.c +++ b/libavdevice/oss.c @@ -22,16 +22,10 @@ #include "config.h" #include - -#if HAVE_SOUNDCARD_H -#include -#else -#include -#endif - #include #include #include +#include #include "libavutil/log.h" From 421c10ed4fb0475a2cb055dd130ba12a6adb9f70 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 26 Sep 2017 17:22:43 +0200 Subject: [PATCH 0424/2557] configure: Drop test for fork() fork() is never used conditionally. --- configure | 2 -- 1 file changed, 2 deletions(-) diff --git a/configure b/configure index 37b3f20ba4848..b4cda14c01d1f 100755 --- a/configure +++ b/configure @@ -1627,7 +1627,6 @@ SYSTEM_FUNCS=" CommandLineToArgvW CryptGenRandom fcntl - fork getaddrinfo gethrtime getopt @@ -4617,7 +4616,6 @@ check_cpp_condition unistd.h "defined(_POSIX_MONOTONIC_CLOCK)" && check_lib clock_gettime time.h clock_gettime -lrt; } check_func fcntl -check_func fork check_func gethrtime check_func getopt check_func getrusage From 3e5950287317938e6b81e7ef8f024b403c303289 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 26 Sep 2017 18:14:41 +0200 Subject: [PATCH 0425/2557] configure: Drop unused attribute checks --- configure | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/configure b/configure index b4cda14c01d1f..1a2824c041542 100755 --- a/configure +++ b/configure @@ -1665,8 +1665,6 @@ TOOLCHAIN_FEATURES=" as_func as_object_arch asm_mod_q - attribute_may_alias - attribute_packed blocks_extension ebp_available ebx_available @@ -4295,14 +4293,6 @@ check_cc < Date: Wed, 4 Oct 2017 20:07:47 +0200 Subject: [PATCH 0426/2557] configure: Drop stray extralibs for libspeex These extralibs are set by pkg-config already. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 1a2824c041542..d3c968b3f4266 100755 --- a/configure +++ b/configure @@ -4760,7 +4760,7 @@ enabled libpulse && require_pkg_config libpulse libpulse-simple pulse/s enabled librtmp && require_pkg_config librtmp librtmp librtmp/rtmp.h RTMP_Socket enabled libschroedinger && require_pkg_config libschroedinger schroedinger-1.0 schroedinger/schro.h schro_init enabled libsnappy && require libsnappy snappy-c.h snappy_compress -lsnappy -enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init -lspeex +enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame enabled libvo_aacenc && require libvo_aacenc vo-aacenc/voAAC.h voGetAACEncAPI -lvo-aacenc From 76481f57b528168b00035aee76f7e0878669011f Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Thu, 5 Oct 2017 23:16:25 +0200 Subject: [PATCH 0427/2557] configure: Remove pointless empty *_COMPONENTS variables --- configure | 5 ----- 1 file changed, 5 deletions(-) diff --git a/configure b/configure index d3c968b3f4266..de3663e18a931 100755 --- a/configure +++ b/configure @@ -1242,16 +1242,11 @@ AVFORMAT_COMPONENTS=" protocols " -AVRESAMPLE_COMPONENTS="" -AVUTIL_COMPONENTS="" - COMPONENT_LIST=" $AVCODEC_COMPONENTS $AVDEVICE_COMPONENTS $AVFILTER_COMPONENTS $AVFORMAT_COMPONENTS - $AVRESAMPLE_COMPONENTS - $AVUTIL_COMPONENTS " EXAMPLE_LIST=" From 80154b1b3a0a9e83a9cbaff8b922440f60998128 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 11 Oct 2017 02:45:37 +0200 Subject: [PATCH 0428/2557] Bump version for master after 3.4 branchpoint Signed-off-by: Michael Niedermayer --- libavcodec/version.h | 2 +- libavdevice/version.h | 2 +- libavfilter/version.h | 2 +- libavformat/version.h | 2 +- libavresample/version.h | 2 +- libavutil/version.h | 2 +- libpostproc/version.h | 2 +- libswresample/version.h | 2 +- libswscale/version.h | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 10d9ac4eb3c04..594023ef26f0a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 57 -#define LIBAVCODEC_VERSION_MINOR 107 +#define LIBAVCODEC_VERSION_MINOR 108 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavdevice/version.h b/libavdevice/version.h index 9d900877af962..d3622c5395333 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVDEVICE_VERSION_MAJOR 57 -#define LIBAVDEVICE_VERSION_MINOR 10 +#define LIBAVDEVICE_VERSION_MINOR 11 #define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ diff --git a/libavfilter/version.h b/libavfilter/version.h index 3e67ad354c215..788d0a72d5bea 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 6 -#define LIBAVFILTER_VERSION_MINOR 107 +#define LIBAVFILTER_VERSION_MINOR 108 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavformat/version.h b/libavformat/version.h index 878917d65ddb1..828be14b209d1 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 57 -#define LIBAVFORMAT_VERSION_MINOR 83 +#define LIBAVFORMAT_VERSION_MINOR 84 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavresample/version.h b/libavresample/version.h index 20c78c74d3f5a..e8f43ee0ffb60 100644 --- a/libavresample/version.h +++ b/libavresample/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVRESAMPLE_VERSION_MAJOR 3 -#define LIBAVRESAMPLE_VERSION_MINOR 7 +#define LIBAVRESAMPLE_VERSION_MINOR 8 #define LIBAVRESAMPLE_VERSION_MICRO 0 #define LIBAVRESAMPLE_VERSION_INT AV_VERSION_INT(LIBAVRESAMPLE_VERSION_MAJOR, \ diff --git a/libavutil/version.h b/libavutil/version.h index f594dc069185f..bf5ea15abe98d 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -80,7 +80,7 @@ #define LIBAVUTIL_VERSION_MAJOR 55 -#define LIBAVUTIL_VERSION_MINOR 78 +#define LIBAVUTIL_VERSION_MINOR 79 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libpostproc/version.h b/libpostproc/version.h index e8f0abe81374f..a8f2fa4ea81af 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -29,7 +29,7 @@ #include "libavutil/avutil.h" #define LIBPOSTPROC_VERSION_MAJOR 54 -#define LIBPOSTPROC_VERSION_MINOR 7 +#define LIBPOSTPROC_VERSION_MINOR 8 #define LIBPOSTPROC_VERSION_MICRO 100 #define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \ diff --git a/libswresample/version.h b/libswresample/version.h index 6a66173f3bd13..46424ae28a193 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -29,7 +29,7 @@ #include "libavutil/avutil.h" #define LIBSWRESAMPLE_VERSION_MAJOR 2 -#define LIBSWRESAMPLE_VERSION_MINOR 9 +#define LIBSWRESAMPLE_VERSION_MINOR 10 #define LIBSWRESAMPLE_VERSION_MICRO 100 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ diff --git a/libswscale/version.h b/libswscale/version.h index 474e93b2615e3..23d5b0c4e9ee6 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -27,7 +27,7 @@ #include "libavutil/version.h" #define LIBSWSCALE_VERSION_MAJOR 4 -#define LIBSWSCALE_VERSION_MINOR 8 +#define LIBSWSCALE_VERSION_MINOR 9 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ From e4d5310a507d82656d670437c3a5f3b42b3fe060 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 11 Oct 2017 02:46:23 +0200 Subject: [PATCH 0429/2557] RELEASE: update for git after 3.4 branchpoint Signed-off-by: Michael Niedermayer --- RELEASE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE b/RELEASE index 48ea63d1809a3..9b601acc0df29 100644 --- a/RELEASE +++ b/RELEASE @@ -1 +1 @@ -3.3.git +3.4.git From 010baac12a14d684a1ae72f6b7509e642c40f3b3 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 11 Oct 2017 18:58:00 +0200 Subject: [PATCH 0430/2557] configure: Fix stupid typo in gsm.h header name --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index de3663e18a931..960c1ed0324ef 100755 --- a/configure +++ b/configure @@ -4737,7 +4737,7 @@ enabled libfaac && require libfaac "stdint.h faac.h" faacEncGetVersion enabled libfdk_aac && require_pkg_config libfdk_aac fdk-aac "fdk-aac/aacenc_lib.h" aacEncOpen enabled libfontconfig && require_pkg_config libfontconfig fontconfig "fontconfig/fontconfig.h" FcInit enabled libfreetype && require_pkg_config libfreetype freetype2 "ft2build.h FT_FREETYPE_H" FT_Init_FreeType -enabled libgsm && require libgsm gsm._h gsm_create -lgsm +enabled libgsm && require libgsm gsm.h gsm_create -lgsm enabled libhdcd && require_pkg_config libhdcd libhdcd "hdcd/hdcd_simple.h" hdcd_new enabled libilbc && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -lilbc enabled libkvazaar && require_pkg_config libkvazaar "kvazaar >= 0.8.1" kvazaar.h kvz_api_get From 58143b15adda6391ec07f3eb19e80ed91d801edd Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 10 Oct 2017 23:30:29 +0200 Subject: [PATCH 0431/2557] configure: remove libdl dependency from libndi_newtek We are not using dynamic loading for libndi. Reviewed-by: James Almer Signed-off-by: Marton Balint --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index e2ef54fb3b213..259619cccd0b0 100755 --- a/configure +++ b/configure @@ -3089,9 +3089,9 @@ decklink_indev_deps="decklink threads" decklink_indev_extralibs="-lstdc++" decklink_outdev_deps="decklink threads" decklink_outdev_extralibs="-lstdc++" -libndi_newtek_indev_deps="libndi_newtek libdl" +libndi_newtek_indev_deps="libndi_newtek" libndi_newtek_indev_extralibs="-lndi" -libndi_newtek_outdev_deps="libndi_newtek libdl" +libndi_newtek_outdev_deps="libndi_newtek" libndi_newtek_outdev_extralibs="-lndi" dshow_indev_deps="IBaseFilter" dshow_indev_extralibs="-lpsapi -lole32 -lstrmiids -luuid -loleaut32 -lshlwapi" From ef7766befde5f2f10c00517094d7153578a9aa94 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Oct 2017 19:35:56 -0300 Subject: [PATCH 0432/2557] fate: add missing closing bracket Regression since 85e2fe6281834ac7f16a12a332d9de4b2ec3cd29 Signed-off-by: James Almer --- tests/fate-run.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fate-run.sh b/tests/fate-run.sh index 51480b46c7f06..e8d2e677091f8 100755 --- a/tests/fate-run.sh +++ b/tests/fate-run.sh @@ -350,6 +350,7 @@ concat(){ else run ffprobe${PROGSUF} -bitexact -show_streams -show_packets -v 0 -of compact=p=0:nk=1 -fflags keepside -safe 0 $extra_args $concatfile fi +} null(){ : From 2b006ccf8318d84101ed83b75df4c9682a963217 Mon Sep 17 00:00:00 2001 From: Sasi Inguva Date: Tue, 10 Oct 2017 10:36:58 -0700 Subject: [PATCH 0433/2557] ffmpeg.c: Fallback to duration_dts, when duration_pts can't be determined. This is required for FLV files, for which duration_pts comes out to be zero. Signed-off-by: Sasi Inguva Reviewed-by: Thomas Mundt Signed-off-by: Michael Niedermayer --- fftools/ffmpeg.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 6d64bc1043ad0..3ee31473dc5c4 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2665,8 +2665,13 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo ist->next_dts = AV_NOPTS_VALUE; } - if (got_output) - ist->next_pts += av_rescale_q(duration_pts, ist->st->time_base, AV_TIME_BASE_Q); + if (got_output) { + if (duration_pts > 0) { + ist->next_pts += av_rescale_q(duration_pts, ist->st->time_base, AV_TIME_BASE_Q); + } else { + ist->next_pts += duration_dts; + } + } break; case AVMEDIA_TYPE_SUBTITLE: if (repeating) From 9054439bad3307dafd9fbadc57e66c276baf22e2 Mon Sep 17 00:00:00 2001 From: Ivan Kalvachev Date: Mon, 9 Oct 2017 01:25:00 +0300 Subject: [PATCH 0434/2557] Fix visual glitch with XvMC, caused by wrong idct permutation. In the past XvMC forced simple_idct since it was using FF_IDCT_PERM_NONE. However now we have SIMD variants of simple_idct that are using FF_IDCT_PERM_TRANSPOSE and if they are selected XvMC would get coefficients in the wrong order. The patch creates new FF_IDCT_NONE that is used only for this kind of hardware decoding and that fallbacks to the old C only simple idct. Signed-off-by: Ivan Kalvachev Signed-off-by: Michael Niedermayer --- libavcodec/avcodec.h | 1 + libavcodec/idctdsp.c | 1 + libavcodec/mpeg12dec.c | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 52cc5b0ca08ad..18c3e3ea1ee91 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3146,6 +3146,7 @@ typedef struct AVCodecContext { #if FF_API_ARCH_ALPHA #define FF_IDCT_SIMPLEALPHA 23 #endif +#define FF_IDCT_NONE 24 /* Used by XvMC to extract IDCT coefficients with FF_IDCT_PERM_NONE */ #define FF_IDCT_SIMPLEAUTO 128 /** diff --git a/libavcodec/idctdsp.c b/libavcodec/idctdsp.c index d596aed1a9e5a..0122d29efa325 100644 --- a/libavcodec/idctdsp.c +++ b/libavcodec/idctdsp.c @@ -279,6 +279,7 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) c->perm_type = FF_IDCT_PERM_NONE; #endif /* CONFIG_FAANIDCT */ } else { // accurate/default + /* Be sure FF_IDCT_NONE will select this one, since it uses FF_IDCT_PERM_NONE */ c->idct_put = ff_simple_idct_put_8; c->idct_add = ff_simple_idct_add_8; c->idct = ff_simple_idct_8; diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 22c29c1505283..4e68be27f1d26 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -1217,7 +1217,7 @@ static void setup_hwaccel_for_pixfmt(AVCodecContext *avctx) #endif ) if (avctx->idct_algo == FF_IDCT_AUTO) - avctx->idct_algo = FF_IDCT_SIMPLE; + avctx->idct_algo = FF_IDCT_NONE; if (avctx->hwaccel && avctx->pix_fmt == AV_PIX_FMT_XVMC) { Mpeg1Context *s1 = avctx->priv_data; From 734ed38931103c523c42333633a315a0ce1b5eb2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Oct 2017 22:23:51 -0300 Subject: [PATCH 0435/2557] configure: fix dependencies for v4l2_indev There's no indev named libv4l2. Fixes ticket #6729 Reviewed-by: bermond Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index dfbc251bb2254..9f95d58c6ee08 100755 --- a/configure +++ b/configure @@ -3116,7 +3116,7 @@ kmsgrab_indev_deps="libdrm" lavfi_indev_deps="avfilter" libcdio_indev_deps="libcdio" libdc1394_indev_deps="libdc1394" -libv4l2_indev_deps="libv4l2" +v4l2_indev_deps="libv4l2" openal_indev_deps="openal" opengl_outdev_deps="opengl" oss_indev_deps_any="soundcard_h sys_soundcard_h" From ce508f0bcc371c5e4399f14dd5e9f5b2aca16ab5 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Thu, 12 Oct 2017 12:43:09 +0200 Subject: [PATCH 0436/2557] lavc/proresdec2: Do not mix variable declaration and statement. Fixes ticket #6728. --- libavcodec/proresdec2.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index 0f791de97ba5f..e9e0153ee97f2 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -598,8 +598,9 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int } else { size_t mb_max_x = slice->mb_count << (mb_x_shift - 1); - for (size_t i = 0; i < 16; ++i) - for (size_t j = 0; j < mb_max_x; ++j) { + size_t i, j; + for (i = 0; i < 16; ++i) + for (j = 0; j < mb_max_x; ++j) { *(uint16_t*)(dest_u + (i * chroma_stride) + (j << 1)) = 511; *(uint16_t*)(dest_v + (i * chroma_stride) + (j << 1)) = 511; } From 25bd2f4f368ac350d635aaa50860ee642233dcc9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 12 Oct 2017 12:27:48 -0300 Subject: [PATCH 0437/2557] configure: add missing OpenCL dependency to libavutil Tested-by: wm4 Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 9f95d58c6ee08..2de19fab0f218 100755 --- a/configure +++ b/configure @@ -3340,7 +3340,7 @@ avformat_deps="avcodec avutil" avformat_suggest="libm network" avresample_deps="avutil" avresample_suggest="libm" -avutil_suggest="libm libdrm libmfx user32 vaapi videotoolbox wincrypt" +avutil_suggest="libm libdrm libmfx opencl user32 vaapi videotoolbox wincrypt" postproc_deps="avutil gpl" postproc_suggest="libm" swresample_deps="avutil" From 6fb580e7d3c4cead297620a7b982b2975c56b166 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 11 Oct 2017 22:28:29 -0300 Subject: [PATCH 0438/2557] configure: fix libxavs check libxavs may require pthreads and libm at link time, and without said ldflags available as global extralibs, the check will fail. Regression since 6dfcbd80ad446ff163b47f2bf432bbf706436ea8. Tested-by: Michael Niedermayer Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 2de19fab0f218..6deef0a1ec7f7 100755 --- a/configure +++ b/configure @@ -6098,7 +6098,7 @@ enabled libx264 && { use_pkg_config libx264 x264 "stdint.h x264.h" x26 enable libx262; } enabled libx265 && require_pkg_config libx265 x265 x265.h x265_api_get && require_cpp_condition x265.h "X265_BUILD >= 68" -enabled libxavs && require libxavs "stdint.h xavs.h" xavs_encoder_encode -lxavs +enabled libxavs && require libxavs "stdint.h xavs.h" xavs_encoder_encode "-lxavs $pthreads_extralibs $libm_extralibs" enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore enabled libzimg && require_pkg_config libzimg "zimg >= 2.3.0" zimg.h zimg_get_api_version enabled libzmq && require_pkg_config libzmq libzmq zmq.h zmq_ctx_new From a688b64fcf4abf0554b10d5446f019ec73121c1d Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 6 Oct 2017 01:52:45 +0200 Subject: [PATCH 0439/2557] configure: Drop feature for randomly disabling/enabling components This feature was never used for anything. --- configure | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/configure b/configure index 960c1ed0324ef..18939f2cf3d48 100755 --- a/configure +++ b/configure @@ -342,14 +342,6 @@ Developer options (useful when working on Libav itself): used only for debugging purposes) --enable-xmm-clobber-test check XMM registers for clobbering (Win64-only; should be used only for debugging purposes) - --enable-random randomly enable/disable components - --disable-random - --enable-random=LIST randomly enable/disable specific components or - --disable-random=LIST component groups. LIST is a comma-separated list - of NAME[:PROB] entries where NAME is a component - (group) and PROB the probability associated with - NAME (default 0.5). - --random-seed=VALUE seed value for --enable/disable-random --disable-valgrind-backtrace do not print a backtrace under Valgrind (only applies to --disable-optimizations builds) --ignore-tests=TESTS comma-separated list (without "fate-" prefix @@ -1855,7 +1847,6 @@ CMDLINE_SET=" optflags pkg_config pkg_config_flags - random_seed samples sysinclude sysroot @@ -2794,27 +2785,6 @@ show_list() { exit 0 } -rand_list(){ - IFS=', ' - set -- $* - unset IFS - for thing; do - comp=${thing%:*} - prob=${thing#$comp} - prob=${prob#:} - is_in ${comp} $COMPONENT_LIST && eval comp=\$$(toupper ${comp%s})_LIST - echo "prob ${prob:-0.5}" - printf '%s\n' $comp - done -} - -do_random(){ - action=$1 - shift - random_seed=$(awk "BEGIN { srand($random_seed); print srand() }") - $action $(rand_list "$@" | awk "BEGIN { srand($random_seed) } \$1 == \"prob\" { prob = \$2; next } rand() < prob { print }") -} - for opt do optval="${opt#*=}" case "$opt" in @@ -2846,14 +2816,6 @@ for opt do map 'eval unset \${$(toupper ${v%s})_LIST}' $COMPONENT_LIST disable $LIBRARY_LIST $PROGRAM_LIST doc ;; - --enable-random|--disable-random) - action=${opt%%-random} - do_random ${action#--} $COMPONENT_LIST - ;; - --enable-random=*|--disable-random=*) - action=${opt%%-random=*} - do_random ${action#--} $optval - ;; --enable-*=*|--disable-*=*) eval $(echo "${opt%%=*}" | sed 's/--/action=/;s/-/ thing=/') is_in "${thing}s" $COMPONENT_LIST || die_unknown "$opt" @@ -5287,9 +5249,6 @@ echo "shared ${shared-no}" echo "network support ${network-no}" echo "threading support ${thread_type-no}" echo "safe bitstream reader ${safe_bitstream_reader-no}" -test -n "$random_seed" && - echo "random seed ${random_seed}" -echo echo "External libraries:" print_enabled '' $EXTERNAL_LIBRARY_LIST | print_3_columns From 8594ec3dd59ed8ec303ca62587aaaf3045fce676 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 6 Oct 2017 01:57:40 +0200 Subject: [PATCH 0440/2557] configure: Drop fallback for deprecated avserver command line options --- configure | 5 ----- 1 file changed, 5 deletions(-) diff --git a/configure b/configure index 18939f2cf3d48..c061111a286aa 100755 --- a/configure +++ b/configure @@ -110,7 +110,6 @@ Program options: --disable-avconv disable avconv build --disable-avplay disable avplay build --disable-avprobe disable avprobe build - --disable-avserver deprecated, does nothing Component options: --disable-doc do not build documentation @@ -2823,10 +2822,6 @@ for opt do name=$(echo "${optval}" | sed "s/,/_${thing}|/g")_${thing} $action $(filter "$name" $list) ;; - --enable-avserver|--disable-avserver*) - warn "avserver has been removed, the ${opt} option is only"\ - "provided for compatibility and will be removed in the future" - ;; --enable-yasm|--disable-yasm) warn "The ${opt} option is only provided for compatibility and will be\n"\ "removed in the future. Use --enable-x86asm / --disable-x86asm instead." From 3613063e87307e5421707aa2ffb22054ad5d62b8 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 23 Sep 2017 17:05:00 +0200 Subject: [PATCH 0441/2557] configure: Simplify nvenc check (and move it to the correct spot) --- configure | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/configure b/configure index c061111a286aa..240410bf19768 100755 --- a/configure +++ b/configure @@ -4747,6 +4747,7 @@ enabled mmal && { check_lib mmal interface/mmal/mmal.h mmal_port_co check_lib mmal interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host; } || die "ERROR: mmal not found" && check_func_headers interface/mmal/mmal.h "MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS"; } +enabled nvenc && require_cpp_condition nvEncodeAPI.h "NVENCAPI_MAJOR_VERSION >= 6" enabled omx && require_header OMX_Core.h enabled omx_rpi && { check_header OMX_Core.h || { ! enabled cross_compile && add_cflags -isystem/opt/vc/include/IL && check_header OMX_Core.h ; } || @@ -4760,11 +4761,6 @@ enabled openssl && { { check_pkg_config openssl openssl openssl/ssl.h enabled gnutls && check_lib gmp gmp.h mpz_export -lgmp -if enabled nvenc; then - require_header nvEncodeAPI.h - require_cpp_condition nvEncodeAPI.h "NVENCAPI_MAJOR_VERSION >= 6" -fi - # SDL adds some CFLAGS that should not be part of the general CFLAGS. enabled avplay && test_pkg_config sdl "sdl >= 1.2.1 sdl < 1.3.0" SDL_events.h SDL_PollEvent From 4f6401df43d7ee9082ea591037b9f9284217d834 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 23 Sep 2017 17:07:50 +0200 Subject: [PATCH 0442/2557] configure: Merge separate parts of GnuTLS test --- configure | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 240410bf19768..bc29d1912f413 100755 --- a/configure +++ b/configure @@ -4686,7 +4686,8 @@ enabled avxsynth && require_header avxsynth/avxsynth_c.h enabled cuda && require cuda cuda.h cuInit -lcuda enabled cuvid && require cuvid cuviddec.h cuvidCreateDecoder -lnvcuvid enabled frei0r && require_header frei0r.h -enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init +enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init && + check_lib gmp gmp.h mpz_export -lgmp enabled libbs2b && require_pkg_config libbs2b libbs2b bs2b.h bs2b_open enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new enabled libdcadec && require libdcadec libdcadec/dca_context.h dcadec_context_create -ldcadec @@ -4759,8 +4760,6 @@ enabled openssl && { { check_pkg_config openssl openssl openssl/ssl.h check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 || die "ERROR: openssl not found"; } -enabled gnutls && check_lib gmp gmp.h mpz_export -lgmp - # SDL adds some CFLAGS that should not be part of the general CFLAGS. enabled avplay && test_pkg_config sdl "sdl >= 1.2.1 sdl < 1.3.0" SDL_events.h SDL_PollEvent From b46900914a1f25ce8dbf49d7c53766ff1f18b60f Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 7 Oct 2017 03:16:11 +0200 Subject: [PATCH 0443/2557] build: Merge mach/mach_time.h and mach_absolute_time() checks --- configure | 4 +--- libavutil/timer.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/configure b/configure index bc29d1912f413..c5d4e262d656a 100755 --- a/configure +++ b/configure @@ -1556,7 +1556,6 @@ HEADERS_LIST=" dxgidebug_h dxva_h io_h - mach_mach_time_h machine_ioctl_bt848_h machine_ioctl_meteor_h malloc_h @@ -4565,7 +4564,6 @@ check_func gettimeofday check_func gmtime_r check_func isatty check_func localtime_r -check_func mach_absolute_time check_func mkstemp check_func mmap check_func mprotect @@ -4579,6 +4577,7 @@ check_func sysctl check_func usleep check_func_headers io.h setmode +check_func_headers mach/mach_time.h mach_absolute_time check_func_headers stdlib.h getenv check_func_headers windows.h GetProcessAffinityMask @@ -4596,7 +4595,6 @@ check_header dxgidebug.h check_header dxva.h check_header dxva2api.h check_header io.h -check_header mach/mach_time.h check_header malloc.h check_header poll.h check_header sys/param.h diff --git a/libavutil/timer.h b/libavutil/timer.h index cc4c5a590156a..8468159d924a1 100644 --- a/libavutil/timer.h +++ b/libavutil/timer.h @@ -32,7 +32,7 @@ #include "config.h" -#if HAVE_MACH_MACH_TIME_H +#if HAVE_MACH_ABSOLUTE_TIME #include #endif From 62d5b5a9d3b0181335072d6fa792f2d805bc27b6 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 4 Oct 2017 02:03:53 +0200 Subject: [PATCH 0444/2557] configure: Extend check_header() to allow checking for multiple headers Also use that new capability to simplify bktr header checks. --- configure | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/configure b/configure index c5d4e262d656a..d5188c88180a7 100755 --- a/configure +++ b/configure @@ -929,13 +929,15 @@ check_stripflags(){ check_header(){ log check_header "$@" - header=$1 + headers=$1 shift - disable_sanitized $header - check_cpp "$@" < -int x; -EOF + disable_sanitized $headers + { + for hdr in $headers; do + print_include $hdr + done + echo "int x;" + } | check_cpp "$@" && enable_sanitized $headers } check_func(){ @@ -1128,9 +1130,9 @@ require(){ require_header(){ log require "$@" - header="$1" + headers="$1" shift - check_header "$header" "$@" || die "ERROR: $header not found" + check_header "$headers" "$@" || die "ERROR: $headers not found" } require_cpp_condition(){ @@ -4780,13 +4782,10 @@ check_lib vfw32 "windows.h vfw.h" capCreateCaptureWindow -lvfw32 check_cpp_condition vfw.h "WM_CAP_DRIVER_CONNECT > WM_USER" && enable vfwcap_defines # check for ioctl_meteor.h, ioctl_bt848.h and alternatives -{ check_header dev/bktr/ioctl_meteor.h && - check_header dev/bktr/ioctl_bt848.h; } || -{ check_header machine/ioctl_meteor.h && - check_header machine/ioctl_bt848.h; } || -{ check_header dev/video/meteor/ioctl_meteor.h && - check_header dev/video/bktr/ioctl_bt848.h; } || -check_header dev/ic/bt8xx.h +check_header "dev/bktr/ioctl_meteor.h dev/bktr/ioctl_bt848.h" || + check_header "machine/ioctl_meteor.h machine/ioctl_bt848.h" || + check_header "dev/video/meteor/ioctl_meteor.h dev/video/bktr/ioctl_bt848.h" || + check_header "dev/ic/bt8xx.h" check_header sys/soundcard.h From 93797681c2310faeeb0158f66f471965213904c6 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 24 Sep 2017 20:10:02 +0200 Subject: [PATCH 0445/2557] build: Rename stdatomic_h variable to stdatomic It does not represent a header but a complete system capability. --- configure | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/configure b/configure index d5188c88180a7..51b52744c0323 100755 --- a/configure +++ b/configure @@ -1562,7 +1562,6 @@ HEADERS_LIST=" machine_ioctl_meteor_h malloc_h poll_h - stdatomic_h sys_param_h sys_resource_h sys_select_h @@ -4612,7 +4611,7 @@ check_header windows.h # it seems there are versions of clang in some distros that try to use the # gcc headers, which explodes for stdatomic # so we also check that atomics actually work here -check_builtin stdatomic_h stdatomic.h "atomic_int foo; atomic_store(&foo, 0)" +check_builtin stdatomic stdatomic.h "atomic_int foo; atomic_store(&foo, 0)" check_lib ole32 "windows.h" CoTaskMemFree -lole32 check_lib shell32 "windows.h shellapi.h" CommandLineToArgvW -lshell32 @@ -5141,7 +5140,7 @@ for thread in $THREADS_LIST; do fi done -if disabled stdatomic_h; then +if disabled stdatomic; then if enabled atomics_gcc; then add_cppflags '-I\$(SRC_PATH)/compat/atomics/gcc' elif enabled atomics_win32; then From 7ac092d05de487d088bc96ab4a7bd6207fbfa98c Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 26 Sep 2017 18:24:24 +0200 Subject: [PATCH 0446/2557] build: CryptGenRandom --> wincrypt, it is a better name --- configure | 2 +- libavutil/random_seed.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 51b52744c0323..75f9fa91ebeb3 100755 --- a/configure +++ b/configure @@ -1611,7 +1611,6 @@ SYSTEM_FUNCS=" clock_gettime closesocket CommandLineToArgvW - CryptGenRandom fcntl getaddrinfo gethrtime @@ -1706,6 +1705,7 @@ HAVE_LIST=" vaapi_drm vaapi_x11 vdpau_x11 + wincrypt " # options emitted with CONFIG_ prefix but not available on the command line diff --git a/libavutil/random_seed.c b/libavutil/random_seed.c index 5bbdf38ec2d7d..089d883916e89 100644 --- a/libavutil/random_seed.c +++ b/libavutil/random_seed.c @@ -23,7 +23,7 @@ #if HAVE_UNISTD_H #include #endif -#if HAVE_CRYPTGENRANDOM +#if HAVE_WINCRYPT #include #include #endif @@ -96,7 +96,7 @@ uint32_t av_get_random_seed(void) { uint32_t seed; -#if HAVE_CRYPTGENRANDOM +#if HAVE_WINCRYPT HCRYPTPROV provider; if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { From f951837ce58e8588b175fb53a76fd453a81528ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 12 Oct 2017 11:03:08 +0300 Subject: [PATCH 0447/2557] configure: Don't add -fPIC to cflags for target_os=win32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We skipped adding it to cflags for mingw/cygwin configurations where the compiler either complains loudly or even errors out; do the same for target_os=win32, for the case when building with clang in msvc mode. This wasn't needed for the actual msvc before, since msvc uses msvc_common_flags to filter out this flag from cflags. When building with clang in msvc mode, no such filter is used. This fixes building shared libraries with clang in msvc mode. Signed-off-by: Martin Storsjö --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 75f9fa91ebeb3..4661d9942ff57 100755 --- a/configure +++ b/configure @@ -4215,7 +4215,7 @@ enable_weak_pic() { enable pic add_cppflags -DPIC case "$target_os" in - mingw*|cygwin*) + mingw*|cygwin*|win*) ;; *) add_cflags -fPIC From 0ca66409911e9fba940424be8bdfa54e056b0a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 12 Oct 2017 11:04:53 +0300 Subject: [PATCH 0448/2557] configure: Don't add -fPIC to asflags when targeting windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On X86 windows, asflags weren't actually ever used for anything, since assembling used x86asflags instead, and that flags list had -DPIC already. This fixes building shared libraries with clang for arm/aarch64 windows. (This wasn't an issue when in msvc mode before, since we don't try to enable pic at all there, since the msvc armasm assembler fails on our pic constructs there.) Signed-off-by: Martin Storsjö --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 4661d9942ff57..96b99b0501ad2 100755 --- a/configure +++ b/configure @@ -4219,9 +4219,9 @@ enable_weak_pic() { ;; *) add_cflags -fPIC + add_asflags -fPIC ;; esac - add_asflags -fPIC } enabled pic && enable_weak_pic From 40d5df67d2c4e1f0dd1e902435567eb5edad6a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 12 Oct 2017 11:08:32 +0300 Subject: [PATCH 0449/2557] configure: Add a comment about why we don't try to enable pic on arm on target_os=win32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 96b99b0501ad2..9b0b95a69e7fe 100755 --- a/configure +++ b/configure @@ -4357,6 +4357,7 @@ EOF .object_arch armv4 EOF + # MS armasm fails to assemble our PIC constructs [ $target_os != win32 ] && enabled_all armv6t2 shared !pic && enable_weak_pic elif enabled mips; then From a37e84be69310cd7de9540c8bc194cb0a6d158ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 13 Sep 2017 23:05:50 +0300 Subject: [PATCH 0450/2557] makedef: Add support for identifying the ARM64 machine type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since this machine type is 5 chars while the existing ones only were 3 (which the regexp assumed), the regexp has to be extended a little. Signed-off-by: Martin Storsjö --- compat/windows/makedef | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compat/windows/makedef b/compat/windows/makedef index fd7959a745fff..0cd169c15c000 100755 --- a/compat/windows/makedef +++ b/compat/windows/makedef @@ -74,12 +74,12 @@ else tr '\t' ' ' | grep '^ \+.\+machine \+(.\+)' | head -1 | - sed -e 's/^ \{1,\}.\{1,\} \{1,\}machine \{1,\}(\(...\)).*/\1/') + sed -e 's/^ \{1,\}.\{1,\} \{1,\}machine \{1,\}(\(.\{3,5\}\)).*/\1/') if [ "${arch}" = "x86" ]; then prefix="_" else - if [ "${arch}" != "ARM" ] && [ "${arch}" != "x64" ]; then + if [ "${arch}" != "ARM" ] && [ "${arch}" != "x64" ] && [ "${arch}" != "ARM64" ]; then echo "Unknown machine type." >&2 exit 1 fi From eb3c1a94adbc28411610167d3dac583436e50125 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 7 Feb 2017 15:49:09 +0100 Subject: [PATCH 0451/2557] pictor: Correctly check frame dimensions Fixes: 559/clusterfuzz-testcase-6424225917173760 Bug-Id: CVE-2017-7862 CC: libav-stable@libav.org Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/targets/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 8c2ea3030af7b40a3c4275696fb5c76cdb80950a) Signed-off-by: Diego Biurrun --- libavcodec/pictordec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/pictordec.c b/libavcodec/pictordec.c index 9477bc402d295..49547cf310697 100644 --- a/libavcodec/pictordec.c +++ b/libavcodec/pictordec.c @@ -140,7 +140,7 @@ static int decode_frame(AVCodecContext *avctx, avctx->pix_fmt = AV_PIX_FMT_PAL8; - if (s->width != avctx->width && s->height != avctx->height) { + if (s->width != avctx->width || s->height != avctx->height) { ret = ff_set_dimensions(avctx, s->width, s->height); if (ret < 0) return ret; From 4226c57b2b1f0b04a7d6dd4b1b3bcdab66bff424 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 12 Oct 2017 14:17:43 -0300 Subject: [PATCH 0452/2557] configure: add missing libfontconfig and libfreetype dependencies to showcqt filter Tested-by: Michael Niedermayer Signed-off-by: James Almer --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 7a1f4ba959ba4..a44519e178cac 100755 --- a/configure +++ b/configure @@ -3267,6 +3267,7 @@ scale_filter_deps="swscale" scale_qsv_filter_deps="libmfx" select_filter_select="pixelutils" showcqt_filter_deps="avcodec avformat swscale" +showcqt_filter_suggest="libfontconfig libfreetype" showcqt_filter_select="fft" showfreqs_filter_deps="avcodec" showfreqs_filter_select="fft" From c87bb9c04af804e2cd6a18110780ffb6d85109e3 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Thu, 12 Oct 2017 23:14:55 +0200 Subject: [PATCH 0453/2557] lavc/ppc/fft_init: Fix compilation on ppc64le with --disable-vsx. --- libavcodec/ppc/fft_init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/ppc/fft_init.c b/libavcodec/ppc/fft_init.c index 57d7c80ea4ccf..733e58b4c9c45 100644 --- a/libavcodec/ppc/fft_init.c +++ b/libavcodec/ppc/fft_init.c @@ -42,7 +42,7 @@ void ff_fft_calc_altivec(FFTContext *s, FFTComplex *z); void ff_fft_calc_interleave_altivec(FFTContext *s, FFTComplex *z); #endif -#if HAVE_GNU_AS && HAVE_ALTIVEC +#if HAVE_GNU_AS && HAVE_ALTIVEC && (HAVE_BIGENDIAN || HAVE_VSX) static void imdct_half_altivec(FFTContext *s, FFTSample *output, const FFTSample *input) { int j, k; @@ -146,11 +146,11 @@ static void imdct_calc_altivec(FFTContext *s, FFTSample *output, const FFTSample p1[k] = vec_perm(b, b, vcprm(3,2,1,0)); } } -#endif /* HAVE_GNU_AS && HAVE_ALTIVEC && HAVE_BIGENDIAN */ +#endif /* HAVE_GNU_AS && HAVE_ALTIVEC && (HAVE_BIGENDIAN || HAVE_VSX) */ av_cold void ff_fft_init_ppc(FFTContext *s) { -#if HAVE_GNU_AS && HAVE_ALTIVEC +#if HAVE_GNU_AS && HAVE_ALTIVEC && (HAVE_BIGENDIAN || HAVE_VSX) if (!PPC_ALTIVEC(av_get_cpu_flags())) return; From 3a6ded7cfcb33e06ade98c5791eae06453f65668 Mon Sep 17 00:00:00 2001 From: Ivan Kalvachev Date: Mon, 9 Oct 2017 02:40:26 +0300 Subject: [PATCH 0454/2557] Fix crash if av_vdpau_bind_context() is not used. The public functions av_alloc_vdpaucontext() and av_vdpau_alloc_context() are allocating AVVDPAUContext structure that is supposed to be placed in avctx->hwaccel_context. However the rest of libavcodec/vdpau.c uses avctx->hwaccel_context as struct VDPAUHWContext, that is bigger and does contain AVVDPAUContext as first member. The usage includes write to the new variables in the bigger stuct, without checking for block size. Fix by always allocating the bigger structure. Signed-off-by: Ivan Kalvachev --- libavcodec/vdpau.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c index 42ebddbeeee2e..4cc51cb79ed12 100644 --- a/libavcodec/vdpau.c +++ b/libavcodec/vdpau.c @@ -816,7 +816,7 @@ do { \ AVVDPAUContext *av_vdpau_alloc_context(void) { - return av_mallocz(sizeof(AVVDPAUContext)); + return av_mallocz(sizeof(VDPAUHWContext)); } int av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device, From 4b175913bed8df8c5d4f474d03963a0d99a87b3f Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 12 Oct 2017 17:32:10 -0300 Subject: [PATCH 0455/2557] build: fix builds configured with a suffix Regression since 6dfcbd80ad446ff163b47f2bf432bbf706436ea8 Tested-by: Michael Niedermayer Signed-off-by: James Almer --- ffbuild/common.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffbuild/common.mak b/ffbuild/common.mak index a6b23e029f02e..63a3c2f2d0ae8 100644 --- a/ffbuild/common.mak +++ b/ffbuild/common.mak @@ -119,7 +119,7 @@ FFLIBS := $($(NAME)_FFLIBS) $(FFLIBS-yes) $(FFLIBS) TESTPROGS += $(TESTPROGS-yes) LDLIBS = $(FFLIBS:%=%$(BUILDSUF)) -FFEXTRALIBS := $(FFLIBS:%=$(LD_LIB)) $(foreach lib,EXTRALIBS-$(NAME) $(FFLIBS:%=EXTRALIBS-%),$($(lib))) $(EXTRALIBS) +FFEXTRALIBS := $(LDLIBS:%=$(LD_LIB)) $(foreach lib,EXTRALIBS-$(NAME) $(FFLIBS:%=EXTRALIBS-%),$($(lib))) $(EXTRALIBS) OBJS := $(sort $(OBJS:%=$(SUBDIR)%)) SLIBOBJS := $(sort $(SLIBOBJS:%=$(SUBDIR)%)) From 368fb74831c037c1a1afd06da64c464c2b40d8b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Thu, 12 Oct 2017 20:45:53 +0200 Subject: [PATCH 0456/2557] lavc/pixlet: reduce diff with Libav (cosmetics only) --- libavcodec/pixlet.c | 271 +++++++++++++++++++++++--------------------- 1 file changed, 144 insertions(+), 127 deletions(-) diff --git a/libavcodec/pixlet.c b/libavcodec/pixlet.c index a9cfe085c9283..d2a5a1ac5d874 100644 --- a/libavcodec/pixlet.c +++ b/libavcodec/pixlet.c @@ -28,12 +28,14 @@ #include "avcodec.h" #include "bytestream.h" #include "get_bits.h" -#include "unary.h" #include "internal.h" #include "thread.h" +#include "unary.h" #define NB_LEVELS 4 +#define PIXLET_MAGIC 0xDEADBEEF + #define H 0 #define V 1 @@ -47,11 +49,11 @@ typedef struct PixletContext { AVClass *class; GetByteContext gb; - GetBitContext gbit; + GetBitContext bc; int levels; int depth; - int h, w; + int w, h; int16_t *filter[2]; int16_t *prediction; @@ -59,6 +61,31 @@ typedef struct PixletContext { SubBand band[4][NB_LEVELS * 3 + 1]; } PixletContext; +static av_cold int pixlet_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV420P16; + avctx->color_range = AVCOL_RANGE_JPEG; + return 0; +} + +static void free_buffers(AVCodecContext *avctx) +{ + PixletContext *ctx = avctx->priv_data; + + av_freep(&ctx->filter[0]); + av_freep(&ctx->filter[1]); + av_freep(&ctx->prediction); +} + +static av_cold int pixlet_close(AVCodecContext *avctx) +{ + PixletContext *ctx = avctx->priv_data; + free_buffers(avctx); + ctx->w = 0; + ctx->h = 0; + return 0; +} + static int init_decoder(AVCodecContext *avctx) { PixletContext *ctx = avctx->priv_data; @@ -72,19 +99,19 @@ static int init_decoder(AVCodecContext *avctx) for (plane = 0; plane < 3; plane++) { unsigned shift = plane > 0; - unsigned w = ctx->w >> shift; - unsigned h = ctx->h >> shift; + unsigned w = ctx->w >> shift; + unsigned h = ctx->h >> shift; - ctx->band[plane][0].width = w >> NB_LEVELS; - ctx->band[plane][0].height = h >> NB_LEVELS; - ctx->band[plane][0].size = (w >> NB_LEVELS) * (h >> NB_LEVELS); + ctx->band[plane][0].width = w >> NB_LEVELS; + ctx->band[plane][0].height = h >> NB_LEVELS; + ctx->band[plane][0].size = (w >> NB_LEVELS) * (h >> NB_LEVELS); for (i = 0; i < NB_LEVELS * 3; i++) { unsigned scale = ctx->levels - (i / 3); - ctx->band[plane][i + 1].width = w >> scale; - ctx->band[plane][i + 1].height = h >> scale; - ctx->band[plane][i + 1].size = (w >> scale) * (h >> scale); + ctx->band[plane][i + 1].width = w >> scale; + ctx->band[plane][i + 1].height = h >> scale; + ctx->band[plane][i + 1].size = (w >> scale) * (h >> scale); ctx->band[plane][i + 1].x = (w >> scale) * (((i + 1) % 3) != 2); ctx->band[plane][i + 1].y = (h >> scale) * (((i + 1) % 3) != 1); @@ -94,35 +121,11 @@ static int init_decoder(AVCodecContext *avctx) return 0; } -static void free_buffers(AVCodecContext *avctx) +static int read_low_coeffs(AVCodecContext *avctx, int16_t *dst, int size, + int width, ptrdiff_t stride) { PixletContext *ctx = avctx->priv_data; - - av_freep(&ctx->filter[0]); - av_freep(&ctx->filter[1]); - av_freep(&ctx->prediction); -} - -static av_cold int pixlet_close(AVCodecContext *avctx) -{ - PixletContext *ctx = avctx->priv_data; - free_buffers(avctx); - ctx->w = 0; - ctx->h = 0; - return 0; -} - -static av_cold int pixlet_init(AVCodecContext *avctx) -{ - avctx->pix_fmt = AV_PIX_FMT_YUV420P16; - avctx->color_range = AVCOL_RANGE_JPEG; - return 0; -} - -static int read_low_coeffs(AVCodecContext *avctx, int16_t *dst, int size, int width, ptrdiff_t stride) -{ - PixletContext *ctx = avctx->priv_data; - GetBitContext *b = &ctx->gbit; + GetBitContext *bc = &ctx->bc; unsigned cnt1, nbits, k, j = 0, i = 0; int64_t value, state = 3; int rlen, escape, flag = 0; @@ -130,45 +133,45 @@ static int read_low_coeffs(AVCodecContext *avctx, int16_t *dst, int size, int wi while (i < size) { nbits = FFMIN(ff_clz((state >> 8) + 3) ^ 0x1F, 14); - cnt1 = get_unary(b, 0, 8); + cnt1 = get_unary(bc, 0, 8); if (cnt1 < 8) { - value = show_bits(b, nbits); + value = show_bits(bc, nbits); if (value <= 1) { - skip_bits(b, nbits - 1); + skip_bits(bc, nbits - 1); escape = ((1 << nbits) - 1) * cnt1; } else { - skip_bits(b, nbits); + skip_bits(bc, nbits); escape = value + ((1 << nbits) - 1) * cnt1 - 1; } } else { - escape = get_bits(b, 16); + escape = get_bits(bc, 16); } - value = -((escape + flag) & 1) | 1; + value = -((escape + flag) & 1) | 1; dst[j++] = value * ((escape + flag + 1) >> 1); i++; if (j == width) { - j = 0; + j = 0; dst += stride; } state = 120 * (escape + flag) + state - (120 * state >> 8); - flag = 0; + flag = 0; if (state * 4ULL > 0xFF || i >= size) continue; - nbits = ((state + 8) >> 5) + (state ? ff_clz(state) : 32) - 24; + nbits = ((state + 8) >> 5) + (state ? ff_clz(state) : 32) - 24; escape = av_mod_uintp2(16383, nbits); - cnt1 = get_unary(b, 0, 8); + cnt1 = get_unary(bc, 0, 8); if (cnt1 > 7) { - rlen = get_bits(b, 16); + rlen = get_bits(bc, 16); } else { - value = show_bits(b, nbits); + value = show_bits(bc, nbits); if (value > 1) { - skip_bits(b, nbits); + skip_bits(bc, nbits); rlen = value + escape * cnt1 - 1; } else { - skip_bits(b, nbits - 1); + skip_bits(bc, nbits - 1); rlen = escape * cnt1; } } @@ -180,31 +183,32 @@ static int read_low_coeffs(AVCodecContext *avctx, int16_t *dst, int size, int wi for (k = 0; k < rlen; k++) { dst[j++] = 0; if (j == width) { - j = 0; + j = 0; dst += stride; } } state = 0; - flag = rlen < 0xFFFF ? 1 : 0; + flag = rlen < 0xFFFF ? 1 : 0; } - align_get_bits(b); - return get_bits_count(b) >> 3; + align_get_bits(bc); + return get_bits_count(bc) >> 3; } -static int read_high_coeffs(AVCodecContext *avctx, uint8_t *src, int16_t *dst, int size, - int c, int a, int d, +static int read_high_coeffs(AVCodecContext *avctx, uint8_t *src, int16_t *dst, + int size, int c, int a, int d, int width, ptrdiff_t stride) { PixletContext *ctx = avctx->priv_data; - GetBitContext *b = &ctx->gbit; + GetBitContext *bc = &ctx->bc; unsigned cnt1, shbits, rlen, nbits, length, i = 0, j = 0, k; int ret, escape, pfx, value, yflag, xflag, flag = 0; int64_t state = 3, tmp; - if ((ret = init_get_bits8(b, src, bytestream2_get_bytes_left(&ctx->gb))) < 0) - return ret; + ret = init_get_bits8(bc, src, bytestream2_get_bytes_left(&ctx->gb)); + if (ret < 0) + return ret; if (a ^ (a >> 31)) { nbits = 33 - ff_clz(a ^ (a >> 31)); @@ -217,26 +221,24 @@ static int read_high_coeffs(AVCodecContext *avctx, uint8_t *src, int16_t *dst, i length = 25 - nbits; while (i < size) { - if (state >> 8 != -3) { + if (state >> 8 != -3) value = ff_clz((state >> 8) + 3) ^ 0x1F; - } else { + else value = -1; - } - - cnt1 = get_unary(b, 0, length); + cnt1 = get_unary(bc, 0, length); if (cnt1 >= length) { - cnt1 = get_bits(b, nbits); + cnt1 = get_bits(bc, nbits); } else { pfx = 14 + ((((uint64_t)(value - 14)) >> 32) & (value - 14)); if (pfx < 1 || pfx > 25) return AVERROR_INVALIDDATA; cnt1 *= (1 << pfx) - 1; - shbits = show_bits(b, pfx); + shbits = show_bits(bc, pfx); if (shbits <= 1) { - skip_bits(b, pfx - 1); + skip_bits(bc, pfx - 1); } else { - skip_bits(b, pfx); + skip_bits(bc, pfx); cnt1 += shbits - 1; } } @@ -248,14 +250,14 @@ static int read_high_coeffs(AVCodecContext *avctx, uint8_t *src, int16_t *dst, i value = 0; } else { xflag &= 1u; - tmp = (int64_t)c * ((yflag + 1) >> 1) + (c >> 1); - value = xflag + (tmp ^ -xflag); + tmp = (int64_t)c * ((yflag + 1) >> 1) + (c >> 1); + value = xflag + (tmp ^ -xflag); } i++; dst[j++] = value; if (j == width) { - j = 0; + j = 0; dst += stride; } state += (int64_t)d * (uint64_t)yflag - ((int64_t)(d * (uint64_t)state) >> 8); @@ -265,25 +267,26 @@ static int read_high_coeffs(AVCodecContext *avctx, uint8_t *src, int16_t *dst, i if ((uint64_t)state > 0xFF / 4 || i >= size) continue; - pfx = ((state + 8) >> 5) + (state ? ff_clz(state): 32) - 24; + pfx = ((state + 8) >> 5) + (state ? ff_clz(state) : 32) - 24; escape = av_mod_uintp2(16383, pfx); - cnt1 = get_unary(b, 0, 8); + cnt1 = get_unary(bc, 0, 8); if (cnt1 < 8) { if (pfx < 1 || pfx > 25) return AVERROR_INVALIDDATA; - value = show_bits(b, pfx); + + value = show_bits(bc, pfx); if (value > 1) { - skip_bits(b, pfx); + skip_bits(bc, pfx); rlen = value + escape * cnt1 - 1; } else { - skip_bits(b, pfx - 1); + skip_bits(bc, pfx - 1); rlen = escape * cnt1; } } else { - if (get_bits1(b)) - value = get_bits(b, 16); + if (get_bits1(bc)) + value = get_bits(bc, 16); else - value = get_bits(b, 8); + value = get_bits(bc, 8); rlen = value + 8 * escape; } @@ -295,20 +298,21 @@ static int read_high_coeffs(AVCodecContext *avctx, uint8_t *src, int16_t *dst, i for (k = 0; k < rlen; k++) { dst[j++] = 0; if (j == width) { - j = 0; + j = 0; dst += stride; } } state = 0; - flag = rlen < 0xFFFF ? 1 : 0; + flag = rlen < 0xFFFF ? 1 : 0; } - align_get_bits(b); - return get_bits_count(b) >> 3; + align_get_bits(bc); + return get_bits_count(bc) >> 3; } -static int read_highpass(AVCodecContext *avctx, uint8_t *ptr, int plane, AVFrame *frame) +static int read_highpass(AVCodecContext *avctx, uint8_t *ptr, + int plane, AVFrame *frame) { PixletContext *ctx = avctx->priv_data; ptrdiff_t stride = frame->linesize[plane] / 2; @@ -319,15 +323,16 @@ static int read_highpass(AVCodecContext *avctx, uint8_t *ptr, int plane, AVFrame int32_t b = bytestream2_get_be32(&ctx->gb); int32_t c = bytestream2_get_be32(&ctx->gb); int32_t d = bytestream2_get_be32(&ctx->gb); - int16_t *dest = (int16_t *)frame->data[plane] + ctx->band[plane][i + 1].x + - stride * ctx->band[plane][i + 1].y; + int16_t *dest = (int16_t *)frame->data[plane] + + ctx->band[plane][i + 1].x + + ctx->band[plane][i + 1].y * stride; unsigned size = ctx->band[plane][i + 1].size; - uint32_t magic; + uint32_t magic = bytestream2_get_be32(&ctx->gb); - magic = bytestream2_get_be32(&ctx->gb); - if (magic != 0xDEADBEEF) { - av_log(avctx, AV_LOG_ERROR, "wrong magic number: 0x%08"PRIX32 - " for plane %d, band %d\n", magic, plane, i); + if (magic != PIXLET_MAGIC) { + av_log(avctx, AV_LOG_ERROR, + "wrong magic number: 0x%08"PRIX32" for plane %d, band %d\n", + magic, plane, i); return AVERROR_INVALIDDATA; } @@ -338,7 +343,9 @@ static int read_highpass(AVCodecContext *avctx, uint8_t *ptr, int plane, AVFrame c, (b >= FFABS(a)) ? b : a, d, ctx->band[plane][i + 1].width, stride); if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "error in highpass coefficients for plane %d, band %d\n", plane, i); + av_log(avctx, AV_LOG_ERROR, + "error in highpass coefficients for plane %d, band %d\n", + plane, i); return ret; } bytestream2_skip(&ctx->gb, ret); @@ -347,7 +354,8 @@ static int read_highpass(AVCodecContext *avctx, uint8_t *ptr, int plane, AVFrame return 0; } -static void lowpass_prediction(int16_t *dst, int16_t *pred, int width, int height, ptrdiff_t stride) +static void lowpass_prediction(int16_t *dst, int16_t *pred, + int width, int height, ptrdiff_t stride) { int16_t val; int i, j; @@ -373,8 +381,8 @@ static void filterfn(int16_t *dest, int16_t *tmp, unsigned size, int64_t scale) int64_t value; hsize = size >> 1; - low = tmp + 4; - high = &low[hsize + 8]; + low = tmp + 4; + high = &low[hsize + 8]; memcpy(low, dest, size); memcpy(high, dest + hsize, size); @@ -411,29 +419,28 @@ static void filterfn(int16_t *dest, int16_t *tmp, unsigned size, int64_t scale) } } -static void reconstruction(AVCodecContext *avctx, - int16_t *dest, unsigned width, unsigned height, ptrdiff_t stride, int nb_levels, - int64_t *scaling_H, int64_t *scaling_V) +static void reconstruction(AVCodecContext *avctx, int16_t *dest, + unsigned width, unsigned height, ptrdiff_t stride, int nb_levels, + int64_t *scaling_h, int64_t *scaling_v) { PixletContext *ctx = avctx->priv_data; unsigned scaled_width, scaled_height; - int64_t scale_H, scale_V; int16_t *ptr, *tmp; int i, j, k; - scaled_height = height >> nb_levels; scaled_width = width >> nb_levels; - tmp = ctx->filter[0]; + scaled_height = height >> nb_levels; + tmp = ctx->filter[0]; for (i = 0; i < nb_levels; i++) { + int64_t scale_v = scaling_v[i]; + int64_t scale_h = scaling_h[i]; scaled_width <<= 1; scaled_height <<= 1; - scale_H = scaling_H[i]; - scale_V = scaling_V[i]; ptr = dest; for (j = 0; j < scaled_height; j++) { - filterfn(ptr, ctx->filter[1], scaled_width, scale_V); + filterfn(ptr, ctx->filter[1], scaled_width, scale_v); ptr += stride; } @@ -441,10 +448,10 @@ static void reconstruction(AVCodecContext *avctx, ptr = dest + j; for (k = 0; k < scaled_height; k++) { tmp[k] = *ptr; - ptr += stride; + ptr += stride; } - filterfn(tmp, ctx->filter[1], scaled_height, scale_H); + filterfn(tmp, ctx->filter[1], scaled_height, scale_h); ptr = dest + j; for (k = 0; k < scaled_height; k++) { @@ -501,11 +508,12 @@ static void postprocess_chroma(AVFrame *frame, int w, int h, int depth) } } -static int decode_plane(AVCodecContext *avctx, int plane, AVPacket *avpkt, AVFrame *frame) +static int decode_plane(AVCodecContext *avctx, int plane, + AVPacket *avpkt, AVFrame *frame) { PixletContext *ctx = avctx->priv_data; - ptrdiff_t stride = frame->linesize[plane] / 2; - unsigned shift = plane > 0; + ptrdiff_t stride = frame->linesize[plane] / 2; + unsigned shift = plane > 0; int16_t *dst; int i, ret; @@ -522,22 +530,28 @@ static int decode_plane(AVCodecContext *avctx, int plane, AVPacket *avpkt, AVFra bytestream2_skip(&ctx->gb, 4); - dst = (int16_t *)frame->data[plane]; + dst = (int16_t *)frame->data[plane]; dst[0] = sign_extend(bytestream2_get_be16(&ctx->gb), 16); - if ((ret = init_get_bits8(&ctx->gbit, avpkt->data + bytestream2_tell(&ctx->gb), - bytestream2_get_bytes_left(&ctx->gb))) < 0) + ret = init_get_bits8(&ctx->bc, avpkt->data + bytestream2_tell(&ctx->gb), + bytestream2_get_bytes_left(&ctx->gb)); + if (ret < 0) return ret; - ret = read_low_coeffs(avctx, dst + 1, ctx->band[plane][0].width - 1, ctx->band[plane][0].width - 1, 0); + ret = read_low_coeffs(avctx, dst + 1, ctx->band[plane][0].width - 1, + ctx->band[plane][0].width - 1, 0); if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "error in lowpass coefficients for plane %d, top row\n", plane); + av_log(avctx, AV_LOG_ERROR, + "error in lowpass coefficients for plane %d, top row\n", plane); return ret; } - ret = read_low_coeffs(avctx, dst + stride, ctx->band[plane][0].height - 1, 1, stride); + ret = read_low_coeffs(avctx, dst + stride, + ctx->band[plane][0].height - 1, 1, stride); if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "error in lowpass coefficients for plane %d, left column\n", plane); + av_log(avctx, AV_LOG_ERROR, + "error in lowpass coefficients for plane %d, left column\n", + plane); return ret; } @@ -545,7 +559,8 @@ static int decode_plane(AVCodecContext *avctx, int plane, AVPacket *avpkt, AVFra (ctx->band[plane][0].width - 1) * (ctx->band[plane][0].height - 1), ctx->band[plane][0].width - 1, stride); if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "error in lowpass coefficients for plane %d, rest\n", plane); + av_log(avctx, AV_LOG_ERROR, + "error in lowpass coefficients for plane %d, rest\n", plane); return ret; } @@ -559,11 +574,12 @@ static int decode_plane(AVCodecContext *avctx, int plane, AVPacket *avpkt, AVFra if (ret < 0) return ret; - lowpass_prediction(dst, ctx->prediction, - ctx->band[plane][0].width, ctx->band[plane][0].height, stride); + lowpass_prediction(dst, ctx->prediction, ctx->band[plane][0].width, + ctx->band[plane][0].height, stride); - reconstruction(avctx, (int16_t *)frame->data[plane], ctx->w >> shift, ctx->h >> shift, - stride, NB_LEVELS, ctx->scaling[plane][H], ctx->scaling[plane][V]); + reconstruction(avctx, (int16_t *)frame->data[plane], ctx->w >> shift, + ctx->h >> shift, stride, NB_LEVELS, ctx->scaling[plane][H], + ctx->scaling[plane][V]); return 0; } @@ -664,14 +680,15 @@ static int pixlet_init_thread_copy(AVCodecContext *avctx) { PixletContext *ctx = avctx->priv_data; - ctx->filter[0] = NULL; - ctx->filter[1] = NULL; + ctx->filter[0] = NULL; + ctx->filter[1] = NULL; ctx->prediction = NULL; - ctx->w = ctx->h = 0; + ctx->w = 0; + ctx->h = 0; return 0; } -#endif +#endif /* HAVE_THREADS */ AVCodec ff_pixlet_decoder = { .name = "pixlet", From d1aef7d08a06f4adce747b251a81f8b99650bdca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Fri, 13 Oct 2017 00:21:11 +0200 Subject: [PATCH 0457/2557] lavc/pixlet: remove unecessary intermediate nb_levels variable This is a change imported from Libav. --- libavcodec/pixlet.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/pixlet.c b/libavcodec/pixlet.c index d2a5a1ac5d874..03a2cdacc8ba1 100644 --- a/libavcodec/pixlet.c +++ b/libavcodec/pixlet.c @@ -420,7 +420,7 @@ static void filterfn(int16_t *dest, int16_t *tmp, unsigned size, int64_t scale) } static void reconstruction(AVCodecContext *avctx, int16_t *dest, - unsigned width, unsigned height, ptrdiff_t stride, int nb_levels, + unsigned width, unsigned height, ptrdiff_t stride, int64_t *scaling_h, int64_t *scaling_v) { PixletContext *ctx = avctx->priv_data; @@ -428,11 +428,11 @@ static void reconstruction(AVCodecContext *avctx, int16_t *dest, int16_t *ptr, *tmp; int i, j, k; - scaled_width = width >> nb_levels; - scaled_height = height >> nb_levels; + scaled_width = width >> NB_LEVELS; + scaled_height = height >> NB_LEVELS; tmp = ctx->filter[0]; - for (i = 0; i < nb_levels; i++) { + for (i = 0; i < NB_LEVELS; i++) { int64_t scale_v = scaling_v[i]; int64_t scale_h = scaling_h[i]; scaled_width <<= 1; @@ -578,7 +578,7 @@ static int decode_plane(AVCodecContext *avctx, int plane, ctx->band[plane][0].height, stride); reconstruction(avctx, (int16_t *)frame->data[plane], ctx->w >> shift, - ctx->h >> shift, stride, NB_LEVELS, ctx->scaling[plane][H], + ctx->h >> shift, stride, ctx->scaling[plane][H], ctx->scaling[plane][V]); return 0; From 9c0279bc2c7bafee9ef9ef4a5799c0e5ea378239 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 12 Oct 2017 20:05:39 -0300 Subject: [PATCH 0458/2557] configure: fix CoreGraphics module name Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index ade67a31bbb73..ce5ad8a7a4878 100755 --- a/configure +++ b/configure @@ -5866,7 +5866,7 @@ check_apple_framework CoreVideo enabled avfoundation && { disable coregraphics applicationservices - check_lib CoreGraphics CoreGraphics/CoreGraphics.h CGGetActiveDisplayList "-framework CoreGraphics" || + check_lib coregraphics CoreGraphics/CoreGraphics.h CGGetActiveDisplayList "-framework CoreGraphics" || check_lib applicationservices ApplicationServices/ApplicationServices.h CGGetActiveDisplayList "-framework ApplicationServices"; } enabled videotoolbox && { From 4440bcf6a0cfd47dcd11c378050272dd1e84467e Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 12 Oct 2017 20:24:36 -0300 Subject: [PATCH 0459/2557] configure: fix pthread_cancel check Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index ce5ad8a7a4878..515d7e25ac256 100755 --- a/configure +++ b/configure @@ -5931,7 +5931,7 @@ fi if enabled pthreads; then - check_func pthread_cancel + check_func pthread_cancel $pthreads_extralibs fi enabled pthreads && From abb5efca263daff670ebb0a07af4fc902e457ade Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Thu, 12 Oct 2017 19:20:28 -0300 Subject: [PATCH 0460/2557] configure: Fix sem_timedwait probe (cherry-picked from libav commit 41262498ff89ef48e5ce4823b2fc2dc514a3eb0c) Signed-off-by: James Almer --- configure | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure b/configure index 515d7e25ac256..f757d767b8ec5 100755 --- a/configure +++ b/configure @@ -5750,7 +5750,6 @@ check_builtin atomic_cas_ptr atomic.h "void **ptr; void *oldval, *newval; atomic check_builtin machine_rw_barrier mbarrier.h "__machine_rw_barrier()" check_builtin MemoryBarrier windows.h "MemoryBarrier()" check_builtin sarestart signal.h "SA_RESTART" -check_builtin sem_timedwait semaphore.h "sem_t *s; sem_init(s,0,0); sem_timedwait(s,0); sem_destroy(s)" -lpthread check_builtin sync_val_compare_and_swap "" "int *ptr; int oldval, newval; __sync_val_compare_and_swap(ptr, oldval, newval)" check_builtin gmtime_r time.h "time_t *time; struct tm *tm; gmtime_r(time, tm)" check_builtin localtime_r time.h "time_t *time; struct tm *tm; localtime_r(time, tm)" @@ -5935,7 +5934,7 @@ if enabled pthreads; then fi enabled pthreads && - check_builtin sem_timedwait semaphore.h "sem_t *s; sem_init(s,0,0); sem_timedwait(s,0); sem_destroy(s)" + check_builtin sem_timedwait semaphore.h "sem_t *s; sem_init(s,0,0); sem_timedwait(s,0); sem_destroy(s)" $pthreads_extralibs enabled zlib && check_lib zlib zlib.h zlibVersion -lz enabled bzlib && check_lib bzlib bzlib.h BZ2_bzlibVersion -lbz2 From 34dbee9f601f30bb41fec5656f94f87ded31f155 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 12 Oct 2017 21:04:26 -0300 Subject: [PATCH 0461/2557] configure: explicitly list videotoolbox deps for avutil There's a bug in configure where they are not being resolved right, so make them explicit deps for avutil for now. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index f757d767b8ec5..1db50df0a4d84 100755 --- a/configure +++ b/configure @@ -3341,7 +3341,7 @@ avformat_deps="avcodec avutil" avformat_suggest="libm network" avresample_deps="avutil" avresample_suggest="libm" -avutil_suggest="clock_gettime libm libdrm libmfx opencl user32 vaapi videotoolbox wincrypt" +avutil_suggest="clock_gettime libm libdrm libmfx opencl user32 vaapi videotoolbox corefoundation corevideo coremedia wincrypt" postproc_deps="avutil gpl" postproc_suggest="libm" swresample_deps="avutil" From 27a0a8388082c6d4b9e96b7b79a59821c8a56168 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Wed, 11 Oct 2017 13:43:30 +0530 Subject: [PATCH 0462/2557] avcodec/mips: Improve avc chroma avg horiz mc msa functions Replace generic with block size specific function. Load the specific destination bytes instead of MSA load and pack. Signed-off-by: Kaustubh Raste Signed-off-by: Michael Niedermayer --- libavcodec/mips/h264chroma_msa.c | 329 ++++++++++++++++--------------- 1 file changed, 169 insertions(+), 160 deletions(-) diff --git a/libavcodec/mips/h264chroma_msa.c b/libavcodec/mips/h264chroma_msa.c index b8fcf6d012f47..2a54675075c89 100644 --- a/libavcodec/mips/h264chroma_msa.c +++ b/libavcodec/mips/h264chroma_msa.c @@ -839,12 +839,11 @@ static void avc_chroma_hv_8w_msa(uint8_t *src, uint8_t *dst, int32_t stride, } } -static void avc_chroma_hz_and_aver_dst_2x2_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1) +static void avc_chroma_hz_and_aver_dst_2x2_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) { uint16_t out0, out1; - uint32_t load0, load1; v16i8 src0, src1; v16u8 dst_data = { 0 }; v8u16 res_r; @@ -856,12 +855,13 @@ static void avc_chroma_hz_and_aver_dst_2x2_msa(uint8_t *src, int32_t src_stride, mask = LD_SB(&chroma_mask_arr[0]); - LD_SB2(src, src_stride, src0, src1); + LD_SB2(src, stride, src0, src1); - load0 = LW(dst); - load1 = LW(dst + dst_stride); + out0 = LH(dst); + out1 = LH(dst + stride); - INSERT_W2_UB(load0, load1, dst_data); + dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 0, out0); + dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 2, out1); src0 = __msa_vshf_b(mask, src1, src0); @@ -877,30 +877,34 @@ static void avc_chroma_hz_and_aver_dst_2x2_msa(uint8_t *src, int32_t src_stride, out1 = __msa_copy_u_h((v8i16) dst_data, 2); SH(out0, dst); - dst += dst_stride; + dst += stride; SH(out1, dst); } -static void avc_chroma_hz_and_aver_dst_2x4_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1) +static void avc_chroma_hz_and_aver_dst_2x4_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) { + uint16_t tp0, tp1, tp2, tp3; v16u8 src0, src1, src2, src3; - v16u8 dst0, dst1, dst2, dst3; + v16u8 dst0, dst_data = { 0 }; v8u16 res_r; - v16i8 res, mask; + v16i8 mask; v16i8 coeff_vec0 = __msa_fill_b(coeff0); v16i8 coeff_vec1 = __msa_fill_b(coeff1); v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); mask = LD_SB(&chroma_mask_arr[64]); - LD_UB4(src, src_stride, src0, src1, src2, src3); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - - dst0 = (v16u8) __msa_insve_h((v8i16) dst0, 1, (v8i16) dst1); - dst0 = (v16u8) __msa_insve_h((v8i16) dst0, 2, (v8i16) dst2); - dst0 = (v16u8) __msa_insve_h((v8i16) dst0, 3, (v8i16) dst3); + LD_UB4(src, stride, src0, src1, src2, src3); + tp0 = LH(dst); + tp1 = LH(dst + stride); + tp2 = LH(dst + 2 * stride); + tp3 = LH(dst + 3 * stride); + dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 0, tp0); + dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 1, tp1); + dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 2, tp2); + dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 3, tp3); VSHF_B2_UB(src0, src1, src2, src3, mask, mask, src0, src2); @@ -911,75 +915,26 @@ static void avc_chroma_hz_and_aver_dst_2x4_msa(uint8_t *src, int32_t src_stride, res_r = (v8u16) __msa_srari_h((v8i16) res_r, 6); res_r = __msa_sat_u_h(res_r, 7); - res = __msa_pckev_b((v16i8) res_r, (v16i8) res_r); - dst0 = __msa_aver_u_b((v16u8) res, dst0); - - ST2x4_UB(dst0, 0, dst, dst_stride); -} - -static void avc_chroma_hz_and_aver_dst_2x8_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1) -{ - v16u8 src0, src1, src2, src3, src4, src5, src6, src7; - v16u8 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; - v8u16 res0_r, res1_r; - v16u8 res0, res1, mask; - v16i8 coeff_vec0 = __msa_fill_b(coeff0); - v16i8 coeff_vec1 = __msa_fill_b(coeff1); - v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); - - mask = LD_UB(&chroma_mask_arr[64]); - - LD_UB8(src, src_stride, src0, src1, src2, src3, src4, src5, src6, src7); - LD_UB8(dst, dst_stride, dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7); - - dst0 = (v16u8) __msa_insve_h((v8i16) dst0, 1, (v8i16) dst1); - dst0 = (v16u8) __msa_insve_h((v8i16) dst0, 2, (v8i16) dst2); - dst0 = (v16u8) __msa_insve_h((v8i16) dst0, 3, (v8i16) dst3); - - dst4 = (v16u8) __msa_insve_h((v8i16) dst4, 1, (v8i16) dst5); - dst4 = (v16u8) __msa_insve_h((v8i16) dst4, 2, (v8i16) dst6); - dst4 = (v16u8) __msa_insve_h((v8i16) dst4, 3, (v8i16) dst7); - - VSHF_B2_UB(src0, src1, src2, src3, mask, mask, src0, src2); - VSHF_B2_UB(src4, src5, src6, src7, mask, mask, src4, src6); - ILVR_D2_UB(src2, src0, src6, src4, src0, src4); - DOTP_UB2_UH(src0, src4, coeff_vec, coeff_vec, res0_r, res1_r); - - res0_r <<= 3; - res1_r <<= 3; + dst0 = (v16u8) __msa_pckev_b((v16i8) res_r, (v16i8) res_r); + dst0 = __msa_aver_u_b(dst0, dst_data); - SRARI_H2_UH(res0_r, res1_r, 6); - SAT_UH2_UH(res0_r, res1_r, 7); - PCKEV_B2_UB(res0_r, res0_r, res1_r, res1_r, res0, res1); - AVER_UB2_UB(res0, dst0, res1, dst4, dst0, dst4); - - ST2x4_UB(dst0, 0, dst, dst_stride); - dst += (4 * dst_stride); - ST2x4_UB(dst4, 0, dst, dst_stride); + ST2x4_UB(dst0, 0, dst, stride); } -static void avc_chroma_hz_and_aver_dst_2w_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1, - int32_t height) +static void avc_chroma_hz_and_aver_dst_2w_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1, int32_t height) { if (2 == height) { - avc_chroma_hz_and_aver_dst_2x2_msa(src, src_stride, dst, dst_stride, - coeff0, coeff1); + avc_chroma_hz_and_aver_dst_2x2_msa(src, dst, stride, coeff0, coeff1); } else if (4 == height) { - avc_chroma_hz_and_aver_dst_2x4_msa(src, src_stride, dst, dst_stride, - coeff0, coeff1); - } else if (8 == height) { - avc_chroma_hz_and_aver_dst_2x8_msa(src, src_stride, dst, dst_stride, - coeff0, coeff1); + avc_chroma_hz_and_aver_dst_2x4_msa(src, dst, stride, coeff0, coeff1); } } -static void avc_chroma_hz_and_aver_dst_4x2_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1) +static void avc_chroma_hz_and_aver_dst_4x2_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) { uint32_t load0, load1; v16i8 src0, src1; @@ -992,10 +947,9 @@ static void avc_chroma_hz_and_aver_dst_4x2_msa(uint8_t *src, int32_t src_stride, mask = LD_SB(&chroma_mask_arr[0]); - LD_SB2(src, src_stride, src0, src1); + LD_SB2(src, stride, src0, src1); - load0 = LW(dst); - load1 = LW(dst + dst_stride); + LW2(dst, stride, load0, load1); INSERT_W2_UB(load0, load1, dst_data); @@ -1008,107 +962,165 @@ static void avc_chroma_hz_and_aver_dst_4x2_msa(uint8_t *src, int32_t src_stride, res = __msa_pckev_b((v16i8) res_r, (v16i8) res_r); dst_data = __msa_aver_u_b((v16u8) res, dst_data); - ST4x2_UB(dst_data, dst, dst_stride); + ST4x2_UB(dst_data, dst, stride); } -static void avc_chroma_hz_and_aver_dst_4x4multiple_msa(uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - uint32_t coeff0, - uint32_t coeff1, - int32_t height) +static void avc_chroma_hz_and_aver_dst_4x4_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) { - uint32_t load0, load1; - uint32_t row; + uint32_t tp0, tp1, tp2, tp3; v16u8 src0, src1, src2, src3; - v16u8 dst0 = { 0 }; - v16u8 dst1 = { 0 }; + v16u8 out, dst_data = { 0 }; + v16i8 mask; v8u16 res0_r, res1_r; - v16u8 res0, res1, mask; v16i8 coeff_vec0 = __msa_fill_b(coeff0); v16i8 coeff_vec1 = __msa_fill_b(coeff1); v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); - mask = LD_UB(&chroma_mask_arr[0]); - - for (row = (height >> 2); row--;) { - LD_UB4(src, src_stride, src0, src1, src2, src3); - src += (4 * src_stride); - - load0 = LW(dst); - load1 = LW(dst + dst_stride); - - INSERT_W2_UB(load0, load1, dst0); - - load0 = LW(dst + 2 * dst_stride); - load1 = LW(dst + 3 * dst_stride); - - INSERT_W2_UB(load0, load1, dst1); + mask = LD_SB(&chroma_mask_arr[0]); - VSHF_B2_UB(src0, src1, src2, src3, mask, mask, src0, src2); - DOTP_UB2_UH(src0, src2, coeff_vec, coeff_vec, res0_r, res1_r); + LD_UB4(src, stride, src0, src1, src2, src3); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst_data); + VSHF_B2_UB(src0, src1, src2, src3, mask, mask, src0, src2); + DOTP_UB2_UH(src0, src2, coeff_vec, coeff_vec, res0_r, res1_r); + res0_r <<= 3; + res1_r <<= 3; + SRARI_H2_UH(res0_r, res1_r, 6); + SAT_UH2_UH(res0_r, res1_r, 7); + out = (v16u8) __msa_pckev_b((v16i8) res1_r, (v16i8) res0_r); + out = __msa_aver_u_b(out, dst_data); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, stride); +} - res0_r <<= 3; - res1_r <<= 3; +static void avc_chroma_hz_and_aver_dst_4x8_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) +{ + uint32_t tp0, tp1, tp2, tp3; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7, out0, out1; + v16u8 dst0 = { 0 }, dst1 = { 0 }; + v16i8 mask; + v8u16 res0, res1, res2, res3; + v16i8 coeff_vec0 = __msa_fill_b(coeff0); + v16i8 coeff_vec1 = __msa_fill_b(coeff1); + v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); - SRARI_H2_UH(res0_r, res1_r, 6); - SAT_UH2_UH(res0_r, res1_r, 7); - PCKEV_B2_UB(res0_r, res0_r, res1_r, res1_r, res0, res1); - AVER_UB2_UB(res0, dst0, res1, dst1, dst0, dst1); + mask = LD_SB(&chroma_mask_arr[0]); - ST4x4_UB(dst0, dst1, 0, 1, 0, 1, dst, dst_stride); - dst += (4 * dst_stride); - } + LD_UB8(src, stride, src0, src1, src2, src3, src4, src5, src6, src7); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); + LW4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst1); + VSHF_B2_UB(src0, src1, src2, src3, mask, mask, src0, src2); + VSHF_B2_UB(src4, src5, src6, src7, mask, mask, src4, src6); + DOTP_UB2_UH(src0, src2, coeff_vec, coeff_vec, res0, res1); + DOTP_UB2_UH(src4, src6, coeff_vec, coeff_vec, res2, res3); + SLLI_4V(res0, res1, res2, res3, 3); + SRARI_H4_UH(res0, res1, res2, res3, 6); + SAT_UH4_UH(res0, res1, res2, res3, 7); + PCKEV_B2_UB(res1, res0, res3, res2, out0, out1); + AVER_UB2_UB(out0, dst0, out1, dst1, out0, out1); + ST4x8_UB(out0, out1, dst, stride); } -static void avc_chroma_hz_and_aver_dst_4w_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1, - int32_t height) +static void avc_chroma_hz_and_aver_dst_4w_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1, int32_t height) { if (2 == height) { - avc_chroma_hz_and_aver_dst_4x2_msa(src, src_stride, dst, dst_stride, - coeff0, coeff1); - } else { - avc_chroma_hz_and_aver_dst_4x4multiple_msa(src, src_stride, - dst, dst_stride, - coeff0, coeff1, height); + avc_chroma_hz_and_aver_dst_4x2_msa(src, dst, stride, coeff0, coeff1); + } else if (4 == height) { + avc_chroma_hz_and_aver_dst_4x4_msa(src, dst, stride, coeff0, coeff1); + } else if (8 == height) { + avc_chroma_hz_and_aver_dst_4x8_msa(src, dst, stride, coeff0, coeff1); } } -static void avc_chroma_hz_and_aver_dst_8w_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1, - int32_t height) +static void avc_chroma_hz_and_aver_dst_8x4_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) { - uint32_t row; + uint64_t tp0, tp1, tp2, tp3; v16u8 src0, src1, src2, src3, out0, out1; + v16u8 dst0 = { 0 }, dst1 = { 0 }; v8u16 res0, res1, res2, res3; - v16u8 dst0, dst1, dst2, dst3; v16i8 mask; v16i8 coeff_vec0 = __msa_fill_b(coeff0); v16i8 coeff_vec1 = __msa_fill_b(coeff1); v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); mask = LD_SB(&chroma_mask_arr[32]); + LD_UB4(src, stride, src0, src1, src2, src3); + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + VSHF_B2_UB(src0, src0, src1, src1, mask, mask, src0, src1); + VSHF_B2_UB(src2, src2, src3, src3, mask, mask, src2, src3); + DOTP_UB4_UH(src0, src1, src2, src3, coeff_vec, coeff_vec, coeff_vec, + coeff_vec, res0, res1, res2, res3); + SLLI_4V(res0, res1, res2, res3, 3); + SRARI_H4_UH(res0, res1, res2, res3, 6); + SAT_UH4_UH(res0, res1, res2, res3, 7); + PCKEV_B2_UB(res1, res0, res3, res2, out0, out1); + AVER_UB2_UB(out0, dst0, out1, dst1, dst0, dst1); + ST8x4_UB(dst0, dst1, dst, stride); +} - for (row = height >> 2; row--;) { - LD_UB4(src, src_stride, src0, src1, src2, src3); - src += (4 * src_stride); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - VSHF_B2_UB(src0, src0, src1, src1, mask, mask, src0, src1); - VSHF_B2_UB(src2, src2, src3, src3, mask, mask, src2, src3); - DOTP_UB4_UH(src0, src1, src2, src3, coeff_vec, coeff_vec, coeff_vec, - coeff_vec, res0, res1, res2, res3); - SLLI_4V(res0, res1, res2, res3, 3); - SRARI_H4_UH(res0, res1, res2, res3, 6); - SAT_UH4_UH(res0, res1, res2, res3, 7); - PCKEV_B2_UB(res1, res0, res3, res2, out0, out1); - PCKEV_D2_UB(dst1, dst0, dst3, dst2, dst0, dst1); - AVER_UB2_UB(out0, dst0, out1, dst1, out0, out1); - ST8x4_UB(out0, out1, dst, dst_stride); - dst += (4 * dst_stride); +static void avc_chroma_hz_and_aver_dst_8x8_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) +{ + uint64_t tp0, tp1, tp2, tp3; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7; + v16u8 out0, out1, out2, out3; + v16u8 dst0 = { 0 }, dst1 = { 0 }, dst2 = { 0 }, dst3 = { 0 }; + v8u16 res0, res1, res2, res3, res4, res5, res6, res7; + v16i8 mask; + v16i8 coeff_vec0 = __msa_fill_b(coeff0); + v16i8 coeff_vec1 = __msa_fill_b(coeff1); + v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); + + mask = LD_SB(&chroma_mask_arr[32]); + + LD_UB8(src, stride, src0, src1, src2, src3, src4, src5, src6, src7); + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + LD4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst2); + INSERT_D2_UB(tp2, tp3, dst3); + VSHF_B2_UB(src0, src0, src1, src1, mask, mask, src0, src1); + VSHF_B2_UB(src2, src2, src3, src3, mask, mask, src2, src3); + VSHF_B2_UB(src4, src4, src5, src5, mask, mask, src4, src5); + VSHF_B2_UB(src6, src6, src7, src7, mask, mask, src6, src7); + DOTP_UB4_UH(src0, src1, src2, src3, coeff_vec, coeff_vec, coeff_vec, + coeff_vec, res0, res1, res2, res3); + DOTP_UB4_UH(src4, src5, src6, src7, coeff_vec, coeff_vec, coeff_vec, + coeff_vec, res4, res5, res6, res7); + SLLI_4V(res0, res1, res2, res3, 3); + SLLI_4V(res4, res5, res6, res7, 3); + SRARI_H4_UH(res0, res1, res2, res3, 6); + SRARI_H4_UH(res4, res5, res6, res7, 6); + SAT_UH4_UH(res0, res1, res2, res3, 7); + SAT_UH4_UH(res4, res5, res6, res7, 7); + PCKEV_B2_UB(res1, res0, res3, res2, out0, out1); + PCKEV_B2_UB(res5, res4, res7, res6, out2, out3); + AVER_UB2_UB(out0, dst0, out1, dst1, out0, out1); + AVER_UB2_UB(out2, dst2, out3, dst3, out2, out3); + ST8x8_UB(out0, out1, out2, out3, dst, stride); +} + +static void avc_chroma_hz_and_aver_dst_8w_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1, int32_t height) +{ + if (4 == height) { + avc_chroma_hz_and_aver_dst_8x4_msa(src, dst, stride, coeff0, coeff1); + } else if (8 == height) { + avc_chroma_hz_and_aver_dst_8x8_msa(src, dst, stride, coeff0, coeff1); } } @@ -1989,8 +2001,7 @@ void ff_avg_h264_chroma_mc8_msa(uint8_t *dst, uint8_t *src, stride, x, (8 - x), y, (8 - y), height); } else if (x) { - avc_chroma_hz_and_aver_dst_8w_msa(src, stride, dst, - stride, x, (8 - x), height); + avc_chroma_hz_and_aver_dst_8w_msa(src, dst, stride, x, (8 - x), height); } else if (y) { avc_chroma_vt_and_aver_dst_8w_msa(src, stride, dst, stride, y, (8 - y), height); @@ -2009,8 +2020,7 @@ void ff_avg_h264_chroma_mc4_msa(uint8_t *dst, uint8_t *src, stride, x, (8 - x), y, (8 - y), height); } else if (x) { - avc_chroma_hz_and_aver_dst_4w_msa(src, stride, dst, - stride, x, (8 - x), height); + avc_chroma_hz_and_aver_dst_4w_msa(src, dst, stride, x, (8 - x), height); } else if (y) { avc_chroma_vt_and_aver_dst_4w_msa(src, stride, dst, stride, y, (8 - y), height); @@ -2031,8 +2041,7 @@ void ff_avg_h264_chroma_mc2_msa(uint8_t *dst, uint8_t *src, stride, x, (8 - x), y, (8 - y), height); } else if (x) { - avc_chroma_hz_and_aver_dst_2w_msa(src, stride, dst, - stride, x, (8 - x), height); + avc_chroma_hz_and_aver_dst_2w_msa(src, dst, stride, x, (8 - x), height); } else if (y) { avc_chroma_vt_and_aver_dst_2w_msa(src, stride, dst, stride, y, (8 - y), height); From e549933a270dd2cfc36f2cf9bb6b29acf3dc6d08 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Wed, 11 Oct 2017 14:17:21 +0530 Subject: [PATCH 0463/2557] avcodec/mips: Improve avc put mc 12, 32 and 22 msa functions Remove loops and unroll as block sizes are known. Removed unused functions. Signed-off-by: Kaustubh Raste Signed-off-by: Michael Niedermayer --- libavcodec/mips/h264qpel_msa.c | 1013 +++++++++++++++++++++++--------- 1 file changed, 747 insertions(+), 266 deletions(-) diff --git a/libavcodec/mips/h264qpel_msa.c b/libavcodec/mips/h264qpel_msa.c index a22a4828c6bb9..f11fce8ff37cc 100644 --- a/libavcodec/mips/h264qpel_msa.c +++ b/libavcodec/mips/h264qpel_msa.c @@ -171,241 +171,6 @@ static const uint8_t luma_mask_arr[16 * 8] = { out0_m; \ } ) -static void avc_luma_mid_4w_msa(const uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - int32_t height) -{ - uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4; - v16i8 mask0, mask1, mask2; - v8i16 hz_out0, hz_out1, hz_out2, hz_out3; - v8i16 hz_out4, hz_out5, hz_out6, hz_out7, hz_out8; - v8i16 dst0, dst1, dst2, dst3; - - LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - src += (5 * src_stride); - - XORI_B5_128_SB(src0, src1, src2, src3, src4); - - hz_out0 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src0, src1, - mask0, mask1, mask2); - hz_out2 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src2, src3, - mask0, mask1, mask2); - - PCKOD_D2_SH(hz_out0, hz_out0, hz_out2, hz_out2, hz_out1, hz_out3); - - hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); - - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB4(src, src_stride, src0, src1, src2, src3); - src += (4 * src_stride); - - XORI_B4_128_SB(src0, src1, src2, src3); - - hz_out5 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src0, src1, - mask0, mask1, - mask2); - hz_out7 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src2, src3, - mask0, mask1, - mask2); - - PCKOD_D2_SH(hz_out5, hz_out5, hz_out7, hz_out7, hz_out6, hz_out8); - - dst0 = AVC_CALC_DPADD_H_6PIX_2COEFF_R_SH(hz_out0, hz_out1, hz_out2, - hz_out3, hz_out4, hz_out5); - dst1 = AVC_CALC_DPADD_H_6PIX_2COEFF_R_SH(hz_out1, hz_out2, hz_out3, - hz_out4, hz_out5, hz_out6); - dst2 = AVC_CALC_DPADD_H_6PIX_2COEFF_R_SH(hz_out2, hz_out3, hz_out4, - hz_out5, hz_out6, hz_out7); - dst3 = AVC_CALC_DPADD_H_6PIX_2COEFF_R_SH(hz_out3, hz_out4, hz_out5, - hz_out6, hz_out7, hz_out8); - - PCKEV_B2_SB(dst1, dst0, dst3, dst2, src0, src1); - XORI_B2_128_SB(src0, src1); - - ST4x4_UB(src0, src1, 0, 2, 0, 2, dst, dst_stride); - - dst += (4 * dst_stride); - - hz_out0 = hz_out4; - hz_out1 = hz_out5; - hz_out2 = hz_out6; - hz_out3 = hz_out7; - hz_out4 = hz_out8; - } -} - -static void avc_luma_mid_8w_msa(const uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - int32_t height) -{ - uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4; - v16i8 mask0, mask1, mask2; - v8i16 hz_out0, hz_out1, hz_out2, hz_out3; - v8i16 hz_out4, hz_out5, hz_out6, hz_out7, hz_out8; - v8i16 dst0, dst1, dst2, dst3; - v16u8 out0, out1; - - LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); - - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - XORI_B5_128_SB(src0, src1, src2, src3, src4); - src += (5 * src_stride); - - hz_out0 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); - hz_out1 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); - hz_out2 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); - hz_out3 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); - hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); - - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB4(src, src_stride, src0, src1, src2, src3); - XORI_B4_128_SB(src0, src1, src2, src3); - src += (4 * src_stride); - - hz_out5 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); - hz_out6 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); - hz_out7 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); - hz_out8 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); - dst0 = AVC_CALC_DPADD_H_6PIX_2COEFF_SH(hz_out0, hz_out1, hz_out2, - hz_out3, hz_out4, hz_out5); - dst1 = AVC_CALC_DPADD_H_6PIX_2COEFF_SH(hz_out1, hz_out2, hz_out3, - hz_out4, hz_out5, hz_out6); - dst2 = AVC_CALC_DPADD_H_6PIX_2COEFF_SH(hz_out2, hz_out3, hz_out4, - hz_out5, hz_out6, hz_out7); - dst3 = AVC_CALC_DPADD_H_6PIX_2COEFF_SH(hz_out3, hz_out4, hz_out5, - hz_out6, hz_out7, hz_out8); - out0 = PCKEV_XORI128_UB(dst0, dst1); - out1 = PCKEV_XORI128_UB(dst2, dst3); - ST8x4_UB(out0, out1, dst, dst_stride); - - dst += (4 * dst_stride); - hz_out3 = hz_out7; - hz_out1 = hz_out5; - hz_out5 = hz_out4; - hz_out4 = hz_out8; - hz_out2 = hz_out6; - hz_out0 = hz_out5; - } -} - -static void avc_luma_mid_16w_msa(const uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - int32_t height) -{ - uint32_t multiple8_cnt; - - for (multiple8_cnt = 2; multiple8_cnt--;) { - avc_luma_mid_8w_msa(src, src_stride, dst, dst_stride, height); - src += 8; - dst += 8; - } -} - -static void avc_luma_midh_qrt_4w_msa(const uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - int32_t height, uint8_t horiz_offset) -{ - uint32_t row; - v16i8 src0, src1, src2, src3, src4, src5, src6; - v8i16 vt_res0, vt_res1, vt_res2, vt_res3; - v4i32 hz_res0, hz_res1; - v8i16 dst0, dst1; - v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5; - v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; - v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; - v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; - v8i16 minus5h = __msa_ldi_h(-5); - v8i16 plus20h = __msa_ldi_h(20); - v8i16 zeros = { 0 }; - v16u8 out; - - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - src += (5 * src_stride); - XORI_B5_128_SB(src0, src1, src2, src3, src4); - - for (row = (height >> 1); row--;) { - LD_SB2(src, src_stride, src5, src6); - src += (2 * src_stride); - - XORI_B2_128_SB(src5, src6); - AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src0, src1, src2, src3, src4, src5, - vt_res0, vt_res1); - AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src1, src2, src3, src4, src5, src6, - vt_res2, vt_res3); - VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, - mask0, mask1, mask2, shf_vec0, shf_vec1, shf_vec2); - VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, - mask0, mask1, mask2, shf_vec3, shf_vec4, shf_vec5); - hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); - DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); - hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); - DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); - - SRARI_W2_SW(hz_res0, hz_res1, 10); - SAT_SW2_SW(hz_res0, hz_res1, 7); - - dst0 = __msa_srari_h(shf_vec2, 5); - dst1 = __msa_srari_h(shf_vec5, 5); - - SAT_SH2_SH(dst0, dst1, 7); - - if (horiz_offset) { - dst0 = __msa_ilvod_h(zeros, dst0); - dst1 = __msa_ilvod_h(zeros, dst1); - } else { - ILVEV_H2_SH(dst0, zeros, dst1, zeros, dst0, dst1); - } - - hz_res0 = __msa_aver_s_w(hz_res0, (v4i32) dst0); - hz_res1 = __msa_aver_s_w(hz_res1, (v4i32) dst1); - dst0 = __msa_pckev_h((v8i16) hz_res1, (v8i16) hz_res0); - - out = PCKEV_XORI128_UB(dst0, dst0); - ST4x2_UB(out, dst, dst_stride); - - dst += (2 * dst_stride); - - src0 = src2; - src1 = src3; - src2 = src4; - src3 = src5; - src4 = src6; - } -} - -static void avc_luma_midh_qrt_8w_msa(const uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - int32_t height, uint8_t horiz_offset) -{ - uint32_t multiple8_cnt; - - for (multiple8_cnt = 2; multiple8_cnt--;) { - avc_luma_midh_qrt_4w_msa(src, src_stride, dst, dst_stride, height, - horiz_offset); - - src += 4; - dst += 4; - } -} - -static void avc_luma_midh_qrt_16w_msa(const uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - int32_t height, uint8_t horiz_offset) -{ - uint32_t multiple8_cnt; - - for (multiple8_cnt = 4; multiple8_cnt--;) { - avc_luma_midh_qrt_4w_msa(src, src_stride, dst, dst_stride, height, - horiz_offset); - - src += 4; - dst += 4; - } -} - static void avc_luma_hv_qrt_4w_msa(const uint8_t *src_x, const uint8_t *src_y, int32_t src_stride, uint8_t *dst, int32_t dst_stride, int32_t height) @@ -3634,57 +3399,773 @@ void ff_put_h264_qpel4_mc02_msa(uint8_t *dst, const uint8_t *src, void ff_put_h264_qpel16_mc12_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_midh_qrt_16w_msa(src - (2 * stride) - 2, - stride, dst, stride, 16, 0); + uint32_t row; + v16u8 out; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 src11; + v8i16 vt_res0, vt_res1, vt_res2, vt_res3, dst0, dst1, dst2, dst3, mask3; + v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5, shf_vec6; + v8i16 shf_vec7, shf_vec8, shf_vec9, shf_vec10, shf_vec11, mask4, mask5; + v4i32 hz_res0, hz_res1, hz_res2, hz_res3; + v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; + v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; + v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; + v8i16 minus5h = __msa_ldi_h(-5); + v8i16 plus20h = __msa_ldi_h(20); + + mask3 = mask0 + 4; + mask4 = mask1 + 4; + mask5 = mask2 + 4; + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + LD_SB5(src + 8, stride, src7, src8, src9, src10, src11); + src += (5 * stride); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + XORI_B5_128_SB(src7, src8, src9, src10, src11); + + for (row = 16; row--;) { + LD_SB2(src, 8, src5, src6); + src += stride; + XORI_B2_128_SB(src5, src6); + + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src0, src1, src2, src3, src4, src5, + vt_res0, vt_res1); + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src7, src8, src9, src10, src11, src6, + vt_res2, vt_res3); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec2); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec5); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask3, + mask4, mask5, shf_vec6, shf_vec7, shf_vec8); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask3, + mask4, mask5, shf_vec9, shf_vec10, shf_vec11); + hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); + hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); + hz_res2 = __msa_hadd_s_w(shf_vec6, shf_vec6); + hz_res3 = __msa_hadd_s_w(shf_vec9, shf_vec9); + DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); + DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); + DPADD_SH2_SW(shf_vec7, shf_vec8, minus5h, plus20h, hz_res2, hz_res2); + DPADD_SH2_SW(shf_vec10, shf_vec11, minus5h, plus20h, hz_res3, hz_res3); + SRARI_W4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 10); + SAT_SW4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 7); + dst0 = __msa_srari_h(shf_vec2, 5); + dst1 = __msa_srari_h(shf_vec5, 5); + dst2 = __msa_srari_h(shf_vec8, 5); + dst3 = __msa_srari_h(shf_vec11, 5); + SAT_SH4_SH(dst0, dst1, dst2, dst3, 7); + PCKEV_H2_SH(dst2, dst0, dst3, dst1, dst0, dst1); + PCKEV_H2_SH(hz_res2, hz_res0, hz_res3, hz_res1, dst2, dst3); + dst0 = __msa_aver_s_h(dst2, dst0); + dst1 = __msa_aver_s_h(dst3, dst1); + out = PCKEV_XORI128_UB(dst0, dst1); + ST_UB(out, dst); + dst += stride; + + src0 = src1; + src1 = src2; + src2 = src3; + src3 = src4; + src4 = src5; + src7 = src8; + src8 = src9; + src9 = src10; + src10 = src11; + src11 = src6; + } } void ff_put_h264_qpel16_mc32_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_midh_qrt_16w_msa(src - (2 * stride) - 2, - stride, dst, stride, 16, 1); -} + uint32_t row; + v16u8 out; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 src11; + v8i16 vt_res0, vt_res1, vt_res2, vt_res3, dst0, dst1, dst2, dst3, mask3; + v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5, shf_vec6; + v8i16 shf_vec7, shf_vec8, shf_vec9, shf_vec10, shf_vec11, mask4, mask5; + v4i32 hz_res0, hz_res1, hz_res2, hz_res3; + v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; + v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; + v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; + v8i16 minus5h = __msa_ldi_h(-5); + v8i16 plus20h = __msa_ldi_h(20); -void ff_put_h264_qpel8_mc12_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_midh_qrt_8w_msa(src - (2 * stride) - 2, stride, dst, stride, 8, 0); -} + mask3 = mask0 + 4; + mask4 = mask1 + 4; + mask5 = mask2 + 4; -void ff_put_h264_qpel8_mc32_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_midh_qrt_8w_msa(src - (2 * stride) - 2, stride, dst, stride, 8, 1); -} + src -= ((2 * stride) + 2); -void ff_put_h264_qpel4_mc12_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_midh_qrt_4w_msa(src - (2 * stride) - 2, stride, dst, stride, 4, 0); -} + LD_SB5(src, stride, src0, src1, src2, src3, src4); + LD_SB5(src + 8, stride, src7, src8, src9, src10, src11); + src += (5 * stride); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + XORI_B5_128_SB(src7, src8, src9, src10, src11); -void ff_put_h264_qpel4_mc32_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_midh_qrt_4w_msa(src - (2 * stride) - 2, stride, dst, stride, 4, 1); -} + for (row = 16; row--;) { + LD_SB2(src, 8, src5, src6); + src += stride; + XORI_B2_128_SB(src5, src6); -void ff_put_h264_qpel16_mc22_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_mid_16w_msa(src - (2 * stride) - 2, stride, dst, stride, 16); + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src0, src1, src2, src3, src4, src5, + vt_res0, vt_res1); + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src7, src8, src9, src10, src11, src6, + vt_res2, vt_res3); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec2); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec5); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask3, + mask4, mask5, shf_vec6, shf_vec7, shf_vec8); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask3, + mask4, mask5, shf_vec9, shf_vec10, shf_vec11); + hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); + hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); + hz_res2 = __msa_hadd_s_w(shf_vec6, shf_vec6); + hz_res3 = __msa_hadd_s_w(shf_vec9, shf_vec9); + DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); + DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); + DPADD_SH2_SW(shf_vec7, shf_vec8, minus5h, plus20h, hz_res2, hz_res2); + DPADD_SH2_SW(shf_vec10, shf_vec11, minus5h, plus20h, hz_res3, hz_res3); + SRARI_W4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 10); + SAT_SW4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 7); + dst0 = __msa_srari_h(shf_vec2, 5); + dst1 = __msa_srari_h(shf_vec5, 5); + dst2 = __msa_srari_h(shf_vec8, 5); + dst3 = __msa_srari_h(shf_vec11, 5); + SAT_SH4_SH(dst0, dst1, dst2, dst3, 7); + dst0 = __msa_pckod_h(dst2, dst0); + dst1 = __msa_pckod_h(dst3, dst1); + PCKEV_H2_SH(hz_res2, hz_res0, hz_res3, hz_res1, dst2, dst3); + dst0 = __msa_aver_s_h(dst2, dst0); + dst1 = __msa_aver_s_h(dst3, dst1); + out = PCKEV_XORI128_UB(dst0, dst1); + ST_UB(out, dst); + dst += stride; + + src0 = src1; + src1 = src2; + src2 = src3; + src3 = src4; + src4 = src5; + src7 = src8; + src8 = src9; + src9 = src10; + src10 = src11; + src11 = src6; + } +} + +void ff_put_h264_qpel8_mc12_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint32_t row; + v16u8 out; + v16i8 src0, src1, src2, src3, src4, src5, src6; + v8i16 vt_res0, vt_res1, vt_res2, vt_res3, dst0, dst1, dst2, dst3; + v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5, shf_vec6; + v8i16 shf_vec7, shf_vec8, shf_vec9, shf_vec10, shf_vec11; + v8i16 mask3, mask4, mask5; + v4i32 hz_res0, hz_res1, hz_res2, hz_res3; + v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; + v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; + v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; + v8i16 minus5h = __msa_ldi_h(-5); + v8i16 plus20h = __msa_ldi_h(20); + + mask3 = mask0 + 4; + mask4 = mask1 + 4; + mask5 = mask2 + 4; + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + + for (row = 4; row--;) { + LD_SB2(src, stride, src5, src6); + src += (2 * stride); + XORI_B2_128_SB(src5, src6); + + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src0, src1, src2, src3, src4, src5, + vt_res0, vt_res1); + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src1, src2, src3, src4, src5, src6, + vt_res2, vt_res3); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec2); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec5); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask3, + mask4, mask5, shf_vec6, shf_vec7, shf_vec8); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask3, + mask4, mask5, shf_vec9, shf_vec10, shf_vec11); + hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); + hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); + hz_res2 = __msa_hadd_s_w(shf_vec6, shf_vec6); + hz_res3 = __msa_hadd_s_w(shf_vec9, shf_vec9); + DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); + DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); + DPADD_SH2_SW(shf_vec7, shf_vec8, minus5h, plus20h, hz_res2, hz_res2); + DPADD_SH2_SW(shf_vec10, shf_vec11, minus5h, plus20h, hz_res3, hz_res3); + SRARI_W4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 10); + SAT_SW4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 7); + dst0 = __msa_srari_h(shf_vec2, 5); + dst1 = __msa_srari_h(shf_vec5, 5); + dst2 = __msa_srari_h(shf_vec8, 5); + dst3 = __msa_srari_h(shf_vec11, 5); + SAT_SH4_SH(dst0, dst1, dst2, dst3, 7); + PCKEV_H2_SH(dst2, dst0, dst3, dst1, dst0, dst1); + PCKEV_H2_SH(hz_res2, hz_res0, hz_res3, hz_res1, dst2, dst3); + dst0 = __msa_aver_s_h(dst2, dst0); + dst1 = __msa_aver_s_h(dst3, dst1); + out = PCKEV_XORI128_UB(dst0, dst1); + ST8x2_UB(out, dst, stride); + dst += (2 * stride); + + src0 = src2; + src1 = src3; + src2 = src4; + src3 = src5; + src4 = src6; + } +} + +void ff_put_h264_qpel8_mc32_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint32_t row; + v16u8 out; + v16i8 src0, src1, src2, src3, src4, src5, src6; + v8i16 vt_res0, vt_res1, vt_res2, vt_res3, dst0, dst1, dst2, dst3; + v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5, shf_vec6; + v8i16 shf_vec7, shf_vec8, shf_vec9, shf_vec10, shf_vec11; + v8i16 mask3, mask4, mask5; + v4i32 hz_res0, hz_res1, hz_res2, hz_res3; + v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; + v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; + v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; + v8i16 minus5h = __msa_ldi_h(-5); + v8i16 plus20h = __msa_ldi_h(20); + + mask3 = mask0 + 4; + mask4 = mask1 + 4; + mask5 = mask2 + 4; + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + + for (row = 4; row--;) { + LD_SB2(src, stride, src5, src6); + src += (2 * stride); + XORI_B2_128_SB(src5, src6); + + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src0, src1, src2, src3, src4, src5, + vt_res0, vt_res1); + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src1, src2, src3, src4, src5, src6, + vt_res2, vt_res3); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec2); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec5); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask3, + mask4, mask5, shf_vec6, shf_vec7, shf_vec8); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask3, + mask4, mask5, shf_vec9, shf_vec10, shf_vec11); + hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); + hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); + hz_res2 = __msa_hadd_s_w(shf_vec6, shf_vec6); + hz_res3 = __msa_hadd_s_w(shf_vec9, shf_vec9); + DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); + DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); + DPADD_SH2_SW(shf_vec7, shf_vec8, minus5h, plus20h, hz_res2, hz_res2); + DPADD_SH2_SW(shf_vec10, shf_vec11, minus5h, plus20h, hz_res3, hz_res3); + SRARI_W4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 10); + SAT_SW4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 7); + dst0 = __msa_srari_h(shf_vec2, 5); + dst1 = __msa_srari_h(shf_vec5, 5); + dst2 = __msa_srari_h(shf_vec8, 5); + dst3 = __msa_srari_h(shf_vec11, 5); + SAT_SH4_SH(dst0, dst1, dst2, dst3, 7); + dst0 = __msa_pckod_h(dst2, dst0); + dst1 = __msa_pckod_h(dst3, dst1); + PCKEV_H2_SH(hz_res2, hz_res0, hz_res3, hz_res1, dst2, dst3); + dst0 = __msa_aver_s_h(dst2, dst0); + dst1 = __msa_aver_s_h(dst3, dst1); + out = PCKEV_XORI128_UB(dst0, dst1); + ST8x2_UB(out, dst, stride); + dst += (2 * stride); + + src0 = src2; + src1 = src3; + src2 = src4; + src3 = src5; + src4 = src6; + } +} + +void ff_put_h264_qpel4_mc12_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + v16u8 out; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 src10_r, src21_r, src32_r, src43_r, src54_r, src65_r, src76_r; + v16i8 src87_r, src10_l, src21_l, src32_l, src43_l, src54_l, src65_l; + v16i8 src76_l, src87_l, filt0, filt1, filt2; + v8i16 vt_res0, vt_res1, vt_res2, vt_res3, dst0, dst1, dst2, dst3, shf_vec7; + v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5, shf_vec6; + v4i32 hz_res0, hz_res1, hz_res2, hz_res3; + v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; + v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; + v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; + v8i16 minus5h = __msa_ldi_h(-5); + v8i16 plus20h = __msa_ldi_h(20); + v8i16 zeros = { 0 }; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + LD_SB4(src, stride, src5, src6, src7, src8); + XORI_B4_128_SB(src5, src6, src7, src8); + + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_r, src65_r, + src76_r, src87_r); + ILVL_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_l, src21_l, + src32_l, src43_l); + ILVL_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_l, src65_l, + src76_l, src87_l); + vt_res0 = AVC_DOT_SH3_SH(src10_r, src32_r, src54_r, filt0, filt1, filt2); + vt_res1 = AVC_DOT_SH3_SH(src10_l, src32_l, src54_l, filt0, filt1, filt2); + vt_res2 = AVC_DOT_SH3_SH(src21_r, src43_r, src65_r, filt0, filt1, filt2); + vt_res3 = AVC_DOT_SH3_SH(src21_l, src43_l, src65_l, filt0, filt1, filt2); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec2); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec5); + hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); + DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); + hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); + DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); + + vt_res0 = AVC_DOT_SH3_SH(src32_r, src54_r, src76_r, filt0, filt1, filt2); + vt_res1 = AVC_DOT_SH3_SH(src32_l, src54_l, src76_l, filt0, filt1, filt2); + vt_res2 = AVC_DOT_SH3_SH(src43_r, src65_r, src87_r, filt0, filt1, filt2); + vt_res3 = AVC_DOT_SH3_SH(src43_l, src65_l, src87_l, filt0, filt1, filt2); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec6); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec7); + hz_res2 = __msa_hadd_s_w(shf_vec0, shf_vec0); + DPADD_SH2_SW(shf_vec1, shf_vec6, minus5h, plus20h, hz_res2, hz_res2); + hz_res3 = __msa_hadd_s_w(shf_vec3, shf_vec3); + DPADD_SH2_SW(shf_vec4, shf_vec7, minus5h, plus20h, hz_res3, hz_res3); + + SRARI_W2_SW(hz_res0, hz_res1, 10); + SAT_SW2_SW(hz_res0, hz_res1, 7); + SRARI_W2_SW(hz_res2, hz_res3, 10); + SAT_SW2_SW(hz_res2, hz_res3, 7); + + dst0 = __msa_srari_h(shf_vec2, 5); + dst1 = __msa_srari_h(shf_vec5, 5); + dst2 = __msa_srari_h(shf_vec6, 5); + dst3 = __msa_srari_h(shf_vec7, 5); + + SAT_SH2_SH(dst0, dst1, 7); + SAT_SH2_SH(dst2, dst3, 7); + ILVEV_H2_SH(dst0, zeros, dst1, zeros, dst0, dst1); + ILVEV_H2_SH(dst2, zeros, dst3, zeros, dst2, dst3); + + hz_res0 = __msa_aver_s_w(hz_res0, (v4i32) dst0); + hz_res1 = __msa_aver_s_w(hz_res1, (v4i32) dst1); + hz_res2 = __msa_aver_s_w(hz_res2, (v4i32) dst2); + hz_res3 = __msa_aver_s_w(hz_res3, (v4i32) dst3); + + PCKEV_H2_SH(hz_res1, hz_res0, hz_res3, hz_res2, dst0, dst2); + out = PCKEV_XORI128_UB(dst0, dst2); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, stride); +} + +void ff_put_h264_qpel4_mc32_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + v16u8 out; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 src10_r, src21_r, src32_r, src43_r, src54_r, src65_r, src76_r; + v16i8 src87_r, src10_l, src21_l, src32_l, src43_l, src54_l, src65_l; + v16i8 src76_l, src87_l, filt0, filt1, filt2; + v8i16 vt_res0, vt_res1, vt_res2, vt_res3, dst0, dst1, dst2, dst3, shf_vec7; + v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5, shf_vec6; + v4i32 hz_res0, hz_res1, hz_res2, hz_res3; + v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; + v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; + v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; + v8i16 minus5h = __msa_ldi_h(-5); + v8i16 plus20h = __msa_ldi_h(20); + v8i16 zeros = { 0 }; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + LD_SB4(src, stride, src5, src6, src7, src8); + XORI_B4_128_SB(src5, src6, src7, src8); + + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_r, src65_r, + src76_r, src87_r); + ILVL_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_l, src21_l, + src32_l, src43_l); + ILVL_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_l, src65_l, + src76_l, src87_l); + + vt_res0 = AVC_DOT_SH3_SH(src10_r, src32_r, src54_r, filt0, filt1, filt2); + vt_res1 = AVC_DOT_SH3_SH(src10_l, src32_l, src54_l, filt0, filt1, filt2); + vt_res2 = AVC_DOT_SH3_SH(src21_r, src43_r, src65_r, filt0, filt1, filt2); + vt_res3 = AVC_DOT_SH3_SH(src21_l, src43_l, src65_l, filt0, filt1, filt2); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec2); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec5); + hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); + DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); + hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); + DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); + + vt_res0 = AVC_DOT_SH3_SH(src32_r, src54_r, src76_r, filt0, filt1, filt2); + vt_res1 = AVC_DOT_SH3_SH(src32_l, src54_l, src76_l, filt0, filt1, filt2); + vt_res2 = AVC_DOT_SH3_SH(src43_r, src65_r, src87_r, filt0, filt1, filt2); + vt_res3 = AVC_DOT_SH3_SH(src43_l, src65_l, src87_l, filt0, filt1, filt2); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec6); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec7); + hz_res2 = __msa_hadd_s_w(shf_vec0, shf_vec0); + DPADD_SH2_SW(shf_vec1, shf_vec6, minus5h, plus20h, hz_res2, hz_res2); + hz_res3 = __msa_hadd_s_w(shf_vec3, shf_vec3); + DPADD_SH2_SW(shf_vec4, shf_vec7, minus5h, plus20h, hz_res3, hz_res3); + + SRARI_W2_SW(hz_res0, hz_res1, 10); + SAT_SW2_SW(hz_res0, hz_res1, 7); + SRARI_W2_SW(hz_res2, hz_res3, 10); + SAT_SW2_SW(hz_res2, hz_res3, 7); + + dst0 = __msa_srari_h(shf_vec2, 5); + dst1 = __msa_srari_h(shf_vec5, 5); + dst2 = __msa_srari_h(shf_vec6, 5); + dst3 = __msa_srari_h(shf_vec7, 5); + + SAT_SH2_SH(dst0, dst1, 7); + SAT_SH2_SH(dst2, dst3, 7); + + dst0 = __msa_ilvod_h(zeros, dst0); + dst1 = __msa_ilvod_h(zeros, dst1); + dst2 = __msa_ilvod_h(zeros, dst2); + dst3 = __msa_ilvod_h(zeros, dst3); + + hz_res0 = __msa_aver_s_w(hz_res0, (v4i32) dst0); + hz_res1 = __msa_aver_s_w(hz_res1, (v4i32) dst1); + hz_res2 = __msa_aver_s_w(hz_res2, (v4i32) dst2); + hz_res3 = __msa_aver_s_w(hz_res3, (v4i32) dst3); + + PCKEV_H2_SH(hz_res1, hz_res0, hz_res3, hz_res2, dst0, dst2); + out = PCKEV_XORI128_UB(dst0, dst2); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, stride); +} + +void ff_put_h264_qpel16_mc22_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + const int32_t filt_const0 = 0xfffb0001; + const int32_t filt_const1 = 0x140014; + const int32_t filt_const2 = 0x1fffb; + const uint8_t *src_tmp = src - (2 * stride) - 2; + uint8_t *dst_tmp = dst; + uint32_t multiple8_cnt, loop_cnt; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4, mask0, mask1, mask2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + v8i16 hz_out7, hz_out8, dst0, dst1, dst2, dst3; + v8i16 hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r, hz_out54_r; + v8i16 hz_out65_r, hz_out76_r, hz_out87_r, hz_out10_l, hz_out21_l; + v8i16 hz_out32_l, hz_out43_l, hz_out54_l, hz_out65_l, hz_out76_l; + v8i16 hz_out87_l, filt0, filt1, filt2; + v4i32 tmp0, tmp1; + + filt0 = (v8i16) __msa_fill_w(filt_const0); + filt1 = (v8i16) __msa_fill_w(filt_const1); + filt2 = (v8i16) __msa_fill_w(filt_const2); + + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + + for (multiple8_cnt = 2; multiple8_cnt--;) { + src = src_tmp; + dst = dst_tmp; + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + src += (5 * stride); + + hz_out0 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src, stride, src0, src1, src2, src3); + XORI_B4_128_SB(src0, src1, src2, src3); + src += (4 * stride); + + hz_out5 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out6 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out7 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out8 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + + ILVR_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, + hz_out4, hz_out3, hz_out10_r, hz_out21_r, hz_out32_r, + hz_out43_r); + ILVL_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, + hz_out4, hz_out3, hz_out10_l, hz_out21_l, hz_out32_l, + hz_out43_l); + ILVR_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, + hz_out8, hz_out7, hz_out54_r, hz_out65_r, hz_out76_r, + hz_out87_r); + ILVL_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, + hz_out8, hz_out7, hz_out54_l, hz_out65_l, hz_out76_l, + hz_out87_l); + + tmp0 = AVC_DOT_SW3_SW(hz_out10_r, hz_out32_r, hz_out54_r, filt0, + filt1, filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out10_l, hz_out32_l, hz_out54_l, filt0, + filt1, filt2); + dst0 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out21_r, hz_out43_r, hz_out65_r, filt0, + filt1, filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out21_l, hz_out43_l, hz_out65_l, filt0, + filt1, filt2); + dst1 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out32_r, hz_out54_r, hz_out76_r, filt0, + filt1, filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out32_l, hz_out54_l, hz_out76_l, filt0, + filt1, filt2); + dst2 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out43_r, hz_out65_r, hz_out87_r, filt0, + filt1, filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out43_l, hz_out65_l, hz_out87_l, filt0, + filt1, filt2); + dst3 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + + out0 = PCKEV_XORI128_UB(dst0, dst1); + out1 = PCKEV_XORI128_UB(dst2, dst3); + ST8x4_UB(out0, out1, dst, stride); + dst += (4 * stride); + + hz_out0 = hz_out4; + hz_out1 = hz_out5; + hz_out2 = hz_out6; + hz_out3 = hz_out7; + hz_out4 = hz_out8; + } + + src_tmp += 8; + dst_tmp += 8; + } } void ff_put_h264_qpel8_mc22_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_mid_8w_msa(src - (2 * stride) - 2, stride, dst, stride, 8); + const int32_t filt_const0 = 0xfffb0001; + const int32_t filt_const1 = 0x140014; + const int32_t filt_const2 = 0x1fffb; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4, mask0, mask1, mask2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + v8i16 hz_out7, hz_out8, hz_out9, hz_out10, hz_out11, hz_out12; + v8i16 hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r, hz_out54_r; + v8i16 hz_out65_r, hz_out76_r, hz_out87_r, hz_out89_r, hz_out910_r; + v8i16 hz_out1110_r, hz_out1211_r, dst0, dst1, dst2, dst3; + v8i16 hz_out10_l, hz_out21_l, hz_out32_l, hz_out43_l, hz_out54_l; + v8i16 hz_out65_l, hz_out76_l, hz_out87_l, hz_out89_l, hz_out910_l; + v8i16 hz_out1110_l, hz_out1211_l, filt0, filt1, filt2; + v4i32 tmp0, tmp1; + + filt0 = (v8i16) __msa_fill_w(filt_const0); + filt1 = (v8i16) __msa_fill_w(filt_const1); + filt2 = (v8i16) __msa_fill_w(filt_const2); + + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + + src -= ((2 * stride) + 2); + LD_SB5(src, stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + src += (5 * stride); + + hz_out0 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); + + LD_SB4(src, stride, src0, src1, src2, src3); + XORI_B4_128_SB(src0, src1, src2, src3); + src += (4 * stride); + hz_out5 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out6 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out7 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out8 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + ILVR_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, hz_out4, + hz_out3, hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r); + ILVL_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, hz_out4, + hz_out3, hz_out10_l, hz_out21_l, hz_out32_l, hz_out43_l); + ILVR_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, hz_out8, + hz_out7, hz_out54_r, hz_out65_r, hz_out76_r, hz_out87_r); + ILVL_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, hz_out8, + hz_out7, hz_out54_l, hz_out65_l, hz_out76_l, hz_out87_l); + + tmp0 = AVC_DOT_SW3_SW(hz_out10_r, hz_out32_r, hz_out54_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out10_l, hz_out32_l, hz_out54_l, filt0, filt1, + filt2); + dst0 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out21_r, hz_out43_r, hz_out65_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out21_l, hz_out43_l, hz_out65_l, filt0, filt1, + filt2); + dst1 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out32_r, hz_out54_r, hz_out76_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out32_l, hz_out54_l, hz_out76_l, filt0, filt1, + filt2); + dst2 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out43_r, hz_out65_r, hz_out87_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out43_l, hz_out65_l, hz_out87_l, filt0, filt1, + filt2); + dst3 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + out0 = PCKEV_XORI128_UB(dst0, dst1); + out1 = PCKEV_XORI128_UB(dst2, dst3); + ST8x4_UB(out0, out1, dst, stride); + dst += (4 * stride); + + LD_SB4(src, stride, src0, src1, src2, src3); + XORI_B4_128_SB(src0, src1, src2, src3); + hz_out9 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out10 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out11 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out12 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + ILVR_H4_SH(hz_out9, hz_out8, hz_out10, hz_out9, hz_out11, hz_out10, + hz_out12, hz_out11, hz_out89_r, hz_out910_r, hz_out1110_r, + hz_out1211_r); + ILVL_H4_SH(hz_out9, hz_out8, hz_out10, hz_out9, hz_out11, hz_out10, + hz_out12, hz_out11, hz_out89_l, hz_out910_l, hz_out1110_l, + hz_out1211_l); + tmp0 = AVC_DOT_SW3_SW(hz_out54_r, hz_out76_r, hz_out89_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out54_l, hz_out76_l, hz_out89_l, filt0, filt1, + filt2); + dst0 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out65_r, hz_out87_r, hz_out910_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out65_l, hz_out87_l, hz_out910_l, filt0, filt1, + filt2); + dst1 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out76_r, hz_out89_r, hz_out1110_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out76_l, hz_out89_l, hz_out1110_l, filt0, filt1, + filt2); + dst2 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out87_r, hz_out910_r, hz_out1211_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out87_l, hz_out910_l, hz_out1211_l, filt0, filt1, + filt2); + dst3 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + out0 = PCKEV_XORI128_UB(dst0, dst1); + out1 = PCKEV_XORI128_UB(dst2, dst3); + ST8x4_UB(out0, out1, dst, stride); } void ff_put_h264_qpel4_mc22_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_mid_4w_msa(src - (2 * stride) - 2, stride, dst, stride, 4); + const int32_t filt_const0 = 0xfffb0001; + const int32_t filt_const1 = 0x140014; + const int32_t filt_const2 = 0x1fffb; + v16u8 res; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 mask0, mask1, mask2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + v8i16 hz_out7, hz_out8, dst0, dst1, filt0, filt1, filt2; + v8i16 hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r, hz_out54_r; + v8i16 hz_out65_r, hz_out76_r, hz_out87_r; + v4i32 tmp0, tmp1; + + LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); + + filt0 = (v8i16) __msa_fill_w(filt_const0); + filt1 = (v8i16) __msa_fill_w(filt_const1); + filt2 = (v8i16) __msa_fill_w(filt_const2); + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + LD_SB4(src, stride, src5, src6, src7, src8); + + XORI_B5_128_SB(src0, src1, src2, src3, src4); + XORI_B4_128_SB(src5, src6, src7, src8); + hz_out0 = AVC_HORZ_FILTER_SH(src0, src1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src2, src3, mask0, mask1, mask2); + hz_out4 = AVC_HORZ_FILTER_SH(src4, src5, mask0, mask1, mask2); + hz_out6 = AVC_HORZ_FILTER_SH(src6, src7, mask0, mask1, mask2); + hz_out8 = AVC_HORZ_FILTER_SH(src8, src8, mask0, mask1, mask2); + PCKOD_D2_SH(hz_out0, hz_out0, hz_out2, hz_out2, hz_out1, hz_out3); + PCKOD_D2_SH(hz_out4, hz_out4, hz_out6, hz_out6, hz_out5, hz_out7); + ILVR_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, hz_out4, + hz_out3, hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r); + ILVR_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, hz_out8, + hz_out7, hz_out54_r, hz_out65_r, hz_out76_r, hz_out87_r); + + tmp0 = AVC_DOT_SW3_SW(hz_out10_r, hz_out32_r, hz_out54_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out21_r, hz_out43_r, hz_out65_r, filt0, filt1, + filt2); + dst0 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out32_r, hz_out54_r, hz_out76_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out43_r, hz_out65_r, hz_out87_r, filt0, filt1, + filt2); + dst1 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + res = PCKEV_XORI128_UB(dst0, dst1); + ST4x4_UB(res, res, 0, 1, 2, 3, dst, stride); } void ff_avg_h264_qpel16_mc10_msa(uint8_t *dst, const uint8_t *src, From e63758468c6420871c883fb96b8b6832adb5b2ee Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Wed, 11 Oct 2017 14:19:27 +0530 Subject: [PATCH 0464/2557] avcodec/mips: Improve hevc bi copy mc msa functions Load the specific destination bytes instead of MSA load and pack. Use immediate unsigned saturation for clip to max saving one vector register. Signed-off-by: Kaustubh Raste Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_bi_msa.c | 652 +++++++++++++++++-------------- 1 file changed, 366 insertions(+), 286 deletions(-) diff --git a/libavcodec/mips/hevc_mc_bi_msa.c b/libavcodec/mips/hevc_mc_bi_msa.c index 8208be327dabf..ccc3f8a64f741 100644 --- a/libavcodec/mips/hevc_mc_bi_msa.c +++ b/libavcodec/mips/hevc_mc_bi_msa.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Manojkumar Bhosale (Manojkumar.Bhosale@imgtec.com) + * Copyright (c) 2015 - 2017 Manojkumar Bhosale (Manojkumar.Bhosale@imgtec.com) * * This file is part of FFmpeg. * @@ -37,6 +37,21 @@ HEVC_BI_RND_CLIP2(in2, in3, vec2, vec3, rnd_val, out2, out3); \ } +#define HEVC_BI_RND_CLIP2_MAX_SATU(in0, in1, vec0, vec1, rnd_val, \ + out0, out1) \ +{ \ + ADDS_SH2_SH(vec0, in0, vec1, in1, out0, out1); \ + SRARI_H2_SH(out0, out1, rnd_val); \ + CLIP_SH2_0_255_MAX_SATU(out0, out1); \ +} + +#define HEVC_BI_RND_CLIP4_MAX_SATU(in0, in1, in2, in3, vec0, vec1, vec2, \ + vec3, rnd_val, out0, out1, out2, out3) \ +{ \ + HEVC_BI_RND_CLIP2_MAX_SATU(in0, in1, vec0, vec1, rnd_val, out0, out1); \ + HEVC_BI_RND_CLIP2_MAX_SATU(in2, in3, vec2, vec3, rnd_val, out2, out3); \ +} + static void hevc_bi_copy_4w_msa(uint8_t *src0_ptr, int32_t src_stride, int16_t *src1_ptr, @@ -45,71 +60,59 @@ static void hevc_bi_copy_4w_msa(uint8_t *src0_ptr, int32_t dst_stride, int32_t height) { + uint32_t loop_cnt, tp0, tp1, tp2, tp3; + uint64_t tpd0, tpd1, tpd2, tpd3; + v16i8 src0 = { 0 }, src1 = { 0 }; v16i8 zero = { 0 }; + v8i16 in0 = { 0 }, in1 = { 0 }, in2 = { 0 }, in3 = { 0 }; + v8i16 dst0, dst1, dst2, dst3; if (2 == height) { - v16i8 src0, src1; - v8i16 dst0, in0, in1; - - LD_SB2(src0_ptr, src_stride, src0, src1); - LD_SH2(src1_ptr, src2_stride, in0, in1); - - src0 = (v16i8) __msa_ilvr_w((v4i32) src1, (v4i32) src0); - in0 = (v8i16) __msa_ilvr_d((v2i64) in1, (v2i64) in0); + LW2(src0_ptr, src_stride, tp0, tp1); + INSERT_W2_SB(tp0, tp1, src0); + LD2(src1_ptr, src2_stride, tpd0, tpd1); + INSERT_D2_SH(tpd0, tpd1, in0); dst0 = (v8i16) __msa_ilvr_b(zero, src0); dst0 <<= 6; dst0 += in0; dst0 = __msa_srari_h(dst0, 7); - dst0 = CLIP_SH_0_255(dst0); + dst0 = CLIP_SH_0_255_MAX_SATU(dst0); dst0 = (v8i16) __msa_pckev_b((v16i8) dst0, (v16i8) dst0); ST4x2_UB(dst0, dst, dst_stride); } else if (4 == height) { - v16i8 src0, src1, src2, src3; - v8i16 dst0, dst1; - v8i16 in0, in1, in2, in3; - - LD_SB4(src0_ptr, src_stride, src0, src1, src2, src3); - LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); - ILVR_W2_SB(src1, src0, src3, src2, src0, src1); - ILVR_D2_SH(in1, in0, in3, in2, in0, in1); - ILVR_B2_SH(zero, src0, zero, src1, dst0, dst1); - - dst0 <<= 6; - dst1 <<= 6; - HEVC_BI_RND_CLIP2(in0, in1, dst0, dst1, 7, dst0, dst1); - + LW4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); + INSERT_W4_SB(tp0, tp1, tp2, tp3, src0); + LD4(src1_ptr, src2_stride, tpd0, tpd1, tpd2, tpd3); + INSERT_D2_SH(tpd0, tpd1, in0); + INSERT_D2_SH(tpd2, tpd3, in1); + ILVRL_B2_SH(zero, src0, dst0, dst1); + SLLI_2V(dst0, dst1, 6); + HEVC_BI_RND_CLIP2_MAX_SATU(in0, in1, dst0, dst1, 7, dst0, dst1); dst0 = (v8i16) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); ST4x4_UB(dst0, dst0, 0, 1, 2, 3, dst, dst_stride); } else if (0 == height % 8) { - uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7; - v8i16 dst0, dst1, dst2, dst3; - v8i16 in0, in1, in2, in3, in4, in5, in6, in7; - for (loop_cnt = (height >> 3); loop_cnt--;) { - LD_SB8(src0_ptr, src_stride, - src0, src1, src2, src3, src4, src5, src6, src7); - src0_ptr += (8 * src_stride); - - LD_SH8(src1_ptr, src2_stride, - in0, in1, in2, in3, in4, in5, in6, in7); - src1_ptr += (8 * src2_stride); - - ILVR_D2_SH(in1, in0, in3, in2, in0, in1); - ILVR_D2_SH(in5, in4, in7, in6, in2, in3); - - ILVR_W4_SB(src1, src0, src3, src2, src5, src4, src7, src6, - src0, src1, src2, src3); - ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - dst0, dst1, dst2, dst3); - + LW4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); + src0_ptr += 4 * src_stride; + INSERT_W4_SB(tp0, tp1, tp2, tp3, src0); + LW4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); + src0_ptr += 4 * src_stride; + INSERT_W4_SB(tp0, tp1, tp2, tp3, src1); + LD4(src1_ptr, src2_stride, tpd0, tpd1, tpd2, tpd3); + src1_ptr += (4 * src2_stride); + INSERT_D2_SH(tpd0, tpd1, in0); + INSERT_D2_SH(tpd2, tpd3, in1); + LD4(src1_ptr, src2_stride, tpd0, tpd1, tpd2, tpd3); + src1_ptr += (4 * src2_stride); + INSERT_D2_SH(tpd0, tpd1, in2); + INSERT_D2_SH(tpd2, tpd3, in3); + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); SLLI_4V(dst0, dst1, dst2, dst3, 6); - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - dst0, dst1, dst2, dst3, 7, - dst0, dst1, dst2, dst3); - + HEVC_BI_RND_CLIP4_MAX_SATU(in0, in1, in2, in3, dst0, dst1, dst2, + dst3, 7, dst0, dst1, dst2, dst3); PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); ST4x8_UB(dst0, dst1, dst, dst_stride); dst += (8 * dst_stride); @@ -126,36 +129,39 @@ static void hevc_bi_copy_6w_msa(uint8_t *src0_ptr, int32_t height) { uint32_t loop_cnt; + uint64_t tp0, tp1, tp2, tp3; + v16u8 out0, out1, out2, out3; v16i8 zero = { 0 }; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7; + v16i8 src0 = { 0 }, src1 = { 0 }, src2 = { 0 }, src3 = { 0 }; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; for (loop_cnt = (height >> 3); loop_cnt--;) { - LD_SB8(src0_ptr, src_stride, - src0, src1, src2, src3, src4, src5, src6, src7); - src0_ptr += (8 * src_stride); + LD4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); + src0_ptr += (4 * src_stride); + INSERT_D2_SB(tp0, tp1, src0); + INSERT_D2_SB(tp2, tp3, src1); + LD4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); + src0_ptr += (4 * src_stride); + INSERT_D2_SB(tp0, tp1, src2); + INSERT_D2_SB(tp2, tp3, src3); LD_SH8(src1_ptr, src2_stride, in0, in1, in2, in3, in4, in5, in6, in7); src1_ptr += (8 * src2_stride); - ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - dst0, dst1, dst2, dst3); - ILVR_B4_SH(zero, src4, zero, src5, zero, src6, zero, src7, - dst4, dst5, dst6, dst7); - + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); + ILVRL_B2_SH(zero, src2, dst4, dst5); + ILVRL_B2_SH(zero, src3, dst6, dst7); SLLI_4V(dst0, dst1, dst2, dst3, 6); SLLI_4V(dst4, dst5, dst6, dst7, 6); - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); - - PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); - ST6x4_UB(dst0, dst1, dst, dst_stride); + HEVC_BI_RND_CLIP4_MAX_SATU(in0, in1, in2, in3, dst0, dst1, dst2, dst3, + 7, dst0, dst1, dst2, dst3); + HEVC_BI_RND_CLIP4_MAX_SATU(in4, in5, in6, in7, dst4, dst5, dst6, dst7, + 7, dst4, dst5, dst6, dst7); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + PCKEV_B2_UB(dst5, dst4, dst7, dst6, out2, out3); + ST6x4_UB(out0, out1, dst, dst_stride); dst += (4 * dst_stride); - - HEVC_BI_RND_CLIP4(in4, in5, in6, in7, - dst4, dst5, dst6, dst7, 7, dst4, dst5, dst6, dst7); - - PCKEV_B2_SH(dst5, dst4, dst7, dst6, dst4, dst5); - ST6x4_UB(dst4, dst5, dst, dst_stride); + ST6x4_UB(out2, out3, dst, dst_stride); dst += (4 * dst_stride); } } @@ -168,100 +174,83 @@ static void hevc_bi_copy_8w_msa(uint8_t *src0_ptr, int32_t dst_stride, int32_t height) { + uint64_t tp0, tp1, tp2, tp3; + v16u8 out0, out1, out2, out3; + v16i8 src0 = { 0 }, src1 = { 0 }, src2 = { 0 }, src3 = { 0 }; v16i8 zero = { 0 }; + v8i16 in0, in1, in2, in3, in4, in5, in6, in7; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; if (2 == height) { - v16i8 src0, src1; - v8i16 in0, in1; - v8i16 dst0, dst1; - - LD_SB2(src0_ptr, src_stride, src0, src1); + LD2(src0_ptr, src_stride, tp0, tp1); + INSERT_D2_SB(tp0, tp1, src0); LD_SH2(src1_ptr, src2_stride, in0, in1); - ILVR_B2_SH(zero, src0, zero, src1, dst0, dst1); - - dst0 <<= 6; - dst1 <<= 6; - HEVC_BI_RND_CLIP2(in0, in1, dst0, dst1, 7, dst0, dst1); - - dst0 = (v8i16) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); - ST8x2_UB(dst0, dst, dst_stride); + ILVRL_B2_SH(zero, src0, dst0, dst1); + SLLI_2V(dst0, dst1, 6); + HEVC_BI_RND_CLIP2_MAX_SATU(in0, in1, dst0, dst1, 7, dst0, dst1); + out0 = (v16u8) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); + ST8x2_UB(out0, dst, dst_stride); } else if (4 == height) { - v16i8 src0, src1, src2, src3; - v8i16 in0, in1, in2, in3; - v8i16 dst0, dst1, dst2, dst3; - - LD_SB4(src0_ptr, src_stride, src0, src1, src2, src3); + LD4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); + INSERT_D2_SB(tp0, tp1, src0); + INSERT_D2_SB(tp2, tp3, src1); + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); - ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - dst0, dst1, dst2, dst3); - SLLI_4V(dst0, dst1, dst2, dst3, 6); - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); - - PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); - ST8x4_UB(dst0, dst1, dst, dst_stride); + HEVC_BI_RND_CLIP4_MAX_SATU(in0, in1, in2, in3, dst0, dst1, dst2, dst3, + 7, dst0, dst1, dst2, dst3); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + ST8x4_UB(out0, out1, dst, dst_stride); } else if (6 == height) { - v16i8 src0, src1, src2, src3, src4, src5; - v8i16 in0, in1, in2, in3, in4, in5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - - LD_SB6(src0_ptr, src_stride, src0, src1, src2, src3, src4, src5); + LD4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); + src0_ptr += 4 * src_stride; + INSERT_D2_SB(tp0, tp1, src0); + INSERT_D2_SB(tp2, tp3, src1); + LD2(src0_ptr, src_stride, tp0, tp1); + INSERT_D2_SB(tp0, tp1, src2); + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); + ILVRL_B2_SH(zero, src2, dst4, dst5); LD_SH6(src1_ptr, src2_stride, in0, in1, in2, in3, in4, in5); - ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - dst0, dst1, dst2, dst3); - ILVR_B2_SH(zero, src4, zero, src5, dst4, dst5); - SLLI_4V(dst0, dst1, dst2, dst3, 6); - dst4 <<= 6; - dst5 <<= 6; - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); - HEVC_BI_RND_CLIP2(in4, in5, dst4, dst5, 7, dst4, dst5); - - PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); - dst2 = (v8i16) __msa_pckev_b((v16i8) dst5, (v16i8) dst4); - ST8x4_UB(dst0, dst1, dst, dst_stride); + SLLI_2V(dst4, dst5, 6); + HEVC_BI_RND_CLIP4_MAX_SATU(in0, in1, in2, in3, dst0, dst1, dst2, dst3, + 7, dst0, dst1, dst2, dst3); + HEVC_BI_RND_CLIP2_MAX_SATU(in4, in5, dst4, dst5, 7, dst4, dst5); + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + ST8x4_UB(out0, out1, dst, dst_stride); dst += (4 * dst_stride); - ST8x2_UB(dst2, dst, dst_stride); + ST8x2_UB(out2, dst, dst_stride); } else if (0 == height % 8) { - v16i8 src0, src1, src2, src3; - v8i16 in0, in1, in2, in3; - v8i16 dst0, dst1, dst2, dst3; uint32_t loop_cnt; for (loop_cnt = (height >> 3); loop_cnt--;) { - LD_SB4(src0_ptr, src_stride, src0, src1, src2, src3); - src0_ptr += (4 * src_stride); - LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); - src1_ptr += (4 * src2_stride); - ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - dst0, dst1, dst2, dst3); - - SLLI_4V(dst0, dst1, dst2, dst3, 6); - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - dst0, dst1, dst2, dst3, 7, - dst0, dst1, dst2, dst3); - - PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); - ST8x4_UB(dst0, dst1, dst, dst_stride); - dst += (4 * dst_stride); - - LD_SB4(src0_ptr, src_stride, src0, src1, src2, src3); - src0_ptr += (4 * src_stride); - LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); - src1_ptr += (4 * src2_stride); - ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - dst0, dst1, dst2, dst3); - + LD4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); + src0_ptr += 4 * src_stride; + INSERT_D2_SB(tp0, tp1, src0); + INSERT_D2_SB(tp2, tp3, src1); + LD4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); + src0_ptr += 4 * src_stride; + INSERT_D2_SB(tp0, tp1, src2); + INSERT_D2_SB(tp2, tp3, src3); + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); + ILVRL_B2_SH(zero, src2, dst4, dst5); + ILVRL_B2_SH(zero, src3, dst6, dst7); + LD_SH8(src1_ptr, src2_stride, in0, in1, in2, in3, in4, in5, in6, + in7); + src1_ptr += (8 * src2_stride); SLLI_4V(dst0, dst1, dst2, dst3, 6); - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - dst0, dst1, dst2, dst3, 7, - dst0, dst1, dst2, dst3); - - PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); - ST8x4_UB(dst0, dst1, dst, dst_stride); - dst += (4 * dst_stride); + SLLI_4V(dst4, dst5, dst6, dst7, 6); + HEVC_BI_RND_CLIP4_MAX_SATU(in0, in1, in2, in3, dst0, dst1, dst2, + dst3, 7, dst0, dst1, dst2, dst3); + HEVC_BI_RND_CLIP4_MAX_SATU(in4, in5, in6, in7, dst4, dst5, dst6, + dst7, 7, dst4, dst5, dst6, dst7); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + PCKEV_B2_UB(dst5, dst4, dst7, dst6, out2, out3); + ST8x8_UB(out0, out1, out2, out3, dst, dst_stride); + dst += (8 * dst_stride); } } } @@ -275,12 +264,13 @@ static void hevc_bi_copy_12w_msa(uint8_t *src0_ptr, int32_t height) { uint32_t loop_cnt; + v16i8 zero = { 0 }; + v16u8 out0, out1, out2; v16i8 src0, src1, src2, src3; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v16i8 zero = { 0 }; - for (loop_cnt = (16 >> 2); loop_cnt--;) { + for (loop_cnt = 4; loop_cnt--;) { LD_SB4(src0_ptr, src_stride, src0, src1, src2, src3); src0_ptr += (4 * src_stride); @@ -288,88 +278,21 @@ static void hevc_bi_copy_12w_msa(uint8_t *src0_ptr, LD_SH4(src1_ptr + 8, src2_stride, in4, in5, in6, in7); src1_ptr += (4 * src2_stride); ILVR_D2_SH(in5, in4, in7, in6, in4, in5); - ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - dst0, dst1, dst2, dst3); - + ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, dst0, dst1, + dst2, dst3); SLLI_4V(dst0, dst1, dst2, dst3, 6); ILVL_W2_SB(src1, src0, src3, src2, src0, src1); ILVR_B2_SH(zero, src0, zero, src1, dst4, dst5); - dst4 <<= 6; - dst5 <<= 6; - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); - HEVC_BI_RND_CLIP2(in4, in5, dst4, dst5, 7, dst4, dst5); - - PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); - dst2 = (v8i16) __msa_pckev_b((v16i8) dst5, (v16i8) dst4); - ST12x4_UB(dst0, dst1, dst2, dst, dst_stride); + SLLI_2V(dst4, dst5, 6); + HEVC_BI_RND_CLIP4_MAX_SATU(in0, in1, in2, in3, dst0, dst1, dst2, dst3, + 7, dst0, dst1, dst2, dst3); + HEVC_BI_RND_CLIP2_MAX_SATU(in4, in5, dst4, dst5, 7, dst4, dst5); + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + ST12x4_UB(out0, out1, out2, dst, dst_stride); dst += (4 * dst_stride); } } -static void hevc_bi_copy_16multx4mult_msa(uint8_t *src0_ptr, - int32_t src_stride, - int16_t *src1_ptr, - int32_t src2_stride, - uint8_t *dst, - int32_t dst_stride, - int32_t height, - int32_t width) -{ - uint32_t loop_cnt; - uint32_t cnt; - uint8_t *src0_ptr_tmp; - int16_t *src1_ptr_tmp; - uint8_t *dst_tmp; - v16i8 zero = { 0 }; - - for (cnt = (width >> 4); cnt--;) { - src0_ptr_tmp = src0_ptr; - src1_ptr_tmp = src1_ptr; - dst_tmp = dst; - - for (loop_cnt = (height >> 2); loop_cnt--;) { - v16i8 src0, src1, src2, src3; - v8i16 in0, in1, in2, in3, in4, in5, in6, in7; - v8i16 dst0_r, dst1_r, dst2_r, dst3_r; - v8i16 dst0_l, dst1_l, dst2_l, dst3_l; - - LD_SB4(src0_ptr_tmp, src_stride, src0, src1, src2, src3); - src0_ptr_tmp += (4 * src_stride); - LD_SH4(src1_ptr_tmp, src2_stride, in0, in1, in2, in3); - LD_SH4(src1_ptr_tmp + 8, src2_stride, in4, in5, in6, in7); - src1_ptr_tmp += (4 * src2_stride); - - ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - dst0_r, dst1_r, dst2_r, dst3_r); - ILVL_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - dst0_l, dst1_l, dst2_l, dst3_l); - - SLLI_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); - SLLI_4V(dst0_l, dst1_l, dst2_l, dst3_l, 6); - HEVC_BI_RND_CLIP4(in0, in1, in4, in5, - dst0_r, dst1_r, dst0_l, dst1_l, 7, - dst0_r, dst1_r, dst0_l, dst1_l); - - PCKEV_B2_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r, dst1_r); - ST_SH2(dst0_r, dst1_r, dst_tmp, dst_stride); - dst_tmp += (2 * dst_stride); - - HEVC_BI_RND_CLIP4(in2, in3, in6, in7, - dst2_r, dst3_r, dst2_l, dst3_l, 7, - dst2_r, dst3_r, dst2_l, dst3_l); - - PCKEV_B2_SH(dst2_l, dst2_r, dst3_l, dst3_r, dst2_r, dst3_r); - ST_SH2(dst2_r, dst3_r, dst_tmp, dst_stride); - dst_tmp += (2 * dst_stride); - } - - src0_ptr += 16; - src1_ptr += 16; - dst += 16; - } -} - static void hevc_bi_copy_16w_msa(uint8_t *src0_ptr, int32_t src_stride, int16_t *src1_ptr, @@ -378,8 +301,34 @@ static void hevc_bi_copy_16w_msa(uint8_t *src0_ptr, int32_t dst_stride, int32_t height) { - hevc_bi_copy_16multx4mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, height, 16); + uint32_t loop_cnt; + v16u8 out0, out1, out2, out3; + v16i8 src0, src1, src2, src3; + v8i16 in0, in1, in2, in3, in4, in5, in6, in7; + v8i16 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; + v16i8 zero = { 0 }; + + for (loop_cnt = (height >> 2); loop_cnt--;) { + LD_SB4(src0_ptr, src_stride, src0, src1, src2, src3); + src0_ptr += (4 * src_stride); + LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); + LD_SH4(src1_ptr + 8, src2_stride, in4, in5, in6, in7); + src1_ptr += (4 * src2_stride); + ILVRL_B2_SH(zero, src0, dst0_r, dst0_l); + ILVRL_B2_SH(zero, src1, dst1_r, dst1_l); + ILVRL_B2_SH(zero, src2, dst2_r, dst2_l); + ILVRL_B2_SH(zero, src3, dst3_r, dst3_l); + SLLI_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SLLI_4V(dst0_l, dst1_l, dst2_l, dst3_l, 6); + HEVC_BI_RND_CLIP4_MAX_SATU(in0, in1, in4, in5, dst0_r, dst1_r, dst0_l, + dst1_l, 7, dst0_r, dst1_r, dst0_l, dst1_l); + HEVC_BI_RND_CLIP4_MAX_SATU(in2, in3, in6, in7, dst2_r, dst3_r, dst2_l, + dst3_l, 7, dst2_r, dst3_r, dst2_l, dst3_l); + PCKEV_B2_UB(dst0_l, dst0_r, dst1_l, dst1_r, out0, out1); + PCKEV_B2_UB(dst2_l, dst2_r, dst3_l, dst3_r, out2, out3); + ST_UB4(out0, out1, out2, out3, dst, dst_stride); + dst += (4 * dst_stride); + } } static void hevc_bi_copy_24w_msa(uint8_t *src0_ptr, @@ -390,11 +339,42 @@ static void hevc_bi_copy_24w_msa(uint8_t *src0_ptr, int32_t dst_stride, int32_t height) { - hevc_bi_copy_16multx4mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, height, 16); + uint32_t loop_cnt; + v16u8 out0, out1, out2, out3, out4, out5; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, zero = { 0 }; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8, dst9, dst10; + v8i16 in0, in1, in2, in3, in4, in5, in6, in7, in8, in9, in10, in11, dst11; + + for (loop_cnt = 8; loop_cnt--;) { + LD_SB4(src0_ptr, src_stride, src0, src1, src4, src5); + LD_SB4(src0_ptr + 16, src_stride, src2, src3, src6, src7); + src0_ptr += (4 * src_stride); + LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); + LD_SH4(src1_ptr + 8, src2_stride, in4, in5, in6, in7); + LD_SH4(src1_ptr + 16, src2_stride, in8, in9, in10, in11); + src1_ptr += (4 * src2_stride); - hevc_bi_copy_8w_msa(src0_ptr + 16, src_stride, src1_ptr + 16, src2_stride, - dst + 16, dst_stride, height); + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); + ILVR_B2_SH(zero, src2, zero, src3, dst4, dst5); + ILVRL_B2_SH(zero, src4, dst6, dst7); + ILVRL_B2_SH(zero, src5, dst8, dst9); + ILVR_B2_SH(zero, src6, zero, src7, dst10, dst11); + SLLI_4V(dst0, dst1, dst2, dst3, 6); + SLLI_4V(dst4, dst5, dst6, dst7, 6); + SLLI_4V(dst8, dst9, dst10, dst11, 6); + HEVC_BI_RND_CLIP4_MAX_SATU(in0, in4, in1, in5, dst0, dst1, dst2, dst3, + 7, dst0, dst1, dst2, dst3); + HEVC_BI_RND_CLIP4_MAX_SATU(in8, in9, in2, in6, dst4, dst5, dst6, dst7, + 7, dst4, dst5, dst6, dst7); + HEVC_BI_RND_CLIP4_MAX_SATU(in3, in7, in10, in11, dst8, dst9, dst10, + dst11, 7, dst8, dst9, dst10, dst11); + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + PCKEV_B3_UB(dst7, dst6, dst9, dst8, dst11, dst10, out3, out4, out5); + ST_UB4(out0, out1, out3, out4, dst, dst_stride); + ST8x4_UB(out2, out5, dst + 16, dst_stride); + dst += (4 * dst_stride); + } } static void hevc_bi_copy_32w_msa(uint8_t *src0_ptr, @@ -405,8 +385,40 @@ static void hevc_bi_copy_32w_msa(uint8_t *src0_ptr, int32_t dst_stride, int32_t height) { - hevc_bi_copy_16multx4mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, height, 32); + uint32_t loop_cnt; + v16u8 out0, out1, out2, out3; + v16i8 src0, src1, src2, src3; + v16i8 zero = { 0 }; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 in0, in1, in2, in3, in4, in5, in6, in7; + + for (loop_cnt = (height >> 1); loop_cnt--;) { + LD_SB2(src0_ptr, 16, src0, src1); + src0_ptr += src_stride; + LD_SB2(src0_ptr, 16, src2, src3); + src0_ptr += src_stride; + LD_SH4(src1_ptr, 8, in0, in1, in2, in3); + src1_ptr += src2_stride; + LD_SH4(src1_ptr, 8, in4, in5, in6, in7); + src1_ptr += src2_stride; + + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); + ILVRL_B2_SH(zero, src2, dst4, dst5); + ILVRL_B2_SH(zero, src3, dst6, dst7); + SLLI_4V(dst0, dst1, dst2, dst3, 6); + SLLI_4V(dst4, dst5, dst6, dst7, 6); + HEVC_BI_RND_CLIP4_MAX_SATU(in0, in1, in2, in3, dst0, dst1, dst2, dst3, + 7, dst0, dst1, dst2, dst3); + HEVC_BI_RND_CLIP4_MAX_SATU(in4, in5, in6, in7, dst4, dst5, dst6, dst7, + 7, dst4, dst5, dst6, dst7); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + PCKEV_B2_UB(dst5, dst4, dst7, dst6, out2, out3); + ST_UB2(out0, out1, dst, 16); + dst += dst_stride; + ST_UB2(out2, out3, dst, 16); + dst += dst_stride; + } } static void hevc_bi_copy_48w_msa(uint8_t *src0_ptr, @@ -417,8 +429,50 @@ static void hevc_bi_copy_48w_msa(uint8_t *src0_ptr, int32_t dst_stride, int32_t height) { - hevc_bi_copy_16multx4mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, height, 48); + uint32_t loop_cnt; + v16u8 out0, out1, out2, out3, out4, out5; + v16i8 src0, src1, src2, src3, src4, src5; + v16i8 zero = { 0 }; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8, dst9, dst10; + v8i16 in0, in1, in2, in3, in4, in5, in6, in7, in8, in9, in10, in11, dst11; + + for (loop_cnt = (height >> 1); loop_cnt--;) { + LD_SB3(src0_ptr, 16, src0, src1, src2); + src0_ptr += src_stride; + LD_SB3(src0_ptr, 16, src3, src4, src5); + src0_ptr += src_stride; + + LD_SH6(src1_ptr, 8, in0, in1, in2, in3, in4, in5); + src1_ptr += src2_stride; + LD_SH6(src1_ptr, 8, in6, in7, in8, in9, in10, in11); + src1_ptr += src2_stride; + + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); + ILVRL_B2_SH(zero, src2, dst4, dst5); + ILVRL_B2_SH(zero, src3, dst6, dst7); + ILVRL_B2_SH(zero, src4, dst8, dst9); + ILVRL_B2_SH(zero, src5, dst10, dst11); + + SLLI_4V(dst0, dst1, dst2, dst3, 6); + SLLI_4V(dst4, dst5, dst6, dst7, 6); + SLLI_4V(dst8, dst9, dst10, dst11, 6); + + HEVC_BI_RND_CLIP4_MAX_SATU(in0, in1, in2, in3, dst0, dst1, dst2, dst3, + 7, dst0, dst1, dst2, dst3); + HEVC_BI_RND_CLIP4_MAX_SATU(in4, in5, in6, in7, dst4, dst5, dst6, dst7, + 7, dst4, dst5, dst6, dst7); + HEVC_BI_RND_CLIP4_MAX_SATU(in8, in9, in10, in11, dst8, dst9, dst10, + dst11, 7, dst8, dst9, dst10, dst11); + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + PCKEV_B3_UB(dst7, dst6, dst9, dst8, dst11, dst10, out3, out4, out5); + ST_UB2(out0, out1, dst, 16); + ST_UB(out2, dst + 32); + dst += dst_stride; + ST_UB2(out3, out4, dst, 16); + ST_UB(out5, dst + 32); + dst += dst_stride; + } } static void hevc_bi_copy_64w_msa(uint8_t *src0_ptr, @@ -429,8 +483,35 @@ static void hevc_bi_copy_64w_msa(uint8_t *src0_ptr, int32_t dst_stride, int32_t height) { - hevc_bi_copy_16multx4mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, height, 64); + uint32_t loop_cnt; + v16u8 out0, out1, out2, out3; + v16i8 src0, src1, src2, src3; + v16i8 zero = { 0 }; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 in0, in1, in2, in3, in4, in5, in6, in7; + + for (loop_cnt = height; loop_cnt--;) { + LD_SB4(src0_ptr, 16, src0, src1, src2, src3); + src0_ptr += src_stride; + LD_SH8(src1_ptr, 8, in0, in1, in2, in3, in4, in5, in6, in7); + src1_ptr += src2_stride; + + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); + ILVRL_B2_SH(zero, src2, dst4, dst5); + ILVRL_B2_SH(zero, src3, dst6, dst7); + SLLI_4V(dst0, dst1, dst2, dst3, 6); + SLLI_4V(dst4, dst5, dst6, dst7, 6); + HEVC_BI_RND_CLIP4_MAX_SATU(in0, in1, in2, in3, dst0, dst1, dst2, dst3, + 7, dst0, dst1, dst2, dst3); + HEVC_BI_RND_CLIP4_MAX_SATU(in4, in5, in6, in7, dst4, dst5, dst6, dst7, + 7, dst4, dst5, dst6, dst7); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + PCKEV_B2_UB(dst5, dst4, dst7, dst6, out2, out3); + + ST_UB4(out0, out1, out2, out3, dst, 16); + dst += dst_stride; + } } static void hevc_hz_bi_8t_4w_msa(uint8_t *src0_ptr, @@ -4368,22 +4449,22 @@ BI_MC_COPY(64); #undef BI_MC_COPY -#define BI_MC(PEL, DIR, WIDTH, TAP, DIR1, FILT_DIR) \ -void ff_hevc_put_hevc_bi_##PEL##_##DIR##WIDTH##_8_msa(uint8_t *dst, \ - ptrdiff_t dst_stride, \ - uint8_t *src, \ - ptrdiff_t src_stride, \ - int16_t *src_16bit, \ - int height, \ - intptr_t mx, \ - intptr_t my, \ - int width) \ -{ \ - const int8_t *filter = ff_hevc_##PEL##_filters[FILT_DIR - 1]; \ - \ - hevc_##DIR1##_bi_##TAP##t_##WIDTH##w_msa(src, src_stride, src_16bit, \ - MAX_PB_SIZE, dst, dst_stride, \ - filter, height); \ +#define BI_MC(PEL, DIR, WIDTH, TAP, DIR1, FILT_DIR) \ +void ff_hevc_put_hevc_bi_##PEL##_##DIR##WIDTH##_8_msa(uint8_t *dst, \ + ptrdiff_t dst_stride, \ + uint8_t *src, \ + ptrdiff_t src_stride, \ + int16_t *src_16bit, \ + int height, \ + intptr_t mx, \ + intptr_t my, \ + int width) \ +{ \ + const int8_t *filter = ff_hevc_##PEL##_filters[FILT_DIR - 1]; \ + \ + hevc_##DIR1##_bi_##TAP##t_##WIDTH##w_msa(src, src_stride, src_16bit, \ + MAX_PB_SIZE, dst, dst_stride, \ + filter, height); \ } BI_MC(qpel, h, 4, 8, hz, mx); @@ -4422,41 +4503,40 @@ BI_MC(epel, v, 32, 4, vt, my); #undef BI_MC -#define BI_MC_HV(PEL, DIR, WIDTH, TAP, DIR1) \ -void ff_hevc_put_hevc_bi_##PEL##_##DIR##WIDTH##_8_msa(uint8_t *dst, \ - ptrdiff_t dst_stride, \ - uint8_t *src, \ - ptrdiff_t src_stride, \ - int16_t *src_16bit, \ - int height, \ - intptr_t mx, \ - intptr_t my, \ - int width) \ -{ \ - const int8_t *filter_x = ff_hevc_##PEL##_filters[mx - 1]; \ - const int8_t *filter_y = ff_hevc_##PEL##_filters[my - 1]; \ - \ - hevc_##DIR1##_bi_##TAP##t_##WIDTH##w_msa(src, src_stride, src_16bit, \ - MAX_PB_SIZE, dst, dst_stride, \ - filter_x, filter_y, \ - height); \ +#define BI_MC_HV(PEL, WIDTH, TAP) \ +void ff_hevc_put_hevc_bi_##PEL##_hv##WIDTH##_8_msa(uint8_t *dst, \ + ptrdiff_t dst_stride, \ + uint8_t *src, \ + ptrdiff_t src_stride, \ + int16_t *src_16bit, \ + int height, \ + intptr_t mx, \ + intptr_t my, \ + int width) \ +{ \ + const int8_t *filter_x = ff_hevc_##PEL##_filters[mx - 1]; \ + const int8_t *filter_y = ff_hevc_##PEL##_filters[my - 1]; \ + \ + hevc_hv_bi_##TAP##t_##WIDTH##w_msa(src, src_stride, src_16bit, \ + MAX_PB_SIZE, dst, dst_stride, \ + filter_x, filter_y, height); \ } -BI_MC_HV(qpel, hv, 4, 8, hv); -BI_MC_HV(qpel, hv, 8, 8, hv); -BI_MC_HV(qpel, hv, 12, 8, hv); -BI_MC_HV(qpel, hv, 16, 8, hv); -BI_MC_HV(qpel, hv, 24, 8, hv); -BI_MC_HV(qpel, hv, 32, 8, hv); -BI_MC_HV(qpel, hv, 48, 8, hv); -BI_MC_HV(qpel, hv, 64, 8, hv); - -BI_MC_HV(epel, hv, 4, 4, hv); -BI_MC_HV(epel, hv, 8, 4, hv); -BI_MC_HV(epel, hv, 6, 4, hv); -BI_MC_HV(epel, hv, 12, 4, hv); -BI_MC_HV(epel, hv, 16, 4, hv); -BI_MC_HV(epel, hv, 24, 4, hv); -BI_MC_HV(epel, hv, 32, 4, hv); +BI_MC_HV(qpel, 4, 8); +BI_MC_HV(qpel, 8, 8); +BI_MC_HV(qpel, 12, 8); +BI_MC_HV(qpel, 16, 8); +BI_MC_HV(qpel, 24, 8); +BI_MC_HV(qpel, 32, 8); +BI_MC_HV(qpel, 48, 8); +BI_MC_HV(qpel, 64, 8); + +BI_MC_HV(epel, 4, 4); +BI_MC_HV(epel, 8, 4); +BI_MC_HV(epel, 6, 4); +BI_MC_HV(epel, 12, 4); +BI_MC_HV(epel, 16, 4); +BI_MC_HV(epel, 24, 4); +BI_MC_HV(epel, 32, 4); #undef BI_MC_HV From 6ca821a3e7751b6b24e63ec1b531e3841d4d7bda Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Wed, 11 Oct 2017 14:20:28 +0530 Subject: [PATCH 0465/2557] avcodec/mips: Improve hevc uni horiz mc msa functions Update macros to remove adds. Signed-off-by: Kaustubh Raste Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_uni_msa.c | 612 ++++++++++++++++-------------- 1 file changed, 323 insertions(+), 289 deletions(-) diff --git a/libavcodec/mips/hevc_mc_uni_msa.c b/libavcodec/mips/hevc_mc_uni_msa.c index eead591ff492e..3a6c5b0d48ce3 100644 --- a/libavcodec/mips/hevc_mc_uni_msa.c +++ b/libavcodec/mips/hevc_mc_uni_msa.c @@ -22,6 +22,85 @@ #include "libavcodec/mips/hevcdsp_mips.h" #include "libavcodec/mips/hevc_macros_msa.h" +static const uint8_t ff_hevc_mask_arr[16 * 3] __attribute__((aligned(0x40))) = { + /* 8 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + /* 4 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20, + /* 4 width cases */ + 8, 9, 9, 10, 10, 11, 11, 12, 24, 25, 25, 26, 26, 27, 27, 28 +}; + +#define HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, \ + mask0, mask1, mask2, mask3, \ + filt0, filt1, filt2, filt3, \ + out0, out1) \ +{ \ + v16i8 vec0_m, vec1_m, vec2_m, vec3_m, vec4_m, vec5_m, vec6_m, vec7_m; \ + \ + VSHF_B2_SB(src0, src1, src2, src3, mask0, mask0, vec0_m, vec1_m); \ + DOTP_SB2_SH(vec0_m, vec1_m, filt0, filt0, out0, out1); \ + VSHF_B2_SB(src0, src1, src2, src3, mask1, mask1, vec2_m, vec3_m); \ + DPADD_SB2_SH(vec2_m, vec3_m, filt1, filt1, out0, out1); \ + VSHF_B2_SB(src0, src1, src2, src3, mask2, mask2, vec4_m, vec5_m); \ + DPADD_SB2_SH(vec4_m, vec5_m, filt2, filt2, out0, out1); \ + VSHF_B2_SB(src0, src1, src2, src3, mask3, mask3, vec6_m, vec7_m); \ + DPADD_SB2_SH(vec6_m, vec7_m, filt3, filt3, out0, out1); \ +} + +#define HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, \ + mask0, mask1, mask2, mask3, \ + filt0, filt1, filt2, filt3, \ + out0, out1, out2, out3) \ +{ \ + v16i8 vec0_m, vec1_m, vec2_m, vec3_m, vec4_m, vec5_m, vec6_m, vec7_m; \ + \ + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0_m, vec1_m); \ + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2_m, vec3_m); \ + DOTP_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt0, filt0, filt0, filt0, \ + out0, out1, out2, out3); \ + VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec0_m, vec1_m); \ + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec2_m, vec3_m); \ + DPADD_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt2, filt2, filt2, filt2, \ + out0, out1, out2, out3); \ + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec4_m, vec5_m); \ + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec6_m, vec7_m); \ + DPADD_SB4_SH(vec4_m, vec5_m, vec6_m, vec7_m, filt1, filt1, filt1, filt1, \ + out0, out1, out2, out3); \ + VSHF_B2_SB(src0, src0, src1, src1, mask3, mask3, vec4_m, vec5_m); \ + VSHF_B2_SB(src2, src2, src3, src3, mask3, mask3, vec6_m, vec7_m); \ + DPADD_SB4_SH(vec4_m, vec5_m, vec6_m, vec7_m, filt3, filt3, filt3, filt3, \ + out0, out1, out2, out3); \ +} + +#define HORIZ_4TAP_4WID_4VECS_FILT(src0, src1, src2, src3, \ + mask0, mask1, filt0, filt1, \ + out0, out1) \ +{ \ + v16i8 vec0_m, vec1_m, vec2_m, vec3_m; \ + \ + VSHF_B2_SB(src0, src1, src2, src3, mask0, mask0, vec0_m, vec1_m); \ + DOTP_SB2_SH(vec0_m, vec1_m, filt0, filt0, out0, out1); \ + VSHF_B2_SB(src0, src1, src2, src3, mask1, mask1, vec2_m, vec3_m); \ + DPADD_SB2_SH(vec2_m, vec3_m, filt1, filt1, out0, out1); \ +} + +#define HORIZ_4TAP_8WID_4VECS_FILT(src0, src1, src2, src3, \ + mask0, mask1, filt0, filt1, \ + out0, out1, out2, out3) \ +{ \ + v16i8 vec0_m, vec1_m, vec2_m, vec3_m; \ + \ + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0_m, vec1_m); \ + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2_m, vec3_m); \ + DOTP_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt0, filt0, filt0, filt0, \ + out0, out1, out2, out3); \ + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec0_m, vec1_m); \ + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2_m, vec3_m); \ + DPADD_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt1, filt1, filt1, filt1, \ + out0, out1, out2, out3); \ +} + static void copy_width8_msa(uint8_t *src, int32_t src_stride, uint8_t *dst, int32_t dst_stride, int32_t height) @@ -227,53 +306,6 @@ static const uint8_t mc_filt_mask_arr[16 * 3] = { tmp0; \ } ) -#define HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, \ - mask0, mask1, mask2, mask3, \ - filt0, filt1, filt2, filt3, \ - out0, out1) \ -{ \ - v16i8 vec0_m, vec1_m, vec2_m, vec3_m, vec4_m, vec5_m, vec6_m, vec7_m; \ - v8i16 res0_m, res1_m, res2_m, res3_m; \ - \ - VSHF_B2_SB(src0, src1, src2, src3, mask0, mask0, vec0_m, vec1_m); \ - DOTP_SB2_SH(vec0_m, vec1_m, filt0, filt0, res0_m, res1_m); \ - VSHF_B2_SB(src0, src1, src2, src3, mask1, mask1, vec2_m, vec3_m); \ - DPADD_SB2_SH(vec2_m, vec3_m, filt1, filt1, res0_m, res1_m); \ - VSHF_B2_SB(src0, src1, src2, src3, mask2, mask2, vec4_m, vec5_m); \ - DOTP_SB2_SH(vec4_m, vec5_m, filt2, filt2, res2_m, res3_m); \ - VSHF_B2_SB(src0, src1, src2, src3, mask3, mask3, vec6_m, vec7_m); \ - DPADD_SB2_SH(vec6_m, vec7_m, filt3, filt3, res2_m, res3_m); \ - ADDS_SH2_SH(res0_m, res2_m, res1_m, res3_m, out0, out1); \ -} - -#define HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, \ - mask0, mask1, mask2, mask3, \ - filt0, filt1, filt2, filt3, \ - out0, out1, out2, out3) \ -{ \ - v16i8 vec0_m, vec1_m, vec2_m, vec3_m, vec4_m, vec5_m, vec6_m, vec7_m; \ - v8i16 res0_m, res1_m, res2_m, res3_m, res4_m, res5_m, res6_m, res7_m; \ - \ - VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0_m, vec1_m); \ - VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2_m, vec3_m); \ - DOTP_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt0, filt0, filt0, filt0, \ - res0_m, res1_m, res2_m, res3_m); \ - VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec0_m, vec1_m); \ - VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec2_m, vec3_m); \ - DOTP_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt2, filt2, filt2, filt2, \ - res4_m, res5_m, res6_m, res7_m); \ - VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec4_m, vec5_m); \ - VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec6_m, vec7_m); \ - DPADD_SB4_SH(vec4_m, vec5_m, vec6_m, vec7_m, filt1, filt1, filt1, filt1, \ - res0_m, res1_m, res2_m, res3_m); \ - VSHF_B2_SB(src0, src0, src1, src1, mask3, mask3, vec4_m, vec5_m); \ - VSHF_B2_SB(src2, src2, src3, src3, mask3, mask3, vec6_m, vec7_m); \ - DPADD_SB4_SH(vec4_m, vec5_m, vec6_m, vec7_m, filt3, filt3, filt3, filt3, \ - res4_m, res5_m, res6_m, res7_m); \ - ADDS_SH4_SH(res0_m, res4_m, res1_m, res5_m, res2_m, res6_m, res3_m, \ - res7_m, out0, out1, out2, out3); \ -} - #define FILT_4TAP_DPADD_S_H(vec0, vec1, filt0, filt1) \ ( { \ v8i16 tmp0; \ @@ -284,34 +316,6 @@ static const uint8_t mc_filt_mask_arr[16 * 3] = { tmp0; \ } ) -#define HORIZ_4TAP_4WID_4VECS_FILT(src0, src1, src2, src3, \ - mask0, mask1, filt0, filt1, \ - out0, out1) \ -{ \ - v16i8 vec0_m, vec1_m, vec2_m, vec3_m; \ - \ - VSHF_B2_SB(src0, src1, src2, src3, mask0, mask0, vec0_m, vec1_m); \ - DOTP_SB2_SH(vec0_m, vec1_m, filt0, filt0, out0, out1); \ - VSHF_B2_SB(src0, src1, src2, src3, mask1, mask1, vec2_m, vec3_m); \ - DPADD_SB2_SH(vec2_m, vec3_m, filt1, filt1, out0, out1); \ -} - -#define HORIZ_4TAP_8WID_4VECS_FILT(src0, src1, src2, src3, \ - mask0, mask1, filt0, filt1, \ - out0, out1, out2, out3) \ -{ \ - v16i8 vec0_m, vec1_m, vec2_m, vec3_m; \ - \ - VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0_m, vec1_m); \ - VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2_m, vec3_m); \ - DOTP_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt0, filt0, filt0, filt0, \ - out0, out1, out2, out3); \ - VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec0_m, vec1_m); \ - VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2_m, vec3_m); \ - DPADD_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt1, filt1, filt1, filt1, \ - out0, out1, out2, out3); \ -} - static void common_hz_8t_4x4_msa(uint8_t *src, int32_t src_stride, uint8_t *dst, int32_t dst_stride, const int8_t *filter) @@ -320,7 +324,7 @@ static void common_hz_8t_4x4_msa(uint8_t *src, int32_t src_stride, v16i8 src0, src1, src2, src3, filt0, filt1, filt2, filt3; v8i16 filt, out0, out1; - mask0 = LD_UB(&mc_filt_mask_arr[16]); + mask0 = LD_UB(&ff_hevc_mask_arr[16]); src -= 3; /* rearranging filter */ @@ -350,7 +354,7 @@ static void common_hz_8t_4x8_msa(uint8_t *src, int32_t src_stride, v16u8 mask0, mask1, mask2, mask3, out; v8i16 filt, out0, out1, out2, out3; - mask0 = LD_UB(&mc_filt_mask_arr[16]); + mask0 = LD_UB(&ff_hevc_mask_arr[16]); src -= 3; /* rearranging filter */ @@ -387,7 +391,7 @@ static void common_hz_8t_4x16_msa(uint8_t *src, int32_t src_stride, v16i8 src0, src1, src2, src3, filt0, filt1, filt2, filt3; v8i16 filt, out0, out1, out2, out3; - mask0 = LD_UB(&mc_filt_mask_arr[16]); + mask0 = LD_UB(&ff_hevc_mask_arr[16]); src -= 3; /* rearranging filter */ @@ -450,47 +454,17 @@ static void common_hz_8t_4w_msa(uint8_t *src, int32_t src_stride, } } -static void common_hz_8t_8x4_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - const int8_t *filter) -{ - v16i8 src0, src1, src2, src3, filt0, filt1, filt2, filt3; - v16u8 mask0, mask1, mask2, mask3, tmp0, tmp1; - v8i16 filt, out0, out1, out2, out3; - - mask0 = LD_UB(&mc_filt_mask_arr[0]); - src -= 3; - - /* rearranging filter */ - filt = LD_SH(filter); - SPLATI_H4_SB(filt, 0, 1, 2, 3, filt0, filt1, filt2, filt3); - - mask1 = mask0 + 2; - mask2 = mask0 + 4; - mask3 = mask0 + 6; - - LD_SB4(src, src_stride, src0, src1, src2, src3); - XORI_B4_128_SB(src0, src1, src2, src3); - HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, - mask3, filt0, filt1, filt2, filt3, out0, out1, - out2, out3); - SRARI_H4_SH(out0, out1, out2, out3, 6); - SAT_SH4_SH(out0, out1, out2, out3, 7); - tmp0 = PCKEV_XORI128_UB(out0, out1); - tmp1 = PCKEV_XORI128_UB(out2, out3); - ST8x4_UB(tmp0, tmp1, dst, dst_stride); -} - -static void common_hz_8t_8x8mult_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - const int8_t *filter, int32_t height) +static void common_hz_8t_8w_msa(uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) { uint32_t loop_cnt; v16i8 src0, src1, src2, src3, filt0, filt1, filt2, filt3; v16u8 mask0, mask1, mask2, mask3, tmp0, tmp1; + v16i8 vec0_m, vec1_m, vec2_m, vec3_m, vec4_m, vec5_m, vec6_m, vec7_m; v8i16 filt, out0, out1, out2, out3; - mask0 = LD_UB(&mc_filt_mask_arr[0]); + mask0 = LD_UB(&ff_hevc_mask_arr[0]); src -= 3; /* rearranging filter */ @@ -505,9 +479,24 @@ static void common_hz_8t_8x8mult_msa(uint8_t *src, int32_t src_stride, LD_SB4(src, src_stride, src0, src1, src2, src3); XORI_B4_128_SB(src0, src1, src2, src3); src += (4 * src_stride); - HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, - mask3, filt0, filt1, filt2, filt3, out0, - out1, out2, out3); + + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0_m, vec1_m); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2_m, vec3_m); + DOTP_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt0, filt0, filt0, filt0, + out0, out1, out2, out3); + VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec0_m, vec1_m); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec2_m, vec3_m); + DPADD_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt2, filt2, filt2, filt2, + out0, out1, out2, out3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec4_m, vec5_m); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec6_m, vec7_m); + DPADD_SB4_SH(vec4_m, vec5_m, vec6_m, vec7_m, filt1, filt1, filt1, filt1, + out0, out1, out2, out3); + VSHF_B2_SB(src0, src0, src1, src1, mask3, mask3, vec4_m, vec5_m); + VSHF_B2_SB(src2, src2, src3, src3, mask3, mask3, vec6_m, vec7_m); + DPADD_SB4_SH(vec4_m, vec5_m, vec6_m, vec7_m, filt3, filt3, filt3, filt3, + out0, out1, out2, out3); + SRARI_H4_SH(out0, out1, out2, out3, 6); SAT_SH4_SH(out0, out1, out2, out3, 7); tmp0 = PCKEV_XORI128_UB(out0, out1); @@ -517,36 +506,22 @@ static void common_hz_8t_8x8mult_msa(uint8_t *src, int32_t src_stride, } } -static void common_hz_8t_8w_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - const int8_t *filter, int32_t height) -{ - if (4 == height) { - common_hz_8t_8x4_msa(src, src_stride, dst, dst_stride, filter); - } else { - common_hz_8t_8x8mult_msa(src, src_stride, dst, dst_stride, filter, - height); - } -} - static void common_hz_8t_12w_msa(uint8_t *src, int32_t src_stride, uint8_t *dst, int32_t dst_stride, const int8_t *filter, int32_t height) { - uint8_t *src1_ptr, *dst1; uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, filt0, filt1, filt2, filt3; - v8i16 filt, out0, out1, out2, out3; - v16u8 mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask00, tmp0, tmp1; - - mask00 = LD_UB(&mc_filt_mask_arr[0]); - mask0 = LD_UB(&mc_filt_mask_arr[16]); + v16u8 mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask00; + v16u8 tmp0, tmp1, tmp2; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 filt0, filt1, filt2, filt3; + v8i16 filt, out0, out1, out2, out3, out4, out5; - src1_ptr = src - 3; - dst1 = dst; + mask00 = LD_UB(&ff_hevc_mask_arr[0]); + mask0 = LD_UB(&ff_hevc_mask_arr[16]); - dst = dst1 + 8; - src = src1_ptr + 8; + src = src - 3; /* rearranging filter */ filt = LD_SH(filter); @@ -559,32 +534,53 @@ static void common_hz_8t_12w_msa(uint8_t *src, int32_t src_stride, mask5 = mask0 + 4; mask6 = mask0 + 6; - for (loop_cnt = (height >> 2); loop_cnt--;) { + for (loop_cnt = 4; loop_cnt--;) { /* 8 width */ - LD_SB4(src1_ptr, src_stride, src0, src1, src2, src3); + LD_SB4(src, src_stride, src0, src1, src2, src3); + /* 4 width */ + LD_SB4(src + 8, src_stride, src4, src5, src6, src7); + XORI_B4_128_SB(src0, src1, src2, src3); - src1_ptr += (4 * src_stride); - HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask00, mask1, mask2, - mask3, filt0, filt1, filt2, filt3, out0, - out1, out2, out3); + XORI_B4_128_SB(src4, src5, src6, src7); + src += (4 * src_stride); + + VSHF_B2_SB(src0, src0, src1, src1, mask00, mask00, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask00, mask00, vec2, vec3); + DOTP_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, out0, + out1, out2, out3); + VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, out0, + out1, out2, out3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec4, vec5); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec6, vec7); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt1, filt1, filt1, filt1, out0, + out1, out2, out3); + VSHF_B2_SB(src0, src0, src1, src1, mask3, mask3, vec4, vec5); + VSHF_B2_SB(src2, src2, src3, src3, mask3, mask3, vec6, vec7); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt3, filt3, filt3, filt3, out0, + out1, out2, out3); + + /* 4 width */ + VSHF_B2_SB(src4, src5, src6, src7, mask0, mask0, vec0, vec1); + DOTP_SB2_SH(vec0, vec1, filt0, filt0, out4, out5); + VSHF_B2_SB(src4, src5, src6, src7, mask4, mask4, vec2, vec3); + DPADD_SB2_SH(vec2, vec3, filt1, filt1, out4, out5); + VSHF_B2_SB(src4, src5, src6, src7, mask5, mask5, vec4, vec5); + DPADD_SB2_SH(vec4, vec5, filt2, filt2, out4, out5); + VSHF_B2_SB(src4, src5, src6, src7, mask6, mask6, vec6, vec7); + DPADD_SB2_SH(vec6, vec7, filt3, filt3, out4, out5); + SRARI_H4_SH(out0, out1, out2, out3, 6); + SRARI_H2_SH(out4, out5, 6); SAT_SH4_SH(out0, out1, out2, out3, 7); + SAT_SH2_SH(out4, out5, 7); tmp0 = PCKEV_XORI128_UB(out0, out1); tmp1 = PCKEV_XORI128_UB(out2, out3); - ST8x4_UB(tmp0, tmp1, dst1, dst_stride); - dst1 += (4 * dst_stride); + tmp2 = PCKEV_XORI128_UB(out4, out5); - /* 4 width */ - LD_SB4(src, src_stride, src0, src1, src2, src3); - XORI_B4_128_SB(src0, src1, src2, src3); - src += (4 * src_stride); - HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask4, mask5, - mask6, filt0, filt1, filt2, filt3, out0, - out1); - SRARI_H2_SH(out0, out1, 6); - SAT_SH2_SH(out0, out1, 7); - tmp0 = PCKEV_XORI128_UB(out0, out1); - ST4x4_UB(tmp0, tmp0, 0, 1, 2, 3, dst, dst_stride); + ST8x4_UB(tmp0, tmp1, dst, dst_stride); + ST4x4_UB(tmp2, tmp2, 0, 1, 2, 3, dst + 8, dst_stride); dst += (4 * dst_stride); } } @@ -594,11 +590,12 @@ static void common_hz_8t_16w_msa(uint8_t *src, int32_t src_stride, const int8_t *filter, int32_t height) { uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, filt0, filt1, filt2, filt3; v16u8 mask0, mask1, mask2, mask3, out; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7; + v16i8 filt0, filt1, filt2, filt3; v8i16 filt, out0, out1, out2, out3; - mask0 = LD_UB(&mc_filt_mask_arr[0]); + mask0 = LD_UB(&ff_hevc_mask_arr[0]); src -= 3; /* rearranging filter */ @@ -609,11 +606,17 @@ static void common_hz_8t_16w_msa(uint8_t *src, int32_t src_stride, mask2 = mask0 + 4; mask3 = mask0 + 6; - for (loop_cnt = (height >> 1); loop_cnt--;) { + for (loop_cnt = (height >> 2); loop_cnt--;) { LD_SB2(src, src_stride, src0, src2); LD_SB2(src + 8, src_stride, src1, src3); - XORI_B4_128_SB(src0, src1, src2, src3); src += (2 * src_stride); + + LD_SB2(src, src_stride, src4, src6); + LD_SB2(src + 8, src_stride, src5, src7); + src += (2 * src_stride); + + XORI_B4_128_SB(src0, src1, src2, src3); + XORI_B4_128_SB(src4, src5, src6, src7); HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, mask3, filt0, filt1, filt2, filt3, out0, out1, out2, out3); @@ -625,6 +628,18 @@ static void common_hz_8t_16w_msa(uint8_t *src, int32_t src_stride, out = PCKEV_XORI128_UB(out2, out3); ST_UB(out, dst); dst += dst_stride; + + HORIZ_8TAP_8WID_4VECS_FILT(src4, src5, src6, src7, mask0, mask1, mask2, + mask3, filt0, filt1, filt2, filt3, out0, + out1, out2, out3); + SRARI_H4_SH(out0, out1, out2, out3, 6); + SAT_SH4_SH(out0, out1, out2, out3, 7); + out = PCKEV_XORI128_UB(out0, out1); + ST_UB(out, dst); + dst += dst_stride; + out = PCKEV_XORI128_UB(out2, out3); + ST_UB(out, dst); + dst += dst_stride; } } @@ -637,10 +652,9 @@ static void common_hz_8t_24w_msa(uint8_t *src, int32_t src_stride, v16u8 mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask7, out; v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9, vec10; v16i8 vec11; - v8i16 out0, out1, out2, out3, out4, out5, out6, out7, out8, out9, out10; - v8i16 out11, filt; + v8i16 out0, out1, out2, out3, out8, out9, filt; - mask0 = LD_UB(&mc_filt_mask_arr[0]); + mask0 = LD_UB(&ff_hevc_mask_arr[0]); src -= 3; /* rearranging filter */ @@ -655,7 +669,7 @@ static void common_hz_8t_24w_msa(uint8_t *src, int32_t src_stride, mask6 = mask0 + 12; mask7 = mask0 + 14; - for (loop_cnt = (height >> 1); loop_cnt--;) { + for (loop_cnt = 16; loop_cnt--;) { LD_SB2(src, src_stride, src0, src2); LD_SB2(src + 16, src_stride, src1, src3); XORI_B4_128_SB(src0, src1, src2, src3); @@ -669,9 +683,9 @@ static void common_hz_8t_24w_msa(uint8_t *src, int32_t src_stride, VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec0, vec8); VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec2, vec9); VSHF_B2_SB(src0, src1, src2, src3, mask6, mask6, vec1, vec3); - DOTP_SB4_SH(vec0, vec8, vec2, vec9, filt2, filt2, filt2, filt2, out4, - out10, out6, out11); - DOTP_SB2_SH(vec1, vec3, filt2, filt2, out5, out7); + DPADD_SB4_SH(vec0, vec8, vec2, vec9, filt2, filt2, filt2, filt2, + out0, out8, out2, out9); + DPADD_SB2_SH(vec1, vec3, filt2, filt2, out1, out3); VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec4, vec10); VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec6, vec11); VSHF_B2_SB(src0, src1, src2, src3, mask5, mask5, vec5, vec7); @@ -682,11 +696,8 @@ static void common_hz_8t_24w_msa(uint8_t *src, int32_t src_stride, VSHF_B2_SB(src2, src2, src3, src3, mask3, mask3, vec6, vec11); VSHF_B2_SB(src0, src1, src2, src3, mask7, mask7, vec5, vec7); DPADD_SB4_SH(vec4, vec10, vec6, vec11, filt3, filt3, filt3, filt3, - out4, out10, out6, out11); - DPADD_SB2_SH(vec5, vec7, filt3, filt3, out5, out7); - ADDS_SH4_SH(out0, out4, out8, out10, out2, out6, out9, out11, out0, - out8, out2, out9); - ADDS_SH2_SH(out1, out5, out3, out7, out1, out3); + out0, out8, out2, out9); + DPADD_SB2_SH(vec5, vec7, filt3, filt3, out1, out3); SRARI_H4_SH(out0, out8, out2, out9, 6); SRARI_H2_SH(out1, out3, 6); SAT_SH4_SH(out0, out8, out2, out9, 7); @@ -707,11 +718,12 @@ static void common_hz_8t_32w_msa(uint8_t *src, int32_t src_stride, const int8_t *filter, int32_t height) { uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, filt0, filt1, filt2, filt3; v16u8 mask0, mask1, mask2, mask3, out; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7; + v16i8 filt0, filt1, filt2, filt3; v8i16 filt, out0, out1, out2, out3; - mask0 = LD_UB(&mc_filt_mask_arr[0]); + mask0 = LD_UB(&ff_hevc_mask_arr[0]); src -= 3; /* rearranging filter */ @@ -724,31 +736,32 @@ static void common_hz_8t_32w_msa(uint8_t *src, int32_t src_stride, for (loop_cnt = (height >> 1); loop_cnt--;) { src0 = LD_SB(src); + src1 = LD_SB(src + 8); src2 = LD_SB(src + 16); src3 = LD_SB(src + 24); - src1 = __msa_sldi_b(src2, src0, 8); src += src_stride; XORI_B4_128_SB(src0, src1, src2, src3); + + src4 = LD_SB(src); + src5 = LD_SB(src + 8); + src6 = LD_SB(src + 16); + src7 = LD_SB(src + 24); + src += src_stride; + XORI_B4_128_SB(src4, src5, src6, src7); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, mask3, filt0, filt1, filt2, filt3, out0, out1, out2, out3); SRARI_H4_SH(out0, out1, out2, out3, 6); SAT_SH4_SH(out0, out1, out2, out3, 7); - src0 = LD_SB(src); - src2 = LD_SB(src + 16); - src3 = LD_SB(src + 24); - src1 = __msa_sldi_b(src2, src0, 8); - src += src_stride; - out = PCKEV_XORI128_UB(out0, out1); ST_UB(out, dst); out = PCKEV_XORI128_UB(out2, out3); ST_UB(out, dst + 16); dst += dst_stride; - XORI_B4_128_SB(src0, src1, src2, src3); - HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + HORIZ_8TAP_8WID_4VECS_FILT(src4, src5, src6, src7, mask0, mask1, mask2, mask3, filt0, filt1, filt2, filt3, out0, out1, out2, out3); SRARI_H4_SH(out0, out1, out2, out3, 6); @@ -767,10 +780,11 @@ static void common_hz_8t_48w_msa(uint8_t *src, int32_t src_stride, { uint32_t loop_cnt; v16i8 src0, src1, src2, src3, filt0, filt1, filt2, filt3, vec0, vec1, vec2; + v16i8 src4; v16u8 mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask7, out; - v8i16 filt, out0, out1, out2, out3, out4, out5, out6; + v8i16 filt, out0, out1, out2, out3; - mask0 = LD_UB(&mc_filt_mask_arr[0]); + mask0 = LD_UB(&ff_hevc_mask_arr[0]); src -= 3; /* rearranging filter */ @@ -785,11 +799,17 @@ static void common_hz_8t_48w_msa(uint8_t *src, int32_t src_stride, mask6 = mask0 + 12; mask7 = mask0 + 14; - for (loop_cnt = height; loop_cnt--;) { - LD_SB3(src, 16, src0, src2, src3); - src1 = __msa_sldi_b(src2, src0, 8); + for (loop_cnt = 64; loop_cnt--;) { + src0 = LD_SB(src); + src1 = LD_SB(src + 8); + src2 = LD_SB(src + 16); + src3 = LD_SB(src + 32); + src4 = LD_SB(src + 40); + src += src_stride; XORI_B4_128_SB(src0, src1, src2, src3); + src4 = (v16i8) __msa_xori_b((v16u8) src4, 128); + VSHF_B3_SB(src0, src0, src1, src1, src2, src2, mask0, mask0, mask0, vec0, vec1, vec2); DOTP_SB3_SH(vec0, vec1, vec2, filt0, filt0, filt0, out0, out1, out2); @@ -799,45 +819,42 @@ static void common_hz_8t_48w_msa(uint8_t *src, int32_t src_stride, out2 = __msa_dpadd_s_h(out2, vec2, filt1); VSHF_B3_SB(src0, src0, src1, src1, src2, src2, mask2, mask2, mask2, vec0, vec1, vec2); - DOTP_SB3_SH(vec0, vec1, vec2, filt2, filt2, filt2, out3, out4, out5); + DPADD_SB2_SH(vec0, vec1, filt2, filt2, out0, out1); + out2 = __msa_dpadd_s_h(out2, vec2, filt2); + VSHF_B3_SB(src0, src0, src1, src1, src2, src2, mask3, mask3, mask3, vec0, vec1, vec2); - DPADD_SB2_SH(vec0, vec1, filt3, filt3, out3, out4); - out5 = __msa_dpadd_s_h(out5, vec2, filt3); - ADDS_SH2_SH(out0, out3, out1, out4, out0, out1); - out2 = __msa_adds_s_h(out2, out5); + DPADD_SB2_SH(vec0, vec1, filt3, filt3, out0, out1); + out2 = __msa_dpadd_s_h(out2, vec2, filt3); + SRARI_H2_SH(out0, out1, 6); - out6 = __msa_srari_h(out2, 6); - SAT_SH3_SH(out0, out1, out6, 7); + out3 = __msa_srari_h(out2, 6); + SAT_SH3_SH(out0, out1, out3, 7); out = PCKEV_XORI128_UB(out0, out1); ST_UB(out, dst); - src1 = LD_SB(src + 40); - src += src_stride; - src1 = (v16i8) __msa_xori_b((v16u8) src1, 128); - - VSHF_B3_SB(src2, src3, src3, src3, src1, src1, mask4, mask0, mask0, + VSHF_B3_SB(src2, src3, src3, src3, src4, src4, mask4, mask0, mask0, vec0, vec1, vec2); DOTP_SB3_SH(vec0, vec1, vec2, filt0, filt0, filt0, out0, out1, out2); - VSHF_B3_SB(src2, src3, src3, src3, src1, src1, mask5, mask1, mask1, + VSHF_B3_SB(src2, src3, src3, src3, src4, src4, mask5, mask1, mask1, vec0, vec1, vec2); DPADD_SB2_SH(vec0, vec1, filt1, filt1, out0, out1); out2 = __msa_dpadd_s_h(out2, vec2, filt1); - VSHF_B3_SB(src2, src3, src3, src3, src1, src1, mask6, mask2, mask2, + VSHF_B3_SB(src2, src3, src3, src3, src4, src4, mask6, mask2, mask2, vec0, vec1, vec2); - DOTP_SB3_SH(vec0, vec1, vec2, filt2, filt2, filt2, out3, out4, out5); - VSHF_B3_SB(src2, src3, src3, src3, src1, src1, mask7, mask3, mask3, + DPADD_SB2_SH(vec0, vec1, filt2, filt2, out0, out1); + out2 = __msa_dpadd_s_h(out2, vec2, filt2); + VSHF_B3_SB(src2, src3, src3, src3, src4, src4, mask7, mask3, mask3, vec0, vec1, vec2); - DPADD_SB2_SH(vec0, vec1, filt3, filt3, out3, out4); - out5 = __msa_dpadd_s_h(out5, vec2, filt3); - ADDS_SH2_SH(out0, out3, out1, out4, out3, out4); - out5 = __msa_adds_s_h(out2, out5); - SRARI_H2_SH(out3, out4, 6); - out5 = __msa_srari_h(out5, 6); - SAT_SH3_SH(out3, out4, out5, 7); - out = PCKEV_XORI128_UB(out6, out3); + DPADD_SB2_SH(vec0, vec1, filt3, filt3, out0, out1); + out2 = __msa_dpadd_s_h(out2, vec2, filt3); + + SRARI_H2_SH(out0, out1, 6); + out2 = __msa_srari_h(out2, 6); + SAT_SH3_SH(out0, out1, out2, 7); + out = PCKEV_XORI128_UB(out3, out0); ST_UB(out, dst + 16); - out = PCKEV_XORI128_UB(out4, out5); + out = PCKEV_XORI128_UB(out1, out2); ST_UB(out, dst + 32); dst += dst_stride; } @@ -848,11 +865,13 @@ static void common_hz_8t_64w_msa(uint8_t *src, int32_t src_stride, const int8_t *filter, int32_t height) { int32_t loop_cnt; - v16i8 src0, src1, src2, src3, filt0, filt1, filt2, filt3; v16u8 mask0, mask1, mask2, mask3, out; - v8i16 filt, out0, out1, out2, out3; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 filt0, filt1, filt2, filt3; + v8i16 res0, res1, res2, res3, filt; - mask0 = LD_UB(&mc_filt_mask_arr[0]); + mask0 = LD_UB(&ff_hevc_mask_arr[0]); src -= 3; /* rearranging filter */ @@ -864,37 +883,57 @@ static void common_hz_8t_64w_msa(uint8_t *src, int32_t src_stride, mask3 = mask0 + 6; for (loop_cnt = height; loop_cnt--;) { - src0 = LD_SB(src); - src2 = LD_SB(src + 16); - src3 = LD_SB(src + 24); - src1 = __msa_sldi_b(src2, src0, 8); + LD_SB8(src, 8, src0, src1, src2, src3, src4, src5, src6, src7); + src += src_stride; - XORI_B4_128_SB(src0, src1, src2, src3); - HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, - mask2, mask3, filt0, filt1, filt2, filt3, - out0, out1, out2, out3); - SRARI_H4_SH(out0, out1, out2, out3, 6); - SAT_SH4_SH(out0, out1, out2, out3, 7); - out = PCKEV_XORI128_UB(out0, out1); + XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); + + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); + DOTP_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, res0, + res1, res2, res3); + VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, res0, + res1, res2, res3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec4, vec5); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec6, vec7); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt1, filt1, filt1, filt1, res0, + res1, res2, res3); + VSHF_B2_SB(src0, src0, src1, src1, mask3, mask3, vec4, vec5); + VSHF_B2_SB(src2, src2, src3, src3, mask3, mask3, vec6, vec7); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt3, filt3, filt3, filt3, res0, + res1, res2, res3); + + SRARI_H4_SH(res0, res1, res2, res3, 6); + SAT_SH4_SH(res0, res1, res2, res3, 7); + out = PCKEV_XORI128_UB(res0, res1); ST_UB(out, dst); - out = PCKEV_XORI128_UB(out2, out3); + out = PCKEV_XORI128_UB(res2, res3); ST_UB(out, dst + 16); - src0 = LD_SB(src + 32); - src2 = LD_SB(src + 48); - src3 = LD_SB(src + 56); - src1 = __msa_sldi_b(src2, src0, 8); - src += src_stride; - - XORI_B4_128_SB(src0, src1, src2, src3); - HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, - mask2, mask3, filt0, filt1, filt2, filt3, - out0, out1, out2, out3); - SRARI_H4_SH(out0, out1, out2, out3, 6); - SAT_SH4_SH(out0, out1, out2, out3, 7); - out = PCKEV_XORI128_UB(out0, out1); + VSHF_B2_SB(src4, src4, src5, src5, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src6, src6, src7, src7, mask0, mask0, vec2, vec3); + DOTP_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, res0, + res1, res2, res3); + VSHF_B2_SB(src4, src4, src5, src5, mask2, mask2, vec0, vec1); + VSHF_B2_SB(src6, src6, src7, src7, mask2, mask2, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, res0, + res1, res2, res3); + VSHF_B2_SB(src4, src4, src5, src5, mask1, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src7, src7, mask1, mask1, vec6, vec7); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt1, filt1, filt1, filt1, res0, + res1, res2, res3); + VSHF_B2_SB(src4, src4, src5, src5, mask3, mask3, vec4, vec5); + VSHF_B2_SB(src6, src6, src7, src7, mask3, mask3, vec6, vec7); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt3, filt3, filt3, filt3, res0, + res1, res2, res3); + + SRARI_H4_SH(res0, res1, res2, res3, 6); + SAT_SH4_SH(res0, res1, res2, res3, 7); + out = PCKEV_XORI128_UB(res0, res1); ST_UB(out, dst + 32); - out = PCKEV_XORI128_UB(out2, out3); + out = PCKEV_XORI128_UB(res2, res3); ST_UB(out, dst + 48); dst += dst_stride; } @@ -3721,15 +3760,13 @@ UNI_MC_COPY(64); #define UNI_MC(PEL, DIR, WIDTH, TAP, DIR1, FILT_DIR) \ void ff_hevc_put_hevc_uni_##PEL##_##DIR##WIDTH##_8_msa(uint8_t *dst, \ - ptrdiff_t \ - dst_stride, \ - uint8_t *src, \ - ptrdiff_t \ - src_stride, \ - int height, \ - intptr_t mx, \ - intptr_t my, \ - int width) \ + ptrdiff_t dst_stride, \ + uint8_t *src, \ + ptrdiff_t src_stride, \ + int height, \ + intptr_t mx, \ + intptr_t my, \ + int width) \ { \ const int8_t *filter = ff_hevc_##PEL##_filters[FILT_DIR - 1]; \ \ @@ -3773,41 +3810,38 @@ UNI_MC(epel, v, 32, 4, vt, my); #undef UNI_MC -#define UNI_MC_HV(PEL, DIR, WIDTH, TAP, DIR1) \ -void ff_hevc_put_hevc_uni_##PEL##_##DIR##WIDTH##_8_msa(uint8_t *dst, \ - ptrdiff_t \ - dst_stride, \ - uint8_t *src, \ - ptrdiff_t \ - src_stride, \ - int height, \ - intptr_t mx, \ - intptr_t my, \ - int width) \ -{ \ - const int8_t *filter_x = ff_hevc_##PEL##_filters[mx - 1]; \ - const int8_t *filter_y = ff_hevc_##PEL##_filters[my - 1]; \ - \ - hevc_##DIR1##_uni_##TAP##t_##WIDTH##w_msa(src, src_stride, dst, \ - dst_stride, filter_x, \ - filter_y, height); \ -} - -UNI_MC_HV(qpel, hv, 4, 8, hv); -UNI_MC_HV(qpel, hv, 8, 8, hv); -UNI_MC_HV(qpel, hv, 12, 8, hv); -UNI_MC_HV(qpel, hv, 16, 8, hv); -UNI_MC_HV(qpel, hv, 24, 8, hv); -UNI_MC_HV(qpel, hv, 32, 8, hv); -UNI_MC_HV(qpel, hv, 48, 8, hv); -UNI_MC_HV(qpel, hv, 64, 8, hv); - -UNI_MC_HV(epel, hv, 4, 4, hv); -UNI_MC_HV(epel, hv, 6, 4, hv); -UNI_MC_HV(epel, hv, 8, 4, hv); -UNI_MC_HV(epel, hv, 12, 4, hv); -UNI_MC_HV(epel, hv, 16, 4, hv); -UNI_MC_HV(epel, hv, 24, 4, hv); -UNI_MC_HV(epel, hv, 32, 4, hv); +#define UNI_MC_HV(PEL, WIDTH, TAP) \ +void ff_hevc_put_hevc_uni_##PEL##_hv##WIDTH##_8_msa(uint8_t *dst, \ + ptrdiff_t dst_stride, \ + uint8_t *src, \ + ptrdiff_t src_stride, \ + int height, \ + intptr_t mx, \ + intptr_t my, \ + int width) \ +{ \ + const int8_t *filter_x = ff_hevc_##PEL##_filters[mx - 1]; \ + const int8_t *filter_y = ff_hevc_##PEL##_filters[my - 1]; \ + \ + hevc_hv_uni_##TAP##t_##WIDTH##w_msa(src, src_stride, dst, dst_stride, \ + filter_x, filter_y, height); \ +} + +UNI_MC_HV(qpel, 4, 8); +UNI_MC_HV(qpel, 8, 8); +UNI_MC_HV(qpel, 12, 8); +UNI_MC_HV(qpel, 16, 8); +UNI_MC_HV(qpel, 24, 8); +UNI_MC_HV(qpel, 32, 8); +UNI_MC_HV(qpel, 48, 8); +UNI_MC_HV(qpel, 64, 8); + +UNI_MC_HV(epel, 4, 4); +UNI_MC_HV(epel, 6, 4); +UNI_MC_HV(epel, 8, 4); +UNI_MC_HV(epel, 12, 4); +UNI_MC_HV(epel, 16, 4); +UNI_MC_HV(epel, 24, 4); +UNI_MC_HV(epel, 32, 4); #undef UNI_MC_HV From e5439e272ed1ac17b78f49183cb9ab28519ce015 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Wed, 11 Oct 2017 14:21:09 +0530 Subject: [PATCH 0466/2557] avcodec/mips: Improve hevc uni weighted vert mc msa functions Pack the data to half word before clipping. Use immediate unsigned saturation for clip to max saving one vector register. Signed-off-by: Kaustubh Raste Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_uniw_msa.c | 441 +++++++++++++++-------------- 1 file changed, 222 insertions(+), 219 deletions(-) diff --git a/libavcodec/mips/hevc_mc_uniw_msa.c b/libavcodec/mips/hevc_mc_uniw_msa.c index 7c01c32d5749a..28c7062fba341 100644 --- a/libavcodec/mips/hevc_mc_uniw_msa.c +++ b/libavcodec/mips/hevc_mc_uniw_msa.c @@ -1337,6 +1337,7 @@ static void hevc_vt_uniwgt_8t_4w_msa(uint8_t *src, int32_t rnd_val) { int32_t loop_cnt; + v16u8 out0, out1; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; v16i8 src9, src10, src11, src12, src13, src14; v16i8 src10_r, src32_r, src54_r, src76_r, src98_r; @@ -1344,21 +1345,27 @@ static void hevc_vt_uniwgt_8t_4w_msa(uint8_t *src, v16i8 src1110_r, src1211_r, src1312_r, src1413_r; v16i8 src2110, src4332, src6554, src8776, src10998; v16i8 src12111110, src14131312; - v8i16 dst10, dst32, dst54, dst76; + v8i16 filter_vec, dst01, dst23, dst45, dst67; v8i16 filt0, filt1, filt2, filt3; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 dst0, dst1, dst2, dst3, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= (3 * src_stride); - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight = weight & 0x0000FFFF; + weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); @@ -1387,28 +1394,21 @@ static void hevc_vt_uniwgt_8t_4w_msa(uint8_t *src, src1413_r, src1312_r, src8776, src10998, src12111110, src14131312); XORI_B4_128_SB(src8776, src10998, src12111110, src14131312); + dst01 = HEVC_FILT_8TAP_SH(src2110, src4332, src6554, src8776, filt0, + filt1, filt2, filt3); + dst23 = HEVC_FILT_8TAP_SH(src4332, src6554, src8776, src10998, filt0, + filt1, filt2, filt3); + dst45 = HEVC_FILT_8TAP_SH(src6554, src8776, src10998, src12111110, + filt0, filt1, filt2, filt3); + dst67 = HEVC_FILT_8TAP_SH(src8776, src10998, src12111110, src14131312, + filt0, filt1, filt2, filt3); - dst10 = const_vec; - DPADD_SB4_SH(src2110, src4332, src6554, src8776, filt0, filt1, - filt2, filt3, dst10, dst10, dst10, dst10); - dst32 = const_vec; - DPADD_SB4_SH(src4332, src6554, src8776, src10998, - filt0, filt1, filt2, filt3, dst32, dst32, dst32, dst32); - dst54 = const_vec; - DPADD_SB4_SH(src6554, src8776, src10998, src12111110, - filt0, filt1, filt2, filt3, dst54, dst54, dst54, dst54); - dst76 = const_vec; - DPADD_SB4_SH(src8776, src10998, src12111110, src14131312, - filt0, filt1, filt2, filt3, dst76, dst76, dst76, dst76); - - HEVC_UNIW_RND_CLIP4(dst10, dst32, dst54, dst76, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst01, dst23, dst45, dst67, weight_vec, + offset_vec, rnd_vec, dst0, dst1, dst2, + dst3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST4x8_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + ST4x8_UB(out0, out1, dst, dst_stride); dst += (8 * dst_stride); src2110 = src10998; @@ -1429,24 +1429,30 @@ static void hevc_vt_uniwgt_8t_8w_msa(uint8_t *src, int32_t rnd_val) { int32_t loop_cnt; + v16u8 out0, out1; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v16i8 src10_r, src32_r, src54_r, src76_r, src98_r; v16i8 src21_r, src43_r, src65_r, src87_r, src109_r; - v8i16 tmp0, tmp1, tmp2, tmp3; v8i16 filt0, filt1, filt2, filt3; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 filter_vec; + v8i16 dst0, dst1, dst2, dst3, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= (3 * src_stride); - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); @@ -1464,28 +1470,21 @@ static void hevc_vt_uniwgt_8t_8w_msa(uint8_t *src, XORI_B4_128_SB(src7, src8, src9, src10); ILVR_B4_SB(src7, src6, src8, src7, src9, src8, src10, src9, src76_r, src87_r, src98_r, src109_r); + dst0 = HEVC_FILT_8TAP_SH(src10_r, src32_r, src54_r, src76_r, filt0, + filt1, filt2, filt3); + dst1 = HEVC_FILT_8TAP_SH(src21_r, src43_r, src65_r, src87_r, filt0, + filt1, filt2, filt3); + dst2 = HEVC_FILT_8TAP_SH(src32_r, src54_r, src76_r, src98_r, filt0, + filt1, filt2, filt3); + dst3 = HEVC_FILT_8TAP_SH(src43_r, src65_r, src87_r, src109_r, filt0, + filt1, filt2, filt3); - tmp0 = const_vec; - DPADD_SB4_SH(src10_r, src32_r, src54_r, src76_r, - filt0, filt1, filt2, filt3, tmp0, tmp0, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB4_SH(src21_r, src43_r, src65_r, src87_r, - filt0, filt1, filt2, filt3, tmp1, tmp1, tmp1, tmp1); - tmp2 = const_vec; - DPADD_SB4_SH(src32_r, src54_r, src76_r, src98_r, - filt0, filt1, filt2, filt3, tmp2, tmp2, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB4_SH(src43_r, src65_r, src87_r, src109_r, - filt0, filt1, filt2, filt3, tmp3, tmp3, tmp3, tmp3); - - HEVC_UNIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, weight_vec, + offset_vec, rnd_vec, dst0, dst1, dst2, + dst3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + ST8x4_UB(out0, out1, dst, dst_stride); dst += (4 * dst_stride); src10_r = src54_r; @@ -1509,28 +1508,34 @@ static void hevc_vt_uniwgt_8t_12w_msa(uint8_t *src, int32_t rnd_val) { int32_t loop_cnt; + v16u8 out0, out1, out2; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v16i8 src10_r, src32_r, src54_r, src76_r, src98_r; v16i8 src21_r, src43_r, src65_r, src87_r, src109_r; - v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; v16i8 src10_l, src32_l, src54_l, src76_l, src98_l; v16i8 src21_l, src43_l, src65_l, src87_l, src109_l; v16i8 src2110, src4332, src6554, src8776, src10998; v8i16 filt0, filt1, filt2, filt3; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5; + v8i16 weight_vec_h, offset_vec, denom_vec, filter_vec; + v4i32 weight_vec, rnd_vec; src -= (3 * src_stride); - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); @@ -1547,7 +1552,7 @@ static void hevc_vt_uniwgt_8t_12w_msa(uint8_t *src, ILVR_D3_SB(src21_l, src10_l, src43_l, src32_l, src65_l, src54_l, src2110, src4332, src6554); - for (loop_cnt = (height >> 2); loop_cnt--;) { + for (loop_cnt = 4; loop_cnt--;) { LD_SB4(src, src_stride, src7, src8, src9, src10); src += (4 * src_stride); XORI_B4_128_SB(src7, src8, src9, src10); @@ -1558,37 +1563,28 @@ static void hevc_vt_uniwgt_8t_12w_msa(uint8_t *src, src76_l, src87_l, src98_l, src109_l); ILVR_D2_SB(src87_l, src76_l, src109_l, src98_l, src8776, src10998); - tmp0 = const_vec; - DPADD_SB4_SH(src10_r, src32_r, src54_r, src76_r, - filt0, filt1, filt2, filt3, tmp0, tmp0, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB4_SH(src21_r, src43_r, src65_r, src87_r, - filt0, filt1, filt2, filt3, tmp1, tmp1, tmp1, tmp1); - tmp2 = const_vec; - DPADD_SB4_SH(src32_r, src54_r, src76_r, src98_r, - filt0, filt1, filt2, filt3, tmp2, tmp2, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB4_SH(src43_r, src65_r, src87_r, src109_r, - filt0, filt1, filt2, filt3, tmp3, tmp3, tmp3, tmp3); - tmp4 = const_vec; - DPADD_SB4_SH(src2110, src4332, src6554, src8776, - filt0, filt1, filt2, filt3, tmp4, tmp4, tmp4, tmp4); - tmp5 = const_vec; - DPADD_SB4_SH(src4332, src6554, src8776, src10998, - filt0, filt1, filt2, filt3, tmp5, tmp5, tmp5, tmp5); + dst0 = HEVC_FILT_8TAP_SH(src10_r, src32_r, src54_r, src76_r, filt0, + filt1, filt2, filt3); + dst1 = HEVC_FILT_8TAP_SH(src21_r, src43_r, src65_r, src87_r, filt0, + filt1, filt2, filt3); + dst2 = HEVC_FILT_8TAP_SH(src32_r, src54_r, src76_r, src98_r, filt0, + filt1, filt2, filt3); + dst3 = HEVC_FILT_8TAP_SH(src43_r, src65_r, src87_r, src109_r, filt0, + filt1, filt2, filt3); + dst4 = HEVC_FILT_8TAP_SH(src2110, src4332, src6554, src8776, filt0, + filt1, filt2, filt3); + dst5 = HEVC_FILT_8TAP_SH(src4332, src6554, src8776, src10998, filt0, + filt1, filt2, filt3); - HEVC_UNIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - HEVC_UNIW_RND_CLIP2(tmp4, tmp5, weight_vec, offset_vec, rnd_vec, - dst4_r, dst5_r, dst4_l, dst5_l); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, weight_vec, + offset_vec, rnd_vec, dst0, dst1, dst2, + dst3); + HEVC_UNIW_RND_CLIP2_MAX_SATU_H(dst4, dst5, weight_vec, offset_vec, + rnd_vec, dst4, dst5); - HEVC_PCK_SW_SB12(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - dst4_l, dst4_r, dst5_l, dst5_r, - dst0_r, dst1_r, dst2_r); - ST12x4_UB(dst0_r, dst1_r, dst2_r, dst, dst_stride); + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + ST8x4_UB(out0, out1, dst, dst_stride); + ST4x4_UB(out2, out2, 0, 1, 2, 3, dst + 8, dst_stride); dst += (4 * dst_stride); src10_r = src54_r; @@ -1604,7 +1600,7 @@ static void hevc_vt_uniwgt_8t_12w_msa(uint8_t *src, } } -static void hevc_vt_uniwgt_8t_16multx2mult_msa(uint8_t *src, +static void hevc_vt_uniwgt_8t_16multx4mult_msa(uint8_t *src, int32_t src_stride, uint8_t *dst, int32_t dst_stride, @@ -1613,91 +1609,101 @@ static void hevc_vt_uniwgt_8t_16multx2mult_msa(uint8_t *src, int32_t weight, int32_t offset, int32_t rnd_val, - int32_t width) + int32_t weightmul16) { uint8_t *src_tmp; uint8_t *dst_tmp; int32_t loop_cnt, cnt; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16u8 out0, out1, out2, out3; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v16i8 src10_r, src32_r, src54_r, src76_r; v16i8 src21_r, src43_r, src65_r, src87_r; - v8i16 tmp0, tmp1, tmp2, tmp3; v16i8 src10_l, src32_l, src54_l, src76_l; v16i8 src21_l, src43_l, src65_l, src87_l; + v16i8 src98_r, src109_r, src98_l, src109_l; v8i16 filt0, filt1, filt2, filt3; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 filter_vec; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= (3 * src_stride); - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); - for (cnt = (width >> 4); cnt--;) { + for (cnt = weightmul16; cnt--;) { src_tmp = src; dst_tmp = dst; LD_SB7(src_tmp, src_stride, src0, src1, src2, src3, src4, src5, src6); src_tmp += (7 * src_stride); XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); - ILVR_B4_SB(src1, src0, src3, src2, src5, src4, src2, src1, - src10_r, src32_r, src54_r, src21_r); - ILVR_B2_SB(src4, src3, src6, src5, src43_r, src65_r); - ILVL_B4_SB(src1, src0, src3, src2, src5, src4, src2, src1, - src10_l, src32_l, src54_l, src21_l); - ILVL_B2_SB(src4, src3, src6, src5, src43_l, src65_l); - - for (loop_cnt = (height >> 1); loop_cnt--;) { - LD_SB2(src_tmp, src_stride, src7, src8); - src_tmp += (2 * src_stride); - XORI_B2_128_SB(src7, src8); - ILVR_B2_SB(src7, src6, src8, src7, src76_r, src87_r); - ILVL_B2_SB(src7, src6, src8, src7, src76_l, src87_l); - - tmp0 = const_vec; - DPADD_SB4_SH(src10_r, src32_r, src54_r, src76_r, - filt0, filt1, filt2, filt3, tmp0, tmp0, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB4_SH(src21_r, src43_r, src65_r, src87_r, - filt0, filt1, filt2, filt3, tmp1, tmp1, tmp1, tmp1); - tmp2 = const_vec; - DPADD_SB4_SH(src10_l, src32_l, src54_l, src76_l, - filt0, filt1, filt2, filt3, tmp2, tmp2, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB4_SH(src21_l, src43_l, src65_l, src87_l, - filt0, filt1, filt2, filt3, tmp3, tmp3, tmp3, tmp3); - - HEVC_UNIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst_tmp, dst_stride); - dst_tmp += (2 * dst_stride); - src10_r = src32_r; - src32_r = src54_r; - src54_r = src76_r; - src21_r = src43_r; - src43_r = src65_r; - src65_r = src87_r; - src10_l = src32_l; - src32_l = src54_l; - src54_l = src76_l; - src21_l = src43_l; - src43_l = src65_l; - src65_l = src87_l; - src6 = src8; + for (loop_cnt = (height >> 2); loop_cnt--;) { + LD_SB4(src_tmp, src_stride, src7, src8, src9, src10); + src_tmp += (4 * src_stride); + XORI_B4_128_SB(src7, src8, src9, src10); + + ILVR_B4_SB(src1, src0, src3, src2, src5, src4, src2, src1, + src10_r, src32_r, src54_r, src21_r); + ILVR_B2_SB(src4, src3, src6, src5, src43_r, src65_r); + ILVL_B4_SB(src1, src0, src3, src2, src5, src4, src2, src1, + src10_l, src32_l, src54_l, src21_l); + ILVL_B2_SB(src4, src3, src6, src5, src43_l, src65_l); + ILVR_B4_SB(src7, src6, src8, src7, src9, src8, src10, src9, + src76_r, src87_r, src98_r, src109_r); + ILVL_B4_SB(src7, src6, src8, src7, src9, src8, src10, src9, + src76_l, src87_l, src98_l, src109_l); + + dst0 = HEVC_FILT_8TAP_SH(src10_r, src32_r, src54_r, src76_r, filt0, + filt1, filt2, filt3); + dst1 = HEVC_FILT_8TAP_SH(src10_l, src32_l, src54_l, src76_l, filt0, + filt1, filt2, filt3); + dst2 = HEVC_FILT_8TAP_SH(src21_r, src43_r, src65_r, src87_r, filt0, + filt1, filt2, filt3); + dst3 = HEVC_FILT_8TAP_SH(src21_l, src43_l, src65_l, src87_l, filt0, + filt1, filt2, filt3); + dst4 = HEVC_FILT_8TAP_SH(src32_r, src54_r, src76_r, src98_r, filt0, + filt1, filt2, filt3); + dst5 = HEVC_FILT_8TAP_SH(src32_l, src54_l, src76_l, src98_l, filt0, + filt1, filt2, filt3); + dst6 = HEVC_FILT_8TAP_SH(src43_r, src65_r, src87_r, src109_r, filt0, + filt1, filt2, filt3); + dst7 = HEVC_FILT_8TAP_SH(src43_l, src65_l, src87_l, src109_l, filt0, + filt1, filt2, filt3); + + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, weight_vec, + offset_vec, rnd_vec, dst0, dst1, + dst2, dst3); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst4, dst5, dst6, dst7, weight_vec, + offset_vec, rnd_vec, dst4, dst5, + dst6, dst7); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + PCKEV_B2_UB(dst5, dst4, dst7, dst6, out2, out3); + ST_UB4(out0, out1, out2, out3, dst_tmp, dst_stride); + dst_tmp += (4 * dst_stride); + + src0 = src4; + src1 = src5; + src2 = src6; + src3 = src7; + src4 = src8; + src5 = src9; + src6 = src10; } src += 16; @@ -1715,9 +1721,9 @@ static void hevc_vt_uniwgt_8t_16w_msa(uint8_t *src, int32_t offset, int32_t rnd_val) { - hevc_vt_uniwgt_8t_16multx2mult_msa(src, src_stride, dst, dst_stride, + hevc_vt_uniwgt_8t_16multx4mult_msa(src, src_stride, dst, dst_stride, filter, height, weight, - offset, rnd_val, 16); + offset, rnd_val, 1); } static void hevc_vt_uniwgt_8t_24w_msa(uint8_t *src, @@ -1730,12 +1736,12 @@ static void hevc_vt_uniwgt_8t_24w_msa(uint8_t *src, int32_t offset, int32_t rnd_val) { - hevc_vt_uniwgt_8t_16multx2mult_msa(src, src_stride, dst, dst_stride, - filter, height, weight, - offset, rnd_val, 16); + hevc_vt_uniwgt_8t_16multx4mult_msa(src, src_stride, dst, dst_stride, + filter, 32, weight, + offset, rnd_val, 1); hevc_vt_uniwgt_8t_8w_msa(src + 16, src_stride, dst + 16, dst_stride, - filter, height, weight, offset, rnd_val); + filter, 32, weight, offset, rnd_val); } static void hevc_vt_uniwgt_8t_32w_msa(uint8_t *src, @@ -1748,9 +1754,9 @@ static void hevc_vt_uniwgt_8t_32w_msa(uint8_t *src, int32_t offset, int32_t rnd_val) { - hevc_vt_uniwgt_8t_16multx2mult_msa(src, src_stride, dst, dst_stride, + hevc_vt_uniwgt_8t_16multx4mult_msa(src, src_stride, dst, dst_stride, filter, height, weight, - offset, rnd_val, 32); + offset, rnd_val, 2); } static void hevc_vt_uniwgt_8t_48w_msa(uint8_t *src, @@ -1763,9 +1769,9 @@ static void hevc_vt_uniwgt_8t_48w_msa(uint8_t *src, int32_t offset, int32_t rnd_val) { - hevc_vt_uniwgt_8t_16multx2mult_msa(src, src_stride, dst, dst_stride, - filter, height, weight, - offset, rnd_val, 48); + hevc_vt_uniwgt_8t_16multx4mult_msa(src, src_stride, dst, dst_stride, + filter, 64, weight, + offset, rnd_val, 3); } static void hevc_vt_uniwgt_8t_64w_msa(uint8_t *src, @@ -1778,9 +1784,9 @@ static void hevc_vt_uniwgt_8t_64w_msa(uint8_t *src, int32_t offset, int32_t rnd_val) { - hevc_vt_uniwgt_8t_16multx2mult_msa(src, src_stride, dst, dst_stride, + hevc_vt_uniwgt_8t_16multx4mult_msa(src, src_stride, dst, dst_stride, filter, height, weight, - offset, rnd_val, 64); + offset, rnd_val, 4); } static void hevc_hv_uniwgt_8t_4w_msa(uint8_t *src, @@ -4939,18 +4945,18 @@ UNIWGT_MC_COPY(64); #define UNI_W_MC(PEL, DIR, WIDTH, TAP, DIR1, FILT_DIR) \ void ff_hevc_put_hevc_uni_w_##PEL##_##DIR##WIDTH##_8_msa(uint8_t *dst, \ - ptrdiff_t \ - dst_stride, \ - uint8_t *src, \ - ptrdiff_t \ - src_stride, \ - int height, \ - int denom, \ - int weight, \ - int offset, \ - intptr_t mx, \ - intptr_t my, \ - int width) \ + ptrdiff_t \ + dst_stride, \ + uint8_t *src, \ + ptrdiff_t \ + src_stride, \ + int height, \ + int denom, \ + int weight, \ + int offset, \ + intptr_t mx, \ + intptr_t my, \ + int width) \ { \ const int8_t *filter = ff_hevc_##PEL##_filters[FILT_DIR - 1]; \ int shift = denom + 14 - 8; \ @@ -4996,46 +5002,43 @@ UNI_W_MC(epel, v, 32, 4, vt, my); #undef UNI_W_MC -#define UNI_W_MC_HV(PEL, DIR, WIDTH, TAP, DIR1) \ -void ff_hevc_put_hevc_uni_w_##PEL##_##DIR##WIDTH##_8_msa(uint8_t *dst, \ - ptrdiff_t \ - dst_stride, \ - uint8_t *src, \ - ptrdiff_t \ - src_stride, \ - int height, \ - int denom, \ - int weight, \ - int offset, \ - intptr_t mx, \ - intptr_t my, \ - int width) \ -{ \ - const int8_t *filter_x = ff_hevc_##PEL##_filters[mx - 1]; \ - const int8_t *filter_y = ff_hevc_##PEL##_filters[my - 1]; \ - int shift = denom + 14 - 8; \ - \ - hevc_##DIR1##_uniwgt_##TAP##t_##WIDTH##w_msa(src, src_stride, dst, \ - dst_stride, filter_x, \ - filter_y, height, weight, \ - offset, shift); \ +#define UNI_W_MC_HV(PEL, WIDTH, TAP) \ +void ff_hevc_put_hevc_uni_w_##PEL##_hv##WIDTH##_8_msa(uint8_t *dst, \ + ptrdiff_t dst_stride, \ + uint8_t *src, \ + ptrdiff_t src_stride, \ + int height, \ + int denom, \ + int weight, \ + int offset, \ + intptr_t mx, \ + intptr_t my, \ + int width) \ +{ \ + const int8_t *filter_x = ff_hevc_##PEL##_filters[mx - 1]; \ + const int8_t *filter_y = ff_hevc_##PEL##_filters[my - 1]; \ + int shift = denom + 14 - 8; \ + \ + hevc_hv_uniwgt_##TAP##t_##WIDTH##w_msa(src, src_stride, dst, dst_stride, \ + filter_x, filter_y, height, \ + weight, offset, shift); \ } -UNI_W_MC_HV(qpel, hv, 4, 8, hv); -UNI_W_MC_HV(qpel, hv, 8, 8, hv); -UNI_W_MC_HV(qpel, hv, 12, 8, hv); -UNI_W_MC_HV(qpel, hv, 16, 8, hv); -UNI_W_MC_HV(qpel, hv, 24, 8, hv); -UNI_W_MC_HV(qpel, hv, 32, 8, hv); -UNI_W_MC_HV(qpel, hv, 48, 8, hv); -UNI_W_MC_HV(qpel, hv, 64, 8, hv); - -UNI_W_MC_HV(epel, hv, 4, 4, hv); -UNI_W_MC_HV(epel, hv, 6, 4, hv); -UNI_W_MC_HV(epel, hv, 8, 4, hv); -UNI_W_MC_HV(epel, hv, 12, 4, hv); -UNI_W_MC_HV(epel, hv, 16, 4, hv); -UNI_W_MC_HV(epel, hv, 24, 4, hv); -UNI_W_MC_HV(epel, hv, 32, 4, hv); +UNI_W_MC_HV(qpel, 4, 8); +UNI_W_MC_HV(qpel, 8, 8); +UNI_W_MC_HV(qpel, 12, 8); +UNI_W_MC_HV(qpel, 16, 8); +UNI_W_MC_HV(qpel, 24, 8); +UNI_W_MC_HV(qpel, 32, 8); +UNI_W_MC_HV(qpel, 48, 8); +UNI_W_MC_HV(qpel, 64, 8); + +UNI_W_MC_HV(epel, 4, 4); +UNI_W_MC_HV(epel, 6, 4); +UNI_W_MC_HV(epel, 8, 4); +UNI_W_MC_HV(epel, 12, 4); +UNI_W_MC_HV(epel, 16, 4); +UNI_W_MC_HV(epel, 24, 4); +UNI_W_MC_HV(epel, 32, 4); #undef UNI_W_MC_HV From 147c1e008a7baf9c4d4e18e9707765ae686b1521 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Thu, 12 Oct 2017 18:46:06 +0530 Subject: [PATCH 0467/2557] doc/filters: correct typo and incomplete desc. Correct typo in signalstats filter section and qualify description for variable in select filter. Signed-off-by: Gyan Doshi Signed-off-by: Michael Niedermayer --- doc/filters.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index e26dde4b1a9f4..13eb62b307466 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -17679,7 +17679,7 @@ with AV_LOG_INFO loglevel. @itemize @item -Print all metadata values for frames with key @code{lavfi.singnalstats.YDIF} with values +Print all metadata values for frames with key @code{lavfi.signalstats.YDIF} with values between 0 and 1. @example signalstats,metadata=print:key=lavfi.signalstats.YDIF:value=0:function=expr:expr='between(VALUE1,0,1)' @@ -17807,7 +17807,7 @@ The PTS of the previously filtered video frame. It's NAN if undefined. The PTS of the last previously filtered video frame. It's NAN if undefined. @item prev_selected_t -The PTS of the last previously selected video frame. It's NAN if undefined. +The PTS of the last previously selected video frame, expressed in seconds. It's NAN if undefined. @item start_pts The PTS of the first video frame in the video. It's NAN if undefined. From 15dc897582ad15210a94c7a8a13e7679f180a049 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 12 Oct 2017 19:36:19 -0300 Subject: [PATCH 0468/2557] configure: list libv4l2 as an optional library for v4l2 Fixes regression since 6dfcbd80ad446ff163b47f2bf432bbf706436ea8 and 734ed38931103c523c42333633a315a0ce1b5eb2. Signed-off-by: James Almer --- configure | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 1db50df0a4d84..dc486ed756f38 100755 --- a/configure +++ b/configure @@ -3116,7 +3116,6 @@ kmsgrab_indev_deps="libdrm" lavfi_indev_deps="avfilter" libcdio_indev_deps="libcdio" libdc1394_indev_deps="libdc1394" -v4l2_indev_deps="libv4l2" openal_indev_deps="openal" opengl_outdev_deps="opengl" oss_indev_deps_any="soundcard_h sys_soundcard_h" @@ -3127,7 +3126,9 @@ sdl2_outdev_deps="sdl2" sndio_indev_deps="sndio" sndio_outdev_deps="sndio" v4l2_indev_deps_any="linux_videodev2_h sys_videoio_h" +v4l2_indev_suggest="libv4l2" v4l2_outdev_deps_any="linux_videodev2_h sys_videoio_h" +v4l2_outdev_suggest="libv4l2" vfwcap_indev_deps="vfw32 vfwcap_defines" xcbgrab_indev_deps="libxcb" xcbgrab_indev_suggest="libxcb_shm libxcb_shape libxcb_xfixes" From 6b52c0b583b84aa5290f3c8a022deefe8dc2fed1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 13 Oct 2017 11:22:44 -0300 Subject: [PATCH 0469/2557] configure: add missing zlib extralibs to the libmysofa check Should fix checks with static builds. Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index dc486ed756f38..64fd0882089f3 100755 --- a/configure +++ b/configure @@ -6009,7 +6009,7 @@ enabled libmfx && { use_pkg_config libmfx libmfx "mfx/mfxvideo.h" MFX { require libmfx "mfx/mfxvideo.h" MFXInit -llibmfx && warn "using libmfx without pkg-config"; } } enabled libmodplug && require_pkg_config libmodplug libmodplug libmodplug/modplug.h ModPlug_Load enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame -enabled libmysofa && require libmysofa "mysofa.h" mysofa_load -lmysofa +enabled libmysofa && require libmysofa "mysofa.h" mysofa_load -lmysofa $zlib_extralibs enabled libnpp && { check_lib libnpp npp.h nppGetLibVersion -lnppig -lnppicc -lnppc || check_lib libnpp npp.h nppGetLibVersion -lnppi -lnppc || die "ERROR: libnpp not found"; } From feed201849b8f9153ba815ade39329cd10a36623 Mon Sep 17 00:00:00 2001 From: Daniel Kucera Date: Mon, 5 Jun 2017 20:28:30 +0200 Subject: [PATCH 0470/2557] libavformat/wtvdec: return AVERROR_EOF on EOF Signed-off-by: Daniel Kucera Signed-off-by: wm4 --- libavformat/wtvdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/wtvdec.c b/libavformat/wtvdec.c index 27be5c9c04d90..301163bdcb1f6 100644 --- a/libavformat/wtvdec.c +++ b/libavformat/wtvdec.c @@ -65,7 +65,7 @@ static int64_t seek_by_sector(AVIOContext *pb, int64_t sector, int64_t offset) } /** - * @return bytes read, 0 on end of file, or <0 on error + * @return bytes read, AVERROR_EOF on end of file, or <0 on error */ static int wtvfile_read_packet(void *opaque, uint8_t *buf, int buf_size) { @@ -76,7 +76,7 @@ static int wtvfile_read_packet(void *opaque, uint8_t *buf, int buf_size) if (wf->error || pb->error) return -1; if (wf->position >= wf->length || avio_feof(pb)) - return 0; + return AVERROR_EOF; buf_size = FFMIN(buf_size, wf->length - wf->position); while(nread < buf_size) { From 8e7e042d41ac42f01d5573a4b0f7d9060356bd46 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 23 Sep 2017 16:26:28 +0200 Subject: [PATCH 0471/2557] Remove all output devices The libavformat API is not suitable for exporting output devices as muxers. Some practical problems are e.g. lack of timing/synchronization mechanisms or interaction with output-specific features. --- configure | 22 ++------ doc/avconv.texi | 1 - doc/avplay.texi | 1 - doc/outdevs.texi | 33 ----------- libavdevice/Makefile | 5 +- libavdevice/alldevices.c | 39 +++++-------- libavdevice/alsa.c | 16 ------ libavdevice/alsa.h | 2 - libavdevice/alsa_enc.c | 117 --------------------------------------- libavdevice/oss_enc.c | 108 ------------------------------------ libavdevice/sndio_enc.c | 95 ------------------------------- libavdevice/version.h | 2 +- 12 files changed, 22 insertions(+), 419 deletions(-) delete mode 100644 doc/outdevs.texi delete mode 100644 libavdevice/alsa_enc.c delete mode 100644 libavdevice/oss_enc.c delete mode 100644 libavdevice/sndio_enc.c diff --git a/configure b/configure index 9b0b95a69e7fe..67354dc6a7194 100755 --- a/configure +++ b/configure @@ -73,7 +73,6 @@ Help options: --list-protocols show all available protocols --list-bsfs show all available bitstream filters --list-indevs show all available input devices - --list-outdevs show all available output devices --list-filters show all available filters Standard options: @@ -163,9 +162,6 @@ Individual component options: --enable-indev=NAME enable input device NAME --disable-indev=NAME disable input device NAME --disable-indevs disable input devices - --enable-outdev=NAME enable output device NAME - --disable-outdev=NAME disable output device NAME - --disable-outdevs disable output devices --disable-devices disable all devices --enable-filter=NAME enable filter NAME --disable-filter=NAME disable filter NAME @@ -1224,7 +1220,6 @@ AVCODEC_COMPONENTS=" AVDEVICE_COMPONENTS=" indevs - outdevs " AVFILTER_COMPONENTS=" filters @@ -2433,9 +2428,8 @@ wtv_demuxer_select="mpegts_demuxer riffdec" xmv_demuxer_select="riffdec" xwma_demuxer_select="riffdec" -# indevs / outdevs +# indevs alsa_indev_deps="alsa" -alsa_outdev_deps="alsa" avfoundation_indev_deps="AVFoundation_AVFoundation_h objc_arc pthreads" avfoundation_indev_extralibs="-framework Foundation -framework AVFoundation -framework CoreVideo -framework CoreMedia" bktr_indev_deps_any="dev_bktr_ioctl_bt848_h machine_ioctl_bt848_h dev_video_bktr_ioctl_bt848_h dev_ic_bt8xx_h" @@ -2447,10 +2441,8 @@ jack_indev_deps_any="sem_timedwait dispatch_dispatch_h" libcdio_indev_deps="libcdio" libdc1394_indev_deps="libdc1394" oss_indev_deps_any="sys_soundcard_h" -oss_outdev_deps_any="sys_soundcard_h" pulse_indev_deps="libpulse" sndio_indev_deps="sndio" -sndio_outdev_deps="sndio" v4l2_indev_deps_any="linux_videodev2_h sys_videoio_h" vfwcap_indev_deps="vfw32 vfwcap_defines" xcbgrab_indev_deps="libxcb libxcb_shape" @@ -2715,7 +2707,6 @@ HWACCEL_LIST=$(find_things hwaccel HWACCEL libavcodec/allcodecs.c) PARSER_LIST=$(find_things parser PARSER libavcodec/allcodecs.c) MUXER_LIST=$(find_things muxer _MUX libavformat/allformats.c) DEMUXER_LIST=$(find_things demuxer DEMUX libavformat/allformats.c) -OUTDEV_LIST=$(find_things outdev OUTDEV libavdevice/alldevices.c) INDEV_LIST=$(find_things indev _IN libavdevice/alldevices.c) FILTER_LIST=$(find_things filter FILTER libavfilter/allfilters.c) @@ -2739,7 +2730,6 @@ AVCODEC_COMPONENTS_LIST=" AVDEVICE_COMPONENTS_LIST=" $INDEV_LIST - $OUTDEV_LIST " AVFILTER_COMPONENTS_LIST=" @@ -2800,7 +2790,7 @@ for opt do add_extralibs $optval ;; --disable-devices) - disable $INDEV_LIST $OUTDEV_LIST + disable $INDEV_LIST ;; --enable-debug=*) debuglevel="$optval" @@ -3906,7 +3896,6 @@ case $target_os in netbsd) disable symver oss_indev_extralibs="-lossaudio" - oss_outdev_extralibs="-lossaudio" ;; openbsd|bitrig) disable symver @@ -3914,7 +3903,6 @@ case $target_os in SLIB_INSTALL_NAME='$(SLIBNAME).$(LIBMAJOR).$(LIBMINOR)' SLIB_INSTALL_LINKS= oss_indev_extralibs="-lossaudio" - oss_outdev_extralibs="-lossaudio" ;; dragonfly) disable symver @@ -4789,13 +4777,13 @@ check_header "dev/bktr/ioctl_meteor.h dev/bktr/ioctl_bt848.h" check_header sys/soundcard.h -enabled_any alsa_indev alsa_outdev && +enabled alsa_indev && check_lib alsa alsa/asoundlib.h snd_pcm_htimestamp -lasound enabled libjack && require_pkg_config libjack jack jack/jack.h jack_port_get_latency_range -enabled_any sndio_indev sndio_outdev && check_lib sndio sndio.h sio_open -lsndio +enabled sndio_indev && check_lib sndio sndio.h sio_open -lsndio if enabled libcdio; then check_lib libcdio "cdio/cdda.h cdio/paranoia.h" cdio_cddap_open -lcdio_paranoia -lcdio_cdda -lcdio || @@ -5252,7 +5240,7 @@ echo "Programs:" print_enabled '' $PROGRAM_LIST | print_3_columns echo -for type in decoder encoder hwaccel parser demuxer muxer protocol filter bsf indev outdev; do +for type in decoder encoder hwaccel parser demuxer muxer protocol filter bsf indev; do echo "Enabled ${type}s:" eval list=\$$(toupper $type)_LIST print_enabled '_*' $list | print_3_columns diff --git a/doc/avconv.texi b/doc/avconv.texi index d8eb44864b569..0650051c38a55 100644 --- a/doc/avconv.texi +++ b/doc/avconv.texi @@ -1264,7 +1264,6 @@ avconv -i src.ext -lmax 21*QP2LAMBDA dst.ext @include demuxers.texi @include muxers.texi @include indevs.texi -@include outdevs.texi @include protocols.texi @include bitstream_filters.texi @include filters.texi diff --git a/doc/avplay.texi b/doc/avplay.texi index 0f72cfd9849de..b2038aed8a641 100644 --- a/doc/avplay.texi +++ b/doc/avplay.texi @@ -164,7 +164,6 @@ Seek to percentage in file corresponding to fraction of width. @include demuxers.texi @include muxers.texi @include indevs.texi -@include outdevs.texi @include protocols.texi @include filters.texi diff --git a/doc/outdevs.texi b/doc/outdevs.texi deleted file mode 100644 index dd7bd6475d6d3..0000000000000 --- a/doc/outdevs.texi +++ /dev/null @@ -1,33 +0,0 @@ -@chapter Output Devices -@c man begin OUTPUT DEVICES - -Output devices are configured elements in Libav which allow to write -multimedia data to an output device attached to your system. - -When you configure your Libav build, all the supported output devices -are enabled by default. You can list all available ones using the -configure option "--list-outdevs". - -You can disable all the output devices using the configure option -"--disable-outdevs", and selectively enable an output device using the -option "--enable-outdev=@var{OUTDEV}", or you can disable a particular -input device using the option "--disable-outdev=@var{OUTDEV}". - -The option "-formats" of the av* tools will display the list of -enabled output devices (amongst the muxers). - -A description of the currently available output devices follows. - -@section alsa - -ALSA (Advanced Linux Sound Architecture) output device. - -@section oss - -OSS (Open Sound System) output device. - -@section sndio - -sndio audio output device. - -@c man end OUTPUT DEVICES diff --git a/libavdevice/Makefile b/libavdevice/Makefile index ab8931c639011..69542020d3129 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -9,19 +9,16 @@ OBJS = alldevices.o \ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o -# input/output devices +# input devices OBJS-$(CONFIG_ALSA_INDEV) += alsa_dec.o alsa.o -OBJS-$(CONFIG_ALSA_OUTDEV) += alsa_enc.o alsa.o OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation_dec.o OBJS-$(CONFIG_BKTR_INDEV) += bktr.o OBJS-$(CONFIG_DV1394_INDEV) += dv1394.o OBJS-$(CONFIG_FBDEV_INDEV) += fbdev.o OBJS-$(CONFIG_JACK_INDEV) += jack.o timefilter.o OBJS-$(CONFIG_OSS_INDEV) += oss_dec.o oss.o -OBJS-$(CONFIG_OSS_OUTDEV) += oss_enc.o oss.o OBJS-$(CONFIG_PULSE_INDEV) += pulse.o OBJS-$(CONFIG_SNDIO_INDEV) += sndio_dec.o sndio.o -OBJS-$(CONFIG_SNDIO_OUTDEV) += sndio_enc.o sndio.o OBJS-$(CONFIG_V4L2_INDEV) += v4l2.o OBJS-$(CONFIG_VFWCAP_INDEV) += vfwcap.o OBJS-$(CONFIG_XCBGRAB_INDEV) += xcbgrab.o diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index cdbca4c8e8be0..47d7421a063d0 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -22,13 +22,6 @@ #include "libavformat/avformat.h" #include "avdevice.h" -#define REGISTER_OUTDEV(X, x) \ - { \ - extern AVOutputFormat ff_##x##_muxer; \ - if (CONFIG_##X##_OUTDEV) \ - av_register_output_format(&ff_##x##_muxer); \ - } - #define REGISTER_INDEV(X, x) \ { \ extern AVInputFormat ff_##x##_demuxer; \ @@ -36,8 +29,6 @@ av_register_input_format(&ff_##x##_demuxer); \ } -#define REGISTER_INOUTDEV(X, x) REGISTER_OUTDEV(X, x); REGISTER_INDEV(X, x) - void avdevice_register_all(void) { static int initialized; @@ -46,21 +37,21 @@ void avdevice_register_all(void) return; initialized = 1; - /* devices */ - REGISTER_INOUTDEV(ALSA, alsa); - REGISTER_INDEV (AVFOUNDATION, avfoundation); - REGISTER_INDEV (BKTR, bktr); - REGISTER_INDEV (DV1394, dv1394); - REGISTER_INDEV (FBDEV, fbdev); - REGISTER_INDEV (JACK, jack); - REGISTER_INOUTDEV(OSS, oss); - REGISTER_INDEV (PULSE, pulse); - REGISTER_INOUTDEV(SNDIO, sndio); - REGISTER_INDEV (V4L2, v4l2); - REGISTER_INDEV (VFWCAP, vfwcap); - REGISTER_INDEV (XCBGRAB, xcbgrab); + /* input devices */ + REGISTER_INDEV(ALSA, alsa); + REGISTER_INDEV(AVFOUNDATION, avfoundation); + REGISTER_INDEV(BKTR, bktr); + REGISTER_INDEV(DV1394, dv1394); + REGISTER_INDEV(FBDEV, fbdev); + REGISTER_INDEV(JACK, jack); + REGISTER_INDEV(OSS, oss); + REGISTER_INDEV(PULSE, pulse); + REGISTER_INDEV(SNDIO, sndio); + REGISTER_INDEV(V4L2, v4l2); + REGISTER_INDEV(VFWCAP, vfwcap); + REGISTER_INDEV(XCBGRAB, xcbgrab); /* external libraries */ - REGISTER_INDEV (LIBCDIO, libcdio); - REGISTER_INDEV (LIBDC1394, libdc1394); + REGISTER_INDEV(LIBCDIO, libcdio); + REGISTER_INDEV(LIBDC1394, libdc1394); } diff --git a/libavdevice/alsa.c b/libavdevice/alsa.c index d394e4377d17f..81c94049cb9fd 100644 --- a/libavdevice/alsa.c +++ b/libavdevice/alsa.c @@ -344,19 +344,3 @@ int ff_alsa_xrun_recover(AVFormatContext *s1, int err) } return err; } - -int ff_alsa_extend_reorder_buf(AlsaData *s, int min_size) -{ - int size = s->reorder_buf_size; - void *r; - - av_assert0(size != 0); - while (size < min_size) - size *= 2; - r = av_realloc(s->reorder_buf, size * s->frame_size); - if (!r) - return AVERROR(ENOMEM); - s->reorder_buf = r; - s->reorder_buf_size = size; - return 0; -} diff --git a/libavdevice/alsa.h b/libavdevice/alsa.h index 590b354053493..773cd2faf8ce9 100644 --- a/libavdevice/alsa.h +++ b/libavdevice/alsa.h @@ -91,6 +91,4 @@ int ff_alsa_close(AVFormatContext *s1); */ int ff_alsa_xrun_recover(AVFormatContext *s1, int err); -int ff_alsa_extend_reorder_buf(AlsaData *s, int size); - #endif /* AVDEVICE_ALSA_H */ diff --git a/libavdevice/alsa_enc.c b/libavdevice/alsa_enc.c deleted file mode 100644 index 3094b5043eb6a..0000000000000 --- a/libavdevice/alsa_enc.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * ALSA input and output - * Copyright (c) 2007 Luca Abeni ( lucabe72 email it ) - * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr ) - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * ALSA input and output: output - * @author Luca Abeni ( lucabe72 email it ) - * @author Benoit Fouet ( benoit fouet free fr ) - * - * This avdevice encoder allows to play audio to an ALSA (Advanced Linux - * Sound Architecture) device. - * - * The filename parameter is the name of an ALSA PCM device capable of - * capture, for example "default" or "plughw:1"; see the ALSA documentation - * for naming conventions. The empty string is equivalent to "default". - * - * The playback period is set to the lower value available for the device, - * which gives a low latency suitable for real-time playback. - */ - -#include - -#include "libavutil/internal.h" - -#include "libavformat/avformat.h" - -#include "alsa.h" - -static av_cold int audio_write_header(AVFormatContext *s1) -{ - AlsaData *s = s1->priv_data; - AVStream *st; - unsigned int sample_rate; - enum AVCodecID codec_id; - int res; - - st = s1->streams[0]; - sample_rate = st->codecpar->sample_rate; - codec_id = st->codecpar->codec_id; - res = ff_alsa_open(s1, SND_PCM_STREAM_PLAYBACK, &sample_rate, - st->codecpar->channels, &codec_id); - if (sample_rate != st->codecpar->sample_rate) { - av_log(s1, AV_LOG_ERROR, - "sample rate %d not available, nearest is %d\n", - st->codecpar->sample_rate, sample_rate); - goto fail; - } - - return res; - -fail: - snd_pcm_close(s->h); - return AVERROR(EIO); -} - -static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt) -{ - AlsaData *s = s1->priv_data; - int res; - int size = pkt->size; - uint8_t *buf = pkt->data; - - size /= s->frame_size; - if (s->reorder_func) { - if (size > s->reorder_buf_size) - if (ff_alsa_extend_reorder_buf(s, size)) - return AVERROR(ENOMEM); - s->reorder_func(buf, s->reorder_buf, size); - buf = s->reorder_buf; - } - while ((res = snd_pcm_writei(s->h, buf, size)) < 0) { - if (res == -EAGAIN) { - - return AVERROR(EAGAIN); - } - - if (ff_alsa_xrun_recover(s1, res) < 0) { - av_log(s1, AV_LOG_ERROR, "ALSA write error: %s\n", - snd_strerror(res)); - - return AVERROR(EIO); - } - } - - return 0; -} - -AVOutputFormat ff_alsa_muxer = { - .name = "alsa", - .long_name = NULL_IF_CONFIG_SMALL("ALSA audio output"), - .priv_data_size = sizeof(AlsaData), - .audio_codec = DEFAULT_CODEC_ID, - .video_codec = AV_CODEC_ID_NONE, - .write_header = audio_write_header, - .write_packet = audio_write_packet, - .write_trailer = ff_alsa_close, - .flags = AVFMT_NOFILE, -}; diff --git a/libavdevice/oss_enc.c b/libavdevice/oss_enc.c deleted file mode 100644 index eb6432ced047b..0000000000000 --- a/libavdevice/oss_enc.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Linux audio grab interface - * Copyright (c) 2000, 2001 Fabrice Bellard - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#if HAVE_SOUNDCARD_H -#include -#else -#include -#endif - -#include -#include -#include - -#include "libavutil/internal.h" - -#include "libavcodec/avcodec.h" - -#include "libavformat/avformat.h" -#include "libavformat/internal.h" - -#include "oss.h" - -static int audio_write_header(AVFormatContext *s1) -{ - OSSAudioData *s = s1->priv_data; - AVStream *st; - int ret; - - st = s1->streams[0]; - s->sample_rate = st->codecpar->sample_rate; - s->channels = st->codecpar->channels; - ret = ff_oss_audio_open(s1, 1, s1->filename); - if (ret < 0) { - return AVERROR(EIO); - } else { - return 0; - } -} - -static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt) -{ - OSSAudioData *s = s1->priv_data; - int len, ret; - int size= pkt->size; - uint8_t *buf= pkt->data; - - while (size > 0) { - len = FFMIN(OSS_AUDIO_BLOCK_SIZE - s->buffer_ptr, size); - memcpy(s->buffer + s->buffer_ptr, buf, len); - s->buffer_ptr += len; - if (s->buffer_ptr >= OSS_AUDIO_BLOCK_SIZE) { - for(;;) { - ret = write(s->fd, s->buffer, OSS_AUDIO_BLOCK_SIZE); - if (ret > 0) - break; - if (ret < 0 && (errno != EAGAIN && errno != EINTR)) - return AVERROR(EIO); - } - s->buffer_ptr = 0; - } - buf += len; - size -= len; - } - return 0; -} - -static int audio_write_trailer(AVFormatContext *s1) -{ - OSSAudioData *s = s1->priv_data; - - ff_oss_audio_close(s); - return 0; -} - -AVOutputFormat ff_oss_muxer = { - .name = "oss", - .long_name = NULL_IF_CONFIG_SMALL("OSS (Open Sound System) playback"), - .priv_data_size = sizeof(OSSAudioData), - /* XXX: we make the assumption that the soundcard accepts this format */ - /* XXX: find better solution with "preinit" method, needed also in - other formats */ - .audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), - .video_codec = AV_CODEC_ID_NONE, - .write_header = audio_write_header, - .write_packet = audio_write_packet, - .write_trailer = audio_write_trailer, - .flags = AVFMT_NOFILE, -}; diff --git a/libavdevice/sndio_enc.c b/libavdevice/sndio_enc.c deleted file mode 100644 index 97b1827f82a89..0000000000000 --- a/libavdevice/sndio_enc.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * sndio play and grab interface - * Copyright (c) 2010 Jacob Meuser - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#include "libavutil/internal.h" - -#include "libavformat/avformat.h" - -#include "libavdevice/sndio.h" - -static av_cold int audio_write_header(AVFormatContext *s1) -{ - SndioData *s = s1->priv_data; - AVStream *st; - int ret; - - st = s1->streams[0]; - s->sample_rate = st->codecpar->sample_rate; - s->channels = st->codecpar->channels; - - ret = ff_sndio_open(s1, 1, s1->filename); - - return ret; -} - -static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt) -{ - SndioData *s = s1->priv_data; - uint8_t *buf= pkt->data; - int size = pkt->size; - int len, ret; - - while (size > 0) { - len = FFMIN(s->buffer_size - s->buffer_offset, size); - memcpy(s->buffer + s->buffer_offset, buf, len); - buf += len; - size -= len; - s->buffer_offset += len; - if (s->buffer_offset >= s->buffer_size) { - ret = sio_write(s->hdl, s->buffer, s->buffer_size); - if (ret == 0 || sio_eof(s->hdl)) - return AVERROR(EIO); - s->softpos += ret; - s->buffer_offset = 0; - } - } - - return 0; -} - -static int audio_write_trailer(AVFormatContext *s1) -{ - SndioData *s = s1->priv_data; - - sio_write(s->hdl, s->buffer, s->buffer_offset); - - ff_sndio_close(s); - - return 0; -} - -AVOutputFormat ff_sndio_muxer = { - .name = "sndio", - .long_name = NULL_IF_CONFIG_SMALL("sndio audio playback"), - .priv_data_size = sizeof(SndioData), - /* XXX: we make the assumption that the soundcard accepts this format */ - /* XXX: find better solution with "preinit" method, needed also in - other formats */ - .audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), - .video_codec = AV_CODEC_ID_NONE, - .write_header = audio_write_header, - .write_packet = audio_write_packet, - .write_trailer = audio_write_trailer, - .flags = AVFMT_NOFILE, -}; diff --git a/libavdevice/version.h b/libavdevice/version.h index 1bcb32c4c9055..e09a23cf676cc 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -29,7 +29,7 @@ #define LIBAVDEVICE_VERSION_MAJOR 57 #define LIBAVDEVICE_VERSION_MINOR 0 -#define LIBAVDEVICE_VERSION_MICRO 0 +#define LIBAVDEVICE_VERSION_MICRO 1 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ LIBAVDEVICE_VERSION_MINOR, \ From 8d3db95f201fba2e22611f9a5f8eced76f8e89ed Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 27 Sep 2017 15:12:41 +0200 Subject: [PATCH 0472/2557] sndio: Coalesce source files after outdev removal --- libavdevice/Makefile | 2 +- libavdevice/sndio.c | 108 ++++++++++++++++++++++++++++++++++-- libavdevice/sndio.h | 48 ---------------- libavdevice/sndio_dec.c | 120 ---------------------------------------- 4 files changed, 104 insertions(+), 174 deletions(-) delete mode 100644 libavdevice/sndio.h delete mode 100644 libavdevice/sndio_dec.c diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 69542020d3129..18228f590f583 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -18,7 +18,7 @@ OBJS-$(CONFIG_FBDEV_INDEV) += fbdev.o OBJS-$(CONFIG_JACK_INDEV) += jack.o timefilter.o OBJS-$(CONFIG_OSS_INDEV) += oss_dec.o oss.o OBJS-$(CONFIG_PULSE_INDEV) += pulse.o -OBJS-$(CONFIG_SNDIO_INDEV) += sndio_dec.o sndio.o +OBJS-$(CONFIG_SNDIO_INDEV) += sndio.o OBJS-$(CONFIG_V4L2_INDEV) += v4l2.o OBJS-$(CONFIG_VFWCAP_INDEV) += vfwcap.o OBJS-$(CONFIG_XCBGRAB_INDEV) += xcbgrab.o diff --git a/libavdevice/sndio.c b/libavdevice/sndio.c index 739551b84128e..ae14453bce720 100644 --- a/libavdevice/sndio.c +++ b/libavdevice/sndio.c @@ -1,5 +1,5 @@ /* - * sndio play and grab interface + * sndio grab interface * Copyright (c) 2010 Jacob Meuser * * This file is part of Libav. @@ -22,9 +22,26 @@ #include #include +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "libavutil/time.h" + #include "libavformat/avformat.h" +#include "libavformat/internal.h" -#include "libavdevice/sndio.h" +typedef struct SndioData { + AVClass *class; + struct sio_hdl *hdl; + enum AVCodecID codec_id; + int64_t hwpos; + int64_t softpos; + uint8_t *buffer; + int bps; + int buffer_size; + int buffer_offset; + int channels; + int sample_rate; +} SndioData; static inline void movecb(void *addr, int delta) { @@ -33,8 +50,8 @@ static inline void movecb(void *addr, int delta) s->hwpos += delta * s->channels * s->bps; } -av_cold int ff_sndio_open(AVFormatContext *s1, int is_output, - const char *audio_device) +static av_cold int sndio_open(AVFormatContext *s1, int is_output, + const char *audio_device) { SndioData *s = s1->priv_data; struct sio_hdl *hdl; @@ -109,8 +126,65 @@ av_cold int ff_sndio_open(AVFormatContext *s1, int is_output, return AVERROR(EIO); } -int ff_sndio_close(SndioData *s) +static av_cold int audio_read_header(AVFormatContext *s1) +{ + SndioData *s = s1->priv_data; + AVStream *st; + int ret; + + st = avformat_new_stream(s1, NULL); + if (!st) + return AVERROR(ENOMEM); + + ret = sndio_open(s1, 0, s1->filename); + if (ret < 0) + return ret; + + /* take real parameters */ + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = s->codec_id; + st->codecpar->sample_rate = s->sample_rate; + st->codecpar->channels = s->channels; + + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ + + return 0; +} + +static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) +{ + SndioData *s = s1->priv_data; + int64_t bdelay, cur_time; + int ret; + + if ((ret = av_new_packet(pkt, s->buffer_size)) < 0) + return ret; + + ret = sio_read(s->hdl, pkt->data, pkt->size); + if (ret == 0 || sio_eof(s->hdl)) { + av_packet_unref(pkt); + return AVERROR_EOF; + } + + pkt->size = ret; + s->softpos += ret; + + /* compute pts of the start of the packet */ + cur_time = av_gettime(); + + bdelay = ret + s->hwpos - s->softpos; + + /* convert to pts */ + pkt->pts = cur_time - ((bdelay * 1000000) / + (s->bps * s->channels * s->sample_rate)); + + return 0; +} + +static av_cold int audio_read_close(AVFormatContext *s1) { + SndioData *s = s1->priv_data; + av_freep(&s->buffer); if (s->hdl) @@ -118,3 +192,27 @@ int ff_sndio_close(SndioData *s) return 0; } + +static const AVOption options[] = { + { "sample_rate", "", offsetof(SndioData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { "channels", "", offsetof(SndioData, channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +static const AVClass sndio_demuxer_class = { + .class_name = "sndio indev", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_sndio_demuxer = { + .name = "sndio", + .long_name = NULL_IF_CONFIG_SMALL("sndio audio capture"), + .priv_data_size = sizeof(SndioData), + .read_header = audio_read_header, + .read_packet = audio_read_packet, + .read_close = audio_read_close, + .flags = AVFMT_NOFILE, + .priv_class = &sndio_demuxer_class, +}; diff --git a/libavdevice/sndio.h b/libavdevice/sndio.h deleted file mode 100644 index cd5c55ecc5462..0000000000000 --- a/libavdevice/sndio.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * sndio play and grab interface - * Copyright (c) 2010 Jacob Meuser - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVDEVICE_SNDIO_H -#define AVDEVICE_SNDIO_H - -#include -#include - -#include "libavformat/avformat.h" -#include "libavutil/log.h" - -typedef struct SndioData { - AVClass *class; - struct sio_hdl *hdl; - enum AVCodecID codec_id; - int64_t hwpos; - int64_t softpos; - uint8_t *buffer; - int bps; - int buffer_size; - int buffer_offset; - int channels; - int sample_rate; -} SndioData; - -int ff_sndio_open(AVFormatContext *s1, int is_output, const char *audio_device); -int ff_sndio_close(SndioData *s); - -#endif /* AVDEVICE_SNDIO_H */ diff --git a/libavdevice/sndio_dec.c b/libavdevice/sndio_dec.c deleted file mode 100644 index a839a6fab2fa8..0000000000000 --- a/libavdevice/sndio_dec.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * sndio play and grab interface - * Copyright (c) 2010 Jacob Meuser - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#include "libavutil/internal.h" -#include "libavutil/opt.h" -#include "libavutil/time.h" - -#include "libavformat/avformat.h" -#include "libavformat/internal.h" - -#include "libavdevice/sndio.h" - -static av_cold int audio_read_header(AVFormatContext *s1) -{ - SndioData *s = s1->priv_data; - AVStream *st; - int ret; - - st = avformat_new_stream(s1, NULL); - if (!st) - return AVERROR(ENOMEM); - - ret = ff_sndio_open(s1, 0, s1->filename); - if (ret < 0) - return ret; - - /* take real parameters */ - st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->codec_id = s->codec_id; - st->codecpar->sample_rate = s->sample_rate; - st->codecpar->channels = s->channels; - - avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ - - return 0; -} - -static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) -{ - SndioData *s = s1->priv_data; - int64_t bdelay, cur_time; - int ret; - - if ((ret = av_new_packet(pkt, s->buffer_size)) < 0) - return ret; - - ret = sio_read(s->hdl, pkt->data, pkt->size); - if (ret == 0 || sio_eof(s->hdl)) { - av_packet_unref(pkt); - return AVERROR_EOF; - } - - pkt->size = ret; - s->softpos += ret; - - /* compute pts of the start of the packet */ - cur_time = av_gettime(); - - bdelay = ret + s->hwpos - s->softpos; - - /* convert to pts */ - pkt->pts = cur_time - ((bdelay * 1000000) / - (s->bps * s->channels * s->sample_rate)); - - return 0; -} - -static av_cold int audio_read_close(AVFormatContext *s1) -{ - SndioData *s = s1->priv_data; - - ff_sndio_close(s); - - return 0; -} - -static const AVOption options[] = { - { "sample_rate", "", offsetof(SndioData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { "channels", "", offsetof(SndioData, channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { NULL }, -}; - -static const AVClass sndio_demuxer_class = { - .class_name = "sndio indev", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVInputFormat ff_sndio_demuxer = { - .name = "sndio", - .long_name = NULL_IF_CONFIG_SMALL("sndio audio capture"), - .priv_data_size = sizeof(SndioData), - .read_header = audio_read_header, - .read_packet = audio_read_packet, - .read_close = audio_read_close, - .flags = AVFMT_NOFILE, - .priv_class = &sndio_demuxer_class, -}; From 6ce13070bddeb78fb2974ed94d28ef9424631817 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 27 Sep 2017 15:18:58 +0200 Subject: [PATCH 0473/2557] oss: Coalesce source files after outdev removal --- libavdevice/Makefile | 2 +- libavdevice/oss.c | 122 +++++++++++++++++++++++++++++++++-- libavdevice/oss.h | 45 ------------- libavdevice/oss_dec.c | 146 ------------------------------------------ 4 files changed, 117 insertions(+), 198 deletions(-) delete mode 100644 libavdevice/oss.h delete mode 100644 libavdevice/oss_dec.c diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 18228f590f583..c7c5a319eeb3c 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -16,7 +16,7 @@ OBJS-$(CONFIG_BKTR_INDEV) += bktr.o OBJS-$(CONFIG_DV1394_INDEV) += dv1394.o OBJS-$(CONFIG_FBDEV_INDEV) += fbdev.o OBJS-$(CONFIG_JACK_INDEV) += jack.o timefilter.o -OBJS-$(CONFIG_OSS_INDEV) += oss_dec.o oss.o +OBJS-$(CONFIG_OSS_INDEV) += oss.o OBJS-$(CONFIG_PULSE_INDEV) += pulse.o OBJS-$(CONFIG_SNDIO_INDEV) += sndio.o OBJS-$(CONFIG_V4L2_INDEV) += v4l2.o diff --git a/libavdevice/oss.c b/libavdevice/oss.c index e504438124f99..e2f0e87eac3b4 100644 --- a/libavdevice/oss.c +++ b/libavdevice/oss.c @@ -28,15 +28,30 @@ #include #include "libavutil/log.h" +#include "libavutil/opt.h" +#include "libavutil/time.h" #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" - -#include "oss.h" - -int ff_oss_audio_open(AVFormatContext *s1, int is_output, - const char *audio_device) +#include "libavformat/internal.h" + +#define OSS_AUDIO_BLOCK_SIZE 4096 + +typedef struct OSSAudioData { + AVClass *class; + int fd; + int sample_rate; + int channels; + int frame_size; /* in bytes ! */ + enum AVCodecID codec_id; + unsigned int flip_left : 1; + uint8_t buffer[OSS_AUDIO_BLOCK_SIZE]; + int buffer_ptr; +} OSSAudioData; + +static int oss_audio_open(AVFormatContext *s1, int is_output, + const char *audio_device) { OSSAudioData *s = s1->priv_data; int audio_fd; @@ -126,8 +141,103 @@ int ff_oss_audio_open(AVFormatContext *s1, int is_output, #undef CHECK_IOCTL_ERROR } -int ff_oss_audio_close(OSSAudioData *s) +static int audio_read_header(AVFormatContext *s1) { + OSSAudioData *s = s1->priv_data; + AVStream *st; + int ret; + + st = avformat_new_stream(s1, NULL); + if (!st) { + return AVERROR(ENOMEM); + } + + ret = oss_audio_open(s1, 0, s1->filename); + if (ret < 0) { + return AVERROR(EIO); + } + + /* take real parameters */ + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = s->codec_id; + st->codecpar->sample_rate = s->sample_rate; + st->codecpar->channels = s->channels; + + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ + return 0; +} + +static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) +{ + OSSAudioData *s = s1->priv_data; + int ret, bdelay; + int64_t cur_time; + struct audio_buf_info abufi; + + if ((ret=av_new_packet(pkt, s->frame_size)) < 0) + return ret; + + ret = read(s->fd, pkt->data, pkt->size); + if (ret <= 0){ + av_packet_unref(pkt); + pkt->size = 0; + if (ret<0) return AVERROR(errno); + else return AVERROR_EOF; + } + pkt->size = ret; + + /* compute pts of the start of the packet */ + cur_time = av_gettime(); + bdelay = ret; + if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) { + bdelay += abufi.bytes; + } + /* subtract time represented by the number of bytes in the audio fifo */ + cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels); + + /* convert to wanted units */ + pkt->pts = cur_time; + + if (s->flip_left && s->channels == 2) { + int i; + short *p = (short *) pkt->data; + + for (i = 0; i < ret; i += 4) { + *p = ~*p; + p += 2; + } + } + return 0; +} + +static int audio_read_close(AVFormatContext *s1) +{ + OSSAudioData *s = s1->priv_data; + close(s->fd); return 0; } + +static const AVOption options[] = { + { "sample_rate", "", offsetof(OSSAudioData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { "channels", "", offsetof(OSSAudioData, channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +static const AVClass oss_demuxer_class = { + .class_name = "OSS demuxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_oss_demuxer = { + .name = "oss", + .long_name = NULL_IF_CONFIG_SMALL("OSS (Open Sound System) capture"), + .priv_data_size = sizeof(OSSAudioData), + .read_header = audio_read_header, + .read_packet = audio_read_packet, + .read_close = audio_read_close, + .flags = AVFMT_NOFILE, + .priv_class = &oss_demuxer_class, +}; diff --git a/libavdevice/oss.h b/libavdevice/oss.h deleted file mode 100644 index 0fbe14b3ec1ab..0000000000000 --- a/libavdevice/oss.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVDEVICE_OSS_H -#define AVDEVICE_OSS_H - -#include "libavcodec/avcodec.h" - -#include "libavformat/avformat.h" - -#define OSS_AUDIO_BLOCK_SIZE 4096 - -typedef struct OSSAudioData { - AVClass *class; - int fd; - int sample_rate; - int channels; - int frame_size; /* in bytes ! */ - enum AVCodecID codec_id; - unsigned int flip_left : 1; - uint8_t buffer[OSS_AUDIO_BLOCK_SIZE]; - int buffer_ptr; -} OSSAudioData; - -int ff_oss_audio_open(AVFormatContext *s1, int is_output, - const char *audio_device); - -int ff_oss_audio_close(OSSAudioData *s); - -#endif /* AVDEVICE_OSS_H */ diff --git a/libavdevice/oss_dec.c b/libavdevice/oss_dec.c deleted file mode 100644 index 6f51a306621dd..0000000000000 --- a/libavdevice/oss_dec.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Linux audio play interface - * Copyright (c) 2000, 2001 Fabrice Bellard - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#include - -#if HAVE_SOUNDCARD_H -#include -#else -#include -#endif - -#include -#include -#include - -#include "libavutil/internal.h" -#include "libavutil/opt.h" -#include "libavutil/time.h" - -#include "libavcodec/avcodec.h" - -#include "libavformat/avformat.h" -#include "libavformat/internal.h" - -#include "oss.h" - -static int audio_read_header(AVFormatContext *s1) -{ - OSSAudioData *s = s1->priv_data; - AVStream *st; - int ret; - - st = avformat_new_stream(s1, NULL); - if (!st) { - return AVERROR(ENOMEM); - } - - ret = ff_oss_audio_open(s1, 0, s1->filename); - if (ret < 0) { - return AVERROR(EIO); - } - - /* take real parameters */ - st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->codec_id = s->codec_id; - st->codecpar->sample_rate = s->sample_rate; - st->codecpar->channels = s->channels; - - avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ - return 0; -} - -static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) -{ - OSSAudioData *s = s1->priv_data; - int ret, bdelay; - int64_t cur_time; - struct audio_buf_info abufi; - - if ((ret=av_new_packet(pkt, s->frame_size)) < 0) - return ret; - - ret = read(s->fd, pkt->data, pkt->size); - if (ret <= 0){ - av_packet_unref(pkt); - pkt->size = 0; - if (ret<0) return AVERROR(errno); - else return AVERROR_EOF; - } - pkt->size = ret; - - /* compute pts of the start of the packet */ - cur_time = av_gettime(); - bdelay = ret; - if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) { - bdelay += abufi.bytes; - } - /* subtract time represented by the number of bytes in the audio fifo */ - cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels); - - /* convert to wanted units */ - pkt->pts = cur_time; - - if (s->flip_left && s->channels == 2) { - int i; - short *p = (short *) pkt->data; - - for (i = 0; i < ret; i += 4) { - *p = ~*p; - p += 2; - } - } - return 0; -} - -static int audio_read_close(AVFormatContext *s1) -{ - OSSAudioData *s = s1->priv_data; - - ff_oss_audio_close(s); - return 0; -} - -static const AVOption options[] = { - { "sample_rate", "", offsetof(OSSAudioData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { "channels", "", offsetof(OSSAudioData, channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { NULL }, -}; - -static const AVClass oss_demuxer_class = { - .class_name = "OSS demuxer", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVInputFormat ff_oss_demuxer = { - .name = "oss", - .long_name = NULL_IF_CONFIG_SMALL("OSS (Open Sound System) capture"), - .priv_data_size = sizeof(OSSAudioData), - .read_header = audio_read_header, - .read_packet = audio_read_packet, - .read_close = audio_read_close, - .flags = AVFMT_NOFILE, - .priv_class = &oss_demuxer_class, -}; From d46cd2498614ae770f6c93e89f7665239b947e1c Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 27 Sep 2017 15:24:58 +0200 Subject: [PATCH 0474/2557] alsa: Coalesce source files after outdev removal --- libavdevice/Makefile | 2 +- libavdevice/alsa.c | 190 +++++++++++++++++++++++++++++++++++++++-- libavdevice/alsa.h | 94 -------------------- libavdevice/alsa_dec.c | 178 -------------------------------------- 4 files changed, 182 insertions(+), 282 deletions(-) delete mode 100644 libavdevice/alsa.h delete mode 100644 libavdevice/alsa_dec.c diff --git a/libavdevice/Makefile b/libavdevice/Makefile index c7c5a319eeb3c..1160088c32971 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -10,7 +10,7 @@ OBJS = alldevices.o \ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o # input devices -OBJS-$(CONFIG_ALSA_INDEV) += alsa_dec.o alsa.o +OBJS-$(CONFIG_ALSA_INDEV) += alsa.o OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation_dec.o OBJS-$(CONFIG_BKTR_INDEV) += bktr.o OBJS-$(CONFIG_DV1394_INDEV) += dv1394.o diff --git a/libavdevice/alsa.c b/libavdevice/alsa.c index 81c94049cb9fd..276a6c84cf259 100644 --- a/libavdevice/alsa.c +++ b/libavdevice/alsa.c @@ -1,5 +1,5 @@ /* - * ALSA input and output + * ALSA input * Copyright (c) 2007 Luca Abeni ( lucabe72 email it ) * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr ) * @@ -22,18 +22,39 @@ /** * @file - * ALSA input and output: common code + * ALSA input * @author Luca Abeni ( lucabe72 email it ) * @author Benoit Fouet ( benoit fouet free fr ) * @author Nicolas George ( nicolas george normalesup org ) */ #include -#include "libavformat/avformat.h" + #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" +#include "libavutil/opt.h" + +#include "libavformat/avformat.h" +#include "libavformat/internal.h" -#include "alsa.h" +/* XXX: we make the assumption that the soundcard accepts this format */ +/* XXX: find better solution with "preinit" method, needed also in + other formats */ +#define DEFAULT_CODEC_ID AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE) + +#define ALSA_BUFFER_SIZE_MAX 32768 + +typedef struct AlsaData { + AVClass *class; + snd_pcm_t *h; + int frame_size; ///< preferred size for reads and writes + int period_size; ///< bytes per sample * channels + int sample_rate; ///< sample rate set by user + int channels; ///< number of channels set by user + void (*reorder_func)(const void *, void *, int); + void *reorder_buf; + int reorder_buf_size; ///< in frames +} AlsaData; static av_cold snd_pcm_format_t codec_id_to_pcm_format(int codec_id) { @@ -183,9 +204,23 @@ static av_cold int find_reorder_func(AlsaData *s, int codec_id, uint64_t layout, return s->reorder_func ? 0 : AVERROR(ENOSYS); } -av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode, - unsigned int *sample_rate, - int channels, enum AVCodecID *codec_id) +/** + * Open an ALSA PCM. + * + * @param s media file handle + * @param mode either SND_PCM_STREAM_CAPTURE or SND_PCM_STREAM_PLAYBACK + * @param sample_rate in: requested sample rate; + * out: actually selected sample rate + * @param channels number of channels + * @param codec_id in: requested AVCodecID or AV_CODEC_ID_NONE; + * out: actually selected AVCodecID, changed only if + * AV_CODEC_ID_NONE was requested + * + * @return 0 if OK, AVERROR_xxx on error + */ +static av_cold int alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode, + unsigned int *sample_rate, + int channels, enum AVCodecID *codec_id) { AlsaData *s = ctx->priv_data; const char *audio_device; @@ -315,7 +350,14 @@ av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode, return AVERROR(EIO); } -av_cold int ff_alsa_close(AVFormatContext *s1) +/** + * Close the ALSA PCM. + * + * @param s1 media file handle + * + * @return 0 + */ +static av_cold int alsa_close(AVFormatContext *s1) { AlsaData *s = s1->priv_data; @@ -324,7 +366,15 @@ av_cold int ff_alsa_close(AVFormatContext *s1) return 0; } -int ff_alsa_xrun_recover(AVFormatContext *s1, int err) +/** + * Try to recover from ALSA buffer underrun. + * + * @param s1 media file handle + * @param err error code reported by the previous ALSA call + * + * @return 0 if OK, AVERROR_xxx on error + */ +static int alsa_xrun_recover(AVFormatContext *s1, int err) { AlsaData *s = s1->priv_data; snd_pcm_t *handle = s->h; @@ -344,3 +394,125 @@ int ff_alsa_xrun_recover(AVFormatContext *s1, int err) } return err; } + +static av_cold int audio_read_header(AVFormatContext *s1) +{ + AlsaData *s = s1->priv_data; + AVStream *st; + int ret; + enum AVCodecID codec_id; + snd_pcm_sw_params_t *sw_params; + + st = avformat_new_stream(s1, NULL); + if (!st) { + av_log(s1, AV_LOG_ERROR, "Cannot add stream\n"); + + return AVERROR(ENOMEM); + } + codec_id = s1->audio_codec_id; + + ret = alsa_open(s1, SND_PCM_STREAM_CAPTURE, &s->sample_rate, s->channels, + &codec_id); + if (ret < 0) { + return AVERROR(EIO); + } + + if (snd_pcm_type(s->h) != SND_PCM_TYPE_HW) + av_log(s1, AV_LOG_WARNING, + "capture with some ALSA plugins, especially dsnoop, " + "may hang.\n"); + + ret = snd_pcm_sw_params_malloc(&sw_params); + if (ret < 0) { + av_log(s1, AV_LOG_ERROR, "cannot allocate software parameters structure (%s)\n", + snd_strerror(ret)); + goto fail; + } + + snd_pcm_sw_params_current(s->h, sw_params); + snd_pcm_sw_params_set_tstamp_mode(s->h, sw_params, SND_PCM_TSTAMP_ENABLE); + + ret = snd_pcm_sw_params(s->h, sw_params); + snd_pcm_sw_params_free(sw_params); + if (ret < 0) { + av_log(s1, AV_LOG_ERROR, "cannot install ALSA software parameters (%s)\n", + snd_strerror(ret)); + goto fail; + } + + /* take real parameters */ + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = codec_id; + st->codecpar->sample_rate = s->sample_rate; + st->codecpar->channels = s->channels; + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ + + return 0; + +fail: + snd_pcm_close(s->h); + return AVERROR(EIO); +} + +static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) +{ + AlsaData *s = s1->priv_data; + AVStream *st = s1->streams[0]; + int res; + snd_htimestamp_t timestamp; + snd_pcm_uframes_t ts_delay; + + if (av_new_packet(pkt, s->period_size) < 0) { + return AVERROR(EIO); + } + + while ((res = snd_pcm_readi(s->h, pkt->data, pkt->size / s->frame_size)) < 0) { + if (res == -EAGAIN) { + av_packet_unref(pkt); + + return AVERROR(EAGAIN); + } + if (alsa_xrun_recover(s1, res) < 0) { + av_log(s1, AV_LOG_ERROR, "ALSA read error: %s\n", + snd_strerror(res)); + av_packet_unref(pkt); + + return AVERROR(EIO); + } + } + + snd_pcm_htimestamp(s->h, &ts_delay, ×tamp); + ts_delay += res; + pkt->pts = timestamp.tv_sec * 1000000LL + + (timestamp.tv_nsec * st->codecpar->sample_rate + - (int64_t)ts_delay * 1000000000LL + st->codecpar->sample_rate * 500LL) + / (st->codecpar->sample_rate * 1000LL); + + pkt->size = res * s->frame_size; + + return 0; +} + +static const AVOption options[] = { + { "sample_rate", "", offsetof(AlsaData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { "channels", "", offsetof(AlsaData, channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +static const AVClass alsa_demuxer_class = { + .class_name = "ALSA demuxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_alsa_demuxer = { + .name = "alsa", + .long_name = NULL_IF_CONFIG_SMALL("ALSA audio input"), + .priv_data_size = sizeof(AlsaData), + .read_header = audio_read_header, + .read_packet = audio_read_packet, + .read_close = alsa_close, + .flags = AVFMT_NOFILE, + .priv_class = &alsa_demuxer_class, +}; diff --git a/libavdevice/alsa.h b/libavdevice/alsa.h deleted file mode 100644 index 773cd2faf8ce9..0000000000000 --- a/libavdevice/alsa.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * ALSA input and output - * Copyright (c) 2007 Luca Abeni ( lucabe72 email it ) - * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr ) - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * ALSA input and output: definitions and structures - * @author Luca Abeni ( lucabe72 email it ) - * @author Benoit Fouet ( benoit fouet free fr ) - */ - -#ifndef AVDEVICE_ALSA_H -#define AVDEVICE_ALSA_H - -#include -#include "config.h" -#include "libavformat/avformat.h" -#include "libavutil/log.h" - -/* XXX: we make the assumption that the soundcard accepts this format */ -/* XXX: find better solution with "preinit" method, needed also in - other formats */ -#define DEFAULT_CODEC_ID AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE) - -#define ALSA_BUFFER_SIZE_MAX 32768 - -typedef struct AlsaData { - AVClass *class; - snd_pcm_t *h; - int frame_size; ///< preferred size for reads and writes - int period_size; ///< bytes per sample * channels - int sample_rate; ///< sample rate set by user - int channels; ///< number of channels set by user - void (*reorder_func)(const void *, void *, int); - void *reorder_buf; - int reorder_buf_size; ///< in frames -} AlsaData; - -/** - * Open an ALSA PCM. - * - * @param s media file handle - * @param mode either SND_PCM_STREAM_CAPTURE or SND_PCM_STREAM_PLAYBACK - * @param sample_rate in: requested sample rate; - * out: actually selected sample rate - * @param channels number of channels - * @param codec_id in: requested AVCodecID or AV_CODEC_ID_NONE; - * out: actually selected AVCodecID, changed only if - * AV_CODEC_ID_NONE was requested - * - * @return 0 if OK, AVERROR_xxx on error - */ -int ff_alsa_open(AVFormatContext *s, snd_pcm_stream_t mode, - unsigned int *sample_rate, - int channels, enum AVCodecID *codec_id); - -/** - * Close the ALSA PCM. - * - * @param s1 media file handle - * - * @return 0 - */ -int ff_alsa_close(AVFormatContext *s1); - -/** - * Try to recover from ALSA buffer underrun. - * - * @param s1 media file handle - * @param err error code reported by the previous ALSA call - * - * @return 0 if OK, AVERROR_xxx on error - */ -int ff_alsa_xrun_recover(AVFormatContext *s1, int err); - -#endif /* AVDEVICE_ALSA_H */ diff --git a/libavdevice/alsa_dec.c b/libavdevice/alsa_dec.c deleted file mode 100644 index 58bf1dd6a1659..0000000000000 --- a/libavdevice/alsa_dec.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * ALSA input and output - * Copyright (c) 2007 Luca Abeni ( lucabe72 email it ) - * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr ) - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * ALSA input and output: input - * @author Luca Abeni ( lucabe72 email it ) - * @author Benoit Fouet ( benoit fouet free fr ) - * @author Nicolas George ( nicolas george normalesup org ) - * - * This avdevice decoder allows to capture audio from an ALSA (Advanced - * Linux Sound Architecture) device. - * - * The filename parameter is the name of an ALSA PCM device capable of - * capture, for example "default" or "plughw:1"; see the ALSA documentation - * for naming conventions. The empty string is equivalent to "default". - * - * The capture period is set to the lower value available for the device, - * which gives a low latency suitable for real-time capture. - * - * The PTS are an Unix time in microsecond. - * - * Due to a bug in the ALSA library - * (https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4308), this - * decoder does not work with certain ALSA plugins, especially the dsnoop - * plugin. - */ - -#include - -#include "libavutil/internal.h" -#include "libavutil/opt.h" - -#include "libavformat/avformat.h" -#include "libavformat/internal.h" - -#include "alsa.h" - -static av_cold int audio_read_header(AVFormatContext *s1) -{ - AlsaData *s = s1->priv_data; - AVStream *st; - int ret; - enum AVCodecID codec_id; - snd_pcm_sw_params_t *sw_params; - - st = avformat_new_stream(s1, NULL); - if (!st) { - av_log(s1, AV_LOG_ERROR, "Cannot add stream\n"); - - return AVERROR(ENOMEM); - } - codec_id = s1->audio_codec_id; - - ret = ff_alsa_open(s1, SND_PCM_STREAM_CAPTURE, &s->sample_rate, s->channels, - &codec_id); - if (ret < 0) { - return AVERROR(EIO); - } - - if (snd_pcm_type(s->h) != SND_PCM_TYPE_HW) - av_log(s1, AV_LOG_WARNING, - "capture with some ALSA plugins, especially dsnoop, " - "may hang.\n"); - - ret = snd_pcm_sw_params_malloc(&sw_params); - if (ret < 0) { - av_log(s1, AV_LOG_ERROR, "cannot allocate software parameters structure (%s)\n", - snd_strerror(ret)); - goto fail; - } - - snd_pcm_sw_params_current(s->h, sw_params); - snd_pcm_sw_params_set_tstamp_mode(s->h, sw_params, SND_PCM_TSTAMP_ENABLE); - - ret = snd_pcm_sw_params(s->h, sw_params); - snd_pcm_sw_params_free(sw_params); - if (ret < 0) { - av_log(s1, AV_LOG_ERROR, "cannot install ALSA software parameters (%s)\n", - snd_strerror(ret)); - goto fail; - } - - /* take real parameters */ - st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->codec_id = codec_id; - st->codecpar->sample_rate = s->sample_rate; - st->codecpar->channels = s->channels; - avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ - - return 0; - -fail: - snd_pcm_close(s->h); - return AVERROR(EIO); -} - -static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) -{ - AlsaData *s = s1->priv_data; - AVStream *st = s1->streams[0]; - int res; - snd_htimestamp_t timestamp; - snd_pcm_uframes_t ts_delay; - - if (av_new_packet(pkt, s->period_size) < 0) { - return AVERROR(EIO); - } - - while ((res = snd_pcm_readi(s->h, pkt->data, pkt->size / s->frame_size)) < 0) { - if (res == -EAGAIN) { - av_packet_unref(pkt); - - return AVERROR(EAGAIN); - } - if (ff_alsa_xrun_recover(s1, res) < 0) { - av_log(s1, AV_LOG_ERROR, "ALSA read error: %s\n", - snd_strerror(res)); - av_packet_unref(pkt); - - return AVERROR(EIO); - } - } - - snd_pcm_htimestamp(s->h, &ts_delay, ×tamp); - ts_delay += res; - pkt->pts = timestamp.tv_sec * 1000000LL - + (timestamp.tv_nsec * st->codecpar->sample_rate - - (int64_t)ts_delay * 1000000000LL + st->codecpar->sample_rate * 500LL) - / (st->codecpar->sample_rate * 1000LL); - - pkt->size = res * s->frame_size; - - return 0; -} - -static const AVOption options[] = { - { "sample_rate", "", offsetof(AlsaData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { "channels", "", offsetof(AlsaData, channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { NULL }, -}; - -static const AVClass alsa_demuxer_class = { - .class_name = "ALSA demuxer", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVInputFormat ff_alsa_demuxer = { - .name = "alsa", - .long_name = NULL_IF_CONFIG_SMALL("ALSA audio input"), - .priv_data_size = sizeof(AlsaData), - .read_header = audio_read_header, - .read_packet = audio_read_packet, - .read_close = ff_alsa_close, - .flags = AVFMT_NOFILE, - .priv_class = &alsa_demuxer_class, -}; From 543f00c78e6dc9fbb1ad83bfd8d57b5127cb4bac Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 27 Sep 2017 15:28:33 +0200 Subject: [PATCH 0475/2557] avfoundation: Drop silly _dec suffix from filename --- libavdevice/Makefile | 2 +- libavdevice/{avfoundation_dec.m => avfoundation.m} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename libavdevice/{avfoundation_dec.m => avfoundation.m} (100%) diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 1160088c32971..420fb065d25ce 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -11,7 +11,7 @@ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o # input devices OBJS-$(CONFIG_ALSA_INDEV) += alsa.o -OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation_dec.o +OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation.o OBJS-$(CONFIG_BKTR_INDEV) += bktr.o OBJS-$(CONFIG_DV1394_INDEV) += dv1394.o OBJS-$(CONFIG_FBDEV_INDEV) += fbdev.o diff --git a/libavdevice/avfoundation_dec.m b/libavdevice/avfoundation.m similarity index 100% rename from libavdevice/avfoundation_dec.m rename to libavdevice/avfoundation.m From 762ab2de6ead68cfe6617d1960921878ddece9e1 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Tue, 26 Sep 2017 15:49:18 +0100 Subject: [PATCH 0476/2557] Remove dv1394 input device Support for this device has been removed in the Linux kernel since v2.6.37. dv1394 has been superseded by libiec61883 which is functionally equivalent. Signed-off-by: Josh de Kock Signed-off-by: Diego Biurrun --- configure | 3 - doc/general.texi | 1 - doc/indevs.texi | 4 - libavdevice/Makefile | 1 - libavdevice/alldevices.c | 1 - libavdevice/dv1394.c | 238 -------------------------- libavdevice/dv1394.h | 357 --------------------------------------- libavdevice/version.h | 2 +- 8 files changed, 1 insertion(+), 606 deletions(-) delete mode 100644 libavdevice/dv1394.c delete mode 100644 libavdevice/dv1394.h diff --git a/configure b/configure index 67354dc6a7194..e45b3201fc9a9 100755 --- a/configure +++ b/configure @@ -2433,8 +2433,6 @@ alsa_indev_deps="alsa" avfoundation_indev_deps="AVFoundation_AVFoundation_h objc_arc pthreads" avfoundation_indev_extralibs="-framework Foundation -framework AVFoundation -framework CoreVideo -framework CoreMedia" bktr_indev_deps_any="dev_bktr_ioctl_bt848_h machine_ioctl_bt848_h dev_video_bktr_ioctl_bt848_h dev_ic_bt8xx_h" -dv1394_indev_deps="dv1394" -dv1394_indev_select="dv_demuxer" fbdev_indev_deps="linux_fb_h" jack_indev_deps="libjack" jack_indev_deps_any="sem_timedwait dispatch_dispatch_h" @@ -4008,7 +4006,6 @@ case $target_os in add_cppflags -U__STRICT_ANSI__ ;; linux) - enable dv1394 enable section_data_rel_ro ;; irix*) diff --git a/doc/general.texi b/doc/general.texi index adf5b4eabfd04..6e39d5c1a0e87 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -1067,7 +1067,6 @@ performance on systems without hardware floating point support). @item Name @tab Input @tab Output @item ALSA @tab X @tab X @item BKTR @tab X @tab -@item DV1394 @tab X @tab @item Linux framebuffer @tab X @tab @item JACK @tab X @tab @item LIBCDIO @tab X diff --git a/doc/indevs.texi b/doc/indevs.texi index a08c7a5f6ba72..7acdd8f3cc3cc 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -55,10 +55,6 @@ For more information see: BSD video input device. -@section dv1394 - -Linux DV 1394 input device. - @section fbdev Linux framebuffer input device. diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 420fb065d25ce..8e533012d86b2 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -13,7 +13,6 @@ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o OBJS-$(CONFIG_ALSA_INDEV) += alsa.o OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation.o OBJS-$(CONFIG_BKTR_INDEV) += bktr.o -OBJS-$(CONFIG_DV1394_INDEV) += dv1394.o OBJS-$(CONFIG_FBDEV_INDEV) += fbdev.o OBJS-$(CONFIG_JACK_INDEV) += jack.o timefilter.o OBJS-$(CONFIG_OSS_INDEV) += oss.o diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index 47d7421a063d0..151e977b850f9 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -41,7 +41,6 @@ void avdevice_register_all(void) REGISTER_INDEV(ALSA, alsa); REGISTER_INDEV(AVFOUNDATION, avfoundation); REGISTER_INDEV(BKTR, bktr); - REGISTER_INDEV(DV1394, dv1394); REGISTER_INDEV(FBDEV, fbdev); REGISTER_INDEV(JACK, jack); REGISTER_INDEV(OSS, oss); diff --git a/libavdevice/dv1394.c b/libavdevice/dv1394.c deleted file mode 100644 index addf1ade67e98..0000000000000 --- a/libavdevice/dv1394.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Linux DV1394 interface - * Copyright (c) 2003 Max Krasnyansky - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" -#include -#include -#include -#include -#include -#include - -#include "libavutil/internal.h" -#include "libavutil/log.h" -#include "libavutil/opt.h" -#include "libavformat/avformat.h" -#include "libavformat/dv.h" -#include "dv1394.h" - -struct dv1394_data { - AVClass *class; - int fd; - int channel; - int format; - - uint8_t *ring; /* Ring buffer */ - int index; /* Current frame index */ - int avail; /* Number of frames available for reading */ - int done; /* Number of completed frames */ - - DVDemuxContext* dv_demux; /* Generic DV muxing/demuxing context */ -}; - -/* - * The trick here is to kludge around well known problem with kernel Ooopsing - * when you try to capture PAL on a device node configure for NTSC. That's - * why we have to configure the device node for PAL, and then read only NTSC - * amount of data. - */ -static int dv1394_reset(struct dv1394_data *dv) -{ - struct dv1394_init init; - - init.channel = dv->channel; - init.api_version = DV1394_API_VERSION; - init.n_frames = DV1394_RING_FRAMES; - init.format = DV1394_PAL; - - if (ioctl(dv->fd, DV1394_INIT, &init) < 0) - return -1; - - dv->avail = dv->done = 0; - return 0; -} - -static int dv1394_start(struct dv1394_data *dv) -{ - /* Tell DV1394 driver to enable receiver */ - if (ioctl(dv->fd, DV1394_START_RECEIVE, 0) < 0) { - av_log(NULL, AV_LOG_ERROR, "Failed to start receiver: %s\n", strerror(errno)); - return -1; - } - return 0; -} - -static int dv1394_read_header(AVFormatContext * context) -{ - struct dv1394_data *dv = context->priv_data; - - dv->dv_demux = avpriv_dv_init_demux(context); - if (!dv->dv_demux) - goto failed; - - /* Open and initialize DV1394 device */ - dv->fd = avpriv_open(context->filename, O_RDONLY); - if (dv->fd < 0) { - av_log(context, AV_LOG_ERROR, "Failed to open DV interface: %s\n", strerror(errno)); - goto failed; - } - - if (dv1394_reset(dv) < 0) { - av_log(context, AV_LOG_ERROR, "Failed to initialize DV interface: %s\n", strerror(errno)); - goto failed; - } - - dv->ring = mmap(NULL, DV1394_PAL_FRAME_SIZE * DV1394_RING_FRAMES, - PROT_READ, MAP_PRIVATE, dv->fd, 0); - if (dv->ring == MAP_FAILED) { - av_log(context, AV_LOG_ERROR, "Failed to mmap DV ring buffer: %s\n", strerror(errno)); - goto failed; - } - - if (dv1394_start(dv) < 0) - goto failed; - - return 0; - -failed: - close(dv->fd); - return AVERROR(EIO); -} - -static int dv1394_read_packet(AVFormatContext *context, AVPacket *pkt) -{ - struct dv1394_data *dv = context->priv_data; - int size; - - size = avpriv_dv_get_packet(dv->dv_demux, pkt); - if (size > 0) - return size; - - if (!dv->avail) { - struct dv1394_status s; - struct pollfd p; - - if (dv->done) { - /* Request more frames */ - if (ioctl(dv->fd, DV1394_RECEIVE_FRAMES, dv->done) < 0) { - /* This usually means that ring buffer overflowed. - * We have to reset :(. - */ - - av_log(context, AV_LOG_ERROR, "DV1394: Ring buffer overflow. Reseting ..\n"); - - dv1394_reset(dv); - dv1394_start(dv); - } - dv->done = 0; - } - - /* Wait until more frames are available */ -restart_poll: - p.fd = dv->fd; - p.events = POLLIN | POLLERR | POLLHUP; - if (poll(&p, 1, -1) < 0) { - if (errno == EAGAIN || errno == EINTR) - goto restart_poll; - av_log(context, AV_LOG_ERROR, "Poll failed: %s\n", strerror(errno)); - return AVERROR(EIO); - } - - if (ioctl(dv->fd, DV1394_GET_STATUS, &s) < 0) { - av_log(context, AV_LOG_ERROR, "Failed to get status: %s\n", strerror(errno)); - return AVERROR(EIO); - } - av_log(context, AV_LOG_TRACE, "DV1394: status\n" - "\tactive_frame\t%d\n" - "\tfirst_clear_frame\t%d\n" - "\tn_clear_frames\t%d\n" - "\tdropped_frames\t%d\n", - s.active_frame, s.first_clear_frame, - s.n_clear_frames, s.dropped_frames); - - dv->avail = s.n_clear_frames; - dv->index = s.first_clear_frame; - dv->done = 0; - - if (s.dropped_frames) { - av_log(context, AV_LOG_ERROR, "DV1394: Frame drop detected (%d). Reseting ..\n", - s.dropped_frames); - - dv1394_reset(dv); - dv1394_start(dv); - } - } - - av_log(context, AV_LOG_TRACE, "index %d, avail %d, done %d\n", dv->index, dv->avail, - dv->done); - - size = avpriv_dv_produce_packet(dv->dv_demux, pkt, - dv->ring + (dv->index * DV1394_PAL_FRAME_SIZE), - DV1394_PAL_FRAME_SIZE); - dv->index = (dv->index + 1) % DV1394_RING_FRAMES; - dv->done++; dv->avail--; - - return size; -} - -static int dv1394_close(AVFormatContext * context) -{ - struct dv1394_data *dv = context->priv_data; - - /* Shutdown DV1394 receiver */ - if (ioctl(dv->fd, DV1394_SHUTDOWN, 0) < 0) - av_log(context, AV_LOG_ERROR, "Failed to shutdown DV1394: %s\n", strerror(errno)); - - /* Unmap ring buffer */ - if (munmap(dv->ring, DV1394_NTSC_FRAME_SIZE * DV1394_RING_FRAMES) < 0) - av_log(context, AV_LOG_ERROR, "Failed to munmap DV1394 ring buffer: %s\n", strerror(errno)); - - close(dv->fd); - av_free(dv->dv_demux); - - return 0; -} - -static const AVOption options[] = { - { "standard", "", offsetof(struct dv1394_data, format), AV_OPT_TYPE_INT, {.i64 = DV1394_NTSC}, DV1394_NTSC, DV1394_PAL, AV_OPT_FLAG_DECODING_PARAM, "standard" }, - { "PAL", "", 0, AV_OPT_TYPE_CONST, {.i64 = DV1394_PAL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "standard" }, - { "NTSC", "", 0, AV_OPT_TYPE_CONST, {.i64 = DV1394_NTSC}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "standard" }, - { "channel", "", offsetof(struct dv1394_data, channel), AV_OPT_TYPE_INT, {.i64 = DV1394_DEFAULT_CHANNEL}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { NULL }, -}; - -static const AVClass dv1394_class = { - .class_name = "DV1394 indev", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVInputFormat ff_dv1394_demuxer = { - .name = "dv1394", - .long_name = NULL_IF_CONFIG_SMALL("DV1394 A/V grab"), - .priv_data_size = sizeof(struct dv1394_data), - .read_header = dv1394_read_header, - .read_packet = dv1394_read_packet, - .read_close = dv1394_close, - .flags = AVFMT_NOFILE, - .priv_class = &dv1394_class, -}; diff --git a/libavdevice/dv1394.h b/libavdevice/dv1394.h deleted file mode 100644 index 9710ff56ea9d1..0000000000000 --- a/libavdevice/dv1394.h +++ /dev/null @@ -1,357 +0,0 @@ -/* - * DV input/output over IEEE 1394 on OHCI chips - * Copyright (C)2001 Daniel Maas - * receive, proc_fs by Dan Dennedy - * - * based on: - * video1394.h - driver for OHCI 1394 boards - * Copyright (C)1999,2000 Sebastien Rougeaux - * Peter Schlaile - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVDEVICE_DV1394_H -#define AVDEVICE_DV1394_H - -#define DV1394_DEFAULT_CHANNEL 63 -#define DV1394_DEFAULT_CARD 0 -#define DV1394_RING_FRAMES 20 - -#define DV1394_WIDTH 720 -#define DV1394_NTSC_HEIGHT 480 -#define DV1394_PAL_HEIGHT 576 - -/* This is the public user-space interface. Try not to break it. */ - -#define DV1394_API_VERSION 0x20011127 - -/* ******************** - ** ** - ** DV1394 API ** - ** ** - ******************** - - There are two methods of operating the DV1394 DV output device. - - 1) - - The simplest is an interface based on write(): simply write - full DV frames of data to the device, and they will be transmitted - as quickly as possible. The FD may be set for non-blocking I/O, - in which case you can use select() or poll() to wait for output - buffer space. - - To set the DV output parameters (e.g. whether you want NTSC or PAL - video), use the DV1394_INIT ioctl, passing in the parameters you - want in a struct dv1394_init. - - Example 1: - To play a raw .DV file: cat foo.DV > /dev/dv1394 - (cat will use write() internally) - - Example 2: - static struct dv1394_init init = { - 0x63, (broadcast channel) - 4, (four-frame ringbuffer) - DV1394_NTSC, (send NTSC video) - 0, 0 (default empty packet rate) - } - - ioctl(fd, DV1394_INIT, &init); - - while(1) { - read( , buf, DV1394_NTSC_FRAME_SIZE ); - write( , buf, DV1394_NTSC_FRAME_SIZE ); - } - - 2) - - For more control over buffering, and to avoid unnecessary copies - of the DV data, you can use the more sophisticated the mmap() interface. - First, call the DV1394_INIT ioctl to specify your parameters, - including the number of frames in the ringbuffer. Then, calling mmap() - on the dv1394 device will give you direct access to the ringbuffer - from which the DV card reads your frame data. - - The ringbuffer is simply one large, contiguous region of memory - containing two or more frames of packed DV data. Each frame of DV data - is 120000 bytes (NTSC) or 144000 bytes (PAL). - - Fill one or more frames in the ringbuffer, then use the DV1394_SUBMIT_FRAMES - ioctl to begin I/O. You can use either the DV1394_WAIT_FRAMES ioctl - or select()/poll() to wait until the frames are transmitted. Next, you'll - need to call the DV1394_GET_STATUS ioctl to determine which ringbuffer - frames are clear (ready to be filled with new DV data). Finally, use - DV1394_SUBMIT_FRAMES again to send the new data to the DV output. - - - Example: here is what a four-frame ringbuffer might look like - during DV transmission: - - - frame 0 frame 1 frame 2 frame 3 - - *--------------------------------------* - | CLEAR | DV data | DV data | CLEAR | - *--------------------------------------* - - - transmission goes in this direction --->>> - - - The DV hardware is currently transmitting the data in frame 1. - Once frame 1 is finished, it will automatically transmit frame 2. - (if frame 2 finishes before frame 3 is submitted, the device - will continue to transmit frame 2, and will increase the dropped_frames - counter each time it repeats the transmission). - - - If you called DV1394_GET_STATUS at this instant, you would - receive the following values: - - n_frames = 4 - active_frame = 1 - first_clear_frame = 3 - n_clear_frames = 2 - - At this point, you should write new DV data into frame 3 and optionally - frame 0. Then call DV1394_SUBMIT_FRAMES to inform the device that - it may transmit the new frames. - - ERROR HANDLING - - An error (buffer underflow/overflow or a break in the DV stream due - to a 1394 bus reset) can be detected by checking the dropped_frames - field of struct dv1394_status (obtained through the - DV1394_GET_STATUS ioctl). - - The best way to recover from such an error is to re-initialize - dv1394, either by using the DV1394_INIT ioctl call, or closing the - file descriptor and opening it again. (note that you must unmap all - ringbuffer mappings when closing the file descriptor, or else - dv1394 will still be considered 'in use'). - - MAIN LOOP - - For maximum efficiency and robustness against bus errors, you are - advised to model the main loop of your application after the - following pseudo-code example: - - (checks of system call return values omitted for brevity; always - check return values in your code!) - - while( frames left ) { - - struct pollfd *pfd = ...; - - pfd->fd = dv1394_fd; - pfd->revents = 0; - pfd->events = POLLOUT | POLLIN; (OUT for transmit, IN for receive) - - (add other sources of I/O here) - - poll(pfd, 1, -1); (or select(); add a timeout if you want) - - if(pfd->revents) { - struct dv1394_status status; - - ioctl(dv1394_fd, DV1394_GET_STATUS, &status); - - if(status.dropped_frames > 0) { - reset_dv1394(); - } else { - int i; - for (i = 0; i < status.n_clear_frames; i++) { - copy_DV_frame(); - } - } - } - } - - where copy_DV_frame() reads or writes on the dv1394 file descriptor - (read/write mode) or copies data to/from the mmap ringbuffer and - then calls ioctl(DV1394_SUBMIT_FRAMES) to notify dv1394 that new - frames are available (mmap mode). - - reset_dv1394() is called in the event of a buffer - underflow/overflow or a halt in the DV stream (e.g. due to a 1394 - bus reset). To guarantee recovery from the error, this function - should close the dv1394 file descriptor (and munmap() all - ringbuffer mappings, if you are using them), then re-open the - dv1394 device (and re-map the ringbuffer). - -*/ - - -/* maximum number of frames in the ringbuffer */ -#define DV1394_MAX_FRAMES 32 - -/* number of *full* isochronous packets per DV frame */ -#define DV1394_NTSC_PACKETS_PER_FRAME 250 -#define DV1394_PAL_PACKETS_PER_FRAME 300 - -/* size of one frame's worth of DV data, in bytes */ -#define DV1394_NTSC_FRAME_SIZE (480 * DV1394_NTSC_PACKETS_PER_FRAME) -#define DV1394_PAL_FRAME_SIZE (480 * DV1394_PAL_PACKETS_PER_FRAME) - - -/* ioctl() commands */ - -enum { - /* I don't like using 0 as a valid ioctl() */ - DV1394_INVALID = 0, - - - /* get the driver ready to transmit video. - pass a struct dv1394_init* as the parameter (see below), - or NULL to get default parameters */ - DV1394_INIT, - - - /* stop transmitting video and free the ringbuffer */ - DV1394_SHUTDOWN, - - - /* submit N new frames to be transmitted, where - the index of the first new frame is first_clear_buffer, - and the index of the last new frame is - (first_clear_buffer + N) % n_frames */ - DV1394_SUBMIT_FRAMES, - - - /* block until N buffers are clear (pass N as the parameter) - Because we re-transmit the last frame on underrun, there - will at most be n_frames - 1 clear frames at any time */ - DV1394_WAIT_FRAMES, - - /* capture new frames that have been received, where - the index of the first new frame is first_clear_buffer, - and the index of the last new frame is - (first_clear_buffer + N) % n_frames */ - DV1394_RECEIVE_FRAMES, - - - DV1394_START_RECEIVE, - - - /* pass a struct dv1394_status* as the parameter (see below) */ - DV1394_GET_STATUS, -}; - - - -enum pal_or_ntsc { - DV1394_NTSC = 0, - DV1394_PAL -}; - - - - -/* this is the argument to DV1394_INIT */ -struct dv1394_init { - /* DV1394_API_VERSION */ - unsigned int api_version; - - /* isochronous transmission channel to use */ - unsigned int channel; - - /* number of frames in the ringbuffer. Must be at least 2 - and at most DV1394_MAX_FRAMES. */ - unsigned int n_frames; - - /* send/receive PAL or NTSC video format */ - enum pal_or_ntsc format; - - /* the following are used only for transmission */ - - /* set these to zero unless you want a - non-default empty packet rate (see below) */ - unsigned long cip_n; - unsigned long cip_d; - - /* set this to zero unless you want a - non-default SYT cycle offset (default = 3 cycles) */ - unsigned int syt_offset; -}; - -/* NOTE: you may only allocate the DV frame ringbuffer once each time - you open the dv1394 device. DV1394_INIT will fail if you call it a - second time with different 'n_frames' or 'format' arguments (which - would imply a different size for the ringbuffer). If you need a - different buffer size, simply close and re-open the device, then - initialize it with your new settings. */ - -/* Q: What are cip_n and cip_d? */ - -/* - A: DV video streams do not utilize 100% of the potential bandwidth offered - by IEEE 1394 (FireWire). To achieve the correct rate of data transmission, - DV devices must periodically insert empty packets into the 1394 data stream. - Typically there is one empty packet per 14-16 data-carrying packets. - - Some DV devices will accept a wide range of empty packet rates, while others - require a precise rate. If the dv1394 driver produces empty packets at - a rate that your device does not accept, you may see ugly patterns on the - DV output, or even no output at all. - - The default empty packet insertion rate seems to work for many people; if - your DV output is stable, you can simply ignore this discussion. However, - we have exposed the empty packet rate as a parameter to support devices that - do not work with the default rate. - - The decision to insert an empty packet is made with a numerator/denominator - algorithm. Empty packets are produced at an average rate of CIP_N / CIP_D. - You can alter the empty packet rate by passing non-zero values for cip_n - and cip_d to the INIT ioctl. - - */ - - - -struct dv1394_status { - /* this embedded init struct returns the current dv1394 - parameters in use */ - struct dv1394_init init; - - /* the ringbuffer frame that is currently being - displayed. (-1 if the device is not transmitting anything) */ - int active_frame; - - /* index of the first buffer (ahead of active_frame) that - is ready to be filled with data */ - unsigned int first_clear_frame; - - /* how many buffers, including first_clear_buffer, are - ready to be filled with data */ - unsigned int n_clear_frames; - - /* how many times the DV stream has underflowed, overflowed, - or otherwise encountered an error, since the previous call - to DV1394_GET_STATUS */ - unsigned int dropped_frames; - - /* N.B. The dropped_frames counter is only a lower bound on the actual - number of dropped frames, with the special case that if dropped_frames - is zero, then it is guaranteed that NO frames have been dropped - since the last call to DV1394_GET_STATUS. - */ -}; - - -#endif /* AVDEVICE_DV1394_H */ diff --git a/libavdevice/version.h b/libavdevice/version.h index e09a23cf676cc..3427d206cd51f 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -29,7 +29,7 @@ #define LIBAVDEVICE_VERSION_MAJOR 57 #define LIBAVDEVICE_VERSION_MINOR 0 -#define LIBAVDEVICE_VERSION_MICRO 1 +#define LIBAVDEVICE_VERSION_MICRO 2 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ LIBAVDEVICE_VERSION_MINOR, \ From 854c4e974db9addffdda6441367f969b42683123 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 13 Oct 2017 15:16:55 -0300 Subject: [PATCH 0477/2557] configure: add a -lstdc++ flag to the some external library checks Two of them are missing it in their pkg-config file, so adding it here is a workaround until said pkg-config files are fixed. Debugged with the help of Reino Wijnsma. Signed-off-by: James Almer --- configure | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 64fd0882089f3..c1ba64e08652d 100755 --- a/configure +++ b/configure @@ -6030,7 +6030,7 @@ enabled libopenjpeg && { { check_lib libopenjpeg openjpeg-2.3/openjpeg.h o { check_lib libopenjpeg openjpeg-1.5/openjpeg.h opj_version -lopenjpeg -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } || { check_lib libopenjpeg openjpeg.h opj_version -lopenjpeg -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } || die "ERROR: libopenjpeg not found"; } -enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create +enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create -lstdc++ && append libopenmpt_extralibs "-lstdc++" enabled libopus && { enabled libopus_decoder && { require_pkg_config libopus opus opus_multistream.h opus_multistream_decoder_create @@ -6042,11 +6042,11 @@ enabled libopus && { enabled libpulse && require_pkg_config libpulse libpulse pulse/pulseaudio.h pa_context_new enabled librsvg && require_pkg_config librsvg librsvg-2.0 librsvg-2.0/librsvg/rsvg.h rsvg_handle_render_cairo enabled librtmp && require_pkg_config librtmp librtmp librtmp/rtmp.h RTMP_Socket -enabled librubberband && require_pkg_config librubberband "rubberband >= 1.8.1" rubberband/rubberband-c.h rubberband_new +enabled librubberband && require_pkg_config librubberband "rubberband >= 1.8.1" rubberband/rubberband-c.h rubberband_new -lstdc++ && append librubberband_extralibs "-lstdc++" enabled libshine && require_pkg_config libshine shine shine/layer3.h shine_encode_buffer enabled libsmbclient && { use_pkg_config libsmbclient smbclient libsmbclient.h smbc_init || require libsmbclient libsmbclient.h smbc_init -lsmbclient; } -enabled libsnappy && require libsnappy snappy-c.h snappy_compress -lsnappy +enabled libsnappy && require libsnappy snappy-c.h snappy_compress -lsnappy -lstdc++ enabled libsoxr && require libsoxr soxr.h soxr_create -lsoxr enabled libssh && require_pkg_config libssh libssh libssh/sftp.h sftp_init enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init -lspeex From fa5e71a815ef559f8d2c63166e0f99ef1ab0b874 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 13 Oct 2017 19:50:37 -0300 Subject: [PATCH 0478/2557] configure: add missing pthreads extralib to the libilbc check Debugged with the help of Reino Wijnsma. Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index c1ba64e08652d..1bb61112d4306 100755 --- a/configure +++ b/configure @@ -5997,7 +5997,7 @@ enabled libgme && { use_pkg_config libgme libgme gme/gme.h gme_new_em enabled libgsm && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do check_lib libgsm "${gsm_hdr}" gsm_create -lgsm && break; done || die "ERROR: libgsm not found"; } -enabled libilbc && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -lilbc +enabled libilbc && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -lilbc $pthreads_extralibs enabled libkvazaar && require_pkg_config libkvazaar "kvazaar >= 0.8.1" kvazaar.h kvz_api_get # While it may appear that require is being used as a pkg-config # fallback for libmfx, it is actually being used to detect a different From 458783315b8fb84e0a06346184b3cf62314c9e2e Mon Sep 17 00:00:00 2001 From: Reino Wijnsma Date: Fri, 13 Oct 2017 19:52:27 -0300 Subject: [PATCH 0479/2557] configure: switch the libzvbi check to pkg-config The library has several dependencies that vary between systems. Their pkg-config properly lists them all. Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 1bb61112d4306..15f7e379d4099 100755 --- a/configure +++ b/configure @@ -6102,7 +6102,7 @@ enabled libxavs && require libxavs "stdint.h xavs.h" xavs_encoder_enco enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore enabled libzimg && require_pkg_config libzimg "zimg >= 2.3.0" zimg.h zimg_get_api_version enabled libzmq && require_pkg_config libzmq libzmq zmq.h zmq_ctx_new -enabled libzvbi && require libzvbi libzvbi.h vbi_decoder_new -lzvbi && +enabled libzvbi && require_pkg_config libzvbi zvbi-0.2 libzvbi.h vbi_decoder_new && { check_cpp_condition libzvbi.h "VBI_VERSION_MAJOR > 0 || VBI_VERSION_MINOR > 2 || VBI_VERSION_MINOR == 2 && VBI_VERSION_MICRO >= 28" || enabled gpl || die "ERROR: libzvbi requires version 0.2.28 or --enable-gpl."; } enabled libxml2 && require_pkg_config libxml2 libxml-2.0 libxml2/libxml/xmlversion.h xmlCheckVersion From ad56e8057d8af0201ed0cb65acc12e5889d4afcc Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 13 Oct 2017 12:34:34 -0300 Subject: [PATCH 0480/2557] configure: force erroring out in check_disable_warning() if an option doesn't exists Should prevent some options from being added to cflags when they don't exist and the compiler only warns about it. Reviewd-by: Michael Niedermayer Signed-off-by: James Almer --- configure | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 15f7e379d4099..22026ef83211f 100755 --- a/configure +++ b/configure @@ -6370,9 +6370,14 @@ fi check_disable_warning(){ warning_flag=-W${1#-Wno-} - test_cflags $warning_flag && add_cflags $1 + test_cflags $unknown_warning_flags $warning_flag && add_cflags $1 } +test_cflags -Werror=unused-command-line-argument && + append unknown_warning_flags "-Werror=unused-command-line-argument" +test_cflags -Werror=unknown-warning-option && + append unknown_warning_flags "-Werror=unknown-warning-option" + check_disable_warning -Wno-parentheses check_disable_warning -Wno-switch check_disable_warning -Wno-format-zero-length From 077011b5af2b3150efc52a9b58f5ef9bb0235087 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 13 Oct 2017 23:22:13 +0000 Subject: [PATCH 0481/2557] qsv: Expose idr_interval for hevc as well --- libavcodec/qsvenc_hevc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index efed4d98f4631..fb65d58c32cac 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -220,6 +220,7 @@ static av_cold int qsv_enc_close(AVCodecContext *avctx) static const AVOption options[] = { QSV_COMMON_OPTS + { "idr_interval", "Distance (in I-frames) between IDR frames", OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_DEFAULT }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VE, "load_plugin" }, { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VE, "load_plugin" }, { "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VE, "load_plugin" }, From 9c85329cd02e9284892bf263ce6133b2fc479792 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 13 Oct 2017 03:06:53 +0200 Subject: [PATCH 0482/2557] avcodec/pafvideo: Check for bitstream end in decode_0() Fixes: Timeout Fixes: 3529/clusterfuzz-testcase-5057068371279872 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/pafvideo.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/pafvideo.c b/libavcodec/pafvideo.c index 91bfe16376be5..6980ae1b352be 100644 --- a/libavcodec/pafvideo.c +++ b/libavcodec/pafvideo.c @@ -181,6 +181,8 @@ static int decode_0(PAFVideoDecContext *c, uint8_t *pkt, uint8_t code) dend = c->frame[page] + c->frame_size; offset = (x & 0x7F) * 2; j = bytestream2_get_le16(&c->gb) + offset; + if (bytestream2_get_bytes_left(&c->gb) < (j - offset) * 16) + return AVERROR_INVALIDDATA; do { offset++; if (dst + 3 * c->width + 4 > dend) @@ -198,7 +200,8 @@ static int decode_0(PAFVideoDecContext *c, uint8_t *pkt, uint8_t code) do { set_src_position(c, &src, &send); if ((src + 3 * c->width + 4 > send) || - (dst + 3 * c->width + 4 > dend)) + (dst + 3 * c->width + 4 > dend) || + bytestream2_get_bytes_left(&c->gb) < 4) return AVERROR_INVALIDDATA; copy_block4(dst, src, c->width, c->width, 4); i++; From 393d6fc7395611a38792e3c271b2be42ac45e672 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 13 Oct 2017 03:06:54 +0200 Subject: [PATCH 0483/2557] avcodec/snowdec: Check mv_scale Fixes: runtime error: signed integer overflow: 2 * -1094995530 cannot be represented in type 'int' Fixes: 3512/clusterfuzz-testcase-minimized-4812747210489856 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/snowdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/snowdec.c b/libavcodec/snowdec.c index b74c468ce32cf..13668c2105ee5 100644 --- a/libavcodec/snowdec.c +++ b/libavcodec/snowdec.c @@ -394,9 +394,10 @@ static int decode_header(SnowContext *s){ s->mv_scale += get_symbol(&s->c, s->header_state, 1); s->qbias += get_symbol(&s->c, s->header_state, 1); s->block_max_depth+= get_symbol(&s->c, s->header_state, 1); - if(s->block_max_depth > 1 || s->block_max_depth < 0){ + if(s->block_max_depth > 1 || s->block_max_depth < 0 || s->mv_scale > 256U){ av_log(s->avctx, AV_LOG_ERROR, "block_max_depth= %d is too large\n", s->block_max_depth); s->block_max_depth= 0; + s->mv_scale = 0; return AVERROR_INVALIDDATA; } if (FFABS(s->qbias) > 127) { From cd2f69cdd63d3ca5c2388d9ce6737b3e46bb19b2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 1 Oct 2017 18:10:35 +0200 Subject: [PATCH 0484/2557] avcodec/dvbsubdec: Factor a few expressions out of compute_default_clut() 32% faster loop Signed-off-by: Michael Niedermayer --- libavcodec/dvbsubdec.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c index b683109643cf9..ef581a9a3f81b 100644 --- a/libavcodec/dvbsubdec.c +++ b/libavcodec/dvbsubdec.c @@ -653,8 +653,8 @@ static void compute_default_clut(AVSubtitleRect *rect, int w, int h) uint8_t list_inv[256]; int counttab[256] = {0}; int count, i, x, y; - -#define V(x,y) rect->data[0][(x) + (y)*rect->linesize[0]] + ptrdiff_t stride = rect->linesize[0]; +#define V(x,y) rect->data[0][(x) + (y)*stride] for (y = 0; ydata[0][(x) + (y)*rect->linesize[0]] ] +#define L(x,y) list[d[(x) + (y)*stride]] for (i = 0; i<256; i++) { int scoretab[256] = {0}; @@ -673,12 +673,13 @@ static void compute_default_clut(AVSubtitleRect *rect, int w, int h) int bestv = 0; for (y = 0; ydata[0][x + y*rect->linesize[0]]; + uint8_t *d = &rect->data[0][x + y*stride]; + int v = *d; int l_m = list[v]; - int l_l = x ? L(x-1, y) : 1; - int l_r = x+1 Date: Sun, 1 Oct 2017 18:10:36 +0200 Subject: [PATCH 0485/2557] avcodec/dvbsubdec: Split best score computation out of loop in compute_default_clut() 3% faster Signed-off-by: Michael Niedermayer --- libavcodec/dvbsubdec.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c index ef581a9a3f81b..85a59f3ced0d5 100644 --- a/libavcodec/dvbsubdec.c +++ b/libavcodec/dvbsubdec.c @@ -680,14 +680,17 @@ static void compute_default_clut(AVSubtitleRect *rect, int w, int h) int l_r = x+1 bestscore) { bestscore = score; - bestv = v; + bestv = x; } } } From 06558100727420f33186e8656936a9373fa647ee Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 14 Oct 2017 21:20:27 -0300 Subject: [PATCH 0486/2557] configure: add pkg-config checks for libcdio/cdparanoia Should be more complete than the now fallback checks. Signed-off-by: James Almer --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index 22026ef83211f..b9a3a9bc1ff42 100755 --- a/configure +++ b/configure @@ -6262,6 +6262,8 @@ enabled jack && check_lib jack jack/jack.h jack_client_open -ljack && enabled sndio && check_lib sndio sndio.h sio_open -lsndio if enabled libcdio; then + use_pkg_config libcdio libcdio_paranoia "cdio/cdda.h cdio/paranoia.h" cdio_cddap_open || + use_pkg_config libcdio libcdio_paranoia "cdio/paranoia/cdda.h cdio/paranoia/paranoia.h" cdio_cddap_open || check_lib libcdio "cdio/cdda.h cdio/paranoia.h" cdio_cddap_open -lcdio_paranoia -lcdio_cdda -lcdio || check_lib libcdio "cdio/paranoia/cdda.h cdio/paranoia/paranoia.h" cdio_cddap_open -lcdio_paranoia -lcdio_cdda -lcdio || die "ERROR: No usable libcdio/cdparanoia found" From d4d4629dfe727d4c890fc7a19eb7e22eb155fce8 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Thu, 28 Sep 2017 21:36:58 +0200 Subject: [PATCH 0487/2557] libavcodec/texturedsp : add rgtc1u_alpha decoding func this func decode an rgtc1 texture and overwrite only the alpha channel of the dest RGBA picture Signed-off-by: Tom Butterworth --- libavcodec/texturedsp.c | 41 ++++++++++++++++++++++++++++++++--------- libavcodec/texturedsp.h | 1 + 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/libavcodec/texturedsp.c b/libavcodec/texturedsp.c index 90b1eb4f115d1..787aa118d10f7 100644 --- a/libavcodec/texturedsp.c +++ b/libavcodec/texturedsp.c @@ -413,7 +413,7 @@ static int dxt5ys_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) static inline void rgtc_block_internal(uint8_t *dst, ptrdiff_t stride, const uint8_t *block, - const int *color_tab) + const int *color_tab, int alpha) { uint8_t indices[16]; int x, y; @@ -429,14 +429,20 @@ static inline void rgtc_block_internal(uint8_t *dst, ptrdiff_t stride, int i = indices[x + y * 4]; /* Interval expansion from [-1 1] or [0 1] to [0 255]. */ int c = color_tab[i]; - uint32_t pixel = RGBA(c, c, c, 255U); - AV_WL32(dst + x * 4 + y * stride, pixel); + + if (alpha){ + dst [x * 4 + y * stride + 3] = (uint8_t)c; + } + else{ + uint32_t pixel = RGBA(c, c, c, 255U); + AV_WL32(dst + x * 4 + y * stride, pixel); + } } } } static inline void rgtc1_block_internal(uint8_t *dst, ptrdiff_t stride, - const uint8_t *block, int sign) + const uint8_t *block, int sign, int alpha) { int color_table[8]; int r0, r1; @@ -472,7 +478,7 @@ static inline void rgtc1_block_internal(uint8_t *dst, ptrdiff_t stride, color_table[7] = 255; /* max range */ // bit code 111 } - rgtc_block_internal(dst, stride, block, color_table); + rgtc_block_internal(dst, stride, block, color_table, alpha); } /** @@ -486,7 +492,7 @@ static inline void rgtc1_block_internal(uint8_t *dst, ptrdiff_t stride, */ static int rgtc1s_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) { - rgtc1_block_internal(dst, stride, block, 1); + rgtc1_block_internal(dst, stride, block, 1, 0); return 8; } @@ -502,7 +508,23 @@ static int rgtc1s_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) */ static int rgtc1u_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) { - rgtc1_block_internal(dst, stride, block, 0); + rgtc1_block_internal(dst, stride, block, 0, 0); + + return 8; +} + +/** + * Decompress one block of a RGRC1 texture with unsigned components + * and overwrite the alpha component in 'dst' (RGBA data). + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int rgtc1u_alpha_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + rgtc1_block_internal(dst, stride, block, 0, 1); return 8; } @@ -516,8 +538,8 @@ static inline void rgtc2_block_internal(uint8_t *dst, ptrdiff_t stride, int x, y; /* Decompress the two channels separately and interleave them afterwards. */ - rgtc1_block_internal(c0, 16, block, sign); - rgtc1_block_internal(c1, 16, block + 8, sign); + rgtc1_block_internal(c0, 16, block, sign, 0); + rgtc1_block_internal(c1, 16, block + 8, sign, 0); /* B is rebuilt exactly like a normal map. */ for (y = 0; y < 4; y++) { @@ -608,6 +630,7 @@ av_cold void ff_texturedsp_init(TextureDSPContext *c) c->dxt5ys_block = dxt5ys_block; c->rgtc1s_block = rgtc1s_block; c->rgtc1u_block = rgtc1u_block; + c->rgtc1u_alpha_block = rgtc1u_alpha_block; c->rgtc2s_block = rgtc2s_block; c->rgtc2u_block = rgtc2u_block; c->dxn3dc_block = dxn3dc_block; diff --git a/libavcodec/texturedsp.h b/libavcodec/texturedsp.h index 26f3b6473fc1e..04b31525d9e4b 100644 --- a/libavcodec/texturedsp.h +++ b/libavcodec/texturedsp.h @@ -53,6 +53,7 @@ typedef struct TextureDSPContext { int (*dxt5ys_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); int (*rgtc1s_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); int (*rgtc1u_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*rgtc1u_alpha_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); int (*rgtc2s_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); int (*rgtc2u_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); int (*dxn3dc_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); From 50a20de6b9edd1d893fe0ea652ccf796dd9850fb Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Thu, 28 Sep 2017 21:37:46 +0200 Subject: [PATCH 0488/2557] libavcodec/texturedspenc : add rgtc1_u_alpha encoding func this func encode the alpha channel of the rgba input to an rgtc1u block Signed-off-by: Tom Butterworth --- libavcodec/texturedspenc.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libavcodec/texturedspenc.c b/libavcodec/texturedspenc.c index 8b2863033b6a5..ae2e95e23f7a9 100644 --- a/libavcodec/texturedspenc.c +++ b/libavcodec/texturedspenc.c @@ -647,9 +647,26 @@ static int dxt5ys_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) return 16; } +/** + * Compress one block of RGBA pixels in a RGTC1U texture and store the + * resulting bytes in 'dst'. Use the alpha channel of the input image. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to compress. + * @return how much texture data has been written. + */ +static int rgtc1u_alpha_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + compress_alpha(dst, stride, block); + + return 8; +} + av_cold void ff_texturedspenc_init(TextureDSPContext *c) { c->dxt1_block = dxt1_block; c->dxt5_block = dxt5_block; c->dxt5ys_block = dxt5ys_block; + c->rgtc1u_alpha_block = rgtc1u_alpha_block; } From 92500c7bc53ba0d585db666aef65152468e80c9c Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Thu, 28 Sep 2017 21:45:31 +0200 Subject: [PATCH 0489/2557] libavcodec/texturedsp : indent after add rgtc1u_alpha func Signed-off-by: Tom Butterworth --- libavcodec/texturedsp.c | 26 +++++++++++++------------- libavcodec/texturedsp.h | 26 +++++++++++++------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/libavcodec/texturedsp.c b/libavcodec/texturedsp.c index 787aa118d10f7..6fc8e560ecec9 100644 --- a/libavcodec/texturedsp.c +++ b/libavcodec/texturedsp.c @@ -620,18 +620,18 @@ static int dxn3dc_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) av_cold void ff_texturedsp_init(TextureDSPContext *c) { - c->dxt1_block = dxt1_block; - c->dxt1a_block = dxt1a_block; - c->dxt2_block = dxt2_block; - c->dxt3_block = dxt3_block; - c->dxt4_block = dxt4_block; - c->dxt5_block = dxt5_block; - c->dxt5y_block = dxt5y_block; - c->dxt5ys_block = dxt5ys_block; - c->rgtc1s_block = rgtc1s_block; - c->rgtc1u_block = rgtc1u_block; + c->dxt1_block = dxt1_block; + c->dxt1a_block = dxt1a_block; + c->dxt2_block = dxt2_block; + c->dxt3_block = dxt3_block; + c->dxt4_block = dxt4_block; + c->dxt5_block = dxt5_block; + c->dxt5y_block = dxt5y_block; + c->dxt5ys_block = dxt5ys_block; + c->rgtc1s_block = rgtc1s_block; + c->rgtc1u_block = rgtc1u_block; c->rgtc1u_alpha_block = rgtc1u_alpha_block; - c->rgtc2s_block = rgtc2s_block; - c->rgtc2u_block = rgtc2u_block; - c->dxn3dc_block = dxn3dc_block; + c->rgtc2s_block = rgtc2s_block; + c->rgtc2u_block = rgtc2u_block; + c->dxn3dc_block = dxn3dc_block; } diff --git a/libavcodec/texturedsp.h b/libavcodec/texturedsp.h index 04b31525d9e4b..9953cf589d799 100644 --- a/libavcodec/texturedsp.h +++ b/libavcodec/texturedsp.h @@ -43,20 +43,20 @@ #define TEXTURE_BLOCK_H 4 typedef struct TextureDSPContext { - int (*dxt1_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); - int (*dxt1a_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); - int (*dxt2_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); - int (*dxt3_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); - int (*dxt4_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); - int (*dxt5_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); - int (*dxt5y_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); - int (*dxt5ys_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); - int (*rgtc1s_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); - int (*rgtc1u_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt1_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt1a_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt2_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt3_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt4_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt5_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt5y_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxt5ys_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*rgtc1s_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*rgtc1u_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); int (*rgtc1u_alpha_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); - int (*rgtc2s_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); - int (*rgtc2u_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); - int (*dxn3dc_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*rgtc2s_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*rgtc2u_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*dxn3dc_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); } TextureDSPContext; void ff_texturedsp_init(TextureDSPContext *c); From 7480f232d24a4215ff69584dbd873036e3bcb30e Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Thu, 28 Sep 2017 21:46:08 +0200 Subject: [PATCH 0490/2557] libavcodec/texturedspenc : indent after add rgtc1u_alpha func Signed-off-by: Tom Butterworth --- libavcodec/texturedspenc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/texturedspenc.c b/libavcodec/texturedspenc.c index ae2e95e23f7a9..3d68e0cf39d98 100644 --- a/libavcodec/texturedspenc.c +++ b/libavcodec/texturedspenc.c @@ -665,8 +665,8 @@ static int rgtc1u_alpha_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *blo av_cold void ff_texturedspenc_init(TextureDSPContext *c) { - c->dxt1_block = dxt1_block; - c->dxt5_block = dxt5_block; - c->dxt5ys_block = dxt5ys_block; + c->dxt1_block = dxt1_block; + c->dxt5_block = dxt5_block; + c->dxt5ys_block = dxt5ys_block; c->rgtc1u_alpha_block = rgtc1u_alpha_block; } From 1c5f264787b1c1cf67e5e71d08b8d8b03b0c8248 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 11 Oct 2017 05:57:59 +0200 Subject: [PATCH 0491/2557] mss1: Add missing macro parameters to ARITH_GET_* macros It is wrong to pass no arguments to a macro that expects one argument and some compilers complain. --- libavcodec/mss1.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/mss1.c b/libavcodec/mss1.c index a31af06e73ee6..6679a1c1f7fe9 100644 --- a/libavcodec/mss1.c +++ b/libavcodec/mss1.c @@ -34,7 +34,7 @@ typedef struct MSS1Context { SliceContext sc; } MSS1Context; -static void arith_normalise(ArithCoder *c) +static void arith1_normalise(ArithCoder *c) { for (;;) { if (c->high >= 0x8000) { @@ -60,7 +60,7 @@ static void arith_normalise(ArithCoder *c) } } -ARITH_GET_BIT() +ARITH_GET_BIT(1) static int arith_get_bits(ArithCoder *c, int bits) { @@ -71,7 +71,7 @@ static int arith_get_bits(ArithCoder *c, int bits) c->high = ((prob + range) >> bits) + c->low - 1; c->low += prob >> bits; - arith_normalise(c); + arith1_normalise(c); return val; } @@ -85,12 +85,12 @@ static int arith_get_number(ArithCoder *c, int mod_val) c->high = (prob + range) / mod_val + c->low - 1; c->low += prob / mod_val; - arith_normalise(c); + arith1_normalise(c); return val; } -static int arith_get_prob(ArithCoder *c, int16_t *probs) +static int arith1_get_prob(ArithCoder *c, int16_t *probs) { int range = c->high - c->low + 1; int val = ((c->value - c->low + 1) * probs[0] - 1) / range; @@ -105,7 +105,7 @@ static int arith_get_prob(ArithCoder *c, int16_t *probs) return sym; } -ARITH_GET_MODEL_SYM() +ARITH_GET_MODEL_SYM(1) static void arith_init(ArithCoder *c, GetBitContext *gb) { @@ -113,7 +113,7 @@ static void arith_init(ArithCoder *c, GetBitContext *gb) c->high = 0xFFFF; c->value = get_bits(gb, 16); c->gbc.gb = gb; - c->get_model_sym = arith_get_model_sym; + c->get_model_sym = arith1_get_model_sym; c->get_number = arith_get_number; } @@ -158,7 +158,7 @@ static int mss1_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, c->pal_pic = ctx->pic->data[0] + ctx->pic->linesize[0] * (avctx->height - 1); c->pal_stride = -ctx->pic->linesize[0]; - c->keyframe = !arith_get_bit(&acoder); + c->keyframe = !arith1_get_bit(&acoder); if (c->keyframe) { c->corrupted = 0; ff_mss12_slicecontext_reset(&ctx->sc); From ae6fe04bee600dec99e81efba3b8350366f6367c Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 16 Oct 2017 17:47:01 -0300 Subject: [PATCH 0492/2557] configure: add missing optional deps on gcrypt and openssl to the hls muxer Should fix ticket #6738 Signed-off-by: James Almer --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index b9a3a9bc1ff42..819fd37718e2c 100755 --- a/configure +++ b/configure @@ -3031,6 +3031,7 @@ fifo_muxer_deps="threads" flac_demuxer_select="flac_parser" hds_muxer_select="flv_muxer" hls_muxer_select="mpegts_muxer" +hls_muxer_suggest="gcrypt openssl" image2_alias_pix_demuxer_select="image2_demuxer" image2_brender_pix_demuxer_select="image2_demuxer" ipod_muxer_select="mov_muxer" From 2e94490225909a2d40d25722b49f54a3fe967635 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 9 Oct 2017 02:13:14 -0400 Subject: [PATCH 0493/2557] ffmpeg: remove hwaccel_lax_profile_check option This has been unused for a long time, and the original purpose has been replaced by the per-stream hwaccel_flags. Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_opt.c | 3 --- 2 files changed, 4 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index f6c76bcc553c6..888f77223a36d 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -624,7 +624,6 @@ extern const AVIOInterruptCB int_cb; extern const OptionDef options[]; extern const HWAccel hwaccels[]; -extern int hwaccel_lax_profile_check; extern AVBufferRef *hw_device_ctx; #if CONFIG_QSV extern char *qsv_device; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 100fa76e46f29..500920326b136 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -100,7 +100,6 @@ const HWAccel hwaccels[] = { #endif { 0 }, }; -int hwaccel_lax_profile_check = 0; AVBufferRef *hw_device_ctx; HWDevice *filter_hw_device; @@ -3640,8 +3639,6 @@ const OptionDef options[] = { { "autorotate", HAS_ARG | OPT_BOOL | OPT_SPEC | OPT_EXPERT | OPT_INPUT, { .off = OFFSET(autorotate) }, "automatically insert correct rotate filters" }, - { "hwaccel_lax_profile_check", OPT_BOOL | OPT_EXPERT, { &hwaccel_lax_profile_check}, - "attempt to decode anyway if HW accelerated decoder's supported profiles do not exactly match the stream" }, /* audio options */ { "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_frames }, From 15b86d3b4aeb51d92687f031934a807fd6f29b99 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 17 Oct 2017 01:17:32 -0300 Subject: [PATCH 0494/2557] configure: add missing optional dep on libfribidi to the drawtext filter Fixes ticket #6740 Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 819fd37718e2c..6e7faf55b6877 100755 --- a/configure +++ b/configure @@ -3224,7 +3224,7 @@ delogo_filter_deps="gpl" deshake_filter_select="pixelutils" deshake_filter_suggest="opencl" drawtext_filter_deps="libfreetype" -drawtext_filter_suggest="libfontconfig" +drawtext_filter_suggest="libfontconfig libfribidi" elbg_filter_deps="avcodec" eq_filter_deps="gpl" fftfilt_filter_deps="avcodec" From f685bbcbe87db3efb952ca4ccd6bbe92420aecbb Mon Sep 17 00:00:00 2001 From: Jacek Jendrzej Date: Thu, 5 Oct 2017 10:34:43 +0200 Subject: [PATCH 0495/2557] avformat: fix build wihout dashenc Signed-off-by: James Almer --- libavformat/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index df709c29dd253..d955a8b12a212 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -133,7 +133,7 @@ OBJS-$(CONFIG_CRC_MUXER) += crcenc.o OBJS-$(CONFIG_DATA_DEMUXER) += rawdec.o OBJS-$(CONFIG_DATA_MUXER) += rawenc.o OBJS-$(CONFIG_DASH_MUXER) += dash.o dashenc.o -OBJS-$(CONFIG_DASH_DEMUXER) += dashdec.o +OBJS-$(CONFIG_DASH_DEMUXER) += dash.o dashdec.o OBJS-$(CONFIG_DAUD_DEMUXER) += dauddec.o OBJS-$(CONFIG_DAUD_MUXER) += daudenc.o OBJS-$(CONFIG_DCSTR_DEMUXER) += dcstr.o From fbd63170bcbc5cad8965edad7c357f6eb4132250 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 16 Oct 2017 23:02:24 +0100 Subject: [PATCH 0496/2557] cbs: Add test dependencies Fixes the MPEG-2 failure with --disable-error-resilience. --- tests/fate/cbs.mak | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/fate/cbs.mak b/tests/fate/cbs.mak index afd5c5dd8fcc4..fc5967e6f37df 100644 --- a/tests/fate/cbs.mak +++ b/tests/fate/cbs.mak @@ -4,6 +4,8 @@ fate-cbs: fate-cbs-h264 fate-cbs-hevc fate-cbs-mpeg2 +FATE_CBS_DEPS = $(call ALLYES, $(1)_DEMUXER $(1)_PARSER $(2)_METADATA_BSF $(3)_DECODER $(3)_MUXER) + define FATE_CBS_TEST # (codec, test_name, sample_file, output_format) FATE_CBS_$(1) += fate-cbs-$(1)-$(2) @@ -30,8 +32,9 @@ FATE_CBS_H264_SAMPLES = \ $(foreach N,$(FATE_CBS_H264_SAMPLES),$(eval $(call FATE_CBS_TEST,h264,$(basename $(N)),h264-conformance/$(N),h264))) -FATE_SAMPLES_AVCONV += $(FATE_CBS_h264) -fate-cbs-h264: $(FATE_CBS_h264) +FATE_CBS_H264-$(call FATE_CBS_DEPS, H264, H264, H264) = $(FATE_CBS_h264) +FATE_SAMPLES_AVCONV += $(FATE_CBS_H264-yes) +fate-cbs-h264: $(FATE_CBS_H264-yes) # H.265 read/write @@ -58,8 +61,9 @@ FATE_CBS_HEVC_SAMPLES = \ $(foreach N,$(FATE_CBS_HEVC_SAMPLES),$(eval $(call FATE_CBS_TEST,hevc,$(basename $(N)),hevc-conformance/$(N),hevc))) -FATE_SAMPLES_AVCONV += $(FATE_CBS_hevc) -fate-cbs-hevc: $(FATE_CBS_hevc) +FATE_CBS_HEVC-$(call FATE_CBS_DEPS, HEVC, HEVC, HEVC) = $(FATE_CBS_hevc) +FATE_SAMPLES_AVCONV += $(FATE_CBS_HEVC-yes) +fate-cbs-hevc: $(FATE_CBS_HEVC-yes) # MPEG-2 read/write @@ -70,5 +74,6 @@ FATE_CBS_MPEG2_SAMPLES = \ $(foreach N,$(FATE_CBS_MPEG2_SAMPLES),$(eval $(call FATE_CBS_TEST,mpeg2,$(basename $(N)),mpeg2/$(N),mpeg2video))) -FATE_SAMPLES_AVCONV += $(FATE_CBS_mpeg2) -fate-cbs-mpeg2: $(FATE_CBS_mpeg2) +FATE_CBS_MPEG2-$(call FATE_CBS_DEPS, MPEGVIDEO, MPEG2, MPEG2VIDEO) = $(FATE_CBS_mpeg2) +FATE_SAMPLES_AVCONV += $(FATE_CBS_MPEG2-yes) +fate-cbs-mpeg2: $(FATE_CBS_MPEG2-yes) From a3accd0c3768933f15422c9dec596da0f436d786 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 17 Oct 2017 21:35:28 +0200 Subject: [PATCH 0497/2557] lavf/cafenc: Allow muxing opus. QuickTime does not require the (unknown) kuki chunk for decoding. --- libavformat/cafenc.c | 3 ++- libavformat/version.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index f550cd965a3c8..211b046563fc6 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -81,6 +81,8 @@ static uint32_t samples_per_packet(enum AVCodecID codec_id, int channels, int bl return 320; case AV_CODEC_ID_MP1: return 384; + case AV_CODEC_ID_OPUS: + return 960; case AV_CODEC_ID_MP2: case AV_CODEC_ID_MP3: return 1152; @@ -117,7 +119,6 @@ static int caf_write_header(AVFormatContext *s) switch (par->codec_id) { case AV_CODEC_ID_AAC: - case AV_CODEC_ID_OPUS: av_log(s, AV_LOG_ERROR, "muxing codec currently unsupported\n"); return AVERROR_PATCHWELCOME; } diff --git a/libavformat/version.h b/libavformat/version.h index 828be14b209d1..22f82a37f7aa3 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -33,7 +33,7 @@ // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 57 #define LIBAVFORMAT_VERSION_MINOR 84 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From d05444d2c6d99767547b1f0761e8459fb07b305d Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 24 Jun 2017 00:30:20 +0100 Subject: [PATCH 0498/2557] h264: Add stream constraint values to the common header With comments describing the derivation of each value. (cherry picked from commit aaf441465080b9bc57f5ca8dea656f9b2c5dc821) --- libavcodec/h264.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/libavcodec/h264.h b/libavcodec/h264.h index 86df5eb9b3fc2..650580bf3adec 100644 --- a/libavcodec/h264.h +++ b/libavcodec/h264.h @@ -44,4 +44,49 @@ enum { H264_NAL_AUXILIARY_SLICE = 19, }; + +enum { + // 7.4.2.1.1: seq_parameter_set_id is in [0, 31]. + H264_MAX_SPS_COUNT = 32, + // 7.4.2.2: pic_parameter_set_id is in [0, 255]. + H264_MAX_PPS_COUNT = 256, + + // A.3: MaxDpbFrames is bounded above by 16. + H264_MAX_DPB_FRAMES = 16, + // 7.4.2.1.1: max_num_ref_frames is in [0, MaxDpbFrames], and + // each reference frame can have two fields. + H264_MAX_REFS = 2 * H264_MAX_DPB_FRAMES, + + // 7.4.3.1: modification_of_pic_nums_idc is not equal to 3 at most + // num_ref_idx_lN_active_minus1 + 1 times (that is, once for each + // possible reference), then equal to 3 once. + H264_MAX_RPLM_COUNT = H264_MAX_REFS + 1, + + // 7.4.3.3: in the worst case, we begin with a full short-term + // reference picture list. Each picture in turn is moved to the + // long-term list (type 3) and then discarded from there (type 2). + // Then, we set the length of the long-term list (type 4), mark + // the current picture as long-term (type 6) and terminate the + // process (type 0). + H264_MAX_MMCO_COUNT = H264_MAX_REFS * 2 + 3, + + // A.2.1, A.2.3: profiles supporting FMO constrain + // num_slice_groups_minus1 to be in [0, 7]. + H264_MAX_SLICE_GROUPS = 8, + + // E.2.2: cpb_cnt_minus1 is in [0, 31]. + H264_MAX_CPB_CNT = 32, + + // A.3: in table A-1 the highest level allows a MaxFS of 139264. + H264_MAX_MB_PIC_SIZE = 139264, + // A.3.1, A.3.2: PicWidthInMbs and PicHeightInMbs are constrained + // to be not greater than sqrt(MaxFS * 8). Hence height/width are + // bounded above by sqrt(139264 * 8) = 1055.5 macroblocks. + H264_MAX_MB_WIDTH = 1055, + H264_MAX_MB_HEIGHT = 1055, + H264_MAX_WIDTH = H264_MAX_MB_WIDTH * 16, + H264_MAX_HEIGHT = H264_MAX_MB_HEIGHT * 16, +}; + + #endif /* AVCODEC_H264_H */ From b1374e925c1cf3af5c8482119f3f2630d66213de Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 24 Jun 2017 00:29:02 +0100 Subject: [PATCH 0499/2557] hevc: Improve stream constraint values in common header Add comments to describe the sources of the constraint values expressed here, and add some more related values which will be used in following patches. Fix the incorrect values for SPS and PPS count (they are not the same as those used for H.264), and remove HEVC_MAX_CU_SIZE because it is not used anywhere. (cherry picked from commit b88da98b34809dedf8882d43ed543632ed233538) --- libavcodec/hevc.h | 65 ++++++++++++++++++++++++++++++++++++-------- libavcodec/hevc_ps.c | 2 +- libavcodec/hevc_ps.h | 6 ++-- libavformat/hevc.c | 6 ++-- 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index f0fb919a7f26c..2f20db82856e1 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -74,19 +74,60 @@ enum HEVCSliceType { HEVC_SLICE_I = 2, }; -/** - * 7.4.2.1 - */ -#define HEVC_MAX_SUB_LAYERS 7 -#define HEVC_MAX_VPS_COUNT 16 -#define HEVC_MAX_SPS_COUNT 32 -#define HEVC_MAX_PPS_COUNT 256 -#define HEVC_MAX_SHORT_TERM_RPS_COUNT 64 -#define HEVC_MAX_CU_SIZE 128 +enum { + // 7.4.3.1: vps_max_layers_minus1 is in [0, 62]. + HEVC_MAX_LAYERS = 63, + // 7.4.3.1: vps_max_sub_layers_minus1 is in [0, 6]. + HEVC_MAX_SUB_LAYERS = 7, + // 7.4.3.1: vps_num_layer_sets_minus1 is in [0, 1023]. + HEVC_MAX_LAYER_SETS = 1024, + + // 7.4.2.1: vps_video_parameter_set_id is u(4). + HEVC_MAX_VPS_COUNT = 16, + // 7.4.3.2.1: sps_seq_parameter_set_id is in [0, 15]. + HEVC_MAX_SPS_COUNT = 16, + // 7.4.3.3.1: pps_pic_parameter_set_id is in [0, 63]. + HEVC_MAX_PPS_COUNT = 64, + + // A.4.2: MaxDpbSize is bounded above by 16. + HEVC_MAX_DPB_SIZE = 16, + // 7.4.3.1: vps_max_dec_pic_buffering_minus1[i] is in [0, MaxDpbSize - 1]. + HEVC_MAX_REFS = HEVC_MAX_DPB_SIZE, + + // 7.4.3.2.1: num_short_term_ref_pic_sets is in [0, 64]. + HEVC_MAX_SHORT_TERM_REF_PIC_SETS = 64, + // 7.4.3.2.1: num_long_term_ref_pics_sps is in [0, 32]. + HEVC_MAX_LONG_TERM_REF_PICS = 32, -#define HEVC_MAX_REFS 16 -#define HEVC_MAX_DPB_SIZE 16 // A.4.1 + // A.3: all profiles require that CtbLog2SizeY is in [4, 6]. + HEVC_MIN_LOG2_CTB_SIZE = 4, + HEVC_MAX_LOG2_CTB_SIZE = 6, + + // E.3.2: cpb_cnt_minus1[i] is in [0, 31]. + HEVC_MAX_CPB_CNT = 32, + + // A.4.1: in table A.6 the highest level allows a MaxLumaPs of 35 651 584. + HEVC_MAX_LUMA_PS = 35651584, + // A.4.1: pic_width_in_luma_samples and pic_height_in_luma_samples are + // constrained to be not greater than sqrt(MaxLumaPs * 8). Hence height/ + // width are bounded above by sqrt(8 * 35651584) = 16888.2 samples. + HEVC_MAX_WIDTH = 16888, + HEVC_MAX_HEIGHT = 16888, + + // A.4.1: table A.6 allows at most 22 tile rows for any level. + HEVC_MAX_TILE_ROWS = 22, + // A.4.1: table A.6 allows at most 20 tile columns for any level. + HEVC_MAX_TILE_COLUMNS = 20, + + // 7.4.7.1: in the worst case (tiles_enabled_flag and + // entropy_coding_sync_enabled_flag are both set), entry points can be + // placed at the beginning of every Ctb row in every tile, giving an + // upper bound of (num_tile_columns_minus1 + 1) * PicHeightInCtbsY - 1. + // Only a stream with very high resolution and perverse parameters could + // get near that, though, so set a lower limit here with the maximum + // possible value for 4K video (at most 135 16x16 Ctb rows). + HEVC_MAX_ENTRY_POINT_OFFSETS = HEVC_MAX_TILE_COLUMNS * 135, +}; -#define HEVC_MAX_LOG2_CTB_SIZE 6 #endif /* AVCODEC_HEVC_H */ diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 902917d4ddaab..72d02c8372b49 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1061,7 +1061,7 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, } sps->nb_st_rps = get_ue_golomb_long(gb); - if (sps->nb_st_rps > HEVC_MAX_SHORT_TERM_RPS_COUNT) { + if (sps->nb_st_rps > HEVC_MAX_SHORT_TERM_REF_PIC_SETS) { av_log(avctx, AV_LOG_ERROR, "Too many short term RPS: %d.\n", sps->nb_st_rps); return AVERROR_INVALIDDATA; diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 76f8eb31e6ae1..477ee4299a6db 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -254,14 +254,14 @@ typedef struct HEVCSPS { ScalingList scaling_list; unsigned int nb_st_rps; - ShortTermRPS st_rps[HEVC_MAX_SHORT_TERM_RPS_COUNT]; + ShortTermRPS st_rps[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]; uint8_t amp_enabled_flag; uint8_t sao_enabled; uint8_t long_term_ref_pics_present_flag; - uint16_t lt_ref_pic_poc_lsb_sps[32]; - uint8_t used_by_curr_pic_lt_sps_flag[32]; + uint16_t lt_ref_pic_poc_lsb_sps[HEVC_MAX_LONG_TERM_REF_PICS]; + uint8_t used_by_curr_pic_lt_sps_flag[HEVC_MAX_LONG_TERM_REF_PICS]; uint8_t num_long_term_ref_pics_sps; struct { diff --git a/libavformat/hevc.c b/libavformat/hevc.c index 1a2d6cdd2b258..e45d2c08d2ddb 100644 --- a/libavformat/hevc.c +++ b/libavformat/hevc.c @@ -417,7 +417,7 @@ static void skip_scaling_list_data(GetBitContext *gb) static int parse_rps(GetBitContext *gb, unsigned int rps_idx, unsigned int num_rps, - unsigned int num_delta_pocs[HEVC_MAX_SHORT_TERM_RPS_COUNT]) + unsigned int num_delta_pocs[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]) { unsigned int i; @@ -486,7 +486,7 @@ static int hvcc_parse_sps(GetBitContext *gb, HEVCDecoderConfigurationRecord *hvcc) { unsigned int i, sps_max_sub_layers_minus1, log2_max_pic_order_cnt_lsb_minus4; - unsigned int num_short_term_ref_pic_sets, num_delta_pocs[HEVC_MAX_SHORT_TERM_RPS_COUNT]; + unsigned int num_short_term_ref_pic_sets, num_delta_pocs[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]; skip_bits(gb, 4); // sps_video_parameter_set_id @@ -556,7 +556,7 @@ static int hvcc_parse_sps(GetBitContext *gb, } num_short_term_ref_pic_sets = get_ue_golomb_long(gb); - if (num_short_term_ref_pic_sets > HEVC_MAX_SHORT_TERM_RPS_COUNT) + if (num_short_term_ref_pic_sets > HEVC_MAX_SHORT_TERM_REF_PIC_SETS) return AVERROR_INVALIDDATA; for (i = 0; i < num_short_term_ref_pic_sets; i++) { From 6734eef6b8b464139fdc140ec9bc9e8d74173869 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 4 May 2017 23:01:51 +0100 Subject: [PATCH 0500/2557] lavc: Add coded bitstream read/write API (cherry picked from commit 18f1706f331bf5dd565774eae680508c8d3a97ad) (cherry picked from commit 44cde38c8acbef7d5250e6d1b52b1020871e093b) --- configure | 1 + libavcodec/Makefile | 1 + libavcodec/cbs.c | 482 ++++++++++++++++++++++++++++++++++++++ libavcodec/cbs.h | 308 ++++++++++++++++++++++++ libavcodec/cbs_internal.h | 86 +++++++ 5 files changed, 878 insertions(+) create mode 100644 libavcodec/cbs.c create mode 100644 libavcodec/cbs.h create mode 100644 libavcodec/cbs_internal.h diff --git a/configure b/configure index 62c185586dca3..99f09fb6b2c77 100755 --- a/configure +++ b/configure @@ -2150,6 +2150,7 @@ CONFIG_EXTRA=" blockdsp bswapdsp cabac + cbs dirac_parse dvprofile exif diff --git a/libavcodec/Makefile b/libavcodec/Makefile index c4ec09b1c4535..9680553c9041f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -59,6 +59,7 @@ OBJS-$(CONFIG_AUDIODSP) += audiodsp.o OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o OBJS-$(CONFIG_CABAC) += cabac.o +OBJS-$(CONFIG_CBS) += cbs.o OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c new file mode 100644 index 0000000000000..fa68040cfa0aa --- /dev/null +++ b/libavcodec/cbs.c @@ -0,0 +1,482 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" + +#include "libavutil/avassert.h" +#include "libavutil/common.h" + +#include "cbs.h" +#include "cbs_internal.h" + + +static const CodedBitstreamType *cbs_type_table[] = { +}; + +int ff_cbs_init(CodedBitstreamContext **ctx_ptr, + enum AVCodecID codec_id, void *log_ctx) +{ + CodedBitstreamContext *ctx; + const CodedBitstreamType *type; + int i; + + type = NULL; + for (i = 0; i < FF_ARRAY_ELEMS(cbs_type_table); i++) { + if (cbs_type_table[i]->codec_id == codec_id) { + type = cbs_type_table[i]; + break; + } + } + if (!type) + return AVERROR(EINVAL); + + ctx = av_mallocz(sizeof(*ctx)); + if (!ctx) + return AVERROR(ENOMEM); + + ctx->log_ctx = log_ctx; + ctx->codec = type; + + ctx->priv_data = av_mallocz(ctx->codec->priv_data_size); + if (!ctx->priv_data) { + av_freep(&ctx); + return AVERROR(ENOMEM); + } + + ctx->decompose_unit_types = NULL; + + ctx->trace_enable = 0; + ctx->trace_level = AV_LOG_TRACE; + + *ctx_ptr = ctx; + return 0; +} + +void ff_cbs_close(CodedBitstreamContext **ctx_ptr) +{ + CodedBitstreamContext *ctx = *ctx_ptr; + + if (!ctx) + return; + + if (ctx->codec && ctx->codec->close) + ctx->codec->close(ctx); + + av_freep(&ctx->priv_data); + av_freep(ctx_ptr); +} + +static void cbs_unit_uninit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + if (ctx->codec->free_unit && unit->content && !unit->content_external) + ctx->codec->free_unit(unit); + + av_freep(&unit->data); + unit->data_size = 0; + unit->data_bit_padding = 0; +} + +void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag) +{ + int i; + + for (i = 0; i < frag->nb_units; i++) + cbs_unit_uninit(ctx, &frag->units[i]); + av_freep(&frag->units); + frag->nb_units = 0; + + av_freep(&frag->data); + frag->data_size = 0; + frag->data_bit_padding = 0; +} + +static int cbs_read_fragment_content(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag) +{ + int err, i, j; + + for (i = 0; i < frag->nb_units; i++) { + if (ctx->decompose_unit_types) { + for (j = 0; j < ctx->nb_decompose_unit_types; j++) { + if (ctx->decompose_unit_types[j] == frag->units[i].type) + break; + } + if (j >= ctx->nb_decompose_unit_types) + continue; + } + + err = ctx->codec->read_unit(ctx, &frag->units[i]); + if (err == AVERROR(ENOSYS)) { + av_log(ctx->log_ctx, AV_LOG_WARNING, + "Decomposition unimplemented for unit %d " + "(type %"PRIu32").\n", i, frag->units[i].type); + } else if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d " + "(type %"PRIu32").\n", i, frag->units[i].type); + return err; + } + } + + return 0; +} + +int ff_cbs_read_extradata(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const AVCodecParameters *par) +{ + int err; + + memset(frag, 0, sizeof(*frag)); + + frag->data = par->extradata; + frag->data_size = par->extradata_size; + + err = ctx->codec->split_fragment(ctx, frag, 1); + if (err < 0) + return err; + + frag->data = NULL; + frag->data_size = 0; + + return cbs_read_fragment_content(ctx, frag); +} + +int ff_cbs_read_packet(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const AVPacket *pkt) +{ + int err; + + memset(frag, 0, sizeof(*frag)); + + frag->data = pkt->data; + frag->data_size = pkt->size; + + err = ctx->codec->split_fragment(ctx, frag, 0); + if (err < 0) + return err; + + frag->data = NULL; + frag->data_size = 0; + + return cbs_read_fragment_content(ctx, frag); +} + +int ff_cbs_read(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const uint8_t *data, size_t size) +{ + int err; + + memset(frag, 0, sizeof(*frag)); + + // (We won't write to this during split.) + frag->data = (uint8_t*)data; + frag->data_size = size; + + err = ctx->codec->split_fragment(ctx, frag, 0); + if (err < 0) + return err; + + frag->data = NULL; + frag->data_size = 0; + + return cbs_read_fragment_content(ctx, frag); +} + + +int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag) +{ + int err, i; + + for (i = 0; i < frag->nb_units; i++) { + if (!frag->units[i].content) + continue; + + err = ctx->codec->write_unit(ctx, &frag->units[i]); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d " + "(type %"PRIu32").\n", i, frag->units[i].type); + return err; + } + } + + err = ctx->codec->assemble_fragment(ctx, frag); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n"); + return err; + } + + return 0; +} + +int ff_cbs_write_extradata(CodedBitstreamContext *ctx, + AVCodecParameters *par, + CodedBitstreamFragment *frag) +{ + int err; + + err = ff_cbs_write_fragment_data(ctx, frag); + if (err < 0) + return err; + + av_freep(&par->extradata); + + par->extradata = av_malloc(frag->data_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!par->extradata) + return AVERROR(ENOMEM); + + memcpy(par->extradata, frag->data, frag->data_size); + memset(par->extradata + frag->data_size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); + par->extradata_size = frag->data_size; + + return 0; +} + +int ff_cbs_write_packet(CodedBitstreamContext *ctx, + AVPacket *pkt, + CodedBitstreamFragment *frag) +{ + int err; + + err = ff_cbs_write_fragment_data(ctx, frag); + if (err < 0) + return err; + + err = av_new_packet(pkt, frag->data_size); + if (err < 0) + return err; + + memcpy(pkt->data, frag->data, frag->data_size); + pkt->size = frag->data_size; + + return 0; +} + + +void ff_cbs_trace_header(CodedBitstreamContext *ctx, + const char *name) +{ + if (!ctx->trace_enable) + return; + + av_log(ctx->log_ctx, ctx->trace_level, "%s\n", name); +} + +void ff_cbs_trace_syntax_element(CodedBitstreamContext *ctx, int position, + const char *name, const char *bits, + int64_t value) +{ + size_t name_len, bits_len; + int pad; + + if (!ctx->trace_enable) + return; + + av_assert0(value >= INT_MIN && value <= UINT32_MAX); + + name_len = strlen(name); + bits_len = strlen(bits); + + if (name_len + bits_len > 60) + pad = bits_len + 2; + else + pad = 61 - name_len; + + av_log(ctx->log_ctx, ctx->trace_level, "%-10d %s%*s = %"PRId64"\n", + position, name, pad, bits, value); +} + +int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, GetBitContext *gbc, + int width, const char *name, uint32_t *write_to, + uint32_t range_min, uint32_t range_max) +{ + uint32_t value; + int position; + + av_assert0(width > 0 && width <= 32); + + if (get_bits_left(gbc) < width) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at " + "%s: bitstream ended.\n", name); + return AVERROR_INVALIDDATA; + } + + if (ctx->trace_enable) + position = get_bits_count(gbc); + + value = get_bits_long(gbc, width); + + if (ctx->trace_enable) { + char bits[33]; + int i; + for (i = 0; i < width; i++) + bits[i] = value >> (width - i - 1) & 1 ? '1' : '0'; + bits[i] = 0; + + ff_cbs_trace_syntax_element(ctx, position, name, bits, value); + } + + if (value < range_min || value > range_max) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " + "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n", + name, value, range_min, range_max); + return AVERROR_INVALIDDATA; + } + + *write_to = value; + return 0; +} + +int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc, + int width, const char *name, uint32_t value, + uint32_t range_min, uint32_t range_max) +{ + av_assert0(width > 0 && width <= 32); + + if (value < range_min || value > range_max) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " + "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n", + name, value, range_min, range_max); + return AVERROR_INVALIDDATA; + } + + if (put_bits_left(pbc) < width) + return AVERROR(ENOSPC); + + if (ctx->trace_enable) { + char bits[33]; + int i; + for (i = 0; i < width; i++) + bits[i] = value >> (width - i - 1) & 1 ? '1' : '0'; + bits[i] = 0; + + ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), name, bits, value); + } + + if (width < 32) + put_bits(pbc, width, value); + else + put_bits32(pbc, value); + + return 0; +} + + +static int cbs_insert_unit(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position) +{ + CodedBitstreamUnit *units; + + units = av_malloc_array(frag->nb_units + 1, sizeof(*units)); + if (!units) + return AVERROR(ENOMEM); + + if (position > 0) + memcpy(units, frag->units, position * sizeof(*units)); + if (position < frag->nb_units) + memcpy(units + position + 1, frag->units + position, + (frag->nb_units - position) * sizeof(*units)); + + memset(units + position, 0, sizeof(*units)); + + av_freep(&frag->units); + frag->units = units; + ++frag->nb_units; + + return 0; +} + +int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position, + CodedBitstreamUnitType type, + void *content) +{ + int err; + + if (position == -1) + position = frag->nb_units; + av_assert0(position >= 0 && position <= frag->nb_units); + + err = cbs_insert_unit(ctx, frag, position); + if (err < 0) + return err; + + frag->units[position].type = type; + frag->units[position].content = content; + frag->units[position].content_external = 1; + + return 0; +} + +int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position, + CodedBitstreamUnitType type, + uint8_t *data, size_t data_size) +{ + int err; + + if (position == -1) + position = frag->nb_units; + av_assert0(position >= 0 && position <= frag->nb_units); + + err = cbs_insert_unit(ctx, frag, position); + if (err < 0) + return err; + + frag->units[position].type = type; + frag->units[position].data = data; + frag->units[position].data_size = data_size; + + return 0; +} + +int ff_cbs_delete_unit(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position) +{ + if (position < 0 || position >= frag->nb_units) + return AVERROR(EINVAL); + + cbs_unit_uninit(ctx, &frag->units[position]); + + --frag->nb_units; + + if (frag->nb_units == 0) { + av_freep(&frag->units); + + } else { + memmove(frag->units + position, + frag->units + position + 1, + (frag->nb_units - position) * sizeof(*frag->units)); + + // Don't bother reallocating the unit array. + } + + return 0; +} diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h new file mode 100644 index 0000000000000..2dc975ed793e5 --- /dev/null +++ b/libavcodec/cbs.h @@ -0,0 +1,308 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_H +#define AVCODEC_CBS_H + +#include +#include + +#include "avcodec.h" + + +/* + * This defines a framework for converting between a coded bitstream + * and structures defining all individual syntax elements found in + * such a stream. + * + * Conversion in both directions is possible. Given a coded bitstream + * (any meaningful fragment), it can be parsed and decomposed into + * syntax elements stored in a set of codec-specific structures. + * Similarly, given a set of those same codec-specific structures the + * syntax elements can be serialised and combined to create a coded + * bitstream. + */ + +struct CodedBitstreamType; + +/** + * The codec-specific type of a bitstream unit. + */ +typedef uint32_t CodedBitstreamUnitType; + +/** + * Coded bitstream unit structure. + * + * A bitstream unit the smallest element of a bitstream which + * is meaningful on its own. For example, an H.264 NAL unit. + * + * See the codec-specific header for the meaning of this for any + * particular codec. + */ +typedef struct CodedBitstreamUnit { + /** + * Codec-specific type of this unit. + */ + CodedBitstreamUnitType type; + + /** + * Pointer to the directly-parsable bitstream form of this unit. + * + * May be NULL if the unit currently only exists in decomposed form. + */ + uint8_t *data; + /** + * The number of bytes in the bitstream (including any padding bits + * in the final byte). + */ + size_t data_size; + /** + * The number of bits which should be ignored in the final byte. + * + * This supports non-byte-aligned bitstreams. + */ + size_t data_bit_padding; + + /** + * Pointer to the decomposed form of this unit. + * + * The type of this structure depends on both the codec and the + * type of this unit. May be NULL if the unit only exists in + * bitstream form. + */ + void *content; + /** + * Whether the content was supplied externally. + * + * If so, it should not be freed when freeing the unit. + */ + int content_external; +} CodedBitstreamUnit; + +/** + * Coded bitstream fragment structure, combining one or more units. + * + * This is any sequence of units. It need not form some greater whole, + * though in many cases it will. For example, an H.264 access unit, + * which is composed of a sequence of H.264 NAL units. + */ +typedef struct CodedBitstreamFragment { + /** + * Pointer to the bitstream form of this fragment. + * + * May be NULL if the fragment only exists as component units. + */ + uint8_t *data; + /** + * The number of bytes in the bitstream. + * + * The number of bytes in the bitstream (including any padding bits + * in the final byte). + */ + size_t data_size; + /** + * The number of bits which should be ignored in the final byte. + */ + size_t data_bit_padding; + + /** + * Number of units in this fragment. + * + * This may be zero if the fragment only exists in bitstream form + * and has not been decomposed. + */ + int nb_units; + /** + * Pointer to an array of units of length nb_units. + * + * Must be NULL if nb_units is zero. + */ + CodedBitstreamUnit *units; +} CodedBitstreamFragment; + +/** + * Context structure for coded bitstream operations. + */ +typedef struct CodedBitstreamContext { + /** + * Logging context to be passed to all av_log() calls associated + * with this context. + */ + void *log_ctx; + + /** + * Internal codec-specific hooks. + */ + const struct CodedBitstreamType *codec; + + /** + * Internal codec-specific data. + * + * This contains any information needed when reading/writing + * bitsteams which will not necessarily be present in a fragment. + * For example, for H.264 it contains all currently visible + * parameter sets - they are required to determine the bitstream + * syntax but need not be present in every access unit. + */ + void *priv_data; + + /** + * Array of unit types which should be decomposed when reading. + * + * Types not in this list will be available in bitstream form only. + * If NULL, all supported types will be decomposed. + */ + CodedBitstreamUnitType *decompose_unit_types; + /** + * Length of the decompose_unit_types array. + */ + int nb_decompose_unit_types; + + /** + * Enable trace output during read/write operations. + */ + int trace_enable; + /** + * Log level to use for trace output. + * + * From AV_LOG_*; defaults to AV_LOG_TRACE. + */ + int trace_level; +} CodedBitstreamContext; + + +/** + * Create and initialise a new context for the given codec. + */ +int ff_cbs_init(CodedBitstreamContext **ctx, + enum AVCodecID codec_id, void *log_ctx); + +/** + * Close a context and free all internal state. + */ +void ff_cbs_close(CodedBitstreamContext **ctx); + + +/** + * Read the extradata bitstream found in codec parameters into a + * fragment, then split into units and decompose. + * + * This also updates the internal state, so will need to be called for + * codecs with extradata to read parameter sets necessary for further + * parsing even if the fragment itself is not desired. + */ +int ff_cbs_read_extradata(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const AVCodecParameters *par); + +/** + * Read the data bitstream from a packet into a fragment, then + * split into units and decompose. + * + * This also updates the internal state of the coded bitstream context + * with any persistent data from the fragment which may be required to + * read following fragments (e.g. parameter sets). + */ +int ff_cbs_read_packet(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const AVPacket *pkt); + +/** + * Read a bitstream from a memory region into a fragment, then + * split into units and decompose. + * + * This also updates the internal state of the coded bitstream context + * with any persistent data from the fragment which may be required to + * read following fragments (e.g. parameter sets). + */ +int ff_cbs_read(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const uint8_t *data, size_t size); + + +/** + * Write the content of the fragment to its own internal buffer. + * + * Writes the content of all units and then assembles them into a new + * data buffer. When modifying the content of decomposed units, this + * can be used to regenerate the bitstream form of units or the whole + * fragment so that it can be extracted for other use. + * + * This also updates the internal state of the coded bitstream context + * with any persistent data from the fragment which may be required to + * write following fragments (e.g. parameter sets). + */ +int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag); + +/** + * Write the bitstream of a fragment to the extradata in codec parameters. + * + * This replaces any existing extradata in the structure. + */ +int ff_cbs_write_extradata(CodedBitstreamContext *ctx, + AVCodecParameters *par, + CodedBitstreamFragment *frag); + +/** + * Write the bitstream of a fragment to a packet. + */ +int ff_cbs_write_packet(CodedBitstreamContext *ctx, + AVPacket *pkt, + CodedBitstreamFragment *frag); + + +/** + * Free all allocated memory in a fragment. + */ +void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag); + + +/** + * Insert a new unit into a fragment with the given content. + * + * The content structure continues to be owned by the caller, and + * will not be freed when the unit is. + */ +int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position, + CodedBitstreamUnitType type, + void *content); + +/** + * Insert a new unit into a fragment with the given data bitstream. + * + * The data buffer will be owned by the unit after this operation. + */ +int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position, + CodedBitstreamUnitType type, + uint8_t *data, size_t data_size); + +/** + * Delete a unit from a fragment and free all memory it uses. + */ +int ff_cbs_delete_unit(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int position); + + +#endif /* AVCODEC_CBS_H */ diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h new file mode 100644 index 0000000000000..f6a42beea3795 --- /dev/null +++ b/libavcodec/cbs_internal.h @@ -0,0 +1,86 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_INTERNAL_H +#define AVCODEC_CBS_INTERNAL_H + +#include "avcodec.h" +#include "cbs.h" +#include "get_bits.h" +#include "put_bits.h" + + +typedef struct CodedBitstreamType { + enum AVCodecID codec_id; + + size_t priv_data_size; + + // Split frag->data into coded bitstream units, creating the + // frag->units array. Fill data but not content on each unit. + // header is set if the fragment came from a header block, which + // may require different parsing for some codecs (e.g. the AVCC + // header in H.264). + int (*split_fragment)(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int header); + + // Read the unit->data bitstream and decompose it, creating + // unit->content. + int (*read_unit)(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit); + + // Write the unit->data bitstream from unit->content. + int (*write_unit)(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit); + + // Read the data from all of frag->units and assemble it into + // a bitstream for the whole fragment. + int (*assemble_fragment)(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag); + + // Free the content and data of a single unit. + void (*free_unit)(CodedBitstreamUnit *unit); + + // Free the codec internal state. + void (*close)(CodedBitstreamContext *ctx); +} CodedBitstreamType; + + +// Helper functions for trace output. + +void ff_cbs_trace_header(CodedBitstreamContext *ctx, + const char *name); + +void ff_cbs_trace_syntax_element(CodedBitstreamContext *ctx, + int position, const char *name, + const char *bitstring, int64_t value); + + +// Helper functions for read/write of common bitstream elements, including +// generation of trace output. + +int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, GetBitContext *gbc, + int width, const char *name, uint32_t *write_to, + uint32_t range_min, uint32_t range_max); + +int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc, + int width, const char *name, uint32_t value, + uint32_t range_min, uint32_t range_max); + + +#endif /* AVCODEC_CBS_INTERNAL_H */ From b4c915f4b3e15c3e787e319b961e4389762f6309 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 14 May 2017 16:18:25 +0100 Subject: [PATCH 0501/2557] lavc: Add coded bitstream read/write support for H.264 (cherry picked from commit acf06f45441be24c5cbae0920579cd69427326a1) (cherry picked from commit 768eb9182e94a94bc2ef46f565a0dac7afef3b57) (cherry picked from commit e7f64191b27bcf37cbf7006606f0f439c6cdc24f) --- configure | 2 + libavcodec/Makefile | 1 + libavcodec/cbs.c | 3 + libavcodec/cbs.h | 2 + libavcodec/cbs_h264.h | 427 +++++++++ libavcodec/cbs_h2645.c | 1010 ++++++++++++++++++++ libavcodec/cbs_h2645.h | 43 + libavcodec/cbs_h264_syntax_template.c | 1230 +++++++++++++++++++++++++ libavcodec/cbs_internal.h | 3 + 9 files changed, 2721 insertions(+) create mode 100644 libavcodec/cbs_h264.h create mode 100644 libavcodec/cbs_h2645.c create mode 100644 libavcodec/cbs_h2645.h create mode 100644 libavcodec/cbs_h264_syntax_template.c diff --git a/configure b/configure index 99f09fb6b2c77..07c25e3dfad37 100755 --- a/configure +++ b/configure @@ -2151,6 +2151,7 @@ CONFIG_EXTRA=" bswapdsp cabac cbs + cbs_h264 dirac_parse dvprofile exif @@ -2404,6 +2405,7 @@ w32threads_deps="atomics_native" threads_if_any="$THREADS_LIST" # subsystems +cbs_h264_select="cbs golomb" dct_select="rdft" dirac_parse_select="golomb" error_resilience_select="me_cmp" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 9680553c9041f..245a44c7d5896 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -60,6 +60,7 @@ OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o OBJS-$(CONFIG_CABAC) += cabac.o OBJS-$(CONFIG_CBS) += cbs.o +OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o h2645_parse.o OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index fa68040cfa0aa..f489d9806f474 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -28,6 +28,9 @@ static const CodedBitstreamType *cbs_type_table[] = { +#if CONFIG_CBS_H264 + &ff_cbs_type_h264, +#endif }; int ff_cbs_init(CodedBitstreamContext **ctx_ptr, diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h index 2dc975ed793e5..a64430667b59d 100644 --- a/libavcodec/cbs.h +++ b/libavcodec/cbs.h @@ -42,6 +42,8 @@ struct CodedBitstreamType; /** * The codec-specific type of a bitstream unit. + * + * H.264 / AVC: nal_unit_type */ typedef uint32_t CodedBitstreamUnitType; diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h new file mode 100644 index 0000000000000..ab7dfd855fecb --- /dev/null +++ b/libavcodec/cbs_h264.h @@ -0,0 +1,427 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_H264_H +#define AVCODEC_CBS_H264_H + +#include +#include + +#include "cbs_h2645.h" +#include "h264.h" + + +enum { + // This limit is arbitrary - it is sufficient for one message of each + // type plus some repeats, and will therefore easily cover all sane + // streams. However, it is possible to make technically-valid streams + // for which it will fail (for example, by including a large number of + // user-data-unregistered messages). + H264_MAX_SEI_PAYLOADS = 64, +}; + + +typedef struct H264RawNALUnitHeader { + uint8_t forbidden_zero_bit; + uint8_t nal_ref_idc; + uint8_t nal_unit_type; + + uint8_t svc_extension_flag; + uint8_t avc_3d_extension_flag; +} H264RawNALUnitHeader; + +typedef struct H264RawScalingList { + int8_t delta_scale[64]; +} H264RawScalingList; + +typedef struct H264RawHRD { + uint8_t cpb_cnt_minus1; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + + uint32_t bit_rate_value_minus1[H264_MAX_CPB_CNT]; + uint32_t cpb_size_value_minus1[H264_MAX_CPB_CNT]; + uint8_t cbr_flag[H264_MAX_CPB_CNT]; + + uint8_t initial_cpb_removal_delay_length_minus1; + uint8_t cpb_removal_delay_length_minus1; + uint8_t dpb_output_delay_length_minus1; + uint8_t time_offset_length; +} H264RawHRD; + +typedef struct H264RawVUI { + uint8_t aspect_ratio_info_present_flag; + uint8_t aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + + uint8_t overscan_info_present_flag; + uint8_t overscan_appropriate_flag; + + uint8_t video_signal_type_present_flag; + uint8_t video_format; + uint8_t video_full_range_flag; + uint8_t colour_description_present_flag; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; + + uint8_t chroma_loc_info_present_flag; + uint8_t chroma_sample_loc_type_top_field; + uint8_t chroma_sample_loc_type_bottom_field; + + uint8_t timing_info_present_flag; + uint32_t num_units_in_tick; + uint32_t time_scale; + uint8_t fixed_frame_rate_flag; + + uint8_t nal_hrd_parameters_present_flag; + H264RawHRD nal_hrd_parameters; + uint8_t vcl_hrd_parameters_present_flag; + H264RawHRD vcl_hrd_parameters; + uint8_t low_delay_hrd_flag; + + uint8_t pic_struct_present_flag; + + uint8_t bitstream_restriction_flag; + uint8_t motion_vectors_over_pic_boundaries_flag; + uint8_t max_bytes_per_pic_denom; + uint8_t max_bits_per_mb_denom; + uint8_t log2_max_mv_length_horizontal; + uint8_t log2_max_mv_length_vertical; + uint8_t max_num_reorder_frames; + uint8_t max_dec_frame_buffering; +} H264RawVUI; + +typedef struct H264RawSPS { + H264RawNALUnitHeader nal_unit_header; + + uint8_t profile_idc; + uint8_t constraint_set0_flag; + uint8_t constraint_set1_flag; + uint8_t constraint_set2_flag; + uint8_t constraint_set3_flag; + uint8_t constraint_set4_flag; + uint8_t constraint_set5_flag; + uint8_t reserved_zero_2bits; + uint8_t level_idc; + + uint8_t seq_parameter_set_id; + + uint8_t chroma_format_idc; + uint8_t separate_colour_plane_flag; + uint8_t bit_depth_luma_minus8; + uint8_t bit_depth_chroma_minus8; + uint8_t qpprime_y_zero_transform_bypass_flag; + + uint8_t seq_scaling_matrix_present_flag; + uint8_t seq_scaling_list_present_flag[12]; + H264RawScalingList scaling_list_4x4[6]; + H264RawScalingList scaling_list_8x8[6]; + + uint8_t log2_max_frame_num_minus4; + uint8_t pic_order_cnt_type; + uint8_t log2_max_pic_order_cnt_lsb_minus4; + uint8_t delta_pic_order_always_zero_flag; + int32_t offset_for_non_ref_pic; + int32_t offset_for_top_to_bottom_field; + uint8_t num_ref_frames_in_pic_order_cnt_cycle; + int32_t offset_for_ref_frame[256]; + + uint8_t max_num_ref_frames; + uint8_t gaps_in_frame_num_allowed_flag; + + uint16_t pic_width_in_mbs_minus1; + uint16_t pic_height_in_map_units_minus1; + + uint8_t frame_mbs_only_flag; + uint8_t mb_adaptive_frame_field_flag; + uint8_t direct_8x8_inference_flag; + + uint8_t frame_cropping_flag; + uint16_t frame_crop_left_offset; + uint16_t frame_crop_right_offset; + uint16_t frame_crop_top_offset; + uint16_t frame_crop_bottom_offset; + + uint8_t vui_parameters_present_flag; + H264RawVUI vui; +} H264RawSPS; + +typedef struct H264RawSPSExtension { + H264RawNALUnitHeader nal_unit_header; + + uint8_t seq_parameter_set_id; + + uint8_t aux_format_idc; + uint8_t bit_depth_aux_minus8; + uint8_t alpha_incr_flag; + uint16_t alpha_opaque_value; + uint16_t alpha_transparent_value; + + uint8_t additional_extension_flag; +} H264RawSPSExtension; + +typedef struct H264RawPPS { + H264RawNALUnitHeader nal_unit_header; + + uint8_t pic_parameter_set_id; + uint8_t seq_parameter_set_id; + + uint8_t entropy_coding_mode_flag; + uint8_t bottom_field_pic_order_in_frame_present_flag; + + uint8_t num_slice_groups_minus1; + uint8_t slice_group_map_type; + uint16_t run_length_minus1[H264_MAX_SLICE_GROUPS]; + uint16_t top_left[H264_MAX_SLICE_GROUPS]; + uint16_t bottom_right[H264_MAX_SLICE_GROUPS]; + uint8_t slice_group_change_direction_flag; + uint16_t slice_group_change_rate_minus1; + uint16_t pic_size_in_map_units_minus1; + uint8_t slice_group_id[H264_MAX_MB_PIC_SIZE]; + + uint8_t num_ref_idx_l0_default_active_minus1; + uint8_t num_ref_idx_l1_default_active_minus1; + + uint8_t weighted_pred_flag; + uint8_t weighted_bipred_idc; + + int8_t pic_init_qp_minus26; + int8_t pic_init_qs_minus26; + int8_t chroma_qp_index_offset; + + uint8_t deblocking_filter_control_present_flag; + uint8_t constrained_intra_pred_flag; + + uint8_t more_rbsp_data; + + uint8_t redundant_pic_cnt_present_flag; + uint8_t transform_8x8_mode_flag; + + uint8_t pic_scaling_matrix_present_flag; + uint8_t pic_scaling_list_present_flag[12]; + H264RawScalingList scaling_list_4x4[6]; + H264RawScalingList scaling_list_8x8[6]; + + int8_t second_chroma_qp_index_offset; +} H264RawPPS; + +typedef struct H264RawAUD { + H264RawNALUnitHeader nal_unit_header; + + uint8_t primary_pic_type; +} H264RawAUD; + +typedef struct H264RawSEIBufferingPeriod { + uint8_t seq_parameter_set_id; + struct { + uint32_t initial_cpb_removal_delay[H264_MAX_CPB_CNT]; + uint32_t initial_cpb_removal_delay_offset[H264_MAX_CPB_CNT]; + } nal, vcl; +} H264RawSEIBufferingPeriod; + +typedef struct H264RawSEIPicTimestamp { + uint8_t ct_type; + uint8_t nuit_field_based_flag; + uint8_t counting_type; + uint8_t full_timestamp_flag; + uint8_t discontinuity_flag; + uint8_t cnt_dropped_flag; + uint8_t n_frames; + uint8_t seconds_flag; + uint8_t seconds_value; + uint8_t minutes_flag; + uint8_t minutes_value; + uint8_t hours_flag; + uint8_t hours_value; + uint32_t time_offset; +} H264RawSEIPicTimestamp; + +typedef struct H264RawSEIPicTiming { + uint32_t cpb_removal_delay; + uint32_t dpb_output_delay; + uint8_t pic_struct; + uint8_t clock_timestamp_flag[3]; + H264RawSEIPicTimestamp timestamp[3]; +} H264RawSEIPicTiming; + +typedef struct H264RawSEIUserDataRegistered { + uint8_t itu_t_t35_country_code; + uint8_t itu_t_t35_country_code_extension_byte; + uint8_t *data; + size_t data_length; +} H264RawSEIUserDataRegistered; + +typedef struct H264RawSEIUserDataUnregistered { + uint8_t uuid_iso_iec_11578[16]; + uint8_t *data; + size_t data_length; +} H264RawSEIUserDataUnregistered; + +typedef struct H264RawSEIRecoveryPoint { + uint16_t recovery_frame_cnt; + uint8_t exact_match_flag; + uint8_t broken_link_flag; + uint8_t changing_slice_group_idc; +} H264RawSEIRecoveryPoint; + +typedef struct H264RawSEIDisplayOrientation { + uint8_t display_orientation_cancel_flag; + uint8_t hor_flip; + uint8_t ver_flip; + uint16_t anticlockwise_rotation; + uint16_t display_orientation_repetition_period; + uint8_t display_orientation_extension_flag; +} H264RawSEIDisplayOrientation; + +typedef struct H264RawSEIPayload { + uint32_t payload_type; + uint32_t payload_size; + union { + H264RawSEIBufferingPeriod buffering_period; + H264RawSEIPicTiming pic_timing; + // H264RawSEIFiller filler -> no fields. + H264RawSEIUserDataRegistered user_data_registered; + H264RawSEIUserDataUnregistered user_data_unregistered; + H264RawSEIRecoveryPoint recovery_point; + H264RawSEIDisplayOrientation display_orientation; + struct { + uint8_t *data; + size_t data_length; + } other; + } payload; +} H264RawSEIPayload; + +typedef struct H264RawSEI { + H264RawNALUnitHeader nal_unit_header; + + H264RawSEIPayload payload[H264_MAX_SEI_PAYLOADS]; + uint8_t payload_count; +} H264RawSEI; + +typedef struct H264RawSliceHeader { + H264RawNALUnitHeader nal_unit_header; + + uint32_t first_mb_in_slice; + uint8_t slice_type; + + uint8_t pic_parameter_set_id; + + uint8_t colour_plane_id; + + uint16_t frame_num; + uint8_t field_pic_flag; + uint8_t bottom_field_flag; + + uint16_t idr_pic_id; + + uint16_t pic_order_cnt_lsb; + int32_t delta_pic_order_cnt_bottom; + int32_t delta_pic_order_cnt[2]; + + uint8_t redundant_pic_cnt; + uint8_t direct_spatial_mv_pred_flag; + + uint8_t num_ref_idx_active_override_flag; + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; + + uint8_t ref_pic_list_modification_flag_l0; + uint8_t ref_pic_list_modification_flag_l1; + struct { + uint8_t modification_of_pic_nums_idc; + int32_t abs_diff_pic_num_minus1; + uint8_t long_term_pic_num; + } rplm_l0[H264_MAX_RPLM_COUNT], rplm_l1[H264_MAX_RPLM_COUNT]; + + uint8_t luma_log2_weight_denom; + uint8_t chroma_log2_weight_denom; + + uint8_t luma_weight_l0_flag[H264_MAX_REFS]; + int8_t luma_weight_l0[H264_MAX_REFS]; + int8_t luma_offset_l0[H264_MAX_REFS]; + uint8_t chroma_weight_l0_flag[H264_MAX_REFS]; + int8_t chroma_weight_l0[H264_MAX_REFS][2]; + int8_t chroma_offset_l0[H264_MAX_REFS][2]; + + uint8_t luma_weight_l1_flag[H264_MAX_REFS]; + int8_t luma_weight_l1[H264_MAX_REFS]; + int8_t luma_offset_l1[H264_MAX_REFS]; + uint8_t chroma_weight_l1_flag[H264_MAX_REFS]; + int8_t chroma_weight_l1[H264_MAX_REFS][2]; + int8_t chroma_offset_l1[H264_MAX_REFS][2]; + + uint8_t no_output_of_prior_pics_flag; + uint8_t long_term_reference_flag; + + uint8_t adaptive_ref_pic_marking_mode_flag; + struct { + uint8_t memory_management_control_operation; + int32_t difference_of_pic_nums_minus1; + uint8_t long_term_pic_num; + uint8_t long_term_frame_idx; + uint8_t max_long_term_frame_idx_plus1; + } mmco[H264_MAX_MMCO_COUNT]; + + uint8_t cabac_init_idc; + + int8_t slice_qp_delta; + + uint8_t sp_for_switch_flag; + int8_t slice_qs_delta; + + uint8_t disable_deblocking_filter_idc; + int8_t slice_alpha_c0_offset_div2; + int8_t slice_beta_offset_div2; + + uint16_t slice_group_change_cycle; +} H264RawSliceHeader; + +typedef struct H264RawSlice { + H264RawSliceHeader header; + + uint8_t *data; + size_t data_size; + int data_bit_start; +} H264RawSlice; + + +typedef struct CodedBitstreamH264Context { + // Reader/writer context in common with the H.265 implementation. + CodedBitstreamH2645Context common; + + // All currently available parameter sets. These are updated when + // any parameter set NAL unit is read/written with this context. + H264RawSPS *sps[H264_MAX_SPS_COUNT]; + H264RawPPS *pps[H264_MAX_PPS_COUNT]; + + // The currently active parameter sets. These are updated when any + // NAL unit refers to the relevant parameter set. These pointers + // must also be present in the arrays above. + const H264RawSPS *active_sps; + const H264RawPPS *active_pps; + + // The NAL unit type of the most recent normal slice. This is required + // to be able to read/write auxiliary slices, because IdrPicFlag is + // otherwise unknown. + uint8_t last_slice_nal_unit_type; +} CodedBitstreamH264Context; + + +#endif /* AVCODEC_CBS_H264_H */ diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c new file mode 100644 index 0000000000000..f03fd3ce7283b --- /dev/null +++ b/libavcodec/cbs_h2645.c @@ -0,0 +1,1010 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/avassert.h" + +#include "bytestream.h" +#include "cbs.h" +#include "cbs_internal.h" +#include "cbs_h264.h" +#include "golomb.h" +#include "h264.h" +#include "h264_sei.h" +#include "h2645_parse.h" + + +static int cbs_read_ue_golomb(CodedBitstreamContext *ctx, GetBitContext *gbc, + const char *name, uint32_t *write_to, + uint32_t range_min, uint32_t range_max) +{ + uint32_t value; + int position, i, j; + unsigned int k; + char bits[65]; + + position = get_bits_count(gbc); + + for (i = 0; i < 32; i++) { + if (get_bits_left(gbc) < i + 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid ue-golomb code at " + "%s: bitstream ended.\n", name); + return AVERROR_INVALIDDATA; + } + k = get_bits1(gbc); + bits[i] = k ? '1' : '0'; + if (k) + break; + } + if (i >= 32) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid ue-golomb code at " + "%s: more than 31 zeroes.\n", name); + return AVERROR_INVALIDDATA; + } + value = 1; + for (j = 0; j < i; j++) { + k = get_bits1(gbc); + bits[i + j + 1] = k ? '1' : '0'; + value = value << 1 | k; + } + bits[i + j + 1] = 0; + --value; + + if (ctx->trace_enable) + ff_cbs_trace_syntax_element(ctx, position, name, bits, value); + + if (value < range_min || value > range_max) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " + "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n", + name, value, range_min, range_max); + return AVERROR_INVALIDDATA; + } + + *write_to = value; + return 0; +} + +static int cbs_read_se_golomb(CodedBitstreamContext *ctx, GetBitContext *gbc, + const char *name, int32_t *write_to, + int32_t range_min, int32_t range_max) +{ + int32_t value; + int position, i, j; + unsigned int k; + uint32_t v; + char bits[65]; + + position = get_bits_count(gbc); + + for (i = 0; i < 32; i++) { + if (get_bits_left(gbc) < i + 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid se-golomb code at " + "%s: bitstream ended.\n", name); + return AVERROR_INVALIDDATA; + } + k = get_bits1(gbc); + bits[i] = k ? '1' : '0'; + if (k) + break; + } + if (i >= 32) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid se-golomb code at " + "%s: more than 31 zeroes.\n", name); + return AVERROR_INVALIDDATA; + } + v = 1; + for (j = 0; j < i; j++) { + k = get_bits1(gbc); + bits[i + j + 1] = k ? '1' : '0'; + v = v << 1 | k; + } + bits[i + j + 1] = 0; + if (v & 1) + value = -(int32_t)(v / 2); + else + value = v / 2; + + if (ctx->trace_enable) + ff_cbs_trace_syntax_element(ctx, position, name, bits, value); + + if (value < range_min || value > range_max) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " + "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n", + name, value, range_min, range_max); + return AVERROR_INVALIDDATA; + } + + *write_to = value; + return 0; +} + +static int cbs_write_ue_golomb(CodedBitstreamContext *ctx, PutBitContext *pbc, + const char *name, uint32_t value, + uint32_t range_min, uint32_t range_max) +{ + int len; + + if (value < range_min || value > range_max) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " + "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n", + name, value, range_min, range_max); + return AVERROR_INVALIDDATA; + } + av_assert0(value != UINT32_MAX); + + len = av_log2(value + 1); + if (put_bits_left(pbc) < 2 * len + 1) + return AVERROR(ENOSPC); + + if (ctx->trace_enable) { + char bits[65]; + int i; + + for (i = 0; i < len; i++) + bits[i] = '0'; + bits[len] = '1'; + for (i = 0; i < len; i++) + bits[len + i + 1] = (value + 1) >> (len - i - 1) & 1 ? '1' : '0'; + bits[len + len + 1] = 0; + + ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), name, bits, value); + } + + put_bits(pbc, len, 0); + if (len + 1 < 32) + put_bits(pbc, len + 1, value + 1); + else + put_bits32(pbc, value + 1); + + return 0; +} + +static int cbs_write_se_golomb(CodedBitstreamContext *ctx, PutBitContext *pbc, + const char *name, int32_t value, + int32_t range_min, int32_t range_max) +{ + int len; + uint32_t uvalue; + + if (value < range_min || value > range_max) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " + "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n", + name, value, range_min, range_max); + return AVERROR_INVALIDDATA; + } + av_assert0(value != INT32_MIN); + + if (value == 0) + uvalue = 0; + else if (value > 0) + uvalue = 2 * (uint32_t)value - 1; + else + uvalue = 2 * (uint32_t)-value; + + len = av_log2(uvalue + 1); + if (put_bits_left(pbc) < 2 * len + 1) + return AVERROR(ENOSPC); + + if (ctx->trace_enable) { + char bits[65]; + int i; + + for (i = 0; i < len; i++) + bits[i] = '0'; + bits[len] = '1'; + for (i = 0; i < len; i++) + bits[len + i + 1] = (uvalue + 1) >> (len - i - 1) & 1 ? '1' : '0'; + bits[len + len + 1] = 0; + + ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), name, bits, value); + } + + put_bits(pbc, len, 0); + if (len + 1 < 32) + put_bits(pbc, len + 1, uvalue + 1); + else + put_bits32(pbc, uvalue + 1); + + return 0; +} + +#define HEADER(name) do { \ + ff_cbs_trace_header(ctx, name); \ + } while (0) + +#define CHECK(call) do { \ + err = (call); \ + if (err < 0) \ + return err; \ + } while (0) + +#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name +#define FUNC_H264(rw, name) FUNC_NAME(rw, h264, name) + + +#define READ +#define READWRITE read +#define RWContext GetBitContext + +#define xu(width, name, var, range_min, range_max) do { \ + uint32_t value = range_min; \ + CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \ + &value, range_min, range_max)); \ + var = value; \ + } while (0) +#define xue(name, var, range_min, range_max) do { \ + uint32_t value = range_min; \ + CHECK(cbs_read_ue_golomb(ctx, rw, #name, \ + &value, range_min, range_max)); \ + var = value; \ + } while (0) +#define xse(name, var, range_min, range_max) do { \ + int32_t value = range_min; \ + CHECK(cbs_read_se_golomb(ctx, rw, #name, \ + &value, range_min, range_max)); \ + var = value; \ + } while (0) + + +#define u(width, name, range_min, range_max) \ + xu(width, name, current->name, range_min, range_max) +#define flag(name) u(1, name, 0, 1) +#define ue(name, range_min, range_max) \ + xue(name, current->name, range_min, range_max) +#define se(name, range_min, range_max) \ + xse(name, current->name, range_min, range_max) + +#define infer(name, value) do { \ + current->name = value; \ + } while (0) + +static int cbs_h2645_read_more_rbsp_data(GetBitContext *gbc) +{ + int bits_left = get_bits_left(gbc); + if (bits_left > 8) + return 1; + if (show_bits(gbc, bits_left) == 1 << (bits_left - 1)) + return 0; + return 1; +} + +#define more_rbsp_data(var) ((var) = cbs_h2645_read_more_rbsp_data(rw)) + +#define byte_alignment(rw) (get_bits_count(rw) % 8) + +#define allocate(name, size) do { \ + name = av_mallocz(size); \ + if (!name) \ + return AVERROR(ENOMEM); \ + } while (0) + +#define FUNC(name) FUNC_H264(READWRITE, name) +#include "cbs_h264_syntax_template.c" +#undef FUNC + +#undef READ +#undef READWRITE +#undef RWContext +#undef xu +#undef xue +#undef xse +#undef u +#undef flag +#undef ue +#undef se +#undef infer +#undef more_rbsp_data +#undef byte_alignment +#undef allocate + + +#define WRITE +#define READWRITE write +#define RWContext PutBitContext + +#define xu(width, name, var, range_min, range_max) do { \ + uint32_t value = var; \ + CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \ + value, range_min, range_max)); \ + } while (0) +#define xue(name, var, range_min, range_max) do { \ + uint32_t value = var; \ + CHECK(cbs_write_ue_golomb(ctx, rw, #name, \ + value, range_min, range_max)); \ + } while (0) +#define xse(name, var, range_min, range_max) do { \ + int32_t value = var; \ + CHECK(cbs_write_se_golomb(ctx, rw, #name, \ + value, range_min, range_max)); \ + } while (0) + +#define u(width, name, range_min, range_max) \ + xu(width, name, current->name, range_min, range_max) +#define flag(name) u(1, name, 0, 1) +#define ue(name, range_min, range_max) \ + xue(name, current->name, range_min, range_max) +#define se(name, range_min, range_max) \ + xse(name, current->name, range_min, range_max) + +#define infer(name, value) do { \ + if (current->name != (value)) { \ + av_log(ctx->log_ctx, AV_LOG_WARNING, "Warning: " \ + "%s does not match inferred value: " \ + "%"PRId64", but should be %"PRId64".\n", \ + #name, (int64_t)current->name, (int64_t)(value)); \ + } \ + } while (0) + +#define more_rbsp_data(var) (var) + +#define byte_alignment(rw) (put_bits_count(rw) % 8) + +#define allocate(name, size) do { \ + if (!name) { \ + av_log(ctx->log_ctx, AV_LOG_ERROR, "%s must be set " \ + "for writing.\n", #name); \ + return AVERROR_INVALIDDATA; \ + } \ + } while (0) + +#define FUNC(name) FUNC_H264(READWRITE, name) +#include "cbs_h264_syntax_template.c" +#undef FUNC + +#undef WRITE +#undef READWRITE +#undef RWContext +#undef xu +#undef xue +#undef xse +#undef u +#undef flag +#undef ue +#undef se +#undef infer +#undef more_rbsp_data +#undef byte_alignment +#undef allocate + + +static void cbs_h264_free_sei(H264RawSEI *sei) +{ + int i; + for (i = 0; i < sei->payload_count; i++) { + H264RawSEIPayload *payload = &sei->payload[i]; + + switch (payload->payload_type) { + case H264_SEI_TYPE_BUFFERING_PERIOD: + case H264_SEI_TYPE_PIC_TIMING: + case H264_SEI_TYPE_RECOVERY_POINT: + case H264_SEI_TYPE_DISPLAY_ORIENTATION: + break; + case H264_SEI_TYPE_USER_DATA_REGISTERED: + av_freep(&payload->payload.user_data_registered.data); + break; + case H264_SEI_TYPE_USER_DATA_UNREGISTERED: + av_freep(&payload->payload.user_data_unregistered.data); + break; + default: + av_freep(&payload->payload.other.data); + break; + } + } +} + +static void cbs_h264_free_slice(H264RawSlice *slice) +{ + av_freep(&slice->data); +} + +static void cbs_h264_free_nal_unit(CodedBitstreamUnit *unit) +{ + switch (unit->type) { + case H264_NAL_SEI: + cbs_h264_free_sei(unit->content); + break; + case H264_NAL_IDR_SLICE: + case H264_NAL_SLICE: + cbs_h264_free_slice(unit->content); + break; + } + av_freep(&unit->content); +} + +static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const H2645Packet *packet) +{ + int err, i; + + for (i = 0; i < packet->nb_nals; i++) { + const H2645NAL *nal = &packet->nals[i]; + size_t size = nal->size; + uint8_t *data; + + // Remove trailing zeroes. + while (size > 0 && nal->data[size - 1] == 0) + --size; + av_assert0(size > 0); + + data = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!data) + return AVERROR(ENOMEM); + memcpy(data, nal->data, size); + memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + err = ff_cbs_insert_unit_data(ctx, frag, -1, nal->type, + data, size); + if (err < 0) { + av_freep(&data); + return err; + } + } + + return 0; +} + +static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int header) +{ + enum AVCodecID codec_id = ctx->codec->codec_id; + CodedBitstreamH2645Context *priv = ctx->priv_data; + GetByteContext gbc; + int err; + + av_assert0(frag->data && frag->nb_units == 0); + if (frag->data_size == 0) + return 0; + + if (header && frag->data[0] && codec_id == AV_CODEC_ID_H264) { + // AVCC header. + size_t size, start, end; + int i, count, version; + + priv->mp4 = 1; + + bytestream2_init(&gbc, frag->data, frag->data_size); + + if (bytestream2_get_bytes_left(&gbc) < 6) + return AVERROR_INVALIDDATA; + + version = bytestream2_get_byte(&gbc); + if (version != 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid AVCC header: " + "first byte %u.", version); + return AVERROR_INVALIDDATA; + } + + bytestream2_skip(&gbc, 3); + priv->nal_length_size = (bytestream2_get_byte(&gbc) & 3) + 1; + + // SPS array. + count = bytestream2_get_byte(&gbc) & 0x1f; + start = bytestream2_tell(&gbc); + for (i = 0; i < count; i++) { + if (bytestream2_get_bytes_left(&gbc) < 2 * (count - i)) + return AVERROR_INVALIDDATA; + size = bytestream2_get_be16(&gbc); + if (bytestream2_get_bytes_left(&gbc) < size) + return AVERROR_INVALIDDATA; + bytestream2_skip(&gbc, size); + } + end = bytestream2_tell(&gbc); + + err = ff_h2645_packet_split(&priv->read_packet, + frag->data + start, end - start, + ctx->log_ctx, 1, 2, AV_CODEC_ID_H264, 1); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split AVCC SPS array.\n"); + return err; + } + err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet); + if (err < 0) + return err; + + // PPS array. + count = bytestream2_get_byte(&gbc); + start = bytestream2_tell(&gbc); + for (i = 0; i < count; i++) { + if (bytestream2_get_bytes_left(&gbc) < 2 * (count - i)) + return AVERROR_INVALIDDATA; + size = bytestream2_get_be16(&gbc); + if (bytestream2_get_bytes_left(&gbc) < size) + return AVERROR_INVALIDDATA; + bytestream2_skip(&gbc, size); + } + end = bytestream2_tell(&gbc); + + err = ff_h2645_packet_split(&priv->read_packet, + frag->data + start, end - start, + ctx->log_ctx, 1, 2, AV_CODEC_ID_H264, 1); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split AVCC PPS array.\n"); + return err; + } + err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet); + if (err < 0) + return err; + + if (bytestream2_get_bytes_left(&gbc) > 0) { + av_log(ctx->log_ctx, AV_LOG_WARNING, "%u bytes left at end of AVCC " + "header.\n", bytestream2_get_bytes_left(&gbc)); + } + + } else { + // Annex B, or later MP4 with already-known parameters. + + err = ff_h2645_packet_split(&priv->read_packet, + frag->data, frag->data_size, + ctx->log_ctx, + priv->mp4, priv->nal_length_size, + codec_id, 1); + if (err < 0) + return err; + + err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet); + if (err < 0) + return err; + } + + return 0; +} + +#define cbs_h2645_replace_ps(h26n, ps_name, ps_var, id_element) \ +static int cbs_h26 ## h26n ## _replace_ ## ps_var(CodedBitstreamContext *ctx, \ + const H26 ## h26n ## Raw ## ps_name *ps_var) \ +{ \ + CodedBitstreamH26 ## h26n ## Context *priv = ctx->priv_data; \ + unsigned int id = ps_var->id_element; \ + if (id > FF_ARRAY_ELEMS(priv->ps_var)) { \ + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid " #ps_name \ + " id : %d.\n", id); \ + return AVERROR_INVALIDDATA; \ + } \ + av_freep(&priv->ps_var[id]); \ + priv->ps_var[id] = av_malloc(sizeof(*ps_var)); \ + if (!priv->ps_var[id]) \ + return AVERROR(ENOMEM); \ + memcpy(priv->ps_var[id], ps_var, sizeof(*ps_var)); \ + return 0; \ +} + +cbs_h2645_replace_ps(4, SPS, sps, seq_parameter_set_id) +cbs_h2645_replace_ps(4, PPS, pps, pic_parameter_set_id) + +static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + GetBitContext gbc; + int err; + + err = init_get_bits(&gbc, unit->data, 8 * unit->data_size); + if (err < 0) + return err; + + switch (unit->type) { + case H264_NAL_SPS: + { + H264RawSPS *sps; + + sps = av_mallocz(sizeof(*sps)); + if (!sps) + return AVERROR(ENOMEM); + err = cbs_h264_read_sps(ctx, &gbc, sps); + if (err >= 0) + err = cbs_h264_replace_sps(ctx, sps); + if (err < 0) { + av_free(sps); + return err; + } + + unit->content = sps; + } + break; + + case H264_NAL_SPS_EXT: + { + H264RawSPSExtension *sps_ext; + + sps_ext = av_mallocz(sizeof(*sps_ext)); + if (!sps_ext) + return AVERROR(ENOMEM); + err = cbs_h264_read_sps_extension(ctx, &gbc, sps_ext); + if (err < 0) { + av_free(sps_ext); + return err; + } + + unit->content = sps_ext; + } + break; + + case H264_NAL_PPS: + { + H264RawPPS *pps; + + pps = av_mallocz(sizeof(*pps)); + if (!pps) + return AVERROR(ENOMEM); + err = cbs_h264_read_pps(ctx, &gbc, pps); + if (err >= 0) + err = cbs_h264_replace_pps(ctx, pps); + if (err < 0) { + av_free(pps); + return err; + } + + unit->content = pps; + } + break; + + case H264_NAL_SLICE: + case H264_NAL_IDR_SLICE: + case H264_NAL_AUXILIARY_SLICE: + { + H264RawSlice *slice; + int pos, len; + + slice = av_mallocz(sizeof(*slice)); + if (!slice) + return AVERROR(ENOMEM); + err = cbs_h264_read_slice_header(ctx, &gbc, &slice->header); + if (err < 0) { + av_free(slice); + return err; + } + + pos = get_bits_count(&gbc); + len = unit->data_size; + if (!unit->data[len - 1]) { + int z; + for (z = 0; z < len && !unit->data[len - z - 1]; z++); + av_log(ctx->log_ctx, AV_LOG_DEBUG, "Deleted %d trailing zeroes " + "from slice data.\n", z); + len -= z; + } + + slice->data_size = len - pos / 8; + slice->data = av_malloc(slice->data_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!slice->data) { + av_free(slice); + return AVERROR(ENOMEM); + } + memcpy(slice->data, + unit->data + pos / 8, slice->data_size); + memset(slice->data + slice->data_size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); + slice->data_bit_start = pos % 8; + + unit->content = slice; + } + break; + + case H264_NAL_AUD: + { + H264RawAUD *aud; + + aud = av_mallocz(sizeof(*aud)); + if (!aud) + return AVERROR(ENOMEM); + err = cbs_h264_read_aud(ctx, &gbc, aud); + if (err < 0) { + av_free(aud); + return err; + } + + unit->content = aud; + } + break; + + case H264_NAL_SEI: + { + H264RawSEI *sei; + + sei = av_mallocz(sizeof(*sei)); + if (!sei) + return AVERROR(ENOMEM); + err = cbs_h264_read_sei(ctx, &gbc, sei); + if (err < 0) { + cbs_h264_free_sei(sei); + return err; + } + + unit->content = sei; + } + break; + + default: + return AVERROR(ENOSYS); + } + + return 0; +} + +static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + PutBitContext *pbc) +{ + int err; + + switch (unit->type) { + case H264_NAL_SPS: + { + H264RawSPS *sps = unit->content; + + err = cbs_h264_write_sps(ctx, pbc, sps); + if (err < 0) + return err; + + err = cbs_h264_replace_sps(ctx, sps); + if (err < 0) + return err; + } + break; + + case H264_NAL_SPS_EXT: + { + H264RawSPSExtension *sps_ext; + + err = cbs_h264_write_sps_extension(ctx, pbc, sps_ext); + if (err < 0) + return err; + } + break; + + case H264_NAL_PPS: + { + H264RawPPS *pps = unit->content; + + err = cbs_h264_write_pps(ctx, pbc, pps); + if (err < 0) + return err; + + err = cbs_h264_replace_pps(ctx, pps); + if (err < 0) + return err; + } + break; + + case H264_NAL_SLICE: + case H264_NAL_IDR_SLICE: + { + H264RawSlice *slice = unit->content; + GetBitContext gbc; + int bits_left, end, zeroes; + + err = cbs_h264_write_slice_header(ctx, pbc, &slice->header); + if (err < 0) + return err; + + if (slice->data) { + if (slice->data_size * 8 + 8 > put_bits_left(pbc)) + return AVERROR(ENOSPC); + + init_get_bits(&gbc, slice->data, slice->data_size * 8); + skip_bits_long(&gbc, slice->data_bit_start); + + // Copy in two-byte blocks, but stop before copying the + // rbsp_stop_one_bit in the final byte. + while (get_bits_left(&gbc) > 23) + put_bits(pbc, 16, get_bits(&gbc, 16)); + + bits_left = get_bits_left(&gbc); + end = get_bits(&gbc, bits_left); + + // rbsp_stop_one_bit must be present here. + av_assert0(end); + zeroes = ff_ctz(end); + if (bits_left > zeroes + 1) + put_bits(pbc, bits_left - zeroes - 1, + end >> (zeroes + 1)); + put_bits(pbc, 1, 1); + while (put_bits_count(pbc) % 8 != 0) + put_bits(pbc, 1, 0); + } else { + // No slice data - that was just the header. + // (Bitstream may be unaligned!) + } + } + break; + + case H264_NAL_AUD: + { + err = cbs_h264_write_aud(ctx, pbc, unit->content); + if (err < 0) + return err; + } + break; + + case H264_NAL_SEI: + { + err = cbs_h264_write_sei(ctx, pbc, unit->content); + if (err < 0) + return err; + } + break; + + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for " + "NAL unit type %"PRIu32".\n", unit->type); + return AVERROR_PATCHWELCOME; + } + + return 0; +} + +static int cbs_h2645_write_nal_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + CodedBitstreamH2645Context *priv = ctx->priv_data; + enum AVCodecID codec_id = ctx->codec->codec_id; + PutBitContext pbc; + int err; + + if (!priv->write_buffer) { + // Initial write buffer size is 1MB. + priv->write_buffer_size = 1024 * 1024; + + reallocate_and_try_again: + err = av_reallocp(&priv->write_buffer, priv->write_buffer_size); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a " + "sufficiently large write buffer (last attempt " + "%zu bytes).\n", priv->write_buffer_size); + return err; + } + } + + init_put_bits(&pbc, priv->write_buffer, priv->write_buffer_size); + + err = cbs_h264_write_nal_unit(ctx, unit, &pbc); + + if (err == AVERROR(ENOSPC)) { + // Overflow. + priv->write_buffer_size *= 2; + goto reallocate_and_try_again; + } + // Overflow but we didn't notice. + av_assert0(put_bits_count(&pbc) <= 8 * priv->write_buffer_size); + + if (err < 0) { + // Write failed for some other reason. + return err; + } + + if (put_bits_count(&pbc) % 8) + unit->data_bit_padding = 8 - put_bits_count(&pbc) % 8; + else + unit->data_bit_padding = 0; + + unit->data_size = (put_bits_count(&pbc) + 7) / 8; + flush_put_bits(&pbc); + + err = av_reallocp(&unit->data, unit->data_size); + if (err < 0) + return err; + + memcpy(unit->data, priv->write_buffer, unit->data_size); + + return 0; +} + +static int cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag) +{ + uint8_t *data; + size_t max_size, dp, sp; + int err, i, zero_run; + + for (i = 0; i < frag->nb_units; i++) { + // Data should already all have been written when we get here. + av_assert0(frag->units[i].data); + } + + max_size = 0; + for (i = 0; i < frag->nb_units; i++) { + // Start code + content with worst-case emulation prevention. + max_size += 3 + frag->units[i].data_size * 3 / 2; + } + + data = av_malloc(max_size); + if (!data) + return AVERROR(ENOMEM); + + dp = 0; + for (i = 0; i < frag->nb_units; i++) { + CodedBitstreamUnit *unit = &frag->units[i]; + + if (unit->data_bit_padding > 0) { + if (i < frag->nb_units - 1) + av_log(ctx->log_ctx, AV_LOG_WARNING, "Probably invalid " + "unaligned padding on non-final NAL unit.\n"); + else + frag->data_bit_padding = unit->data_bit_padding; + } + + if (unit->type == H264_NAL_SPS || + unit->type == H264_NAL_PPS || + i == 0 /* (Assume this is the start of an access unit.) */) { + // zero_byte + data[dp++] = 0; + } + // start_code_prefix_one_3bytes + data[dp++] = 0; + data[dp++] = 0; + data[dp++] = 1; + + zero_run = 0; + for (sp = 0; sp < unit->data_size; sp++) { + if (zero_run < 2) { + if (unit->data[sp] == 0) + ++zero_run; + else + zero_run = 0; + } else { + if ((unit->data[sp] & ~3) == 0) { + // emulation_prevention_three_byte + data[dp++] = 3; + } + zero_run = unit->data[sp] == 0; + } + data[dp++] = unit->data[sp]; + } + } + + av_assert0(dp <= max_size); + err = av_reallocp(&data, dp); + if (err) + return err; + + frag->data = data; + frag->data_size = dp; + + return 0; +} + +static void cbs_h264_close(CodedBitstreamContext *ctx) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + int i; + + ff_h2645_packet_uninit(&h264->common.read_packet); + + av_freep(&h264->common.write_buffer); + + for (i = 0; i < FF_ARRAY_ELEMS(h264->sps); i++) + av_freep(&h264->sps[i]); + for (i = 0; i < FF_ARRAY_ELEMS(h264->pps); i++) + av_freep(&h264->pps[i]); +} + +const CodedBitstreamType ff_cbs_type_h264 = { + .codec_id = AV_CODEC_ID_H264, + + .priv_data_size = sizeof(CodedBitstreamH264Context), + + .split_fragment = &cbs_h2645_split_fragment, + .read_unit = &cbs_h264_read_nal_unit, + .write_unit = &cbs_h2645_write_nal_unit, + .assemble_fragment = &cbs_h2645_assemble_fragment, + + .free_unit = &cbs_h264_free_nal_unit, + .close = &cbs_h264_close, +}; diff --git a/libavcodec/cbs_h2645.h b/libavcodec/cbs_h2645.h new file mode 100644 index 0000000000000..f4cf65bdde500 --- /dev/null +++ b/libavcodec/cbs_h2645.h @@ -0,0 +1,43 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_H2645_H +#define AVCODEC_CBS_H2645_H + +#include +#include + +#include "h2645_parse.h" + + +typedef struct CodedBitstreamH2645Context { + // If set, the stream being read is in MP4 (AVCC/HVCC) format. If not + // set, the stream is assumed to be in annex B format. + int mp4; + // Size in bytes of the NAL length field for MP4 format. + int nal_length_size; + // Packet reader. + H2645Packet read_packet; + + // Write buffer + uint8_t *write_buffer; + size_t write_buffer_size; +} CodedBitstreamH2645Context; + + +#endif /* AVCODEC_CBS_H2645_H */ diff --git a/libavcodec/cbs_h264_syntax_template.c b/libavcodec/cbs_h264_syntax_template.c new file mode 100644 index 0000000000000..8303acbdc459a --- /dev/null +++ b/libavcodec/cbs_h264_syntax_template.c @@ -0,0 +1,1230 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static int FUNC(rbsp_trailing_bits)(CodedBitstreamContext *ctx, RWContext *rw) +{ + int err; + av_unused int one = 1, zero = 0; + xu(1, rbsp_stop_one_bit, one, 1, 1); + while (byte_alignment(rw) != 0) + xu(1, rbsp_alignment_zero_bit, zero, 0, 0); + + return 0; +} + +static int FUNC(nal_unit_header)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawNALUnitHeader *current, + uint32_t valid_type_mask) +{ + int err; + + u(1, forbidden_zero_bit, 0, 0); + u(2, nal_ref_idc, 0, 3); + u(5, nal_unit_type, 0, 31); + + if (!(1 << current->nal_unit_type & valid_type_mask)) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid NAL unit type %d.\n", + current->nal_unit_type); + return AVERROR_INVALIDDATA; + } + + if (current->nal_unit_type == 14 || + current->nal_unit_type == 20 || + current->nal_unit_type == 21) { + if (current->nal_unit_type != 21) + flag(svc_extension_flag); + else + flag(avc_3d_extension_flag); + + if (current->svc_extension_flag) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SVC not supported.\n"); + return AVERROR_PATCHWELCOME; + + } else if (current->avc_3d_extension_flag) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "3DAVC not supported.\n"); + return AVERROR_PATCHWELCOME; + + } else { + av_log(ctx->log_ctx, AV_LOG_ERROR, "MVC not supported.\n"); + return AVERROR_PATCHWELCOME; + } + } + + return 0; +} + +static int FUNC(scaling_list)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawScalingList *current, + int size_of_scaling_list) +{ + int err, i, scale; + + scale = 8; + for (i = 0; i < size_of_scaling_list; i++) { + xse(delta_scale, current->delta_scale[i], -128, +127); + scale = (scale + current->delta_scale[i] + 256) % 256; + if (scale == 0) + break; + } + + return 0; +} + +static int FUNC(hrd_parameters)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawHRD *current) +{ + int err, i; + + ue(cpb_cnt_minus1, 0, 31); + u(4, bit_rate_scale, 0, 15); + u(4, cpb_size_scale, 0, 15); + + for (i = 0; i <= current->cpb_cnt_minus1; i++) { + ue(bit_rate_value_minus1[i], 0, UINT32_MAX - 1); + ue(cpb_size_value_minus1[i], 0, UINT32_MAX - 1); + flag(cbr_flag[i]); + } + + u(5, initial_cpb_removal_delay_length_minus1, 0, 31); + u(5, cpb_removal_delay_length_minus1, 0, 31); + u(5, dpb_output_delay_length_minus1, 0, 31); + u(5, time_offset_length, 0, 31); + + return 0; +} + +static int FUNC(vui_parameters)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawVUI *current, H264RawSPS *sps) +{ + int err; + + flag(aspect_ratio_info_present_flag); + if (current->aspect_ratio_info_present_flag) { + u(8, aspect_ratio_idc, 0, 255); + if (current->aspect_ratio_idc == 255) { + u(16, sar_width, 0, 65535); + u(16, sar_height, 0, 65535); + } + } else { + infer(aspect_ratio_idc, 0); + } + + flag(overscan_info_present_flag); + if (current->overscan_info_present_flag) + flag(overscan_appropriate_flag); + + flag(video_signal_type_present_flag); + if (current->video_signal_type_present_flag) { + u(3, video_format, 0, 7); + flag(video_full_range_flag); + flag(colour_description_present_flag); + if (current->colour_description_present_flag) { + u(8, colour_primaries, 0, 255); + u(8, transfer_characteristics, 0, 255); + u(8, matrix_coefficients, 0, 255); + } + } else { + infer(video_format, 5); + infer(video_full_range_flag, 0); + infer(colour_primaries, 2); + infer(transfer_characteristics, 2); + infer(matrix_coefficients, 2); + } + + flag(chroma_loc_info_present_flag); + if (current->chroma_loc_info_present_flag) { + ue(chroma_sample_loc_type_top_field, 0, 5); + ue(chroma_sample_loc_type_bottom_field, 0, 5); + } else { + infer(chroma_sample_loc_type_top_field, 0); + infer(chroma_sample_loc_type_bottom_field, 0); + } + + flag(timing_info_present_flag); + if (current->timing_info_present_flag) { + u(32, num_units_in_tick, 1, UINT32_MAX); + u(32, time_scale, 1, UINT32_MAX); + flag(fixed_frame_rate_flag); + } else { + infer(fixed_frame_rate_flag, 0); + } + + flag(nal_hrd_parameters_present_flag); + if (current->nal_hrd_parameters_present_flag) + CHECK(FUNC(hrd_parameters)(ctx, rw, ¤t->nal_hrd_parameters)); + + flag(vcl_hrd_parameters_present_flag); + if (current->vcl_hrd_parameters_present_flag) + CHECK(FUNC(hrd_parameters)(ctx, rw, ¤t->vcl_hrd_parameters)); + + if (current->nal_hrd_parameters_present_flag || + current->vcl_hrd_parameters_present_flag) + flag(low_delay_hrd_flag); + else + infer(low_delay_hrd_flag, 1 - current->fixed_frame_rate_flag); + + flag(pic_struct_present_flag); + + flag(bitstream_restriction_flag); + if (current->bitstream_restriction_flag) { + flag(motion_vectors_over_pic_boundaries_flag); + ue(max_bytes_per_pic_denom, 0, 16); + ue(max_bits_per_mb_denom, 0, 16); + ue(log2_max_mv_length_horizontal, 0, 16); + ue(log2_max_mv_length_vertical, 0, 16); + ue(max_num_reorder_frames, 0, H264_MAX_DPB_FRAMES); + ue(max_dec_frame_buffering, 0, H264_MAX_DPB_FRAMES); + } else { + infer(motion_vectors_over_pic_boundaries_flag, 1); + infer(max_bytes_per_pic_denom, 2); + infer(max_bits_per_mb_denom, 1); + infer(log2_max_mv_length_horizontal, 16); + infer(log2_max_mv_length_vertical, 16); + + if ((sps->profile_idc == 44 || sps->profile_idc == 86 || + sps->profile_idc == 110 || sps->profile_idc == 110 || + sps->profile_idc == 122 || sps->profile_idc == 244) && + sps->constraint_set3_flag) { + infer(max_num_reorder_frames, 0); + infer(max_dec_frame_buffering, 0); + } else { + infer(max_num_reorder_frames, H264_MAX_DPB_FRAMES); + infer(max_dec_frame_buffering, H264_MAX_DPB_FRAMES); + } + } + + return 0; +} + +static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSPS *current) +{ + int err, i; + + HEADER("Sequence Parameter Set"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + 1 << H264_NAL_SPS)); + + u(8, profile_idc, 0, 255); + + flag(constraint_set0_flag); + flag(constraint_set1_flag); + flag(constraint_set2_flag); + flag(constraint_set3_flag); + flag(constraint_set4_flag); + flag(constraint_set5_flag); + + u(2, reserved_zero_2bits, 0, 0); + + u(8, level_idc, 0, 255); + + ue(seq_parameter_set_id, 0, 31); + + if (current->profile_idc == 100 || current->profile_idc == 110 || + current->profile_idc == 122 || current->profile_idc == 244 || + current->profile_idc == 44 || current->profile_idc == 83 || + current->profile_idc == 86 || current->profile_idc == 118 || + current->profile_idc == 128 || current->profile_idc == 138) { + ue(chroma_format_idc, 0, 3); + + if (current->chroma_format_idc == 3) + flag(separate_colour_plane_flag); + else + infer(separate_colour_plane_flag, 0); + + ue(bit_depth_luma_minus8, 0, 6); + ue(bit_depth_chroma_minus8, 0, 6); + + flag(qpprime_y_zero_transform_bypass_flag); + + flag(seq_scaling_matrix_present_flag); + if (current->seq_scaling_matrix_present_flag) { + for (i = 0; i < ((current->chroma_format_idc != 3) ? 8 : 12); i++) { + flag(seq_scaling_list_present_flag[i]); + if (current->seq_scaling_list_present_flag[i]) { + if (i < 6) + CHECK(FUNC(scaling_list)(ctx, rw, + ¤t->scaling_list_4x4[i], + 16)); + else + CHECK(FUNC(scaling_list)(ctx, rw, + ¤t->scaling_list_8x8[i - 6], + 64)); + } + } + } + } else { + infer(chroma_format_idc, current->profile_idc == 183 ? 0 : 1); + + infer(separate_colour_plane_flag, 0); + infer(bit_depth_luma_minus8, 0); + infer(bit_depth_chroma_minus8, 0); + } + + ue(log2_max_frame_num_minus4, 0, 12); + ue(pic_order_cnt_type, 0, 2); + + if (current->pic_order_cnt_type == 0) { + ue(log2_max_pic_order_cnt_lsb_minus4, 0, 12); + } else if (current->pic_order_cnt_type == 1) { + flag(delta_pic_order_always_zero_flag); + se(offset_for_non_ref_pic, INT32_MIN + 1, INT32_MAX); + se(offset_for_top_to_bottom_field, INT32_MIN + 1, INT32_MAX); + ue(num_ref_frames_in_pic_order_cnt_cycle, 0, 255); + + for (i = 0; i < current->num_ref_frames_in_pic_order_cnt_cycle; i++) + se(offset_for_ref_frame[i], INT32_MIN + 1, INT32_MAX); + } + + ue(max_num_ref_frames, 0, H264_MAX_DPB_FRAMES); + flag(gaps_in_frame_num_allowed_flag); + + ue(pic_width_in_mbs_minus1, 0, H264_MAX_MB_WIDTH); + ue(pic_height_in_map_units_minus1, 0, H264_MAX_MB_HEIGHT); + + flag(frame_mbs_only_flag); + if (!current->frame_mbs_only_flag) + flag(mb_adaptive_frame_field_flag); + + flag(direct_8x8_inference_flag); + + flag(frame_cropping_flag); + if (current->frame_cropping_flag) { + ue(frame_crop_left_offset, 0, H264_MAX_WIDTH); + ue(frame_crop_right_offset, 0, H264_MAX_WIDTH); + ue(frame_crop_top_offset, 0, H264_MAX_HEIGHT); + ue(frame_crop_bottom_offset, 0, H264_MAX_HEIGHT); + } + + flag(vui_parameters_present_flag); + if (current->vui_parameters_present_flag) + CHECK(FUNC(vui_parameters)(ctx, rw, ¤t->vui, current)); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(sps_extension)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSPSExtension *current) +{ + int err; + + HEADER("Sequence Parameter Set Extension"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + 1 << H264_NAL_SPS_EXT)); + + ue(seq_parameter_set_id, 0, 31); + + ue(aux_format_idc, 0, 3); + + if (current->aux_format_idc != 0) { + int bits; + + ue(bit_depth_aux_minus8, 0, 4); + flag(alpha_incr_flag); + + bits = current->bit_depth_aux_minus8 + 9; + u(bits, alpha_opaque_value, 0, (1 << bits) - 1); + u(bits, alpha_transparent_value, 0, (1 << bits) - 1); + } + + flag(additional_extension_flag); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(pps)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawPPS *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps; + int err, i; + + HEADER("Picture Parameter Set"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + 1 << H264_NAL_PPS)); + + ue(pic_parameter_set_id, 0, 255); + ue(seq_parameter_set_id, 0, 31); + + sps = h264->sps[current->seq_parameter_set_id]; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SPS id %d not available.\n", + current->seq_parameter_set_id); + return AVERROR_INVALIDDATA; + } + + flag(entropy_coding_mode_flag); + flag(bottom_field_pic_order_in_frame_present_flag); + + ue(num_slice_groups_minus1, 0, 7); + if (current->num_slice_groups_minus1 > 0) { + unsigned int pic_size; + int iGroup; + + pic_size = (sps->pic_width_in_mbs_minus1 + 1) * + (sps->pic_height_in_map_units_minus1 + 1); + + ue(slice_group_map_type, 0, 6); + + if (current->slice_group_map_type == 0) { + for (iGroup = 0; iGroup <= current->num_slice_groups_minus1; iGroup++) + ue(run_length_minus1[iGroup], 0, pic_size - 1); + + } else if (current->slice_group_map_type == 2) { + for (iGroup = 0; iGroup < current->num_slice_groups_minus1; iGroup++) { + ue(top_left[iGroup], 0, pic_size - 1); + ue(bottom_right[iGroup], current->top_left[iGroup], pic_size - 1); + } + } else if (current->slice_group_map_type == 3 || + current->slice_group_map_type == 4 || + current->slice_group_map_type == 5) { + flag(slice_group_change_direction_flag); + ue(slice_group_change_rate_minus1, 0, pic_size - 1); + } else if (current->slice_group_map_type == 6) { + ue(pic_size_in_map_units_minus1, pic_size - 1, pic_size - 1); + for (i = 0; i <= current->pic_size_in_map_units_minus1; i++) + u(av_log2(2 * current->num_slice_groups_minus1 + 1), + slice_group_id[i], 0, current->num_slice_groups_minus1); + } + } + + ue(num_ref_idx_l0_default_active_minus1, 0, 31); + ue(num_ref_idx_l1_default_active_minus1, 0, 31); + + flag(weighted_pred_flag); + u(2, weighted_bipred_idc, 0, 2); + + se(pic_init_qp_minus26, -26 - 6 * sps->bit_depth_luma_minus8, +25); + se(pic_init_qs_minus26, -26, +25); + se(chroma_qp_index_offset, -12, +12); + + flag(deblocking_filter_control_present_flag); + flag(constrained_intra_pred_flag); + flag(redundant_pic_cnt_present_flag); + + if (more_rbsp_data(current->more_rbsp_data)) + { + flag(transform_8x8_mode_flag); + + flag(pic_scaling_matrix_present_flag); + if (current->pic_scaling_matrix_present_flag) { + for (i = 0; i < 6 + (((sps->chroma_format_idc != 3) ? 2 : 6) * + current->transform_8x8_mode_flag); i++) { + flag(pic_scaling_list_present_flag[i]); + if (current->pic_scaling_list_present_flag[i]) { + if (i < 6) + CHECK(FUNC(scaling_list)(ctx, rw, + ¤t->scaling_list_4x4[i], + 16)); + else + CHECK(FUNC(scaling_list)(ctx, rw, + ¤t->scaling_list_8x8[i - 6], + 64)); + } + } + } + + se(second_chroma_qp_index_offset, -12, +12); + } else { + infer(transform_8x8_mode_flag, 0); + infer(pic_scaling_matrix_present_flag, 0); + infer(second_chroma_qp_index_offset, current->chroma_qp_index_offset); + } + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIBufferingPeriod *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps; + int err, i, length; + + ue(seq_parameter_set_id, 0, 31); + + sps = h264->sps[current->seq_parameter_set_id]; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SPS id %d not available.\n", + current->seq_parameter_set_id); + return AVERROR_INVALIDDATA; + } + h264->active_sps = sps; + + if (sps->vui.nal_hrd_parameters_present_flag) { + for (i = 0; i <= sps->vui.nal_hrd_parameters.cpb_cnt_minus1; i++) { + length = sps->vui.nal_hrd_parameters.initial_cpb_removal_delay_length_minus1 + 1; + xu(length, initial_cpb_removal_delay[SchedSelIdx], + current->nal.initial_cpb_removal_delay[i], + 0, (1 << (uint64_t)length) - 1); + xu(length, initial_cpb_removal_delay_offset[SchedSelIdx], + current->nal.initial_cpb_removal_delay_offset[i], + 0, (1 << (uint64_t)length) - 1); + } + } + + if (sps->vui.vcl_hrd_parameters_present_flag) { + for (i = 0; i <= sps->vui.vcl_hrd_parameters.cpb_cnt_minus1; i++) { + length = sps->vui.vcl_hrd_parameters.initial_cpb_removal_delay_length_minus1 + 1; + xu(length, initial_cpb_removal_delay[SchedSelIdx], + current->vcl.initial_cpb_removal_delay[i], + 0, (1 << (uint64_t)length) - 1); + xu(length, initial_cpb_removal_delay_offset[SchedSelIdx], + current->vcl.initial_cpb_removal_delay_offset[i], + 0, (1 << (uint64_t)length) - 1); + } + } + + return 0; +} + +static int FUNC(sei_pic_timestamp)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIPicTimestamp *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps; + uint8_t time_offset_length; + int err; + + u(2, ct_type, 0, 2); + flag(nuit_field_based_flag); + u(5, counting_type, 0, 6); + flag(full_timestamp_flag); + flag(discontinuity_flag); + flag(cnt_dropped_flag); + u(8, n_frames, 0, 255); + if (current->full_timestamp_flag) { + u(6, seconds_value, 0, 59); + u(6, minutes_value, 0, 59); + u(5, hours_value, 0, 23); + } else { + flag(seconds_flag); + if (current->seconds_flag) { + u(6, seconds_value, 0, 59); + flag(minutes_flag); + if (current->minutes_flag) { + u(6, minutes_value, 0, 59); + flag(hours_flag); + if (current->hours_flag) + u(5, hours_value, 0, 23); + } + } + } + + sps = h264->active_sps; + if (sps->vui.nal_hrd_parameters_present_flag) + time_offset_length = sps->vui.nal_hrd_parameters.time_offset_length; + else if (sps->vui.vcl_hrd_parameters_present_flag) + time_offset_length = sps->vui.vcl_hrd_parameters.time_offset_length; + else + time_offset_length = 24; + + if (time_offset_length > 0) + u(time_offset_length, time_offset, + 0, (1 << (uint64_t)time_offset_length) - 1); + else + infer(time_offset, 0); + + return 0; +} + +static int FUNC(sei_pic_timing)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIPicTiming *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps; + int err; + + sps = h264->active_sps; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "No active SPS for pic_timing.\n"); + return AVERROR_INVALIDDATA; + } + + if (sps->vui.nal_hrd_parameters_present_flag || + sps->vui.vcl_hrd_parameters_present_flag) { + const H264RawHRD *hrd; + + if (sps->vui.nal_hrd_parameters_present_flag) + hrd = &sps->vui.nal_hrd_parameters; + else if (sps->vui.vcl_hrd_parameters_present_flag) + hrd = &sps->vui.vcl_hrd_parameters; + else { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "No HRD parameters for pic_timing.\n"); + return AVERROR_INVALIDDATA; + } + + u(hrd->cpb_removal_delay_length_minus1 + 1, cpb_removal_delay, + 0, (1 << (uint64_t)hrd->cpb_removal_delay_length_minus1) + 1); + u(hrd->dpb_output_delay_length_minus1 + 1, dpb_output_delay, + 0, (1 << (uint64_t)hrd->dpb_output_delay_length_minus1) + 1); + } + + if (sps->vui.pic_struct_present_flag) { + static const int num_clock_ts[9] = { + 1, 1, 1, 2, 2, 3, 3, 2, 3 + }; + int i; + + u(4, pic_struct, 0, 8); + if (current->pic_struct > 8) + return AVERROR_INVALIDDATA; + + for (i = 0; i < num_clock_ts[current->pic_struct]; i++) { + flag(clock_timestamp_flag[i]); + if (current->clock_timestamp_flag[i]) + CHECK(FUNC(sei_pic_timestamp)(ctx, rw, ¤t->timestamp[i])); + } + } + + return 0; +} + +static int FUNC(sei_user_data_registered)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIUserDataRegistered *current, + uint32_t *payload_size) +{ + int err, i, j; + + u(8, itu_t_t35_country_code, 0x00, 0xff); + if (current->itu_t_t35_country_code != 0xff) + i = 1; + else { + u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff); + i = 2; + } + +#ifdef READ + if (*payload_size < i) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Invalid SEI user data registered payload.\n"); + return AVERROR_INVALIDDATA; + } + current->data_length = *payload_size - i; +#else + *payload_size = i + current->data_length; +#endif + + allocate(current->data, current->data_length); + for (j = 0; j < current->data_length; j++) + xu(8, itu_t_t35_payload_byte, current->data[j], 0x00, 0xff); + + return 0; +} + +static int FUNC(sei_user_data_unregistered)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIUserDataUnregistered *current, + uint32_t *payload_size) +{ + int err, i; + +#ifdef READ + if (*payload_size < 16) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Invalid SEI user data unregistered payload.\n"); + return AVERROR_INVALIDDATA; + } + current->data_length = *payload_size - 16; +#else + *payload_size = 16 + current->data_length; +#endif + + for (i = 0; i < 16; i++) { + xu(8, uuid_iso_iec_11578, + current->uuid_iso_iec_11578[i], 0x00, 0xff); + } + + allocate(current->data, current->data_length); + + for (i = 0; i < current->data_length; i++) + xu(8, user_data_payload_byte, current->data[i], 0x00, 0xff); + + return 0; +} + +static int FUNC(sei_recovery_point)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIRecoveryPoint *current) +{ + int err; + + ue(recovery_frame_cnt, 0, 65535); + flag(exact_match_flag); + flag(broken_link_flag); + u(2, changing_slice_group_idc, 0, 2); + + return 0; +} + +static int FUNC(sei_display_orientation)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIDisplayOrientation *current) +{ + int err; + + flag(display_orientation_cancel_flag); + if (!current->display_orientation_cancel_flag) { + flag(hor_flip); + flag(ver_flip); + u(16, anticlockwise_rotation, 0, 65535); + ue(display_orientation_repetition_period, 0, 16384); + flag(display_orientation_extension_flag); + } + + return 0; +} + +static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEIPayload *current) +{ + int err, i; + int start_position, end_position; + +#ifdef READ + start_position = get_bits_count(rw); +#else + start_position = put_bits_count(rw); +#endif + + switch (current->payload_type) { + case H264_SEI_TYPE_BUFFERING_PERIOD: + CHECK(FUNC(sei_buffering_period) + (ctx, rw, ¤t->payload.buffering_period)); + break; + case H264_SEI_TYPE_PIC_TIMING: + CHECK(FUNC(sei_pic_timing) + (ctx, rw, ¤t->payload.pic_timing)); + break; + case H264_SEI_TYPE_FILLER_PAYLOAD: + { + av_unused int ff_byte = 0xff; + for (i = 0; i < current->payload_size; i++) + xu(8, ff_byte, ff_byte, 0xff, 0xff); + } + break; + case H264_SEI_TYPE_USER_DATA_REGISTERED: + CHECK(FUNC(sei_user_data_registered) + (ctx, rw, ¤t->payload.user_data_registered, ¤t->payload_size)); + break; + case H264_SEI_TYPE_USER_DATA_UNREGISTERED: + CHECK(FUNC(sei_user_data_unregistered) + (ctx, rw, ¤t->payload.user_data_unregistered, ¤t->payload_size)); + break; + case H264_SEI_TYPE_RECOVERY_POINT: + CHECK(FUNC(sei_recovery_point) + (ctx, rw, ¤t->payload.recovery_point)); + break; + case H264_SEI_TYPE_DISPLAY_ORIENTATION: + CHECK(FUNC(sei_display_orientation) + (ctx, rw, ¤t->payload.display_orientation)); + break; + default: + { + allocate(current->payload.other.data, current->payload_size); + for (i = 0; i < current->payload_size; i++) + xu(8, payload_byte, current->payload.other.data[i], 0, 255); + } + } + + if (byte_alignment(rw)) { + av_unused int one = 1, zero = 0; + xu(1, bit_equal_to_one, one, 1, 1); + while (byte_alignment(rw)) + xu(1, bit_equal_to_zero, zero, 0, 0); + } + +#ifdef READ + end_position = get_bits_count(rw); + if (end_position < start_position + 8 * current->payload_size) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Incorrect SEI payload length: " + "header %d bits, actually %d bits.\n", + 8 * current->payload_size, + end_position - start_position); + return AVERROR_INVALIDDATA; + } +#else + end_position = put_bits_count(rw); + current->payload_size = (end_position - start_position) / 8; +#endif + + return 0; +} + +static int FUNC(sei)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSEI *current) +{ + int err, k; + + HEADER("Supplemental Enhancement Information"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + 1 << H264_NAL_SEI)); + +#ifdef READ + for (k = 0; k < H264_MAX_SEI_PAYLOADS; k++) { + uint32_t payload_type = 0; + uint32_t payload_size = 0; + uint32_t tmp; + + while (show_bits(rw, 8) == 0xff) { + xu(8, ff_byte, tmp, 0xff, 0xff); + payload_type += 255; + } + xu(8, last_payload_type_byte, tmp, 0, 254); + payload_type += tmp; + + while (show_bits(rw, 8) == 0xff) { + xu(8, ff_byte, tmp, 0xff, 0xff); + payload_size += 255; + } + xu(8, last_payload_size_byte, tmp, 0, 254); + payload_size += tmp; + + current->payload[k].payload_type = payload_type; + current->payload[k].payload_size = payload_size; + + CHECK(FUNC(sei_payload)(ctx, rw, ¤t->payload[k])); + + if (!cbs_h2645_read_more_rbsp_data(rw)) + break; + } + if (k >= H264_MAX_SEI_PAYLOADS) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many payloads in " + "SEI message: found %d.\n", k); + return AVERROR_INVALIDDATA; + } + current->payload_count = k + 1; +#else + for (k = 0; k < current->payload_count; k++) { + PutBitContext start_state; + uint32_t tmp; + int need_size, i; + + // Somewhat clumsy: we write the payload twice when + // we don't know the size in advance. This will mess + // with trace output, but is otherwise harmless. + start_state = *rw; + need_size = !current->payload[k].payload_size; + for (i = 0; i < 1 + need_size; i++) { + *rw = start_state; + + tmp = current->payload[k].payload_type; + while (tmp >= 255) { + xu(8, ff_byte, 0xff, 0xff, 0xff); + tmp -= 255; + } + xu(8, last_payload_type_byte, tmp, 0, 254); + + tmp = current->payload[k].payload_size; + while (tmp >= 255) { + xu(8, ff_byte, 0xff, 0xff, 0xff); + tmp -= 255; + } + xu(8, last_payload_size_byte, tmp, 0, 254); + + CHECK(FUNC(sei_payload)(ctx, rw, ¤t->payload[k])); + } + } +#endif + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(aud)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawAUD *current) +{ + int err; + + HEADER("Access Unit Delimiter"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + 1 << H264_NAL_AUD)); + + u(3, primary_pic_type, 0, 7); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(ref_pic_list_modification)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSliceHeader *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps = h264->active_sps; + int err, i, mopn; + + if (current->slice_type % 5 != 2 && + current->slice_type % 5 != 4) { + flag(ref_pic_list_modification_flag_l0); + if (current->ref_pic_list_modification_flag_l0) { + for (i = 0; i < H264_MAX_RPLM_COUNT; i++) { + xue(modification_of_pic_nums_idc, + current->rplm_l0[i].modification_of_pic_nums_idc, 0, 3); + + mopn = current->rplm_l0[i].modification_of_pic_nums_idc; + if (mopn == 3) + break; + + if (mopn == 0 || mopn == 1) + xue(abs_diff_pic_num_minus1, + current->rplm_l0[i].abs_diff_pic_num_minus1, + 0, (1 + current->field_pic_flag) * + (1 << (sps->log2_max_frame_num_minus4 + 4))); + else if (mopn == 2) + xue(long_term_pic_num, + current->rplm_l0[i].long_term_pic_num, + 0, sps->max_num_ref_frames - 1); + } + } + } + + if (current->slice_type % 5 == 1) { + flag(ref_pic_list_modification_flag_l1); + if (current->ref_pic_list_modification_flag_l1) { + for (i = 0; i < H264_MAX_RPLM_COUNT; i++) { + xue(modification_of_pic_nums_idc, + current->rplm_l1[i].modification_of_pic_nums_idc, 0, 3); + + mopn = current->rplm_l1[i].modification_of_pic_nums_idc; + if (mopn == 3) + break; + + if (mopn == 0 || mopn == 1) + xue(abs_diff_pic_num_minus1, + current->rplm_l1[i].abs_diff_pic_num_minus1, + 0, (1 + current->field_pic_flag) * + (1 << (sps->log2_max_frame_num_minus4 + 4))); + else if (mopn == 2) + xue(long_term_pic_num, + current->rplm_l1[i].long_term_pic_num, + 0, sps->max_num_ref_frames - 1); + } + } + } + + return 0; +} + +static int FUNC(pred_weight_table)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSliceHeader *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps = h264->active_sps; + int chroma; + int err, i, j; + + ue(luma_log2_weight_denom, 0, 7); + + chroma = !sps->separate_colour_plane_flag && sps->chroma_format_idc != 0; + if (chroma) + ue(chroma_log2_weight_denom, 0, 7); + + for (i = 0; i <= current->num_ref_idx_l0_active_minus1; i++) { + flag(luma_weight_l0_flag[i]); + if (current->luma_weight_l0_flag[i]) { + se(luma_weight_l0[i], -128, +127); + se(luma_offset_l0[i], -128, +127); + } + if (chroma) { + flag(chroma_weight_l0_flag[i]); + if (current->chroma_weight_l0_flag[i]) { + for (j = 0; j < 2; j++) { + se(chroma_weight_l0[i][j], -128, +127); + se(chroma_offset_l0[i][j], -128, +127); + } + } + } + } + + if (current->slice_type % 5 == 1) { + for (i = 0; i <= current->num_ref_idx_l1_active_minus1; i++) { + flag(luma_weight_l1_flag[i]); + if (current->luma_weight_l1_flag[i]) { + se(luma_weight_l1[i], -128, +127); + se(luma_offset_l1[i], -128, +127); + } + if (chroma) { + flag(chroma_weight_l1_flag[i]); + if (current->chroma_weight_l1_flag[i]) { + for (j = 0; j < 2; j++) { + se(chroma_weight_l1[i][j], -128, +127); + se(chroma_offset_l1[i][j], -128, +127); + } + } + } + } + } + + return 0; +} + +static int FUNC(dec_ref_pic_marking)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSliceHeader *current, int idr_pic_flag) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps = h264->active_sps; + int err, i; + uint32_t mmco; + + if (idr_pic_flag) { + flag(no_output_of_prior_pics_flag); + flag(long_term_reference_flag); + } else { + flag(adaptive_ref_pic_marking_mode_flag); + if (current->adaptive_ref_pic_marking_mode_flag) { + for (i = 0; i < H264_MAX_MMCO_COUNT; i++) { + xue(memory_management_control_operation, + current->mmco[i].memory_management_control_operation, + 0, 6); + + mmco = current->mmco[i].memory_management_control_operation; + if (mmco == 0) + break; + + if (mmco == 1 || mmco == 3) + xue(difference_of_pic_nums_minus1, + current->mmco[i].difference_of_pic_nums_minus1, + 0, INT32_MAX); + if (mmco == 2) + xue(long_term_pic_num, + current->mmco[i].long_term_pic_num, + 0, sps->max_num_ref_frames - 1); + if (mmco == 3 || mmco == 6) + xue(long_term_frame_idx, + current->mmco[i].long_term_frame_idx, + 0, sps->max_num_ref_frames - 1); + if (mmco == 4) + xue(max_long_term_frame_idx_plus1, + current->mmco[i].max_long_term_frame_idx_plus1, + 0, sps->max_num_ref_frames); + } + if (i == H264_MAX_MMCO_COUNT) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many " + "memory management control operations.\n"); + return AVERROR_INVALIDDATA; + } + } + } + + return 0; +} + +static int FUNC(slice_header)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawSliceHeader *current) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + const H264RawSPS *sps; + const H264RawPPS *pps; + int err; + int idr_pic_flag; + int slice_type_i, slice_type_p, slice_type_b; + int slice_type_si, slice_type_sp; + + HEADER("Slice Header"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + 1 << H264_NAL_SLICE | + 1 << H264_NAL_IDR_SLICE | + 1 << H264_NAL_AUXILIARY_SLICE)); + + if (current->nal_unit_header.nal_unit_type == H264_NAL_AUXILIARY_SLICE) { + if (!h264->last_slice_nal_unit_type) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Auxiliary slice " + "is not decodable without the main picture " + "in the same access unit.\n"); + return AVERROR_INVALIDDATA; + } + } else { + h264->last_slice_nal_unit_type = + current->nal_unit_header.nal_unit_type; + } + idr_pic_flag = h264->last_slice_nal_unit_type == H264_NAL_IDR_SLICE; + + ue(first_mb_in_slice, 0, H264_MAX_MB_PIC_SIZE - 1); + ue(slice_type, 0, 9); + + slice_type_i = current->slice_type % 5 == 2; + slice_type_p = current->slice_type % 5 == 0; + slice_type_b = current->slice_type % 5 == 1; + slice_type_si = current->slice_type % 5 == 4; + slice_type_sp = current->slice_type % 5 == 3; + + if (idr_pic_flag && !(slice_type_i || slice_type_si)) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid slice type %d " + "for IDR picture.\n", current->slice_type); + return AVERROR_INVALIDDATA; + } + + ue(pic_parameter_set_id, 0, 255); + + pps = h264->pps[current->pic_parameter_set_id]; + if (!pps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "PPS id %d not available.\n", + current->pic_parameter_set_id); + return AVERROR_INVALIDDATA; + } + h264->active_pps = pps; + + sps = h264->sps[pps->seq_parameter_set_id]; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SPS id %d not available.\n", + pps->seq_parameter_set_id); + return AVERROR_INVALIDDATA; + } + h264->active_sps = sps; + + if (sps->separate_colour_plane_flag) + u(2, colour_plane_id, 0, 2); + + u(sps->log2_max_frame_num_minus4 + 4, frame_num, + 0, (1 << (sps->log2_max_frame_num_minus4 + 4)) - 1); + + if (!sps->frame_mbs_only_flag) { + flag(field_pic_flag); + if (current->field_pic_flag) + flag(bottom_field_flag); + else + infer(bottom_field_flag, 0); + } else { + infer(field_pic_flag, 0); + infer(bottom_field_flag, 0); + } + + if (idr_pic_flag) + ue(idr_pic_id, 0, 65535); + + if (sps->pic_order_cnt_type == 0) { + u(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, pic_order_cnt_lsb, + 0, (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1); + if (pps->bottom_field_pic_order_in_frame_present_flag && + !current->field_pic_flag) + se(delta_pic_order_cnt_bottom, INT32_MIN + 1, INT32_MAX); + + } else if (sps->pic_order_cnt_type == 1) { + if (!sps->delta_pic_order_always_zero_flag) { + se(delta_pic_order_cnt[0], INT32_MIN + 1, INT32_MAX); + if (pps->bottom_field_pic_order_in_frame_present_flag && + !current->field_pic_flag) + se(delta_pic_order_cnt[1], INT32_MIN + 1, INT32_MAX); + else + infer(delta_pic_order_cnt[1], 0); + } else { + infer(delta_pic_order_cnt[0], 0); + infer(delta_pic_order_cnt[1], 0); + } + } + + if (pps->redundant_pic_cnt_present_flag) + ue(redundant_pic_cnt, 0, 127); + + if (slice_type_b) + flag(direct_spatial_mv_pred_flag); + + if (slice_type_p || slice_type_sp || slice_type_b) { + flag(num_ref_idx_active_override_flag); + if (current->num_ref_idx_active_override_flag) { + ue(num_ref_idx_l0_active_minus1, 0, 31); + if (slice_type_b) + ue(num_ref_idx_l1_active_minus1, 0, 31); + } else { + infer(num_ref_idx_l0_active_minus1, + pps->num_ref_idx_l0_default_active_minus1); + infer(num_ref_idx_l1_active_minus1, + pps->num_ref_idx_l1_default_active_minus1); + } + } + + if (current->nal_unit_header.nal_unit_type == 20 || + current->nal_unit_header.nal_unit_type == 21) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "MVC / 3DAVC not supported.\n"); + return AVERROR_PATCHWELCOME; + } else { + CHECK(FUNC(ref_pic_list_modification)(ctx, rw, current)); + } + + if ((pps->weighted_pred_flag && (slice_type_p || slice_type_sp)) || + (pps->weighted_bipred_idc == 1 && slice_type_b)) { + CHECK(FUNC(pred_weight_table)(ctx, rw, current)); + } + + if (current->nal_unit_header.nal_ref_idc != 0) { + CHECK(FUNC(dec_ref_pic_marking)(ctx, rw, current, idr_pic_flag)); + } + + if (pps->entropy_coding_mode_flag && + !slice_type_i && !slice_type_si) { + ue(cabac_init_idc, 0, 2); + } + + se(slice_qp_delta, - 51 - 6 * sps->bit_depth_luma_minus8, + + 51 + 6 * sps->bit_depth_luma_minus8); + if (slice_type_sp || slice_type_si) { + if (slice_type_sp) + flag(sp_for_switch_flag); + se(slice_qs_delta, -51, +51); + } + + if (pps->deblocking_filter_control_present_flag) { + ue(disable_deblocking_filter_idc, 0, 2); + if (current->disable_deblocking_filter_idc != 1) { + se(slice_alpha_c0_offset_div2, -6, +6); + se(slice_beta_offset_div2, -6, +6); + } else { + infer(slice_alpha_c0_offset_div2, 0); + infer(slice_beta_offset_div2, 0); + } + } else { + infer(disable_deblocking_filter_idc, 0); + infer(slice_alpha_c0_offset_div2, 0); + infer(slice_beta_offset_div2, 0); + } + + if (pps->num_slice_groups_minus1 > 0 && + pps->slice_group_map_type >= 3 && + pps->slice_group_map_type <= 5) { + unsigned int pic_size, max, bits; + + pic_size = (sps->pic_width_in_mbs_minus1 + 1) * + (sps->pic_height_in_map_units_minus1 + 1); + max = (pic_size + pps->slice_group_change_rate_minus1) / + (pps->slice_group_change_rate_minus1 + 1); + bits = av_log2(2 * max - 1); + + u(bits, slice_group_change_cycle, 0, max); + } + + if (pps->entropy_coding_mode_flag) { + av_unused int one = 1; + while (byte_alignment(rw)) + xu(1, cabac_alignment_one_bit, one, 1, 1); + } + + return 0; +} diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index f6a42beea3795..2d417d4a40ae4 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -83,4 +83,7 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc, uint32_t range_min, uint32_t range_max); +extern const CodedBitstreamType ff_cbs_type_h264; + + #endif /* AVCODEC_CBS_INTERNAL_H */ From 9b0c7aa0e446eceec96ba8f4009e004fad29fba3 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 14 May 2017 16:32:00 +0100 Subject: [PATCH 0502/2557] lavc: Add coded bitstream read/write support for H.265 (cherry picked from commit 867381b8b51fa21fa2b8f071f508f3d39cc9c1f0) (cherry picked from commit f763489364416bb6866adc4f4a96012dd2ca1bd0) (cherry picked from commit 067a9ddeb8feff1f724856f0054930c55219f76b) --- configure | 2 + libavcodec/Makefile | 1 + libavcodec/cbs.c | 3 + libavcodec/cbs.h | 1 + libavcodec/cbs_h2645.c | 413 ++++++- libavcodec/cbs_h265.h | 537 +++++++++ libavcodec/cbs_h265_syntax_template.c | 1503 +++++++++++++++++++++++++ libavcodec/cbs_internal.h | 1 + 8 files changed, 2458 insertions(+), 3 deletions(-) create mode 100644 libavcodec/cbs_h265.h create mode 100644 libavcodec/cbs_h265_syntax_template.c diff --git a/configure b/configure index 07c25e3dfad37..e5bfbaabf2229 100755 --- a/configure +++ b/configure @@ -2152,6 +2152,7 @@ CONFIG_EXTRA=" cabac cbs cbs_h264 + cbs_h265 dirac_parse dvprofile exif @@ -2406,6 +2407,7 @@ threads_if_any="$THREADS_LIST" # subsystems cbs_h264_select="cbs golomb" +cbs_h265_select="cbs golomb" dct_select="rdft" dirac_parse_select="golomb" error_resilience_select="me_cmp" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 245a44c7d5896..39b7dd1e2f296 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -61,6 +61,7 @@ OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o OBJS-$(CONFIG_CABAC) += cabac.o OBJS-$(CONFIG_CBS) += cbs.o OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o h2645_parse.o +OBJS-$(CONFIG_CBS_H265) += cbs_h2645.o h2645_parse.o OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index f489d9806f474..d7eb3033c4caf 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -31,6 +31,9 @@ static const CodedBitstreamType *cbs_type_table[] = { #if CONFIG_CBS_H264 &ff_cbs_type_h264, #endif +#if CONFIG_CBS_H265 + &ff_cbs_type_h265, +#endif }; int ff_cbs_init(CodedBitstreamContext **ctx_ptr, diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h index a64430667b59d..a367fd0bf600f 100644 --- a/libavcodec/cbs.h +++ b/libavcodec/cbs.h @@ -44,6 +44,7 @@ struct CodedBitstreamType; * The codec-specific type of a bitstream unit. * * H.264 / AVC: nal_unit_type + * H.265 / HEVC: nal_unit_type */ typedef uint32_t CodedBitstreamUnitType; diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index f03fd3ce7283b..bd2b5cbbf2552 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -23,10 +23,12 @@ #include "cbs.h" #include "cbs_internal.h" #include "cbs_h264.h" +#include "cbs_h265.h" #include "golomb.h" #include "h264.h" #include "h264_sei.h" #include "h2645_parse.h" +#include "hevc.h" static int cbs_read_ue_golomb(CodedBitstreamContext *ctx, GetBitContext *gbc, @@ -235,6 +237,7 @@ static int cbs_write_se_golomb(CodedBitstreamContext *ctx, PutBitContext *pbc, #define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name #define FUNC_H264(rw, name) FUNC_NAME(rw, h264, name) +#define FUNC_H265(rw, name) FUNC_NAME(rw, h265, name) #define READ @@ -297,6 +300,10 @@ static int cbs_h2645_read_more_rbsp_data(GetBitContext *gbc) #include "cbs_h264_syntax_template.c" #undef FUNC +#define FUNC(name) FUNC_H265(READWRITE, name) +#include "cbs_h265_syntax_template.c" +#undef FUNC + #undef READ #undef READWRITE #undef RWContext @@ -366,6 +373,10 @@ static int cbs_h2645_read_more_rbsp_data(GetBitContext *gbc) #include "cbs_h264_syntax_template.c" #undef FUNC +#define FUNC(name) FUNC_H265(READWRITE, name) +#include "cbs_h265_syntax_template.c" +#undef FUNC + #undef WRITE #undef READWRITE #undef RWContext @@ -426,6 +437,40 @@ static void cbs_h264_free_nal_unit(CodedBitstreamUnit *unit) av_freep(&unit->content); } +static void cbs_h265_free_nal_unit(CodedBitstreamUnit *unit) +{ + switch (unit->type) { + case HEVC_NAL_VPS: + av_freep(&((H265RawVPS*)unit->content)->extension_data.data); + break; + case HEVC_NAL_SPS: + av_freep(&((H265RawSPS*)unit->content)->extension_data.data); + break; + case HEVC_NAL_PPS: + av_freep(&((H265RawPPS*)unit->content)->extension_data.data); + break; + case HEVC_NAL_TRAIL_N: + case HEVC_NAL_TRAIL_R: + case HEVC_NAL_TSA_N: + case HEVC_NAL_TSA_R: + case HEVC_NAL_STSA_N: + case HEVC_NAL_STSA_R: + case HEVC_NAL_RADL_N: + case HEVC_NAL_RADL_R: + case HEVC_NAL_RASL_N: + case HEVC_NAL_RASL_R: + case HEVC_NAL_BLA_W_LP: + case HEVC_NAL_BLA_W_RADL: + case HEVC_NAL_BLA_N_LP: + case HEVC_NAL_IDR_W_RADL: + case HEVC_NAL_IDR_N_LP: + case HEVC_NAL_CRA_NUT: + av_freep(&((H265RawSlice*)unit->content)->data); + break; + } + av_freep(&unit->content); +} + static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, const H2645Packet *packet) @@ -547,6 +592,58 @@ static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx, "header.\n", bytestream2_get_bytes_left(&gbc)); } + } else if (header && frag->data[0] && codec_id == AV_CODEC_ID_HEVC) { + // HVCC header. + size_t size, start, end; + int i, j, nb_arrays, nal_unit_type, nb_nals, version; + + priv->mp4 = 1; + + bytestream2_init(&gbc, frag->data, frag->data_size); + + if (bytestream2_get_bytes_left(&gbc) < 23) + return AVERROR_INVALIDDATA; + + version = bytestream2_get_byte(&gbc); + if (version != 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid HVCC header: " + "first byte %u.", version); + return AVERROR_INVALIDDATA; + } + + bytestream2_skip(&gbc, 20); + priv->nal_length_size = (bytestream2_get_byte(&gbc) & 3) + 1; + + nb_arrays = bytestream2_get_byte(&gbc); + for (i = 0; i < nb_arrays; i++) { + nal_unit_type = bytestream2_get_byte(&gbc) & 0x3f; + nb_nals = bytestream2_get_be16(&gbc); + + start = bytestream2_tell(&gbc); + for (j = 0; j < nb_nals; j++) { + if (bytestream2_get_bytes_left(&gbc) < 2) + return AVERROR_INVALIDDATA; + size = bytestream2_get_be16(&gbc); + if (bytestream2_get_bytes_left(&gbc) < size) + return AVERROR_INVALIDDATA; + bytestream2_skip(&gbc, size); + } + end = bytestream2_tell(&gbc); + + err = ff_h2645_packet_split(&priv->read_packet, + frag->data + start, end - start, + ctx->log_ctx, 1, 2, AV_CODEC_ID_HEVC, 1); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split " + "HVCC array %d (%d NAL units of type %d).\n", + i, nb_nals, nal_unit_type); + return err; + } + err = cbs_h2645_fragment_add_nals(ctx, frag, &priv->read_packet); + if (err < 0) + return err; + } + } else { // Annex B, or later MP4 with already-known parameters. @@ -587,6 +684,9 @@ static int cbs_h26 ## h26n ## _replace_ ## ps_var(CodedBitstreamContext *ctx, \ cbs_h2645_replace_ps(4, SPS, sps, seq_parameter_set_id) cbs_h2645_replace_ps(4, PPS, pps, pic_parameter_set_id) +cbs_h2645_replace_ps(5, VPS, vps, vps_video_parameter_set_id) +cbs_h2645_replace_ps(5, SPS, sps, sps_seq_parameter_set_id) +cbs_h2645_replace_ps(5, PPS, pps, pps_pic_parameter_set_id) static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit) @@ -738,6 +838,153 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, return 0; } +static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + GetBitContext gbc; + int err; + + err = init_get_bits(&gbc, unit->data, 8 * unit->data_size); + if (err < 0) + return err; + + switch (unit->type) { + case HEVC_NAL_VPS: + { + H265RawVPS *vps; + + vps = av_mallocz(sizeof(*vps)); + if (!vps) + return AVERROR(ENOMEM); + err = cbs_h265_read_vps(ctx, &gbc, vps); + if (err >= 0) + err = cbs_h265_replace_vps(ctx, vps); + if (err < 0) { + av_free(vps); + return err; + } + + unit->content = vps; + } + break; + case HEVC_NAL_SPS: + { + H265RawSPS *sps; + + sps = av_mallocz(sizeof(*sps)); + if (!sps) + return AVERROR(ENOMEM); + err = cbs_h265_read_sps(ctx, &gbc, sps); + if (err >= 0) + err = cbs_h265_replace_sps(ctx, sps); + if (err < 0) { + av_free(sps); + return err; + } + + unit->content = sps; + } + break; + + case HEVC_NAL_PPS: + { + H265RawPPS *pps; + + pps = av_mallocz(sizeof(*pps)); + if (!pps) + return AVERROR(ENOMEM); + err = cbs_h265_read_pps(ctx, &gbc, pps); + if (err >= 0) + err = cbs_h265_replace_pps(ctx, pps); + if (err < 0) { + av_free(pps); + return err; + } + + unit->content = pps; + } + break; + + case HEVC_NAL_TRAIL_N: + case HEVC_NAL_TRAIL_R: + case HEVC_NAL_TSA_N: + case HEVC_NAL_TSA_R: + case HEVC_NAL_STSA_N: + case HEVC_NAL_STSA_R: + case HEVC_NAL_RADL_N: + case HEVC_NAL_RADL_R: + case HEVC_NAL_RASL_N: + case HEVC_NAL_RASL_R: + case HEVC_NAL_BLA_W_LP: + case HEVC_NAL_BLA_W_RADL: + case HEVC_NAL_BLA_N_LP: + case HEVC_NAL_IDR_W_RADL: + case HEVC_NAL_IDR_N_LP: + case HEVC_NAL_CRA_NUT: + { + H265RawSlice *slice; + int pos, len; + + slice = av_mallocz(sizeof(*slice)); + if (!slice) + return AVERROR(ENOMEM); + err = cbs_h265_read_slice_segment_header(ctx, &gbc, &slice->header); + if (err < 0) { + av_free(slice); + return err; + } + + pos = get_bits_count(&gbc); + len = unit->data_size; + if (!unit->data[len - 1]) { + int z; + for (z = 0; z < len && !unit->data[len - z - 1]; z++); + av_log(ctx->log_ctx, AV_LOG_DEBUG, "Deleted %d trailing zeroes " + "from slice data.\n", z); + len -= z; + } + + slice->data_size = len - pos / 8; + slice->data = av_malloc(slice->data_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!slice->data) { + av_free(slice); + return AVERROR(ENOMEM); + } + memcpy(slice->data, + unit->data + pos / 8, slice->data_size); + memset(slice->data + slice->data_size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); + slice->data_bit_start = pos % 8; + + unit->content = slice; + } + break; + + case HEVC_NAL_AUD: + { + H265RawAUD *aud; + + aud = av_mallocz(sizeof(*aud)); + if (!aud) + return AVERROR(ENOMEM); + err = cbs_h265_read_aud(ctx, &gbc, aud); + if (err < 0) { + av_free(aud); + return err; + } + + unit->content = aud; + } + break; + + default: + return AVERROR(ENOSYS); + } + + return 0; +} + static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit, PutBitContext *pbc) @@ -850,6 +1097,127 @@ static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx, return 0; } +static int cbs_h265_write_nal_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + PutBitContext *pbc) +{ + int err; + + switch (unit->type) { + case HEVC_NAL_VPS: + { + H265RawVPS *vps = unit->content; + + err = cbs_h265_write_vps(ctx, pbc, vps); + if (err < 0) + return err; + + err = cbs_h265_replace_vps(ctx, vps); + if (err < 0) + return err; + } + break; + + case HEVC_NAL_SPS: + { + H265RawSPS *sps = unit->content; + + err = cbs_h265_write_sps(ctx, pbc, sps); + if (err < 0) + return err; + + err = cbs_h265_replace_sps(ctx, sps); + if (err < 0) + return err; + } + break; + + case HEVC_NAL_PPS: + { + H265RawPPS *pps = unit->content; + + err = cbs_h265_write_pps(ctx, pbc, pps); + if (err < 0) + return err; + + err = cbs_h265_replace_pps(ctx, pps); + if (err < 0) + return err; + } + break; + + case HEVC_NAL_TRAIL_N: + case HEVC_NAL_TRAIL_R: + case HEVC_NAL_TSA_N: + case HEVC_NAL_TSA_R: + case HEVC_NAL_STSA_N: + case HEVC_NAL_STSA_R: + case HEVC_NAL_RADL_N: + case HEVC_NAL_RADL_R: + case HEVC_NAL_RASL_N: + case HEVC_NAL_RASL_R: + case HEVC_NAL_BLA_W_LP: + case HEVC_NAL_BLA_W_RADL: + case HEVC_NAL_BLA_N_LP: + case HEVC_NAL_IDR_W_RADL: + case HEVC_NAL_IDR_N_LP: + case HEVC_NAL_CRA_NUT: + { + H265RawSlice *slice = unit->content; + GetBitContext gbc; + int bits_left, end, zeroes; + + err = cbs_h265_write_slice_segment_header(ctx, pbc, &slice->header); + if (err < 0) + return err; + + if (slice->data) { + if (slice->data_size * 8 + 8 > put_bits_left(pbc)) + return AVERROR(ENOSPC); + + init_get_bits(&gbc, slice->data, slice->data_size * 8); + skip_bits_long(&gbc, slice->data_bit_start); + + // Copy in two-byte blocks, but stop before copying the + // rbsp_stop_one_bit in the final byte. + while (get_bits_left(&gbc) > 23) + put_bits(pbc, 16, get_bits(&gbc, 16)); + + bits_left = get_bits_left(&gbc); + end = get_bits(&gbc, bits_left); + + // rbsp_stop_one_bit must be present here. + av_assert0(end); + zeroes = ff_ctz(end); + if (bits_left > zeroes + 1) + put_bits(pbc, bits_left - zeroes - 1, + end >> (zeroes + 1)); + put_bits(pbc, 1, 1); + while (put_bits_count(pbc) % 8 != 0) + put_bits(pbc, 1, 0); + } else { + // No slice data - that was just the header. + } + } + break; + + case HEVC_NAL_AUD: + { + err = cbs_h265_write_aud(ctx, pbc, unit->content); + if (err < 0) + return err; + } + break; + + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for " + "NAL unit type %"PRIu32".\n", unit->type); + return AVERROR_PATCHWELCOME; + } + + return 0; +} + static int cbs_h2645_write_nal_unit(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit) { @@ -874,7 +1242,10 @@ static int cbs_h2645_write_nal_unit(CodedBitstreamContext *ctx, init_put_bits(&pbc, priv->write_buffer, priv->write_buffer_size); - err = cbs_h264_write_nal_unit(ctx, unit, &pbc); + if (codec_id == AV_CODEC_ID_H264) + err = cbs_h264_write_nal_unit(ctx, unit, &pbc); + else + err = cbs_h265_write_nal_unit(ctx, unit, &pbc); if (err == AVERROR(ENOSPC)) { // Overflow. @@ -940,8 +1311,13 @@ static int cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx, frag->data_bit_padding = unit->data_bit_padding; } - if (unit->type == H264_NAL_SPS || - unit->type == H264_NAL_PPS || + if ((ctx->codec->codec_id == AV_CODEC_ID_H264 && + (unit->type == H264_NAL_SPS || + unit->type == H264_NAL_PPS)) || + (ctx->codec->codec_id == AV_CODEC_ID_HEVC && + (unit->type == HEVC_NAL_VPS || + unit->type == HEVC_NAL_SPS || + unit->type == HEVC_NAL_PPS)) || i == 0 /* (Assume this is the start of an access unit.) */) { // zero_byte data[dp++] = 0; @@ -995,6 +1371,23 @@ static void cbs_h264_close(CodedBitstreamContext *ctx) av_freep(&h264->pps[i]); } +static void cbs_h265_close(CodedBitstreamContext *ctx) +{ + CodedBitstreamH265Context *h265 = ctx->priv_data; + int i; + + ff_h2645_packet_uninit(&h265->common.read_packet); + + av_freep(&h265->common.write_buffer); + + for (i = 0; i < FF_ARRAY_ELEMS(h265->vps); i++) + av_freep(&h265->vps[i]); + for (i = 0; i < FF_ARRAY_ELEMS(h265->sps); i++) + av_freep(&h265->sps[i]); + for (i = 0; i < FF_ARRAY_ELEMS(h265->pps); i++) + av_freep(&h265->pps[i]); +} + const CodedBitstreamType ff_cbs_type_h264 = { .codec_id = AV_CODEC_ID_H264, @@ -1008,3 +1401,17 @@ const CodedBitstreamType ff_cbs_type_h264 = { .free_unit = &cbs_h264_free_nal_unit, .close = &cbs_h264_close, }; + +const CodedBitstreamType ff_cbs_type_h265 = { + .codec_id = AV_CODEC_ID_HEVC, + + .priv_data_size = sizeof(CodedBitstreamH265Context), + + .split_fragment = &cbs_h2645_split_fragment, + .read_unit = &cbs_h265_read_nal_unit, + .write_unit = &cbs_h2645_write_nal_unit, + .assemble_fragment = &cbs_h2645_assemble_fragment, + + .free_unit = &cbs_h265_free_nal_unit, + .close = &cbs_h265_close, +}; diff --git a/libavcodec/cbs_h265.h b/libavcodec/cbs_h265.h new file mode 100644 index 0000000000000..b4777cf6bef19 --- /dev/null +++ b/libavcodec/cbs_h265.h @@ -0,0 +1,537 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_H265_H +#define AVCODEC_CBS_H265_H + +#include +#include + +#include "cbs_h2645.h" +#include "hevc.h" + + +typedef struct H265RawNALUnitHeader { + uint8_t forbidden_zero_bit; + uint8_t nal_unit_type; + uint8_t nuh_layer_id; + uint8_t nuh_temporal_id_plus1; +} H265RawNALUnitHeader; + +typedef struct H265RawProfileTierLevel { + uint8_t general_profile_space; + uint8_t general_tier_flag; + uint8_t general_profile_idc; + + uint8_t general_profile_compatibility_flag[32]; + + uint8_t general_progressive_source_flag; + uint8_t general_interlaced_source_flag; + uint8_t general_non_packed_constraint_flag; + uint8_t general_frame_only_constraint_flag; + + uint8_t general_max_12bit_constraint_flag; + uint8_t general_max_10bit_constraint_flag; + uint8_t general_max_8bit_constraint_flag; + uint8_t general_max_422chroma_constraint_flag; + uint8_t general_max_420chroma_constraint_flag; + uint8_t general_max_monochrome_constraint_flag; + uint8_t general_intra_constraint_flag; + uint8_t general_one_picture_only_constraint_flag; + uint8_t general_lower_bit_rate_constraint_flag; + uint8_t general_max_14bit_constraint_flag; + + uint8_t general_inbld_flag; + + uint8_t general_level_idc; + + uint8_t sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS]; + uint8_t sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS]; + + // TODO: much of that again for each sub-layer. +} H265RawProfileTierLevel; + +typedef struct H265RawSubLayerHRDParameters { + uint32_t bit_rate_value_minus1[HEVC_MAX_CPB_CNT]; + uint32_t cpb_size_value_minus1[HEVC_MAX_CPB_CNT]; + uint32_t cpb_size_du_value_minus1[HEVC_MAX_CPB_CNT]; + uint32_t bit_rate_du_value_minus1[HEVC_MAX_CPB_CNT]; + uint8_t cbr_flag[HEVC_MAX_CPB_CNT]; +} H265RawSubLayerHRDParameters; + +typedef struct H265RawHRDParameters { + uint8_t nal_hrd_parameters_present_flag; + uint8_t vcl_hrd_parameters_present_flag; + + uint8_t sub_pic_hrd_params_present_flag; + uint8_t tick_divisor_minus2; + uint8_t du_cpb_removal_delay_increment_length_minus1; + uint8_t sub_pic_cpb_params_in_pic_timing_sei_flag; + uint8_t dpb_output_delay_du_length_minus1; + + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + uint8_t cpb_size_du_scale; + + uint8_t initial_cpb_removal_delay_length_minus1; + uint8_t au_cpb_removal_delay_length_minus1; + uint8_t dpb_output_delay_length_minus1; + + uint8_t fixed_pic_rate_general_flag[HEVC_MAX_SUB_LAYERS]; + uint8_t fixed_pic_rate_within_cvs_flag[HEVC_MAX_SUB_LAYERS]; + uint16_t elemental_duration_in_tc_minus1[HEVC_MAX_SUB_LAYERS]; + uint8_t low_delay_hrd_flag[HEVC_MAX_SUB_LAYERS]; + uint8_t cpb_cnt_minus1[HEVC_MAX_SUB_LAYERS]; + H265RawSubLayerHRDParameters nal_sub_layer_hrd_parameters[HEVC_MAX_SUB_LAYERS]; + H265RawSubLayerHRDParameters vcl_sub_layer_hrd_parameters[HEVC_MAX_SUB_LAYERS]; +} H265RawHRDParameters; + +typedef struct H265RawVUI { + uint8_t aspect_ratio_info_present_flag; + uint8_t aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + + uint8_t overscan_info_present_flag; + uint8_t overscan_appropriate_flag; + + uint8_t video_signal_type_present_flag; + uint8_t video_format; + uint8_t video_full_range_flag; + uint8_t colour_description_present_flag; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; + + uint8_t chroma_loc_info_present_flag; + uint8_t chroma_sample_loc_type_top_field; + uint8_t chroma_sample_loc_type_bottom_field; + + uint8_t neutral_chroma_indication_flag; + uint8_t field_seq_flag; + uint8_t frame_field_info_present_flag; + + uint8_t default_display_window_flag; + uint16_t def_disp_win_left_offset; + uint16_t def_disp_win_right_offset; + uint16_t def_disp_win_top_offset; + uint16_t def_disp_win_bottom_offset; + + uint8_t vui_timing_info_present_flag; + uint32_t vui_num_units_in_tick; + uint32_t vui_time_scale; + uint8_t vui_poc_proportional_to_timing_flag; + uint32_t vui_num_ticks_poc_diff_one_minus1; + uint8_t vui_hrd_parameters_present_flag; + H265RawHRDParameters hrd_parameters; + + uint8_t bitstream_restriction_flag; + uint8_t tiles_fixed_structure_flag; + uint8_t motion_vectors_over_pic_boundaries_flag; + uint8_t restricted_ref_pic_lists_flag; + uint16_t min_spatial_segmentation_idc; + uint8_t max_bytes_per_pic_denom; + uint8_t max_bits_per_min_cu_denom; + uint8_t log2_max_mv_length_horizontal; + uint8_t log2_max_mv_length_vertical; +} H265RawVUI; + +typedef struct H265RawPSExtensionData { + uint8_t *data; + size_t bit_length; +} H265RawPSExtensionData; + +typedef struct H265RawVPS { + H265RawNALUnitHeader nal_unit_header; + + uint8_t vps_video_parameter_set_id; + + uint8_t vps_base_layer_internal_flag; + uint8_t vps_base_layer_available_flag; + uint8_t vps_max_layers_minus1; + uint8_t vps_max_sub_layers_minus1; + uint8_t vps_temporal_id_nesting_flag; + + H265RawProfileTierLevel profile_tier_level; + + uint8_t vps_sub_layer_ordering_info_present_flag; + uint8_t vps_max_dec_pic_buffering_minus1[HEVC_MAX_SUB_LAYERS]; + uint8_t vps_max_num_reorder_pics[HEVC_MAX_SUB_LAYERS]; + uint32_t vps_max_latency_increase_plus1[HEVC_MAX_SUB_LAYERS]; + + uint8_t vps_max_layer_id; + uint16_t vps_num_layer_sets_minus1; + uint8_t layer_id_included_flag[HEVC_MAX_LAYER_SETS][HEVC_MAX_LAYERS]; + + uint8_t vps_timing_info_present_flag; + uint32_t vps_num_units_in_tick; + uint32_t vps_time_scale; + uint8_t vps_poc_proportional_to_timing_flag; + uint32_t vps_num_ticks_poc_diff_one_minus1; + uint16_t vps_num_hrd_parameters; + uint16_t hrd_layer_set_idx[HEVC_MAX_LAYER_SETS]; + uint8_t cprms_present_flag[HEVC_MAX_LAYER_SETS]; + H265RawHRDParameters hrd_parameters[HEVC_MAX_LAYER_SETS]; + + uint8_t vps_extension_flag; + H265RawPSExtensionData extension_data; +} H265RawVPS; + +typedef struct H265RawSTRefPicSet { + uint8_t inter_ref_pic_set_prediction_flag; + + uint8_t delta_idx_minus1; + uint8_t delta_rps_sign; + uint16_t abs_delta_rps_minus1; + + uint8_t used_by_curr_pic_flag[HEVC_MAX_REFS]; + uint8_t use_delta_flag[HEVC_MAX_REFS]; + + uint8_t num_negative_pics; + uint8_t num_positive_pics; + uint16_t delta_poc_s0_minus1[HEVC_MAX_REFS]; + uint8_t used_by_curr_pic_s0_flag[HEVC_MAX_REFS]; + uint16_t delta_poc_s1_minus1[HEVC_MAX_REFS]; + uint8_t used_by_curr_pic_s1_flag[HEVC_MAX_REFS]; +} H265RawSTRefPicSet; + +typedef struct H265RawScalingList { + uint8_t scaling_list_pred_mode_flag[4][6]; + uint8_t scaling_list_pred_matrix_id_delta[4][6]; + int16_t scaling_list_dc_coef_minus8[4][6]; + int8_t scaling_list_delta_coeff[4][6][64]; +} H265RawScalingList; + +typedef struct H265RawSPS { + H265RawNALUnitHeader nal_unit_header; + + uint8_t sps_video_parameter_set_id; + + uint8_t sps_max_sub_layers_minus1; + uint8_t sps_temporal_id_nesting_flag; + + H265RawProfileTierLevel profile_tier_level; + + uint8_t sps_seq_parameter_set_id; + + uint8_t chroma_format_idc; + uint8_t separate_colour_plane_flag; + + uint16_t pic_width_in_luma_samples; + uint16_t pic_height_in_luma_samples; + + uint8_t conformance_window_flag; + uint16_t conf_win_left_offset; + uint16_t conf_win_right_offset; + uint16_t conf_win_top_offset; + uint16_t conf_win_bottom_offset; + + uint8_t bit_depth_luma_minus8; + uint8_t bit_depth_chroma_minus8; + + uint8_t log2_max_pic_order_cnt_lsb_minus4; + + uint8_t sps_sub_layer_ordering_info_present_flag; + uint8_t sps_max_dec_pic_buffering_minus1[HEVC_MAX_SUB_LAYERS]; + uint8_t sps_max_num_reorder_pics[HEVC_MAX_SUB_LAYERS]; + uint32_t sps_max_latency_increase_plus1[HEVC_MAX_SUB_LAYERS]; + + uint8_t log2_min_luma_coding_block_size_minus3; + uint8_t log2_diff_max_min_luma_coding_block_size; + uint8_t log2_min_luma_transform_block_size_minus2; + uint8_t log2_diff_max_min_luma_transform_block_size; + uint8_t max_transform_hierarchy_depth_inter; + uint8_t max_transform_hierarchy_depth_intra; + + uint8_t scaling_list_enabled_flag; + uint8_t sps_scaling_list_data_present_flag; + H265RawScalingList scaling_list; + + uint8_t amp_enabled_flag; + uint8_t sample_adaptive_offset_enabled_flag; + + uint8_t pcm_enabled_flag; + uint8_t pcm_sample_bit_depth_luma_minus1; + uint8_t pcm_sample_bit_depth_chroma_minus1; + uint8_t log2_min_pcm_luma_coding_block_size_minus3; + uint8_t log2_diff_max_min_pcm_luma_coding_block_size; + uint8_t pcm_loop_filter_disabled_flag; + + uint8_t num_short_term_ref_pic_sets; + H265RawSTRefPicSet st_ref_pic_set[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]; + + uint8_t long_term_ref_pics_present_flag; + uint8_t num_long_term_ref_pics_sps; + uint16_t lt_ref_pic_poc_lsb_sps[HEVC_MAX_LONG_TERM_REF_PICS]; + uint8_t used_by_curr_pic_lt_sps_flag[HEVC_MAX_LONG_TERM_REF_PICS]; + + uint8_t sps_temporal_mvp_enabled_flag; + uint8_t strong_intra_smoothing_enabled_flag; + + uint8_t vui_parameters_present_flag; + H265RawVUI vui; + + uint8_t sps_extension_present_flag; + uint8_t sps_range_extension_flag; + uint8_t sps_multilayer_extension_flag; + uint8_t sps_3d_extension_flag; + uint8_t sps_scc_extension_flag; + uint8_t sps_extension_4bits; + + H265RawPSExtensionData extension_data; + + // Range extension. + uint8_t transform_skip_rotation_enabled_flag; + uint8_t transform_skip_context_enabled_flag; + uint8_t implicit_rdpcm_enabled_flag; + uint8_t explicit_rdpcm_enabled_flag; + uint8_t extended_precision_processing_flag; + uint8_t intra_smoothing_disabled_flag; + uint8_t high_precision_offsets_enabled_flag; + uint8_t persistent_rice_adaptation_enabled_flag; + uint8_t cabac_bypass_alignment_enabled_flag; + + // Screen content coding extension. + uint8_t sps_curr_pic_ref_enabled_flag; + uint8_t palette_mode_enabled_flag; + uint8_t palette_max_size; + uint8_t delta_palette_max_predictor_size; + uint8_t sps_palette_predictor_initializer_present_flag; + uint8_t sps_num_palette_predictor_initializer_minus1; + uint16_t sps_palette_predictor_initializers[3][128]; + + uint8_t motion_vector_resolution_control_idc; + uint8_t intra_boundary_filtering_disable_flag; +} H265RawSPS; + +typedef struct H265RawPPS { + H265RawNALUnitHeader nal_unit_header; + + uint8_t pps_pic_parameter_set_id; + uint8_t pps_seq_parameter_set_id; + + uint8_t dependent_slice_segments_enabled_flag; + uint8_t output_flag_present_flag; + uint8_t num_extra_slice_header_bits; + uint8_t sign_data_hiding_enabled_flag; + uint8_t cabac_init_present_flag; + + uint8_t num_ref_idx_l0_default_active_minus1; + uint8_t num_ref_idx_l1_default_active_minus1; + + int8_t init_qp_minus26; + + uint8_t constrained_intra_pred_flag; + uint8_t transform_skip_enabled_flag; + uint8_t cu_qp_delta_enabled_flag; + uint8_t diff_cu_qp_delta_depth; + + int8_t pps_cb_qp_offset; + int8_t pps_cr_qp_offset; + uint8_t pps_slice_chroma_qp_offsets_present_flag; + + uint8_t weighted_pred_flag; + uint8_t weighted_bipred_flag; + + uint8_t transquant_bypass_enabled_flag; + uint8_t tiles_enabled_flag; + uint8_t entropy_coding_sync_enabled_flag; + + uint8_t num_tile_columns_minus1; + uint8_t num_tile_rows_minus1; + uint8_t uniform_spacing_flag; + uint16_t column_width_minus1[HEVC_MAX_TILE_COLUMNS]; + uint16_t row_height_minus1[HEVC_MAX_TILE_ROWS]; + uint8_t loop_filter_across_tiles_enabled_flag; + + uint8_t pps_loop_filter_across_slices_enabled_flag; + uint8_t deblocking_filter_control_present_flag; + uint8_t deblocking_filter_override_enabled_flag; + uint8_t pps_deblocking_filter_disabled_flag; + int8_t pps_beta_offset_div2; + int8_t pps_tc_offset_div2; + + uint8_t pps_scaling_list_data_present_flag; + H265RawScalingList scaling_list; + + uint8_t lists_modification_present_flag; + uint8_t log2_parallel_merge_level_minus2; + + uint8_t slice_segment_header_extension_present_flag; + + uint8_t pps_extension_present_flag; + uint8_t pps_range_extension_flag; + uint8_t pps_multilayer_extension_flag; + uint8_t pps_3d_extension_flag; + uint8_t pps_scc_extension_flag; + uint8_t pps_extension_4bits; + + H265RawPSExtensionData extension_data; + + // Range extension. + uint8_t log2_max_transform_skip_block_size_minus2; + uint8_t cross_component_prediction_enabled_flag; + uint8_t chroma_qp_offset_list_enabled_flag; + uint8_t diff_cu_chroma_qp_offset_depth; + uint8_t chroma_qp_offset_list_len_minus1; + int8_t cb_qp_offset_list[6]; + int8_t cr_qp_offset_list[6]; + uint8_t log2_sao_offset_scale_luma; + uint8_t log2_sao_offset_scale_chroma; + + // Screen content coding extension. + uint8_t pps_curr_pic_ref_enabled_flag; + uint8_t residual_adaptive_colour_transform_enabled_flag; + uint8_t pps_slice_act_qp_offsets_present_flag; + int8_t pps_act_y_qp_offset_plus5; + int8_t pps_act_cb_qp_offset_plus5; + int8_t pps_act_cr_qp_offset_plus3; + + uint8_t pps_palette_predictor_initializer_present_flag; + uint8_t pps_num_palette_predictor_initializer; + uint8_t monochrome_palette_flag; + uint8_t luma_bit_depth_entry_minus8; + uint8_t chroma_bit_depth_entry_minus8; + uint16_t pps_palette_predictor_initializers[3][128]; +} H265RawPPS; + +typedef struct H265RawAUD { + H265RawNALUnitHeader nal_unit_header; + + uint8_t pic_type; +} H265RawAUD; + +typedef struct H265RawSliceHeader { + H265RawNALUnitHeader nal_unit_header; + + uint8_t first_slice_segment_in_pic_flag; + uint8_t no_output_of_prior_pics_flag; + uint8_t slice_pic_parameter_set_id; + + uint8_t dependent_slice_segment_flag; + uint16_t slice_segment_address; + + uint8_t slice_reserved_flag[8]; + uint8_t slice_type; + + uint8_t pic_output_flag; + uint8_t colour_plane_id; + + uint16_t slice_pic_order_cnt_lsb; + + uint8_t short_term_ref_pic_set_sps_flag; + H265RawSTRefPicSet short_term_ref_pic_set; + uint8_t short_term_ref_pic_set_idx; + + uint8_t num_long_term_sps; + uint8_t num_long_term_pics; + uint8_t lt_idx_sps[HEVC_MAX_REFS]; + uint8_t poc_lsb_lt[HEVC_MAX_REFS]; + uint8_t used_by_curr_pic_lt_flag[HEVC_MAX_REFS]; + uint8_t delta_poc_msb_present_flag[HEVC_MAX_REFS]; + uint32_t delta_poc_msb_cycle_lt[HEVC_MAX_REFS]; + + uint8_t slice_temporal_mvp_enabled_flag; + + uint8_t slice_sao_luma_flag; + uint8_t slice_sao_chroma_flag; + + uint8_t num_ref_idx_active_override_flag; + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; + + uint8_t ref_pic_list_modification_flag_l0; + uint8_t list_entry_l0[HEVC_MAX_REFS]; + uint8_t ref_pic_list_modification_flag_l1; + uint8_t list_entry_l1[HEVC_MAX_REFS]; + + uint8_t mvd_l1_zero_flag; + uint8_t cabac_init_flag; + uint8_t collocated_from_l0_flag; + uint8_t collocated_ref_idx; + + uint8_t luma_log2_weight_denom; + int8_t delta_chroma_log2_weight_denom; + uint8_t luma_weight_l0_flag[HEVC_MAX_REFS]; + uint8_t chroma_weight_l0_flag[HEVC_MAX_REFS]; + int8_t delta_luma_weight_l0[HEVC_MAX_REFS]; + int16_t luma_offset_l0[HEVC_MAX_REFS]; + int8_t delta_chroma_weight_l0[HEVC_MAX_REFS][2]; + int16_t chroma_offset_l0[HEVC_MAX_REFS][2]; + uint8_t luma_weight_l1_flag[HEVC_MAX_REFS]; + uint8_t chroma_weight_l1_flag[HEVC_MAX_REFS]; + int8_t delta_luma_weight_l1[HEVC_MAX_REFS]; + int16_t luma_offset_l1[HEVC_MAX_REFS]; + int8_t delta_chroma_weight_l1[HEVC_MAX_REFS][2]; + int16_t chroma_offset_l1[HEVC_MAX_REFS][2]; + + uint8_t five_minus_max_num_merge_cand; + uint8_t use_integer_mv_flag; + + int8_t slice_qp_delta; + int8_t slice_cb_qp_offset; + int8_t slice_cr_qp_offset; + int8_t slice_act_y_qp_offset; + int8_t slice_act_cb_qp_offset; + int8_t slice_act_cr_qp_offset; + uint8_t cu_chroma_qp_offset_enabled_flag; + + uint8_t deblocking_filter_override_flag; + uint8_t slice_deblocking_filter_disabled_flag; + int8_t slice_beta_offset_div2; + int8_t slice_tc_offset_div2; + uint8_t slice_loop_filter_across_slices_enabled_flag; + + uint16_t num_entry_point_offsets; + uint8_t offset_len_minus1; + uint32_t entry_point_offset_minus1[HEVC_MAX_ENTRY_POINT_OFFSETS]; + + uint16_t slice_segment_header_extension_length; + uint8_t slice_segment_header_extension_data_byte[256]; +} H265RawSliceHeader; + + +typedef struct H265RawSlice { + H265RawSliceHeader header; + + uint8_t *data; + size_t data_size; + int data_bit_start; +} H265RawSlice; + + +typedef struct CodedBitstreamH265Context { + // Reader/writer context in common with the H.264 implementation. + CodedBitstreamH2645Context common; + + // All currently available parameter sets. These are updated when + // any parameter set NAL unit is read/written with this context. + H265RawVPS *vps[HEVC_MAX_VPS_COUNT]; + H265RawSPS *sps[HEVC_MAX_SPS_COUNT]; + H265RawPPS *pps[HEVC_MAX_PPS_COUNT]; + + // The currently active parameter sets. These are updated when any + // NAL unit refers to the relevant parameter set. These pointers + // must also be present in the arrays above. + const H265RawVPS *active_vps; + const H265RawSPS *active_sps; + const H265RawPPS *active_pps; +} CodedBitstreamH265Context; + + +#endif /* AVCODEC_CBS_H265_H */ diff --git a/libavcodec/cbs_h265_syntax_template.c b/libavcodec/cbs_h265_syntax_template.c new file mode 100644 index 0000000000000..dae7f2dd46325 --- /dev/null +++ b/libavcodec/cbs_h265_syntax_template.c @@ -0,0 +1,1503 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static int FUNC(rbsp_trailing_bits)(CodedBitstreamContext *ctx, RWContext *rw) +{ + int err; + av_unused int one = 1, zero = 0; + xu(1, rbsp_stop_one_bit, one, 1, 1); + while (byte_alignment(rw) != 0) + xu(1, rbsp_alignment_zero_bit, zero, 0, 0); + + return 0; +} + +static int FUNC(nal_unit_header)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawNALUnitHeader *current, + int expected_nal_unit_type) +{ + int err; + + u(1, forbidden_zero_bit, 0, 0); + + if (expected_nal_unit_type >= 0) + u(6, nal_unit_type, expected_nal_unit_type, + expected_nal_unit_type); + else + u(6, nal_unit_type, 0, 63); + + u(6, nuh_layer_id, 0, 62); + u(3, nuh_temporal_id_plus1, 1, 7); + + return 0; +} + +static int FUNC(byte_alignment)(CodedBitstreamContext *ctx, RWContext *rw) +{ + int err; + av_unused int one = 1, zero = 0; + xu(1, alignment_bit_equal_to_one, one, 1, 1); + while (byte_alignment(rw) != 0) + xu(1, alignment_bit_equal_to_zero, zero, 0, 0); + + return 0; +} + +static int FUNC(extension_data)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawPSExtensionData *current) +{ + int err; + size_t k; +#ifdef READ + GetBitContext start; + uint8_t bit; + start = *rw; + for (k = 0; cbs_h2645_read_more_rbsp_data(rw); k++) + skip_bits(rw, 1); + current->bit_length = k; + if (k > 0) { + *rw = start; + allocate(current->data, (current->bit_length + 7) / 8); + for (k = 0; k < current->bit_length; k++) { + xu(1, extension_data, bit, 0, 1); + current->data[k / 8] |= bit << (7 - k % 8); + } + } +#else + for (k = 0; k < current->bit_length; k++) + xu(1, extension_data, current->data[k / 8] >> (7 - k % 8), 0, 1); +#endif + return 0; +} + +static int FUNC(profile_tier_level)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawProfileTierLevel *current, + int profile_present_flag, + int max_num_sub_layers_minus1) +{ + av_unused unsigned int zero = 0; + int err, i, j; + + if (profile_present_flag) { + u(2, general_profile_space, 0, 0); + flag(general_tier_flag); + u(5, general_profile_idc, 0, 31); + + for (j = 0; j < 32; j++) + flag(general_profile_compatibility_flag[j]); + + flag(general_progressive_source_flag); + flag(general_interlaced_source_flag); + flag(general_non_packed_constraint_flag); + flag(general_frame_only_constraint_flag); + +#define profile_compatible(x) (current->general_profile_idc == (x) || \ + current->general_profile_compatibility_flag[x]) + if (profile_compatible(4) || profile_compatible(5) || + profile_compatible(6) || profile_compatible(7) || + profile_compatible(8) || profile_compatible(9) || + profile_compatible(10)) { + flag(general_max_12bit_constraint_flag); + flag(general_max_10bit_constraint_flag); + flag(general_max_8bit_constraint_flag); + flag(general_max_422chroma_constraint_flag); + flag(general_max_420chroma_constraint_flag); + flag(general_max_monochrome_constraint_flag); + flag(general_intra_constraint_flag); + flag(general_one_picture_only_constraint_flag); + flag(general_lower_bit_rate_constraint_flag); + + if (profile_compatible(5) || profile_compatible(9) || + profile_compatible(10)) { + flag(general_max_14bit_constraint_flag); + xu(24, general_reserved_zero_33bits, zero, 0, 0); + xu(9, general_reserved_zero_33bits, zero, 0, 0); + } else { + xu(24, general_reserved_zero_34bits, zero, 0, 0); + xu(10, general_reserved_zero_34bits, zero, 0, 0); + } + } else { + xu(24, general_reserved_zero_43bits, zero, 0, 0); + xu(19, general_reserved_zero_43bits, zero, 0, 0); + } + + if (profile_compatible(1) || profile_compatible(2) || + profile_compatible(3) || profile_compatible(4) || + profile_compatible(5) || profile_compatible(9)) { + flag(general_inbld_flag); + } else { + xu(1, general_reserved_zero_bit, zero, 0, 0); + } +#undef profile_compatible + } + + u(8, general_level_idc, 0, 255); + + for (i = 0; i < max_num_sub_layers_minus1; i++) { + flag(sub_layer_profile_present_flag[i]); + flag(sub_layer_level_present_flag[i]); + } + + if (max_num_sub_layers_minus1 > 0) { + for (i = max_num_sub_layers_minus1; i < 8; i++) { + av_unused int zero = 0; + xu(2, reserved_zero_2bits, zero, 0, 0); + } + } + + for (i = 0; i < max_num_sub_layers_minus1; i++) { + if (current->sub_layer_profile_present_flag[i]) + return AVERROR_PATCHWELCOME; + if (current->sub_layer_level_present_flag[i]) + return AVERROR_PATCHWELCOME; + } + + return 0; +} + +static int FUNC(sub_layer_hrd_parameters)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawHRDParameters *hrd, + int nal, int sub_layer_id) +{ + H265RawSubLayerHRDParameters *current; + int err, i; + + if (nal) + current = &hrd->nal_sub_layer_hrd_parameters[sub_layer_id]; + else + current = &hrd->vcl_sub_layer_hrd_parameters[sub_layer_id]; + + for (i = 0; i <= hrd->cpb_cnt_minus1[sub_layer_id]; i++) { + ue(bit_rate_value_minus1[i], 0, UINT32_MAX - 1); + ue(cpb_size_value_minus1[i], 0, UINT32_MAX - 1); + if (hrd->sub_pic_hrd_params_present_flag) { + ue(cpb_size_du_value_minus1[i], 0, UINT32_MAX - 1); + ue(bit_rate_du_value_minus1[i], 0, UINT32_MAX - 1); + } + flag(cbr_flag[i]); + } + + return 0; +} + +static int FUNC(hrd_parameters)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawHRDParameters *current, int common_inf_present_flag, + int max_num_sub_layers_minus1) +{ + int err, i; + + if (common_inf_present_flag) { + flag(nal_hrd_parameters_present_flag); + flag(vcl_hrd_parameters_present_flag); + + if (current->nal_hrd_parameters_present_flag || + current->vcl_hrd_parameters_present_flag) { + flag(sub_pic_hrd_params_present_flag); + if (current->sub_pic_hrd_params_present_flag) { + u(8, tick_divisor_minus2, 0, 255); + u(5, du_cpb_removal_delay_increment_length_minus1, 0, 31); + flag(sub_pic_cpb_params_in_pic_timing_sei_flag); + u(5, dpb_output_delay_du_length_minus1, 0, 31); + } + + u(4, bit_rate_scale, 0, 15); + u(4, cpb_size_scale, 0, 15); + if (current->sub_pic_hrd_params_present_flag) + u(4, cpb_size_du_scale, 0, 15); + + u(5, initial_cpb_removal_delay_length_minus1, 0, 31); + u(5, au_cpb_removal_delay_length_minus1, 0, 31); + u(5, dpb_output_delay_length_minus1, 0, 31); + } else { + infer(sub_pic_hrd_params_present_flag, 0); + + infer(initial_cpb_removal_delay_length_minus1, 23); + infer(au_cpb_removal_delay_length_minus1, 23); + infer(dpb_output_delay_length_minus1, 23); + } + } + + for (i = 0; i <= max_num_sub_layers_minus1; i++) { + flag(fixed_pic_rate_general_flag[i]); + + if (!current->fixed_pic_rate_general_flag[i]) + flag(fixed_pic_rate_within_cvs_flag[i]); + else + infer(fixed_pic_rate_within_cvs_flag[i], 1); + + if (current->fixed_pic_rate_within_cvs_flag[i]) { + ue(elemental_duration_in_tc_minus1[i], 0, 2047); + infer(low_delay_hrd_flag[i], 0); + } else + flag(low_delay_hrd_flag[i]); + + if (!current->low_delay_hrd_flag[i]) + ue(cpb_cnt_minus1[i], 0, 31); + else + infer(cpb_cnt_minus1[i], 0); + + if (current->nal_hrd_parameters_present_flag) + CHECK(FUNC(sub_layer_hrd_parameters)(ctx, rw, current, 0, i)); + if (current->vcl_hrd_parameters_present_flag) + CHECK(FUNC(sub_layer_hrd_parameters)(ctx, rw, current, 1, i)); + } + + return 0; +} + +static int FUNC(vui_parameters)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawVUI *current, const H265RawSPS *sps) +{ + int err; + + flag(aspect_ratio_info_present_flag); + if (current->aspect_ratio_info_present_flag) { + u(8, aspect_ratio_idc, 0, 255); + if (current->aspect_ratio_idc == 255) { + u(16, sar_width, 0, 65535); + u(16, sar_height, 0, 65535); + } + } else { + infer(aspect_ratio_idc, 0); + } + + flag(overscan_info_present_flag); + if (current->overscan_info_present_flag) + flag(overscan_appropriate_flag); + + flag(video_signal_type_present_flag); + if (current->video_signal_type_present_flag) { + u(3, video_format, 0, 7); + flag(video_full_range_flag); + flag(colour_description_present_flag); + if (current->colour_description_present_flag) { + u(8, colour_primaries, 0, 255); + u(8, transfer_characteristics, 0, 255); + u(8, matrix_coefficients, 0, 255); + } else { + infer(colour_primaries, 2); + infer(transfer_characteristics, 2); + infer(matrix_coefficients, 2); + } + } else { + infer(video_format, 5); + infer(video_full_range_flag, 0); + infer(colour_primaries, 2); + infer(transfer_characteristics, 2); + infer(matrix_coefficients, 2); + } + + flag(chroma_loc_info_present_flag); + if (current->chroma_loc_info_present_flag) { + ue(chroma_sample_loc_type_top_field, 0, 5); + ue(chroma_sample_loc_type_bottom_field, 0, 5); + } else { + infer(chroma_sample_loc_type_top_field, 0); + infer(chroma_sample_loc_type_bottom_field, 0); + } + + flag(neutral_chroma_indication_flag); + flag(field_seq_flag); + flag(frame_field_info_present_flag); + + flag(default_display_window_flag); + if (current->default_display_window_flag) { + ue(def_disp_win_left_offset, 0, 16384); + ue(def_disp_win_right_offset, 0, 16384); + ue(def_disp_win_top_offset, 0, 16384); + ue(def_disp_win_bottom_offset, 0, 16384); + } + + flag(vui_timing_info_present_flag); + if (current->vui_timing_info_present_flag) { + u(32, vui_num_units_in_tick, 1, UINT32_MAX); + u(32, vui_time_scale, 1, UINT32_MAX); + flag(vui_poc_proportional_to_timing_flag); + if (current->vui_poc_proportional_to_timing_flag) + ue(vui_num_ticks_poc_diff_one_minus1, 0, UINT32_MAX - 1); + + flag(vui_hrd_parameters_present_flag); + if (current->vui_hrd_parameters_present_flag) { + CHECK(FUNC(hrd_parameters)(ctx, rw, ¤t->hrd_parameters, + 1, sps->sps_max_sub_layers_minus1)); + } + } + + flag(bitstream_restriction_flag); + if (current->bitstream_restriction_flag) { + flag(tiles_fixed_structure_flag); + flag(motion_vectors_over_pic_boundaries_flag); + flag(restricted_ref_pic_lists_flag); + ue(min_spatial_segmentation_idc, 0, 4095); + ue(max_bytes_per_pic_denom, 0, 16); + ue(max_bits_per_min_cu_denom, 0, 16); + ue(log2_max_mv_length_horizontal, 0, 16); + ue(log2_max_mv_length_vertical, 0, 16); + } else { + infer(tiles_fixed_structure_flag, 0); + infer(motion_vectors_over_pic_boundaries_flag, 1); + infer(min_spatial_segmentation_idc, 0); + infer(max_bytes_per_pic_denom, 2); + infer(max_bits_per_min_cu_denom, 1); + infer(log2_max_mv_length_horizontal, 15); + infer(log2_max_mv_length_vertical, 15); + } + + return 0; +} + +static int FUNC(vps)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawVPS *current) +{ + int err, i, j; + + HEADER("Video Parameter Set"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, HEVC_NAL_VPS)); + + u(4, vps_video_parameter_set_id, 0, 15); + + flag(vps_base_layer_internal_flag); + flag(vps_base_layer_available_flag); + u(6, vps_max_layers_minus1, 0, HEVC_MAX_LAYERS - 1); + u(3, vps_max_sub_layers_minus1, 0, HEVC_MAX_SUB_LAYERS - 1); + flag(vps_temporal_id_nesting_flag); + + if (current->vps_max_sub_layers_minus1 == 0 && + current->vps_temporal_id_nesting_flag != 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid stream: " + "vps_temporal_id_nesting_flag must be 1 if " + "vps_max_sub_layers_minus1 is 0.\n"); + return AVERROR_INVALIDDATA; + } + + { + av_unused uint16_t ffff = 0xffff; + xu(16, vps_reserved_0xffff_16bits, ffff, 0xffff, 0xffff); + } + + CHECK(FUNC(profile_tier_level)(ctx, rw, ¤t->profile_tier_level, + 1, current->vps_max_sub_layers_minus1)); + + flag(vps_sub_layer_ordering_info_present_flag); + for (i = (current->vps_sub_layer_ordering_info_present_flag ? + 0 : current->vps_max_sub_layers_minus1); + i <= current->vps_max_sub_layers_minus1; i++) { + ue(vps_max_dec_pic_buffering_minus1[i], 0, HEVC_MAX_DPB_SIZE - 1); + ue(vps_max_num_reorder_pics[i], 0, current->vps_max_dec_pic_buffering_minus1[i]); + ue(vps_max_latency_increase_plus1[i], 0, UINT32_MAX - 1); + } + if (!current->vps_sub_layer_ordering_info_present_flag) { + for (i = 0; i < current->vps_max_sub_layers_minus1; i++) { + infer(vps_max_dec_pic_buffering_minus1[i], + current->vps_max_dec_pic_buffering_minus1[current->vps_max_sub_layers_minus1]); + infer(vps_max_num_reorder_pics[i], + current->vps_max_num_reorder_pics[current->vps_max_sub_layers_minus1]); + infer(vps_max_latency_increase_plus1[i], + current->vps_max_latency_increase_plus1[current->vps_max_sub_layers_minus1]); + } + } + + u(6, vps_max_layer_id, 0, HEVC_MAX_LAYERS - 1); + ue(vps_num_layer_sets_minus1, 0, HEVC_MAX_LAYER_SETS - 1); + for (i = 1; i <= current->vps_num_layer_sets_minus1; i++) { + for (j = 0; j <= current->vps_max_layer_id; j++) + flag(layer_id_included_flag[i][j]); + } + for (j = 0; j <= current->vps_max_layer_id; j++) + infer(layer_id_included_flag[0][j], j == 0); + + flag(vps_timing_info_present_flag); + if (current->vps_timing_info_present_flag) { + u(32, vps_num_units_in_tick, 1, UINT32_MAX); + u(32, vps_time_scale, 1, UINT32_MAX); + flag(vps_poc_proportional_to_timing_flag); + if (current->vps_poc_proportional_to_timing_flag) + ue(vps_num_ticks_poc_diff_one_minus1, 0, UINT32_MAX - 1); + ue(vps_num_hrd_parameters, 0, current->vps_num_layer_sets_minus1 + 1); + for (i = 0; i < current->vps_num_hrd_parameters; i++) { + ue(hrd_layer_set_idx[i], + current->vps_base_layer_internal_flag ? 0 : 1, + current->vps_num_layer_sets_minus1); + if (i > 0) + flag(cprms_present_flag[i]); + else + infer(cprms_present_flag[0], 1); + + CHECK(FUNC(hrd_parameters)(ctx, rw, ¤t->hrd_parameters[i], + current->cprms_present_flag[i], + current->vps_max_sub_layers_minus1)); + } + } + + flag(vps_extension_flag); + if (current->vps_extension_flag) + CHECK(FUNC(extension_data)(ctx, rw, ¤t->extension_data)); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(st_ref_pic_set)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSTRefPicSet *current, int st_rps_idx, + const H265RawSPS *sps) +{ + int err, i, j; + + if (st_rps_idx != 0) + flag(inter_ref_pic_set_prediction_flag); + else + infer(inter_ref_pic_set_prediction_flag, 0); + + if (current->inter_ref_pic_set_prediction_flag) { + unsigned int ref_rps_idx, num_delta_pocs; + const H265RawSTRefPicSet *ref; + int delta_rps, d_poc; + int ref_delta_poc_s0[HEVC_MAX_REFS], ref_delta_poc_s1[HEVC_MAX_REFS]; + int delta_poc_s0[HEVC_MAX_REFS], delta_poc_s1[HEVC_MAX_REFS]; + uint8_t used_by_curr_pic_s0[HEVC_MAX_REFS], + used_by_curr_pic_s1[HEVC_MAX_REFS]; + + if (st_rps_idx == sps->num_short_term_ref_pic_sets) + ue(delta_idx_minus1, 0, st_rps_idx - 1); + else + infer(delta_idx_minus1, 0); + + ref_rps_idx = st_rps_idx - (current->delta_idx_minus1 + 1); + ref = &sps->st_ref_pic_set[ref_rps_idx]; + num_delta_pocs = ref->num_negative_pics + ref->num_positive_pics; + + flag(delta_rps_sign); + ue(abs_delta_rps_minus1, 0, INT16_MAX); + delta_rps = (1 - 2 * current->delta_rps_sign) * + (current->abs_delta_rps_minus1 + 1); + + for (j = 0; j <= num_delta_pocs; j++) { + flag(used_by_curr_pic_flag[j]); + if (!current->used_by_curr_pic_flag[j]) + flag(use_delta_flag[j]); + else + infer(use_delta_flag[j], 1); + } + + // Since the stored form of an RPS here is actually the delta-step + // form used when inter_ref_pic_set_prediction_flag is not set, we + // need to reconstruct that here in order to be able to refer to + // the RPS later (which is required for parsing, because we don't + // even know what syntax elements appear without it). Therefore, + // this code takes the delta-step form of the reference set, turns + // it into the delta-array form, applies the prediction process of + // 7.4.8, converts the result back to the delta-step form, and + // stores that as the current set for future use. Note that the + // inferences here mean that writers using prediction will need + // to fill in the delta-step values correctly as well - since the + // whole RPS prediction process is somewhat overly sophisticated, + // this hopefully forms a useful check for them to ensure their + // predicted form actually matches what was intended rather than + // an onerous additional requirement. + + d_poc = 0; + for (i = 0; i < ref->num_negative_pics; i++) { + d_poc -= ref->delta_poc_s0_minus1[i] + 1; + ref_delta_poc_s0[i] = d_poc; + } + d_poc = 0; + for (i = 0; i < ref->num_positive_pics; i++) { + d_poc += ref->delta_poc_s1_minus1[i] + 1; + ref_delta_poc_s1[i] = d_poc; + } + + i = 0; + for (j = ref->num_positive_pics - 1; j >= 0; j--) { + d_poc = ref_delta_poc_s1[j] + delta_rps; + if (d_poc < 0 && current->use_delta_flag[ref->num_negative_pics + j]) { + delta_poc_s0[i] = d_poc; + used_by_curr_pic_s0[i++] = + current->used_by_curr_pic_flag[ref->num_negative_pics + j]; + } + } + if (delta_rps < 0 && current->use_delta_flag[num_delta_pocs]) { + delta_poc_s0[i] = delta_rps; + used_by_curr_pic_s0[i++] = + current->used_by_curr_pic_flag[num_delta_pocs]; + } + for (j = 0; j < ref->num_negative_pics; j++) { + d_poc = ref_delta_poc_s0[j] + delta_rps; + if (d_poc < 0 && current->use_delta_flag[j]) { + delta_poc_s0[i] = d_poc; + used_by_curr_pic_s0[i++] = current->used_by_curr_pic_flag[j]; + } + } + + infer(num_negative_pics, i); + for (i = 0; i < current->num_negative_pics; i++) { + infer(delta_poc_s0_minus1[i], + -(delta_poc_s0[i] - (i == 0 ? 0 : delta_poc_s0[i - 1])) - 1); + infer(used_by_curr_pic_s0_flag[i], used_by_curr_pic_s0[i]); + } + + i = 0; + for (j = ref->num_negative_pics - 1; j >= 0; j--) { + d_poc = ref_delta_poc_s0[j] + delta_rps; + if (d_poc > 0 && current->use_delta_flag[j]) { + delta_poc_s1[i] = d_poc; + used_by_curr_pic_s1[i++] = current->used_by_curr_pic_flag[j]; + } + } + if (delta_rps > 0 && current->use_delta_flag[num_delta_pocs]) { + delta_poc_s1[i] = delta_rps; + used_by_curr_pic_s1[i++] = + current->used_by_curr_pic_flag[num_delta_pocs]; + } + for (j = 0; j < ref->num_positive_pics; j++) { + d_poc = ref_delta_poc_s1[j] + delta_rps; + if (d_poc > 0 && current->use_delta_flag[ref->num_negative_pics + j]) { + delta_poc_s1[i] = d_poc; + used_by_curr_pic_s1[i++] = + current->used_by_curr_pic_flag[ref->num_negative_pics + j]; + } + } + + infer(num_positive_pics, i); + for (i = 0; i < current->num_positive_pics; i++) { + infer(delta_poc_s1_minus1[i], + delta_poc_s1[i] - (i == 0 ? 0 : delta_poc_s1[i - 1]) - 1); + infer(used_by_curr_pic_s1_flag[i], used_by_curr_pic_s1[i]); + } + + } else { + ue(num_negative_pics, 0, 15); + ue(num_positive_pics, 0, 15 - current->num_negative_pics); + + for (i = 0; i < current->num_negative_pics; i++) { + ue(delta_poc_s0_minus1[i], 0, INT16_MAX); + flag(used_by_curr_pic_s0_flag[i]); + } + + for (i = 0; i < current->num_positive_pics; i++) { + ue(delta_poc_s1_minus1[i], 0, INT16_MAX); + flag(used_by_curr_pic_s1_flag[i]); + } + } + + return 0; +} + +static int FUNC(scaling_list_data)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawScalingList *current) +{ + int sizeId, matrixId; + int err, n, i; + + for (sizeId = 0; sizeId < 4; sizeId++) { + for (matrixId = 0; matrixId < 6; matrixId += (sizeId == 3 ? 3 : 1)) { + flag(scaling_list_pred_mode_flag[sizeId][matrixId]); + if (!current->scaling_list_pred_mode_flag[sizeId][matrixId]) { + ue(scaling_list_pred_matrix_id_delta[sizeId][matrixId], + 0, sizeId == 3 ? matrixId / 3 : matrixId); + } else { + n = FFMIN(64, 1 << (4 + (sizeId << 1))); + if (sizeId > 1) + se(scaling_list_dc_coef_minus8[sizeId - 2][matrixId], -7, +247); + for (i = 0; i < n; i++) { + xse(scaling_list_delta_coeff, + current->scaling_list_delta_coeff[sizeId][matrixId][i], + -128, +127); + } + } + } + } + + return 0; +} + +static int FUNC(sps_range_extension)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSPS *current) +{ + int err; + + flag(transform_skip_rotation_enabled_flag); + flag(transform_skip_context_enabled_flag); + flag(implicit_rdpcm_enabled_flag); + flag(explicit_rdpcm_enabled_flag); + flag(extended_precision_processing_flag); + flag(intra_smoothing_disabled_flag); + flag(high_precision_offsets_enabled_flag); + flag(persistent_rice_adaptation_enabled_flag); + flag(cabac_bypass_alignment_enabled_flag); + + return 0; +} + +static int FUNC(sps_scc_extension)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSPS *current) +{ + int err, comp, i; + + flag(sps_curr_pic_ref_enabled_flag); + + flag(palette_mode_enabled_flag); + if (current->palette_mode_enabled_flag) { + ue(palette_max_size, 0, 64); + ue(delta_palette_max_predictor_size, 0, 128); + + flag(sps_palette_predictor_initializer_present_flag); + if (current->sps_palette_predictor_initializer_present_flag) { + ue(sps_num_palette_predictor_initializer_minus1, 0, 128); + for (comp = 0; comp < (current->chroma_format_idc ? 3 : 1); comp++) { + int bit_depth = comp == 0 ? current->bit_depth_luma_minus8 + 8 + : current->bit_depth_chroma_minus8 + 8; + for (i = 0; i <= current->sps_num_palette_predictor_initializer_minus1; i++) + u(bit_depth, sps_palette_predictor_initializers[comp][i], + 0, (1 << bit_depth) - 1); + } + } + } + + u(2, motion_vector_resolution_control_idc, 0, 2); + flag(intra_boundary_filtering_disable_flag); + + return 0; +} + +static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSPS *current) +{ + CodedBitstreamH265Context *h265 = ctx->priv_data; + const H265RawVPS *vps; + int err, i; + unsigned int min_cb_log2_size_y, ctb_log2_size_y, + min_cb_size_y, min_tb_log2_size_y; + + HEADER("Sequence Parameter Set"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, HEVC_NAL_SPS)); + + u(4, sps_video_parameter_set_id, 0, 15); + h265->active_vps = vps = h265->vps[current->sps_video_parameter_set_id]; + + u(3, sps_max_sub_layers_minus1, 0, HEVC_MAX_SUB_LAYERS - 1); + flag(sps_temporal_id_nesting_flag); + if (vps) { + if (vps->vps_max_sub_layers_minus1 > current->sps_max_sub_layers_minus1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid stream: " + "sps_max_sub_layers_minus1 (%d) must be less than or equal to " + "vps_max_sub_layers_minus1 (%d).\n", + vps->vps_max_sub_layers_minus1, + current->sps_max_sub_layers_minus1); + return AVERROR_INVALIDDATA; + } + if (vps->vps_temporal_id_nesting_flag && + !current->sps_temporal_id_nesting_flag) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid stream: " + "sps_temporal_id_nesting_flag must be 1 if " + "vps_temporal_id_nesting_flag is 1.\n"); + return AVERROR_INVALIDDATA; + } + } + + CHECK(FUNC(profile_tier_level)(ctx, rw, ¤t->profile_tier_level, + 1, current->sps_max_sub_layers_minus1)); + + ue(sps_seq_parameter_set_id, 0, 15); + + ue(chroma_format_idc, 0, 3); + if (current->chroma_format_idc == 3) + flag(separate_colour_plane_flag); + else + infer(separate_colour_plane_flag, 0); + + ue(pic_width_in_luma_samples, 1, HEVC_MAX_WIDTH); + ue(pic_height_in_luma_samples, 1, HEVC_MAX_HEIGHT); + + flag(conformance_window_flag); + if (current->conformance_window_flag) { + ue(conf_win_left_offset, 0, current->pic_width_in_luma_samples); + ue(conf_win_right_offset, 0, current->pic_width_in_luma_samples); + ue(conf_win_top_offset, 0, current->pic_height_in_luma_samples); + ue(conf_win_bottom_offset, 0, current->pic_height_in_luma_samples); + } else { + infer(conf_win_left_offset, 0); + infer(conf_win_right_offset, 0); + infer(conf_win_top_offset, 0); + infer(conf_win_bottom_offset, 0); + } + + ue(bit_depth_luma_minus8, 0, 8); + ue(bit_depth_chroma_minus8, 0, 8); + + ue(log2_max_pic_order_cnt_lsb_minus4, 0, 12); + + flag(sps_sub_layer_ordering_info_present_flag); + for (i = (current->sps_sub_layer_ordering_info_present_flag ? + 0 : current->sps_max_sub_layers_minus1); + i <= current->sps_max_sub_layers_minus1; i++) { + ue(sps_max_dec_pic_buffering_minus1[i], 0, HEVC_MAX_DPB_SIZE - 1); + ue(sps_max_num_reorder_pics[i], 0, current->sps_max_dec_pic_buffering_minus1[i]); + ue(sps_max_latency_increase_plus1[i], 0, UINT32_MAX - 1); + } + if (!current->sps_sub_layer_ordering_info_present_flag) { + for (i = 0; i < current->sps_max_sub_layers_minus1; i++) { + infer(sps_max_dec_pic_buffering_minus1[i], + current->sps_max_dec_pic_buffering_minus1[current->sps_max_sub_layers_minus1]); + infer(sps_max_num_reorder_pics[i], + current->sps_max_num_reorder_pics[current->sps_max_sub_layers_minus1]); + infer(sps_max_latency_increase_plus1[i], + current->sps_max_latency_increase_plus1[current->sps_max_sub_layers_minus1]); + } + } + + ue(log2_min_luma_coding_block_size_minus3, 0, 3); + min_cb_log2_size_y = current->log2_min_luma_coding_block_size_minus3 + 3; + + ue(log2_diff_max_min_luma_coding_block_size, 0, 3); + ctb_log2_size_y = min_cb_log2_size_y + + current->log2_diff_max_min_luma_coding_block_size; + + min_cb_size_y = 1 << min_cb_log2_size_y; + if (current->pic_width_in_luma_samples % min_cb_size_y || + current->pic_height_in_luma_samples % min_cb_size_y) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid dimensions: %ux%u not divisible " + "by MinCbSizeY = %u.\n", current->pic_width_in_luma_samples, + current->pic_height_in_luma_samples, min_cb_size_y); + return AVERROR_INVALIDDATA; + } + + ue(log2_min_luma_transform_block_size_minus2, 0, min_cb_log2_size_y - 3); + min_tb_log2_size_y = current->log2_min_luma_transform_block_size_minus2 + 2; + + ue(log2_diff_max_min_luma_transform_block_size, + 0, FFMIN(ctb_log2_size_y, 5) - min_tb_log2_size_y); + + ue(max_transform_hierarchy_depth_inter, + 0, ctb_log2_size_y - min_tb_log2_size_y); + ue(max_transform_hierarchy_depth_intra, + 0, ctb_log2_size_y - min_tb_log2_size_y); + + flag(scaling_list_enabled_flag); + if (current->scaling_list_enabled_flag) { + flag(sps_scaling_list_data_present_flag); + if (current->sps_scaling_list_data_present_flag) + CHECK(FUNC(scaling_list_data)(ctx, rw, ¤t->scaling_list)); + } else { + infer(sps_scaling_list_data_present_flag, 0); + } + + flag(amp_enabled_flag); + flag(sample_adaptive_offset_enabled_flag); + + flag(pcm_enabled_flag); + if (current->pcm_enabled_flag) { + u(4, pcm_sample_bit_depth_luma_minus1, + 0, current->bit_depth_luma_minus8 + 8 - 1); + u(4, pcm_sample_bit_depth_chroma_minus1, + 0, current->bit_depth_chroma_minus8 + 8 - 1); + + ue(log2_min_pcm_luma_coding_block_size_minus3, + FFMIN(min_cb_log2_size_y, 5) - 3, FFMIN(ctb_log2_size_y, 5) - 3); + ue(log2_diff_max_min_pcm_luma_coding_block_size, + 0, FFMIN(ctb_log2_size_y, 5) - (current->log2_min_pcm_luma_coding_block_size_minus3 + 3)); + + flag(pcm_loop_filter_disabled_flag); + } + + ue(num_short_term_ref_pic_sets, 0, HEVC_MAX_SHORT_TERM_REF_PIC_SETS); + for (i = 0; i < current->num_short_term_ref_pic_sets; i++) + CHECK(FUNC(st_ref_pic_set)(ctx, rw, ¤t->st_ref_pic_set[i], i, current)); + + flag(long_term_ref_pics_present_flag); + if (current->long_term_ref_pics_present_flag) { + ue(num_long_term_ref_pics_sps, 0, HEVC_MAX_LONG_TERM_REF_PICS); + for (i = 0; i < current->num_long_term_ref_pics_sps; i++) { + u(current->log2_max_pic_order_cnt_lsb_minus4 + 4, + lt_ref_pic_poc_lsb_sps[i], + 0, (1 << (current->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1); + flag(used_by_curr_pic_lt_sps_flag[i]); + } + } + + flag(sps_temporal_mvp_enabled_flag); + flag(strong_intra_smoothing_enabled_flag); + + flag(vui_parameters_present_flag); + if (current->vui_parameters_present_flag) + CHECK(FUNC(vui_parameters)(ctx, rw, ¤t->vui, current)); + + flag(sps_extension_present_flag); + if (current->sps_extension_present_flag) { + flag(sps_range_extension_flag); + flag(sps_multilayer_extension_flag); + flag(sps_3d_extension_flag); + flag(sps_scc_extension_flag); + u(4, sps_extension_4bits, 0, (1 << 4) - 1); + } + + if (current->sps_range_extension_flag) + CHECK(FUNC(sps_range_extension)(ctx, rw, current)); + if (current->sps_multilayer_extension_flag) + return AVERROR_PATCHWELCOME; + if (current->sps_3d_extension_flag) + return AVERROR_PATCHWELCOME; + if (current->sps_scc_extension_flag) + CHECK(FUNC(sps_scc_extension)(ctx, rw, current)); + if (current->sps_extension_4bits) + CHECK(FUNC(extension_data)(ctx, rw, ¤t->extension_data)); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(pps_range_extension)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawPPS *current) +{ + CodedBitstreamH265Context *h265 = ctx->priv_data; + const H265RawSPS *sps = h265->active_sps; + int err, i; + + if (current->transform_skip_enabled_flag) + ue(log2_max_transform_skip_block_size_minus2, 0, 3); + flag(cross_component_prediction_enabled_flag); + + flag(chroma_qp_offset_list_enabled_flag); + if (current->chroma_qp_offset_list_enabled_flag) { + ue(diff_cu_chroma_qp_offset_depth, + 0, sps->log2_diff_max_min_luma_coding_block_size); + ue(chroma_qp_offset_list_len_minus1, 0, 5); + for (i = 0; i <= current->chroma_qp_offset_list_len_minus1; i++) { + se(cb_qp_offset_list[i], -12, +12); + se(cr_qp_offset_list[i], -12, +12); + } + } + + ue(log2_sao_offset_scale_luma, 0, FFMAX(0, sps->bit_depth_luma_minus8 - 2)); + ue(log2_sao_offset_scale_chroma, 0, FFMAX(0, sps->bit_depth_chroma_minus8 - 2)); + + return 0; +} + +static int FUNC(pps_scc_extension)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawPPS *current) +{ + int err, comp, i; + + flag(pps_curr_pic_ref_enabled_flag); + + flag(residual_adaptive_colour_transform_enabled_flag); + if (current->residual_adaptive_colour_transform_enabled_flag) { + flag(pps_slice_act_qp_offsets_present_flag); + se(pps_act_y_qp_offset_plus5, -7, +17); + se(pps_act_cb_qp_offset_plus5, -7, +17); + se(pps_act_cr_qp_offset_plus3, -9, +15); + } else { + infer(pps_slice_act_qp_offsets_present_flag, 0); + infer(pps_act_y_qp_offset_plus5, 0); + infer(pps_act_cb_qp_offset_plus5, 0); + infer(pps_act_cr_qp_offset_plus3, 0); + } + + flag(pps_palette_predictor_initializer_present_flag); + if (current->pps_palette_predictor_initializer_present_flag) { + ue(pps_num_palette_predictor_initializer, 0, 128); + if (current->pps_num_palette_predictor_initializer > 0) { + flag(monochrome_palette_flag); + ue(luma_bit_depth_entry_minus8, 0, 8); + if (!current->monochrome_palette_flag) + ue(chroma_bit_depth_entry_minus8, 0, 8); + for (comp = 0; comp < (current->monochrome_palette_flag ? 1 : 3); comp++) { + int bit_depth = comp == 0 ? current->luma_bit_depth_entry_minus8 + 8 + : current->chroma_bit_depth_entry_minus8 + 8; + for (i = 0; i < current->pps_num_palette_predictor_initializer; i++) + u(bit_depth, pps_palette_predictor_initializers[comp][i], + 0, (1 << bit_depth) - 1); + } + } + } + + return 0; +} + +static int FUNC(pps)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawPPS *current) +{ + CodedBitstreamH265Context *h265 = ctx->priv_data; + const H265RawSPS *sps; + int err, i; + + HEADER("Picture Parameter Set"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, HEVC_NAL_PPS)); + + ue(pps_pic_parameter_set_id, 0, 63); + ue(pps_seq_parameter_set_id, 0, 15); + sps = h265->sps[current->pps_seq_parameter_set_id]; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SPS id %d not available.\n", + current->pps_seq_parameter_set_id); + return AVERROR_INVALIDDATA; + } + h265->active_sps = sps; + + flag(dependent_slice_segments_enabled_flag); + flag(output_flag_present_flag); + u(3, num_extra_slice_header_bits, 0, 7); + flag(sign_data_hiding_enabled_flag); + flag(cabac_init_present_flag); + + ue(num_ref_idx_l0_default_active_minus1, 0, 14); + ue(num_ref_idx_l1_default_active_minus1, 0, 14); + + se(init_qp_minus26, -(26 + 6 * sps->bit_depth_luma_minus8), +25); + + flag(constrained_intra_pred_flag); + flag(transform_skip_enabled_flag); + flag(cu_qp_delta_enabled_flag); + if (current->cu_qp_delta_enabled_flag) + ue(diff_cu_qp_delta_depth, + 0, sps->log2_diff_max_min_luma_coding_block_size); + else + infer(diff_cu_qp_delta_depth, 0); + + se(pps_cb_qp_offset, -12, +12); + se(pps_cr_qp_offset, -12, +12); + flag(pps_slice_chroma_qp_offsets_present_flag); + + flag(weighted_pred_flag); + flag(weighted_bipred_flag); + + flag(transquant_bypass_enabled_flag); + flag(tiles_enabled_flag); + flag(entropy_coding_sync_enabled_flag); + + if (current->tiles_enabled_flag) { + ue(num_tile_columns_minus1, 0, HEVC_MAX_TILE_COLUMNS); + ue(num_tile_rows_minus1, 0, HEVC_MAX_TILE_ROWS); + flag(uniform_spacing_flag); + if (!current->uniform_spacing_flag) { + for (i = 0; i < current->num_tile_columns_minus1; i++) + ue(column_width_minus1[i], 0, sps->pic_width_in_luma_samples); + for (i = 0; i < current->num_tile_rows_minus1; i++) + ue(row_height_minus1[i], 0, sps->pic_height_in_luma_samples); + } + flag(loop_filter_across_tiles_enabled_flag); + } else { + infer(num_tile_columns_minus1, 0); + infer(num_tile_rows_minus1, 0); + } + + flag(pps_loop_filter_across_slices_enabled_flag); + flag(deblocking_filter_control_present_flag); + if (current->deblocking_filter_control_present_flag) { + flag(deblocking_filter_override_enabled_flag); + flag(pps_deblocking_filter_disabled_flag); + if (!current->pps_deblocking_filter_disabled_flag) { + se(pps_beta_offset_div2, -6, +6); + se(pps_tc_offset_div2, -6, +6); + } else { + infer(pps_beta_offset_div2, 0); + infer(pps_tc_offset_div2, 0); + } + } else { + infer(deblocking_filter_override_enabled_flag, 0); + infer(pps_deblocking_filter_disabled_flag, 0); + infer(pps_beta_offset_div2, 0); + infer(pps_tc_offset_div2, 0); + } + + flag(pps_scaling_list_data_present_flag); + if (current->pps_scaling_list_data_present_flag) + CHECK(FUNC(scaling_list_data)(ctx, rw, ¤t->scaling_list)); + + flag(lists_modification_present_flag); + + ue(log2_parallel_merge_level_minus2, + 0, (sps->log2_min_luma_coding_block_size_minus3 + 3 + + sps->log2_diff_max_min_luma_coding_block_size - 2)); + + flag(slice_segment_header_extension_present_flag); + + flag(pps_extension_present_flag); + if (current->pps_extension_present_flag) { + flag(pps_range_extension_flag); + flag(pps_multilayer_extension_flag); + flag(pps_3d_extension_flag); + flag(pps_scc_extension_flag); + u(4, pps_extension_4bits, 0, (1 << 4) - 1); + } + if (current->pps_range_extension_flag) + CHECK(FUNC(pps_range_extension)(ctx, rw, current)); + if (current->pps_multilayer_extension_flag) + return AVERROR_PATCHWELCOME; + if (current->pps_3d_extension_flag) + return AVERROR_PATCHWELCOME; + if (current->pps_scc_extension_flag) + CHECK(FUNC(pps_scc_extension)(ctx, rw, current)); + if (current->pps_extension_4bits) + CHECK(FUNC(extension_data)(ctx, rw, ¤t->extension_data)); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(aud)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawAUD *current) +{ + int err; + + HEADER("Access Unit Delimiter"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, HEVC_NAL_AUD)); + + u(3, pic_type, 0, 2); + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} + +static int FUNC(ref_pic_lists_modification)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSliceHeader *current, + unsigned int num_pic_total_curr) +{ + unsigned int entry_size; + int err, i; + + entry_size = av_log2(num_pic_total_curr - 1) + 1; + + flag(ref_pic_list_modification_flag_l0); + if (current->ref_pic_list_modification_flag_l0) { + for (i = 0; i <= current->num_ref_idx_l0_active_minus1; i++) + u(entry_size, list_entry_l0[i], 0, num_pic_total_curr - 1); + } + + if (current->slice_type == HEVC_SLICE_B) { + flag(ref_pic_list_modification_flag_l1); + if (current->ref_pic_list_modification_flag_l1) { + for (i = 0; i <= current->num_ref_idx_l1_active_minus1; i++) + u(entry_size, list_entry_l1[i], 0, num_pic_total_curr - 1); + } + } + + return 0; +} + +static int FUNC(pred_weight_table)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSliceHeader *current) +{ + CodedBitstreamH265Context *h265 = ctx->priv_data; + const H265RawSPS *sps = h265->active_sps; + int err, i, j; + int chroma = !sps->separate_colour_plane_flag && + sps->chroma_format_idc != 0; + + ue(luma_log2_weight_denom, 0, 7); + if (chroma) + se(delta_chroma_log2_weight_denom, -7, 7); + else + infer(delta_chroma_log2_weight_denom, 0); + + for (i = 0; i <= current->num_ref_idx_l0_active_minus1; i++) { + if (1 /* is not same POC and same layer_id */) + flag(luma_weight_l0_flag[i]); + else + infer(luma_weight_l0_flag[i], 0); + } + if (chroma) { + for (i = 0; i <= current->num_ref_idx_l0_active_minus1; i++) { + if (1 /* is not same POC and same layer_id */) + flag(chroma_weight_l0_flag[i]); + else + infer(chroma_weight_l0_flag[i], 0); + } + } + + for (i = 0; i <= current->num_ref_idx_l0_active_minus1; i++) { + if (current->luma_weight_l0_flag[i]) { + se(delta_luma_weight_l0[i], -128, +127); + se(luma_offset_l0[i], + -(1 << (sps->bit_depth_luma_minus8 + 8 - 1)), + ((1 << (sps->bit_depth_luma_minus8 + 8 - 1)) - 1)); + } else { + infer(delta_luma_weight_l0[i], 0); + infer(luma_offset_l0[i], 0); + } + if (current->chroma_weight_l0_flag[i]) { + for (j = 0; j < 2; j++) { + se(delta_chroma_weight_l0[i][j], -128, +127); + se(chroma_offset_l0[i][j], + -(4 << (sps->bit_depth_chroma_minus8 + 8 - 1)), + ((4 << (sps->bit_depth_chroma_minus8 + 8 - 1)) - 1)); + } + } else { + for (j = 0; j < 2; j++) { + infer(delta_chroma_weight_l0[i][j], 0); + infer(chroma_offset_l0[i][j], 0); + } + } + } + + if (current->slice_type == HEVC_SLICE_B) { + for (i = 0; i <= current->num_ref_idx_l1_active_minus1; i++) { + if (1 /* RefPicList1[i] is not CurrPic, nor is it in a different layer */) + flag(luma_weight_l1_flag[i]); + else + infer(luma_weight_l1_flag[i], 0); + } + if (chroma) { + for (i = 0; i <= current->num_ref_idx_l1_active_minus1; i++) { + if (1 /* RefPicList1[i] is not CurrPic, nor is it in a different layer */) + flag(chroma_weight_l1_flag[i]); + else + infer(chroma_weight_l1_flag[i], 0); + } + } + + for (i = 0; i <= current->num_ref_idx_l1_active_minus1; i++) { + if (current->luma_weight_l1_flag[i]) { + se(delta_luma_weight_l1[i], -128, +127); + se(luma_offset_l1[i], + -(1 << (sps->bit_depth_luma_minus8 + 8 - 1)), + ((1 << (sps->bit_depth_luma_minus8 + 8 - 1)) - 1)); + } else { + infer(delta_luma_weight_l1[i], 0); + infer(luma_offset_l1[i], 0); + } + if (current->chroma_weight_l1_flag[i]) { + for (j = 0; j < 2; j++) { + se(delta_chroma_weight_l1[i][j], -128, +127); + se(chroma_offset_l1[i][j], + -(4 << (sps->bit_depth_chroma_minus8 + 8 - 1)), + ((4 << (sps->bit_depth_chroma_minus8 + 8 - 1)) - 1)); + } + } else { + for (j = 0; j < 2; j++) { + infer(delta_chroma_weight_l1[i][j], 0); + infer(chroma_offset_l1[i][j], 0); + } + } + } + } + + return 0; +} + +static int FUNC(slice_segment_header)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawSliceHeader *current) +{ + CodedBitstreamH265Context *h265 = ctx->priv_data; + const H265RawSPS *sps; + const H265RawPPS *pps; + unsigned int min_cb_log2_size_y, ctb_log2_size_y, ctb_size_y; + unsigned int pic_width_in_ctbs_y, pic_height_in_ctbs_y, pic_size_in_ctbs_y; + unsigned int num_pic_total_curr = 0; + int err, i; + + HEADER("Slice Segment Header"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, -1)); + + flag(first_slice_segment_in_pic_flag); + + if (current->nal_unit_header.nal_unit_type >= HEVC_NAL_BLA_W_LP && + current->nal_unit_header.nal_unit_type <= HEVC_NAL_IRAP_VCL23) + flag(no_output_of_prior_pics_flag); + + ue(slice_pic_parameter_set_id, 0, 63); + + pps = h265->pps[current->slice_pic_parameter_set_id]; + if (!pps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "PPS id %d not available.\n", + current->slice_pic_parameter_set_id); + return AVERROR_INVALIDDATA; + } + h265->active_pps = pps; + + sps = h265->sps[pps->pps_seq_parameter_set_id]; + if (!sps) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "SPS id %d not available.\n", + pps->pps_seq_parameter_set_id); + return AVERROR_INVALIDDATA; + } + h265->active_sps = sps; + + min_cb_log2_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3; + ctb_log2_size_y = min_cb_log2_size_y + sps->log2_diff_max_min_luma_coding_block_size; + ctb_size_y = 1 << ctb_log2_size_y; + pic_width_in_ctbs_y = + (sps->pic_width_in_luma_samples + ctb_size_y - 1) / ctb_size_y; + pic_height_in_ctbs_y = + (sps->pic_height_in_luma_samples + ctb_size_y - 1) / ctb_size_y; + pic_size_in_ctbs_y = pic_width_in_ctbs_y * pic_height_in_ctbs_y; + + if (!current->first_slice_segment_in_pic_flag) { + unsigned int address_size = av_log2(pic_size_in_ctbs_y - 1) + 1; + if (pps->dependent_slice_segments_enabled_flag) + flag(dependent_slice_segment_flag); + else + infer(dependent_slice_segment_flag, 0); + u(address_size, slice_segment_address, 0, pic_size_in_ctbs_y - 1); + } else { + infer(dependent_slice_segment_flag, 0); + } + + if (!current->dependent_slice_segment_flag) { + for (i = 0; i < pps->num_extra_slice_header_bits; i++) + flag(slice_reserved_flag[i]); + + ue(slice_type, 0, 2); + + if (pps->output_flag_present_flag) + flag(pic_output_flag); + + if (sps->separate_colour_plane_flag) + u(2, colour_plane_id, 0, 2); + + if (current->nal_unit_header.nal_unit_type != HEVC_NAL_IDR_W_RADL && + current->nal_unit_header.nal_unit_type != HEVC_NAL_IDR_N_LP) { + const H265RawSTRefPicSet *rps; + + u(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, slice_pic_order_cnt_lsb, + 0, (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1); + + flag(short_term_ref_pic_set_sps_flag); + if (!current->short_term_ref_pic_set_sps_flag) { + CHECK(FUNC(st_ref_pic_set)(ctx, rw, ¤t->short_term_ref_pic_set, + sps->num_short_term_ref_pic_sets, sps)); + rps = ¤t->short_term_ref_pic_set; + } else if (sps->num_short_term_ref_pic_sets > 1) { + unsigned int idx_size = av_log2(sps->num_short_term_ref_pic_sets - 1) + 1; + u(idx_size, short_term_ref_pic_set_idx, + 0, sps->num_short_term_ref_pic_sets - 1); + rps = &sps->st_ref_pic_set[current->short_term_ref_pic_set_idx]; + } else { + infer(short_term_ref_pic_set_idx, 0); + rps = &sps->st_ref_pic_set[0]; + } + + num_pic_total_curr = 0; + for (i = 0; i < rps->num_negative_pics; i++) + if (rps->used_by_curr_pic_s0_flag[i]) + ++num_pic_total_curr; + for (i = 0; i < rps->num_positive_pics; i++) + if (rps->used_by_curr_pic_s1_flag[i]) + ++num_pic_total_curr; + + if (sps->long_term_ref_pics_present_flag) { + unsigned int idx_size; + + if (sps->num_long_term_ref_pics_sps > 0) { + ue(num_long_term_sps, 0, sps->num_long_term_ref_pics_sps); + idx_size = av_log2(sps->num_long_term_ref_pics_sps - 1) + 1; + } else { + infer(num_long_term_sps, 0); + idx_size = 0; + } + ue(num_long_term_pics, 0, HEVC_MAX_LONG_TERM_REF_PICS); + + for (i = 0; i < current->num_long_term_sps + + current->num_long_term_pics; i++) { + if (i < current->num_long_term_sps) { + if (sps->num_long_term_ref_pics_sps > 1) + u(idx_size, lt_idx_sps[i], + 0, sps->num_long_term_ref_pics_sps - 1); + if (sps->used_by_curr_pic_lt_sps_flag[current->lt_idx_sps[i]]) + ++num_pic_total_curr; + } else { + u(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, poc_lsb_lt[i], + 0, (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1); + flag(used_by_curr_pic_lt_flag[i]); + if (current->used_by_curr_pic_lt_flag[i]) + ++num_pic_total_curr; + } + flag(delta_poc_msb_present_flag[i]); + if (current->delta_poc_msb_present_flag[i]) + ue(delta_poc_msb_cycle_lt[i], 0, UINT32_MAX - 1); + else + infer(delta_poc_msb_cycle_lt[i], 0); + } + } + + if (sps->sps_temporal_mvp_enabled_flag) + flag(slice_temporal_mvp_enabled_flag); + else + infer(slice_temporal_mvp_enabled_flag, 0); + + if (pps->pps_curr_pic_ref_enabled_flag) + ++num_pic_total_curr; + } + + if (sps->sample_adaptive_offset_enabled_flag) { + flag(slice_sao_luma_flag); + if (!sps->separate_colour_plane_flag && sps->chroma_format_idc != 0) + flag(slice_sao_chroma_flag); + else + infer(slice_sao_chroma_flag, 0); + } else { + infer(slice_sao_luma_flag, 0); + infer(slice_sao_chroma_flag, 0); + } + + if (current->slice_type == HEVC_SLICE_P || + current->slice_type == HEVC_SLICE_B) { + flag(num_ref_idx_active_override_flag); + if (current->num_ref_idx_active_override_flag) { + ue(num_ref_idx_l0_active_minus1, 0, 14); + if (current->slice_type == HEVC_SLICE_B) + ue(num_ref_idx_l1_active_minus1, 0, 14); + else + infer(num_ref_idx_l1_active_minus1, pps->num_ref_idx_l1_default_active_minus1); + } else { + infer(num_ref_idx_l0_active_minus1, pps->num_ref_idx_l0_default_active_minus1); + infer(num_ref_idx_l1_active_minus1, pps->num_ref_idx_l1_default_active_minus1); + } + + if (pps->lists_modification_present_flag && num_pic_total_curr > 1) + CHECK(FUNC(ref_pic_lists_modification)(ctx, rw, current, + num_pic_total_curr)); + + if (current->slice_type == HEVC_SLICE_B) + flag(mvd_l1_zero_flag); + if (pps->cabac_init_present_flag) + flag(cabac_init_flag); + else + infer(cabac_init_flag, 0); + if (current->slice_temporal_mvp_enabled_flag) { + if (current->slice_type == HEVC_SLICE_B) + flag(collocated_from_l0_flag); + else + infer(collocated_from_l0_flag, 1); + if (current->collocated_from_l0_flag) { + if (current->num_ref_idx_l0_active_minus1 > 0) + ue(collocated_ref_idx, 0, current->num_ref_idx_l0_active_minus1); + else + infer(collocated_ref_idx, 0); + } else { + if (current->num_ref_idx_l1_active_minus1 > 0) + ue(collocated_ref_idx, 0, current->num_ref_idx_l1_active_minus1); + else + infer(collocated_ref_idx, 0); + } + } + + if ((pps->weighted_pred_flag && current->slice_type == HEVC_SLICE_P) || + (pps->weighted_bipred_flag && current->slice_type == HEVC_SLICE_B)) + CHECK(FUNC(pred_weight_table)(ctx, rw, current)); + + ue(five_minus_max_num_merge_cand, 0, 4); + if (sps->motion_vector_resolution_control_idc == 2) + flag(use_integer_mv_flag); + else + infer(use_integer_mv_flag, sps->motion_vector_resolution_control_idc); + } + + se(slice_qp_delta, + - 6 * sps->bit_depth_luma_minus8 - (pps->init_qp_minus26 + 26), + + 51 - (pps->init_qp_minus26 + 26)); + if (pps->pps_slice_chroma_qp_offsets_present_flag) { + se(slice_cb_qp_offset, -12, +12); + se(slice_cr_qp_offset, -12, +12); + } else { + infer(slice_cb_qp_offset, 0); + infer(slice_cr_qp_offset, 0); + } + if (pps->pps_slice_act_qp_offsets_present_flag) { + se(slice_act_y_qp_offset, + -12 - (pps->pps_act_y_qp_offset_plus5 - 5), + +12 - (pps->pps_act_y_qp_offset_plus5 - 5)); + se(slice_act_cb_qp_offset, + -12 - (pps->pps_act_cb_qp_offset_plus5 - 5), + +12 - (pps->pps_act_cb_qp_offset_plus5 - 5)); + se(slice_act_cr_qp_offset, + -12 - (pps->pps_act_cr_qp_offset_plus3 - 3), + +12 - (pps->pps_act_cr_qp_offset_plus3 - 3)); + } else { + infer(slice_act_y_qp_offset, 0); + infer(slice_act_cb_qp_offset, 0); + infer(slice_act_cr_qp_offset, 0); + } + if (pps->chroma_qp_offset_list_enabled_flag) + flag(cu_chroma_qp_offset_enabled_flag); + else + infer(cu_chroma_qp_offset_enabled_flag, 0); + + if (pps->deblocking_filter_override_enabled_flag) + flag(deblocking_filter_override_flag); + else + infer(deblocking_filter_override_flag, 0); + if (current->deblocking_filter_override_flag) { + flag(slice_deblocking_filter_disabled_flag); + if (!current->slice_deblocking_filter_disabled_flag) { + se(slice_beta_offset_div2, -6, +6); + se(slice_tc_offset_div2, -6, +6); + } else { + infer(slice_beta_offset_div2, pps->pps_beta_offset_div2); + infer(slice_tc_offset_div2, pps->pps_tc_offset_div2); + } + } else { + infer(slice_deblocking_filter_disabled_flag, + pps->pps_deblocking_filter_disabled_flag); + infer(slice_beta_offset_div2, pps->pps_beta_offset_div2); + infer(slice_tc_offset_div2, pps->pps_tc_offset_div2); + } + if (pps->pps_loop_filter_across_slices_enabled_flag && + (current->slice_sao_luma_flag || current->slice_sao_chroma_flag || + !current->slice_deblocking_filter_disabled_flag)) + flag(slice_loop_filter_across_slices_enabled_flag); + else + infer(slice_loop_filter_across_slices_enabled_flag, + pps->pps_loop_filter_across_slices_enabled_flag); + } + + if (pps->tiles_enabled_flag || pps->entropy_coding_sync_enabled_flag) { + unsigned int num_entry_point_offsets_limit; + if (!pps->tiles_enabled_flag && pps->entropy_coding_sync_enabled_flag) + num_entry_point_offsets_limit = pic_height_in_ctbs_y - 1; + else if (pps->tiles_enabled_flag && !pps->entropy_coding_sync_enabled_flag) + num_entry_point_offsets_limit = + (pps->num_tile_columns_minus1 + 1) * (pps->num_tile_rows_minus1 + 1); + else + num_entry_point_offsets_limit = + (pps->num_tile_columns_minus1 + 1) * pic_height_in_ctbs_y - 1; + ue(num_entry_point_offsets, 0, num_entry_point_offsets_limit); + + if (current->num_entry_point_offsets > HEVC_MAX_ENTRY_POINT_OFFSETS) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many entry points: " + "%"PRIu16".\n", current->num_entry_point_offsets); + return AVERROR_PATCHWELCOME; + } + + if (current->num_entry_point_offsets > 0) { + ue(offset_len_minus1, 0, 31); + for (i = 0; i < current->num_entry_point_offsets; i++) + u(current->offset_len_minus1 + 1, entry_point_offset_minus1[i], + 0, (1 << (current->offset_len_minus1 + 1)) - 1); + } + } + + if (pps->slice_segment_header_extension_present_flag) { + ue(slice_segment_header_extension_length, 0, 256); + for (i = 0; i < current->slice_segment_header_extension_length; i++) + u(8, slice_segment_header_extension_data_byte[i], 0x00, 0xff); + } + + CHECK(FUNC(byte_alignment)(ctx, rw)); + + return 0; +} diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index 2d417d4a40ae4..f8263bef0a35f 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -84,6 +84,7 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc, extern const CodedBitstreamType ff_cbs_type_h264; +extern const CodedBitstreamType ff_cbs_type_h265; #endif /* AVCODEC_CBS_INTERNAL_H */ From 686e388bbb6aeef077095a83f84b53d143d44d63 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 4 May 2017 23:03:03 +0100 Subject: [PATCH 0503/2557] lavc: Add coded bitstream read/write support for MPEG-2 (cherry picked from commit 2bc9ba8d3c41f3a8e56484bd67b05040c7909a01) (cherry picked from commit a41b69b5eb950c10d8ede472bcc4e88ce4246db9) --- configure | 2 + libavcodec/Makefile | 1 + libavcodec/cbs.c | 3 + libavcodec/cbs.h | 1 + libavcodec/cbs_internal.h | 1 + libavcodec/cbs_mpeg2.c | 414 +++++++++++++++++++++++++ libavcodec/cbs_mpeg2.h | 224 +++++++++++++ libavcodec/cbs_mpeg2_syntax_template.c | 384 +++++++++++++++++++++++ 8 files changed, 1030 insertions(+) create mode 100644 libavcodec/cbs_mpeg2.c create mode 100644 libavcodec/cbs_mpeg2.h create mode 100644 libavcodec/cbs_mpeg2_syntax_template.c diff --git a/configure b/configure index e5bfbaabf2229..bb0a748f9e4d9 100755 --- a/configure +++ b/configure @@ -2153,6 +2153,7 @@ CONFIG_EXTRA=" cbs cbs_h264 cbs_h265 + cbs_mpeg2 dirac_parse dvprofile exif @@ -2408,6 +2409,7 @@ threads_if_any="$THREADS_LIST" # subsystems cbs_h264_select="cbs golomb" cbs_h265_select="cbs golomb" +cbs_mpeg2_select="cbs" dct_select="rdft" dirac_parse_select="golomb" error_resilience_select="me_cmp" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 39b7dd1e2f296..0265c921309a3 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -62,6 +62,7 @@ OBJS-$(CONFIG_CABAC) += cabac.o OBJS-$(CONFIG_CBS) += cbs.o OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o h2645_parse.o OBJS-$(CONFIG_CBS_H265) += cbs_h2645.o h2645_parse.o +OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index d7eb3033c4caf..97ab520c22ae5 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -34,6 +34,9 @@ static const CodedBitstreamType *cbs_type_table[] = { #if CONFIG_CBS_H265 &ff_cbs_type_h265, #endif +#if CONFIG_CBS_MPEG2 + &ff_cbs_type_mpeg2, +#endif }; int ff_cbs_init(CodedBitstreamContext **ctx_ptr, diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h index a367fd0bf600f..ff97880610767 100644 --- a/libavcodec/cbs.h +++ b/libavcodec/cbs.h @@ -45,6 +45,7 @@ struct CodedBitstreamType; * * H.264 / AVC: nal_unit_type * H.265 / HEVC: nal_unit_type + * MPEG-2: start code value (without prefix) */ typedef uint32_t CodedBitstreamUnitType; diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index f8263bef0a35f..ae0b417b43afe 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -85,6 +85,7 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc, extern const CodedBitstreamType ff_cbs_type_h264; extern const CodedBitstreamType ff_cbs_type_h265; +extern const CodedBitstreamType ff_cbs_type_mpeg2; #endif /* AVCODEC_CBS_INTERNAL_H */ diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c new file mode 100644 index 0000000000000..d137762227330 --- /dev/null +++ b/libavcodec/cbs_mpeg2.c @@ -0,0 +1,414 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" + +#include "cbs.h" +#include "cbs_internal.h" +#include "cbs_mpeg2.h" +#include "internal.h" + + +#define HEADER(name) do { \ + ff_cbs_trace_header(ctx, name); \ + } while (0) + +#define CHECK(call) do { \ + err = (call); \ + if (err < 0) \ + return err; \ + } while (0) + +#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name +#define FUNC_MPEG2(rw, name) FUNC_NAME(rw, mpeg2, name) +#define FUNC(name) FUNC_MPEG2(READWRITE, name) + + +#define READ +#define READWRITE read +#define RWContext GetBitContext + +#define xui(width, name, var) do { \ + uint32_t value = 0; \ + CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \ + &value, 0, (1 << width) - 1)); \ + var = value; \ + } while (0) + +#define ui(width, name) \ + xui(width, name, current->name) + +#define marker_bit() do { \ + av_unused int one = 1; \ + CHECK(ff_cbs_read_unsigned(ctx, rw, 1, "marker_bit", &one, 1, 1)); \ + } while (0) + +#define nextbits(width, compare, var) \ + (get_bits_left(rw) >= width && \ + (var = show_bits(rw, width)) == (compare)) + +#include "cbs_mpeg2_syntax_template.c" + +#undef READ +#undef READWRITE +#undef RWContext +#undef xui +#undef ui +#undef marker_bit +#undef nextbits + + +#define WRITE +#define READWRITE write +#define RWContext PutBitContext + +#define xui(width, name, var) do { \ + CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \ + var, 0, (1 << width) - 1)); \ + } while (0) + +#define ui(width, name) \ + xui(width, name, current->name) + +#define marker_bit() do { \ + CHECK(ff_cbs_write_unsigned(ctx, rw, 1, "marker_bit", 1, 1, 1)); \ + } while (0) + +#define nextbits(width, compare, var) (var) + +#include "cbs_mpeg2_syntax_template.c" + +#undef READ +#undef READWRITE +#undef RWContext +#undef xui +#undef ui +#undef marker_bit +#undef nextbits + + +static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int header) +{ + const uint8_t *start, *end; + uint8_t *unit_data; + uint32_t start_code = -1, next_start_code = -1; + size_t unit_size; + int err, i, unit_type; + + start = avpriv_find_start_code(frag->data, frag->data + frag->data_size, + &start_code); + for (i = 0;; i++) { + end = avpriv_find_start_code(start, frag->data + frag->data_size, + &next_start_code); + + unit_type = start_code & 0xff; + + // The start and end pointers point at to the byte following the + // start_code_identifier in the start code that they found. + if (end == frag->data + frag->data_size) { + // We didn't find a start code, so this is the final unit. + unit_size = end - (start - 1); + } else { + // Unit runs from start to the beginning of the start code + // pointed to by end (including any padding zeroes). + unit_size = (end - 4) - (start - 1); + } + + unit_data = av_malloc(unit_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!unit_data) + return AVERROR(ENOMEM); + memcpy(unit_data, start - 1, unit_size); + memset(unit_data + unit_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + err = ff_cbs_insert_unit_data(ctx, frag, i, unit_type, + unit_data, unit_size); + if (err < 0) { + av_freep(&unit_data); + return err; + } + + if (end == frag->data + frag->data_size) + break; + + start_code = next_start_code; + start = end; + } + + return 0; +} + +static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + GetBitContext gbc; + int err; + + err = init_get_bits(&gbc, unit->data, 8 * unit->data_size); + if (err < 0) + return err; + + if (MPEG2_START_IS_SLICE(unit->type)) { + MPEG2RawSlice *slice; + int pos, len; + + slice = av_mallocz(sizeof(*slice)); + if (!slice) + return AVERROR(ENOMEM); + err = cbs_mpeg2_read_slice_header(ctx, &gbc, &slice->header); + if (err < 0) { + av_free(slice); + return err; + } + + pos = get_bits_count(&gbc); + len = unit->data_size; + + slice->data_size = len - pos / 8; + slice->data = av_malloc(slice->data_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!slice->data) { + av_free(slice); + return AVERROR(ENOMEM); + } + + memcpy(slice->data, + unit->data + pos / 8, slice->data_size); + memset(slice->data + slice->data_size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); + slice->data_bit_start = pos % 8; + + unit->content = slice; + + } else { + switch (unit->type) { +#define START(start_code, type, func) \ + case start_code: \ + { \ + type *header; \ + header = av_mallocz(sizeof(*header)); \ + if (!header) \ + return AVERROR(ENOMEM); \ + err = cbs_mpeg2_read_ ## func(ctx, &gbc, header); \ + if (err < 0) { \ + av_free(header); \ + return err; \ + } \ + unit->content = header; \ + } \ + break; + START(0x00, MPEG2RawPictureHeader, picture_header); + START(0xb2, MPEG2RawUserData, user_data); + START(0xb3, MPEG2RawSequenceHeader, sequence_header); + START(0xb5, MPEG2RawExtensionData, extension_data); + START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header); +#undef START + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown start code %02x.\n", + unit->type); + return AVERROR_INVALIDDATA; + } + } + + return 0; +} + +static int cbs_mpeg2_write_header(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + PutBitContext *pbc) +{ + int err; + + switch (unit->type) { +#define START(start_code, type, func) \ + case start_code: \ + err = cbs_mpeg2_write_ ## func(ctx, pbc, unit->content); \ + break; + START(0x00, MPEG2RawPictureHeader, picture_header); + START(0xb2, MPEG2RawUserData, user_data); + START(0xb3, MPEG2RawSequenceHeader, sequence_header); + START(0xb5, MPEG2RawExtensionData, extension_data); + START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header); +#undef START + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for start " + "code %02"PRIu32".\n", unit->type); + return AVERROR_PATCHWELCOME; + } + + return err; +} + +static int cbs_mpeg2_write_slice(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + PutBitContext *pbc) +{ + MPEG2RawSlice *slice = unit->content; + GetBitContext gbc; + size_t bits_left; + int err; + + err = cbs_mpeg2_write_slice_header(ctx, pbc, &slice->header); + if (err < 0) + return err; + + if (slice->data) { + if (slice->data_size * 8 + 8 > put_bits_left(pbc)) + return AVERROR(ENOSPC); + + init_get_bits(&gbc, slice->data, slice->data_size * 8); + skip_bits_long(&gbc, slice->data_bit_start); + + while (get_bits_left(&gbc) > 15) + put_bits(pbc, 16, get_bits(&gbc, 16)); + + bits_left = get_bits_left(&gbc); + put_bits(pbc, bits_left, get_bits(&gbc, bits_left)); + + // Align with zeroes. + while (put_bits_count(pbc) % 8 != 0) + put_bits(pbc, 1, 0); + } + + return 0; +} + +static int cbs_mpeg2_write_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + CodedBitstreamMPEG2Context *priv = ctx->priv_data; + PutBitContext pbc; + int err; + + if (!priv->write_buffer) { + // Initial write buffer size is 1MB. + priv->write_buffer_size = 1024 * 1024; + + reallocate_and_try_again: + err = av_reallocp(&priv->write_buffer, priv->write_buffer_size); + if (err < 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a " + "sufficiently large write buffer (last attempt " + "%zu bytes).\n", priv->write_buffer_size); + return err; + } + } + + init_put_bits(&pbc, priv->write_buffer, priv->write_buffer_size); + + if (unit->type >= 0x01 && unit->type <= 0xaf) + err = cbs_mpeg2_write_slice(ctx, unit, &pbc); + else + err = cbs_mpeg2_write_header(ctx, unit, &pbc); + + if (err == AVERROR(ENOSPC)) { + // Overflow. + priv->write_buffer_size *= 2; + goto reallocate_and_try_again; + } + if (err < 0) { + // Write failed for some other reason. + return err; + } + + if (put_bits_count(&pbc) % 8) + unit->data_bit_padding = 8 - put_bits_count(&pbc) % 8; + else + unit->data_bit_padding = 0; + + unit->data_size = (put_bits_count(&pbc) + 7) / 8; + flush_put_bits(&pbc); + + err = av_reallocp(&unit->data, unit->data_size); + if (err < 0) + return err; + + memcpy(unit->data, priv->write_buffer, unit->data_size); + + return 0; +} + +static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag) +{ + uint8_t *data; + size_t size, dp, sp; + int i; + + size = 0; + for (i = 0; i < frag->nb_units; i++) + size += 3 + frag->units[i].data_size; + + data = av_malloc(size); + if (!data) + return AVERROR(ENOMEM); + + dp = 0; + for (i = 0; i < frag->nb_units; i++) { + CodedBitstreamUnit *unit = &frag->units[i]; + + data[dp++] = 0; + data[dp++] = 0; + data[dp++] = 1; + + for (sp = 0; sp < unit->data_size; sp++) + data[dp++] = unit->data[sp]; + } + + av_assert0(dp == size); + + frag->data = data; + frag->data_size = size; + + return 0; +} + +static void cbs_mpeg2_free_unit(CodedBitstreamUnit *unit) +{ + if (MPEG2_START_IS_SLICE(unit->type)) { + MPEG2RawSlice *slice = unit->content; + av_freep(&slice->data); + av_freep(&slice->header.extra_information); + } else if (unit->type == MPEG2_START_USER_DATA) { + MPEG2RawUserData *user = unit->content; + av_freep(&user->user_data); + } + av_freep(&unit->content); +} + +static void cbs_mpeg2_close(CodedBitstreamContext *ctx) +{ + CodedBitstreamMPEG2Context *priv = ctx->priv_data; + + av_freep(&priv->write_buffer); +} + +const CodedBitstreamType ff_cbs_type_mpeg2 = { + .codec_id = AV_CODEC_ID_MPEG2VIDEO, + + .priv_data_size = sizeof(CodedBitstreamMPEG2Context), + + .split_fragment = &cbs_mpeg2_split_fragment, + .read_unit = &cbs_mpeg2_read_unit, + .write_unit = &cbs_mpeg2_write_unit, + .assemble_fragment = &cbs_mpeg2_assemble_fragment, + + .free_unit = &cbs_mpeg2_free_unit, + .close = &cbs_mpeg2_close, +}; diff --git a/libavcodec/cbs_mpeg2.h b/libavcodec/cbs_mpeg2.h new file mode 100644 index 0000000000000..a8f12b2e75ddf --- /dev/null +++ b/libavcodec/cbs_mpeg2.h @@ -0,0 +1,224 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_MPEG2_H +#define AVCODEC_CBS_MPEG2_H + +#include +#include + + +enum { + MPEG2_START_PICTURE = 0x00, + MPEG2_START_SLICE_MIN = 0x01, + MPEG2_START_SLICE_MAX = 0xaf, + MPEG2_START_USER_DATA = 0xb2, + MPEG2_START_SEQUENCE_HEADER = 0xb3, + MPEG2_START_SEQUENCE_ERROR = 0xb4, + MPEG2_START_EXTENSION = 0xb5, + MPEG2_START_SEQUENCE_END = 0xb7, + MPEG2_START_GROUP = 0xb8, +}; + +#define MPEG2_START_IS_SLICE(type) \ + ((type) >= MPEG2_START_SLICE_MIN && \ + (type) <= MPEG2_START_SLICE_MAX) + +enum { + MPEG2_EXTENSION_SEQUENCE = 0x1, + MPEG2_EXTENSION_SEQUENCE_DISPLAY = 0x2, + MPEG2_EXTENSION_QUANT_MATRIX = 0x3, + MPEG2_EXTENSION_COPYRIGHT = 0x4, + MPEG2_EXTENSION_SEQUENCE_SCALABLE = 0x5, + MPEG2_EXTENSION_PICTURE_DISPLAY = 0x7, + MPEG2_EXTENSION_PICTURE_CODING = 0x8, + MPEG2_EXTENSION_PICTURE_SPATIAL_SCALABLE = 0x9, + MPEG2_EXTENSION_PICTURE_TEMPORAL_SCALABLE = 0xa, + MPEG2_EXTENSION_CAMAERA_PARAMETERS = 0xb, + MPEG2_EXTENSION_ITU_T = 0xc, +}; + + +typedef struct MPEG2RawSequenceHeader { + uint8_t sequence_header_code; + + uint16_t horizontal_size_value; + uint16_t vertical_size_value; + uint8_t aspect_ratio_information; + uint8_t frame_rate_code; + uint32_t bit_rate_value; + uint16_t vbv_buffer_size_value; + uint8_t constrained_parameters_flag; + + uint8_t load_intra_quantiser_matrix; + uint8_t intra_quantiser_matrix[64]; + uint8_t load_non_intra_quantiser_matrix; + uint8_t non_intra_quantiser_matrix[64]; +} MPEG2RawSequenceHeader; + +typedef struct MPEG2RawUserData { + uint8_t user_data_start_code; + + uint8_t *user_data; + size_t user_data_length; +} MPEG2RawUserData; + +typedef struct MPEG2RawSequenceExtension { + uint8_t profile_and_level_indication; + uint8_t progressive_sequence; + uint8_t chroma_format; + uint8_t horizontal_size_extension; + uint8_t vertical_size_extension; + uint16_t bit_rate_extension; + uint8_t vbv_buffer_size_extension; + uint8_t low_delay; + uint8_t frame_rate_extension_n; + uint8_t frame_rate_extension_d; +} MPEG2RawSequenceExtension; + +typedef struct MPEG2RawSequenceDisplayExtension { + uint8_t video_format; + + uint8_t colour_description; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; + + uint16_t display_horizontal_size; + uint16_t display_vertical_size; +} MPEG2RawSequenceDisplayExtension; + +typedef struct MPEG2RawGroupOfPicturesHeader { + uint8_t group_start_code; + + uint32_t time_code; + uint8_t closed_gop; + uint8_t broken_link; +} MPEG2RawGroupOfPicturesHeader; + +typedef struct MPEG2RawPictureHeader { + uint8_t picture_start_code; + + uint16_t temporal_reference; + uint8_t picture_coding_type; + uint16_t vbv_delay; + + uint8_t full_pel_forward_vector; + uint8_t forward_f_code; + uint8_t full_pel_backward_vector; + uint8_t backward_f_code; + + uint8_t extra_bit_picture; +} MPEG2RawPictureHeader; + +typedef struct MPEG2RawPictureCodingExtension { + uint8_t f_code[2][2]; + + uint8_t intra_dc_precision; + uint8_t picture_structure; + uint8_t top_field_first; + uint8_t frame_pred_frame_dct; + uint8_t concealment_motion_vectors; + uint8_t q_scale_type; + uint8_t intra_vlc_format; + uint8_t alternate_scan; + uint8_t repeat_first_field; + uint8_t chroma_420_type; + uint8_t progressive_frame; + + uint8_t composite_display_flag; + uint8_t v_axis; + uint8_t field_sequence; + uint8_t sub_carrier; + uint8_t burst_amplitude; + uint8_t sub_carrier_phase; +} MPEG2RawPictureCodingExtension; + +typedef struct MPEG2RawQuantMatrixExtension { + uint8_t load_intra_quantiser_matrix; + uint8_t intra_quantiser_matrix[64]; + uint8_t load_non_intra_quantiser_matrix; + uint8_t non_intra_quantiser_matrix[64]; + uint8_t load_chroma_intra_quantiser_matrix; + uint8_t chroma_intra_quantiser_matrix[64]; + uint8_t load_chroma_non_intra_quantiser_matrix; + uint8_t chroma_non_intra_quantiser_matrix[64]; +} MPEG2RawQuantMatrixExtension; + +typedef struct MPEG2RawPictureDisplayExtension { + uint16_t frame_centre_horizontal_offset[3]; + uint16_t frame_centre_vertical_offset[3]; +} MPEG2RawPictureDisplayExtension; + +typedef struct MPEG2RawExtensionData { + uint8_t extension_start_code; + uint8_t extension_start_code_identifier; + + union { + MPEG2RawSequenceExtension sequence; + MPEG2RawSequenceDisplayExtension sequence_display; + MPEG2RawQuantMatrixExtension quant_matrix; + MPEG2RawPictureCodingExtension picture_coding; + MPEG2RawPictureDisplayExtension picture_display; + } data; +} MPEG2RawExtensionData; + +typedef struct MPEG2RawSliceHeader { + uint8_t slice_vertical_position; + + uint8_t slice_vertical_position_extension; + uint8_t priority_breakpoint; + + uint8_t quantiser_scale_code; + + uint8_t slice_extension_flag; + uint8_t intra_slice; + uint8_t slice_picture_id_enable; + uint8_t slice_picture_id; + + uint8_t extra_bit_slice; + + size_t extra_information_length; + uint8_t *extra_information; +} MPEG2RawSliceHeader; + +typedef struct MPEG2RawSlice { + MPEG2RawSliceHeader header; + + uint8_t *data; + size_t data_size; + int data_bit_start; +} MPEG2RawSlice; + + +typedef struct CodedBitstreamMPEG2Context { + // Elements stored in headers which are required for other decoding. + uint16_t horizontal_size; + uint16_t vertical_size; + uint8_t scalable; + uint8_t scalable_mode; + uint8_t progressive_sequence; + uint8_t number_of_frame_centre_offsets; + + // Write buffer. + uint8_t *write_buffer; + size_t write_buffer_size; +} CodedBitstreamMPEG2Context; + + +#endif /* AVCODEC_CBS_MPEG2_H */ diff --git a/libavcodec/cbs_mpeg2_syntax_template.c b/libavcodec/cbs_mpeg2_syntax_template.c new file mode 100644 index 0000000000000..90dde26aedc7a --- /dev/null +++ b/libavcodec/cbs_mpeg2_syntax_template.c @@ -0,0 +1,384 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static int FUNC(sequence_header)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawSequenceHeader *current) +{ + CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; + int err, i; + + HEADER("Sequence Header"); + + ui(8, sequence_header_code); + + ui(12, horizontal_size_value); + ui(12, vertical_size_value); + + mpeg2->horizontal_size = current->horizontal_size_value; + mpeg2->vertical_size = current->vertical_size_value; + + ui(4, aspect_ratio_information); + ui(4, frame_rate_code); + ui(18, bit_rate_value); + + marker_bit(); + + ui(10, vbv_buffer_size_value); + ui(1, constrained_parameters_flag); + + ui(1, load_intra_quantiser_matrix); + if (current->load_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, intra_quantiser_matrix[i]); + } + + ui(1, load_non_intra_quantiser_matrix); + if (current->load_non_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, non_intra_quantiser_matrix[i]); + } + + return 0; +} + +static int FUNC(user_data)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawUserData *current) +{ + size_t k; + int err; + + HEADER("User Data"); + + ui(8, user_data_start_code); + +#ifdef READ + k = get_bits_left(rw); + av_assert0(k % 8 == 0); + current->user_data_length = k /= 8; + if (k > 0) { + current->user_data = av_malloc(k); + if (!current->user_data) + return AVERROR(ENOMEM); + } +#endif + + for (k = 0; k < current->user_data_length; k++) + xui(8, user_data, current->user_data[k]); + + return 0; +} + +static int FUNC(sequence_extension)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawSequenceExtension *current) +{ + CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; + int err; + + HEADER("Sequence Extension"); + + ui(8, profile_and_level_indication); + ui(1, progressive_sequence); + ui(2, chroma_format); + ui(2, horizontal_size_extension); + ui(2, vertical_size_extension); + + mpeg2->horizontal_size = (mpeg2->horizontal_size & 0xfff) | + current->horizontal_size_extension << 12; + mpeg2->vertical_size = (mpeg2->vertical_size & 0xfff) | + current->vertical_size_extension << 12; + mpeg2->progressive_sequence = current->progressive_sequence; + + ui(12, bit_rate_extension); + marker_bit(); + ui(8, vbv_buffer_size_extension); + ui(1, low_delay); + ui(2, frame_rate_extension_n); + ui(5, frame_rate_extension_d); + + return 0; +} + +static int FUNC(sequence_display_extension)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawSequenceDisplayExtension *current) +{ + int err; + + HEADER("Sequence Display Extension"); + + ui(3, video_format); + + ui(1, colour_description); + if (current->colour_description) { + ui(8, colour_primaries); + ui(8, transfer_characteristics); + ui(8, matrix_coefficients); + } + + ui(14, display_horizontal_size); + marker_bit(); + ui(14, display_vertical_size); + + return 0; +} + +static int FUNC(group_of_pictures_header)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawGroupOfPicturesHeader *current) +{ + int err; + + HEADER("Group of Pictures Header"); + + ui(8, group_start_code); + + ui(25, time_code); + ui(1, closed_gop); + ui(1, broken_link); + + return 0; +} + +static int FUNC(picture_header)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawPictureHeader *current) +{ + int err; + + HEADER("Picture Header"); + + ui(8, picture_start_code); + + ui(10, temporal_reference); + ui(3, picture_coding_type); + ui(16, vbv_delay); + + if (current->picture_coding_type == 2 || + current->picture_coding_type == 3) { + ui(1, full_pel_forward_vector); + ui(3, forward_f_code); + } + + if (current->picture_coding_type == 3) { + ui(1, full_pel_backward_vector); + ui(3, backward_f_code); + } + + ui(1, extra_bit_picture); + + return 0; +} + +static int FUNC(picture_coding_extension)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawPictureCodingExtension *current) +{ + CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; + int err; + + HEADER("Picture Coding Extension"); + + ui(4, f_code[0][0]); + ui(4, f_code[0][1]); + ui(4, f_code[1][0]); + ui(4, f_code[1][1]); + + ui(2, intra_dc_precision); + ui(2, picture_structure); + ui(1, top_field_first); + ui(1, frame_pred_frame_dct); + ui(1, concealment_motion_vectors); + ui(1, q_scale_type); + ui(1, intra_vlc_format); + ui(1, alternate_scan); + ui(1, repeat_first_field); + ui(1, chroma_420_type); + ui(1, progressive_frame); + + if (mpeg2->progressive_sequence) { + if (current->repeat_first_field) { + if (current->top_field_first) + mpeg2->number_of_frame_centre_offsets = 3; + else + mpeg2->number_of_frame_centre_offsets = 2; + } else { + mpeg2->number_of_frame_centre_offsets = 1; + } + } else { + if (current->picture_structure == 1 || // Top field. + current->picture_structure == 2) { // Bottom field. + mpeg2->number_of_frame_centre_offsets = 1; + } else { + if (current->repeat_first_field) + mpeg2->number_of_frame_centre_offsets = 3; + else + mpeg2->number_of_frame_centre_offsets = 2; + } + } + + ui(1, composite_display_flag); + if (current->composite_display_flag) { + ui(1, v_axis); + ui(3, field_sequence); + ui(1, sub_carrier); + ui(7, burst_amplitude); + ui(8, sub_carrier_phase); + } + + return 0; +} + +static int FUNC(quant_matrix_extension)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawQuantMatrixExtension *current) +{ + int err, i; + + HEADER("Quant Matrix Extension"); + + ui(1, load_intra_quantiser_matrix); + if (current->load_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, intra_quantiser_matrix[i]); + } + + ui(1, load_non_intra_quantiser_matrix); + if (current->load_non_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, non_intra_quantiser_matrix[i]); + } + + ui(1, load_chroma_intra_quantiser_matrix); + if (current->load_chroma_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, intra_quantiser_matrix[i]); + } + + ui(1, load_chroma_non_intra_quantiser_matrix); + if (current->load_chroma_non_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, chroma_non_intra_quantiser_matrix[i]); + } + + return 0; +} + +static int FUNC(picture_display_extension)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawPictureDisplayExtension *current) +{ + CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; + int err, i; + + HEADER("Picture Display Extension"); + + for (i = 0; i < mpeg2->number_of_frame_centre_offsets; i++) { + ui(16, frame_centre_horizontal_offset[i]); + marker_bit(); + ui(16, frame_centre_vertical_offset[i]); + marker_bit(); + } + + return 0; +} + +static int FUNC(extension_data)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawExtensionData *current) +{ + int err; + + HEADER("Extension Data"); + + ui(8, extension_start_code); + ui(4, extension_start_code_identifier); + + switch (current->extension_start_code_identifier) { + case 1: + return FUNC(sequence_extension) + (ctx, rw, ¤t->data.sequence); + case 2: + return FUNC(sequence_display_extension) + (ctx, rw, ¤t->data.sequence_display); + case 3: + return FUNC(quant_matrix_extension) + (ctx, rw, ¤t->data.quant_matrix); + case 7: + return FUNC(picture_display_extension) + (ctx, rw, ¤t->data.picture_display); + case 8: + return FUNC(picture_coding_extension) + (ctx, rw, ¤t->data.picture_coding); + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid extension ID %d.\n", + current->extension_start_code_identifier); + return AVERROR_INVALIDDATA; + } +} + +static int FUNC(slice_header)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawSliceHeader *current) +{ + CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; + int err; + + HEADER("Slice Header"); + + ui(8, slice_vertical_position); + + if (mpeg2->vertical_size > 2800) + ui(3, slice_vertical_position_extension); + if (mpeg2->scalable) { + if (mpeg2->scalable_mode == 0) + ui(7, priority_breakpoint); + } + + ui(5, quantiser_scale_code); + + if (nextbits(1, 1, current->slice_extension_flag)) { + ui(1, slice_extension_flag); + ui(1, intra_slice); + ui(1, slice_picture_id_enable); + ui(6, slice_picture_id); + + { + size_t k; +#ifdef READ + GetBitContext start; + uint8_t bit; + start = *rw; + for (k = 0; nextbits(1, 1, bit); k++) + skip_bits(rw, 8); + current->extra_information_length = k; + if (k > 0) { + *rw = start; + current->extra_information = + av_malloc(current->extra_information_length); + if (!current->extra_information) + return AVERROR(ENOMEM); + for (k = 0; k < current->extra_information_length; k++) { + xui(1, extra_bit_slice, bit); + xui(8, extra_information_slice, + current->extra_information[k]); + } + } +#else + for (k = 0; k < current->extra_information_length; k++) { + xui(1, extra_bit_slice, 1); + xui(8, extra_information_slice, current->extra_information[k]); + } +#endif + } + } + ui(1, extra_bit_slice); + + return 0; +} From 9c7d70b49b64aa5571772a7cdb9bc426174261e0 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 4 May 2017 23:06:20 +0100 Subject: [PATCH 0504/2557] lavc: Add trace_headers bitstream filter Supports all streams that the coded bitstream infrastructure does (currently H.264, H.265 and MPEG-2). (cherry picked from commit f11d8a5e8b185340cc50fcbc8a1437b0fbe7e931) --- configure | 1 + doc/bitstream_filters.texi | 8 +++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/trace_headers_bsf.c | 126 +++++++++++++++++++++++++++++++++ 5 files changed, 137 insertions(+) create mode 100644 libavcodec/trace_headers_bsf.c diff --git a/configure b/configure index bb0a748f9e4d9..74aac3a4f42e4 100755 --- a/configure +++ b/configure @@ -2914,6 +2914,7 @@ vc1_parser_select="vc1dsp" # bitstream_filters mjpeg2jpeg_bsf_select="jpegtables" +trace_headers_bsf_select="cbs_h264 cbs_h265 cbs_mpeg2" # external libraries aac_at_decoder_deps="audiotoolbox" diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 2dffe021f9296..990b4f3c582b1 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -275,6 +275,14 @@ codec) with metadata headers. See also the @ref{mov2textsub} filter. +@section trace_headers + +Log trace output containing all syntax elements in the coded stream +headers (everything above the level of individual coded blocks). +This can be useful for debugging low-level stream issues. + +Supports H.264, H.265 and MPEG-2. + @section vp9_superframe Merge VP9 invisible (alt-ref) frames back into VP9 superframes. This diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 0265c921309a3..5e09889bc6380 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1028,6 +1028,7 @@ OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o OBJS-$(CONFIG_NULL_BSF) += null_bsf.o OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o +OBJS-$(CONFIG_TRACE_HEADERS_BSF) += trace_headers_bsf.o OBJS-$(CONFIG_VP9_RAW_REORDER_BSF) += vp9_raw_reorder_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF) += vp9_superframe_split_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index ce34de640d30b..dd0247182b7f8 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -41,6 +41,7 @@ extern const AVBitStreamFilter ff_noise_bsf; extern const AVBitStreamFilter ff_null_bsf; extern const AVBitStreamFilter ff_remove_extradata_bsf; extern const AVBitStreamFilter ff_text2movsub_bsf; +extern const AVBitStreamFilter ff_trace_headers_bsf; extern const AVBitStreamFilter ff_vp9_raw_reorder_bsf; extern const AVBitStreamFilter ff_vp9_superframe_bsf; extern const AVBitStreamFilter ff_vp9_superframe_split_bsf; diff --git a/libavcodec/trace_headers_bsf.c b/libavcodec/trace_headers_bsf.c new file mode 100644 index 0000000000000..93d04cb5097ca --- /dev/null +++ b/libavcodec/trace_headers_bsf.c @@ -0,0 +1,126 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/log.h" + +#include "bsf.h" +#include "cbs.h" + + +typedef struct TraceHeadersContext { + CodedBitstreamContext *cbc; +} TraceHeadersContext; + + +static int trace_headers_init(AVBSFContext *bsf) +{ + TraceHeadersContext *ctx = bsf->priv_data; + int err; + + err = ff_cbs_init(&ctx->cbc, bsf->par_in->codec_id, bsf); + if (err < 0) + return err; + + ctx->cbc->trace_enable = 1; + ctx->cbc->trace_level = AV_LOG_INFO; + + if (bsf->par_in->extradata) { + CodedBitstreamFragment ps; + + av_log(bsf, AV_LOG_INFO, "Extradata\n"); + + err = ff_cbs_read_extradata(ctx->cbc, &ps, bsf->par_in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); + return err; + } + + ff_cbs_fragment_uninit(ctx->cbc, &ps); + } + + return 0; +} + +static void trace_headers_close(AVBSFContext *bsf) +{ + TraceHeadersContext *ctx = bsf->priv_data; + + ff_cbs_close(&ctx->cbc); +} + +static int trace_headers(AVBSFContext *bsf, AVPacket *out) +{ + TraceHeadersContext *ctx = bsf->priv_data; + CodedBitstreamFragment au; + AVPacket *in; + char tmp[256] = { 0 }; + int err; + + err = ff_bsf_get_packet(bsf, &in); + if (err < 0) + return err; + + if (in->flags & AV_PKT_FLAG_KEY) + av_strlcat(tmp, ", key frame", sizeof(tmp)); + if (in->flags & AV_PKT_FLAG_CORRUPT) + av_strlcat(tmp, ", corrupt", sizeof(tmp)); + + if (in->pts != AV_NOPTS_VALUE) + av_strlcatf(tmp, sizeof(tmp), ", pts %"PRId64, in->pts); + else + av_strlcat(tmp, ", no pts", sizeof(tmp)); + if (in->dts != AV_NOPTS_VALUE) + av_strlcatf(tmp, sizeof(tmp), ", dts %"PRId64, in->dts); + else + av_strlcat(tmp, ", no dts", sizeof(tmp)); + if (in->duration > 0) + av_strlcatf(tmp, sizeof(tmp), ", duration %"PRId64, in->duration); + + av_log(bsf, AV_LOG_INFO, "Packet: %d bytes%s.\n", in->size, tmp); + + err = ff_cbs_read_packet(ctx->cbc, &au, in); + if (err < 0) + return err; + + ff_cbs_fragment_uninit(ctx->cbc, &au); + + av_packet_move_ref(out, in); + av_packet_free(&in); + + return 0; +} + +static const enum AVCodecID trace_headers_codec_ids[] = { + AV_CODEC_ID_H264, + AV_CODEC_ID_HEVC, + AV_CODEC_ID_MPEG2VIDEO, + AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_trace_headers_bsf = { + .name = "trace_headers", + .priv_data_size = sizeof(TraceHeadersContext), + .init = &trace_headers_init, + .close = &trace_headers_close, + .filter = &trace_headers, + .codec_ids = trace_headers_codec_ids, +}; From a308872b049e33f69f4b629a06f47e3681906b93 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 4 May 2017 23:09:02 +0100 Subject: [PATCH 0505/2557] lavc: Add h264_metadata bitstream filter This is able to modify some header metadata found in the SPS/VUI, and can also add/remove AUDs and insert user data in SEI NAL units. (cherry picked from commit 9e93001b6135a23fe4e200196c08fb4fbffed6fc) (cherry picked from commit c42b62d1f9641f10ffc23cad9abbe47d8a4a165b) --- configure | 1 + doc/bitstream_filters.texi | 63 ++++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/h264_metadata_bsf.c | 524 +++++++++++++++++++++++++++++++++ 5 files changed, 590 insertions(+) create mode 100644 libavcodec/h264_metadata_bsf.c diff --git a/configure b/configure index 74aac3a4f42e4..85889e62ed5ec 100755 --- a/configure +++ b/configure @@ -2913,6 +2913,7 @@ mpeg4video_parser_select="h263dsp mpegvideo qpeldsp" vc1_parser_select="vc1dsp" # bitstream_filters +h264_metadata_bsf_select="cbs_h264" mjpeg2jpeg_bsf_select="jpegtables" trace_headers_bsf_select="cbs_h264 cbs_h265 cbs_mpeg2" diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 990b4f3c582b1..f7dfa1f753aac 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -92,6 +92,69 @@ When this option is enabled, the long-term headers are removed from the bitstream after extraction. @end table +@section h264_metadata + +Modify metadata embedded in an H.264 stream. + +@table @option +@item aud +Insert or remove AUD NAL units in all access units of the stream. + +@table @samp +@item insert +@item remove +@end table + +@item sample_aspect_ratio +Set the sample aspect ratio of the stream in the VUI parameters. + +@item video_format +@item video_full_range_flag +Set the video format in the stream (see H.264 section E.2.1 and +table E-2). + +@item colour_primaries +@item transfer_characteristics +@item matrix_coefficients +Set the colour description in the stream (see H.264 section E.2.1 +and tables E-3, E-4 and E-5). + +@item chroma_sample_loc_type +Set the chroma sample location in the stream (see H.264 section +E.2.1 and figure E-1). + +@item tick_rate +Set the tick rate (num_units_in_tick / time_scale) in the VUI +parameters. This is the smallest time unit representable in the +stream, and in many cases represents the field rate of the stream +(double the frame rate). +@item fixed_frame_rate_flag +Set whether the stream has fixed framerate - typically this indicates +that the framerate is exactly half the tick rate, but the exact +meaning is dependent on interlacing and the picture structure (see +H.264 section E.2.1 and table E-6). + +@item crop_left +@item crop_right +@item crop_top +@item crop_bottom +Set the frame cropping offsets in the SPS. These values will replace +the current ones if the stream is already cropped. + +These fields are set in pixels. Note that some sizes may not be +representable if the chroma is subsampled or the stream is interlaced +(see H.264 section 7.4.2.1.1). + +@item sei_user_data +Insert a string as SEI unregistered user data. The argument must +be of the form @emph{UUID+string}, where the UUID is as hex digits +possibly separated by hyphens, and the string can be anything. + +For example, @samp{086f3693-b7b3-4f2c-9653-21492feee5b8+hello} will +insert the string ``hello'' associated with the given UUID. + +@end table + @section h264_mp4toannexb Convert an H.264 bitstream from length prefixed mode to start code diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5e09889bc6380..25ad785dbee9b 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1015,6 +1015,7 @@ OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o OBJS-$(CONFIG_DCA_CORE_BSF) += dca_core_bsf.o OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \ h2645_parse.o +OBJS-$(CONFIG_H264_METADATA_BSF) += h264_metadata_bsf.o OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index dd0247182b7f8..0e133b90360ef 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -29,6 +29,7 @@ extern const AVBitStreamFilter ff_chomp_bsf; extern const AVBitStreamFilter ff_dump_extradata_bsf; extern const AVBitStreamFilter ff_dca_core_bsf; extern const AVBitStreamFilter ff_extract_extradata_bsf; +extern const AVBitStreamFilter ff_h264_metadata_bsf; extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf; extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf; extern const AVBitStreamFilter ff_imx_dump_header_bsf; diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c new file mode 100644 index 0000000000000..496f7f00fe853 --- /dev/null +++ b/libavcodec/h264_metadata_bsf.c @@ -0,0 +1,524 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "bsf.h" +#include "cbs.h" +#include "cbs_h264.h" +#include "h264.h" +#include "h264_sei.h" + +enum { + PASS, + INSERT, + REMOVE, +}; + +typedef struct H264MetadataContext { + const AVClass *class; + + CodedBitstreamContext *cbc; + CodedBitstreamFragment access_unit; + + H264RawAUD aud_nal; + H264RawSEI sei_nal; + + int aud; + + AVRational sample_aspect_ratio; + + int video_format; + int video_full_range_flag; + int colour_primaries; + int transfer_characteristics; + int matrix_coefficients; + + int chroma_sample_loc_type; + + AVRational tick_rate; + int fixed_frame_rate_flag; + + int crop_left; + int crop_right; + int crop_top; + int crop_bottom; + + const char *sei_user_data; + int sei_first_au; +} H264MetadataContext; + + +static int h264_metadata_update_sps(AVBSFContext *bsf, + H264RawSPS *sps) +{ + H264MetadataContext *ctx = bsf->priv_data; + int need_vui = 0; + int crop_unit_x, crop_unit_y; + + if (ctx->sample_aspect_ratio.num && ctx->sample_aspect_ratio.den) { + // Table E-1. + static const AVRational sar_idc[] = { + { 0, 0 }, // Unspecified (never written here). + { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, + { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, + { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, + { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, + }; + int num, den, i; + + av_reduce(&num, &den, ctx->sample_aspect_ratio.num, + ctx->sample_aspect_ratio.den, 65535); + + for (i = 1; i < FF_ARRAY_ELEMS(sar_idc); i++) { + if (num == sar_idc[i].num && + den == sar_idc[i].den) + break; + } + if (i == FF_ARRAY_ELEMS(sar_idc)) { + sps->vui.aspect_ratio_idc = 255; + sps->vui.sar_width = num; + sps->vui.sar_height = den; + } else { + sps->vui.aspect_ratio_idc = i; + } + sps->vui.aspect_ratio_info_present_flag = 1; + need_vui = 1; + } + +#define SET_OR_INFER(field, value, present_flag, infer) do { \ + if (value >= 0) { \ + field = value; \ + need_vui = 1; \ + } else if (!present_flag) \ + field = infer; \ + } while (0) + + if (ctx->video_format >= 0 || + ctx->video_full_range_flag >= 0 || + ctx->colour_primaries >= 0 || + ctx->transfer_characteristics >= 0 || + ctx->matrix_coefficients >= 0) { + + SET_OR_INFER(sps->vui.video_format, ctx->video_format, + sps->vui.video_signal_type_present_flag, 5); + + SET_OR_INFER(sps->vui.video_full_range_flag, + ctx->video_full_range_flag, + sps->vui.video_signal_type_present_flag, 0); + + if (ctx->colour_primaries >= 0 || + ctx->transfer_characteristics >= 0 || + ctx->matrix_coefficients >= 0) { + + SET_OR_INFER(sps->vui.colour_primaries, + ctx->colour_primaries, + sps->vui.colour_description_present_flag, 2); + + SET_OR_INFER(sps->vui.transfer_characteristics, + ctx->transfer_characteristics, + sps->vui.colour_description_present_flag, 2); + + SET_OR_INFER(sps->vui.matrix_coefficients, + ctx->matrix_coefficients, + sps->vui.colour_description_present_flag, 2); + + sps->vui.colour_description_present_flag = 1; + } + sps->vui.video_signal_type_present_flag = 1; + need_vui = 1; + } + + if (ctx->chroma_sample_loc_type >= 0) { + sps->vui.chroma_sample_loc_type_top_field = + ctx->chroma_sample_loc_type; + sps->vui.chroma_sample_loc_type_bottom_field = + ctx->chroma_sample_loc_type; + sps->vui.chroma_loc_info_present_flag = 1; + need_vui = 1; + } + + if (ctx->tick_rate.num && ctx->tick_rate.den) { + int num, den; + + av_reduce(&num, &den, ctx->tick_rate.num, ctx->tick_rate.den, + UINT32_MAX > INT_MAX ? UINT32_MAX : INT_MAX); + + sps->vui.time_scale = num; + sps->vui.num_units_in_tick = den; + + sps->vui.timing_info_present_flag = 1; + need_vui = 1; + } + SET_OR_INFER(sps->vui.fixed_frame_rate_flag, + ctx->fixed_frame_rate_flag, + sps->vui.timing_info_present_flag, 0); + + if (sps->separate_colour_plane_flag || sps->chroma_format_idc == 0) { + crop_unit_x = 1; + crop_unit_y = 2 - sps->frame_mbs_only_flag; + } else { + crop_unit_x = 1 + (sps->chroma_format_idc < 3); + crop_unit_y = (1 + (sps->chroma_format_idc < 2)) * + (2 - sps->frame_mbs_only_flag); + } +#define CROP(border, unit) do { \ + if (ctx->crop_ ## border >= 0) { \ + if (ctx->crop_ ## border % unit != 0) { \ + av_log(bsf, AV_LOG_ERROR, "Invalid value for crop_%s: " \ + "must be a multiple of %d.\n", #border, unit); \ + return AVERROR(EINVAL); \ + } \ + sps->frame_crop_ ## border ## _offset = \ + ctx->crop_ ## border / unit; \ + sps->frame_cropping_flag = 1; \ + } \ + } while (0) + CROP(left, crop_unit_x); + CROP(right, crop_unit_x); + CROP(top, crop_unit_y); + CROP(bottom, crop_unit_y); +#undef CROP + + if (need_vui) + sps->vui_parameters_present_flag = 1; + + return 0; +} + +static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) +{ + H264MetadataContext *ctx = bsf->priv_data; + AVPacket *in = NULL; + CodedBitstreamFragment *au = &ctx->access_unit; + int err, i, j, has_sps; + char *sei_udu_string = NULL; + + err = ff_bsf_get_packet(bsf, &in); + if (err < 0) + goto fail; + + err = ff_cbs_read_packet(ctx->cbc, au, in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); + goto fail; + } + + if (au->nb_units == 0) { + av_log(bsf, AV_LOG_ERROR, "No NAL units in packet.\n"); + err = AVERROR_INVALIDDATA; + goto fail; + } + + // If an AUD is present, it must be the first NAL unit. + if (au->units[0].type == H264_NAL_AUD) { + if (ctx->aud == REMOVE) + ff_cbs_delete_unit(ctx->cbc, au, 0); + } else { + if (ctx->aud == INSERT) { + static const int primary_pic_type_table[] = { + 0x084, // 2, 7 + 0x0a5, // 0, 2, 5, 7 + 0x0e7, // 0, 1, 2, 5, 6, 7 + 0x210, // 4, 9 + 0x318, // 3, 4, 8, 9 + 0x294, // 2, 4, 7, 9 + 0x3bd, // 0, 2, 3, 4, 5, 7, 8, 9 + 0x3ff, // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + }; + int primary_pic_type_mask = 0xff; + H264RawAUD *aud = &ctx->aud_nal; + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_SLICE || + au->units[i].type == H264_NAL_IDR_SLICE) { + H264RawSlice *slice = au->units[i].content; + for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++) { + if (!(primary_pic_type_table[j] & + (1 << slice->header.slice_type))) + primary_pic_type_mask &= ~(1 << j); + } + } + } + for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++) + if (primary_pic_type_mask & (1 << j)) + break; + if (j >= FF_ARRAY_ELEMS(primary_pic_type_table)) { + av_log(bsf, AV_LOG_ERROR, "No usable primary_pic_type: " + "invalid slice types?\n"); + err = AVERROR_INVALIDDATA; + goto fail; + } + + aud->nal_unit_header.nal_unit_type = H264_NAL_AUD; + aud->primary_pic_type = j; + + err = ff_cbs_insert_unit_content(ctx->cbc, au, + 0, H264_NAL_AUD, aud); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n"); + goto fail; + } + } + } + + has_sps = 0; + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_SPS) { + err = h264_metadata_update_sps(bsf, au->units[i].content); + if (err < 0) + goto fail; + has_sps = 1; + } + } + + // Insert the SEI in access units containing SPSs, and also + // unconditionally in the first access unit we ever see. + if (ctx->sei_user_data && (has_sps || !ctx->sei_first_au)) { + H264RawSEI *sei; + H264RawSEIPayload *payload; + H264RawSEIUserDataUnregistered *udu; + int sei_pos, sei_new; + + ctx->sei_first_au = 1; + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_SEI || + au->units[i].type == H264_NAL_SLICE || + au->units[i].type == H264_NAL_IDR_SLICE) + break; + } + sei_pos = i; + + if (sei_pos < au->nb_units && + au->units[sei_pos].type == H264_NAL_SEI) { + sei_new = 0; + sei = au->units[sei_pos].content; + } else { + sei_new = 1; + sei = &ctx->sei_nal; + memset(sei, 0, sizeof(*sei)); + + sei->nal_unit_header.nal_unit_type = H264_NAL_SEI; + + err = ff_cbs_insert_unit_content(ctx->cbc, au, + sei_pos, H264_NAL_SEI, sei); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to insert SEI.\n"); + goto fail; + } + } + + payload = &sei->payload[sei->payload_count]; + + payload->payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED; + udu = &payload->payload.user_data_unregistered; + + for (i = j = 0; j < 32 && ctx->sei_user_data[i]; i++) { + int c, v; + c = ctx->sei_user_data[i]; + if (c == '-') { + continue; + } else if (av_isxdigit(c)) { + c = av_tolower(c); + v = (c <= '9' ? c - '0' : c - 'a' + 10); + } else { + goto invalid_user_data; + } + if (i & 1) + udu->uuid_iso_iec_11578[j / 2] |= v; + else + udu->uuid_iso_iec_11578[j / 2] = v << 4; + ++j; + } + if (j == 32 && ctx->sei_user_data[i] == '+') { + sei_udu_string = av_strdup(ctx->sei_user_data + i + 1); + if (!sei_udu_string) { + err = AVERROR(ENOMEM); + goto sei_fail; + } + + udu->data = sei_udu_string; + udu->data_length = strlen(sei_udu_string); + + payload->payload_size = 16 + udu->data_length; + + if (!sei_new) { + // This will be freed by the existing internal + // reference in fragment_uninit(). + sei_udu_string = NULL; + } + + } else { + invalid_user_data: + av_log(bsf, AV_LOG_ERROR, "Invalid user data: " + "must be \"UUID+string\".\n"); + err = AVERROR(EINVAL); + sei_fail: + memset(payload, 0, sizeof(&payload)); + goto fail; + } + + ++sei->payload_count; + } + + err = ff_cbs_write_packet(ctx->cbc, out, au); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); + goto fail; + } + + err = av_packet_copy_props(out, in); + if (err < 0) + goto fail; + + err = 0; +fail: + ff_cbs_fragment_uninit(ctx->cbc, au); + av_freep(&sei_udu_string); + + av_packet_free(&in); + + return err; +} + +static int h264_metadata_init(AVBSFContext *bsf) +{ + H264MetadataContext *ctx = bsf->priv_data; + CodedBitstreamFragment *au = &ctx->access_unit; + int err, i; + + err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_H264, bsf); + if (err < 0) + return err; + + if (bsf->par_in->extradata) { + err = ff_cbs_read_extradata(ctx->cbc, au, bsf->par_in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); + goto fail; + } + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_SPS) { + err = h264_metadata_update_sps(bsf, au->units[i].content); + if (err < 0) + goto fail; + } + } + + err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, au); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); + goto fail; + } + } + + err = 0; +fail: + ff_cbs_fragment_uninit(ctx->cbc, au); + return err; +} + +static void h264_metadata_close(AVBSFContext *bsf) +{ + H264MetadataContext *ctx = bsf->priv_data; + ff_cbs_close(&ctx->cbc); +} + +#define OFFSET(x) offsetof(H264MetadataContext, x) +static const AVOption h264_metadata_options[] = { + { "aud", "Access Unit Delimiter NAL units", + OFFSET(aud), AV_OPT_TYPE_INT, + { .i64 = PASS }, PASS, REMOVE, 0, "aud" }, + { "pass", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PASS }, .unit = "aud" }, + { "insert", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = INSERT }, .unit = "aud" }, + { "remove", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE }, .unit = "aud" }, + + { "sample_aspect_ratio", "Set sample aspect ratio (table E-1)", + OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, + { .dbl = 0.0 }, 0, 65535 }, + + { "video_format", "Set video format (table E-2)", + OFFSET(video_format), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 7 }, + { "video_full_range_flag", "Set video full range flag", + OFFSET(video_full_range_flag), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 1 }, + { "colour_primaries", "Set colour primaries (table E-3)", + OFFSET(colour_primaries), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + { "transfer_characteristics", "Set transfer characteristics (table E-4)", + OFFSET(transfer_characteristics), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + { "matrix_coefficients", "Set matrix coefficients (table E-5)", + OFFSET(matrix_coefficients), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + + { "chroma_sample_loc_type", "Set chroma sample location type (figure E-1)", + OFFSET(chroma_sample_loc_type), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 6 }, + + { "tick_rate", "Set VUI tick rate (num_units_in_tick / time_scale)", + OFFSET(tick_rate), AV_OPT_TYPE_RATIONAL, + { .dbl = 0.0 }, 0, UINT_MAX }, + { "fixed_frame_rate_flag", "Set VUI fixed frame rate flag", + OFFSET(fixed_frame_rate_flag), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 1 }, + + { "crop_left", "Set left border crop offset", + OFFSET(crop_left), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, H264_MAX_WIDTH }, + { "crop_right", "Set right border crop offset", + OFFSET(crop_right), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, H264_MAX_WIDTH }, + { "crop_top", "Set top border crop offset", + OFFSET(crop_top), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, H264_MAX_HEIGHT }, + { "crop_bottom", "Set bottom border crop offset", + OFFSET(crop_bottom), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, H264_MAX_HEIGHT }, + + { "sei_user_data", "Insert SEI user data (UUID+string)", + OFFSET(sei_user_data), AV_OPT_TYPE_STRING, { .str = NULL } }, + + { NULL } +}; + +static const AVClass h264_metadata_class = { + .class_name = "h264_metadata_bsf", + .item_name = av_default_item_name, + .option = h264_metadata_options, + .version = LIBAVCODEC_VERSION_MAJOR, +}; + +static const enum AVCodecID h264_metadata_codec_ids[] = { + AV_CODEC_ID_H264, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_h264_metadata_bsf = { + .name = "h264_metadata", + .priv_data_size = sizeof(H264MetadataContext), + .priv_class = &h264_metadata_class, + .init = &h264_metadata_init, + .close = &h264_metadata_close, + .filter = &h264_metadata_filter, + .codec_ids = h264_metadata_codec_ids, +}; From 8b26306294ffe78cc73357e2ddd56dd463db50ab Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 4 May 2017 23:10:19 +0100 Subject: [PATCH 0506/2557] lavc: Add h264_redundant_pps bitstream filter This applies a specific fixup to some Blu-ray streams which contain redundant PPSs modifying irrelevant parameters of the stream which confuse other transformations which require correct extradata. A new single global PPS is created, and all of the redundant PPSs within the stream are removed. (cherry picked from commit e6874bc3af2f09af39b5d91b9c5f9ded67459696) --- configure | 1 + doc/bitstream_filters.texi | 9 ++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/h264_redundant_pps_bsf.c | 178 ++++++++++++++++++++++++++++ 5 files changed, 190 insertions(+) create mode 100644 libavcodec/h264_redundant_pps_bsf.c diff --git a/configure b/configure index 85889e62ed5ec..607f75e5f7a27 100755 --- a/configure +++ b/configure @@ -2914,6 +2914,7 @@ vc1_parser_select="vc1dsp" # bitstream_filters h264_metadata_bsf_select="cbs_h264" +h264_redundant_pps_bsf_select="cbs_h264" mjpeg2jpeg_bsf_select="jpegtables" trace_headers_bsf_select="cbs_h264 cbs_h265 cbs_mpeg2" diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index f7dfa1f753aac..0e116a9c094e3 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -174,6 +174,15 @@ ffmpeg -i INPUT.mp4 -codec copy -bsf:v h264_mp4toannexb OUTPUT.ts Please note that this filter is auto-inserted for MPEG-TS (muxer @code{mpegts}) and raw H.264 (muxer @code{h264}) output formats. +@section h264_redundant_pps + +This applies a specific fixup to some Blu-ray streams which contain +redundant PPSs modifying irrelevant parameters of the stream which +confuse other transformations which require correct extradata. + +A new single global PPS is created, and all of the redundant PPSs +within the stream are removed. + @section hevc_mp4toannexb Convert an HEVC/H.265 bitstream from length prefixed mode to start code diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 25ad785dbee9b..a5b2b17cf3249 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1017,6 +1017,7 @@ OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \ h2645_parse.o OBJS-$(CONFIG_H264_METADATA_BSF) += h264_metadata_bsf.o OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o +OBJS-$(CONFIG_H264_REDUNDANT_PPS_BSF) += h264_redundant_pps_bsf.o OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 0e133b90360ef..5ab4f1464223a 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -31,6 +31,7 @@ extern const AVBitStreamFilter ff_dca_core_bsf; extern const AVBitStreamFilter ff_extract_extradata_bsf; extern const AVBitStreamFilter ff_h264_metadata_bsf; extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf; +extern const AVBitStreamFilter ff_h264_redundant_pps_bsf; extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf; extern const AVBitStreamFilter ff_imx_dump_header_bsf; extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf; diff --git a/libavcodec/h264_redundant_pps_bsf.c b/libavcodec/h264_redundant_pps_bsf.c new file mode 100644 index 0000000000000..26baca84e3be2 --- /dev/null +++ b/libavcodec/h264_redundant_pps_bsf.c @@ -0,0 +1,178 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/mem.h" + +#include "bsf.h" +#include "cbs.h" +#include "cbs_h264.h" +#include "h264.h" + + +typedef struct H264RedundantPPSContext { + CodedBitstreamContext *input; + CodedBitstreamContext *output; + + CodedBitstreamFragment access_unit; + + int global_pic_init_qp; + int current_pic_init_qp; +} H264RedundantPPSContext; + + +static int h264_redundant_pps_fixup_pps(H264RedundantPPSContext *ctx, + H264RawPPS *pps) +{ + // Record the current value of pic_init_qp in order to fix up + // following slices, then overwrite with the global value. + ctx->current_pic_init_qp = pps->pic_init_qp_minus26 + 26; + pps->pic_init_qp_minus26 = ctx->global_pic_init_qp - 26; + + // Some PPSs have this set, so it must be set in all of them. + // (Slices which do not use such a PPS on input will still have + // *_weight_l*flag as zero and therefore write equivalently.) + pps->weighted_pred_flag = 1; + + return 0; +} + +static int h264_redundant_pps_fixup_slice(H264RedundantPPSContext *ctx, + H264RawSliceHeader *slice) +{ + int qp; + + qp = ctx->current_pic_init_qp + slice->slice_qp_delta; + slice->slice_qp_delta = qp - ctx->global_pic_init_qp; + + return 0; +} + +static int h264_redundant_pps_filter(AVBSFContext *bsf, AVPacket *out) +{ + H264RedundantPPSContext *ctx = bsf->priv_data; + AVPacket *in; + CodedBitstreamFragment *au = &ctx->access_unit; + int au_has_sps; + int err, i; + + err = ff_bsf_get_packet(bsf, &in); + if (err < 0) + return err; + + err = ff_cbs_read_packet(ctx->input, au, in); + if (err < 0) + return err; + + au_has_sps = 0; + for (i = 0; i < au->nb_units; i++) { + CodedBitstreamUnit *nal = &au->units[i]; + + if (nal->type == H264_NAL_SPS) + au_has_sps = 1; + if (nal->type == H264_NAL_PPS) { + h264_redundant_pps_fixup_pps(ctx, nal->content); + if (!au_has_sps) { + av_log(ctx, AV_LOG_VERBOSE, "Deleting redundant PPS " + "at %"PRId64".\n", in->pts); + ff_cbs_delete_unit(ctx->input, au, i); + } + } + if (nal->type == H264_NAL_SLICE || + nal->type == H264_NAL_IDR_SLICE) { + H264RawSlice *slice = nal->content; + h264_redundant_pps_fixup_slice(ctx, &slice->header); + } + } + + err = ff_cbs_write_packet(ctx->output, out, au); + if (err < 0) + return err; + + ff_cbs_fragment_uninit(ctx->output, au); + + err = av_packet_copy_props(out, in); + if (err < 0) + return err; + + av_packet_free(&in); + + return 0; +} + +static int h264_redundant_pps_init(AVBSFContext *bsf) +{ + H264RedundantPPSContext *ctx = bsf->priv_data; + CodedBitstreamFragment *au = &ctx->access_unit; + int err, i; + + err = ff_cbs_init(&ctx->input, AV_CODEC_ID_H264, bsf); + if (err < 0) + return err; + + err = ff_cbs_init(&ctx->output, AV_CODEC_ID_H264, bsf); + if (err < 0) + return err; + + ctx->global_pic_init_qp = 26; + + if (bsf->par_in->extradata) { + err = ff_cbs_read_extradata(ctx->input, au, bsf->par_in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); + return err; + } + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_PPS) + h264_redundant_pps_fixup_pps(ctx, au->units[i].content); + } + + err = ff_cbs_write_extradata(ctx->output, bsf->par_out, au); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); + return err; + } + + ff_cbs_fragment_uninit(ctx->output, au); + } + + return 0; +} + +static void h264_redundant_pps_close(AVBSFContext *bsf) +{ + H264RedundantPPSContext *ctx = bsf->priv_data; + ff_cbs_close(&ctx->input); + ff_cbs_close(&ctx->output); +} + +static const enum AVCodecID h264_redundant_pps_codec_ids[] = { + AV_CODEC_ID_H264, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_h264_redundant_pps_bsf = { + .name = "h264_redundant_pps", + .priv_data_size = sizeof(H264RedundantPPSContext), + .init = &h264_redundant_pps_init, + .close = &h264_redundant_pps_close, + .filter = &h264_redundant_pps_filter, + .codec_ids = h264_redundant_pps_codec_ids, +}; From 03f982bbca4211108477e772db9a339517ecde37 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 23 Jul 2017 16:23:51 +0100 Subject: [PATCH 0507/2557] lavc: Add hevc_metadata bitstream filter This is able to modify some header metadata found in the VPS/SPS/VUI, and can also add/remove AUDs. (cherry picked from commit b31a9eae0233325c4b382c657f4b687d5d8b0812) --- configure | 1 + doc/bitstream_filters.texi | 54 ++++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/h265_metadata_bsf.c | 458 +++++++++++++++++++++++++++++++++ 5 files changed, 515 insertions(+) create mode 100644 libavcodec/h265_metadata_bsf.c diff --git a/configure b/configure index 607f75e5f7a27..fb1383369fbfe 100755 --- a/configure +++ b/configure @@ -2915,6 +2915,7 @@ vc1_parser_select="vc1dsp" # bitstream_filters h264_metadata_bsf_select="cbs_h264" h264_redundant_pps_bsf_select="cbs_h264" +hevc_metadata_bsf_select="cbs_h265" mjpeg2jpeg_bsf_select="jpegtables" trace_headers_bsf_select="cbs_h264 cbs_h265 cbs_mpeg2" diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 0e116a9c094e3..140954880cc10 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -183,6 +183,60 @@ confuse other transformations which require correct extradata. A new single global PPS is created, and all of the redundant PPSs within the stream are removed. +@section hevc_metadata + +Modify metadata embedded in an HEVC stream. + +@table @option +@item aud +Insert or remove AUD NAL units in all access units of the stream. + +@table @samp +@item insert +@item remove +@end table + +@item sample_aspect_ratio +Set the sample aspect ratio in the stream in the VUI parameters. + +@item video_format +@item video_full_range_flag +Set the video format in the stream (see H.265 section E.3.1 and +table E.2). + +@item colour_primaries +@item transfer_characteristics +@item matrix_coefficients +Set the colour description in the stream (see H.265 section E.3.1 +and tables E.3, E.4 and E.5). + +@item chroma_sample_loc_type +Set the chroma sample location in the stream (see H.265 section +E.3.1 and figure E.1). + +@item tick_rate +Set the tick rate in the VPS and VUI parameters (num_units_in_tick / +time_scale). Combined with @option{num_ticks_poc_diff_one}, this can +set a constant framerate in the stream. Note that it is likely to be +overridden by container parameters when the stream is in a container. + +@item num_ticks_poc_diff_one +Set poc_proportional_to_timing_flag in VPS and VUI and use this value +to set num_ticks_poc_diff_one_minus1 (see H.265 sections 7.4.3.1 and +E.3.1). Ignored if @option{tick_rate} is not also set. + +@item crop_left +@item crop_right +@item crop_top +@item crop_bottom +Set the conformance window cropping offsets in the SPS. These values +will replace the current ones if the stream is already cropped. + +These fields are set in pixels. Note that some sizes may not be +representable if the chroma is subsampled (H.265 section 7.4.3.2.1). + +@end table + @section hevc_mp4toannexb Convert an HEVC/H.265 bitstream from length prefixed mode to start code diff --git a/libavcodec/Makefile b/libavcodec/Makefile index a5b2b17cf3249..8a68c1b929be5 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1018,6 +1018,7 @@ OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \ OBJS-$(CONFIG_H264_METADATA_BSF) += h264_metadata_bsf.o OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o OBJS-$(CONFIG_H264_REDUNDANT_PPS_BSF) += h264_redundant_pps_bsf.o +OBJS-$(CONFIG_HEVC_METADATA_BSF) += h265_metadata_bsf.o OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 5ab4f1464223a..6e6b894e7fc83 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -32,6 +32,7 @@ extern const AVBitStreamFilter ff_extract_extradata_bsf; extern const AVBitStreamFilter ff_h264_metadata_bsf; extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf; extern const AVBitStreamFilter ff_h264_redundant_pps_bsf; +extern const AVBitStreamFilter ff_hevc_metadata_bsf; extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf; extern const AVBitStreamFilter ff_imx_dump_header_bsf; extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf; diff --git a/libavcodec/h265_metadata_bsf.c b/libavcodec/h265_metadata_bsf.c new file mode 100644 index 0000000000000..9af5cc256f932 --- /dev/null +++ b/libavcodec/h265_metadata_bsf.c @@ -0,0 +1,458 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "bsf.h" +#include "cbs.h" +#include "cbs_h265.h" +#include "hevc.h" + +enum { + PASS, + INSERT, + REMOVE, +}; + +typedef struct H265MetadataContext { + const AVClass *class; + + CodedBitstreamContext *cbc; + CodedBitstreamFragment access_unit; + + H265RawAUD aud_nal; + + int aud; + + AVRational sample_aspect_ratio; + + int video_format; + int video_full_range_flag; + int colour_primaries; + int transfer_characteristics; + int matrix_coefficients; + + int chroma_sample_loc_type; + + AVRational tick_rate; + int poc_proportional_to_timing_flag; + int num_ticks_poc_diff_one; + + int crop_left; + int crop_right; + int crop_top; + int crop_bottom; +} H265MetadataContext; + + +static int h265_metadata_update_vps(AVBSFContext *bsf, + H265RawVPS *vps) +{ + H265MetadataContext *ctx = bsf->priv_data; + + if (ctx->tick_rate.num && ctx->tick_rate.den) { + int num, den; + + av_reduce(&num, &den, ctx->tick_rate.num, ctx->tick_rate.den, + UINT32_MAX > INT_MAX ? UINT32_MAX : INT_MAX); + + vps->vps_time_scale = num; + vps->vps_num_units_in_tick = den; + + vps->vps_timing_info_present_flag = 1; + + if (ctx->num_ticks_poc_diff_one > 0) { + vps->vps_num_ticks_poc_diff_one_minus1 = + ctx->num_ticks_poc_diff_one - 1; + vps->vps_poc_proportional_to_timing_flag = 1; + } else if (ctx->num_ticks_poc_diff_one == 0) { + vps->vps_poc_proportional_to_timing_flag = 0; + } + } + + return 0; +} + +static int h265_metadata_update_sps(AVBSFContext *bsf, + H265RawSPS *sps) +{ + H265MetadataContext *ctx = bsf->priv_data; + int need_vui = 0; + int crop_unit_x, crop_unit_y; + + if (ctx->sample_aspect_ratio.num && ctx->sample_aspect_ratio.den) { + // Table E-1. + static const AVRational sar_idc[] = { + { 0, 0 }, // Unspecified (never written here). + { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, + { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, + { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, + { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, + }; + int num, den, i; + + av_reduce(&num, &den, ctx->sample_aspect_ratio.num, + ctx->sample_aspect_ratio.den, 65535); + + for (i = 1; i < FF_ARRAY_ELEMS(sar_idc); i++) { + if (num == sar_idc[i].num && + den == sar_idc[i].den) + break; + } + if (i == FF_ARRAY_ELEMS(sar_idc)) { + sps->vui.aspect_ratio_idc = 255; + sps->vui.sar_width = num; + sps->vui.sar_height = den; + } else { + sps->vui.aspect_ratio_idc = i; + } + sps->vui.aspect_ratio_info_present_flag = 1; + need_vui = 1; + } + +#define SET_OR_INFER(field, value, present_flag, infer) do { \ + if (value >= 0) { \ + field = value; \ + need_vui = 1; \ + } else if (!present_flag) \ + field = infer; \ + } while (0) + + if (ctx->video_format >= 0 || + ctx->video_full_range_flag >= 0 || + ctx->colour_primaries >= 0 || + ctx->transfer_characteristics >= 0 || + ctx->matrix_coefficients >= 0) { + + SET_OR_INFER(sps->vui.video_format, ctx->video_format, + sps->vui.video_signal_type_present_flag, 5); + + SET_OR_INFER(sps->vui.video_full_range_flag, + ctx->video_full_range_flag, + sps->vui.video_signal_type_present_flag, 0); + + if (ctx->colour_primaries >= 0 || + ctx->transfer_characteristics >= 0 || + ctx->matrix_coefficients >= 0) { + + SET_OR_INFER(sps->vui.colour_primaries, + ctx->colour_primaries, + sps->vui.colour_description_present_flag, 2); + + SET_OR_INFER(sps->vui.transfer_characteristics, + ctx->transfer_characteristics, + sps->vui.colour_description_present_flag, 2); + + SET_OR_INFER(sps->vui.matrix_coefficients, + ctx->matrix_coefficients, + sps->vui.colour_description_present_flag, 2); + + sps->vui.colour_description_present_flag = 1; + } + sps->vui.video_signal_type_present_flag = 1; + need_vui = 1; + } + + if (ctx->chroma_sample_loc_type >= 0) { + sps->vui.chroma_sample_loc_type_top_field = + ctx->chroma_sample_loc_type; + sps->vui.chroma_sample_loc_type_bottom_field = + ctx->chroma_sample_loc_type; + sps->vui.chroma_loc_info_present_flag = 1; + need_vui = 1; + } + + if (ctx->tick_rate.num && ctx->tick_rate.den) { + int num, den; + + av_reduce(&num, &den, ctx->tick_rate.num, ctx->tick_rate.den, + UINT32_MAX > INT_MAX ? UINT32_MAX : INT_MAX); + + sps->vui.vui_time_scale = num; + sps->vui.vui_num_units_in_tick = den; + + sps->vui.vui_timing_info_present_flag = 1; + need_vui = 1; + + if (ctx->num_ticks_poc_diff_one > 0) { + sps->vui.vui_num_ticks_poc_diff_one_minus1 = + ctx->num_ticks_poc_diff_one - 1; + sps->vui.vui_poc_proportional_to_timing_flag = 1; + } else if (ctx->num_ticks_poc_diff_one == 0) { + sps->vui.vui_poc_proportional_to_timing_flag = 0; + } + } + + if (sps->separate_colour_plane_flag || sps->chroma_format_idc == 0) { + crop_unit_x = 1; + crop_unit_y = 1; + } else { + crop_unit_x = 1 + (sps->chroma_format_idc < 3); + crop_unit_y = 1 + (sps->chroma_format_idc < 2); + } +#define CROP(border, unit) do { \ + if (ctx->crop_ ## border >= 0) { \ + if (ctx->crop_ ## border % unit != 0) { \ + av_log(bsf, AV_LOG_ERROR, "Invalid value for crop_%s: " \ + "must be a multiple of %d.\n", #border, unit); \ + return AVERROR(EINVAL); \ + } \ + sps->conf_win_ ## border ## _offset = \ + ctx->crop_ ## border / unit; \ + sps->conformance_window_flag = 1; \ + } \ + } while (0) + CROP(left, crop_unit_x); + CROP(right, crop_unit_x); + CROP(top, crop_unit_y); + CROP(bottom, crop_unit_y); +#undef CROP + + if (need_vui) + sps->vui_parameters_present_flag = 1; + + return 0; +} + +static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *out) +{ + H265MetadataContext *ctx = bsf->priv_data; + AVPacket *in = NULL; + CodedBitstreamFragment *au = &ctx->access_unit; + int err, i; + + err = ff_bsf_get_packet(bsf, &in); + if (err < 0) + goto fail; + + err = ff_cbs_read_packet(ctx->cbc, au, in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); + goto fail; + } + + if (au->nb_units == 0) { + av_log(bsf, AV_LOG_ERROR, "No NAL units in packet.\n"); + err = AVERROR_INVALIDDATA; + goto fail; + } + + // If an AUD is present, it must be the first NAL unit. + if (au->units[0].type == HEVC_NAL_AUD) { + if (ctx->aud == REMOVE) + ff_cbs_delete_unit(ctx->cbc, au, 0); + } else { + if (ctx->aud == INSERT) { + H265RawAUD *aud = &ctx->aud_nal; + int pic_type = 0, temporal_id = 8, layer_id = 0; + + for (i = 0; i < au->nb_units; i++) { + const H265RawNALUnitHeader *nal = au->units[i].content; + if (!nal) + continue; + if (nal->nuh_temporal_id_plus1 < temporal_id + 1) + temporal_id = nal->nuh_temporal_id_plus1 - 1; + + if (au->units[i].type <= HEVC_NAL_RSV_VCL31) { + const H265RawSlice *slice = au->units[i].content; + layer_id = nal->nuh_layer_id; + if (slice->header.slice_type == HEVC_SLICE_B && + pic_type < 2) + pic_type = 2; + if (slice->header.slice_type == HEVC_SLICE_P && + pic_type < 1) + pic_type = 1; + } + } + + aud->nal_unit_header = (H265RawNALUnitHeader) { + .nal_unit_type = HEVC_NAL_AUD, + .nuh_layer_id = layer_id, + .nuh_temporal_id_plus1 = temporal_id + 1, + }; + aud->pic_type = pic_type; + + err = ff_cbs_insert_unit_content(ctx->cbc, au, + 0, HEVC_NAL_AUD, aud); + if (err) { + av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n"); + goto fail; + } + } + } + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == HEVC_NAL_VPS) { + err = h265_metadata_update_vps(bsf, au->units[i].content); + if (err < 0) + goto fail; + } + if (au->units[i].type == HEVC_NAL_SPS) { + err = h265_metadata_update_sps(bsf, au->units[i].content); + if (err < 0) + goto fail; + } + } + + err = ff_cbs_write_packet(ctx->cbc, out, au); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); + goto fail; + } + + err = av_packet_copy_props(out, in); + if (err < 0) + goto fail; + + err = 0; +fail: + ff_cbs_fragment_uninit(ctx->cbc, au); + + av_packet_free(&in); + + return err; +} + +static int h265_metadata_init(AVBSFContext *bsf) +{ + H265MetadataContext *ctx = bsf->priv_data; + CodedBitstreamFragment *au = &ctx->access_unit; + int err, i; + + err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_HEVC, bsf); + if (err < 0) + return err; + + if (bsf->par_in->extradata) { + err = ff_cbs_read_extradata(ctx->cbc, au, bsf->par_in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); + goto fail; + } + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == HEVC_NAL_VPS) { + err = h265_metadata_update_vps(bsf, au->units[i].content); + if (err < 0) + goto fail; + } + if (au->units[i].type == HEVC_NAL_SPS) { + err = h265_metadata_update_sps(bsf, au->units[i].content); + if (err < 0) + goto fail; + } + } + + err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, au); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); + goto fail; + } + } + + err = 0; +fail: + ff_cbs_fragment_uninit(ctx->cbc, au); + return err; +} + +static void h265_metadata_close(AVBSFContext *bsf) +{ + H265MetadataContext *ctx = bsf->priv_data; + ff_cbs_close(&ctx->cbc); +} + +#define OFFSET(x) offsetof(H265MetadataContext, x) +static const AVOption h265_metadata_options[] = { + { "aud", "Access Unit Delimiter NAL units", + OFFSET(aud), AV_OPT_TYPE_INT, + { .i64 = PASS }, PASS, REMOVE, 0, "aud" }, + { "pass", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PASS }, .unit = "aud" }, + { "insert", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = INSERT }, .unit = "aud" }, + { "remove", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE }, .unit = "aud" }, + + { "sample_aspect_ratio", "Set sample aspect ratio (table E-1)", + OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, + { .dbl = 0.0 }, 0, 65535 }, + + { "video_format", "Set video format (table E-2)", + OFFSET(video_format), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 7 }, + { "video_full_range_flag", "Set video full range flag", + OFFSET(video_full_range_flag), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 1 }, + { "colour_primaries", "Set colour primaries (table E-3)", + OFFSET(colour_primaries), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + { "transfer_characteristics", "Set transfer characteristics (table E-4)", + OFFSET(transfer_characteristics), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + { "matrix_coefficients", "Set matrix coefficients (table E-5)", + OFFSET(matrix_coefficients), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + + { "chroma_sample_loc_type", "Set chroma sample location type (figure E-1)", + OFFSET(chroma_sample_loc_type), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 6 }, + + { "tick_rate", + "Set VPS and VUI tick rate (num_units_in_tick / time_scale)", + OFFSET(tick_rate), AV_OPT_TYPE_RATIONAL, + { .dbl = 0.0 }, 0, UINT_MAX }, + { "num_ticks_poc_diff_one", + "Set VPS and VUI number of ticks per POC increment", + OFFSET(num_ticks_poc_diff_one), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, INT_MAX }, + + { "crop_left", "Set left border crop offset", + OFFSET(crop_left), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, HEVC_MAX_WIDTH }, + { "crop_right", "Set right border crop offset", + OFFSET(crop_right), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, HEVC_MAX_WIDTH }, + { "crop_top", "Set top border crop offset", + OFFSET(crop_top), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, HEVC_MAX_HEIGHT }, + { "crop_bottom", "Set bottom border crop offset", + OFFSET(crop_bottom), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, HEVC_MAX_HEIGHT }, + + { NULL } +}; + +static const AVClass h265_metadata_class = { + .class_name = "h265_metadata_bsf", + .item_name = av_default_item_name, + .option = h265_metadata_options, + .version = LIBAVCODEC_VERSION_MAJOR, +}; + +static const enum AVCodecID h265_metadata_codec_ids[] = { + AV_CODEC_ID_HEVC, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_hevc_metadata_bsf = { + .name = "hevc_metadata", + .priv_data_size = sizeof(H265MetadataContext), + .priv_class = &h265_metadata_class, + .init = &h265_metadata_init, + .close = &h265_metadata_close, + .filter = &h265_metadata_filter, + .codec_ids = h265_metadata_codec_ids, +}; From 278c308ceae6b8d7bac1dfc24518821aae603988 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 12 Sep 2017 22:11:56 +0100 Subject: [PATCH 0508/2557] mpeg12: Add a common function to find the best frame rate This will be used later in both the mpeg2_metadata filter and the VAAPI MPEG-2 encoder. Also adds a unit test. (cherry picked from commit b5859e0b04bdbe12c97cb12ac10a45d51d2d73c9) --- libavcodec/Makefile | 1 + libavcodec/mpeg12.h | 4 ++ libavcodec/mpeg12framerate.c | 64 ++++++++++++++++++++++ libavcodec/tests/mpeg12framerate.c | 87 ++++++++++++++++++++++++++++++ tests/fate/libavcodec.mak | 5 ++ 5 files changed, 161 insertions(+) create mode 100644 libavcodec/tests/mpeg12framerate.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 8a68c1b929be5..a0b23a794eb73 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1090,6 +1090,7 @@ TESTPROGS-$(CONFIG_GOLOMB) += golomb TESTPROGS-$(CONFIG_IDCTDSP) += dct TESTPROGS-$(CONFIG_IIRFILTER) += iirfilter TESTPROGS-$(HAVE_MMX) += motion +TESTPROGS-$(CONFIG_MPEGVIDEO) += mpeg12framerate TESTPROGS-$(CONFIG_RANGECODER) += rangecoder TESTPROGS-$(CONFIG_SNOW_ENCODER) += snowenc diff --git a/libavcodec/mpeg12.h b/libavcodec/mpeg12.h index f551504b8cc74..1ec99f17e16d7 100644 --- a/libavcodec/mpeg12.h +++ b/libavcodec/mpeg12.h @@ -73,4 +73,8 @@ void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], void ff_mpeg1_encode_init(MpegEncContext *s); void ff_mpeg1_encode_slice_header(MpegEncContext *s); +void ff_mpeg12_find_best_frame_rate(AVRational frame_rate, + int *code, int *ext_n, int *ext_d, + int nonstandard); + #endif /* AVCODEC_MPEG12_H */ diff --git a/libavcodec/mpeg12framerate.c b/libavcodec/mpeg12framerate.c index 094cd180a5f6e..ab3d351173bc1 100644 --- a/libavcodec/mpeg12framerate.c +++ b/libavcodec/mpeg12framerate.c @@ -18,6 +18,9 @@ #include "libavutil/rational.h" +#include "mpeg12.h" +#include "mpeg12data.h" + const AVRational ff_mpeg12_frame_rate_tab[16] = { { 0, 0}, {24000, 1001}, @@ -37,3 +40,64 @@ const AVRational ff_mpeg12_frame_rate_tab[16] = { { 15, 1}, { 0, 0}, }; + +void ff_mpeg12_find_best_frame_rate(AVRational frame_rate, + int *code, int *ext_n, int *ext_d, + int nonstandard) +{ + int mpeg2 = ext_n && ext_d; + int max_code = nonstandard ? 12 : 8; + int c, n, d, best_c, best_n, best_d; + AVRational best_error = { INT_MAX, 1 }; + + // Default to NTSC if the inputs make no sense. + best_c = 4; + best_n = best_d = 1; + + for (c = 1; c <= max_code; c++) { + if (av_cmp_q(frame_rate, ff_mpeg12_frame_rate_tab[c]) == 0) { + best_c = c; + goto found; + } + } + + for (c = 1; c <= max_code; c++) { + for (n = 1; n <= (mpeg2 ? 4 : 1); n++) { + for (d = 1; d <= (mpeg2 ? 32 : 1); d++) { + AVRational test, error; + int cmp; + + test = av_mul_q(ff_mpeg12_frame_rate_tab[c], + (AVRational) { n, d }); + + cmp = av_cmp_q(test, frame_rate); + if (cmp == 0) { + best_c = c; + best_n = n; + best_d = d; + goto found; + } + + if (cmp < 0) + error = av_div_q(frame_rate, test); + else + error = av_div_q(test, frame_rate); + + cmp = av_cmp_q(error, best_error); + if (cmp < 0 || (cmp == 0 && n == 1 && d == 1)) { + best_c = c; + best_n = n; + best_d = d; + best_error = error; + } + } + } + } + +found: + *code = best_c; + if (mpeg2) { + *ext_n = best_n - 1; + *ext_d = best_d - 1; + } +} diff --git a/libavcodec/tests/mpeg12framerate.c b/libavcodec/tests/mpeg12framerate.c new file mode 100644 index 0000000000000..595bdb278a0ed --- /dev/null +++ b/libavcodec/tests/mpeg12framerate.c @@ -0,0 +1,87 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/mpeg12.h" +#include "libavcodec/mpeg12data.h" + +int main(void) +{ + int i; + +#define TEST_MATCH(frame_rate, code, ext_n, ext_d) do { \ + AVRational fr = frame_rate; \ + int c, n, d; \ + ff_mpeg12_find_best_frame_rate(fr, &c, &n, &d, 0); \ + if (c != code || n != ext_n || d != ext_d) { \ + av_log(NULL, AV_LOG_ERROR, "Failed to match %d/%d: " \ + "code = %d, ext_n = %d, ext_d = %d.\n", \ + fr.num, fr.den, c, n, d); \ + return 1; \ + } \ + } while (0) +#define TEST_EXACT(frn, frd) do { \ + AVRational fr = (AVRational) { frn, frd }; \ + int c, n, d; \ + ff_mpeg12_find_best_frame_rate(fr, &c, &n, &d, 0); \ + if (av_cmp_q(fr, av_mul_q(ff_mpeg12_frame_rate_tab[c], \ + (AVRational) { n + 1, d + 1 })) != 0) { \ + av_log(NULL, AV_LOG_ERROR, "Failed to find exact %d/%d: " \ + "code = %d, ext_n = %d, ext_d = %d.\n", \ + fr.num, fr.den, c, n, d); \ + return 1; \ + } \ + } while (0) + + // Framerates in the table must be chosen exactly. + for (i = 1; i <= 8; i++) + TEST_MATCH(ff_mpeg12_frame_rate_tab[i], i, 0, 0); + + // As should the same ones with small perturbations. + // (1/1000 used here to be smaller than half the difference + // between 24 and 24000/1001.) + for (i = 1; i <= 8; i++) { + TEST_MATCH(av_sub_q(ff_mpeg12_frame_rate_tab[i], + (AVRational) { 1, 1000 }), i, 0, 0); + TEST_MATCH(av_add_q(ff_mpeg12_frame_rate_tab[i], + (AVRational) { 1, 1000 }), i, 0, 0); + } + + // Exactly constructable framerates should be exact. Note that some + // values can be made in multiple ways (e.g. 12 = 24 / 2 == 60 / 5), + // and there is no reason to favour any particular choice. + TEST_EXACT( 1, 1); + TEST_EXACT( 2, 1); + TEST_EXACT( 12, 1); + TEST_EXACT( 15000, 1001); + TEST_EXACT( 15, 1); + TEST_EXACT( 120, 1); + TEST_EXACT(120000, 1001); + TEST_EXACT( 200, 1); + TEST_EXACT( 240, 1); + + // Values higher than 240 (the highest representable, as 60 * 4 / 1) + // should be mapped to 240. + for (i = 240; i < 1000; i += 10) + TEST_MATCH(((AVRational) { i, 1 }), 8, 3, 0); + // Values lower than 24000/32032 (the lowest representable, as + // 24000/1001 * 1 / 32) should be mapped to 24000/32032. + for (i = 74; i > 0; i--) + TEST_MATCH(((AVRational) { i, 100 }), 1, 0, 31); + + return 0; +} diff --git a/tests/fate/libavcodec.mak b/tests/fate/libavcodec.mak index 27d631d16c4b1..a2d5d9fe33372 100644 --- a/tests/fate/libavcodec.mak +++ b/tests/fate/libavcodec.mak @@ -45,6 +45,11 @@ FATE_LIBAVCODEC-$(CONFIG_IIRFILTER) += fate-iirfilter fate-iirfilter: libavcodec/tests/iirfilter$(EXESUF) fate-iirfilter: CMD = run libavcodec/tests/iirfilter +FATE_LIBAVCODEC-$(CONFIG_MPEGVIDEO) += fate-mpeg12framerate +fate-mpeg12framerate: libavcodec/tests/mpeg12framerate$(EXESUF) +fate-mpeg12framerate: CMD = run libavcodec/tests/mpeg12framerate +fate-mpeg12framerate: REF = /dev/null + FATE_LIBAVCODEC-yes += fate-libavcodec-options fate-libavcodec-options: libavcodec/tests/options$(EXESUF) fate-libavcodec-options: CMD = run libavcodec/tests/options From 569721ac8dee6b73cd68ea858f59c7d800a1686d Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 1 Aug 2017 15:35:14 +0100 Subject: [PATCH 0509/2557] lavc: Add mpeg2_metadata bitstream filter (cherry picked from commit b78c30d7ec26af67c00ce2002709a189f6a87a7e) --- configure | 1 + doc/bitstream_filters.texi | 36 ++++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/mpeg2_metadata_bsf.c | 312 ++++++++++++++++++++++++++++++++ 5 files changed, 351 insertions(+) create mode 100644 libavcodec/mpeg2_metadata_bsf.c diff --git a/configure b/configure index fb1383369fbfe..834bdfaedafb2 100755 --- a/configure +++ b/configure @@ -2917,6 +2917,7 @@ h264_metadata_bsf_select="cbs_h264" h264_redundant_pps_bsf_select="cbs_h264" hevc_metadata_bsf_select="cbs_h265" mjpeg2jpeg_bsf_select="jpegtables" +mpeg2_metadata_bsf_select="cbs_mpeg2" trace_headers_bsf_select="cbs_h264 cbs_h265 cbs_mpeg2" # external libraries diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 140954880cc10..5efb8e0ee886c 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -324,6 +324,42 @@ See also the @ref{text2movsub} filter. Decompress non-standard compressed MP3 audio headers. +@section mpeg2_metadata + +Modify metadata embedded in an MPEG-2 stream. + +@table @option +@item display_aspect_ratio +Set the display aspect ratio in the stream. + +The following fixed values are supported: +@table @option +@item 4/3 +@item 16/9 +@item 221/100 +@end table +Any other value will result in square pixels being signalled instead +(see H.262 section 6.3.3 and table 6-3). + +@item frame_rate +Set the frame rate in the stream. This is constructed from a table +of known values combined with a small multiplier and divisor - if +the supplied value is not exactly representable, the nearest +representable value will be used instead (see H.262 section 6.3.3 +and table 6-4). + +@item video_format +Set the video format in the stream (see H.262 section 6.3.6 and +table 6-6). + +@item colour_primaries +@item transfer_characteristics +@item matrix_coefficients +Set the colour description in the stream (see H.262 section 6.3.6 +and tables 6-7, 6-8 and 6-9). + +@end table + @section mpeg4_unpack_bframes Unpack DivX-style packed B-frames. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index a0b23a794eb73..6d6fc36f15380 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1027,6 +1027,7 @@ OBJS-$(CONFIG_MPEG4_UNPACK_BFRAMES_BSF) += mpeg4_unpack_bframes_bsf.o OBJS-$(CONFIG_MOV2TEXTSUB_BSF) += movsub_bsf.o OBJS-$(CONFIG_MP3_HEADER_DECOMPRESS_BSF) += mp3_header_decompress_bsf.o \ mpegaudiodata.o +OBJS-$(CONFIG_MPEG2_METADATA_BSF) += mpeg2_metadata_bsf.o OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o OBJS-$(CONFIG_NULL_BSF) += null_bsf.o OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 6e6b894e7fc83..7b0cb5032a3ce 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -38,6 +38,7 @@ extern const AVBitStreamFilter ff_imx_dump_header_bsf; extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf; extern const AVBitStreamFilter ff_mjpega_dump_header_bsf; extern const AVBitStreamFilter ff_mp3_header_decompress_bsf; +extern const AVBitStreamFilter ff_mpeg2_metadata_bsf; extern const AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf; extern const AVBitStreamFilter ff_mov2textsub_bsf; extern const AVBitStreamFilter ff_noise_bsf; diff --git a/libavcodec/mpeg2_metadata_bsf.c b/libavcodec/mpeg2_metadata_bsf.c new file mode 100644 index 0000000000000..f1f84e6cd90ea --- /dev/null +++ b/libavcodec/mpeg2_metadata_bsf.c @@ -0,0 +1,312 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "bsf.h" +#include "cbs.h" +#include "cbs_mpeg2.h" +#include "mpeg12.h" + +typedef struct MPEG2MetadataContext { + const AVClass *class; + + CodedBitstreamContext *cbc; + CodedBitstreamFragment fragment; + + MPEG2RawExtensionData sequence_display_extension; + + AVRational display_aspect_ratio; + + AVRational frame_rate; + + int video_format; + int colour_primaries; + int transfer_characteristics; + int matrix_coefficients; + + int mpeg1_warned; +} MPEG2MetadataContext; + + +static int mpeg2_metadata_update_fragment(AVBSFContext *bsf, + CodedBitstreamFragment *frag) +{ + MPEG2MetadataContext *ctx = bsf->priv_data; + MPEG2RawSequenceHeader *sh = NULL; + MPEG2RawSequenceExtension *se = NULL; + MPEG2RawSequenceDisplayExtension *sde = NULL; + int i, se_pos, add_sde = 0; + + for (i = 0; i < frag->nb_units; i++) { + if (frag->units[i].type == MPEG2_START_SEQUENCE_HEADER) { + sh = frag->units[i].content; + } else if (frag->units[i].type == MPEG2_START_EXTENSION) { + MPEG2RawExtensionData *ext = frag->units[i].content; + if (ext->extension_start_code_identifier == + MPEG2_EXTENSION_SEQUENCE) { + se = &ext->data.sequence; + se_pos = i; + } else if (ext->extension_start_code_identifier == + MPEG2_EXTENSION_SEQUENCE_DISPLAY) { + sde = &ext->data.sequence_display; + } + } + } + + if (!sh || !se) { + // No sequence header and sequence extension: not an MPEG-2 video + // sequence. + if (sh && !ctx->mpeg1_warned) { + av_log(bsf, AV_LOG_WARNING, "Stream contains a sequence " + "header but not a sequence extension: maybe it's " + "actually MPEG-1?\n"); + ctx->mpeg1_warned = 1; + } + return 0; + } + + if (ctx->display_aspect_ratio.num && ctx->display_aspect_ratio.den) { + int num, den; + + av_reduce(&num, &den, ctx->display_aspect_ratio.num, + ctx->display_aspect_ratio.den, 65535); + + if (num == 4 && den == 3) + sh->aspect_ratio_information = 2; + else if (num == 16 && den == 9) + sh->aspect_ratio_information = 3; + else if (num == 221 && den == 100) + sh->aspect_ratio_information = 4; + else + sh->aspect_ratio_information = 1; + } + + if (ctx->frame_rate.num && ctx->frame_rate.den) { + int code, ext_n, ext_d; + + ff_mpeg12_find_best_frame_rate(ctx->frame_rate, + &code, &ext_n, &ext_d, 0); + + sh->frame_rate_code = code; + se->frame_rate_extension_n = ext_n; + se->frame_rate_extension_d = ext_d; + } + + if (ctx->video_format >= 0 || + ctx->colour_primaries >= 0 || + ctx->transfer_characteristics >= 0 || + ctx->matrix_coefficients >= 0) { + if (!sde) { + add_sde = 1; + ctx->sequence_display_extension.extension_start_code = + MPEG2_START_EXTENSION; + ctx->sequence_display_extension.extension_start_code_identifier = + MPEG2_EXTENSION_SEQUENCE_DISPLAY; + sde = &ctx->sequence_display_extension.data.sequence_display; + + *sde = (MPEG2RawSequenceDisplayExtension) { + .video_format = 5, + + .colour_description = 0, + .colour_primaries = 2, + .transfer_characteristics = 2, + .matrix_coefficients = 2, + + .display_horizontal_size = + se->horizontal_size_extension << 12 | sh->horizontal_size_value, + .display_vertical_size = + se->vertical_size_extension << 12 | sh->vertical_size_value, + }; + } + + if (ctx->video_format >= 0) + sde->video_format = ctx->video_format; + + if (ctx->colour_primaries >= 0 || + ctx->transfer_characteristics >= 0 || + ctx->matrix_coefficients >= 0) { + sde->colour_description = 1; + + if (ctx->colour_primaries >= 0) + sde->colour_primaries = ctx->colour_primaries; + else if (add_sde) + sde->colour_primaries = 2; + + if (ctx->transfer_characteristics >= 0) + sde->transfer_characteristics = ctx->transfer_characteristics; + else if (add_sde) + sde->transfer_characteristics = 2; + + if (ctx->matrix_coefficients >= 0) + sde->matrix_coefficients = ctx->matrix_coefficients; + else if (add_sde) + sde->matrix_coefficients = 2; + } + } + + if (add_sde) { + int err; + + err = ff_cbs_insert_unit_content(ctx->cbc, frag, se_pos + 1, + MPEG2_START_EXTENSION, + &ctx->sequence_display_extension); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to insert new sequence " + "display extension.\n"); + return err; + } + } + + return 0; +} + +static int mpeg2_metadata_filter(AVBSFContext *bsf, AVPacket *out) +{ + MPEG2MetadataContext *ctx = bsf->priv_data; + AVPacket *in = NULL; + CodedBitstreamFragment *frag = &ctx->fragment; + int err; + + err = ff_bsf_get_packet(bsf, &in); + if (err < 0) + goto fail; + + err = ff_cbs_read_packet(ctx->cbc, frag, in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); + goto fail; + } + + err = mpeg2_metadata_update_fragment(bsf, frag); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to update frame fragment.\n"); + goto fail; + } + + err = ff_cbs_write_packet(ctx->cbc, out, frag); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); + goto fail; + } + + err = av_packet_copy_props(out, in); + if (err < 0) { + av_packet_unref(out); + goto fail; + } + + err = 0; +fail: + ff_cbs_fragment_uninit(ctx->cbc, frag); + + av_packet_free(&in); + + return err; +} + +static int mpeg2_metadata_init(AVBSFContext *bsf) +{ + MPEG2MetadataContext *ctx = bsf->priv_data; + CodedBitstreamFragment *frag = &ctx->fragment; + int err; + + err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_MPEG2VIDEO, bsf); + if (err < 0) + return err; + + if (bsf->par_in->extradata) { + err = ff_cbs_read_extradata(ctx->cbc, frag, bsf->par_in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); + goto fail; + } + + err = mpeg2_metadata_update_fragment(bsf, frag); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to update metadata fragment.\n"); + goto fail; + } + + err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, frag); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); + goto fail; + } + } + + err = 0; +fail: + ff_cbs_fragment_uninit(ctx->cbc, frag); + return err; +} + +static void mpeg2_metadata_close(AVBSFContext *bsf) +{ + MPEG2MetadataContext *ctx = bsf->priv_data; + ff_cbs_close(&ctx->cbc); +} + +#define OFFSET(x) offsetof(MPEG2MetadataContext, x) +static const AVOption mpeg2_metadata_options[] = { + { "display_aspect_ratio", "Set display aspect ratio (table 6-3)", + OFFSET(display_aspect_ratio), AV_OPT_TYPE_RATIONAL, + { .dbl = 0.0 }, 0, 65535 }, + + { "frame_rate", "Set frame rate", + OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, + { .dbl = 0.0 }, 0, UINT_MAX }, + + { "video_format", "Set video format (table 6-6)", + OFFSET(video_format), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 7 }, + { "colour_primaries", "Set colour primaries (table 6-7)", + OFFSET(colour_primaries), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + { "transfer_characteristics", "Set transfer characteristics (table 6-8)", + OFFSET(transfer_characteristics), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + { "matrix_coefficients", "Set matrix coefficients (table 6-9)", + OFFSET(matrix_coefficients), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 255 }, + + { NULL } +}; + +static const AVClass mpeg2_metadata_class = { + .class_name = "mpeg2_metadata_bsf", + .item_name = av_default_item_name, + .option = mpeg2_metadata_options, + .version = LIBAVCODEC_VERSION_MAJOR, +}; + +static const enum AVCodecID mpeg2_metadata_codec_ids[] = { + AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_mpeg2_metadata_bsf = { + .name = "mpeg2_metadata", + .priv_data_size = sizeof(MPEG2MetadataContext), + .priv_class = &mpeg2_metadata_class, + .init = &mpeg2_metadata_init, + .close = &mpeg2_metadata_close, + .filter = &mpeg2_metadata_filter, + .codec_ids = mpeg2_metadata_codec_ids, +}; From 2e29ca2a9f19ba9a5b189f322f38497d2e2e3db0 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 7 May 2017 15:01:42 +0100 Subject: [PATCH 0510/2557] vaapi_h264: Convert to use coded bitstream infrastructure (cherry picked from commit 7a4fac5e91789b73e07bd4ad20493cfde028df76) --- configure | 2 +- libavcodec/Makefile | 2 +- libavcodec/vaapi_encode_h264.c | 1425 ++++++++++++-------------------- 3 files changed, 551 insertions(+), 878 deletions(-) diff --git a/configure b/configure index 834bdfaedafb2..d11a95a04f7d8 100755 --- a/configure +++ b/configure @@ -2826,7 +2826,7 @@ h264_qsv_encoder_select="qsvenc" h264_rkmpp_decoder_deps="rkmpp" h264_rkmpp_decoder_select="h264_mp4toannexb_bsf" h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" -h264_vaapi_encoder_select="vaapi_encode golomb" +h264_vaapi_encoder_select="cbs_h264 vaapi_encode" h264_vda_decoder_deps="vda" h264_vda_decoder_select="h264_decoder" h264_vdpau_decoder_deps="vdpau" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 6d6fc36f15380..7b6fcd7aa2519 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -346,7 +346,7 @@ OBJS-$(CONFIG_H264_OMX_ENCODER) += omx.o OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec_h2645.o OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.o OBJS-$(CONFIG_H264_RKMPP_DECODER) += rkmppdec.o -OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o vaapi_encode_h26x.o +OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o OBJS-$(CONFIG_H264_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o OBJS-$(CONFIG_H264_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_H264_V4L2M2M_ENCODER) += v4l2_m2m_enc.o diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index efde80b08ee9c..9a8019aa7b41d 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -16,128 +16,36 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include #include #include "libavutil/avassert.h" +#include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/opt.h" -#include "libavutil/pixfmt.h" #include "avcodec.h" +#include "cbs.h" +#include "cbs_h264.h" #include "h264.h" #include "h264_sei.h" #include "internal.h" #include "vaapi_encode.h" -#include "vaapi_encode_h26x.h" enum { - SLICE_TYPE_P = 0, - SLICE_TYPE_B = 1, - SLICE_TYPE_I = 2, - SLICE_TYPE_SP = 3, - SLICE_TYPE_SI = 4, + SEI_TIMING = 0x01, + SEI_IDENTIFIER = 0x02, }; -// This structure contains all possibly-useful per-sequence syntax elements -// which are not already contained in the various VAAPI structures. -typedef struct VAAPIEncodeH264MiscSequenceParams { - unsigned int profile_idc; - char constraint_set0_flag; - char constraint_set1_flag; - char constraint_set2_flag; - char constraint_set3_flag; - char constraint_set4_flag; - char constraint_set5_flag; - - char separate_colour_plane_flag; - char qpprime_y_zero_transform_bypass_flag; - - char gaps_in_frame_num_allowed_flag; - char delta_pic_order_always_zero_flag; - char bottom_field_pic_order_in_frame_present_flag; - - unsigned int num_slice_groups_minus1; - unsigned int slice_group_map_type; - - int pic_init_qs_minus26; - - char overscan_info_present_flag; - char overscan_appropriate_flag; - - char video_signal_type_present_flag; - unsigned int video_format; - char video_full_range_flag; - char colour_description_present_flag; - unsigned int colour_primaries; - unsigned int transfer_characteristics; - unsigned int matrix_coefficients; - - char chroma_loc_info_present_flag; - unsigned int chroma_sample_loc_type_top_field; - unsigned int chroma_sample_loc_type_bottom_field; - - // Some timing elements are in VAEncSequenceParameterBufferH264. - char fixed_frame_rate_flag; - - char nal_hrd_parameters_present_flag; - char vcl_hrd_parameters_present_flag; - char low_delay_hrd_flag; - char pic_struct_present_flag; - - char motion_vectors_over_pic_boundaries_flag; - unsigned int max_bytes_per_pic_denom; - unsigned int max_bits_per_mb_denom; - unsigned int max_num_reorder_frames; - unsigned int max_dec_pic_buffering; - - unsigned int cpb_cnt_minus1; - unsigned int bit_rate_scale; - unsigned int cpb_size_scale; - unsigned int bit_rate_value_minus1[32]; - unsigned int cpb_size_value_minus1[32]; - char cbr_flag[32]; - unsigned int initial_cpb_removal_delay_length_minus1; - unsigned int cpb_removal_delay_length_minus1; - unsigned int dpb_output_delay_length_minus1; - unsigned int time_offset_length; - - unsigned int initial_cpb_removal_delay; - unsigned int initial_cpb_removal_delay_offset; - - unsigned int pic_struct; -} VAAPIEncodeH264MiscSequenceParams; - -// This structure contains all possibly-useful per-slice syntax elements -// which are not already contained in the various VAAPI structures. -typedef struct VAAPIEncodeH264MiscSliceParams { - unsigned int nal_unit_type; - unsigned int nal_ref_idc; - - unsigned int colour_plane_id; - char field_pic_flag; - char bottom_field_flag; - - unsigned int redundant_pic_cnt; - - char sp_for_switch_flag; - int slice_qs_delta; - - char ref_pic_list_modification_flag_l0; - char ref_pic_list_modification_flag_l1; - - char no_output_of_prior_pics_flag; - char long_term_reference_flag; - char adaptive_ref_pic_marking_mode_flag; -} VAAPIEncodeH264MiscSliceParams; - -typedef struct VAAPIEncodeH264Slice { - VAAPIEncodeH264MiscSliceParams misc_slice_params; -} VAAPIEncodeH264Slice; +// Random (version 4) ISO 11578 UUID. +static const uint8_t vaapi_encode_h264_sei_identifier_uuid[16] = { + 0x59, 0x94, 0x8b, 0x28, 0x11, 0xec, 0x45, 0xaf, + 0x96, 0x75, 0x19, 0xd4, 0x1f, 0xea, 0xa9, 0x4d, +}; typedef struct VAAPIEncodeH264Context { - VAAPIEncodeH264MiscSequenceParams misc_sequence_params; - int mb_width; int mb_height; @@ -145,15 +53,31 @@ typedef struct VAAPIEncodeH264Context { int fixed_qp_p; int fixed_qp_b; + H264RawSPS sps; + H264RawPPS pps; + H264RawSEI sei; + H264RawSlice slice; + + H264RawSEIBufferingPeriod buffering_period; + H264RawSEIPicTiming pic_timing; + H264RawSEIUserDataUnregistered identifier; + char *identifier_string; + + int frame_num; + int pic_order_cnt; int next_frame_num; int64_t last_idr_frame; int64_t idr_pic_count; + int primary_pic_type; + int slice_type; + int cpb_delay; int dpb_delay; - // Rate control configuration. - int send_timing_sei; + CodedBitstreamContext *cbc; + CodedBitstreamFragment current_access_unit; + int sei_needed; } VAAPIEncodeH264Context; typedef struct VAAPIEncodeH264Options { @@ -162,567 +86,77 @@ typedef struct VAAPIEncodeH264Options { int low_power; // Entropy encoder type. int coder; + int sei; } VAAPIEncodeH264Options; -#define vseq_var(name) vseq->name, name -#define vseq_field(name) vseq->seq_fields.bits.name, name -#define vvui_field(name) vseq->vui_fields.bits.name, name -#define vpic_var(name) vpic->name, name -#define vpic_field(name) vpic->pic_fields.bits.name, name -#define vslice_var(name) vslice->name, name -#define vslice_field(name) vslice->slice_fields.bits.name, name -#define mseq_var(name) mseq->name, name -#define mslice_var(name) mslice->name, name - -static void vaapi_encode_h264_write_nal_header(PutBitContext *pbc, - int nal_unit_type, int nal_ref_idc) -{ - u(1, 0, forbidden_zero_bit); - u(2, nal_ref_idc, nal_ref_idc); - u(5, nal_unit_type, nal_unit_type); -} - -static void vaapi_encode_h264_write_trailing_rbsp(PutBitContext *pbc) -{ - u(1, 1, rbsp_stop_one_bit); - while (put_bits_count(pbc) & 7) - u(1, 0, rbsp_alignment_zero_bit); -} - -static void vaapi_encode_h264_write_vui(PutBitContext *pbc, - VAAPIEncodeContext *ctx) -{ - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - int i; - - u(1, vvui_field(aspect_ratio_info_present_flag)); - if (vseq->vui_fields.bits.aspect_ratio_info_present_flag) { - u(8, vseq_var(aspect_ratio_idc)); - if (vseq->aspect_ratio_idc == 255) { - u(16, vseq_var(sar_width)); - u(16, vseq_var(sar_height)); - } - } - - u(1, mseq_var(overscan_info_present_flag)); - if (mseq->overscan_info_present_flag) - u(1, mseq_var(overscan_appropriate_flag)); - - u(1, mseq_var(video_signal_type_present_flag)); - if (mseq->video_signal_type_present_flag) { - u(3, mseq_var(video_format)); - u(1, mseq_var(video_full_range_flag)); - u(1, mseq_var(colour_description_present_flag)); - if (mseq->colour_description_present_flag) { - u(8, mseq_var(colour_primaries)); - u(8, mseq_var(transfer_characteristics)); - u(8, mseq_var(matrix_coefficients)); - } - } - - u(1, mseq_var(chroma_loc_info_present_flag)); - if (mseq->chroma_loc_info_present_flag) { - ue(mseq_var(chroma_sample_loc_type_top_field)); - ue(mseq_var(chroma_sample_loc_type_bottom_field)); - } - - u(1, vvui_field(timing_info_present_flag)); - if (vseq->vui_fields.bits.timing_info_present_flag) { - u(32, vseq_var(num_units_in_tick)); - u(32, vseq_var(time_scale)); - u(1, mseq_var(fixed_frame_rate_flag)); - } - - u(1, mseq_var(nal_hrd_parameters_present_flag)); - if (mseq->nal_hrd_parameters_present_flag) { - ue(mseq_var(cpb_cnt_minus1)); - u(4, mseq_var(bit_rate_scale)); - u(4, mseq_var(cpb_size_scale)); - for (i = 0; i <= mseq->cpb_cnt_minus1; i++) { - ue(mseq_var(bit_rate_value_minus1[i])); - ue(mseq_var(cpb_size_value_minus1[i])); - u(1, mseq_var(cbr_flag[i])); - } - u(5, mseq_var(initial_cpb_removal_delay_length_minus1)); - u(5, mseq_var(cpb_removal_delay_length_minus1)); - u(5, mseq_var(dpb_output_delay_length_minus1)); - u(5, mseq_var(time_offset_length)); - } - u(1, mseq_var(vcl_hrd_parameters_present_flag)); - if (mseq->vcl_hrd_parameters_present_flag) { - av_assert0(0 && "vcl hrd parameters not supported"); - } - - if (mseq->nal_hrd_parameters_present_flag || - mseq->vcl_hrd_parameters_present_flag) - u(1, mseq_var(low_delay_hrd_flag)); - u(1, mseq_var(pic_struct_present_flag)); - - u(1, vvui_field(bitstream_restriction_flag)); - if (vseq->vui_fields.bits.bitstream_restriction_flag) { - u(1, mseq_var(motion_vectors_over_pic_boundaries_flag)); - ue(mseq_var(max_bytes_per_pic_denom)); - ue(mseq_var(max_bits_per_mb_denom)); - ue(vvui_field(log2_max_mv_length_horizontal)); - ue(vvui_field(log2_max_mv_length_vertical)); - ue(mseq_var(max_num_reorder_frames)); - ue(mseq_var(max_dec_pic_buffering)); - } -} - -static void vaapi_encode_h264_write_sps(PutBitContext *pbc, - VAAPIEncodeContext *ctx) -{ - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - int i; - - vaapi_encode_h264_write_nal_header(pbc, H264_NAL_SPS, 3); - - u(8, mseq_var(profile_idc)); - u(1, mseq_var(constraint_set0_flag)); - u(1, mseq_var(constraint_set1_flag)); - u(1, mseq_var(constraint_set2_flag)); - u(1, mseq_var(constraint_set3_flag)); - u(1, mseq_var(constraint_set4_flag)); - u(1, mseq_var(constraint_set5_flag)); - u(2, 0, reserved_zero_2bits); - - u(8, vseq_var(level_idc)); - - ue(vseq_var(seq_parameter_set_id)); - - if (mseq->profile_idc == 100 || mseq->profile_idc == 110 || - mseq->profile_idc == 122 || mseq->profile_idc == 244 || - mseq->profile_idc == 44 || mseq->profile_idc == 83 || - mseq->profile_idc == 86 || mseq->profile_idc == 118 || - mseq->profile_idc == 128 || mseq->profile_idc == 138) { - ue(vseq_field(chroma_format_idc)); - - if (vseq->seq_fields.bits.chroma_format_idc == 3) - u(1, mseq_var(separate_colour_plane_flag)); - - ue(vseq_var(bit_depth_luma_minus8)); - ue(vseq_var(bit_depth_chroma_minus8)); - - u(1, mseq_var(qpprime_y_zero_transform_bypass_flag)); - - u(1, vseq_field(seq_scaling_matrix_present_flag)); - if (vseq->seq_fields.bits.seq_scaling_matrix_present_flag) { - av_assert0(0 && "scaling matrices not supported"); - } - } - - ue(vseq_field(log2_max_frame_num_minus4)); - ue(vseq_field(pic_order_cnt_type)); - - if (vseq->seq_fields.bits.pic_order_cnt_type == 0) { - ue(vseq_field(log2_max_pic_order_cnt_lsb_minus4)); - } else if (vseq->seq_fields.bits.pic_order_cnt_type == 1) { - u(1, mseq_var(delta_pic_order_always_zero_flag)); - se(vseq_var(offset_for_non_ref_pic)); - se(vseq_var(offset_for_top_to_bottom_field)); - ue(vseq_var(num_ref_frames_in_pic_order_cnt_cycle)); - - for (i = 0; i < vseq->num_ref_frames_in_pic_order_cnt_cycle; i++) - se(vseq_var(offset_for_ref_frame[i])); - } - - ue(vseq_var(max_num_ref_frames)); - u(1, mseq_var(gaps_in_frame_num_allowed_flag)); - - ue(vseq->picture_width_in_mbs - 1, pic_width_in_mbs_minus1); - ue(vseq->picture_height_in_mbs - 1, pic_height_in_mbs_minus1); - - u(1, vseq_field(frame_mbs_only_flag)); - if (!vseq->seq_fields.bits.frame_mbs_only_flag) - u(1, vseq_field(mb_adaptive_frame_field_flag)); - - u(1, vseq_field(direct_8x8_inference_flag)); - - u(1, vseq_var(frame_cropping_flag)); - if (vseq->frame_cropping_flag) { - ue(vseq_var(frame_crop_left_offset)); - ue(vseq_var(frame_crop_right_offset)); - ue(vseq_var(frame_crop_top_offset)); - ue(vseq_var(frame_crop_bottom_offset)); - } - - u(1, vseq_var(vui_parameters_present_flag)); - if (vseq->vui_parameters_present_flag) - vaapi_encode_h264_write_vui(pbc, ctx); - - vaapi_encode_h264_write_trailing_rbsp(pbc); -} - -static void vaapi_encode_h264_write_pps(PutBitContext *pbc, - VAAPIEncodeContext *ctx) -{ - VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - - vaapi_encode_h264_write_nal_header(pbc, H264_NAL_PPS, 3); - - ue(vpic_var(pic_parameter_set_id)); - ue(vpic_var(seq_parameter_set_id)); - - u(1, vpic_field(entropy_coding_mode_flag)); - u(1, mseq_var(bottom_field_pic_order_in_frame_present_flag)); - - ue(mseq_var(num_slice_groups_minus1)); - if (mseq->num_slice_groups_minus1 > 0) { - ue(mseq_var(slice_group_map_type)); - av_assert0(0 && "slice groups not supported"); - } - - ue(vpic_var(num_ref_idx_l0_active_minus1)); - ue(vpic_var(num_ref_idx_l1_active_minus1)); - - u(1, vpic_field(weighted_pred_flag)); - u(2, vpic_field(weighted_bipred_idc)); - - se(vpic->pic_init_qp - 26, pic_init_qp_minus26); - se(mseq_var(pic_init_qs_minus26)); - se(vpic_var(chroma_qp_index_offset)); - - u(1, vpic_field(deblocking_filter_control_present_flag)); - u(1, vpic_field(constrained_intra_pred_flag)); - u(1, vpic_field(redundant_pic_cnt_present_flag)); - u(1, vpic_field(transform_8x8_mode_flag)); - - u(1, vpic_field(pic_scaling_matrix_present_flag)); - if (vpic->pic_fields.bits.pic_scaling_matrix_present_flag) { - av_assert0(0 && "scaling matrices not supported"); - } - - se(vpic_var(second_chroma_qp_index_offset)); - - vaapi_encode_h264_write_trailing_rbsp(pbc); -} - -static void vaapi_encode_h264_write_slice_header2(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic, - VAAPIEncodeSlice *slice) +static int vaapi_encode_h264_write_access_unit(AVCodecContext *avctx, + char *data, size_t *data_len, + CodedBitstreamFragment *au) { - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; - VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - VAAPIEncodeH264Slice *pslice = slice->priv_data; - VAAPIEncodeH264MiscSliceParams *mslice = &pslice->misc_slice_params; - - vaapi_encode_h264_write_nal_header(pbc, mslice->nal_unit_type, - mslice->nal_ref_idc); - - ue(vslice->macroblock_address, first_mb_in_slice); - ue(vslice_var(slice_type)); - ue(vpic_var(pic_parameter_set_id)); - - if (mseq->separate_colour_plane_flag) { - u(2, mslice_var(colour_plane_id)); - } - - u(4 + vseq->seq_fields.bits.log2_max_frame_num_minus4, - (vpic->frame_num & - ((1 << (4 + vseq->seq_fields.bits.log2_max_frame_num_minus4)) - 1)), - frame_num); - - if (!vseq->seq_fields.bits.frame_mbs_only_flag) { - u(1, mslice_var(field_pic_flag)); - if (mslice->field_pic_flag) - u(1, mslice_var(bottom_field_flag)); - } - - if (vpic->pic_fields.bits.idr_pic_flag) { - ue(vslice_var(idr_pic_id)); - } - - if (vseq->seq_fields.bits.pic_order_cnt_type == 0) { - u(4 + vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4, - vslice_var(pic_order_cnt_lsb)); - if (mseq->bottom_field_pic_order_in_frame_present_flag && - !mslice->field_pic_flag) { - se(vslice_var(delta_pic_order_cnt_bottom)); - } - } - - if (vseq->seq_fields.bits.pic_order_cnt_type == 1 && - !vseq->seq_fields.bits.delta_pic_order_always_zero_flag) { - se(vslice_var(delta_pic_order_cnt[0])); - if (mseq->bottom_field_pic_order_in_frame_present_flag && - !mslice->field_pic_flag) { - se(vslice_var(delta_pic_order_cnt[1])); - } - } - - if (vpic->pic_fields.bits.redundant_pic_cnt_present_flag) { - ue(mslice_var(redundant_pic_cnt)); - } - - if (vslice->slice_type == SLICE_TYPE_B) { - u(1, vslice_var(direct_spatial_mv_pred_flag)); - } - - if (vslice->slice_type == SLICE_TYPE_P || - vslice->slice_type == SLICE_TYPE_SP || - vslice->slice_type == SLICE_TYPE_B) { - u(1, vslice_var(num_ref_idx_active_override_flag)); - if (vslice->num_ref_idx_active_override_flag) { - ue(vslice_var(num_ref_idx_l0_active_minus1)); - if (vslice->slice_type == SLICE_TYPE_B) - ue(vslice_var(num_ref_idx_l1_active_minus1)); - } - } - - if (mslice->nal_unit_type == 20 || mslice->nal_unit_type == 21) { - av_assert0(0 && "no MVC support"); - } else { - if (vslice->slice_type % 5 != 2 && vslice->slice_type % 5 != 4) { - u(1, mslice_var(ref_pic_list_modification_flag_l0)); - if (mslice->ref_pic_list_modification_flag_l0) { - av_assert0(0 && "ref pic list modification"); - } - } - if (vslice->slice_type % 5 == 1) { - u(1, mslice_var(ref_pic_list_modification_flag_l1)); - if (mslice->ref_pic_list_modification_flag_l1) { - av_assert0(0 && "ref pic list modification"); - } - } - } - - if ((vpic->pic_fields.bits.weighted_pred_flag && - (vslice->slice_type == SLICE_TYPE_P || - vslice->slice_type == SLICE_TYPE_SP)) || - (vpic->pic_fields.bits.weighted_bipred_idc == 1 && - vslice->slice_type == SLICE_TYPE_B)) { - av_assert0(0 && "prediction weights not supported"); - } - - av_assert0(mslice->nal_ref_idc > 0 == - vpic->pic_fields.bits.reference_pic_flag); - if (mslice->nal_ref_idc != 0) { - if (vpic->pic_fields.bits.idr_pic_flag) { - u(1, mslice_var(no_output_of_prior_pics_flag)); - u(1, mslice_var(long_term_reference_flag)); - } else { - u(1, mslice_var(adaptive_ref_pic_marking_mode_flag)); - if (mslice->adaptive_ref_pic_marking_mode_flag) { - av_assert0(0 && "MMCOs not supported"); - } - } - } - - if (vpic->pic_fields.bits.entropy_coding_mode_flag && - vslice->slice_type != SLICE_TYPE_I && - vslice->slice_type != SLICE_TYPE_SI) { - ue(vslice_var(cabac_init_idc)); - } - - se(vslice_var(slice_qp_delta)); - if (vslice->slice_type == SLICE_TYPE_SP || - vslice->slice_type == SLICE_TYPE_SI) { - if (vslice->slice_type == SLICE_TYPE_SP) - u(1, mslice_var(sp_for_switch_flag)); - se(mslice_var(slice_qs_delta)); - } - - if (vpic->pic_fields.bits.deblocking_filter_control_present_flag) { - ue(vslice_var(disable_deblocking_filter_idc)); - if (vslice->disable_deblocking_filter_idc != 1) { - se(vslice_var(slice_alpha_c0_offset_div2)); - se(vslice_var(slice_beta_offset_div2)); - } - } + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + int err; - if (mseq->num_slice_groups_minus1 > 0 && - mseq->slice_group_map_type >= 3 && mseq->slice_group_map_type <= 5) { - av_assert0(0 && "slice groups not supported"); + err = ff_cbs_write_fragment_data(priv->cbc, au); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); + return err; } - // No alignment - this need not be a byte boundary. -} - -static void vaapi_encode_h264_write_buffering_period(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic) -{ - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; - int i; - - ue(vpic_var(seq_parameter_set_id)); - - if (mseq->nal_hrd_parameters_present_flag) { - for (i = 0; i <= mseq->cpb_cnt_minus1; i++) { - u(mseq->initial_cpb_removal_delay_length_minus1 + 1, - mseq_var(initial_cpb_removal_delay)); - u(mseq->initial_cpb_removal_delay_length_minus1 + 1, - mseq_var(initial_cpb_removal_delay_offset)); - } - } - if (mseq->vcl_hrd_parameters_present_flag) { - av_assert0(0 && "vcl hrd parameters not supported"); + if (*data_len < 8 * au->data_size - au->data_bit_padding) { + av_log(avctx, AV_LOG_ERROR, "Access unit too large: " + "%zu < %zu.\n", *data_len, + 8 * au->data_size - au->data_bit_padding); + return AVERROR(ENOSPC); } -} -static void vaapi_encode_h264_write_pic_timing(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic) -{ - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - int i, num_clock_ts; - - if (mseq->nal_hrd_parameters_present_flag || - mseq->vcl_hrd_parameters_present_flag) { - u(mseq->cpb_removal_delay_length_minus1 + 1, - 2 * vseq->num_units_in_tick * priv->cpb_delay, - cpb_removal_delay); - u(mseq->dpb_output_delay_length_minus1 + 1, - 2 * vseq->num_units_in_tick * priv->dpb_delay, - dpb_output_delay); - } - if (mseq->pic_struct_present_flag) { - u(4, mseq_var(pic_struct)); - num_clock_ts = (mseq->pic_struct <= 2 ? 1 : - mseq->pic_struct <= 4 ? 2 : - mseq->pic_struct <= 8 ? 3 : 0); - for (i = 0; i < num_clock_ts; i++) { - u(1, 0, clock_timestamp_flag[i]); - // No full timestamp information. - } - } -} + memcpy(data, au->data, au->data_size); + *data_len = 8 * au->data_size - au->data_bit_padding; -static void vaapi_encode_h264_write_identifier(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic) -{ - const char *lavc = LIBAVCODEC_IDENT; - const char *vaapi = VA_VERSION_S; - const char *driver = vaQueryVendorString(ctx->hwctx->display); - char tmp[256]; - int i; - - // Random (version 4) ISO 11578 UUID. - uint8_t uuid[16] = { - 0x59, 0x94, 0x8b, 0x28, 0x11, 0xec, 0x45, 0xaf, - 0x96, 0x75, 0x19, 0xd4, 0x1f, 0xea, 0xa9, 0x4d, - }; - - for (i = 0; i < 16; i++) - u(8, uuid[i], uuid_iso_iec_11578); - - snprintf(tmp, sizeof(tmp), "%s / VAAPI %s / %s", lavc, vaapi, driver); - for (i = 0; i < sizeof(tmp) && tmp[i]; i++) - u(8, tmp[i], user_data_payload_byte); + return 0; } -static void vaapi_encode_h264_write_sei(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic) +static int vaapi_encode_h264_add_nal(AVCodecContext *avctx, + CodedBitstreamFragment *au, + void *nal_unit) { + VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH264Context *priv = ctx->priv_data; - PutBitContext payload_bits; - char payload[256]; - int payload_type, payload_size, i; - void (*write_payload)(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic) = NULL; - - vaapi_encode_h264_write_nal_header(pbc, H264_NAL_SEI, 0); - - for (payload_type = 0; payload_type < 64; payload_type++) { - switch (payload_type) { - case H264_SEI_TYPE_BUFFERING_PERIOD: - if (!priv->send_timing_sei || - pic->type != PICTURE_TYPE_IDR) - continue; - write_payload = &vaapi_encode_h264_write_buffering_period; - break; - case H264_SEI_TYPE_PIC_TIMING: - if (!priv->send_timing_sei) - continue; - write_payload = &vaapi_encode_h264_write_pic_timing; - break; - case H264_SEI_TYPE_USER_DATA_UNREGISTERED: - if (pic->encode_order != 0) - continue; - write_payload = &vaapi_encode_h264_write_identifier; - break; - default: - continue; - } - - init_put_bits(&payload_bits, payload, sizeof(payload)); - write_payload(&payload_bits, ctx, pic); - if (put_bits_count(&payload_bits) & 7) { - write_u(&payload_bits, 1, 1, bit_equal_to_one); - while (put_bits_count(&payload_bits) & 7) - write_u(&payload_bits, 1, 0, bit_equal_to_zero); - } - payload_size = put_bits_count(&payload_bits) / 8; - flush_put_bits(&payload_bits); + H264RawNALUnitHeader *header = nal_unit; + int err; - u(8, payload_type, last_payload_type_byte); - u(8, payload_size, last_payload_size_byte); - for (i = 0; i < payload_size; i++) - u(8, payload[i] & 0xff, sei_payload); + err = ff_cbs_insert_unit_content(priv->cbc, au, -1, + header->nal_unit_type, nal_unit); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " + "type = %d.\n", header->nal_unit_type); + return err; } - vaapi_encode_h264_write_trailing_rbsp(pbc); + return 0; } static int vaapi_encode_h264_write_sequence_header(AVCodecContext *avctx, char *data, size_t *data_len) { - VAAPIEncodeContext *ctx = avctx->priv_data; - PutBitContext pbc; - char tmp[256]; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + CodedBitstreamFragment *au = &priv->current_access_unit; int err; - size_t nal_len, bit_len, bit_pos, next_len; - - bit_len = *data_len; - bit_pos = 0; - - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h264_write_sps(&pbc, ctx); - nal_len = put_bits_count(&pbc); - flush_put_bits(&pbc); - next_len = bit_len - bit_pos; - err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, - &next_len, - tmp, nal_len); + err = vaapi_encode_h264_add_nal(avctx, au, &priv->sps); if (err < 0) - return err; - bit_pos += next_len; - - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h264_write_pps(&pbc, ctx); - nal_len = put_bits_count(&pbc); - flush_put_bits(&pbc); + goto fail; - next_len = bit_len - bit_pos; - err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, - &next_len, - tmp, nal_len); + err = vaapi_encode_h264_add_nal(avctx, au, &priv->pps); if (err < 0) - return err; - bit_pos += next_len; + goto fail; - *data_len = bit_pos; - return 0; + err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au); +fail: + ff_cbs_fragment_uninit(priv->cbc, au); + return err; } static int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx, @@ -730,18 +164,19 @@ static int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx, VAAPIEncodeSlice *slice, char *data, size_t *data_len) { - VAAPIEncodeContext *ctx = avctx->priv_data; - PutBitContext pbc; - char tmp[256]; - size_t header_len; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + CodedBitstreamFragment *au = &priv->current_access_unit; + int err; - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h264_write_slice_header2(&pbc, ctx, pic, slice); - header_len = put_bits_count(&pbc); - flush_put_bits(&pbc); + err = vaapi_encode_h264_add_nal(avctx, au, &priv->slice); + if (err < 0) + goto fail; - return ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data, data_len, - tmp, header_len); + err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au); +fail: + ff_cbs_fragment_uninit(priv->cbc, au); + return err; } static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, @@ -749,198 +184,344 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, int index, int *type, char *data, size_t *data_len) { - VAAPIEncodeContext *ctx = avctx->priv_data; - PutBitContext pbc; - char tmp[256]; - size_t header_len; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264Options *opt = ctx->codec_options; + CodedBitstreamFragment *au = &priv->current_access_unit; + int err, i; + + if (priv->sei_needed) { + memset(&priv->sei, 0, sizeof(priv->sei)); + priv->sei.nal_unit_header.nal_unit_type = H264_NAL_SEI; + + i = 0; + if (pic->encode_order == 0 && opt->sei & SEI_IDENTIFIER) { + priv->sei.payload[i].payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED; + priv->sei.payload[i].payload.user_data_unregistered = priv->identifier; + ++i; + } + if (opt->sei & SEI_TIMING) { + if (pic->type == PICTURE_TYPE_IDR) { + priv->sei.payload[i].payload_type = H264_SEI_TYPE_BUFFERING_PERIOD; + priv->sei.payload[i].payload.buffering_period = priv->buffering_period; + ++i; + } + priv->sei.payload[i].payload_type = H264_SEI_TYPE_PIC_TIMING; + priv->sei.payload[i].payload.pic_timing = priv->pic_timing; + ++i; + } - if (index == 0 && ctx->va_rc_mode == VA_RC_CBR) { - *type = VAEncPackedHeaderH264_SEI; + priv->sei.payload_count = i; + av_assert0(priv->sei.payload_count > 0); - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h264_write_sei(&pbc, ctx, pic); - header_len = put_bits_count(&pbc); - flush_put_bits(&pbc); + err = vaapi_encode_h264_add_nal(avctx, au, &priv->sei); + if (err < 0) + goto fail; + priv->sei_needed = 0; - return ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data, data_len, - tmp, header_len); + err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au); + if (err < 0) + goto fail; + ff_cbs_fragment_uninit(priv->cbc, au); + + *type = VAEncPackedHeaderH264_SEI; + return 0; } else { return AVERROR_EOF; } + +fail: + ff_cbs_fragment_uninit(priv->cbc, au); + return err; } static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) { - VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params; - VAAPIEncodeH264Options *opt = - (VAAPIEncodeH264Options*)ctx->codec_options_data; - int i; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264Options *opt = ctx->codec_options; + H264RawSPS *sps = &priv->sps; + H264RawPPS *pps = &priv->pps; + VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params; - { - vseq->seq_parameter_set_id = 0; + memset(&priv->current_access_unit, 0, + sizeof(priv->current_access_unit)); - vseq->level_idc = avctx->level; + memset(sps, 0, sizeof(*sps)); + memset(pps, 0, sizeof(*pps)); - vseq->max_num_ref_frames = 1 + (avctx->max_b_frames > 0); + sps->nal_unit_header.nal_ref_idc = 3; + sps->nal_unit_header.nal_unit_type = H264_NAL_SPS; - vseq->picture_width_in_mbs = priv->mb_width; - vseq->picture_height_in_mbs = priv->mb_height; + sps->profile_idc = avctx->profile & 0xff; + sps->constraint_set1_flag = + !!(avctx->profile & FF_PROFILE_H264_CONSTRAINED); + sps->constraint_set3_flag = + !!(avctx->profile & FF_PROFILE_H264_INTRA); - vseq->seq_fields.bits.chroma_format_idc = 1; - vseq->seq_fields.bits.frame_mbs_only_flag = 1; - vseq->seq_fields.bits.direct_8x8_inference_flag = 1; - vseq->seq_fields.bits.log2_max_frame_num_minus4 = 4; - vseq->seq_fields.bits.pic_order_cnt_type = 0; - vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = - av_clip(av_log2(avctx->max_b_frames + 1) - 2, 0, 12); + sps->level_idc = avctx->level; - if (avctx->width != ctx->surface_width || - avctx->height != ctx->surface_height) { - vseq->frame_cropping_flag = 1; + sps->seq_parameter_set_id = 0; + sps->chroma_format_idc = 1; - vseq->frame_crop_left_offset = 0; - vseq->frame_crop_right_offset = - (ctx->surface_width - avctx->width) / 2; - vseq->frame_crop_top_offset = 0; - vseq->frame_crop_bottom_offset = - (ctx->surface_height - avctx->height) / 2; - } else { - vseq->frame_cropping_flag = 0; - } + sps->log2_max_frame_num_minus4 = 4; + sps->pic_order_cnt_type = 0; + sps->log2_max_pic_order_cnt_lsb_minus4 = + av_clip(av_log2(ctx->b_per_p + 1) - 2, 0, 12); + + sps->max_num_ref_frames = + (avctx->profile & FF_PROFILE_H264_INTRA) ? 0 : + 1 + (ctx->b_per_p > 0); + + sps->pic_width_in_mbs_minus1 = priv->mb_width - 1; + sps->pic_height_in_map_units_minus1 = priv->mb_height - 1; + + sps->frame_mbs_only_flag = 1; + sps->direct_8x8_inference_flag = 1; - vseq->vui_parameters_present_flag = 1; - if (avctx->sample_aspect_ratio.num != 0) { - vseq->vui_fields.bits.aspect_ratio_info_present_flag = 1; - // There is a large enum of these which we could support - // individually rather than using the generic X/Y form? - if (avctx->sample_aspect_ratio.num == - avctx->sample_aspect_ratio.den) { - vseq->aspect_ratio_idc = 1; - } else { - vseq->aspect_ratio_idc = 255; // Extended SAR. - vseq->sar_width = avctx->sample_aspect_ratio.num; - vseq->sar_height = avctx->sample_aspect_ratio.den; + if (avctx->width != 16 * priv->mb_width || + avctx->height != 16 * priv->mb_height) { + sps->frame_cropping_flag = 1; + + sps->frame_crop_left_offset = 0; + sps->frame_crop_right_offset = + (16 * priv->mb_width - avctx->width) / 2; + sps->frame_crop_top_offset = 0; + sps->frame_crop_bottom_offset = + (16 * priv->mb_height - avctx->height) / 2; + } else { + sps->frame_cropping_flag = 0; + } + + sps->vui_parameters_present_flag = 1; + + if (avctx->sample_aspect_ratio.num != 0 && + avctx->sample_aspect_ratio.den != 0) { + static const AVRational sar_idc[] = { + { 0, 0 }, + { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, + { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, + { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, + { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, + }; + int i; + for (i = 0; i < FF_ARRAY_ELEMS(sar_idc); i++) { + if (avctx->sample_aspect_ratio.num == sar_idc[i].num && + avctx->sample_aspect_ratio.den == sar_idc[i].den) { + sps->vui.aspect_ratio_idc = i; + break; } } + if (i >= FF_ARRAY_ELEMS(sar_idc)) { + sps->vui.aspect_ratio_idc = 255; + sps->vui.sar_width = avctx->sample_aspect_ratio.num; + sps->vui.sar_height = avctx->sample_aspect_ratio.den; + } + sps->vui.aspect_ratio_info_present_flag = 1; + } + + if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || + avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED || + avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { + sps->vui.video_signal_type_present_flag = 1; + sps->vui.video_format = 5; // Unspecified. + sps->vui.video_full_range_flag = + avctx->color_range == AVCOL_RANGE_JPEG; + if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || avctx->color_trc != AVCOL_TRC_UNSPECIFIED || avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { - mseq->video_signal_type_present_flag = 1; - mseq->video_format = 5; // Unspecified. - mseq->video_full_range_flag = 0; - mseq->colour_description_present_flag = 1; - // These enums are derived from the standard and hence - // we can just use the values directly. - mseq->colour_primaries = avctx->color_primaries; - mseq->transfer_characteristics = avctx->color_trc; - mseq->matrix_coefficients = avctx->colorspace; + sps->vui.colour_description_present_flag = 1; + sps->vui.colour_primaries = avctx->color_primaries; + sps->vui.transfer_characteristics = avctx->color_trc; + sps->vui.matrix_coefficients = avctx->colorspace; } + } else { + sps->vui.video_format = 5; + sps->vui.video_full_range_flag = 0; + sps->vui.colour_primaries = avctx->color_primaries; + sps->vui.transfer_characteristics = avctx->color_trc; + sps->vui.matrix_coefficients = avctx->colorspace; + } - vseq->vui_fields.bits.bitstream_restriction_flag = 1; - mseq->motion_vectors_over_pic_boundaries_flag = 1; - mseq->max_bytes_per_pic_denom = 0; - mseq->max_bits_per_mb_denom = 0; - vseq->vui_fields.bits.log2_max_mv_length_horizontal = 16; - vseq->vui_fields.bits.log2_max_mv_length_vertical = 16; - - mseq->max_num_reorder_frames = (avctx->max_b_frames > 0); - mseq->max_dec_pic_buffering = vseq->max_num_ref_frames; - - vseq->bits_per_second = avctx->bit_rate; + if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) { + sps->vui.chroma_loc_info_present_flag = 1; + sps->vui.chroma_sample_loc_type_top_field = + sps->vui.chroma_sample_loc_type_bottom_field = + avctx->chroma_sample_location - 1; + } - vseq->vui_fields.bits.timing_info_present_flag = 1; - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { - vseq->num_units_in_tick = avctx->framerate.den; - vseq->time_scale = 2 * avctx->framerate.num; - mseq->fixed_frame_rate_flag = 1; - } else { - vseq->num_units_in_tick = avctx->time_base.num; - vseq->time_scale = 2 * avctx->time_base.den; - mseq->fixed_frame_rate_flag = 0; - } + sps->vui.timing_info_present_flag = 1; + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + sps->vui.num_units_in_tick = avctx->framerate.den; + sps->vui.time_scale = 2 * avctx->framerate.num; + sps->vui.fixed_frame_rate_flag = 1; + } else { + sps->vui.num_units_in_tick = avctx->time_base.num; + sps->vui.time_scale = 2 * avctx->time_base.den; + sps->vui.fixed_frame_rate_flag = 0; + } - if (ctx->va_rc_mode == VA_RC_CBR) { - priv->send_timing_sei = 1; - mseq->nal_hrd_parameters_present_flag = 1; + if (opt->sei & SEI_TIMING) { + H264RawHRD *hrd = &sps->vui.nal_hrd_parameters; - mseq->cpb_cnt_minus1 = 0; + sps->vui.nal_hrd_parameters_present_flag = 1; - // Try to scale these to a sensible range so that the - // golomb encode of the value is not overlong. - mseq->bit_rate_scale = - av_clip_uintp2(av_log2(avctx->bit_rate) - 15 - 6, 4); - mseq->bit_rate_value_minus1[0] = - (avctx->bit_rate >> mseq->bit_rate_scale + 6) - 1; + hrd->cpb_cnt_minus1 = 0; - mseq->cpb_size_scale = - av_clip_uintp2(av_log2(ctx->hrd_params.hrd.buffer_size) - 15 - 4, 4); - mseq->cpb_size_value_minus1[0] = - (ctx->hrd_params.hrd.buffer_size >> mseq->cpb_size_scale + 4) - 1; + // Try to scale these to a sensible range so that the + // golomb encode of the value is not overlong. + hrd->bit_rate_scale = + av_clip_uintp2(av_log2(avctx->bit_rate) - 15 - 6, 4); + hrd->bit_rate_value_minus1[0] = + (avctx->bit_rate >> hrd->bit_rate_scale + 6) - 1; - // CBR mode isn't actually available here, despite naming. - mseq->cbr_flag[0] = 0; + hrd->cpb_size_scale = + av_clip_uintp2(av_log2(ctx->hrd_params.hrd.buffer_size) - 15 - 4, 4); + hrd->cpb_size_value_minus1[0] = + (ctx->hrd_params.hrd.buffer_size >> hrd->cpb_size_scale + 4) - 1; - mseq->initial_cpb_removal_delay_length_minus1 = 23; - mseq->cpb_removal_delay_length_minus1 = 23; - mseq->dpb_output_delay_length_minus1 = 7; - mseq->time_offset_length = 0; + // CBR mode as defined for the HRD cannot be achieved without filler + // data, so this flag cannot be set even with VAAPI CBR modes. + hrd->cbr_flag[0] = 0; - // This calculation can easily overflow 32 bits. - mseq->initial_cpb_removal_delay = 90000 * - (uint64_t)ctx->hrd_params.hrd.initial_buffer_fullness / - ctx->hrd_params.hrd.buffer_size; + hrd->initial_cpb_removal_delay_length_minus1 = 23; + hrd->cpb_removal_delay_length_minus1 = 23; + hrd->dpb_output_delay_length_minus1 = 7; + hrd->time_offset_length = 0; - mseq->initial_cpb_removal_delay_offset = 0; - } else { - priv->send_timing_sei = 0; - mseq->nal_hrd_parameters_present_flag = 0; - } + priv->buffering_period.seq_parameter_set_id = sps->seq_parameter_set_id; - vseq->intra_period = avctx->gop_size; - vseq->intra_idr_period = avctx->gop_size; - vseq->ip_period = ctx->b_per_p + 1; + // This calculation can easily overflow 32 bits. + priv->buffering_period.nal.initial_cpb_removal_delay[0] = 90000 * + (uint64_t)ctx->hrd_params.hrd.initial_buffer_fullness / + ctx->hrd_params.hrd.buffer_size; + priv->buffering_period.nal.initial_cpb_removal_delay_offset[0] = 0; + } else { + sps->vui.nal_hrd_parameters_present_flag = 0; + sps->vui.low_delay_hrd_flag = 1 - sps->vui.fixed_frame_rate_flag; } - { - vpic->CurrPic.picture_id = VA_INVALID_ID; - vpic->CurrPic.flags = VA_PICTURE_H264_INVALID; - - for (i = 0; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) { - vpic->ReferenceFrames[i].picture_id = VA_INVALID_ID; - vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID; - } + sps->vui.bitstream_restriction_flag = 1; + sps->vui.motion_vectors_over_pic_boundaries_flag = 1; + sps->vui.log2_max_mv_length_horizontal = 16; + sps->vui.log2_max_mv_length_vertical = 16; + sps->vui.max_num_reorder_frames = (ctx->b_per_p > 0); + sps->vui.max_dec_frame_buffering = vseq->max_num_ref_frames; - vpic->coded_buf = VA_INVALID_ID; + pps->nal_unit_header.nal_ref_idc = 3; + pps->nal_unit_header.nal_unit_type = H264_NAL_PPS; - vpic->pic_parameter_set_id = 0; - vpic->seq_parameter_set_id = 0; + pps->pic_parameter_set_id = 0; + pps->seq_parameter_set_id = 0; - vpic->num_ref_idx_l0_active_minus1 = 0; - vpic->num_ref_idx_l1_active_minus1 = 0; + pps->entropy_coding_mode_flag = + !(sps->profile_idc == FF_PROFILE_H264_BASELINE || + sps->profile_idc == FF_PROFILE_H264_EXTENDED || + sps->profile_idc == FF_PROFILE_H264_CAVLC_444); + if (!opt->coder && pps->entropy_coding_mode_flag) + pps->entropy_coding_mode_flag = 0; - vpic->pic_fields.bits.entropy_coding_mode_flag = - opt->coder ? ((avctx->profile & 0xff) != 66) : 0; - vpic->pic_fields.bits.weighted_pred_flag = 0; - vpic->pic_fields.bits.weighted_bipred_idc = 0; - vpic->pic_fields.bits.transform_8x8_mode_flag = - ((avctx->profile & 0xff) >= 100); + pps->num_ref_idx_l0_default_active_minus1 = 0; + pps->num_ref_idx_l1_default_active_minus1 = 0; - vpic->pic_init_qp = priv->fixed_qp_idr; - } + pps->pic_init_qp_minus26 = priv->fixed_qp_idr - 26; - { - mseq->profile_idc = avctx->profile & 0xff; + if (sps->profile_idc == FF_PROFILE_H264_BASELINE || + sps->profile_idc == FF_PROFILE_H264_EXTENDED || + sps->profile_idc == FF_PROFILE_H264_MAIN) { + pps->more_rbsp_data = 0; + } else { + pps->more_rbsp_data = 1; + + pps->transform_8x8_mode_flag = 1; + } + + *vseq = (VAEncSequenceParameterBufferH264) { + .seq_parameter_set_id = sps->seq_parameter_set_id, + .level_idc = sps->level_idc, + .intra_period = avctx->gop_size, + .intra_idr_period = avctx->gop_size, + .ip_period = ctx->b_per_p + 1, + + .bits_per_second = avctx->bit_rate, + .max_num_ref_frames = sps->max_num_ref_frames, + .picture_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1, + .picture_height_in_mbs = sps->pic_height_in_map_units_minus1 + 1, + + .seq_fields.bits = { + .chroma_format_idc = sps->chroma_format_idc, + .frame_mbs_only_flag = sps->frame_mbs_only_flag, + .mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag, + .seq_scaling_matrix_present_flag = sps->seq_scaling_matrix_present_flag, + .direct_8x8_inference_flag = sps->direct_8x8_inference_flag, + .log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4, + .pic_order_cnt_type = sps->pic_order_cnt_type, + .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4, + .delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag, + }, + + .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8, + .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8, + + .frame_cropping_flag = sps->frame_cropping_flag, + .frame_crop_left_offset = sps->frame_crop_left_offset, + .frame_crop_right_offset = sps->frame_crop_right_offset, + .frame_crop_top_offset = sps->frame_crop_top_offset, + .frame_crop_bottom_offset = sps->frame_crop_bottom_offset, + + .vui_parameters_present_flag = sps->vui_parameters_present_flag, + + .vui_fields.bits = { + .aspect_ratio_info_present_flag = sps->vui.aspect_ratio_info_present_flag, + .timing_info_present_flag = sps->vui.timing_info_present_flag, + .bitstream_restriction_flag = sps->vui.bitstream_restriction_flag, + .log2_max_mv_length_horizontal = sps->vui.log2_max_mv_length_horizontal, + .log2_max_mv_length_vertical = sps->vui.log2_max_mv_length_vertical, + }, + + .aspect_ratio_idc = sps->vui.aspect_ratio_idc, + .sar_width = sps->vui.sar_width, + .sar_height = sps->vui.sar_height, + .num_units_in_tick = sps->vui.num_units_in_tick, + .time_scale = sps->vui.time_scale, + }; - if (avctx->profile & FF_PROFILE_H264_CONSTRAINED) - mseq->constraint_set1_flag = 1; - if (avctx->profile & FF_PROFILE_H264_INTRA) - mseq->constraint_set3_flag = 1; - } + *vpic = (VAEncPictureParameterBufferH264) { + .CurrPic = { + .picture_id = VA_INVALID_ID, + .flags = VA_PICTURE_H264_INVALID, + }, + + .coded_buf = VA_INVALID_ID, + + .pic_parameter_set_id = pps->pic_parameter_set_id, + .seq_parameter_set_id = pps->seq_parameter_set_id, + + .pic_init_qp = pps->pic_init_qp_minus26 + 26, + .num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1, + .num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1, + + .chroma_qp_index_offset = pps->chroma_qp_index_offset, + .second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset, + + .pic_fields.bits = { + .entropy_coding_mode_flag = pps->entropy_coding_mode_flag, + .weighted_pred_flag = pps->weighted_pred_flag, + .weighted_bipred_idc = pps->weighted_bipred_idc, + .constrained_intra_pred_flag = pps->constrained_intra_pred_flag, + .transform_8x8_mode_flag = pps->transform_8x8_mode_flag, + .deblocking_filter_control_present_flag = + pps->deblocking_filter_control_present_flag, + .redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag, + .pic_order_present_flag = + pps->bottom_field_pic_order_in_frame_present_flag, + .pic_scaling_matrix_present_flag = pps->pic_scaling_matrix_present_flag, + }, + }; return 0; } @@ -948,54 +529,99 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, VAAPIEncodePicture *pic) { - VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodeH264Options *opt = ctx->codec_options; + H264RawSPS *sps = &priv->sps; + VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; int i; + memset(&priv->current_access_unit, 0, + sizeof(priv->current_access_unit)); + if (pic->type == PICTURE_TYPE_IDR) { av_assert0(pic->display_order == pic->encode_order); - vpic->frame_num = 0; + priv->frame_num = 0; priv->next_frame_num = 1; - priv->cpb_delay = 0; + priv->cpb_delay = 0; priv->last_idr_frame = pic->display_order; + ++priv->idr_pic_count; + + priv->slice_type = 7; + priv->primary_pic_type = 0; } else { - vpic->frame_num = priv->next_frame_num; + priv->frame_num = priv->next_frame_num; + if (pic->type != PICTURE_TYPE_B) { - // nal_ref_idc != 0 - ++priv->next_frame_num; + // Reference picture, so frame_num advances. + priv->next_frame_num = (priv->frame_num + 1) & + ((1 << (4 + sps->log2_max_frame_num_minus4)) - 1); } ++priv->cpb_delay; + + if (pic->type == PICTURE_TYPE_I) { + priv->slice_type = 7; + priv->primary_pic_type = 0; + } else if (pic->type == PICTURE_TYPE_P) { + priv->slice_type = 5; + priv->primary_pic_type = 1; + } else { + priv->slice_type = 6; + priv->primary_pic_type = 2; + } } - priv->dpb_delay = pic->display_order - pic->encode_order + 1; + priv->pic_order_cnt = pic->display_order - priv->last_idr_frame; + priv->dpb_delay = pic->display_order - pic->encode_order + 1; - vpic->frame_num = vpic->frame_num & - ((1 << (4 + vseq->seq_fields.bits.log2_max_frame_num_minus4)) - 1); + if (opt->sei & SEI_IDENTIFIER && pic->encode_order == 0) + priv->sei_needed = 1; + + if (opt->sei & SEI_TIMING) { + memset(&priv->pic_timing, 0, sizeof(priv->pic_timing)); + + priv->pic_timing.cpb_removal_delay = + 2 * sps->vui.num_units_in_tick * priv->cpb_delay; + priv->pic_timing.dpb_output_delay = + 2 * sps->vui.num_units_in_tick * priv->dpb_delay; + + priv->sei_needed = 1; + } - vpic->CurrPic.picture_id = pic->recon_surface; - vpic->CurrPic.frame_idx = vpic->frame_num; - vpic->CurrPic.flags = 0; - vpic->CurrPic.TopFieldOrderCnt = pic->display_order - priv->last_idr_frame; - vpic->CurrPic.BottomFieldOrderCnt = pic->display_order - priv->last_idr_frame; + vpic->CurrPic = (VAPictureH264) { + .picture_id = pic->recon_surface, + .frame_idx = priv->frame_num, + .flags = 0, + .TopFieldOrderCnt = priv->pic_order_cnt, + .BottomFieldOrderCnt = priv->pic_order_cnt, + }; for (i = 0; i < pic->nb_refs; i++) { VAAPIEncodePicture *ref = pic->refs[i]; + unsigned int frame_num = (ref->encode_order - priv->last_idr_frame) & + ((1 << (4 + sps->log2_max_frame_num_minus4)) - 1); + unsigned int pic_order_cnt = ref->display_order - priv->last_idr_frame; + av_assert0(ref && ref->encode_order < pic->encode_order); - vpic->ReferenceFrames[i].picture_id = ref->recon_surface; - vpic->ReferenceFrames[i].frame_idx = ref->encode_order; - vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE; - vpic->ReferenceFrames[i].TopFieldOrderCnt = ref->display_order - priv->last_idr_frame; - vpic->ReferenceFrames[i].BottomFieldOrderCnt = ref->display_order - priv->last_idr_frame; + vpic->ReferenceFrames[i] = (VAPictureH264) { + .picture_id = ref->recon_surface, + .frame_idx = frame_num, + .flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE, + .TopFieldOrderCnt = pic_order_cnt, + .BottomFieldOrderCnt = pic_order_cnt, + }; } for (; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) { - vpic->ReferenceFrames[i].picture_id = VA_INVALID_ID; - vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID; + vpic->ReferenceFrames[i] = (VAPictureH264) { + .picture_id = VA_INVALID_ID, + .flags = VA_PICTURE_H264_INVALID, + }; } vpic->coded_buf = pic->output_buffer; - vpic->pic_fields.bits.idr_pic_flag = (pic->type == PICTURE_TYPE_IDR); + vpic->frame_num = priv->frame_num; + + vpic->pic_fields.bits.idr_pic_flag = (pic->type == PICTURE_TYPE_IDR); vpic->pic_fields.bits.reference_pic_flag = (pic->type != PICTURE_TYPE_B); pic->nb_slices = 1; @@ -1007,58 +633,57 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx, VAAPIEncodePicture *pic, VAAPIEncodeSlice *slice) { - VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; - VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params; - VAAPIEncodeH264Context *priv = ctx->priv_data; - VAAPIEncodeH264Slice *pslice; - VAAPIEncodeH264MiscSliceParams *mslice; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + H264RawSPS *sps = &priv->sps; + H264RawPPS *pps = &priv->pps; + H264RawSliceHeader *sh = &priv->slice.header; + VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params; + VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params; int i; - slice->priv_data = av_mallocz(sizeof(*pslice)); - if (!slice->priv_data) - return AVERROR(ENOMEM); - pslice = slice->priv_data; - mslice = &pslice->misc_slice_params; + if (pic->type == PICTURE_TYPE_IDR) { + sh->nal_unit_header.nal_unit_type = H264_NAL_IDR_SLICE; + sh->nal_unit_header.nal_ref_idc = 3; + } else { + sh->nal_unit_header.nal_unit_type = H264_NAL_SLICE; + sh->nal_unit_header.nal_ref_idc = pic->type != PICTURE_TYPE_B; + } + + // Only one slice per frame. + sh->first_mb_in_slice = 0; + sh->slice_type = priv->slice_type; + + sh->pic_parameter_set_id = pps->pic_parameter_set_id; - if (pic->type == PICTURE_TYPE_IDR) - mslice->nal_unit_type = H264_NAL_IDR_SLICE; + sh->frame_num = priv->frame_num; + sh->idr_pic_id = priv->idr_pic_count; + + sh->pic_order_cnt_lsb = priv->pic_order_cnt & + ((1 << (4 + sps->log2_max_pic_order_cnt_lsb_minus4)) - 1); + + sh->direct_spatial_mv_pred_flag = 1; + + if (pic->type == PICTURE_TYPE_B) + sh->slice_qp_delta = priv->fixed_qp_b - (pps->pic_init_qp_minus26 + 26); + else if (pic->type == PICTURE_TYPE_P) + sh->slice_qp_delta = priv->fixed_qp_p - (pps->pic_init_qp_minus26 + 26); else - mslice->nal_unit_type = H264_NAL_SLICE; + sh->slice_qp_delta = priv->fixed_qp_idr - (pps->pic_init_qp_minus26 + 26); - switch (pic->type) { - case PICTURE_TYPE_IDR: - vslice->slice_type = SLICE_TYPE_I; - mslice->nal_ref_idc = 3; - break; - case PICTURE_TYPE_I: - vslice->slice_type = SLICE_TYPE_I; - mslice->nal_ref_idc = 2; - break; - case PICTURE_TYPE_P: - vslice->slice_type = SLICE_TYPE_P; - mslice->nal_ref_idc = 1; - break; - case PICTURE_TYPE_B: - vslice->slice_type = SLICE_TYPE_B; - mslice->nal_ref_idc = 0; - break; - default: - av_assert0(0 && "invalid picture type"); - } - // Only one slice per frame. - vslice->macroblock_address = 0; - vslice->num_macroblocks = priv->mb_width * priv->mb_height; + vslice->macroblock_address = sh->first_mb_in_slice; + vslice->num_macroblocks = priv->mb_width * priv->mb_height; vslice->macroblock_info = VA_INVALID_ID; - vslice->pic_parameter_set_id = vpic->pic_parameter_set_id; - vslice->idr_pic_id = priv->idr_pic_count++; + vslice->slice_type = sh->slice_type % 5; + vslice->pic_parameter_set_id = sh->pic_parameter_set_id; + vslice->idr_pic_id = sh->idr_pic_id; + + vslice->pic_order_cnt_lsb = sh->pic_order_cnt_lsb; - vslice->pic_order_cnt_lsb = (pic->display_order - priv->last_idr_frame) & - ((1 << (4 + vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4)) - 1); + vslice->direct_spatial_mv_pred_flag = sh->direct_spatial_mv_pred_flag; for (i = 0; i < FF_ARRAY_ELEMS(vslice->RefPicList0); i++) { vslice->RefPicList0[i].picture_id = VA_INVALID_ID; @@ -1072,26 +697,15 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx, // Backward reference for P- or B-frame. av_assert0(pic->type == PICTURE_TYPE_P || pic->type == PICTURE_TYPE_B); - - vslice->num_ref_idx_l0_active_minus1 = 0; vslice->RefPicList0[0] = vpic->ReferenceFrames[0]; } if (pic->nb_refs >= 2) { // Forward reference for B-frame. av_assert0(pic->type == PICTURE_TYPE_B); - - vslice->num_ref_idx_l1_active_minus1 = 0; vslice->RefPicList1[0] = vpic->ReferenceFrames[1]; } - if (pic->type == PICTURE_TYPE_B) - vslice->slice_qp_delta = priv->fixed_qp_b - vpic->pic_init_qp; - else if (pic->type == PICTURE_TYPE_P) - vslice->slice_qp_delta = priv->fixed_qp_p - vpic->pic_init_qp; - else - vslice->slice_qp_delta = priv->fixed_qp_idr - vpic->pic_init_qp; - - vslice->direct_spatial_mv_pred_flag = 1; + vslice->slice_qp_delta = sh->slice_qp_delta; return 0; } @@ -1101,6 +715,11 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx) VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH264Context *priv = ctx->priv_data; VAAPIEncodeH264Options *opt = ctx->codec_options; + int err; + + err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_H264, avctx); + if (err < 0) + return err; priv->mb_width = FFALIGN(avctx->width, 16) / 16; priv->mb_height = FFALIGN(avctx->height, 16) / 16; @@ -1118,6 +737,8 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx) else priv->fixed_qp_b = priv->fixed_qp_p; + opt->sei &= ~SEI_TIMING; + av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = " "%d / %d / %d for IDR- / P- / B-frames.\n", priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b); @@ -1140,6 +761,34 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx) if (avctx->compression_level == FF_COMPRESSION_DEFAULT) avctx->compression_level = opt->quality; + if (opt->sei & SEI_IDENTIFIER) { + const char *lavc = LIBAVCODEC_IDENT; + const char *vaapi = VA_VERSION_S; + const char *driver; + int len; + + memcpy(priv->identifier.uuid_iso_iec_11578, + vaapi_encode_h264_sei_identifier_uuid, + sizeof(priv->identifier.uuid_iso_iec_11578)); + + driver = vaQueryVendorString(ctx->hwctx->display); + if (!driver) + driver = "unknown driver"; + + len = snprintf(NULL, 0, "%s / VAAPI %s / %s", lavc, vaapi, driver); + if (len >= 0) { + priv->identifier_string = av_malloc(len + 1); + if (!priv->identifier_string) + return AVERROR(ENOMEM); + + snprintf(priv->identifier_string, len + 1, + "%s / VAAPI %s / %s", lavc, vaapi, driver); + + priv->identifier.data = priv->identifier_string; + priv->identifier.data_length = len + 1; + } + } + return 0; } @@ -1251,6 +900,19 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx) return ff_vaapi_encode_init(avctx); } +static av_cold int vaapi_encode_h264_close(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + + if (priv) { + ff_cbs_close(&priv->cbc); + av_freep(&priv->identifier_string); + } + + return ff_vaapi_encode_close(avctx); +} + #define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \ offsetof(VAAPIEncodeH264Options, x)) #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) @@ -1268,6 +930,17 @@ static const AVOption vaapi_encode_h264_options[] = { { "cabac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, FLAGS, "coder" }, { "vlc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS, "coder" }, { "ac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, FLAGS, "coder" }, + + { "sei", "Set SEI to include", + OFFSET(sei), AV_OPT_TYPE_FLAGS, + { .i64 = SEI_IDENTIFIER | SEI_TIMING }, + 0, INT_MAX, FLAGS, "sei" }, + { "identifier", "Include encoder version identifier", + 0, AV_OPT_TYPE_CONST, { .i64 = SEI_IDENTIFIER }, + INT_MIN, INT_MAX, FLAGS, "sei" }, + { "timing", "Include timing parameters (buffering_period and pic_timing)", + 0, AV_OPT_TYPE_CONST, { .i64 = SEI_TIMING }, + INT_MIN, INT_MAX, FLAGS, "sei" }, { NULL }, }; @@ -1301,7 +974,7 @@ AVCodec ff_h264_vaapi_encoder = { sizeof(VAAPIEncodeH264Options)), .init = &vaapi_encode_h264_init, .encode2 = &ff_vaapi_encode2, - .close = &ff_vaapi_encode_close, + .close = &vaapi_encode_h264_close, .priv_class = &vaapi_encode_h264_class, .capabilities = AV_CODEC_CAP_DELAY, .defaults = vaapi_encode_h264_defaults, From 281b68b0265953ab2623a39484d927a0e921c405 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 7 May 2017 22:58:56 +0100 Subject: [PATCH 0511/2557] vaapi_h264: Add support for AUD NAL units Adds a new private option to enable them (off by default). (cherry picked from commit 820a4483af13cf6fd51f13638e57bcd1c3f629d4) --- libavcodec/vaapi_encode_h264.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 9a8019aa7b41d..b147457b7573e 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -53,6 +53,7 @@ typedef struct VAAPIEncodeH264Context { int fixed_qp_p; int fixed_qp_b; + H264RawAUD aud; H264RawSPS sps; H264RawPPS pps; H264RawSEI sei; @@ -77,6 +78,7 @@ typedef struct VAAPIEncodeH264Context { CodedBitstreamContext *cbc; CodedBitstreamFragment current_access_unit; + int aud_needed; int sei_needed; } VAAPIEncodeH264Context; @@ -86,6 +88,7 @@ typedef struct VAAPIEncodeH264Options { int low_power; // Entropy encoder type. int coder; + int aud; int sei; } VAAPIEncodeH264Options; @@ -145,6 +148,13 @@ static int vaapi_encode_h264_write_sequence_header(AVCodecContext *avctx, CodedBitstreamFragment *au = &priv->current_access_unit; int err; + if (priv->aud_needed) { + err = vaapi_encode_h264_add_nal(avctx, au, &priv->aud); + if (err < 0) + goto fail; + priv->aud_needed = 0; + } + err = vaapi_encode_h264_add_nal(avctx, au, &priv->sps); if (err < 0) goto fail; @@ -169,6 +179,13 @@ static int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx, CodedBitstreamFragment *au = &priv->current_access_unit; int err; + if (priv->aud_needed) { + err = vaapi_encode_h264_add_nal(avctx, au, &priv->aud); + if (err < 0) + goto fail; + priv->aud_needed = 0; + } + err = vaapi_encode_h264_add_nal(avctx, au, &priv->slice); if (err < 0) goto fail; @@ -191,6 +208,11 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, int err, i; if (priv->sei_needed) { + if (priv->aud_needed) { + vaapi_encode_h264_add_nal(avctx, au, &priv->aud); + priv->aud_needed = 0; + } + memset(&priv->sei, 0, sizeof(priv->sei)); priv->sei.nal_unit_header.nal_unit_type = H264_NAL_SEI; @@ -573,6 +595,14 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, priv->pic_order_cnt = pic->display_order - priv->last_idr_frame; priv->dpb_delay = pic->display_order - pic->encode_order + 1; + if (opt->aud) { + priv->aud_needed = 1; + priv->aud.nal_unit_header.nal_unit_type = H264_NAL_AUD; + priv->aud.primary_pic_type = priv->primary_pic_type; + } else { + priv->aud_needed = 0; + } + if (opt->sei & SEI_IDENTIFIER && pic->encode_order == 0) priv->sei_needed = 1; @@ -931,6 +961,9 @@ static const AVOption vaapi_encode_h264_options[] = { { "vlc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS, "coder" }, { "ac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, FLAGS, "coder" }, + { "aud", "Include AUD", + OFFSET(aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, + { "sei", "Set SEI to include", OFFSET(sei), AV_OPT_TYPE_FLAGS, { .i64 = SEI_IDENTIFIER | SEI_TIMING }, From 0bc7575ced65bf4aa4678ac12d550aaf87890d0e Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 7 May 2017 23:02:09 +0100 Subject: [PATCH 0512/2557] vaapi_h264: Add support for SEI recovery points Included by default with non-IDR intra frames. (cherry picked from commit a49ee60d5fdbdae1706a44cfbb814abb9793815f) --- libavcodec/vaapi_encode_h264.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index b147457b7573e..201e94a8ce2f8 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -37,6 +37,7 @@ enum { SEI_TIMING = 0x01, SEI_IDENTIFIER = 0x02, + SEI_RECOVERY_POINT = 0x04, }; // Random (version 4) ISO 11578 UUID. @@ -61,6 +62,7 @@ typedef struct VAAPIEncodeH264Context { H264RawSEIBufferingPeriod buffering_period; H264RawSEIPicTiming pic_timing; + H264RawSEIRecoveryPoint recovery_point; H264RawSEIUserDataUnregistered identifier; char *identifier_string; @@ -232,6 +234,11 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, priv->sei.payload[i].payload.pic_timing = priv->pic_timing; ++i; } + if (opt->sei & SEI_RECOVERY_POINT && pic->type == PICTURE_TYPE_I) { + priv->sei.payload[i].payload_type = H264_SEI_TYPE_RECOVERY_POINT; + priv->sei.payload[i].payload.recovery_point = priv->recovery_point; + ++i; + } priv->sei.payload_count = i; av_assert0(priv->sei.payload_count > 0); @@ -617,6 +624,14 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, priv->sei_needed = 1; } + if (opt->sei & SEI_RECOVERY_POINT && pic->type == PICTURE_TYPE_I) { + priv->recovery_point.recovery_frame_cnt = 0; + priv->recovery_point.exact_match_flag = 1; + priv->recovery_point.broken_link_flag = ctx->b_per_p > 0; + + priv->sei_needed = 1; + } + vpic->CurrPic = (VAPictureH264) { .picture_id = pic->recon_surface, .frame_idx = priv->frame_num, @@ -966,7 +981,7 @@ static const AVOption vaapi_encode_h264_options[] = { { "sei", "Set SEI to include", OFFSET(sei), AV_OPT_TYPE_FLAGS, - { .i64 = SEI_IDENTIFIER | SEI_TIMING }, + { .i64 = SEI_IDENTIFIER | SEI_TIMING | SEI_RECOVERY_POINT }, 0, INT_MAX, FLAGS, "sei" }, { "identifier", "Include encoder version identifier", 0, AV_OPT_TYPE_CONST, { .i64 = SEI_IDENTIFIER }, @@ -974,6 +989,9 @@ static const AVOption vaapi_encode_h264_options[] = { { "timing", "Include timing parameters (buffering_period and pic_timing)", 0, AV_OPT_TYPE_CONST, { .i64 = SEI_TIMING }, INT_MIN, INT_MAX, FLAGS, "sei" }, + { "recovery_point", "Include recovery points where appropriate", + 0, AV_OPT_TYPE_CONST, { .i64 = SEI_RECOVERY_POINT }, + INT_MIN, INT_MAX, FLAGS, "sei" }, { NULL }, }; From 94a4048619665e99a19d9e2961254dc9b5c736a7 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 9 Sep 2017 22:49:14 +0100 Subject: [PATCH 0513/2557] vaapi_h264: Fix CPB/DPB delays This should be ticks, not time_scale steps - it was wrong for all framerates not a multiple of 1/2. (cherry picked from commit 30645174e333c7db1946ab09be769db9be9d7481) --- libavcodec/vaapi_encode_h264.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 201e94a8ce2f8..46950772a95f5 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -616,10 +616,8 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, if (opt->sei & SEI_TIMING) { memset(&priv->pic_timing, 0, sizeof(priv->pic_timing)); - priv->pic_timing.cpb_removal_delay = - 2 * sps->vui.num_units_in_tick * priv->cpb_delay; - priv->pic_timing.dpb_output_delay = - 2 * sps->vui.num_units_in_tick * priv->dpb_delay; + priv->pic_timing.cpb_removal_delay = 2 * priv->cpb_delay; + priv->pic_timing.dpb_output_delay = 2 * priv->dpb_delay; priv->sei_needed = 1; } From 00179664bccd1dd6fa0d1c40db453528757bf6f7 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 14 May 2017 21:36:24 +0100 Subject: [PATCH 0514/2557] vaapi_h265: Convert to use coded bitstream infrastructure Also improves the metadata and generally makes the configuration a bit cleaner. (cherry picked from commit ac12486714b48f9bd5d9167f90b77c936751d6ef) --- configure | 2 +- libavcodec/Makefile | 2 +- libavcodec/vaapi_encode_h265.c | 1536 ++++++++++++-------------------- libavcodec/vaapi_encode_h26x.c | 68 -- libavcodec/vaapi_encode_h26x.h | 45 - 5 files changed, 585 insertions(+), 1068 deletions(-) delete mode 100644 libavcodec/vaapi_encode_h26x.c delete mode 100644 libavcodec/vaapi_encode_h26x.h diff --git a/configure b/configure index d11a95a04f7d8..7e244eea4dba3 100755 --- a/configure +++ b/configure @@ -2845,7 +2845,7 @@ hevc_qsv_encoder_select="hevcparse qsvenc" hevc_rkmpp_decoder_deps="rkmpp" hevc_rkmpp_decoder_select="hevc_mp4toannexb_bsf" hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" -hevc_vaapi_encoder_select="vaapi_encode golomb" +hevc_vaapi_encoder_select="cbs_h265 vaapi_encode" hevc_v4l2m2m_decoder_deps="v4l2_m2m hevc_v4l2_m2m" hevc_v4l2m2m_encoder_deps="v4l2_m2m hevc_v4l2_m2m" mjpeg_cuvid_decoder_deps="cuda cuvid" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 7b6fcd7aa2519..b52e5ada7ab58 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -363,7 +363,7 @@ OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec_h2645.o OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \ hevc_data.o OBJS-$(CONFIG_HEVC_RKMPP_DECODER) += rkmppdec.o -OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o vaapi_encode_h26x.o +OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_HEVC_V4L2M2M_ENCODER) += v4l2_m2m_enc.o OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 971458db8759f..4edd53a73c0e0 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -16,163 +16,25 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include #include #include "libavutil/avassert.h" -#include "libavutil/internal.h" +#include "libavutil/common.h" #include "libavutil/opt.h" -#include "libavutil/pixfmt.h" #include "avcodec.h" +#include "cbs.h" +#include "cbs_h265.h" #include "hevc.h" #include "internal.h" #include "put_bits.h" #include "vaapi_encode.h" -#include "vaapi_encode_h26x.h" - - -#define MAX_ST_REF_PIC_SETS 32 -#define MAX_DPB_PICS 16 -#define MAX_LAYERS 1 - - -typedef struct VAAPIEncodeH265STRPS { - char inter_ref_pic_set_prediction_flag; - - unsigned int num_negative_pics; - unsigned int num_positive_pics; - - unsigned int delta_poc_s0_minus1[MAX_DPB_PICS]; - char used_by_curr_pic_s0_flag[MAX_DPB_PICS]; - - unsigned int delta_poc_s1_minus1[MAX_DPB_PICS]; - char used_by_curr_pic_s1_flag[MAX_DPB_PICS]; -} VAAPIEncodeH265STRPS; - -// This structure contains all possibly-useful per-sequence syntax elements -// which are not already contained in the various VAAPI structures. -typedef struct VAAPIEncodeH265MiscSequenceParams { - - // Parameter set IDs. - unsigned int video_parameter_set_id; - unsigned int seq_parameter_set_id; - - // Layering. - unsigned int vps_max_layers_minus1; - unsigned int vps_max_sub_layers_minus1; - char vps_temporal_id_nesting_flag; - unsigned int vps_max_layer_id; - unsigned int vps_num_layer_sets_minus1; - unsigned int sps_max_sub_layers_minus1; - char sps_temporal_id_nesting_flag; - char layer_id_included_flag[MAX_LAYERS][64]; - - // Profile/tier/level parameters. - char general_profile_compatibility_flag[32]; - char general_progressive_source_flag; - char general_interlaced_source_flag; - char general_non_packed_constraint_flag; - char general_frame_only_constraint_flag; - char general_inbld_flag; - - // Decode/display ordering parameters. - unsigned int log2_max_pic_order_cnt_lsb_minus4; - char vps_sub_layer_ordering_info_present_flag; - unsigned int vps_max_dec_pic_buffering_minus1[MAX_LAYERS]; - unsigned int vps_max_num_reorder_pics[MAX_LAYERS]; - unsigned int vps_max_latency_increase_plus1[MAX_LAYERS]; - char sps_sub_layer_ordering_info_present_flag; - unsigned int sps_max_dec_pic_buffering_minus1[MAX_LAYERS]; - unsigned int sps_max_num_reorder_pics[MAX_LAYERS]; - unsigned int sps_max_latency_increase_plus1[MAX_LAYERS]; - - // Timing information. - char vps_timing_info_present_flag; - unsigned int vps_num_units_in_tick; - unsigned int vps_time_scale; - char vps_poc_proportional_to_timing_flag; - unsigned int vps_num_ticks_poc_diff_minus1; - - // Cropping information. - char conformance_window_flag; - unsigned int conf_win_left_offset; - unsigned int conf_win_right_offset; - unsigned int conf_win_top_offset; - unsigned int conf_win_bottom_offset; - - // Short-term reference picture sets. - unsigned int num_short_term_ref_pic_sets; - VAAPIEncodeH265STRPS st_ref_pic_set[MAX_ST_REF_PIC_SETS]; - - // Long-term reference pictures. - char long_term_ref_pics_present_flag; - unsigned int num_long_term_ref_pics_sps; - struct { - unsigned int lt_ref_pic_poc_lsb_sps; - char used_by_curr_pic_lt_sps_flag; - } lt_ref_pic; - - // Deblocking filter control. - char deblocking_filter_control_present_flag; - char deblocking_filter_override_enabled_flag; - char pps_deblocking_filter_disabled_flag; - int pps_beta_offset_div2; - int pps_tc_offset_div2; - - // Video Usability Information. - char vui_parameters_present_flag; - char aspect_ratio_info_present_flag; - unsigned int aspect_ratio_idc; - unsigned int sar_width; - unsigned int sar_height; - char video_signal_type_present_flag; - unsigned int video_format; - char video_full_range_flag; - char colour_description_present_flag; - unsigned int colour_primaries; - unsigned int transfer_characteristics; - unsigned int matrix_coeffs; - - // Oddments. - char uniform_spacing_flag; - char output_flag_present_flag; - char cabac_init_present_flag; - unsigned int num_extra_slice_header_bits; - char lists_modification_present_flag; - char pps_slice_chroma_qp_offsets_present_flag; - char pps_slice_chroma_offset_list_enabled_flag; -} VAAPIEncodeH265MiscSequenceParams; - -// This structure contains all possibly-useful per-slice syntax elements -// which are not already contained in the various VAAPI structures. -typedef struct VAAPIEncodeH265MiscSliceParams { - // Slice segments. - char first_slice_segment_in_pic_flag; - - // Short-term reference picture sets. - char short_term_ref_pic_set_sps_flag; - unsigned int short_term_ref_pic_idx; - VAAPIEncodeH265STRPS st_ref_pic_set; - - // Deblocking filter. - char deblocking_filter_override_flag; - - // Oddments. - char slice_reserved_flag[8]; - char no_output_of_prior_pics_flag; - char pic_output_flag; -} VAAPIEncodeH265MiscSliceParams; - -typedef struct VAAPIEncodeH265Slice { - VAAPIEncodeH265MiscSliceParams misc_slice_params; - - int64_t pic_order_cnt; -} VAAPIEncodeH265Slice; -typedef struct VAAPIEncodeH265Context { - VAAPIEncodeH265MiscSequenceParams misc_sequence_params; +typedef struct VAAPIEncodeH265Context { unsigned int ctu_width; unsigned int ctu_height; @@ -180,17 +42,19 @@ typedef struct VAAPIEncodeH265Context { int fixed_qp_p; int fixed_qp_b; + H265RawVPS vps; + H265RawSPS sps; + H265RawPPS pps; + H265RawSlice slice; + int64_t last_idr_frame; + int pic_order_cnt; - // Rate control configuration. - struct { - VAEncMiscParameterBuffer misc; - VAEncMiscParameterRateControl rc; - } rc_params; - struct { - VAEncMiscParameterBuffer misc; - VAEncMiscParameterHRD hrd; - } hrd_params; + int slice_nal_unit; + int slice_type; + + CodedBitstreamContext *cbc; + CodedBitstreamFragment current_access_unit; } VAAPIEncodeH265Context; typedef struct VAAPIEncodeH265Options { @@ -198,564 +62,77 @@ typedef struct VAAPIEncodeH265Options { } VAAPIEncodeH265Options; -#define vseq_var(name) vseq->name, name -#define vseq_field(name) vseq->seq_fields.bits.name, name -#define vpic_var(name) vpic->name, name -#define vpic_field(name) vpic->pic_fields.bits.name, name -#define vslice_var(name) vslice->name, name -#define vslice_field(name) vslice->slice_fields.bits.name, name -#define mseq_var(name) mseq->name, name -#define mslice_var(name) mslice->name, name -#define mstrps_var(name) mstrps->name, name - -static void vaapi_encode_h265_write_nal_unit_header(PutBitContext *pbc, - int nal_unit_type) -{ - u(1, 0, forbidden_zero_bit); - u(6, nal_unit_type, nal_unit_type); - u(6, 0, nuh_layer_id); - u(3, 1, nuh_temporal_id_plus1); -} - -static void vaapi_encode_h265_write_rbsp_trailing_bits(PutBitContext *pbc) -{ - u(1, 1, rbsp_stop_one_bit); - while (put_bits_count(pbc) & 7) - u(1, 0, rbsp_alignment_zero_bit); -} - -static void vaapi_encode_h265_write_profile_tier_level(PutBitContext *pbc, - VAAPIEncodeContext *ctx) -{ - VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; - int j; - - if (1) { - u(2, 0, general_profile_space); - u(1, vseq_var(general_tier_flag)); - u(5, vseq_var(general_profile_idc)); - - for (j = 0; j < 32; j++) { - u(1, mseq_var(general_profile_compatibility_flag[j])); - } - - u(1, mseq_var(general_progressive_source_flag)); - u(1, mseq_var(general_interlaced_source_flag)); - u(1, mseq_var(general_non_packed_constraint_flag)); - u(1, mseq_var(general_frame_only_constraint_flag)); - - if (0) { - // Not main profile. - // Lots of extra constraint flags. - } else { - // put_bits only handles up to 31 bits. - u(23, 0, general_reserved_zero_43bits); - u(20, 0, general_reserved_zero_43bits); - } - - if (vseq->general_profile_idc >= 1 && vseq->general_profile_idc <= 5) { - u(1, mseq_var(general_inbld_flag)); - } else { - u(1, 0, general_reserved_zero_bit); - } - } - - u(8, vseq_var(general_level_idc)); - - // No sublayers. -} - -static void vaapi_encode_h265_write_vps(PutBitContext *pbc, - VAAPIEncodeContext *ctx) -{ - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; - int i, j; - - vaapi_encode_h265_write_nal_unit_header(pbc, HEVC_NAL_VPS); - - u(4, mseq->video_parameter_set_id, vps_video_parameter_set_id); - - u(1, 1, vps_base_layer_internal_flag); - u(1, 1, vps_base_layer_available_flag); - u(6, mseq_var(vps_max_layers_minus1)); - u(3, mseq_var(vps_max_sub_layers_minus1)); - u(1, mseq_var(vps_temporal_id_nesting_flag)); - - u(16, 0xffff, vps_reserved_0xffff_16bits); - - vaapi_encode_h265_write_profile_tier_level(pbc, ctx); - - u(1, mseq_var(vps_sub_layer_ordering_info_present_flag)); - for (i = (mseq->vps_sub_layer_ordering_info_present_flag ? - 0 : mseq->vps_max_sub_layers_minus1); - i <= mseq->vps_max_sub_layers_minus1; i++) { - ue(mseq_var(vps_max_dec_pic_buffering_minus1[i])); - ue(mseq_var(vps_max_num_reorder_pics[i])); - ue(mseq_var(vps_max_latency_increase_plus1[i])); - } - - u(6, mseq_var(vps_max_layer_id)); - ue(mseq_var(vps_num_layer_sets_minus1)); - for (i = 1; i <= mseq->vps_num_layer_sets_minus1; i++) { - for (j = 0; j < mseq->vps_max_layer_id; j++) - u(1, mseq_var(layer_id_included_flag[i][j])); - } - - u(1, mseq_var(vps_timing_info_present_flag)); - if (mseq->vps_timing_info_present_flag) { - u(1, 0, put_bits_hack_zero_bit); - u(31, mseq_var(vps_num_units_in_tick)); - u(1, 0, put_bits_hack_zero_bit); - u(31, mseq_var(vps_time_scale)); - u(1, mseq_var(vps_poc_proportional_to_timing_flag)); - if (mseq->vps_poc_proportional_to_timing_flag) { - ue(mseq_var(vps_num_ticks_poc_diff_minus1)); - } - ue(0, vps_num_hrd_parameters); - } - - u(1, 0, vps_extension_flag); - - vaapi_encode_h265_write_rbsp_trailing_bits(pbc); -} - -static void vaapi_encode_h265_write_st_ref_pic_set(PutBitContext *pbc, - int st_rps_idx, - VAAPIEncodeH265STRPS *mstrps) -{ - int i; - - if (st_rps_idx != 0) - u(1, mstrps_var(inter_ref_pic_set_prediction_flag)); - - if (mstrps->inter_ref_pic_set_prediction_flag) { - av_assert0(0 && "inter ref pic set prediction not supported"); - } else { - ue(mstrps_var(num_negative_pics)); - ue(mstrps_var(num_positive_pics)); - - for (i = 0; i < mstrps->num_negative_pics; i++) { - ue(mstrps_var(delta_poc_s0_minus1[i])); - u(1, mstrps_var(used_by_curr_pic_s0_flag[i])); - } - for (i = 0; i < mstrps->num_positive_pics; i++) { - ue(mstrps_var(delta_poc_s1_minus1[i])); - u(1, mstrps_var(used_by_curr_pic_s1_flag[i])); - } - } -} - -static void vaapi_encode_h265_write_vui_parameters(PutBitContext *pbc, - VAAPIEncodeContext *ctx) -{ - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; - - u(1, mseq_var(aspect_ratio_info_present_flag)); - if (mseq->aspect_ratio_info_present_flag) { - u(8, mseq_var(aspect_ratio_idc)); - if (mseq->aspect_ratio_idc == 255) { - u(16, mseq_var(sar_width)); - u(16, mseq_var(sar_height)); - } - } - - u(1, 0, overscan_info_present_flag); - - u(1, mseq_var(video_signal_type_present_flag)); - if (mseq->video_signal_type_present_flag) { - u(3, mseq_var(video_format)); - u(1, mseq_var(video_full_range_flag)); - u(1, mseq_var(colour_description_present_flag)); - if (mseq->colour_description_present_flag) { - u(8, mseq_var(colour_primaries)); - u(8, mseq_var(transfer_characteristics)); - u(8, mseq_var(matrix_coeffs)); - } - } - - u(1, 0, chroma_loc_info_present_flag); - u(1, 0, neutral_chroma_indication_flag); - u(1, 0, field_seq_flag); - u(1, 0, frame_field_info_present_flag); - u(1, 0, default_display_window_flag); - u(1, 0, vui_timing_info_present_flag); - u(1, 0, bitstream_restriction_flag_flag); -} - -static void vaapi_encode_h265_write_sps(PutBitContext *pbc, - VAAPIEncodeContext *ctx) -{ - VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; - int i; - - vaapi_encode_h265_write_nal_unit_header(pbc, HEVC_NAL_SPS); - - u(4, mseq->video_parameter_set_id, sps_video_parameter_set_id); - - u(3, mseq_var(sps_max_sub_layers_minus1)); - u(1, mseq_var(sps_temporal_id_nesting_flag)); - - vaapi_encode_h265_write_profile_tier_level(pbc, ctx); - - ue(mseq->seq_parameter_set_id, sps_seq_parameter_set_id); - ue(vseq_field(chroma_format_idc)); - if (vseq->seq_fields.bits.chroma_format_idc == 3) - u(1, 0, separate_colour_plane_flag); - - ue(vseq_var(pic_width_in_luma_samples)); - ue(vseq_var(pic_height_in_luma_samples)); - - u(1, mseq_var(conformance_window_flag)); - if (mseq->conformance_window_flag) { - ue(mseq_var(conf_win_left_offset)); - ue(mseq_var(conf_win_right_offset)); - ue(mseq_var(conf_win_top_offset)); - ue(mseq_var(conf_win_bottom_offset)); - } - - ue(vseq_field(bit_depth_luma_minus8)); - ue(vseq_field(bit_depth_chroma_minus8)); - - ue(mseq_var(log2_max_pic_order_cnt_lsb_minus4)); - - u(1, mseq_var(sps_sub_layer_ordering_info_present_flag)); - for (i = (mseq->sps_sub_layer_ordering_info_present_flag ? - 0 : mseq->sps_max_sub_layers_minus1); - i <= mseq->sps_max_sub_layers_minus1; i++) { - ue(mseq_var(sps_max_dec_pic_buffering_minus1[i])); - ue(mseq_var(sps_max_num_reorder_pics[i])); - ue(mseq_var(sps_max_latency_increase_plus1[i])); - } - - ue(vseq_var(log2_min_luma_coding_block_size_minus3)); - ue(vseq_var(log2_diff_max_min_luma_coding_block_size)); - ue(vseq_var(log2_min_transform_block_size_minus2)); - ue(vseq_var(log2_diff_max_min_transform_block_size)); - ue(vseq_var(max_transform_hierarchy_depth_inter)); - ue(vseq_var(max_transform_hierarchy_depth_intra)); - - u(1, vseq_field(scaling_list_enabled_flag)); - if (vseq->seq_fields.bits.scaling_list_enabled_flag) { - u(1, 0, sps_scaling_list_data_present_flag); - } - - u(1, vseq_field(amp_enabled_flag)); - u(1, vseq_field(sample_adaptive_offset_enabled_flag)); - - u(1, vseq_field(pcm_enabled_flag)); - if (vseq->seq_fields.bits.pcm_enabled_flag) { - u(4, vseq_var(pcm_sample_bit_depth_luma_minus1)); - u(4, vseq_var(pcm_sample_bit_depth_chroma_minus1)); - ue(vseq_var(log2_min_pcm_luma_coding_block_size_minus3)); - ue(vseq->log2_max_pcm_luma_coding_block_size_minus3 - - vseq->log2_min_pcm_luma_coding_block_size_minus3, - log2_diff_max_min_pcm_luma_coding_block_size); - u(1, vseq_field(pcm_loop_filter_disabled_flag)); - } - - ue(mseq_var(num_short_term_ref_pic_sets)); - for (i = 0; i < mseq->num_short_term_ref_pic_sets; i++) - vaapi_encode_h265_write_st_ref_pic_set(pbc, i, - &mseq->st_ref_pic_set[i]); - - u(1, mseq_var(long_term_ref_pics_present_flag)); - if (mseq->long_term_ref_pics_present_flag) { - ue(0, num_long_term_ref_pics_sps); - } - - u(1, vseq_field(sps_temporal_mvp_enabled_flag)); - u(1, vseq_field(strong_intra_smoothing_enabled_flag)); - - u(1, mseq_var(vui_parameters_present_flag)); - if (mseq->vui_parameters_present_flag) { - vaapi_encode_h265_write_vui_parameters(pbc, ctx); - } - - u(1, 0, sps_extension_present_flag); - - vaapi_encode_h265_write_rbsp_trailing_bits(pbc); -} - -static void vaapi_encode_h265_write_pps(PutBitContext *pbc, - VAAPIEncodeContext *ctx) +static int vaapi_encode_h265_write_access_unit(AVCodecContext *avctx, + char *data, size_t *data_len, + CodedBitstreamFragment *au) { - VAEncPictureParameterBufferHEVC *vpic = ctx->codec_picture_params; - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; - int i; - - vaapi_encode_h265_write_nal_unit_header(pbc, HEVC_NAL_PPS); - - ue(vpic->slice_pic_parameter_set_id, pps_pic_parameter_set_id); - ue(mseq->seq_parameter_set_id, pps_seq_parameter_set_id); - - u(1, vpic_field(dependent_slice_segments_enabled_flag)); - u(1, mseq_var(output_flag_present_flag)); - u(3, mseq_var(num_extra_slice_header_bits)); - u(1, vpic_field(sign_data_hiding_enabled_flag)); - u(1, mseq_var(cabac_init_present_flag)); - - ue(vpic_var(num_ref_idx_l0_default_active_minus1)); - ue(vpic_var(num_ref_idx_l1_default_active_minus1)); - - se(vpic->pic_init_qp - 26, init_qp_minus26); - - u(1, vpic_field(constrained_intra_pred_flag)); - u(1, vpic_field(transform_skip_enabled_flag)); - - u(1, vpic_field(cu_qp_delta_enabled_flag)); - if (vpic->pic_fields.bits.cu_qp_delta_enabled_flag) - ue(vpic_var(diff_cu_qp_delta_depth)); - - se(vpic_var(pps_cb_qp_offset)); - se(vpic_var(pps_cr_qp_offset)); - - u(1, mseq_var(pps_slice_chroma_qp_offsets_present_flag)); - u(1, vpic_field(weighted_pred_flag)); - u(1, vpic_field(weighted_bipred_flag)); - u(1, vpic_field(transquant_bypass_enabled_flag)); - u(1, vpic_field(tiles_enabled_flag)); - u(1, vpic_field(entropy_coding_sync_enabled_flag)); + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + int err; - if (vpic->pic_fields.bits.tiles_enabled_flag) { - ue(vpic_var(num_tile_columns_minus1)); - ue(vpic_var(num_tile_rows_minus1)); - u(1, mseq_var(uniform_spacing_flag)); - if (!mseq->uniform_spacing_flag) { - for (i = 0; i < vpic->num_tile_columns_minus1; i++) - ue(vpic_var(column_width_minus1[i])); - for (i = 0; i < vpic->num_tile_rows_minus1; i++) - ue(vpic_var(row_height_minus1[i])); - } - u(1, vpic_field(loop_filter_across_tiles_enabled_flag)); + err = ff_cbs_write_fragment_data(priv->cbc, au); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); + return err; } - u(1, vpic_field(pps_loop_filter_across_slices_enabled_flag)); - u(1, mseq_var(deblocking_filter_control_present_flag)); - if (mseq->deblocking_filter_control_present_flag) { - u(1, mseq_var(deblocking_filter_override_enabled_flag)); - u(1, mseq_var(pps_deblocking_filter_disabled_flag)); - if (!mseq->pps_deblocking_filter_disabled_flag) { - se(mseq_var(pps_beta_offset_div2)); - se(mseq_var(pps_tc_offset_div2)); - } + if (*data_len < 8 * au->data_size - au->data_bit_padding) { + av_log(avctx, AV_LOG_ERROR, "Access unit too large: " + "%zu < %zu.\n", *data_len, + 8 * au->data_size - au->data_bit_padding); + return AVERROR(ENOSPC); } - u(1, 0, pps_scaling_list_data_present_flag); - // No scaling list data. + memcpy(data, au->data, au->data_size); + *data_len = 8 * au->data_size - au->data_bit_padding; - u(1, mseq_var(lists_modification_present_flag)); - ue(vpic_var(log2_parallel_merge_level_minus2)); - u(1, 0, slice_segment_header_extension_present_flag); - u(1, 0, pps_extension_present_flag); - - vaapi_encode_h265_write_rbsp_trailing_bits(pbc); + return 0; } -static void vaapi_encode_h265_write_slice_header2(PutBitContext *pbc, - VAAPIEncodeContext *ctx, - VAAPIEncodePicture *pic, - VAAPIEncodeSlice *slice) +static int vaapi_encode_h265_add_nal(AVCodecContext *avctx, + CodedBitstreamFragment *au, + void *nal_unit) { - VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; - VAEncSliceParameterBufferHEVC *vslice = slice->codec_slice_params; - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; - VAAPIEncodeH265Slice *pslice = slice->priv_data; - VAAPIEncodeH265MiscSliceParams *mslice = &pslice->misc_slice_params; - int i; - - vaapi_encode_h265_write_nal_unit_header(pbc, vpic->nal_unit_type); - - u(1, mslice_var(first_slice_segment_in_pic_flag)); - if (vpic->nal_unit_type >= HEVC_NAL_BLA_W_LP && - vpic->nal_unit_type <= 23) - u(1, mslice_var(no_output_of_prior_pics_flag)); - - ue(vslice_var(slice_pic_parameter_set_id)); - - if (!mslice->first_slice_segment_in_pic_flag) { - if (vpic->pic_fields.bits.dependent_slice_segments_enabled_flag) - u(1, vslice_field(dependent_slice_segment_flag)); - u(av_log2((priv->ctu_width * priv->ctu_height) - 1) + 1, - vslice_var(slice_segment_address)); - } - if (!vslice->slice_fields.bits.dependent_slice_segment_flag) { - for (i = 0; i < mseq->num_extra_slice_header_bits; i++) - u(1, mslice_var(slice_reserved_flag[i])); - - ue(vslice_var(slice_type)); - if (mseq->output_flag_present_flag) - u(1, 1, pic_output_flag); - if (vseq->seq_fields.bits.separate_colour_plane_flag) - u(2, vslice_field(colour_plane_id)); - if (vpic->nal_unit_type != HEVC_NAL_IDR_W_RADL && - vpic->nal_unit_type != HEVC_NAL_IDR_N_LP) { - u(4 + mseq->log2_max_pic_order_cnt_lsb_minus4, - (pslice->pic_order_cnt & - ((1 << (mseq->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1)), - slice_pic_order_cnt_lsb); - - u(1, mslice_var(short_term_ref_pic_set_sps_flag)); - if (!mslice->short_term_ref_pic_set_sps_flag) { - vaapi_encode_h265_write_st_ref_pic_set(pbc, mseq->num_short_term_ref_pic_sets, - &mslice->st_ref_pic_set); - } else if (mseq->num_short_term_ref_pic_sets > 1) { - u(av_log2(mseq->num_short_term_ref_pic_sets - 1) + 1, - mslice_var(short_term_ref_pic_idx)); - } - - if (mseq->long_term_ref_pics_present_flag) { - av_assert0(0); - } - } - - if (vseq->seq_fields.bits.sps_temporal_mvp_enabled_flag) { - u(1, vslice_field(slice_temporal_mvp_enabled_flag)); - } - - if (vseq->seq_fields.bits.sample_adaptive_offset_enabled_flag) { - u(1, vslice_field(slice_sao_luma_flag)); - if (!vseq->seq_fields.bits.separate_colour_plane_flag && - vseq->seq_fields.bits.chroma_format_idc != 0) { - u(1, vslice_field(slice_sao_chroma_flag)); - } - } - - if (vslice->slice_type == HEVC_SLICE_P || vslice->slice_type == HEVC_SLICE_B) { - u(1, vslice_field(num_ref_idx_active_override_flag)); - if (vslice->slice_fields.bits.num_ref_idx_active_override_flag) { - ue(vslice_var(num_ref_idx_l0_active_minus1)); - if (vslice->slice_type == HEVC_SLICE_B) { - ue(vslice_var(num_ref_idx_l1_active_minus1)); - } - } - - if (mseq->lists_modification_present_flag) { - av_assert0(0); - // ref_pic_lists_modification() - } - if (vslice->slice_type == HEVC_SLICE_B) { - u(1, vslice_field(mvd_l1_zero_flag)); - } - if (mseq->cabac_init_present_flag) { - u(1, vslice_field(cabac_init_flag)); - } - if (vslice->slice_fields.bits.slice_temporal_mvp_enabled_flag) { - if (vslice->slice_type == HEVC_SLICE_B) - u(1, vslice_field(collocated_from_l0_flag)); - ue(vpic->collocated_ref_pic_index, collocated_ref_idx); - } - if ((vpic->pic_fields.bits.weighted_pred_flag && - vslice->slice_type == HEVC_SLICE_P) || - (vpic->pic_fields.bits.weighted_bipred_flag && - vslice->slice_type == HEVC_SLICE_B)) { - av_assert0(0); - // pred_weight_table() - } - ue(5 - vslice->max_num_merge_cand, five_minus_max_num_merge_cand); - } - - se(vslice_var(slice_qp_delta)); - if (mseq->pps_slice_chroma_qp_offsets_present_flag) { - se(vslice_var(slice_cb_qp_offset)); - se(vslice_var(slice_cr_qp_offset)); - } - if (mseq->pps_slice_chroma_offset_list_enabled_flag) { - u(1, 0, cu_chroma_qp_offset_enabled_flag); - } - if (mseq->deblocking_filter_override_enabled_flag) { - u(1, mslice_var(deblocking_filter_override_flag)); - } - if (mslice->deblocking_filter_override_flag) { - u(1, vslice_field(slice_deblocking_filter_disabled_flag)); - if (!vslice->slice_fields.bits.slice_deblocking_filter_disabled_flag) { - se(vslice_var(slice_beta_offset_div2)); - se(vslice_var(slice_tc_offset_div2)); - } - } - if (vpic->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag && - (vslice->slice_fields.bits.slice_sao_luma_flag || - vslice->slice_fields.bits.slice_sao_chroma_flag || - vslice->slice_fields.bits.slice_deblocking_filter_disabled_flag)) { - u(1, vslice_field(slice_loop_filter_across_slices_enabled_flag)); - } - - if (vpic->pic_fields.bits.tiles_enabled_flag || - vpic->pic_fields.bits.entropy_coding_sync_enabled_flag) { - // num_entry_point_offsets - } + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + H265RawNALUnitHeader *header = nal_unit; + int err; - if (0) { - // slice_segment_header_extension_length - } + err = ff_cbs_insert_unit_content(priv->cbc, au, -1, + header->nal_unit_type, nal_unit); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " + "type = %d.\n", header->nal_unit_type); + return err; } - u(1, 1, alignment_bit_equal_to_one); - while (put_bits_count(pbc) & 7) - u(1, 0, alignment_bit_equal_to_zero); + return 0; } static int vaapi_encode_h265_write_sequence_header(AVCodecContext *avctx, char *data, size_t *data_len) { - VAAPIEncodeContext *ctx = avctx->priv_data; - PutBitContext pbc; - char tmp[256]; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + CodedBitstreamFragment *au = &priv->current_access_unit; int err; - size_t nal_len, bit_len, bit_pos, next_len; - - bit_len = *data_len; - bit_pos = 0; - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h265_write_vps(&pbc, ctx); - nal_len = put_bits_count(&pbc); - flush_put_bits(&pbc); - - next_len = bit_len - bit_pos; - err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, - &next_len, - tmp, nal_len); + err = vaapi_encode_h265_add_nal(avctx, au, &priv->vps); if (err < 0) - return err; - bit_pos += next_len; + goto fail; - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h265_write_sps(&pbc, ctx); - nal_len = put_bits_count(&pbc); - flush_put_bits(&pbc); - - next_len = bit_len - bit_pos; - err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, - &next_len, - tmp, nal_len); + err = vaapi_encode_h265_add_nal(avctx, au, &priv->sps); if (err < 0) - return err; - bit_pos += next_len; + goto fail; - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h265_write_pps(&pbc, ctx); - nal_len = put_bits_count(&pbc); - flush_put_bits(&pbc); - - next_len = bit_len - bit_pos; - err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8, - &next_len, - tmp, nal_len); + err = vaapi_encode_h265_add_nal(avctx, au, &priv->pps); if (err < 0) - return err; - bit_pos += next_len; + goto fail; - *data_len = bit_pos; - return 0; + err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); +fail: + ff_cbs_fragment_uninit(priv->cbc, au); + return err; } static int vaapi_encode_h265_write_slice_header(AVCodecContext *avctx, @@ -763,195 +140,377 @@ static int vaapi_encode_h265_write_slice_header(AVCodecContext *avctx, VAAPIEncodeSlice *slice, char *data, size_t *data_len) { - VAAPIEncodeContext *ctx = avctx->priv_data; - PutBitContext pbc; - char tmp[256]; - size_t header_len; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + CodedBitstreamFragment *au = &priv->current_access_unit; + int err; - init_put_bits(&pbc, tmp, sizeof(tmp)); - vaapi_encode_h265_write_slice_header2(&pbc, ctx, pic, slice); - header_len = put_bits_count(&pbc); - flush_put_bits(&pbc); + err = vaapi_encode_h265_add_nal(avctx, au, &priv->slice); + if (err < 0) + goto fail; - return ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data, data_len, - tmp, header_len); + err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); +fail: + ff_cbs_fragment_uninit(priv->cbc, au); + return err; } static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) { - VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferHEVC *vpic = ctx->codec_picture_params; - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + H265RawVPS *vps = &priv->vps; + H265RawSPS *sps = &priv->sps; + H265RawPPS *pps = &priv->pps; + H265RawVUI *vui = &sps->vui; + VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferHEVC *vpic = ctx->codec_picture_params; int i; - { - // general_profile_space == 0. - vseq->general_profile_idc = 1; // Main profile (ctx->codec_profile?) - vseq->general_tier_flag = 0; - - vseq->general_level_idc = avctx->level * 3; - - vseq->intra_period = 0; - vseq->intra_idr_period = 0; - vseq->ip_period = 0; - - vseq->pic_width_in_luma_samples = ctx->surface_width; - vseq->pic_height_in_luma_samples = ctx->surface_height; - - vseq->seq_fields.bits.chroma_format_idc = 1; // 4:2:0. - vseq->seq_fields.bits.separate_colour_plane_flag = 0; - vseq->seq_fields.bits.bit_depth_luma_minus8 = - avctx->profile == FF_PROFILE_HEVC_MAIN_10 ? 2 : 0; - vseq->seq_fields.bits.bit_depth_chroma_minus8 = - avctx->profile == FF_PROFILE_HEVC_MAIN_10 ? 2 : 0; - // Other misc flags all zero. - - // These have to come from the capabilities of the encoder. We have - // no way to query it, so just hardcode ones which worked for me... - // CTB size from 8x8 to 32x32. - vseq->log2_min_luma_coding_block_size_minus3 = 0; - vseq->log2_diff_max_min_luma_coding_block_size = 2; - // Transform size from 4x4 to 32x32. - vseq->log2_min_transform_block_size_minus2 = 0; - vseq->log2_diff_max_min_transform_block_size = 3; - // Full transform hierarchy allowed (2-5). - vseq->max_transform_hierarchy_depth_inter = 3; - vseq->max_transform_hierarchy_depth_intra = 3; - - vseq->vui_parameters_present_flag = 0; - - vseq->bits_per_second = avctx->bit_rate; - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { - vseq->vui_num_units_in_tick = avctx->framerate.den; - vseq->vui_time_scale = avctx->framerate.num; - } else { - vseq->vui_num_units_in_tick = avctx->time_base.num; - vseq->vui_time_scale = avctx->time_base.den; - } + memset(&priv->current_access_unit, 0, + sizeof(priv->current_access_unit)); - vseq->intra_period = avctx->gop_size; - vseq->intra_idr_period = avctx->gop_size; - vseq->ip_period = ctx->b_per_p + 1; - } + memset(vps, 0, sizeof(*vps)); + memset(sps, 0, sizeof(*sps)); + memset(pps, 0, sizeof(*pps)); - { - vpic->decoded_curr_pic.picture_id = VA_INVALID_ID; - vpic->decoded_curr_pic.flags = VA_PICTURE_HEVC_INVALID; - for (i = 0; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++) { - vpic->reference_frames[i].picture_id = VA_INVALID_ID; - vpic->reference_frames[i].flags = VA_PICTURE_HEVC_INVALID; - } + // VPS - vpic->collocated_ref_pic_index = 0xff; + vps->nal_unit_header = (H265RawNALUnitHeader) { + .nal_unit_type = HEVC_NAL_VPS, + .nuh_layer_id = 0, + .nuh_temporal_id_plus1 = 1, + }; - vpic->last_picture = 0; + vps->vps_video_parameter_set_id = 0; - vpic->pic_init_qp = priv->fixed_qp_idr; + vps->vps_base_layer_internal_flag = 1; + vps->vps_base_layer_available_flag = 1; + vps->vps_max_layers_minus1 = 0; + vps->vps_max_sub_layers_minus1 = 0; + vps->vps_temporal_id_nesting_flag = 1; - vpic->diff_cu_qp_delta_depth = 0; - vpic->pps_cb_qp_offset = 0; - vpic->pps_cr_qp_offset = 0; + vps->profile_tier_level = (H265RawProfileTierLevel) { + .general_profile_space = 0, + .general_profile_idc = avctx->profile, + .general_tier_flag = 0, - // tiles_enabled_flag == 0, so ignore num_tile_(rows|columns)_minus1. + .general_progressive_source_flag = 1, + .general_interlaced_source_flag = 0, + .general_non_packed_constraint_flag = 1, + .general_frame_only_constraint_flag = 1, - vpic->log2_parallel_merge_level_minus2 = 0; + .general_level_idc = avctx->level, + }; + vps->profile_tier_level.general_profile_compatibility_flag[avctx->profile & 31] = 1; - // No limit on size. - vpic->ctu_max_bitsize_allowed = 0; + vps->vps_sub_layer_ordering_info_present_flag = 0; + vps->vps_max_dec_pic_buffering_minus1[0] = (ctx->b_per_p > 0) + 1; + vps->vps_max_num_reorder_pics[0] = (ctx->b_per_p > 0); + vps->vps_max_latency_increase_plus1[0] = 0; - vpic->num_ref_idx_l0_default_active_minus1 = 0; - vpic->num_ref_idx_l1_default_active_minus1 = 0; + vps->vps_max_layer_id = 0; + vps->vps_num_layer_sets_minus1 = 0; + vps->layer_id_included_flag[0][0] = 1; - vpic->slice_pic_parameter_set_id = 0; + vps->vps_timing_info_present_flag = 1; + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + vps->vps_num_units_in_tick = avctx->framerate.den; + vps->vps_time_scale = avctx->framerate.num; + vps->vps_poc_proportional_to_timing_flag = 1; + vps->vps_num_ticks_poc_diff_one_minus1 = 0; + } else { + vps->vps_num_units_in_tick = avctx->time_base.num; + vps->vps_time_scale = avctx->time_base.den; + vps->vps_poc_proportional_to_timing_flag = 0; + } + vps->vps_num_hrd_parameters = 0; - vpic->pic_fields.bits.screen_content_flag = 0; - vpic->pic_fields.bits.enable_gpu_weighted_prediction = 0; - // Per-CU QP changes are required for non-constant-QP modes. - vpic->pic_fields.bits.cu_qp_delta_enabled_flag = - ctx->va_rc_mode != VA_RC_CQP; - } + // SPS - { - mseq->video_parameter_set_id = 5; - mseq->seq_parameter_set_id = 5; + sps->nal_unit_header = (H265RawNALUnitHeader) { + .nal_unit_type = HEVC_NAL_SPS, + .nuh_layer_id = 0, + .nuh_temporal_id_plus1 = 1, + }; - mseq->vps_max_layers_minus1 = 0; - mseq->vps_max_sub_layers_minus1 = 0; - mseq->vps_temporal_id_nesting_flag = 1; - mseq->sps_max_sub_layers_minus1 = 0; - mseq->sps_temporal_id_nesting_flag = 1; + sps->sps_video_parameter_set_id = vps->vps_video_parameter_set_id; - for (i = 0; i < 32; i++) { - mseq->general_profile_compatibility_flag[i] = - (i == vseq->general_profile_idc); - } + sps->sps_max_sub_layers_minus1 = vps->vps_max_sub_layers_minus1; + sps->sps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag; - mseq->general_progressive_source_flag = 1; - mseq->general_interlaced_source_flag = 0; - mseq->general_non_packed_constraint_flag = 0; - mseq->general_frame_only_constraint_flag = 1; - mseq->general_inbld_flag = 0; - - mseq->log2_max_pic_order_cnt_lsb_minus4 = 8; - mseq->vps_sub_layer_ordering_info_present_flag = 0; - mseq->vps_max_dec_pic_buffering_minus1[0] = (avctx->max_b_frames > 0) + 1; - mseq->vps_max_num_reorder_pics[0] = (avctx->max_b_frames > 0); - mseq->vps_max_latency_increase_plus1[0] = 0; - mseq->sps_sub_layer_ordering_info_present_flag = 0; - mseq->sps_max_dec_pic_buffering_minus1[0] = (avctx->max_b_frames > 0) + 1; - mseq->sps_max_num_reorder_pics[0] = (avctx->max_b_frames > 0); - mseq->sps_max_latency_increase_plus1[0] = 0; - - mseq->vps_timing_info_present_flag = 1; - mseq->vps_num_units_in_tick = avctx->time_base.num; - mseq->vps_time_scale = avctx->time_base.den; - mseq->vps_poc_proportional_to_timing_flag = 1; - mseq->vps_num_ticks_poc_diff_minus1 = 0; - - if (avctx->width != ctx->surface_width || - avctx->height != ctx->surface_height) { - mseq->conformance_window_flag = 1; - mseq->conf_win_left_offset = 0; - mseq->conf_win_right_offset = - (ctx->surface_width - avctx->width) / 2; - mseq->conf_win_top_offset = 0; - mseq->conf_win_bottom_offset = - (ctx->surface_height - avctx->height) / 2; - } else { - mseq->conformance_window_flag = 0; - } + sps->profile_tier_level = vps->profile_tier_level; - mseq->num_short_term_ref_pic_sets = 0; - // STRPSs should ideally be here rather than repeated in each slice. + sps->sps_seq_parameter_set_id = 0; - mseq->vui_parameters_present_flag = 1; - if (avctx->sample_aspect_ratio.num != 0) { - mseq->aspect_ratio_info_present_flag = 1; - if (avctx->sample_aspect_ratio.num == - avctx->sample_aspect_ratio.den) { - mseq->aspect_ratio_idc = 1; - } else { - mseq->aspect_ratio_idc = 255; // Extended SAR. - mseq->sar_width = avctx->sample_aspect_ratio.num; - mseq->sar_height = avctx->sample_aspect_ratio.den; + sps->chroma_format_idc = 1; // YUV 4:2:0. + sps->separate_colour_plane_flag = 0; + + sps->pic_width_in_luma_samples = ctx->surface_width; + sps->pic_height_in_luma_samples = ctx->surface_height; + + if (avctx->width != ctx->surface_width || + avctx->height != ctx->surface_height) { + sps->conformance_window_flag = 1; + sps->conf_win_left_offset = 0; + sps->conf_win_right_offset = + (ctx->surface_width - avctx->width) / 2; + sps->conf_win_top_offset = 0; + sps->conf_win_bottom_offset = + (ctx->surface_height - avctx->height) / 2; + } else { + sps->conformance_window_flag = 0; + } + + sps->bit_depth_luma_minus8 = + avctx->profile == FF_PROFILE_HEVC_MAIN_10 ? 2 : 0; + sps->bit_depth_chroma_minus8 = sps->bit_depth_luma_minus8; + + sps->log2_max_pic_order_cnt_lsb_minus4 = 8; + + sps->sps_sub_layer_ordering_info_present_flag = + vps->vps_sub_layer_ordering_info_present_flag; + for (i = 0; i <= sps->sps_max_sub_layers_minus1; i++) { + sps->sps_max_dec_pic_buffering_minus1[i] = + vps->vps_max_dec_pic_buffering_minus1[i]; + sps->sps_max_num_reorder_pics[i] = + vps->vps_max_num_reorder_pics[i]; + sps->sps_max_latency_increase_plus1[i] = + vps->vps_max_latency_increase_plus1[i]; + } + + // These have to come from the capabilities of the encoder. We have no + // way to query them, so just hardcode parameters which work on the Intel + // driver. + // CTB size from 8x8 to 32x32. + sps->log2_min_luma_coding_block_size_minus3 = 0; + sps->log2_diff_max_min_luma_coding_block_size = 2; + // Transform size from 4x4 to 32x32. + sps->log2_min_luma_transform_block_size_minus2 = 0; + sps->log2_diff_max_min_luma_transform_block_size = 3; + // Full transform hierarchy allowed (2-5). + sps->max_transform_hierarchy_depth_inter = 3; + sps->max_transform_hierarchy_depth_intra = 3; + // AMP works. + sps->amp_enabled_flag = 1; + // SAO and temporal MVP do not work. + sps->sample_adaptive_offset_enabled_flag = 0; + sps->sps_temporal_mvp_enabled_flag = 0; + + sps->pcm_enabled_flag = 0; + + // STRPSs should ideally be here rather than defined individually in + // each slice, but the structure isn't completely fixed so for now + // don't bother. + sps->num_short_term_ref_pic_sets = 0; + sps->long_term_ref_pics_present_flag = 0; + + sps->vui_parameters_present_flag = 1; + + if (avctx->sample_aspect_ratio.num != 0 && + avctx->sample_aspect_ratio.den != 0) { + static const AVRational sar_idc[] = { + { 0, 0 }, + { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, + { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, + { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, + { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, + }; + int i; + for (i = 0; i < FF_ARRAY_ELEMS(sar_idc); i++) { + if (avctx->sample_aspect_ratio.num == sar_idc[i].num && + avctx->sample_aspect_ratio.den == sar_idc[i].den) { + vui->aspect_ratio_idc = i; + break; } } - if (1) { - // Should this be conditional on some of these being set? - mseq->video_signal_type_present_flag = 1; - mseq->video_format = 5; // Unspecified. - mseq->video_full_range_flag = 0; - mseq->colour_description_present_flag = 1; - mseq->colour_primaries = avctx->color_primaries; - mseq->transfer_characteristics = avctx->color_trc; - mseq->matrix_coeffs = avctx->colorspace; + if (i >= FF_ARRAY_ELEMS(sar_idc)) { + vui->aspect_ratio_idc = 255; + vui->sar_width = avctx->sample_aspect_ratio.num; + vui->sar_height = avctx->sample_aspect_ratio.den; + } + vui->aspect_ratio_info_present_flag = 1; + } + + if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || + avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED || + avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { + vui->video_signal_type_present_flag = 1; + vui->video_format = 5; // Unspecified. + vui->video_full_range_flag = + avctx->color_range == AVCOL_RANGE_JPEG; + + if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED || + avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { + vui->colour_description_present_flag = 1; + vui->colour_primaries = avctx->color_primaries; + vui->transfer_characteristics = avctx->color_trc; + vui->matrix_coefficients = avctx->colorspace; } + } else { + vui->video_format = 5; + vui->video_full_range_flag = 0; + vui->colour_primaries = avctx->color_primaries; + vui->transfer_characteristics = avctx->color_trc; + vui->matrix_coefficients = avctx->colorspace; + } + + if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) { + vui->chroma_loc_info_present_flag = 1; + vui->chroma_sample_loc_type_top_field = + vui->chroma_sample_loc_type_bottom_field = + avctx->chroma_sample_location - 1; } + vui->vui_timing_info_present_flag = 1; + vui->vui_num_units_in_tick = vps->vps_num_units_in_tick; + vui->vui_time_scale = vps->vps_time_scale; + vui->vui_poc_proportional_to_timing_flag = vps->vps_poc_proportional_to_timing_flag; + vui->vui_num_ticks_poc_diff_one_minus1 = vps->vps_num_ticks_poc_diff_one_minus1; + vui->vui_hrd_parameters_present_flag = 0; + + vui->bitstream_restriction_flag = 1; + vui->motion_vectors_over_pic_boundaries_flag = 1; + vui->restricted_ref_pic_lists_flag = 1; + vui->max_bytes_per_pic_denom = 0; + vui->max_bits_per_min_cu_denom = 0; + vui->log2_max_mv_length_horizontal = 15; + vui->log2_max_mv_length_vertical = 15; + + + // PPS + + pps->nal_unit_header = (H265RawNALUnitHeader) { + .nal_unit_type = HEVC_NAL_PPS, + .nuh_layer_id = 0, + .nuh_temporal_id_plus1 = 1, + }; + + pps->pps_pic_parameter_set_id = 0; + pps->pps_seq_parameter_set_id = sps->sps_seq_parameter_set_id; + + pps->num_ref_idx_l0_default_active_minus1 = 0; + pps->num_ref_idx_l1_default_active_minus1 = 0; + + pps->init_qp_minus26 = priv->fixed_qp_idr - 26; + + pps->cu_qp_delta_enabled_flag = (ctx->va_rc_mode != VA_RC_CQP); + pps->diff_cu_qp_delta_depth = 0; + + pps->pps_loop_filter_across_slices_enabled_flag = 1; + + + // Fill VAAPI parameter buffers. + + *vseq = (VAEncSequenceParameterBufferHEVC) { + .general_profile_idc = vps->profile_tier_level.general_profile_idc, + .general_level_idc = vps->profile_tier_level.general_level_idc, + .general_tier_flag = vps->profile_tier_level.general_tier_flag, + + .intra_period = avctx->gop_size, + .intra_idr_period = avctx->gop_size, + .ip_period = ctx->b_per_p + 1, + .bits_per_second = avctx->bit_rate, + + .pic_width_in_luma_samples = sps->pic_width_in_luma_samples, + .pic_height_in_luma_samples = sps->pic_height_in_luma_samples, + + .seq_fields.bits = { + .chroma_format_idc = sps->chroma_format_idc, + .separate_colour_plane_flag = sps->separate_colour_plane_flag, + .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8, + .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8, + .scaling_list_enabled_flag = sps->scaling_list_enabled_flag, + .strong_intra_smoothing_enabled_flag = + sps->strong_intra_smoothing_enabled_flag, + .amp_enabled_flag = sps->amp_enabled_flag, + .sample_adaptive_offset_enabled_flag = + sps->sample_adaptive_offset_enabled_flag, + .pcm_enabled_flag = sps->pcm_enabled_flag, + .pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled_flag, + .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag, + }, + + .log2_min_luma_coding_block_size_minus3 = + sps->log2_min_luma_coding_block_size_minus3, + .log2_diff_max_min_luma_coding_block_size = + sps->log2_diff_max_min_luma_coding_block_size, + .log2_min_transform_block_size_minus2 = + sps->log2_min_luma_transform_block_size_minus2, + .log2_diff_max_min_transform_block_size = + sps->log2_diff_max_min_luma_transform_block_size, + .max_transform_hierarchy_depth_inter = + sps->max_transform_hierarchy_depth_inter, + .max_transform_hierarchy_depth_intra = + sps->max_transform_hierarchy_depth_intra, + + .pcm_sample_bit_depth_luma_minus1 = + sps->pcm_sample_bit_depth_luma_minus1, + .pcm_sample_bit_depth_chroma_minus1 = + sps->pcm_sample_bit_depth_chroma_minus1, + .log2_min_pcm_luma_coding_block_size_minus3 = + sps->log2_min_pcm_luma_coding_block_size_minus3, + .log2_max_pcm_luma_coding_block_size_minus3 = + sps->log2_min_pcm_luma_coding_block_size_minus3 + + sps->log2_diff_max_min_pcm_luma_coding_block_size, + + .vui_parameters_present_flag = 0, + }; + + *vpic = (VAEncPictureParameterBufferHEVC) { + .decoded_curr_pic = { + .picture_id = VA_INVALID_ID, + .flags = VA_PICTURE_HEVC_INVALID, + }, + + .coded_buf = VA_INVALID_ID, + + .collocated_ref_pic_index = 0xff, + + .last_picture = 0, + + .pic_init_qp = pps->init_qp_minus26 + 26, + .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth, + .pps_cb_qp_offset = pps->pps_cb_qp_offset, + .pps_cr_qp_offset = pps->pps_cr_qp_offset, + + .num_tile_columns_minus1 = pps->num_tile_columns_minus1, + .num_tile_rows_minus1 = pps->num_tile_rows_minus1, + + .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level_minus2, + .ctu_max_bitsize_allowed = 0, + + .num_ref_idx_l0_default_active_minus1 = + pps->num_ref_idx_l0_default_active_minus1, + .num_ref_idx_l1_default_active_minus1 = + pps->num_ref_idx_l1_default_active_minus1, + + .slice_pic_parameter_set_id = pps->pps_pic_parameter_set_id, + + .pic_fields.bits = { + .sign_data_hiding_enabled_flag = pps->sign_data_hiding_enabled_flag, + .constrained_intra_pred_flag = pps->constrained_intra_pred_flag, + .transform_skip_enabled_flag = pps->transform_skip_enabled_flag, + .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag, + .weighted_pred_flag = pps->weighted_pred_flag, + .weighted_bipred_flag = pps->weighted_bipred_flag, + .transquant_bypass_enabled_flag = pps->transquant_bypass_enabled_flag, + .tiles_enabled_flag = pps->tiles_enabled_flag, + .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag, + .loop_filter_across_tiles_enabled_flag = + pps->loop_filter_across_tiles_enabled_flag, + .scaling_list_data_present_flag = (sps->sps_scaling_list_data_present_flag | + pps->pps_scaling_list_data_present_flag), + .screen_content_flag = 0, + .enable_gpu_weighted_prediction = 0, + .no_output_of_prior_pics_flag = 0, + }, + }; + return 0; } @@ -959,65 +518,87 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx, VAAPIEncodePicture *pic) { VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; VAAPIEncodeH265Context *priv = ctx->priv_data; + VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; int i; if (pic->type == PICTURE_TYPE_IDR) { av_assert0(pic->display_order == pic->encode_order); + priv->last_idr_frame = pic->display_order; + + priv->slice_nal_unit = HEVC_NAL_IDR_W_RADL; + priv->slice_type = HEVC_SLICE_I; } else { av_assert0(pic->encode_order > priv->last_idr_frame); - // Display order need not be if we have RA[SD]L pictures, though. + + if (pic->type == PICTURE_TYPE_I) { + priv->slice_nal_unit = HEVC_NAL_CRA_NUT; + priv->slice_type = HEVC_SLICE_I; + } else if (pic->type == PICTURE_TYPE_P) { + av_assert0(pic->refs[0]); + priv->slice_nal_unit = HEVC_NAL_TRAIL_R; + priv->slice_type = HEVC_SLICE_P; + } else { + av_assert0(pic->refs[0] && pic->refs[1]); + if (pic->refs[1]->type == PICTURE_TYPE_I) + priv->slice_nal_unit = HEVC_NAL_RASL_N; + else + priv->slice_nal_unit = HEVC_NAL_TRAIL_N; + priv->slice_type = HEVC_SLICE_B; + } } + priv->pic_order_cnt = pic->display_order - priv->last_idr_frame; - vpic->decoded_curr_pic.picture_id = pic->recon_surface; - vpic->decoded_curr_pic.pic_order_cnt = - pic->display_order - priv->last_idr_frame; - vpic->decoded_curr_pic.flags = 0; + vpic->decoded_curr_pic = (VAPictureHEVC) { + .picture_id = pic->recon_surface, + .pic_order_cnt = priv->pic_order_cnt, + .flags = 0, + }; for (i = 0; i < pic->nb_refs; i++) { VAAPIEncodePicture *ref = pic->refs[i]; - av_assert0(ref); - vpic->reference_frames[i].picture_id = ref->recon_surface; - vpic->reference_frames[i].pic_order_cnt = - ref->display_order - priv->last_idr_frame; - vpic->reference_frames[i].flags = - (ref->display_order < pic->display_order ? - VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE : 0) | - (ref->display_order > pic->display_order ? - VA_PICTURE_HEVC_RPS_ST_CURR_AFTER : 0); + av_assert0(ref && ref->encode_order < pic->encode_order); + + vpic->reference_frames[i] = (VAPictureHEVC) { + .picture_id = ref->recon_surface, + .pic_order_cnt = ref->display_order - priv->last_idr_frame, + .flags = (ref->display_order < pic->display_order ? + VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE : 0) | + (ref->display_order > pic->display_order ? + VA_PICTURE_HEVC_RPS_ST_CURR_AFTER : 0), + }; } for (; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++) { - vpic->reference_frames[i].picture_id = VA_INVALID_ID; - vpic->reference_frames[i].flags = VA_PICTURE_HEVC_INVALID; + vpic->reference_frames[i] = (VAPictureHEVC) { + .picture_id = VA_INVALID_ID, + .flags = VA_PICTURE_HEVC_INVALID, + }; } vpic->coded_buf = pic->output_buffer; + vpic->nal_unit_type = priv->slice_nal_unit; + switch (pic->type) { case PICTURE_TYPE_IDR: - vpic->nal_unit_type = HEVC_NAL_IDR_W_RADL; - vpic->pic_fields.bits.idr_pic_flag = 1; - vpic->pic_fields.bits.coding_type = 1; + vpic->pic_fields.bits.idr_pic_flag = 1; + vpic->pic_fields.bits.coding_type = 1; vpic->pic_fields.bits.reference_pic_flag = 1; break; case PICTURE_TYPE_I: - vpic->nal_unit_type = HEVC_NAL_TRAIL_R; - vpic->pic_fields.bits.idr_pic_flag = 0; - vpic->pic_fields.bits.coding_type = 1; + vpic->pic_fields.bits.idr_pic_flag = 0; + vpic->pic_fields.bits.coding_type = 1; vpic->pic_fields.bits.reference_pic_flag = 1; break; case PICTURE_TYPE_P: - vpic->nal_unit_type = HEVC_NAL_TRAIL_R; - vpic->pic_fields.bits.idr_pic_flag = 0; - vpic->pic_fields.bits.coding_type = 2; + vpic->pic_fields.bits.idr_pic_flag = 0; + vpic->pic_fields.bits.coding_type = 2; vpic->pic_fields.bits.reference_pic_flag = 1; break; case PICTURE_TYPE_B: - vpic->nal_unit_type = HEVC_NAL_TRAIL_R; - vpic->pic_fields.bits.idr_pic_flag = 0; - vpic->pic_fields.bits.coding_type = 3; + vpic->pic_fields.bits.idr_pic_flag = 0; + vpic->pic_fields.bits.coding_type = 3; vpic->pic_fields.bits.reference_pic_flag = 0; break; default: @@ -1034,90 +615,40 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, VAAPIEncodeSlice *slice) { VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + const H265RawSPS *sps = &priv->sps; + const H265RawPPS *pps = &priv->pps; + H265RawSliceHeader *sh = &priv->slice.header; VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; VAEncSliceParameterBufferHEVC *vslice = slice->codec_slice_params; - VAAPIEncodeH265Context *priv = ctx->priv_data; - VAAPIEncodeH265Slice *pslice; - VAAPIEncodeH265MiscSliceParams *mslice; int i; - slice->priv_data = av_mallocz(sizeof(*pslice)); - if (!slice->priv_data) - return AVERROR(ENOMEM); - pslice = slice->priv_data; - mslice = &pslice->misc_slice_params; - - // Currently we only support one slice per frame. - vslice->slice_segment_address = 0; - vslice->num_ctu_in_slice = priv->ctu_width * priv->ctu_height; - - switch (pic->type) { - case PICTURE_TYPE_IDR: - case PICTURE_TYPE_I: - vslice->slice_type = HEVC_SLICE_I; - break; - case PICTURE_TYPE_P: - vslice->slice_type = HEVC_SLICE_P; - break; - case PICTURE_TYPE_B: - vslice->slice_type = HEVC_SLICE_B; - break; - default: - av_assert0(0 && "invalid picture type"); - } - - vslice->slice_pic_parameter_set_id = vpic->slice_pic_parameter_set_id; - - pslice->pic_order_cnt = pic->display_order - priv->last_idr_frame; - - for (i = 0; i < FF_ARRAY_ELEMS(vslice->ref_pic_list0); i++) { - vslice->ref_pic_list0[i].picture_id = VA_INVALID_ID; - vslice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID; - vslice->ref_pic_list1[i].picture_id = VA_INVALID_ID; - vslice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID; - } - - av_assert0(pic->nb_refs <= 2); - if (pic->nb_refs >= 1) { - // Backward reference for P- or B-frame. - av_assert0(pic->type == PICTURE_TYPE_P || - pic->type == PICTURE_TYPE_B); - - vslice->num_ref_idx_l0_active_minus1 = 0; - vslice->ref_pic_list0[0] = vpic->reference_frames[0]; - } - if (pic->nb_refs >= 2) { - // Forward reference for B-frame. - av_assert0(pic->type == PICTURE_TYPE_B); - - vslice->num_ref_idx_l1_active_minus1 = 0; - vslice->ref_pic_list1[0] = vpic->reference_frames[1]; - } + sh->nal_unit_header = (H265RawNALUnitHeader) { + .nal_unit_type = priv->slice_nal_unit, + .nuh_layer_id = 0, + .nuh_temporal_id_plus1 = 1, + }; - vslice->max_num_merge_cand = 5; + sh->slice_pic_parameter_set_id = pps->pps_pic_parameter_set_id; - if (pic->type == PICTURE_TYPE_B) - vslice->slice_qp_delta = priv->fixed_qp_b - vpic->pic_init_qp; - else if (pic->type == PICTURE_TYPE_P) - vslice->slice_qp_delta = priv->fixed_qp_p - vpic->pic_init_qp; - else - vslice->slice_qp_delta = priv->fixed_qp_idr - vpic->pic_init_qp; + // Currently we only support one slice per frame. + sh->first_slice_segment_in_pic_flag = 1; + sh->slice_segment_address = 0; - vslice->slice_fields.bits.last_slice_of_pic_flag = 1; + sh->slice_type = priv->slice_type; - mslice->first_slice_segment_in_pic_flag = 1; + sh->slice_pic_order_cnt_lsb = priv->pic_order_cnt & + (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1; - if (pic->type == PICTURE_TYPE_IDR) { - // No reference pictures. - } else if (0) { - mslice->short_term_ref_pic_set_sps_flag = 1; - mslice->short_term_ref_pic_idx = 0; - } else { + if (pic->type != PICTURE_TYPE_IDR) { + H265RawSTRefPicSet *rps; VAAPIEncodePicture *st; int used; - mslice->short_term_ref_pic_set_sps_flag = 0; - mslice->st_ref_pic_set.inter_ref_pic_set_prediction_flag = 0; + sh->short_term_ref_pic_set_sps_flag = 0; + + rps = &sh->short_term_ref_pic_set; + memset(rps, 0, sizeof(*rps)); for (st = ctx->pic_start; st; st = st->next) { if (st->encode_order >= pic->encode_order) { @@ -1130,28 +661,111 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, used = 1; } if (!used) { - // Currently true, but need not be. - continue; + // Usually each picture always uses all of the others in the + // DPB as references. The one case we have to treat here is + // a non-IDR IRAP picture, which may need to hold unused + // references across itself to be used for the decoding of + // following RASL pictures. This looks for such an RASL + // picture, and keeps the reference if there is one. + VAAPIEncodePicture *rp; + for (rp = ctx->pic_start; rp; rp = rp->next) { + if (rp->encode_order < pic->encode_order) + continue; + if (rp->type != PICTURE_TYPE_B) + continue; + if (rp->refs[0] == st && rp->refs[1] == pic) + break; + } + if (!rp) + continue; } // This only works for one instance of each (delta_poc_sN_minus1 // is relative to the previous frame in the list, not relative to // the current frame directly). if (st->display_order < pic->display_order) { - i = mslice->st_ref_pic_set.num_negative_pics; - mslice->st_ref_pic_set.delta_poc_s0_minus1[i] = + rps->delta_poc_s0_minus1[rps->num_negative_pics] = pic->display_order - st->display_order - 1; - mslice->st_ref_pic_set.used_by_curr_pic_s0_flag[i] = used; - ++mslice->st_ref_pic_set.num_negative_pics; + rps->used_by_curr_pic_s0_flag[rps->num_negative_pics] = used; + ++rps->num_negative_pics; } else { - i = mslice->st_ref_pic_set.num_positive_pics; - mslice->st_ref_pic_set.delta_poc_s1_minus1[i] = + rps->delta_poc_s1_minus1[rps->num_positive_pics] = st->display_order - pic->display_order - 1; - mslice->st_ref_pic_set.used_by_curr_pic_s1_flag[i] = used; - ++mslice->st_ref_pic_set.num_positive_pics; + rps->used_by_curr_pic_s1_flag[rps->num_positive_pics] = used; + ++rps->num_positive_pics; } } + + sh->num_long_term_sps = 0; + sh->num_long_term_pics = 0; + + sh->slice_temporal_mvp_enabled_flag = + sps->sps_temporal_mvp_enabled_flag; + if (sh->slice_temporal_mvp_enabled_flag) { + sh->collocated_from_l0_flag = sh->slice_type == HEVC_SLICE_B; + sh->collocated_ref_idx = 0; + } + + sh->num_ref_idx_active_override_flag = 0; + sh->num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1; + sh->num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1; } + sh->slice_sao_luma_flag = sh->slice_sao_chroma_flag = + sps->sample_adaptive_offset_enabled_flag; + + if (pic->type == PICTURE_TYPE_B) + sh->slice_qp_delta = priv->fixed_qp_b - (pps->init_qp_minus26 + 26); + else if (pic->type == PICTURE_TYPE_P) + sh->slice_qp_delta = priv->fixed_qp_p - (pps->init_qp_minus26 + 26); + else + sh->slice_qp_delta = priv->fixed_qp_idr - (pps->init_qp_minus26 + 26); + + + *vslice = (VAEncSliceParameterBufferHEVC) { + .slice_segment_address = sh->slice_segment_address, + .num_ctu_in_slice = priv->ctu_width * priv->ctu_height, + + .slice_type = sh->slice_type, + .slice_pic_parameter_set_id = sh->slice_pic_parameter_set_id, + + .num_ref_idx_l0_active_minus1 = sh->num_ref_idx_l0_active_minus1, + .num_ref_idx_l1_active_minus1 = sh->num_ref_idx_l1_active_minus1, + .ref_pic_list0[0] = vpic->reference_frames[0], + .ref_pic_list1[0] = vpic->reference_frames[1], + + .luma_log2_weight_denom = sh->luma_log2_weight_denom, + .delta_chroma_log2_weight_denom = sh->delta_chroma_log2_weight_denom, + + .max_num_merge_cand = 5 - sh->five_minus_max_num_merge_cand, + + .slice_qp_delta = sh->slice_qp_delta, + .slice_cb_qp_offset = sh->slice_cb_qp_offset, + .slice_cr_qp_offset = sh->slice_cr_qp_offset, + + .slice_beta_offset_div2 = sh->slice_beta_offset_div2, + .slice_tc_offset_div2 = sh->slice_tc_offset_div2, + + .slice_fields.bits = { + .last_slice_of_pic_flag = 1, + .dependent_slice_segment_flag = sh->dependent_slice_segment_flag, + .colour_plane_id = sh->colour_plane_id, + .slice_temporal_mvp_enabled_flag = + sh->slice_temporal_mvp_enabled_flag, + .slice_sao_luma_flag = sh->slice_sao_luma_flag, + .slice_sao_chroma_flag = sh->slice_sao_chroma_flag, + .num_ref_idx_active_override_flag = + sh->num_ref_idx_active_override_flag, + .mvd_l1_zero_flag = sh->mvd_l1_zero_flag, + .cabac_init_flag = sh->cabac_init_flag, + .slice_deblocking_filter_disabled_flag = + sh->slice_deblocking_filter_disabled_flag, + .slice_loop_filter_across_slices_enabled_flag = + sh->slice_loop_filter_across_slices_enabled_flag, + .collocated_from_l0_flag = sh->collocated_from_l0_flag, + }, + }; + + return 0; } @@ -1160,6 +774,11 @@ static av_cold int vaapi_encode_h265_configure(AVCodecContext *avctx) VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH265Context *priv = ctx->priv_data; VAAPIEncodeH265Options *opt = ctx->codec_options; + int err; + + err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_HEVC, avctx); + if (err < 0) + return err; priv->ctu_width = FFALIGN(ctx->surface_width, 32) / 32; priv->ctu_height = FFALIGN(ctx->surface_height, 32) / 32; @@ -1271,6 +890,17 @@ static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx) return ff_vaapi_encode_init(avctx); } +static av_cold int vaapi_encode_h265_close(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = ctx->priv_data; + + if (priv) + ff_cbs_close(&priv->cbc); + + return ff_vaapi_encode_close(avctx); +} + #define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \ offsetof(VAAPIEncodeH265Options, x)) #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) @@ -1309,7 +939,7 @@ AVCodec ff_hevc_vaapi_encoder = { sizeof(VAAPIEncodeH265Options)), .init = &vaapi_encode_h265_init, .encode2 = &ff_vaapi_encode2, - .close = &ff_vaapi_encode_close, + .close = &vaapi_encode_h265_close, .priv_class = &vaapi_encode_h265_class, .capabilities = AV_CODEC_CAP_DELAY, .defaults = vaapi_encode_h265_defaults, diff --git a/libavcodec/vaapi_encode_h26x.c b/libavcodec/vaapi_encode_h26x.c deleted file mode 100644 index d806f9b52b354..0000000000000 --- a/libavcodec/vaapi_encode_h26x.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "vaapi_encode_h26x.h" - -int ff_vaapi_encode_h26x_nal_unit_to_byte_stream(uint8_t *dst, size_t *dst_bit_len, - uint8_t *src, size_t src_bit_len) -{ - size_t dp, sp; - int zero_run = 0; - size_t dst_len = *dst_bit_len / 8; - size_t src_len = (src_bit_len + 7) / 8; - int trailing_zeroes = src_len * 8 - src_bit_len; - - if (dst_len < src_len + 4) { - // Definitely doesn't fit. - goto fail; - } - - // Start code. - dst[0] = dst[1] = dst[2] = 0; - dst[3] = 1; - dp = 4; - - for (sp = 0; sp < src_len; sp++) { - if (dp >= dst_len) - goto fail; - if (zero_run < 2) { - if (src[sp] == 0) - ++zero_run; - else - zero_run = 0; - } else { - if ((src[sp] & ~3) == 0) { - // emulation_prevention_three_byte - dst[dp++] = 3; - if (dp >= dst_len) - goto fail; - } - zero_run = src[sp] == 0; - } - dst[dp++] = src[sp]; - } - - *dst_bit_len = 8 * dp - trailing_zeroes; - return 0; - -fail: - *dst_bit_len = 0; - return AVERROR(ENOSPC); -} diff --git a/libavcodec/vaapi_encode_h26x.h b/libavcodec/vaapi_encode_h26x.h deleted file mode 100644 index f8c6e13adb9b4..0000000000000 --- a/libavcodec/vaapi_encode_h26x.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVCODEC_VAAPI_ENCODE_H26X_H -#define AVCODEC_VAAPI_ENCODE_H26X_H - -#include -#include - -#include "golomb.h" -#include "put_bits.h" - - -// Debug code may be interested in the name of the syntax element being -// for tracing purposes. Here, it is just discarded. - -#define write_u(pbc, width, value, name) put_bits(pbc, width, value) -#define write_ue(pbc, value, name) set_ue_golomb(pbc, value) -#define write_se(pbc, value, name) set_se_golomb(pbc, value) - -#define u(width, ...) write_u(pbc, width, __VA_ARGS__) -#define ue(...) write_ue(pbc, __VA_ARGS__) -#define se(...) write_se(pbc, __VA_ARGS__) - - -// Copy from src to dst, applying emulation prevention. -int ff_vaapi_encode_h26x_nal_unit_to_byte_stream(uint8_t *dst, size_t *dst_len, - uint8_t *src, size_t src_len); - -#endif /* AVCODEC_VAAPI_ENCODE_H26X_H */ From 038a51258c4c5d8b77f4f9efcce6f397e5755c24 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 23 Jul 2017 23:22:54 +0100 Subject: [PATCH 0515/2557] vaapi_h265: Add support for AUD NAL units Matching the H.264 encoder. (cherry picked from commit e3e8eab359238486dc233f7aa89b7bb3cb19ec38) --- libavcodec/vaapi_encode_h265.c | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 4edd53a73c0e0..3ae92a7a09a24 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -42,6 +42,7 @@ typedef struct VAAPIEncodeH265Context { int fixed_qp_p; int fixed_qp_b; + H265RawAUD aud; H265RawVPS vps; H265RawSPS sps; H265RawPPS pps; @@ -52,13 +53,16 @@ typedef struct VAAPIEncodeH265Context { int slice_nal_unit; int slice_type; + int pic_type; CodedBitstreamContext *cbc; CodedBitstreamFragment current_access_unit; + int aud_needed; } VAAPIEncodeH265Context; typedef struct VAAPIEncodeH265Options { int qp; + int aud; } VAAPIEncodeH265Options; @@ -117,6 +121,13 @@ static int vaapi_encode_h265_write_sequence_header(AVCodecContext *avctx, CodedBitstreamFragment *au = &priv->current_access_unit; int err; + if (priv->aud_needed) { + err = vaapi_encode_h265_add_nal(avctx, au, &priv->aud); + if (err < 0) + goto fail; + priv->aud_needed = 0; + } + err = vaapi_encode_h265_add_nal(avctx, au, &priv->vps); if (err < 0) goto fail; @@ -145,6 +156,13 @@ static int vaapi_encode_h265_write_slice_header(AVCodecContext *avctx, CodedBitstreamFragment *au = &priv->current_access_unit; int err; + if (priv->aud_needed) { + err = vaapi_encode_h265_add_nal(avctx, au, &priv->aud); + if (err < 0) + goto fail; + priv->aud_needed = 0; + } + err = vaapi_encode_h265_add_nal(avctx, au, &priv->slice); if (err < 0) goto fail; @@ -519,6 +537,7 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx, { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH265Context *priv = ctx->priv_data; + VAAPIEncodeH265Options *opt = ctx->codec_options; VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; int i; @@ -529,16 +548,19 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx, priv->slice_nal_unit = HEVC_NAL_IDR_W_RADL; priv->slice_type = HEVC_SLICE_I; + priv->pic_type = 0; } else { av_assert0(pic->encode_order > priv->last_idr_frame); if (pic->type == PICTURE_TYPE_I) { priv->slice_nal_unit = HEVC_NAL_CRA_NUT; priv->slice_type = HEVC_SLICE_I; + priv->pic_type = 0; } else if (pic->type == PICTURE_TYPE_P) { av_assert0(pic->refs[0]); priv->slice_nal_unit = HEVC_NAL_TRAIL_R; priv->slice_type = HEVC_SLICE_P; + priv->pic_type = 1; } else { av_assert0(pic->refs[0] && pic->refs[1]); if (pic->refs[1]->type == PICTURE_TYPE_I) @@ -546,10 +568,23 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx, else priv->slice_nal_unit = HEVC_NAL_TRAIL_N; priv->slice_type = HEVC_SLICE_B; + priv->pic_type = 2; } } priv->pic_order_cnt = pic->display_order - priv->last_idr_frame; + if (opt->aud) { + priv->aud_needed = 1; + priv->aud.nal_unit_header = (H265RawNALUnitHeader) { + .nal_unit_type = HEVC_NAL_AUD, + .nuh_layer_id = 0, + .nuh_temporal_id_plus1 = 1, + }; + priv->aud.pic_type = priv->pic_type; + } else { + priv->aud_needed = 0; + } + vpic->decoded_curr_pic = (VAPictureHEVC) { .picture_id = pic->recon_surface, .pic_order_cnt = priv->pic_order_cnt, @@ -907,6 +942,10 @@ static av_cold int vaapi_encode_h265_close(AVCodecContext *avctx) static const AVOption vaapi_encode_h265_options[] = { { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)", OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 25 }, 0, 52, FLAGS }, + + { "aud", "Include AUD", + OFFSET(aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, + { NULL }, }; From d8928ad6b6e899c409129c8e16b225c09a8a5abb Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 24 Jun 2017 00:29:32 +0100 Subject: [PATCH 0516/2557] vaapi_mpeg2: Convert to use coded bitstream infrastructure (cherry picked from commit 10eb496d9ae94df6f792b0e1d8750738eb3a0952) --- configure | 2 +- libavcodec/vaapi_encode_mpeg2.c | 638 +++++++++++++++++++++----------- 2 files changed, 424 insertions(+), 216 deletions(-) diff --git a/configure b/configure index 7e244eea4dba3..8f4b339b5e1cc 100755 --- a/configure +++ b/configure @@ -2864,7 +2864,7 @@ mpeg2_qsv_decoder_select="qsvdec mpeg2_qsv_hwaccel" mpeg2_qsv_encoder_deps="libmfx" mpeg2_qsv_encoder_select="qsvenc" mpeg2_vaapi_encoder_deps="VAEncPictureParameterBufferMPEG2" -mpeg2_vaapi_encoder_select="vaapi_encode" +mpeg2_vaapi_encoder_select="cbs_mpeg2 vaapi_encode" mpeg2_v4l2m2m_decoder_deps="v4l2_m2m mpeg2_v4l2_m2m" mpeg4_crystalhd_decoder_select="crystalhd" mpeg4_cuvid_decoder_deps="cuda cuvid" diff --git a/libavcodec/vaapi_encode_mpeg2.c b/libavcodec/vaapi_encode_mpeg2.c index dc918884e89cc..02eca30dc5126 100644 --- a/libavcodec/vaapi_encode_mpeg2.c +++ b/libavcodec/vaapi_encode_mpeg2.c @@ -20,15 +20,11 @@ #include #include "libavutil/avassert.h" -#include "libavutil/common.h" -#include "libavutil/internal.h" -#include "libavutil/opt.h" -#include "libavutil/pixfmt.h" #include "avcodec.h" -#include "internal.h" -#include "mpegvideo.h" -#include "put_bits.h" +#include "cbs.h" +#include "cbs_mpeg2.h" +#include "mpeg12.h" #include "vaapi_encode.h" typedef struct VAAPIEncodeMPEG2Context { @@ -39,79 +35,104 @@ typedef struct VAAPIEncodeMPEG2Context { int quant_p; int quant_b; + MPEG2RawSequenceHeader sequence_header; + MPEG2RawExtensionData sequence_extension; + MPEG2RawExtensionData sequence_display_extension; + MPEG2RawGroupOfPicturesHeader gop_header; + MPEG2RawPictureHeader picture_header; + MPEG2RawExtensionData picture_coding_extension; + int64_t last_i_frame; unsigned int bit_rate; unsigned int vbv_buffer_size; + + AVRational frame_rate; + + unsigned int f_code_horizontal; + unsigned int f_code_vertical; + + CodedBitstreamContext *cbc; + CodedBitstreamFragment current_fragment; } VAAPIEncodeMPEG2Context; -#define vseq_var(name) vseq->name, name -#define vseqext_field(name) vseq->sequence_extension.bits.name, name -#define vgop_field(name) vseq->gop_header.bits.name, name -#define vpic_var(name) vpic->name, name -#define vpcext_field(name) vpic->picture_coding_extension.bits.name, name -#define vcomp_field(name) vpic->composite_display.bits.name, name +static int vaapi_encode_mpeg2_write_fragment(AVCodecContext *avctx, + char *data, size_t *data_len, + CodedBitstreamFragment *frag) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + int err; + + err = ff_cbs_write_fragment_data(priv->cbc, frag); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); + return err; + } + + if (*data_len < 8 * frag->data_size - frag->data_bit_padding) { + av_log(avctx, AV_LOG_ERROR, "Access unit too large: " + "%zu < %zu.\n", *data_len, + 8 * frag->data_size - frag->data_bit_padding); + return AVERROR(ENOSPC); + } + + memcpy(data, frag->data, frag->data_size); + *data_len = 8 * frag->data_size - frag->data_bit_padding; + + return 0; +} + +static int vaapi_encode_mpeg2_add_header(AVCodecContext *avctx, + CodedBitstreamFragment *frag, + int type, void *header) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + int err; + + err = ff_cbs_insert_unit_content(priv->cbc, frag, -1, type, header); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to add header: " + "type = %d.\n", type); + return err; + } -#define u2(width, value, name) put_bits(&pbc, width, value) -#define u(width, ...) u2(width, __VA_ARGS__) + return 0; +} static int vaapi_encode_mpeg2_write_sequence_header(AVCodecContext *avctx, char *data, size_t *data_len) { - VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncSequenceParameterBufferMPEG2 *vseq = ctx->codec_sequence_params; - VAAPIEncodeMPEG2Context *priv = ctx->priv_data; - PutBitContext pbc; - - init_put_bits(&pbc, data, 8 * *data_len); - - u(32, SEQ_START_CODE, sequence_header_code); - - u(12, vseq->picture_width, horizontal_size_value); - u(12, vseq->picture_height, vertical_size_value); - u(4, vseq_var(aspect_ratio_information)); - u(4, 8, frame_rate_code); - u(18, priv->bit_rate & 0x3fff, bit_rate_value); - u(1, 1, marker_bit); - u(10, priv->vbv_buffer_size & 0x3ff, vbv_buffer_size_value); - u(1, 0, constrained_parameters_flag); - u(1, 0, load_intra_quantiser_matrix); - // intra_quantiser_matrix[64] - u(1, 0, load_non_intra_quantiser_matrix); - // non_intra_quantiser_matrix[64] - - while (put_bits_count(&pbc) % 8) - u(1, 0, zero_bit); - - u(32, EXT_START_CODE, extension_start_code); - u(4, 1, extension_start_code_identifier); - u(8, vseqext_field(profile_and_level_indication)); - u(1, vseqext_field(progressive_sequence)); - u(2, vseqext_field(chroma_format)); - u(2, 0, horizontal_size_extension); - u(2, 0, vertical_size_extension); - u(12, priv->bit_rate >> 18, bit_rate_extension); - u(1, 1, marker_bit); - u(8, priv->vbv_buffer_size >> 10, vbv_buffer_size_extension); - u(1, vseqext_field(low_delay)); - u(2, vseqext_field(frame_rate_extension_n)); - u(2, vseqext_field(frame_rate_extension_d)); - - while (put_bits_count(&pbc) % 8) - u(1, 0, zero_bit); - - u(32, GOP_START_CODE, group_start_code); - u(25, vgop_field(time_code)); - u(1, vgop_field(closed_gop)); - u(1, vgop_field(broken_link)); - - while (put_bits_count(&pbc) % 8) - u(1, 0, zero_bit); - - *data_len = put_bits_count(&pbc); - flush_put_bits(&pbc); - + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + CodedBitstreamFragment *frag = &priv->current_fragment; + int err; + + err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_SEQUENCE_HEADER, + &priv->sequence_header); + if (err < 0) + goto fail; + + err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_EXTENSION, + &priv->sequence_extension); + if (err < 0) + goto fail; + + err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_EXTENSION, + &priv->sequence_display_extension); + if (err < 0) + goto fail; + + err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_GROUP, + &priv->gop_header); + if (err < 0) + goto fail; + + err = vaapi_encode_mpeg2_write_fragment(avctx, data, data_len, frag); +fail: + ff_cbs_fragment_uninit(priv->cbc, frag); return 0; } @@ -119,139 +140,275 @@ static int vaapi_encode_mpeg2_write_picture_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, char *data, size_t *data_len) { - VAEncPictureParameterBufferMPEG2 *vpic = pic->codec_picture_params; - int picture_coding_type; - PutBitContext pbc; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + CodedBitstreamFragment *frag = &priv->current_fragment; + int err; + + err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_PICTURE, + &priv->picture_header); + if (err < 0) + goto fail; + + err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_EXTENSION, + &priv->picture_coding_extension); + if (err < 0) + goto fail; + + err = vaapi_encode_mpeg2_write_fragment(avctx, data, data_len, frag); +fail: + ff_cbs_fragment_uninit(priv->cbc, frag); + return 0; +} - init_put_bits(&pbc, data, 8 * *data_len); +static int vaapi_encode_mpeg2_init_sequence_params(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + MPEG2RawSequenceHeader *sh = &priv->sequence_header; + MPEG2RawSequenceExtension *se = &priv->sequence_extension.data.sequence; + MPEG2RawSequenceDisplayExtension *sde = &priv->sequence_display_extension.data.sequence_display; + MPEG2RawGroupOfPicturesHeader *goph = &priv->gop_header; + MPEG2RawPictureHeader *ph = &priv->picture_header; + MPEG2RawPictureCodingExtension *pce = &priv->picture_coding_extension.data.picture_coding; + VAEncSequenceParameterBufferMPEG2 *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferMPEG2 *vpic = ctx->codec_picture_params; + int code, ext_n, ext_d; - u(32, PICTURE_START_CODE, picture_start_code); - u(10, vpic_var(temporal_reference)); + memset(sh, 0, sizeof(*sh)); + memset(se, 0, sizeof(*se)); + memset(sde, 0, sizeof(*sde)); + memset(goph, 0, sizeof(*goph)); + memset(ph, 0, sizeof(*ph)); + memset(pce, 0, sizeof(*pce)); - switch (vpic->picture_type) { - case VAEncPictureTypeIntra: - picture_coding_type = AV_PICTURE_TYPE_I; - break; - case VAEncPictureTypePredictive: - picture_coding_type = AV_PICTURE_TYPE_P; + + if (avctx->bit_rate > 0) { + priv->bit_rate = (avctx->bit_rate + 399) / 400; + } else { + // Unknown (not a bitrate-targetting mode), so just use the + // highest value. + priv->bit_rate = 0x3fffffff; + } + if (avctx->rc_buffer_size > 0) { + priv->vbv_buffer_size = (avctx->rc_buffer_size + (1 << 14) - 1) >> 14; + } else { + // Unknown, so guess a value from the bitrate. + priv->vbv_buffer_size = priv->bit_rate >> 14; + } + + switch (avctx->level) { + case 4: // High. + case 6: // High 1440. + priv->f_code_horizontal = 9; + priv->f_code_vertical = 5; break; - case VAEncPictureTypeBidirectional: - picture_coding_type = AV_PICTURE_TYPE_B; + case 8: // Main. + priv->f_code_horizontal = 8; + priv->f_code_vertical = 5; break; + case 10: // Low. default: - av_assert0(0 && "invalid picture_coding_type"); - } - u(3, picture_coding_type, picture_coding_type); - u(16, 0xffff, vbv_delay); - if (picture_coding_type == 2 || picture_coding_type == 3) { - u(1, 0, full_pel_forward_vector); - u(3, 7, forward_f_code); - } - if (picture_coding_type == 3) { - u(1, 0, full_pel_backward_vector); - u(3, 7, backward_f_code); + priv->f_code_horizontal = 7; + priv->f_code_vertical = 4; + break; } - u(1, 0, extra_bit_picture); - - while (put_bits_count(&pbc) % 8) - u(1, 0, zero_bit); - - u(32, EXT_START_CODE, extension_start_code); - u(4, 8, extension_start_code_identifier); - u(4, vpic_var(f_code[0][0])); - u(4, vpic_var(f_code[0][1])); - u(4, vpic_var(f_code[1][0])); - u(4, vpic_var(f_code[1][1])); - u(2, vpcext_field(intra_dc_precision)); - u(2, vpcext_field(picture_structure)); - u(1, vpcext_field(top_field_first)); - u(1, vpcext_field(frame_pred_frame_dct)); - u(1, vpcext_field(concealment_motion_vectors)); - u(1, vpcext_field(q_scale_type)); - u(1, vpcext_field(intra_vlc_format)); - u(1, vpcext_field(alternate_scan)); - u(1, vpcext_field(repeat_first_field)); - u(1, 1, chroma_420_type); - u(1, vpcext_field(progressive_frame)); - u(1, vpcext_field(composite_display_flag)); - if (vpic->picture_coding_extension.bits.composite_display_flag) { - u(1, vcomp_field(v_axis)); - u(3, vcomp_field(field_sequence)); - u(1, vcomp_field(sub_carrier)); - u(7, vcomp_field(burst_amplitude)); - u(8, vcomp_field(sub_carrier_phase)); + + + // Sequence header + + sh->sequence_header_code = MPEG2_START_SEQUENCE_HEADER; + + sh->horizontal_size_value = avctx->width & 0xfff; + sh->vertical_size_value = avctx->height & 0xfff; + + if (avctx->sample_aspect_ratio.num != 0 && + avctx->sample_aspect_ratio.den != 0) { + AVRational dar = av_div_q(avctx->sample_aspect_ratio, + (AVRational) { avctx->width, avctx->height }); + + if (av_cmp_q(avctx->sample_aspect_ratio, (AVRational) { 1, 1 }) == 0) { + sh->aspect_ratio_information = 1; + } else if (av_cmp_q(dar, (AVRational) { 3, 4 }) == 0) { + sh->aspect_ratio_information = 2; + } else if (av_cmp_q(dar, (AVRational) { 9, 16 }) == 0) { + sh->aspect_ratio_information = 3; + } else if (av_cmp_q(dar, (AVRational) { 100, 221 }) == 0) { + sh->aspect_ratio_information = 4; + } else { + av_log(avctx, AV_LOG_WARNING, "Sample aspect ratio %d:%d is not " + "representable, signalling square pixels instead.\n", + avctx->sample_aspect_ratio.num, + avctx->sample_aspect_ratio.den); + sh->aspect_ratio_information = 1; + } + } else { + // Unknown - assume square pixels. + sh->aspect_ratio_information = 1; } - while (put_bits_count(&pbc) % 8) - u(1, 0, zero_bit); + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) + priv->frame_rate = avctx->framerate; + else + priv->frame_rate = av_inv_q(avctx->time_base); + ff_mpeg12_find_best_frame_rate(priv->frame_rate, + &code, &ext_n, &ext_d, 0); + sh->frame_rate_code = code; - *data_len = put_bits_count(&pbc); - flush_put_bits(&pbc); + sh->bit_rate_value = priv->bit_rate & 0x3ffff; + sh->vbv_buffer_size_value = priv->vbv_buffer_size & 0x3ff; - return 0; -} + sh->constrained_parameters_flag = 0; + sh->load_intra_quantiser_matrix = 0; + sh->load_non_intra_quantiser_matrix = 0; -static int vaapi_encode_mpeg2_init_sequence_params(AVCodecContext *avctx) -{ - VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncSequenceParameterBufferMPEG2 *vseq = ctx->codec_sequence_params; - VAEncPictureParameterBufferMPEG2 *vpic = ctx->codec_picture_params; - VAAPIEncodeMPEG2Context *priv = ctx->priv_data; - vseq->intra_period = avctx->gop_size; - vseq->ip_period = ctx->b_per_p + 1; + // Sequence extension - vseq->picture_width = avctx->width; - vseq->picture_height = avctx->height; + priv->sequence_extension.extension_start_code = MPEG2_START_EXTENSION; + priv->sequence_extension.extension_start_code_identifier = + MPEG2_EXTENSION_SEQUENCE; - vseq->bits_per_second = avctx->bit_rate; - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) - vseq->frame_rate = (float)avctx->framerate.num / avctx->framerate.den; - else - vseq->frame_rate = (float)avctx->time_base.den / avctx->time_base.num; - - vseq->aspect_ratio_information = 1; - vseq->vbv_buffer_size = avctx->rc_buffer_size / (16 * 1024); - - vseq->sequence_extension.bits.profile_and_level_indication = - avctx->profile << 4 | avctx->level; - vseq->sequence_extension.bits.progressive_sequence = 1; - vseq->sequence_extension.bits.chroma_format = 1; - vseq->sequence_extension.bits.low_delay = 0; - vseq->sequence_extension.bits.frame_rate_extension_n = 0; - vseq->sequence_extension.bits.frame_rate_extension_d = 0; - - vseq->new_gop_header = 0; - vseq->gop_header.bits.time_code = 0; - vseq->gop_header.bits.closed_gop = 1; - vseq->gop_header.bits.broken_link = 0; - - vpic->forward_reference_picture = VA_INVALID_ID; - vpic->backward_reference_picture = VA_INVALID_ID; - vpic->reconstructed_picture = VA_INVALID_ID; - - vpic->coded_buf = VA_INVALID_ID; - - vpic->temporal_reference = 0; - vpic->f_code[0][0] = 15; - vpic->f_code[0][1] = 15; - vpic->f_code[1][0] = 15; - vpic->f_code[1][1] = 15; - - vpic->picture_coding_extension.bits.intra_dc_precision = 0; - vpic->picture_coding_extension.bits.picture_structure = 3; - vpic->picture_coding_extension.bits.top_field_first = 0; - vpic->picture_coding_extension.bits.frame_pred_frame_dct = 1; - vpic->picture_coding_extension.bits.concealment_motion_vectors = 0; - vpic->picture_coding_extension.bits.q_scale_type = 0; - vpic->picture_coding_extension.bits.intra_vlc_format = 0; - vpic->picture_coding_extension.bits.alternate_scan = 0; - vpic->picture_coding_extension.bits.repeat_first_field = 0; - vpic->picture_coding_extension.bits.progressive_frame = 1; - vpic->picture_coding_extension.bits.composite_display_flag = 0; - - priv->bit_rate = (avctx->bit_rate + 399) / 400; - priv->vbv_buffer_size = avctx->rc_buffer_size / (16 * 1024); + se->profile_and_level_indication = avctx->profile << 4 | avctx->level; + se->progressive_sequence = 1; + se->chroma_format = 1; + + se->horizontal_size_extension = avctx->width >> 12; + se->vertical_size_extension = avctx->height >> 12; + + se->bit_rate_extension = priv->bit_rate >> 18; + se->vbv_buffer_size_extension = priv->vbv_buffer_size >> 10; + se->low_delay = ctx->b_per_p == 0; + + se->frame_rate_extension_n = ext_n; + se->frame_rate_extension_d = ext_d; + + + // Sequence display extension + + priv->sequence_display_extension.extension_start_code = + MPEG2_START_EXTENSION; + priv->sequence_display_extension.extension_start_code_identifier = + MPEG2_EXTENSION_SEQUENCE_DISPLAY; + + sde->video_format = 5; + if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED || + avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { + sde->colour_description = 1; + sde->colour_primaries = avctx->color_primaries; + sde->transfer_characteristics = avctx->color_trc; + sde->matrix_coefficients = avctx->colorspace; + } else { + sde->colour_description = 0; + } + + sde->display_horizontal_size = avctx->width; + sde->display_vertical_size = avctx->height; + + + // GOP header + + goph->group_start_code = MPEG2_START_GROUP; + + goph->time_code = 0; + goph->closed_gop = 1; + goph->broken_link = 0; + + + // Defaults for picture header + + ph->picture_start_code = MPEG2_START_PICTURE; + + ph->vbv_delay = 0xffff; // Not currently calculated. + + ph->full_pel_forward_vector = 0; + ph->forward_f_code = 7; + ph->full_pel_backward_vector = 0; + ph->forward_f_code = 7; + + + // Defaults for picture coding extension + + priv->picture_coding_extension.extension_start_code = + MPEG2_START_EXTENSION; + priv->picture_coding_extension.extension_start_code_identifier = + MPEG2_EXTENSION_PICTURE_CODING; + + pce->intra_dc_precision = 0; + pce->picture_structure = 3; + pce->top_field_first = 0; + pce->frame_pred_frame_dct = 1; + pce->concealment_motion_vectors = 0; + pce->q_scale_type = 0; + pce->intra_vlc_format = 0; + pce->alternate_scan = 0; + pce->repeat_first_field = 0; + pce->progressive_frame = 1; + pce->composite_display_flag = 0; + + + + *vseq = (VAEncSequenceParameterBufferMPEG2) { + .intra_period = avctx->gop_size, + .ip_period = ctx->b_per_p + 1, + + .picture_width = avctx->width, + .picture_height = avctx->height, + + .bits_per_second = avctx->bit_rate, + .frame_rate = av_q2d(priv->frame_rate), + .aspect_ratio_information = sh->aspect_ratio_information, + .vbv_buffer_size = priv->vbv_buffer_size, + + .sequence_extension.bits = { + .profile_and_level_indication = se->profile_and_level_indication, + .progressive_sequence = se->progressive_sequence, + .chroma_format = se->chroma_format, + .low_delay = se->low_delay, + .frame_rate_extension_n = se->frame_rate_extension_n, + .frame_rate_extension_d = se->frame_rate_extension_d, + }, + + .new_gop_header = 1, + .gop_header.bits = { + .time_code = goph->time_code, + .closed_gop = goph->closed_gop, + .broken_link = goph->broken_link, + }, + }; + + *vpic = (VAEncPictureParameterBufferMPEG2) { + .forward_reference_picture = VA_INVALID_ID, + .backward_reference_picture = VA_INVALID_ID, + .reconstructed_picture = VA_INVALID_ID, + .coded_buf = VA_INVALID_ID, + + .vbv_delay = 0xffff, + .f_code = { { 15, 15 }, { 15, 15 } }, + + .picture_coding_extension.bits = { + .intra_dc_precision = pce->intra_dc_precision, + .picture_structure = pce->picture_structure, + .top_field_first = pce->top_field_first, + .frame_pred_frame_dct = pce->frame_pred_frame_dct, + .concealment_motion_vectors = pce->concealment_motion_vectors, + .q_scale_type = pce->q_scale_type, + .intra_vlc_format = pce->intra_vlc_format, + .alternate_scan = pce->alternate_scan, + .repeat_first_field = pce->repeat_first_field, + .progressive_frame = pce->progressive_frame, + .composite_display_flag = pce->composite_display_flag, + }, + + .composite_display.bits = { + .v_axis = pce->v_axis, + .field_sequence = pce->field_sequence, + .sub_carrier = pce->sub_carrier, + .burst_amplitude = pce->burst_amplitude, + .sub_carrier_phase = pce->sub_carrier_phase, + }, + }; return 0; } @@ -260,56 +417,61 @@ static int vaapi_encode_mpeg2_init_picture_params(AVCodecContext *avctx, VAAPIEncodePicture *pic) { VAAPIEncodeContext *ctx = avctx->priv_data; - VAEncPictureParameterBufferMPEG2 *vpic = pic->codec_picture_params; VAAPIEncodeMPEG2Context *priv = ctx->priv_data; - int fch, fcv; + MPEG2RawPictureHeader *ph = &priv->picture_header; + MPEG2RawPictureCodingExtension *pce = &priv->picture_coding_extension.data.picture_coding; + VAEncPictureParameterBufferMPEG2 *vpic = pic->codec_picture_params; - switch (avctx->level) { - case 4: // High. - case 6: // High 1440. - fch = 9; - fcv = 5; - break; - case 8: // Main. - fch = 8; - fcv = 5; - break; - case 10: // Low. - default: - fch = 7; - fcv = 4; - break; + if (pic->type == PICTURE_TYPE_IDR || pic->type == PICTURE_TYPE_I) { + ph->temporal_reference = 0; + ph->picture_coding_type = 1; + priv->last_i_frame = pic->display_order; + } else { + ph->temporal_reference = pic->display_order - priv->last_i_frame; + ph->picture_coding_type = pic->type == PICTURE_TYPE_B ? 3 : 2; + } + + if (pic->type == PICTURE_TYPE_P || pic->type == PICTURE_TYPE_B) { + pce->f_code[0][0] = priv->f_code_horizontal; + pce->f_code[0][1] = priv->f_code_vertical; + } else { + pce->f_code[0][0] = 15; + pce->f_code[0][1] = 15; + } + if (pic->type == PICTURE_TYPE_B) { + pce->f_code[1][0] = priv->f_code_horizontal; + pce->f_code[1][1] = priv->f_code_vertical; + } else { + pce->f_code[1][0] = 15; + pce->f_code[1][1] = 15; } + vpic->reconstructed_picture = pic->recon_surface; + vpic->coded_buf = pic->output_buffer; + switch (pic->type) { case PICTURE_TYPE_IDR: case PICTURE_TYPE_I: vpic->picture_type = VAEncPictureTypeIntra; - priv->last_i_frame = pic->display_order; break; case PICTURE_TYPE_P: vpic->picture_type = VAEncPictureTypePredictive; vpic->forward_reference_picture = pic->refs[0]->recon_surface; - vpic->f_code[0][0] = fch; - vpic->f_code[0][1] = fcv; break; case PICTURE_TYPE_B: vpic->picture_type = VAEncPictureTypeBidirectional; vpic->forward_reference_picture = pic->refs[0]->recon_surface; vpic->backward_reference_picture = pic->refs[1]->recon_surface; - vpic->f_code[0][0] = fch; - vpic->f_code[0][1] = fcv; - vpic->f_code[1][0] = fch; - vpic->f_code[1][1] = fcv; break; default: av_assert0(0 && "invalid picture type"); } - vpic->reconstructed_picture = pic->recon_surface; - vpic->coded_buf = pic->output_buffer; - - vpic->temporal_reference = pic->display_order - priv->last_i_frame; + vpic->temporal_reference = ph->temporal_reference; + vpic->f_code[0][0] = pce->f_code[0][0]; + vpic->f_code[0][1] = pce->f_code[0][1]; + vpic->f_code[1][0] = pce->f_code[1][0]; + vpic->f_code[1][1] = pce->f_code[1][1]; pic->nb_slices = priv->mb_height; @@ -354,6 +516,11 @@ static av_cold int vaapi_encode_mpeg2_configure(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + int err; + + err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_MPEG2VIDEO, avctx); + if (err < 0) + return err; priv->mb_width = FFALIGN(avctx->width, 16) / 16; priv->mb_height = FFALIGN(avctx->height, 16) / 16; @@ -420,11 +587,41 @@ static av_cold int vaapi_encode_mpeg2_init(AVCodecContext *avctx) case FF_PROFILE_MPEG2_MAIN: ctx->va_profile = VAProfileMPEG2Main; break; + case FF_PROFILE_MPEG2_422: + av_log(avctx, AV_LOG_ERROR, "MPEG-2 4:2:2 profile " + "is not supported.\n"); + return AVERROR_PATCHWELCOME; + case FF_PROFILE_MPEG2_HIGH: + av_log(avctx, AV_LOG_ERROR, "MPEG-2 high profile " + "is not supported.\n"); + return AVERROR_PATCHWELCOME; + case FF_PROFILE_MPEG2_SS: + case FF_PROFILE_MPEG2_SNR_SCALABLE: + av_log(avctx, AV_LOG_ERROR, "MPEG-2 scalable profiles " + "are not supported.\n"); + return AVERROR_PATCHWELCOME; default: av_log(avctx, AV_LOG_ERROR, "Unknown MPEG-2 profile %d.\n", avctx->profile); return AVERROR(EINVAL); } + switch (avctx->level) { + case 4: // High + case 6: // High 1440 + case 8: // Main + case 10: // Low + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown MPEG-2 level %d.\n", + avctx->level); + return AVERROR(EINVAL); + } + + if (avctx->height % 4096 == 0 || avctx->width % 4096 == 0) { + av_log(avctx, AV_LOG_ERROR, "MPEG-2 does not support picture " + "height or width divisible by 4096.\n"); + return AVERROR(EINVAL); + } ctx->va_entrypoint = VAEntrypointEncSlice; ctx->va_rt_format = VA_RT_FORMAT_YUV420; @@ -439,6 +636,17 @@ static av_cold int vaapi_encode_mpeg2_init(AVCodecContext *avctx) return ff_vaapi_encode_init(avctx); } +static av_cold int vaapi_encode_mpeg2_close(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeMPEG2Context *priv = ctx->priv_data; + + if (priv) + ff_cbs_close(&priv->cbc); + + return ff_vaapi_encode_close(avctx); +} + static const AVCodecDefault vaapi_encode_mpeg2_defaults[] = { { "profile", "4" }, { "level", "4" }, @@ -460,7 +668,7 @@ AVCodec ff_mpeg2_vaapi_encoder = { .priv_data_size = sizeof(VAAPIEncodeContext), .init = &vaapi_encode_mpeg2_init, .encode2 = &ff_vaapi_encode2, - .close = &ff_vaapi_encode_close, + .close = &vaapi_encode_mpeg2_close, .capabilities = AV_CODEC_CAP_DELAY, .defaults = vaapi_encode_mpeg2_defaults, .pix_fmts = (const enum AVPixelFormat[]) { From 809b0402dc916b876dfdd6bb9c88f171cf3e77c0 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 15 Aug 2017 18:14:32 +0100 Subject: [PATCH 0517/2557] cbs: Add some read/write tests Use the appropriate metadata filter for each codec - in the absence of any options to modify the stream, the output bitstream should be identical to the input (though the output file may differ in padding). All tests use conformance bitstreams, the MPEG-2 streams are newly added from the conformance test streams (cherry picked from commit 3cae7f8b9baaf43789490b676d8f5825f2e1bc2c) (cherry picked from commit fbd63170bcbc5cad8965edad7c357f6eb4132250) --- tests/Makefile | 1 + tests/fate/cbs.mak | 79 +++++++++++++++++++ tests/ref/fate/cbs-h264-AUD_MW_E | 1 + tests/ref/fate/cbs-h264-BASQP1_Sony_C | 1 + tests/ref/fate/cbs-h264-CABACI3_Sony_B | 1 + tests/ref/fate/cbs-h264-CVBS3_Sony_C | 1 + tests/ref/fate/cbs-h264-CVFC1_Sony_C | 1 + tests/ref/fate/cbs-h264-CVMANL1_TOSHIBA_B | 1 + tests/ref/fate/cbs-h264-CVNLFI1_Sony_C | 1 + tests/ref/fate/cbs-h264-CVSE2_Sony_B | 1 + tests/ref/fate/cbs-h264-CVWP1_TOSHIBA_E | 1 + tests/ref/fate/cbs-h264-FM1_BT_B | 1 + tests/ref/fate/cbs-h264-MR1_BT_A | 1 + tests/ref/fate/cbs-h264-SVA_Base_B | 1 + tests/ref/fate/cbs-h264-Sharp_MP_PAFF_1r2 | 1 + tests/ref/fate/cbs-h264-sp1_bt_a | 1 + tests/ref/fate/cbs-hevc-CAINIT_E_SHARP_3 | 1 + tests/ref/fate/cbs-hevc-CAINIT_H_SHARP_3 | 1 + tests/ref/fate/cbs-hevc-CONFWIN_A_Sony_1 | 1 + tests/ref/fate/cbs-hevc-HRD_A_Fujitsu_2 | 1 + tests/ref/fate/cbs-hevc-LTRPSPS_A_Qualcomm_1 | 1 + tests/ref/fate/cbs-hevc-NUT_A_ericsson_5 | 1 + tests/ref/fate/cbs-hevc-PICSIZE_A_Bossen_1 | 1 + tests/ref/fate/cbs-hevc-PICSIZE_B_Bossen_1 | 1 + tests/ref/fate/cbs-hevc-RPLM_A_qualcomm_4 | 1 + tests/ref/fate/cbs-hevc-RPS_A_docomo_4 | 1 + tests/ref/fate/cbs-hevc-RPS_E_qualcomm_5 | 1 + tests/ref/fate/cbs-hevc-SLIST_A_Sony_4 | 1 + tests/ref/fate/cbs-hevc-SLIST_D_Sony_9 | 1 + tests/ref/fate/cbs-hevc-STRUCT_A_Samsung_5 | 1 + tests/ref/fate/cbs-hevc-TILES_B_Cisco_1 | 1 + tests/ref/fate/cbs-hevc-WPP_A_ericsson_MAIN_2 | 1 + tests/ref/fate/cbs-hevc-WPP_F_ericsson_MAIN_2 | 1 + tests/ref/fate/cbs-hevc-WP_A_Toshiba_3 | 1 + tests/ref/fate/cbs-hevc-ipcm_E_NEC_2 | 1 + tests/ref/fate/cbs-mpeg2-hhi_burst_422_short | 1 + tests/ref/fate/cbs-mpeg2-sony-ct3 | 1 + tests/ref/fate/cbs-mpeg2-tcela-6 | 1 + 38 files changed, 116 insertions(+) create mode 100644 tests/fate/cbs.mak create mode 100644 tests/ref/fate/cbs-h264-AUD_MW_E create mode 100644 tests/ref/fate/cbs-h264-BASQP1_Sony_C create mode 100644 tests/ref/fate/cbs-h264-CABACI3_Sony_B create mode 100644 tests/ref/fate/cbs-h264-CVBS3_Sony_C create mode 100644 tests/ref/fate/cbs-h264-CVFC1_Sony_C create mode 100644 tests/ref/fate/cbs-h264-CVMANL1_TOSHIBA_B create mode 100644 tests/ref/fate/cbs-h264-CVNLFI1_Sony_C create mode 100644 tests/ref/fate/cbs-h264-CVSE2_Sony_B create mode 100644 tests/ref/fate/cbs-h264-CVWP1_TOSHIBA_E create mode 100644 tests/ref/fate/cbs-h264-FM1_BT_B create mode 100644 tests/ref/fate/cbs-h264-MR1_BT_A create mode 100644 tests/ref/fate/cbs-h264-SVA_Base_B create mode 100644 tests/ref/fate/cbs-h264-Sharp_MP_PAFF_1r2 create mode 100644 tests/ref/fate/cbs-h264-sp1_bt_a create mode 100644 tests/ref/fate/cbs-hevc-CAINIT_E_SHARP_3 create mode 100644 tests/ref/fate/cbs-hevc-CAINIT_H_SHARP_3 create mode 100644 tests/ref/fate/cbs-hevc-CONFWIN_A_Sony_1 create mode 100644 tests/ref/fate/cbs-hevc-HRD_A_Fujitsu_2 create mode 100644 tests/ref/fate/cbs-hevc-LTRPSPS_A_Qualcomm_1 create mode 100644 tests/ref/fate/cbs-hevc-NUT_A_ericsson_5 create mode 100644 tests/ref/fate/cbs-hevc-PICSIZE_A_Bossen_1 create mode 100644 tests/ref/fate/cbs-hevc-PICSIZE_B_Bossen_1 create mode 100644 tests/ref/fate/cbs-hevc-RPLM_A_qualcomm_4 create mode 100644 tests/ref/fate/cbs-hevc-RPS_A_docomo_4 create mode 100644 tests/ref/fate/cbs-hevc-RPS_E_qualcomm_5 create mode 100644 tests/ref/fate/cbs-hevc-SLIST_A_Sony_4 create mode 100644 tests/ref/fate/cbs-hevc-SLIST_D_Sony_9 create mode 100644 tests/ref/fate/cbs-hevc-STRUCT_A_Samsung_5 create mode 100644 tests/ref/fate/cbs-hevc-TILES_B_Cisco_1 create mode 100644 tests/ref/fate/cbs-hevc-WPP_A_ericsson_MAIN_2 create mode 100644 tests/ref/fate/cbs-hevc-WPP_F_ericsson_MAIN_2 create mode 100644 tests/ref/fate/cbs-hevc-WP_A_Toshiba_3 create mode 100644 tests/ref/fate/cbs-hevc-ipcm_E_NEC_2 create mode 100644 tests/ref/fate/cbs-mpeg2-hhi_burst_422_short create mode 100644 tests/ref/fate/cbs-mpeg2-sony-ct3 create mode 100644 tests/ref/fate/cbs-mpeg2-tcela-6 diff --git a/tests/Makefile b/tests/Makefile index 656c2c59c528d..fd3713fe81f50 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -115,6 +115,7 @@ include $(SRC_PATH)/tests/fate/audio.mak include $(SRC_PATH)/tests/fate/bmp.mak include $(SRC_PATH)/tests/fate/build.mak include $(SRC_PATH)/tests/fate/canopus.mak +include $(SRC_PATH)/tests/fate/cbs.mak include $(SRC_PATH)/tests/fate/cdxl.mak include $(SRC_PATH)/tests/fate/checkasm.mak include $(SRC_PATH)/tests/fate/concatdec.mak diff --git a/tests/fate/cbs.mak b/tests/fate/cbs.mak new file mode 100644 index 0000000000000..fc5967e6f37df --- /dev/null +++ b/tests/fate/cbs.mak @@ -0,0 +1,79 @@ +# Read/write tests: this uses the codec metadata filter - with no +# arguments, it decomposes the stream fully and then recomposes it +# without making any changes. + +fate-cbs: fate-cbs-h264 fate-cbs-hevc fate-cbs-mpeg2 + +FATE_CBS_DEPS = $(call ALLYES, $(1)_DEMUXER $(1)_PARSER $(2)_METADATA_BSF $(3)_DECODER $(3)_MUXER) + +define FATE_CBS_TEST +# (codec, test_name, sample_file, output_format) +FATE_CBS_$(1) += fate-cbs-$(1)-$(2) +fate-cbs-$(1)-$(2): CMD = md5 -i $(TARGET_SAMPLES)/$(3) -c:v copy -bsf:v $(1)_metadata -f $(4) +endef + +# H.264 read/write + +FATE_CBS_H264_SAMPLES = \ + SVA_Base_B.264 \ + BASQP1_Sony_C.jsv \ + FM1_BT_B.h264 \ + CVFC1_Sony_C.jsv \ + AUD_MW_E.264 \ + CVBS3_Sony_C.jsv \ + MR1_BT_A.h264 \ + CVWP1_TOSHIBA_E.264 \ + CVNLFI1_Sony_C.jsv \ + Sharp_MP_PAFF_1r2.jvt \ + CVMANL1_TOSHIBA_B.264 \ + sp1_bt_a.h264 \ + CVSE2_Sony_B.jsv \ + CABACI3_Sony_B.jsv + +$(foreach N,$(FATE_CBS_H264_SAMPLES),$(eval $(call FATE_CBS_TEST,h264,$(basename $(N)),h264-conformance/$(N),h264))) + +FATE_CBS_H264-$(call FATE_CBS_DEPS, H264, H264, H264) = $(FATE_CBS_h264) +FATE_SAMPLES_AVCONV += $(FATE_CBS_H264-yes) +fate-cbs-h264: $(FATE_CBS_H264-yes) + +# H.265 read/write + +FATE_CBS_HEVC_SAMPLES = \ + STRUCT_A_Samsung_5.bit \ + WP_A_Toshiba_3.bit \ + SLIST_A_Sony_4.bit \ + SLIST_D_Sony_9.bit \ + CAINIT_E_SHARP_3.bit \ + CAINIT_H_SHARP_3.bit \ + TILES_B_Cisco_1.bit \ + WPP_A_ericsson_MAIN_2.bit \ + WPP_F_ericsson_MAIN_2.bit \ + ipcm_E_NEC_2.bit \ + NUT_A_ericsson_5.bit \ + PICSIZE_A_Bossen_1.bit \ + PICSIZE_B_Bossen_1.bit \ + RPS_A_docomo_4.bit \ + RPS_E_qualcomm_5.bit \ + LTRPSPS_A_Qualcomm_1.bit \ + RPLM_A_qualcomm_4.bit \ + CONFWIN_A_Sony_1.bit \ + HRD_A_Fujitsu_2.bit + +$(foreach N,$(FATE_CBS_HEVC_SAMPLES),$(eval $(call FATE_CBS_TEST,hevc,$(basename $(N)),hevc-conformance/$(N),hevc))) + +FATE_CBS_HEVC-$(call FATE_CBS_DEPS, HEVC, HEVC, HEVC) = $(FATE_CBS_hevc) +FATE_SAMPLES_AVCONV += $(FATE_CBS_HEVC-yes) +fate-cbs-hevc: $(FATE_CBS_HEVC-yes) + +# MPEG-2 read/write + +FATE_CBS_MPEG2_SAMPLES = \ + hhi_burst_422_short.bits \ + sony-ct3.bs \ + tcela-6.bits + +$(foreach N,$(FATE_CBS_MPEG2_SAMPLES),$(eval $(call FATE_CBS_TEST,mpeg2,$(basename $(N)),mpeg2/$(N),mpeg2video))) + +FATE_CBS_MPEG2-$(call FATE_CBS_DEPS, MPEGVIDEO, MPEG2, MPEG2VIDEO) = $(FATE_CBS_mpeg2) +FATE_SAMPLES_AVCONV += $(FATE_CBS_MPEG2-yes) +fate-cbs-mpeg2: $(FATE_CBS_MPEG2-yes) diff --git a/tests/ref/fate/cbs-h264-AUD_MW_E b/tests/ref/fate/cbs-h264-AUD_MW_E new file mode 100644 index 0000000000000..f204792416260 --- /dev/null +++ b/tests/ref/fate/cbs-h264-AUD_MW_E @@ -0,0 +1 @@ +9b8884667eda0b9853bec631458686ce diff --git a/tests/ref/fate/cbs-h264-BASQP1_Sony_C b/tests/ref/fate/cbs-h264-BASQP1_Sony_C new file mode 100644 index 0000000000000..c2185c770b08a --- /dev/null +++ b/tests/ref/fate/cbs-h264-BASQP1_Sony_C @@ -0,0 +1 @@ +00c52ae60bf9a41ae1145fbf5fea9838 diff --git a/tests/ref/fate/cbs-h264-CABACI3_Sony_B b/tests/ref/fate/cbs-h264-CABACI3_Sony_B new file mode 100644 index 0000000000000..59aeb721555ff --- /dev/null +++ b/tests/ref/fate/cbs-h264-CABACI3_Sony_B @@ -0,0 +1 @@ +2d94c80b858aec880530bad47afe3668 diff --git a/tests/ref/fate/cbs-h264-CVBS3_Sony_C b/tests/ref/fate/cbs-h264-CVBS3_Sony_C new file mode 100644 index 0000000000000..55f5e0b50e53a --- /dev/null +++ b/tests/ref/fate/cbs-h264-CVBS3_Sony_C @@ -0,0 +1 @@ +59ff1df9b25e80277cad4ad99e634df6 diff --git a/tests/ref/fate/cbs-h264-CVFC1_Sony_C b/tests/ref/fate/cbs-h264-CVFC1_Sony_C new file mode 100644 index 0000000000000..98004cf63c904 --- /dev/null +++ b/tests/ref/fate/cbs-h264-CVFC1_Sony_C @@ -0,0 +1 @@ +669f4f3d3ae35fa5a6f5c94e48776dcf diff --git a/tests/ref/fate/cbs-h264-CVMANL1_TOSHIBA_B b/tests/ref/fate/cbs-h264-CVMANL1_TOSHIBA_B new file mode 100644 index 0000000000000..14aa45300d839 --- /dev/null +++ b/tests/ref/fate/cbs-h264-CVMANL1_TOSHIBA_B @@ -0,0 +1 @@ +0c1d9694df747cc4697caf866bd3051a diff --git a/tests/ref/fate/cbs-h264-CVNLFI1_Sony_C b/tests/ref/fate/cbs-h264-CVNLFI1_Sony_C new file mode 100644 index 0000000000000..d5f5ad1931a3b --- /dev/null +++ b/tests/ref/fate/cbs-h264-CVNLFI1_Sony_C @@ -0,0 +1 @@ +7817d89bd749bc617a225978958a3af0 diff --git a/tests/ref/fate/cbs-h264-CVSE2_Sony_B b/tests/ref/fate/cbs-h264-CVSE2_Sony_B new file mode 100644 index 0000000000000..7845723edd80c --- /dev/null +++ b/tests/ref/fate/cbs-h264-CVSE2_Sony_B @@ -0,0 +1 @@ +ca8bdba497bd2f3b97c50d59692eb537 diff --git a/tests/ref/fate/cbs-h264-CVWP1_TOSHIBA_E b/tests/ref/fate/cbs-h264-CVWP1_TOSHIBA_E new file mode 100644 index 0000000000000..4cb9c475fcfbb --- /dev/null +++ b/tests/ref/fate/cbs-h264-CVWP1_TOSHIBA_E @@ -0,0 +1 @@ +01290611165b8d8ccba8468f3dae4c4d diff --git a/tests/ref/fate/cbs-h264-FM1_BT_B b/tests/ref/fate/cbs-h264-FM1_BT_B new file mode 100644 index 0000000000000..862de950de28e --- /dev/null +++ b/tests/ref/fate/cbs-h264-FM1_BT_B @@ -0,0 +1 @@ +f7d5474ec576eea3f70d83a26a641a60 diff --git a/tests/ref/fate/cbs-h264-MR1_BT_A b/tests/ref/fate/cbs-h264-MR1_BT_A new file mode 100644 index 0000000000000..0532652e6cfc8 --- /dev/null +++ b/tests/ref/fate/cbs-h264-MR1_BT_A @@ -0,0 +1 @@ +699d37e66764ddb3b4265c299ca77dcd diff --git a/tests/ref/fate/cbs-h264-SVA_Base_B b/tests/ref/fate/cbs-h264-SVA_Base_B new file mode 100644 index 0000000000000..a591b811b12f8 --- /dev/null +++ b/tests/ref/fate/cbs-h264-SVA_Base_B @@ -0,0 +1 @@ +443e55dd5f63dccf9a62acbb48451b08 diff --git a/tests/ref/fate/cbs-h264-Sharp_MP_PAFF_1r2 b/tests/ref/fate/cbs-h264-Sharp_MP_PAFF_1r2 new file mode 100644 index 0000000000000..cc7d63931c79a --- /dev/null +++ b/tests/ref/fate/cbs-h264-Sharp_MP_PAFF_1r2 @@ -0,0 +1 @@ +fd01840ed6b086c3118b7c53c86d01f5 diff --git a/tests/ref/fate/cbs-h264-sp1_bt_a b/tests/ref/fate/cbs-h264-sp1_bt_a new file mode 100644 index 0000000000000..388c53aa5e756 --- /dev/null +++ b/tests/ref/fate/cbs-h264-sp1_bt_a @@ -0,0 +1 @@ +8405c5583d31d7015ed401b34b4ec93c diff --git a/tests/ref/fate/cbs-hevc-CAINIT_E_SHARP_3 b/tests/ref/fate/cbs-hevc-CAINIT_E_SHARP_3 new file mode 100644 index 0000000000000..53af86aaa4684 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-CAINIT_E_SHARP_3 @@ -0,0 +1 @@ +44d1c0b80828af779d942cc20dde4ea4 diff --git a/tests/ref/fate/cbs-hevc-CAINIT_H_SHARP_3 b/tests/ref/fate/cbs-hevc-CAINIT_H_SHARP_3 new file mode 100644 index 0000000000000..5e127d7894cec --- /dev/null +++ b/tests/ref/fate/cbs-hevc-CAINIT_H_SHARP_3 @@ -0,0 +1 @@ +ae9311dfcaf65bb8de9c4fcf23ce0871 diff --git a/tests/ref/fate/cbs-hevc-CONFWIN_A_Sony_1 b/tests/ref/fate/cbs-hevc-CONFWIN_A_Sony_1 new file mode 100644 index 0000000000000..00445155d0a33 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-CONFWIN_A_Sony_1 @@ -0,0 +1 @@ +dce8104b2addbdd601eb280a88e18583 diff --git a/tests/ref/fate/cbs-hevc-HRD_A_Fujitsu_2 b/tests/ref/fate/cbs-hevc-HRD_A_Fujitsu_2 new file mode 100644 index 0000000000000..b9c90ae3c372d --- /dev/null +++ b/tests/ref/fate/cbs-hevc-HRD_A_Fujitsu_2 @@ -0,0 +1 @@ +716a90051f028c90daeb86b3825af36d diff --git a/tests/ref/fate/cbs-hevc-LTRPSPS_A_Qualcomm_1 b/tests/ref/fate/cbs-hevc-LTRPSPS_A_Qualcomm_1 new file mode 100644 index 0000000000000..21dfa5763a83c --- /dev/null +++ b/tests/ref/fate/cbs-hevc-LTRPSPS_A_Qualcomm_1 @@ -0,0 +1 @@ +11b599202a4d25693123bea8bb003e54 diff --git a/tests/ref/fate/cbs-hevc-NUT_A_ericsson_5 b/tests/ref/fate/cbs-hevc-NUT_A_ericsson_5 new file mode 100644 index 0000000000000..32e58affe79e7 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-NUT_A_ericsson_5 @@ -0,0 +1 @@ +25cf94dfa2e0334eeedbfa9a8ed1c4b2 diff --git a/tests/ref/fate/cbs-hevc-PICSIZE_A_Bossen_1 b/tests/ref/fate/cbs-hevc-PICSIZE_A_Bossen_1 new file mode 100644 index 0000000000000..cc180049202ce --- /dev/null +++ b/tests/ref/fate/cbs-hevc-PICSIZE_A_Bossen_1 @@ -0,0 +1 @@ +e87fbd90c297d401738db928e3e04dd4 diff --git a/tests/ref/fate/cbs-hevc-PICSIZE_B_Bossen_1 b/tests/ref/fate/cbs-hevc-PICSIZE_B_Bossen_1 new file mode 100644 index 0000000000000..5495cec6c3e91 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-PICSIZE_B_Bossen_1 @@ -0,0 +1 @@ +4993d49d6f2f532dfc683a9d26c1e313 diff --git a/tests/ref/fate/cbs-hevc-RPLM_A_qualcomm_4 b/tests/ref/fate/cbs-hevc-RPLM_A_qualcomm_4 new file mode 100644 index 0000000000000..c68d615cbff4d --- /dev/null +++ b/tests/ref/fate/cbs-hevc-RPLM_A_qualcomm_4 @@ -0,0 +1 @@ +f5d2633eefcd95e189faf4302d270457 diff --git a/tests/ref/fate/cbs-hevc-RPS_A_docomo_4 b/tests/ref/fate/cbs-hevc-RPS_A_docomo_4 new file mode 100644 index 0000000000000..772d16a192693 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-RPS_A_docomo_4 @@ -0,0 +1 @@ +97bd4fefd8cd95584f586027e244f283 diff --git a/tests/ref/fate/cbs-hevc-RPS_E_qualcomm_5 b/tests/ref/fate/cbs-hevc-RPS_E_qualcomm_5 new file mode 100644 index 0000000000000..faef7da0d9232 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-RPS_E_qualcomm_5 @@ -0,0 +1 @@ +b2528ef681729176ccb38a77be93a0de diff --git a/tests/ref/fate/cbs-hevc-SLIST_A_Sony_4 b/tests/ref/fate/cbs-hevc-SLIST_A_Sony_4 new file mode 100644 index 0000000000000..23b2e324d15e5 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-SLIST_A_Sony_4 @@ -0,0 +1 @@ +72cf53bbc967c9679e21a6d3203edb07 diff --git a/tests/ref/fate/cbs-hevc-SLIST_D_Sony_9 b/tests/ref/fate/cbs-hevc-SLIST_D_Sony_9 new file mode 100644 index 0000000000000..4cea86dba6c7b --- /dev/null +++ b/tests/ref/fate/cbs-hevc-SLIST_D_Sony_9 @@ -0,0 +1 @@ +59a22d715e30748492da5e0b9d421909 diff --git a/tests/ref/fate/cbs-hevc-STRUCT_A_Samsung_5 b/tests/ref/fate/cbs-hevc-STRUCT_A_Samsung_5 new file mode 100644 index 0000000000000..6a4508b0c5c12 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-STRUCT_A_Samsung_5 @@ -0,0 +1 @@ +647eb851b935fd3bc6a98ce5ce45dbc7 diff --git a/tests/ref/fate/cbs-hevc-TILES_B_Cisco_1 b/tests/ref/fate/cbs-hevc-TILES_B_Cisco_1 new file mode 100644 index 0000000000000..d767e26d6839a --- /dev/null +++ b/tests/ref/fate/cbs-hevc-TILES_B_Cisco_1 @@ -0,0 +1 @@ +85a114def19cefbd0fb0daf8370d711c diff --git a/tests/ref/fate/cbs-hevc-WPP_A_ericsson_MAIN_2 b/tests/ref/fate/cbs-hevc-WPP_A_ericsson_MAIN_2 new file mode 100644 index 0000000000000..fe6928fc8bc48 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-WPP_A_ericsson_MAIN_2 @@ -0,0 +1 @@ +de7d440b556eea827953e6d12aeb4023 diff --git a/tests/ref/fate/cbs-hevc-WPP_F_ericsson_MAIN_2 b/tests/ref/fate/cbs-hevc-WPP_F_ericsson_MAIN_2 new file mode 100644 index 0000000000000..08aee566f1286 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-WPP_F_ericsson_MAIN_2 @@ -0,0 +1 @@ +f197136f1fb3242c3422a48470dd7d35 diff --git a/tests/ref/fate/cbs-hevc-WP_A_Toshiba_3 b/tests/ref/fate/cbs-hevc-WP_A_Toshiba_3 new file mode 100644 index 0000000000000..b868c438f8803 --- /dev/null +++ b/tests/ref/fate/cbs-hevc-WP_A_Toshiba_3 @@ -0,0 +1 @@ +158312a1a35ef4b20cb4aeee48549c03 diff --git a/tests/ref/fate/cbs-hevc-ipcm_E_NEC_2 b/tests/ref/fate/cbs-hevc-ipcm_E_NEC_2 new file mode 100644 index 0000000000000..cc68b6fb49deb --- /dev/null +++ b/tests/ref/fate/cbs-hevc-ipcm_E_NEC_2 @@ -0,0 +1 @@ +2e1f9c95364cfac2aa6e6ee3a52c43c4 diff --git a/tests/ref/fate/cbs-mpeg2-hhi_burst_422_short b/tests/ref/fate/cbs-mpeg2-hhi_burst_422_short new file mode 100644 index 0000000000000..c319fba7b3b09 --- /dev/null +++ b/tests/ref/fate/cbs-mpeg2-hhi_burst_422_short @@ -0,0 +1 @@ +e0c2fdd9baeba0c5ba5839a8cd7a72d3 diff --git a/tests/ref/fate/cbs-mpeg2-sony-ct3 b/tests/ref/fate/cbs-mpeg2-sony-ct3 new file mode 100644 index 0000000000000..b5b4b12f0737b --- /dev/null +++ b/tests/ref/fate/cbs-mpeg2-sony-ct3 @@ -0,0 +1 @@ +b1e15a09cfffbad801810af0928736ab diff --git a/tests/ref/fate/cbs-mpeg2-tcela-6 b/tests/ref/fate/cbs-mpeg2-tcela-6 new file mode 100644 index 0000000000000..530369d6728ac --- /dev/null +++ b/tests/ref/fate/cbs-mpeg2-tcela-6 @@ -0,0 +1 @@ +771b6756a63793e05b74e645794908a2 From a6cfc287a06c7f75709fc9dfcdcc9cce54eaeca6 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 17 Oct 2017 21:15:23 +0100 Subject: [PATCH 0518/2557] Changelog: Add metadata bitstream filters This starts a new section - 3.4 has been released. --- Changelog | 4 ++++ libavcodec/version.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index d6ec4ad1b557a..7973d90e6994b 100644 --- a/Changelog +++ b/Changelog @@ -2,6 +2,10 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. version : +- Bitstream filters for editing metadata in H.264, HEVC and MPEG-2 streams + + +version 3.4: - deflicker video filter - doubleweave video filter - lumakey video filter diff --git a/libavcodec/version.h b/libavcodec/version.h index 594023ef26f0a..1a513f2e7260d 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 57 #define LIBAVCODEC_VERSION_MINOR 108 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From d180fce6c707d22a69206c1f8efeabd38424de95 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 17 Oct 2017 23:00:07 +0200 Subject: [PATCH 0519/2557] lavf/cafenc: Only allow mono and stereo for Opus. Found-by: James Almer --- libavformat/cafenc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index 211b046563fc6..0f7c4ebbb32c4 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -123,6 +123,11 @@ static int caf_write_header(AVFormatContext *s) return AVERROR_PATCHWELCOME; } + if (par->codec_id == AV_CODEC_ID_OPUS && par->channels > 2) { + av_log(s, AV_LOG_ERROR, "Only mono and stereo are supported for Opus\n"); + return AVERROR_INVALIDDATA; + } + if (!codec_tag) { av_log(s, AV_LOG_ERROR, "unsupported codec\n"); return AVERROR_INVALIDDATA; From df45ea45df18d909d545cf12769caf85310bebd9 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Mon, 9 Oct 2017 11:06:10 +0530 Subject: [PATCH 0520/2557] doc/filters: add note on flite thread safety and update URL Signed-off-by: Gyan Doshi Signed-off-by: Michael Niedermayer --- doc/filters.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 13eb62b307466..ce7e053194b8a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -4512,7 +4512,7 @@ Synthesize a voice utterance using the libflite library. To enable compilation of this filter you need to configure FFmpeg with @code{--enable-libflite}. -Note that the flite library is not thread-safe. +Note that versions of the flite library prior to 2.0 are not thread-safe. The filter accepts the following options: @@ -4567,7 +4567,7 @@ ffplay -f lavfi flite=text='No more be grieved for which that thou hast done.' @end itemize For more information about libflite, check: -@url{http://www.speech.cs.cmu.edu/flite/} +@url{http://www.festvox.org/flite/} @section anoisesrc From 69ac24e556c6fbc7138be5a60d0b90d2a5676c3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 13 Oct 2017 11:10:42 +0300 Subject: [PATCH 0521/2557] aarch64: Get rid of a stray double space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The extra space got included as part of the expansion of ELF, which later interfered with gas-preprocessor which earlier only stripped out leftover lines starting with '#' if the line started with that char. Signed-off-by: Martin Storsjö --- libavutil/aarch64/asm.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/aarch64/asm.S b/libavutil/aarch64/asm.S index 7e2af4df17e3c..15b55d57d2a47 100644 --- a/libavutil/aarch64/asm.S +++ b/libavutil/aarch64/asm.S @@ -23,7 +23,7 @@ #ifdef __ELF__ # define ELF #else -# define ELF # +# define ELF # #endif #if HAVE_AS_FUNC From 732510636e597585a79be7d111c88b3f7e174fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 13 Oct 2017 12:22:55 +0300 Subject: [PATCH 0522/2557] aarch64: Remove a dot from a label MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes building with armasm64 (when run through gas-preprocessor). Signed-off-by: Martin Storsjö --- libavcodec/aarch64/mpegaudiodsp_neon.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/aarch64/mpegaudiodsp_neon.S b/libavcodec/aarch64/mpegaudiodsp_neon.S index 34181d97daa9a..2a36f676039a8 100644 --- a/libavcodec/aarch64/mpegaudiodsp_neon.S +++ b/libavcodec/aarch64/mpegaudiodsp_neon.S @@ -24,7 +24,7 @@ #define WFRAC_BITS 16 // fractional bits for window #define OUT_SHIFT (WFRAC_BITS + FRAC_BITS - 15) -const tbl_rev128.s, align=4 +const tbl_rev128_s, align=4 .byte 12, 13, 14, 15 .byte 8, 9, 10, 11 .byte 4, 5, 6, 7 @@ -39,7 +39,7 @@ function ff_mpadsp_apply_window_\type\()_neon, export=1 ld1 {v4.4s,v5.4s,v6.4s,v7.4s}, [x7], #64 st1 {v0.4s,v1.4s,v2.4s,v3.4s}, [x8], #64 st1 {v4.4s,v5.4s,v6.4s,v7.4s}, [x8], #64 - movrel x15, tbl_rev128.s + movrel x15, tbl_rev128_s ld1 {v27.4s}, [x15] .ifc \type, fixed lsl x4, x4, #1 From 41df62fd674bd0c67f7b6952381d235a393245d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 13 Oct 2017 11:10:27 +0300 Subject: [PATCH 0523/2557] configure: Set the default assembler to armasm64 for MSVC for arm64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- configure | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure b/configure index e45b3201fc9a9..d74a83e239251 100755 --- a/configure +++ b/configure @@ -2946,6 +2946,9 @@ case "$toolchain" in nm_default="dumpbin -symbols" ar_default="lib" case "$arch" in + aarch64|arm64) + as_default="armasm64" + ;; arm*) as_default="armasm" ;; From 98afe3fb71afd4a18009924aaba56bc577bbd400 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 17 Oct 2017 11:04:57 +0000 Subject: [PATCH 0524/2557] qsv: Make the hevc idr_interval consistent with the h264 one According to the MediaSDK documentation the idr_interval value has a different meaning depending on the codec: 0 in H264 means make every I-frame IDR, in HEVC it means to have it only at the beginning. 1 in H264 means every other I-frame is not-IDR, in HEVC it means that every I-frame is IDR. Keep the behaviour consistent between the two encoders by increasing by 1 internally the idr_interval value for HEVC. --- libavcodec/qsvenc_hevc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index fb65d58c32cac..dbb55e2f18285 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -181,6 +181,9 @@ static av_cold int qsv_enc_init(AVCodecContext *avctx) } } + // HEVC and H264 meaning of the value is shifted by 1, make it consistent + q->qsv.idr_interval++; + ret = ff_qsv_enc_init(avctx, &q->qsv); if (ret < 0) return ret; @@ -220,7 +223,8 @@ static av_cold int qsv_enc_close(AVCodecContext *avctx) static const AVOption options[] = { QSV_COMMON_OPTS - { "idr_interval", "Distance (in I-frames) between IDR frames", OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, + { "idr_interval", "Distance (in I-frames) between IDR frames", OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT_MAX, VE, "idr_interval" }, + { "begin_only", "Output an IDR-frame only at the beginning of the stream", 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, 0, 0, VE, "idr_interval" }, { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_DEFAULT }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VE, "load_plugin" }, { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VE, "load_plugin" }, { "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VE, "load_plugin" }, From d2917501c252d999e5478c4b804e326ac77cf37b Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 17 Oct 2017 22:05:09 -0300 Subject: [PATCH 0525/2557] avcodec/cfhd: support cropped height tag Ported from libav. Authored by one of the following: Anton Khirnov Diego Biurrun Vittorio Giovara Reviewed-by: kierank Signed-off-by: James Almer --- libavcodec/cfhd.c | 6 ++++++ libavcodec/cfhd.h | 1 + 2 files changed, 7 insertions(+) diff --git a/libavcodec/cfhd.c b/libavcodec/cfhd.c index 5646ee82718de..fd5555834bb98 100644 --- a/libavcodec/cfhd.c +++ b/libavcodec/cfhd.c @@ -73,6 +73,7 @@ static void init_frame_defaults(CFHDContext *s) { s->coded_width = 0; s->coded_height = 0; + s->cropped_height = 0; s->bpc = 10; s->channel_cnt = 4; s->subband_cnt = SUBBAND_COUNT; @@ -455,6 +456,9 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame, break; } planes = av_pix_fmt_count_planes(s->coded_format); + } else if (tag == -85) { + av_log(avctx, AV_LOG_DEBUG, "Cropped height %"PRIu16"\n", data); + s->cropped_height = data; } else av_log(avctx, AV_LOG_DEBUG, "Unknown tag %i data %x\n", tag, data); @@ -472,6 +476,8 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame, ret = ff_set_dimensions(avctx, s->coded_width, s->coded_height); if (ret < 0) return ret; + if (s->cropped_height) + avctx->height = s->cropped_height; frame.f->width = frame.f->height = 0; diff --git a/libavcodec/cfhd.h b/libavcodec/cfhd.h index b0a52088aa42a..2573e750a6dd8 100644 --- a/libavcodec/cfhd.h +++ b/libavcodec/cfhd.h @@ -81,6 +81,7 @@ typedef struct CFHDContext { int coded_width; int coded_height; + int cropped_height; enum AVPixelFormat coded_format; int a_width; From 247281e8051102e09f46f5434a2ce1c8e54781f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Mon, 16 Oct 2017 22:28:00 +0300 Subject: [PATCH 0526/2557] configure: add pkg-config check for alsa Helps with use cases such as static linking, as the .pc file does actually contain the necessary Libs.private entries for all required dependencies. --- configure | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 8f4b339b5e1cc..e4c4567138eb5 100755 --- a/configure +++ b/configure @@ -6268,7 +6268,8 @@ EOF fi check_header soundcard.h -enabled alsa && check_lib alsa alsa/asoundlib.h snd_pcm_htimestamp -lasound +enabled alsa && use_pkg_config alsa alsa "alsa/asoundlib.h" snd_pcm_htimestamp || + check_lib alsa alsa/asoundlib.h snd_pcm_htimestamp -lasound enabled jack && check_lib jack jack/jack.h jack_client_open -ljack && check_func jack_port_get_latency_range -ljack From 624d4739dbfc950ee756e83ae187f97dc82d10c9 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 23 Sep 2017 16:46:11 +0100 Subject: [PATCH 0527/2557] cbs_h264: Fix writing streams with auxiliary pictures Tested with the alphaconformanceG sample. Fixes CID 1419836. (cherry picked from commit 9ed18f302b09e444f5b1be01979cce62c4b2c04a) --- libavcodec/cbs_h2645.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index bd2b5cbbf2552..9039e0f6f44a0 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -1008,7 +1008,7 @@ static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx, case H264_NAL_SPS_EXT: { - H264RawSPSExtension *sps_ext; + H264RawSPSExtension *sps_ext = unit->content; err = cbs_h264_write_sps_extension(ctx, pbc, sps_ext); if (err < 0) @@ -1032,6 +1032,7 @@ static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx, case H264_NAL_SLICE: case H264_NAL_IDR_SLICE: + case H264_NAL_AUXILIARY_SLICE: { H264RawSlice *slice = unit->content; GetBitContext gbc; From d792613badfe7e7ca3552533e691c5015991a98a Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 18 Oct 2017 19:34:53 +0100 Subject: [PATCH 0528/2557] h264_metadata: Fix clearing SEI payload in error case Fixes CID 1419832, 1419835. --- libavcodec/h264_metadata_bsf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 496f7f00fe853..73e73e96e48d6 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -372,7 +372,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) "must be \"UUID+string\".\n"); err = AVERROR(EINVAL); sei_fail: - memset(payload, 0, sizeof(&payload)); + memset(payload, 0, sizeof(*payload)); goto fail; } From 41272e112b389e61b875ba2372a64a251f1da9fc Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 18 Oct 2017 19:37:30 +0100 Subject: [PATCH 0529/2557] cbs_h264: Fix memory leak in error case Fixes CID 1419834. --- libavcodec/cbs_h2645.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 9039e0f6f44a0..742857bd199a9 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -824,6 +824,7 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, err = cbs_h264_read_sei(ctx, &gbc, sei); if (err < 0) { cbs_h264_free_sei(sei); + av_free(sei); return err; } From 03b1470088e6e4a11e5db0efd8c26d9ac8304d31 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 18 Oct 2017 19:39:10 +0100 Subject: [PATCH 0530/2557] vaapi_h264: Add missing return value check Fixes CID 1419829. --- libavcodec/vaapi_encode_h264.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 46950772a95f5..9d9611f882322 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -211,7 +211,9 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, if (priv->sei_needed) { if (priv->aud_needed) { - vaapi_encode_h264_add_nal(avctx, au, &priv->aud); + err = vaapi_encode_h264_add_nal(avctx, au, &priv->aud); + if (err < 0) + goto fail; priv->aud_needed = 0; } From 32a618a948c20f18db102d0b0976790222a57105 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 18 Oct 2017 19:46:53 +0100 Subject: [PATCH 0531/2557] vaapi_h264: Do not use deprecated header type SEI headers should be inserted as generic raw data (the old specific type has been deprecated in libva2). --- libavcodec/vaapi_encode_h264.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 9d9611f882322..9a4bd53da1182 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -256,7 +256,7 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, ff_cbs_fragment_uninit(priv->cbc, au); - *type = VAEncPackedHeaderH264_SEI; + *type = VAEncPackedHeaderRawData; return 0; } else { return AVERROR_EOF; From 242d8c8763d86f27ad3d63a4d48deccbb133c6c7 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 17 Oct 2017 21:47:03 +0100 Subject: [PATCH 0532/2557] opusenc: Fix double-declaration of variable --- libavcodec/opusenc_psy.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/opusenc_psy.c b/libavcodec/opusenc_psy.c index b446d41f755db..1b108ecb873b6 100644 --- a/libavcodec/opusenc_psy.c +++ b/libavcodec/opusenc_psy.c @@ -370,7 +370,6 @@ static int celt_search_for_tf(OpusPsyContext *s, OpusPsyStep **start, CeltFrame for (cway = 0; cway < 2; cway++) { int mag[2]; int base = f->transient ? 120 : 960; - int i; for (i = 0; i < 2; i++) { int c = ff_celt_tf_select[f->size][f->transient][cway][i]; From c37de519202ac2e5f20141673081b0e6b57ab983 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 17 Oct 2017 22:25:46 +0100 Subject: [PATCH 0533/2557] vorbis: Reorder conditions to avoid possible overread This can trigger a single-byte overread if the codebook has the maximum number of entries. Fixes #6743. --- libavcodec/vorbis.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/vorbis.c b/libavcodec/vorbis.c index 399020eec5517..ce23b947f0835 100644 --- a/libavcodec/vorbis.c +++ b/libavcodec/vorbis.c @@ -58,7 +58,7 @@ int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num) uint32_t exit_at_level[33] = { 404 }; unsigned i, j, p, code; - for (p = 0; (bits[p] == 0) && (p < num); ++p) + for (p = 0; (p < num) && (bits[p] == 0); ++p) ; if (p == num) return 0; @@ -71,7 +71,7 @@ int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num) ++p; - for (i = p; (bits[i] == 0) && (i < num); ++i) + for (i = p; (i < num) && (bits[i] == 0); ++i) ; if (i == num) return 0; From 89cc48551bbe9f147ba9f4ca3821a35797cf7b47 Mon Sep 17 00:00:00 2001 From: Dave Rice Date: Wed, 18 Oct 2017 15:21:46 -0400 Subject: [PATCH 0534/2557] avdevice/decklink_dec: 32 bit audio support Signed-off-by: Marton Balint --- doc/indevs.texi | 4 ++++ libavdevice/decklink_common.h | 1 + libavdevice/decklink_common_c.h | 1 + libavdevice/decklink_dec.cpp | 17 ++++++++++++++--- libavdevice/decklink_dec_c.c | 1 + libavdevice/version.h | 2 +- 6 files changed, 22 insertions(+), 4 deletions(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index 55a4084bb2240..d308bbf7de9f1 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -311,6 +311,10 @@ Sets maximum input buffer size in bytes. If the buffering reaches this value, incoming frames will be dropped. Defaults to @samp{1073741824}. +@item audio_depth +Sets the audio sample bit depth. Must be @samp{16} or @samp{32}. +Defaults to @samp{16}. + @end table @subsection Examples diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index 6b2525fb53691..b6acb01bb92ca 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -97,6 +97,7 @@ struct decklink_ctx { int frames_buffer_available_spots; int channels; + int audio_depth; }; typedef enum { DIRECTION_IN, DIRECTION_OUT} decklink_direction_t; diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h index 5616ab32f9cc6..368ac259e4a4c 100644 --- a/libavdevice/decklink_common_c.h +++ b/libavdevice/decklink_common_c.h @@ -42,6 +42,7 @@ struct decklink_cctx { double preroll; int v210; int audio_channels; + int audio_depth; int duplex_mode; DecklinkPtsSource audio_pts_source; DecklinkPtsSource video_pts_source; diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index d9ac01ac91bd1..b4b9e02cecc21 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -771,7 +771,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( av_init_packet(&pkt); //hack among hacks - pkt.size = audioFrame->GetSampleFrameCount() * ctx->audio_st->codecpar->channels * (16 / 8); + pkt.size = audioFrame->GetSampleFrameCount() * ctx->audio_st->codecpar->channels * (ctx->audio_depth / 8); audioFrame->GetBytes(&audioFrameBytes); audioFrame->GetPacketTime(&audio_pts, ctx->audio_st->time_base.den); pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, ctx->audio_pts_source, ctx->audio_st->time_base, &initial_audio_pts); @@ -854,6 +854,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) ctx->audio_pts_source = cctx->audio_pts_source; ctx->video_pts_source = cctx->video_pts_source; ctx->draw_bars = cctx->draw_bars; + ctx->audio_depth = cctx->audio_depth; cctx->ctx = ctx; /* Check audio channel option for valid values: 2, 8 or 16 */ @@ -867,6 +868,16 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) return AVERROR(EINVAL); } + /* Check audio bit depth option for valid values: 16 or 32 */ + switch (cctx->audio_depth) { + case 16: + case 32: + break; + default: + av_log(avctx, AV_LOG_ERROR, "Value for audio bit depth option must be either 16 or 32\n"); + return AVERROR(EINVAL); + } + /* List available devices. */ if (ctx->list_devices) { ff_decklink_list_devices_legacy(avctx, 1, 0); @@ -930,7 +941,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) goto error; } st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; + st->codecpar->codec_id = cctx->audio_depth == 32 ? AV_CODEC_ID_PCM_S32LE : AV_CODEC_ID_PCM_S16LE; st->codecpar->sample_rate = bmdAudioSampleRate48kHz; st->codecpar->channels = cctx->audio_channels; avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ @@ -1021,7 +1032,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) } av_log(avctx, AV_LOG_VERBOSE, "Using %d input audio channels\n", ctx->audio_st->codecpar->channels); - result = ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, ctx->audio_st->codecpar->channels); + result = ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz, cctx->audio_depth == 32 ? bmdAudioSampleType32bitInteger : bmdAudioSampleType16bitInteger, ctx->audio_st->codecpar->channels); if (result != S_OK) { av_log(avctx, AV_LOG_ERROR, "Cannot enable audio input\n"); diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c index 1127d23adaafd..1c6d826945442 100644 --- a/libavdevice/decklink_dec_c.c +++ b/libavdevice/decklink_dec_c.c @@ -72,6 +72,7 @@ static const AVOption options[] = { { "wallclock", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PTS_SRC_WALLCLOCK}, 0, 0, DEC, "pts_source"}, { "draw_bars", "draw bars on signal loss" , OFFSET(draw_bars), AV_OPT_TYPE_BOOL, { .i64 = 1}, 0, 1, DEC }, { "queue_size", "input queue buffer size", OFFSET(queue_size), AV_OPT_TYPE_INT64, { .i64 = (1024 * 1024 * 1024)}, 0, INT64_MAX, DEC }, + { "audio_depth", "audio bitdepth (16 or 32)", OFFSET(audio_depth), AV_OPT_TYPE_INT, { .i64 = 16}, 16, 32, DEC }, { NULL }, }; diff --git a/libavdevice/version.h b/libavdevice/version.h index d3622c5395333..68defac41784a 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -29,7 +29,7 @@ #define LIBAVDEVICE_VERSION_MAJOR 57 #define LIBAVDEVICE_VERSION_MINOR 11 -#define LIBAVDEVICE_VERSION_MICRO 100 +#define LIBAVDEVICE_VERSION_MICRO 101 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ LIBAVDEVICE_VERSION_MINOR, \ From f4090940bd3024e69d236257d327f11d1e496229 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Wed, 4 Oct 2017 00:43:30 +0200 Subject: [PATCH 0535/2557] ffmpeg: always init output stream before reaping filters Otherwise the frame size of the codec is not set in the buffersink. Fixes ticket #6603 and the following simpler case: ffmpeg -c aac -filter_complex "sine=d=0.1,asetnsamples=1025" out.aac Signed-off-by: Marton Balint --- fftools/ffmpeg.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 3ee31473dc5c4..d581b40bf2f79 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -4536,6 +4536,15 @@ static int transcode_step(void) } if (ost->filter && ost->filter->graph->graph) { + if (!ost->initialized) { + char error[1024] = {0}; + ret = init_output_stream(ost, error, sizeof(error)); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error initializing output stream %d:%d -- %s\n", + ost->file_index, ost->index, error); + exit_program(1); + } + } if ((ret = transcode_from_filter(ost->filter->graph, &ist)) < 0) return ret; if (!ist) From ec0f4fa17ce29cf01d4def21041b0b87f7e3105d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 17 Aug 2017 12:25:56 +0200 Subject: [PATCH 0536/2557] FATE: add a test for the H.264 sample fixed by 7c4f6f6 --- tests/fate/h264.mak | 2 ++ tests/ref/fate/h264-ref-pic-mod-overflow | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 tests/ref/fate/h264-ref-pic-mod-overflow diff --git a/tests/fate/h264.mak b/tests/fate/h264.mak index bdc390d4793f9..7676fb8e27765 100644 --- a/tests/fate/h264.mak +++ b/tests/fate/h264.mak @@ -183,6 +183,7 @@ FATE_H264 := $(FATE_H264:%=fate-h264-conformance-%) \ fate-h264-intra-refresh-recovery \ fate-h264-lossless \ fate-h264-missing-frame \ + fate-h264-ref-pic-mod-overflow \ FATE_H264-$(call DEMDEC, H264, H264) += $(FATE_H264) FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-crop-to-container @@ -396,6 +397,7 @@ fate-h264-intra-refresh-recovery: CMD = framecrc -i $(TARGET_SAM fate-h264-invalid-ref-mod: CMD = framecrc -i $(TARGET_SAMPLES)/h264/h264refframeregression.mp4 -an -frames 10 -pix_fmt yuv420p10le fate-h264-lossless: CMD = framecrc -i $(TARGET_SAMPLES)/h264/lossless.h264 fate-h264-mixed-nal-coding: CMD = framecrc -i $(TARGET_SAMPLES)/h264/mixed-nal-coding.mp4 +fate-h264-ref-pic-mod-overflow: CMD = framecrc -i $(TARGET_SAMPLES)/h264/ref-pic-mod-overflow.h264 fate-h264-twofields-packet: CMD = framecrc -i $(TARGET_SAMPLES)/h264/twofields_packet.mp4 -an -frames 30 fate-h264-unescaped-extradata: CMD = framecrc -i $(TARGET_SAMPLES)/h264/unescaped_extradata.mp4 -an -frames 10 fate-h264-missing-frame: CMD = framecrc -i $(TARGET_SAMPLES)/h264/nondeterministic_cut.h264 diff --git a/tests/ref/fate/h264-ref-pic-mod-overflow b/tests/ref/fate/h264-ref-pic-mod-overflow new file mode 100644 index 0000000000000..b84ef5a900e97 --- /dev/null +++ b/tests/ref/fate/h264-ref-pic-mod-overflow @@ -0,0 +1,21 @@ +#tb 0: 1/25 +0, 0, 0, 1, 3110400, 0x5cd0bee9 +0, 1, 1, 1, 3110400, 0x19d0155c +0, 2, 2, 1, 3110400, 0x3519be4b +0, 3, 3, 1, 3110400, 0x87dc6708 +0, 4, 4, 1, 3110400, 0xef3c1056 +0, 5, 5, 1, 3110400, 0x5064aad2 +0, 6, 6, 1, 3110400, 0xbfb35057 +0, 7, 7, 1, 3110400, 0x6089eb95 +0, 8, 8, 1, 3110400, 0x85de8dea +0, 9, 9, 1, 3110400, 0x216b1e5a +0, 10, 10, 1, 3110400, 0xba73bdc4 +0, 11, 11, 1, 3110400, 0x536e437a +0, 12, 12, 1, 3110400, 0x4be0cdbd +0, 13, 13, 1, 3110400, 0x7316462d +0, 14, 14, 1, 3110400, 0x80eb8622 +0, 15, 15, 1, 3110400, 0xa612a70b +0, 16, 16, 1, 3110400, 0x9ff65345 +0, 17, 17, 1, 3110400, 0x57003dfa +0, 18, 18, 1, 3110400, 0xf29e036e +0, 19, 19, 1, 3110400, 0x70285363 From b46a77f19ddc4b2b5fa3187835ceb602a5244e24 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 19 Oct 2017 16:38:20 +0200 Subject: [PATCH 0537/2557] lavc: external hardware frame pool initialization This adds a new API, which allows the API user to query the required AVHWFramesContext parameters. This also reduces code duplication across the hwaccels by introducing ff_decode_get_hw_frames_ctx(), which uses the new API function. It takes care of initializing the hw_frames_ctx if needed, and does additional error handling and API usage checking. Support for VDA and Cuvid missing. Signed-off-by: Anton Khirnov --- doc/APIchanges | 3 + libavcodec/avcodec.h | 113 +++++++++++++++++++ libavcodec/decode.c | 82 ++++++++++++++ libavcodec/decode.h | 9 ++ libavcodec/dxva2.c | 55 ++++----- libavcodec/dxva2_h264.c | 3 + libavcodec/dxva2_hevc.c | 3 + libavcodec/dxva2_internal.h | 3 + libavcodec/dxva2_mpeg2.c | 3 + libavcodec/dxva2_vc1.c | 5 + libavcodec/vaapi_decode.c | 216 +++++++++++++++++------------------- libavcodec/vaapi_decode.h | 5 +- libavcodec/vaapi_h264.c | 1 + libavcodec/vaapi_hevc.c | 1 + libavcodec/vaapi_mpeg2.c | 1 + libavcodec/vaapi_mpeg4.c | 2 + libavcodec/vaapi_vc1.c | 2 + libavcodec/vaapi_vp8.c | 1 + libavcodec/vdpau.c | 58 +++++----- libavcodec/vdpau_h264.c | 1 + libavcodec/vdpau_hevc.c | 1 + libavcodec/vdpau_internal.h | 2 + libavcodec/vdpau_mpeg12.c | 1 + libavcodec/vdpau_mpeg4.c | 1 + libavcodec/vdpau_vc1.c | 2 + libavcodec/version.h | 2 +- 26 files changed, 395 insertions(+), 181 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index fa27007f44ce8..9f3a1f2465810 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2017-03-23 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavc 58.5.0 - avcodec.h + Add avcodec_get_hw_frames_parameters(). + 2017-xx-xx - xxxxxxx - lavu 56.6.0 - pixdesc.h Add av_color_range_from_name(), av_color_primaries_from_name(), av_color_transfer_from_name(), av_color_space_from_name(), and diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 162f1abe4b78f..5624835023ea4 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2990,6 +2990,16 @@ typedef struct AVHWAccel { * Internal hwaccel capabilities. */ int caps_internal; + + /** + * Fill the given hw_frames context with current codec parameters. Called + * from get_format. Refer to avcodec_get_hw_frames_parameters() for + * details. + * + * This CAN be called before AVHWAccel.init is called, and you must assume + * that avctx->hwaccel_priv_data is invalid. + */ + int (*frame_params)(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); } AVHWAccel; /** @@ -3984,6 +3994,109 @@ int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); */ int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); +/** + * Create and return a AVHWFramesContext with values adequate for hardware + * decoding. This is meant to get called from the get_format callback, and is + * a helper for preparing a AVHWFramesContext for AVCodecContext.hw_frames_ctx. + * This API is for decoding with certain hardware acceleration modes/APIs only. + * + * The returned AVHWFramesContext is not initialized. The caller must do this + * with av_hwframe_ctx_init(). + * + * Calling this function is not a requirement, but makes it simpler to avoid + * codec or hardware API specific details when manually allocating frames. + * + * Alternatively to this, an API user can set AVCodecContext.hw_device_ctx, + * which sets up AVCodecContext.hw_frames_ctx fully automatically, and makes + * it unnecessary to call this function or having to care about + * AVHWFramesContext initialization at all. + * + * There are a number of requirements for calling this function: + * + * - It must be called from get_format with the same avctx parameter that was + * passed to get_format. Calling it outside of get_format is not allowed, and + * can trigger undefined behavior. + * - The function is not always supported (see description of return values). + * Even if this function returns successfully, hwaccel initialization could + * fail later. (The degree to which implementations check whether the stream + * is actually supported varies. Some do this check only after the user's + * get_format callback returns.) + * - The hw_pix_fmt must be one of the choices suggested by get_format. If the + * user decides to use a AVHWFramesContext prepared with this API function, + * the user must return the same hw_pix_fmt from get_format. + * - The device_ref passed to this function must support the given hw_pix_fmt. + * - After calling this API function, it is the user's responsibility to + * initialize the AVHWFramesContext (returned by the out_frames_ref parameter), + * and to set AVCodecContext.hw_frames_ctx to it. If done, this must be done + * before returning from get_format (this is implied by the normal + * AVCodecContext.hw_frames_ctx API rules). + * - The AVHWFramesContext parameters may change every time time get_format is + * called. Also, AVCodecContext.hw_frames_ctx is reset before get_format. So + * you are inherently required to go through this process again on every + * get_format call. + * - It is perfectly possible to call this function without actually using + * the resulting AVHWFramesContext. One use-case might be trying to reuse a + * previously initialized AVHWFramesContext, and calling this API function + * only to test whether the required frame parameters have changed. + * - Fields that use dynamically allocated values of any kind must not be set + * by the user unless setting them is explicitly allowed by the documentation. + * If the user sets AVHWFramesContext.free and AVHWFramesContext.user_opaque, + * the new free callback must call the potentially set previous free callback. + * This API call may set any dynamically allocated fields, including the free + * callback. + * + * The function will set at least the following fields on AVHWFramesContext + * (potentially more, depending on hwaccel API): + * + * - All fields set by av_hwframe_ctx_alloc(). + * - Set the format field to hw_pix_fmt. + * - Set the sw_format field to the most suited and most versatile format. (An + * implication is that this will prefer generic formats over opaque formats + * with arbitrary restrictions, if possible.) + * - Set the width/height fields to the coded frame size, rounded up to the + * API-specific minimum alignment. + * - Only _if_ the hwaccel requires a pre-allocated pool: set the initial_pool_size + * field to the number of maximum reference surfaces possible with the codec, + * plus 1 surface for the user to work (meaning the user can safely reference + * at most 1 decoded surface at a time), plus additional buffering introduced + * by frame threading. If the hwaccel does not require pre-allocation, the + * field is left to 0, and the decoder will allocate new surfaces on demand + * during decoding. + * - Possibly AVHWFramesContext.hwctx fields, depending on the underlying + * hardware API. + * + * Essentially, out_frames_ref returns the same as av_hwframe_ctx_alloc(), but + * with basic frame parameters set. + * + * The function is stateless, and does not change the AVCodecContext or the + * device_ref AVHWDeviceContext. + * + * @param avctx The context which is currently calling get_format, and which + * implicitly contains all state needed for filling the returned + * AVHWFramesContext properly. + * @param device_ref A reference to the AVHWDeviceContext describing the device + * which will be used by the hardware decoder. + * @param hw_pix_fmt The hwaccel format you are going to return from get_format. + * @param out_frames_ref On success, set to a reference to an _uninitialized_ + * AVHWFramesContext, created from the given device_ref. + * Fields will be set to values required for decoding. + * Not changed if an error is returned. + * @return zero on success, a negative value on error. The following error codes + * have special semantics: + * AVERROR(ENOENT): the decoder does not support this functionality. Setup + * is always manual, or it is a decoder which does not + * support setting AVCodecContext.hw_frames_ctx at all, + * or it is a software format. + * AVERROR(EINVAL): it is known that hardware decoding is not supported for + * this configuration, or the device_ref is not supported + * for the hwaccel referenced by hw_pix_fmt. + */ +int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, + AVBufferRef *device_ref, + enum AVPixelFormat hw_pix_fmt, + AVBufferRef **out_frames_ref); + + /** * @defgroup lavc_parsing Frame parsing diff --git a/libavcodec/decode.c b/libavcodec/decode.c index c76ee6696aeee..54cda530bb8c3 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -669,6 +669,88 @@ static AVHWAccel *find_hwaccel(enum AVCodecID codec_id, return NULL; } +int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx, + enum AVHWDeviceType dev_type) +{ + AVHWDeviceContext *device_ctx; + AVHWFramesContext *frames_ctx; + int ret; + + if (!avctx->hwaccel) + return AVERROR(ENOSYS); + + if (avctx->hw_frames_ctx) + return 0; + if (!avctx->hw_device_ctx) { + av_log(avctx, AV_LOG_ERROR, "A hardware frames or device context is " + "required for hardware accelerated decoding.\n"); + return AVERROR(EINVAL); + } + + device_ctx = (AVHWDeviceContext *)avctx->hw_device_ctx->data; + if (device_ctx->type != dev_type) { + av_log(avctx, AV_LOG_ERROR, "Device type %s expected for hardware " + "decoding, but got %s.\n", av_hwdevice_get_type_name(dev_type), + av_hwdevice_get_type_name(device_ctx->type)); + return AVERROR(EINVAL); + } + + ret = avcodec_get_hw_frames_parameters(avctx, + avctx->hw_device_ctx, + avctx->hwaccel->pix_fmt, + avctx->hw_frames_ctx); + if (ret < 0) { + av_buffer_unref(&avctx->hw_frames_ctx); + return ret; + } + + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + + + if (frames_ctx->initial_pool_size) { + // We guarantee 4 base work surfaces. The function above guarantees 1 + // (the absolute minimum), so add the missing count. + frames_ctx->initial_pool_size += 3; + + // Add an additional surface per thread is frame threading is enabled. + if (avctx->active_thread_type & FF_THREAD_FRAME) + frames_ctx->initial_pool_size += avctx->thread_count; + } + + ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); + if (ret < 0) { + av_buffer_unref(&avctx->hw_frames_ctx); + return ret; + } + + return 0; +} + +int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, + AVBufferRef *device_ref, + enum AVPixelFormat hw_pix_fmt, + AVBufferRef **out_frames_ref) +{ + AVBufferRef *frames_ref = NULL; + AVHWAccel *hwa = find_hwaccel(avctx->codec_id, hw_pix_fmt); + int ret; + + if (!hwa || !hwa->frame_params) + return AVERROR(ENOENT); + + frames_ref = av_hwframe_ctx_alloc(device_ref); + if (!frames_ref) + return AVERROR(ENOMEM); + + ret = hwa->frame_params(avctx, frames_ref); + if (ret >= 0) { + *out_frames_ref = frames_ref; + } else { + av_buffer_unref(&frames_ref); + } + return ret; +} + static int setup_hwaccel(AVCodecContext *avctx, const enum AVPixelFormat fmt, const char *name) diff --git a/libavcodec/decode.h b/libavcodec/decode.h index 235f355f823ee..37b2e45c6391d 100644 --- a/libavcodec/decode.h +++ b/libavcodec/decode.h @@ -23,6 +23,7 @@ #include "libavutil/buffer.h" #include "libavutil/frame.h" +#include "libavutil/hwcontext.h" #include "avcodec.h" @@ -70,4 +71,12 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt); void ff_decode_bsfs_uninit(AVCodecContext *avctx); +/** + * Make sure avctx.hw_frames_ctx is set. If it's not set, the function will + * try to allocate it from hw_device_ctx. If that is not possible, an error + * message is printed, and an error code is returned. + */ +int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx, + enum AVHWDeviceType dev_type); + #endif /* AVCODEC_DECODE_H */ diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index 9ceb6236d4eef..e34409d44a3b7 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -29,6 +29,7 @@ #include "libavutil/time.h" #include "avcodec.h" +#include "decode.h" #include "dxva2_internal.h" /* define all the GUIDs used directly here, @@ -572,14 +573,20 @@ static void ff_dxva2_unlock(AVCodecContext *avctx) #endif } -// This must work before the decoder is created. -// This somehow needs to be exported to the user. -static void dxva_adjust_hwframes(AVCodecContext *avctx, AVHWFramesContext *frames_ctx) +int ff_dxva2_common_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) { - FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); + AVHWFramesContext *frames_ctx = (AVHWFramesContext *)hw_frames_ctx->data; + AVHWDeviceContext *device_ctx = frames_ctx->device_ctx; int surface_alignment, num_surfaces; - frames_ctx->format = sctx->pix_fmt; + if (device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { + frames_ctx->format = AV_PIX_FMT_DXVA2_VLD; + } else if (device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { + frames_ctx->format = AV_PIX_FMT_D3D11; + } else { + return AVERROR(EINVAL); + } /* decoding MPEG-2 requires additional alignment on some Intel GPUs, but it causes issues for H.264 on certain AMD GPUs..... */ @@ -592,8 +599,8 @@ static void dxva_adjust_hwframes(AVCodecContext *avctx, AVHWFramesContext *frame else surface_alignment = 16; - /* 4 base work surfaces */ - num_surfaces = 4; + /* 1 base work surface */ + num_surfaces = 1; /* add surfaces based on number of possible refs */ if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC) @@ -627,12 +634,16 @@ static void dxva_adjust_hwframes(AVCodecContext *avctx, AVHWFramesContext *frame frames_hwctx->BindFlags |= D3D11_BIND_DECODER; } #endif + + return 0; } int ff_dxva2_decode_init(AVCodecContext *avctx) { FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); - AVHWFramesContext *frames_ctx = NULL; + AVHWFramesContext *frames_ctx; + enum AVHWDeviceType dev_type = avctx->hwaccel->pix_fmt == AV_PIX_FMT_DXVA2_VLD + ? AV_HWDEVICE_TYPE_DXVA2 : AV_HWDEVICE_TYPE_D3D11VA; int ret = 0; // Old API. @@ -642,32 +653,14 @@ int ff_dxva2_decode_init(AVCodecContext *avctx) // (avctx->pix_fmt is not updated yet at this point) sctx->pix_fmt = avctx->hwaccel->pix_fmt; - if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) { - av_log(avctx, AV_LOG_ERROR, "Either a hw_frames_ctx or a hw_device_ctx needs to be set for hardware decoding.\n"); - return AVERROR(EINVAL); - } - - if (avctx->hw_frames_ctx) { - frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - } else { - avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); - if (!avctx->hw_frames_ctx) - return AVERROR(ENOMEM); - - frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - - dxva_adjust_hwframes(avctx, frames_ctx); - - ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); - if (ret < 0) - goto fail; - } + ret = ff_decode_get_hw_frames_ctx(avctx, dev_type); + if (ret < 0) + return ret; + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; sctx->device_ctx = frames_ctx->device_ctx; - if (frames_ctx->format != sctx->pix_fmt || - !((sctx->pix_fmt == AV_PIX_FMT_D3D11 && CONFIG_D3D11VA) || - (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && CONFIG_DXVA2))) { + if (frames_ctx->format != sctx->pix_fmt) { av_log(avctx, AV_LOG_ERROR, "Invalid pixfmt for hwaccel!\n"); ret = AVERROR(EINVAL); goto fail; diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c index de0885058ad2f..8ce8c358c5c43 100644 --- a/libavcodec/dxva2_h264.c +++ b/libavcodec/dxva2_h264.c @@ -523,6 +523,7 @@ AVHWAccel ff_h264_dxva2_hwaccel = { .start_frame = dxva2_h264_start_frame, .decode_slice = dxva2_h264_decode_slice, .end_frame = dxva2_h264_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; @@ -539,6 +540,7 @@ AVHWAccel ff_h264_d3d11va_hwaccel = { .start_frame = dxva2_h264_start_frame, .decode_slice = dxva2_h264_decode_slice, .end_frame = dxva2_h264_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; @@ -555,6 +557,7 @@ AVHWAccel ff_h264_d3d11va2_hwaccel = { .start_frame = dxva2_h264_start_frame, .decode_slice = dxva2_h264_decode_slice, .end_frame = dxva2_h264_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c index 4bff26d6a8e4f..1d665f07d19cd 100644 --- a/libavcodec/dxva2_hevc.c +++ b/libavcodec/dxva2_hevc.c @@ -432,6 +432,7 @@ AVHWAccel ff_hevc_dxva2_hwaccel = { .start_frame = dxva2_hevc_start_frame, .decode_slice = dxva2_hevc_decode_slice, .end_frame = dxva2_hevc_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; @@ -448,6 +449,7 @@ AVHWAccel ff_hevc_d3d11va_hwaccel = { .start_frame = dxva2_hevc_start_frame, .decode_slice = dxva2_hevc_decode_slice, .end_frame = dxva2_hevc_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; @@ -464,6 +466,7 @@ AVHWAccel ff_hevc_d3d11va2_hwaccel = { .start_frame = dxva2_hevc_start_frame, .decode_slice = dxva2_hevc_decode_slice, .end_frame = dxva2_hevc_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h index 901cc1114489a..42ff346226b37 100644 --- a/libavcodec/dxva2_internal.h +++ b/libavcodec/dxva2_internal.h @@ -156,6 +156,9 @@ int ff_dxva2_decode_init(AVCodecContext *avctx); int ff_dxva2_decode_uninit(AVCodecContext *avctx); +int ff_dxva2_common_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx); + int ff_dxva2_is_d3d11(const AVCodecContext *avctx); #endif /* AVCODEC_DXVA2_INTERNAL_H */ diff --git a/libavcodec/dxva2_mpeg2.c b/libavcodec/dxva2_mpeg2.c index ab80ca300a117..036d5baac5a02 100644 --- a/libavcodec/dxva2_mpeg2.c +++ b/libavcodec/dxva2_mpeg2.c @@ -328,6 +328,7 @@ AVHWAccel ff_mpeg2_dxva2_hwaccel = { .start_frame = dxva2_mpeg2_start_frame, .decode_slice = dxva2_mpeg2_decode_slice, .end_frame = dxva2_mpeg2_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; @@ -344,6 +345,7 @@ AVHWAccel ff_mpeg2_d3d11va_hwaccel = { .start_frame = dxva2_mpeg2_start_frame, .decode_slice = dxva2_mpeg2_decode_slice, .end_frame = dxva2_mpeg2_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; @@ -360,6 +362,7 @@ AVHWAccel ff_mpeg2_d3d11va2_hwaccel = { .start_frame = dxva2_mpeg2_start_frame, .decode_slice = dxva2_mpeg2_decode_slice, .end_frame = dxva2_mpeg2_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c index 22d3d299b6cf0..79f758a3b962c 100644 --- a/libavcodec/dxva2_vc1.c +++ b/libavcodec/dxva2_vc1.c @@ -328,6 +328,7 @@ AVHWAccel ff_wmv3_dxva2_hwaccel = { .start_frame = dxva2_vc1_start_frame, .decode_slice = dxva2_vc1_decode_slice, .end_frame = dxva2_vc1_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; @@ -344,6 +345,7 @@ AVHWAccel ff_vc1_dxva2_hwaccel = { .start_frame = dxva2_vc1_start_frame, .decode_slice = dxva2_vc1_decode_slice, .end_frame = dxva2_vc1_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; @@ -360,6 +362,7 @@ AVHWAccel ff_wmv3_d3d11va_hwaccel = { .start_frame = dxva2_vc1_start_frame, .decode_slice = dxva2_vc1_decode_slice, .end_frame = dxva2_vc1_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; @@ -376,6 +379,7 @@ AVHWAccel ff_wmv3_d3d11va2_hwaccel = { .start_frame = dxva2_vc1_start_frame, .decode_slice = dxva2_vc1_decode_slice, .end_frame = dxva2_vc1_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; @@ -392,6 +396,7 @@ AVHWAccel ff_vc1_d3d11va_hwaccel = { .start_frame = dxva2_vc1_start_frame, .decode_slice = dxva2_vc1_decode_slice, .end_frame = dxva2_vc1_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index a63c4c62ec97f..5ae98d8fd7e69 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -21,6 +21,7 @@ #include "libavutil/pixdesc.h" #include "avcodec.h" +#include "decode.h" #include "internal.h" #include "vaapi_decode.h" @@ -270,10 +271,15 @@ static const struct { #undef MAP }; -static int vaapi_decode_make_config(AVCodecContext *avctx) +/* + * Set *va_config and the frames_ref fields from the current codec parameters + * in avctx. + */ +static int vaapi_decode_make_config(AVCodecContext *avctx, + AVBufferRef *device_ref, + VAConfigID *va_config, + AVBufferRef *frames_ref) { - VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; - AVVAAPIHWConfig *hwconfig = NULL; AVHWFramesConstraints *constraints = NULL; VAStatus vas; @@ -283,13 +289,16 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) int profile_count, exact_match, alt_profile; const AVPixFmtDescriptor *sw_desc, *desc; + AVHWDeviceContext *device = (AVHWDeviceContext*)device_ref->data; + AVVAAPIDeviceContext *hwctx = device->hwctx; + codec_desc = avcodec_descriptor_get(avctx->codec_id); if (!codec_desc) { err = AVERROR(EINVAL); goto fail; } - profile_count = vaMaxNumProfiles(ctx->hwctx->display); + profile_count = vaMaxNumProfiles(hwctx->display); profile_list = av_malloc_array(profile_count, sizeof(VAProfile)); if (!profile_list) { @@ -297,7 +306,7 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) goto fail; } - vas = vaQueryConfigProfiles(ctx->hwctx->display, + vas = vaQueryConfigProfiles(hwctx->display, profile_list, &profile_count); if (vas != VA_STATUS_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: " @@ -355,12 +364,9 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) } } - ctx->va_profile = profile; - ctx->va_entrypoint = VAEntrypointVLD; - - vas = vaCreateConfig(ctx->hwctx->display, ctx->va_profile, - ctx->va_entrypoint, NULL, 0, - &ctx->va_config); + vas = vaCreateConfig(hwctx->display, profile, + VAEntrypointVLD, NULL, 0, + va_config); if (vas != VA_STATUS_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to create decode " "configuration: %d (%s).\n", vas, vaErrorStr(vas)); @@ -368,20 +374,15 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) goto fail; } - hwconfig = av_hwdevice_hwconfig_alloc(avctx->hw_device_ctx ? - avctx->hw_device_ctx : - ctx->frames->device_ref); + hwconfig = av_hwdevice_hwconfig_alloc(device_ref); if (!hwconfig) { err = AVERROR(ENOMEM); goto fail; } - hwconfig->config_id = ctx->va_config; + hwconfig->config_id = *va_config; constraints = - av_hwdevice_get_hwframe_constraints(avctx->hw_device_ctx ? - avctx->hw_device_ctx : - ctx->frames->device_ref, - hwconfig); + av_hwdevice_get_hwframe_constraints(device_ref, hwconfig); if (!constraints) { err = AVERROR(ENOMEM); goto fail; @@ -407,48 +408,52 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) goto fail; } - // Find the first format in the list which matches the expected - // bit depth and subsampling. If none are found (this can happen - // when 10-bit streams are decoded to 8-bit surfaces, for example) - // then just take the first format on the list. - ctx->surface_format = constraints->valid_sw_formats[0]; - sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); - for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { - desc = av_pix_fmt_desc_get(constraints->valid_sw_formats[i]); - if (desc->nb_components != sw_desc->nb_components || - desc->log2_chroma_w != sw_desc->log2_chroma_w || - desc->log2_chroma_h != sw_desc->log2_chroma_h) - continue; - for (j = 0; j < desc->nb_components; j++) { - if (desc->comp[j].depth != sw_desc->comp[j].depth) - break; + if (frames_ref) { + AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data; + + frames->format = AV_PIX_FMT_VAAPI; + frames->width = avctx->coded_width; + frames->height = avctx->coded_height; + + // Find the first format in the list which matches the expected + // bit depth and subsampling. If none are found (this can happen + // when 10-bit streams are decoded to 8-bit surfaces, for example) + // then just take the first format on the list. + frames->sw_format = constraints->valid_sw_formats[0]; + sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); + for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { + desc = av_pix_fmt_desc_get(constraints->valid_sw_formats[i]); + if (desc->nb_components != sw_desc->nb_components || + desc->log2_chroma_w != sw_desc->log2_chroma_w || + desc->log2_chroma_h != sw_desc->log2_chroma_h) + continue; + for (j = 0; j < desc->nb_components; j++) { + if (desc->comp[j].depth != sw_desc->comp[j].depth) + break; + } + if (j < desc->nb_components) + continue; + frames->sw_format = constraints->valid_sw_formats[i]; + break; } - if (j < desc->nb_components) - continue; - ctx->surface_format = constraints->valid_sw_formats[i]; - break; - } - // Start with at least four surfaces. - ctx->surface_count = 4; - // Add per-codec number of surfaces used for storing reference frames. - switch (avctx->codec_id) { - case AV_CODEC_ID_H264: - case AV_CODEC_ID_HEVC: - ctx->surface_count += 16; - break; - case AV_CODEC_ID_VP9: - ctx->surface_count += 8; - break; - case AV_CODEC_ID_VP8: - ctx->surface_count += 3; - break; - default: - ctx->surface_count += 2; + frames->initial_pool_size = 1; + // Add per-codec number of surfaces used for storing reference frames. + switch (avctx->codec_id) { + case AV_CODEC_ID_H264: + case AV_CODEC_ID_HEVC: + frames->initial_pool_size += 16; + break; + case AV_CODEC_ID_VP9: + frames->initial_pool_size += 8; + break; + case AV_CODEC_ID_VP8: + frames->initial_pool_size += 3; + break; + default: + frames->initial_pool_size += 2; + } } - // Add an additional surface per thread is frame threading is enabled. - if (avctx->active_thread_type & FF_THREAD_FRAME) - ctx->surface_count += avctx->thread_count; av_hwframe_constraints_free(&constraints); av_freep(&hwconfig); @@ -458,14 +463,38 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) fail: av_hwframe_constraints_free(&constraints); av_freep(&hwconfig); - if (ctx->va_config != VA_INVALID_ID) { - vaDestroyConfig(ctx->hwctx->display, ctx->va_config); - ctx->va_config = VA_INVALID_ID; + if (*va_config != VA_INVALID_ID) { + vaDestroyConfig(hwctx->display, *va_config); + *va_config = VA_INVALID_ID; } av_freep(&profile_list); return err; } +int ff_vaapi_common_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) +{ + AVHWFramesContext *hw_frames = (AVHWFramesContext *)hw_frames_ctx->data; + AVHWDeviceContext *device_ctx = hw_frames->device_ctx; + AVVAAPIDeviceContext *hwctx; + VAConfigID va_config = VA_INVALID_ID; + int err; + + if (device_ctx->type != AV_HWDEVICE_TYPE_VAAPI) + return AVERROR(EINVAL); + hwctx = device_ctx->hwctx; + + err = vaapi_decode_make_config(avctx, hw_frames->device_ref, &va_config, + hw_frames_ctx); + if (err) + return err; + + if (va_config != VA_INVALID_ID) + vaDestroyConfig(hwctx->display, va_config); + + return 0; +} + int ff_vaapi_decode_init(AVCodecContext *avctx) { VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; @@ -502,36 +531,8 @@ int ff_vaapi_decode_init(AVCodecContext *avctx) ctx->hwctx->driver_quirks = AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS; - } else -#endif - if (avctx->hw_frames_ctx) { - // This structure has a shorter lifetime than the enclosing - // AVCodecContext, so we inherit the references from there - // and do not need to make separate ones. - - ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - ctx->hwfc = ctx->frames->hwctx; - ctx->device = ctx->frames->device_ctx; - ctx->hwctx = ctx->device->hwctx; - - } else if (avctx->hw_device_ctx) { - ctx->device = (AVHWDeviceContext*)avctx->hw_device_ctx->data; - ctx->hwctx = ctx->device->hwctx; - - if (ctx->device->type != AV_HWDEVICE_TYPE_VAAPI) { - av_log(avctx, AV_LOG_ERROR, "Device supplied for VAAPI " - "decoding must be a VAAPI device (not %d).\n", - ctx->device->type); - err = AVERROR(EINVAL); - goto fail; - } - - } else { - av_log(avctx, AV_LOG_ERROR, "A hardware device or frames context " - "is required for VAAPI decoding.\n"); - err = AVERROR(EINVAL); - goto fail; } +#endif #if FF_API_VAAPI_CONTEXT if (ctx->have_old_context) { @@ -543,34 +544,19 @@ int ff_vaapi_decode_init(AVCodecContext *avctx) } else { #endif - err = vaapi_decode_make_config(avctx); - if (err) + err = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VAAPI); + if (err < 0) goto fail; - if (!avctx->hw_frames_ctx) { - avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); - if (!avctx->hw_frames_ctx) { - err = AVERROR(ENOMEM); - goto fail; - } - ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - - ctx->frames->format = AV_PIX_FMT_VAAPI; - ctx->frames->width = avctx->coded_width; - ctx->frames->height = avctx->coded_height; - - ctx->frames->sw_format = ctx->surface_format; - ctx->frames->initial_pool_size = ctx->surface_count; + ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + ctx->hwfc = ctx->frames->hwctx; + ctx->device = ctx->frames->device_ctx; + ctx->hwctx = ctx->device->hwctx; - err = av_hwframe_ctx_init(avctx->hw_frames_ctx); - if (err < 0) { - av_log(avctx, AV_LOG_ERROR, "Failed to initialise internal " - "frames context: %d.\n", err); - goto fail; - } - - ctx->hwfc = ctx->frames->hwctx; - } + err = vaapi_decode_make_config(avctx, ctx->frames->device_ref, + &ctx->va_config, avctx->hw_frames_ctx); + if (err) + goto fail; vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, avctx->coded_width, avctx->coded_height, diff --git a/libavcodec/vaapi_decode.h b/libavcodec/vaapi_decode.h index 0ff400e34c154..e195e863a044f 100644 --- a/libavcodec/vaapi_decode.h +++ b/libavcodec/vaapi_decode.h @@ -53,8 +53,6 @@ typedef struct VAAPIDecodePicture { } VAAPIDecodePicture; typedef struct VAAPIDecodeContext { - VAProfile va_profile; - VAEntrypoint va_entrypoint; VAConfigID va_config; VAContextID va_context; @@ -96,4 +94,7 @@ int ff_vaapi_decode_cancel(AVCodecContext *avctx, int ff_vaapi_decode_init(AVCodecContext *avctx); int ff_vaapi_decode_uninit(AVCodecContext *avctx); +int ff_vaapi_common_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx); + #endif /* AVCODEC_VAAPI_DECODE_H */ diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c index f765523005a11..0a5c0dfc76756 100644 --- a/libavcodec/vaapi_h264.c +++ b/libavcodec/vaapi_h264.c @@ -399,6 +399,7 @@ AVHWAccel ff_h264_vaapi_hwaccel = { .frame_priv_data_size = sizeof(VAAPIDecodePicture), .init = &ff_vaapi_decode_init, .uninit = &ff_vaapi_decode_uninit, + .frame_params = &ff_vaapi_common_frame_params, .priv_data_size = sizeof(VAAPIDecodeContext), .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c index 4b4d8782acd91..085d84142d246 100644 --- a/libavcodec/vaapi_hevc.c +++ b/libavcodec/vaapi_hevc.c @@ -434,6 +434,7 @@ AVHWAccel ff_hevc_vaapi_hwaccel = { .frame_priv_data_size = sizeof(VAAPIDecodePictureHEVC), .init = ff_vaapi_decode_init, .uninit = ff_vaapi_decode_uninit, + .frame_params = ff_vaapi_common_frame_params, .priv_data_size = sizeof(VAAPIDecodeContext), .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; diff --git a/libavcodec/vaapi_mpeg2.c b/libavcodec/vaapi_mpeg2.c index a14d115fb065a..5c0a79788fb55 100644 --- a/libavcodec/vaapi_mpeg2.c +++ b/libavcodec/vaapi_mpeg2.c @@ -184,6 +184,7 @@ AVHWAccel ff_mpeg2_vaapi_hwaccel = { .frame_priv_data_size = sizeof(VAAPIDecodePicture), .init = &ff_vaapi_decode_init, .uninit = &ff_vaapi_decode_uninit, + .frame_params = &ff_vaapi_common_frame_params, .priv_data_size = sizeof(VAAPIDecodeContext), .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; diff --git a/libavcodec/vaapi_mpeg4.c b/libavcodec/vaapi_mpeg4.c index b4819b804f4ae..258ae68568399 100644 --- a/libavcodec/vaapi_mpeg4.c +++ b/libavcodec/vaapi_mpeg4.c @@ -200,6 +200,7 @@ AVHWAccel ff_mpeg4_vaapi_hwaccel = { .frame_priv_data_size = sizeof(VAAPIDecodePicture), .init = &ff_vaapi_decode_init, .uninit = &ff_vaapi_decode_uninit, + .frame_params = &ff_vaapi_common_frame_params, .priv_data_size = sizeof(VAAPIDecodeContext), .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; @@ -217,6 +218,7 @@ AVHWAccel ff_h263_vaapi_hwaccel = { .frame_priv_data_size = sizeof(VAAPIDecodePicture), .init = &ff_vaapi_decode_init, .uninit = &ff_vaapi_decode_uninit, + .frame_params = &ff_vaapi_common_frame_params, .priv_data_size = sizeof(VAAPIDecodeContext), .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c index 42634f2baf4b6..8df219f7e2a8d 100644 --- a/libavcodec/vaapi_vc1.c +++ b/libavcodec/vaapi_vc1.c @@ -399,6 +399,7 @@ AVHWAccel ff_wmv3_vaapi_hwaccel = { .frame_priv_data_size = sizeof(VAAPIDecodePicture), .init = &ff_vaapi_decode_init, .uninit = &ff_vaapi_decode_uninit, + .frame_params = &ff_vaapi_common_frame_params, .priv_data_size = sizeof(VAAPIDecodeContext), .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; @@ -415,6 +416,7 @@ AVHWAccel ff_vc1_vaapi_hwaccel = { .frame_priv_data_size = sizeof(VAAPIDecodePicture), .init = &ff_vaapi_decode_init, .uninit = &ff_vaapi_decode_uninit, + .frame_params = &ff_vaapi_common_frame_params, .priv_data_size = sizeof(VAAPIDecodeContext), .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; diff --git a/libavcodec/vaapi_vp8.c b/libavcodec/vaapi_vp8.c index 1ba5c7ec94172..3ccc2bd0abc10 100644 --- a/libavcodec/vaapi_vp8.c +++ b/libavcodec/vaapi_vp8.c @@ -232,5 +232,6 @@ AVHWAccel ff_vp8_vaapi_hwaccel = { .init = &ff_vaapi_decode_init, .uninit = &ff_vaapi_decode_uninit, .priv_data_size = sizeof(VAAPIDecodeContext), + .frame_params = &ff_vaapi_common_frame_params, .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c index 68d0813f658d9..da6fc1e0bf679 100644 --- a/libavcodec/vdpau.c +++ b/libavcodec/vdpau.c @@ -24,6 +24,7 @@ #include #include "avcodec.h" +#include "decode.h" #include "internal.h" #include "h264dec.h" #include "vc1.h" @@ -100,6 +101,25 @@ int av_vdpau_get_surface_parameters(AVCodecContext *avctx, return 0; } +int ff_vdpau_common_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) +{ + AVHWFramesContext *hw_frames = (AVHWFramesContext*)hw_frames_ctx->data; + VdpChromaType type; + uint32_t width; + uint32_t height; + + if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height)) + return AVERROR(EINVAL); + + hw_frames->format = AV_PIX_FMT_VDPAU; + hw_frames->sw_format = avctx->sw_pix_fmt; + hw_frames->width = width; + hw_frames->height = height; + + return 0; +} + int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile, int level) { @@ -115,6 +135,7 @@ int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile, VdpChromaType type; uint32_t width; uint32_t height; + int ret; vdctx->width = UINT32_MAX; vdctx->height = UINT32_MAX; @@ -142,41 +163,14 @@ int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile, type != VDP_CHROMA_TYPE_420) return AVERROR(ENOSYS); } else { - AVHWFramesContext *frames_ctx = NULL; + AVHWFramesContext *frames_ctx; AVVDPAUDeviceContext *dev_ctx; - // We assume the hw_frames_ctx always survives until ff_vdpau_common_uninit - // is called. This holds true as the user is not allowed to touch - // hw_device_ctx, or hw_frames_ctx after get_format (and ff_get_format - // itself also uninits before unreffing hw_frames_ctx). - if (avctx->hw_frames_ctx) { - frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - } else if (avctx->hw_device_ctx) { - int ret; - - avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); - if (!avctx->hw_frames_ctx) - return AVERROR(ENOMEM); - - frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - frames_ctx->format = AV_PIX_FMT_VDPAU; - frames_ctx->sw_format = avctx->sw_pix_fmt; - frames_ctx->width = avctx->coded_width; - frames_ctx->height = avctx->coded_height; - - ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); - if (ret < 0) { - av_buffer_unref(&avctx->hw_frames_ctx); - return ret; - } - } - - if (!frames_ctx) { - av_log(avctx, AV_LOG_ERROR, "A hardware frames context is " - "required for VDPAU decoding.\n"); - return AVERROR(EINVAL); - } + ret = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VDPAU); + if (ret < 0) + return ret; + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; dev_ctx = frames_ctx->device_ctx->hwctx; vdctx->device = dev_ctx->device; diff --git a/libavcodec/vdpau_h264.c b/libavcodec/vdpau_h264.c index a18941848a281..8edbc44021459 100644 --- a/libavcodec/vdpau_h264.c +++ b/libavcodec/vdpau_h264.c @@ -273,6 +273,7 @@ AVHWAccel ff_h264_vdpau_hwaccel = { .frame_priv_data_size = sizeof(struct vdpau_picture_context), .init = vdpau_h264_init, .uninit = ff_vdpau_common_uninit, + .frame_params = ff_vdpau_common_frame_params, .priv_data_size = sizeof(VDPAUContext), .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; diff --git a/libavcodec/vdpau_hevc.c b/libavcodec/vdpau_hevc.c index 399253e2975f4..a177c00e43ba1 100644 --- a/libavcodec/vdpau_hevc.c +++ b/libavcodec/vdpau_hevc.c @@ -424,6 +424,7 @@ AVHWAccel ff_hevc_vdpau_hwaccel = { .frame_priv_data_size = sizeof(struct vdpau_picture_context), .init = vdpau_hevc_init, .uninit = ff_vdpau_common_uninit, + .frame_params = ff_vdpau_common_frame_params, .priv_data_size = sizeof(VDPAUContext), .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; diff --git a/libavcodec/vdpau_internal.h b/libavcodec/vdpau_internal.h index a0eb46c48ed35..8194a9ce36d3d 100644 --- a/libavcodec/vdpau_internal.h +++ b/libavcodec/vdpau_internal.h @@ -119,5 +119,7 @@ int ff_vdpau_common_end_frame(AVCodecContext *avctx, AVFrame *frame, int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx); int ff_vdpau_add_buffer(struct vdpau_picture_context *pic, const uint8_t *buf, uint32_t buf_size); +int ff_vdpau_common_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx); #endif /* AVCODEC_VDPAU_INTERNAL_H */ diff --git a/libavcodec/vdpau_mpeg12.c b/libavcodec/vdpau_mpeg12.c index 2af3201e9560b..db1ba34e03e3c 100644 --- a/libavcodec/vdpau_mpeg12.c +++ b/libavcodec/vdpau_mpeg12.c @@ -149,6 +149,7 @@ AVHWAccel ff_mpeg2_vdpau_hwaccel = { .frame_priv_data_size = sizeof(struct vdpau_picture_context), .init = vdpau_mpeg2_init, .uninit = ff_vdpau_common_uninit, + .frame_params = ff_vdpau_common_frame_params, .priv_data_size = sizeof(VDPAUContext), .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; diff --git a/libavcodec/vdpau_mpeg4.c b/libavcodec/vdpau_mpeg4.c index 4f3d6e54484b1..519866cf0a1c7 100644 --- a/libavcodec/vdpau_mpeg4.c +++ b/libavcodec/vdpau_mpeg4.c @@ -118,6 +118,7 @@ AVHWAccel ff_mpeg4_vdpau_hwaccel = { .frame_priv_data_size = sizeof(struct vdpau_picture_context), .init = vdpau_mpeg4_init, .uninit = ff_vdpau_common_uninit, + .frame_params = ff_vdpau_common_frame_params, .priv_data_size = sizeof(VDPAUContext), .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; diff --git a/libavcodec/vdpau_vc1.c b/libavcodec/vdpau_vc1.c index 251d1aae5d674..45b51304c6d83 100644 --- a/libavcodec/vdpau_vc1.c +++ b/libavcodec/vdpau_vc1.c @@ -143,6 +143,7 @@ AVHWAccel ff_wmv3_vdpau_hwaccel = { .frame_priv_data_size = sizeof(struct vdpau_picture_context), .init = vdpau_vc1_init, .uninit = ff_vdpau_common_uninit, + .frame_params = ff_vdpau_common_frame_params, .priv_data_size = sizeof(VDPAUContext), .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; @@ -159,6 +160,7 @@ AVHWAccel ff_vc1_vdpau_hwaccel = { .frame_priv_data_size = sizeof(struct vdpau_picture_context), .init = vdpau_vc1_init, .uninit = ff_vdpau_common_uninit, + .frame_params = ff_vdpau_common_frame_params, .priv_data_size = sizeof(VDPAUContext), .caps_internal = HWACCEL_CAP_ASYNC_SAFE, }; diff --git a/libavcodec/version.h b/libavcodec/version.h index bc5b8304bd16e..aa6cdcd6bc4c8 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 4 +#define LIBAVCODEC_VERSION_MINOR 5 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From c6496de33456f20144b994ac38f308f2de333608 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 23 Sep 2017 16:35:49 +0200 Subject: [PATCH 0538/2557] configure: Move enabling libc_type into probe_libc() function --- configure | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure b/configure index d74a83e239251..706f1073ee334 100755 --- a/configure +++ b/configure @@ -4147,12 +4147,11 @@ EOF eval ${pfx}libc_type=default add_${pfx}cppflags -D_DEFAULT_SOURCE fi + eval test -n "\${${pfx}libc_type}" && enable ${pfx}libc_${libc_type} } probe_libc -test -n "$libc_type" && enable libc_$libc_type probe_libc host_ -test -n "$host_libc_type" && enable host_libc_$host_libc_type # hacks for compiler/libc/os combinations From 62be1caf161c1241a9e148f347850cfe092588dc Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 24 Sep 2017 11:52:08 +0200 Subject: [PATCH 0539/2557] configure: Bail out early if neither static nor shared libs are built --- configure | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 706f1073ee334..70463ae2c833f 100755 --- a/configure +++ b/configure @@ -2857,6 +2857,17 @@ done disabled logging && logfile=/dev/null +# we need to build at least one lib type +if ! enabled_any static shared; then + cat < Date: Thu, 19 Oct 2017 19:18:18 +0200 Subject: [PATCH 0540/2557] build: Delete compiler-generated compat files on 'make clean' --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 6ea835931885f..b1a2c301b56c3 100644 --- a/Makefile +++ b/Makefile @@ -168,6 +168,7 @@ uninstall-data: clean:: $(RM) $(CLEANSUFFIXES) + $(RM) $(addprefix compat/,$(CLEANSUFFIXES)) $(addprefix compat/*/,$(CLEANSUFFIXES)) $(RM) -rf coverage.info lcov distclean:: From 858db4b01fa2b55ee55056c033054ca54ac9b0fd Mon Sep 17 00:00:00 2001 From: Daniel Kucera Date: Tue, 17 Oct 2017 10:29:30 +0200 Subject: [PATCH 0541/2557] libavformat: not treat 0 as EOF transfer_func variable passed to retry_transfer_wrapper are h->prot->url_read and h->prot->url_write functions. These need to return EOF or other error properly. In case of returning >= 0, url_read/url_write is retried until error is returned. Signed-off-by: Daniel Kucera --- libavformat/avio.c | 6 ++++-- libavformat/aviobuf.c | 20 ++++++++++++-------- libavformat/cache.c | 4 ++-- libavformat/concat.c | 9 +++++---- libavformat/http.c | 5 ++++- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/libavformat/avio.c b/libavformat/avio.c index 64248e098b9e3..4718753b7b99a 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -391,8 +391,10 @@ static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf, } av_usleep(1000); } - } else if (ret < 1) - return (ret < 0 && ret != AVERROR_EOF) ? ret : len; + } else if (ret == AVERROR_EOF) + return (len > 0) ? len : AVERROR_EOF; + else if (ret < 0) + return ret; if (ret) { fast_retries = FFMAX(fast_retries, 2); wait_since = 0; diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 636cb46161ad0..0d4eb051e1219 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -572,13 +572,14 @@ static void fill_buffer(AVIOContext *s) if (s->read_packet) len = s->read_packet(s->opaque, dst, len); else - len = 0; - if (len <= 0) { + len = AVERROR_EOF; + if (len == AVERROR_EOF) { /* do not modify buffer if EOF reached so that a seek back can be done without rereading data */ s->eof_reached = 1; - if (len < 0) - s->error = len; + } else if (len < 0) { + s->eof_reached = 1; + s->error= len; } else { s->pos += len; s->buf_ptr = dst; @@ -646,13 +647,16 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size) // bypass the buffer and read data directly into buf if(s->read_packet) len = s->read_packet(s->opaque, buf, size); - - if (len <= 0) { + else + len = AVERROR_EOF; + if (len == AVERROR_EOF) { /* do not modify buffer if EOF reached so that a seek back can be done without rereading data */ s->eof_reached = 1; - if(len<0) - s->error= len; + break; + } else if (len < 0) { + s->eof_reached = 1; + s->error= len; break; } else { s->pos += len; diff --git a/libavformat/cache.c b/libavformat/cache.c index 6aabca2e7835a..66bbbf54c9abf 100644 --- a/libavformat/cache.c +++ b/libavformat/cache.c @@ -201,7 +201,7 @@ static int cache_read(URLContext *h, unsigned char *buf, int size) } r = ffurl_read(c->inner, buf, size); - if (r == 0 && size>0) { + if (r == AVERROR_EOF && size>0) { c->is_true_eof = 1; av_assert0(c->end >= c->logical_pos); } @@ -263,7 +263,7 @@ static int64_t cache_seek(URLContext *h, int64_t pos, int whence) if (whence == SEEK_SET) size = FFMIN(sizeof(tmp), pos - c->logical_pos); ret = cache_read(h, tmp, size); - if (ret == 0 && whence == SEEK_END) { + if (ret == AVERROR_EOF && whence == SEEK_END) { av_assert0(c->is_true_eof); goto resolve_eof; } diff --git a/libavformat/concat.c b/libavformat/concat.c index 46b520fe80443..19c83c309acff 100644 --- a/libavformat/concat.c +++ b/libavformat/concat.c @@ -135,19 +135,20 @@ static int concat_read(URLContext *h, unsigned char *buf, int size) while (size > 0) { result = ffurl_read(nodes[i].uc, buf, size); - if (result < 0) - return total ? total : result; - if (!result) { + if (result == AVERROR_EOF) { if (i + 1 == data->length || ffurl_seek(nodes[++i].uc, 0, SEEK_SET) < 0) break; + result = 0; } + if (result < 0) + return total ? total : result; total += result; buf += result; size -= result; } data->current = i; - return total; + return total ? total : result; } static int64_t concat_seek(URLContext *h, int64_t pos, int whence) diff --git a/libavformat/http.c b/libavformat/http.c index 668cd51986680..bd9148f45dc1c 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -1296,8 +1296,11 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size) "Chunked encoding data size: %"PRIu64"'\n", s->chunksize); - if (!s->chunksize) + if (!s->chunksize) { + av_log(h, AV_LOG_DEBUG, "Last chunk received, closing conn\n"); + ffurl_closep(&s->hd); return 0; + } else if (s->chunksize == UINT64_MAX) { av_log(h, AV_LOG_ERROR, "Invalid chunk size %"PRIu64"\n", s->chunksize); From 279dc407163ee85d530a15582052a47436110a7b Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Wed, 18 Oct 2017 11:34:06 -0700 Subject: [PATCH 0542/2557] lavc: drop support for OpenJPEG 1.3-2.0 We now require 2.1+ with pkg-config. Signed-off-by: Michael Bradshaw --- Changelog | 2 + configure | 17 +--- libavcodec/libopenjpegdec.c | 103 ++---------------------- libavcodec/libopenjpegenc.c | 156 ++++++------------------------------ 4 files changed, 35 insertions(+), 243 deletions(-) diff --git a/Changelog b/Changelog index 7973d90e6994b..b7c1348f77573 100644 --- a/Changelog +++ b/Changelog @@ -3,6 +3,8 @@ releases are sorted from youngest to oldest. version : - Bitstream filters for editing metadata in H.264, HEVC and MPEG-2 streams +- Dropped support for OpenJPEG versions 2.0 and below. Using OpenJPEG now + requires 2.1 (or later) and pkg-config. version 3.4: diff --git a/configure b/configure index e4c4567138eb5..36279d5874a6c 100755 --- a/configure +++ b/configure @@ -1938,11 +1938,6 @@ HEADERS_LIST=" machine_ioctl_meteor_h malloc_h opencv2_core_core_c_h - openjpeg_2_3_openjpeg_h - openjpeg_2_2_openjpeg_h - openjpeg_2_1_openjpeg_h - openjpeg_2_0_openjpeg_h - openjpeg_1_5_openjpeg_h OpenGL_gl3_h poll_h soundcard_h @@ -6034,16 +6029,8 @@ enabled libopencv && { check_header opencv2/core/core_c.h && require libopencv opencv2/core/core_c.h cvCreateImageHeader -lopencv_core -lopencv_imgproc; } || require_pkg_config libopencv opencv opencv/cxcore.h cvCreateImageHeader; } enabled libopenh264 && require_pkg_config libopenh264 openh264 wels/codec_api.h WelsGetCodecVersion -enabled libopenjpeg && { { check_lib libopenjpeg openjpeg-2.3/openjpeg.h opj_version -lopenjp2 -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } || - check_lib libopenjpeg openjpeg-2.3/openjpeg.h opj_version -lopenjp2 || - { check_lib libopenjpeg openjpeg-2.2/openjpeg.h opj_version -lopenjp2 -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } || - check_lib libopenjpeg openjpeg-2.2/openjpeg.h opj_version -lopenjp2 || - { check_lib libopenjpeg openjpeg-2.1/openjpeg.h opj_version -lopenjp2 -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } || - check_lib libopenjpeg openjpeg-2.1/openjpeg.h opj_version -lopenjp2 || - { check_lib libopenjpeg openjpeg-2.0/openjpeg.h opj_version -lopenjp2 -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } || - { check_lib libopenjpeg openjpeg-1.5/openjpeg.h opj_version -lopenjpeg -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } || - { check_lib libopenjpeg openjpeg.h opj_version -lopenjpeg -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } || - die "ERROR: libopenjpeg not found"; } +enabled libopenjpeg && { use_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version || + { require_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } } enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create -lstdc++ && append libopenmpt_extralibs "-lstdc++" enabled libopus && { enabled libopus_decoder && { diff --git a/libavcodec/libopenjpegdec.c b/libavcodec/libopenjpegdec.c index 67d47bd6a0aa1..daf0a1c565fac 100644 --- a/libavcodec/libopenjpegdec.c +++ b/libavcodec/libopenjpegdec.c @@ -34,27 +34,7 @@ #include "internal.h" #include "thread.h" -#if HAVE_OPENJPEG_2_3_OPENJPEG_H -# include -#elif HAVE_OPENJPEG_2_2_OPENJPEG_H -# include -#elif HAVE_OPENJPEG_2_1_OPENJPEG_H -# include -#elif HAVE_OPENJPEG_2_0_OPENJPEG_H -# include -#elif HAVE_OPENJPEG_1_5_OPENJPEG_H -# include -#else -# include -#endif - -#if HAVE_OPENJPEG_2_3_OPENJPEG_H || HAVE_OPENJPEG_2_2_OPENJPEG_H || HAVE_OPENJPEG_2_1_OPENJPEG_H || HAVE_OPENJPEG_2_0_OPENJPEG_H -# define OPENJPEG_MAJOR_VERSION 2 -# define OPJ(x) OPJ_##x -#else -# define OPENJPEG_MAJOR_VERSION 1 -# define OPJ(x) x -#endif +#include #define JP2_SIG_TYPE 0x6A502020 #define JP2_SIG_VALUE 0x0D0A870A @@ -97,9 +77,6 @@ static const enum AVPixelFormat libopenjpeg_all_pix_fmts[] = { typedef struct LibOpenJPEGContext { AVClass *class; opj_dparameters_t dec_params; -#if OPENJPEG_MAJOR_VERSION == 1 - opj_event_mgr_t event_mgr; -#endif // OPENJPEG_MAJOR_VERSION == 1 int lowqual; } LibOpenJPEGContext; @@ -118,7 +95,6 @@ static void info_callback(const char *msg, void *data) av_log(data, AV_LOG_DEBUG, "%s", msg); } -#if OPENJPEG_MAJOR_VERSION == 2 typedef struct BufferReader { int pos; int size; @@ -176,7 +152,6 @@ static OPJ_BOOL stream_seek(OPJ_OFF_T nb_bytes, void *user_data) reader->pos = (int)nb_bytes; return OPJ_TRUE; } -#endif // OPENJPEG_MAJOR_VERSION == 2 static inline int libopenjpeg_matches_pix_fmt(const opj_image_t *image, enum AVPixelFormat pix_fmt) { @@ -221,15 +196,15 @@ static inline enum AVPixelFormat libopenjpeg_guess_pix_fmt(const opj_image_t *im int possible_fmts_nb = 0; switch (image->color_space) { - case OPJ(CLRSPC_SRGB): + case OPJ_CLRSPC_SRGB: possible_fmts = libopenjpeg_rgb_pix_fmts; possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_rgb_pix_fmts); break; - case OPJ(CLRSPC_GRAY): + case OPJ_CLRSPC_GRAY: possible_fmts = libopenjpeg_gray_pix_fmts; possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_gray_pix_fmts); break; - case OPJ(CLRSPC_SYCC): + case OPJ_CLRSPC_SYCC: possible_fmts = libopenjpeg_yuv_pix_fmts; possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_yuv_pix_fmts); break; @@ -356,14 +331,9 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, int ispacked = 0; int i; opj_image_t *image = NULL; -#if OPENJPEG_MAJOR_VERSION == 1 - opj_dinfo_t *dec = NULL; - opj_cio_t *stream = NULL; -#else // OPENJPEG_MAJOR_VERSION == 2 BufferReader reader = {0, avpkt->size, avpkt->data}; opj_codec_t *dec = NULL; opj_stream_t *stream = NULL; -#endif // OPENJPEG_MAJOR_VERSION == 1 *got_frame = 0; @@ -371,13 +341,13 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, if ((AV_RB32(buf) == 12) && (AV_RB32(buf + 4) == JP2_SIG_TYPE) && (AV_RB32(buf + 8) == JP2_SIG_VALUE)) { - dec = opj_create_decompress(OPJ(CODEC_JP2)); + dec = opj_create_decompress(OPJ_CODEC_JP2); } else { /* If the AVPacket contains a jp2c box, then skip to * the starting byte of the codestream. */ if (AV_RB32(buf + 4) == AV_RB32("jp2c")) buf += 8; - dec = opj_create_decompress(OPJ(CODEC_J2K)); + dec = opj_create_decompress(OPJ_CODEC_J2K); } if (!dec) { @@ -386,15 +356,6 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, goto done; } -#if OPENJPEG_MAJOR_VERSION == 1 - memset(&ctx->event_mgr, 0, sizeof(ctx->event_mgr)); - ctx->event_mgr.info_handler = info_callback; - ctx->event_mgr.error_handler = error_callback; - ctx->event_mgr.warning_handler = warning_callback; - opj_set_event_mgr((opj_common_ptr) dec, &ctx->event_mgr, avctx); - ctx->dec_params.cp_limit_decoding = LIMIT_TO_MAIN_HEADER; - ctx->dec_params.cp_layer = ctx->lowqual; -#else // OPENJPEG_MAJOR_VERSION == 2 if (!opj_set_error_handler(dec, error_callback, avctx) || !opj_set_warning_handler(dec, warning_callback, avctx) || !opj_set_info_handler(dec, info_callback, avctx)) { @@ -405,16 +366,11 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, ctx->dec_params.cp_layer = ctx->lowqual; ctx->dec_params.cp_reduce = avctx->lowres; -#endif // OPENJPEG_MAJOR_VERSION == 1 // Tie decoder with decoding parameters opj_setup_decoder(dec, &ctx->dec_params); -#if OPENJPEG_MAJOR_VERSION == 1 - stream = opj_cio_open((opj_common_ptr) dec, buf, buf_size); -#else // OPENJPEG_MAJOR_VERSION == 2 stream = opj_stream_default_create(OPJ_STREAM_READ); -#endif // OPENJPEG_MAJOR_VERSION == 1 if (!stream) { av_log(avctx, AV_LOG_ERROR, @@ -423,27 +379,13 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, goto done; } -#if OPENJPEG_MAJOR_VERSION == 1 - // Decode the header only. - image = opj_decode_with_info(dec, stream, NULL); - opj_cio_close(stream); - stream = NULL; - ret = !image; -#else // OPENJPEG_MAJOR_VERSION == 2 opj_stream_set_read_function(stream, stream_read); opj_stream_set_skip_function(stream, stream_skip); opj_stream_set_seek_function(stream, stream_seek); -#if HAVE_OPENJPEG_2_3_OPENJPEG_H || HAVE_OPENJPEG_2_2_OPENJPEG_H || HAVE_OPENJPEG_2_1_OPENJPEG_H opj_stream_set_user_data(stream, &reader, NULL); -#elif HAVE_OPENJPEG_2_0_OPENJPEG_H - opj_stream_set_user_data(stream, &reader); -#else -#error Missing call to opj_stream_set_user_data -#endif opj_stream_set_user_data_length(stream, avpkt->size); // Decode the header only. ret = !opj_read_header(stream, dec, &image); -#endif // OPENJPEG_MAJOR_VERSION == 1 if (ret) { av_log(avctx, AV_LOG_ERROR, "Error decoding codestream header.\n"); @@ -477,25 +419,7 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) goto done; -#if OPENJPEG_MAJOR_VERSION == 1 - ctx->dec_params.cp_limit_decoding = NO_LIMITATION; - ctx->dec_params.cp_reduce = avctx->lowres; - // Tie decoder with decoding parameters. - opj_setup_decoder(dec, &ctx->dec_params); - stream = opj_cio_open((opj_common_ptr) dec, buf, buf_size); - if (!stream) { - av_log(avctx, AV_LOG_ERROR, - "Codestream could not be opened for reading.\n"); - ret = AVERROR_EXTERNAL; - goto done; - } - opj_image_destroy(image); - // Decode the codestream - image = opj_decode_with_info(dec, stream, NULL); - ret = !image; -#else // OPENJPEG_MAJOR_VERSION == 2 ret = !opj_decode(dec, stream, image); -#endif // OPENJPEG_MAJOR_VERSION == 1 if (ret) { av_log(avctx, AV_LOG_ERROR, "Error decoding codestream.\n"); @@ -556,25 +480,11 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, done: opj_image_destroy(image); -#if OPENJPEG_MAJOR_VERSION == 2 opj_stream_destroy(stream); opj_destroy_codec(dec); -#else - opj_cio_close(stream); - opj_destroy_decompress(dec); -#endif return ret; } -static av_cold void libopenjpeg_static_init(AVCodec *codec) -{ - const char *version = opj_version(); - int major, minor; - - if (sscanf(version, "%d.%d", &major, &minor) == 2 && 1000*major + minor <= 1003) - codec->capabilities |= AV_CODEC_CAP_EXPERIMENTAL; -} - #define OFFSET(x) offsetof(LibOpenJPEGContext, x) #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM @@ -602,5 +512,4 @@ AVCodec ff_libopenjpeg_decoder = { .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .max_lowres = 31, .priv_class = &openjpeg_class, - .init_static_data = libopenjpeg_static_init, }; diff --git a/libavcodec/libopenjpegenc.c b/libavcodec/libopenjpegenc.c index 92b4433b04759..59fe52d64a232 100644 --- a/libavcodec/libopenjpegenc.c +++ b/libavcodec/libopenjpegenc.c @@ -31,38 +31,11 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "internal.h" - -#if HAVE_OPENJPEG_2_3_OPENJPEG_H -# include -#elif HAVE_OPENJPEG_2_2_OPENJPEG_H -# include -#elif HAVE_OPENJPEG_2_1_OPENJPEG_H -# include -#elif HAVE_OPENJPEG_2_0_OPENJPEG_H -# include -#elif HAVE_OPENJPEG_1_5_OPENJPEG_H -# include -#else -# include -#endif - -#if HAVE_OPENJPEG_2_3_OPENJPEG_H || HAVE_OPENJPEG_2_2_OPENJPEG_H || HAVE_OPENJPEG_2_1_OPENJPEG_H || HAVE_OPENJPEG_2_0_OPENJPEG_H -# define OPENJPEG_MAJOR_VERSION 2 -# define OPJ(x) OPJ_##x -#else -# define OPENJPEG_MAJOR_VERSION 1 -# define OPJ(x) x -#endif +#include typedef struct LibOpenJPEGContext { AVClass *avclass; -#if OPENJPEG_MAJOR_VERSION == 1 - opj_image_t *image; -#endif // OPENJPEG_MAJOR_VERSION == 1 opj_cparameters_t enc_params; -#if OPENJPEG_MAJOR_VERSION == 1 - opj_event_mgr_t event_mgr; -#endif // OPENJPEG_MAJOR_VERSION == 1 int format; int profile; int prog_order; @@ -88,7 +61,6 @@ static void info_callback(const char *msg, void *data) av_log(data, AV_LOG_DEBUG, "%s\n", msg); } -#if OPENJPEG_MAJOR_VERSION == 2 typedef struct PacketWriter { int pos; AVPacket *packet; @@ -158,7 +130,6 @@ static OPJ_BOOL stream_seek(OPJ_OFF_T nb_bytes, void *user_data) writer->pos = (int)nb_bytes; return OPJ_TRUE; } -#endif // OPENJPEG_MAJOR_VERSION == 2 static void cinema_parameters(opj_cparameters_t *p) { @@ -182,7 +153,7 @@ static void cinema_parameters(opj_cparameters_t *p) p->csty |= 0x01; /* The progression order shall be CPRL */ - p->prog_order = OPJ(CPRL); + p->prog_order = OPJ_CPRL; /* No ROI */ p->roi_compno = -1; @@ -206,7 +177,7 @@ static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *p int sub_dx[4]; int sub_dy[4]; int numcomps; - OPJ_COLOR_SPACE color_space = OPJ(CLRSPC_UNKNOWN); + OPJ_COLOR_SPACE color_space = OPJ_CLRSPC_UNKNOWN; sub_dx[0] = sub_dx[3] = 1; sub_dy[0] = sub_dy[3] = 1; @@ -220,7 +191,7 @@ static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *p case AV_PIX_FMT_YA8: case AV_PIX_FMT_GRAY16: case AV_PIX_FMT_YA16: - color_space = OPJ(CLRSPC_GRAY); + color_space = OPJ_CLRSPC_GRAY; break; case AV_PIX_FMT_RGB24: case AV_PIX_FMT_RGBA: @@ -233,7 +204,7 @@ static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *p case AV_PIX_FMT_GBRP14: case AV_PIX_FMT_GBRP16: case AV_PIX_FMT_XYZ12: - color_space = OPJ(CLRSPC_SRGB); + color_space = OPJ_CLRSPC_SRGB; break; case AV_PIX_FMT_YUV410P: case AV_PIX_FMT_YUV411P: @@ -268,7 +239,7 @@ static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *p case AV_PIX_FMT_YUVA420P16: case AV_PIX_FMT_YUVA422P16: case AV_PIX_FMT_YUVA444P16: - color_space = OPJ(CLRSPC_SYCC); + color_space = OPJ_CLRSPC_SYCC; break; default: av_log(avctx, AV_LOG_ERROR, @@ -309,7 +280,6 @@ static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx) opj_set_default_encoder_parameters(&ctx->enc_params); -#if HAVE_OPENJPEG_2_3_OPENJPEG_H || HAVE_OPENJPEG_2_2_OPENJPEG_H || HAVE_OPENJPEG_2_1_OPENJPEG_H switch (ctx->cinema_mode) { case OPJ_CINEMA2K_24: ctx->enc_params.rsiz = OPJ_PROFILE_CINEMA_2K; @@ -348,12 +318,8 @@ static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx) if (err) { av_log(avctx, AV_LOG_ERROR, "Invalid parameter pairing: cinema_mode and profile conflict.\n"); - goto fail; + return err; } -#else - ctx->enc_params.cp_rsiz = ctx->profile; - ctx->enc_params.cp_cinema = ctx->cinema_mode; -#endif if (!ctx->numresolution) { ctx->numresolution = 6; @@ -373,23 +339,7 @@ static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx) cinema_parameters(&ctx->enc_params); } -#if OPENJPEG_MAJOR_VERSION == 1 - ctx->image = mj2_create_image(avctx, &ctx->enc_params); - if (!ctx->image) { - av_log(avctx, AV_LOG_ERROR, "Error creating the mj2 image\n"); - err = AVERROR(EINVAL); - goto fail; - } -#endif // OPENJPEG_MAJOR_VERSION == 1 - return 0; - -fail: -#if OPENJPEG_MAJOR_VERSION == 1 - opj_image_destroy(ctx->image); - ctx->image = NULL; -#endif // OPENJPEG_MAJOR_VERSION == 1 - return err; } static int libopenjpeg_copy_packed8(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) @@ -602,12 +552,6 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, int ret; AVFrame *gbrframe; int cpyresult = 0; -#if OPENJPEG_MAJOR_VERSION == 1 - opj_image_t *image = ctx->image; - opj_cinfo_t *compress = NULL; - opj_cio_t *stream = NULL; - int len; -#else // OPENJPEG_MAJOR_VERSION == 2 PacketWriter writer = { 0 }; opj_codec_t *compress = NULL; opj_stream_t *stream = NULL; @@ -617,7 +561,6 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, ret = AVERROR(EINVAL); goto done; } -#endif // OPENJPEG_MAJOR_VERSION == 1 switch (avctx->pix_fmt) { case AV_PIX_FMT_RGB24: @@ -712,11 +655,9 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, goto done; } -#if OPENJPEG_MAJOR_VERSION == 2 if ((ret = ff_alloc_packet2(avctx, pkt, 1024, 0)) < 0) { goto done; } -#endif // OPENJPEG_MAJOR_VERSION == 2 compress = opj_create_compress(ctx->format); if (!compress) { @@ -725,10 +666,6 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, goto done; } -#if OPENJPEG_MAJOR_VERSION == 1 - opj_setup_encoder(compress, &ctx->enc_params, image); - stream = opj_cio_open((opj_common_ptr) compress, NULL, 0); -#else // OPENJPEG_MAJOR_VERSION == 2 if (!opj_set_error_handler(compress, error_callback, avctx) || !opj_set_warning_handler(compress, warning_callback, avctx) || !opj_set_info_handler(compress, info_callback, avctx)) { @@ -743,43 +680,18 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, goto done; } stream = opj_stream_default_create(OPJ_STREAM_WRITE); -#endif // OPENJPEG_MAJOR_VERSION == 1 if (!stream) { av_log(avctx, AV_LOG_ERROR, "Error creating the cio stream\n"); ret = AVERROR(ENOMEM); goto done; } -#if OPENJPEG_MAJOR_VERSION == 1 - memset(&ctx->event_mgr, 0, sizeof(ctx->event_mgr)); - ctx->event_mgr.info_handler = info_callback; - ctx->event_mgr.error_handler = error_callback; - ctx->event_mgr.warning_handler = warning_callback; - opj_set_event_mgr((opj_common_ptr) compress, &ctx->event_mgr, avctx); - if (!opj_encode(compress, stream, image, NULL)) { - av_log(avctx, AV_LOG_ERROR, "Error during the opj encode\n"); - ret = AVERROR_EXTERNAL; - goto done; - } - len = cio_tell(stream); - if ((ret = ff_alloc_packet2(avctx, pkt, len, 0)) < 0) { - goto done; - } - - memcpy(pkt->data, stream->buffer, len); -#else // OPENJPEG_MAJOR_VERSION == 2 writer.packet = pkt; opj_stream_set_write_function(stream, stream_write); opj_stream_set_skip_function(stream, stream_skip); opj_stream_set_seek_function(stream, stream_seek); -#if HAVE_OPENJPEG_2_3_OPENJPEG_H || HAVE_OPENJPEG_2_2_OPENJPEG_H || HAVE_OPENJPEG_2_1_OPENJPEG_H opj_stream_set_user_data(stream, &writer, NULL); -#elif HAVE_OPENJPEG_2_0_OPENJPEG_H - opj_stream_set_user_data(stream, &writer); -#else -#error Missing call to opj_stream_set_user_data -#endif if (!opj_start_compress(compress, image, stream) || !opj_encode(compress, stream) || @@ -790,56 +702,39 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } av_shrink_packet(pkt, writer.pos); -#endif // OPENJPEG_MAJOR_VERSION == 1 pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; ret = 0; done: -#if OPENJPEG_MAJOR_VERSION == 2 opj_stream_destroy(stream); opj_destroy_codec(compress); opj_image_destroy(image); -#else - opj_cio_close(stream); - opj_destroy_compress(compress); -#endif return ret; } -static av_cold int libopenjpeg_encode_close(AVCodecContext *avctx) -{ -#if OPENJPEG_MAJOR_VERSION == 1 - LibOpenJPEGContext *ctx = avctx->priv_data; - - opj_image_destroy(ctx->image); - ctx->image = NULL; -#endif // OPENJPEG_MAJOR_VERSION == 1 - return 0; -} - #define OFFSET(x) offsetof(LibOpenJPEGContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "format", "Codec Format", OFFSET(format), AV_OPT_TYPE_INT, { .i64 = OPJ(CODEC_JP2) }, OPJ(CODEC_J2K), OPJ(CODEC_JP2), VE, "format" }, - { "j2k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(CODEC_J2K) }, 0, 0, VE, "format" }, - { "jp2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(CODEC_JP2) }, 0, 0, VE, "format" }, - { "profile", NULL, OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = OPJ(STD_RSIZ) }, OPJ(STD_RSIZ), OPJ(CINEMA4K), VE, "profile" }, - { "jpeg2000", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(STD_RSIZ) }, 0, 0, VE, "profile" }, - { "cinema2k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(CINEMA2K) }, 0, 0, VE, "profile" }, - { "cinema4k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(CINEMA4K) }, 0, 0, VE, "profile" }, - { "cinema_mode", "Digital Cinema", OFFSET(cinema_mode), AV_OPT_TYPE_INT, { .i64 = OPJ(OFF) }, OPJ(OFF), OPJ(CINEMA4K_24), VE, "cinema_mode" }, - { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(OFF) }, 0, 0, VE, "cinema_mode" }, - { "2k_24", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(CINEMA2K_24) }, 0, 0, VE, "cinema_mode" }, - { "2k_48", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(CINEMA2K_48) }, 0, 0, VE, "cinema_mode" }, - { "4k_24", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(CINEMA4K_24) }, 0, 0, VE, "cinema_mode" }, - { "prog_order", "Progression Order", OFFSET(prog_order), AV_OPT_TYPE_INT, { .i64 = OPJ(LRCP) }, OPJ(LRCP), OPJ(CPRL), VE, "prog_order" }, - { "lrcp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(LRCP) }, 0, 0, VE, "prog_order" }, - { "rlcp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(RLCP) }, 0, 0, VE, "prog_order" }, - { "rpcl", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(RPCL) }, 0, 0, VE, "prog_order" }, - { "pcrl", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(PCRL) }, 0, 0, VE, "prog_order" }, - { "cprl", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ(CPRL) }, 0, 0, VE, "prog_order" }, + { "format", "Codec Format", OFFSET(format), AV_OPT_TYPE_INT, { .i64 = OPJ_CODEC_JP2 }, OPJ_CODEC_J2K, OPJ_CODEC_JP2, VE, "format" }, + { "j2k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_CODEC_J2K }, 0, 0, VE, "format" }, + { "jp2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_CODEC_JP2 }, 0, 0, VE, "format" }, + { "profile", NULL, OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = OPJ_STD_RSIZ }, OPJ_STD_RSIZ, OPJ_CINEMA4K, VE, "profile" }, + { "jpeg2000", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_STD_RSIZ }, 0, 0, VE, "profile" }, + { "cinema2k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_CINEMA2K }, 0, 0, VE, "profile" }, + { "cinema4k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_CINEMA4K }, 0, 0, VE, "profile" }, + { "cinema_mode", "Digital Cinema", OFFSET(cinema_mode), AV_OPT_TYPE_INT, { .i64 = OPJ_OFF }, OPJ_OFF, OPJ_CINEMA4K_24, VE, "cinema_mode" }, + { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_OFF }, 0, 0, VE, "cinema_mode" }, + { "2k_24", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_CINEMA2K_24 }, 0, 0, VE, "cinema_mode" }, + { "2k_48", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_CINEMA2K_48 }, 0, 0, VE, "cinema_mode" }, + { "4k_24", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_CINEMA4K_24 }, 0, 0, VE, "cinema_mode" }, + { "prog_order", "Progression Order", OFFSET(prog_order), AV_OPT_TYPE_INT, { .i64 = OPJ_LRCP }, OPJ_LRCP, OPJ_CPRL, VE, "prog_order" }, + { "lrcp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_LRCP }, 0, 0, VE, "prog_order" }, + { "rlcp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_RLCP }, 0, 0, VE, "prog_order" }, + { "rpcl", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_RPCL }, 0, 0, VE, "prog_order" }, + { "pcrl", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_PCRL }, 0, 0, VE, "prog_order" }, + { "cprl", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OPJ_CPRL }, 0, 0, VE, "prog_order" }, { "numresolution", NULL, OFFSET(numresolution), AV_OPT_TYPE_INT, { .i64 = 6 }, 0, 33, VE }, { "irreversible", NULL, OFFSET(irreversible), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, { "disto_alloc", NULL, OFFSET(disto_alloc), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, @@ -862,7 +757,6 @@ AVCodec ff_libopenjpeg_encoder = { .priv_data_size = sizeof(LibOpenJPEGContext), .init = libopenjpeg_encode_init, .encode2 = libopenjpeg_encode_frame, - .close = libopenjpeg_encode_close, .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48, From a5fd8aa45b11c10613e6e576033a6b5a16b9cbb9 Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Mon, 16 Oct 2017 14:17:35 -0700 Subject: [PATCH 0543/2557] avformat/mov: Set start_pad correctly in mov_fix_index() Sets the correct start padding value when an edit list is present. A new fate test is added, fate-mov-440hz-10ms, to ensure this is handled correctly. Signed-off-by: Dale Curtis Reviewed-by: Sasi Inguva Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 2 +- tests/fate/mov.mak | 4 ++++ tests/ref/fate/mov-440hz-10ms | 11 +++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/ref/fate/mov-440hz-10ms diff --git a/libavformat/mov.c b/libavformat/mov.c index b22a1161401d1..573f134d2d9fa 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3249,7 +3249,6 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) // Increment skip_samples for the first non-zero audio edit list if (first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) { st->skip_samples += frame_duration; - msc->start_pad = st->skip_samples; } } } @@ -3323,6 +3322,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) // Update av stream length st->duration = edit_list_dts_entry_end - start_dts; + msc->start_pad = st->skip_samples; // Free the old index and the old CTTS structures av_free(e_old); diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index cfdada7a2e070..5013e7d528885 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -7,6 +7,7 @@ FATE_MOV = fate-mov-3elist \ fate-mov-2elist-elist1-ends-bframe \ fate-mov-3elist-encrypted \ fate-mov-gpmf-remux \ + fate-mov-440hz-10ms \ FATE_MOV_FFPROBE = fate-mov-aac-2048-priming \ fate-mov-zombie \ @@ -39,6 +40,9 @@ fate-mov-1elist-ends-last-bframe: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/mov-1e # Makes sure that we handle timestamps of packets in case of multiple edit lists with one of them ending on a B-frame correctly. fate-mov-2elist-elist1-ends-bframe: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/mov-2elist-elist1-ends-bframe.mov +# Makes sure that we handle edit lists and start padding correctly. +fate-mov-440hz-10ms: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/440hz-10ms.m4a + fate-mov-aac-2048-priming: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_packets -print_format compact $(TARGET_SAMPLES)/mov/aac-2048-priming.mov fate-mov-zombie: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_streams -show_packets -show_frames -bitexact -print_format compact $(TARGET_SAMPLES)/mov/white_zombie_scrunch-part.mov diff --git a/tests/ref/fate/mov-440hz-10ms b/tests/ref/fate/mov-440hz-10ms new file mode 100644 index 0000000000000..498879e52db52 --- /dev/null +++ b/tests/ref/fate/mov-440hz-10ms @@ -0,0 +1,11 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 44100 +#channel_layout 0: 4 +#channel_layout_name 0: mono +#stream#, dts, pts, duration, size, hash +0, 0, 0, 960, 1920, 44e7e48ff08835ce30e93c7971dae7df From 535117d1f6deba266654b8a43cd5bd7630045fd3 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sat, 21 Oct 2017 20:22:52 +0200 Subject: [PATCH 0544/2557] lavd/lavfi: Constify two variables. Fixes the following warnings: libavdevice/lavfi.c:136:16: warning: assignment discards 'const' qualifier from pointer target type libavdevice/lavfi.c:137:17: warning: assignment discards 'const' qualifier from pointer target type --- libavdevice/lavfi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index ede391f4d6bb4..986e579813aed 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -121,7 +121,7 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) { LavfiContext *lavfi = avctx->priv_data; AVFilterInOut *input_links = NULL, *output_links = NULL, *inout; - AVFilter *buffersink, *abuffersink; + const AVFilter *buffersink, *abuffersink; int *pix_fmts = create_all_formats(AV_PIX_FMT_NB); enum AVMediaType type; int ret = 0, i, n; From ea049ad862a4b2b398bbdade5af36291d786e02d Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sat, 21 Oct 2017 20:24:49 +0200 Subject: [PATCH 0545/2557] lavfi/graphparser: Constify a variable. Fixes the following warning: libavfilter/graphparser.c:122:10: warning: assignment discards 'const' qualifier from pointer target type --- libavfilter/graphparser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index 1405926bfd570..d92b5360a6afd 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -96,7 +96,7 @@ static char *parse_link_name(const char **buf, void *log_ctx) static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int index, const char *name, const char *args, void *log_ctx) { - AVFilter *filt; + const AVFilter *filt; char name2[30]; const char *inst_name = NULL, *filt_name = NULL; char *tmp_args = NULL; From 75bd2157272a963dc42e46762324741805c593ca Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 21 Oct 2017 16:26:07 -0300 Subject: [PATCH 0546/2557] avcodec/version: re-enable FF_API_MPV_OPT until the open ABI period is over ffserver depends on it, so keep it in place until the two can be removed together. --- libavcodec/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 9f1543a6aa4c6..1d4e5df596bec 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -161,7 +161,7 @@ #define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 59) #endif #ifndef FF_API_MPV_OPT -#define FF_API_MPV_OPT (LIBAVCODEC_VERSION_MAJOR < 58) +#define FF_API_MPV_OPT (LIBAVCODEC_VERSION_MAJOR < 59) #endif #ifndef FF_API_STREAM_CODEC_TAG #define FF_API_STREAM_CODEC_TAG (LIBAVCODEC_VERSION_MAJOR < 58) From efb79cabb2c801c9e76a0af6c72121f547ab7f59 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 21 Oct 2017 21:02:35 +0100 Subject: [PATCH 0547/2557] libavcodec/version: add a comment about FF_API_MPV_OPT deprecation In order to prevent it from being forgotten and delayed until the next bump. Signed-off-by: Rostislav Pehlivanov --- libavcodec/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 1d4e5df596bec..8584bb7006ffa 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -160,8 +160,8 @@ #ifndef FF_API_AVCTX_TIMEBASE #define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 59) #endif -#ifndef FF_API_MPV_OPT -#define FF_API_MPV_OPT (LIBAVCODEC_VERSION_MAJOR < 59) +#ifndef FF_API_MPV_OPT /* To be removed with ffserver removal */ +#define FF_API_MPV_OPT 1 #endif #ifndef FF_API_STREAM_CODEC_TAG #define FF_API_STREAM_CODEC_TAG (LIBAVCODEC_VERSION_MAJOR < 58) From d3a3ee9c7a736c664789494ce6c09c330f7b1499 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 21 Oct 2017 17:48:01 -0300 Subject: [PATCH 0548/2557] ffserver: remove usage of deprecated rc_eq option The private codec option will be used instead when available. --- fftools/ffserver_config.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fftools/ffserver_config.c b/fftools/ffserver_config.c index 54135be989c90..71b50106beb8c 100644 --- a/fftools/ffserver_config.c +++ b/fftools/ffserver_config.c @@ -291,11 +291,9 @@ static void add_codec(FFServerStream *stream, AVCodecContext *av, } if (!av_dict_get(recommended, "rc_eq", NULL, 0)) { - av->rc_eq = av_strdup("tex^qComp"); av_dict_set(&recommended, "rc_eq", "tex^qComp", 0); WARNING("Setting default value for video rate control equation = " - "%s. Use NoDefaults to disable it.\n", - av->rc_eq); + "tex^qComp. Use NoDefaults to disable it.\n"); } if (!av_dict_get(recommended, "maxrate", NULL, 0)) { av->rc_max_rate = av->bit_rate * 2; From 5ae972f63b7684950eec28c81cb180e05457f109 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 21 Oct 2017 18:19:02 -0300 Subject: [PATCH 0549/2557] avcodec/v4l2_m2m_enc: fix usage of deprecated codec flag --- libavcodec/v4l2_m2m_enc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c index f71ce5fb74af1..76ce85fdaac5e 100644 --- a/libavcodec/v4l2_m2m_enc.c +++ b/libavcodec/v4l2_m2m_enc.c @@ -204,7 +204,7 @@ static int v4l2_prepare_encoder(V4L2m2mContext *s) v4l2_set_ext_ctrl(s, MPEG_CID(MPEG4_PROFILE), val, "mpeg4 profile"); qmin_cid = MPEG_CID(MPEG4_MIN_QP); qmax_cid = MPEG_CID(MPEG4_MAX_QP); - if (avctx->flags & CODEC_FLAG_QPEL) + if (avctx->flags & AV_CODEC_FLAG_QPEL) v4l2_set_ext_ctrl(s, MPEG_CID(MPEG4_QPEL), 1, "qpel"); qmin = 1; qmax = 31; From 4dee92f6bc8b89e9c335ab737412bf18f3a99be3 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 27 Sep 2017 01:44:21 +0100 Subject: [PATCH 0550/2557] hevc: Fix aligned array declarations (cherry picked from commit d41e10c1485ec34aa342f7bc2e5bf4f9b6e66414) --- libavcodec/hevcdec.h | 2 +- libavcodec/hevcdsp.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 293beb70832d0..ada2903222004 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -363,7 +363,7 @@ typedef struct HEVCLocalContext { DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[(MAX_PB_SIZE + 7) * EDGE_EMU_BUFFER_STRIDE * 2]; /* The extended size between the new edge emu buffer is abused by SAO */ DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer2)[(MAX_PB_SIZE + 7) * EDGE_EMU_BUFFER_STRIDE * 2]; - DECLARE_ALIGNED(32, int16_t, tmp [MAX_PB_SIZE * MAX_PB_SIZE]); + DECLARE_ALIGNED(32, int16_t, tmp)[MAX_PB_SIZE * MAX_PB_SIZE]; int ct_depth; CodingUnit cu; diff --git a/libavcodec/hevcdsp.c b/libavcodec/hevcdsp.c index 76ae72b6d4c97..e432aa3cf9abc 100644 --- a/libavcodec/hevcdsp.c +++ b/libavcodec/hevcdsp.c @@ -91,7 +91,7 @@ static const int8_t transform[32][32] = { 90, -90, 88, -85, 82, -78, 73, -67, 61, -54, 46, -38, 31, -22, 13, -4 }, }; -DECLARE_ALIGNED(16, const int8_t, ff_hevc_epel_filters[7][4]) = { +DECLARE_ALIGNED(16, const int8_t, ff_hevc_epel_filters)[7][4] = { { -2, 58, 10, -2}, { -4, 54, 16, -2}, { -6, 46, 28, -4}, @@ -101,7 +101,7 @@ DECLARE_ALIGNED(16, const int8_t, ff_hevc_epel_filters[7][4]) = { { -2, 10, 58, -2}, }; -DECLARE_ALIGNED(16, const int8_t, ff_hevc_qpel_filters[3][16]) = { +DECLARE_ALIGNED(16, const int8_t, ff_hevc_qpel_filters)[3][16] = { { -1, 4,-10, 58, 17, -5, 1, 0, -1, 4,-10, 58, 17, -5, 1, 0}, { -1, 4,-11, 40, 40,-11, 4, -1, -1, 4,-11, 40, 40,-11, 4, -1}, { 0, 1, -5, 17, 58,-10, 4, -1, 0, 1, -5, 17, 58,-10, 4, -1} From e0a967a405463ac581b5861b8bf45fa67c4a3a2f Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 27 Sep 2017 01:48:37 +0100 Subject: [PATCH 0551/2557] cinepakenc: Move declaration out of for initialisation statement (cherry picked from commit 92f0aceb36c6e4412d4cf346e70dc74b5a4069e9) --- libavcodec/cinepakenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index a28f6690708f6..330c8827d1c20 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -994,8 +994,9 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, #define SMALLEST_CODEBOOK 1 for(v1enough = 0, v1_size = SMALLEST_CODEBOOK; v1_size <= CODEBOOK_MAX && !v1enough; v1_size <<= 2) { for(v4enough = 0, v4_size = 0; v4_size <= v1_size && !v4enough; v4_size = v4_size ? v4_size << 2 : v1_size >= SMALLEST_CODEBOOK << 2 ? v1_size >> 2 : SMALLEST_CODEBOOK) { + CinepakMode mode; //try all modes - for(CinepakMode mode = 0; mode < MODE_COUNT; mode++) { + for(mode = 0; mode < MODE_COUNT; mode++) { //don't allow MODE_MC in intra frames if(keyframe && mode == MODE_MC) continue; From e7d20d5e3500a24d9713572cfb641d415e6beffa Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 17 Oct 2017 21:28:25 +0100 Subject: [PATCH 0552/2557] movtextdec: Move declaration out of for initialisation statement --- libavcodec/movtextdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index fb5085c3e8222..bd19577724e23 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -436,6 +436,7 @@ static int mov_text_decode_frame(AVCodecContext *avctx, int text_length, tsmb_type, ret_tsmb; uint64_t tsmb_size; const uint8_t *tsmb; + size_t i; if (!ptr || avpkt->size < 2) return AVERROR_INVALIDDATA; @@ -495,7 +496,7 @@ static int mov_text_decode_frame(AVCodecContext *avctx, if (tsmb_size > avpkt->size - m->tracksize) break; - for (size_t i = 0; i < box_count; i++) { + for (i = 0; i < box_count; i++) { if (tsmb_type == box_types[i].type) { if (m->tracksize + m->size_var + box_types[i].base_size > avpkt->size) break; From e08897619e0e358a37d125bbebd51e3b73d85136 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 21 Oct 2017 18:34:02 -0300 Subject: [PATCH 0553/2557] avcodec/libxvid: make 4 the default for me_quality This will make the default behavior the same as it was with me_method. --- libavcodec/libxvid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c index d916f117141eb..6dd5d8d7a2b2e 100644 --- a/libavcodec/libxvid.c +++ b/libavcodec/libxvid.c @@ -938,7 +938,7 @@ static const AVOption options[] = { { "frame", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "ssim" }, { "ssim_acc", "SSIM accuracy", OFFSET(ssim_acc), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 4, VE }, { "gmc", "use GMC", OFFSET(gmc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, - { "me_quality", "Motion estimation quality", OFFSET(me_quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 6, VE }, + { "me_quality", "Motion estimation quality", OFFSET(me_quality), AV_OPT_TYPE_INT, { .i64 = 4 }, 0, 6, VE }, { "mpeg_quant", "Use MPEG quantizers instead of H.263", OFFSET(mpeg_quant), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, { NULL }, }; From 88e2e31d3460c88fefe17f30d585ec079883f42e Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 21 Oct 2017 18:37:38 -0300 Subject: [PATCH 0554/2557] avcodec/libxavs: make dia the default for motion-est This will make the default behavior the same as it was with me_method. --- libavcodec/libxavs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c index f257e5584d91f..7eb3083da725c 100644 --- a/libavcodec/libxavs.c +++ b/libavcodec/libxavs.c @@ -465,7 +465,7 @@ static const AVOption options[] = { { "mbtree", "Use macroblock tree ratecontrol.", OFFSET(mbtree), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE}, { "mixed-refs", "One reference per partition, as opposed to one reference per macroblock", OFFSET(mixed_refs), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE }, { "fast-pskip", NULL, OFFSET(fast_pskip), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE}, - { "motion-est", "Set motion estimation method", OFFSET(motion_est), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, XAVS_ME_TESA, VE, "motion-est"}, + { "motion-est", "Set motion estimation method", OFFSET(motion_est), AV_OPT_TYPE_INT, { .i64 = XAVS_ME_DIA }, -1, XAVS_ME_TESA, VE, "motion-est"}, { "dia", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = XAVS_ME_DIA }, INT_MIN, INT_MAX, VE, "motion-est" }, { "hex", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = XAVS_ME_HEX }, INT_MIN, INT_MAX, VE, "motion-est" }, { "umh", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = XAVS_ME_UMH }, INT_MIN, INT_MAX, VE, "motion-est" }, From d4d2e9fe4e1e93d37fd543092e45041f58fa8c00 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 21 Oct 2017 22:08:08 -0300 Subject: [PATCH 0555/2557] avformat: Drop deprecated feof() AVIO fuction Deprecated in 08/2014. --- libavformat/avio.h | 7 ------- libavformat/aviobuf.c | 7 ------- libavformat/libavformat.v | 2 -- libavformat/version.h | 3 --- 4 files changed, 19 deletions(-) diff --git a/libavformat/avio.h b/libavformat/avio.h index f9c5972adae65..19ecd96eb77ab 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -569,13 +569,6 @@ int64_t avio_size(AVIOContext *s); * @return non zero if and only if end of file */ int avio_feof(AVIOContext *s); -#if FF_API_URL_FEOF -/** - * @deprecated use avio_feof() - */ -attribute_deprecated -int url_feof(AVIOContext *s); -#endif /** @warning Writes up to 4 KiB per call */ int avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3); diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 0d4eb051e1219..3e9d774a1311d 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -364,13 +364,6 @@ int avio_feof(AVIOContext *s) return s->eof_reached; } -#if FF_API_URL_FEOF -int url_feof(AVIOContext *s) -{ - return avio_feof(s); -} -#endif - void avio_wl32(AVIOContext *s, unsigned int val) { avio_w8(s, (uint8_t) val ); diff --git a/libavformat/libavformat.v b/libavformat/libavformat.v index c961cd8f19ccd..291a38f8e7714 100644 --- a/libavformat/libavformat.v +++ b/libavformat/libavformat.v @@ -12,8 +12,6 @@ LIBAVFORMAT_MAJOR { ffurl_close; ffurl_open; ffurl_write; - #those are deprecated, remove on next bump - url_feof; local: *; }; diff --git a/libavformat/version.h b/libavformat/version.h index 8e940597ee68a..c0cd7dd409eea 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -55,9 +55,6 @@ * at once through the bump. This improves the git bisect-ability of the change. * */ -#ifndef FF_API_URL_FEOF -#define FF_API_URL_FEOF (LIBAVFORMAT_VERSION_MAJOR < 58) -#endif #ifndef FF_API_LAVF_FMT_RAWPICTURE #define FF_API_LAVF_FMT_RAWPICTURE (LIBAVFORMAT_VERSION_MAJOR < 58) #endif From 32e18dbfe8e4a0781c09e96512c302019de7f69f Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 21 Oct 2017 17:55:08 -0300 Subject: [PATCH 0556/2557] Revert efb79cabb2 and 75bd215727 ffserver usage of rc_eq was fixed. Signed-off-by: James Almer --- libavcodec/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 8584bb7006ffa..9f1543a6aa4c6 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -160,8 +160,8 @@ #ifndef FF_API_AVCTX_TIMEBASE #define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 59) #endif -#ifndef FF_API_MPV_OPT /* To be removed with ffserver removal */ -#define FF_API_MPV_OPT 1 +#ifndef FF_API_MPV_OPT +#define FF_API_MPV_OPT (LIBAVCODEC_VERSION_MAJOR < 58) #endif #ifndef FF_API_STREAM_CODEC_TAG #define FF_API_STREAM_CODEC_TAG (LIBAVCODEC_VERSION_MAJOR < 58) From 8f483108b503fa03ed5e956e25df4cb899171df5 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 21 Oct 2017 23:13:44 -0300 Subject: [PATCH 0557/2557] avcodec: Drop deprecated audio resample API Deprecated in 03/2013. --- libavcodec/Makefile | 2 - libavcodec/avcodec.h | 97 --------- libavcodec/resample.c | 439 ----------------------------------------- libavcodec/resample2.c | 319 ------------------------------ libavcodec/version.h | 3 - 5 files changed, 860 deletions(-) delete mode 100644 libavcodec/resample.c delete mode 100644 libavcodec/resample2.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index b52e5ada7ab58..651348972ebde 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -45,8 +45,6 @@ OBJS = allcodecs.o \ profiles.o \ qsv_api.o \ raw.o \ - resample.o \ - resample2.o \ utils.o \ vorbis_parser.o \ xiph.o \ diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 42d230ea96f52..6922b5b6fc827 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -5516,103 +5516,6 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, * @} */ -#if FF_API_AVCODEC_RESAMPLE -/** - * @defgroup lavc_resample Audio resampling - * @ingroup libavc - * @deprecated use libswresample instead - * - * @{ - */ -struct ReSampleContext; -struct AVResampleContext; - -typedef struct ReSampleContext ReSampleContext; - -/** - * Initialize audio resampling context. - * - * @param output_channels number of output channels - * @param input_channels number of input channels - * @param output_rate output sample rate - * @param input_rate input sample rate - * @param sample_fmt_out requested output sample format - * @param sample_fmt_in input sample format - * @param filter_length length of each FIR filter in the filterbank relative to the cutoff frequency - * @param log2_phase_count log2 of the number of entries in the polyphase filterbank - * @param linear if 1 then the used FIR filter will be linearly interpolated - between the 2 closest, if 0 the closest will be used - * @param cutoff cutoff frequency, 1.0 corresponds to half the output sampling rate - * @return allocated ReSampleContext, NULL if error occurred - */ -attribute_deprecated -ReSampleContext *av_audio_resample_init(int output_channels, int input_channels, - int output_rate, int input_rate, - enum AVSampleFormat sample_fmt_out, - enum AVSampleFormat sample_fmt_in, - int filter_length, int log2_phase_count, - int linear, double cutoff); - -attribute_deprecated -int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples); - -/** - * Free resample context. - * - * @param s a non-NULL pointer to a resample context previously - * created with av_audio_resample_init() - */ -attribute_deprecated -void audio_resample_close(ReSampleContext *s); - - -/** - * Initialize an audio resampler. - * Note, if either rate is not an integer then simply scale both rates up so they are. - * @param filter_length length of each FIR filter in the filterbank relative to the cutoff freq - * @param log2_phase_count log2 of the number of entries in the polyphase filterbank - * @param linear If 1 then the used FIR filter will be linearly interpolated - between the 2 closest, if 0 the closest will be used - * @param cutoff cutoff frequency, 1.0 corresponds to half the output sampling rate - */ -attribute_deprecated -struct AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_length, int log2_phase_count, int linear, double cutoff); - -/** - * Resample an array of samples using a previously configured context. - * @param src an array of unconsumed samples - * @param consumed the number of samples of src which have been consumed are returned here - * @param src_size the number of unconsumed samples available - * @param dst_size the amount of space in samples available in dst - * @param update_ctx If this is 0 then the context will not be modified, that way several channels can be resampled with the same context. - * @return the number of samples written in dst or -1 if an error occurred - */ -attribute_deprecated -int av_resample(struct AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx); - - -/** - * Compensate samplerate/timestamp drift. The compensation is done by changing - * the resampler parameters, so no audible clicks or similar distortions occur - * @param compensation_distance distance in output samples over which the compensation should be performed - * @param sample_delta number of output samples which should be output less - * - * example: av_resample_compensate(c, 10, 500) - * here instead of 510 samples only 500 samples would be output - * - * note, due to rounding the actual compensation might be slightly different, - * especially if the compensation_distance is large and the in_rate used during init is small - */ -attribute_deprecated -void av_resample_compensate(struct AVResampleContext *c, int sample_delta, int compensation_distance); -attribute_deprecated -void av_resample_close(struct AVResampleContext *c); - -/** - * @} - */ -#endif - #if FF_API_AVPICTURE /** * @addtogroup lavc_picture diff --git a/libavcodec/resample.c b/libavcodec/resample.c deleted file mode 100644 index 4c5eb9f10e672..0000000000000 --- a/libavcodec/resample.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * samplerate conversion for both audio and video - * Copyright (c) 2000 Fabrice Bellard - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * samplerate conversion for both audio and video - */ - -#include - -#include "avcodec.h" -#include "audioconvert.h" -#include "libavutil/opt.h" -#include "libavutil/mem.h" -#include "libavutil/samplefmt.h" - -#if FF_API_AVCODEC_RESAMPLE -FF_DISABLE_DEPRECATION_WARNINGS - -#define MAX_CHANNELS 8 - -struct AVResampleContext; - -static const char *context_to_name(void *ptr) -{ - return "audioresample"; -} - -static const AVOption options[] = {{NULL}}; -static const AVClass audioresample_context_class = { - "ReSampleContext", context_to_name, options, LIBAVUTIL_VERSION_INT -}; - -struct ReSampleContext { - struct AVResampleContext *resample_context; - short *temp[MAX_CHANNELS]; - int temp_len; - float ratio; - /* channel convert */ - int input_channels, output_channels, filter_channels; - AVAudioConvert *convert_ctx[2]; - enum AVSampleFormat sample_fmt[2]; ///< input and output sample format - unsigned sample_size[2]; ///< size of one sample in sample_fmt - short *buffer[2]; ///< buffers used for conversion to S16 - unsigned buffer_size[2]; ///< sizes of allocated buffers -}; - -/* n1: number of samples */ -static void stereo_to_mono(short *output, short *input, int n1) -{ - short *p, *q; - int n = n1; - - p = input; - q = output; - while (n >= 4) { - q[0] = (p[0] + p[1]) >> 1; - q[1] = (p[2] + p[3]) >> 1; - q[2] = (p[4] + p[5]) >> 1; - q[3] = (p[6] + p[7]) >> 1; - q += 4; - p += 8; - n -= 4; - } - while (n > 0) { - q[0] = (p[0] + p[1]) >> 1; - q++; - p += 2; - n--; - } -} - -/* n1: number of samples */ -static void mono_to_stereo(short *output, short *input, int n1) -{ - short *p, *q; - int n = n1; - int v; - - p = input; - q = output; - while (n >= 4) { - v = p[0]; q[0] = v; q[1] = v; - v = p[1]; q[2] = v; q[3] = v; - v = p[2]; q[4] = v; q[5] = v; - v = p[3]; q[6] = v; q[7] = v; - q += 8; - p += 4; - n -= 4; - } - while (n > 0) { - v = p[0]; q[0] = v; q[1] = v; - q += 2; - p += 1; - n--; - } -} - -/* -5.1 to stereo input: [fl, fr, c, lfe, rl, rr] -- Left = front_left + rear_gain * rear_left + center_gain * center -- Right = front_right + rear_gain * rear_right + center_gain * center -Where rear_gain is usually around 0.5-1.0 and - center_gain is almost always 0.7 (-3 dB) -*/ -static void surround_to_stereo(short **output, short *input, int channels, int samples) -{ - int i; - short l, r; - - for (i = 0; i < samples; i++) { - int fl,fr,c,rl,rr; - fl = input[0]; - fr = input[1]; - c = input[2]; - // lfe = input[3]; - rl = input[4]; - rr = input[5]; - - l = av_clip_int16(fl + (0.5 * rl) + (0.7 * c)); - r = av_clip_int16(fr + (0.5 * rr) + (0.7 * c)); - - /* output l & r. */ - *output[0]++ = l; - *output[1]++ = r; - - /* increment input. */ - input += channels; - } -} - -static void deinterleave(short **output, short *input, int channels, int samples) -{ - int i, j; - - for (i = 0; i < samples; i++) { - for (j = 0; j < channels; j++) { - *output[j]++ = *input++; - } - } -} - -static void interleave(short *output, short **input, int channels, int samples) -{ - int i, j; - - for (i = 0; i < samples; i++) { - for (j = 0; j < channels; j++) { - *output++ = *input[j]++; - } - } -} - -static void ac3_5p1_mux(short *output, short *input1, short *input2, int n) -{ - int i; - short l, r; - - for (i = 0; i < n; i++) { - l = *input1++; - r = *input2++; - *output++ = l; /* left */ - *output++ = (l / 2) + (r / 2); /* center */ - *output++ = r; /* right */ - *output++ = 0; /* left surround */ - *output++ = 0; /* right surroud */ - *output++ = 0; /* low freq */ - } -} - -#define SUPPORT_RESAMPLE(ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8) \ - ch8<<7 | ch7<<6 | ch6<<5 | ch5<<4 | ch4<<3 | ch3<<2 | ch2<<1 | ch1<<0 - -static const uint8_t supported_resampling[MAX_CHANNELS] = { - // output ch: 1 2 3 4 5 6 7 8 - SUPPORT_RESAMPLE(1, 1, 0, 0, 0, 0, 0, 0), // 1 input channel - SUPPORT_RESAMPLE(1, 1, 0, 0, 0, 1, 0, 0), // 2 input channels - SUPPORT_RESAMPLE(0, 0, 1, 0, 0, 0, 0, 0), // 3 input channels - SUPPORT_RESAMPLE(0, 0, 0, 1, 0, 0, 0, 0), // 4 input channels - SUPPORT_RESAMPLE(0, 0, 0, 0, 1, 0, 0, 0), // 5 input channels - SUPPORT_RESAMPLE(0, 1, 0, 0, 0, 1, 0, 0), // 6 input channels - SUPPORT_RESAMPLE(0, 0, 0, 0, 0, 0, 1, 0), // 7 input channels - SUPPORT_RESAMPLE(0, 0, 0, 0, 0, 0, 0, 1), // 8 input channels -}; - -ReSampleContext *av_audio_resample_init(int output_channels, int input_channels, - int output_rate, int input_rate, - enum AVSampleFormat sample_fmt_out, - enum AVSampleFormat sample_fmt_in, - int filter_length, int log2_phase_count, - int linear, double cutoff) -{ - ReSampleContext *s; - - if (input_channels > MAX_CHANNELS) { - av_log(NULL, AV_LOG_ERROR, - "Resampling with input channels greater than %d is unsupported.\n", - MAX_CHANNELS); - return NULL; - } - if (!(supported_resampling[input_channels-1] & (1<<(output_channels-1)))) { - int i; - av_log(NULL, AV_LOG_ERROR, "Unsupported audio resampling. Allowed " - "output channels for %d input channel%s", input_channels, - input_channels > 1 ? "s:" : ":"); - for (i = 0; i < MAX_CHANNELS; i++) - if (supported_resampling[input_channels-1] & (1<ratio = (float)output_rate / (float)input_rate; - - s->input_channels = input_channels; - s->output_channels = output_channels; - - s->filter_channels = s->input_channels; - if (s->output_channels < s->filter_channels) - s->filter_channels = s->output_channels; - - s->sample_fmt[0] = sample_fmt_in; - s->sample_fmt[1] = sample_fmt_out; - s->sample_size[0] = av_get_bytes_per_sample(s->sample_fmt[0]); - s->sample_size[1] = av_get_bytes_per_sample(s->sample_fmt[1]); - - if (s->sample_fmt[0] != AV_SAMPLE_FMT_S16) { - if (!(s->convert_ctx[0] = av_audio_convert_alloc(AV_SAMPLE_FMT_S16, 1, - s->sample_fmt[0], 1, NULL, 0))) { - av_log(s, AV_LOG_ERROR, - "Cannot convert %s sample format to s16 sample format\n", - av_get_sample_fmt_name(s->sample_fmt[0])); - av_free(s); - return NULL; - } - } - - if (s->sample_fmt[1] != AV_SAMPLE_FMT_S16) { - if (!(s->convert_ctx[1] = av_audio_convert_alloc(s->sample_fmt[1], 1, - AV_SAMPLE_FMT_S16, 1, NULL, 0))) { - av_log(s, AV_LOG_ERROR, - "Cannot convert s16 sample format to %s sample format\n", - av_get_sample_fmt_name(s->sample_fmt[1])); - av_audio_convert_free(s->convert_ctx[0]); - av_free(s); - return NULL; - } - } - - s->resample_context = av_resample_init(output_rate, input_rate, - filter_length, log2_phase_count, - linear, cutoff); - - *(const AVClass**)s->resample_context = &audioresample_context_class; - - return s; -} - -/* resample audio. 'nb_samples' is the number of input samples */ -/* XXX: optimize it ! */ -int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples) -{ - int i, nb_samples1; - short *bufin[MAX_CHANNELS]; - short *bufout[MAX_CHANNELS]; - short *buftmp2[MAX_CHANNELS], *buftmp3[MAX_CHANNELS]; - short *output_bak = NULL; - int lenout; - - if (s->sample_fmt[0] != AV_SAMPLE_FMT_S16) { - int istride[1] = { s->sample_size[0] }; - int ostride[1] = { 2 }; - const void *ibuf[1] = { input }; - void *obuf[1]; - unsigned input_size = nb_samples * s->input_channels * 2; - - if (!s->buffer_size[0] || s->buffer_size[0] < input_size) { - av_free(s->buffer[0]); - s->buffer_size[0] = input_size; - s->buffer[0] = av_malloc(s->buffer_size[0]); - if (!s->buffer[0]) { - av_log(s->resample_context, AV_LOG_ERROR, "Could not allocate buffer\n"); - return 0; - } - } - - obuf[0] = s->buffer[0]; - - if (av_audio_convert(s->convert_ctx[0], obuf, ostride, - ibuf, istride, nb_samples * s->input_channels) < 0) { - av_log(s->resample_context, AV_LOG_ERROR, - "Audio sample format conversion failed\n"); - return 0; - } - - input = s->buffer[0]; - } - - lenout= 2*s->output_channels*nb_samples * s->ratio + 16; - - if (s->sample_fmt[1] != AV_SAMPLE_FMT_S16) { - int out_size = lenout * av_get_bytes_per_sample(s->sample_fmt[1]) * - s->output_channels; - output_bak = output; - - if (!s->buffer_size[1] || s->buffer_size[1] < out_size) { - av_free(s->buffer[1]); - s->buffer_size[1] = out_size; - s->buffer[1] = av_malloc(s->buffer_size[1]); - if (!s->buffer[1]) { - av_log(s->resample_context, AV_LOG_ERROR, "Could not allocate buffer\n"); - return 0; - } - } - - output = s->buffer[1]; - } - - /* XXX: move those malloc to resample init code */ - for (i = 0; i < s->filter_channels; i++) { - bufin[i] = av_malloc_array((nb_samples + s->temp_len), sizeof(short)); - bufout[i] = av_malloc_array(lenout, sizeof(short)); - - if (!bufin[i] || !bufout[i]) { - av_log(s->resample_context, AV_LOG_ERROR, "Could not allocate buffer\n"); - nb_samples1 = 0; - goto fail; - } - - memcpy(bufin[i], s->temp[i], s->temp_len * sizeof(short)); - buftmp2[i] = bufin[i] + s->temp_len; - } - - if (s->input_channels == 2 && s->output_channels == 1) { - buftmp3[0] = output; - stereo_to_mono(buftmp2[0], input, nb_samples); - } else if (s->output_channels >= 2 && s->input_channels == 1) { - buftmp3[0] = bufout[0]; - memcpy(buftmp2[0], input, nb_samples * sizeof(short)); - } else if (s->input_channels == 6 && s->output_channels ==2) { - buftmp3[0] = bufout[0]; - buftmp3[1] = bufout[1]; - surround_to_stereo(buftmp2, input, s->input_channels, nb_samples); - } else if (s->output_channels >= s->input_channels && s->input_channels >= 2) { - for (i = 0; i < s->input_channels; i++) { - buftmp3[i] = bufout[i]; - } - deinterleave(buftmp2, input, s->input_channels, nb_samples); - } else { - buftmp3[0] = output; - memcpy(buftmp2[0], input, nb_samples * sizeof(short)); - } - - nb_samples += s->temp_len; - - /* resample each channel */ - nb_samples1 = 0; /* avoid warning */ - for (i = 0; i < s->filter_channels; i++) { - int consumed; - int is_last = i + 1 == s->filter_channels; - - nb_samples1 = av_resample(s->resample_context, buftmp3[i], bufin[i], - &consumed, nb_samples, lenout, is_last); - s->temp_len = nb_samples - consumed; - s->temp[i] = av_realloc_array(s->temp[i], s->temp_len, sizeof(short)); - memcpy(s->temp[i], bufin[i] + consumed, s->temp_len * sizeof(short)); - } - - if (s->output_channels == 2 && s->input_channels == 1) { - mono_to_stereo(output, buftmp3[0], nb_samples1); - } else if (s->output_channels == 6 && s->input_channels == 2) { - ac3_5p1_mux(output, buftmp3[0], buftmp3[1], nb_samples1); - } else if ((s->output_channels == s->input_channels && s->input_channels >= 2) || - (s->output_channels == 2 && s->input_channels == 6)) { - interleave(output, buftmp3, s->output_channels, nb_samples1); - } - - if (s->sample_fmt[1] != AV_SAMPLE_FMT_S16) { - int istride[1] = { 2 }; - int ostride[1] = { s->sample_size[1] }; - const void *ibuf[1] = { output }; - void *obuf[1] = { output_bak }; - - if (av_audio_convert(s->convert_ctx[1], obuf, ostride, - ibuf, istride, nb_samples1 * s->output_channels) < 0) { - av_log(s->resample_context, AV_LOG_ERROR, - "Audio sample format conversion failed\n"); - return 0; - } - } - -fail: - for (i = 0; i < s->filter_channels; i++) { - av_free(bufin[i]); - av_free(bufout[i]); - } - - return nb_samples1; -} - -void audio_resample_close(ReSampleContext *s) -{ - int i; - av_resample_close(s->resample_context); - for (i = 0; i < s->filter_channels; i++) - av_freep(&s->temp[i]); - av_freep(&s->buffer[0]); - av_freep(&s->buffer[1]); - av_audio_convert_free(s->convert_ctx[0]); - av_audio_convert_free(s->convert_ctx[1]); - av_free(s); -} - -FF_ENABLE_DEPRECATION_WARNINGS -#endif diff --git a/libavcodec/resample2.c b/libavcodec/resample2.c deleted file mode 100644 index 56ae9f72294ba..0000000000000 --- a/libavcodec/resample2.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * audio resampling - * Copyright (c) 2004 Michael Niedermayer - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * audio resampling - * @author Michael Niedermayer - */ - -#include "libavutil/avassert.h" -#include "avcodec.h" -#include "libavutil/common.h" - -#if FF_API_AVCODEC_RESAMPLE - -#ifndef CONFIG_RESAMPLE_HP -#define FILTER_SHIFT 15 - -typedef int16_t FELEM; -typedef int32_t FELEM2; -typedef int64_t FELEML; -#define FELEM_MAX INT16_MAX -#define FELEM_MIN INT16_MIN -#define WINDOW_TYPE 9 -#elif !defined(CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE) -#define FILTER_SHIFT 30 - -#define FELEM int32_t -#define FELEM2 int64_t -#define FELEML int64_t -#define FELEM_MAX INT32_MAX -#define FELEM_MIN INT32_MIN -#define WINDOW_TYPE 12 -#else -#define FILTER_SHIFT 0 - -typedef double FELEM; -typedef double FELEM2; -typedef double FELEML; -#define WINDOW_TYPE 24 -#endif - - -typedef struct AVResampleContext{ - const AVClass *av_class; - FELEM *filter_bank; - int filter_length; - int ideal_dst_incr; - int dst_incr; - int index; - int frac; - int src_incr; - int compensation_distance; - int phase_shift; - int phase_mask; - int linear; -}AVResampleContext; - -/** - * 0th order modified bessel function of the first kind. - */ -static double bessel(double x){ - double v=1; - double lastv=0; - double t=1; - int i; - - x= x*x/4; - for(i=1; v != lastv; i++){ - lastv=v; - t *= x/(i*i); - v += t; - } - return v; -} - -/** - * Build a polyphase filterbank. - * @param factor resampling factor - * @param scale wanted sum of coefficients for each filter - * @param type 0->cubic, 1->blackman nuttall windowed sinc, 2..16->kaiser windowed sinc beta=2..16 - * @return 0 on success, negative on error - */ -static int build_filter(FELEM *filter, double factor, int tap_count, int phase_count, int scale, int type){ - int ph, i; - double x, y, w; - double *tab = av_malloc_array(tap_count, sizeof(*tab)); - const int center= (tap_count-1)/2; - - if (!tab) - return AVERROR(ENOMEM); - - /* if upsampling, only need to interpolate, no filter */ - if (factor > 1.0) - factor = 1.0; - - for(ph=0;phphase_shift= phase_shift; - c->phase_mask= phase_count-1; - c->linear= linear; - - c->filter_length= FFMAX((int)ceil(filter_size/factor), 1); - c->filter_bank= av_mallocz_array(c->filter_length, (phase_count+1)*sizeof(FELEM)); - if (!c->filter_bank) - goto error; - if (build_filter(c->filter_bank, factor, c->filter_length, phase_count, 1<filter_bank[c->filter_length*phase_count+1], c->filter_bank, (c->filter_length-1)*sizeof(FELEM)); - c->filter_bank[c->filter_length*phase_count]= c->filter_bank[c->filter_length - 1]; - - if(!av_reduce(&c->src_incr, &c->dst_incr, out_rate, in_rate * (int64_t)phase_count, INT32_MAX/2)) - goto error; - c->ideal_dst_incr= c->dst_incr; - - c->index= -phase_count*((c->filter_length-1)/2); - - return c; -error: - av_free(c->filter_bank); - av_free(c); - return NULL; -} - -void av_resample_close(AVResampleContext *c){ - av_freep(&c->filter_bank); - av_freep(&c); -} - -void av_resample_compensate(AVResampleContext *c, int sample_delta, int compensation_distance){ -// sample_delta += (c->ideal_dst_incr - c->dst_incr)*(int64_t)c->compensation_distance / c->ideal_dst_incr; - c->compensation_distance= compensation_distance; - c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance; -} - -int av_resample(AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx){ - int dst_index, i; - int index= c->index; - int frac= c->frac; - int dst_incr_frac= c->dst_incr % c->src_incr; - int dst_incr= c->dst_incr / c->src_incr; - int compensation_distance= c->compensation_distance; - - if(compensation_distance == 0 && c->filter_length == 1 && c->phase_shift==0){ - int64_t index2= ((int64_t)index)<<32; - int64_t incr= (1LL<<32) * c->dst_incr / c->src_incr; - dst_size= FFMIN(dst_size, (src_size-1-index) * (int64_t)c->src_incr / c->dst_incr); - - for(dst_index=0; dst_index < dst_size; dst_index++){ - dst[dst_index] = src[index2>>32]; - index2 += incr; - } - index += dst_index * dst_incr; - index += (frac + dst_index * (int64_t)dst_incr_frac) / c->src_incr; - frac = (frac + dst_index * (int64_t)dst_incr_frac) % c->src_incr; - }else{ - for(dst_index=0; dst_index < dst_size; dst_index++){ - FELEM *filter= c->filter_bank + c->filter_length*(index & c->phase_mask); - int sample_index= index >> c->phase_shift; - FELEM2 val=0; - - if(sample_index < 0){ - for(i=0; ifilter_length; i++) - val += src[FFABS(sample_index + i) % src_size] * filter[i]; - }else if(sample_index + c->filter_length > src_size){ - break; - }else if(c->linear){ - FELEM2 v2=0; - for(i=0; ifilter_length; i++){ - val += src[sample_index + i] * (FELEM2)filter[i]; - v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_length]; - } - val+=(v2-val)*(FELEML)frac / c->src_incr; - }else{ - for(i=0; ifilter_length; i++){ - val += src[sample_index + i] * (FELEM2)filter[i]; - } - } - -#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE - dst[dst_index] = av_clip_int16(lrintf(val)); -#else - val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT; - dst[dst_index] = (unsigned)(val + 32768) > 65535 ? (val>>31) ^ 32767 : val; -#endif - - frac += dst_incr_frac; - index += dst_incr; - if(frac >= c->src_incr){ - frac -= c->src_incr; - index++; - } - - if(dst_index + 1 == compensation_distance){ - compensation_distance= 0; - dst_incr_frac= c->ideal_dst_incr % c->src_incr; - dst_incr= c->ideal_dst_incr / c->src_incr; - } - } - } - *consumed= FFMAX(index, 0) >> c->phase_shift; - if(index>=0) index &= c->phase_mask; - - if(compensation_distance){ - compensation_distance -= dst_index; - av_assert2(compensation_distance > 0); - } - if(update_ctx){ - c->frac= frac; - c->index= index; - c->dst_incr= dst_incr_frac + c->src_incr*dst_incr; - c->compensation_distance= compensation_distance; - } - - return dst_index; -} - -#endif diff --git a/libavcodec/version.h b/libavcodec/version.h index cd2ca5f1a2d52..acbc61d757108 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -57,9 +57,6 @@ #ifndef FF_API_AUDIO_CONVERT #define FF_API_AUDIO_CONVERT (LIBAVCODEC_VERSION_MAJOR < 58) #endif -#ifndef FF_API_AVCODEC_RESAMPLE -#define FF_API_AVCODEC_RESAMPLE FF_API_AUDIO_CONVERT -#endif #ifndef FF_API_LOWRES #define FF_API_LOWRES (LIBAVCODEC_VERSION_MAJOR < 59) #endif From 43befa68263be9db116997226e5147d88aba008d Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 21 Oct 2017 23:16:13 -0300 Subject: [PATCH 0558/2557] avcodec: Drop deprecated audio convert API Deprecated in 10/2013. --- libavcodec/Makefile | 1 - libavcodec/audioconvert.c | 120 -------------------------------------- libavcodec/audioconvert.h | 86 --------------------------- libavcodec/version.h | 3 - 4 files changed, 210 deletions(-) delete mode 100644 libavcodec/audioconvert.c delete mode 100644 libavcodec/audioconvert.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 651348972ebde..4424e749ce546 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -20,7 +20,6 @@ HEADERS = avcodec.h \ xvmc.h \ OBJS = allcodecs.o \ - audioconvert.o \ avdct.o \ avpacket.o \ avpicture.o \ diff --git a/libavcodec/audioconvert.c b/libavcodec/audioconvert.c deleted file mode 100644 index 5e46fae2df5f3..0000000000000 --- a/libavcodec/audioconvert.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * audio conversion - * Copyright (c) 2006 Michael Niedermayer - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * audio conversion - * @author Michael Niedermayer - */ - -#include "libavutil/avstring.h" -#include "libavutil/common.h" -#include "libavutil/libm.h" -#include "libavutil/samplefmt.h" -#include "avcodec.h" -#include "audioconvert.h" - -#if FF_API_AUDIO_CONVERT - -struct AVAudioConvert { - int in_channels, out_channels; - int fmt_pair; -}; - -AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels, - enum AVSampleFormat in_fmt, int in_channels, - const float *matrix, int flags) -{ - AVAudioConvert *ctx; - if (in_channels!=out_channels) - return NULL; /* FIXME: not supported */ - ctx = av_malloc(sizeof(AVAudioConvert)); - if (!ctx) - return NULL; - ctx->in_channels = in_channels; - ctx->out_channels = out_channels; - ctx->fmt_pair = out_fmt + AV_SAMPLE_FMT_NB*in_fmt; - return ctx; -} - -void av_audio_convert_free(AVAudioConvert *ctx) -{ - av_free(ctx); -} - -int av_audio_convert(AVAudioConvert *ctx, - void * const out[6], const int out_stride[6], - const void * const in[6], const int in_stride[6], int len) -{ - int ch; - - //FIXME optimize common cases - - for(ch=0; chout_channels; ch++){ - const int is= in_stride[ch]; - const int os= out_stride[ch]; - const uint8_t *pi= in[ch]; - uint8_t *po= out[ch]; - uint8_t *end= po + os*len; - if(!out[ch]) - continue; - -#define CONV(ofmt, otype, ifmt, expr)\ -if(ctx->fmt_pair == ofmt + AV_SAMPLE_FMT_NB*ifmt){\ - do{\ - *(otype*)po = expr; pi += is; po += os;\ - }while(po < end);\ -} - -//FIXME put things below under ifdefs so we do not waste space for cases no codec will need -//FIXME rounding ? - - CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_U8 , *(const uint8_t*)pi) - else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<8) - else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<24) - else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7))) - else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7))) - else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_S16, (*(const int16_t*)pi>>8) + 0x80) - else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, *(const int16_t*)pi) - else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, *(const int16_t*)pi<<16) - else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0 / (1<<15))) - else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0 / (1<<15))) - else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_S32, (*(const int32_t*)pi>>24) + 0x80) - else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32, *(const int32_t*)pi>>16) - else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, *(const int32_t*)pi) - else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0 / (1U<<31))) - else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0 / (1U<<31))) - else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8( lrintf(*(const float*)pi * (1<<7)) + 0x80)) - else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16( lrintf(*(const float*)pi * (1<<15)))) - else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float*)pi * (1U<<31)))) - else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_FLT, *(const float*)pi) - else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_FLT, *(const float*)pi) - else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8( lrint(*(const double*)pi * (1<<7)) + 0x80)) - else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16( lrint(*(const double*)pi * (1<<15)))) - else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double*)pi * (1U<<31)))) - else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_DBL, *(const double*)pi) - else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_DBL, *(const double*)pi) - else return -1; - } - return 0; -} - -#endif /* FF_API_AUDIO_CONVERT */ diff --git a/libavcodec/audioconvert.h b/libavcodec/audioconvert.h deleted file mode 100644 index 996c3f37adc08..0000000000000 --- a/libavcodec/audioconvert.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * audio conversion - * Copyright (c) 2006 Michael Niedermayer - * Copyright (c) 2008 Peter Ross - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVCODEC_AUDIOCONVERT_H -#define AVCODEC_AUDIOCONVERT_H - -#include "version.h" - -/** - * @file - * Audio format conversion routines - * This interface is deprecated and will be dropped in a future - * version. You should use the libswresample library instead. - */ - -#if FF_API_AUDIO_CONVERT - -#include "libavutil/cpu.h" -#include "avcodec.h" -#include "libavutil/channel_layout.h" - -struct AVAudioConvert; -typedef struct AVAudioConvert AVAudioConvert; - -/** - * Create an audio sample format converter context - * @param out_fmt Output sample format - * @param out_channels Number of output channels - * @param in_fmt Input sample format - * @param in_channels Number of input channels - * @param[in] matrix Channel mixing matrix (of dimension in_channel*out_channels). Set to NULL to ignore. - * @param flags See AV_CPU_FLAG_xx - * @return NULL on error - * @deprecated See libswresample - */ - -attribute_deprecated -AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels, - enum AVSampleFormat in_fmt, int in_channels, - const float *matrix, int flags); - -/** - * Free audio sample format converter context - * @deprecated See libswresample - */ - -attribute_deprecated -void av_audio_convert_free(AVAudioConvert *ctx); - -/** - * Convert between audio sample formats - * @param[in] out array of output buffers for each channel. set to NULL to ignore processing of the given channel. - * @param[in] out_stride distance between consecutive output samples (measured in bytes) - * @param[in] in array of input buffers for each channel - * @param[in] in_stride distance between consecutive input samples (measured in bytes) - * @param len length of audio frame size (measured in samples) - * @deprecated See libswresample - */ - -attribute_deprecated -int av_audio_convert(AVAudioConvert *ctx, - void * const out[6], const int out_stride[6], - const void * const in[6], const int in_stride[6], int len); - -#endif /* FF_API_AUDIO_CONVERT */ - -#endif /* AVCODEC_AUDIOCONVERT_H */ diff --git a/libavcodec/version.h b/libavcodec/version.h index acbc61d757108..1431d94d76d4e 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -54,9 +54,6 @@ #ifndef FF_API_VIMA_DECODER #define FF_API_VIMA_DECODER (LIBAVCODEC_VERSION_MAJOR < 58) #endif -#ifndef FF_API_AUDIO_CONVERT -#define FF_API_AUDIO_CONVERT (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_LOWRES #define FF_API_LOWRES (LIBAVCODEC_VERSION_MAJOR < 59) #endif From 5ad1a989b67dedf801abc78ad7dc86ff573c1406 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 21 Oct 2017 23:55:23 -0300 Subject: [PATCH 0559/2557] avcodec: Drop deprecated VIMA codecid Deprecated in 02/2015. Signed-off-by: James Almer --- libavcodec/avcodec.h | 3 --- libavcodec/version.h | 3 --- 2 files changed, 6 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 076332b6f1567..dfbb61ca88d30 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -520,9 +520,6 @@ enum AVCodecID { AV_CODEC_ID_ADPCM_G722, AV_CODEC_ID_ADPCM_IMA_APC, AV_CODEC_ID_ADPCM_VIMA, -#if FF_API_VIMA_DECODER - AV_CODEC_ID_VIMA = AV_CODEC_ID_ADPCM_VIMA, -#endif AV_CODEC_ID_ADPCM_AFC = 0x11800, AV_CODEC_ID_ADPCM_IMA_OKI, diff --git a/libavcodec/version.h b/libavcodec/version.h index 55b7cfff118b8..9040dae8fb04f 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -51,9 +51,6 @@ * at once through the bump. This improves the git bisect-ability of the change. */ -#ifndef FF_API_VIMA_DECODER -#define FF_API_VIMA_DECODER (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_LOWRES #define FF_API_LOWRES (LIBAVCODEC_VERSION_MAJOR < 59) #endif From 417d473bde220a1f267bc694835c129a5adc4309 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 22 Oct 2017 00:30:12 -0300 Subject: [PATCH 0560/2557] avcodec: remove ABI portion of the side data merging API The actual API is left in place until the deprecation period ends. Signed-off-by: James Almer --- libavcodec/avpacket.c | 28 ------------------ libavcodec/decode.c | 68 ++++--------------------------------------- libavcodec/internal.h | 4 --- libavcodec/version.h | 3 -- 4 files changed, 6 insertions(+), 97 deletions(-) diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index d1f4ea9eb3feb..90b821592835e 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -479,34 +479,6 @@ int av_packet_split_side_data(AVPacket *pkt){ } #endif -#if FF_API_MERGE_SD -int ff_packet_split_and_drop_side_data(AVPacket *pkt){ - if (!pkt->side_data_elems && pkt->size >12 && AV_RB64(pkt->data + pkt->size - 8) == FF_MERGE_MARKER){ - int i; - unsigned int size; - uint8_t *p; - - p = pkt->data + pkt->size - 8 - 5; - for (i=1; ; i++){ - size = AV_RB32(p); - if (size>INT_MAX - 5 || p - pkt->data < size) - return 0; - if (p[4]&128) - break; - if (p - pkt->data < size + 5) - return 0; - p-= size+5; - if (i > AV_PKT_DATA_NB) - return 0; - } - pkt->size = p - pkt->data - size; - av_assert0(pkt->size >= 0); - return 1; - } - return 0; -} -#endif - uint8_t *av_packet_pack_dictionary(AVDictionary *dict, int *size) { AVDictionaryEntry *t = NULL; diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 7f08f0ec1838e..15fc82ad39a50 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -369,8 +369,7 @@ static int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame) DecodeSimpleContext *ds = &avci->ds; AVPacket *pkt = ds->in_pkt; // copy to ensure we do not change pkt - AVPacket tmp; - int got_frame, actual_got_frame, did_split; + int got_frame, actual_got_frame; int ret; if (!pkt->data && !avci->draining) { @@ -390,31 +389,12 @@ static int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame) avctx->active_thread_type & FF_THREAD_FRAME)) return AVERROR_EOF; - tmp = *pkt; -#if FF_API_MERGE_SD -FF_DISABLE_DEPRECATION_WARNINGS - did_split = avci->compat_decode_partial_size ? - ff_packet_split_and_drop_side_data(&tmp) : - av_packet_split_side_data(&tmp); - - if (did_split) { - ret = extract_packet_props(avctx->internal, &tmp); - if (ret < 0) - return ret; - - ret = apply_param_change(avctx, &tmp); - if (ret < 0) - return ret; - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif - got_frame = 0; if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) { - ret = ff_thread_decode_frame(avctx, frame, &got_frame, &tmp); + ret = ff_thread_decode_frame(avctx, frame, &got_frame, pkt); } else { - ret = avctx->codec->decode(avctx, frame, &got_frame, &tmp); + ret = avctx->codec->decode(avctx, frame, &got_frame, pkt); if (!(avctx->codec->caps_internal & FF_CODEC_CAP_SETS_PKT_DTS)) frame->pkt_dts = pkt->dts; @@ -544,13 +524,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } } } -#if FF_API_MERGE_SD - if (did_split) { - av_packet_free_side_data(&tmp); - if(ret == tmp.size) - ret = pkt->size; - } -#endif if (avctx->codec->type == AVMEDIA_TYPE_AUDIO && !avci->showed_multi_packet_warning && @@ -999,7 +972,6 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, AVPacket *avpkt) { int i, ret = 0; - AVCodecInternal *avci = avctx->internal; if (!avpkt->data && avpkt->size) { av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n"); @@ -1016,29 +988,9 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, get_subtitle_defaults(sub); if ((avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || avpkt->size) { - AVPacket pkt_recoded; - AVPacket tmp = *avpkt; -#if FF_API_MERGE_SD -FF_DISABLE_DEPRECATION_WARNINGS - int did_split = avci->compat_decode_partial_size ? - ff_packet_split_and_drop_side_data(&tmp) : - av_packet_split_side_data(&tmp); - //apply_param_change(avctx, &tmp); - - if (did_split) { - /* FFMIN() prevents overflow in case the packet wasn't allocated with - * proper padding. - * If the side data is smaller than the buffer padding size, the - * remaining bytes should have already been filled with zeros by the - * original packet allocation anyway. */ - memset(tmp.data + tmp.size, 0, - FFMIN(avpkt->size - tmp.size, AV_INPUT_BUFFER_PADDING_SIZE)); - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif + AVPacket pkt_recoded = *avpkt; - pkt_recoded = tmp; - ret = recode_subtitle(avctx, &pkt_recoded, &tmp); + ret = recode_subtitle(avctx, &pkt_recoded, avpkt); if (ret < 0) { *got_sub_ptr = 0; } else { @@ -1087,7 +1039,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } } - if (tmp.data != pkt_recoded.data) { // did we recode? + if (avpkt->data != pkt_recoded.data) { // did we recode? /* prevent from destroying side data from original packet */ pkt_recoded.side_data = NULL; pkt_recoded.side_data_elems = 0; @@ -1096,14 +1048,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } } -#if FF_API_MERGE_SD - if (did_split) { - av_packet_free_side_data(&tmp); - if(ret == tmp.size) - ret = avpkt->size; - } -#endif - if (*got_sub_ptr) avctx->frame_number++; } diff --git a/libavcodec/internal.h b/libavcodec/internal.h index faa923c11f275..f1d520237a2a0 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -373,10 +373,6 @@ int ff_set_sar(AVCodecContext *avctx, AVRational sar); int ff_side_data_update_matrix_encoding(AVFrame *frame, enum AVMatrixEncoding matrix_encoding); -#if FF_API_MERGE_SD -int ff_packet_split_and_drop_side_data(AVPacket *pkt); -#endif - /** * Select the (possibly hardware accelerated) pixel format. * This is a wrapper around AVCodecContext.get_format() and should be used diff --git a/libavcodec/version.h b/libavcodec/version.h index fd334e83fd937..b09beaa3b9c7c 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -130,9 +130,6 @@ #ifndef FF_API_VAAPI_CONTEXT #define FF_API_VAAPI_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 58) #endif -#ifndef FF_API_MERGE_SD -#define FF_API_MERGE_SD (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_AVCTX_TIMEBASE #define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 59) #endif From 657ce888e852489f850e1e1fc093a6523e28dbed Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 22 Oct 2017 00:35:23 -0300 Subject: [PATCH 0561/2557] postproc: Drop deprecated qp typedef Deprecated in 08/2015. Signed-off-by: James Almer --- libpostproc/postprocess.h | 4 ---- libpostproc/version.h | 4 ---- 2 files changed, 8 deletions(-) diff --git a/libpostproc/postprocess.h b/libpostproc/postprocess.h index d180686e7392b..348ee7cc6100e 100644 --- a/libpostproc/postprocess.h +++ b/libpostproc/postprocess.h @@ -53,10 +53,6 @@ const char *postproc_license(void); #define PP_QUALITY_MAX 6 -#if FF_API_QP_TYPE -#define QP_STORE_T int8_t //deprecated -#endif - #include typedef void pp_context; diff --git a/libpostproc/version.h b/libpostproc/version.h index 3ae75ff8b067b..79eea7c248a08 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -42,8 +42,4 @@ #define LIBPOSTPROC_IDENT "postproc" AV_STRINGIFY(LIBPOSTPROC_VERSION) -#ifndef FF_API_QP_TYPE -#define FF_API_QP_TYPE (LIBPOSTPROC_VERSION_MAJOR < 55) -#endif - #endif /* POSTPROC_VERSION_H */ From 382aaa3312a51d13a5acbdfe0d87391c2a9d2f95 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 22 Oct 2017 00:44:55 -0300 Subject: [PATCH 0562/2557] avutil/crc: remove gap in AVCRCId enum values Signed-off-by: James Almer --- libavutil/crc.h | 4 ---- libavutil/version.h | 3 --- 2 files changed, 7 deletions(-) diff --git a/libavutil/crc.h b/libavutil/crc.h index 2a1b0d7624502..fe9a7c8fcbfee 100644 --- a/libavutil/crc.h +++ b/libavutil/crc.h @@ -53,11 +53,7 @@ typedef enum { AV_CRC_32_IEEE, AV_CRC_32_IEEE_LE, /*< reversed bitorder version of AV_CRC_32_IEEE */ AV_CRC_16_ANSI_LE, /*< reversed bitorder version of AV_CRC_16_ANSI */ -#if FF_API_CRC_BIG_TABLE - AV_CRC_24_IEEE = 12, -#else AV_CRC_24_IEEE, -#endif /* FF_API_CRC_BIG_TABLE */ AV_CRC_MAX, /*< Not part of public API! Do not use outside libavutil. */ }AVCRCId; diff --git a/libavutil/version.h b/libavutil/version.h index e9b8d0c37d805..aa56ad2fbdb45 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -130,9 +130,6 @@ #ifndef FF_API_ERROR_FRAME #define FF_API_ERROR_FRAME (LIBAVUTIL_VERSION_MAJOR < 57) #endif -#ifndef FF_API_CRC_BIG_TABLE -#define FF_API_CRC_BIG_TABLE (LIBAVUTIL_VERSION_MAJOR < 56) -#endif #ifndef FF_API_PKT_PTS #define FF_API_PKT_PTS (LIBAVUTIL_VERSION_MAJOR < 57) #endif From 68649bfed30a35dc3e45ea240541b2774b2f282b Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 26 Sep 2017 18:26:11 +0200 Subject: [PATCH 0563/2557] configure: Group system feature variables and system libraries together --- configure | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 70463ae2c833f..173610a19c148 100755 --- a/configure +++ b/configure @@ -1601,6 +1601,15 @@ MATH_FUNCS=" truncf " +SYSTEM_FEATURES=" + dos_paths + libc_msvcrt + MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS + section_data_rel_ro + threads + uwp +" + SYSTEM_FUNCS=" aligned_malloc clock_gettime @@ -1639,6 +1648,14 @@ SYSTEM_FUNCS=" VirtualAlloc " +SYSTEM_LIBRARIES=" + sdl + vaapi_drm + vaapi_x11 + vdpau_x11 + wincrypt +" + TOOLCHAIN_FEATURES=" as_arch_directive as_fpu_directive @@ -1686,21 +1703,12 @@ HAVE_LIST=" $HEADERS_LIST $INTRINSICS_LIST $MATH_FUNCS + $SYSTEM_FEATURES $SYSTEM_FUNCS + $SYSTEM_LIBRARIES $THREADS_LIST $TOOLCHAIN_FEATURES $TYPES_LIST - dos_paths - libc_msvcrt - MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS - sdl - section_data_rel_ro - threads - uwp - vaapi_drm - vaapi_x11 - vdpau_x11 - wincrypt " # options emitted with CONFIG_ prefix but not available on the command line From ca4df37f06f8a47651c67693b4851ed8d7e3ef74 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 22 Oct 2017 01:29:41 -0300 Subject: [PATCH 0564/2557] avformat: remove ABI portion of the side data merging API Signed-off-by: James Almer --- libavformat/mux.c | 24 +----------------------- libavformat/utils.c | 7 ------- libavformat/version.h | 3 --- 3 files changed, 1 insertion(+), 33 deletions(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index 498eb2e61fa10..77e03ee5baa92 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -674,7 +674,7 @@ FF_ENABLE_DEPRECATION_WARNINGS */ static int write_packet(AVFormatContext *s, AVPacket *pkt) { - int ret, did_split; + int ret; int64_t pts_backup, dts_backup; pts_backup = pkt->pts; @@ -739,12 +739,6 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) } } -#if FF_API_LAVF_MERGE_SD -FF_DISABLE_DEPRECATION_WARNINGS - did_split = av_packet_split_side_data(pkt); -FF_ENABLE_DEPRECATION_WARNINGS -#endif - if (!s->internal->header_written) { ret = s->internal->write_header_ret ? s->internal->write_header_ret : write_header_internal(s); if (ret < 0) @@ -767,12 +761,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } fail: -#if FF_API_LAVF_MERGE_SD -FF_DISABLE_DEPRECATION_WARNINGS - if (did_split) - av_packet_merge_side_data(pkt); -FF_ENABLE_DEPRECATION_WARNINGS -#endif if (ret < 0) { pkt->pts = pts_backup; @@ -869,16 +857,6 @@ static int do_packet_auto_bsf(AVFormatContext *s, AVPacket *pkt) { } } -#if FF_API_LAVF_MERGE_SD -FF_DISABLE_DEPRECATION_WARNINGS - if (st->internal->nb_bsfcs) { - ret = av_packet_split_side_data(pkt); - if (ret < 0) - av_log(s, AV_LOG_WARNING, "Failed to split side data before bitstream filter\n"); - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif - for (i = 0; i < st->internal->nb_bsfcs; i++) { AVBSFContext *ctx = st->internal->bsfcs[i]; // TODO: when any bitstream filter requires flushing at EOF, we'll need to diff --git a/libavformat/utils.c b/libavformat/utils.c index 1a7996c4fd854..d89dd563572c1 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1677,13 +1677,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } st->inject_global_side_data = 0; } - -#if FF_API_LAVF_MERGE_SD -FF_DISABLE_DEPRECATION_WARNINGS - if (!(s->flags & AVFMT_FLAG_KEEP_SIDE_DATA)) - av_packet_merge_side_data(pkt); -FF_ENABLE_DEPRECATION_WARNINGS -#endif } av_opt_get_dict_val(s, "metadata", AV_OPT_SEARCH_CHILDREN, &metadata); diff --git a/libavformat/version.h b/libavformat/version.h index c0cd7dd409eea..3bb1e489cfb32 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -76,9 +76,6 @@ #ifndef FF_API_HLS_WRAP #define FF_API_HLS_WRAP (LIBAVFORMAT_VERSION_MAJOR < 59) #endif -#ifndef FF_API_LAVF_MERGE_SD -#define FF_API_LAVF_MERGE_SD (LIBAVFORMAT_VERSION_MAJOR < 58) -#endif #ifndef FF_API_LAVF_KEEPSIDE_FLAG #define FF_API_LAVF_KEEPSIDE_FLAG (LIBAVFORMAT_VERSION_MAJOR < 59) #endif From b89081e01be76fc6166131fb082151041b1a56b5 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 22 Oct 2017 01:36:28 -0300 Subject: [PATCH 0565/2557] avformat: remove dead av_stream_get_side_data() cruft Signed-off-by: James Almer --- libavformat/avformat.h | 5 ----- libavformat/utils.c | 5 ----- libavformat/version.h | 3 --- 3 files changed, 13 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 870409061fdb9..ece1b179f3acb 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2082,13 +2082,8 @@ uint8_t *av_stream_new_side_data(AVStream *stream, * @param size pointer for side information size to store (optional) * @return pointer to data if present or NULL otherwise */ -#if FF_API_NOCONST_GET_SIDE_DATA -uint8_t *av_stream_get_side_data(AVStream *stream, - enum AVPacketSideDataType type, int *size); -#else uint8_t *av_stream_get_side_data(const AVStream *stream, enum AVPacketSideDataType type, int *size); -#endif AVProgram *av_new_program(AVFormatContext *s, int id); diff --git a/libavformat/utils.c b/libavformat/utils.c index d89dd563572c1..6dbc48d54d737 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -5244,13 +5244,8 @@ int ff_generate_avci_extradata(AVStream *st) return 0; } -#if FF_API_NOCONST_GET_SIDE_DATA -uint8_t *av_stream_get_side_data(AVStream *st, - enum AVPacketSideDataType type, int *size) -#else uint8_t *av_stream_get_side_data(const AVStream *st, enum AVPacketSideDataType type, int *size) -#endif { int i; diff --git a/libavformat/version.h b/libavformat/version.h index 3bb1e489cfb32..0feb788c366b3 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -67,9 +67,6 @@ #ifndef FF_API_LAVF_AVCTX #define FF_API_LAVF_AVCTX (LIBAVFORMAT_VERSION_MAJOR < 59) #endif -#ifndef FF_API_NOCONST_GET_SIDE_DATA -#define FF_API_NOCONST_GET_SIDE_DATA (LIBAVFORMAT_VERSION_MAJOR < 58) -#endif #ifndef FF_API_HTTP_USER_AGENT #define FF_API_HTTP_USER_AGENT (LIBAVFORMAT_VERSION_MAJOR < 59) #endif From 72c3d9ae4528543a17d760a173a78a05a85e579e Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 22 Oct 2017 10:12:52 -0300 Subject: [PATCH 0566/2557] avcodec/libavcodec.v: remove obsolete exports Forgotten cruft that should have been removed in 8f483108b503fa03ed5e956e25df4cb899171df5. Signed-off-by: James Almer --- libavcodec/libavcodec.v | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/libavcodec.v b/libavcodec/libavcodec.v index 304c2ef4279af..f1d5e5bc776af 100644 --- a/libavcodec/libavcodec.v +++ b/libavcodec/libavcodec.v @@ -1,9 +1,6 @@ LIBAVCODEC_MAJOR { global: av*; - #deprecated, remove after next bump - audio_resample; - audio_resample_close; local: *; }; From 06899863a82c80a91e56c32c65d4e8703fe779b0 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Wed, 1 Mar 2017 23:35:14 +0100 Subject: [PATCH 0567/2557] lavc/bitstream_filter: Make a cast explicit. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following gcc warning: libavcodec/bitstream_filter.c:133:14: warning: assignment discards ‘const’ qualifier from pointer target type --- libavcodec/bitstream_filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/bitstream_filter.c b/libavcodec/bitstream_filter.c index 8599b90d4a2a9..d2bf86d894a08 100644 --- a/libavcodec/bitstream_filter.c +++ b/libavcodec/bitstream_filter.c @@ -131,7 +131,7 @@ int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc, return ret; } - pkt.data = buf; + pkt.data = (uint8_t *)buf; pkt.size = buf_size; ret = av_bsf_send_packet(priv->ctx, &pkt); From 1eb01cca6f70fcd690fb72d55a0a7317672508fd Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 22 Oct 2017 19:47:05 -0300 Subject: [PATCH 0568/2557] avutil/hmac: remove gap in AVHMACType enum values Signed-off-by: James Almer --- libavutil/hmac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/hmac.h b/libavutil/hmac.h index 576a0a4fb9629..412e950719ba5 100644 --- a/libavutil/hmac.h +++ b/libavutil/hmac.h @@ -35,7 +35,7 @@ enum AVHMACType { AV_HMAC_SHA1, AV_HMAC_SHA224, AV_HMAC_SHA256, - AV_HMAC_SHA384 = 12, + AV_HMAC_SHA384, AV_HMAC_SHA512, }; From 90eb0a2180fd682f8b73278fabc7eb66fa6300d2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 22 Oct 2017 20:25:38 -0300 Subject: [PATCH 0569/2557] avutil/tests/hmac: remove superfluous loop The gap in enum values has been removed. Signed-off-by: James Almer --- libavutil/tests/hmac.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/libavutil/tests/hmac.c b/libavutil/tests/hmac.c index 5eeb63ce057b9..0fa50e4570891 100644 --- a/libavutil/tests/hmac.c +++ b/libavutil/tests/hmac.c @@ -70,7 +70,7 @@ int main(void) } /* SHA-2 */ - for (i = AV_HMAC_SHA224; i <= AV_HMAC_SHA256; i++) { + for (i = AV_HMAC_SHA224; i <= AV_HMAC_SHA512; i++) { hmac = av_hmac_alloc(i); if (!hmac) return 1; @@ -83,17 +83,5 @@ int main(void) av_hmac_free(hmac); } - for (i = AV_HMAC_SHA384; i <= AV_HMAC_SHA512; i++) { - hmac = av_hmac_alloc(i); - if (!hmac) - return 1; - // RFC 4231 test vectors - test(hmac, key1, sizeof(key1), data1, sizeof(data1)); - test(hmac, key2, sizeof(key2), data2, sizeof(data2)); - test(hmac, key3, 20, data3, sizeof(data3)); - test(hmac, key3, sizeof(key3), data4, sizeof(data4)); - test(hmac, key3, sizeof(key3), data6, sizeof(data6)); - av_hmac_free(hmac); - } return 0; } From 0cb8369bce32c559fc3ccd1eb0f93151e293b465 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 22 Oct 2017 20:51:31 -0300 Subject: [PATCH 0570/2557] avcodec/tak: make buf const in avpriv_dca_parse_core_frame_header() Signed-off-by: James Almer --- libavcodec/dca.c | 2 +- libavcodec/dca.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/dca.c b/libavcodec/dca.c index 307b21471e661..942fe6c3c9d19 100644 --- a/libavcodec/dca.c +++ b/libavcodec/dca.c @@ -146,7 +146,7 @@ int ff_dca_parse_core_frame_header(DCACoreFrameHeader *h, GetBitContext *gb) return 0; } -int avpriv_dca_parse_core_frame_header(DCACoreFrameHeader *h, uint8_t *buf, int size) +int avpriv_dca_parse_core_frame_header(DCACoreFrameHeader *h, const uint8_t *buf, int size) { GetBitContext gb; diff --git a/libavcodec/dca.h b/libavcodec/dca.h index 172c965b3b412..c70598af92009 100644 --- a/libavcodec/dca.h +++ b/libavcodec/dca.h @@ -213,7 +213,7 @@ int avpriv_dca_convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst, * Parse and validate core frame header * @return 0 on success, negative DCA_PARSE_ERROR_ code on failure */ -int avpriv_dca_parse_core_frame_header(DCACoreFrameHeader *h, uint8_t *buf, int size); +int avpriv_dca_parse_core_frame_header(DCACoreFrameHeader *h, const uint8_t *buf, int size); int ff_dca_parse_core_frame_header(DCACoreFrameHeader *h, GetBitContext *gb); From 3605b312f65c4a009301d2d165e2db8d68063acb Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 22 Oct 2017 01:11:55 +0200 Subject: [PATCH 0571/2557] lavf/avio: Print the https warning also for missing tls protocol. --- libavformat/avio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/avio.c b/libavformat/avio.c index 4718753b7b99a..4dc468350c943 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -297,7 +297,7 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags, return url_alloc_for_protocol(puc, p, filename, flags, int_cb); *puc = NULL; - if (av_strstart(filename, "https:", NULL)) + if (av_strstart(filename, "https:", NULL) || av_strstart(filename, "tls:", NULL)) av_log(NULL, AV_LOG_WARNING, "https protocol not found, recompile FFmpeg with " "openssl, gnutls " "or securetransport enabled.\n"); From 2b320318273b74df6e1b712fb33544d6a1b26be1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Tue, 5 Sep 2017 15:58:13 +0200 Subject: [PATCH 0572/2557] lavc: drop VDA Deprecated (aka removed) in OSX 10.11, and we have a replacement for it (VideoToolbox). --- Changelog | 1 + MAINTAINERS | 1 - configure | 14 - doc/ffmpeg.texi | 3 - fftools/ffmpeg.h | 2 - fftools/ffmpeg_opt.c | 6 +- fftools/ffmpeg_videotoolbox.c | 45 +- libavcodec/Makefile | 7 +- libavcodec/allcodecs.c | 3 - libavcodec/h264_slice.c | 5 - libavcodec/vda.c | 84 ---- libavcodec/vda.h | 230 ---------- libavcodec/vda_h264.c | 425 ------------------ libavcodec/vda_h264_dec.c | 263 ----------- libavcodec/videotoolbox.c | 10 +- .../{vda_vt_internal.h => vt_internal.h} | 16 +- libavutil/pixdesc.c | 10 - libavutil/pixfmt.h | 3 - libavutil/utils.c | 3 - 19 files changed, 14 insertions(+), 1117 deletions(-) delete mode 100644 libavcodec/vda.c delete mode 100644 libavcodec/vda.h delete mode 100644 libavcodec/vda_h264.c delete mode 100644 libavcodec/vda_h264_dec.c rename libavcodec/{vda_vt_internal.h => vt_internal.h} (82%) diff --git a/Changelog b/Changelog index b7c1348f77573..6592d868dace7 100644 --- a/Changelog +++ b/Changelog @@ -5,6 +5,7 @@ version : - Bitstream filters for editing metadata in H.264, HEVC and MPEG-2 streams - Dropped support for OpenJPEG versions 2.0 and below. Using OpenJPEG now requires 2.1 (or later) and pkg-config. +- VDA dropped (use VideoToolbox instead) version 3.4: diff --git a/MAINTAINERS b/MAINTAINERS index 9027ed5846e92..1d2ff78b0e88f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -244,7 +244,6 @@ Codecs: txd.c Ivo van Poorten vc2* Rostislav Pehlivanov vcr1.c Michael Niedermayer - vda_h264_dec.c Xidorn Quan videotoolboxenc.c Rick Kern vima.c Paul B Mahol vorbisdec.c Denes Balatoni, David Conrad diff --git a/configure b/configure index 31830d4fcdc5a..e487610c1a7e2 100755 --- a/configure +++ b/configure @@ -318,7 +318,6 @@ External library support: --enable-omx-rpi enable OpenMAX IL code for Raspberry Pi [no] --enable-rkmpp enable Rockchip Media Process Platform code [no] --disable-vaapi disable Video Acceleration API (mainly Unix/Intel) code [autodetect] - --disable-vda disable Apple Video Decode Acceleration code [autodetect] --disable-vdpau disable Nvidia Video Decode and Presentation API for Unix code [autodetect] --disable-videotoolbox disable VideoToolbox code [autodetect] @@ -1650,7 +1649,6 @@ HWACCEL_AUTODETECT_LIBRARY_LIST=" dxva2 nvenc vaapi - vda vdpau videotoolbox v4l2_m2m @@ -2660,10 +2658,6 @@ cuda_deps_any="libdl LoadLibrary" cuvid_deps="cuda" d3d11va_deps="d3d11_h dxva_h ID3D11VideoDecoder ID3D11VideoContext" dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" -vda_framework_deps="VideoDecodeAcceleration_VDADecoder_h blocks_extension" -vda_framework_extralibs="-framework VideoDecodeAcceleration" -vda_deps="vda_framework pthreads corefoundation" -vda_extralibs="-framework QuartzCore" videotoolbox_hwaccel_deps="videotoolbox pthreads" videotoolbox_hwaccel_extralibs="-framework QuartzCore" xvmc_deps="X11_extensions_XvMClib_h" @@ -2685,10 +2679,6 @@ h264_mmal_hwaccel_deps="mmal" h264_qsv_hwaccel_deps="libmfx" h264_vaapi_hwaccel_deps="vaapi" h264_vaapi_hwaccel_select="h264_decoder" -h264_vda_hwaccel_deps="vda" -h264_vda_hwaccel_select="h264_decoder" -h264_vda_old_hwaccel_deps="vda" -h264_vda_old_hwaccel_select="h264_decoder" h264_vdpau_hwaccel_deps="vdpau" h264_vdpau_hwaccel_select="h264_decoder" h264_videotoolbox_hwaccel_deps="videotoolbox" @@ -2822,8 +2812,6 @@ h264_rkmpp_decoder_deps="rkmpp" h264_rkmpp_decoder_select="h264_mp4toannexb_bsf" h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" h264_vaapi_encoder_select="cbs_h264 vaapi_encode" -h264_vda_decoder_deps="vda" -h264_vda_decoder_select="h264_decoder" h264_vdpau_decoder_deps="vdpau" h264_vdpau_decoder_select="h264_decoder" h264_v4l2m2m_decoder_deps="v4l2_m2m h264_v4l2_m2m" @@ -3011,7 +2999,6 @@ libzvbi_teletext_decoder_deps="libzvbi" videotoolbox_suggest="coreservices" videotoolbox_deps="corefoundation coremedia corevideo" videotoolbox_encoder_deps="videotoolbox VTCompressionSessionPrepareToEncodeFrames" -videotoolbox_encoder_suggest="vda_framework" # demuxers / muxers ac3_demuxer_select="ac3_parser" @@ -5847,7 +5834,6 @@ check_header sys/un.h check_header termios.h check_header unistd.h check_header valgrind/valgrind.h -check_header VideoDecodeAcceleration/VDADecoder.h check_func_headers VideoToolbox/VTCompressionSession.h VTCompressionSessionPrepareToEncodeFrames -framework VideoToolbox check_header windows.h check_header X11/extensions/XvMClib.h diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 0405d009b967f..cdb3bc68aeff3 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -786,9 +786,6 @@ Do not use any hardware acceleration (the default). @item auto Automatically select the hardware acceleration method. -@item vda -Use Apple VDA hardware acceleration. - @item vdpau Use VDPAU (Video Decode and Presentation API for Unix) hardware acceleration. diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 888f77223a36d..0db481d74725b 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -63,7 +63,6 @@ enum HWAccelID { HWACCEL_AUTO, HWACCEL_VDPAU, HWACCEL_DXVA2, - HWACCEL_VDA, HWACCEL_VIDEOTOOLBOX, HWACCEL_QSV, HWACCEL_VAAPI, @@ -661,7 +660,6 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); int ffmpeg_parse_options(int argc, char **argv); -int vda_init(AVCodecContext *s); int videotoolbox_init(AVCodecContext *s); int qsv_init(AVCodecContext *s); int cuvid_init(AVCodecContext *s); diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 500920326b136..2fa5d6d2861f4 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -78,10 +78,6 @@ const HWAccel hwaccels[] = { { "dxva2", hwaccel_decode_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD, AV_HWDEVICE_TYPE_DXVA2 }, #endif -#if CONFIG_VDA - { "vda", videotoolbox_init, HWACCEL_VDA, AV_PIX_FMT_VDA, - AV_HWDEVICE_TYPE_NONE }, -#endif #if CONFIG_VIDEOTOOLBOX { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX, AV_HWDEVICE_TYPE_NONE }, @@ -3631,7 +3627,7 @@ const OptionDef options[] = { { "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_output_formats) }, "select output format used with HW accelerated decoding", "format" }, -#if CONFIG_VDA || CONFIG_VIDEOTOOLBOX +#if CONFIG_VIDEOTOOLBOX { "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" }, #endif { "hwaccels", OPT_EXIT, { .func_arg = show_hwaccels }, diff --git a/fftools/ffmpeg_videotoolbox.c b/fftools/ffmpeg_videotoolbox.c index e9039654b93de..b820aec017f7d 100644 --- a/fftools/ffmpeg_videotoolbox.c +++ b/fftools/ffmpeg_videotoolbox.c @@ -23,12 +23,7 @@ #endif #include "libavcodec/avcodec.h" -#if CONFIG_VDA -# include "libavcodec/vda.h" -#endif -#if CONFIG_VIDEOTOOLBOX -# include "libavcodec/videotoolbox.h" -#endif +#include "libavcodec/videotoolbox.h" #include "libavutil/imgutils.h" #include "ffmpeg.h" @@ -114,15 +109,7 @@ static void videotoolbox_uninit(AVCodecContext *s) av_frame_free(&vt->tmp_frame); - if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) { -#if CONFIG_VIDEOTOOLBOX - av_videotoolbox_default_free(s); -#endif - } else { -#if CONFIG_VDA - av_vda_default_free(s); -#endif - } + av_videotoolbox_default_free(s); av_freep(&ist->hwaccel_ctx); } @@ -147,8 +134,7 @@ int videotoolbox_init(AVCodecContext *s) goto fail; } - if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) { -#if CONFIG_VIDEOTOOLBOX + // TODO: reindent if (!videotoolbox_pixfmt) { ret = av_videotoolbox_default_init(s); } else { @@ -166,31 +152,8 @@ int videotoolbox_init(AVCodecContext *s) ret = av_videotoolbox_default_init2(s, vtctx); CFRelease(pixfmt_str); } -#endif - } else { -#if CONFIG_VDA - if (!videotoolbox_pixfmt) { - ret = av_vda_default_init(s); - } else { - AVVDAContext *vdactx = av_vda_alloc_context(); - CFStringRef pixfmt_str = CFStringCreateWithCString(kCFAllocatorDefault, - videotoolbox_pixfmt, - kCFStringEncodingUTF8); -#if HAVE_UTGETOSTYPEFROMSTRING - vdactx->cv_pix_fmt_type = UTGetOSTypeFromString(pixfmt_str); -#else - av_log(s, loglevel, "UTGetOSTypeFromString() is not available " - "on this platform, %s pixel format can not be honored from " - "the command line\n", videotoolbox_pixfmt); -#endif - ret = av_vda_default_init2(s, vdactx); - CFRelease(pixfmt_str); - } -#endif - } if (ret < 0) { - av_log(NULL, loglevel, - "Error creating %s decoder.\n", ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX ? "Videotoolbox" : "VDA"); + av_log(NULL, loglevel, "Error creating Videotoolbox decoder.\n"); goto fail; } diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 4424e749ce546..bc4d7dab27761 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -12,7 +12,6 @@ HEADERS = avcodec.h \ mediacodec.h \ qsv.h \ vaapi.h \ - vda.h \ vdpau.h \ version.h \ videotoolbox.h \ @@ -338,7 +337,6 @@ OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o OBJS-$(CONFIG_NVENC_ENCODER) += nvenc_h264.o OBJS-$(CONFIG_NVENC_H264_ENCODER) += nvenc_h264.o -OBJS-$(CONFIG_H264_VDA_DECODER) += vda_h264_dec.o OBJS-$(CONFIG_H264_OMX_ENCODER) += omx.o OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec_h2645.o OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.o @@ -824,7 +822,6 @@ OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o OBJS-$(CONFIG_D3D11VA) += dxva2.o OBJS-$(CONFIG_DXVA2) += dxva2.o OBJS-$(CONFIG_VAAPI) += vaapi_decode.o -OBJS-$(CONFIG_VDA) += vda.o videotoolbox.o OBJS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.o OBJS-$(CONFIG_VDPAU) += vdpau.o @@ -834,7 +831,6 @@ OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec_h2645.o OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o -OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o @@ -1066,9 +1062,8 @@ SKIPHEADERS-$(CONFIG_QSVDEC) += qsvdec.h SKIPHEADERS-$(CONFIG_QSVENC) += qsvenc.h SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_decode.h vaapi_encode.h -SKIPHEADERS-$(CONFIG_VDA) += vda.h vda_vt_internal.h SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h vdpau_internal.h -SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vda_vt_internal.h +SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vt_internal.h SKIPHEADERS-$(CONFIG_V4L2_M2M) += v4l2_buffers.h v4l2_context.h v4l2_m2m.h TESTPROGS = avpacket \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4f34312e67353..60b66d46b97fa 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -72,8 +72,6 @@ static void register_all(void) REGISTER_HWACCEL(H264_MMAL, h264_mmal); REGISTER_HWACCEL(H264_QSV, h264_qsv); REGISTER_HWACCEL(H264_VAAPI, h264_vaapi); - REGISTER_HWACCEL(H264_VDA, h264_vda); - REGISTER_HWACCEL(H264_VDA_OLD, h264_vda_old); REGISTER_HWACCEL(H264_VDPAU, h264_vdpau); REGISTER_HWACCEL(H264_VIDEOTOOLBOX, h264_videotoolbox); REGISTER_HWACCEL(HEVC_CUVID, hevc_cuvid); @@ -217,7 +215,6 @@ static void register_all(void) REGISTER_DECODER(H264_MMAL, h264_mmal); REGISTER_DECODER(H264_QSV, h264_qsv); REGISTER_DECODER(H264_RKMPP, h264_rkmpp); - REGISTER_DECODER(H264_VDA, h264_vda); #if FF_API_VDPAU REGISTER_DECODER(H264_VDPAU, h264_vdpau); #endif diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 5d9558745e2a4..35dcabd611352 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -755,7 +755,6 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) #define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \ (CONFIG_H264_D3D11VA_HWACCEL * 2) + \ CONFIG_H264_VAAPI_HWACCEL + \ - (CONFIG_H264_VDA_HWACCEL * 2) + \ CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \ CONFIG_H264_VDPAU_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts; @@ -834,10 +833,6 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) #if CONFIG_H264_VAAPI_HWACCEL *fmt++ = AV_PIX_FMT_VAAPI; #endif -#if CONFIG_H264_VDA_HWACCEL - *fmt++ = AV_PIX_FMT_VDA_VLD; - *fmt++ = AV_PIX_FMT_VDA; -#endif #if CONFIG_H264_VIDEOTOOLBOX_HWACCEL *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif diff --git a/libavcodec/vda.c b/libavcodec/vda.c deleted file mode 100644 index 819ae030b03fd..0000000000000 --- a/libavcodec/vda.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#include "libavutil/mem.h" - -#include "vda.h" -#include "vda_vt_internal.h" - -#if CONFIG_H264_VDA_HWACCEL -AVVDAContext *av_vda_alloc_context(void) -{ - AVVDAContext *ret = av_mallocz(sizeof(*ret)); - - if (ret) { - ret->output_callback = ff_vda_output_callback; - ret->cv_pix_fmt_type = kCVPixelFormatType_422YpCbCr8; - } - - return ret; -} - -int av_vda_default_init(AVCodecContext *avctx) -{ - return av_vda_default_init2(avctx, NULL); -} - -int av_vda_default_init2(AVCodecContext *avctx, AVVDAContext *vdactx) -{ - avctx->hwaccel_context = vdactx ?: av_vda_alloc_context(); - if (!avctx->hwaccel_context) - return AVERROR(ENOMEM); - return ff_vda_default_init(avctx); -} - -void av_vda_default_free(AVCodecContext *avctx) -{ - ff_vda_default_free(avctx); - av_freep(&avctx->hwaccel_context); -} - -void ff_vda_default_free(AVCodecContext *avctx) -{ - AVVDAContext *vda = avctx->hwaccel_context; - if (vda && vda->decoder) - VDADecoderDestroy(vda->decoder); -} - -#else -AVVDAContext *av_vda_alloc_context(void) -{ - return NULL; -} - -int av_vda_default_init(AVCodecContext *avctx) -{ - return AVERROR(ENOSYS); -} - -int av_vda_default_init2(AVCodecContext *avctx, AVVDAContext *vdactx) -{ - return AVERROR(ENOSYS); -} - -void av_vda_default_free(AVCodecContext *ctx) -{ -} -#endif diff --git a/libavcodec/vda.h b/libavcodec/vda.h deleted file mode 100644 index bde14e31d7dfd..0000000000000 --- a/libavcodec/vda.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - * VDA HW acceleration - * - * copyright (c) 2011 Sebastien Zwickert - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVCODEC_VDA_H -#define AVCODEC_VDA_H - -/** - * @file - * @ingroup lavc_codec_hwaccel_vda - * Public libavcodec VDA header. - */ - -#include "libavcodec/avcodec.h" - -#include - -// emmintrin.h is unable to compile with -std=c99 -Werror=missing-prototypes -// http://openradar.appspot.com/8026390 -#undef __GNUC_STDC_INLINE__ - -#define Picture QuickdrawPicture -#include -#undef Picture - -#include "libavcodec/version.h" - -// extra flags not defined in VDADecoder.h -enum { - kVDADecodeInfo_Asynchronous = 1UL << 0, - kVDADecodeInfo_FrameDropped = 1UL << 1 -}; - -/** - * @defgroup lavc_codec_hwaccel_vda VDA - * @ingroup lavc_codec_hwaccel - * - * @{ - */ - -/** - * This structure is used to provide the necessary configurations and data - * to the VDA FFmpeg HWAccel implementation. - * - * The application must make it available as AVCodecContext.hwaccel_context. - */ -struct vda_context { - /** - * VDA decoder object. - * - * - encoding: unused - * - decoding: Set/Unset by libavcodec. - */ - VDADecoder decoder; - - /** - * The Core Video pixel buffer that contains the current image data. - * - * encoding: unused - * decoding: Set by libavcodec. Unset by user. - */ - CVPixelBufferRef cv_buffer; - - /** - * Use the hardware decoder in synchronous mode. - * - * encoding: unused - * decoding: Set by user. - */ - int use_sync_decoding; - - /** - * The frame width. - * - * - encoding: unused - * - decoding: Set/Unset by user. - */ - int width; - - /** - * The frame height. - * - * - encoding: unused - * - decoding: Set/Unset by user. - */ - int height; - - /** - * The frame format. - * - * - encoding: unused - * - decoding: Set/Unset by user. - */ - int format; - - /** - * The pixel format for output image buffers. - * - * - encoding: unused - * - decoding: Set/Unset by user. - */ - OSType cv_pix_fmt_type; - - /** - * unused - */ - uint8_t *priv_bitstream; - - /** - * unused - */ - int priv_bitstream_size; - - /** - * unused - */ - int priv_allocated_size; - - /** - * Use av_buffer to manage buffer. - * When the flag is set, the CVPixelBuffers returned by the decoder will - * be released automatically, so you have to retain them if necessary. - * Not setting this flag may cause memory leak. - * - * encoding: unused - * decoding: Set by user. - */ - int use_ref_buffer; -}; - -/** Create the video decoder. */ -int ff_vda_create_decoder(struct vda_context *vda_ctx, - uint8_t *extradata, - int extradata_size); - -/** Destroy the video decoder. */ -int ff_vda_destroy_decoder(struct vda_context *vda_ctx); - -/** - * This struct holds all the information that needs to be passed - * between the caller and libavcodec for initializing VDA decoding. - * Its size is not a part of the public ABI, it must be allocated with - * av_vda_alloc_context() and freed with av_free(). - */ -typedef struct AVVDAContext { - /** - * VDA decoder object. Created and freed by the caller. - */ - VDADecoder decoder; - - /** - * The output callback that must be passed to VDADecoderCreate. - * Set by av_vda_alloc_context(). - */ - VDADecoderOutputCallback output_callback; - - /** - * CVPixelBuffer Format Type that VDA will use for decoded frames; set by - * the caller. - */ - OSType cv_pix_fmt_type; -} AVVDAContext; - -/** - * Allocate and initialize a VDA context. - * - * This function should be called from the get_format() callback when the caller - * selects the AV_PIX_FMT_VDA format. The caller must then create the decoder - * object (using the output callback provided by libavcodec) that will be used - * for VDA-accelerated decoding. - * - * When decoding with VDA is finished, the caller must destroy the decoder - * object and free the VDA context using av_free(). - * - * @return the newly allocated context or NULL on failure - */ -AVVDAContext *av_vda_alloc_context(void); - -/** - * This is a convenience function that creates and sets up the VDA context using - * an internal implementation. - * - * @param avctx the corresponding codec context - * - * @return >= 0 on success, a negative AVERROR code on failure - */ -int av_vda_default_init(AVCodecContext *avctx); - -/** - * This is a convenience function that creates and sets up the VDA context using - * an internal implementation. - * - * @param avctx the corresponding codec context - * @param vdactx the VDA context to use - * - * @return >= 0 on success, a negative AVERROR code on failure - */ -int av_vda_default_init2(AVCodecContext *avctx, AVVDAContext *vdactx); - -/** - * This function must be called to free the VDA context initialized with - * av_vda_default_init(). - * - * @param avctx the corresponding codec context - */ -void av_vda_default_free(AVCodecContext *avctx); - -/** - * @} - */ - -#endif /* AVCODEC_VDA_H */ diff --git a/libavcodec/vda_h264.c b/libavcodec/vda_h264.c deleted file mode 100644 index 7b88ec7015f54..0000000000000 --- a/libavcodec/vda_h264.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * VDA H264 HW acceleration. - * - * copyright (c) 2011 Sebastien Zwickert - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include - -#include "vda.h" -#include "libavutil/avutil.h" -#include "h264dec.h" - -struct vda_buffer { - CVPixelBufferRef cv_buffer; -}; -#include "internal.h" -#include "vda_vt_internal.h" - -/* Decoder callback that adds the vda frame to the queue in display order. */ -static void vda_decoder_callback(void *vda_hw_ctx, - CFDictionaryRef user_info, - OSStatus status, - uint32_t infoFlags, - CVImageBufferRef image_buffer) -{ - struct vda_context *vda_ctx = vda_hw_ctx; - - if (infoFlags & kVDADecodeInfo_FrameDropped) - vda_ctx->cv_buffer = NULL; - - if (!image_buffer) - return; - - if (vda_ctx->cv_pix_fmt_type != CVPixelBufferGetPixelFormatType(image_buffer)) - return; - - vda_ctx->cv_buffer = CVPixelBufferRetain(image_buffer); -} - -static int vda_sync_decode(VTContext *ctx, struct vda_context *vda_ctx) -{ - OSStatus status; - CFDataRef coded_frame; - uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames - - coded_frame = CFDataCreate(kCFAllocatorDefault, - ctx->bitstream, - ctx->bitstream_size); - - status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL); - - if (kVDADecoderNoErr == status) - status = VDADecoderFlush(vda_ctx->decoder, flush_flags); - - CFRelease(coded_frame); - - return status; -} - - -static int vda_old_h264_start_frame(AVCodecContext *avctx, - av_unused const uint8_t *buffer, - av_unused uint32_t size) -{ - VTContext *vda = avctx->internal->hwaccel_priv_data; - struct vda_context *vda_ctx = avctx->hwaccel_context; - - if (!vda_ctx->decoder) - return -1; - - vda->bitstream_size = 0; - - return 0; -} - -static int vda_old_h264_decode_slice(AVCodecContext *avctx, - const uint8_t *buffer, - uint32_t size) -{ - VTContext *vda = avctx->internal->hwaccel_priv_data; - struct vda_context *vda_ctx = avctx->hwaccel_context; - void *tmp; - - if (!vda_ctx->decoder) - return -1; - - tmp = av_fast_realloc(vda->bitstream, - &vda->allocated_size, - vda->bitstream_size + size + 4); - if (!tmp) - return AVERROR(ENOMEM); - - vda->bitstream = tmp; - - AV_WB32(vda->bitstream + vda->bitstream_size, size); - memcpy(vda->bitstream + vda->bitstream_size + 4, buffer, size); - - vda->bitstream_size += size + 4; - - return 0; -} - -static void vda_h264_release_buffer(void *opaque, uint8_t *data) -{ - struct vda_buffer *context = opaque; - CVPixelBufferRelease(context->cv_buffer); - av_free(context); -} - -static int vda_old_h264_end_frame(AVCodecContext *avctx) -{ - H264Context *h = avctx->priv_data; - VTContext *vda = avctx->internal->hwaccel_priv_data; - struct vda_context *vda_ctx = avctx->hwaccel_context; - AVFrame *frame = h->cur_pic_ptr->f; - struct vda_buffer *context; - AVBufferRef *buffer; - int status; - - if (!vda_ctx->decoder || !vda->bitstream) - return -1; - - status = vda_sync_decode(vda, vda_ctx); - frame->data[3] = (void*)vda_ctx->cv_buffer; - - if (status) - av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status); - - if (!vda_ctx->use_ref_buffer || status) - return status; - - context = av_mallocz(sizeof(*context)); - buffer = av_buffer_create(NULL, 0, vda_h264_release_buffer, context, 0); - if (!context || !buffer) { - CVPixelBufferRelease(vda_ctx->cv_buffer); - av_free(context); - return -1; - } - - context->cv_buffer = vda_ctx->cv_buffer; - frame->buf[3] = buffer; - - return status; -} - -int ff_vda_create_decoder(struct vda_context *vda_ctx, - uint8_t *extradata, - int extradata_size) -{ - OSStatus status; - CFNumberRef height; - CFNumberRef width; - CFNumberRef format; - CFDataRef avc_data; - CFMutableDictionaryRef config_info; - CFMutableDictionaryRef buffer_attributes; - CFMutableDictionaryRef io_surface_properties; - CFNumberRef cv_pix_fmt; - - vda_ctx->priv_bitstream = NULL; - vda_ctx->priv_allocated_size = 0; - - /* Each VCL NAL in the bitstream sent to the decoder - * is preceded by a 4 bytes length header. - * Change the avcC atom header if needed, to signal headers of 4 bytes. */ - if (extradata_size >= 4 && (extradata[4] & 0x03) != 0x03) { - uint8_t *rw_extradata; - - if (!(rw_extradata = av_malloc(extradata_size))) - return AVERROR(ENOMEM); - - memcpy(rw_extradata, extradata, extradata_size); - - rw_extradata[4] |= 0x03; - - avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, extradata_size); - - av_freep(&rw_extradata); - } else { - avc_data = CFDataCreate(kCFAllocatorDefault, extradata, extradata_size); - } - - config_info = CFDictionaryCreateMutable(kCFAllocatorDefault, - 4, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->height); - width = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->width); - format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->format); - - CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height); - CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width); - CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format); - CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data); - - buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, - 2, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt32Type, - &vda_ctx->cv_pix_fmt_type); - CFDictionarySetValue(buffer_attributes, - kCVPixelBufferPixelFormatTypeKey, - cv_pix_fmt); - CFDictionarySetValue(buffer_attributes, - kCVPixelBufferIOSurfacePropertiesKey, - io_surface_properties); - - status = VDADecoderCreate(config_info, - buffer_attributes, - (VDADecoderOutputCallback *)vda_decoder_callback, - vda_ctx, - &vda_ctx->decoder); - - CFRelease(height); - CFRelease(width); - CFRelease(format); - CFRelease(avc_data); - CFRelease(config_info); - CFRelease(io_surface_properties); - CFRelease(cv_pix_fmt); - CFRelease(buffer_attributes); - - return status; -} - -int ff_vda_destroy_decoder(struct vda_context *vda_ctx) -{ - OSStatus status = kVDADecoderNoErr; - - if (vda_ctx->decoder) - status = VDADecoderDestroy(vda_ctx->decoder); - - return status; -} - -AVHWAccel ff_h264_vda_old_hwaccel = { - .name = "h264_vda", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .pix_fmt = AV_PIX_FMT_VDA_VLD, - .start_frame = vda_old_h264_start_frame, - .decode_slice = vda_old_h264_decode_slice, - .end_frame = vda_old_h264_end_frame, - .uninit = ff_videotoolbox_uninit, - .priv_data_size = sizeof(VTContext), -}; - -void ff_vda_output_callback(void *opaque, - CFDictionaryRef user_info, - OSStatus status, - uint32_t infoFlags, - CVImageBufferRef image_buffer) -{ - AVCodecContext *ctx = opaque; - VTContext *vda = ctx->internal->hwaccel_priv_data; - - - if (vda->frame) { - CVPixelBufferRelease(vda->frame); - vda->frame = NULL; - } - - if (!image_buffer) - return; - - vda->frame = CVPixelBufferRetain(image_buffer); -} - -static int vda_h264_end_frame(AVCodecContext *avctx) -{ - H264Context *h = avctx->priv_data; - VTContext *vda = avctx->internal->hwaccel_priv_data; - AVVDAContext *vda_ctx = avctx->hwaccel_context; - AVFrame *frame = h->cur_pic_ptr->f; - uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames - CFDataRef coded_frame; - OSStatus status; - - if (!vda->bitstream_size) - return AVERROR_INVALIDDATA; - - - coded_frame = CFDataCreate(kCFAllocatorDefault, - vda->bitstream, - vda->bitstream_size); - - status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL); - - if (status == kVDADecoderNoErr) - status = VDADecoderFlush(vda_ctx->decoder, flush_flags); - - CFRelease(coded_frame); - - if (!vda->frame) - return AVERROR_UNKNOWN; - - if (status != kVDADecoderNoErr) { - av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status); - return AVERROR_UNKNOWN; - } - - return ff_videotoolbox_buffer_create(vda, frame); -} - -int ff_vda_default_init(AVCodecContext *avctx) -{ - AVVDAContext *vda_ctx = avctx->hwaccel_context; - OSStatus status = kVDADecoderNoErr; - CFNumberRef height; - CFNumberRef width; - CFNumberRef format; - CFDataRef avc_data; - CFMutableDictionaryRef config_info; - CFMutableDictionaryRef buffer_attributes; - CFMutableDictionaryRef io_surface_properties; - CFNumberRef cv_pix_fmt; - int32_t fmt = 'avc1', pix_fmt = vda_ctx->cv_pix_fmt_type; - - // kCVPixelFormatType_420YpCbCr8Planar; - - avc_data = ff_videotoolbox_avcc_extradata_create(avctx); - - config_info = CFDictionaryCreateMutable(kCFAllocatorDefault, - 4, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->height); - width = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->width); - format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &fmt); - CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height); - CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width); - CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data); - CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format); - - buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, - 2, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt32Type, - &pix_fmt); - - CFDictionarySetValue(buffer_attributes, - kCVPixelBufferPixelFormatTypeKey, - cv_pix_fmt); - CFDictionarySetValue(buffer_attributes, - kCVPixelBufferIOSurfacePropertiesKey, - io_surface_properties); - - status = VDADecoderCreate(config_info, - buffer_attributes, - (VDADecoderOutputCallback *)ff_vda_output_callback, - avctx, - &vda_ctx->decoder); - - CFRelease(format); - CFRelease(height); - CFRelease(width); - CFRelease(avc_data); - CFRelease(config_info); - CFRelease(cv_pix_fmt); - CFRelease(io_surface_properties); - CFRelease(buffer_attributes); - - if (status != kVDADecoderNoErr) { - av_log(avctx, AV_LOG_ERROR, "Cannot initialize VDA %d\n", status); - } - - switch (status) { - case kVDADecoderHardwareNotSupportedErr: - case kVDADecoderFormatNotSupportedErr: - return AVERROR(ENOSYS); - case kVDADecoderConfigurationError: - return AVERROR(EINVAL); - case kVDADecoderDecoderFailedErr: - return AVERROR_INVALIDDATA; - case kVDADecoderNoErr: - return 0; - default: - return AVERROR_UNKNOWN; - } -} - -AVHWAccel ff_h264_vda_hwaccel = { - .name = "h264_vda", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .pix_fmt = AV_PIX_FMT_VDA, - .alloc_frame = ff_videotoolbox_alloc_frame, - .start_frame = ff_videotoolbox_h264_start_frame, - .decode_slice = ff_videotoolbox_h264_decode_slice, - .end_frame = vda_h264_end_frame, - .uninit = ff_videotoolbox_uninit, - .priv_data_size = sizeof(VTContext), -}; diff --git a/libavcodec/vda_h264_dec.c b/libavcodec/vda_h264_dec.c deleted file mode 100644 index 972bd6bbd6441..0000000000000 --- a/libavcodec/vda_h264_dec.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (c) 2012, Xidorn Quan - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * H.264 decoder via VDA - * @author Xidorn Quan - */ - -#include -#include - -#include "vda.h" -#include "h264dec.h" -#include "avcodec.h" - -#ifndef kCFCoreFoundationVersionNumber10_7 -#define kCFCoreFoundationVersionNumber10_7 635.00 -#endif - -extern AVCodec ff_h264_decoder, ff_h264_vda_decoder; - -static const enum AVPixelFormat vda_pixfmts_prior_10_7[] = { - AV_PIX_FMT_UYVY422, - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_NONE -}; - -static const enum AVPixelFormat vda_pixfmts[] = { - AV_PIX_FMT_UYVY422, - AV_PIX_FMT_YUYV422, - AV_PIX_FMT_NV12, - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_NONE -}; - -typedef struct { - H264Context h264ctx; - int h264_initialized; - struct vda_context vda_ctx; - enum AVPixelFormat pix_fmt; - - /* for backing-up fields set by user. - * we have to gain full control of such fields here */ - void *hwaccel_context; - enum AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt); - int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags); -} VDADecoderContext; - -static enum AVPixelFormat get_format(struct AVCodecContext *avctx, - const enum AVPixelFormat *fmt) -{ - return AV_PIX_FMT_VDA_VLD; -} - -typedef struct { - CVPixelBufferRef cv_buffer; -} VDABufferContext; - -static void release_buffer(void *opaque, uint8_t *data) -{ - VDABufferContext *context = opaque; - CVPixelBufferUnlockBaseAddress(context->cv_buffer, 0); - CVPixelBufferRelease(context->cv_buffer); - av_free(context); -} - -static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flag) -{ - VDABufferContext *context = av_mallocz(sizeof(VDABufferContext)); - AVBufferRef *buffer = av_buffer_create(NULL, 0, release_buffer, context, 0); - if (!context || !buffer) { - av_free(context); - return AVERROR(ENOMEM); - } - - pic->buf[0] = buffer; - pic->data[0] = (void *)1; - return 0; -} - -static inline void set_context(AVCodecContext *avctx) -{ - VDADecoderContext *ctx = avctx->priv_data; - ctx->hwaccel_context = avctx->hwaccel_context; - avctx->hwaccel_context = &ctx->vda_ctx; - ctx->get_format = avctx->get_format; - avctx->get_format = get_format; - ctx->get_buffer2 = avctx->get_buffer2; - avctx->get_buffer2 = get_buffer2; -} - -static inline void restore_context(AVCodecContext *avctx) -{ - VDADecoderContext *ctx = avctx->priv_data; - avctx->hwaccel_context = ctx->hwaccel_context; - avctx->get_format = ctx->get_format; - avctx->get_buffer2 = ctx->get_buffer2; -} - -static int vdadec_decode(AVCodecContext *avctx, - void *data, int *got_frame, AVPacket *avpkt) -{ - VDADecoderContext *ctx = avctx->priv_data; - AVFrame *pic = data; - int ret; - - set_context(avctx); - ret = ff_h264_decoder.decode(avctx, data, got_frame, avpkt); - restore_context(avctx); - if (*got_frame) { - AVBufferRef *buffer = pic->buf[0]; - VDABufferContext *context = av_buffer_get_opaque(buffer); - CVPixelBufferRef cv_buffer = (CVPixelBufferRef)pic->data[3]; - - CVPixelBufferRetain(cv_buffer); - CVPixelBufferLockBaseAddress(cv_buffer, 0); - context->cv_buffer = cv_buffer; - pic->format = ctx->pix_fmt; - if (CVPixelBufferIsPlanar(cv_buffer)) { - int i, count = CVPixelBufferGetPlaneCount(cv_buffer); - av_assert0(count < 4); - for (i = 0; i < count; i++) { - pic->data[i] = CVPixelBufferGetBaseAddressOfPlane(cv_buffer, i); - pic->linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(cv_buffer, i); - } - } else { - pic->data[0] = CVPixelBufferGetBaseAddress(cv_buffer); - pic->linesize[0] = CVPixelBufferGetBytesPerRow(cv_buffer); - } - } - avctx->pix_fmt = ctx->pix_fmt; - - return ret; -} - -static av_cold int vdadec_close(AVCodecContext *avctx) -{ - VDADecoderContext *ctx = avctx->priv_data; - /* release buffers and decoder */ - ff_vda_destroy_decoder(&ctx->vda_ctx); - /* close H.264 decoder */ - if (ctx->h264_initialized) { - set_context(avctx); - ff_h264_decoder.close(avctx); - restore_context(avctx); - } - return 0; -} - -static av_cold int vdadec_init(AVCodecContext *avctx) -{ - VDADecoderContext *ctx = avctx->priv_data; - struct vda_context *vda_ctx = &ctx->vda_ctx; - OSStatus status; - int ret, i; - - ctx->h264_initialized = 0; - - /* init pix_fmts of codec */ - if (!ff_h264_vda_decoder.pix_fmts) { - if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber10_7) - ff_h264_vda_decoder.pix_fmts = vda_pixfmts_prior_10_7; - else - ff_h264_vda_decoder.pix_fmts = vda_pixfmts; - } - - /* init vda */ - memset(vda_ctx, 0, sizeof(struct vda_context)); - vda_ctx->width = avctx->width; - vda_ctx->height = avctx->height; - vda_ctx->format = 'avc1'; - vda_ctx->use_sync_decoding = 1; - vda_ctx->use_ref_buffer = 1; - ctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts); - switch (ctx->pix_fmt) { - case AV_PIX_FMT_UYVY422: - vda_ctx->cv_pix_fmt_type = '2vuy'; - break; - case AV_PIX_FMT_YUYV422: - vda_ctx->cv_pix_fmt_type = 'yuvs'; - break; - case AV_PIX_FMT_NV12: - vda_ctx->cv_pix_fmt_type = '420v'; - break; - case AV_PIX_FMT_YUV420P: - vda_ctx->cv_pix_fmt_type = 'y420'; - break; - default: - av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format: %d\n", avctx->pix_fmt); - goto failed; - } - status = ff_vda_create_decoder(vda_ctx, - avctx->extradata, avctx->extradata_size); - if (status != kVDADecoderNoErr) { - av_log(avctx, AV_LOG_ERROR, - "Failed to init VDA decoder: %d.\n", status); - goto failed; - } - - /* init H.264 decoder */ - set_context(avctx); - ret = ff_h264_decoder.init(avctx); - restore_context(avctx); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Failed to open H.264 decoder.\n"); - goto failed; - } - ctx->h264_initialized = 1; - - for (i = 0; i < MAX_SPS_COUNT; i++) { - const SPS *sps = ctx->h264ctx.ps.sps_list[i] ? (const SPS*)ctx->h264ctx.ps.sps_list[i]->data : NULL; - if (sps && (sps->bit_depth_luma != 8 || - sps->chroma_format_idc == 2 || - sps->chroma_format_idc == 3)) { - av_log(avctx, AV_LOG_ERROR, "Format is not supported.\n"); - goto failed; - } - } - - return 0; - -failed: - vdadec_close(avctx); - return -1; -} - -static void vdadec_flush(AVCodecContext *avctx) -{ - set_context(avctx); - ff_h264_decoder.flush(avctx); - restore_context(avctx); -} - -AVCodec ff_h264_vda_decoder = { - .name = "h264_vda", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .priv_data_size = sizeof(VDADecoderContext), - .init = vdadec_init, - .close = vdadec_close, - .decode = vdadec_decode, - .capabilities = AV_CODEC_CAP_DELAY, - .flush = vdadec_flush, - .long_name = NULL_IF_CONFIG_SMALL("H.264 (VDA acceleration)"), -}; diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index ec8b6d885c8e5..3bdc1f7d1f29b 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -21,13 +21,9 @@ */ #include "config.h" -#if CONFIG_VIDEOTOOLBOX -# include "videotoolbox.h" -# include "libavutil/hwcontext_videotoolbox.h" -#else -# include "vda.h" -#endif -#include "vda_vt_internal.h" +#include "videotoolbox.h" +#include "libavutil/hwcontext_videotoolbox.h" +#include "vt_internal.h" #include "libavutil/avutil.h" #include "libavutil/hwcontext.h" #include "bytestream.h" diff --git a/libavcodec/vda_vt_internal.h b/libavcodec/vt_internal.h similarity index 82% rename from libavcodec/vda_vt_internal.h rename to libavcodec/vt_internal.h index 326a60a695647..607dd7a6d0999 100644 --- a/libavcodec/vda_vt_internal.h +++ b/libavcodec/vt_internal.h @@ -16,17 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVCODEC_VDA_VT_INTERNAL_H -#define AVCODEC_VDA_VT_INTERNAL_H - -void ff_vda_output_callback(void *vda_hw_ctx, - CFDictionaryRef user_info, - OSStatus status, - uint32_t infoFlags, - CVImageBufferRef image_buffer); - -int ff_vda_default_init(AVCodecContext *avctx); -void ff_vda_default_free(AVCodecContext *avctx); +#ifndef AVCODEC_VT_INTERNAL_H +#define AVCODEC_VT_INTERNAL_H typedef struct VTContext { // The current bitstream buffer. @@ -60,4 +51,5 @@ int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx, uint32_t size); CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx); CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx); -#endif /* AVCODEC_VDA_VT_INTERNAL_H */ + +#endif /* AVCODEC_VT_INTERNAL_H */ diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 2cfab89c030fa..a428d63066fa0 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -1670,12 +1670,6 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_h = 1, .flags = AV_PIX_FMT_FLAG_HWACCEL, }, - [AV_PIX_FMT_VDA_VLD] = { - .name = "vda_vld", - .log2_chroma_w = 1, - .log2_chroma_h = 1, - .flags = AV_PIX_FMT_FLAG_HWACCEL, - }, [AV_PIX_FMT_YA8] = { .name = "ya8", .nb_components = 2, @@ -2029,10 +2023,6 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, }, - [AV_PIX_FMT_VDA] = { - .name = "vda", - .flags = AV_PIX_FMT_FLAG_HWACCEL, - }, [AV_PIX_FMT_QSV] = { .name = "qsv", .flags = AV_PIX_FMT_FLAG_HWACCEL, diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 24889c8e5288c..f54f5549b6eac 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -176,7 +176,6 @@ enum AVPixelFormat { AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian - AV_PIX_FMT_VDA_VLD, ///< hardware decoding through VDA AV_PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP AV_PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big-endian @@ -221,8 +220,6 @@ enum AVPixelFormat { AV_PIX_FMT_YVYU422, ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb - AV_PIX_FMT_VDA, ///< HW acceleration through VDA, data[3] contains a CVPixelBufferRef - AV_PIX_FMT_YA16BE, ///< 16 bits gray, 16 bits alpha (big-endian) AV_PIX_FMT_YA16LE, ///< 16 bits gray, 16 bits alpha (little-endian) diff --git a/libavutil/utils.c b/libavutil/utils.c index 2c170db2e10db..230081ea475fb 100644 --- a/libavutil/utils.c +++ b/libavutil/utils.c @@ -41,9 +41,6 @@ unsigned avutil_version(void) if (checks_done) return LIBAVUTIL_VERSION_INT; -#if FF_API_VDPAU - av_assert0(AV_PIX_FMT_VDA_VLD == 81); //check if the pix fmt enum has not had anything inserted or removed by mistake -#endif av_assert0(AV_SAMPLE_FMT_DBLP == 9); av_assert0(AVMEDIA_TYPE_ATTACHMENT == 4); av_assert0(AV_PICTURE_TYPE_BI == 7); From 4a9d32baca3af0d1831f9556a922c7ab5b426b10 Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Thu, 12 Oct 2017 10:59:23 -0700 Subject: [PATCH 0573/2557] mov: fix decode of fragments that overlap in time When keyframe intervals of dash segments are not perfectly aligned, fragments in the stream can overlap in time. The previous sorting by timestamp causes packets to be read out of decode order and results in decode errors. Insert new "trun" index entries into index_entries in the order that the trun are referenced by the sidx. Signed-off-by: Michael Niedermayer --- libavformat/isom.h | 26 +- libavformat/mov.c | 684 +++++++++++++++++++++++++++++++-------------- 2 files changed, 485 insertions(+), 225 deletions(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index b9380e9dcc3e9..395d20d25c6e7 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -93,7 +93,6 @@ typedef struct MOVFragment { unsigned duration; unsigned size; unsigned flags; - int64_t time; } MOVFragment; typedef struct MOVTrackExt { @@ -109,17 +108,28 @@ typedef struct MOVSbgp { unsigned int index; } MOVSbgp; +typedef struct MOVFragmentStreamInfo { + int id; + int64_t sidx_pts; + int64_t first_tfra_pts; + int64_t tfdt_dts; + int index_entry; +} MOVFragmentStreamInfo; + typedef struct MOVFragmentIndexItem { int64_t moof_offset; - int64_t time; int headers_read; + int current; + int nb_stream_info; + MOVFragmentStreamInfo * stream_info; } MOVFragmentIndexItem; typedef struct MOVFragmentIndex { - unsigned track_id; - unsigned item_count; - unsigned current_item; - MOVFragmentIndexItem *items; + int allocated_size; + int complete; + int current; + int nb_items; + MOVFragmentIndexItem * item; } MOVFragmentIndex; typedef struct MOVIndexRange { @@ -250,9 +260,7 @@ typedef struct MOVContext { int moov_retry; int use_mfra_for; int has_looked_for_mfra; - MOVFragmentIndex** fragment_index_data; - unsigned fragment_index_count; - int fragment_index_complete; + MOVFragmentIndex frag_index; int atom_depth; unsigned int aax_mode; ///< 'aax' file has been detected uint8_t file_key[20]; diff --git a/libavformat/mov.c b/libavformat/mov.c index 573f134d2d9fa..a5177e8f91f0e 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1168,6 +1168,211 @@ static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; /* now go for mdat */ } +static MOVFragmentStreamInfo * get_frag_stream_info( + MOVFragmentIndex *frag_index, + int index, + int id) +{ + int i; + MOVFragmentIndexItem * item; + + if (index < 0 || index >= frag_index->nb_items) + return NULL; + item = &frag_index->item[index]; + for (i = 0; i < item->nb_stream_info; i++) + if (item->stream_info[i].id == id) + return &item->stream_info[i]; + + // This shouldn't happen + return NULL; +} + +static void set_frag_stream(MOVFragmentIndex *frag_index, int id) +{ + int i; + MOVFragmentIndexItem * item; + + if (frag_index->current < 0 || + frag_index->current >= frag_index->nb_items) + return; + + item = &frag_index->item[frag_index->current]; + for (i = 0; i < item->nb_stream_info; i++) + if (item->stream_info[i].id == id) { + item->current = i; + return; + } + + // id not found. This shouldn't happen. + item->current = -1; +} + +static MOVFragmentStreamInfo * get_current_frag_stream_info( + MOVFragmentIndex *frag_index) +{ + MOVFragmentIndexItem * item = &frag_index->item[frag_index->current]; + if (item->current >= 0 && item->current < item->nb_stream_info) + return &item->stream_info[item->current]; + + // This shouldn't happen + return NULL; +} + +static int search_frag_moof_offset(MOVFragmentIndex *frag_index, int64_t offset) +{ + int a, b, m; + int64_t moof_offset; + + // Optimize for appending new entries + if (!frag_index->nb_items || + frag_index->item[frag_index->nb_items - 1].moof_offset < offset) + return frag_index->nb_items; + + a = -1; + b = frag_index->nb_items; + + while (b - a > 1) { + m = (a + b) >> 1; + moof_offset = frag_index->item[m].moof_offset; + if (moof_offset >= offset) + b = m; + if (moof_offset <= offset) + a = m; + } + return b; +} + +static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info) +{ + + if (frag_stream_info) { + if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE) + return frag_stream_info->sidx_pts; + if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE) + return frag_stream_info->first_tfra_pts; + if (frag_stream_info->tfdt_dts != AV_NOPTS_VALUE) + return frag_stream_info->tfdt_dts; + } + return AV_NOPTS_VALUE; +} + +static int64_t get_frag_time(MOVFragmentIndex *frag_index, + int index, int track_id) +{ + MOVFragmentStreamInfo * frag_stream_info; + int64_t timestamp; + int i; + + if (track_id >= 0) { + frag_stream_info = get_frag_stream_info(frag_index, index, track_id); + return frag_stream_info->sidx_pts; + } + + for (i = 0; i < frag_index->item[index].nb_stream_info; i++) { + frag_stream_info = &frag_index->item[index].stream_info[i]; + timestamp = get_stream_info_time(frag_stream_info); + if (timestamp != AV_NOPTS_VALUE) + return timestamp; + } + return AV_NOPTS_VALUE; +} + +static int search_frag_timestamp(MOVFragmentIndex *frag_index, + AVStream *st, int64_t timestamp) +{ + int a, b, m; + int64_t frag_time; + int id = -1; + + if (st) { + // If the stream is referenced by any sidx, limit the search + // to fragments that referenced this stream in the sidx + MOVStreamContext *sc = st->priv_data; + if (sc->has_sidx) + id = st->id; + } + + a = -1; + b = frag_index->nb_items; + + while (b - a > 1) { + m = (a + b) >> 1; + frag_time = get_frag_time(frag_index, m, id); + if (frag_time != AV_NOPTS_VALUE) { + if (frag_time >= timestamp) + b = m; + if (frag_time <= timestamp) + a = m; + } + } + return a; +} + +static int update_frag_index(MOVContext *c, int64_t offset) +{ + int index, i; + MOVFragmentIndexItem * item; + MOVFragmentStreamInfo * frag_stream_info; + + // If moof_offset already exists in frag_index, return index to it + index = search_frag_moof_offset(&c->frag_index, offset); + if (index < c->frag_index.nb_items && + c->frag_index.item[index].moof_offset == offset) + return index; + + // offset is not yet in frag index. + // Insert new item at index (sorted by moof offset) + item = av_fast_realloc(c->frag_index.item, + &c->frag_index.allocated_size, + (c->frag_index.nb_items + 1) * + sizeof(*c->frag_index.item)); + if(!item) + return -1; + c->frag_index.item = item; + + frag_stream_info = av_realloc_array(NULL, c->fc->nb_streams, + sizeof(*item->stream_info)); + if (!frag_stream_info) + return -1; + + for (i = 0; i < c->fc->nb_streams; i++) { + frag_stream_info[i].id = c->fc->streams[i]->id; + frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE; + frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE; + frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE; + frag_stream_info[i].index_entry = -1; + } + + if (index < c->frag_index.nb_items) + memmove(c->frag_index.item + index + 1, c->frag_index.item + index, + (c->frag_index.nb_items - index) * sizeof(*c->frag_index.item)); + + item = &c->frag_index.item[index]; + item->headers_read = 0; + item->current = 0; + item->nb_stream_info = c->fc->nb_streams; + item->moof_offset = offset; + item->stream_info = frag_stream_info; + c->frag_index.nb_items++; + + return index; +} + +static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index, + int id, int entries) +{ + int i; + MOVFragmentStreamInfo * frag_stream_info; + + if (index < 0) + return; + for (i = index; i < frag_index->nb_items; i++) { + frag_stream_info = get_frag_stream_info(frag_index, i, id); + if (frag_stream_info && frag_stream_info->index_entry >= 0) + frag_stream_info->index_entry += entries; + } +} + static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom) { if (!c->has_looked_for_mfra && c->use_mfra_for > 0) { @@ -1187,6 +1392,7 @@ static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom) } c->fragment.moof_offset = c->fragment.implicit_offset = avio_tell(pb) - 8; av_log(c->fc, AV_LOG_TRACE, "moof offset %"PRIx64"\n", c->fragment.moof_offset); + c->frag_index.current = update_frag_index(c, c->fragment.moof_offset); return mov_read_default(c, pb, atom); } @@ -4118,8 +4324,7 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) { MOVFragment *frag = &c->fragment; MOVTrackExt *trex = NULL; - MOVFragmentIndex* index = NULL; - int flags, track_id, i, found = 0; + int flags, track_id, i; avio_r8(pb); /* version */ flags = avio_rb24(pb); @@ -4128,6 +4333,7 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (!track_id) return AVERROR_INVALIDDATA; frag->track_id = track_id; + set_frag_stream(&c->frag_index, track_id); for (i = 0; i < c->trex_count; i++) if (c->trex_data[i].track_id == frag->track_id) { trex = &c->trex_data[i]; @@ -4149,35 +4355,8 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_rb32(pb) : trex->size; frag->flags = flags & MOV_TFHD_DEFAULT_FLAGS ? avio_rb32(pb) : trex->flags; - frag->time = AV_NOPTS_VALUE; - for (i = 0; i < c->fragment_index_count; i++) { - int j; - MOVFragmentIndex* candidate = c->fragment_index_data[i]; - if (candidate->track_id == frag->track_id) { - av_log(c->fc, AV_LOG_DEBUG, - "found fragment index for track %u\n", frag->track_id); - index = candidate; - for (j = index->current_item; j < index->item_count; j++) { - if (frag->implicit_offset == index->items[j].moof_offset) { - av_log(c->fc, AV_LOG_DEBUG, "found fragment index entry " - "for track %u and moof_offset %"PRId64"\n", - frag->track_id, index->items[j].moof_offset); - frag->time = index->items[j].time; - index->current_item = j + 1; - found = 1; - break; - } - } - if (found) - break; - } - } - if (index && !found) { - av_log(c->fc, AV_LOG_DEBUG, "track %u has a fragment index but " - "it doesn't have an (in-order) entry for moof_offset " - "%"PRId64"\n", frag->track_id, frag->implicit_offset); - } av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags); + return 0; } @@ -4232,6 +4411,8 @@ static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom) AVStream *st = NULL; MOVStreamContext *sc; int version, i; + MOVFragmentStreamInfo * frag_stream_info; + int64_t base_media_decode_time; for (i = 0; i < c->fc->nb_streams; i++) { if (c->fc->streams[i]->id == frag->track_id) { @@ -4249,10 +4430,16 @@ static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom) version = avio_r8(pb); avio_rb24(pb); /* flags */ if (version) { - sc->track_end = avio_rb64(pb); + base_media_decode_time = avio_rb64(pb); } else { - sc->track_end = avio_rb32(pb); + base_media_decode_time = avio_rb32(pb); } + + frag_stream_info = get_current_frag_stream_info(&c->frag_index); + if (frag_stream_info) + frag_stream_info->tfdt_dts = base_media_decode_time; + sc->track_end = base_media_decode_time; + return 0; } @@ -4263,10 +4450,15 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) MOVStreamContext *sc; MOVStts *ctts_data; uint64_t offset; - int64_t dts; + int64_t dts, pts = AV_NOPTS_VALUE; int data_offset = 0; unsigned entries, first_sample_flags = frag->flags; int flags, distance, i; + int64_t prev_dts = AV_NOPTS_VALUE; + int next_frag_index = -1, index_entry_pos; + size_t requested_size; + AVIndexEntry *new_entries; + MOVFragmentStreamInfo * frag_stream_info; for (i = 0; i < c->fc->nb_streams; i++) { if (c->fc->streams[i]->id == frag->track_id) { @@ -4281,6 +4473,23 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc = st->priv_data; if (sc->pseudo_stream_id+1 != frag->stsd_id && sc->pseudo_stream_id != -1) return 0; + + // Find the next frag_index index that has a valid index_entry for + // the current track_id. + // + // A valid index_entry means the trun for the fragment was read + // and it's samples are in index_entries at the given position. + // New index entries will be inserted before the index_entry found. + index_entry_pos = st->nb_index_entries; + for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) { + frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id); + if (frag_stream_info && frag_stream_info->index_entry >= 0) { + next_frag_index = i; + index_entry_pos = frag_stream_info->index_entry; + break; + } + } + avio_r8(pb); /* version */ flags = avio_rb24(pb); entries = avio_rb32(pb); @@ -4290,18 +4499,99 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR_INVALIDDATA; if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb); if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb); - dts = sc->track_end - sc->time_offset; - offset = frag->base_data_offset + data_offset; + + frag_stream_info = get_current_frag_stream_info(&c->frag_index); + if (frag_stream_info) + { + if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE && + c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) { + pts = frag_stream_info->first_tfra_pts; + av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64 + ", using it for pts\n", pts); + } else if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE) { + // FIXME: sidx earliest_presentation_time is *PTS*, s.b. + // pts = frag_stream_info->sidx_pts; + dts = frag_stream_info->sidx_pts - sc->time_offset; + av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64 + ", using it for pts\n", pts); + } else if (frag_stream_info->tfdt_dts != AV_NOPTS_VALUE) { + dts = frag_stream_info->tfdt_dts - sc->time_offset; + av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64 + ", using it for dts\n", dts); + } else { + dts = sc->track_end - sc->time_offset; + av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64 + ", using it for dts\n", dts); + } + } else { + dts = sc->track_end - sc->time_offset; + av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64 + ", using it for dts\n", dts); + } + offset = frag->base_data_offset + data_offset; distance = 0; av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags); + + // realloc space for new index entries + if((unsigned)st->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) { + entries = UINT_MAX / sizeof(AVIndexEntry) - st->nb_index_entries; + av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n"); + } + if (entries <= 0) + return -1; + + requested_size = (st->nb_index_entries + entries) * sizeof(AVIndexEntry); + new_entries = av_fast_realloc(st->index_entries, + &st->index_entries_allocated_size, + requested_size); + if(!new_entries) + return AVERROR(ENOMEM); + st->index_entries= new_entries; + + requested_size = (st->nb_index_entries + entries) * sizeof(*sc->ctts_data); + ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, + requested_size); + if (!ctts_data) + return AVERROR(ENOMEM); + sc->ctts_data = ctts_data; + + // In case there were samples without ctts entries, ensure they get + // zero valued entries. This ensures clips which mix boxes with and + // without ctts entries don't pickup uninitialized data. + memset(sc->ctts_data + sc->ctts_count, 0, + (st->nb_index_entries - sc->ctts_count) * sizeof(*sc->ctts_data)); + + if (index_entry_pos < st->nb_index_entries) { + // Make hole in index_entries and ctts_data for new samples + memmove(st->index_entries + index_entry_pos + entries, + st->index_entries + index_entry_pos, + sizeof(*st->index_entries) * + (st->nb_index_entries - index_entry_pos)); + memmove(sc->ctts_data + index_entry_pos + entries, + sc->ctts_data + index_entry_pos, + sizeof(*sc->ctts_data) * (sc->ctts_count - index_entry_pos)); + if (index_entry_pos < sc->current_sample) { + sc->current_sample += entries; + } + } + + st->nb_index_entries += entries; + sc->ctts_count = st->nb_index_entries; + + // Record the index_entry position in frag_index of this fragment + if (frag_stream_info) + frag_stream_info->index_entry = index_entry_pos; + + if (index_entry_pos > 0) + prev_dts = st->index_entries[index_entry_pos-1].timestamp; + for (i = 0; i < entries && !pb->eof_reached; i++) { unsigned sample_size = frag->size; int sample_flags = i ? frag->flags : first_sample_flags; unsigned sample_duration = frag->duration; unsigned ctts_duration = 0; int keyframe = 0; - int ctts_index = 0; - int old_nb_index_entries = st->nb_index_entries; + int index_entry_flags = 0; if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration = avio_rb32(pb); if (flags & MOV_TRUN_SAMPLE_SIZE) sample_size = avio_rb32(pb); @@ -4309,27 +4599,22 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb); mov_update_dts_shift(sc, ctts_duration); - if (frag->time != AV_NOPTS_VALUE) { - if (c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) { - int64_t pts = frag->time; - av_log(c->fc, AV_LOG_DEBUG, "found frag time %"PRId64 - " sc->dts_shift %d ctts.duration %d" - " sc->time_offset %"PRId64" flags & MOV_TRUN_SAMPLE_CTS %d\n", pts, - sc->dts_shift, ctts_duration, - sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS); - dts = pts - sc->dts_shift; - if (flags & MOV_TRUN_SAMPLE_CTS) { - dts -= ctts_duration; - } else { - dts -= sc->time_offset; - } - av_log(c->fc, AV_LOG_DEBUG, "calculated into dts %"PRId64"\n", dts); + if (pts != AV_NOPTS_VALUE) { + dts = pts - sc->dts_shift; + if (flags & MOV_TRUN_SAMPLE_CTS) { + dts -= ctts_duration; } else { - dts = frag->time - sc->time_offset; - av_log(c->fc, AV_LOG_DEBUG, "found frag time %"PRId64 - ", using it for dts\n", dts); + dts -= sc->time_offset; } - frag->time = AV_NOPTS_VALUE; + av_log(c->fc, AV_LOG_DEBUG, + "pts %"PRId64" calculated dts %"PRId64 + " sc->dts_shift %d ctts.duration %d" + " sc->time_offset %"PRId64 + " flags & MOV_TRUN_SAMPLE_CTS %d\n", + pts, dts, + sc->dts_shift, ctts_duration, + sc->time_offset, flags & MOV_TRUN_SAMPLE_CTS); + pts = AV_NOPTS_VALUE; } if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) @@ -4338,47 +4623,28 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) keyframe = !(sample_flags & (MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC | MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES)); - if (keyframe) + if (keyframe) { distance = 0; - ctts_index = av_add_index_entry(st, offset, dts, sample_size, distance, - keyframe ? AVINDEX_KEYFRAME : 0); - if (ctts_index >= 0 && old_nb_index_entries < st->nb_index_entries) { - unsigned int size_needed = st->nb_index_entries * sizeof(*sc->ctts_data); - unsigned int request_size = size_needed > sc->ctts_allocated_size ? - FFMAX(size_needed, 2 * sc->ctts_allocated_size) : size_needed; - unsigned int old_ctts_size = sc->ctts_allocated_size; - ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, request_size); - if (!ctts_data) { - av_freep(&sc->ctts_data); - return AVERROR(ENOMEM); - } - sc->ctts_data = ctts_data; - - // In case there were samples without ctts entries, ensure they get - // zero valued entries. This ensures clips which mix boxes with and - // without ctts entries don't pickup uninitialized data. - memset((uint8_t*)(sc->ctts_data) + old_ctts_size, 0, sc->ctts_allocated_size - old_ctts_size); - - if (ctts_index != old_nb_index_entries) { - memmove(sc->ctts_data + ctts_index + 1, sc->ctts_data + ctts_index, - sizeof(*sc->ctts_data) * (sc->ctts_count - ctts_index)); - if (ctts_index <= sc->current_sample) { - // if we inserted a new item before the current sample, move the - // counter ahead so it is still pointing to the same sample. - sc->current_sample++; - } - } - - sc->ctts_data[ctts_index].count = 1; - sc->ctts_data[ctts_index].duration = ctts_duration; - sc->ctts_count++; - } else { - av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n"); + index_entry_flags |= AVINDEX_KEYFRAME; } + // Fragments can overlap in time. Discard overlapping frames after + // decoding. + if (prev_dts >= dts) + index_entry_flags |= AVINDEX_DISCARD_FRAME; + + st->index_entries[index_entry_pos].pos = offset; + st->index_entries[index_entry_pos].timestamp = dts; + st->index_entries[index_entry_pos].size= sample_size; + st->index_entries[index_entry_pos].min_distance= distance; + st->index_entries[index_entry_pos].flags = index_entry_flags; + + sc->ctts_data[index_entry_pos].count = 1; + sc->ctts_data[index_entry_pos].duration = ctts_duration; + index_entry_pos++; av_log(c->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", " - "size %u, distance %d, keyframe %d\n", st->index, ctts_index, - offset, dts, sample_size, distance, keyframe); + "size %u, distance %d, keyframe %d\n", st->index, + index_entry_pos, offset, dts, sample_size, distance, keyframe); distance++; dts += sample_duration; offset += sample_size; @@ -4386,6 +4652,44 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->duration_for_fps += sample_duration; sc->nb_frames_for_fps ++; } + if (i < entries) { + // EOF found before reading all entries. Fix the hole this would + // leave in index_entries and ctts_data + int gap = entries - i; + memmove(st->index_entries + index_entry_pos, + st->index_entries + index_entry_pos + gap, + sizeof(*st->index_entries) * + (st->nb_index_entries - (index_entry_pos + gap))); + memmove(sc->ctts_data + index_entry_pos, + sc->ctts_data + index_entry_pos + gap, + sizeof(*sc->ctts_data) * + (sc->ctts_count - (index_entry_pos + gap))); + + st->nb_index_entries -= gap; + sc->ctts_count -= gap; + if (index_entry_pos < sc->current_sample) { + sc->current_sample -= gap; + } + entries = i; + } + + // The end of this new fragment may overlap in time with the start + // of the next fragment in index_entries. Mark the samples in the next + // fragment that overlap with AVINDEX_DISCARD_FRAME + prev_dts = AV_NOPTS_VALUE; + if (index_entry_pos > 0) + prev_dts = st->index_entries[index_entry_pos-1].timestamp; + for (i = index_entry_pos; i < st->nb_index_entries; i++) { + if (prev_dts < st->index_entries[i].timestamp) + break; + st->index_entries[i].flags |= AVINDEX_DISCARD_FRAME; + } + + // If a hole was created to insert the new index_entries into, + // the index_entry recorded for all subsequent moof must + // be incremented by the number of entries inserted. + fix_frag_index_entries(&c->frag_index, next_frag_index, + frag->track_id, entries); if (pb->eof_reached) return AVERROR_EOF; @@ -4401,14 +4705,12 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom) { - int64_t offset = avio_tell(pb) + atom.size, pts; + int64_t offset = avio_tell(pb) + atom.size, pts, timestamp; uint8_t version; - unsigned i, track_id; + unsigned i, j, track_id, item_count; AVStream *st = NULL; AVStream *ref_st = NULL; MOVStreamContext *sc, *ref_sc = NULL; - MOVFragmentIndex *index = NULL; - MOVFragmentIndex **tmp; AVRational timescale; version = avio_r8(pb); @@ -4450,57 +4752,46 @@ static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_rb16(pb); // reserved - index = av_mallocz(sizeof(MOVFragmentIndex)); - if (!index) - return AVERROR(ENOMEM); - - index->track_id = track_id; - - index->item_count = avio_rb16(pb); - index->items = av_mallocz_array(index->item_count, sizeof(MOVFragmentIndexItem)); - - if (!index->items) { - av_freep(&index); - return AVERROR(ENOMEM); - } + item_count = avio_rb16(pb); - for (i = 0; i < index->item_count; i++) { + for (i = 0; i < item_count; i++) { + int index; + MOVFragmentStreamInfo * frag_stream_info; uint32_t size = avio_rb32(pb); uint32_t duration = avio_rb32(pb); if (size & 0x80000000) { avpriv_request_sample(c->fc, "sidx reference_type 1"); - av_freep(&index->items); - av_freep(&index); return AVERROR_PATCHWELCOME; } avio_rb32(pb); // sap_flags - index->items[i].moof_offset = offset; - index->items[i].time = av_rescale_q(pts, st->time_base, timescale); + timestamp = av_rescale_q(pts, st->time_base, timescale); + + index = update_frag_index(c, offset); + frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id); + if (frag_stream_info) + frag_stream_info->sidx_pts = timestamp; + offset += size; pts += duration; } st->duration = sc->track_end = pts; - tmp = av_realloc_array(c->fragment_index_data, - c->fragment_index_count + 1, - sizeof(MOVFragmentIndex*)); - if (!tmp) { - av_freep(&index->items); - av_freep(&index); - return AVERROR(ENOMEM); - } - - c->fragment_index_data = tmp; - c->fragment_index_data[c->fragment_index_count++] = index; sc->has_sidx = 1; if (offset == avio_size(pb)) { - for (i = 0; i < c->fc->nb_streams; i++) { - if (c->fc->streams[i]->id == c->fragment_index_data[0]->track_id) { - ref_st = c->fc->streams[i]; - ref_sc = ref_st->priv_data; - break; + // Find first entry in fragment index that came from an sidx. + // This will pretty much always be the first entry. + for (i = 0; i < c->frag_index.nb_items; i++) { + MOVFragmentIndexItem * item = &c->frag_index.item[i]; + for (j = 0; ref_st == NULL && j < item->nb_stream_info; j++) { + MOVFragmentStreamInfo * si; + si = &item->stream_info[j]; + if (si->sidx_pts != AV_NOPTS_VALUE) { + ref_st = c->fc->streams[i]; + ref_sc = ref_st->priv_data; + break; + } } } for (i = 0; i < c->fc->nb_streams; i++) { @@ -4511,7 +4802,7 @@ static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom) } } - c->fragment_index_complete = 1; + c->frag_index.complete = 1; } return 0; @@ -5680,9 +5971,9 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) return err; } if (c->found_moov && c->found_mdat && - ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->fragment_index_complete) || + ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) || start_pos + a.size == avio_size(pb))) { - if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->fragment_index_complete) + if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) c->next_root_atom = start_pos + a.size; c->atom_depth --; return 0; @@ -6027,12 +6318,10 @@ static int mov_read_close(AVFormatContext *s) av_freep(&mov->trex_data); av_freep(&mov->bitrates); - for (i = 0; i < mov->fragment_index_count; i++) { - MOVFragmentIndex* index = mov->fragment_index_data[i]; - av_freep(&index->items); - av_freep(&mov->fragment_index_data[i]); + for (i = 0; i < mov->frag_index.nb_items; i++) { + av_freep(&mov->frag_index.item[i].stream_info); } - av_freep(&mov->fragment_index_data); + av_freep(&mov->frag_index.item); av_freep(&mov->aes_decrypt); av_freep(&mov->chapter_tracks); @@ -6076,48 +6365,27 @@ static void export_orphan_timecode(AVFormatContext *s) static int read_tfra(MOVContext *mov, AVIOContext *f) { - MOVFragmentIndex* index = NULL; int version, fieldlength, i, j; int64_t pos = avio_tell(f); uint32_t size = avio_rb32(f); - void *tmp; + unsigned track_id, item_count; if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) { return 1; } av_log(mov->fc, AV_LOG_VERBOSE, "found tfra\n"); - index = av_mallocz(sizeof(MOVFragmentIndex)); - if (!index) { - return AVERROR(ENOMEM); - } - - tmp = av_realloc_array(mov->fragment_index_data, - mov->fragment_index_count + 1, - sizeof(MOVFragmentIndex*)); - if (!tmp) { - av_freep(&index); - return AVERROR(ENOMEM); - } - mov->fragment_index_data = tmp; - mov->fragment_index_data[mov->fragment_index_count++] = index; version = avio_r8(f); avio_rb24(f); - index->track_id = avio_rb32(f); + track_id = avio_rb32(f); fieldlength = avio_rb32(f); - index->item_count = avio_rb32(f); - index->items = av_mallocz_array( - index->item_count, sizeof(MOVFragmentIndexItem)); - if (!index->items) { - index->item_count = 0; - return AVERROR(ENOMEM); - } - for (i = 0; i < index->item_count; i++) { + item_count = avio_rb32(f); + for (i = 0; i < item_count; i++) { int64_t time, offset; + int index; + MOVFragmentStreamInfo * frag_stream_info; if (avio_feof(f)) { - index->item_count = 0; - av_freep(&index->items); return AVERROR_INVALIDDATA; } @@ -6128,8 +6396,16 @@ static int read_tfra(MOVContext *mov, AVIOContext *f) time = avio_rb32(f); offset = avio_rb32(f); } - index->items[i].time = time; - index->items[i].moof_offset = offset; + + // The first sample of each stream in a fragment is always a random + // access sample. So it's entry in the tfra can be used as the + // initial PTS of the fragment. + index = update_frag_index(mov, offset); + frag_stream_info = get_frag_stream_info(&mov->frag_index, index, track_id); + if (frag_stream_info && + frag_stream_info->first_tfra_pts == AV_NOPTS_VALUE) + frag_stream_info->first_tfra_pts = time; + for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++) avio_r8(f); for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++) @@ -6390,12 +6666,9 @@ static int mov_read_header(AVFormatContext *s) } ff_configure_buffers_for_index(s, AV_TIME_BASE); - for (i = 0; i < mov->fragment_index_count; i++) { - MOVFragmentIndex *idx = mov->fragment_index_data[i]; - for (j = 0; j < idx->item_count; j++) - if (idx->items[j].moof_offset <= mov->fragment.moof_offset) - idx->items[j].headers_read = 1; - } + for (i = 0; i < mov->frag_index.nb_items; i++) + if (mov->frag_index.item[i].moof_offset <= mov->fragment.moof_offset) + mov->frag_index.item[i].headers_read = 1; return 0; } @@ -6433,42 +6706,28 @@ static int should_retry(AVIOContext *pb, int error_code) { return 1; } -static int mov_switch_root(AVFormatContext *s, int64_t target) +static int mov_switch_root(AVFormatContext *s, int64_t target, int index) { MOVContext *mov = s->priv_data; - int i, j; - int already_read = 0; + if (index >= 0 && index < mov->frag_index.nb_items) + target = mov->frag_index.item[index].moof_offset; if (avio_seek(s->pb, target, SEEK_SET) != target) { av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target); return AVERROR_INVALIDDATA; } mov->next_root_atom = 0; - - for (i = 0; i < mov->fragment_index_count; i++) { - MOVFragmentIndex *index = mov->fragment_index_data[i]; - int found = 0; - for (j = 0; j < index->item_count; j++) { - MOVFragmentIndexItem *item = &index->items[j]; - if (found) { - mov->next_root_atom = item->moof_offset; - break; // Advance to next index in outer loop - } else if (item->moof_offset == target) { - index->current_item = FFMIN(j, index->current_item); - if (item->headers_read) - already_read = 1; - item->headers_read = 1; - found = 1; - } - } - if (!found) - index->current_item = 0; + if (index < 0 || index >= mov->frag_index.nb_items) + index = search_frag_moof_offset(&mov->frag_index, target); + if (index < mov->frag_index.nb_items) { + if (index + 1 < mov->frag_index.nb_items) + mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset; + if (mov->frag_index.item[index].headers_read) + return 0; + mov->frag_index.item[index].headers_read = 1; } - if (already_read) - return 0; - mov->found_mdat = 0; if (mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX }) < 0 || @@ -6516,7 +6775,7 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) { if (!mov->next_root_atom) return AVERROR_EOF; - if ((ret = mov_switch_root(s, mov->next_root_atom)) < 0) + if ((ret = mov_switch_root(s, mov->next_root_atom, -1)) < 0) return ret; goto retry; } @@ -6640,25 +6899,18 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp) { MOVContext *mov = s->priv_data; - MOVStreamContext *sc = st->priv_data; - int i, j; + int index; - if (!mov->fragment_index_complete) + if (!mov->frag_index.complete) return 0; - for (i = 0; i < mov->fragment_index_count; i++) { - if (mov->fragment_index_data[i]->track_id == st->id || !sc->has_sidx) { - MOVFragmentIndex *index = mov->fragment_index_data[i]; - for (j = index->item_count - 1; j >= 0; j--) { - if (index->items[j].time <= timestamp) { - if (index->items[j].headers_read) - return 0; - - return mov_switch_root(s, index->items[j].moof_offset); - } - } - } - } + index = search_frag_timestamp(&mov->frag_index, st, timestamp); + if (index < 0) + index = 0; + if (!mov->frag_index.item[index].headers_read) + return mov_switch_root(s, -1, index); + if (index + 1 < mov->frag_index.nb_items) + mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset; return 0; } From 2c9fa4162b346a394188a2e5a3442076155f2e34 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 22 Oct 2017 01:41:57 +0200 Subject: [PATCH 0574/2557] ffmpeg: add -bitexact flag to simplify enabling bitexact mode in (de)muxer and (de/en)coder Signed-off-by: Michael Niedermayer --- doc/ffmpeg.texi | 2 ++ fftools/ffmpeg.h | 1 + fftools/ffmpeg_opt.c | 16 ++++++++++++++++ 3 files changed, 19 insertions(+) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index cdb3bc68aeff3..7db80ebf6a857 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1250,6 +1250,8 @@ or as a floating point number (e.g. 0.04166, 2.0833e-5) Default value is 0. +@item -bitexact (@emph{input/output}) +Enable bitexact mode for (de)muxer and (de/en)coder @item -shortest (@emph{output}) Finish encoding when the shortest input stream ends. @item -dts_delta_threshold diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 0db481d74725b..50fc8d57674f7 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -160,6 +160,7 @@ typedef struct OptionsContext { float mux_preload; float mux_max_delay; int shortest; + int bitexact; int video_disable; int audio_disable; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 2fa5d6d2861f4..d441d29390b2f 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -782,6 +782,9 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) exit_program(1); } + if (o->bitexact) + ist->dec_ctx->flags |= AV_CODEC_FLAG_BITEXACT; + switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: if(!ist->dec) @@ -1045,6 +1048,8 @@ static int open_input_file(OptionsContext *o, const char *filename) av_format_set_data_codec(ic, find_codec_or_die(data_codec_name, AVMEDIA_TYPE_DATA, 0)); ic->flags |= AVFMT_FLAG_NONBLOCK; + if (o->bitexact) + ic->flags |= AVFMT_FLAG_BITEXACT; ic->interrupt_callback = int_cb; if (!av_dict_get(o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) { @@ -1366,6 +1371,10 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); } + + if (o->bitexact) + ost->enc_ctx->flags |= AV_CODEC_FLAG_BITEXACT; + MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st); if (time_base) { AVRational q; @@ -2144,6 +2153,10 @@ static int open_output_file(OptionsContext *o, const char *filename) const AVOption *o = av_opt_find(oc, "fflags", NULL, 0, 0); av_opt_eval_flags(oc, o, e->value, &format_flags); } + if (o->bitexact) { + format_flags |= AVFMT_FLAG_BITEXACT; + oc->flags |= AVFMT_FLAG_BITEXACT; + } /* create streams for all unlabeled output pads */ for (i = 0; i < nb_filtergraphs; i++) { @@ -3467,6 +3480,9 @@ const OptionDef options[] = { { "shortest", OPT_BOOL | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(shortest) }, "finish encoding within shortest input" }, + { "bitexact", OPT_BOOL | OPT_EXPERT | OPT_OFFSET | + OPT_OUTPUT | OPT_INPUT, { .off = OFFSET(bitexact) }, + "bitexact mode" }, { "apad", OPT_STRING | HAS_ARG | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(apad) }, "audio pad", "" }, From f1fd12ef858cf7efe843aa3063894a11b2d1e7d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 23 Oct 2017 10:48:02 +0300 Subject: [PATCH 0575/2557] lavu/arm: Check for have_vfp_vm instead of !have_vfpv3 for float_dsp_vfp This was missed in e754c8e8 / e2710e790c0 since those functions weren't exercised by checkasm. Fixes ticket #6766. --- libavutil/arm/float_dsp_init_vfp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavutil/arm/float_dsp_init_vfp.c b/libavutil/arm/float_dsp_init_vfp.c index e15abf3f54c9a..05873e7e37546 100644 --- a/libavutil/arm/float_dsp_init_vfp.c +++ b/libavutil/arm/float_dsp_init_vfp.c @@ -36,11 +36,11 @@ void ff_butterflies_float_vfp(float *av_restrict v1, float *av_restrict v2, int av_cold void ff_float_dsp_init_vfp(AVFloatDSPContext *fdsp, int cpu_flags) { - if (!have_vfpv3(cpu_flags)) { + if (have_vfp_vm(cpu_flags)) { fdsp->vector_fmul = ff_vector_fmul_vfp; fdsp->vector_fmul_window = ff_vector_fmul_window_vfp; } fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_vfp; - if (!have_vfpv3(cpu_flags)) + if (have_vfp_vm(cpu_flags)) fdsp->butterflies_float = ff_butterflies_float_vfp; } From 8c2b82912334a3b41cfd4a9c8bf195e7c67cfb2a Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 23 Oct 2017 10:58:00 -0300 Subject: [PATCH 0576/2557] avutil/frame: remove unneccessary metadata pointer getter Signed-off-by: James Almer --- libavutil/frame.c | 2 -- libavutil/frame.h | 1 - 2 files changed, 3 deletions(-) diff --git a/libavutil/frame.c b/libavutil/frame.c index d5fd2932e34a5..09dd98a6b52be 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -48,8 +48,6 @@ MAKE_ACCESSORS(AVFrame, frame, enum AVColorRange, color_range) (frame)->channels == \ av_get_channel_layout_nb_channels((frame)->channel_layout)) -AVDictionary **avpriv_frame_get_metadatap(AVFrame *frame) {return &frame->metadata;}; - #if FF_API_FRAME_QP int av_frame_set_qp_table(AVFrame *f, AVBufferRef *buf, int stride, int qp_type) { diff --git a/libavutil/frame.h b/libavutil/frame.h index abe4f4fd178d5..fef558ea2f0a7 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -587,7 +587,6 @@ int av_frame_get_decode_error_flags (const AVFrame *frame); void av_frame_set_decode_error_flags (AVFrame *frame, int val); int av_frame_get_pkt_size(const AVFrame *frame); void av_frame_set_pkt_size(AVFrame *frame, int val); -AVDictionary **avpriv_frame_get_metadatap(AVFrame *frame); #if FF_API_FRAME_QP int8_t *av_frame_get_qp_table(AVFrame *f, int *stride, int *type); int av_frame_set_qp_table(AVFrame *f, AVBufferRef *buf, int stride, int type); From 7bbe33b0526723f0a20c27e3b8d03b186b27fdf6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 23 Oct 2017 14:34:15 -0300 Subject: [PATCH 0577/2557] avcodec/libx264: add me_method alias to set X264Context->motion_est Replaces the now dropped global option. Addresses ticket #6771. Reviewed-by: Paul B Mahol Signed-off-by: James Almer --- libavcodec/libx264.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index b11ede6198863..b5e04d674d4cc 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -958,6 +958,7 @@ static const AVOption options[] = { { "vbr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_NAL_HRD_VBR}, INT_MIN, INT_MAX, VE, "nal-hrd" }, { "cbr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_NAL_HRD_CBR}, INT_MIN, INT_MAX, VE, "nal-hrd" }, { "avcintra-class","AVC-Intra class 50/100/200", OFFSET(avcintra_class),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 200 , VE}, + { "me_method", "Set motion estimation method", OFFSET(motion_est), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, X264_ME_TESA, VE, "motion-est"}, { "motion-est", "Set motion estimation method", OFFSET(motion_est), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, X264_ME_TESA, VE, "motion-est"}, { "dia", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = X264_ME_DIA }, INT_MIN, INT_MAX, VE, "motion-est" }, { "hex", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = X264_ME_HEX }, INT_MIN, INT_MAX, VE, "motion-est" }, From eb5f84633991eeed2c4a547ae04b593ad6adb03e Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 23 Oct 2017 16:52:24 -0300 Subject: [PATCH 0578/2557] avcodec: drop deprecated vismv option Deprecated in 08/2014. Signed-off-by: James Almer --- doc/codecs.texi | 15 --- libavcodec/mpegvideo.c | 218 ------------------------------------- libavcodec/options_table.h | 6 - libavcodec/utils.c | 6 - libavcodec/version.h | 4 - 5 files changed, 249 deletions(-) diff --git a/doc/codecs.texi b/doc/codecs.texi index 6ab02c35dee27..6f0aad21693a8 100644 --- a/doc/codecs.texi +++ b/doc/codecs.texi @@ -506,21 +506,6 @@ threading operations skip motion compensation @end table -@item vismv @var{integer} (@emph{decoding,video}) -Visualize motion vectors (MVs). - -This option is deprecated, see the codecview filter instead. - -Possible values: -@table @samp -@item pf -forward predicted MVs of P-frames -@item bf -forward predicted MVs of B-frames -@item bb -backward predicted MVs of B-frames -@end table - @item cmp @var{integer} (@emph{encoding,video}) Set full pel me compare function. diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 75e67429957b9..2f5793b9a4658 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -1418,134 +1418,6 @@ void ff_mpv_frame_end(MpegEncContext *s) ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); } - -#if FF_API_VISMV -static int clip_line(int *sx, int *sy, int *ex, int *ey, int maxx) -{ - if(*sx > *ex) - return clip_line(ex, ey, sx, sy, maxx); - - if (*sx < 0) { - if (*ex < 0) - return 1; - *sy = *ey + (*sy - *ey) * (int64_t)*ex / (*ex - *sx); - *sx = 0; - } - - if (*ex > maxx) { - if (*sx > maxx) - return 1; - *ey = *sy + (*ey - *sy) * (int64_t)(maxx - *sx) / (*ex - *sx); - *ex = maxx; - } - return 0; -} - - -/** - * Draw a line from (ex, ey) -> (sx, sy). - * @param w width of the image - * @param h height of the image - * @param stride stride/linesize of the image - * @param color color of the arrow - */ -static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, - int w, int h, int stride, int color) -{ - int x, y, fr, f; - - if (clip_line(&sx, &sy, &ex, &ey, w - 1)) - return; - if (clip_line(&sy, &sx, &ey, &ex, h - 1)) - return; - - sx = av_clip(sx, 0, w - 1); - sy = av_clip(sy, 0, h - 1); - ex = av_clip(ex, 0, w - 1); - ey = av_clip(ey, 0, h - 1); - - buf[sy * stride + sx] += color; - - if (FFABS(ex - sx) > FFABS(ey - sy)) { - if (sx > ex) { - FFSWAP(int, sx, ex); - FFSWAP(int, sy, ey); - } - buf += sx + sy * stride; - ex -= sx; - f = ((ey - sy) << 16) / ex; - for (x = 0; x <= ex; x++) { - y = (x * f) >> 16; - fr = (x * f) & 0xFFFF; - buf[y * stride + x] += (color * (0x10000 - fr)) >> 16; - if(fr) buf[(y + 1) * stride + x] += (color * fr ) >> 16; - } - } else { - if (sy > ey) { - FFSWAP(int, sx, ex); - FFSWAP(int, sy, ey); - } - buf += sx + sy * stride; - ey -= sy; - if (ey) - f = ((ex - sx) << 16) / ey; - else - f = 0; - for(y= 0; y <= ey; y++){ - x = (y*f) >> 16; - fr = (y*f) & 0xFFFF; - buf[y * stride + x] += (color * (0x10000 - fr)) >> 16; - if(fr) buf[y * stride + x + 1] += (color * fr ) >> 16; - } - } -} - -/** - * Draw an arrow from (ex, ey) -> (sx, sy). - * @param w width of the image - * @param h height of the image - * @param stride stride/linesize of the image - * @param color color of the arrow - */ -static void draw_arrow(uint8_t *buf, int sx, int sy, int ex, - int ey, int w, int h, int stride, int color, int tail, int direction) -{ - int dx,dy; - - if (direction) { - FFSWAP(int, sx, ex); - FFSWAP(int, sy, ey); - } - - sx = av_clip(sx, -100, w + 100); - sy = av_clip(sy, -100, h + 100); - ex = av_clip(ex, -100, w + 100); - ey = av_clip(ey, -100, h + 100); - - dx = ex - sx; - dy = ey - sy; - - if (dx * dx + dy * dy > 3 * 3) { - int rx = dx + dy; - int ry = -dx + dy; - int length = ff_sqrt((rx * rx + ry * ry) << 8); - - // FIXME subpixel accuracy - rx = ROUNDED_DIV(rx * 3 << 4, length); - ry = ROUNDED_DIV(ry * 3 << 4, length); - - if (tail) { - rx = -rx; - ry = -ry; - } - - draw_line(buf, sx, sy, sx + rx, sy + ry, w, h, stride, color); - draw_line(buf, sx, sy, sx - ry, sy + rx, w, h, stride, color); - } - draw_line(buf, sx, sy, ex, ey, w, h, stride, color); -} -#endif - static int add_mb(AVMotionVector *mb, uint32_t mb_type, int dst_x, int dst_y, int motion_x, int motion_y, int motion_scale, @@ -1737,12 +1609,6 @@ void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_ int mb_y; int i; int h_chroma_shift, v_chroma_shift, block_height; -#if FF_API_VISMV - const int shift = 1 + quarter_sample; - uint8_t *ptr; - const int width = avctx->width; - const int height = avctx->height; -#endif const int mv_sample_log2 = avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_SVQ3 ? 2 : 1; const int mv_stride = (mb_width << mv_sample_log2) + (avctx->codec->id == AV_CODEC_ID_H264 ? 0 : 1); @@ -1755,96 +1621,12 @@ void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_ av_frame_make_writable(pict); pict->opaque = NULL; -#if FF_API_VISMV - ptr = pict->data[0]; -#endif block_height = 16 >> v_chroma_shift; for (mb_y = 0; mb_y < mb_height; mb_y++) { int mb_x; for (mb_x = 0; mb_x < mb_width; mb_x++) { const int mb_index = mb_x + mb_y * mb_stride; -#if FF_API_VISMV - if ((avctx->debug_mv) && motion_val[0]) { - int type; - for (type = 0; type < 3; type++) { - int direction = 0; - switch (type) { - case 0: - if ((!(avctx->debug_mv & FF_DEBUG_VIS_MV_P_FOR)) || - (pict->pict_type!= AV_PICTURE_TYPE_P)) - continue; - direction = 0; - break; - case 1: - if ((!(avctx->debug_mv & FF_DEBUG_VIS_MV_B_FOR)) || - (pict->pict_type!= AV_PICTURE_TYPE_B)) - continue; - direction = 0; - break; - case 2: - if ((!(avctx->debug_mv & FF_DEBUG_VIS_MV_B_BACK)) || - (pict->pict_type!= AV_PICTURE_TYPE_B)) - continue; - direction = 1; - break; - } - if (!USES_LIST(mbtype_table[mb_index], direction)) - continue; - - if (IS_8X8(mbtype_table[mb_index])) { - int i; - for (i = 0; i < 4; i++) { - int sx = mb_x * 16 + 4 + 8 * (i & 1); - int sy = mb_y * 16 + 4 + 8 * (i >> 1); - int xy = (mb_x * 2 + (i & 1) + - (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1); - int mx = (motion_val[direction][xy][0] >> shift) + sx; - int my = (motion_val[direction][xy][1] >> shift) + sy; - draw_arrow(ptr, sx, sy, mx, my, width, - height, pict->linesize[0], 100, 0, direction); - } - } else if (IS_16X8(mbtype_table[mb_index])) { - int i; - for (i = 0; i < 2; i++) { - int sx = mb_x * 16 + 8; - int sy = mb_y * 16 + 4 + 8 * i; - int xy = (mb_x * 2 + (mb_y * 2 + i) * mv_stride) << (mv_sample_log2 - 1); - int mx = (motion_val[direction][xy][0] >> shift); - int my = (motion_val[direction][xy][1] >> shift); - - if (IS_INTERLACED(mbtype_table[mb_index])) - my *= 2; - - draw_arrow(ptr, sx, sy, mx + sx, my + sy, width, - height, pict->linesize[0], 100, 0, direction); - } - } else if (IS_8X16(mbtype_table[mb_index])) { - int i; - for (i = 0; i < 2; i++) { - int sx = mb_x * 16 + 4 + 8 * i; - int sy = mb_y * 16 + 8; - int xy = (mb_x * 2 + i + mb_y * 2 * mv_stride) << (mv_sample_log2 - 1); - int mx = motion_val[direction][xy][0] >> shift; - int my = motion_val[direction][xy][1] >> shift; - - if (IS_INTERLACED(mbtype_table[mb_index])) - my *= 2; - - draw_arrow(ptr, sx, sy, mx + sx, my + sy, width, - height, pict->linesize[0], 100, 0, direction); - } - } else { - int sx= mb_x * 16 + 8; - int sy= mb_y * 16 + 8; - int xy= (mb_x + mb_y * mv_stride) << mv_sample_log2; - int mx= (motion_val[direction][xy][0]>>shift) + sx; - int my= (motion_val[direction][xy][1]>>shift) + sy; - draw_arrow(ptr, sx, sy, mx, my, width, height, pict->linesize[0], 100, 0, direction); - } - } - } -#endif if ((avctx->debug & FF_DEBUG_VIS_QP)) { uint64_t c = (qscale_table[mb_index] * 128 / 31) * 0x0101010101010101ULL; diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 51932f857d22d..942aecec055be 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -249,12 +249,6 @@ static const AVOption avcodec_options[] = { {"buffers", "picture buffer allocations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BUFFERS }, INT_MIN, INT_MAX, V|D, "debug"}, {"thread_ops", "threading operations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_THREADS }, INT_MIN, INT_MAX, V|A|D, "debug"}, {"nomc", "skip motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_NOMC }, INT_MIN, INT_MAX, V|A|D, "debug"}, -#if FF_API_VISMV -{"vismv", "visualize motion vectors (MVs) (deprecated)", OFFSET(debug_mv), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, INT_MAX, V|D, "debug_mv"}, -{"pf", "forward predicted MVs of P-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_P_FOR }, INT_MIN, INT_MAX, V|D, "debug_mv"}, -{"bf", "forward predicted MVs of B-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_B_FOR }, INT_MIN, INT_MAX, V|D, "debug_mv"}, -{"bb", "backward predicted MVs of B-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_B_BACK }, INT_MIN, INT_MAX, V|D, "debug_mv"}, -#endif {"cmp", "full-pel ME compare function", OFFSET(me_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"}, {"subcmp", "sub-pel ME compare function", OFFSET(me_sub_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"}, {"mbcmp", "macroblock compare function", OFFSET(mb_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"}, diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 6f6707a7c7c5e..965b6c627647a 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -816,12 +816,6 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code avctx->lowres = avctx->codec->max_lowres; } -#if FF_API_VISMV - if (avctx->debug_mv) - av_log(avctx, AV_LOG_WARNING, "The 'vismv' option is deprecated, " - "see the codecview filter instead.\n"); -#endif - if (av_codec_is_encoder(avctx->codec)) { int i; #if FF_API_CODED_FRAME diff --git a/libavcodec/version.h b/libavcodec/version.h index 3dd58c448d9a1..6c52ae983caaa 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -57,10 +57,6 @@ #ifndef FF_API_DEBUG_MV #define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 58) #endif -#ifndef FF_API_VISMV -/* XXX: don't forget to drop the -vismv documentation */ -#define FF_API_VISMV (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_VAAPI_CONTEXT #define FF_API_VAAPI_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 58) #endif From fb41bad7e051240017bc4cc79c50ea36ac12b96c Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 23 Oct 2017 17:00:06 -0300 Subject: [PATCH 0579/2557] avodec/vaapi: drop deprecated vaapi_context fields Deprecated in 07/2015. Signed-off-by: James Almer --- libavcodec/vaapi.h | 109 ------------------------------------------- libavcodec/version.h | 3 -- 2 files changed, 112 deletions(-) diff --git a/libavcodec/vaapi.h b/libavcodec/vaapi.h index bb28455329362..2cf7da5889ab4 100644 --- a/libavcodec/vaapi.h +++ b/libavcodec/vaapi.h @@ -77,115 +77,6 @@ struct attribute_deprecated vaapi_context { * - decoding: Set by user */ uint32_t context_id; - -#if FF_API_VAAPI_CONTEXT - /** - * VAPictureParameterBuffer ID - * - * - encoding: unused - * - decoding: Set by libavcodec - */ - attribute_deprecated - uint32_t pic_param_buf_id; - - /** - * VAIQMatrixBuffer ID - * - * - encoding: unused - * - decoding: Set by libavcodec - */ - attribute_deprecated - uint32_t iq_matrix_buf_id; - - /** - * VABitPlaneBuffer ID (for VC-1 decoding) - * - * - encoding: unused - * - decoding: Set by libavcodec - */ - attribute_deprecated - uint32_t bitplane_buf_id; - - /** - * Slice parameter/data buffer IDs - * - * - encoding: unused - * - decoding: Set by libavcodec - */ - attribute_deprecated - uint32_t *slice_buf_ids; - - /** - * Number of effective slice buffer IDs to send to the HW - * - * - encoding: unused - * - decoding: Set by libavcodec - */ - attribute_deprecated - unsigned int n_slice_buf_ids; - - /** - * Size of pre-allocated slice_buf_ids - * - * - encoding: unused - * - decoding: Set by libavcodec - */ - attribute_deprecated - unsigned int slice_buf_ids_alloc; - - /** - * Pointer to VASliceParameterBuffers - * - * - encoding: unused - * - decoding: Set by libavcodec - */ - attribute_deprecated - void *slice_params; - - /** - * Size of a VASliceParameterBuffer element - * - * - encoding: unused - * - decoding: Set by libavcodec - */ - attribute_deprecated - unsigned int slice_param_size; - - /** - * Size of pre-allocated slice_params - * - * - encoding: unused - * - decoding: Set by libavcodec - */ - attribute_deprecated - unsigned int slice_params_alloc; - - /** - * Number of slices currently filled in - * - * - encoding: unused - * - decoding: Set by libavcodec - */ - attribute_deprecated - unsigned int slice_count; - - /** - * Pointer to slice data buffer base - * - encoding: unused - * - decoding: Set by libavcodec - */ - attribute_deprecated - const uint8_t *slice_data; - - /** - * Current size of slice data - * - * - encoding: unused - * - decoding: Set by libavcodec - */ - attribute_deprecated - uint32_t slice_data_size; -#endif }; /* @} */ diff --git a/libavcodec/version.h b/libavcodec/version.h index 6c52ae983caaa..8fbbe6cd96a96 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -57,9 +57,6 @@ #ifndef FF_API_DEBUG_MV #define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 58) #endif -#ifndef FF_API_VAAPI_CONTEXT -#define FF_API_VAAPI_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_AVCTX_TIMEBASE #define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 59) #endif From f192f2f061d979e3d2716b9892ca276b5d5cd418 Mon Sep 17 00:00:00 2001 From: Mateusz Date: Fri, 6 Oct 2017 16:49:54 +0200 Subject: [PATCH 0580/2557] swscale: more accurate DITHER_COPY macro for full and limited range Signed-off-by: Michael Niedermayer --- libswscale/swscale_unscaled.c | 73 +++++++++++----------- tests/ref/vsynth/vsynth1-ffvhuff420p12 | 4 +- tests/ref/vsynth/vsynth1-vc2-420p10 | 4 +- tests/ref/vsynth/vsynth1-vc2-420p12 | 4 +- tests/ref/vsynth/vsynth2-ffvhuff420p12 | 4 +- tests/ref/vsynth/vsynth2-vc2-420p10 | 4 +- tests/ref/vsynth/vsynth2-vc2-420p12 | 4 +- tests/ref/vsynth/vsynth3-ffvhuff420p12 | 4 +- tests/ref/vsynth/vsynth_lena-ffvhuff420p12 | 4 +- tests/ref/vsynth/vsynth_lena-vc2-420p10 | 4 +- tests/ref/vsynth/vsynth_lena-vc2-420p12 | 4 +- 11 files changed, 58 insertions(+), 55 deletions(-) diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index ef36aec500bec..5d81cd5af9d46 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -110,24 +110,6 @@ DECLARE_ALIGNED(8, static const uint8_t, dithers)[8][8][8]={ { 112, 16,104, 8,118, 22,110, 14,}, }}; -static const uint16_t dither_scale[15][16]={ -{ 2, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,}, -{ 2, 3, 7, 7, 13, 13, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,}, -{ 3, 3, 4, 15, 15, 29, 57, 57, 57, 113, 113, 113, 113, 113, 113, 113,}, -{ 3, 4, 4, 5, 31, 31, 61, 121, 241, 241, 241, 241, 481, 481, 481, 481,}, -{ 3, 4, 5, 5, 6, 63, 63, 125, 249, 497, 993, 993, 993, 993, 993, 1985,}, -{ 3, 5, 6, 6, 6, 7, 127, 127, 253, 505, 1009, 2017, 4033, 4033, 4033, 4033,}, -{ 3, 5, 6, 7, 7, 7, 8, 255, 255, 509, 1017, 2033, 4065, 8129,16257,16257,}, -{ 3, 5, 6, 8, 8, 8, 8, 9, 511, 511, 1021, 2041, 4081, 8161,16321,32641,}, -{ 3, 5, 7, 8, 9, 9, 9, 9, 10, 1023, 1023, 2045, 4089, 8177,16353,32705,}, -{ 3, 5, 7, 8, 10, 10, 10, 10, 10, 11, 2047, 2047, 4093, 8185,16369,32737,}, -{ 3, 5, 7, 8, 10, 11, 11, 11, 11, 11, 12, 4095, 4095, 8189,16377,32753,}, -{ 3, 5, 7, 9, 10, 12, 12, 12, 12, 12, 12, 13, 8191, 8191,16381,32761,}, -{ 3, 5, 7, 9, 10, 12, 13, 13, 13, 13, 13, 13, 14,16383,16383,32765,}, -{ 3, 5, 7, 9, 10, 12, 14, 14, 14, 14, 14, 14, 14, 15,32767,32767,}, -{ 3, 5, 7, 9, 11, 12, 14, 15, 15, 15, 15, 15, 15, 15, 16,65535,}, -}; - static void fillPlane(uint8_t *plane, int stride, int width, int height, int y, uint8_t val) @@ -1502,24 +1484,45 @@ static int packedCopyWrapper(SwsContext *c, const uint8_t *src[], } #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\ - uint16_t scale= dither_scale[dst_depth-1][src_depth-1];\ - int shift= src_depth-dst_depth + dither_scale[src_depth-2][dst_depth-1];\ - for (i = 0; i < height; i++) {\ - const uint8_t *dither= dithers[src_depth-9][i&7];\ - for (j = 0; j < length-7; j+=8){\ - dst[j+0] = dbswap((bswap(src[j+0]) + dither[0])*scale>>shift);\ - dst[j+1] = dbswap((bswap(src[j+1]) + dither[1])*scale>>shift);\ - dst[j+2] = dbswap((bswap(src[j+2]) + dither[2])*scale>>shift);\ - dst[j+3] = dbswap((bswap(src[j+3]) + dither[3])*scale>>shift);\ - dst[j+4] = dbswap((bswap(src[j+4]) + dither[4])*scale>>shift);\ - dst[j+5] = dbswap((bswap(src[j+5]) + dither[5])*scale>>shift);\ - dst[j+6] = dbswap((bswap(src[j+6]) + dither[6])*scale>>shift);\ - dst[j+7] = dbswap((bswap(src[j+7]) + dither[7])*scale>>shift);\ + unsigned shift= src_depth-dst_depth, tmp;\ + if (shiftonly) {\ + for (i = 0; i < height; i++) {\ + const uint8_t *dither= dithers[shift-1][i&7];\ + for (j = 0; j < length-7; j+=8) {\ + tmp = (bswap(src[j+0]) + dither[0])>>shift; dst[j+0] = dbswap(tmp - (tmp>>dst_depth));\ + tmp = (bswap(src[j+1]) + dither[1])>>shift; dst[j+1] = dbswap(tmp - (tmp>>dst_depth));\ + tmp = (bswap(src[j+2]) + dither[2])>>shift; dst[j+2] = dbswap(tmp - (tmp>>dst_depth));\ + tmp = (bswap(src[j+3]) + dither[3])>>shift; dst[j+3] = dbswap(tmp - (tmp>>dst_depth));\ + tmp = (bswap(src[j+4]) + dither[4])>>shift; dst[j+4] = dbswap(tmp - (tmp>>dst_depth));\ + tmp = (bswap(src[j+5]) + dither[5])>>shift; dst[j+5] = dbswap(tmp - (tmp>>dst_depth));\ + tmp = (bswap(src[j+6]) + dither[6])>>shift; dst[j+6] = dbswap(tmp - (tmp>>dst_depth));\ + tmp = (bswap(src[j+7]) + dither[7])>>shift; dst[j+7] = dbswap(tmp - (tmp>>dst_depth));\ + }\ + for (; j < length; j++) {\ + tmp = (bswap(src[j]) + dither[j&7])>>shift; dst[j] = dbswap(tmp - (tmp>>dst_depth));\ + }\ + dst += dstStride;\ + src += srcStride;\ + }\ + } else {\ + for (i = 0; i < height; i++) {\ + const uint8_t *dither= dithers[shift-1][i&7];\ + for (j = 0; j < length-7; j+=8) {\ + tmp = bswap(src[j+0]); dst[j+0] = dbswap((tmp - (tmp>>dst_depth) + dither[0])>>shift);\ + tmp = bswap(src[j+1]); dst[j+1] = dbswap((tmp - (tmp>>dst_depth) + dither[1])>>shift);\ + tmp = bswap(src[j+2]); dst[j+2] = dbswap((tmp - (tmp>>dst_depth) + dither[2])>>shift);\ + tmp = bswap(src[j+3]); dst[j+3] = dbswap((tmp - (tmp>>dst_depth) + dither[3])>>shift);\ + tmp = bswap(src[j+4]); dst[j+4] = dbswap((tmp - (tmp>>dst_depth) + dither[4])>>shift);\ + tmp = bswap(src[j+5]); dst[j+5] = dbswap((tmp - (tmp>>dst_depth) + dither[5])>>shift);\ + tmp = bswap(src[j+6]); dst[j+6] = dbswap((tmp - (tmp>>dst_depth) + dither[6])>>shift);\ + tmp = bswap(src[j+7]); dst[j+7] = dbswap((tmp - (tmp>>dst_depth) + dither[7])>>shift);\ + }\ + for (; j < length; j++) {\ + tmp = bswap(src[j]); dst[j] = dbswap((tmp - (tmp>>dst_depth) + dither[j&7])>>shift);\ + }\ + dst += dstStride;\ + src += srcStride;\ }\ - for (; j < length; j++)\ - dst[j] = dbswap((bswap(src[j]) + dither[j&7])*scale>>shift);\ - dst += dstStride;\ - src += srcStride;\ } static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], diff --git a/tests/ref/vsynth/vsynth1-ffvhuff420p12 b/tests/ref/vsynth/vsynth1-ffvhuff420p12 index 0d80bd6d6806f..d4b22f3b4be13 100644 --- a/tests/ref/vsynth/vsynth1-ffvhuff420p12 +++ b/tests/ref/vsynth/vsynth1-ffvhuff420p12 @@ -1,4 +1,4 @@ 866485c954242232878e40f0389790dd *tests/data/fate/vsynth1-ffvhuff420p12.avi 14205356 tests/data/fate/vsynth1-ffvhuff420p12.avi -b48f32c140712e8c7bf81cfdd66ae312 *tests/data/fate/vsynth1-ffvhuff420p12.out.rawvideo -stddev: 0.68 PSNR: 51.47 MAXDIFF: 1 bytes: 7603200/ 7603200 +c5ccac874dbf808e9088bc3107860042 *tests/data/fate/vsynth1-ffvhuff420p12.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-vc2-420p10 b/tests/ref/vsynth/vsynth1-vc2-420p10 index 037c77cacf02d..025a1cc779ee4 100644 --- a/tests/ref/vsynth/vsynth1-vc2-420p10 +++ b/tests/ref/vsynth/vsynth1-vc2-420p10 @@ -1,4 +1,4 @@ 1365742985b6315f6796c765aa17f39e *tests/data/fate/vsynth1-vc2-420p10.mov 1417047 tests/data/fate/vsynth1-vc2-420p10.mov -d3deedfa461a2696f82910890412fa2d *tests/data/fate/vsynth1-vc2-420p10.out.rawvideo -stddev: 0.60 PSNR: 52.47 MAXDIFF: 1 bytes: 7603200/ 760320 +387696707c79cf1a6c9aeff4024226b9 *tests/data/fate/vsynth1-vc2-420p10.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 760320 diff --git a/tests/ref/vsynth/vsynth1-vc2-420p12 b/tests/ref/vsynth/vsynth1-vc2-420p12 index b0c56afcd5625..719f0d5f37e64 100644 --- a/tests/ref/vsynth/vsynth1-vc2-420p12 +++ b/tests/ref/vsynth/vsynth1-vc2-420p12 @@ -1,4 +1,4 @@ 08a844d17940cd612da269fb08430628 *tests/data/fate/vsynth1-vc2-420p12.mov 1746007 tests/data/fate/vsynth1-vc2-420p12.mov -5a78509638a96b0fa17c1b7e9159fd24 *tests/data/fate/vsynth1-vc2-420p12.out.rawvideo -stddev: 0.67 PSNR: 51.48 MAXDIFF: 1 bytes: 7603200/ 760320 +387696707c79cf1a6c9aeff4024226b9 *tests/data/fate/vsynth1-vc2-420p12.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 760320 diff --git a/tests/ref/vsynth/vsynth2-ffvhuff420p12 b/tests/ref/vsynth/vsynth2-ffvhuff420p12 index 82c467ac3ea5b..f97edfbf4e10f 100644 --- a/tests/ref/vsynth/vsynth2-ffvhuff420p12 +++ b/tests/ref/vsynth/vsynth2-ffvhuff420p12 @@ -1,4 +1,4 @@ 3ab9567895bf1ec31a82aadf16a5da0e *tests/data/fate/vsynth2-ffvhuff420p12.avi 10562808 tests/data/fate/vsynth2-ffvhuff420p12.avi -542327cb5ca7708085513ffc3d7c693c *tests/data/fate/vsynth2-ffvhuff420p12.out.rawvideo -stddev: 0.72 PSNR: 50.87 MAXDIFF: 1 bytes: 7603200/ 7603200 +36d7ca943916e1743cefa609eba0205c *tests/data/fate/vsynth2-ffvhuff420p12.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-vc2-420p10 b/tests/ref/vsynth/vsynth2-vc2-420p10 index 9de40d227598e..48d97d60e4274 100644 --- a/tests/ref/vsynth/vsynth2-vc2-420p10 +++ b/tests/ref/vsynth/vsynth2-vc2-420p10 @@ -1,4 +1,4 @@ 1197f8108683b9eb6b0777adb2db1aa8 *tests/data/fate/vsynth2-vc2-420p10.mov 1181271 tests/data/fate/vsynth2-vc2-420p10.mov -75174cb90e76c433f6d769531d573ac2 *tests/data/fate/vsynth2-vc2-420p10.out.rawvideo -stddev: 0.63 PSNR: 52.11 MAXDIFF: 1 bytes: 7603200/ 760320 +01389f7ae4f2a3dc0d7b8384d435fd83 *tests/data/fate/vsynth2-vc2-420p10.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 760320 diff --git a/tests/ref/vsynth/vsynth2-vc2-420p12 b/tests/ref/vsynth/vsynth2-vc2-420p12 index 660a1eeb5c38c..9b9ccb8ec1e43 100644 --- a/tests/ref/vsynth/vsynth2-vc2-420p12 +++ b/tests/ref/vsynth/vsynth2-vc2-420p12 @@ -1,4 +1,4 @@ 0e6b3aefd70fca45e67dc8cbc99640e8 *tests/data/fate/vsynth2-vc2-420p12.mov 1525079 tests/data/fate/vsynth2-vc2-420p12.mov -b4d45651e20faa7a0bb84a0738638c48 *tests/data/fate/vsynth2-vc2-420p12.out.rawvideo -stddev: 0.73 PSNR: 50.84 MAXDIFF: 1 bytes: 7603200/ 760320 +01389f7ae4f2a3dc0d7b8384d435fd83 *tests/data/fate/vsynth2-vc2-420p12.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 760320 diff --git a/tests/ref/vsynth/vsynth3-ffvhuff420p12 b/tests/ref/vsynth/vsynth3-ffvhuff420p12 index 72d412d644d0a..201ec7658b2d6 100644 --- a/tests/ref/vsynth/vsynth3-ffvhuff420p12 +++ b/tests/ref/vsynth/vsynth3-ffvhuff420p12 @@ -1,4 +1,4 @@ e5a178d75afeda6df1d4eb6f7cdfa3a0 *tests/data/fate/vsynth3-ffvhuff420p12.avi 175260 tests/data/fate/vsynth3-ffvhuff420p12.avi -ee95a44ccd612b5057860b43fe9775d6 *tests/data/fate/vsynth3-ffvhuff420p12.out.rawvideo -stddev: 0.69 PSNR: 51.35 MAXDIFF: 1 bytes: 86700/ 86700 +a038ad7c3c09f776304ef7accdea9c74 *tests/data/fate/vsynth3-ffvhuff420p12.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth_lena-ffvhuff420p12 b/tests/ref/vsynth/vsynth_lena-ffvhuff420p12 index e8ea4bcc85d68..e77698ba0c5e1 100644 --- a/tests/ref/vsynth/vsynth_lena-ffvhuff420p12 +++ b/tests/ref/vsynth/vsynth_lena-ffvhuff420p12 @@ -1,4 +1,4 @@ b2f3d04ca30c113b79877bb5518dd6ea *tests/data/fate/vsynth_lena-ffvhuff420p12.avi 10925580 tests/data/fate/vsynth_lena-ffvhuff420p12.avi -08b3c6c70eba608bae926608ff253f2a *tests/data/fate/vsynth_lena-ffvhuff420p12.out.rawvideo -stddev: 0.68 PSNR: 51.38 MAXDIFF: 1 bytes: 7603200/ 7603200 +dde5895817ad9d219f79a52d0bdfb001 *tests/data/fate/vsynth_lena-ffvhuff420p12.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth_lena-vc2-420p10 b/tests/ref/vsynth/vsynth_lena-vc2-420p10 index 6428dd17887c2..2558ef8e9b564 100644 --- a/tests/ref/vsynth/vsynth_lena-vc2-420p10 +++ b/tests/ref/vsynth/vsynth_lena-vc2-420p10 @@ -1,4 +1,4 @@ 5bccec653c330f03b90065a84fad9b4b *tests/data/fate/vsynth_lena-vc2-420p10.mov 1154775 tests/data/fate/vsynth_lena-vc2-420p10.mov -32265ec286c54104b3be8f11c519da1b *tests/data/fate/vsynth_lena-vc2-420p10.out.rawvideo -stddev: 0.61 PSNR: 52.34 MAXDIFF: 1 bytes: 7603200/ 760320 +b1c660113acab8eb4075f3d9fbb9cee9 *tests/data/fate/vsynth_lena-vc2-420p10.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 760320 diff --git a/tests/ref/vsynth/vsynth_lena-vc2-420p12 b/tests/ref/vsynth/vsynth_lena-vc2-420p12 index e62b2b6d38831..bc60116ffe829 100644 --- a/tests/ref/vsynth/vsynth_lena-vc2-420p12 +++ b/tests/ref/vsynth/vsynth_lena-vc2-420p12 @@ -1,4 +1,4 @@ d27a6d3517cc9a6d22e338f4b206545c *tests/data/fate/vsynth_lena-vc2-420p12.mov 1516759 tests/data/fate/vsynth_lena-vc2-420p12.mov -bc62f1c3bade7224c55219dba8a3c6af *tests/data/fate/vsynth_lena-vc2-420p12.out.rawvideo -stddev: 0.68 PSNR: 51.39 MAXDIFF: 1 bytes: 7603200/ 760320 +b1c660113acab8eb4075f3d9fbb9cee9 *tests/data/fate/vsynth_lena-vc2-420p12.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 760320 From e724bdfffbd3c27aac53d1f32f20f105f37caef0 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 24 Oct 2017 00:28:03 +0200 Subject: [PATCH 0581/2557] lavc: fix hw_device_ctx operation Commit b46a77f19d accidentally broke this (requested change that was added to the patch later and which was not fully tested). Signed-off-by: Mark Thompson --- libavcodec/decode.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 54cda530bb8c3..27f75d73e3e8a 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -698,11 +698,9 @@ int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx, ret = avcodec_get_hw_frames_parameters(avctx, avctx->hw_device_ctx, avctx->hwaccel->pix_fmt, - avctx->hw_frames_ctx); - if (ret < 0) { - av_buffer_unref(&avctx->hw_frames_ctx); + &avctx->hw_frames_ctx); + if (ret < 0) return ret; - } frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; From 17f5171cd4753e7f50e6d95df069bccbc90265bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 23 Oct 2017 10:44:07 +0300 Subject: [PATCH 0582/2557] arm: Check for have_vfp_vm instead of !have_vfpv3 for float_dsp_vfp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was missed in e2710e790c0 since those functions weren't exercised by checkasm. Signed-off-by: Martin Storsjö --- libavutil/arm/float_dsp_init_vfp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavutil/arm/float_dsp_init_vfp.c b/libavutil/arm/float_dsp_init_vfp.c index 61ff2ed38e9c9..79ba6ecd3dd5f 100644 --- a/libavutil/arm/float_dsp_init_vfp.c +++ b/libavutil/arm/float_dsp_init_vfp.c @@ -36,11 +36,11 @@ void ff_butterflies_float_vfp(float *restrict v1, float *restrict v2, int len); av_cold void ff_float_dsp_init_vfp(AVFloatDSPContext *fdsp, int cpu_flags) { - if (!have_vfpv3(cpu_flags)) { + if (have_vfp_vm(cpu_flags)) { fdsp->vector_fmul = ff_vector_fmul_vfp; fdsp->vector_fmul_window = ff_vector_fmul_window_vfp; } fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_vfp; - if (!have_vfpv3(cpu_flags)) + if (have_vfp_vm(cpu_flags)) fdsp->butterflies_float = ff_butterflies_float_vfp; } From b487add7ecf78efda36d49815f8f8757bd24d4cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 23 Oct 2017 10:44:53 +0300 Subject: [PATCH 0583/2557] arm: Remove a redundant check in fmtconvert_init_arm.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was missed in e2710e790c0, where have_vfp && !have_vfpv3 were converted into have_vfp_vm. Signed-off-by: Martin Storsjö --- libavcodec/arm/fmtconvert_init_arm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libavcodec/arm/fmtconvert_init_arm.c b/libavcodec/arm/fmtconvert_init_arm.c index 11396e898c113..70c8023aa2542 100644 --- a/libavcodec/arm/fmtconvert_init_arm.c +++ b/libavcodec/arm/fmtconvert_init_arm.c @@ -42,10 +42,8 @@ av_cold void ff_fmt_convert_init_arm(FmtConvertContext *c, AVCodecContext *avctx int cpu_flags = av_get_cpu_flags(); if (have_vfp_vm(cpu_flags)) { - if (!have_vfpv3(cpu_flags)) { - c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_vfp; - c->int32_to_float_fmul_array8 = ff_int32_to_float_fmul_array8_vfp; - } + c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_vfp; + c->int32_to_float_fmul_array8 = ff_int32_to_float_fmul_array8_vfp; } if (have_neon(cpu_flags)) { From 3c14547eb75c5b18099060085d12f09518ee2732 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 24 Oct 2017 22:32:59 +0200 Subject: [PATCH 0584/2557] lavfi/tests/filtfmts: Constify a variable. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following warning: libavfilter/tests/filtfmts.c: In function ‘main’: libavfilter/tests/filtfmts.c:103:18: warning: assignment discards ‘const’ qualifier from pointer target type --- libavfilter/tests/filtfmts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/tests/filtfmts.c b/libavfilter/tests/filtfmts.c index 199d74d7a93f6..72b860ae5b5b4 100644 --- a/libavfilter/tests/filtfmts.c +++ b/libavfilter/tests/filtfmts.c @@ -73,7 +73,7 @@ static void print_formats(AVFilterContext *filter_ctx) int main(int argc, char **argv) { - AVFilter *filter; + const AVFilter *filter; AVFilterContext *filter_ctx; AVFilterGraph *graph_ctx; const char *filter_name; From df95f145be1556da7e147d642e4fd8bf96276321 Mon Sep 17 00:00:00 2001 From: JULIAN GARDNER Date: Tue, 24 Oct 2017 22:46:00 +0200 Subject: [PATCH 0585/2557] lavc/dvbsub: Do not fail hard in the region block for 256-colour encoding. Adds a hunk forgotten in 8a6799d2 --- libavcodec/dvbsub.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/dvbsub.c b/libavcodec/dvbsub.c index 3cdbade99c429..04c0c60626f37 100644 --- a/libavcodec/dvbsub.c +++ b/libavcodec/dvbsub.c @@ -342,6 +342,9 @@ static int encode_dvb_subtitles(DVBSubtitleContext *s, } else if (h->rects[region_id]->nb_colors <= 16) { /* 4 bpp, standard encoding */ bpp_index = 1; + } else if (h->rects[region_id]->nb_colors <= 256) { + /* 8 bpp, standard encoding */ + bpp_index = 2; } else { return -1; } From 6e1654768585692e327343059b35695b6123444a Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 24 Oct 2017 22:49:04 +0200 Subject: [PATCH 0586/2557] lavc/dvbsub: Add the missing line separator to dvb_encode_rle8(). Fixes 256-colour dvb subtitle encoding. Fixes ticket #6769. --- libavcodec/dvbsub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/dvbsub.c b/libavcodec/dvbsub.c index 04c0c60626f37..8cce702a9e002 100644 --- a/libavcodec/dvbsub.c +++ b/libavcodec/dvbsub.c @@ -239,9 +239,9 @@ static void dvb_encode_rle8(uint8_t **pq, x += len; } /* end of line */ - // 00000000 00000000 end of 8-bit/pixel_code_string - *q++ = 0x00; + // 00000000 end of 8-bit/pixel_code_string *q++ = 0x00; + *q++ = 0xf0; bitmap += linesize; } *pq = q; From f31478ba1472afe5c1eed60f219ae331816425a2 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Tue, 24 Oct 2017 13:25:21 +0800 Subject: [PATCH 0587/2557] lavc/vaapi_encode_h264: correct VUI max_dec_frame_buffering setting This should refer to the existing SPS structure, not the VAAPI sequence parameter buffer (which is not yet initialised). Signed-off-by: Jun Zhao Signed-off-by: Wang, Yi A Signed-off-by: Mark Thompson --- libavcodec/vaapi_encode_h264.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 9a4bd53da1182..1d43e934ef015 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -441,7 +441,7 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) sps->vui.log2_max_mv_length_horizontal = 16; sps->vui.log2_max_mv_length_vertical = 16; sps->vui.max_num_reorder_frames = (ctx->b_per_p > 0); - sps->vui.max_dec_frame_buffering = vseq->max_num_ref_frames; + sps->vui.max_dec_frame_buffering = sps->max_num_ref_frames; pps->nal_unit_header.nal_ref_idc = 3; pps->nal_unit_header.nal_unit_type = H264_NAL_PPS; From 5b2c71bb94d7cab23ee81b5c29388f5fadbcaf22 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 24 Oct 2017 22:56:48 +0100 Subject: [PATCH 0588/2557] cbs_mpeg2: Fix type for marker_bit reading --- libavcodec/cbs_mpeg2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index d137762227330..0cac29733e4c4 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -54,7 +54,7 @@ xui(width, name, current->name) #define marker_bit() do { \ - av_unused int one = 1; \ + av_unused uint32_t one; \ CHECK(ff_cbs_read_unsigned(ctx, rw, 1, "marker_bit", &one, 1, 1)); \ } while (0) From 79d666aa57517eda4ad71a83af0c63c722efef70 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 24 Oct 2017 22:57:44 +0100 Subject: [PATCH 0589/2557] cbs_mpeg2: Fix format specifier --- libavcodec/cbs_mpeg2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index 0cac29733e4c4..8fb5375e3b918 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -220,7 +220,7 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header); #undef START default: - av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown start code %02x.\n", + av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown start code %"PRIx32".\n", unit->type); return AVERROR_INVALIDDATA; } From 59b00ffea3c90b41f6e83f8184068657fed112dc Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 24 Oct 2017 22:58:47 +0100 Subject: [PATCH 0590/2557] cbs_h264: Fix format specifier --- libavcodec/cbs_h264_syntax_template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs_h264_syntax_template.c b/libavcodec/cbs_h264_syntax_template.c index 8303acbdc459a..2d60273506f42 100644 --- a/libavcodec/cbs_h264_syntax_template.c +++ b/libavcodec/cbs_h264_syntax_template.c @@ -761,7 +761,7 @@ static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw, end_position = get_bits_count(rw); if (end_position < start_position + 8 * current->payload_size) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Incorrect SEI payload length: " - "header %d bits, actually %d bits.\n", + "header %"PRIu32" bits, actually %d bits.\n", 8 * current->payload_size, end_position - start_position); return AVERROR_INVALIDDATA; From c8c995bc1ddc34df93049f002432286018c8cc94 Mon Sep 17 00:00:00 2001 From: Felicia Lim Date: Mon, 27 Mar 2017 16:21:20 -0700 Subject: [PATCH 0591/2557] libopus: Add channel mapping 2 support in libopusdec Enables demuxing of Ambisonics content coded with channel mapping 2 Signed-off-by: Michael Niedermayer --- libavcodec/libopusdec.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c index e6ca61a78f3fc..9dab0fdf65c20 100644 --- a/libavcodec/libopusdec.c +++ b/libavcodec/libopusdec.c @@ -57,8 +57,6 @@ static av_cold int libopus_decode_init(AVCodecContext *avc) avc->sample_rate = 48000; avc->sample_fmt = avc->request_sample_fmt == AV_SAMPLE_FMT_FLT ? AV_SAMPLE_FMT_FLT : AV_SAMPLE_FMT_S16; - avc->channel_layout = avc->channels > 8 ? 0 : - ff_vorbis_channel_layouts[avc->channels - 1]; if (avc->extradata_size >= OPUS_HEAD_SIZE) { opus->pre_skip = AV_RL16(avc->extradata + 10); @@ -82,14 +80,35 @@ static av_cold int libopus_decode_init(AVCodecContext *avc) mapping = mapping_arr; } - if (avc->channels > 2 && avc->channels <= 8) { - const uint8_t *vorbis_offset = ff_vorbis_channel_layout_offsets[avc->channels - 1]; - int ch; - - /* Remap channels from Vorbis order to ffmpeg order */ - for (ch = 0; ch < avc->channels; ch++) - mapping_arr[ch] = mapping[vorbis_offset[ch]]; - mapping = mapping_arr; + if (channel_map == 1) { + avc->channel_layout = avc->channels > 8 ? 0 : + ff_vorbis_channel_layouts[avc->channels - 1]; + if (avc->channels > 2 && avc->channels <= 8) { + const uint8_t *vorbis_offset = ff_vorbis_channel_layout_offsets[avc->channels - 1]; + int ch; + + /* Remap channels from Vorbis order to ffmpeg order */ + for (ch = 0; ch < avc->channels; ch++) + mapping_arr[ch] = mapping[vorbis_offset[ch]]; + mapping = mapping_arr; + } + } else if (channel_map == 2) { + int ambisonic_order = ff_sqrt(avc->channels) - 1; + if (avc->channels != (ambisonic_order + 1) * (ambisonic_order + 1) && + avc->channels != (ambisonic_order + 1) * (ambisonic_order + 1) + 2) { + av_log(avc, AV_LOG_ERROR, + "Channel mapping 2 is only specified for channel counts" + " which can be written as (n + 1)^2 or (n + 2)^2 + 2" + " for nonnegative integer n\n"); + return AVERROR_INVALIDDATA; + } + if (avc->channels > 227) { + av_log(avc, AV_LOG_ERROR, "Too many channels\n"); + return AVERROR_INVALIDDATA; + } + avc->channel_layout = 0; + } else { + avc->channel_layout = 0; } opus->dec = opus_multistream_decoder_create(avc->sample_rate, avc->channels, From 617f0c65e1bac8983a5b6521818c1b9b57f0804b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 22 Oct 2017 17:11:20 +0200 Subject: [PATCH 0592/2557] ffserver: Fix off by 1 error in path Code suggested by ubitux Signed-off-by: Michael Niedermayer --- fftools/ffserver.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/fftools/ffserver.c b/fftools/ffserver.c index d4885dfa0eeac..7f8b2387bd0c8 100644 --- a/fftools/ffserver.c +++ b/fftools/ffserver.c @@ -476,7 +476,7 @@ static int compute_datarate(DataRateData *drd, int64_t count) static void start_children(FFServerStream *feed) { char *pathname; - char *slash; + char *dirname, *prog; int i; size_t cmd_length; @@ -495,22 +495,18 @@ static void start_children(FFServerStream *feed) return; } - slash = strrchr(my_program_name, '/'); - if (!slash) { - pathname = av_mallocz(sizeof("ffmpeg")); - } else { - pathname = av_mallocz(slash - my_program_name + sizeof("ffmpeg")); - if (pathname != NULL) { - memcpy(pathname, my_program_name, slash - my_program_name); - } - } - if (!pathname) { + /* use "ffmpeg" in the path of current program. Ignore user provided path */ + prog = av_strdup(my_program_name); + if (prog) { + dirname = av_dirname(prog); + pathname = *dirname ? av_asprintf("%s/%s", dirname, "ffmpeg") + : av_asprintf("ffmpeg"); + av_free(prog); + } + if (!prog || !pathname) { http_log("Could not allocate memory for children cmd line\n"); return; } - /* use "ffmpeg" in the path of current program. Ignore user provided path */ - - strcat(pathname, "ffmpeg"); for (; feed; feed = feed->next) { From 431eccd61e155190a7762314938799076cffeb67 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 22 Oct 2017 17:11:21 +0200 Subject: [PATCH 0593/2557] tests/ffserver.regression.ref: update checksums to what ffserver currently produces Signed-off-by: Michael Niedermayer --- tests/ffserver.regression.ref | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/ffserver.regression.ref b/tests/ffserver.regression.ref index 398c28515603e..fd8536c853f97 100644 --- a/tests/ffserver.regression.ref +++ b/tests/ffserver.regression.ref @@ -1,11 +1,11 @@ 0c9639f09decbc54c9f091dcf1ca0e8f *ff-test_h.avi e28ba75853caf975e06d92955c9f7f73 *ff-test_l.avi a767dbdf5d1bded3450279f812f97b37 *ff-test.swf -dc16f607e13328a832e73801cd21ec98 *ff-test_h.asf -69337d6c8cd7ac7e626338decdbf41d3 *ff-test_l.asf +ca209a0c67afbd3bc3bcde0840f313fc *ff-test_h.asf +f97a91609bfc8a1857455f17c5ec101c *ff-test_l.asf 06f5a6a4c5d1c6735f4d0068e825c91f *ff-test_h.rm 1f57580f02f0317407b3b82a3d5e093f *ff-test_l.rm -4c887dfc1dd0f6ea1a3a2be6dd32e495 *ff-test.jpg -1d04b73b04aad27793cc762d5afabac1 *ff-test_small.jpg -bc36c40ee34ebee6ffe50f3094aab733 *ff-test.mjpg +e04e6ebf9584654df131f5eec881ac38 *ff-test.jpg +f15d43e9d3630601b61a024023249bb8 *ff-test_small.jpg +4735c72cde67000f12e9d1dbfbd975a7 *ff-test.mjpg fd038af80560e15271ce42651093ee43 *ff-stat From 7e294a1f09a2b7bbba5c057e23e533fffef5336d Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Mon, 23 Oct 2017 15:18:12 +0800 Subject: [PATCH 0594/2557] fate: add a test for mpeg2 issue of ticket #6677 Signed-off-by: Zhong Li Signed-off-by: Michael Niedermayer --- tests/fate/video.mak | 3 +++ tests/ref/fate/mpeg2-ticket6677 | 12 ++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 tests/ref/fate/mpeg2-ticket6677 diff --git a/tests/fate/video.mak b/tests/fate/video.mak index 6f76365165e03..51678078a3781 100644 --- a/tests/fate/video.mak +++ b/tests/fate/video.mak @@ -257,6 +257,9 @@ fate-mpeg2-ticket186: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_S FATE_VIDEO-$(call DEMDEC, MPEGPS, MPEG2VIDEO) += fate-mpeg2-ticket6024 fate-mpeg2-ticket6024: CMD = framecrc -flags +bitexact -idct simple -flags +truncated -i $(TARGET_SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg -an +FATE_VIDEO-$(call DEMDEC, MPEGVIDEO, MPEG2VIDEO) += fate-mpeg2-ticket6677 +fate-mpeg2-ticket6677: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/mpeg2/sony-ct3.bs + FATE_VIDEO-$(call DEMDEC, MV, MVC1) += fate-mv-mvc1 fate-mv-mvc1: CMD = framecrc -i $(TARGET_SAMPLES)/mv/posture.mv -an -frames 25 -pix_fmt rgb555le diff --git a/tests/ref/fate/mpeg2-ticket6677 b/tests/ref/fate/mpeg2-ticket6677 new file mode 100644 index 0000000000000..5fc7cb2a26ac8 --- /dev/null +++ b/tests/ref/fate/mpeg2-ticket6677 @@ -0,0 +1,12 @@ +#tb 0: 1/30 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 720x480 +#sar 0: 8/9 +0, 0, 0, 1, 518400, 0x354b6fc3 +0, 1, 1, 1, 518400, 0xd86f281b +0, 2, 2, 1, 518400, 0xdd2e2b38 +0, 3, 3, 1, 518400, 0x589535d4 +0, 4, 4, 1, 518400, 0x3f8f02b6 +0, 5, 5, 1, 518400, 0xa81b246a +0, 6, 6, 1, 518400, 0xb98dd9f7 From 94ab0bef408c738b18d851c47a5bcd69a6258cc2 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 1 Oct 2017 22:50:59 +0100 Subject: [PATCH 0595/2557] vaapi: Disable deprecation warnings around use of struct vaapi_context --- libavcodec/vaapi_decode.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/vaapi_decode.h b/libavcodec/vaapi_decode.h index e195e863a044f..fda228b5a98ab 100644 --- a/libavcodec/vaapi_decode.h +++ b/libavcodec/vaapi_decode.h @@ -24,6 +24,7 @@ #include "libavutil/frame.h" #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_vaapi.h" +#include "libavutil/internal.h" #include "avcodec.h" @@ -57,9 +58,11 @@ typedef struct VAAPIDecodeContext { VAContextID va_context; #if FF_API_VAAPI_CONTEXT +FF_DISABLE_DEPRECATION_WARNINGS int have_old_context; struct vaapi_context *old_context; AVBufferRef *device_ref; +FF_ENABLE_DEPRECATION_WARNINGS #endif AVHWDeviceContext *device; From a126b67e1b01d5886afaa6bcad108a85392ce15c Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 1 Oct 2017 22:51:07 +0100 Subject: [PATCH 0596/2557] configure: Add config option for libva2 (VAAPI 1) --- configure | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure b/configure index 173610a19c148..52232367950fc 100755 --- a/configure +++ b/configure @@ -1650,6 +1650,7 @@ SYSTEM_FUNCS=" SYSTEM_LIBRARIES=" sdl + vaapi_1 vaapi_drm vaapi_x11 vdpau_x11 @@ -4834,6 +4835,10 @@ enabled vaapi && enabled vaapi && check_lib vaapi_x11 "va/va.h va/va_x11.h" vaGetDisplay -lva -lva-x11 -lX11 +enabled vaapi && + check_cpp_condition "va/va.h" "VA_CHECK_VERSION(1, 0, 0)" && + enable vaapi_1 + enabled vdpau && check_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || disable vdpau From f0a978a519167e5ad5dd479245a7b5da77488d43 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 1 Oct 2017 22:51:13 +0100 Subject: [PATCH 0597/2557] vaapi: Remove H.264 baseline profile This has been deprecated in libva2 because hardware does not and will not support it. Therefore never consider it for decode, and for encode assume the user meant constrained baseline profile instead. --- libavcodec/vaapi_decode.c | 1 - libavcodec/vaapi_encode_h264.c | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index 5ae98d8fd7e69..febe22a710708 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -247,7 +247,6 @@ static const struct { MAP(MPEG4, MPEG4_MAIN, MPEG4Main ), MAP(H264, H264_CONSTRAINED_BASELINE, H264ConstrainedBaseline), - MAP(H264, H264_BASELINE, H264Baseline), MAP(H264, H264_MAIN, H264Main ), MAP(H264, H264_HIGH, H264High ), #if VA_CHECK_VERSION(0, 37, 0) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 1288249be7a87..3ff19d2c83d31 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -863,12 +863,13 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx) ctx->codec = &vaapi_encode_type_h264; switch (avctx->profile) { + case FF_PROFILE_H264_BASELINE: + av_log(avctx, AV_LOG_WARNING, "H.264 baseline profile is not " + "supported, using constrained baseline profile instead.\n"); + avctx->profile = FF_PROFILE_H264_CONSTRAINED_BASELINE; case FF_PROFILE_H264_CONSTRAINED_BASELINE: ctx->va_profile = VAProfileH264ConstrainedBaseline; break; - case FF_PROFILE_H264_BASELINE: - ctx->va_profile = VAProfileH264Baseline; - break; case FF_PROFILE_H264_MAIN: ctx->va_profile = VAProfileH264Main; break; From bfc83acfd6b33986480d4c6d3c571ba6a59f1d98 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 1 Oct 2017 22:51:20 +0100 Subject: [PATCH 0598/2557] vaapi: Always free parameter buffers after vaEndPicture() with libva2 This is an ABI change in libva2: previously the Intel driver had this behaviour and it was implemented as a driver quirk, but now it is part of the specification so all drivers must do it. --- libavcodec/vaapi_decode.c | 4 ++-- libavcodec/vaapi_encode.c | 4 ++-- libavfilter/vf_deinterlace_vaapi.c | 2 +- libavfilter/vf_scale_vaapi.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index febe22a710708..02304191ff03e 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -189,14 +189,14 @@ int ff_vaapi_decode_issue(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "Failed to end picture decode " "issue: %d (%s).\n", vas, vaErrorStr(vas)); err = AVERROR(EIO); - if (ctx->hwctx->driver_quirks & + if (HAVE_VAAPI_1 || ctx->hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) goto fail; else goto fail_at_end; } - if (ctx->hwctx->driver_quirks & + if (HAVE_VAAPI_1 || ctx->hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) ff_vaapi_decode_destroy_buffers(avctx, pic); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 462ec7a8e7ae8..47795ba735546 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -392,14 +392,14 @@ static int vaapi_encode_issue(AVCodecContext *avctx, err = AVERROR(EIO); // vaRenderPicture() has been called here, so we should not destroy // the parameter buffers unless separate destruction is required. - if (ctx->hwctx->driver_quirks & + if (HAVE_VAAPI_1 || ctx->hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) goto fail; else goto fail_at_end; } - if (ctx->hwctx->driver_quirks & + if (HAVE_VAAPI_1 || ctx->hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) { for (i = 0; i < pic->nb_param_buffers; i++) { vas = vaDestroyBuffer(ctx->hwctx->display, diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c index f3afcc4f754ae..95a0f40419c0d 100644 --- a/libavfilter/vf_deinterlace_vaapi.c +++ b/libavfilter/vf_deinterlace_vaapi.c @@ -536,7 +536,7 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) goto fail_after_render; } - if (ctx->hwctx->driver_quirks & + if (HAVE_VAAPI_1 || ctx->hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) { vas = vaDestroyBuffer(ctx->hwctx->display, params_id); if (vas != VA_STATUS_SUCCESS) { diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c index 50be68eee0737..4c8f2cf4efd91 100644 --- a/libavfilter/vf_scale_vaapi.c +++ b/libavfilter/vf_scale_vaapi.c @@ -347,7 +347,7 @@ static int scale_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) goto fail_after_render; } - if (ctx->hwctx->driver_quirks & + if (HAVE_VAAPI_1 || ctx->hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) { vas = vaDestroyBuffer(ctx->hwctx->display, params_id); if (vas != VA_STATUS_SUCCESS) { From 2708c8e8efefaad337ccab1e3bf59dcde66c6bc5 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 1 Oct 2017 22:51:31 +0100 Subject: [PATCH 0599/2557] hwcontext_vaapi: Set message callbacks on internally-created devices The message callbacks are library-safe in libva2, so we can now use them. --- libavutil/hwcontext_vaapi.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 2260518ca6e4a..12f8ac93cd3ba 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -916,6 +916,22 @@ static void vaapi_device_free(AVHWDeviceContext *ctx) av_freep(&priv); } +#if HAVE_VAAPI_1 +static void vaapi_device_log_error(void *context, const char *message) +{ + AVHWDeviceContext *ctx = context; + + av_log(ctx, AV_LOG_ERROR, "libva: %s", message); +} + +static void vaapi_device_log_info(void *context, const char *message) +{ + AVHWDeviceContext *ctx = context; + + av_log(ctx, AV_LOG_VERBOSE, "libva: %s", message); +} +#endif + static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags) { @@ -985,6 +1001,11 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, return AVERROR(EINVAL); } +#if HAVE_VAAPI_1 + vaSetErrorCallback(display, &vaapi_device_log_error, ctx); + vaSetInfoCallback (display, &vaapi_device_log_info, ctx); +#endif + hwctx->display = display; vas = vaInitialize(display, &major, &minor); From 0af8a72174108b9bb482f1073a1e9a3bc258af51 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 24 Sep 2017 14:24:02 +0200 Subject: [PATCH 0600/2557] build: Drop support for legacy TI ARM compiler --- compat/tms470/math.h | 30 --------------------- configure | 58 ---------------------------------------- libavutil/intreadwrite.h | 2 +- libavutil/mem.h | 7 ----- 4 files changed, 1 insertion(+), 96 deletions(-) delete mode 100644 compat/tms470/math.h diff --git a/compat/tms470/math.h b/compat/tms470/math.h deleted file mode 100644 index b686d4d8a9451..0000000000000 --- a/compat/tms470/math.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBAV_COMPAT_TMS470_MATH_H -#define LIBAV_COMPAT_TMS470_MATH_H - -#include_next - -#undef INFINITY -#undef NAN - -#define INFINITY (*(const float*)((const unsigned []){ 0x7f800000 })) -#define NAN (*(const float*)((const unsigned []){ 0x7fc00000 })) - -#endif /* LIBAV_COMPAT_TMS470_MATH_H */ diff --git a/configure b/configure index 52232367950fc..edfe2a8375ace 100755 --- a/configure +++ b/configure @@ -3220,35 +3220,6 @@ suncc_flags(){ done } -tms470_flags(){ - for flag; do - case $flag in - -march=*|-mcpu=*) - case "${flag#*=}" in - armv7-a|cortex-a*) echo -mv=7a8 ;; - armv7-r|cortex-r*) echo -mv=7r4 ;; - armv7-m|cortex-m*) echo -mv=7m3 ;; - armv6*|arm11*) echo -mv=6 ;; - armv5*e|arm[79]*e*|arm9[24]6*|arm96*|arm102[26]) - echo -mv=5e ;; - armv4*|arm7*|arm9[24]*) echo -mv=4 ;; - esac - ;; - -mfpu=neon) echo --float_support=vfpv3 --neon ;; - -mfpu=vfp) echo --float_support=vfpv2 ;; - -mfpu=vfpv3) echo --float_support=vfpv3 ;; - -mfpu=vfpv3-d16) echo --float_support=vfpv3d16 ;; - -msoft-float) echo --float_support=vfplib ;; - -O[0-3]|-mf=*) echo $flag ;; - -g) echo -g -mn ;; - -pds=*) echo $flag ;; - -D*|-I*) echo $flag ;; - --gcc|--abi=*) echo $flag ;; - -me) echo $flag ;; - esac - done -} - probe_cc(){ pfx=$1 _cc=$2 @@ -3305,16 +3276,6 @@ probe_cc(){ _depflags='-MMD' _cflags_speed='-O3' _cflags_size='-Os' - elif $_cc -version 2>/dev/null | grep -Eq 'TMS470|TI ARM'; then - _type=tms470 - _ident=$($_cc -version | head -n1 | tr -s ' ') - _flags='--gcc --abi=eabi -me' - _cc_e='-ppl -fe=$@' - _cc_o='-fe=$@' - _depflags='-ppa -ppd=$(@:.o=.d)' - _cflags_speed='-O3 -mf=5' - _cflags_size='-O3 -mf=2' - _flags_filter=tms470_flags elif $_cc -v 2>&1 | grep -q clang; then _type=clang _ident=$($_cc --version 2>/dev/null | head -n1) @@ -3497,9 +3458,6 @@ fi if $ar 2>&1 | grep -q Microsoft; then arflags="-nologo" ar_o='-out:$@' -elif $ar 2>&1 | grep -q 'Texas Instruments'; then - arflags="rq" - ar_o='$@' elif $ar 2>&1 | grep -q 'Usage: ar.*-X.*any'; then arflags='-Xany -r -c' ar_o='$@' @@ -3518,10 +3476,6 @@ if test -n "$sysroot"; then add_cppflags --sysroot="$sysroot" add_ldflags --sysroot="$sysroot" ;; - tms470) - add_cppflags -I"$sysinclude" - add_ldflags --sysroot="$sysroot" - ;; esac fi @@ -4179,15 +4133,6 @@ case $libc_type in bionic) add_compat strtod.o strtod=avpriv_strtod ;; - glibc) - if enabled tms470; then - CPPFLAGS="-I${source_path}/compat/tms470 ${CPPFLAGS}" - add_cppflags -D__USER_LABEL_PREFIX__= - add_cppflags -D__builtin_memset=memset - add_cppflags -D__gnuc_va_list=va_list -D_VA_LIST_DEFINED - add_cflags -pds=48 # incompatible redefinition of macro - fi - ;; esac check_compile_assert flt_lim "float.h limits.h" "DBL_MAX == (double)DBL_MAX" || @@ -5030,9 +4975,6 @@ elif enabled armcc; then add_cflags -W${armcc_opt},--diag_suppress=3343 # hardfp compat add_cflags -W${armcc_opt},--diag_suppress=167 # pointer sign add_cflags -W${armcc_opt},--diag_suppress=513 # pointer sign -elif enabled tms470; then - add_cflags -pds=824 -pds=837 - disable inline_asm elif enabled pathscale; then add_cflags -fstrict-overflow -OPT:wrap_around_unsafe_opt=OFF disable inline_asm diff --git a/libavutil/intreadwrite.h b/libavutil/intreadwrite.h index a9763172a812b..84685f02ebb61 100644 --- a/libavutil/intreadwrite.h +++ b/libavutil/intreadwrite.h @@ -183,7 +183,7 @@ typedef union { * by per-arch headers. */ -#if defined(__GNUC__) && !defined(__TI_COMPILER_VERSION__) +#if defined(__GNUC__) union unaligned_64 { uint64_t l; } __attribute__((packed)) av_alias; union unaligned_32 { uint32_t l; } __attribute__((packed)) av_alias; diff --git a/libavutil/mem.h b/libavutil/mem.h index a03ba2f528b9a..0aee0e0d88611 100644 --- a/libavutil/mem.h +++ b/libavutil/mem.h @@ -41,13 +41,6 @@ #if defined(__ICC) && __ICC < 1200 || defined(__SUNPRO_C) #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v -#elif defined(__TI_COMPILER_VERSION__) - #define DECLARE_ALIGNED(n,t,v) \ - AV_PRAGMA(DATA_ALIGN(v,n)) \ - t __attribute__((aligned(n))) v - #define DECLARE_ASM_CONST(n,t,v) \ - AV_PRAGMA(DATA_ALIGN(v,n)) \ - static const t __attribute__((aligned(n))) v #elif defined(__GNUC__) || defined(__clang__) #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v From 9dc79b2943d99f256a3279f09580b27a95fb9aa8 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 6 Oct 2017 02:24:25 +0200 Subject: [PATCH 0601/2557] configure: Drop support for legacy PGI compiler --- configure | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/configure b/configure index edfe2a8375ace..ac7b40feba0bb 100755 --- a/configure +++ b/configure @@ -3172,17 +3172,6 @@ icl_flags(){ done } -pgi_flags(){ - for flag; do - case $flag in - -flto) echo -Mipa=fast,libopt,libinline,vestigial ;; - -fomit-frame-pointer) echo -Mnoframe ;; - -g) echo -gopt ;; - *) echo $flag ;; - esac - done -} - suncc_flags(){ for flag; do case $flag in @@ -3305,14 +3294,6 @@ probe_cc(){ _cflags_speed='-O2' _cflags_size='-Os' _flags_filter='filter_out -Wdisabled-optimization|-Wtype-limits|-fno-signed-zeros' - elif $_cc -V 2>&1 | grep -q Portland; then - _type=pgi - _ident="PGI $($_cc -V 2>&1 | awk '/^pgcc/ { print $2; exit }')" - opt_common='-alias=ansi -Mdse -Mlre -Mpre' - _cflags_speed="-O3 -Mautoinline -Munroll=c:4 $opt_common" - _cflags_size="-O2 -Munroll=c:1 $opt_common" - _cflags_noopt="-O1" - _flags_filter=pgi_flags elif $_cc 2>&1 | grep -q 'Microsoft.*ARM.*Assembler'; then _type=armasm _ident=$($_cc | head -n1) From 50e30d9bb71e1dff27be16c264fac90e362b9896 Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Tue, 24 Oct 2017 13:03:59 -0700 Subject: [PATCH 0602/2557] Don't use _tzcnt instrinics with clang for windows w/o BMI. Technically _tzcnt* intrinsics are only available when the BMI instruction set is present. However the instruction encoding degrades to "rep bsf" on older processors. Clang for Windows debatably restricts the _tzcnt* instrinics behind the __BMI__ architecture define, so check for its presence or exclude the usage of these intrinics when clang is present. See also: https://ffmpeg.org/pipermail/ffmpeg-devel/2015-November/183404.html https://bugs.llvm.org/show_bug.cgi?id=30506 http://lists.llvm.org/pipermail/cfe-dev/2016-October/051034.html Signed-off-by: Dale Curtis Reviewed-by: Matt Oliver Signed-off-by: Michael Niedermayer --- libavutil/x86/intmath.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavutil/x86/intmath.h b/libavutil/x86/intmath.h index e83971c084ce5..40743fd13ef22 100644 --- a/libavutil/x86/intmath.h +++ b/libavutil/x86/intmath.h @@ -47,7 +47,8 @@ static av_always_inline av_const int ff_log2_x86(unsigned int v) # endif # define ff_log2_16bit av_log2 -#if defined(__INTEL_COMPILER) || (defined(_MSC_VER) && (_MSC_VER >= 1700)) +#if defined(__INTEL_COMPILER) || (defined(_MSC_VER) && (_MSC_VER >= 1700) && \ + (defined(__BMI__) || !defined(__clang__))) # define ff_ctz(v) _tzcnt_u32(v) # if ARCH_X86_64 From e6debcaaed2290f6877809087a188db661ee1400 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 25 Oct 2017 19:26:58 +0200 Subject: [PATCH 0603/2557] tools/target_dec_fuzzer: Fix build after FF_INPUT_BUFFER_PADDING_SIZE was removed Signed-off-by: Michael Niedermayer --- tools/target_dec_fuzzer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index a8696f9fc7368..65b9f094f1cf2 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -99,7 +99,7 @@ static void FDBCreate(FuzzDataBuffer *FDB) { static void FDBDesroy(FuzzDataBuffer *FDB) { av_free(FDB->data_); } static void FDBRealloc(FuzzDataBuffer *FDB, size_t size) { - size_t needed = size + FF_INPUT_BUFFER_PADDING_SIZE; + size_t needed = size + AV_INPUT_BUFFER_PADDING_SIZE; av_assert0(needed > size); if (needed > FDB->size_) { av_free(FDB->data_); @@ -116,8 +116,8 @@ static void FDBPrepare(FuzzDataBuffer *FDB, AVPacket *dst, const uint8_t *data, FDBRealloc(FDB, size); memcpy(FDB->data_, data, size); size_t padd = FDB->size_ - size; - if (padd > FF_INPUT_BUFFER_PADDING_SIZE) - padd = FF_INPUT_BUFFER_PADDING_SIZE; + if (padd > AV_INPUT_BUFFER_PADDING_SIZE) + padd = AV_INPUT_BUFFER_PADDING_SIZE; memset(FDB->data_ + size, 0, padd); av_init_packet(dst); dst->data = FDB->data_; From c23209f63d51a33061f336c2a53e1dae664182d0 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 25 Oct 2017 19:27:29 +0200 Subject: [PATCH 0604/2557] tools/target_dec_fuzzer: Fix build after AV_CODEC_CAP_HWACCEL_VDPAU was removed Signed-off-by: Michael Niedermayer --- tools/target_dec_fuzzer.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index 65b9f094f1cf2..62d62a9de34f8 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -154,10 +154,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { av_log_set_level(AV_LOG_PANIC); } - // Unsupported - if (c->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU) - return 0; - switch (c->type) { case AVMEDIA_TYPE_AUDIO : decode_handler = avcodec_decode_audio4; break; case AVMEDIA_TYPE_VIDEO : decode_handler = avcodec_decode_video2; break; From 2aab7c2dfaca4386c38e5d565cd2bf73096bcc86 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Tue, 24 Oct 2017 12:38:30 +0530 Subject: [PATCH 0605/2557] avcodec/mips: Improve avc put mc 11, 31, 13 and 33 msa functions Remove loops and unroll as block sizes are known. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/h264qpel_msa.c | 400 ++++++++++++++++++++------------- 1 file changed, 240 insertions(+), 160 deletions(-) diff --git a/libavcodec/mips/h264qpel_msa.c b/libavcodec/mips/h264qpel_msa.c index f11fce8ff37cc..fcccb98ebdf84 100644 --- a/libavcodec/mips/h264qpel_msa.c +++ b/libavcodec/mips/h264qpel_msa.c @@ -171,23 +171,27 @@ static const uint8_t luma_mask_arr[16 * 8] = { out0_m; \ } ) -static void avc_luma_hv_qrt_4w_msa(const uint8_t *src_x, const uint8_t *src_y, - int32_t src_stride, uint8_t *dst, - int32_t dst_stride, int32_t height) +static void avc_luma_hv_qrt_4x4_msa(const uint8_t *src_x, const uint8_t *src_y, + uint8_t *dst, int32_t stride) { - uint32_t loop_cnt; - v16i8 src_hz0, src_hz1, src_hz2, src_hz3; - v16i8 src_vt0, src_vt1, src_vt2, src_vt3, src_vt4; - v16i8 src_vt5, src_vt6, src_vt7, src_vt8; - v16i8 mask0, mask1, mask2; - v8i16 hz_out0, hz_out1, vert_out0, vert_out1; - v8i16 out0, out1; + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; v16u8 out; + v16i8 src_hz0, src_hz1, src_hz2, src_hz3, src_vt7, src_vt8; + v16i8 src_vt0, src_vt1, src_vt2, src_vt3, src_vt4, src_vt5, src_vt6; + v16i8 src_vt10_r, src_vt32_r, src_vt54_r, src_vt76_r; + v16i8 mask0, mask1, mask2, filt0, filt1, filt2; + v8i16 hz_out0, hz_out1, vt_out0, vt_out1, out0, out1; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); - LD_SB5(src_y, src_stride, src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); - src_y += (5 * src_stride); + LD_SB5(src_y, stride, src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); + src_y += (5 * stride); src_vt0 = (v16i8) __msa_insve_w((v4i32) src_vt0, 1, (v4i32) src_vt1); src_vt1 = (v16i8) __msa_insve_w((v4i32) src_vt1, 1, (v4i32) src_vt2); @@ -196,149 +200,237 @@ static void avc_luma_hv_qrt_4w_msa(const uint8_t *src_x, const uint8_t *src_y, XORI_B4_128_SB(src_vt0, src_vt1, src_vt2, src_vt3); - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB4(src_x, src_stride, src_hz0, src_hz1, src_hz2, src_hz3); - src_x += (4 * src_stride); - - XORI_B4_128_SB(src_hz0, src_hz1, src_hz2, src_hz3); - - hz_out0 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src_hz0, - src_hz1, mask0, - mask1, mask2); - hz_out1 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src_hz2, - src_hz3, mask0, - mask1, mask2); - - SRARI_H2_SH(hz_out0, hz_out1, 5); - SAT_SH2_SH(hz_out0, hz_out1, 7); - - LD_SB4(src_y, src_stride, src_vt5, src_vt6, src_vt7, src_vt8); - src_y += (4 * src_stride); - - src_vt4 = (v16i8) __msa_insve_w((v4i32) src_vt4, 1, (v4i32) src_vt5); - src_vt5 = (v16i8) __msa_insve_w((v4i32) src_vt5, 1, (v4i32) src_vt6); - src_vt6 = (v16i8) __msa_insve_w((v4i32) src_vt6, 1, (v4i32) src_vt7); - src_vt7 = (v16i8) __msa_insve_w((v4i32) src_vt7, 1, (v4i32) src_vt8); - - XORI_B4_128_SB(src_vt4, src_vt5, src_vt6, src_vt7); + LD_SB4(src_x, stride, src_hz0, src_hz1, src_hz2, src_hz3); + XORI_B4_128_SB(src_hz0, src_hz1, src_hz2, src_hz3); + hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz1, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src_hz2, src_hz3, mask0, mask1, mask2); - /* filter calc */ - vert_out0 = AVC_CALC_DPADD_B_6PIX_2COEFF_R_SH(src_vt0, src_vt1, - src_vt2, src_vt3, - src_vt4, src_vt5); - vert_out1 = AVC_CALC_DPADD_B_6PIX_2COEFF_R_SH(src_vt2, src_vt3, - src_vt4, src_vt5, - src_vt6, src_vt7); + SRARI_H2_SH(hz_out0, hz_out1, 5); + SAT_SH2_SH(hz_out0, hz_out1, 7); - SRARI_H2_SH(vert_out0, vert_out1, 5); - SAT_SH2_SH(vert_out0, vert_out1, 7); + LD_SB4(src_y, stride, src_vt5, src_vt6, src_vt7, src_vt8); - out0 = __msa_srari_h((hz_out0 + vert_out0), 1); - out1 = __msa_srari_h((hz_out1 + vert_out1), 1); + src_vt4 = (v16i8) __msa_insve_w((v4i32) src_vt4, 1, (v4i32) src_vt5); + src_vt5 = (v16i8) __msa_insve_w((v4i32) src_vt5, 1, (v4i32) src_vt6); + src_vt6 = (v16i8) __msa_insve_w((v4i32) src_vt6, 1, (v4i32) src_vt7); + src_vt7 = (v16i8) __msa_insve_w((v4i32) src_vt7, 1, (v4i32) src_vt8); - SAT_SH2_SH(out0, out1, 7); - out = PCKEV_XORI128_UB(out0, out1); - ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); - dst += (4 * dst_stride); + XORI_B4_128_SB(src_vt4, src_vt5, src_vt6, src_vt7); + ILVR_B2_SB(src_vt1, src_vt0, src_vt3, src_vt2, src_vt10_r, src_vt32_r); + ILVR_B2_SB(src_vt5, src_vt4, src_vt7, src_vt6, src_vt54_r, src_vt76_r); + vt_out0 = AVC_DOT_SH3_SH(src_vt10_r, src_vt32_r, src_vt54_r, filt0, filt1, + filt2); + vt_out1 = AVC_DOT_SH3_SH(src_vt32_r, src_vt54_r, src_vt76_r, filt0, filt1, + filt2); + SRARI_H2_SH(vt_out0, vt_out1, 5); + SAT_SH2_SH(vt_out0, vt_out1, 7); + + out0 = __msa_srari_h((hz_out0 + vt_out0), 1); + out1 = __msa_srari_h((hz_out1 + vt_out1), 1); - src_vt3 = src_vt7; - src_vt1 = src_vt5; - src_vt0 = src_vt4; - src_vt4 = src_vt8; - src_vt2 = src_vt6; - } + SAT_SH2_SH(out0, out1, 7); + out = PCKEV_XORI128_UB(out0, out1); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, stride); } -static void avc_luma_hv_qrt_8w_msa(const uint8_t *src_x, const uint8_t *src_y, - int32_t src_stride, uint8_t *dst, - int32_t dst_stride, int32_t height) +static void avc_luma_hv_qrt_8x8_msa(const uint8_t *src_x, const uint8_t *src_y, + uint8_t *dst, int32_t stride) { - uint32_t loop_cnt; - v16i8 src_hz0, src_hz1, src_hz2, src_hz3; - v16i8 src_vt0, src_vt1, src_vt2, src_vt3, src_vt4; - v16i8 src_vt5, src_vt6, src_vt7, src_vt8; - v16i8 mask0, mask1, mask2; - v8i16 hz_out0, hz_out1, hz_out2, hz_out3; - v8i16 vert_out0, vert_out1, vert_out2, vert_out3; - v8i16 out0, out1, out2, out3; - v16u8 tmp0, tmp1; - - LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); - LD_SB5(src_y, src_stride, src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); - src_y += (5 * src_stride); - - src_vt0 = (v16i8) __msa_insve_d((v2i64) src_vt0, 1, (v2i64) src_vt1); - src_vt1 = (v16i8) __msa_insve_d((v2i64) src_vt1, 1, (v2i64) src_vt2); - src_vt2 = (v16i8) __msa_insve_d((v2i64) src_vt2, 1, (v2i64) src_vt3); - src_vt3 = (v16i8) __msa_insve_d((v2i64) src_vt3, 1, (v2i64) src_vt4); + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + v16u8 out0, out1; + v16i8 src_hz0, src_hz1, src_hz2, src_hz3, mask0, mask1, mask2; + v16i8 src_vt0, src_vt1, src_vt2, src_vt3, src_vt4, src_vt5, src_vt6; + v16i8 src_vt7, src_vt8, src_vt9, src_vt10, src_vt11, src_vt12; + v16i8 src_vt10_r, src_vt21_r, src_vt32_r, src_vt43_r, src_vt54_r; + v16i8 src_vt65_r, src_vt76_r, src_vt87_r, src_vt98_r, src_vt109_r; + v16i8 src_vt1110_r, src_vt1211_r, filt0, filt1, filt2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, vt_out0, vt_out1, vt_out2; + v8i16 vt_out3, tmp0, tmp1, tmp2, tmp3; - XORI_B4_128_SB(src_vt0, src_vt1, src_vt2, src_vt3); + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB4(src_x, src_stride, src_hz0, src_hz1, src_hz2, src_hz3); - XORI_B4_128_SB(src_hz0, src_hz1, src_hz2, src_hz3); - src_x += (4 * src_stride); + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + LD_SB5(src_y, stride, src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); + src_y += (5 * stride); - hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz0, mask0, mask1, mask2); - hz_out1 = AVC_HORZ_FILTER_SH(src_hz1, src_hz1, mask0, mask1, mask2); - hz_out2 = AVC_HORZ_FILTER_SH(src_hz2, src_hz2, mask0, mask1, mask2); - hz_out3 = AVC_HORZ_FILTER_SH(src_hz3, src_hz3, mask0, mask1, mask2); + XORI_B5_128_SB(src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); - SRARI_H4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 5); - SAT_SH4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 7); + LD_SB4(src_x, stride, src_hz0, src_hz1, src_hz2, src_hz3); + XORI_B4_128_SB(src_hz0, src_hz1, src_hz2, src_hz3); + src_x += (4 * stride); + + hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src_hz1, src_hz1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src_hz2, src_hz2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src_hz3, src_hz3, mask0, mask1, mask2); + + SRARI_H4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 5); + SAT_SH4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 7); + + LD_SB4(src_y, stride, src_vt5, src_vt6, src_vt7, src_vt8); + src_y += (4 * stride); + XORI_B4_128_SB(src_vt5, src_vt6, src_vt7, src_vt8); + + ILVR_B4_SB(src_vt1, src_vt0, src_vt2, src_vt1, src_vt3, src_vt2, src_vt4, + src_vt3, src_vt10_r, src_vt21_r, src_vt32_r, src_vt43_r); + ILVR_B4_SB(src_vt5, src_vt4, src_vt6, src_vt5, src_vt7, src_vt6, src_vt8, + src_vt7, src_vt54_r, src_vt65_r, src_vt76_r, src_vt87_r); + vt_out0 = AVC_DOT_SH3_SH(src_vt10_r, src_vt32_r, src_vt54_r, filt0, filt1, + filt2); + vt_out1 = AVC_DOT_SH3_SH(src_vt21_r, src_vt43_r, src_vt65_r, filt0, filt1, + filt2); + vt_out2 = AVC_DOT_SH3_SH(src_vt32_r, src_vt54_r, src_vt76_r, filt0, filt1, + filt2); + vt_out3 = AVC_DOT_SH3_SH(src_vt43_r, src_vt65_r, src_vt87_r, filt0, filt1, + filt2); + SRARI_H4_SH(vt_out0, vt_out1, vt_out2, vt_out3, 5); + SAT_SH4_SH(vt_out0, vt_out1, vt_out2, vt_out3, 7); + + tmp0 = __msa_srari_h((hz_out0 + vt_out0), 1); + tmp1 = __msa_srari_h((hz_out1 + vt_out1), 1); + tmp2 = __msa_srari_h((hz_out2 + vt_out2), 1); + tmp3 = __msa_srari_h((hz_out3 + vt_out3), 1); + + LD_SB4(src_x, stride, src_hz0, src_hz1, src_hz2, src_hz3); + XORI_B4_128_SB(src_hz0, src_hz1, src_hz2, src_hz3); - LD_SB4(src_y, src_stride, src_vt5, src_vt6, src_vt7, src_vt8); - src_y += (4 * src_stride); + SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + ST8x4_UB(out0, out1, dst, stride); + dst += (4 * stride); - src_vt4 = (v16i8) __msa_insve_d((v2i64) src_vt4, 1, (v2i64) src_vt5); - src_vt5 = (v16i8) __msa_insve_d((v2i64) src_vt5, 1, (v2i64) src_vt6); - src_vt6 = (v16i8) __msa_insve_d((v2i64) src_vt6, 1, (v2i64) src_vt7); - src_vt7 = (v16i8) __msa_insve_d((v2i64) src_vt7, 1, (v2i64) src_vt8); + LD_SB4(src_y, stride, src_vt9, src_vt10, src_vt11, src_vt12); + XORI_B4_128_SB(src_vt9, src_vt10, src_vt11, src_vt12); + + hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src_hz1, src_hz1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src_hz2, src_hz2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src_hz3, src_hz3, mask0, mask1, mask2); + + SRARI_H4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 5); + SAT_SH4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 7); + + ILVR_B4_SB(src_vt9, src_vt8, src_vt10, src_vt9, src_vt11, src_vt10, + src_vt12, src_vt11, src_vt98_r, src_vt109_r, src_vt1110_r, + src_vt1211_r); + vt_out0 = AVC_DOT_SH3_SH(src_vt54_r, src_vt76_r, src_vt98_r, filt0, filt1, + filt2); + vt_out1 = AVC_DOT_SH3_SH(src_vt65_r, src_vt87_r, src_vt109_r, filt0, filt1, + filt2); + vt_out2 = AVC_DOT_SH3_SH(src_vt76_r, src_vt98_r, src_vt1110_r, filt0, filt1, + filt2); + vt_out3 = AVC_DOT_SH3_SH(src_vt87_r, src_vt109_r, src_vt1211_r, filt0, + filt1, filt2); + SRARI_H4_SH(vt_out0, vt_out1, vt_out2, vt_out3, 5); + SAT_SH4_SH(vt_out0, vt_out1, vt_out2, vt_out3, 7); + + tmp0 = __msa_srari_h((hz_out0 + vt_out0), 1); + tmp1 = __msa_srari_h((hz_out1 + vt_out1), 1); + tmp2 = __msa_srari_h((hz_out2 + vt_out2), 1); + tmp3 = __msa_srari_h((hz_out3 + vt_out3), 1); + + SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + ST8x4_UB(out0, out1, dst, stride); + dst += (4 * stride); +} - XORI_B4_128_SB(src_vt4, src_vt5, src_vt6, src_vt7); +static void avc_luma_hv_qrt_16x16_msa(const uint8_t *src_x, + const uint8_t *src_y, uint8_t *dst, + int32_t stride) +{ + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + const uint8_t *src_x_tmp = src_x; + const uint8_t *src_y_tmp = src_y; + uint8_t *dst_tmp = dst; + uint32_t multiple8_cnt, loop_cnt; + v16u8 tmp0, tmp1; + v16i8 src_hz0, src_hz1, src_hz2, src_hz3, mask0, mask1, mask2; + v16i8 src_vt0, src_vt1, src_vt2, src_vt3, src_vt4, src_vt5, src_vt6; + v16i8 src_vt7, src_vt8; + v16i8 src_vt10_r, src_vt21_r, src_vt32_r, src_vt43_r, src_vt54_r; + v16i8 src_vt65_r, src_vt76_r, src_vt87_r, filt0, filt1, filt2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, vt_out0, vt_out1, vt_out2; + v8i16 vt_out3, out0, out1, out2, out3; - /* filter calc */ - AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src_vt0, src_vt1, src_vt2, src_vt3, - src_vt4, src_vt5, vert_out0, vert_out1); - AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src_vt2, src_vt3, src_vt4, src_vt5, - src_vt6, src_vt7, vert_out2, vert_out3); + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); - SRARI_H4_SH(vert_out0, vert_out1, vert_out2, vert_out3, 5); - SAT_SH4_SH(vert_out0, vert_out1, vert_out2, vert_out3, 7); + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); - out0 = __msa_srari_h((hz_out0 + vert_out0), 1); - out1 = __msa_srari_h((hz_out1 + vert_out1), 1); - out2 = __msa_srari_h((hz_out2 + vert_out2), 1); - out3 = __msa_srari_h((hz_out3 + vert_out3), 1); + for (multiple8_cnt = 2; multiple8_cnt--;) { + src_x = src_x_tmp; + src_y = src_y_tmp; + dst = dst_tmp; - SAT_SH4_SH(out0, out1, out2, out3, 7); - tmp0 = PCKEV_XORI128_UB(out0, out1); - tmp1 = PCKEV_XORI128_UB(out2, out3); - ST8x4_UB(tmp0, tmp1, dst, dst_stride); + LD_SB5(src_y, stride, src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); + src_y += (5 * stride); - dst += (4 * dst_stride); - src_vt3 = src_vt7; - src_vt1 = src_vt5; - src_vt5 = src_vt4; - src_vt4 = src_vt8; - src_vt2 = src_vt6; - src_vt0 = src_vt5; - } -} + XORI_B5_128_SB(src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); -static void avc_luma_hv_qrt_16w_msa(const uint8_t *src_x, const uint8_t *src_y, - int32_t src_stride, uint8_t *dst, - int32_t dst_stride, int32_t height) -{ - uint32_t multiple8_cnt; + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src_x, stride, src_hz0, src_hz1, src_hz2, src_hz3); + XORI_B4_128_SB(src_hz0, src_hz1, src_hz2, src_hz3); + src_x += (4 * stride); + + hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src_hz1, src_hz1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src_hz2, src_hz2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src_hz3, src_hz3, mask0, mask1, mask2); + SRARI_H4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 5); + SAT_SH4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 7); + + LD_SB4(src_y, stride, src_vt5, src_vt6, src_vt7, src_vt8); + src_y += (4 * stride); + + XORI_B4_128_SB(src_vt5, src_vt6, src_vt7, src_vt8); + ILVR_B4_SB(src_vt1, src_vt0, src_vt2, src_vt1, src_vt3, src_vt2, + src_vt4, src_vt3, src_vt10_r, src_vt21_r, src_vt32_r, + src_vt43_r); + ILVR_B4_SB(src_vt5, src_vt4, src_vt6, src_vt5, src_vt7, src_vt6, + src_vt8, src_vt7, src_vt54_r, src_vt65_r, src_vt76_r, + src_vt87_r); + vt_out0 = AVC_DOT_SH3_SH(src_vt10_r, src_vt32_r, src_vt54_r, filt0, + filt1, filt2); + vt_out1 = AVC_DOT_SH3_SH(src_vt21_r, src_vt43_r, src_vt65_r, filt0, + filt1, filt2); + vt_out2 = AVC_DOT_SH3_SH(src_vt32_r, src_vt54_r, src_vt76_r, filt0, + filt1, filt2); + vt_out3 = AVC_DOT_SH3_SH(src_vt43_r, src_vt65_r, src_vt87_r, filt0, + filt1, filt2); + SRARI_H4_SH(vt_out0, vt_out1, vt_out2, vt_out3, 5); + SAT_SH4_SH(vt_out0, vt_out1, vt_out2, vt_out3, 7); + + out0 = __msa_srari_h((hz_out0 + vt_out0), 1); + out1 = __msa_srari_h((hz_out1 + vt_out1), 1); + out2 = __msa_srari_h((hz_out2 + vt_out2), 1); + out3 = __msa_srari_h((hz_out3 + vt_out3), 1); + + SAT_SH4_SH(out0, out1, out2, out3, 7); + tmp0 = PCKEV_XORI128_UB(out0, out1); + tmp1 = PCKEV_XORI128_UB(out2, out3); + ST8x4_UB(tmp0, tmp1, dst, stride); + dst += (4 * stride); - for (multiple8_cnt = 2; multiple8_cnt--;) { - avc_luma_hv_qrt_8w_msa(src_x, src_y, src_stride, dst, dst_stride, - height); + src_vt0 = src_vt4; + src_vt1 = src_vt5; + src_vt2 = src_vt6; + src_vt3 = src_vt7; + src_vt4 = src_vt8; + } - src_x += 8; - src_y += 8; - dst += 8; + src_x_tmp += 8; + src_y_tmp += 8; + dst_tmp += 8; } } @@ -2531,90 +2623,78 @@ void ff_put_h264_qpel4_mc03_msa(uint8_t *dst, const uint8_t *src, void ff_put_h264_qpel16_mc11_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_hv_qrt_16w_msa(src - 2, - src - (stride * 2), stride, dst, stride, 16); + avc_luma_hv_qrt_16x16_msa(src - 2, src - (stride * 2), dst, stride); } void ff_put_h264_qpel16_mc31_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_hv_qrt_16w_msa(src - 2, - src - (stride * 2) + - sizeof(uint8_t), stride, dst, stride, 16); + avc_luma_hv_qrt_16x16_msa(src - 2, src - (stride * 2) + 1, dst, stride); } void ff_put_h264_qpel16_mc13_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_hv_qrt_16w_msa(src + stride - 2, - src - (stride * 2), stride, dst, stride, 16); + avc_luma_hv_qrt_16x16_msa(src + stride - 2, src - (stride * 2), dst, + stride); } void ff_put_h264_qpel16_mc33_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_hv_qrt_16w_msa(src + stride - 2, - src - (stride * 2) + - sizeof(uint8_t), stride, dst, stride, 16); + avc_luma_hv_qrt_16x16_msa(src + stride - 2, src - (stride * 2) + 1, dst, + stride); } void ff_put_h264_qpel8_mc11_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_hv_qrt_8w_msa(src - 2, src - (stride * 2), stride, dst, stride, 8); + avc_luma_hv_qrt_8x8_msa(src - 2, src - (stride * 2), dst, stride); } void ff_put_h264_qpel8_mc31_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_hv_qrt_8w_msa(src - 2, - src - (stride * 2) + - sizeof(uint8_t), stride, dst, stride, 8); + avc_luma_hv_qrt_8x8_msa(src - 2, src - (stride * 2) + 1, dst, stride); } void ff_put_h264_qpel8_mc13_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_hv_qrt_8w_msa(src + stride - 2, - src - (stride * 2), stride, dst, stride, 8); + avc_luma_hv_qrt_8x8_msa(src + stride - 2, src - (stride * 2), dst, stride); } void ff_put_h264_qpel8_mc33_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_hv_qrt_8w_msa(src + stride - 2, - src - (stride * 2) + - sizeof(uint8_t), stride, dst, stride, 8); + avc_luma_hv_qrt_8x8_msa(src + stride - 2, src - (stride * 2) + 1, dst, + stride); } void ff_put_h264_qpel4_mc11_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_hv_qrt_4w_msa(src - 2, src - (stride * 2), stride, dst, stride, 4); + avc_luma_hv_qrt_4x4_msa(src - 2, src - (stride * 2), dst, stride); } void ff_put_h264_qpel4_mc31_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_hv_qrt_4w_msa(src - 2, - src - (stride * 2) + - sizeof(uint8_t), stride, dst, stride, 4); + avc_luma_hv_qrt_4x4_msa(src - 2, src - (stride * 2) + 1, dst, stride); } void ff_put_h264_qpel4_mc13_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_hv_qrt_4w_msa(src + stride - 2, - src - (stride * 2), stride, dst, stride, 4); + avc_luma_hv_qrt_4x4_msa(src + stride - 2, src - (stride * 2), dst, stride); } void ff_put_h264_qpel4_mc33_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_hv_qrt_4w_msa(src + stride - 2, - src - (stride * 2) + - sizeof(uint8_t), stride, dst, stride, 4); + avc_luma_hv_qrt_4x4_msa(src + stride - 2, src - (stride * 2) + 1, dst, + stride); } void ff_put_h264_qpel16_mc21_msa(uint8_t *dst, const uint8_t *src, From ce0a52e9e92950be9350b09fbdc0b0cfdfb862ec Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Tue, 24 Oct 2017 12:40:42 +0530 Subject: [PATCH 0606/2557] avcodec/mips: Improve avc chroma copy and avg vert mc msa functions Replace generic with block size specific function. Load the specific destination bytes instead of MSA load and pack. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/h264chroma_msa.c | 627 ++++++++++++++----------------- 1 file changed, 275 insertions(+), 352 deletions(-) diff --git a/libavcodec/mips/h264chroma_msa.c b/libavcodec/mips/h264chroma_msa.c index 2a54675075c89..a5c333471b04a 100644 --- a/libavcodec/mips/h264chroma_msa.c +++ b/libavcodec/mips/h264chroma_msa.c @@ -1124,24 +1124,25 @@ static void avc_chroma_hz_and_aver_dst_8w_msa(uint8_t *src, uint8_t *dst, } } -static void avc_chroma_vt_and_aver_dst_2x2_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1) +static void avc_chroma_vt_and_aver_dst_2x2_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) { uint16_t out0, out1; - uint32_t load0, load1; v16i8 src0, src1, src2, tmp0, tmp1, res; v16u8 dst_data = { 0 }; + v8i16 out; v8u16 res_r; v16i8 coeff_vec0 = __msa_fill_b(coeff0); v16i8 coeff_vec1 = __msa_fill_b(coeff1); v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); - LD_SB3(src, src_stride, src0, src1, src2); - load0 = LW(dst); - load1 = LW(dst + dst_stride); + LD_SB3(src, stride, src0, src1, src2); + out0 = LH(dst); + out1 = LH(dst + stride); - INSERT_W2_UB(load0, load1, dst_data); + dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 0, out0); + dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 2, out1); ILVR_B2_SB(src1, src0, src2, src1, tmp0, tmp1); @@ -1151,20 +1152,20 @@ static void avc_chroma_vt_and_aver_dst_2x2_msa(uint8_t *src, int32_t src_stride, res_r = (v8u16) __msa_srari_h((v8i16) res_r, 6); res_r = __msa_sat_u_h(res_r, 7); res = __msa_pckev_b((v16i8) res_r, (v16i8) res_r); - dst_data = __msa_aver_u_b((v16u8) res, dst_data); - out0 = __msa_copy_u_h((v8i16) dst_data, 0); - out1 = __msa_copy_u_h((v8i16) dst_data, 2); + out = (v8i16) __msa_aver_u_b((v16u8) res, dst_data); + out0 = __msa_copy_u_h(out, 0); + out1 = __msa_copy_u_h(out, 2); SH(out0, dst); - dst += dst_stride; + dst += stride; SH(out1, dst); } -static void avc_chroma_vt_and_aver_dst_2x4_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1) +static void avc_chroma_vt_and_aver_dst_2x4_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) { - uint32_t load0, load1; + uint16_t tp0, tp1, tp2, tp3; v16i8 src0, src1, src2, src3, src4; v16u8 tmp0, tmp1, tmp2, tmp3; v8u16 res_r; @@ -1174,19 +1175,16 @@ static void avc_chroma_vt_and_aver_dst_2x4_msa(uint8_t *src, int32_t src_stride, v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); v16u8 dst_data = { 0 }; - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - - load0 = LW(dst); - load1 = LW(dst + dst_stride); - - dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 0, load0); - dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 1, load1); + LD_SB5(src, stride, src0, src1, src2, src3, src4); - load0 = LW(dst + 2 * dst_stride); - load1 = LW(dst + 3 * dst_stride); - - dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 2, load0); - dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 3, load1); + tp0 = LH(dst); + tp1 = LH(dst + stride); + tp2 = LH(dst + 2 * stride); + tp3 = LH(dst + 3 * stride); + dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 0, tp0); + dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 1, tp1); + dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 2, tp2); + dst_data = (v16u8) __msa_insert_h((v8i16) dst_data, 3, tp3); ILVR_B4_UB(src1, src0, src2, src1, src3, src2, src4, src3, tmp0, tmp1, tmp2, tmp3); @@ -1202,102 +1200,26 @@ static void avc_chroma_vt_and_aver_dst_2x4_msa(uint8_t *src, int32_t src_stride, res = (v8i16) __msa_pckev_b((v16i8) res_r, (v16i8) res_r); res = (v8i16) __msa_aver_u_b((v16u8) res, dst_data); - ST2x4_UB(res, 0, dst, dst_stride); - dst += (4 * dst_stride); -} - -static void avc_chroma_vt_and_aver_dst_2x8_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1) -{ - uint32_t load0, load1, load2, load3; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; - v16u8 tmp0, tmp1, tmp2, tmp3; - v8i16 res; - v8u16 res_r; - v16i8 coeff_vec0 = __msa_fill_b(coeff0); - v16i8 coeff_vec1 = __msa_fill_b(coeff1); - v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); - v16u8 dst_data0 = { 0 }; - v16u8 dst_data1 = { 0 }; - - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - src += (5 * src_stride); - LD_SB4(src, src_stride, src5, src6, src7, src8); - - LW4(dst, dst_stride, load0, load1, load2, load3); - - dst_data0 = (v16u8) __msa_insert_h((v8i16) dst_data0, 0, load0); - dst_data0 = (v16u8) __msa_insert_h((v8i16) dst_data0, 1, load1); - dst_data0 = (v16u8) __msa_insert_h((v8i16) dst_data0, 2, load2); - dst_data0 = (v16u8) __msa_insert_h((v8i16) dst_data0, 3, load3); - - LW4(dst + 4 * dst_stride, dst_stride, load0, load1, load2, load3); - - dst_data1 = (v16u8) __msa_insert_h((v8i16) dst_data1, 0, load0); - dst_data1 = (v16u8) __msa_insert_h((v8i16) dst_data1, 1, load1); - dst_data1 = (v16u8) __msa_insert_h((v8i16) dst_data1, 2, load2); - dst_data1 = (v16u8) __msa_insert_h((v8i16) dst_data1, 3, load3); - - ILVR_B4_UB(src1, src0, src2, src1, src3, src2, src4, src3, - tmp0, tmp1, tmp2, tmp3); - - ILVR_W2_UB(tmp1, tmp0, tmp3, tmp2, tmp0, tmp2); - - tmp0 = (v16u8) __msa_ilvr_d((v2i64) tmp2, (v2i64) tmp0); - - res_r = __msa_dotp_u_h(tmp0, coeff_vec); - res_r <<= 3; - res_r = (v8u16) __msa_srari_h((v8i16) res_r, 6); - res_r = __msa_sat_u_h(res_r, 7); - - res = (v8i16) __msa_pckev_b((v16i8) res_r, (v16i8) res_r); - res = (v8i16) __msa_aver_u_b((v16u8) res, dst_data0); - - ST2x4_UB(res, 0, dst, dst_stride); - dst += (4 * dst_stride); - - ILVR_B4_UB(src5, src4, src6, src5, src7, src6, src8, src7, - tmp0, tmp1, tmp2, tmp3); - - ILVR_W2_UB(tmp1, tmp0, tmp3, tmp2, tmp0, tmp2); - - tmp0 = (v16u8) __msa_ilvr_d((v2i64) tmp2, (v2i64) tmp0); - - res_r = __msa_dotp_u_h(tmp0, coeff_vec); - res_r <<= 3; - res_r = (v8u16) __msa_srari_h((v8i16) res_r, 6); - res_r = __msa_sat_u_h(res_r, 7); - - res = (v8i16) __msa_pckev_b((v16i8) res_r, (v16i8) res_r); - res = (v8i16) __msa_aver_u_b((v16u8) res, dst_data1); - - ST2x4_UB(res, 0, dst, dst_stride); + ST2x4_UB(res, 0, dst, stride); } -static void avc_chroma_vt_and_aver_dst_2w_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1, - int32_t height) +static void avc_chroma_vt_and_aver_dst_2w_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1, int32_t height) { if (2 == height) { - avc_chroma_vt_and_aver_dst_2x2_msa(src, src_stride, dst, dst_stride, - coeff0, coeff1); + avc_chroma_vt_and_aver_dst_2x2_msa(src, dst, stride, coeff0, coeff1); } else if (4 == height) { - avc_chroma_vt_and_aver_dst_2x4_msa(src, src_stride, dst, dst_stride, - coeff0, coeff1); - } else if (8 == height) { - avc_chroma_vt_and_aver_dst_2x8_msa(src, src_stride, dst, dst_stride, - coeff0, coeff1); + avc_chroma_vt_and_aver_dst_2x4_msa(src, dst, stride, coeff0, coeff1); } } -static void avc_chroma_vt_and_aver_dst_4x2_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1) +static void avc_chroma_vt_and_aver_dst_4x2_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) { uint32_t load0, load1; - v16i8 src0, src1, src2, tmp0, tmp1; + v16u8 src0, src1, src2, tmp0, tmp1; v16u8 dst_data = { 0 }; v8u16 res_r; v16u8 res; @@ -1305,128 +1227,184 @@ static void avc_chroma_vt_and_aver_dst_4x2_msa(uint8_t *src, int32_t src_stride, v16i8 coeff_vec1 = __msa_fill_b(coeff1); v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); - LD_SB3(src, src_stride, src0, src1, src2); + LD_UB3(src, stride, src0, src1, src2); - load0 = LW(dst); - load1 = LW(dst + dst_stride); + LW2(dst, stride, load0, load1); INSERT_W2_UB(load0, load1, dst_data); - ILVR_B2_SB(src1, src0, src2, src1, tmp0, tmp1); + ILVR_B2_UB(src1, src0, src2, src1, tmp0, tmp1); - tmp0 = (v16i8) __msa_ilvr_d((v2i64) tmp1, (v2i64) tmp0); + tmp0 = (v16u8) __msa_ilvr_d((v2i64) tmp1, (v2i64) tmp0); - res_r = __msa_dotp_u_h((v16u8) tmp0, coeff_vec); + res_r = __msa_dotp_u_h(tmp0, coeff_vec); res_r <<= 3; res_r = (v8u16) __msa_srari_h((v8i16) res_r, 6); res_r = __msa_sat_u_h(res_r, 7); res = (v16u8) __msa_pckev_b((v16i8) res_r, (v16i8) res_r); res = __msa_aver_u_b(res, dst_data); - ST4x2_UB(res, dst, dst_stride); + ST4x2_UB(res, dst, stride); } -static void avc_chroma_vt_and_aver_dst_4x4mul_msa(uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - uint32_t coeff0, - uint32_t coeff1, - int32_t height) +static void avc_chroma_vt_and_aver_dst_4x4_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) { - uint32_t load0, load1, row; - v16i8 src0, src1, src2, src3, src4; + uint32_t tp0, tp1, tp2, tp3; + v16u8 src0, src1, src2, src3, src4; v16u8 tmp0, tmp1, tmp2, tmp3; v16u8 dst0 = { 0 }; - v16u8 dst1 = { 0 }; v8u16 res0_r, res1_r; - v16u8 res0, res1; + v16u8 out; v16i8 coeff_vec0 = __msa_fill_b(coeff0); v16i8 coeff_vec1 = __msa_fill_b(coeff1); v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); - src0 = LD_SB(src); - src += src_stride; - - for (row = (height >> 2); row--;) { - LD_SB4(src, src_stride, src1, src2, src3, src4); - src += (4 * src_stride); - - load0 = LW(dst); - load1 = LW(dst + dst_stride); - - INSERT_W2_UB(load0, load1, dst0); - load0 = LW(dst + 2 * dst_stride); - load1 = LW(dst + 3 * dst_stride); - INSERT_W2_UB(load0, load1, dst1); - - ILVR_B4_UB(src1, src0, src2, src1, src3, src2, src4, src3, - tmp0, tmp1, tmp2, tmp3); - ILVR_D2_UB(tmp1, tmp0, tmp3, tmp2, tmp0, tmp2); - DOTP_UB2_UH(tmp0, tmp2, coeff_vec, coeff_vec, res0_r, res1_r); - - res0_r <<= 3; - res1_r <<= 3; + LD_UB5(src, stride, src0, src1, src2, src3, src4); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); + ILVR_B4_UB(src1, src0, src2, src1, src3, src2, src4, src3, tmp0, tmp1, tmp2, + tmp3); + ILVR_D2_UB(tmp1, tmp0, tmp3, tmp2, tmp0, tmp2); + DOTP_UB2_UH(tmp0, tmp2, coeff_vec, coeff_vec, res0_r, res1_r); + res0_r <<= 3; + res1_r <<= 3; + SRARI_H2_UH(res0_r, res1_r, 6); + SAT_UH2_UH(res0_r, res1_r, 7); + out = (v16u8) __msa_pckev_b((v16i8) res1_r, (v16i8) res0_r); + out = __msa_aver_u_b(out, dst0); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, stride); +} - SRARI_H2_UH(res0_r, res1_r, 6); - SAT_UH2_UH(res0_r, res1_r, 7); - PCKEV_B2_UB(res0_r, res0_r, res1_r, res1_r, res0, res1); - AVER_UB2_UB(res0, dst0, res1, dst1, res0, res1); +static void avc_chroma_vt_and_aver_dst_4x8_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) +{ + uint32_t tp0, tp1, tp2, tp3; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16u8 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, out0, out1; + v16u8 dst0 = { 0 }, dst1 = { 0 }; + v8u16 res0, res1, res2, res3; + v16i8 coeff_vec0 = __msa_fill_b(coeff0); + v16i8 coeff_vec1 = __msa_fill_b(coeff1); + v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); - ST4x4_UB(res0, res1, 0, 1, 0, 1, dst, dst_stride); - dst += (4 * dst_stride); - src0 = src4; - } + LD_UB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + LD_UB4(src, stride, src5, src6, src7, src8); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); + LW4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst1); + ILVR_B4_UB(src1, src0, src2, src1, src3, src2, src4, src3, tmp0, tmp1, tmp2, + tmp3); + ILVR_B4_UB(src5, src4, src6, src5, src7, src6, src8, src7, tmp4, tmp5, tmp6, + tmp7); + ILVR_D2_UB(tmp1, tmp0, tmp3, tmp2, tmp0, tmp2); + ILVR_D2_UB(tmp5, tmp4, tmp7, tmp6, tmp4, tmp6); + DOTP_UB2_UH(tmp0, tmp2, coeff_vec, coeff_vec, res0, res1); + DOTP_UB2_UH(tmp4, tmp6, coeff_vec, coeff_vec, res2, res3); + SLLI_4V(res0, res1, res2, res3, 3); + SRARI_H4_UH(res0, res1, res2, res3, 6); + SAT_UH4_UH(res0, res1, res2, res3, 7); + PCKEV_B2_UB(res1, res0, res3, res2, out0, out1); + AVER_UB2_UB(out0, dst0, out1, dst1, out0, out1); + ST4x8_UB(out0, out1, dst, stride); } -static void avc_chroma_vt_and_aver_dst_4w_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1, - int32_t height) +static void avc_chroma_vt_and_aver_dst_4w_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1, int32_t height) { if (2 == height) { - avc_chroma_vt_and_aver_dst_4x2_msa(src, src_stride, dst, dst_stride, - coeff0, coeff1); - } else { - avc_chroma_vt_and_aver_dst_4x4mul_msa(src, src_stride, dst, dst_stride, - coeff0, coeff1, height); + avc_chroma_vt_and_aver_dst_4x2_msa(src, dst, stride, coeff0, coeff1); + } else if (4 == height) { + avc_chroma_vt_and_aver_dst_4x4_msa(src, dst, stride, coeff0, coeff1); + } else if (8 == height) { + avc_chroma_vt_and_aver_dst_4x8_msa(src, dst, stride, coeff0, coeff1); } } -static void avc_chroma_vt_and_aver_dst_8w_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coeff0, uint32_t coeff1, - int32_t height) +static void avc_chroma_vt_and_aver_dst_8x4_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) { - uint32_t row; + uint64_t tp0, tp1, tp2, tp3; v16u8 src0, src1, src2, src3, src4; v16u8 out0, out1; v8u16 res0, res1, res2, res3; - v16u8 dst0, dst1, dst2, dst3; + v16u8 dst0 = { 0 }, dst1 = { 0 }; v16i8 coeff_vec0 = __msa_fill_b(coeff0); v16i8 coeff_vec1 = __msa_fill_b(coeff1); v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); - src0 = LD_UB(src); - src += src_stride; + LD_UB5(src, stride, src0, src1, src2, src3, src4); + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + ILVR_B4_UB(src1, src0, src2, src1, src3, src2, src4, src3, + src0, src1, src2, src3); + DOTP_UB4_UH(src0, src1, src2, src3, coeff_vec, coeff_vec, coeff_vec, + coeff_vec, res0, res1, res2, res3); + SLLI_4V(res0, res1, res2, res3, 3); + SRARI_H4_UH(res0, res1, res2, res3, 6); + SAT_UH4_UH(res0, res1, res2, res3, 7); + PCKEV_B2_UB(res1, res0, res3, res2, out0, out1); + AVER_UB2_UB(out0, dst0, out1, dst1, out0, out1); + ST8x4_UB(out0, out1, dst, stride); +} - for (row = height >> 2; row--;) { - LD_UB4(src, src_stride, src1, src2, src3, src4); - src += (4 * src_stride); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - ILVR_B4_UB(src1, src0, src2, src1, src3, src2, src4, src3, - src0, src1, src2, src3); - DOTP_UB4_UH(src0, src1, src2, src3, coeff_vec, coeff_vec, coeff_vec, - coeff_vec, res0, res1, res2, res3); - SLLI_4V(res0, res1, res2, res3, 3); - SRARI_H4_UH(res0, res1, res2, res3, 6); - SAT_UH4_UH(res0, res1, res2, res3, 7); - PCKEV_B2_UB(res1, res0, res3, res2, out0, out1); - PCKEV_D2_UB(dst1, dst0, dst3, dst2, dst0, dst1); - AVER_UB2_UB(out0, dst0, out1, dst1, out0, out1); - ST8x4_UB(out0, out1, dst, dst_stride); +static void avc_chroma_vt_and_aver_dst_8x8_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1) +{ + uint64_t tp0, tp1, tp2, tp3; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16u8 out0, out1, out2, out3; + v16u8 dst0 = { 0 }, dst1 = { 0 }, dst2 = { 0 }, dst3 = { 0 }; + v8u16 res0, res1, res2, res3, res4, res5, res6, res7; + v16i8 coeff_vec0 = __msa_fill_b(coeff0); + v16i8 coeff_vec1 = __msa_fill_b(coeff1); + v16u8 coeff_vec = (v16u8) __msa_ilvr_b(coeff_vec0, coeff_vec1); - dst += (4 * dst_stride); - src0 = src4; + LD_UB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + LD_UB4(src, stride, src5, src6, src7, src8); + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + LD4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst2); + INSERT_D2_UB(tp2, tp3, dst3); + ILVR_B4_UB(src1, src0, src2, src1, src3, src2, src4, src3, + src0, src1, src2, src3); + ILVR_B4_UB(src5, src4, src6, src5, src7, src6, src8, src7, + src4, src5, src6, src7); + DOTP_UB4_UH(src0, src1, src2, src3, coeff_vec, coeff_vec, coeff_vec, + coeff_vec, res0, res1, res2, res3); + DOTP_UB4_UH(src4, src5, src6, src7, coeff_vec, coeff_vec, coeff_vec, + coeff_vec, res4, res5, res6, res7); + SLLI_4V(res0, res1, res2, res3, 3); + SLLI_4V(res4, res5, res6, res7, 3); + SRARI_H4_UH(res0, res1, res2, res3, 6); + SRARI_H4_UH(res4, res5, res6, res7, 6); + SAT_UH4_UH(res0, res1, res2, res3, 7); + SAT_UH4_UH(res0, res1, res2, res3, 7); + PCKEV_B2_UB(res1, res0, res3, res2, out0, out1); + PCKEV_B2_UB(res5, res4, res7, res6, out2, out3); + AVER_UB2_UB(out0, dst0, out1, dst1, out0, out1); + AVER_UB2_UB(out2, dst2, out3, dst3, out2, out3); + ST8x8_UB(out0, out1, out2, out3, dst, stride); +} + +static void avc_chroma_vt_and_aver_dst_8w_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coeff0, + uint32_t coeff1, int32_t height) +{ + if (4 == height) { + avc_chroma_vt_and_aver_dst_8x4_msa(src, dst, stride, coeff0, coeff1); + } else if (8 == height) { + avc_chroma_vt_and_aver_dst_8x8_msa(src, dst, stride, coeff0, coeff1); } } @@ -1771,160 +1749,115 @@ static void avc_chroma_hv_and_aver_dst_8w_msa(uint8_t *src, int32_t src_stride, } } -static void copy_width8_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, +static void copy_width4_msa(uint8_t *src, uint8_t *dst, int32_t stride, int32_t height) { - int32_t cnt; - uint64_t out0, out1, out2, out3, out4, out5, out6, out7; - v16u8 src0, src1, src2, src3, src4, src5, src6, src7; + uint32_t tp0, tp1, tp2, tp3, tp4, tp5, tp6, tp7; - if (0 == height % 12) { - for (cnt = (height / 12); cnt--;) { - LD_UB8(src, src_stride, - src0, src1, src2, src3, src4, src5, src6, src7); - src += (8 * src_stride); - - out0 = __msa_copy_u_d((v2i64) src0, 0); - out1 = __msa_copy_u_d((v2i64) src1, 0); - out2 = __msa_copy_u_d((v2i64) src2, 0); - out3 = __msa_copy_u_d((v2i64) src3, 0); - out4 = __msa_copy_u_d((v2i64) src4, 0); - out5 = __msa_copy_u_d((v2i64) src5, 0); - out6 = __msa_copy_u_d((v2i64) src6, 0); - out7 = __msa_copy_u_d((v2i64) src7, 0); - - SD4(out0, out1, out2, out3, dst, dst_stride); - dst += (4 * dst_stride); - SD4(out4, out5, out6, out7, dst, dst_stride); - dst += (4 * dst_stride); - - LD_UB4(src, src_stride, src0, src1, src2, src3); - src += (4 * src_stride); - - out0 = __msa_copy_u_d((v2i64) src0, 0); - out1 = __msa_copy_u_d((v2i64) src1, 0); - out2 = __msa_copy_u_d((v2i64) src2, 0); - out3 = __msa_copy_u_d((v2i64) src3, 0); - - SD4(out0, out1, out2, out3, dst, dst_stride); - dst += (4 * dst_stride); - } - } else if (0 == height % 8) { - for (cnt = height >> 3; cnt--;) { - LD_UB8(src, src_stride, - src0, src1, src2, src3, src4, src5, src6, src7); - src += (8 * src_stride); - - out0 = __msa_copy_u_d((v2i64) src0, 0); - out1 = __msa_copy_u_d((v2i64) src1, 0); - out2 = __msa_copy_u_d((v2i64) src2, 0); - out3 = __msa_copy_u_d((v2i64) src3, 0); - out4 = __msa_copy_u_d((v2i64) src4, 0); - out5 = __msa_copy_u_d((v2i64) src5, 0); - out6 = __msa_copy_u_d((v2i64) src6, 0); - out7 = __msa_copy_u_d((v2i64) src7, 0); - - SD4(out0, out1, out2, out3, dst, dst_stride); - dst += (4 * dst_stride); - SD4(out4, out5, out6, out7, dst, dst_stride); - dst += (4 * dst_stride); - } - } else if (0 == height % 4) { - for (cnt = (height / 4); cnt--;) { - LD_UB4(src, src_stride, src0, src1, src2, src3); - src += (4 * src_stride); - out0 = __msa_copy_u_d((v2i64) src0, 0); - out1 = __msa_copy_u_d((v2i64) src1, 0); - out2 = __msa_copy_u_d((v2i64) src2, 0); - out3 = __msa_copy_u_d((v2i64) src3, 0); - - SD4(out0, out1, out2, out3, dst, dst_stride); - dst += (4 * dst_stride); - } - } else if (0 == height % 2) { - for (cnt = (height / 2); cnt--;) { - LD_UB2(src, src_stride, src0, src1); - src += (2 * src_stride); - out0 = __msa_copy_u_d((v2i64) src0, 0); - out1 = __msa_copy_u_d((v2i64) src1, 0); - - SD(out0, dst); - dst += dst_stride; - SD(out1, dst); - dst += dst_stride; - } + if (8 == height) { + LW4(src, stride, tp0, tp1, tp2, tp3); + src += 4 * stride; + LW4(src, stride, tp4, tp5, tp6, tp7); + SW4(tp0, tp1, tp2, tp3, dst, stride); + dst += 4 * stride; + SW4(tp4, tp5, tp6, tp7, dst, stride); + } else if (4 == height) { + LW4(src, stride, tp0, tp1, tp2, tp3); + SW4(tp0, tp1, tp2, tp3, dst, stride); + } else if (2 == height) { + LW2(src, stride, tp0, tp1); + SW(tp0, dst); + dst += stride; + SW(tp1, dst); } } -static void avg_width4_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - int32_t height) +static void copy_width8_msa(uint8_t *src, uint8_t *dst, int32_t stride, + int32_t height) { - int32_t cnt; - uint32_t out0, out1, out2, out3; - v16u8 src0, src1, src2, src3; - v16u8 dst0, dst1, dst2, dst3; - - if (0 == (height % 4)) { - for (cnt = (height / 4); cnt--;) { - LD_UB4(src, src_stride, src0, src1, src2, src3); - src += (4 * src_stride); - - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); + uint64_t src0, src1, src2, src3, src4, src5, src6, src7; - AVER_UB4_UB(src0, dst0, src1, dst1, src2, dst2, src3, dst3, - dst0, dst1, dst2, dst3); - - out0 = __msa_copy_u_w((v4i32) dst0, 0); - out1 = __msa_copy_u_w((v4i32) dst1, 0); - out2 = __msa_copy_u_w((v4i32) dst2, 0); - out3 = __msa_copy_u_w((v4i32) dst3, 0); - SW4(out0, out1, out2, out3, dst, dst_stride); - dst += (4 * dst_stride); - } - } else if (0 == (height % 2)) { - for (cnt = (height / 2); cnt--;) { - LD_UB2(src, src_stride, src0, src1); - src += (2 * src_stride); - - LD_UB2(dst, dst_stride, dst0, dst1); - - AVER_UB2_UB(src0, dst0, src1, dst1, dst0, dst1); - - out0 = __msa_copy_u_w((v4i32) dst0, 0); - out1 = __msa_copy_u_w((v4i32) dst1, 0); - SW(out0, dst); - dst += dst_stride; - SW(out1, dst); - dst += dst_stride; - } + if (8 == height) { + LD4(src, stride, src0, src1, src2, src3); + src += 4 * stride; + LD4(src, stride, src4, src5, src6, src7); + SD4(src0, src1, src2, src3, dst, stride); + dst += 4 * stride; + SD4(src4, src5, src6, src7, dst, stride); + } else if (4 == height) { + LD4(src, stride, src0, src1, src2, src3); + SD4(src0, src1, src2, src3, dst, stride); } } -static void avg_width8_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, +static void avg_width4_msa(uint8_t *src, uint8_t *dst, int32_t stride, int32_t height) { - int32_t cnt; - uint64_t out0, out1, out2, out3; - v16u8 src0, src1, src2, src3; - v16u8 dst0, dst1, dst2, dst3; - - for (cnt = (height / 4); cnt--;) { - LD_UB4(src, src_stride, src0, src1, src2, src3); - src += (4 * src_stride); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); + uint32_t tp0, tp1, tp2, tp3; + v16u8 src0 = { 0 }, src1 = { 0 }, dst0 = { 0 }, dst1 = { 0 }; + + if (8 == height) { + LW4(src, stride, tp0, tp1, tp2, tp3); + src += 4 * stride; + INSERT_W4_UB(tp0, tp1, tp2, tp3, src0); + LW4(src, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, src1); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); + LW4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst1); + AVER_UB2_UB(src0, dst0, src1, dst1, dst0, dst1); + ST4x8_UB(dst0, dst1, dst, stride); + } else if (4 == height) { + LW4(src, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, src0); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); + dst0 = __msa_aver_u_b(src0, dst0); + ST4x4_UB(dst0, dst0, 0, 1, 2, 3, dst, stride); + } else if (2 == height) { + LW2(src, stride, tp0, tp1); + INSERT_W2_UB(tp0, tp1, src0); + LW2(dst, stride, tp0, tp1); + INSERT_W2_UB(tp0, tp1, dst0); + dst0 = __msa_aver_u_b(src0, dst0); + ST4x2_UB(dst0, dst, stride); + } +} - AVER_UB4_UB(src0, dst0, src1, dst1, src2, dst2, src3, dst3, - dst0, dst1, dst2, dst3); +static void avg_width8_msa(uint8_t *src, uint8_t *dst, int32_t stride, + int32_t height) +{ + uint64_t tp0, tp1, tp2, tp3, tp4, tp5, tp6, tp7; + v16u8 src0 = { 0 }, src1 = { 0 }, src2 = { 0 }, src3 = { 0 }; + v16u8 dst0 = { 0 }, dst1 = { 0 }, dst2 = { 0 }, dst3 = { 0 }; - out0 = __msa_copy_u_d((v2i64) dst0, 0); - out1 = __msa_copy_u_d((v2i64) dst1, 0); - out2 = __msa_copy_u_d((v2i64) dst2, 0); - out3 = __msa_copy_u_d((v2i64) dst3, 0); - SD4(out0, out1, out2, out3, dst, dst_stride); - dst += (4 * dst_stride); + if (8 == height) { + LD4(src, stride, tp0, tp1, tp2, tp3); + src += 4 * stride; + LD4(src, stride, tp4, tp5, tp6, tp7); + INSERT_D2_UB(tp0, tp1, src0); + INSERT_D2_UB(tp2, tp3, src1); + INSERT_D2_UB(tp4, tp5, src2); + INSERT_D2_UB(tp6, tp7, src3); + LD4(dst, stride, tp0, tp1, tp2, tp3); + LD4(dst + 4 * stride, stride, tp4, tp5, tp6, tp7); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + INSERT_D2_UB(tp4, tp5, dst2); + INSERT_D2_UB(tp6, tp7, dst3); + AVER_UB4_UB(src0, dst0, src1, dst1, src2, dst2, src3, dst3, dst0, dst1, + dst2, dst3); + ST8x8_UB(dst0, dst1, dst2, dst3, dst, stride); + } else if (4 == height) { + LD4(src, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, src0); + INSERT_D2_UB(tp2, tp3, src1); + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + AVER_UB2_UB(src0, dst0, src1, dst1, dst0, dst1); + ST8x4_UB(dst0, dst1, dst, stride); } } @@ -1940,15 +1873,13 @@ void ff_put_h264_chroma_mc8_msa(uint8_t *dst, uint8_t *src, } else if (y) { avc_chroma_vt_8w_msa(src, dst, stride, y, (8 - y), height); } else { - copy_width8_msa(src, stride, dst, stride, height); + copy_width8_msa(src, dst, stride, height); } } void ff_put_h264_chroma_mc4_msa(uint8_t *dst, uint8_t *src, ptrdiff_t stride, int height, int x, int y) { - int32_t cnt; - av_assert2(x < 8 && y < 8 && x >= 0 && y >= 0); if (x && y) { @@ -1958,12 +1889,7 @@ void ff_put_h264_chroma_mc4_msa(uint8_t *dst, uint8_t *src, } else if (y) { avc_chroma_vt_4w_msa(src, dst, stride, y, (8 - y), height); } else { - for (cnt = height; cnt--;) { - *((uint32_t *) dst) = *((uint32_t *) src); - - src += stride; - dst += stride; - } + copy_width4_msa(src, dst, stride, height); } } @@ -2003,10 +1929,9 @@ void ff_avg_h264_chroma_mc8_msa(uint8_t *dst, uint8_t *src, } else if (x) { avc_chroma_hz_and_aver_dst_8w_msa(src, dst, stride, x, (8 - x), height); } else if (y) { - avc_chroma_vt_and_aver_dst_8w_msa(src, stride, dst, - stride, y, (8 - y), height); + avc_chroma_vt_and_aver_dst_8w_msa(src, dst, stride, y, (8 - y), height); } else { - avg_width8_msa(src, stride, dst, stride, height); + avg_width8_msa(src, dst, stride, height); } } @@ -2022,10 +1947,9 @@ void ff_avg_h264_chroma_mc4_msa(uint8_t *dst, uint8_t *src, } else if (x) { avc_chroma_hz_and_aver_dst_4w_msa(src, dst, stride, x, (8 - x), height); } else if (y) { - avc_chroma_vt_and_aver_dst_4w_msa(src, stride, dst, - stride, y, (8 - y), height); + avc_chroma_vt_and_aver_dst_4w_msa(src, dst, stride, y, (8 - y), height); } else { - avg_width4_msa(src, stride, dst, stride, height); + avg_width4_msa(src, dst, stride, height); } } @@ -2043,8 +1967,7 @@ void ff_avg_h264_chroma_mc2_msa(uint8_t *dst, uint8_t *src, } else if (x) { avc_chroma_hz_and_aver_dst_2w_msa(src, dst, stride, x, (8 - x), height); } else if (y) { - avc_chroma_vt_and_aver_dst_2w_msa(src, stride, dst, - stride, y, (8 - y), height); + avc_chroma_vt_and_aver_dst_2w_msa(src, dst, stride, y, (8 - y), height); } else { for (cnt = height; cnt--;) { dst[0] = (dst[0] + src[0] + 1) >> 1; From 736a48901fa0061f52d3f6679546d4d6b5fdb510 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Tue, 24 Oct 2017 12:41:30 +0530 Subject: [PATCH 0607/2557] avcodec/mips: Improve hevc bi weighted hv mc msa functions Use immediate unsigned saturation for clip to max saving one vector register. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_biw_msa.c | 706 ++++++++++++++++++---------- libavutil/mips/generic_macros_msa.h | 35 ++ 2 files changed, 489 insertions(+), 252 deletions(-) diff --git a/libavcodec/mips/hevc_mc_biw_msa.c b/libavcodec/mips/hevc_mc_biw_msa.c index 05a28ece44f33..458e73d865b9b 100644 --- a/libavcodec/mips/hevc_mc_biw_msa.c +++ b/libavcodec/mips/hevc_mc_biw_msa.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Manojkumar Bhosale (Manojkumar.Bhosale@imgtec.com) + * Copyright (c) 2015 - 2017 Manojkumar Bhosale (Manojkumar.Bhosale@imgtec.com) * * This file is part of FFmpeg. * @@ -22,6 +22,12 @@ #include "libavcodec/mips/hevcdsp_mips.h" #include "libavcodec/mips/hevc_macros_msa.h" +static const uint8_t ff_hevc_mask_arr[16 * 2] __attribute__((aligned(0x40))) = { + /* 8 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 +}; + #define HEVC_BIW_RND_CLIP2(in0, in1, vec0, vec1, wgt, rnd, offset, \ out0_r, out1_r, out0_l, out1_l) \ { \ @@ -1831,23 +1837,23 @@ static void hevc_hv_biwgt_8t_4w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; - v8i16 in0, in1; + uint64_t tp0, tp1; + int32_t offset, weight; + v16u8 out; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v8i16 in0 = { 0 }, in1 = { 0 }; v8i16 filt0, filt1, filt2, filt3; - v4i32 filt_h0, filt_h1, filt_h2, filt_h3; + v8i16 filt_h0, filt_h1, filt_h2, filt_h3; v16i8 mask1, mask2, mask3; - v8i16 filter_vec, const_vec; + v8i16 filter_vec, weight_vec; v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; v8i16 dst30, dst41, dst52, dst63, dst66, dst87; - v4i32 dst0_r, dst1_r; - v4i32 tmp1, tmp2; - v4i32 weight_vec0, weight_vec1, offset_vec, rnd_vec; - v8i16 dst10_r, dst32_r, dst54_r, dst76_r; - v8i16 dst21_r, dst43_r, dst65_r, dst87_r; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; - v8u16 mask4 = { 0, 4, 1, 5, 2, 6, 3, 7 }; + v8i16 tmp0, tmp1, tmp2, tmp3; + v8i16 dst10, dst32, dst54, dst76; + v8i16 dst21, dst43, dst65, dst97, dst108, dst109, dst98; + v4i32 offset_vec, rnd_vec, const_vec, dst0, dst1, dst2, dst3; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); src0_ptr -= ((3 * src_stride) + 3); @@ -1855,10 +1861,9 @@ static void hevc_hv_biwgt_8t_4w_msa(uint8_t *src0_ptr, SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W4_SW(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); mask1 = mask0 + 2; mask2 = mask0 + 4; @@ -1866,13 +1871,14 @@ static void hevc_hv_biwgt_8t_4w_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; + weight = weight0 | (weight1 << 16); - const_vec = __msa_ldi_h(128); + const_vec = __msa_fill_w((128 * weight1)); const_vec <<= 6; offset_vec = __msa_fill_w(offset); - weight_vec0 = __msa_fill_w(weight0); - weight_vec1 = __msa_fill_w(weight1); rnd_vec = __msa_fill_w(rnd_val + 1); + offset_vec += const_vec; + weight_vec = (v8i16) __msa_fill_w(weight); LD_SB7(src0_ptr, src_stride, src0, src1, src2, src3, src4, src5, src6); src0_ptr += (7 * src_stride); @@ -1886,70 +1892,77 @@ static void hevc_hv_biwgt_8t_4w_msa(uint8_t *src0_ptr, VSHF_B4_SB(src3, src6, mask0, mask1, mask2, mask3, vec12, vec13, vec14, vec15); - dst30 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst30, dst30, dst30, dst30); - dst41 = const_vec; - DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, - dst41, dst41, dst41, dst41); - dst52 = const_vec; - DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, - dst52, dst52, dst52, dst52); - dst63 = const_vec; - DPADD_SB4_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, filt3, - dst63, dst63, dst63, dst63); - - ILVR_H3_SH(dst41, dst30, dst52, dst41, dst63, dst52, - dst10_r, dst21_r, dst32_r); - dst43_r = __msa_ilvl_h(dst41, dst30); - dst54_r = __msa_ilvl_h(dst52, dst41); - dst65_r = __msa_ilvl_h(dst63, dst52); - dst66 = (v8i16) __msa_splati_d((v2i64) dst63, 1); + dst30 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst41 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst52 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst63 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, + filt3); - for (loop_cnt = height >> 1; loop_cnt--;) { - LD_SB2(src0_ptr, src_stride, src7, src8); - src0_ptr += (2 * src_stride); - LD_SH2(src1_ptr, src2_stride, in0, in1); - src1_ptr += (2 * src2_stride); + ILVRL_H2_SH(dst41, dst30, dst10, dst43); + ILVRL_H2_SH(dst52, dst41, dst21, dst54); + ILVRL_H2_SH(dst63, dst52, dst32, dst65); - in0 = (v8i16) __msa_ilvr_d((v2i64) in1, (v2i64) in0); - XORI_B2_128_SB(src7, src8); + dst66 = (v8i16) __msa_splati_d((v2i64) dst63, 1); - VSHF_B4_SB(src7, src8, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); - dst87 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst87, dst87, dst87, dst87); - dst76_r = __msa_ilvr_h(dst87, dst66); - dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, - filt_h0, filt_h1, filt_h2, filt_h3); - dst87_r = __msa_vshf_h((v8i16) mask4, dst87, dst87); - dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, - filt_h0, filt_h1, filt_h2, filt_h3); + for (loop_cnt = height >> 2; loop_cnt--;) { + LD_SB4(src0_ptr, src_stride, src7, src8, src9, src10); + src0_ptr += (4 * src_stride); + XORI_B4_128_SB(src7, src8, src9, src10); - dst0_r >>= 6; - dst1_r >>= 6; + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in0); + src1_ptr += (2 * src2_stride); + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in1); + src1_ptr += (2 * src2_stride); - ILVRL_H2_SW(in0, in0, tmp1, tmp2); - tmp1 = __msa_dpadd_s_w(offset_vec, (v8i16) tmp1, (v8i16) weight_vec0); - tmp2 = __msa_dpadd_s_w(offset_vec, (v8i16) tmp2, (v8i16) weight_vec0); - tmp1 += dst0_r * weight_vec1; - tmp2 += dst1_r * weight_vec1; - SRAR_W2_SW(tmp1, tmp2, rnd_vec); - tmp1 = CLIP_SW_0_255(tmp1); - tmp2 = CLIP_SW_0_255(tmp2); - - HEVC_PCK_SW_SB2(tmp2, tmp1, tmp1); - ST4x2_UB(tmp1, dst, dst_stride); - dst += (2 * dst_stride); + VSHF_B4_SB(src7, src9, mask0, mask1, mask2, mask3, + vec0, vec1, vec2, vec3); + VSHF_B4_SB(src8, src10, mask0, mask1, mask2, mask3, + vec4, vec5, vec6, vec7); + dst97 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst108 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + + dst76 = __msa_ilvr_h(dst97, dst66); + ILVRL_H2_SH(dst108, dst97, dst87, dst109); + dst66 = (v8i16) __msa_splati_d((v2i64) dst97, 1); + dst98 = __msa_ilvr_h(dst66, dst108); + + dst0 = HEVC_FILT_8TAP(dst10, dst32, dst54, dst76, filt_h0, filt_h1, + filt_h2, filt_h3); + dst1 = HEVC_FILT_8TAP(dst21, dst43, dst65, dst87, filt_h0, filt_h1, + filt_h2, filt_h3); + dst2 = HEVC_FILT_8TAP(dst32, dst54, dst76, dst98, filt_h0, filt_h1, + filt_h2, filt_h3); + dst3 = HEVC_FILT_8TAP(dst43, dst65, dst87, dst109, filt_h0, filt_h1, + filt_h2, filt_h3); + SRA_4V(dst0, dst1, dst2, dst3, 6); + PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp1, tmp3); + ILVRL_H2_SH(tmp1, in0, tmp0, tmp1); + ILVRL_H2_SH(tmp3, in1, tmp2, tmp3); + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + CLIP_SW4_0_255_MAX_SATU(dst0, dst1, dst2, dst3); + PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp0, tmp1); + out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); + dst += (4 * dst_stride); - dst10_r = dst32_r; - dst32_r = dst54_r; - dst54_r = dst76_r; - dst21_r = dst43_r; - dst43_r = dst65_r; - dst65_r = dst87_r; - dst66 = (v8i16) __msa_splati_d((v2i64) dst87, 1); + dst10 = dst54; + dst32 = dst76; + dst54 = dst98; + dst21 = dst65; + dst43 = dst87; + dst65 = dst109; + dst66 = (v8i16) __msa_splati_d((v2i64) dst108, 1); } } @@ -1967,57 +1980,58 @@ static void hevc_hv_biwgt_8t_8multx2mult_msa(uint8_t *src0_ptr, int32_t offset0, int32_t offset1, int32_t rnd_val, - int32_t width) + int32_t width8mult) { uint32_t loop_cnt, cnt; - int32_t offset; + int32_t offset, weight; uint8_t *src0_ptr_tmp; int16_t *src1_ptr_tmp; uint8_t *dst_tmp; + v16u8 out; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; v8i16 in0, in1; v8i16 filt0, filt1, filt2, filt3; - v4i32 filt_h0, filt_h1, filt_h2, filt_h3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1, filt_h2, filt_h3; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1, mask2, mask3; - v8i16 filter_vec, const_vec; + v8i16 filter_vec, weight_vec; v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; v4i32 dst0_r, dst0_l, dst1_r, dst1_l; - v4i32 tmp0, tmp1, tmp2, tmp3; + v8i16 tmp0, tmp1, tmp2, tmp3; v8i16 dst10_r, dst32_r, dst54_r, dst76_r; v8i16 dst10_l, dst32_l, dst54_l, dst76_l; v8i16 dst21_r, dst43_r, dst65_r, dst87_r; v8i16 dst21_l, dst43_l, dst65_l, dst87_l; - v4i32 weight_vec0, weight_vec1, offset_vec, rnd_vec; + v4i32 offset_vec, rnd_vec, const_vec; src0_ptr -= ((3 * src_stride) + 3); offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; + weight = weight0 | (weight1 << 16); - const_vec = __msa_ldi_h(128); + const_vec = __msa_fill_w((128 * weight1)); const_vec <<= 6; offset_vec = __msa_fill_w(offset); - weight_vec0 = __msa_fill_w(weight0); - weight_vec1 = __msa_fill_w(weight1); rnd_vec = __msa_fill_w(rnd_val + 1); + offset_vec += const_vec; + weight_vec = (v8i16) __msa_fill_w(weight); filter_vec = LD_SH(filter_x); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W4_SW(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); mask1 = mask0 + 2; mask2 = mask0 + 4; mask3 = mask0 + 6; - for (cnt = width >> 3; cnt--;) { + for (cnt = width8mult; cnt--;) { src0_ptr_tmp = src0_ptr; src1_ptr_tmp = src1_ptr; dst_tmp = dst; @@ -2038,18 +2052,14 @@ static void hevc_hv_biwgt_8t_8multx2mult_msa(uint8_t *src0_ptr, VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, vec12, vec13, vec14, vec15); - dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - dst1 = const_vec; - DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - dst2 = const_vec; - DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - dst3 = const_vec; - DPADD_SB4_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst1 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst2 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst3 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, + filt2, filt3); /* row 4 row 5 row 6 */ VSHF_B4_SB(src4, src4, mask0, mask1, mask2, mask3, @@ -2059,22 +2069,12 @@ static void hevc_hv_biwgt_8t_8multx2mult_msa(uint8_t *src0_ptr, VSHF_B4_SB(src6, src6, mask0, mask1, mask2, mask3, vec8, vec9, vec10, vec11); - dst4 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst4, dst4, dst4, dst4); - dst5 = const_vec; - DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, - dst5, dst5, dst5, dst5); - dst6 = const_vec; - DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, - dst6, dst6, dst6, dst6); - - ILVR_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, - dst10_r, dst32_r, dst54_r, dst21_r); - ILVR_H2_SH(dst4, dst3, dst6, dst5, dst43_r, dst65_r); - ILVL_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, - dst10_l, dst32_l, dst54_l, dst21_l); - ILVL_H2_SH(dst4, dst3, dst6, dst5, dst43_l, dst65_l); + dst4 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst5 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst6 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); for (loop_cnt = height >> 1; loop_cnt--;) { LD_SB2(src0_ptr_tmp, src_stride, src7, src8); @@ -2084,11 +2084,17 @@ static void hevc_hv_biwgt_8t_8multx2mult_msa(uint8_t *src0_ptr, LD_SH2(src1_ptr_tmp, src2_stride, in0, in1); src1_ptr_tmp += (2 * src2_stride); + ILVR_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, dst10_r, + dst32_r, dst54_r, dst21_r); + ILVL_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, dst10_l, + dst32_l, dst54_l, dst21_l); + ILVR_H2_SH(dst4, dst3, dst6, dst5, dst43_r, dst65_r); + ILVL_H2_SH(dst4, dst3, dst6, dst5, dst43_l, dst65_l); + VSHF_B4_SB(src7, src7, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst7 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst7, dst7, dst7, dst7); + dst7 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, + filt2, filt3); ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, @@ -2102,10 +2108,8 @@ static void hevc_hv_biwgt_8t_8multx2mult_msa(uint8_t *src0_ptr, /* row 8 */ VSHF_B4_SB(src8, src8, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - - dst8 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst8, dst8, dst8, dst8); + dst8 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, + filt2, filt3); ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, @@ -2116,43 +2120,26 @@ static void hevc_hv_biwgt_8t_8multx2mult_msa(uint8_t *src0_ptr, dst1_r >>= 6; dst1_l >>= 6; - ILVRL_H2_SW(in0, in0, tmp0, tmp1); - ILVRL_H2_SW(in1, in1, tmp2, tmp3); - tmp0 = __msa_dpadd_s_w(offset_vec, (v8i16) tmp0, - (v8i16) weight_vec0); - tmp1 = __msa_dpadd_s_w(offset_vec, (v8i16) tmp1, - (v8i16) weight_vec0); - tmp2 = __msa_dpadd_s_w(offset_vec, (v8i16) tmp2, - (v8i16) weight_vec0); - tmp3 = __msa_dpadd_s_w(offset_vec, (v8i16) tmp3, - (v8i16) weight_vec0); - - tmp0 += (dst0_r * weight_vec1); - tmp1 += (dst0_l * weight_vec1); - tmp2 += (dst1_r * weight_vec1); - tmp3 += (dst1_l * weight_vec1); - - SRAR_W4_SW(tmp0, tmp1, tmp2, tmp3, rnd_vec); - tmp0 = CLIP_SW_0_255(tmp0); - tmp1 = CLIP_SW_0_255(tmp1); - tmp2 = CLIP_SW_0_255(tmp2); - tmp3 = CLIP_SW_0_255(tmp3); - HEVC_PCK_SW_SB4(tmp1, tmp0, tmp3, tmp2, dst0_r); - ST8x2_UB(dst0_r, dst_tmp, dst_stride); + PCKEV_H2_SH(dst0_l, dst0_r, dst1_l, dst1_r, tmp1, tmp3); + ILVRL_H2_SH(tmp1, in0, tmp0, tmp1); + ILVRL_H2_SH(tmp3, in1, tmp2, tmp3); + dst0_r = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst0_l = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst1_r = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst1_l = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + SRAR_W4_SW(dst0_l, dst0_r, dst1_l, dst1_r, rnd_vec); + CLIP_SW4_0_255_MAX_SATU(dst0_l, dst0_r, dst1_l, dst1_r); + PCKEV_H2_SH(dst0_l, dst0_r, dst1_l, dst1_r, tmp0, tmp1); + out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); + ST8x2_UB(out, dst_tmp, dst_stride); dst_tmp += (2 * dst_stride); - dst10_r = dst32_r; - dst32_r = dst54_r; - dst54_r = dst76_r; - dst10_l = dst32_l; - dst32_l = dst54_l; - dst54_l = dst76_l; - dst21_r = dst43_r; - dst43_r = dst65_r; - dst65_r = dst87_r; - dst21_l = dst43_l; - dst43_l = dst65_l; - dst65_l = dst87_l; + dst0 = dst2; + dst1 = dst3; + dst2 = dst4; + dst3 = dst5; + dst4 = dst6; + dst5 = dst7; dst6 = dst8; } @@ -2181,7 +2168,7 @@ static void hevc_hv_biwgt_8t_8w_msa(uint8_t *src0_ptr, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, height, weight0, weight1, offset0, - offset1, rnd_val, 8); + offset1, rnd_val, 1); } static void hevc_hv_biwgt_8t_12w_msa(uint8_t *src0_ptr, @@ -2199,16 +2186,239 @@ static void hevc_hv_biwgt_8t_12w_msa(uint8_t *src0_ptr, int32_t offset1, int32_t rnd_val) { - hevc_hv_biwgt_8t_8multx2mult_msa(src0_ptr, src_stride, - src1_ptr, src2_stride, - dst, dst_stride, filter_x, filter_y, - height, weight0, weight1, offset0, - offset1, rnd_val, 8); - hevc_hv_biwgt_8t_4w_msa(src0_ptr + 8, src_stride, - src1_ptr + 8, src2_stride, - dst + 8, dst_stride, filter_x, filter_y, - height, weight0, weight1, offset0, offset1, - rnd_val); + uint32_t loop_cnt; + uint8_t *src0_ptr_tmp, *dst_tmp; + int16_t *src1_ptr_tmp; + int32_t offset, weight; + uint64_t tp0, tp1; + v16u8 out; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; + v16i8 mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask7; + v8i16 in0 = { 0 }, in1 = { 0 }; + v8i16 filter_vec, weight_vec, tmp0, tmp1, tmp2, tmp3; + v8i16 filt0, filt1, filt2, filt3, filt_h0, filt_h1, filt_h2, filt_h3; + v8i16 dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6, dsth7, dsth8; + v8i16 dst10_r, dst32_r, dst54_r, dst76_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst76_l, dst21_l, dst43_l, dst65_l; + v8i16 dst30, dst41, dst52, dst63, dst66, dst87, dst10, dst32, dst54, dst76; + v8i16 dst21, dst43, dst65, dst97, dst108, dst109, dst98, dst87_r, dst87_l; + v4i32 offset_vec, rnd_vec, const_vec, dst0, dst1, dst2, dst3; + + src0_ptr -= ((3 * src_stride) + 3); + + offset = (offset0 + offset1) << rnd_val; + weight0 = weight0 & 0x0000FFFF; + weight = weight0 | (weight1 << 16); + + const_vec = __msa_fill_w((128 * weight1)); + const_vec <<= 6; + offset_vec = __msa_fill_w(offset); + rnd_vec = __msa_fill_w(rnd_val + 1); + offset_vec += const_vec; + weight_vec = (v8i16) __msa_fill_w(weight); + + filter_vec = LD_SH(filter_x); + SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + mask2 = mask0 + 4; + mask3 = mask0 + 6; + + src0_ptr_tmp = src0_ptr; + src1_ptr_tmp = src1_ptr; + dst_tmp = dst; + + LD_SB7(src0_ptr_tmp, src_stride, src0, src1, src2, src3, src4, src5, src6); + src0_ptr_tmp += (7 * src_stride); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); + VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, vec4, vec5, vec6, vec7); + VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, vec8, vec9, vec10, + vec11); + VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, vec12, vec13, vec14, + vec15); + dsth0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dsth1 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dsth2 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dsth3 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, + filt2, filt3); + VSHF_B4_SB(src4, src4, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); + VSHF_B4_SB(src5, src5, mask0, mask1, mask2, mask3, vec4, vec5, vec6, vec7); + VSHF_B4_SB(src6, src6, mask0, mask1, mask2, mask3, vec8, vec9, vec10, + vec11); + dsth4 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dsth5 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dsth6 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + + for (loop_cnt = 8; loop_cnt--;) { + LD_SB2(src0_ptr_tmp, src_stride, src7, src8); + src0_ptr_tmp += (2 * src_stride); + XORI_B2_128_SB(src7, src8); + + LD_SH2(src1_ptr_tmp, src2_stride, in0, in1); + src1_ptr_tmp += (2 * src2_stride); + + ILVR_H4_SH(dsth1, dsth0, dsth3, dsth2, dsth5, dsth4, dsth2, dsth1, + dst10_r, dst32_r, dst54_r, dst21_r); + ILVL_H4_SH(dsth1, dsth0, dsth3, dsth2, dsth5, dsth4, dsth2, dsth1, + dst10_l, dst32_l, dst54_l, dst21_l); + ILVR_H2_SH(dsth4, dsth3, dsth6, dsth5, dst43_r, dst65_r); + ILVL_H2_SH(dsth4, dsth3, dsth6, dsth5, dst43_l, dst65_l); + + VSHF_B4_SB(src7, src7, mask0, mask1, mask2, mask3, vec0, vec1, vec2, + vec3); + dsth7 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + + ILVRL_H2_SH(dsth7, dsth6, dst76_r, dst76_l); + dst0 = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst1 = HEVC_FILT_8TAP(dst10_l, dst32_l, dst54_l, dst76_l, filt_h0, + filt_h1, filt_h2, filt_h3); + dst0 >>= 6; + dst1 >>= 6; + + VSHF_B4_SB(src8, src8, mask0, mask1, mask2, mask3, vec0, vec1, vec2, + vec3); + dsth8 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + + ILVRL_H2_SH(dsth8, dsth7, dst87_r, dst87_l); + dst2 = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst3 = HEVC_FILT_8TAP(dst21_l, dst43_l, dst65_l, dst87_l, filt_h0, + filt_h1, filt_h2, filt_h3); + dst2 >>= 6; + dst3 >>= 6; + + PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp1, tmp3); + ILVRL_H2_SH(tmp1, in0, tmp0, tmp1); + ILVRL_H2_SH(tmp3, in1, tmp2, tmp3); + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + SRAR_W4_SW(dst1, dst0, dst3, dst2, rnd_vec); + CLIP_SW4_0_255_MAX_SATU(dst1, dst0, dst3, dst2); + PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp0, tmp1); + out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); + ST8x2_UB(out, dst_tmp, dst_stride); + dst_tmp += (2 * dst_stride); + + dsth0 = dsth2; + dsth1 = dsth3; + dsth2 = dsth4; + dsth3 = dsth5; + dsth4 = dsth6; + dsth5 = dsth7; + dsth6 = dsth8; + } + + src0_ptr += 8; + src1_ptr += 8; + dst += 8; + + mask4 = LD_SB(ff_hevc_mask_arr + 16); + mask5 = mask4 + 2; + mask6 = mask4 + 4; + mask7 = mask4 + 6; + + LD_SB7(src0_ptr, src_stride, src0, src1, src2, src3, src4, src5, src6); + src0_ptr += (7 * src_stride); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + VSHF_B4_SB(src0, src3, mask4, mask5, mask6, mask7, vec0, vec1, vec2, vec3); + VSHF_B4_SB(src1, src4, mask4, mask5, mask6, mask7, vec4, vec5, vec6, vec7); + VSHF_B4_SB(src2, src5, mask4, mask5, mask6, mask7, vec8, vec9, vec10, + vec11); + VSHF_B4_SB(src3, src6, mask4, mask5, mask6, mask7, vec12, vec13, vec14, + vec15); + dst30 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst41 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst52 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst63 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, + filt3); + ILVRL_H2_SH(dst41, dst30, dst10, dst43); + ILVRL_H2_SH(dst52, dst41, dst21, dst54); + ILVRL_H2_SH(dst63, dst52, dst32, dst65); + + dst66 = (v8i16) __msa_splati_d((v2i64) dst63, 1); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src0_ptr, src_stride, src7, src8, src9, src10); + src0_ptr += (4 * src_stride); + XORI_B4_128_SB(src7, src8, src9, src10); + + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in0); + src1_ptr += (2 * src2_stride); + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in1); + src1_ptr += (2 * src2_stride); + + VSHF_B4_SB(src7, src9, mask4, mask5, mask6, mask7, vec0, vec1, vec2, + vec3); + VSHF_B4_SB(src8, src10, mask4, mask5, mask6, mask7, vec4, vec5, vec6, + vec7); + dst97 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst108 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + + dst76 = __msa_ilvr_h(dst97, dst66); + ILVRL_H2_SH(dst108, dst97, dst87, dst109); + dst66 = (v8i16) __msa_splati_d((v2i64) dst97, 1); + dst98 = __msa_ilvr_h(dst66, dst108); + + dst0 = HEVC_FILT_8TAP(dst10, dst32, dst54, dst76, filt_h0, filt_h1, + filt_h2, filt_h3); + dst1 = HEVC_FILT_8TAP(dst21, dst43, dst65, dst87, filt_h0, filt_h1, + filt_h2, filt_h3); + dst2 = HEVC_FILT_8TAP(dst32, dst54, dst76, dst98, filt_h0, filt_h1, + filt_h2, filt_h3); + dst3 = HEVC_FILT_8TAP(dst43, dst65, dst87, dst109, filt_h0, filt_h1, + filt_h2, filt_h3); + SRA_4V(dst0, dst1, dst2, dst3, 6); + PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp1, tmp3); + ILVRL_H2_SH(tmp1, in0, tmp0, tmp1); + ILVRL_H2_SH(tmp3, in1, tmp2, tmp3); + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + CLIP_SW4_0_255_MAX_SATU(dst0, dst1, dst2, dst3); + PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp0, tmp1); + out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); + dst += (4 * dst_stride); + + dst10 = dst54; + dst32 = dst76; + dst54 = dst98; + dst21 = dst65; + dst43 = dst87; + dst65 = dst109; + dst66 = (v8i16) __msa_splati_d((v2i64) dst108, 1); + } } static void hevc_hv_biwgt_8t_16w_msa(uint8_t *src0_ptr, @@ -2230,7 +2440,7 @@ static void hevc_hv_biwgt_8t_16w_msa(uint8_t *src0_ptr, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, height, weight0, weight1, offset0, - offset1, rnd_val, 16); + offset1, rnd_val, 2); } static void hevc_hv_biwgt_8t_24w_msa(uint8_t *src0_ptr, @@ -2252,7 +2462,7 @@ static void hevc_hv_biwgt_8t_24w_msa(uint8_t *src0_ptr, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, height, weight0, weight1, offset0, - offset1, rnd_val, 24); + offset1, rnd_val, 3); } static void hevc_hv_biwgt_8t_32w_msa(uint8_t *src0_ptr, @@ -2274,7 +2484,7 @@ static void hevc_hv_biwgt_8t_32w_msa(uint8_t *src0_ptr, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, height, weight0, weight1, offset0, - offset1, rnd_val, 32); + offset1, rnd_val, 4); } static void hevc_hv_biwgt_8t_48w_msa(uint8_t *src0_ptr, @@ -2296,7 +2506,7 @@ static void hevc_hv_biwgt_8t_48w_msa(uint8_t *src0_ptr, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, height, weight0, weight1, offset0, - offset1, rnd_val, 48); + offset1, rnd_val, 6); } static void hevc_hv_biwgt_8t_64w_msa(uint8_t *src0_ptr, @@ -2318,7 +2528,7 @@ static void hevc_hv_biwgt_8t_64w_msa(uint8_t *src0_ptr, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, height, weight0, weight1, offset0, - offset1, rnd_val, 64); + offset1, rnd_val, 8); } static void hevc_hz_biwgt_4t_4x2_msa(uint8_t *src0_ptr, @@ -5453,35 +5663,32 @@ BI_W_MC_COPY(64); #undef BI_W_MC_COPY -#define BI_W_MC(PEL, DIR, WIDTH, TAP, DIR1, FILT_DIR) \ -void ff_hevc_put_hevc_bi_w_##PEL##_##DIR##WIDTH##_8_msa(uint8_t *dst, \ - ptrdiff_t \ - dst_stride, \ - uint8_t *src, \ - ptrdiff_t \ - src_stride, \ - int16_t *src_16bit, \ - int height, \ - int denom, \ - int weight0, \ - int weight1, \ - int offset0, \ - int offset1, \ - intptr_t mx, \ - intptr_t my, \ - int width) \ -{ \ - const int8_t *filter = ff_hevc_##PEL##_filters[FILT_DIR - 1]; \ - \ - int shift = 14 + 1 - 8; \ - int log2Wd = denom + shift - 1; \ - \ - hevc_##DIR1##_biwgt_##TAP##t_##WIDTH##w_msa(src, src_stride, \ - src_16bit, MAX_PB_SIZE, \ - dst, dst_stride, \ - filter, height, \ - weight0, weight1, offset0, \ - offset1, log2Wd); \ +#define BI_W_MC(PEL, DIR, WIDTH, TAP, DIR1, FILT_DIR) \ +void ff_hevc_put_hevc_bi_w_##PEL##_##DIR##WIDTH##_8_msa(uint8_t *dst, \ + ptrdiff_t \ + dst_stride, \ + uint8_t *src, \ + ptrdiff_t \ + src_stride, \ + int16_t *src_16bit, \ + int height, \ + int denom, \ + int weight0, \ + int weight1, \ + int offset0, \ + int offset1, \ + intptr_t mx, \ + intptr_t my, \ + int width) \ +{ \ + const int8_t *filter = ff_hevc_##PEL##_filters[FILT_DIR - 1]; \ + int log2Wd = denom + 14 - 8; \ + \ + hevc_##DIR1##_biwgt_##TAP##t_##WIDTH##w_msa(src, src_stride, src_16bit, \ + MAX_PB_SIZE, dst, dst_stride, \ + filter, height, weight0, \ + weight1, offset0, offset1, \ + log2Wd); \ } BI_W_MC(qpel, h, 4, 8, hz, mx); @@ -5520,53 +5727,48 @@ BI_W_MC(epel, v, 32, 4, vt, my); #undef BI_W_MC -#define BI_W_MC_HV(PEL, DIR, WIDTH, TAP, DIR1) \ -void ff_hevc_put_hevc_bi_w_##PEL##_##DIR##WIDTH##_8_msa(uint8_t *dst, \ - ptrdiff_t \ - dst_stride, \ - uint8_t *src, \ - ptrdiff_t \ - src_stride, \ - int16_t *src_16bit, \ - int height, \ - int denom, \ - int weight0, \ - int weight1, \ - int offset0, \ - int offset1, \ - intptr_t mx, \ - intptr_t my, \ - int width) \ -{ \ - const int8_t *filter_x = ff_hevc_##PEL##_filters[mx - 1]; \ - const int8_t *filter_y = ff_hevc_##PEL##_filters[my - 1]; \ - \ - int shift = 14 + 1 - 8; \ - int log2Wd = denom + shift - 1; \ - \ - hevc_##DIR1##_biwgt_##TAP##t_##WIDTH##w_msa(src, src_stride, \ - src_16bit, MAX_PB_SIZE, \ - dst, dst_stride, \ - filter_x, filter_y, \ - height, weight0, weight1, \ - offset0, offset1, log2Wd); \ +#define BI_W_MC_HV(PEL, WIDTH, TAP) \ +void ff_hevc_put_hevc_bi_w_##PEL##_hv##WIDTH##_8_msa(uint8_t *dst, \ + ptrdiff_t dst_stride, \ + uint8_t *src, \ + ptrdiff_t src_stride, \ + int16_t *src_16bit, \ + int height, \ + int denom, \ + int weight0, \ + int weight1, \ + int offset0, \ + int offset1, \ + intptr_t mx, \ + intptr_t my, \ + int width) \ +{ \ + const int8_t *filter_x = ff_hevc_##PEL##_filters[mx - 1]; \ + const int8_t *filter_y = ff_hevc_##PEL##_filters[my - 1]; \ + int log2Wd = denom + 14 - 8; \ + \ + hevc_hv_biwgt_##TAP##t_##WIDTH##w_msa(src, src_stride, src_16bit, \ + MAX_PB_SIZE, dst, dst_stride, \ + filter_x, filter_y, height, \ + weight0, weight1, offset0, \ + offset1, log2Wd); \ } -BI_W_MC_HV(qpel, hv, 4, 8, hv); -BI_W_MC_HV(qpel, hv, 8, 8, hv); -BI_W_MC_HV(qpel, hv, 12, 8, hv); -BI_W_MC_HV(qpel, hv, 16, 8, hv); -BI_W_MC_HV(qpel, hv, 24, 8, hv); -BI_W_MC_HV(qpel, hv, 32, 8, hv); -BI_W_MC_HV(qpel, hv, 48, 8, hv); -BI_W_MC_HV(qpel, hv, 64, 8, hv); - -BI_W_MC_HV(epel, hv, 4, 4, hv); -BI_W_MC_HV(epel, hv, 8, 4, hv); -BI_W_MC_HV(epel, hv, 6, 4, hv); -BI_W_MC_HV(epel, hv, 12, 4, hv); -BI_W_MC_HV(epel, hv, 16, 4, hv); -BI_W_MC_HV(epel, hv, 24, 4, hv); -BI_W_MC_HV(epel, hv, 32, 4, hv); +BI_W_MC_HV(qpel, 4, 8); +BI_W_MC_HV(qpel, 8, 8); +BI_W_MC_HV(qpel, 12, 8); +BI_W_MC_HV(qpel, 16, 8); +BI_W_MC_HV(qpel, 24, 8); +BI_W_MC_HV(qpel, 32, 8); +BI_W_MC_HV(qpel, 48, 8); +BI_W_MC_HV(qpel, 64, 8); + +BI_W_MC_HV(epel, 4, 4); +BI_W_MC_HV(epel, 8, 4); +BI_W_MC_HV(epel, 6, 4); +BI_W_MC_HV(epel, 12, 4); +BI_W_MC_HV(epel, 16, 4); +BI_W_MC_HV(epel, 24, 4); +BI_W_MC_HV(epel, 32, 4); #undef BI_W_MC_HV diff --git a/libavutil/mips/generic_macros_msa.h b/libavutil/mips/generic_macros_msa.h index c892529f05ac7..6a467046631f4 100644 --- a/libavutil/mips/generic_macros_msa.h +++ b/libavutil/mips/generic_macros_msa.h @@ -1088,6 +1088,25 @@ out_m; \ } ) +#define CLIP_SW_0_255_MAX_SATU(in) \ +( { \ + v4i32 out_m; \ + \ + out_m = __msa_maxi_s_w((v4i32) in, 0); \ + out_m = (v4i32) __msa_sat_u_w((v4u32) out_m, 7); \ + out_m; \ +} ) +#define CLIP_SW2_0_255_MAX_SATU(in0, in1) \ +{ \ + in0 = CLIP_SW_0_255_MAX_SATU(in0); \ + in1 = CLIP_SW_0_255_MAX_SATU(in1); \ +} +#define CLIP_SW4_0_255_MAX_SATU(in0, in1, in2, in3) \ +{ \ + CLIP_SW2_0_255_MAX_SATU(in0, in1); \ + CLIP_SW2_0_255_MAX_SATU(in2, in3); \ +} + /* Description : Addition of 4 signed word elements 4 signed word elements of input vector are added together and resulted integer sum is returned @@ -2244,6 +2263,22 @@ out3 = in6 - in7; \ } +/* Description : Sign extend byte elements from right half of the vector + Arguments : Input - in (byte vector) + Output - out (sign extended halfword vector) + Return Type - signed halfword + Details : Sign bit of byte elements from input vector 'in' is + extracted and interleaved with same vector 'in' to generate + 8 halfword elements keeping sign intact +*/ +#define UNPCK_R_SB_SH(in, out) \ +{ \ + v16i8 sign_m; \ + \ + sign_m = __msa_clti_s_b((v16i8) in, 0); \ + out = (v8i16) __msa_ilvr_b(sign_m, (v16i8) in); \ +} + /* Description : Sign extend halfword elements from right half of the vector Arguments : Inputs - in (input halfword vector) Outputs - out (sign extended word vectors) From 50ce2960263daf48227df758df9ade19db7154fa Mon Sep 17 00:00:00 2001 From: Mateusz Date: Tue, 24 Oct 2017 10:02:17 +0200 Subject: [PATCH 0608/2557] swscale: use dithering in DITHER_COPY only if not set -sws_dither none This patch uses dithering in DITHER_COPY macro only if it was not used option '-sws_dither none'. With option '-sws_dither none' it uses downshift. For human eye dithering is OK, for video codecs not necessarily. If user don't want to use dithering, we should respect that. Signed-off-by: Mateusz Brzostek Signed-off-by: Michael Niedermayer --- libswscale/swscale_unscaled.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 5d81cd5af9d46..5ec2116bcfa8d 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -1485,7 +1485,25 @@ static int packedCopyWrapper(SwsContext *c, const uint8_t *src[], #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\ unsigned shift= src_depth-dst_depth, tmp;\ - if (shiftonly) {\ + if (c->dither == SWS_DITHER_NONE) {\ + for (i = 0; i < height; i++) {\ + for (j = 0; j < length-7; j+=8) {\ + dst[j+0] = dbswap(bswap(src[j+0])>>shift);\ + dst[j+1] = dbswap(bswap(src[j+1])>>shift);\ + dst[j+2] = dbswap(bswap(src[j+2])>>shift);\ + dst[j+3] = dbswap(bswap(src[j+3])>>shift);\ + dst[j+4] = dbswap(bswap(src[j+4])>>shift);\ + dst[j+5] = dbswap(bswap(src[j+5])>>shift);\ + dst[j+6] = dbswap(bswap(src[j+6])>>shift);\ + dst[j+7] = dbswap(bswap(src[j+7])>>shift);\ + }\ + for (; j < length; j++) {\ + dst[j] = dbswap(bswap(src[j])>>shift);\ + }\ + dst += dstStride;\ + src += srcStride;\ + }\ + } else if (shiftonly) {\ for (i = 0; i < height; i++) {\ const uint8_t *dither= dithers[shift-1][i&7];\ for (j = 0; j < length-7; j+=8) {\ From 984b882b769cab6372454cf8d5cda7c554c5ee77 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Wed, 25 Oct 2017 13:45:22 +0800 Subject: [PATCH 0609/2557] fate: fix mpeg2-ticket6677 faillures on some platforms Signed-off-by: Zhong Li Signed-off-by: Michael Niedermayer --- tests/fate/video.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fate/video.mak b/tests/fate/video.mak index 51678078a3781..c7f2dcea9e0f4 100644 --- a/tests/fate/video.mak +++ b/tests/fate/video.mak @@ -258,7 +258,7 @@ FATE_VIDEO-$(call DEMDEC, MPEGPS, MPEG2VIDEO) += fate-mpeg2-ticket6024 fate-mpeg2-ticket6024: CMD = framecrc -flags +bitexact -idct simple -flags +truncated -i $(TARGET_SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg -an FATE_VIDEO-$(call DEMDEC, MPEGVIDEO, MPEG2VIDEO) += fate-mpeg2-ticket6677 -fate-mpeg2-ticket6677: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/mpeg2/sony-ct3.bs +fate-mpeg2-ticket6677: CMD = framecrc -flags +bitexact -idct simple -vsync drop -i $(TARGET_SAMPLES)/mpeg2/sony-ct3.bs FATE_VIDEO-$(call DEMDEC, MV, MVC1) += fate-mv-mvc1 fate-mv-mvc1: CMD = framecrc -i $(TARGET_SAMPLES)/mv/posture.mv -an -frames 25 -pix_fmt rgb555le From 6bd665b7c5798803366b877903fa3bce7f129d05 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 22 Oct 2017 20:29:53 -0300 Subject: [PATCH 0610/2557] avcodec/tak: remove GetBitContext usage from avpriv_tak_parse_streaminfo() This prevents potential ABI issues with GetBitContext. Reviewed-by: Paul B Mahol Signed-off-by: James Almer --- libavcodec/tak.c | 17 +++++++++++++++-- libavcodec/tak.h | 8 ++++++-- libavformat/takdec.c | 7 +++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/libavcodec/tak.c b/libavcodec/tak.c index d2670e00ff279..8aa956b661e19 100644 --- a/libavcodec/tak.c +++ b/libavcodec/tak.c @@ -90,7 +90,7 @@ int ff_tak_check_crc(const uint8_t *buf, unsigned int buf_size) return 0; } -void avpriv_tak_parse_streaminfo(GetBitContext *gb, TAKStreamInfo *s) +void ff_tak_parse_streaminfo(TAKStreamInfo *s, GetBitContext *gb) { uint64_t channel_mask = 0; int frame_type, i; @@ -125,6 +125,19 @@ void avpriv_tak_parse_streaminfo(GetBitContext *gb, TAKStreamInfo *s) s->frame_samples = tak_get_nb_samples(s->sample_rate, frame_type); } +int avpriv_tak_parse_streaminfo(TAKStreamInfo *s, const uint8_t *buf, int size) +{ + GetBitContext gb; + int ret = init_get_bits8(&gb, buf, size); + + if (ret < 0) + return AVERROR_INVALIDDATA; + + ff_tak_parse_streaminfo(s, &gb); + + return 0; +} + int ff_tak_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, TAKStreamInfo *ti, int log_level_offset) { @@ -144,7 +157,7 @@ int ff_tak_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, } if (ti->flags & TAK_FRAME_FLAG_HAS_INFO) { - avpriv_tak_parse_streaminfo(gb, ti); + ff_tak_parse_streaminfo(ti, gb); if (get_bits(gb, 6)) skip_bits(gb, 25); diff --git a/libavcodec/tak.h b/libavcodec/tak.h index 4fa1239093bc9..dc45a8c070897 100644 --- a/libavcodec/tak.h +++ b/libavcodec/tak.h @@ -143,10 +143,14 @@ int ff_tak_check_crc(const uint8_t *buf, unsigned int buf_size); /** * Parse the Streaminfo metadata block. - * @param[in] gb pointer to GetBitContext * @param[out] s storage for parsed information + * @param[in] buf input buffer + * @param[in] size size of input buffer in bytes + * @return non-zero on error, 0 if OK */ -void avpriv_tak_parse_streaminfo(GetBitContext *gb, TAKStreamInfo *s); +int avpriv_tak_parse_streaminfo(TAKStreamInfo *s, const uint8_t *buf, int size); + +void ff_tak_parse_streaminfo(TAKStreamInfo *s, GetBitContext *gb); /** * Validate and decode a frame header. diff --git a/libavformat/takdec.c b/libavformat/takdec.c index 1535bec64f378..6fda35c1bef20 100644 --- a/libavformat/takdec.c +++ b/libavformat/takdec.c @@ -103,7 +103,6 @@ static int tak_read_header(AVFormatContext *s) } } - init_get_bits8(&gb, buffer, size - 3); break; case TAK_METADATA_MD5: { uint8_t md5[16]; @@ -145,7 +144,9 @@ static int tak_read_header(AVFormatContext *s) if (type == TAK_METADATA_STREAMINFO) { TAKStreamInfo ti; - avpriv_tak_parse_streaminfo(&gb, &ti); + ret = avpriv_tak_parse_streaminfo(&ti, buffer, size -3); + if (ret < 0) + return AVERROR_INVALIDDATA; if (ti.samples > 0) st->duration = ti.samples; st->codecpar->bits_per_coded_sample = ti.bps; @@ -161,11 +162,13 @@ static int tak_read_header(AVFormatContext *s) } else if (type == TAK_METADATA_LAST_FRAME) { if (size != 11) return AVERROR_INVALIDDATA; + init_get_bits8(&gb, buffer, size - 3); tc->mlast_frame = 1; tc->data_end = get_bits64(&gb, TAK_LAST_FRAME_POS_BITS) + get_bits(&gb, TAK_LAST_FRAME_SIZE_BITS); av_freep(&buffer); } else if (type == TAK_METADATA_ENCODER) { + init_get_bits8(&gb, buffer, size - 3); av_log(s, AV_LOG_VERBOSE, "encoder version: %0X\n", get_bits_long(&gb, TAK_ENCODER_VERSION_BITS)); av_freep(&buffer); From ae100046ca32b0b83031a60d0c3cdfc5ceb9f874 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 23 Oct 2017 23:39:54 -0300 Subject: [PATCH 0611/2557] avcodec/exif: remove GetByteContext usage from avpriv_exif_decode_ifd() This prevents potential ABI issues with GetByteContext. Reviewed-by: Paul B Mahol Signed-off-by: James Almer --- libavcodec/exif.c | 16 +++++++++++++--- libavcodec/exif.h | 7 +++++-- libavcodec/mjpegdec.c | 2 +- libavcodec/webp.c | 2 +- libavformat/avidec.c | 4 ++-- 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/libavcodec/exif.c b/libavcodec/exif.c index 07ce1741c2642..2874772db4d7d 100644 --- a/libavcodec/exif.c +++ b/libavcodec/exif.c @@ -92,7 +92,7 @@ static int exif_decode_tag(void *logctx, GetByteContext *gbytes, int le, // store metadata or proceed with next IFD ret = ff_tis_ifd(id); if (ret) { - ret = avpriv_exif_decode_ifd(logctx, gbytes, le, depth + 1, metadata); + ret = ff_exif_decode_ifd(logctx, gbytes, le, depth + 1, metadata); } else { const char *name = exif_get_tag_name(id); char *use_name = (char*) name; @@ -119,8 +119,8 @@ static int exif_decode_tag(void *logctx, GetByteContext *gbytes, int le, } -int avpriv_exif_decode_ifd(void *logctx, GetByteContext *gbytes, int le, - int depth, AVDictionary **metadata) +int ff_exif_decode_ifd(void *logctx, GetByteContext *gbytes, + int le, int depth, AVDictionary **metadata) { int i, ret; int entries; @@ -140,3 +140,13 @@ int avpriv_exif_decode_ifd(void *logctx, GetByteContext *gbytes, int le, // return next IDF offset or 0x000000000 or a value < 0 for failure return ff_tget_long(gbytes, le); } + +int avpriv_exif_decode_ifd(void *logctx, const uint8_t *buf, int size, + int le, int depth, AVDictionary **metadata) +{ + GetByteContext gb; + + bytestream2_init(&gb, buf, size); + + return ff_exif_decode_ifd(logctx, &gb, le, depth, metadata); +} diff --git a/libavcodec/exif.h b/libavcodec/exif.h index 5f09208b9d766..05af756c48fd0 100644 --- a/libavcodec/exif.h +++ b/libavcodec/exif.h @@ -164,7 +164,10 @@ static const struct exif_tag tag_list[] = { // JEITA CP-3451 EXIF specification: /** Recursively decodes all IFD's and * adds included TAGS into the metadata dictionary. */ -int avpriv_exif_decode_ifd(void *logctx, GetByteContext *gbytes, int le, - int depth, AVDictionary **metadata); +int avpriv_exif_decode_ifd(void *logctx, const uint8_t *buf, int size, + int le, int depth, AVDictionary **metadata); + +int ff_exif_decode_ifd(void *logctx, GetByteContext *gbytes, int le, + int depth, AVDictionary **metadata); #endif /* AVCODEC_EXIF_H */ diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 5b2409755cb32..d980ac99a13b1 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -1867,7 +1867,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) // read 0th IFD and store the metadata // (return values > 0 indicate the presence of subimage metadata) - ret = avpriv_exif_decode_ifd(s->avctx, &gbytes, le, 0, &s->exif_metadata); + ret = ff_exif_decode_ifd(s->avctx, &gbytes, le, 0, &s->exif_metadata); if (ret < 0) { av_log(s->avctx, AV_LOG_ERROR, "mjpeg: error decoding EXIF data\n"); } diff --git a/libavcodec/webp.c b/libavcodec/webp.c index efa864a6f141d..c8475faa2d9ec 100644 --- a/libavcodec/webp.c +++ b/libavcodec/webp.c @@ -1504,7 +1504,7 @@ static int webp_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } bytestream2_seek(&exif_gb, ifd_offset, SEEK_SET); - if (avpriv_exif_decode_ifd(avctx, &exif_gb, le, 0, &exif_metadata) < 0) { + if (ff_exif_decode_ifd(avctx, &exif_gb, le, 0, &exif_metadata) < 0) { av_log(avctx, AV_LOG_ERROR, "error decoding Exif data\n"); goto exif_end; } diff --git a/libavformat/avidec.c b/libavformat/avidec.c index b8a31dcff2875..3ff515d492f96 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -401,10 +401,10 @@ static int avi_extract_stream_metadata(AVFormatContext *s, AVStream *st) // skip 4 byte padding bytestream2_skip(&gb, 4); offset = bytestream2_tell(&gb); - bytestream2_init(&gb, data + offset, data_size - offset); // decode EXIF tags from IFD, AVI is always little-endian - return avpriv_exif_decode_ifd(s, &gb, 1, 0, &st->metadata); + return avpriv_exif_decode_ifd(s, data + offset, data_size - offset, + 1, 0, &st->metadata); break; case MKTAG('C', 'A', 'S', 'I'): avpriv_request_sample(s, "RIFF stream data tag type CASI (%u)", tag); From a07ac9302335c1f12dcfb7d4ef57689f25c8e2c4 Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Fri, 29 Sep 2017 16:32:20 +0200 Subject: [PATCH 0612/2557] avformat/wavenc: skip writing incorrect peak-of-peaks position value According to EBU tech 3285 supplement 3 the dwPosPeakOfPeaks field should contain the absolute position to the maximum audio sample value, but the current implementation writes the relative peak frame index instead. Fix the issue by writing the "unknown" value (-1) for now until the feature is implemented correctly. Previous version reviewed-by: Peter Bubestinger Reviewed-by: Michael Niedermayer Signed-off-by: Tobias Rapp --- libavformat/version.h | 2 +- libavformat/wavenc.c | 11 +---------- tests/ref/lavf/wav_peak | 2 +- tests/ref/lavf/wav_peak_only | 2 +- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/libavformat/version.h b/libavformat/version.h index 0feb788c366b3..8ae091ffabf9c 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -33,7 +33,7 @@ // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 #define LIBAVFORMAT_VERSION_MINOR 0 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c index adb20cb215689..159119d693624 100644 --- a/libavformat/wavenc.c +++ b/libavformat/wavenc.c @@ -74,8 +74,6 @@ typedef struct WAVMuxContext { uint32_t peak_num_frames; uint32_t peak_outbuf_size; uint32_t peak_outbuf_bytes; - uint32_t peak_pos_pop; - uint16_t peak_pop; uint8_t *peak_output; int last_duration; int write_bext; @@ -195,7 +193,6 @@ static void peak_write_frame(AVFormatContext *s) { WAVMuxContext *wav = s->priv_data; AVCodecParameters *par = s->streams[0]->codecpar; - int peak_of_peaks; int c; if (!wav->peak_output) @@ -213,12 +210,6 @@ static void peak_write_frame(AVFormatContext *s) wav->peak_maxpos[c] = FFMAX(wav->peak_maxpos[c], wav->peak_maxneg[c]); - peak_of_peaks = FFMAX3(wav->peak_maxpos[c], wav->peak_maxneg[c], - wav->peak_pop); - if (peak_of_peaks > wav->peak_pop) - wav->peak_pos_pop = wav->peak_num_frames; - wav->peak_pop = peak_of_peaks; - if (wav->peak_outbuf_size - wav->peak_outbuf_bytes < wav->peak_format * wav->peak_ppv) { wav->peak_outbuf_size += PEAK_BUFFER_SIZE; @@ -287,7 +278,7 @@ static int peak_write_chunk(AVFormatContext *s) avio_wl32(pb, wav->peak_block_size); /* frames per value */ avio_wl32(pb, par->channels); /* number of channels */ avio_wl32(pb, wav->peak_num_frames); /* number of peak frames */ - avio_wl32(pb, wav->peak_pos_pop); /* audio sample frame index */ + avio_wl32(pb, -1); /* audio sample frame position (not implemented) */ avio_wl32(pb, 128); /* equal to size of header */ avio_write(pb, timestamp, 28); /* ASCII time stamp */ ffio_fill(pb, 0, 60); diff --git a/tests/ref/lavf/wav_peak b/tests/ref/lavf/wav_peak index aa7e5fc49e93e..861b246d72aa1 100644 --- a/tests/ref/lavf/wav_peak +++ b/tests/ref/lavf/wav_peak @@ -1,3 +1,3 @@ -35148d1f6e66b0080893851d917ecbf4 *./tests/data/lavf/lavf.peak.wav +105805963fb767d00da056f42f32d9f3 *./tests/data/lavf/lavf.peak.wav 89094 ./tests/data/lavf/lavf.peak.wav ./tests/data/lavf/lavf.peak.wav CRC=0x3a1da17e diff --git a/tests/ref/lavf/wav_peak_only b/tests/ref/lavf/wav_peak_only index dccd0e72ff4f4..b203d0345bed0 100644 --- a/tests/ref/lavf/wav_peak_only +++ b/tests/ref/lavf/wav_peak_only @@ -1,2 +1,2 @@ -b609a363e6d490710ed52231a8d09d3c *./tests/data/lavf/lavf.peak_only.wav +f1a8aeeae8069f3992c4d780436c3d23 *./tests/data/lavf/lavf.peak_only.wav 832 ./tests/data/lavf/lavf.peak_only.wav From f2c867051c8fb2eb06c1b43a4b08d60a1eafd987 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Thu, 26 Oct 2017 18:29:02 +0200 Subject: [PATCH 0613/2557] lavc/avcodec: Constify the return value of av_bitstream_filter_next(). Fixes the following gcc warning: libavcodec/bitstream_filter.c:39:12: warning: return discards 'const' qualifier from pointer target type --- libavcodec/avcodec.h | 2 +- libavcodec/bitstream_filter.c | 2 +- libavcodec/version.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 5f13f865e4fb0..ee7834c8a2935 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -5484,7 +5484,7 @@ void av_bitstream_filter_close(AVBitStreamFilterContext *bsf); * filters. */ attribute_deprecated -AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f); +const AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f); #endif /** diff --git a/libavcodec/bitstream_filter.c b/libavcodec/bitstream_filter.c index d2bf86d894a08..ed1cf3335ba54 100644 --- a/libavcodec/bitstream_filter.c +++ b/libavcodec/bitstream_filter.c @@ -28,7 +28,7 @@ #if FF_API_OLD_BSF FF_DISABLE_DEPRECATION_WARNINGS -AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f) +const AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f) { const AVBitStreamFilter *filter = NULL; void *opaque = NULL; diff --git a/libavcodec/version.h b/libavcodec/version.h index 69f124a4c61e6..226da1935fef1 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 0 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From a4743d2574254aa0c494b337947e8c9880c7ead7 Mon Sep 17 00:00:00 2001 From: Mateusz Date: Sat, 7 Oct 2017 19:05:53 +0200 Subject: [PATCH 0614/2557] avformat/yuv4mpeg: add gray9/10/12 support Signed-off-by: Mateusz Brzostek --- libavformat/yuv4mpegdec.c | 6 ++++++ libavformat/yuv4mpegenc.c | 23 ++++++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/libavformat/yuv4mpegdec.c b/libavformat/yuv4mpegdec.c index 462b823860642..ff0125e4cf306 100644 --- a/libavformat/yuv4mpegdec.c +++ b/libavformat/yuv4mpegdec.c @@ -126,6 +126,12 @@ static int yuv4_read_header(AVFormatContext *s) pix_fmt = AV_PIX_FMT_YUV444P; } else if (strncmp("mono16", tokstart, 6) == 0) { pix_fmt = AV_PIX_FMT_GRAY16; + } else if (strncmp("mono12", tokstart, 6) == 0) { + pix_fmt = AV_PIX_FMT_GRAY12; + } else if (strncmp("mono10", tokstart, 6) == 0) { + pix_fmt = AV_PIX_FMT_GRAY10; + } else if (strncmp("mono9", tokstart, 5) == 0) { + pix_fmt = AV_PIX_FMT_GRAY9; } else if (strncmp("mono", tokstart, 4) == 0) { pix_fmt = AV_PIX_FMT_GRAY8; } else { diff --git a/libavformat/yuv4mpegenc.c b/libavformat/yuv4mpegenc.c index b4dc6e9ef64eb..44f40bbad98d0 100644 --- a/libavformat/yuv4mpegenc.c +++ b/libavformat/yuv4mpegenc.c @@ -69,6 +69,15 @@ static int yuv4_generate_header(AVFormatContext *s, char* buf) case AV_PIX_FMT_GRAY8: colorspace = " Cmono"; break; + case AV_PIX_FMT_GRAY9: + colorspace = " Cmono9"; + break; + case AV_PIX_FMT_GRAY10: + colorspace = " Cmono10"; + break; + case AV_PIX_FMT_GRAY12: + colorspace = " Cmono12"; + break; case AV_PIX_FMT_GRAY16: colorspace = " Cmono16"; break; @@ -184,6 +193,9 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUV444P: break; + case AV_PIX_FMT_GRAY9: + case AV_PIX_FMT_GRAY10: + case AV_PIX_FMT_GRAY12: case AV_PIX_FMT_GRAY16: case AV_PIX_FMT_YUV420P9: case AV_PIX_FMT_YUV422P9: @@ -213,7 +225,8 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) ptr += frame->linesize[0]; } - if (st->codecpar->format != AV_PIX_FMT_GRAY8 && + if (st->codecpar->format != AV_PIX_FMT_GRAY8 && st->codecpar->format != AV_PIX_FMT_GRAY9 && + st->codecpar->format != AV_PIX_FMT_GRAY10 && st->codecpar->format != AV_PIX_FMT_GRAY12 && st->codecpar->format != AV_PIX_FMT_GRAY16) { // Adjust for smaller Cb and Cr planes av_pix_fmt_get_chroma_sub_sample(st->codecpar->format, &h_chroma_shift, @@ -255,11 +268,14 @@ static int yuv4_write_header(AVFormatContext *s) "stream, some mjpegtools might not work.\n"); break; case AV_PIX_FMT_GRAY8: - case AV_PIX_FMT_GRAY16: case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUV444P: break; + case AV_PIX_FMT_GRAY9: + case AV_PIX_FMT_GRAY10: + case AV_PIX_FMT_GRAY12: + case AV_PIX_FMT_GRAY16: case AV_PIX_FMT_YUV420P9: case AV_PIX_FMT_YUV422P9: case AV_PIX_FMT_YUV444P9: @@ -291,7 +307,8 @@ static int yuv4_write_header(AVFormatContext *s) "yuv444p10, yuv422p10, yuv420p10, " "yuv444p12, yuv422p12, yuv420p12, " "yuv444p14, yuv422p14, yuv420p14, " - "yuv444p16, yuv422p16, yuv420p16 " + "yuv444p16, yuv422p16, yuv420p16, " + "gray9, gray10, gray12 " "and gray16 pixel formats. " "Use -pix_fmt to select one.\n"); return AVERROR(EIO); From c64800e976f9e49d2d06431e63e2e1e9329872e1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 26 Oct 2017 15:27:57 -0300 Subject: [PATCH 0615/2557] configure: add optional zlib dependency to avformat id3v2 code is compiled unconditionally and uses zlib when available. Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 7767fb259643d..2e0236285e99e 100755 --- a/configure +++ b/configure @@ -3318,7 +3318,7 @@ avdevice_suggest="libm" avfilter_deps="avutil" avfilter_suggest="libm" avformat_deps="avcodec avutil" -avformat_suggest="libm network" +avformat_suggest="libm network zlib" avresample_deps="avutil" avresample_suggest="libm" avutil_suggest="clock_gettime libm libdrm libmfx opencl user32 vaapi videotoolbox corefoundation corevideo coremedia wincrypt" From 693a11b8a269c695c2608172c223be246dd7343e Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Thu, 26 Oct 2017 23:43:11 +0200 Subject: [PATCH 0616/2557] lavf: Remove AVFMT_RAWPICTURE. Deprecated since October 2015. --- fftools/ffmpeg.c | 40 ---------------------------------------- libavformat/avformat.h | 4 ---- libavformat/version.h | 3 --- 3 files changed, 47 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index d581b40bf2f79..cabc6864e7e63 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1199,24 +1199,6 @@ static void do_video_out(OutputFile *of, #endif return; -#if FF_API_LAVF_FMT_RAWPICTURE - if (of->ctx->oformat->flags & AVFMT_RAWPICTURE && - enc->codec->id == AV_CODEC_ID_RAWVIDEO) { - /* raw pictures are written as AVPicture structure to - avoid any copies. We support temporarily the older - method. */ - if (in_picture->interlaced_frame) - mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; - else - mux_par->field_order = AV_FIELD_PROGRESSIVE; - pkt.data = (uint8_t *)in_picture; - pkt.size = sizeof(AVPicture); - pkt.pts = av_rescale_q(in_picture->pts, enc->time_base, ost->mux_timebase); - pkt.flags |= AV_PKT_FLAG_KEY; - - output_packet(of, &pkt, ost, 0); - } else -#endif { int forced_keyframe = 0; double pts_time; @@ -1897,10 +1879,6 @@ static void flush_encoders(void) if (enc->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1) continue; -#if FF_API_LAVF_FMT_RAWPICTURE - if (enc->codec_type == AVMEDIA_TYPE_VIDEO && (of->ctx->oformat->flags & AVFMT_RAWPICTURE) && enc->codec->id == AV_CODEC_ID_RAWVIDEO) - continue; -#endif if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO) continue; @@ -1991,7 +1969,6 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p InputFile *f = input_files [ist->file_index]; int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); - AVPicture pict; AVPacket opkt; av_init_packet(&opkt); @@ -2079,23 +2056,6 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p } av_copy_packet_side_data(&opkt, pkt); -#if FF_API_LAVF_FMT_RAWPICTURE - if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && - ost->st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO && - (of->ctx->oformat->flags & AVFMT_RAWPICTURE)) { - /* store AVPicture in AVPacket, as expected by the output format */ - int ret = avpicture_fill(&pict, opkt.data, ost->st->codecpar->format, ost->st->codecpar->width, ost->st->codecpar->height); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "avpicture_fill failed: %s\n", - av_err2str(ret)); - exit_program(1); - } - opkt.data = (uint8_t *)&pict; - opkt.size = sizeof(AVPicture); - opkt.flags |= AV_PKT_FLAG_KEY; - } -#endif - output_packet(of, &opkt, ost, 0); } diff --git a/libavformat/avformat.h b/libavformat/avformat.h index ece1b179f3acb..65fc9eac0cd29 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -465,10 +465,6 @@ typedef struct AVProbeData { #define AVFMT_NOFILE 0x0001 #define AVFMT_NEEDNUMBER 0x0002 /**< Needs '%d' in filename. */ #define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */ -#if FF_API_LAVF_FMT_RAWPICTURE -#define AVFMT_RAWPICTURE 0x0020 /**< Format wants AVPicture structure for - raw picture data. @deprecated Not used anymore */ -#endif #define AVFMT_GLOBALHEADER 0x0040 /**< Format wants global header. */ #define AVFMT_NOTIMESTAMPS 0x0080 /**< Format does not need / have any timestamps. */ #define AVFMT_GENERIC_INDEX 0x0100 /**< Use generic index building code. */ diff --git a/libavformat/version.h b/libavformat/version.h index 8ae091ffabf9c..ac409dbad2d69 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -55,9 +55,6 @@ * at once through the bump. This improves the git bisect-ability of the change. * */ -#ifndef FF_API_LAVF_FMT_RAWPICTURE -#define FF_API_LAVF_FMT_RAWPICTURE (LIBAVFORMAT_VERSION_MAJOR < 58) -#endif #ifndef FF_API_COMPUTE_PKT_FIELDS2 #define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 59) #endif From cbcb8f5a22e8ccc1d6b39ca7a5e565552b149b96 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 8 Oct 2017 14:51:03 +0200 Subject: [PATCH 0617/2557] fate: add fate test for ticket #6603 Signed-off-by: Marton Balint --- tests/fate/ffmpeg.mak | 4 ++++ tests/ref/fate/ffmpeg-filter_complex_audio | 10 ++++++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/ref/fate/ffmpeg-filter_complex_audio diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index d8f2e715901df..8c25c8237f91e 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -26,6 +26,10 @@ fate-mapchan: $(FATE_MAPCHAN) FATE_FFMPEG-$(CONFIG_COLOR_FILTER) += fate-ffmpeg-filter_complex fate-ffmpeg-filter_complex: CMD = framecrc -filter_complex color=d=1:r=5 -fflags +bitexact +# Ticket 6603 +FATE_FFMPEG-$(call ALLYES, AEVALSRC_FILTER ASETNSAMPLES_FILTER AC3_FIXED_ENCODER) += fate-ffmpeg-filter_complex_audio +fate-ffmpeg-filter_complex_audio: CMD = framecrc -filter_complex "aevalsrc=0:d=0.1,asetnsamples=1537" -c ac3_fixed + FATE_SAMPLES_FFMPEG-$(CONFIG_COLORKEY_FILTER) += fate-ffmpeg-filter_colorkey fate-ffmpeg-filter_colorkey: tests/data/filtergraphs/colorkey fate-ffmpeg-filter_colorkey: CMD = framecrc -idct simple -fflags +bitexact -flags +bitexact -sws_flags +accurate_rnd+bitexact -i $(TARGET_SAMPLES)/cavs/cavs.mpg -fflags +bitexact -flags +bitexact -sws_flags +accurate_rnd+bitexact -i $(TARGET_SAMPLES)/lena.pnm -an -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/colorkey -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -qscale 2 -frames:v 10 diff --git a/tests/ref/fate/ffmpeg-filter_complex_audio b/tests/ref/fate/ffmpeg-filter_complex_audio new file mode 100644 index 0000000000000..c4246750610d0 --- /dev/null +++ b/tests/ref/fate/ffmpeg-filter_complex_audio @@ -0,0 +1,10 @@ +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: ac3 +#sample_rate 0: 44100 +#channel_layout 0: 4 +#channel_layout_name 0: mono +0, -256, -256, 1536, 416, 0x3001fb2d +0, 1280, 1280, 1536, 418, 0xba72fc16 +0, 2816, 2816, 1536, 418, 0xba72fc16 +0, 4352, 4352, 1536, 418, 0xba72fc16 From 61e25ab0bf9f2be44ebce555f205561c34b674ee Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 8 Oct 2017 15:27:50 +0200 Subject: [PATCH 0618/2557] fate: add fate test for ticket #6375 Signed-off-by: Marton Balint --- tests/fate/ffmpeg.mak | 4 + tests/ref/fate/ffmpeg-attached_pics | 141 ++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 tests/ref/fate/ffmpeg-attached_pics diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 8c25c8237f91e..607cc79649786 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -30,6 +30,10 @@ fate-ffmpeg-filter_complex: CMD = framecrc -filter_complex color=d=1:r=5 -fflags FATE_FFMPEG-$(call ALLYES, AEVALSRC_FILTER ASETNSAMPLES_FILTER AC3_FIXED_ENCODER) += fate-ffmpeg-filter_complex_audio fate-ffmpeg-filter_complex_audio: CMD = framecrc -filter_complex "aevalsrc=0:d=0.1,asetnsamples=1537" -c ac3_fixed +# Ticket 6375 +FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER ALAC_DECODER ALAC_ENCODER) += fate-ffmpeg-attached_pics +fate-ffmpeg-attached_pics: CMD = threads=2 framecrc -i $(TARGET_SAMPLES)/lossless-audio/inside.m4a -acodec alac -max_muxing_queue_size 16 + FATE_SAMPLES_FFMPEG-$(CONFIG_COLORKEY_FILTER) += fate-ffmpeg-filter_colorkey fate-ffmpeg-filter_colorkey: tests/data/filtergraphs/colorkey fate-ffmpeg-filter_colorkey: CMD = framecrc -idct simple -fflags +bitexact -flags +bitexact -sws_flags +accurate_rnd+bitexact -i $(TARGET_SAMPLES)/cavs/cavs.mpg -fflags +bitexact -flags +bitexact -sws_flags +accurate_rnd+bitexact -i $(TARGET_SAMPLES)/lena.pnm -an -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/colorkey -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -qscale 2 -frames:v 10 diff --git a/tests/ref/fate/ffmpeg-attached_pics b/tests/ref/fate/ffmpeg-attached_pics new file mode 100644 index 0000000000000..3a0f15181987d --- /dev/null +++ b/tests/ref/fate/ffmpeg-attached_pics @@ -0,0 +1,141 @@ +#extradata 1: 36, 0x45f80468 +#tb 0: 1/90000 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 200x200 +#sar 0: 2834/2834 +#tb 1: 1/44100 +#media_type 1: audio +#codec_id 1: alac +#sample_rate 1: 44100 +#channel_layout 1: 3 +#channel_layout_name 1: stereo +0, 0, 0, 0, 120000, 0x748cc771 +1, 0, 0, 4096, 32, 0x204b0676 +1, 4096, 4096, 4096, 5826, 0x56583236 +1, 8192, 8192, 4096, 5532, 0x5f047492 +1, 12288, 12288, 4096, 5245, 0xaa3f1897 +1, 16384, 16384, 4096, 4782, 0x392f3ac3 +1, 20480, 20480, 4096, 4602, 0x9bd6ffad +1, 24576, 24576, 4096, 4357, 0x5df6530b +1, 28672, 28672, 4096, 7443, 0x38ce542b +1, 32768, 32768, 4096, 5803, 0x196ae519 +1, 36864, 36864, 4096, 5619, 0xd436cd94 +1, 40960, 40960, 4096, 4896, 0x42df7109 +1, 45056, 45056, 4096, 4755, 0xfbfdfd5f +1, 49152, 49152, 4096, 4597, 0x93f3ce66 +1, 53248, 53248, 4096, 7777, 0x56ffe620 +1, 57344, 57344, 4096, 5498, 0xa0865dc8 +1, 61440, 61440, 4096, 5343, 0x42134619 +1, 65536, 65536, 4096, 6261, 0xd60d1379 +1, 69632, 69632, 4096, 4496, 0x0eb49c68 +1, 73728, 73728, 4096, 4336, 0x21d541bd +1, 77824, 77824, 4096, 8395, 0x02030a38 +1, 81920, 81920, 4096, 8174, 0x47bdb71d +1, 86016, 86016, 4096, 7434, 0x2304318e +1, 90112, 90112, 4096, 7619, 0x80e6a037 +1, 94208, 94208, 4096, 6086, 0xd3438d2f +1, 98304, 98304, 4096, 6075, 0xd6019fbf +1, 102400, 102400, 4096, 9597, 0x28f46a38 +1, 106496, 106496, 4096, 10287, 0x9dbf0938 +1, 110592, 110592, 4096, 10537, 0xc417fb81 +1, 114688, 114688, 4096, 10360, 0xc580caa3 +1, 118784, 118784, 4096, 9778, 0xb9c2d3e5 +1, 122880, 122880, 4096, 10307, 0x05b1b271 +1, 126976, 126976, 4096, 11289, 0x97f07c63 +1, 131072, 131072, 4096, 11561, 0x8a45194a +1, 135168, 135168, 4096, 11327, 0x86587829 +1, 139264, 139264, 4096, 11347, 0x15659d6e +1, 143360, 143360, 4096, 11006, 0x9a002c7f +1, 147456, 147456, 4096, 11147, 0x853955e0 +1, 151552, 151552, 4096, 11025, 0x7bdafbda +1, 155648, 155648, 4096, 11561, 0x2ec43d86 +1, 159744, 159744, 4096, 11329, 0x6eaba39a +1, 163840, 163840, 4096, 10886, 0x5c31b777 +1, 167936, 167936, 4096, 11505, 0xcd7f2b9a +1, 172032, 172032, 4096, 11243, 0xa1cb6c83 +1, 176128, 176128, 4096, 11718, 0x5b0d6e74 +1, 180224, 180224, 4096, 11898, 0xa649ca9a +1, 184320, 184320, 4096, 11358, 0x037bc2f4 +1, 188416, 188416, 4096, 10864, 0x9239d22f +1, 192512, 192512, 4096, 12181, 0xd5c24fba +1, 196608, 196608, 4096, 11551, 0xa0d8c8d1 +1, 200704, 200704, 4096, 10858, 0x330fcbd8 +1, 204800, 204800, 4096, 9918, 0xd64a0ae4 +1, 208896, 208896, 4096, 9944, 0x0627d87a +1, 212992, 212992, 4096, 9490, 0xa8cc1e93 +1, 217088, 217088, 4096, 9427, 0xb2b6db53 +1, 221184, 221184, 4096, 9799, 0x23ef915a +1, 225280, 225280, 4096, 9544, 0x79fb4344 +1, 229376, 229376, 4096, 12091, 0xdc2e58e4 +1, 233472, 233472, 4096, 11079, 0xe23d2e0e +1, 237568, 237568, 4096, 10772, 0xec04a623 +1, 241664, 241664, 4096, 11608, 0x9ab81556 +1, 245760, 245760, 4096, 10744, 0x538c70fa +1, 249856, 249856, 4096, 10316, 0xfc26a3bf +1, 253952, 253952, 4096, 11768, 0x20a1590f +1, 258048, 258048, 4096, 11283, 0xd6cb802d +1, 262144, 262144, 4096, 10112, 0xf1de16a2 +1, 266240, 266240, 4096, 12051, 0x881feda5 +1, 270336, 270336, 4096, 11348, 0xede7baab +1, 274432, 274432, 4096, 10816, 0x816c90c7 +1, 278528, 278528, 4096, 12319, 0x1750b376 +1, 282624, 282624, 4096, 11228, 0x8db96bea +1, 286720, 286720, 4096, 10217, 0x7503aeb2 +1, 290816, 290816, 4096, 12084, 0x36dde3c4 +1, 294912, 294912, 4096, 11697, 0xa16f51f7 +1, 299008, 299008, 4096, 10977, 0xf5b026e4 +1, 303104, 303104, 4096, 10459, 0xcab7f410 +1, 307200, 307200, 4096, 10287, 0x910baac6 +1, 311296, 311296, 4096, 10313, 0x5c0ca807 +1, 315392, 315392, 4096, 10018, 0x366a00da +1, 319488, 319488, 4096, 10250, 0x69459be7 +1, 323584, 323584, 4096, 9947, 0x5d8efc8e +1, 327680, 327680, 4096, 11550, 0xb90d385c +1, 331776, 331776, 4096, 11249, 0xb93f8093 +1, 335872, 335872, 4096, 11168, 0xe8fb345a +1, 339968, 339968, 4096, 11389, 0xa0eebbe6 +1, 344064, 344064, 4096, 10632, 0xc4646a98 +1, 348160, 348160, 4096, 11055, 0x5b2c3bb5 +1, 352256, 352256, 4096, 11551, 0xc6951ab2 +1, 356352, 356352, 4096, 11495, 0xde18135a +1, 360448, 360448, 4096, 11141, 0x98a92ed5 +1, 364544, 364544, 4096, 11272, 0x99837e81 +1, 368640, 368640, 4096, 10973, 0xfc8b1294 +1, 372736, 372736, 4096, 10754, 0x562f8fcc +1, 376832, 376832, 4096, 11784, 0x8a114dde +1, 380928, 380928, 4096, 11358, 0x8405af06 +1, 385024, 385024, 4096, 11194, 0x164570f6 +1, 389120, 389120, 4096, 11512, 0x8358d96f +1, 393216, 393216, 4096, 12245, 0x206d6330 +1, 397312, 397312, 4096, 11556, 0x2412fc6c +1, 401408, 401408, 4096, 10997, 0x8e31e829 +1, 405504, 405504, 4096, 9927, 0x7eb2f59a +1, 409600, 409600, 4096, 9797, 0x51089850 +1, 413696, 413696, 4096, 9648, 0xf29a7d52 +1, 417792, 417792, 4096, 9077, 0xddc149ad +1, 421888, 421888, 4096, 9759, 0x38d0b78d +1, 425984, 425984, 4096, 10347, 0x3073bad7 +1, 430080, 430080, 4096, 11585, 0x114310ec +1, 434176, 434176, 4096, 11137, 0x6f420692 +1, 438272, 438272, 4096, 11099, 0xf9810272 +1, 442368, 442368, 4096, 11682, 0xe68452b7 +1, 446464, 446464, 4096, 11186, 0x899175ec +1, 450560, 450560, 4096, 9933, 0xac27d52f +1, 454656, 454656, 4096, 11609, 0xb6e31541 +1, 458752, 458752, 4096, 11632, 0x4898412b +1, 462848, 462848, 4096, 11132, 0x6a3d6295 +1, 466944, 466944, 4096, 11960, 0xcc76d187 +1, 471040, 471040, 4096, 11196, 0x384f57ef +1, 475136, 475136, 4096, 10619, 0x0e6d2961 +1, 479232, 479232, 4096, 11867, 0x7fe3b947 +1, 483328, 483328, 4096, 11190, 0x28785152 +1, 487424, 487424, 4096, 10375, 0xc67a06dc +1, 491520, 491520, 4096, 11959, 0xcc9a0e02 +1, 495616, 495616, 4096, 11400, 0x67e6d6e7 +1, 499712, 499712, 4096, 9897, 0x5db7d50f +1, 503808, 503808, 4096, 11460, 0x753cc6b9 +1, 507904, 507904, 4096, 11375, 0x76e9d803 +1, 512000, 512000, 4096, 11105, 0x22f71d1c +1, 516096, 516096, 4096, 10949, 0x7951202a +1, 520192, 520192, 4085, 11292, 0x8fc9ca01 From 171adca696ee1f507d698940a35ccf7a85c5d072 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 27 Oct 2017 08:26:11 +0800 Subject: [PATCH 0619/2557] Revert "flvdec: Check the avio_seek return value after reading a metadata packet" This reverts commit ef7fe81b8554a2865d47a55edf47420878fa3d91. --- libavformat/flvdec.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 2d89bef15f25b..2e70352c5374c 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -1015,13 +1015,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) "Skipping flv packet: type %d, size %d, flags %d.\n", type, size, flags); skip: - if (avio_seek(s->pb, next, SEEK_SET) != next) { - // This can happen if flv_read_metabody above read past - // next, on a non-seekable input, and the preceding data has - // been flushed out from the IO buffer. - av_log(s, AV_LOG_ERROR, "Unable to seek to the next packet\n"); - return AVERROR_INVALIDDATA; - } + avio_seek(s->pb, next, SEEK_SET); ret = FFERROR_REDO; goto leave; } From 15537c904ec96e4d2e9435100d403283a5fed029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 27 Oct 2017 08:27:43 +0800 Subject: [PATCH 0620/2557] flvdec: Check the avio_seek return value after reading a metadata packet merge from libav: 585dc1aecef0371ad6f16cb3750ae2a6da9cf00a If the metadata packet is corrupted, flv_read_metabody can accidentally read past the start of the next packet. If the start of the next packet had been flushed out of the IO buffer, we would be unable to seek to the right position (on a nonseekable stream). Prefer to clearly error out instead of silently trying to read from a desynced stream which will only be interpreted as garbage. --- libavformat/flvdec.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 2e70352c5374c..2d89bef15f25b 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -1015,7 +1015,13 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) "Skipping flv packet: type %d, size %d, flags %d.\n", type, size, flags); skip: - avio_seek(s->pb, next, SEEK_SET); + if (avio_seek(s->pb, next, SEEK_SET) != next) { + // This can happen if flv_read_metabody above read past + // next, on a non-seekable input, and the preceding data has + // been flushed out from the IO buffer. + av_log(s, AV_LOG_ERROR, "Unable to seek to the next packet\n"); + return AVERROR_INVALIDDATA; + } ret = FFERROR_REDO; goto leave; } From 273f11969d1d2abc75e53a9baed5d86855e794b0 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Fri, 27 Oct 2017 02:42:25 +0200 Subject: [PATCH 0621/2557] fate: fix ffmpeg-attached_pics test dependencies Signed-off-by: Marton Balint --- tests/fate/ffmpeg.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 607cc79649786..a806c05d45025 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -31,7 +31,7 @@ FATE_FFMPEG-$(call ALLYES, AEVALSRC_FILTER ASETNSAMPLES_FILTER AC3_FIXED_ENCODER fate-ffmpeg-filter_complex_audio: CMD = framecrc -filter_complex "aevalsrc=0:d=0.1,asetnsamples=1537" -c ac3_fixed # Ticket 6375 -FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER ALAC_DECODER ALAC_ENCODER) += fate-ffmpeg-attached_pics +FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER PNG_DECODER ALAC_DECODER ALAC_ENCODER) += fate-ffmpeg-attached_pics fate-ffmpeg-attached_pics: CMD = threads=2 framecrc -i $(TARGET_SAMPLES)/lossless-audio/inside.m4a -acodec alac -max_muxing_queue_size 16 FATE_SAMPLES_FFMPEG-$(CONFIG_COLORKEY_FILTER) += fate-ffmpeg-filter_colorkey From 5834cba05efbfd24dadedd187753f244ad7e0cab Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 27 Oct 2017 00:33:13 -0300 Subject: [PATCH 0622/2557] MAINTAINERS: add my GPG fingerprint Signed-off-by: James Almer --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1d2ff78b0e88f..1bc2c59839adc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -586,6 +586,7 @@ FFmpeg release signing key FCF9 86EA 15E6 E293 A564 4F10 B432 2F04 D676 58D8 Ganesh Ajjanagadde C96A 848E 97C3 CEA2 AB72 5CE4 45F9 6A2D 3C36 FB1B Gwenole Beauchesne 2E63 B3A6 3E44 37E2 017D 2704 53C7 6266 B153 99C4 Jaikrishnan Menon 61A1 F09F 01C9 2D45 78E1 C862 25DC 8831 AF70 D368 +James Almer 7751 2E8C FD94 A169 57E6 9A7A 1463 01AD 7376 59E0 Jean Delvare 7CA6 9F44 60F1 BDC4 1FD2 C858 A552 6B9B B3CD 4E6A Loren Merritt ABD9 08F4 C920 3F65 D8BE 35D7 1540 DAA7 060F 56DE Lou Logan 7D68 DC73 CBEF EABB 671A B6CF 621C 2E28 82F8 DC3A From 0e702124ee149593168cbbb7b30376249a64ae66 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 13 Oct 2017 12:24:51 +0200 Subject: [PATCH 0623/2557] doc: Provide better examples for hls and segment muxing Some encoders do not output further IDRs if not requested to. --- doc/muxers.texi | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 62cd8d025b142..8c34322e7970b 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -163,8 +163,11 @@ filename specifies the playlist filename; the segment filenames receive the same basename as the playlist, a sequential number and a .ts extension. +Make sure to require a closed GOP when encoding and to set the GOP +size to fit your segment time constraint. + @example -avconv -i in.nut out.m3u8 +avconv -i in.mkv -c:v h264 -flags +cgop -g 30 -hls_time 1 out.m3u8 @end example @table @option @@ -625,8 +628,11 @@ Prepend @var{prefix} to each entry. Useful to generate absolute paths. Wrap around segment index once it reaches @var{limit}. @end table +Make sure to require a closed GOP when encoding and to set the GOP +size to fit your segment time constraint. + @example -avconv -i in.mkv -c copy -map 0 -f segment -list out.list out%03d.nut +avconv -i in.mkv -c hevc -flags +cgop -g 60 -map 0 -f segment -list out.list out%03d.nut @end example @c man end MUXERS From 4723c6226aa1ece4099338cc9b38a9cef4fa4846 Mon Sep 17 00:00:00 2001 From: Anton Schubert Date: Thu, 26 Oct 2017 18:02:04 +0200 Subject: [PATCH 0624/2557] dashenc: fix bitrate estimation with correct scaling Signed-off-by: Anton Schubert Signed-off-by: Luca Barbato --- libavformat/dashenc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 336cea24ec33b..4f8d7d85dc0f4 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1040,6 +1040,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; + AVStream *st = s->streams[i]; char filename[1024] = "", full_path[1024], temp_path[1024]; int range_length, index_length = 0; @@ -1091,7 +1092,9 @@ static int dash_flush(AVFormatContext *s, int final, int stream) if (!os->bit_rate) { // calculate average bitrate of first segment - int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / (os->max_pts - os->start_pts); + int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / av_rescale_q(os->max_pts - os->start_pts, + st->time_base, + AV_TIME_BASE_Q); if (bitrate >= 0) { os->bit_rate = bitrate; snprintf(os->bandwidth_str, sizeof(os->bandwidth_str), From 91760a934055ab06812885ab5ec1a97a8db6d217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Gro=C3=9Fe?= Date: Thu, 26 Oct 2017 18:02:05 +0200 Subject: [PATCH 0625/2557] dashenc: copy stream frame rate to output stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Leads to setting of DefaultDuration in Matroska muxer based on frame rate instead of timebase. Fixes playback in Chrome. Signed-off-by: Peter Große Signed-off-by: Luca Barbato --- libavformat/dashenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 4f8d7d85dc0f4..23d33dbb0584b 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -870,6 +870,7 @@ static int dash_write_header(AVFormatContext *s) avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar); st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; st->time_base = s->streams[i]->time_base; + st->avg_frame_rate = s->streams[i]->avg_frame_rate; ctx->avoid_negative_ts = s->avoid_negative_ts; if ((ret = avio_open_dyn_buf(&ctx->pb)) < 0) From 2d11218877a5734ab1c5a97a650d0c74de0022ee Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 27 Oct 2017 19:41:38 -0300 Subject: [PATCH 0626/2557] avcodec/audiotoolboxdec: fix ac3_parser header include --- libavcodec/audiotoolboxdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/audiotoolboxdec.c b/libavcodec/audiotoolboxdec.c index a149949abaaea..3711665bbdca7 100644 --- a/libavcodec/audiotoolboxdec.c +++ b/libavcodec/audiotoolboxdec.c @@ -24,7 +24,7 @@ #include "config.h" #include "avcodec.h" -#include "ac3_parser.h" +#include "ac3_parser_internal.h" #include "bytestream.h" #include "internal.h" #include "mpegaudiodecheader.h" From 851829455889cfefee8d802d8428ed36effb9fcf Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Thu, 26 Oct 2017 16:52:22 +0200 Subject: [PATCH 0627/2557] lswr/swresample: Mention the actually supported formats when erroring out. Fixes ticket #6779. --- libswresample/swresample.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 74c96dce605e4..f076b6c8cfa59 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -240,7 +240,7 @@ av_cold int swr_init(struct SwrContext *s){ &&s->int_sample_fmt != AV_SAMPLE_FMT_S64P &&s->int_sample_fmt != AV_SAMPLE_FMT_FLTP &&s->int_sample_fmt != AV_SAMPLE_FMT_DBLP){ - av_log(s, AV_LOG_ERROR, "Requested sample format %s is not supported internally, S16/S32/S64/FLT/DBL is supported\n", av_get_sample_fmt_name(s->int_sample_fmt)); + av_log(s, AV_LOG_ERROR, "Requested sample format %s is not supported internally, s16p/s32p/s64p/fltp/dblp are supported\n", av_get_sample_fmt_name(s->int_sample_fmt)); return AVERROR(EINVAL); } @@ -276,7 +276,7 @@ av_cold int swr_init(struct SwrContext *s){ && s->int_sample_fmt != AV_SAMPLE_FMT_FLTP && s->int_sample_fmt != AV_SAMPLE_FMT_DBLP && s->resample){ - av_log(s, AV_LOG_ERROR, "Resampling only supported with internal s16/s32/flt/dbl\n"); + av_log(s, AV_LOG_ERROR, "Resampling only supported with internal s16p/s32p/fltp/dblp\n"); ret = AVERROR(EINVAL); goto fail; } From aba926e7d654b6dfab680130c92e571ee9a956f0 Mon Sep 17 00:00:00 2001 From: Bjorn Roche Date: Mon, 23 Oct 2017 19:12:57 -0400 Subject: [PATCH 0628/2557] lavfi/paletteuse: fix to support transparency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch enables paletteuse to identify the transparency in incoming video and tag transparent pixels on outgoing video with the correct index from the palette. This requires tracking the transparency index in the palette, establishing an alpha threshold below which a pixel is considered transparent and above which the pixel is considered opaque, and additional changes to track the alpha value throughout the conversion process. This change is a partial fix for https://trac.ffmpeg.org/ticket/4443 However, animated GIFs are still output incorrectly due to a bug in gif optimization which does not correctly handle transparency. Signed-off-by: Clément Bœsch --- doc/filters.texi | 7 ++ libavfilter/vf_paletteuse.c | 195 +++++++++++++++++++++++------------- 2 files changed, 131 insertions(+), 71 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index ce7e053194b8a..64e84d9b452ee 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -11545,6 +11545,13 @@ Default is @var{none}. @item new Take new palette for each output frame. + +@item alpha_threshold +Sets the alpha threshold for transparency. Alpha values above this threshold +will be treated as completely opaque, and values below this threshold will be +treated as completely transparent. + +The option must be an integer value in the range [0,255]. Default is @var{128}. @end table @subsection Examples diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 79a06728919e9..fdd3e838b0e4d 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -56,7 +56,7 @@ enum diff_mode { }; struct color_node { - uint8_t val[3]; + uint8_t val[4]; uint8_t palette_id; int split; int left_id, right_id; @@ -86,6 +86,8 @@ typedef struct PaletteUseContext { struct cache_node cache[CACHE_SIZE]; /* lookup cache */ struct color_node map[AVPALETTE_COUNT]; /* 3D-Tree (KD-Tree with K=3) for reverse colormap */ uint32_t palette[AVPALETTE_COUNT]; + int transparency_index; /* index in the palette of transparency. -1 if there is no transparency in the palette. */ + int trans_thresh; int palette_loaded; int dither; int new; @@ -116,6 +118,7 @@ static const AVOption paletteuse_options[] = { { "bayer_scale", "set scale for bayer dithering", OFFSET(bayer_scale), AV_OPT_TYPE_INT, {.i64=2}, 0, 5, FLAGS }, { "diff_mode", "set frame difference mode", OFFSET(diff_mode), AV_OPT_TYPE_INT, {.i64=DIFF_MODE_NONE}, 0, NB_DIFF_MODE-1, FLAGS, "diff_mode" }, { "rectangle", "process smallest different rectangle", 0, AV_OPT_TYPE_CONST, {.i64=DIFF_MODE_RECTANGLE}, INT_MIN, INT_MAX, FLAGS, "diff_mode" }, + { "alpha_threshold", "set the alpha threshold for transparency", OFFSET(trans_thresh), AV_OPT_TYPE_INT, {.i64=128}, 0, 255 }, /* following are the debug options, not part of the official API */ { "debug_kdtree", "save Graphviz graph of the kdtree in specified file", OFFSET(dot_filename), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, @@ -157,34 +160,43 @@ static int query_formats(AVFilterContext *ctx) static av_always_inline int dither_color(uint32_t px, int er, int eg, int eb, int scale, int shift) { - return av_clip_uint8((px >> 16 & 0xff) + ((er * scale) / (1<> 24 ) << 24 + | av_clip_uint8((px >> 16 & 0xff) + ((er * scale) / (1<> 8 & 0xff) + ((eg * scale) / (1<= trans_thresh && c2[0] >= trans_thresh) { + return dr*dr + dg*dg + db*db; + } else { + return 255*255 + 255*255 + 255*255; + } } -static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *palette, const uint8_t *rgb) +static av_always_inline uint8_t colormap_nearest_bruteforce(const uint32_t *palette, const uint8_t *argb, const int trans_thresh) { int i, pal_id = -1, min_dist = INT_MAX; for (i = 0; i < AVPALETTE_COUNT; i++) { const uint32_t c = palette[i]; - if ((c & 0xff000000) == 0xff000000) { // ignore transparent entry - const uint8_t palrgb[] = { + if (c >> 24 >= trans_thresh) { // ignore transparent entry + const uint8_t palargb[] = { + palette[i]>>24 & 0xff, palette[i]>>16 & 0xff, palette[i]>> 8 & 0xff, palette[i] & 0xff, }; - const int d = diff(palrgb, rgb); + const int d = diff(palargb, argb, trans_thresh); if (d < min_dist) { pal_id = i; min_dist = d; @@ -203,13 +215,14 @@ struct nearest_color { static void colormap_nearest_node(const struct color_node *map, const int node_pos, const uint8_t *target, + const int trans_thresh, struct nearest_color *nearest) { const struct color_node *kd = map + node_pos; const int s = kd->split; int dx, nearer_kd_id, further_kd_id; const uint8_t *current = kd->val; - const int current_to_target = diff(target, current); + const int current_to_target = diff(target, current, trans_thresh); if (current_to_target < nearest->dist_sqd) { nearest->node_pos = node_pos; @@ -223,17 +236,17 @@ static void colormap_nearest_node(const struct color_node *map, else nearer_kd_id = kd->right_id, further_kd_id = kd->left_id; if (nearer_kd_id != -1) - colormap_nearest_node(map, nearer_kd_id, target, nearest); + colormap_nearest_node(map, nearer_kd_id, target, trans_thresh, nearest); if (further_kd_id != -1 && dx*dx < nearest->dist_sqd) - colormap_nearest_node(map, further_kd_id, target, nearest); + colormap_nearest_node(map, further_kd_id, target, trans_thresh, nearest); } } -static av_always_inline uint8_t colormap_nearest_recursive(const struct color_node *node, const uint8_t *rgb) +static av_always_inline uint8_t colormap_nearest_recursive(const struct color_node *node, const uint8_t *rgb, const int trans_thresh) { struct nearest_color res = {.dist_sqd = INT_MAX, .node_pos = -1}; - colormap_nearest_node(node, 0, rgb, &res); + colormap_nearest_node(node, 0, rgb, trans_thresh, &res); return node[res.node_pos].palette_id; } @@ -242,7 +255,7 @@ struct stack_node { int dx2; }; -static av_always_inline uint8_t colormap_nearest_iterative(const struct color_node *root, const uint8_t *target) +static av_always_inline uint8_t colormap_nearest_iterative(const struct color_node *root, const uint8_t *target, const int trans_thresh) { int pos = 0, best_node_id = -1, best_dist = INT_MAX, cur_color_id = 0; struct stack_node nodes[16]; @@ -252,7 +265,7 @@ static av_always_inline uint8_t colormap_nearest_iterative(const struct color_no const struct color_node *kd = &root[cur_color_id]; const uint8_t *current = kd->val; - const int current_to_target = diff(target, current); + const int current_to_target = diff(target, current, trans_thresh); /* Compare current color node to the target and update our best node if * it's actually better. */ @@ -314,25 +327,27 @@ static av_always_inline uint8_t colormap_nearest_iterative(const struct color_no return root[best_node_id].palette_id; } -#define COLORMAP_NEAREST(search, palette, root, target) \ - search == COLOR_SEARCH_NNS_ITERATIVE ? colormap_nearest_iterative(root, target) : \ - search == COLOR_SEARCH_NNS_RECURSIVE ? colormap_nearest_recursive(root, target) : \ - colormap_nearest_bruteforce(palette, target) +#define COLORMAP_NEAREST(search, palette, root, target, trans_thresh) \ + search == COLOR_SEARCH_NNS_ITERATIVE ? colormap_nearest_iterative(root, target, trans_thresh) : \ + search == COLOR_SEARCH_NNS_RECURSIVE ? colormap_nearest_recursive(root, target, trans_thresh) : \ + colormap_nearest_bruteforce(palette, target, trans_thresh) /** * Check if the requested color is in the cache already. If not, find it in the * color tree and cache it. - * Note: r, g, and b are the component of c but are passed as well to avoid + * Note: a, r, g, and b are the components of color, but are passed as well to avoid * recomputing them (they are generally computed by the caller for other uses). */ static av_always_inline int color_get(struct cache_node *cache, uint32_t color, - uint8_t r, uint8_t g, uint8_t b, + uint8_t a, uint8_t r, uint8_t g, uint8_t b, + int transparency_index, + int trans_thresh, const struct color_node *map, const uint32_t *palette, const enum color_search_method search_method) { int i; - const uint8_t rgb[] = {r, g, b}; + const uint8_t argb_elts[] = {a, r, g, b}; const uint8_t rhash = r & ((1<= 0) { + return transparency_index; + } + for (i = 0; i < node->nb_entries; i++) { e = &node->entries[i]; if (e->color == color) @@ -351,20 +371,24 @@ static av_always_inline int color_get(struct cache_node *cache, uint32_t color, if (!e) return AVERROR(ENOMEM); e->color = color; - e->pal_entry = COLORMAP_NEAREST(search_method, palette, map, rgb); + e->pal_entry = COLORMAP_NEAREST(search_method, palette, map, argb_elts, trans_thresh); + return e->pal_entry; } static av_always_inline int get_dst_color_err(struct cache_node *cache, uint32_t c, const struct color_node *map, const uint32_t *palette, + int transparency_index, + int trans_thresh, int *er, int *eg, int *eb, const enum color_search_method search_method) { + const uint8_t a = c >> 24 & 0xff; const uint8_t r = c >> 16 & 0xff; const uint8_t g = c >> 8 & 0xff; const uint8_t b = c & 0xff; - const int dstx = color_get(cache, c, r, g, b, map, palette, search_method); + const int dstx = color_get(cache, c, a, r, g, b, transparency_index, trans_thresh, map, palette, search_method); const uint32_t dstc = palette[dstx]; *er = r - (dstc >> 16 & 0xff); *eg = g - (dstc >> 8 & 0xff); @@ -385,6 +409,8 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram const int dst_linesize = out->linesize[0]; uint32_t *src = ((uint32_t *)in ->data[0]) + y_start*src_linesize; uint8_t *dst = out->data[0] + y_start*dst_linesize; + int transparency_index = s->transparency_index; + int trans_thresh = s->trans_thresh; w += x_start; h += y_start; @@ -395,14 +421,14 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram if (dither == DITHERING_BAYER) { const int d = s->ordered_dither[(y & 7)<<3 | (x & 7)]; + const uint8_t a8 = src[x] >> 24 & 0xff; const uint8_t r8 = src[x] >> 16 & 0xff; const uint8_t g8 = src[x] >> 8 & 0xff; const uint8_t b8 = src[x] & 0xff; const uint8_t r = av_clip_uint8(r8 + d); const uint8_t g = av_clip_uint8(g8 + d); const uint8_t b = av_clip_uint8(b8 + d); - const uint32_t c = r<<16 | g<<8 | b; - const int color = color_get(cache, c, r, g, b, map, palette, search_method); + const int color = color_get(cache, src[x], a8, r, g, b, transparency_index, trans_thresh, map, palette, search_method); if (color < 0) return color; @@ -410,7 +436,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram } else if (dither == DITHERING_HECKBERT) { const int right = x < w - 1, down = y < h - 1; - const int color = get_dst_color_err(cache, src[x], map, palette, &er, &eg, &eb, search_method); + const int color = get_dst_color_err(cache, src[x], map, palette, transparency_index, trans_thresh, &er, &eg, &eb, search_method); if (color < 0) return color; @@ -422,7 +448,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram } else if (dither == DITHERING_FLOYD_STEINBERG) { const int right = x < w - 1, down = y < h - 1, left = x > x_start; - const int color = get_dst_color_err(cache, src[x], map, palette, &er, &eg, &eb, search_method); + const int color = get_dst_color_err(cache, src[x], map, palette, transparency_index, trans_thresh, &er, &eg, &eb, search_method); if (color < 0) return color; @@ -436,7 +462,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram } else if (dither == DITHERING_SIERRA2) { const int right = x < w - 1, down = y < h - 1, left = x > x_start; const int right2 = x < w - 2, left2 = x > x_start + 1; - const int color = get_dst_color_err(cache, src[x], map, palette, &er, &eg, &eb, search_method); + const int color = get_dst_color_err(cache, src[x], map, palette, transparency_index, trans_thresh, &er, &eg, &eb, search_method); if (color < 0) return color; @@ -455,7 +481,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram } else if (dither == DITHERING_SIERRA2_4A) { const int right = x < w - 1, down = y < h - 1, left = x > x_start; - const int color = get_dst_color_err(cache, src[x], map, palette, &er, &eg, &eb, search_method); + const int color = get_dst_color_err(cache, src[x], map, palette, transparency_index, trans_thresh, &er, &eg, &eb, search_method); if (color < 0) return color; @@ -466,10 +492,11 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram if ( down) src[src_linesize + x ] = dither_color(src[src_linesize + x ], er, eg, eb, 1, 2); } else { + const uint8_t a = src[x] >> 24 & 0xff; const uint8_t r = src[x] >> 16 & 0xff; const uint8_t g = src[x] >> 8 & 0xff; const uint8_t b = src[x] & 0xff; - const int color = color_get(cache, src[x] & 0xffffff, r, g, b, map, palette, search_method); + const int color = color_get(cache, src[x], a, r, g, b, transparency_index, trans_thresh, map, palette, search_method); if (color < 0) return color; @@ -489,19 +516,19 @@ static void disp_node(AVBPrint *buf, int depth) { const struct color_node *node = &map[node_id]; - const uint32_t fontcolor = node->val[0] > 0x50 && - node->val[1] > 0x50 && - node->val[2] > 0x50 ? 0 : 0xffffff; + const uint32_t fontcolor = node->val[1] > 0x50 && + node->val[2] > 0x50 && + node->val[3] > 0x50 ? 0 : 0xffffff; av_bprintf(buf, "%*cnode%d [" "label=\"%c%02X%c%02X%c%02X%c\" " "fillcolor=\"#%02x%02x%02x\" " "fontcolor=\"#%06"PRIX32"\"]\n", depth*INDENT, ' ', node->palette_id, - "[ "[node->split], node->val[0], - "][ "[node->split], node->val[1], - " ]["[node->split], node->val[2], + "[ "[node->split], node->val[1], + "][ "[node->split], node->val[2], + " ]["[node->split], node->val[3], " ]"[node->split], - node->val[0], node->val[1], node->val[2], + node->val[1], node->val[2], node->val[3], fontcolor); if (parent_id != -1) av_bprintf(buf, "%*cnode%d -> node%d\n", depth*INDENT, ' ', @@ -536,7 +563,7 @@ static int disp_tree(const struct color_node *node, const char *fname) return 0; } -static int debug_accuracy(const struct color_node *node, const uint32_t *palette, +static int debug_accuracy(const struct color_node *node, const uint32_t *palette, const int trans_thresh, const enum color_search_method search_method) { int r, g, b, ret = 0; @@ -545,15 +572,15 @@ static int debug_accuracy(const struct color_node *node, const uint32_t *palette for (g = 0; g < 256; g++) { for (b = 0; b < 256; b++) { const uint8_t rgb[] = {r, g, b}; - const int r1 = COLORMAP_NEAREST(search_method, palette, node, rgb); - const int r2 = colormap_nearest_bruteforce(palette, rgb); + const int r1 = COLORMAP_NEAREST(search_method, palette, node, rgb, trans_thresh); + const int r2 = colormap_nearest_bruteforce(palette, rgb, trans_thresh); if (r1 != r2) { const uint32_t c1 = palette[r1]; const uint32_t c2 = palette[r2]; const uint8_t palrgb1[] = { c1>>16 & 0xff, c1>> 8 & 0xff, c1 & 0xff }; const uint8_t palrgb2[] = { c2>>16 & 0xff, c2>> 8 & 0xff, c2 & 0xff }; - const int d1 = diff(palrgb1, rgb); - const int d2 = diff(palrgb2, rgb); + const int d1 = diff(palrgb1, rgb, trans_thresh); + const int d2 = diff(palrgb2, rgb, trans_thresh); if (d1 != d2) { av_log(NULL, AV_LOG_ERROR, "/!\\ %02X%02X%02X: %d ! %d (%06"PRIX32" ! %06"PRIX32") / dist: %d ! %d\n", @@ -584,17 +611,19 @@ static int cmp_##name(const void *pa, const void *pb) \ { \ const struct color *a = pa; \ const struct color *b = pb; \ - return (a->value >> (8 * (2 - (pos))) & 0xff) \ - - (b->value >> (8 * (2 - (pos))) & 0xff); \ + return (a->value >> (8 * (3 - (pos))) & 0xff) \ + - (b->value >> (8 * (3 - (pos))) & 0xff); \ } -DECLARE_CMP_FUNC(r, 0) -DECLARE_CMP_FUNC(g, 1) -DECLARE_CMP_FUNC(b, 2) +DECLARE_CMP_FUNC(a, 0) +DECLARE_CMP_FUNC(r, 1) +DECLARE_CMP_FUNC(g, 2) +DECLARE_CMP_FUNC(b, 3) -static const cmp_func cmp_funcs[] = {cmp_r, cmp_g, cmp_b}; +static const cmp_func cmp_funcs[] = {cmp_a, cmp_r, cmp_g, cmp_b}; static int get_next_color(const uint8_t *color_used, const uint32_t *palette, + const int trans_thresh, int *component, const struct color_rect *box) { int wr, wg, wb; @@ -609,11 +638,16 @@ static int get_next_color(const uint8_t *color_used, const uint32_t *palette, for (i = 0; i < AVPALETTE_COUNT; i++) { const uint32_t c = palette[i]; + const uint8_t a = c >> 24 & 0xff; const uint8_t r = c >> 16 & 0xff; const uint8_t g = c >> 8 & 0xff; const uint8_t b = c & 0xff; - if (color_used[i] || + if (a < trans_thresh) { + continue; + } + + if (color_used[i] || (a != 0xff) || r < box->min[0] || g < box->min[1] || b < box->min[2] || r > box->max[0] || g > box->max[1] || b > box->max[2]) continue; @@ -639,9 +673,9 @@ static int get_next_color(const uint8_t *color_used, const uint32_t *palette, wr = ranges.max[0] - ranges.min[0]; wg = ranges.max[1] - ranges.min[1]; wb = ranges.max[2] - ranges.min[2]; - if (wr >= wg && wr >= wb) longest = 0; - if (wg >= wr && wg >= wb) longest = 1; - if (wb >= wr && wb >= wg) longest = 2; + if (wr >= wg && wr >= wb) longest = 1; + if (wg >= wr && wg >= wb) longest = 2; + if (wb >= wr && wb >= wg) longest = 3; cmpf = cmp_funcs[longest]; *component = longest; @@ -655,6 +689,7 @@ static int colormap_insert(struct color_node *map, uint8_t *color_used, int *nb_used, const uint32_t *palette, + const int trans_thresh, const struct color_rect *box) { uint32_t c; @@ -662,7 +697,7 @@ static int colormap_insert(struct color_node *map, int node_left_id = -1, node_right_id = -1; struct color_node *node; struct color_rect box1, box2; - const int pal_id = get_next_color(color_used, palette, &component, box); + const int pal_id = get_next_color(color_used, palette, trans_thresh, &component, box); if (pal_id < 0) return -1; @@ -673,21 +708,22 @@ static int colormap_insert(struct color_node *map, node = &map[cur_id]; node->split = component; node->palette_id = pal_id; - node->val[0] = c>>16 & 0xff; - node->val[1] = c>> 8 & 0xff; - node->val[2] = c & 0xff; + node->val[0] = c>>24 & 0xff; + node->val[1] = c>>16 & 0xff; + node->val[2] = c>> 8 & 0xff; + node->val[3] = c & 0xff; color_used[pal_id] = 1; /* get the two boxes this node creates */ box1 = box2 = *box; - box1.max[component] = node->val[component]; - box2.min[component] = node->val[component] + 1; + box1.max[component-1] = node->val[component]; + box2.min[component-1] = node->val[component] + 1; - node_left_id = colormap_insert(map, color_used, nb_used, palette, &box1); + node_left_id = colormap_insert(map, color_used, nb_used, palette, trans_thresh, &box1); - if (box2.min[component] <= box2.max[component]) - node_right_id = colormap_insert(map, color_used, nb_used, palette, &box2); + if (box2.min[component-1] <= box2.max[component-1]) + node_right_id = colormap_insert(map, color_used, nb_used, palette, trans_thresh, &box2); node->left_id = node_left_id; node->right_id = node_right_id; @@ -711,6 +747,16 @@ static void load_colormap(PaletteUseContext *s) /* disable transparent colors and dups */ qsort(s->palette, AVPALETTE_COUNT, sizeof(*s->palette), cmp_pal_entry); + // update transparency index: + if (s->transparency_index >= 0) { + for (i = 0; i < AVPALETTE_COUNT; i++) { + if ((s->palette[i]>>24 & 0xff) == 0) { + s->transparency_index = i; // we are assuming at most one transparent color in palette + break; + } + } + } + for (i = 0; i < AVPALETTE_COUNT; i++) { const uint32_t c = s->palette[i]; if (i != 0 && c == last_color) { @@ -718,7 +764,7 @@ static void load_colormap(PaletteUseContext *s) continue; } last_color = c; - if ((c & 0xff000000) != 0xff000000) { + if (c >> 24 < s->trans_thresh) { color_used[i] = 1; // ignore transparent color(s) continue; } @@ -727,13 +773,13 @@ static void load_colormap(PaletteUseContext *s) box.min[0] = box.min[1] = box.min[2] = 0x00; box.max[0] = box.max[1] = box.max[2] = 0xff; - colormap_insert(s->map, color_used, &nb_used, s->palette, &box); + colormap_insert(s->map, color_used, &nb_used, s->palette, s->trans_thresh, &box); if (s->dot_filename) disp_tree(s->map, s->dot_filename); if (s->debug_accuracy) { - if (!debug_accuracy(s->map, s->palette, s->color_search_method)) + if (!debug_accuracy(s->map, s->palette, s->trans_thresh, s->color_search_method)) av_log(NULL, AV_LOG_INFO, "Accuracy check passed\n"); } } @@ -756,7 +802,7 @@ static void debug_mean_error(PaletteUseContext *s, const AVFrame *in1, const uint32_t c2 = palette[src2[x]]; const uint8_t rgb1[] = {c1 >> 16 & 0xff, c1 >> 8 & 0xff, c1 & 0xff}; const uint8_t rgb2[] = {c2 >> 16 & 0xff, c2 >> 8 & 0xff, c2 & 0xff}; - mean_err += diff(rgb1, rgb2); + mean_err += diff(rgb1, rgb2, s->trans_thresh); } src1 += src1_linesize; src2 += src2_linesize; @@ -941,6 +987,8 @@ static void load_palette(PaletteUseContext *s, const AVFrame *palette_frame) const uint32_t *p = (const uint32_t *)palette_frame->data[0]; const int p_linesize = palette_frame->linesize[0] >> 2; + s->transparency_index = -1; + if (s->new) { memset(s->palette, 0, sizeof(s->palette)); memset(s->map, 0, sizeof(s->map)); @@ -951,8 +999,13 @@ static void load_palette(PaletteUseContext *s, const AVFrame *palette_frame) i = 0; for (y = 0; y < palette_frame->height; y++) { - for (x = 0; x < palette_frame->width; x++) - s->palette[i++] = p[x]; + for (x = 0; x < palette_frame->width; x++) { + s->palette[i] = p[x]; + if (p[x]>>24 < s->trans_thresh) { + s->transparency_index = i; // we are assuming at most one transparent color in palette + } + i++; + } p += p_linesize; } From 5c8e904eb38605cbce217cafb86f404bee60fd55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Sat, 28 Oct 2017 17:15:06 +0200 Subject: [PATCH 0629/2557] lavfi/paletteuse: move "new" option before debugging options --- libavfilter/vf_paletteuse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index fdd3e838b0e4d..15dddeaa1addd 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -118,6 +118,7 @@ static const AVOption paletteuse_options[] = { { "bayer_scale", "set scale for bayer dithering", OFFSET(bayer_scale), AV_OPT_TYPE_INT, {.i64=2}, 0, 5, FLAGS }, { "diff_mode", "set frame difference mode", OFFSET(diff_mode), AV_OPT_TYPE_INT, {.i64=DIFF_MODE_NONE}, 0, NB_DIFF_MODE-1, FLAGS, "diff_mode" }, { "rectangle", "process smallest different rectangle", 0, AV_OPT_TYPE_CONST, {.i64=DIFF_MODE_RECTANGLE}, INT_MIN, INT_MAX, FLAGS, "diff_mode" }, + { "new", "take new palette for each output frame", OFFSET(new), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { "alpha_threshold", "set the alpha threshold for transparency", OFFSET(trans_thresh), AV_OPT_TYPE_INT, {.i64=128}, 0, 255 }, /* following are the debug options, not part of the official API */ @@ -128,7 +129,6 @@ static const AVOption paletteuse_options[] = { { "bruteforce", "brute-force into the palette", 0, AV_OPT_TYPE_CONST, {.i64=COLOR_SEARCH_BRUTEFORCE}, INT_MIN, INT_MAX, FLAGS, "search" }, { "mean_err", "compute and print mean error", OFFSET(calc_mean_err), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { "debug_accuracy", "test color search accuracy", OFFSET(debug_accuracy), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, - { "new", "take new palette for each output frame", OFFSET(new), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { NULL } }; From 33e226f84d599bfd30eaf0687c59b6ad5e63022c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Sat, 28 Oct 2017 17:39:48 +0200 Subject: [PATCH 0630/2557] lavfi/paletteuse: simplify color get function prototypes --- libavfilter/vf_paletteuse.c | 43 +++++++++++++------------------------ 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 15dddeaa1addd..73d22a5b95a83 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -338,12 +338,8 @@ static av_always_inline uint8_t colormap_nearest_iterative(const struct color_no * Note: a, r, g, and b are the components of color, but are passed as well to avoid * recomputing them (they are generally computed by the caller for other uses). */ -static av_always_inline int color_get(struct cache_node *cache, uint32_t color, +static av_always_inline int color_get(PaletteUseContext *s, uint32_t color, uint8_t a, uint8_t r, uint8_t g, uint8_t b, - int transparency_index, - int trans_thresh, - const struct color_node *map, - const uint32_t *palette, const enum color_search_method search_method) { int i; @@ -352,12 +348,12 @@ static av_always_inline int color_get(struct cache_node *cache, uint32_t color, const uint8_t ghash = g & ((1<cache[hash]; struct cached_color *e; // first, check for transparency - if (a < trans_thresh && transparency_index >= 0) { - return transparency_index; + if (a < s->trans_thresh && s->transparency_index >= 0) { + return s->transparency_index; } for (i = 0; i < node->nb_entries; i++) { @@ -371,25 +367,21 @@ static av_always_inline int color_get(struct cache_node *cache, uint32_t color, if (!e) return AVERROR(ENOMEM); e->color = color; - e->pal_entry = COLORMAP_NEAREST(search_method, palette, map, argb_elts, trans_thresh); + e->pal_entry = COLORMAP_NEAREST(search_method, s->palette, s->map, argb_elts, s->trans_thresh); return e->pal_entry; } -static av_always_inline int get_dst_color_err(struct cache_node *cache, - uint32_t c, const struct color_node *map, - const uint32_t *palette, - int transparency_index, - int trans_thresh, - int *er, int *eg, int *eb, +static av_always_inline int get_dst_color_err(PaletteUseContext *s, + uint32_t c, int *er, int *eg, int *eb, const enum color_search_method search_method) { const uint8_t a = c >> 24 & 0xff; const uint8_t r = c >> 16 & 0xff; const uint8_t g = c >> 8 & 0xff; const uint8_t b = c & 0xff; - const int dstx = color_get(cache, c, a, r, g, b, transparency_index, trans_thresh, map, palette, search_method); - const uint32_t dstc = palette[dstx]; + const int dstx = color_get(s, c, a, r, g, b, search_method); + const uint32_t dstc = s->palette[dstx]; *er = r - (dstc >> 16 & 0xff); *eg = g - (dstc >> 8 & 0xff); *eb = b - (dstc & 0xff); @@ -402,15 +394,10 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram const enum color_search_method search_method) { int x, y; - const struct color_node *map = s->map; - struct cache_node *cache = s->cache; - const uint32_t *palette = s->palette; const int src_linesize = in ->linesize[0] >> 2; const int dst_linesize = out->linesize[0]; uint32_t *src = ((uint32_t *)in ->data[0]) + y_start*src_linesize; uint8_t *dst = out->data[0] + y_start*dst_linesize; - int transparency_index = s->transparency_index; - int trans_thresh = s->trans_thresh; w += x_start; h += y_start; @@ -428,7 +415,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram const uint8_t r = av_clip_uint8(r8 + d); const uint8_t g = av_clip_uint8(g8 + d); const uint8_t b = av_clip_uint8(b8 + d); - const int color = color_get(cache, src[x], a8, r, g, b, transparency_index, trans_thresh, map, palette, search_method); + const int color = color_get(s, src[x], a8, r, g, b, search_method); if (color < 0) return color; @@ -436,7 +423,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram } else if (dither == DITHERING_HECKBERT) { const int right = x < w - 1, down = y < h - 1; - const int color = get_dst_color_err(cache, src[x], map, palette, transparency_index, trans_thresh, &er, &eg, &eb, search_method); + const int color = get_dst_color_err(s, src[x], &er, &eg, &eb, search_method); if (color < 0) return color; @@ -448,7 +435,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram } else if (dither == DITHERING_FLOYD_STEINBERG) { const int right = x < w - 1, down = y < h - 1, left = x > x_start; - const int color = get_dst_color_err(cache, src[x], map, palette, transparency_index, trans_thresh, &er, &eg, &eb, search_method); + const int color = get_dst_color_err(s, src[x], &er, &eg, &eb, search_method); if (color < 0) return color; @@ -462,7 +449,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram } else if (dither == DITHERING_SIERRA2) { const int right = x < w - 1, down = y < h - 1, left = x > x_start; const int right2 = x < w - 2, left2 = x > x_start + 1; - const int color = get_dst_color_err(cache, src[x], map, palette, transparency_index, trans_thresh, &er, &eg, &eb, search_method); + const int color = get_dst_color_err(s, src[x], &er, &eg, &eb, search_method); if (color < 0) return color; @@ -481,7 +468,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram } else if (dither == DITHERING_SIERRA2_4A) { const int right = x < w - 1, down = y < h - 1, left = x > x_start; - const int color = get_dst_color_err(cache, src[x], map, palette, transparency_index, trans_thresh, &er, &eg, &eb, search_method); + const int color = get_dst_color_err(s, src[x], &er, &eg, &eb, search_method); if (color < 0) return color; @@ -496,7 +483,7 @@ static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFram const uint8_t r = src[x] >> 16 & 0xff; const uint8_t g = src[x] >> 8 & 0xff; const uint8_t b = src[x] & 0xff; - const int color = color_get(cache, src[x], a, r, g, b, transparency_index, trans_thresh, map, palette, search_method); + const int color = color_get(s, src[x], a, r, g, b, search_method); if (color < 0) return color; From 3729ae659fb21b0509be7f19f9f41a4729f30347 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 8 Jul 2017 19:14:05 +0200 Subject: [PATCH 0631/2557] avcodec: add MagicYUV encoder Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/general.texi | 2 +- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 2 +- libavcodec/magicyuvenc.c | 558 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 562 insertions(+), 2 deletions(-) create mode 100644 libavcodec/magicyuvenc.c diff --git a/Changelog b/Changelog index 6592d868dace7..8c45b2946df45 100644 --- a/Changelog +++ b/Changelog @@ -6,6 +6,7 @@ version : - Dropped support for OpenJPEG versions 2.0 and below. Using OpenJPEG now requires 2.1 (or later) and pkg-config. - VDA dropped (use VideoToolbox instead) +- MagicYUV encoder version 3.4: diff --git a/doc/general.texi b/doc/general.texi index a40400612ea03..56f315d67b9aa 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -792,7 +792,7 @@ following image formats are supported: @item LucasArts SANM/Smush @tab @tab X @tab Used in LucasArts games / SMUSH animations. @item lossless MJPEG @tab X @tab X -@item MagicYUV Video @tab @tab X +@item MagicYUV Video @tab X @tab X @item Mandsoft Screen Capture Codec @tab @tab X @item Microsoft ATC Screen @tab @tab X @tab Also known as Microsoft Screen 3. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 8c878c36992fd..e4e7a4adbfe44 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -397,6 +397,7 @@ OBJS-$(CONFIG_M101_DECODER) += m101.o OBJS-$(CONFIG_MACE3_DECODER) += mace.o OBJS-$(CONFIG_MACE6_DECODER) += mace.o OBJS-$(CONFIG_MAGICYUV_DECODER) += magicyuv.o +OBJS-$(CONFIG_MAGICYUV_ENCODER) += magicyuvenc.o OBJS-$(CONFIG_MDEC_DECODER) += mdec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_METASOUND_DECODER) += metasound.o metasound_data.o \ twinvq.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 83691267aad0e..98655ddd7c91e 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -240,7 +240,7 @@ static void register_all(void) REGISTER_ENCODER(LJPEG, ljpeg); REGISTER_DECODER(LOCO, loco); REGISTER_DECODER(M101, m101); - REGISTER_DECODER(MAGICYUV, magicyuv); + REGISTER_ENCDEC (MAGICYUV, magicyuv); REGISTER_DECODER(MDEC, mdec); REGISTER_DECODER(MIMIC, mimic); REGISTER_ENCDEC (MJPEG, mjpeg); diff --git a/libavcodec/magicyuvenc.c b/libavcodec/magicyuvenc.c new file mode 100644 index 0000000000000..f948b03e4b52e --- /dev/null +++ b/libavcodec/magicyuvenc.c @@ -0,0 +1,558 @@ +/* + * MagicYUV encoder + * Copyright (c) 2017 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/qsort.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "put_bits.h" +#include "internal.h" +#include "thread.h" +#include "lossless_videoencdsp.h" + +typedef enum Prediction { + LEFT = 1, + GRADIENT, + MEDIAN, +} Prediction; + +typedef struct HuffEntry { + uint8_t sym; + uint8_t len; + uint32_t code; +} HuffEntry; + +typedef struct PTable { + int value; ///< input value + int64_t prob; ///< number of occurences of this value in input +} PTable; + +typedef struct MagicYUVContext { + const AVClass *class; + int frame_pred; + PutBitContext pb; + int planes; + uint8_t format; + AVFrame *p; + int max; + int slice_height; + int nb_slices; + int correlate; + int hshift[4]; + int vshift[4]; + uint8_t *slices[4]; + unsigned slice_pos[4]; + unsigned tables_size; + HuffEntry he[4][256]; + LLVidEncDSPContext llvidencdsp; + void (*predict)(struct MagicYUVContext *s, uint8_t *src, uint8_t *dst, + ptrdiff_t stride, int width, int height); +} MagicYUVContext; + +static void left_predict(MagicYUVContext *s, + uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int width, int height) +{ + uint8_t prev = 0; + int i, j; + + for (i = 0; i < width; i++) { + dst[i] = src[i] - prev; + prev = src[i]; + } + dst += width; + src += stride; + for (j = 1; j < height; j++) { + prev = src[-stride]; + for (i = 0; i < width; i++) { + dst[i] = src[i] - prev; + prev = src[i]; + } + dst += width; + src += stride; + } +} + +static void gradient_predict(MagicYUVContext *s, + uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int width, int height) +{ + int left = 0, top, lefttop; + int i, j; + + for (i = 0; i < width; i++) { + dst[i] = src[i] - left; + left = src[i]; + } + dst += width; + src += stride; + for (j = 1; j < height; j++) { + top = src[-stride]; + left = src[0] - top; + dst[0] = left; + for (i = 1; i < width; i++) { + top = src[i - stride]; + lefttop = src[i - (stride + 1)]; + left = src[i-1]; + dst[i] = (src[i] - top) - left + lefttop; + } + dst += width; + src += stride; + } +} + +static void median_predict(MagicYUVContext *s, + uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int width, int height) +{ + int left = 0, lefttop; + int i, j; + + for (i = 0; i < width; i++) { + dst[i] = src[i] - left; + left = src[i]; + } + dst += width; + src += stride; + for (j = 1; j < height; j++) { + left = lefttop = src[-stride]; + s->llvidencdsp.sub_median_pred(dst, src - stride, src, width, &left, &lefttop); + dst += width; + src += stride; + } +} + +static av_cold int magy_encode_init(AVCodecContext *avctx) +{ + MagicYUVContext *s = avctx->priv_data; + int i; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_GBRP: + avctx->codec_tag = MKTAG('M', '8', 'R', 'G'); + s->correlate = 1; + s->format = 0x65; + break; + case AV_PIX_FMT_GBRAP: + avctx->codec_tag = MKTAG('M', '8', 'R', 'A'); + s->correlate = 1; + s->format = 0x66; + break; + case AV_PIX_FMT_YUV420P: + avctx->codec_tag = MKTAG('M', '8', 'Y', '0'); + s->hshift[1] = + s->vshift[1] = + s->hshift[2] = + s->vshift[2] = 1; + s->format = 0x69; + break; + case AV_PIX_FMT_YUV422P: + avctx->codec_tag = MKTAG('M', '8', 'Y', '2'); + s->hshift[1] = + s->hshift[2] = 1; + s->format = 0x68; + break; + case AV_PIX_FMT_YUV444P: + avctx->codec_tag = MKTAG('M', '8', 'Y', '4'); + s->format = 0x67; + break; + case AV_PIX_FMT_YUVA444P: + avctx->codec_tag = MKTAG('M', '8', 'Y', 'A'); + s->format = 0x6a; + break; + case AV_PIX_FMT_GRAY8: + avctx->codec_tag = MKTAG('M', '8', 'G', '0'); + s->format = 0x6b; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format: %d\n", + avctx->pix_fmt); + return AVERROR_INVALIDDATA; + } + + ff_llvidencdsp_init(&s->llvidencdsp); + + s->planes = av_pix_fmt_count_planes(avctx->pix_fmt); + + s->nb_slices = 1; + + for (i = 0; i < s->planes; i++) { + s->slices[i] = av_malloc(avctx->width * (avctx->height + 2) + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!s->slices[i]) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer.\n"); + return AVERROR(ENOMEM); + } + } + + switch (s->frame_pred) { + case LEFT: s->predict = left_predict; break; + case GRADIENT: s->predict = gradient_predict; break; + case MEDIAN: s->predict = median_predict; break; + } + + return 0; +} + +static int magy_huff_cmp_len(const void *a, const void *b) +{ + const HuffEntry *aa = a, *bb = b; + return (aa->len - bb->len) * 256 + aa->sym - bb->sym; +} + +static int huff_cmp_sym(const void *a, const void *b) +{ + const HuffEntry *aa = a, *bb = b; + return bb->sym - aa->sym; +} + +static void calculate_codes(HuffEntry *he) +{ + uint32_t code; + int i; + + AV_QSORT(he, 256, HuffEntry, magy_huff_cmp_len); + + code = 1; + for (i = 255; i >= 0; i--) { + he[i].code = code >> (32 - he[i].len); + code += 0x80000000u >> (he[i].len - 1); + } + + AV_QSORT(he, 256, HuffEntry, huff_cmp_sym); +} + +static void count_usage(uint8_t *src, int width, + int height, PTable *counts) +{ + int i, j; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + counts[src[i]].prob++; + } + src += width; + } +} + +typedef struct PackageMergerList { + int nitems; ///< number of items in the list and probability ex. 4 + int item_idx[515]; ///< index range for each item in items 0, 2, 5, 9, 13 + int probability[514]; ///< probability of each item 3, 8, 18, 46 + int items[257 * 16]; ///< chain of all individual values that make up items A, B, A, B, C, A, B, C, D, C, D, D, E +} PackageMergerList; + +static int compare_by_prob(const void *a, const void *b) +{ + PTable a_val = *(PTable *)a; + PTable b_val = *(PTable *)b; + return a_val.prob - b_val.prob; +} + +static void magy_huffman_compute_bits(PTable *prob_table, HuffEntry *distincts, + int size, int max_length) +{ + PackageMergerList list_a, list_b, *to = &list_a, *from = &list_b, *temp; + int times, i, j, k; + int nbits[257] = {0}; + int min; + + av_assert0(max_length > 0); + + to->nitems = 0; + from->nitems = 0; + to->item_idx[0] = 0; + from->item_idx[0] = 0; + AV_QSORT(prob_table, size, PTable, compare_by_prob); + + for (times = 0; times <= max_length; times++) { + to->nitems = 0; + to->item_idx[0] = 0; + + j = 0; + k = 0; + + if (times < max_length) { + i = 0; + } + while (i < size || j + 1 < from->nitems) { + to->nitems++; + to->item_idx[to->nitems] = to->item_idx[to->nitems - 1]; + if (i < size && + (j + 1 >= from->nitems || + prob_table[i].prob < + from->probability[j] + from->probability[j + 1])) { + to->items[to->item_idx[to->nitems]++] = prob_table[i].value; + to->probability[to->nitems - 1] = prob_table[i].prob; + i++; + } else { + for (k = from->item_idx[j]; k < from->item_idx[j + 2]; k++) { + to->items[to->item_idx[to->nitems]++] = from->items[k]; + } + to->probability[to->nitems - 1] = + from->probability[j] + from->probability[j + 1]; + j += 2; + } + } + temp = to; + to = from; + from = temp; + } + + min = (size - 1 < from->nitems) ? size - 1 : from->nitems; + for (i = 0; i < from->item_idx[min]; i++) { + nbits[from->items[i]]++; + } + + for (i = 0; i < size; i++) { + distincts[i].sym = i; + distincts[i].len = nbits[i]; + } +} + +static int encode_table(AVCodecContext *avctx, uint8_t *dst, + int width, int height, + PutBitContext *pb, HuffEntry *he) +{ + PTable counts[256] = { 0 }; + int i; + + count_usage(dst, width, height, counts); + + for (i = 0; i < 256; i++) { + counts[i].prob++; + counts[i].value = i; + } + + magy_huffman_compute_bits(counts, he, 256, 16); + + calculate_codes(he); + + for (i = 0; i < 256; i++) { + put_bits(pb, 1, 0); + put_bits(pb, 7, he[i].len); + } + + return 0; +} + +static int encode_slice(uint8_t *src, uint8_t *dst, int dst_size, + int width, int height, HuffEntry *he, int prediction) +{ + PutBitContext pb; + int i, j; + int count; + + init_put_bits(&pb, dst, dst_size); + + put_bits(&pb, 8, 0); + put_bits(&pb, 8, prediction); + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + const int idx = src[i]; + put_bits(&pb, he[idx].len, he[idx].code); + } + + src += width; + } + + count = put_bits_count(&pb) & 0x1F; + + if (count) + put_bits(&pb, 32 - count, 0); + + count = put_bits_count(&pb); + + flush_put_bits(&pb); + + return count >> 3; +} + +static int magy_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + MagicYUVContext *s = avctx->priv_data; + PutByteContext pb; + const int width = avctx->width, height = avctx->height; + int pos, slice, i, j, ret = 0; + + ret = ff_alloc_packet2(avctx, pkt, (256 + 4 * s->nb_slices + width * height) * + s->planes + 256, 0); + if (ret < 0) + return ret; + + bytestream2_init_writer(&pb, pkt->data, pkt->size); + bytestream2_put_le32(&pb, MKTAG('M', 'A', 'G', 'Y')); + bytestream2_put_le32(&pb, 32); + bytestream2_put_byte(&pb, 7); + bytestream2_put_byte(&pb, s->format); + bytestream2_put_byte(&pb, 0); + bytestream2_put_byte(&pb, 0); + bytestream2_put_le32(&pb, 0); + + bytestream2_put_le32(&pb, avctx->width); + bytestream2_put_le32(&pb, avctx->height); + bytestream2_put_le32(&pb, avctx->width); + bytestream2_put_le32(&pb, avctx->height); + bytestream2_put_le32(&pb, 0); + + for (i = 0; i < s->planes; i++) { + bytestream2_put_le32(&pb, 0); + for (j = 1; j < s->nb_slices; j++) { + bytestream2_put_le32(&pb, 0); + } + } + + bytestream2_put_byte(&pb, s->planes); + + for (i = 0; i < s->planes; i++) { + for (slice = 0; slice < s->nb_slices; slice++) { + bytestream2_put_byte(&pb, i); + } + } + + if (s->correlate) { + uint8_t *r, *g, *b; + AVFrame *p = av_frame_clone(frame); + + g = p->data[0]; + b = p->data[1]; + r = p->data[2]; + + for (i = 0; i < height; i++) { + s->llvidencdsp.diff_bytes(b, b, g, width); + s->llvidencdsp.diff_bytes(r, r, g, width); + g += p->linesize[0]; + b += p->linesize[1]; + r += p->linesize[2]; + } + + FFSWAP(uint8_t*, p->data[0], p->data[1]); + FFSWAP(int, p->linesize[0], p->linesize[1]); + + for (i = 0; i < s->planes; i++) { + for (slice = 0; slice < s->nb_slices; slice++) { + s->predict(s, p->data[i], s->slices[i], p->linesize[i], + p->width, p->height); + } + } + + av_frame_free(&p); + } else { + for (i = 0; i < s->planes; i++) { + for (slice = 0; slice < s->nb_slices; slice++) { + s->predict(s, frame->data[i], s->slices[i], frame->linesize[i], + AV_CEIL_RSHIFT(frame->width, s->hshift[i]), + AV_CEIL_RSHIFT(frame->height, s->vshift[i])); + } + } + } + + init_put_bits(&s->pb, pkt->data + bytestream2_tell_p(&pb), bytestream2_get_bytes_left_p(&pb)); + + for (i = 0; i < s->planes; i++) { + encode_table(avctx, s->slices[i], + AV_CEIL_RSHIFT(frame->width, s->hshift[i]), + AV_CEIL_RSHIFT(frame->height, s->vshift[i]), + &s->pb, s->he[i]); + } + s->tables_size = (put_bits_count(&s->pb) + 7) >> 3; + bytestream2_skip_p(&pb, s->tables_size); + + for (i = 0; i < s->planes; i++) { + unsigned slice_size; + + s->slice_pos[i] = bytestream2_tell_p(&pb); + slice_size = encode_slice(s->slices[i], pkt->data + bytestream2_tell_p(&pb), + bytestream2_get_bytes_left_p(&pb), + AV_CEIL_RSHIFT(frame->width, s->hshift[i]), + AV_CEIL_RSHIFT(frame->height, s->vshift[i]), + s->he[i], s->frame_pred); + bytestream2_skip_p(&pb, slice_size); + } + + pos = bytestream2_tell_p(&pb); + bytestream2_seek_p(&pb, 32, SEEK_SET); + bytestream2_put_le32(&pb, s->slice_pos[0] - 32); + for (i = 0; i < s->planes; i++) { + bytestream2_put_le32(&pb, s->slice_pos[i] - 32); + } + bytestream2_seek_p(&pb, pos, SEEK_SET); + + pkt->size = bytestream2_tell_p(&pb); + pkt->flags |= AV_PKT_FLAG_KEY; + + *got_packet = 1; + + return 0; +} + +static av_cold int magy_encode_close(AVCodecContext *avctx) +{ + MagicYUVContext *s = avctx->priv_data; + int i; + + for (i = 0; i < s->planes; i++) + av_freep(&s->slices[i]); + + return 0; +} + +#define OFFSET(x) offsetof(MagicYUVContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "pred", "Prediction method", OFFSET(frame_pred), AV_OPT_TYPE_INT, {.i64=LEFT}, LEFT, MEDIAN, VE, "pred" }, + { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LEFT }, 0, 0, VE, "pred" }, + { "gradient", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = GRADIENT }, 0, 0, VE, "pred" }, + { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MEDIAN }, 0, 0, VE, "pred" }, + { NULL}, +}; + +static const AVClass magicyuv_class = { + .class_name = "magicyuv", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_magicyuv_encoder = { + .name = "magicyuv", + .long_name = NULL_IF_CONFIG_SMALL("MagicYUV video"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MAGICYUV, + .priv_data_size = sizeof(MagicYUVContext), + .priv_class = &magicyuv_class, + .init = magy_encode_init, + .close = magy_encode_close, + .encode2 = magy_encode_frame, + .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_GRAY8, + AV_PIX_FMT_NONE + }, +}; From 3d547c19c211ac61771629e6bcdfbdba393a76ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Sat, 28 Oct 2017 17:59:47 +0200 Subject: [PATCH 0632/2557] lavfi/paletteuse: fix debug_accuracy after aba926e7d --- libavfilter/vf_paletteuse.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 73d22a5b95a83..19017ac7b70b6 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -558,16 +558,16 @@ static int debug_accuracy(const struct color_node *node, const uint32_t *palette for (r = 0; r < 256; r++) { for (g = 0; g < 256; g++) { for (b = 0; b < 256; b++) { - const uint8_t rgb[] = {r, g, b}; - const int r1 = COLORMAP_NEAREST(search_method, palette, node, rgb, trans_thresh); - const int r2 = colormap_nearest_bruteforce(palette, rgb, trans_thresh); + const uint8_t argb[] = {0xff, r, g, b}; + const int r1 = COLORMAP_NEAREST(search_method, palette, node, argb, trans_thresh); + const int r2 = colormap_nearest_bruteforce(palette, argb, trans_thresh); if (r1 != r2) { const uint32_t c1 = palette[r1]; const uint32_t c2 = palette[r2]; - const uint8_t palrgb1[] = { c1>>16 & 0xff, c1>> 8 & 0xff, c1 & 0xff }; - const uint8_t palrgb2[] = { c2>>16 & 0xff, c2>> 8 & 0xff, c2 & 0xff }; - const int d1 = diff(palrgb1, rgb, trans_thresh); - const int d2 = diff(palrgb2, rgb, trans_thresh); + const uint8_t palargb1[] = { 0xff, c1>>16 & 0xff, c1>> 8 & 0xff, c1 & 0xff }; + const uint8_t palargb2[] = { 0xff, c2>>16 & 0xff, c2>> 8 & 0xff, c2 & 0xff }; + const int d1 = diff(palargb1, argb, trans_thresh); + const int d2 = diff(palargb2, argb, trans_thresh); if (d1 != d2) { av_log(NULL, AV_LOG_ERROR, "/!\\ %02X%02X%02X: %d ! %d (%06"PRIX32" ! %06"PRIX32") / dist: %d ! %d\n", From 157d08e971f43dd17ba2c3618e31c76fa938efe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Sat, 28 Oct 2017 18:01:41 +0200 Subject: [PATCH 0633/2557] lavfi/paletteuse: fix debug_mean_error after aba926e7d --- libavfilter/vf_paletteuse.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 19017ac7b70b6..84c31de3bebb8 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -787,9 +787,9 @@ static void debug_mean_error(PaletteUseContext *s, const AVFrame *in1, for (x = 0; x < in1->width; x++) { const uint32_t c1 = src1[x]; const uint32_t c2 = palette[src2[x]]; - const uint8_t rgb1[] = {c1 >> 16 & 0xff, c1 >> 8 & 0xff, c1 & 0xff}; - const uint8_t rgb2[] = {c2 >> 16 & 0xff, c2 >> 8 & 0xff, c2 & 0xff}; - mean_err += diff(rgb1, rgb2, s->trans_thresh); + const uint8_t argb1[] = {0xff, c1 >> 16 & 0xff, c1 >> 8 & 0xff, c1 & 0xff}; + const uint8_t argb2[] = {0xff, c2 >> 16 & 0xff, c2 >> 8 & 0xff, c2 & 0xff}; + mean_err += diff(argb1, argb2, s->trans_thresh); } src1 += src1_linesize; src2 += src2_linesize; From 26ad6df1ced738e3443b9105b6b434ac18d1deac Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 28 Oct 2017 13:14:47 -0300 Subject: [PATCH 0634/2557] avcodec: bump minor after addition of MagicYUV encoder Signed-off-by: James Almer --- libavcodec/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 226da1935fef1..6c0d7a83285a5 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 0 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MINOR 1 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 93a1aac44198a7d27e427090e3749aa923a78eaa Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 28 Oct 2017 13:14:51 -0300 Subject: [PATCH 0635/2557] configure: add missing llvidencdsp dependency to MagicYUV encoder Signed-off-by: James Almer --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 0e1ccaac587a9..2f259996ae302 100755 --- a/configure +++ b/configure @@ -2518,6 +2518,7 @@ jv_decoder_select="blockdsp" lagarith_decoder_select="llviddsp" ljpeg_encoder_select="aandcttables idctdsp jpegtables mpegvideoenc" magicyuv_decoder_select="llviddsp" +magicyuv_encoder_select="llvidencdsp" mdec_decoder_select="blockdsp idctdsp mpegvideo" metasound_decoder_select="lsp mdct sinewin" mimic_decoder_select="blockdsp bswapdsp hpeldsp idctdsp" From 1d348dd03fb485b9c62904734cde11a2f4813f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Sat, 28 Oct 2017 18:49:30 +0200 Subject: [PATCH 0636/2557] lavfi/paletteuse: fix debug_kdtree after aba926e7d --- libavfilter/vf_paletteuse.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 84c31de3bebb8..ed80ab04d5e9e 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -506,15 +506,16 @@ static void disp_node(AVBPrint *buf, const uint32_t fontcolor = node->val[1] > 0x50 && node->val[2] > 0x50 && node->val[3] > 0x50 ? 0 : 0xffffff; + const int rgb_comp = node->split - 1; av_bprintf(buf, "%*cnode%d [" "label=\"%c%02X%c%02X%c%02X%c\" " "fillcolor=\"#%02x%02x%02x\" " "fontcolor=\"#%06"PRIX32"\"]\n", depth*INDENT, ' ', node->palette_id, - "[ "[node->split], node->val[1], - "][ "[node->split], node->val[2], - " ]["[node->split], node->val[3], - " ]"[node->split], + "[ "[rgb_comp], node->val[1], + "][ "[rgb_comp], node->val[2], + " ]["[rgb_comp], node->val[3], + " ]"[rgb_comp], node->val[1], node->val[2], node->val[3], fontcolor); if (parent_id != -1) From b43d13144bdb63704dd55533b3fba9be376164ce Mon Sep 17 00:00:00 2001 From: dxfhgwet Date: Sat, 28 Oct 2017 10:20:22 -0700 Subject: [PATCH 0637/2557] avfilter/zscale: fix segfault on library error --- libavfilter/vf_zscale.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_zscale.c b/libavfilter/vf_zscale.c index c303dd4d63dc7..5ee272ed1d63b 100644 --- a/libavfilter/vf_zscale.c +++ b/libavfilter/vf_zscale.c @@ -321,7 +321,7 @@ static int print_zimg_error(AVFilterContext *ctx) av_log(ctx, AV_LOG_ERROR, "code %d: %s\n", err_code, err_msg); - return err_code; + return AVERROR_EXTERNAL; } static int convert_chroma_location(enum AVChromaLocation chroma_location) @@ -624,7 +624,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) ret = zimg_filter_graph_process(s->graph, &src_buf, &dst_buf, s->tmp, 0, 0, 0, 0); if (ret) { - print_zimg_error(link->dst); + ret = print_zimg_error(link->dst); goto fail; } @@ -639,7 +639,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) ret = zimg_filter_graph_process(s->alpha_graph, &src_buf, &dst_buf, s->tmp, 0, 0, 0, 0); if (ret) { - print_zimg_error(link->dst); + ret = print_zimg_error(link->dst); goto fail; } } else if (odesc->flags & AV_PIX_FMT_FLAG_ALPHA) { From ff763351e74550df3b9a0465634d1ec48b15b043 Mon Sep 17 00:00:00 2001 From: dxfhgwet Date: Fri, 27 Oct 2017 21:54:13 -0700 Subject: [PATCH 0638/2557] avfilter/zscale: fix memory leak --- libavfilter/vf_zscale.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vf_zscale.c b/libavfilter/vf_zscale.c index 5ee272ed1d63b..09fd842fe55ba 100644 --- a/libavfilter/vf_zscale.c +++ b/libavfilter/vf_zscale.c @@ -673,6 +673,7 @@ static void uninit(AVFilterContext *ctx) ZScaleContext *s = ctx->priv; zimg_filter_graph_free(s->graph); + zimg_filter_graph_free(s->alpha_graph); av_freep(&s->tmp); s->tmp_size = 0; } From 3606c114172ec0cb25660b4c2e146bed5b211ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Gro=C3=9Fe?= Date: Thu, 26 Oct 2017 17:58:35 +0200 Subject: [PATCH 0639/2557] dashenc: use av_dict_set_int instead of static function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Große Signed-off-by: Michael Niedermayer --- libavformat/dashenc.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 240ff41380569..5086f4a21f8f9 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -664,14 +664,6 @@ static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const ch return 0; } -static int dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags) -{ - char valuestr[22]; - snprintf(valuestr, sizeof(valuestr), "%"PRId64, value); - flags &= ~AV_DICT_DONT_STRDUP_VAL; - return av_dict_set(pm, key, valuestr, flags); -} - static int dash_init(AVFormatContext *s) { DASHContext *c = s->priv_data; @@ -782,8 +774,8 @@ static int dash_init(AVFormatContext *s) if (!strcmp(os->format_name, "mp4")) { av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0); } else { - dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000, 0); - dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit + av_dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000, 0); + av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit } if ((ret = avformat_write_header(ctx, &opts)) < 0) return ret; From 8edb9d457251c190f7ad9de764981f79eb113374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Gro=C3=9Fe?= Date: Fri, 27 Oct 2017 21:18:47 +0200 Subject: [PATCH 0640/2557] dashenc: move UTCTiming element to the end of the manifest Required by comformance XSD [1]. [1] https://github.com/Dash-Industry-Forum/Conformance-and-reference-source/blob/master/conformance/MPDValidator/schemas/DASH-MPD.xsd Signed-off-by: Michael Niedermayer --- libavformat/dashenc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 5086f4a21f8f9..04b0fd99e6787 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -627,8 +627,6 @@ static int write_manifest(AVFormatContext *s, int final) av_free(escaped); } avio_printf(out, "\t\n"); - if (c->utc_timing_url) - avio_printf(out, "\t\n", c->utc_timing_url); if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) { OutputStream *os = &c->streams[0]; @@ -646,6 +644,10 @@ static int write_manifest(AVFormatContext *s, int final) return ret; } avio_printf(out, "\t\n"); + + if (c->utc_timing_url) + avio_printf(out, "\t\n", c->utc_timing_url); + avio_printf(out, "\n"); avio_flush(out); ff_format_io_close(s, &out); From 80137531139588774e048d6e1dae34ab5cbbbfa2 Mon Sep 17 00:00:00 2001 From: Sasi Inguva Date: Wed, 18 Oct 2017 20:11:16 -0700 Subject: [PATCH 0641/2557] lavf/mov.c: Fix parsing of edit list atoms with invalid elst entry count. Signed-off-by: Sasi Inguva Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 21 +++++++- tests/fate/mov.mak | 4 ++ tests/ref/fate/mov-invalid-elst-entry-count | 57 +++++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 tests/ref/fate/mov-invalid-elst-entry-count diff --git a/libavformat/mov.c b/libavformat/mov.c index 2ee67561e429e..209b7470a9a72 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4852,6 +4852,7 @@ static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom) { MOVStreamContext *sc; int i, edit_count, version; + int64_t elst_entry_size; if (c->fc->nb_streams < 1 || c->ignore_editlist) return 0; @@ -4860,6 +4861,21 @@ static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom) version = avio_r8(pb); /* version */ avio_rb24(pb); /* flags */ edit_count = avio_rb32(pb); /* entries */ + atom.size -= 8; + + elst_entry_size = version == 1 ? 20 : 12; + if (atom.size != edit_count * elst_entry_size) { + if (c->fc->strict_std_compliance >= FF_COMPLIANCE_STRICT) { + av_log(c->fc, AV_LOG_ERROR, "Invalid edit list entry_count: %d for elst atom of size: %"PRId64" bytes.\n", + edit_count, atom.size + 8); + return AVERROR_INVALIDDATA; + } else { + edit_count = atom.size / elst_entry_size; + if (edit_count * elst_entry_size != atom.size) { + av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.", atom.size, edit_count); + } + } + } if (!edit_count) return 0; @@ -4872,17 +4888,20 @@ static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR(ENOMEM); av_log(c->fc, AV_LOG_TRACE, "track[%u].edit_count = %i\n", c->fc->nb_streams - 1, edit_count); - for (i = 0; i < edit_count && !pb->eof_reached; i++) { + for (i = 0; i < edit_count && atom.size > 0 && !pb->eof_reached; i++) { MOVElst *e = &sc->elst_data[i]; if (version == 1) { e->duration = avio_rb64(pb); e->time = avio_rb64(pb); + atom.size -= 16; } else { e->duration = avio_rb32(pb); /* segment duration */ e->time = (int32_t)avio_rb32(pb); /* media time */ + atom.size -= 8; } e->rate = avio_rb32(pb) / 65536.0; + atom.size -= 4; av_log(c->fc, AV_LOG_TRACE, "duration=%"PRId64" time=%"PRId64" rate=%f\n", e->duration, e->time, e->rate); diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 5013e7d528885..604703e254473 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -6,6 +6,7 @@ FATE_MOV = fate-mov-3elist \ fate-mov-1elist-ends-last-bframe \ fate-mov-2elist-elist1-ends-bframe \ fate-mov-3elist-encrypted \ + fate-mov-invalid-elst-entry-count \ fate-mov-gpmf-remux \ fate-mov-440hz-10ms \ @@ -43,6 +44,9 @@ fate-mov-2elist-elist1-ends-bframe: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/mov- # Makes sure that we handle edit lists and start padding correctly. fate-mov-440hz-10ms: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/440hz-10ms.m4a +# Makes sure that we handle invalid edit list entry count correctly. +fate-mov-invalid-elst-entry-count: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/invalid_elst_entry_count.mov + fate-mov-aac-2048-priming: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_packets -print_format compact $(TARGET_SAMPLES)/mov/aac-2048-priming.mov fate-mov-zombie: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_streams -show_packets -show_frames -bitexact -print_format compact $(TARGET_SAMPLES)/mov/white_zombie_scrunch-part.mov diff --git a/tests/ref/fate/mov-invalid-elst-entry-count b/tests/ref/fate/mov-invalid-elst-entry-count new file mode 100644 index 0000000000000..13b575816b4f1 --- /dev/null +++ b/tests/ref/fate/mov-invalid-elst-entry-count @@ -0,0 +1,57 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/24 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 640x480 +#sar 0: 1/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 460800, 549730883a0b56e6accaf021903daecf +0, 1, 1, 1, 460800, 783389b4342d4be925fc5244791e760a +0, 2, 2, 1, 460800, 8384af6426d94a2077930c93013e09ad +0, 3, 3, 1, 460800, 9380a1d9ecacf5b3105383c1c8083188 +0, 4, 4, 1, 460800, eb28174acfceb868b9058757bed049c5 +0, 5, 5, 1, 460800, 9732bd4a58884dbf2be48d819433130f +0, 6, 6, 1, 460800, 0c553fb530cf042eb84f5b13817a96a6 +0, 7, 7, 1, 460800, 621f02aded5e35fa1f373afd3ed283bd +0, 8, 8, 1, 460800, c76167c6bda91f657708c88252ea315d +0, 9, 9, 1, 460800, 872df2d8c522e2440ddd04bca7dce497 +0, 10, 10, 1, 460800, 6ee9154e48c5132ad4ba122b255bd2bb +0, 11, 11, 1, 460800, 362e61629795702ebe9183ce3786d7f2 +0, 12, 12, 1, 460800, f3ec59e6fc4e3c2e75f42bef34ca73b5 +0, 13, 13, 1, 460800, 68d9caea8697736dd716cba43b614919 +0, 14, 14, 1, 460800, 4a4efb0201a64236db4330725758c139 +0, 15, 15, 1, 460800, f32f8997dcdd87ad910dea886a0de17d +0, 16, 16, 1, 460800, 51a8549d7b4aaacaf6050bc07a82b440 +0, 17, 17, 1, 460800, 5145aa05bbb0c3faab40fc8fa233af1d +0, 18, 18, 1, 460800, bbfcbe3c9600b2a0f413057d7959e9e7 +0, 19, 19, 1, 460800, 02cfd4a350fa274e12fce8352001bf21 +0, 20, 20, 1, 460800, 20dd372da9e656add433f31e3e9c1fb8 +0, 21, 21, 1, 460800, 3b885593f8b42676ce40c329a63f62bf +0, 22, 22, 1, 460800, c38b453b56c3ea14f7d8691d83752486 +0, 23, 23, 1, 460800, 79643132988dabc9dc1ba3af0aeaebc5 +0, 24, 24, 1, 460800, 60a099be31244b2f69ca6107cdbd7e06 +0, 25, 25, 1, 460800, 1de6ff4e0aa81216e4b7b1c8e74fb143 +0, 26, 26, 1, 460800, 5223a81e6964c28cf42593f259397aa1 +0, 27, 27, 1, 460800, 2dfcf01c86aa712cd6f1c7656eeb17db +0, 28, 28, 1, 460800, 8c86ee0f02fabccaed8d8fc8babd031e +0, 29, 29, 1, 460800, b3ea1983f7efeec11306445d9ae5d477 +0, 30, 30, 1, 460800, 86a4cc9fa7db5ff5ca2be69ad191179f +0, 31, 31, 1, 460800, 8194715afe23ae34a019797a53a6ee2c +0, 32, 32, 1, 460800, 447a153f1c6bb703eff62edfd14e08e0 +0, 33, 33, 1, 460800, 092257082789b898dbb14d1f19e79347 +0, 34, 34, 1, 460800, d6320d204a119cfeef5645a4118bc600 +0, 35, 35, 1, 460800, 2ee710deae4bb0d156528797ad1c4981 +0, 36, 36, 1, 460800, 1256eac030985c04c4501ad5a72e9d66 +0, 37, 37, 1, 460800, f16ad8c1aa572be7666c7907ce4aebbc +0, 38, 38, 1, 460800, 865088cbd47d0151b62a45d5426c8216 +0, 39, 39, 1, 460800, 26c78ca43d93c6da153f3dea5d945e0e +0, 40, 40, 1, 460800, d775d6705c965401ccc143d5ae432938 +0, 41, 41, 1, 460800, f9837d514753c59e6776452d9043524f +0, 42, 42, 1, 460800, 8463f5172914828abcc770f888bfd183 +0, 43, 43, 1, 460800, 3108557748cfb7965b33b16b35359de0 +0, 44, 44, 1, 460800, 477d596944e028dd72c207bb6e6b22de +0, 45, 45, 1, 460800, 69e4ffbd600c8d8bc070d7d7324ee2b1 +0, 46, 46, 1, 460800, 2211c57bc9ec1788217002900f9102b1 +0, 47, 47, 1, 460800, bcfb5f0a7f88da3ec8c6b447ed4b67eb From eb54efc1e1aafe18d0a8a0c72a78314645bccc83 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 28 Oct 2017 16:16:46 +0200 Subject: [PATCH 0642/2557] avformat/ac3dec: Check buf2 before adding 16 in ac3_eac3_probe() This is needed since e0250cf3651e6417e0117486a7816b45fb2d34cd as that uses end-buf2 Note, there are more than 16 bytes allocated beyond "end" Fixes: regression (segfault) with probetest Signed-off-by: Michael Niedermayer --- libavformat/ac3dec.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/ac3dec.c b/libavformat/ac3dec.c index 8ea73824a684b..6f423ff7eb2d7 100644 --- a/libavformat/ac3dec.c +++ b/libavformat/ac3dec.c @@ -47,8 +47,11 @@ static int ac3_eac3_probe(AVProbeData *p, enum AVCodecID expected_codec_id) uint16_t frame_size; int i, ret; - if(!memcmp(buf2, "\x1\x10\0\0\0\0\0\0", 8)) + if(!memcmp(buf2, "\x1\x10\0\0\0\0\0\0", 8)) { + if (buf2 + 16 > end) + break; buf2+=16; + } if (buf[0] == 0x77 && buf[1] == 0x0B) { for(i=0; i<8; i+=2) { buf3[i ] = buf2[i+1]; From 859144fb1fffc671069e2e119c14de0b66b648c4 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Fri, 27 Oct 2017 22:14:23 +0200 Subject: [PATCH 0643/2557] fate: change fate-ffmpeg-attached_pics to encode to pcm_s16le Previously alac encoder was used, from a first glance I thought it is bitexact, but it turns out it is using floating point arithmetic as well, so probably it is not. Fixes fate failures on mingw32/64. Signed-off-by: Marton Balint --- tests/fate/ffmpeg.mak | 6 +- tests/ref/fate/ffmpeg-attached_pics | 259 ++++++++++++++-------------- 2 files changed, 132 insertions(+), 133 deletions(-) diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index a806c05d45025..0975af2612664 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -30,9 +30,9 @@ fate-ffmpeg-filter_complex: CMD = framecrc -filter_complex color=d=1:r=5 -fflags FATE_FFMPEG-$(call ALLYES, AEVALSRC_FILTER ASETNSAMPLES_FILTER AC3_FIXED_ENCODER) += fate-ffmpeg-filter_complex_audio fate-ffmpeg-filter_complex_audio: CMD = framecrc -filter_complex "aevalsrc=0:d=0.1,asetnsamples=1537" -c ac3_fixed -# Ticket 6375 -FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER PNG_DECODER ALAC_DECODER ALAC_ENCODER) += fate-ffmpeg-attached_pics -fate-ffmpeg-attached_pics: CMD = threads=2 framecrc -i $(TARGET_SAMPLES)/lossless-audio/inside.m4a -acodec alac -max_muxing_queue_size 16 +# Ticket 6375, use case of NoX +FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER PNG_DECODER ALAC_DECODER PCM_S16LE_ENCODER RAWVIDEO_ENCODER) += fate-ffmpeg-attached_pics +fate-ffmpeg-attached_pics: CMD = threads=2 framecrc -i $(TARGET_SAMPLES)/lossless-audio/inside.m4a -c:a pcm_s16le -max_muxing_queue_size 16 FATE_SAMPLES_FFMPEG-$(CONFIG_COLORKEY_FILTER) += fate-ffmpeg-filter_colorkey fate-ffmpeg-filter_colorkey: tests/data/filtergraphs/colorkey diff --git a/tests/ref/fate/ffmpeg-attached_pics b/tests/ref/fate/ffmpeg-attached_pics index 3a0f15181987d..ee2f20638e6f8 100644 --- a/tests/ref/fate/ffmpeg-attached_pics +++ b/tests/ref/fate/ffmpeg-attached_pics @@ -1,4 +1,3 @@ -#extradata 1: 36, 0x45f80468 #tb 0: 1/90000 #media_type 0: video #codec_id 0: rawvideo @@ -6,136 +5,136 @@ #sar 0: 2834/2834 #tb 1: 1/44100 #media_type 1: audio -#codec_id 1: alac +#codec_id 1: pcm_s16le #sample_rate 1: 44100 #channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 0, 120000, 0x748cc771 -1, 0, 0, 4096, 32, 0x204b0676 -1, 4096, 4096, 4096, 5826, 0x56583236 -1, 8192, 8192, 4096, 5532, 0x5f047492 -1, 12288, 12288, 4096, 5245, 0xaa3f1897 -1, 16384, 16384, 4096, 4782, 0x392f3ac3 -1, 20480, 20480, 4096, 4602, 0x9bd6ffad -1, 24576, 24576, 4096, 4357, 0x5df6530b -1, 28672, 28672, 4096, 7443, 0x38ce542b -1, 32768, 32768, 4096, 5803, 0x196ae519 -1, 36864, 36864, 4096, 5619, 0xd436cd94 -1, 40960, 40960, 4096, 4896, 0x42df7109 -1, 45056, 45056, 4096, 4755, 0xfbfdfd5f -1, 49152, 49152, 4096, 4597, 0x93f3ce66 -1, 53248, 53248, 4096, 7777, 0x56ffe620 -1, 57344, 57344, 4096, 5498, 0xa0865dc8 -1, 61440, 61440, 4096, 5343, 0x42134619 -1, 65536, 65536, 4096, 6261, 0xd60d1379 -1, 69632, 69632, 4096, 4496, 0x0eb49c68 -1, 73728, 73728, 4096, 4336, 0x21d541bd -1, 77824, 77824, 4096, 8395, 0x02030a38 -1, 81920, 81920, 4096, 8174, 0x47bdb71d -1, 86016, 86016, 4096, 7434, 0x2304318e -1, 90112, 90112, 4096, 7619, 0x80e6a037 -1, 94208, 94208, 4096, 6086, 0xd3438d2f -1, 98304, 98304, 4096, 6075, 0xd6019fbf -1, 102400, 102400, 4096, 9597, 0x28f46a38 -1, 106496, 106496, 4096, 10287, 0x9dbf0938 -1, 110592, 110592, 4096, 10537, 0xc417fb81 -1, 114688, 114688, 4096, 10360, 0xc580caa3 -1, 118784, 118784, 4096, 9778, 0xb9c2d3e5 -1, 122880, 122880, 4096, 10307, 0x05b1b271 -1, 126976, 126976, 4096, 11289, 0x97f07c63 -1, 131072, 131072, 4096, 11561, 0x8a45194a -1, 135168, 135168, 4096, 11327, 0x86587829 -1, 139264, 139264, 4096, 11347, 0x15659d6e -1, 143360, 143360, 4096, 11006, 0x9a002c7f -1, 147456, 147456, 4096, 11147, 0x853955e0 -1, 151552, 151552, 4096, 11025, 0x7bdafbda -1, 155648, 155648, 4096, 11561, 0x2ec43d86 -1, 159744, 159744, 4096, 11329, 0x6eaba39a -1, 163840, 163840, 4096, 10886, 0x5c31b777 -1, 167936, 167936, 4096, 11505, 0xcd7f2b9a -1, 172032, 172032, 4096, 11243, 0xa1cb6c83 -1, 176128, 176128, 4096, 11718, 0x5b0d6e74 -1, 180224, 180224, 4096, 11898, 0xa649ca9a -1, 184320, 184320, 4096, 11358, 0x037bc2f4 -1, 188416, 188416, 4096, 10864, 0x9239d22f -1, 192512, 192512, 4096, 12181, 0xd5c24fba -1, 196608, 196608, 4096, 11551, 0xa0d8c8d1 -1, 200704, 200704, 4096, 10858, 0x330fcbd8 -1, 204800, 204800, 4096, 9918, 0xd64a0ae4 -1, 208896, 208896, 4096, 9944, 0x0627d87a -1, 212992, 212992, 4096, 9490, 0xa8cc1e93 -1, 217088, 217088, 4096, 9427, 0xb2b6db53 -1, 221184, 221184, 4096, 9799, 0x23ef915a -1, 225280, 225280, 4096, 9544, 0x79fb4344 -1, 229376, 229376, 4096, 12091, 0xdc2e58e4 -1, 233472, 233472, 4096, 11079, 0xe23d2e0e -1, 237568, 237568, 4096, 10772, 0xec04a623 -1, 241664, 241664, 4096, 11608, 0x9ab81556 -1, 245760, 245760, 4096, 10744, 0x538c70fa -1, 249856, 249856, 4096, 10316, 0xfc26a3bf -1, 253952, 253952, 4096, 11768, 0x20a1590f -1, 258048, 258048, 4096, 11283, 0xd6cb802d -1, 262144, 262144, 4096, 10112, 0xf1de16a2 -1, 266240, 266240, 4096, 12051, 0x881feda5 -1, 270336, 270336, 4096, 11348, 0xede7baab -1, 274432, 274432, 4096, 10816, 0x816c90c7 -1, 278528, 278528, 4096, 12319, 0x1750b376 -1, 282624, 282624, 4096, 11228, 0x8db96bea -1, 286720, 286720, 4096, 10217, 0x7503aeb2 -1, 290816, 290816, 4096, 12084, 0x36dde3c4 -1, 294912, 294912, 4096, 11697, 0xa16f51f7 -1, 299008, 299008, 4096, 10977, 0xf5b026e4 -1, 303104, 303104, 4096, 10459, 0xcab7f410 -1, 307200, 307200, 4096, 10287, 0x910baac6 -1, 311296, 311296, 4096, 10313, 0x5c0ca807 -1, 315392, 315392, 4096, 10018, 0x366a00da -1, 319488, 319488, 4096, 10250, 0x69459be7 -1, 323584, 323584, 4096, 9947, 0x5d8efc8e -1, 327680, 327680, 4096, 11550, 0xb90d385c -1, 331776, 331776, 4096, 11249, 0xb93f8093 -1, 335872, 335872, 4096, 11168, 0xe8fb345a -1, 339968, 339968, 4096, 11389, 0xa0eebbe6 -1, 344064, 344064, 4096, 10632, 0xc4646a98 -1, 348160, 348160, 4096, 11055, 0x5b2c3bb5 -1, 352256, 352256, 4096, 11551, 0xc6951ab2 -1, 356352, 356352, 4096, 11495, 0xde18135a -1, 360448, 360448, 4096, 11141, 0x98a92ed5 -1, 364544, 364544, 4096, 11272, 0x99837e81 -1, 368640, 368640, 4096, 10973, 0xfc8b1294 -1, 372736, 372736, 4096, 10754, 0x562f8fcc -1, 376832, 376832, 4096, 11784, 0x8a114dde -1, 380928, 380928, 4096, 11358, 0x8405af06 -1, 385024, 385024, 4096, 11194, 0x164570f6 -1, 389120, 389120, 4096, 11512, 0x8358d96f -1, 393216, 393216, 4096, 12245, 0x206d6330 -1, 397312, 397312, 4096, 11556, 0x2412fc6c -1, 401408, 401408, 4096, 10997, 0x8e31e829 -1, 405504, 405504, 4096, 9927, 0x7eb2f59a -1, 409600, 409600, 4096, 9797, 0x51089850 -1, 413696, 413696, 4096, 9648, 0xf29a7d52 -1, 417792, 417792, 4096, 9077, 0xddc149ad -1, 421888, 421888, 4096, 9759, 0x38d0b78d -1, 425984, 425984, 4096, 10347, 0x3073bad7 -1, 430080, 430080, 4096, 11585, 0x114310ec -1, 434176, 434176, 4096, 11137, 0x6f420692 -1, 438272, 438272, 4096, 11099, 0xf9810272 -1, 442368, 442368, 4096, 11682, 0xe68452b7 -1, 446464, 446464, 4096, 11186, 0x899175ec -1, 450560, 450560, 4096, 9933, 0xac27d52f -1, 454656, 454656, 4096, 11609, 0xb6e31541 -1, 458752, 458752, 4096, 11632, 0x4898412b -1, 462848, 462848, 4096, 11132, 0x6a3d6295 -1, 466944, 466944, 4096, 11960, 0xcc76d187 -1, 471040, 471040, 4096, 11196, 0x384f57ef -1, 475136, 475136, 4096, 10619, 0x0e6d2961 -1, 479232, 479232, 4096, 11867, 0x7fe3b947 -1, 483328, 483328, 4096, 11190, 0x28785152 -1, 487424, 487424, 4096, 10375, 0xc67a06dc -1, 491520, 491520, 4096, 11959, 0xcc9a0e02 -1, 495616, 495616, 4096, 11400, 0x67e6d6e7 -1, 499712, 499712, 4096, 9897, 0x5db7d50f -1, 503808, 503808, 4096, 11460, 0x753cc6b9 -1, 507904, 507904, 4096, 11375, 0x76e9d803 -1, 512000, 512000, 4096, 11105, 0x22f71d1c -1, 516096, 516096, 4096, 10949, 0x7951202a -1, 520192, 520192, 4085, 11292, 0x8fc9ca01 +1, 0, 0, 4096, 16384, 0x00000000 +1, 4096, 4096, 4096, 16384, 0x29cd639d +1, 8192, 8192, 4096, 16384, 0xd52066e5 +1, 12288, 12288, 4096, 16384, 0x0c933408 +1, 16384, 16384, 4096, 16384, 0xb3b97675 +1, 20480, 20480, 4096, 16384, 0x1cb4a26b +1, 24576, 24576, 4096, 16384, 0x6bf693b9 +1, 28672, 28672, 4096, 16384, 0x12896c95 +1, 32768, 32768, 4096, 16384, 0x48b7167a +1, 36864, 36864, 4096, 16384, 0x5a9c06ad +1, 40960, 40960, 4096, 16384, 0x42fa8e65 +1, 45056, 45056, 4096, 16384, 0x175e6a61 +1, 49152, 49152, 4096, 16384, 0x3cd0e606 +1, 53248, 53248, 4096, 16384, 0x5ceff67d +1, 57344, 57344, 4096, 16384, 0xa24ba733 +1, 61440, 61440, 4096, 16384, 0xafe61a2d +1, 65536, 65536, 4096, 16384, 0xef8355f1 +1, 69632, 69632, 4096, 16384, 0x8e53cb7c +1, 73728, 73728, 4096, 16384, 0x461bb940 +1, 77824, 77824, 4096, 16384, 0x96bb6ebd +1, 81920, 81920, 4096, 16384, 0xb99977dc +1, 86016, 86016, 4096, 16384, 0xa6b6a178 +1, 90112, 90112, 4096, 16384, 0x7bdc3e50 +1, 94208, 94208, 4096, 16384, 0x44cda519 +1, 98304, 98304, 4096, 16384, 0xbdfd2e72 +1, 102400, 102400, 4096, 16384, 0x5c09dc3c +1, 106496, 106496, 4096, 16384, 0xe5aabb75 +1, 110592, 110592, 4096, 16384, 0x5db83fb2 +1, 114688, 114688, 4096, 16384, 0x69a6e3c0 +1, 118784, 118784, 4096, 16384, 0x0c09a90d +1, 122880, 122880, 4096, 16384, 0x978d2b50 +1, 126976, 126976, 4096, 16384, 0x9707fbaa +1, 131072, 131072, 4096, 16384, 0x8003f93b +1, 135168, 135168, 4096, 16384, 0xaa12ab0c +1, 139264, 139264, 4096, 16384, 0x49980501 +1, 143360, 143360, 4096, 16384, 0xdcb891db +1, 147456, 147456, 4096, 16384, 0x52b76938 +1, 151552, 151552, 4096, 16384, 0x7cb55457 +1, 155648, 155648, 4096, 16384, 0x6b08b7d2 +1, 159744, 159744, 4096, 16384, 0xb56bb312 +1, 163840, 163840, 4096, 16384, 0xcbf9d3e0 +1, 167936, 167936, 4096, 16384, 0xe8958c07 +1, 172032, 172032, 4096, 16384, 0x054ac021 +1, 176128, 176128, 4096, 16384, 0x36811603 +1, 180224, 180224, 4096, 16384, 0x3354f6e1 +1, 184320, 184320, 4096, 16384, 0xa6c11686 +1, 188416, 188416, 4096, 16384, 0xed353877 +1, 192512, 192512, 4096, 16384, 0xef21373e +1, 196608, 196608, 4096, 16384, 0x31c806d9 +1, 200704, 200704, 4096, 16384, 0x3c1c79d4 +1, 204800, 204800, 4096, 16384, 0x1b7b3d9a +1, 208896, 208896, 4096, 16384, 0x08977239 +1, 212992, 212992, 4096, 16384, 0x07f9d169 +1, 217088, 217088, 4096, 16384, 0xa66ae19a +1, 221184, 221184, 4096, 16384, 0x42f51169 +1, 225280, 225280, 4096, 16384, 0x98ff59b6 +1, 229376, 229376, 4096, 16384, 0x855216b9 +1, 233472, 233472, 4096, 16384, 0x0986573d +1, 237568, 237568, 4096, 16384, 0x060aeffe +1, 241664, 241664, 4096, 16384, 0x391c19bc +1, 245760, 245760, 4096, 16384, 0x9939c472 +1, 249856, 249856, 4096, 16384, 0x4e0d31c5 +1, 253952, 253952, 4096, 16384, 0xed2678a6 +1, 258048, 258048, 4096, 16384, 0xfd899fc3 +1, 262144, 262144, 4096, 16384, 0x35cf5263 +1, 266240, 266240, 4096, 16384, 0xa2e35dad +1, 270336, 270336, 4096, 16384, 0xf9ed08a0 +1, 274432, 274432, 4096, 16384, 0x022d9356 +1, 278528, 278528, 4096, 16384, 0x508042f7 +1, 282624, 282624, 4096, 16384, 0xe2e7e70b +1, 286720, 286720, 4096, 16384, 0x30812bfd +1, 290816, 290816, 4096, 16384, 0x5590ea7d +1, 294912, 294912, 4096, 16384, 0xebaa4fc4 +1, 299008, 299008, 4096, 16384, 0x731cee53 +1, 303104, 303104, 4096, 16384, 0x1127b480 +1, 307200, 307200, 4096, 16384, 0x0809f7c8 +1, 311296, 311296, 4096, 16384, 0xc0d4256f +1, 315392, 315392, 4096, 16384, 0xe868795c +1, 319488, 319488, 4096, 16384, 0x801a77d1 +1, 323584, 323584, 4096, 16384, 0x1d44bed5 +1, 327680, 327680, 4096, 16384, 0x7619f16b +1, 331776, 331776, 4096, 16384, 0x301064b6 +1, 335872, 335872, 4096, 16384, 0x42f3e0fb +1, 339968, 339968, 4096, 16384, 0xfe186dc6 +1, 344064, 344064, 4096, 16384, 0x1a9bbbab +1, 348160, 348160, 4096, 16384, 0x3c4e00a8 +1, 352256, 352256, 4096, 16384, 0x3101c84e +1, 356352, 356352, 4096, 16384, 0x11a6c764 +1, 360448, 360448, 4096, 16384, 0xb75e82a1 +1, 364544, 364544, 4096, 16384, 0x81e3b3dd +1, 368640, 368640, 4096, 16384, 0x2656fc8e +1, 372736, 372736, 4096, 16384, 0x6c655f40 +1, 376832, 376832, 4096, 16384, 0xba0432f9 +1, 380928, 380928, 4096, 16384, 0x7028ee57 +1, 385024, 385024, 4096, 16384, 0x16baf6ed +1, 389120, 389120, 4096, 16384, 0x863bcff5 +1, 393216, 393216, 4096, 16384, 0x4dbce87e +1, 397312, 397312, 4096, 16384, 0x825e268c +1, 401408, 401408, 4096, 16384, 0xfe269f0a +1, 405504, 405504, 4096, 16384, 0x47b9c0ef +1, 409600, 409600, 4096, 16384, 0xbbe55aac +1, 413696, 413696, 4096, 16384, 0xeb0674a7 +1, 417792, 417792, 4096, 16384, 0x01afba1b +1, 421888, 421888, 4096, 16384, 0x5ec18306 +1, 425984, 425984, 4096, 16384, 0x6d0b844f +1, 430080, 430080, 4096, 16384, 0x6cd1bea2 +1, 434176, 434176, 4096, 16384, 0x97e47cbb +1, 438272, 438272, 4096, 16384, 0xbb6bf554 +1, 442368, 442368, 4096, 16384, 0x33ea7961 +1, 446464, 446464, 4096, 16384, 0x83ce2f2a +1, 450560, 450560, 4096, 16384, 0x3bed9e0d +1, 454656, 454656, 4096, 16384, 0xd3a9570a +1, 458752, 458752, 4096, 16384, 0x4d5e1aca +1, 462848, 462848, 4096, 16384, 0x874a9b11 +1, 466944, 466944, 4096, 16384, 0xe51061d8 +1, 471040, 471040, 4096, 16384, 0x3582fac4 +1, 475136, 475136, 4096, 16384, 0x35df558e +1, 479232, 479232, 4096, 16384, 0xe2485fed +1, 483328, 483328, 4096, 16384, 0x31f9c6a7 +1, 487424, 487424, 4096, 16384, 0x0a82b244 +1, 491520, 491520, 4096, 16384, 0xfbb428f4 +1, 495616, 495616, 4096, 16384, 0x57b90bb6 +1, 499712, 499712, 4096, 16384, 0x5c6daa1a +1, 503808, 503808, 4096, 16384, 0xe02ac113 +1, 507904, 507904, 4096, 16384, 0x47ed59b6 +1, 512000, 512000, 4096, 16384, 0x220e4bd3 +1, 516096, 516096, 4096, 16384, 0x65de48b1 +1, 520192, 520192, 4085, 16340, 0x326fa751 From 1da8c4ec85c150349b81237d13d84cb16404243d Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 17 Oct 2017 23:39:59 +0200 Subject: [PATCH 0644/2557] lavfi/palettegen: Allow setting the background colour. --- doc/filters.texi | 3 +++ libavfilter/version.h | 2 +- libavfilter/vf_palettegen.c | 5 ++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 64e84d9b452ee..6f6dfcff48241 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -11458,6 +11458,9 @@ If not set, the maximum of colors in the palette will be 256. You probably want to disable this option for a standalone image. Set by default. +@item transparency_color +Set the color that will be used as background for transparency. + @item stats_mode Set statistics mode. diff --git a/libavfilter/version.h b/libavfilter/version.h index 5bcf9b4df08e9..908dc4938a64d 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #define LIBAVFILTER_VERSION_MAJOR 7 #define LIBAVFILTER_VERSION_MINOR 0 -#define LIBAVFILTER_VERSION_MICRO 100 +#define LIBAVFILTER_VERSION_MICRO 101 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ diff --git a/libavfilter/vf_palettegen.c b/libavfilter/vf_palettegen.c index 03de3173483e2..2a04ae5c4d8bd 100644 --- a/libavfilter/vf_palettegen.c +++ b/libavfilter/vf_palettegen.c @@ -27,6 +27,7 @@ #include "libavutil/internal.h" #include "libavutil/opt.h" #include "libavutil/qsort.h" +#include "libavutil/intreadwrite.h" #include "avfilter.h" #include "internal.h" @@ -74,6 +75,7 @@ typedef struct PaletteGenContext { struct range_box boxes[256]; // define the segmentation of the colorspace (the final palette) int nb_boxes; // number of boxes (increase will segmenting them) int palette_pushed; // if the palette frame is pushed into the outlink or not + uint8_t[4] transparency_color; // background color for transparency } PaletteGenContext; #define OFFSET(x) offsetof(PaletteGenContext, x) @@ -81,6 +83,7 @@ typedef struct PaletteGenContext { static const AVOption palettegen_options[] = { { "max_colors", "set the maximum number of colors to use in the palette", OFFSET(max_colors), AV_OPT_TYPE_INT, {.i64=256}, 4, 256, FLAGS }, { "reserve_transparent", "reserve a palette entry for transparency", OFFSET(reserve_transparent), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, + { "transparency_color", "set a background color for transparency", OFFSET(transparency_color), AV_OPT_TYPE_COLOR, {.str="lime"}, CHAR_MIN, CHAR_MAX, FLAGS }, { "stats_mode", "set statistics mode", OFFSET(stats_mode), AV_OPT_TYPE_INT, {.i64=STATS_MODE_ALL_FRAMES}, 0, NB_STATS_MODE-1, FLAGS, "mode" }, { "full", "compute full frame histograms", 0, AV_OPT_TYPE_CONST, {.i64=STATS_MODE_ALL_FRAMES}, INT_MIN, INT_MAX, FLAGS, "mode" }, { "diff", "compute histograms only for the part that differs from previous frame", 0, AV_OPT_TYPE_CONST, {.i64=STATS_MODE_DIFF_FRAMES}, INT_MIN, INT_MAX, FLAGS, "mode" }, @@ -250,7 +253,7 @@ static void write_palette(AVFilterContext *ctx, AVFrame *out) if (s->reserve_transparent) { av_assert0(s->nb_boxes < 256); - pal[out->width - pal_linesize - 1] = 0x0000ff00; // add a green transparent color + pal[out->width - pal_linesize - 1] = AV_RB32(&s->transparency_color) >> 8; } } From 8b43039fe19cacb8e7e0950ae50851cb91fa34e4 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 29 Oct 2017 02:35:36 +0200 Subject: [PATCH 0645/2557] lavfi/palettegen: Fix compilation after 1da8c4e. Found-by: James Almer --- libavfilter/vf_palettegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_palettegen.c b/libavfilter/vf_palettegen.c index 2a04ae5c4d8bd..5ff73e6b2b0d9 100644 --- a/libavfilter/vf_palettegen.c +++ b/libavfilter/vf_palettegen.c @@ -75,7 +75,7 @@ typedef struct PaletteGenContext { struct range_box boxes[256]; // define the segmentation of the colorspace (the final palette) int nb_boxes; // number of boxes (increase will segmenting them) int palette_pushed; // if the palette frame is pushed into the outlink or not - uint8_t[4] transparency_color; // background color for transparency + uint8_t transparency_color[4]; // background color for transparency } PaletteGenContext; #define OFFSET(x) offsetof(PaletteGenContext, x) From ca2b7794234cccd6c4ae548c4bd2eac5c53b80f2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 28 Oct 2017 23:47:22 -0300 Subject: [PATCH 0646/2557] avformat: remove use of deprecated AVFMT_FLAG_KEEP_SIDE_DATA flag It has no effect whatsoever since the major bump. Replace the flag's documentation to reflect this as well. Signed-off-by: James Almer --- fftools/ffmpeg_opt.c | 2 -- fftools/ffprobe.c | 2 -- libavformat/avformat.h | 2 +- libavformat/options_table.h | 2 +- libavformat/tests/seek.c | 2 -- 5 files changed, 2 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 3a947d8686e22..f4ff1605f0789 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -991,7 +991,6 @@ static int open_input_file(OptionsContext *o, const char *filename) print_error(filename, AVERROR(ENOMEM)); exit_program(1); } - ic->flags |= AVFMT_FLAG_KEEP_SIDE_DATA; if (o->nb_audio_sample_rate) { av_dict_set_int(&o->g->format_opts, "sample_rate", o->audio_sample_rate[o->nb_audio_sample_rate - 1].u.i, 0); } @@ -1989,7 +1988,6 @@ static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch int i, err; AVFormatContext *ic = avformat_alloc_context(); - ic->flags |= AVFMT_FLAG_KEEP_SIDE_DATA; ic->interrupt_callback = int_cb; err = avformat_open_input(&ic, filename, NULL, NULL); if (err < 0) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index b2e8949d9f909..ab36f8bc42652 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2828,8 +2828,6 @@ static int open_input_file(InputFile *ifile, const char *filename) exit_program(1); } - fmt_ctx->flags |= AVFMT_FLAG_KEEP_SIDE_DATA; - if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) { av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE); scan_all_pmts_set = 1; diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 65fc9eac0cd29..edb0c601f910c 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1444,7 +1444,7 @@ typedef struct AVFormatContext { #define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down) #define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (this could be made default once all code is converted) #if FF_API_LAVF_KEEPSIDE_FLAG -#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Don't merge side data but keep it separate. Deprecated, will be the default. +#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Deprecated, does nothing. #endif #define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats #define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops. diff --git a/libavformat/options_table.h b/libavformat/options_table.h index 118086df665eb..b60d031f67e3c 100644 --- a/libavformat/options_table.h +++ b/libavformat/options_table.h @@ -49,7 +49,7 @@ static const AVOption avformat_options[] = { {"discardcorrupt", "discard corrupted frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_DISCARD_CORRUPT }, INT_MIN, INT_MAX, D, "fflags"}, {"sortdts", "try to interleave outputted packets by dts", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_SORT_DTS }, INT_MIN, INT_MAX, D, "fflags"}, #if FF_API_LAVF_KEEPSIDE_FLAG -{"keepside", "don't merge side data", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_KEEP_SIDE_DATA }, INT_MIN, INT_MAX, D, "fflags"}, +{"keepside", "deprecated, does nothing", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_KEEP_SIDE_DATA }, INT_MIN, INT_MAX, D, "fflags"}, #endif {"fastseek", "fast but inaccurate seeks", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_FAST_SEEK }, INT_MIN, INT_MAX, D, "fflags"}, {"latm", "enable RTP MP4A-LATM payload", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_MP4A_LATM }, INT_MIN, INT_MAX, E, "fflags"}, diff --git a/libavformat/tests/seek.c b/libavformat/tests/seek.c index 5cf3a123e33fb..7ed56ba4ef980 100644 --- a/libavformat/tests/seek.c +++ b/libavformat/tests/seek.c @@ -67,8 +67,6 @@ int main(int argc, char **argv) int frame_count = 1; int duration = 4; - ic->flags |= AVFMT_FLAG_KEEP_SIDE_DATA; - for(i=2; i Date: Sun, 29 Oct 2017 12:30:44 +0800 Subject: [PATCH 0647/2557] avformat/hlsenc: fix base_output_dirname is null when basename_size is 0 bug fix ticket id: #6777 when use argument hls_segment_filename, the basename_size will be 0 Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 418f153c6f99f..55ce800c5a556 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1335,6 +1335,7 @@ static int hls_write_header(AVFormatContext *s) AVDictionary *options = NULL; int basename_size = 0; int vtt_basename_size = 0; + int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1; if (hls->segment_type == SEGMENT_TYPE_FMP4) { pattern = "%d.m4s"; @@ -1445,7 +1446,6 @@ static int hls_write_header(AVFormatContext *s) } if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) { - int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1; hls->base_output_dirname = av_malloc(fmp4_init_filename_len); if (!hls->base_output_dirname) { ret = AVERROR(ENOMEM); @@ -1453,19 +1453,25 @@ static int hls_write_header(AVFormatContext *s) } av_strlcpy(hls->base_output_dirname, hls->fmp4_init_filename, fmp4_init_filename_len); } else { - hls->base_output_dirname = av_malloc(basename_size); + if (basename_size > 0) { + hls->base_output_dirname = av_malloc(basename_size); + } else { + hls->base_output_dirname = av_malloc(strlen(hls->fmp4_init_filename)); + } if (!hls->base_output_dirname) { ret = AVERROR(ENOMEM); goto fail; } - av_strlcpy(hls->base_output_dirname, s->filename, basename_size); - p = strrchr(hls->base_output_dirname, '/'); + if (basename_size > 0) { + av_strlcpy(hls->base_output_dirname, s->filename, basename_size); + p = strrchr(hls->base_output_dirname, '/'); + } if (p) { *(p + 1) = '\0'; av_strlcat(hls->base_output_dirname, hls->fmp4_init_filename, basename_size); } else { - av_strlcpy(hls->base_output_dirname, hls->fmp4_init_filename, basename_size); + av_strlcpy(hls->base_output_dirname, hls->fmp4_init_filename, fmp4_init_filename_len); } } From c3e279e75227946046ccb447d355b557118a616c Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Sun, 29 Oct 2017 12:31:49 +0800 Subject: [PATCH 0648/2557] avformat/hlsenc: fix missing first segment bug in fmp4 mode fix ticket id: #6776 fix code logic error, need not check first segment. Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 55ce800c5a556..530fc11305f48 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1080,7 +1080,7 @@ static int hls_window(AVFormatContext *s, int last) avio_printf(out, ",BYTERANGE=\"%"PRId64"@%"PRId64"\"", en->size, en->pos); } avio_printf(out, "\n"); - } else { + } if (hls->flags & HLS_ROUND_DURATIONS) avio_printf(out, "#EXTINF:%ld,\n", lrint(en->duration)); else @@ -1088,7 +1088,7 @@ static int hls_window(AVFormatContext *s, int last) if (byterange_mode) avio_printf(out, "#EXT-X-BYTERANGE:%"PRId64"@%"PRId64"\n", en->size, en->pos); - } + if (hls->flags & HLS_PROGRAM_DATE_TIME) { time_t tt, wrongsecs; int milli; @@ -1113,11 +1113,9 @@ static int hls_window(AVFormatContext *s, int last) avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, milli, buf1); prog_date_time += en->duration; } - if (!((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == hls->segments))) { if (hls->baseurl) avio_printf(out, "%s", hls->baseurl); avio_printf(out, "%s\n", en->filename); - } } if (last && (hls->flags & HLS_OMIT_ENDLIST)==0) From 073986c5aeb84e51b202f908d5ede059d371d57b Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Sun, 29 Oct 2017 12:32:24 +0800 Subject: [PATCH 0649/2557] avformat/hlsenc: reindent hlsenc code Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 530fc11305f48..0ea93480a5bb6 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1081,13 +1081,13 @@ static int hls_window(AVFormatContext *s, int last) } avio_printf(out, "\n"); } - if (hls->flags & HLS_ROUND_DURATIONS) - avio_printf(out, "#EXTINF:%ld,\n", lrint(en->duration)); - else - avio_printf(out, "#EXTINF:%f,\n", en->duration); - if (byterange_mode) - avio_printf(out, "#EXT-X-BYTERANGE:%"PRId64"@%"PRId64"\n", - en->size, en->pos); + if (hls->flags & HLS_ROUND_DURATIONS) + avio_printf(out, "#EXTINF:%ld,\n", lrint(en->duration)); + else + avio_printf(out, "#EXTINF:%f,\n", en->duration); + if (byterange_mode) + avio_printf(out, "#EXT-X-BYTERANGE:%"PRId64"@%"PRId64"\n", + en->size, en->pos); if (hls->flags & HLS_PROGRAM_DATE_TIME) { time_t tt, wrongsecs; @@ -1113,9 +1113,9 @@ static int hls_window(AVFormatContext *s, int last) avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, milli, buf1); prog_date_time += en->duration; } - if (hls->baseurl) - avio_printf(out, "%s", hls->baseurl); - avio_printf(out, "%s\n", en->filename); + if (hls->baseurl) + avio_printf(out, "%s", hls->baseurl); + avio_printf(out, "%s\n", en->filename); } if (last && (hls->flags & HLS_OMIT_ENDLIST)==0) From 7da254886fbf39dc1bde9b3776f8cfbfcc471a7e Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 28 Oct 2017 23:17:44 +0200 Subject: [PATCH 0650/2557] libavcodec/magicyuv : remove unneed variable assignment --- libavcodec/magicyuv.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/libavcodec/magicyuv.c b/libavcodec/magicyuv.c index 3c1a89077bf56..195df121cdb99 100644 --- a/libavcodec/magicyuv.c +++ b/libavcodec/magicyuv.c @@ -280,11 +280,9 @@ static int magy_decode_slice10(AVCodecContext *avctx, void *tdata, case GRADIENT: dst = (uint16_t *)p->data[i] + j * sheight * stride; s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); - left = lefttop = 0; dst += stride; if (interlaced) { s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); - left = lefttop = 0; dst += stride; } for (k = 1 + interlaced; k < height; k++) { @@ -302,14 +300,13 @@ static int magy_decode_slice10(AVCodecContext *avctx, void *tdata, break; case MEDIAN: dst = (uint16_t *)p->data[i] + j * sheight * stride; - lefttop = left = dst[0]; s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); dst += stride; if (interlaced) { - lefttop = left = dst[0]; s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); dst += stride; } + lefttop = left = dst[0]; for (k = 1 + interlaced; k < height; k++) { magicyuv_median_pred16(dst, dst - fake_stride, dst, width, &left, &lefttop, max); lefttop = left = dst[0]; @@ -411,11 +408,9 @@ static int magy_decode_slice(AVCodecContext *avctx, void *tdata, case GRADIENT: dst = p->data[i] + j * sheight * stride; s->llviddsp.add_left_pred(dst, dst, width, 0); - left = lefttop = 0; dst += stride; if (interlaced) { s->llviddsp.add_left_pred(dst, dst, width, 0); - left = lefttop = 0; dst += stride; } for (k = 1 + interlaced; k < height; k++) { @@ -433,14 +428,13 @@ static int magy_decode_slice(AVCodecContext *avctx, void *tdata, break; case MEDIAN: dst = p->data[i] + j * sheight * stride; - lefttop = left = dst[0]; s->llviddsp.add_left_pred(dst, dst, width, 0); dst += stride; if (interlaced) { - lefttop = left = dst[0]; s->llviddsp.add_left_pred(dst, dst, width, 0); dst += stride; } + lefttop = left = dst[0]; for (k = 1 + interlaced; k < height; k++) { s->llviddsp.add_median_pred(dst, dst - fake_stride, dst, width, &left, &lefttop); From ca106d6a5c4c62516876222745e16bafcc774d06 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 29 Oct 2017 12:13:54 +0100 Subject: [PATCH 0651/2557] avcodec/magicyuvenc: improve compression Signed-off-by: Paul B Mahol --- libavcodec/magicyuvenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/magicyuvenc.c b/libavcodec/magicyuvenc.c index f948b03e4b52e..a30922f57077a 100644 --- a/libavcodec/magicyuvenc.c +++ b/libavcodec/magicyuvenc.c @@ -344,7 +344,7 @@ static int encode_table(AVCodecContext *avctx, uint8_t *dst, for (i = 0; i < 256; i++) { counts[i].prob++; - counts[i].value = i; + counts[i].value = 255 - i; } magy_huffman_compute_bits(counts, he, 256, 16); From 7df37dd319f2d9d3e1becd5d433884e3ccfa1ee2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 23 Oct 2017 11:10:48 -0300 Subject: [PATCH 0652/2557] avutil/frame: deprecate getters and setters for AVFrame fields The fields can be accessed directly, so these are not needed anymore. Reviewed-by: Paul B Mahol Signed-off-by: James Almer --- libavutil/frame.c | 2 ++ libavutil/frame.h | 26 ++++++++++++++++++++++++++ libavutil/version.h | 3 +++ 3 files changed, 31 insertions(+) diff --git a/libavutil/frame.c b/libavutil/frame.c index 09dd98a6b52be..982fbb5c813db 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -31,6 +31,7 @@ static AVFrameSideData *frame_new_side_data(AVFrame *frame, enum AVFrameSideDataType type, AVBufferRef *buf); +#if FF_API_FRAME_GET_SET MAKE_ACCESSORS(AVFrame, frame, int64_t, best_effort_timestamp) MAKE_ACCESSORS(AVFrame, frame, int64_t, pkt_duration) MAKE_ACCESSORS(AVFrame, frame, int64_t, pkt_pos) @@ -42,6 +43,7 @@ MAKE_ACCESSORS(AVFrame, frame, int, decode_error_flags) MAKE_ACCESSORS(AVFrame, frame, int, pkt_size) MAKE_ACCESSORS(AVFrame, frame, enum AVColorSpace, colorspace) MAKE_ACCESSORS(AVFrame, frame, enum AVColorRange, color_range) +#endif #define CHECK_CHANNELS_CONSISTENCY(frame) \ av_assert2(!(frame)->channel_layout || \ diff --git a/libavutil/frame.h b/libavutil/frame.h index fef558ea2f0a7..0c6aab1c029c8 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -565,36 +565,62 @@ typedef struct AVFrame { */ } AVFrame; +#if FF_API_FRAME_GET_SET /** * Accessors for some AVFrame fields. These used to be provided for ABI * compatibility, and do not need to be used anymore. */ +attribute_deprecated int64_t av_frame_get_best_effort_timestamp(const AVFrame *frame); +attribute_deprecated void av_frame_set_best_effort_timestamp(AVFrame *frame, int64_t val); +attribute_deprecated int64_t av_frame_get_pkt_duration (const AVFrame *frame); +attribute_deprecated void av_frame_set_pkt_duration (AVFrame *frame, int64_t val); +attribute_deprecated int64_t av_frame_get_pkt_pos (const AVFrame *frame); +attribute_deprecated void av_frame_set_pkt_pos (AVFrame *frame, int64_t val); +attribute_deprecated int64_t av_frame_get_channel_layout (const AVFrame *frame); +attribute_deprecated void av_frame_set_channel_layout (AVFrame *frame, int64_t val); +attribute_deprecated int av_frame_get_channels (const AVFrame *frame); +attribute_deprecated void av_frame_set_channels (AVFrame *frame, int val); +attribute_deprecated int av_frame_get_sample_rate (const AVFrame *frame); +attribute_deprecated void av_frame_set_sample_rate (AVFrame *frame, int val); +attribute_deprecated AVDictionary *av_frame_get_metadata (const AVFrame *frame); +attribute_deprecated void av_frame_set_metadata (AVFrame *frame, AVDictionary *val); +attribute_deprecated int av_frame_get_decode_error_flags (const AVFrame *frame); +attribute_deprecated void av_frame_set_decode_error_flags (AVFrame *frame, int val); +attribute_deprecated int av_frame_get_pkt_size(const AVFrame *frame); +attribute_deprecated void av_frame_set_pkt_size(AVFrame *frame, int val); #if FF_API_FRAME_QP +attribute_deprecated int8_t *av_frame_get_qp_table(AVFrame *f, int *stride, int *type); +attribute_deprecated int av_frame_set_qp_table(AVFrame *f, AVBufferRef *buf, int stride, int type); #endif +attribute_deprecated enum AVColorSpace av_frame_get_colorspace(const AVFrame *frame); +attribute_deprecated void av_frame_set_colorspace(AVFrame *frame, enum AVColorSpace val); +attribute_deprecated enum AVColorRange av_frame_get_color_range(const AVFrame *frame); +attribute_deprecated void av_frame_set_color_range(AVFrame *frame, enum AVColorRange val); +#endif /** * Get the name of a colorspace. diff --git a/libavutil/version.h b/libavutil/version.h index ad22e67b0384b..1bc4b2a6cbea9 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -124,6 +124,9 @@ #ifndef FF_API_CRYPTO_SIZE_T #define FF_API_CRYPTO_SIZE_T (LIBAVUTIL_VERSION_MAJOR < 57) #endif +#ifndef FF_API_FRAME_GET_SET +#define FF_API_FRAME_GET_SET (LIBAVUTIL_VERSION_MAJOR < 57) +#endif /** From 307c24b32f30f08b759457bd9997cdfcd51927ae Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 23 Oct 2017 11:28:07 -0300 Subject: [PATCH 0653/2557] avformat: move public AVStream fields up in the struct Remove the silly second notice. Reviewed-by: Paul B Mahol Signed-off-by: James Almer --- libavformat/avformat.h | 65 ++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index edb0c601f910c..a84e0f4dcce70 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -976,6 +976,34 @@ typedef struct AVStream { int event_flags; #define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in updated metadata. + /** + * Real base framerate of the stream. + * This is the lowest framerate with which all timestamps can be + * represented accurately (it is the least common multiple of all + * framerates in the stream). Note, this value is just a guess! + * For example, if the time base is 1/90000 and all frames have either + * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1. + */ + AVRational r_frame_rate; + + /** + * String containing paris of key and values describing recommended encoder configuration. + * Paris are separated by ','. + * Keys are separated from values by '='. + */ + char *recommended_encoder_configuration; + + /** + * Codec parameters associated with this stream. Allocated and freed by + * libavformat in avformat_new_stream() and avformat_free_context() + * respectively. + * + * - demuxing: filled by libavformat on stream creation or in + * avformat_find_stream_info() + * - muxing: filled by the caller before avformat_write_header() + */ + AVCodecParameters *codecpar; + /***************************************************************** * All fields below this line are not part of the public API. They * may not be used outside of libavformat and can be changed and @@ -1060,19 +1088,6 @@ typedef struct AVStream { int nb_index_entries; unsigned int index_entries_allocated_size; - /** - * Real base framerate of the stream. - * This is the lowest framerate with which all timestamps can be - * represented accurately (it is the least common multiple of all - * framerates in the stream). Note, this value is just a guess! - * For example, if the time base is 1/90000 and all frames have either - * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1. - * - * Code outside avformat should access this field using: - * av_stream_get/set_r_frame_rate(stream) - */ - AVRational r_frame_rate; - /** * Stream Identifier * This is the MPEG-TS stream identifier +1 @@ -1178,19 +1193,6 @@ typedef struct AVStream { */ int inject_global_side_data; - /***************************************************************** - * All fields above this line are not part of the public API. - * Fields below are part of the public API and ABI again. - ***************************************************************** - */ - - /** - * String containing paris of key and values describing recommended encoder configuration. - * Paris are separated by ','. - * Keys are separated from values by '='. - */ - char *recommended_encoder_configuration; - /** * display aspect ratio (0 if unknown) * - encoding: unused @@ -1205,17 +1207,6 @@ typedef struct AVStream { * Must not be accessed in any way by callers. */ AVStreamInternal *internal; - - /* - * Codec parameters associated with this stream. Allocated and freed by - * libavformat in avformat_new_stream() and avformat_free_context() - * respectively. - * - * - demuxing: filled by libavformat on stream creation or in - * avformat_find_stream_info() - * - muxing: filled by the caller before avformat_write_header() - */ - AVCodecParameters *codecpar; } AVStream; AVRational av_stream_get_r_frame_rate(const AVStream *s); From b7785d10b00c88029d8af7dbddac09ab0d6f2b7f Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 23 Oct 2017 11:39:08 -0300 Subject: [PATCH 0654/2557] avformat: deprecate getters and setters for AVFormatContext and AVStream fields The fields can be accessed directly, so these are not needed anymore. Reviewed-by: Paul B Mahol Signed-off-by: James Almer --- libavformat/avformat.h | 30 +++++++++++++++++++++++++++++- libavformat/utils.c | 4 ++++ libavformat/version.h | 3 +++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index a84e0f4dcce70..941a7bc3eb3d9 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1209,11 +1209,22 @@ typedef struct AVStream { AVStreamInternal *internal; } AVStream; +#if FF_API_FORMAT_GET_SET +/** + * Accessors for some AVStream fields. These used to be provided for ABI + * compatibility, and do not need to be used anymore. + */ +attribute_deprecated AVRational av_stream_get_r_frame_rate(const AVStream *s); +attribute_deprecated void av_stream_set_r_frame_rate(AVStream *s, AVRational r); -struct AVCodecParserContext *av_stream_get_parser(const AVStream *s); +attribute_deprecated char* av_stream_get_recommended_encoder_configuration(const AVStream *s); +attribute_deprecated void av_stream_set_recommended_encoder_configuration(AVStream *s, char *configuration); +#endif + +struct AVCodecParserContext *av_stream_get_parser(const AVStream *s); /** * Returns the pts of the last muxed packet + its duration @@ -1885,29 +1896,46 @@ typedef struct AVFormatContext { int max_streams; } AVFormatContext; +#if FF_API_FORMAT_GET_SET /** * Accessors for some AVFormatContext fields. These used to be provided for ABI * compatibility, and do not need to be used anymore. */ +attribute_deprecated int av_format_get_probe_score(const AVFormatContext *s); +attribute_deprecated AVCodec * av_format_get_video_codec(const AVFormatContext *s); +attribute_deprecated void av_format_set_video_codec(AVFormatContext *s, AVCodec *c); +attribute_deprecated AVCodec * av_format_get_audio_codec(const AVFormatContext *s); +attribute_deprecated void av_format_set_audio_codec(AVFormatContext *s, AVCodec *c); +attribute_deprecated AVCodec * av_format_get_subtitle_codec(const AVFormatContext *s); +attribute_deprecated void av_format_set_subtitle_codec(AVFormatContext *s, AVCodec *c); +attribute_deprecated AVCodec * av_format_get_data_codec(const AVFormatContext *s); +attribute_deprecated void av_format_set_data_codec(AVFormatContext *s, AVCodec *c); +attribute_deprecated int av_format_get_metadata_header_padding(const AVFormatContext *s); +attribute_deprecated void av_format_set_metadata_header_padding(AVFormatContext *s, int c); +attribute_deprecated void * av_format_get_opaque(const AVFormatContext *s); +attribute_deprecated void av_format_set_opaque(AVFormatContext *s, void *opaque); +attribute_deprecated av_format_control_message av_format_get_control_message_cb(const AVFormatContext *s); +attribute_deprecated void av_format_set_control_message_cb(AVFormatContext *s, av_format_control_message callback); #if FF_API_OLD_OPEN_CALLBACKS attribute_deprecated AVOpenCallback av_format_get_open_cb(const AVFormatContext *s); attribute_deprecated void av_format_set_open_cb(AVFormatContext *s, AVOpenCallback callback); #endif +#endif /** * This function will cause global side data to be injected in the next packet diff --git a/libavformat/utils.c b/libavformat/utils.c index 0ab2f61eb09fd..cbfb78bf4d630 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -104,6 +104,7 @@ static int64_t wrap_timestamp(const AVStream *st, int64_t timestamp) return timestamp; } +#if FF_API_FORMAT_GET_SET MAKE_ACCESSORS(AVStream, stream, AVRational, r_frame_rate) MAKE_ACCESSORS(AVStream, stream, char *, recommended_encoder_configuration) MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, video_codec) @@ -118,6 +119,7 @@ FF_DISABLE_DEPRECATION_WARNINGS MAKE_ACCESSORS(AVFormatContext, format, AVOpenCallback, open_cb) FF_ENABLE_DEPRECATION_WARNINGS #endif +#endif int64_t av_stream_get_end_pts(const AVStream *st) { @@ -215,10 +217,12 @@ static const AVCodec *find_probe_decoder(AVFormatContext *s, const AVStream *st, return codec; } +#if FF_API_FORMAT_GET_SET int av_format_get_probe_score(const AVFormatContext *s) { return s->probe_score; } +#endif /* an arbitrarily chosen "sane" max packet size -- 50M */ #define SANE_CHUNK_SIZE (50000000) diff --git a/libavformat/version.h b/libavformat/version.h index ac409dbad2d69..06d54834a97d6 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -76,6 +76,9 @@ #ifndef FF_API_OLD_ROTATE_API #define FF_API_OLD_ROTATE_API (LIBAVFORMAT_VERSION_MAJOR < 59) #endif +#ifndef FF_API_FORMAT_GET_SET +#define FF_API_FORMAT_GET_SET (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif #ifndef FF_API_R_FRAME_RATE From c8e8092543ddd09b5e5e69cde13d6f054edc69ab Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 29 Oct 2017 10:35:40 -0300 Subject: [PATCH 0655/2557] avformat/avformat.h: fix pairs typo Found-by: Paul B Mahol Signed-off-by: James Almer --- libavformat/avformat.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 941a7bc3eb3d9..b36e2a3bd4d6a 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -987,8 +987,8 @@ typedef struct AVStream { AVRational r_frame_rate; /** - * String containing paris of key and values describing recommended encoder configuration. - * Paris are separated by ','. + * String containing pairs of key and values describing recommended encoder configuration. + * Pairs are separated by ','. * Keys are separated from values by '='. */ char *recommended_encoder_configuration; From 9b0510a8e35930a22790518270ee6d3fad9f1666 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 29 Oct 2017 01:40:18 +0200 Subject: [PATCH 0656/2557] lsws/yuv2rgb: Fix yuva2rgb32 on big endian hardware. --- libswscale/version.h | 2 +- libswscale/yuv2rgb.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libswscale/version.h b/libswscale/version.h index 9c241220315bb..0393a6fe4aff6 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -28,7 +28,7 @@ #define LIBSWSCALE_VERSION_MAJOR 5 #define LIBSWSCALE_VERSION_MINOR 0 -#define LIBSWSCALE_VERSION_MICRO 100 +#define LIBSWSCALE_VERSION_MICRO 101 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ LIBSWSCALE_VERSION_MINOR, \ diff --git a/libswscale/yuv2rgb.c b/libswscale/yuv2rgb.c index 1fe5abed9c49c..737cbb06c806e 100644 --- a/libswscale/yuv2rgb.c +++ b/libswscale/yuv2rgb.c @@ -267,7 +267,11 @@ ENDYUV2RGBLINE(8, 1) PUTRGB(dst_2, py_2, 0); ENDYUV2RGBFUNC() +#if HAVE_BIGENDIAN +YUV2RGBFUNC(yuva2argb_c, uint32_t, 1) +#else YUV2RGBFUNC(yuva2rgba_c, uint32_t, 1) +#endif LOADCHROMA(0); PUTRGBA(dst_1, py_1, pa_1, 0, 24); PUTRGBA(dst_2, py_2, pa_2, 0, 24); @@ -301,7 +305,11 @@ ENDYUV2RGBLINE(8, 1) PUTRGBA(dst_2, py_2, pa_2, 0, 24); ENDYUV2RGBFUNC() +#if HAVE_BIGENDIAN +YUV2RGBFUNC(yuva2rgba_c, uint32_t, 1) +#else YUV2RGBFUNC(yuva2argb_c, uint32_t, 1) +#endif LOADCHROMA(0); PUTRGBA(dst_1, py_1, pa_1, 0, 0); PUTRGBA(dst_2, py_2, pa_2, 0, 0); From e9930883a26c77261c19ea9ad9b930b065c6f579 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 22 Oct 2017 19:06:50 +0200 Subject: [PATCH 0657/2557] libavcodec/bswapdsp : add AVX2 func for bswap_buf (swap uint32_t) --- libavcodec/x86/bswapdsp.asm | 48 +++++++++++++++++++++++++--------- libavcodec/x86/bswapdsp_init.c | 3 +++ 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/libavcodec/x86/bswapdsp.asm b/libavcodec/x86/bswapdsp.asm index 56d808362278a..219d172481160 100644 --- a/libavcodec/x86/bswapdsp.asm +++ b/libavcodec/x86/bswapdsp.asm @@ -35,14 +35,18 @@ SECTION .text mov r3d, r2d sar r2d, 3 jz .left4_%1 +%if cpuflag(avx2) + sar r2d, 1 + jz .left8_%1 +%endif .loop8_%1: mov%1 m0, [r1 + 0] - mov%1 m1, [r1 + 16] -%if cpuflag(ssse3) + mov%1 m1, [r1 + mmsize] +%if cpuflag(ssse3)||cpuflag(avx2) pshufb m0, m2 pshufb m1, m2 mov%1 [r0 + 0], m0 - mov%1 [r0 + 16], m1 + mov%1 [r0 + mmsize], m1 %else pshuflw m0, m0, 10110001b pshuflw m1, m1, 10110001b @@ -59,18 +63,29 @@ SECTION .text mov%1 [r0 + 0], m2 mov%1 [r0 + 16], m3 %endif - add r0, 32 - add r1, 32 + add r0, mmsize*2 + add r1, mmsize*2 dec r2d jnz .loop8_%1 +%if cpuflag(avx2) +.left8_%1: + mov r2d, r3d + test r3d, 8 + jz .left4_%1 + mov%1 m0, [r1] + pshufb m0, m2 + mov%1 [r0 + 0], m0 + add r1, mmsize + add r0, mmsize +%endif .left4_%1: mov r2d, r3d test r3d, 4 jz .left - mov%1 m0, [r1] + mov%1 xm0, [r1] %if cpuflag(ssse3) - pshufb m0, m2 - mov%1 [r0], m0 + pshufb xm0, xm2 + mov%1 [r0], xm0 %else pshuflw m0, m0, 10110001b pshufhw m0, m0, 10110001b @@ -86,16 +101,20 @@ SECTION .text ; void ff_bswap_buf(uint32_t *dst, const uint32_t *src, int w); %macro BSWAP32_BUF 0 -%if cpuflag(ssse3) +%if cpuflag(ssse3)||cpuflag(avx2) cglobal bswap32_buf, 3,4,3 mov r3, r1 +%if cpuflag(avx2) + vbroadcasti128 m2, [pb_bswap32] +%else mova m2, [pb_bswap32] +%endif %else cglobal bswap32_buf, 3,4,5 mov r3, r1 %endif or r3, r0 - test r3, 15 + test r3, mmsize - 1 jz .start_align BSWAP_LOOPS u jmp .left @@ -105,9 +124,9 @@ cglobal bswap32_buf, 3,4,5 %if cpuflag(ssse3) test r2d, 2 jz .left1 - movq m0, [r1] - pshufb m0, m2 - movq [r0], m0 + movq xm0, [r1] + pshufb xm0, xm2 + movq [r0], xm0 add r1, 8 add r0, 8 .left1: @@ -137,3 +156,6 @@ BSWAP32_BUF INIT_XMM ssse3 BSWAP32_BUF + +INIT_YMM avx2 +BSWAP32_BUF diff --git a/libavcodec/x86/bswapdsp_init.c b/libavcodec/x86/bswapdsp_init.c index c042e56371298..877bab1a2ce41 100644 --- a/libavcodec/x86/bswapdsp_init.c +++ b/libavcodec/x86/bswapdsp_init.c @@ -25,6 +25,7 @@ void ff_bswap32_buf_sse2(uint32_t *dst, const uint32_t *src, int w); void ff_bswap32_buf_ssse3(uint32_t *dst, const uint32_t *src, int w); +void ff_bswap32_buf_avx2(uint32_t *dst, const uint32_t *src, int w); av_cold void ff_bswapdsp_init_x86(BswapDSPContext *c) { @@ -34,4 +35,6 @@ av_cold void ff_bswapdsp_init_x86(BswapDSPContext *c) c->bswap_buf = ff_bswap32_buf_sse2; if (EXTERNAL_SSSE3(cpu_flags)) c->bswap_buf = ff_bswap32_buf_ssse3; + if (EXTERNAL_AVX2_FAST(cpu_flags)) + c->bswap_buf = ff_bswap32_buf_avx2; } From 75bd01090f5b93eb1d2b4543d1c01031281879a4 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 24 Oct 2017 23:03:02 +0200 Subject: [PATCH 0658/2557] lavf/rtpenc: Add support for 24 bit pcm encoding as defined by RFC 3190. Fixes ticket #6770. --- libavformat/rtpenc.c | 3 +++ libavformat/sdp.c | 6 ++++++ libavformat/version.h | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index 573593fa663fd..63047beccc8d7 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -66,6 +66,7 @@ static int is_supported(enum AVCodecID id) case AV_CODEC_ID_PCM_S8: case AV_CODEC_ID_PCM_S16BE: case AV_CODEC_ID_PCM_S16LE: + case AV_CODEC_ID_PCM_S24BE: case AV_CODEC_ID_PCM_U16BE: case AV_CODEC_ID_PCM_U16LE: case AV_CODEC_ID_PCM_U8: @@ -544,6 +545,8 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) case AV_CODEC_ID_PCM_S16BE: case AV_CODEC_ID_PCM_S16LE: return rtp_send_samples(s1, pkt->data, size, 16 * st->codecpar->channels); + case AV_CODEC_ID_PCM_S24BE: + return rtp_send_samples(s1, pkt->data, size, 24 * st->codecpar->channels); case AV_CODEC_ID_ADPCM_G722: /* The actual sample size is half a byte per sample, but since the * stream clock rate is 8000 Hz while the sample rate is 16000 Hz, diff --git a/libavformat/sdp.c b/libavformat/sdp.c index 0242ca379c23e..e7149167a1404 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -584,6 +584,12 @@ static char *sdp_write_media_attributes(char *buff, int size, AVStream *st, int payload_type, p->sample_rate, p->channels); break; + case AV_CODEC_ID_PCM_S24BE: + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d L24/%d/%d\r\n", + payload_type, + p->sample_rate, p->channels); + break; case AV_CODEC_ID_PCM_MULAW: if (payload_type >= RTP_PT_PRIVATE) av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n", diff --git a/libavformat/version.h b/libavformat/version.h index 06d54834a97d6..4598d86ff12b9 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -33,7 +33,7 @@ // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 #define LIBAVFORMAT_VERSION_MINOR 0 -#define LIBAVFORMAT_VERSION_MICRO 101 +#define LIBAVFORMAT_VERSION_MICRO 102 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From 3dca4887aef4f1c2ab2f94a02342b3f50913522c Mon Sep 17 00:00:00 2001 From: Anton Schubert Date: Sun, 29 Oct 2017 16:10:34 +0100 Subject: [PATCH 0659/2557] dashenc: fix bitrate estimation with correct scaling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Anton Schubert Signed-off-by: Peter Große Signed-off-by: Michael Niedermayer --- libavformat/dashenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 04b0fd99e6787..e25a660fbe1c5 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -947,6 +947,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; + AVStream *st = s->streams[i]; char filename[1024] = "", full_path[1024], temp_path[1024]; int range_length, index_length = 0; @@ -1001,7 +1002,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) if (!os->bit_rate) { // calculate average bitrate of first segment - int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / (os->max_pts - os->start_pts); + int64_t bitrate = (int64_t) range_length * 8 / ((os->max_pts - os->start_pts) * av_q2d(st->time_base)); if (bitrate >= 0) { os->bit_rate = bitrate; snprintf(os->bandwidth_str, sizeof(os->bandwidth_str), From 44ede215b6623eb5e24bac013ea668366e2f258a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Gro=C3=9Fe?= Date: Sun, 29 Oct 2017 16:10:36 +0100 Subject: [PATCH 0660/2557] dashenc: set DASH related options for the subsequent matroska muxer when using webm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch is inspired by the ffmpeg webm_chunk muxer and fixes that all resulting tracks have the same track number. Signed-off-by: Peter Große Signed-off-by: Michael Niedermayer --- libavformat/dashenc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index e25a660fbe1c5..0ca7cf5aa3a20 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -778,6 +778,9 @@ static int dash_init(AVFormatContext *s) } else { av_dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000, 0); av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit + av_dict_set_int(&opts, "dash", 1, 0); + av_dict_set_int(&opts, "dash_track_number", i + 1, 0); + av_dict_set_int(&opts, "live", 1, 0); } if ((ret = avformat_write_header(ctx, &opts)) < 0) return ret; From 1443859a8d0dcffdc01f969f7cde61769aaca31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Gro=C3=9Fe?= Date: Thu, 26 Oct 2017 17:58:37 +0200 Subject: [PATCH 0661/2557] dashenc: don't write header data before the first packet arrives MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: 1b8ef01f04ab ("dashenc: add webm support") Signed-off-by: Peter Große Signed-off-by: Michael Niedermayer --- libavformat/dashenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 0ca7cf5aa3a20..23b2d3fed456a 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -782,7 +782,7 @@ static int dash_init(AVFormatContext *s) av_dict_set_int(&opts, "dash_track_number", i + 1, 0); av_dict_set_int(&opts, "live", 1, 0); } - if ((ret = avformat_write_header(ctx, &opts)) < 0) + if ((ret = avformat_init_output(ctx, &opts)) < 0) return ret; os->ctx_inited = 1; avio_flush(ctx->pb); From 2911dabd51dc61f594e43904f27f3afd01f3f835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Gro=C3=9Fe?= Date: Thu, 26 Oct 2017 18:17:31 +0200 Subject: [PATCH 0662/2557] dashenc: allow AdaptationSets to have different average frame rates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Große Signed-off-by: Michael Niedermayer --- libavformat/dashenc.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 23b2d3fed456a..c55106c11d73e 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -55,6 +55,8 @@ typedef struct AdaptationSet { char id[10]; enum AVMediaType media_type; AVDictionary *metadata; + AVRational min_frame_rate, max_frame_rate; + int ambiguous_frame_rate; } AdaptationSet; typedef struct OutputStream { @@ -97,8 +99,6 @@ typedef struct DASHContext { const char *single_file_name; const char *init_seg_name; const char *media_seg_name; - AVRational min_frame_rate, max_frame_rate; - int ambiguous_frame_rate; const char *utc_timing_url; } DASHContext; @@ -393,8 +393,8 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind avio_printf(out, "\t\tid, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); - if (as->media_type == AVMEDIA_TYPE_VIDEO && c->max_frame_rate.num && !c->ambiguous_frame_rate) - avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(c->min_frame_rate, c->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", c->max_frame_rate.num, c->max_frame_rate.den); + if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate) + avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", as->max_frame_rate.num, as->max_frame_rate.den); lang = av_dict_get(as->metadata, "language", NULL, 0); if (lang) avio_printf(out, " lang=\"%s\"", lang->value); @@ -677,7 +677,6 @@ static int dash_init(AVFormatContext *s) c->single_file = 1; if (c->single_file) c->use_template = 0; - c->ambiguous_frame_rate = 0; av_strlcpy(c->dirname, s->filename, sizeof(c->dirname)); ptr = strrchr(c->dirname, '/'); @@ -805,12 +804,12 @@ static int dash_init(AVFormatContext *s) if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { AVRational avg_frame_rate = s->streams[i]->avg_frame_rate; if (avg_frame_rate.num > 0) { - if (av_cmp_q(avg_frame_rate, c->min_frame_rate) < 0) - c->min_frame_rate = avg_frame_rate; - if (av_cmp_q(c->max_frame_rate, avg_frame_rate) < 0) - c->max_frame_rate = avg_frame_rate; + if (av_cmp_q(avg_frame_rate, as->min_frame_rate) < 0) + as->min_frame_rate = avg_frame_rate; + if (av_cmp_q(as->max_frame_rate, avg_frame_rate) < 0) + as->max_frame_rate = avg_frame_rate; } else { - c->ambiguous_frame_rate = 1; + as->ambiguous_frame_rate = 1; } c->has_video = 1; } From fe334712ddc633dba3774beb56579381a00d59bf Mon Sep 17 00:00:00 2001 From: Anton Schubert Date: Sun, 29 Oct 2017 16:10:35 +0100 Subject: [PATCH 0663/2557] dashenc: Don't output frameRates at both AS and Representation-level. Only output maxFrameRate at AS-level. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix conformance regarding section "3.2.4. Presence of Attributes and Element" of the "Guidelines for Implementation: DASH-IF Interoperability Points V4.1" (http://dashif.org/guidelines/) Signed-off-by: Anton Schubert Signed-off-by: Peter Große Signed-off-by: Michael Niedermayer --- libavformat/dashenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index c55106c11d73e..82381b67a9cbd 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -393,8 +393,8 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind avio_printf(out, "\t\tid, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); - if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate) - avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", as->max_frame_rate.num, as->max_frame_rate.den); + if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0) + avio_printf(out, " maxFrameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den); lang = av_dict_get(as->metadata, "language", NULL, 0); if (lang) avio_printf(out, " lang=\"%s\"", lang->value); From 3c838e6442bbe1afb7bf82942471342bcea87a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Gro=C3=9Fe?= Date: Thu, 26 Oct 2017 17:58:40 +0200 Subject: [PATCH 0664/2557] dashenc: copy stream frame rate to output stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Leads to setting of DefaultDuration in Matroska muxer based on frame rate instead of timebase. Fixes playback in Chrome. Signed-off-by: Peter Große Signed-off-by: Michael Niedermayer --- libavformat/dashenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 82381b67a9cbd..7813f4485a297 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -752,6 +752,7 @@ static int dash_init(AVFormatContext *s) avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar); st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; st->time_base = s->streams[i]->time_base; + st->avg_frame_rate = s->streams[i]->avg_frame_rate; ctx->avoid_negative_ts = s->avoid_negative_ts; ctx->flags = s->flags; From fe533628b9604e2f8e5179d5c5dd17c3cb764265 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 26 Oct 2017 00:02:56 +0200 Subject: [PATCH 0665/2557] avcodec/jpeglsdec: Check ilv for being a supported value Fixes: 1773/clusterfuzz-testcase-minimized-4832523987189760 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/jpeglsdec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/jpeglsdec.c b/libavcodec/jpeglsdec.c index 64505321affe3..cb2f89a88c3dd 100644 --- a/libavcodec/jpeglsdec.c +++ b/libavcodec/jpeglsdec.c @@ -443,6 +443,10 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near, avpriv_report_missing_feature(s->avctx, "Sample interleaved images"); ret = AVERROR_PATCHWELCOME; goto end; + } else { /* unknown interleaving */ + avpriv_report_missing_feature(s->avctx, "Unknown interleaved images"); + ret = AVERROR_PATCHWELCOME; + goto end; } if (s->xfrm && s->nb_components == 3) { From f80224ed19a4c012549fd460d529c7c04e68cf21 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 26 Oct 2017 00:02:57 +0200 Subject: [PATCH 0666/2557] avcodec/jpeglsdec: Check for end of bitstream in ls_decode_line() Fixes: 1773/clusterfuzz-testcase-minimized-4832523987189760 Fixes: Timeout Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/jpeglsdec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/jpeglsdec.c b/libavcodec/jpeglsdec.c index cb2f89a88c3dd..5308b744df1fd 100644 --- a/libavcodec/jpeglsdec.c +++ b/libavcodec/jpeglsdec.c @@ -233,6 +233,9 @@ static inline void ls_decode_line(JLSState *state, MJpegDecodeContext *s, while (x < w) { int err, pred; + if (get_bits_left(&s->gb) <= 0) + return; + /* compute gradients */ Ra = x ? R(dst, x - stride) : R(last, x); Rb = R(last, x); From bfb1a946255f9b12dccc6b12f5a865852f487a87 Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Fri, 27 Oct 2017 20:46:27 +0200 Subject: [PATCH 0667/2557] examples/avio_reading: return AVERROR_EOF at EOF. Signed-off-by: Nicolas George --- doc/examples/avio_reading.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/examples/avio_reading.c b/doc/examples/avio_reading.c index 02474e907af61..7860fd5e2fd7b 100644 --- a/doc/examples/avio_reading.c +++ b/doc/examples/avio_reading.c @@ -44,6 +44,8 @@ static int read_packet(void *opaque, uint8_t *buf, int buf_size) struct buffer_data *bd = (struct buffer_data *)opaque; buf_size = FFMIN(buf_size, bd->size); + if (!buf_size) + return AVERROR_EOF; printf("ptr:%p size:%zu\n", bd->ptr, bd->size); /* copy internal buffer data to buf */ From a606f27f4c610708fa96e35eed7b7537d3d8f712 Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Fri, 27 Oct 2017 20:46:28 +0200 Subject: [PATCH 0668/2557] lavf/avio: temporarily accept 0 as EOF. Print a warning to let applicatios fix their use. After a deprecation period, check with a low-level assert. Also make the constraint explicit in the doxygen comment. Signed-off-by: Nicolas George --- libavformat/avio.h | 2 ++ libavformat/aviobuf.c | 30 +++++++++++++++++++++--------- libavformat/version.h | 3 +++ 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/libavformat/avio.h b/libavformat/avio.h index 19ecd96eb77ab..76ff7cd81ea7a 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -452,6 +452,8 @@ void avio_free_directory_entry(AVIODirEntry **entry); * @param write_flag Set to 1 if the buffer should be writable, 0 otherwise. * @param opaque An opaque pointer to user-specific data. * @param read_packet A function for refilling the buffer, may be NULL. + * For stream protocols, must never return 0 but rather + * a proper AVERROR code. * @param write_packet A function for writing the buffer contents, may be NULL. * The function may not change the input buffers content. * @param seek A function for seeking to specified byte position, may be NULL. diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 3e9d774a1311d..bfd40f5097105 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -524,6 +524,24 @@ void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType typ s->last_time = time; } +static int read_packet_wrapper(AVIOContext *s, uint8_t *buf, int size) +{ + int ret; + + if (!s->read_packet) + return AVERROR_EOF; + ret = s->read_packet(s->opaque, buf, size); +#if FF_API_OLD_AVIO_EOF_0 + if (!ret && !s->max_packet_size) { + av_log(NULL, AV_LOG_WARNING, "Invalid return value 0 for stream protocol\n"); + ret = AVERROR_EOF; + } +#else + av_assert2(ret || s->max_packet_size); +#endif + return ret; +} + /* Input stream */ static void fill_buffer(AVIOContext *s) @@ -562,10 +580,7 @@ static void fill_buffer(AVIOContext *s) len = s->orig_buffer_size; } - if (s->read_packet) - len = s->read_packet(s->opaque, dst, len); - else - len = AVERROR_EOF; + len = read_packet_wrapper(s, dst, len); if (len == AVERROR_EOF) { /* do not modify buffer if EOF reached so that a seek back can be done without rereading data */ @@ -638,10 +653,7 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size) if (len == 0 || s->write_flag) { if((s->direct || size > s->buffer_size) && !s->update_checksum) { // bypass the buffer and read data directly into buf - if(s->read_packet) - len = s->read_packet(s->opaque, buf, size); - else - len = AVERROR_EOF; + len = read_packet_wrapper(s, buf, size); if (len == AVERROR_EOF) { /* do not modify buffer if EOF reached so that a seek back can be done without rereading data */ @@ -708,7 +720,7 @@ int avio_read_partial(AVIOContext *s, unsigned char *buf, int size) return -1; if (s->read_packet && s->write_flag) { - len = s->read_packet(s->opaque, buf, size); + len = read_packet_wrapper(s, buf, size); if (len > 0) s->pos += len; return len; diff --git a/libavformat/version.h b/libavformat/version.h index 4598d86ff12b9..2db03232e41a9 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -79,6 +79,9 @@ #ifndef FF_API_FORMAT_GET_SET #define FF_API_FORMAT_GET_SET (LIBAVFORMAT_VERSION_MAJOR < 59) #endif +#ifndef FF_API_OLD_AVIO_EOF_0 +#define FF_API_OLD_AVIO_EOF_0 (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif #ifndef FF_API_R_FRAME_RATE From 158a79c31d55d0b82ff3f514c586f5be033ad0c2 Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Fri, 27 Oct 2017 20:46:29 +0200 Subject: [PATCH 0669/2557] lavf/aviobuf: return EINVAL when reading from a write-only context. Signed-off-by: Nicolas George --- libavformat/aviobuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index bfd40f5097105..3b4c8439d6ce1 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -529,7 +529,7 @@ static int read_packet_wrapper(AVIOContext *s, uint8_t *buf, int size) int ret; if (!s->read_packet) - return AVERROR_EOF; + return AVERROR(EINVAL); ret = s->read_packet(s->opaque, buf, size); #if FF_API_OLD_AVIO_EOF_0 if (!ret && !s->max_packet_size) { From ddd0b19169dc3c0dfcdbaf246147a64c87b22c24 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 29 Oct 2017 14:10:56 -0300 Subject: [PATCH 0670/2557] ffprobe: remove usage of deprecated getter functions Signed-off-by: James Almer --- fftools/ffprobe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index ab36f8bc42652..07ca842efa319 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2792,7 +2792,7 @@ static int show_format(WriterContext *w, InputFile *ifile) else print_str_opt("size", "N/A"); if (fmt_ctx->bit_rate > 0) print_val ("bit_rate", fmt_ctx->bit_rate, unit_bit_per_second_str); else print_str_opt("bit_rate", "N/A"); - print_int("probe_score", av_format_get_probe_score(fmt_ctx)); + print_int("probe_score", fmt_ctx->probe_score); if (do_show_format_tags) ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS); From 5cc5130c813fd89e5a8b998e504908ef36bed0f1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 29 Oct 2017 14:12:10 -0300 Subject: [PATCH 0671/2557] ffmpeg: remove usage of deprecated getter functions Signed-off-by: James Almer --- fftools/ffmpeg_opt.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index f4ff1605f0789..ca6f10d5ca6aa 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1025,23 +1025,19 @@ static int open_input_file(OptionsContext *o, const char *filename) MATCH_PER_TYPE_OPT(codec_names, str, subtitle_codec_name, ic, "s"); MATCH_PER_TYPE_OPT(codec_names, str, data_codec_name, ic, "d"); - ic->video_codec_id = video_codec_name ? - find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0)->id : AV_CODEC_ID_NONE; - ic->audio_codec_id = audio_codec_name ? - find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0)->id : AV_CODEC_ID_NONE; - ic->subtitle_codec_id= subtitle_codec_name ? - find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0)->id : AV_CODEC_ID_NONE; - ic->data_codec_id = data_codec_name ? - find_codec_or_die(data_codec_name, AVMEDIA_TYPE_DATA, 0)->id : AV_CODEC_ID_NONE; - if (video_codec_name) - av_format_set_video_codec (ic, find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0)); + ic->video_codec = find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0); if (audio_codec_name) - av_format_set_audio_codec (ic, find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0)); + ic->audio_codec = find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0); if (subtitle_codec_name) - av_format_set_subtitle_codec(ic, find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0)); + ic->subtitle_codec = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0); if (data_codec_name) - av_format_set_data_codec(ic, find_codec_or_die(data_codec_name, AVMEDIA_TYPE_DATA, 0)); + ic->data_codec = find_codec_or_die(data_codec_name , AVMEDIA_TYPE_DATA , 0); + + ic->video_codec_id = video_codec_name ? ic->video_codec->id : AV_CODEC_ID_NONE; + ic->audio_codec_id = audio_codec_name ? ic->audio_codec->id : AV_CODEC_ID_NONE; + ic->subtitle_codec_id = subtitle_codec_name ? ic->subtitle_codec->id : AV_CODEC_ID_NONE; + ic->data_codec_id = data_codec_name ? ic->data_codec->id : AV_CODEC_ID_NONE; ic->flags |= AVFMT_FLAG_NONBLOCK; if (o->bitexact) From 2245476e5c451552f8f32a4a881f6b4968898a47 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 29 Oct 2017 14:40:38 -0300 Subject: [PATCH 0672/2557] avdevice: remove usage of deprecated setter and getter functions Signed-off-by: James Almer --- libavdevice/avdevice.c | 4 ++-- libavdevice/decklink_dec.cpp | 2 +- libavdevice/libndi_newtek_dec.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c index 01c46924d10a0..72e1b67887f9b 100644 --- a/libavdevice/avdevice.c +++ b/libavdevice/avdevice.c @@ -135,9 +135,9 @@ int avdevice_app_to_dev_control_message(struct AVFormatContext *s, enum AVAppToD int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToAppMessageType type, void *data, size_t data_size) { - if (!av_format_get_control_message_cb(s)) + if (!s->control_message_cb) return AVERROR(ENOSYS); - return av_format_get_control_message_cb(s)(s, type, data, data_size); + return s->control_message_cb(s, type, data, data_size); } int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s, diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index b4b9e02cecc21..e786dd85dc8fb 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -959,7 +959,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) st->time_base.den = ctx->bmd_tb_den; st->time_base.num = ctx->bmd_tb_num; - av_stream_set_r_frame_rate(st, av_make_q(st->time_base.den, st->time_base.num)); + st->r_frame_rate = av_make_q(st->time_base.den, st->time_base.num)); switch((BMDPixelFormat)cctx->raw_format) { case bmdFormat8BitYUV: diff --git a/libavdevice/libndi_newtek_dec.c b/libavdevice/libndi_newtek_dec.c index 8cbcd9a1d2058..5bbaa3978679c 100644 --- a/libavdevice/libndi_newtek_dec.c +++ b/libavdevice/libndi_newtek_dec.c @@ -189,7 +189,7 @@ static int ndi_create_video_stream(AVFormatContext *avctx, NDIlib_video_frame_t } st->time_base = NDI_TIME_BASE_Q; - av_stream_set_r_frame_rate(st, av_make_q(v->frame_rate_N, v->frame_rate_D)); + st->r_frame_rate = av_make_q(v->frame_rate_N, v->frame_rate_D)); tmp = av_mul_q(av_d2q(v->picture_aspect_ratio, INT_MAX), (AVRational){v->yres, v->xres}); av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den, tmp.num, tmp.den, 1000); From 59ceee5896aff8d6af8fca89f5c8eb3c82007d8d Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 29 Oct 2017 21:22:53 +0100 Subject: [PATCH 0673/2557] fate: Fix some of the fitsdec tests on big-endian. --- tests/fate/fits.mak | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/fate/fits.mak b/tests/fate/fits.mak index 3d58f98807007..0335a7b508240 100644 --- a/tests/fate/fits.mak +++ b/tests/fate/fits.mak @@ -18,16 +18,16 @@ tests/data/lena%.fits: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data -y $(TARGET_PATH)/$(@) 2>/dev/null FATE_FITS_DEC-$(call DEMDEC, FITS, FITS) += fate-fitsdec-ext_data_min_max -fate-fitsdec-ext_data_min_max: CMD = framecrc -i $(TARGET_SAMPLES)/fits/x0cj010ct_d0h.fit -pix_fmt gray16 +fate-fitsdec-ext_data_min_max: CMD = framecrc -i $(TARGET_SAMPLES)/fits/x0cj010ct_d0h.fit -pix_fmt gray16le FATE_FITS_DEC-$(call DEMDEC, FITS, FITS) += fate-fitsdec-blank_bitpix32 -fate-fitsdec-blank_bitpix32: CMD = framecrc -blank_value 65535 -i $(TARGET_SAMPLES)/fits/file008.fits -pix_fmt gray16 +fate-fitsdec-blank_bitpix32: CMD = framecrc -blank_value 65535 -i $(TARGET_SAMPLES)/fits/file008.fits -pix_fmt gray16le FATE_FITS_DEC-$(call DEMDEC, FITS, FITS) += fate-fitsdec-bitpix-32 -fate-fitsdec-bitpix-32: CMD = framecrc -i $(TARGET_SAMPLES)/fits/tst0005.fits -pix_fmt gray16 +fate-fitsdec-bitpix-32: CMD = framecrc -i $(TARGET_SAMPLES)/fits/tst0005.fits -pix_fmt gray16le FATE_FITS_DEC-$(call DEMDEC, FITS, FITS) += fate-fitsdec-bitpix-64 -fate-fitsdec-bitpix-64: CMD = framecrc -i $(TARGET_SAMPLES)/fits/tst0006.fits -pix_fmt gray16 +fate-fitsdec-bitpix-64: CMD = framecrc -i $(TARGET_SAMPLES)/fits/tst0006.fits -pix_fmt gray16le FATE_FITS_DEC-$(call ALLYES, GIF_DEMUXER FITS_DEMUXER GIF_DECODER FITS_DECODER FITS_ENCODER FITS_MUXER) += fate-fitsdec-multi fate-fitsdec-multi: tests/data/fits-multi.fits From 4ccc1ef2a3b1a22d849861423df830e110c9a4ab Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 29 Oct 2017 22:01:40 +0100 Subject: [PATCH 0674/2557] fate: Add bitexact flag to the invalid-elst test. Fixes fate-mov-invalid-elst-entry-count on a ppc system. --- tests/fate/mov.mak | 2 +- tests/ref/fate/mov-invalid-elst-entry-count | 86 ++++++++++----------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 604703e254473..6815e4feca7c3 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -45,7 +45,7 @@ fate-mov-2elist-elist1-ends-bframe: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/mov- fate-mov-440hz-10ms: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/440hz-10ms.m4a # Makes sure that we handle invalid edit list entry count correctly. -fate-mov-invalid-elst-entry-count: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/invalid_elst_entry_count.mov +fate-mov-invalid-elst-entry-count: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/mov/invalid_elst_entry_count.mov fate-mov-aac-2048-priming: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_packets -print_format compact $(TARGET_SAMPLES)/mov/aac-2048-priming.mov diff --git a/tests/ref/fate/mov-invalid-elst-entry-count b/tests/ref/fate/mov-invalid-elst-entry-count index 13b575816b4f1..ac1e02ea0406e 100644 --- a/tests/ref/fate/mov-invalid-elst-entry-count +++ b/tests/ref/fate/mov-invalid-elst-entry-count @@ -8,50 +8,50 @@ #sar 0: 1/1 #stream#, dts, pts, duration, size, hash 0, 0, 0, 1, 460800, 549730883a0b56e6accaf021903daecf -0, 1, 1, 1, 460800, 783389b4342d4be925fc5244791e760a -0, 2, 2, 1, 460800, 8384af6426d94a2077930c93013e09ad -0, 3, 3, 1, 460800, 9380a1d9ecacf5b3105383c1c8083188 -0, 4, 4, 1, 460800, eb28174acfceb868b9058757bed049c5 -0, 5, 5, 1, 460800, 9732bd4a58884dbf2be48d819433130f +0, 1, 1, 1, 460800, d5fc844d512a1decb0814b8692914d60 +0, 2, 2, 1, 460800, 69753185911f99aa38bd9d9ee0ff24f7 +0, 3, 3, 1, 460800, 2a985178c8b24e97708c6d33142f18a9 +0, 4, 4, 1, 460800, a23818e43bdf4ee77291e0f74051d0bf +0, 5, 5, 1, 460800, f2c927b11350b9822065bec5f06b65d9 0, 6, 6, 1, 460800, 0c553fb530cf042eb84f5b13817a96a6 -0, 7, 7, 1, 460800, 621f02aded5e35fa1f373afd3ed283bd -0, 8, 8, 1, 460800, c76167c6bda91f657708c88252ea315d -0, 9, 9, 1, 460800, 872df2d8c522e2440ddd04bca7dce497 -0, 10, 10, 1, 460800, 6ee9154e48c5132ad4ba122b255bd2bb -0, 11, 11, 1, 460800, 362e61629795702ebe9183ce3786d7f2 +0, 7, 7, 1, 460800, a2be429b570ce30a7471b901f2ea5bcc +0, 8, 8, 1, 460800, b4f4a3b1988404b35c57688755beb8b9 +0, 9, 9, 1, 460800, 2778b931d5e1570e1b809a87b1c45491 +0, 10, 10, 1, 460800, 4eb341ebf32006d8bce13f1d132d84b2 +0, 11, 11, 1, 460800, c39a34287300ee52547752198a2222fc 0, 12, 12, 1, 460800, f3ec59e6fc4e3c2e75f42bef34ca73b5 -0, 13, 13, 1, 460800, 68d9caea8697736dd716cba43b614919 -0, 14, 14, 1, 460800, 4a4efb0201a64236db4330725758c139 -0, 15, 15, 1, 460800, f32f8997dcdd87ad910dea886a0de17d -0, 16, 16, 1, 460800, 51a8549d7b4aaacaf6050bc07a82b440 -0, 17, 17, 1, 460800, 5145aa05bbb0c3faab40fc8fa233af1d -0, 18, 18, 1, 460800, bbfcbe3c9600b2a0f413057d7959e9e7 -0, 19, 19, 1, 460800, 02cfd4a350fa274e12fce8352001bf21 -0, 20, 20, 1, 460800, 20dd372da9e656add433f31e3e9c1fb8 -0, 21, 21, 1, 460800, 3b885593f8b42676ce40c329a63f62bf -0, 22, 22, 1, 460800, c38b453b56c3ea14f7d8691d83752486 -0, 23, 23, 1, 460800, 79643132988dabc9dc1ba3af0aeaebc5 +0, 13, 13, 1, 460800, 3f0e6116a94fefe890b79d1e94c156c6 +0, 14, 14, 1, 460800, 0a8a597c0806818112bf8351f53d350a +0, 15, 15, 1, 460800, ab5c10023712ea21d595f5f856f53c66 +0, 16, 16, 1, 460800, d4e218051ef32e68e3df58c8c3d6a1ab +0, 17, 17, 1, 460800, 24082fa9a277123a65398a36cb1b06af +0, 18, 18, 1, 460800, 4c6da38c984496fb514d5e4d8ebb13f8 +0, 19, 19, 1, 460800, 5354435f662e80a47e1460d3ba020133 +0, 20, 20, 1, 460800, 6854beaaf90ad9f055af80fc75e802ae +0, 21, 21, 1, 460800, cb40c57f9b61788fb4abe674b585142f +0, 22, 22, 1, 460800, 8f42c6553c33dc049f6fb5e71f631125 +0, 23, 23, 1, 460800, d393b3efa7921caab3504044551bf6c3 0, 24, 24, 1, 460800, 60a099be31244b2f69ca6107cdbd7e06 -0, 25, 25, 1, 460800, 1de6ff4e0aa81216e4b7b1c8e74fb143 -0, 26, 26, 1, 460800, 5223a81e6964c28cf42593f259397aa1 -0, 27, 27, 1, 460800, 2dfcf01c86aa712cd6f1c7656eeb17db -0, 28, 28, 1, 460800, 8c86ee0f02fabccaed8d8fc8babd031e -0, 29, 29, 1, 460800, b3ea1983f7efeec11306445d9ae5d477 -0, 30, 30, 1, 460800, 86a4cc9fa7db5ff5ca2be69ad191179f -0, 31, 31, 1, 460800, 8194715afe23ae34a019797a53a6ee2c -0, 32, 32, 1, 460800, 447a153f1c6bb703eff62edfd14e08e0 -0, 33, 33, 1, 460800, 092257082789b898dbb14d1f19e79347 -0, 34, 34, 1, 460800, d6320d204a119cfeef5645a4118bc600 -0, 35, 35, 1, 460800, 2ee710deae4bb0d156528797ad1c4981 +0, 25, 25, 1, 460800, 05e542c105dc3f6f810d815fbf022afe +0, 26, 26, 1, 460800, bf478f55694eda43942a343e0b70eb19 +0, 27, 27, 1, 460800, b1012ea5ff7232da20d2c7f242540bda +0, 28, 28, 1, 460800, 936cdd0fd147f9c3ad4e82bed77a6d2c +0, 29, 29, 1, 460800, 20baafde1ab281444d8cbf58995344c2 +0, 30, 30, 1, 460800, b0bb3647ec88d1a862e2e92c32d95b65 +0, 31, 31, 1, 460800, c86d78b06c281a8c3b63b4d7beeb3ddd +0, 32, 32, 1, 460800, 4d699157c55ec3439390c6ff400655b4 +0, 33, 33, 1, 460800, 3327b0e09944dc13f0f2124cdfad86e9 +0, 34, 34, 1, 460800, 5db56bb14cd478f70bb5244781f1382d +0, 35, 35, 1, 460800, cb8564d7a763444cc85512df3f7f10db 0, 36, 36, 1, 460800, 1256eac030985c04c4501ad5a72e9d66 -0, 37, 37, 1, 460800, f16ad8c1aa572be7666c7907ce4aebbc -0, 38, 38, 1, 460800, 865088cbd47d0151b62a45d5426c8216 -0, 39, 39, 1, 460800, 26c78ca43d93c6da153f3dea5d945e0e -0, 40, 40, 1, 460800, d775d6705c965401ccc143d5ae432938 -0, 41, 41, 1, 460800, f9837d514753c59e6776452d9043524f -0, 42, 42, 1, 460800, 8463f5172914828abcc770f888bfd183 -0, 43, 43, 1, 460800, 3108557748cfb7965b33b16b35359de0 -0, 44, 44, 1, 460800, 477d596944e028dd72c207bb6e6b22de -0, 45, 45, 1, 460800, 69e4ffbd600c8d8bc070d7d7324ee2b1 -0, 46, 46, 1, 460800, 2211c57bc9ec1788217002900f9102b1 -0, 47, 47, 1, 460800, bcfb5f0a7f88da3ec8c6b447ed4b67eb +0, 37, 37, 1, 460800, 20efdff9919faac5528cb576a21d6c2a +0, 38, 38, 1, 460800, 28420714ad1008772ce8100d917e2226 +0, 39, 39, 1, 460800, 6c18dad0a470e8c0d62413b549e0ae2c +0, 40, 40, 1, 460800, 3d8b9352e5d21697733e5fb5fdd55d58 +0, 41, 41, 1, 460800, 025e32ced915530eb814d399a8b28a20 +0, 42, 42, 1, 460800, cc880a64b66f158595521182a1db8a36 +0, 43, 43, 1, 460800, 322a2349a08e3b3cd18562050287c133 +0, 44, 44, 1, 460800, c19c16a382449594f1dec7a77a4e264e +0, 45, 45, 1, 460800, 0d424b26031fa1db52fbd80c100e27a4 +0, 46, 46, 1, 460800, cef6158cd43beee0aea777982613e493 +0, 47, 47, 1, 460800, eb64a091a54ebb1077c667e1b33add2a From d3f1b0d3d87f782d6a89a73c57e8be992d4785da Mon Sep 17 00:00:00 2001 From: Lukas Stabe Date: Sun, 29 Oct 2017 11:35:57 +0100 Subject: [PATCH 0675/2557] movenc: add m4b to ipod format extensions m4b is commonly used as extension for m4a audiobook files. The format is exactly the same. The only thing that differs is the extension. Signed-off-by: Michael Niedermayer --- libavformat/movenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index a34987a7dc99c..a920eb7c8fd6c 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -6664,7 +6664,7 @@ AVOutputFormat ff_ipod_muxer = { .name = "ipod", .long_name = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"), .mime_type = "video/mp4", - .extensions = "m4v,m4a", + .extensions = "m4v,m4a,m4b", .priv_data_size = sizeof(MOVMuxContext), .audio_codec = AV_CODEC_ID_AAC, .video_codec = AV_CODEC_ID_H264, From 59ad504696958fbd9db7b478b4b7e0a2b436b7f2 Mon Sep 17 00:00:00 2001 From: Jonas Licht Date: Sun, 29 Oct 2017 12:11:39 +0100 Subject: [PATCH 0676/2557] libavformat/mov.c: use calculated dts offset when seeking in streams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subtract the calculated dts offset from the requested timestamp before seeking. This fixes an error "Error while filtering: Operation not permitted" observed with a short file which contains only one key frame and starts with negative timestamps. Then, av_index_search_timestamp() returns a valid negative timestamp, but mov_seek_stream bails out with AVERROR_INVALIDDATA. Fixes ticket #6139. Signed-off-by: Jonas Licht Signed-off-by: Peter Große Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 6 ++++-- tests/ref/seek/extra-mp4 | 16 ++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 209b7470a9a72..60f0228e2dfbc 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -6901,10 +6901,12 @@ static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags) { MOVStreamContext *sc = st->priv_data; - int sample, time_sample; + int sample, time_sample, ret; unsigned int i; - int ret = mov_seek_fragment(s, st, timestamp); + timestamp -= sc->time_offset; + + ret = mov_seek_fragment(s, st, timestamp); if (ret < 0) return ret; diff --git a/tests/ref/seek/extra-mp4 b/tests/ref/seek/extra-mp4 index c25544c0954b9..c17ce4003c68a 100644 --- a/tests/ref/seek/extra-mp4 +++ b/tests/ref/seek/extra-mp4 @@ -28,10 +28,10 @@ ret: 0 st: 0 flags:0 dts: 50.633333 pts: 50.733333 pos:5926157 size: 13 ret: 0 st: 0 flags:0 dts: 50.666667 pts: 50.666667 pos:5927464 size: 150 ret: 0 st: 0 flags:0 dts: 50.700000 pts: 50.700000 pos:5927614 size: 176 ret: 0 st:-1 flags:1 ts: 153.470835 -ret: 0 st: 0 flags:1 dts: 153.466667 pts: 153.500000 pos:15867700 size: 96169 -ret: 0 st: 0 flags:0 dts: 153.500000 pts: 153.533333 pos:15963869 size: 785 -ret: 0 st: 0 flags:0 dts: 153.533333 pts: 153.633333 pos:15964654 size: 3135 -ret: 0 st: 0 flags:0 dts: 153.566667 pts: 153.566667 pos:15967789 size: 859 +ret: 0 st: 0 flags:1 dts: 151.966667 pts: 152.000000 pos:15705355 size:146924 +ret: 0 st: 0 flags:0 dts: 152.000000 pts: 152.100000 pos:15852279 size: 1355 +ret: 0 st: 0 flags:0 dts: 152.033333 pts: 152.033333 pos:15853634 size: 211 +ret: 0 st: 0 flags:0 dts: 152.066667 pts: 152.066667 pos:15853845 size: 217 ret: 0 st: 0 flags:0 ts: 76.365000 ret: 0 st: 0 flags:1 dts: 77.833333 pts: 77.866667 pos:8659657 size: 41182 ret: 0 st: 0 flags:0 dts: 77.866667 pts: 77.966667 pos:8700839 size: 4197 @@ -83,10 +83,10 @@ ret: 0 st: 0 flags:0 dts: 101.333333 pts: 101.433333 pos:11049548 size: ret: 0 st: 0 flags:0 dts: 101.366667 pts: 101.366667 pos:11053072 size: 562 ret: 0 st: 0 flags:0 dts: 101.400000 pts: 101.400000 pos:11053634 size: 599 ret: 0 st:-1 flags:0 ts: 25.306672 -ret: 0 st: 0 flags:1 dts: 27.400000 pts: 27.433333 pos:2674605 size:127383 -ret: 0 st: 0 flags:0 dts: 27.433333 pts: 27.466667 pos:2801988 size: 68 -ret: 0 st: 0 flags:0 dts: 27.466667 pts: 27.500000 pos:2802268 size: 1754 -ret: 0 st: 0 flags:0 dts: 27.500000 pts: 27.533333 pos:2804022 size: 4071 +ret: 0 st: 0 flags:1 dts: 25.300000 pts: 25.333333 pos:2607246 size: 40273 +ret: 0 st: 0 flags:0 dts: 25.333333 pts: 25.433333 pos:2647519 size: 2959 +ret: 0 st: 0 flags:0 dts: 25.366667 pts: 25.366667 pos:2650478 size: 197 +ret: 0 st: 0 flags:0 dts: 25.400000 pts: 25.400000 pos:2650675 size: 230 ret: 0 st:-1 flags:1 ts: 128.200839 ret: 0 st: 0 flags:1 dts: 127.833333 pts: 127.866667 pos:13514072 size: 67382 ret: 0 st: 0 flags:0 dts: 127.866667 pts: 127.966667 pos:13581454 size: 2936 From 195dd5c59c89b125b89078c736ae107bcaf23b37 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 13 Oct 2017 18:59:15 +0200 Subject: [PATCH 0677/2557] lavc/avrndec: remove AV_CODEC_CAP_DR1, as it's broken In the is_mjpeg case, the user's get_buffer2 callback is not called, thus completely breaking the API. Signed-off-by: James Almer --- libavcodec/avrndec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/avrndec.c b/libavcodec/avrndec.c index c37f99661b5dc..104ff2d9048ee 100644 --- a/libavcodec/avrndec.c +++ b/libavcodec/avrndec.c @@ -168,7 +168,6 @@ AVCodec ff_avrn_decoder = { .init = init, .close = end, .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, .max_lowres = 3, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; From 4776c61424fa32394e251e9769e1ad2c2fa55598 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 13 Oct 2017 18:59:16 +0200 Subject: [PATCH 0678/2557] decode: avoid leaks on failure in ff_get_buffer() If the get_buffer() call fails, the frame might have some side data already set. Make sure it gets freed. Merges Libav commit de77671438c24ffea93398c8dc885d4dd04477de. Signed-off-by: James Almer --- libavcodec/decode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 15fc82ad39a50..86fe5aef52a9c 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1598,6 +1598,9 @@ static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) frame->height = avctx->height; } + if (ret < 0) + av_frame_unref(frame); + return ret; } From 783535a4cd2657c08fb21e149da619262f8d9719 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 29 Oct 2017 22:21:46 -0300 Subject: [PATCH 0679/2557] x86/bswapdsp: add missing preprocessor wrappers for AVX2 functions Fixes build with old nasm/yasm. Signed-off-by: James Almer --- libavcodec/x86/bswapdsp.asm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/x86/bswapdsp.asm b/libavcodec/x86/bswapdsp.asm index 219d172481160..213ffbde07fc0 100644 --- a/libavcodec/x86/bswapdsp.asm +++ b/libavcodec/x86/bswapdsp.asm @@ -157,5 +157,7 @@ BSWAP32_BUF INIT_XMM ssse3 BSWAP32_BUF +%if HAVE_AVX2_EXTERNAL INIT_YMM avx2 BSWAP32_BUF +%endif From 5c819f433e85cf4c19823f17beb1092012e95b1d Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 30 Oct 2017 11:47:03 -0300 Subject: [PATCH 0680/2557] avdevice/decklink_dec: remove extra bracket Fixes compilation broken in 2245476e5c451552f8f32a4a881f6b4968898a47 Fixes ticket #6791 Signed-off-by: James Almer --- libavdevice/decklink_dec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index e786dd85dc8fb..191547ff10439 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -959,7 +959,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) st->time_base.den = ctx->bmd_tb_den; st->time_base.num = ctx->bmd_tb_num; - st->r_frame_rate = av_make_q(st->time_base.den, st->time_base.num)); + st->r_frame_rate = av_make_q(st->time_base.den, st->time_base.num); switch((BMDPixelFormat)cctx->raw_format) { case bmdFormat8BitYUV: From da71351dd36a4f91bc4ea8129cffc5a858b8d686 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 30 Oct 2017 11:48:14 -0300 Subject: [PATCH 0681/2557] avdevice/libndi_newtek_dec: remove extra bracket Fixes compilation broken in 2245476e5c451552f8f32a4a881f6b4968898a47 Signed-off-by: James Almer --- libavdevice/libndi_newtek_dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/libndi_newtek_dec.c b/libavdevice/libndi_newtek_dec.c index 5bbaa3978679c..2f14f4b03fd77 100644 --- a/libavdevice/libndi_newtek_dec.c +++ b/libavdevice/libndi_newtek_dec.c @@ -189,7 +189,7 @@ static int ndi_create_video_stream(AVFormatContext *avctx, NDIlib_video_frame_t } st->time_base = NDI_TIME_BASE_Q; - st->r_frame_rate = av_make_q(v->frame_rate_N, v->frame_rate_D)); + st->r_frame_rate = av_make_q(v->frame_rate_N, v->frame_rate_D); tmp = av_mul_q(av_d2q(v->picture_aspect_ratio, INT_MAX), (AVRational){v->yres, v->xres}); av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den, tmp.num, tmp.den, 1000); From 39e9a7a80fd30d11f04031a141cf0db20be4953f Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 29 Oct 2017 12:42:18 -0300 Subject: [PATCH 0682/2557] avcodec/avcodec.h: remove doxy from the old bsf API functions Make it clear that these are deprecated and the new API should be used instead. As a side effect, this slightly reduces differences with libav. Reviewed-by: Derek Buitenhuis Signed-off-by: James Almer --- libavcodec/avcodec.h | 70 +++++++++----------------------------------- 1 file changed, 14 insertions(+), 56 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index ee7834c8a2935..c4134424f0728 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -5407,81 +5407,39 @@ typedef struct AVBitStreamFilter { #if FF_API_OLD_BSF /** - * Register a bitstream filter. - * - * The filter will be accessible to the application code through - * av_bitstream_filter_next() or can be directly initialized with - * av_bitstream_filter_init(). - * - * @see avcodec_register_all() + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use the new bitstream filtering API (using AVBSFContext). */ attribute_deprecated void av_register_bitstream_filter(AVBitStreamFilter *bsf); - /** - * Create and initialize a bitstream filter context given a bitstream - * filter name. - * - * The returned context must be freed with av_bitstream_filter_close(). - * - * @param name the name of the bitstream filter - * @return a bitstream filter context if a matching filter was found - * and successfully initialized, NULL otherwise + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use av_bsf_get_by_name(), av_bsf_alloc(), and av_bsf_init() + * from the new bitstream filtering API (using AVBSFContext). */ attribute_deprecated AVBitStreamFilterContext *av_bitstream_filter_init(const char *name); - /** - * Filter bitstream. - * - * This function filters the buffer buf with size buf_size, and places the - * filtered buffer in the buffer pointed to by poutbuf. - * - * The output buffer must be freed by the caller. - * - * @param bsfc bitstream filter context created by av_bitstream_filter_init() - * @param avctx AVCodecContext accessed by the filter, may be NULL. - * If specified, this must point to the encoder context of the - * output stream the packet is sent to. - * @param args arguments which specify the filter configuration, may be NULL - * @param poutbuf pointer which is updated to point to the filtered buffer - * @param poutbuf_size pointer which is updated to the filtered buffer size in bytes - * @param buf buffer containing the data to filter - * @param buf_size size in bytes of buf - * @param keyframe set to non-zero if the buffer to filter corresponds to a key-frame packet data - * @return >= 0 in case of success, or a negative error code in case of failure - * - * If the return value is positive, an output buffer is allocated and - * is available in *poutbuf, and is distinct from the input buffer. - * - * If the return value is 0, the output buffer is not allocated and - * should be considered identical to the input buffer, or in case - * *poutbuf was set it points to the input buffer (not necessarily to - * its starting address). A special case is if *poutbuf was set to NULL and - * *poutbuf_size was set to 0, which indicates the packet should be dropped. + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use av_bsf_send_packet() and av_bsf_receive_packet() from the + * new bitstream filtering API (using AVBSFContext). */ attribute_deprecated int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size, int keyframe); - /** - * Release bitstream filter context. - * - * @param bsf the bitstream filter context created with - * av_bitstream_filter_init(), can be NULL + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use av_bsf_free() from the new bitstream filtering API (using + * AVBSFContext). */ attribute_deprecated void av_bitstream_filter_close(AVBitStreamFilterContext *bsf); - /** - * If f is NULL, return the first registered bitstream filter, - * if f is non-NULL, return the next registered bitstream filter - * after f, or NULL if f is the last one. - * - * This function can be used to iterate over all registered bitstream - * filters. + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use av_bsf_next() from the new bitstream filtering API (using + * AVBSFContext). */ attribute_deprecated const AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f); From 67c72f08a4707c18a67a4734660e3a23cc9488b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 30 Oct 2017 11:39:53 +0200 Subject: [PATCH 0683/2557] configure: Stop using dlltool to create an import library MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There shouldn't be any functional difference between the import library created by dlltool and the one produced by the linker itself. Keep installing it with both names though, for compatibility with users that expect both to exist. The dlltool step was added in ec10a9ab4; prior to that, a MSVC compatible import library was generated using lib.exe. After that commit, there was no functional difference between the two import libraries (and since MSVC 2012, link.exe works just fine with the GNU binutils generated one). Signed-off-by: Martin Storsjö --- configure | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/configure b/configure index ac7b40feba0bb..5981223e3172e 100755 --- a/configure +++ b/configure @@ -3892,10 +3892,6 @@ case $target_os in ;; mingw32*|mingw64*) target_os=mingw32 - LIBTARGET=i386 - if enabled x86_64; then - LIBTARGET="i386:x86-64" - fi if enabled shared; then # Cannot build both shared and static libs when using dllexport. disable static @@ -3907,7 +3903,7 @@ case $target_os in SLIBSUF=".dll" SLIBNAME_WITH_VERSION='$(SLIBPREF)$(NAME)-$(LIBVERSION)$(SLIBSUF)' SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(NAME)-$(LIBMAJOR)$(SLIBSUF)' - SLIB_EXTRA_CMD=-'$(DLLTOOL) -m $(LIBTARGET) -d $$(@:$(SLIBSUF)=.def) -l $(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib) -D $(SLIBNAME_WITH_MAJOR)' + SLIB_EXTRA_CMD='cp $(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a) $(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib)' SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)' SLIB_INSTALL_LINKS= SLIB_INSTALL_EXTRA_SHLIB='$(SLIBNAME:$(SLIBSUF)=.lib)' @@ -3915,7 +3911,6 @@ case $target_os in SLIB_CREATE_DEF_CMD='ARCH="$(ARCH)" AR="$(AR_CMD)" NM="$(NM_CMD)" $(SRC_PATH)/compat/windows/makedef $(SUBDIR)lib$(NAME).ver $(OBJS) > $$(@:$(SLIBSUF)=.def)' SHFLAGS='-shared -Wl,--out-implib,$(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a) -Wl,--enable-auto-image-base $$(@:$(SLIBSUF)=.def)' enabled x86_64 && objformat="win64" || objformat="win32" - dlltool="${cross_prefix}dlltool" ranlib=: enable dos_paths ;; @@ -5260,7 +5255,6 @@ X86ASM_O=$X86ASM_O LD_O=$LD_O LD_LIB=$LD_LIB LD_PATH=$LD_PATH -DLLTOOL=$dlltool LDFLAGS=$LDFLAGS LDEXEFLAGS=$LDEXEFLAGS LDSOFLAGS=$LDSOFLAGS @@ -5307,7 +5301,6 @@ LIB_INSTALL_EXTRA_CMD=$LIB_INSTALL_EXTRA_CMD EXTRALIBS=$extralibs COMPAT_OBJS=$compat_objs INSTALL=install -LIBTARGET=${LIBTARGET} SLIBNAME=${SLIBNAME} SLIBNAME_WITH_VERSION=${SLIBNAME_WITH_VERSION} SLIBNAME_WITH_MAJOR=${SLIBNAME_WITH_MAJOR} From f1251a6b9ccaac8a38d24398bbff156bf786717c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 30 Oct 2017 04:08:17 +0100 Subject: [PATCH 0684/2557] ffmpeg: Fix stored encoder metadata with -bitexact Signed-off-by: Michael Niedermayer --- fftools/ffmpeg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index cabc6864e7e63..ade8df6abc54e 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3120,7 +3120,7 @@ static void set_encoder_id(OutputFile *of, OutputStream *ost) uint8_t *encoder_string; int encoder_string_len; int format_flags = 0; - int codec_flags = 0; + int codec_flags = ost->enc_ctx->flags; if (av_dict_get(ost->st->metadata, "encoder", NULL, 0)) return; From 0976752420706c0a8b3cb8fd61497a47c7d7270f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 27 Oct 2017 02:23:20 +0200 Subject: [PATCH 0685/2557] avcodec/aacdec_fixed: Fix integer overflow in predict() Fixes: runtime error: signed integer overflow: -2110708110 + -82837504 cannot be represented in type 'int' Fixes: 3547/clusterfuzz-testcase-minimized-6009386439802880 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/aacdec_fixed.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c index f6a533010f2ac..5e9249ceeaadd 100644 --- a/libavcodec/aacdec_fixed.c +++ b/libavcodec/aacdec_fixed.c @@ -307,9 +307,9 @@ static av_always_inline void predict(PredictorState *ps, int *coef, if (shift < 31) { if (shift > 0) { - *coef += (pv.mant + (1 << (shift - 1))) >> shift; + *coef += (unsigned)((pv.mant + (1 << (shift - 1))) >> shift); } else - *coef += pv.mant << -shift; + *coef += (unsigned)(pv.mant << -shift); } } From 41d96af2a74cb5df50346b160067facd43149667 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 27 Oct 2017 02:23:21 +0200 Subject: [PATCH 0686/2557] avcodec/aacdec_fixed: Fix integer overflow in apply_dependent_coupling_fixed() Fixes: runtime error: signed integer overflow: 623487 * 536870912 cannot be represented in type 'int' Fixes: 3594/clusterfuzz-testcase-minimized-4650622935629824 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/aacdec_fixed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c index 5e9249ceeaadd..d802f3834f632 100644 --- a/libavcodec/aacdec_fixed.c +++ b/libavcodec/aacdec_fixed.c @@ -394,7 +394,7 @@ static void apply_dependent_coupling_fixed(AACContext *ac, for (k = offsets[i]; k < offsets[i + 1]; k++) { tmp = (int)(((int64_t)src[group * 128 + k] * c + \ (int64_t)0x1000000000) >> 37); - dest[group * 128 + k] += tmp * (1 << shift); + dest[group * 128 + k] += tmp * (1U << shift); } } } From 1181d93231e9b807965724587d363c1cfd5a1d0d Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Fri, 27 Oct 2017 17:01:26 +0530 Subject: [PATCH 0687/2557] avcodec/mips: Improve avc avg mc 22, 11, 31, 13 and 33 msa functions Remove loops and unroll as block sizes are known. Load the specific destination bytes instead of MSA load and pack. Remove unused macro and functions. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/h264qpel_msa.c | 781 ++++++++++++++++++++++----------- 1 file changed, 513 insertions(+), 268 deletions(-) diff --git a/libavcodec/mips/h264qpel_msa.c b/libavcodec/mips/h264qpel_msa.c index fcccb98ebdf84..e3a8634924d35 100644 --- a/libavcodec/mips/h264qpel_msa.c +++ b/libavcodec/mips/h264qpel_msa.c @@ -75,22 +75,6 @@ static const uint8_t luma_mask_arr[16 * 8] = { DPADD_SB2_SH(tmp0_m, tmp1_m, plus20b_m, plus20b_m, out1, out2); \ } -#define AVC_CALC_DPADD_B_6PIX_2COEFF_R_SH(vec0, vec1, vec2, vec3, vec4, vec5) \ -( { \ - v8i16 tmp1_m; \ - v16i8 tmp0_m, tmp2_m; \ - v16i8 minus5b_m = __msa_ldi_b(-5); \ - v16i8 plus20b_m = __msa_ldi_b(20); \ - \ - tmp1_m = (v8i16) __msa_ilvr_b((v16i8) vec5, (v16i8) vec0); \ - tmp1_m = __msa_hadd_s_h((v16i8) tmp1_m, (v16i8) tmp1_m); \ - \ - ILVR_B2_SB(vec4, vec1, vec3, vec2, tmp0_m, tmp2_m); \ - DPADD_SB2_SH(tmp0_m, tmp2_m, minus5b_m, plus20b_m, tmp1_m, tmp1_m); \ - \ - tmp1_m; \ -} ) - #define AVC_CALC_DPADD_H_6PIX_2COEFF_R_SH(vec0, vec1, vec2, vec3, vec4, vec5) \ ( { \ v4i32 tmp1_m; \ @@ -1157,128 +1141,6 @@ static void avc_luma_vt_qrt_and_aver_dst_16x16_msa(const uint8_t *src, } } -static void avc_luma_mid_and_aver_dst_4x4_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, int32_t dst_stride) -{ - v16i8 src0, src1, src2, src3, src4; - v16i8 mask0, mask1, mask2; - v8i16 hz_out0, hz_out1, hz_out2, hz_out3; - v8i16 hz_out4, hz_out5, hz_out6, hz_out7, hz_out8; - v8i16 res0, res1, res2, res3; - v16u8 dst0, dst1, dst2, dst3; - v16u8 tmp0, tmp1, tmp2, tmp3; - - LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - src += (5 * src_stride); - - XORI_B5_128_SB(src0, src1, src2, src3, src4); - - hz_out0 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src0, src1, - mask0, mask1, mask2); - hz_out2 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src2, src3, - mask0, mask1, mask2); - - PCKOD_D2_SH(hz_out0, hz_out0, hz_out2, hz_out2, hz_out1, hz_out3); - - hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); - - LD_SB4(src, src_stride, src0, src1, src2, src3); - XORI_B4_128_SB(src0, src1, src2, src3); - - hz_out5 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src0, src1, - mask0, mask1, mask2); - hz_out7 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src2, src3, - mask0, mask1, mask2); - - PCKOD_D2_SH(hz_out5, hz_out5, hz_out7, hz_out7, hz_out6, hz_out8); - - res0 = AVC_CALC_DPADD_H_6PIX_2COEFF_R_SH(hz_out0, hz_out1, hz_out2, - hz_out3, hz_out4, hz_out5); - res1 = AVC_CALC_DPADD_H_6PIX_2COEFF_R_SH(hz_out1, hz_out2, hz_out3, - hz_out4, hz_out5, hz_out6); - res2 = AVC_CALC_DPADD_H_6PIX_2COEFF_R_SH(hz_out2, hz_out3, hz_out4, - hz_out5, hz_out6, hz_out7); - res3 = AVC_CALC_DPADD_H_6PIX_2COEFF_R_SH(hz_out3, hz_out4, hz_out5, - hz_out6, hz_out7, hz_out8); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - tmp0 = PCKEV_XORI128_UB(res0, res1); - tmp1 = PCKEV_XORI128_UB(res2, res3); - PCKEV_D2_UB(dst1, dst0, dst3, dst2, tmp2, tmp3); - AVER_UB2_UB(tmp0, tmp2, tmp1, tmp3, tmp0, tmp1); - - ST4x4_UB(tmp0, tmp1, 0, 2, 0, 2, dst, dst_stride); -} - -static void avc_luma_mid_and_aver_dst_8w_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - int32_t height) -{ - uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4; - v16i8 mask0, mask1, mask2; - v8i16 hz_out0, hz_out1, hz_out2, hz_out3; - v8i16 hz_out4, hz_out5, hz_out6, hz_out7, hz_out8; - v16u8 dst0, dst1, dst2, dst3; - v8i16 res0, res1, res2, res3; - - LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); - - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - XORI_B5_128_SB(src0, src1, src2, src3, src4); - src += (5 * src_stride); - - hz_out0 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); - hz_out1 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); - hz_out2 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); - hz_out3 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); - hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); - - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB4(src, src_stride, src0, src1, src2, src3); - XORI_B4_128_SB(src0, src1, src2, src3); - src += (4 * src_stride); - - hz_out5 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); - hz_out6 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); - hz_out7 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); - hz_out8 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); - - res0 = AVC_CALC_DPADD_H_6PIX_2COEFF_SH(hz_out0, hz_out1, hz_out2, - hz_out3, hz_out4, hz_out5); - res1 = AVC_CALC_DPADD_H_6PIX_2COEFF_SH(hz_out1, hz_out2, hz_out3, - hz_out4, hz_out5, hz_out6); - res2 = AVC_CALC_DPADD_H_6PIX_2COEFF_SH(hz_out2, hz_out3, hz_out4, - hz_out5, hz_out6, hz_out7); - res3 = AVC_CALC_DPADD_H_6PIX_2COEFF_SH(hz_out3, hz_out4, hz_out5, - hz_out6, hz_out7, hz_out8); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - ILVR_D2_UB(dst1, dst0, dst3, dst2, dst0, dst1); - CONVERT_UB_AVG_ST8x4_UB(res0, res1, res2, res3, dst0, dst1, - dst, dst_stride); - - dst += (4 * dst_stride); - hz_out3 = hz_out7; - hz_out1 = hz_out5; - hz_out5 = hz_out4; - hz_out4 = hz_out8; - hz_out2 = hz_out6; - hz_out0 = hz_out5; - } -} - -static void avc_luma_mid_and_aver_dst_16x16_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride) -{ - avc_luma_mid_and_aver_dst_8w_msa(src, src_stride, dst, dst_stride, 16); - avc_luma_mid_and_aver_dst_8w_msa(src + 8, src_stride, dst + 8, dst_stride, - 16); -} - static void avc_luma_midh_qrt_and_aver_dst_4w_msa(const uint8_t *src, int32_t src_stride, uint8_t *dst, @@ -1578,22 +1440,28 @@ static void avc_luma_midv_qrt_and_aver_dst_16w_msa(const uint8_t *src, static void avc_luma_hv_qrt_and_aver_dst_4x4_msa(const uint8_t *src_x, const uint8_t *src_y, - int32_t src_stride, uint8_t *dst, - int32_t dst_stride) + int32_t stride) { - v16i8 src_hz0, src_hz1, src_hz2, src_hz3; - v16u8 dst0, dst1, dst2, dst3; - v16i8 src_vt0, src_vt1, src_vt2, src_vt3, src_vt4; - v16i8 src_vt5, src_vt6, src_vt7, src_vt8; - v16i8 mask0, mask1, mask2; - v8i16 hz_out0, hz_out1, vert_out0, vert_out1; - v8i16 res0, res1; - v16u8 res; + uint32_t tp0, tp1, tp2, tp3; + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + v16u8 res, dst0 = { 0 }; + v16i8 src_hz0, src_hz1, src_hz2, src_hz3, src_vt7, src_vt8; + v16i8 src_vt0, src_vt1, src_vt2, src_vt3, src_vt4, src_vt5, src_vt6; + v16i8 src_vt10_r, src_vt32_r, src_vt54_r, src_vt76_r; + v16i8 mask0, mask1, mask2, filt0, filt1, filt2; + v8i16 hz_out0, hz_out1, vt_out0, vt_out1, res0, res1; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); - LD_SB5(src_y, src_stride, src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); - src_y += (5 * src_stride); + + LD_SB5(src_y, stride, src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); + src_y += (5 * stride); src_vt0 = (v16i8) __msa_insve_w((v4i32) src_vt0, 1, (v4i32) src_vt1); src_vt1 = (v16i8) __msa_insve_w((v4i32) src_vt1, 1, (v4i32) src_vt2); @@ -1601,16 +1469,16 @@ static void avc_luma_hv_qrt_and_aver_dst_4x4_msa(const uint8_t *src_x, src_vt3 = (v16i8) __msa_insve_w((v4i32) src_vt3, 1, (v4i32) src_vt4); XORI_B4_128_SB(src_vt0, src_vt1, src_vt2, src_vt3); - LD_SB4(src_x, src_stride, src_hz0, src_hz1, src_hz2, src_hz3); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); + + LD_SB4(src_x, stride, src_hz0, src_hz1, src_hz2, src_hz3); XORI_B4_128_SB(src_hz0, src_hz1, src_hz2, src_hz3); - hz_out0 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src_hz0, src_hz1, - mask0, mask1, mask2); - hz_out1 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src_hz2, src_hz3, - mask0, mask1, mask2); + hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz1, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src_hz2, src_hz3, mask0, mask1, mask2); + SRARI_H2_SH(hz_out0, hz_out1, 5); SAT_SH2_SH(hz_out0, hz_out1, 7); - LD_SB4(src_y, src_stride, src_vt5, src_vt6, src_vt7, src_vt8); + + LD_SB4(src_y, stride, src_vt5, src_vt6, src_vt7, src_vt8); src_vt4 = (v16i8) __msa_insve_w((v4i32) src_vt4, 1, (v4i32) src_vt5); src_vt5 = (v16i8) __msa_insve_w((v4i32) src_vt5, 1, (v4i32) src_vt6); @@ -1618,132 +1486,245 @@ static void avc_luma_hv_qrt_and_aver_dst_4x4_msa(const uint8_t *src_x, src_vt7 = (v16i8) __msa_insve_w((v4i32) src_vt7, 1, (v4i32) src_vt8); XORI_B4_128_SB(src_vt4, src_vt5, src_vt6, src_vt7); + ILVR_B2_SB(src_vt1, src_vt0, src_vt3, src_vt2, src_vt10_r, src_vt32_r); + ILVR_B2_SB(src_vt5, src_vt4, src_vt7, src_vt6, src_vt54_r, src_vt76_r); + vt_out0 = AVC_DOT_SH3_SH(src_vt10_r, src_vt32_r, src_vt54_r, filt0, filt1, + filt2); + vt_out1 = AVC_DOT_SH3_SH(src_vt32_r, src_vt54_r, src_vt76_r, filt0, filt1, + filt2); + SRARI_H2_SH(vt_out0, vt_out1, 5); + SAT_SH2_SH(vt_out0, vt_out1, 7); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); - /* filter calc */ - vert_out0 = AVC_CALC_DPADD_B_6PIX_2COEFF_R_SH(src_vt0, src_vt1, src_vt2, - src_vt3, src_vt4, src_vt5); - vert_out1 = AVC_CALC_DPADD_B_6PIX_2COEFF_R_SH(src_vt2, src_vt3, src_vt4, - src_vt5, src_vt6, src_vt7); - SRARI_H2_SH(vert_out0, vert_out1, 5); - SAT_SH2_SH(vert_out0, vert_out1, 7); - - res1 = __msa_srari_h((hz_out1 + vert_out1), 1); - res0 = __msa_srari_h((hz_out0 + vert_out0), 1); + res1 = __msa_srari_h((hz_out1 + vt_out1), 1); + res0 = __msa_srari_h((hz_out0 + vt_out0), 1); SAT_SH2_SH(res0, res1, 7); res = PCKEV_XORI128_UB(res0, res1); - - dst0 = (v16u8) __msa_insve_w((v4i32) dst0, 1, (v4i32) dst1); - dst1 = (v16u8) __msa_insve_w((v4i32) dst2, 1, (v4i32) dst3); - dst0 = (v16u8) __msa_insve_d((v2i64) dst0, 1, (v2i64) dst1); dst0 = __msa_aver_u_b(res, dst0); - ST4x4_UB(dst0, dst0, 0, 1, 2, 3, dst, dst_stride); + ST4x4_UB(dst0, dst0, 0, 1, 2, 3, dst, stride); } static void avc_luma_hv_qrt_and_aver_dst_8x8_msa(const uint8_t *src_x, const uint8_t *src_y, - int32_t src_stride, uint8_t *dst, - int32_t dst_stride) + int32_t stride) { - uint32_t loop_cnt; - v16i8 src_hz0, src_hz1, src_hz2, src_hz3; - v16u8 dst0, dst1, dst2, dst3; - v16i8 src_vt0, src_vt1, src_vt2, src_vt3; - v16i8 src_vt4, src_vt5, src_vt6, src_vt7, src_vt8; - v16i8 mask0, mask1, mask2; - v8i16 hz_out0, hz_out1, hz_out2, hz_out3; - v8i16 vert_out0, vert_out1, vert_out2, vert_out3; - v8i16 out0, out1, out2, out3; + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + uint64_t tp0, tp1, tp2, tp3; + v16u8 out0, out1, dst0 = { 0 }, dst1 = { 0 }; + v16i8 src_hz0, src_hz1, src_hz2, src_hz3, src_vt0, src_vt1, src_vt2; + v16i8 src_vt3, src_vt4, src_vt5, src_vt6, src_vt7, src_vt8; + v16i8 src_vt9, src_vt10, src_vt11, src_vt12, mask0, mask1, mask2; + v16i8 src_vt10_r, src_vt21_r, src_vt32_r, src_vt43_r, src_vt54_r; + v16i8 src_vt65_r, src_vt76_r, src_vt87_r, src_vt98_r, src_vt109_r; + v16i8 src_vt1110_r, src_vt1211_r, filt0, filt1, filt2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, vt_out0, vt_out1, vt_out2; + v8i16 vt_out3, tmp0, tmp1, tmp2, tmp3; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + LD_SB5(src_y, stride, src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); + src_y += (5 * stride); - LD_SB5(src_y, src_stride, src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); - src_y += (5 * src_stride); + XORI_B5_128_SB(src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); - src_vt0 = (v16i8) __msa_insve_d((v2i64) src_vt0, 1, (v2i64) src_vt1); - src_vt1 = (v16i8) __msa_insve_d((v2i64) src_vt1, 1, (v2i64) src_vt2); - src_vt2 = (v16i8) __msa_insve_d((v2i64) src_vt2, 1, (v2i64) src_vt3); - src_vt3 = (v16i8) __msa_insve_d((v2i64) src_vt3, 1, (v2i64) src_vt4); + LD_SB4(src_x, stride, src_hz0, src_hz1, src_hz2, src_hz3); + XORI_B4_128_SB(src_hz0, src_hz1, src_hz2, src_hz3); + src_x += (4 * stride); - XORI_B4_128_SB(src_vt0, src_vt1, src_vt2, src_vt3); + hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src_hz1, src_hz1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src_hz2, src_hz2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src_hz3, src_hz3, mask0, mask1, mask2); - for (loop_cnt = 2; loop_cnt--;) { - LD_SB4(src_x, src_stride, src_hz0, src_hz1, src_hz2, src_hz3); - XORI_B4_128_SB(src_hz0, src_hz1, src_hz2, src_hz3); - src_x += (4 * src_stride); + SRARI_H4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 5); + SAT_SH4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 7); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz0, mask0, mask1, mask2); - hz_out1 = AVC_HORZ_FILTER_SH(src_hz1, src_hz1, mask0, mask1, mask2); - hz_out2 = AVC_HORZ_FILTER_SH(src_hz2, src_hz2, mask0, mask1, mask2); - hz_out3 = AVC_HORZ_FILTER_SH(src_hz3, src_hz3, mask0, mask1, mask2); - SRARI_H4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 5); - SAT_SH4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 7); - LD_SB4(src_y, src_stride, src_vt5, src_vt6, src_vt7, src_vt8); - src_y += (4 * src_stride); - - src_vt4 = (v16i8) __msa_insve_d((v2i64) src_vt4, 1, (v2i64) src_vt5); - src_vt5 = (v16i8) __msa_insve_d((v2i64) src_vt5, 1, (v2i64) src_vt6); - src_vt6 = (v16i8) __msa_insve_d((v2i64) src_vt6, 1, (v2i64) src_vt7); - src_vt7 = (v16i8) __msa_insve_d((v2i64) src_vt7, 1, (v2i64) src_vt8); - - XORI_B4_128_SB(src_vt4, src_vt5, src_vt6, src_vt7); - AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src_vt0, src_vt1, src_vt2, src_vt3, - src_vt4, src_vt5, vert_out0, vert_out1); - AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src_vt2, src_vt3, src_vt4, src_vt5, - src_vt6, src_vt7, vert_out2, vert_out3); - SRARI_H4_SH(vert_out0, vert_out1, vert_out2, vert_out3, 5); - SAT_SH4_SH(vert_out0, vert_out1, vert_out2, vert_out3, 7); - - out0 = __msa_srari_h((hz_out0 + vert_out0), 1); - out1 = __msa_srari_h((hz_out1 + vert_out1), 1); - out2 = __msa_srari_h((hz_out2 + vert_out2), 1); - out3 = __msa_srari_h((hz_out3 + vert_out3), 1); + LD_SB4(src_y, stride, src_vt5, src_vt6, src_vt7, src_vt8); + src_y += (4 * stride); + XORI_B4_128_SB(src_vt5, src_vt6, src_vt7, src_vt8); - SAT_SH4_SH(out0, out1, out2, out3, 7); - ILVR_D2_UB(dst1, dst0, dst3, dst2, dst0, dst1); - CONVERT_UB_AVG_ST8x4_UB(out0, out1, out2, out3, dst0, dst1, - dst, dst_stride); - dst += (4 * dst_stride); + ILVR_B4_SB(src_vt1, src_vt0, src_vt2, src_vt1, src_vt3, src_vt2, src_vt4, + src_vt3, src_vt10_r, src_vt21_r, src_vt32_r, src_vt43_r); + ILVR_B4_SB(src_vt5, src_vt4, src_vt6, src_vt5, src_vt7, src_vt6, src_vt8, + src_vt7, src_vt54_r, src_vt65_r, src_vt76_r, src_vt87_r); + vt_out0 = AVC_DOT_SH3_SH(src_vt10_r, src_vt32_r, src_vt54_r, filt0, filt1, + filt2); + vt_out1 = AVC_DOT_SH3_SH(src_vt21_r, src_vt43_r, src_vt65_r, filt0, filt1, + filt2); + vt_out2 = AVC_DOT_SH3_SH(src_vt32_r, src_vt54_r, src_vt76_r, filt0, filt1, + filt2); + vt_out3 = AVC_DOT_SH3_SH(src_vt43_r, src_vt65_r, src_vt87_r, filt0, filt1, + filt2); + SRARI_H4_SH(vt_out0, vt_out1, vt_out2, vt_out3, 5); + SAT_SH4_SH(vt_out0, vt_out1, vt_out2, vt_out3, 7); - src_vt0 = src_vt4; - src_vt1 = src_vt5; - src_vt2 = src_vt6; - src_vt3 = src_vt7; - src_vt4 = src_vt8; - } + tmp0 = __msa_srari_h((hz_out0 + vt_out0), 1); + tmp1 = __msa_srari_h((hz_out1 + vt_out1), 1); + tmp2 = __msa_srari_h((hz_out2 + vt_out2), 1); + tmp3 = __msa_srari_h((hz_out3 + vt_out3), 1); + + LD_SB4(src_x, stride, src_hz0, src_hz1, src_hz2, src_hz3); + XORI_B4_128_SB(src_hz0, src_hz1, src_hz2, src_hz3); + + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + + SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + AVER_UB2_UB(out0, dst0, out1, dst1, dst0, dst1); + ST8x4_UB(dst0, dst1, dst, stride); + dst += (4 * stride); + + LD_SB4(src_y, stride, src_vt9, src_vt10, src_vt11, src_vt12); + XORI_B4_128_SB(src_vt9, src_vt10, src_vt11, src_vt12); + + hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src_hz1, src_hz1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src_hz2, src_hz2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src_hz3, src_hz3, mask0, mask1, mask2); + + SRARI_H4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 5); + SAT_SH4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 7); + + ILVR_B4_SB(src_vt9, src_vt8, src_vt10, src_vt9, src_vt11, src_vt10, + src_vt12, src_vt11, src_vt98_r, src_vt109_r, src_vt1110_r, + src_vt1211_r); + vt_out0 = AVC_DOT_SH3_SH(src_vt54_r, src_vt76_r, src_vt98_r, filt0, filt1, + filt2); + vt_out1 = AVC_DOT_SH3_SH(src_vt65_r, src_vt87_r, src_vt109_r, filt0, filt1, + filt2); + vt_out2 = AVC_DOT_SH3_SH(src_vt76_r, src_vt98_r, src_vt1110_r, filt0, filt1, + filt2); + vt_out3 = AVC_DOT_SH3_SH(src_vt87_r, src_vt109_r, src_vt1211_r, filt0, + filt1, filt2); + SRARI_H4_SH(vt_out0, vt_out1, vt_out2, vt_out3, 5); + SAT_SH4_SH(vt_out0, vt_out1, vt_out2, vt_out3, 7); + + tmp0 = __msa_srari_h((hz_out0 + vt_out0), 1); + tmp1 = __msa_srari_h((hz_out1 + vt_out1), 1); + tmp2 = __msa_srari_h((hz_out2 + vt_out2), 1); + tmp3 = __msa_srari_h((hz_out3 + vt_out3), 1); + + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + + SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + AVER_UB2_UB(out0, dst0, out1, dst1, dst0, dst1); + ST8x4_UB(dst0, dst1, dst, stride); + dst += (4 * stride); } static void avc_luma_hv_qrt_and_aver_dst_16x16_msa(const uint8_t *src_x, const uint8_t *src_y, - int32_t src_stride, uint8_t *dst, - int32_t dst_stride) + int32_t stride) { - uint32_t multiple8_cnt; + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + const uint8_t *src_x_tmp = src_x; + const uint8_t *src_y_tmp = src_y; + uint8_t *dst_tmp = dst; + uint32_t multiple8_cnt, loop_cnt; + uint64_t tp0, tp1, tp2, tp3; + v16u8 tmp0, tmp1, dst0 = { 0 }, dst1 = { 0 }; + v16i8 src_hz0, src_hz1, src_hz2, src_hz3, mask0, mask1, mask2; + v16i8 src_vt0, src_vt1, src_vt2, src_vt3, src_vt4, src_vt5, src_vt6; + v16i8 src_vt7, src_vt8; + v16i8 src_vt10_r, src_vt21_r, src_vt32_r, src_vt43_r, src_vt54_r; + v16i8 src_vt65_r, src_vt76_r, src_vt87_r, filt0, filt1, filt2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, vt_out0, vt_out1, vt_out2; + v8i16 vt_out3, out0, out1, out2, out3; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); for (multiple8_cnt = 2; multiple8_cnt--;) { - avc_luma_hv_qrt_and_aver_dst_8x8_msa(src_x, src_y, src_stride, - dst, dst_stride); + src_x = src_x_tmp; + src_y = src_y_tmp; + dst = dst_tmp; + + LD_SB5(src_y, stride, src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); + src_y += (5 * stride); + + XORI_B5_128_SB(src_vt0, src_vt1, src_vt2, src_vt3, src_vt4); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src_x, stride, src_hz0, src_hz1, src_hz2, src_hz3); + XORI_B4_128_SB(src_hz0, src_hz1, src_hz2, src_hz3); + src_x += (4 * stride); + + hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src_hz1, src_hz1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src_hz2, src_hz2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src_hz3, src_hz3, mask0, mask1, mask2); + SRARI_H4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 5); + SAT_SH4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 7); + + LD_SB4(src_y, stride, src_vt5, src_vt6, src_vt7, src_vt8); + src_y += (4 * stride); + + XORI_B4_128_SB(src_vt5, src_vt6, src_vt7, src_vt8); + ILVR_B4_SB(src_vt1, src_vt0, src_vt2, src_vt1, src_vt3, src_vt2, + src_vt4, src_vt3, src_vt10_r, src_vt21_r, src_vt32_r, + src_vt43_r); + ILVR_B4_SB(src_vt5, src_vt4, src_vt6, src_vt5, src_vt7, src_vt6, + src_vt8, src_vt7, src_vt54_r, src_vt65_r, src_vt76_r, + src_vt87_r); + vt_out0 = AVC_DOT_SH3_SH(src_vt10_r, src_vt32_r, src_vt54_r, filt0, + filt1, filt2); + vt_out1 = AVC_DOT_SH3_SH(src_vt21_r, src_vt43_r, src_vt65_r, filt0, + filt1, filt2); + vt_out2 = AVC_DOT_SH3_SH(src_vt32_r, src_vt54_r, src_vt76_r, filt0, + filt1, filt2); + vt_out3 = AVC_DOT_SH3_SH(src_vt43_r, src_vt65_r, src_vt87_r, filt0, + filt1, filt2); + SRARI_H4_SH(vt_out0, vt_out1, vt_out2, vt_out3, 5); + SAT_SH4_SH(vt_out0, vt_out1, vt_out2, vt_out3, 7); + + out0 = __msa_srari_h((hz_out0 + vt_out0), 1); + out1 = __msa_srari_h((hz_out1 + vt_out1), 1); + out2 = __msa_srari_h((hz_out2 + vt_out2), 1); + out3 = __msa_srari_h((hz_out3 + vt_out3), 1); - src_x += 8; - src_y += 8; - dst += 8; - } + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); - src_x += (8 * src_stride) - 16; - src_y += (8 * src_stride) - 16; - dst += (8 * dst_stride) - 16; + SAT_SH4_SH(out0, out1, out2, out3, 7); + tmp0 = PCKEV_XORI128_UB(out0, out1); + tmp1 = PCKEV_XORI128_UB(out2, out3); + AVER_UB2_UB(tmp0, dst0, tmp1, dst1, dst0, dst1); + ST8x4_UB(dst0, dst1, dst, stride); + dst += (4 * stride); - for (multiple8_cnt = 2; multiple8_cnt--;) { - avc_luma_hv_qrt_and_aver_dst_8x8_msa(src_x, src_y, src_stride, - dst, dst_stride); + src_vt0 = src_vt4; + src_vt1 = src_vt5; + src_vt2 = src_vt6; + src_vt3 = src_vt7; + src_vt4 = src_vt8; + } - src_x += 8; - src_y += 8; - dst += 8; + src_x_tmp += 8; + src_y_tmp += 8; + dst_tmp += 8; } } @@ -4349,7 +4330,7 @@ void ff_avg_h264_qpel16_mc11_msa(uint8_t *dst, const uint8_t *src, { avc_luma_hv_qrt_and_aver_dst_16x16_msa(src - 2, src - (stride * 2), - stride, dst, stride); + dst, stride); } void ff_avg_h264_qpel16_mc31_msa(uint8_t *dst, const uint8_t *src, @@ -4357,7 +4338,7 @@ void ff_avg_h264_qpel16_mc31_msa(uint8_t *dst, const uint8_t *src, { avc_luma_hv_qrt_and_aver_dst_16x16_msa(src - 2, src - (stride * 2) + - sizeof(uint8_t), stride, + sizeof(uint8_t), dst, stride); } @@ -4366,7 +4347,7 @@ void ff_avg_h264_qpel16_mc13_msa(uint8_t *dst, const uint8_t *src, { avc_luma_hv_qrt_and_aver_dst_16x16_msa(src + stride - 2, src - (stride * 2), - stride, dst, stride); + dst, stride); } void ff_avg_h264_qpel16_mc33_msa(uint8_t *dst, const uint8_t *src, @@ -4374,7 +4355,7 @@ void ff_avg_h264_qpel16_mc33_msa(uint8_t *dst, const uint8_t *src, { avc_luma_hv_qrt_and_aver_dst_16x16_msa(src + stride - 2, src - (stride * 2) + - sizeof(uint8_t), stride, + sizeof(uint8_t), dst, stride); } @@ -4383,7 +4364,7 @@ void ff_avg_h264_qpel8_mc11_msa(uint8_t *dst, const uint8_t *src, { avc_luma_hv_qrt_and_aver_dst_8x8_msa(src - 2, src - (stride * 2), - stride, dst, stride); + dst, stride); } void ff_avg_h264_qpel8_mc31_msa(uint8_t *dst, const uint8_t *src, @@ -4391,7 +4372,7 @@ void ff_avg_h264_qpel8_mc31_msa(uint8_t *dst, const uint8_t *src, { avc_luma_hv_qrt_and_aver_dst_8x8_msa(src - 2, src - (stride * 2) + - sizeof(uint8_t), stride, dst, stride); + sizeof(uint8_t), dst, stride); } void ff_avg_h264_qpel8_mc13_msa(uint8_t *dst, const uint8_t *src, @@ -4399,7 +4380,7 @@ void ff_avg_h264_qpel8_mc13_msa(uint8_t *dst, const uint8_t *src, { avc_luma_hv_qrt_and_aver_dst_8x8_msa(src + stride - 2, src - (stride * 2), - stride, dst, stride); + dst, stride); } void ff_avg_h264_qpel8_mc33_msa(uint8_t *dst, const uint8_t *src, @@ -4407,7 +4388,7 @@ void ff_avg_h264_qpel8_mc33_msa(uint8_t *dst, const uint8_t *src, { avc_luma_hv_qrt_and_aver_dst_8x8_msa(src + stride - 2, src - (stride * 2) + - sizeof(uint8_t), stride, dst, stride); + sizeof(uint8_t), dst, stride); } @@ -4416,7 +4397,7 @@ void ff_avg_h264_qpel4_mc11_msa(uint8_t *dst, const uint8_t *src, { avc_luma_hv_qrt_and_aver_dst_4x4_msa(src - 2, src - (stride * 2), - stride, dst, stride); + dst, stride); } void ff_avg_h264_qpel4_mc31_msa(uint8_t *dst, const uint8_t *src, @@ -4424,7 +4405,7 @@ void ff_avg_h264_qpel4_mc31_msa(uint8_t *dst, const uint8_t *src, { avc_luma_hv_qrt_and_aver_dst_4x4_msa(src - 2, src - (stride * 2) + - sizeof(uint8_t), stride, dst, stride); + sizeof(uint8_t), dst, stride); } void ff_avg_h264_qpel4_mc13_msa(uint8_t *dst, const uint8_t *src, @@ -4432,7 +4413,7 @@ void ff_avg_h264_qpel4_mc13_msa(uint8_t *dst, const uint8_t *src, { avc_luma_hv_qrt_and_aver_dst_4x4_msa(src + stride - 2, src - (stride * 2), - stride, dst, stride); + dst, stride); } void ff_avg_h264_qpel4_mc33_msa(uint8_t *dst, const uint8_t *src, @@ -4440,7 +4421,7 @@ void ff_avg_h264_qpel4_mc33_msa(uint8_t *dst, const uint8_t *src, { avc_luma_hv_qrt_and_aver_dst_4x4_msa(src + stride - 2, src - (stride * 2) + - sizeof(uint8_t), stride, dst, stride); + sizeof(uint8_t), dst, stride); } void ff_avg_h264_qpel16_mc21_msa(uint8_t *dst, const uint8_t *src, @@ -4548,20 +4529,284 @@ void ff_avg_h264_qpel4_mc32_msa(uint8_t *dst, const uint8_t *src, void ff_avg_h264_qpel16_mc22_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_mid_and_aver_dst_16x16_msa(src - (2 * stride) - 2, - stride, dst, stride); + const int32_t filt_const0 = 0xfffb0001; + const int32_t filt_const1 = 0x140014; + const int32_t filt_const2 = 0x1fffb; + const uint8_t *src_tmp = src - (2 * stride) - 2; + uint8_t *dst_tmp = dst; + uint64_t tp0, tp1, tp2, tp3; + uint32_t multiple8_cnt, loop_cnt; + v16u8 dst0, dst1, out0, out1; + v16i8 src0, src1, src2, src3, src4, mask0, mask1, mask2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + v8i16 hz_out7, hz_out8, res0, res1, res2, res3; + v8i16 hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r, hz_out54_r; + v8i16 hz_out65_r, hz_out76_r, hz_out87_r, hz_out10_l, hz_out21_l; + v8i16 hz_out32_l, hz_out43_l, hz_out54_l, hz_out65_l, hz_out76_l; + v8i16 hz_out87_l, filt0, filt1, filt2; + v4i32 tmp0, tmp1; + + filt0 = (v8i16) __msa_fill_w(filt_const0); + filt1 = (v8i16) __msa_fill_w(filt_const1); + filt2 = (v8i16) __msa_fill_w(filt_const2); + + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + + for (multiple8_cnt = 2; multiple8_cnt--;) { + src = src_tmp; + dst = dst_tmp; + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + src += (5 * stride); + + hz_out0 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src, stride, src0, src1, src2, src3); + XORI_B4_128_SB(src0, src1, src2, src3); + src += (4 * stride); + + hz_out5 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out6 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out7 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out8 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + ILVR_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, + hz_out4, hz_out3, hz_out10_r, hz_out21_r, hz_out32_r, + hz_out43_r); + ILVL_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, + hz_out4, hz_out3, hz_out10_l, hz_out21_l, hz_out32_l, + hz_out43_l); + ILVR_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, + hz_out8, hz_out7, hz_out54_r, hz_out65_r, hz_out76_r, + hz_out87_r); + ILVL_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, + hz_out8, hz_out7, hz_out54_l, hz_out65_l, hz_out76_l, + hz_out87_l); + + tmp0 = AVC_DOT_SW3_SW(hz_out10_r, hz_out32_r, hz_out54_r, filt0, + filt1, filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out10_l, hz_out32_l, hz_out54_l, filt0, + filt1, filt2); + res0 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out21_r, hz_out43_r, hz_out65_r, filt0, + filt1, filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out21_l, hz_out43_l, hz_out65_l, filt0, + filt1, filt2); + res1 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out32_r, hz_out54_r, hz_out76_r, filt0, + filt1, filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out32_l, hz_out54_l, hz_out76_l, filt0, + filt1, filt2); + res2 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out43_r, hz_out65_r, hz_out87_r, filt0, + filt1, filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out43_l, hz_out65_l, hz_out87_l, filt0, + filt1, filt2); + res3 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + out0 = PCKEV_XORI128_UB(res0, res1); + out1 = PCKEV_XORI128_UB(res2, res3); + AVER_UB2_UB(out0, dst0, out1, dst1, out0, out1); + ST8x4_UB(out0, out1, dst, stride); + dst += (4 * stride); + + hz_out0 = hz_out4; + hz_out1 = hz_out5; + hz_out2 = hz_out6; + hz_out3 = hz_out7; + hz_out4 = hz_out8; + } + + src_tmp += 8; + dst_tmp += 8; + } } void ff_avg_h264_qpel8_mc22_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_mid_and_aver_dst_8w_msa(src - (2 * stride) - 2, - stride, dst, stride, 8); + const int32_t filt_const0 = 0xfffb0001; + const int32_t filt_const1 = 0x140014; + const int32_t filt_const2 = 0x1fffb; + uint64_t tp0, tp1, tp2, tp3; + v16u8 out0, out1, dst0 = { 0 }, dst1 = { 0 }; + v16i8 src0, src1, src2, src3, src4, mask0, mask1, mask2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + v8i16 hz_out7, hz_out8, hz_out9, hz_out10, hz_out11, hz_out12; + v8i16 hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r, hz_out54_r; + v8i16 hz_out65_r, hz_out76_r, hz_out87_r, hz_out89_r, hz_out910_r; + v8i16 hz_out1110_r, hz_out1211_r, res0, res1, res2, res3; + v8i16 hz_out10_l, hz_out21_l, hz_out32_l, hz_out43_l, hz_out54_l; + v8i16 hz_out65_l, hz_out76_l, hz_out87_l, hz_out89_l, hz_out910_l; + v8i16 hz_out1110_l, hz_out1211_l, filt0, filt1, filt2; + v4i32 tmp0, tmp1; + + filt0 = (v8i16) __msa_fill_w(filt_const0); + filt1 = (v8i16) __msa_fill_w(filt_const1); + filt2 = (v8i16) __msa_fill_w(filt_const2); + + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + + src -= ((2 * stride) + 2); + LD_SB5(src, stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + src += (5 * stride); + + hz_out0 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); + + LD_SB4(src, stride, src0, src1, src2, src3); + XORI_B4_128_SB(src0, src1, src2, src3); + src += (4 * stride); + hz_out5 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out6 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out7 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out8 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + ILVR_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, hz_out4, + hz_out3, hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r); + ILVL_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, hz_out4, + hz_out3, hz_out10_l, hz_out21_l, hz_out32_l, hz_out43_l); + ILVR_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, hz_out8, + hz_out7, hz_out54_r, hz_out65_r, hz_out76_r, hz_out87_r); + ILVL_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, hz_out8, + hz_out7, hz_out54_l, hz_out65_l, hz_out76_l, hz_out87_l); + + tmp0 = AVC_DOT_SW3_SW(hz_out10_r, hz_out32_r, hz_out54_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out10_l, hz_out32_l, hz_out54_l, filt0, filt1, + filt2); + res0 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out21_r, hz_out43_r, hz_out65_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out21_l, hz_out43_l, hz_out65_l, filt0, filt1, + filt2); + res1 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out32_r, hz_out54_r, hz_out76_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out32_l, hz_out54_l, hz_out76_l, filt0, filt1, + filt2); + res2 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out43_r, hz_out65_r, hz_out87_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out43_l, hz_out65_l, hz_out87_l, filt0, filt1, + filt2); + res3 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + out0 = PCKEV_XORI128_UB(res0, res1); + out1 = PCKEV_XORI128_UB(res2, res3); + AVER_UB2_UB(out0, dst0, out1, dst1, dst0, dst1); + ST8x4_UB(dst0, dst1, dst, stride); + dst += (4 * stride); + + LD_SB4(src, stride, src0, src1, src2, src3); + XORI_B4_128_SB(src0, src1, src2, src3); + hz_out9 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out10 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out11 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out12 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + ILVR_H4_SH(hz_out9, hz_out8, hz_out10, hz_out9, hz_out11, hz_out10, + hz_out12, hz_out11, hz_out89_r, hz_out910_r, hz_out1110_r, + hz_out1211_r); + ILVL_H4_SH(hz_out9, hz_out8, hz_out10, hz_out9, hz_out11, hz_out10, + hz_out12, hz_out11, hz_out89_l, hz_out910_l, hz_out1110_l, + hz_out1211_l); + tmp0 = AVC_DOT_SW3_SW(hz_out54_r, hz_out76_r, hz_out89_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out54_l, hz_out76_l, hz_out89_l, filt0, filt1, + filt2); + res0 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out65_r, hz_out87_r, hz_out910_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out65_l, hz_out87_l, hz_out910_l, filt0, filt1, + filt2); + res1 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out76_r, hz_out89_r, hz_out1110_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out76_l, hz_out89_l, hz_out1110_l, filt0, filt1, + filt2); + res2 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out87_r, hz_out910_r, hz_out1211_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out87_l, hz_out910_l, hz_out1211_l, filt0, filt1, + filt2); + res3 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + out0 = PCKEV_XORI128_UB(res0, res1); + out1 = PCKEV_XORI128_UB(res2, res3); + AVER_UB2_UB(out0, dst0, out1, dst1, dst0, dst1); + ST8x4_UB(dst0, dst1, dst, stride); } void ff_avg_h264_qpel4_mc22_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_mid_and_aver_dst_4x4_msa(src - (2 * stride) - 2, - stride, dst, stride); + const int32_t filt_const0 = 0xfffb0001; + const int32_t filt_const1 = 0x140014; + const int32_t filt_const2 = 0x1fffb; + uint32_t tp0, tp1, tp2, tp3; + v16u8 res, dst0 = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 mask0, mask1, mask2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + v8i16 hz_out7, hz_out8, res0, res1, filt0, filt1, filt2; + v8i16 hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r, hz_out54_r; + v8i16 hz_out65_r, hz_out76_r, hz_out87_r; + v4i32 tmp0, tmp1; + + LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); + + filt0 = (v8i16) __msa_fill_w(filt_const0); + filt1 = (v8i16) __msa_fill_w(filt_const1); + filt2 = (v8i16) __msa_fill_w(filt_const2); + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + LD_SB4(src, stride, src5, src6, src7, src8); + + XORI_B5_128_SB(src0, src1, src2, src3, src4); + XORI_B4_128_SB(src5, src6, src7, src8); + hz_out0 = AVC_HORZ_FILTER_SH(src0, src1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src2, src3, mask0, mask1, mask2); + hz_out4 = AVC_HORZ_FILTER_SH(src4, src5, mask0, mask1, mask2); + hz_out6 = AVC_HORZ_FILTER_SH(src6, src7, mask0, mask1, mask2); + hz_out8 = AVC_HORZ_FILTER_SH(src8, src8, mask0, mask1, mask2); + PCKOD_D2_SH(hz_out0, hz_out0, hz_out2, hz_out2, hz_out1, hz_out3); + PCKOD_D2_SH(hz_out4, hz_out4, hz_out6, hz_out6, hz_out5, hz_out7); + ILVR_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, hz_out4, + hz_out3, hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r); + ILVR_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, hz_out8, + hz_out7, hz_out54_r, hz_out65_r, hz_out76_r, hz_out87_r); + + tmp0 = AVC_DOT_SW3_SW(hz_out10_r, hz_out32_r, hz_out54_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out21_r, hz_out43_r, hz_out65_r, filt0, filt1, + filt2); + res0 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out32_r, hz_out54_r, hz_out76_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out43_r, hz_out65_r, hz_out87_r, filt0, filt1, + filt2); + res1 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); + res = PCKEV_XORI128_UB(res0, res1); + res = __msa_aver_u_b(res, dst0); + ST4x4_UB(res, res, 0, 1, 2, 3, dst, stride); } From 93218c2234968bcd4426c3bb748c1080e57117b5 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Fri, 27 Oct 2017 17:03:01 +0530 Subject: [PATCH 0688/2557] avcodec/mips: Improve avc chroma avg hv mc msa functions Replace generic with block size specific function. Load the specific destination bytes instead of MSA load and pack. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/h264chroma_msa.c | 438 +++++++++++++++++-------------- 1 file changed, 238 insertions(+), 200 deletions(-) diff --git a/libavcodec/mips/h264chroma_msa.c b/libavcodec/mips/h264chroma_msa.c index a5c333471b04a..4c257611947ab 100644 --- a/libavcodec/mips/h264chroma_msa.c +++ b/libavcodec/mips/h264chroma_msa.c @@ -1408,15 +1408,15 @@ static void avc_chroma_vt_and_aver_dst_8w_msa(uint8_t *src, uint8_t *dst, } } -static void avc_chroma_hv_and_aver_dst_2x2_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, +static void avc_chroma_hv_and_aver_dst_2x2_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coef_hor0, uint32_t coef_hor1, uint32_t coef_ver0, uint32_t coef_ver1) { uint16_t out0, out1; - v16u8 dst0, dst1; + v16u8 dst0 = { 0 }; v16u8 src0, src1, src2; v8u16 res_hz0, res_hz1, res_vt0, res_vt1; v16i8 res, mask; @@ -1428,8 +1428,11 @@ static void avc_chroma_hv_and_aver_dst_2x2_msa(uint8_t *src, int32_t src_stride, mask = LD_SB(&chroma_mask_arr[48]); - LD_UB3(src, src_stride, src0, src1, src2); - LD_UB2(dst, dst_stride, dst0, dst1); + LD_UB3(src, stride, src0, src1, src2); + out0 = LH(dst); + out1 = LH(dst + stride); + dst0 = (v16u8) __msa_insert_h((v8i16) dst0, 0, out0); + dst0 = (v16u8) __msa_insert_h((v8i16) dst0, 1, out1); VSHF_B2_UB(src0, src1, src1, src2, mask, mask, src0, src1); DOTP_UB2_UH(src0, src1, coeff_hz_vec, coeff_hz_vec, res_hz0, res_hz1); MUL2(res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_vt0, res_vt1); @@ -1438,67 +1441,26 @@ static void avc_chroma_hv_and_aver_dst_2x2_msa(uint8_t *src, int32_t src_stride, res_vt0 = (v8u16) __msa_srari_h((v8i16) res_vt0, 6); res_vt0 = __msa_sat_u_h(res_vt0, 7); res = __msa_pckev_b((v16i8) res_vt0, (v16i8) res_vt0); - dst0 = (v16u8) __msa_insve_h((v8i16) dst0, 1, (v8i16) dst1); dst0 = __msa_aver_u_b((v16u8) res, dst0); out0 = __msa_copy_u_h((v8i16) dst0, 0); out1 = __msa_copy_u_h((v8i16) dst0, 1); SH(out0, dst); - dst += dst_stride; + dst += stride; SH(out1, dst); } -static void avc_chroma_hv_and_aver_dst_2x4_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, +static void avc_chroma_hv_and_aver_dst_2x4_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coef_hor0, uint32_t coef_hor1, uint32_t coef_ver0, uint32_t coef_ver1) { + uint16_t tp0, tp1, tp2, tp3; v16u8 src0, src1, src2, src3, src4; v16u8 tmp0, tmp1, tmp2, tmp3; - v16u8 dst0, dst1, dst2, dst3; - v8u16 res_hz0, res_hz1, res_vt0, res_vt1; - v16i8 res, mask; - v16i8 coeff_hz_vec0 = __msa_fill_b(coef_hor0); - v16i8 coeff_hz_vec1 = __msa_fill_b(coef_hor1); - v16u8 coeff_hz_vec = (v16u8) __msa_ilvr_b(coeff_hz_vec0, coeff_hz_vec1); - v8u16 coeff_vt_vec0 = (v8u16) __msa_fill_h(coef_ver0); - v8u16 coeff_vt_vec1 = (v8u16) __msa_fill_h(coef_ver1); - - mask = LD_SB(&chroma_mask_arr[48]); - - LD_UB5(src, src_stride, src0, src1, src2, src3, src4); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - VSHF_B2_UB(src0, src1, src2, src3, mask, mask, tmp0, tmp1); - VSHF_B2_UB(src1, src2, src3, src4, mask, mask, tmp2, tmp3); - ILVR_D2_UB(tmp1, tmp0, tmp3, tmp2, src0, src1); - DOTP_UB2_UH(src0, src1, coeff_hz_vec, coeff_hz_vec, res_hz0, res_hz1); - MUL2(res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_vt0, res_vt1); - - res_vt0 += res_vt1; - res_vt0 = (v8u16) __msa_srari_h((v8i16) res_vt0, 6); - res_vt0 = __msa_sat_u_h(res_vt0, 7); - res = __msa_pckev_b((v16i8) res_vt0, (v16i8) res_vt0); - - dst0 = (v16u8) __msa_insve_h((v8i16) dst0, 1, (v8i16) dst1); - dst0 = (v16u8) __msa_insve_h((v8i16) dst0, 2, (v8i16) dst2); - dst0 = (v16u8) __msa_insve_h((v8i16) dst0, 3, (v8i16) dst3); - dst0 = __msa_aver_u_b((v16u8) res, dst0); - - ST2x4_UB(dst0, 0, dst, dst_stride); -} - -static void avc_chroma_hv_and_aver_dst_2x8_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coef_hor0, - uint32_t coef_hor1, - uint32_t coef_ver0, - uint32_t coef_ver1) -{ - v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8; - v16u8 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; - v16u8 tmp0, tmp1, tmp2, tmp3; + v16u8 dst0 = { 0 }; v8u16 res_hz0, res_hz1, res_vt0, res_vt1; v16i8 res, mask; v16i8 coeff_hz_vec0 = __msa_fill_b(coef_hor0); @@ -1509,26 +1471,18 @@ static void avc_chroma_hv_and_aver_dst_2x8_msa(uint8_t *src, int32_t src_stride, mask = LD_SB(&chroma_mask_arr[48]); - LD_UB5(src, src_stride, src0, src1, src2, src3, src4); - src += (5 * src_stride); - LD_UB4(src, src_stride, src5, src6, src7, src8); - - LD_UB8(dst, dst_stride, dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7); - - dst0 = (v16u8) __msa_insve_h((v8i16) dst0, 1, (v8i16) dst1); - dst0 = (v16u8) __msa_insve_h((v8i16) dst0, 2, (v8i16) dst2); - dst0 = (v16u8) __msa_insve_h((v8i16) dst0, 3, (v8i16) dst3); - - dst4 = (v16u8) __msa_insve_h((v8i16) dst4, 1, (v8i16) dst5); - dst4 = (v16u8) __msa_insve_h((v8i16) dst4, 2, (v8i16) dst6); - dst4 = (v16u8) __msa_insve_h((v8i16) dst4, 3, (v8i16) dst7); - + LD_UB5(src, stride, src0, src1, src2, src3, src4); + tp0 = LH(dst); + tp1 = LH(dst + stride); + tp2 = LH(dst + 2 * stride); + tp3 = LH(dst + 3 * stride); + dst0 = (v16u8) __msa_insert_h((v8i16) dst0, 0, tp0); + dst0 = (v16u8) __msa_insert_h((v8i16) dst0, 1, tp1); + dst0 = (v16u8) __msa_insert_h((v8i16) dst0, 2, tp2); + dst0 = (v16u8) __msa_insert_h((v8i16) dst0, 3, tp3); VSHF_B2_UB(src0, src1, src2, src3, mask, mask, tmp0, tmp1); VSHF_B2_UB(src1, src2, src3, src4, mask, mask, tmp2, tmp3); ILVR_D2_UB(tmp1, tmp0, tmp3, tmp2, src0, src1); - VSHF_B2_UB(src4, src5, src6, src7, mask, mask, tmp0, tmp1); - VSHF_B2_UB(src5, src6, src7, src8, mask, mask, tmp2, tmp3); - ILVR_D2_UB(tmp1, tmp0, tmp3, tmp2, src4, src5); DOTP_UB2_UH(src0, src1, coeff_hz_vec, coeff_hz_vec, res_hz0, res_hz1); MUL2(res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_vt0, res_vt1); @@ -1538,23 +1492,11 @@ static void avc_chroma_hv_and_aver_dst_2x8_msa(uint8_t *src, int32_t src_stride, res = __msa_pckev_b((v16i8) res_vt0, (v16i8) res_vt0); dst0 = __msa_aver_u_b((v16u8) res, dst0); - ST2x4_UB(dst0, 0, dst, dst_stride); - dst += (4 * dst_stride); - - DOTP_UB2_UH(src4, src5, coeff_hz_vec, coeff_hz_vec, res_hz0, res_hz1); - MUL2(res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_vt0, res_vt1); - - res_vt0 += res_vt1; - res_vt0 = (v8u16) __msa_srari_h((v8i16) res_vt0, 6); - res_vt0 = __msa_sat_u_h(res_vt0, 7); - res = __msa_pckev_b((v16i8) res_vt0, (v16i8) res_vt0); - dst4 = __msa_aver_u_b((v16u8) res, dst4); - - ST2x4_UB(dst4, 0, dst, dst_stride); + ST2x4_UB(dst0, 0, dst, stride); } -static void avc_chroma_hv_and_aver_dst_2w_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, +static void avc_chroma_hv_and_aver_dst_2w_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coef_hor0, uint32_t coef_hor1, uint32_t coef_ver0, @@ -1562,31 +1504,26 @@ static void avc_chroma_hv_and_aver_dst_2w_msa(uint8_t *src, int32_t src_stride, int32_t height) { if (2 == height) { - avc_chroma_hv_and_aver_dst_2x2_msa(src, src_stride, dst, dst_stride, - coef_hor0, coef_hor1, - coef_ver0, coef_ver1); + avc_chroma_hv_and_aver_dst_2x2_msa(src, dst, stride, coef_hor0, + coef_hor1, coef_ver0, coef_ver1); } else if (4 == height) { - avc_chroma_hv_and_aver_dst_2x4_msa(src, src_stride, dst, dst_stride, - coef_hor0, coef_hor1, - coef_ver0, coef_ver1); - } else if (8 == height) { - avc_chroma_hv_and_aver_dst_2x8_msa(src, src_stride, dst, dst_stride, - coef_hor0, coef_hor1, - coef_ver0, coef_ver1); + avc_chroma_hv_and_aver_dst_2x4_msa(src, dst, stride, coef_hor0, + coef_hor1, coef_ver0, coef_ver1); } } -static void avc_chroma_hv_and_aver_dst_4x2_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, +static void avc_chroma_hv_and_aver_dst_4x2_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coef_hor0, uint32_t coef_hor1, uint32_t coef_ver0, uint32_t coef_ver1) { + uint32_t tp0, tp1; v16u8 src0, src1, src2; - v16u8 dst0, dst1; + v16u8 dst0, dst_data = { 0 }; v8u16 res_hz0, res_hz1, res_vt0, res_vt1; - v16i8 res, mask; + v16i8 mask; v16i8 coeff_hz_vec0 = __msa_fill_b(coef_hor0); v16i8 coeff_hz_vec1 = __msa_fill_b(coef_hor1); v16u8 coeff_hz_vec = (v16u8) __msa_ilvr_b(coeff_hz_vec0, coeff_hz_vec1); @@ -1595,8 +1532,9 @@ static void avc_chroma_hv_and_aver_dst_4x2_msa(uint8_t *src, int32_t src_stride, mask = LD_SB(&chroma_mask_arr[0]); - LD_UB3(src, src_stride, src0, src1, src2); - LD_UB2(dst, dst_stride, dst0, dst1); + LD_UB3(src, stride, src0, src1, src2); + LW2(dst, stride, tp0, tp1); + INSERT_W2_UB(tp0, tp1, dst_data); VSHF_B2_UB(src0, src1, src1, src2, mask, mask, src0, src1); DOTP_UB2_UH(src0, src1, coeff_hz_vec, coeff_hz_vec, res_hz0, res_hz1); MUL2(res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_vt0, res_vt1); @@ -1604,26 +1542,22 @@ static void avc_chroma_hv_and_aver_dst_4x2_msa(uint8_t *src, int32_t src_stride, res_vt0 += res_vt1; res_vt0 = (v8u16) __msa_srari_h((v8i16) res_vt0, 6); res_vt0 = __msa_sat_u_h(res_vt0, 7); - res = __msa_pckev_b((v16i8) res_vt0, (v16i8) res_vt0); - dst0 = (v16u8) __msa_insve_w((v4i32) dst0, 1, (v4i32) dst1); - dst0 = __msa_aver_u_b((v16u8) res, dst0); + dst0 = (v16u8) __msa_pckev_b((v16i8) res_vt0, (v16i8) res_vt0); + dst0 = __msa_aver_u_b(dst0, dst_data); - ST4x2_UB(dst0, dst, dst_stride); + ST4x2_UB(dst0, dst, stride); } -static void avc_chroma_hv_and_aver_dst_4x4mul_msa(uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - uint32_t coef_hor0, - uint32_t coef_hor1, - uint32_t coef_ver0, - uint32_t coef_ver1, - int32_t height) +static void avc_chroma_hv_and_aver_dst_4x4_msa(uint8_t *src, uint8_t *dst, + int32_t stride, + uint32_t coef_hor0, + uint32_t coef_hor1, + uint32_t coef_ver0, + uint32_t coef_ver1) { - uint32_t row; + uint32_t tp0, tp1, tp2, tp3; v16u8 src0, src1, src2, src3, src4; - v16u8 dst0, dst1, dst2, dst3; + v16u8 out, dst_data = { 0 }; v8u16 res_hz0, res_hz1, res_hz2, res_hz3; v8u16 res_vt0, res_vt1, res_vt2, res_vt3; v16i8 mask; @@ -1632,45 +1566,78 @@ static void avc_chroma_hv_and_aver_dst_4x4mul_msa(uint8_t *src, v16u8 coeff_hz_vec = (v16u8) __msa_ilvr_b(coeff_hz_vec0, coeff_hz_vec1); v8u16 coeff_vt_vec0 = (v8u16) __msa_fill_h(coef_ver0); v8u16 coeff_vt_vec1 = (v8u16) __msa_fill_h(coef_ver1); - v16u8 res0, res1; mask = LD_SB(&chroma_mask_arr[0]); - src0 = LD_UB(src); - src += src_stride; - - for (row = (height >> 2); row--;) { - LD_UB4(src, src_stride, src1, src2, src3, src4); - src += (4 * src_stride); - - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - - VSHF_B2_UB(src0, src1, src1, src2, mask, mask, src0, src1); - VSHF_B2_UB(src2, src3, src3, src4, mask, mask, src2, src3); - DOTP_UB4_UH(src0, src1, src2, src3, coeff_hz_vec, coeff_hz_vec, - coeff_hz_vec, coeff_hz_vec, res_hz0, res_hz1, res_hz2, - res_hz3); - MUL4(res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_hz2, - coeff_vt_vec1, res_hz3, coeff_vt_vec0, res_vt0, res_vt1, res_vt2, - res_vt3); - ADD2(res_vt0, res_vt1, res_vt2, res_vt3, res_vt0, res_vt1); - SRARI_H2_UH(res_vt0, res_vt1, 6); - SAT_UH2_UH(res_vt0, res_vt1, 7); - PCKEV_B2_UB(res_vt0, res_vt0, res_vt1, res_vt1, res0, res1); - - dst0 = (v16u8) __msa_insve_w((v4i32) dst0, 1, (v4i32) dst1); - dst1 = (v16u8) __msa_insve_w((v4i32) dst2, 1, (v4i32) dst3); - - AVER_UB2_UB(res0, dst0, res1, dst1, dst0, dst1); - - ST4x4_UB(dst0, dst1, 0, 1, 0, 1, dst, dst_stride); - dst += (4 * dst_stride); - src0 = src4; - } + LD_UB5(src, stride, src0, src1, src2, src3, src4); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst_data); + VSHF_B2_UB(src0, src1, src1, src2, mask, mask, src0, src1); + VSHF_B2_UB(src2, src3, src3, src4, mask, mask, src2, src3); + DOTP_UB4_UH(src0, src1, src2, src3, coeff_hz_vec, coeff_hz_vec, + coeff_hz_vec, coeff_hz_vec, res_hz0, res_hz1, res_hz2, + res_hz3); + MUL4(res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_hz2, coeff_vt_vec1, + res_hz3, coeff_vt_vec0, res_vt0, res_vt1, res_vt2, res_vt3); + ADD2(res_vt0, res_vt1, res_vt2, res_vt3, res_vt0, res_vt1); + SRARI_H2_UH(res_vt0, res_vt1, 6); + SAT_UH2_UH(res_vt0, res_vt1, 7); + out = (v16u8) __msa_pckev_b((v16i8) res_vt1, (v16i8) res_vt0); + out = __msa_aver_u_b(out, dst_data); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, stride); +} + +static void avc_chroma_hv_and_aver_dst_4x8_msa(uint8_t *src, uint8_t *dst, + int32_t stride, + uint32_t coef_hor0, + uint32_t coef_hor1, + uint32_t coef_ver0, + uint32_t coef_ver1) +{ + uint32_t tp0, tp1, tp2, tp3; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, res0, res1; + v16u8 dst0 = { 0 }, dst1 = { 0 }; + v8u16 res_hz0, res_hz1, res_hz2, res_hz3, res_hz4, res_hz5, res_hz6, res_hz7; + v8u16 res_vt0, res_vt1, res_vt2, res_vt3, res_vt4, res_vt5, res_vt6, res_vt7; + v16i8 mask; + v16i8 coeff_hz_vec0 = __msa_fill_b(coef_hor0); + v16i8 coeff_hz_vec1 = __msa_fill_b(coef_hor1); + v16u8 coeff_hz_vec = (v16u8) __msa_ilvr_b(coeff_hz_vec0, coeff_hz_vec1); + v8u16 coeff_vt_vec0 = (v8u16) __msa_fill_h(coef_ver0); + v8u16 coeff_vt_vec1 = (v8u16) __msa_fill_h(coef_ver1); + + mask = LD_SB(&chroma_mask_arr[0]); + + LD_UB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + LD_UB4(src, stride, src5, src6, src7, src8); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); + LW4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst1); + VSHF_B2_UB(src0, src1, src1, src2, mask, mask, src0, src1); + VSHF_B2_UB(src2, src3, src3, src4, mask, mask, src2, src3); + VSHF_B2_UB(src4, src5, src5, src6, mask, mask, src4, src5); + VSHF_B2_UB(src6, src7, src7, src8, mask, mask, src6, src7); + DOTP_UB4_UH(src0, src1, src2, src3, coeff_hz_vec, coeff_hz_vec, + coeff_hz_vec, coeff_hz_vec, res_hz0, res_hz1, res_hz2, res_hz3); + DOTP_UB4_UH(src4, src5, src6, src7, coeff_hz_vec, coeff_hz_vec, + coeff_hz_vec, coeff_hz_vec, res_hz4, res_hz5, res_hz6, res_hz7); + MUL4(res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_hz2, coeff_vt_vec1, + res_hz3, coeff_vt_vec0, res_vt0, res_vt1, res_vt2, res_vt3); + MUL4(res_hz4, coeff_vt_vec1, res_hz5, coeff_vt_vec0, res_hz6, coeff_vt_vec1, + res_hz7, coeff_vt_vec0, res_vt4, res_vt5, res_vt6, res_vt7); + ADD2(res_vt0, res_vt1, res_vt2, res_vt3, res_vt0, res_vt1); + ADD2(res_vt4, res_vt5, res_vt6, res_vt7, res_vt2, res_vt3); + SRARI_H4_UH(res_vt0, res_vt1, res_vt2, res_vt3, 6); + SAT_UH4_UH(res_vt0, res_vt1, res_vt2, res_vt3, 7); + PCKEV_B2_UB(res_vt1, res_vt0, res_vt3, res_vt2, res0, res1); + AVER_UB2_UB(res0, dst0, res1, dst1, res0, res1); + ST4x8_UB(res0, res1, dst, stride); } -static void avc_chroma_hv_and_aver_dst_4w_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, +static void avc_chroma_hv_and_aver_dst_4w_msa(uint8_t *src, uint8_t *dst, + int32_t stride, uint32_t coef_hor0, uint32_t coef_hor1, uint32_t coef_ver0, @@ -1678,30 +1645,30 @@ static void avc_chroma_hv_and_aver_dst_4w_msa(uint8_t *src, int32_t src_stride, int32_t height) { if (2 == height) { - avc_chroma_hv_and_aver_dst_4x2_msa(src, src_stride, dst, dst_stride, - coef_hor0, coef_hor1, - coef_ver0, coef_ver1); - } else { - avc_chroma_hv_and_aver_dst_4x4mul_msa(src, src_stride, dst, dst_stride, - coef_hor0, coef_hor1, - coef_ver0, coef_ver1, height); + avc_chroma_hv_and_aver_dst_4x2_msa(src, dst, stride, coef_hor0, + coef_hor1, coef_ver0, coef_ver1); + } else if (4 == height) { + avc_chroma_hv_and_aver_dst_4x4_msa(src, dst, stride, coef_hor0, + coef_hor1, coef_ver0, coef_ver1); + } else if (8 == height) { + avc_chroma_hv_and_aver_dst_4x8_msa(src, dst, stride, coef_hor0, + coef_hor1, coef_ver0, coef_ver1); } } -static void avc_chroma_hv_and_aver_dst_8w_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - uint32_t coef_hor0, - uint32_t coef_hor1, - uint32_t coef_ver0, - uint32_t coef_ver1, - int32_t height) +static void avc_chroma_hv_and_aver_dst_8x4_msa(uint8_t *src, uint8_t *dst, + int32_t stride, + uint32_t coef_hor0, + uint32_t coef_hor1, + uint32_t coef_ver0, + uint32_t coef_ver1) { - uint32_t row; + uint64_t tp0, tp1, tp2, tp3; v16u8 src0, src1, src2, src3, src4, out0, out1; v8u16 res_hz0, res_hz1, res_hz2; v8u16 res_hz3, res_hz4; v8u16 res_vt0, res_vt1, res_vt2, res_vt3; - v16u8 dst0, dst1, dst2, dst3; + v16u8 dst0 = { 0 }, dst1 = { 0 }; v16i8 mask; v16i8 coeff_hz_vec0 = __msa_fill_b(coef_hor0); v16i8 coeff_hz_vec1 = __msa_fill_b(coef_hor1); @@ -1712,40 +1679,114 @@ static void avc_chroma_hv_and_aver_dst_8w_msa(uint8_t *src, int32_t src_stride, mask = LD_SB(&chroma_mask_arr[32]); src0 = LD_UB(src); - src += src_stride; + src += stride; + src0 = (v16u8) __msa_vshf_b(mask, (v16i8) src0, (v16i8) src0); + res_hz0 = __msa_dotp_u_h(src0, coeff_hz_vec); + LD_UB4(src, stride, src1, src2, src3, src4); + src += (4 * stride); + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + VSHF_B2_UB(src1, src1, src2, src2, mask, mask, src1, src2); + VSHF_B2_UB(src3, src3, src4, src4, mask, mask, src3, src4); + DOTP_UB4_UH(src1, src2, src3, src4, coeff_hz_vec, coeff_hz_vec, + coeff_hz_vec, coeff_hz_vec, res_hz1, res_hz2, res_hz3, res_hz4); + MUL4(res_hz1, coeff_vt_vec0, res_hz2, coeff_vt_vec0, res_hz3, coeff_vt_vec0, + res_hz4, coeff_vt_vec0, res_vt0, res_vt1, res_vt2, res_vt3); + res_vt0 += (res_hz0 * coeff_vt_vec1); + res_vt1 += (res_hz1 * coeff_vt_vec1); + res_vt2 += (res_hz2 * coeff_vt_vec1); + res_vt3 += (res_hz3 * coeff_vt_vec1); + SRARI_H4_UH(res_vt0, res_vt1, res_vt2, res_vt3, 6); + SAT_UH4_UH(res_vt0, res_vt1, res_vt2, res_vt3, 7); + PCKEV_B2_UB(res_vt1, res_vt0, res_vt3, res_vt2, out0, out1); + AVER_UB2_UB(out0, dst0, out1, dst1, out0, out1); + ST8x4_UB(out0, out1, dst, stride); +} +static void avc_chroma_hv_and_aver_dst_8x8_msa(uint8_t *src, uint8_t *dst, + int32_t stride, + uint32_t coef_hor0, + uint32_t coef_hor1, + uint32_t coef_ver0, + uint32_t coef_ver1) +{ + uint64_t tp0, tp1, tp2, tp3; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16u8 out0, out1, out2, out3; + v16u8 dst0 = { 0 }, dst1 = { 0 }, dst2 = { 0 }, dst3 = { 0 }; + v8u16 res_hz0, res_hz1, res_hz2, res_hz3, res_hz4; + v8u16 res_hz5, res_hz6, res_hz7, res_hz8; + v8u16 res_vt0, res_vt1, res_vt2, res_vt3; + v8u16 res_vt4, res_vt5, res_vt6, res_vt7; + v16i8 mask; + v16i8 coeff_hz_vec0 = __msa_fill_b(coef_hor0); + v16i8 coeff_hz_vec1 = __msa_fill_b(coef_hor1); + v16u8 coeff_hz_vec = (v16u8) __msa_ilvr_b(coeff_hz_vec0, coeff_hz_vec1); + v8u16 coeff_vt_vec0 = (v8u16) __msa_fill_h(coef_ver0); + v8u16 coeff_vt_vec1 = (v8u16) __msa_fill_h(coef_ver1); + + mask = LD_SB(&chroma_mask_arr[32]); + + LD_UB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + LD_UB4(src, stride, src5, src6, src7, src8); src0 = (v16u8) __msa_vshf_b(mask, (v16i8) src0, (v16i8) src0); + VSHF_B2_UB(src1, src1, src2, src2, mask, mask, src1, src2); + VSHF_B2_UB(src3, src3, src4, src4, mask, mask, src3, src4); + VSHF_B2_UB(src5, src5, src6, src6, mask, mask, src5, src6); + VSHF_B2_UB(src7, src7, src8, src8, mask, mask, src7, src8); res_hz0 = __msa_dotp_u_h(src0, coeff_hz_vec); + DOTP_UB4_UH(src1, src2, src3, src4, coeff_hz_vec, coeff_hz_vec, + coeff_hz_vec, coeff_hz_vec, res_hz1, res_hz2, res_hz3, + res_hz4); + DOTP_UB4_UH(src5, src6, src7, src8, coeff_hz_vec, coeff_hz_vec, + coeff_hz_vec, coeff_hz_vec, res_hz5, res_hz6, res_hz7, res_hz8); + MUL4(res_hz1, coeff_vt_vec0, res_hz2, coeff_vt_vec0, res_hz3, + coeff_vt_vec0, res_hz4, coeff_vt_vec0, res_vt0, res_vt1, res_vt2, + res_vt3); + MUL4(res_hz5, coeff_vt_vec0, res_hz6, coeff_vt_vec0, res_hz7, + coeff_vt_vec0, res_hz8, coeff_vt_vec0, res_vt4, res_vt5, res_vt6, + res_vt7); + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + LD4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst2); + INSERT_D2_UB(tp2, tp3, dst3); + res_vt0 += (res_hz0 * coeff_vt_vec1); + res_vt1 += (res_hz1 * coeff_vt_vec1); + res_vt2 += (res_hz2 * coeff_vt_vec1); + res_vt3 += (res_hz3 * coeff_vt_vec1); + res_vt4 += (res_hz4 * coeff_vt_vec1); + res_vt5 += (res_hz5 * coeff_vt_vec1); + res_vt6 += (res_hz6 * coeff_vt_vec1); + res_vt7 += (res_hz7 * coeff_vt_vec1); + SRARI_H4_UH(res_vt0, res_vt1, res_vt2, res_vt3, 6); + SRARI_H4_UH(res_vt4, res_vt5, res_vt6, res_vt7, 6); + SAT_UH4_UH(res_vt0, res_vt1, res_vt2, res_vt3, 7); + SAT_UH4_UH(res_vt4, res_vt5, res_vt6, res_vt7, 7); + PCKEV_B2_UB(res_vt1, res_vt0, res_vt3, res_vt2, out0, out1); + PCKEV_B2_UB(res_vt5, res_vt4, res_vt7, res_vt6, out2, out3); + AVER_UB2_UB(out0, dst0, out1, dst1, out0, out1); + AVER_UB2_UB(out2, dst2, out3, dst3, out2, out3); + ST8x8_UB(out0, out1, out2, out3, dst, stride); +} - for (row = (height >> 2); row--;) { - LD_UB4(src, src_stride, src1, src2, src3, src4); - src += (4 * src_stride); - - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - VSHF_B2_UB(src1, src1, src2, src2, mask, mask, src1, src2); - VSHF_B2_UB(src3, src3, src4, src4, mask, mask, src3, src4); - DOTP_UB4_UH(src1, src2, src3, src4, coeff_hz_vec, coeff_hz_vec, - coeff_hz_vec, coeff_hz_vec, res_hz1, res_hz2, res_hz3, - res_hz4); - MUL4(res_hz1, coeff_vt_vec0, res_hz2, coeff_vt_vec0, res_hz3, - coeff_vt_vec0, res_hz4, coeff_vt_vec0, res_vt0, res_vt1, res_vt2, - res_vt3); - - res_vt0 += (res_hz0 * coeff_vt_vec1); - res_vt1 += (res_hz1 * coeff_vt_vec1); - res_vt2 += (res_hz2 * coeff_vt_vec1); - res_vt3 += (res_hz3 * coeff_vt_vec1); - - SRARI_H4_UH(res_vt0, res_vt1, res_vt2, res_vt3, 6); - SAT_UH4_UH(res_vt0, res_vt1, res_vt2, res_vt3, 7); - - PCKEV_B2_UB(res_vt1, res_vt0, res_vt3, res_vt2, out0, out1); - PCKEV_D2_UB(dst1, dst0, dst3, dst2, dst0, dst1); - AVER_UB2_UB(out0, dst0, out1, dst1, out0, out1); - ST8x4_UB(out0, out1, dst, dst_stride); - dst += (4 * dst_stride); - - res_hz0 = res_hz4; +static void avc_chroma_hv_and_aver_dst_8w_msa(uint8_t *src, uint8_t *dst, + int32_t stride, + uint32_t coef_hor0, + uint32_t coef_hor1, + uint32_t coef_ver0, + uint32_t coef_ver1, + int32_t height) +{ + if (4 == height) { + avc_chroma_hv_and_aver_dst_8x4_msa(src, dst, stride, coef_hor0, + coef_hor1, coef_ver0, coef_ver1); + } else if (8 == height) { + avc_chroma_hv_and_aver_dst_8x8_msa(src, dst, stride, coef_hor0, + coef_hor1, coef_ver0, coef_ver1); } } @@ -1923,8 +1964,7 @@ void ff_avg_h264_chroma_mc8_msa(uint8_t *dst, uint8_t *src, if (x && y) { - avc_chroma_hv_and_aver_dst_8w_msa(src, stride, dst, - stride, x, (8 - x), y, + avc_chroma_hv_and_aver_dst_8w_msa(src, dst, stride, x, (8 - x), y, (8 - y), height); } else if (x) { avc_chroma_hz_and_aver_dst_8w_msa(src, dst, stride, x, (8 - x), height); @@ -1941,8 +1981,7 @@ void ff_avg_h264_chroma_mc4_msa(uint8_t *dst, uint8_t *src, av_assert2(x < 8 && y < 8 && x >= 0 && y >= 0); if (x && y) { - avc_chroma_hv_and_aver_dst_4w_msa(src, stride, dst, - stride, x, (8 - x), y, + avc_chroma_hv_and_aver_dst_4w_msa(src, dst, stride, x, (8 - x), y, (8 - y), height); } else if (x) { avc_chroma_hz_and_aver_dst_4w_msa(src, dst, stride, x, (8 - x), height); @@ -1961,8 +2000,7 @@ void ff_avg_h264_chroma_mc2_msa(uint8_t *dst, uint8_t *src, av_assert2(x < 8 && y < 8 && x >= 0 && y >= 0); if (x && y) { - avc_chroma_hv_and_aver_dst_2w_msa(src, stride, dst, - stride, x, (8 - x), y, + avc_chroma_hv_and_aver_dst_2w_msa(src, dst, stride, x, (8 - x), y, (8 - y), height); } else if (x) { avc_chroma_hz_and_aver_dst_2w_msa(src, dst, stride, x, (8 - x), height); From a8305b0ea3ccfe00a50cd3312bfcc455c78aacb5 Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Mon, 30 Oct 2017 10:04:55 +0100 Subject: [PATCH 0689/2557] lavfi/testsrc2: fix hang with very small sizes. Move a subtraction to the other side of the equal to avoid overflows. --- libavfilter/vsrc_testsrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index fe0d50aa41a6a..a790974d14213 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -857,8 +857,8 @@ static void test2_fill_picture(AVFilterContext *ctx, AVFrame *frame) uint8_t alpha[256]; r = s->pts; - for (y = ymin; y < ymax - 15; y += 16) { - for (x = xmin; x < xmax - 15; x += 16) { + for (y = ymin; y + 15 < ymax; y += 16) { + for (x = xmin; x + 15 < xmax; x += 16) { if ((x ^ y) & 16) continue; for (i = 0; i < 256; i++) { From bd8f1fa100070952c7a90ac50737dc82787f2b0e Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 31 Oct 2017 12:27:57 -0300 Subject: [PATCH 0690/2557] avcodec/hevc_sei: rename HEVCSEIContext to HEVCSEI Cosmetic change skipped in 0b30cb8dae5e7edb2a5f35900547321499c217f1 by mistake. Signed-off-by: James Almer --- libavcodec/hevc_parse.c | 4 ++-- libavcodec/hevc_parse.h | 2 +- libavcodec/hevc_parser.c | 6 +++--- libavcodec/hevc_sei.c | 16 ++++++++-------- libavcodec/hevc_sei.h | 8 ++++---- libavcodec/hevcdec.h | 3 +-- libavcodec/mediacodecdec.c | 2 +- 7 files changed, 20 insertions(+), 21 deletions(-) diff --git a/libavcodec/hevc_parse.c b/libavcodec/hevc_parse.c index 1122a60af3990..b1b27eef09cd2 100644 --- a/libavcodec/hevc_parse.c +++ b/libavcodec/hevc_parse.c @@ -22,7 +22,7 @@ #include "hevc_parse.h" static int hevc_decode_nal_units(const uint8_t *buf, int buf_size, HEVCParamSets *ps, - HEVCSEIContext *sei, int is_nalff, int nal_length_size, + HEVCSEI *sei, int is_nalff, int nal_length_size, int err_recognition, int apply_defdispwin, void *logctx) { int i; @@ -75,7 +75,7 @@ static int hevc_decode_nal_units(const uint8_t *buf, int buf_size, HEVCParamSets } int ff_hevc_decode_extradata(const uint8_t *data, int size, HEVCParamSets *ps, - HEVCSEIContext *sei, int *is_nalff, int *nal_length_size, + HEVCSEI *sei, int *is_nalff, int *nal_length_size, int err_recognition, int apply_defdispwin, void *logctx) { int ret = 0; diff --git a/libavcodec/hevc_parse.h b/libavcodec/hevc_parse.h index 02e1d5b324bf3..4ab96ab1cb68f 100644 --- a/libavcodec/hevc_parse.h +++ b/libavcodec/hevc_parse.h @@ -30,7 +30,7 @@ #include "hevc_sei.h" int ff_hevc_decode_extradata(const uint8_t *data, int size, HEVCParamSets *ps, - HEVCSEIContext *sei, int *is_nalff, int *nal_length_size, + HEVCSEI *sei, int *is_nalff, int *nal_length_size, int err_recognition, int apply_defdispwin, void *logctx); #endif /* AVCODEC_HEVC_PARSE_H */ diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c index dc63c6b95433b..ff7e8a49d66d0 100644 --- a/libavcodec/hevc_parser.c +++ b/libavcodec/hevc_parser.c @@ -40,7 +40,7 @@ typedef struct HEVCParserContext { H2645Packet pkt; HEVCParamSets ps; - HEVCSEIContext sei; + HEVCSEI sei; SliceHeader sh; int parsed_extradata; @@ -54,7 +54,7 @@ static int hevc_parse_slice_header(AVCodecParserContext *s, H2645NAL *nal, { HEVCParserContext *ctx = s->priv_data; HEVCParamSets *ps = &ctx->ps; - HEVCSEIContext *sei = &ctx->sei; + HEVCSEI *sei = &ctx->sei; SliceHeader *sh = &ctx->sh; GetBitContext *gb = &nal->gb; const HEVCWindow *ow; @@ -180,7 +180,7 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, { HEVCParserContext *ctx = s->priv_data; HEVCParamSets *ps = &ctx->ps; - HEVCSEIContext *sei = &ctx->sei; + HEVCSEI *sei = &ctx->sei; int is_global = buf == avctx->extradata; int ret, i; diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index d0f9966a295c7..1ea67836b0992 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -124,7 +124,7 @@ static int decode_nal_sei_display_orientation(HEVCSEIDisplayOrientation *s, GetB return 0; } -static int decode_nal_sei_pic_timing(HEVCSEIContext *s, GetBitContext *gb, const HEVCParamSets *ps, +static int decode_nal_sei_pic_timing(HEVCSEI *s, GetBitContext *gb, const HEVCParamSets *ps, void *logctx, int size) { HEVCSEIPictureTiming *h = &s->picture_timing; @@ -205,7 +205,7 @@ static int decode_registered_user_data_closed_caption(HEVCSEIA53Caption *s, GetB return 0; } -static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCSEIContext *s, GetBitContext *gb, +static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCSEI *s, GetBitContext *gb, int size) { uint32_t country_code; @@ -236,7 +236,7 @@ static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCSEIContext *s, GetB return 0; } -static int decode_nal_sei_active_parameter_sets(HEVCSEIContext *s, GetBitContext *gb, void *logctx) +static int decode_nal_sei_active_parameter_sets(HEVCSEI *s, GetBitContext *gb, void *logctx) { int num_sps_ids_minus1; int i; @@ -272,7 +272,7 @@ static int decode_nal_sei_alternative_transfer(HEVCSEIAlternativeTransfer *s, Ge return 0; } -static int decode_nal_sei_prefix(GetBitContext *gb, HEVCSEIContext *s, const HEVCParamSets *ps, +static int decode_nal_sei_prefix(GetBitContext *gb, HEVCSEI *s, const HEVCParamSets *ps, int type, int size, void *logctx) { switch (type) { @@ -301,7 +301,7 @@ static int decode_nal_sei_prefix(GetBitContext *gb, HEVCSEIContext *s, const HEV } } -static int decode_nal_sei_suffix(GetBitContext *gb, HEVCSEIContext *s, +static int decode_nal_sei_suffix(GetBitContext *gb, HEVCSEI *s, int type, int size, void *logctx) { switch (type) { @@ -314,7 +314,7 @@ static int decode_nal_sei_suffix(GetBitContext *gb, HEVCSEIContext *s, } } -static int decode_nal_sei_message(GetBitContext *gb, HEVCSEIContext *s, +static int decode_nal_sei_message(GetBitContext *gb, HEVCSEI *s, const HEVCParamSets *ps, int nal_unit_type, void *logctx) { @@ -344,7 +344,7 @@ static int more_rbsp_data(GetBitContext *gb) return get_bits_left(gb) > 0 && show_bits(gb, 8) != 0x80; } -int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEIContext *s, +int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, const HEVCParamSets *ps, int type) { int ret; @@ -357,7 +357,7 @@ int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEIContext *s, return 1; } -void ff_hevc_reset_sei(HEVCSEIContext *s) +void ff_hevc_reset_sei(HEVCSEI *s) { s->a53_caption.a53_caption_size = 0; av_freep(&s->a53_caption.a53_caption); diff --git a/libavcodec/hevc_sei.h b/libavcodec/hevc_sei.h index 1b522227ecfa6..8daf2e3f2f763 100644 --- a/libavcodec/hevc_sei.h +++ b/libavcodec/hevc_sei.h @@ -106,7 +106,7 @@ typedef struct HEVCSEIAlternativeTransfer { int preferred_transfer_characteristics; } HEVCSEIAlternativeTransfer; -typedef struct HEVCSEIContext { +typedef struct HEVCSEI { HEVCSEIPictureHash picture_hash; HEVCSEIFramePacking frame_packing; HEVCSEIDisplayOrientation display_orientation; @@ -116,11 +116,11 @@ typedef struct HEVCSEIContext { HEVCSEIContentLight content_light; int active_seq_parameter_set_id; HEVCSEIAlternativeTransfer alternative_transfer; -} HEVCSEIContext; +} HEVCSEI; struct HEVCParamSets; -int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEIContext *s, +int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, const struct HEVCParamSets *ps, int type); /** @@ -130,6 +130,6 @@ int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEIContext *s, * * @param s HEVCContext. */ -void ff_hevc_reset_sei(HEVCSEIContext *s); +void ff_hevc_reset_sei(HEVCSEI *s); #endif /* AVCODEC_HEVC_SEI_H */ diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index ada2903222004..1bfdaef73ffef 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -405,6 +405,7 @@ typedef struct HEVCContext { uint8_t *sao_pixel_buffer_v[3]; HEVCParamSets ps; + HEVCSEI sei; AVBufferPool *tab_mvf_pool; AVBufferPool *rpl_tab_pool; @@ -480,8 +481,6 @@ typedef struct HEVCContext { int nal_length_size; ///< Number of bytes used for nal length (1, 2 or 4) int nuh_layer_id; - - HEVCSEIContext sei; } HEVCContext; /** diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 6962ce2474f52..0cf9419ea32b7 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -182,7 +182,7 @@ static int hevc_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format) int ret; HEVCParamSets ps; - HEVCSEIContext sei; + HEVCSEI sei; const HEVCVPS *vps = NULL; const HEVCPPS *pps = NULL; From 9e2b0f32e905cc51d5e559aa4f80970e55438049 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 31 Oct 2017 12:38:36 -0300 Subject: [PATCH 0691/2557] avcodec/hevc_sei: reorder some parameters in static functions Cosmetic change skipped in 0b30cb8dae5e7edb2a5f35900547321499c217f1 by mistake. Signed-off-by: James Almer --- libavcodec/hevc_sei.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 1ea67836b0992..6ce1669820872 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -272,8 +272,8 @@ static int decode_nal_sei_alternative_transfer(HEVCSEIAlternativeTransfer *s, Ge return 0; } -static int decode_nal_sei_prefix(GetBitContext *gb, HEVCSEI *s, const HEVCParamSets *ps, - int type, int size, void *logctx) +static int decode_nal_sei_prefix(GetBitContext *gb, void *logctx, HEVCSEI *s, + const HEVCParamSets *ps, int type, int size) { switch (type) { case 256: // Mismatched value from HM 8.1 @@ -301,8 +301,8 @@ static int decode_nal_sei_prefix(GetBitContext *gb, HEVCSEI *s, const HEVCParamS } } -static int decode_nal_sei_suffix(GetBitContext *gb, HEVCSEI *s, - int type, int size, void *logctx) +static int decode_nal_sei_suffix(GetBitContext *gb, void *logctx, HEVCSEI *s, + int type, int size) { switch (type) { case HEVC_SEI_TYPE_DECODED_PICTURE_HASH: @@ -314,9 +314,8 @@ static int decode_nal_sei_suffix(GetBitContext *gb, HEVCSEI *s, } } -static int decode_nal_sei_message(GetBitContext *gb, HEVCSEI *s, - const HEVCParamSets *ps, int nal_unit_type, - void *logctx) +static int decode_nal_sei_message(GetBitContext *gb, void *logctx, HEVCSEI *s, + const HEVCParamSets *ps, int nal_unit_type) { int payload_type = 0; int payload_size = 0; @@ -333,9 +332,9 @@ static int decode_nal_sei_message(GetBitContext *gb, HEVCSEI *s, payload_size += byte; } if (nal_unit_type == HEVC_NAL_SEI_PREFIX) { - return decode_nal_sei_prefix(gb, s, ps, payload_type, payload_size, logctx); + return decode_nal_sei_prefix(gb, logctx, s, ps, payload_type, payload_size); } else { /* nal_unit_type == NAL_SEI_SUFFIX */ - return decode_nal_sei_suffix(gb, s, payload_type, payload_size, logctx); + return decode_nal_sei_suffix(gb, logctx, s, payload_type, payload_size); } } @@ -350,7 +349,7 @@ int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, int ret; do { - ret = decode_nal_sei_message(gb, s, ps, type, logctx); + ret = decode_nal_sei_message(gb, logctx, s, ps, type); if (ret < 0) return ret; } while (more_rbsp_data(gb)); From 37f4a093f7f95241e4fcd582758504491e85e488 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 31 Oct 2017 16:18:32 -0300 Subject: [PATCH 0692/2557] avcodec/vp9_superframe_bsf: allocate cache of packets during init Also use av_packet_move_ref() to cache them instead of copying pointers. Fixes invalid reads since e1bc3f4396ade6033787717d3650fb62663eae8. Signed-off-by: James Almer --- libavcodec/vp9_superframe_bsf.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/libavcodec/vp9_superframe_bsf.c b/libavcodec/vp9_superframe_bsf.c index 121d3a3d81cc4..dea2cc232f979 100644 --- a/libavcodec/vp9_superframe_bsf.c +++ b/libavcodec/vp9_superframe_bsf.c @@ -147,8 +147,8 @@ static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out) goto done; } - s->cache[s->n_cache++] = in; - in = NULL; + av_packet_move_ref(s->cache[s->n_cache++], in); + if (invisible) { res = AVERROR(EAGAIN); goto done; @@ -164,7 +164,7 @@ static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out) goto done; for (n = 0; n < s->n_cache; n++) - av_packet_free(&s->cache[n]); + av_packet_unref(s->cache[n]); s->n_cache = 0; done: @@ -174,13 +174,28 @@ static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out) return res; } +static int vp9_superframe_init(AVBSFContext *ctx) +{ + VP9BSFContext *s = ctx->priv_data; + int n; + + // alloc cached data + for (n = 0; n < MAX_CACHE; n++) { + s->cache[n] = av_packet_alloc(); + if (!s->cache[n]) + return AVERROR(ENOMEM); + } + + return 0; +} + static void vp9_superframe_close(AVBSFContext *ctx) { VP9BSFContext *s = ctx->priv_data; int n; // free cached data - for (n = 0; n < s->n_cache; n++) + for (n = 0; n < MAX_CACHE; n++) av_packet_free(&s->cache[n]); } @@ -192,6 +207,7 @@ const AVBitStreamFilter ff_vp9_superframe_bsf = { .name = "vp9_superframe", .priv_data_size = sizeof(VP9BSFContext), .filter = vp9_superframe_filter, + .init = vp9_superframe_init, .close = vp9_superframe_close, .codec_ids = codec_ids, }; From e6055af025c1f96b47ac71107dca6169ed430824 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 27 Oct 2017 18:18:18 +0200 Subject: [PATCH 0693/2557] avfilter: pass correct argument to helper function Signed-off-by: Paul B Mahol --- libavfilter/avfilter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index bc9e60bb851e6..b98b32bacb51b 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -1532,7 +1532,7 @@ int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, return 0; if (link->status_in) min = FFMIN(min, ff_framequeue_queued_samples(&link->fifo)); - ret = take_samples(link, min, link->max_samples, &frame); + ret = take_samples(link, min, max, &frame); if (ret < 0) return ret; consume_update(link, frame); From d0920da029c54c372c1daa93c6d976f2145daf62 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 27 Oct 2017 17:59:29 +0200 Subject: [PATCH 0694/2557] avfilter/af_join: switch to activate Fixes #6780. Signed-off-by: Paul B Mahol --- libavfilter/af_join.c | 98 ++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/libavfilter/af_join.c b/libavfilter/af_join.c index 33df6856910b2..cf5131e8dcaf0 100644 --- a/libavfilter/af_join.c +++ b/libavfilter/af_join.c @@ -32,6 +32,7 @@ #include "audio.h" #include "avfilter.h" #include "formats.h" +#include "filters.h" #include "internal.h" typedef struct ChannelMap { @@ -78,34 +79,6 @@ static const AVOption join_options[] = { AVFILTER_DEFINE_CLASS(join); -static int try_push_frame(AVFilterContext *ctx); - -static int filter_frame(AVFilterLink *link, AVFrame *frame) -{ - AVFilterContext *ctx = link->dst; - JoinContext *s = ctx->priv; - int i, j; - - for (i = 0; i < ctx->nb_inputs; i++) - if (link == ctx->inputs[i]) - break; - av_assert0(i < ctx->nb_inputs); - av_assert0(!s->input_frames[i]); - s->input_frames[i] = frame; - - /* request the same number of samples on all inputs */ - /* FIXME that means a frame arriving asynchronously on a different input - will not have the requested number of samples */ - if (i == 0) { - int nb_samples = s->input_frames[0]->nb_samples; - - for (j = 1; !i && j < ctx->nb_inputs; j++) - ctx->inputs[j]->request_samples = nb_samples; - } - - return try_push_frame(ctx); -} - static int parse_maps(AVFilterContext *ctx) { JoinContext *s = ctx->priv; @@ -220,9 +193,6 @@ static av_cold int join_init(AVFilterContext *ctx) pad.name = av_strdup(name); if (!pad.name) return AVERROR(ENOMEM); - pad.filter_frame = filter_frame; - - pad.needs_fifo = 1; if ((ret = ff_insert_inpad(ctx, i, &pad)) < 0) { av_freep(&pad.name); @@ -390,21 +360,6 @@ static int join_config_output(AVFilterLink *outlink) return ret; } -static int join_request_frame(AVFilterLink *outlink) -{ - AVFilterContext *ctx = outlink->src; - JoinContext *s = ctx->priv; - int i; - - /* get a frame on each input */ - for (i = 0; i < ctx->nb_inputs; i++) { - AVFilterLink *inlink = ctx->inputs[i]; - if (!s->input_frames[i]) - return ff_request_frame(inlink); - } - return 0; -} - static int try_push_frame(AVFilterContext *ctx) { AVFilterLink *outlink = ctx->outputs[0]; @@ -420,6 +375,8 @@ static int try_push_frame(AVFilterContext *ctx) return 0; nb_samples = FFMIN(nb_samples, s->input_frames[i]->nb_samples); } + if (!nb_samples) + return 0; /* setup the output frame */ frame = av_frame_alloc(); @@ -508,12 +465,58 @@ static int try_push_frame(AVFilterContext *ctx) return ret; } +static int activate(AVFilterContext *ctx) +{ + JoinContext *s = ctx->priv; + int i, ret, status; + int nb_samples = 0; + int64_t pts; + + if (!s->input_frames[0]) { + ret = ff_inlink_consume_frame(ctx->inputs[0], &s->input_frames[0]); + if (ret < 0) { + return ret; + } else if (ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) { + ff_outlink_set_status(ctx->outputs[0], status, pts); + return 0; + } else { + if (ff_outlink_frame_wanted(ctx->outputs[0]) && !s->input_frames[0]) { + ff_inlink_request_frame(ctx->inputs[0]); + return 0; + } + } + } + + nb_samples = s->input_frames[0]->nb_samples; + + for (i = 1; i < ctx->nb_inputs && nb_samples > 0; i++) { + if (s->input_frames[i]) + continue; + + if (ff_inlink_check_available_samples(ctx->inputs[i], nb_samples) > 0) { + ret = ff_inlink_consume_samples(ctx->inputs[i], nb_samples, nb_samples, &s->input_frames[i]); + if (ret < 0) { + return ret; + } else if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) { + ff_outlink_set_status(ctx->outputs[0], status, pts); + return 0; + } + } else { + if (ff_outlink_frame_wanted(ctx->outputs[0])) { + ff_inlink_request_frame(ctx->inputs[i]); + return 0; + } + } + } + + return try_push_frame(ctx); +} + static const AVFilterPad avfilter_af_join_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, .config_props = join_config_output, - .request_frame = join_request_frame, }, { NULL } }; @@ -526,6 +529,7 @@ AVFilter ff_af_join = { .priv_class = &join_class, .init = join_init, .uninit = join_uninit, + .activate = activate, .query_formats = join_query_formats, .inputs = NULL, .outputs = avfilter_af_join_outputs, From 05d77587cb7d0a4e349c5320eb7c0b48610cf6bf Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 31 Oct 2017 16:21:33 -0700 Subject: [PATCH 0695/2557] lavc/videotoolbox: fix out-of-bounds memory access during hvcc creation Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 3bdc1f7d1f29b..ecb2502c1f3b8 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -131,7 +131,7 @@ CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx) int vt_extradata_size = 23 + 5 + vps->data_size + 5 + sps->data_size + 3; uint8_t *vt_extradata; - for (i = 0; i < MAX_PPS_COUNT; i++) { + for (i = 0; i < HEVC_MAX_PPS_COUNT; i++) { if (h->ps.pps_list[i]) { const HEVCPPS *pps = (const HEVCPPS *)h->ps.pps_list[i]->data; vt_extradata_size += 2 + pps->data_size; @@ -258,7 +258,7 @@ CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx) HEVC_NAL_PPS & 0x3f); AV_WB16(p + 1, num_pps); p += 3; - for (i = 0; i < MAX_PPS_COUNT; i++) { + for (i = 0; i < HEVC_MAX_PPS_COUNT; i++) { if (h->ps.pps_list[i]) { const HEVCPPS *pps = (const HEVCPPS *)h->ps.pps_list[i]->data; AV_WB16(p, pps->data_size); From 7a02b364b68c0bf7f065f5c217fae458f0efdb8d Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 31 Oct 2017 20:29:53 -0300 Subject: [PATCH 0696/2557] avcodec/vp9_superframe_bsf: cache packets by creating new references rather than moving them Should hopefully fix the invalid reads after free introduced in e1bc3f4396ade6033787717d3650fb62663eae8 for all targets. Signed-off-by: James Almer --- libavcodec/vp9_superframe_bsf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/vp9_superframe_bsf.c b/libavcodec/vp9_superframe_bsf.c index dea2cc232f979..ceead5559cb84 100644 --- a/libavcodec/vp9_superframe_bsf.c +++ b/libavcodec/vp9_superframe_bsf.c @@ -147,7 +147,9 @@ static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out) goto done; } - av_packet_move_ref(s->cache[s->n_cache++], in); + res = av_packet_ref(s->cache[s->n_cache++], in); + if (res < 0) + goto done; if (invisible) { res = AVERROR(EAGAIN); From ff994c2aaa0a9bbe49cfcdb175f1f6782f7856ed Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sat, 28 Oct 2017 22:52:02 +0200 Subject: [PATCH 0697/2557] lswr/rematrix: Support s32p. Fixes ticket #6785. --- libswresample/rematrix.c | 19 ++++++++++++++----- libswresample/version.h | 2 +- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c index 66a43c16c165a..9fcfff1318c56 100644 --- a/libswresample/rematrix.c +++ b/libswresample/rematrix.c @@ -445,14 +445,23 @@ av_cold int swri_rematrix_init(SwrContext *s){ s->mix_2_1_f = (mix_2_1_func_type*)sum2_double; s->mix_any_f = (mix_any_func_type*)get_mix_any_func_double(s); }else if(s->midbuf.fmt == AV_SAMPLE_FMT_S32P){ - // Only for dithering currently -// s->native_matrix = av_calloc(nb_in * nb_out, sizeof(double)); s->native_one = av_mallocz(sizeof(int)); if (!s->native_one) return AVERROR(ENOMEM); -// for (i = 0; i < nb_out; i++) -// for (j = 0; j < nb_in; j++) -// ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j]; + s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int)); + if (!s->native_matrix) { + av_freep(&s->native_one); + return AVERROR(ENOMEM); + } + for (i = 0; i < nb_out; i++) { + double rem = 0; + + for (j = 0; j < nb_in; j++) { + double target = s->matrix[i][j] * 32768 + rem; + ((int*)s->native_matrix)[i * nb_in + j] = lrintf(target); + rem += target - ((int*)s->native_matrix)[i * nb_in + j]; + } + } *((int*)s->native_one) = 32768; s->mix_1_1_f = (mix_1_1_func_type*)copy_s32; s->mix_2_1_f = (mix_2_1_func_type*)sum2_s32; diff --git a/libswresample/version.h b/libswresample/version.h index 54dfd71e42d1e..2640b10675948 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -30,7 +30,7 @@ #define LIBSWRESAMPLE_VERSION_MAJOR 3 #define LIBSWRESAMPLE_VERSION_MINOR 0 -#define LIBSWRESAMPLE_VERSION_MICRO 100 +#define LIBSWRESAMPLE_VERSION_MICRO 101 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ LIBSWRESAMPLE_VERSION_MINOR, \ From 6854dd70391fb9d4f3c91fdd12ac07aface61ad9 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Fri, 27 Oct 2017 17:21:17 +0530 Subject: [PATCH 0698/2557] avcodec/mips: Improve hevc bi weighted copy, hz and vt mc msa functions Pack the data to half word before clipping. Use immediate unsigned saturation for clip to max saving one vector register. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_biw_msa.c | 1570 +++++++++++++++-------------- 1 file changed, 793 insertions(+), 777 deletions(-) diff --git a/libavcodec/mips/hevc_mc_biw_msa.c b/libavcodec/mips/hevc_mc_biw_msa.c index 458e73d865b9b..75c1c7a15855d 100644 --- a/libavcodec/mips/hevc_mc_biw_msa.c +++ b/libavcodec/mips/hevc_mc_biw_msa.c @@ -29,8 +29,10 @@ static const uint8_t ff_hevc_mask_arr[16 * 2] __attribute__((aligned(0x40))) = { }; #define HEVC_BIW_RND_CLIP2(in0, in1, vec0, vec1, wgt, rnd, offset, \ - out0_r, out1_r, out0_l, out1_l) \ + out0, out1) \ { \ + v4i32 out0_r, out1_r, out0_l, out1_l; \ + \ ILVR_H2_SW(in0, vec0, in1, vec1, out0_r, out1_r); \ ILVL_H2_SW(in0, vec0, in1, vec1, out0_l, out1_l); \ \ @@ -40,37 +42,41 @@ static const uint8_t ff_hevc_mask_arr[16 * 2] __attribute__((aligned(0x40))) = { out1_l = __msa_dpadd_s_w(offset, (v8i16) out1_l, (v8i16) wgt); \ \ SRAR_W4_SW(out0_r, out1_r, out0_l, out1_l, rnd); \ - \ - out0_r = CLIP_SW_0_255(out0_r); \ - out1_r = CLIP_SW_0_255(out1_r); \ - out0_l = CLIP_SW_0_255(out0_l); \ - out1_l = CLIP_SW_0_255(out1_l); \ + PCKEV_H2_SH(out0_l, out0_r, out1_l, out1_r, out0, out1); \ + CLIP_SH2_0_255(out0, out1); \ } -#define HEVC_BIW_RND_CLIP4(in0, in1, in2, in3, vec0, vec1, vec2, vec3, \ - wgt, rnd, offset, \ - out0_r, out1_r, out2_r, out3_r, \ - out0_l, out1_l, out2_l, out3_l) \ -{ \ - HEVC_BIW_RND_CLIP2(in0, in1, vec0, vec1, wgt, rnd, offset, \ - out0_r, out1_r, out0_l, out1_l) \ - HEVC_BIW_RND_CLIP2(in2, in3, vec2, vec3, wgt, rnd, offset, \ - out2_r, out3_r, out2_l, out3_l) \ +#define HEVC_BIW_RND_CLIP4(in0, in1, in2, in3, vec0, vec1, vec2, vec3, \ + wgt, rnd, offset, out0, out1, out2, out3) \ +{ \ + HEVC_BIW_RND_CLIP2(in0, in1, vec0, vec1, wgt, rnd, offset, out0, out1); \ + HEVC_BIW_RND_CLIP2(in2, in3, vec2, vec3, wgt, rnd, offset, out2, out3); \ } -#define HEVC_BI_RND_CLIP2(in0, in1, vec0, vec1, rnd_val, out0, out1) \ -{ \ - ADDS_SH2_SH(vec0, in0, vec1, in1, out0, out1); \ - SRARI_H2_SH(out0, out1, rnd_val); \ - CLIP_SH2_0_255(out0, out1); \ +#define HEVC_BIW_RND_CLIP2_MAX_SATU(in0, in1, vec0, vec1, wgt, rnd, \ + offset, out0, out1) \ +{ \ + v4i32 out0_r, out1_r, out0_l, out1_l; \ + \ + ILVR_H2_SW(in0, vec0, in1, vec1, out0_r, out1_r); \ + ILVL_H2_SW(in0, vec0, in1, vec1, out0_l, out1_l); \ + out0_r = __msa_dpadd_s_w(offset, (v8i16) out0_r, (v8i16) wgt); \ + out1_r = __msa_dpadd_s_w(offset, (v8i16) out1_r, (v8i16) wgt); \ + out0_l = __msa_dpadd_s_w(offset, (v8i16) out0_l, (v8i16) wgt); \ + out1_l = __msa_dpadd_s_w(offset, (v8i16) out1_l, (v8i16) wgt); \ + SRAR_W4_SW(out0_r, out1_r, out0_l, out1_l, rnd); \ + PCKEV_H2_SH(out0_l, out0_r, out1_l, out1_r, out0, out1); \ + CLIP_SH2_0_255_MAX_SATU(out0, out1); \ } -#define HEVC_BI_RND_CLIP4(in0, in1, in2, in3, \ - vec0, vec1, vec2, vec3, rnd_val, \ - out0, out1, out2, out3) \ -{ \ - HEVC_BI_RND_CLIP2(in0, in1, vec0, vec1, rnd_val, out0, out1); \ - HEVC_BI_RND_CLIP2(in2, in3, vec2, vec3, rnd_val, out2, out3); \ +#define HEVC_BIW_RND_CLIP4_MAX_SATU(in0, in1, in2, in3, vec0, vec1, vec2, \ + vec3, wgt, rnd, offset, out0, out1, \ + out2, out3) \ +{ \ + HEVC_BIW_RND_CLIP2_MAX_SATU(in0, in1, vec0, vec1, wgt, rnd, offset, \ + out0, out1); \ + HEVC_BIW_RND_CLIP2_MAX_SATU(in2, in3, vec2, vec3, wgt, rnd, offset, \ + out2, out3); \ } static void hevc_biwgt_copy_4w_msa(uint8_t *src0_ptr, @@ -86,93 +92,77 @@ static void hevc_biwgt_copy_4w_msa(uint8_t *src0_ptr, int32_t offset1, int32_t rnd_val) { + uint32_t loop_cnt, tp0, tp1, tp2, tp3; + uint64_t tpd0, tpd1, tpd2, tpd3; int32_t offset, weight; + v16u8 out0, out1; v16i8 zero = { 0 }; - v4i32 weight_vec, offset_vec, rnd_vec; + v16i8 src0 = { 0 }, src1 = { 0 }; + v8i16 in0 = { 0 }, in1 = { 0 }, in2 = { 0 }, in3 = { 0 }; + v8i16 dst0, dst1, dst2, dst3, weight_vec; + v4i32 dst0_r, dst0_l, offset_vec, rnd_vec; offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); offset_vec = __msa_fill_w(offset); - weight_vec = __msa_fill_w(weight); + weight_vec = (v8i16) __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); if (2 == height) { - v16i8 src0, src1; - v8i16 in0, in1, dst0; - v4i32 dst0_r, dst0_l; - - LD_SB2(src0_ptr, src_stride, src0, src1); - LD_SH2(src1_ptr, src2_stride, in0, in1); - in0 = (v8i16) __msa_ilvr_d((v2i64) in1, (v2i64) in0); - src0 = (v16i8) __msa_ilvr_w((v4i32) src1, (v4i32) src0); + LW2(src0_ptr, src_stride, tp0, tp1); + INSERT_W2_SB(tp0, tp1, src0); + LD2(src1_ptr, src2_stride, tpd0, tpd1); + INSERT_D2_SH(tpd0, tpd1, in0); dst0 = (v8i16) __msa_ilvr_b(zero, src0); dst0 <<= 6; ILVRL_H2_SW(dst0, in0, dst0_r, dst0_l); - dst0_r = __msa_dpadd_s_w(offset_vec, (v8i16) dst0_r, - (v8i16) weight_vec); - dst0_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst0_l, - (v8i16) weight_vec); + dst0_r = __msa_dpadd_s_w(offset_vec, (v8i16) dst0_r, weight_vec); + dst0_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst0_l, weight_vec); SRAR_W2_SW(dst0_r, dst0_l, rnd_vec); - dst0_r = CLIP_SW_0_255(dst0_r); - dst0_l = CLIP_SW_0_255(dst0_l); - - HEVC_PCK_SW_SB2(dst0_l, dst0_r, dst0_r); - ST4x2_UB(dst0_r, dst, dst_stride); + dst0 = (v8i16) __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); + dst0 = CLIP_SH_0_255_MAX_SATU(dst0); + out0 = (v16u8) __msa_pckev_b((v16i8) dst0, (v16i8) dst0); + ST4x2_UB(out0, dst, dst_stride); } else if (4 == height) { - v16i8 src0, src1, src2, src3; - v8i16 in0, in1, in2, in3; - v8i16 dst0, dst1; - v4i32 dst0_r, dst1_r, dst0_l, dst1_l; - - LD_SB4(src0_ptr, src_stride, src0, src1, src2, src3); - LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); - ILVR_D2_SH(in1, in0, in3, in2, in0, in1); - ILVR_W2_SB(src1, src0, src3, src2, src0, src1); - ILVR_B2_SH(zero, src0, zero, src1, dst0, dst1); - dst0 <<= 6; - dst1 <<= 6; - HEVC_BIW_RND_CLIP2(dst0, dst1, in0, in1, - weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst0_l, dst1_l); - - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST4x4_UB(dst0_r, dst0_r, 0, 1, 2, 3, dst, dst_stride); + LW4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); + INSERT_W4_SB(tp0, tp1, tp2, tp3, src0); + LD4(src1_ptr, src2_stride, tpd0, tpd1, tpd2, tpd3); + INSERT_D2_SH(tpd0, tpd1, in0); + INSERT_D2_SH(tpd2, tpd3, in1); + ILVRL_B2_SH(zero, src0, dst0, dst1); + SLLI_2V(dst0, dst1, 6); + HEVC_BIW_RND_CLIP2_MAX_SATU(dst0, dst1, in0, in1, weight_vec, rnd_vec, + offset_vec, dst0, dst1); + out0 = (v16u8) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); + ST4x4_UB(out0, out0, 0, 1, 2, 3, dst, dst_stride); } else if (0 == height % 8) { - uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7; - v8i16 in0, in1, in2, in3, in4, in5, in6, in7; - v8i16 dst0, dst1, dst2, dst3; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; - for (loop_cnt = (height >> 3); loop_cnt--;) { - LD_SB8(src0_ptr, src_stride, - src0, src1, src2, src3, src4, src5, src6, src7); - src0_ptr += (8 * src_stride); - LD_SH8(src1_ptr, src2_stride, - in0, in1, in2, in3, in4, in5, in6, in7); - src1_ptr += (8 * src2_stride); - - ILVR_D2_SH(in1, in0, in3, in2, in0, in1); - ILVR_D2_SH(in5, in4, in7, in6, in2, in3); - ILVR_W4_SB(src1, src0, src3, src2, src5, src4, src7, src6, - src0, src1, src2, src3); - ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - dst0, dst1, dst2, dst3); - + LW4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); + src0_ptr += 4 * src_stride; + INSERT_W4_SB(tp0, tp1, tp2, tp3, src0); + LW4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); + src0_ptr += 4 * src_stride; + INSERT_W4_SB(tp0, tp1, tp2, tp3, src1); + LD4(src1_ptr, src2_stride, tpd0, tpd1, tpd2, tpd3); + src1_ptr += (4 * src2_stride); + INSERT_D2_SH(tpd0, tpd1, in0); + INSERT_D2_SH(tpd2, tpd3, in1); + LD4(src1_ptr, src2_stride, tpd0, tpd1, tpd2, tpd3); + src1_ptr += (4 * src2_stride); + INSERT_D2_SH(tpd0, tpd1, in2); + INSERT_D2_SH(tpd2, tpd3, in3); + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); SLLI_4V(dst0, dst1, dst2, dst3, 6); - HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, - in0, in1, in2, in3, - weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST4x8_UB(dst0_r, dst1_r, dst, dst_stride); + HEVC_BIW_RND_CLIP4_MAX_SATU(dst0, dst1, dst2, dst3, in0, in1, in2, + in3, weight_vec, rnd_vec, offset_vec, + dst0, dst1, dst2, dst3); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + ST4x8_UB(out0, out1, dst, dst_stride); dst += (8 * dst_stride); } } @@ -193,11 +183,12 @@ static void hevc_biwgt_copy_6w_msa(uint8_t *src0_ptr, { uint32_t loop_cnt; int32_t offset, weight; + uint64_t tp0, tp1, tp2, tp3; + v16u8 out0, out1; v16i8 zero = { 0 }; - v16i8 src0, src1, src2, src3; + v16i8 src0 = { 0 }, src1 = { 0 }; v8i16 in0, in1, in2, in3; v8i16 dst0, dst1, dst2, dst3; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; v4i32 offset_vec, weight_vec, rnd_vec; offset = (offset0 + offset1) << rnd_val; @@ -209,23 +200,21 @@ static void hevc_biwgt_copy_6w_msa(uint8_t *src0_ptr, rnd_vec = __msa_fill_w(rnd_val + 1); for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB4(src0_ptr, src_stride, src0, src1, src2, src3); + LD4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); src0_ptr += (4 * src_stride); + INSERT_D2_SB(tp0, tp1, src0); + INSERT_D2_SB(tp2, tp3, src1); LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); src1_ptr += (4 * src2_stride); - ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - dst0, dst1, dst2, dst3); - + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); SLLI_4V(dst0, dst1, dst2, dst3, 6); - HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, - in0, in1, in2, in3, - weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST6x4_UB(dst0_r, dst1_r, dst, dst_stride); + HEVC_BIW_RND_CLIP4_MAX_SATU(dst0, dst1, dst2, dst3, + in0, in1, in2, in3, + weight_vec, rnd_vec, offset_vec, + dst0, dst1, dst2, dst3); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + ST6x4_UB(out0, out1, dst, dst_stride); dst += (4 * dst_stride); } } @@ -243,8 +232,13 @@ static void hevc_biwgt_copy_8w_msa(uint8_t *src0_ptr, int32_t offset1, int32_t rnd_val) { + uint64_t tp0, tp1, tp2, tp3; int32_t offset, weight; + v16u8 out0, out1, out2; v16i8 zero = { 0 }; + v16i8 src0 = { 0 }, src1 = { 0 }, src2 = { 0 }; + v8i16 in0, in1, in2, in3, in4, in5; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5; v4i32 offset_vec, weight_vec, rnd_vec; offset = (offset0 + offset1) << rnd_val; @@ -256,80 +250,59 @@ static void hevc_biwgt_copy_8w_msa(uint8_t *src0_ptr, rnd_vec = __msa_fill_w(rnd_val + 1); if (2 == height) { - v16i8 src0, src1; - v8i16 in0, in1, dst0, dst1; - v4i32 dst0_r, dst1_r, dst0_l, dst1_l; - - LD_SB2(src0_ptr, src_stride, src0, src1); + LD2(src0_ptr, src_stride, tp0, tp1); + INSERT_D2_SB(tp0, tp1, src0); LD_SH2(src1_ptr, src2_stride, in0, in1); + ILVRL_B2_SH(zero, src0, dst0, dst1); + SLLI_2V(dst0, dst1, 6); - ILVR_B2_SH(zero, src0, zero, src1, dst0, dst1); - - dst0 <<= 6; - dst1 <<= 6; HEVC_BIW_RND_CLIP2(dst0, dst1, in0, in1, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + dst0, dst1); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST8x2_UB(dst0_r, dst, dst_stride); + out0 = (v16u8) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); + ST8x2_UB(out0, dst, dst_stride); } else if (6 == height) { - v16i8 src0, src1, src2, src3, src4, src5; - v8i16 in0, in1, in2, in3, in4, in5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; - - LD_SB6(src0_ptr, src_stride, src0, src1, src2, src3, src4, src5); + LD4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); + src0_ptr += 4 * src_stride; + INSERT_D2_SB(tp0, tp1, src0); + INSERT_D2_SB(tp2, tp3, src1); + LD2(src0_ptr, src_stride, tp0, tp1); + INSERT_D2_SB(tp0, tp1, src2); + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); + ILVRL_B2_SH(zero, src2, dst4, dst5); LD_SH6(src1_ptr, src2_stride, in0, in1, in2, in3, in4, in5); - ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - dst0, dst1, dst2, dst3); - ILVR_B2_SH(zero, src4, zero, src5, dst4, dst5); - SLLI_4V(dst0, dst1, dst2, dst3, 6); - dst4 <<= 6; - dst5 <<= 6; - HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, - in0, in1, in2, in3, - weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - HEVC_BIW_RND_CLIP2(dst4, dst5, in4, in5, - weight_vec, rnd_vec, offset_vec, - dst4_r, dst5_r, dst4_l, dst5_l); - - HEVC_PCK_SW_SB12(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - dst4_l, dst4_r, dst5_l, dst5_r, - dst0_r, dst1_r, dst2_r); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + SLLI_2V(dst4, dst5, 6); + HEVC_BIW_RND_CLIP4_MAX_SATU(dst0, dst1, dst2, dst3, in0, in1, in2, in3, + weight_vec, rnd_vec, offset_vec, dst0, dst1, + dst2, dst3); + HEVC_BIW_RND_CLIP2_MAX_SATU(dst4, dst5, in4, in5, weight_vec, rnd_vec, + offset_vec, dst4, dst5); + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + ST8x4_UB(out0, out1, dst, dst_stride); dst += (4 * dst_stride); - ST8x2_UB(dst2_r, dst, dst_stride); + ST8x2_UB(out2, dst, dst_stride); } else if (0 == height % 4) { uint32_t loop_cnt; - v16i8 src0, src1, src2, src3; - v8i16 in0, in1, in2, in3; - v8i16 dst0, dst1, dst2, dst3; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB4(src0_ptr, src_stride, src0, src1, src2, src3); + LD4(src0_ptr, src_stride, tp0, tp1, tp2, tp3); src0_ptr += (4 * src_stride); + INSERT_D2_SB(tp0, tp1, src0); + INSERT_D2_SB(tp2, tp3, src1); + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); src1_ptr += (4 * src2_stride); - ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - dst0, dst1, dst2, dst3); SLLI_4V(dst0, dst1, dst2, dst3, 6); - HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, - in0, in1, in2, in3, - weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + HEVC_BIW_RND_CLIP4_MAX_SATU(dst0, dst1, dst2, dst3, in0, in1, in2, + in3, weight_vec, rnd_vec, offset_vec, + dst0, dst1, dst2, dst3); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + ST8x4_UB(out0, out1, dst, dst_stride); dst += (4 * dst_stride); } } @@ -351,11 +324,10 @@ static void hevc_biwgt_copy_12w_msa(uint8_t *src0_ptr, uint32_t loop_cnt; int32_t offset, weight; v16i8 zero = { 0 }; + v16u8 out0, out1, out2; v16i8 src0, src1, src2, src3; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; v4i32 offset_vec, weight_vec, rnd_vec; offset = (offset0 + offset1) << rnd_val; @@ -383,44 +355,37 @@ static void hevc_biwgt_copy_12w_msa(uint8_t *src0_ptr, dst4 <<= 6; dst5 <<= 6; - HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, - in0, in1, in2, in3, - weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - HEVC_BIW_RND_CLIP2(dst4, dst5, in4, in5, - weight_vec, rnd_vec, offset_vec, - dst4_r, dst5_r, dst4_l, dst5_l); - - HEVC_PCK_SW_SB12(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - dst4_l, dst4_r, dst5_l, dst5_r, - dst0_r, dst1_r, dst2_r); - ST12x4_UB(dst0_r, dst1_r, dst2_r, dst, dst_stride); + HEVC_BIW_RND_CLIP4_MAX_SATU(dst0, dst1, dst2, dst3, in0, in1, in2, in3, + weight_vec, rnd_vec, offset_vec, dst0, dst1, + dst2, dst3); + HEVC_BIW_RND_CLIP2_MAX_SATU(dst4, dst5, in4, in5, weight_vec, rnd_vec, + offset_vec, dst4, dst5); + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + ST12x4_UB(out0, out1, out2, dst, dst_stride); dst += (4 * dst_stride); } } -static void hevc_biwgt_copy_16multx4mult_msa(uint8_t *src0_ptr, - int32_t src_stride, - int16_t *src1_ptr, - int32_t src2_stride, - uint8_t *dst, - int32_t dst_stride, - int32_t height, - int32_t weight0, - int32_t weight1, - int32_t offset0, - int32_t offset1, - int32_t rnd_val, - int32_t width) +static void hevc_biwgt_copy_16w_msa(uint8_t *src0_ptr, + int32_t src_stride, + int16_t *src1_ptr, + int32_t src2_stride, + uint8_t *dst, + int32_t dst_stride, + int32_t height, + int32_t weight0, + int32_t weight1, + int32_t offset0, + int32_t offset1, + int32_t rnd_val) { - uint32_t loop_cnt, cnt; - uint8_t *src0_ptr_tmp; - int16_t *src1_ptr_tmp; - uint8_t *dst_tmp; + uint32_t loop_cnt; int32_t offset, weight; + v16u8 out0, out1, out2, out3; v16i8 zero = { 0 }; + v16i8 src0, src1, src2, src3; + v8i16 in0, in1, in2, in3, in4, in5, in6, in7; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; v4i32 offset_vec, weight_vec, rnd_vec; offset = (offset0 + offset1) << rnd_val; @@ -431,79 +396,31 @@ static void hevc_biwgt_copy_16multx4mult_msa(uint8_t *src0_ptr, weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); - for (cnt = (width >> 4); cnt--;) { - src0_ptr_tmp = src0_ptr; - src1_ptr_tmp = src1_ptr; - dst_tmp = dst; - - for (loop_cnt = (height >> 2); loop_cnt--;) { - v16i8 src0, src1, src2, src3; - v8i16 in0, in1, in2, in3, in4, in5, in6, in7; - v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l; - - LD_SB4(src0_ptr_tmp, src_stride, src0, src1, src2, src3); - src0_ptr_tmp += (4 * src_stride); - LD_SH4(src1_ptr_tmp, src2_stride, in0, in1, in2, in3); - LD_SH4(src1_ptr_tmp + 8, src2_stride, in4, in5, in6, in7); - src1_ptr_tmp += (4 * src2_stride); - - ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - tmp0, tmp1, tmp2, tmp3); - ILVL_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, - tmp4, tmp5, tmp6, tmp7); - - SLLI_4V(tmp0, tmp1, tmp2, tmp3, 6); - SLLI_4V(tmp4, tmp5, tmp6, tmp7, 6); - HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp4, tmp5, - in0, in1, in4, in5, - weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst_tmp, dst_stride); - dst_tmp += (2 * dst_stride); - - HEVC_BIW_RND_CLIP4(tmp2, tmp3, tmp6, tmp7, - in2, in3, in6, in7, - weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst_tmp, dst_stride); - dst_tmp += (2 * dst_stride); - } - - src0_ptr += 16; - src1_ptr += 16; - dst += 16; + for (loop_cnt = (height >> 2); loop_cnt--;) { + LD_SB4(src0_ptr, src_stride, src0, src1, src2, src3); + src0_ptr += (4 * src_stride); + LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); + LD_SH4(src1_ptr + 8, src2_stride, in4, in5, in6, in7); + src1_ptr += (4 * src2_stride); + ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, tmp0, tmp1, + tmp2, tmp3); + ILVL_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, tmp4, tmp5, + tmp6, tmp7); + SLLI_4V(tmp0, tmp1, tmp2, tmp3, 6); + SLLI_4V(tmp4, tmp5, tmp6, tmp7, 6); + HEVC_BIW_RND_CLIP4_MAX_SATU(tmp0, tmp1, tmp4, tmp5, in0, in1, in4, in5, + weight_vec, rnd_vec, offset_vec, tmp0, tmp1, + tmp4, tmp5); + HEVC_BIW_RND_CLIP4_MAX_SATU(tmp2, tmp3, tmp6, tmp7, in2, in3, in6, in7, + weight_vec, rnd_vec, offset_vec, tmp2, tmp3, + tmp6, tmp7); + PCKEV_B2_UB(tmp4, tmp0, tmp5, tmp1, out0, out1); + PCKEV_B2_UB(tmp6, tmp2, tmp7, tmp3, out2, out3); + ST_UB4(out0, out1, out2, out3, dst, dst_stride); + dst += (4 * dst_stride); } } -static void hevc_biwgt_copy_16w_msa(uint8_t *src0_ptr, - int32_t src_stride, - int16_t *src1_ptr, - int32_t src2_stride, - uint8_t *dst, - int32_t dst_stride, - int32_t height, - int32_t weight0, - int32_t weight1, - int32_t offset0, - int32_t offset1, - int32_t rnd_val) -{ - hevc_biwgt_copy_16multx4mult_msa(src0_ptr, src_stride, - src1_ptr, src2_stride, - dst, dst_stride, height, weight0, - weight1, offset0, offset1, rnd_val, 16); -} - static void hevc_biwgt_copy_24w_msa(uint8_t *src0_ptr, int32_t src_stride, int16_t *src1_ptr, @@ -517,14 +434,55 @@ static void hevc_biwgt_copy_24w_msa(uint8_t *src0_ptr, int32_t offset1, int32_t rnd_val) { - hevc_biwgt_copy_16multx4mult_msa(src0_ptr, src_stride, - src1_ptr, src2_stride, - dst, dst_stride, height, weight0, - weight1, offset0, offset1, rnd_val, 16); - hevc_biwgt_copy_8w_msa(src0_ptr + 16, src_stride, - src1_ptr + 16, src2_stride, - dst + 16, dst_stride, height, weight0, - weight1, offset0, offset1, rnd_val); + uint32_t loop_cnt; + int32_t offset, weight; + v16u8 out0, out1, out2, out3, out4, out5; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, zero = { 0 }; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8, dst9, dst10; + v8i16 in0, in1, in2, in3, in4, in5, in6, in7, in8, in9, in10, in11, dst11; + v4i32 offset_vec, weight_vec, rnd_vec; + + offset = (offset0 + offset1) << rnd_val; + weight0 = weight0 & 0x0000FFFF; + weight = weight0 | (weight1 << 16); + + offset_vec = __msa_fill_w(offset); + weight_vec = __msa_fill_w(weight); + rnd_vec = __msa_fill_w(rnd_val + 1); + + for (loop_cnt = 8; loop_cnt--;) { + LD_SB4(src0_ptr, src_stride, src0, src1, src4, src5); + LD_SB4(src0_ptr + 16, src_stride, src2, src3, src6, src7); + src0_ptr += (4 * src_stride); + LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); + LD_SH4(src1_ptr + 8, src2_stride, in4, in5, in6, in7); + LD_SH4(src1_ptr + 16, src2_stride, in8, in9, in10, in11); + src1_ptr += (4 * src2_stride); + + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); + ILVR_B2_SH(zero, src2, zero, src3, dst4, dst5); + ILVRL_B2_SH(zero, src4, dst6, dst7); + ILVRL_B2_SH(zero, src5, dst8, dst9); + ILVR_B2_SH(zero, src6, zero, src7, dst10, dst11); + SLLI_4V(dst0, dst1, dst2, dst3, 6); + SLLI_4V(dst4, dst5, dst6, dst7, 6); + SLLI_4V(dst8, dst9, dst10, dst11, 6); + HEVC_BIW_RND_CLIP4_MAX_SATU(dst0, dst1, dst2, dst3, in0, in4, in1, in5, + weight_vec, rnd_vec, offset_vec, dst0, dst1, + dst2, dst3); + HEVC_BIW_RND_CLIP4_MAX_SATU(dst4, dst5, dst6, dst7, in8, in9, in2, in6, + weight_vec, rnd_vec, offset_vec, dst4, dst5, + dst6, dst7); + HEVC_BIW_RND_CLIP4_MAX_SATU(dst8, dst9, dst10, dst11, in3, in7, in10, + in11, weight_vec, rnd_vec, offset_vec, + dst8, dst9, dst10, dst11); + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + PCKEV_B3_UB(dst7, dst6, dst9, dst8, dst11, dst10, out3, out4, out5); + ST_UB4(out0, out1, out3, out4, dst, dst_stride); + ST8x4_UB(out2, out5, dst + 16, dst_stride); + dst += (4 * dst_stride); + } } static void hevc_biwgt_copy_32w_msa(uint8_t *src0_ptr, @@ -540,10 +498,52 @@ static void hevc_biwgt_copy_32w_msa(uint8_t *src0_ptr, int32_t offset1, int32_t rnd_val) { - hevc_biwgt_copy_16multx4mult_msa(src0_ptr, src_stride, - src1_ptr, src2_stride, - dst, dst_stride, height, weight0, - weight1, offset0, offset1, rnd_val, 32); + uint32_t loop_cnt; + int32_t offset, weight; + v16u8 out0, out1, out2, out3; + v16i8 zero = { 0 }; + v16i8 src0, src1, src2, src3; + v8i16 in0, in1, in2, in3, in4, in5, in6, in7; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + v4i32 offset_vec, weight_vec, rnd_vec; + + offset = (offset0 + offset1) << rnd_val; + weight0 = weight0 & 0x0000FFFF; + weight = weight0 | (weight1 << 16); + + offset_vec = __msa_fill_w(offset); + weight_vec = __msa_fill_w(weight); + rnd_vec = __msa_fill_w(rnd_val + 1); + + for (loop_cnt = (height >> 1); loop_cnt--;) { + LD_SB2(src0_ptr, 16, src0, src1); + src0_ptr += src_stride; + LD_SB2(src0_ptr, 16, src2, src3); + src0_ptr += src_stride; + LD_SH4(src1_ptr, 8, in0, in1, in2, in3); + src1_ptr += src2_stride; + LD_SH4(src1_ptr, 8, in4, in5, in6, in7); + src1_ptr += src2_stride; + + ILVRL_B2_SH(zero, src0, tmp0, tmp4); + ILVRL_B2_SH(zero, src1, tmp1, tmp5); + ILVRL_B2_SH(zero, src2, tmp2, tmp6); + ILVRL_B2_SH(zero, src3, tmp3, tmp7); + SLLI_4V(tmp0, tmp1, tmp2, tmp3, 6); + SLLI_4V(tmp4, tmp5, tmp6, tmp7, 6); + HEVC_BIW_RND_CLIP4_MAX_SATU(tmp0, tmp4, tmp1, tmp5, in0, in1, in2, in3, + weight_vec, rnd_vec, offset_vec, tmp0, tmp4, + tmp1, tmp5); + HEVC_BIW_RND_CLIP4_MAX_SATU(tmp2, tmp6, tmp3, tmp7, in4, in5, in6, in7, + weight_vec, rnd_vec, offset_vec, tmp2, tmp6, + tmp3, tmp7); + PCKEV_B2_UB(tmp4, tmp0, tmp5, tmp1, out0, out1); + PCKEV_B2_UB(tmp6, tmp2, tmp7, tmp3, out2, out3); + ST_UB2(out0, out1, dst, 16); + dst += dst_stride; + ST_UB2(out2, out3, dst, 16); + dst += dst_stride; + } } static void hevc_biwgt_copy_48w_msa(uint8_t *src0_ptr, @@ -559,10 +559,43 @@ static void hevc_biwgt_copy_48w_msa(uint8_t *src0_ptr, int32_t offset1, int32_t rnd_val) { - hevc_biwgt_copy_16multx4mult_msa(src0_ptr, src_stride, - src1_ptr, src2_stride, - dst, dst_stride, height, weight0, - weight1, offset0, offset1, rnd_val, 48); + uint32_t loop_cnt; + int32_t offset, weight; + v16u8 out0, out1, out2; + v16i8 src0, src1, src2; + v16i8 zero = { 0 }; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, in0, in1, in2, in3, in4, in5; + v4i32 offset_vec, weight_vec, rnd_vec; + + offset = (offset0 + offset1) << rnd_val; + weight0 = weight0 & 0x0000FFFF; + weight = weight0 | (weight1 << 16); + + offset_vec = __msa_fill_w(offset); + weight_vec = __msa_fill_w(weight); + rnd_vec = __msa_fill_w(rnd_val + 1); + + for (loop_cnt = 64; loop_cnt--;) { + LD_SB3(src0_ptr, 16, src0, src1, src2); + src0_ptr += src_stride; + LD_SH6(src1_ptr, 8, in0, in1, in2, in3, in4, in5); + src1_ptr += src2_stride; + + ILVRL_B2_SH(zero, src0, dst0, dst1); + ILVRL_B2_SH(zero, src1, dst2, dst3); + ILVRL_B2_SH(zero, src2, dst4, dst5); + SLLI_4V(dst0, dst1, dst2, dst3, 6); + SLLI_2V(dst4, dst5, 6); + HEVC_BIW_RND_CLIP4_MAX_SATU(dst0, dst1, dst2, dst3, in0, in1, in2, in3, + weight_vec, rnd_vec, offset_vec, dst0, dst1, + dst2, dst3); + HEVC_BIW_RND_CLIP2_MAX_SATU(dst4, dst5, in4, in5, weight_vec, rnd_vec, + offset_vec, dst4, dst5); + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + ST_UB2(out0, out1, dst, 16); + ST_UB(out2, dst + 32); + dst += dst_stride; + } } static void hevc_biwgt_copy_64w_msa(uint8_t *src0_ptr, @@ -578,10 +611,46 @@ static void hevc_biwgt_copy_64w_msa(uint8_t *src0_ptr, int32_t offset1, int32_t rnd_val) { - hevc_biwgt_copy_16multx4mult_msa(src0_ptr, src_stride, - src1_ptr, src2_stride, - dst, dst_stride, height, weight0, - weight1, offset0, offset1, rnd_val, 64); + uint32_t loop_cnt; + int32_t offset, weight; + v16u8 out0, out1, out2, out3; + v16i8 zero = { 0 }; + v16i8 src0, src1, src2, src3; + v8i16 in0, in1, in2, in3, in4, in5, in6, in7; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + v4i32 offset_vec, weight_vec, rnd_vec; + + offset = (offset0 + offset1) << rnd_val; + weight0 = weight0 & 0x0000FFFF; + weight = weight0 | (weight1 << 16); + + offset_vec = __msa_fill_w(offset); + weight_vec = __msa_fill_w(weight); + rnd_vec = __msa_fill_w(rnd_val + 1); + + for (loop_cnt = height; loop_cnt--;) { + LD_SB4(src0_ptr, 16, src0, src1, src2, src3); + src0_ptr += src_stride; + LD_SH8(src1_ptr, 8, in0, in1, in2, in3, in4, in5, in6, in7); + src1_ptr += src2_stride; + + ILVR_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, tmp0, tmp1, + tmp2, tmp3); + ILVL_B4_SH(zero, src0, zero, src1, zero, src2, zero, src3, tmp4, tmp5, + tmp6, tmp7); + SLLI_4V(tmp0, tmp1, tmp2, tmp3, 6); + SLLI_4V(tmp4, tmp5, tmp6, tmp7, 6); + HEVC_BIW_RND_CLIP4_MAX_SATU(tmp0, tmp4, tmp1, tmp5, in0, in1, in2, in3, + weight_vec, rnd_vec, offset_vec, tmp0, tmp4, + tmp1, tmp5); + HEVC_BIW_RND_CLIP4_MAX_SATU(tmp2, tmp6, tmp3, tmp7, in4, in5, in6, in7, + weight_vec, rnd_vec, offset_vec, tmp2, tmp6, + tmp3, tmp7); + PCKEV_B2_UB(tmp4, tmp0, tmp5, tmp1, out0, out1); + PCKEV_B2_UB(tmp6, tmp2, tmp7, tmp3, out2, out3); + ST_UB4(out0, out1, out2, out3, dst, 16); + dst += dst_stride; + } } static void hevc_hz_biwgt_8t_4w_msa(uint8_t *src0_ptr, @@ -599,17 +668,16 @@ static void hevc_hz_biwgt_8t_4w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v8i16 filt0, filt1, filt2, filt3; v16i8 src0, src1, src2, src3; v16i8 mask1, mask2, mask3; v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1; v8i16 in0, in1, in2, in3; - v4i32 dst0_r, dst1_r, dst0_l, dst1_l; - v8i16 filter_vec, const_vec; + v8i16 filter_vec, out0, out1; v4i32 weight_vec, offset_vec, rnd_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[16]); src0_ptr -= 3; filter_vec = LD_SH(filter); @@ -622,9 +690,10 @@ static void hevc_hz_biwgt_8t_4w_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -639,21 +708,19 @@ static void hevc_hz_biwgt_8t_4w_msa(uint8_t *src0_ptr, VSHF_B4_SB(src0, src1, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src2, src3, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); + dst1 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); HEVC_BIW_RND_CLIP2(dst0, dst1, in0, in1, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + out0, out1); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST4x4_UB(dst0_r, dst0_r, 0, 1, 2, 3, dst, dst_stride); + out0 = (v8i16) __msa_pckev_b((v16i8) out1, (v16i8) out0); + ST4x4_UB(out0, out0, 0, 1, 2, 3, dst, dst_stride); dst += (4 * dst_stride); } } @@ -673,25 +740,25 @@ static void hevc_hz_biwgt_8t_8w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v8i16 filt0, filt1, filt2, filt3; v16i8 src0, src1, src2, src3; v16i8 mask1, mask2, mask3; v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2, dst3; v8i16 in0, in1, in2, in3; - v4i32 dst0_r, dst1_r, dst0_l, dst1_l, dst2_r, dst3_r, dst2_l, dst3_l; - v8i16 filter_vec, const_vec; + v8i16 filter_vec, out0, out1, out2, out3; v4i32 weight_vec, offset_vec, rnd_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); src0_ptr -= 3; offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -712,34 +779,28 @@ static void hevc_hz_biwgt_8t_8w_msa(uint8_t *src0_ptr, VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); + dst1 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); + dst2 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + dst3 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + out0, out1, out2, out3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(out1, out0, out3, out2, out0, out1); + ST8x4_UB(out0, out1, dst, dst_stride); dst += (4 * dst_stride); } } @@ -758,12 +819,85 @@ static void hevc_hz_biwgt_8t_12w_msa(uint8_t *src0_ptr, int32_t offset1, int32_t rnd_val) { - hevc_hz_biwgt_8t_8w_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter, height, - weight0, weight1, offset0, offset1, rnd_val); - hevc_hz_biwgt_8t_4w_msa(src0_ptr + 8, src_stride, src1_ptr + 8, src2_stride, - dst + 8, dst_stride, filter, height, - weight0, weight1, offset0, offset1, rnd_val); + uint32_t loop_cnt; + int32_t offset, weight, constant; + v16i8 src0, src1, src2, src3, vec0, vec1, vec2, vec3; + v16i8 mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask7; + v8i16 filt0, filt1, filt2, filt3, out0, out1, out2, out3; + v8i16 dst0, dst1, dst2, dst3, in0, in1, in2, in3, filter_vec; + v4i32 weight_vec, offset_vec, rnd_vec; + + src0_ptr -= 3; + + weight0 = weight0 & 0x0000FFFF; + weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset = (offset0 + offset1) << rnd_val; + offset += constant; + + offset_vec = __msa_fill_w(offset); + weight_vec = __msa_fill_w(weight); + rnd_vec = __msa_fill_w(rnd_val + 1); + + filter_vec = LD_SH(filter); + SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); + + mask0 = LD_SB(&ff_hevc_mask_arr[0]); + mask1 = mask0 + 2; + mask2 = mask0 + 4; + mask3 = mask0 + 6; + mask4 = LD_SB(&ff_hevc_mask_arr[16]); + mask5 = mask4 + 2; + mask6 = mask4 + 4; + mask7 = mask4 + 6; + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src0_ptr, src_stride, src0, src1, src2, src3); + LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); + XORI_B4_128_SB(src0, src1, src2, src3); + VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, vec0, vec1, vec2, + vec3); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, vec0, vec1, vec2, + vec3); + dst1 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, vec0, vec1, vec2, + vec3); + dst2 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, vec0, vec1, vec2, + vec3); + dst3 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, + weight_vec, rnd_vec, offset_vec, out0, out1, out2, + out3); + PCKEV_B2_SH(out1, out0, out3, out2, out0, out1); + ST8x4_UB(out0, out1, dst, dst_stride); + + LD_SB4(src0_ptr + 8, src_stride, src0, src1, src2, src3); + src0_ptr += (4 * src_stride); + LD_SH4(src1_ptr + 8, src2_stride, in0, in1, in2, in3); + src1_ptr += (4 * src2_stride); + ILVR_D2_SH(in1, in0, in3, in2, in0, in1); + XORI_B4_128_SB(src0, src1, src2, src3); + VSHF_B4_SB(src0, src1, mask4, mask5, mask6, mask7, vec0, vec1, vec2, + vec3); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + VSHF_B4_SB(src2, src3, mask4, mask5, mask6, mask7, vec0, vec1, vec2, + vec3); + dst1 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + HEVC_BIW_RND_CLIP2(dst0, dst1, in0, in1, weight_vec, rnd_vec, + offset_vec, out0, out1); + out0 = (v8i16) __msa_pckev_b((v16i8) out1, (v16i8) out0); + ST4x4_UB(out0, out0, 0, 1, 2, 3, dst + 8, dst_stride); + dst += (4 * dst_stride); + } } static void hevc_hz_biwgt_8t_16w_msa(uint8_t *src0_ptr, @@ -781,15 +915,14 @@ static void hevc_hz_biwgt_8t_16w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1, src2, src3; v8i16 in0, in1, in2, in3; v8i16 filt0, filt1, filt2, filt3; v16i8 mask1, mask2, mask3; - v8i16 filter_vec, const_vec; + v8i16 filter_vec, out0, out1, out2, out3; v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2, dst3; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; v4i32 weight_vec, offset_vec, rnd_vec; v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; @@ -797,9 +930,10 @@ static void hevc_hz_biwgt_8t_16w_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -824,34 +958,28 @@ static void hevc_hz_biwgt_8t_16w_msa(uint8_t *src0_ptr, VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); + dst1 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); + dst2 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + dst3 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + out0, out1, out2, out3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(out1, out0, out3, out2, out0, out1); + ST_SH2(out0, out1, dst, dst_stride); dst += (2 * dst_stride); } } @@ -872,25 +1000,26 @@ static void hevc_hz_biwgt_8t_24w_msa(uint8_t *src0_ptr, { uint32_t loop_cnt; uint64_t dst_val0; - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1; v8i16 in0, in1, in2; v8i16 filt0, filt1, filt2, filt3; v16i8 mask1, mask2, mask3, mask4, mask5, mask6, mask7; v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2; - v4i32 dst0_r, dst1_r, dst2_r, dst0_l, dst1_l, dst2_l; - v8i16 filter_vec, const_vec; + v4i32 dst2_r, dst2_l; + v8i16 filter_vec, out0, out1, out2; v4i32 weight_vec, offset_vec, rnd_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); src0_ptr = src0_ptr - 3; offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -906,33 +1035,30 @@ static void hevc_hz_biwgt_8t_24w_msa(uint8_t *src0_ptr, mask6 = mask0 + 12; mask7 = mask0 + 14; - for (loop_cnt = height; loop_cnt--;) { - LD_SB2(src0_ptr, 16, src0, src1); - src0_ptr += src_stride; - LD_SH2(src1_ptr, 8, in0, in1); - in2 = LD_SH(src1_ptr + 16); - src1_ptr += src2_stride; - XORI_B2_128_SB(src0, src1); + LD_SB2(src0_ptr, 16, src0, src1); + src0_ptr += src_stride; + LD_SH2(src1_ptr, 8, in0, in1); + in2 = LD_SH(src1_ptr + 16); + src1_ptr += src2_stride; + XORI_B2_128_SB(src0, src1); + for (loop_cnt = 31; loop_cnt--;) { VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src0, src1, mask4, mask5, mask6, mask7, vec0, vec1, vec2, vec3); - dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); + dst1 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); + dst2 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); HEVC_BIW_RND_CLIP2(dst0, dst1, in0, in1, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + out0, out1); ILVRL_H2_SW(dst2, in2, dst2_r, dst2_l); dst2_r = __msa_dpadd_s_w(offset_vec, (v8i16) dst2_r, @@ -940,16 +1066,44 @@ static void hevc_hz_biwgt_8t_24w_msa(uint8_t *src0_ptr, dst2_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst2_l, (v8i16) weight_vec); SRAR_W2_SW(dst2_r, dst2_l, rnd_vec); - dst2_r = CLIP_SW_0_255(dst2_r); - dst2_l = CLIP_SW_0_255(dst2_l); + dst2_r = (v4i32) __msa_pckev_h((v8i16) dst2_l, (v8i16) dst2_r); + out2 = CLIP_SH_0_255(dst2_r); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - HEVC_PCK_SW_SB2(dst2_l, dst2_r, dst2_r); - dst_val0 = __msa_copy_u_d((v2i64) dst2_r, 0); - ST_SW(dst0_r, dst); + LD_SB2(src0_ptr, 16, src0, src1); + src0_ptr += src_stride; + LD_SH2(src1_ptr, 8, in0, in1); + in2 = LD_SH(src1_ptr + 16); + src1_ptr += src2_stride; + XORI_B2_128_SB(src0, src1); + PCKEV_B2_SH(out1, out0, out2, out2, out0, out2); + dst_val0 = __msa_copy_u_d((v2i64) out2, 0); + ST_SH(out0, dst); SD(dst_val0, dst + 16); dst += dst_stride; } + + VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + VSHF_B4_SB(src0, src1, mask4, mask5, mask6, mask7, vec0, vec1, vec2, vec3); + dst1 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); + dst2 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + HEVC_BIW_RND_CLIP2(dst0, dst1, in0, in1, weight_vec, rnd_vec, offset_vec, + out0, out1); + ILVRL_H2_SW(dst2, in2, dst2_r, dst2_l); + dst2_r = __msa_dpadd_s_w(offset_vec, (v8i16) dst2_r, (v8i16) weight_vec); + dst2_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst2_l, (v8i16) weight_vec); + SRAR_W2_SW(dst2_r, dst2_l, rnd_vec); + dst2_r = (v4i32) __msa_pckev_h((v8i16) dst2_l, (v8i16) dst2_r); + out2 = CLIP_SH_0_255(dst2_r); + PCKEV_B2_SH(out1, out0, out2, out2, out0, out2); + dst_val0 = __msa_copy_u_d((v2i64) out2, 0); + ST_SH(out0, dst); + SD(dst_val0, dst + 16); + dst += dst_stride; } static void hevc_hz_biwgt_8t_32w_msa(uint8_t *src0_ptr, @@ -967,25 +1121,25 @@ static void hevc_hz_biwgt_8t_32w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1, src2; v8i16 in0, in1, in2, in3; v8i16 filt0, filt1, filt2, filt3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1, mask2, mask3, mask4, mask5, mask6, mask7; v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2, dst3; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; + v8i16 filter_vec, out0, out1, out2, out3; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 3; offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -1012,34 +1166,28 @@ static void hevc_hz_biwgt_8t_32w_msa(uint8_t *src0_ptr, VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src0, src1, mask4, mask5, mask6, mask7, vec0, vec1, vec2, vec3); - dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); + dst1 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); + dst2 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + dst3 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + out0, out1, out2, out3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, 16); + PCKEV_B2_SH(out1, out0, out3, out2, out0, out1); + ST_SH2(out0, out1, dst, 16); dst += dst_stride; } } @@ -1059,27 +1207,25 @@ static void hevc_hz_biwgt_8t_48w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; - uint64_t dst_val0; - v16i8 src0, src1, src2, src3; - v8i16 in0, in1, in2, in3, in4, in5; + int32_t offset, weight, constant; + v16i8 src0, src1, src2, src3, src4; + v8i16 in0, in1, in2, in3; v8i16 filt0, filt1, filt2, filt3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1, mask2, mask3, mask4, mask5, mask6, mask7; v16i8 vec0, vec1, vec2, vec3; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; + v8i16 dst0, dst1, dst2, dst3; + v8i16 filter_vec, out0, out1, out2, out3; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 3; offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -1095,86 +1241,57 @@ static void hevc_hz_biwgt_8t_48w_msa(uint8_t *src0_ptr, mask6 = mask0 + 12; mask7 = mask0 + 14; - for (loop_cnt = height; loop_cnt--;) { - LD_SB3(src0_ptr, 16, src0, src1, src2); - src3 = LD_SB(src0_ptr + 40); + for (loop_cnt = 64; loop_cnt--;) { + LD_SB2(src0_ptr, 16, src0, src1); + src2 = LD_SB(src0_ptr + 24); + LD_SH4(src1_ptr, 8, in0, in1, in2, in3); + XORI_B3_128_SB(src0, src1, src2); + LD_SB2(src0_ptr + 32, 8, src3, src4); src0_ptr += src_stride; - LD_SH2(src1_ptr, 8, in0, in1); - in2 = LD_SH(src1_ptr + 16); - XORI_B4_128_SB(src0, src1, src2, src3); + XORI_B2_128_SB(src3, src4); VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src0, src1, mask4, mask5, mask6, mask7, vec0, vec1, vec2, vec3); - dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); + dst1 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - VSHF_B4_SB(src1, src2, mask4, mask5, mask6, mask7, - vec0, vec1, vec2, vec3); - dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + dst2 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst4 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst4, dst4, dst4, dst4); - VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); - dst5 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst5, dst5, dst5, dst5); + dst3 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); - HEVC_BIW_RND_CLIP2(dst0, dst1, in0, in1, + HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + out0, out1, out2, out3); - ILVRL_H2_SW(dst2, in2, dst2_r, dst2_l); - dst2_r = __msa_dpadd_s_w(offset_vec, (v8i16) dst2_r, - (v8i16) weight_vec); - dst2_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst2_l, - (v8i16) weight_vec); - SRAR_W2_SW(dst2_r, dst2_l, rnd_vec); - dst2_r = CLIP_SW_0_255(dst2_r); - dst2_l = CLIP_SW_0_255(dst2_l); - - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - HEVC_PCK_SW_SB2(dst2_l, dst2_r, dst2_r); - dst_val0 = __msa_copy_u_d((v2i64) dst2_r, 0); - ST_SW(dst0_r, dst); - SD(dst_val0, dst + 16); + PCKEV_B2_SH(out1, out0, out3, out2, out0, out1); + ST_SH2(out0, out1, dst, 16); - LD_SH2(src1_ptr + 24, 8, in3, in4); - in5 = LD_SH(src1_ptr + 40); + LD_SH2(src1_ptr + 32, 8, in2, in3); src1_ptr += src2_stride; - HEVC_BIW_RND_CLIP2(dst3, dst4, in3, in4, + VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, + vec0, vec1, vec2, vec3); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + VSHF_B4_SB(src4, src4, mask0, mask1, mask2, mask3, + vec0, vec1, vec2, vec3); + dst1 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + + HEVC_BIW_RND_CLIP2(dst0, dst1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst3_r, dst4_r, dst3_l, dst4_l); + out0, out1); - ILVRL_H2_SW(dst5, in5, dst5_r, dst5_l); - dst5_r = __msa_dpadd_s_w(offset_vec, (v8i16) dst5_r, - (v8i16) weight_vec); - dst5_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst5_l, - (v8i16) weight_vec); - SRAR_W2_SW(dst5_r, dst5_l, rnd_vec); - dst5_r = CLIP_SW_0_255(dst5_r); - dst5_l = CLIP_SW_0_255(dst5_l); - - HEVC_PCK_SW_SB4(dst4_l, dst4_r, dst5_l, dst5_r, dst4_r); - HEVC_PCK_SW_SB2(dst3_l, dst3_r, dst3_r); - dst_val0 = __msa_copy_u_d((v2i64) dst3_r, 0); - SD(dst_val0, dst + 24); - ST_SW(dst4_r, dst + 32); + out0 = (v8i16) __msa_pckev_b((v16i8) out1, (v16i8) out0); + ST_SH(out0, dst + 32); dst += dst_stride; } } @@ -1197,25 +1314,25 @@ static void hevc_hz_biwgt_8t_64w_msa(uint8_t *src0_ptr, uint8_t *dst_tmp; int16_t *src1_ptr_tmp; uint32_t loop_cnt, cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1, src2; v8i16 in0, in1, in2, in3; v8i16 filt0, filt1, filt2, filt3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1, mask2, mask3, mask4, mask5, mask6, mask7; v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2, dst3; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; + v8i16 filter_vec, out0, out1, out2, out3; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 3; offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -1246,34 +1363,28 @@ static void hevc_hz_biwgt_8t_64w_msa(uint8_t *src0_ptr, VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, + filt2, filt3); VSHF_B4_SB(src0, src1, mask4, mask5, mask6, mask7, vec0, vec1, vec2, vec3); - dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); + dst1 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, + filt2, filt3); VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); + dst2 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, + filt2, filt3); VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + dst3 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, + filt2, filt3); HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + out0, out1, out2, out3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst_tmp, 16); + PCKEV_B2_SH(out1, out0, out3, out2, out0, out1); + ST_SH2(out0, out1, dst_tmp, 16); dst_tmp += 32; } @@ -1309,22 +1420,22 @@ static void hevc_vt_biwgt_8t_4w_msa(uint8_t *src0_ptr, v16i8 src2110, src4332, src6554, src8776, src10998; v16i8 src12111110, src14131312; v8i16 dst10, dst32, dst54, dst76; - v4i32 dst10_r, dst32_r, dst54_r, dst76_r; - v4i32 dst10_l, dst32_l, dst54_l, dst76_l; v8i16 filt0, filt1, filt2, filt3; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 filter_vec, out0, out1, out2, out3; + v4i32 weight_vec, weight1_vec, offset_vec, rnd_vec, const_vec; src0_ptr -= (3 * src_stride); offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); - const_vec = __msa_ldi_h(128); + const_vec = __msa_ldi_w(128); const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); + weight1_vec = __msa_fill_w(weight1); + offset_vec += const_vec * weight1_vec; filter_vec = LD_SH(filter); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); @@ -1357,28 +1468,22 @@ static void hevc_vt_biwgt_8t_4w_msa(uint8_t *src0_ptr, src8776, src10998, src12111110, src14131312); XORI_B4_128_SB(src8776, src10998, src12111110, src14131312); - dst10 = const_vec; - DPADD_SB4_SH(src2110, src4332, src6554, src8776, filt0, filt1, - filt2, filt3, dst10, dst10, dst10, dst10); - dst32 = const_vec; - DPADD_SB4_SH(src4332, src6554, src8776, src10998, - filt0, filt1, filt2, filt3, dst32, dst32, dst32, dst32); - dst54 = const_vec; - DPADD_SB4_SH(src6554, src8776, src10998, src12111110, - filt0, filt1, filt2, filt3, dst54, dst54, dst54, dst54); - dst76 = const_vec; - DPADD_SB4_SH(src8776, src10998, src12111110, src14131312, - filt0, filt1, filt2, filt3, dst76, dst76, dst76, dst76); + DOTP_SB4_SH(src2110, src4332, src6554, src8776, filt0, filt0, filt0, + filt0, dst10, dst32, dst54, dst76); + DPADD_SB4_SH(src4332, src6554, src8776, src10998, filt1, filt1, filt1, + filt1, dst10, dst32, dst54, dst76); + DPADD_SB4_SH(src6554, src8776, src10998, src12111110, filt2, filt2, + filt2, filt2, dst10, dst32, dst54, dst76); + DPADD_SB4_SH(src8776, src10998, src12111110, src14131312, filt3, filt3, + filt3, filt3, dst10, dst32, dst54, dst76); HEVC_BIW_RND_CLIP4(dst10, dst32, dst54, dst76, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst10_r, dst32_r, dst54_r, dst76_r, - dst10_l, dst32_l, dst54_l, dst76_l); + out0, out1, out2, out3); - HEVC_PCK_SW_SB8(dst10_l, dst10_r, dst32_l, dst32_r, - dst54_l, dst54_r, dst76_l, dst76_r, dst10_r, dst54_r); - ST4x8_UB(dst10_r, dst54_r, dst, dst_stride); + PCKEV_B2_SH(out1, out0, out3, out2, out0, out1); + ST4x8_UB(out0, out1, dst, dst_stride); dst += (8 * dst_stride); src2110 = src10998; @@ -1411,20 +1516,21 @@ static void hevc_vt_biwgt_8t_8w_msa(uint8_t *src0_ptr, v16i8 src21_r, src43_r, src65_r, src87_r, src109_r; v8i16 tmp0, tmp1, tmp2, tmp3; v8i16 filt0, filt1, filt2, filt3; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 filter_vec, out0, out1, out2, out3; + v4i32 weight_vec, weight1_vec, offset_vec, rnd_vec, const_vec; src0_ptr -= (3 * src_stride); offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); - const_vec = __msa_ldi_h(128); + const_vec = __msa_ldi_w(128); const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); + weight1_vec = __msa_fill_w(weight1); + offset_vec += const_vec * weight1_vec; filter_vec = LD_SH(filter); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); @@ -1447,28 +1553,22 @@ static void hevc_vt_biwgt_8t_8w_msa(uint8_t *src0_ptr, ILVR_B4_SB(src7, src6, src8, src7, src9, src8, src10, src9, src76_r, src87_r, src98_r, src109_r); - tmp0 = const_vec; - DPADD_SB4_SH(src10_r, src32_r, src54_r, src76_r, - filt0, filt1, filt2, filt3, tmp0, tmp0, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB4_SH(src21_r, src43_r, src65_r, src87_r, - filt0, filt1, filt2, filt3, tmp1, tmp1, tmp1, tmp1); - tmp2 = const_vec; - DPADD_SB4_SH(src32_r, src54_r, src76_r, src98_r, - filt0, filt1, filt2, filt3, tmp2, tmp2, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB4_SH(src43_r, src65_r, src87_r, src109_r, - filt0, filt1, filt2, filt3, tmp3, tmp3, tmp3, tmp3); + DOTP_SB4_SH(src10_r, src21_r, src32_r, src43_r, filt0, filt0, filt0, + filt0, tmp0, tmp1, tmp2, tmp3); + DPADD_SB4_SH(src32_r, src43_r, src54_r, src65_r, filt1, filt1, filt1, + filt1, tmp0, tmp1, tmp2, tmp3); + DPADD_SB4_SH(src54_r, src65_r, src76_r, src87_r, filt2, filt2, filt2, + filt2, tmp0, tmp1, tmp2, tmp3); + DPADD_SB4_SH(src76_r, src87_r, src98_r, src109_r, filt3, filt3, filt3, + filt3, tmp0, tmp1, tmp2, tmp3); HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + out0, out1, out2, out3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(out1, out0, out3, out2, out0, out1); + ST8x4_UB(out0, out1, dst, dst_stride); dst += (4 * dst_stride); src10_r = src54_r; @@ -1506,20 +1606,22 @@ static void hevc_vt_biwgt_8t_12w_msa(uint8_t *src0_ptr, v16i8 src21_l, src43_l, src65_l, src87_l; v16i8 src2110, src4332, src6554, src8776; v8i16 filt0, filt1, filt2, filt3; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst0_l, dst1_l, dst2_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 out0, out1, out2, filter_vec; + v4i32 dst2_r, dst2_l; + v4i32 weight_vec, weight1_vec, offset_vec, rnd_vec, const_vec; src0_ptr -= (3 * src_stride); offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); - const_vec = __msa_ldi_h(128); + const_vec = __msa_ldi_w(128); const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); + weight1_vec = __msa_fill_w(weight1); + offset_vec += const_vec * weight1_vec; filter_vec = LD_SH(filter); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); @@ -1537,7 +1639,7 @@ static void hevc_vt_biwgt_8t_12w_msa(uint8_t *src0_ptr, ILVR_D3_SB(src21_l, src10_l, src43_l, src32_l, src65_l, src54_l, src2110, src4332, src6554); - for (loop_cnt = (height >> 1); loop_cnt--;) { + for (loop_cnt = 8; loop_cnt--;) { LD_SB2(src0_ptr, src_stride, src7, src8); src0_ptr += (2 * src_stride); LD_SH2(src1_ptr, src2_stride, in0, in1); @@ -1550,19 +1652,18 @@ static void hevc_vt_biwgt_8t_12w_msa(uint8_t *src0_ptr, ILVL_B2_SB(src7, src6, src8, src7, src76_l, src87_l); src8776 = (v16i8) __msa_ilvr_d((v2i64) src87_l, (v2i64) src76_l); - tmp0 = const_vec; - DPADD_SB4_SH(src10_r, src32_r, src54_r, src76_r, - filt0, filt1, filt2, filt3, tmp0, tmp0, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB4_SH(src21_r, src43_r, src65_r, src87_r, - filt0, filt1, filt2, filt3, tmp1, tmp1, tmp1, tmp1); - tmp2 = const_vec; - DPADD_SB4_SH(src2110, src4332, src6554, src8776, - filt0, filt1, filt2, filt3, tmp2, tmp2, tmp2, tmp2); + DOTP_SB3_SH(src10_r, src21_r, src2110, filt0, filt0, filt0, + tmp0, tmp1, tmp2); + DPADD_SB2_SH(src32_r, src43_r, filt1, filt1, tmp0, tmp1); + tmp2 = __msa_dpadd_s_h(tmp2, src4332, (v16i8) filt1); + DPADD_SB2_SH(src54_r, src65_r, filt2, filt2, tmp0, tmp1); + tmp2 = __msa_dpadd_s_h(tmp2, src6554, (v16i8) filt2); + DPADD_SB2_SH(src76_r, src87_r, filt3, filt3, tmp0, tmp1); + tmp2 = __msa_dpadd_s_h(tmp2, src8776, (v16i8) filt3); HEVC_BIW_RND_CLIP2(tmp0, tmp1, in0, in1, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + out0, out1); ILVRL_H2_SW(tmp2, in2, dst2_r, dst2_l); dst2_r = __msa_dpadd_s_w(offset_vec, (v8i16) dst2_r, @@ -1570,13 +1671,11 @@ static void hevc_vt_biwgt_8t_12w_msa(uint8_t *src0_ptr, dst2_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst2_l, (v8i16) weight_vec); SRAR_W2_SW(dst2_r, dst2_l, rnd_vec); - dst2_r = CLIP_SW_0_255(dst2_r); - dst2_l = CLIP_SW_0_255(dst2_l); - - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - HEVC_PCK_SW_SB2(dst2_l, dst2_r, dst2_r); - ST8x2_UB(dst0_r, dst, dst_stride); - ST4x2_UB(dst2_r, dst + 8, dst_stride); + dst2_r = (v4i32) __msa_pckev_h((v8i16) dst2_l, (v8i16) dst2_r); + out2 = CLIP_SH_0_255(dst2_r); + PCKEV_B2_SH(out1, out0, out2, out2, out0, out2); + ST8x2_UB(out0, dst, dst_stride); + ST4x2_UB(out2, dst + 8, dst_stride); dst += (2 * dst_stride); src10_r = src32_r; @@ -1620,9 +1719,9 @@ static void hevc_vt_biwgt_8t_16multx2mult_msa(uint8_t *src0_ptr, v16i8 src21_l, src43_l, src65_l, src87_l; v8i16 tmp0, tmp1, tmp2, tmp3; v8i16 filt0, filt1, filt2, filt3; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 filter_vec; + v8i16 out0, out1, out2, out3; + v4i32 weight_vec, weight1_vec, offset_vec, rnd_vec, const_vec; src0_ptr -= (3 * src_stride); @@ -1630,11 +1729,13 @@ static void hevc_vt_biwgt_8t_16multx2mult_msa(uint8_t *src0_ptr, weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); - const_vec = __msa_ldi_h(128); + const_vec = __msa_ldi_w(128); const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); + weight1_vec = __msa_fill_w(weight1); + offset_vec += const_vec * weight1_vec; filter_vec = LD_SH(filter); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); @@ -1667,28 +1768,22 @@ static void hevc_vt_biwgt_8t_16multx2mult_msa(uint8_t *src0_ptr, ILVR_B2_SB(src7, src6, src8, src7, src76_r, src87_r); ILVL_B2_SB(src7, src6, src8, src7, src76_l, src87_l); - tmp0 = const_vec; - DPADD_SB4_SH(src10_r, src32_r, src54_r, src76_r, - filt0, filt1, filt2, filt3, tmp0, tmp0, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB4_SH(src21_r, src43_r, src65_r, src87_r, - filt0, filt1, filt2, filt3, tmp1, tmp1, tmp1, tmp1); - tmp2 = const_vec; - DPADD_SB4_SH(src10_l, src32_l, src54_l, src76_l, - filt0, filt1, filt2, filt3, tmp2, tmp2, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB4_SH(src21_l, src43_l, src65_l, src87_l, - filt0, filt1, filt2, filt3, tmp3, tmp3, tmp3, tmp3); + DOTP_SB4_SH(src10_r, src21_r, src10_l, src21_l, filt0, filt0, + filt0, filt0, tmp0, tmp1, tmp2, tmp3); + DPADD_SB4_SH(src32_r, src43_r, src32_l, src43_l, filt1, filt1, + filt1, filt1, tmp0, tmp1, tmp2, tmp3); + DPADD_SB4_SH(src54_r, src65_r, src54_l, src65_l, filt2, filt2, + filt2, filt2, tmp0, tmp1, tmp2, tmp3); + DPADD_SB4_SH(src76_r, src87_r, src76_l, src87_l, filt3, filt3, + filt3, filt3, tmp0, tmp1, tmp2, tmp3); HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + out0, out1, out2, out3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst_tmp, dst_stride); + PCKEV_B2_SH(out2, out0, out3, out1, out0, out1); + ST_SH2(out0, out1, dst_tmp, dst_stride); dst_tmp += (2 * dst_stride); src10_r = src32_r; @@ -2615,7 +2710,6 @@ static void hevc_hz_biwgt_4t_4x4_msa(uint8_t *src0_ptr, v8i16 dst0, dst1; v16i8 vec0, vec1; v8i16 in0, in1, in2, in3; - v4i32 dst0_r, dst1_r, dst0_l, dst1_l; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; @@ -2650,10 +2744,10 @@ static void hevc_hz_biwgt_4t_4x4_msa(uint8_t *src0_ptr, DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); HEVC_BIW_RND_CLIP2(dst0, dst1, in0, in1, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + dst0, dst1); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST4x4_UB(dst0_r, dst0_r, 0, 1, 2, 3, dst, dst_stride); + dst0 = (v8i16) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); + ST4x4_UB(dst0, dst0, 0, 1, 2, 3, dst, dst_stride); } static void hevc_hz_biwgt_4t_4x8multiple_msa(uint8_t *src0_ptr, @@ -2678,7 +2772,6 @@ static void hevc_hz_biwgt_4t_4x8multiple_msa(uint8_t *src0_ptr, v16i8 mask1; v16i8 vec0, vec1; v8i16 dst0, dst1, dst2, dst3; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; @@ -2727,12 +2820,10 @@ static void hevc_hz_biwgt_4t_4x8multiple_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + dst0, dst1, dst2, dst3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST4x8_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); + ST4x8_UB(dst0, dst1, dst, dst_stride); dst += (8 * dst_stride); } } @@ -2791,7 +2882,6 @@ static void hevc_hz_biwgt_4t_6w_msa(uint8_t *src0_ptr, v16i8 vec0, vec1; v8i16 in0, in1, in2, in3; v8i16 dst0, dst1, dst2, dst3; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; @@ -2835,12 +2925,10 @@ static void hevc_hz_biwgt_4t_6w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + dst0, dst1, dst2, dst3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST6x4_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); + ST6x4_UB(dst0, dst1, dst, dst_stride); dst += (4 * dst_stride); } } @@ -2867,7 +2955,6 @@ static void hevc_hz_biwgt_4t_8x2_msa(uint8_t *src0_ptr, v16i8 mask1, vec0, vec1; v8i16 dst0, dst1; v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst0_l, dst1_l; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -2898,10 +2985,10 @@ static void hevc_hz_biwgt_4t_8x2_msa(uint8_t *src0_ptr, DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); HEVC_BIW_RND_CLIP2(dst0, dst1, in0, in1, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + dst0, dst1); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST8x2_UB(dst0_r, dst, dst_stride); + dst0 = (v8i16) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); + ST8x2_UB(dst0, dst, dst_stride); } static void hevc_hz_biwgt_4t_8x6_msa(uint8_t *src0_ptr, @@ -2927,8 +3014,6 @@ static void hevc_hz_biwgt_4t_8x6_msa(uint8_t *src0_ptr, v16i8 vec0, vec1; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -2975,18 +3060,16 @@ static void hevc_hz_biwgt_4t_8x6_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + dst0, dst1, dst2, dst3); HEVC_BIW_RND_CLIP2(dst4, dst5, in4, in5, weight_vec, rnd_vec, offset_vec, - dst4_r, dst5_r, dst4_l, dst5_l); + dst4, dst5); - HEVC_PCK_SW_SB12(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - dst4_l, dst4_r, dst5_l, dst5_r, dst0_r, dst1_r, dst2_r); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); + dst3 = (v8i16) __msa_pckev_b((v16i8) dst5, (v16i8) dst4); + ST8x4_UB(dst0, dst1, dst, dst_stride); dst += (4 * dst_stride); - ST8x2_UB(dst2_r, dst, dst_stride); + ST8x2_UB(dst3, dst, dst_stride); } static void hevc_hz_biwgt_4t_8x4multiple_msa(uint8_t *src0_ptr, @@ -3012,7 +3095,6 @@ static void hevc_hz_biwgt_4t_8x4multiple_msa(uint8_t *src0_ptr, v16i8 vec0, vec1; v8i16 in0, in1, in2, in3; v8i16 dst0, dst1, dst2, dst3; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; @@ -3055,12 +3137,10 @@ static void hevc_hz_biwgt_4t_8x4multiple_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + dst0, dst1, dst2, dst3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); + ST8x4_UB(dst0, dst1, dst, dst_stride); dst += (4 * dst_stride); } } @@ -3123,8 +3203,6 @@ static void hevc_hz_biwgt_4t_12w_msa(uint8_t *src0_ptr, v16i8 vec0, vec1; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -3176,17 +3254,14 @@ static void hevc_hz_biwgt_4t_12w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + dst0, dst1, dst2, dst3); HEVC_BIW_RND_CLIP2(dst4, dst5, in4, in5, weight_vec, rnd_vec, offset_vec, - dst4_r, dst5_r, dst4_l, dst5_l); + dst4, dst5); - HEVC_PCK_SW_SB12(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - dst4_l, dst4_r, dst5_l, dst5_r, - dst0_r, dst1_r, dst2_r); - ST12x4_UB(dst0_r, dst1_r, dst2_r, dst, dst_stride); + PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); + dst3 = (v8i16) __msa_pckev_b((v16i8) dst5, (v16i8) dst4); + ST12x4_UB(dst0, dst1, dst3, dst, dst_stride); dst += (4 * dst_stride); } } @@ -3215,7 +3290,6 @@ static void hevc_hz_biwgt_4t_16w_msa(uint8_t *src0_ptr, v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; v16i8 vec0, vec1; v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -3271,23 +3345,19 @@ static void hevc_hz_biwgt_4t_16w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + dst0, dst1, dst2, dst3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); + ST_SH2(dst0, dst1, dst, dst_stride); dst += (2 * dst_stride); HEVC_BIW_RND_CLIP4(dst4, dst5, dst6, dst7, in4, in5, in6, in7, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + dst0, dst1, dst2, dst3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); + ST_SH2(dst0, dst1, dst, dst_stride); dst += (2 * dst_stride); } } @@ -3317,7 +3387,6 @@ static void hevc_hz_biwgt_4t_24w_msa(uint8_t *src0_ptr, v8i16 dst0, dst1, dst2, dst3; v8i16 in0, in1, in2, in3, in4, in5; v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -3364,12 +3433,10 @@ static void hevc_hz_biwgt_4t_24w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + dst0, dst1, dst2, dst3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); + ST_SH2(dst0, dst1, dst, dst_stride); dst += (2 * dst_stride); /* 8 width */ VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); @@ -3380,10 +3447,10 @@ static void hevc_hz_biwgt_4t_24w_msa(uint8_t *src0_ptr, DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); HEVC_BIW_RND_CLIP2(dst0, dst1, in4, in5, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + dst0, dst1); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST8x2_UB(dst0_r, dst_tmp, dst_stride); + dst0 = (v8i16) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); + ST8x2_UB(dst0, dst_tmp, dst_stride); dst_tmp += (2 * dst_stride); } } @@ -3412,7 +3479,6 @@ static void hevc_hz_biwgt_4t_32w_msa(uint8_t *src0_ptr, v16i8 vec0, vec1; v8i16 in0, in1, in2, in3; v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -3457,12 +3523,10 @@ static void hevc_hz_biwgt_4t_32w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + dst0, dst1, dst2, dst3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, 16); + PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); + ST_SH2(dst0, dst1, dst, 16); dst += dst_stride; } } @@ -3554,7 +3618,6 @@ static void hevc_vt_biwgt_4t_4x4_msa(uint8_t *src0_ptr, v16i8 src10_r, src32_r, src54_r, src21_r, src43_r, src65_r; v16i8 src2110, src4332, src6554; v8i16 dst10, dst32; - v4i32 dst10_r, dst32_r, dst10_l, dst32_l; v8i16 filt0, filt1; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; @@ -3597,10 +3660,10 @@ static void hevc_vt_biwgt_4t_4x4_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP2(dst10, dst32, in0, in1, weight_vec, rnd_vec, offset_vec, - dst10_r, dst32_r, dst10_l, dst32_l); + dst10, dst32); - HEVC_PCK_SW_SB4(dst10_l, dst10_r, dst32_l, dst32_r, dst10_r); - ST4x4_UB(dst10_r, dst10_r, 0, 1, 2, 3, dst, dst_stride); + dst10 = (v8i16) __msa_pckev_b((v16i8) dst32, (v16i8) dst10); + ST4x4_UB(dst10, dst10, 0, 1, 2, 3, dst, dst_stride); dst += (4 * dst_stride); } @@ -3626,8 +3689,6 @@ static void hevc_vt_biwgt_4t_4x8multiple_msa(uint8_t *src0_ptr, v16i8 src21_r, src43_r, src65_r, src87_r, src109_r; v16i8 src2110, src4332, src6554, src8776; v8i16 dst10, dst32, dst54, dst76; - v4i32 dst10_r, dst32_r, dst54_r, dst76_r; - v4i32 dst10_l, dst32_l, dst54_l, dst76_l; v8i16 filt0, filt1; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; @@ -3687,12 +3748,10 @@ static void hevc_vt_biwgt_4t_4x8multiple_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(dst10, dst32, dst54, dst76, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst10_r, dst32_r, dst54_r, dst76_r, - dst10_l, dst32_l, dst54_l, dst76_l); + dst10, dst32, dst54, dst76); - HEVC_PCK_SW_SB8(dst10_l, dst10_r, dst32_l, dst32_r, - dst54_l, dst54_r, dst76_l, dst76_r, dst10_r, dst54_r); - ST4x8_UB(dst10_r, dst54_r, dst, dst_stride); + PCKEV_B2_SH(dst32, dst10, dst76, dst54, dst10, dst32); + ST4x8_UB(dst10, dst32, dst, dst_stride); dst += (8 * dst_stride); } } @@ -3751,7 +3810,6 @@ static void hevc_vt_biwgt_4t_6w_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; src0_ptr -= src_stride; @@ -3798,12 +3856,10 @@ static void hevc_vt_biwgt_4t_6w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + tmp0, tmp1, tmp2, tmp3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST6x4_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + ST6x4_UB(tmp0, tmp1, dst, dst_stride); dst += (4 * dst_stride); } } @@ -3829,7 +3885,6 @@ static void hevc_vt_biwgt_4t_8x2_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst0_l, dst1_l; src0_ptr -= src_stride; @@ -3862,10 +3917,10 @@ static void hevc_vt_biwgt_4t_8x2_msa(uint8_t *src0_ptr, DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); HEVC_BIW_RND_CLIP2(tmp0, tmp1, in0, in1, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + tmp0, tmp1); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST8x2_UB(dst0_r, dst, dst_stride); + tmp0 = (v8i16) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); + ST8x2_UB(tmp0, dst, dst_stride); } static void hevc_vt_biwgt_4t_8x6_msa(uint8_t *src0_ptr, @@ -3891,8 +3946,6 @@ static void hevc_vt_biwgt_4t_8x6_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; src0_ptr -= src_stride; @@ -3936,18 +3989,16 @@ static void hevc_vt_biwgt_4t_8x6_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + tmp0, tmp1, tmp2, tmp3); HEVC_BIW_RND_CLIP2(tmp4, tmp5, in4, in5, weight_vec, rnd_vec, offset_vec, - dst4_r, dst5_r, dst4_l, dst5_l); + tmp4, tmp5); - HEVC_PCK_SW_SB12(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - dst4_l, dst4_r, dst5_l, dst5_r, dst0_r, dst1_r, dst2_r); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + tmp3 = (v8i16) __msa_pckev_b((v16i8) tmp5, (v16i8) tmp4); + ST8x4_UB(tmp0, tmp1, dst, dst_stride); dst += (4 * dst_stride); - ST8x2_UB(dst2_r, dst, dst_stride); + ST8x2_UB(tmp3, dst, dst_stride); } static void hevc_vt_biwgt_4t_8x4multiple_msa(uint8_t *src0_ptr, @@ -3973,7 +4024,6 @@ static void hevc_vt_biwgt_4t_8x4multiple_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; src0_ptr -= src_stride; @@ -4020,12 +4070,10 @@ static void hevc_vt_biwgt_4t_8x4multiple_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + tmp0, tmp1, tmp2, tmp3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + ST8x4_UB(tmp0, tmp1, dst, dst_stride); dst += (4 * dst_stride); } } @@ -4086,8 +4134,6 @@ static void hevc_vt_biwgt_4t_12w_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; src0_ptr -= (1 * src_stride); @@ -4147,17 +4193,14 @@ static void hevc_vt_biwgt_4t_12w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + tmp0, tmp1, tmp2, tmp3); HEVC_BIW_RND_CLIP2(tmp4, tmp5, in4, in5, weight_vec, rnd_vec, offset_vec, - dst4_r, dst5_r, dst4_l, dst5_l); + tmp4, tmp5); - HEVC_PCK_SW_SB12(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - dst4_l, dst4_r, dst5_l, dst5_r, - dst0_r, dst1_r, dst2_r); - ST12x4_UB(dst0_r, dst1_r, dst2_r, dst, dst_stride); + PCKEV_B2_SH(tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + tmp2 = (v8i16) __msa_pckev_b((v16i8) tmp5, (v16i8) tmp4); + ST12x4_UB(tmp0, tmp1, tmp2, dst, dst_stride); dst += (4 * dst_stride); } } @@ -4186,7 +4229,6 @@ static void hevc_vt_biwgt_4t_16w_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; src0_ptr -= src_stride; @@ -4231,11 +4273,9 @@ static void hevc_vt_biwgt_4t_16w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); + tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_SH(tmp2, tmp0, tmp3, tmp1, tmp0, tmp1); + ST_SH2(tmp0, tmp1, dst, dst_stride); dst += (2 * dst_stride); LD_SB2(src0_ptr, src_stride, src5, src2); src0_ptr += (2 * src_stride); @@ -4258,12 +4298,10 @@ static void hevc_vt_biwgt_4t_16w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + tmp0, tmp1, tmp2, tmp3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(tmp2, tmp0, tmp3, tmp1, tmp0, tmp1); + ST_SH2(tmp0, tmp1, dst, dst_stride); dst += (2 * dst_stride); } } @@ -4294,8 +4332,6 @@ static void hevc_vt_biwgt_4t_24w_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; src0_ptr -= src_stride; @@ -4357,19 +4393,17 @@ static void hevc_vt_biwgt_4t_24w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp4, tmp5, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + tmp0, tmp1, tmp4, tmp5); /* 8width */ HEVC_BIW_RND_CLIP2(tmp2, tmp3, in4, in5, weight_vec, rnd_vec, offset_vec, - dst4_r, dst5_r, dst4_l, dst5_l); + tmp2, tmp3); /* 16width */ - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); + PCKEV_B2_SH(tmp4, tmp0, tmp5, tmp1, tmp0, tmp1); /* 8width */ - HEVC_PCK_SW_SB4(dst4_l, dst4_r, dst5_l, dst5_r, dst4_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); - ST8x2_UB(dst4_r, dst + 16, dst_stride); + tmp2 = (v8i16) __msa_pckev_b((v16i8) tmp3, (v16i8) tmp2); + ST_SH2(tmp0, tmp1, dst, dst_stride); + ST8x2_UB(tmp2, dst + 16, dst_stride); dst += (2 * dst_stride); /* 16width */ @@ -4404,20 +4438,18 @@ static void hevc_vt_biwgt_4t_24w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp4, tmp5, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + tmp0, tmp1, tmp4, tmp5); /* 8width */ HEVC_BIW_RND_CLIP2(tmp2, tmp3, in4, in5, weight_vec, rnd_vec, offset_vec, - dst4_r, dst5_r, dst4_l, dst5_l); + tmp2, tmp3); /* 16width */ - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); + PCKEV_B2_SH(tmp4, tmp0, tmp5, tmp1, tmp0, tmp1); /* 8width */ - HEVC_PCK_SW_SB4(dst4_l, dst4_r, dst5_l, dst5_r, dst4_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); - ST8x2_UB(dst4_r, dst + 16, dst_stride); + tmp2 = (v8i16) __msa_pckev_b((v16i8) tmp3, (v16i8) tmp2); + ST_SH2(tmp0, tmp1, dst, dst_stride); + ST8x2_UB(tmp2, dst + 16, dst_stride); dst += (2 * dst_stride); } } @@ -4449,8 +4481,6 @@ static void hevc_vt_biwgt_4t_32w_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v8i16 filter_vec, const_vec; v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r, dst6_r, dst7_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l, dst6_l, dst7_l; src0_ptr -= src_stride; @@ -4501,12 +4531,10 @@ static void hevc_vt_biwgt_4t_32w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp4, tmp5, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + tmp0, tmp1, tmp4, tmp5); /* 16width */ - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(tmp4, tmp0, tmp5, tmp1, tmp0, tmp1); + ST_SH2(tmp0, tmp1, dst, dst_stride); dst += (2 * dst_stride); src10_r = src32_r; @@ -4537,13 +4565,11 @@ static void hevc_vt_biwgt_4t_32w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp2, tmp3, tmp6, tmp7, in4, in5, in6, in7, weight_vec, rnd_vec, offset_vec, - dst4_r, dst5_r, dst6_r, dst7_r, - dst4_l, dst5_l, dst6_l, dst7_l); + tmp2, tmp3, tmp6, tmp7); /* next 16width */ - HEVC_PCK_SW_SB8(dst4_l, dst4_r, dst6_l, dst6_r, - dst5_l, dst5_r, dst7_l, dst7_r, dst4_r, dst5_r); - ST_SW2(dst4_r, dst5_r, dst_tmp, dst_stride); + PCKEV_B2_SH(tmp6, tmp2, tmp7, tmp3, tmp2, tmp3); + ST_SH2(tmp2, tmp3, dst_tmp, dst_stride); dst_tmp += (2 * dst_stride); src76_r = src98_r; @@ -4678,7 +4704,6 @@ static void hevc_hv_biwgt_4t_4x4_msa(uint8_t *src0_ptr, v16i8 vec0, vec1, vec2, vec3, vec4, vec5; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; v8i16 tmp0, tmp1; - v4i32 dst0_l, dst1_l; v4i32 dst0_r, dst1_r, dst2_r, dst3_r; v8i16 dst10_r, dst32_r, dst21_r, dst43_r; v4i32 weight_vec, offset_vec, rnd_vec; @@ -4756,10 +4781,10 @@ static void hevc_hv_biwgt_4t_4x4_msa(uint8_t *src0_ptr, PCKEV_H2_SH(dst1_r, dst0_r, dst3_r, dst2_r, tmp0, tmp1); HEVC_BIW_RND_CLIP2(tmp0, tmp1, in0, in1, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + tmp0, tmp1); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST4x4_UB(dst0_r, dst0_r, 0, 1, 2, 3, dst, dst_stride); + tmp0 = (v8i16) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); + ST4x4_UB(tmp0, tmp0, 0, 1, 2, 3, dst, dst_stride); } static void hevc_hv_biwgt_4t_4multx8mult_msa(uint8_t *src0_ptr, @@ -4789,7 +4814,6 @@ static void hevc_hv_biwgt_4t_4multx8mult_msa(uint8_t *src0_ptr, v16i8 vec0, vec1, vec2, vec3, vec4, vec5; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8, dst9; v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r, dst6_r, dst7_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l; v8i16 tmp0, tmp1, tmp2, tmp3; v8i16 dst10_r, dst32_r, dst54_r, dst76_r; v8i16 dst21_r, dst43_r, dst65_r, dst87_r; @@ -4899,12 +4923,10 @@ static void hevc_hv_biwgt_4t_4multx8mult_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + tmp0, tmp1, tmp2, tmp3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST4x8_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + ST4x8_UB(tmp0, tmp1, dst, dst_stride); dst += (8 * dst_stride); } } @@ -5065,12 +5087,10 @@ static void hevc_hv_biwgt_4t_6w_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + tmp0, tmp1, tmp2, tmp3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST6x4_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + ST6x4_UB(tmp0, tmp1, dst, dst_stride); dst += (4 * dst_stride); } } @@ -5175,9 +5195,9 @@ static void hevc_hv_biwgt_4t_8x2_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP2(tmp0, tmp1, in0, in1, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst0_l, dst1_l); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST8x2_UB(dst0_r, dst, dst_stride); + tmp0, tmp1); + tmp0 = (v8i16) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); + ST8x2_UB(tmp0, dst, dst_stride); } static void hevc_hv_biwgt_4t_8x6_msa(uint8_t *src0_ptr, @@ -5309,12 +5329,10 @@ static void hevc_hv_biwgt_4t_8x6_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + tmp0, tmp1, tmp2, tmp3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_SH(tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + ST8x4_UB(tmp0, tmp1, dst, dst_stride); dst += (4 * dst_stride); LD_SB2(src0_ptr, src_stride, src7, src8); @@ -5344,10 +5362,10 @@ static void hevc_hv_biwgt_4t_8x6_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP2(tmp4, tmp5, in4, in5, weight_vec, rnd_vec, offset_vec, - dst4_r, dst5_r, dst4_l, dst5_l); + tmp4, tmp5); - HEVC_PCK_SW_SB4(dst4_l, dst4_r, dst5_l, dst5_r, dst2_r); - ST8x2_UB(dst2_r, dst, dst_stride); + tmp4 = (v8i16) __msa_pckev_b((v16i8) tmp5, (v16i8) tmp4); + ST8x2_UB(tmp4, dst, dst_stride); } static void hevc_hv_biwgt_4t_8multx4mult_msa(uint8_t *src0_ptr, @@ -5484,12 +5502,10 @@ static void hevc_hv_biwgt_4t_8multx4mult_msa(uint8_t *src0_ptr, HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + tmp0, tmp1, tmp2, tmp3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST8x4_UB(dst0_r, dst1_r, dst_tmp, dst_stride); + PCKEV_B2_SH(tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + ST8x4_UB(tmp0, tmp1, dst_tmp, dst_stride); dst_tmp += (4 * dst_stride); } From e39c0f29a17fb9d83596539c7f99db1bc16c09b0 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Fri, 27 Oct 2017 18:35:28 +0530 Subject: [PATCH 0699/2557] avcodec/mips: Improve hevc bi hz and hv mc msa functions Align the mask buffer. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_bi_msa.c | 940 +++++++++++++++++++------------ 1 file changed, 595 insertions(+), 345 deletions(-) diff --git a/libavcodec/mips/hevc_mc_bi_msa.c b/libavcodec/mips/hevc_mc_bi_msa.c index ccc3f8a64f741..9c03ef8c5ae78 100644 --- a/libavcodec/mips/hevc_mc_bi_msa.c +++ b/libavcodec/mips/hevc_mc_bi_msa.c @@ -22,6 +22,12 @@ #include "libavcodec/mips/hevcdsp_mips.h" #include "libavcodec/mips/hevc_macros_msa.h" +static const uint8_t ff_hevc_mask_arr[16 * 2] __attribute__((aligned(0x40))) = { + /* 8 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 +}; + #define HEVC_BI_RND_CLIP2(in0, in1, vec0, vec1, rnd_val, out0, out1) \ { \ ADDS_SH2_SH(vec0, in0, vec1, in1, out0, out1); \ @@ -531,7 +537,7 @@ static void hevc_hz_bi_8t_4w_msa(uint8_t *src0_ptr, v8i16 dst0, dst1, dst2, dst3; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[16]); src0_ptr -= 3; @@ -557,26 +563,26 @@ static void hevc_hz_bi_8t_4w_msa(uint8_t *src0_ptr, ILVR_D2_SH(in5, in4, in7, in6, in2, in3); XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); - VSHF_B4_SB(src0, src1, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - VSHF_B4_SB(src2, src3, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - VSHF_B4_SB(src4, src5, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - VSHF_B4_SB(src6, src7, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + VSHF_B2_SB(src0, src1, src2, src3, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src4, src5, src6, src7, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src1, src2, src3, mask1, mask1, vec0, vec1); + VSHF_B2_SB(src4, src5, src6, src7, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src1, src2, src3, mask2, mask2, vec0, vec1); + VSHF_B2_SB(src4, src5, src6, src7, mask2, mask2, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src1, src2, src3, mask3, mask3, vec0, vec1); + VSHF_B2_SB(src4, src5, src6, src7, mask3, mask3, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt3, filt3, filt3, filt3, dst0, + dst1, dst2, dst3); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); @@ -604,7 +610,7 @@ static void hevc_hz_bi_8t_8w_msa(uint8_t *src0_ptr, v8i16 dst0, dst1, dst2, dst3; v8i16 in0, in1, in2, in3; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); src0_ptr -= 3; @@ -625,26 +631,26 @@ static void hevc_hz_bi_8t_8w_msa(uint8_t *src0_ptr, src1_ptr += (4 * src2_stride); XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask3, mask3, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask3, mask3, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt3, filt3, filt3, filt3, dst0, + dst1, dst2, dst3); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); @@ -664,10 +670,83 @@ static void hevc_hz_bi_8t_12w_msa(uint8_t *src0_ptr, const int8_t *filter, int32_t height) { - hevc_hz_bi_8t_8w_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter, height); - hevc_hz_bi_8t_4w_msa(src0_ptr + 8, src_stride, src1_ptr + 8, src2_stride, - dst + 8, dst_stride, filter, height); + uint32_t loop_cnt; + int32_t tmp0, tmp1; + int64_t tmp2, tmp3; + v16i8 src0, src1, src2, src3; + v16i8 vec0, vec1, vec2; + v8i16 filt0, filt1, filt2, filt3; + v16i8 mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask7; + v8i16 dst0, dst1, dst2; + v8i16 in0, in1, in2, in3; + v8i16 filter_vec, const_vec; + + src0_ptr -= 3; + const_vec = __msa_ldi_h(128); + const_vec <<= 6; + + filter_vec = LD_SH(filter); + SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + mask2 = mask0 + 4; + mask3 = mask0 + 6; + mask4 = LD_SB(&ff_hevc_mask_arr[16]); + mask5 = mask4 + 2; + mask6 = mask4 + 4; + mask7 = mask4 + 6; + + for (loop_cnt = 8; loop_cnt--;) { + LD_SB2(src0_ptr, 8, src0, src1); + src0_ptr += src_stride; + LD_SB2(src0_ptr, 8, src2, src3); + src0_ptr += src_stride; + LD_SH2(src1_ptr, 8, in0, in1); + src1_ptr += src2_stride; + LD_SH2(src1_ptr, 8, in2, in3); + src1_ptr += src2_stride; + XORI_B4_128_SB(src0, src1, src2, src3); + + dst0 = const_vec; + dst1 = const_vec; + dst2 = const_vec; + + VSHF_B3_SB(src0, src0, src1, src3, src2, src2, mask0, mask4, mask0, + vec0, vec1, vec2); + DPADD_SB2_SH(vec0, vec1, filt0, filt0, dst0, dst1); + dst2 = __msa_dpadd_s_h(dst2, vec2, (v16i8) filt0); + VSHF_B3_SB(src0, src0, src1, src3, src2, src2, mask1, mask5, mask1, + vec0, vec1, vec2); + DPADD_SB2_SH(vec0, vec1, filt1, filt1, dst0, dst1); + dst2 = __msa_dpadd_s_h(dst2, vec2, (v16i8) filt1); + VSHF_B3_SB(src0, src0, src1, src3, src2, src2, mask2, mask6, mask2, + vec0, vec1, vec2); + DPADD_SB2_SH(vec0, vec1, filt2, filt2, dst0, dst1); + dst2 = __msa_dpadd_s_h(dst2, vec2, (v16i8) filt2); + VSHF_B3_SB(src0, src0, src1, src3, src2, src2, mask3, mask7, mask3, + vec0, vec1, vec2); + DPADD_SB2_SH(vec0, vec1, filt3, filt3, dst0, dst1); + dst2 = __msa_dpadd_s_h(dst2, vec2, (v16i8) filt3); + + in1 = (v8i16) __msa_pckev_d((v2i64) in3, (v2i64) in1); + HEVC_BI_RND_CLIP2(in0, in1, dst0, dst1, 7, dst0, dst1); + dst2 = __msa_adds_s_h(in2, dst2); + dst2 = __msa_srari_h(dst2, 7); + dst2 = CLIP_SH_0_255(dst2); + PCKEV_B2_SH(dst1, dst0, dst2, dst2, dst0, dst1); + + tmp2 = __msa_copy_s_d((v2i64) dst0, 0); + tmp0 = __msa_copy_s_w((v4i32) dst0, 2); + tmp3 = __msa_copy_s_d((v2i64) dst1, 0); + tmp1 = __msa_copy_s_w((v4i32) dst0, 3); + SD(tmp2, dst); + SW(tmp0, dst + 8); + dst += dst_stride; + SD(tmp3, dst); + SW(tmp1, dst + 8); + dst += dst_stride; + } } static void hevc_hz_bi_8t_16w_msa(uint8_t *src0_ptr, @@ -687,7 +766,7 @@ static void hevc_hz_bi_8t_16w_msa(uint8_t *src0_ptr, v8i16 dst0, dst1, dst2, dst3; v8i16 in0, in1, in2, in3; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); src0_ptr -= 3; const_vec = __msa_ldi_h(128); @@ -711,26 +790,26 @@ static void hevc_hz_bi_8t_16w_msa(uint8_t *src0_ptr, src1_ptr += src2_stride; XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask3, mask3, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask3, mask3, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt3, filt3, filt3, filt3, dst0, + dst1, dst2, dst3); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); @@ -759,7 +838,7 @@ static void hevc_hz_bi_8t_24w_msa(uint8_t *src0_ptr, v8i16 dst0, dst1, dst2; v8i16 in0, in1, in2; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); src0_ptr = src0_ptr - 3; const_vec = __msa_ldi_h(128); @@ -784,21 +863,21 @@ static void hevc_hz_bi_8t_24w_msa(uint8_t *src0_ptr, src1_ptr += src2_stride; XORI_B2_128_SB(src0, src1); - VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - VSHF_B4_SB(src0, src1, mask4, mask5, mask6, mask7, - vec0, vec1, vec2, vec3); dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); + VSHF_B2_SB(src0, src0, src0, src1, mask0, mask4, vec0, vec1); + VSHF_B2_SB(src1, src1, src0, src0, mask0, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt1, dst0, + dst1, dst2, dst0); + VSHF_B2_SB(src0, src1, src1, src1, mask5, mask1, vec0, vec1); + VSHF_B2_SB(src0, src0, src0, src1, mask2, mask6, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt2, filt2, dst1, + dst2, dst0, dst1); + VSHF_B2_SB(src1, src1, src0, src0, mask2, mask3, vec0, vec1); + VSHF_B2_SB(src0, src1, src1, src1, mask7, mask3, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt3, filt3, filt3, dst2, + dst0, dst1, dst2); HEVC_BI_RND_CLIP2(in0, in1, dst0, dst1, 7, dst0, dst1); dst2 = __msa_adds_s_h(dst2, in2); @@ -830,7 +909,7 @@ static void hevc_hz_bi_8t_32w_msa(uint8_t *src0_ptr, v8i16 dst0, dst1, dst2, dst3; v8i16 in0, in1, in2, in3; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); src0_ptr -= 3; const_vec = __msa_ldi_h(128); @@ -855,26 +934,26 @@ static void hevc_hz_bi_8t_32w_msa(uint8_t *src0_ptr, src1_ptr += src2_stride; XORI_B3_128_SB(src0, src1, src2); - VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - VSHF_B4_SB(src0, src1, mask4, mask5, mask6, mask7, - vec0, vec1, vec2, vec3); dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask0, mask4, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask1, mask5, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask2, mask6, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask2, mask2, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask3, mask7, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask3, mask3, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt3, filt3, filt3, filt3, dst0, + dst1, dst2, dst3); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); @@ -903,7 +982,7 @@ static void hevc_hz_bi_8t_48w_msa(uint8_t *src0_ptr, v8i16 dst0, dst1, dst2, dst3, dst4, dst5; v8i16 in0, in1, in2, in3, in4, in5; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); src0_ptr -= 3; @@ -921,62 +1000,53 @@ static void hevc_hz_bi_8t_48w_msa(uint8_t *src0_ptr, mask6 = mask0 + 12; mask7 = mask0 + 14; - for (loop_cnt = height; loop_cnt--;) { - LD_SB2(src0_ptr, 16, src0, src1); - XORI_B2_128_SB(src0, src1); - LD_SH2(src1_ptr, 8, in0, in1); + for (loop_cnt = 64; loop_cnt--;) { + LD_SB3(src0_ptr, 16, src0, src1, src2); + src3 = LD_SB(src0_ptr + 40); + src0_ptr += src_stride; + LD_SH4(src1_ptr, 8, in0, in1, in2, in3); + XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - VSHF_B4_SB(src0, src1, mask4, mask5, mask6, mask7, - vec0, vec1, vec2, vec3); dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - - HEVC_BI_RND_CLIP2(in0, in1, dst0, dst1, 7, dst0, dst1); - - tmp0 = __msa_pckev_b((v16i8) dst1, (v16i8) dst0); - ST_SB(tmp0, dst); - - LD_SB2(src0_ptr + 32, 8, src2, src3); - XORI_B2_128_SB(src2, src3); - src0_ptr += src_stride; - - LD_SH2(src1_ptr + 16, 8, in2, in3); - - VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - VSHF_B4_SB(src1, src2, mask4, mask5, mask6, mask7, - vec0, vec1, vec2, vec3); dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask0, mask4, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src2, mask0, mask4, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask1, mask5, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src2, mask1, mask5, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask2, mask6, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src2, mask2, mask6, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask3, mask7, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src2, mask3, mask7, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt3, filt3, filt3, filt3, dst0, + dst1, dst2, dst3); + HEVC_BI_RND_CLIP2(in0, in1, dst0, dst1, 7, dst0, dst1); HEVC_BI_RND_CLIP2(in2, in3, dst2, dst3, 7, dst2, dst3); - - tmp1 = __msa_pckev_b((v16i8) dst3, (v16i8) dst2); + PCKEV_B2_SB(dst1, dst0, dst3, dst2, tmp0, tmp1); + ST_SB(tmp0, dst); ST_SB(tmp1, dst + 16); LD_SH2(src1_ptr + 32, 8, in4, in5); src1_ptr += src2_stride; - VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst4 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst4, dst4, dst4, dst4); - VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst5 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst5, dst5, dst5, dst5); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt1, filt1, dst4, + dst5, dst4, dst5); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask3, mask3, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt3, filt3, dst4, + dst5, dst4, dst5); HEVC_BI_RND_CLIP2(in4, in5, dst4, dst5, 7, dst4, dst5); @@ -995,14 +1065,10 @@ static void hevc_hz_bi_8t_64w_msa(uint8_t *src0_ptr, const int8_t *filter, int32_t height) { - uint8_t *src0_ptr_tmp; - uint8_t *dst_tmp; - int16_t *src1_ptr_tmp; uint32_t loop_cnt; - uint32_t cnt; - v16i8 src0, src1, src2, tmp0, tmp1; + v16i8 src0, src1, src2, src3, src4, src5, tmp0, tmp1; v8i16 filt0, filt1, filt2, filt3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1, mask2, mask3, mask4, mask5, mask6, mask7; v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2, dst3; @@ -1026,48 +1092,74 @@ static void hevc_hz_bi_8t_64w_msa(uint8_t *src0_ptr, mask7 = mask0 + 14; for (loop_cnt = height; loop_cnt--;) { - src0_ptr_tmp = src0_ptr; - dst_tmp = dst; - src1_ptr_tmp = src1_ptr; + LD_SB2(src0_ptr, 16, src0, src1); + src2 = LD_SB(src0_ptr + 24); + LD_SB2(src0_ptr + 32, 16, src3, src4); + src5 = LD_SB(src0_ptr + 56); + LD_SH4(src1_ptr, 8, in0, in1, in2, in3); + XORI_B3_128_SB(src0, src1, src2); - for (cnt = 2; cnt--;) { - LD_SB2(src0_ptr_tmp, 16, src0, src1); - src2 = LD_SB(src0_ptr_tmp + 24); - src0_ptr_tmp += 32; - LD_SH4(src1_ptr_tmp, 8, in0, in1, in2, in3); - src1_ptr_tmp += 32; - XORI_B3_128_SB(src0, src1, src2); + dst0 = const_vec; + dst1 = const_vec; + dst2 = const_vec; + dst3 = const_vec; - VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); - dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - VSHF_B4_SB(src0, src1, mask4, mask5, mask6, mask7, - vec0, vec1, vec2, vec3); - dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); - dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); - dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask0, mask4, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask1, mask5, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask2, mask6, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask2, mask2, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask3, mask7, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask3, mask3, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt3, filt3, filt3, filt3, dst0, + dst1, dst2, dst3); - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - dst0, dst1, dst2, dst3, 7, - dst0, dst1, dst2, dst3); + HEVC_BI_RND_CLIP4(in0, in1, in2, in3, + dst0, dst1, dst2, dst3, 7, + dst0, dst1, dst2, dst3); - PCKEV_B2_SB(dst1, dst0, dst3, dst2, tmp0, tmp1); - ST_SB2(tmp0, tmp1, dst_tmp, 16); - dst_tmp += 32; - } + PCKEV_B2_SB(dst1, dst0, dst3, dst2, tmp0, tmp1); + ST_SB2(tmp0, tmp1, dst, 16); + + src0 = src3; + src1 = src4; + src2 = src5; + LD_SH4(src1_ptr + 32, 8, in0, in1, in2, in3); + XORI_B3_128_SB(src0, src1, src2); + + dst0 = const_vec; + dst1 = const_vec; + dst2 = const_vec; + dst3 = const_vec; + VSHF_B2_SB(src0, src0, src0, src1, mask0, mask4, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask1, mask5, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask2, mask6, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask2, mask2, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask3, mask7, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask3, mask3, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt3, filt3, filt3, filt3, dst0, + dst1, dst2, dst3); + HEVC_BI_RND_CLIP4(in0, in1, in2, in3, + dst0, dst1, dst2, dst3, 7, + dst0, dst1, dst2, dst3); + PCKEV_B2_SB(dst1, dst0, dst3, dst2, tmp0, tmp1); + ST_SB2(tmp0, tmp1, dst + 32, 16); src1_ptr += src2_stride; src0_ptr += src_stride; dst += dst_stride; @@ -1528,30 +1620,30 @@ static void hevc_hv_bi_8t_4w_msa(uint8_t *src0_ptr, int32_t height) { uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; - v8i16 in0, in1; + uint64_t tp0, tp1; + v16u8 out; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v8i16 in0 = { 0 }, in1 = { 0 }; v8i16 filt0, filt1, filt2, filt3; - v4i32 filt_h0, filt_h1, filt_h2, filt_h3; + v8i16 filt_h0, filt_h1, filt_h2, filt_h3; v16i8 mask1, mask2, mask3; v8i16 filter_vec, const_vec; v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; - v8i16 dst30, dst41, dst52, dst63, dst66, dst87; - v4i32 dst0_r, dst1_r, in0_r, in0_l; - v8i16 dst10_r, dst32_r, dst54_r, dst76_r; - v8i16 dst21_r, dst43_r, dst65_r, dst87_r; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; - v8u16 mask4 = { 0, 4, 1, 5, 2, 6, 3, 7 }; + v8i16 out0, out1; + v8i16 dst30, dst41, dst52, dst63, dst66, dst97, dst108; + v8i16 dst10, dst32, dst54, dst76, dst98, dst21, dst43, dst65, dst87, dst109; + v4i32 dst0, dst1, dst2, dst3; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); src0_ptr -= ((3 * src_stride) + 3); filter_vec = LD_SH(filter_x); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W4_SW(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); mask1 = mask0 + 2; mask2 = mask0 + 4; @@ -1572,71 +1664,77 @@ static void hevc_hv_bi_8t_4w_msa(uint8_t *src0_ptr, VSHF_B4_SB(src3, src6, mask0, mask1, mask2, mask3, vec12, vec13, vec14, vec15); - dst30 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst30, dst30, dst30, dst30); - dst41 = const_vec; - DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, - dst41, dst41, dst41, dst41); - dst52 = const_vec; - DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, - dst52, dst52, dst52, dst52); - dst63 = const_vec; - DPADD_SB4_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, filt3, - dst63, dst63, dst63, dst63); - - ILVR_H3_SH(dst41, dst30, dst52, dst41, dst63, dst52, - dst10_r, dst21_r, dst32_r); - dst43_r = __msa_ilvl_h(dst41, dst30); - dst54_r = __msa_ilvl_h(dst52, dst41); - dst65_r = __msa_ilvl_h(dst63, dst52); + dst30 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst41 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst52 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst63 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, + filt3); + + ILVRL_H2_SH(dst41, dst30, dst10, dst43); + ILVRL_H2_SH(dst52, dst41, dst21, dst54); + ILVRL_H2_SH(dst63, dst52, dst32, dst65); + dst66 = (v8i16) __msa_splati_d((v2i64) dst63, 1); - for (loop_cnt = height >> 1; loop_cnt--;) { - LD_SB2(src0_ptr, src_stride, src7, src8); - src0_ptr += (2 * src_stride); - LD_SH2(src1_ptr, src2_stride, in0, in1); - src1_ptr += (2 * src2_stride); + for (loop_cnt = height >> 2; loop_cnt--;) { + LD_SB4(src0_ptr, src_stride, src7, src8, src9, src10); + src0_ptr += (4 * src_stride); + XORI_B4_128_SB(src7, src8, src9, src10); - in0 = (v8i16) __msa_ilvr_d((v2i64) in1, (v2i64) in0); - XORI_B2_128_SB(src7, src8); + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in0); + src1_ptr += (2 * src2_stride); + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in1); + src1_ptr += (2 * src2_stride); - VSHF_B4_SB(src7, src8, mask0, mask1, mask2, mask3, + VSHF_B4_SB(src7, src9, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst87 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst87, dst87, dst87, dst87); - dst76_r = __msa_ilvr_h(dst87, dst66); - dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, - filt_h0, filt_h1, filt_h2, filt_h3); - dst87_r = __msa_vshf_h((v8i16) mask4, dst87, dst87); - dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, - filt_h0, filt_h1, filt_h2, filt_h3); - - dst0_r >>= 6; - dst1_r >>= 6; - UNPCK_SH_SW(in0, in0_r, in0_l); - dst0_r = __msa_adds_s_w(dst0_r, in0_r); - dst1_r = __msa_adds_s_w(dst1_r, in0_l); - SRARI_W2_SW(dst0_r, dst1_r, 7); - dst0_r = CLIP_SW_0_255(dst0_r); - dst1_r = CLIP_SW_0_255(dst1_r); - - HEVC_PCK_SW_SB2(dst1_r, dst0_r, dst0_r); - ST4x2_UB(dst0_r, dst, dst_stride); - dst += (2 * dst_stride); + VSHF_B4_SB(src8, src10, mask0, mask1, mask2, mask3, + vec4, vec5, vec6, vec7); + dst97 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst108 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + + dst76 = __msa_ilvr_h(dst97, dst66); + ILVRL_H2_SH(dst108, dst97, dst87, dst109); + dst66 = (v8i16) __msa_splati_d((v2i64) dst97, 1); + dst98 = __msa_ilvr_h(dst66, dst108); + + dst0 = HEVC_FILT_8TAP(dst10, dst32, dst54, dst76, filt_h0, filt_h1, + filt_h2, filt_h3); + dst1 = HEVC_FILT_8TAP(dst21, dst43, dst65, dst87, filt_h0, filt_h1, + filt_h2, filt_h3); + dst2 = HEVC_FILT_8TAP(dst32, dst54, dst76, dst98, filt_h0, filt_h1, + filt_h2, filt_h3); + dst3 = HEVC_FILT_8TAP(dst43, dst65, dst87, dst109, filt_h0, filt_h1, + filt_h2, filt_h3); + + SRA_4V(dst0, dst1, dst2, dst3, 6); + PCKEV_H2_SH(dst1, dst0, dst3, dst2, out0, out1); + ADDS_SH2_SH(out0, in0, out1, in1, out0, out1); + ADDS_SH2_SH(out0, const_vec, out1, const_vec, out0, out1); + SRARI_H2_SH(out0, out1, 7); + CLIP_SH2_0_255_MAX_SATU(out0, out1); + out = (v16u8) __msa_pckev_b((v16i8) out1, (v16i8) out0); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); + dst += (4 * dst_stride); - dst10_r = dst32_r; - dst32_r = dst54_r; - dst54_r = dst76_r; - dst21_r = dst43_r; - dst43_r = dst65_r; - dst65_r = dst87_r; - dst66 = (v8i16) __msa_splati_d((v2i64) dst87, 1); + dst10 = dst54; + dst32 = dst76; + dst54 = dst98; + dst21 = dst65; + dst43 = dst87; + dst65 = dst109; + dst66 = (v8i16) __msa_splati_d((v2i64) dst108, 1); } } -static void hevc_hv_bi_8t_8multx2mult_msa(uint8_t *src0_ptr, +static void hevc_hv_bi_8t_8multx1mult_msa(uint8_t *src0_ptr, int32_t src_stride, int16_t *src1_ptr, int32_t src2_stride, @@ -1651,22 +1749,20 @@ static void hevc_hv_bi_8t_8multx2mult_msa(uint8_t *src0_ptr, uint8_t *src0_ptr_tmp; int16_t *src1_ptr_tmp; uint8_t *dst_tmp; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; - v8i16 in0, in1; - v4i32 in0_r, in0_l, in1_r, in1_l; + v16u8 out; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7; + v8i16 in0, tmp; v8i16 filt0, filt1, filt2, filt3; - v4i32 filt_h0, filt_h1, filt_h2, filt_h3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1, filt_h2, filt_h3; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1, mask2, mask3; v8i16 filter_vec, const_vec; v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; - v4i32 dst0_r, dst0_l, dst1_r, dst1_l; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v4i32 dst0_r, dst0_l; v8i16 dst10_r, dst32_r, dst54_r, dst76_r; v8i16 dst10_l, dst32_l, dst54_l, dst76_l; - v8i16 dst21_r, dst43_r, dst65_r, dst87_r; - v8i16 dst21_l, dst43_l, dst65_l, dst87_l; src0_ptr -= ((3 * src_stride) + 3); const_vec = __msa_ldi_h(128); @@ -1676,9 +1772,9 @@ static void hevc_hv_bi_8t_8multx2mult_msa(uint8_t *src0_ptr, SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); - SPLATI_W4_SW(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); mask1 = mask0 + 2; mask2 = mask0 + 4; @@ -1703,18 +1799,14 @@ static void hevc_hv_bi_8t_8multx2mult_msa(uint8_t *src0_ptr, vec8, vec9, vec10, vec11); VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, vec12, vec13, vec14, vec15); - dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - dst1 = const_vec; - DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - dst2 = const_vec; - DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - dst3 = const_vec; - DPADD_SB4_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst1 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst2 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst3 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, + filt2, filt3); VSHF_B4_SB(src4, src4, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); @@ -1722,38 +1814,28 @@ static void hevc_hv_bi_8t_8multx2mult_msa(uint8_t *src0_ptr, vec4, vec5, vec6, vec7); VSHF_B4_SB(src6, src6, mask0, mask1, mask2, mask3, vec8, vec9, vec10, vec11); - dst4 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst4, dst4, dst4, dst4); - dst5 = const_vec; - DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, - dst5, dst5, dst5, dst5); - dst6 = const_vec; - DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, - dst6, dst6, dst6, dst6); - - ILVR_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, - dst10_r, dst32_r, dst54_r, dst21_r); - ILVR_H2_SH(dst4, dst3, dst6, dst5, dst43_r, dst65_r); - ILVL_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, - dst10_l, dst32_l, dst54_l, dst21_l); - ILVL_H2_SH(dst4, dst3, dst6, dst5, dst43_l, dst65_l); - - for (loop_cnt = height >> 1; loop_cnt--;) { - /* row 7 */ - LD_SB2(src0_ptr_tmp, src_stride, src7, src8); - XORI_B2_128_SB(src7, src8); - src0_ptr_tmp += 2 * src_stride; + dst4 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst5 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst6 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); - LD_SH2(src1_ptr_tmp, src2_stride, in0, in1); - src1_ptr_tmp += (2 * src2_stride); + for (loop_cnt = height; loop_cnt--;) { + src7 = LD_SB(src0_ptr_tmp); + src7 = (v16i8) __msa_xori_b((v16u8) src7, 128); + src0_ptr_tmp += src_stride; + + in0 = LD_SH(src1_ptr_tmp); + src1_ptr_tmp += src2_stride; VSHF_B4_SB(src7, src7, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst7 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst7, dst7, dst7, dst7); - + dst7 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, + filt2, filt3); + ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); + ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, filt_h0, filt_h1, filt_h2, filt_h3); @@ -1762,49 +1844,21 @@ static void hevc_hv_bi_8t_8multx2mult_msa(uint8_t *src0_ptr, dst0_r >>= 6; dst0_l >>= 6; - VSHF_B4_SB(src8, src8, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); - dst8 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst8, dst8, dst8, dst8); - - ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); - dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, - filt_h0, filt_h1, filt_h2, filt_h3); - dst1_l = HEVC_FILT_8TAP(dst21_l, dst43_l, dst65_l, dst87_l, - filt_h0, filt_h1, filt_h2, filt_h3); - dst1_r >>= 6; - dst1_l >>= 6; - - UNPCK_SH_SW(in0, in0_r, in0_l); - UNPCK_SH_SW(in1, in1_r, in1_l); - in0_r = __msa_adds_s_w(in0_r, dst0_r); - in0_l = __msa_adds_s_w(in0_l, dst0_l); - in1_r = __msa_adds_s_w(in1_r, dst1_r); - in1_l = __msa_adds_s_w(in1_l, dst1_l); - SRARI_W4_SW(in0_r, in0_l, in1_r, in1_l, 7); - in0_r = CLIP_SW_0_255(in0_r); - in0_l = CLIP_SW_0_255(in0_l); - in1_r = CLIP_SW_0_255(in1_r); - in1_l = CLIP_SW_0_255(in1_l); - - HEVC_PCK_SW_SB4(in0_l, in0_r, in1_l, in1_r, dst0_r); - ST8x2_UB(dst0_r, dst_tmp, dst_stride); - dst_tmp += (2 * dst_stride); - - dst10_r = dst32_r; - dst32_r = dst54_r; - dst54_r = dst76_r; - dst10_l = dst32_l; - dst32_l = dst54_l; - dst54_l = dst76_l; - dst21_r = dst43_r; - dst43_r = dst65_r; - dst65_r = dst87_r; - dst21_l = dst43_l; - dst43_l = dst65_l; - dst65_l = dst87_l; - dst6 = dst8; + tmp = __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); + ADDS_SH2_SH(tmp, in0, tmp, const_vec, tmp, tmp); + tmp = __msa_srari_h(tmp, 7); + tmp = CLIP_SH_0_255_MAX_SATU(tmp); + out = (v16u8) __msa_pckev_b((v16i8) tmp, (v16i8) tmp); + ST8x1_UB(out, dst_tmp); + dst_tmp += dst_stride; + + dst0 = dst1; + dst1 = dst2; + dst2 = dst3; + dst3 = dst4; + dst4 = dst5; + dst5 = dst6; + dst6 = dst7; } src0_ptr += 8; @@ -1823,7 +1877,7 @@ static void hevc_hv_bi_8t_8w_msa(uint8_t *src0_ptr, const int8_t *filter_y, int32_t height) { - hevc_hv_bi_8t_8multx2mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, + hevc_hv_bi_8t_8multx1mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, height, 8); } @@ -1838,12 +1892,208 @@ static void hevc_hv_bi_8t_12w_msa(uint8_t *src0_ptr, const int8_t *filter_y, int32_t height) { - hevc_hv_bi_8t_8multx2mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter_x, filter_y, - height, 8); + uint32_t loop_cnt; + uint8_t *src0_ptr_tmp, *dst_tmp; + int16_t *src1_ptr_tmp; + uint64_t tp0, tp1; + v16u8 out; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask7; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; + v8i16 in0, in1 = { 0 }, out0, out1, tmp, filter_vec, const_vec; + v8i16 filt0, filt1, filt2, filt3, filt_h0, filt_h1, filt_h2, filt_h3; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 dst30, dst41, dst52, dst63, dst66, dst97, dst108; + v8i16 dst10, dst32, dst54, dst76, dst98, dst21, dst43, dst65, dst87, dst109; + v8i16 dst10_r, dst32_r, dst54_r, dst76_r; + v8i16 dst10_l, dst32_l, dst54_l, dst76_l; + v4i32 dst0_r, dst0_l, tmp0, tmp1, tmp2, tmp3; - hevc_hv_bi_8t_4w_msa(src0_ptr + 8, src_stride, src1_ptr + 8, src2_stride, - dst + 8, dst_stride, filter_x, filter_y, height); + src0_ptr -= ((3 * src_stride) + 3); + + const_vec = __msa_ldi_h(128); + const_vec <<= 6; + + filter_vec = LD_SH(filter_x); + SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + mask2 = mask0 + 4; + mask3 = mask0 + 6; + + src0_ptr_tmp = src0_ptr; + dst_tmp = dst; + src1_ptr_tmp = src1_ptr; + + LD_SB7(src0_ptr_tmp, src_stride, src0, src1, src2, src3, src4, src5, + src6); + src0_ptr_tmp += (7 * src_stride); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + /* row 0 row 1 row 2 row 3 */ + VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, vec0, vec1, vec2, + vec3); + VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, vec4, vec5, vec6, + vec7); + VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, vec8, vec9, vec10, + vec11); + VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, vec12, vec13, vec14, + vec15); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst1 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst2 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst3 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, + filt2, filt3); + VSHF_B4_SB(src4, src4, mask0, mask1, mask2, mask3, vec0, vec1, vec2, + vec3); + VSHF_B4_SB(src5, src5, mask0, mask1, mask2, mask3, vec4, vec5, vec6, + vec7); + VSHF_B4_SB(src6, src6, mask0, mask1, mask2, mask3, vec8, vec9, vec10, + vec11); + dst4 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst5 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst6 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + + for (loop_cnt = 16; loop_cnt--;) { + src7 = LD_SB(src0_ptr_tmp); + src7 = (v16i8) __msa_xori_b((v16u8) src7, 128); + src0_ptr_tmp += src_stride; + + in0 = LD_SH(src1_ptr_tmp); + src1_ptr_tmp += src2_stride; + + VSHF_B4_SB(src7, src7, mask0, mask1, mask2, mask3, vec0, vec1, vec2, + vec3); + dst7 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, + filt2, filt3); + ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); + ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); + dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst0_l = HEVC_FILT_8TAP(dst10_l, dst32_l, dst54_l, dst76_l, filt_h0, + filt_h1, filt_h2, filt_h3); + dst0_r >>= 6; + dst0_l >>= 6; + + tmp = __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); + ADDS_SH2_SH(tmp, in0, tmp, const_vec, tmp, tmp); + tmp = __msa_srari_h(tmp, 7); + tmp = CLIP_SH_0_255_MAX_SATU(tmp); + out = (v16u8) __msa_pckev_b((v16i8) tmp, (v16i8) tmp); + ST8x1_UB(out, dst_tmp); + dst_tmp += dst_stride; + + dst0 = dst1; + dst1 = dst2; + dst2 = dst3; + dst3 = dst4; + dst4 = dst5; + dst5 = dst6; + dst6 = dst7; + } + + src0_ptr += 8; + dst += 8; + src1_ptr += 8; + + mask4 = LD_SB(ff_hevc_mask_arr + 16); + mask5 = mask4 + 2; + mask6 = mask4 + 4; + mask7 = mask4 + 6; + + LD_SB7(src0_ptr, src_stride, src0, src1, src2, src3, src4, src5, src6); + src0_ptr += (7 * src_stride); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + /* row 0 row 1 row 2 row 3 */ + VSHF_B4_SB(src0, src3, mask4, mask5, mask6, mask7, vec0, vec1, vec2, vec3); + VSHF_B4_SB(src1, src4, mask4, mask5, mask6, mask7, vec4, vec5, vec6, vec7); + VSHF_B4_SB(src2, src5, mask4, mask5, mask6, mask7, + vec8, vec9, vec10, vec11); + VSHF_B4_SB(src3, src6, mask4, mask5, mask6, mask7, + vec12, vec13, vec14, vec15); + dst30 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst41 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst52 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst63 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, + filt3); + + ILVRL_H2_SH(dst41, dst30, dst10, dst43); + ILVRL_H2_SH(dst52, dst41, dst21, dst54); + ILVRL_H2_SH(dst63, dst52, dst32, dst65); + + dst66 = (v8i16) __msa_splati_d((v2i64) dst63, 1); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src0_ptr, src_stride, src7, src8, src9, src10); + src0_ptr += (4 * src_stride); + XORI_B4_128_SB(src7, src8, src9, src10); + + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in0); + src1_ptr += (2 * src2_stride); + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in1); + src1_ptr += (2 * src2_stride); + + VSHF_B4_SB(src7, src9, mask4, mask5, mask6, mask7, vec0, vec1, vec2, + vec3); + VSHF_B4_SB(src8, src10, mask4, mask5, mask6, mask7, vec4, vec5, vec6, + vec7); + dst97 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst108 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + + dst76 = __msa_ilvr_h(dst97, dst66); + ILVRL_H2_SH(dst108, dst97, dst87, dst109); + dst66 = (v8i16) __msa_splati_d((v2i64) dst97, 1); + dst98 = __msa_ilvr_h(dst66, dst108); + + tmp0 = HEVC_FILT_8TAP(dst10, dst32, dst54, dst76, filt_h0, filt_h1, + filt_h2, filt_h3); + tmp1 = HEVC_FILT_8TAP(dst21, dst43, dst65, dst87, filt_h0, filt_h1, + filt_h2, filt_h3); + tmp2 = HEVC_FILT_8TAP(dst32, dst54, dst76, dst98, filt_h0, filt_h1, + filt_h2, filt_h3); + tmp3 = HEVC_FILT_8TAP(dst43, dst65, dst87, dst109, filt_h0, filt_h1, + filt_h2, filt_h3); + SRA_4V(tmp0, tmp1, tmp2, tmp3, 6); + PCKEV_H2_SH(tmp1, tmp0, tmp3, tmp2, out0, out1); + ADDS_SH2_SH(out0, in0, out1, in1, out0, out1); + ADDS_SH2_SH(out0, const_vec, out1, const_vec, out0, out1); + SRARI_H2_SH(out0, out1, 7); + CLIP_SH2_0_255_MAX_SATU(out0, out1); + out = (v16u8) __msa_pckev_b((v16i8) out1, (v16i8) out0); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); + dst += (4 * dst_stride); + + dst10 = dst54; + dst32 = dst76; + dst54 = dst98; + dst21 = dst65; + dst43 = dst87; + dst65 = dst109; + dst66 = (v8i16) __msa_splati_d((v2i64) dst108, 1); + } } static void hevc_hv_bi_8t_16w_msa(uint8_t *src0_ptr, @@ -1856,7 +2106,7 @@ static void hevc_hv_bi_8t_16w_msa(uint8_t *src0_ptr, const int8_t *filter_y, int32_t height) { - hevc_hv_bi_8t_8multx2mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, + hevc_hv_bi_8t_8multx1mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, height, 16); } @@ -1871,7 +2121,7 @@ static void hevc_hv_bi_8t_24w_msa(uint8_t *src0_ptr, const int8_t *filter_y, int32_t height) { - hevc_hv_bi_8t_8multx2mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, + hevc_hv_bi_8t_8multx1mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, height, 24); } @@ -1886,7 +2136,7 @@ static void hevc_hv_bi_8t_32w_msa(uint8_t *src0_ptr, const int8_t *filter_y, int32_t height) { - hevc_hv_bi_8t_8multx2mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, + hevc_hv_bi_8t_8multx1mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, height, 32); } @@ -1901,7 +2151,7 @@ static void hevc_hv_bi_8t_48w_msa(uint8_t *src0_ptr, const int8_t *filter_y, int32_t height) { - hevc_hv_bi_8t_8multx2mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, + hevc_hv_bi_8t_8multx1mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, height, 48); } @@ -1916,7 +2166,7 @@ static void hevc_hv_bi_8t_64w_msa(uint8_t *src0_ptr, const int8_t *filter_y, int32_t height) { - hevc_hv_bi_8t_8multx2mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, + hevc_hv_bi_8t_8multx1mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, height, 64); } From a211626978823c28d4b8e914019766833b77155b Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Fri, 27 Oct 2017 18:58:33 +0530 Subject: [PATCH 0700/2557] avcodec/mips: Improve hevc uni vt and hv mc msa functions Remove unused macro. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_uni_msa.c | 744 ++++++++++++++++++++---------- 1 file changed, 499 insertions(+), 245 deletions(-) diff --git a/libavcodec/mips/hevc_mc_uni_msa.c b/libavcodec/mips/hevc_mc_uni_msa.c index 3a6c5b0d48ce3..7d24858ba73ec 100644 --- a/libavcodec/mips/hevc_mc_uni_msa.c +++ b/libavcodec/mips/hevc_mc_uni_msa.c @@ -292,20 +292,6 @@ static const uint8_t mc_filt_mask_arr[16 * 3] = { 8, 9, 9, 10, 10, 11, 11, 12, 24, 25, 25, 26, 26, 27, 27, 28 }; -#define FILT_8TAP_DPADD_S_H(vec0, vec1, vec2, vec3, \ - filt0, filt1, filt2, filt3) \ -( { \ - v8i16 tmp0, tmp1; \ - \ - tmp0 = __msa_dotp_s_h((v16i8) vec0, (v16i8) filt0); \ - tmp0 = __msa_dpadd_s_h(tmp0, (v16i8) vec1, (v16i8) filt1); \ - tmp1 = __msa_dotp_s_h((v16i8) vec2, (v16i8) filt2); \ - tmp1 = __msa_dpadd_s_h(tmp1, (v16i8) vec3, (v16i8) filt3); \ - tmp0 = __msa_adds_s_h(tmp0, tmp1); \ - \ - tmp0; \ -} ) - #define FILT_4TAP_DPADD_S_H(vec0, vec1, filt0, filt1) \ ( { \ v8i16 tmp0; \ @@ -944,12 +930,14 @@ static void common_vt_8t_4w_msa(uint8_t *src, int32_t src_stride, const int8_t *filter, int32_t height) { uint32_t loop_cnt; + v16u8 out0, out1; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 src11, src12, src13, src14; v16i8 src10_r, src32_r, src54_r, src76_r, src98_r, src21_r, src43_r; v16i8 src65_r, src87_r, src109_r, src2110, src4332, src6554, src8776; + v16i8 src1110_r, src1211_r, src1312_r, src1413_r, src12111110, src14131312; v16i8 src10998, filt0, filt1, filt2, filt3; - v16u8 out; - v8i16 filt, out10, out32; + v8i16 filt, out10, out32, out54, out76; src -= (3 * src_stride); @@ -966,28 +954,45 @@ static void common_vt_8t_4w_msa(uint8_t *src, int32_t src_stride, src4332, src6554); XORI_B3_128_SB(src2110, src4332, src6554); - for (loop_cnt = (height >> 2); loop_cnt--;) { + for (loop_cnt = (height >> 3); loop_cnt--;) { LD_SB4(src, src_stride, src7, src8, src9, src10); src += (4 * src_stride); + LD_SB4(src, src_stride, src11, src12, src13, src14); + src += (4 * src_stride); ILVR_B4_SB(src7, src6, src8, src7, src9, src8, src10, src9, src76_r, src87_r, src98_r, src109_r); + ILVR_B4_SB(src11, src10, src12, src11, src13, src12, src14, src13, + src1110_r, src1211_r, src1312_r, src1413_r); ILVR_D2_SB(src87_r, src76_r, src109_r, src98_r, src8776, src10998); + ILVR_D2_SB(src1211_r, src1110_r, src1413_r, src1312_r, + src12111110, src14131312); XORI_B2_128_SB(src8776, src10998); - out10 = FILT_8TAP_DPADD_S_H(src2110, src4332, src6554, src8776, filt0, - filt1, filt2, filt3); - out32 = FILT_8TAP_DPADD_S_H(src4332, src6554, src8776, src10998, filt0, - filt1, filt2, filt3); + XORI_B2_128_SB(src12111110, src14131312); + + DOTP_SB2_SH(src2110, src4332, filt0, filt0, out10, out32); + DOTP_SB2_SH(src6554, src8776, filt0, filt0, out54, out76); + DPADD_SB2_SH(src4332, src6554, filt1, filt1, out10, out32); + DPADD_SB2_SH(src8776, src10998, filt1, filt1, out54, out76); + DPADD_SB2_SH(src6554, src8776, filt2, filt2, out10, out32); + DPADD_SB2_SH(src10998, src12111110, filt2, filt2, out54, out76); + DPADD_SB2_SH(src8776, src10998, filt3, filt3, out10, out32); + DPADD_SB2_SH(src12111110, src14131312, filt3, filt3, out54, out76); SRARI_H2_SH(out10, out32, 6); + SRARI_H2_SH(out54, out76, 6); SAT_SH2_SH(out10, out32, 7); - out = PCKEV_XORI128_UB(out10, out32); - ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); + SAT_SH2_SH(out54, out76, 7); + out0 = PCKEV_XORI128_UB(out10, out32); + out1 = PCKEV_XORI128_UB(out54, out76); + ST4x4_UB(out0, out0, 0, 1, 2, 3, dst, dst_stride); + dst += (4 * dst_stride); + ST4x4_UB(out1, out1, 0, 1, 2, 3, dst, dst_stride); dst += (4 * dst_stride); - src2110 = src6554; - src4332 = src8776; - src6554 = src10998; - src6 = src10; + src2110 = src10998; + src4332 = src12111110; + src6554 = src14131312; + src6 = src14; } } @@ -1021,14 +1026,14 @@ static void common_vt_8t_8w_msa(uint8_t *src, int32_t src_stride, ILVR_B4_SB(src7, src6, src8, src7, src9, src8, src10, src9, src76_r, src87_r, src98_r, src109_r); - out0_r = FILT_8TAP_DPADD_S_H(src10_r, src32_r, src54_r, src76_r, filt0, - filt1, filt2, filt3); - out1_r = FILT_8TAP_DPADD_S_H(src21_r, src43_r, src65_r, src87_r, filt0, - filt1, filt2, filt3); - out2_r = FILT_8TAP_DPADD_S_H(src32_r, src54_r, src76_r, src98_r, filt0, - filt1, filt2, filt3); - out3_r = FILT_8TAP_DPADD_S_H(src43_r, src65_r, src87_r, src109_r, filt0, - filt1, filt2, filt3); + DOTP_SB4_SH(src10_r, src21_r, src32_r, src43_r, filt0, filt0, filt0, + filt0, out0_r, out1_r, out2_r, out3_r); + DPADD_SB4_SH(src32_r, src43_r, src54_r, src65_r, filt1, filt1, filt1, + filt1, out0_r, out1_r, out2_r, out3_r); + DPADD_SB4_SH(src54_r, src65_r, src76_r, src87_r, filt2, filt2, filt2, + filt2, out0_r, out1_r, out2_r, out3_r); + DPADD_SB4_SH(src76_r, src87_r, src98_r, src109_r, filt3, filt3, filt3, + filt3, out0_r, out1_r, out2_r, out3_r); SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 6); SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); tmp0 = PCKEV_XORI128_UB(out0_r, out1_r); @@ -1050,61 +1055,81 @@ static void common_vt_8t_12w_msa(uint8_t *src, int32_t src_stride, uint8_t *dst, int32_t dst_stride, const int8_t *filter, int32_t height) { - int32_t loop_cnt; + uint32_t loop_cnt; uint32_t out2, out3; uint64_t out0, out1; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, res0, res1; - v16i8 res2, vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; - v8i16 vec01, vec23, vec45, vec67, tmp0, tmp1, tmp2; - v8i16 filt, filt0, filt1, filt2, filt3; - v4i32 mask = { 2, 6, 2, 6 }; + v16u8 tmp0, tmp1, tmp2, tmp3; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 filt0, filt1, filt2, filt3; + v16i8 src10_r, src32_r, src54_r, src76_r, src98_r, src21_r, src43_r; + v16i8 src65_r, src87_r, src109_r, src10_l, src32_l, src54_l, src76_l; + v16i8 src98_l, src21_l, src43_l, src65_l, src87_l, src109_l; + v8i16 filt, out0_r, out1_r, out2_r, out3_r, out0_l, out1_l, out2_l, out3_l; src -= (3 * src_stride); - /* rearranging filter_y */ filt = LD_SH(filter); - SPLATI_H4_SH(filt, 0, 1, 2, 3, filt0, filt1, filt2, filt3); + SPLATI_H4_SB(filt, 0, 1, 2, 3, filt0, filt1, filt2, filt3); LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); src += (7 * src_stride); XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); - /* 4 width */ - VSHF_W2_SB(src0, src1, src1, src2, mask, mask, vec0, vec1); - VSHF_W2_SB(src2, src3, src3, src4, mask, mask, vec2, vec3); - VSHF_W2_SB(src4, src5, src5, src6, mask, mask, vec4, vec5); - - for (loop_cnt = (height >> 1); loop_cnt--;) { - LD_SB2(src, src_stride, src7, src8); - XORI_B2_128_SB(src7, src8); - src += (2 * src_stride); + ILVR_B4_SB(src1, src0, src3, src2, src5, src4, src2, src1, src10_r, src32_r, + src54_r, src21_r); + ILVR_B2_SB(src4, src3, src6, src5, src43_r, src65_r); + ILVL_B4_SB(src1, src0, src3, src2, src5, src4, src2, src1, src10_l, src32_l, + src54_l, src21_l); + ILVL_B2_SB(src4, src3, src6, src5, src43_l, src65_l); - ILVR_B4_SH(src1, src0, src3, src2, src5, src4, src7, src6, - vec01, vec23, vec45, vec67); - tmp0 = FILT_8TAP_DPADD_S_H(vec01, vec23, vec45, vec67, filt0, filt1, - filt2, filt3); - ILVR_B4_SH(src2, src1, src4, src3, src6, src5, src8, src7, vec01, vec23, - vec45, vec67); - tmp1 = FILT_8TAP_DPADD_S_H(vec01, vec23, vec45, vec67, filt0, filt1, - filt2, filt3); + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src, src_stride, src7, src8, src9, src10); + XORI_B4_128_SB(src7, src8, src9, src10); + src += (4 * src_stride); - /* 4 width */ - VSHF_W2_SB(src6, src7, src7, src8, mask, mask, vec6, vec7); - ILVR_B4_SH(vec1, vec0, vec3, vec2, vec5, vec4, vec7, vec6, vec01, vec23, - vec45, vec67); - tmp2 = FILT_8TAP_DPADD_S_H(vec01, vec23, vec45, vec67, filt0, filt1, - filt2, filt3); - SRARI_H2_SH(tmp0, tmp1, 6); - tmp2 = __msa_srari_h(tmp2, 6); - SAT_SH3_SH(tmp0, tmp1, tmp2, 7); - PCKEV_B3_SB(tmp0, tmp0, tmp1, tmp1, tmp2, tmp2, res0, res1, res2); - XORI_B3_128_SB(res0, res1, res2); + ILVR_B4_SB(src7, src6, src8, src7, src9, src8, src10, src9, src76_r, + src87_r, src98_r, src109_r); + ILVL_B4_SB(src7, src6, src8, src7, src9, src8, src10, src9, src76_l, + src87_l, src98_l, src109_l); + out0_r = HEVC_FILT_8TAP_SH(src10_r, src32_r, src54_r, src76_r, filt0, + filt1, filt2, filt3); + out1_r = HEVC_FILT_8TAP_SH(src21_r, src43_r, src65_r, src87_r, filt0, + filt1, filt2, filt3); + out2_r = HEVC_FILT_8TAP_SH(src32_r, src54_r, src76_r, src98_r, filt0, + filt1, filt2, filt3); + out3_r = HEVC_FILT_8TAP_SH(src43_r, src65_r, src87_r, src109_r, filt0, + filt1, filt2, filt3); + out0_l = HEVC_FILT_8TAP_SH(src10_l, src32_l, src54_l, src76_l, filt0, + filt1, filt2, filt3); + out1_l = HEVC_FILT_8TAP_SH(src21_l, src43_l, src65_l, src87_l, filt0, + filt1, filt2, filt3); + out2_l = HEVC_FILT_8TAP_SH(src32_l, src54_l, src76_l, src98_l, filt0, + filt1, filt2, filt3); + out3_l = HEVC_FILT_8TAP_SH(src43_l, src65_l, src87_l, src109_l, filt0, + filt1, filt2, filt3); + SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 6); + SRARI_H4_SH(out0_l, out1_l, out2_l, out3_l, 6); + SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); + SAT_SH4_SH(out0_l, out1_l, out2_l, out3_l, 7); + PCKEV_B4_UB(out0_l, out0_r, out1_l, out1_r, out2_l, out2_r, out3_l, + out3_r, tmp0, tmp1, tmp2, tmp3); + XORI_B4_128_UB(tmp0, tmp1, tmp2, tmp3); - out0 = __msa_copy_u_d((v2i64) res0, 0); - out1 = __msa_copy_u_d((v2i64) res1, 0); - out2 = __msa_copy_u_w((v4i32) res2, 0); - out3 = __msa_copy_u_w((v4i32) res2, 1); + out0 = __msa_copy_u_d((v2i64) tmp0, 0); + out1 = __msa_copy_u_d((v2i64) tmp1, 0); + out2 = __msa_copy_u_w((v4i32) tmp0, 2); + out3 = __msa_copy_u_w((v4i32) tmp1, 2); + SD(out0, dst); + SW(out2, (dst + 8)); + dst += dst_stride; + SD(out1, dst); + SW(out3, (dst + 8)); + dst += dst_stride; + out0 = __msa_copy_u_d((v2i64) tmp2, 0); + out1 = __msa_copy_u_d((v2i64) tmp3, 0); + out2 = __msa_copy_u_w((v4i32) tmp2, 2); + out3 = __msa_copy_u_w((v4i32) tmp3, 2); SD(out0, dst); SW(out2, (dst + 8)); dst += dst_stride; @@ -1112,19 +1137,19 @@ static void common_vt_8t_12w_msa(uint8_t *src, int32_t src_stride, SW(out3, (dst + 8)); dst += dst_stride; - src0 = src2; - src1 = src3; - src2 = src4; - src3 = src5; - src4 = src6; - src5 = src7; - src6 = src8; - vec0 = vec2; - vec1 = vec3; - vec2 = vec4; - vec3 = vec5; - vec4 = vec6; - vec5 = vec7; + src10_r = src54_r; + src32_r = src76_r; + src54_r = src98_r; + src21_r = src65_r; + src43_r = src87_r; + src65_r = src109_r; + src10_l = src54_l; + src32_l = src76_l; + src54_l = src98_l; + src21_l = src65_l; + src43_l = src87_l; + src65_l = src109_l; + src6 = src10; } } @@ -1165,22 +1190,22 @@ static void common_vt_8t_16w_msa(uint8_t *src, int32_t src_stride, src87_r, src98_r, src109_r); ILVL_B4_SB(src7, src6, src8, src7, src9, src8, src10, src9, src76_l, src87_l, src98_l, src109_l); - out0_r = FILT_8TAP_DPADD_S_H(src10_r, src32_r, src54_r, src76_r, filt0, - filt1, filt2, filt3); - out1_r = FILT_8TAP_DPADD_S_H(src21_r, src43_r, src65_r, src87_r, filt0, - filt1, filt2, filt3); - out2_r = FILT_8TAP_DPADD_S_H(src32_r, src54_r, src76_r, src98_r, filt0, - filt1, filt2, filt3); - out3_r = FILT_8TAP_DPADD_S_H(src43_r, src65_r, src87_r, src109_r, filt0, - filt1, filt2, filt3); - out0_l = FILT_8TAP_DPADD_S_H(src10_l, src32_l, src54_l, src76_l, filt0, - filt1, filt2, filt3); - out1_l = FILT_8TAP_DPADD_S_H(src21_l, src43_l, src65_l, src87_l, filt0, - filt1, filt2, filt3); - out2_l = FILT_8TAP_DPADD_S_H(src32_l, src54_l, src76_l, src98_l, filt0, - filt1, filt2, filt3); - out3_l = FILT_8TAP_DPADD_S_H(src43_l, src65_l, src87_l, src109_l, filt0, - filt1, filt2, filt3); + out0_r = HEVC_FILT_8TAP_SH(src10_r, src32_r, src54_r, src76_r, filt0, + filt1, filt2, filt3); + out1_r = HEVC_FILT_8TAP_SH(src21_r, src43_r, src65_r, src87_r, filt0, + filt1, filt2, filt3); + out2_r = HEVC_FILT_8TAP_SH(src32_r, src54_r, src76_r, src98_r, filt0, + filt1, filt2, filt3); + out3_r = HEVC_FILT_8TAP_SH(src43_r, src65_r, src87_r, src109_r, filt0, + filt1, filt2, filt3); + out0_l = HEVC_FILT_8TAP_SH(src10_l, src32_l, src54_l, src76_l, filt0, + filt1, filt2, filt3); + out1_l = HEVC_FILT_8TAP_SH(src21_l, src43_l, src65_l, src87_l, filt0, + filt1, filt2, filt3); + out2_l = HEVC_FILT_8TAP_SH(src32_l, src54_l, src76_l, src98_l, filt0, + filt1, filt2, filt3); + out3_l = HEVC_FILT_8TAP_SH(src43_l, src65_l, src87_l, src109_l, filt0, + filt1, filt2, filt3); SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 6); SRARI_H4_SH(out0_l, out1_l, out2_l, out3_l, 6); SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); @@ -1250,22 +1275,22 @@ static void common_vt_8t_16w_mult_msa(uint8_t *src, int32_t src_stride, src87_r, src98_r, src109_r); ILVL_B4_SB(src7, src6, src8, src7, src9, src8, src10, src9, src76_l, src87_l, src98_l, src109_l); - out0_r = FILT_8TAP_DPADD_S_H(src10_r, src32_r, src54_r, src76_r, - filt0, filt1, filt2, filt3); - out1_r = FILT_8TAP_DPADD_S_H(src21_r, src43_r, src65_r, src87_r, - filt0, filt1, filt2, filt3); - out2_r = FILT_8TAP_DPADD_S_H(src32_r, src54_r, src76_r, src98_r, - filt0, filt1, filt2, filt3); - out3_r = FILT_8TAP_DPADD_S_H(src43_r, src65_r, src87_r, src109_r, - filt0, filt1, filt2, filt3); - out0_l = FILT_8TAP_DPADD_S_H(src10_l, src32_l, src54_l, src76_l, - filt0, filt1, filt2, filt3); - out1_l = FILT_8TAP_DPADD_S_H(src21_l, src43_l, src65_l, src87_l, - filt0, filt1, filt2, filt3); - out2_l = FILT_8TAP_DPADD_S_H(src32_l, src54_l, src76_l, src98_l, - filt0, filt1, filt2, filt3); - out3_l = FILT_8TAP_DPADD_S_H(src43_l, src65_l, src87_l, src109_l, - filt0, filt1, filt2, filt3); + out0_r = HEVC_FILT_8TAP_SH(src10_r, src32_r, src54_r, src76_r, + filt0, filt1, filt2, filt3); + out1_r = HEVC_FILT_8TAP_SH(src21_r, src43_r, src65_r, src87_r, + filt0, filt1, filt2, filt3); + out2_r = HEVC_FILT_8TAP_SH(src32_r, src54_r, src76_r, src98_r, + filt0, filt1, filt2, filt3); + out3_r = HEVC_FILT_8TAP_SH(src43_r, src65_r, src87_r, src109_r, + filt0, filt1, filt2, filt3); + out0_l = HEVC_FILT_8TAP_SH(src10_l, src32_l, src54_l, src76_l, + filt0, filt1, filt2, filt3); + out1_l = HEVC_FILT_8TAP_SH(src21_l, src43_l, src65_l, src87_l, + filt0, filt1, filt2, filt3); + out2_l = HEVC_FILT_8TAP_SH(src32_l, src54_l, src76_l, src98_l, + filt0, filt1, filt2, filt3); + out3_l = HEVC_FILT_8TAP_SH(src43_l, src65_l, src87_l, src109_l, + filt0, filt1, filt2, filt3); SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 6); SRARI_H4_SH(out0_l, out1_l, out2_l, out3_l, 6); SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); @@ -1340,37 +1365,34 @@ static void hevc_hv_uni_8t_4w_msa(uint8_t *src, int32_t height) { uint32_t loop_cnt; + v16u8 out0, out1; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 src9, src10, src11, src12, src13, src14; v8i16 filt0, filt1, filt2, filt3; - v4i32 filt_h0, filt_h1, filt_h2, filt_h3; + v8i16 filt_h0, filt_h1, filt_h2, filt_h3; v16i8 mask1, mask2, mask3; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; - v8i16 dst30, dst41, dst52, dst63, dst66, dst87; - v4i32 dst0_r, dst1_r; - v8i16 dst10_r, dst32_r, dst54_r, dst76_r; - v8i16 dst21_r, dst43_r, dst65_r, dst87_r; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; - v8i16 mask4 = { 0, 4, 1, 5, 2, 6, 3, 7 }; + v8i16 dst30, dst41, dst52, dst63, dst66, dst117, dst128, dst139, dst1410; + v8i16 dst10_r, dst32_r, dst54_r, dst76_r, dst98_r, dst1110_r, dst1312_r; + v8i16 dst21_r, dst43_r, dst65_r, dst87_r, dst109_r, dst1211_r, dst1413_r; + v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r, dst6_r, dst7_r; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); src -= ((3 * src_stride) + 3); filter_vec = LD_SH(filter_x); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W4_SW(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); mask1 = mask0 + 2; mask2 = mask0 + 4; mask3 = mask0 + 6; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); src += (7 * src_stride); XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); @@ -1382,61 +1404,91 @@ static void hevc_hv_uni_8t_4w_msa(uint8_t *src, VSHF_B4_SB(src3, src6, mask0, mask1, mask2, mask3, vec12, vec13, vec14, vec15); - dst30 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst30, dst30, dst30, dst30); - dst41 = const_vec; - DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, - dst41, dst41, dst41, dst41); - dst52 = const_vec; - DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, - dst52, dst52, dst52, dst52); - dst63 = const_vec; - DPADD_SB4_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, filt3, - dst63, dst63, dst63, dst63); - - ILVR_H3_SH(dst41, dst30, dst52, dst41, dst63, dst52, - dst10_r, dst21_r, dst32_r); - dst43_r = __msa_ilvl_h(dst41, dst30); - dst54_r = __msa_ilvl_h(dst52, dst41); - dst65_r = __msa_ilvl_h(dst63, dst52); + dst30 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst41 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst52 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst63 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, + filt3); + + ILVRL_H2_SH(dst41, dst30, dst10_r, dst43_r); + ILVRL_H2_SH(dst52, dst41, dst21_r, dst54_r); + ILVRL_H2_SH(dst63, dst52, dst32_r, dst65_r); + dst66 = (v8i16) __msa_splati_d((v2i64) dst63, 1); - for (loop_cnt = height >> 1; loop_cnt--;) { - LD_SB2(src, src_stride, src7, src8); - src += 2 * src_stride; - XORI_B2_128_SB(src7, src8); + for (loop_cnt = height >> 3; loop_cnt--;) { + LD_SB8(src, src_stride, src7, src8, src9, src10, src11, src12, src13, + src14); + src += (8 * src_stride); + XORI_B8_128_SB(src7, src8, src9, src10, src11, src12, src13, src14); - VSHF_B4_SB(src7, src8, mask0, mask1, mask2, mask3, + VSHF_B4_SB(src7, src11, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst87 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst87, dst87, dst87, dst87); + VSHF_B4_SB(src8, src12, mask0, mask1, mask2, mask3, + vec4, vec5, vec6, vec7); + VSHF_B4_SB(src9, src13, mask0, mask1, mask2, mask3, + vec8, vec9, vec10, vec11); + VSHF_B4_SB(src10, src14, mask0, mask1, mask2, mask3, + vec12, vec13, vec14, vec15); - dst76_r = __msa_ilvr_h(dst87, dst66); - dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, - filt_h0, filt_h1, filt_h2, filt_h3); - dst87_r = __msa_vshf_h(mask4, dst87, dst87); - dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, - filt_h0, filt_h1, filt_h2, filt_h3); + dst117 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst128 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst139 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, + filt2, filt3); + dst1410 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, + filt2, filt3); - dst0_r >>= 6; - dst1_r >>= 6; - SRARI_W2_SW(dst0_r, dst1_r, 6); - dst0_r = CLIP_SW_0_255(dst0_r); - dst1_r = CLIP_SW_0_255(dst1_r); + dst76_r = __msa_ilvr_h(dst117, dst66); + ILVRL_H2_SH(dst128, dst117, dst87_r, dst1211_r); + ILVRL_H2_SH(dst139, dst128, dst98_r, dst1312_r); + ILVRL_H2_SH(dst1410, dst139, dst109_r, dst1413_r); + dst117 = (v8i16) __msa_splati_d((v2i64) dst117, 1); + dst1110_r = __msa_ilvr_h(dst117, dst1410); + + dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst2_r = HEVC_FILT_8TAP(dst32_r, dst54_r, dst76_r, dst98_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst3_r = HEVC_FILT_8TAP(dst43_r, dst65_r, dst87_r, dst109_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst4_r = HEVC_FILT_8TAP(dst54_r, dst76_r, dst98_r, dst1110_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst5_r = HEVC_FILT_8TAP(dst65_r, dst87_r, dst109_r, dst1211_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst6_r = HEVC_FILT_8TAP(dst76_r, dst98_r, dst1110_r, dst1312_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst7_r = HEVC_FILT_8TAP(dst87_r, dst109_r, dst1211_r, dst1413_r, + filt_h0, filt_h1, filt_h2, filt_h3); - HEVC_PCK_SW_SB2(dst1_r, dst0_r, dst0_r); - ST4x2_UB(dst0_r, dst, dst_stride); - dst += (2 * dst_stride); + SRA_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SRA_4V(dst4_r, dst5_r, dst6_r, dst7_r, 6); + SRARI_W4_SW(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SRARI_W4_SW(dst4_r, dst5_r, dst6_r, dst7_r, 6); + SAT_SW4_SW(dst0_r, dst1_r, dst2_r, dst3_r, 7); + SAT_SW4_SW(dst4_r, dst5_r, dst6_r, dst7_r, 7); + PCKEV_H2_SW(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r, dst1_r); + PCKEV_H2_SW(dst5_r, dst4_r, dst7_r, dst6_r, dst4_r, dst5_r); + out0 = PCKEV_XORI128_UB(dst0_r, dst1_r); + out1 = PCKEV_XORI128_UB(dst4_r, dst5_r); + ST4x4_UB(out0, out0, 0, 1, 2, 3, dst, dst_stride); + dst += (4 * dst_stride); + ST4x4_UB(out1, out1, 0, 1, 2, 3, dst, dst_stride); + dst += (4 * dst_stride); - dst10_r = dst32_r; - dst32_r = dst54_r; - dst54_r = dst76_r; - dst21_r = dst43_r; - dst43_r = dst65_r; - dst65_r = dst87_r; - dst66 = (v8i16) __msa_splati_d((v2i64) dst87, 1); + dst10_r = dst98_r; + dst32_r = dst1110_r; + dst54_r = dst1312_r; + dst21_r = dst109_r; + dst43_r = dst1211_r; + dst65_r = dst1413_r; + dst66 = (v8i16) __msa_splati_d((v2i64) dst1410, 1); } } @@ -1451,11 +1503,12 @@ static void hevc_hv_uni_8t_8multx2mult_msa(uint8_t *src, uint32_t loop_cnt, cnt; uint8_t *src_tmp; uint8_t *dst_tmp; + v16u8 out; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; v8i16 filt0, filt1, filt2, filt3; - v4i32 filt_h0, filt_h1, filt_h2, filt_h3; + v8i16 filt_h0, filt_h1, filt_h2, filt_h3; v16i8 mask1, mask2, mask3; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; @@ -1464,20 +1517,17 @@ static void hevc_hv_uni_8t_8multx2mult_msa(uint8_t *src, v8i16 dst10_l, dst32_l, dst54_l, dst76_l; v8i16 dst21_r, dst43_r, dst65_r, dst87_r; v8i16 dst21_l, dst43_l, dst65_l, dst87_l; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); src -= ((3 * src_stride) + 3); - const_vec = __msa_ldi_h(128); - const_vec <<= 6; filter_vec = LD_SH(filter_x); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W4_SW(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); mask1 = mask0 + 2; mask2 = mask0 + 4; @@ -1500,18 +1550,14 @@ static void hevc_hv_uni_8t_8multx2mult_msa(uint8_t *src, vec8, vec9, vec10, vec11); VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, vec12, vec13, vec14, vec15); - dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - dst1 = const_vec; - DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - dst2 = const_vec; - DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - dst3 = const_vec; - DPADD_SB4_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst1 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst2 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst3 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, + filt2, filt3); VSHF_B4_SB(src4, src4, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); @@ -1519,33 +1565,29 @@ static void hevc_hv_uni_8t_8multx2mult_msa(uint8_t *src, vec4, vec5, vec6, vec7); VSHF_B4_SB(src6, src6, mask0, mask1, mask2, mask3, vec8, vec9, vec10, vec11); - dst4 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst4, dst4, dst4, dst4); - dst5 = const_vec; - DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, - dst5, dst5, dst5, dst5); - dst6 = const_vec; - DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, - dst6, dst6, dst6, dst6); - - ILVR_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, - dst10_r, dst32_r, dst54_r, dst21_r); - ILVR_H2_SH(dst4, dst3, dst6, dst5, dst43_r, dst65_r); - ILVL_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, - dst10_l, dst32_l, dst54_l, dst21_l); - ILVL_H2_SH(dst4, dst3, dst6, dst5, dst43_l, dst65_l); + dst4 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst5 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst6 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); for (loop_cnt = height >> 1; loop_cnt--;) { LD_SB2(src_tmp, src_stride, src7, src8); XORI_B2_128_SB(src7, src8); src_tmp += 2 * src_stride; + ILVR_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, + dst10_r, dst32_r, dst54_r, dst21_r); + ILVL_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, + dst10_l, dst32_l, dst54_l, dst21_l); + ILVR_H2_SH(dst4, dst3, dst6, dst5, dst43_r, dst65_r); + ILVL_H2_SH(dst4, dst3, dst6, dst5, dst43_l, dst65_l); + VSHF_B4_SB(src7, src7, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst7 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst7, dst7, dst7, dst7); + dst7 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, + filt2, filt3); ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, @@ -1557,9 +1599,8 @@ static void hevc_hv_uni_8t_8multx2mult_msa(uint8_t *src, VSHF_B4_SB(src8, src8, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst8 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst8, dst8, dst8, dst8); + dst8 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, + filt2, filt3); ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, @@ -1569,27 +1610,19 @@ static void hevc_hv_uni_8t_8multx2mult_msa(uint8_t *src, dst1_r >>= 6; dst1_l >>= 6; SRARI_W4_SW(dst0_r, dst0_l, dst1_r, dst1_l, 6); - dst0_r = CLIP_SW_0_255(dst0_r); - dst0_l = CLIP_SW_0_255(dst0_l); - dst1_r = CLIP_SW_0_255(dst1_r); - dst1_l = CLIP_SW_0_255(dst1_l); + SAT_SW4_SW(dst0_r, dst0_l, dst1_r, dst1_l, 7); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST8x2_UB(dst0_r, dst_tmp, dst_stride); + PCKEV_H2_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst0, dst1); + out = PCKEV_XORI128_UB(dst0, dst1); + ST8x2_UB(out, dst_tmp, dst_stride); dst_tmp += (2 * dst_stride); - dst10_r = dst32_r; - dst32_r = dst54_r; - dst54_r = dst76_r; - dst10_l = dst32_l; - dst32_l = dst54_l; - dst54_l = dst76_l; - dst21_r = dst43_r; - dst43_r = dst65_r; - dst65_r = dst87_r; - dst21_l = dst43_l; - dst43_l = dst65_l; - dst65_l = dst87_l; + dst0 = dst2; + dst1 = dst3; + dst2 = dst4; + dst3 = dst5; + dst4 = dst6; + dst5 = dst7; dst6 = dst8; } @@ -1618,11 +1651,232 @@ static void hevc_hv_uni_8t_12w_msa(uint8_t *src, const int8_t *filter_y, int32_t height) { - hevc_hv_uni_8t_8multx2mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, 8); + uint32_t loop_cnt; + uint8_t *src_tmp, *dst_tmp; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 src11, src12, src13, src14; + v16i8 mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask7; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; + v8i16 dst30, dst41, dst52, dst63, dst66, dst117, dst128, dst139, dst1410; + v8i16 filt0, filt1, filt2, filt3, filt_h0, filt_h1, filt_h2, filt_h3; + v8i16 dst10_r, dst32_r, dst54_r, dst76_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst76_l, dst21_l, dst43_l, dst65_l; + v8i16 dst87_r, dst98_r, dst1110_r, dst1312_r, dst109_r, dst1211_r; + v8i16 dst1413_r, dst87_l, filter_vec; + v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r, dst6_r, dst7_r; + v4i32 dst0_l, dst1_l; - hevc_hv_uni_8t_4w_msa(src + 8, src_stride, dst + 8, dst_stride, - filter_x, filter_y, height); + src -= ((3 * src_stride) + 3); + + filter_vec = LD_SH(filter_x); + SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + mask2 = mask0 + 4; + mask3 = mask0 + 6; + + src_tmp = src; + dst_tmp = dst; + + LD_SB7(src_tmp, src_stride, src0, src1, src2, src3, src4, src5, src6); + src_tmp += (7 * src_stride); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + /* row 0 row 1 row 2 row 3 */ + VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); + VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, vec4, vec5, vec6, vec7); + VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, vec8, vec9, vec10, + vec11); + VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, vec12, vec13, vec14, + vec15); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst1 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst2 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst3 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, + filt2, filt3); + + VSHF_B4_SB(src4, src4, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); + VSHF_B4_SB(src5, src5, mask0, mask1, mask2, mask3, vec4, vec5, vec6, vec7); + VSHF_B4_SB(src6, src6, mask0, mask1, mask2, mask3, vec8, vec9, vec10, + vec11); + dst4 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst5 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst6 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + + for (loop_cnt = 8; loop_cnt--;) { + LD_SB2(src_tmp, src_stride, src7, src8); + XORI_B2_128_SB(src7, src8); + src_tmp += 2 * src_stride; + + ILVR_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, dst10_r, + dst32_r, dst54_r, dst21_r); + ILVL_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, dst10_l, + dst32_l, dst54_l, dst21_l); + ILVR_H2_SH(dst4, dst3, dst6, dst5, dst43_r, dst65_r); + ILVL_H2_SH(dst4, dst3, dst6, dst5, dst43_l, dst65_l); + + VSHF_B4_SB(src7, src7, mask0, mask1, mask2, mask3, vec0, vec1, vec2, + vec3); + dst7 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + + ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); + dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, + filt_h0, filt_h1, filt_h2, filt_h3); + dst0_l = HEVC_FILT_8TAP(dst10_l, dst32_l, dst54_l, dst76_l, + filt_h0, filt_h1, filt_h2, filt_h3); + dst0_r >>= 6; + dst0_l >>= 6; + + VSHF_B4_SB(src8, src8, mask0, mask1, mask2, mask3, vec0, vec1, vec2, + vec3); + dst8 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + + ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); + dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, + filt_h0, filt_h1, filt_h2, filt_h3); + dst1_l = HEVC_FILT_8TAP(dst21_l, dst43_l, dst65_l, dst87_l, + filt_h0, filt_h1, filt_h2, filt_h3); + dst1_r >>= 6; + dst1_l >>= 6; + SRARI_W4_SW(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SAT_SW4_SW(dst0_r, dst0_l, dst1_r, dst1_l, 7); + + PCKEV_H2_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst0, dst1); + out0 = PCKEV_XORI128_UB(dst0, dst1); + ST8x2_UB(out0, dst_tmp, dst_stride); + dst_tmp += (2 * dst_stride); + + dst0 = dst2; + dst1 = dst3; + dst2 = dst4; + dst3 = dst5; + dst4 = dst6; + dst5 = dst7; + dst6 = dst8; + } + + src += 8; + dst += 8; + + mask4 = LD_SB(ff_hevc_mask_arr + 16); + mask5 = mask4 + 2; + mask6 = mask4 + 4; + mask7 = mask4 + 6; + + LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); + src += (7 * src_stride); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + VSHF_B4_SB(src0, src3, mask4, mask5, mask6, mask7, vec0, vec1, vec2, vec3); + VSHF_B4_SB(src1, src4, mask4, mask5, mask6, mask7, vec4, vec5, vec6, vec7); + VSHF_B4_SB(src2, src5, mask4, mask5, mask6, mask7, vec8, vec9, vec10, + vec11); + VSHF_B4_SB(src3, src6, mask4, mask5, mask6, mask7, vec12, vec13, vec14, + vec15); + + dst30 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst41 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst52 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst63 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, + filt3); + + ILVRL_H2_SH(dst41, dst30, dst10_r, dst43_r); + ILVRL_H2_SH(dst52, dst41, dst21_r, dst54_r); + ILVRL_H2_SH(dst63, dst52, dst32_r, dst65_r); + + dst66 = (v8i16) __msa_splati_d((v2i64) dst63, 1); + + for (loop_cnt = 2; loop_cnt--;) { + LD_SB8(src, src_stride, src7, src8, src9, src10, src11, src12, src13, + src14); + src += (8 * src_stride); + XORI_B8_128_SB(src7, src8, src9, src10, src11, src12, src13, src14); + + VSHF_B4_SB(src7, src11, mask4, mask5, mask6, mask7, vec0, vec1, vec2, + vec3); + VSHF_B4_SB(src8, src12, mask4, mask5, mask6, mask7, vec4, vec5, vec6, + vec7); + VSHF_B4_SB(src9, src13, mask4, mask5, mask6, mask7, vec8, vec9, vec10, + vec11); + VSHF_B4_SB(src10, src14, mask4, mask5, mask6, mask7, vec12, vec13, + vec14, vec15); + + dst117 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst128 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst139 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, + filt2, filt3); + dst1410 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, + filt2, filt3); + + dst76_r = __msa_ilvr_h(dst117, dst66); + ILVRL_H2_SH(dst128, dst117, dst87_r, dst1211_r); + ILVRL_H2_SH(dst139, dst128, dst98_r, dst1312_r); + ILVRL_H2_SH(dst1410, dst139, dst109_r, dst1413_r); + dst117 = (v8i16) __msa_splati_d((v2i64) dst117, 1); + dst1110_r = __msa_ilvr_h(dst117, dst1410); + + dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst2_r = HEVC_FILT_8TAP(dst32_r, dst54_r, dst76_r, dst98_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst3_r = HEVC_FILT_8TAP(dst43_r, dst65_r, dst87_r, dst109_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst4_r = HEVC_FILT_8TAP(dst54_r, dst76_r, dst98_r, dst1110_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst5_r = HEVC_FILT_8TAP(dst65_r, dst87_r, dst109_r, dst1211_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst6_r = HEVC_FILT_8TAP(dst76_r, dst98_r, dst1110_r, dst1312_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst7_r = HEVC_FILT_8TAP(dst87_r, dst109_r, dst1211_r, dst1413_r, + filt_h0, filt_h1, filt_h2, filt_h3); + + SRA_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SRA_4V(dst4_r, dst5_r, dst6_r, dst7_r, 6); + SRARI_W4_SW(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SRARI_W4_SW(dst4_r, dst5_r, dst6_r, dst7_r, 6); + SAT_SW4_SW(dst0_r, dst1_r, dst2_r, dst3_r, 7); + SAT_SW4_SW(dst4_r, dst5_r, dst6_r, dst7_r, 7); + PCKEV_H2_SW(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r, dst1_r); + PCKEV_H2_SW(dst5_r, dst4_r, dst7_r, dst6_r, dst4_r, dst5_r); + out0 = PCKEV_XORI128_UB(dst0_r, dst1_r); + out1 = PCKEV_XORI128_UB(dst4_r, dst5_r); + ST4x4_UB(out0, out0, 0, 1, 2, 3, dst, dst_stride); + dst += (4 * dst_stride); + ST4x4_UB(out1, out1, 0, 1, 2, 3, dst, dst_stride); + dst += (4 * dst_stride); + + dst10_r = dst98_r; + dst32_r = dst1110_r; + dst54_r = dst1312_r; + dst21_r = dst109_r; + dst43_r = dst1211_r; + dst65_r = dst1413_r; + dst66 = (v8i16) __msa_splati_d((v2i64) dst1410, 1); + } } static void hevc_hv_uni_8t_16w_msa(uint8_t *src, From fdfc51766d28087c44307ddb5a4b087d47dbe8ef Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Tue, 31 Oct 2017 16:09:45 +0800 Subject: [PATCH 0701/2557] examples/transcoding: suppress build warning. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit suppress the "warning: assignment discards ‘const’ qualifier from pointer target type" build warning. Signed-off-by: Jun Zhao Reviewed-by: Steven Liu Signed-off-by: Michael Niedermayer --- doc/examples/transcoding.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/examples/transcoding.c b/doc/examples/transcoding.c index e1b3311081b99..e32ab202453da 100644 --- a/doc/examples/transcoding.c +++ b/doc/examples/transcoding.c @@ -227,8 +227,8 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, { char args[512]; int ret = 0; - AVFilter *buffersrc = NULL; - AVFilter *buffersink = NULL; + const AVFilter *buffersrc = NULL; + const AVFilter *buffersink = NULL; AVFilterContext *buffersrc_ctx = NULL; AVFilterContext *buffersink_ctx = NULL; AVFilterInOut *outputs = avfilter_inout_alloc(); From cb6e20f8de12cf6401ae2dd5f9eea9587ddfe1eb Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Tue, 31 Oct 2017 16:11:06 +0800 Subject: [PATCH 0702/2557] examples/filtering_video: suppress the build warning. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit suppress the "warning: assignment discards ‘const’ qualifier from pointer target type" build warning. Signed-off-by: Jun Zhao Reviewed-by: Steven Liu Signed-off-by: Michael Niedermayer --- doc/examples/filtering_video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/examples/filtering_video.c b/doc/examples/filtering_video.c index fedb2e1c999aa..9b607ba016f73 100644 --- a/doc/examples/filtering_video.c +++ b/doc/examples/filtering_video.c @@ -92,8 +92,8 @@ static int init_filters(const char *filters_descr) { char args[512]; int ret = 0; - AVFilter *buffersrc = avfilter_get_by_name("buffer"); - AVFilter *buffersink = avfilter_get_by_name("buffersink"); + const AVFilter *buffersrc = avfilter_get_by_name("buffer"); + const AVFilter *buffersink = avfilter_get_by_name("buffersink"); AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); AVRational time_base = fmt_ctx->streams[video_stream_index]->time_base; From 5c51d0edd4f37d675cbe1a010baa38c6968b8f19 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Tue, 31 Oct 2017 16:12:36 +0800 Subject: [PATCH 0703/2557] examples/filtering_audio: suppress the build warning. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit suppress the "warning: assignment discards ‘const’ qualifier from pointer target type" build warning. Signed-off-by: Jun Zhao Reviewed-by: Steven Liu Signed-off-by: Michael Niedermayer --- doc/examples/filtering_audio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/examples/filtering_audio.c b/doc/examples/filtering_audio.c index d58b9b75ea056..18d6ca275c50d 100644 --- a/doc/examples/filtering_audio.c +++ b/doc/examples/filtering_audio.c @@ -89,8 +89,8 @@ static int init_filters(const char *filters_descr) { char args[512]; int ret = 0; - AVFilter *abuffersrc = avfilter_get_by_name("abuffer"); - AVFilter *abuffersink = avfilter_get_by_name("abuffersink"); + const AVFilter *abuffersrc = avfilter_get_by_name("abuffer"); + const AVFilter *abuffersink = avfilter_get_by_name("abuffersink"); AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); static const enum AVSampleFormat out_sample_fmts[] = { AV_SAMPLE_FMT_S16, -1 }; From 17806f6083c888fbb1a35da6dd21c42a20e5a315 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Wed, 1 Nov 2017 03:05:51 +0100 Subject: [PATCH 0704/2557] lavu/murmur3: Enforce usual function attribute order. --- libavutil/murmur3.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavutil/murmur3.c b/libavutil/murmur3.c index 4271e01453f77..ef853f404abeb 100644 --- a/libavutil/murmur3.c +++ b/libavutil/murmur3.c @@ -60,7 +60,7 @@ static uint64_t inline get_k1(const uint8_t *src) return k; } -static uint64_t inline get_k2(const uint8_t *src) +static inline uint64_t get_k2(const uint8_t *src) { uint64_t k = AV_RL64(src + 8); k *= c2; @@ -69,7 +69,7 @@ static uint64_t inline get_k2(const uint8_t *src) return k; } -static uint64_t inline update_h1(uint64_t k, uint64_t h1, uint64_t h2) +static inline uint64_t update_h1(uint64_t k, uint64_t h1, uint64_t h2) { k ^= h1; k = ROT(k, 27); @@ -79,7 +79,7 @@ static uint64_t inline update_h1(uint64_t k, uint64_t h1, uint64_t h2) return k; } -static uint64_t inline update_h2(uint64_t k, uint64_t h1, uint64_t h2) +static inline uint64_t update_h2(uint64_t k, uint64_t h1, uint64_t h2) { k ^= h2; k = ROT(k, 31); From a0560d0477549eaaa7d002e013bd8376e80873e4 Mon Sep 17 00:00:00 2001 From: Moritz Barsnick Date: Wed, 1 Nov 2017 01:30:57 +0100 Subject: [PATCH 0705/2557] avfilter/vf_ocr: check ff_set_common_formats() return value Signed-off-by: Moritz Barsnick --- libavfilter/vf_ocr.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavfilter/vf_ocr.c b/libavfilter/vf_ocr.c index e003982f05fcd..abfff494387b0 100644 --- a/libavfilter/vf_ocr.c +++ b/libavfilter/vf_ocr.c @@ -90,9 +90,7 @@ static int query_formats(AVFilterContext *ctx) AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); if (!fmts_list) return AVERROR(ENOMEM); - ff_set_common_formats(ctx, fmts_list); - - return 0; + return ff_set_common_formats(ctx, fmts_list); } static int filter_frame(AVFilterLink *inlink, AVFrame *in) From f6b9e365cd48b96bc8a4af23fb11971bfc263919 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Wed, 1 Nov 2017 13:41:18 +0100 Subject: [PATCH 0706/2557] lavc/ppc/svq1enc_altivec: Fix function prototype after dad31083. Silences a gcc warning: src/libavcodec/ppc/svq1enc_altivec.c: In function 'ff_svq1enc_init_ppc': src/libavcodec/ppc/svq1enc_altivec.c:80:26: warning: assignment from incompatible pointer type --- libavcodec/ppc/svq1enc_altivec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/ppc/svq1enc_altivec.c b/libavcodec/ppc/svq1enc_altivec.c index f63f0866024e6..aa66b40996b23 100644 --- a/libavcodec/ppc/svq1enc_altivec.c +++ b/libavcodec/ppc/svq1enc_altivec.c @@ -31,7 +31,7 @@ #if HAVE_ALTIVEC static int ssd_int8_vs_int16_altivec(const int8_t *pix1, const int16_t *pix2, - int size) + intptr_t size) { int i, size16 = size >> 4; vector signed char vpix1; From 40d635e8c33035e05c60ea32e44d7679df7309dd Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Wed, 1 Nov 2017 14:15:15 +0100 Subject: [PATCH 0707/2557] lavc/ppc/h264dsp: Fix function prototype after bc26fe89. Silences the following gcc warnings: src/libavcodec/ppc/h264dsp.c: In function 'ff_h264dsp_init_ppc': src/libavcodec/ppc/h264dsp.c:809:40: warning: assignment from incompatible pointer type src/libavcodec/ppc/h264dsp.c:810:40: warning: assignment from incompatible pointer type src/libavcodec/ppc/h264dsp.c:811:40: warning: assignment from incompatible pointer type src/libavcodec/ppc/h264dsp.c:812:40: warning: assignment from incompatible pointer type --- libavcodec/ppc/h264dsp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/ppc/h264dsp.c b/libavcodec/ppc/h264dsp.c index e84a058d04eb0..f510544dda581 100644 --- a/libavcodec/ppc/h264dsp.c +++ b/libavcodec/ppc/h264dsp.c @@ -771,12 +771,12 @@ void biweight_h264_W_altivec(uint8_t *dst, uint8_t *src, int stride, int height, } #define H264_WEIGHT(W) \ -static void weight_h264_pixels ## W ## _altivec(uint8_t *block, int stride, int height, \ +static void weight_h264_pixels ## W ## _altivec(uint8_t *block, ptrdiff_t stride, int height, \ int log2_denom, int weight, int offset) \ { \ weight_h264_W_altivec(block, stride, height, log2_denom, weight, offset, W); \ }\ -static void biweight_h264_pixels ## W ## _altivec(uint8_t *dst, uint8_t *src, int stride, int height, \ +static void biweight_h264_pixels ## W ## _altivec(uint8_t *dst, uint8_t *src, ptrdiff_t stride, int height, \ int log2_denom, int weightd, int weights, int offset) \ { \ biweight_h264_W_altivec(dst, src, stride, height, log2_denom, weightd, weights, offset, W); \ From 502050cb4ca71145e4368f1bd471b09795281caa Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 31 Oct 2017 01:01:21 -0300 Subject: [PATCH 0708/2557] avformat/movenc: let avpriv_ac3_parse_header() allocate the AC3HeaderInfo struct This removes sizeof(AC3HeaderInfo) from the ABI. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/movenc.c | 72 ++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index a920eb7c8fd6c..cc3fc19d9b662 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -345,9 +345,9 @@ struct eac3_info { #if CONFIG_AC3_PARSER static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track) { - AC3HeaderInfo tmp, *hdr = &tmp; + AC3HeaderInfo *hdr = NULL; struct eac3_info *info; - int num_blocks; + int num_blocks, ret; if (!track->eac3_priv && !(track->eac3_priv = av_mallocz(sizeof(*info)))) return AVERROR(ENOMEM); @@ -357,9 +357,10 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track) /* drop the packets until we see a good one */ if (!track->entry) { av_log(mov, AV_LOG_WARNING, "Dropping invalid packet from start of the stream\n"); - return 0; - } - return AVERROR_INVALIDDATA; + ret = 0; + } else + ret = AVERROR_INVALIDDATA; + goto end; } info->data_rate = FFMAX(info->data_rate, hdr->bit_rate / 1000); @@ -367,20 +368,25 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track) if (!info->ec3_done) { /* AC-3 substream must be the first one */ - if (hdr->bitstream_id <= 10 && hdr->substreamid != 0) - return AVERROR(EINVAL); + if (hdr->bitstream_id <= 10 && hdr->substreamid != 0) { + ret = AVERROR(EINVAL); + goto end; + } /* this should always be the case, given that our AC-3 parser * concatenates dependent frames to their independent parent */ if (hdr->frame_type == EAC3_FRAME_TYPE_INDEPENDENT) { /* substream ids must be incremental */ - if (hdr->substreamid > info->num_ind_sub + 1) - return AVERROR(EINVAL); + if (hdr->substreamid > info->num_ind_sub + 1) { + ret = AVERROR(EINVAL); + goto end; + } if (hdr->substreamid == info->num_ind_sub + 1) { //info->num_ind_sub++; avpriv_request_sample(track->par, "Multiple independent substreams"); - return AVERROR_PATCHWELCOME; + ret = AVERROR_PATCHWELCOME; + goto end; } else if (hdr->substreamid < info->num_ind_sub || hdr->substreamid == 0 && info->substream[0].bsid) { info->ec3_done = 1; @@ -402,12 +408,14 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track) while (cumul_size != pkt->size) { GetBitContext gbc; - int i, ret; + int i; ret = avpriv_ac3_parse_header(&hdr, pkt->data + cumul_size, pkt->size - cumul_size); if (ret < 0) - return AVERROR_INVALIDDATA; - if (hdr->frame_type != EAC3_FRAME_TYPE_DEPENDENT) - return AVERROR(EINVAL); + goto end; + if (hdr->frame_type != EAC3_FRAME_TYPE_DEPENDENT) { + ret = AVERROR(EINVAL); + goto end; + } info->substream[parent].num_dep_sub++; ret /= 8; @@ -433,37 +441,43 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track) } concatenate: - if (!info->num_blocks && num_blocks == 6) - return pkt->size; - else if (info->num_blocks + num_blocks > 6) - return AVERROR_INVALIDDATA; + if (!info->num_blocks && num_blocks == 6) { + ret = pkt->size; + goto end; + } + else if (info->num_blocks + num_blocks > 6) { + ret = AVERROR_INVALIDDATA; + goto end; + } if (!info->num_blocks) { - int ret = av_packet_ref(&info->pkt, pkt); - if (ret < 0) - return ret; - info->num_blocks = num_blocks; - return 0; + ret = av_packet_ref(&info->pkt, pkt); + if (!ret) + info->num_blocks = num_blocks; + goto end; } else { - int ret; if ((ret = av_grow_packet(&info->pkt, pkt->size)) < 0) - return ret; + goto end; memcpy(info->pkt.data + info->pkt.size - pkt->size, pkt->data, pkt->size); info->num_blocks += num_blocks; info->pkt.duration += pkt->duration; if ((ret = av_copy_packet_side_data(&info->pkt, pkt)) < 0) - return ret; + goto end; if (info->num_blocks != 6) - return 0; + goto end; av_packet_unref(pkt); ret = av_packet_ref(pkt, &info->pkt); if (ret < 0) - return ret; + goto end; av_packet_unref(&info->pkt); info->num_blocks = 0; } + ret = pkt->size; + +end: + av_free(hdr); - return pkt->size; + return ret; } #endif From e70cdf91a7bc997f2b6e917f2ee4bfdc25d31684 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 31 Oct 2017 14:59:08 -0300 Subject: [PATCH 0709/2557] avformat/mux: be less strict with bitstream filter failures This makes the autobsf feature behave the same as the manual bitstream filtering in ffmpeg.c Fixes ticket #6794 Reviewed-by: rcombs Reviewed-by: Carl Eugen Hoyos Signed-off-by: James Almer --- libavformat/mux.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index 77e03ee5baa92..1445e7dcd6f8a 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -876,7 +876,9 @@ static int do_packet_auto_bsf(AVFormatContext *s, AVPacket *pkt) { av_log(ctx, AV_LOG_ERROR, "Failed to send packet to filter %s for stream %d\n", ctx->filter->name, pkt->stream_index); - return ret; + if (s->error_recognition & AV_EF_EXPLODE) + return ret; + return 0; } } return 1; From 4b97435566dc005c8ece7a29c53c47fdd439ae66 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 1 Nov 2017 13:55:29 -0300 Subject: [PATCH 0710/2557] doc/libav-merge: mention skipped hlsenc commit Signed-off-by: James Almer --- doc/libav-merge.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/libav-merge.txt b/doc/libav-merge.txt index 4a46bfcf464a8..19183115adfc5 100644 --- a/doc/libav-merge.txt +++ b/doc/libav-merge.txt @@ -101,6 +101,7 @@ Stuff that didn't reach the codebase: - use av_cpu_max_align() instead of hardcoding alignment requirements (see https://ffmpeg.org/pipermail/ffmpeg-devel/2017-September/215834.html) - f44ec22e0 lavc: use av_cpu_max_align() instead of hardcoding alignment requirements - 4de220d2e frame: allow align=0 (meaning automatic) for av_frame_get_buffer() +- Support recovery from an already present HLS playlist (see 16cb06bb30) Collateral damage that needs work locally: ------------------------------------------ From cf170869821aff42f59538c62574f9f7bdce85d6 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 1 Nov 2017 00:48:56 +0000 Subject: [PATCH 0711/2557] ffmpeg: Fix flush packet stream copy input timestamp handling Since a7da13474286774cf378c3ea606c19a7c1a0eba3, flush packets are passed to process_input_packet() during stream copy. This modifies the input timestamp handling to ignore them - since they contain no data, timestamps should not be affected. --- fftools/ffmpeg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 942579b3781fd..286d898b12105 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2699,7 +2699,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } /* handle stream copy */ - if (!ist->decoding_needed) { + if (!ist->decoding_needed && pkt) { ist->dts = ist->next_dts; switch (ist->dec_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: @@ -2712,7 +2712,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo AVRational time_base_q = AV_TIME_BASE_Q; int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate)); ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q); - } else if (pkt && pkt->duration) { + } else if (pkt->duration) { ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q); } else if(ist->dec_ctx->framerate.num != 0) { int ticks= av_stream_get_parser(ist->st) ? av_stream_get_parser(ist->st)->repeat_pict + 1 : ist->dec_ctx->ticks_per_frame; From e8fafef1db43ead4eae5a6301ccc300e73aa47da Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 30 Oct 2017 23:21:40 +0100 Subject: [PATCH 0712/2557] avcodec/xan: Improve overlapping check Fixes: memcpy-param-overlap Fixes: 3612/clusterfuzz-testcase-minimized-6393461273001984 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/xan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/xan.c b/libavcodec/xan.c index 4c01c0013fd8d..8b4ec82405c07 100644 --- a/libavcodec/xan.c +++ b/libavcodec/xan.c @@ -263,7 +263,7 @@ static inline void xan_wc3_copy_pixel_run(XanContext *s, AVFrame *frame, prevframe_index = (y + motion_y) * stride + x + motion_x; prevframe_x = x + motion_x; - if (prev_palette_plane == palette_plane && FFABS(curframe_index - prevframe_index) < pixel_count) { + if (prev_palette_plane == palette_plane && FFABS(motion_x + width*motion_y) < pixel_count) { avpriv_request_sample(s->avctx, "Overlapping copy"); return ; } From 2b739e1cb8f6ce8baead03ce5c999103ba78f24f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 30 Oct 2017 23:21:41 +0100 Subject: [PATCH 0713/2557] avcodec/h264idct_template: Fix integer overflows in ff_h264_idct8_add() Fixes: runtime error: signed integer overflow: 924846844 + 1457520640 cannot be represented in type 'int' Fixes: 3416/clusterfuzz-testcase-minimized-6125587682820096 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/h264idct_template.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/h264idct_template.c b/libavcodec/h264idct_template.c index 3ad58c4a11d8b..fbd07cb8d57c6 100644 --- a/libavcodec/h264idct_template.c +++ b/libavcodec/h264idct_template.c @@ -107,10 +107,10 @@ void FUNCC(ff_h264_idct8_add)(uint8_t *_dst, int16_t *_block, int stride){ } for( i = 0; i < 8; i++ ) { - const unsigned a0 = block[0+i*8] + block[4+i*8]; - const unsigned a2 = block[0+i*8] - block[4+i*8]; - const unsigned a4 = (block[2+i*8]>>1) - block[6+i*8]; - const unsigned a6 = (block[6+i*8]>>1) + block[2+i*8]; + const unsigned a0 = block[0+i*8] + (unsigned)block[4+i*8]; + const unsigned a2 = block[0+i*8] - (unsigned)block[4+i*8]; + const unsigned a4 = (block[2+i*8]>>1) - (unsigned)block[6+i*8]; + const unsigned a6 = (block[6+i*8]>>1) + (unsigned)block[2+i*8]; const unsigned b0 = a0 + a6; const unsigned b2 = a2 + a4; From 3df4939988ace682f7ac0366ef8fd700d207e6b6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 31 Oct 2017 00:36:32 -0300 Subject: [PATCH 0714/2557] avcodec/dca: return standard error codes in avpriv_dca_parse_core_frame_header() This prevents making the DCAParseError enum part of the ABI. Reviewed-by: Michael Niedermayer Reviewed-by: foo86 Signed-off-by: James Almer --- libavcodec/dca.c | 11 ++++++++--- libavcodec/dca.h | 12 ++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/libavcodec/dca.c b/libavcodec/dca.c index 942fe6c3c9d19..a0729e61abc55 100644 --- a/libavcodec/dca.c +++ b/libavcodec/dca.c @@ -149,9 +149,14 @@ int ff_dca_parse_core_frame_header(DCACoreFrameHeader *h, GetBitContext *gb) int avpriv_dca_parse_core_frame_header(DCACoreFrameHeader *h, const uint8_t *buf, int size) { GetBitContext gb; + int ret; - if (init_get_bits8(&gb, buf, size) < 0) - return DCA_PARSE_ERROR_INVALIDDATA; + ret = init_get_bits8(&gb, buf, size); + if (ret < 0) + return ret; - return ff_dca_parse_core_frame_header(h, &gb); + if (ff_dca_parse_core_frame_header(h, &gb) < 0) + return AVERROR_INVALIDDATA; + + return 0; } diff --git a/libavcodec/dca.h b/libavcodec/dca.h index c70598af92009..dcc7c7b39576c 100644 --- a/libavcodec/dca.h +++ b/libavcodec/dca.h @@ -46,7 +46,6 @@ enum DCAParseError { DCA_PARSE_ERROR_RESERVED_BIT = -7, DCA_PARSE_ERROR_LFE_FLAG = -8, DCA_PARSE_ERROR_PCM_RES = -9, - DCA_PARSE_ERROR_INVALIDDATA = -10, }; typedef struct DCACoreFrameHeader { @@ -211,10 +210,19 @@ int avpriv_dca_convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst, /** * Parse and validate core frame header - * @return 0 on success, negative DCA_PARSE_ERROR_ code on failure + * @param[out] h Pointer to struct where header info is written. + * @param[in] buf Pointer to the data buffer + * @param[in] size Size of the data buffer + * @return 0 on success, negative AVERROR code on failure */ int avpriv_dca_parse_core_frame_header(DCACoreFrameHeader *h, const uint8_t *buf, int size); +/** + * Parse and validate core frame header + * @param[out] h Pointer to struct where header info is written. + * @param[in] gbc BitContext containing the first 120 bits of the frame. + * @return 0 on success, negative DCA_PARSE_ERROR_ code on failure + */ int ff_dca_parse_core_frame_header(DCACoreFrameHeader *h, GetBitContext *gb); #endif /* AVCODEC_DCA_H */ From 42a9722a5c48c3889764de3af68d9afc6d627f61 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Wed, 1 Nov 2017 22:41:09 +0100 Subject: [PATCH 0715/2557] lavc/ppc/hpeldsp_altivec: Remove declaration of two unused variables. --- libavcodec/ppc/hpeldsp_altivec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/ppc/hpeldsp_altivec.c b/libavcodec/ppc/hpeldsp_altivec.c index 4f19521860317..a531b6b6ecd55 100644 --- a/libavcodec/ppc/hpeldsp_altivec.c +++ b/libavcodec/ppc/hpeldsp_altivec.c @@ -84,7 +84,7 @@ void ff_avg_pixels16_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t li /* next one assumes that ((line_size % 8) == 0) */ static void avg_pixels8_altivec(uint8_t * block, const uint8_t * pixels, ptrdiff_t line_size, int h) { - register vector unsigned char pixelsv1, pixelsv2, pixelsv, blockv; + register vector unsigned char pixelsv, blockv; int i; for (i = 0; i < h; i++) { From 3524c92950832705210e50eeafad002fe2d58be5 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Sun, 29 Oct 2017 13:23:18 +0530 Subject: [PATCH 0716/2557] lavf/img2enc: remove redundant option 'updatefirst' 'updatefirst' is an undocumented option redundant to older option 'update'. Since it doesn't serve as a shorthand, this patch removes it. --- libavformat/img2enc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index d793807b33cef..7d64659340d5a 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -104,7 +104,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, - "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", + "Could not get frame filename number %d from pattern '%s' (either set update or use a pattern like %%03d within the filename pattern)\n", img->img_number, img->path); return AVERROR(EINVAL); } @@ -203,7 +203,6 @@ static int query_codec(enum AVCodecID id, int std_compliance) #define OFFSET(x) offsetof(VideoMuxData, x) #define ENC AV_OPT_FLAG_ENCODING_PARAM static const AVOption muxoptions[] = { - { "updatefirst", "continuously overwrite one file", OFFSET(update), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC }, { "update", "continuously overwrite one file", OFFSET(update), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC }, { "start_number", "set first number in the sequence", OFFSET(img_number), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, ENC }, { "strftime", "use strftime for filename", OFFSET(use_strftime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC }, From 345e7072ab867ee1e56cbf857dbc93d37f168294 Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Wed, 1 Nov 2017 21:15:00 +0100 Subject: [PATCH 0717/2557] lavfi: check links properties after configuring them. For now, check the image size. Inspired by a patch from Paul B Mahol. Invalid sizes would be detected later by allocation failures, detecting problems earlier is cleaner. --- libavfilter/avfiltergraph.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index 69cf26896d76c..a009e0a760e11 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -28,6 +28,7 @@ #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/channel_layout.h" +#include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -263,6 +264,27 @@ static int graph_config_links(AVFilterGraph *graph, AVClass *log_ctx) return 0; } +static int graph_check_links(AVFilterGraph *graph, AVClass *log_ctx) +{ + AVFilterContext *f; + AVFilterLink *l; + unsigned i, j; + int ret; + + for (i = 0; i < graph->nb_filters; i++) { + f = graph->filters[i]; + for (j = 0; j < f->nb_outputs; j++) { + l = f->outputs[j]; + if (l->type == AVMEDIA_TYPE_VIDEO) { + ret = av_image_check_size2(l->w, l->h, INT64_MAX, l->format, 0, f); + if (ret < 0) + return ret; + } + } + } + return 0; +} + AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, const char *name) { int i; @@ -1256,6 +1278,8 @@ int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx) return ret; if ((ret = graph_config_links(graphctx, log_ctx))) return ret; + if ((ret = graph_check_links(graphctx, log_ctx))) + return ret; if ((ret = graph_config_pointers(graphctx, log_ctx))) return ret; From 61a17423d3711cb34a18b44e1ec2510c2f70a56c Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 20 Oct 2017 20:58:12 +0200 Subject: [PATCH 0718/2557] configure: Miscellaneous small changes to helper functions - Reuse sanitize_var_name() where appropriate - Add some quotes to enabled()/disabled() to ease readability - Fix logged names of some helper functions - Filter LDFLAGS also in test_ldflags() --- configure | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/configure b/configure index 5981223e3172e..4dfe24e39e5fe 100755 --- a/configure +++ b/configure @@ -513,13 +513,13 @@ disable_weak(){ enable_sanitized(){ for var; do - enable $(echo "$var" | sed 's/[^A-Za-z0-9_]/_/g') + enable $(sanitize_var_name $var) done } disable_sanitized(){ for var; do - disable $(echo "$var" | sed 's/[^A-Za-z0-9_]/_/g') + disable $(sanitize_var_name $var) done } @@ -552,12 +552,12 @@ enable_deep_weak(){ } enabled(){ - test "${1#!}" = "$1" && op== || op=!= + test "${1#!}" = "$1" && op="=" || op="!=" eval test "x\$${1#!}" $op "xyes" } disabled(){ - test "${1#!}" = "$1" && op== || op=!= + test "${1#!}" = "$1" && op="=" || op="!=" eval test "x\$${1#!}" $op "xno" } @@ -899,6 +899,7 @@ check_objcflags(){ test_ldflags(){ log test_ldflags "$@" + set -- $($ldflags_filter "$@") check_ld "$@" < Date: Sat, 21 Oct 2017 00:22:38 +0200 Subject: [PATCH 0719/2557] configure: Remove unused apply() helper function --- configure | 6 ------ 1 file changed, 6 deletions(-) diff --git a/configure b/configure index 4dfe24e39e5fe..6ff2ae2f921e7 100755 --- a/configure +++ b/configure @@ -1196,12 +1196,6 @@ check_host_cpp_condition(){ EOF } -apply(){ - file=$1 - shift - "$@" < "$file" > "$file.tmp" && mv "$file.tmp" "$file" || rm "$file.tmp" -} - cp_if_changed(){ cmp -s "$1" "$2" && { test "$quiet" != "yes" && echo "$2 is unchanged"; } && return mkdir -p "$(dirname $2)" From 192fe52e42f64a493c47cad1461b20fe1149dbea Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 23 Sep 2017 16:42:11 +0200 Subject: [PATCH 0720/2557] configure: Miscellaneous minor changes to config file handling - Move generating config.fate to a more sensible place. - Move printing warnings to a more appropriate place. - Improve "generated by" comment in libavutil/avconfig.h. - Drop pointless informative output about generating config files. - Write a standard comment header to config.asm as well. --- configure | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/configure b/configure index 6ff2ae2f921e7..fc45fde2d4ccb 100755 --- a/configure +++ b/configure @@ -4109,12 +4109,6 @@ esac check_compile_assert flt_lim "float.h limits.h" "DBL_MAX == (double)DBL_MAX" || add_cppflags '-I\$(SRC_PATH)/compat/float' -esc(){ - echo "$*" | sed 's/%/%25/g;s/:/%3a/g' -} - -echo "config:$arch:$subarch:$cpu:$target_os:$(esc $cc_ident):$(esc $LIBAV_CONFIGURATION)" > avbuild/config.fate - check_cpp_condition stdlib.h "defined(__PIC__) || defined(__pic__) || defined(PIC)" && enable_weak pic set_default $PATHS_LIST @@ -5192,12 +5186,18 @@ fi echo "License: $license" -echo "Creating configuration files ..." - fi # test "$quiet" != "yes" +test -n "$WARNINGS" && printf "\n$WARNINGS" + test -e Makefile || echo "include $source_path/Makefile" > Makefile +esc(){ + echo "$*" | sed 's/%/%25/g;s/:/%3a/g' +} + +echo "config:$arch:$subarch:$cpu:$target_os:$(esc $cc_ident):$(esc $LIBAV_CONFIGURATION)" > avbuild/config.fate + config_files="$TMPH avbuild/config.mak" cat > avbuild/config.mak <$TMPASM + cat > $TMPASM <> $TMPH @@ -5355,7 +5357,7 @@ touch avbuild/.config enabled x86asm && cp_if_changed $TMPASM config.asm cat > $TMPH < avbuild/config.sh < Date: Fri, 20 Oct 2017 03:57:55 +0200 Subject: [PATCH 0721/2557] configure: Simplify MIPS instruction set handling --- configure | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index fc45fde2d4ccb..644597617598a 100755 --- a/configure +++ b/configure @@ -4268,10 +4268,10 @@ EOF elif enabled mips; then - check_inline_asm loongson '"dmult.g $1, $2, $3"' + # make sure that only one instruction set is enabled + disable $ARCH_EXT_LIST_MIPS - # make sure that only an instruction set is enabled - disable mips64r6 mips32r6 mips64r2 mips32r2 mips64r1 mips32r1 + check_inline_asm loongson '"dmult.g $1, $2, $3"' if enabled mips64; then check_inline_asm mips64r6 '"dlsa $0, $0, $0, 1"' || From d5995c531d6e9e20e126ae64665783abe959d82b Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Wed, 1 Nov 2017 21:38:39 +0100 Subject: [PATCH 0722/2557] lavfi/framepool: use av_image_check_size2(). Allow filters to handle larger frames. --- libavfilter/framepool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/framepool.c b/libavfilter/framepool.c index 42c0e58498b57..da2ac5cf69dbc 100644 --- a/libavfilter/framepool.c +++ b/libavfilter/framepool.c @@ -71,7 +71,7 @@ FFFramePool *ff_frame_pool_video_init(AVBufferRef* (*alloc)(int size), pool->format = format; pool->align = align; - if ((ret = av_image_check_size(width, height, 0, NULL)) < 0) { + if ((ret = av_image_check_size2(width, height, INT64_MAX, format, 0, NULL)) < 0) { goto fail; } From c52beb4839e030a15b68919b822cb25ad553b9bc Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 2 Nov 2017 22:29:28 +0800 Subject: [PATCH 0723/2557] avformat/hlsenc: check hls segment mode for ignore the init filename ignore the fmp4_init_filename when in normal hls segment mode Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 0ea93480a5bb6..6d573db094ca9 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1443,6 +1443,7 @@ static int hls_write_header(AVFormatContext *s) } } + if (hls->segment_type == SEGMENT_TYPE_FMP4) { if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) { hls->base_output_dirname = av_malloc(fmp4_init_filename_len); if (!hls->base_output_dirname) { @@ -1472,6 +1473,7 @@ static int hls_write_header(AVFormatContext *s) av_strlcpy(hls->base_output_dirname, hls->fmp4_init_filename, fmp4_init_filename_len); } } + } if (!hls->use_localtime) { ret = sls_flag_check_duration_size_index(hls); From c7360512c27df260550d6fec36039769e6a996ea Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 2 Nov 2017 22:30:06 +0800 Subject: [PATCH 0724/2557] avformat/hlsenc: reindent hlsenc code Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 52 ++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 6d573db094ca9..5ea9d216a4aa5 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1444,36 +1444,36 @@ static int hls_write_header(AVFormatContext *s) } if (hls->segment_type == SEGMENT_TYPE_FMP4) { - if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) { - hls->base_output_dirname = av_malloc(fmp4_init_filename_len); - if (!hls->base_output_dirname) { - ret = AVERROR(ENOMEM); - goto fail; - } - av_strlcpy(hls->base_output_dirname, hls->fmp4_init_filename, fmp4_init_filename_len); - } else { - if (basename_size > 0) { - hls->base_output_dirname = av_malloc(basename_size); + if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) { + hls->base_output_dirname = av_malloc(fmp4_init_filename_len); + if (!hls->base_output_dirname) { + ret = AVERROR(ENOMEM); + goto fail; + } + av_strlcpy(hls->base_output_dirname, hls->fmp4_init_filename, fmp4_init_filename_len); } else { - hls->base_output_dirname = av_malloc(strlen(hls->fmp4_init_filename)); - } - if (!hls->base_output_dirname) { - ret = AVERROR(ENOMEM); - goto fail; - } + if (basename_size > 0) { + hls->base_output_dirname = av_malloc(basename_size); + } else { + hls->base_output_dirname = av_malloc(strlen(hls->fmp4_init_filename)); + } + if (!hls->base_output_dirname) { + ret = AVERROR(ENOMEM); + goto fail; + } - if (basename_size > 0) { - av_strlcpy(hls->base_output_dirname, s->filename, basename_size); - p = strrchr(hls->base_output_dirname, '/'); - } - if (p) { - *(p + 1) = '\0'; - av_strlcat(hls->base_output_dirname, hls->fmp4_init_filename, basename_size); - } else { - av_strlcpy(hls->base_output_dirname, hls->fmp4_init_filename, fmp4_init_filename_len); + if (basename_size > 0) { + av_strlcpy(hls->base_output_dirname, s->filename, basename_size); + p = strrchr(hls->base_output_dirname, '/'); + } + if (p) { + *(p + 1) = '\0'; + av_strlcat(hls->base_output_dirname, hls->fmp4_init_filename, basename_size); + } else { + av_strlcpy(hls->base_output_dirname, hls->fmp4_init_filename, fmp4_init_filename_len); + } } } - } if (!hls->use_localtime) { ret = sls_flag_check_duration_size_index(hls); From 72dbc610be3272ba36603f78a39cc2d2d8fe0cc3 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Wed, 1 Nov 2017 11:36:25 +0530 Subject: [PATCH 0725/2557] avcodec/mips: Improve avc avg mc 02, 12 and 32 msa functions Remove loops and unroll as block sizes are known. Load the specific destination bytes instead of MSA load and pack. Remove unused macro and functions. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/h264qpel_msa.c | 1002 +++++++++++++++++++++----------- 1 file changed, 676 insertions(+), 326 deletions(-) diff --git a/libavcodec/mips/h264qpel_msa.c b/libavcodec/mips/h264qpel_msa.c index e3a8634924d35..3df72f591c4ff 100644 --- a/libavcodec/mips/h264qpel_msa.c +++ b/libavcodec/mips/h264qpel_msa.c @@ -749,177 +749,6 @@ static void avc_luma_hz_qrt_and_aver_dst_16x16_msa(const uint8_t *src, } } -static void avc_luma_vt_and_aver_dst_4x4_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, int32_t dst_stride) -{ - int16_t filt_const0 = 0xfb01; - int16_t filt_const1 = 0x1414; - int16_t filt_const2 = 0x1fb; - v16u8 dst0, dst1, dst2, dst3; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; - v16i8 src10_r, src32_r, src54_r, src76_r, src21_r, src43_r, src65_r; - v16i8 src87_r, src2110, src4332, src6554, src8776; - v8i16 out10, out32; - v16i8 filt0, filt1, filt2; - v16u8 res; - - filt0 = (v16i8) __msa_fill_h(filt_const0); - filt1 = (v16i8) __msa_fill_h(filt_const1); - filt2 = (v16i8) __msa_fill_h(filt_const2); - - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - src += (5 * src_stride); - - ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, - src10_r, src21_r, src32_r, src43_r); - ILVR_D2_SB(src21_r, src10_r, src43_r, src32_r, src2110, src4332); - XORI_B2_128_SB(src2110, src4332); - LD_SB4(src, src_stride, src5, src6, src7, src8); - ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, - src54_r, src65_r, src76_r, src87_r); - ILVR_D2_SB(src65_r, src54_r, src87_r, src76_r, src6554, src8776); - XORI_B2_128_SB(src6554, src8776); - out10 = DPADD_SH3_SH(src2110, src4332, src6554, filt0, filt1, filt2); - out32 = DPADD_SH3_SH(src4332, src6554, src8776, filt0, filt1, filt2); - SRARI_H2_SH(out10, out32, 5); - SAT_SH2_SH(out10, out32, 7); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - res = PCKEV_XORI128_UB(out10, out32); - - ILVR_W2_UB(dst1, dst0, dst3, dst2, dst0, dst1); - - dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0); - dst0 = __msa_aver_u_b(res, dst0); - - ST4x4_UB(dst0, dst0, 0, 1, 2, 3, dst, dst_stride); -} - -static void avc_luma_vt_and_aver_dst_8x8_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, int32_t dst_stride) -{ - int32_t loop_cnt; - int16_t filt_const0 = 0xfb01; - int16_t filt_const1 = 0x1414; - int16_t filt_const2 = 0x1fb; - v16u8 dst0, dst1, dst2, dst3; - v16i8 src0, src1, src2, src3, src4, src7, src8, src9, src10; - v16i8 src10_r, src32_r, src76_r, src98_r; - v16i8 src21_r, src43_r, src87_r, src109_r; - v8i16 out0, out1, out2, out3; - v16i8 filt0, filt1, filt2; - - filt0 = (v16i8) __msa_fill_h(filt_const0); - filt1 = (v16i8) __msa_fill_h(filt_const1); - filt2 = (v16i8) __msa_fill_h(filt_const2); - - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - src += (5 * src_stride); - - XORI_B5_128_SB(src0, src1, src2, src3, src4); - ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, - src10_r, src21_r, src32_r, src43_r); - - for (loop_cnt = 2; loop_cnt--;) { - LD_SB4(src, src_stride, src7, src8, src9, src10); - src += (4 * src_stride); - - XORI_B4_128_SB(src7, src8, src9, src10); - ILVR_B4_SB(src7, src4, src8, src7, src9, src8, src10, src9, - src76_r, src87_r, src98_r, src109_r); - out0 = DPADD_SH3_SH(src10_r, src32_r, src76_r, filt0, filt1, filt2); - out1 = DPADD_SH3_SH(src21_r, src43_r, src87_r, filt0, filt1, filt2); - out2 = DPADD_SH3_SH(src32_r, src76_r, src98_r, filt0, filt1, filt2); - out3 = DPADD_SH3_SH(src43_r, src87_r, src109_r, filt0, filt1, filt2); - SRARI_H4_SH(out0, out1, out2, out3, 5); - SAT_SH4_SH(out0, out1, out2, out3, 7); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - ILVR_D2_UB(dst1, dst0, dst3, dst2, dst0, dst1); - CONVERT_UB_AVG_ST8x4_UB(out0, out1, out2, out3, dst0, dst1, - dst, dst_stride); - dst += (4 * dst_stride); - - src10_r = src76_r; - src32_r = src98_r; - src21_r = src87_r; - src43_r = src109_r; - src4 = src10; - } -} - -static void avc_luma_vt_and_aver_dst_16x16_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, int32_t dst_stride) -{ - int32_t loop_cnt; - int16_t filt_const0 = 0xfb01; - int16_t filt_const1 = 0x1414; - int16_t filt_const2 = 0x1fb; - v16u8 dst0, dst1, dst2, dst3; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; - v16i8 src10_r, src32_r, src54_r, src76_r, src21_r, src43_r, src65_r; - v16i8 src87_r, src10_l, src32_l, src54_l, src76_l, src21_l, src43_l; - v16i8 src65_l, src87_l; - v8i16 out0_r, out1_r, out2_r, out3_r, out0_l, out1_l, out2_l, out3_l; - v16i8 filt0, filt1, filt2; - v16u8 res0, res1, res2, res3; - - filt0 = (v16i8) __msa_fill_h(filt_const0); - filt1 = (v16i8) __msa_fill_h(filt_const1); - filt2 = (v16i8) __msa_fill_h(filt_const2); - - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - src += (5 * src_stride); - - XORI_B5_128_SB(src0, src1, src2, src3, src4); - ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, - src10_r, src21_r, src32_r, src43_r); - ILVL_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, - src10_l, src21_l, src32_l, src43_l); - - for (loop_cnt = 4; loop_cnt--;) { - LD_SB4(src, src_stride, src5, src6, src7, src8); - src += (4 * src_stride); - - XORI_B4_128_SB(src5, src6, src7, src8); - ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, - src54_r, src65_r, src76_r, src87_r); - ILVL_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, - src54_l, src65_l, src76_l, src87_l); - out0_r = DPADD_SH3_SH(src10_r, src32_r, src54_r, filt0, filt1, filt2); - out1_r = DPADD_SH3_SH(src21_r, src43_r, src65_r, filt0, filt1, filt2); - out2_r = DPADD_SH3_SH(src32_r, src54_r, src76_r, filt0, filt1, filt2); - out3_r = DPADD_SH3_SH(src43_r, src65_r, src87_r, filt0, filt1, filt2); - out0_l = DPADD_SH3_SH(src10_l, src32_l, src54_l, filt0, filt1, filt2); - out1_l = DPADD_SH3_SH(src21_l, src43_l, src65_l, filt0, filt1, filt2); - out2_l = DPADD_SH3_SH(src32_l, src54_l, src76_l, filt0, filt1, filt2); - out3_l = DPADD_SH3_SH(src43_l, src65_l, src87_l, filt0, filt1, filt2); - SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 5); - SRARI_H4_SH(out0_l, out1_l, out2_l, out3_l, 5); - SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); - SAT_SH4_SH(out0_l, out1_l, out2_l, out3_l, 7); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - PCKEV_B4_UB(out0_l, out0_r, out1_l, out1_r, out2_l, out2_r, out3_l, - out3_r, res0, res1, res2, res3); - XORI_B4_128_UB(res0, res1, res2, res3); - AVER_UB4_UB(res0, dst0, res1, dst1, res2, dst2, res3, dst3, - res0, res1, res2, res3); - ST_UB4(res0, res1, res2, res3, dst, dst_stride); - dst += (4 * dst_stride); - - src10_r = src54_r; - src32_r = src76_r; - src21_r = src65_r; - src43_r = src87_r; - src10_l = src54_l; - src32_l = src76_l; - src21_l = src65_l; - src43_l = src87_l; - src4 = src8; - } -} - static void avc_luma_vt_qrt_and_aver_dst_4x4_msa(const uint8_t *src, int32_t src_stride, uint8_t *dst, @@ -1141,125 +970,6 @@ static void avc_luma_vt_qrt_and_aver_dst_16x16_msa(const uint8_t *src, } } -static void avc_luma_midh_qrt_and_aver_dst_4w_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - int32_t height, - uint8_t horiz_offset) -{ - uint32_t row; - v16i8 src0, src1, src2, src3, src4, src5, src6; - v16u8 dst0, dst1, res; - v8i16 vt_res0, vt_res1, vt_res2, vt_res3; - v4i32 hz_res0, hz_res1; - v8i16 res0, res1; - v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5; - v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; - v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; - v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; - v8i16 minus5h = __msa_ldi_h(-5); - v8i16 plus20h = __msa_ldi_h(20); - v8i16 zeros = { 0 }; - - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - src += (5 * src_stride); - - XORI_B5_128_SB(src0, src1, src2, src3, src4); - - for (row = (height >> 1); row--;) { - LD_SB2(src, src_stride, src5, src6); - src += (2 * src_stride); - - XORI_B2_128_SB(src5, src6); - LD_UB2(dst, dst_stride, dst0, dst1); - - dst0 = (v16u8) __msa_ilvr_w((v4i32) dst1, (v4i32) dst0); - - AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src0, src1, src2, src3, src4, src5, - vt_res0, vt_res1); - AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src1, src2, src3, src4, src5, src6, - vt_res2, vt_res3); - VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, - mask0, mask1, mask2, shf_vec0, shf_vec1, shf_vec2); - VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, - mask0, mask1, mask2, shf_vec3, shf_vec4, shf_vec5); - - hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); - DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); - - hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); - DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); - - SRARI_W2_SW(hz_res0, hz_res1, 10); - SAT_SW2_SW(hz_res0, hz_res1, 7); - - res0 = __msa_srari_h(shf_vec2, 5); - res1 = __msa_srari_h(shf_vec5, 5); - - SAT_SH2_SH(res0, res1, 7); - - if (horiz_offset) { - res0 = __msa_ilvod_h(zeros, res0); - res1 = __msa_ilvod_h(zeros, res1); - } else { - ILVEV_H2_SH(res0, zeros, res1, zeros, res0, res1); - } - hz_res0 = __msa_aver_s_w(hz_res0, (v4i32) res0); - hz_res1 = __msa_aver_s_w(hz_res1, (v4i32) res1); - res0 = __msa_pckev_h((v8i16) hz_res1, (v8i16) hz_res0); - - res = PCKEV_XORI128_UB(res0, res0); - - dst0 = __msa_aver_u_b(res, dst0); - - ST4x2_UB(dst0, dst, dst_stride); - dst += (2 * dst_stride); - - src0 = src2; - src1 = src3; - src2 = src4; - src3 = src5; - src4 = src6; - } -} - -static void avc_luma_midh_qrt_and_aver_dst_8w_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - int32_t height, - uint8_t horiz_offset) -{ - uint32_t multiple8_cnt; - - for (multiple8_cnt = 2; multiple8_cnt--;) { - avc_luma_midh_qrt_and_aver_dst_4w_msa(src, src_stride, dst, dst_stride, - height, horiz_offset); - - src += 4; - dst += 4; - } -} - -static void avc_luma_midh_qrt_and_aver_dst_16w_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - int32_t height, - uint8_t horiz_offset) -{ - uint32_t multiple8_cnt; - - for (multiple8_cnt = 4; multiple8_cnt--;) { - avc_luma_midh_qrt_and_aver_dst_4w_msa(src, src_stride, dst, dst_stride, - height, horiz_offset); - - src += 4; - dst += 4; - } -} - static void avc_luma_midv_qrt_and_aver_dst_4w_msa(const uint8_t *src, int32_t src_stride, uint8_t *dst, @@ -4469,61 +4179,701 @@ void ff_avg_h264_qpel4_mc23_msa(uint8_t *dst, const uint8_t *src, void ff_avg_h264_qpel16_mc02_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_vt_and_aver_dst_16x16_msa(src - (stride * 2), stride, dst, stride); -} + int32_t loop_cnt; + int16_t filt_const0 = 0xfb01; + int16_t filt_const1 = 0x1414; + int16_t filt_const2 = 0x1fb; + v16u8 res0, res1, res2, res3, dst0, dst1, dst2, dst3; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 src10_r, src32_r, src54_r, src76_r, src21_r, src43_r, src65_r; + v16i8 src87_r, src10_l, src32_l, src54_l, src76_l, src21_l, src43_l; + v16i8 src65_l, src87_l, filt0, filt1, filt2; + v8i16 out0_r, out1_r, out2_r, out3_r, out0_l, out1_l, out2_l, out3_l; -void ff_avg_h264_qpel8_mc02_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_vt_and_aver_dst_8x8_msa(src - (stride * 2), stride, dst, stride); -} + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + src -= (stride * 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + + XORI_B5_128_SB(src0, src1, src2, src3, src4); + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + ILVL_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_l, src21_l, + src32_l, src43_l); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src, stride, src5, src6, src7, src8); + src += (4 * stride); + + XORI_B4_128_SB(src5, src6, src7, src8); + ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_r, + src65_r, src76_r, src87_r); + ILVL_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_l, + src65_l, src76_l, src87_l); + out0_r = AVC_DOT_SH3_SH(src10_r, src32_r, src54_r, filt0, filt1, filt2); + out1_r = AVC_DOT_SH3_SH(src21_r, src43_r, src65_r, filt0, filt1, filt2); + out2_r = AVC_DOT_SH3_SH(src32_r, src54_r, src76_r, filt0, filt1, filt2); + out3_r = AVC_DOT_SH3_SH(src43_r, src65_r, src87_r, filt0, filt1, filt2); + out0_l = AVC_DOT_SH3_SH(src10_l, src32_l, src54_l, filt0, filt1, filt2); + out1_l = AVC_DOT_SH3_SH(src21_l, src43_l, src65_l, filt0, filt1, filt2); + out2_l = AVC_DOT_SH3_SH(src32_l, src54_l, src76_l, filt0, filt1, filt2); + out3_l = AVC_DOT_SH3_SH(src43_l, src65_l, src87_l, filt0, filt1, filt2); + SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 5); + SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); + SRARI_H4_SH(out0_l, out1_l, out2_l, out3_l, 5); + SAT_SH4_SH(out0_l, out1_l, out2_l, out3_l, 7); + LD_UB4(dst, stride, dst0, dst1, dst2, dst3); + PCKEV_B4_UB(out0_l, out0_r, out1_l, out1_r, out2_l, out2_r, out3_l, + out3_r, res0, res1, res2, res3); + XORI_B4_128_UB(res0, res1, res2, res3); + AVER_UB2_UB(res0, dst0, res1, dst1, res0, res1); + AVER_UB2_UB(res2, dst2, res3, dst3, res2, res3); + ST_UB4(res0, res1, res2, res3, dst, stride); + dst += (4 * stride); + + src10_r = src54_r; + src32_r = src76_r; + src21_r = src65_r; + src43_r = src87_r; + src10_l = src54_l; + src32_l = src76_l; + src21_l = src65_l; + src43_l = src87_l; + src4 = src8; + } +} + +void ff_avg_h264_qpel8_mc02_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint64_t tp0, tp1, tp2, tp3; + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + v16u8 dst0 = { 0 }, dst1 = { 0 }, dst2 = { 0 }, dst3 = { 0 }; + v16u8 out0, out1, out2, out3; + v16i8 src0, src1, src2, src3, src4, src7, src8, src9, src10, src109_r; + v16i8 src10_r, src32_r, src76_r, src98_r, src21_r, src43_r, src87_r; + v16i8 filt0, filt1, filt2; + v8i16 out0_r, out1_r, out2_r, out3_r, out4_r, out5_r, out6_r, out7_r; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + + src -= (stride * 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + + XORI_B5_128_SB(src0, src1, src2, src3, src4); + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + + LD_SB4(src, stride, src7, src8, src9, src10); + src += (4 * stride); + XORI_B4_128_SB(src7, src8, src9, src10); + ILVR_B4_SB(src7, src4, src8, src7, src9, src8, src10, src9, src76_r, + src87_r, src98_r, src109_r); + out0_r = AVC_DOT_SH3_SH(src10_r, src32_r, src76_r, filt0, filt1, filt2); + out1_r = AVC_DOT_SH3_SH(src21_r, src43_r, src87_r, filt0, filt1, filt2); + out2_r = AVC_DOT_SH3_SH(src32_r, src76_r, src98_r, filt0, filt1, filt2); + out3_r = AVC_DOT_SH3_SH(src43_r, src87_r, src109_r, filt0, filt1, filt2); + + LD_SB4(src, stride, src0, src1, src2, src3); + XORI_B4_128_SB(src0, src1, src2, src3); + ILVR_B4_SB(src0, src10, src1, src0, src2, src1, src3, src2, src10_r, + src21_r, src32_r, src43_r); + out4_r = AVC_DOT_SH3_SH(src76_r, src98_r, src10_r, filt0, filt1, filt2); + out5_r = AVC_DOT_SH3_SH(src87_r, src109_r, src21_r, filt0, filt1, filt2); + out6_r = AVC_DOT_SH3_SH(src98_r, src10_r, src32_r, filt0, filt1, filt2); + out7_r = AVC_DOT_SH3_SH(src109_r, src21_r, src43_r, filt0, filt1, filt2); + + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + LD4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst2); + INSERT_D2_UB(tp2, tp3, dst3); + + SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 5); + SRARI_H4_SH(out4_r, out5_r, out6_r, out7_r, 5); + SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); + SAT_SH4_SH(out4_r, out5_r, out6_r, out7_r, 7); + out0 = PCKEV_XORI128_UB(out0_r, out1_r); + out1 = PCKEV_XORI128_UB(out2_r, out3_r); + out2 = PCKEV_XORI128_UB(out4_r, out5_r); + out3 = PCKEV_XORI128_UB(out6_r, out7_r); + AVER_UB4_UB(out0, dst0, out1, dst1, out2, dst2, out3, dst3, dst0, dst1, + dst2, dst3); + ST8x8_UB(dst0, dst1, dst2, dst3, dst, stride); +} void ff_avg_h264_qpel4_mc02_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_vt_and_aver_dst_4x4_msa(src - (stride * 2), stride, dst, stride); + uint32_t tp0, tp1, tp2, tp3; + int16_t filt_const0 = 0xfb01; + int16_t filt_const1 = 0x1414; + int16_t filt_const2 = 0x1fb; + v16u8 res, dst0 = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 src10_r, src32_r, src54_r, src76_r, src21_r, src43_r, src65_r; + v16i8 src87_r, src2110, src4332, src6554, src8776, filt0, filt1, filt2; + v8i16 out10, out32; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + + src -= (stride * 2); + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + ILVR_D2_SB(src21_r, src10_r, src43_r, src32_r, src2110, src4332); + XORI_B2_128_SB(src2110, src4332); + LD_SB4(src, stride, src5, src6, src7, src8); + ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_r, src65_r, + src76_r, src87_r); + ILVR_D2_SB(src65_r, src54_r, src87_r, src76_r, src6554, src8776); + XORI_B2_128_SB(src6554, src8776); + out10 = AVC_DOT_SH3_SH(src2110, src4332, src6554, filt0, filt1, filt2); + out32 = AVC_DOT_SH3_SH(src4332, src6554, src8776, filt0, filt1, filt2); + SRARI_H2_SH(out10, out32, 5); + SAT_SH2_SH(out10, out32, 7); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); + res = PCKEV_XORI128_UB(out10, out32); + dst0 = __msa_aver_u_b(res, dst0); + ST4x4_UB(dst0, dst0, 0, 1, 2, 3, dst, stride); } void ff_avg_h264_qpel16_mc12_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_midh_qrt_and_aver_dst_16w_msa(src - (2 * stride) - 2, - stride, dst, stride, 16, 0); + uint32_t row; + v16u8 out, dst0; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 src11; + v8i16 vt_res0, vt_res1, vt_res2, vt_res3, tmp0, tmp1, tmp2, tmp3, mask3; + v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5, shf_vec6; + v8i16 shf_vec7, shf_vec8, shf_vec9, shf_vec10, shf_vec11, mask4, mask5; + v4i32 hz_res0, hz_res1, hz_res2, hz_res3; + v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; + v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; + v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; + v8i16 minus5h = __msa_ldi_h(-5); + v8i16 plus20h = __msa_ldi_h(20); + + mask3 = mask0 + 4; + mask4 = mask1 + 4; + mask5 = mask2 + 4; + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + LD_SB5(src + 8, stride, src7, src8, src9, src10, src11); + src += (5 * stride); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + XORI_B5_128_SB(src7, src8, src9, src10, src11); + + for (row = 16; row--;) { + LD_SB2(src, 8, src5, src6); + src += stride; + XORI_B2_128_SB(src5, src6); + dst0 = LD_UB(dst); + + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src0, src1, src2, src3, src4, src5, + vt_res0, vt_res1); + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src7, src8, src9, src10, src11, src6, + vt_res2, vt_res3); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec2); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec5); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask3, + mask4, mask5, shf_vec6, shf_vec7, shf_vec8); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask3, + mask4, mask5, shf_vec9, shf_vec10, shf_vec11); + hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); + hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); + hz_res2 = __msa_hadd_s_w(shf_vec6, shf_vec6); + hz_res3 = __msa_hadd_s_w(shf_vec9, shf_vec9); + DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); + DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); + DPADD_SH2_SW(shf_vec7, shf_vec8, minus5h, plus20h, hz_res2, hz_res2); + DPADD_SH2_SW(shf_vec10, shf_vec11, minus5h, plus20h, hz_res3, hz_res3); + SRARI_W4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 10); + SAT_SW4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 7); + tmp0 = __msa_srari_h(shf_vec2, 5); + tmp1 = __msa_srari_h(shf_vec5, 5); + tmp2 = __msa_srari_h(shf_vec8, 5); + tmp3 = __msa_srari_h(shf_vec11, 5); + SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); + PCKEV_H2_SH(tmp2, tmp0, tmp3, tmp1, tmp0, tmp1); + PCKEV_H2_SH(hz_res2, hz_res0, hz_res3, hz_res1, tmp2, tmp3); + tmp0 = __msa_aver_s_h(tmp2, tmp0); + tmp1 = __msa_aver_s_h(tmp3, tmp1); + out = PCKEV_XORI128_UB(tmp0, tmp1); + out = __msa_aver_u_b(out, dst0); + ST_UB(out, dst); + dst += stride; + + src0 = src1; + src1 = src2; + src2 = src3; + src3 = src4; + src4 = src5; + src7 = src8; + src8 = src9; + src9 = src10; + src10 = src11; + src11 = src6; + } } void ff_avg_h264_qpel16_mc32_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_midh_qrt_and_aver_dst_16w_msa(src - (2 * stride) - 2, - stride, dst, stride, 16, 1); -} + uint32_t row; + v16u8 out, dst0; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 src11; + v8i16 vt_res0, vt_res1, vt_res2, vt_res3, tmp0, tmp1, tmp2, tmp3, mask3; + v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5, shf_vec6; + v8i16 shf_vec7, shf_vec8, shf_vec9, shf_vec10, shf_vec11, mask4, mask5; + v4i32 hz_res0, hz_res1, hz_res2, hz_res3; + v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; + v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; + v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; + v8i16 minus5h = __msa_ldi_h(-5); + v8i16 plus20h = __msa_ldi_h(20); -void ff_avg_h264_qpel8_mc12_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_midh_qrt_and_aver_dst_8w_msa(src - (2 * stride) - 2, - stride, dst, stride, 8, 0); -} + mask3 = mask0 + 4; + mask4 = mask1 + 4; + mask5 = mask2 + 4; -void ff_avg_h264_qpel8_mc32_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_midh_qrt_and_aver_dst_8w_msa(src - (2 * stride) - 2, - stride, dst, stride, 8, 1); -} + src -= ((2 * stride) + 2); -void ff_avg_h264_qpel4_mc12_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_midh_qrt_and_aver_dst_4w_msa(src - (2 * stride) - 2, - stride, dst, stride, 4, 0); -} + LD_SB5(src, stride, src0, src1, src2, src3, src4); + LD_SB5(src + 8, stride, src7, src8, src9, src10, src11); + src += (5 * stride); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + XORI_B5_128_SB(src7, src8, src9, src10, src11); -void ff_avg_h264_qpel4_mc32_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_midh_qrt_and_aver_dst_4w_msa(src - (2 * stride) - 2, - stride, dst, stride, 4, 1); + for (row = 16; row--;) { + LD_SB2(src, 8, src5, src6); + src += stride; + XORI_B2_128_SB(src5, src6); + dst0 = LD_UB(dst); + + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src0, src1, src2, src3, src4, src5, + vt_res0, vt_res1); + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src7, src8, src9, src10, src11, src6, + vt_res2, vt_res3); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec2); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec5); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask3, + mask4, mask5, shf_vec6, shf_vec7, shf_vec8); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask3, + mask4, mask5, shf_vec9, shf_vec10, shf_vec11); + hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); + hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); + hz_res2 = __msa_hadd_s_w(shf_vec6, shf_vec6); + hz_res3 = __msa_hadd_s_w(shf_vec9, shf_vec9); + DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); + DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); + DPADD_SH2_SW(shf_vec7, shf_vec8, minus5h, plus20h, hz_res2, hz_res2); + DPADD_SH2_SW(shf_vec10, shf_vec11, minus5h, plus20h, hz_res3, hz_res3); + SRARI_W4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 10); + SAT_SW4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 7); + tmp0 = __msa_srari_h(shf_vec2, 5); + tmp1 = __msa_srari_h(shf_vec5, 5); + tmp2 = __msa_srari_h(shf_vec8, 5); + tmp3 = __msa_srari_h(shf_vec11, 5); + SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); + tmp0 = __msa_pckod_h(tmp2, tmp0); + tmp1 = __msa_pckod_h(tmp3, tmp1); + PCKEV_H2_SH(hz_res2, hz_res0, hz_res3, hz_res1, tmp2, tmp3); + tmp0 = __msa_aver_s_h(tmp2, tmp0); + tmp1 = __msa_aver_s_h(tmp3, tmp1); + out = PCKEV_XORI128_UB(tmp0, tmp1); + out = __msa_aver_u_b(out, dst0); + ST_UB(out, dst); + dst += stride; + + src0 = src1; + src1 = src2; + src2 = src3; + src3 = src4; + src4 = src5; + src7 = src8; + src8 = src9; + src9 = src10; + src10 = src11; + src11 = src6; + } +} + +void ff_avg_h264_qpel8_mc12_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint32_t row; + uint64_t tp0, tp1; + v16u8 out, dst0 = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6; + v8i16 vt_res0, vt_res1, vt_res2, vt_res3, tmp0, tmp1, tmp2, tmp3; + v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5, shf_vec6; + v8i16 shf_vec7, shf_vec8, shf_vec9, shf_vec10, shf_vec11; + v8i16 mask3, mask4, mask5; + v4i32 hz_res0, hz_res1, hz_res2, hz_res3; + v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; + v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; + v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; + v8i16 minus5h = __msa_ldi_h(-5); + v8i16 plus20h = __msa_ldi_h(20); + + mask3 = mask0 + 4; + mask4 = mask1 + 4; + mask5 = mask2 + 4; + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + + for (row = 4; row--;) { + LD_SB2(src, stride, src5, src6); + src += (2 * stride); + XORI_B2_128_SB(src5, src6); + + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src0, src1, src2, src3, src4, src5, + vt_res0, vt_res1); + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src1, src2, src3, src4, src5, src6, + vt_res2, vt_res3); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec2); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec5); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask3, + mask4, mask5, shf_vec6, shf_vec7, shf_vec8); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask3, + mask4, mask5, shf_vec9, shf_vec10, shf_vec11); + hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); + hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); + hz_res2 = __msa_hadd_s_w(shf_vec6, shf_vec6); + hz_res3 = __msa_hadd_s_w(shf_vec9, shf_vec9); + DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); + DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); + DPADD_SH2_SW(shf_vec7, shf_vec8, minus5h, plus20h, hz_res2, hz_res2); + DPADD_SH2_SW(shf_vec10, shf_vec11, minus5h, plus20h, hz_res3, hz_res3); + SRARI_W4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 10); + SAT_SW4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 7); + tmp0 = __msa_srari_h(shf_vec2, 5); + tmp1 = __msa_srari_h(shf_vec5, 5); + tmp2 = __msa_srari_h(shf_vec8, 5); + tmp3 = __msa_srari_h(shf_vec11, 5); + LD2(dst, stride, tp0, tp1); + INSERT_D2_UB(tp0, tp1, dst0); + SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); + PCKEV_H2_SH(tmp2, tmp0, tmp3, tmp1, tmp0, tmp1); + PCKEV_H2_SH(hz_res2, hz_res0, hz_res3, hz_res1, tmp2, tmp3); + tmp0 = __msa_aver_s_h(tmp2, tmp0); + tmp1 = __msa_aver_s_h(tmp3, tmp1); + out = PCKEV_XORI128_UB(tmp0, tmp1); + out = __msa_aver_u_b(out, dst0); + ST8x2_UB(out, dst, stride); + dst += (2 * stride); + + src0 = src2; + src1 = src3; + src2 = src4; + src3 = src5; + src4 = src6; + } +} + +void ff_avg_h264_qpel8_mc32_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint32_t row; + uint64_t tp0, tp1; + v16u8 out, dst0 = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6; + v8i16 vt_res0, vt_res1, vt_res2, vt_res3, tmp0, tmp1, tmp2, tmp3; + v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5, shf_vec6; + v8i16 shf_vec7, shf_vec8, shf_vec9, shf_vec10, shf_vec11; + v8i16 mask3, mask4, mask5; + v4i32 hz_res0, hz_res1, hz_res2, hz_res3; + v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; + v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; + v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; + v8i16 minus5h = __msa_ldi_h(-5); + v8i16 plus20h = __msa_ldi_h(20); + + mask3 = mask0 + 4; + mask4 = mask1 + 4; + mask5 = mask2 + 4; + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + + for (row = 4; row--;) { + LD_SB2(src, stride, src5, src6); + src += (2 * stride); + XORI_B2_128_SB(src5, src6); + + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src0, src1, src2, src3, src4, src5, + vt_res0, vt_res1); + AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src1, src2, src3, src4, src5, src6, + vt_res2, vt_res3); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec2); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec5); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask3, + mask4, mask5, shf_vec6, shf_vec7, shf_vec8); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask3, + mask4, mask5, shf_vec9, shf_vec10, shf_vec11); + hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); + hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); + hz_res2 = __msa_hadd_s_w(shf_vec6, shf_vec6); + hz_res3 = __msa_hadd_s_w(shf_vec9, shf_vec9); + DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); + DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); + DPADD_SH2_SW(shf_vec7, shf_vec8, minus5h, plus20h, hz_res2, hz_res2); + DPADD_SH2_SW(shf_vec10, shf_vec11, minus5h, plus20h, hz_res3, hz_res3); + SRARI_W4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 10); + SAT_SW4_SW(hz_res0, hz_res1, hz_res2, hz_res3, 7); + tmp0 = __msa_srari_h(shf_vec2, 5); + tmp1 = __msa_srari_h(shf_vec5, 5); + tmp2 = __msa_srari_h(shf_vec8, 5); + tmp3 = __msa_srari_h(shf_vec11, 5); + LD2(dst, stride, tp0, tp1); + INSERT_D2_UB(tp0, tp1, dst0); + SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); + tmp0 = __msa_pckod_h(tmp2, tmp0); + tmp1 = __msa_pckod_h(tmp3, tmp1); + PCKEV_H2_SH(hz_res2, hz_res0, hz_res3, hz_res1, tmp2, tmp3); + tmp0 = __msa_aver_s_h(tmp2, tmp0); + tmp1 = __msa_aver_s_h(tmp3, tmp1); + out = PCKEV_XORI128_UB(tmp0, tmp1); + out = __msa_aver_u_b(out, dst0); + ST8x2_UB(out, dst, stride); + dst += (2 * stride); + + src0 = src2; + src1 = src3; + src2 = src4; + src3 = src5; + src4 = src6; + } +} + +void ff_avg_h264_qpel4_mc12_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint32_t tp0, tp1, tp2, tp3; + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + v16u8 out, dstv = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 src10_r, src21_r, src32_r, src43_r, src54_r, src65_r, src76_r; + v16i8 src87_r, src10_l, src21_l, src32_l, src43_l, src54_l, src65_l; + v16i8 src76_l, src87_l, filt0, filt1, filt2; + v8i16 vt_res0, vt_res1, vt_res2, vt_res3, dst0, dst1, dst2, dst3, shf_vec7; + v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5, shf_vec6; + v4i32 hz_res0, hz_res1, hz_res2, hz_res3; + v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; + v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; + v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; + v8i16 minus5h = __msa_ldi_h(-5); + v8i16 plus20h = __msa_ldi_h(20); + v8i16 zeros = { 0 }; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + LD_SB4(src, stride, src5, src6, src7, src8); + XORI_B4_128_SB(src5, src6, src7, src8); + + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_r, src65_r, + src76_r, src87_r); + ILVL_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_l, src21_l, + src32_l, src43_l); + ILVL_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_l, src65_l, + src76_l, src87_l); + vt_res0 = AVC_DOT_SH3_SH(src10_r, src32_r, src54_r, filt0, filt1, filt2); + vt_res1 = AVC_DOT_SH3_SH(src10_l, src32_l, src54_l, filt0, filt1, filt2); + vt_res2 = AVC_DOT_SH3_SH(src21_r, src43_r, src65_r, filt0, filt1, filt2); + vt_res3 = AVC_DOT_SH3_SH(src21_l, src43_l, src65_l, filt0, filt1, filt2); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec2); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec5); + hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); + DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); + hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); + DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); + + vt_res0 = AVC_DOT_SH3_SH(src32_r, src54_r, src76_r, filt0, filt1, filt2); + vt_res1 = AVC_DOT_SH3_SH(src32_l, src54_l, src76_l, filt0, filt1, filt2); + vt_res2 = AVC_DOT_SH3_SH(src43_r, src65_r, src87_r, filt0, filt1, filt2); + vt_res3 = AVC_DOT_SH3_SH(src43_l, src65_l, src87_l, filt0, filt1, filt2); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec6); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec7); + hz_res2 = __msa_hadd_s_w(shf_vec0, shf_vec0); + DPADD_SH2_SW(shf_vec1, shf_vec6, minus5h, plus20h, hz_res2, hz_res2); + hz_res3 = __msa_hadd_s_w(shf_vec3, shf_vec3); + DPADD_SH2_SW(shf_vec4, shf_vec7, minus5h, plus20h, hz_res3, hz_res3); + + SRARI_W2_SW(hz_res0, hz_res1, 10); + SAT_SW2_SW(hz_res0, hz_res1, 7); + SRARI_W2_SW(hz_res2, hz_res3, 10); + SAT_SW2_SW(hz_res2, hz_res3, 7); + + dst0 = __msa_srari_h(shf_vec2, 5); + dst1 = __msa_srari_h(shf_vec5, 5); + dst2 = __msa_srari_h(shf_vec6, 5); + dst3 = __msa_srari_h(shf_vec7, 5); + + SAT_SH2_SH(dst0, dst1, 7); + SAT_SH2_SH(dst2, dst3, 7); + ILVEV_H2_SH(dst0, zeros, dst1, zeros, dst0, dst1); + ILVEV_H2_SH(dst2, zeros, dst3, zeros, dst2, dst3); + + hz_res0 = __msa_aver_s_w(hz_res0, (v4i32) dst0); + hz_res1 = __msa_aver_s_w(hz_res1, (v4i32) dst1); + hz_res2 = __msa_aver_s_w(hz_res2, (v4i32) dst2); + hz_res3 = __msa_aver_s_w(hz_res3, (v4i32) dst3); + + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dstv); + PCKEV_H2_SH(hz_res1, hz_res0, hz_res3, hz_res2, dst0, dst2); + out = PCKEV_XORI128_UB(dst0, dst2); + out = __msa_aver_u_b(out, dstv); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, stride); +} + +void ff_avg_h264_qpel4_mc32_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint32_t tp0, tp1, tp2, tp3; + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + v16u8 out, dstv = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 src10_r, src21_r, src32_r, src43_r, src54_r, src65_r, src76_r; + v16i8 src87_r, src10_l, src21_l, src32_l, src43_l, src54_l, src65_l; + v16i8 src76_l, src87_l, filt0, filt1, filt2; + v8i16 vt_res0, vt_res1, vt_res2, vt_res3, dst0, dst1, dst2, dst3, shf_vec7; + v8i16 shf_vec0, shf_vec1, shf_vec2, shf_vec3, shf_vec4, shf_vec5, shf_vec6; + v4i32 hz_res0, hz_res1, hz_res2, hz_res3; + v8i16 mask0 = { 0, 5, 1, 6, 2, 7, 3, 8 }; + v8i16 mask1 = { 1, 4, 2, 5, 3, 6, 4, 7 }; + v8i16 mask2 = { 2, 3, 3, 4, 4, 5, 5, 6 }; + v8i16 minus5h = __msa_ldi_h(-5); + v8i16 plus20h = __msa_ldi_h(20); + v8i16 zeros = { 0 }; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + LD_SB4(src, stride, src5, src6, src7, src8); + XORI_B4_128_SB(src5, src6, src7, src8); + + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_r, src65_r, + src76_r, src87_r); + ILVL_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_l, src21_l, + src32_l, src43_l); + ILVL_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_l, src65_l, + src76_l, src87_l); + vt_res0 = AVC_DOT_SH3_SH(src10_r, src32_r, src54_r, filt0, filt1, filt2); + vt_res1 = AVC_DOT_SH3_SH(src10_l, src32_l, src54_l, filt0, filt1, filt2); + vt_res2 = AVC_DOT_SH3_SH(src21_r, src43_r, src65_r, filt0, filt1, filt2); + vt_res3 = AVC_DOT_SH3_SH(src21_l, src43_l, src65_l, filt0, filt1, filt2); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec2); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec5); + hz_res0 = __msa_hadd_s_w(shf_vec0, shf_vec0); + DPADD_SH2_SW(shf_vec1, shf_vec2, minus5h, plus20h, hz_res0, hz_res0); + hz_res1 = __msa_hadd_s_w(shf_vec3, shf_vec3); + DPADD_SH2_SW(shf_vec4, shf_vec5, minus5h, plus20h, hz_res1, hz_res1); + + vt_res0 = AVC_DOT_SH3_SH(src32_r, src54_r, src76_r, filt0, filt1, filt2); + vt_res1 = AVC_DOT_SH3_SH(src32_l, src54_l, src76_l, filt0, filt1, filt2); + vt_res2 = AVC_DOT_SH3_SH(src43_r, src65_r, src87_r, filt0, filt1, filt2); + vt_res3 = AVC_DOT_SH3_SH(src43_l, src65_l, src87_l, filt0, filt1, filt2); + VSHF_H3_SH(vt_res0, vt_res1, vt_res0, vt_res1, vt_res0, vt_res1, mask0, + mask1, mask2, shf_vec0, shf_vec1, shf_vec6); + VSHF_H3_SH(vt_res2, vt_res3, vt_res2, vt_res3, vt_res2, vt_res3, mask0, + mask1, mask2, shf_vec3, shf_vec4, shf_vec7); + hz_res2 = __msa_hadd_s_w(shf_vec0, shf_vec0); + DPADD_SH2_SW(shf_vec1, shf_vec6, minus5h, plus20h, hz_res2, hz_res2); + hz_res3 = __msa_hadd_s_w(shf_vec3, shf_vec3); + DPADD_SH2_SW(shf_vec4, shf_vec7, minus5h, plus20h, hz_res3, hz_res3); + + SRARI_W2_SW(hz_res0, hz_res1, 10); + SAT_SW2_SW(hz_res0, hz_res1, 7); + SRARI_W2_SW(hz_res2, hz_res3, 10); + SAT_SW2_SW(hz_res2, hz_res3, 7); + + dst0 = __msa_srari_h(shf_vec2, 5); + dst1 = __msa_srari_h(shf_vec5, 5); + dst2 = __msa_srari_h(shf_vec6, 5); + dst3 = __msa_srari_h(shf_vec7, 5); + + SAT_SH2_SH(dst0, dst1, 7); + SAT_SH2_SH(dst2, dst3, 7); + + dst0 = __msa_ilvod_h(zeros, dst0); + dst1 = __msa_ilvod_h(zeros, dst1); + dst2 = __msa_ilvod_h(zeros, dst2); + dst3 = __msa_ilvod_h(zeros, dst3); + + hz_res0 = __msa_aver_s_w(hz_res0, (v4i32) dst0); + hz_res1 = __msa_aver_s_w(hz_res1, (v4i32) dst1); + hz_res2 = __msa_aver_s_w(hz_res2, (v4i32) dst2); + hz_res3 = __msa_aver_s_w(hz_res3, (v4i32) dst3); + + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dstv); + PCKEV_H2_SH(hz_res1, hz_res0, hz_res3, hz_res2, dst0, dst2); + out = PCKEV_XORI128_UB(dst0, dst2); + out = __msa_aver_u_b(out, dstv); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, stride); } void ff_avg_h264_qpel16_mc22_msa(uint8_t *dst, const uint8_t *src, From 48d77d5cd4ac0858e1e9abf387f739a5c773200f Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Tue, 31 Oct 2017 18:30:40 +0530 Subject: [PATCH 0726/2557] avcodec/mips: Improve hevc uni weighted hv mc msa functions Use immediate unsigned saturation for clip to max saving one vector register. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_macros_msa.h | 9 + libavcodec/mips/hevc_mc_uniw_msa.c | 1598 +++++++++++++++++----------- 2 files changed, 965 insertions(+), 642 deletions(-) diff --git a/libavcodec/mips/hevc_macros_msa.h b/libavcodec/mips/hevc_macros_msa.h index 7dcfea03b41c9..27c69ff89a2f4 100644 --- a/libavcodec/mips/hevc_macros_msa.h +++ b/libavcodec/mips/hevc_macros_msa.h @@ -80,6 +80,15 @@ out_m; \ } ) +#define HEVC_FILT_4TAP_SH(in0, in1, filt0, filt1) \ +( { \ + v8i16 out_m; \ + \ + out_m = __msa_dotp_s_h((v16i8) in0, (v16i8) filt0); \ + out_m = __msa_dpadd_s_h(out_m, (v16i8) in1, (v16i8) filt1); \ + out_m; \ +} ) + #define HEVC_FILT_4TAP(in0, in1, filt0, filt1) \ ( { \ v4i32 out_m; \ diff --git a/libavcodec/mips/hevc_mc_uniw_msa.c b/libavcodec/mips/hevc_mc_uniw_msa.c index 28c7062fba341..0796b0aa7c2b3 100644 --- a/libavcodec/mips/hevc_mc_uniw_msa.c +++ b/libavcodec/mips/hevc_mc_uniw_msa.c @@ -1801,40 +1801,42 @@ static void hevc_hv_uniwgt_8t_4w_msa(uint8_t *src, int32_t rnd_val) { uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16u8 out; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v8i16 filt0, filt1, filt2, filt3; - v4i32 filt_h0, filt_h1, filt_h2, filt_h3; + v8i16 filt_h0, filt_h1, filt_h2, filt_h3; v16i8 mask1, mask2, mask3; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; - v8i16 dst30, dst41, dst52, dst63, dst66, dst87; - v4i32 dst0_r, dst1_r, weight_vec, offset_vec, rnd_vec; - v8i16 dst10_r, dst32_r, dst54_r, dst76_r; - v8i16 dst21_r, dst43_r, dst65_r, dst87_r; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; - v8u16 mask4 = { 0, 4, 1, 5, 2, 6, 3, 7 }; + v8i16 dst30, dst41, dst52, dst63, dst66, dst97, dst108; + v8i16 dst10_r, dst32_r, dst54_r, dst76_r, dst98_r; + v8i16 dst21_r, dst43_r, dst65_r, dst87_r, dst109_r; + v4i32 dst0_r, dst1_r, dst2_r, dst3_r; + v4i32 weight_vec, offset_vec, rnd_vec, const_128, denom_vec; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); src -= ((3 * src_stride) + 3); filter_vec = LD_SH(filter_x); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W4_SW(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); mask1 = mask0 + 2; mask2 = mask0 + 4; mask3 = mask0 + 6; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight_vec = __msa_fill_w(weight); offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + denom_vec = rnd_vec - 6; + + const_128 = __msa_ldi_w(128); + const_128 *= weight_vec; + offset_vec += __msa_srar_w(const_128, denom_vec); LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); src += (7 * src_stride); @@ -1847,64 +1849,68 @@ static void hevc_hv_uniwgt_8t_4w_msa(uint8_t *src, vec8, vec9, vec10, vec11); VSHF_B4_SB(src3, src6, mask0, mask1, mask2, mask3, vec12, vec13, vec14, vec15); - dst30 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst30, dst30, dst30, dst30); - dst41 = const_vec; - DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, - dst41, dst41, dst41, dst41); - dst52 = const_vec; - DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, - dst52, dst52, dst52, dst52); - dst63 = const_vec; - DPADD_SB4_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, filt3, - dst63, dst63, dst63, dst63); - - ILVR_H3_SH(dst41, dst30, dst52, dst41, dst63, dst52, - dst10_r, dst21_r, dst32_r); - - dst43_r = __msa_ilvl_h(dst41, dst30); - dst54_r = __msa_ilvl_h(dst52, dst41); - dst65_r = __msa_ilvl_h(dst63, dst52); + dst30 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst41 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst52 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst63 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, + filt3); + + ILVRL_H2_SH(dst41, dst30, dst10_r, dst43_r); + ILVRL_H2_SH(dst52, dst41, dst21_r, dst54_r); + ILVRL_H2_SH(dst63, dst52, dst32_r, dst65_r); dst66 = (v8i16) __msa_splati_d((v2i64) dst63, 1); - for (loop_cnt = height >> 1; loop_cnt--;) { - LD_SB2(src, src_stride, src7, src8); - src += (2 * src_stride); - XORI_B2_128_SB(src7, src8); + for (loop_cnt = height >> 2; loop_cnt--;) { + LD_SB4(src, src_stride, src7, src8, src9, src10); + src += (4 * src_stride); + XORI_B4_128_SB(src7, src8, src9, src10); - VSHF_B4_SB(src7, src8, mask0, mask1, mask2, mask3, + VSHF_B4_SB(src7, src9, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst87 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst87, dst87, dst87, dst87); - dst76_r = __msa_ilvr_h(dst87, dst66); - dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, - filt_h0, filt_h1, filt_h2, filt_h3); - dst87_r = __msa_vshf_h((v8i16) mask4, dst87, dst87); - dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, - filt_h0, filt_h1, filt_h2, filt_h3); - - dst0_r >>= 6; - dst1_r >>= 6; + VSHF_B4_SB(src8, src10, mask0, mask1, mask2, mask3, + vec4, vec5, vec6, vec7); + dst97 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst108 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + + dst76_r = __msa_ilvr_h(dst97, dst66); + ILVRL_H2_SH(dst108, dst97, dst87_r, dst109_r); + dst66 = (v8i16) __msa_splati_d((v2i64) dst97, 1); + dst98_r = __msa_ilvr_h(dst66, dst108); + + dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst2_r = HEVC_FILT_8TAP(dst32_r, dst54_r, dst76_r, dst98_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst3_r = HEVC_FILT_8TAP(dst43_r, dst65_r, dst87_r, dst109_r, filt_h0, + filt_h1, filt_h2, filt_h3); + + SRA_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); MUL2(dst0_r, weight_vec, dst1_r, weight_vec, dst0_r, dst1_r); - SRAR_W2_SW(dst0_r, dst1_r, rnd_vec); + MUL2(dst2_r, weight_vec, dst3_r, weight_vec, dst2_r, dst3_r); + SRAR_W4_SW(dst0_r, dst1_r, dst2_r, dst3_r, rnd_vec); ADD2(dst0_r, offset_vec, dst1_r, offset_vec, dst0_r, dst1_r); - dst0_r = CLIP_SW_0_255(dst0_r); - dst1_r = CLIP_SW_0_255(dst1_r); - - HEVC_PCK_SW_SB2(dst1_r, dst0_r, dst0_r); - ST4x2_UB(dst0_r, dst, dst_stride); - dst += (2 * dst_stride); + ADD2(dst2_r, offset_vec, dst3_r, offset_vec, dst2_r, dst3_r); + CLIP_SW4_0_255_MAX_SATU(dst0_r, dst1_r, dst2_r, dst3_r); + PCKEV_H2_SW(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r, dst1_r); + out = (v16u8) __msa_pckev_b((v16i8) dst1_r, (v16i8) dst0_r); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); + dst += (4 * dst_stride); - dst10_r = dst32_r; - dst32_r = dst54_r; - dst54_r = dst76_r; - dst21_r = dst43_r; - dst43_r = dst65_r; - dst65_r = dst87_r; - dst66 = (v8i16) __msa_splati_d((v2i64) dst87, 1); + dst10_r = dst54_r; + dst32_r = dst76_r; + dst54_r = dst98_r; + dst21_r = dst65_r; + dst43_r = dst87_r; + dst65_r = dst109_r; + dst66 = (v8i16) __msa_splati_d((v2i64) dst108, 1); } } @@ -1927,7 +1933,7 @@ static void hevc_hv_uniwgt_8t_8multx2mult_msa(uint8_t *src, v8i16 filt0, filt1, filt2, filt3; v4i32 filt_h0, filt_h1, filt_h2, filt_h3; v16i8 mask1, mask2, mask3; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; @@ -1936,23 +1942,25 @@ static void hevc_hv_uniwgt_8t_8multx2mult_msa(uint8_t *src, v8i16 dst10_l, dst32_l, dst54_l, dst76_l; v8i16 dst21_r, dst43_r, dst65_r, dst87_r; v8i16 dst21_l, dst43_l, dst65_l, dst87_l; - v4i32 weight_vec, offset_vec, rnd_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v4i32 weight_vec, offset_vec, rnd_vec, const_128, denom_vec; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); src -= ((3 * src_stride) + 3); - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight_vec = __msa_fill_w(weight); offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + denom_vec = rnd_vec - 6; + + const_128 = __msa_ldi_w(128); + const_128 *= weight_vec; + offset_vec += __msa_srar_w(const_128, denom_vec); filter_vec = LD_SH(filter_x); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); SPLATI_W4_SW(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); mask1 = mask0 + 2; @@ -1975,18 +1983,14 @@ static void hevc_hv_uniwgt_8t_8multx2mult_msa(uint8_t *src, vec8, vec9, vec10, vec11); VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, vec12, vec13, vec14, vec15); - dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - dst1 = const_vec; - DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - dst2 = const_vec; - DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - dst3 = const_vec; - DPADD_SB4_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst1 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst2 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst3 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, + filt2, filt3); VSHF_B4_SB(src4, src4, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); @@ -1994,15 +1998,12 @@ static void hevc_hv_uniwgt_8t_8multx2mult_msa(uint8_t *src, vec4, vec5, vec6, vec7); VSHF_B4_SB(src6, src6, mask0, mask1, mask2, mask3, vec8, vec9, vec10, vec11); - dst4 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst4, dst4, dst4, dst4); - dst5 = const_vec; - DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, - dst5, dst5, dst5, dst5); - dst6 = const_vec; - DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, - dst6, dst6, dst6, dst6); + dst4 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst5 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst6 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); ILVR_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, dst10_r, dst32_r, dst54_r, dst21_r); @@ -2018,9 +2019,8 @@ static void hevc_hv_uniwgt_8t_8multx2mult_msa(uint8_t *src, VSHF_B4_SB(src7, src7, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst7 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst7, dst7, dst7, dst7); + dst7 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, + filt2, filt3); ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, @@ -2033,9 +2033,8 @@ static void hevc_hv_uniwgt_8t_8multx2mult_msa(uint8_t *src, /* row 8 */ VSHF_B4_SB(src8, src8, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst8 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst8, dst8, dst8, dst8); + dst8 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, + filt2, filt3); ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, @@ -2045,11 +2044,15 @@ static void hevc_hv_uniwgt_8t_8multx2mult_msa(uint8_t *src, dst1_r >>= 6; dst1_l >>= 6; - HEVC_HV_UNIW_RND_CLIP4(dst0_r, dst1_r, dst0_l, dst1_l, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + MUL2(dst0_r, weight_vec, dst0_l, weight_vec, dst0_r, dst0_l); + MUL2(dst1_r, weight_vec, dst1_l, weight_vec, dst1_r, dst1_l); + SRAR_W4_SW(dst0_r, dst1_r, dst0_l, dst1_l, rnd_vec); + ADD2(dst0_r, offset_vec, dst0_l, offset_vec, dst0_r, dst0_l); + ADD2(dst1_r, offset_vec, dst1_l, offset_vec, dst1_r, dst1_l); + CLIP_SW4_0_255_MAX_SATU(dst0_r, dst1_r, dst0_l, dst1_l); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); + PCKEV_H2_SW(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r, dst1_r); + dst0_r = (v4i32) __msa_pckev_b((v16i8) dst1_r, (v16i8) dst0_r); ST8x2_UB(dst0_r, dst_tmp, dst_stride); dst_tmp += (2 * dst_stride); @@ -2100,12 +2103,198 @@ static void hevc_hv_uniwgt_8t_12w_msa(uint8_t *src, int32_t offset, int32_t rnd_val) { - hevc_hv_uniwgt_8t_8multx2mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, weight, - offset, rnd_val, 8); - hevc_hv_uniwgt_8t_4w_msa(src + 8, src_stride, dst + 8, dst_stride, - filter_x, filter_y, height, weight, offset, - rnd_val); + uint32_t loop_cnt; + uint8_t *src_tmp, *dst_tmp; + v16u8 out; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask7; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 dst30, dst41, dst52, dst63, dst66, dst97, dst108; + v8i16 filt0, filt1, filt2, filt3, filt_h0, filt_h1, filt_h2, filt_h3; + v8i16 dst10_r, dst32_r, dst54_r, dst76_r, dst10_l, dst32_l, dst54_l; + v8i16 dst98_r, dst21_r, dst43_r, dst65_r, dst87_r, dst109_r; + v8i16 dst76_l, filter_vec; + v4i32 dst0_r, dst0_l, dst1_r, dst2_r, dst3_r; + v4i32 weight_vec, offset_vec, rnd_vec, const_128, denom_vec; + + src -= ((3 * src_stride) + 3); + + filter_vec = LD_SH(filter_x); + SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + + weight_vec = __msa_fill_w(weight); + offset_vec = __msa_fill_w(offset); + rnd_vec = __msa_fill_w(rnd_val); + denom_vec = rnd_vec - 6; + + const_128 = __msa_ldi_w(128); + const_128 *= weight_vec; + offset_vec += __msa_srar_w(const_128, denom_vec); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + mask2 = mask0 + 4; + mask3 = mask0 + 6; + + src_tmp = src; + dst_tmp = dst; + + LD_SB7(src_tmp, src_stride, src0, src1, src2, src3, src4, src5, src6); + src_tmp += (7 * src_stride); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + /* row 0 row 1 row 2 row 3 */ + VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); + VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, vec4, vec5, vec6, vec7); + VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, vec8, vec9, vec10, + vec11); + VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, vec12, vec13, vec14, + vec15); + dst0 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst1 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst2 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst3 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, + filt2, filt3); + VSHF_B4_SB(src4, src4, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); + VSHF_B4_SB(src5, src5, mask0, mask1, mask2, mask3, vec4, vec5, vec6, vec7); + VSHF_B4_SB(src6, src6, mask0, mask1, mask2, mask3, vec8, vec9, vec10, + vec11); + dst4 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst5 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst6 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + + for (loop_cnt = 16; loop_cnt--;) { + src7 = LD_SB(src_tmp); + src7 = (v16i8) __msa_xori_b((v16u8) src7, 128); + src_tmp += src_stride; + + VSHF_B4_SB(src7, src7, mask0, mask1, mask2, mask3, vec0, vec1, vec2, + vec3); + dst7 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); + ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); + + dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, + filt_h0, filt_h1, filt_h2, filt_h3); + dst0_l = HEVC_FILT_8TAP(dst10_l, dst32_l, dst54_l, dst76_l, + filt_h0, filt_h1, filt_h2, filt_h3); + dst0_r >>= 6; + dst0_l >>= 6; + + MUL2(dst0_r, weight_vec, dst0_l, weight_vec, dst0_r, dst0_l); + SRAR_W2_SW(dst0_r, dst0_l, rnd_vec); + ADD2(dst0_r, offset_vec, dst0_l, offset_vec, dst0_r, dst0_l); + CLIP_SW2_0_255_MAX_SATU(dst0_r, dst0_l); + dst0_r = (v4i32) __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); + out = (v16u8) __msa_pckev_b((v16i8) dst0_r, (v16i8) dst0_r); + ST8x1_UB(out, dst_tmp); + dst_tmp += dst_stride; + + dst0 = dst1; + dst1 = dst2; + dst2 = dst3; + dst3 = dst4; + dst4 = dst5; + dst5 = dst6; + dst6 = dst7; + } + + src += 8; + dst += 8; + + mask4 = LD_SB(ff_hevc_mask_arr + 16); + mask5 = mask4 + 2; + mask6 = mask4 + 4; + mask7 = mask4 + 6; + + LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); + src += (7 * src_stride); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + VSHF_B4_SB(src0, src3, mask4, mask5, mask6, mask7, vec0, vec1, vec2, vec3); + VSHF_B4_SB(src1, src4, mask4, mask5, mask6, mask7, vec4, vec5, vec6, vec7); + VSHF_B4_SB(src2, src5, mask4, mask5, mask6, mask7, vec8, vec9, vec10, + vec11); + VSHF_B4_SB(src3, src6, mask4, mask5, mask6, mask7, vec12, vec13, vec14, + vec15); + dst30 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst41 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + dst52 = HEVC_FILT_8TAP_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, + filt3); + dst63 = HEVC_FILT_8TAP_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, + filt3); + ILVRL_H2_SH(dst41, dst30, dst10_r, dst43_r); + ILVRL_H2_SH(dst52, dst41, dst21_r, dst54_r); + ILVRL_H2_SH(dst63, dst52, dst32_r, dst65_r); + + dst66 = (v8i16) __msa_splati_d((v2i64) dst63, 1); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src, src_stride, src7, src8, src9, src10); + src += (4 * src_stride); + XORI_B4_128_SB(src7, src8, src9, src10); + + VSHF_B4_SB(src7, src9, mask4, mask5, mask6, mask7, vec0, vec1, vec2, + vec3); + VSHF_B4_SB(src8, src10, mask4, mask5, mask6, mask7, vec4, vec5, vec6, + vec7); + dst97 = HEVC_FILT_8TAP_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, + filt3); + dst108 = HEVC_FILT_8TAP_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, + filt3); + + dst76_r = __msa_ilvr_h(dst97, dst66); + ILVRL_H2_SH(dst108, dst97, dst87_r, dst109_r); + dst66 = (v8i16) __msa_splati_d((v2i64) dst97, 1); + dst98_r = __msa_ilvr_h(dst66, dst108); + + dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst2_r = HEVC_FILT_8TAP(dst32_r, dst54_r, dst76_r, dst98_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst3_r = HEVC_FILT_8TAP(dst43_r, dst65_r, dst87_r, dst109_r, filt_h0, + filt_h1, filt_h2, filt_h3); + + SRA_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); + MUL2(dst0_r, weight_vec, dst1_r, weight_vec, dst0_r, dst1_r); + MUL2(dst2_r, weight_vec, dst3_r, weight_vec, dst2_r, dst3_r); + SRAR_W4_SW(dst0_r, dst1_r, dst2_r, dst3_r, rnd_vec); + ADD2(dst0_r, offset_vec, dst1_r, offset_vec, dst0_r, dst1_r); + ADD2(dst2_r, offset_vec, dst3_r, offset_vec, dst2_r, dst3_r); + CLIP_SW4_0_255_MAX_SATU(dst0_r, dst1_r, dst2_r, dst3_r); + PCKEV_H2_SW(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r, dst1_r); + out = (v16u8) __msa_pckev_b((v16i8) dst1_r, (v16i8) dst0_r); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); + dst += (4 * dst_stride); + + dst10_r = dst54_r; + dst32_r = dst76_r; + dst54_r = dst98_r; + dst21_r = dst65_r; + dst43_r = dst87_r; + dst65_r = dst109_r; + dst66 = (v8i16) __msa_splati_d((v2i64) dst108, 1); + } } static void hevc_hv_uniwgt_8t_16w_msa(uint8_t *src, @@ -3977,22 +4166,20 @@ static void hevc_hv_uniwgt_4t_4x2_msa(uint8_t *src, int32_t dst_stride, const int8_t *filter_x, const int8_t *filter_y, - int32_t height, int32_t weight, int32_t offset, int32_t rnd_val) { + v16u8 out; v16i8 src0, src1, src2, src3, src4; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; - v8i16 filter_vec, const_vec; + v8i16 filt_h0, filt_h1, filter_vec, tmp; v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; - v4i32 dst0_r, dst1_r; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 dst20, dst31, dst42, dst10, dst32, dst21, dst43; + v8i16 offset_vec, const_128, denom_vec; + v4i32 dst0, dst1, weight_vec, rnd_vec; src -= (src_stride + 1); @@ -4000,63 +4187,41 @@ static void hevc_hv_uniwgt_4t_4x2_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); - - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); - LD_SB2(src, src_stride, src3, src4); - XORI_B2_128_SB(src3, src4); - - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - dst32_r = __msa_ilvr_h(dst3, dst2); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; - - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - dst43_r = __msa_ilvr_h(dst4, dst3); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - - MUL2(dst0_r, weight_vec, dst1_r, weight_vec, dst0_r, dst1_r); - SRAR_W2_SW(dst0_r, dst1_r, rnd_vec); - ADD2(dst0_r, offset_vec, dst1_r, offset_vec, dst0_r, dst1_r); - dst0_r = CLIP_SW_0_255(dst0_r); - dst1_r = CLIP_SW_0_255(dst1_r); - - HEVC_PCK_SW_SB2(dst1_r, dst0_r, dst0_r); - ST4x2_UB(dst0_r, dst, dst_stride); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val - 6); + const_128 = __msa_fill_h((128 * weight)); + offset_vec += __msa_srar_h(const_128, denom_vec); + + LD_SB5(src, src_stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + VSHF_B2_SB(src0, src2, src0, src2, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src3, src1, src3, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src4, src2, src4, mask0, mask1, vec4, vec5); + dst20 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst31 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst42 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + ILVRL_H2_SH(dst31, dst20, dst10, dst32); + ILVRL_H2_SH(dst42, dst31, dst21, dst43); + dst0 = HEVC_FILT_4TAP(dst10, dst32, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21, dst43, filt_h0, filt_h1); + dst0 >>= 6; + dst1 >>= 6; + MUL2(dst0, weight_vec, dst1, weight_vec, dst0, dst1); + SRAR_W2_SW(dst0, dst1, rnd_vec); + tmp = __msa_pckev_h((v8i16) dst1, (v8i16) dst0); + tmp += offset_vec; + tmp = CLIP_SH_0_255_MAX_SATU(tmp); + out = (v16u8) __msa_pckev_b((v16i8) tmp, (v16i8) tmp); + ST4x2_UB(out, dst, dst_stride); } static void hevc_hv_uniwgt_4t_4x4_msa(uint8_t *src, @@ -4065,22 +4230,20 @@ static void hevc_hv_uniwgt_4t_4x4_msa(uint8_t *src, int32_t dst_stride, const int8_t *filter_x, const int8_t *filter_y, - int32_t height, int32_t weight, int32_t offset, int32_t rnd_val) { + v16u8 out; v16i8 src0, src1, src2, src3, src4, src5, src6; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1, filter_vec, tmp0, tmp1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; - v4i32 weight_vec, offset_vec, rnd_vec; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 dst30, dst41, dst52, dst63, dst10, dst32, dst54, dst21, dst43, dst65; + v8i16 offset_vec, const_128, denom_vec; + v4i32 dst0, dst1, dst2, dst3, weight_vec, rnd_vec; src -= (src_stride + 1); @@ -4088,76 +4251,46 @@ static void hevc_hv_uniwgt_4t_4x4_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); - - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); - - LD_SB4(src, src_stride, src3, src4, src5, src6); - XORI_B4_128_SB(src3, src4, src5, src6); - - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - dst32_r = __msa_ilvr_h(dst3, dst2); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; - - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - dst43_r = __msa_ilvr_h(dst4, dst3); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - dst10_r = __msa_ilvr_h(dst5, dst4); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_r >>= 6; + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val - 6); + const_128 = __msa_fill_h((128 * weight)); + offset_vec += __msa_srar_h(const_128, denom_vec); - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - dst21_r = __msa_ilvr_h(dst2, dst5); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_r >>= 6; - - HEVC_HV_UNIW_RND_CLIP4(dst0_r, dst1_r, dst2_r, dst3_r, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r); - HEVC_PCK_SW_SB4(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r); - ST4x4_UB(dst0_r, dst0_r, 0, 1, 2, 3, dst, dst_stride); + LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + VSHF_B2_SB(src0, src3, src0, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src4, src1, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src5, src2, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src3, src6, src3, src6, mask0, mask1, vec6, vec7); + dst30 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst41 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst52 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst63 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + ILVRL_H2_SH(dst41, dst30, dst10, dst43); + ILVRL_H2_SH(dst52, dst41, dst21, dst54); + ILVRL_H2_SH(dst63, dst52, dst32, dst65); + dst0 = HEVC_FILT_4TAP(dst10, dst32, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21, dst43, filt_h0, filt_h1); + dst2 = HEVC_FILT_4TAP(dst32, dst54, filt_h0, filt_h1); + dst3 = HEVC_FILT_4TAP(dst43, dst65, filt_h0, filt_h1); + SRA_4V(dst0, dst1, dst2, dst3, 6); + MUL2(dst0, weight_vec, dst1, weight_vec, dst0, dst1); + MUL2(dst2, weight_vec, dst3, weight_vec, dst2, dst3); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp0, tmp1); + ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); + CLIP_SH2_0_255_MAX_SATU(tmp0, tmp1); + out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); } static void hevc_hv_uniwgt_4t_4multx8mult_msa(uint8_t *src, @@ -4172,18 +4305,18 @@ static void hevc_hv_uniwgt_4t_4multx8mult_msa(uint8_t *src, int32_t rnd_val) { uint32_t loop_cnt; + v16u8 out0, out1; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8, dst9; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r, dst6_r, dst7_r; + v8i16 filt_h0, filt_h1, filter_vec, tmp0, tmp1, tmp2, tmp3; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 dst10, dst21, dst22, dst73, dst84, dst95, dst106; v8i16 dst10_r, dst32_r, dst54_r, dst76_r; v8i16 dst21_r, dst43_r, dst65_r, dst87_r; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 dst98_r, dst109_r, offset_vec, const_128, denom_vec; + v4i32 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, weight_vec, rnd_vec; src -= (src_stride + 1); @@ -4191,34 +4324,30 @@ static void hevc_hv_uniwgt_4t_4multx8mult_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val - 6); + const_128 = __msa_fill_h((128 * weight)); + offset_vec += __msa_srar_h(const_128, denom_vec); + LD_SB3(src, src_stride, src0, src1, src2); src += (3 * src_stride); XORI_B3_128_SB(src0, src1, src2); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); + VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src2, src1, src2, mask0, mask1, vec2, vec3); + dst10 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst21 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + ILVRL_H2_SH(dst21, dst10, dst10_r, dst21_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst21, 1); for (loop_cnt = height >> 3; loop_cnt--;) { LD_SB8(src, src_stride, @@ -4226,77 +4355,50 @@ static void hevc_hv_uniwgt_4t_4multx8mult_msa(uint8_t *src, src += (8 * src_stride); XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - dst32_r = __msa_ilvr_h(dst3, dst2); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; + VSHF_B2_SB(src3, src7, src3, src7, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src8, src4, src8, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src9, src5, src9, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src10, src6, src10, mask0, mask1, vec6, vec7); + dst73 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst84 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst95 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst106 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + dst32_r = __msa_ilvr_h(dst73, dst22); + ILVRL_H2_SH(dst84, dst73, dst43_r, dst87_r); + ILVRL_H2_SH(dst95, dst84, dst54_r, dst98_r); + ILVRL_H2_SH(dst106, dst95, dst65_r, dst109_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst73, 1); + dst76_r = __msa_ilvr_h(dst22, dst106); + dst0 = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst2 = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst3 = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst4 = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); + dst5 = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); + dst6 = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7 = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + SRA_4V(dst0, dst1, dst2, dst3, 6); + SRA_4V(dst4, dst5, dst6, dst7, 6); + MUL2(dst0, weight_vec, dst1, weight_vec, dst0, dst1); + MUL2(dst2, weight_vec, dst3, weight_vec, dst2, dst3); + MUL2(dst4, weight_vec, dst5, weight_vec, dst4, dst5); + MUL2(dst6, weight_vec, dst7, weight_vec, dst6, dst7); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); + PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, tmp0, tmp1, + tmp2, tmp3); + ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); + ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST4x8_UB(out0, out1, dst, dst_stride); + dst += (8 * dst_stride); - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - dst43_r = __msa_ilvr_h(dst4, dst3); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - dst54_r = __msa_ilvr_h(dst5, dst4); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); - dst2_r >>= 6; - - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); - dst65_r = __msa_ilvr_h(dst6, dst5); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); - dst3_r >>= 6; - - VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); - dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); - dst76_r = __msa_ilvr_h(dst7, dst6); - dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); - dst4_r >>= 6; - - VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec0, vec1); - dst8 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst8, dst8); - dst87_r = __msa_ilvr_h(dst8, dst7); - dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); - dst5_r >>= 6; - - VSHF_B2_SB(src9, src9, src9, src9, mask0, mask1, vec0, vec1); - dst9 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst9, dst9); - dst10_r = __msa_ilvr_h(dst9, dst8); - dst6_r = HEVC_FILT_4TAP(dst76_r, dst10_r, filt_h0, filt_h1); - dst6_r >>= 6; - - VSHF_B2_SB(src10, src10, src10, src10, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - dst21_r = __msa_ilvr_h(dst2, dst9); - dst7_r = HEVC_FILT_4TAP(dst87_r, dst21_r, filt_h0, filt_h1); - dst7_r >>= 6; - - HEVC_HV_UNIW_RND_CLIP4(dst0_r, dst1_r, dst2_r, dst3_r, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r); - HEVC_PCK_SW_SB4(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r); - ST4x4_UB(dst0_r, dst0_r, 0, 1, 2, 3, dst, dst_stride); - dst += (4 * dst_stride); - - HEVC_HV_UNIW_RND_CLIP4(dst4_r, dst5_r, dst6_r, dst7_r, - weight_vec, offset_vec, rnd_vec, - dst4_r, dst5_r, dst6_r, dst7_r); - HEVC_PCK_SW_SB4(dst5_r, dst4_r, dst7_r, dst6_r, dst0_r); - ST4x4_UB(dst0_r, dst0_r, 0, 1, 2, 3, dst, dst_stride); - dst += (4 * dst_stride); - } -} + dst10_r = dst98_r; + dst21_r = dst109_r; + dst22 = (v8i16) __msa_splati_d((v2i64) dst106, 1); + } +} static void hevc_hv_uniwgt_4t_4w_msa(uint8_t *src, int32_t src_stride, @@ -4311,11 +4413,11 @@ static void hevc_hv_uniwgt_4t_4w_msa(uint8_t *src, { if (2 == height) { hevc_hv_uniwgt_4t_4x2_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, weight, + filter_x, filter_y, weight, offset, rnd_val); } else if (4 == height) { hevc_hv_uniwgt_4t_4x4_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, weight, + filter_x,filter_y, weight, offset, rnd_val); } else if (0 == (height % 8)) { hevc_hv_uniwgt_4t_4multx8mult_msa(src, src_stride, dst, dst_stride, @@ -4335,20 +4437,22 @@ static void hevc_hv_uniwgt_4t_6w_msa(uint8_t *src, int32_t offset, int32_t rnd_val) { - uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5, src6; + v16u8 out0, out1, out2; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v4i32 dst0_r, dst0_l, dst1_r, dst1_l; - v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst2_r, dst2_l, dst3_r, dst3_l; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; - v8i16 dst10_l, dst32_l, dst21_l, dst43_l; + v8i16 filt_h0, filt_h1, filter_vec; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6, dsth7, dsth8, dsth9; + v8i16 dsth10, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + v8i16 dst10_r, dst32_r, dst54_r, dst76_r, dst98_r, dst21_r, dst43_r; + v8i16 dst65_r, dst87_r, dst109_r, dst10_l, dst32_l, dst54_l, dst76_l; + v8i16 dst98_l, dst21_l, dst43_l, dst65_l, dst87_l, dst109_l; + v8i16 dst1021_l, dst3243_l, dst5465_l, dst7687_l, dst98109_l; + v8i16 offset_vec, const_128, denom_vec; + v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r, dst6_r, dst7_r; + v4i32 dst0_l, dst1_l, dst2_l, dst3_l, weight_vec, rnd_vec; src -= (src_stride + 1); @@ -4356,20 +4460,20 @@ static void hevc_hv_uniwgt_4t_6w_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val - 6); + const_128 = __msa_fill_h((128 * weight)); + offset_vec += __msa_srar_h(const_128, denom_vec); + LD_SB3(src, src_stride, src0, src1, src2); src += (3 * src_stride); XORI_B3_128_SB(src0, src1, src2); @@ -4377,72 +4481,78 @@ static void hevc_hv_uniwgt_4t_6w_msa(uint8_t *src, VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - - ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); - ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); - - for (loop_cnt = height >> 2; loop_cnt--;) { - LD_SB4(src, src_stride, src3, src4, src5, src6); - src += (4 * src_stride); - XORI_B4_128_SB(src3, src4, src5, src6); - - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - ILVRL_H2_SH(dst5, dst4, dst10_r, dst10_l); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_l = HEVC_FILT_4TAP(dst32_l, dst10_l, filt_h0, filt_h1); - dst2_r >>= 6; - dst2_l >>= 6; - - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - ILVRL_H2_SH(dst2, dst5, dst21_r, dst21_l); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_l = HEVC_FILT_4TAP(dst43_l, dst21_l, filt_h0, filt_h1); - dst3_r >>= 6; - dst3_l >>= 6; - - HEVC_HV_UNIW_RND_CLIP4(dst0_r, dst1_r, dst0_l, dst1_l, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst0_l, dst1_l); - HEVC_HV_UNIW_RND_CLIP4(dst2_r, dst3_r, dst2_l, dst3_l, - weight_vec, offset_vec, rnd_vec, - dst2_r, dst3_r, dst2_l, dst3_l); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST6x4_UB(dst0_r, dst1_r, dst, dst_stride); - dst += (4 * dst_stride); - } + dsth0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + ILVRL_H2_SH(dsth1, dsth0, dst10_r, dst10_l); + ILVRL_H2_SH(dsth2, dsth1, dst21_r, dst21_l); + + LD_SB8(src, src_stride, src3, src4, src5, src6, src7, src8, src9, src10); + XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + dsth3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src9, src9, src9, src9, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src10, src10, src10, src10, mask0, mask1, vec6, vec7); + dsth7 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth8 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth9 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth10 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + ILVRL_H2_SH(dsth3, dsth2, dst32_r, dst32_l); + ILVRL_H2_SH(dsth4, dsth3, dst43_r, dst43_l); + ILVRL_H2_SH(dsth5, dsth4, dst54_r, dst54_l); + ILVRL_H2_SH(dsth6, dsth5, dst65_r, dst65_l); + ILVRL_H2_SH(dsth7, dsth6, dst76_r, dst76_l); + ILVRL_H2_SH(dsth8, dsth7, dst87_r, dst87_l); + ILVRL_H2_SH(dsth9, dsth8, dst98_r, dst98_l); + ILVRL_H2_SH(dsth10, dsth9, dst109_r, dst109_l); + PCKEV_D2_SH(dst21_l, dst10_l, dst43_l, dst32_l, dst1021_l, dst3243_l); + PCKEV_D2_SH(dst65_l, dst54_l, dst87_l, dst76_l, dst5465_l, dst7687_l); + dst98109_l = (v8i16) __msa_pckev_d((v2i64) dst109_l, (v2i64) dst98_l); + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); + dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); + dst6_r = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7_r = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst1021_l, dst3243_l, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst3243_l, dst5465_l, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst5465_l, dst7687_l, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst7687_l, dst98109_l, filt_h0, filt_h1); + SRA_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SRA_4V(dst4_r, dst5_r, dst6_r, dst7_r, 6); + SRA_4V(dst0_l, dst1_l, dst2_l, dst3_l, 6); + MUL2(dst0_r, weight_vec, dst1_r, weight_vec, dst0_r, dst1_r); + MUL2(dst2_r, weight_vec, dst3_r, weight_vec, dst2_r, dst3_r); + MUL2(dst4_r, weight_vec, dst5_r, weight_vec, dst4_r, dst5_r); + MUL2(dst6_r, weight_vec, dst7_r, weight_vec, dst6_r, dst7_r); + MUL2(dst0_l, weight_vec, dst1_l, weight_vec, dst0_l, dst1_l); + MUL2(dst2_l, weight_vec, dst3_l, weight_vec, dst2_l, dst3_l); + SRAR_W4_SW(dst0_r, dst1_r, dst2_r, dst3_r, rnd_vec); + SRAR_W4_SW(dst4_r, dst5_r, dst6_r, dst7_r, rnd_vec); + SRAR_W4_SW(dst0_l, dst1_l, dst2_l, dst3_l, rnd_vec); + PCKEV_H2_SH(dst1_r, dst0_r, dst3_r, dst2_r, tmp0, tmp1); + PCKEV_H2_SH(dst5_r, dst4_r, dst7_r, dst6_r, tmp2, tmp3); + PCKEV_H2_SH(dst1_l, dst0_l, dst3_l, dst2_l, tmp4, tmp5); + ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); + ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); + ADD2(tmp4, offset_vec, tmp5, offset_vec, tmp4, tmp5); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH2_0_255_MAX_SATU(tmp4, tmp5); + PCKEV_B3_UB(tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, out0, out1, out2); + ST4x8_UB(out0, out1, dst, dst_stride); + ST2x4_UB(out2, 0, dst + 4, dst_stride); + dst += 4 * dst_stride; + ST2x4_UB(out2, 4, dst + 4, dst_stride); } static void hevc_hv_uniwgt_4t_8x2_msa(uint8_t *src, @@ -4451,23 +4561,24 @@ static void hevc_hv_uniwgt_4t_8x2_msa(uint8_t *src, int32_t dst_stride, const int8_t *filter_x, const int8_t *filter_y, - int32_t height, int32_t weight, int32_t offset, int32_t rnd_val) { + v16u8 out; v16i8 src0, src1, src2, src3, src4; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1, filter_vec; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; v8i16 dst0, dst1, dst2, dst3, dst4; v4i32 dst0_r, dst0_l, dst1_r, dst1_l; v8i16 dst10_r, dst32_r, dst21_r, dst43_r; v8i16 dst10_l, dst32_l, dst21_l, dst43_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 tmp0, tmp1; + v8i16 offset_vec, const_128, denom_vec; + v4i32 weight_vec, rnd_vec; src -= (src_stride + 1); @@ -4475,65 +4586,144 @@ static void hevc_hv_uniwgt_4t_8x2_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val - 6); + const_128 = __msa_fill_h((128 * weight)); + offset_vec += __msa_srar_h(const_128, denom_vec); + LD_SB5(src, src_stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec8, vec9); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec8, vec9, filt0, filt1); ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); - - LD_SB2(src, src_stride, src3, src4); - src += (2 * src_stride); - XORI_B2_128_SB(src3, src4); - - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + MUL2(dst0_r, weight_vec, dst1_r, weight_vec, dst0_r, dst1_r); + MUL2(dst0_l, weight_vec, dst1_l, weight_vec, dst0_l, dst1_l); + SRAR_W4_SW(dst0_r, dst0_l, dst1_r, dst1_l, rnd_vec); + PCKEV_H2_SH(dst0_l, dst0_r, dst1_l, dst1_r, tmp0, tmp1); + ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); + CLIP_SH2_0_255_MAX_SATU(tmp0, tmp1); + out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); + ST8x2_UB(out, dst, dst_stride); +} - HEVC_HV_UNIW_RND_CLIP4(dst0_r, dst1_r, dst0_l, dst1_l, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst0_l, dst1_l); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST8x2_UB(dst0_r, dst, dst_stride); - dst += (2 * dst_stride); +static void hevc_hv_uniwgt_4t_8multx4_msa(uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_x, + const int8_t *filter_y, + int32_t width8mult, + int32_t weight, + int32_t offset, + int32_t rnd_val) +{ + uint32_t cnt; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4, src5, src6, mask0, mask1; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 filt0, filt1, filt_h0, filt_h1, filter_vec; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, tmp0, tmp1, tmp2, tmp3; + v8i16 dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + v8i16 offset_vec, const_128, denom_vec; + v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + v4i32 weight_vec, rnd_vec; + + src -= (src_stride + 1); + + filter_vec = LD_SH(filter_x); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + + weight_vec = __msa_fill_w(weight); + rnd_vec = __msa_fill_w(rnd_val); + + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val - 6); + const_128 = __msa_fill_h((128 * weight)); + offset_vec += __msa_srar_h(const_128, denom_vec); + + for (cnt = width8mult; cnt--;) { + LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); + src += 8; + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); + ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + MUL2(dst0_r, weight_vec, dst1_r, weight_vec, dst0_r, dst1_r); + MUL2(dst2_r, weight_vec, dst3_r, weight_vec, dst2_r, dst3_r); + MUL2(dst0_l, weight_vec, dst1_l, weight_vec, dst0_l, dst1_l); + MUL2(dst2_l, weight_vec, dst3_l, weight_vec, dst2_l, dst3_l); + SRAR_W4_SW(dst0_r, dst0_l, dst1_r, dst1_l, rnd_vec); + SRAR_W4_SW(dst2_r, dst2_l, dst3_r, dst3_l, rnd_vec); + PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, + dst3_r, tmp0, tmp1, tmp2, tmp3); + ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); + ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST8x4_UB(out0, out1, dst, dst_stride); + dst += 8; + } } static void hevc_hv_uniwgt_4t_8x6_msa(uint8_t *src, @@ -4542,26 +4732,27 @@ static void hevc_hv_uniwgt_4t_8x6_msa(uint8_t *src, int32_t dst_stride, const int8_t *filter_x, const int8_t *filter_y, - int32_t height, int32_t weight, int32_t offset, int32_t rnd_val) { + v16u8 out0, out1, out2; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1, filter_vec; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; + v16i8 vec10, vec11, vec12, vec13, vec14, vec15, vec16, vec17; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; - v4i32 dst4_r, dst4_l, dst5_r, dst5_l; + v4i32 dst4_r, dst4_l, dst5_r, dst5_l, weight_vec, rnd_vec; v8i16 dst10_r, dst32_r, dst10_l, dst32_l; v8i16 dst21_r, dst43_r, dst21_l, dst43_l; v8i16 dst54_r, dst54_l, dst65_r, dst65_l; v8i16 dst76_r, dst76_l, dst87_r, dst87_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + v8i16 offset_vec, const_128, denom_vec; src -= (src_stride + 1); @@ -4569,126 +4760,87 @@ static void hevc_hv_uniwgt_4t_8x6_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); - - XORI_B3_128_SB(src0, src1, src2); - + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val - 6); + const_128 = __msa_fill_h((128 * weight)); + offset_vec += __msa_srar_h(const_128, denom_vec); + + LD_SB5(src, src_stride, src0, src1, src2, src3, src4); + src += (5 * src_stride); + LD_SB4(src, src_stride, src5, src6, src7, src8); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + XORI_B4_128_SB(src5, src6, src7, src8); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec8, vec9); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec10, vec11); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec12, vec13); + VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec14, vec15); + VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec16, vec17); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec8, vec9, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec10, vec11, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(vec12, vec13, filt0, filt1); + dst7 = HEVC_FILT_4TAP_SH(vec14, vec15, filt0, filt1); + dst8 = HEVC_FILT_4TAP_SH(vec16, vec17, filt0, filt1); ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); - - LD_SB2(src, src_stride, src3, src4); - src += (2 * src_stride); - XORI_B2_128_SB(src3, src4); - - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); + ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); + ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - - LD_SB2(src, src_stride, src5, src6); - src += (2 * src_stride); - XORI_B2_128_SB(src5, src6); - - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); - dst2_r >>= 6; - dst2_l >>= 6; - - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); - ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); - dst3_r >>= 6; - dst3_l >>= 6; - - LD_SB2(src, src_stride, src7, src8); - src += (2 * src_stride); - XORI_B2_128_SB(src7, src8); - - /* row 7 */ - VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); - dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); - ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); dst4_l = HEVC_FILT_4TAP(dst54_l, dst76_l, filt_h0, filt_h1); - - dst4_r >>= 6; - dst4_l >>= 6; - - /* row 8 */ - VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec0, vec1); - dst8 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst8, dst8); - ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); dst5_l = HEVC_FILT_4TAP(dst65_l, dst87_l, filt_h0, filt_h1); - dst5_r >>= 6; - dst5_l >>= 6; - - HEVC_HV_UNIW_RND_CLIP4(dst0_r, dst1_r, dst0_l, dst1_l, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst0_l, dst1_l); - HEVC_HV_UNIW_RND_CLIP4(dst2_r, dst3_r, dst2_l, dst3_l, - weight_vec, offset_vec, rnd_vec, - dst2_r, dst3_r, dst2_l, dst3_l); - HEVC_HV_UNIW_RND_CLIP4(dst4_r, dst5_r, dst4_l, dst5_l, - weight_vec, offset_vec, rnd_vec, - dst4_r, dst5_r, dst4_l, dst5_l); - HEVC_PCK_SW_SB12(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - dst4_l, dst4_r, dst5_l, dst5_r, dst0_r, dst1_r, dst2_r); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + SRA_4V(dst4_r, dst4_l, dst5_r, dst5_l, 6); + MUL2(dst0_r, weight_vec, dst1_r, weight_vec, dst0_r, dst1_r); + MUL2(dst2_r, weight_vec, dst3_r, weight_vec, dst2_r, dst3_r); + MUL2(dst4_r, weight_vec, dst5_r, weight_vec, dst4_r, dst5_r); + MUL2(dst0_l, weight_vec, dst1_l, weight_vec, dst0_l, dst1_l); + MUL2(dst2_l, weight_vec, dst3_l, weight_vec, dst2_l, dst3_l); + MUL2(dst4_l, weight_vec, dst5_l, weight_vec, dst4_l, dst5_l); + SRAR_W4_SW(dst0_r, dst0_l, dst1_r, dst1_l, rnd_vec); + SRAR_W4_SW(dst2_r, dst2_l, dst3_r, dst3_l, rnd_vec); + SRAR_W4_SW(dst4_r, dst4_l, dst5_r, dst5_l, rnd_vec); + PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, dst3_r, + tmp0, tmp1, tmp2, tmp3); + PCKEV_H2_SH(dst4_l, dst4_r, dst5_l, dst5_r, tmp4, tmp5); + ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); + ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); + ADD2(tmp4, offset_vec, tmp5, offset_vec, tmp4, tmp5); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH2_0_255_MAX_SATU(tmp4, tmp5); + PCKEV_B3_UB(tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, out0, out1, out2); + ST8x4_UB(out0, out1, dst, dst_stride); dst += (4 * dst_stride); - ST8x2_UB(dst2_r, dst, dst_stride); + ST8x2_UB(out2, dst, dst_stride); } static void hevc_hv_uniwgt_4t_8multx4mult_msa(uint8_t *src, @@ -4701,24 +4853,25 @@ static void hevc_hv_uniwgt_4t_8multx4mult_msa(uint8_t *src, int32_t weight, int32_t offset, int32_t rnd_val, - int32_t width) + int32_t width8mult) { uint32_t loop_cnt, cnt; uint8_t *src_tmp; uint8_t *dst_tmp; + v16u8 out0, out1; v16i8 src0, src1, src2, src3, src4, src5, src6; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1, filter_vec; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, tmp0, tmp1, tmp2, tmp3; + v8i16 dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; v4i32 dst0_r, dst0_l, dst1_r, dst1_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 offset_vec, const_128, denom_vec; v4i32 dst2_r, dst2_l, dst3_r, dst3_l; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; - v8i16 dst10_l, dst32_l, dst21_l, dst43_l; + v4i32 weight_vec, rnd_vec; src -= (src_stride + 1); @@ -4726,21 +4879,21 @@ static void hevc_hv_uniwgt_4t_8multx4mult_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); - for (cnt = width >> 3; cnt--;) { + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val - 6); + const_128 = __msa_fill_h((128 * weight)); + offset_vec += __msa_srar_h(const_128, denom_vec); + + for (cnt = width8mult; cnt--;) { src_tmp = src; dst_tmp = dst; @@ -4751,12 +4904,9 @@ static void hevc_hv_uniwgt_4t_8multx4mult_msa(uint8_t *src, VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); @@ -4767,51 +4917,47 @@ static void hevc_hv_uniwgt_4t_8multx4mult_msa(uint8_t *src, XORI_B4_128_SB(src3, src4, src5, src6); VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - ILVRL_H2_SH(dst5, dst4, dst10_r, dst10_l); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_l = HEVC_FILT_4TAP(dst32_l, dst10_l, filt_h0, filt_h1); - dst2_r >>= 6; - dst2_l >>= 6; - - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - ILVRL_H2_SH(dst2, dst5, dst21_r, dst21_l); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_l = HEVC_FILT_4TAP(dst43_l, dst21_l, filt_h0, filt_h1); - dst3_r >>= 6; - dst3_l >>= 6; - - HEVC_HV_UNIW_RND_CLIP4(dst0_r, dst1_r, dst0_l, dst1_l, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst0_l, dst1_l); - HEVC_HV_UNIW_RND_CLIP4(dst2_r, dst3_r, dst2_l, dst3_l, - weight_vec, offset_vec, rnd_vec, - dst2_r, dst3_r, dst2_l, dst3_l); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST8x4_UB(dst0_r, dst1_r, dst_tmp, dst_stride); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + MUL2(dst0_r, weight_vec, dst1_r, weight_vec, dst0_r, dst1_r); + MUL2(dst2_r, weight_vec, dst3_r, weight_vec, dst2_r, dst3_r); + MUL2(dst0_l, weight_vec, dst1_l, weight_vec, dst0_l, dst1_l); + MUL2(dst2_l, weight_vec, dst3_l, weight_vec, dst2_l, dst3_l); + SRAR_W4_SW(dst0_r, dst0_l, dst1_r, dst1_l, rnd_vec); + SRAR_W4_SW(dst2_r, dst2_l, dst3_r, dst3_l, rnd_vec); + PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, + dst3_r, tmp0, tmp1, tmp2, tmp3); + ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); + ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST8x4_UB(out0, out1, dst_tmp, dst_stride); dst_tmp += (4 * dst_stride); + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dst2 = dst6; } src += 8; @@ -4833,16 +4979,20 @@ static void hevc_hv_uniwgt_4t_8w_msa(uint8_t *src, if (2 == height) { hevc_hv_uniwgt_4t_8x2_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, weight, + filter_x, filter_y, weight, offset, rnd_val); + } else if (4 == height) { + hevc_hv_uniwgt_4t_8multx4_msa(src, src_stride, dst, dst_stride, + filter_x, filter_y, 1, weight, + offset, rnd_val); } else if (6 == height) { hevc_hv_uniwgt_4t_8x6_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, weight, + filter_x, filter_y, weight, offset, rnd_val); } else if (0 == (height % 4)) { hevc_hv_uniwgt_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, filter_x, filter_y, height, weight, - offset, rnd_val, 8); + offset, rnd_val, 1); } } @@ -4857,12 +5007,170 @@ static void hevc_hv_uniwgt_4t_12w_msa(uint8_t *src, int32_t offset, int32_t rnd_val) { - hevc_hv_uniwgt_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, weight, - offset, rnd_val, 8); - hevc_hv_uniwgt_4t_4w_msa(src + 8, src_stride, dst + 8, dst_stride, - filter_x, filter_y, height, weight, - offset, rnd_val); + uint32_t loop_cnt; + uint8_t *src_tmp, *dst_tmp; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 mask0, mask1, mask2, mask3; + v8i16 filt0, filt1, filt_h0, filt_h1, filter_vec, tmp0, tmp1, tmp2, tmp3; + v8i16 dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6; + v8i16 dst10, dst21, dst22, dst73, dst84, dst95, dst106; + v8i16 dst76_r, dst98_r, dst87_r, dst109_r; + v8i16 dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + v8i16 offset_vec, const_128, denom_vec; + v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + v4i32 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, weight_vec, rnd_vec; + + src -= (src_stride + 1); + + filter_vec = LD_SH(filter_x); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + + weight_vec = __msa_fill_w(weight); + rnd_vec = __msa_fill_w(rnd_val); + + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val - 6); + const_128 = __msa_fill_h((128 * weight)); + offset_vec += __msa_srar_h(const_128, denom_vec); + + src_tmp = src; + dst_tmp = dst; + + LD_SB3(src_tmp, src_stride, src0, src1, src2); + src_tmp += (3 * src_stride); + XORI_B3_128_SB(src0, src1, src2); + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + dsth0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + ILVRL_H2_SH(dsth1, dsth0, dst10_r, dst10_l); + ILVRL_H2_SH(dsth2, dsth1, dst21_r, dst21_l); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src_tmp, src_stride, src3, src4, src5, src6); + src_tmp += (4 * src_stride); + XORI_B4_128_SB(src3, src4, src5, src6); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + dsth3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + ILVRL_H2_SH(dsth3, dsth2, dst32_r, dst32_l); + ILVRL_H2_SH(dsth4, dsth3, dst43_r, dst43_l); + ILVRL_H2_SH(dsth5, dsth4, dst54_r, dst54_l); + ILVRL_H2_SH(dsth6, dsth5, dst65_r, dst65_l); + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + MUL2(dst0_r, weight_vec, dst1_r, weight_vec, dst0_r, dst1_r); + MUL2(dst2_r, weight_vec, dst3_r, weight_vec, dst2_r, dst3_r); + MUL2(dst0_l, weight_vec, dst1_l, weight_vec, dst0_l, dst1_l); + MUL2(dst2_l, weight_vec, dst3_l, weight_vec, dst2_l, dst3_l); + SRAR_W4_SW(dst0_r, dst0_l, dst1_r, dst1_l, rnd_vec); + SRAR_W4_SW(dst2_r, dst2_l, dst3_r, dst3_l, rnd_vec); + PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, + dst3_r, tmp0, tmp1, tmp2, tmp3); + ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); + ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST8x4_UB(out0, out1, dst_tmp, dst_stride); + dst_tmp += (4 * dst_stride); + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dsth2 = dsth6; + } + + src += 8; + dst += 8; + + mask2 = LD_SB(ff_hevc_mask_arr + 16); + mask3 = mask2 + 2; + + LD_SB3(src, src_stride, src0, src1, src2); + src += (3 * src_stride); + XORI_B3_128_SB(src0, src1, src2); + VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); + VSHF_B2_SB(src1, src2, src1, src2, mask2, mask3, vec2, vec3); + dst10 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst21 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + ILVRL_H2_SH(dst21, dst10, dst10_r, dst21_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst21, 1); + + for (loop_cnt = 2; loop_cnt--;) { + LD_SB8(src, src_stride, src3, src4, src5, src6, src7, src8, src9, + src10); + src += (8 * src_stride); + XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); + VSHF_B2_SB(src3, src7, src3, src7, mask2, mask3, vec0, vec1); + VSHF_B2_SB(src4, src8, src4, src8, mask2, mask3, vec2, vec3); + VSHF_B2_SB(src5, src9, src5, src9, mask2, mask3, vec4, vec5); + VSHF_B2_SB(src6, src10, src6, src10, mask2, mask3, vec6, vec7); + dst73 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst84 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst95 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst106 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + dst32_r = __msa_ilvr_h(dst73, dst22); + ILVRL_H2_SH(dst84, dst73, dst43_r, dst87_r); + ILVRL_H2_SH(dst95, dst84, dst54_r, dst98_r); + ILVRL_H2_SH(dst106, dst95, dst65_r, dst109_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst73, 1); + dst76_r = __msa_ilvr_h(dst22, dst106); + dst0 = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst2 = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst3 = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst4 = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); + dst5 = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); + dst6 = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7 = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + SRA_4V(dst0, dst1, dst2, dst3, 6); + SRA_4V(dst4, dst5, dst6, dst7, 6); + MUL2(dst0, weight_vec, dst1, weight_vec, dst0, dst1); + MUL2(dst2, weight_vec, dst3, weight_vec, dst2, dst3); + MUL2(dst4, weight_vec, dst5, weight_vec, dst4, dst5); + MUL2(dst6, weight_vec, dst7, weight_vec, dst6, dst7); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); + PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, tmp0, tmp1, + tmp2, tmp3); + ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); + ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST4x8_UB(out0, out1, dst, dst_stride); + dst += (8 * dst_stride); + + dst10_r = dst98_r; + dst21_r = dst109_r; + dst22 = (v8i16) __msa_splati_d((v2i64) dst106, 1); + } } static void hevc_hv_uniwgt_4t_16w_msa(uint8_t *src, @@ -4876,9 +5184,15 @@ static void hevc_hv_uniwgt_4t_16w_msa(uint8_t *src, int32_t offset, int32_t rnd_val) { - hevc_hv_uniwgt_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, weight, - offset, rnd_val, 16); + if (4 == height) { + hevc_hv_uniwgt_4t_8multx4_msa(src, src_stride, dst, dst_stride, + filter_x, filter_y, 2, weight, offset, + rnd_val); + } else { + hevc_hv_uniwgt_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, weight, + offset, rnd_val, 2); + } } static void hevc_hv_uniwgt_4t_24w_msa(uint8_t *src, @@ -4894,7 +5208,7 @@ static void hevc_hv_uniwgt_4t_24w_msa(uint8_t *src, { hevc_hv_uniwgt_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, filter_x, filter_y, height, weight, - offset, rnd_val, 24); + offset, rnd_val, 3); } static void hevc_hv_uniwgt_4t_32w_msa(uint8_t *src, @@ -4910,7 +5224,7 @@ static void hevc_hv_uniwgt_4t_32w_msa(uint8_t *src, { hevc_hv_uniwgt_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, filter_x, filter_y, height, weight, - offset, rnd_val, 32); + offset, rnd_val, 4); } #define UNIWGT_MC_COPY(WIDTH) \ From cf5a6c754aa3b67062b8cc60fa244e9c7d82010f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 1 Nov 2017 20:02:59 +0100 Subject: [PATCH 0727/2557] avcodec/gdv: Check compression before allocating frame Fixes: 2926/clusterfuzz-testcase-4987110014582784 This reduces decoding time from 7 to 4 seconds The timeout should have been fixed in 0561bd2fc2bff0dbe651d5998e9f129c43d25eb3 but ossfuzz did not close this issue Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer --- libavcodec/gdv.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libavcodec/gdv.c b/libavcodec/gdv.c index dc91869edf94e..e52a637610a54 100644 --- a/libavcodec/gdv.c +++ b/libavcodec/gdv.c @@ -409,17 +409,20 @@ static int gdv_decode_frame(AVCodecContext *avctx, void *data, unsigned flags; uint8_t *dst; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; - if (pal && pal_size == AVPALETTE_SIZE) - memcpy(gdv->pal, pal, AVPALETTE_SIZE); - bytestream2_init(gb, avpkt->data, avpkt->size); bytestream2_init_writer(pb, gdv->frame, gdv->frame_size); flags = bytestream2_get_le32(gb); compression = flags & 0xF; + if (compression == 4 || compression == 7 || compression > 8) + return AVERROR_INVALIDDATA; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + if (pal && pal_size == AVPALETTE_SIZE) + memcpy(gdv->pal, pal, AVPALETTE_SIZE); + rescale(gdv, gdv->frame, avctx->width, avctx->height, !!(flags & 0x10), !!(flags & 0x20)); @@ -451,7 +454,7 @@ static int gdv_decode_frame(AVCodecContext *avctx, void *data, ret = decompress_68(avctx, flags >> 8, 1); break; default: - return AVERROR_INVALIDDATA; + av_assert0(0); } memcpy(frame->data[1], gdv->pal, AVPALETTE_SIZE); From eaa25b09e4116f2fd649c8638021514911e908c9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 2 Nov 2017 23:26:46 -0300 Subject: [PATCH 0728/2557] avformat/tls_openssl: move some functions up in the file Cosmetic change, reduces differences with libav. --- libavformat/tls_openssl.c | 146 +++++++++++++++++++------------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c index 3108a86f4110c..94eb082b28a04 100644 --- a/libavformat/tls_openssl.c +++ b/libavformat/tls_openssl.c @@ -66,6 +66,79 @@ static unsigned long openssl_thread_id(void) #endif #endif +int ff_openssl_init(void) +{ + avpriv_lock_avformat(); + if (!openssl_init) { + SSL_library_init(); + SSL_load_error_strings(); +#if HAVE_THREADS + if (!CRYPTO_get_locking_callback()) { + int i; + openssl_mutexes = av_malloc_array(sizeof(pthread_mutex_t), CRYPTO_num_locks()); + if (!openssl_mutexes) { + avpriv_unlock_avformat(); + return AVERROR(ENOMEM); + } + + for (i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_init(&openssl_mutexes[i], NULL); + CRYPTO_set_locking_callback(openssl_lock); +#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 + CRYPTO_set_id_callback(openssl_thread_id); +#endif + } +#endif + } + openssl_init++; + avpriv_unlock_avformat(); + + return 0; +} + +void ff_openssl_deinit(void) +{ + avpriv_lock_avformat(); + openssl_init--; + if (!openssl_init) { +#if HAVE_THREADS + if (CRYPTO_get_locking_callback() == openssl_lock) { + int i; + CRYPTO_set_locking_callback(NULL); + for (i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_destroy(&openssl_mutexes[i]); + av_free(openssl_mutexes); + } +#endif + } + avpriv_unlock_avformat(); +} + +static int print_tls_error(URLContext *h, int ret) +{ + av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); + return AVERROR(EIO); +} + +static int tls_close(URLContext *h) +{ + TLSContext *c = h->priv_data; + if (c->ssl) { + SSL_shutdown(c->ssl); + SSL_free(c->ssl); + } + if (c->ctx) + SSL_CTX_free(c->ctx); + if (c->tls_shared.tcp) + ffurl_close(c->tls_shared.tcp); +#if OPENSSL_VERSION_NUMBER >= 0x1010000fL + if (c->url_bio_method) + BIO_meth_free(c->url_bio_method); +#endif + ff_openssl_deinit(); + return 0; +} + static int url_bio_create(BIO *b) { #if OPENSSL_VERSION_NUMBER >= 0x1010000fL @@ -143,79 +216,6 @@ static BIO_METHOD url_bio_method = { }; #endif -int ff_openssl_init(void) -{ - avpriv_lock_avformat(); - if (!openssl_init) { - SSL_library_init(); - SSL_load_error_strings(); -#if HAVE_THREADS - if (!CRYPTO_get_locking_callback()) { - int i; - openssl_mutexes = av_malloc_array(sizeof(pthread_mutex_t), CRYPTO_num_locks()); - if (!openssl_mutexes) { - avpriv_unlock_avformat(); - return AVERROR(ENOMEM); - } - - for (i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_init(&openssl_mutexes[i], NULL); - CRYPTO_set_locking_callback(openssl_lock); -#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 - CRYPTO_set_id_callback(openssl_thread_id); -#endif - } -#endif - } - openssl_init++; - avpriv_unlock_avformat(); - - return 0; -} - -void ff_openssl_deinit(void) -{ - avpriv_lock_avformat(); - openssl_init--; - if (!openssl_init) { -#if HAVE_THREADS - if (CRYPTO_get_locking_callback() == openssl_lock) { - int i; - CRYPTO_set_locking_callback(NULL); - for (i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_destroy(&openssl_mutexes[i]); - av_free(openssl_mutexes); - } -#endif - } - avpriv_unlock_avformat(); -} - -static int print_tls_error(URLContext *h, int ret) -{ - av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); - return AVERROR(EIO); -} - -static int tls_close(URLContext *h) -{ - TLSContext *c = h->priv_data; - if (c->ssl) { - SSL_shutdown(c->ssl); - SSL_free(c->ssl); - } - if (c->ctx) - SSL_CTX_free(c->ctx); - if (c->tls_shared.tcp) - ffurl_close(c->tls_shared.tcp); -#if OPENSSL_VERSION_NUMBER >= 0x1010000fL - if (c->url_bio_method) - BIO_meth_free(c->url_bio_method); -#endif - ff_openssl_deinit(); - return 0; -} - static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options) { TLSContext *p = h->priv_data; From 1c06a32cfa5798332c1c879834a831e1e12c6f53 Mon Sep 17 00:00:00 2001 From: Nicolas Frattaroli Date: Thu, 2 Nov 2017 23:39:53 +0100 Subject: [PATCH 0729/2557] diracdec: fix deprecated API usage avcodec_get_chroma_sub_sample is deprecated and generates a warning during build, so av_pix_fmt_get_chroma_sub_sample is used Signed-off-by: Nicolas Frattaroli Signed-off-by: James Almer --- libavcodec/diracdec.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libavcodec/diracdec.c b/libavcodec/diracdec.c index 0abb8b05990b2..7157357d593c6 100644 --- a/libavcodec/diracdec.c +++ b/libavcodec/diracdec.c @@ -26,6 +26,7 @@ * @author Marco Gerards , David Conrad, Jordi Ortiz */ +#include "libavutil/pixdesc.h" #include "libavutil/thread.h" #include "avcodec.h" #include "get_bits.h" @@ -1927,7 +1928,10 @@ static int get_buffer_with_edge(AVCodecContext *avctx, AVFrame *f, int flags) { int ret, i; int chroma_x_shift, chroma_y_shift; - avcodec_get_chroma_sub_sample(avctx->pix_fmt, &chroma_x_shift, &chroma_y_shift); + ret = av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &chroma_x_shift, + &chroma_y_shift); + if (ret < 0) + return ret; f->width = avctx->width + 2 * EDGE_WIDTH; f->height = avctx->height + 2 * EDGE_WIDTH + 2; @@ -2126,7 +2130,11 @@ static int dirac_decode_data_unit(AVCodecContext *avctx, const uint8_t *buf, int s->pshift = s->bit_depth > 8; - avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift); + ret = av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, + &s->chroma_x_shift, + &s->chroma_y_shift); + if (ret < 0) + return ret; ret = alloc_sequence_buffers(s); if (ret < 0) From 6a50a8f340161a0b65feb3537591b0381a6a6b38 Mon Sep 17 00:00:00 2001 From: Nicolas Frattaroli Date: Thu, 2 Nov 2017 20:12:48 +0100 Subject: [PATCH 0730/2557] snowenc: fix use of deprecated API Replace avcodec_get_chroma_sub_sample with the recommended av_pix_fmt_get_chroma_sub_sample, which fixes a compilation warning. Signed-off-by: Michael Niedermayer --- libavcodec/snowenc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index e7d670ac10f80..4fec377591136 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -22,6 +22,7 @@ #include "libavutil/libm.h" #include "libavutil/log.h" #include "libavutil/opt.h" +#include "libavutil/pixdesc.h" #include "avcodec.h" #include "internal.h" #include "snow_dwt.h" @@ -127,7 +128,13 @@ FF_ENABLE_DEPRECATION_WARNINGS av_log(avctx, AV_LOG_ERROR, "pixel format not supported\n"); return AVERROR_PATCHWELCOME; } - avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_h_shift, &s->chroma_v_shift); + + ret = av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_h_shift, + &s->chroma_v_shift); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "pixel format invalid or unknown\n"); + return ret; + } ff_set_cmp(&s->mecc, s->mecc.me_cmp, s->avctx->me_cmp); ff_set_cmp(&s->mecc, s->mecc.me_sub_cmp, s->avctx->me_sub_cmp); From 2cf3c0ab0d84b5cdb379059f8570809a13a306b9 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 6 Oct 2017 21:38:43 +0200 Subject: [PATCH 0731/2557] Revert "configure: Detect AIX ar command instead of hardcoding it in the OS section" This reverts commit 4822ee3ca620a92cd2b0a9a03ea9e34288192c79. AIX is a fringe oddity. Do not clutter the main codepath with AIX workarounds. --- configure | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/configure b/configure index 644597617598a..6f96a06f03c73 100755 --- a/configure +++ b/configure @@ -3434,9 +3434,6 @@ fi if $ar 2>&1 | grep -q Microsoft; then arflags="-nologo" ar_o='-out:$@' -elif $ar 2>&1 | grep -q 'Usage: ar.*-X.*any'; then - arflags='-Xany -r -c' - ar_o='$@' else arflags="rc" ar_o='$@' @@ -3815,6 +3812,7 @@ case $target_os in SHFLAGS=-shared add_cppflags '-I\$(SRC_PATH)/compat/aix' enabled shared && add_ldflags -Wl,-brtl + ar_default='ar -Xany' ;; android) disable symver From 1f24b33d9af83a02ed06a644797028b139281096 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 10 Oct 2017 21:18:03 +0200 Subject: [PATCH 0732/2557] avfilter/vf_tile: remove limit of max tile size Signed-off-by: Paul B Mahol --- libavfilter/vf_tile.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_tile.c b/libavfilter/vf_tile.c index 87e0b940cfcc6..e9d246fc73b0b 100644 --- a/libavfilter/vf_tile.c +++ b/libavfilter/vf_tile.c @@ -23,6 +23,7 @@ * tile video filter */ +#include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avfilter.h" @@ -44,8 +45,6 @@ typedef struct TileContext { uint8_t rgba_color[4]; } TileContext; -#define REASONABLE_SIZE 1024 - #define OFFSET(x) offsetof(TileContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM @@ -68,12 +67,21 @@ static av_cold int init(AVFilterContext *ctx) { TileContext *tile = ctx->priv; - if (tile->w > REASONABLE_SIZE || tile->h > REASONABLE_SIZE) { + if (tile->w > UINT_MAX / tile->h) { av_log(ctx, AV_LOG_ERROR, "Tile size %ux%u is insane.\n", tile->w, tile->h); return AVERROR(EINVAL); } + if (tile->padding) { + if ((tile->w - 1 > (UINT32_MAX - 2 * tile->margin) / tile->padding) || + (tile->h - 1 > (UINT32_MAX - 2 * tile->margin) / tile->padding)) { + av_log(ctx, AV_LOG_ERROR, "Combination of Tile size %ux%u, padding %d and margin %d overflows.\n", + tile->w, tile->h, tile->padding, tile->margin); + return AVERROR(EINVAL); + } + } + if (tile->nb_frames == 0) { tile->nb_frames = tile->w * tile->h; } else if (tile->nb_frames > tile->w * tile->h) { @@ -142,6 +150,7 @@ static void draw_blank_frame(AVFilterContext *ctx, AVFrame *out_buf) x0, y0, inlink->w, inlink->h); tile->current++; } + static int end_last_frame(AVFilterContext *ctx) { TileContext *tile = ctx->priv; From 1746c7c8f2f9a6c5eacb486426dd0a579b4b7498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 3 Nov 2017 11:36:49 +0200 Subject: [PATCH 0733/2557] libspeexenc: Use speex_lib_get_mode instead of the speex_foo_mode data symbols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids issues linking to a DLL version of libspeex, since the libspeex headers lack proper dllimport declarations for the data symbols. This isn't an issue when building with mingw with GNU binutils, since GNU ld can fix up that kind of data import automatically. libspeexdec.c already uses speex_lib_get_mode as well. Signed-off-by: Martin Storsjö --- libavcodec/libspeexenc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/libspeexenc.c b/libavcodec/libspeexenc.c index f3a31e98798b2..eb02e8ec6d8bb 100644 --- a/libavcodec/libspeexenc.c +++ b/libavcodec/libspeexenc.c @@ -158,9 +158,9 @@ static av_cold int encode_init(AVCodecContext *avctx) /* sample rate and encoding mode */ switch (avctx->sample_rate) { - case 8000: mode = &speex_nb_mode; break; - case 16000: mode = &speex_wb_mode; break; - case 32000: mode = &speex_uwb_mode; break; + case 8000: mode = speex_lib_get_mode(SPEEX_MODEID_NB); break; + case 16000: mode = speex_lib_get_mode(SPEEX_MODEID_WB); break; + case 32000: mode = speex_lib_get_mode(SPEEX_MODEID_UWB); break; default: av_log(avctx, AV_LOG_ERROR, "Sample rate of %d Hz is not supported. " "Resample to 8, 16, or 32 kHz.\n", avctx->sample_rate); From 55fe72a841ba306370e68e86c88f34b4456aa4dd Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 2 Nov 2017 20:42:05 -0300 Subject: [PATCH 0734/2557] matroskadec: don't warn about unknown spherical medata when none is present track->video.projection.type is set to 0 (a Matroska specific "No spherical metadata present" value, with no related AVSphericalMapping) by default on files without the element. This removes bogus warnings on every single matroska file without Spherical metadata. Signed-off-by: James Almer --- libavformat/matroskadec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index c6e1a190a8e8b..3953cd304e2a5 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -1658,6 +1658,9 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) return AVERROR_INVALIDDATA; } break; + case MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR: + /* No Spherical metadata */ + return 0; default: av_log(NULL, AV_LOG_WARNING, "Unknown spherical metadata type %"PRIu64"\n", From 9d0b42bce52cfe71d5aa2e3775ab3f534a875c44 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Wed, 1 Nov 2017 21:39:33 +0100 Subject: [PATCH 0735/2557] fate: Fix fitsdec-gbrap16 test on big-endian hardware. --- tests/fate/fits.mak | 4 ++-- tests/ref/fate/{fitsdec-gbrap16 => fitsdec-gbrap16le} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename tests/ref/fate/{fitsdec-gbrap16 => fitsdec-gbrap16le} (100%) diff --git a/tests/fate/fits.mak b/tests/fate/fits.mak index 0335a7b508240..113498cf7261f 100644 --- a/tests/fate/fits.mak +++ b/tests/fate/fits.mak @@ -8,7 +8,7 @@ tests/data/fits-multi.fits: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data map.tests/data/lena-gray.fits := gray8 map.tests/data/lena-gbrp.fits := rgb24 map.tests/data/lena-gbrp16.fits := rgb48 -map.tests/data/lena-gbrap16.fits := rgba64 +map.tests/data/lena-gbrap16le.fits := rgba64 tests/data/lena%.fits: TAG = GEN tests/data/lena%.fits: NAME = $(map.$(@)) @@ -37,7 +37,7 @@ fate-fitsdec%: PIXFMT = $(word 3, $(subst -, ,$(@))) fate-fitsdec%: SRC = $(TARGET_PATH)/tests/data/lena-$(PIXFMT).fits fate-fitsdec%: CMD = framecrc -i $(SRC) -pix_fmt $(PIXFMT) -FATE_FITS_DEC_PIXFMT = gray gbrp gbrp16 gbrap16 +FATE_FITS_DEC_PIXFMT = gray gbrp gbrp16 gbrap16le $(FATE_FITS_DEC_PIXFMT:%=fate-fitsdec-%): fate-fitsdec-%: tests/data/lena-%.fits FATE_FITS_DEC-$(call ALLYES, FITS_DEMUXER IMAGE2_DEMUXER FITS_DECODER PNG_DECODER FITS_ENCODER FITS_MUXER) += $(FATE_FITS_DEC_PIXFMT:%=fate-fitsdec-%) diff --git a/tests/ref/fate/fitsdec-gbrap16 b/tests/ref/fate/fitsdec-gbrap16le similarity index 100% rename from tests/ref/fate/fitsdec-gbrap16 rename to tests/ref/fate/fitsdec-gbrap16le From c2a8f0fcbe57ea9ccaa864130f078af10516c3c1 Mon Sep 17 00:00:00 2001 From: Sasi Inguva Date: Thu, 2 Nov 2017 17:33:28 -0700 Subject: [PATCH 0736/2557] lavf/mov.c: Refine edit list start seek, based on PTS computed from CTTS. Partially fixes t/6699. Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 129 ++++++++++++++++++--------- tests/fate/mov.mak | 8 ++ tests/ref/fate/mov-ibi-elst-starts-b | 33 +++++++ 3 files changed, 127 insertions(+), 43 deletions(-) create mode 100644 tests/ref/fate/mov-ibi-elst-starts-b diff --git a/libavformat/mov.c b/libavformat/mov.c index 60f0228e2dfbc..7954db6e47162 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3014,34 +3014,99 @@ static int get_edit_list_entry(MOVContext *mov, } /** - * Find the closest previous frame to the timestamp, in e_old index + * Find the closest previous frame to the timestamp_pts, in e_old index * entries. Searching for just any frame / just key frames can be controlled by * last argument 'flag'. - * Returns the index of the entry in st->index_entries if successful, - * else returns -1. + * Note that if ctts_data is not NULL, we will always search for a key frame + * irrespective of the value of 'flag'. If we don't find any keyframe, we will + * return the first frame of the video. + * + * Here the timestamp_pts is considered to be a presentation timestamp and + * the timestamp of index entries are considered to be decoding timestamps. + * + * Returns 0 if successful in finding a frame, else returns -1. + * Places the found index corresponding output arg. + * + * If ctts_old is not NULL, then refines the searched entry by searching + * backwards from the found timestamp, to find the frame with correct PTS. + * + * Places the found ctts_index and ctts_sample in corresponding output args. */ -static int64_t find_prev_closest_index(AVStream *st, - AVIndexEntry *e_old, - int nb_old, - int64_t timestamp, - int flag) +static int find_prev_closest_index(AVStream *st, + AVIndexEntry *e_old, + int nb_old, + MOVStts* ctts_data, + int64_t ctts_count, + int64_t timestamp_pts, + int flag, + int64_t* index, + int64_t* ctts_index, + int64_t* ctts_sample) { + MOVStreamContext *msc = st->priv_data; AVIndexEntry *e_keep = st->index_entries; int nb_keep = st->nb_index_entries; - int64_t found = -1; int64_t i = 0; + int64_t index_ctts_count; + + av_assert0(index); + + // If dts_shift > 0, then all the index timestamps will have to be offset by + // at least dts_shift amount to obtain PTS. + // Hence we decrement the searched timestamp_pts by dts_shift to find the closest index element. + if (msc->dts_shift > 0) { + timestamp_pts -= msc->dts_shift; + } st->index_entries = e_old; st->nb_index_entries = nb_old; - found = av_index_search_timestamp(st, timestamp, flag | AVSEEK_FLAG_BACKWARD); + *index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD); // Keep going backwards in the index entries until the timestamp is the same. - if (found >= 0) { - for (i = found; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp; + if (*index >= 0) { + for (i = *index; i > 0 && e_old[i].timestamp == e_old[i - 1].timestamp; i--) { if ((flag & AVSEEK_FLAG_ANY) || (e_old[i - 1].flags & AVINDEX_KEYFRAME)) { - found = i - 1; + *index = i - 1; + } + } + } + + // If we have CTTS then refine the search, by searching backwards over PTS + // computed by adding corresponding CTTS durations to index timestamps. + if (ctts_data && *index >= 0) { + av_assert0(ctts_index); + av_assert0(ctts_sample); + // Find out the ctts_index for the found frame. + *ctts_index = 0; + *ctts_sample = 0; + for (index_ctts_count = 0; index_ctts_count < *index; index_ctts_count++) { + if (*ctts_index < ctts_count) { + (*ctts_sample)++; + if (ctts_data[*ctts_index].count == *ctts_sample) { + (*ctts_index)++; + *ctts_sample = 0; + } + } + } + + while (*index >= 0 && (*ctts_index) >= 0) { + // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly). + // No need to add dts_shift to the timestamp here becase timestamp_pts has already been + // compensated by dts_shift above. + if ((e_old[*index].timestamp + ctts_data[*ctts_index].duration) <= timestamp_pts && + (e_old[*index].flags & AVINDEX_KEYFRAME)) { + break; + } + + (*index)--; + if (*ctts_sample == 0) { + (*ctts_index)--; + if (*ctts_index >= 0) + *ctts_sample = ctts_data[*ctts_index].count - 1; + } else { + (*ctts_sample)--; } } } @@ -3049,7 +3114,7 @@ static int64_t find_prev_closest_index(AVStream *st, /* restore AVStream state*/ st->index_entries = e_keep; st->nb_index_entries = nb_keep; - return found; + return *index >= 0 ? 0 : -1; } /** @@ -3220,10 +3285,8 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) int64_t empty_edits_sum_duration = 0; int64_t edit_list_index = 0; int64_t index; - int64_t index_ctts_count; int flags; int64_t start_dts = 0; - int64_t edit_list_media_time_dts = 0; int64_t edit_list_start_encountered = 0; int64_t search_timestamp = 0; int64_t* frame_duration_buffer = NULL; @@ -3293,17 +3356,11 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) st->skip_samples = msc->start_pad = 0; } - //find closest previous key frame - edit_list_media_time_dts = edit_list_media_time; - if (msc->dts_shift > 0) { - edit_list_media_time_dts -= msc->dts_shift; - } - // While reordering frame index according to edit list we must handle properly // the scenario when edit list entry starts from none key frame. // We find closest previous key frame and preserve it and consequent frames in index. // All frames which are outside edit list entry time boundaries will be dropped after decoding. - search_timestamp = edit_list_media_time_dts; + search_timestamp = edit_list_media_time; if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { // Audio decoders like AAC need need a decoder delay samples previous to the current sample, // to correctly decode this frame. Hence for audio we seek to a frame 1 sec. before the @@ -3311,38 +3368,24 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) search_timestamp = FFMAX(search_timestamp - msc->time_scale, e_old[0].timestamp); } - index = find_prev_closest_index(st, e_old, nb_old, search_timestamp, 0); - if (index == -1) { + if (find_prev_closest_index(st, e_old, nb_old, ctts_data_old, ctts_count_old, search_timestamp, 0, + &index, &ctts_index_old, &ctts_sample_old) < 0) { av_log(mov->fc, AV_LOG_WARNING, "st: %d edit list: %"PRId64" Missing key frame while searching for timestamp: %"PRId64"\n", st->index, edit_list_index, search_timestamp); - index = find_prev_closest_index(st, e_old, nb_old, search_timestamp, AVSEEK_FLAG_ANY); - - if (index == -1) { + if (find_prev_closest_index(st, e_old, nb_old, ctts_data_old, ctts_count_old, search_timestamp, AVSEEK_FLAG_ANY, + &index, &ctts_index_old, &ctts_sample_old) < 0) { av_log(mov->fc, AV_LOG_WARNING, "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n" "Rounding edit list media time to zero.\n", st->index, edit_list_index, search_timestamp); index = 0; + ctts_index_old = 0; + ctts_sample_old = 0; edit_list_media_time = 0; } } current = e_old + index; - - ctts_index_old = 0; - ctts_sample_old = 0; - - // set ctts_index properly for the found key frame - for (index_ctts_count = 0; index_ctts_count < index; index_ctts_count++) { - if (ctts_data_old && ctts_index_old < ctts_count_old) { - ctts_sample_old++; - if (ctts_data_old[ctts_index_old].count == ctts_sample_old) { - ctts_index_old++; - ctts_sample_old = 0; - } - } - } - edit_list_start_ctts_sample = ctts_sample_old; // Iterate over index and arrange it according to edit list diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 6815e4feca7c3..01893a076756d 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -9,6 +9,7 @@ FATE_MOV = fate-mov-3elist \ fate-mov-invalid-elst-entry-count \ fate-mov-gpmf-remux \ fate-mov-440hz-10ms \ + fate-mov-ibi-elst-starts-b \ FATE_MOV_FFPROBE = fate-mov-aac-2048-priming \ fate-mov-zombie \ @@ -47,6 +48,13 @@ fate-mov-440hz-10ms: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/440hz-10ms.m4a # Makes sure that we handle invalid edit list entry count correctly. fate-mov-invalid-elst-entry-count: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/mov/invalid_elst_entry_count.mov +# Makes sure that 1st key-frame is picked when, +# i) One B-frame between 2 key-frames +# ii) Edit list starts on B-frame. +# iii) Both key-frames have their DTS < edit list start +# i.e. Pts Order: I-B-I +fate-mov-ibi-elst-starts-b: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/mov/mov_ibi_elst_starts_b.mov + fate-mov-aac-2048-priming: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_packets -print_format compact $(TARGET_SAMPLES)/mov/aac-2048-priming.mov fate-mov-zombie: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_streams -show_packets -show_frames -bitexact -print_format compact $(TARGET_SAMPLES)/mov/white_zombie_scrunch-part.mov diff --git a/tests/ref/fate/mov-ibi-elst-starts-b b/tests/ref/fate/mov-ibi-elst-starts-b new file mode 100644 index 0000000000000..1ab9c2a51db1a --- /dev/null +++ b/tests/ref/fate/mov-ibi-elst-starts-b @@ -0,0 +1,33 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 115200, 7e20f8729b6b53dc11791927bf4a5aec +0, 1, 1, 1, 115200, 4e5dc2b806e394cd666c968f736fecd0 +0, 2, 2, 1, 115200, 7a3c7473d44c5f60c07655f6fc0c2ac3 +0, 3, 3, 1, 115200, 038254422a603a3270c09cdcd149707b +0, 4, 4, 1, 115200, 7553b6b4547cb23ef8f0392ed5a5d4b0 +0, 5, 5, 1, 115200, 6d017ede7f446124af7308667cb0dc41 +0, 6, 6, 1, 115200, 77752f0288ae64f857732b8e62e47457 +0, 7, 7, 1, 115200, d656833951af99330625f7c6de7685c4 +0, 8, 8, 1, 115200, 14338b833e431e566ac98da841600bfe +0, 9, 9, 1, 115200, 07ea95d1659f3c4424a470a546d0df6e +0, 10, 10, 1, 115200, fd05b8cc83072f813e89d394d1f6efc6 +0, 11, 11, 1, 115200, 750b82ca5c7e901545e7b1aa69692426 +0, 12, 12, 1, 115200, 7347679ab09bc936047368b8caebcaff +0, 13, 13, 1, 115200, 63a23fdd57ac8462b9ffbcb12ab717b3 +0, 14, 14, 1, 115200, 705257a1c99693db233e2a3ee027adcf +0, 15, 15, 1, 115200, df861a2ec7a4ef70e82b1c28025e5a48 +0, 16, 16, 1, 115200, 2a8b403c077b6b43aa71eaf7d1537713 +0, 17, 17, 1, 115200, 973b5cd3ce473e3970dfa96045553172 +0, 18, 18, 1, 115200, fc612c0afeae3b6576b5ee2f3f119832 +0, 19, 19, 1, 115200, 97074fe5a0b6e7e8470729654092e56c +0, 20, 20, 1, 115200, 8cf9337201065335b3aa4da21dc9b37a +0, 21, 21, 1, 115200, 93ff3589294cc0673af3daee1e7fe42a +0, 22, 22, 1, 115200, c0b6fd870a022f374f9d6c697e8e293d +0, 23, 23, 1, 115200, bc4638ff7036b323c39a948a6407695d From 5cb261301c1d2114951ae0e9bea07ec1b8fbbd96 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Fri, 3 Nov 2017 10:39:18 +0530 Subject: [PATCH 0737/2557] avcodec/mips: Improve avc avg mc 20, 21 and 23 msa functions Load the specific destination bytes instead of MSA load and pack. Remove unused macros and functions. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/h264qpel_msa.c | 1274 +++++++++++++++++++++----------- 1 file changed, 834 insertions(+), 440 deletions(-) diff --git a/libavcodec/mips/h264qpel_msa.c b/libavcodec/mips/h264qpel_msa.c index 3df72f591c4ff..dd11f00d8e0b3 100644 --- a/libavcodec/mips/h264qpel_msa.c +++ b/libavcodec/mips/h264qpel_msa.c @@ -21,30 +21,6 @@ #include "libavutil/mips/generic_macros_msa.h" #include "h264dsp_mips.h" -#define AVC_CALC_DPADD_H_6PIX_2COEFF_SH(in0, in1, in2, in3, in4, in5) \ -( { \ - v4i32 tmp0_m, tmp1_m; \ - v8i16 out0_m, out1_m, out2_m, out3_m; \ - v8i16 minus5h_m = __msa_ldi_h(-5); \ - v8i16 plus20h_m = __msa_ldi_h(20); \ - \ - ILVRL_H2_SW(in5, in0, tmp0_m, tmp1_m); \ - \ - tmp0_m = __msa_hadd_s_w((v8i16) tmp0_m, (v8i16) tmp0_m); \ - tmp1_m = __msa_hadd_s_w((v8i16) tmp1_m, (v8i16) tmp1_m); \ - \ - ILVRL_H2_SH(in1, in4, out0_m, out1_m); \ - DPADD_SH2_SW(out0_m, out1_m, minus5h_m, minus5h_m, tmp0_m, tmp1_m); \ - ILVRL_H2_SH(in2, in3, out2_m, out3_m); \ - DPADD_SH2_SW(out2_m, out3_m, plus20h_m, plus20h_m, tmp0_m, tmp1_m); \ - \ - SRARI_W2_SW(tmp0_m, tmp1_m, 10); \ - SAT_SW2_SW(tmp0_m, tmp1_m, 7); \ - out0_m = __msa_pckev_h((v8i16) tmp1_m, (v8i16) tmp0_m); \ - \ - out0_m; \ -} ) - static const uint8_t luma_mask_arr[16 * 8] = { /* 8 width cases */ 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, @@ -75,44 +51,6 @@ static const uint8_t luma_mask_arr[16 * 8] = { DPADD_SB2_SH(tmp0_m, tmp1_m, plus20b_m, plus20b_m, out1, out2); \ } -#define AVC_CALC_DPADD_H_6PIX_2COEFF_R_SH(vec0, vec1, vec2, vec3, vec4, vec5) \ -( { \ - v4i32 tmp1_m; \ - v8i16 tmp2_m, tmp3_m; \ - v8i16 minus5h_m = __msa_ldi_h(-5); \ - v8i16 plus20h_m = __msa_ldi_h(20); \ - \ - tmp1_m = (v4i32) __msa_ilvr_h((v8i16) vec5, (v8i16) vec0); \ - tmp1_m = __msa_hadd_s_w((v8i16) tmp1_m, (v8i16) tmp1_m); \ - \ - ILVR_H2_SH(vec1, vec4, vec2, vec3, tmp2_m, tmp3_m); \ - DPADD_SH2_SW(tmp2_m, tmp3_m, minus5h_m, plus20h_m, tmp1_m, tmp1_m); \ - \ - tmp1_m = __msa_srari_w(tmp1_m, 10); \ - tmp1_m = __msa_sat_s_w(tmp1_m, 7); \ - \ - tmp2_m = __msa_pckev_h((v8i16) tmp1_m, (v8i16) tmp1_m); \ - \ - tmp2_m; \ -} ) - -#define AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src0, src1, \ - mask0, mask1, mask2) \ -( { \ - v8i16 hz_out_m; \ - v16i8 vec0_m, vec1_m, vec2_m; \ - v16i8 minus5b_m = __msa_ldi_b(-5); \ - v16i8 plus20b_m = __msa_ldi_b(20); \ - \ - vec0_m = __msa_vshf_b((v16i8) mask0, (v16i8) src1, (v16i8) src0); \ - hz_out_m = __msa_hadd_s_h(vec0_m, vec0_m); \ - \ - VSHF_B2_SB(src0, src1, src0, src1, mask1, mask2, vec1_m, vec2_m); \ - DPADD_SB2_SH(vec1_m, vec2_m, minus5b_m, plus20b_m, hz_out_m, hz_out_m); \ - \ - hz_out_m; \ -} ) - #define AVC_HORZ_FILTER_SH(in0, in1, mask0, mask1, mask2) \ ( { \ v8i16 out0_m; \ @@ -418,150 +356,6 @@ static void avc_luma_hv_qrt_16x16_msa(const uint8_t *src_x, } } -static void avc_luma_hz_and_aver_dst_4x4_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, int32_t dst_stride) -{ - v16i8 src0, src1, src2, src3; - v16u8 dst0, dst1, dst2, dst3, res; - v8i16 res0, res1; - v16i8 mask0, mask1, mask2; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v16i8 minus5b = __msa_ldi_b(-5); - v16i8 plus20b = __msa_ldi_b(20); - - LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); - LD_SB4(src, src_stride, src0, src1, src2, src3); - - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B2_SB(src0, src1, src2, src3, mask0, mask0, vec0, vec1); - HADD_SB2_SH(vec0, vec1, res0, res1); - VSHF_B2_SB(src0, src1, src2, src3, mask1, mask1, vec2, vec3); - DPADD_SB2_SH(vec2, vec3, minus5b, minus5b, res0, res1); - VSHF_B2_SB(src0, src1, src2, src3, mask2, mask2, vec4, vec5); - DPADD_SB2_SH(vec4, vec5, plus20b, plus20b, res0, res1); - SRARI_H2_SH(res0, res1, 5); - SAT_SH2_SH(res0, res1, 7); - res = PCKEV_XORI128_UB(res0, res1); - ILVR_W2_UB(dst1, dst0, dst3, dst2, dst0, dst1); - - dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0); - res = __msa_aver_u_b(res, dst0); - - ST4x4_UB(res, res, 0, 1, 2, 3, dst, dst_stride); -} - -static void avc_luma_hz_and_aver_dst_8x8_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, int32_t dst_stride) -{ - uint32_t loop_cnt; - v16i8 src0, src1, src2, src3; - v16u8 dst0, dst1, dst2, dst3; - v8i16 res0, res1, res2, res3; - v16i8 mask0, mask1, mask2; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v16i8 vec6, vec7, vec8, vec9, vec10, vec11; - v16i8 minus5b = __msa_ldi_b(-5); - v16i8 plus20b = __msa_ldi_b(20); - - LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); - - for (loop_cnt = 2; loop_cnt--;) { - LD_SB4(src, src_stride, src0, src1, src2, src3); - src += (4 * src_stride); - - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - - XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); - VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); - HADD_SB4_SH(vec0, vec1, vec2, vec3, res0, res1, res2, res3); - VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec4, vec5); - VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec6, vec7); - DPADD_SB4_SH(vec4, vec5, vec6, vec7, minus5b, minus5b, minus5b, minus5b, - res0, res1, res2, res3); - VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec8, vec9); - VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec10, vec11); - DPADD_SB4_SH(vec8, vec9, vec10, vec11, plus20b, plus20b, plus20b, - plus20b, res0, res1, res2, res3); - SRARI_H4_SH(res0, res1, res2, res3, 5); - SAT_SH4_SH(res0, res1, res2, res3, 7); - ILVR_D2_UB(dst1, dst0, dst3, dst2, dst0, dst1); - CONVERT_UB_AVG_ST8x4_UB(res0, res1, res2, res3, dst0, dst1, - dst, dst_stride); - - dst += (4 * dst_stride); - } -} - -static void avc_luma_hz_and_aver_dst_16x16_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, int32_t dst_stride) -{ - uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7; - v16u8 dst0, dst1, dst2, dst3; - v16i8 mask0, mask1, mask2; - v8i16 res0, res1, res2, res3, res4, res5, res6, res7; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v16i8 vec6, vec7, vec8, vec9, vec10, vec11; - v16i8 minus5b = __msa_ldi_b(-5); - v16i8 plus20b = __msa_ldi_b(20); - - LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); - - for (loop_cnt = 4; loop_cnt--;) { - LD_SB2(src, 8, src0, src1); - src += src_stride; - LD_SB2(src, 8, src2, src3); - src += src_stride; - - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - - XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec3); - VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec6, vec9); - VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec1, vec4); - VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec7, vec10); - VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec2, vec5); - VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec8, vec11); - HADD_SB4_SH(vec0, vec3, vec6, vec9, res0, res1, res2, res3); - DPADD_SB4_SH(vec1, vec4, vec7, vec10, minus5b, minus5b, minus5b, - minus5b, res0, res1, res2, res3); - DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, - plus20b, res0, res1, res2, res3); - LD_SB2(src, 8, src4, src5); - src += src_stride; - LD_SB2(src, 8, src6, src7); - src += src_stride; - XORI_B4_128_SB(src4, src5, src6, src7); - VSHF_B2_SB(src4, src4, src5, src5, mask0, mask0, vec0, vec3); - VSHF_B2_SB(src6, src6, src7, src7, mask0, mask0, vec6, vec9); - VSHF_B2_SB(src4, src4, src5, src5, mask1, mask1, vec1, vec4); - VSHF_B2_SB(src6, src6, src7, src7, mask1, mask1, vec7, vec10); - VSHF_B2_SB(src4, src4, src5, src5, mask2, mask2, vec2, vec5); - VSHF_B2_SB(src6, src6, src7, src7, mask2, mask2, vec8, vec11); - HADD_SB4_SH(vec0, vec3, vec6, vec9, res4, res5, res6, res7); - DPADD_SB4_SH(vec1, vec4, vec7, vec10, minus5b, minus5b, minus5b, - minus5b, res4, res5, res6, res7); - DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, - plus20b, res4, res5, res6, res7); - SRARI_H4_SH(res0, res1, res2, res3, 5); - SRARI_H4_SH(res4, res5, res6, res7, 5); - SAT_SH4_SH(res0, res1, res2, res3, 7); - SAT_SH4_SH(res4, res5, res6, res7, 7); - PCKEV_B4_SB(res1, res0, res3, res2, res5, res4, res7, res6, - vec0, vec1, vec2, vec3); - XORI_B4_128_SB(vec0, vec1, vec2, vec3); - AVER_UB4_UB(vec0, dst0, vec1, dst1, vec2, dst2, vec3, dst3, - dst0, dst1, dst2, dst3); - ST_UB4(dst0, dst1, dst2, dst3, dst, dst_stride); - dst += (4 * dst_stride); - } -} - static void avc_luma_hz_qrt_and_aver_dst_4x4_msa(const uint8_t *src, int32_t src_stride, uint8_t *dst, @@ -970,184 +764,6 @@ static void avc_luma_vt_qrt_and_aver_dst_16x16_msa(const uint8_t *src, } } -static void avc_luma_midv_qrt_and_aver_dst_4w_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - int32_t height, - uint8_t ver_offset) -{ - int32_t loop_cnt; - int32_t out0, out1; - v16i8 src0, src1, src2, src3, src4; - v16u8 dst0, dst1; - v16i8 mask0, mask1, mask2; - v8i16 hz_out0, hz_out1, hz_out2, hz_out3; - v8i16 hz_out4, hz_out5, hz_out6; - v8i16 res0, res1, res2, res3; - v16u8 vec0, vec1; - - LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - src += (5 * src_stride); - - XORI_B5_128_SB(src0, src1, src2, src3, src4); - - hz_out0 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src0, src1, - mask0, mask1, mask2); - hz_out2 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src2, src3, - mask0, mask1, mask2); - - PCKOD_D2_SH(hz_out0, hz_out0, hz_out2, hz_out2, hz_out1, hz_out3); - - hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); - - for (loop_cnt = (height >> 1); loop_cnt--;) { - LD_SB2(src, src_stride, src0, src1); - src += (2 * src_stride); - - XORI_B2_128_SB(src0, src1); - LD_UB2(dst, dst_stride, dst0, dst1); - hz_out5 = AVC_XOR_VSHF_B_AND_APPLY_6TAP_HORIZ_FILT_SH(src0, src1, - mask0, mask1, - mask2); - hz_out6 = (v8i16) __msa_pckod_d((v2i64) hz_out5, (v2i64) hz_out5); - res0 = AVC_CALC_DPADD_H_6PIX_2COEFF_R_SH(hz_out0, hz_out1, hz_out2, - hz_out3, hz_out4, hz_out5); - res2 = AVC_CALC_DPADD_H_6PIX_2COEFF_R_SH(hz_out1, hz_out2, hz_out3, - hz_out4, hz_out5, hz_out6); - - if (ver_offset) { - res1 = __msa_srari_h(hz_out3, 5); - res3 = __msa_srari_h(hz_out4, 5); - } else { - res1 = __msa_srari_h(hz_out2, 5); - res3 = __msa_srari_h(hz_out3, 5); - } - - SAT_SH2_SH(res1, res3, 7); - - res0 = __msa_aver_s_h(res0, res1); - res1 = __msa_aver_s_h(res2, res3); - - vec0 = PCKEV_XORI128_UB(res0, res0); - vec1 = PCKEV_XORI128_UB(res1, res1); - - AVER_UB2_UB(vec0, dst0, vec1, dst1, dst0, dst1); - - out0 = __msa_copy_u_w((v4i32) dst0, 0); - out1 = __msa_copy_u_w((v4i32) dst1, 0); - SW(out0, dst); - dst += dst_stride; - SW(out1, dst); - dst += dst_stride; - - hz_out0 = hz_out2; - hz_out1 = hz_out3; - hz_out2 = hz_out4; - hz_out3 = hz_out5; - hz_out4 = hz_out6; - } -} - -static void avc_luma_midv_qrt_and_aver_dst_8w_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - int32_t height, - uint8_t vert_offset) -{ - int32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4; - v16u8 dst0, dst1, dst2, dst3; - v16i8 mask0, mask1, mask2; - v8i16 hz_out0, hz_out1, hz_out2, hz_out3; - v8i16 hz_out4, hz_out5, hz_out6, hz_out7, hz_out8; - v8i16 res0, res1, res2, res3; - v8i16 res4, res5, res6, res7; - - LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); - - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - XORI_B5_128_SB(src0, src1, src2, src3, src4); - src += (5 * src_stride); - - hz_out0 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); - hz_out1 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); - hz_out2 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); - hz_out3 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); - hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); - - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB4(src, src_stride, src0, src1, src2, src3); - XORI_B4_128_SB(src0, src1, src2, src3); - src += (4 * src_stride); - - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - - hz_out5 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); - hz_out6 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); - hz_out7 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); - hz_out8 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); - - res0 = AVC_CALC_DPADD_H_6PIX_2COEFF_SH(hz_out0, hz_out1, hz_out2, - hz_out3, hz_out4, hz_out5); - res2 = AVC_CALC_DPADD_H_6PIX_2COEFF_SH(hz_out1, hz_out2, hz_out3, - hz_out4, hz_out5, hz_out6); - res4 = AVC_CALC_DPADD_H_6PIX_2COEFF_SH(hz_out2, hz_out3, hz_out4, - hz_out5, hz_out6, hz_out7); - res6 = AVC_CALC_DPADD_H_6PIX_2COEFF_SH(hz_out3, hz_out4, hz_out5, - hz_out6, hz_out7, hz_out8); - - if (vert_offset) { - res1 = __msa_srari_h(hz_out3, 5); - res3 = __msa_srari_h(hz_out4, 5); - res5 = __msa_srari_h(hz_out5, 5); - res7 = __msa_srari_h(hz_out6, 5); - } else { - res1 = __msa_srari_h(hz_out2, 5); - res3 = __msa_srari_h(hz_out3, 5); - res5 = __msa_srari_h(hz_out4, 5); - res7 = __msa_srari_h(hz_out5, 5); - } - - SAT_SH4_SH(res1, res3, res5, res7, 7); - - res0 = __msa_aver_s_h(res0, res1); - res1 = __msa_aver_s_h(res2, res3); - res2 = __msa_aver_s_h(res4, res5); - res3 = __msa_aver_s_h(res6, res7); - ILVR_D2_UB(dst1, dst0, dst3, dst2, dst0, dst1); - CONVERT_UB_AVG_ST8x4_UB(res0, res1, res2, res3, dst0, dst1, - dst, dst_stride); - dst += (4 * dst_stride); - - hz_out0 = hz_out4; - hz_out1 = hz_out5; - hz_out2 = hz_out6; - hz_out3 = hz_out7; - hz_out4 = hz_out8; - } -} - -static void avc_luma_midv_qrt_and_aver_dst_16w_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - int32_t height, - uint8_t vert_offset) -{ - int32_t multiple8_cnt; - - for (multiple8_cnt = 2; multiple8_cnt--;) { - avc_luma_midv_qrt_and_aver_dst_8w_msa(src, src_stride, dst, dst_stride, - height, vert_offset); - - src += 8; - dst += 8; - } -} - static void avc_luma_hv_qrt_and_aver_dst_4x4_msa(const uint8_t *src_x, const uint8_t *src_y, uint8_t *dst, @@ -3978,37 +3594,169 @@ void ff_avg_h264_qpel4_mc30_msa(uint8_t *dst, const uint8_t *src, void ff_avg_h264_qpel16_mc20_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_hz_and_aver_dst_16x16_msa(src - 2, stride, dst, stride); -} - -void ff_avg_h264_qpel8_mc20_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_hz_and_aver_dst_8x8_msa(src - 2, stride, dst, stride); -} - -void ff_avg_h264_qpel4_mc20_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_hz_and_aver_dst_4x4_msa(src - 2, stride, dst, stride); -} + uint32_t loop_cnt; + v16u8 dst0, dst1, dst2, dst3; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, mask0, mask1, mask2; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9, vec10; + v16i8 vec11; + v8i16 res0, res1, res2, res3, res4, res5, res6, res7; + v16i8 minus5b = __msa_ldi_b(-5); + v16i8 plus20b = __msa_ldi_b(20); -void ff_avg_h264_qpel16_mc01_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_vt_qrt_and_aver_dst_16x16_msa(src - (stride * 2), - stride, dst, stride, 0); -} + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + src -= 2; -void ff_avg_h264_qpel16_mc03_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_vt_qrt_and_aver_dst_16x16_msa(src - (stride * 2), - stride, dst, stride, 1); -} + for (loop_cnt = 4; loop_cnt--;) { + LD_SB2(src, 8, src0, src1); + src += stride; + LD_SB2(src, 8, src2, src3); + src += stride; + LD_SB2(src, 8, src4, src5); + src += stride; + LD_SB2(src, 8, src6, src7); + src += stride; -void ff_avg_h264_qpel8_mc01_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) + LD_UB4(dst, stride, dst0, dst1, dst2, dst3); + XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec3); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec6, vec9); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec1, vec4); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec7, vec10); + VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec2, vec5); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec8, vec11); + HADD_SB4_SH(vec0, vec3, vec6, vec9, res0, res1, res2, res3); + DPADD_SB4_SH(vec1, vec4, vec7, vec10, minus5b, minus5b, minus5b, + minus5b, res0, res1, res2, res3); + DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, + plus20b, res0, res1, res2, res3); + VSHF_B2_SB(src4, src4, src5, src5, mask0, mask0, vec0, vec3); + VSHF_B2_SB(src6, src6, src7, src7, mask0, mask0, vec6, vec9); + VSHF_B2_SB(src4, src4, src5, src5, mask1, mask1, vec1, vec4); + VSHF_B2_SB(src6, src6, src7, src7, mask1, mask1, vec7, vec10); + VSHF_B2_SB(src4, src4, src5, src5, mask2, mask2, vec2, vec5); + VSHF_B2_SB(src6, src6, src7, src7, mask2, mask2, vec8, vec11); + HADD_SB4_SH(vec0, vec3, vec6, vec9, res4, res5, res6, res7); + DPADD_SB4_SH(vec1, vec4, vec7, vec10, minus5b, minus5b, minus5b, + minus5b, res4, res5, res6, res7); + DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, + plus20b, res4, res5, res6, res7); + SRARI_H4_SH(res0, res1, res2, res3, 5); + SRARI_H4_SH(res4, res5, res6, res7, 5); + SAT_SH4_SH(res0, res1, res2, res3, 7); + SAT_SH4_SH(res4, res5, res6, res7, 7); + PCKEV_B4_SB(res1, res0, res3, res2, res5, res4, res7, res6, vec0, vec1, + vec2, vec3); + XORI_B4_128_SB(vec0, vec1, vec2, vec3); + AVER_UB2_UB(vec0, dst0, vec1, dst1, dst0, dst1); + AVER_UB2_UB(vec2, dst2, vec3, dst3, dst2, dst3); + ST_UB4(dst0, dst1, dst2, dst3, dst, stride); + dst += (4 * stride); + } +} + +void ff_avg_h264_qpel8_mc20_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint64_t tp0, tp1, tp2, tp3; + v16u8 out0, out1, out2 = { 0 }, out3 = { 0 }; + v16u8 out4, out5, out6 = { 0 }, out7 = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, mask0, mask1, mask2; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9, vec10; + v16i8 vec11; + v8i16 res0, res1, res2, res3, res4, res5, res6, res7; + v16i8 minus5b = __msa_ldi_b(-5); + v16i8 plus20b = __msa_ldi_b(20); + + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + + LD_SB8(src - 2, stride, src0, src1, src2, src3, src4, src5, src6, src7); + XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); + HADD_SB4_SH(vec0, vec1, vec2, vec3, res0, res1, res2, res3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec4, vec5); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec6, vec7); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, minus5b, minus5b, minus5b, minus5b, + res0, res1, res2, res3); + VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec8, vec9); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec10, vec11); + DPADD_SB4_SH(vec8, vec9, vec10, vec11, plus20b, plus20b, plus20b, plus20b, + res0, res1, res2, res3); + VSHF_B2_SB(src4, src4, src5, src5, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src6, src6, src7, src7, mask0, mask0, vec2, vec3); + HADD_SB4_SH(vec0, vec1, vec2, vec3, res4, res5, res6, res7); + VSHF_B2_SB(src4, src4, src5, src5, mask1, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src7, src7, mask1, mask1, vec6, vec7); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, minus5b, minus5b, minus5b, minus5b, + res4, res5, res6, res7); + VSHF_B2_SB(src4, src4, src5, src5, mask2, mask2, vec8, vec9); + VSHF_B2_SB(src6, src6, src7, src7, mask2, mask2, vec10, vec11); + DPADD_SB4_SH(vec8, vec9, vec10, vec11, plus20b, plus20b, plus20b, plus20b, + res4, res5, res6, res7); + SRARI_H4_SH(res0, res1, res2, res3, 5); + SRARI_H4_SH(res4, res5, res6, res7, 5); + SAT_SH4_SH(res0, res1, res2, res3, 7); + SAT_SH4_SH(res4, res5, res6, res7, 7); + out0 = PCKEV_XORI128_UB(res0, res1); + out1 = PCKEV_XORI128_UB(res2, res3); + out4 = PCKEV_XORI128_UB(res4, res5); + out5 = PCKEV_XORI128_UB(res6, res7); + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, out2); + INSERT_D2_UB(tp2, tp3, out3); + LD4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, out6); + INSERT_D2_UB(tp2, tp3, out7); + AVER_UB2_UB(out0, out2, out1, out3, out0, out1); + AVER_UB2_UB(out4, out6, out5, out7, out4, out5); + ST8x8_UB(out0, out1, out4, out5, dst, stride); +} + +void ff_avg_h264_qpel4_mc20_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint32_t tp0, tp1, tp2, tp3; + v16u8 res, dst0 = { 0 }; + v16i8 src0, src1, src2, src3, vec0, vec1, vec2, vec3, vec4, vec5; + v16i8 mask0, mask1, mask2; + v8i16 res0, res1; + v16i8 minus5b = __msa_ldi_b(-5); + v16i8 plus20b = __msa_ldi_b(20); + + LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); + LD_SB4(src - 2, stride, src0, src1, src2, src3); + XORI_B4_128_SB(src0, src1, src2, src3); + VSHF_B2_SB(src0, src1, src2, src3, mask0, mask0, vec0, vec1); + HADD_SB2_SH(vec0, vec1, res0, res1); + VSHF_B2_SB(src0, src1, src2, src3, mask1, mask1, vec2, vec3); + DPADD_SB2_SH(vec2, vec3, minus5b, minus5b, res0, res1); + VSHF_B2_SB(src0, src1, src2, src3, mask2, mask2, vec4, vec5); + DPADD_SB2_SH(vec4, vec5, plus20b, plus20b, res0, res1); + SRARI_H2_SH(res0, res1, 5); + SAT_SH2_SH(res0, res1, 7); + res = PCKEV_XORI128_UB(res0, res1); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); + res = __msa_aver_u_b(res, dst0); + ST4x4_UB(res, res, 0, 1, 2, 3, dst, stride); +} + +void ff_avg_h264_qpel16_mc01_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_vt_qrt_and_aver_dst_16x16_msa(src - (stride * 2), + stride, dst, stride, 0); +} + +void ff_avg_h264_qpel16_mc03_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_vt_qrt_and_aver_dst_16x16_msa(src - (stride * 2), + stride, dst, stride, 1); +} + +void ff_avg_h264_qpel8_mc01_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) { avc_luma_vt_qrt_and_aver_dst_8x8_msa(src - (stride * 2), stride, dst, stride, 0); @@ -4137,43 +3885,689 @@ void ff_avg_h264_qpel4_mc33_msa(uint8_t *dst, const uint8_t *src, void ff_avg_h264_qpel16_mc21_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_midv_qrt_and_aver_dst_16w_msa(src - (2 * stride) - 2, - stride, dst, stride, 16, 0); + uint64_t tp0, tp1, tp2, tp3; + uint8_t *dst_tmp = dst; + const uint8_t *src_tmp = src - (2 * stride) - 2; + uint32_t multiple8_cnt, loop_cnt; + const int32_t filt_const0 = 0xfffb0001; + const int32_t filt_const1 = 0x140014; + const int32_t filt_const2 = 0x1fffb; + v16u8 out0, out1, dst0 = { 0 }, dst1 = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, mask0, mask1; + v16i8 mask2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + v8i16 hz_out7, hz_out8, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + v8i16 hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r, hz_out54_r; + v8i16 hz_out65_r, hz_out76_r, hz_out87_r, hz_out10_l, hz_out21_l; + v8i16 hz_out32_l, hz_out43_l, hz_out54_l, hz_out65_l, hz_out76_l; + v8i16 hz_out87_l, filt0, filt1, filt2; + v4i32 tmp0_w, tmp1_w; + + filt0 = (v8i16) __msa_fill_w(filt_const0); + filt1 = (v8i16) __msa_fill_w(filt_const1); + filt2 = (v8i16) __msa_fill_w(filt_const2); + + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + + for (multiple8_cnt = 2; multiple8_cnt--;) { + dst = dst_tmp; + src = src_tmp; + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + src += (5 * stride); + + hz_out0 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB2(src, stride, src5, src6); + src += (2 * stride); + + XORI_B2_128_SB(src5, src6); + hz_out5 = AVC_HORZ_FILTER_SH(src5, src5, mask0, mask1, mask2); + hz_out6 = AVC_HORZ_FILTER_SH(src6, src6, mask0, mask1, mask2); + ILVR_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, + hz_out4, hz_out3, hz_out10_r, hz_out21_r, hz_out32_r, + hz_out43_r); + ILVL_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, + hz_out4, hz_out3, hz_out10_l, hz_out21_l, hz_out32_l, + hz_out43_l); + ILVR_H2_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out54_r, + hz_out65_r); + ILVL_H2_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out54_l, + hz_out65_l); + tmp0_w = AVC_DOT_SW3_SW(hz_out10_r, hz_out32_r, hz_out54_r, filt0, + filt1, filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out10_l, hz_out32_l, hz_out54_l, filt0, + filt1, filt2); + tmp0 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out21_r, hz_out43_r, hz_out65_r, filt0, + filt1, filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out21_l, hz_out43_l, hz_out65_l, filt0, + filt1, filt2); + tmp2 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + + tmp1 = __msa_srari_h(hz_out2, 5); + tmp3 = __msa_srari_h(hz_out3, 5); + SAT_SH2_SH(tmp1, tmp3, 7); + + tmp0 = __msa_aver_s_h(tmp0, tmp1); + tmp1 = __msa_aver_s_h(tmp2, tmp3); + + LD2(dst, stride, tp0, tp1); + INSERT_D2_UB(tp0, tp1, dst0); + + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + dst0 = __msa_aver_u_b(out0, dst0); + ST8x2_UB(dst0, dst, stride); + dst += (2 * stride); + + LD_SB2(src, stride, src7, src8); + src += (2 * stride); + + XORI_B2_128_SB(src7, src8); + hz_out7 = AVC_HORZ_FILTER_SH(src7, src7, mask0, mask1, mask2); + hz_out8 = AVC_HORZ_FILTER_SH(src8, src8, mask0, mask1, mask2); + ILVR_H2_SH(hz_out7, hz_out6, hz_out8, hz_out7, hz_out76_r, + hz_out87_r); + ILVL_H2_SH(hz_out7, hz_out6, hz_out8, hz_out7, hz_out76_l, + hz_out87_l); + tmp0_w = AVC_DOT_SW3_SW(hz_out32_r, hz_out54_r, hz_out76_r, filt0, + filt1, filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out32_l, hz_out54_l, hz_out76_l, filt0, + filt1, filt2); + tmp4 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out43_r, hz_out65_r, hz_out87_r, filt0, + filt1, filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out43_l, hz_out65_l, hz_out87_l, filt0, + filt1, filt2); + tmp6 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + + tmp5 = __msa_srari_h(hz_out4, 5); + tmp7 = __msa_srari_h(hz_out5, 5); + SAT_SH2_SH(tmp5, tmp7, 7); + + tmp2 = __msa_aver_s_h(tmp4, tmp5); + tmp3 = __msa_aver_s_h(tmp6, tmp7); + + LD2(dst, stride, tp2, tp3); + INSERT_D2_UB(tp2, tp3, dst1); + + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + dst1 = __msa_aver_u_b(out1, dst1); + ST8x2_UB(dst1, dst, stride); + dst += (2 * stride); + + hz_out0 = hz_out4; + hz_out1 = hz_out5; + hz_out2 = hz_out6; + hz_out3 = hz_out7; + hz_out4 = hz_out8; + } + + src_tmp += 8; + dst_tmp += 8; + } } void ff_avg_h264_qpel16_mc23_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_midv_qrt_and_aver_dst_16w_msa(src - (2 * stride) - 2, - stride, dst, stride, 16, 1); -} + uint64_t tp0, tp1, tp2, tp3; + uint8_t *dst_tmp = dst; + const uint8_t *src_tmp = src - (2 * stride) - 2; + uint32_t multiple8_cnt, loop_cnt; + const int32_t filt_const0 = 0xfffb0001; + const int32_t filt_const1 = 0x140014; + const int32_t filt_const2 = 0x1fffb; + v16u8 out0, out1, dst0 = { 0 }, dst1 = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, mask0, mask1; + v16i8 mask2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + v8i16 hz_out7, hz_out8, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + v8i16 hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r, hz_out54_r; + v8i16 hz_out65_r, hz_out76_r, hz_out87_r, hz_out10_l, hz_out21_l; + v8i16 hz_out32_l, hz_out43_l, hz_out54_l, hz_out65_l, hz_out76_l; + v8i16 hz_out87_l, filt0, filt1, filt2; + v4i32 tmp0_w, tmp1_w; -void ff_avg_h264_qpel8_mc21_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_midv_qrt_and_aver_dst_8w_msa(src - (2 * stride) - 2, - stride, dst, stride, 8, 0); -} + filt0 = (v8i16) __msa_fill_w(filt_const0); + filt1 = (v8i16) __msa_fill_w(filt_const1); + filt2 = (v8i16) __msa_fill_w(filt_const2); -void ff_avg_h264_qpel8_mc23_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_midv_qrt_and_aver_dst_8w_msa(src - (2 * stride) - 2, - stride, dst, stride, 8, 1); -} + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); -void ff_avg_h264_qpel4_mc21_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_midv_qrt_and_aver_dst_4w_msa(src - (2 * stride) - 2, - stride, dst, stride, 4, 0); -} + for (multiple8_cnt = 2; multiple8_cnt--;) { + dst = dst_tmp; + src = src_tmp; -void ff_avg_h264_qpel4_mc23_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_midv_qrt_and_aver_dst_4w_msa(src - (2 * stride) - 2, - stride, dst, stride, 4, 1); + LD_SB5(src, stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + src += (5 * stride); + + hz_out0 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB2(src, stride, src5, src6); + src += (2 * stride); + + XORI_B2_128_SB(src5, src6); + hz_out5 = AVC_HORZ_FILTER_SH(src5, src5, mask0, mask1, mask2); + hz_out6 = AVC_HORZ_FILTER_SH(src6, src6, mask0, mask1, mask2); + ILVR_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, + hz_out4, hz_out3, hz_out10_r, hz_out21_r, hz_out32_r, + hz_out43_r); + ILVL_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, + hz_out4, hz_out3, hz_out10_l, hz_out21_l, hz_out32_l, + hz_out43_l); + ILVR_H2_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out54_r, hz_out65_r); + ILVL_H2_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out54_l, hz_out65_l); + + tmp0_w = AVC_DOT_SW3_SW(hz_out10_r, hz_out32_r, hz_out54_r, filt0, + filt1, filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out10_l, hz_out32_l, hz_out54_l, filt0, + filt1, filt2); + tmp0 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out21_r, hz_out43_r, hz_out65_r, filt0, + filt1, filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out21_l, hz_out43_l, hz_out65_l, filt0, + filt1, filt2); + tmp2 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + + tmp1 = __msa_srari_h(hz_out3, 5); + tmp3 = __msa_srari_h(hz_out4, 5); + SAT_SH2_SH(tmp1, tmp3, 7); + + tmp0 = __msa_aver_s_h(tmp0, tmp1); + tmp1 = __msa_aver_s_h(tmp2, tmp3); + + LD2(dst, stride, tp0, tp1); + INSERT_D2_UB(tp0, tp1, dst0); + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + dst0 = __msa_aver_u_b(out0, dst0); + ST8x2_UB(dst0, dst, stride); + dst += (2 * stride); + + LD_SB2(src, stride, src7, src8); + src += (2 * stride); + + XORI_B2_128_SB(src7, src8); + hz_out7 = AVC_HORZ_FILTER_SH(src7, src7, mask0, mask1, mask2); + hz_out8 = AVC_HORZ_FILTER_SH(src8, src8, mask0, mask1, mask2); + ILVR_H2_SH(hz_out7, hz_out6, hz_out8, hz_out7, hz_out76_r, + hz_out87_r); + ILVL_H2_SH(hz_out7, hz_out6, hz_out8, hz_out7, hz_out76_l, + hz_out87_l); + tmp0_w = AVC_DOT_SW3_SW(hz_out32_r, hz_out54_r, hz_out76_r, filt0, + filt1, filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out32_l, hz_out54_l, hz_out76_l, filt0, + filt1, filt2); + tmp4 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out43_r, hz_out65_r, hz_out87_r, filt0, + filt1, filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out43_l, hz_out65_l, hz_out87_l, filt0, + filt1, filt2); + tmp6 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + + tmp5 = __msa_srari_h(hz_out5, 5); + tmp7 = __msa_srari_h(hz_out6, 5); + SAT_SH2_SH(tmp5, tmp7, 7); + + tmp2 = __msa_aver_s_h(tmp4, tmp5); + tmp3 = __msa_aver_s_h(tmp6, tmp7); + + LD2(dst, stride, tp2, tp3); + INSERT_D2_UB(tp2, tp3, dst1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + dst1 = __msa_aver_u_b(out1, dst1); + ST8x2_UB(dst1, dst, stride); + dst += (2 * stride); + + hz_out0 = hz_out4; + hz_out1 = hz_out5; + hz_out2 = hz_out6; + hz_out3 = hz_out7; + hz_out4 = hz_out8; + } + + src_tmp += 8; + dst_tmp += 8; + } +} + +void ff_avg_h264_qpel8_mc21_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + const int32_t filt_const0 = 0xfffb0001; + const int32_t filt_const1 = 0x140014; + const int32_t filt_const2 = 0x1fffb; + uint64_t tp0, tp1, tp2, tp3; + v16u8 dst0 = { 0 }, dst1 = { 0 }, out0, out1; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 src11, src12, mask0, mask1, mask2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + v8i16 hz_out7, hz_out8, hz_out9, hz_out10, hz_out11, hz_out12; + v8i16 hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r, hz_out54_r; + v8i16 hz_out65_r, hz_out76_r, hz_out87_r, hz_out89_r, hz_out910_r; + v8i16 hz_out1110_r, hz_out1211_r, tmp0, tmp1, tmp2, tmp3; + v8i16 hz_out10_l, hz_out21_l, hz_out32_l, hz_out43_l, hz_out54_l; + v8i16 hz_out65_l, hz_out76_l, hz_out87_l, hz_out89_l, hz_out910_l; + v8i16 hz_out1110_l, hz_out1211_l, filt0, filt1, filt2; + v4i32 tmp0_w, tmp1_w; + + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + + filt0 = (v8i16) __msa_fill_w(filt_const0); + filt1 = (v8i16) __msa_fill_w(filt_const1); + filt2 = (v8i16) __msa_fill_w(filt_const2); + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + src += (5 * stride); + + hz_out0 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); + + LD_SB4(src, stride, src5, src6, src7, src8); + src += (4 * stride); + XORI_B4_128_SB(src5, src6, src7, src8); + + hz_out5 = AVC_HORZ_FILTER_SH(src5, src5, mask0, mask1, mask2); + hz_out6 = AVC_HORZ_FILTER_SH(src6, src6, mask0, mask1, mask2); + hz_out7 = AVC_HORZ_FILTER_SH(src7, src7, mask0, mask1, mask2); + hz_out8 = AVC_HORZ_FILTER_SH(src8, src8, mask0, mask1, mask2); + + ILVR_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, hz_out4, + hz_out3, hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r); + ILVL_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, hz_out4, + hz_out3, hz_out10_l, hz_out21_l, hz_out32_l, hz_out43_l); + ILVR_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, hz_out8, + hz_out7, hz_out54_r, hz_out65_r, hz_out76_r, hz_out87_r); + ILVL_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, hz_out8, + hz_out7, hz_out54_l, hz_out65_l, hz_out76_l, hz_out87_l); + + tmp0_w = AVC_DOT_SW3_SW(hz_out10_r, hz_out32_r, hz_out54_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out10_l, hz_out32_l, hz_out54_l, filt0, filt1, + filt2); + tmp0 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out21_r, hz_out43_r, hz_out65_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out21_l, hz_out43_l, hz_out65_l, filt0, filt1, + filt2); + tmp1 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out32_r, hz_out54_r, hz_out76_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out32_l, hz_out54_l, hz_out76_l, filt0, filt1, + filt2); + tmp2 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out43_r, hz_out65_r, hz_out87_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out43_l, hz_out65_l, hz_out87_l, filt0, filt1, + filt2); + tmp3 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + + SRARI_H4_SH(hz_out2, hz_out3, hz_out4, hz_out5, 5); + SAT_SH4_SH(hz_out2, hz_out3, hz_out4, hz_out5, 7); + + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + + tmp0 = __msa_aver_s_h(tmp0, hz_out2); + tmp1 = __msa_aver_s_h(tmp1, hz_out3); + tmp2 = __msa_aver_s_h(tmp2, hz_out4); + tmp3 = __msa_aver_s_h(tmp3, hz_out5); + + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + AVER_UB2_UB(out0, dst0, out1, dst1, dst0, dst1); + ST8x4_UB(dst0, dst1, dst, stride); + dst += (4 * stride); + + LD_SB4(src, stride, src9, src10, src11, src12); + XORI_B4_128_SB(src9, src10, src11, src12); + hz_out9 = AVC_HORZ_FILTER_SH(src9, src9, mask0, mask1, mask2); + hz_out10 = AVC_HORZ_FILTER_SH(src10, src10, mask0, mask1, mask2); + hz_out11 = AVC_HORZ_FILTER_SH(src11, src11, mask0, mask1, mask2); + hz_out12 = AVC_HORZ_FILTER_SH(src12, src12, mask0, mask1, mask2); + ILVR_H4_SH(hz_out9, hz_out8, hz_out10, hz_out9, hz_out11, hz_out10, + hz_out12, hz_out11, hz_out89_r, hz_out910_r, hz_out1110_r, + hz_out1211_r); + ILVL_H4_SH(hz_out9, hz_out8, hz_out10, hz_out9, hz_out11, hz_out10, + hz_out12, hz_out11, hz_out89_l, hz_out910_l, hz_out1110_l, + hz_out1211_l); + tmp0_w = AVC_DOT_SW3_SW(hz_out54_r, hz_out76_r, hz_out89_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out54_l, hz_out76_l, hz_out89_l, filt0, filt1, + filt2); + tmp0 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out65_r, hz_out87_r, hz_out910_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out65_l, hz_out87_l, hz_out910_l, filt0, filt1, + filt2); + tmp1 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out76_r, hz_out89_r, hz_out1110_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out76_l, hz_out89_l, hz_out1110_l, filt0, filt1, + filt2); + tmp2 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out87_r, hz_out910_r, hz_out1211_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out87_l, hz_out910_l, hz_out1211_l, filt0, filt1, + filt2); + tmp3 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + + SRARI_H4_SH(hz_out6, hz_out7, hz_out8, hz_out9, 5); + SAT_SH4_SH(hz_out6, hz_out7, hz_out8, hz_out9, 7); + + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + + tmp0 = __msa_aver_s_h(tmp0, hz_out6); + tmp1 = __msa_aver_s_h(tmp1, hz_out7); + tmp2 = __msa_aver_s_h(tmp2, hz_out8); + tmp3 = __msa_aver_s_h(tmp3, hz_out9); + + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + AVER_UB2_UB(out0, dst0, out1, dst1, dst0, dst1); + ST8x4_UB(dst0, dst1, dst, stride); +} + +void ff_avg_h264_qpel8_mc23_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + const int32_t filt_const0 = 0xfffb0001; + const int32_t filt_const1 = 0x140014; + const int32_t filt_const2 = 0x1fffb; + uint64_t tp0, tp1, tp2, tp3; + v16u8 dst0 = { 0 }, dst1 = { 0 }, out0, out1; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 src11, src12, mask0, mask1, mask2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + v8i16 hz_out7, hz_out8, hz_out9, hz_out10, hz_out11, hz_out12; + v8i16 hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r, hz_out54_r; + v8i16 hz_out65_r, hz_out76_r, hz_out87_r, hz_out89_r, hz_out910_r; + v8i16 hz_out1110_r, hz_out1211_r, tmp0, tmp1, tmp2, tmp3; + v8i16 hz_out10_l, hz_out21_l, hz_out32_l, hz_out43_l, hz_out54_l; + v8i16 hz_out65_l, hz_out76_l, hz_out87_l, hz_out89_l, hz_out910_l; + v8i16 hz_out1110_l, hz_out1211_l, filt0, filt1, filt2; + v4i32 tmp0_w, tmp1_w; + + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + + filt0 = (v8i16) __msa_fill_w(filt_const0); + filt1 = (v8i16) __msa_fill_w(filt_const1); + filt2 = (v8i16) __msa_fill_w(filt_const2); + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + src += (5 * stride); + + hz_out0 = AVC_HORZ_FILTER_SH(src0, src0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src1, src1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src2, src2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src3, src3, mask0, mask1, mask2); + hz_out4 = AVC_HORZ_FILTER_SH(src4, src4, mask0, mask1, mask2); + + LD_SB4(src, stride, src5, src6, src7, src8); + src += (4 * stride); + XORI_B4_128_SB(src5, src6, src7, src8); + + hz_out5 = AVC_HORZ_FILTER_SH(src5, src5, mask0, mask1, mask2); + hz_out6 = AVC_HORZ_FILTER_SH(src6, src6, mask0, mask1, mask2); + hz_out7 = AVC_HORZ_FILTER_SH(src7, src7, mask0, mask1, mask2); + hz_out8 = AVC_HORZ_FILTER_SH(src8, src8, mask0, mask1, mask2); + + ILVR_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, hz_out4, + hz_out3, hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r); + ILVL_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, hz_out4, + hz_out3, hz_out10_l, hz_out21_l, hz_out32_l, hz_out43_l); + ILVR_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, hz_out8, + hz_out7, hz_out54_r, hz_out65_r, hz_out76_r, hz_out87_r); + ILVL_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, hz_out8, + hz_out7, hz_out54_l, hz_out65_l, hz_out76_l, hz_out87_l); + + tmp0_w = AVC_DOT_SW3_SW(hz_out10_r, hz_out32_r, hz_out54_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out10_l, hz_out32_l, hz_out54_l, filt0, filt1, + filt2); + tmp0 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out21_r, hz_out43_r, hz_out65_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out21_l, hz_out43_l, hz_out65_l, filt0, filt1, + filt2); + tmp1 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out32_r, hz_out54_r, hz_out76_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out32_l, hz_out54_l, hz_out76_l, filt0, filt1, + filt2); + tmp2 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out43_r, hz_out65_r, hz_out87_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out43_l, hz_out65_l, hz_out87_l, filt0, filt1, + filt2); + tmp3 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + + SRARI_H4_SH(hz_out3, hz_out4, hz_out5, hz_out6, 5); + SAT_SH4_SH(hz_out3, hz_out4, hz_out5, hz_out6, 7); + + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + + tmp0 = __msa_aver_s_h(tmp0, hz_out3); + tmp1 = __msa_aver_s_h(tmp1, hz_out4); + tmp2 = __msa_aver_s_h(tmp2, hz_out5); + tmp3 = __msa_aver_s_h(tmp3, hz_out6); + + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + AVER_UB2_UB(out0, dst0, out1, dst1, dst0, dst1); + ST8x4_UB(dst0, dst1, dst, stride); + dst += (4 * stride); + + LD_SB4(src, stride, src9, src10, src11, src12); + XORI_B4_128_SB(src9, src10, src11, src12); + hz_out9 = AVC_HORZ_FILTER_SH(src9, src9, mask0, mask1, mask2); + hz_out10 = AVC_HORZ_FILTER_SH(src10, src10, mask0, mask1, mask2); + hz_out11 = AVC_HORZ_FILTER_SH(src11, src11, mask0, mask1, mask2); + hz_out12 = AVC_HORZ_FILTER_SH(src12, src12, mask0, mask1, mask2); + ILVR_H4_SH(hz_out9, hz_out8, hz_out10, hz_out9, hz_out11, hz_out10, + hz_out12, hz_out11, hz_out89_r, hz_out910_r, hz_out1110_r, + hz_out1211_r); + ILVL_H4_SH(hz_out9, hz_out8, hz_out10, hz_out9, hz_out11, hz_out10, + hz_out12, hz_out11, hz_out89_l, hz_out910_l, hz_out1110_l, + hz_out1211_l); + tmp0_w = AVC_DOT_SW3_SW(hz_out54_r, hz_out76_r, hz_out89_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out54_l, hz_out76_l, hz_out89_l, filt0, filt1, + filt2); + tmp0 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out65_r, hz_out87_r, hz_out910_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out65_l, hz_out87_l, hz_out910_l, filt0, filt1, + filt2); + tmp1 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out76_r, hz_out89_r, hz_out1110_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out76_l, hz_out89_l, hz_out1110_l, filt0, filt1, + filt2); + tmp2 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + tmp0_w = AVC_DOT_SW3_SW(hz_out87_r, hz_out910_r, hz_out1211_r, filt0, filt1, + filt2); + tmp1_w = AVC_DOT_SW3_SW(hz_out87_l, hz_out910_l, hz_out1211_l, filt0, filt1, + filt2); + tmp3 = __msa_pckev_h((v8i16) tmp1_w, (v8i16) tmp0_w); + + SRARI_H4_SH(hz_out7, hz_out8, hz_out9, hz_out10, 5); + SAT_SH4_SH(hz_out7, hz_out8, hz_out9, hz_out10, 7); + + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + + tmp0 = __msa_aver_s_h(tmp0, hz_out7); + tmp1 = __msa_aver_s_h(tmp1, hz_out8); + tmp2 = __msa_aver_s_h(tmp2, hz_out9); + tmp3 = __msa_aver_s_h(tmp3, hz_out10); + + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + AVER_UB2_UB(out0, dst0, out1, dst1, dst0, dst1); + ST8x4_UB(dst0, dst1, dst, stride); +} + +void ff_avg_h264_qpel4_mc21_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint32_t tp0, tp1, tp2, tp3; + const int32_t filt_const0 = 0xfffb0001; + const int32_t filt_const1 = 0x140014; + const int32_t filt_const2 = 0x1fffb; + v16u8 res, out = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 mask0, mask1, mask2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + v8i16 hz_out7, hz_out8, dst0, dst1, filt0, filt1, filt2; + v8i16 hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r, hz_out54_r; + v8i16 hz_out65_r, hz_out76_r, hz_out87_r; + v4i32 tmp0, tmp1; + + LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); + + filt0 = (v8i16) __msa_fill_w(filt_const0); + filt1 = (v8i16) __msa_fill_w(filt_const1); + filt2 = (v8i16) __msa_fill_w(filt_const2); + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + LD_SB4(src, stride, src5, src6, src7, src8); + + XORI_B5_128_SB(src0, src1, src2, src3, src4); + XORI_B4_128_SB(src5, src6, src7, src8); + + hz_out0 = AVC_HORZ_FILTER_SH(src0, src1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src2, src3, mask0, mask1, mask2); + hz_out4 = AVC_HORZ_FILTER_SH(src4, src5, mask0, mask1, mask2); + hz_out6 = AVC_HORZ_FILTER_SH(src6, src7, mask0, mask1, mask2); + hz_out8 = AVC_HORZ_FILTER_SH(src8, src8, mask0, mask1, mask2); + PCKOD_D2_SH(hz_out0, hz_out0, hz_out2, hz_out2, hz_out1, hz_out3); + PCKOD_D2_SH(hz_out4, hz_out4, hz_out6, hz_out6, hz_out5, hz_out7); + + ILVR_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, hz_out4, + hz_out3, hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r); + ILVR_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, hz_out8, + hz_out7, hz_out54_r, hz_out65_r, hz_out76_r, hz_out87_r); + + tmp0 = AVC_DOT_SW3_SW(hz_out10_r, hz_out32_r, hz_out54_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out21_r, hz_out43_r, hz_out65_r, filt0, filt1, + filt2); + dst0 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out32_r, hz_out54_r, hz_out76_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out43_r, hz_out65_r, hz_out87_r, filt0, filt1, + filt2); + dst1 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + + SRARI_H2_SH(hz_out2, hz_out4, 5); + SAT_SH2_SH(hz_out2, hz_out4, 7); + + dst0 = __msa_aver_s_h(dst0, hz_out2); + dst1 = __msa_aver_s_h(dst1, hz_out4); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, out); + res = PCKEV_XORI128_UB(dst0, dst1); + res = __msa_aver_u_b(res, out); + ST4x4_UB(res, res, 0, 1, 2, 3, dst, stride); +} + +void ff_avg_h264_qpel4_mc23_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + const int32_t filt_const0 = 0xfffb0001; + const int32_t filt_const1 = 0x140014; + const int32_t filt_const2 = 0x1fffb; + uint32_t tp0, tp1, tp2, tp3; + v16u8 res, out = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 mask0, mask1, mask2; + v8i16 hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + v8i16 hz_out7, hz_out8, dst0, dst1, filt0, filt1, filt2; + v8i16 hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r, hz_out54_r; + v8i16 hz_out65_r, hz_out76_r, hz_out87_r; + v4i32 tmp0, tmp1; + + LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); + + filt0 = (v8i16) __msa_fill_w(filt_const0); + filt1 = (v8i16) __msa_fill_w(filt_const1); + filt2 = (v8i16) __msa_fill_w(filt_const2); + + src -= ((2 * stride) + 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + LD_SB4(src, stride, src5, src6, src7, src8); + + XORI_B5_128_SB(src0, src1, src2, src3, src4); + XORI_B4_128_SB(src5, src6, src7, src8); + + hz_out0 = AVC_HORZ_FILTER_SH(src0, src1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src2, src3, mask0, mask1, mask2); + hz_out4 = AVC_HORZ_FILTER_SH(src4, src5, mask0, mask1, mask2); + hz_out6 = AVC_HORZ_FILTER_SH(src6, src7, mask0, mask1, mask2); + hz_out8 = AVC_HORZ_FILTER_SH(src8, src8, mask0, mask1, mask2); + PCKOD_D2_SH(hz_out0, hz_out0, hz_out2, hz_out2, hz_out1, hz_out3); + PCKOD_D2_SH(hz_out4, hz_out4, hz_out6, hz_out6, hz_out5, hz_out7); + + ILVR_H4_SH(hz_out1, hz_out0, hz_out2, hz_out1, hz_out3, hz_out2, hz_out4, + hz_out3, hz_out10_r, hz_out21_r, hz_out32_r, hz_out43_r); + ILVR_H4_SH(hz_out5, hz_out4, hz_out6, hz_out5, hz_out7, hz_out6, hz_out8, + hz_out7, hz_out54_r, hz_out65_r, hz_out76_r, hz_out87_r); + + tmp0 = AVC_DOT_SW3_SW(hz_out10_r, hz_out32_r, hz_out54_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out21_r, hz_out43_r, hz_out65_r, filt0, filt1, + filt2); + dst0 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + tmp0 = AVC_DOT_SW3_SW(hz_out32_r, hz_out54_r, hz_out76_r, filt0, filt1, + filt2); + tmp1 = AVC_DOT_SW3_SW(hz_out43_r, hz_out65_r, hz_out87_r, filt0, filt1, + filt2); + dst1 = __msa_pckev_h((v8i16) tmp1, (v8i16) tmp0); + + PCKEV_D2_SH(hz_out4, hz_out3, hz_out6, hz_out5, hz_out0, hz_out1); + SRARI_H2_SH(hz_out0, hz_out1, 5); + SAT_SH2_SH(hz_out0, hz_out1, 7); + + dst0 = __msa_aver_s_h(dst0, hz_out0); + dst1 = __msa_aver_s_h(dst1, hz_out1); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, out); + res = PCKEV_XORI128_UB(dst0, dst1); + res = __msa_aver_u_b(res, out); + ST4x4_UB(res, res, 0, 1, 2, 3, dst, stride); } void ff_avg_h264_qpel16_mc02_msa(uint8_t *dst, const uint8_t *src, From e1555eb76cd21870a8ae8f8907d902443d896e44 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Fri, 3 Nov 2017 11:07:08 +0530 Subject: [PATCH 0738/2557] avcodec/mips: Improve hevc bi 4 tap hz and vt mc msa functions Use global mask buffer for appropriate mask load. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_bi_msa.c | 428 +++++++++++++++---------------- 1 file changed, 210 insertions(+), 218 deletions(-) diff --git a/libavcodec/mips/hevc_mc_bi_msa.c b/libavcodec/mips/hevc_mc_bi_msa.c index 9c03ef8c5ae78..e9c9184d2796f 100644 --- a/libavcodec/mips/hevc_mc_bi_msa.c +++ b/libavcodec/mips/hevc_mc_bi_msa.c @@ -2183,7 +2183,7 @@ static void hevc_hz_bi_4t_4x2_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v16i8 src0, src1, dst0, vec0, vec1; v8i16 in0, in1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[16]); v16i8 mask1; v8i16 tmp0; v8i16 filter_vec, const_vec; @@ -2226,7 +2226,8 @@ static void hevc_hz_bi_4t_4x4_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v16i8 src0, src1, src2, src3, dst0, vec0, vec1; v8i16 in0, in1, in2, in3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v16i8 vec2, vec3; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[16]); v16i8 mask1; v8i16 tmp0, tmp1; v8i16 filter_vec, const_vec; @@ -2247,12 +2248,12 @@ static void hevc_hz_bi_4t_4x4_msa(uint8_t *src0_ptr, ILVR_D2_SH(in1, in0, in3, in2, in0, in1); XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); tmp0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, tmp0, tmp0); - VSHF_B2_SB(src2, src3, src2, src3, mask0, mask1, vec0, vec1); tmp1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, tmp1, tmp1); + VSHF_B2_SB(src0, src1, src2, src3, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src0, src1, src2, src3, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt1, filt1, tmp0, tmp1, + tmp0, tmp1); HEVC_BI_RND_CLIP2(in0, in1, tmp0, tmp1, 7, tmp0, tmp1); dst0 = __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); @@ -2273,8 +2274,8 @@ static void hevc_hz_bi_4t_4x8multiple_msa(uint8_t *src0_ptr, v16i8 src0, src1, src2, src3, src4, src5, src6, src7; v16i8 dst0, dst1; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; - v16i8 mask1, vec0, vec1; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[16]); + v16i8 mask1, vec0, vec1, vec2, vec3; v8i16 tmp0, tmp1, tmp2, tmp3; v8i16 filter_vec, const_vec; @@ -2300,18 +2301,18 @@ static void hevc_hz_bi_4t_4x8multiple_msa(uint8_t *src0_ptr, ILVR_D2_SH(in5, in4, in7, in6, in2, in3); XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); - VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); tmp0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, tmp0, tmp0); - VSHF_B2_SB(src2, src3, src2, src3, mask0, mask1, vec0, vec1); tmp1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, tmp1, tmp1); - VSHF_B2_SB(src4, src5, src4, src5, mask0, mask1, vec0, vec1); tmp2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, tmp2, tmp2); - VSHF_B2_SB(src6, src7, src6, src7, mask0, mask1, vec0, vec1); tmp3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, tmp3, tmp3); + VSHF_B2_SB(src0, src1, src2, src3, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src4, src5, src6, src7, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, tmp0, + tmp1, tmp2, tmp3); + VSHF_B2_SB(src0, src1, src2, src3, mask1, mask1, vec0, vec1); + VSHF_B2_SB(src4, src5, src6, src7, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, tmp0, + tmp1, tmp2, tmp3); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, tmp0, tmp1, tmp2, tmp3, 7, tmp0, tmp1, tmp2, tmp3); @@ -2357,9 +2358,9 @@ static void hevc_hz_bi_4t_6w_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v16i8 src0, src1, src2, src3; v8i16 in0, in1, in2, in3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1; - v16i8 vec0, vec1; + v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2, dst3; v8i16 filter_vec, const_vec; @@ -2380,18 +2381,18 @@ static void hevc_hz_bi_4t_6w_msa(uint8_t *src0_ptr, src1_ptr += (4 * src2_stride); XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); @@ -2414,8 +2415,8 @@ static void hevc_hz_bi_4t_8x2_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v16i8 src0, src1; v8i16 in0, in1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; - v16i8 mask1, vec0, vec1; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); + v16i8 mask1, vec0, vec1, vec2, vec3; v8i16 dst0, dst1; v8i16 filter_vec, const_vec; @@ -2433,12 +2434,12 @@ static void hevc_hz_bi_4t_8x2_msa(uint8_t *src0_ptr, LD_SH2(src1_ptr, src2_stride, in0, in1); XORI_B2_128_SB(src0, src1); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt1, filt1, dst0, dst1, + dst0, dst1); HEVC_BI_RND_CLIP2(in0, in1, dst0, dst1, 7, dst0, dst1); dst0 = (v8i16) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); @@ -2457,9 +2458,9 @@ static void hevc_hz_bi_4t_8x6_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v16i8 src0, src1, src2, src3, src4, src5; v8i16 in0, in1, in2, in3, in4, in5; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1; - v16i8 vec0, vec1; + v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; v8i16 filter_vec, const_vec; @@ -2479,24 +2480,25 @@ static void hevc_hz_bi_4t_8x6_msa(uint8_t *src0_ptr, LD_SH2(src1_ptr, src2_stride, in4, in5); XORI_B6_128_SB(src0, src1, src2, src3, src4, src5); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, dst1, + dst2, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, dst1, + dst2, dst3); dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); + + VSHF_B2_SB(src4, src4, src5, src5, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src4, src4, src5, src5, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt1, filt1, dst4, dst5, + dst4, dst5); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); @@ -2522,9 +2524,9 @@ static void hevc_hz_bi_4t_8x4multiple_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v16i8 src0, src1, src2, src3; v8i16 in0, in1, in2, in3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v16i8 vec0, vec1; + v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2, dst3; v8i16 filter_vec, const_vec; @@ -2545,18 +2547,18 @@ static void hevc_hz_bi_4t_8x4multiple_msa(uint8_t *src0_ptr, src1_ptr += (4 * src2_stride); XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); @@ -2602,12 +2604,12 @@ static void hevc_hz_bi_4t_12w_msa(uint8_t *src0_ptr, v8i16 filt0, filt1; v16i8 src0, src1, src2, src3; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask2 = { 8, 9, 9, 10, 10, 11, 11, 12, 24, 25, 25, 26, 26, 27, 27, 28 }; v16i8 mask1, mask3; - v16i8 vec0, vec1; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; v8i16 filter_vec, const_vec; @@ -2632,24 +2634,24 @@ static void hevc_hz_bi_4t_12w_msa(uint8_t *src0_ptr, ILVR_D2_SH(in5, in4, in7, in6, in4, in5); XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - VSHF_B2_SB(src2, src3, src2, src3, mask2, mask3, vec0, vec1); dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); + VSHF_B2_SB(src0, src1, src2, src3, mask2, mask2, vec4, vec5); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + DPADD_SB2_SH(vec4, vec5, filt0, filt0, dst4, dst5); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2, vec3); + VSHF_B2_SB(src0, src1, src2, src3, mask3, mask3, vec4, vec5); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); + DPADD_SB2_SH(vec4, vec5, filt1, filt1, dst4, dst5); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); @@ -2672,13 +2674,11 @@ static void hevc_hz_bi_4t_16w_msa(uint8_t *src0_ptr, int32_t height) { uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7; - v8i16 in0, in1, in2, in3, in4, in5, in6, in7; + v16i8 src0, src1, src2, src3, vec0, vec1, vec2, vec3; + v8i16 in0, in1, in2, in3, dst0, dst1, dst2, dst3; v8i16 filt0, filt1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; - v16i8 vec0, vec1; v8i16 filter_vec, const_vec; src0_ptr -= 1; @@ -2691,49 +2691,36 @@ static void hevc_hz_bi_4t_16w_msa(uint8_t *src0_ptr, mask1 = mask0 + 2; - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB4(src0_ptr, src_stride, src0, src2, src4, src6); - LD_SB4(src0_ptr + 8, src_stride, src1, src3, src5, src7); - src0_ptr += (4 * src_stride); - LD_SH4(src1_ptr, src2_stride, in0, in2, in4, in6); - LD_SH4(src1_ptr + 8, src2_stride, in1, in3, in5, in7); - src1_ptr += (4 * src2_stride); - XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); + for (loop_cnt = (height >> 1); loop_cnt--;) { + LD_SB2(src0_ptr, src_stride, src0, src2); + LD_SB2(src0_ptr + 8, src_stride, src1, src3); + src0_ptr += (2 * src_stride); + LD_SH2(src1_ptr, src2_stride, in0, in2); + LD_SH2(src1_ptr + 8, src2_stride, in1, in3); + src1_ptr += (2 * src2_stride); + + XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); - VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); - dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); + + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); - HEVC_BI_RND_CLIP4(in4, in5, in6, in7, - dst4, dst5, dst6, dst7, 7, dst4, dst5, dst6, dst7); - PCKEV_B4_SH(dst1, dst0, dst3, dst2, - dst5, dst4, dst7, dst6, dst0, dst1, dst2, dst3); - ST_SH4(dst0, dst1, dst2, dst3, dst, dst_stride); - dst += (4 * dst_stride); + PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); + ST_SH2(dst0, dst1, dst, dst_stride); + dst += (2 * dst_stride); } } @@ -2752,9 +2739,9 @@ static void hevc_hz_bi_4t_24w_msa(uint8_t *src0_ptr, v16i8 src0, src1, src2, src3, src4, src5, src6, src7; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; v8i16 filt0, filt1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1, mask2, mask3; - v16i8 vec0, vec1; + v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; v8i16 filter_vec, const_vec; @@ -2782,30 +2769,31 @@ static void hevc_hz_bi_4t_24w_msa(uint8_t *src0_ptr, src1_ptr += (4 * src2_stride); XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - VSHF_B2_SB(src2, src3, src2, src3, mask2, mask3, vec0, vec1); dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src0, src0, src0, src1, mask0, mask2, vec0, vec1); + VSHF_B2_SB(src2, src2, src2, src3, mask0, mask2, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask1, mask3, vec0, vec1); + VSHF_B2_SB(src2, src2, src2, src3, mask1, mask3, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); + dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - VSHF_B2_SB(src4, src5, src4, src5, mask2, mask3, vec0, vec1); dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); - VSHF_B2_SB(src6, src7, src6, src7, mask2, mask3, vec0, vec1); dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); + VSHF_B2_SB(src4, src4, src4, src5, mask0, mask2, vec0, vec1); + VSHF_B2_SB(src6, src6, src6, src7, mask0, mask2, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst4, + dst5, dst6, dst7); + VSHF_B2_SB(src4, src4, src4, src5, mask1, mask3, vec0, vec1); + VSHF_B2_SB(src6, src6, src6, src7, mask1, mask3, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst4, + dst5, dst6, dst7); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); @@ -2820,18 +2808,18 @@ static void hevc_hz_bi_4t_24w_msa(uint8_t *src0_ptr, LD_SH4(src1_ptr_tmp, src2_stride, in0, in1, in2, in3); src1_ptr_tmp += (4 * src2_stride); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + VSHF_B2_SB(src1, src1, src3, src3, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src5, src5, src7, src7, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src1, src1, src3, src3, mask1, mask1, vec0, vec1); + VSHF_B2_SB(src5, src5, src7, src7, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); @@ -2855,10 +2843,10 @@ static void hevc_hz_bi_4t_32w_msa(uint8_t *src0_ptr, v16i8 src0, src1, src2; v8i16 in0, in1, in2, in3; v8i16 filt0, filt1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1, mask2, mask3; v8i16 dst0, dst1, dst2, dst3; - v16i8 vec0, vec1; + v16i8 vec0, vec1, vec2, vec3; v8i16 filter_vec, const_vec; src0_ptr -= 1; @@ -2873,34 +2861,7 @@ static void hevc_hz_bi_4t_32w_msa(uint8_t *src0_ptr, mask2 = mask0 + 8; mask3 = mask0 + 10; - for (loop_cnt = (height >> 1); loop_cnt--;) { - LD_SB2(src0_ptr, 16, src0, src1); - src2 = LD_SB(src0_ptr + 24); - src0_ptr += src_stride; - LD_SH4(src1_ptr, 8, in0, in1, in2, in3); - src1_ptr += src2_stride; - XORI_B3_128_SB(src0, src1, src2); - - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); - - PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); - ST_SH2(dst0, dst1, dst, 16); - dst += dst_stride; - + for (loop_cnt = height; loop_cnt--;) { LD_SB2(src0_ptr, 16, src0, src1); src2 = LD_SB(src0_ptr + 24); src0_ptr += src_stride; @@ -2908,18 +2869,18 @@ static void hevc_hz_bi_4t_32w_msa(uint8_t *src0_ptr, src1_ptr += src2_stride; XORI_B3_128_SB(src0, src1, src2); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask0, mask2, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask1, mask3, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, dst0, dst1, dst2, dst3, 7, dst0, dst1, dst2, dst3); @@ -3131,10 +3092,9 @@ static void hevc_vt_bi_4t_6w_msa(uint8_t *src0_ptr, const int8_t *filter, int32_t height) { - int32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v8i16 in0, in1, in2, in3; - v16i8 src10_r, src32_r, src21_r, src43_r; + v16i8 src10_r, src32_r, src21_r, src43_r, src54_r, src65_r; v8i16 dst0_r, dst1_r, dst2_r, dst3_r; v8i16 filt0, filt1; v8i16 filter_vec, const_vec; @@ -3149,40 +3109,70 @@ static void hevc_vt_bi_4t_6w_msa(uint8_t *src0_ptr, LD_SB3(src0_ptr, src_stride, src0, src1, src2); src0_ptr += (3 * src_stride); + LD_SB2(src0_ptr, src_stride, src3, src4); + src0_ptr += (2 * src_stride); + LD_SB2(src0_ptr, src_stride, src5, src6); + src0_ptr += (2 * src_stride); + LD_SB2(src0_ptr, src_stride, src7, src8); + src0_ptr += (2 * src_stride); + LD_SB2(src0_ptr, src_stride, src9, src10); + src0_ptr += (2 * src_stride); + + LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); + src1_ptr += (4 * src2_stride); + XORI_B3_128_SB(src0, src1, src2); + XORI_B2_128_SB(src3, src4); + XORI_B2_128_SB(src5, src6); + XORI_B2_128_SB(src7, src8); + XORI_B2_128_SB(src9, src10); + ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); + ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB2(src0_ptr, src_stride, src3, src4); - src0_ptr += (2 * src_stride); - LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); - src1_ptr += (4 * src2_stride); - XORI_B2_128_SB(src3, src4); - ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); + dst0_r = const_vec; + DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, dst0_r, dst0_r); + dst1_r = const_vec; + DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, dst1_r, dst1_r); - dst0_r = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, dst0_r, dst0_r); - dst1_r = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, dst1_r, dst1_r); + ILVR_B2_SB(src5, src4, src6, src5, src54_r, src65_r); - LD_SB2(src0_ptr, src_stride, src5, src2); - src0_ptr += (2 * src_stride); - XORI_B2_128_SB(src5, src2); - ILVR_B2_SB(src5, src4, src2, src5, src10_r, src21_r); + dst2_r = const_vec; + DPADD_SB2_SH(src32_r, src54_r, filt0, filt1, dst2_r, dst2_r); + dst3_r = const_vec; + DPADD_SB2_SH(src43_r, src65_r, filt0, filt1, dst3_r, dst3_r); - dst2_r = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, dst2_r, dst2_r); - dst3_r = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, dst3_r, dst3_r); + HEVC_BI_RND_CLIP4(in0, in1, in2, in3, + dst0_r, dst1_r, dst2_r, dst3_r, 7, + dst0_r, dst1_r, dst2_r, dst3_r); - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - dst0_r, dst1_r, dst2_r, dst3_r, 7, - dst0_r, dst1_r, dst2_r, dst3_r); + PCKEV_B2_SH(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r, dst1_r); + ST6x4_UB(dst0_r, dst1_r, dst, dst_stride); + dst += (4 * dst_stride); - PCKEV_B2_SH(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r, dst1_r); - ST6x4_UB(dst0_r, dst1_r, dst, dst_stride); - dst += (4 * dst_stride); - } + LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); + src1_ptr += (4 * src2_stride); + ILVR_B2_SB(src7, src6, src8, src7, src32_r, src43_r); + + dst0_r = const_vec; + DPADD_SB2_SH(src54_r, src32_r, filt0, filt1, dst0_r, dst0_r); + dst1_r = const_vec; + DPADD_SB2_SH(src65_r, src43_r, filt0, filt1, dst1_r, dst1_r); + + ILVR_B2_SB(src9, src8, src10, src9, src54_r, src65_r); + + dst2_r = const_vec; + DPADD_SB2_SH(src32_r, src54_r, filt0, filt1, dst2_r, dst2_r); + dst3_r = const_vec; + DPADD_SB2_SH(src43_r, src65_r, filt0, filt1, dst3_r, dst3_r); + + HEVC_BI_RND_CLIP4(in0, in1, in2, in3, + dst0_r, dst1_r, dst2_r, dst3_r, 7, + dst0_r, dst1_r, dst2_r, dst3_r); + + PCKEV_B2_SH(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r, dst1_r); + ST6x4_UB(dst0_r, dst1_r, dst, dst_stride); + dst += (4 * dst_stride); } static void hevc_vt_bi_4t_8x2_msa(uint8_t *src0_ptr, @@ -3384,12 +3374,12 @@ static void hevc_vt_bi_4t_12w_msa(uint8_t *src0_ptr, int32_t height) { int32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5; + v16i8 src0, src1, src2, src3, src4, src5, src6; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; - v16i8 src10_r, src32_r, src21_r, src43_r; + v16i8 src10_r, src32_r, src21_r, src43_r, src54_r, src65_r; v8i16 dst0_r, dst1_r, dst2_r, dst3_r; v16i8 src10_l, src32_l, src54_l, src21_l, src43_l, src65_l; - v16i8 src2110, src4332; + v16i8 src2110, src4332, src6554; v8i16 dst0_l, dst1_l, filt0, filt1; v8i16 filter_vec, const_vec; @@ -3411,15 +3401,21 @@ static void hevc_vt_bi_4t_12w_msa(uint8_t *src0_ptr, for (loop_cnt = (height >> 2); loop_cnt--;) { LD_SB2(src0_ptr, src_stride, src3, src4); src0_ptr += (2 * src_stride); + LD_SB2(src0_ptr, src_stride, src5, src6); + src0_ptr += (2 * src_stride); LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); LD_SH4((src1_ptr + 8), src2_stride, in4, in5, in6, in7); src1_ptr += (4 * src2_stride); ILVR_D2_SH(in5, in4, in7, in6, in4, in5); XORI_B2_128_SB(src3, src4); + XORI_B2_128_SB(src5, src6); ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); ILVL_B2_SB(src3, src2, src4, src3, src32_l, src43_l); src4332 = (v16i8) __msa_ilvr_d((v2i64) src43_l, (v2i64) src32_l); + ILVR_B2_SB(src5, src4, src6, src5, src54_r, src65_r); + ILVL_B2_SB(src5, src4, src6, src5, src54_l, src65_l); + src6554 = (v16i8) __msa_ilvr_d((v2i64) src65_l, (v2i64) src54_l); dst0_r = const_vec; DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, dst0_r, dst0_r); @@ -3427,21 +3423,12 @@ static void hevc_vt_bi_4t_12w_msa(uint8_t *src0_ptr, DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, dst1_r, dst1_r); dst0_l = const_vec; DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst0_l, dst0_l); - - LD_SB2(src0_ptr, src_stride, src5, src2); - src0_ptr += (2 * src_stride); - XORI_B2_128_SB(src5, src2); - - ILVR_B2_SB(src5, src4, src2, src5, src10_r, src21_r); - ILVL_B2_SB(src5, src4, src2, src5, src54_l, src65_l); - src2110 = (v16i8) __msa_ilvr_d((v2i64) src65_l, (v2i64) src54_l); - dst2_r = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, dst2_r, dst2_r); + DPADD_SB2_SH(src32_r, src54_r, filt0, filt1, dst2_r, dst2_r); dst3_r = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, dst3_r, dst3_r); + DPADD_SB2_SH(src43_r, src65_r, filt0, filt1, dst3_r, dst3_r); dst1_l = const_vec; - DPADD_SB2_SH(src4332, src2110, filt0, filt1, dst1_l, dst1_l); + DPADD_SB2_SH(src4332, src6554, filt0, filt1, dst1_l, dst1_l); HEVC_BI_RND_CLIP4(in0, in1, in2, in3, dst0_r, dst1_r, dst2_r, dst3_r, 7, dst0_r, dst1_r, dst2_r, dst3_r); @@ -3451,6 +3438,11 @@ static void hevc_vt_bi_4t_12w_msa(uint8_t *src0_ptr, dst0_l = (v8i16) __msa_pckev_b((v16i8) dst1_l, (v16i8) dst0_l); ST12x4_UB(dst0_r, dst1_r, dst0_l, dst, dst_stride); dst += (4 * dst_stride); + + src2 = src6; + src10_r = src54_r; + src21_r = src65_r; + src2110 = src6554; } } @@ -4664,7 +4656,7 @@ static void hevc_hv_bi_4t_32w_msa(uint8_t *src0_ptr, uint8_t *dst, int32_t dst_stride, const int8_t *filter_x, - const const int8_t *filter_y, + const int8_t *filter_y, int32_t height) { hevc_hv_bi_4t_8multx4mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, From 8f6c398d44b5b40ed99ed06fa0c0bbf83524b6d7 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Fri, 3 Nov 2017 11:59:08 +0530 Subject: [PATCH 0739/2557] avcodec/mips: Improve hevc bi wgt 4 tap hz and vt mc msa functions Use global mask buffer for appropriate mask load. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_biw_msa.c | 587 +++++++++++++----------------- 1 file changed, 247 insertions(+), 340 deletions(-) diff --git a/libavcodec/mips/hevc_mc_biw_msa.c b/libavcodec/mips/hevc_mc_biw_msa.c index 75c1c7a15855d..0e5f8a02cfdb9 100644 --- a/libavcodec/mips/hevc_mc_biw_msa.c +++ b/libavcodec/mips/hevc_mc_biw_msa.c @@ -2633,22 +2633,21 @@ static void hevc_hz_biwgt_4t_4x2_msa(uint8_t *src0_ptr, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight0, int32_t weight1, int32_t offset0, int32_t offset1, int32_t rnd_val) { - int32_t offset, weight; + int32_t offset, weight, constant; v8i16 filt0, filt1; v16i8 src0, src1; v8i16 in0, in1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[16]); v16i8 mask1, vec0, vec1; v8i16 dst0; v4i32 dst0_r, dst0_l; - v8i16 filter_vec, const_vec; + v8i16 out0, filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -2661,9 +2660,10 @@ static void hevc_hz_biwgt_4t_4x2_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -2674,18 +2674,16 @@ static void hevc_hz_biwgt_4t_4x2_msa(uint8_t *src0_ptr, XORI_B2_128_SB(src0, src1); VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); ILVRL_H2_SW(dst0, in0, dst0_r, dst0_l); dst0_r = __msa_dpadd_s_w(offset_vec, (v8i16) dst0_r, (v8i16) weight_vec); dst0_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst0_l, (v8i16) weight_vec); SRAR_W2_SW(dst0_r, dst0_l, rnd_vec); - dst0_r = CLIP_SW_0_255(dst0_r); - dst0_l = CLIP_SW_0_255(dst0_l); - - HEVC_PCK_SW_SB2(dst0_l, dst0_r, dst0_r); - ST4x2_UB(dst0_r, dst, dst_stride); + dst0_r = (v4i32) __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); + out0 = CLIP_SH_0_255(dst0_r); + out0 = (v8i16) __msa_pckev_b((v16i8) out0, (v16i8) out0); + ST4x2_UB(out0, dst, dst_stride); } static void hevc_hz_biwgt_4t_4x4_msa(uint8_t *src0_ptr, @@ -2695,22 +2693,21 @@ static void hevc_hz_biwgt_4t_4x4_msa(uint8_t *src0_ptr, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight0, int32_t weight1, int32_t offset0, int32_t offset1, int32_t rnd_val) { - int32_t offset, weight; + int32_t offset, weight, constant; v8i16 filt0, filt1; v16i8 src0, src1, src2, src3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[16]); v16i8 mask1; v8i16 dst0, dst1; v16i8 vec0, vec1; v8i16 in0, in1, in2, in3; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -2724,9 +2721,10 @@ static void hevc_hz_biwgt_4t_4x4_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -2737,11 +2735,9 @@ static void hevc_hz_biwgt_4t_4x4_msa(uint8_t *src0_ptr, ILVR_D2_SH(in1, in0, in3, in2, in0, in1); VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src2, src3, src2, src3, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + dst1 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); HEVC_BIW_RND_CLIP2(dst0, dst1, in0, in1, weight_vec, rnd_vec, offset_vec, dst0, dst1); @@ -2765,15 +2761,15 @@ static void hevc_hz_biwgt_4t_4x8multiple_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t weight, offset; + int32_t weight, offset, constant; v8i16 filt0, filt1; v16i8 src0, src1, src2, src3, src4, src5, src6, src7; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[16]); v16i8 mask1; v16i8 vec0, vec1; v8i16 dst0, dst1, dst2, dst3; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -2784,9 +2780,10 @@ static void hevc_hz_biwgt_4t_4x8multiple_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -2806,17 +2803,13 @@ static void hevc_hz_biwgt_4t_4x8multiple_msa(uint8_t *src0_ptr, XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src2, src3, src2, src3, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + dst1 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src4, src5, src4, src5, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + dst2 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src6, src7, src6, src7, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, @@ -2844,11 +2837,11 @@ static void hevc_hz_biwgt_4t_4w_msa(uint8_t *src0_ptr, { if (2 == height) { hevc_hz_biwgt_4t_4x2_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter, height, + dst, dst_stride, filter, weight0, weight1, offset0, offset1, rnd_val); } else if (4 == height) { hevc_hz_biwgt_4t_4x4_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter, height, + dst, dst_stride, filter, weight0, weight1, offset0, offset1, rnd_val); } else if (0 == (height % 8)) { hevc_hz_biwgt_4t_4x8multiple_msa(src0_ptr, src_stride, @@ -2874,15 +2867,15 @@ static void hevc_hz_biwgt_4t_6w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v8i16 filt0, filt1; v16i8 src0, src1, src2, src3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1; v16i8 vec0, vec1; v8i16 in0, in1, in2, in3; v8i16 dst0, dst1, dst2, dst3; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -2893,16 +2886,17 @@ static void hevc_hz_biwgt_4t_6w_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); mask1 = mask0 + 2; - for (loop_cnt = (height >> 2); loop_cnt--;) { + for (loop_cnt = 2; loop_cnt--;) { LD_SB4(src0_ptr, src_stride, src0, src1, src2, src3); src0_ptr += (4 * src_stride); LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); @@ -2910,17 +2904,13 @@ static void hevc_hz_biwgt_4t_6w_msa(uint8_t *src0_ptr, XORI_B4_128_SB(src0, src1, src2, src3); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + dst1 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + dst2 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, @@ -2940,21 +2930,20 @@ static void hevc_hz_biwgt_4t_8x2_msa(uint8_t *src0_ptr, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight0, int32_t weight1, int32_t offset0, int32_t offset1, int32_t rnd_val) { - int32_t offset, weight; + int32_t offset, weight, constant; v8i16 filt0, filt1; v16i8 src0, src1; v8i16 in0, in1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1, vec0, vec1; v8i16 dst0, dst1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -2965,9 +2954,10 @@ static void hevc_hz_biwgt_4t_8x2_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -2978,11 +2968,9 @@ static void hevc_hz_biwgt_4t_8x2_msa(uint8_t *src0_ptr, LD_SH2(src1_ptr, src2_stride, in0, in1); XORI_B2_128_SB(src0, src1); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + dst1 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); HEVC_BIW_RND_CLIP2(dst0, dst1, in0, in1, weight_vec, rnd_vec, offset_vec, dst0, dst1); @@ -2998,22 +2986,21 @@ static void hevc_hz_biwgt_4t_8x6_msa(uint8_t *src0_ptr, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight0, int32_t weight1, int32_t offset0, int32_t offset1, int32_t rnd_val) { - int32_t weight, offset; + int32_t weight, offset, constant; v8i16 filt0, filt1; v16i8 src0, src1, src2, src3, src4, src5; v8i16 in0, in1, in2, in3, in4, in5; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1; v16i8 vec0, vec1; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -3024,9 +3011,10 @@ static void hevc_hz_biwgt_4t_8x6_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -3040,23 +3028,17 @@ static void hevc_hz_biwgt_4t_8x6_msa(uint8_t *src0_ptr, LD_SH2(src1_ptr, src2_stride, in4, in5); XORI_B6_128_SB(src0, src1, src2, src3, src4, src5); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + dst1 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + dst2 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); + dst4 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); + dst5 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, @@ -3087,15 +3069,15 @@ static void hevc_hz_biwgt_4t_8x4multiple_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v8i16 filt0, filt1; v16i8 src0, src1, src2, src3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; v16i8 vec0, vec1; v8i16 in0, in1, in2, in3; v8i16 dst0, dst1, dst2, dst3; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -3106,9 +3088,10 @@ static void hevc_hz_biwgt_4t_8x4multiple_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -3123,17 +3106,13 @@ static void hevc_hz_biwgt_4t_8x4multiple_msa(uint8_t *src0_ptr, XORI_B4_128_SB(src0, src1, src2, src3); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + dst1 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + dst2 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, @@ -3161,11 +3140,11 @@ static void hevc_hz_biwgt_4t_8w_msa(uint8_t *src0_ptr, { if (2 == height) { hevc_hz_biwgt_4t_8x2_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter, height, + dst, dst_stride, filter, weight0, weight1, offset0, offset1, rnd_val); } else if (6 == height) { hevc_hz_biwgt_4t_8x6_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter, height, + dst, dst_stride, filter, weight0, weight1, offset0, offset1, rnd_val); } else if (0 == (height % 4)) { hevc_hz_biwgt_4t_8x4multiple_msa(src0_ptr, src_stride, @@ -3191,18 +3170,18 @@ static void hevc_hz_biwgt_4t_12w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v8i16 filt0, filt1; v16i8 src0, src1, src2, src3; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask2 = { 8, 9, 9, 10, 10, 11, 11, 12, 24, 25, 25, 26, 26, 27, 27, 28 }; v16i8 mask1, mask3; v16i8 vec0, vec1; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -3213,9 +3192,10 @@ static void hevc_hz_biwgt_4t_12w_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -3223,7 +3203,7 @@ static void hevc_hz_biwgt_4t_12w_msa(uint8_t *src0_ptr, mask1 = mask0 + 2; mask3 = mask2 + 2; - for (loop_cnt = (height >> 2); loop_cnt--;) { + for (loop_cnt = 4; loop_cnt--;) { LD_SB4(src0_ptr, src_stride, src0, src1, src2, src3); src0_ptr += (4 * src_stride); LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); @@ -3233,23 +3213,17 @@ static void hevc_hz_biwgt_4t_12w_msa(uint8_t *src0_ptr, XORI_B4_128_SB(src0, src1, src2, src3); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + dst1 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + dst2 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); + dst4 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src2, src3, src2, src3, mask2, mask3, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); + dst5 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, @@ -3281,15 +3255,15 @@ static void hevc_hz_biwgt_4t_16w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1, src2, src3, src4, src5, src6, src7; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; v8i16 filt0, filt1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; v16i8 vec0, vec1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -3300,9 +3274,10 @@ static void hevc_hz_biwgt_4t_16w_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -3319,29 +3294,21 @@ static void hevc_hz_biwgt_4t_16w_msa(uint8_t *src0_ptr, XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + dst1 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + dst2 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); + dst4 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); + dst5 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); + dst6 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); - dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); + dst7 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, @@ -3377,16 +3344,15 @@ static void hevc_hz_biwgt_4t_24w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; - uint8_t *dst_tmp = dst + 16; + int32_t offset, weight, constant; v16i8 src0, src1, src2, src3; v8i16 filt0, filt1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1, mask2, mask3; v16i8 vec0, vec1; v8i16 dst0, dst1, dst2, dst3; v8i16 in0, in1, in2, in3, in4, in5; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -3397,9 +3363,10 @@ static void hevc_hz_biwgt_4t_24w_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -3408,7 +3375,7 @@ static void hevc_hz_biwgt_4t_24w_msa(uint8_t *src0_ptr, mask2 = mask0 + 8; mask3 = mask0 + 10; - for (loop_cnt = (height >> 1); loop_cnt--;) { + for (loop_cnt = 16; loop_cnt--;) { LD_SB2(src0_ptr, src_stride, src0, src2); LD_SB2(src0_ptr + 16, src_stride, src1, src3); src0_ptr += (2 * src_stride); @@ -3419,17 +3386,13 @@ static void hevc_hz_biwgt_4t_24w_msa(uint8_t *src0_ptr, XORI_B4_128_SB(src0, src1, src2, src3); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + dst1 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + dst2 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src2, src3, src2, src3, mask2, mask3, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, @@ -3437,21 +3400,19 @@ static void hevc_hz_biwgt_4t_24w_msa(uint8_t *src0_ptr, PCKEV_B2_SH(dst1, dst0, dst3, dst2, dst0, dst1); ST_SH2(dst0, dst1, dst, dst_stride); - dst += (2 * dst_stride); + /* 8 width */ VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + dst1 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); HEVC_BIW_RND_CLIP2(dst0, dst1, in4, in5, weight_vec, rnd_vec, offset_vec, dst0, dst1); dst0 = (v8i16) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); - ST8x2_UB(dst0, dst_tmp, dst_stride); - dst_tmp += (2 * dst_stride); + ST8x2_UB(dst0, (dst + 16), dst_stride); + dst += (2 * dst_stride); } } @@ -3470,15 +3431,15 @@ static void hevc_hz_biwgt_4t_32w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1, src2; v8i16 filt0, filt1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1, mask2, mask3; v8i16 dst0, dst1, dst2, dst3; v16i8 vec0, vec1; v8i16 in0, in1, in2, in3; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= 1; @@ -3489,9 +3450,10 @@ static void hevc_hz_biwgt_4t_32w_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -3509,17 +3471,13 @@ static void hevc_hz_biwgt_4t_32w_msa(uint8_t *src0_ptr, XORI_B3_128_SB(src0, src1, src2); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + dst1 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + dst2 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); HEVC_BIW_RND_CLIP4(dst0, dst1, dst2, dst3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, @@ -3538,20 +3496,19 @@ static void hevc_vt_biwgt_4t_4x2_msa(uint8_t *src0_ptr, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight0, int32_t weight1, int32_t offset0, int32_t offset1, int32_t rnd_val) { - int32_t weight, offset; + int32_t weight, offset, constant; v16i8 src0, src1, src2, src3, src4; v8i16 in0, in1, dst10; v16i8 src10_r, src32_r, src21_r, src43_r, src2110, src4332; v4i32 dst10_r, dst10_l; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec, out; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= src_stride; @@ -3559,9 +3516,10 @@ static void hevc_vt_biwgt_4t_4x2_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -3584,18 +3542,16 @@ static void hevc_vt_biwgt_4t_4x2_msa(uint8_t *src0_ptr, src4332 = (v16i8) __msa_ilvr_d((v2i64) src43_r, (v2i64) src32_r); src4332 = (v16i8) __msa_xori_b((v16u8) src4332, 128); - dst10 = const_vec; - DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst10, dst10); + dst10 = HEVC_FILT_4TAP_SH(src2110, src4332, filt0, filt1); ILVRL_H2_SW(dst10, in0, dst10_r, dst10_l); dst10_r = __msa_dpadd_s_w(offset_vec, (v8i16) dst10_r, (v8i16) weight_vec); dst10_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst10_l, (v8i16) weight_vec); SRAR_W2_SW(dst10_r, dst10_l, rnd_vec); - dst10_r = CLIP_SW_0_255(dst10_r); - dst10_l = CLIP_SW_0_255(dst10_l); - - HEVC_PCK_SW_SB2(dst10_l, dst10_r, dst10_r); - ST4x2_UB(dst10_r, dst, dst_stride); + dst10_r = (v4i32) __msa_pckev_h((v8i16) dst10_l, (v8i16) dst10_r); + out = CLIP_SH_0_255(dst10_r); + out = (v8i16) __msa_pckev_b((v16i8) out, (v16i8) out); + ST4x2_UB(out, dst, dst_stride); } static void hevc_vt_biwgt_4t_4x4_msa(uint8_t *src0_ptr, @@ -3605,21 +3561,20 @@ static void hevc_vt_biwgt_4t_4x4_msa(uint8_t *src0_ptr, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight0, int32_t weight1, int32_t offset0, int32_t offset1, int32_t rnd_val) { - int32_t weight, offset; + int32_t weight, offset, constant; v16i8 src0, src1, src2, src3, src4, src5, src6; v8i16 in0, in1, in2, in3; v16i8 src10_r, src32_r, src54_r, src21_r, src43_r, src65_r; v16i8 src2110, src4332, src6554; v8i16 dst10, dst32; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= src_stride; @@ -3627,9 +3582,10 @@ static void hevc_vt_biwgt_4t_4x4_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -3653,10 +3609,8 @@ static void hevc_vt_biwgt_4t_4x4_msa(uint8_t *src0_ptr, ILVR_D2_SB(src43_r, src32_r, src65_r, src54_r, src4332, src6554); XORI_B2_128_SB(src4332, src6554); - dst10 = const_vec; - DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst10, dst10); - dst32 = const_vec; - DPADD_SB2_SH(src4332, src6554, filt0, filt1, dst32, dst32); + dst10 = HEVC_FILT_4TAP_SH(src2110, src4332, filt0, filt1); + dst32 = HEVC_FILT_4TAP_SH(src4332, src6554, filt0, filt1); HEVC_BIW_RND_CLIP2(dst10, dst32, in0, in1, weight_vec, rnd_vec, offset_vec, @@ -3682,7 +3636,7 @@ static void hevc_vt_biwgt_4t_4x8multiple_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t weight, offset; + int32_t weight, offset, constant; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; v16i8 src10_r, src32_r, src54_r, src76_r, src98_r; @@ -3690,7 +3644,7 @@ static void hevc_vt_biwgt_4t_4x8multiple_msa(uint8_t *src0_ptr, v16i8 src2110, src4332, src6554, src8776; v8i16 dst10, dst32, dst54, dst76; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= src_stride; @@ -3698,9 +3652,10 @@ static void hevc_vt_biwgt_4t_4x8multiple_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -3730,12 +3685,9 @@ static void hevc_vt_biwgt_4t_4x8multiple_msa(uint8_t *src0_ptr, src4332, src6554, src8776); XORI_B3_128_SB(src4332, src6554, src8776); - dst10 = const_vec; - DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst10, dst10); - dst32 = const_vec; - DPADD_SB2_SH(src4332, src6554, filt0, filt1, dst32, dst32); - dst54 = const_vec; - DPADD_SB2_SH(src6554, src8776, filt0, filt1, dst54, dst54); + dst10 = HEVC_FILT_4TAP_SH(src2110, src4332, filt0, filt1); + dst32 = HEVC_FILT_4TAP_SH(src4332, src6554, filt0, filt1); + dst54 = HEVC_FILT_4TAP_SH(src6554, src8776, filt0, filt1); LD_SB2(src0_ptr, src_stride, src9, src2); src0_ptr += (2 * src_stride); @@ -3743,8 +3695,7 @@ static void hevc_vt_biwgt_4t_4x8multiple_msa(uint8_t *src0_ptr, src2110 = (v16i8) __msa_ilvr_d((v2i64) src109_r, (v2i64) src98_r); src2110 = (v16i8) __msa_xori_b((v16u8) src2110, 128); - dst76 = const_vec; - DPADD_SB2_SH(src8776, src2110, filt0, filt1, dst76, dst76); + dst76 = HEVC_FILT_4TAP_SH(src8776, src2110, filt0, filt1); HEVC_BIW_RND_CLIP4(dst10, dst32, dst54, dst76, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, @@ -3772,11 +3723,11 @@ static void hevc_vt_biwgt_4t_4w_msa(uint8_t *src0_ptr, { if (2 == height) { hevc_vt_biwgt_4t_4x2_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter, height, + dst, dst_stride, filter, weight0, weight1, offset0, offset1, rnd_val); } else if (4 == height) { hevc_vt_biwgt_4t_4x4_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter, height, + dst, dst_stride, filter, weight0, weight1, offset0, offset1, rnd_val); } else if (0 == (height % 8)) { hevc_vt_biwgt_4t_4x8multiple_msa(src0_ptr, src_stride, @@ -3802,13 +3753,13 @@ static void hevc_vt_biwgt_4t_6w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1, src2, src3, src4; v8i16 in0, in1, in2, in3; v16i8 src10_r, src32_r, src21_r, src43_r; v8i16 tmp0, tmp1, tmp2, tmp3; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= src_stride; @@ -3816,9 +3767,10 @@ static void hevc_vt_biwgt_4t_6w_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -3839,20 +3791,16 @@ static void hevc_vt_biwgt_4t_6w_msa(uint8_t *src0_ptr, XORI_B2_128_SB(src3, src4); ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); + tmp0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + tmp1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); LD_SB2(src0_ptr, src_stride, src1, src2); src0_ptr += (2 * src_stride); XORI_B2_128_SB(src1, src2); ILVR_B2_SB(src1, src4, src2, src1, src10_r, src21_r); - tmp2 = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, tmp3, tmp3); + tmp2 = HEVC_FILT_4TAP_SH(src32_r, src10_r, filt0, filt1); + tmp3 = HEVC_FILT_4TAP_SH(src43_r, src21_r, filt0, filt1); HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, @@ -3871,19 +3819,18 @@ static void hevc_vt_biwgt_4t_8x2_msa(uint8_t *src0_ptr, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight0, int32_t weight1, int32_t offset0, int32_t offset1, int32_t rnd_val) { - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1, src2, src3, src4; v8i16 in0, in1, tmp0, tmp1; v16i8 src10_r, src32_r, src21_r, src43_r; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= src_stride; @@ -3891,9 +3838,10 @@ static void hevc_vt_biwgt_4t_8x2_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -3911,10 +3859,8 @@ static void hevc_vt_biwgt_4t_8x2_msa(uint8_t *src0_ptr, XORI_B2_128_SB(src3, src4); ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); + tmp0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + tmp1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); HEVC_BIW_RND_CLIP2(tmp0, tmp1, in0, in1, weight_vec, rnd_vec, offset_vec, tmp0, tmp1); @@ -3930,21 +3876,20 @@ static void hevc_vt_biwgt_4t_8x6_msa(uint8_t *src0_ptr, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight0, int32_t weight1, int32_t offset0, int32_t offset1, int32_t rnd_val) { - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; v8i16 in0, in1, in2, in3, in4, in5; v16i8 src10_r, src32_r, src54_r, src76_r; v16i8 src21_r, src43_r, src65_r, src87_r; v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= src_stride; @@ -3952,9 +3897,10 @@ static void hevc_vt_biwgt_4t_8x6_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -3974,18 +3920,12 @@ static void hevc_vt_biwgt_4t_8x6_msa(uint8_t *src0_ptr, src32_r, src43_r, src54_r, src65_r); ILVR_B2_SB(src7, src6, src8, src7, src76_r, src87_r); - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); - tmp2 = const_vec; - DPADD_SB2_SH(src32_r, src54_r, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src43_r, src65_r, filt0, filt1, tmp3, tmp3); - tmp4 = const_vec; - DPADD_SB2_SH(src54_r, src76_r, filt0, filt1, tmp4, tmp4); - tmp5 = const_vec; - DPADD_SB2_SH(src65_r, src87_r, filt0, filt1, tmp5, tmp5); + tmp0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + tmp1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + tmp2 = HEVC_FILT_4TAP_SH(src32_r, src54_r, filt0, filt1); + tmp3 = HEVC_FILT_4TAP_SH(src43_r, src65_r, filt0, filt1); + tmp4 = HEVC_FILT_4TAP_SH(src54_r, src76_r, filt0, filt1); + tmp5 = HEVC_FILT_4TAP_SH(src65_r, src87_r, filt0, filt1); HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, @@ -4016,13 +3956,13 @@ static void hevc_vt_biwgt_4t_8x4multiple_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1, src2, src3, src4; v8i16 in0, in1, in2, in3; v16i8 src10_r, src32_r, src21_r, src43_r; v8i16 tmp0, tmp1, tmp2, tmp3; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= src_stride; @@ -4030,9 +3970,10 @@ static void hevc_vt_biwgt_4t_8x4multiple_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -4053,20 +3994,16 @@ static void hevc_vt_biwgt_4t_8x4multiple_msa(uint8_t *src0_ptr, XORI_B2_128_SB(src3, src4); ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); + tmp0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + tmp1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); LD_SB2(src0_ptr, src_stride, src1, src2); src0_ptr += (2 * src_stride); XORI_B2_128_SB(src1, src2); ILVR_B2_SB(src1, src4, src2, src1, src10_r, src21_r); - tmp2 = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, tmp3, tmp3); + tmp2 = HEVC_FILT_4TAP_SH(src32_r, src10_r, filt0, filt1); + tmp3 = HEVC_FILT_4TAP_SH(src43_r, src21_r, filt0, filt1); HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, @@ -4094,11 +4031,11 @@ static void hevc_vt_biwgt_4t_8w_msa(uint8_t *src0_ptr, { if (2 == height) { hevc_vt_biwgt_4t_8x2_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter, height, + dst, dst_stride, filter, weight0, weight1, offset0, offset1, rnd_val); } else if (6 == height) { hevc_vt_biwgt_4t_8x6_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter, height, + dst, dst_stride, filter, weight0, weight1, offset0, offset1, rnd_val); } else { hevc_vt_biwgt_4t_8x4multiple_msa(src0_ptr, src_stride, @@ -4124,7 +4061,7 @@ static void hevc_vt_biwgt_4t_12w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1, src2, src3, src4, src5; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; v16i8 src10_r, src32_r, src21_r, src43_r; @@ -4132,7 +4069,7 @@ static void hevc_vt_biwgt_4t_12w_msa(uint8_t *src0_ptr, v16i8 src10_l, src32_l, src54_l, src21_l, src43_l, src65_l; v16i8 src2110, src4332; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= (1 * src_stride); @@ -4140,9 +4077,10 @@ static void hevc_vt_biwgt_4t_12w_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -4170,12 +4108,9 @@ static void hevc_vt_biwgt_4t_12w_msa(uint8_t *src0_ptr, ILVL_B2_SB(src3, src2, src4, src3, src32_l, src43_l); src4332 = (v16i8) __msa_ilvr_d((v2i64) src43_l, (v2i64) src32_l); - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); - tmp4 = const_vec; - DPADD_SB2_SH(src2110, src4332, filt0, filt1, tmp4, tmp4); + tmp0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + tmp1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + tmp4 = HEVC_FILT_4TAP_SH(src2110, src4332, filt0, filt1); LD_SB2(src0_ptr, src_stride, src5, src2); src0_ptr += (2 * src_stride); @@ -4184,12 +4119,9 @@ static void hevc_vt_biwgt_4t_12w_msa(uint8_t *src0_ptr, ILVL_B2_SB(src5, src4, src2, src5, src54_l, src65_l); src2110 = (v16i8) __msa_ilvr_d((v2i64) src65_l, (v2i64) src54_l); - tmp2 = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, tmp3, tmp3); - tmp5 = const_vec; - DPADD_SB2_SH(src4332, src2110, filt0, filt1, tmp5, tmp5); + tmp2 = HEVC_FILT_4TAP_SH(src32_r, src10_r, filt0, filt1); + tmp3 = HEVC_FILT_4TAP_SH(src43_r, src21_r, filt0, filt1); + tmp5 = HEVC_FILT_4TAP_SH(src4332, src2110, filt0, filt1); HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, @@ -4220,14 +4152,14 @@ static void hevc_vt_biwgt_4t_16w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1, src2, src3, src4, src5; v8i16 in0, in1, in2, in3; v16i8 src10_r, src32_r, src21_r, src43_r; v16i8 src10_l, src32_l, src21_l, src43_l; v8i16 tmp0, tmp1, tmp2, tmp3; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= src_stride; @@ -4235,9 +4167,10 @@ static void hevc_vt_biwgt_4t_16w_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -4261,14 +4194,10 @@ static void hevc_vt_biwgt_4t_16w_msa(uint8_t *src0_ptr, ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); ILVL_B2_SB(src3, src2, src4, src3, src32_l, src43_l); - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); - tmp2 = const_vec; - DPADD_SB2_SH(src10_l, src32_l, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src21_l, src43_l, filt0, filt1, tmp3, tmp3); + tmp0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + tmp1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + tmp2 = HEVC_FILT_4TAP_SH(src10_l, src32_l, filt0, filt1); + tmp3 = HEVC_FILT_4TAP_SH(src21_l, src43_l, filt0, filt1); HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, @@ -4287,14 +4216,10 @@ static void hevc_vt_biwgt_4t_16w_msa(uint8_t *src0_ptr, ILVR_B2_SB(src5, src4, src2, src5, src10_r, src21_r); ILVL_B2_SB(src5, src4, src2, src5, src10_l, src21_l); - tmp0 = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, tmp1, tmp1); - tmp2 = const_vec; - DPADD_SB2_SH(src32_l, src10_l, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src43_l, src21_l, filt0, filt1, tmp3, tmp3); + tmp0 = HEVC_FILT_4TAP_SH(src32_r, src10_r, filt0, filt1); + tmp1 = HEVC_FILT_4TAP_SH(src43_r, src21_r, filt0, filt1); + tmp2 = HEVC_FILT_4TAP_SH(src32_l, src10_l, filt0, filt1); + tmp3 = HEVC_FILT_4TAP_SH(src43_l, src21_l, filt0, filt1); HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, in0, in1, in2, in3, weight_vec, rnd_vec, offset_vec, @@ -4321,7 +4246,7 @@ static void hevc_vt_biwgt_4t_24w_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1, src2, src3, src4, src5; v16i8 src6, src7, src8, src9, src10, src11; v8i16 in0, in1, in2, in3, in4, in5; @@ -4330,7 +4255,7 @@ static void hevc_vt_biwgt_4t_24w_msa(uint8_t *src0_ptr, v16i8 src21_r, src43_r, src87_r, src109_r; v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= src_stride; @@ -4338,9 +4263,10 @@ static void hevc_vt_biwgt_4t_24w_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -4376,19 +4302,13 @@ static void hevc_vt_biwgt_4t_24w_msa(uint8_t *src0_ptr, XORI_B2_128_SB(src9, src10); ILVR_B2_SB(src9, src8, src10, src9, src98_r, src109_r); /* 16width */ - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp4 = const_vec; - DPADD_SB2_SH(src10_l, src32_l, filt0, filt1, tmp4, tmp4); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); - tmp5 = const_vec; - DPADD_SB2_SH(src21_l, src43_l, filt0, filt1, tmp5, tmp5); + tmp0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + tmp4 = HEVC_FILT_4TAP_SH(src10_l, src32_l, filt0, filt1); + tmp1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + tmp5 = HEVC_FILT_4TAP_SH(src21_l, src43_l, filt0, filt1); /* 8width */ - tmp2 = const_vec; - DPADD_SB2_SH(src76_r, src98_r, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src87_r, src109_r, filt0, filt1, tmp3, tmp3); + tmp2 = HEVC_FILT_4TAP_SH(src76_r, src98_r, filt0, filt1); + tmp3 = HEVC_FILT_4TAP_SH(src87_r, src109_r, filt0, filt1); /* 16width */ HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp4, tmp5, in0, in1, in2, in3, @@ -4421,19 +4341,13 @@ static void hevc_vt_biwgt_4t_24w_msa(uint8_t *src0_ptr, XORI_B2_128_SB(src11, src8); ILVR_B2_SB(src11, src10, src8, src11, src76_r, src87_r); /* 16width */ - tmp0 = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, tmp0, tmp0); - tmp4 = const_vec; - DPADD_SB2_SH(src32_l, src10_l, filt0, filt1, tmp4, tmp4); - tmp1 = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, tmp1, tmp1); - tmp5 = const_vec; - DPADD_SB2_SH(src43_l, src21_l, filt0, filt1, tmp5, tmp5); + tmp0 = HEVC_FILT_4TAP_SH(src32_r, src10_r, filt0, filt1); + tmp4 = HEVC_FILT_4TAP_SH(src32_l, src10_l, filt0, filt1); + tmp1 = HEVC_FILT_4TAP_SH(src43_r, src21_r, filt0, filt1); + tmp5 = HEVC_FILT_4TAP_SH(src43_l, src21_l, filt0, filt1); /* 8width */ - tmp2 = const_vec; - DPADD_SB2_SH(src98_r, src76_r, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src109_r, src87_r, filt0, filt1, tmp3, tmp3); + tmp2 = HEVC_FILT_4TAP_SH(src98_r, src76_r, filt0, filt1); + tmp3 = HEVC_FILT_4TAP_SH(src109_r, src87_r, filt0, filt1); /* 16width */ HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp4, tmp5, in0, in1, in2, in3, @@ -4470,7 +4384,7 @@ static void hevc_vt_biwgt_4t_32w_msa(uint8_t *src0_ptr, { uint32_t loop_cnt; uint8_t *dst_tmp = dst + 16; - int32_t offset, weight; + int32_t offset, weight, constant; v16i8 src0, src1, src2, src3, src4, src6, src7, src8, src9, src10; v8i16 in0, in1, in2, in3, in4, in5, in6, in7; v16i8 src10_r, src32_r, src76_r, src98_r; @@ -4479,7 +4393,7 @@ static void hevc_vt_biwgt_4t_32w_msa(uint8_t *src0_ptr, v16i8 src10_l, src32_l, src76_l, src98_l; v16i8 src21_l, src43_l, src87_l, src109_l; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec; v4i32 weight_vec, offset_vec, rnd_vec; src0_ptr -= src_stride; @@ -4487,9 +4401,10 @@ static void hevc_vt_biwgt_4t_32w_msa(uint8_t *src0_ptr, offset = (offset0 + offset1) << rnd_val; weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); + constant = 128 * weight1; + constant <<= 6; + offset += constant; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; offset_vec = __msa_fill_w(offset); weight_vec = __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); @@ -4519,14 +4434,10 @@ static void hevc_vt_biwgt_4t_32w_msa(uint8_t *src0_ptr, ILVL_B2_SB(src3, src2, src4, src3, src32_l, src43_l); /* 16width */ - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp4 = const_vec; - DPADD_SB2_SH(src10_l, src32_l, filt0, filt1, tmp4, tmp4); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); - tmp5 = const_vec; - DPADD_SB2_SH(src21_l, src43_l, filt0, filt1, tmp5, tmp5); + tmp0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + tmp4 = HEVC_FILT_4TAP_SH(src10_l, src32_l, filt0, filt1); + tmp1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + tmp5 = HEVC_FILT_4TAP_SH(src21_l, src43_l, filt0, filt1); /* 16width */ HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp4, tmp5, in0, in1, in2, in3, @@ -4553,14 +4464,10 @@ static void hevc_vt_biwgt_4t_32w_msa(uint8_t *src0_ptr, ILVR_B2_SB(src9, src8, src10, src9, src98_r, src109_r); ILVL_B2_SB(src9, src8, src10, src9, src98_l, src109_l); /* next 16width */ - tmp2 = const_vec; - DPADD_SB2_SH(src76_r, src98_r, filt0, filt1, tmp2, tmp2); - tmp6 = const_vec; - DPADD_SB2_SH(src76_l, src98_l, filt0, filt1, tmp6, tmp6); - tmp3 = const_vec; - DPADD_SB2_SH(src87_r, src109_r, filt0, filt1, tmp3, tmp3); - tmp7 = const_vec; - DPADD_SB2_SH(src87_l, src109_l, filt0, filt1, tmp7, tmp7); + tmp2 = HEVC_FILT_4TAP_SH(src76_r, src98_r, filt0, filt1); + tmp6 = HEVC_FILT_4TAP_SH(src76_l, src98_l, filt0, filt1); + tmp3 = HEVC_FILT_4TAP_SH(src87_r, src109_r, filt0, filt1); + tmp7 = HEVC_FILT_4TAP_SH(src87_l, src109_l, filt0, filt1); /* next 16width */ HEVC_BIW_RND_CLIP4(tmp2, tmp3, tmp6, tmp7, in4, in5, in6, in7, From 3357b68bc02d855a92656d7a474b22adb32ca1a7 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Wed, 1 Nov 2017 15:14:22 +0100 Subject: [PATCH 0740/2557] lavc/alac: Avoid allocating huge memory blocks for malicious alac input. --- libavcodec/alac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/alac.c b/libavcodec/alac.c index d6bd21ba1351a..93cf198eeafe5 100644 --- a/libavcodec/alac.c +++ b/libavcodec/alac.c @@ -524,7 +524,7 @@ static int alac_set_info(ALACContext *alac) alac->max_samples_per_frame = bytestream2_get_be32u(&gb); if (!alac->max_samples_per_frame || - alac->max_samples_per_frame > INT_MAX / sizeof(int32_t)) { + alac->max_samples_per_frame > 4096 * 4096) { av_log(alac->avctx, AV_LOG_ERROR, "max samples per frame invalid: %"PRIu32"\n", alac->max_samples_per_frame); From 22241208eb7d0168b2afc128af5a128a9ef0a89b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Gro=C3=9Fe?= Date: Mon, 30 Oct 2017 12:25:26 +0100 Subject: [PATCH 0741/2557] avconv.c: fix calculation of input file duration in seek_to_start() Fixes looping files without audio or when using stream_copy, where ist->nb_samples is not set since no decoding is done. Signed-off-by: Diego Biurrun --- avtools/avconv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/avtools/avconv.c b/avtools/avconv.c index 4e3ffecdefe90..cee7a7b452515 100644 --- a/avtools/avconv.c +++ b/avtools/avconv.c @@ -2553,9 +2553,9 @@ static int seek_to_start(InputFile *ifile, AVFormatContext *is) continue; } else { if (ist->framerate.num) { - duration = av_rescale_q(1, ist->framerate, ist->st->time_base); + duration = FFMAX(av_rescale_q(1, av_inv_q(ist->framerate), ist->st->time_base), 1); } else if (ist->st->avg_frame_rate.num) { - duration = av_rescale_q(1, ist->st->avg_frame_rate, ist->st->time_base); + duration = FFMAX(av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), ist->st->time_base), 1); } else duration = 1; } if (!ifile->duration) From 03b82b3ab9883cef017e513c7d0b3b986b3b3e7b Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Sat, 4 Nov 2017 17:41:06 +0000 Subject: [PATCH 0742/2557] h2645_parse: Allocate a single buffer per packet Drastically reduces memory usage on pathological streams. Fixes ticket #6789 --- libavcodec/h2645_parse.c | 21 ++++++++++++--------- libavcodec/h2645_parse.h | 10 ++++++++-- libavcodec/h264_parser.c | 13 +++++++++---- libavcodec/qsvenc_hevc.c | 13 +++++++++---- 4 files changed, 38 insertions(+), 19 deletions(-) diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c index 3fbbaf4d29445..e6c40381b0904 100644 --- a/libavcodec/h2645_parse.c +++ b/libavcodec/h2645_parse.c @@ -31,11 +31,10 @@ #include "h2645_parse.h" int ff_h2645_extract_rbsp(const uint8_t *src, int length, - H2645NAL *nal, int small_padding) + H2645RBSP *rbsp, H2645NAL *nal, int small_padding) { int i, si, di; uint8_t *dst; - int64_t padding = small_padding ? 0 : MAX_MBPAIR_SIZE; nal->skipped_bytes = 0; #define STARTCODE_TEST \ @@ -92,11 +91,7 @@ int ff_h2645_extract_rbsp(const uint8_t *src, int length, } else if (i > length) i = length; - av_fast_padded_malloc(&nal->rbsp_buffer, &nal->rbsp_buffer_size, - length + padding); - if (!nal->rbsp_buffer) - return AVERROR(ENOMEM); - + nal->rbsp_buffer = &rbsp->rbsp_buffer[rbsp->rbsp_buffer_size]; dst = nal->rbsp_buffer; memcpy(dst, src, i); @@ -145,6 +140,8 @@ int ff_h2645_extract_rbsp(const uint8_t *src, int length, nal->size = di; nal->raw_data = src; nal->raw_size = si; + rbsp->rbsp_buffer_size += si; + return si; } @@ -270,9 +267,14 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, GetByteContext bc; int consumed, ret = 0; int next_avc = is_nalff ? 0 : length; + int64_t padding = small_padding ? 0 : MAX_MBPAIR_SIZE; bytestream2_init(&bc, buf, length); + av_fast_padded_malloc(&pkt->rbsp.rbsp_buffer, &pkt->rbsp.rbsp_buffer_alloc_size, length + padding); + if (!pkt->rbsp.rbsp_buffer) + return AVERROR(ENOMEM); + pkt->rbsp.rbsp_buffer_size = 0; pkt->nb_nals = 0; while (bytestream2_get_bytes_left(&bc) >= 4) { H2645NAL *nal; @@ -341,7 +343,7 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, } nal = &pkt->nals[pkt->nb_nals]; - consumed = ff_h2645_extract_rbsp(bc.buffer, extract_length, nal, small_padding); + consumed = ff_h2645_extract_rbsp(bc.buffer, extract_length, &pkt->rbsp, nal, small_padding); if (consumed < 0) return consumed; @@ -385,9 +387,10 @@ void ff_h2645_packet_uninit(H2645Packet *pkt) { int i; for (i = 0; i < pkt->nals_allocated; i++) { - av_freep(&pkt->nals[i].rbsp_buffer); av_freep(&pkt->nals[i].skipped_bytes_pos); } av_freep(&pkt->nals); pkt->nals_allocated = 0; + av_freep(&pkt->rbsp.rbsp_buffer); + pkt->rbsp.rbsp_buffer_alloc_size = pkt->rbsp.rbsp_buffer_size = 0; } diff --git a/libavcodec/h2645_parse.h b/libavcodec/h2645_parse.h index 5f3e17a0f258b..2e29ad26cbca5 100644 --- a/libavcodec/h2645_parse.h +++ b/libavcodec/h2645_parse.h @@ -30,7 +30,6 @@ typedef struct H2645NAL { uint8_t *rbsp_buffer; - int rbsp_buffer_size; int size; const uint8_t *data; @@ -65,9 +64,16 @@ typedef struct H2645NAL { int ref_idc; } H2645NAL; +typedef struct H2645RBSP { + uint8_t *rbsp_buffer; + int rbsp_buffer_alloc_size; + int rbsp_buffer_size; +} H2645RBSP; + /* an input packet split into unescaped NAL units */ typedef struct H2645Packet { H2645NAL *nals; + H2645RBSP rbsp; int nb_nals; int nals_allocated; } H2645Packet; @@ -75,7 +81,7 @@ typedef struct H2645Packet { /** * Extract the raw (unescaped) bitstream. */ -int ff_h2645_extract_rbsp(const uint8_t *src, int length, +int ff_h2645_extract_rbsp(const uint8_t *src, int length, H2645RBSP *rbsp, H2645NAL *nal, int small_padding); /** diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index dd0a965af033e..39f97e00a6126 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -243,6 +243,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, const uint8_t * const buf, int buf_size) { H264ParseContext *p = s->priv_data; + H2645RBSP rbsp = { NULL }; H2645NAL nal = { NULL }; int buf_index, next_avc; unsigned int pps_id; @@ -263,6 +264,10 @@ static inline int parse_nal_units(AVCodecParserContext *s, if (!buf_size) return 0; + av_fast_padded_malloc(&rbsp.rbsp_buffer, &rbsp.rbsp_buffer_alloc_size, buf_size); + if (!rbsp.rbsp_buffer) + return AVERROR(ENOMEM); + buf_index = 0; next_avc = p->is_avc ? 0 : buf_size; for (;;) { @@ -300,7 +305,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, } break; } - consumed = ff_h2645_extract_rbsp(buf + buf_index, src_length, &nal, 1); + consumed = ff_h2645_extract_rbsp(buf + buf_index, src_length, &rbsp, &nal, 1); if (consumed < 0) break; @@ -544,18 +549,18 @@ static inline int parse_nal_units(AVCodecParserContext *s, p->last_frame_num = p->poc.frame_num; } - av_freep(&nal.rbsp_buffer); + av_freep(&rbsp.rbsp_buffer); return 0; /* no need to evaluate the rest */ } } if (q264) { - av_freep(&nal.rbsp_buffer); + av_freep(&rbsp.rbsp_buffer); return 0; } /* didn't find a picture! */ av_log(avctx, AV_LOG_ERROR, "missing picture in access unit with size %d\n", buf_size); fail: - av_freep(&nal.rbsp_buffer); + av_freep(&rbsp.rbsp_buffer); return -1; } diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index b0e5ace7c7d88..ff396b278413e 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -56,6 +56,7 @@ static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx) PutByteContext pbc; GetBitContext gb; + H2645RBSP sps_rbsp = { NULL }; H2645NAL sps_nal = { NULL }; HEVCSPS sps = { 0 }; HEVCVPS vps = { 0 }; @@ -69,8 +70,12 @@ static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx) return AVERROR_UNKNOWN; } + av_fast_padded_malloc(&sps_rbsp.rbsp_buffer, &sps_rbsp.rbsp_buffer_alloc_size, avctx->extradata_size); + if (!sps_rbsp.rbsp_buffer) + return AVERROR(ENOMEM); + /* parse the SPS */ - ret = ff_h2645_extract_rbsp(avctx->extradata + 4, avctx->extradata_size - 4, &sps_nal, 1); + ret = ff_h2645_extract_rbsp(avctx->extradata + 4, avctx->extradata_size - 4, &sps_rbsp, &sps_nal, 1); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error unescaping the SPS buffer\n"); return ret; @@ -78,7 +83,7 @@ static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx) ret = init_get_bits8(&gb, sps_nal.data, sps_nal.size); if (ret < 0) { - av_freep(&sps_nal.rbsp_buffer); + av_freep(&sps_rbsp.rbsp_buffer); return ret; } @@ -87,13 +92,13 @@ static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx) if (type != HEVC_NAL_SPS) { av_log(avctx, AV_LOG_ERROR, "Unexpected NAL type in the extradata: %d\n", type); - av_freep(&sps_nal.rbsp_buffer); + av_freep(&sps_rbsp.rbsp_buffer); return AVERROR_INVALIDDATA; } get_bits(&gb, 9); ret = ff_hevc_parse_sps(&sps, &gb, &sps_id, 0, NULL, avctx); - av_freep(&sps_nal.rbsp_buffer); + av_freep(&sps_rbsp.rbsp_buffer); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error parsing the SPS\n"); return ret; From 77748d12a01de6f290a9d3663a0b777d752ac5b7 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Wed, 30 Aug 2017 14:38:46 +0100 Subject: [PATCH 0743/2557] h264: Make Truncating SPS/PPS message debug. --- libavcodec/h264_ps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index b7d5f65d32694..8d1ef831fadff 100644 --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -348,7 +348,7 @@ int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx, sps->data_size = gb->buffer_end - gb->buffer; if (sps->data_size > sizeof(sps->data)) { - av_log(avctx, AV_LOG_WARNING, "Truncating likely oversized SPS\n"); + av_log(avctx, AV_LOG_DEBUG, "Truncating likely oversized SPS\n"); sps->data_size = sizeof(sps->data); } memcpy(sps->data, gb->buffer, sps->data_size); @@ -745,7 +745,7 @@ int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avct pps->data_size = gb->buffer_end - gb->buffer; if (pps->data_size > sizeof(pps->data)) { - av_log(avctx, AV_LOG_WARNING, "Truncating likely oversized PPS " + av_log(avctx, AV_LOG_DEBUG, "Truncating likely oversized PPS " "(%"SIZE_SPECIFIER" > %"SIZE_SPECIFIER")\n", pps->data_size, sizeof(pps->data)); pps->data_size = sizeof(pps->data); From 626d200e76e15487cff20992256a55919432b0b3 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Mon, 24 Jul 2017 19:25:41 +0100 Subject: [PATCH 0744/2557] vc2enc: Calculate average slice quantiser correctly --- libavcodec/vc2enc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c index 96e27d93ede2d..f7fb17b0761c6 100644 --- a/libavcodec/vc2enc.c +++ b/libavcodec/vc2enc.c @@ -167,7 +167,7 @@ typedef struct VC2EncContext { int slice_max_bytes; int slice_min_bytes; int q_ceil; - int q_avg; + int64_t q_avg; /* Options */ double tolerance; @@ -755,7 +755,7 @@ static int calc_slice_sizes(VC2EncContext *s) for (i = 0; i < s->num_x*s->num_y; i++) { SliceArgs *args = &enc_args[i]; total_bytes_needed += args->bytes; - s->q_avg = (s->q_avg + args->quant_idx)/2; + s->q_avg += args->quant_idx; } return total_bytes_needed; @@ -1045,7 +1045,7 @@ static av_cold int vc2_encode_end(AVCodecContext *avctx) int i; VC2EncContext *s = avctx->priv_data; - av_log(avctx, AV_LOG_INFO, "Qavg: %i\n", s->q_avg); + av_log(avctx, AV_LOG_INFO, "Qavg: %f\n", (float)s->q_avg / (s->num_x*s->num_y)); for (i = 0; i < 3; i++) { ff_vc2enc_free_transforms(&s->transform_args[i].t); From 84d31e2475c41b0a69a11c4cba54755d034bb341 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 28 Oct 2017 22:06:22 +0200 Subject: [PATCH 0745/2557] ffplay: create the window and the renderer before starting playback Signed-off-by: Marton Balint --- fftools/ffplay.c | 67 +++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 8e88a77820eed..7f1971aae5a99 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -361,6 +361,7 @@ static AVPacket flush_pkt; static SDL_Window *window; static SDL_Renderer *renderer; +static SDL_RendererInfo renderer_info = {0}; static const struct TextureFormatEntry { enum AVPixelFormat format; @@ -1320,38 +1321,15 @@ static int video_open(VideoState *is) h = default_height; } - if (!window) { - int flags = SDL_WINDOW_SHOWN; - if (!window_title) - window_title = input_filename; - if (is_full_screen) - flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; - if (borderless) - flags |= SDL_WINDOW_BORDERLESS; - else - flags |= SDL_WINDOW_RESIZABLE; - window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, flags); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); - if (window) { - SDL_RendererInfo info; - renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); - if (!renderer) { - av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError()); - renderer = SDL_CreateRenderer(window, -1, 0); - } - if (renderer) { - if (!SDL_GetRendererInfo(renderer, &info)) - av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", info.name); - } - } - } else { - SDL_SetWindowSize(window, w, h); - } + if (!window_title) + window_title = input_filename; + SDL_SetWindowTitle(window, window_title); - if (!window || !renderer) { - av_log(NULL, AV_LOG_FATAL, "SDL: could not set video mode - exiting\n"); - do_exit(is); - } + SDL_SetWindowSize(window, w, h); + SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + if (is_full_screen) + SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); + SDL_ShowWindow(window); is->width = w; is->height = h; @@ -1362,7 +1340,7 @@ static int video_open(VideoState *is) /* display the current picture, if any */ static void video_display(VideoState *is) { - if (!window) + if (!is->width) video_open(is); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); @@ -3744,6 +3722,31 @@ int main(int argc, char **argv) av_init_packet(&flush_pkt); flush_pkt.data = (uint8_t *)&flush_pkt; + if (!display_disable) { + int flags = SDL_WINDOW_HIDDEN; + if (borderless) + flags |= SDL_WINDOW_BORDERLESS; + else + flags |= SDL_WINDOW_RESIZABLE; + window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); + if (window) { + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (!renderer) { + av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError()); + renderer = SDL_CreateRenderer(window, -1, 0); + } + if (renderer) { + if (!SDL_GetRendererInfo(renderer, &renderer_info)) + av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", renderer_info.name); + } + } + if (!window || !renderer) { + av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError()); + do_exit(NULL); + } + } + is = stream_open(input_filename, file_iformat); if (!is) { av_log(NULL, AV_LOG_FATAL, "Failed to initialize VideoState!\n"); From 415038f2bd321a3b41564d4e0c6c17d7a096c397 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 28 Oct 2017 22:46:08 +0200 Subject: [PATCH 0746/2557] ffplay: only use hardware accelerated SDL texture formats Typically only a small subset of the SDL texture formats are supported directly by the SDL renderer drivers, the rest is software emulated. It's better if libswscale does the format conversion to a hardware-accelerated texture format instead of SDL. This should fix video render slowdowns with some texture formats after 3bd2228d05a05eab5f91ac00b01efac9cb07649b. Signed-off-by: Marton Balint --- fftools/ffplay.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 7f1971aae5a99..c264e92535380 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -1828,10 +1828,18 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c AVCodecParameters *codecpar = is->video_st->codecpar; AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL); AVDictionaryEntry *e = NULL; - int i; + int nb_pix_fmts = 0; + int i, j; - for (i = 0; i < FF_ARRAY_ELEMS(pix_fmts); i++) - pix_fmts[i] = sdl_texture_format_map[i].format; + for (i = 0; i < renderer_info.num_texture_formats; i++) { + for (j = 0; j < FF_ARRAY_ELEMS(sdl_texture_format_map) - 1; j++) { + if (renderer_info.texture_formats[i] == sdl_texture_format_map[j].texture_fmt) { + pix_fmts[nb_pix_fmts++] = sdl_texture_format_map[j].format; + break; + } + } + } + pix_fmts[nb_pix_fmts] = AV_PIX_FMT_NONE; while ((e = av_dict_get(sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) { if (!strcmp(e->key, "sws_flags")) { @@ -3741,7 +3749,7 @@ int main(int argc, char **argv) av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", renderer_info.name); } } - if (!window || !renderer) { + if (!window || !renderer || !renderer_info.num_texture_formats) { av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError()); do_exit(NULL); } From 1358f7ddb3a0b3ebbf2c6100fb31c2c4788b7458 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Sat, 4 Nov 2017 18:31:59 +0000 Subject: [PATCH 0747/2557] Revert "vc2enc: Calculate average slice quantiser correctly" This reverts commit 626d200e76e15487cff20992256a55919432b0b3. --- libavcodec/vc2enc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c index f7fb17b0761c6..96e27d93ede2d 100644 --- a/libavcodec/vc2enc.c +++ b/libavcodec/vc2enc.c @@ -167,7 +167,7 @@ typedef struct VC2EncContext { int slice_max_bytes; int slice_min_bytes; int q_ceil; - int64_t q_avg; + int q_avg; /* Options */ double tolerance; @@ -755,7 +755,7 @@ static int calc_slice_sizes(VC2EncContext *s) for (i = 0; i < s->num_x*s->num_y; i++) { SliceArgs *args = &enc_args[i]; total_bytes_needed += args->bytes; - s->q_avg += args->quant_idx; + s->q_avg = (s->q_avg + args->quant_idx)/2; } return total_bytes_needed; @@ -1045,7 +1045,7 @@ static av_cold int vc2_encode_end(AVCodecContext *avctx) int i; VC2EncContext *s = avctx->priv_data; - av_log(avctx, AV_LOG_INFO, "Qavg: %f\n", (float)s->q_avg / (s->num_x*s->num_y)); + av_log(avctx, AV_LOG_INFO, "Qavg: %i\n", s->q_avg); for (i = 0; i < 3; i++) { ff_vc2enc_free_transforms(&s->transform_args[i].t); From 8e0febe28effe7f427e45190eab37110126161ea Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 4 Nov 2017 18:50:30 +0100 Subject: [PATCH 0748/2557] configure: Use right variable and right value for AIX ar flags --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 6f96a06f03c73..d43bd6ee86e6b 100755 --- a/configure +++ b/configure @@ -3812,7 +3812,7 @@ case $target_os in SHFLAGS=-shared add_cppflags '-I\$(SRC_PATH)/compat/aix' enabled shared && add_ldflags -Wl,-brtl - ar_default='ar -Xany' + arflags='-Xany -r -c' ;; android) disable symver From 66f0c958bfd5475658b432d1af4d2e174b2dfcda Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 4 Nov 2017 01:19:19 +0100 Subject: [PATCH 0749/2557] avcodec/exr: fix undefined shift in pxr24_uncompress() Fixes: runtime error: left shift of 255 by 24 places cannot be represented in type 'int' Fixes: 3787/clusterfuzz-testcase-minimized-5728764920070144 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer --- libavcodec/exr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 0b755db3cb3e8..b1ecde4ebd37d 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -855,7 +855,7 @@ static int pxr24_uncompress(EXRContext *s, const uint8_t *src, in = ptr[2] + td->xsize; for (j = 0; j < td->xsize; ++j) { - uint32_t diff = (*(ptr[0]++) << 24) | + uint32_t diff = ((unsigned)*(ptr[0]++) << 24) | (*(ptr[1]++) << 16) | (*(ptr[2]++) << 8); pixel += diff; From 4b51437dccd62fc5491280db44e3c21b44aeeb3f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 3 Nov 2017 17:48:29 +0100 Subject: [PATCH 0750/2557] avcodec/xan: Check for bitstream end in xan_huffman_decode() Fixes: Timeout Fixes: 3707/clusterfuzz-testcase-6465922706440192 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/xan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/xan.c b/libavcodec/xan.c index 8b4ec82405c07..1ccf164847bb7 100644 --- a/libavcodec/xan.c +++ b/libavcodec/xan.c @@ -131,7 +131,10 @@ static int xan_huffman_decode(uint8_t *dest, int dest_len, return ret; while (val != 0x16) { - unsigned idx = val - 0x17 + get_bits1(&gb) * byte; + unsigned idx; + if (get_bits_left(&gb) < 1) + return AVERROR_INVALIDDATA; + idx = val - 0x17 + get_bits1(&gb) * byte; if (idx >= 2 * byte) return AVERROR_INVALIDDATA; val = src[idx]; From 1e7e9fbb03c36b51ca7999ff2450afd64e789011 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Fri, 3 Nov 2017 12:29:58 +0530 Subject: [PATCH 0751/2557] avcodec/mips: Improve hevc uni 4 tap hz and vt mc msa functions Use global mask buffer for appropriate mask load. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_uni_msa.c | 509 ++++++++++++++++-------------- 1 file changed, 274 insertions(+), 235 deletions(-) diff --git a/libavcodec/mips/hevc_mc_uni_msa.c b/libavcodec/mips/hevc_mc_uni_msa.c index 7d24858ba73ec..993dad06aa6b0 100644 --- a/libavcodec/mips/hevc_mc_uni_msa.c +++ b/libavcodec/mips/hevc_mc_uni_msa.c @@ -1947,7 +1947,7 @@ static void common_hz_4t_4x2_msa(uint8_t *src, int32_t src_stride, v16u8 out; v8i16 filt, res0; - mask0 = LD_SB(&mc_filt_mask_arr[16]); + mask0 = LD_SB(&ff_hevc_mask_arr[16]); src -= 1; /* rearranging filter */ @@ -1959,7 +1959,7 @@ static void common_hz_4t_4x2_msa(uint8_t *src, int32_t src_stride, LD_SB2(src, src_stride, src0, src1); XORI_B2_128_SB(src0, src1); VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); - res0 = FILT_4TAP_DPADD_S_H(vec0, vec1, filt0, filt1); + res0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); res0 = __msa_srari_h(res0, 6); res0 = __msa_sat_s_h(res0, 7); out = PCKEV_XORI128_UB(res0, res0); @@ -1974,7 +1974,7 @@ static void common_hz_4t_4x4_msa(uint8_t *src, int32_t src_stride, v8i16 filt, out0, out1; v16u8 out; - mask0 = LD_SB(&mc_filt_mask_arr[16]); + mask0 = LD_SB(&ff_hevc_mask_arr[16]); src -= 1; /* rearranging filter */ @@ -2001,7 +2001,7 @@ static void common_hz_4t_4x8_msa(uint8_t *src, int32_t src_stride, v16u8 out; v8i16 filt, out0, out1, out2, out3; - mask0 = LD_SB(&mc_filt_mask_arr[16]); + mask0 = LD_SB(&ff_hevc_mask_arr[16]); src -= 1; /* rearranging filter */ @@ -2038,7 +2038,7 @@ static void common_hz_4t_4x16_msa(uint8_t *src, int32_t src_stride, v16u8 out; v8i16 filt, out0, out1, out2, out3; - mask0 = LD_SB(&mc_filt_mask_arr[16]); + mask0 = LD_SB(&ff_hevc_mask_arr[16]); src -= 1; /* rearranging filter */ @@ -2098,12 +2098,11 @@ static void common_hz_4t_6w_msa(uint8_t *src, int32_t src_stride, uint8_t *dst, int32_t dst_stride, const int8_t *filter, int32_t height) { - uint32_t loop_cnt; v16i8 src0, src1, src2, src3, filt0, filt1, mask0, mask1; v16u8 out4, out5; v8i16 filt, out0, out1, out2, out3; - mask0 = LD_SB(&mc_filt_mask_arr[0]); + mask0 = LD_SB(&ff_hevc_mask_arr[0]); src -= 1; /* rearranging filter */ @@ -2112,21 +2111,31 @@ static void common_hz_4t_6w_msa(uint8_t *src, int32_t src_stride, mask1 = mask0 + 2; - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB4(src, src_stride, src0, src1, src2, src3); - src += (4 * src_stride); + LD_SB4(src, src_stride, src0, src1, src2, src3); + src += (4 * src_stride); - XORI_B4_128_SB(src0, src1, src2, src3); - HORIZ_4TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, filt0, - filt1, out0, out1, out2, out3); - SRARI_H4_SH(out0, out1, out2, out3, 6); - SAT_SH4_SH(out0, out1, out2, out3, 7); + XORI_B4_128_SB(src0, src1, src2, src3); + HORIZ_4TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, filt0, + filt1, out0, out1, out2, out3); + SRARI_H4_SH(out0, out1, out2, out3, 6); + SAT_SH4_SH(out0, out1, out2, out3, 7); + out4 = PCKEV_XORI128_UB(out0, out1); + out5 = PCKEV_XORI128_UB(out2, out3); + ST6x4_UB(out4, out5, dst, dst_stride); + dst += (4 * dst_stride); - out4 = PCKEV_XORI128_UB(out0, out1); - out5 = PCKEV_XORI128_UB(out2, out3); - ST6x4_UB(out4, out5, dst, dst_stride); - dst += (4 * dst_stride); - } + LD_SB4(src, src_stride, src0, src1, src2, src3); + src += (4 * src_stride); + + XORI_B4_128_SB(src0, src1, src2, src3); + HORIZ_4TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, filt0, + filt1, out0, out1, out2, out3); + SRARI_H4_SH(out0, out1, out2, out3, 6); + SAT_SH4_SH(out0, out1, out2, out3, 7); + out4 = PCKEV_XORI128_UB(out0, out1); + out5 = PCKEV_XORI128_UB(out2, out3); + ST6x4_UB(out4, out5, dst, dst_stride); + dst += (4 * dst_stride); } static void common_hz_4t_8x2mult_msa(uint8_t *src, int32_t src_stride, @@ -2138,7 +2147,7 @@ static void common_hz_4t_8x2mult_msa(uint8_t *src, int32_t src_stride, v16u8 out; v8i16 filt, vec0, vec1, vec2, vec3; - mask0 = LD_SB(&mc_filt_mask_arr[0]); + mask0 = LD_SB(&ff_hevc_mask_arr[0]); src -= 1; filt = LD_SH(filter); @@ -2172,7 +2181,7 @@ static void common_hz_4t_8x4mult_msa(uint8_t *src, int32_t src_stride, v16u8 tmp0, tmp1; v8i16 filt, out0, out1, out2, out3; - mask0 = LD_SB(&mc_filt_mask_arr[0]); + mask0 = LD_SB(&ff_hevc_mask_arr[0]); src -= 1; /* rearranging filter */ @@ -2221,8 +2230,8 @@ static void common_hz_4t_12w_msa(uint8_t *src, int32_t src_stride, v16u8 tmp0, tmp1; v8i16 filt, out0, out1, out2, out3, out4, out5; - mask0 = LD_SB(&mc_filt_mask_arr[0]); - mask2 = LD_SB(&mc_filt_mask_arr[32]); + mask0 = LD_SB(&ff_hevc_mask_arr[0]); + mask2 = LD_SB(&ff_hevc_mask_arr[32]); src -= 1; @@ -2233,32 +2242,33 @@ static void common_hz_4t_12w_msa(uint8_t *src, int32_t src_stride, mask1 = mask0 + 2; mask3 = mask2 + 2; - for (loop_cnt = (height >> 2); loop_cnt--;) { + for (loop_cnt = 4; loop_cnt--;) { LD_SB4(src, src_stride, src0, src1, src2, src3); src += (4 * src_stride); XORI_B4_128_SB(src0, src1, src2, src3); + VSHF_B2_SB(src0, src1, src2, src3, mask2, mask2, vec0, vec1); + DOTP_SB2_SH(vec0, vec1, filt0, filt0, out0, out1); + VSHF_B2_SB(src0, src1, src2, src3, mask3, mask3, vec2, vec3); + DPADD_SB2_SH(vec2, vec3, filt1, filt1, out0, out1); + SRARI_H2_SH(out0, out1, 6); + SAT_SH2_SH(out0, out1, 7); + tmp0 = PCKEV_XORI128_UB(out0, out1); + ST4x4_UB(tmp0, tmp0, 0, 1, 2, 3, dst + 8, dst_stride); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec4, vec5); VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec6, vec7); - VSHF_B2_SB(src0, src1, src2, src3, mask2, mask2, vec0, vec1); DOTP_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt0, filt0, filt0, out2, out3, out4, out5); - DOTP_SB2_SH(vec0, vec1, filt0, filt0, out0, out1); VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec8, vec9); VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec10, vec11); - VSHF_B2_SB(src0, src1, src2, src3, mask3, mask3, vec2, vec3); DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt1, filt1, filt1, filt1, out2, out3, out4, out5); - DPADD_SB2_SH(vec2, vec3, filt1, filt1, out0, out1); - SRARI_H4_SH(out0, out1, out2, out3, 6); - SRARI_H2_SH(out4, out5, 6); - SAT_SH4_SH(out0, out1, out2, out3, 7); - SAT_SH2_SH(out4, out5, 7); + SRARI_H4_SH(out2, out3, out4, out5, 6); + SAT_SH4_SH(out2, out3, out4, out5, 7); tmp0 = PCKEV_XORI128_UB(out2, out3); tmp1 = PCKEV_XORI128_UB(out4, out5); ST8x4_UB(tmp0, tmp1, dst, dst_stride); - tmp0 = PCKEV_XORI128_UB(out0, out1); - ST4x4_UB(tmp0, tmp0, 0, 1, 2, 3, dst + 8, dst_stride); dst += (4 * dst_stride); } } @@ -2270,10 +2280,11 @@ static void common_hz_4t_16w_msa(uint8_t *src, int32_t src_stride, uint32_t loop_cnt; v16i8 src0, src1, src2, src3, src4, src5, src6, src7; v16i8 filt0, filt1, mask0, mask1; + v16i8 vec0_m, vec1_m, vec2_m, vec3_m; v8i16 filt, out0, out1, out2, out3, out4, out5, out6, out7; v16u8 out; - mask0 = LD_SB(&mc_filt_mask_arr[0]); + mask0 = LD_SB(&ff_hevc_mask_arr[0]); src -= 1; /* rearranging filter */ @@ -2288,20 +2299,34 @@ static void common_hz_4t_16w_msa(uint8_t *src, int32_t src_stride, src += (4 * src_stride); XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); - HORIZ_4TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, filt0, - filt1, out0, out1, out2, out3); - HORIZ_4TAP_8WID_4VECS_FILT(src4, src5, src6, src7, mask0, mask1, filt0, - filt1, out4, out5, out6, out7); + + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0_m, vec1_m); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2_m, vec3_m); + DOTP_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt0, filt0, filt0, filt0, + out0, out1, out2, out3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec0_m, vec1_m); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2_m, vec3_m); + DPADD_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt1, filt1, filt1, filt1, + out0, out1, out2, out3); SRARI_H4_SH(out0, out1, out2, out3, 6); - SRARI_H4_SH(out4, out5, out6, out7, 6); SAT_SH4_SH(out0, out1, out2, out3, 7); - SAT_SH4_SH(out4, out5, out6, out7, 7); out = PCKEV_XORI128_UB(out0, out1); ST_UB(out, dst); dst += dst_stride; out = PCKEV_XORI128_UB(out2, out3); ST_UB(out, dst); dst += dst_stride; + + VSHF_B2_SB(src4, src4, src5, src5, mask0, mask0, vec0_m, vec1_m); + VSHF_B2_SB(src6, src6, src7, src7, mask0, mask0, vec2_m, vec3_m); + DOTP_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt0, filt0, filt0, filt0, + out4, out5, out6, out7); + VSHF_B2_SB(src4, src4, src5, src5, mask1, mask1, vec0_m, vec1_m); + VSHF_B2_SB(src6, src6, src7, src7, mask1, mask1, vec2_m, vec3_m); + DPADD_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt1, filt1, filt1, filt1, + out4, out5, out6, out7); + SRARI_H4_SH(out4, out5, out6, out7, 6); + SAT_SH4_SH(out4, out5, out6, out7, 7); out = PCKEV_XORI128_UB(out4, out5); ST_UB(out, dst); dst += dst_stride; @@ -2323,7 +2348,7 @@ static void common_hz_4t_24w_msa(uint8_t *src, int32_t src_stride, v8i16 filt, out0, out1, out2, out3; v16u8 tmp0, tmp1; - mask0 = LD_SB(&mc_filt_mask_arr[0]); + mask0 = LD_SB(&ff_hevc_mask_arr[0]); src -= 1; /* rearranging filter */ @@ -2334,7 +2359,7 @@ static void common_hz_4t_24w_msa(uint8_t *src, int32_t src_stride, mask00 = mask0 + 8; mask11 = mask0 + 10; - for (loop_cnt = (height >> 2); loop_cnt--;) { + for (loop_cnt = 8; loop_cnt--;) { LD_SB4(src, src_stride, src0, src2, src4, src6); LD_SB4(src + 16, src_stride, src1, src3, src5, src7); src += (4 * src_stride); @@ -2402,9 +2427,10 @@ static void common_hz_4t_32w_msa(uint8_t *src, int32_t src_stride, v16i8 src0, src1, src2, src3, src4, src5, src6, src7; v16i8 filt0, filt1, mask0, mask1; v16u8 out; + v16i8 vec0_m, vec1_m, vec2_m, vec3_m; v8i16 filt, out0, out1, out2, out3, out4, out5, out6, out7; - mask0 = LD_SB(&mc_filt_mask_arr[0]); + mask0 = LD_SB(&ff_hevc_mask_arr[0]); src -= 1; /* rearranging filter */ @@ -2415,20 +2441,35 @@ static void common_hz_4t_32w_msa(uint8_t *src, int32_t src_stride, for (loop_cnt = (height >> 1); loop_cnt--;) { src0 = LD_SB(src); + src1 = LD_SB(src + 8); src2 = LD_SB(src + 16); src3 = LD_SB(src + 24); src += src_stride; src4 = LD_SB(src); + src5 = LD_SB(src + 8); src6 = LD_SB(src + 16); src7 = LD_SB(src + 24); - SLDI_B2_SB(src2, src6, src0, src4, src1, src5, 8); src += src_stride; XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); - HORIZ_4TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, - filt0, filt1, out0, out1, out2, out3); - HORIZ_4TAP_8WID_4VECS_FILT(src4, src5, src6, src7, mask0, mask1, - filt0, filt1, out4, out5, out6, out7); + + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0_m, vec1_m); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2_m, vec3_m); + DOTP_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt0, filt0, filt0, filt0, + out0, out1, out2, out3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec0_m, vec1_m); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2_m, vec3_m); + DPADD_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt1, filt1, filt1, filt1, + out0, out1, out2, out3); + + VSHF_B2_SB(src4, src4, src5, src5, mask0, mask0, vec0_m, vec1_m); + VSHF_B2_SB(src6, src6, src7, src7, mask0, mask0, vec2_m, vec3_m); + DOTP_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt0, filt0, filt0, filt0, + out4, out5, out6, out7); + VSHF_B2_SB(src4, src4, src5, src5, mask1, mask1, vec0_m, vec1_m); + VSHF_B2_SB(src6, src6, src7, src7, mask1, mask1, vec2_m, vec3_m); + DPADD_SB4_SH(vec0_m, vec1_m, vec2_m, vec3_m, filt1, filt1, filt1, filt1, + out4, out5, out6, out7); SRARI_H4_SH(out0, out1, out2, out3, 6); SRARI_H4_SH(out4, out5, out6, out7, 6); SAT_SH4_SH(out0, out1, out2, out3, 7); @@ -2470,7 +2511,7 @@ static void common_vt_4t_4x2_msa(uint8_t *src, int32_t src_stride, ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); src4332 = (v16i8) __msa_ilvr_d((v2i64) src43_r, (v2i64) src32_r); src4332 = (v16i8) __msa_xori_b((v16u8) src4332, 128); - out10 = FILT_4TAP_DPADD_S_H(src2110, src4332, filt0, filt1); + out10 = HEVC_FILT_4TAP_SH(src2110, src4332, filt0, filt1); out10 = __msa_srari_h(out10, 6); out10 = __msa_sat_s_h(out10, 7); out = PCKEV_XORI128_UB(out10, out10); @@ -2507,14 +2548,14 @@ static void common_vt_4t_4x4multiple_msa(uint8_t *src, int32_t src_stride, ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); src4332 = (v16i8) __msa_ilvr_d((v2i64) src43_r, (v2i64) src32_r); src4332 = (v16i8) __msa_xori_b((v16u8) src4332, 128); - out10 = FILT_4TAP_DPADD_S_H(src2110, src4332, filt0, filt1); + out10 = HEVC_FILT_4TAP_SH(src2110, src4332, filt0, filt1); src2 = LD_SB(src); src += (src_stride); ILVR_B2_SB(src5, src4, src2, src5, src54_r, src65_r); src2110 = (v16i8) __msa_ilvr_d((v2i64) src65_r, (v2i64) src54_r); src2110 = (v16i8) __msa_xori_b((v16u8) src2110, 128); - out32 = FILT_4TAP_DPADD_S_H(src4332, src2110, filt0, filt1); + out32 = HEVC_FILT_4TAP_SH(src4332, src2110, filt0, filt1); SRARI_H2_SH(out10, out32, 6); SAT_SH2_SH(out10, out32, 7); out = PCKEV_XORI128_UB(out10, out32); @@ -2539,51 +2580,65 @@ static void common_vt_4t_6w_msa(uint8_t *src, int32_t src_stride, uint8_t *dst, int32_t dst_stride, const int8_t *filter, int32_t height) { - uint32_t loop_cnt; - v16u8 src0, src1, src2, src3, vec0, vec1, vec2, vec3, out0, out1; - v8i16 vec01, vec12, vec23, vec30, tmp0, tmp1, tmp2, tmp3; - v8i16 filt, filt0, filt1; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4, src5, src6; + v16i8 src10_r, src32_r, src21_r, src43_r, src54_r, src65_r; + v8i16 dst0_r, dst1_r, dst2_r, dst3_r, filt0, filt1, filter_vec; src -= src_stride; - /* rearranging filter_y */ - filt = LD_SH(filter); - SPLATI_H2_SH(filt, 0, 1, filt0, filt1); + filter_vec = LD_SH(filter); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); - LD_UB3(src, src_stride, src0, src1, src2); + LD_SB3(src, src_stride, src0, src1, src2); src += (3 * src_stride); + XORI_B3_128_SB(src0, src1, src2); + ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); - vec0 = (v16u8) __msa_xori_b((v16u8) src0, 128); - vec1 = (v16u8) __msa_xori_b((v16u8) src1, 128); - vec2 = (v16u8) __msa_xori_b((v16u8) src2, 128); + LD_SB2(src, src_stride, src3, src4); + src += (2 * src_stride); + XORI_B2_128_SB(src3, src4); + ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_UB4(src, src_stride, src3, src0, src1, src2); - src += (4 * src_stride); + dst0_r = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + dst1_r = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); - vec3 = (v16u8) __msa_xori_b((v16u8) src3, 128); - ILVR_B2_SH(vec1, vec0, vec3, vec2, vec01, vec23); - tmp0 = FILT_4TAP_DPADD_S_H(vec01, vec23, filt0, filt1); + LD_SB2(src, src_stride, src5, src6); + src += (2 * src_stride); + XORI_B2_128_SB(src5, src6); + ILVR_B2_SB(src5, src4, src6, src5, src54_r, src65_r); - vec0 = __msa_xori_b((v16u8) src0, 128); - ILVR_B2_SH(vec2, vec1, vec0, vec3, vec12, vec30); - tmp1 = FILT_4TAP_DPADD_S_H(vec12, vec30, filt0, filt1); + dst2_r = HEVC_FILT_4TAP_SH(src32_r, src54_r, filt0, filt1); + dst3_r = HEVC_FILT_4TAP_SH(src43_r, src65_r, filt0, filt1); - vec1 = __msa_xori_b((v16u8) src1, 128); - vec01 = (v8i16) __msa_ilvr_b((v16i8) vec1, (v16i8) vec0); - tmp2 = FILT_4TAP_DPADD_S_H(vec23, vec01, filt0, filt1); + SRARI_H4_SH(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SAT_SH4_SH(dst0_r, dst1_r, dst2_r, dst3_r, 7); + out0 = PCKEV_XORI128_UB(dst0_r, dst1_r); + out1 = PCKEV_XORI128_UB(dst2_r, dst3_r); + ST6x4_UB(out0, out1, dst, dst_stride); + dst += (4 * dst_stride); - vec2 = __msa_xori_b((v16u8) src2, 128); - vec12 = (v8i16) __msa_ilvr_b((v16i8) vec2, (v16i8) vec1); - tmp3 = FILT_4TAP_DPADD_S_H(vec30, vec12, filt0, filt1); + LD_SB2(src, src_stride, src3, src4); + src += (2 * src_stride); + XORI_B2_128_SB(src3, src4); + ILVR_B2_SB(src3, src6, src4, src3, src32_r, src43_r); - SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 6); - SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); - out0 = PCKEV_XORI128_UB(tmp0, tmp1); - out1 = PCKEV_XORI128_UB(tmp2, tmp3); - ST6x4_UB(out0, out1, dst, dst_stride); - dst += (4 * dst_stride); - } + dst0_r = HEVC_FILT_4TAP_SH(src54_r, src32_r, filt0, filt1); + dst1_r = HEVC_FILT_4TAP_SH(src65_r, src43_r, filt0, filt1); + + LD_SB2(src, src_stride, src5, src6); + src += (2 * src_stride); + XORI_B2_128_SB(src5, src6); + ILVR_B2_SB(src5, src4, src6, src5, src54_r, src65_r); + + dst2_r = HEVC_FILT_4TAP_SH(src32_r, src54_r, filt0, filt1); + dst3_r = HEVC_FILT_4TAP_SH(src43_r, src65_r, filt0, filt1); + + SRARI_H4_SH(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SAT_SH4_SH(dst0_r, dst1_r, dst2_r, dst3_r, 7); + out0 = PCKEV_XORI128_UB(dst0_r, dst1_r); + out1 = PCKEV_XORI128_UB(dst2_r, dst3_r); + ST6x4_UB(out0, out1, dst, dst_stride); } static void common_vt_4t_8x2_msa(uint8_t *src, int32_t src_stride, @@ -2603,9 +2658,9 @@ static void common_vt_4t_8x2_msa(uint8_t *src, int32_t src_stride, LD_SB5(src, src_stride, src0, src1, src2, src3, src4); XORI_B5_128_SB(src0, src1, src2, src3, src4); ILVR_B2_SH(src1, src0, src3, src2, src01, src23); - tmp0 = FILT_4TAP_DPADD_S_H(src01, src23, filt0, filt1); + tmp0 = HEVC_FILT_4TAP_SH(src01, src23, filt0, filt1); ILVR_B2_SH(src2, src1, src4, src3, src12, src34); - tmp1 = FILT_4TAP_DPADD_S_H(src12, src34, filt0, filt1); + tmp1 = HEVC_FILT_4TAP_SH(src12, src34, filt0, filt1); SRARI_H2_SH(tmp0, tmp1, 6); SAT_SH2_SH(tmp0, tmp1, 7); out = PCKEV_XORI128_UB(tmp0, tmp1); @@ -2640,9 +2695,9 @@ static void common_vt_4t_8x6_msa(uint8_t *src, int32_t src_stride, XORI_B3_128_SB(src3, src4, src5); ILVR_B3_SH(src3, src2, src4, src3, src5, src4, vec1, vec3, vec4); - tmp0 = FILT_4TAP_DPADD_S_H(vec0, vec1, filt0, filt1); - tmp1 = FILT_4TAP_DPADD_S_H(vec2, vec3, filt0, filt1); - tmp2 = FILT_4TAP_DPADD_S_H(vec1, vec4, filt0, filt1); + tmp0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + tmp1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + tmp2 = HEVC_FILT_4TAP_SH(vec1, vec4, filt0, filt1); SRARI_H2_SH(tmp0, tmp1, 6); tmp2 = __msa_srari_h(tmp2, 6); SAT_SH3_SH(tmp0, tmp1, tmp2, 7); @@ -2693,10 +2748,10 @@ static void common_vt_4t_8x4mult_msa(uint8_t *src, int32_t src_stride, XORI_B4_128_SB(src7, src8, src9, src10); ILVR_B4_SB(src7, src2, src8, src7, src9, src8, src10, src9, src72_r, src87_r, src98_r, src109_r); - out0_r = FILT_4TAP_DPADD_S_H(src10_r, src72_r, filt0, filt1); - out1_r = FILT_4TAP_DPADD_S_H(src21_r, src87_r, filt0, filt1); - out2_r = FILT_4TAP_DPADD_S_H(src72_r, src98_r, filt0, filt1); - out3_r = FILT_4TAP_DPADD_S_H(src87_r, src109_r, filt0, filt1); + out0_r = HEVC_FILT_4TAP_SH(src10_r, src72_r, filt0, filt1); + out1_r = HEVC_FILT_4TAP_SH(src21_r, src87_r, filt0, filt1); + out2_r = HEVC_FILT_4TAP_SH(src72_r, src98_r, filt0, filt1); + out3_r = HEVC_FILT_4TAP_SH(src87_r, src109_r, filt0, filt1); SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 6); SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); tmp0 = PCKEV_XORI128_UB(out0_r, out1_r); @@ -2730,58 +2785,60 @@ static void common_vt_4t_12w_msa(uint8_t *src, int32_t src_stride, { uint32_t loop_cnt; v16i8 src0, src1, src2, src3, src4, src5, src6; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; v16u8 out0, out1; - v8i16 src10, src21, src32, src43, src54, src65, src87, src109, src1211; - v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, filt, filt0, filt1; - v4u32 mask = { 2, 6, 2, 6 }; + v16i8 src10_r, src32_r, src21_r, src43_r, src54_r, src65_r; + v16i8 src10_l, src32_l, src54_l, src21_l, src43_l, src65_l; + v16i8 src2110, src4332, src6554; + v8i16 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, filt0, filt1; + v8i16 filter_vec; - /* rearranging filter_y */ - filt = LD_SH(filter); - SPLATI_H2_SH(filt, 0, 1, filt0, filt1); + src -= (1 * src_stride); - src -= src_stride; + filter_vec = LD_SH(filter); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); LD_SB3(src, src_stride, src0, src1, src2); src += (3 * src_stride); XORI_B3_128_SB(src0, src1, src2); - VSHF_W2_SB(src0, src1, src1, src2, mask, mask, vec0, vec1); + ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); + ILVL_B2_SB(src1, src0, src2, src1, src10_l, src21_l); + src2110 = (v16i8) __msa_ilvr_d((v2i64) src21_l, (v2i64) src10_l); - for (loop_cnt = (height >> 2); loop_cnt--;) { + for (loop_cnt = 4; loop_cnt--;) { LD_SB4(src, src_stride, src3, src4, src5, src6); src += (4 * src_stride); XORI_B4_128_SB(src3, src4, src5, src6); - ILVR_B2_SH(src1, src0, src3, src2, src10, src32); - VSHF_W2_SB(src2, src3, src3, src4, mask, mask, vec2, vec3); - VSHF_W2_SB(src4, src5, src5, src6, mask, mask, vec4, vec5); - tmp0 = FILT_4TAP_DPADD_S_H(src10, src32, filt0, filt1); - ILVR_B4_SH(src2, src1, src4, src3, src5, src4, src6, src5, - src21, src43, src54, src65); - tmp1 = FILT_4TAP_DPADD_S_H(src21, src43, filt0, filt1); - tmp2 = FILT_4TAP_DPADD_S_H(src32, src54, filt0, filt1); - tmp3 = FILT_4TAP_DPADD_S_H(src43, src65, filt0, filt1); - ILVR_B3_SH(vec1, vec0, vec3, vec2, vec5, vec4, src87, src109, src1211); - tmp4 = FILT_4TAP_DPADD_S_H(src87, src109, filt0, filt1); - tmp5 = FILT_4TAP_DPADD_S_H(src109, src1211, filt0, filt1); - SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 6); - SRARI_H2_SH(tmp4, tmp5, 6); - SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); - SAT_SH2_SH(tmp4, tmp5, 7); - out0 = PCKEV_XORI128_UB(tmp0, tmp1); - out1 = PCKEV_XORI128_UB(tmp2, tmp3); + ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); + ILVL_B2_SB(src3, src2, src4, src3, src32_l, src43_l); + src4332 = (v16i8) __msa_ilvr_d((v2i64) src43_l, (v2i64) src32_l); + ILVR_B2_SB(src5, src4, src6, src5, src54_r, src65_r); + ILVL_B2_SB(src5, src4, src6, src5, src54_l, src65_l); + src6554 = (v16i8) __msa_ilvr_d((v2i64) src65_l, (v2i64) src54_l); + + dst0_r = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + dst1_r = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + dst0_l = HEVC_FILT_4TAP_SH(src2110, src4332, filt0, filt1); + dst2_r = HEVC_FILT_4TAP_SH(src32_r, src54_r, filt0, filt1); + dst3_r = HEVC_FILT_4TAP_SH(src43_r, src65_r, filt0, filt1); + dst1_l = HEVC_FILT_4TAP_SH(src4332, src6554, filt0, filt1); + + SRARI_H4_SH(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SRARI_H2_SH(dst0_l, dst1_l, 6); + SAT_SH4_SH(dst0_r, dst1_r, dst2_r, dst3_r, 7); + SAT_SH2_SH(dst0_l, dst1_l, 7); + out0 = PCKEV_XORI128_UB(dst0_r, dst1_r); + out1 = PCKEV_XORI128_UB(dst2_r, dst3_r); ST8x4_UB(out0, out1, dst, dst_stride); - out0 = PCKEV_XORI128_UB(tmp4, tmp5); + out0 = PCKEV_XORI128_UB(dst0_l, dst1_l); ST4x4_UB(out0, out0, 0, 1, 2, 3, dst + 8, dst_stride); dst += (4 * dst_stride); - src0 = src4; - src1 = src5; - src2 = src6; - vec0 = vec4; - vec1 = vec5; src2 = src6; + src10_r = src54_r; + src21_r = src65_r; + src2110 = src6554; } } @@ -2817,14 +2874,14 @@ static void common_vt_4t_16w_msa(uint8_t *src, int32_t src_stride, src32_r, src43_r, src54_r, src65_r); ILVL_B4_SB(src3, src2, src4, src3, src5, src4, src6, src5, src32_l, src43_l, src54_l, src65_l); - out0_r = FILT_4TAP_DPADD_S_H(src10_r, src32_r, filt0, filt1); - out1_r = FILT_4TAP_DPADD_S_H(src21_r, src43_r, filt0, filt1); - out2_r = FILT_4TAP_DPADD_S_H(src32_r, src54_r, filt0, filt1); - out3_r = FILT_4TAP_DPADD_S_H(src43_r, src65_r, filt0, filt1); - out0_l = FILT_4TAP_DPADD_S_H(src10_l, src32_l, filt0, filt1); - out1_l = FILT_4TAP_DPADD_S_H(src21_l, src43_l, filt0, filt1); - out2_l = FILT_4TAP_DPADD_S_H(src32_l, src54_l, filt0, filt1); - out3_l = FILT_4TAP_DPADD_S_H(src43_l, src65_l, filt0, filt1); + out0_r = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + out1_r = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + out2_r = HEVC_FILT_4TAP_SH(src32_r, src54_r, filt0, filt1); + out3_r = HEVC_FILT_4TAP_SH(src43_r, src65_r, filt0, filt1); + out0_l = HEVC_FILT_4TAP_SH(src10_l, src32_l, filt0, filt1); + out1_l = HEVC_FILT_4TAP_SH(src21_l, src43_l, filt0, filt1); + out2_l = HEVC_FILT_4TAP_SH(src32_l, src54_l, filt0, filt1); + out3_l = HEVC_FILT_4TAP_SH(src43_l, src65_l, filt0, filt1); SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 6); SRARI_H4_SH(out0_l, out1_l, out2_l, out3_l, 6); SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); @@ -2873,7 +2930,7 @@ static void common_vt_4t_24w_msa(uint8_t *src, int32_t src_stride, XORI_B3_128_SB(src6, src7, src8); ILVR_B2_SB(src7, src6, src8, src7, src76_r, src87_r); - for (loop_cnt = (height >> 2); loop_cnt--;) { + for (loop_cnt = 8; loop_cnt--;) { /* 16 width */ LD_SB2(src, src_stride, src3, src4); XORI_B2_128_SB(src3, src4); @@ -2887,14 +2944,14 @@ static void common_vt_4t_24w_msa(uint8_t *src, int32_t src_stride, ILVR_B2_SB(src9, src8, src10, src9, src98_r, src109_r); /* 16 width */ - out0_r = FILT_4TAP_DPADD_S_H(src10_r, src32_r, filt0, filt1); - out0_l = FILT_4TAP_DPADD_S_H(src10_l, src32_l, filt0, filt1); - out1_r = FILT_4TAP_DPADD_S_H(src21_r, src43_r, filt0, filt1); - out1_l = FILT_4TAP_DPADD_S_H(src21_l, src43_l, filt0, filt1); + out0_r = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + out0_l = HEVC_FILT_4TAP_SH(src10_l, src32_l, filt0, filt1); + out1_r = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + out1_l = HEVC_FILT_4TAP_SH(src21_l, src43_l, filt0, filt1); /* 8 width */ - out2_r = FILT_4TAP_DPADD_S_H(src76_r, src98_r, filt0, filt1); - out3_r = FILT_4TAP_DPADD_S_H(src87_r, src109_r, filt0, filt1); + out2_r = HEVC_FILT_4TAP_SH(src76_r, src98_r, filt0, filt1); + out3_r = HEVC_FILT_4TAP_SH(src87_r, src109_r, filt0, filt1); /* 16 + 8 width */ SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 6); @@ -2927,14 +2984,14 @@ static void common_vt_4t_24w_msa(uint8_t *src, int32_t src_stride, ILVR_B2_SB(src11, src10, src8, src11, src76_r, src87_r); /* 16 width */ - out0_r = FILT_4TAP_DPADD_S_H(src32_r, src10_r, filt0, filt1); - out0_l = FILT_4TAP_DPADD_S_H(src32_l, src10_l, filt0, filt1); - out1_r = FILT_4TAP_DPADD_S_H(src43_r, src21_r, filt0, filt1); - out1_l = FILT_4TAP_DPADD_S_H(src43_l, src21_l, filt0, filt1); + out0_r = HEVC_FILT_4TAP_SH(src32_r, src10_r, filt0, filt1); + out0_l = HEVC_FILT_4TAP_SH(src32_l, src10_l, filt0, filt1); + out1_r = HEVC_FILT_4TAP_SH(src43_r, src21_r, filt0, filt1); + out1_l = HEVC_FILT_4TAP_SH(src43_l, src21_l, filt0, filt1); /* 8 width */ - out2_r = FILT_4TAP_DPADD_S_H(src98_r, src76_r, filt0, filt1); - out3_r = FILT_4TAP_DPADD_S_H(src109_r, src87_r, filt0, filt1); + out2_r = HEVC_FILT_4TAP_SH(src98_r, src76_r, filt0, filt1); + out3_r = HEVC_FILT_4TAP_SH(src109_r, src87_r, filt0, filt1); /* 16 + 8 width */ SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 6); @@ -2954,13 +3011,11 @@ static void common_vt_4t_24w_msa(uint8_t *src, int32_t src_stride, } } -static void common_vt_4t_32w_mult_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - const int8_t *filter, int32_t height, - int32_t width) +static void common_vt_4t_32w_msa(uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) { - uint32_t loop_cnt, cnt; - uint8_t *dst_tmp, *src_tmp; + uint32_t loop_cnt; v16i8 src0, src1, src2, src3, src4, src6, src7, src8, src9, src10; v16i8 src10_r, src32_r, src76_r, src98_r; v16i8 src21_r, src43_r, src87_r, src109_r; @@ -2976,93 +3031,77 @@ static void common_vt_4t_32w_mult_msa(uint8_t *src, int32_t src_stride, filt = LD_SH(filter); SPLATI_H2_SB(filt, 0, 1, filt0, filt1); - for (cnt = (width >> 5); cnt--;) { - dst_tmp = dst; - src_tmp = src; + /* 16 width */ + LD_SB3(src, src_stride, src0, src1, src2); + XORI_B3_128_SB(src0, src1, src2); + + ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); + ILVL_B2_SB(src1, src0, src2, src1, src10_l, src21_l); + + /* next 16 width */ + LD_SB3(src + 16, src_stride, src6, src7, src8); + src += (3 * src_stride); + + XORI_B3_128_SB(src6, src7, src8); + ILVR_B2_SB(src7, src6, src8, src7, src76_r, src87_r); + ILVL_B2_SB(src7, src6, src8, src7, src76_l, src87_l); + for (loop_cnt = (height >> 1); loop_cnt--;) { /* 16 width */ - LD_SB3(src_tmp, src_stride, src0, src1, src2); - XORI_B3_128_SB(src0, src1, src2); + LD_SB2(src, src_stride, src3, src4); + XORI_B2_128_SB(src3, src4); + ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); + ILVL_B2_SB(src3, src2, src4, src3, src32_l, src43_l); - ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); - ILVL_B2_SB(src1, src0, src2, src1, src10_l, src21_l); + /* 16 width */ + out0_r = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + out0_l = HEVC_FILT_4TAP_SH(src10_l, src32_l, filt0, filt1); + out1_r = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + out1_l = HEVC_FILT_4TAP_SH(src21_l, src43_l, filt0, filt1); + + /* 16 width */ + SRARI_H4_SH(out0_r, out1_r, out0_l, out1_l, 6); + SAT_SH4_SH(out0_r, out1_r, out0_l, out1_l, 7); + out = PCKEV_XORI128_UB(out0_r, out0_l); + ST_UB(out, dst); + out = PCKEV_XORI128_UB(out1_r, out1_l); + ST_UB(out, dst + dst_stride); + + src10_r = src32_r; + src21_r = src43_r; + src10_l = src32_l; + src21_l = src43_l; + src2 = src4; /* next 16 width */ - LD_SB3(src_tmp + 16, src_stride, src6, src7, src8); - src_tmp += (3 * src_stride); + LD_SB2(src + 16, src_stride, src9, src10); + src += (2 * src_stride); + XORI_B2_128_SB(src9, src10); + ILVR_B2_SB(src9, src8, src10, src9, src98_r, src109_r); + ILVL_B2_SB(src9, src8, src10, src9, src98_l, src109_l); - XORI_B3_128_SB(src6, src7, src8); - ILVR_B2_SB(src7, src6, src8, src7, src76_r, src87_r); - ILVL_B2_SB(src7, src6, src8, src7, src76_l, src87_l); - - for (loop_cnt = (height >> 1); loop_cnt--;) { - /* 16 width */ - LD_SB2(src_tmp, src_stride, src3, src4); - XORI_B2_128_SB(src3, src4); - ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); - ILVL_B2_SB(src3, src2, src4, src3, src32_l, src43_l); - - /* 16 width */ - out0_r = FILT_4TAP_DPADD_S_H(src10_r, src32_r, filt0, filt1); - out0_l = FILT_4TAP_DPADD_S_H(src10_l, src32_l, filt0, filt1); - out1_r = FILT_4TAP_DPADD_S_H(src21_r, src43_r, filt0, filt1); - out1_l = FILT_4TAP_DPADD_S_H(src21_l, src43_l, filt0, filt1); - - /* 16 width */ - SRARI_H4_SH(out0_r, out1_r, out0_l, out1_l, 6); - SAT_SH4_SH(out0_r, out1_r, out0_l, out1_l, 7); - out = PCKEV_XORI128_UB(out0_r, out0_l); - ST_UB(out, dst_tmp); - out = PCKEV_XORI128_UB(out1_r, out1_l); - ST_UB(out, dst_tmp + dst_stride); - - src10_r = src32_r; - src21_r = src43_r; - src10_l = src32_l; - src21_l = src43_l; - src2 = src4; - - /* next 16 width */ - LD_SB2(src_tmp + 16, src_stride, src9, src10); - src_tmp += (2 * src_stride); - XORI_B2_128_SB(src9, src10); - ILVR_B2_SB(src9, src8, src10, src9, src98_r, src109_r); - ILVL_B2_SB(src9, src8, src10, src9, src98_l, src109_l); - - /* next 16 width */ - out2_r = FILT_4TAP_DPADD_S_H(src76_r, src98_r, filt0, filt1); - out2_l = FILT_4TAP_DPADD_S_H(src76_l, src98_l, filt0, filt1); - out3_r = FILT_4TAP_DPADD_S_H(src87_r, src109_r, filt0, filt1); - out3_l = FILT_4TAP_DPADD_S_H(src87_l, src109_l, filt0, filt1); - - /* next 16 width */ - SRARI_H4_SH(out2_r, out3_r, out2_l, out3_l, 6); - SAT_SH4_SH(out2_r, out3_r, out2_l, out3_l, 7); - out = PCKEV_XORI128_UB(out2_r, out2_l); - ST_UB(out, dst_tmp + 16); - out = PCKEV_XORI128_UB(out3_r, out3_l); - ST_UB(out, dst_tmp + 16 + dst_stride); - - dst_tmp += 2 * dst_stride; - - src76_r = src98_r; - src87_r = src109_r; - src76_l = src98_l; - src87_l = src109_l; - src8 = src10; - } + /* next 16 width */ + out2_r = HEVC_FILT_4TAP_SH(src76_r, src98_r, filt0, filt1); + out2_l = HEVC_FILT_4TAP_SH(src76_l, src98_l, filt0, filt1); + out3_r = HEVC_FILT_4TAP_SH(src87_r, src109_r, filt0, filt1); + out3_l = HEVC_FILT_4TAP_SH(src87_l, src109_l, filt0, filt1); - src += 32; - dst += 32; - } -} + /* next 16 width */ + SRARI_H4_SH(out2_r, out3_r, out2_l, out3_l, 6); + SAT_SH4_SH(out2_r, out3_r, out2_l, out3_l, 7); + out = PCKEV_XORI128_UB(out2_r, out2_l); + ST_UB(out, dst + 16); + out = PCKEV_XORI128_UB(out3_r, out3_l); + ST_UB(out, dst + 16 + dst_stride); -static void common_vt_4t_32w_msa(uint8_t *src, int32_t src_stride, - uint8_t *dst, int32_t dst_stride, - const int8_t *filter, int32_t height) -{ - common_vt_4t_32w_mult_msa(src, src_stride, dst, dst_stride, - filter, height, 32); + dst += 2 * dst_stride; + + src76_r = src98_r; + src87_r = src109_r; + src76_l = src98_l; + src87_l = src109_l; + src8 = src10; + } } static void hevc_hv_uni_4t_4x2_msa(uint8_t *src, From b9cd26f556f4ca0dfe71ffd75a7272782b324753 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Fri, 3 Nov 2017 13:05:23 +0530 Subject: [PATCH 0752/2557] avcodec/mips: Improve hevc uni weighted 4 tap hz mc msa functions Use global mask buffer for appropriate mask load. Use immediate unsigned saturation for clip to max saving one vector register. Remove unused macro. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_uniw_msa.c | 892 +++++++++++++++-------------- 1 file changed, 448 insertions(+), 444 deletions(-) diff --git a/libavcodec/mips/hevc_mc_uniw_msa.c b/libavcodec/mips/hevc_mc_uniw_msa.c index 0796b0aa7c2b3..31fec7330e3d2 100644 --- a/libavcodec/mips/hevc_mc_uniw_msa.c +++ b/libavcodec/mips/hevc_mc_uniw_msa.c @@ -29,19 +29,6 @@ static const uint8_t ff_hevc_mask_arr[16 * 2] __attribute__((aligned(0x40))) = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; -#define HEVC_HV_UNIW_RND_CLIP4(in0, in1, in2, in3, wgt, offset, rnd, \ - out0, out1, out2, out3) \ -{ \ - MUL4(in0, wgt, in1, wgt, in2, wgt, in3, wgt, out0, out1, out2, out3); \ - SRAR_W4_SW(out0, out1, out2, out3, rnd); \ - ADD4(out0, offset, out1, offset, out2, offset, out3, offset, \ - out0, out1, out2, out3); \ - out0 = CLIP_SW_0_255(out0); \ - out1 = CLIP_SW_0_255(out1); \ - out2 = CLIP_SW_0_255(out2); \ - out3 = CLIP_SW_0_255(out3); \ -} - #define HEVC_UNIW_RND_CLIP2(in0, in1, wgt, offset, rnd, \ out0_r, out1_r, out0_l, out1_l) \ { \ @@ -2382,19 +2369,19 @@ static void hevc_hz_uniwgt_4t_4x2_msa(uint8_t *src, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight, int32_t offset, int32_t rnd_val) { + v16u8 out; v8i16 filt0, filt1; v16i8 src0, src1, vec0, vec1; v16i8 mask1; v8i16 dst0; v4i32 dst0_r, dst0_l; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[16]); src -= 1; @@ -2405,29 +2392,33 @@ static void hevc_hz_uniwgt_4t_4x2_msa(uint8_t *src, weight = weight & 0x0000FFFF; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + LD_SB2(src, src_stride, src0, src1); XORI_B2_128_SB(src0, src1); VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); ILVRL_H2_SW(dst0, dst0, dst0_r, dst0_l); DOTP_SH2_SW(dst0_r, dst0_l, weight_vec, weight_vec, dst0_r, dst0_l); SRAR_W2_SW(dst0_r, dst0_l, rnd_vec); - ADD2(dst0_r, offset_vec, dst0_l, offset_vec, dst0_r, dst0_l); - dst0_r = CLIP_SW_0_255(dst0_r); - dst0_l = CLIP_SW_0_255(dst0_l); - - HEVC_PCK_SW_SB2(dst0_l, dst0_r, dst0_r); - ST4x2_UB(dst0_r, dst, dst_stride); + dst0 = __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); + dst0 = __msa_adds_s_h(dst0, offset_vec); + dst0 = CLIP_SH_0_255_MAX_SATU(dst0); + out = (v16u8) __msa_pckev_b((v16i8) dst0, (v16i8) dst0); + ST4x2_UB(out, dst, dst_stride); dst += (4 * dst_stride); } @@ -2436,19 +2427,18 @@ static void hevc_hz_uniwgt_4t_4x4_msa(uint8_t *src, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight, int32_t offset, int32_t rnd_val) { + v16u8 out; v8i16 filt0, filt1; v16i8 src0, src1, src2, src3; - v16i8 mask1, vec0, vec1; + v16i8 mask1, vec0, vec1, vec2, vec3; v8i16 dst0, dst1; - v4i32 dst0_r, dst1_r, dst0_l, dst1_l; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[16]); src -= 1; @@ -2460,29 +2450,32 @@ static void hevc_hz_uniwgt_4t_4x4_msa(uint8_t *src, weight = weight & 0x0000FFFF; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + LD_SB4(src, src_stride, src0, src1, src2, src3); XORI_B4_128_SB(src0, src1, src2, src3); VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - - VSHF_B2_SB(src2, src3, src2, src3, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + VSHF_B2_SB(src2, src3, src2, src3, mask0, mask1, vec2, vec3); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); - HEVC_UNIW_RND_CLIP2(dst0, dst1, weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + HEVC_UNIW_RND_CLIP2_MAX_SATU_H(dst0, dst1, weight_vec, offset_vec, rnd_vec, + dst0, dst1); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST4x4_UB(dst0_r, dst0_r, 0, 1, 2, 3, dst, dst_stride); + out = (v16u8) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); dst += (4 * dst_stride); } @@ -2497,14 +2490,15 @@ static void hevc_hz_uniwgt_4t_4x8multiple_msa(uint8_t *src, int32_t rnd_val) { uint32_t loop_cnt; + v16u8 out0, out1; v8i16 filt0, filt1; v16i8 src0, src1, src2, src3, src4, src5, src6, src7; - v16i8 mask1, vec0, vec1; + v16i8 mask1, vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v8i16 dst0, dst1, dst2, dst3; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v8i16 filter_vec; + v8i16 weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[16]); src -= 1; @@ -2512,13 +2506,20 @@ static void hevc_hz_uniwgt_4t_4x8multiple_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); weight = weight & 0x0000FFFF; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + mask1 = mask0 + 2; for (loop_cnt = (height >> 3); loop_cnt--;) { @@ -2528,29 +2529,20 @@ static void hevc_hz_uniwgt_4t_4x8multiple_msa(uint8_t *src, XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - - VSHF_B2_SB(src2, src3, src2, src3, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - - VSHF_B2_SB(src4, src5, src4, src5, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - VSHF_B2_SB(src6, src7, src6, src7, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + VSHF_B2_SB(src2, src3, src2, src3, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src4, src5, src4, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src7, src6, src7, mask0, mask1, vec6, vec7); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); - HEVC_UNIW_RND_CLIP4(dst0, dst1, dst2, dst3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, + weight_vec, offset_vec, rnd_vec, + dst0, dst1, dst2, dst3); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST4x8_UB(dst0_r, dst1_r, dst, dst_stride); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + ST4x8_UB(out0, out1, dst, dst_stride); dst += (8 * dst_stride); } } @@ -2567,10 +2559,10 @@ static void hevc_hz_uniwgt_4t_4w_msa(uint8_t *src, { if (2 == height) { hevc_hz_uniwgt_4t_4x2_msa(src, src_stride, dst, dst_stride, - filter, height, weight, offset, rnd_val); + filter, weight, offset, rnd_val); } else if (4 == height) { hevc_hz_uniwgt_4t_4x4_msa(src, src_stride, dst, dst_stride, - filter, height, weight, offset, rnd_val); + filter, weight, offset, rnd_val); } else if (8 == height || 16 == height) { hevc_hz_uniwgt_4t_4x8multiple_msa(src, src_stride, dst, dst_stride, filter, height, weight, @@ -2588,16 +2580,15 @@ static void hevc_hz_uniwgt_4t_6w_msa(uint8_t *src, int32_t offset, int32_t rnd_val) { - uint32_t loop_cnt; + v16u8 out0, out1, out2, out3; v8i16 filt0, filt1; - v16i8 src0, src1, src2, src3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v16i8 vec0, vec1; - v8i16 dst0, dst1, dst2, dst3; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= 1; @@ -2605,48 +2596,53 @@ static void hevc_hz_uniwgt_4t_6w_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); weight = weight & 0x0000FFFF; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); - mask1 = mask0 + 2; - - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB4(src, src_stride, src0, src1, src2, src3); - src += (4 * src_stride); - - XORI_B4_128_SB(src0, src1, src2, src3); - - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + weight *= 128; + rnd_val -= 6; - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); - HEVC_UNIW_RND_CLIP4(dst0, dst1, dst2, dst3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); + mask1 = mask0 + 2; - ST6x4_UB(dst0_r, dst1_r, dst, dst_stride); - dst += (4 * dst_stride); - } + LD_SB8(src, src_stride, src0, src1, src2, src3, src4, src5, src6, src7); + XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec6, vec7); + dst4 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst7 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, + weight_vec, offset_vec, rnd_vec, + dst0, dst1, dst2, dst3); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst4, dst5, dst6, dst7, + weight_vec, offset_vec, rnd_vec, + dst4, dst5, dst6, dst7); + + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + PCKEV_B2_UB(dst5, dst4, dst7, dst6, out2, out3); + ST6x4_UB(out0, out1, dst, dst_stride); + dst += (4 * dst_stride); + ST6x4_UB(out2, out3, dst, dst_stride); } static void hevc_hz_uniwgt_4t_8x2_msa(uint8_t *src, @@ -2654,19 +2650,18 @@ static void hevc_hz_uniwgt_4t_8x2_msa(uint8_t *src, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight, int32_t offset, int32_t rnd_val) { + v16u8 out; v8i16 filt0, filt1, dst0, dst1; v16i8 src0, src1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v16i8 vec0, vec1; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst0_l, dst1_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v16i8 vec0, vec1, vec2, vec3; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= 1; @@ -2674,52 +2669,52 @@ static void hevc_hz_uniwgt_4t_8x2_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); weight = weight & 0x0000FFFF; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + mask1 = mask0 + 2; LD_SB2(src, src_stride, src0, src1); XORI_B2_128_SB(src0, src1); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); - HEVC_UNIW_RND_CLIP2(dst0, dst1, weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + HEVC_UNIW_RND_CLIP2_MAX_SATU_H(dst0, dst1, weight_vec, offset_vec, rnd_vec, + dst0, dst1); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST8x2_UB(dst0_r, dst, dst_stride); + out = (v16u8) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); + ST8x2_UB(out, dst, dst_stride); } -static void hevc_hz_uniwgt_4t_8x6_msa(uint8_t *src, +static void hevc_hz_uniwgt_4t_8x4_msa(uint8_t *src, int32_t src_stride, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight, int32_t offset, int32_t rnd_val) { - v8i16 filt0, filt1; - v16i8 src0, src1, src2, src3, src4, src5; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; - v16i8 mask1; - v16i8 vec0, vec1; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3; + v16i8 mask0, mask1, vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 filt0, filt1, dst0, dst1, dst2, dst3; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= 1; @@ -2727,61 +2722,113 @@ static void hevc_hz_uniwgt_4t_8x6_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); weight = weight & 0x0000FFFF; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); - mask1 = mask0 + 2; + weight *= 128; + rnd_val -= 6; - LD_SB6(src, src_stride, src0, src1, src2, src3, src4, src5); - LD_SB6(src, src_stride, src0, src1, src2, src3, src4, src5); - XORI_B6_128_SB(src0, src1, src2, src3, src4, src5); + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + mask0 = LD_SB(&ff_hevc_mask_arr[0]); + mask1 = mask0 + 2; + + LD_SB4(src, src_stride, src0, src1, src2, src3); + XORI_B4_128_SB(src0, src1, src2, src3); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, + weight_vec, offset_vec, rnd_vec, + dst0, dst1, dst2, dst3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + ST8x4_UB(out0, out1, dst, dst_stride); +} - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); +static void hevc_hz_uniwgt_4t_8x6_msa(uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter, + int32_t weight, + int32_t offset, + int32_t rnd_val) +{ + v16u8 out0, out1, out2; + v8i16 filt0, filt1; + v16i8 src0, src1, src2, src3, src4, src5; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); + v16i8 mask1; + v16i8 vec11; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9, vec10; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); + src -= 1; - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); + filter_vec = LD_SH(filter); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); - HEVC_UNIW_RND_CLIP4(dst0, dst1, dst2, dst3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + weight = weight & 0x0000FFFF; - HEVC_UNIW_RND_CLIP2(dst4, dst5, weight_vec, offset_vec, rnd_vec, - dst4_r, dst5_r, dst4_l, dst5_l); + weight_vec = __msa_fill_w(weight); + rnd_vec = __msa_fill_w(rnd_val); - HEVC_PCK_SW_SB12(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - dst4_l, dst4_r, dst5_l, dst5_r, dst0_r, dst1_r, dst2_r); + weight *= 128; + rnd_val -= 6; - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + + mask1 = mask0 + 2; + + LD_SB6(src, src_stride, src0, src1, src2, src3, src4, src5); + XORI_B6_128_SB(src0, src1, src2, src3, src4, src5); + + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec8, vec9); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec10, vec11); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec8, vec9, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec10, vec11, filt0, filt1); + + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, + weight_vec, offset_vec, rnd_vec, + dst0, dst1, dst2, dst3); + + HEVC_UNIW_RND_CLIP2_MAX_SATU_H(dst4, dst5, weight_vec, offset_vec, rnd_vec, + dst4, dst5); + + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + ST8x4_UB(out0, out1, dst, dst_stride); dst += (4 * dst_stride); - ST8x2_UB(dst2_r, dst, dst_stride); + ST8x2_UB(out2, dst, dst_stride); } -static void hevc_hz_uniwgt_4t_8x4multiple_msa(uint8_t *src, +static void hevc_hz_uniwgt_4t_8x8multiple_msa(uint8_t *src, int32_t src_stride, uint8_t *dst, int32_t dst_stride, @@ -2793,14 +2840,14 @@ static void hevc_hz_uniwgt_4t_8x4multiple_msa(uint8_t *src, { uint32_t loop_cnt; v8i16 filt0, filt1; - v16i8 src0, src1, src2, src3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16u8 out0, out1, out2, out3; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1; - v16i8 vec0, vec1; - v8i16 dst0, dst1, dst2, dst3; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= 1; @@ -2808,47 +2855,56 @@ static void hevc_hz_uniwgt_4t_8x4multiple_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); weight = weight & 0x0000FFFF; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); - mask1 = mask0 + 2; - - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB4(src, src_stride, src0, src1, src2, src3); - src += (4 * src_stride); - - XORI_B4_128_SB(src0, src1, src2, src3); - - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + weight *= 128; + rnd_val -= 6; - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + mask1 = mask0 + 2; - HEVC_UNIW_RND_CLIP4(dst0, dst1, dst2, dst3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + for (loop_cnt = (height >> 3); loop_cnt--;) { + LD_SB8(src, src_stride, src0, src1, src2, src3, src4, src5, src6, src7); + src += (8 * src_stride); + XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec6, vec7); + dst4 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst7 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, + weight_vec, offset_vec, rnd_vec, + dst0, dst1, dst2, dst3); + + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst4, dst5, dst6, dst7, + weight_vec, offset_vec, rnd_vec, + dst4, dst5, dst6, dst7); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); - dst += (4 * dst_stride); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + PCKEV_B2_UB(dst5, dst4, dst7, dst6, out2, out3); + ST8x8_UB(out0, out1, out2, out3, dst, dst_stride); + dst += (8 * dst_stride); } } @@ -2864,12 +2920,15 @@ static void hevc_hz_uniwgt_4t_8w_msa(uint8_t *src, { if (2 == height) { hevc_hz_uniwgt_4t_8x2_msa(src, src_stride, dst, dst_stride, - filter, height, weight, offset, rnd_val); + filter, weight, offset, rnd_val); + } else if (4 == height) { + hevc_hz_uniwgt_4t_8x4_msa(src, src_stride, dst, dst_stride, + filter, weight, offset, rnd_val); } else if (6 == height) { hevc_hz_uniwgt_4t_8x6_msa(src, src_stride, dst, dst_stride, - filter, height, weight, offset, rnd_val); + filter, weight, offset, rnd_val); } else { - hevc_hz_uniwgt_4t_8x4multiple_msa(src, src_stride, dst, dst_stride, + hevc_hz_uniwgt_4t_8x8multiple_msa(src, src_stride, dst, dst_stride, filter, height, weight, offset, rnd_val); } @@ -2886,19 +2945,18 @@ static void hevc_hz_uniwgt_4t_12w_msa(uint8_t *src, int32_t rnd_val) { uint32_t loop_cnt; + v16u8 out0, out1, out2; v8i16 filt0, filt1; v16i8 src0, src1, src2, src3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask2 = { 8, 9, 9, 10, 10, 11, 11, 12, 24, 25, 25, 26, 26, 27, 27, 28 }; v16i8 mask1; - v16i8 vec0, vec1; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9, vec10; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v8i16 filter_vec, const_vec; - v16i8 mask3; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v16i8 mask3, vec11; + v4i32 weight_vec, rnd_vec; src -= 1; @@ -2906,60 +2964,51 @@ static void hevc_hz_uniwgt_4t_12w_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); weight = weight & 0x0000FFFF; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + mask1 = mask0 + 2; mask3 = mask2 + 2; - for (loop_cnt = (height >> 2); loop_cnt--;) { + for (loop_cnt = 4; loop_cnt--;) { LD_SB4(src, src_stride, src0, src1, src2, src3); src += (4 * src_stride); XORI_B4_128_SB(src0, src1, src2, src3); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - VSHF_B2_SB(src2, src3, src2, src3, mask2, mask3, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - HEVC_UNIW_RND_CLIP4(dst0, dst1, dst2, dst3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec8, vec9); + VSHF_B2_SB(src2, src3, src2, src3, mask2, mask3, vec10, vec11); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec8, vec9, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec10, vec11, filt0, filt1); - HEVC_UNIW_RND_CLIP2(dst4, dst5, weight_vec, offset_vec, rnd_vec, - dst4_r, dst5_r, dst4_l, dst5_l); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, + weight_vec, offset_vec, rnd_vec, + dst0, dst1, dst2, dst3); - HEVC_PCK_SW_SB12(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - dst4_l, dst4_r, dst5_l, dst5_r, - dst0_r, dst1_r, dst2_r); + HEVC_UNIW_RND_CLIP2_MAX_SATU_H(dst4, dst5, weight_vec, offset_vec, + rnd_vec, dst4, dst5); - ST12x4_UB(dst0_r, dst1_r, dst2_r, dst, dst_stride); + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + ST12x4_UB(out0, out1, out2, dst, dst_stride); dst += (4 * dst_stride); } } @@ -2975,15 +3024,15 @@ static void hevc_hz_uniwgt_4t_16w_msa(uint8_t *src, int32_t rnd_val) { uint32_t loop_cnt; + v16u8 out0, out1, out2, out3; v16i8 src0, src1, src2, src3, src4, src5, src6, src7; v8i16 filt0, filt1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; - v16i8 vec0, vec1; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= 1; @@ -2991,13 +3040,20 @@ static void hevc_hz_uniwgt_4t_16w_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); weight = weight & 0x0000FFFF; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + mask1 = mask0 + 2; for (loop_cnt = (height >> 2); loop_cnt--;) { @@ -3008,56 +3064,35 @@ static void hevc_hz_uniwgt_4t_16w_msa(uint8_t *src, XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec6, vec7); + dst4 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst7 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, + weight_vec, offset_vec, rnd_vec, + dst0, dst1, dst2, dst3); - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst4, dst5, dst6, dst7, + weight_vec, offset_vec, rnd_vec, + dst4, dst5, dst6, dst7); - VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); - dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); + PCKEV_B4_UB(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, + out0, out1, out2, out3); - HEVC_UNIW_RND_CLIP4(dst0, dst1, dst2, dst3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); - dst += (2 * dst_stride); - - HEVC_UNIW_RND_CLIP4(dst4, dst5, dst6, dst7, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); - dst += (2 * dst_stride); + ST_UB4(out0, out1, out2, out3, dst, dst_stride); + dst += (4 * dst_stride); } } @@ -3072,16 +3107,14 @@ static void hevc_hz_uniwgt_4t_24w_msa(uint8_t *src, int32_t rnd_val) { uint32_t loop_cnt; - uint8_t *dst_tmp = dst + 16; + v16u8 out0, out1, out2; v16i8 src0, src1, src2, src3; v8i16 filt0, filt1; - v8i16 dst0, dst1, dst2, dst3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; - v16i8 mask1, mask2, mask3; - v16i8 vec0, vec1; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v16i8 mask0, mask1, mask2, mask3; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= 1; @@ -3089,19 +3122,25 @@ static void hevc_hz_uniwgt_4t_24w_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); weight = weight & 0x0000FFFF; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + + mask0 = LD_SB(&ff_hevc_mask_arr[0]); mask1 = mask0 + 2; mask2 = mask0 + 8; mask3 = mask0 + 10; - for (loop_cnt = (height >> 1); loop_cnt--;) { - /* 16 width */ + for (loop_cnt = 16; loop_cnt--;) { LD_SB2(src, src_stride, src0, src2); LD_SB2(src + 16, src_stride, src1, src3); src += (2 * src_stride); @@ -3109,46 +3148,29 @@ static void hevc_hz_uniwgt_4t_24w_msa(uint8_t *src, XORI_B4_128_SB(src0, src1, src2, src3); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - - VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - VSHF_B2_SB(src2, src3, src2, src3, mask2, mask3, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - HEVC_UNIW_RND_CLIP4(dst0, dst1, dst2, dst3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); - dst += (2 * dst_stride); - - /* 8 width */ + VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src2, src3, src2, src3, mask2, mask3, vec6, vec7); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec2, vec3); + dst4 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, + weight_vec, offset_vec, rnd_vec, + dst0, dst1, dst2, dst3); - HEVC_UNIW_RND_CLIP2(dst0, dst1, weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + HEVC_UNIW_RND_CLIP2_MAX_SATU_H(dst4, dst5, weight_vec, offset_vec, + rnd_vec, dst4, dst5); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST8x2_UB(dst0_r, dst_tmp, dst_stride); - dst_tmp += (2 * dst_stride); + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + ST_UB2(out0, out1, dst, dst_stride); + ST8x2_UB(out2, dst + 16, dst_stride); + dst += (2 * dst_stride); } } @@ -3163,15 +3185,15 @@ static void hevc_hz_uniwgt_4t_32w_msa(uint8_t *src, int32_t rnd_val) { uint32_t loop_cnt; - v16i8 src0, src1, src2; + v16u8 out0, out1, out2, out3; + v16i8 src0, src1, src2, src3, src4, src5; v8i16 filt0, filt1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(&ff_hevc_mask_arr[0]); v16i8 mask1, mask2, mask3; - v8i16 dst0, dst1, dst2, dst3; - v16i8 vec0, vec1; - v8i16 filter_vec, const_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= 1; @@ -3179,13 +3201,20 @@ static void hevc_hz_uniwgt_4t_32w_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); weight = weight & 0x0000FFFF; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + mask1 = mask0 + 2; mask2 = mask0 + 8; mask3 = mask0 + 10; @@ -3194,65 +3223,40 @@ static void hevc_hz_uniwgt_4t_32w_msa(uint8_t *src, LD_SB2(src, 16, src0, src1); src2 = LD_SB(src + 24); src += src_stride; - - XORI_B3_128_SB(src0, src1, src2); - - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - - VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - HEVC_UNIW_RND_CLIP4(dst0, dst1, dst2, dst3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, 16); - dst += dst_stride; - - LD_SB2(src, 16, src0, src1); - src2 = LD_SB(src + 24); + LD_SB2(src, 16, src3, src4); + src5 = LD_SB(src + 24); src += src_stride; - - XORI_B3_128_SB(src0, src1, src2); - + XORI_B6_128_SB(src0, src1, src2, src3, src4, src5); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - - VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - HEVC_UNIW_RND_CLIP4(dst0, dst1, dst2, dst3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); + VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec2, vec3); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec6, vec7); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src3, src4, src3, src4, mask2, mask3, vec2, vec3); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec6, vec7); + dst4 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst7 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, + weight_vec, offset_vec, rnd_vec, + dst0, dst1, dst2, dst3); + + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst4, dst5, dst6, dst7, + weight_vec, offset_vec, rnd_vec, + dst4, dst5, dst6, dst7); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, 16); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + PCKEV_B2_UB(dst5, dst4, dst7, dst6, out2, out3); + ST_UB2(out0, out1, dst, 16); + dst += dst_stride; + ST_UB2(out2, out3, dst, 16); dst += dst_stride; } } From 3ddb887c88483ce089b29a30d0d0aa574c8cdc66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Gro=C3=9Fe?= Date: Sun, 29 Oct 2017 12:08:05 +0100 Subject: [PATCH 0753/2557] ffmpeg.c: fix calculation of input file duration in seek_to_start() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes looping files without audio or when using stream_copy, where ist->nb_samples is not set since no decoding is done. This fixes ticket #5719 and also fixes an endless loop with the sample in ticket #6139. Signed-off-by: Peter Große Signed-off-by: Michael Niedermayer --- fftools/ffmpeg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 286d898b12105..65dbe9362634b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -4150,9 +4150,9 @@ static int seek_to_start(InputFile *ifile, AVFormatContext *is) continue; } else { if (ist->framerate.num) { - duration = av_rescale_q(1, ist->framerate, ist->st->time_base); + duration = av_rescale_q(1, av_inv_q(ist->framerate), ist->st->time_base); } else if (ist->st->avg_frame_rate.num) { - duration = av_rescale_q(1, ist->st->avg_frame_rate, ist->st->time_base); + duration = av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), ist->st->time_base); } else duration = 1; } if (!ifile->duration) From 0ae1f6ddeb350d767a4860e1dcffea9cebe9917c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Gro=C3=9Fe?= Date: Sun, 29 Oct 2017 15:07:12 +0100 Subject: [PATCH 0754/2557] ffmpeg.c: fix code style in seek_to_start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Große Signed-off-by: Michael Niedermayer --- fftools/ffmpeg.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 65dbe9362634b..679929cfc459e 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -4146,14 +4146,17 @@ static int seek_to_start(InputFile *ifile, AVFormatContext *is) AVRational sample_rate = {1, avctx->sample_rate}; duration = av_rescale_q(ist->nb_samples, sample_rate, ist->st->time_base); - } else + } else { continue; + } } else { if (ist->framerate.num) { duration = av_rescale_q(1, av_inv_q(ist->framerate), ist->st->time_base); } else if (ist->st->avg_frame_rate.num) { duration = av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), ist->st->time_base); - } else duration = 1; + } else { + duration = 1; + } } if (!ifile->duration) ifile->time_base = ist->st->time_base; From 3f4fccf4d6d2a9a6db46bfca0e6fb648d8e3708b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 5 Nov 2017 10:39:23 +0100 Subject: [PATCH 0755/2557] avformat/mvdec: check for EOF Fixes #6805. Signed-off-by: Paul B Mahol --- libavformat/mvdec.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index f7aa4cbaecf86..fa596179ed97a 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -227,7 +227,9 @@ static int read_table(AVFormatContext *avctx, AVStream *st, int (*parse)(AVFormatContext *avctx, AVStream *st, const char *name, int size)) { - int count, i; + unsigned count; + int i; + AVIOContext *pb = avctx->pb; avio_skip(pb, 4); count = avio_rb32(pb); @@ -235,6 +237,10 @@ static int read_table(AVFormatContext *avctx, AVStream *st, for (i = 0; i < count; i++) { char name[17]; int size; + + if (avio_feof(pb)) + return AVERROR_EOF; + avio_read(pb, name, 16); name[sizeof(name) - 1] = 0; size = avio_rb32(pb); From 6ea77115324c638c4a76e9902ac83f9625834bdd Mon Sep 17 00:00:00 2001 From: Piotr Bandurski Date: Wed, 22 Mar 2017 20:34:28 +0100 Subject: [PATCH 0756/2557] avcodec/qdrw: support 16bpp files with bppcnt == 2 && bpp == 8 --- libavcodec/qdrw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/qdrw.c b/libavcodec/qdrw.c index 3a0bc6f760a9c..82cc528a30f2d 100644 --- a/libavcodec/qdrw.c +++ b/libavcodec/qdrw.c @@ -434,7 +434,7 @@ static int decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "bppcount %d bpp %d\n", bppcnt, bpp); if (bppcnt == 3 && bpp == 8) { avctx->pix_fmt = AV_PIX_FMT_RGB24; - } else if (bppcnt == 3 && bpp == 5) { + } else if (bppcnt == 3 && bpp == 5 || bppcnt == 2 && bpp == 8) { avctx->pix_fmt = AV_PIX_FMT_RGB555; } else if (bppcnt == 4 && bpp == 8) { avctx->pix_fmt = AV_PIX_FMT_ARGB; From 2cc51d5025c976aa268a854df1eec86014512c8c Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 5 Nov 2017 01:53:49 +0100 Subject: [PATCH 0757/2557] lavc/v4l2_context: Change the type of the ioctl cmd to uint32_t. Fixes a warning on recent Linux: libavcodec/v4l2_context.c: In function 'ff_v4l2_context_set_status': libavcodec/v4l2_context.c:496:26: warning: comparison is always false due to limited range of data type --- libavcodec/v4l2_context.c | 2 +- libavcodec/v4l2_context.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index 9f3b56ddabf7d..4c169928fab9e 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -484,7 +484,7 @@ static int v4l2_get_coded_format(V4L2Context* ctx, uint32_t *p) * *****************************************************************************/ -int ff_v4l2_context_set_status(V4L2Context* ctx, int cmd) +int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd) { int type = ctx->type; int ret; diff --git a/libavcodec/v4l2_context.h b/libavcodec/v4l2_context.h index 503cc36dc4a2b..632f1d0aac019 100644 --- a/libavcodec/v4l2_context.h +++ b/libavcodec/v4l2_context.h @@ -135,7 +135,7 @@ void ff_v4l2_context_release(V4L2Context* ctx); * those frames will be dropped. * @return 0 in case of success, a negative value representing the error otherwise. */ -int ff_v4l2_context_set_status(V4L2Context* ctx, int cmd); +int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd); /** * Dequeues a buffer from a V4L2Context to an AVPacket. From e06bdc3c37f4fc756247bc5ebe576f2624b05e24 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 5 Nov 2017 20:51:03 +0100 Subject: [PATCH 0758/2557] lavf/amr: Add amrnb and amrwb demuxers. Fixes ticket #6678. --- Changelog | 1 + doc/general.texi | 2 + libavformat/Makefile | 2 + libavformat/allformats.c | 2 + libavformat/amr.c | 133 ++++++++++++++++++++++++++++++++++++--- libavformat/version.h | 4 +- 6 files changed, 132 insertions(+), 12 deletions(-) diff --git a/Changelog b/Changelog index 8c45b2946df45..24ca4f009013f 100644 --- a/Changelog +++ b/Changelog @@ -7,6 +7,7 @@ version : requires 2.1 (or later) and pkg-config. - VDA dropped (use VideoToolbox instead) - MagicYUV encoder +- Raw AMR-NB and AMR-WB demuxers version 3.4: diff --git a/doc/general.texi b/doc/general.texi index 9e6ae13435871..e6ae277d232a1 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -439,6 +439,8 @@ library: @item QCP @tab @tab X @item raw ADTS (AAC) @tab X @tab X @item raw AC-3 @tab X @tab X +@item raw AMR-NB @tab @tab X +@item raw AMR-WB @tab @tab X @item raw Chinese AVS video @tab X @tab X @item raw CRI ADX @tab X @tab X @item raw Dirac @tab X @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index caebe5b146d08..287c6ff9ef146 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -87,6 +87,8 @@ OBJS-$(CONFIG_AIFF_MUXER) += aiffenc.o id3v2enc.o OBJS-$(CONFIG_AIX_DEMUXER) += aixdec.o OBJS-$(CONFIG_AMR_DEMUXER) += amr.o OBJS-$(CONFIG_AMR_MUXER) += amr.o +OBJS-$(CONFIG_AMRNB_DEMUXER) += amr.o +OBJS-$(CONFIG_AMRWB_DEMUXER) += amr.o OBJS-$(CONFIG_ANM_DEMUXER) += anm.o OBJS-$(CONFIG_APC_DEMUXER) += apc.o OBJS-$(CONFIG_APE_DEMUXER) += ape.o apetag.o img2.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 405ddb5ad9f00..dc8984e1b86e1 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -63,6 +63,8 @@ static void register_all(void) REGISTER_MUXDEMUX(AIFF, aiff); REGISTER_DEMUXER (AIX, aix); REGISTER_MUXDEMUX(AMR, amr); + REGISTER_DEMUXER (AMRNB, amrnb); + REGISTER_DEMUXER (AMRWB, amrwb); REGISTER_DEMUXER (ANM, anm); REGISTER_DEMUXER (APC, apc); REGISTER_DEMUXER (APE, ape); diff --git a/libavformat/amr.c b/libavformat/amr.c index b5194a2d9e3a7..fffeb65f68ce3 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -38,6 +38,13 @@ typedef struct { static const char AMR_header[] = "#!AMR\n"; static const char AMRWB_header[] = "#!AMR-WB\n"; +static const uint8_t amrnb_packed_size[16] = { + 13, 14, 16, 18, 20, 21, 27, 32, 6, 1, 1, 1, 1, 1, 1, 1 +}; +static const uint8_t amrwb_packed_size[16] = { + 18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 1, 1, 1, 1, 1, 1 +}; + #if CONFIG_AMR_MUXER static int amr_write_header(AVFormatContext *s) { @@ -126,17 +133,9 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt) mode = (toc >> 3) & 0x0F; if (par->codec_id == AV_CODEC_ID_AMR_NB) { - static const uint8_t packed_size[16] = { - 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 - }; - - size = packed_size[mode] + 1; + size = amrnb_packed_size[mode]; } else if (par->codec_id == AV_CODEC_ID_AMR_WB) { - static const uint8_t packed_size[16] = { - 18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1 - }; - - size = packed_size[mode]; + size = amrwb_packed_size[mode]; } if (!size || av_new_packet(pkt, size)) @@ -176,6 +175,120 @@ AVInputFormat ff_amr_demuxer = { }; #endif +#if CONFIG_AMRNB_DEMUXER +static int amrnb_probe(AVProbeData *p) +{ + int mode, i = 0, valid = 0; + const uint8_t *b = p->buf; + + while (i < p->buf_size) { + mode = b[i] >> 3 & 0x0F; + if (mode < 9 && (b[i] & 0x4) == 0x4) { + int last = mode; + int size = amrnb_packed_size[mode]; + while (size--) { + if (b[++i] != last) + break; + last = b[i]; + } + if (size > 0) { + valid++; + i += size; + } + } else { + valid = 0; + i++; + } + } + if (valid > 100) + return AVPROBE_SCORE_EXTENSION / 2 + 1; + return 0; +} + +static int amrnb_read_header(AVFormatContext *s) +{ + AVStream *st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + st->codecpar->codec_tag = MKTAG('s', 'a', 'm', 'r'); + st->codecpar->codec_id = AV_CODEC_ID_AMR_NB; + st->codecpar->sample_rate = 8000; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + avpriv_set_pts_info(st, 64, 1, 8000); + + return 0; +} + +AVInputFormat ff_amrnb_demuxer = { + .name = "amrnb", + .long_name = NULL_IF_CONFIG_SMALL("raw AMR-NB"), + .priv_data_size = sizeof(AMRContext), + .read_probe = amrnb_probe, + .read_header = amrnb_read_header, + .read_packet = amr_read_packet, + .flags = AVFMT_GENERIC_INDEX, +}; +#endif + +#if CONFIG_AMRWB_DEMUXER +static int amrwb_probe(AVProbeData *p) +{ + int mode, i = 0, valid = 0; + const uint8_t *b = p->buf; + + while (i < p->buf_size) { + mode = b[i] >> 3 & 0x0F; + if (mode < 10 && (b[i] & 0x4) == 0x4) { + int last = mode; + int size = amrwb_packed_size[mode]; + while (size--) { + if (b[++i] != last) + break; + last = b[i]; + } + if (size > 0) { + valid++; + i += size; + } + } else { + valid = 0; + i++; + } + } + if (valid > 100) + return AVPROBE_SCORE_EXTENSION / 2 - 1; + return 0; +} + +static int amrwb_read_header(AVFormatContext *s) +{ + AVStream *st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + st->codecpar->codec_tag = MKTAG('s', 'a', 'w', 'b'); + st->codecpar->codec_id = AV_CODEC_ID_AMR_WB; + st->codecpar->sample_rate = 16000; + st->codecpar->channels = 1; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + avpriv_set_pts_info(st, 64, 1, 16000); + + return 0; +} + +AVInputFormat ff_amrwb_demuxer = { + .name = "amrwb", + .long_name = NULL_IF_CONFIG_SMALL("raw AMR-WB"), + .priv_data_size = sizeof(AMRContext), + .read_probe = amrwb_probe, + .read_header = amrwb_read_header, + .read_packet = amr_read_packet, + .flags = AVFMT_GENERIC_INDEX, +}; +#endif + #if CONFIG_AMR_MUXER AVOutputFormat ff_amr_muxer = { .name = "amr", diff --git a/libavformat/version.h b/libavformat/version.h index 2db03232e41a9..5d2409cf862b9 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,8 +32,8 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 0 -#define LIBAVFORMAT_VERSION_MICRO 102 +#define LIBAVFORMAT_VERSION_MINOR 1 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From e131b8cedb00043dcc97cc05ca04749ec8ff57de Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 4 Nov 2017 01:19:20 +0100 Subject: [PATCH 0759/2557] avcodec/h264idct_template: Fix integer overflows in ff_h264_idct8_add() Fixes: runtime error: signed integer overflow: -503316480 + -2013265038 cannot be represented in type 'int' Fixes: 3805/clusterfuzz-testcase-minimized-6578427831255040 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/h264idct_template.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/h264idct_template.c b/libavcodec/h264idct_template.c index fbd07cb8d57c6..7526bdd812c3a 100644 --- a/libavcodec/h264idct_template.c +++ b/libavcodec/h264idct_template.c @@ -91,10 +91,10 @@ void FUNCC(ff_h264_idct8_add)(uint8_t *_dst, int16_t *_block, int stride){ const int a5 = -block[i+1*8] + (unsigned)block[i+7*8] + block[i+5*8] + (block[i+5*8]>>1); const int a7 = block[i+3*8] + (unsigned)block[i+5*8] + block[i+1*8] + (block[i+1*8]>>1); - const int b1 = (a7>>2) + a1; - const int b3 = a3 + (a5>>2); - const int b5 = (a3>>2) - a5; - const int b7 = a7 - (a1>>2); + const int b1 = (a7>>2) + (unsigned)a1; + const int b3 = (unsigned)a3 + (a5>>2); + const int b5 = (a3>>2) - (unsigned)a5; + const int b7 = (unsigned)a7 - (a1>>2); block[i+0*8] = b0 + b7; block[i+7*8] = b0 - b7; From e34fe61bf45331d2e6d2840604f799fa4b55c843 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 1 Nov 2017 14:00:18 +0100 Subject: [PATCH 0760/2557] avutil/softfloat: Add FLOAT_MIN Signed-off-by: Michael Niedermayer --- libavutil/softfloat.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/softfloat.h b/libavutil/softfloat.h index b13d728f30827..a651406f749d2 100644 --- a/libavutil/softfloat.h +++ b/libavutil/softfloat.h @@ -43,6 +43,7 @@ static const SoftFloat FLOAT_EPSILON = { 0x29F16B12, -16}; static const SoftFloat FLOAT_1584893192 = { 0x32B771ED, 1}; ///< 1.584893192 (10^.2) static const SoftFloat FLOAT_100000 = { 0x30D40000, 17}; ///< 100000 static const SoftFloat FLOAT_0999999 = { 0x3FFFFBCE, 0}; ///< 0.999999 +static const SoftFloat FLOAT_MIN = { 0x20000000, MIN_EXP}; /** From 7d1dec466895eed12f2c79b7ab5447f5390fe869 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 1 Nov 2017 14:00:19 +0100 Subject: [PATCH 0761/2557] avcodec/aacsbr_fixed: Fix division by zero in sbr_gain_calc() Fixes: 3642/clusterfuzz-testcase-minimized-5443853801750528 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/aacsbr_fixed.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/aacsbr_fixed.c b/libavcodec/aacsbr_fixed.c index 289bb86a810b8..3d5875a4690d2 100644 --- a/libavcodec/aacsbr_fixed.c +++ b/libavcodec/aacsbr_fixed.c @@ -433,6 +433,7 @@ static void sbr_gain_calc(AACContext *ac, SpectralBandReplication *sbr, av_add_sf(FLOAT_1, sbr->e_curr[e][m]), av_add_sf(FLOAT_1, sbr->q_mapped[e][m])))); } + sbr->gain[e][m] = av_add_sf(sbr->gain[e][m], FLOAT_MIN); } for (m = sbr->f_tablelim[k] - sbr->kx[1]; m < sbr->f_tablelim[k + 1] - sbr->kx[1]; m++) { sum[0] = av_add_sf(sum[0], sbr->e_origmapped[e][m]); From 981e99ab99986935affad7c164ebdfe28e8ea7f8 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 1 Nov 2017 14:00:20 +0100 Subject: [PATCH 0762/2557] avcodec/sbrdsp_fixed: Fix integer overflow in shift in sbr_hf_g_filt_c() Fixes: runtime error: shift exponent 66 is too large for 64-bit type 'long long' Fixes: 3642/clusterfuzz-testcase-minimized-5443853801750528 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/sbrdsp_fixed.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavcodec/sbrdsp_fixed.c b/libavcodec/sbrdsp_fixed.c index 896b2d75c6c6c..a0ef6859f1a71 100644 --- a/libavcodec/sbrdsp_fixed.c +++ b/libavcodec/sbrdsp_fixed.c @@ -244,12 +244,14 @@ static void sbr_hf_g_filt_c(int (*Y)[2], const int (*X_high)[40][2], int64_t accu; for (m = 0; m < m_max; m++) { - int64_t r = 1LL << (22-g_filt[m].exp); - accu = (int64_t)X_high[m][ixh][0] * ((g_filt[m].mant + 0x40)>>7); - Y[m][0] = (int)((accu + r) >> (23-g_filt[m].exp)); + if (22 - g_filt[m].exp < 61) { + int64_t r = 1LL << (22-g_filt[m].exp); + accu = (int64_t)X_high[m][ixh][0] * ((g_filt[m].mant + 0x40)>>7); + Y[m][0] = (int)((accu + r) >> (23-g_filt[m].exp)); - accu = (int64_t)X_high[m][ixh][1] * ((g_filt[m].mant + 0x40)>>7); - Y[m][1] = (int)((accu + r) >> (23-g_filt[m].exp)); + accu = (int64_t)X_high[m][ixh][1] * ((g_filt[m].mant + 0x40)>>7); + Y[m][1] = (int)((accu + r) >> (23-g_filt[m].exp)); + } } } From cb618da8d39d236fac01e31fd424c7369d00e5d0 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 4 Nov 2017 15:17:28 +0100 Subject: [PATCH 0763/2557] Maintainers : add myself for exr Signed-off-by: Michael Niedermayer --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1bc2c59839adc..c70d949a710a4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -170,6 +170,7 @@ Codecs: eacmv*, eaidct*, eat* Peter Ross evrc* Paul B Mahol exif.c, exif.h Thilo Borgmann + exr.c Martin Vignali ffv1* Michael Niedermayer ffwavesynth.c Nicolas George fifo.c Jan Sebechlebsky From d68a557df4937b695a5f6a14877d92647be95aaa Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 4 Nov 2017 19:31:54 +0100 Subject: [PATCH 0764/2557] ffplay: use SDL2 audio API It allows us to specify what kind of audio parameter changes are allowed. Should fix ticket #6721. Signed-off-by: Marton Balint --- fftools/ffplay.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index c264e92535380..bd1457c7e3eb7 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -362,6 +362,7 @@ static AVPacket flush_pkt; static SDL_Window *window; static SDL_Renderer *renderer; static SDL_RendererInfo renderer_info = {0}; +static SDL_AudioDeviceID audio_dev; static const struct TextureFormatEntry { enum AVPixelFormat format; @@ -1192,7 +1193,7 @@ static void stream_component_close(VideoState *is, int stream_index) switch (codecpar->codec_type) { case AVMEDIA_TYPE_AUDIO: decoder_abort(&is->auddec, &is->sampq); - SDL_CloseAudio(); + SDL_CloseAudioDevice(audio_dev); decoder_destroy(&is->auddec); swr_free(&is->swr_ctx); av_freep(&is->audio_buf1); @@ -2451,7 +2452,7 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) else { memset(stream, 0, len1); if (!is->muted && is->audio_buf) - SDL_MixAudio(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1, is->audio_volume); + SDL_MixAudioFormat(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, AUDIO_S16SYS, len1, is->audio_volume); } len -= len1; stream += len1; @@ -2496,7 +2497,7 @@ static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb wanted_spec.samples = FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC)); wanted_spec.callback = sdl_audio_callback; wanted_spec.userdata = opaque; - while (SDL_OpenAudio(&wanted_spec, &spec) < 0) { + while (!(audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) { av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): %s\n", wanted_spec.channels, wanted_spec.freq, SDL_GetError()); wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)]; @@ -2659,7 +2660,7 @@ static int stream_component_open(VideoState *is, int stream_index) } if ((ret = decoder_start(&is->auddec, audio_thread, is)) < 0) goto out; - SDL_PauseAudio(0); + SDL_PauseAudioDevice(audio_dev, 0); break; case AVMEDIA_TYPE_VIDEO: is->video_stream = stream_index; From 0a60cc909ed5c2b0fb6f58d9ae0bfc44b00060bf Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Mon, 6 Nov 2017 13:36:40 +0100 Subject: [PATCH 0765/2557] lavf/amr: Do not set codec_tag for raw amr_nb and raw amr_wb. --- libavformat/amr.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavformat/amr.c b/libavformat/amr.c index fffeb65f68ce3..8b4d736d2f900 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -210,7 +210,6 @@ static int amrnb_read_header(AVFormatContext *s) AVStream *st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codecpar->codec_tag = MKTAG('s', 'a', 'm', 'r'); st->codecpar->codec_id = AV_CODEC_ID_AMR_NB; st->codecpar->sample_rate = 8000; st->codecpar->channels = 1; @@ -267,7 +266,6 @@ static int amrwb_read_header(AVFormatContext *s) AVStream *st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - st->codecpar->codec_tag = MKTAG('s', 'a', 'w', 'b'); st->codecpar->codec_id = AV_CODEC_ID_AMR_WB; st->codecpar->sample_rate = 16000; st->codecpar->channels = 1; From 4c38aa79ece4fa0ea7533774197d6408d7d3b9e5 Mon Sep 17 00:00:00 2001 From: Ashish Pratap Singh Date: Mon, 6 Nov 2017 07:49:19 -0500 Subject: [PATCH 0766/2557] avfilter/vf_libvmaf: fix errors while running with psnr=1. This patch fixes the seg fault which ocuured while running libvmaf filter with option psnr=1. Signed-off-by: ashk43712 Signed-off-by: Ronald S. Bultje --- libavfilter/vf_libvmaf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_libvmaf.c b/libavfilter/vf_libvmaf.c index 2c3a9f33493ad..7670c51e2113b 100644 --- a/libavfilter/vf_libvmaf.c +++ b/libavfilter/vf_libvmaf.c @@ -40,7 +40,6 @@ typedef struct LIBVMAFContext { const AVClass *class; FFFrameSync fs; const AVPixFmtDescriptor *desc; - char *format; int width; int height; double vmaf_score; @@ -149,6 +148,7 @@ static void compute_vmaf_score(LIBVMAFContext *s) { int (*read_frame)(float *ref_data, float *main_data, float *temp_data, int stride, void *ctx); + char *format; if (s->desc->comp[0].depth <= 8) { read_frame = read_frame_8bit; @@ -156,7 +156,9 @@ static void compute_vmaf_score(LIBVMAFContext *s) read_frame = read_frame_10bit; } - s->vmaf_score = compute_vmaf(s->format, s->width, s->height, read_frame, s, + format = (char *) s->desc->name; + + s->vmaf_score = compute_vmaf(format, s->width, s->height, read_frame, s, s->model_path, s->log_path, s->log_fmt, 0, 0, s->enable_transform, s->phone_model, s->psnr, s->ssim, s->ms_ssim, s->pool); @@ -258,7 +260,6 @@ static int config_input_ref(AVFilterLink *inlink) return 0; } - static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; From 7b7037e5b035d8805972982d54441663a25bb016 Mon Sep 17 00:00:00 2001 From: Ashish Pratap Singh Date: Mon, 6 Nov 2017 07:49:33 -0500 Subject: [PATCH 0767/2557] avfilter:vf_libvmaf: improve docs. Signed-off-by: Ronald S. Bultje --- doc/filters.texi | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 6f6dfcff48241..2ba6e04166889 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -9885,25 +9885,16 @@ distances from the focal point in the source and target images, respectively. @section libvmaf -Obtain the average VMAF (Video Multi-Method Assessment Fusion) +Obtain the VMAF (Video Multi-Method Assessment Fusion) score between two input videos. -This filter takes two input videos. - -Both video inputs must have the same resolution and pixel format for -this filter to work correctly. Also it assumes that both inputs -have the same number of frames, which are compared one by one. - -The obtained average VMAF score is printed through the logging system. +The obtained VMAF score is printed through the logging system. It requires Netflix's vmaf library (libvmaf) as a pre-requisite. After installing the library it can be enabled using: @code{./configure --enable-libvmaf}. If no model path is specified it uses the default model: @code{vmaf_v0.6.1.pkl}. -On the below examples the input file @file{main.mpg} being processed is -compared with the reference file @file{ref.mpg}. - The filter has following options: @table @option @@ -9934,12 +9925,14 @@ Enables computing ssim along with vmaf. Enables computing ms_ssim along with vmaf. @item pool -Set the pool method to be used for computing vmaf. +Set the pool method (mean, min or harmonic mean) to be used for computing vmaf. @end table This filter also supports the @ref{framesync} options. -For example: +On the below examples the input file @file{main.mpg} being processed is +compared with the reference file @file{ref.mpg}. + @example ffmpeg -i main.mpg -i ref.mpg -lavfi libvmaf -f null - @end example From a6a6935ee8703f18fa21751ba291e003acd99ab8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 29 Oct 2017 21:20:10 +0100 Subject: [PATCH 0768/2557] avformat: add TiVo ty demuxer Signed-off-by: Paul B Mahol --- Changelog | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/ty.c | 765 +++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 5 files changed, 769 insertions(+), 1 deletion(-) create mode 100644 libavformat/ty.c diff --git a/Changelog b/Changelog index 24ca4f009013f..80ada1f5f1d28 100644 --- a/Changelog +++ b/Changelog @@ -8,6 +8,7 @@ version : - VDA dropped (use VideoToolbox instead) - MagicYUV encoder - Raw AMR-NB and AMR-WB demuxers +- TiVo ty/ty+ demuxer version 3.4: diff --git a/libavformat/Makefile b/libavformat/Makefile index 287c6ff9ef146..146a4656f23c9 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -492,6 +492,7 @@ OBJS-$(CONFIG_TRUEHD_MUXER) += rawenc.o OBJS-$(CONFIG_TTA_DEMUXER) += tta.o apetag.o img2.o OBJS-$(CONFIG_TTA_MUXER) += ttaenc.o apetag.o img2.o OBJS-$(CONFIG_TTY_DEMUXER) += tty.o sauce.o +OBJS-$(CONFIG_TY_DEMUXER) += ty.o OBJS-$(CONFIG_TXD_DEMUXER) += txd.o OBJS-$(CONFIG_UNCODEDFRAMECRC_MUXER) += uncodedframecrcenc.o framehash.o OBJS-$(CONFIG_V210_DEMUXER) += v210.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index dc8984e1b86e1..1896d50e9edd9 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -322,6 +322,7 @@ static void register_all(void) REGISTER_MUXDEMUX(TTA, tta); REGISTER_DEMUXER (TXD, txd); REGISTER_DEMUXER (TTY, tty); + REGISTER_DEMUXER (TY, ty); REGISTER_MUXER (UNCODEDFRAMECRC, uncodedframecrc); REGISTER_DEMUXER (V210, v210); REGISTER_DEMUXER (V210X, v210x); diff --git a/libavformat/ty.c b/libavformat/ty.c new file mode 100644 index 0000000000000..bd871cba2e9a4 --- /dev/null +++ b/libavformat/ty.c @@ -0,0 +1,765 @@ +/* + * TiVo ty stream demuxer + * Copyright (c) 2005 VLC authors and VideoLAN + * Copyright (c) 2005 by Neal Symms (tivo@freakinzoo.com) - February 2005 + * based on code by Christopher Wingert for tivo-mplayer + * tivo(at)wingert.org, February 2003 + * Copyright (c) 2017 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "internal.h" +#include "mpeg.h" + +#define SERIES1_PES_LENGTH 11 /* length of audio PES hdr on S1 */ +#define SERIES2_PES_LENGTH 16 /* length of audio PES hdr on S2 */ +#define AC3_PES_LENGTH 14 /* length of audio PES hdr for AC3 */ +#define VIDEO_PES_LENGTH 16 /* length of video PES header */ +#define DTIVO_PTS_OFFSET 6 /* offs into PES for MPEG PTS on DTivo */ +#define SA_PTS_OFFSET 9 /* offset into PES for MPEG PTS on SA */ +#define AC3_PTS_OFFSET 9 /* offset into PES for AC3 PTS on DTivo */ +#define VIDEO_PTS_OFFSET 9 /* offset into PES for video PTS on all */ +#define AC3_PKT_LENGTH 1536 /* size of TiVo AC3 pkts (w/o PES hdr) */ + +static const uint8_t ty_VideoPacket[] = { 0x00, 0x00, 0x01, 0xe0 }; +static const uint8_t ty_MPEGAudioPacket[] = { 0x00, 0x00, 0x01, 0xc0 }; +static const uint8_t ty_AC3AudioPacket[] = { 0x00, 0x00, 0x01, 0xbd }; + +#define TIVO_PES_FILEID 0xf5467abd +#define CHUNK_SIZE (128 * 1024) +#define CHUNK_PEEK_COUNT 3 /* number of chunks to probe */ + +typedef struct TyRecHdr { + int64_t rec_size; + uint8_t ex[2]; + uint8_t rec_type; + uint8_t subrec_type; + uint64_t ty_pts; /* TY PTS in the record header */ +} TyRecHdr; + +typedef enum { + TIVO_TYPE_UNKNOWN, + TIVO_TYPE_SA, + TIVO_TYPE_DTIVO +} TiVo_type; + +typedef enum { + TIVO_SERIES_UNKNOWN, + TIVO_SERIES1, + TIVO_SERIES2 +} TiVo_series; + +typedef enum { + TIVO_AUDIO_UNKNOWN, + TIVO_AUDIO_AC3, + TIVO_AUDIO_MPEG +} TiVo_audio; + +typedef struct TySeqTable { + uint64_t timestamp; + uint8_t chunk_bitmask[8]; +} TySeqTable; + +typedef struct TYDemuxContext { + unsigned cur_chunk; + unsigned cur_chunk_pos; + int64_t cur_pos; + TiVo_type tivo_type; /* TiVo type (SA / DTiVo) */ + TiVo_series tivo_series; /* Series1 or Series2 */ + TiVo_audio audio_type; /* AC3 or MPEG */ + int pes_length; /* Length of Audio PES header */ + int pts_offset; /* offset into audio PES of PTS */ + uint8_t pes_buffer[20]; /* holds incomplete pes headers */ + int pes_buf_cnt; /* how many bytes in our buffer */ + size_t ac3_pkt_size; /* length of ac3 pkt we've seen so far */ + uint64_t last_ty_pts; /* last TY timestamp we've seen */ + unsigned seq_table_size; /* number of entries in SEQ table */ + + int64_t first_audio_pts; + int64_t last_audio_pts; + int64_t last_video_pts; + + TyRecHdr *rec_hdrs; /* record headers array */ + int cur_rec; /* current record in this chunk */ + int num_recs; /* number of recs in this chunk */ + int seq_rec; /* record number where seq start is */ + TySeqTable *seq_table; /* table of SEQ entries from mstr chk */ + int first_chunk; + + uint8_t chunk[CHUNK_SIZE]; +} TYDemuxContext; + +static int ty_probe(AVProbeData *p) +{ + if (AV_RB32(p->buf) == TIVO_PES_FILEID && + AV_RB32(p->buf + 4) == 0x02 && + AV_RB32(p->buf + 8) == CHUNK_SIZE) { + return AVPROBE_SCORE_MAX; + } + return 0; +} + +static TyRecHdr *parse_chunk_headers(const uint8_t *buf, + int num_recs) +{ + TyRecHdr *hdrs, *rec_hdr; + int i; + + hdrs = av_calloc(num_recs, sizeof(TyRecHdr)); + if (!hdrs) + return NULL; + + for (i = 0; i < num_recs; i++) { + const uint8_t *record_header = buf + (i * 16); + + rec_hdr = &hdrs[i]; /* for brevity */ + rec_hdr->rec_type = record_header[3]; + rec_hdr->subrec_type = record_header[2] & 0x0f; + if ((record_header[0] & 0x80) == 0x80) { + uint8_t b1, b2; + + /* marker bit 2 set, so read extended data */ + b1 = (((record_header[0] & 0x0f) << 4) | + ((record_header[1] & 0xf0) >> 4)); + b2 = (((record_header[1] & 0x0f) << 4) | + ((record_header[2] & 0xf0) >> 4)); + + rec_hdr->ex[0] = b1; + rec_hdr->ex[1] = b2; + rec_hdr->rec_size = 0; + rec_hdr->ty_pts = 0; + } else { + rec_hdr->rec_size = (record_header[0] << 8 | + record_header[1]) << 4 | + (record_header[2] >> 4); + rec_hdr->ty_pts = AV_RB64(&record_header[8]); + } + } + return hdrs; +} + +static int find_es_header(const uint8_t *header, + const uint8_t *buffer, int search_len) +{ + int count; + + for (count = 0; count < search_len; count++) { + if (!memcmp(&buffer[count], header, 4)) + return count; + } + return -1; +} + +static int analyze_chunk(AVFormatContext *s, const uint8_t *chunk) +{ + TYDemuxContext *ty = s->priv_data; + int num_recs, i; + TyRecHdr *hdrs; + int num_6e0, num_be0, num_9c0, num_3c0; + + /* skip if it's a Part header */ + if (AV_RB32(&chunk[0]) == TIVO_PES_FILEID) + return 0; + + /* number of records in chunk (we ignore high order byte; + * rarely are there > 256 chunks & we don't need that many anyway) */ + num_recs = chunk[0]; + if (num_recs < 5) { + /* try again with the next chunk. Sometimes there are dead ones */ + return 0; + } + + chunk += 4; /* skip past rec count & SEQ bytes */ + ff_dlog(s, "probe: chunk has %d recs\n", num_recs); + hdrs = parse_chunk_headers(chunk, num_recs); + if (!hdrs) + return AVERROR(ENOMEM); + + /* scan headers. + * 1. check video packets. Presence of 0x6e0 means S1. + * No 6e0 but have be0 means S2. + * 2. probe for audio 0x9c0 vs 0x3c0 (AC3 vs Mpeg) + * If AC-3, then we have DTivo. + * If MPEG, search for PTS offset. This will determine SA vs. DTivo. + */ + num_6e0 = num_be0 = num_9c0 = num_3c0 = 0; + for (i = 0; i < num_recs; i++) { + switch (hdrs[i].subrec_type << 8 | hdrs[i].rec_type) { + case 0x6e0: + num_6e0++; + break; + case 0xbe0: + num_be0++; + break; + case 0x3c0: + num_3c0++; + break; + case 0x9c0: + num_9c0++; + break; + } + } + ff_dlog(s, "probe: chunk has %d 0x6e0 recs, %d 0xbe0 recs.\n", + num_6e0, num_be0); + + /* set up our variables */ + if (num_6e0 > 0) { + ff_dlog(s, "detected Series 1 Tivo\n"); + ty->tivo_series = TIVO_SERIES1; + ty->pes_length = SERIES1_PES_LENGTH; + } else if (num_be0 > 0) { + ff_dlog(s, "detected Series 2 Tivo\n"); + ty->tivo_series = TIVO_SERIES2; + ty->pes_length = SERIES2_PES_LENGTH; + } + if (num_9c0 > 0) { + ff_dlog(s, "detected AC-3 Audio (DTivo)\n"); + ty->audio_type = TIVO_AUDIO_AC3; + ty->tivo_type = TIVO_TYPE_DTIVO; + ty->pts_offset = AC3_PTS_OFFSET; + ty->pes_length = AC3_PES_LENGTH; + } else if (num_3c0 > 0) { + ty->audio_type = TIVO_AUDIO_MPEG; + ff_dlog(s, "detected MPEG Audio\n"); + } + + /* if tivo_type still unknown, we can check PTS location + * in MPEG packets to determine tivo_type */ + if (ty->tivo_type == TIVO_TYPE_UNKNOWN) { + uint32_t data_offset = 16 * num_recs; + for (i = 0; i < num_recs; i++) { + if ((hdrs[i].subrec_type << 0x08 | hdrs[i].rec_type) == 0x3c0 && hdrs[i].rec_size > 15) { + /* first make sure we're aligned */ + int pes_offset = find_es_header(ty_MPEGAudioPacket, + &chunk[data_offset], 5); + if (pes_offset >= 0) { + /* pes found. on SA, PES has hdr data at offset 6, not PTS. */ + if ((chunk[data_offset + 6 + pes_offset] & 0x80) == 0x80) { + /* S1SA or S2(any) Mpeg Audio (PES hdr, not a PTS start) */ + if (ty->tivo_series == TIVO_SERIES1) + ff_dlog(s, "detected Stand-Alone Tivo\n"); + ty->tivo_type = TIVO_TYPE_SA; + ty->pts_offset = SA_PTS_OFFSET; + } else { + if (ty->tivo_series == TIVO_SERIES1) + ff_dlog(s, "detected DirecTV Tivo\n"); + ty->tivo_type = TIVO_TYPE_DTIVO; + ty->pts_offset = DTIVO_PTS_OFFSET; + } + break; + } + } + data_offset += hdrs[i].rec_size; + } + } + av_free(hdrs); + + return 0; +} + +static int ty_read_header(AVFormatContext *s) +{ + TYDemuxContext *ty = s->priv_data; + AVIOContext *pb = s->pb; + AVStream *st, *ast; + int i, ret = 0; + + ty->first_audio_pts = AV_NOPTS_VALUE; + ty->last_audio_pts = AV_NOPTS_VALUE; + ty->last_video_pts = AV_NOPTS_VALUE; + + for (i = 0; i < CHUNK_PEEK_COUNT; i++) { + avio_read(pb, ty->chunk, CHUNK_SIZE); + + ret = analyze_chunk(s, ty->chunk); + if (ret < 0) + return ret; + if (ty->tivo_series != TIVO_SERIES_UNKNOWN && + ty->audio_type != TIVO_AUDIO_UNKNOWN && + ty->tivo_type != TIVO_TYPE_UNKNOWN) + break; + } + + if (ty->tivo_series == TIVO_SERIES_UNKNOWN || + ty->audio_type == TIVO_AUDIO_UNKNOWN || + ty->tivo_type == TIVO_TYPE_UNKNOWN) + return AVERROR(EIO); + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_MPEG2VIDEO; + st->need_parsing = AVSTREAM_PARSE_FULL_RAW; + avpriv_set_pts_info(st, 64, 1, 90000); + + ast = avformat_new_stream(s, NULL); + if (!ast) + return AVERROR(ENOMEM); + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + + if (ty->audio_type == TIVO_AUDIO_MPEG) { + ast->codecpar->codec_id = AV_CODEC_ID_MP2; + ast->need_parsing = AVSTREAM_PARSE_FULL_RAW; + } else { + ast->codecpar->codec_id = AV_CODEC_ID_AC3; + } + avpriv_set_pts_info(ast, 64, 1, 90000); + + ty->first_chunk = 1; + + avio_seek(pb, 0, SEEK_SET); + + return 0; +} + +/* parse a master chunk, filling the SEQ table and other variables. + * We assume the stream is currently pointing to it. + */ +static void parse_master(AVFormatContext *s) +{ + TYDemuxContext *ty = s->priv_data; + unsigned map_size; /* size of bitmask, in bytes */ + unsigned i, j; + + /* Note that the entries in the SEQ table in the stream may have + different sizes depending on the bits per entry. We store them + all in the same size structure, so we have to parse them out one + by one. If we had a dynamic structure, we could simply read the + entire table directly from the stream into memory in place. */ + + /* clear the SEQ table */ + av_freep(&ty->seq_table); + + /* parse header info */ + + map_size = AV_RB32(ty->chunk + 20); /* size of bitmask, in bytes */ + i = AV_RB32(ty->chunk + 28); /* size of SEQ table, in bytes */ + + ty->seq_table_size = i / (8LL + map_size); + + if (ty->seq_table_size == 0) { + ty->seq_table = NULL; + return; + } + + /* parse all the entries */ + ty->seq_table = av_calloc(ty->seq_table_size, sizeof(TySeqTable)); + if (ty->seq_table == NULL) { + ty->seq_table_size = 0; + return; + } + + ty->cur_chunk_pos = 32; + for (j = 0; j < ty->seq_table_size; j++) { + ty->seq_table[j].timestamp = AV_RB64(ty->chunk + ty->cur_chunk_pos); + ty->cur_chunk_pos += 8; + if (map_size > 8) { + av_log(s, AV_LOG_ERROR, "Unsupported SEQ bitmap size in master chunk.\n"); + ty->cur_chunk_pos += map_size; + } else { + memcpy(ty->seq_table[j].chunk_bitmask, ty->chunk + ty->cur_chunk_pos, map_size); + } + } +} + +static int get_chunk(AVFormatContext *s) +{ + TYDemuxContext *ty = s->priv_data; + AVIOContext *pb = s->pb; + int read_size, num_recs; + + ff_dlog(s, "parsing ty chunk #%d\n", ty->cur_chunk); + + /* if we have left-over filler space from the last chunk, get that */ + if (avio_feof(pb)) + return AVERROR_EOF; + + /* read the TY packet header */ + read_size = avio_read(pb, ty->chunk, CHUNK_SIZE); + ty->cur_chunk++; + + if ((read_size < 4) || (AV_RB32(ty->chunk) == 0)) { + return AVERROR_EOF; + } + + /* check if it's a PART Header */ + if (AV_RB32(ty->chunk) == TIVO_PES_FILEID) { + parse_master(s); /* parse master chunk */ + return get_chunk(s); + } + + /* number of records in chunk (8- or 16-bit number) */ + if (ty->chunk[3] & 0x80) { + /* 16 bit rec cnt */ + ty->num_recs = num_recs = (ty->chunk[1] << 8) + ty->chunk[0]; + ty->seq_rec = (ty->chunk[3] << 8) + ty->chunk[2]; + if (ty->seq_rec != 0xffff) { + ty->seq_rec &= ~0x8000; + } + } else { + /* 8 bit reclen - TiVo 1.3 format */ + ty->num_recs = num_recs = ty->chunk[0]; + ty->seq_rec = ty->chunk[1]; + } + ty->cur_rec = 0; + ty->first_chunk = 0; + + ff_dlog(s, "chunk has %d records\n", num_recs); + ty->cur_chunk_pos = 4; + + av_freep(&ty->rec_hdrs); + + if (num_recs * 16 >= CHUNK_SIZE - 4) + return AVERROR_INVALIDDATA; + + ty->rec_hdrs = parse_chunk_headers(ty->chunk + 4, num_recs); + ty->cur_chunk_pos += 16 * num_recs; + + return 0; +} + +static int demux_video(AVFormatContext *s, TyRecHdr *rec_hdr, AVPacket *pkt) +{ + TYDemuxContext *ty = s->priv_data; + const int subrec_type = rec_hdr->subrec_type; + const int64_t rec_size = rec_hdr->rec_size; + int es_offset1; + int got_packet = 0; + + if (subrec_type != 0x02 && subrec_type != 0x0c && + subrec_type != 0x08 && rec_size > 4) { + /* get the PTS from this packet if it has one. + * on S1, only 0x06 has PES. On S2, however, most all do. + * Do NOT Pass the PES Header to the MPEG2 codec */ + es_offset1 = find_es_header(ty_VideoPacket, ty->chunk + ty->cur_chunk_pos, 5); + if (es_offset1 != -1) { + ty->last_video_pts = ff_parse_pes_pts( + ty->chunk + ty->cur_chunk_pos + es_offset1 + VIDEO_PTS_OFFSET); + if (subrec_type != 0x06) { + /* if we found a PES, and it's not type 6, then we're S2 */ + /* The packet will have video data (& other headers) so we + * chop out the PES header and send the rest */ + if (rec_size >= VIDEO_PES_LENGTH + es_offset1) { + int size = rec_hdr->rec_size - VIDEO_PES_LENGTH - es_offset1; + + ty->cur_chunk_pos += VIDEO_PES_LENGTH + es_offset1; + if (av_new_packet(pkt, size) < 0) + return AVERROR(ENOMEM); + memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, size); + ty->cur_chunk_pos += size; + pkt->stream_index = 0; + got_packet = 1; + } else { + ff_dlog(s, "video rec type 0x%02x has short PES" + " (%"PRId64" bytes)\n", subrec_type, rec_size); + /* nuke this block; it's too short, but has PES marker */ + ty->cur_chunk_pos += rec_size; + return 0; + } + } + } + } + + if (subrec_type == 0x06) { + /* type 6 (S1 DTivo) has no data, so we're done */ + ty->cur_chunk_pos += rec_size; + return 0; + } + + if (!got_packet) { + if (av_new_packet(pkt, rec_size) < 0) + return AVERROR(ENOMEM); + memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size); + ty->cur_chunk_pos += rec_size; + pkt->stream_index = 0; + got_packet = 1; + } + + /* if it's not a continue blk, then set PTS */ + if (subrec_type != 0x02) { + if (subrec_type == 0x0c && pkt->size >= 6) + pkt->data[5] |= 0x08; + if (subrec_type == 0x07) { + ty->last_ty_pts = rec_hdr->ty_pts; + } else { + /* yes I know this is a cheap hack. It's the timestamp + used for display and skipping fwd/back, so it + doesn't have to be accurate to the millisecond. + I adjust it here by roughly one 1/30 sec. Yes it + will be slightly off for UK streams, but it's OK. + */ + ty->last_ty_pts += 35000000; + //ty->last_ty_pts += 33366667; + } + /* set PTS for this block before we send */ + if (ty->last_video_pts > AV_NOPTS_VALUE) { + pkt->pts = ty->last_video_pts; + /* PTS gets used ONCE. + * Any subsequent frames we get BEFORE next PES + * header will have their PTS computed in the codec */ + ty->last_video_pts = AV_NOPTS_VALUE; + } + } + + return got_packet; +} + +static int check_sync_pes(AVFormatContext *s, AVPacket *pkt, + int32_t offset, int32_t rec_len) +{ + TYDemuxContext *ty = s->priv_data; + + if (offset < 0 || offset + ty->pes_length > rec_len) { + /* entire PES header not present */ + ff_dlog(s, "PES header at %d not complete in record. storing.\n", offset); + /* save the partial pes header */ + if (offset < 0) { + /* no header found, fake some 00's (this works, believe me) */ + memset(ty->pes_buffer, 0, 4); + ty->pes_buf_cnt = 4; + if (rec_len > 4) + ff_dlog(s, "PES header not found in record of %d bytes!\n", rec_len); + return -1; + } + /* copy the partial pes header we found */ + memcpy(ty->pes_buffer, pkt->data + offset, rec_len - offset); + ty->pes_buf_cnt = rec_len - offset; + + if (offset > 0) { + /* PES Header was found, but not complete, so trim the end of this record */ + pkt->size -= rec_len - offset; + return 1; + } + return -1; /* partial PES, no audio data */ + } + /* full PES header present, extract PTS */ + ty->last_audio_pts = ff_parse_pes_pts(&pkt->data[ offset + ty->pts_offset]); + if (ty->first_audio_pts == AV_NOPTS_VALUE) + ty->first_audio_pts = ty->last_audio_pts; + pkt->pts = ty->last_audio_pts; + memmove(pkt->data + offset, pkt->data + offset + ty->pes_length, rec_len - ty->pes_length); + pkt->size -= ty->pes_length; + return 0; +} + +static int demux_audio(AVFormatContext *s, TyRecHdr *rec_hdr, AVPacket *pkt) +{ + TYDemuxContext *ty = s->priv_data; + const int subrec_type = rec_hdr->subrec_type; + const int64_t rec_size = rec_hdr->rec_size; + int es_offset1; + + if (subrec_type == 2) { + int need = 0; + /* SA or DTiVo Audio Data, no PES (continued block) + * ================================================ + */ + + /* continue PES if previous was incomplete */ + if (ty->pes_buf_cnt > 0) { + need = ty->pes_length - ty->pes_buf_cnt; + + ff_dlog(s, "continuing PES header\n"); + /* do we have enough data to complete? */ + if (need >= rec_size) { + /* don't have complete PES hdr; save what we have and return */ + memcpy(ty->pes_buffer + ty->pes_buf_cnt, ty->chunk + ty->cur_chunk_pos, rec_size); + ty->cur_chunk_pos += rec_size; + ty->pes_buf_cnt += rec_size; + return 0; + } + + /* we have enough; reconstruct this frame with the new hdr */ + memcpy(ty->pes_buffer + ty->pes_buf_cnt, ty->chunk + ty->cur_chunk_pos, need); + ty->cur_chunk_pos += need; + /* get the PTS out of this PES header (MPEG or AC3) */ + if (ty->audio_type == TIVO_AUDIO_MPEG) { + es_offset1 = find_es_header(ty_MPEGAudioPacket, + ty->pes_buffer, 5); + } else { + es_offset1 = find_es_header(ty_AC3AudioPacket, + ty->pes_buffer, 5); + } + if (es_offset1 < 0) { + ff_dlog(s, "Can't find audio PES header in packet.\n"); + } else { + ty->last_audio_pts = ff_parse_pes_pts( + &ty->pes_buffer[es_offset1 + ty->pts_offset]); + pkt->pts = ty->last_audio_pts; + } + ty->pes_buf_cnt = 0; + + } + if (av_new_packet(pkt, rec_size - need) < 0) + return AVERROR(ENOMEM); + memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size - need); + ty->cur_chunk_pos += rec_size - need; + pkt->stream_index = 1; + + /* S2 DTivo has AC3 packets with 2 padding bytes at end. This is + * not allowed in the AC3 spec and will cause problems. So here + * we try to trim things. */ + /* Also, S1 DTivo has alternating short / long AC3 packets. That + * is, one packet is short (incomplete) and the next packet has + * the first one's missing data, plus all of its own. Strange. */ + if (ty->audio_type == TIVO_AUDIO_AC3 && + ty->tivo_series == TIVO_SERIES2) { + if (ty->ac3_pkt_size + pkt->size > AC3_PKT_LENGTH) { + pkt->size -= 2; + ty->ac3_pkt_size = 0; + } else { + ty->ac3_pkt_size += pkt->size; + } + } + } else if (subrec_type == 0x03) { + if (av_new_packet(pkt, rec_size) < 0) + return AVERROR(ENOMEM); + memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size); + ty->cur_chunk_pos += rec_size; + pkt->stream_index = 1; + /* MPEG Audio with PES Header, either SA or DTiVo */ + /* ================================================ */ + es_offset1 = find_es_header(ty_MPEGAudioPacket, pkt->data, 5); + + /* SA PES Header, No Audio Data */ + /* ================================================ */ + if ((es_offset1 == 0) && (rec_size == 16)) { + ty->last_audio_pts = ff_parse_pes_pts(&pkt->data[SA_PTS_OFFSET]); + if (ty->first_audio_pts == AV_NOPTS_VALUE) + ty->first_audio_pts = ty->last_audio_pts; + av_packet_unref(pkt); + return 0; + } + /* DTiVo Audio with PES Header */ + /* ================================================ */ + + /* Check for complete PES */ + if (check_sync_pes(s, pkt, es_offset1, rec_size) == -1) { + /* partial PES header found, nothing else. + * we're done. */ + av_packet_unref(pkt); + return 0; + } + } else if (subrec_type == 0x04) { + /* SA Audio with no PES Header */ + /* ================================================ */ + if (av_new_packet(pkt, rec_size) < 0) + return AVERROR(ENOMEM); + memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size); + ty->cur_chunk_pos += rec_size; + pkt->stream_index = 1; + pkt->pts = ty->last_audio_pts; + } else if (subrec_type == 0x09) { + if (av_new_packet(pkt, rec_size) < 0) + return AVERROR(ENOMEM); + memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size); + ty->cur_chunk_pos += rec_size ; + pkt->stream_index = 1; + + /* DTiVo AC3 Audio Data with PES Header */ + /* ================================================ */ + es_offset1 = find_es_header(ty_AC3AudioPacket, pkt->data, 5); + + /* Check for complete PES */ + if (check_sync_pes(s, pkt, es_offset1, rec_size) == -1) { + /* partial PES header found, nothing else. we're done. */ + av_packet_unref(pkt); + return 0; + } + /* S2 DTivo has invalid long AC3 packets */ + if (ty->tivo_series == TIVO_SERIES2) { + if (pkt->size > AC3_PKT_LENGTH) { + pkt->size -= 2; + ty->ac3_pkt_size = 0; + } else { + ty->ac3_pkt_size = pkt->size; + } + } + } else { + /* Unsupported/Unknown */ + ty->cur_chunk_pos += rec_size; + return 0; + } + + return 1; +} + +static int ty_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + TYDemuxContext *ty = s->priv_data; + AVIOContext *pb = s->pb; + TyRecHdr *rec; + int64_t rec_size = 0; + int ret = 0; + + if (avio_feof(pb)) + return AVERROR_EOF; + + while (ret <= 0) { + if (ty->first_chunk || ty->cur_rec >= ty->num_recs) { + if (get_chunk(s) < 0 || ty->num_recs == 0) + return AVERROR_EOF; + } + + rec = &ty->rec_hdrs[ty->cur_rec]; + rec_size = rec->rec_size; + ty->cur_rec++; + + if (rec_size <= 0) + continue; + + if (ty->cur_chunk_pos + rec->rec_size > CHUNK_SIZE) + return AVERROR_INVALIDDATA; + + if (avio_feof(pb)) + return AVERROR_EOF; + + switch (rec->rec_type) { + case VIDEO_ID: + ret = demux_video(s, rec, pkt); + break; + case AUDIO_ID: + ret = demux_audio(s, rec, pkt); + break; + default: + ff_dlog(s, "Invalid record type 0x%02x\n", rec->rec_type); + case 0x01: + case 0x02: + case 0x03: /* TiVo data services */ + case 0x05: /* unknown, but seen regularly */ + ty->cur_chunk_pos += rec->rec_size; + break; + } + } + + return 0; +} + +AVInputFormat ff_ty_demuxer = { + .name = "ty", + .long_name = NULL_IF_CONFIG_SMALL("TiVo TY Stream"), + .priv_data_size = sizeof(TYDemuxContext), + .read_probe = ty_probe, + .read_header = ty_read_header, + .read_packet = ty_read_packet, + .extensions = "ty,ty+", + .flags = AVFMT_TS_DISCONT, +}; diff --git a/libavformat/version.h b/libavformat/version.h index 5d2409cf862b9..509a4839e9eb6 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 1 +#define LIBAVFORMAT_VERSION_MINOR 2 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From f7c01ff24d706e2c7d645944227a5242e0f1203f Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 6 Nov 2017 13:25:18 -0300 Subject: [PATCH 0769/2557] avformat/rtpdec_asf: free the buffer pointed by the AVIOContext Don't free the buffer allocated in ff_wms_parse_sdp_a_line() after calling avformat_open_input(), as it may free it and replace it with another one. Should fix ticket #6808 Tested-by: Carl Eugen Hoyos Signed-off-by: James Almer --- libavformat/rtpdec_asf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/rtpdec_asf.c b/libavformat/rtpdec_asf.c index 2c09fda10b7dc..09f214a71c9c9 100644 --- a/libavformat/rtpdec_asf.c +++ b/libavformat/rtpdec_asf.c @@ -139,12 +139,12 @@ int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p) ret = avformat_open_input(&rt->asf_ctx, "", iformat, &opts); av_dict_free(&opts); if (ret < 0) { - av_free(buf); + av_free(pb.buffer); return ret; } av_dict_copy(&s->metadata, rt->asf_ctx->metadata, 0); rt->asf_pb_pos = avio_tell(&pb); - av_free(buf); + av_free(pb.buffer); rt->asf_ctx->pb = NULL; } return ret; From cdd19e2c560397a72433425b1c5f781cc157a7cf Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 6 Nov 2017 20:50:16 +0100 Subject: [PATCH 0770/2557] avformat/ty: try harder to find stream signature Search all chunks, not just first one. Signed-off-by: Paul B Mahol --- libavformat/ty.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libavformat/ty.c b/libavformat/ty.c index bd871cba2e9a4..3926d3e9b705a 100644 --- a/libavformat/ty.c +++ b/libavformat/ty.c @@ -108,11 +108,16 @@ typedef struct TYDemuxContext { static int ty_probe(AVProbeData *p) { - if (AV_RB32(p->buf) == TIVO_PES_FILEID && - AV_RB32(p->buf + 4) == 0x02 && - AV_RB32(p->buf + 8) == CHUNK_SIZE) { - return AVPROBE_SCORE_MAX; + int i; + + for (i = 0; i + 12 < p->buf_size; i += CHUNK_SIZE) { + if (AV_RB32(p->buf + i) == TIVO_PES_FILEID && + AV_RB32(p->buf + i + 4) == 0x02 && + AV_RB32(p->buf + i + 8) == CHUNK_SIZE) { + return AVPROBE_SCORE_MAX; + } } + return 0; } From a29a0aba79dad35a80cfcdf6db6b506afb48dcaa Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 6 Nov 2017 21:00:08 +0100 Subject: [PATCH 0771/2557] avformat/ty: do not overread chunk Signed-off-by: Paul B Mahol --- libavformat/ty.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/ty.c b/libavformat/ty.c index 3926d3e9b705a..1ce72dd0f9855 100644 --- a/libavformat/ty.c +++ b/libavformat/ty.c @@ -249,7 +249,11 @@ static int analyze_chunk(AVFormatContext *s, const uint8_t *chunk) * in MPEG packets to determine tivo_type */ if (ty->tivo_type == TIVO_TYPE_UNKNOWN) { uint32_t data_offset = 16 * num_recs; + for (i = 0; i < num_recs; i++) { + if (data_offset + hdrs[i].rec_size > CHUNK_SIZE) + break; + if ((hdrs[i].subrec_type << 0x08 | hdrs[i].rec_type) == 0x3c0 && hdrs[i].rec_size > 15) { /* first make sure we're aligned */ int pes_offset = find_es_header(ty_MPEGAudioPacket, From 4ada428aae2f4ab42c6cebc0d7591c0e62db6fe2 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 6 Nov 2017 22:39:16 +0100 Subject: [PATCH 0772/2557] avcodec: remove remaining uses of avcodec_get_chroma_sub_sample Replace them with av_pix_fmt_get_chroma_sub_sample. Signed-off-by: James Almer --- libavcodec/dirac.c | 6 +++++- libavcodec/ffv1enc.c | 5 ++++- libavcodec/j2kenc.c | 7 +++++-- libavcodec/libtheoraenc.c | 4 +++- libavcodec/mjpegdec.c | 15 ++++++++++++--- libavcodec/mpegvideo.c | 16 ++++++++++------ libavcodec/vc2enc.c | 6 ++++-- libavcodec/vp3.c | 4 +++- 8 files changed, 46 insertions(+), 17 deletions(-) diff --git a/libavcodec/dirac.c b/libavcodec/dirac.c index 027ce79a2e13a..d5870d6c00d5c 100644 --- a/libavcodec/dirac.c +++ b/libavcodec/dirac.c @@ -147,6 +147,7 @@ static int parse_source_parameters(AVDiracSeqHeader *dsh, GetBitContext *gb, unsigned luma_depth = 8, luma_offset = 16; int idx; int chroma_x_shift, chroma_y_shift; + int ret; /* [DIRAC_STD] 10.3.2 Frame size. frame_size(video_params) */ /* [DIRAC_STD] custom_dimensions_flag */ @@ -269,7 +270,10 @@ static int parse_source_parameters(AVDiracSeqHeader *dsh, GetBitContext *gb, return AVERROR_INVALIDDATA; dsh->pix_fmt = dirac_pix_fmt[dsh->chroma_format][dsh->pixel_range_index-2]; - avcodec_get_chroma_sub_sample(dsh->pix_fmt, &chroma_x_shift, &chroma_y_shift); + ret = av_pix_fmt_get_chroma_sub_sample(dsh->pix_fmt, &chroma_x_shift, &chroma_y_shift); + if (ret) + return ret; + if ((dsh->width % (1<height % (1<chroma_planes && s->version > 3) s->plane_count--; - avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_h_shift, &s->chroma_v_shift); + ret = av_pix_fmt_get_chroma_sub_sample (avctx->pix_fmt, &s->chroma_h_shift, &s->chroma_v_shift); + if (ret) + return ret; + s->picture_number = 0; if (avctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2)) { diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index c8d38617327d2..2135ece540300 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -69,6 +69,7 @@ #include "bytestream.h" #include "jpeg2000.h" #include "libavutil/common.h" +#include "libavutil/pixdesc.h" #include "libavutil/opt.h" #define NMSEDEC_BITS 7 @@ -1150,8 +1151,10 @@ FF_ENABLE_DEPRECATION_WARNINGS } else{ // planar YUV s->planar = 1; s->ncomponents = 3; - avcodec_get_chroma_sub_sample(avctx->pix_fmt, - s->chroma_shift, s->chroma_shift + 1); + ret = av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, + s->chroma_shift, s->chroma_shift + 1); + if (ret) + return ret; } ff_jpeg2000_init_tier1_luts(); diff --git a/libavcodec/libtheoraenc.c b/libavcodec/libtheoraenc.c index fae55e8f23b02..d4c39283a60c8 100644 --- a/libavcodec/libtheoraenc.c +++ b/libavcodec/libtheoraenc.c @@ -208,7 +208,9 @@ static av_cold int encode_init(AVCodecContext* avc_context) av_log(avc_context, AV_LOG_ERROR, "Unsupported pix_fmt\n"); return AVERROR(EINVAL); } - avcodec_get_chroma_sub_sample(avc_context->pix_fmt, &h->uv_hshift, &h->uv_vshift); + ret = av_pix_fmt_get_chroma_sub_sample(avc_context->pix_fmt, &h->uv_hshift, &h->uv_vshift); + if (ret) + return ret; if (avc_context->flags & AV_CODEC_FLAG_QSCALE) { /* Clip global_quality in QP units to the [0 - 10] range diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index d980ac99a13b1..e005dd0cd3bf2 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -2428,7 +2428,10 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, avctx->pix_fmt == AV_PIX_FMT_GBRP || avctx->pix_fmt == AV_PIX_FMT_GBRAP ); - avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift); + ret = av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift); + if (ret) + return ret; + av_assert0(s->nb_components == av_pix_fmt_count_planes(s->picture_ptr->format)); for (p = 0; pnb_components; p++) { uint8_t *line = s->picture_ptr->data[p]; @@ -2487,7 +2490,10 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, avctx->pix_fmt == AV_PIX_FMT_GBRP || avctx->pix_fmt == AV_PIX_FMT_GBRAP ); - avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift); + ret = av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift); + if (ret) + return ret; + av_assert0(s->nb_components == av_pix_fmt_count_planes(s->picture_ptr->format)); for (p = 0; p < s->nb_components; p++) { uint8_t *dst; @@ -2515,7 +2521,10 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } if (s->flipped && !s->rgb) { int j; - avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift); + ret = av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift); + if (ret) + return ret; + av_assert0(s->nb_components == av_pix_fmt_count_planes(s->picture_ptr->format)); for (index=0; indexnb_components; index++) { uint8_t *dst = s->picture_ptr->data[index]; diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 2f5793b9a4658..080e9077fcf4a 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -876,7 +876,7 @@ static void clear_context(MpegEncContext *s) */ av_cold int ff_mpv_common_init(MpegEncContext *s) { - int i; + int i, ret; int nb_slices = (HAVE_THREADS && s->avctx->active_thread_type & FF_THREAD_SLICE) ? s->avctx->thread_count : 1; @@ -915,10 +915,11 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) dct_init(s); /* set chroma shifts */ - avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, - &s->chroma_x_shift, - &s->chroma_y_shift); - + ret = av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, + &s->chroma_x_shift, + &s->chroma_y_shift); + if (ret) + return ret; FF_ALLOCZ_OR_GOTO(s->avctx, s->picture, MAX_PICTURE_COUNT * sizeof(Picture), fail); @@ -1452,6 +1453,7 @@ void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_ const int mv_stride = (mb_width << mv_sample_log2) + (avctx->codec->id == AV_CODEC_ID_H264 ? 0 : 1); int mb_x, mb_y, mbcount = 0; + int ret; /* size is width * height * 2 * 4 where 2 is for directions and 4 is * for the maximum number of MB (4 MB in case of IS_8x8) */ @@ -1616,7 +1618,9 @@ void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_ if (low_delay) *low_delay = 0; // needed to see the vectors without trashing the buffers - avcodec_get_chroma_sub_sample(avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift); + ret = av_pix_fmt_get_chroma_sub_sample (avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift); + if (ret) + return ret; av_frame_make_writable(pict); diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c index 96e27d93ede2d..fa4ff54a3ce6a 100644 --- a/libavcodec/vc2enc.c +++ b/libavcodec/vc2enc.c @@ -1063,7 +1063,7 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx) { Plane *p; SubBand *b; - int i, j, level, o, shift; + int i, j, level, o, shift, ret; const AVPixFmtDescriptor *fmt = av_pix_fmt_desc_get(avctx->pix_fmt); const int depth = fmt->comp[0].depth; VC2EncContext *s = avctx->priv_data; @@ -1138,7 +1138,9 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx) } /* Chroma subsampling */ - avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift); + ret = av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift); + if (ret) + return ret; /* Bit depth and color range index */ if (depth == 8 && avctx->color_range == AVCOL_RANGE_JPEG) { diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index f167acf4eefa7..cf9c57f5faa62 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -1761,7 +1761,9 @@ static av_cold int vp3_decode_init(AVCodecContext *avctx) for (i = 0; i < 3; i++) s->qps[i] = -1; - avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift); + ret = av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift); + if (ret) + return ret; s->y_superblock_width = (s->width + 31) / 32; s->y_superblock_height = (s->height + 31) / 32; From bb3d62874e87827ce33ac3821ba1ee96d231698d Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 6 Nov 2017 22:39:17 +0100 Subject: [PATCH 0773/2557] avutil/pixdesc: remove reference to avcodec_get_chroma_sub_sample Don't recommend to use deprecated functions. Signed-off-by: James Almer --- libavutil/pixdesc.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libavutil/pixdesc.h b/libavutil/pixdesc.h index fc3737c4adee6..ea046033a3638 100644 --- a/libavutil/pixdesc.h +++ b/libavutil/pixdesc.h @@ -225,11 +225,6 @@ enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc); * Utility function to access log2_chroma_w log2_chroma_h from * the pixel format AVPixFmtDescriptor. * - * See av_get_chroma_sub_sample() for a function that asserts a - * valid pixel format instead of returning an error code. - * Its recommended that you use avcodec_get_chroma_sub_sample unless - * you do check the return code! - * * @param[in] pix_fmt the pixel format * @param[out] h_shift store log2_chroma_w (horizontal/width shift) * @param[out] v_shift store log2_chroma_h (vertical/height shift) From fbca6e7d162b9a7105d1059826dfe96616fa803a Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Wed, 1 Nov 2017 20:45:20 -0400 Subject: [PATCH 0774/2557] matroskadec: allow RealAudio/Cook/Sipro streams of flavor 0 Regression since 569d18aa9dc989c37bb4d4b968026fe5afa6fff9. Bug-Id: 1055 Cc: libav-stable@libav.org --- libavformat/matroskadec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 3953cd304e2a5..9c8aea36ff589 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -1916,7 +1916,7 @@ static int matroska_parse_tracks(AVFormatContext *s) track->audio.sub_packet_h = avio_rb16(&b); track->audio.frame_size = avio_rb16(&b); track->audio.sub_packet_size = avio_rb16(&b); - if (flavor <= 0 || + if (flavor < 0 || track->audio.coded_framesize <= 0 || track->audio.sub_packet_h <= 0 || track->audio.frame_size <= 0 || From 97ac8a47ddc81cb57b7a702e2a301570faa1f11b Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 21 Oct 2017 18:47:49 +0200 Subject: [PATCH 0775/2557] libavcodec/blockdsp : fix comment. clear_block need 32 aligned now --- libavcodec/blockdsp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/blockdsp.h b/libavcodec/blockdsp.h index 6e27a02ba52d8..26fc2ea13b6ad 100644 --- a/libavcodec/blockdsp.h +++ b/libavcodec/blockdsp.h @@ -33,8 +33,8 @@ typedef void (*op_fill_func)(uint8_t *block /* align width (8 or 16) */, uint8_t value, ptrdiff_t line_size, int h); typedef struct BlockDSPContext { - void (*clear_block)(int16_t *block /* align 16 */); - void (*clear_blocks)(int16_t *blocks /* align 16 */); + void (*clear_block)(int16_t *block /* align 32 */); + void (*clear_blocks)(int16_t *blocks /* align 32 */); op_fill_func fill_block_tab[2]; } BlockDSPContext; From 9c714731895aab109151a36bf21838f7c4e86445 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 28 Oct 2017 17:12:58 +0200 Subject: [PATCH 0776/2557] libavcodec/utvideo : simplify decode_plane the func is only call with step = 1 no need to pass it in the func --- libavcodec/utvideodec.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 26c3f8a506c4f..83dbae99b1aab 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -126,7 +126,7 @@ static int build_huff(const uint8_t *src, VLC *vlc, int *fsym) } static int decode_plane10(UtvideoContext *c, int plane_no, - uint16_t *dst, int step, ptrdiff_t stride, + uint16_t *dst, ptrdiff_t stride, int width, int height, const uint8_t *src, const uint8_t *huff, int use_pred) @@ -152,7 +152,7 @@ static int decode_plane10(UtvideoContext *c, int plane_no, prev = 0x200; for (j = sstart; j < send; j++) { - for (i = 0; i < width * step; i += step) { + for (i = 0; i < width; i++) { pix = fsym; if (use_pred) { prev += pix; @@ -195,8 +195,7 @@ static int decode_plane10(UtvideoContext *c, int plane_no, prev = 0x200; for (j = sstart; j < send; j++) { - int ws = width * step; - for (i = 0; i < ws; i += step) { + for (i = 0; i < width; i++) { pix = get_vlc2(&gb, vlc.table, VLC_BITS, 3); if (pix < 0) { av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n"); @@ -240,7 +239,7 @@ static int compute_cmask(int plane_no, int interlaced, enum AVPixelFormat pix_fm } static int decode_plane(UtvideoContext *c, int plane_no, - uint8_t *dst, int step, ptrdiff_t stride, + uint8_t *dst, ptrdiff_t stride, int width, int height, const uint8_t *src, int use_pred) { @@ -266,7 +265,7 @@ static int decode_plane(UtvideoContext *c, int plane_no, prev = 0x80; for (j = sstart; j < send; j++) { - for (i = 0; i < width * step; i += step) { + for (i = 0; i < width; i++) { pix = fsym; if (use_pred) { prev += pix; @@ -310,8 +309,7 @@ static int decode_plane(UtvideoContext *c, int plane_no, prev = 0x80; for (j = sstart; j < send; j++) { - int ws = width * step; - for (i = 0; i < ws; i += step) { + for (i = 0; i < width; i++) { pix = get_vlc2(&gb, vlc.table, VLC_BITS, 3); if (pix < 0) { av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n"); @@ -634,7 +632,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, case AV_PIX_FMT_GBRP: case AV_PIX_FMT_GBRAP: for (i = 0; i < c->planes; i++) { - ret = decode_plane(c, i, frame.f->data[i], 1, + ret = decode_plane(c, i, frame.f->data[i], frame.f->linesize[i], avctx->width, avctx->height, plane_start[i], c->frame_pred == PRED_LEFT); @@ -671,7 +669,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, case AV_PIX_FMT_GBRAP10: case AV_PIX_FMT_GBRP10: for (i = 0; i < c->planes; i++) { - ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i], 1, + ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i], frame.f->linesize[i] / 2, avctx->width, avctx->height, plane_start[i], plane_start[i + 1] - 1024, @@ -685,7 +683,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, break; case AV_PIX_FMT_YUV420P: for (i = 0; i < 3; i++) { - ret = decode_plane(c, i, frame.f->data[i], 1, frame.f->linesize[i], + ret = decode_plane(c, i, frame.f->data[i], frame.f->linesize[i], avctx->width >> !!i, avctx->height >> !!i, plane_start[i], c->frame_pred == PRED_LEFT); if (ret) @@ -717,7 +715,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, break; case AV_PIX_FMT_YUV422P: for (i = 0; i < 3; i++) { - ret = decode_plane(c, i, frame.f->data[i], 1, frame.f->linesize[i], + ret = decode_plane(c, i, frame.f->data[i], frame.f->linesize[i], avctx->width >> !!i, avctx->height, plane_start[i], c->frame_pred == PRED_LEFT); if (ret) @@ -747,7 +745,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, break; case AV_PIX_FMT_YUV444P: for (i = 0; i < 3; i++) { - ret = decode_plane(c, i, frame.f->data[i], 1, frame.f->linesize[i], + ret = decode_plane(c, i, frame.f->data[i], frame.f->linesize[i], avctx->width, avctx->height, plane_start[i], c->frame_pred == PRED_LEFT); if (ret) @@ -777,7 +775,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, break; case AV_PIX_FMT_YUV422P10: for (i = 0; i < 3; i++) { - ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i], 1, frame.f->linesize[i] / 2, + ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i], frame.f->linesize[i] / 2, avctx->width >> !!i, avctx->height, plane_start[i], plane_start[i + 1] - 1024, c->frame_pred == PRED_LEFT); if (ret) From ad784e0cb68f59d541210b4c53e1486ecbdb488a Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 28 Oct 2017 14:06:22 +0200 Subject: [PATCH 0777/2557] fate/utvideo : add test for decoding and encoding --- tests/fate/utvideo.mak | 48 +++++++++++++++ tests/ref/fate/utvideo_rgb_int_gradient | 6 ++ tests/ref/fate/utvideo_rgb_int_median | 6 ++ tests/ref/fate/utvideo_rgba_gradient | 6 ++ tests/ref/fate/utvideo_yuv420_gradient | 6 ++ tests/ref/fate/utvideo_yuv420_int_gradient | 6 ++ tests/ref/fate/utvideo_yuv420_int_median | 6 ++ tests/ref/fate/utvideo_yuv422_gradient | 6 ++ tests/ref/fate/utvideo_yuv422_int_gradient | 6 ++ tests/ref/fate/utvideo_yuv422_int_median | 6 ++ tests/ref/fate/utvideo_yuv444_709_gradient | 6 ++ .../ref/fate/utvideo_yuv444_709_int_gradient | 6 ++ tests/ref/fate/utvideo_yuv444_709_int_median | 6 ++ tests/ref/fate/utvideo_yuv444_709_median | 6 ++ tests/ref/fate/utvideoenc_yuv444_left | 60 +++++++++++++++++++ tests/ref/fate/utvideoenc_yuv444_median | 60 +++++++++++++++++++ tests/ref/fate/utvideoenc_yuv444_none | 60 +++++++++++++++++++ 17 files changed, 306 insertions(+) create mode 100644 tests/ref/fate/utvideo_rgb_int_gradient create mode 100644 tests/ref/fate/utvideo_rgb_int_median create mode 100644 tests/ref/fate/utvideo_rgba_gradient create mode 100644 tests/ref/fate/utvideo_yuv420_gradient create mode 100644 tests/ref/fate/utvideo_yuv420_int_gradient create mode 100644 tests/ref/fate/utvideo_yuv420_int_median create mode 100644 tests/ref/fate/utvideo_yuv422_gradient create mode 100644 tests/ref/fate/utvideo_yuv422_int_gradient create mode 100644 tests/ref/fate/utvideo_yuv422_int_median create mode 100644 tests/ref/fate/utvideo_yuv444_709_gradient create mode 100644 tests/ref/fate/utvideo_yuv444_709_int_gradient create mode 100644 tests/ref/fate/utvideo_yuv444_709_int_median create mode 100644 tests/ref/fate/utvideo_yuv444_709_median create mode 100644 tests/ref/fate/utvideoenc_yuv444_left create mode 100644 tests/ref/fate/utvideoenc_yuv444_median create mode 100644 tests/ref/fate/utvideoenc_yuv444_none diff --git a/tests/fate/utvideo.mak b/tests/fate/utvideo.mak index 2cf06b36f5865..929a4ee6e2f27 100644 --- a/tests/fate/utvideo.mak +++ b/tests/fate/utvideo.mak @@ -10,6 +10,15 @@ fate-utvideo_rgba_left: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_rgba FATE_UTVIDEO += fate-utvideo_rgba_median fate-utvideo_rgba_median: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_rgba_median.avi +FATE_UTVIDEO += fate-utvideo_rgb_int_median +fate-utvideo_rgb_int_median: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_rgb_64x48_int_median.avi + +FATE_UTVIDEO += fate-utvideo_rgba_gradient +fate-utvideo_rgba_gradient: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_rgba_gradient.avi + +FATE_UTVIDEO += fate-utvideo_rgb_int_gradient +fate-utvideo_rgb_int_gradient: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_rgb_64x48_int_gradient.avi + FATE_UTVIDEO += fate-utvideo_rgba_single_symbol fate-utvideo_rgba_single_symbol: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_rgba_single_symbol.avi @@ -19,12 +28,42 @@ fate-utvideo_yuv420_left: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yu FATE_UTVIDEO += fate-utvideo_yuv420_median fate-utvideo_yuv420_median: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yuv420_median.avi +FATE_UTVIDEO += fate-utvideo_yuv420_int_median +fate-utvideo_yuv420_int_median: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yuv420_709_64x48_int_median.avi + +FATE_UTVIDEO += fate-utvideo_yuv420_gradient +fate-utvideo_yuv420_gradient: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yuv420_709_64x48_gradient.avi + +FATE_UTVIDEO += fate-utvideo_yuv420_int_gradient +fate-utvideo_yuv420_int_gradient: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yuv420_709_64x48_int_gradient.avi + FATE_UTVIDEO += fate-utvideo_yuv422_left fate-utvideo_yuv422_left: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yuv422_left.avi FATE_UTVIDEO += fate-utvideo_yuv422_median fate-utvideo_yuv422_median: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yuv422_median.avi +FATE_UTVIDEO += fate-utvideo_yuv422_int_median +fate-utvideo_yuv422_int_median: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yuv422_709_64x48_int_median.avi + +FATE_UTVIDEO += fate-utvideo_yuv422_gradient +fate-utvideo_yuv422_gradient: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yuv422_709_64x48_gradient.avi + +FATE_UTVIDEO += fate-utvideo_yuv422_int_gradient +fate-utvideo_yuv422_int_gradient: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yuv422_709_64x48_int_gradient.avi + +FATE_UTVIDEO += fate-utvideo_yuv444_709_median +fate-utvideo_yuv444_709_median: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yuv444_709_64x48_median.avi + +FATE_UTVIDEO += fate-utvideo_yuv444_709_int_median +fate-utvideo_yuv444_709_int_median: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yuv444_709_64x48_int_median.avi + +FATE_UTVIDEO += fate-utvideo_yuv444_709_gradient +fate-utvideo_yuv444_709_gradient: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yuv444_709_gradient.avi + +FATE_UTVIDEO += fate-utvideo_yuv444_709_int_gradient +fate-utvideo_yuv444_709_int_gradient: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_yuv444_709_64x48_int_gradient.avi + FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, UTVIDEO) += $(FATE_UTVIDEO) fate-utvideo: $(FATE_UTVIDEO) @@ -66,6 +105,15 @@ fate-utvideoenc_yuv422_median: OPTS = -pix_fmt yuv422p -pred median FATE_UTVIDEOENC += fate-utvideoenc_yuv422_none fate-utvideoenc_yuv422_none: OPTS = -pix_fmt yuv422p -pred none +FATE_UTVIDEOENC += fate-utvideoenc_yuv444_left +fate-utvideoenc_yuv444_left: OPTS = -pix_fmt yuv444p -pred left + +FATE_UTVIDEOENC += fate-utvideoenc_yuv444_median +fate-utvideoenc_yuv444_median: OPTS = -pix_fmt yuv444p -pred median + +FATE_UTVIDEOENC += fate-utvideoenc_yuv444_none +fate-utvideoenc_yuv444_none: OPTS = -pix_fmt yuv444p -pred none + $(FATE_UTVIDEOENC): $(VREF) FATE_AVCONV-$(call ENCMUX, UTVIDEO, AVI) += $(FATE_UTVIDEOENC) diff --git a/tests/ref/fate/utvideo_rgb_int_gradient b/tests/ref/fate/utvideo_rgb_int_gradient new file mode 100644 index 0000000000000..a4e6986622ec9 --- /dev/null +++ b/tests/ref/fate/utvideo_rgb_int_gradient @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x48 +#sar 0: 0/1 +0, 0, 0, 1, 9216, 0xd00fdd8c diff --git a/tests/ref/fate/utvideo_rgb_int_median b/tests/ref/fate/utvideo_rgb_int_median new file mode 100644 index 0000000000000..a4e6986622ec9 --- /dev/null +++ b/tests/ref/fate/utvideo_rgb_int_median @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x48 +#sar 0: 0/1 +0, 0, 0, 1, 9216, 0xd00fdd8c diff --git a/tests/ref/fate/utvideo_rgba_gradient b/tests/ref/fate/utvideo_rgba_gradient new file mode 100644 index 0000000000000..f52f46b23e519 --- /dev/null +++ b/tests/ref/fate/utvideo_rgba_gradient @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 37x37 +#sar 0: 0/1 +0, 0, 0, 1, 5476, 0x20f860ad diff --git a/tests/ref/fate/utvideo_yuv420_gradient b/tests/ref/fate/utvideo_yuv420_gradient new file mode 100644 index 0000000000000..5e2b7ee1be283 --- /dev/null +++ b/tests/ref/fate/utvideo_yuv420_gradient @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x48 +#sar 0: 0/1 +0, 0, 0, 1, 4608, 0xc441dd90 diff --git a/tests/ref/fate/utvideo_yuv420_int_gradient b/tests/ref/fate/utvideo_yuv420_int_gradient new file mode 100644 index 0000000000000..08e45d79e6abd --- /dev/null +++ b/tests/ref/fate/utvideo_yuv420_int_gradient @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x48 +#sar 0: 0/1 +0, 0, 0, 1, 4608, 0x8cecddae diff --git a/tests/ref/fate/utvideo_yuv420_int_median b/tests/ref/fate/utvideo_yuv420_int_median new file mode 100644 index 0000000000000..08e45d79e6abd --- /dev/null +++ b/tests/ref/fate/utvideo_yuv420_int_median @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x48 +#sar 0: 0/1 +0, 0, 0, 1, 4608, 0x8cecddae diff --git a/tests/ref/fate/utvideo_yuv422_gradient b/tests/ref/fate/utvideo_yuv422_gradient new file mode 100644 index 0000000000000..f4949b23413bd --- /dev/null +++ b/tests/ref/fate/utvideo_yuv422_gradient @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x48 +#sar 0: 0/1 +0, 0, 0, 1, 6144, 0xd33add91 diff --git a/tests/ref/fate/utvideo_yuv422_int_gradient b/tests/ref/fate/utvideo_yuv422_int_gradient new file mode 100644 index 0000000000000..f4949b23413bd --- /dev/null +++ b/tests/ref/fate/utvideo_yuv422_int_gradient @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x48 +#sar 0: 0/1 +0, 0, 0, 1, 6144, 0xd33add91 diff --git a/tests/ref/fate/utvideo_yuv422_int_median b/tests/ref/fate/utvideo_yuv422_int_median new file mode 100644 index 0000000000000..f4949b23413bd --- /dev/null +++ b/tests/ref/fate/utvideo_yuv422_int_median @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x48 +#sar 0: 0/1 +0, 0, 0, 1, 6144, 0xd33add91 diff --git a/tests/ref/fate/utvideo_yuv444_709_gradient b/tests/ref/fate/utvideo_yuv444_709_gradient new file mode 100644 index 0000000000000..0870c87d3bf76 --- /dev/null +++ b/tests/ref/fate/utvideo_yuv444_709_gradient @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 38x38 +#sar 0: 0/1 +0, 0, 0, 1, 4332, 0xa9de65ba diff --git a/tests/ref/fate/utvideo_yuv444_709_int_gradient b/tests/ref/fate/utvideo_yuv444_709_int_gradient new file mode 100644 index 0000000000000..af9337cd6a82c --- /dev/null +++ b/tests/ref/fate/utvideo_yuv444_709_int_gradient @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x48 +#sar 0: 0/1 +0, 0, 0, 1, 9216, 0xbcb2dd78 diff --git a/tests/ref/fate/utvideo_yuv444_709_int_median b/tests/ref/fate/utvideo_yuv444_709_int_median new file mode 100644 index 0000000000000..af9337cd6a82c --- /dev/null +++ b/tests/ref/fate/utvideo_yuv444_709_int_median @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x48 +#sar 0: 0/1 +0, 0, 0, 1, 9216, 0xbcb2dd78 diff --git a/tests/ref/fate/utvideo_yuv444_709_median b/tests/ref/fate/utvideo_yuv444_709_median new file mode 100644 index 0000000000000..af9337cd6a82c --- /dev/null +++ b/tests/ref/fate/utvideo_yuv444_709_median @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x48 +#sar 0: 0/1 +0, 0, 0, 1, 9216, 0xbcb2dd78 diff --git a/tests/ref/fate/utvideoenc_yuv444_left b/tests/ref/fate/utvideoenc_yuv444_left new file mode 100644 index 0000000000000..1b8d9257610be --- /dev/null +++ b/tests/ref/fate/utvideoenc_yuv444_left @@ -0,0 +1,60 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#extradata 0, 16, e46c7123194c0ebf19a23e5cefebaa63 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: utvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 144080, 678b4a3ece35971c3e0f199fcab2b4a1 +0, 1, 1, 1, 144120, d0c326ed062b569a04ea84359e43cfde +0, 2, 2, 1, 144956, 32e2d8a1dc22b1d837e8f70509767d7d +0, 3, 3, 1, 143324, 6fff1691c498ccf1cf848147dcc1b62c +0, 4, 4, 1, 142464, df4caa8316ec987fe3cba4a76c0976f0 +0, 5, 5, 1, 144068, 2cc92f54850a45d76b8a959d62c28408 +0, 6, 6, 1, 143840, c80e0e9945a92869ca639b59118f24f3 +0, 7, 7, 1, 143536, 682a3148911f94daa333e12a505d689f +0, 8, 8, 1, 143736, af692d8d5fe2e23f9e16c7164ceaaeb5 +0, 9, 9, 1, 144076, 13412473483a727e8cced00d0d0fbb78 +0, 10, 10, 1, 144012, 4f1402c7d25ee222329cc007aa4df345 +0, 11, 11, 1, 143520, cc4b83f407d031cc4a166c3210583599 +0, 12, 12, 1, 141640, e4a4d1b88c7aabfcc40c51ff80305f70 +0, 13, 13, 1, 143096, b3de93652c190bc88dd6e17a27db4ebf +0, 14, 14, 1, 144704, 48ce5d6a84b965f38f5e4a46e8bfd0c3 +0, 15, 15, 1, 144520, 936970ae76c23e6a7880f2c875c1fb66 +0, 16, 16, 1, 143704, 32d9a3e4118e1134f3c0ead846805aaf +0, 17, 17, 1, 143648, 4214224b843fab53ae45921426de1892 +0, 18, 18, 1, 142920, 22b1c3a09f23fa262d7ffa2fb4347f3a +0, 19, 19, 1, 142604, d24c0ba247bb38bf7bdfc348d7c6fdf1 +0, 20, 20, 1, 141928, 8115cdd0fb51fa90821f93900c8cc980 +0, 21, 21, 1, 142072, f6d87afe383aa9a85b89832e422859e0 +0, 22, 22, 1, 142204, ced75258ae7001a8a4029423d61abf06 +0, 23, 23, 1, 143420, 686a5ded45cd70af9e699e9919da9cc7 +0, 24, 24, 1, 144552, 5a1e0f522e74a1284b86c5d0e185f16d +0, 25, 25, 1, 143328, f54e6787ac2f3ac0e925388b66c95b2a +0, 26, 26, 1, 142584, 652dda504ace9c4e1569319ef6cd333d +0, 27, 27, 1, 142084, 3eafb87f47844ce6d0572af051d2e25b +0, 28, 28, 1, 140196, 92b60cf33e5c430f3e92a39bb4389096 +0, 29, 29, 1, 140152, 658a331d3f5ee1bb50392f3835aed56d +0, 30, 30, 1, 141484, b54db7d5978d99f7192dd2008438ab41 +0, 31, 31, 1, 142360, ed84a9d2241ade4c36f95eaa1ae00b0e +0, 32, 32, 1, 142744, 7dbb99de3a4a81de5564bb577471128d +0, 33, 33, 1, 144360, bd26a71b0824a04badfffa0653f0ac00 +0, 34, 34, 1, 143464, 11fe56173423180d581bc52fe044657a +0, 35, 35, 1, 142856, 9f690fa8727669ba8640032933eb8235 +0, 36, 36, 1, 142108, b5c182f3f0e6d307f598dc55f51f9d51 +0, 37, 37, 1, 142492, ab7b6b446b4f5f5ec2b2eb52f934523c +0, 38, 38, 1, 140532, 3fda7e5443dcf59e52f523bcf863d5d2 +0, 39, 39, 1, 140288, 1426cb304a219876586ba5c161809fac +0, 40, 40, 1, 140540, 3a69f372875e2cd6ec5b49498e1f1a05 +0, 41, 41, 1, 141868, aca8f0bd1b29c4142b80e5e3e59aeb75 +0, 42, 42, 1, 141892, 91bf3847703041b4fbe87602e78fb577 +0, 43, 43, 1, 142080, f1b28c53e1068a6305ebb6d4862aebf1 +0, 44, 44, 1, 141220, 188ffeef2973b490364e8cf01fc2d8e6 +0, 45, 45, 1, 139908, 1eaa1194f719aa6da4c7ab4dddcee4ce +0, 46, 46, 1, 138868, 2243b5d473d6df2ea283752fe799c95b +0, 47, 47, 1, 139276, d74f2cbfac00177d848fb1b1e223e654 +0, 48, 48, 1, 139312, 27054be184a1028a86c5e3406418a92c +0, 49, 49, 1, 138132, feb653f902c92cfd1954b61b9d1149f2 diff --git a/tests/ref/fate/utvideoenc_yuv444_median b/tests/ref/fate/utvideoenc_yuv444_median new file mode 100644 index 0000000000000..f690a38089332 --- /dev/null +++ b/tests/ref/fate/utvideoenc_yuv444_median @@ -0,0 +1,60 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#extradata 0, 16, e46c7123194c0ebf19a23e5cefebaa63 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: utvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 136492, 5e3cc78fe9e404b0eca7c2df98841eab +0, 1, 1, 1, 136336, cec7bad80feac6e16a3d84734ae473d8 +0, 2, 2, 1, 137296, cb43d766c513da815c5964f1f48c2e49 +0, 3, 3, 1, 136088, 4c8900602c580526057b52bb14161274 +0, 4, 4, 1, 135276, a9b134a0e49812ff929cdd57d8a00907 +0, 5, 5, 1, 136668, 0b9dc3cd51ce5c674315c06bd677fcea +0, 6, 6, 1, 136480, 16020ff181e477f1b01b86aa5070bf7c +0, 7, 7, 1, 135876, 557f1f43cdfc06603f3bd97bb9d44394 +0, 8, 8, 1, 136204, c03b7cd310961ef9fe8734f45a9276e2 +0, 9, 9, 1, 136796, b668c63bed0b2de4d182cf0281e71ecf +0, 10, 10, 1, 136252, 7758777682f6e3ea84010cbaf2645a6e +0, 11, 11, 1, 136284, 699e6ab66911cdd0fa357c069537e3ec +0, 12, 12, 1, 135096, 65d4d3b6e1bbf6d67baca1f346d06735 +0, 13, 13, 1, 136088, 7d69fb86f67b3fd3df4008cb03d9f1ef +0, 14, 14, 1, 136876, abca4a026bf93da58283d5ddd51cead4 +0, 15, 15, 1, 137096, f5bb254ede8a9ed4c07fb80fb1a301d7 +0, 16, 16, 1, 136232, cdbe70b4b7051b9c1092ea626e825658 +0, 17, 17, 1, 136308, acb31052249c48b729842938977172e8 +0, 18, 18, 1, 135444, bf38e56e2a152154b0401507550b5605 +0, 19, 19, 1, 135300, 1737341c361f656feffc86903da34647 +0, 20, 20, 1, 134548, c28e9c441544b7c51cf76afd4b5a2799 +0, 21, 21, 1, 134816, 5b8ba0d205863105d723afcc28274fb2 +0, 22, 22, 1, 134776, 90c5ac5ed83ed6a43b4fe14c0ee07dc5 +0, 23, 23, 1, 136332, 3ca065b60b4fbc5b04f68e6bb900d862 +0, 24, 24, 1, 136724, 283b23278ca40dc93a326e96e5c22629 +0, 25, 25, 1, 135948, 6568fb8593edce20f294a936ab11153b +0, 26, 26, 1, 135400, 22abaf0c3184a79cb90b4d7fe6cee897 +0, 27, 27, 1, 135056, abd6117e31af2d136c0df8ab1db64599 +0, 28, 28, 1, 133676, 67a65017fb2a232a726717628fbe1d95 +0, 29, 29, 1, 133700, 7dff3d958ecbedc691d3b188084d26d9 +0, 30, 30, 1, 134444, 192c98c1a7c2f4a15c7aa59607b7d1ff +0, 31, 31, 1, 135388, 32d1aba6d499162345fcb0ca858558d5 +0, 32, 32, 1, 135680, 77cd1f8ddf7ce977ba9ff074d595e033 +0, 33, 33, 1, 136404, 9eb0213f0d66d957f668f88d426f014f +0, 34, 34, 1, 135816, 337b4082181e8627f2fe9c852681688f +0, 35, 35, 1, 135616, c73c95e75669ce9dafd0ac253239430a +0, 36, 36, 1, 135136, e4e5515dbb05b855b4ce42fe1638d119 +0, 37, 37, 1, 135572, 987ffdc8d0c142e92dc02190f73afd70 +0, 38, 38, 1, 134748, 8a01538b863e51066f896f18ad8cc68b +0, 39, 39, 1, 134428, 3096e9435e5813d54013bf5c86e15c4f +0, 40, 40, 1, 133796, 78d3952c814172173b24881e110c861f +0, 41, 41, 1, 135052, b0c2bf0b1047dd71268d3c3114b655d8 +0, 42, 42, 1, 134768, 653862b7e519c299278186920217a303 +0, 43, 43, 1, 134692, 26fb91814efadd0120f247d6b5f22d81 +0, 44, 44, 1, 134164, e85390622cb7eb6618512ead58d578c6 +0, 45, 45, 1, 133380, 7c04e5015f89c24713227329aa1820fb +0, 46, 46, 1, 132872, 877db229c19c9719bd9b19d0dab1c169 +0, 47, 47, 1, 132864, c4a86326303f96d53cb267111ed199e5 +0, 48, 48, 1, 132644, 7dd3fe41c535d168eb0450d96171ec0f +0, 49, 49, 1, 131772, c430f15c1683207fbec250dc9d7a2b13 diff --git a/tests/ref/fate/utvideoenc_yuv444_none b/tests/ref/fate/utvideoenc_yuv444_none new file mode 100644 index 0000000000000..880b813769dfa --- /dev/null +++ b/tests/ref/fate/utvideoenc_yuv444_none @@ -0,0 +1,60 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#extradata 0, 16, e46c7123194c0ebf19a23e5cefebaa63 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: utvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 286288, f77b660b13f4ca2d906dbe620019224f +0, 1, 1, 1, 286388, 61c3e9c05be428c2adf312257580d528 +0, 2, 2, 1, 286148, cf2d8de31997ba6c9c87ca0203295ffd +0, 3, 3, 1, 286124, 981f9eeeed512af38eac7c5df0693b85 +0, 4, 4, 1, 286644, be9e95106ca59737b1154b865e917110 +0, 5, 5, 1, 286280, e70b66f13e4a08c10e1d014ac1be0cf9 +0, 6, 6, 1, 286176, b20a78e4bcd02d7fedc0f00af8276847 +0, 7, 7, 1, 286132, 80cc66c88ea015b62bbf46ae188eed95 +0, 8, 8, 1, 285968, 446ae00d0e1fc233b66ecb35c720464d +0, 9, 9, 1, 285888, 9d4b29bfd62e5cac2d77185e19706325 +0, 10, 10, 1, 285792, bc74548c1ed37dc1d6ca523e00b83ed7 +0, 11, 11, 1, 285412, f7234684c90e0dfcfd7ff9a7612b9cb9 +0, 12, 12, 1, 286080, 3873173b7da6113b058c0e50d1fb2ac9 +0, 13, 13, 1, 285524, 90654181491240e1883cfa8e9dcbc53a +0, 14, 14, 1, 285628, 5ae2de1a60c2586af4a27dca27e0d614 +0, 15, 15, 1, 285620, 9d78ee5f1390c05af2677bedf2b088e4 +0, 16, 16, 1, 285768, 7c47cbbba7af11ace3233c904e628242 +0, 17, 17, 1, 285880, 8292ea2eb80b860edf0747707eb99966 +0, 18, 18, 1, 285956, 17aef410ca3fec63ef83185401e005a3 +0, 19, 19, 1, 285992, 779819d6d090a67261ef3611f7b50ad6 +0, 20, 20, 1, 285920, 52fbe43f864350643cb4e8a57fcf8f63 +0, 21, 21, 1, 286040, c2e7919e6e20c7fcf78c0229e4d456d4 +0, 22, 22, 1, 285844, edc46036a229878d26a8df1f6dfbd661 +0, 23, 23, 1, 285868, 7e5a9af2d70dc57a7ca0a03f88a3a1a9 +0, 24, 24, 1, 286056, 174d2c8aca73cb5481e12a5a22516d02 +0, 25, 25, 1, 285836, cf1d28a88aa4fc2a5e16e03e2081919f +0, 26, 26, 1, 286004, 2ffd12c7501e4709939712a62945ec29 +0, 27, 27, 1, 286264, 61962127ef2a4612a9a352119b7444dd +0, 28, 28, 1, 286632, 9355ea7ef38424633b9e0b77ebb23d77 +0, 29, 29, 1, 286508, a741f67693b0154355966a1b07265939 +0, 30, 30, 1, 286124, 0fb2a3a0b6e525907b6d0c50ca8f7be1 +0, 31, 31, 1, 286308, 89fd53c38119426cdd63be714e857dac +0, 32, 32, 1, 286032, 674d9043981cce19c39e2c6d405d856a +0, 33, 33, 1, 285672, 7b9678e7772b71abf5a95fa967d319af +0, 34, 34, 1, 285520, 6e626d4c722ccafea6600a62c093a47a +0, 35, 35, 1, 285828, 49e9023d9c820798af6b445ec1d87b13 +0, 36, 36, 1, 286344, 6cf611f3ef47442659e3ce3807d3a480 +0, 37, 37, 1, 286360, a0eca88afed37e0747b1fa61c7e36713 +0, 38, 38, 1, 286264, 5b3e605f71b8bab3aa2cc3ed439c6f8a +0, 39, 39, 1, 286096, f9a1c5beca596e2b5eef2392b0adb01e +0, 40, 40, 1, 286284, eb2440f6539413efc86e5a0cd545ecd4 +0, 41, 41, 1, 285816, 520d3344f335b580bfb2fad58b1643b4 +0, 42, 42, 1, 285864, 48ed0d9ed707808298800c87f2d61d75 +0, 43, 43, 1, 286108, 9cb952285049f8354ab7e00c0ab2f7d5 +0, 44, 44, 1, 286308, 7ba07e4cc04cd42272ab75e1a65703ca +0, 45, 45, 1, 286552, 55722a7bc60c9eb68a94fd0e8ba3ba4f +0, 46, 46, 1, 286456, e3e54e031bcf3067360955817690a755 +0, 47, 47, 1, 286240, 96aa493b2b8d264ffb0d49c952594c11 +0, 48, 48, 1, 286128, 6e7e04eec86f257aa46c59f0e8b6b22c +0, 49, 49, 1, 286128, ab72c8a01a095040efb1d4cb1fddbd4a From fbe91487797c91dc9e4b79628a448e2451ef28a6 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 29 Oct 2017 18:01:30 +0100 Subject: [PATCH 0778/2557] checkasm/llviddsp : add test for other dsp func add_median_pred add_left_pred : add two func one with acc 0, and one with random acc add_left_pred16 --- tests/checkasm/llviddsp.c | 116 +++++++++++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 8 deletions(-) diff --git a/tests/checkasm/llviddsp.c b/tests/checkasm/llviddsp.c index b1f3b83b43b59..9b35e2cadcb07 100644 --- a/tests/checkasm/llviddsp.c +++ b/tests/checkasm/llviddsp.c @@ -31,23 +31,29 @@ #define randomize_buffers(buf, size) \ do { \ int j; \ + uint8_t *tmp_buf = (uint8_t *)buf;\ for (j = 0; j < size; j++) \ - buf[j] = rnd() & 0xFF; \ + tmp_buf[j] = rnd() & 0xFF; \ } while (0) +#define init_buffer(a0, a1, type, width)\ + type *a0 = av_mallocz_array(width, sizeof(type));\ + type *a1 = av_mallocz_array(width, sizeof(type));\ + if (!a0 || !a1)\ + fail();\ + randomize_buffers(a0, width * sizeof(type));\ + memcpy(a1, a0, width*sizeof(type));\ + static void check_add_bytes(LLVidDSPContext c, int width) { - uint8_t *src0 = av_mallocz(width); - uint8_t *src1 = av_mallocz(width); uint8_t *dst0 = av_mallocz(width); uint8_t *dst1 = av_mallocz(width); - declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, uint8_t *src, ptrdiff_t w); + init_buffer(src0, src1, uint8_t, width); - if (!src0 || !src1 || !dst0 || !dst1) + if (!dst0 || !dst1) fail(); - randomize_buffers(src0, width); - memcpy(src1, src0, width); + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, uint8_t *src, ptrdiff_t w); if (check_func(c.add_bytes, "add_bytes")) { call_ref(dst0, src0, width); @@ -63,14 +69,108 @@ static void check_add_bytes(LLVidDSPContext c, int width) av_free(dst1); } +static void check_add_median_pred(LLVidDSPContext c, int width) { + int A0, A1, B0, B1; + uint8_t *dst0 = av_mallocz(width); + uint8_t *dst1 = av_mallocz(width); + init_buffer(src0, src1, uint8_t, width); + init_buffer(diff0, diff1, uint8_t, width); + + A0 = rnd() & 0xFF; + B0 = rnd() & 0xFF; + A1 = A0; + B1 = B0; + + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, const uint8_t *src1, + const uint8_t *diff, ptrdiff_t w, + int *left, int *left_top); + + if (check_func(c.add_median_pred, "add_median_pred")) { + call_ref(dst0, src0, diff0, width, &A0, &B0); + call_new(dst1, src1, diff1, width, &A1, &B1); + if (memcmp(dst0, dst1, width) || (A0 != A1) || (B0 != B1)) + fail(); + bench_new(dst1, src1, diff1, width, &A1, &B1); + } + + av_free(src0); + av_free(src1); + av_free(diff0); + av_free(diff1); + av_free(dst0); + av_free(dst1); +} + +static void check_add_left_pred(LLVidDSPContext c, int width, int acc, const char * report) +{ + uint8_t *dst0 = av_mallocz(width); + uint8_t *dst1 = av_mallocz(width); + init_buffer(src0, src1, uint8_t, width); + + if (!dst0 || !dst1) + fail(); + + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, uint8_t *src, ptrdiff_t w, int acc); + + if (check_func(c.add_left_pred, "%s", report)) { + call_ref(dst0, src0, width, acc); + call_new(dst1, src1, width, acc); + if (memcmp(dst0, dst1, width)) + fail(); + bench_new(dst1, src1, width, acc); + } + + av_free(src0); + av_free(src1); + av_free(dst0); + av_free(dst1); +} + +static void check_add_left_pred_16(LLVidDSPContext c, unsigned mask, int width, unsigned acc, const char * report) +{ + uint16_t *dst0 = av_mallocz_array(width, sizeof(uint16_t)); + uint16_t *dst1 = av_mallocz_array(width, sizeof(uint16_t)); + init_buffer(src0, src1, uint16_t, width); + + if (!dst0 || !dst1) + fail(); + + declare_func_emms(AV_CPU_FLAG_MMX, void, uint16_t *dst, uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc); + + if (check_func(c.add_left_pred_int16, "%s", report)) { + call_ref(dst0, src0, mask, width, acc); + call_new(dst1, src1, mask, width, acc); + if (memcmp(dst0, dst1, width)) + fail(); + bench_new(dst1, src1, mask, width, acc); + } + + av_free(src0); + av_free(src1); + av_free(dst0); + av_free(dst1); +} + void checkasm_check_llviddsp(void) { LLVidDSPContext c; int width = 16 * av_clip(rnd(), 16, 128); + int accRnd = rnd() & 0xFF; ff_llviddsp_init(&c); check_add_bytes(c, width); - report("add_bytes"); + + check_add_median_pred(c, width); + report("add_median_pred"); + + check_add_left_pred(c, width, 0, "add_left_pred_zero"); + report("add_left_pred_zero"); + + check_add_left_pred(c, width, accRnd, "add_left_pred_rnd_acc"); + report("add_left_pred_rnd_acc"); + + check_add_left_pred_16(c, 255, width, accRnd, "add_left_pred_int16"); + report("add_left_pred_int16"); } From da62128ea1429daae6c680838d6726e9cfd10972 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 6 Nov 2017 21:51:54 +0100 Subject: [PATCH 0779/2557] libavcodec/lossless_videodsp : add add_bytes avx2 version --- libavcodec/lossless_videodsp.h | 2 +- libavcodec/x86/lossless_videodsp.asm | 5 +++++ libavcodec/x86/lossless_videodsp_init.c | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libavcodec/lossless_videodsp.h b/libavcodec/lossless_videodsp.h index cecf0fe1e5186..ccab39bac6594 100644 --- a/libavcodec/lossless_videodsp.h +++ b/libavcodec/lossless_videodsp.h @@ -29,7 +29,7 @@ #include "libavutil/cpu.h" typedef struct LLVidDSPContext { - void (*add_bytes)(uint8_t *dst /* align 16 */, uint8_t *src /* align 16 */, + void (*add_bytes)(uint8_t *dst /* align 32 */, uint8_t *src /* align 32 */, ptrdiff_t w); void (*add_median_pred)(uint8_t *dst, const uint8_t *top, const uint8_t *diff, ptrdiff_t w, diff --git a/libavcodec/x86/lossless_videodsp.asm b/libavcodec/x86/lossless_videodsp.asm index 443fe02951d7e..70ed555737dbc 100644 --- a/libavcodec/x86/lossless_videodsp.asm +++ b/libavcodec/x86/lossless_videodsp.asm @@ -217,6 +217,11 @@ ADD_BYTES INIT_XMM sse2 ADD_BYTES +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +ADD_BYTES +%endif + %macro ADD_HFYU_LEFT_LOOP_INT16 2 ; %1 = dst alignment (a/u), %2 = src alignment (a/u) add wd, wd add srcq, wq diff --git a/libavcodec/x86/lossless_videodsp_init.c b/libavcodec/x86/lossless_videodsp_init.c index 21bbd12bd2d91..4f20c1ce920a3 100644 --- a/libavcodec/x86/lossless_videodsp_init.c +++ b/libavcodec/x86/lossless_videodsp_init.c @@ -25,6 +25,7 @@ void ff_add_bytes_mmx(uint8_t *dst, uint8_t *src, ptrdiff_t w); void ff_add_bytes_sse2(uint8_t *dst, uint8_t *src, ptrdiff_t w); +void ff_add_bytes_avx2(uint8_t *dst, uint8_t *src, ptrdiff_t w); void ff_add_median_pred_mmxext(uint8_t *dst, const uint8_t *top, const uint8_t *diff, ptrdiff_t w, @@ -115,4 +116,7 @@ void ff_llviddsp_init_x86(LLVidDSPContext *c) if (EXTERNAL_SSE4(cpu_flags)) { c->add_left_pred_int16 = ff_add_left_pred_int16_sse4; } + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + c->add_bytes = ff_add_bytes_avx2; + } } From 0380b72d35a092f3089af52e57dee0d848bc2b9f Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 6 Nov 2017 21:52:37 +0100 Subject: [PATCH 0780/2557] libavcodec/lossless_video_dsp : cosmetic add better separator for each function, in order to make reading of the asm file easier --- libavcodec/x86/lossless_videodsp.asm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavcodec/x86/lossless_videodsp.asm b/libavcodec/x86/lossless_videodsp.asm index 70ed555737dbc..ba4d4f0153de4 100644 --- a/libavcodec/x86/lossless_videodsp.asm +++ b/libavcodec/x86/lossless_videodsp.asm @@ -36,9 +36,11 @@ pb_zzzzzzzz67676767: db -1,-1,-1,-1,-1,-1,-1,-1, 6, 7, 6, 7, 6, 7, 6, 7 SECTION .text +;------------------------------------------------------------------------------ ; void ff_add_median_pred_mmxext(uint8_t *dst, const uint8_t *top, ; const uint8_t *diff, int w, ; int *left, int *left_top) +;------------------------------------------------------------------------------ %macro MEDIAN_PRED 0 cglobal add_median_pred, 6,6,8, dst, top, diff, w, left, left_top movu m0, [topq] @@ -149,7 +151,9 @@ MEDIAN_PRED RET %endmacro +;------------------------------------------------------------------------------ ; int ff_add_left_pred(uint8_t *dst, const uint8_t *src, int w, int left) +;------------------------------------------------------------------------------ INIT_MMX ssse3 cglobal add_left_pred, 3,3,7, dst, src, w, left .skip_prologue: @@ -178,6 +182,9 @@ cglobal add_left_pred_unaligned, 3,3,7, dst, src, w, left .src_unaligned: ADD_LEFT_LOOP 0, 0 +;------------------------------------------------------------------------------ +; void ff_add_bytes(uint8_t *dst, uint8_t *src, ptrdiff_t w); +;------------------------------------------------------------------------------ %macro ADD_BYTES 0 cglobal add_bytes, 3,4,2, dst, src, w, size mov sizeq, wq @@ -263,7 +270,9 @@ ADD_BYTES RET %endmacro +;--------------------------------------------------------------------------------------------- ; int add_left_pred_int16(uint16_t *dst, const uint16_t *src, unsigned mask, int w, int left) +;--------------------------------------------------------------------------------------------- INIT_MMX ssse3 cglobal add_left_pred_int16, 4,4,8, dst, src, mask, w, left .skip_prologue: From 7e1f21148dfdf7f6477b17a7c77e4406fe4650a6 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 6 Nov 2017 23:59:00 +0100 Subject: [PATCH 0781/2557] libavcodec/mepgvideo : remove warning introduce by previous patch Signed-off-by: James Almer --- libavcodec/mpegvideo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 080e9077fcf4a..2eb19c21bb387 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -1453,7 +1453,6 @@ void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_ const int mv_stride = (mb_width << mv_sample_log2) + (avctx->codec->id == AV_CODEC_ID_H264 ? 0 : 1); int mb_x, mb_y, mbcount = 0; - int ret; /* size is width * height * 2 * 4 where 2 is for directions and 4 is * for the maximum number of MB (4 MB in case of IS_8x8) */ @@ -1609,7 +1608,7 @@ void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_ if ((avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || (avctx->debug_mv)) { int mb_y; - int i; + int i, ret; int h_chroma_shift, v_chroma_shift, block_height; const int mv_sample_log2 = avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_SVQ3 ? 2 : 1; const int mv_stride = (mb_width << mv_sample_log2) + From ecd69cade8eded32b1185f4e70e65dbb3f6ac293 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Mon, 6 Nov 2017 10:49:23 +0530 Subject: [PATCH 0782/2557] avcodec/mips: Improve avc avg mc 10, 30, 01 and 03 msa functions Align the mask buffer to 64 bytes. Load the specific destination bytes instead of MSA load and pack. Remove unused macros and functions. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/h264qpel_msa.c | 1269 +++++++++++++++++++------------- 1 file changed, 751 insertions(+), 518 deletions(-) diff --git a/libavcodec/mips/h264qpel_msa.c b/libavcodec/mips/h264qpel_msa.c index dd11f00d8e0b3..9c779bdd4f407 100644 --- a/libavcodec/mips/h264qpel_msa.c +++ b/libavcodec/mips/h264qpel_msa.c @@ -21,7 +21,7 @@ #include "libavutil/mips/generic_macros_msa.h" #include "h264dsp_mips.h" -static const uint8_t luma_mask_arr[16 * 8] = { +static const uint8_t luma_mask_arr[16 * 6] __attribute__((aligned(0x40))) = { /* 8 width cases */ 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 1, 4, 2, 5, 3, 6, 4, 7, 5, 8, 6, 9, 7, 10, 8, 11, @@ -31,9 +31,6 @@ static const uint8_t luma_mask_arr[16 * 8] = { 0, 5, 1, 6, 2, 7, 3, 8, 16, 21, 17, 22, 18, 23, 19, 24, 1, 4, 2, 5, 3, 6, 4, 7, 17, 20, 18, 21, 19, 22, 20, 23, 2, 3, 3, 4, 4, 5, 5, 6, 18, 19, 19, 20, 20, 21, 21, 22, - - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 25, - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26 }; #define AVC_CALC_DPADD_B_6PIX_2COEFF_SH(vec0, vec1, vec2, vec3, vec4, vec5, \ @@ -356,414 +353,6 @@ static void avc_luma_hv_qrt_16x16_msa(const uint8_t *src_x, } } -static void avc_luma_hz_qrt_and_aver_dst_4x4_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - uint8_t hor_offset) -{ - uint8_t slide; - v16i8 src0, src1, src2, src3; - v16u8 dst0, dst1, dst2, dst3; - v16i8 mask0, mask1, mask2; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 out0, out1; - v16i8 minus5b = __msa_ldi_b(-5); - v16i8 plus20b = __msa_ldi_b(20); - v16u8 res0, res1; - - LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); - - if (hor_offset) { - slide = 3; - } else { - slide = 2; - } - - LD_SB4(src, src_stride, src0, src1, src2, src3); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - - XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B2_SB(src0, src1, src2, src3, mask0, mask0, vec0, vec1); - HADD_SB2_SH(vec0, vec1, out0, out1); - VSHF_B2_SB(src0, src1, src2, src3, mask1, mask1, vec2, vec3); - DPADD_SB2_SH(vec2, vec3, minus5b, minus5b, out0, out1); - VSHF_B2_SB(src0, src1, src2, src3, mask2, mask2, vec4, vec5); - DPADD_SB2_SH(vec4, vec5, plus20b, plus20b, out0, out1); - SRARI_H2_SH(out0, out1, 5); - SAT_SH2_SH(out0, out1, 7); - - PCKEV_B2_UB(out0, out0, out1, out1, res0, res1); - - src0 = __msa_sld_b(src0, src0, slide); - src1 = __msa_sld_b(src1, src1, slide); - src2 = __msa_sld_b(src2, src2, slide); - src3 = __msa_sld_b(src3, src3, slide); - src0 = (v16i8) __msa_insve_w((v4i32) src0, 1, (v4i32) src1); - src1 = (v16i8) __msa_insve_w((v4i32) src2, 1, (v4i32) src3); - res0 = (v16u8) __msa_aver_s_b((v16i8) res0, src0); - res1 = (v16u8) __msa_aver_s_b((v16i8) res1, src1); - - XORI_B2_128_UB(res0, res1); - - dst0 = (v16u8) __msa_insve_w((v4i32) dst0, 1, (v4i32) dst1); - dst1 = (v16u8) __msa_insve_w((v4i32) dst2, 1, (v4i32) dst3); - - AVER_UB2_UB(res0, dst0, res1, dst1, dst0, dst1); - - ST4x4_UB(dst0, dst1, 0, 1, 0, 1, dst, dst_stride); -} - -static void avc_luma_hz_qrt_and_aver_dst_8x8_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - uint8_t hor_offset) -{ - uint8_t slide; - uint32_t loop_cnt; - v16i8 src0, src1, src2, src3; - v16i8 mask0, mask1, mask2; - v16u8 dst0, dst1, dst2, dst3; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v16i8 vec6, vec7, vec8, vec9, vec10, vec11; - v8i16 out0, out1, out2, out3; - v16i8 minus5b = __msa_ldi_b(-5); - v16i8 plus20b = __msa_ldi_b(20); - v16i8 res0, res1, res2, res3; - - LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); - - if (hor_offset) { - slide = 3; - } else { - slide = 2; - } - - for (loop_cnt = 2; loop_cnt--;) { - LD_SB4(src, src_stride, src0, src1, src2, src3); - src += (4 * src_stride); - - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - - XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); - VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); - HADD_SB4_SH(vec0, vec1, vec2, vec3, out0, out1, out2, out3); - VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec4, vec5); - VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec6, vec7); - DPADD_SB4_SH(vec4, vec5, vec6, vec7, minus5b, minus5b, minus5b, minus5b, - out0, out1, out2, out3); - VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec8, vec9); - VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec10, vec11); - DPADD_SB4_SH(vec8, vec9, vec10, vec11, plus20b, plus20b, plus20b, - plus20b, out0, out1, out2, out3); - - src0 = __msa_sld_b(src0, src0, slide); - src1 = __msa_sld_b(src1, src1, slide); - src2 = __msa_sld_b(src2, src2, slide); - src3 = __msa_sld_b(src3, src3, slide); - - SRARI_H4_SH(out0, out1, out2, out3, 5); - SAT_SH4_SH(out0, out1, out2, out3, 7); - - PCKEV_B4_SB(out0, out0, out1, out1, out2, out2, out3, out3, - res0, res1, res2, res3); - - res0 = __msa_aver_s_b(res0, src0); - res1 = __msa_aver_s_b(res1, src1); - res2 = __msa_aver_s_b(res2, src2); - res3 = __msa_aver_s_b(res3, src3); - - XORI_B4_128_SB(res0, res1, res2, res3); - AVER_ST8x4_UB(res0, dst0, res1, dst1, res2, dst2, res3, dst3, - dst, dst_stride); - - dst += (4 * dst_stride); - } -} - -static void avc_luma_hz_qrt_and_aver_dst_16x16_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - uint8_t hor_offset) -{ - uint32_t loop_cnt; - v16i8 out0, out1; - v16i8 src0, src1, src2, src3; - v16i8 mask0, mask1, mask2, vshf; - v16u8 dst0, dst1; - v8i16 res0, res1, res2, res3; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v16i8 vec6, vec7, vec8, vec9, vec10, vec11; - v16i8 minus5b = __msa_ldi_b(-5); - v16i8 plus20b = __msa_ldi_b(20); - - LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); - - if (hor_offset) { - vshf = LD_SB(&luma_mask_arr[16 + 96]); - } else { - vshf = LD_SB(&luma_mask_arr[96]); - } - - for (loop_cnt = 8; loop_cnt--;) { - LD_SB2(src, 8, src0, src1); - src += src_stride; - LD_SB2(src, 8, src2, src3); - src += src_stride; - - LD_UB2(dst, dst_stride, dst0, dst1); - - XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec3); - VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec6, vec9); - VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec1, vec4); - VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec7, vec10); - VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec2, vec5); - VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec8, vec11); - HADD_SB4_SH(vec0, vec3, vec6, vec9, res0, res1, res2, res3); - DPADD_SB4_SH(vec1, vec4, vec7, vec10, minus5b, minus5b, minus5b, - minus5b, res0, res1, res2, res3); - DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, - plus20b, res0, res1, res2, res3); - VSHF_B2_SB(src0, src1, src2, src3, vshf, vshf, src0, src2); - SRARI_H4_SH(res0, res1, res2, res3, 5); - SAT_SH4_SH(res0, res1, res2, res3, 7); - PCKEV_B2_SB(res1, res0, res3, res2, out0, out1); - - out0 = __msa_aver_s_b(out0, src0); - out1 = __msa_aver_s_b(out1, src2); - - XORI_B2_128_SB(out0, out1); - AVER_UB2_UB(out0, dst0, out1, dst1, dst0, dst1); - ST_UB2(dst0, dst1, dst, dst_stride); - dst += (2 * dst_stride); - } -} - -static void avc_luma_vt_qrt_and_aver_dst_4x4_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - uint8_t ver_offset) -{ - int16_t filt_const0 = 0xfb01; - int16_t filt_const1 = 0x1414; - int16_t filt_const2 = 0x1fb; - v16u8 dst0, dst1, dst2, dst3; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; - v16i8 src10_r, src32_r, src54_r, src76_r, src21_r, src43_r, src65_r; - v16i8 src87_r, src2110, src4332, src6554, src8776; - v8i16 out10, out32; - v16i8 filt0, filt1, filt2; - v16u8 res; - - filt0 = (v16i8) __msa_fill_h(filt_const0); - filt1 = (v16i8) __msa_fill_h(filt_const1); - filt2 = (v16i8) __msa_fill_h(filt_const2); - - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - src += (5 * src_stride); - - ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, - src10_r, src21_r, src32_r, src43_r); - ILVR_D2_SB(src21_r, src10_r, src43_r, src32_r, src2110, src4332); - XORI_B2_128_SB(src2110, src4332); - LD_SB4(src, src_stride, src5, src6, src7, src8); - ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, - src54_r, src65_r, src76_r, src87_r); - ILVR_D2_SB(src65_r, src54_r, src87_r, src76_r, src6554, src8776); - XORI_B2_128_SB(src6554, src8776); - out10 = DPADD_SH3_SH(src2110, src4332, src6554, filt0, filt1, filt2); - out32 = DPADD_SH3_SH(src4332, src6554, src8776, filt0, filt1, filt2); - SRARI_H2_SH(out10, out32, 5); - SAT_SH2_SH(out10, out32, 7); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - res = PCKEV_XORI128_UB(out10, out32); - - if (ver_offset) { - src32_r = (v16i8) __msa_insve_w((v4i32) src3, 1, (v4i32) src4); - src54_r = (v16i8) __msa_insve_w((v4i32) src5, 1, (v4i32) src6); - } else { - src32_r = (v16i8) __msa_insve_w((v4i32) src2, 1, (v4i32) src3); - src54_r = (v16i8) __msa_insve_w((v4i32) src4, 1, (v4i32) src5); - } - - src32_r = (v16i8) __msa_insve_d((v2i64) src32_r, 1, (v2i64) src54_r); - res = __msa_aver_u_b(res, (v16u8) src32_r); - - ILVR_W2_UB(dst1, dst0, dst3, dst2, dst0, dst1); - - dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0); - dst0 = __msa_aver_u_b(res, dst0); - - ST4x4_UB(dst0, dst0, 0, 1, 2, 3, dst, dst_stride); -} - -static void avc_luma_vt_qrt_and_aver_dst_8x8_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - uint8_t ver_offset) -{ - int32_t loop_cnt; - int16_t filt_const0 = 0xfb01; - int16_t filt_const1 = 0x1414; - int16_t filt_const2 = 0x1fb; - v16u8 dst0, dst1, dst2, dst3; - v16i8 src0, src1, src2, src3, src4, src7, src8, src9, src10; - v16i8 src10_r, src32_r, src76_r, src98_r; - v16i8 src21_r, src43_r, src87_r, src109_r; - v8i16 out0_r, out1_r, out2_r, out3_r; - v16i8 res0, res1; - v16u8 vec0, vec1; - v16i8 filt0, filt1, filt2; - - filt0 = (v16i8) __msa_fill_h(filt_const0); - filt1 = (v16i8) __msa_fill_h(filt_const1); - filt2 = (v16i8) __msa_fill_h(filt_const2); - - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - src += (5 * src_stride); - - XORI_B5_128_SB(src0, src1, src2, src3, src4); - ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, - src10_r, src21_r, src32_r, src43_r); - - for (loop_cnt = 2; loop_cnt--;) { - LD_SB4(src, src_stride, src7, src8, src9, src10); - src += (4 * src_stride); - - XORI_B4_128_SB(src7, src8, src9, src10); - ILVR_B4_SB(src7, src4, src8, src7, src9, src8, src10, src9, - src76_r, src87_r, src98_r, src109_r); - out0_r = DPADD_SH3_SH(src10_r, src32_r, src76_r, filt0, filt1, filt2); - out1_r = DPADD_SH3_SH(src21_r, src43_r, src87_r, filt0, filt1, filt2); - out2_r = DPADD_SH3_SH(src32_r, src76_r, src98_r, filt0, filt1, filt2); - out3_r = DPADD_SH3_SH(src43_r, src87_r, src109_r, filt0, filt1, filt2); - SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 5); - SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); - PCKEV_B2_SB(out1_r, out0_r, out3_r, out2_r, res0, res1); - - if (ver_offset) { - PCKEV_D2_SB(src4, src3, src8, src7, src10_r, src32_r); - } else { - PCKEV_D2_SB(src3, src2, src7, src4, src10_r, src32_r); - } - - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - ILVR_D2_UB(dst1, dst0, dst3, dst2, dst0, dst1); - - vec0 = (v16u8) __msa_aver_s_b(res0, src10_r); - vec1 = (v16u8) __msa_aver_s_b(res1, src32_r); - - XORI_B2_128_UB(vec0, vec1); - AVER_UB2_UB(vec0, dst0, vec1, dst1, vec0, vec1); - ST8x4_UB(vec0, vec1, dst, dst_stride); - dst += (4 * dst_stride); - - src10_r = src76_r; - src32_r = src98_r; - src21_r = src87_r; - src43_r = src109_r; - src2 = src8; - src3 = src9; - src4 = src10; - } -} - -static void avc_luma_vt_qrt_and_aver_dst_16x16_msa(const uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - uint8_t ver_offset) -{ - int32_t loop_cnt; - int16_t filt_const0 = 0xfb01; - int16_t filt_const1 = 0x1414; - int16_t filt_const2 = 0x1fb; - v16u8 dst0, dst1, dst2, dst3; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; - v16i8 src10_r, src32_r, src54_r, src76_r, src21_r, src43_r, src65_r; - v16i8 src87_r, src10_l, src32_l, src54_l, src76_l, src21_l, src43_l; - v16i8 src65_l, src87_l; - v8i16 out0_r, out1_r, out2_r, out3_r, out0_l, out1_l, out2_l, out3_l; - v16i8 out0, out1, out2, out3; - v16i8 filt0, filt1, filt2; - v16u8 res0, res1, res2, res3; - - filt0 = (v16i8) __msa_fill_h(filt_const0); - filt1 = (v16i8) __msa_fill_h(filt_const1); - filt2 = (v16i8) __msa_fill_h(filt_const2); - - LD_SB5(src, src_stride, src0, src1, src2, src3, src4); - src += (5 * src_stride); - - XORI_B5_128_SB(src0, src1, src2, src3, src4); - ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, - src10_r, src21_r, src32_r, src43_r); - ILVL_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, - src10_l, src21_l, src32_l, src43_l); - - for (loop_cnt = 4; loop_cnt--;) { - LD_SB4(src, src_stride, src5, src6, src7, src8); - src += (4 * src_stride); - - XORI_B4_128_SB(src5, src6, src7, src8); - ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, - src54_r, src65_r, src76_r, src87_r); - ILVL_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, - src54_l, src65_l, src76_l, src87_l); - out0_r = DPADD_SH3_SH(src10_r, src32_r, src54_r, filt0, filt1, filt2); - out1_r = DPADD_SH3_SH(src21_r, src43_r, src65_r, filt0, filt1, filt2); - out2_r = DPADD_SH3_SH(src32_r, src54_r, src76_r, filt0, filt1, filt2); - out3_r = DPADD_SH3_SH(src43_r, src65_r, src87_r, filt0, filt1, filt2); - out0_l = DPADD_SH3_SH(src10_l, src32_l, src54_l, filt0, filt1, filt2); - out1_l = DPADD_SH3_SH(src21_l, src43_l, src65_l, filt0, filt1, filt2); - out2_l = DPADD_SH3_SH(src32_l, src54_l, src76_l, filt0, filt1, filt2); - out3_l = DPADD_SH3_SH(src43_l, src65_l, src87_l, filt0, filt1, filt2); - SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 5); - SRARI_H4_SH(out0_l, out1_l, out2_l, out3_l, 5); - SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); - SAT_SH4_SH(out0_l, out1_l, out2_l, out3_l, 7); - PCKEV_B4_SB(out0_l, out0_r, out1_l, out1_r, out2_l, out2_r, out3_l, - out3_r, out0, out1, out2, out3); - LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - - if (ver_offset) { - res0 = (v16u8) __msa_aver_s_b(out0, src3); - res1 = (v16u8) __msa_aver_s_b(out1, src4); - res2 = (v16u8) __msa_aver_s_b(out2, src5); - res3 = (v16u8) __msa_aver_s_b(out3, src6); - } else { - res0 = (v16u8) __msa_aver_s_b(out0, src2); - res1 = (v16u8) __msa_aver_s_b(out1, src3); - res2 = (v16u8) __msa_aver_s_b(out2, src4); - res3 = (v16u8) __msa_aver_s_b(out3, src5); - } - - XORI_B4_128_UB(res0, res1, res2, res3); - AVER_UB4_UB(res0, dst0, res1, dst1, res2, dst2, res3, dst3, - dst0, dst1, dst2, dst3); - ST_UB4(dst0, dst1, dst2, dst3, dst, dst_stride); - dst += (4 * dst_stride); - - src10_r = src54_r; - src32_r = src76_r; - src21_r = src65_r; - src43_r = src87_r; - src10_l = src54_l; - src32_l = src76_l; - src21_l = src65_l; - src43_l = src87_l; - src2 = src6; - src3 = src7; - src4 = src8; - } -} - static void avc_luma_hv_qrt_and_aver_dst_4x4_msa(const uint8_t *src_x, const uint8_t *src_y, uint8_t *dst, @@ -3557,118 +3146,226 @@ void ff_put_h264_qpel4_mc22_msa(uint8_t *dst, const uint8_t *src, void ff_avg_h264_qpel16_mc10_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) -{ - avc_luma_hz_qrt_and_aver_dst_16x16_msa(src - 2, stride, dst, stride, 0); -} - -void ff_avg_h264_qpel16_mc30_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_hz_qrt_and_aver_dst_16x16_msa(src - 2, stride, dst, stride, 1); -} - -void ff_avg_h264_qpel8_mc10_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_hz_qrt_and_aver_dst_8x8_msa(src - 2, stride, dst, stride, 0); -} - -void ff_avg_h264_qpel8_mc30_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_hz_qrt_and_aver_dst_8x8_msa(src - 2, stride, dst, stride, 1); -} - -void ff_avg_h264_qpel4_mc10_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_hz_qrt_and_aver_dst_4x4_msa(src - 2, stride, dst, stride, 0); -} - -void ff_avg_h264_qpel4_mc30_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_hz_qrt_and_aver_dst_4x4_msa(src - 2, stride, dst, stride, 1); -} - -void ff_avg_h264_qpel16_mc20_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) { uint32_t loop_cnt; v16u8 dst0, dst1, dst2, dst3; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, mask0, mask1, mask2; + v16i8 out0, out1, out2, out3, src0, src1, src2, src3, src4, src5, src6; + v16i8 mask0, mask1, mask2, mask3, mask4, mask5, src7, vec11; v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9, vec10; - v16i8 vec11; v8i16 res0, res1, res2, res3, res4, res5, res6, res7; v16i8 minus5b = __msa_ldi_b(-5); v16i8 plus20b = __msa_ldi_b(20); LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + mask3 = mask0 + 8; + mask4 = mask1 + 8; + mask5 = mask2 + 8; src -= 2; for (loop_cnt = 4; loop_cnt--;) { - LD_SB2(src, 8, src0, src1); + LD_SB2(src, 16, src0, src1); src += stride; - LD_SB2(src, 8, src2, src3); + LD_SB2(src, 16, src2, src3); src += stride; - LD_SB2(src, 8, src4, src5); + LD_SB2(src, 16, src4, src5); src += stride; - LD_SB2(src, 8, src6, src7); + LD_SB2(src, 16, src6, src7); src += stride; LD_UB4(dst, stride, dst0, dst1, dst2, dst3); XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); - VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec3); - VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec6, vec9); - VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec1, vec4); - VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec7, vec10); - VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec2, vec5); - VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec8, vec11); + VSHF_B2_SB(src0, src0, src0, src1, mask0, mask3, vec0, vec3); + VSHF_B2_SB(src2, src2, src2, src3, mask0, mask3, vec6, vec9); + VSHF_B2_SB(src0, src0, src0, src1, mask1, mask4, vec1, vec4); + VSHF_B2_SB(src2, src2, src2, src3, mask1, mask4, vec7, vec10); + VSHF_B2_SB(src0, src0, src0, src1, mask2, mask5, vec2, vec5); + VSHF_B2_SB(src2, src2, src2, src3, mask2, mask5, vec8, vec11); HADD_SB4_SH(vec0, vec3, vec6, vec9, res0, res1, res2, res3); DPADD_SB4_SH(vec1, vec4, vec7, vec10, minus5b, minus5b, minus5b, minus5b, res0, res1, res2, res3); DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, plus20b, res0, res1, res2, res3); - VSHF_B2_SB(src4, src4, src5, src5, mask0, mask0, vec0, vec3); - VSHF_B2_SB(src6, src6, src7, src7, mask0, mask0, vec6, vec9); - VSHF_B2_SB(src4, src4, src5, src5, mask1, mask1, vec1, vec4); - VSHF_B2_SB(src6, src6, src7, src7, mask1, mask1, vec7, vec10); - VSHF_B2_SB(src4, src4, src5, src5, mask2, mask2, vec2, vec5); - VSHF_B2_SB(src6, src6, src7, src7, mask2, mask2, vec8, vec11); + VSHF_B2_SB(src4, src4, src4, src5, mask0, mask3, vec0, vec3); + VSHF_B2_SB(src6, src6, src6, src7, mask0, mask3, vec6, vec9); + VSHF_B2_SB(src4, src4, src4, src5, mask1, mask4, vec1, vec4); + VSHF_B2_SB(src6, src6, src6, src7, mask1, mask4, vec7, vec10); + VSHF_B2_SB(src4, src4, src4, src5, mask2, mask5, vec2, vec5); + VSHF_B2_SB(src6, src6, src6, src7, mask2, mask5, vec8, vec11); HADD_SB4_SH(vec0, vec3, vec6, vec9, res4, res5, res6, res7); DPADD_SB4_SH(vec1, vec4, vec7, vec10, minus5b, minus5b, minus5b, minus5b, res4, res5, res6, res7); DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, plus20b, res4, res5, res6, res7); + SLDI_B2_SB(src1, src3, src0, src2, src0, src2, 2); + SLDI_B2_SB(src5, src7, src4, src6, src4, src6, 2); SRARI_H4_SH(res0, res1, res2, res3, 5); SRARI_H4_SH(res4, res5, res6, res7, 5); SAT_SH4_SH(res0, res1, res2, res3, 7); SAT_SH4_SH(res4, res5, res6, res7, 7); - PCKEV_B4_SB(res1, res0, res3, res2, res5, res4, res7, res6, vec0, vec1, - vec2, vec3); - XORI_B4_128_SB(vec0, vec1, vec2, vec3); - AVER_UB2_UB(vec0, dst0, vec1, dst1, dst0, dst1); - AVER_UB2_UB(vec2, dst2, vec3, dst3, dst2, dst3); + PCKEV_B2_SB(res1, res0, res3, res2, out0, out1); + PCKEV_B2_SB(res5, res4, res7, res6, out2, out3); + out0 = __msa_aver_s_b(out0, src0); + out1 = __msa_aver_s_b(out1, src2); + out2 = __msa_aver_s_b(out2, src4); + out3 = __msa_aver_s_b(out3, src6); + XORI_B4_128_SB(out0, out1, out2, out3); + AVER_UB2_UB(out0, dst0, out1, dst1, dst0, dst1); + AVER_UB2_UB(out2, dst2, out3, dst3, dst2, dst3); ST_UB4(dst0, dst1, dst2, dst3, dst, stride); dst += (4 * stride); } } -void ff_avg_h264_qpel8_mc20_msa(uint8_t *dst, const uint8_t *src, +void ff_avg_h264_qpel16_mc30_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint32_t loop_cnt; + v16u8 dst0, dst1, dst2, dst3; + v16i8 out0, out1, out2, out3, src0, src1, src2, src3, src4, src5, src6; + v16i8 mask0, mask1, mask2, mask3, mask4, mask5, src7, vec11; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9, vec10; + v8i16 res0, res1, res2, res3, res4, res5, res6, res7; + v16i8 minus5b = __msa_ldi_b(-5); + v16i8 plus20b = __msa_ldi_b(20); + + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + mask3 = mask0 + 8; + mask4 = mask1 + 8; + mask5 = mask2 + 8; + src -= 2; + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB2(src, 16, src0, src1); + src += stride; + LD_SB2(src, 16, src2, src3); + src += stride; + LD_SB2(src, 16, src4, src5); + src += stride; + LD_SB2(src, 16, src6, src7); + src += stride; + + LD_UB4(dst, stride, dst0, dst1, dst2, dst3); + XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); + VSHF_B2_SB(src0, src0, src0, src1, mask0, mask3, vec0, vec3); + VSHF_B2_SB(src2, src2, src2, src3, mask0, mask3, vec6, vec9); + VSHF_B2_SB(src0, src0, src0, src1, mask1, mask4, vec1, vec4); + VSHF_B2_SB(src2, src2, src2, src3, mask1, mask4, vec7, vec10); + VSHF_B2_SB(src0, src0, src0, src1, mask2, mask5, vec2, vec5); + VSHF_B2_SB(src2, src2, src2, src3, mask2, mask5, vec8, vec11); + HADD_SB4_SH(vec0, vec3, vec6, vec9, res0, res1, res2, res3); + DPADD_SB4_SH(vec1, vec4, vec7, vec10, minus5b, minus5b, minus5b, + minus5b, res0, res1, res2, res3); + DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, + plus20b, res0, res1, res2, res3); + VSHF_B2_SB(src4, src4, src4, src5, mask0, mask3, vec0, vec3); + VSHF_B2_SB(src6, src6, src6, src7, mask0, mask3, vec6, vec9); + VSHF_B2_SB(src4, src4, src4, src5, mask1, mask4, vec1, vec4); + VSHF_B2_SB(src6, src6, src6, src7, mask1, mask4, vec7, vec10); + VSHF_B2_SB(src4, src4, src4, src5, mask2, mask5, vec2, vec5); + VSHF_B2_SB(src6, src6, src6, src7, mask2, mask5, vec8, vec11); + HADD_SB4_SH(vec0, vec3, vec6, vec9, res4, res5, res6, res7); + DPADD_SB4_SH(vec1, vec4, vec7, vec10, minus5b, minus5b, minus5b, + minus5b, res4, res5, res6, res7); + DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, + plus20b, res4, res5, res6, res7); + SLDI_B2_SB(src1, src3, src0, src2, src0, src2, 3); + SLDI_B2_SB(src5, src7, src4, src6, src4, src6, 3); + SRARI_H4_SH(res0, res1, res2, res3, 5); + SRARI_H4_SH(res4, res5, res6, res7, 5); + SAT_SH4_SH(res0, res1, res2, res3, 7); + SAT_SH4_SH(res4, res5, res6, res7, 7); + PCKEV_B2_SB(res1, res0, res3, res2, out0, out1); + PCKEV_B2_SB(res5, res4, res7, res6, out2, out3); + out0 = __msa_aver_s_b(out0, src0); + out1 = __msa_aver_s_b(out1, src2); + out2 = __msa_aver_s_b(out2, src4); + out3 = __msa_aver_s_b(out3, src6); + XORI_B4_128_SB(out0, out1, out2, out3); + AVER_UB2_UB(out0, dst0, out1, dst1, dst0, dst1); + AVER_UB2_UB(out2, dst2, out3, dst3, dst2, dst3); + ST_UB4(dst0, dst1, dst2, dst3, dst, stride); + dst += (4 * stride); + } +} + +void ff_avg_h264_qpel8_mc10_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { uint64_t tp0, tp1, tp2, tp3; - v16u8 out0, out1, out2 = { 0 }, out3 = { 0 }; - v16u8 out4, out5, out6 = { 0 }, out7 = { 0 }; + v16u8 dst0 = { 0 }, dst1 = { 0 }, dst2 = { 0 }, dst3 = { 0 }; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, mask0, mask1, mask2; + v16i8 tmp0, tmp1, tmp2, tmp3, vec11; v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9, vec10; - v16i8 vec11; v8i16 res0, res1, res2, res3, res4, res5, res6, res7; v16i8 minus5b = __msa_ldi_b(-5); v16i8 plus20b = __msa_ldi_b(20); LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + LD_SB8(src - 2, stride, src0, src1, src2, src3, src4, src5, src6, src7); + XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); + HADD_SB4_SH(vec0, vec1, vec2, vec3, res0, res1, res2, res3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec4, vec5); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec6, vec7); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, minus5b, minus5b, minus5b, minus5b, + res0, res1, res2, res3); + VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec8, vec9); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec10, vec11); + DPADD_SB4_SH(vec8, vec9, vec10, vec11, plus20b, plus20b, plus20b, plus20b, + res0, res1, res2, res3); + VSHF_B2_SB(src4, src4, src5, src5, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src6, src6, src7, src7, mask0, mask0, vec2, vec3); + HADD_SB4_SH(vec0, vec1, vec2, vec3, res4, res5, res6, res7); + VSHF_B2_SB(src4, src4, src5, src5, mask1, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src7, src7, mask1, mask1, vec6, vec7); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, minus5b, minus5b, minus5b, minus5b, + res4, res5, res6, res7); + VSHF_B2_SB(src4, src4, src5, src5, mask2, mask2, vec8, vec9); + VSHF_B2_SB(src6, src6, src7, src7, mask2, mask2, vec10, vec11); + DPADD_SB4_SH(vec8, vec9, vec10, vec11, plus20b, plus20b, plus20b, plus20b, + res4, res5, res6, res7); + SLDI_B2_SB(src0, src1, src0, src1, src0, src1, 2); + SLDI_B2_SB(src2, src3, src2, src3, src2, src3, 2); + SLDI_B2_SB(src4, src5, src4, src5, src4, src5, 2); + SLDI_B2_SB(src6, src7, src6, src7, src6, src7, 2); + PCKEV_D2_SB(src1, src0, src3, src2, src0, src1); + PCKEV_D2_SB(src5, src4, src7, src6, src4, src5); + SRARI_H4_SH(res0, res1, res2, res3, 5); + SRARI_H4_SH(res4, res5, res6, res7, 5); + SAT_SH4_SH(res0, res1, res2, res3, 7); + SAT_SH4_SH(res4, res5, res6, res7, 7); + PCKEV_B2_SB(res1, res0, res3, res2, tmp0, tmp1); + PCKEV_B2_SB(res5, res4, res7, res6, tmp2, tmp3); + tmp0 = __msa_aver_s_b(tmp0, src0); + tmp1 = __msa_aver_s_b(tmp1, src1); + tmp2 = __msa_aver_s_b(tmp2, src4); + tmp3 = __msa_aver_s_b(tmp3, src5); + XORI_B4_128_SB(tmp0, tmp1, tmp2, tmp3); + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + LD4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst2); + INSERT_D2_UB(tp2, tp3, dst3); + AVER_UB2_UB(tmp0, dst0, tmp1, dst1, dst0, dst1); + AVER_UB2_UB(tmp2, dst2, tmp3, dst3, dst2, dst3); + ST8x8_UB(dst0, dst1, dst2, dst3, dst, stride); +} + +void ff_avg_h264_qpel8_mc30_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint64_t tp0, tp1, tp2, tp3; + v16u8 dst0 = { 0 }, dst1 = { 0 }, dst2 = { 0 }, dst3 = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, mask0, mask1, mask2; + v16i8 tmp0, tmp1, tmp2, tmp3, vec11; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9, vec10; + v8i16 res0, res1, res2, res3, res4, res5, res6, res7; + v16i8 minus5b = __msa_ldi_b(-5); + v16i8 plus20b = __msa_ldi_b(20); + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); LD_SB8(src - 2, stride, src0, src1, src2, src3, src4, src5, src6, src7); XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); @@ -3693,33 +3390,42 @@ void ff_avg_h264_qpel8_mc20_msa(uint8_t *dst, const uint8_t *src, VSHF_B2_SB(src6, src6, src7, src7, mask2, mask2, vec10, vec11); DPADD_SB4_SH(vec8, vec9, vec10, vec11, plus20b, plus20b, plus20b, plus20b, res4, res5, res6, res7); + SLDI_B2_SB(src0, src1, src0, src1, src0, src1, 3); + SLDI_B2_SB(src2, src3, src2, src3, src2, src3, 3); + SLDI_B2_SB(src4, src5, src4, src5, src4, src5, 3); + SLDI_B2_SB(src6, src7, src6, src7, src6, src7, 3); + PCKEV_D2_SB(src1, src0, src3, src2, src0, src1); + PCKEV_D2_SB(src5, src4, src7, src6, src4, src5); SRARI_H4_SH(res0, res1, res2, res3, 5); SRARI_H4_SH(res4, res5, res6, res7, 5); SAT_SH4_SH(res0, res1, res2, res3, 7); SAT_SH4_SH(res4, res5, res6, res7, 7); - out0 = PCKEV_XORI128_UB(res0, res1); - out1 = PCKEV_XORI128_UB(res2, res3); - out4 = PCKEV_XORI128_UB(res4, res5); - out5 = PCKEV_XORI128_UB(res6, res7); + PCKEV_B2_SB(res1, res0, res3, res2, tmp0, tmp1); + PCKEV_B2_SB(res5, res4, res7, res6, tmp2, tmp3); + tmp0 = __msa_aver_s_b(tmp0, src0); + tmp1 = __msa_aver_s_b(tmp1, src1); + tmp2 = __msa_aver_s_b(tmp2, src4); + tmp3 = __msa_aver_s_b(tmp3, src5); + XORI_B4_128_SB(tmp0, tmp1, tmp2, tmp3); LD4(dst, stride, tp0, tp1, tp2, tp3); - INSERT_D2_UB(tp0, tp1, out2); - INSERT_D2_UB(tp2, tp3, out3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); LD4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); - INSERT_D2_UB(tp0, tp1, out6); - INSERT_D2_UB(tp2, tp3, out7); - AVER_UB2_UB(out0, out2, out1, out3, out0, out1); - AVER_UB2_UB(out4, out6, out5, out7, out4, out5); - ST8x8_UB(out0, out1, out4, out5, dst, stride); + INSERT_D2_UB(tp0, tp1, dst2); + INSERT_D2_UB(tp2, tp3, dst3); + AVER_UB2_UB(tmp0, dst0, tmp1, dst1, dst0, dst1); + AVER_UB2_UB(tmp2, dst2, tmp3, dst3, dst2, dst3); + ST8x8_UB(dst0, dst1, dst2, dst3, dst, stride); } -void ff_avg_h264_qpel4_mc20_msa(uint8_t *dst, const uint8_t *src, +void ff_avg_h264_qpel4_mc10_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { uint32_t tp0, tp1, tp2, tp3; - v16u8 res, dst0 = { 0 }; - v16i8 src0, src1, src2, src3, vec0, vec1, vec2, vec3, vec4, vec5; + v16u8 dst0 = { 0 }; + v16i8 src0, src1, src2, src3, res, vec0, vec1, vec2, vec3, vec4, vec5; v16i8 mask0, mask1, mask2; - v8i16 res0, res1; + v8i16 out0, out1; v16i8 minus5b = __msa_ldi_b(-5); v16i8 plus20b = __msa_ldi_b(20); @@ -3727,60 +3433,587 @@ void ff_avg_h264_qpel4_mc20_msa(uint8_t *dst, const uint8_t *src, LD_SB4(src - 2, stride, src0, src1, src2, src3); XORI_B4_128_SB(src0, src1, src2, src3); VSHF_B2_SB(src0, src1, src2, src3, mask0, mask0, vec0, vec1); - HADD_SB2_SH(vec0, vec1, res0, res1); + HADD_SB2_SH(vec0, vec1, out0, out1); VSHF_B2_SB(src0, src1, src2, src3, mask1, mask1, vec2, vec3); - DPADD_SB2_SH(vec2, vec3, minus5b, minus5b, res0, res1); + DPADD_SB2_SH(vec2, vec3, minus5b, minus5b, out0, out1); VSHF_B2_SB(src0, src1, src2, src3, mask2, mask2, vec4, vec5); - DPADD_SB2_SH(vec4, vec5, plus20b, plus20b, res0, res1); - SRARI_H2_SH(res0, res1, 5); - SAT_SH2_SH(res0, res1, 7); - res = PCKEV_XORI128_UB(res0, res1); + DPADD_SB2_SH(vec4, vec5, plus20b, plus20b, out0, out1); + SRARI_H2_SH(out0, out1, 5); + SAT_SH2_SH(out0, out1, 7); + res = __msa_pckev_b((v16i8) out1, (v16i8) out0); + SLDI_B2_SB(src0, src1, src0, src1, src0, src1, 2); + SLDI_B2_SB(src2, src3, src2, src3, src2, src3, 2); + src0 = (v16i8) __msa_insve_w((v4i32) src0, 1, (v4i32) src1); + src1 = (v16i8) __msa_insve_w((v4i32) src2, 1, (v4i32) src3); + src0 = (v16i8) __msa_insve_d((v2i64) src0, 1, (v2i64) src1); + res = __msa_aver_s_b(res, src0); + res = (v16i8) __msa_xori_b((v16u8) res, 128); LW4(dst, stride, tp0, tp1, tp2, tp3); INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); - res = __msa_aver_u_b(res, dst0); - ST4x4_UB(res, res, 0, 1, 2, 3, dst, stride); + dst0 = __msa_aver_u_b((v16u8) res, dst0); + ST4x4_UB(dst0, dst0, 0, 1, 2, 3, dst, stride); } -void ff_avg_h264_qpel16_mc01_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) +void ff_avg_h264_qpel4_mc30_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) { - avc_luma_vt_qrt_and_aver_dst_16x16_msa(src - (stride * 2), - stride, dst, stride, 0); + uint32_t tp0, tp1, tp2, tp3; + v16u8 dst0 = { 0 }; + v16i8 src0, src1, src2, src3, res, vec0, vec1, vec2, vec3, vec4, vec5; + v16i8 mask0, mask1, mask2; + v8i16 out0, out1; + v16i8 minus5b = __msa_ldi_b(-5); + v16i8 plus20b = __msa_ldi_b(20); + + LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); + LD_SB4(src - 2, stride, src0, src1, src2, src3); + XORI_B4_128_SB(src0, src1, src2, src3); + VSHF_B2_SB(src0, src1, src2, src3, mask0, mask0, vec0, vec1); + HADD_SB2_SH(vec0, vec1, out0, out1); + VSHF_B2_SB(src0, src1, src2, src3, mask1, mask1, vec2, vec3); + DPADD_SB2_SH(vec2, vec3, minus5b, minus5b, out0, out1); + VSHF_B2_SB(src0, src1, src2, src3, mask2, mask2, vec4, vec5); + DPADD_SB2_SH(vec4, vec5, plus20b, plus20b, out0, out1); + SRARI_H2_SH(out0, out1, 5); + SAT_SH2_SH(out0, out1, 7); + res = __msa_pckev_b((v16i8) out1, (v16i8) out0); + SLDI_B2_SB(src0, src1, src0, src1, src0, src1, 3); + SLDI_B2_SB(src2, src3, src2, src3, src2, src3, 3); + src0 = (v16i8) __msa_insve_w((v4i32) src0, 1, (v4i32) src1); + src1 = (v16i8) __msa_insve_w((v4i32) src2, 1, (v4i32) src3); + src0 = (v16i8) __msa_insve_d((v2i64) src0, 1, (v2i64) src1); + res = __msa_aver_s_b(res, src0); + res = (v16i8) __msa_xori_b((v16u8) res, 128); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); + dst0 = __msa_aver_u_b((v16u8) res, dst0); + ST4x4_UB(dst0, dst0, 0, 1, 2, 3, dst, stride); } -void ff_avg_h264_qpel16_mc03_msa(uint8_t *dst, const uint8_t *src, +void ff_avg_h264_qpel16_mc20_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_vt_qrt_and_aver_dst_16x16_msa(src - (stride * 2), - stride, dst, stride, 1); -} + uint32_t loop_cnt; + v16u8 dst0, dst1, dst2, dst3; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, mask0, mask1, mask2; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9, vec10; + v16i8 vec11; + v8i16 res0, res1, res2, res3, res4, res5, res6, res7; + v16i8 minus5b = __msa_ldi_b(-5); + v16i8 plus20b = __msa_ldi_b(20); -void ff_avg_h264_qpel8_mc01_msa(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - avc_luma_vt_qrt_and_aver_dst_8x8_msa(src - (stride * 2), - stride, dst, stride, 0); -} + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + src -= 2; + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB2(src, 8, src0, src1); + src += stride; + LD_SB2(src, 8, src2, src3); + src += stride; + LD_SB2(src, 8, src4, src5); + src += stride; + LD_SB2(src, 8, src6, src7); + src += stride; + + LD_UB4(dst, stride, dst0, dst1, dst2, dst3); + XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec3); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec6, vec9); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec1, vec4); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec7, vec10); + VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec2, vec5); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec8, vec11); + HADD_SB4_SH(vec0, vec3, vec6, vec9, res0, res1, res2, res3); + DPADD_SB4_SH(vec1, vec4, vec7, vec10, minus5b, minus5b, minus5b, + minus5b, res0, res1, res2, res3); + DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, + plus20b, res0, res1, res2, res3); + VSHF_B2_SB(src4, src4, src5, src5, mask0, mask0, vec0, vec3); + VSHF_B2_SB(src6, src6, src7, src7, mask0, mask0, vec6, vec9); + VSHF_B2_SB(src4, src4, src5, src5, mask1, mask1, vec1, vec4); + VSHF_B2_SB(src6, src6, src7, src7, mask1, mask1, vec7, vec10); + VSHF_B2_SB(src4, src4, src5, src5, mask2, mask2, vec2, vec5); + VSHF_B2_SB(src6, src6, src7, src7, mask2, mask2, vec8, vec11); + HADD_SB4_SH(vec0, vec3, vec6, vec9, res4, res5, res6, res7); + DPADD_SB4_SH(vec1, vec4, vec7, vec10, minus5b, minus5b, minus5b, + minus5b, res4, res5, res6, res7); + DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, + plus20b, res4, res5, res6, res7); + SRARI_H4_SH(res0, res1, res2, res3, 5); + SRARI_H4_SH(res4, res5, res6, res7, 5); + SAT_SH4_SH(res0, res1, res2, res3, 7); + SAT_SH4_SH(res4, res5, res6, res7, 7); + PCKEV_B4_SB(res1, res0, res3, res2, res5, res4, res7, res6, vec0, vec1, + vec2, vec3); + XORI_B4_128_SB(vec0, vec1, vec2, vec3); + AVER_UB2_UB(vec0, dst0, vec1, dst1, dst0, dst1); + AVER_UB2_UB(vec2, dst2, vec3, dst3, dst2, dst3); + ST_UB4(dst0, dst1, dst2, dst3, dst, stride); + dst += (4 * stride); + } +} + +void ff_avg_h264_qpel8_mc20_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint64_t tp0, tp1, tp2, tp3; + v16u8 out0, out1, out2 = { 0 }, out3 = { 0 }; + v16u8 out4, out5, out6 = { 0 }, out7 = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, mask0, mask1, mask2; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9, vec10; + v16i8 vec11; + v8i16 res0, res1, res2, res3, res4, res5, res6, res7; + v16i8 minus5b = __msa_ldi_b(-5); + v16i8 plus20b = __msa_ldi_b(20); + + LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2); + + LD_SB8(src - 2, stride, src0, src1, src2, src3, src4, src5, src6, src7); + XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); + HADD_SB4_SH(vec0, vec1, vec2, vec3, res0, res1, res2, res3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec4, vec5); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec6, vec7); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, minus5b, minus5b, minus5b, minus5b, + res0, res1, res2, res3); + VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec8, vec9); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec10, vec11); + DPADD_SB4_SH(vec8, vec9, vec10, vec11, plus20b, plus20b, plus20b, plus20b, + res0, res1, res2, res3); + VSHF_B2_SB(src4, src4, src5, src5, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src6, src6, src7, src7, mask0, mask0, vec2, vec3); + HADD_SB4_SH(vec0, vec1, vec2, vec3, res4, res5, res6, res7); + VSHF_B2_SB(src4, src4, src5, src5, mask1, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src7, src7, mask1, mask1, vec6, vec7); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, minus5b, minus5b, minus5b, minus5b, + res4, res5, res6, res7); + VSHF_B2_SB(src4, src4, src5, src5, mask2, mask2, vec8, vec9); + VSHF_B2_SB(src6, src6, src7, src7, mask2, mask2, vec10, vec11); + DPADD_SB4_SH(vec8, vec9, vec10, vec11, plus20b, plus20b, plus20b, plus20b, + res4, res5, res6, res7); + SRARI_H4_SH(res0, res1, res2, res3, 5); + SRARI_H4_SH(res4, res5, res6, res7, 5); + SAT_SH4_SH(res0, res1, res2, res3, 7); + SAT_SH4_SH(res4, res5, res6, res7, 7); + out0 = PCKEV_XORI128_UB(res0, res1); + out1 = PCKEV_XORI128_UB(res2, res3); + out4 = PCKEV_XORI128_UB(res4, res5); + out5 = PCKEV_XORI128_UB(res6, res7); + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, out2); + INSERT_D2_UB(tp2, tp3, out3); + LD4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, out6); + INSERT_D2_UB(tp2, tp3, out7); + AVER_UB2_UB(out0, out2, out1, out3, out0, out1); + AVER_UB2_UB(out4, out6, out5, out7, out4, out5); + ST8x8_UB(out0, out1, out4, out5, dst, stride); +} + +void ff_avg_h264_qpel4_mc20_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint32_t tp0, tp1, tp2, tp3; + v16u8 res, dst0 = { 0 }; + v16i8 src0, src1, src2, src3, vec0, vec1, vec2, vec3, vec4, vec5; + v16i8 mask0, mask1, mask2; + v8i16 res0, res1; + v16i8 minus5b = __msa_ldi_b(-5); + v16i8 plus20b = __msa_ldi_b(20); + + LD_SB3(&luma_mask_arr[48], 16, mask0, mask1, mask2); + LD_SB4(src - 2, stride, src0, src1, src2, src3); + XORI_B4_128_SB(src0, src1, src2, src3); + VSHF_B2_SB(src0, src1, src2, src3, mask0, mask0, vec0, vec1); + HADD_SB2_SH(vec0, vec1, res0, res1); + VSHF_B2_SB(src0, src1, src2, src3, mask1, mask1, vec2, vec3); + DPADD_SB2_SH(vec2, vec3, minus5b, minus5b, res0, res1); + VSHF_B2_SB(src0, src1, src2, src3, mask2, mask2, vec4, vec5); + DPADD_SB2_SH(vec4, vec5, plus20b, plus20b, res0, res1); + SRARI_H2_SH(res0, res1, 5); + SAT_SH2_SH(res0, res1, 7); + res = PCKEV_XORI128_UB(res0, res1); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); + res = __msa_aver_u_b(res, dst0); + ST4x4_UB(res, res, 0, 1, 2, 3, dst, stride); +} + +void ff_avg_h264_qpel16_mc01_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + int32_t loop_cnt; + int16_t filt_const0 = 0xfb01; + int16_t filt_const1 = 0x1414; + int16_t filt_const2 = 0x1fb; + v16u8 res0, res1, res2, res3, dst0, dst1, dst2, dst3; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 src10_r, src32_r, src54_r, src76_r, src21_r, src43_r, src65_r; + v16i8 src87_r, src10_l, src32_l, src54_l, src76_l, src21_l, src43_l; + v16i8 src65_l, src87_l, filt0, filt1, filt2; + v8i16 out0_r, out1_r, out2_r, out3_r, out0_l, out1_l, out2_l, out3_l; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + + src -= (stride * 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + + XORI_B5_128_SB(src0, src1, src2, src3, src4); + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + ILVL_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_l, src21_l, + src32_l, src43_l); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src, stride, src5, src6, src7, src8); + src += (4 * stride); + + XORI_B4_128_SB(src5, src6, src7, src8); + ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_r, + src65_r, src76_r, src87_r); + ILVL_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_l, + src65_l, src76_l, src87_l); + out0_r = AVC_DOT_SH3_SH(src10_r, src32_r, src54_r, filt0, filt1, filt2); + out1_r = AVC_DOT_SH3_SH(src21_r, src43_r, src65_r, filt0, filt1, filt2); + out2_r = AVC_DOT_SH3_SH(src32_r, src54_r, src76_r, filt0, filt1, filt2); + out3_r = AVC_DOT_SH3_SH(src43_r, src65_r, src87_r, filt0, filt1, filt2); + out0_l = AVC_DOT_SH3_SH(src10_l, src32_l, src54_l, filt0, filt1, filt2); + out1_l = AVC_DOT_SH3_SH(src21_l, src43_l, src65_l, filt0, filt1, filt2); + out2_l = AVC_DOT_SH3_SH(src32_l, src54_l, src76_l, filt0, filt1, filt2); + out3_l = AVC_DOT_SH3_SH(src43_l, src65_l, src87_l, filt0, filt1, filt2); + SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 5); + SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); + SRARI_H4_SH(out0_l, out1_l, out2_l, out3_l, 5); + SAT_SH4_SH(out0_l, out1_l, out2_l, out3_l, 7); + PCKEV_B4_UB(out0_l, out0_r, out1_l, out1_r, out2_l, out2_r, out3_l, + out3_r, res0, res1, res2, res3); + res0 = (v16u8) __msa_aver_s_b((v16i8) res0, src2); + res1 = (v16u8) __msa_aver_s_b((v16i8) res1, src3); + res2 = (v16u8) __msa_aver_s_b((v16i8) res2, src4); + res3 = (v16u8) __msa_aver_s_b((v16i8) res3, src5); + LD_UB4(dst, stride, dst0, dst1, dst2, dst3); + XORI_B4_128_UB(res0, res1, res2, res3); + AVER_UB2_UB(res0, dst0, res1, dst1, dst0, dst1); + AVER_UB2_UB(res2, dst2, res3, dst3, dst2, dst3); + ST_UB4(dst0, dst1, dst2, dst3, dst, stride); + dst += (4 * stride); + + src10_r = src54_r; + src32_r = src76_r; + src21_r = src65_r; + src43_r = src87_r; + src10_l = src54_l; + src32_l = src76_l; + src21_l = src65_l; + src43_l = src87_l; + src2 = src6; + src3 = src7; + src4 = src8; + } +} + +void ff_avg_h264_qpel16_mc03_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + int32_t loop_cnt; + int16_t filt_const0 = 0xfb01; + int16_t filt_const1 = 0x1414; + int16_t filt_const2 = 0x1fb; + v16u8 res0, res1, res2, res3, dst0, dst1, dst2, dst3; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 src10_r, src32_r, src54_r, src76_r, src21_r, src43_r, src65_r; + v16i8 src87_r, src10_l, src32_l, src54_l, src76_l, src21_l, src43_l; + v16i8 src65_l, src87_l, filt0, filt1, filt2; + v8i16 out0_r, out1_r, out2_r, out3_r, out0_l, out1_l, out2_l, out3_l; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + + src -= (stride * 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + + XORI_B5_128_SB(src0, src1, src2, src3, src4); + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + ILVL_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_l, src21_l, + src32_l, src43_l); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src, stride, src5, src6, src7, src8); + src += (4 * stride); + + XORI_B4_128_SB(src5, src6, src7, src8); + ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_r, + src65_r, src76_r, src87_r); + ILVL_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_l, + src65_l, src76_l, src87_l); + out0_r = AVC_DOT_SH3_SH(src10_r, src32_r, src54_r, filt0, filt1, filt2); + out1_r = AVC_DOT_SH3_SH(src21_r, src43_r, src65_r, filt0, filt1, filt2); + out2_r = AVC_DOT_SH3_SH(src32_r, src54_r, src76_r, filt0, filt1, filt2); + out3_r = AVC_DOT_SH3_SH(src43_r, src65_r, src87_r, filt0, filt1, filt2); + out0_l = AVC_DOT_SH3_SH(src10_l, src32_l, src54_l, filt0, filt1, filt2); + out1_l = AVC_DOT_SH3_SH(src21_l, src43_l, src65_l, filt0, filt1, filt2); + out2_l = AVC_DOT_SH3_SH(src32_l, src54_l, src76_l, filt0, filt1, filt2); + out3_l = AVC_DOT_SH3_SH(src43_l, src65_l, src87_l, filt0, filt1, filt2); + SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 5); + SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); + SRARI_H4_SH(out0_l, out1_l, out2_l, out3_l, 5); + SAT_SH4_SH(out0_l, out1_l, out2_l, out3_l, 7); + PCKEV_B4_UB(out0_l, out0_r, out1_l, out1_r, out2_l, out2_r, out3_l, + out3_r, res0, res1, res2, res3); + res0 = (v16u8) __msa_aver_s_b((v16i8) res0, src3); + res1 = (v16u8) __msa_aver_s_b((v16i8) res1, src4); + res2 = (v16u8) __msa_aver_s_b((v16i8) res2, src5); + res3 = (v16u8) __msa_aver_s_b((v16i8) res3, src6); + LD_UB4(dst, stride, dst0, dst1, dst2, dst3); + XORI_B4_128_UB(res0, res1, res2, res3); + AVER_UB2_UB(res0, dst0, res1, dst1, dst0, dst1); + AVER_UB2_UB(res2, dst2, res3, dst3, dst2, dst3); + ST_UB4(dst0, dst1, dst2, dst3, dst, stride); + dst += (4 * stride); + + src10_r = src54_r; + src32_r = src76_r; + src21_r = src65_r; + src43_r = src87_r; + src10_l = src54_l; + src32_l = src76_l; + src21_l = src65_l; + src43_l = src87_l; + src3 = src7; + src4 = src8; + } +} + +void ff_avg_h264_qpel8_mc01_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint64_t tp0, tp1, tp2, tp3; + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + v16u8 dst0 = { 0 }, dst1 = { 0 }, dst2 = { 0 }, dst3 = { 0 }; + v16i8 src0, src1, src2, src3, src4, src7, src8, src9, src10, src11, src12; + v16i8 src13, src14, tmp0, tmp1, tmp2, tmp3, src109_r; + v16i8 src10_r, src32_r, src76_r, src98_r, src21_r, src43_r, src87_r; + v16i8 filt0, filt1, filt2, out0, out1, out2, out3; + v8i16 out0_r, out1_r, out2_r, out3_r, out4_r, out5_r, out6_r, out7_r; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + + src -= (stride * 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + + XORI_B5_128_SB(src0, src1, src2, src3, src4); + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + LD_SB8(src, stride, src7, src8, src9, src10, src11, src12, src13, src14); + XORI_B8_128_SB(src7, src8, src9, src10, src11, src12, src13, src14); + ILVR_B4_SB(src7, src4, src8, src7, src9, src8, src10, src9, src76_r, + src87_r, src98_r, src109_r); + out0_r = AVC_DOT_SH3_SH(src10_r, src32_r, src76_r, filt0, filt1, filt2); + out1_r = AVC_DOT_SH3_SH(src21_r, src43_r, src87_r, filt0, filt1, filt2); + out2_r = AVC_DOT_SH3_SH(src32_r, src76_r, src98_r, filt0, filt1, filt2); + out3_r = AVC_DOT_SH3_SH(src43_r, src87_r, src109_r, filt0, filt1, filt2); + PCKEV_D2_SB(src3, src2, src7, src4, tmp0, tmp1); + ILVR_B4_SB(src11, src10, src12, src11, src13, src12, src14, src13, src10_r, + src21_r, src32_r, src43_r); + out4_r = AVC_DOT_SH3_SH(src76_r, src98_r, src10_r, filt0, filt1, filt2); + out5_r = AVC_DOT_SH3_SH(src87_r, src109_r, src21_r, filt0, filt1, filt2); + out6_r = AVC_DOT_SH3_SH(src98_r, src10_r, src32_r, filt0, filt1, filt2); + out7_r = AVC_DOT_SH3_SH(src109_r, src21_r, src43_r, filt0, filt1, filt2); + PCKEV_D2_SB(src9, src8, src11, src10, tmp2, tmp3); + SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 5); + SRARI_H4_SH(out4_r, out5_r, out6_r, out7_r, 5); + SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); + SAT_SH4_SH(out4_r, out5_r, out6_r, out7_r, 7); + + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + LD4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst2); + INSERT_D2_UB(tp2, tp3, dst3); + + PCKEV_B2_SB(out1_r, out0_r, out3_r, out2_r, out0, out1); + PCKEV_B2_SB(out5_r, out4_r, out7_r, out6_r, out2, out3); + out0 = __msa_aver_s_b(out0, tmp0); + out1 = __msa_aver_s_b(out1, tmp1); + out2 = __msa_aver_s_b(out2, tmp2); + out3 = __msa_aver_s_b(out3, tmp3); + XORI_B4_128_SB(out0, out1, out2, out3); + AVER_UB4_UB(out0, dst0, out1, dst1, out2, dst2, out3, dst3, dst0, dst1, + dst2, dst3); + ST8x8_UB(dst0, dst1, dst2, dst3, dst, stride); +} void ff_avg_h264_qpel8_mc03_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_vt_qrt_and_aver_dst_8x8_msa(src - (stride * 2), - stride, dst, stride, 1); + uint64_t tp0, tp1, tp2, tp3; + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + v16u8 dst0 = { 0 }, dst1 = { 0 }, dst2 = { 0 }, dst3 = { 0 }; + v16i8 src0, src1, src2, src3, src4, src7, src8, src9, src10, src11, src12; + v16i8 src13, src14, tmp0, tmp1, tmp2, tmp3, src109_r; + v16i8 src10_r, src32_r, src76_r, src98_r, src21_r, src43_r, src87_r; + v16i8 filt0, filt1, filt2, out0, out1, out2, out3; + v8i16 out0_r, out1_r, out2_r, out3_r, out4_r, out5_r, out6_r, out7_r; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + + src -= (stride * 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + + XORI_B5_128_SB(src0, src1, src2, src3, src4); + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + LD_SB8(src, stride, src7, src8, src9, src10, src11, src12, src13, src14); + XORI_B8_128_SB(src7, src8, src9, src10, src11, src12, src13, src14); + ILVR_B4_SB(src7, src4, src8, src7, src9, src8, src10, src9, src76_r, + src87_r, src98_r, src109_r); + out0_r = AVC_DOT_SH3_SH(src10_r, src32_r, src76_r, filt0, filt1, filt2); + out1_r = AVC_DOT_SH3_SH(src21_r, src43_r, src87_r, filt0, filt1, filt2); + out2_r = AVC_DOT_SH3_SH(src32_r, src76_r, src98_r, filt0, filt1, filt2); + out3_r = AVC_DOT_SH3_SH(src43_r, src87_r, src109_r, filt0, filt1, filt2); + PCKEV_D2_SB(src4, src3, src8, src7, tmp0, tmp1); + ILVR_B4_SB(src11, src10, src12, src11, src13, src12, src14, src13, src10_r, + src21_r, src32_r, src43_r); + out4_r = AVC_DOT_SH3_SH(src76_r, src98_r, src10_r, filt0, filt1, filt2); + out5_r = AVC_DOT_SH3_SH(src87_r, src109_r, src21_r, filt0, filt1, filt2); + out6_r = AVC_DOT_SH3_SH(src98_r, src10_r, src32_r, filt0, filt1, filt2); + out7_r = AVC_DOT_SH3_SH(src109_r, src21_r, src43_r, filt0, filt1, filt2); + PCKEV_D2_SB(src10, src9, src12, src11, tmp2, tmp3); + SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 5); + SRARI_H4_SH(out4_r, out5_r, out6_r, out7_r, 5); + SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); + SAT_SH4_SH(out4_r, out5_r, out6_r, out7_r, 7); + + LD4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst0); + INSERT_D2_UB(tp2, tp3, dst1); + LD4(dst + 4 * stride, stride, tp0, tp1, tp2, tp3); + INSERT_D2_UB(tp0, tp1, dst2); + INSERT_D2_UB(tp2, tp3, dst3); + + PCKEV_B2_SB(out1_r, out0_r, out3_r, out2_r, out0, out1); + PCKEV_B2_SB(out5_r, out4_r, out7_r, out6_r, out2, out3); + out0 = __msa_aver_s_b(out0, tmp0); + out1 = __msa_aver_s_b(out1, tmp1); + out2 = __msa_aver_s_b(out2, tmp2); + out3 = __msa_aver_s_b(out3, tmp3); + XORI_B4_128_SB(out0, out1, out2, out3); + AVER_UB4_UB(out0, dst0, out1, dst1, out2, dst2, out3, dst3, dst0, dst1, + dst2, dst3); + ST8x8_UB(dst0, dst1, dst2, dst3, dst, stride); } void ff_avg_h264_qpel4_mc01_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_vt_qrt_and_aver_dst_4x4_msa(src - (stride * 2), - stride, dst, stride, 0); + uint32_t tp0, tp1, tp2, tp3; + int16_t filt_const0 = 0xfb01; + int16_t filt_const1 = 0x1414; + int16_t filt_const2 = 0x1fb; + v16u8 res, dst0 = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 src10_r, src32_r, src54_r, src76_r, src21_r, src43_r, src65_r; + v16i8 src87_r, src2110, src4332, src6554, src8776, filt0, filt1, filt2; + v8i16 out10, out32; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + + src -= (stride * 2); + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + ILVR_D2_SB(src21_r, src10_r, src43_r, src32_r, src2110, src4332); + XORI_B2_128_SB(src2110, src4332); + LD_SB4(src, stride, src5, src6, src7, src8); + ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_r, src65_r, + src76_r, src87_r); + ILVR_D2_SB(src65_r, src54_r, src87_r, src76_r, src6554, src8776); + XORI_B2_128_SB(src6554, src8776); + src32_r = (v16i8) __msa_insve_w((v4i32) src2, 1, (v4i32) src3); + src54_r = (v16i8) __msa_insve_w((v4i32) src4, 1, (v4i32) src5); + src32_r = (v16i8) __msa_insve_d((v2i64) src32_r, 1, (v2i64) src54_r); + out10 = AVC_DOT_SH3_SH(src2110, src4332, src6554, filt0, filt1, filt2); + out32 = AVC_DOT_SH3_SH(src4332, src6554, src8776, filt0, filt1, filt2); + SRARI_H2_SH(out10, out32, 5); + SAT_SH2_SH(out10, out32, 7); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); + res = PCKEV_XORI128_UB(out10, out32); + res = __msa_aver_u_b(res, (v16u8) src32_r); + dst0 = __msa_aver_u_b(res, dst0); + ST4x4_UB(dst0, dst0, 0, 1, 2, 3, dst, stride); } void ff_avg_h264_qpel4_mc03_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { - avc_luma_vt_qrt_and_aver_dst_4x4_msa(src - (stride * 2), - stride, dst, stride, 1); + uint32_t tp0, tp1, tp2, tp3; + int16_t filt_const0 = 0xfb01; + int16_t filt_const1 = 0x1414; + int16_t filt_const2 = 0x1fb; + v16u8 res, dst0 = { 0 }; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 src10_r, src32_r, src54_r, src76_r, src21_r, src43_r, src65_r; + v16i8 src87_r, src2110, src4332, src6554, src8776, filt0, filt1, filt2; + v8i16 out10, out32; + + filt0 = (v16i8) __msa_fill_h(filt_const0); + filt1 = (v16i8) __msa_fill_h(filt_const1); + filt2 = (v16i8) __msa_fill_h(filt_const2); + + src -= (stride * 2); + + LD_SB5(src, stride, src0, src1, src2, src3, src4); + src += (5 * stride); + + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + ILVR_D2_SB(src21_r, src10_r, src43_r, src32_r, src2110, src4332); + XORI_B2_128_SB(src2110, src4332); + LD_SB4(src, stride, src5, src6, src7, src8); + ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_r, src65_r, + src76_r, src87_r); + ILVR_D2_SB(src65_r, src54_r, src87_r, src76_r, src6554, src8776); + XORI_B2_128_SB(src6554, src8776); + out10 = AVC_DOT_SH3_SH(src2110, src4332, src6554, filt0, filt1, filt2); + out32 = AVC_DOT_SH3_SH(src4332, src6554, src8776, filt0, filt1, filt2); + SRARI_H2_SH(out10, out32, 5); + SAT_SH2_SH(out10, out32, 7); + LW4(dst, stride, tp0, tp1, tp2, tp3); + INSERT_W4_UB(tp0, tp1, tp2, tp3, dst0); + res = PCKEV_XORI128_UB(out10, out32); + src32_r = (v16i8) __msa_insve_w((v4i32) src3, 1, (v4i32) src4); + src54_r = (v16i8) __msa_insve_w((v4i32) src5, 1, (v4i32) src6); + src32_r = (v16i8) __msa_insve_d((v2i64) src32_r, 1, (v2i64) src54_r); + res = __msa_aver_u_b(res, (v16u8) src32_r); + dst0 = __msa_aver_u_b(res, dst0); + ST4x4_UB(dst0, dst0, 0, 1, 2, 3, dst, stride); } void ff_avg_h264_qpel16_mc11_msa(uint8_t *dst, const uint8_t *src, From 991eca0f8729043724ae4574be0eb4c20bdba915 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Mon, 6 Nov 2017 11:15:04 +0530 Subject: [PATCH 0783/2557] avcodec/mips: Improve hevc bi 4 tap hv mc msa functions Use global mask buffer for appropriate mask load. Use immediate unsigned saturation for clip to max saving one vector register. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_bi_msa.c | 1140 ++++++++++++++++++------------ 1 file changed, 685 insertions(+), 455 deletions(-) diff --git a/libavcodec/mips/hevc_mc_bi_msa.c b/libavcodec/mips/hevc_mc_bi_msa.c index e9c9184d2796f..b555517b27d7e 100644 --- a/libavcodec/mips/hevc_mc_bi_msa.c +++ b/libavcodec/mips/hevc_mc_bi_msa.c @@ -3772,20 +3772,20 @@ static void hevc_hv_bi_4t_4x2_msa(uint8_t *src0_ptr, uint8_t *dst, int32_t dst_stride, const int8_t *filter_x, - const int8_t *filter_y, - int32_t height) + const int8_t *filter_y) { - v8i16 in0, in1; + uint64_t tp0, tp1; + v16u8 out; + v8i16 in0 = { 0 }; v16i8 src0, src1, src2, src3, src4; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; v8i16 filter_vec, const_vec; v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4; - v4i32 dst0_r, dst1_r; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; + v8i16 dst20, dst31, dst42, dst10, dst32, dst21, dst43, tmp; + v4i32 dst0, dst1; src0_ptr -= (src_stride + 1); @@ -3793,56 +3793,43 @@ static void hevc_hv_bi_4t_4x2_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; const_vec = __msa_ldi_h(128); const_vec <<= 6; - LD_SB3(src0_ptr, src_stride, src0, src1, src2); - src0_ptr += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); - - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); - - LD_SB2(src0_ptr, src_stride, src3, src4); - LD_SH2(src1_ptr, src2_stride, in0, in1); - in0 = (v8i16) __msa_ilvr_d((v2i64) in1, (v2i64) in0); - XORI_B2_128_SB(src3, src4); - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - dst32_r = __msa_ilvr_h(dst3, dst2); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - dst43_r = __msa_ilvr_h(dst4, dst3); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - dst0_r = (v4i32) __msa_pckev_h((v8i16) dst1_r, (v8i16) dst0_r); - dst0_r = (v4i32) __msa_adds_s_h((v8i16) dst0_r, in0); - dst0_r = (v4i32) __msa_srari_h((v8i16) dst0_r, 7); - dst0_r = (v4i32) CLIP_SH_0_255(dst0_r); - - dst0_r = (v4i32) __msa_pckev_b((v16i8) dst0_r, (v16i8) dst0_r); - ST4x2_UB(dst0_r, dst, dst_stride); + LD_SB5(src0_ptr, src_stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in0); + in0 = __msa_adds_s_h(in0, const_vec); + + VSHF_B2_SB(src0, src2, src0, src2, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src3, src1, src3, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src4, src2, src4, mask0, mask1, vec4, vec5); + + dst20 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst31 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst42 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + + ILVRL_H2_SH(dst31, dst20, dst10, dst32); + ILVRL_H2_SH(dst42, dst31, dst21, dst43); + + dst0 = HEVC_FILT_4TAP(dst10, dst32, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21, dst43, filt_h0, filt_h1); + dst0 >>= 6; + dst1 >>= 6; + tmp = __msa_pckev_h((v8i16) dst1, (v8i16) dst0); + tmp = __msa_adds_s_h(tmp, in0); + tmp = __msa_srari_h(tmp, 7); + tmp = CLIP_SH_0_255_MAX_SATU(tmp); + out = (v16u8) __msa_pckev_b((v16i8) tmp, (v16i8) tmp); + ST4x2_UB(out, dst, dst_stride); } static void hevc_hv_bi_4t_4x4_msa(uint8_t *src0_ptr, @@ -3852,21 +3839,22 @@ static void hevc_hv_bi_4t_4x4_msa(uint8_t *src0_ptr, uint8_t *dst, int32_t dst_stride, const int8_t *filter_x, - const int8_t *filter_y, - int32_t height) + const int8_t *filter_y) { - v8i16 in0, in1, in2, in3; + uint64_t tp0, tp1; + v16u8 out; v16i8 src0, src1, src2, src3, src4, src5, src6; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v8i16 dst0_r, dst1_r; - v4i32 tmp0, tmp1, tmp2, tmp3; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 tmp0, tmp1; + v8i16 in0 = { 0 }, in1 = { 0 }; + v8i16 dst30, dst41, dst52, dst63; + v8i16 dst10, dst32, dst54, dst21, dst43, dst65; + v4i32 dst0, dst1, dst2, dst3; src0_ptr -= (src_stride + 1); @@ -3874,69 +3862,50 @@ static void hevc_hv_bi_4t_4x4_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; + LD_SB7(src0_ptr, src_stride, src0, src1, src2, src3, src4, src5, src6); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + const_vec = __msa_ldi_h(128); const_vec <<= 6; - LD_SB3(src0_ptr, src_stride, src0, src1, src2); - src0_ptr += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in0); + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in1); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); + ADDS_SH2_SH(in0, const_vec, in1, const_vec, in0, in1); - LD_SB4(src0_ptr, src_stride, src3, src4, src5, src6); - LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); - ILVR_D2_SH(in1, in0, in3, in2, in0, in1); - XORI_B4_128_SB(src3, src4, src5, src6); - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - dst32_r = __msa_ilvr_h(dst3, dst2); - tmp0 = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - tmp0 >>= 6; - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - dst43_r = __msa_ilvr_h(dst4, dst3); - tmp1 = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - tmp1 >>= 6; - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - dst10_r = __msa_ilvr_h(dst5, dst4); - tmp2 = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - tmp2 >>= 6; - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - dst21_r = __msa_ilvr_h(dst2, dst5); - tmp3 = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - tmp3 >>= 6; - PCKEV_H2_SH(tmp1, tmp0, tmp3, tmp2, dst0_r, dst1_r); - HEVC_BI_RND_CLIP2(in0, in1, dst0_r, dst1_r, 7, dst0_r, dst1_r); + VSHF_B2_SB(src0, src3, src0, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src4, src1, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src5, src2, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src3, src6, src3, src6, mask0, mask1, vec6, vec7); - dst0_r = (v8i16) __msa_pckev_b((v16i8) dst1_r, (v16i8) dst0_r); - ST4x4_UB(dst0_r, dst0_r, 0, 1, 2, 3, dst, dst_stride); - dst += (4 * dst_stride); + dst30 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst41 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst52 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst63 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + ILVRL_H2_SH(dst41, dst30, dst10, dst43); + ILVRL_H2_SH(dst52, dst41, dst21, dst54); + ILVRL_H2_SH(dst63, dst52, dst32, dst65); + dst0 = HEVC_FILT_4TAP(dst10, dst32, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21, dst43, filt_h0, filt_h1); + dst2 = HEVC_FILT_4TAP(dst32, dst54, filt_h0, filt_h1); + dst3 = HEVC_FILT_4TAP(dst43, dst65, filt_h0, filt_h1); + SRA_4V(dst0, dst1, dst2, dst3, 6); + PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp0, tmp1); + ADDS_SH2_SH(tmp0, in0, tmp1, in1, tmp0, tmp1); + SRARI_H2_SH(tmp0, tmp1, 7); + CLIP_SH2_0_255_MAX_SATU(tmp0, tmp1); + out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); } static void hevc_hv_bi_4t_4multx8mult_msa(uint8_t *src0_ptr, @@ -3950,18 +3919,21 @@ static void hevc_hv_bi_4t_4multx8mult_msa(uint8_t *src0_ptr, int32_t height) { uint32_t loop_cnt; - v8i16 in0, in1, in2, in3, in4, in5, in6, in7; + uint64_t tp0, tp1; + v16u8 out0, out1; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8, dst9; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v8i16 tmp0, tmp1, tmp2, tmp3; + v8i16 dst10, dst21, dst22, dst73, dst84, dst95, dst106; v8i16 dst10_r, dst32_r, dst54_r, dst76_r; v8i16 dst21_r, dst43_r, dst65_r, dst87_r; + v8i16 dst98_r, dst109_r; + v8i16 in0 = { 0 }, in1 = { 0 }, in2 = { 0 }, in3 = { 0 }; v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r, dst6_r, dst7_r; src0_ptr -= (src_stride + 1); @@ -3970,10 +3942,9 @@ static void hevc_hv_bi_4t_4multx8mult_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; @@ -3984,90 +3955,75 @@ static void hevc_hv_bi_4t_4multx8mult_msa(uint8_t *src0_ptr, src0_ptr += (3 * src_stride); XORI_B3_128_SB(src0, src1, src2); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); + VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src2, src1, src2, mask0, mask1, vec2, vec3); + dst10 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst21 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + ILVRL_H2_SH(dst21, dst10, dst10_r, dst21_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst21, 1); + for (loop_cnt = height >> 3; loop_cnt--;) { LD_SB8(src0_ptr, src_stride, src3, src4, src5, src6, src7, src8, src9, src10); src0_ptr += (8 * src_stride); - LD_SH8(src1_ptr, src2_stride, in0, in1, in2, in3, in4, in5, in6, in7); - src1_ptr += (8 * src2_stride); - ILVR_D2_SH(in1, in0, in3, in2, in0, in1); - ILVR_D2_SH(in5, in4, in7, in6, in2, in3); XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - dst32_r = __msa_ilvr_h(dst3, dst2); + VSHF_B2_SB(src3, src7, src3, src7, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src8, src4, src8, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src9, src5, src9, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src10, src6, src10, mask0, mask1, vec6, vec7); + + dst73 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst84 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst95 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst106 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + dst32_r = __msa_ilvr_h(dst73, dst22); + ILVRL_H2_SH(dst84, dst73, dst43_r, dst87_r); + ILVRL_H2_SH(dst95, dst84, dst54_r, dst98_r); + ILVRL_H2_SH(dst106, dst95, dst65_r, dst109_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst73, 1); + dst76_r = __msa_ilvr_h(dst22, dst106); + + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in0); + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in1); + + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in2); + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in3); + + ADDS_SH4_SH(in0, const_vec, in1, const_vec, in2, const_vec, in3, + const_vec, in0, in1, in2, in3); dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - dst43_r = __msa_ilvr_h(dst4, dst3); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - dst54_r = __msa_ilvr_h(dst5, dst4); dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); - dst2_r >>= 6; - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); - dst65_r = __msa_ilvr_h(dst6, dst5); dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); - dst3_r >>= 6; - /* row 7 */ - VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); - dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); - dst76_r = __msa_ilvr_h(dst7, dst6); dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); - dst4_r >>= 6; - /* row 8 */ - VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec0, vec1); - dst8 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst8, dst8); - dst87_r = __msa_ilvr_h(dst8, dst7); dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); - dst5_r >>= 6; - /* row 9 */ - VSHF_B2_SB(src9, src9, src9, src9, mask0, mask1, vec0, vec1); - dst9 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst9, dst9); - dst10_r = __msa_ilvr_h(dst9, dst8); - dst6_r = HEVC_FILT_4TAP(dst76_r, dst10_r, filt_h0, filt_h1); - dst6_r >>= 6; - /* row 10 */ - VSHF_B2_SB(src10, src10, src10, src10, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - dst21_r = __msa_ilvr_h(dst2, dst9); - dst7_r = HEVC_FILT_4TAP(dst87_r, dst21_r, filt_h0, filt_h1); - dst7_r >>= 6; + dst6_r = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7_r = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + SRA_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SRA_4V(dst4_r, dst5_r, dst6_r, dst7_r, 6); PCKEV_H4_SH(dst1_r, dst0_r, dst3_r, dst2_r, dst5_r, dst4_r, dst7_r, dst6_r, tmp0, tmp1, tmp2, tmp3); - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - tmp0, tmp1, tmp2, tmp3, 7, tmp0, tmp1, tmp2, tmp3); - - PCKEV_B2_SH(tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); - ST4x8_UB(tmp0, tmp1, dst, dst_stride); + ADDS_SH4_SH(in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, tmp0, tmp1, + tmp2, tmp3); + SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST4x8_UB(out0, out1, dst, dst_stride); dst += (8 * dst_stride); + + dst10_r = dst98_r; + dst21_r = dst109_r; + dst22 = (v8i16) __msa_splati_d((v2i64) dst106, 1); } } @@ -4083,10 +4039,10 @@ static void hevc_hv_bi_4t_4w_msa(uint8_t *src0_ptr, { if (2 == height) { hevc_hv_bi_4t_4x2_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter_x, filter_y, height); + dst, dst_stride, filter_x, filter_y); } else if (4 == height) { hevc_hv_bi_4t_4x4_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter_x, filter_y, height); + dst, dst_stride, filter_x, filter_y); } else if (0 == (height % 8)) { hevc_hv_bi_4t_4multx8mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, @@ -4105,20 +4061,28 @@ static void hevc_hv_bi_4t_6w_msa(uint8_t *src0_ptr, const int8_t *filter_y, int32_t height) { - uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5, src6; - v8i16 in0, in1, in2, in3; + uint32_t tpw0, tpw1, tpw2, tpw3; + uint64_t tp0, tp1; + v16u8 out0, out1, out2; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; + v8i16 dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6, dsth7, dsth8, dsth9; + v8i16 dsth10, tmp4, tmp5; v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + v4i32 dst4_r, dst5_r, dst6_r, dst7_r; v8i16 tmp0, tmp1, tmp2, tmp3; v8i16 dst10_r, dst32_r, dst21_r, dst43_r; v8i16 dst10_l, dst32_l, dst21_l, dst43_l; + v8i16 dst54_r, dst76_r, dst98_r, dst65_r, dst87_r, dst109_r; + v8i16 dst54_l, dst76_l, dst98_l, dst65_l, dst87_l, dst109_l; + v8i16 dst1021_l, dst3243_l, dst5465_l, dst7687_l, dst98109_l; + v8i16 in0 = { 0 }, in1 = { 0 }, in2 = { 0 }, in3 = { 0 }; + v8i16 in4 = { 0 }, in5 = { 0 }; src0_ptr -= (src_stride + 1); @@ -4126,10 +4090,9 @@ static void hevc_hv_bi_4t_6w_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; @@ -4143,71 +4106,101 @@ static void hevc_hv_bi_4t_6w_msa(uint8_t *src0_ptr, VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); - ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); + dsth0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); - for (loop_cnt = height >> 2; loop_cnt--;) { - LD_SB4(src0_ptr, src_stride, src3, src4, src5, src6); - src0_ptr += (4 * src_stride); - LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); - src1_ptr += (4 * src2_stride); - XORI_B4_128_SB(src3, src4, src5, src6); - - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + ILVRL_H2_SH(dsth1, dsth0, dst10_r, dst10_l); + ILVRL_H2_SH(dsth2, dsth1, dst21_r, dst21_l); - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; + LD_SB8(src0_ptr, src_stride, + src3, src4, src5, src6, src7, src8, src9, src10); + XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); - ILVRL_H2_SH(dst5, dst4, dst10_r, dst10_l); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_l = HEVC_FILT_4TAP(dst32_l, dst10_l, filt_h0, filt_h1); - dst2_r >>= 6; - dst2_l >>= 6; + dsth3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - ILVRL_H2_SH(dst2, dst5, dst21_r, dst21_l); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_l = HEVC_FILT_4TAP(dst43_l, dst21_l, filt_h0, filt_h1); - dst3_r >>= 6; - dst3_l >>= 6; - PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, tmp0, tmp1, tmp2, tmp3); - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - tmp0, tmp1, tmp2, tmp3, 7, tmp0, tmp1, tmp2, tmp3); + VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src9, src9, src9, src9, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src10, src10, src10, src10, mask0, mask1, vec6, vec7); + + dsth7 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth8 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth9 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth10 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + ILVRL_H2_SH(dsth3, dsth2, dst32_r, dst32_l); + ILVRL_H2_SH(dsth4, dsth3, dst43_r, dst43_l); + ILVRL_H2_SH(dsth5, dsth4, dst54_r, dst54_l); + ILVRL_H2_SH(dsth6, dsth5, dst65_r, dst65_l); + ILVRL_H2_SH(dsth7, dsth6, dst76_r, dst76_l); + ILVRL_H2_SH(dsth8, dsth7, dst87_r, dst87_l); + ILVRL_H2_SH(dsth9, dsth8, dst98_r, dst98_l); + ILVRL_H2_SH(dsth10, dsth9, dst109_r, dst109_l); + PCKEV_D2_SH(dst21_l, dst10_l, dst43_l, dst32_l, dst1021_l, dst3243_l); + PCKEV_D2_SH(dst65_l, dst54_l, dst87_l, dst76_l, dst5465_l, dst7687_l); + dst98109_l = (v8i16) __msa_pckev_d((v2i64) dst109_l, (v2i64) dst98_l); - PCKEV_B2_SW(tmp1, tmp0, tmp3, tmp2, dst0_r, dst1_r); - ST6x4_UB(dst0_r, dst1_r, dst, dst_stride); - dst += (4 * dst_stride); - } + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); + dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); + dst6_r = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7_r = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst1021_l, dst3243_l, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst3243_l, dst5465_l, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst5465_l, dst7687_l, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst7687_l, dst98109_l, filt_h0, filt_h1); + SRA_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SRA_4V(dst4_r, dst5_r, dst6_r, dst7_r, 6); + SRA_4V(dst0_l, dst1_l, dst2_l, dst3_l, 6); + PCKEV_H2_SH(dst1_r, dst0_r, dst3_r, dst2_r, tmp0, tmp1); + PCKEV_H2_SH(dst5_r, dst4_r, dst7_r, dst6_r, tmp2, tmp3); + PCKEV_H2_SH(dst1_l, dst0_l, dst3_l, dst2_l, tmp4, tmp5); + + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in0); + LD2(src1_ptr + 2 * src2_stride, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in1); + + LD2(src1_ptr + 4 * src2_stride, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in2); + LD2(src1_ptr + 6 * src2_stride, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in3); + + ADDS_SH4_SH(in0, const_vec, in1, const_vec, in2, const_vec, in3, const_vec, + in0, in1, in2, in3); + ADDS_SH4_SH(in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, tmp0, tmp1, tmp2, + tmp3); + SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST4x8_UB(out0, out1, dst, dst_stride); + + LW4(src1_ptr + 4, src2_stride, tpw0, tpw1, tpw2, tpw3); + src1_ptr += (4 * src2_stride); + INSERT_W4_SH(tpw0, tpw1, tpw2, tpw3, in4); + LW4(src1_ptr + 4, src2_stride, tpw0, tpw1, tpw2, tpw3); + INSERT_W4_SH(tpw0, tpw1, tpw2, tpw3, in5); + ADDS_SH2_SH(in4, const_vec, in5, const_vec, in4, in5); + ADDS_SH2_SH(in4, tmp4, in5, tmp5, tmp4, tmp5); + SRARI_H2_SH(tmp4, tmp5, 7); + CLIP_SH2_0_255_MAX_SATU(tmp4, tmp5); + out2 = (v16u8) __msa_pckev_b((v16i8) tmp5, (v16i8) tmp4); + ST2x4_UB(out2, 0, dst + 4, dst_stride); + dst += 4 * dst_stride; + ST2x4_UB(out2, 4, dst + 4, dst_stride); } static void hevc_hv_bi_4t_8x2_msa(uint8_t *src0_ptr, @@ -4217,16 +4210,16 @@ static void hevc_hv_bi_4t_8x2_msa(uint8_t *src0_ptr, uint8_t *dst, int32_t dst_stride, const int8_t *filter_x, - const int8_t *filter_y, - int32_t height) + const int8_t *filter_y) { + v16u8 out; v16i8 src0, src1, src2, src3, src4; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; v8i16 dst0, dst1, dst2, dst3, dst4; v4i32 dst0_r, dst0_l, dst1_r, dst1_l; v8i16 dst10_r, dst32_r, dst21_r, dst43_r; @@ -4240,62 +4233,144 @@ static void hevc_hv_bi_4t_8x2_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; const_vec = __msa_ldi_h(128); const_vec <<= 6; - LD_SB3(src0_ptr, src_stride, src0, src1, src2); - src0_ptr += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); + LD_SB5(src0_ptr, src_stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + + LD_SH2(src1_ptr, src2_stride, in0, in1); + ADDS_SH2_SH(in0, const_vec, in1, const_vec, in0, in1); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec8, vec9); + + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec8, vec9, filt0, filt1); ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); - - LD_SB2(src0_ptr, src_stride, src3, src4); - LD_SH2(src1_ptr, src2_stride, in0, in1); - XORI_B2_128_SB(src3, src4); - - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); PCKEV_H2_SH(dst0_l, dst0_r, dst1_l, dst1_r, tmp0, tmp1); - HEVC_BI_RND_CLIP2(in0, in1, tmp0, tmp1, 7, tmp0, tmp1); + ADDS_SH2_SH(in0, tmp0, in1, tmp1, tmp0, tmp1); + SRARI_H2_SH(tmp0, tmp1, 7); + CLIP_SH2_0_255_MAX_SATU(tmp0, tmp1); + out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); + ST8x2_UB(out, dst, dst_stride); +} - dst0_r = (v4i32) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); - ST8x2_UB(dst0_r, dst, dst_stride); +static void hevc_hv_bi_4t_8multx4_msa(uint8_t *src0_ptr, + int32_t src_stride, + int16_t *src1_ptr, + int32_t src2_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_x, + const int8_t *filter_y, + int32_t width8mult) +{ + uint32_t cnt; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4, src5, src6, mask0, mask1; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 filt0, filt1, filt_h0, filt_h1, filter_vec, const_vec; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, tmp0, tmp1, tmp2, tmp3; + v8i16 in0, in1, in2, in3; + v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + v8i16 dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + + src0_ptr -= (src_stride + 1); + + filter_vec = LD_SH(filter_x); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + + const_vec = __msa_ldi_h(128); + const_vec <<= 6; + + for (cnt = width8mult; cnt--;) { + LD_SB7(src0_ptr, src_stride, src0, src1, src2, src3, src4, src5, src6); + src0_ptr += 8; + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); + src1_ptr += 8; + ADDS_SH4_SH(in0, const_vec, in1, const_vec, in2, const_vec, in3, + const_vec, in0, in1, in2, in3); + + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + + ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); + ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); + + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); + + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); + + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, + dst3_r, tmp0, tmp1, tmp2, tmp3); + ADDS_SH4_SH(in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, + tmp0, tmp1, tmp2, tmp3); + SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST8x4_UB(out0, out1, dst, dst_stride); + dst += 8; + } } static void hevc_hv_bi_4t_8x6_msa(uint8_t *src0_ptr, @@ -4305,17 +4380,18 @@ static void hevc_hv_bi_4t_8x6_msa(uint8_t *src0_ptr, uint8_t *dst, int32_t dst_stride, const int8_t *filter_x, - const int8_t *filter_y, - int32_t height) + const int8_t *filter_y) { + v16u8 out0, out1, out2; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; v8i16 in0, in1, in2, in3, in4, in5; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; + v16i8 vec10, vec11, vec12, vec13, vec14, vec15, vec16, vec17; v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; @@ -4331,120 +4407,87 @@ static void hevc_hv_bi_4t_8x6_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; const_vec = __msa_ldi_h(128); const_vec <<= 6; - LD_SB3(src0_ptr, src_stride, src0, src1, src2); - src0_ptr += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); + LD_SB5(src0_ptr, src_stride, src0, src1, src2, src3, src4); + src0_ptr += (5 * src_stride); + LD_SB4(src0_ptr, src_stride, src5, src6, src7, src8); + + XORI_B5_128_SB(src0, src1, src2, src3, src4); + XORI_B4_128_SB(src5, src6, src7, src8); + + LD_SH6(src1_ptr, src2_stride, in0, in1, in2, in3, in4, in5); + ADDS_SH4_SH(in0, const_vec, in1, const_vec, in2, const_vec, in3, const_vec, + in0, in1, in2, in3); + ADDS_SH2_SH(in4, const_vec, in5, const_vec, in4, in5); + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec8, vec9); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec10, vec11); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec12, vec13); + VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec14, vec15); + VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec16, vec17); + + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec8, vec9, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec10, vec11, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(vec12, vec13, filt0, filt1); + dst7 = HEVC_FILT_4TAP_SH(vec14, vec15, filt0, filt1); + dst8 = HEVC_FILT_4TAP_SH(vec16, vec17, filt0, filt1); ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); - - LD_SB2(src0_ptr, src_stride, src3, src4); - src0_ptr += (2 * src_stride); - XORI_B2_128_SB(src3, src4); - LD_SH6(src1_ptr, src2_stride, in0, in1, in2, in3, in4, in5); - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); + ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); + ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - tmp0 = __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); - - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - tmp1 = __msa_pckev_h((v8i16) dst1_l, (v8i16) dst1_r); - - LD_SB2(src0_ptr, src_stride, src5, src6); - src0_ptr += (2 * src_stride); - XORI_B2_128_SB(src5, src6); - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); - dst2_r >>= 6; - dst2_l >>= 6; - tmp2 = __msa_pckev_h((v8i16) dst2_l, (v8i16) dst2_r); - - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); - - ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); - dst3_r >>= 6; - dst3_l >>= 6; - tmp3 = __msa_pckev_h((v8i16) dst3_l, (v8i16) dst3_r); - - LD_SB2(src0_ptr, src_stride, src7, src8); - XORI_B2_128_SB(src7, src8); - /* row 7 */ - VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); - dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); - - ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); dst4_l = HEVC_FILT_4TAP(dst54_l, dst76_l, filt_h0, filt_h1); - - dst4_r >>= 6; - dst4_l >>= 6; - tmp4 = __msa_pckev_h((v8i16) dst4_l, (v8i16) dst4_r); - /* row 8 */ - VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec0, vec1); - dst8 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst8, dst8); - - ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); dst5_l = HEVC_FILT_4TAP(dst65_l, dst87_l, filt_h0, filt_h1); - dst5_r >>= 6; - dst5_l >>= 6; - tmp5 = __msa_pckev_h((v8i16) dst5_l, (v8i16) dst5_r); - - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - tmp0, tmp1, tmp2, tmp3, 7, tmp0, tmp1, tmp2, tmp3); - HEVC_BI_RND_CLIP2(in4, in5, tmp4, tmp5, 7, tmp4, tmp5); - PCKEV_B2_SW(tmp1, tmp0, tmp3, tmp2, dst0_r, dst1_r); - dst2_r = (v4i32) __msa_pckev_b((v16i8) tmp5, (v16i8) tmp4); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + SRA_4V(dst4_r, dst4_l, dst5_r, dst5_l, 6); + PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, dst3_r, + tmp0, tmp1, tmp2, tmp3); + PCKEV_H2_SH(dst4_l, dst4_r, dst5_l, dst5_r, tmp4, tmp5); + ADDS_SH4_SH(in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, + tmp0, tmp1, tmp2, tmp3); + ADDS_SH2_SH(in4, tmp4, in5, tmp5, tmp4, tmp5); + SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); + SRARI_H2_SH(tmp4, tmp5, 7); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH2_0_255_MAX_SATU(tmp4, tmp5); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + out2 = (v16u8) __msa_pckev_b((v16i8) tmp5, (v16i8) tmp4); + ST8x4_UB(out0, out1, dst, dst_stride); dst += (4 * dst_stride); - ST8x2_UB(dst2_r, dst, dst_stride); + ST8x2_UB(out2, dst, dst_stride); } static void hevc_hv_bi_4t_8multx4mult_msa(uint8_t *src0_ptr, @@ -4462,19 +4505,21 @@ static void hevc_hv_bi_4t_8multx4mult_msa(uint8_t *src0_ptr, uint8_t *src0_ptr_tmp; int16_t *src1_ptr_tmp; uint8_t *dst_tmp; + v16u8 out0, out1; v16i8 src0, src1, src2, src3, src4, src5, src6; v8i16 in0, in1, in2, in3; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; v8i16 tmp0, tmp1, tmp2, tmp3; v8i16 dst10_r, dst32_r, dst21_r, dst43_r; v8i16 dst10_l, dst32_l, dst21_l, dst43_l; + v8i16 dst54_r, dst54_l, dst65_r, dst65_l, dst6; src0_ptr -= (src_stride + 1); @@ -4482,10 +4527,9 @@ static void hevc_hv_bi_4t_8multx4mult_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; @@ -4504,12 +4548,10 @@ static void hevc_hv_bi_4t_8multx4mult_msa(uint8_t *src0_ptr, VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); + + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); @@ -4521,55 +4563,50 @@ static void hevc_hv_bi_4t_8multx4mult_msa(uint8_t *src0_ptr, src1_ptr_tmp += (4 * src2_stride); XORI_B4_128_SB(src3, src4, src5, src6); + ADDS_SH4_SH(in0, const_vec, in1, const_vec, in2, const_vec, in3, + const_vec, in0, in1, in2, in3); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - ILVRL_H2_SH(dst5, dst4, dst10_r, dst10_l); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_l = HEVC_FILT_4TAP(dst32_l, dst10_l, filt_h0, filt_h1); - dst2_r >>= 6; - dst2_l >>= 6; - - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - ILVRL_H2_SH(dst2, dst5, dst21_r, dst21_l); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_l = HEVC_FILT_4TAP(dst43_l, dst21_l, filt_h0, filt_h1); - dst3_r >>= 6; - dst3_l >>= 6; - - PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, tmp0, tmp1, tmp2, tmp3); - HEVC_BI_RND_CLIP4(in0, in1, in2, in3, - tmp0, tmp1, tmp2, tmp3, 7, - tmp0, tmp1, tmp2, tmp3); - - PCKEV_B2_SW(tmp1, tmp0, tmp3, tmp2, dst0_r, dst1_r); - ST8x4_UB(dst0_r, dst1_r, dst_tmp, dst_stride); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); + + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, + dst3_r, tmp0, tmp1, tmp2, tmp3); + ADDS_SH4_SH(in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, + tmp0, tmp1, tmp2, tmp3); + SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST8x4_UB(out0, out1, dst_tmp, dst_stride); dst_tmp += (4 * dst_stride); + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dst2 = dst6; } src0_ptr += 8; @@ -4590,10 +4627,13 @@ static void hevc_hv_bi_4t_8w_msa(uint8_t *src0_ptr, { if (2 == height) { hevc_hv_bi_4t_8x2_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter_x, filter_y, height); + dst, dst_stride, filter_x, filter_y); + } else if (4 == height) { + hevc_hv_bi_4t_8multx4_msa(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, 1); } else if (6 == height) { hevc_hv_bi_4t_8x6_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter_x, filter_y, height); + dst, dst_stride, filter_x, filter_y); } else { hevc_hv_bi_4t_8multx4mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, @@ -4612,11 +4652,196 @@ static void hevc_hv_bi_4t_12w_msa(uint8_t *src0_ptr, const int8_t *filter_y, int32_t height) { - hevc_hv_bi_4t_8multx4mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter_x, filter_y, - height, 8); - hevc_hv_bi_4t_4w_msa(src0_ptr + 8, src_stride, src1_ptr + 8, src2_stride, - dst + 8, dst_stride, filter_x, filter_y, height); + uint32_t loop_cnt; + uint64_t tp0, tp1; + uint8_t *src0_ptr_tmp, *dst_tmp; + int16_t *src1_ptr_tmp; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 mask0, mask1, mask2, mask3; + v8i16 filt0, filt1, filt_h0, filt_h1, filter_vec, tmp0, tmp1, tmp2, tmp3; + v8i16 dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6, const_vec; + v8i16 dst10, dst21, dst22, dst73, dst84, dst95, dst106; + v8i16 dst76_r, dst98_r, dst87_r, dst109_r; + v8i16 in0 = { 0 }, in1 = { 0 }, in2 = { 0 }, in3 = { 0 }; + v8i16 dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + v4i32 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + + src0_ptr -= (src_stride + 1); + + filter_vec = LD_SH(filter_x); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + + const_vec = __msa_ldi_h(128); + const_vec <<= 6; + + src0_ptr_tmp = src0_ptr; + dst_tmp = dst; + src1_ptr_tmp = src1_ptr; + + LD_SB3(src0_ptr_tmp, src_stride, src0, src1, src2); + src0_ptr_tmp += (3 * src_stride); + + XORI_B3_128_SB(src0, src1, src2); + + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + + dsth0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + + ILVRL_H2_SH(dsth1, dsth0, dst10_r, dst10_l); + ILVRL_H2_SH(dsth2, dsth1, dst21_r, dst21_l); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src0_ptr_tmp, src_stride, src3, src4, src5, src6); + src0_ptr_tmp += (4 * src_stride); + XORI_B4_128_SB(src3, src4, src5, src6); + + LD_SH4(src1_ptr_tmp, src2_stride, in0, in1, in2, in3); + src1_ptr_tmp += (4 * src2_stride); + ADDS_SH4_SH(in0, const_vec, in1, const_vec, in2, const_vec, in3, + const_vec, in0, in1, in2, in3); + + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + + dsth3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + ILVRL_H2_SH(dsth3, dsth2, dst32_r, dst32_l); + ILVRL_H2_SH(dsth4, dsth3, dst43_r, dst43_l); + ILVRL_H2_SH(dsth5, dsth4, dst54_r, dst54_l); + ILVRL_H2_SH(dsth6, dsth5, dst65_r, dst65_l); + + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); + + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, + dst3_r, tmp0, tmp1, tmp2, tmp3); + ADDS_SH4_SH(in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, + tmp0, tmp1, tmp2, tmp3); + SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST8x4_UB(out0, out1, dst_tmp, dst_stride); + dst_tmp += (4 * dst_stride); + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dsth2 = dsth6; + } + + src0_ptr += 8; + dst += 8; + src1_ptr += 8; + + mask2 = LD_SB(ff_hevc_mask_arr + 16); + mask3 = mask2 + 2; + + LD_SB3(src0_ptr, src_stride, src0, src1, src2); + src0_ptr += (3 * src_stride); + XORI_B3_128_SB(src0, src1, src2); + VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); + VSHF_B2_SB(src1, src2, src1, src2, mask2, mask3, vec2, vec3); + + dst10 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst21 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + + ILVRL_H2_SH(dst21, dst10, dst10_r, dst21_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst21, 1); + + for (loop_cnt = 2; loop_cnt--;) { + LD_SB8(src0_ptr, src_stride, + src3, src4, src5, src6, src7, src8, src9, src10); + src0_ptr += (8 * src_stride); + XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); + VSHF_B2_SB(src3, src7, src3, src7, mask2, mask3, vec0, vec1); + VSHF_B2_SB(src4, src8, src4, src8, mask2, mask3, vec2, vec3); + VSHF_B2_SB(src5, src9, src5, src9, mask2, mask3, vec4, vec5); + VSHF_B2_SB(src6, src10, src6, src10, mask2, mask3, vec6, vec7); + + dst73 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst84 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst95 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst106 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + dst32_r = __msa_ilvr_h(dst73, dst22); + ILVRL_H2_SH(dst84, dst73, dst43_r, dst87_r); + ILVRL_H2_SH(dst95, dst84, dst54_r, dst98_r); + ILVRL_H2_SH(dst106, dst95, dst65_r, dst109_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst73, 1); + dst76_r = __msa_ilvr_h(dst22, dst106); + + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in0); + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in1); + + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in2); + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in3); + + ADDS_SH4_SH(in0, const_vec, in1, const_vec, in2, const_vec, in3, + const_vec, in0, in1, in2, in3); + + dst0 = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst2 = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst3 = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst4 = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); + dst5 = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); + dst6 = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7 = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + + SRA_4V(dst0, dst1, dst2, dst3, 6); + SRA_4V(dst4, dst5, dst6, dst7, 6); + PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, + tmp0, tmp1, tmp2, tmp3); + ADDS_SH4_SH(in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, + tmp0, tmp1, tmp2, tmp3); + SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST4x8_UB(out0, out1, dst, dst_stride); + dst += (8 * dst_stride); + + dst10_r = dst98_r; + dst21_r = dst109_r; + dst22 = (v8i16) __msa_splati_d((v2i64) dst106, 1); + } } static void hevc_hv_bi_4t_16w_msa(uint8_t *src0_ptr, @@ -4629,9 +4854,14 @@ static void hevc_hv_bi_4t_16w_msa(uint8_t *src0_ptr, const int8_t *filter_y, int32_t height) { - hevc_hv_bi_4t_8multx4mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, - dst, dst_stride, filter_x, filter_y, - height, 16); + if (4 == height) { + hevc_hv_bi_4t_8multx4_msa(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, 2); + } else { + hevc_hv_bi_4t_8multx4mult_msa(src0_ptr, src_stride, src1_ptr, + src2_stride, dst, dst_stride, filter_x, + filter_y, height, 16); + } } static void hevc_hv_bi_4t_24w_msa(uint8_t *src0_ptr, From 15c632719a5f781fdd11a68cdad5eeb9ee5392b8 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Mon, 6 Nov 2017 14:15:31 +0100 Subject: [PATCH 0784/2557] configure: libvmaf is not GPLv2-compatible. It is licensed under Apache 2.0. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 83b4cc9364d57..5b7a745b76154 100755 --- a/configure +++ b/configure @@ -1569,6 +1569,7 @@ EXTERNAL_LIBRARY_VERSION3_LIST=" gmp libopencore_amrnb libopencore_amrwb + libvmaf libvo_amrwbenc rkmpp " @@ -1625,7 +1626,6 @@ EXTERNAL_LIBRARY_LIST=" libtheora libtwolame libv4l2 - libvmaf libvorbis libvpx libwavpack From ce52e430b2df17b5efa28669f6c58992758f9913 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 7 Nov 2017 16:38:59 -0300 Subject: [PATCH 0785/2557] compat/w32dlfcn: add missing config.h include Fixes warnings about undefined HAVE_WINRT Signed-off-by: James Almer --- compat/w32dlfcn.h | 1 + 1 file changed, 1 insertion(+) diff --git a/compat/w32dlfcn.h b/compat/w32dlfcn.h index 78cc8f4c96d6c..c83bdc933307b 100644 --- a/compat/w32dlfcn.h +++ b/compat/w32dlfcn.h @@ -21,6 +21,7 @@ #ifdef _WIN32 #include +#include "config.h" #if (_WIN32_WINNT < 0x0602) || HAVE_WINRT #include "libavutil/wchar_filename.h" #endif From 2c2f25eb8920129ef3cfe6da2e1cefdedc485965 Mon Sep 17 00:00:00 2001 From: Greg Wessels Date: Sat, 4 Nov 2017 23:43:09 -0500 Subject: [PATCH 0786/2557] avutil/hwcontext_d3d11va: Fix leak when wrapping texture in AVD3D11FrameDescriptor Reviewed-by: Aaron Levinson Signed-off-by: James Almer --- libavutil/hwcontext_d3d11va.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 52683b92cd742..65dd6651fc1da 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -123,6 +123,7 @@ static void d3d11va_frames_uninit(AVHWFramesContext *ctx) static void free_texture(void *opaque, uint8_t *data) { ID3D11Texture2D_Release((ID3D11Texture2D *)opaque); + av_free(data); } static AVBufferRef *wrap_texture_buf(ID3D11Texture2D *tex, int index) From cd1ff3e45d45ce8d733b4acc8e23444c1a227d07 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 5 Nov 2017 14:59:47 -0300 Subject: [PATCH 0787/2557] avformat: move priv_pts from AVStream to an internal struct It has no reason to be in a public header, even if defined as private. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/avformat.h | 2 -- libavformat/internal.h | 2 ++ libavformat/mux.c | 18 +++++++++--------- libavformat/utils.c | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index b36e2a3bd4d6a..c068aa8009c7e 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1200,8 +1200,6 @@ typedef struct AVStream { */ AVRational display_aspect_ratio; - struct FFFrac *priv_pts; - /** * An opaque field for libavformat internal usage. * Must not be accessed in any way by callers. diff --git a/libavformat/internal.h b/libavformat/internal.h index d136c79bdd42a..fcd47840a5c72 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -196,6 +196,8 @@ struct AVStreamInternal { * Whether the internal avctx needs to be updated from codecpar (after a late change to codecpar) */ int need_context_update; + + FFFrac *priv_pts; }; #ifdef __GNUC__ diff --git a/libavformat/mux.c b/libavformat/mux.c index 1445e7dcd6f8a..b1244c67f3ba0 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -432,16 +432,16 @@ static int init_pts(AVFormatContext *s) break; } - if (!st->priv_pts) - st->priv_pts = av_mallocz(sizeof(*st->priv_pts)); - if (!st->priv_pts) + if (!st->internal->priv_pts) + st->internal->priv_pts = av_mallocz(sizeof(*st->internal->priv_pts)); + if (!st->internal->priv_pts) return AVERROR(ENOMEM); if (den != AV_NOPTS_VALUE) { if (den <= 0) return AVERROR_INVALIDDATA; - frac_init(st->priv_pts, 0, 0, den); + frac_init(st->internal->priv_pts, 0, 0, den); } } @@ -601,7 +601,7 @@ static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket * } pkt->dts = // pkt->pts= st->cur_dts; - pkt->pts = st->priv_pts->val; + pkt->pts = st->internal->priv_pts->val; } //calculate dts from pts @@ -638,7 +638,7 @@ static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket * av_ts2str(pkt->pts), av_ts2str(pkt->dts)); st->cur_dts = pkt->dts; - st->priv_pts->val = pkt->dts; + st->internal->priv_pts->val = pkt->dts; /* update pts */ switch (st->codecpar->codec_type) { @@ -650,12 +650,12 @@ static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket * /* HACK/FIXME, we skip the initial 0 size packets as they are most * likely equal to the encoder delay, but it would be better if we * had the real timestamps from the encoder */ - if (frame_size >= 0 && (pkt->size || st->priv_pts->num != st->priv_pts->den >> 1 || st->priv_pts->val)) { - frac_add(st->priv_pts, (int64_t)st->time_base.den * frame_size); + if (frame_size >= 0 && (pkt->size || st->internal->priv_pts->num != st->internal->priv_pts->den >> 1 || st->internal->priv_pts->val)) { + frac_add(st->internal->priv_pts, (int64_t)st->time_base.den * frame_size); } break; case AVMEDIA_TYPE_VIDEO: - frac_add(st->priv_pts, (int64_t)st->time_base.den * st->time_base.num); + frac_add(st->internal->priv_pts, (int64_t)st->time_base.den * st->time_base.num); break; } return 0; diff --git a/libavformat/utils.c b/libavformat/utils.c index cbfb78bf4d630..2b2411ffe7f9a 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -123,8 +123,8 @@ FF_ENABLE_DEPRECATION_WARNINGS int64_t av_stream_get_end_pts(const AVStream *st) { - if (st->priv_pts) { - return st->priv_pts->val; + if (st->internal->priv_pts) { + return st->internal->priv_pts->val; } else return AV_NOPTS_VALUE; } @@ -4263,6 +4263,7 @@ static void free_stream(AVStream **pst) av_bsf_free(&st->internal->bsfcs[i]); av_freep(&st->internal->bsfcs); } + av_freep(&st->internal->priv_pts); av_bsf_free(&st->internal->extract_extradata.bsf); av_packet_free(&st->internal->extract_extradata.pkt); } @@ -4282,7 +4283,6 @@ FF_ENABLE_DEPRECATION_WARNINGS av_freep(&st->info->duration_error); av_freep(&st->info); av_freep(&st->recommended_encoder_configuration); - av_freep(&st->priv_pts); av_freep(pst); } From ba79a101a2f938e2d83ccc32aca5df6e27f1d8e6 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 31 Oct 2017 02:56:31 +0100 Subject: [PATCH 0788/2557] lavc/dnxhddata: Do not print frame rates with supported profiles. The list is unmaintained, misleading and the frame rates are ignored by all compatible players. --- libavcodec/dnxhddata.c | 50 ++++++++++++++++-------------------------- libavcodec/dnxhddata.h | 1 - 2 files changed, 19 insertions(+), 32 deletions(-) diff --git a/libavcodec/dnxhddata.c b/libavcodec/dnxhddata.c index 4462df3c2a603..e995449d6342e 100644 --- a/libavcodec/dnxhddata.c +++ b/libavcodec/dnxhddata.c @@ -939,96 +939,84 @@ const CIDEntry ff_dnxhd_cid_table[] = { dnxhd_1235_dc_codes, dnxhd_1235_dc_bits, dnxhd_1235_ac_codes, dnxhd_1235_ac_bits, dnxhd_1235_ac_info, dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1235_run, - { 175, 185, 365, 440 }, - { { 24000, 1001 }, { 25, 1 }, { 50, 1 }, { 60000, 1001 } } }, + { 175, 185, 365, 440 } }, { 1237, 1920, 1080, 606208, 606208, 0, 4, 8, 3, dnxhd_1237_luma_weight, dnxhd_1237_chroma_weight, dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_info, dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run, - { 115, 120, 145, 240, 290 }, - { { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } }, + { 115, 120, 145, 240, 290 } }, { 1238, 1920, 1080, 917504, 917504, 0, 4, 8, 4, dnxhd_1238_luma_weight, dnxhd_1238_chroma_weight, dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1238_ac_codes, dnxhd_1238_ac_bits, dnxhd_1238_ac_info, dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1238_run, - { 175, 185, 220, 365, 440 }, - { { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } }, + { 175, 185, 220, 365, 440 } }, { 1241, 1920, 1080, 917504, 458752, DNXHD_INTERLACED, 6, 10, 4, dnxhd_1241_luma_weight, dnxhd_1241_chroma_weight, dnxhd_1235_dc_codes, dnxhd_1235_dc_bits, dnxhd_1235_ac_codes, dnxhd_1235_ac_bits, dnxhd_1235_ac_info, dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1235_run, - { 185, 220 }, - { { 25, 1 }, { 30000, 1001 } } }, + { 185, 220 } }, { 1242, 1920, 1080, 606208, 303104, DNXHD_INTERLACED, 4, 8, 3, dnxhd_1242_luma_weight, dnxhd_1242_chroma_weight, dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_info, dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run, - { 120, 145 }, - { { 25, 1 }, { 30000, 1001 } } }, + { 120, 145 } }, { 1243, 1920, 1080, 917504, 458752, DNXHD_INTERLACED, 4, 8, 4, dnxhd_1243_luma_weight, dnxhd_1243_chroma_weight, dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1238_ac_codes, dnxhd_1238_ac_bits, dnxhd_1238_ac_info, dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1238_run, - { 185, 220 }, - { { 25, 1 }, { 30000, 1001 } } }, + { 185, 220 } }, { 1244, 1440, 1080, 606208, 303104, DNXHD_INTERLACED, 4, 8, 3, dnxhd_1260_luma_weight, dnxhd_1260_chroma_weight, dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_info, dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run, - { 120, 145 }, - { { 25, 1 }, { 30000, 1001 } } }, + { 120, 145 } }, { 1250, 1280, 720, 458752, 458752, 0, 6, 10, 4, dnxhd_1250_luma_weight, dnxhd_1250_chroma_weight, dnxhd_1235_dc_codes, dnxhd_1235_dc_bits, dnxhd_1250_ac_codes, dnxhd_1250_ac_bits, dnxhd_1250_ac_info, dnxhd_1250_run_codes, dnxhd_1250_run_bits, dnxhd_1250_run, - { 90, 90, 180, 220 }, - { { 24000, 1001 }, { 25, 1 }, { 50, 1 }, { 60000, 1001 } } }, + { 90, 180, 220 } }, { 1251, 1280, 720, 458752, 458752, 0, 4, 8, 4, dnxhd_1251_luma_weight, dnxhd_1251_chroma_weight, dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1251_ac_codes, dnxhd_1251_ac_bits, dnxhd_1251_ac_info, dnxhd_1250_run_codes, dnxhd_1250_run_bits, dnxhd_1250_run, - { 90, 90, 110, 180, 220 }, - { { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } }, + { 90, 110, 180, 220 } }, { 1252, 1280, 720, 303104, 303104, 0, 4, 8, 5, dnxhd_1252_luma_weight, dnxhd_1252_chroma_weight, dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1252_ac_codes, dnxhd_1252_ac_bits, dnxhd_1252_ac_info, dnxhd_1250_run_codes, dnxhd_1250_run_bits, dnxhd_1250_run, - { 60, 60, 75, 120, 145 }, - { { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } }, + { 60, 75, 120, 145 } }, { 1253, 1920, 1080, 188416, 188416, 0, 4, 8, 3, dnxhd_1237_luma_weight, dnxhd_1237_chroma_weight, dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_info, dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run, - { 36, 36, 45, 75, 90 }, - { { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } }, + { 36, 45, 75, 90 } }, { 1256, 1920, 1080, 1835008, 1835008, DNXHD_444, 6, 10, 4, dnxhd_1235_luma_weight, dnxhd_1235_luma_weight, dnxhd_1235_dc_codes, dnxhd_1235_dc_bits, dnxhd_1235_ac_codes, dnxhd_1235_ac_bits, dnxhd_1235_ac_info, dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1235_run, - { 350, 390, 440, 730, 880 }, - { { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } }, + { 350, 390, 440, 730, 880 } }, { 1258, 960, 720, 212992, 212992, 0, 4, 8, 5, dnxhd_1252_luma_weight, dnxhd_1252_chroma_weight, @@ -1056,35 +1044,35 @@ const CIDEntry ff_dnxhd_cid_table[] = { dnxhd_1235_dc_codes, dnxhd_1235_dc_bits, dnxhd_1235_ac_codes, dnxhd_1235_ac_bits, dnxhd_1235_ac_info, dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1235_run, - { 0 }, { { 0 } }, { 57344, 255} }, + { 0 }, { 57344, 255} }, { 1271, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE, 0, 6, DNXHD_VARIABLE, 4, dnxhd_1241_luma_weight, dnxhd_1241_chroma_weight, dnxhd_1235_dc_codes, dnxhd_1235_dc_bits, dnxhd_1235_ac_codes, dnxhd_1235_ac_bits, dnxhd_1235_ac_info, dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1235_run, - { 0 }, { { 0 } }, { 28672, 255} }, + { 0 }, { 28672, 255} }, { 1272, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE, 0, 4, 8, 4, dnxhd_1238_luma_weight, dnxhd_1238_chroma_weight, dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1238_ac_codes, dnxhd_1238_ac_bits, dnxhd_1238_ac_info, dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1238_run, - { 0 }, { { 0 } }, { 28672, 255} }, + { 0 }, { 28672, 255} }, { 1273, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE, 0, 4, 8, 3, dnxhd_1237_luma_weight, dnxhd_1237_chroma_weight, dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_info, dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run, - { 0 }, { { 0 } }, { 18944, 255} }, + { 0 }, { 18944, 255} }, { 1274, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE, 0, 4, 8, 3, dnxhd_1237_luma_weight, dnxhd_1237_chroma_weight, dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_info, dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run, - { 0 }, { { 0 } }, { 5888, 255} }, + { 0 }, { 5888, 255} }, }; int ff_dnxhd_get_cid_table(int cid) @@ -1175,9 +1163,9 @@ void ff_dnxhd_print_profiles(AVCodecContext *avctx, int loglevel) if (!cid->bit_rates[j]) break; - av_log(avctx, loglevel, "Frame size: %dx%d%c; bitrate: %dMbps; pixel format: %s; framerate: %d/%d\n", + av_log(avctx, loglevel, "Frame size: %dx%d%c; bitrate: %dMbps; pixel format: %s\n", cid->width, cid->height, cid->flags & DNXHD_INTERLACED ? 'i' : 'p', cid->bit_rates[j], - cid->bit_depth == 10 ? "yuv422p10" : "yuv422p", cid->frame_rates[j].num, cid->frame_rates[j].den); + cid->bit_depth == 10 ? "yuv422p10" : "yuv422p"); } } } diff --git a/libavcodec/dnxhddata.h b/libavcodec/dnxhddata.h index c96c5e8f65aa8..6de2c0918ec7b 100644 --- a/libavcodec/dnxhddata.h +++ b/libavcodec/dnxhddata.h @@ -55,7 +55,6 @@ typedef struct CIDEntry { const uint16_t *run_codes; const uint8_t *run_bits, *run; int bit_rates[5]; ///< Helper to choose variants, rounded to nearest 5Mb/s - AVRational frame_rates[5]; AVRational packet_scale; } CIDEntry; From 4cfb46f94f1d1dd0bb599cf2ddc3e7920bb4bf82 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 8 Nov 2017 14:53:27 -0300 Subject: [PATCH 0789/2557] checkasm/llviddsp: fix warnings about mixed declaration and code Signed-off-by: James Almer --- tests/checkasm/llviddsp.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/tests/checkasm/llviddsp.c b/tests/checkasm/llviddsp.c index 9b35e2cadcb07..4c763ecf1b9bc 100644 --- a/tests/checkasm/llviddsp.c +++ b/tests/checkasm/llviddsp.c @@ -37,8 +37,6 @@ } while (0) #define init_buffer(a0, a1, type, width)\ - type *a0 = av_mallocz_array(width, sizeof(type));\ - type *a1 = av_mallocz_array(width, sizeof(type));\ if (!a0 || !a1)\ fail();\ randomize_buffers(a0, width * sizeof(type));\ @@ -48,12 +46,15 @@ static void check_add_bytes(LLVidDSPContext c, int width) { uint8_t *dst0 = av_mallocz(width); uint8_t *dst1 = av_mallocz(width); + uint8_t *src0 = av_mallocz_array(width, sizeof(uint8_t)); + uint8_t *src1 = av_mallocz_array(width, sizeof(uint8_t)); + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, uint8_t *src, ptrdiff_t w); + init_buffer(src0, src1, uint8_t, width); if (!dst0 || !dst1) fail(); - declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, uint8_t *src, ptrdiff_t w); if (check_func(c.add_bytes, "add_bytes")) { call_ref(dst0, src0, width); @@ -73,6 +74,14 @@ static void check_add_median_pred(LLVidDSPContext c, int width) { int A0, A1, B0, B1; uint8_t *dst0 = av_mallocz(width); uint8_t *dst1 = av_mallocz(width); + uint8_t *src0 = av_mallocz_array(width, sizeof(uint8_t)); + uint8_t *src1 = av_mallocz_array(width, sizeof(uint8_t)); + uint8_t *diff0 = av_mallocz_array(width, sizeof(uint8_t)); + uint8_t *diff1 = av_mallocz_array(width, sizeof(uint8_t)); + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, const uint8_t *src1, + const uint8_t *diff, ptrdiff_t w, + int *left, int *left_top); + init_buffer(src0, src1, uint8_t, width); init_buffer(diff0, diff1, uint8_t, width); @@ -81,9 +90,6 @@ static void check_add_median_pred(LLVidDSPContext c, int width) { A1 = A0; B1 = B0; - declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, const uint8_t *src1, - const uint8_t *diff, ptrdiff_t w, - int *left, int *left_top); if (check_func(c.add_median_pred, "add_median_pred")) { call_ref(dst0, src0, diff0, width, &A0, &B0); @@ -105,13 +111,15 @@ static void check_add_left_pred(LLVidDSPContext c, int width, int acc, const cha { uint8_t *dst0 = av_mallocz(width); uint8_t *dst1 = av_mallocz(width); + uint8_t *src0 = av_mallocz_array(width, sizeof(uint8_t)); + uint8_t *src1 = av_mallocz_array(width, sizeof(uint8_t)); + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, uint8_t *src, ptrdiff_t w, int acc); + init_buffer(src0, src1, uint8_t, width); if (!dst0 || !dst1) fail(); - declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, uint8_t *src, ptrdiff_t w, int acc); - if (check_func(c.add_left_pred, "%s", report)) { call_ref(dst0, src0, width, acc); call_new(dst1, src1, width, acc); @@ -130,13 +138,15 @@ static void check_add_left_pred_16(LLVidDSPContext c, unsigned mask, int width, { uint16_t *dst0 = av_mallocz_array(width, sizeof(uint16_t)); uint16_t *dst1 = av_mallocz_array(width, sizeof(uint16_t)); + uint16_t *src0 = av_mallocz_array(width, sizeof(uint16_t)); + uint16_t *src1 = av_mallocz_array(width, sizeof(uint16_t)); + declare_func_emms(AV_CPU_FLAG_MMX, void, uint16_t *dst, uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc); + init_buffer(src0, src1, uint16_t, width); if (!dst0 || !dst1) fail(); - declare_func_emms(AV_CPU_FLAG_MMX, void, uint16_t *dst, uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc); - if (check_func(c.add_left_pred_int16, "%s", report)) { call_ref(dst0, src0, mask, width, acc); call_new(dst1, src1, mask, width, acc); From 9d3eb75cf637e6f2a664ad3ab67c4f785226f62e Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 8 Nov 2017 14:58:36 -0300 Subject: [PATCH 0790/2557] avcodec/qsvenc_jpeg: fix copyright header Fixes fate-source after 1926f13a206bfbd99abf536e7424e2b321f2e2ad. Signed-off-by: James Almer --- libavcodec/qsvenc_jpeg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/qsvenc_jpeg.c b/libavcodec/qsvenc_jpeg.c index 3fa17f13abb68..731ec9a014b2d 100644 --- a/libavcodec/qsvenc_jpeg.c +++ b/libavcodec/qsvenc_jpeg.c @@ -1,20 +1,20 @@ /* * Intel MediaSDK QSV based MJPEG encoder * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ From 4878854eefe6d7f4f18fe3b1909f4e9571e18b48 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Mon, 6 Nov 2017 11:32:57 +0530 Subject: [PATCH 0791/2557] avcodec/mips: Improve hevc bi wgt 4 tap hv mc msa functions Use global mask buffer for appropriate mask load. Use immediate unsigned saturation for clip to max saving one vector register. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_biw_msa.c | 1396 ++++++++++++++++++----------- 1 file changed, 872 insertions(+), 524 deletions(-) diff --git a/libavcodec/mips/hevc_mc_biw_msa.c b/libavcodec/mips/hevc_mc_biw_msa.c index 0e5f8a02cfdb9..ea65f00497dd0 100644 --- a/libavcodec/mips/hevc_mc_biw_msa.c +++ b/libavcodec/mips/hevc_mc_biw_msa.c @@ -4495,26 +4495,25 @@ static void hevc_hv_biwgt_4t_4x2_msa(uint8_t *src0_ptr, int32_t dst_stride, const int8_t *filter_x, const int8_t *filter_y, - int32_t height, int32_t weight0, int32_t weight1, int32_t offset0, int32_t offset1, int32_t rnd_val) { + uint64_t tp0, tp1; int32_t offset, weight; - v8i16 in0, in1; + v8i16 in0 = { 0 }; + v16u8 out; v16i8 src0, src1, src2, src3, src4; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec, tmp, weight_vec; v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4; - v4i32 dst0_r, dst1_r, dst0_l; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 dst20, dst31, dst42, dst10, dst32, dst21, dst43, tmp0, tmp1; + v4i32 dst0, dst1, offset_vec, rnd_vec, const_vec; src0_ptr -= (src_stride + 1); @@ -4522,10 +4521,9 @@ static void hevc_hv_biwgt_4t_4x2_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; @@ -4533,56 +4531,44 @@ static void hevc_hv_biwgt_4t_4x2_msa(uint8_t *src0_ptr, weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); - const_vec = __msa_ldi_h(128); + const_vec = __msa_fill_w((128 * weight1)); const_vec <<= 6; offset_vec = __msa_fill_w(offset); - weight_vec = __msa_fill_w(weight); + weight_vec = (v8i16) __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); + offset_vec += const_vec; - LD_SB3(src0_ptr, src_stride, src0, src1, src2); - src0_ptr += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); + LD_SB5(src0_ptr, src_stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); + VSHF_B2_SB(src0, src2, src0, src2, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src3, src1, src3, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src4, src2, src4, mask0, mask1, vec4, vec5); - LD_SB2(src0_ptr, src_stride, src3, src4); - LD_SH2(src1_ptr, src2_stride, in0, in1); - in0 = (v8i16) __msa_ilvr_d((v2i64) in1, (v2i64) in0); - XORI_B2_128_SB(src3, src4); - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - dst32_r = __msa_ilvr_h(dst3, dst2); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - dst43_r = __msa_ilvr_h(dst4, dst3); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_r = (v4i32) __msa_pckev_h((v8i16) dst1_r, (v8i16) dst0_r); + dst20 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst31 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst42 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); - ILVRL_H2_SW(dst1_r, in0, dst0_r, dst0_l); - dst0_r = __msa_dpadd_s_w(offset_vec, (v8i16) dst0_r, (v8i16) weight_vec); - dst0_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst0_l, (v8i16) weight_vec); - SRAR_W2_SW(dst0_r, dst0_l, rnd_vec); - dst0_r = CLIP_SW_0_255(dst0_r); - dst0_l = CLIP_SW_0_255(dst0_l); + ILVRL_H2_SH(dst31, dst20, dst10, dst32); + ILVRL_H2_SH(dst42, dst31, dst21, dst43); + + dst0 = HEVC_FILT_4TAP(dst10, dst32, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21, dst43, filt_h0, filt_h1); + dst0 >>= 6; + dst1 >>= 6; + dst0 = (v4i32) __msa_pckev_h((v8i16) dst1, (v8i16) dst0); - HEVC_PCK_SW_SB2(dst0_l, dst0_r, dst0_r); - ST4x2_UB(dst0_r, dst, dst_stride); + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in0); + + ILVRL_H2_SH(dst0, in0, tmp0, tmp1); + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + SRAR_W2_SW(dst0, dst1, rnd_vec); + tmp = __msa_pckev_h((v8i16) dst1, (v8i16) dst0); + tmp = CLIP_SH_0_255_MAX_SATU(tmp); + out = (v16u8) __msa_pckev_b((v16i8) tmp, (v16i8) tmp); + ST4x2_UB(out, dst, dst_stride); } static void hevc_hv_biwgt_4t_4x4_msa(uint8_t *src0_ptr, @@ -4593,27 +4579,28 @@ static void hevc_hv_biwgt_4t_4x4_msa(uint8_t *src0_ptr, int32_t dst_stride, const int8_t *filter_x, const int8_t *filter_y, - int32_t height, int32_t weight0, int32_t weight1, int32_t offset0, int32_t offset1, int32_t rnd_val) { + uint64_t tp0, tp1; int32_t offset, weight; - v8i16 in0, in1, in2, in3; + v16u8 out; + v8i16 in0 = { 0 }, in1 = { 0 }; v16i8 src0, src1, src2, src3, src4, src5, src6; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v8i16 tmp0, tmp1; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 filter_vec, weight_vec; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 tmp0, tmp1, tmp2, tmp3; + v8i16 dst30, dst41, dst52, dst63; + v8i16 dst10, dst32, dst54, dst21, dst43, dst65; + v4i32 offset_vec, rnd_vec, const_vec; + v4i32 dst0, dst1, dst2, dst3; src0_ptr -= (src_stride + 1); @@ -4621,10 +4608,9 @@ static void hevc_hv_biwgt_4t_4x4_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; @@ -4632,66 +4618,54 @@ static void hevc_hv_biwgt_4t_4x4_msa(uint8_t *src0_ptr, weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); - const_vec = __msa_ldi_h(128); + const_vec = __msa_fill_w((128 * weight1)); const_vec <<= 6; offset_vec = __msa_fill_w(offset); - weight_vec = __msa_fill_w(weight); + weight_vec = (v8i16) __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); + offset_vec += const_vec; - LD_SB3(src0_ptr, src_stride, src0, src1, src2); - src0_ptr += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); + LD_SB7(src0_ptr, src_stride, src0, src1, src2, src3, src4, src5, src6); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); + VSHF_B2_SB(src0, src3, src0, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src4, src1, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src5, src2, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src3, src6, src3, src6, mask0, mask1, vec6, vec7); - LD_SB4(src0_ptr, src_stride, src3, src4, src5, src6); - LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); - ILVR_D2_SH(in1, in0, in3, in2, in0, in1); - XORI_B4_128_SB(src3, src4, src5, src6); - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - dst32_r = __msa_ilvr_h(dst3, dst2); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - dst43_r = __msa_ilvr_h(dst4, dst3); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - dst10_r = __msa_ilvr_h(dst5, dst4); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_r >>= 6; - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - dst21_r = __msa_ilvr_h(dst2, dst5); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_r >>= 6; - PCKEV_H2_SH(dst1_r, dst0_r, dst3_r, dst2_r, tmp0, tmp1); - HEVC_BIW_RND_CLIP2(tmp0, tmp1, in0, in1, - weight_vec, rnd_vec, offset_vec, - tmp0, tmp1); + dst30 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst41 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst52 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst63 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); - tmp0 = (v8i16) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); - ST4x4_UB(tmp0, tmp0, 0, 1, 2, 3, dst, dst_stride); + ILVRL_H2_SH(dst41, dst30, dst10, dst43); + ILVRL_H2_SH(dst52, dst41, dst21, dst54); + ILVRL_H2_SH(dst63, dst52, dst32, dst65); + dst0 = HEVC_FILT_4TAP(dst10, dst32, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21, dst43, filt_h0, filt_h1); + dst2 = HEVC_FILT_4TAP(dst32, dst54, filt_h0, filt_h1); + dst3 = HEVC_FILT_4TAP(dst43, dst65, filt_h0, filt_h1); + SRA_4V(dst0, dst1, dst2, dst3, 6); + PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp1, tmp3); + + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in0); + src1_ptr += (2 * src2_stride); + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in1); + + ILVRL_H2_SH(tmp1, in0, tmp0, tmp1); + ILVRL_H2_SH(tmp3, in1, tmp2, tmp3); + + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp0, tmp1); + CLIP_SH2_0_255_MAX_SATU(tmp0, tmp1); + out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); } static void hevc_hv_biwgt_4t_4multx8mult_msa(uint8_t *src0_ptr, @@ -4710,21 +4684,24 @@ static void hevc_hv_biwgt_4t_4multx8mult_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t loop_cnt; + uint64_t tp0, tp1; int32_t offset, weight; - v8i16 in0, in1, in2, in3, in4, in5, in6, in7; + v16u8 out0, out1; + v8i16 in0 = { 0 }, in1 = { 0 }, in2 = { 0 }, in3 = { 0 }; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8, dst9; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r, dst6_r, dst7_r; - v8i16 tmp0, tmp1, tmp2, tmp3; + v8i16 filter_vec, weight_vec; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + v8i16 dst10, dst21, dst22, dst73, dst84, dst95, dst106; v8i16 dst10_r, dst32_r, dst54_r, dst76_r; v8i16 dst21_r, dst43_r, dst65_r, dst87_r; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 dst98_r, dst109_r; + v4i32 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v4i32 offset_vec, rnd_vec, const_vec; src0_ptr -= (src_stride + 1); @@ -4732,10 +4709,9 @@ static void hevc_hv_biwgt_4t_4multx8mult_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; @@ -4743,98 +4719,96 @@ static void hevc_hv_biwgt_4t_4multx8mult_msa(uint8_t *src0_ptr, weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); - const_vec = __msa_ldi_h(128); + const_vec = __msa_fill_w((128 * weight1)); const_vec <<= 6; offset_vec = __msa_fill_w(offset); - weight_vec = __msa_fill_w(weight); + weight_vec = (v8i16) __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); + offset_vec += const_vec; LD_SB3(src0_ptr, src_stride, src0, src1, src2); src0_ptr += (3 * src_stride); XORI_B3_128_SB(src0, src1, src2); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); + VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src2, src1, src2, mask0, mask1, vec2, vec3); + dst10 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst21 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + ILVRL_H2_SH(dst21, dst10, dst10_r, dst21_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst21, 1); for (loop_cnt = height >> 3; loop_cnt--;) { LD_SB8(src0_ptr, src_stride, src3, src4, src5, src6, src7, src8, src9, src10); src0_ptr += (8 * src_stride); - LD_SH8(src1_ptr, src2_stride, in0, in1, in2, in3, in4, in5, in6, in7); - src1_ptr += (8 * src2_stride); - ILVR_D2_SH(in1, in0, in3, in2, in0, in1); - ILVR_D2_SH(in5, in4, in7, in6, in2, in3); XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - dst32_r = __msa_ilvr_h(dst3, dst2); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - dst43_r = __msa_ilvr_h(dst4, dst3); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - dst54_r = __msa_ilvr_h(dst5, dst4); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); - dst2_r >>= 6; - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); - dst65_r = __msa_ilvr_h(dst6, dst5); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); - dst3_r >>= 6; - VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); - dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); - dst76_r = __msa_ilvr_h(dst7, dst6); - dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); - dst4_r >>= 6; - VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec0, vec1); - dst8 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst8, dst8); - dst87_r = __msa_ilvr_h(dst8, dst7); - dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); - dst5_r >>= 6; - VSHF_B2_SB(src9, src9, src9, src9, mask0, mask1, vec0, vec1); - dst9 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst9, dst9); - dst10_r = __msa_ilvr_h(dst9, dst8); - dst6_r = HEVC_FILT_4TAP(dst76_r, dst10_r, filt_h0, filt_h1); - dst6_r >>= 6; - VSHF_B2_SB(src10, src10, src10, src10, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - dst21_r = __msa_ilvr_h(dst2, dst9); - dst7_r = HEVC_FILT_4TAP(dst87_r, dst21_r, filt_h0, filt_h1); - dst7_r >>= 6; - PCKEV_H4_SH(dst1_r, dst0_r, dst3_r, dst2_r, - dst5_r, dst4_r, dst7_r, dst6_r, tmp0, tmp1, tmp2, tmp3); - HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, - in0, in1, in2, in3, - weight_vec, rnd_vec, offset_vec, - tmp0, tmp1, tmp2, tmp3); + VSHF_B2_SB(src3, src7, src3, src7, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src8, src4, src8, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src9, src5, src9, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src10, src6, src10, mask0, mask1, vec6, vec7); + + dst73 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst84 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst95 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst106 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + dst32_r = __msa_ilvr_h(dst73, dst22); + ILVRL_H2_SH(dst84, dst73, dst43_r, dst87_r); + ILVRL_H2_SH(dst95, dst84, dst54_r, dst98_r); + ILVRL_H2_SH(dst106, dst95, dst65_r, dst109_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst73, 1); + dst76_r = __msa_ilvr_h(dst22, dst106); - PCKEV_B2_SH(tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); - ST4x8_UB(tmp0, tmp1, dst, dst_stride); + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in0); + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in1); + + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in2); + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in3); + + dst0 = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst2 = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst3 = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst4 = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); + dst5 = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); + dst6 = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7 = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + SRA_4V(dst0, dst1, dst2, dst3, 6); + SRA_4V(dst4, dst5, dst6, dst7, 6); + PCKEV_H4_SW(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, dst0, dst1, + dst2, dst3); + ILVRL_H2_SH(dst0, in0, tmp0, tmp1); + ILVRL_H2_SH(dst1, in1, tmp2, tmp3); + ILVRL_H2_SH(dst2, in2, tmp4, tmp5); + ILVRL_H2_SH(dst3, in3, tmp6, tmp7); + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + dst4 = __msa_dpadd_s_w(offset_vec, tmp4, weight_vec); + dst5 = __msa_dpadd_s_w(offset_vec, tmp5, weight_vec); + dst6 = __msa_dpadd_s_w(offset_vec, tmp6, weight_vec); + dst7 = __msa_dpadd_s_w(offset_vec, tmp7, weight_vec); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); + PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, tmp0, tmp1, + tmp2, tmp3); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST4x8_UB(out0, out1, dst, dst_stride); dst += (8 * dst_stride); + + dst10_r = dst98_r; + dst21_r = dst109_r; + dst22 = (v8i16) __msa_splati_d((v2i64) dst106, 1); } } @@ -4856,13 +4830,11 @@ static void hevc_hv_biwgt_4t_4w_msa(uint8_t *src0_ptr, if (2 == height) { hevc_hv_biwgt_4t_4x2_msa(src0_ptr, src_stride, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, - height, weight0, weight1, offset0, offset1, - rnd_val); + weight0, weight1, offset0, offset1, rnd_val); } else if (4 == height) { hevc_hv_biwgt_4t_4x4_msa(src0_ptr, src_stride, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, - height, weight0, weight1, offset0, offset1, - rnd_val); + weight0, weight1, offset0, offset1, rnd_val); } else if (0 == (height % 8)) { hevc_hv_biwgt_4t_4multx8mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, @@ -4887,22 +4859,28 @@ static void hevc_hv_biwgt_4t_6w_msa(uint8_t *src0_ptr, int32_t offset1, int32_t rnd_val) { - uint32_t loop_cnt; + uint32_t tpw0, tpw1, tpw2, tpw3; + uint64_t tp0, tp1; int32_t offset, weight; - v16i8 src0, src1, src2, src3, src4, src5, src6; - v8i16 in0, in1, in2, in3; + v16u8 out0, out1, out2; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v8i16 in0 = { 0 }, in1 = { 0 }, in2 = { 0 }, in3 = { 0 }; + v8i16 in4 = { 0 }, in5 = { 0 }; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1, filter_vec; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; + v8i16 dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6, dsth7, dsth8, dsth9; + v8i16 dsth10, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, weight_vec; + v8i16 dst10_r, dst32_r, dst54_r, dst76_r, dst98_r, dst21_r, dst43_r; + v8i16 dst65_r, dst87_r, dst109_r, dst10_l, dst32_l, dst54_l, dst76_l; + v8i16 dst98_l, dst21_l, dst43_l, dst65_l, dst87_l, dst109_l; + v8i16 dst1021_l, dst3243_l, dst5465_l, dst7687_l, dst98109_l; v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; - v8i16 tmp0, tmp1, tmp2, tmp3; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; - v8i16 dst10_l, dst32_l, dst21_l, dst43_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v4i32 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v4i32 dst4_r, dst5_r, dst6_r, dst7_r; + v4i32 offset_vec, rnd_vec, const_vec; src0_ptr -= (src_stride + 1); @@ -4910,10 +4888,9 @@ static void hevc_hv_biwgt_4t_6w_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; @@ -4921,11 +4898,12 @@ static void hevc_hv_biwgt_4t_6w_msa(uint8_t *src0_ptr, weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); - const_vec = __msa_ldi_h(128); + const_vec = __msa_fill_w((128 * weight1)); const_vec <<= 6; offset_vec = __msa_fill_w(offset); - weight_vec = __msa_fill_w(weight); + weight_vec = (v8i16) __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); + offset_vec += const_vec; LD_SB3(src0_ptr, src_stride, src0, src1, src2); src0_ptr += (3 * src_stride); @@ -4934,72 +4912,120 @@ static void hevc_hv_biwgt_4t_6w_msa(uint8_t *src0_ptr, VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - - ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); - ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); + dsth0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); - for (loop_cnt = height >> 2; loop_cnt--;) { - LD_SB4(src0_ptr, src_stride, src3, src4, src5, src6); - src0_ptr += (4 * src_stride); - LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); - src1_ptr += (4 * src2_stride); - XORI_B4_128_SB(src3, src4, src5, src6); - - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + ILVRL_H2_SH(dsth1, dsth0, dst10_r, dst10_l); + ILVRL_H2_SH(dsth2, dsth1, dst21_r, dst21_l); - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; + LD_SB8(src0_ptr, src_stride, src3, src4, src5, src6, src7, src8, src9, + src10); + XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; + dsth3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - ILVRL_H2_SH(dst5, dst4, dst10_r, dst10_l); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_l = HEVC_FILT_4TAP(dst32_l, dst10_l, filt_h0, filt_h1); - dst2_r >>= 6; - dst2_l >>= 6; - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - ILVRL_H2_SH(dst2, dst5, dst21_r, dst21_l); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_l = HEVC_FILT_4TAP(dst43_l, dst21_l, filt_h0, filt_h1); - dst3_r >>= 6; - dst3_l >>= 6; - PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, tmp0, tmp1, tmp2, tmp3); - HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, - in0, in1, in2, in3, - weight_vec, rnd_vec, offset_vec, - tmp0, tmp1, tmp2, tmp3); + VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src9, src9, src9, src9, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src10, src10, src10, src10, mask0, mask1, vec6, vec7); + + dsth7 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth8 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth9 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth10 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + ILVRL_H2_SH(dsth3, dsth2, dst32_r, dst32_l); + ILVRL_H2_SH(dsth4, dsth3, dst43_r, dst43_l); + ILVRL_H2_SH(dsth5, dsth4, dst54_r, dst54_l); + ILVRL_H2_SH(dsth6, dsth5, dst65_r, dst65_l); + ILVRL_H2_SH(dsth7, dsth6, dst76_r, dst76_l); + ILVRL_H2_SH(dsth8, dsth7, dst87_r, dst87_l); + ILVRL_H2_SH(dsth9, dsth8, dst98_r, dst98_l); + ILVRL_H2_SH(dsth10, dsth9, dst109_r, dst109_l); + PCKEV_D2_SH(dst21_l, dst10_l, dst43_l, dst32_l, dst1021_l, dst3243_l); + PCKEV_D2_SH(dst65_l, dst54_l, dst87_l, dst76_l, dst5465_l, dst7687_l); + dst98109_l = (v8i16) __msa_pckev_d((v2i64) dst109_l, (v2i64) dst98_l); - PCKEV_B2_SH(tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); - ST6x4_UB(tmp0, tmp1, dst, dst_stride); - dst += (4 * dst_stride); - } + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); + dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); + dst6_r = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7_r = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst1021_l, dst3243_l, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst3243_l, dst5465_l, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst5465_l, dst7687_l, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst7687_l, dst98109_l, filt_h0, filt_h1); + SRA_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SRA_4V(dst4_r, dst5_r, dst6_r, dst7_r, 6); + SRA_4V(dst0_l, dst1_l, dst2_l, dst3_l, 6); + PCKEV_H2_SW(dst1_r, dst0_r, dst3_r, dst2_r, dst0, dst1); + PCKEV_H2_SW(dst5_r, dst4_r, dst7_r, dst6_r, dst2, dst3); + + LD2(src1_ptr, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in0); + LD2(src1_ptr + 2 * src2_stride, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in1); + + LD2(src1_ptr + 4 * src2_stride, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in2); + LD2(src1_ptr + 6 * src2_stride, src2_stride, tp0, tp1); + INSERT_D2_SH(tp0, tp1, in3); + + ILVRL_H2_SH(dst0, in0, tmp0, tmp1); + ILVRL_H2_SH(dst1, in1, tmp2, tmp3); + ILVRL_H2_SH(dst2, in2, tmp4, tmp5); + ILVRL_H2_SH(dst3, in3, tmp6, tmp7); + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + dst4 = __msa_dpadd_s_w(offset_vec, tmp4, weight_vec); + dst5 = __msa_dpadd_s_w(offset_vec, tmp5, weight_vec); + dst6 = __msa_dpadd_s_w(offset_vec, tmp6, weight_vec); + dst7 = __msa_dpadd_s_w(offset_vec, tmp7, weight_vec); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); + PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, tmp0, tmp1, + tmp2, tmp3); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST4x8_UB(out0, out1, dst, dst_stride); + + PCKEV_H2_SW(dst1_l, dst0_l, dst3_l, dst2_l, dst4, dst5); + + LW4(src1_ptr + 4, src2_stride, tpw0, tpw1, tpw2, tpw3); + src1_ptr += (4 * src2_stride); + INSERT_W4_SH(tpw0, tpw1, tpw2, tpw3, in4); + LW4(src1_ptr + 4, src2_stride, tpw0, tpw1, tpw2, tpw3); + INSERT_W4_SH(tpw0, tpw1, tpw2, tpw3, in5); + + ILVRL_H2_SH(dst4, in4, tmp0, tmp1); + ILVRL_H2_SH(dst5, in5, tmp2, tmp3); + + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp4, tmp5); + + CLIP_SH2_0_255_MAX_SATU(tmp4, tmp5); + out2 = (v16u8) __msa_pckev_b((v16i8) tmp5, (v16i8) tmp4); + ST2x4_UB(out2, 0, dst + 4, dst_stride); + dst += 4 * dst_stride; + ST2x4_UB(out2, 4, dst + 4, dst_stride); } static void hevc_hv_biwgt_4t_8x2_msa(uint8_t *src0_ptr, @@ -5010,7 +5036,6 @@ static void hevc_hv_biwgt_4t_8x2_msa(uint8_t *src0_ptr, int32_t dst_stride, const int8_t *filter_x, const int8_t *filter_y, - int32_t height, int32_t weight0, int32_t weight1, int32_t offset0, @@ -5018,20 +5043,21 @@ static void hevc_hv_biwgt_4t_8x2_msa(uint8_t *src0_ptr, int32_t rnd_val) { int32_t weight, offset; + v16u8 out; v16i8 src0, src1, src2, src3, src4; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; + v8i16 filter_vec, weight_vec; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; v8i16 dst0, dst1, dst2, dst3, dst4; v8i16 in0, in1; v4i32 dst0_r, dst0_l, dst1_r, dst1_l; v8i16 dst10_r, dst32_r, dst21_r, dst43_r; v8i16 dst10_l, dst32_l, dst21_l, dst43_l; - v8i16 tmp0, tmp1; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 tmp0, tmp1, tmp2, tmp3; + v4i32 offset_vec, rnd_vec, const_vec; src0_ptr -= (src_stride + 1); @@ -5039,10 +5065,9 @@ static void hevc_hv_biwgt_4t_8x2_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; @@ -5050,61 +5075,177 @@ static void hevc_hv_biwgt_4t_8x2_msa(uint8_t *src0_ptr, weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); - const_vec = __msa_ldi_h(128); + const_vec = __msa_fill_w((128 * weight1)); const_vec <<= 6; offset_vec = __msa_fill_w(offset); - weight_vec = __msa_fill_w(weight); + weight_vec = (v8i16) __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); + offset_vec += const_vec; - LD_SB3(src0_ptr, src_stride, src0, src1, src2); - src0_ptr += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); + LD_SB5(src0_ptr, src_stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + + LD_SH2(src1_ptr, src2_stride, in0, in1); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec8, vec9); + + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec8, vec9, filt0, filt1); ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); + ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + PCKEV_H2_SH(dst0_l, dst0_r, dst1_l, dst1_r, tmp1, tmp3); + + ILVRL_H2_SH(tmp1, in0, tmp0, tmp1); + ILVRL_H2_SH(tmp3, in1, tmp2, tmp3); + + dst0_r = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst0_l = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst1_r = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst1_l = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + SRAR_W4_SW(dst0_r, dst0_l, dst1_r, dst1_l, rnd_vec); + PCKEV_H2_SH(dst0_l, dst0_r, dst1_l, dst1_r, tmp0, tmp1); + CLIP_SH2_0_255_MAX_SATU(tmp0, tmp1); + out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); + ST8x2_UB(out, dst, dst_stride); +} - LD_SB2(src0_ptr, src_stride, src3, src4); +static void hevc_hv_biwgt_4t_8multx4_msa(uint8_t *src0_ptr, + int32_t src_stride, + int16_t *src1_ptr, + int32_t src2_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_x, + const int8_t *filter_y, + int32_t weight0, + int32_t weight1, + int32_t offset0, + int32_t offset1, + int32_t rnd_val, + int32_t width8mult) +{ + int32_t weight, offset; + uint32_t cnt; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4, src5, src6, mask0, mask1; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 filt0, filt1, filt_h0, filt_h1, filter_vec, weight_vec; + v8i16 dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, in0, in1, in2, in3; + v8i16 dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + v4i32 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v4i32 offset_vec, rnd_vec, const_vec; - LD_SH2(src1_ptr, src2_stride, in0, in1); - XORI_B2_128_SB(src3, src4); + src0_ptr -= (src_stride + 1); - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + filter_vec = LD_SH(filter_x); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - tmp0 = __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - tmp1 = __msa_pckev_h((v8i16) dst1_l, (v8i16) dst1_r); + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; - HEVC_BIW_RND_CLIP2(tmp0, tmp1, in0, in1, - weight_vec, rnd_vec, offset_vec, - tmp0, tmp1); - tmp0 = (v8i16) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); - ST8x2_UB(tmp0, dst, dst_stride); + offset = (offset0 + offset1) << rnd_val; + weight0 = weight0 & 0x0000FFFF; + weight = weight0 | (weight1 << 16); + + const_vec = __msa_fill_w((128 * weight1)); + const_vec <<= 6; + offset_vec = __msa_fill_w(offset); + rnd_vec = __msa_fill_w(rnd_val + 1); + offset_vec += const_vec; + weight_vec = (v8i16) __msa_fill_w(weight); + + for (cnt = width8mult; cnt--;) { + LD_SB7(src0_ptr, src_stride, src0, src1, src2, src3, src4, src5, src6); + src0_ptr += 8; + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + LD_SH4(src1_ptr, src2_stride, in0, in1, in2, in3); + src1_ptr += 8; + + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + + dsth0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + + ILVRL_H2_SH(dsth1, dsth0, dst10_r, dst10_l); + ILVRL_H2_SH(dsth2, dsth1, dst21_r, dst21_l); + + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + + dsth3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + ILVRL_H2_SH(dsth3, dsth2, dst32_r, dst32_l); + ILVRL_H2_SH(dsth4, dsth3, dst43_r, dst43_l); + ILVRL_H2_SH(dsth5, dsth4, dst54_r, dst54_l); + ILVRL_H2_SH(dsth6, dsth5, dst65_r, dst65_l); + + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); + + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + PCKEV_H4_SW(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, + dst3_r, dst0, dst1, dst2, dst3); + + ILVRL_H2_SH(dst0, in0, tmp0, tmp1); + ILVRL_H2_SH(dst1, in1, tmp2, tmp3); + ILVRL_H2_SH(dst2, in2, tmp4, tmp5); + ILVRL_H2_SH(dst3, in3, tmp6, tmp7); + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + dst4 = __msa_dpadd_s_w(offset_vec, tmp4, weight_vec); + dst5 = __msa_dpadd_s_w(offset_vec, tmp5, weight_vec); + dst6 = __msa_dpadd_s_w(offset_vec, tmp6, weight_vec); + dst7 = __msa_dpadd_s_w(offset_vec, tmp7, weight_vec); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); + PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, + tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST8x4_UB(out0, out1, dst, dst_stride); + dst += 8; + } } static void hevc_hv_biwgt_4t_8x6_msa(uint8_t *src0_ptr, @@ -5115,7 +5256,6 @@ static void hevc_hv_biwgt_4t_8x6_msa(uint8_t *src0_ptr, int32_t dst_stride, const int8_t *filter_x, const int8_t *filter_y, - int32_t height, int32_t weight0, int32_t weight1, int32_t offset0, @@ -5123,14 +5263,16 @@ static void hevc_hv_biwgt_4t_8x6_msa(uint8_t *src0_ptr, int32_t rnd_val) { uint32_t offset, weight; + v16u8 out0, out1, out2; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; + v8i16 filter_vec, weight_vec; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; + v16i8 vec10, vec11, vec12, vec13, vec14, vec15, vec16, vec17; + v8i16 dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6, dsth7, dsth8; v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; v4i32 dst4_r, dst4_l, dst5_r, dst5_l; v8i16 dst10_r, dst32_r, dst10_l, dst32_l; @@ -5138,8 +5280,9 @@ static void hevc_hv_biwgt_4t_8x6_msa(uint8_t *src0_ptr, v8i16 dst54_r, dst54_l, dst65_r, dst65_l; v8i16 dst76_r, dst76_l, dst87_r, dst87_l; v8i16 in0, in1, in2, in3, in4, in5; - v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + v4i32 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v4i32 offset_vec, rnd_vec, const_vec; src0_ptr -= (src_stride + 1); @@ -5147,10 +5290,9 @@ static void hevc_hv_biwgt_4t_8x6_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; @@ -5158,121 +5300,103 @@ static void hevc_hv_biwgt_4t_8x6_msa(uint8_t *src0_ptr, weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); - const_vec = __msa_ldi_h(128); + const_vec = __msa_fill_w((128 * weight1)); const_vec <<= 6; offset_vec = __msa_fill_w(offset); - weight_vec = __msa_fill_w(weight); + weight_vec = (v8i16) __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); + offset_vec += const_vec; - LD_SB3(src0_ptr, src_stride, src0, src1, src2); - src0_ptr += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); + LD_SB5(src0_ptr, src_stride, src0, src1, src2, src3, src4); + src0_ptr += (5 * src_stride); + LD_SB4(src0_ptr, src_stride, src5, src6, src7, src8); + + XORI_B5_128_SB(src0, src1, src2, src3, src4); + XORI_B4_128_SB(src5, src6, src7, src8); + + LD_SH6(src1_ptr, src2_stride, in0, in1, in2, in3, in4, in5); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - - ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); - ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); - - LD_SB2(src0_ptr, src_stride, src3, src4); - src0_ptr += (2 * src_stride); - XORI_B2_128_SB(src3, src4); - LD_SH6(src1_ptr, src2_stride, in0, in1, in2, in3, in4, in5); - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec8, vec9); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec10, vec11); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec12, vec13); + VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec14, vec15); + VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec16, vec17); + + dsth0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + dsth4 = HEVC_FILT_4TAP_SH(vec8, vec9, filt0, filt1); + dsth5 = HEVC_FILT_4TAP_SH(vec10, vec11, filt0, filt1); + dsth6 = HEVC_FILT_4TAP_SH(vec12, vec13, filt0, filt1); + dsth7 = HEVC_FILT_4TAP_SH(vec14, vec15, filt0, filt1); + dsth8 = HEVC_FILT_4TAP_SH(vec16, vec17, filt0, filt1); + + ILVRL_H2_SH(dsth1, dsth0, dst10_r, dst10_l); + ILVRL_H2_SH(dsth2, dsth1, dst21_r, dst21_l); + ILVRL_H2_SH(dsth3, dsth2, dst32_r, dst32_l); + ILVRL_H2_SH(dsth4, dsth3, dst43_r, dst43_l); + ILVRL_H2_SH(dsth5, dsth4, dst54_r, dst54_l); + ILVRL_H2_SH(dsth6, dsth5, dst65_r, dst65_l); + ILVRL_H2_SH(dsth7, dsth6, dst76_r, dst76_l); + ILVRL_H2_SH(dsth8, dsth7, dst87_r, dst87_l); - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - tmp0 = __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); - - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - tmp1 = __msa_pckev_h((v8i16) dst1_l, (v8i16) dst1_r); - - LD_SB2(src0_ptr, src_stride, src5, src6); - src0_ptr += (2 * src_stride); - XORI_B2_128_SB(src5, src6); - - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); - dst2_r >>= 6; - dst2_l >>= 6; - tmp2 = __msa_pckev_h((v8i16) dst2_l, (v8i16) dst2_r); - - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); - - ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); - dst3_r >>= 6; - dst3_l >>= 6; - tmp3 = __msa_pckev_h((v8i16) dst3_l, (v8i16) dst3_r); - - HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, - in0, in1, in2, in3, - weight_vec, rnd_vec, offset_vec, - tmp0, tmp1, tmp2, tmp3); - - PCKEV_B2_SH(tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); - ST8x4_UB(tmp0, tmp1, dst, dst_stride); - dst += (4 * dst_stride); - - LD_SB2(src0_ptr, src_stride, src7, src8); - XORI_B2_128_SB(src7, src8); - - VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); - dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); - - ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); dst4_l = HEVC_FILT_4TAP(dst54_l, dst76_l, filt_h0, filt_h1); - dst4_r >>= 6; - dst4_l >>= 6; - tmp4 = __msa_pckev_h((v8i16) dst4_l, (v8i16) dst4_r); - - VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec0, vec1); - dst8 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst8, dst8); - - ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); dst5_l = HEVC_FILT_4TAP(dst65_l, dst87_l, filt_h0, filt_h1); - dst5_r >>= 6; - dst5_l >>= 6; - tmp5 = __msa_pckev_h((v8i16) dst5_l, (v8i16) dst5_r); - HEVC_BIW_RND_CLIP2(tmp4, tmp5, in4, in5, - weight_vec, rnd_vec, offset_vec, - tmp4, tmp5); - - tmp4 = (v8i16) __msa_pckev_b((v16i8) tmp5, (v16i8) tmp4); - ST8x2_UB(tmp4, dst, dst_stride); + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + SRA_4V(dst4_r, dst4_l, dst5_r, dst5_l, 6); + PCKEV_H4_SW(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, dst3_r, + dst0, dst1, dst2, dst3); + + ILVRL_H2_SH(dst0, in0, tmp0, tmp1); + ILVRL_H2_SH(dst1, in1, tmp2, tmp3); + ILVRL_H2_SH(dst2, in2, tmp4, tmp5); + ILVRL_H2_SH(dst3, in3, tmp6, tmp7); + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + dst4 = __msa_dpadd_s_w(offset_vec, tmp4, weight_vec); + dst5 = __msa_dpadd_s_w(offset_vec, tmp5, weight_vec); + dst6 = __msa_dpadd_s_w(offset_vec, tmp6, weight_vec); + dst7 = __msa_dpadd_s_w(offset_vec, tmp7, weight_vec); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); + PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, + tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + + PCKEV_H2_SW(dst4_l, dst4_r, dst5_l, dst5_r, dst0, dst1); + ILVRL_H2_SH(dst0, in4, tmp0, tmp1); + ILVRL_H2_SH(dst1, in5, tmp2, tmp3); + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp4, tmp5); + CLIP_SH2_0_255_MAX_SATU(tmp4, tmp5); + out2 = (v16u8) __msa_pckev_b((v16i8) tmp5, (v16i8) tmp4); + ST8x4_UB(out0, out1, dst, dst_stride); + dst += (4 * dst_stride); + ST8x2_UB(out2, dst, dst_stride); } static void hevc_hv_biwgt_4t_8multx4mult_msa(uint8_t *src0_ptr, @@ -5297,20 +5421,22 @@ static void hevc_hv_biwgt_4t_8multx4mult_msa(uint8_t *src0_ptr, uint8_t *src0_ptr_tmp; int16_t *src1_ptr_tmp; uint8_t *dst_tmp; + v16u8 out0, out1; v16i8 src0, src1, src2, src3, src4, src5, src6; v8i16 in0, in1, in2, in3; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; + v8i16 filter_vec; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6; v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; - v8i16 tmp0, tmp1, tmp2, tmp3; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; - v8i16 dst10_l, dst32_l, dst21_l, dst43_l; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + v4i32 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l, weight_vec; + v4i32 offset_vec, rnd_vec, const_vec; src0_ptr -= (src_stride + 1); @@ -5318,10 +5444,9 @@ static void hevc_hv_biwgt_4t_8multx4mult_msa(uint8_t *src0_ptr, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; @@ -5329,11 +5454,12 @@ static void hevc_hv_biwgt_4t_8multx4mult_msa(uint8_t *src0_ptr, weight0 = weight0 & 0x0000FFFF; weight = weight0 | (weight1 << 16); - const_vec = __msa_ldi_h(128); + const_vec = __msa_fill_w((128 * weight1)); const_vec <<= 6; offset_vec = __msa_fill_w(offset); - weight_vec = __msa_fill_w(weight); + weight_vec = (v8i16) __msa_fill_w(weight); rnd_vec = __msa_fill_w(rnd_val + 1); + offset_vec += const_vec; for (cnt = width >> 3; cnt--;) { src0_ptr_tmp = src0_ptr; @@ -5347,15 +5473,12 @@ static void hevc_hv_biwgt_4t_8multx4mult_msa(uint8_t *src0_ptr, VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); + dsth0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); - ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); - ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); + ILVRL_H2_SH(dsth1, dsth0, dst10_r, dst10_l); + ILVRL_H2_SH(dsth2, dsth1, dst21_r, dst21_l); for (loop_cnt = height >> 2; loop_cnt--;) { LD_SB4(src0_ptr_tmp, src_stride, src3, src4, src5, src6); @@ -5365,55 +5488,59 @@ static void hevc_hv_biwgt_4t_8multx4mult_msa(uint8_t *src0_ptr, XORI_B4_128_SB(src3, src4, src5, src6); VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; + dsth3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); + ILVRL_H2_SH(dsth3, dsth2, dst32_r, dst32_l); + ILVRL_H2_SH(dsth4, dsth3, dst43_r, dst43_l); + ILVRL_H2_SH(dsth5, dsth4, dst54_r, dst54_l); + ILVRL_H2_SH(dsth6, dsth5, dst65_r, dst65_l); - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - ILVRL_H2_SH(dst5, dst4, dst10_r, dst10_l); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_l = HEVC_FILT_4TAP(dst32_l, dst10_l, filt_h0, filt_h1); - dst2_r >>= 6; - dst2_l >>= 6; - - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - ILVRL_H2_SH(dst2, dst5, dst21_r, dst21_l); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_l = HEVC_FILT_4TAP(dst43_l, dst21_l, filt_h0, filt_h1); - dst3_r >>= 6; - dst3_l >>= 6; - - PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, tmp0, tmp1, tmp2, tmp3); - HEVC_BIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, - in0, in1, in2, in3, - weight_vec, rnd_vec, offset_vec, - tmp0, tmp1, tmp2, tmp3); - - PCKEV_B2_SH(tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); - ST8x4_UB(tmp0, tmp1, dst_tmp, dst_stride); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); + + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + PCKEV_H4_SW(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, + dst3_r, dst0, dst1, dst2, dst3); + ILVRL_H2_SH(dst0, in0, tmp0, tmp1); + ILVRL_H2_SH(dst1, in1, tmp2, tmp3); + ILVRL_H2_SH(dst2, in2, tmp4, tmp5); + ILVRL_H2_SH(dst3, in3, tmp6, tmp7); + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + dst4 = __msa_dpadd_s_w(offset_vec, tmp4, weight_vec); + dst5 = __msa_dpadd_s_w(offset_vec, tmp5, weight_vec); + dst6 = __msa_dpadd_s_w(offset_vec, tmp6, weight_vec); + dst7 = __msa_dpadd_s_w(offset_vec, tmp7, weight_vec); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); + PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, + tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST8x4_UB(out0, out1, dst_tmp, dst_stride); dst_tmp += (4 * dst_stride); + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dsth2 = dsth6; } src0_ptr += 8; @@ -5440,13 +5567,16 @@ static void hevc_hv_biwgt_4t_8w_msa(uint8_t *src0_ptr, if (2 == height) { hevc_hv_biwgt_4t_8x2_msa(src0_ptr, src_stride, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, - height, weight0, weight1, offset0, offset1, - rnd_val); + weight0, weight1, offset0, offset1, rnd_val); + } else if (4 == height) { + hevc_hv_biwgt_4t_8multx4_msa(src0_ptr, src_stride, src1_ptr, + src2_stride, dst, dst_stride, filter_x, + filter_y, weight0, weight1, offset0, + offset1, rnd_val, 1); } else if (6 == height) { hevc_hv_biwgt_4t_8x6_msa(src0_ptr, src_stride, src1_ptr, src2_stride, dst, dst_stride, filter_x, filter_y, - height, weight0, weight1, offset0, offset1, - rnd_val); + weight0, weight1, offset0, offset1, rnd_val); } else if (0 == (height % 4)) { hevc_hv_biwgt_4t_8multx4mult_msa(src0_ptr, src_stride, src1_ptr, src2_stride, @@ -5471,16 +5601,228 @@ static void hevc_hv_biwgt_4t_12w_msa(uint8_t *src0_ptr, int32_t offset1, int32_t rnd_val) { - hevc_hv_biwgt_4t_8multx4mult_msa(src0_ptr, src_stride, - src1_ptr, src2_stride, - dst, dst_stride, - filter_x, filter_y, height, weight0, - weight1, offset0, offset1, rnd_val, 8); + uint32_t loop_cnt; + uint64_t tp0, tp1; + int32_t offset, weight; + uint8_t *src0_ptr_tmp, *dst_tmp; + int16_t *src1_ptr_tmp; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 mask0, mask1, mask2, mask3; + v8i16 filt0, filt1, filt_h0, filt_h1, filter_vec; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + v8i16 dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6, weight_vec; + v8i16 dst10, dst21, dst22, dst73, dst84, dst95, dst106; + v8i16 dst76_r, dst98_r, dst87_r, dst109_r; + v8i16 in0 = { 0 }, in1 = { 0 }, in2 = { 0 }, in3 = { 0 }; + v8i16 dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + v4i32 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v4i32 offset_vec, rnd_vec, const_vec; + + src0_ptr -= (src_stride + 1); + + filter_vec = LD_SH(filter_x); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + + offset = (offset0 + offset1) << rnd_val; + weight0 = weight0 & 0x0000FFFF; + weight = weight0 | (weight1 << 16); + + const_vec = __msa_fill_w((128 * weight1)); + const_vec <<= 6; + offset_vec = __msa_fill_w(offset); + rnd_vec = __msa_fill_w(rnd_val + 1); + offset_vec += const_vec; + weight_vec = (v8i16) __msa_fill_w(weight); + + src0_ptr_tmp = src0_ptr; + dst_tmp = dst; + src1_ptr_tmp = src1_ptr; + + LD_SB3(src0_ptr_tmp, src_stride, src0, src1, src2); + src0_ptr_tmp += (3 * src_stride); + + XORI_B3_128_SB(src0, src1, src2); + + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + + dsth0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); - hevc_hv_biwgt_4t_4w_msa(src0_ptr + 8, src_stride, src1_ptr + 8, src2_stride, - dst + 8, dst_stride, filter_x, filter_y, - height, weight0, weight1, offset0, - offset1, rnd_val); + ILVRL_H2_SH(dsth1, dsth0, dst10_r, dst10_l); + ILVRL_H2_SH(dsth2, dsth1, dst21_r, dst21_l); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src0_ptr_tmp, src_stride, src3, src4, src5, src6); + src0_ptr_tmp += (4 * src_stride); + XORI_B4_128_SB(src3, src4, src5, src6); + + LD_SH4(src1_ptr_tmp, src2_stride, in0, in1, in2, in3); + src1_ptr_tmp += (4 * src2_stride); + + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + + dsth3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + ILVRL_H2_SH(dsth3, dsth2, dst32_r, dst32_l); + ILVRL_H2_SH(dsth4, dsth3, dst43_r, dst43_l); + ILVRL_H2_SH(dsth5, dsth4, dst54_r, dst54_l); + ILVRL_H2_SH(dsth6, dsth5, dst65_r, dst65_l); + + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); + + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + PCKEV_H4_SW(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, + dst3_r, dst0, dst1, dst2, dst3); + ILVRL_H2_SH(dst0, in0, tmp0, tmp1); + ILVRL_H2_SH(dst1, in1, tmp2, tmp3); + ILVRL_H2_SH(dst2, in2, tmp4, tmp5); + ILVRL_H2_SH(dst3, in3, tmp6, tmp7); + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + dst4 = __msa_dpadd_s_w(offset_vec, tmp4, weight_vec); + dst5 = __msa_dpadd_s_w(offset_vec, tmp5, weight_vec); + dst6 = __msa_dpadd_s_w(offset_vec, tmp6, weight_vec); + dst7 = __msa_dpadd_s_w(offset_vec, tmp7, weight_vec); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); + PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, + tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST8x4_UB(out0, out1, dst_tmp, dst_stride); + dst_tmp += (4 * dst_stride); + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dsth2 = dsth6; + } + + src0_ptr += 8; + dst += 8; + src1_ptr += 8; + + mask2 = LD_SB(ff_hevc_mask_arr + 16); + mask3 = mask2 + 2; + + LD_SB3(src0_ptr, src_stride, src0, src1, src2); + src0_ptr += (3 * src_stride); + XORI_B3_128_SB(src0, src1, src2); + VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); + VSHF_B2_SB(src1, src2, src1, src2, mask2, mask3, vec2, vec3); + + dst10 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst21 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + + ILVRL_H2_SH(dst21, dst10, dst10_r, dst21_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst21, 1); + + for (loop_cnt = 2; loop_cnt--;) { + LD_SB8(src0_ptr, src_stride, src3, src4, src5, src6, src7, src8, src9, + src10); + src0_ptr += (8 * src_stride); + XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); + VSHF_B2_SB(src3, src7, src3, src7, mask2, mask3, vec0, vec1); + VSHF_B2_SB(src4, src8, src4, src8, mask2, mask3, vec2, vec3); + VSHF_B2_SB(src5, src9, src5, src9, mask2, mask3, vec4, vec5); + VSHF_B2_SB(src6, src10, src6, src10, mask2, mask3, vec6, vec7); + + dst73 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst84 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst95 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst106 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + dst32_r = __msa_ilvr_h(dst73, dst22); + ILVRL_H2_SH(dst84, dst73, dst43_r, dst87_r); + ILVRL_H2_SH(dst95, dst84, dst54_r, dst98_r); + ILVRL_H2_SH(dst106, dst95, dst65_r, dst109_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst73, 1); + dst76_r = __msa_ilvr_h(dst22, dst106); + + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in0); + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in1); + + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in2); + LD2(src1_ptr, src2_stride, tp0, tp1); + src1_ptr += 2 * src2_stride; + INSERT_D2_SH(tp0, tp1, in3); + + dst0 = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst2 = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst3 = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst4 = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); + dst5 = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); + dst6 = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7 = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + + SRA_4V(dst0, dst1, dst2, dst3, 6); + SRA_4V(dst4, dst5, dst6, dst7, 6); + PCKEV_H4_SW(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, + dst0, dst1, dst2, dst3); + ILVRL_H2_SH(dst0, in0, tmp0, tmp1); + ILVRL_H2_SH(dst1, in1, tmp2, tmp3); + ILVRL_H2_SH(dst2, in2, tmp4, tmp5); + ILVRL_H2_SH(dst3, in3, tmp6, tmp7); + dst0 = __msa_dpadd_s_w(offset_vec, tmp0, weight_vec); + dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); + dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); + dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); + dst4 = __msa_dpadd_s_w(offset_vec, tmp4, weight_vec); + dst5 = __msa_dpadd_s_w(offset_vec, tmp5, weight_vec); + dst6 = __msa_dpadd_s_w(offset_vec, tmp6, weight_vec); + dst7 = __msa_dpadd_s_w(offset_vec, tmp7, weight_vec); + SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); + SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); + PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, + tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); + ST4x8_UB(out0, out1, dst, dst_stride); + dst += (8 * dst_stride); + + dst10_r = dst98_r; + dst21_r = dst109_r; + dst22 = (v8i16) __msa_splati_d((v2i64) dst106, 1); + } } static void hevc_hv_biwgt_4t_16w_msa(uint8_t *src0_ptr, @@ -5498,11 +5840,17 @@ static void hevc_hv_biwgt_4t_16w_msa(uint8_t *src0_ptr, int32_t offset1, int32_t rnd_val) { - hevc_hv_biwgt_4t_8multx4mult_msa(src0_ptr, src_stride, - src1_ptr, src2_stride, - dst, dst_stride, - filter_x, filter_y, height, weight0, - weight1, offset0, offset1, rnd_val, 16); + if (4 == height) { + hevc_hv_biwgt_4t_8multx4_msa(src0_ptr, src_stride, src1_ptr, + src2_stride, dst, dst_stride, filter_x, + filter_y, weight0, weight1, offset0, + offset1, rnd_val, 2); + } else { + hevc_hv_biwgt_4t_8multx4mult_msa(src0_ptr, src_stride, src1_ptr, + src2_stride, dst, dst_stride, + filter_x, filter_y, height, weight0, + weight1, offset0, offset1, rnd_val, 16); + } } static void hevc_hv_biwgt_4t_24w_msa(uint8_t *src0_ptr, From 350721e9fd6bdec5e9bf024315b64ce29de45bf7 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Mon, 6 Nov 2017 16:20:51 +0530 Subject: [PATCH 0792/2557] avcodec/mips: Improve hevc uni 4 tap hv mc msa functions Use global mask buffer for appropriate mask load. Remove unused macro and table. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_uni_msa.c | 1125 +++++++++++++++-------------- 1 file changed, 566 insertions(+), 559 deletions(-) diff --git a/libavcodec/mips/hevc_mc_uni_msa.c b/libavcodec/mips/hevc_mc_uni_msa.c index 993dad06aa6b0..740c970ca12ad 100644 --- a/libavcodec/mips/hevc_mc_uni_msa.c +++ b/libavcodec/mips/hevc_mc_uni_msa.c @@ -283,25 +283,6 @@ static void copy_width64_msa(uint8_t *src, int32_t src_stride, } } -static const uint8_t mc_filt_mask_arr[16 * 3] = { - /* 8 width cases */ - 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, - /* 4 width cases */ - 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20, - /* 4 width cases */ - 8, 9, 9, 10, 10, 11, 11, 12, 24, 25, 25, 26, 26, 27, 27, 28 -}; - -#define FILT_4TAP_DPADD_S_H(vec0, vec1, filt0, filt1) \ -( { \ - v8i16 tmp0; \ - \ - tmp0 = __msa_dotp_s_h((v16i8) vec0, (v16i8) filt0); \ - tmp0 = __msa_dpadd_s_h(tmp0, (v16i8) vec1, (v16i8) filt1); \ - \ - tmp0; \ -} ) - static void common_hz_8t_4x4_msa(uint8_t *src, int32_t src_stride, uint8_t *dst, int32_t dst_stride, const int8_t *filter) @@ -3109,19 +3090,18 @@ static void hevc_hv_uni_4t_4x2_msa(uint8_t *src, uint8_t *dst, int32_t dst_stride, const int8_t *filter_x, - const int8_t *filter_y, - int32_t height) + const int8_t *filter_y) { + v16u8 out; v16i8 src0, src1, src2, src3, src4; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; - v8i16 filter_vec, const_vec; + v8i16 filter_vec, tmp; v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4; - v4i32 dst0_r, dst1_r; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; + v8i16 dst20, dst31, dst42, dst10, dst32, dst21, dst43; + v4i32 dst0, dst1; src -= (src_stride + 1); @@ -3129,60 +3109,35 @@ static void hevc_hv_uni_4t_4x2_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); - - XORI_B3_128_SB(src0, src1, src2); - - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); - LD_SB2(src, src_stride, src3, src4); - XORI_B2_128_SB(src3, src4); - - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - dst32_r = __msa_ilvr_h(dst3, dst2); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; - - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - dst43_r = __msa_ilvr_h(dst4, dst3); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - - dst0_r = (v4i32) __msa_pckev_h((v8i16) dst1_r, (v8i16) dst0_r); - dst0_r = (v4i32) __msa_srari_h((v8i16) dst0_r, 6); - dst0_r = (v4i32) CLIP_SH_0_255(dst0_r); - dst0_r = (v4i32) __msa_pckev_b((v16i8) dst0_r, (v16i8) dst0_r); + LD_SB5(src, src_stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); - ST4x2_UB(dst0_r, dst, dst_stride); + VSHF_B2_SB(src0, src2, src0, src2, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src3, src1, src3, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src4, src2, src4, mask0, mask1, vec4, vec5); + + dst20 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst31 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst42 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + + ILVRL_H2_SH(dst31, dst20, dst10, dst32); + ILVRL_H2_SH(dst42, dst31, dst21, dst43); + + dst0 = HEVC_FILT_4TAP(dst10, dst32, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21, dst43, filt_h0, filt_h1); + dst0 >>= 6; + dst1 >>= 6; + tmp = __msa_pckev_h((v8i16) dst1, (v8i16) dst0); + tmp = __msa_srari_h(tmp, 6); + tmp = __msa_sat_s_h(tmp, 7); + out = PCKEV_XORI128_UB(tmp, tmp); + ST4x2_UB(out, dst, dst_stride); } static void hevc_hv_uni_4t_4x4_msa(uint8_t *src, @@ -3190,20 +3145,19 @@ static void hevc_hv_uni_4t_4x4_msa(uint8_t *src, uint8_t *dst, int32_t dst_stride, const int8_t *filter_x, - const int8_t *filter_y, - int32_t height) + const int8_t *filter_y) { + v16u8 out; v16i8 src0, src1, src2, src3, src4, src5, src6; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r; - v8i16 out0_r, out1_r; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 filter_vec, tmp0, tmp1; + v8i16 dst30, dst41, dst52, dst63; + v8i16 dst10, dst32, dst54, dst21, dst43, dst65; + v4i32 dst0, dst1, dst2, dst3; src -= (src_stride + 1); @@ -3211,78 +3165,38 @@ static void hevc_hv_uni_4t_4x4_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); - - XORI_B3_128_SB(src0, src1, src2); - - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); - LD_SB4(src, src_stride, src3, src4, src5, src6); - XORI_B4_128_SB(src3, src4, src5, src6); - - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - dst32_r = __msa_ilvr_h(dst3, dst2); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; - - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - dst43_r = __msa_ilvr_h(dst4, dst3); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - dst10_r = __msa_ilvr_h(dst5, dst4); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_r >>= 6; - - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - dst21_r = __msa_ilvr_h(dst2, dst5); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_r >>= 6; - - PCKEV_H2_SH(dst1_r, dst0_r, dst3_r, dst2_r, out0_r, out1_r); - SRARI_H2_SH(out0_r, out1_r, 6); - CLIP_SH2_0_255(out0_r, out1_r); - out0_r = (v8i16) __msa_pckev_b((v16i8) out1_r, (v16i8) out0_r); + LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); - ST4x4_UB(out0_r, out0_r, 0, 1, 2, 3, dst, dst_stride); + VSHF_B2_SB(src0, src3, src0, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src4, src1, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src5, src2, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src3, src6, src3, src6, mask0, mask1, vec6, vec7); + + dst30 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst41 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst52 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst63 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + ILVRL_H2_SH(dst41, dst30, dst10, dst43); + ILVRL_H2_SH(dst52, dst41, dst21, dst54); + ILVRL_H2_SH(dst63, dst52, dst32, dst65); + dst0 = HEVC_FILT_4TAP(dst10, dst32, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21, dst43, filt_h0, filt_h1); + dst2 = HEVC_FILT_4TAP(dst32, dst54, filt_h0, filt_h1); + dst3 = HEVC_FILT_4TAP(dst43, dst65, filt_h0, filt_h1); + SRA_4V(dst0, dst1, dst2, dst3, 6); + PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp0, tmp1); + SRARI_H2_SH(tmp0, tmp1, 6); + SAT_SH2_SH(tmp0, tmp1, 7); + out = PCKEV_XORI128_UB(tmp0, tmp1); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); } static void hevc_hv_uni_4t_4multx8mult_msa(uint8_t *src, @@ -3294,19 +3208,20 @@ static void hevc_hv_uni_4t_4multx8mult_msa(uint8_t *src, int32_t height) { uint32_t loop_cnt; + v16u8 out0, out1; v16i8 src0, src1, src2, src3, src4, src5; v16i8 src6, src7, src8, src9, src10; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8, dst9; + v8i16 filter_vec, tmp0, tmp1, tmp2, tmp3; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 dst10, dst21, dst22, dst73, dst84, dst95, dst106; v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r, dst6_r, dst7_r; v8i16 dst10_r, dst32_r, dst54_r, dst76_r; v8i16 dst21_r, dst43_r, dst65_r, dst87_r; - v8i16 out0_r, out1_r, out2_r, out3_r; + v8i16 dst98_r, dst109_r; src -= (src_stride + 1); @@ -3314,33 +3229,23 @@ static void hevc_hv_uni_4t_4multx8mult_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - LD_SB3(src, src_stride, src0, src1, src2); src += (3 * src_stride); XORI_B3_128_SB(src0, src1, src2); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); + VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src2, src1, src2, mask0, mask1, vec2, vec3); + dst10 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst21 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + ILVRL_H2_SH(dst21, dst10, dst10_r, dst21_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst21, 1); for (loop_cnt = height >> 3; loop_cnt--;) { LD_SB8(src, src_stride, @@ -3349,88 +3254,46 @@ static void hevc_hv_uni_4t_4multx8mult_msa(uint8_t *src, XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + VSHF_B2_SB(src3, src7, src3, src7, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src8, src4, src8, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src9, src5, src9, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src10, src6, src10, mask0, mask1, vec6, vec7); - dst32_r = __msa_ilvr_h(dst3, dst2); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; + dst73 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst84 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst95 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst106 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); + dst32_r = __msa_ilvr_h(dst73, dst22); + ILVRL_H2_SH(dst84, dst73, dst43_r, dst87_r); + ILVRL_H2_SH(dst95, dst84, dst54_r, dst98_r); + ILVRL_H2_SH(dst106, dst95, dst65_r, dst109_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst73, 1); + dst76_r = __msa_ilvr_h(dst22, dst106); - dst43_r = __msa_ilvr_h(dst4, dst3); + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - dst54_r = __msa_ilvr_h(dst5, dst4); dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); - dst2_r >>= 6; - - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); - - dst65_r = __msa_ilvr_h(dst6, dst5); dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); - dst3_r >>= 6; - - /* row 7 */ - VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); - dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); - - dst76_r = __msa_ilvr_h(dst7, dst6); dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); - dst4_r >>= 6; - - /* row 8 */ - VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec0, vec1); - dst8 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst8, dst8); - - dst87_r = __msa_ilvr_h(dst8, dst7); dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); - dst5_r >>= 6; - - /* row 9 */ - VSHF_B2_SB(src9, src9, src9, src9, mask0, mask1, vec0, vec1); - dst9 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst9, dst9); - - dst10_r = __msa_ilvr_h(dst9, dst8); - dst6_r = HEVC_FILT_4TAP(dst76_r, dst10_r, filt_h0, filt_h1); - dst6_r >>= 6; - - /* row 10 */ - VSHF_B2_SB(src10, src10, src10, src10, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - dst21_r = __msa_ilvr_h(dst2, dst9); - dst7_r = HEVC_FILT_4TAP(dst87_r, dst21_r, filt_h0, filt_h1); - dst7_r >>= 6; - + dst6_r = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7_r = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + SRA_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SRA_4V(dst4_r, dst5_r, dst6_r, dst7_r, 6); PCKEV_H4_SH(dst1_r, dst0_r, dst3_r, dst2_r, dst5_r, dst4_r, dst7_r, dst6_r, - out0_r, out1_r, out2_r, out3_r); - - SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 6); - CLIP_SH4_0_255(out0_r, out1_r, out2_r, out3_r); - - PCKEV_B2_SH(out1_r, out0_r, out3_r, out2_r, out0_r, out1_r); - ST4x8_UB(out0_r, out1_r, dst, dst_stride); + tmp0, tmp1, tmp2, tmp3); + SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 6); + SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + ST4x8_UB(out0, out1, dst, dst_stride); dst += (8 * dst_stride); + + dst10_r = dst98_r; + dst21_r = dst109_r; + dst22 = (v8i16) __msa_splati_d((v2i64) dst106, 1); } } @@ -3444,10 +3307,10 @@ static void hevc_hv_uni_4t_4w_msa(uint8_t *src, { if (2 == height) { hevc_hv_uni_4t_4x2_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height); + filter_x, filter_y); } else if (4 == height) { hevc_hv_uni_4t_4x4_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height); + filter_x, filter_y); } else if (0 == (height % 8)) { hevc_hv_uni_4t_4multx8mult_msa(src, src_stride, dst, dst_stride, filter_x, filter_y, height); @@ -3462,19 +3325,23 @@ static void hevc_hv_uni_4t_6w_msa(uint8_t *src, const int8_t *filter_y, int32_t height) { - uint32_t loop_cnt; + v16u8 out0, out1, out2; v16i8 src0, src1, src2, src3, src4, src5, src6; + v16i8 src7, src8, src9, src10; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; + v8i16 filt_h0, filt_h1, filter_vec; + v8i16 dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6, dsth7, dsth8, dsth9; + v8i16 dsth10, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + v4i32 dst4_r, dst5_r, dst6_r, dst7_r; v8i16 dst10_r, dst32_r, dst21_r, dst43_r; v8i16 dst10_l, dst32_l, dst21_l, dst43_l; - v8i16 out0_r, out1_r, out2_r, out3_r; + v8i16 dst54_r, dst76_r, dst98_r, dst65_r, dst87_r, dst109_r; + v8i16 dst98_l, dst65_l, dst54_l, dst76_l, dst87_l, dst109_l; + v8i16 dst1021_l, dst3243_l, dst5465_l, dst7687_l, dst98109_l; src -= (src_stride + 1); @@ -3482,16 +3349,12 @@ static void hevc_hv_uni_4t_6w_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - LD_SB3(src, src_stride, src0, src1, src2); src += (3 * src_stride); @@ -3501,79 +3364,78 @@ static void hevc_hv_uni_4t_6w_msa(uint8_t *src, VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - - ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); - ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); - - for (loop_cnt = height >> 2; loop_cnt--;) { - LD_SB4(src, src_stride, src3, src4, src5, src6); - src += (4 * src_stride); - - XORI_B4_128_SB(src3, src4, src5, src6); - - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - ILVRL_H2_SH(dst5, dst4, dst10_r, dst10_l); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_l = HEVC_FILT_4TAP(dst32_l, dst10_l, filt_h0, filt_h1); - - dst2_r >>= 6; - dst2_l >>= 6; + dsth0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + ILVRL_H2_SH(dsth1, dsth0, dst10_r, dst10_l); + ILVRL_H2_SH(dsth2, dsth1, dst21_r, dst21_l); - ILVRL_H2_SH(dst2, dst5, dst21_r, dst21_l); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_l = HEVC_FILT_4TAP(dst43_l, dst21_l, filt_h0, filt_h1); + LD_SB8(src, src_stride, src3, src4, src5, src6, src7, src8, src9, src10); + XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); - dst3_r >>= 6; - dst3_l >>= 6; + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); - PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - out0_r, out1_r, out2_r, out3_r); + dsth3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); - SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 6); - CLIP_SH4_0_255(out0_r, out1_r, out2_r, out3_r); + VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src9, src9, src9, src9, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src10, src10, src10, src10, mask0, mask1, vec6, vec7); + + dsth7 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth8 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth9 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth10 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + ILVRL_H2_SH(dsth3, dsth2, dst32_r, dst32_l); + ILVRL_H2_SH(dsth4, dsth3, dst43_r, dst43_l); + ILVRL_H2_SH(dsth5, dsth4, dst54_r, dst54_l); + ILVRL_H2_SH(dsth6, dsth5, dst65_r, dst65_l); + ILVRL_H2_SH(dsth7, dsth6, dst76_r, dst76_l); + ILVRL_H2_SH(dsth8, dsth7, dst87_r, dst87_l); + ILVRL_H2_SH(dsth9, dsth8, dst98_r, dst98_l); + ILVRL_H2_SH(dsth10, dsth9, dst109_r, dst109_l); + + PCKEV_D2_SH(dst21_l, dst10_l, dst43_l, dst32_l, dst1021_l, dst3243_l); + PCKEV_D2_SH(dst65_l, dst54_l, dst87_l, dst76_l, dst5465_l, dst7687_l); + dst98109_l = (v8i16) __msa_pckev_d((v2i64) dst109_l, (v2i64) dst98_l); - PCKEV_B2_SH(out1_r, out0_r, out3_r, out2_r, out0_r, out1_r); - ST6x4_UB(out0_r, out1_r, dst, dst_stride); - dst += (4 * dst_stride); - } + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); + dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); + dst6_r = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7_r = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst1021_l, dst3243_l, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst3243_l, dst5465_l, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst5465_l, dst7687_l, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst7687_l, dst98109_l, filt_h0, filt_h1); + SRA_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SRA_4V(dst4_r, dst5_r, dst6_r, dst7_r, 6); + SRA_4V(dst0_l, dst1_l, dst2_l, dst3_l, 6); + PCKEV_H2_SH(dst1_r, dst0_r, dst3_r, dst2_r, tmp0, tmp1); + PCKEV_H2_SH(dst5_r, dst4_r, dst7_r, dst6_r, tmp2, tmp3); + PCKEV_H2_SH(dst1_l, dst0_l, dst3_l, dst2_l, tmp4, tmp5); + SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 6); + SRARI_H2_SH(tmp4, tmp5, 6); + SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3,7); + SAT_SH2_SH(tmp4, tmp5,7); + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + out2 = PCKEV_XORI128_UB(tmp4, tmp5); + ST4x8_UB(out0, out1, dst, dst_stride); + ST2x4_UB(out2, 0, dst + 4, dst_stride); + dst += 4 * dst_stride; + ST2x4_UB(out2, 4, dst + 4, dst_stride); } static void hevc_hv_uni_4t_8x2_msa(uint8_t *src, @@ -3581,16 +3443,15 @@ static void hevc_hv_uni_4t_8x2_msa(uint8_t *src, uint8_t *dst, int32_t dst_stride, const int8_t *filter_x, - const int8_t *filter_y, - int32_t height) + const int8_t *filter_y) { + v16u8 out; v16i8 src0, src1, src2, src3, src4; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1, filter_vec; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; v8i16 dst0, dst1, dst2, dst3, dst4; v4i32 dst0_r, dst0_l, dst1_r, dst1_l; v8i16 dst10_r, dst32_r, dst21_r, dst43_r; @@ -3603,66 +3464,125 @@ static void hevc_hv_uni_4t_8x2_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); - - XORI_B3_128_SB(src0, src1, src2); + LD_SB5(src, src_stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec8, vec9); + + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec8, vec9, filt0, filt1); ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); - - LD_SB2(src, src_stride, src3, src4); - XORI_B2_128_SB(src3, src4); - - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); PCKEV_H2_SH(dst0_l, dst0_r, dst1_l, dst1_r, out0_r, out1_r); SRARI_H2_SH(out0_r, out1_r, 6); - CLIP_SH2_0_255(out0_r, out1_r); - out0_r = (v8i16) __msa_pckev_b((v16i8) out1_r, (v16i8) out0_r); + SAT_SH2_SH(out0_r, out1_r, 7); + out = PCKEV_XORI128_UB(out0_r, out1_r); + ST8x2_UB(out, dst, dst_stride); +} + +static void hevc_hv_uni_4t_8multx4_msa(uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_x, + const int8_t *filter_y, + int32_t width8mult) +{ + uint32_t cnt; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4, src5, src6, mask0, mask1; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 filt0, filt1, filt_h0, filt_h1, filter_vec; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, tmp0, tmp1, tmp2, tmp3; + v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + v8i16 dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; - ST8x2_UB(out0_r, dst, dst_stride); + src -= (src_stride + 1); + + filter_vec = LD_SH(filter_x); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + + for (cnt = width8mult; cnt--;) { + LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); + src += 8; + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + + ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); + ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); + + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); + + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); + + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + + PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, + dst3_r, tmp0, tmp1, tmp2, tmp3); + SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 6); + SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + ST8x4_UB(out0, out1, dst, dst_stride); + dst += 8; + } } static void hevc_hv_uni_4t_8x6_msa(uint8_t *src, @@ -3670,16 +3590,16 @@ static void hevc_hv_uni_4t_8x6_msa(uint8_t *src, uint8_t *dst, int32_t dst_stride, const int8_t *filter_x, - const int8_t *filter_y, - int32_t height) + const int8_t *filter_y) { + v16u8 out0, out1, out2; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1, filter_vec; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; + v16i8 vec10, vec11, vec12, vec13, vec14, vec15, vec16, vec17; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; v4i32 dst4_r, dst4_l, dst5_r, dst5_l; @@ -3695,157 +3615,104 @@ static void hevc_hv_uni_4t_8x6_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); + LD_SB5(src, src_stride, src0, src1, src2, src3, src4); + src += (5 * src_stride); + LD_SB4(src, src_stride, src5, src6, src7, src8); - XORI_B3_128_SB(src0, src1, src2); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + XORI_B4_128_SB(src5, src6, src7, src8); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec8, vec9); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec10, vec11); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec12, vec13); + VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec14, vec15); + VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec16, vec17); + + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec8, vec9, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec10, vec11, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(vec12, vec13, filt0, filt1); + dst7 = HEVC_FILT_4TAP_SH(vec14, vec15, filt0, filt1); + dst8 = HEVC_FILT_4TAP_SH(vec16, vec17, filt0, filt1); ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); - - LD_SB2(src, src_stride, src3, src4); - src += (2 * src_stride); - - XORI_B2_128_SB(src3, src4); - - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); + ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); + ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - - dst0_r >>= 6; - dst0_l >>= 6; - - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - - LD_SB2(src, src_stride, src5, src6); - src += (2 * src_stride); - - XORI_B2_128_SB(src5, src6); - - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); - dst2_r >>= 6; - dst2_l >>= 6; - - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); - - ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); - dst3_r >>= 6; - dst3_l >>= 6; - - LD_SB2(src, src_stride, src7, src8); - src += (2 * src_stride); - - XORI_B2_128_SB(src7, src8); - - /* row 7 */ - VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); - dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); - - ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); dst4_l = HEVC_FILT_4TAP(dst54_l, dst76_l, filt_h0, filt_h1); - - dst4_r >>= 6; - dst4_l >>= 6; - - /* row 8 */ - VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec0, vec1); - dst8 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst8, dst8); - - ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); dst5_l = HEVC_FILT_4TAP(dst65_l, dst87_l, filt_h0, filt_h1); - dst5_r >>= 6; - dst5_l >>= 6; + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + SRA_4V(dst4_r, dst4_l, dst5_r, dst5_l, 6); PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, dst3_r, out0_r, out1_r, out2_r, out3_r); PCKEV_H2_SH(dst4_l, dst4_r, dst5_l, dst5_r, out4_r, out5_r); SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 6); SRARI_H2_SH(out4_r, out5_r, 6); - CLIP_SH4_0_255(out0_r, out1_r, out2_r, out3_r); - CLIP_SH2_0_255(out4_r, out5_r); - - PCKEV_B2_SH(out1_r, out0_r, out3_r, out2_r, out0_r, out1_r); - out2_r = (v8i16) __msa_pckev_b((v16i8) out5_r, (v16i8) out4_r); + SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); + SAT_SH2_SH(out4_r, out5_r, 7); + out0 = PCKEV_XORI128_UB(out0_r, out1_r); + out1 = PCKEV_XORI128_UB(out2_r, out3_r); + out2 = PCKEV_XORI128_UB(out4_r, out5_r); - ST8x4_UB(out0_r, out1_r, dst, dst_stride); + ST8x4_UB(out0, out1, dst, dst_stride); dst += (4 * dst_stride); - ST8x2_UB(out2_r, dst, dst_stride); + ST8x2_UB(out2, dst, dst_stride); } -static void hevc_hv_uni_4t_8w_mult_msa(uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - const int8_t *filter_x, - const int8_t *filter_y, - int32_t height, - int32_t width) +static void hevc_hv_uni_4t_8multx4mult_msa(uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_x, + const int8_t *filter_y, + int32_t height, + int32_t width8mult) { uint32_t loop_cnt, cnt; uint8_t *src_tmp; uint8_t *dst_tmp; + v16u8 out0, out1; v16i8 src0, src1, src2, src3, src4, src5, src6; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1, filter_vec; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; - v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; v8i16 dst10_r, dst32_r, dst21_r, dst43_r; v8i16 dst10_l, dst32_l, dst21_l, dst43_l; + v8i16 dst54_r, dst54_l, dst65_r, dst65_l, dst6; v8i16 out0_r, out1_r, out2_r, out3_r; src -= (src_stride + 1); @@ -3854,17 +3721,13 @@ static void hevc_hv_uni_4t_8w_mult_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; - - for (cnt = width >> 3; cnt--;) { + for (cnt = width8mult; cnt--;) { src_tmp = src; dst_tmp = dst; @@ -3877,79 +3740,62 @@ static void hevc_hv_uni_4t_8w_mult_msa(uint8_t *src, VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); + dst0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); - for (loop_cnt = height >> 2; loop_cnt--;) { + for (loop_cnt = (height >> 2); loop_cnt--;) { LD_SB4(src_tmp, src_stride, src3, src4, src5, src6); src_tmp += (4 * src_stride); XORI_B4_128_SB(src3, src4, src5, src6); - /* row 3 */ VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + + dst3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - - dst0_r >>= 6; - dst0_l >>= 6; - - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - ILVRL_H2_SH(dst5, dst4, dst10_r, dst10_l); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_l = HEVC_FILT_4TAP(dst32_l, dst10_l, filt_h0, filt_h1); - - dst2_r >>= 6; - dst2_l >>= 6; - - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); - ILVRL_H2_SH(dst2, dst5, dst21_r, dst21_l); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_l = HEVC_FILT_4TAP(dst43_l, dst21_l, filt_h0, filt_h1); - - dst3_r >>= 6; - dst3_l >>= 6; + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, dst3_r, out0_r, out1_r, out2_r, out3_r); SRARI_H4_SH(out0_r, out1_r, out2_r, out3_r, 6); - CLIP_SH4_0_255(out0_r, out1_r, out2_r, out3_r); - - PCKEV_B2_SH(out1_r, out0_r, out3_r, out2_r, out0_r, out1_r); - ST8x4_UB(out0_r, out1_r, dst_tmp, dst_stride); + SAT_SH4_SH(out0_r, out1_r, out2_r, out3_r, 7); + out0 = PCKEV_XORI128_UB(out0_r, out1_r); + out1 = PCKEV_XORI128_UB(out2_r, out3_r); + ST8x4_UB(out0, out1, dst_tmp, dst_stride); dst_tmp += (4 * dst_stride); + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dst2 = dst6; } src += 8; @@ -3967,13 +3813,16 @@ static void hevc_hv_uni_4t_8w_msa(uint8_t *src, { if (2 == height) { hevc_hv_uni_4t_8x2_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height); + filter_x, filter_y); + } else if (4 == height) { + hevc_hv_uni_4t_8multx4_msa(src, src_stride, dst, dst_stride, + filter_x, filter_y, 1); } else if (6 == height) { hevc_hv_uni_4t_8x6_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height); + filter_x, filter_y); } else if (0 == (height % 4)) { - hevc_hv_uni_4t_8w_mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, 8); + hevc_hv_uni_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 1); } } @@ -3985,11 +3834,164 @@ static void hevc_hv_uni_4t_12w_msa(uint8_t *src, const int8_t *filter_y, int32_t height) { - hevc_hv_uni_4t_8w_mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, 8); + uint32_t loop_cnt; + uint8_t *src_tmp, *dst_tmp; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 mask0, mask1, mask2, mask3; + v8i16 filt0, filt1, filt_h0, filt_h1, filter_vec, tmp0, tmp1, tmp2, tmp3; + v8i16 dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6; + v8i16 dst10, dst21, dst22, dst73, dst84, dst95, dst106; + v8i16 dst76_r, dst98_r, dst87_r, dst109_r; + v8i16 dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + v4i32 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; - hevc_hv_uni_4t_4w_msa(src + 8, src_stride, dst + 8, dst_stride, - filter_x, filter_y, height); + src -= (src_stride + 1); + + filter_vec = LD_SH(filter_x); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + + src_tmp = src; + dst_tmp = dst; + + LD_SB3(src_tmp, src_stride, src0, src1, src2); + src_tmp += (3 * src_stride); + + XORI_B3_128_SB(src0, src1, src2); + + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + + dsth0 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth1 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth2 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + + ILVRL_H2_SH(dsth1, dsth0, dst10_r, dst10_l); + ILVRL_H2_SH(dsth2, dsth1, dst21_r, dst21_l); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src_tmp, src_stride, src3, src4, src5, src6); + src_tmp += (4 * src_stride); + XORI_B4_128_SB(src3, src4, src5, src6); + + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + + dsth3 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dsth4 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dsth5 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dsth6 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + ILVRL_H2_SH(dsth3, dsth2, dst32_r, dst32_l); + ILVRL_H2_SH(dsth4, dsth3, dst43_r, dst43_l); + ILVRL_H2_SH(dsth5, dsth4, dst54_r, dst54_l); + ILVRL_H2_SH(dsth6, dsth5, dst65_r, dst65_l); + + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); + + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + + PCKEV_H4_SH(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, + dst3_r, tmp0, tmp1, tmp2, tmp3); + SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 6); + SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + ST8x4_UB(out0, out1, dst_tmp, dst_stride); + dst_tmp += (4 * dst_stride); + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dsth2 = dsth6; + } + + src += 8; + dst += 8; + + mask2 = LD_SB(ff_hevc_mask_arr + 16); + mask3 = mask2 + 2; + + LD_SB3(src, src_stride, src0, src1, src2); + src += (3 * src_stride); + XORI_B3_128_SB(src0, src1, src2); + VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); + VSHF_B2_SB(src1, src2, src1, src2, mask2, mask3, vec2, vec3); + + dst10 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst21 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + + ILVRL_H2_SH(dst21, dst10, dst10_r, dst21_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst21, 1); + + for (loop_cnt = 2; loop_cnt--;) { + LD_SB8(src, src_stride, + src3, src4, src5, src6, src7, src8, src9, src10); + src += (8 * src_stride); + XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); + VSHF_B2_SB(src3, src7, src3, src7, mask2, mask3, vec0, vec1); + VSHF_B2_SB(src4, src8, src4, src8, mask2, mask3, vec2, vec3); + VSHF_B2_SB(src5, src9, src5, src9, mask2, mask3, vec4, vec5); + VSHF_B2_SB(src6, src10, src6, src10, mask2, mask3, vec6, vec7); + + dst73 = HEVC_FILT_4TAP_SH(vec0, vec1, filt0, filt1); + dst84 = HEVC_FILT_4TAP_SH(vec2, vec3, filt0, filt1); + dst95 = HEVC_FILT_4TAP_SH(vec4, vec5, filt0, filt1); + dst106 = HEVC_FILT_4TAP_SH(vec6, vec7, filt0, filt1); + + dst32_r = __msa_ilvr_h(dst73, dst22); + ILVRL_H2_SH(dst84, dst73, dst43_r, dst87_r); + ILVRL_H2_SH(dst95, dst84, dst54_r, dst98_r); + ILVRL_H2_SH(dst106, dst95, dst65_r, dst109_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst73, 1); + dst76_r = __msa_ilvr_h(dst22, dst106); + + dst0 = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst2 = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst3 = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst4 = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); + dst5 = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); + dst6 = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7 = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + SRA_4V(dst0, dst1, dst2, dst3, 6); + SRA_4V(dst4, dst5, dst6, dst7, 6); + PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, + tmp0, tmp1, tmp2, tmp3); + SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 6); + SAT_SH4_SH(tmp0, tmp1, tmp2, tmp3, 7); + out0 = PCKEV_XORI128_UB(tmp0, tmp1); + out1 = PCKEV_XORI128_UB(tmp2, tmp3); + ST4x8_UB(out0, out1, dst, dst_stride); + dst += (8 * dst_stride); + + dst10_r = dst98_r; + dst21_r = dst109_r; + dst22 = (v8i16) __msa_splati_d((v2i64) dst106, 1); + } } static void hevc_hv_uni_4t_16w_msa(uint8_t *src, @@ -4000,8 +4002,13 @@ static void hevc_hv_uni_4t_16w_msa(uint8_t *src, const int8_t *filter_y, int32_t height) { - hevc_hv_uni_4t_8w_mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, 16); + if (4 == height) { + hevc_hv_uni_4t_8multx4_msa(src, src_stride, dst, dst_stride, filter_x, + filter_y, 2); + } else { + hevc_hv_uni_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 2); + } } static void hevc_hv_uni_4t_24w_msa(uint8_t *src, @@ -4012,8 +4019,8 @@ static void hevc_hv_uni_4t_24w_msa(uint8_t *src, const int8_t *filter_y, int32_t height) { - hevc_hv_uni_4t_8w_mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, 24); + hevc_hv_uni_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 3); } static void hevc_hv_uni_4t_32w_msa(uint8_t *src, @@ -4024,8 +4031,8 @@ static void hevc_hv_uni_4t_32w_msa(uint8_t *src, const int8_t *filter_y, int32_t height) { - hevc_hv_uni_4t_8w_mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, 32); + hevc_hv_uni_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 4); } #define UNI_MC_COPY(WIDTH) \ From 4fba8728e82ff1b7cd1c5d77eb72c33cb8fb8fb8 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Mon, 6 Nov 2017 16:28:44 +0530 Subject: [PATCH 0793/2557] avcodec/mips: Improve hevc uni weighted 4 tap vt mc msa functions Use global mask buffer for appropriate mask load. Use immediate unsigned saturation for clip to max saving one vector register. Remove unused macro. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_mc_uniw_msa.c | 1052 ++++++++++++++-------------- 1 file changed, 529 insertions(+), 523 deletions(-) diff --git a/libavcodec/mips/hevc_mc_uniw_msa.c b/libavcodec/mips/hevc_mc_uniw_msa.c index 31fec7330e3d2..f9ecb414ba95a 100644 --- a/libavcodec/mips/hevc_mc_uniw_msa.c +++ b/libavcodec/mips/hevc_mc_uniw_msa.c @@ -29,33 +29,6 @@ static const uint8_t ff_hevc_mask_arr[16 * 2] __attribute__((aligned(0x40))) = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; -#define HEVC_UNIW_RND_CLIP2(in0, in1, wgt, offset, rnd, \ - out0_r, out1_r, out0_l, out1_l) \ -{ \ - ILVR_H2_SW(in0, in0, in1, in1, out0_r, out1_r); \ - ILVL_H2_SW(in0, in0, in1, in1, out0_l, out1_l); \ - DOTP_SH4_SW(out0_r, out1_r, out0_l, out1_l, wgt, wgt, wgt, wgt, \ - out0_r, out1_r, out0_l, out1_l); \ - SRAR_W4_SW(out0_r, out1_r, out0_l, out1_l, rnd); \ - ADD4(out0_r, offset, out1_r, offset, \ - out0_l, offset, out1_l, offset, \ - out0_r, out1_r, out0_l, out1_l); \ - out0_r = CLIP_SW_0_255(out0_r); \ - out1_r = CLIP_SW_0_255(out1_r); \ - out0_l = CLIP_SW_0_255(out0_l); \ - out1_l = CLIP_SW_0_255(out1_l); \ -} - -#define HEVC_UNIW_RND_CLIP4(in0, in1, in2, in3, wgt, offset, rnd, \ - out0_r, out1_r, out2_r, out3_r, \ - out0_l, out1_l, out2_l, out3_l) \ -{ \ - HEVC_UNIW_RND_CLIP2(in0, in1, wgt, offset, rnd, \ - out0_r, out1_r, out0_l, out1_l); \ - HEVC_UNIW_RND_CLIP2(in2, in3, wgt, offset, rnd, \ - out2_r, out3_r, out2_l, out3_l); \ -} - #define HEVC_UNIW_RND_CLIP2_MAX_SATU_H(in0_h, in1_h, wgt_w, offset_h, rnd_w, \ out0_h, out1_h) \ { \ @@ -3266,55 +3239,54 @@ static void hevc_vt_uniwgt_4t_4x2_msa(uint8_t *src, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight, int32_t offset, int32_t rnd_val) { + v16u8 out; v16i8 src0, src1, src2, src3, src4; v16i8 src10_r, src32_r, src21_r, src43_r; v16i8 src2110, src4332; - v8i16 dst10; + v8i16 dst0; v4i32 dst0_r, dst0_l; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= src_stride; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); + LD_SB5(src, src_stride, src0, src1, src2, src3, src4); ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); - src2110 = (v16i8) __msa_ilvr_d((v2i64) src21_r, (v2i64) src10_r); - src2110 = (v16i8) __msa_xori_b((v16u8) src2110, 128); - LD_SB2(src, src_stride, src3, src4); ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); - src4332 = (v16i8) __msa_ilvr_d((v2i64) src43_r, (v2i64) src32_r); - src4332 = (v16i8) __msa_xori_b((v16u8) src4332, 128); - - dst10 = const_vec; - DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst10, dst10); - - ILVRL_H2_SW(dst10, dst10, dst0_r, dst0_l); + ILVR_D2_SB(src21_r, src10_r, src43_r, src32_r, src2110, src4332); + XORI_B2_128_SB(src2110, src4332); + dst0 = HEVC_FILT_4TAP_SH(src2110, src4332, filt0, filt1); + ILVRL_H2_SW(dst0, dst0, dst0_r, dst0_l); DOTP_SH2_SW(dst0_r, dst0_l, weight_vec, weight_vec, dst0_r, dst0_l); SRAR_W2_SW(dst0_r, dst0_l, rnd_vec); - ADD2(dst0_r, offset_vec, dst0_l, offset_vec, dst0_r, dst0_l); - dst0_r = CLIP_SW_0_255(dst0_r); - dst0_l = CLIP_SW_0_255(dst0_l); - - HEVC_PCK_SW_SB2(dst0_l, dst0_r, dst0_r); - ST4x2_UB(dst0_r, dst, dst_stride); + dst0 = __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); + dst0 = __msa_adds_s_h(dst0, offset_vec); + dst0 = CLIP_SH_0_255_MAX_SATU(dst0); + out = (v16u8) __msa_pckev_b((v16i8) dst0, (v16i8) dst0); + ST4x2_UB(out, dst, dst_stride); } static void hevc_vt_uniwgt_4t_4x4_msa(uint8_t *src, @@ -3322,55 +3294,53 @@ static void hevc_vt_uniwgt_4t_4x4_msa(uint8_t *src, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight, int32_t offset, int32_t rnd_val) { + v16u8 out; v16i8 src0, src1, src2, src3, src4, src5, src6; v16i8 src10_r, src32_r, src54_r, src21_r, src43_r, src65_r; v16i8 src2110, src4332, src6554; - v8i16 dst10, dst32; - v4i32 dst0_r, dst1_r, dst0_l, dst1_l; + v8i16 dst0, dst1; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= src_stride; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); + LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); - src2110 = (v16i8) __msa_ilvr_d((v2i64) src21_r, (v2i64) src10_r); - src2110 = (v16i8) __msa_xori_b((v16u8) src2110, 128); - - LD_SB4(src, src_stride, src3, src4, src5, src6); ILVR_B4_SB(src3, src2, src4, src3, src5, src4, src6, src5, src32_r, src43_r, src54_r, src65_r); - ILVR_D2_SB(src43_r, src32_r, src65_r, src54_r, src4332, src6554); - XORI_B2_128_SB(src4332, src6554); - - dst10 = const_vec; - DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst10, dst10); - dst32 = const_vec; - DPADD_SB2_SH(src4332, src6554, filt0, filt1, dst32, dst32); - HEVC_UNIW_RND_CLIP2(dst10, dst32, weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst0_l, dst1_l); - - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST4x4_UB(dst0_r, dst0_r, 0, 1, 2, 3, dst, dst_stride); - dst += (4 * dst_stride); + ILVR_D3_SB(src21_r, src10_r, src43_r, src32_r, src65_r, src54_r, + src2110, src4332, src6554); + XORI_B3_128_SB(src2110, src4332, src6554); + dst0 = HEVC_FILT_4TAP_SH(src2110, src4332, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(src4332, src6554, filt0, filt1); + HEVC_UNIW_RND_CLIP2_MAX_SATU_H(dst0, dst1, weight_vec, offset_vec, rnd_vec, + dst0, dst1); + + out = (v16u8) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); + ST4x4_UB(out, out, 0, 1, 2, 3, dst, dst_stride); } static void hevc_vt_uniwgt_4t_4x8multiple_msa(uint8_t *src, @@ -3384,26 +3354,33 @@ static void hevc_vt_uniwgt_4t_4x8multiple_msa(uint8_t *src, int32_t rnd_val) { int32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9; + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v16i8 src10_r, src32_r, src54_r, src76_r, src98_r; v16i8 src21_r, src43_r, src65_r, src87_r, src109_r; v16i8 src2110, src4332, src6554, src8776; - v8i16 dst10, dst32, dst54, dst76; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; - v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; + v16i8 src10998; + v8i16 dst0, dst1, dst2, dst3, filt0, filt1; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= src_stride; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); @@ -3414,39 +3391,31 @@ static void hevc_vt_uniwgt_4t_4x8multiple_msa(uint8_t *src, src2110 = (v16i8) __msa_xori_b((v16u8) src2110, 128); for (loop_cnt = (height >> 3); loop_cnt--;) { - LD_SB6(src, src_stride, src3, src4, src5, src6, src7, src8); - src += (6 * src_stride); + LD_SB8(src, src_stride, + src3, src4, src5, src6, src7, src8, src9, src10); + src += (8 * src_stride); ILVR_B4_SB(src3, src2, src4, src3, src5, src4, src6, src5, src32_r, src43_r, src54_r, src65_r); ILVR_B2_SB(src7, src6, src8, src7, src76_r, src87_r); - ILVR_D3_SB(src43_r, src32_r, src65_r, src54_r, src87_r, src76_r, - src4332, src6554, src8776); - XORI_B3_128_SB(src4332, src6554, src8776); - - dst10 = const_vec; - DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst10, dst10); - dst32 = const_vec; - DPADD_SB2_SH(src4332, src6554, filt0, filt1, dst32, dst32); - dst54 = const_vec; - DPADD_SB2_SH(src6554, src8776, filt0, filt1, dst54, dst54); - - LD_SB2(src, src_stride, src9, src2); - src += (2 * src_stride); - ILVR_B2_SB(src9, src8, src2, src9, src98_r, src109_r); - src2110 = (v16i8) __msa_ilvr_d((v2i64) src109_r, (v2i64) src98_r); - src2110 = (v16i8) __msa_xori_b((v16u8) src2110, 128); - - dst76 = const_vec; - DPADD_SB2_SH(src8776, src2110, filt0, filt1, dst76, dst76); - HEVC_UNIW_RND_CLIP4(dst10, dst32, dst54, dst76, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST4x8_UB(dst0_r, dst1_r, dst, dst_stride); + ILVR_B2_SB(src9, src8, src10, src9, src98_r, src109_r); + ILVR_D4_SB(src43_r, src32_r, src65_r, src54_r, src87_r, src76_r, + src109_r, src98_r, src4332, src6554, src8776, src10998); + XORI_B4_128_SB(src4332, src6554, src8776, src10998); + dst0 = HEVC_FILT_4TAP_SH(src2110, src4332, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(src4332, src6554, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(src6554, src8776, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(src8776, src10998, filt0, filt1); + + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, + weight_vec, offset_vec, rnd_vec, + dst0, dst1, dst2, dst3); + + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + ST4x8_UB(out0, out1, dst, dst_stride); dst += (8 * dst_stride); + + src2 = src10; + src2110 = src10998; } } @@ -3462,10 +3431,10 @@ static void hevc_vt_uniwgt_4t_4w_msa(uint8_t *src, { if (2 == height) { hevc_vt_uniwgt_4t_4x2_msa(src, src_stride, dst, dst_stride, - filter, height, weight, offset, rnd_val); + filter, weight, offset, rnd_val); } else if (4 == height) { hevc_vt_uniwgt_4t_4x4_msa(src, src_stride, dst, dst_stride, - filter, height, weight, offset, rnd_val); + filter, weight, offset, rnd_val); } else if (0 == (height % 8)) { hevc_vt_uniwgt_4t_4x8multiple_msa(src, src_stride, dst, dst_stride, filter, height, weight, offset, @@ -3483,64 +3452,66 @@ static void hevc_vt_uniwgt_4t_6w_msa(uint8_t *src, int32_t offset, int32_t rnd_val) { - int32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4; + v16u8 out0, out1, out2, out3; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v16i8 src10_r, src32_r, src21_r, src43_r; - v8i16 tmp0, tmp1, tmp2, tmp3; + v16i8 src54_r, src65_r, src76_r, src87_r, src98_r, src109_r; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= src_stride; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); LD_SB3(src, src_stride, src0, src1, src2); src += (3 * src_stride); + LD_SB8(src, src_stride, src3, src4, src5, src6, src7, src8, src9, src10); XORI_B3_128_SB(src0, src1, src2); + XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); + ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); + ILVR_B2_SB(src5, src4, src6, src5, src54_r, src65_r); + ILVR_B2_SB(src7, src6, src8, src7, src76_r, src87_r); + ILVR_B2_SB(src9, src8, src10, src9, src98_r, src109_r); + dst0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(src32_r, src54_r, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(src43_r, src65_r, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(src54_r, src76_r, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(src65_r, src87_r, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(src76_r, src98_r, filt0, filt1); + dst7 = HEVC_FILT_4TAP_SH(src87_r, src109_r, filt0, filt1); - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB2(src, src_stride, src3, src4); - src += (2 * src_stride); - XORI_B2_128_SB(src3, src4); - ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); - - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, + weight_vec, offset_vec, rnd_vec, + dst0, dst1, dst2, dst3); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst4, dst5, dst6, dst7, + weight_vec, offset_vec, rnd_vec, + dst4, dst5, dst6, dst7); - LD_SB2(src, src_stride, src1, src2); - src += (2 * src_stride); - XORI_B2_128_SB(src1, src2); - ILVR_B2_SB(src1, src4, src2, src1, src10_r, src21_r); - - tmp2 = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, tmp3, tmp3); - HEVC_UNIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - - ST6x4_UB(dst0_r, dst1_r, dst, dst_stride); - dst += (4 * dst_stride); - } + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + PCKEV_B2_UB(dst5, dst4, dst7, dst6, out2, out3); + ST6x4_UB(out0, out1, dst, dst_stride); + dst += (4 * dst_stride); + ST6x4_UB(out2, out3, dst, dst_stride); } static void hevc_vt_uniwgt_4t_8x2_msa(uint8_t *src, @@ -3548,49 +3519,105 @@ static void hevc_vt_uniwgt_4t_8x2_msa(uint8_t *src, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight, int32_t offset, int32_t rnd_val) { + v16u8 out; v16i8 src0, src1, src2, src3, src4; v16i8 src10_r, src32_r, src21_r, src43_r; - v8i16 tmp0, tmp1; + v8i16 dst0, dst1; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst0_l, dst1_l; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= src_stride; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); + LD_SB5(src, src_stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); - LD_SB2(src, src_stride, src3, src4); - XORI_B2_128_SB(src3, src4); ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); + dst0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + + HEVC_UNIW_RND_CLIP2_MAX_SATU_H(dst0, dst1, weight_vec, offset_vec, rnd_vec, + dst0, dst1); + + out = (v16u8) __msa_pckev_b((v16i8) dst1, (v16i8) dst0); + ST8x2_UB(out, dst, dst_stride); +} + +static void hevc_vt_uniwgt_4t_8x4_msa(uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter, + int32_t weight, + int32_t offset, + int32_t rnd_val) +{ + v16u8 out0, out1; + v16i8 src0, src1, src2, src3, src4; + v16i8 src10_r, src32_r, src21_r, src43_r; + v16i8 src5, src6, src54_r, src65_r; + v8i16 filt0, filt1; + v8i16 dst0, dst1, dst2, dst3; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; + + src -= src_stride; - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); - HEVC_UNIW_RND_CLIP2(tmp0, tmp1, weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst0_l, dst1_l); + weight = weight & 0x0000FFFF; + + weight_vec = __msa_fill_w(weight); + rnd_vec = __msa_fill_w(rnd_val); - HEVC_PCK_SW_SB4(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r); - ST8x2_UB(dst0_r, dst, dst_stride); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + + filter_vec = LD_SH(filter); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); + + LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); + src += (3 * src_stride); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); + ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); + ILVR_B2_SB(src5, src4, src6, src5, src54_r, src65_r); + dst0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(src32_r, src54_r, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(src43_r, src65_r, filt0, filt1); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, weight_vec, + offset_vec, rnd_vec, dst0, dst1, dst2, + dst3); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + ST8x4_UB(out0, out1, dst, dst_stride); } static void hevc_vt_uniwgt_4t_8x6_msa(uint8_t *src, @@ -3598,101 +3625,102 @@ static void hevc_vt_uniwgt_4t_8x6_msa(uint8_t *src, uint8_t *dst, int32_t dst_stride, const int8_t *filter, - int32_t height, int32_t weight, int32_t offset, int32_t rnd_val) { + v16u8 out0, out1, out2; v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; v16i8 src10_r, src32_r, src54_r, src76_r; v16i8 src21_r, src43_r, src65_r, src87_r; - v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= src_stride; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); LD_SB3(src, src_stride, src0, src1, src2); src += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); - ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); - LD_SB6(src, src_stride, src3, src4, src5, src6, src7, src8); - XORI_B6_128_SB(src3, src4, src5, src6, src7, src8); - ILVR_B4_SB(src3, src2, src4, src3, src5, src4, src6, src5, - src32_r, src43_r, src54_r, src65_r); - ILVR_B2_SB(src7, src6, src8, src7, src76_r, src87_r); - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); - tmp2 = const_vec; - DPADD_SB2_SH(src32_r, src54_r, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src43_r, src65_r, filt0, filt1, tmp3, tmp3); - tmp4 = const_vec; - DPADD_SB2_SH(src54_r, src76_r, filt0, filt1, tmp4, tmp4); - tmp5 = const_vec; - DPADD_SB2_SH(src65_r, src87_r, filt0, filt1, tmp5, tmp5); - HEVC_UNIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - HEVC_UNIW_RND_CLIP2(tmp4, tmp5, weight_vec, offset_vec, rnd_vec, - dst4_r, dst5_r, dst4_l, dst5_l); - - HEVC_PCK_SW_SB12(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - dst4_l, dst4_r, dst5_l, dst5_r, dst0_r, dst1_r, dst2_r); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); + XORI_B3_128_SB(src0, src1, src2); + XORI_B6_128_SB(src3, src4, src5, src6, src7, src8); + ILVR_B4_SB(src1, src0, src2, src1, src3, src2, src4, src3, src10_r, src21_r, + src32_r, src43_r); + ILVR_B4_SB(src5, src4, src6, src5, src7, src6, src8, src7, src54_r, src65_r, + src76_r, src87_r); + dst0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(src32_r, src54_r, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(src43_r, src65_r, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(src54_r, src76_r, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(src65_r, src87_r, filt0, filt1); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, weight_vec, + offset_vec, rnd_vec, dst0, dst1, dst2, dst3); + HEVC_UNIW_RND_CLIP2_MAX_SATU_H(dst4, dst5, weight_vec, offset_vec, rnd_vec, + dst4, dst5); + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + ST8x4_UB(out0, out1, dst, dst_stride); dst += (4 * dst_stride); - ST8x2_UB(dst2_r, dst, dst_stride); + ST8x2_UB(out2, dst, dst_stride); } -static void hevc_vt_uniwgt_4t_8x4multiple_msa(uint8_t *src, - int32_t src_stride, - uint8_t *dst, - int32_t dst_stride, - const int8_t *filter, - int32_t height, - int32_t weight, - int32_t offset, - int32_t rnd_val) +static void hevc_vt_uniwgt_4t_8x8mult_msa(uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter, + int32_t height, + int32_t weight, + int32_t offset, + int32_t rnd_val) { int32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4; + v16u8 out0, out1, out2, out3; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v16i8 src10_r, src32_r, src21_r, src43_r; - v8i16 tmp0, tmp1, tmp2, tmp3; + v16i8 src54_r, src65_r, src76_r, src87_r, src98_r, src109_r; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= src_stride; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); @@ -3701,35 +3729,37 @@ static void hevc_vt_uniwgt_4t_8x4multiple_msa(uint8_t *src, XORI_B3_128_SB(src0, src1, src2); ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB2(src, src_stride, src3, src4); - src += (2 * src_stride); - XORI_B2_128_SB(src3, src4); + for (loop_cnt = (height >> 3); loop_cnt--;) { + LD_SB8(src, src_stride, + src3, src4, src5, src6, src7, src8, src9, src10); + src += (8 * src_stride); + XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); + ILVR_B2_SB(src5, src4, src6, src5, src54_r, src65_r); + ILVR_B2_SB(src7, src6, src8, src7, src76_r, src87_r); + ILVR_B2_SB(src9, src8, src10, src9, src98_r, src109_r); + dst0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(src32_r, src54_r, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(src43_r, src65_r, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(src54_r, src76_r, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(src65_r, src87_r, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(src76_r, src98_r, filt0, filt1); + dst7 = HEVC_FILT_4TAP_SH(src87_r, src109_r, filt0, filt1); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, weight_vec, + offset_vec, rnd_vec, dst0, dst1, dst2, + dst3); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst4, dst5, dst6, dst7, weight_vec, + offset_vec, rnd_vec, dst4, dst5, dst6, + dst7); + PCKEV_B2_UB(dst1, dst0, dst3, dst2, out0, out1); + PCKEV_B2_UB(dst5, dst4, dst7, dst6, out2, out3); + ST8x8_UB(out0, out1, out2, out3, dst, dst_stride); + dst += (8 * dst_stride); - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); - - LD_SB2(src, src_stride, src1, src2); - src += (2 * src_stride); - XORI_B2_128_SB(src1, src2); - ILVR_B2_SB(src1, src4, src2, src1, src10_r, src21_r); - - tmp2 = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, tmp3, tmp3); - HEVC_UNIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST8x4_UB(dst0_r, dst1_r, dst, dst_stride); - dst += (4 * dst_stride); + src2 = src10; + src10_r = src98_r; + src21_r = src109_r; } } @@ -3745,14 +3775,17 @@ static void hevc_vt_uniwgt_4t_8w_msa(uint8_t *src, { if (2 == height) { hevc_vt_uniwgt_4t_8x2_msa(src, src_stride, dst, dst_stride, - filter, height, weight, offset, rnd_val); + filter, weight, offset, rnd_val); + } else if (4 == height) { + hevc_vt_uniwgt_4t_8x4_msa(src, src_stride, dst, dst_stride, + filter, weight, offset, rnd_val); } else if (6 == height) { hevc_vt_uniwgt_4t_8x6_msa(src, src_stride, dst, dst_stride, - filter, height, weight, offset, rnd_val); + filter, weight, offset, rnd_val); } else { - hevc_vt_uniwgt_4t_8x4multiple_msa(src, src_stride, dst, dst_stride, - filter, height, weight, offset, - rnd_val); + hevc_vt_uniwgt_4t_8x8mult_msa(src, src_stride, dst, dst_stride, + filter, height, weight, offset, + rnd_val); } } @@ -3767,27 +3800,35 @@ static void hevc_vt_uniwgt_4t_12w_msa(uint8_t *src, int32_t rnd_val) { int32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5; + v16u8 out0, out1, out2, out3, out4, out5; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v16i8 src10_r, src32_r, src21_r, src43_r; - v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; v16i8 src10_l, src32_l, src54_l, src21_l, src43_l, src65_l; v16i8 src2110, src4332; + v16i8 src54_r, src76_r, src98_r, src65_r, src87_r, src109_r; + v16i8 src76_l, src98_l, src87_l, src109_l, src6554, src8776, src10998; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; + v8i16 dst9, dst10, dst11, filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= (1 * src_stride); - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); @@ -3798,47 +3839,56 @@ static void hevc_vt_uniwgt_4t_12w_msa(uint8_t *src, ILVL_B2_SB(src1, src0, src2, src1, src10_l, src21_l); src2110 = (v16i8) __msa_ilvr_d((v2i64) src21_l, (v2i64) src10_l); - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB2(src, src_stride, src3, src4); - src += (2 * src_stride); - XORI_B2_128_SB(src3, src4); - ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); - ILVL_B2_SB(src3, src2, src4, src3, src32_l, src43_l); + for (loop_cnt = 2; loop_cnt--;) { + LD_SB8(src, src_stride, src3, src4, src5, src6, src7, src8, src9, src10); + src += (8 * src_stride); + XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); + ILVRL_B2_SB(src3, src2, src32_r, src32_l); + ILVRL_B2_SB(src4, src3, src43_r, src43_l); + ILVRL_B2_SB(src5, src4, src54_r, src54_l); + ILVRL_B2_SB(src6, src5, src65_r, src65_l); src4332 = (v16i8) __msa_ilvr_d((v2i64) src43_l, (v2i64) src32_l); + src6554 = (v16i8) __msa_ilvr_d((v2i64) src65_l, (v2i64) src54_l); + dst0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(src32_r, src54_r, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(src43_r, src65_r, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(src2110, src4332, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(src4332, src6554, filt0, filt1); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, weight_vec, + offset_vec, rnd_vec, dst0, dst1, dst2, + dst3); + HEVC_UNIW_RND_CLIP2_MAX_SATU_H(dst4, dst5, weight_vec, offset_vec, + rnd_vec, dst4, dst5); + PCKEV_B3_UB(dst1, dst0, dst3, dst2, dst5, dst4, out0, out1, out2); + ST12x4_UB(out0, out1, out2, dst, dst_stride); + dst += (4 * dst_stride); - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); - tmp4 = const_vec; - DPADD_SB2_SH(src2110, src4332, filt0, filt1, tmp4, tmp4); - - LD_SB2(src, src_stride, src5, src2); - src += (2 * src_stride); - XORI_B2_128_SB(src5, src2); - ILVR_B2_SB(src5, src4, src2, src5, src10_r, src21_r); - ILVL_B2_SB(src5, src4, src2, src5, src54_l, src65_l); - src2110 = (v16i8) __msa_ilvr_d((v2i64) src65_l, (v2i64) src54_l); - - tmp2 = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, tmp3, tmp3); - tmp5 = const_vec; - DPADD_SB2_SH(src4332, src2110, filt0, filt1, tmp5, tmp5); - HEVC_UNIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - HEVC_UNIW_RND_CLIP2(tmp4, tmp5, weight_vec, offset_vec, rnd_vec, - dst4_r, dst5_r, dst4_l, dst5_l); - - HEVC_PCK_SW_SB12(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - dst4_l, dst4_r, dst5_l, dst5_r, - dst0_r, dst1_r, dst2_r); - ST12x4_UB(dst0_r, dst1_r, dst2_r, dst, dst_stride); + ILVRL_B2_SB(src7, src6, src76_r, src76_l); + ILVRL_B2_SB(src8, src7, src87_r, src87_l); + ILVRL_B2_SB(src9, src8, src98_r, src98_l); + ILVRL_B2_SB(src10, src9, src109_r, src109_l); + src8776 = (v16i8) __msa_ilvr_d((v2i64) src87_l, (v2i64) src76_l); + src10998 = (v16i8) __msa_ilvr_d((v2i64) src109_l, (v2i64) src98_l); + dst6 = HEVC_FILT_4TAP_SH(src54_r, src76_r, filt0, filt1); + dst7 = HEVC_FILT_4TAP_SH(src65_r, src87_r, filt0, filt1); + dst8 = HEVC_FILT_4TAP_SH(src76_r, src98_r, filt0, filt1); + dst9 = HEVC_FILT_4TAP_SH(src87_r, src109_r, filt0, filt1); + dst10 = HEVC_FILT_4TAP_SH(src6554, src8776, filt0, filt1); + dst11 = HEVC_FILT_4TAP_SH(src8776, src10998, filt0, filt1); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst6, dst7, dst8, dst9, weight_vec, + offset_vec, rnd_vec, dst6, dst7, dst8, + dst9); + HEVC_UNIW_RND_CLIP2_MAX_SATU_H(dst10, dst11, weight_vec, offset_vec, + rnd_vec, dst10, dst11); + PCKEV_B3_UB(dst7, dst6, dst9, dst8, dst11, dst10, out3, out4, out5); + ST12x4_UB(out3, out4, out5, dst, dst_stride); dst += (4 * dst_stride); + + src2 = src10; + src10_r = src98_r; + src21_r = src109_r; + src2110 = src10998; } } @@ -3853,25 +3903,33 @@ static void hevc_vt_uniwgt_4t_16w_msa(uint8_t *src, int32_t rnd_val) { int32_t loop_cnt; + v16u8 out0, out1, out2, out3; v16i8 src0, src1, src2, src3, src4, src5; v16i8 src10_r, src32_r, src21_r, src43_r; v16i8 src10_l, src32_l, src21_l, src43_l; - v8i16 tmp0, tmp1, tmp2, tmp3; + v16i8 src54_r, src54_l, src65_r, src65_l, src6; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= src_stride; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); @@ -3882,53 +3940,37 @@ static void hevc_vt_uniwgt_4t_16w_msa(uint8_t *src, ILVL_B2_SB(src1, src0, src2, src1, src10_l, src21_l); for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB2(src, src_stride, src3, src4); - src += (2 * src_stride); - XORI_B2_128_SB(src3, src4); - ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); - ILVL_B2_SB(src3, src2, src4, src3, src32_l, src43_l); - - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); - tmp2 = const_vec; - DPADD_SB2_SH(src10_l, src32_l, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src21_l, src43_l, filt0, filt1, tmp3, tmp3); - HEVC_UNIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); - dst += (2 * dst_stride); + LD_SB4(src, src_stride, src3, src4, src5, src6); + src += (4 * src_stride); + XORI_B4_128_SB(src3, src4, src5, src6); + ILVRL_B2_SB(src3, src2, src32_r, src32_l); + ILVRL_B2_SB(src4, src3, src43_r, src43_l); + ILVRL_B2_SB(src5, src4, src54_r, src54_l); + ILVRL_B2_SB(src6, src5, src65_r, src65_l); + dst0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(src32_r, src54_r, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(src43_r, src65_r, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(src10_l, src32_l, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(src21_l, src43_l, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(src32_l, src54_l, filt0, filt1); + dst7 = HEVC_FILT_4TAP_SH(src43_l, src65_l, filt0, filt1); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, weight_vec, + offset_vec, rnd_vec, dst0, dst1, dst2, + dst3); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst4, dst5, dst6, dst7, weight_vec, + offset_vec, rnd_vec, dst4, dst5, dst6, + dst7); + PCKEV_B4_UB(dst4, dst0, dst5, dst1, dst6, dst2, dst7, dst3, out0, out1, + out2, out3); + ST_UB4(out0, out1, out2, out3, dst, dst_stride); + dst += (4 * dst_stride); - LD_SB2(src, src_stride, src5, src2); - src += (2 * src_stride); - XORI_B2_128_SB(src5, src2); - ILVR_B2_SB(src5, src4, src2, src5, src10_r, src21_r); - ILVL_B2_SB(src5, src4, src2, src5, src10_l, src21_l); - - tmp0 = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, tmp0, tmp0); - tmp1 = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, tmp1, tmp1); - tmp2 = const_vec; - DPADD_SB2_SH(src32_l, src10_l, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src43_l, src21_l, filt0, filt1, tmp3, tmp3); - HEVC_UNIW_RND_CLIP4(tmp0, tmp1, tmp2, tmp3, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); - dst += (2 * dst_stride); + src2 = src6; + src10_r = src54_r; + src21_r = src65_r; + src10_l = src54_l; + src21_l = src65_l; } } @@ -3943,113 +3985,94 @@ static void hevc_vt_uniwgt_4t_24w_msa(uint8_t *src, int32_t rnd_val) { uint32_t loop_cnt; + v16u8 out0, out1, out2, out3, out4, out5; v16i8 src0, src1, src2, src3, src4, src5; - v16i8 src6, src7, src8, src9, src10, src11; - v16i8 src10_r, src32_r, src76_r, src98_r; - v16i8 src21_r, src43_r, src87_r, src109_r; - v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; - v16i8 src10_l, src32_l, src21_l, src43_l; + v16i8 src6, src7, src8, src9, src10, src11, src12, src13; + v16i8 src10_r, src32_r, src54_r, src21_r, src43_r, src65_r; + v16i8 src10_l, src32_l, src54_l, src21_l, src43_l, src65_l; + v16i8 src87_r, src98_r, src109_r, src1110_r, src1211_r, src1312_r; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8, dst9, dst10; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec, dst11; + v4i32 weight_vec, rnd_vec; src -= src_stride; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); LD_SB3(src, src_stride, src0, src1, src2); + LD_SB3(src + 16, src_stride, src7, src8, src9); + src += (3 * src_stride); XORI_B3_128_SB(src0, src1, src2); + XORI_B3_128_SB(src7, src8, src9); ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); ILVL_B2_SB(src1, src0, src2, src1, src10_l, src21_l); + ILVR_B2_SB(src8, src7, src9, src8, src87_r, src98_r); - LD_SB3(src + 16, src_stride, src6, src7, src8); - src += (3 * src_stride); - XORI_B3_128_SB(src6, src7, src8); - ILVR_B2_SB(src7, src6, src8, src7, src76_r, src87_r); - - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB2(src, src_stride, src3, src4); - XORI_B2_128_SB(src3, src4); + for (loop_cnt = 8; loop_cnt--;) { + LD_SB4(src, src_stride, src3, src4, src5, src6); + LD_SB4(src + 16, src_stride, src10, src11, src12, src13); + src += (4 * src_stride); + XORI_B4_128_SB(src3, src4, src5, src6); + XORI_B4_128_SB(src10, src11, src12, src13); ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); ILVL_B2_SB(src3, src2, src4, src3, src32_l, src43_l); - LD_SB2(src + 16, src_stride, src9, src10); - src += (2 * src_stride); - XORI_B2_128_SB(src9, src10); - ILVR_B2_SB(src9, src8, src10, src9, src98_r, src109_r); - - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp4 = const_vec; - DPADD_SB2_SH(src10_l, src32_l, filt0, filt1, tmp4, tmp4); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); - tmp5 = const_vec; - DPADD_SB2_SH(src21_l, src43_l, filt0, filt1, tmp5, tmp5); - tmp2 = const_vec; - DPADD_SB2_SH(src76_r, src98_r, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src87_r, src109_r, filt0, filt1, tmp3, tmp3); - - HEVC_UNIW_RND_CLIP4(tmp0, tmp1, tmp4, tmp5, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - HEVC_UNIW_RND_CLIP2(tmp2, tmp3, weight_vec, offset_vec, rnd_vec, - dst4_r, dst5_r, dst4_l, dst5_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); - HEVC_PCK_SW_SB4(dst4_l, dst4_r, dst5_l, dst5_r, dst4_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); - ST8x2_UB(dst4_r, dst + 16, dst_stride); - dst += (2 * dst_stride); + ILVRL_B2_SB(src5, src4, src54_r, src54_l); + ILVRL_B2_SB(src6, src5, src65_r, src65_l); + ILVR_B2_SB(src10, src9, src11, src10, src109_r, src1110_r); + ILVR_B2_SB(src12, src11, src13, src12, src1211_r, src1312_r); + dst0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(src32_r, src54_r, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(src43_r, src65_r, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(src10_l, src32_l, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(src21_l, src43_l, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(src32_l, src54_l, filt0, filt1); + dst7 = HEVC_FILT_4TAP_SH(src43_l, src65_l, filt0, filt1); + dst8 = HEVC_FILT_4TAP_SH(src87_r, src109_r, filt0, filt1); + dst9 = HEVC_FILT_4TAP_SH(src98_r, src1110_r, filt0, filt1); + dst10 = HEVC_FILT_4TAP_SH(src109_r, src1211_r, filt0, filt1); + dst11 = HEVC_FILT_4TAP_SH(src1110_r, src1312_r, filt0, filt1); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, weight_vec, + offset_vec, rnd_vec, dst0, dst1, dst2, + dst3); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst4, dst5, dst6, dst7, weight_vec, + offset_vec, rnd_vec, dst4, dst5, dst6, + dst7); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst8, dst9, dst10, dst11, weight_vec, + offset_vec, rnd_vec, dst8, dst9, dst10, + dst11); + PCKEV_B4_UB(dst4, dst0, dst5, dst1, dst6, dst2, dst7, dst3, out0, out1, + out2, out3); + PCKEV_B2_UB(dst9, dst8, dst11, dst10, out4, out5); + ST_UB4(out0, out1, out2, out3, dst, dst_stride); + ST8x4_UB(out4, out5, dst + 16, dst_stride); + dst += (4 * dst_stride); - LD_SB2(src, src_stride, src5, src2); - XORI_B2_128_SB(src5, src2); - ILVR_B2_SB(src5, src4, src2, src5, src10_r, src21_r); - ILVL_B2_SB(src5, src4, src2, src5, src10_l, src21_l); - LD_SB2(src + 16, src_stride, src11, src8); - src += (2 * src_stride); - XORI_B2_128_SB(src11, src8); - ILVR_B2_SB(src11, src10, src8, src11, src76_r, src87_r); - - tmp0 = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, tmp0, tmp0); - tmp4 = const_vec; - DPADD_SB2_SH(src32_l, src10_l, filt0, filt1, tmp4, tmp4); - tmp1 = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, tmp1, tmp1); - tmp5 = const_vec; - DPADD_SB2_SH(src43_l, src21_l, filt0, filt1, tmp5, tmp5); - tmp2 = const_vec; - DPADD_SB2_SH(src98_r, src76_r, filt0, filt1, tmp2, tmp2); - tmp3 = const_vec; - DPADD_SB2_SH(src109_r, src87_r, filt0, filt1, tmp3, tmp3); - - HEVC_UNIW_RND_CLIP4(tmp0, tmp1, tmp4, tmp5, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - HEVC_UNIW_RND_CLIP2(tmp2, tmp3, weight_vec, offset_vec, rnd_vec, - dst4_r, dst5_r, dst4_l, dst5_l); - - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); - HEVC_PCK_SW_SB4(dst4_l, dst4_r, dst5_l, dst5_r, dst4_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); - ST8x2_UB(dst4_r, dst + 16, dst_stride); - dst += (2 * dst_stride); + src2 = src6; + src9 = src13; + src10_r = src54_r; + src21_r = src65_r; + src10_l = src54_l; + src21_l = src65_l; + src87_r = src1211_r; + src98_r = src1312_r; } } @@ -4063,104 +4086,87 @@ static void hevc_vt_uniwgt_4t_32w_msa(uint8_t *src, int32_t offset, int32_t rnd_val) { - int32_t loop_cnt; - uint8_t *dst_tmp = dst + 16; - v16i8 src0, src1, src2, src3, src4, src6, src7, src8, src9, src10; + uint32_t loop_cnt; + v16u8 out0, out1, out2, out3; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9; v16i8 src10_r, src32_r, src76_r, src98_r; - v16i8 src21_r, src43_r, src87_r, src109_r; - v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + v16i8 src21_r, src43_r, src65_r, src87_r; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; v16i8 src10_l, src32_l, src76_l, src98_l; - v16i8 src21_l, src43_l, src87_l, src109_l; + v16i8 src21_l, src43_l, src65_l, src87_l; v8i16 filt0, filt1; - v8i16 filter_vec, const_vec; - v4i32 weight_vec, offset_vec, rnd_vec; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r, dst6_r, dst7_r; - v4i32 dst0_l, dst1_l, dst2_l, dst3_l, dst4_l, dst5_l, dst6_l, dst7_l; + v8i16 filter_vec, weight_vec_h, offset_vec, denom_vec; + v4i32 weight_vec, rnd_vec; src -= src_stride; - const_vec = __msa_ldi_h(128); - const_vec <<= 6; weight = weight & 0x0000FFFF; weight_vec = __msa_fill_w(weight); - offset_vec = __msa_fill_w(offset); rnd_vec = __msa_fill_w(rnd_val); + weight *= 128; + rnd_val -= 6; + + weight_vec_h = __msa_fill_h(weight); + offset_vec = __msa_fill_h(offset); + denom_vec = __msa_fill_h(rnd_val); + + weight_vec_h = __msa_srar_h(weight_vec_h, denom_vec); + offset_vec = __msa_adds_s_h(offset_vec, weight_vec_h); + filter_vec = LD_SH(filter); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); LD_SB3(src, src_stride, src0, src1, src2); - XORI_B3_128_SB(src0, src1, src2); + LD_SB3(src + 16, src_stride, src5, src6, src7); + src += (3 * src_stride); + XORI_B6_128_SB(src0, src1, src2, src5, src6, src7); ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); ILVL_B2_SB(src1, src0, src2, src1, src10_l, src21_l); - - LD_SB3(src + 16, src_stride, src6, src7, src8); - src += (3 * src_stride); - XORI_B3_128_SB(src6, src7, src8); - ILVR_B2_SB(src7, src6, src8, src7, src76_r, src87_r); - ILVL_B2_SB(src7, src6, src8, src7, src76_l, src87_l); + ILVR_B2_SB(src6, src5, src7, src6, src65_r, src76_r); + ILVL_B2_SB(src6, src5, src7, src6, src65_l, src76_l); for (loop_cnt = (height >> 1); loop_cnt--;) { LD_SB2(src, src_stride, src3, src4); - XORI_B2_128_SB(src3, src4); + LD_SB2(src + 16, src_stride, src8, src9); + src += (2 * src_stride); + XORI_B4_128_SB(src3, src4, src8, src9); ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); ILVL_B2_SB(src3, src2, src4, src3, src32_l, src43_l); + ILVRL_B2_SB(src8, src7, src87_r, src87_l); + ILVRL_B2_SB(src9, src8, src98_r, src98_l); + dst0 = HEVC_FILT_4TAP_SH(src10_r, src32_r, filt0, filt1); + dst1 = HEVC_FILT_4TAP_SH(src21_r, src43_r, filt0, filt1); + dst2 = HEVC_FILT_4TAP_SH(src10_l, src32_l, filt0, filt1); + dst3 = HEVC_FILT_4TAP_SH(src21_l, src43_l, filt0, filt1); + dst4 = HEVC_FILT_4TAP_SH(src65_r, src87_r, filt0, filt1); + dst5 = HEVC_FILT_4TAP_SH(src76_r, src98_r, filt0, filt1); + dst6 = HEVC_FILT_4TAP_SH(src65_l, src87_l, filt0, filt1); + dst7 = HEVC_FILT_4TAP_SH(src76_l, src98_l, filt0, filt1); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst0, dst1, dst2, dst3, weight_vec, + offset_vec, rnd_vec, dst0, dst1, dst2, + dst3); + HEVC_UNIW_RND_CLIP4_MAX_SATU_H(dst4, dst5, dst6, dst7, weight_vec, + offset_vec, rnd_vec, dst4, dst5, dst6, + dst7); + PCKEV_B4_UB(dst2, dst0, dst3, dst1, dst6, dst4, dst7, dst5, out0, out1, + out2, out3); + ST_UB2(out0, out2, dst, 16); + dst += dst_stride; + ST_UB2(out1, out3, dst, 16); + dst += dst_stride; - tmp0 = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, tmp0, tmp0); - tmp4 = const_vec; - DPADD_SB2_SH(src10_l, src32_l, filt0, filt1, tmp4, tmp4); - tmp1 = const_vec; - DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, tmp1, tmp1); - tmp5 = const_vec; - DPADD_SB2_SH(src21_l, src43_l, filt0, filt1, tmp5, tmp5); - - HEVC_UNIW_RND_CLIP4(tmp0, tmp1, tmp4, tmp5, - weight_vec, offset_vec, rnd_vec, - dst0_r, dst1_r, dst2_r, dst3_r, - dst0_l, dst1_l, dst2_l, dst3_l); - HEVC_PCK_SW_SB8(dst0_l, dst0_r, dst2_l, dst2_r, - dst1_l, dst1_r, dst3_l, dst3_r, dst0_r, dst1_r); - ST_SW2(dst0_r, dst1_r, dst, dst_stride); - dst += (2 * dst_stride); - + src2 = src4; + src7 = src9; src10_r = src32_r; src21_r = src43_r; src10_l = src32_l; src21_l = src43_l; - src2 = src4; - - LD_SB2(src + 16, src_stride, src9, src10); - src += (2 * src_stride); - XORI_B2_128_SB(src9, src10); - ILVR_B2_SB(src9, src8, src10, src9, src98_r, src109_r); - ILVL_B2_SB(src9, src8, src10, src9, src98_l, src109_l); - - tmp2 = const_vec; - DPADD_SB2_SH(src76_r, src98_r, filt0, filt1, tmp2, tmp2); - tmp6 = const_vec; - DPADD_SB2_SH(src76_l, src98_l, filt0, filt1, tmp6, tmp6); - tmp3 = const_vec; - DPADD_SB2_SH(src87_r, src109_r, filt0, filt1, tmp3, tmp3); - tmp7 = const_vec; - DPADD_SB2_SH(src87_l, src109_l, filt0, filt1, tmp7, tmp7); - - HEVC_UNIW_RND_CLIP4(tmp2, tmp3, tmp6, tmp7, - weight_vec, offset_vec, rnd_vec, - dst4_r, dst5_r, dst6_r, dst7_r, - dst4_l, dst5_l, dst6_l, dst7_l); - - HEVC_PCK_SW_SB8(dst4_l, dst4_r, dst6_l, dst6_r, - dst5_l, dst5_r, dst7_l, dst7_r, dst4_r, dst5_r); - ST_SW2(dst4_r, dst5_r, dst_tmp, dst_stride); - dst_tmp += (2 * dst_stride); - + src65_r = src87_r; src76_r = src98_r; - src87_r = src109_r; + src65_l = src87_l; src76_l = src98_l; - src87_l = src109_l; - src8 = src10; } } From 372a4dda3356f4e9954c22950fe0463b9aa6b6b2 Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Mon, 6 Nov 2017 18:06:53 +0530 Subject: [PATCH 0794/2557] avcodec/mips: Improve hevc non-uni hv mc msa functions Use mask buffer. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevcdsp_msa.c | 1478 +++++++++++++++++++-------------- 1 file changed, 870 insertions(+), 608 deletions(-) diff --git a/libavcodec/mips/hevcdsp_msa.c b/libavcodec/mips/hevcdsp_msa.c index 73cc3ea21307c..b17127c5f6bab 100644 --- a/libavcodec/mips/hevcdsp_msa.c +++ b/libavcodec/mips/hevcdsp_msa.c @@ -22,6 +22,13 @@ #include "libavcodec/mips/hevcdsp_mips.h" #include "libavcodec/mips/hevc_macros_msa.h" +static const uint8_t ff_hevc_mask_arr[16 * 2] __attribute__((aligned(0x40))) = { + /* 8 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + /* 4 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 +}; + static void hevc_copy_4w_msa(uint8_t *src, int32_t src_stride, int16_t *dst, int32_t dst_stride, int32_t height) @@ -1308,31 +1315,28 @@ static void hevc_hv_8t_4w_msa(uint8_t *src, int32_t src_stride, int32_t height) { uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + int32_t dst_stride_in_bytes = 2 * dst_stride; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v8i16 filt0, filt1, filt2, filt3; - v4i32 filt_h0, filt_h1, filt_h2, filt_h3; + v8i16 filt_h0, filt_h1, filt_h2, filt_h3; v16i8 mask1, mask2, mask3; v8i16 filter_vec, const_vec; v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; - v8i16 dst30, dst41, dst52, dst63, dst66, dst87; - v4i32 dst0_r, dst1_r; - v8i16 dst10_r, dst32_r, dst54_r, dst76_r; - v8i16 dst21_r, dst43_r, dst65_r, dst87_r; - v16i8 mask0 = { - 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 - }; - v8u16 mask4 = { 0, 4, 1, 5, 2, 6, 3, 7 }; + v8i16 dst30, dst41, dst52, dst63, dst66, dst97, dst108; + v4i32 dst0_r, dst1_r, dst2_r, dst3_r; + v8i16 dst10_r, dst32_r, dst54_r, dst76_r, dst98_r; + v8i16 dst21_r, dst43_r, dst65_r, dst87_r, dst109_r; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); src -= ((3 * src_stride) + 3); filter_vec = LD_SH(filter_x); SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W4_SW(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); mask1 = mask0 + 2; mask2 = mask0 + 4; @@ -1364,47 +1368,56 @@ static void hevc_hv_8t_4w_msa(uint8_t *src, int32_t src_stride, DPADD_SB4_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, filt3, dst63, dst63, dst63, dst63); - ILVR_H3_SH(dst41, dst30, dst52, dst41, dst63, dst52, - dst10_r, dst21_r, dst32_r); - dst43_r = __msa_ilvl_h(dst41, dst30); - dst54_r = __msa_ilvl_h(dst52, dst41); - dst65_r = __msa_ilvl_h(dst63, dst52); + ILVRL_H2_SH(dst41, dst30, dst10_r, dst43_r); + ILVRL_H2_SH(dst52, dst41, dst21_r, dst54_r); + ILVRL_H2_SH(dst63, dst52, dst32_r, dst65_r); dst66 = (v8i16) __msa_splati_d((v2i64) dst63, 1); - for (loop_cnt = height >> 1; loop_cnt--;) { - LD_SB2(src, src_stride, src7, src8); - src += (2 * src_stride); - XORI_B2_128_SB(src7, src8); + for (loop_cnt = height >> 2; loop_cnt--;) { + LD_SB4(src, src_stride, src7, src8, src9, src10); + src += (4 * src_stride); + XORI_B4_128_SB(src7, src8, src9, src10); - VSHF_B4_SB(src7, src8, mask0, mask1, mask2, mask3, + VSHF_B4_SB(src7, src9, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); - dst87 = const_vec; + VSHF_B4_SB(src8, src10, mask0, mask1, mask2, mask3, + vec4, vec5, vec6, vec7); + dst97 = const_vec; + dst108 = const_vec; DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst87, dst87, dst87, dst87); - dst76_r = __msa_ilvr_h(dst87, dst66); + dst97, dst97, dst97, dst97); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, + dst108, dst108, dst108, dst108); + + dst76_r = __msa_ilvr_h(dst97, dst66); + ILVRL_H2_SH(dst108, dst97, dst87_r, dst109_r); + dst66 = (v8i16) __msa_splati_d((v2i64) dst97, 1); + dst98_r = __msa_ilvr_h(dst66, dst108); + dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, filt_h0, filt_h1, filt_h2, filt_h3); - dst87_r = __msa_vshf_h((v8i16) mask4, dst87, dst87); dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, filt_h0, filt_h1, filt_h2, filt_h3); - dst0_r >>= 6; - dst1_r >>= 6; - - dst0_r = (v4i32) __msa_pckev_h((v8i16) dst1_r, (v8i16) dst0_r); - ST8x2_UB(dst0_r, dst, (2 * dst_stride)); - dst += (2 * dst_stride); + dst2_r = HEVC_FILT_8TAP(dst32_r, dst54_r, dst76_r, dst98_r, + filt_h0, filt_h1, filt_h2, filt_h3); + dst3_r = HEVC_FILT_8TAP(dst43_r, dst65_r, dst87_r, dst109_r, + filt_h0, filt_h1, filt_h2, filt_h3); + SRA_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); + PCKEV_H2_SW(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r, dst2_r); + ST8x4_UB(dst0_r, dst2_r, dst, dst_stride_in_bytes); + dst += (4 * dst_stride); - dst10_r = dst32_r; - dst32_r = dst54_r; - dst54_r = dst76_r; - dst21_r = dst43_r; - dst43_r = dst65_r; - dst65_r = dst87_r; - dst66 = (v8i16) __msa_splati_d((v2i64) dst87, 1); + dst10_r = dst54_r; + dst32_r = dst76_r; + dst54_r = dst98_r; + dst21_r = dst65_r; + dst43_r = dst87_r; + dst65_r = dst109_r; + dst66 = (v8i16) __msa_splati_d((v2i64) dst108, 1); } } -static void hevc_hv_8t_8multx2mult_msa(uint8_t *src, +static void hevc_hv_8t_8multx1mult_msa(uint8_t *src, int32_t src_stride, int16_t *dst, int32_t dst_stride, @@ -1415,19 +1428,17 @@ static void hevc_hv_8t_8multx2mult_msa(uint8_t *src, uint32_t loop_cnt, cnt; uint8_t *src_tmp; int16_t *dst_tmp; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7; v8i16 filt0, filt1, filt2, filt3; - v4i32 filt_h0, filt_h1, filt_h2, filt_h3; + v8i16 filt_h0, filt_h1, filt_h2, filt_h3; v16i8 mask1, mask2, mask3; v8i16 filter_vec, const_vec; v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; v4i32 dst0_r, dst0_l; v8i16 dst10_r, dst32_r, dst54_r, dst76_r; v8i16 dst10_l, dst32_l, dst54_l, dst76_l; - v8i16 dst21_r, dst43_r, dst65_r, dst87_r; - v8i16 dst21_l, dst43_l, dst65_l, dst87_l; v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; src -= ((3 * src_stride) + 3); @@ -1435,10 +1446,9 @@ static void hevc_hv_8t_8multx2mult_msa(uint8_t *src, SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W4_SW(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); mask1 = mask0 + 2; mask2 = mask0 + 4; @@ -1494,17 +1504,10 @@ static void hevc_hv_8t_8multx2mult_msa(uint8_t *src, DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, dst6, dst6, dst6, dst6); - ILVR_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, - dst10_r, dst32_r, dst54_r, dst21_r); - ILVR_H2_SH(dst4, dst3, dst6, dst5, dst43_r, dst65_r); - ILVL_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst2, dst1, - dst10_l, dst32_l, dst54_l, dst21_l); - ILVL_H2_SH(dst4, dst3, dst6, dst5, dst43_l, dst65_l); - - for (loop_cnt = height >> 1; loop_cnt--;) { - LD_SB2(src_tmp, src_stride, src7, src8); - XORI_B2_128_SB(src7, src8); - src_tmp += 2 * src_stride; + for (loop_cnt = height; loop_cnt--;) { + src7 = LD_SB(src_tmp); + src7 = (v16i8) __msa_xori_b((v16u8) src7, 128); + src_tmp += src_stride; VSHF_B4_SB(src7, src7, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); @@ -1512,6 +1515,9 @@ static void hevc_hv_8t_8multx2mult_msa(uint8_t *src, DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, dst7, dst7, dst7, dst7); + ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); + ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, filt_h0, filt_h1, filt_h2, filt_h3); @@ -1524,37 +1530,13 @@ static void hevc_hv_8t_8multx2mult_msa(uint8_t *src, ST_SW(dst0_r, dst_tmp); dst_tmp += dst_stride; - VSHF_B4_SB(src8, src8, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); - dst8 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst8, dst8, dst8, dst8); - - ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); - dst6 = dst8; - dst0_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, - filt_h0, filt_h1, filt_h2, filt_h3); - dst0_l = HEVC_FILT_8TAP(dst21_l, dst43_l, dst65_l, dst87_l, - filt_h0, filt_h1, filt_h2, filt_h3); - dst0_r >>= 6; - dst0_l >>= 6; - - dst0_r = (v4i32) __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); - ST_SW(dst0_r, dst_tmp); - dst_tmp += dst_stride; - - dst10_r = dst32_r; - dst32_r = dst54_r; - dst54_r = dst76_r; - dst10_l = dst32_l; - dst32_l = dst54_l; - dst54_l = dst76_l; - dst21_r = dst43_r; - dst43_r = dst65_r; - dst65_r = dst87_r; - dst21_l = dst43_l; - dst43_l = dst65_l; - dst65_l = dst87_l; + dst0 = dst1; + dst1 = dst2; + dst2 = dst3; + dst3 = dst4; + dst4 = dst5; + dst5 = dst6; + dst6 = dst7; } src += 8; @@ -1567,7 +1549,7 @@ static void hevc_hv_8t_8w_msa(uint8_t *src, int32_t src_stride, const int8_t *filter_x, const int8_t *filter_y, int32_t height) { - hevc_hv_8t_8multx2mult_msa(src, src_stride, dst, dst_stride, + hevc_hv_8t_8multx1mult_msa(src, src_stride, dst, dst_stride, filter_x, filter_y, height, 8); } @@ -1576,11 +1558,195 @@ static void hevc_hv_8t_12w_msa(uint8_t *src, int32_t src_stride, const int8_t *filter_x, const int8_t *filter_y, int32_t height) { - hevc_hv_8t_8multx2mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, 8); + uint32_t loop_cnt; + int32_t dst_stride_in_bytes = 2 * dst_stride; + uint8_t *src_tmp; + int16_t *dst_tmp; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask7; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; + v8i16 filt0, filt1, filt2, filt3, filt_h0, filt_h1, filt_h2, filt_h3; + v8i16 filter_vec, const_vec; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 dst30, dst41, dst52, dst63, dst66, dst97, dst108; + v8i16 dst10_r, dst32_r, dst54_r, dst76_r, dst98_r, dst21_r, dst43_r; + v8i16 dst65_r, dst87_r, dst109_r, dst10_l, dst32_l, dst54_l, dst76_l; + v4i32 dst0_r, dst0_l, dst1_r, dst2_r, dst3_r; + + src -= ((3 * src_stride) + 3); + filter_vec = LD_SH(filter_x); + SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W4_SH(filter_vec, filt_h0, filt_h1, filt_h2, filt_h3); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + mask2 = mask0 + 4; + mask3 = mask0 + 6; + + const_vec = __msa_ldi_h(128); + const_vec <<= 6; + + src_tmp = src; + dst_tmp = dst; + + LD_SB7(src_tmp, src_stride, src0, src1, src2, src3, src4, src5, src6); + src_tmp += (7 * src_stride); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + /* row 0 row 1 row 2 row 3 */ + VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); + VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, vec4, vec5, vec6, vec7); + VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, vec8, vec9, vec10, + vec11); + VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, vec12, vec13, vec14, + vec15); + dst0 = const_vec; + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, dst0, dst0, + dst0, dst0); + dst1 = const_vec; + DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, dst1, dst1, + dst1, dst1); + dst2 = const_vec; + DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, dst2, + dst2, dst2, dst2); + dst3 = const_vec; + DPADD_SB4_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, filt3, dst3, + dst3, dst3, dst3); + + /* row 4 row 5 row 6 */ + VSHF_B4_SB(src4, src4, mask0, mask1, mask2, mask3, vec0, vec1, vec2, vec3); + VSHF_B4_SB(src5, src5, mask0, mask1, mask2, mask3, vec4, vec5, vec6, vec7); + VSHF_B4_SB(src6, src6, mask0, mask1, mask2, mask3, vec8, vec9, vec10, + vec11); + dst4 = const_vec; + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, dst4, dst4, + dst4, dst4); + dst5 = const_vec; + DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, dst5, dst5, + dst5, dst5); + dst6 = const_vec; + DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, dst6, + dst6, dst6, dst6); + + for (loop_cnt = height; loop_cnt--;) { + src7 = LD_SB(src_tmp); + src7 = (v16i8) __msa_xori_b((v16u8) src7, 128); + src_tmp += src_stride; + + VSHF_B4_SB(src7, src7, mask0, mask1, mask2, mask3, vec0, vec1, vec2, + vec3); + dst7 = const_vec; + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, dst7, + dst7, dst7, dst7); + + ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); + ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); + dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst0_l = HEVC_FILT_8TAP(dst10_l, dst32_l, dst54_l, dst76_l, filt_h0, + filt_h1, filt_h2, filt_h3); + dst0_r >>= 6; + dst0_l >>= 6; + + dst0_r = (v4i32) __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); + ST_SW(dst0_r, dst_tmp); + dst_tmp += dst_stride; + + dst0 = dst1; + dst1 = dst2; + dst2 = dst3; + dst3 = dst4; + dst4 = dst5; + dst5 = dst6; + dst6 = dst7; + } + + src += 8; + dst += 8; + + mask4 = LD_SB(ff_hevc_mask_arr + 16); + mask5 = mask4 + 2; + mask6 = mask4 + 4; + mask7 = mask4 + 6; + + LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); + src += (7 * src_stride); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + VSHF_B4_SB(src0, src3, mask4, mask5, mask6, mask7, vec0, vec1, vec2, vec3); + VSHF_B4_SB(src1, src4, mask4, mask5, mask6, mask7, vec4, vec5, vec6, vec7); + VSHF_B4_SB(src2, src5, mask4, mask5, mask6, mask7, vec8, vec9, vec10, + vec11); + VSHF_B4_SB(src3, src6, mask4, mask5, mask6, mask7, vec12, vec13, vec14, + vec15); + dst30 = const_vec; + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, dst30, + dst30, dst30, dst30); + dst41 = const_vec; + DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, dst41, + dst41, dst41, dst41); + dst52 = const_vec; + DPADD_SB4_SH(vec8, vec9, vec10, vec11, filt0, filt1, filt2, filt3, dst52, + dst52, dst52, dst52); + dst63 = const_vec; + DPADD_SB4_SH(vec12, vec13, vec14, vec15, filt0, filt1, filt2, filt3, dst63, + dst63, dst63, dst63); + + ILVRL_H2_SH(dst41, dst30, dst10_r, dst43_r); + ILVRL_H2_SH(dst52, dst41, dst21_r, dst54_r); + ILVRL_H2_SH(dst63, dst52, dst32_r, dst65_r); - hevc_hv_8t_4w_msa(src + 8, src_stride, dst + 8, dst_stride, - filter_x, filter_y, height); + dst66 = (v8i16) __msa_splati_d((v2i64) dst63, 1); + + for (loop_cnt = height >> 2; loop_cnt--;) { + LD_SB4(src, src_stride, src7, src8, src9, src10); + src += (4 * src_stride); + XORI_B4_128_SB(src7, src8, src9, src10); + + VSHF_B4_SB(src7, src9, mask4, mask5, mask6, mask7, vec0, vec1, vec2, + vec3); + VSHF_B4_SB(src8, src10, mask4, mask5, mask6, mask7, vec4, vec5, vec6, + vec7); + dst97 = const_vec; + dst108 = const_vec; + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, dst97, + dst97, dst97, dst97); + DPADD_SB4_SH(vec4, vec5, vec6, vec7, filt0, filt1, filt2, filt3, dst108, + dst108, dst108, dst108); + + dst76_r = __msa_ilvr_h(dst97, dst66); + ILVRL_H2_SH(dst108, dst97, dst87_r, dst109_r); + dst66 = (v8i16) __msa_splati_d((v2i64) dst97, 1); + dst98_r = __msa_ilvr_h(dst66, dst108); + + dst0_r = HEVC_FILT_8TAP(dst10_r, dst32_r, dst54_r, dst76_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst1_r = HEVC_FILT_8TAP(dst21_r, dst43_r, dst65_r, dst87_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst2_r = HEVC_FILT_8TAP(dst32_r, dst54_r, dst76_r, dst98_r, filt_h0, + filt_h1, filt_h2, filt_h3); + dst3_r = HEVC_FILT_8TAP(dst43_r, dst65_r, dst87_r, dst109_r, filt_h0, + filt_h1, filt_h2, filt_h3); + SRA_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); + PCKEV_H2_SW(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r, dst2_r); + ST8x4_UB(dst0_r, dst2_r, dst, dst_stride_in_bytes); + dst += (4 * dst_stride); + + dst10_r = dst54_r; + dst32_r = dst76_r; + dst54_r = dst98_r; + dst21_r = dst65_r; + dst43_r = dst87_r; + dst65_r = dst109_r; + dst66 = (v8i16) __msa_splati_d((v2i64) dst108, 1); + } } static void hevc_hv_8t_16w_msa(uint8_t *src, int32_t src_stride, @@ -1588,7 +1754,7 @@ static void hevc_hv_8t_16w_msa(uint8_t *src, int32_t src_stride, const int8_t *filter_x, const int8_t *filter_y, int32_t height) { - hevc_hv_8t_8multx2mult_msa(src, src_stride, dst, dst_stride, + hevc_hv_8t_8multx1mult_msa(src, src_stride, dst, dst_stride, filter_x, filter_y, height, 16); } @@ -1597,7 +1763,7 @@ static void hevc_hv_8t_24w_msa(uint8_t *src, int32_t src_stride, const int8_t *filter_x, const int8_t *filter_y, int32_t height) { - hevc_hv_8t_8multx2mult_msa(src, src_stride, dst, dst_stride, + hevc_hv_8t_8multx1mult_msa(src, src_stride, dst, dst_stride, filter_x, filter_y, height, 24); } @@ -1606,7 +1772,7 @@ static void hevc_hv_8t_32w_msa(uint8_t *src, int32_t src_stride, const int8_t *filter_x, const int8_t *filter_y, int32_t height) { - hevc_hv_8t_8multx2mult_msa(src, src_stride, dst, dst_stride, + hevc_hv_8t_8multx1mult_msa(src, src_stride, dst, dst_stride, filter_x, filter_y, height, 32); } @@ -1615,7 +1781,7 @@ static void hevc_hv_8t_48w_msa(uint8_t *src, int32_t src_stride, const int8_t *filter_x, const int8_t *filter_y, int32_t height) { - hevc_hv_8t_8multx2mult_msa(src, src_stride, dst, dst_stride, + hevc_hv_8t_8multx1mult_msa(src, src_stride, dst, dst_stride, filter_x, filter_y, height, 48); } @@ -1624,7 +1790,7 @@ static void hevc_hv_8t_64w_msa(uint8_t *src, int32_t src_stride, const int8_t *filter_x, const int8_t *filter_y, int32_t height) { - hevc_hv_8t_8multx2mult_msa(src, src_stride, dst, dst_stride, + hevc_hv_8t_8multx1mult_msa(src, src_stride, dst, dst_stride, filter_x, filter_y, height, 64); } @@ -2994,69 +3160,52 @@ static void hevc_hv_4t_4x2_msa(uint8_t *src, const int8_t *filter_x, const int8_t *filter_y) { + int32_t dst_stride_in_bytes = 2 * dst_stride; v16i8 src0, src1, src2, src3, src4; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; v8i16 filter_vec, const_vec; v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4; - v4i32 dst0_r, dst1_r; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; + v8i16 dst20, dst31, dst42, dst10, dst32, dst21, dst43; + v4i32 dst0, dst1; src -= (src_stride + 1); filter_vec = LD_SH(filter_x); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; const_vec = __msa_ldi_h(128); const_vec <<= 6; - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); - - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); - - LD_SB2(src, src_stride, src3, src4); - XORI_B2_128_SB(src3, src4); - - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - dst32_r = __msa_ilvr_h(dst3, dst2); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; - - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - dst43_r = __msa_ilvr_h(dst4, dst3); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - - dst0_r = (v4i32) __msa_pckev_h((v8i16) dst1_r, (v8i16) dst0_r); - ST8x2_UB(dst0_r, dst, 2 * dst_stride); + LD_SB5(src, src_stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + VSHF_B2_SB(src0, src2, src0, src2, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src3, src1, src3, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src4, src2, src4, mask0, mask1, vec4, vec5); + + dst20 = const_vec; + dst31 = const_vec; + dst42 = const_vec; + DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst20, dst20); + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst31, dst31); + DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst42, dst42); + ILVRL_H2_SH(dst31, dst20, dst10, dst32); + ILVRL_H2_SH(dst42, dst31, dst21, dst43); + + dst0 = HEVC_FILT_4TAP(dst10, dst32, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21, dst43, filt_h0, filt_h1); + dst0 >>= 6; + dst1 >>= 6; + dst0 = (v4i32) __msa_pckev_h((v8i16) dst1, (v8i16) dst0); + ST8x2_UB(dst0, dst, dst_stride_in_bytes); } static void hevc_hv_4t_4x4_msa(uint8_t *src, @@ -3066,16 +3215,16 @@ static void hevc_hv_4t_4x4_msa(uint8_t *src, const int8_t *filter_x, const int8_t *filter_y) { + int32_t dst_stride_in_bytes = 2 * dst_stride; v16i8 src0, src1, src2, src3, src4, src5, src6; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; + v8i16 dst30, dst41, dst52, dst63, dst10, dst32, dst54, dst21, dst43, dst65; + v4i32 dst0, dst1, dst2, dst3; src -= (src_stride + 1); @@ -3083,71 +3232,43 @@ static void hevc_hv_4t_4x4_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; const_vec = __msa_ldi_h(128); const_vec <<= 6; - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); - - XORI_B3_128_SB(src0, src1, src2); - - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); - - LD_SB4(src, src_stride, src3, src4, src5, src6); - XORI_B4_128_SB(src3, src4, src5, src6); - - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - dst32_r = __msa_ilvr_h(dst3, dst2); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; - - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - dst43_r = __msa_ilvr_h(dst4, dst3); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - dst10_r = __msa_ilvr_h(dst5, dst4); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_r >>= 6; - - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); + LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); - dst21_r = __msa_ilvr_h(dst2, dst5); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_r >>= 6; + VSHF_B2_SB(src0, src3, src0, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src4, src1, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src5, src2, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src3, src6, src3, src6, mask0, mask1, vec6, vec7); - PCKEV_H2_SW(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r, dst1_r); - ST8x4_UB(dst0_r, dst1_r, dst, 2 * dst_stride); + dst30 = const_vec; + dst41 = const_vec; + dst52 = const_vec; + dst63 = const_vec; + DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst30, dst30); + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst41, dst41); + DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst52, dst52); + DPADD_SB2_SH(vec6, vec7, filt0, filt1, dst63, dst63); + + ILVRL_H2_SH(dst41, dst30, dst10, dst43); + ILVRL_H2_SH(dst52, dst41, dst21, dst54); + ILVRL_H2_SH(dst63, dst52, dst32, dst65); + + dst0 = HEVC_FILT_4TAP(dst10, dst32, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21, dst43, filt_h0, filt_h1); + dst2 = HEVC_FILT_4TAP(dst32, dst54, filt_h0, filt_h1); + dst3 = HEVC_FILT_4TAP(dst43, dst65, filt_h0, filt_h1); + SRA_4V(dst0, dst1, dst2, dst3, 6); + PCKEV_H2_SW(dst1, dst0, dst3, dst2, dst0, dst2); + ST8x4_UB(dst0, dst2, dst, dst_stride_in_bytes); } @@ -3163,25 +3284,24 @@ static void hevc_hv_4t_4multx8mult_msa(uint8_t *src, v16i8 src0, src1, src2, src3, src4, src5, src6; v16i8 src7, src8, src9, src10; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); v16i8 mask1; v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8, dst9; - v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r, dst6_r, dst7_r; - v8i16 dst10_r, dst32_r, dst54_r, dst76_r; - v8i16 dst21_r, dst43_r, dst65_r, dst87_r; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 dst10, dst21, dst22, dst73, dst84, dst95, dst106; + v8i16 dst10_r, dst32_r, dst54_r, dst76_r, dst98_r; + v8i16 dst21_r, dst43_r, dst65_r, dst87_r, dst109_r; + v4i32 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; src -= (src_stride + 1); filter_vec = LD_SH(filter_x); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; @@ -3191,19 +3311,14 @@ static void hevc_hv_4t_4multx8mult_msa(uint8_t *src, LD_SB3(src, src_stride, src0, src1, src2); src += (3 * src_stride); XORI_B3_128_SB(src0, src1, src2); - - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - - ILVR_H2_SH(dst1, dst0, dst2, dst1, dst10_r, dst21_r); + VSHF_B2_SB(src0, src1, src0, src1, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src2, src1, src2, mask0, mask1, vec2, vec3); + dst10 = const_vec; + DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst10, dst10); + dst21 = const_vec; + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst21, dst21); + ILVRL_H2_SH(dst21, dst10, dst10_r, dst21_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst21, 1); for (loop_cnt = height >> 3; loop_cnt--;) { LD_SB8(src, src_stride, @@ -3211,75 +3326,45 @@ static void hevc_hv_4t_4multx8mult_msa(uint8_t *src, src += (8 * src_stride); XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - dst32_r = __msa_ilvr_h(dst3, dst2); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_r >>= 6; - - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - dst43_r = __msa_ilvr_h(dst4, dst3); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_r >>= 6; - - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - dst54_r = __msa_ilvr_h(dst5, dst4); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); - dst2_r >>= 6; - - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); - - dst65_r = __msa_ilvr_h(dst6, dst5); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); - dst3_r >>= 6; - - VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); - dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); - - dst76_r = __msa_ilvr_h(dst7, dst6); - dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); - dst4_r >>= 6; - - VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec0, vec1); - dst8 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst8, dst8); - - dst87_r = __msa_ilvr_h(dst8, dst7); - dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); - dst5_r >>= 6; - - VSHF_B2_SB(src9, src9, src9, src9, mask0, mask1, vec0, vec1); - dst9 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst9, dst9); - - dst10_r = __msa_ilvr_h(dst9, dst8); - dst6_r = HEVC_FILT_4TAP(dst76_r, dst10_r, filt_h0, filt_h1); - dst6_r >>= 6; - - VSHF_B2_SB(src10, src10, src10, src10, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - dst21_r = __msa_ilvr_h(dst2, dst9); - dst7_r = HEVC_FILT_4TAP(dst87_r, dst21_r, filt_h0, filt_h1); - dst7_r >>= 6; - - PCKEV_H4_SW(dst1_r, dst0_r, dst3_r, dst2_r, - dst5_r, dst4_r, dst7_r, dst6_r, - dst0_r, dst1_r, dst2_r, dst3_r); - ST8x8_UB(dst0_r, dst1_r, dst2_r, dst3_r, dst, 2 * dst_stride); + VSHF_B2_SB(src3, src7, src3, src7, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src8, src4, src8, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src9, src5, src9, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src10, src6, src10, mask0, mask1, vec6, vec7); + + dst73 = const_vec; + dst84 = const_vec; + dst95 = const_vec; + dst106 = const_vec; + DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst73, dst73); + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst84, dst84); + DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst95, dst95); + DPADD_SB2_SH(vec6, vec7, filt0, filt1, dst106, dst106); + + dst32_r = __msa_ilvr_h(dst73, dst22); + ILVRL_H2_SH(dst84, dst73, dst43_r, dst87_r); + ILVRL_H2_SH(dst95, dst84, dst54_r, dst98_r); + ILVRL_H2_SH(dst106, dst95, dst65_r, dst109_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst73, 1); + dst76_r = __msa_ilvr_h(dst22, dst106); + + dst0 = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst1 = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst2 = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst3 = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst4 = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); + dst5 = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); + dst6 = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7 = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + SRA_4V(dst0, dst1, dst2, dst3, 6); + SRA_4V(dst4, dst5, dst6, dst7, 6); + PCKEV_H4_SW(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, + dst0, dst1, dst2, dst3); + ST8x8_UB(dst0, dst1, dst2, dst3, dst, 2 * dst_stride); dst += (8 * dst_stride); + + dst10_r = dst98_r; + dst21_r = dst109_r; + dst22 = (v8i16) __msa_splati_d((v2i64) dst106, 1); } } @@ -3311,30 +3396,31 @@ static void hevc_hv_4t_6w_msa(uint8_t *src, const int8_t *filter_y, int32_t height) { - uint32_t loop_cnt; - uint64_t dst_val0, dst_val1, dst_val2, dst_val3; - uint32_t dst_val_int0, dst_val_int1, dst_val_int2, dst_val_int3; - v16i8 src0, src1, src2, src3, src4, src5, src6; + int32_t dst_stride_in_bytes = 2 * dst_stride; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; - v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; - v8i16 dst10_l, dst32_l, dst21_l, dst43_l; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6, dsth7, dsth8, dsth9; + v8i16 dsth10, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + v8i16 dst10_r, dst32_r, dst54_r, dst76_r, dst98_r, dst21_r, dst43_r; + v8i16 dst65_r, dst87_r, dst109_r, dst10_l, dst32_l, dst54_l, dst76_l; + v8i16 dst98_l, dst21_l, dst43_l, dst65_l, dst87_l, dst109_l; + v8i16 dst1021_l, dst3243_l, dst5465_l, dst7687_l, dst98109_l; + v4i32 dst0_r, dst1_r, dst2_r, dst3_r, dst4_r, dst5_r, dst6_r, dst7_r; + v4i32 dst0_l, dst1_l, dst2_l, dst3_l; src -= (src_stride + 1); filter_vec = LD_SH(filter_x); SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; @@ -3349,89 +3435,83 @@ static void hevc_hv_4t_6w_msa(uint8_t *src, VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - dst1 = const_vec; - DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); - dst2 = const_vec; - DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - - ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); - ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); - - for (loop_cnt = height >> 2; loop_cnt--;) { - LD_SB4(src, src_stride, src3, src4, src5, src6); - src += (4 * src_stride); - XORI_B4_128_SB(src3, src4, src5, src6); - - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); - dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); - dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); - dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - ILVRL_H2_SH(dst5, dst4, dst10_r, dst10_l); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_l = HEVC_FILT_4TAP(dst32_l, dst10_l, filt_h0, filt_h1); - dst2_r >>= 6; - dst2_l >>= 6; - - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - ILVRL_H2_SH(dst2, dst5, dst21_r, dst21_l); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_l = HEVC_FILT_4TAP(dst43_l, dst21_l, filt_h0, filt_h1); - dst3_r >>= 6; - dst3_l >>= 6; + dsth0 = const_vec; + dsth1 = const_vec; + dsth2 = const_vec; + DPADD_SB2_SH(vec0, vec1, filt0, filt1, dsth0, dsth0); + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dsth1, dsth1); + DPADD_SB2_SH(vec4, vec5, filt0, filt1, dsth2, dsth2); - PCKEV_H4_SW(dst0_l, dst0_r, dst1_l, dst1_r, - dst2_l, dst2_r, dst3_l, dst3_r, - dst0_r, dst1_r, dst2_r, dst3_r); + ILVRL_H2_SH(dsth1, dsth0, dst10_r, dst10_l); + ILVRL_H2_SH(dsth2, dsth1, dst21_r, dst21_l); - dst_val0 = __msa_copy_u_d((v2i64) dst0_r, 0); - dst_val1 = __msa_copy_u_d((v2i64) dst1_r, 0); - dst_val2 = __msa_copy_u_d((v2i64) dst2_r, 0); - dst_val3 = __msa_copy_u_d((v2i64) dst3_r, 0); + LD_SB8(src, src_stride, src3, src4, src5, src6, src7, src8, src9, src10); + XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); - dst_val_int0 = __msa_copy_u_w((v4i32) dst0_r, 2); - dst_val_int1 = __msa_copy_u_w((v4i32) dst1_r, 2); - dst_val_int2 = __msa_copy_u_w((v4i32) dst2_r, 2); - dst_val_int3 = __msa_copy_u_w((v4i32) dst3_r, 2); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + + dsth3 = const_vec; + dsth4 = const_vec; + dsth5 = const_vec; + dsth6 = const_vec; + DPADD_SB2_SH(vec0, vec1, filt0, filt1, dsth3, dsth3); + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dsth4, dsth4); + DPADD_SB2_SH(vec4, vec5, filt0, filt1, dsth5, dsth5); + DPADD_SB2_SH(vec6, vec7, filt0, filt1, dsth6, dsth6); - SD(dst_val0, dst); - SW(dst_val_int0, dst + 4); - dst += dst_stride; - SD(dst_val1, dst); - SW(dst_val_int1, dst + 4); - dst += dst_stride; - SD(dst_val2, dst); - SW(dst_val_int2, dst + 4); - dst += dst_stride; - SD(dst_val3, dst); - SW(dst_val_int3, dst + 4); - dst += dst_stride; + VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src9, src9, src9, src9, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src10, src10, src10, src10, mask0, mask1, vec6, vec7); + + dsth7 = const_vec; + dsth8 = const_vec; + dsth9 = const_vec; + dsth10 = const_vec; + DPADD_SB2_SH(vec0, vec1, filt0, filt1, dsth7, dsth7); + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dsth8, dsth8); + DPADD_SB2_SH(vec4, vec5, filt0, filt1, dsth9, dsth9); + DPADD_SB2_SH(vec6, vec7, filt0, filt1, dsth10, dsth10); + + ILVRL_H2_SH(dsth3, dsth2, dst32_r, dst32_l); + ILVRL_H2_SH(dsth4, dsth3, dst43_r, dst43_l); + ILVRL_H2_SH(dsth5, dsth4, dst54_r, dst54_l); + ILVRL_H2_SH(dsth6, dsth5, dst65_r, dst65_l); + ILVRL_H2_SH(dsth7, dsth6, dst76_r, dst76_l); + ILVRL_H2_SH(dsth8, dsth7, dst87_r, dst87_l); + ILVRL_H2_SH(dsth9, dsth8, dst98_r, dst98_l); + ILVRL_H2_SH(dsth10, dsth9, dst109_r, dst109_l); + + PCKEV_D2_SH(dst21_l, dst10_l, dst43_l, dst32_l, dst1021_l, dst3243_l); + PCKEV_D2_SH(dst65_l, dst54_l, dst87_l, dst76_l, dst5465_l, dst7687_l); + dst98109_l = (v8i16) __msa_pckev_d((v2i64) dst109_l, (v2i64) dst98_l); - } + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); + dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); + dst6_r = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + dst7_r = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst1021_l, dst3243_l, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst3243_l, dst5465_l, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst5465_l, dst7687_l, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst7687_l, dst98109_l, filt_h0, filt_h1); + SRA_4V(dst0_r, dst1_r, dst2_r, dst3_r, 6); + SRA_4V(dst4_r, dst5_r, dst6_r, dst7_r, 6); + SRA_4V(dst0_l, dst1_l, dst2_l, dst3_l, 6); + PCKEV_H2_SH(dst1_r, dst0_r, dst3_r, dst2_r, tmp0, tmp1); + PCKEV_H2_SH(dst5_r, dst4_r, dst7_r, dst6_r, tmp2, tmp3); + PCKEV_H2_SH(dst1_l, dst0_l, dst3_l, dst2_l, tmp4, tmp5); + ST8x4_UB(tmp0, tmp1, dst, dst_stride_in_bytes); + ST4x4_UB(tmp4, tmp4, 0, 1, 2, 3, dst + 4, dst_stride_in_bytes); + dst += 4 * dst_stride; + ST8x4_UB(tmp2, tmp3, dst, dst_stride_in_bytes); + ST4x4_UB(tmp5, tmp5, 0, 1, 2, 3, dst + 4, dst_stride_in_bytes); } static void hevc_hv_4t_8x2_msa(uint8_t *src, @@ -3439,16 +3519,15 @@ static void hevc_hv_4t_8x2_msa(uint8_t *src, int16_t *dst, int32_t dst_stride, const int8_t *filter_x, - const int8_t *filter_y, - int32_t height) + const int8_t *filter_y) { v16i8 src0, src1, src2, src3, src4; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; v8i16 dst0, dst1, dst2, dst3, dst4; v4i32 dst0_r, dst0_l, dst1_r, dst1_l; v8i16 dst10_r, dst32_r, dst21_r, dst43_r; @@ -3460,23 +3539,23 @@ static void hevc_hv_4t_8x2_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; const_vec = __msa_ldi_h(128); const_vec <<= 6; - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); - XORI_B3_128_SB(src0, src1, src2); + LD_SB5(src, src_stride, src0, src1, src2, src3, src4); + XORI_B5_128_SB(src0, src1, src2, src3, src4); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec8, vec9); dst0 = const_vec; DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); @@ -3484,53 +3563,123 @@ static void hevc_hv_4t_8x2_msa(uint8_t *src, DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); dst2 = const_vec; DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); + dst3 = const_vec; + DPADD_SB2_SH(vec6, vec7, filt0, filt1, dst3, dst3); + dst4 = const_vec; + DPADD_SB2_SH(vec8, vec9, filt0, filt1, dst4, dst4); ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); - - LD_SB2(src, src_stride, src3, src4); - src += (2 * src_stride); - XORI_B2_128_SB(src3, src4); - - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - dst0_r >>= 6; - dst0_l >>= 6; - - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); PCKEV_H2_SW(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r, dst1_r); ST_SW2(dst0_r, dst1_r, dst, dst_stride); } +static void hevc_hv_4t_8multx4_msa(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter_x, + const int8_t *filter_y, int32_t width8mult) +{ + int32_t cnt; + v16i8 src0, src1, src2, src3, src4, src5, src6, mask0, mask1; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 filt0, filt1, filt_h0, filt_h1, filter_vec, const_vec; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6; + v8i16 dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + + src -= (src_stride + 1); + + filter_vec = LD_SH(filter_x); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + + const_vec = __msa_ldi_h(128); + const_vec <<= 6; + + for (cnt = width8mult; cnt--;) { + LD_SB7(src, src_stride, src0, src1, src2, src3, src4, src5, src6); + src += 8; + XORI_B7_128_SB(src0, src1, src2, src3, src4, src5, src6); + + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + + dst0 = const_vec; + dst1 = const_vec; + dst2 = const_vec; + DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); + DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); + + ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); + ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); + + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + dst3 = const_vec; + dst4 = const_vec; + dst5 = const_vec; + dst6 = const_vec; + DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst4, dst4); + DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst5, dst5); + DPADD_SB2_SH(vec6, vec7, filt0, filt1, dst6, dst6); + ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); + + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + PCKEV_H2_SW(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r, dst1_r); + PCKEV_H2_SW(dst2_l, dst2_r, dst3_l, dst3_r, dst2_r, dst3_r); + + ST_SW4(dst0_r, dst1_r, dst2_r, dst3_r, dst, dst_stride); + dst += 8; + } +} + static void hevc_hv_4t_8x6_msa(uint8_t *src, int32_t src_stride, int16_t *dst, int32_t dst_stride, const int8_t *filter_x, - const int8_t *filter_y, - int32_t height) + const int8_t *filter_y) { v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; + v16i8 vec10, vec11, vec12, vec13, vec14, vec15, vec16, vec17; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; v4i32 dst4_r, dst4_l, dst5_r, dst5_l; @@ -3545,24 +3694,31 @@ static void hevc_hv_4t_8x6_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; const_vec = __msa_ldi_h(128); const_vec <<= 6; - LD_SB3(src, src_stride, src0, src1, src2); - src += (3 * src_stride); + LD_SB5(src, src_stride, src0, src1, src2, src3, src4); + src += (5 * src_stride); + LD_SB4(src, src_stride, src5, src6, src7, src8); - XORI_B3_128_SB(src0, src1, src2); + XORI_B5_128_SB(src0, src1, src2, src3, src4); + XORI_B4_128_SB(src5, src6, src7, src8); VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec6, vec7); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec8, vec9); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec10, vec11); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec12, vec13); + VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec14, vec15); + VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec16, vec17); dst0 = const_vec; DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); @@ -3570,91 +3726,44 @@ static void hevc_hv_4t_8x6_msa(uint8_t *src, DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); dst2 = const_vec; DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); + dst3 = const_vec; + DPADD_SB2_SH(vec6, vec7, filt0, filt1, dst3, dst3); + dst4 = const_vec; + DPADD_SB2_SH(vec8, vec9, filt0, filt1, dst4, dst4); + dst5 = const_vec; + DPADD_SB2_SH(vec10, vec11, filt0, filt1, dst5, dst5); + dst6 = const_vec; + DPADD_SB2_SH(vec12, vec13, filt0, filt1, dst6, dst6); + dst7 = const_vec; + DPADD_SB2_SH(vec14, vec15, filt0, filt1, dst7, dst7); + dst8 = const_vec; + DPADD_SB2_SH(vec16, vec17, filt0, filt1, dst8, dst8); ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); - - LD_SB2(src, src_stride, src3, src4); - src += (2 * src_stride); - - XORI_B2_128_SB(src3, src4); - - /* row 3 */ - VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); - dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); + ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); + ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - - dst0_r >>= 6; - dst0_l >>= 6; - - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - - LD_SB2(src, src_stride, src5, src6); - src += (2 * src_stride); - - XORI_B2_128_SB(src5, src6); - - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); - - ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); - dst2_r >>= 6; - dst2_l >>= 6; - - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst6 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst6, dst6); - - ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); - dst3_r >>= 6; - dst3_l >>= 6; - - LD_SB2(src, src_stride, src7, src8); - - XORI_B2_128_SB(src7, src8); - - /* row 7 */ - VSHF_B2_SB(src7, src7, src7, src7, mask0, mask1, vec0, vec1); - dst7 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst7, dst7); - - ILVRL_H2_SH(dst7, dst6, dst76_r, dst76_l); dst4_r = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); dst4_l = HEVC_FILT_4TAP(dst54_l, dst76_l, filt_h0, filt_h1); - dst4_r >>= 6; - dst4_l >>= 6; - - /* row 8 */ - VSHF_B2_SB(src8, src8, src8, src8, mask0, mask1, vec0, vec1); - dst8 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst8, dst8); - - ILVRL_H2_SH(dst8, dst7, dst87_r, dst87_l); dst5_r = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); dst5_l = HEVC_FILT_4TAP(dst65_l, dst87_l, filt_h0, filt_h1); - dst5_r >>= 6; - dst5_l >>= 6; + + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + SRA_4V(dst4_r, dst4_l, dst5_r, dst5_l, 6); PCKEV_H4_SW(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r, dst2_r, dst3_r); @@ -3674,22 +3783,22 @@ static void hevc_hv_4t_8multx4mult_msa(uint8_t *src, const int8_t *filter_x, const int8_t *filter_y, int32_t height, - int32_t width) + int32_t width8mult) { uint32_t loop_cnt, cnt; uint8_t *src_tmp; int16_t *dst_tmp; v16i8 src0, src1, src2, src3, src4, src5, src6; v8i16 filt0, filt1; - v4i32 filt_h0, filt_h1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v8i16 filt_h0, filt_h1; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; v8i16 filter_vec, const_vec; - v16i8 vec0, vec1, vec2, vec3, vec4, vec5; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6; v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; - v8i16 dst10_r, dst32_r, dst21_r, dst43_r; - v8i16 dst10_l, dst32_l, dst21_l, dst43_l; + v8i16 dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; src -= (src_stride + 1); @@ -3697,17 +3806,16 @@ static void hevc_hv_4t_8multx4mult_msa(uint8_t *src, SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); filter_vec = LD_SH(filter_y); - vec0 = __msa_clti_s_b((v16i8) filter_vec, 0); - filter_vec = (v8i16) __msa_ilvr_b(vec0, (v16i8) filter_vec); + UNPCK_R_SB_SH(filter_vec, filter_vec); - SPLATI_W2_SW(filter_vec, 0, filt_h0, filt_h1); + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); mask1 = mask0 + 2; const_vec = __msa_ldi_h(128); const_vec <<= 6; - for (cnt = width >> 3; cnt--;) { + for (cnt = width8mult; cnt--;) { src_tmp = src; dst_tmp = dst; @@ -3736,59 +3844,48 @@ static void hevc_hv_4t_8multx4mult_msa(uint8_t *src, XORI_B4_128_SB(src3, src4, src5, src6); VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + dst3 = const_vec; + dst4 = const_vec; + dst5 = const_vec; + dst6 = const_vec; DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst4, dst4); + DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst5, dst5); + DPADD_SB2_SH(vec6, vec7, filt0, filt1, dst6, dst6); ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); - - dst0_r >>= 6; - dst0_l >>= 6; - - /* row 4 */ - VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec0, vec1); - dst4 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst4, dst4); - - ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); - dst1_r >>= 6; - dst1_l >>= 6; - - /* row 5 */ - VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec0, vec1); - dst5 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst5, dst5); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); - ILVRL_H2_SH(dst5, dst4, dst10_r, dst10_l); - dst2_r = HEVC_FILT_4TAP(dst32_r, dst10_r, filt_h0, filt_h1); - dst2_l = HEVC_FILT_4TAP(dst32_l, dst10_l, filt_h0, filt_h1); - - dst2_r >>= 6; - dst2_l >>= 6; - - /* row 6 */ - VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - ILVRL_H2_SH(dst2, dst5, dst21_r, dst21_l); - dst3_r = HEVC_FILT_4TAP(dst43_r, dst21_r, filt_h0, filt_h1); - dst3_l = HEVC_FILT_4TAP(dst43_l, dst21_l, filt_h0, filt_h1); - - dst3_r >>= 6; - dst3_l >>= 6; + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); PCKEV_H4_SW(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, dst3_r, dst0_r, dst1_r, dst2_r, dst3_r); - ST_SW2(dst0_r, dst1_r, dst_tmp, dst_stride); - dst_tmp += (2 * dst_stride); - ST_SW2(dst2_r, dst3_r, dst_tmp, dst_stride); - dst_tmp += (2 * dst_stride); + ST_SW4(dst0_r, dst1_r, dst2_r, dst3_r, dst_tmp, dst_stride); + dst_tmp += (4 * dst_stride); + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dst2 = dst6; } src += 8; @@ -3807,13 +3904,16 @@ static void hevc_hv_4t_8w_msa(uint8_t *src, if (2 == height) { hevc_hv_4t_8x2_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height); + filter_x, filter_y); + } else if (4 == height) { + hevc_hv_4t_8multx4_msa(src, src_stride, dst, dst_stride, + filter_x, filter_y, 1); } else if (6 == height) { hevc_hv_4t_8x6_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height); + filter_x, filter_y); } else if (0 == (height % 4)) { hevc_hv_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, 8); + filter_x, filter_y, height, 1); } } @@ -3825,12 +3925,169 @@ static void hevc_hv_4t_12w_msa(uint8_t *src, const int8_t *filter_y, int32_t height) { - hevc_hv_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, 8); + uint32_t loop_cnt; + uint8_t *src_tmp; + int16_t *dst_tmp; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + v16i8 mask0, mask1, mask2, mask3; + v8i16 filt0, filt1, filt_h0, filt_h1, filter_vec, const_vec; + v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst10, dst21, dst22, dst73; + v8i16 dst84, dst95, dst106, dst76_r, dst98_r, dst87_r, dst109_r; + v8i16 dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + v8i16 dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + v4i32 dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + v4i32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + + src -= (src_stride + 1); + + filter_vec = LD_SH(filter_x); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); + + filter_vec = LD_SH(filter_y); + UNPCK_R_SB_SH(filter_vec, filter_vec); + + SPLATI_W2_SH(filter_vec, 0, filt_h0, filt_h1); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + + const_vec = __msa_ldi_h(128); + const_vec <<= 6; + + src_tmp = src; + dst_tmp = dst; + + LD_SB3(src_tmp, src_stride, src0, src1, src2); + src_tmp += (3 * src_stride); + + XORI_B3_128_SB(src0, src1, src2); + + VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec4, vec5); + + dst0 = const_vec; + dst1 = const_vec; + dst2 = const_vec; + DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst1, dst1); + DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst2, dst2); - hevc_hv_4t_4w_msa(src + 8, src_stride, dst + 8, dst_stride, - filter_x, filter_y, height); + ILVRL_H2_SH(dst1, dst0, dst10_r, dst10_l); + ILVRL_H2_SH(dst2, dst1, dst21_r, dst21_l); + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src_tmp, src_stride, src3, src4, src5, src6); + src_tmp += (4 * src_stride); + XORI_B4_128_SB(src3, src4, src5, src6); + + VSHF_B2_SB(src3, src3, src3, src3, mask0, mask1, vec0, vec1); + VSHF_B2_SB(src4, src4, src4, src4, mask0, mask1, vec2, vec3); + VSHF_B2_SB(src5, src5, src5, src5, mask0, mask1, vec4, vec5); + VSHF_B2_SB(src6, src6, src6, src6, mask0, mask1, vec6, vec7); + dst3 = const_vec; + dst4 = const_vec; + dst5 = const_vec; + dst6 = const_vec; + DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst4, dst4); + DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst5, dst5); + DPADD_SB2_SH(vec6, vec7, filt0, filt1, dst6, dst6); + + ILVRL_H2_SH(dst3, dst2, dst32_r, dst32_l); + ILVRL_H2_SH(dst4, dst3, dst43_r, dst43_l); + ILVRL_H2_SH(dst5, dst4, dst54_r, dst54_l); + ILVRL_H2_SH(dst6, dst5, dst65_r, dst65_l); + + dst0_r = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + dst0_l = HEVC_FILT_4TAP(dst10_l, dst32_l, filt_h0, filt_h1); + dst1_r = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + dst1_l = HEVC_FILT_4TAP(dst21_l, dst43_l, filt_h0, filt_h1); + dst2_r = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + dst2_l = HEVC_FILT_4TAP(dst32_l, dst54_l, filt_h0, filt_h1); + dst3_r = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + dst3_l = HEVC_FILT_4TAP(dst43_l, dst65_l, filt_h0, filt_h1); + + SRA_4V(dst0_r, dst0_l, dst1_r, dst1_l, 6); + SRA_4V(dst2_r, dst2_l, dst3_r, dst3_l, 6); + PCKEV_H4_SW(dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, dst3_l, + dst3_r, dst0_r, dst1_r, dst2_r, dst3_r); + ST_SW4(dst0_r, dst1_r, dst2_r, dst3_r, dst_tmp, dst_stride); + dst_tmp += (4 * dst_stride); + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dst2 = dst6; + } + + src += 8; + dst += 8; + + mask2 = LD_SB(ff_hevc_mask_arr + 16); + mask3 = mask2 + 2; + + LD_SB3(src, src_stride, src0, src1, src2); + src += (3 * src_stride); + XORI_B3_128_SB(src0, src1, src2); + VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); + VSHF_B2_SB(src1, src2, src1, src2, mask2, mask3, vec2, vec3); + dst10 = const_vec; + dst21 = const_vec; + DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst10, dst10); + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst21, dst21); + ILVRL_H2_SH(dst21, dst10, dst10_r, dst21_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst21, 1); + + for (loop_cnt = 2; loop_cnt--;) { + LD_SB8(src, src_stride, src3, src4, src5, src6, src7, src8, src9, + src10); + src += (8 * src_stride); + XORI_B8_128_SB(src3, src4, src5, src6, src7, src8, src9, src10); + VSHF_B2_SB(src3, src7, src3, src7, mask2, mask3, vec0, vec1); + VSHF_B2_SB(src4, src8, src4, src8, mask2, mask3, vec2, vec3); + VSHF_B2_SB(src5, src9, src5, src9, mask2, mask3, vec4, vec5); + VSHF_B2_SB(src6, src10, src6, src10, mask2, mask3, vec6, vec7); + + dst73 = const_vec; + dst84 = const_vec; + dst95 = const_vec; + dst106 = const_vec; + DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst73, dst73); + DPADD_SB2_SH(vec2, vec3, filt0, filt1, dst84, dst84); + DPADD_SB2_SH(vec4, vec5, filt0, filt1, dst95, dst95); + DPADD_SB2_SH(vec6, vec7, filt0, filt1, dst106, dst106); + + dst32_r = __msa_ilvr_h(dst73, dst22); + ILVRL_H2_SH(dst84, dst73, dst43_r, dst87_r); + ILVRL_H2_SH(dst95, dst84, dst54_r, dst98_r); + ILVRL_H2_SH(dst106, dst95, dst65_r, dst109_r); + dst22 = (v8i16) __msa_splati_d((v2i64) dst73, 1); + dst76_r = __msa_ilvr_h(dst22, dst106); + + tmp0 = HEVC_FILT_4TAP(dst10_r, dst32_r, filt_h0, filt_h1); + tmp1 = HEVC_FILT_4TAP(dst21_r, dst43_r, filt_h0, filt_h1); + tmp2 = HEVC_FILT_4TAP(dst32_r, dst54_r, filt_h0, filt_h1); + tmp3 = HEVC_FILT_4TAP(dst43_r, dst65_r, filt_h0, filt_h1); + tmp4 = HEVC_FILT_4TAP(dst54_r, dst76_r, filt_h0, filt_h1); + tmp5 = HEVC_FILT_4TAP(dst65_r, dst87_r, filt_h0, filt_h1); + tmp6 = HEVC_FILT_4TAP(dst76_r, dst98_r, filt_h0, filt_h1); + tmp7 = HEVC_FILT_4TAP(dst87_r, dst109_r, filt_h0, filt_h1); + + SRA_4V(tmp0, tmp1, tmp2, tmp3, 6); + SRA_4V(tmp4, tmp5, tmp6, tmp7, 6); + PCKEV_H4_SW(tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, tmp7, tmp6, tmp0, tmp1, + tmp2, tmp3); + ST8x8_UB(tmp0, tmp1, tmp2, tmp3, dst, 2 * dst_stride); + dst += (8 * dst_stride); + + dst10_r = dst98_r; + dst21_r = dst109_r; + dst22 = (v8i16) __msa_splati_d((v2i64) dst106, 1); + } } static void hevc_hv_4t_16w_msa(uint8_t *src, @@ -3841,8 +4098,13 @@ static void hevc_hv_4t_16w_msa(uint8_t *src, const int8_t *filter_y, int32_t height) { - hevc_hv_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, 16); + if (4 == height) { + hevc_hv_4t_8multx4_msa(src, src_stride, dst, dst_stride, + filter_x, filter_y, 2); + } else { + hevc_hv_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 2); + } } static void hevc_hv_4t_24w_msa(uint8_t *src, @@ -3854,7 +4116,7 @@ static void hevc_hv_4t_24w_msa(uint8_t *src, int32_t height) { hevc_hv_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, 24); + filter_x, filter_y, height, 3); } static void hevc_hv_4t_32w_msa(uint8_t *src, @@ -3866,7 +4128,7 @@ static void hevc_hv_4t_32w_msa(uint8_t *src, int32_t height) { hevc_hv_4t_8multx4mult_msa(src, src_stride, dst, dst_stride, - filter_x, filter_y, height, 32); + filter_x, filter_y, height, 4); } #define MC_COPY(WIDTH) \ @@ -3893,19 +4155,19 @@ MC_COPY(64); #undef MC_COPY -#define MC(PEL, DIR, WIDTH, TAP, DIR1, FILT_DIR) \ -void ff_hevc_put_hevc_##PEL##_##DIR##WIDTH##_8_msa(int16_t *dst, \ - uint8_t *src, \ - ptrdiff_t src_stride, \ - int height, \ - intptr_t mx, \ - intptr_t my, \ - int width) \ -{ \ - const int8_t *filter = ff_hevc_##PEL##_filters[FILT_DIR - 1]; \ - \ - hevc_##DIR1##_##TAP##t_##WIDTH##w_msa(src, src_stride, dst, \ - MAX_PB_SIZE, filter, height); \ +#define MC(PEL, DIR, WIDTH, TAP, DIR1, FILT_DIR) \ +void ff_hevc_put_hevc_##PEL##_##DIR##WIDTH##_8_msa(int16_t *dst, \ + uint8_t *src, \ + ptrdiff_t src_stride, \ + int height, \ + intptr_t mx, \ + intptr_t my, \ + int width) \ +{ \ + const int8_t *filter = ff_hevc_##PEL##_filters[FILT_DIR - 1]; \ + \ + hevc_##DIR1##_##TAP##t_##WIDTH##w_msa(src, src_stride, dst, \ + MAX_PB_SIZE, filter, height); \ } MC(qpel, h, 4, 8, hz, mx); @@ -3944,37 +4206,37 @@ MC(epel, v, 32, 4, vt, my); #undef MC -#define MC_HV(PEL, DIR, WIDTH, TAP, DIR1) \ -void ff_hevc_put_hevc_##PEL##_##DIR##WIDTH##_8_msa(int16_t *dst, \ - uint8_t *src, \ - ptrdiff_t src_stride, \ - int height, \ - intptr_t mx, \ - intptr_t my, \ - int width) \ -{ \ - const int8_t *filter_x = ff_hevc_##PEL##_filters[mx - 1]; \ - const int8_t *filter_y = ff_hevc_##PEL##_filters[my - 1]; \ - \ - hevc_##DIR1##_##TAP##t_##WIDTH##w_msa(src, src_stride, dst, MAX_PB_SIZE, \ - filter_x, filter_y, height); \ -} - -MC_HV(qpel, hv, 4, 8, hv); -MC_HV(qpel, hv, 8, 8, hv); -MC_HV(qpel, hv, 12, 8, hv); -MC_HV(qpel, hv, 16, 8, hv); -MC_HV(qpel, hv, 24, 8, hv); -MC_HV(qpel, hv, 32, 8, hv); -MC_HV(qpel, hv, 48, 8, hv); -MC_HV(qpel, hv, 64, 8, hv); - -MC_HV(epel, hv, 4, 4, hv); -MC_HV(epel, hv, 6, 4, hv); -MC_HV(epel, hv, 8, 4, hv); -MC_HV(epel, hv, 12, 4, hv); -MC_HV(epel, hv, 16, 4, hv); -MC_HV(epel, hv, 24, 4, hv); -MC_HV(epel, hv, 32, 4, hv); +#define MC_HV(PEL, WIDTH, TAP) \ +void ff_hevc_put_hevc_##PEL##_hv##WIDTH##_8_msa(int16_t *dst, \ + uint8_t *src, \ + ptrdiff_t src_stride, \ + int height, \ + intptr_t mx, \ + intptr_t my, \ + int width) \ +{ \ + const int8_t *filter_x = ff_hevc_##PEL##_filters[mx - 1]; \ + const int8_t *filter_y = ff_hevc_##PEL##_filters[my - 1]; \ + \ + hevc_hv_##TAP##t_##WIDTH##w_msa(src, src_stride, dst, MAX_PB_SIZE, \ + filter_x, filter_y, height); \ +} + +MC_HV(qpel, 4, 8); +MC_HV(qpel, 8, 8); +MC_HV(qpel, 12, 8); +MC_HV(qpel, 16, 8); +MC_HV(qpel, 24, 8); +MC_HV(qpel, 32, 8); +MC_HV(qpel, 48, 8); +MC_HV(qpel, 64, 8); + +MC_HV(epel, 4, 4); +MC_HV(epel, 6, 4); +MC_HV(epel, 8, 4); +MC_HV(epel, 12, 4); +MC_HV(epel, 16, 4); +MC_HV(epel, 24, 4); +MC_HV(epel, 32, 4); #undef MC_HV From 349e9a878767fe755de5fe256fd55a7de22cb937 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 8 Nov 2017 17:01:44 -0300 Subject: [PATCH 0795/2557] avformat/ty: fix format specifiers in debug log messages Signed-off-by: James Almer --- libavformat/ty.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/ty.c b/libavformat/ty.c index 1ce72dd0f9855..02ab59aa2e152 100644 --- a/libavformat/ty.c +++ b/libavformat/ty.c @@ -538,14 +538,14 @@ static int check_sync_pes(AVFormatContext *s, AVPacket *pkt, if (offset < 0 || offset + ty->pes_length > rec_len) { /* entire PES header not present */ - ff_dlog(s, "PES header at %d not complete in record. storing.\n", offset); + ff_dlog(s, "PES header at %"PRId32" not complete in record. storing.\n", offset); /* save the partial pes header */ if (offset < 0) { /* no header found, fake some 00's (this works, believe me) */ memset(ty->pes_buffer, 0, 4); ty->pes_buf_cnt = 4; if (rec_len > 4) - ff_dlog(s, "PES header not found in record of %d bytes!\n", rec_len); + ff_dlog(s, "PES header not found in record of %"PRId32" bytes!\n", rec_len); return -1; } /* copy the partial pes header we found */ From da99b3f0c90a47210cb802a15366babad22f2c70 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Wed, 8 Nov 2017 09:15:29 +0100 Subject: [PATCH 0796/2557] lavfi/scale2ref: Set output frame rate to main input frame rate. Fixes ticket #6817. --- libavfilter/vf_scale.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 3329c1234663e..2fd9c90d84f33 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -362,6 +362,7 @@ static int config_props_ref(AVFilterLink *outlink) outlink->h = inlink->h; outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; outlink->time_base = inlink->time_base; + outlink->frame_rate = inlink->frame_rate; return 0; } From 69218b41980883a7e75656f3058171939f5729ef Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 8 Nov 2017 19:32:09 -0300 Subject: [PATCH 0797/2557] configure: add missing avutil deps for hwcontext modules Fixes ticket #6812 Signed-off-by: James Almer --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 14f10dededf68..f396abda5bbb5 100755 --- a/configure +++ b/configure @@ -3313,7 +3313,7 @@ avformat_deps="avcodec avutil" avformat_suggest="libm network zlib" avresample_deps="avutil" avresample_suggest="libm" -avutil_suggest="clock_gettime libm libdrm libmfx opencl user32 vaapi videotoolbox corefoundation corevideo coremedia wincrypt" +avutil_suggest="clock_gettime cuda libm libdrm libmfx opencl user32 vaapi videotoolbox corefoundation corevideo coremedia wincrypt" postproc_deps="avutil gpl" postproc_suggest="libm" swresample_deps="avutil" @@ -3323,7 +3323,7 @@ swscale_suggest="libm" avcodec_extralibs="pthreads_extralibs iconv_extralibs" avfilter_extralibs="pthreads_extralibs" -avutil_extralibs="nanosleep_extralibs pthreads_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs" +avutil_extralibs="d3d11va_extralibs nanosleep_extralibs pthreads_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs" # programs ffmpeg_deps="avcodec avfilter avformat swresample" From 3228ac730c11eca49d5680d5550128e397061c85 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Wed, 8 Nov 2017 23:50:04 +0000 Subject: [PATCH 0798/2557] vc2enc_dwt: pad the temporary buffer by the slice size Since non-Haar wavelets need to look into pixels outside the frame, we need to pad the buffer. The old factor of two seemed to be a workaround that fact and only padded to the left and bottom. This correctly pads by the slice size and as such reduces memory usage and potential exploits. Reported by Liu Bingchang. Ideally, there should be no temporary buffer but the encoder is designed to deinterleave the coefficients into the classical wavelet structure with the lower frequency values in the top left corner. Signed-off-by: Rostislav Pehlivanov --- libavcodec/vc2enc.c | 3 ++- libavcodec/vc2enc_dwt.c | 12 +++++++++--- libavcodec/vc2enc_dwt.h | 4 +++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c index fa4ff54a3ce6a..0a8c3633ef842 100644 --- a/libavcodec/vc2enc.c +++ b/libavcodec/vc2enc.c @@ -1192,7 +1192,8 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx) /* DWT init */ if (ff_vc2enc_init_transforms(&s->transform_args[i].t, s->plane[i].coef_stride, - s->plane[i].dwt_height)) + s->plane[i].dwt_height, + s->slice_width, s->slice_height)) goto alloc_fail; } diff --git a/libavcodec/vc2enc_dwt.c b/libavcodec/vc2enc_dwt.c index c60b003a31303..d22af8a31380b 100644 --- a/libavcodec/vc2enc_dwt.c +++ b/libavcodec/vc2enc_dwt.c @@ -255,21 +255,27 @@ static void vc2_subband_dwt_haar_shift(VC2TransformContext *t, dwtcoef *data, dwt_haar(t, data, stride, width, height, 1); } -av_cold int ff_vc2enc_init_transforms(VC2TransformContext *s, int p_width, int p_height) +av_cold int ff_vc2enc_init_transforms(VC2TransformContext *s, int p_stride, + int p_height, int slice_w, int slice_h) { s->vc2_subband_dwt[VC2_TRANSFORM_9_7] = vc2_subband_dwt_97; s->vc2_subband_dwt[VC2_TRANSFORM_5_3] = vc2_subband_dwt_53; s->vc2_subband_dwt[VC2_TRANSFORM_HAAR] = vc2_subband_dwt_haar; s->vc2_subband_dwt[VC2_TRANSFORM_HAAR_S] = vc2_subband_dwt_haar_shift; - s->buffer = av_malloc(2*p_width*p_height*sizeof(dwtcoef)); + /* Pad by the slice size, only matters for non-Haar wavelets */ + s->buffer = av_calloc((p_stride + slice_w)*(p_height + slice_h), sizeof(dwtcoef)); if (!s->buffer) return 1; + s->padding = (slice_h >> 1)*p_stride + (slice_w >> 1); + s->buffer += s->padding; + return 0; } av_cold void ff_vc2enc_free_transforms(VC2TransformContext *s) { - av_freep(&s->buffer); + av_free(s->buffer - s->padding); + s->buffer = NULL; } diff --git a/libavcodec/vc2enc_dwt.h b/libavcodec/vc2enc_dwt.h index 7fbbfbe0ed9cf..a6932bcdaf096 100644 --- a/libavcodec/vc2enc_dwt.h +++ b/libavcodec/vc2enc_dwt.h @@ -41,12 +41,14 @@ enum VC2TransformType { typedef struct VC2TransformContext { dwtcoef *buffer; + int padding; void (*vc2_subband_dwt[VC2_TRANSFORMS_NB])(struct VC2TransformContext *t, dwtcoef *data, ptrdiff_t stride, int width, int height); } VC2TransformContext; -int ff_vc2enc_init_transforms(VC2TransformContext *t, int p_width, int p_height); +int ff_vc2enc_init_transforms(VC2TransformContext *t, int p_stride, int p_height, + int slice_w, int slice_h); void ff_vc2enc_free_transforms(VC2TransformContext *t); #endif /* AVCODEC_VC2ENC_DWT_H */ From 723b6baaf8db43d0872bad504c4f4c780b53516b Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Thu, 9 Nov 2017 02:34:54 +0000 Subject: [PATCH 0799/2557] pngdec: check for bprint finalization sucess on icc data parsing It can fail in case of OOM. Signed-off-by: Rostislav Pehlivanov --- libavcodec/pngdec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 0d6612cccafb8..5a3d2883749f9 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -862,6 +862,8 @@ static int decode_iccp_chunk(PNGDecContext *s, int length, AVFrame *f) return ret; av_bprint_finalize(&bp, (char **)&data); + if (!data) + return AVERROR(ENOMEM); sd = av_frame_new_side_data(f, AV_FRAME_DATA_ICC_PROFILE, bp.len); if (!sd) { From 0a771e6b32429f9195d431415bf707c28ef31fff Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Mon, 25 Sep 2017 20:28:08 +0100 Subject: [PATCH 0800/2557] pngdec: expose gAMA and cHRM chunks as side/meta data Signed-off-by: Rostislav Pehlivanov --- libavcodec/pngdec.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 5a3d2883749f9..20707f0ae5862 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -25,6 +25,7 @@ #include "libavutil/bprint.h" #include "libavutil/imgutils.h" #include "libavutil/stereo3d.h" +#include "libavutil/mastering_display_metadata.h" #include "avcodec.h" #include "bytestream.h" @@ -1167,7 +1168,7 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, AVDictionary **metadatap = NULL; uint32_t tag, length; int decode_next_dat = 0; - int ret; + int i, ret; for (;;) { length = bytestream2_get_bytes_left(&s->gb); @@ -1289,6 +1290,42 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, goto fail; break; } + case MKTAG('c', 'H', 'R', 'M'): { + AVMasteringDisplayMetadata *mdm = av_mastering_display_metadata_create_side_data(p); + if (!mdm) { + ret = AVERROR(ENOMEM); + goto fail; + } + + mdm->white_point[0] = av_make_q(bytestream2_get_be32(&s->gb), 100000); + mdm->white_point[1] = av_make_q(bytestream2_get_be32(&s->gb), 100000); + + /* RGB Primaries */ + for (i = 0; i < 3; i++) { + mdm->display_primaries[i][0] = av_make_q(bytestream2_get_be32(&s->gb), 100000); + mdm->display_primaries[i][1] = av_make_q(bytestream2_get_be32(&s->gb), 100000); + } + + mdm->has_primaries = 1; + bytestream2_skip(&s->gb, 4); /* crc */ + break; + } + case MKTAG('g', 'A', 'M', 'A'): { + AVBPrint bp; + char *gamma_str; + int num = bytestream2_get_be32(&s->gb); + + av_bprint_init(&bp, 0, -1); + av_bprintf(&bp, "%i/%i", num, 100000); + av_bprint_finalize(&bp, &gamma_str); + if (!gamma_str) + return AVERROR(ENOMEM); + + av_dict_set(&p->metadata, "gamma", gamma_str, AV_DICT_DONT_STRDUP_VAL); + + bytestream2_skip(&s->gb, 4); /* crc */ + break; + } case MKTAG('I', 'E', 'N', 'D'): if (!(s->pic_state & PNG_ALLIMAGE)) av_log(avctx, AV_LOG_ERROR, "IEND without all image\n"); From fbf295e2bd4d48d7a0a094ed5afce2fa5b6cf35a Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Mon, 3 Oct 2016 19:53:11 +0100 Subject: [PATCH 0801/2557] aacenc: support extended channel layouts using PCEs This commit implements support for PCE (Program Configuration Elements) in the AAC encoder, and as such allows for encoding of channel layouts not present in the presets defined by the spec (which only lists the 8 most common ones). This has been a highly requested feature and is also the first open source encoder to support this many layouts. Many thanks to pkviet who implemented support for and verified all channel layouts. --- Changelog | 1 + libavcodec/aacenc.c | 69 +++++++++- libavcodec/aacenc.h | 286 ++++++++++++++++++++++++++++++++++++++++- libavcodec/aacenctab.h | 13 +- 4 files changed, 361 insertions(+), 8 deletions(-) diff --git a/Changelog b/Changelog index 4f937216ebafd..c1c886193e8b8 100644 --- a/Changelog +++ b/Changelog @@ -10,6 +10,7 @@ version : - Raw AMR-NB and AMR-WB demuxers - TiVo ty/ty+ demuxer - Intel QSV-accelerated MJPEG encoding +- PCE support for extended channel layouts in the AAC encoder version 3.4: diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index 3efcbda4038c1..51e467f7549ed 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -50,6 +50,40 @@ static AVOnce aac_table_init = AV_ONCE_INIT; +static void put_pce(PutBitContext *pb, AVCodecContext *avctx) +{ + int i, j; + AACEncContext *s = avctx->priv_data; + AACPCEInfo *pce = &s->pce; + + put_bits(pb, 4, 0); + + put_bits(pb, 2, avctx->profile); + put_bits(pb, 4, s->samplerate_index); + + put_bits(pb, 4, pce->num_ele[0]); /* Front */ + put_bits(pb, 4, pce->num_ele[1]); /* Side */ + put_bits(pb, 4, pce->num_ele[2]); /* Back */ + put_bits(pb, 2, pce->num_ele[3]); /* LFE */ + put_bits(pb, 3, 0); /* Assoc data */ + put_bits(pb, 4, 0); /* CCs */ + + put_bits(pb, 1, 0); /* Stereo mixdown */ + put_bits(pb, 1, 0); /* Mono mixdown */ + put_bits(pb, 1, 0); /* Something else */ + + for (i = 0; i < 4; i++) { + for (j = 0; j < pce->num_ele[i]; j++) { + if (i < 3) + put_bits(pb, 1, pce->pairing[i][j]); + put_bits(pb, 4, pce->index[i][j]); + } + } + + avpriv_align_put_bits(pb); + put_bits(pb, 8, 0); +} + /** * Make AAC audio config object. * @see 1.6.2.1 "Syntax - AudioSpecificConfig" @@ -58,7 +92,7 @@ static void put_audio_specific_config(AVCodecContext *avctx) { PutBitContext pb; AACEncContext *s = avctx->priv_data; - int channels = s->channels - (s->channels == 8 ? 1 : 0); + int channels = (!s->needs_pce)*(s->channels - (s->channels == 8 ? 1 : 0)); init_put_bits(&pb, avctx->extradata, avctx->extradata_size); put_bits(&pb, 5, s->profile+1); //profile @@ -68,6 +102,8 @@ static void put_audio_specific_config(AVCodecContext *avctx) put_bits(&pb, 1, 0); //frame length - 1024 samples put_bits(&pb, 1, 0); //does not depend on core coder put_bits(&pb, 1, 0); //is not extension + if (s->needs_pce) + put_pce(&pb, avctx); //Explicitly Mark SBR absent put_bits(&pb, 11, 0x2b7); //sync extension @@ -488,7 +524,7 @@ static void copy_input_samples(AACEncContext *s, const AVFrame *frame) { int ch; int end = 2048 + (frame ? frame->nb_samples : 0); - const uint8_t *channel_map = aac_chan_maps[s->channels - 1]; + const uint8_t *channel_map = s->reorder_map; /* copy and remap input samples */ for (ch = 0; ch < s->channels; ch++) { @@ -920,16 +956,36 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) /* Constants */ s->last_frame_pb_count = 0; - avctx->extradata_size = 5; + avctx->extradata_size = 20; avctx->frame_size = 1024; avctx->initial_padding = 1024; s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120; /* Channel map and unspecified bitrate guessing */ s->channels = avctx->channels; - ERROR_IF(s->channels > AAC_MAX_CHANNELS || s->channels == 7, - "Unsupported number of channels: %d\n", s->channels); - s->chan_map = aac_chan_configs[s->channels-1]; + + s->needs_pce = 1; + for (i = 0; i < FF_ARRAY_ELEMS(aac_normal_chan_layouts); i++) { + if (avctx->channel_layout == aac_normal_chan_layouts[i]) { + s->needs_pce = s->options.pce; + break; + } + } + + if (s->needs_pce) { + for (i = 0; i < FF_ARRAY_ELEMS(aac_pce_configs); i++) + if (avctx->channel_layout == aac_pce_configs[i].layout) + break; + ERROR_IF(i == FF_ARRAY_ELEMS(aac_pce_configs), "Unsupported channel layout\n"); + av_log(avctx, AV_LOG_INFO, "Using a PCE to encode channel layout\n"); + s->pce = aac_pce_configs[i]; + s->reorder_map = s->pce.reorder_map; + s->chan_map = s->pce.config_map; + } else { + s->reorder_map = aac_chan_maps[s->channels - 1]; + s->chan_map = aac_chan_configs[s->channels - 1]; + } + if (!avctx->bit_rate) { for (i = 1; i <= s->chan_map[0]; i++) { avctx->bit_rate += s->chan_map[i] == TYPE_CPE ? 128000 : /* Pair */ @@ -1062,6 +1118,7 @@ static const AVOption aacenc_options[] = { {"aac_tns", "Temporal noise shaping", offsetof(AACEncContext, options.tns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS}, {"aac_ltp", "Long term prediction", offsetof(AACEncContext, options.ltp), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS}, {"aac_pred", "AAC-Main prediction", offsetof(AACEncContext, options.pred), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS}, + {"aac_pce", "Forces the use of PCEs", offsetof(AACEncContext, options.pce), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS}, {NULL} }; diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h index ea2d3b9628c03..5a015ca92e307 100644 --- a/libavcodec/aacenc.h +++ b/libavcodec/aacenc.h @@ -45,6 +45,7 @@ typedef struct AACEncOptions { int pns; int tns; int ltp; + int pce; int pred; int mid_side; int intensity_stereo; @@ -89,6 +90,286 @@ typedef struct AACQuantizeBandCostCacheEntry { uint16_t generation; } AACQuantizeBandCostCacheEntry; +typedef struct AACPCEInfo { + int64_t layout; + int num_ele[4]; ///< front, side, back, lfe + int pairing[3][8]; ///< front, side, back + int index[4][8]; ///< front, side, back, lfe + uint8_t config_map[16]; ///< configs the encoder's channel specific settings + uint8_t reorder_map[16]; ///< maps channels from lavc to aac order +} AACPCEInfo; + +/** + * List of PCE (Program Configuration Element) for the channel layouts listed + * in channel_layout.h + * + * For those wishing in the future to add other layouts: + * + * - num_ele: number of elements in each group of front, side, back, lfe channels + * (an element is of type SCE (single channel), CPE (channel pair) for + * the first 3 groups; and is LFE for LFE group). + * + * - pairing: 0 for an SCE element or 1 for a CPE; does not apply to LFE group + * + * - index: there are three independent indices for SCE, CPE and LFE; + * they are incremented irrespective of the group to which the element belongs; + * they are not reset when going from one group to another + * + * Example: for 7.0 channel layout, + * .pairing = { { 1, 0 }, { 1 }, { 1 }, }, (3 CPE and 1 SCE in front group) + * .index = { { 0, 0 }, { 1 }, { 2 }, }, + * (index is 0 for the single SCE but goes from 0 to 2 for the CPEs) + * + * The index order impacts the channel ordering. But is otherwise arbitrary + * (the sequence could have been 2, 0, 1 instead of 0, 1, 2). + * + * Spec allows for discontinuous indices, e.g. if one has a total of two SCE, + * SCE.0 SCE.15 is OK per spec; BUT it won't be decoded by our AAC decoder + * which at this time requires that indices fully cover some range starting + * from 0 (SCE.1 SCE.0 is OK but not SCE.0 SCE.15). + * + * - config_map: total number of elements and their types. Beware, the way the + * types are ordered impacts the final channel ordering. + * + * - reorder_map: reorders the channels. + * + */ +static const AACPCEInfo aac_pce_configs[] = { + { + .layout = AV_CH_LAYOUT_MONO, + .num_ele = { 1, 0, 0, 0 }, + .pairing = { { 0 }, }, + .index = { { 0 }, }, + .config_map = { 1, TYPE_SCE, }, + .reorder_map = { 0 }, + }, + { + .layout = AV_CH_LAYOUT_STEREO, + .num_ele = { 1, 0, 0, 0 }, + .pairing = { { 1 }, }, + .index = { { 0 }, }, + .config_map = { 1, TYPE_CPE, }, + .reorder_map = { 0, 1 }, + }, + { + .layout = AV_CH_LAYOUT_2POINT1, + .num_ele = { 1, 0, 0, 1 }, + .pairing = { { 1 }, }, + .index = { { 0 },{ 0 },{ 0 },{ 0 } }, + .config_map = { 2, TYPE_CPE, TYPE_LFE }, + .reorder_map = { 0, 1, 2 }, + }, + { + .layout = AV_CH_LAYOUT_2_1, + .num_ele = { 1, 0, 1, 0 }, + .pairing = { { 1 },{ 0 },{ 0 } }, + .index = { { 0 },{ 0 },{ 0 }, }, + .config_map = { 2, TYPE_CPE, TYPE_SCE }, + .reorder_map = { 0, 1, 2 }, + }, + { + .layout = AV_CH_LAYOUT_SURROUND, + .num_ele = { 2, 0, 0, 0 }, + .pairing = { { 1, 0 }, }, + .index = { { 0, 0 }, }, + .config_map = { 2, TYPE_CPE, TYPE_SCE, }, + .reorder_map = { 0, 1, 2 }, + }, + { + .layout = AV_CH_LAYOUT_3POINT1, + .num_ele = { 2, 0, 0, 1 }, + .pairing = { { 1, 0 }, }, + .index = { { 0, 0 }, { 0 }, { 0 }, { 0 }, }, + .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_LFE }, + .reorder_map = { 0, 1, 2, 3 }, + }, + { + .layout = AV_CH_LAYOUT_4POINT0, + .num_ele = { 2, 0, 1, 0 }, + .pairing = { { 1, 0 }, { 0 }, { 0 }, }, + .index = { { 0, 0 }, { 0 }, { 1 } }, + .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_SCE }, + .reorder_map = { 0, 1, 2, 3 }, + }, + { + .layout = AV_CH_LAYOUT_4POINT1, + .num_ele = { 2, 1, 1, 0 }, + .pairing = { { 1, 0 }, { 0 }, { 0 }, }, + .index = { { 0, 0 }, { 1 }, { 2 }, { 0 } }, + .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_SCE }, + .reorder_map = { 0, 1, 2, 3, 4 }, + }, + { + .layout = AV_CH_LAYOUT_2_2, + .num_ele = { 1, 1, 0, 0 }, + .pairing = { { 1 }, { 1 }, }, + .index = { { 0 }, { 1 }, }, + .config_map = { 2, TYPE_CPE, TYPE_CPE }, + .reorder_map = { 0, 1, 2, 3 }, + }, + { + .layout = AV_CH_LAYOUT_QUAD, + .num_ele = { 1, 0, 1, 0 }, + .pairing = { { 1 }, { 0 }, { 1 }, }, + .index = { { 0 }, { 0 }, { 1 } }, + .config_map = { 2, TYPE_CPE, TYPE_CPE }, + .reorder_map = { 0, 1, 2, 3 }, + }, + { + .layout = AV_CH_LAYOUT_5POINT0, + .num_ele = { 2, 1, 0, 0 }, + .pairing = { { 1, 0 }, { 1 }, }, + .index = { { 0, 0 }, { 1 } }, + .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE }, + .reorder_map = { 0, 1, 2, 3, 4 }, + }, + { + .layout = AV_CH_LAYOUT_5POINT1, + .num_ele = { 2, 1, 1, 0 }, + .pairing = { { 1, 0 }, { 0 }, { 1 }, }, + .index = { { 0, 0 }, { 1 }, { 1 } }, + .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE }, + .reorder_map = { 0, 1, 2, 3, 4, 5 }, + }, + { + .layout = AV_CH_LAYOUT_5POINT0_BACK, + .num_ele = { 2, 0, 1, 0 }, + .pairing = { { 1, 0 }, { 0 }, { 1 } }, + .index = { { 0, 0 }, { 0 }, { 1 } }, + .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE }, + .reorder_map = { 0, 1, 2, 3, 4 }, + }, + { + .layout = AV_CH_LAYOUT_5POINT1_BACK, + .num_ele = { 2, 1, 1, 0 }, + .pairing = { { 1, 0 }, { 0 }, { 1 }, }, + .index = { { 0, 0 }, { 1 }, { 1 } }, + .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE }, + .reorder_map = { 0, 1, 2, 3, 4, 5 }, + }, + { + .layout = AV_CH_LAYOUT_6POINT0, + .num_ele = { 2, 1, 1, 0 }, + .pairing = { { 1, 0 }, { 1 }, { 0 }, }, + .index = { { 0, 0 }, { 1 }, { 1 } }, + .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE }, + .reorder_map = { 0, 1, 2, 3, 4, 5 }, + }, + { + .layout = AV_CH_LAYOUT_6POINT0_FRONT, + .num_ele = { 2, 1, 0, 0 }, + .pairing = { { 1, 1 }, { 1 } }, + .index = { { 1, 0 }, { 2 }, }, + .config_map = { 3, TYPE_CPE, TYPE_CPE, TYPE_CPE, }, + .reorder_map = { 0, 1, 2, 3, 4, 5 }, + }, + { + .layout = AV_CH_LAYOUT_HEXAGONAL, + .num_ele = { 2, 0, 2, 0 }, + .pairing = { { 1, 0 },{ 0 },{ 1, 0 }, }, + .index = { { 0, 0 },{ 0 },{ 1, 1 } }, + .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, }, + .reorder_map = { 0, 1, 2, 3, 4, 5 }, + }, + { + .layout = AV_CH_LAYOUT_6POINT1, + .num_ele = { 2, 1, 2, 0 }, + .pairing = { { 1, 0 },{ 0 },{ 1, 0 }, }, + .index = { { 0, 0 },{ 1 },{ 1, 2 } }, + .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE }, + .reorder_map = { 0, 1, 2, 3, 4, 5, 6 }, + }, + { + .layout = AV_CH_LAYOUT_6POINT1_BACK, + .num_ele = { 2, 1, 2, 0 }, + .pairing = { { 1, 0 }, { 0 }, { 1, 0 }, }, + .index = { { 0, 0 }, { 1 }, { 1, 2 } }, + .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE }, + .reorder_map = { 0, 1, 2, 3, 4, 5, 6 }, + }, + { + .layout = AV_CH_LAYOUT_6POINT1_FRONT, + .num_ele = { 2, 1, 2, 0 }, + .pairing = { { 1, 0 }, { 0 }, { 1, 0 }, }, + .index = { { 0, 0 }, { 1 }, { 1, 2 } }, + .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE }, + .reorder_map = { 0, 1, 2, 3, 4, 5, 6 }, + }, + { + .layout = AV_CH_LAYOUT_7POINT0, + .num_ele = { 2, 1, 1, 0 }, + .pairing = { { 1, 0 }, { 1 }, { 1 }, }, + .index = { { 0, 0 }, { 1 }, { 2 }, }, + .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE }, + .reorder_map = { 0, 1, 2, 3, 4, 5, 6 }, + }, + { + .layout = AV_CH_LAYOUT_7POINT0_FRONT, + .num_ele = { 2, 1, 1, 0 }, + .pairing = { { 1, 0 }, { 1 }, { 1 }, }, + .index = { { 0, 0 }, { 1 }, { 2 }, }, + .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE }, + .reorder_map = { 0, 1, 2, 3, 4, 5, 6 }, + }, + { + .layout = AV_CH_LAYOUT_7POINT1, + .num_ele = { 2, 1, 2, 0 }, + .pairing = { { 1, 0 }, { 0 }, { 1, 1 }, }, + .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } }, + .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE }, + .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 }, + }, + { + .layout = AV_CH_LAYOUT_7POINT1_WIDE, + .num_ele = { 2, 1, 2, 0 }, + .pairing = { { 1, 0 }, { 0 },{ 1, 1 }, }, + .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } }, + .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE }, + .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 }, + }, + { + .layout = AV_CH_LAYOUT_7POINT1_WIDE_BACK, + .num_ele = { 2, 1, 2, 0 }, + .pairing = { { 1, 0 }, { 0 }, { 1, 1 }, }, + .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } }, + .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE }, + .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 }, + }, + { + .layout = AV_CH_LAYOUT_OCTAGONAL, + .num_ele = { 2, 1, 2, 0 }, + .pairing = { { 1, 0 }, { 1 }, { 1, 0 }, }, + .index = { { 0, 0 }, { 1 }, { 2, 1 } }, + .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE }, + .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 }, + }, + { /* Meant for order 2/mixed ambisonics */ + .layout = AV_CH_LAYOUT_OCTAGONAL | AV_CH_TOP_CENTER, + .num_ele = { 2, 2, 2, 0 }, + .pairing = { { 1, 0 }, { 1, 0 }, { 1, 0 }, }, + .index = { { 0, 0 }, { 1, 1 }, { 2, 2 } }, + .config_map = { 6, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE }, + .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, + }, + { /* Meant for order 2/mixed ambisonics */ + .layout = AV_CH_LAYOUT_6POINT0_FRONT | AV_CH_BACK_CENTER | + AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT | AV_CH_TOP_CENTER, + .num_ele = { 2, 2, 2, 0 }, + .pairing = { { 1, 1 }, { 1, 0 }, { 1, 0 }, }, + .index = { { 0, 1 }, { 2, 0 }, { 3, 1 } }, + .config_map = { 6, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE }, + .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + }, + { + .layout = AV_CH_LAYOUT_HEXADECAGONAL, + .num_ele = { 4, 2, 4, 0 }, + .pairing = { { 1, 0, 1, 0 }, { 1, 1 }, { 1, 0, 1, 0 }, }, + .index = { { 0, 0, 1, 1 }, { 2, 3 }, { 4, 2, 5, 3 } }, + .config_map = { 10, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE }, + .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + }, +}; + /** * AAC encoder context */ @@ -99,12 +380,15 @@ typedef struct AACEncContext { FFTContext mdct1024; ///< long (1024 samples) frame transform context FFTContext mdct128; ///< short (128 samples) frame transform context AVFloatDSPContext *fdsp; - float *planar_samples[8]; ///< saved preprocessed input + AACPCEInfo pce; ///< PCE data, if needed + float *planar_samples[16]; ///< saved preprocessed input int profile; ///< copied from avctx + int needs_pce; ///< flag for non-standard layout LPCContext lpc; ///< used by TNS int samplerate_index; ///< MPEG-4 samplerate index int channels; ///< channel count + const uint8_t *reorder_map; ///< lavc to aac reorder map const uint8_t *chan_map; ///< channel configuration map ChannelElement *cpe; ///< channel elements diff --git a/libavcodec/aacenctab.h b/libavcodec/aacenctab.h index 5fc9411232742..c852a29f5348a 100644 --- a/libavcodec/aacenctab.h +++ b/libavcodec/aacenctab.h @@ -36,13 +36,24 @@ /** Total number of codebooks, including special ones **/ #define CB_TOT_ALL 15 -#define AAC_MAX_CHANNELS 8 +#define AAC_MAX_CHANNELS 16 extern const uint8_t *ff_aac_swb_size_1024[]; extern const int ff_aac_swb_size_1024_len; extern const uint8_t *ff_aac_swb_size_128[]; extern const int ff_aac_swb_size_128_len; +/* Supported layouts without using a PCE */ +static const int64_t aac_normal_chan_layouts[7] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_5POINT1, + AV_CH_LAYOUT_7POINT1, +}; + /** default channel configurations */ static const uint8_t aac_chan_configs[AAC_MAX_CHANNELS][6] = { {1, TYPE_SCE}, // 1 channel - single channel element From 7b7775a604fb406e3c16c29796dda7366e1c4ca8 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Thu, 9 Nov 2017 04:30:07 +0000 Subject: [PATCH 0802/2557] aacenc: use the PCE comment field for encoder ID Also handle extradata of variable size (for bitexact/if PCEs aren't used). Signed-off-by: Rostislav Pehlivanov --- libavcodec/aacenc.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index 51e467f7549ed..fa7932d42d71c 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -55,6 +55,8 @@ static void put_pce(PutBitContext *pb, AVCodecContext *avctx) int i, j; AACEncContext *s = avctx->priv_data; AACPCEInfo *pce = &s->pce; + const int bitexact = avctx->flags & AV_CODEC_FLAG_BITEXACT; + const char *aux_data = bitexact ? "Lavc" : LIBAVCODEC_IDENT; put_bits(pb, 4, 0); @@ -81,20 +83,26 @@ static void put_pce(PutBitContext *pb, AVCodecContext *avctx) } avpriv_align_put_bits(pb); - put_bits(pb, 8, 0); + put_bits(pb, 8, strlen(aux_data)); + avpriv_put_string(pb, aux_data, 0); } /** * Make AAC audio config object. * @see 1.6.2.1 "Syntax - AudioSpecificConfig" */ -static void put_audio_specific_config(AVCodecContext *avctx) +static int put_audio_specific_config(AVCodecContext *avctx) { PutBitContext pb; AACEncContext *s = avctx->priv_data; int channels = (!s->needs_pce)*(s->channels - (s->channels == 8 ? 1 : 0)); + const int max_size = 32; - init_put_bits(&pb, avctx->extradata, avctx->extradata_size); + avctx->extradata = av_mallocz(max_size); + if (!avctx->extradata) + return AVERROR(ENOMEM); + + init_put_bits(&pb, avctx->extradata, max_size); put_bits(&pb, 5, s->profile+1); //profile put_bits(&pb, 4, s->samplerate_index); //sample rate index put_bits(&pb, 4, channels); @@ -110,6 +118,9 @@ static void put_audio_specific_config(AVCodecContext *avctx) put_bits(&pb, 5, AOT_SBR); put_bits(&pb, 1, 0); flush_put_bits(&pb); + avctx->extradata_size = put_bits_count(&pb) >> 3; + + return 0; } void ff_quantize_band_cost_cache_init(struct AACEncContext *s) @@ -931,7 +942,6 @@ static av_cold int alloc_buffers(AVCodecContext *avctx, AACEncContext *s) int ch; FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->buffer.samples, s->channels, 3 * 1024 * sizeof(s->buffer.samples[0]), alloc_fail); FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->cpe, s->chan_map[0], sizeof(ChannelElement), alloc_fail); - FF_ALLOCZ_OR_GOTO(avctx, avctx->extradata, 5 + AV_INPUT_BUFFER_PADDING_SIZE, alloc_fail); for(ch = 0; ch < s->channels; ch++) s->planar_samples[ch] = s->buffer.samples + 3 * 1024 * ch; @@ -956,7 +966,6 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) /* Constants */ s->last_frame_pb_count = 0; - avctx->extradata_size = 20; avctx->frame_size = 1024; avctx->initial_padding = 1024; s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120; @@ -1071,7 +1080,8 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) if ((ret = alloc_buffers(avctx, s)) < 0) goto fail; - put_audio_specific_config(avctx); + if ((ret = put_audio_specific_config(avctx))) + goto fail; sizes[0] = ff_aac_swb_size_1024[s->samplerate_index]; sizes[1] = ff_aac_swb_size_128[s->samplerate_index]; From fbf77b5ac37bf2a807d8336450801d7aecf2e359 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 6 Nov 2017 17:44:33 +0100 Subject: [PATCH 0803/2557] build: Add uninstall-pkgconfig target to match install-lib*-pkgconfig --- Makefile | 2 +- avbuild/library.mak | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b1a2c301b56c3..1c10f154622e6 100644 --- a/Makefile +++ b/Makefile @@ -161,7 +161,7 @@ install-data: $(DATA_FILES) $(Q)mkdir -p "$(DATADIR)" $(INSTALL) -m 644 $(DATA_FILES) "$(DATADIR)" -uninstall: uninstall-libs uninstall-headers uninstall-data +uninstall: uninstall-data uninstall-headers uninstall-libs uninstall-pkgconfig uninstall-data: $(RM) -r "$(DATADIR)" diff --git a/avbuild/library.mak b/avbuild/library.mak index 4e4b3f196d460..a4b57e8824a72 100644 --- a/avbuild/library.mak +++ b/avbuild/library.mak @@ -92,8 +92,10 @@ uninstall-libs:: uninstall-headers:: $(RM) $(addprefix "$(INCINSTDIR)/",$(HEADERS) $(BUILT_HEADERS)) - $(RM) "$(LIBDIR)/pkgconfig/lib$(NAME).pc" -rmdir "$(INCINSTDIR)" + +uninstall-pkgconfig:: + $(RM) "$(LIBDIR)/pkgconfig/lib$(NAME).pc" endef $(eval $(RULES)) From fc9dcfe7d50d7f1b38fb287b4d92b5f3fc4bfb05 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Thu, 9 Nov 2017 12:51:54 +0000 Subject: [PATCH 0804/2557] aacenc: mark the preset 5.0/5.1 layouts correctly with back speakers The spec is correct, it does list these layouts as having rear speakers. Questionable how many decoders correctly interpret those correctly since side is way more popular. Also fixes fate-aac-yoraw-encode. Reported-by: pkviet Signed-off-by: Rostislav Pehlivanov --- libavcodec/aacenctab.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/aacenctab.h b/libavcodec/aacenctab.h index c852a29f5348a..64932d709f848 100644 --- a/libavcodec/aacenctab.h +++ b/libavcodec/aacenctab.h @@ -49,8 +49,8 @@ static const int64_t aac_normal_chan_layouts[7] = { AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_SURROUND, AV_CH_LAYOUT_4POINT0, - AV_CH_LAYOUT_5POINT0, - AV_CH_LAYOUT_5POINT1, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_5POINT1_BACK, AV_CH_LAYOUT_7POINT1, }; From dfa859b85a524a116ef1b0275e8d104675a56055 Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Thu, 9 Nov 2017 09:21:05 +0100 Subject: [PATCH 0805/2557] lavc/pngdec: fix av_bprint_finalize() usage. --- libavcodec/pngdec.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 20707f0ae5862..1d72f9542a730 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -524,9 +524,9 @@ static int decode_text_chunk(PNGDecContext *s, uint32_t length, int compressed, if ((ret = decode_zbuf(&bp, data, data_end)) < 0) return ret; text_len = bp.len; - av_bprint_finalize(&bp, (char **)&text); - if (!text) - return AVERROR(ENOMEM); + ret = av_bprint_finalize(&bp, (char **)&text); + if (ret < 0) + return ret; } else { text = (uint8_t *)data; text_len = data_end - text; @@ -862,9 +862,9 @@ static int decode_iccp_chunk(PNGDecContext *s, int length, AVFrame *f) if ((ret = decode_zbuf(&bp, s->gb.buffer, s->gb.buffer + length)) < 0) return ret; - av_bprint_finalize(&bp, (char **)&data); - if (!data) - return AVERROR(ENOMEM); + ret = av_bprint_finalize(&bp, (char **)&data); + if (ret < 0) + return ret; sd = av_frame_new_side_data(f, AV_FRAME_DATA_ICC_PROFILE, bp.len); if (!sd) { @@ -1317,9 +1317,9 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, av_bprint_init(&bp, 0, -1); av_bprintf(&bp, "%i/%i", num, 100000); - av_bprint_finalize(&bp, &gamma_str); - if (!gamma_str) - return AVERROR(ENOMEM); + ret = av_bprint_finalize(&bp, &gamma_str); + if (ret < 0) + return ret; av_dict_set(&p->metadata, "gamma", gamma_str, AV_DICT_DONT_STRDUP_VAL); From 7ebe7e8e7a76c0ce302f4f583ef0d14220031214 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 6 Nov 2017 17:49:55 +0100 Subject: [PATCH 0806/2557] build: Remove pkg-config files on clean instead of on distclean The files are no longer generated by configure, so they should not be removed by the distclean target any longer. --- Makefile | 1 - avbuild/common.mak | 3 +-- avbuild/library.mak | 4 ---- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 1c10f154622e6..5f91294c8ec5a 100644 --- a/Makefile +++ b/Makefile @@ -172,7 +172,6 @@ clean:: $(RM) -rf coverage.info lcov distclean:: - $(RM) $(DISTCLEANSUFFIXES) $(RM) .version avversion.h config.asm config.h mapfile \ avbuild/.config avbuild/config.* libavutil/avconfig.h \ libavcodec/bsf_list.c libavformat/protocol_list.c diff --git a/avbuild/common.mak b/avbuild/common.mak index a627dc0ccf93c..17989533f9b32 100644 --- a/avbuild/common.mak +++ b/avbuild/common.mak @@ -49,8 +49,7 @@ $(TOOLOBJS): | tools OBJDIRS := $(OBJDIRS) $(dir $(OBJS) $(HOBJS) $(HOSTOBJS) $(TESTOBJS)) -CLEANSUFFIXES = *.d *.o *~ *.h.c *.gcda *.gcno *.map *.ver *.version -DISTCLEANSUFFIXES = *.pc +CLEANSUFFIXES = *.d *.gcda *.gcno *.h.c *.map *.o *.pc *.ver *.version *~ LIBSUFFIXES = *.a *.lib *.so *.so.* *.dylib *.dll *.def *.dll.a define RULES diff --git a/avbuild/library.mak b/avbuild/library.mak index a4b57e8824a72..98a100dc7eeb8 100644 --- a/avbuild/library.mak +++ b/avbuild/library.mak @@ -57,10 +57,6 @@ clean:: $(RM) $(addprefix $(SUBDIR),$(CLEANFILES) $(CLEANSUFFIXES) $(LIBSUFFIXES)) \ $(CLEANSUFFIXES:%=$(SUBDIR)$(ARCH)/%) $(CLEANSUFFIXES:%=$(SUBDIR)tests/%) -distclean:: clean - $(RM) $(DISTCLEANSUFFIXES:%=$(SUBDIR)%) $(DISTCLEANSUFFIXES:%=$(SUBDIR)$(ARCH)/%) \ - $(DISTCLEANSUFFIXES:%=$(SUBDIR)tests/%) - install-lib$(NAME)-shared: $(SUBDIR)$(SLIBNAME) $(Q)mkdir -p "$(SHLIBDIR)" $$(INSTALL) -m 755 $$< "$(SHLIBDIR)/$(SLIB_INSTALL_NAME)" From 17b6c7efb471e8ff1b8a7271f6531ba1d52bf69c Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 6 Nov 2017 17:57:25 +0100 Subject: [PATCH 0807/2557] build: Add missing config.sh dependency for pkg-config files Also only update config.sh when it changed to avoid spurious rebuilds. --- avbuild/library.mak | 2 +- configure | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/avbuild/library.mak b/avbuild/library.mak index 98a100dc7eeb8..81778b7ad1e94 100644 --- a/avbuild/library.mak +++ b/avbuild/library.mak @@ -39,7 +39,7 @@ $(TESTPROGS) $(TOOLS): %$(EXESUF): %.o $(SUBDIR)lib$(NAME).version: $(SUBDIR)version.h | $(SUBDIR) $$(M) $$(SRC_PATH)/avbuild/libversion.sh $(NAME) $$< > $$@ -$(SUBDIR)lib$(NAME).pc: $(SUBDIR)version.h | $(SUBDIR) +$(SUBDIR)lib$(NAME).pc: $(SUBDIR)version.h avbuild/config.sh | $(SUBDIR) $$(M) $$(SRC_PATH)/avbuild/pkgconfig_generate.sh $(NAME) "$(DESC)" $(SUBDIR)lib$(NAME).ver: $(SUBDIR)lib$(NAME).v $(OBJS) diff --git a/configure b/configure index d43bd6ee86e6b..1f220c8befe44 100755 --- a/configure +++ b/configure @@ -5385,7 +5385,7 @@ print_enabled_components libavformat/protocol_list.c URLProtocol url_protocols $ # Settings for pkg-config files -cat > avbuild/config.sh < $TMPH <> avbuild/config.sh done + +cp_if_changed $TMPH avbuild/config.sh From bf7ae32a081432fed786a126a6b385495aae7945 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 9 Nov 2017 00:18:32 -0300 Subject: [PATCH 0808/2557] avdevice/decklink_dec: make some function static Reviewed-by: Aaron Levinson Signed-off-by: James Almer --- libavdevice/decklink_dec.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 191547ff10439..e90b42811a904 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -262,8 +262,8 @@ static uint8_t* teletext_data_unit_from_ancillary_packet(uint16_t *py, uint16_t return tgt; } -uint8_t *vanc_to_cc(AVFormatContext *avctx, uint16_t *buf, size_t words, - unsigned &cc_count) +static uint8_t *vanc_to_cc(AVFormatContext *avctx, uint16_t *buf, size_t words, + unsigned &cc_count) { size_t i, len = (buf[5] & 0xff) + 6 + 1; uint8_t cdp_sum, rate; @@ -352,8 +352,8 @@ uint8_t *vanc_to_cc(AVFormatContext *avctx, uint16_t *buf, size_t words, return cc; } -uint8_t *get_metadata(AVFormatContext *avctx, uint16_t *buf, size_t width, - uint8_t *tgt, size_t tgt_size, AVPacket *pkt) +static uint8_t *get_metadata(AVFormatContext *avctx, uint16_t *buf, size_t width, + uint8_t *tgt, size_t tgt_size, AVPacket *pkt) { decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data; uint16_t *max_buf = buf + width; From 28f5753fed4b462c868ce5a952fb770246620fa0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 9 Nov 2017 14:27:33 -0300 Subject: [PATCH 0809/2557] configure: fix the non pkg-config libmfx check on Windows Based on a patch by Aaron Levinson. Reviewed-by: alevinsn Signed-off-by: James Almer --- configure | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure b/configure index f396abda5bbb5..f087ba61b17d7 100755 --- a/configure +++ b/configure @@ -5824,6 +5824,7 @@ check_header asm/types.h # so we also check that atomics actually work here check_builtin stdatomic_h stdatomic.h "atomic_int foo, bar = ATOMIC_VAR_INIT(-1); atomic_store(&foo, 0)" +check_lib advapi32 "windows.h" RegCloseKey -ladvapi32 check_lib ole32 "windows.h" CoTaskMemFree -lole32 check_lib shell32 "windows.h shellapi.h" CommandLineToArgvW -lshell32 check_lib wincrypt "windows.h wincrypt.h" CryptGenRandom -ladvapi32 @@ -5981,7 +5982,7 @@ enabled libkvazaar && require_pkg_config libkvazaar "kvazaar >= 0.8.1" kv # pkg-config support. Instead, users should make sure that the build # can find the libraries and headers through other means. enabled libmfx && { use_pkg_config libmfx libmfx "mfx/mfxvideo.h" MFXInit || - { require libmfx "mfx/mfxvideo.h" MFXInit -llibmfx && warn "using libmfx without pkg-config"; } } + { require libmfx "mfx/mfxvideo.h" MFXInit "-llibmfx $advapi32_extralibs" && warn "using libmfx without pkg-config"; } } enabled libmodplug && require_pkg_config libmodplug libmodplug libmodplug/modplug.h ModPlug_Load enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame enabled libmysofa && require libmysofa "mysofa.h" mysofa_load -lmysofa $zlib_extralibs From 51090133b31bc719ea868db15d3ee38e9dbe90f1 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 2 Nov 2017 18:34:09 +0100 Subject: [PATCH 0810/2557] avcodec/cngdec: Fix integer clipping Fixes: runtime error: value -36211.7 is outside the range of representable values of type 'short' Fixes: 2992/clusterfuzz-testcase-6649611793989632 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/cngdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cngdec.c b/libavcodec/cngdec.c index 1e884f3c33955..28432ac7194b6 100644 --- a/libavcodec/cngdec.c +++ b/libavcodec/cngdec.c @@ -153,7 +153,7 @@ static int cng_decode_frame(AVCodecContext *avctx, void *data, return ret; buf_out = (int16_t *)frame->data[0]; for (i = 0; i < avctx->frame_size; i++) - buf_out[i] = p->filter_out[i + p->order]; + buf_out[i] = av_clip_int16(p->filter_out[i + p->order]); memcpy(p->filter_out, p->filter_out + avctx->frame_size, p->order * sizeof(*p->filter_out)); From e7fe5e511aaeb3b8d949706b7f8620042cdfbd6c Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Fri, 10 Nov 2017 06:59:25 +0800 Subject: [PATCH 0811/2557] lavf/dashdec: Fix several memleaks. Signed-off-by: Carl Eugen Hoyos Tested-by: Steven Liu --- libavformat/dashdec.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index f63f1fffbd33f..bc20fb74860fd 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -328,17 +328,17 @@ static void free_representation(struct representation *pls) } av_freep(&pls->url_template); - av_freep(pls); + av_freep(&pls); } -static void set_httpheader_options(DASHContext *c, AVDictionary *opts) +static void set_httpheader_options(DASHContext *c, AVDictionary **opts) { // broker prior HTTP options that should be consistent across requests - av_dict_set(&opts, "user-agent", c->user_agent, 0); - av_dict_set(&opts, "cookies", c->cookies, 0); - av_dict_set(&opts, "headers", c->headers, 0); + av_dict_set(opts, "user-agent", c->user_agent, 0); + av_dict_set(opts, "cookies", c->cookies, 0); + av_dict_set(opts, "headers", c->headers, 0); if (c->is_live) { - av_dict_set(&opts, "seekable", "0", 0); + av_dict_set(opts, "seekable", "0", 0); } } static void update_options(char **dest, const char *name, void *src) @@ -885,7 +885,7 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) if (!in) { close_in = 1; - set_httpheader_options(c, opts); + set_httpheader_options(c, &opts); ret = avio_open2(&in, url, AVIO_FLAG_READ, c->interrupt_callback, &opts); av_dict_free(&opts); if (ret < 0) @@ -1302,7 +1302,7 @@ static int open_input(DASHContext *c, struct representation *pls, struct fragmen char url[MAX_URL_SIZE]; int ret; - set_httpheader_options(c, opts); + set_httpheader_options(c, &opts); if (seg->size >= 0) { /* try to restrict the HTTP request to the part we want * (if this is in fact a HTTP request) */ @@ -1466,8 +1466,12 @@ static int save_avio_options(AVFormatContext *s) if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) { if (buf[0] != '\0') { ret = av_dict_set(&c->avio_opts, *opt, buf, AV_DICT_DONT_STRDUP_VAL); - if (ret < 0) + if (ret < 0) { + av_freep(&buf); return ret; + } + } else { + av_freep(&buf); } } opt++; From 1b323c3f9c8997c4df8e843cb065f10d097ae18c Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 10 Nov 2017 07:01:45 +0800 Subject: [PATCH 0812/2557] avformat/dashdec: use the current DASHContext for the rep_dest fix ticket id: #6820 Signed-off-by: Steven Liu Tested-by: mrskman --- libavformat/dashdec.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index bc20fb74860fd..0e3afd2a3b913 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -1079,9 +1079,8 @@ static int64_t calc_min_seg_no(AVFormatContext *s, struct representation *pls) return num; } -static int64_t calc_max_seg_no(struct representation *pls) +static int64_t calc_max_seg_no(struct representation *pls, DASHContext *c) { - DASHContext *c = pls->parent->priv_data; int64_t num = 0; if (pls->n_fragments) { @@ -1101,21 +1100,21 @@ static int64_t calc_max_seg_no(struct representation *pls) return num; } -static void move_timelines(struct representation *rep_src, struct representation *rep_dest) +static void move_timelines(struct representation *rep_src, struct representation *rep_dest, DASHContext *c) { if (rep_dest && rep_src ) { free_timelines_list(rep_dest); rep_dest->timelines = rep_src->timelines; rep_dest->n_timelines = rep_src->n_timelines; rep_dest->first_seq_no = rep_src->first_seq_no; - rep_dest->last_seq_no = calc_max_seg_no(rep_dest); + rep_dest->last_seq_no = calc_max_seg_no(rep_dest, c); rep_src->timelines = NULL; rep_src->n_timelines = 0; rep_dest->cur_seq_no = rep_src->cur_seq_no; } } -static void move_segments(struct representation *rep_src, struct representation *rep_dest) +static void move_segments(struct representation *rep_src, struct representation *rep_dest, DASHContext *c) { if (rep_dest && rep_src ) { free_fragment_list(rep_dest); @@ -1126,7 +1125,7 @@ static void move_segments(struct representation *rep_src, struct representation rep_dest->fragments = rep_src->fragments; rep_dest->n_fragments = rep_src->n_fragments; rep_dest->parent = rep_src->parent; - rep_dest->last_seq_no = calc_max_seg_no(rep_dest); + rep_dest->last_seq_no = calc_max_seg_no(rep_dest, c); rep_src->fragments = NULL; rep_src->n_fragments = 0; } @@ -1163,21 +1162,21 @@ static int refresh_manifest(AVFormatContext *s) if (cur_video && cur_video->timelines) { c->cur_video->cur_seq_no = calc_next_seg_no_from_timelines(c->cur_video, currentVideoTime * cur_video->fragment_timescale - 1); if (c->cur_video->cur_seq_no >= 0) { - move_timelines(c->cur_video, cur_video); + move_timelines(c->cur_video, cur_video, c); } } if (cur_audio && cur_audio->timelines) { c->cur_audio->cur_seq_no = calc_next_seg_no_from_timelines(c->cur_audio, currentAudioTime * cur_audio->fragment_timescale - 1); if (c->cur_audio->cur_seq_no >= 0) { - move_timelines(c->cur_audio, cur_audio); + move_timelines(c->cur_audio, cur_audio, c); } } } if (cur_video && cur_video->fragments) { - move_segments(c->cur_video, cur_video); + move_segments(c->cur_video, cur_video, c); } if (cur_audio && cur_audio->fragments) { - move_segments(c->cur_audio, cur_audio); + move_segments(c->cur_audio, cur_audio, c); } finish: @@ -1226,7 +1225,7 @@ static struct fragment *get_current_fragment(struct representation *pls) } if (c->is_live) { min_seq_no = calc_min_seg_no(pls->parent, pls); - max_seq_no = calc_max_seg_no(pls); + max_seq_no = calc_max_seg_no(pls, c); if (pls->timelines || pls->fragments) { refresh_manifest(pls->parent); @@ -1564,7 +1563,7 @@ static int open_demux_for_component(AVFormatContext *s, struct representation *p pls->parent = s; pls->cur_seq_no = calc_cur_seg_no(s, pls); - pls->last_seq_no = calc_max_seg_no(pls); + pls->last_seq_no = calc_max_seg_no(pls, s->priv_data); ret = reopen_demux_for_component(s, pls); if (ret < 0) { From 84556ef05963138cbc39fa1a39b790dffe15ffe8 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Sun, 5 Nov 2017 21:29:22 +0530 Subject: [PATCH 0813/2557] lavu/timecode: clarify error msg for timecode_rate The user-supplied value for timecode_rate in drawtext is rounded to nearest integer. So, a supplied value of 0.49 or lower is rounded to 0. This throws a misleading error message which says "Timecode frame rate must be specified". Changed message to account for values under one. Also noted supported framerates for drop TC. Signed-off-by: Michael Niedermayer --- doc/filters.texi | 4 +++- libavutil/timecode.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 2ba6e04166889..5c6729a484ea5 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -7365,7 +7365,9 @@ format. It can be used with or without text parameter. @var{timecode_rate} option must be specified. @item timecode_rate, rate, r -Set the timecode frame rate (timecode only). +Set the timecode frame rate (timecode only). Value will be rounded to nearest +integer. Minimum value is "1". +Drop-frame timecode is supported for frame rates 30 & 60. @item tc24hmax If set to 1, the output of the timecode option will wrap around at 24 hours. diff --git a/libavutil/timecode.c b/libavutil/timecode.c index c0c67c8478689..e9d8504ee7a68 100644 --- a/libavutil/timecode.c +++ b/libavutil/timecode.c @@ -155,7 +155,7 @@ static int check_fps(int fps) static int check_timecode(void *log_ctx, AVTimecode *tc) { if ((int)tc->fps <= 0) { - av_log(log_ctx, AV_LOG_ERROR, "Timecode frame rate must be specified\n"); + av_log(log_ctx, AV_LOG_ERROR, "Valid timecode frame rate must be specified. Minimum value is 1\n"); return AVERROR(EINVAL); } if ((tc->flags & AV_TIMECODE_FLAG_DROPFRAME) && tc->fps != 30 && tc->fps != 60) { From 2c6b0315d9cda3ff549c66eb8603afd8ba5e4574 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Wed, 8 Nov 2017 21:02:23 +0800 Subject: [PATCH 0814/2557] lavc/libkvazaar: switch to ff_alloc_packet2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ff_alloc_packet have been deprecated, switch to use the ff_alloc_packet2. Signed-off-by: Jun Zhao Reviewed-by: Arttu Ylä-Outinen Signed-off-by: Michael Niedermayer --- libavcodec/libkvazaar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libkvazaar.c b/libavcodec/libkvazaar.c index f35b0df61d5e3..25e7b32f5f043 100644 --- a/libavcodec/libkvazaar.c +++ b/libavcodec/libkvazaar.c @@ -231,7 +231,7 @@ static int libkvazaar_encode(AVCodecContext *avctx, kvz_data_chunk *chunk = NULL; uint64_t written = 0; - retval = ff_alloc_packet(avpkt, len_out); + retval = ff_alloc_packet2(avctx, avpkt, len_out, len_out); if (retval < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate output packet.\n"); goto done; From dd435c957aa48349f25c58bac88010d5af696227 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Wed, 8 Nov 2017 21:04:51 +0800 Subject: [PATCH 0815/2557] lavc/libx265: switch to ff_alloc_packet2 ff_alloc_packet have been deprecated, switch to use ff_alloc_packet2. Signed-off-by: Jun Zhao Reviewed-by: Derek Buitenhuis Signed-off-by: Michael Niedermayer --- libavcodec/libx265.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 784b51c52d40e..4456e300f2e4d 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -294,7 +294,7 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, for (i = 0; i < nnal; i++) payload += nal[i].sizeBytes; - ret = ff_alloc_packet(pkt, payload); + ret = ff_alloc_packet2(avctx, pkt, payload, payload); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); return ret; From 1fa3a9a31de11a2dee0efc75b89862e80ab3c90f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 8 Nov 2017 23:55:00 +0100 Subject: [PATCH 0816/2557] avutil/frame: Add private_ref to AVFrame This gives FFmpeg libs a field that they can freely and safely use. Avoiding the need of wrapping of a users opaque_ref field and its issues. Signed-off-by: Michael Niedermayer --- libavutil/frame.c | 8 +++++++- libavutil/frame.h | 13 +++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/libavutil/frame.c b/libavutil/frame.c index 982fbb5c813db..662a7e5ab5cc9 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -383,12 +383,17 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif av_buffer_unref(&dst->opaque_ref); + av_buffer_unref(&dst->private_ref); if (src->opaque_ref) { dst->opaque_ref = av_buffer_ref(src->opaque_ref); if (!dst->opaque_ref) return AVERROR(ENOMEM); } - + if (src->private_ref) { + dst->private_ref = av_buffer_ref(src->private_ref); + if (!dst->private_ref) + return AVERROR(ENOMEM); + } return 0; } @@ -524,6 +529,7 @@ void av_frame_unref(AVFrame *frame) av_buffer_unref(&frame->hw_frames_ctx); av_buffer_unref(&frame->opaque_ref); + av_buffer_unref(&frame->private_ref); get_frame_defaults(frame); } diff --git a/libavutil/frame.h b/libavutil/frame.h index 0c6aab1c029c8..d54bd9a35436d 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -563,6 +563,19 @@ typedef struct AVFrame { /** * @} */ + + /** + * AVBufferRef for internal use by a single libav* library. + * Must not be used to transfer data between libraries. + * Has to be NULL when ownership of the frame leaves the respective library. + * + * Code outside the FFmpeg libs should never check or change the contents of the buffer ref. + * + * FFmpeg calls av_buffer_unref() on it when the frame is unreferenced. + * av_frame_copy_props() calls create a new reference with av_buffer_ref() + * for the target frame's private_ref field. + */ + AVBufferRef *private_ref; } AVFrame; #if FF_API_FRAME_GET_SET From 9f1cfd88af88a7d7d5c56a368a46639dfdfdef75 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 13 Oct 2017 18:59:17 +0200 Subject: [PATCH 0817/2557] decode: add a method for attaching lavc-internal data to frames Use the AVFrame.private_ref field. This new struct will be useful in the following commits. Merges Libav commit 359a8a3e2d1194b52b6c386f94fd0929567dfb67. --- libavcodec/decode.c | 51 ++++++++++++++++++++++++++++++++++-- libavcodec/decode.h | 11 ++++++++ libavcodec/wrapped_avframe.c | 7 +++++ 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 86fe5aef52a9c..0f215d6915526 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -613,6 +613,16 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) if (ret == AVERROR_EOF) avci->draining_done = 1; + /* free the per-frame decode data */ + if (!ret) { + /* the only case where decode data is not set should be decoders + * that do not call ff_get_buffer() */ + av_assert0((frame->private_ref && frame->private_ref->size == sizeof(FrameDecodeData)) || + !(avctx->codec->capabilities & AV_CODEC_CAP_DR1)); + + av_buffer_unref(&frame->private_ref); + } + return ret; } @@ -1552,6 +1562,37 @@ static void validate_avframe_allocation(AVCodecContext *avctx, AVFrame *frame) } } +static void decode_data_free(void *opaque, uint8_t *data) +{ + FrameDecodeData *fdd = (FrameDecodeData*)data; + + av_freep(&fdd); +} + +int ff_attach_decode_data(AVFrame *frame) +{ + AVBufferRef *fdd_buf; + FrameDecodeData *fdd; + + av_assert1(!frame->private_ref); + av_buffer_unref(&frame->private_ref); + + fdd = av_mallocz(sizeof(*fdd)); + if (!fdd) + return AVERROR(ENOMEM); + + fdd_buf = av_buffer_create((uint8_t*)fdd, sizeof(*fdd), decode_data_free, + NULL, AV_BUFFER_FLAG_READONLY); + if (!fdd_buf) { + av_freep(&fdd); + return AVERROR(ENOMEM); + } + + frame->private_ref = fdd_buf; + + return 0; +} + static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) { const AVHWAccel *hwaccel = avctx->hwaccel; @@ -1588,8 +1629,14 @@ static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) avctx->sw_pix_fmt = avctx->pix_fmt; ret = avctx->get_buffer2(avctx, frame, flags); - if (ret >= 0) - validate_avframe_allocation(avctx, frame); + if (ret < 0) + goto end; + + validate_avframe_allocation(avctx, frame); + + ret = ff_attach_decode_data(frame); + if (ret < 0) + goto end; end: if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions && diff --git a/libavcodec/decode.h b/libavcodec/decode.h index c9630228dc5fe..519f875c985d3 100644 --- a/libavcodec/decode.h +++ b/libavcodec/decode.h @@ -21,8 +21,17 @@ #ifndef AVCODEC_DECODE_H #define AVCODEC_DECODE_H +#include "libavutil/buffer.h" + #include "avcodec.h" +/** + * This struct stores per-frame lavc-internal data and is attached to it via + * private_ref. + */ +typedef struct FrameDecodeData { +} FrameDecodeData; + /** * Called by decoders to get the next packet for decoding. * @@ -36,4 +45,6 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt); void ff_decode_bsfs_uninit(AVCodecContext *avctx); +int ff_attach_decode_data(AVFrame *frame); + #endif /* AVCODEC_DECODE_H */ diff --git a/libavcodec/wrapped_avframe.c b/libavcodec/wrapped_avframe.c index 5f88a668b927d..85ff32d13aef0 100644 --- a/libavcodec/wrapped_avframe.c +++ b/libavcodec/wrapped_avframe.c @@ -25,6 +25,7 @@ */ #include "avcodec.h" +#include "decode.h" #include "internal.h" #include "libavutil/internal.h" @@ -98,6 +99,12 @@ static int wrapped_avframe_decode(AVCodecContext *avctx, void *data, av_frame_move_ref(out, in); + err = ff_attach_decode_data(out); + if (err < 0) { + av_frame_unref(out); + return err; + } + *got_frame = 1; return 0; } From 7fa64514c8d2ec4d3dcb5f194511609ddcc288e6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 10 Nov 2017 16:07:44 +0100 Subject: [PATCH 0818/2557] decode: add a mechanism for performing delayed processing on the decoded frames This will be useful in the CUVID hwaccel. Merges Libav commit badf0951f54c1332e77455dc40398f3512540c1b. --- libavcodec/decode.c | 15 +++++++++++++++ libavcodec/decode.h | 14 ++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 0f215d6915526..8b03f61a22b5a 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -620,6 +620,18 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) av_assert0((frame->private_ref && frame->private_ref->size == sizeof(FrameDecodeData)) || !(avctx->codec->capabilities & AV_CODEC_CAP_DR1)); + if (frame->private_ref) { + FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data; + + if (fdd->post_process) { + ret = fdd->post_process(avctx, frame); + if (ret < 0) { + av_frame_unref(frame); + return ret; + } + } + } + av_buffer_unref(&frame->private_ref); } @@ -1566,6 +1578,9 @@ static void decode_data_free(void *opaque, uint8_t *data) { FrameDecodeData *fdd = (FrameDecodeData*)data; + if (fdd->post_process_opaque_free) + fdd->post_process_opaque_free(fdd->post_process_opaque); + av_freep(&fdd); } diff --git a/libavcodec/decode.h b/libavcodec/decode.h index 519f875c985d3..51947b9ec08ca 100644 --- a/libavcodec/decode.h +++ b/libavcodec/decode.h @@ -22,6 +22,7 @@ #define AVCODEC_DECODE_H #include "libavutil/buffer.h" +#include "libavutil/frame.h" #include "avcodec.h" @@ -30,6 +31,19 @@ * private_ref. */ typedef struct FrameDecodeData { + /** + * The callback to perform some delayed processing on the frame right + * before it is returned to the caller. + * + * @note This code is called at some unspecified point after the frame is + * returned from the decoder's decode/receive_frame call. Therefore it cannot rely + * on AVCodecContext being in any specific state, so it does not get to + * access AVCodecContext directly at all. All the state it needs must be + * stored in the post_process_opaque object. + */ + int (*post_process)(void *logctx, AVFrame *frame); + void *post_process_opaque; + void (*post_process_opaque_free)(void *opaque); } FrameDecodeData; /** From 81c021c6a2d7848c31984d65f225ba54bdd6f560 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 13 Oct 2017 18:59:19 +0200 Subject: [PATCH 0819/2557] decode: add a per-frame private data for hwaccel use This will be useful in the CUVID hwaccel. It should also eventually replace current decoder-specific mechanisms used by various other hwaccels. Merges Libav commit 704311b2946d74a80f65906961cd9baaa18683a3. --- libavcodec/decode.c | 3 +++ libavcodec/decode.h | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 8b03f61a22b5a..44b874d4f817d 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1581,6 +1581,9 @@ static void decode_data_free(void *opaque, uint8_t *data) if (fdd->post_process_opaque_free) fdd->post_process_opaque_free(fdd->post_process_opaque); + if (fdd->hwaccel_priv_free) + fdd->hwaccel_priv_free(fdd->hwaccel_priv); + av_freep(&fdd); } diff --git a/libavcodec/decode.h b/libavcodec/decode.h index 51947b9ec08ca..03fc783bba308 100644 --- a/libavcodec/decode.h +++ b/libavcodec/decode.h @@ -44,6 +44,12 @@ typedef struct FrameDecodeData { int (*post_process)(void *logctx, AVFrame *frame); void *post_process_opaque; void (*post_process_opaque_free)(void *opaque); + + /** + * Per-frame private data for hwaccels. + */ + void *hwaccel_priv; + void (*hwaccel_priv_free)(void *priv); } FrameDecodeData; /** From a337b36b8bd68cacd0e8903c0b26420cb30fbee8 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Fri, 10 Nov 2017 22:09:23 +0100 Subject: [PATCH 0820/2557] aptx: implement the aptX bluetooth codec The encoder was reverse engineered from binary library and from EP0398973B1 patent (long expired). The decoder was simply deduced from the encoder. --- doc/general.texi | 2 + libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 1 + libavcodec/aptx.c | 860 ++++++++++++++++++++++++++++++++++++++++ libavcodec/avcodec.h | 1 + libavcodec/codec_desc.c | 7 + 6 files changed, 873 insertions(+) create mode 100644 libavcodec/aptx.c diff --git a/doc/general.texi b/doc/general.texi index e6ae277d232a1..de4efee913eaa 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -993,6 +993,8 @@ following image formats are supported: @item Amazing Studio PAF Audio @tab @tab X @item Apple lossless audio @tab X @tab X @tab QuickTime fourcc 'alac' +@item aptX @tab X @tab X + @tab Used in Bluetooth A2DP @item ATRAC1 @tab @tab X @item ATRAC3 @tab @tab X @item ATRAC3+ @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 45f4db5939262..95c843dee7591 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -188,6 +188,8 @@ OBJS-$(CONFIG_AMV_ENCODER) += mjpegenc.o mjpegenc_common.o \ OBJS-$(CONFIG_ANM_DECODER) += anm.o OBJS-$(CONFIG_ANSI_DECODER) += ansi.o cga_data.o OBJS-$(CONFIG_APE_DECODER) += apedec.o +OBJS-$(CONFIG_APTX_DECODER) += aptx.o +OBJS-$(CONFIG_APTX_ENCODER) += aptx.o OBJS-$(CONFIG_APNG_DECODER) += png.o pngdec.o pngdsp.o OBJS-$(CONFIG_APNG_ENCODER) += png.o pngenc.o OBJS-$(CONFIG_SSA_DECODER) += assdec.o ass.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index d96e499ba775d..463f7ed64e2cf 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -406,6 +406,7 @@ static void register_all(void) REGISTER_DECODER(AMRNB, amrnb); REGISTER_DECODER(AMRWB, amrwb); REGISTER_DECODER(APE, ape); + REGISTER_ENCDEC (APTX, aptx); REGISTER_DECODER(ATRAC1, atrac1); REGISTER_DECODER(ATRAC3, atrac3); REGISTER_DECODER(ATRAC3AL, atrac3al); diff --git a/libavcodec/aptx.c b/libavcodec/aptx.c new file mode 100644 index 0000000000000..d09ce8f83897c --- /dev/null +++ b/libavcodec/aptx.c @@ -0,0 +1,860 @@ +/* + * Audio Processing Technology codec for Bluetooth (aptX) + * + * Copyright (C) 2017 Aurelien Jacobs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" +#include "mathops.h" +#include "audio_frame_queue.h" + + +enum channels { + LEFT, + RIGHT, + NB_CHANNELS +}; + +enum subbands { + LF, // Low Frequency (0-5.5 kHz) + MLF, // Medium-Low Frequency (5.5-11kHz) + MHF, // Medium-High Frequency (11-16.5kHz) + HF, // High Frequency (16.5-22kHz) + NB_SUBBANDS +}; + +#define NB_FILTERS 2 +#define FILTER_TAPS 16 + +typedef struct { + int pos; + int32_t buffer[2*FILTER_TAPS]; +} FilterSignal; + +typedef struct { + FilterSignal outer_filter_signal[NB_FILTERS]; + FilterSignal inner_filter_signal[NB_FILTERS][NB_FILTERS]; +} QMFAnalysis; + +typedef struct { + int32_t quantized_sample; + int32_t quantized_sample_parity_change; + int32_t error; +} Quantize; + +typedef struct { + int32_t quantization_factor; + int32_t factor_select; + int32_t reconstructed_difference; +} InvertQuantize; + +typedef struct { + int32_t prev_sign[2]; + int32_t s_weight[2]; + int32_t d_weight[24]; + int32_t pos; + int32_t reconstructed_differences[48]; + int32_t previous_reconstructed_sample; + int32_t predicted_difference; + int32_t predicted_sample; +} Prediction; + +typedef struct { + int32_t codeword_history; + int32_t dither_parity; + int32_t dither[NB_SUBBANDS]; + + QMFAnalysis qmf; + Quantize quantize[NB_SUBBANDS]; + InvertQuantize invert_quantize[NB_SUBBANDS]; + Prediction prediction[NB_SUBBANDS]; +} Channel; + +typedef struct { + int32_t sync_idx; + Channel channels[NB_CHANNELS]; + AudioFrameQueue afq; +} AptXContext; + + +static const int32_t quantize_intervals_LF[65] = { + -9948, 9948, 29860, 49808, 69822, 89926, 110144, 130502, + 151026, 171738, 192666, 213832, 235264, 256982, 279014, 301384, + 324118, 347244, 370790, 394782, 419250, 444226, 469742, 495832, + 522536, 549890, 577936, 606720, 636290, 666700, 698006, 730270, + 763562, 797958, 833538, 870398, 908640, 948376, 989740, 1032874, + 1077948, 1125150, 1174700, 1226850, 1281900, 1340196, 1402156, 1468282, + 1539182, 1615610, 1698514, 1789098, 1888944, 2000168, 2125700, 2269750, + 2438670, 2642660, 2899462, 3243240, 3746078, 4535138, 5664098, 7102424, + 8897462, +}; +static const int32_t invert_quantize_dither_factors_LF[65] = { + 9948, 9948, 9962, 9988, 10026, 10078, 10142, 10218, + 10306, 10408, 10520, 10646, 10784, 10934, 11098, 11274, + 11462, 11664, 11880, 12112, 12358, 12618, 12898, 13194, + 13510, 13844, 14202, 14582, 14988, 15422, 15884, 16380, + 16912, 17484, 18098, 18762, 19480, 20258, 21106, 22030, + 23044, 24158, 25390, 26760, 28290, 30008, 31954, 34172, + 36728, 39700, 43202, 47382, 52462, 58762, 66770, 77280, + 91642, 112348, 144452, 199326, 303512, 485546, 643414, 794914, + 1000124, +}; +static const int32_t quantize_dither_factors_LF[65] = { + 0, 4, 7, 10, 13, 16, 19, 22, + 26, 28, 32, 35, 38, 41, 44, 47, + 51, 54, 58, 62, 65, 70, 74, 79, + 84, 90, 95, 102, 109, 116, 124, 133, + 143, 154, 166, 180, 195, 212, 231, 254, + 279, 308, 343, 383, 430, 487, 555, 639, + 743, 876, 1045, 1270, 1575, 2002, 2628, 3591, + 5177, 8026, 13719, 26047, 45509, 39467, 37875, 51303, + 0, +}; +static const int16_t quantize_factor_select_offset_LF[65] = { + 0, -21, -19, -17, -15, -12, -10, -8, + -6, -4, -1, 1, 3, 6, 8, 10, + 13, 15, 18, 20, 23, 26, 29, 31, + 34, 37, 40, 43, 47, 50, 53, 57, + 60, 64, 68, 72, 76, 80, 85, 89, + 94, 99, 105, 110, 116, 123, 129, 136, + 144, 152, 161, 171, 182, 194, 207, 223, + 241, 263, 291, 328, 382, 467, 522, 522, + 522, +}; + + +static const int32_t quantize_intervals_MLF[9] = { + -89806, 89806, 278502, 494338, 759442, 1113112, 1652322, 2720256, 5190186, +}; +static const int32_t invert_quantize_dither_factors_MLF[9] = { + 89806, 89806, 98890, 116946, 148158, 205512, 333698, 734236, 1735696, +}; +static const int32_t quantize_dither_factors_MLF[9] = { + 0, 2271, 4514, 7803, 14339, 32047, 100135, 250365, 0, +}; +static const int16_t quantize_factor_select_offset_MLF[9] = { + 0, -14, 6, 29, 58, 96, 154, 270, 521, +}; + + +static const int32_t quantize_intervals_MHF[3] = { + -194080, 194080, 890562, +}; +static const int32_t invert_quantize_dither_factors_MHF[3] = { + 194080, 194080, 502402, +}; +static const int32_t quantize_dither_factors_MHF[3] = { + 0, 77081, 0, +}; +static const int16_t quantize_factor_select_offset_MHF[3] = { + 0, -33, 136, +}; + + +static const int32_t quantize_intervals_HF[5] = { + -163006, 163006, 542708, 1120554, 2669238, +}; +static const int32_t invert_quantize_dither_factors_HF[5] = { + 163006, 163006, 216698, 361148, 1187538, +}; +static const int32_t quantize_dither_factors_HF[5] = { + 0, 13423, 36113, 206598, 0, +}; +static const int16_t quantize_factor_select_offset_HF[5] = { + 0, -8, 33, 95, 262, +}; + +typedef const struct { + const int32_t *quantize_intervals; + const int32_t *invert_quantize_dither_factors; + const int32_t *quantize_dither_factors; + const int16_t *quantize_factor_select_offset; + int tables_size; + int32_t quantized_bits; + int32_t prediction_order; +} ConstTables; + +static ConstTables tables[NB_SUBBANDS] = { + [LF] = { quantize_intervals_LF, + invert_quantize_dither_factors_LF, + quantize_dither_factors_LF, + quantize_factor_select_offset_LF, + FF_ARRAY_ELEMS(quantize_intervals_LF), + 7, 24 }, + [MLF] = { quantize_intervals_MLF, + invert_quantize_dither_factors_MLF, + quantize_dither_factors_MLF, + quantize_factor_select_offset_MLF, + FF_ARRAY_ELEMS(quantize_intervals_MLF), + 4, 12 }, + [MHF] = { quantize_intervals_MHF, + invert_quantize_dither_factors_MHF, + quantize_dither_factors_MHF, + quantize_factor_select_offset_MHF, + FF_ARRAY_ELEMS(quantize_intervals_MHF), + 2, 6 }, + [HF] = { quantize_intervals_HF, + invert_quantize_dither_factors_HF, + quantize_dither_factors_HF, + quantize_factor_select_offset_HF, + FF_ARRAY_ELEMS(quantize_intervals_HF), + 3, 12 }, +}; + +static const int16_t quantization_factors[32] = { + 2048, 2093, 2139, 2186, 2233, 2282, 2332, 2383, + 2435, 2489, 2543, 2599, 2656, 2714, 2774, 2834, + 2896, 2960, 3025, 3091, 3158, 3228, 3298, 3371, + 3444, 3520, 3597, 3676, 3756, 3838, 3922, 4008, +}; + + +/* Rounded right shift with optionnal clipping */ +#define RSHIFT_SIZE(size) \ +av_always_inline \ +static int##size##_t rshift##size(int##size##_t value, int shift) \ +{ \ + int##size##_t rounding = (int##size##_t)1 << (shift - 1); \ + int##size##_t mask = ((int##size##_t)1 << (shift + 1)) - 1; \ + return ((value + rounding) >> shift) - ((value & mask) == rounding); \ +} \ +av_always_inline \ +static int##size##_t rshift##size##_clip24(int##size##_t value, int shift) \ +{ \ + return av_clip_intp2(rshift##size(value, shift), 23); \ +} +RSHIFT_SIZE(32) +RSHIFT_SIZE(64) + + +av_always_inline +static void aptx_update_codeword_history(Channel *channel) +{ + int32_t cw = ((channel->quantize[0].quantized_sample & 3) << 0) + + ((channel->quantize[1].quantized_sample & 2) << 1) + + ((channel->quantize[2].quantized_sample & 1) << 3); + channel->codeword_history = (cw << 8) + (channel->codeword_history << 4); +} + +static void aptx_generate_dither(Channel *channel) +{ + int subband; + int64_t m; + int32_t d; + + aptx_update_codeword_history(channel); + + m = (int64_t)5184443 * (channel->codeword_history >> 7); + d = (m << 2) + (m >> 22); + for (subband = 0; subband < NB_SUBBANDS; subband++) + channel->dither[subband] = d << (23 - 5*subband); + channel->dither_parity = (d >> 25) & 1; +} + +/* + * Convolution filter coefficients for the outer QMF of the QMF tree. + * The 2 sets are a mirror of each other. + */ +static const int32_t aptx_qmf_outer_coeffs[NB_FILTERS][FILTER_TAPS] = { + { + 730, -413, -9611, 43626, -121026, 269973, -585547, 2801966, + 697128, -160481, 27611, 8478, -10043, 3511, 688, -897, + }, + { + -897, 688, 3511, -10043, 8478, 27611, -160481, 697128, + 2801966, -585547, 269973, -121026, 43626, -9611, -413, 730, + }, +}; + +/* + * Convolution filter coefficients for the inner QMF of the QMF tree. + * The 2 sets are a mirror of each other. + */ +static const int32_t aptx_qmf_inner_coeffs[NB_FILTERS][FILTER_TAPS] = { + { + 1033, -584, -13592, 61697, -171156, 381799, -828088, 3962579, + 985888, -226954, 39048, 11990, -14203, 4966, 973, -1268, + }, + { + -1268, 973, 4966, -14203, 11990, 39048, -226954, 985888, + 3962579, -828088, 381799, -171156, 61697, -13592, -584, 1033, + }, +}; + +/* + * Push one sample into a circular signal buffer. + */ +av_always_inline +static void aptx_qmf_filter_signal_push(FilterSignal *signal, int32_t sample) +{ + signal->buffer[signal->pos ] = sample; + signal->buffer[signal->pos+FILTER_TAPS] = sample; + signal->pos = (signal->pos + 1) & (FILTER_TAPS - 1); +} + +/* + * Compute the convolution of the signal with the coefficients, and reduce + * to 24 bits by applying the specified right shifting. + */ +av_always_inline +static int32_t aptx_qmf_convolution(FilterSignal *signal, + const int32_t coeffs[FILTER_TAPS], + int shift) +{ + int32_t *sig = &signal->buffer[signal->pos]; + int64_t e = 0; + int i; + + for (i = 0; i < FILTER_TAPS; i++) + e += MUL64(sig[i], coeffs[i]); + + return rshift64_clip24(e, shift); +} + +/* + * Half-band QMF analysis filter realized with a polyphase FIR filter. + * Split into 2 subbands and downsample by 2. + * So for each pair of samples that goes in, one sample goes out, + * split into 2 separate subbands. + */ +av_always_inline +static void aptx_qmf_polyphase_analysis(FilterSignal signal[NB_FILTERS], + const int32_t coeffs[NB_FILTERS][FILTER_TAPS], + int shift, + int32_t samples[NB_FILTERS], + int32_t *low_subband_output, + int32_t *high_subband_output) +{ + int32_t subbands[NB_FILTERS]; + int i; + + for (i = 0; i < NB_FILTERS; i++) { + aptx_qmf_filter_signal_push(&signal[i], samples[NB_FILTERS-1-i]); + subbands[i] = aptx_qmf_convolution(&signal[i], coeffs[i], shift); + } + + *low_subband_output = av_clip_intp2(subbands[0] + subbands[1], 23); + *high_subband_output = av_clip_intp2(subbands[0] - subbands[1], 23); +} + +/* + * Two stage QMF analysis tree. + * Split 4 input samples into 4 subbands and downsample by 4. + * So for each group of 4 samples that goes in, one sample goes out, + * split into 4 separate subbands. + */ +static void aptx_qmf_tree_analysis(QMFAnalysis *qmf, + int32_t samples[4], + int32_t subband_samples[4]) +{ + int32_t intermediate_samples[4]; + int i; + + /* Split 4 input samples into 2 intermediate subbands downsampled to 2 samples */ + for (i = 0; i < 2; i++) + aptx_qmf_polyphase_analysis(qmf->outer_filter_signal, + aptx_qmf_outer_coeffs, 23, + &samples[2*i], + &intermediate_samples[0+i], + &intermediate_samples[2+i]); + + /* Split 2 intermediate subband samples into 4 final subbands downsampled to 1 sample */ + for (i = 0; i < 2; i++) + aptx_qmf_polyphase_analysis(qmf->inner_filter_signal[i], + aptx_qmf_inner_coeffs, 23, + &intermediate_samples[2*i], + &subband_samples[2*i+0], + &subband_samples[2*i+1]); +} + +/* + * Half-band QMF synthesis filter realized with a polyphase FIR filter. + * Join 2 subbands and upsample by 2. + * So for each 2 subbands sample that goes in, a pair of samples goes out. + */ +av_always_inline +static void aptx_qmf_polyphase_synthesis(FilterSignal signal[NB_FILTERS], + const int32_t coeffs[NB_FILTERS][FILTER_TAPS], + int shift, + int32_t low_subband_input, + int32_t high_subband_input, + int32_t samples[NB_FILTERS]) +{ + int32_t subbands[NB_FILTERS]; + int i; + + subbands[0] = low_subband_input + high_subband_input; + subbands[1] = low_subband_input - high_subband_input; + + for (i = 0; i < NB_FILTERS; i++) { + aptx_qmf_filter_signal_push(&signal[i], subbands[1-i]); + samples[i] = aptx_qmf_convolution(&signal[i], coeffs[i], shift); + } +} + +/* + * Two stage QMF synthesis tree. + * Join 4 subbands and upsample by 4. + * So for each 4 subbands sample that goes in, a group of 4 samples goes out. + */ +static void aptx_qmf_tree_synthesis(QMFAnalysis *qmf, + int32_t subband_samples[4], + int32_t samples[4]) +{ + int32_t intermediate_samples[4]; + int i; + + /* Join 4 subbands into 2 intermediate subbands upsampled to 2 samples. */ + for (i = 0; i < 2; i++) + aptx_qmf_polyphase_synthesis(qmf->inner_filter_signal[i], + aptx_qmf_inner_coeffs, 22, + subband_samples[2*i+0], + subband_samples[2*i+1], + &intermediate_samples[2*i]); + + /* Join 2 samples from intermediate subbands upsampled to 4 samples. */ + for (i = 0; i < 2; i++) + aptx_qmf_polyphase_synthesis(qmf->outer_filter_signal, + aptx_qmf_outer_coeffs, 21, + intermediate_samples[0+i], + intermediate_samples[2+i], + &samples[2*i]); +} + + +av_always_inline +static int32_t aptx_bin_search(int32_t value, int32_t factor, + const int32_t *intervals, int32_t nb_intervals) +{ + int32_t idx = 0; + int i; + + for (i = nb_intervals >> 1; i > 0; i >>= 1) + if (MUL64(factor, intervals[idx + i]) <= ((int64_t)value << 24)) + idx += i; + + return idx; +} + +static void aptx_quantize_difference(Quantize *quantize, + int32_t sample_difference, + int32_t dither, + int32_t quantization_factor, + ConstTables *tables) +{ + const int32_t *intervals = tables->quantize_intervals; + int32_t quantized_sample, dithered_sample, parity_change; + int32_t d, mean, interval, inv; + int64_t error; + + quantized_sample = aptx_bin_search(FFABS(sample_difference) >> 4, + quantization_factor, + intervals, tables->tables_size); + + d = rshift32_clip24(MULH(dither, dither), 7) - (1 << 23); + d = rshift64(MUL64(d, tables->quantize_dither_factors[quantized_sample]), 23); + + intervals += quantized_sample; + mean = (intervals[1] + intervals[0]) / 2; + interval = (intervals[1] - intervals[0]) * (-(sample_difference < 0) | 1); + + dithered_sample = rshift64_clip24(MUL64(dither, interval) + ((int64_t)(mean + d) << 32), 32); + error = ((int64_t)FFABS(sample_difference) << 20) - MUL64(dithered_sample, quantization_factor); + quantize->error = FFABS(rshift64(error, 23)); + + parity_change = quantized_sample; + if (error < 0) + quantized_sample--; + else + parity_change--; + + inv = -(sample_difference < 0); + quantize->quantized_sample = quantized_sample ^ inv; + quantize->quantized_sample_parity_change = parity_change ^ inv; +} + +static void aptx_encode_channel(Channel *channel, int32_t samples[4]) +{ + int32_t subband_samples[4]; + int subband; + aptx_qmf_tree_analysis(&channel->qmf, samples, subband_samples); + aptx_generate_dither(channel); + for (subband = 0; subband < NB_SUBBANDS; subband++) { + int32_t diff = av_clip_intp2(subband_samples[subband] - channel->prediction[subband].predicted_sample, 23); + aptx_quantize_difference(&channel->quantize[subband], diff, + channel->dither[subband], + channel->invert_quantize[subband].quantization_factor, + &tables[subband]); + } +} + +static void aptx_decode_channel(Channel *channel, int32_t samples[4]) +{ + int32_t subband_samples[4]; + int subband; + for (subband = 0; subband < NB_SUBBANDS; subband++) + subband_samples[subband] = channel->prediction[subband].previous_reconstructed_sample; + aptx_qmf_tree_synthesis(&channel->qmf, subband_samples, samples); +} + + +static void aptx_invert_quantization(InvertQuantize *invert_quantize, + int32_t quantized_sample, int32_t dither, + ConstTables *tables) +{ + int32_t qr, idx, shift, factor_select; + + idx = (quantized_sample ^ -(quantized_sample < 0)) + 1; + qr = tables->quantize_intervals[idx] / 2; + if (quantized_sample < 0) + qr = -qr; + + qr = rshift64_clip24(((int64_t)qr<<32) + MUL64(dither, tables->invert_quantize_dither_factors[idx]), 32); + invert_quantize->reconstructed_difference = MUL64(invert_quantize->quantization_factor, qr) >> 19; + + shift = 24 - tables->quantized_bits; + + /* update factor_select */ + factor_select = 32620 * invert_quantize->factor_select; + factor_select = rshift32(factor_select + (tables->quantize_factor_select_offset[idx] << 15), 15); + invert_quantize->factor_select = av_clip(factor_select, 0, (shift << 8) | 0xFF); + + /* update quantization factor */ + idx = (invert_quantize->factor_select & 0xFF) >> 3; + shift -= invert_quantize->factor_select >> 8; + invert_quantize->quantization_factor = (quantization_factors[idx] << 11) >> shift; +} + +static int32_t *aptx_reconstructed_differences_update(Prediction *prediction, + int32_t reconstructed_difference, + int order) +{ + int32_t *rd1 = prediction->reconstructed_differences, *rd2 = rd1 + order; + int p = prediction->pos; + + rd1[p] = rd2[p]; + prediction->pos = p = (p + 1) % order; + rd2[p] = reconstructed_difference; + return &rd2[p]; +} + +static void aptx_prediction_filtering(Prediction *prediction, + int32_t reconstructed_difference, + int order) +{ + int32_t reconstructed_sample, predictor, srd0; + int32_t *reconstructed_differences; + int64_t predicted_difference = 0; + int i; + + reconstructed_sample = av_clip_intp2(reconstructed_difference + prediction->predicted_sample, 23); + predictor = av_clip_intp2((MUL64(prediction->s_weight[0], prediction->previous_reconstructed_sample) + + MUL64(prediction->s_weight[1], reconstructed_sample)) >> 22, 23); + prediction->previous_reconstructed_sample = reconstructed_sample; + + reconstructed_differences = aptx_reconstructed_differences_update(prediction, reconstructed_difference, order); + srd0 = FFDIFFSIGN(reconstructed_difference, 0) << 23; + for (i = 0; i < order; i++) { + int32_t srd = FF_SIGNBIT(reconstructed_differences[-i-1]) | 1; + prediction->d_weight[i] -= rshift32(prediction->d_weight[i] - srd*srd0, 8); + predicted_difference += MUL64(reconstructed_differences[-i], prediction->d_weight[i]); + } + + prediction->predicted_difference = av_clip_intp2(predicted_difference >> 22, 23); + prediction->predicted_sample = av_clip_intp2(predictor + prediction->predicted_difference, 23); +} + +static void aptx_process_subband(InvertQuantize *invert_quantize, + Prediction *prediction, + int32_t quantized_sample, int32_t dither, + ConstTables *tables) +{ + int32_t sign, same_sign[2], weight[2], sw1, range; + + aptx_invert_quantization(invert_quantize, quantized_sample, dither, tables); + + sign = FFDIFFSIGN(invert_quantize->reconstructed_difference, + -prediction->predicted_difference); + same_sign[0] = sign * prediction->prev_sign[0]; + same_sign[1] = sign * prediction->prev_sign[1]; + prediction->prev_sign[0] = prediction->prev_sign[1]; + prediction->prev_sign[1] = sign | 1; + + range = 0x100000; + sw1 = rshift32(-same_sign[1] * prediction->s_weight[1], 1); + sw1 = (av_clip(sw1, -range, range) & ~0xF) << 4; + + range = 0x300000; + weight[0] = 254 * prediction->s_weight[0] + 0x800000*same_sign[0] + sw1; + prediction->s_weight[0] = av_clip(rshift32(weight[0], 8), -range, range); + + range = 0x3C0000 - prediction->s_weight[0]; + weight[1] = 255 * prediction->s_weight[1] + 0xC00000*same_sign[1]; + prediction->s_weight[1] = av_clip(rshift32(weight[1], 8), -range, range); + + aptx_prediction_filtering(prediction, + invert_quantize->reconstructed_difference, + tables->prediction_order); +} + +static void aptx_invert_quantize_and_prediction(Channel *channel) +{ + int subband; + for (subband = 0; subband < NB_SUBBANDS; subband++) + aptx_process_subband(&channel->invert_quantize[subband], + &channel->prediction[subband], + channel->quantize[subband].quantized_sample, + channel->dither[subband], + &tables[subband]); +} + +static int32_t aptx_quantized_parity(Channel *channel) +{ + int32_t parity = channel->dither_parity; + int subband; + + for (subband = 0; subband < NB_SUBBANDS; subband++) + parity ^= channel->quantize[subband].quantized_sample; + + return parity & 1; +} + +/* For each sample, ensure that the parity of all subbands of all channels + * is 0 except once every 8 samples where the parity is forced to 1. */ +static int aptx_check_parity(Channel channels[NB_CHANNELS], int32_t *idx) +{ + int32_t parity = aptx_quantized_parity(&channels[LEFT]) + ^ aptx_quantized_parity(&channels[RIGHT]); + + int eighth = *idx == 7; + *idx = (*idx + 1) & 7; + + return parity ^ eighth; +} + +static void aptx_insert_sync(Channel channels[NB_CHANNELS], int32_t *idx) +{ + if (aptx_check_parity(channels, idx)) { + int i; + Channel *c; + static const int map[] = { 1, 2, 0, 3 }; + Quantize *min = &channels[NB_CHANNELS-1].quantize[map[0]]; + for (c = &channels[NB_CHANNELS-1]; c >= channels; c--) + for (i = 0; i < NB_SUBBANDS; i++) + if (c->quantize[map[i]].error < min->error) + min = &c->quantize[map[i]]; + + /* Forcing the desired parity is done by offsetting by 1 the quantized + * sample from the subband featuring the smallest quantization error. */ + min->quantized_sample = min->quantized_sample_parity_change; + } +} + +static uint16_t aptx_pack_codeword(Channel *channel) +{ + int32_t parity = aptx_quantized_parity(channel); + return (((channel->quantize[3].quantized_sample & 0x06) | parity) << 13) + | (((channel->quantize[2].quantized_sample & 0x03) ) << 11) + | (((channel->quantize[1].quantized_sample & 0x0F) ) << 7) + | (((channel->quantize[0].quantized_sample & 0x7F) ) << 0); +} + +static void aptx_unpack_codeword(Channel *channel, uint16_t codeword) +{ + channel->quantize[0].quantized_sample = sign_extend(codeword >> 0, 7); + channel->quantize[1].quantized_sample = sign_extend(codeword >> 7, 4); + channel->quantize[2].quantized_sample = sign_extend(codeword >> 11, 2); + channel->quantize[3].quantized_sample = sign_extend(codeword >> 13, 3); + channel->quantize[3].quantized_sample = (channel->quantize[3].quantized_sample & ~1) + | aptx_quantized_parity(channel); +} + +static void aptx_encode_samples(AptXContext *ctx, + int32_t samples[NB_CHANNELS][4], + uint8_t output[2*NB_CHANNELS]) +{ + int channel; + for (channel = 0; channel < NB_CHANNELS; channel++) + aptx_encode_channel(&ctx->channels[channel], samples[channel]); + + aptx_insert_sync(ctx->channels, &ctx->sync_idx); + + for (channel = 0; channel < NB_CHANNELS; channel++) { + aptx_invert_quantize_and_prediction(&ctx->channels[channel]); + AV_WB16(output + 2*channel, aptx_pack_codeword(&ctx->channels[channel])); + } +} + +static int aptx_decode_samples(AptXContext *ctx, + const uint8_t input[2*NB_CHANNELS], + int32_t samples[NB_CHANNELS][4]) +{ + int channel, ret; + + for (channel = 0; channel < NB_CHANNELS; channel++) { + uint16_t codeword; + aptx_generate_dither(&ctx->channels[channel]); + + codeword = AV_RB16(input + 2*channel); + aptx_unpack_codeword(&ctx->channels[channel], codeword); + aptx_invert_quantize_and_prediction(&ctx->channels[channel]); + } + + ret = aptx_check_parity(ctx->channels, &ctx->sync_idx); + + for (channel = 0; channel < NB_CHANNELS; channel++) + aptx_decode_channel(&ctx->channels[channel], samples[channel]); + + return ret; +} + + +static av_cold int aptx_init(AVCodecContext *avctx) +{ + AptXContext *s = avctx->priv_data; + int chan, subband; + + if (avctx->frame_size == 0) + avctx->frame_size = 1024; + + if (avctx->frame_size & 3) { + av_log(avctx, AV_LOG_ERROR, "Frame size must be a multiple of 4 samples\n"); + return AVERROR(EINVAL); + } + + for (chan = 0; chan < NB_CHANNELS; chan++) { + Channel *channel = &s->channels[chan]; + for (subband = 0; subband < NB_SUBBANDS; subband++) { + Prediction *prediction = &channel->prediction[subband]; + prediction->prev_sign[0] = 1; + prediction->prev_sign[1] = 1; + } + } + + ff_af_queue_init(avctx, &s->afq); + return 0; +} + +static int aptx_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AptXContext *s = avctx->priv_data; + AVFrame *frame = data; + int pos, channel, sample, ret; + + if (avpkt->size < 4) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->channels = NB_CHANNELS; + frame->format = AV_SAMPLE_FMT_S32P; + frame->nb_samples = avpkt->size & ~3; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + for (pos = 0; pos < frame->nb_samples; pos += 4) { + int32_t samples[NB_CHANNELS][4]; + + if (aptx_decode_samples(s, &avpkt->data[pos], samples)) { + av_log(avctx, AV_LOG_ERROR, "Synchronization error\n"); + return AVERROR_INVALIDDATA; + } + + for (channel = 0; channel < NB_CHANNELS; channel++) + for (sample = 0; sample < 4; sample++) + AV_WN32A(&frame->data[channel][4*(sample+pos)], + samples[channel][sample] << 8); + } + + *got_frame_ptr = 1; + return frame->nb_samples; +} + +static int aptx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + AptXContext *s = avctx->priv_data; + int pos, channel, sample, ret; + + if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) + return ret; + + if ((ret = ff_alloc_packet2(avctx, avpkt, frame->nb_samples, 0)) < 0) + return ret; + + for (pos = 0; pos < frame->nb_samples; pos += 4) { + int32_t samples[NB_CHANNELS][4]; + + for (channel = 0; channel < NB_CHANNELS; channel++) + for (sample = 0; sample < 4; sample++) + samples[channel][sample] = (int32_t)AV_RN32A(&frame->data[channel][4*(sample+pos)]) >> 8; + + aptx_encode_samples(s, samples, avpkt->data + pos); + } + + ff_af_queue_remove(&s->afq, frame->nb_samples, &avpkt->pts, &avpkt->duration); + *got_packet_ptr = 1; + return 0; +} + +static av_cold int aptx_close(AVCodecContext *avctx) +{ + AptXContext *s = avctx->priv_data; + ff_af_queue_close(&s->afq); + return 0; +} + + +#if CONFIG_APTX_DECODER +AVCodec ff_aptx_decoder = { + .name = "aptx", + .long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_APTX, + .priv_data_size = sizeof(AptXContext), + .init = aptx_init, + .decode = aptx_decode_frame, + .close = aptx_close, + .capabilities = AV_CODEC_CAP_DR1, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_NONE }, +}; +#endif + +#if CONFIG_APTX_ENCODER +AVCodec ff_aptx_encoder = { + .name = "aptx", + .long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_APTX, + .priv_data_size = sizeof(AptXContext), + .init = aptx_init, + .encode2 = aptx_encode_frame, + .close = aptx_close, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_NONE }, + .supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0}, +}; +#endif diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index c4134424f0728..429d62a60a5e5 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -632,6 +632,7 @@ enum AVCodecID { AV_CODEC_ID_ATRAC3AL, AV_CODEC_ID_ATRAC3PAL, AV_CODEC_ID_DOLBY_E, + AV_CODEC_ID_APTX, /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 92bf1d268168a..c3688de1d6df4 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2859,6 +2859,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("ADPCM MTAF"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_APTX, + .type = AVMEDIA_TYPE_AUDIO, + .name = "aptx", + .long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"), + .props = AV_CODEC_PROP_LOSSY, + }, /* subtitle codecs */ { From 018eef1a1bb6f791201e9b9f38a317a2059c3af1 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Fri, 10 Nov 2017 22:09:24 +0100 Subject: [PATCH 0821/2557] aptx: add raw muxer and demuxer for aptX --- doc/general.texi | 1 + libavformat/Makefile | 2 ++ libavformat/allformats.c | 1 + libavformat/aptxdec.c | 78 ++++++++++++++++++++++++++++++++++++++++ libavformat/rawenc.c | 13 +++++++ libavformat/utils.c | 1 + 6 files changed, 96 insertions(+) create mode 100644 libavformat/aptxdec.c diff --git a/doc/general.texi b/doc/general.texi index de4efee913eaa..efd4a92495e32 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -441,6 +441,7 @@ library: @item raw AC-3 @tab X @tab X @item raw AMR-NB @tab @tab X @item raw AMR-WB @tab @tab X +@item raw aptX @tab X @tab X @item raw Chinese AVS video @tab X @tab X @item raw CRI ADX @tab X @tab X @item raw Dirac @tab X @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index 146a4656f23c9..b1e7b193f48e1 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -94,6 +94,8 @@ OBJS-$(CONFIG_APC_DEMUXER) += apc.o OBJS-$(CONFIG_APE_DEMUXER) += ape.o apetag.o img2.o OBJS-$(CONFIG_APNG_DEMUXER) += apngdec.o OBJS-$(CONFIG_APNG_MUXER) += apngenc.o +OBJS-$(CONFIG_APTX_DEMUXER) += aptxdec.o rawdec.o +OBJS-$(CONFIG_APTX_MUXER) += rawenc.o OBJS-$(CONFIG_AQTITLE_DEMUXER) += aqtitledec.o subtitles.o OBJS-$(CONFIG_ASF_DEMUXER) += asfdec_f.o asf.o asfcrypt.o \ avlanguage.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 1896d50e9edd9..9213af9301fa5 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -69,6 +69,7 @@ static void register_all(void) REGISTER_DEMUXER (APC, apc); REGISTER_DEMUXER (APE, ape); REGISTER_MUXDEMUX(APNG, apng); + REGISTER_MUXDEMUX(APTX, aptx); REGISTER_DEMUXER (AQTITLE, aqtitle); REGISTER_MUXDEMUX(ASF, asf); REGISTER_DEMUXER (ASF_O, asf_o); diff --git a/libavformat/aptxdec.c b/libavformat/aptxdec.c new file mode 100644 index 0000000000000..3b8fae1b55e39 --- /dev/null +++ b/libavformat/aptxdec.c @@ -0,0 +1,78 @@ +/* + * RAW aptX demuxer + * + * Copyright (C) 2017 Aurelien Jacobs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" +#include "rawdec.h" + +#define APTX_BLOCK_SIZE 4 +#define APTX_PACKET_SIZE (256*APTX_BLOCK_SIZE) + +typedef struct AptXDemuxerContext { + AVClass *class; + int sample_rate; +} AptXDemuxerContext; + +static int aptx_read_header(AVFormatContext *s) +{ + AptXDemuxerContext *s1 = s->priv_data; + AVStream *st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_APTX; + st->codecpar->format = AV_SAMPLE_FMT_S32P; + st->codecpar->channels = 2; + st->codecpar->sample_rate = s1->sample_rate; + st->codecpar->bits_per_coded_sample = 4; + st->codecpar->block_align = APTX_BLOCK_SIZE; + st->codecpar->frame_size = APTX_PACKET_SIZE; + st->start_time = 0; + return 0; +} + +static int aptx_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + return av_get_packet(s->pb, pkt, APTX_PACKET_SIZE); +} + +static const AVOption aptx_options[] = { + { "sample_rate", "", offsetof(AptXDemuxerContext, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +static const AVClass aptx_demuxer_class = { + .class_name = "aptx demuxer", + .item_name = av_default_item_name, + .option = aptx_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_aptx_demuxer = { + .name = "aptx", + .long_name = NULL_IF_CONFIG_SMALL("raw aptX"), + .extensions = "aptx", + .priv_data_size = sizeof(AptXDemuxerContext), + .read_header = aptx_read_header, + .read_packet = aptx_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .priv_class = &aptx_demuxer_class, +}; diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index f640121cb4698..aa3ef76fbf41c 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -91,6 +91,19 @@ AVOutputFormat ff_adx_muxer = { }; #endif +#if CONFIG_APTX_MUXER +AVOutputFormat ff_aptx_muxer = { + .name = "aptx", + .long_name = NULL_IF_CONFIG_SMALL("raw aptX (Audio Processing Technology for Bluetooth)"), + .extensions = "aptx", + .audio_codec = AV_CODEC_ID_APTX, + .video_codec = AV_CODEC_ID_NONE, + .write_header = force_one_stream, + .write_packet = ff_raw_write_packet, + .flags = AVFMT_NOTIMESTAMPS, +}; +#endif + #if CONFIG_CAVSVIDEO_MUXER AVOutputFormat ff_cavsvideo_muxer = { .name = "cavsvideo", diff --git a/libavformat/utils.c b/libavformat/utils.c index 2b2411ffe7f9a..d45a6b55a7e11 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -324,6 +324,7 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, } fmt_id_type[] = { { "aac", AV_CODEC_ID_AAC, AVMEDIA_TYPE_AUDIO }, { "ac3", AV_CODEC_ID_AC3, AVMEDIA_TYPE_AUDIO }, + { "aptx", AV_CODEC_ID_APTX, AVMEDIA_TYPE_AUDIO }, { "dts", AV_CODEC_ID_DTS, AVMEDIA_TYPE_AUDIO }, { "dvbsub", AV_CODEC_ID_DVB_SUBTITLE,AVMEDIA_TYPE_SUBTITLE }, { "dvbtxt", AV_CODEC_ID_DVB_TELETEXT,AVMEDIA_TYPE_SUBTITLE }, From eb7a01d692684b3d7008506aaedfcdd79193bde6 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Fri, 10 Nov 2017 21:31:07 +0000 Subject: [PATCH 0822/2557] Changelog: list the new aptX features Signed-off-by: Rostislav Pehlivanov --- Changelog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog b/Changelog index c1c886193e8b8..3914672831357 100644 --- a/Changelog +++ b/Changelog @@ -11,6 +11,8 @@ version : - TiVo ty/ty+ demuxer - Intel QSV-accelerated MJPEG encoding - PCE support for extended channel layouts in the AAC encoder +- native aptX encoder and decoder +- Raw aptX muxer and demuxer version 3.4: From 5593049466bcd1d3f1ddbfe580be4f36123d7c3d Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 3 Oct 2017 15:15:16 +0200 Subject: [PATCH 0823/2557] avcodec/cuvid: rename cuvid.c to cuviddec.c cuvid.c is used by Libav's CUVID hwaccel. Resolve the conflict and avoid future merge problems by renaming our decoder. Signed-off-by: Timo Rothenpieler --- libavcodec/Makefile | 10 +++++----- libavcodec/{cuvid.c => cuviddec.c} | 0 2 files changed, 5 insertions(+), 5 deletions(-) rename libavcodec/{cuvid.c => cuviddec.c} (100%) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 95c843dee7591..3704316d8c3d1 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -338,7 +338,7 @@ OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264_cabac.o h264_cavlc.o \ h264_mb.o h264_picture.o \ h264_refs.o h264_sei.o \ h264_slice.o h264data.o -OBJS-$(CONFIG_H264_CUVID_DECODER) += cuvid.o +OBJS-$(CONFIG_H264_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_H264_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o @@ -357,7 +357,7 @@ OBJS-$(CONFIG_HAP_ENCODER) += hapenc.o hap.o OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o \ hevc_cabac.o hevc_refs.o hevcpred.o \ hevcdsp.o hevc_filter.o hevc_data.o -OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuvid.o +OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o OBJS-$(CONFIG_NVENC_HEVC_ENCODER) += nvenc_hevc.o @@ -624,7 +624,7 @@ OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1_block.o vc1_loopfilter.o vc1_mc.o vc1_pred.o vc1.o vc1data.o \ msmpeg4dec.o msmpeg4.o msmpeg4data.o \ wmv2dsp.o wmv2data.o -OBJS-$(CONFIG_VC1_CUVID_DECODER) += cuvid.o +OBJS-$(CONFIG_VC1_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_VC1_MMAL_DECODER) += mmaldec.o OBJS-$(CONFIG_VC1_QSV_DECODER) += qsvdec_other.o OBJS-$(CONFIG_VC1_V4L2M2M_DECODER) += v4l2_m2m_dec.o @@ -643,7 +643,7 @@ OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o \ vp6dsp.o vp56rac.o OBJS-$(CONFIG_VP7_DECODER) += vp8.o vp56rac.o OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp56rac.o -OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuvid.o +OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_VP8_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_VP8_QSV_DECODER) += qsvdec_other.o OBJS-$(CONFIG_VP8_RKMPP_DECODER) += rkmppdec.o @@ -653,7 +653,7 @@ OBJS-$(CONFIG_VP8_V4L2M2M_ENCODER) += v4l2_m2m_enc.o OBJS-$(CONFIG_VP9_DECODER) += vp9.o vp9data.o vp9dsp.o vp9lpf.o vp9recon.o \ vp9block.o vp9prob.o vp9mvs.o vp56rac.o \ vp9dsp_8bpp.o vp9dsp_10bpp.o vp9dsp_12bpp.o -OBJS-$(CONFIG_VP9_CUVID_DECODER) += cuvid.o +OBJS-$(CONFIG_VP9_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_VP9_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_VP9_RKMPP_DECODER) += rkmppdec.o OBJS-$(CONFIG_VP9_VAAPI_ENCODER) += vaapi_encode_vp9.o diff --git a/libavcodec/cuvid.c b/libavcodec/cuviddec.c similarity index 100% rename from libavcodec/cuvid.c rename to libavcodec/cuviddec.c From ae5046e492cd87233111e994ca4ae3d74a233b51 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 3 Oct 2017 15:04:45 +0200 Subject: [PATCH 0824/2557] avcodec: allow multiple hwaccels for the same codec/pixfmt Currently, AVHWAccels are looked up using a (codec_id, pixfmt) tuple. This means it's impossible to have 2 decoders for the same codec and using the same opaque hardware pixel format. This breaks merging Libav's CUVID hwaccel. FFmpeg has its own CUVID support, but it's a full stream decoder, using NVIDIA's codec parser. The Libav one is a true hwaccel, which is based on the builtin software decoders. Fix this by introducing another field to disambiguate AVHWAccels, and use it for our CUVID decoders. FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS makes this mechanism backwards compatible and optional. --- libavcodec/avcodec.h | 7 +++++++ libavcodec/cuviddec.c | 2 ++ libavcodec/decode.c | 12 ++++++++---- libavcodec/internal.h | 5 +++++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 429d62a60a5e5..15ca871b59112 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3532,6 +3532,13 @@ typedef struct AVHWAccel { * Internal hwaccel capabilities. */ int caps_internal; + + /** + * Some hwaccels are ambiguous if only the id and pix_fmt fields are used. + * If non-NULL, the associated AVCodec must have + * FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS set. + */ + const AVClass *decoder_class; } AVHWAccel; /** diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index 2ba8e00c6af1f..6370348639776 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -1106,6 +1106,7 @@ static const AVOption options[] = { .type = AVMEDIA_TYPE_VIDEO, \ .id = AV_CODEC_ID_##X, \ .pix_fmt = AV_PIX_FMT_CUDA, \ + .decoder_class = &x##_cuvid_class, \ }; \ AVCodec ff_##x##_cuvid_decoder = { \ .name = #x "_cuvid", \ @@ -1120,6 +1121,7 @@ static const AVOption options[] = { .receive_frame = cuvid_output_frame, \ .flush = cuvid_flush, \ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ + .caps_internal = FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS, \ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA, \ AV_PIX_FMT_NV12, \ AV_PIX_FMT_P010, \ diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 44b874d4f817d..9fdc7bb56548f 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1090,15 +1090,19 @@ enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const en return fmt[0]; } -static AVHWAccel *find_hwaccel(enum AVCodecID codec_id, +static AVHWAccel *find_hwaccel(AVCodecContext *avctx, enum AVPixelFormat pix_fmt) { AVHWAccel *hwaccel = NULL; + const AVClass *av_class = + (avctx->codec->caps_internal & FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS) + ? avctx->codec->priv_class : NULL; - while ((hwaccel = av_hwaccel_next(hwaccel))) - if (hwaccel->id == codec_id + while ((hwaccel = av_hwaccel_next(hwaccel))) { + if (hwaccel->decoder_class == av_class && hwaccel->id == avctx->codec_id && hwaccel->pix_fmt == pix_fmt) return hwaccel; + } return NULL; } @@ -1106,7 +1110,7 @@ static int setup_hwaccel(AVCodecContext *avctx, const enum AVPixelFormat fmt, const char *name) { - AVHWAccel *hwa = find_hwaccel(avctx->codec_id, fmt); + AVHWAccel *hwa = find_hwaccel(avctx, fmt); int ret = 0; if (!hwa) { diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 7748f09f5496c..948d5461c1015 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -69,6 +69,11 @@ */ #define FF_CODEC_CAP_SLICE_THREAD_HAS_MF (1 << 5) +/** + * Allow only AVHWAccels which have a matching decoder_class field. + */ +#define FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS (1 << 6) + #ifdef TRACE # define ff_tlog(ctx, ...) av_log(ctx, AV_LOG_TRACE, __VA_ARGS__) #else From 0aecc08e5fd15960639a75c43265539e70d0189e Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 3 Oct 2017 17:43:13 +0200 Subject: [PATCH 0825/2557] avcodec/decode: add missing \n to log message --- libavcodec/decode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 9fdc7bb56548f..570799f6d7acb 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1115,7 +1115,7 @@ static int setup_hwaccel(AVCodecContext *avctx, if (!hwa) { av_log(avctx, AV_LOG_ERROR, - "Could not find an AVHWAccel for the pixel format: %s", + "Could not find an AVHWAccel for the pixel format: %s\n", name); return AVERROR(ENOENT); } From 0e00624389955bc559d75855d5c4876266d9575f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 11 Feb 2017 16:49:34 +0100 Subject: [PATCH 0826/2557] h264dec: add a NVDEC hwaccel Some parts of the code are based on a patch by Timo Rothenpieler Merges Libav commit b9129ec4668c511e0a79e25c6f25d748cee172c9. Due to the name clash with our cuvid decoder, rename it to nvdec. This commit also changes the Libav code to dynamic loading of the cuda/cuvid libraries. Signed-off-by: Timo Rothenpieler --- Changelog | 1 + configure | 10 +- fftools/ffmpeg.h | 1 + fftools/ffmpeg_opt.c | 4 + libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 1 + libavcodec/h264_slice.c | 4 + libavcodec/nvdec.c | 431 ++++++++++++++++++++++++++++++++++++++++ libavcodec/nvdec.h | 62 ++++++ libavcodec/nvdec_h264.c | 176 ++++++++++++++++ libavcodec/version.h | 2 +- 11 files changed, 691 insertions(+), 3 deletions(-) create mode 100644 libavcodec/nvdec.c create mode 100644 libavcodec/nvdec.h create mode 100644 libavcodec/nvdec_h264.c diff --git a/Changelog b/Changelog index 3914672831357..ba2951db2507e 100644 --- a/Changelog +++ b/Changelog @@ -13,6 +13,7 @@ version : - PCE support for extended channel layouts in the AAC encoder - native aptX encoder and decoder - Raw aptX muxer and demuxer +- NVIDIA NVDEC-accelerated H.264 hwaccel decoding version 3.4: diff --git a/configure b/configure index f087ba61b17d7..1b90d8e9a18f0 100755 --- a/configure +++ b/configure @@ -313,6 +313,7 @@ External library support: --enable-libmfx enable Intel MediaSDK (AKA Quick Sync Video) code via libmfx [no] --enable-libnpp enable Nvidia Performance Primitives-based code [no] --enable-mmal enable Broadcom Multi-Media Abstraction Layer (Raspberry Pi) via MMAL [no] + --disable-nvdec disable Nvidia video decoding acceleration (via hwaccel) [autodetect] --disable-nvenc disable Nvidia video encoding code [autodetect] --enable-omx enable OpenMAX IL code [no] --enable-omx-rpi enable OpenMAX IL code for Raspberry Pi [no] @@ -1647,6 +1648,7 @@ HWACCEL_AUTODETECT_LIBRARY_LIST=" cuvid d3d11va dxva2 + nvdec nvenc vaapi vdpau @@ -2672,6 +2674,8 @@ h264_dxva2_hwaccel_deps="dxva2" h264_dxva2_hwaccel_select="h264_decoder" h264_mediacodec_hwaccel_deps="mediacodec" h264_mmal_hwaccel_deps="mmal" +h264_nvdec_hwaccel_deps="cuda nvdec" +h264_nvdec_hwaccel_select="h264_decoder" h264_qsv_hwaccel_deps="libmfx" h264_vaapi_hwaccel_deps="vaapi" h264_vaapi_hwaccel_select="h264_decoder" @@ -5940,6 +5944,8 @@ done enabled cuda_sdk && require cuda_sdk cuda.h cuCtxCreate -lcuda enabled cuvid && { enabled cuda || die "ERROR: CUVID requires CUDA"; } +enabled nvdec && { enabled cuda || + die "ERROR: NVDEC hwaccel requires CUDA"; } enabled chromaprint && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint enabled decklink && { require_header DeckLinkAPI.h && { check_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a060100" || die "ERROR: Decklink API version must be >= 10.6.1."; } } @@ -6295,11 +6301,11 @@ if enabled x86; then mingw32*|mingw64*|win32|win64|linux|cygwin*) ;; *) - disable cuda cuvid nvenc + disable cuda cuvid nvdec nvenc ;; esac else - disable cuda cuvid nvenc + disable cuda cuvid nvdec nvenc fi enabled nvenc && diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 50fc8d57674f7..e0977e1bf16f2 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -68,6 +68,7 @@ enum HWAccelID { HWACCEL_VAAPI, HWACCEL_CUVID, HWACCEL_D3D11VA, + HWACCEL_NVDEC, }; typedef struct HWAccel { diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index ca6f10d5ca6aa..e50895e64cc1a 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -90,6 +90,10 @@ const HWAccel hwaccels[] = { { "vaapi", hwaccel_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI, AV_HWDEVICE_TYPE_VAAPI }, #endif +#if CONFIG_NVDEC + { "nvdec", hwaccel_decode_init, HWACCEL_NVDEC, AV_PIX_FMT_CUDA, + AV_HWDEVICE_TYPE_CUDA }, +#endif #if CONFIG_CUVID { "cuvid", cuvid_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA, AV_HWDEVICE_TYPE_NONE }, diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3704316d8c3d1..db1f70784a43f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -830,6 +830,7 @@ OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o # hardware accelerators OBJS-$(CONFIG_D3D11VA) += dxva2.o OBJS-$(CONFIG_DXVA2) += dxva2.o +OBJS-$(CONFIG_NVDEC) += nvdec.o OBJS-$(CONFIG_VAAPI) += vaapi_decode.o OBJS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.o OBJS-$(CONFIG_VDPAU) += vdpau.o @@ -838,6 +839,7 @@ OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o OBJS-$(CONFIG_H263_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o +OBJS-$(CONFIG_H264_NVDEC_HWACCEL) += nvdec_h264.o OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec_h2645.o OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 463f7ed64e2cf..c58f99c1769e2 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -70,6 +70,7 @@ static void register_all(void) REGISTER_HWACCEL(H264_DXVA2, h264_dxva2); REGISTER_HWACCEL(H264_MEDIACODEC, h264_mediacodec); REGISTER_HWACCEL(H264_MMAL, h264_mmal); + REGISTER_HWACCEL(H264_NVDEC, h264_nvdec); REGISTER_HWACCEL(H264_QSV, h264_qsv); REGISTER_HWACCEL(H264_VAAPI, h264_vaapi); REGISTER_HWACCEL(H264_VDPAU, h264_vdpau); diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 94a1547ad65d6..da76b9293ff48 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -757,6 +757,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) { #define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \ (CONFIG_H264_D3D11VA_HWACCEL * 2) + \ + CONFIG_H264_NVDEC_HWACCEL + \ CONFIG_H264_VAAPI_HWACCEL + \ CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \ CONFIG_H264_VDPAU_HWACCEL) @@ -812,6 +813,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) case 8: #if CONFIG_H264_VDPAU_HWACCEL *fmt++ = AV_PIX_FMT_VDPAU; +#endif +#if CONFIG_H264_NVDEC_HWACCEL + *fmt++ = AV_PIX_FMT_CUDA; #endif if (CHROMA444(h)) { if (h->avctx->colorspace == AVCOL_SPC_RGB) diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c new file mode 100644 index 0000000000000..9ca9faa37879a --- /dev/null +++ b/libavcodec/nvdec.c @@ -0,0 +1,431 @@ +/* + * HW decode acceleration through NVDEC + * + * Copyright (c) 2016 Anton Khirnov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/common.h" +#include "libavutil/error.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_cuda_internal.h" +#include "libavutil/pixdesc.h" +#include "libavutil/pixfmt.h" + +#include "avcodec.h" +#include "decode.h" +#include "nvdec.h" +#include "internal.h" + +typedef struct NVDECDecoder { + CUvideodecoder decoder; + + AVBufferRef *hw_device_ref; + CUcontext cuda_ctx; + + CudaFunctions *cudl; + CuvidFunctions *cvdl; +} NVDECDecoder; + +typedef struct NVDECFramePool { + unsigned int dpb_size; + unsigned int nb_allocated; +} NVDECFramePool; + +static int map_avcodec_id(enum AVCodecID id) +{ + switch (id) { + case AV_CODEC_ID_H264: return cudaVideoCodec_H264; + } + return -1; +} + +static int map_chroma_format(enum AVPixelFormat pix_fmt) +{ + int shift_h = 0, shift_v = 0; + + av_pix_fmt_get_chroma_sub_sample(pix_fmt, &shift_h, &shift_v); + + if (shift_h == 1 && shift_v == 1) + return cudaVideoChromaFormat_420; + else if (shift_h == 1 && shift_v == 0) + return cudaVideoChromaFormat_422; + else if (shift_h == 0 && shift_v == 0) + return cudaVideoChromaFormat_444; + + return -1; +} + +static void nvdec_decoder_free(void *opaque, uint8_t *data) +{ + NVDECDecoder *decoder = (NVDECDecoder*)data; + + if (decoder->decoder) + decoder->cvdl->cuvidDestroyDecoder(decoder->decoder); + + av_buffer_unref(&decoder->hw_device_ref); + + cuvid_free_functions(&decoder->cvdl); + + av_freep(&decoder); +} + +static int nvdec_decoder_create(AVBufferRef **out, AVBufferRef *hw_device_ref, + CUVIDDECODECREATEINFO *params, void *logctx) +{ + AVHWDeviceContext *hw_device_ctx = (AVHWDeviceContext*)hw_device_ref->data; + AVCUDADeviceContext *device_hwctx = hw_device_ctx->hwctx; + + AVBufferRef *decoder_ref; + NVDECDecoder *decoder; + + CUcontext dummy; + CUresult err; + int ret; + + decoder = av_mallocz(sizeof(*decoder)); + if (!decoder) + return AVERROR(ENOMEM); + + decoder_ref = av_buffer_create((uint8_t*)decoder, sizeof(*decoder), + nvdec_decoder_free, NULL, AV_BUFFER_FLAG_READONLY); + if (!decoder_ref) { + av_freep(&decoder); + return AVERROR(ENOMEM); + } + + decoder->hw_device_ref = av_buffer_ref(hw_device_ref); + if (!decoder->hw_device_ref) { + ret = AVERROR(ENOMEM); + goto fail; + } + decoder->cuda_ctx = device_hwctx->cuda_ctx; + decoder->cudl = device_hwctx->internal->cuda_dl; + + ret = cuvid_load_functions(&decoder->cvdl); + if (ret < 0) { + av_log(logctx, AV_LOG_ERROR, "Failed loading nvcuvid.\n"); + goto fail; + } + + err = decoder->cudl->cuCtxPushCurrent(decoder->cuda_ctx); + if (err != CUDA_SUCCESS) { + ret = AVERROR_UNKNOWN; + goto fail; + } + + err = decoder->cvdl->cuvidCreateDecoder(&decoder->decoder, params); + + decoder->cudl->cuCtxPopCurrent(&dummy); + + if (err != CUDA_SUCCESS) { + av_log(logctx, AV_LOG_ERROR, "Error creating a NVDEC decoder: %d\n", err); + ret = AVERROR_UNKNOWN; + goto fail; + } + + *out = decoder_ref; + + return 0; +fail: + av_buffer_unref(&decoder_ref); + return ret; +} + +static AVBufferRef *nvdec_decoder_frame_alloc(void *opaque, int size) +{ + NVDECFramePool *pool = opaque; + AVBufferRef *ret; + + if (pool->nb_allocated >= pool->dpb_size) + return NULL; + + ret = av_buffer_alloc(sizeof(unsigned int)); + if (!ret) + return NULL; + + *(unsigned int*)ret->data = pool->nb_allocated++; + + return ret; +} + +int ff_nvdec_decode_uninit(AVCodecContext *avctx) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + + av_freep(&ctx->bitstream); + ctx->bitstream_len = 0; + ctx->bitstream_allocated = 0; + + av_freep(&ctx->slice_offsets); + ctx->nb_slices = 0; + ctx->slice_offsets_allocated = 0; + + av_buffer_unref(&ctx->decoder_ref); + av_buffer_pool_uninit(&ctx->decoder_pool); + + return 0; +} + +int ff_nvdec_decode_init(AVCodecContext *avctx, unsigned int dpb_size) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + + NVDECFramePool *pool; + AVHWFramesContext *frames_ctx; + const AVPixFmtDescriptor *sw_desc; + + CUVIDDECODECREATEINFO params = { 0 }; + + int cuvid_codec_type, cuvid_chroma_format; + int ret = 0; + + sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); + if (!sw_desc) + return AVERROR_BUG; + + cuvid_codec_type = map_avcodec_id(avctx->codec_id); + if (cuvid_codec_type < 0) { + av_log(avctx, AV_LOG_ERROR, "Unsupported codec ID\n"); + return AVERROR_BUG; + } + + cuvid_chroma_format = map_chroma_format(avctx->sw_pix_fmt); + if (cuvid_chroma_format < 0) { + av_log(avctx, AV_LOG_ERROR, "Unsupported chroma format\n"); + return AVERROR(ENOSYS); + } + + if (avctx->thread_type & FF_THREAD_FRAME) + dpb_size += avctx->thread_count; + + if (!avctx->hw_frames_ctx) { + AVHWFramesContext *frames_ctx; + + if (!avctx->hw_device_ctx) { + av_log(avctx, AV_LOG_ERROR, "A hardware device or frames context " + "is required for CUVID decoding.\n"); + return AVERROR(EINVAL); + } + + avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); + if (!avctx->hw_frames_ctx) + return AVERROR(ENOMEM); + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + + frames_ctx->format = AV_PIX_FMT_CUDA; + frames_ctx->width = avctx->coded_width; + frames_ctx->height = avctx->coded_height; + frames_ctx->sw_format = AV_PIX_FMT_NV12; + frames_ctx->sw_format = sw_desc->comp[0].depth > 8 ? + AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; + frames_ctx->initial_pool_size = dpb_size; + + ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error initializing internal frames context\n"); + return ret; + } + } + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + + params.ulWidth = avctx->coded_width; + params.ulHeight = avctx->coded_height; + params.ulTargetWidth = avctx->coded_width; + params.ulTargetHeight = avctx->coded_height; + params.bitDepthMinus8 = sw_desc->comp[0].depth - 8; + params.OutputFormat = params.bitDepthMinus8 ? + cudaVideoSurfaceFormat_P016 : cudaVideoSurfaceFormat_NV12; + params.CodecType = cuvid_codec_type; + params.ChromaFormat = cuvid_chroma_format; + params.ulNumDecodeSurfaces = dpb_size; + params.ulNumOutputSurfaces = 1; + + ret = nvdec_decoder_create(&ctx->decoder_ref, frames_ctx->device_ref, ¶ms, avctx); + if (ret < 0) + return ret; + + pool = av_mallocz(sizeof(*pool)); + if (!pool) { + ret = AVERROR(ENOMEM); + goto fail; + } + pool->dpb_size = dpb_size; + + ctx->decoder_pool = av_buffer_pool_init2(sizeof(int), pool, + nvdec_decoder_frame_alloc, av_free); + if (!ctx->decoder_pool) { + ret = AVERROR(ENOMEM); + goto fail; + } + + return 0; +fail: + ff_nvdec_decode_uninit(avctx); + return ret; +} + +static void nvdec_fdd_priv_free(void *priv) +{ + NVDECFrame *cf = priv; + + if (!cf) + return; + + av_buffer_unref(&cf->idx_ref); + av_buffer_unref(&cf->decoder_ref); + + av_freep(&priv); +} + +static int nvdec_retrieve_data(void *logctx, AVFrame *frame) +{ + FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data; + NVDECFrame *cf = (NVDECFrame*)fdd->hwaccel_priv; + NVDECDecoder *decoder = (NVDECDecoder*)cf->decoder_ref->data; + + CUVIDPROCPARAMS vpp = { .progressive_frame = 1 }; + + CUresult err; + CUcontext dummy; + CUdeviceptr devptr; + + unsigned int pitch, i; + unsigned int offset = 0; + int ret = 0; + + err = decoder->cudl->cuCtxPushCurrent(decoder->cuda_ctx); + if (err != CUDA_SUCCESS) + return AVERROR_UNKNOWN; + + err = decoder->cvdl->cuvidMapVideoFrame(decoder->decoder, cf->idx, &devptr, + &pitch, &vpp); + if (err != CUDA_SUCCESS) { + av_log(logctx, AV_LOG_ERROR, "Error mapping a picture with CUVID: %d\n", + err); + ret = AVERROR_UNKNOWN; + goto finish; + } + + for (i = 0; frame->data[i]; i++) { + CUDA_MEMCPY2D cpy = { + .srcMemoryType = CU_MEMORYTYPE_DEVICE, + .dstMemoryType = CU_MEMORYTYPE_DEVICE, + .srcDevice = devptr, + .dstDevice = (CUdeviceptr)frame->data[i], + .srcPitch = pitch, + .dstPitch = frame->linesize[i], + .srcY = offset, + .WidthInBytes = FFMIN(pitch, frame->linesize[i]), + .Height = frame->height >> (i ? 1 : 0), + }; + + err = decoder->cudl->cuMemcpy2D(&cpy); + if (err != CUDA_SUCCESS) { + av_log(logctx, AV_LOG_ERROR, "Error copying decoded frame: %d\n", + err); + ret = AVERROR_UNKNOWN; + goto copy_fail; + } + + offset += cpy.Height; + } + +copy_fail: + decoder->cvdl->cuvidUnmapVideoFrame(decoder->decoder, devptr); + +finish: + decoder->cudl->cuCtxPopCurrent(&dummy); + return ret; +} + +int ff_nvdec_start_frame(AVCodecContext *avctx, AVFrame *frame) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data; + NVDECFrame *cf = NULL; + int ret; + + ctx->bitstream_len = 0; + ctx->nb_slices = 0; + + if (fdd->hwaccel_priv) + return 0; + + cf = av_mallocz(sizeof(*cf)); + if (!cf) + return AVERROR(ENOMEM); + + cf->decoder_ref = av_buffer_ref(ctx->decoder_ref); + if (!cf->decoder_ref) + goto fail; + + cf->idx_ref = av_buffer_pool_get(ctx->decoder_pool); + if (!cf->idx_ref) { + av_log(avctx, AV_LOG_ERROR, "No decoder surfaces left\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + cf->idx = *(unsigned int*)cf->idx_ref->data; + + fdd->hwaccel_priv = cf; + fdd->hwaccel_priv_free = nvdec_fdd_priv_free; + fdd->post_process = nvdec_retrieve_data; + + return 0; +fail: + nvdec_fdd_priv_free(cf); + return ret; + +} + +int ff_nvdec_end_frame(AVCodecContext *avctx) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + NVDECDecoder *decoder = (NVDECDecoder*)ctx->decoder_ref->data; + CUVIDPICPARAMS *pp = &ctx->pic_params; + + CUresult err; + CUcontext dummy; + + int ret = 0; + + pp->nBitstreamDataLen = ctx->bitstream_len; + pp->pBitstreamData = ctx->bitstream; + pp->nNumSlices = ctx->nb_slices; + pp->pSliceDataOffsets = ctx->slice_offsets; + + err = decoder->cudl->cuCtxPushCurrent(decoder->cuda_ctx); + if (err != CUDA_SUCCESS) + return AVERROR_UNKNOWN; + + err = decoder->cvdl->cuvidDecodePicture(decoder->decoder, &ctx->pic_params); + if (err != CUDA_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Error decoding a picture with NVDEC: %d\n", + err); + ret = AVERROR_UNKNOWN; + goto finish; + } + +finish: + decoder->cudl->cuCtxPopCurrent(&dummy); + + return ret; +} diff --git a/libavcodec/nvdec.h b/libavcodec/nvdec.h new file mode 100644 index 0000000000000..75ed5d492d58d --- /dev/null +++ b/libavcodec/nvdec.h @@ -0,0 +1,62 @@ +/* + * HW decode acceleration through NVDEC + * + * Copyright (c) 2016 Anton Khirnov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_NVDEC_H +#define AVCODEC_NVDEC_H + +#include "compat/cuda/dynlink_loader.h" + +#include + +#include "libavutil/buffer.h" +#include "libavutil/frame.h" + +#include "avcodec.h" + +typedef struct NVDECFrame { + unsigned int idx; + AVBufferRef *idx_ref; + AVBufferRef *decoder_ref; +} NVDECFrame; + +typedef struct NVDECContext { + CUVIDPICPARAMS pic_params; + + AVBufferPool *decoder_pool; + + AVBufferRef *decoder_ref; + + uint8_t *bitstream; + int bitstream_len; + unsigned int bitstream_allocated; + + unsigned *slice_offsets; + int nb_slices; + unsigned int slice_offsets_allocated; +} NVDECContext; + +int ff_nvdec_decode_init(AVCodecContext *avctx, unsigned int dpb_size); +int ff_nvdec_decode_uninit(AVCodecContext *avctx); +int ff_nvdec_start_frame(AVCodecContext *avctx, AVFrame *frame); +int ff_nvdec_end_frame(AVCodecContext *avctx); + +#endif /* AVCODEC_NVDEC_H */ diff --git a/libavcodec/nvdec_h264.c b/libavcodec/nvdec_h264.c new file mode 100644 index 0000000000000..4a6054089bb57 --- /dev/null +++ b/libavcodec/nvdec_h264.c @@ -0,0 +1,176 @@ +/* + * MPEG-4 Part 10 / AVC / H.264 HW decode acceleration through NVDEC + * + * Copyright (c) 2016 Anton Khirnov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "avcodec.h" +#include "nvdec.h" +#include "decode.h" +#include "internal.h" +#include "h264dec.h" + +static void dpb_add(const H264Context *h, CUVIDH264DPBENTRY *dst, const H264Picture *src, + int frame_idx) +{ + FrameDecodeData *fdd = (FrameDecodeData*)src->f->private_ref->data; + const NVDECFrame *cf = fdd->hwaccel_priv; + + dst->PicIdx = cf ? cf->idx : -1; + dst->FrameIdx = frame_idx; + dst->is_long_term = src->long_ref; + dst->not_existing = 0; + dst->used_for_reference = src->reference & 3; + dst->FieldOrderCnt[0] = src->field_poc[0]; + dst->FieldOrderCnt[1] = src->field_poc[1]; +} + +static int nvdec_h264_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + const H264Context *h = avctx->priv_data; + const PPS *pps = h->ps.pps; + const SPS *sps = h->ps.sps; + + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + CUVIDPICPARAMS *pp = &ctx->pic_params; + CUVIDH264PICPARAMS *ppc = &pp->CodecSpecific.h264; + FrameDecodeData *fdd; + NVDECFrame *cf; + + int i, dpb_size, ret; + + ret = ff_nvdec_start_frame(avctx, h->cur_pic_ptr->f); + if (ret < 0) + return ret; + + fdd = (FrameDecodeData*)h->cur_pic_ptr->f->private_ref->data; + cf = (NVDECFrame*)fdd->hwaccel_priv; + + *pp = (CUVIDPICPARAMS) { + .PicWidthInMbs = h->mb_width, + .FrameHeightInMbs = h->mb_height, + .CurrPicIdx = cf->idx, + .field_pic_flag = FIELD_PICTURE(h), + .bottom_field_flag = h->picture_structure == PICT_BOTTOM_FIELD, + .second_field = FIELD_PICTURE(h) && !h->first_field, + .ref_pic_flag = h->nal_ref_idc != 0, + .intra_pic_flag = 0, + + .CodecSpecific.h264 = { + .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4, + .pic_order_cnt_type = sps->poc_type, + .log2_max_pic_order_cnt_lsb_minus4 = FFMAX(sps->log2_max_poc_lsb - 4, 0), + .delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag, + .frame_mbs_only_flag = sps->frame_mbs_only_flag, + .direct_8x8_inference_flag = sps->direct_8x8_inference_flag, + .num_ref_frames = sps->ref_frame_count, + .residual_colour_transform_flag = sps->residual_color_transform_flag, + .bit_depth_luma_minus8 = sps->bit_depth_luma - 8, + .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8, + .qpprime_y_zero_transform_bypass_flag = sps->transform_bypass, + + .entropy_coding_mode_flag = pps->cabac, + .pic_order_present_flag = pps->pic_order_present, + .num_ref_idx_l0_active_minus1 = pps->ref_count[0] - 1, + .num_ref_idx_l1_active_minus1 = pps->ref_count[1] - 1, + .weighted_pred_flag = pps->weighted_pred, + .weighted_bipred_idc = pps->weighted_bipred_idc, + .pic_init_qp_minus26 = pps->init_qp - 26, + .deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present, + .redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present, + .transform_8x8_mode_flag = pps->transform_8x8_mode, + .MbaffFrameFlag = sps->mb_aff && !FIELD_PICTURE(h), + .constrained_intra_pred_flag = pps->constrained_intra_pred, + .chroma_qp_index_offset = pps->chroma_qp_index_offset[0], + .second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1], + .ref_pic_flag = h->nal_ref_idc != 0, + .frame_num = h->poc.frame_num, + .CurrFieldOrderCnt[0] = h->cur_pic_ptr->field_poc[0], + .CurrFieldOrderCnt[1] = h->cur_pic_ptr->field_poc[1], + }, + }; + + memcpy(ppc->WeightScale4x4, pps->scaling_matrix4, sizeof(ppc->WeightScale4x4)); + memcpy(ppc->WeightScale8x8[0], pps->scaling_matrix8[0], sizeof(ppc->WeightScale8x8[0])); + memcpy(ppc->WeightScale8x8[1], pps->scaling_matrix8[3], sizeof(ppc->WeightScale8x8[0])); + + dpb_size = 0; + for (i = 0; i < h->short_ref_count; i++) + dpb_add(h, &ppc->dpb[dpb_size++], h->short_ref[i], h->short_ref[i]->frame_num); + for (i = 0; i < 16; i++) { + if (h->long_ref[i]) + dpb_add(h, &ppc->dpb[dpb_size++], h->long_ref[i], i); + } + + for (i = dpb_size; i < FF_ARRAY_ELEMS(ppc->dpb); i++) + ppc->dpb[i].PicIdx = -1; + + return 0; +} + +static int nvdec_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, + uint32_t size) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + void *tmp; + + tmp = av_fast_realloc(ctx->bitstream, &ctx->bitstream_allocated, + ctx->bitstream_len + size + 3); + if (!tmp) + return AVERROR(ENOMEM); + ctx->bitstream = tmp; + + tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated, + (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets)); + if (!tmp) + return AVERROR(ENOMEM); + ctx->slice_offsets = tmp; + + AV_WB24(ctx->bitstream + ctx->bitstream_len, 1); + memcpy(ctx->bitstream + ctx->bitstream_len + 3, buffer, size); + ctx->slice_offsets[ctx->nb_slices] = ctx->bitstream_len ; + ctx->bitstream_len += size + 3; + ctx->nb_slices++; + + return 0; +} + +static int nvdec_h264_decode_init(AVCodecContext *avctx) +{ + const H264Context *h = avctx->priv_data; + const SPS *sps = h->ps.sps; + return ff_nvdec_decode_init(avctx, sps->ref_frame_count + sps->num_reorder_frames); +} + +AVHWAccel ff_h264_nvdec_hwaccel = { + .name = "h264_nvdec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .pix_fmt = AV_PIX_FMT_CUDA, + .start_frame = nvdec_h264_start_frame, + .end_frame = ff_nvdec_end_frame, + .decode_slice = nvdec_h264_decode_slice, + .init = nvdec_h264_decode_init, + .uninit = ff_nvdec_decode_uninit, + .priv_data_size = sizeof(NVDECContext), +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 6c0d7a83285a5..e7323764ec7f6 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 1 +#define LIBAVCODEC_VERSION_MINOR 2 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From 27604549456282102eadbcb920b9a64775c683e1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 10 Nov 2017 21:06:58 -0300 Subject: [PATCH 0827/2557] avcodec/nvdec: fix copyright headers Fixes fate-source. Signed-off-by: James Almer --- libavcodec/nvdec.c | 10 +++++----- libavcodec/nvdec.h | 10 +++++----- libavcodec/nvdec_h264.c | 10 +++++----- libavcodec/nvdec_hevc.c | 10 +++++----- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index ab66b91a929dc..db338accfac42 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -3,21 +3,21 @@ * * Copyright (c) 2016 Anton Khirnov * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" diff --git a/libavcodec/nvdec.h b/libavcodec/nvdec.h index 75ed5d492d58d..18a64cd445d3d 100644 --- a/libavcodec/nvdec.h +++ b/libavcodec/nvdec.h @@ -3,21 +3,21 @@ * * Copyright (c) 2016 Anton Khirnov * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef AVCODEC_NVDEC_H diff --git a/libavcodec/nvdec_h264.c b/libavcodec/nvdec_h264.c index 4a6054089bb57..75dd4b2eb8f8c 100644 --- a/libavcodec/nvdec_h264.c +++ b/libavcodec/nvdec_h264.c @@ -3,21 +3,21 @@ * * Copyright (c) 2016 Anton Khirnov * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/libavcodec/nvdec_hevc.c b/libavcodec/nvdec_hevc.c index 3c40ab2beaf44..89c1be5f7c874 100644 --- a/libavcodec/nvdec_hevc.c +++ b/libavcodec/nvdec_hevc.c @@ -3,21 +3,21 @@ * * Copyright (c) 2017 Anton Khirnov * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include From cd4663dc80323ba64989d0c103d51ad3ee0e9c2f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 21 Jun 2012 16:01:52 +0200 Subject: [PATCH 0828/2557] smacker: add sanity check for length in smacker_decode_tree() Signed-off-by: Michael Niedermayer Bug-Id: 1098 Cc: libav-stable@libav.org Signed-off-by: Sean McGovern --- libavcodec/smacker.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index 0e057a1c2a882..7deccffa54972 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -43,7 +43,7 @@ #define SMKTREE_BITS 9 #define SMK_NODE 0x80000000 - +#define SMKTREE_DECODE_MAX_RECURSION 32 typedef struct SmackVContext { AVCodecContext *avctx; @@ -97,6 +97,11 @@ enum SmkBlockTypes { static int smacker_decode_tree(BitstreamContext *bc, HuffContext *hc, uint32_t prefix, int length) { + if (length > SMKTREE_DECODE_MAX_RECURSION) { + av_log(NULL, AV_LOG_ERROR, "Maximum tree recursion level exceeded.\n"); + return AVERROR_INVALIDDATA; + } + if (!bitstream_read_bit(bc)) { // Leaf if(hc->current >= 256){ av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); From 0ccddbad200c1d9439c5a836501917d515cddf76 Mon Sep 17 00:00:00 2001 From: Andreas Cadhalpun Date: Sat, 19 Nov 2016 14:21:11 +0100 Subject: [PATCH 0829/2557] smacker: limit recursion depth of smacker_decode_bigtree This fixes segmentation faults due to stack-overflow caused by too deep recursion. Reviewed-by: Michael Niedermayer Signed-off-by: Andreas Cadhalpun Signed-off-by: Sean McGovern --- libavcodec/smacker.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index 7deccffa54972..636e3b48e3133 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -44,6 +44,7 @@ #define SMKTREE_BITS 9 #define SMK_NODE 0x80000000 #define SMKTREE_DECODE_MAX_RECURSION 32 +#define SMKTREE_DECODE_BIG_MAX_RECURSION 500 typedef struct SmackVContext { AVCodecContext *avctx; @@ -133,8 +134,14 @@ static int smacker_decode_tree(BitstreamContext *bc, HuffContext *hc, * Decode header tree */ static int smacker_decode_bigtree(BitstreamContext *bc, HuffContext *hc, - DBCtx *ctx) + DBCtx *ctx, int length) { + // Larger length can cause segmentation faults due to too deep recursion. + if (length > SMKTREE_DECODE_BIG_MAX_RECURSION) { + av_log(NULL, AV_LOG_ERROR, "Maximum bigtree recursion level exceeded.\n"); + return AVERROR_INVALIDDATA; + } + if (hc->current + 1 >= hc->length) { av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); return AVERROR_INVALIDDATA; @@ -163,12 +170,12 @@ static int smacker_decode_bigtree(BitstreamContext *bc, HuffContext *hc, int r = 0, r_new, t; t = hc->current++; - r = smacker_decode_bigtree(bc, hc, ctx); + r = smacker_decode_bigtree(bc, hc, ctx, length + 1); if(r < 0) return r; hc->values[t] = SMK_NODE | r; r++; - r_new = smacker_decode_bigtree(bc, hc, ctx); + r_new = smacker_decode_bigtree(bc, hc, ctx, length + 1); if (r_new < 0) return r_new; return r + r_new; @@ -269,7 +276,7 @@ static int smacker_decode_header_tree(SmackVContext *smk, BitstreamContext *bc, goto error; } - if ((res = smacker_decode_bigtree(bc, &huff, &ctx)) < 0) + if ((res = smacker_decode_bigtree(bc, &huff, &ctx, 0)) < 0) err = res; bitstream_skip(bc, 1); if(ctx.last[0] == -1) ctx.last[0] = huff.current++; From 006546c635f05444cd7dd241f9e65bef346771bd Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 11 Nov 2017 01:39:47 -0300 Subject: [PATCH 0830/2557] avcodec/mpegaudiodecheader: remove dead code Signed-off-by: James Almer --- libavcodec/mpegaudiodecheader.c | 12 ------------ libavcodec/mpegaudiodecheader.h | 5 ----- 2 files changed, 17 deletions(-) diff --git a/libavcodec/mpegaudiodecheader.c b/libavcodec/mpegaudiodecheader.c index ae86b087f3ee2..6cc79f18b566e 100644 --- a/libavcodec/mpegaudiodecheader.c +++ b/libavcodec/mpegaudiodecheader.c @@ -152,15 +152,3 @@ int ff_mpa_decode_header(uint32_t head, int *sample_rate, int *channels, int *fr *bit_rate = s->bit_rate; return s->frame_size; } - -#if LIBAVCODEC_VERSION_MAJOR < 58 -int avpriv_mpa_decode_header2(uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bit_rate, enum AVCodecID *codec_id) -{ - return ff_mpa_decode_header(head, sample_rate, channels, frame_size, bit_rate, codec_id); -} - -int avpriv_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bit_rate) -{ - return ff_mpa_decode_header(head, sample_rate, channels, frame_size, bit_rate, &avctx->codec_id); -} -#endif diff --git a/libavcodec/mpegaudiodecheader.h b/libavcodec/mpegaudiodecheader.h index 952ba174406fc..1cb9216461ab0 100644 --- a/libavcodec/mpegaudiodecheader.h +++ b/libavcodec/mpegaudiodecheader.h @@ -57,11 +57,6 @@ int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header); int ff_mpa_decode_header(uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bitrate, enum AVCodecID *codec_id); -#if LIBAVCODEC_VERSION_MAJOR < 58 -int avpriv_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bitrate); -int avpriv_mpa_decode_header2(uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bitrate, enum AVCodecID *codec_id); -#endif - /* fast header check for resync */ static inline int ff_mpa_check_header(uint32_t header){ /* header */ From 1b6e52c68fd0ce24f0e5dbafe93146c7793c677b Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 11 Nov 2017 01:41:16 -0300 Subject: [PATCH 0831/2557] avcodec/dnxhddata: remove dead code Signed-off-by: James Almer --- libavcodec/dnxhddata.c | 7 ------- libavcodec/dnxhddata.h | 5 +---- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/libavcodec/dnxhddata.c b/libavcodec/dnxhddata.c index e995449d6342e..d7d3331b4f8ad 100644 --- a/libavcodec/dnxhddata.c +++ b/libavcodec/dnxhddata.c @@ -1100,13 +1100,6 @@ int avpriv_dnxhd_get_interlaced(int cid) return ff_dnxhd_cid_table[i].flags & DNXHD_INTERLACED ? 1 : 0; } -#if LIBAVCODEC_VERSION_MAJOR < 58 -uint64_t avpriv_dnxhd_parse_header_prefix(const uint8_t *buf) -{ - return ff_dnxhd_parse_header_prefix(buf); -} -#endif - static int dnxhd_find_hr_cid(AVCodecContext *avctx) { switch (avctx->profile) { diff --git a/libavcodec/dnxhddata.h b/libavcodec/dnxhddata.h index 6de2c0918ec7b..f80ce18f3c43d 100644 --- a/libavcodec/dnxhddata.h +++ b/libavcodec/dnxhddata.h @@ -105,8 +105,5 @@ static av_always_inline int ff_dnxhd_get_hr_frame_size(int cid, int w, int h) int avpriv_dnxhd_get_frame_size(int cid); int avpriv_dnxhd_get_interlaced(int cid); -#if LIBAVCODEC_VERSION_MAJOR < 58 -attribute_deprecated -uint64_t avpriv_dnxhd_parse_header_prefix(const uint8_t *buf); -#endif + #endif /* AVCODEC_DNXHDDATA_H */ From 5c22c90c1d5050f1206e46494b193320ac2397cb Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 5 Nov 2017 13:35:40 -0300 Subject: [PATCH 0832/2557] vp9_superframe_bsf: cache packets by creating new references instead of moving pointers Fixes invalid reads after free. Signed-off-by: James Almer --- libavcodec/vp9_superframe_bsf.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/libavcodec/vp9_superframe_bsf.c b/libavcodec/vp9_superframe_bsf.c index 3669216009d7a..ad66cb599bdef 100644 --- a/libavcodec/vp9_superframe_bsf.c +++ b/libavcodec/vp9_superframe_bsf.c @@ -148,8 +148,9 @@ static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out) goto done; } - s->cache[s->n_cache++] = in; - in = NULL; + res = av_packet_ref(s->cache[s->n_cache++], in); + if (res < 0) + goto done; if (invisible) { res = AVERROR(EAGAIN); goto done; @@ -165,7 +166,7 @@ static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out) goto done; for (n = 0; n < s->n_cache; n++) - av_packet_free(&s->cache[n]); + av_packet_unref(s->cache[n]); s->n_cache = 0; done: @@ -175,13 +176,28 @@ static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out) return res; } +static int vp9_superframe_init(AVBSFContext *ctx) +{ + VP9BSFContext *s = ctx->priv_data; + int n; + + // alloc cache packets + for (n = 0; n < MAX_CACHE; n++) { + s->cache[n] = av_packet_alloc(); + if (!s->cache[n]) + return AVERROR(ENOMEM); + } + + return 0; +} + static void vp9_superframe_close(AVBSFContext *ctx) { VP9BSFContext *s = ctx->priv_data; int n; // free cached data - for (n = 0; n < s->n_cache; n++) + for (n = 0; n < MAX_CACHE; n++) av_packet_free(&s->cache[n]); } @@ -193,6 +209,7 @@ const AVBitStreamFilter ff_vp9_superframe_bsf = { .name = "vp9_superframe", .priv_data_size = sizeof(VP9BSFContext), .filter = vp9_superframe_filter, + .init = vp9_superframe_init, .close = vp9_superframe_close, .codec_ids = codec_ids, }; From c84bc81158dab39598dcc72893ac4520dd95151e Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Fri, 10 Nov 2017 16:07:28 -0800 Subject: [PATCH 0833/2557] avformat/utils: preserve AV_PKT_FLAG_DISCARD in parse_packet Signed-off-by: Michael Niedermayer --- libavformat/utils.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/utils.c b/libavformat/utils.c index d45a6b55a7e11..3fd17dd771c02 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1458,6 +1458,7 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) out_pkt.pts = st->parser->pts; out_pkt.dts = st->parser->dts; out_pkt.pos = st->parser->pos; + out_pkt.flags |= pkt->flags & AV_PKT_FLAG_DISCARD; if (st->need_parsing == AVSTREAM_PARSE_FULL_RAW) out_pkt.pos = st->parser->frame_offset; From b197d83ca3f7316a4eb31bf60d9895835f7f2b4b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 31 Oct 2017 20:44:21 +0100 Subject: [PATCH 0834/2557] avformat/utils: Look at the first 3 frames if timestamps indicate frame reorder but decoder delay does not Fixes: Ticket6487 Signed-off-by: Michael Niedermayer --- libavformat/avformat.h | 1 + libavformat/utils.c | 16 ++++++++++++---- tests/ref/fate/mov-zombie | 4 ++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index c068aa8009c7e..3c6775d0f656d 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1026,6 +1026,7 @@ typedef struct AVStream { double (*duration_error)[2][MAX_STD_TIMEBASES]; int64_t codec_info_duration; int64_t codec_info_duration_fields; + int frame_delay_evidence; /** * 0 -> decoder has not been searched for yet. diff --git a/libavformat/utils.c b/libavformat/utils.c index 3fd17dd771c02..87887063be7c7 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -3628,6 +3628,7 @@ FF_ENABLE_DEPRECATION_WARNINGS /* check if one codec still needs to be handled */ for (i = 0; i < ic->nb_streams; i++) { int fps_analyze_framecount = 20; + int count; st = ic->streams[i]; if (!has_codec_parameters(st, NULL)) @@ -3644,14 +3645,18 @@ FF_ENABLE_DEPRECATION_WARNINGS if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) fps_analyze_framecount = 0; /* variable fps and no guess at the real fps */ + count = (ic->iformat->flags & AVFMT_NOTIMESTAMPS) ? + st->info->codec_info_duration_fields/2 : + st->info->duration_count; if (!(st->r_frame_rate.num && st->avg_frame_rate.num) && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - int count = (ic->iformat->flags & AVFMT_NOTIMESTAMPS) ? - st->info->codec_info_duration_fields/2 : - st->info->duration_count; if (count < fps_analyze_framecount) break; } + // Look at the first 3 frames if there is evidence of frame delay + // but the decoder delay is not set. + if (st->info->frame_delay_evidence && count < 2 && st->internal->avctx->has_b_frames == 0) + break; if (!st->internal->avctx->extradata && (!st->internal->extract_extradata.inited || st->internal->extract_extradata.bsf) && @@ -3801,10 +3806,13 @@ FF_ENABLE_DEPRECATION_WARNINGS st->info->codec_info_duration_fields += st->parser && st->need_parsing && avctx->ticks_per_frame ==2 ? st->parser->repeat_pict + 1 : 2; } } + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { #if FF_API_R_FRAME_RATE - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) ff_rfps_add_frame(ic, st, pkt->dts); #endif + if (pkt->dts != pkt->pts && pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE) + st->info->frame_delay_evidence = 1; + } if (!st->internal->avctx->extradata) { ret = extract_extradata(st, pkt); if (ret < 0) diff --git a/tests/ref/fate/mov-zombie b/tests/ref/fate/mov-zombie index e89abb1167682..fef2adc35436f 100644 --- a/tests/ref/fate/mov-zombie +++ b/tests/ref/fate/mov-zombie @@ -1,6 +1,6 @@ packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=-3004|dts_time=-0.033378|duration=3003|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=4133|pos=11309|flags=K_ -frame|media_type=video|stream_index=0|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=-3004|pkt_dts_time=-0.033378|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=11309|pkt_size=4133|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft packet|codec_type=video|stream_index=0|pts=5440|pts_time=0.060444|dts=-567|dts_time=-0.006300|duration=3003|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=1077|pos=15442|flags=__ +frame|media_type=video|stream_index=0|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=-567|pkt_dts_time=-0.006300|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=11309|pkt_size=4133|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft packet|codec_type=video|stream_index=0|pts=2437|pts_time=0.027078|dts=2436|dts_time=0.027067|duration=3003|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=355|pos=16519|flags=__ frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=2437|pkt_pts_time=0.027078|pkt_dts=2436|pkt_dts_time=0.027067|best_effort_timestamp=2437|best_effort_timestamp_time=0.027078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=16519|pkt_size=355|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=2|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft packet|codec_type=video|stream_index=0|pts=11446|pts_time=0.127178|dts=5439|dts_time=0.060433|duration=3003|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=1110|pos=16874|flags=__ @@ -129,5 +129,5 @@ packet|codec_type=video|stream_index=0|pts=188623|pts_time=2.095811|dts=188622|d frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=188623|pkt_pts_time=2.095811|pkt_dts=188622|pkt_dts_time=2.095800|best_effort_timestamp=188623|best_effort_timestamp_time=2.095811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=100846|pkt_size=974|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=64|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft packet|codec_type=video|stream_index=0|pts=197632|pts_time=2.195911|dts=191625|dts_time=2.129167|duration=3003|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=580|pos=101820|flags=__ frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=191626|pkt_pts_time=2.129178|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=191626|best_effort_timestamp_time=2.129178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=99180|pkt_size=1666|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=63|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft -stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_time_base=212521/12744000|codec_tag_string=avc1|codec_tag=0x31637661|width=160|height=240|coded_width=160|coded_height=240|has_b_frames=0|sample_aspect_ratio=2:1|display_aspect_ratio=4:3|pix_fmt=yuv420p|level=12|color_range=tv|color_space=smpte170m|color_transfer=bt709|color_primaries=smpte170m|chroma_location=topleft|field_order=unknown|timecode=N/A|refs=2|is_avc=true|nal_length_size=4|id=N/A|r_frame_rate=30000/1001|avg_frame_rate=6372000/212521|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=2125200|duration=23.613333|bit_rate=333874|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=708|nb_read_frames=65|nb_read_packets=66|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|tag:rotate=0|tag:creation_time=2008-05-12T20:59:27.000000Z|tag:language=eng|tag:handler_name=Apple Alias Data Handler|tag:encoder=H.264 +stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_time_base=212521/12744000|codec_tag_string=avc1|codec_tag=0x31637661|width=160|height=240|coded_width=160|coded_height=240|has_b_frames=1|sample_aspect_ratio=2:1|display_aspect_ratio=4:3|pix_fmt=yuv420p|level=12|color_range=tv|color_space=smpte170m|color_transfer=bt709|color_primaries=smpte170m|chroma_location=topleft|field_order=unknown|timecode=N/A|refs=2|is_avc=true|nal_length_size=4|id=N/A|r_frame_rate=30000/1001|avg_frame_rate=6372000/212521|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=2125200|duration=23.613333|bit_rate=333874|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=708|nb_read_frames=65|nb_read_packets=66|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|tag:rotate=0|tag:creation_time=2008-05-12T20:59:27.000000Z|tag:language=eng|tag:handler_name=Apple Alias Data Handler|tag:encoder=H.264 side_data|side_data_type=Display Matrix|displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|rotation=0 From 85af60df89ed92c60fb1641cd01c6095eba6576e Mon Sep 17 00:00:00 2001 From: Aleksandr Slobodeniuk Date: Fri, 10 Nov 2017 13:51:07 +0300 Subject: [PATCH 0835/2557] avcodec: fix wrong duration of packets (dvd, bluray) Signed-off-by: Michael Niedermayer --- libavcodec/utils.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 965b6c627647a..b3a578110bbf7 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -1808,13 +1808,13 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba, /* calc from frame_bytes, channels, and bits_per_coded_sample */ switch (id) { case AV_CODEC_ID_PCM_DVD: - if(bps<4) + if(bps<4 || frame_bytes<3) return 0; - return 2 * (frame_bytes / ((bps * 2 / 8) * ch)); + return 2 * ((frame_bytes - 3) / ((bps * 2 / 8) * ch)); case AV_CODEC_ID_PCM_BLURAY: - if(bps<4) + if(bps<4 || frame_bytes<4) return 0; - return frame_bytes / ((FFALIGN(ch, 2) * bps) / 8); + return (frame_bytes - 4) / ((FFALIGN(ch, 2) * bps) / 8); case AV_CODEC_ID_S302M: return 2 * (frame_bytes / ((bps + 4) / 4)) / ch; } From bc509617310d60216e1f1433a13bebe16d4d9d40 Mon Sep 17 00:00:00 2001 From: Sasi Inguva Date: Thu, 9 Nov 2017 16:11:22 -0800 Subject: [PATCH 0836/2557] lavf/mov.c: Parse upto 2 keyframes after the edit list end in mov_fix_index. Partially fixes t/6699. Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 32 ++++++++++++++-------- tests/fate/mov.mak | 4 +++ tests/ref/fate/mov-elst-ends-betn-b-and-i | 33 +++++++++++++++++++++++ 3 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 tests/ref/fate/mov-elst-ends-betn-b-and-i diff --git a/libavformat/mov.c b/libavformat/mov.c index 5fc597ee26de1..fd170baa57f9e 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3298,6 +3298,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) int packet_skip_samples = 0; MOVIndexRange *current_index_range; int i; + int found_keyframe_after_edit = 0; if (!msc->elst_data || msc->elst_count <= 0 || nb_old <= 0) { return; @@ -3393,6 +3394,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) // Iterate over index and arrange it according to edit list edit_list_start_encountered = 0; + found_keyframe_after_edit = 0; for (; current < e_old_end; current++, index++) { // check if frame outside edit list mark it for discard frame_duration = (current + 1 < e_old_end) ? @@ -3505,18 +3507,26 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) } // Break when found first key frame after edit entry completion - if (((curr_cts + frame_duration) >= (edit_list_duration + edit_list_media_time)) && + if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) && ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) { - - if (ctts_data_old && ctts_sample_old != 0) { - if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count, - &msc->ctts_allocated_size, - ctts_sample_old - edit_list_start_ctts_sample, - ctts_data_old[ctts_index_old].duration) == -1) { - av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n", - ctts_index_old, ctts_sample_old - edit_list_start_ctts_sample, - ctts_data_old[ctts_index_old].duration); - break; + if (ctts_data_old) { + // If we have CTTS and this is the the first keyframe after edit elist, + // wait for one more, because there might be trailing B-frames after this I-frame + // that do belong to the edit. + if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) { + found_keyframe_after_edit = 1; + continue; + } + if (ctts_sample_old != 0) { + if (add_ctts_entry(&msc->ctts_data, &msc->ctts_count, + &msc->ctts_allocated_size, + ctts_sample_old - edit_list_start_ctts_sample, + ctts_data_old[ctts_index_old].duration) == -1) { + av_log(mov->fc, AV_LOG_ERROR, "Cannot add CTTS entry %"PRId64" - {%"PRId64", %d}\n", + ctts_index_old, ctts_sample_old - edit_list_start_ctts_sample, + ctts_data_old[ctts_index_old].duration); + break; + } } } break; diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 01893a076756d..76f66ff4988b0 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -10,6 +10,7 @@ FATE_MOV = fate-mov-3elist \ fate-mov-gpmf-remux \ fate-mov-440hz-10ms \ fate-mov-ibi-elst-starts-b \ + fate-mov-elst-ends-betn-b-and-i \ FATE_MOV_FFPROBE = fate-mov-aac-2048-priming \ fate-mov-zombie \ @@ -42,6 +43,9 @@ fate-mov-1elist-ends-last-bframe: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/mov-1e # Makes sure that we handle timestamps of packets in case of multiple edit lists with one of them ending on a B-frame correctly. fate-mov-2elist-elist1-ends-bframe: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/mov-2elist-elist1-ends-bframe.mov +# Makes sure that if edit list ends on a B-frame but before the I-frame, then we output the B-frame but discard the I-frame. +fate-mov-elst-ends-betn-b-and-i: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/elst_ends_betn_b_and_i.mp4 + # Makes sure that we handle edit lists and start padding correctly. fate-mov-440hz-10ms: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/440hz-10ms.m4a diff --git a/tests/ref/fate/mov-elst-ends-betn-b-and-i b/tests/ref/fate/mov-elst-ends-betn-b-and-i new file mode 100644 index 0000000000000..d6f325bba29ad --- /dev/null +++ b/tests/ref/fate/mov-elst-ends-betn-b-and-i @@ -0,0 +1,33 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 115200, e10741e5457e9326d5e992e6c05c3e32 +0, 1, 1, 1, 115200, 7e20f8729b6b53dc11791927bf4a5aec +0, 2, 2, 1, 115200, 4e5dc2b806e394cd666c968f736fecd0 +0, 3, 3, 1, 115200, 7a3c7473d44c5f60c07655f6fc0c2ac3 +0, 4, 4, 1, 115200, 038254422a603a3270c09cdcd149707b +0, 5, 5, 1, 115200, 7553b6b4547cb23ef8f0392ed5a5d4b0 +0, 6, 6, 1, 115200, 6d017ede7f446124af7308667cb0dc41 +0, 7, 7, 1, 115200, 77752f0288ae64f857732b8e62e47457 +0, 8, 8, 1, 115200, d656833951af99330625f7c6de7685c4 +0, 9, 9, 1, 115200, 14338b833e431e566ac98da841600bfe +0, 10, 10, 1, 115200, 07ea95d1659f3c4424a470a546d0df6e +0, 11, 11, 1, 115200, fd05b8cc83072f813e89d394d1f6efc6 +0, 12, 12, 1, 115200, 750b82ca5c7e901545e7b1aa69692426 +0, 13, 13, 1, 115200, 7347679ab09bc936047368b8caebcaff +0, 14, 14, 1, 115200, 63a23fdd57ac8462b9ffbcb12ab717b3 +0, 15, 15, 1, 115200, 705257a1c99693db233e2a3ee027adcf +0, 16, 16, 1, 115200, df861a2ec7a4ef70e82b1c28025e5a48 +0, 17, 17, 1, 115200, 2a8b403c077b6b43aa71eaf7d1537713 +0, 18, 18, 1, 115200, 973b5cd3ce473e3970dfa96045553172 +0, 19, 19, 1, 115200, fc612c0afeae3b6576b5ee2f3f119832 +0, 20, 20, 1, 115200, 97074fe5a0b6e7e8470729654092e56c +0, 21, 21, 1, 115200, 8cf9337201065335b3aa4da21dc9b37a +0, 22, 22, 1, 115200, 93ff3589294cc0673af3daee1e7fe42a +0, 23, 23, 1, 115200, c0b6fd870a022f374f9d6c697e8e293d From 6a4d1c9063174234ca439244cf8f5f534afa1c28 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Fri, 10 Nov 2017 22:06:22 +0100 Subject: [PATCH 0837/2557] ffmpeg: use explicitly requested hwaccel only With there being two hwaccels that use the CUDA pix_fmt now, just relying on the pix_fmt to identify the selected hwaccel is not enough anymore. So this checks if the user explicitly selected a hwaccel, and only accepts that one. --- fftools/ffmpeg.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 0aff1d369d636..db391f7f7d327 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2782,11 +2782,12 @@ static void print_sdp(void) av_freep(&avc); } -static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt) +static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt, enum HWAccelID selected_hwaccel_id) { int i; for (i = 0; hwaccels[i].name; i++) - if (hwaccels[i].pix_fmt == pix_fmt) + if (hwaccels[i].pix_fmt == pix_fmt && + (!selected_hwaccel_id || selected_hwaccel_id == HWACCEL_AUTO || hwaccels[i].id == selected_hwaccel_id)) return &hwaccels[i]; return NULL; } @@ -2804,7 +2805,7 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) break; - hwaccel = get_hwaccel(*p); + hwaccel = get_hwaccel(*p, ist->hwaccel_id); if (!hwaccel || (ist->active_hwaccel_id && ist->active_hwaccel_id != hwaccel->id) || (ist->hwaccel_id != HWACCEL_AUTO && ist->hwaccel_id != hwaccel->id)) From 8dd73f68a6319d1784b33da9553671f1a0c197f9 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sat, 11 Nov 2017 12:59:44 +0100 Subject: [PATCH 0838/2557] avcodec/decode: always free private_ref There is no reason to keep this intact when decoding failed, specially as private_ref is supposed to always be NULL when a frame is returned to the user. --- libavcodec/decode.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 570799f6d7acb..7601d1608289a 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -613,7 +613,6 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) if (ret == AVERROR_EOF) avci->draining_done = 1; - /* free the per-frame decode data */ if (!ret) { /* the only case where decode data is not set should be decoders * that do not call ff_get_buffer() */ @@ -631,10 +630,11 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) } } } - - av_buffer_unref(&frame->private_ref); } + /* free the per-frame decode data */ + av_buffer_unref(&frame->private_ref); + return ret; } From 7e76e1ea80052ee95ef33d5341b9251b90766c9c Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sat, 11 Nov 2017 13:12:06 +0100 Subject: [PATCH 0839/2557] wmavoice: free frame before ff_get_buffer synth_superframe can be called twice per call to decode_packet. It is not fully clear if calling ff_get_buffer on the same frame twice is supported, so unref the frame first to be save. --- libavcodec/wmavoice.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/wmavoice.c b/libavcodec/wmavoice.c index 2ec4499981f52..3f86d0da3578b 100644 --- a/libavcodec/wmavoice.c +++ b/libavcodec/wmavoice.c @@ -1756,6 +1756,10 @@ static int synth_superframe(AVCodecContext *ctx, AVFrame *frame, stabilize_lsps(lsps[n], s->lsps); } + /* synth_superframe can run multiple times per packet + * free potential previous frame */ + av_frame_unref(frame); + /* get output buffer */ frame->nb_samples = MAX_SFRAMESIZE; if ((res = ff_get_buffer(ctx, frame, 0)) < 0) From e5233b15814d808997594ae2cb14ad1513ff2d0d Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 11 Nov 2017 17:12:08 -0300 Subject: [PATCH 0840/2557] doc/libav-merge: mention skipped outdev removal commit Signed-off-by: James Almer --- doc/libav-merge.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/libav-merge.txt b/doc/libav-merge.txt index 19183115adfc5..916e4befa1e99 100644 --- a/doc/libav-merge.txt +++ b/doc/libav-merge.txt @@ -102,6 +102,7 @@ Stuff that didn't reach the codebase: - f44ec22e0 lavc: use av_cpu_max_align() instead of hardcoding alignment requirements - 4de220d2e frame: allow align=0 (meaning automatic) for av_frame_get_buffer() - Support recovery from an already present HLS playlist (see 16cb06bb30) +- Remove all output devices (see 8e7e042d41 and https://ffmpeg.org/pipermail/ffmpeg-devel/2017-September/216904.html) Collateral damage that needs work locally: ------------------------------------------ From ac36d0c97a9d33c08c2378998e278947ad2adf7f Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 11 Nov 2017 17:17:30 -0300 Subject: [PATCH 0841/2557] doc/libav-merge: mention more skipped outdev removal commits Signed-off-by: James Almer --- doc/libav-merge.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/libav-merge.txt b/doc/libav-merge.txt index 916e4befa1e99..37839a97a7c21 100644 --- a/doc/libav-merge.txt +++ b/doc/libav-merge.txt @@ -102,7 +102,7 @@ Stuff that didn't reach the codebase: - f44ec22e0 lavc: use av_cpu_max_align() instead of hardcoding alignment requirements - 4de220d2e frame: allow align=0 (meaning automatic) for av_frame_get_buffer() - Support recovery from an already present HLS playlist (see 16cb06bb30) -- Remove all output devices (see 8e7e042d41 and https://ffmpeg.org/pipermail/ffmpeg-devel/2017-September/216904.html) +- Remove all output devices (see 8e7e042d41, 8d3db95f20, 6ce13070bd, d46cd24986 and https://ffmpeg.org/pipermail/ffmpeg-devel/2017-September/216904.html) Collateral damage that needs work locally: ------------------------------------------ From fb94e7b39a170d4b7fdf66e5d997525a76f12ab2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 11 Nov 2017 18:04:22 -0300 Subject: [PATCH 0842/2557] Revert "Merge commit '8e97a8c69162afce47abea96c8c0914f3550e212'" This reverts commit 1a4315f24d2c5857ebeb379fe39f0124746ee30a, reversing changes made to 869401cefc22e221edbf135bacaa1f21014fd001. At least one distro (Arch) ships gsm.h inside the gsm/ folder --- configure | 5 ++++- libavcodec/libgsmdec.c | 5 +++++ libavcodec/libgsmenc.c | 5 +++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/configure b/configure index b1674916a135b..e7b06d4305de0 100755 --- a/configure +++ b/configure @@ -1922,6 +1922,7 @@ HEADERS_LIST=" dxgidebug_h dxva_h ES2_gl_h + gsm_h io_h machine_ioctl_bt848_h machine_ioctl_meteor_h @@ -5921,7 +5922,9 @@ enabled libfreetype && require_pkg_config libfreetype freetype2 "ft2build. enabled libfribidi && require_pkg_config libfribidi fribidi fribidi.h fribidi_version_info enabled libgme && { check_pkg_config libgme libgme gme/gme.h gme_new_emu || require libgme gme/gme.h gme_new_emu -lgme -lstdc++; } -enabled libgsm && require libgsm gsm.h gsm_create -lgsm +enabled libgsm && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do + check_lib libgsm "${gsm_hdr}" gsm_create -lgsm && break; + done || die "ERROR: libgsm not found"; } enabled libilbc && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -lilbc $pthreads_extralibs enabled libkvazaar && require_pkg_config libkvazaar "kvazaar >= 0.8.1" kvazaar.h kvz_api_get # While it may appear that require is being used as a pkg-config diff --git a/libavcodec/libgsmdec.c b/libavcodec/libgsmdec.c index 85bb022b97e4d..a503215f679b0 100644 --- a/libavcodec/libgsmdec.c +++ b/libavcodec/libgsmdec.c @@ -27,7 +27,12 @@ // The idiosyncrasies of GSM-in-WAV are explained at http://kbs.cs.tu-berlin.de/~jutta/toast.html +#include "config.h" +#if HAVE_GSM_H #include +#else +#include +#endif #include "libavutil/channel_layout.h" #include "libavutil/common.h" diff --git a/libavcodec/libgsmenc.c b/libavcodec/libgsmenc.c index b60b23b31dc04..e25db95181009 100644 --- a/libavcodec/libgsmenc.c +++ b/libavcodec/libgsmenc.c @@ -27,7 +27,12 @@ // The idiosyncrasies of GSM-in-WAV are explained at http://kbs.cs.tu-berlin.de/~jutta/toast.html +#include "config.h" +#if HAVE_GSM_H #include +#else +#include +#endif #include "libavutil/common.h" From 7546964f96168cd6ac819ef4c3212ee586619f1a Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 28 Oct 2017 19:53:38 +0200 Subject: [PATCH 0843/2557] nvdec: add frames_params support --- libavcodec/nvdec.c | 74 ++++++++++++++++++++++++----------------- libavcodec/nvdec.h | 5 ++- libavcodec/nvdec_h264.c | 8 +++-- libavcodec/nvdec_hevc.c | 8 +++-- 4 files changed, 57 insertions(+), 38 deletions(-) diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index db338accfac42..e4babad43eb7e 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -185,7 +185,7 @@ int ff_nvdec_decode_uninit(AVCodecContext *avctx) return 0; } -int ff_nvdec_decode_init(AVCodecContext *avctx, unsigned int dpb_size) +int ff_nvdec_decode_init(AVCodecContext *avctx) { NVDECContext *ctx = avctx->internal->hwaccel_priv_data; @@ -214,37 +214,12 @@ int ff_nvdec_decode_init(AVCodecContext *avctx, unsigned int dpb_size) return AVERROR(ENOSYS); } - if (avctx->thread_type & FF_THREAD_FRAME) - dpb_size += avctx->thread_count; - if (!avctx->hw_frames_ctx) { - AVHWFramesContext *frames_ctx; - - if (!avctx->hw_device_ctx) { - av_log(avctx, AV_LOG_ERROR, "A hardware device or frames context " - "is required for CUVID decoding.\n"); - return AVERROR(EINVAL); - } - - avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); - if (!avctx->hw_frames_ctx) - return AVERROR(ENOMEM); - frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - - frames_ctx->format = AV_PIX_FMT_CUDA; - frames_ctx->width = avctx->coded_width; - frames_ctx->height = avctx->coded_height; - frames_ctx->sw_format = AV_PIX_FMT_NV12; - frames_ctx->sw_format = sw_desc->comp[0].depth > 8 ? - AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; - frames_ctx->initial_pool_size = dpb_size; - - ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Error initializing internal frames context\n"); + ret = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_CUDA); + if (ret < 0) return ret; - } } + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; params.ulWidth = avctx->coded_width; @@ -256,7 +231,7 @@ int ff_nvdec_decode_init(AVCodecContext *avctx, unsigned int dpb_size) cudaVideoSurfaceFormat_P016 : cudaVideoSurfaceFormat_NV12; params.CodecType = cuvid_codec_type; params.ChromaFormat = cuvid_chroma_format; - params.ulNumDecodeSurfaces = dpb_size; + params.ulNumDecodeSurfaces = frames_ctx->initial_pool_size; params.ulNumOutputSurfaces = 1; ret = nvdec_decoder_create(&ctx->decoder_ref, frames_ctx->device_ref, ¶ms, avctx); @@ -268,7 +243,7 @@ int ff_nvdec_decode_init(AVCodecContext *avctx, unsigned int dpb_size) ret = AVERROR(ENOMEM); goto fail; } - pool->dpb_size = dpb_size; + pool->dpb_size = frames_ctx->initial_pool_size; ctx->decoder_pool = av_buffer_pool_init2(sizeof(int), pool, nvdec_decoder_frame_alloc, av_free); @@ -430,3 +405,40 @@ int ff_nvdec_end_frame(AVCodecContext *avctx) return ret; } + +int ff_nvdec_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx, + int dpb_size) +{ + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data; + const AVPixFmtDescriptor *sw_desc; + int cuvid_codec_type, cuvid_chroma_format; + + sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); + if (!sw_desc) + return AVERROR_BUG; + + cuvid_codec_type = map_avcodec_id(avctx->codec_id); + if (cuvid_codec_type < 0) { + av_log(avctx, AV_LOG_ERROR, "Unsupported codec ID\n"); + return AVERROR_BUG; + } + + cuvid_chroma_format = map_chroma_format(avctx->sw_pix_fmt); + if (cuvid_chroma_format < 0) { + av_log(avctx, AV_LOG_VERBOSE, "Unsupported chroma format\n"); + return AVERROR(EINVAL); + } + + if (avctx->thread_type & FF_THREAD_FRAME) + dpb_size += avctx->thread_count; + + frames_ctx->format = AV_PIX_FMT_CUDA; + frames_ctx->width = avctx->coded_width; + frames_ctx->height = avctx->coded_height; + frames_ctx->sw_format = sw_desc->comp[0].depth > 8 ? + AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; + frames_ctx->initial_pool_size = dpb_size; + + return 0; +} diff --git a/libavcodec/nvdec.h b/libavcodec/nvdec.h index 18a64cd445d3d..14d29ee94bae1 100644 --- a/libavcodec/nvdec.h +++ b/libavcodec/nvdec.h @@ -54,9 +54,12 @@ typedef struct NVDECContext { unsigned int slice_offsets_allocated; } NVDECContext; -int ff_nvdec_decode_init(AVCodecContext *avctx, unsigned int dpb_size); +int ff_nvdec_decode_init(AVCodecContext *avctx); int ff_nvdec_decode_uninit(AVCodecContext *avctx); int ff_nvdec_start_frame(AVCodecContext *avctx, AVFrame *frame); int ff_nvdec_end_frame(AVCodecContext *avctx); +int ff_nvdec_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx, + int dpb_size); #endif /* AVCODEC_NVDEC_H */ diff --git a/libavcodec/nvdec_h264.c b/libavcodec/nvdec_h264.c index 75dd4b2eb8f8c..b0e756c7344b2 100644 --- a/libavcodec/nvdec_h264.c +++ b/libavcodec/nvdec_h264.c @@ -155,11 +155,12 @@ static int nvdec_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, return 0; } -static int nvdec_h264_decode_init(AVCodecContext *avctx) +static int nvdec_h264_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) { const H264Context *h = avctx->priv_data; const SPS *sps = h->ps.sps; - return ff_nvdec_decode_init(avctx, sps->ref_frame_count + sps->num_reorder_frames); + return ff_nvdec_frame_params(avctx, hw_frames_ctx, sps->ref_frame_count + sps->num_reorder_frames); } AVHWAccel ff_h264_nvdec_hwaccel = { @@ -170,7 +171,8 @@ AVHWAccel ff_h264_nvdec_hwaccel = { .start_frame = nvdec_h264_start_frame, .end_frame = ff_nvdec_end_frame, .decode_slice = nvdec_h264_decode_slice, - .init = nvdec_h264_decode_init, + .frame_params = nvdec_h264_frame_params, + .init = ff_nvdec_decode_init, .uninit = ff_nvdec_decode_uninit, .priv_data_size = sizeof(NVDECContext), }; diff --git a/libavcodec/nvdec_hevc.c b/libavcodec/nvdec_hevc.c index 89c1be5f7c874..f02a7a15feb96 100644 --- a/libavcodec/nvdec_hevc.c +++ b/libavcodec/nvdec_hevc.c @@ -258,11 +258,12 @@ static int nvdec_hevc_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, return 0; } -static int nvdec_hevc_decode_init(AVCodecContext *avctx) +static int nvdec_hevc_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) { const HEVCContext *s = avctx->priv_data; const HEVCSPS *sps = s->ps.sps; - return ff_nvdec_decode_init(avctx, sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering + 1); + return ff_nvdec_frame_params(avctx, hw_frames_ctx, sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering + 1); } AVHWAccel ff_hevc_nvdec_hwaccel = { @@ -273,7 +274,8 @@ AVHWAccel ff_hevc_nvdec_hwaccel = { .start_frame = nvdec_hevc_start_frame, .end_frame = ff_nvdec_end_frame, .decode_slice = nvdec_hevc_decode_slice, - .init = nvdec_hevc_decode_init, + .frame_params = nvdec_hevc_frame_params, + .init = ff_nvdec_decode_init, .uninit = ff_nvdec_decode_uninit, .priv_data_size = sizeof(NVDECContext), }; From 91df92e442844fbde69396d169bb352091cbb66f Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 11 Nov 2017 22:25:12 -0300 Subject: [PATCH 0844/2557] avcodec/Makefile: build libxvid_rc.o only if libxvid_encoder is enabled Signed-off-by: James Almer --- libavcodec/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 7ac4e13a06364..8c5dfd6319bb1 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -96,7 +96,6 @@ OBJS-$(CONFIG_INTRAX8) += intrax8.o intrax8dsp.o msmpeg4data.o OBJS-$(CONFIG_IVIDSP) += ivi_dsp.o OBJS-$(CONFIG_JNI) += ffjni.o jni.o OBJS-$(CONFIG_JPEGTABLES) += jpegtables.o -OBJS-$(CONFIG_LIBXVID) += libxvid_rc.o OBJS-$(CONFIG_LLAUDDSP) += lossless_audiodsp.o OBJS-$(CONFIG_LLVIDDSP) += lossless_videodsp.o OBJS-$(CONFIG_LLVIDENCDSP) += lossless_videoencdsp.o @@ -959,7 +958,7 @@ OBJS-$(CONFIG_LIBX262_ENCODER) += libx264.o OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o -OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o +OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o libxvid_rc.o OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o ass.o # parsers From b998a56b0ac9744537837c668e32487d060be3c0 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 12 Nov 2017 04:29:06 +0100 Subject: [PATCH 0845/2557] lavc/jpeg2000dec: Fix used variables reading palette. Affected files with palette and colour-depth < 8. --- libavcodec/jpeg2000dec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 9a5e64e85408a..62b9009a82c15 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -2039,13 +2039,13 @@ static int jp2_find_codestream(Jpeg2000DecoderContext *s) } if (colour_depth[1] <= 8) { g = bytestream2_get_byteu(&s->g) << 8 - colour_depth[1]; - r |= r >> colour_depth[1]; + g |= g >> colour_depth[1]; } else { g = bytestream2_get_be16u(&s->g) >> colour_depth[1] - 8; } if (colour_depth[2] <= 8) { b = bytestream2_get_byteu(&s->g) << 8 - colour_depth[2]; - r |= r >> colour_depth[2]; + b |= b >> colour_depth[2]; } else { b = bytestream2_get_be16u(&s->g) >> colour_depth[2] - 8; } From 2afeb3f8ab0041d470d905102d23080c88d67d92 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 12 Nov 2017 11:19:19 +0100 Subject: [PATCH 0846/2557] avfilter/vf_maskedclamp: ignore SAR from all inputs Signed-off-by: Paul B Mahol --- libavfilter/vf_maskedclamp.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/libavfilter/vf_maskedclamp.c b/libavfilter/vf_maskedclamp.c index 67a979f8c06ae..9812e08533a7c 100644 --- a/libavfilter/vf_maskedclamp.c +++ b/libavfilter/vf_maskedclamp.c @@ -235,27 +235,15 @@ static int config_output(AVFilterLink *outlink) av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n"); return AVERROR(EINVAL); } - if (base->w != dark->w || - base->h != dark->h || - base->sample_aspect_ratio.num != dark->sample_aspect_ratio.num || - base->sample_aspect_ratio.den != dark->sample_aspect_ratio.den || - base->w != bright->w || - base->h != bright->h || - base->sample_aspect_ratio.num != bright->sample_aspect_ratio.num || - base->sample_aspect_ratio.den != bright->sample_aspect_ratio.den) { + if (base->w != dark->w || base->h != dark->h || + base->w != bright->w || base->h != bright->h) { av_log(ctx, AV_LOG_ERROR, "First input link %s parameters " - "(size %dx%d, SAR %d:%d) do not match the corresponding " - "second input link %s parameters (%dx%d, SAR %d:%d) " - "and/or third input link %s parameters (%dx%d, SAR %d:%d)\n", + "(size %dx%d) do not match the corresponding " + "second input link %s parameters (%dx%d) " + "and/or third input link %s parameters (size %dx%d)\n", ctx->input_pads[0].name, base->w, base->h, - base->sample_aspect_ratio.num, - base->sample_aspect_ratio.den, ctx->input_pads[1].name, dark->w, dark->h, - dark->sample_aspect_ratio.num, - dark->sample_aspect_ratio.den, - ctx->input_pads[2].name, bright->w, bright->h, - bright->sample_aspect_ratio.num, - bright->sample_aspect_ratio.den); + ctx->input_pads[2].name, bright->w, bright->h); return AVERROR(EINVAL); } From 19d2108a984f7009e74eeddf883e6bad758a98e6 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 12 Nov 2017 11:35:32 +0100 Subject: [PATCH 0847/2557] avfilter/vf_hysteresis: ignore SAR from all inputs Signed-off-by: Paul B Mahol --- libavfilter/vf_hysteresis.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/libavfilter/vf_hysteresis.c b/libavfilter/vf_hysteresis.c index a788e1b9ee64b..edca40fa212cb 100644 --- a/libavfilter/vf_hysteresis.c +++ b/libavfilter/vf_hysteresis.c @@ -301,20 +301,13 @@ static int config_output(AVFilterLink *outlink) av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n"); return AVERROR(EINVAL); } - if (base->w != alt->w || - base->h != alt->h || - base->sample_aspect_ratio.num != alt->sample_aspect_ratio.num || - base->sample_aspect_ratio.den != alt->sample_aspect_ratio.den) { + if (base->w != alt->w || base->h != alt->h) { av_log(ctx, AV_LOG_ERROR, "First input link %s parameters " - "(size %dx%d, SAR %d:%d) do not match the corresponding " - "second input link %s parameters (%dx%d, SAR %d:%d)\n", + "(size %dx%d) do not match the corresponding " + "second input link %s parameters (size %dx%d)\n", ctx->input_pads[0].name, base->w, base->h, - base->sample_aspect_ratio.num, - base->sample_aspect_ratio.den, ctx->input_pads[1].name, - alt->w, alt->h, - alt->sample_aspect_ratio.num, - alt->sample_aspect_ratio.den); + alt->w, alt->h); return AVERROR(EINVAL); } From 79aa9d8aeee0e164a1af2087f481f69d73969c6b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 12 Nov 2017 11:39:16 +0100 Subject: [PATCH 0848/2557] avfilter/vf_blend: ignore SAR from all inputs Signed-off-by: Paul B Mahol --- libavfilter/vf_blend.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c index 054c0d55d099d..70c37c75da76d 100644 --- a/libavfilter/vf_blend.c +++ b/libavfilter/vf_blend.c @@ -524,19 +524,12 @@ static int config_output(AVFilterLink *outlink) av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n"); return AVERROR(EINVAL); } - if (toplink->w != bottomlink->w || - toplink->h != bottomlink->h || - toplink->sample_aspect_ratio.num != bottomlink->sample_aspect_ratio.num || - toplink->sample_aspect_ratio.den != bottomlink->sample_aspect_ratio.den) { + if (toplink->w != bottomlink->w || toplink->h != bottomlink->h) { av_log(ctx, AV_LOG_ERROR, "First input link %s parameters " - "(size %dx%d, SAR %d:%d) do not match the corresponding " - "second input link %s parameters (%dx%d, SAR %d:%d)\n", + "(size %dx%d) do not match the corresponding " + "second input link %s parameters (size %dx%d)\n", ctx->input_pads[TOP].name, toplink->w, toplink->h, - toplink->sample_aspect_ratio.num, - toplink->sample_aspect_ratio.den, - ctx->input_pads[BOTTOM].name, bottomlink->w, bottomlink->h, - bottomlink->sample_aspect_ratio.num, - bottomlink->sample_aspect_ratio.den); + ctx->input_pads[BOTTOM].name, bottomlink->w, bottomlink->h); return AVERROR(EINVAL); } } From a28e70beab05a877ed277f5d93ba515b5874ffd7 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 12 Nov 2017 11:40:49 +0100 Subject: [PATCH 0849/2557] avfilter/vf_lut2: ignore SAR from all inputs Signed-off-by: Paul B Mahol --- libavfilter/vf_lut2.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/libavfilter/vf_lut2.c b/libavfilter/vf_lut2.c index 585d121ca3539..1385cba9b129d 100644 --- a/libavfilter/vf_lut2.c +++ b/libavfilter/vf_lut2.c @@ -304,20 +304,13 @@ static int lut2_config_output(AVFilterLink *outlink) av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n"); return AVERROR(EINVAL); } - if (srcx->w != srcy->w || - srcx->h != srcy->h || - srcx->sample_aspect_ratio.num != srcy->sample_aspect_ratio.num || - srcx->sample_aspect_ratio.den != srcy->sample_aspect_ratio.den) { + if (srcx->w != srcy->w || srcx->h != srcy->h) { av_log(ctx, AV_LOG_ERROR, "First input link %s parameters " - "(size %dx%d, SAR %d:%d) do not match the corresponding " - "second input link %s parameters (%dx%d, SAR %d:%d)\n", + "(size %dx%d) do not match the corresponding " + "second input link %s parameters (size %dx%d)\n", ctx->input_pads[0].name, srcx->w, srcx->h, - srcx->sample_aspect_ratio.num, - srcx->sample_aspect_ratio.den, ctx->input_pads[1].name, - srcy->w, srcy->h, - srcy->sample_aspect_ratio.num, - srcy->sample_aspect_ratio.den); + srcy->w, srcy->h); return AVERROR(EINVAL); } From 789731affa81f7c7c11ae96e9ad89e6dfbef9ad3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 12 Nov 2017 11:43:06 +0100 Subject: [PATCH 0850/2557] avfilter/vf_maskedmerge: ignore SAR from all inputs Signed-off-by: Paul B Mahol --- libavfilter/vf_maskedmerge.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/libavfilter/vf_maskedmerge.c b/libavfilter/vf_maskedmerge.c index d31b92659e2f4..86559abdacf19 100644 --- a/libavfilter/vf_maskedmerge.c +++ b/libavfilter/vf_maskedmerge.c @@ -199,27 +199,15 @@ static int config_output(AVFilterLink *outlink) av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n"); return AVERROR(EINVAL); } - if (base->w != overlay->w || - base->h != overlay->h || - base->sample_aspect_ratio.num != overlay->sample_aspect_ratio.num || - base->sample_aspect_ratio.den != overlay->sample_aspect_ratio.den || - base->w != mask->w || - base->h != mask->h || - base->sample_aspect_ratio.num != mask->sample_aspect_ratio.num || - base->sample_aspect_ratio.den != mask->sample_aspect_ratio.den) { + if (base->w != overlay->w || base->h != overlay->h || + base->w != mask->w || base->h != mask->h) { av_log(ctx, AV_LOG_ERROR, "First input link %s parameters " - "(size %dx%d, SAR %d:%d) do not match the corresponding " - "second input link %s parameters (%dx%d, SAR %d:%d) " - "and/or third input link %s parameters (%dx%d, SAR %d:%d)\n", + "(size %dx%d) do not match the corresponding " + "second input link %s parameters (size %dx%d) " + "and/or third input link %s parameters (size %dx%d)\n", ctx->input_pads[0].name, base->w, base->h, - base->sample_aspect_ratio.num, - base->sample_aspect_ratio.den, ctx->input_pads[1].name, overlay->w, overlay->h, - overlay->sample_aspect_ratio.num, - overlay->sample_aspect_ratio.den, - ctx->input_pads[2].name, mask->w, mask->h, - mask->sample_aspect_ratio.num, - mask->sample_aspect_ratio.den); + ctx->input_pads[2].name, mask->w, mask->h); return AVERROR(EINVAL); } From 5f1bb258aba5bac5bb38483ec208e6e17a885ff7 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 12 Nov 2017 11:48:52 +0100 Subject: [PATCH 0851/2557] avfilter/vf_hysteresis: allow using framesync options Signed-off-by: Paul B Mahol --- libavfilter/vf_hysteresis.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_hysteresis.c b/libavfilter/vf_hysteresis.c index edca40fa212cb..551b33f33258b 100644 --- a/libavfilter/vf_hysteresis.c +++ b/libavfilter/vf_hysteresis.c @@ -33,6 +33,7 @@ typedef struct HysteresisContext { const AVClass *class; + FFFrameSync fs; int planes; int threshold; @@ -40,7 +41,6 @@ typedef struct HysteresisContext { int width[4], height[4]; int nb_planes; int depth; - FFFrameSync fs; uint8_t *map; uint32_t *xy; @@ -58,8 +58,6 @@ static const AVOption hysteresis_options[] = { { NULL } }; -AVFILTER_DEFINE_CLASS(hysteresis); - static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { @@ -350,6 +348,8 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->xy); } +FRAMESYNC_DEFINE_CLASS(hysteresis, HysteresisContext, fs); + static const AVFilterPad hysteresis_inputs[] = { { .name = "base", @@ -375,6 +375,7 @@ static const AVFilterPad hysteresis_outputs[] = { AVFilter ff_vf_hysteresis = { .name = "hysteresis", .description = NULL_IF_CONFIG_SMALL("Grow first stream into second stream by connecting components."), + .preinit = hysteresis_framesync_preinit, .priv_size = sizeof(HysteresisContext), .uninit = uninit, .query_formats = query_formats, From 56960ed9c3a632e155a12312089ce3bf15df71e9 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Sun, 12 Nov 2017 22:19:28 +0800 Subject: [PATCH 0852/2557] Revert "lavf/dashdec: Fix several memleaks." This reverts commit e7fe5e511aaeb3b8d949706b7f8620042cdfbd6c. --- libavformat/dashdec.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 0e3afd2a3b913..0f5f91c6b5b80 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -328,17 +328,17 @@ static void free_representation(struct representation *pls) } av_freep(&pls->url_template); - av_freep(&pls); + av_freep(pls); } -static void set_httpheader_options(DASHContext *c, AVDictionary **opts) +static void set_httpheader_options(DASHContext *c, AVDictionary *opts) { // broker prior HTTP options that should be consistent across requests - av_dict_set(opts, "user-agent", c->user_agent, 0); - av_dict_set(opts, "cookies", c->cookies, 0); - av_dict_set(opts, "headers", c->headers, 0); + av_dict_set(&opts, "user-agent", c->user_agent, 0); + av_dict_set(&opts, "cookies", c->cookies, 0); + av_dict_set(&opts, "headers", c->headers, 0); if (c->is_live) { - av_dict_set(opts, "seekable", "0", 0); + av_dict_set(&opts, "seekable", "0", 0); } } static void update_options(char **dest, const char *name, void *src) @@ -885,7 +885,7 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) if (!in) { close_in = 1; - set_httpheader_options(c, &opts); + set_httpheader_options(c, opts); ret = avio_open2(&in, url, AVIO_FLAG_READ, c->interrupt_callback, &opts); av_dict_free(&opts); if (ret < 0) @@ -1301,7 +1301,7 @@ static int open_input(DASHContext *c, struct representation *pls, struct fragmen char url[MAX_URL_SIZE]; int ret; - set_httpheader_options(c, &opts); + set_httpheader_options(c, opts); if (seg->size >= 0) { /* try to restrict the HTTP request to the part we want * (if this is in fact a HTTP request) */ @@ -1465,12 +1465,8 @@ static int save_avio_options(AVFormatContext *s) if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) { if (buf[0] != '\0') { ret = av_dict_set(&c->avio_opts, *opt, buf, AV_DICT_DONT_STRDUP_VAL); - if (ret < 0) { - av_freep(&buf); + if (ret < 0) return ret; - } - } else { - av_freep(&buf); } } opt++; From 52b9575d4a900afd0629331f19af78024f43b6bc Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 12 Nov 2017 22:20:22 +0800 Subject: [PATCH 0853/2557] lavf/dashdec: Fix several memleaks. --- libavformat/dashdec.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 0f5f91c6b5b80..0e3afd2a3b913 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -328,17 +328,17 @@ static void free_representation(struct representation *pls) } av_freep(&pls->url_template); - av_freep(pls); + av_freep(&pls); } -static void set_httpheader_options(DASHContext *c, AVDictionary *opts) +static void set_httpheader_options(DASHContext *c, AVDictionary **opts) { // broker prior HTTP options that should be consistent across requests - av_dict_set(&opts, "user-agent", c->user_agent, 0); - av_dict_set(&opts, "cookies", c->cookies, 0); - av_dict_set(&opts, "headers", c->headers, 0); + av_dict_set(opts, "user-agent", c->user_agent, 0); + av_dict_set(opts, "cookies", c->cookies, 0); + av_dict_set(opts, "headers", c->headers, 0); if (c->is_live) { - av_dict_set(&opts, "seekable", "0", 0); + av_dict_set(opts, "seekable", "0", 0); } } static void update_options(char **dest, const char *name, void *src) @@ -885,7 +885,7 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) if (!in) { close_in = 1; - set_httpheader_options(c, opts); + set_httpheader_options(c, &opts); ret = avio_open2(&in, url, AVIO_FLAG_READ, c->interrupt_callback, &opts); av_dict_free(&opts); if (ret < 0) @@ -1301,7 +1301,7 @@ static int open_input(DASHContext *c, struct representation *pls, struct fragmen char url[MAX_URL_SIZE]; int ret; - set_httpheader_options(c, opts); + set_httpheader_options(c, &opts); if (seg->size >= 0) { /* try to restrict the HTTP request to the part we want * (if this is in fact a HTTP request) */ @@ -1465,8 +1465,12 @@ static int save_avio_options(AVFormatContext *s) if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) { if (buf[0] != '\0') { ret = av_dict_set(&c->avio_opts, *opt, buf, AV_DICT_DONT_STRDUP_VAL); - if (ret < 0) + if (ret < 0) { + av_freep(&buf); return ret; + } + } else { + av_freep(&buf); } } opt++; From 65c4f4d1069b1ffbfb6484e133b827556c80fe65 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sat, 11 Nov 2017 14:48:37 +0100 Subject: [PATCH 0854/2557] MAINTAINERS: update for cuvid/nvdec changes --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index c70d949a710a4..4df6c6533d857 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -158,7 +158,7 @@ Codecs: cpia.c Stephan Hilb crystalhd.c Philip Langdale cscd.c Reimar Doeffinger - cuvid.c Timo Rothenpieler + cuviddec.c Timo Rothenpieler dca* foo86 dirac* Rostislav Pehlivanov dnxhd* Baptiste Coudurier @@ -213,7 +213,7 @@ Codecs: msrle.c Mike Melanson msvideo1.c Mike Melanson nuv.c Reimar Doeffinger - nvenc* Timo Rothenpieler + nvdec*, nvenc* Timo Rothenpieler opus* Rostislav Pehlivanov paf.* Paul B Mahol pcx.c Ivo van Poorten From 3e0e1634585b1a26b7d753aa42c7f350636927ae Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sun, 12 Nov 2017 15:15:55 +0100 Subject: [PATCH 0855/2557] avcodec/nvdec: don't add thread buffer twice This is already added to the initial pool size in ff_decode_get_hw_frames_ctx, so adding it here again increases the amount of surfaces needlessly. --- libavcodec/nvdec.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index e4babad43eb7e..58ebeeb9c1994 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -430,9 +430,6 @@ int ff_nvdec_frame_params(AVCodecContext *avctx, return AVERROR(EINVAL); } - if (avctx->thread_type & FF_THREAD_FRAME) - dpb_size += avctx->thread_count; - frames_ctx->format = AV_PIX_FMT_CUDA; frames_ctx->width = avctx->coded_width; frames_ctx->height = avctx->coded_height; From c60bc02bf4bc4f6f57fd0fd4c5b2e63253623185 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sat, 11 Nov 2017 16:08:53 +0100 Subject: [PATCH 0856/2557] avcodec/nvdec: check hardware capabilities --- libavcodec/nvdec.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index 58ebeeb9c1994..628789734385e 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -74,6 +74,56 @@ static int map_chroma_format(enum AVPixelFormat pix_fmt) return -1; } +static int nvdec_test_capabilities(NVDECDecoder *decoder, + CUVIDDECODECREATEINFO *params, void *logctx) +{ + CUresult err; + CUVIDDECODECAPS caps = { 0 }; + + caps.eCodecType = params->CodecType; + caps.eChromaFormat = params->ChromaFormat; + caps.nBitDepthMinus8 = params->bitDepthMinus8; + + err = decoder->cvdl->cuvidGetDecoderCaps(&caps); + if (err != CUDA_SUCCESS) { + av_log(logctx, AV_LOG_ERROR, "Failed querying decoder capabilities\n"); + return AVERROR_UNKNOWN; + } + + av_log(logctx, AV_LOG_VERBOSE, "NVDEC capabilities:\n"); + av_log(logctx, AV_LOG_VERBOSE, "format supported: %s, max_mb_count: %d\n", + caps.bIsSupported ? "yes" : "no", caps.nMaxMBCount); + av_log(logctx, AV_LOG_VERBOSE, "min_width: %d, max_width: %d\n", + caps.nMinWidth, caps.nMaxWidth); + av_log(logctx, AV_LOG_VERBOSE, "min_height: %d, max_height: %d\n", + caps.nMinHeight, caps.nMaxHeight); + + if (!caps.bIsSupported) { + av_log(logctx, AV_LOG_ERROR, "Hardware is lacking required capabilities\n"); + return AVERROR(EINVAL); + } + + if (params->ulWidth > caps.nMaxWidth || params->ulWidth < caps.nMinWidth) { + av_log(logctx, AV_LOG_ERROR, "Video width %d not within range from %d to %d\n", + (int)params->ulWidth, caps.nMinWidth, caps.nMaxWidth); + return AVERROR(EINVAL); + } + + if (params->ulHeight > caps.nMaxHeight || params->ulHeight < caps.nMinHeight) { + av_log(logctx, AV_LOG_ERROR, "Video height %d not within range from %d to %d\n", + (int)params->ulHeight, caps.nMinHeight, caps.nMaxHeight); + return AVERROR(EINVAL); + } + + if ((params->ulWidth * params->ulHeight) / 256 > caps.nMaxMBCount) { + av_log(logctx, AV_LOG_ERROR, "Video macroblock count %d exceeds maximum of %d\n", + (int)(params->ulWidth * params->ulHeight) / 256, caps.nMaxMBCount); + return AVERROR(EINVAL); + } + + return 0; +} + static void nvdec_decoder_free(void *opaque, uint8_t *data) { NVDECDecoder *decoder = (NVDECDecoder*)data; @@ -132,6 +182,12 @@ static int nvdec_decoder_create(AVBufferRef **out, AVBufferRef *hw_device_ref, goto fail; } + ret = nvdec_test_capabilities(decoder, params, logctx); + if (ret < 0) { + decoder->cudl->cuCtxPopCurrent(&dummy); + goto fail; + } + err = decoder->cvdl->cuvidCreateDecoder(&decoder->decoder, params); decoder->cudl->cuCtxPopCurrent(&dummy); From 3f6294a53d58ececeacb42ce2ba8349a8b0a4abb Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sat, 11 Nov 2017 15:07:41 +0100 Subject: [PATCH 0857/2557] avcodec/nvdec: add support for 12 bit formats --- libavcodec/nvdec.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index 628789734385e..274f69f997923 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -489,9 +489,21 @@ int ff_nvdec_frame_params(AVCodecContext *avctx, frames_ctx->format = AV_PIX_FMT_CUDA; frames_ctx->width = avctx->coded_width; frames_ctx->height = avctx->coded_height; - frames_ctx->sw_format = sw_desc->comp[0].depth > 8 ? - AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; frames_ctx->initial_pool_size = dpb_size; + switch (sw_desc->comp[0].depth) { + case 8: + frames_ctx->sw_format = AV_PIX_FMT_NV12; + break; + case 10: + frames_ctx->sw_format = AV_PIX_FMT_P010; + break; + case 12: + frames_ctx->sw_format = AV_PIX_FMT_P016; + break; + default: + return AVERROR(EINVAL); + } + return 0; } From 1ef4af2d492e87e6d9fc9157a2d9c7f95585f61c Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 12 Nov 2017 15:20:45 +0000 Subject: [PATCH 0858/2557] hwcontext_vaapi: Fix build with libva 2.0 vaExportSurfaceHandle() wasn't included in the 2.0 release. Fixes ticket #6828. --- libavutil/hwcontext_vaapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 40a85d288c6a9..0382eb06f2ca8 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -1076,7 +1076,7 @@ static void vaapi_unmap_to_drm(AVHWFramesContext *dst_fc, static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { -#if CONFIG_VAAPI_1 +#if VA_CHECK_VERSION(1, 1, 0) AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; VASurfaceID surface_id; VAStatus vas; From 9a6e4c88d64149eaaf28d7ea77de80cedf602935 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 11 Nov 2017 01:45:37 -0300 Subject: [PATCH 0859/2557] avcodec/h264_metadata_bsf: fix the AVClass version number Reviewed-by: Michael Niedermayer Reviewed-by: jkqxz Signed-off-by: James Almer --- libavcodec/h264_metadata_bsf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 73e73e96e48d6..ada40a57c7138 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -506,7 +506,7 @@ static const AVClass h264_metadata_class = { .class_name = "h264_metadata_bsf", .item_name = av_default_item_name, .option = h264_metadata_options, - .version = LIBAVCODEC_VERSION_MAJOR, + .version = LIBAVUTIL_VERSION_INT, }; static const enum AVCodecID h264_metadata_codec_ids[] = { From 9549f22bf88dfe622760f0416a29482ba91d5423 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 11 Nov 2017 01:45:46 -0300 Subject: [PATCH 0860/2557] avcodec/h265_metadata_bsf: fix the AVClass version number Reviewed-by: Michael Niedermayer Reviewed-by: jkqxz Signed-off-by: James Almer --- libavcodec/h265_metadata_bsf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h265_metadata_bsf.c b/libavcodec/h265_metadata_bsf.c index 9af5cc256f932..67dbe288e30a7 100644 --- a/libavcodec/h265_metadata_bsf.c +++ b/libavcodec/h265_metadata_bsf.c @@ -440,7 +440,7 @@ static const AVClass h265_metadata_class = { .class_name = "h265_metadata_bsf", .item_name = av_default_item_name, .option = h265_metadata_options, - .version = LIBAVCODEC_VERSION_MAJOR, + .version = LIBAVUTIL_VERSION_INT, }; static const enum AVCodecID h265_metadata_codec_ids[] = { From a7e7abf8495f1d5eb2fea43b3603b13fa221553c Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 11 Nov 2017 01:46:01 -0300 Subject: [PATCH 0861/2557] avcodec/mpeg2_metadata_bsf: fix the AVClass version number Reviewed-by: Michael Niedermayer Reviewed-by: jkqxz Signed-off-by: James Almer --- libavcodec/mpeg2_metadata_bsf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpeg2_metadata_bsf.c b/libavcodec/mpeg2_metadata_bsf.c index f1f84e6cd90ea..b9a49ab9436fe 100644 --- a/libavcodec/mpeg2_metadata_bsf.c +++ b/libavcodec/mpeg2_metadata_bsf.c @@ -294,7 +294,7 @@ static const AVClass mpeg2_metadata_class = { .class_name = "mpeg2_metadata_bsf", .item_name = av_default_item_name, .option = mpeg2_metadata_options, - .version = LIBAVCODEC_VERSION_MAJOR, + .version = LIBAVUTIL_VERSION_INT, }; static const enum AVCodecID mpeg2_metadata_codec_ids[] = { From ff007e30d8d45ba1ff2b2a4615f1cd5bafb50626 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 25 Oct 2017 00:15:55 +0100 Subject: [PATCH 0862/2557] vaapi_h264: Add workaround for bad SEI in old Intel drivers With pre-2.0 Intel drivers in CBR mode, if an explicit SEI message with the old (now deprecated) type is not included, the driver generates and inserts some timing SEI which is almost certainly invlaid. Before 7a4fac5e91789b73e07bd4ad20493cfde028df76 we always inserted our own SEI so this would not be visible, but since then it has been possible to disable that. We would also like to avoid using the deprecated type, and using the new type, while working in old drivers, does not suppress the spurious message like the old type does. Therefore, suppress the bad SEI insertion by providing a zero-length buffer with the old type, which the driver can insert harmlessly. --- libavcodec/vaapi_encode_h264.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 3ff19d2c83d31..377e3652de738 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -82,6 +82,7 @@ typedef struct VAAPIEncodeH264Context { CodedBitstreamFragment current_access_unit; int aud_needed; int sei_needed; + int sei_cbr_workaround_needed; } VAAPIEncodeH264Context; typedef struct VAAPIEncodeH264Options { @@ -254,6 +255,19 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, *type = VAEncPackedHeaderH264_SEI; return 0; + +#if !HAVE_VAAPI_1 + } else if (priv->sei_cbr_workaround_needed) { + // Insert a zero-length header using the old SEI type. This is + // required to avoid triggering broken behaviour on Intel platforms + // in CBR mode where an invalid SEI message is generated by the + // driver and inserted into the stream. + *data_len = 0; + *type = VAEncPackedHeaderH264_SEI; + priv->sei_cbr_workaround_needed = 0; + return 0; +#endif + } else { return AVERROR_EOF; } @@ -608,6 +622,10 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, if (opt->sei & SEI_IDENTIFIER && pic->encode_order == 0) priv->sei_needed = 1; +#if !HAVE_VAAPI_1 + if (ctx->va_rc_mode == VA_RC_CBR) + priv->sei_cbr_workaround_needed = 1; +#endif if (opt->sei & SEI_TIMING) { memset(&priv->pic_timing, 0, sizeof(priv->pic_timing)); From c77da21e5d15056b8ba060ee5ce9e73f26653612 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 1 Oct 2017 22:55:24 +0100 Subject: [PATCH 0863/2557] vaapi_h264: Do not use deprecated header type SEI headers should be inserted as generic raw data (the old specific type has been deprecated in libva2). --- libavcodec/vaapi_encode_h264.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 377e3652de738..48cebd6edfac2 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -253,7 +253,7 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, ff_cbs_fragment_uninit(&priv->cbc, au); - *type = VAEncPackedHeaderH264_SEI; + *type = VAEncPackedHeaderRawData; return 0; #if !HAVE_VAAPI_1 From 476d301316aa5436c1d26cfc4858f36875637853 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 9 Nov 2017 01:04:11 +0000 Subject: [PATCH 0864/2557] cbs: Add a missing return value check --- libavcodec/cbs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index 7440914939f6a..3baa31a4ddd64 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -260,7 +260,7 @@ int ff_cbs_write_packet(CodedBitstreamContext *ctx, if (err < 0) return err; - av_new_packet(pkt, frag->data_size); + err = av_new_packet(pkt, frag->data_size); if (err < 0) return err; From 22aed77687f86b6b9efb9b0fdf4b26130a858c6d Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 9 Nov 2017 01:04:30 +0000 Subject: [PATCH 0865/2557] cbs_h2645: Fix memory leak on when reading SEI fails --- libavcodec/cbs_h2645.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index a1b887fd4c9f8..61729ccbb371d 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -821,6 +821,7 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, err = cbs_h264_read_sei(ctx, &bc, sei); if (err < 0) { cbs_h264_free_sei(sei); + av_free(sei); return err; } From d5fcf9426110df2d2f5b15ad0031185b3cfd3619 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 9 Nov 2017 01:04:34 +0000 Subject: [PATCH 0866/2557] h264_metadata: Fix clearing SEI payload in error case --- libavcodec/h264_metadata_bsf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 1afa5014b37ef..ac0b9823b919b 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -368,7 +368,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) "must be \"UUID+string\".\n"); err = AVERROR(EINVAL); sei_fail: - memset(payload, 0, sizeof(&payload)); + memset(payload, 0, sizeof(*payload)); goto fail; } From 620f88a0b94a651c6cc912b1fb32d308762d59b5 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 9 Nov 2017 01:04:39 +0000 Subject: [PATCH 0867/2557] vaapi_h264: Add missing return value check --- libavcodec/vaapi_encode_h264.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 48cebd6edfac2..03605b05b29e8 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -210,7 +210,9 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, if (priv->sei_needed) { if (priv->aud_needed) { - vaapi_encode_h264_add_nal(avctx, au, &priv->aud); + err = vaapi_encode_h264_add_nal(avctx, au, &priv->aud); + if (err < 0) + goto fail; priv->aud_needed = 0; } From 7a060867f3d75395e37e724b5e4d43f34f0f60aa Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 7 Nov 2017 19:41:06 +0100 Subject: [PATCH 0868/2557] avfilter/vf_tile: add overlap option Signed-off-by: Paul B Mahol --- doc/filters.texi | 4 ++++ libavfilter/vf_tile.c | 54 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 5c6729a484ea5..4a35c44c7b6ae 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -14441,6 +14441,10 @@ refer to the pad video filter. Specify the color of the unused area. For the syntax of this option, check the "Color" section in the ffmpeg-utils manual. The default value of @var{color} is "black". + +@item overlap +Set the number of frames to overlap when tiling several successive frames together. +The value must be between @code{0} and @var{nb_frames - 1}. @end table @subsection Examples diff --git a/libavfilter/vf_tile.c b/libavfilter/vf_tile.c index e9d246fc73b0b..7717ce12e72eb 100644 --- a/libavfilter/vf_tile.c +++ b/libavfilter/vf_tile.c @@ -37,11 +37,13 @@ typedef struct TileContext { unsigned w, h; unsigned margin; unsigned padding; + unsigned overlap; unsigned current; unsigned nb_frames; FFDrawContext draw; FFDrawColor blank; AVFrame *out_ref; + AVFrame *prev_out_ref; uint8_t rgba_color[4]; } TileContext; @@ -58,6 +60,8 @@ static const AVOption tile_options[] = { { "padding", "set inner border thickness in pixels", OFFSET(padding), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1024, FLAGS }, { "color", "set the color of the unused area", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str = "black"}, .flags = FLAGS }, + { "overlap", "set how many frames to overlap for each render", OFFSET(overlap), + AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS }, { NULL } }; @@ -90,6 +94,11 @@ static av_cold int init(AVFilterContext *ctx) return AVERROR(EINVAL); } + if (tile->overlap >= tile->nb_frames) { + av_log(ctx, AV_LOG_WARNING, "overlap must be less than %d\n", tile->nb_frames); + tile->overlap = tile->nb_frames - 1; + } + return 0; } @@ -120,19 +129,19 @@ static int config_props(AVFilterLink *outlink) outlink->h = tile->h * inlink->h + total_margin_h; outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; outlink->frame_rate = av_mul_q(inlink->frame_rate, - av_make_q(1, tile->nb_frames)); + av_make_q(1, tile->nb_frames - tile->overlap)); ff_draw_init(&tile->draw, inlink->format, 0); ff_draw_color(&tile->draw, &tile->blank, tile->rgba_color); return 0; } -static void get_current_tile_pos(AVFilterContext *ctx, unsigned *x, unsigned *y) +static void get_tile_pos(AVFilterContext *ctx, unsigned *x, unsigned *y, unsigned current) { TileContext *tile = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - const unsigned tx = tile->current % tile->w; - const unsigned ty = tile->current / tile->w; + const unsigned tx = current % tile->w; + const unsigned ty = current / tile->w; *x = tile->margin + (inlink->w + tile->padding) * tx; *y = tile->margin + (inlink->h + tile->padding) * ty; @@ -144,7 +153,7 @@ static void draw_blank_frame(AVFilterContext *ctx, AVFrame *out_buf) AVFilterLink *inlink = ctx->inputs[0]; unsigned x0, y0; - get_current_tile_pos(ctx, &x0, &y0); + get_tile_pos(ctx, &x0, &y0, tile->current); ff_fill_rectangle(&tile->draw, &tile->blank, out_buf->data, out_buf->linesize, x0, y0, inlink->w, inlink->h); @@ -160,8 +169,13 @@ static int end_last_frame(AVFilterContext *ctx) while (tile->current < tile->nb_frames) draw_blank_frame(ctx, out_buf); + tile->current = tile->overlap; + if (tile->current) { + av_frame_free(&tile->prev_out_ref); + tile->prev_out_ref = av_frame_clone(out_buf); + } ret = ff_filter_frame(outlink, out_buf); - tile->current = 0; + tile->out_ref = NULL; return ret; } @@ -176,7 +190,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) AVFilterLink *outlink = ctx->outputs[0]; unsigned x0, y0; - if (!tile->current) { + if (!tile->out_ref) { tile->out_ref = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!tile->out_ref) { av_frame_free(&picref); @@ -194,7 +208,21 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) 0, 0, outlink->w, outlink->h); } - get_current_tile_pos(ctx, &x0, &y0); + if (tile->prev_out_ref) { + unsigned x1, y1, i; + + for (i = tile->nb_frames - tile->overlap; i < tile->nb_frames; i++) { + get_tile_pos(ctx, &x1, &y1, i); + get_tile_pos(ctx, &x0, &y0, i - (tile->nb_frames - tile->overlap)); + ff_copy_rectangle2(&tile->draw, + tile->out_ref->data, tile->out_ref->linesize, + tile->prev_out_ref->data, tile->prev_out_ref->linesize, + x0, y0, x1, y1, inlink->w, inlink->h); + + } + } + + get_tile_pos(ctx, &x0, &y0, tile->current); ff_copy_rectangle2(&tile->draw, tile->out_ref->data, tile->out_ref->linesize, picref->data, picref->linesize, @@ -215,11 +243,18 @@ static int request_frame(AVFilterLink *outlink) int r; r = ff_request_frame(inlink); - if (r == AVERROR_EOF && tile->current) + if (r == AVERROR_EOF && tile->current && tile->out_ref) r = end_last_frame(ctx); return r; } +static av_cold void uninit(AVFilterContext *ctx) +{ + TileContext *tile = ctx->priv; + + av_frame_free(&tile->prev_out_ref); +} + static const AVFilterPad tile_inputs[] = { { .name = "default", @@ -243,6 +278,7 @@ AVFilter ff_vf_tile = { .name = "tile", .description = NULL_IF_CONFIG_SMALL("Tile several successive frames together."), .init = init, + .uninit = uninit, .query_formats = query_formats, .priv_size = sizeof(TileContext), .inputs = tile_inputs, From c31ce95f1c4c504ff9e3a90b1e4e37f695547c72 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 31 Oct 2017 15:12:24 +0100 Subject: [PATCH 0869/2557] videotoolbox: add frame_params support Allows decoding with API users which require this API. Reviewed-by: Aman Gupta --- libavcodec/videotoolbox.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index ecb2502c1f3b8..f0790e7353834 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -947,6 +947,19 @@ static int videotoolbox_common_init(AVCodecContext *avctx) return err; } +static int videotoolbox_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) +{ + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data; + + frames_ctx->format = AV_PIX_FMT_VIDEOTOOLBOX; + frames_ctx->width = avctx->coded_width; + frames_ctx->height = avctx->coded_height; + frames_ctx->sw_format = AV_PIX_FMT_NV12; + + return 0; +} + AVHWAccel ff_h263_videotoolbox_hwaccel = { .name = "h263_videotoolbox", .type = AVMEDIA_TYPE_VIDEO, @@ -956,6 +969,7 @@ AVHWAccel ff_h263_videotoolbox_hwaccel = { .start_frame = videotoolbox_mpeg_start_frame, .decode_slice = videotoolbox_mpeg_decode_slice, .end_frame = videotoolbox_mpeg_end_frame, + .frame_params = videotoolbox_frame_params, .init = videotoolbox_common_init, .uninit = videotoolbox_uninit, .priv_data_size = sizeof(VTContext), @@ -970,6 +984,7 @@ AVHWAccel ff_hevc_videotoolbox_hwaccel = { .start_frame = ff_videotoolbox_h264_start_frame, .decode_slice = ff_videotoolbox_h264_decode_slice, .end_frame = videotoolbox_hevc_end_frame, + .frame_params = videotoolbox_frame_params, .init = videotoolbox_common_init, .uninit = ff_videotoolbox_uninit, .priv_data_size = sizeof(VTContext), @@ -984,6 +999,7 @@ AVHWAccel ff_h264_videotoolbox_hwaccel = { .start_frame = ff_videotoolbox_h264_start_frame, .decode_slice = ff_videotoolbox_h264_decode_slice, .end_frame = videotoolbox_h264_end_frame, + .frame_params = videotoolbox_frame_params, .init = videotoolbox_common_init, .uninit = videotoolbox_uninit, .priv_data_size = sizeof(VTContext), @@ -998,6 +1014,7 @@ AVHWAccel ff_mpeg1_videotoolbox_hwaccel = { .start_frame = videotoolbox_mpeg_start_frame, .decode_slice = videotoolbox_mpeg_decode_slice, .end_frame = videotoolbox_mpeg_end_frame, + .frame_params = videotoolbox_frame_params, .init = videotoolbox_common_init, .uninit = videotoolbox_uninit, .priv_data_size = sizeof(VTContext), @@ -1012,6 +1029,7 @@ AVHWAccel ff_mpeg2_videotoolbox_hwaccel = { .start_frame = videotoolbox_mpeg_start_frame, .decode_slice = videotoolbox_mpeg_decode_slice, .end_frame = videotoolbox_mpeg_end_frame, + .frame_params = videotoolbox_frame_params, .init = videotoolbox_common_init, .uninit = videotoolbox_uninit, .priv_data_size = sizeof(VTContext), @@ -1026,6 +1044,7 @@ AVHWAccel ff_mpeg4_videotoolbox_hwaccel = { .start_frame = videotoolbox_mpeg_start_frame, .decode_slice = videotoolbox_mpeg_decode_slice, .end_frame = videotoolbox_mpeg_end_frame, + .frame_params = videotoolbox_frame_params, .init = videotoolbox_common_init, .uninit = videotoolbox_uninit, .priv_data_size = sizeof(VTContext), From 6665938ca8b7ad8b7ec77c23e611bb8224e88a90 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 12 Nov 2017 20:26:42 +0100 Subject: [PATCH 0870/2557] avformat/ty: check if header is correctly parsed and is still present Fixes #6829. Signed-off-by: Paul B Mahol --- libavformat/ty.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/ty.c b/libavformat/ty.c index 02ab59aa2e152..0f08e787f5997 100644 --- a/libavformat/ty.c +++ b/libavformat/ty.c @@ -440,6 +440,8 @@ static int get_chunk(AVFormatContext *s) return AVERROR_INVALIDDATA; ty->rec_hdrs = parse_chunk_headers(ty->chunk + 4, num_recs); + if (!ty->rec_hdrs) + return AVERROR(ENOMEM); ty->cur_chunk_pos += 16 * num_recs; return 0; @@ -723,8 +725,8 @@ static int ty_read_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR_EOF; while (ret <= 0) { - if (ty->first_chunk || ty->cur_rec >= ty->num_recs) { - if (get_chunk(s) < 0 || ty->num_recs == 0) + if (!ty->rec_hdrs || ty->first_chunk || ty->cur_rec >= ty->num_recs) { + if (get_chunk(s) < 0 || ty->num_recs <= 0) return AVERROR_EOF; } From a38b14a432b3a031d6bafdbb5f790724b9b2094d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 12 Nov 2017 20:38:30 +0100 Subject: [PATCH 0871/2557] avformat/ty: fix memory leaks Signed-off-by: Paul B Mahol --- libavformat/ty.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libavformat/ty.c b/libavformat/ty.c index 0f08e787f5997..ba874280ea503 100644 --- a/libavformat/ty.c +++ b/libavformat/ty.c @@ -764,6 +764,16 @@ static int ty_read_packet(AVFormatContext *s, AVPacket *pkt) return 0; } +static int ty_read_close(AVFormatContext *s) +{ + TYDemuxContext *ty = s->priv_data; + + av_freep(&ty->seq_table); + av_freep(&ty->rec_hdrs); + + return 0; +} + AVInputFormat ff_ty_demuxer = { .name = "ty", .long_name = NULL_IF_CONFIG_SMALL("TiVo TY Stream"), @@ -771,6 +781,7 @@ AVInputFormat ff_ty_demuxer = { .read_probe = ty_probe, .read_header = ty_read_header, .read_packet = ty_read_packet, + .read_close = ty_read_close, .extensions = "ty,ty+", .flags = AVFMT_TS_DISCONT, }; From f38d0d0c22c1871ef0728a718c5e00a6ba93bfa1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 12 Nov 2017 22:57:06 +0100 Subject: [PATCH 0872/2557] avformat/ty: check cur_chunk_pos before using it Fixes #6831. Signed-off-by: Paul B Mahol --- libavformat/ty.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/ty.c b/libavformat/ty.c index ba874280ea503..d348643f40cfb 100644 --- a/libavformat/ty.c +++ b/libavformat/ty.c @@ -378,6 +378,8 @@ static void parse_master(AVFormatContext *s) ty->cur_chunk_pos = 32; for (j = 0; j < ty->seq_table_size; j++) { + if (ty->cur_chunk_pos >= CHUNK_SIZE - 8) + return; ty->seq_table[j].timestamp = AV_RB64(ty->chunk + ty->cur_chunk_pos); ty->cur_chunk_pos += 8; if (map_size > 8) { From fd18d310ec200fa7ace29cbfc725d451663bf49c Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Wed, 25 Oct 2017 11:03:14 -0700 Subject: [PATCH 0873/2557] lavf/tls_securetransport: build on iOS This works as expected on iOS, except for the ca_file feature which is disabled because SecItemImport is not available. Signed-off-by: Aman Gupta --- configure | 6 +++++- libavformat/tls_securetransport.c | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 2f026c45bc499..c6fb3449292e1 100755 --- a/configure +++ b/configure @@ -2035,6 +2035,7 @@ SYSTEM_FUNCS=" posix_memalign pthread_cancel sched_getaffinity + SecItemImport SetConsoleTextAttribute SetConsoleCtrlHandler setmode @@ -6032,9 +6033,12 @@ fi enabled securetransport && check_func SecIdentityCreate "-Wl,-framework,CoreFoundation -Wl,-framework,Security" && - check_lib securetransport "Security/SecureTransport.h Security/Security.h" "SSLCreateContext SecItemImport" "-Wl,-framework,CoreFoundation -Wl,-framework,Security" || + check_lib securetransport "Security/SecureTransport.h Security/Security.h" "SSLCreateContext" "-Wl,-framework,CoreFoundation -Wl,-framework,Security" || disable securetransport +enabled securetransport && + check_func SecItemImport "-Wl,-framework,CoreFoundation -Wl,-framework,Security" + enabled schannel && check_func_headers "windows.h security.h" InitializeSecurityContext -DSECURITY_WIN32 -lsecur32 && check_cpp_condition winerror.h "defined(SEC_I_CONTEXT_EXPIRED)" && diff --git a/libavformat/tls_securetransport.c b/libavformat/tls_securetransport.c index 9958931b0cc56..b862e0003a0d4 100644 --- a/libavformat/tls_securetransport.c +++ b/libavformat/tls_securetransport.c @@ -69,6 +69,9 @@ static int print_tls_error(URLContext *h, int ret) static int import_pem(URLContext *h, char *path, CFArrayRef *array) { +#if !HAVE_SECITEMIMPORT + return AVERROR_PATCHWELCOME; +#else AVIOContext *s = NULL; CFDataRef data = NULL; int64_t ret = 0; @@ -124,6 +127,7 @@ static int import_pem(URLContext *h, char *path, CFArrayRef *array) if (s) avio_close(s); return ret; +#endif } static int load_ca(URLContext *h) From b72ac6dbb815a40c111ab9ec3b55879c8068da7c Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 12 Nov 2017 22:56:45 -0300 Subject: [PATCH 0874/2557] configure: fix writing library dependencies to config.sh Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 1f220c8befe44..e608d26608b69 100755 --- a/configure +++ b/configure @@ -5405,7 +5405,7 @@ EOF for lib in $LIBRARY_LIST; do lib_deps="$(eval echo \$${lib}_deps)" - echo ${lib}_deps=\"$lib_deps\" >> avbuild/config.sh + echo ${lib}_deps=\"$lib_deps\" >> $TMPH done cp_if_changed $TMPH avbuild/config.sh From d9ff1e4c8bdf97cbb1ab4bd97102eefbe8ebf95a Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 12 Nov 2017 22:59:34 -0300 Subject: [PATCH 0875/2557] configure: fix writing library dependencies to config.sh Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index c6fb3449292e1..46b4815f2ead1 100755 --- a/configure +++ b/configure @@ -7011,7 +7011,7 @@ EOF for lib in $LIBRARY_LIST; do lib_deps="$(eval echo \$${lib}_deps)" - echo ${lib}_deps=\"$lib_deps\" >> ffbuild/config.sh + echo ${lib}_deps=\"$lib_deps\" >> $TMPH done cp_if_changed $TMPH ffbuild/config.sh From 3ee63f3fb70c3be36aa62adf9ad0fe2defa2bd51 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Mon, 13 Nov 2017 10:44:16 +0800 Subject: [PATCH 0876/2557] avformat/hlsenc: allocate space for terminating null Fixes CID #1420394 --- libavformat/hlsenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 5ea9d216a4aa5..b571772f606b2 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1455,7 +1455,7 @@ static int hls_write_header(AVFormatContext *s) if (basename_size > 0) { hls->base_output_dirname = av_malloc(basename_size); } else { - hls->base_output_dirname = av_malloc(strlen(hls->fmp4_init_filename)); + hls->base_output_dirname = av_malloc(strlen(hls->fmp4_init_filename) + 1); } if (!hls->base_output_dirname) { ret = AVERROR(ENOMEM); From f3e34072aadf20be60c0fae38cbe14ad4581c6a5 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 13 Nov 2017 10:52:01 +0800 Subject: [PATCH 0877/2557] avformat/img2enc: add frame_pts option for make output filename fix ticket id: #1452 when use frame_pts option, the output image name can be set with PTS of current frame. Signed-off-by: Steven Liu --- doc/muxers.texi | 9 +++++++++ libavformat/img2enc.c | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/doc/muxers.texi b/doc/muxers.texi index 43f3776b13555..616568ebea6a5 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -897,9 +897,18 @@ can be used: ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg" @end example +You can set the file name with current frame's PTS: +@example +ffmpeg -f v4l2 -r 1 -i /dev/video0 -copyts -f image2 -frame_pts true %d.jpg" +@end example + @subsection Options @table @option +@item frame_pts +If set to 1, expand the filename with pts from pkt->pts. +Default value is 0. + @item start_number Start the sequence from the specified number. Default value is 1. diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 7d64659340d5a..b680676bff7b4 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -42,6 +42,7 @@ typedef struct VideoMuxData { char target[4][1024]; int update; int use_strftime; + int frame_pts; const char *muxer; int use_rename; } VideoMuxData; @@ -99,6 +100,11 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); return AVERROR(EINVAL); } + } else if (img->frame_pts) { + if (av_get_frame_filename2(filename, sizeof(filename), img->path, pkt->pts, AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + av_log(s, AV_LOG_ERROR, "Cannot write filename by pts of the frames."); + return AVERROR(EINVAL); + } } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, img->img_number, AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && @@ -206,6 +212,7 @@ static const AVOption muxoptions[] = { { "update", "continuously overwrite one file", OFFSET(update), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC }, { "start_number", "set first number in the sequence", OFFSET(img_number), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, ENC }, { "strftime", "use strftime for filename", OFFSET(use_strftime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC }, + { "frame_pts", "use current frame pts for filename", OFFSET(frame_pts), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC }, { "atomic_writing", "write files atomically (using temporary files and renames)", OFFSET(use_rename), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC }, { NULL }, }; From 1828c549c3ecd45d54ff03aee784b00a41f0e69e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 12 Nov 2017 18:07:45 +0100 Subject: [PATCH 0878/2557] avfilter/vf_*_qsv: Fix flags Reviewed-by: Mark Thompson Signed-off-by: Michael Niedermayer --- libavfilter/vf_overlay_qsv.c | 2 +- libavfilter/vf_vpp_qsv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_overlay_qsv.c b/libavfilter/vf_overlay_qsv.c index 471576e35a235..1f50d4bb21469 100644 --- a/libavfilter/vf_overlay_qsv.c +++ b/libavfilter/vf_overlay_qsv.c @@ -42,7 +42,7 @@ #define OVERLAY 1 #define OFFSET(x) offsetof(QSVOverlayContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) enum var_name { VAR_MAIN_iW, VAR_MW, diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 86af017d2ec92..eb2f1cc7eb8e5 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -37,7 +37,7 @@ #include "qsvvpp.h" #define OFFSET(x) offsetof(VPPContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) /* number of video enhancement filters */ #define ENH_FILTERS_COUNT (5) From 43171a2a738f5114768d34a7278e56e5fde714bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Sun, 12 Nov 2017 16:24:37 +0000 Subject: [PATCH 0879/2557] Fix missing used attribute for inline assembly variables Variables used in inline assembly need to be marked with attribute((used)). Static constants already were, via the define of DECLARE_ASM_CONST. But DECLARE_ALIGNED does not add this attribute, and some of the variables defined with it are const only used in inline assembly, and therefore appeared dead. This change adds a macro DECLARE_ASM_ALIGNED that marks variables as used. This change makes FFMPEG work with Clang's ThinLTO. Signed-off-by: Michael Niedermayer --- libavcodec/cabac.c | 2 +- libavcodec/x86/constants.c | 20 ++++++++++---------- libavutil/mem.h | 17 +++++++++++++++++ libswscale/x86/swscale.c | 12 ++++++------ 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/libavcodec/cabac.c b/libavcodec/cabac.c index dd2b057c6dd83..e51139de3bb72 100644 --- a/libavcodec/cabac.c +++ b/libavcodec/cabac.c @@ -32,7 +32,7 @@ #include "cabac.h" #include "cabac_functions.h" -const uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63] = { +DECLARE_ASM_ALIGNED(1, const uint8_t, ff_h264_cabac_tables)[512 + 4*2*64 + 4*64 + 63] = { 9,8,7,7,6,6,6,6,5,5,5,5,5,5,5,5, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, diff --git a/libavcodec/x86/constants.c b/libavcodec/x86/constants.c index 11002ee61e62e..47905c74a17c7 100644 --- a/libavcodec/x86/constants.c +++ b/libavcodec/x86/constants.c @@ -26,23 +26,23 @@ DECLARE_ALIGNED(32, const ymm_reg, ff_pw_1) = { 0x0001000100010001ULL, 0x000 0x0001000100010001ULL, 0x0001000100010001ULL }; DECLARE_ALIGNED(32, const ymm_reg, ff_pw_2) = { 0x0002000200020002ULL, 0x0002000200020002ULL, 0x0002000200020002ULL, 0x0002000200020002ULL }; -DECLARE_ALIGNED(16, const xmm_reg, ff_pw_3) = { 0x0003000300030003ULL, 0x0003000300030003ULL }; -DECLARE_ALIGNED(32, const ymm_reg, ff_pw_4) = { 0x0004000400040004ULL, 0x0004000400040004ULL, +DECLARE_ASM_ALIGNED(16, const xmm_reg, ff_pw_3) = { 0x0003000300030003ULL, 0x0003000300030003ULL }; +DECLARE_ASM_ALIGNED(32, const ymm_reg, ff_pw_4) = { 0x0004000400040004ULL, 0x0004000400040004ULL, 0x0004000400040004ULL, 0x0004000400040004ULL }; -DECLARE_ALIGNED(16, const xmm_reg, ff_pw_5) = { 0x0005000500050005ULL, 0x0005000500050005ULL }; +DECLARE_ASM_ALIGNED(16, const xmm_reg, ff_pw_5) = { 0x0005000500050005ULL, 0x0005000500050005ULL }; DECLARE_ALIGNED(16, const xmm_reg, ff_pw_8) = { 0x0008000800080008ULL, 0x0008000800080008ULL }; -DECLARE_ALIGNED(16, const xmm_reg, ff_pw_9) = { 0x0009000900090009ULL, 0x0009000900090009ULL }; +DECLARE_ASM_ALIGNED(16, const xmm_reg, ff_pw_9) = { 0x0009000900090009ULL, 0x0009000900090009ULL }; DECLARE_ALIGNED(8, const uint64_t, ff_pw_15) = 0x000F000F000F000FULL; DECLARE_ALIGNED(16, const xmm_reg, ff_pw_16) = { 0x0010001000100010ULL, 0x0010001000100010ULL }; DECLARE_ALIGNED(16, const xmm_reg, ff_pw_17) = { 0x0011001100110011ULL, 0x0011001100110011ULL }; -DECLARE_ALIGNED(16, const xmm_reg, ff_pw_18) = { 0x0012001200120012ULL, 0x0012001200120012ULL }; +DECLARE_ASM_ALIGNED(16, const xmm_reg, ff_pw_18) = { 0x0012001200120012ULL, 0x0012001200120012ULL }; DECLARE_ALIGNED(16, const xmm_reg, ff_pw_20) = { 0x0014001400140014ULL, 0x0014001400140014ULL }; DECLARE_ALIGNED(16, const xmm_reg, ff_pw_32) = { 0x0020002000200020ULL, 0x0020002000200020ULL }; -DECLARE_ALIGNED(8, const uint64_t, ff_pw_42) = 0x002A002A002A002AULL; -DECLARE_ALIGNED(8, const uint64_t, ff_pw_53) = 0x0035003500350035ULL; -DECLARE_ALIGNED(16, const xmm_reg, ff_pw_64) = { 0x0040004000400040ULL, 0x0040004000400040ULL }; -DECLARE_ALIGNED(8, const uint64_t, ff_pw_96) = 0x0060006000600060ULL; -DECLARE_ALIGNED(8, const uint64_t, ff_pw_128) = 0x0080008000800080ULL; +DECLARE_ASM_ALIGNED(8, const uint64_t, ff_pw_42) = 0x002A002A002A002AULL; +DECLARE_ASM_ALIGNED(8, const uint64_t, ff_pw_53) = 0x0035003500350035ULL; +DECLARE_ASM_ALIGNED(16, const xmm_reg, ff_pw_64) = { 0x0040004000400040ULL, 0x0040004000400040ULL }; +DECLARE_ASM_ALIGNED(8, const uint64_t, ff_pw_96) = 0x0060006000600060ULL; +DECLARE_ASM_ALIGNED(8, const uint64_t, ff_pw_128) = 0x0080008000800080ULL; DECLARE_ALIGNED(32, const ymm_reg, ff_pw_255) = { 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL }; DECLARE_ALIGNED(32, const ymm_reg, ff_pw_256) = { 0x0100010001000100ULL, 0x0100010001000100ULL, diff --git a/libavutil/mem.h b/libavutil/mem.h index e5ca8299dc987..9e344bd2c3355 100644 --- a/libavutil/mem.h +++ b/libavutil/mem.h @@ -73,6 +73,19 @@ * @param v Name of the variable */ +/** + * @def DECLARE_ASM_ALIGNED(n,t,v) + * Declare an aligned variable appropriate for use in inline assembly code. + * + * @code{.c} + * DECLARE_ASM_ALIGNED(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008); + * @endcode + * + * @param n Minimum alignment in bytes + * @param t Type of the variable (or array element) + * @param v Name of the variable + */ + /** * @def DECLARE_ASM_CONST(n,t,v) * Declare a static constant aligned variable appropriate for use in inline @@ -89,18 +102,22 @@ #if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C) #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v #elif defined(__DJGPP__) #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (FFMIN(n, 16)))) v #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v #elif defined(__GNUC__) || defined(__clang__) #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (n))) v #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v #elif defined(_MSC_VER) #define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ASM_ALIGNED(n,t,v) __declspec(align(n)) t v #define DECLARE_ASM_CONST(n,t,v) __declspec(align(n)) static const t v #else #define DECLARE_ALIGNED(n,t,v) t v + #define DECLARE_ASM_ALIGNED(n,t,v) t v #define DECLARE_ASM_CONST(n,t,v) static const t v #endif diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c index 869e7fb176401..7dc2d7057442f 100644 --- a/libswscale/x86/swscale.c +++ b/libswscale/x86/swscale.c @@ -53,13 +53,13 @@ DECLARE_ASM_CONST(8, uint64_t, b15Mask)= 0x001F001F001F001FLL; DECLARE_ASM_CONST(8, uint64_t, g15Mask)= 0x03E003E003E003E0LL; DECLARE_ASM_CONST(8, uint64_t, r15Mask)= 0x7C007C007C007C00LL; -DECLARE_ALIGNED(8, const uint64_t, ff_M24A) = 0x00FF0000FF0000FFLL; -DECLARE_ALIGNED(8, const uint64_t, ff_M24B) = 0xFF0000FF0000FF00LL; -DECLARE_ALIGNED(8, const uint64_t, ff_M24C) = 0x0000FF0000FF0000LL; +DECLARE_ASM_ALIGNED(8, const uint64_t, ff_M24A) = 0x00FF0000FF0000FFLL; +DECLARE_ASM_ALIGNED(8, const uint64_t, ff_M24B) = 0xFF0000FF0000FF00LL; +DECLARE_ASM_ALIGNED(8, const uint64_t, ff_M24C) = 0x0000FF0000FF0000LL; -DECLARE_ALIGNED(8, const uint64_t, ff_bgr2YOffset) = 0x1010101010101010ULL; -DECLARE_ALIGNED(8, const uint64_t, ff_bgr2UVOffset) = 0x8080808080808080ULL; -DECLARE_ALIGNED(8, const uint64_t, ff_w1111) = 0x0001000100010001ULL; +DECLARE_ASM_ALIGNED(8, const uint64_t, ff_bgr2YOffset) = 0x1010101010101010ULL; +DECLARE_ASM_ALIGNED(8, const uint64_t, ff_bgr2UVOffset) = 0x8080808080808080ULL; +DECLARE_ASM_ALIGNED(8, const uint64_t, ff_w1111) = 0x0001000100010001ULL; //MMX versions From c897a9285846b6a072b9650976afd4f091b7a71f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 5 Nov 2017 21:20:05 +0100 Subject: [PATCH 0880/2557] avcodec/snowdec: Fix integer overflow in header parsing Fixes: 3984/clusterfuzz-testcase-minimized-5265759929368576 Fixes: runtime error: signed integer overflow: -1085585801 + -1094995529 cannot be represented in type 'int' Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/snowdec.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/snowdec.c b/libavcodec/snowdec.c index 13668c2105ee5..727e908fb5a49 100644 --- a/libavcodec/snowdec.c +++ b/libavcodec/snowdec.c @@ -374,7 +374,7 @@ static int decode_header(SnowContext *s){ } } - s->spatial_decomposition_type+= get_symbol(&s->c, s->header_state, 1); + s->spatial_decomposition_type+= (unsigned)get_symbol(&s->c, s->header_state, 1); if(s->spatial_decomposition_type > 1U){ av_log(s->avctx, AV_LOG_ERROR, "spatial_decomposition_type %d not supported\n", s->spatial_decomposition_type); return AVERROR_INVALIDDATA; @@ -390,10 +390,10 @@ static int decode_header(SnowContext *s){ } - s->qlog += get_symbol(&s->c, s->header_state, 1); - s->mv_scale += get_symbol(&s->c, s->header_state, 1); - s->qbias += get_symbol(&s->c, s->header_state, 1); - s->block_max_depth+= get_symbol(&s->c, s->header_state, 1); + s->qlog += (unsigned)get_symbol(&s->c, s->header_state, 1); + s->mv_scale += (unsigned)get_symbol(&s->c, s->header_state, 1); + s->qbias += (unsigned)get_symbol(&s->c, s->header_state, 1); + s->block_max_depth+= (unsigned)get_symbol(&s->c, s->header_state, 1); if(s->block_max_depth > 1 || s->block_max_depth < 0 || s->mv_scale > 256U){ av_log(s->avctx, AV_LOG_ERROR, "block_max_depth= %d is too large\n", s->block_max_depth); s->block_max_depth= 0; From 770c934fa1635f4fadf5db4fc5cc5ad15d82455a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 5 Nov 2017 21:20:06 +0100 Subject: [PATCH 0881/2557] avcodec/mdct_*: Fix integer overflow in addition in RESCALE() Fixes: runtime error: signed integer overflow: 1219998458 - -1469874012 cannot be represented in type 'int' Fixes: 3443/clusterfuzz-testcase-minimized-5369987105554432 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/mdct_fixed.c | 8 ++++---- libavcodec/mdct_template.c | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libavcodec/mdct_fixed.c b/libavcodec/mdct_fixed.c index a32cb00ca0360..aabf0c88f8da0 100644 --- a/libavcodec/mdct_fixed.c +++ b/libavcodec/mdct_fixed.c @@ -39,13 +39,13 @@ void ff_mdct_calcw_c(FFTContext *s, FFTDouble *out, const FFTSample *input) /* pre rotation */ for(i=0;i> 6) +# define RSCALE(x, y) ((int)((x) + (unsigned)(y) + 32) >> 6) #else /* FFT_FIXED_32 */ -# define RSCALE(x) ((x) >> 1) +# define RSCALE(x, y) ((int)((x) + (unsigned)(y)) >> 1) #endif /* FFT_FIXED_32 */ #endif @@ -181,13 +181,13 @@ void ff_mdct_calc_c(FFTContext *s, FFTSample *out, const FFTSample *input) /* pre rotation */ for(i=0;i Date: Sun, 5 Nov 2017 21:20:07 +0100 Subject: [PATCH 0882/2557] avcodec/aacdec_fixed: Fix undefined shift Fixes: runtime error: left shift of negative value -801112064 Fixes: 3492/clusterfuzz-testcase-minimized-5784775283441664 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/aacdec_fixed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c index ffd577c7893ae..f96999efb41ae 100644 --- a/libavcodec/aacdec_fixed.c +++ b/libavcodec/aacdec_fixed.c @@ -309,7 +309,7 @@ static av_always_inline void predict(PredictorState *ps, int *coef, if (shift > 0) { *coef += (unsigned)((pv.mant + (1 << (shift - 1))) >> shift); } else - *coef += (unsigned)(pv.mant << -shift); + *coef += (unsigned)pv.mant << -shift; } } From 2afe05402f05d485f0c356b04dc562f0510d317d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 5 Nov 2017 21:20:08 +0100 Subject: [PATCH 0883/2557] avcodec/aacpsdsp_template: Fix integer overflows in ps_decorrelate_c() Fixes: runtime error: signed integer overflow: 1939661764 - -454942263 cannot be represented in type 'int' Fixes: 3191/clusterfuzz-testcase-minimized-5688798451073024 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/aacpsdsp_template.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/aacpsdsp_template.c b/libavcodec/aacpsdsp_template.c index e35e9699b0b5a..19be200653645 100644 --- a/libavcodec/aacpsdsp_template.c +++ b/libavcodec/aacpsdsp_template.c @@ -130,12 +130,12 @@ static void ps_decorrelate_c(INTFLOAT (*out)[2], INTFLOAT (*delay)[2], INTFLOAT apd_im = in_im; in_re = AAC_MSUB30(link_delay_re, fractional_delay_re, link_delay_im, fractional_delay_im); - in_re -= a_re; + in_re -= (UINTFLOAT)a_re; in_im = AAC_MADD30(link_delay_re, fractional_delay_im, link_delay_im, fractional_delay_re); - in_im -= a_im; - ap_delay[m][n+5][0] = apd_re + AAC_MUL31(ag[m], in_re); - ap_delay[m][n+5][1] = apd_im + AAC_MUL31(ag[m], in_im); + in_im -= (UINTFLOAT)a_im; + ap_delay[m][n+5][0] = apd_re + (UINTFLOAT)AAC_MUL31(ag[m], in_re); + ap_delay[m][n+5][1] = apd_im + (UINTFLOAT)AAC_MUL31(ag[m], in_im); } out[n][0] = AAC_MUL16(transient_gain[n], in_re); out[n][1] = AAC_MUL16(transient_gain[n], in_im); From 480d33dfdc590c0509a4acdb6c2754e208123aab Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Sun, 12 Nov 2017 14:16:01 -0800 Subject: [PATCH 0884/2557] MAINTAINERS: add myself as videotoolbox* maintainer Reviewed-by: Rick Kern Signed-off-by: Michael Niedermayer --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 4df6c6533d857..6a92b5190df52 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -245,7 +245,7 @@ Codecs: txd.c Ivo van Poorten vc2* Rostislav Pehlivanov vcr1.c Michael Niedermayer - videotoolboxenc.c Rick Kern + videotoolboxenc.c Rick Kern, Aman Gupta vima.c Paul B Mahol vorbisdec.c Denes Balatoni, David Conrad vorbisenc.c Oded Shimon @@ -272,7 +272,7 @@ Hardware acceleration: vaapi* Gwenole Beauchesne vaapi_encode* Mark Thompson vdpau* Philip Langdale, Carl Eugen Hoyos - videotoolbox* Rick Kern + videotoolbox* Rick Kern, Aman Gupta libavdevice From 52bf0febb3a8a47b16ac6c3bfd707c347299f174 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 13 Nov 2017 11:12:52 -0800 Subject: [PATCH 0885/2557] avformat/http: fix stray quote in trace logging Signed-off-by: Aman Gupta Reviewed-by: Michael Niedermayer --- libavformat/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/http.c b/libavformat/http.c index bd9148f45dc1c..29635eb546555 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -1293,7 +1293,7 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size) s->chunksize = strtoull(line, NULL, 16); av_log(h, AV_LOG_TRACE, - "Chunked encoding data size: %"PRIu64"'\n", + "Chunked encoding data size: %"PRIu64"\n", s->chunksize); if (!s->chunksize) { From f3f73f0893e2bddd80897148d21cdf3e8e4d8492 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sat, 11 Nov 2017 21:19:07 +0100 Subject: [PATCH 0886/2557] avcodec: implement vp9 nvdec hwaccel --- Changelog | 2 +- configure | 2 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/nvdec.c | 1 + libavcodec/nvdec_vp9.c | 227 +++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- libavcodec/vp9.c | 11 +- 8 files changed, 244 insertions(+), 3 deletions(-) create mode 100644 libavcodec/nvdec_vp9.c diff --git a/Changelog b/Changelog index 869ecde162753..68829f22a449e 100644 --- a/Changelog +++ b/Changelog @@ -13,7 +13,7 @@ version : - PCE support for extended channel layouts in the AAC encoder - native aptX encoder and decoder - Raw aptX muxer and demuxer -- NVIDIA NVDEC-accelerated H.264 and HEVC hwaccel decoding +- NVIDIA NVDEC-accelerated H.264, HEVC and VP9 hwaccel decoding - Intel QSV-accelerated overlay filter diff --git a/configure b/configure index 46b4815f2ead1..da6d6449007f5 100755 --- a/configure +++ b/configure @@ -2764,6 +2764,8 @@ vp9_d3d11va2_hwaccel_select="vp9_decoder" vp9_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_VP9" vp9_dxva2_hwaccel_select="vp9_decoder" vp9_mediacodec_hwaccel_deps="mediacodec" +vp9_nvdec_hwaccel_deps="cuda nvdec" +vp9_nvdec_hwaccel_select="vp9_decoder" vp9_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferVP9_bit_depth" vp9_vaapi_hwaccel_select="vp9_decoder" wmv3_d3d11va_hwaccel_select="vc1_d3d11va_hwaccel" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 8c5dfd6319bb1..2476aecc4072e 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -869,6 +869,7 @@ OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL) += dxva2_vp9.o OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o +OBJS-$(CONFIG_VP9_NVDEC_HWACCEL) += nvdec_vp9.o OBJS-$(CONFIG_VP9_VAAPI_HWACCEL) += vaapi_vp9.o OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec_other.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index c817003693862..8ac9d9629d4bb 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -123,6 +123,7 @@ static void register_all(void) REGISTER_HWACCEL(VP9_D3D11VA2, vp9_d3d11va2); REGISTER_HWACCEL(VP9_DXVA2, vp9_dxva2); REGISTER_HWACCEL(VP9_MEDIACODEC, vp9_mediacodec); + REGISTER_HWACCEL(VP9_NVDEC, vp9_nvdec); REGISTER_HWACCEL(VP9_VAAPI, vp9_vaapi); REGISTER_HWACCEL(WMV3_D3D11VA, wmv3_d3d11va); REGISTER_HWACCEL(WMV3_D3D11VA2, wmv3_d3d11va2); diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index 274f69f997923..7d768b2327325 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -54,6 +54,7 @@ static int map_avcodec_id(enum AVCodecID id) switch (id) { case AV_CODEC_ID_H264: return cudaVideoCodec_H264; case AV_CODEC_ID_HEVC: return cudaVideoCodec_HEVC; + case AV_CODEC_ID_VP9: return cudaVideoCodec_VP9; } return -1; } diff --git a/libavcodec/nvdec_vp9.c b/libavcodec/nvdec_vp9.c new file mode 100644 index 0000000000000..06c13e6f033b3 --- /dev/null +++ b/libavcodec/nvdec_vp9.c @@ -0,0 +1,227 @@ +/* + * VP9 HW decode acceleration through NVDEC + * + * Copyright (c) 2016 Timo Rothenpieler + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/pixdesc.h" + +#include "avcodec.h" +#include "nvdec.h" +#include "decode.h" +#include "internal.h" +#include "vp9shared.h" + +static unsigned char get_ref_idx(AVFrame *frame) +{ + FrameDecodeData *fdd; + NVDECFrame *cf; + + if (!frame || !frame->private_ref) + return 255; + + fdd = (FrameDecodeData*)frame->private_ref->data; + cf = (NVDECFrame*)fdd->hwaccel_priv; + + return cf->idx; +} + +static int nvdec_vp9_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + VP9SharedContext *h = avctx->priv_data; + const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); + + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + CUVIDPICPARAMS *pp = &ctx->pic_params; + CUVIDVP9PICPARAMS *ppc = &pp->CodecSpecific.vp9; + FrameDecodeData *fdd; + NVDECFrame *cf; + AVFrame *cur_frame = h->frames[CUR_FRAME].tf.f; + + int ret, i; + + ret = ff_nvdec_start_frame(avctx, cur_frame); + if (ret < 0) + return ret; + + fdd = (FrameDecodeData*)cur_frame->private_ref->data; + cf = (NVDECFrame*)fdd->hwaccel_priv; + + *pp = (CUVIDPICPARAMS) { + .PicWidthInMbs = (cur_frame->width + 15) / 16, + .FrameHeightInMbs = (cur_frame->height + 15) / 16, + .CurrPicIdx = cf->idx, + + .CodecSpecific.vp9 = { + .width = cur_frame->width, + .height = cur_frame->height, + + .LastRefIdx = get_ref_idx(h->refs[h->h.refidx[0]].f), + .GoldenRefIdx = get_ref_idx(h->refs[h->h.refidx[1]].f), + .AltRefIdx = get_ref_idx(h->refs[h->h.refidx[2]].f), + + .profile = h->h.profile, + .frameContextIdx = h->h.framectxid, + .frameType = !h->h.keyframe, + .showFrame = !h->h.invisible, + .errorResilient = h->h.errorres, + .frameParallelDecoding = h->h.parallelmode, + .subSamplingX = pixdesc->log2_chroma_w, + .subSamplingY = pixdesc->log2_chroma_h, + .intraOnly = h->h.intraonly, + .allow_high_precision_mv = h->h.keyframe ? 0 : h->h.highprecisionmvs, + .refreshEntropyProbs = h->h.refreshctx, + + .bitDepthMinus8Luma = pixdesc->comp[0].depth - 8, + .bitDepthMinus8Chroma = pixdesc->comp[1].depth - 8, + + .loopFilterLevel = h->h.filter.level, + .loopFilterSharpness = h->h.filter.sharpness, + .modeRefLfEnabled = h->h.lf_delta.enabled, + + .log2_tile_columns = h->h.tiling.log2_tile_cols, + .log2_tile_rows = h->h.tiling.log2_tile_rows, + + .segmentEnabled = h->h.segmentation.enabled, + .segmentMapUpdate = h->h.segmentation.update_map, + .segmentMapTemporalUpdate = h->h.segmentation.temporal, + .segmentFeatureMode = h->h.segmentation.absolute_vals, + + .qpYAc = h->h.yac_qi, + .qpYDc = h->h.ydc_qdelta, + .qpChDc = h->h.uvdc_qdelta, + .qpChAc = h->h.uvac_qdelta, + + .resetFrameContext = h->h.resetctx, + .mcomp_filter_type = h->h.filtermode ^ (h->h.filtermode <= 1), + + .frameTagSize = h->h.uncompressed_header_size, + .offsetToDctParts = h->h.compressed_header_size, + + .refFrameSignBias[0] = 0, + } + }; + + for (i = 0; i < 2; i++) + ppc->mbModeLfDelta[i] = h->h.lf_delta.mode[i]; + + for (i = 0; i < 4; i++) + ppc->mbRefLfDelta[i] = h->h.lf_delta.ref[i]; + + for (i = 0; i < 7; i++) + ppc->mb_segment_tree_probs[i] = h->h.segmentation.prob[i]; + + for (i = 0; i < 3; i++) { + ppc->activeRefIdx[i] = h->h.refidx[i]; + ppc->segment_pred_probs[i] = h->h.segmentation.pred_prob[i]; + ppc->refFrameSignBias[i + 1] = h->h.signbias[i]; + } + + for (i = 0; i < 8; i++) { + ppc->segmentFeatureEnable[i][0] = h->h.segmentation.feat[i].q_enabled; + ppc->segmentFeatureEnable[i][1] = h->h.segmentation.feat[i].lf_enabled; + ppc->segmentFeatureEnable[i][2] = h->h.segmentation.feat[i].ref_enabled; + ppc->segmentFeatureEnable[i][3] = h->h.segmentation.feat[i].skip_enabled; + + ppc->segmentFeatureData[i][0] = h->h.segmentation.feat[i].q_val; + ppc->segmentFeatureData[i][1] = h->h.segmentation.feat[i].lf_val; + ppc->segmentFeatureData[i][2] = h->h.segmentation.feat[i].ref_val; + ppc->segmentFeatureData[i][3] = 0; + } + + switch (avctx->colorspace) { + default: + case AVCOL_SPC_UNSPECIFIED: + ppc->colorSpace = 0; + break; + case AVCOL_SPC_BT470BG: + ppc->colorSpace = 1; + break; + case AVCOL_SPC_BT709: + ppc->colorSpace = 2; + break; + case AVCOL_SPC_SMPTE170M: + ppc->colorSpace = 3; + break; + case AVCOL_SPC_SMPTE240M: + ppc->colorSpace = 4; + break; + case AVCOL_SPC_BT2020_NCL: + ppc->colorSpace = 5; + break; + case AVCOL_SPC_RESERVED: + ppc->colorSpace = 6; + break; + case AVCOL_SPC_RGB: + ppc->colorSpace = 7; + break; + } + + return 0; +} + +static int nvdec_vp9_end_frame(AVCodecContext *avctx) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + int ret = ff_nvdec_end_frame(avctx); + ctx->bitstream = NULL; + return ret; +} + +static int nvdec_vp9_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + void *tmp; + + tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated, + (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets)); + if (!tmp) + return AVERROR(ENOMEM); + ctx->slice_offsets = tmp; + + if (!ctx->bitstream) + ctx->bitstream = (uint8_t*)buffer; + + ctx->slice_offsets[ctx->nb_slices] = buffer - ctx->bitstream; + ctx->bitstream_len += size; + ctx->nb_slices++; + + return 0; +} + +static int nvdec_vp9_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) +{ + // VP9 uses a fixed size pool of 8 possible reference frames + return ff_nvdec_frame_params(avctx, hw_frames_ctx, 8); +} + +AVHWAccel ff_vp9_nvdec_hwaccel = { + .name = "vp9_nvdec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP9, + .pix_fmt = AV_PIX_FMT_CUDA, + .start_frame = nvdec_vp9_start_frame, + .end_frame = nvdec_vp9_end_frame, + .decode_slice = nvdec_vp9_decode_slice, + .frame_params = nvdec_vp9_frame_params, + .init = ff_nvdec_decode_init, + .uninit = ff_nvdec_decode_uninit, + .priv_data_size = sizeof(NVDECContext), +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 9c17e5716dcb5..9d1b0ee4c83e9 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 3 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index 6b5de19266f33..6ce9be61bb25a 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -169,7 +169,10 @@ static int vp9_frame_ref(AVCodecContext *avctx, VP9Frame *dst, VP9Frame *src) static int update_size(AVCodecContext *avctx, int w, int h) { -#define HWACCEL_MAX (CONFIG_VP9_DXVA2_HWACCEL + CONFIG_VP9_D3D11VA_HWACCEL * 2 + CONFIG_VP9_VAAPI_HWACCEL) +#define HWACCEL_MAX (CONFIG_VP9_DXVA2_HWACCEL + \ + CONFIG_VP9_D3D11VA_HWACCEL * 2 + \ + CONFIG_VP9_NVDEC_HWACCEL + \ + CONFIG_VP9_VAAPI_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts; VP9Context *s = avctx->priv_data; uint8_t *p; @@ -191,12 +194,18 @@ static int update_size(AVCodecContext *avctx, int w, int h) *fmtp++ = AV_PIX_FMT_D3D11VA_VLD; *fmtp++ = AV_PIX_FMT_D3D11; #endif +#if CONFIG_VP9_NVDEC_HWACCEL + *fmtp++ = AV_PIX_FMT_CUDA; +#endif #if CONFIG_VP9_VAAPI_HWACCEL *fmtp++ = AV_PIX_FMT_VAAPI; #endif break; case AV_PIX_FMT_YUV420P10: case AV_PIX_FMT_YUV420P12: +#if CONFIG_VP9_NVDEC_HWACCEL + *fmtp++ = AV_PIX_FMT_CUDA; +#endif #if CONFIG_VP9_VAAPI_HWACCEL *fmtp++ = AV_PIX_FMT_VAAPI; #endif From 538de4354dcd6c57154c5a5dec0744dcaa06b874 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sun, 12 Nov 2017 18:09:31 +0100 Subject: [PATCH 0887/2557] avcodec/nvdec: warn about thread count if applicable --- libavcodec/nvdec.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index 7d768b2327325..5d65f1d3ddb38 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -292,8 +292,15 @@ int ff_nvdec_decode_init(AVCodecContext *avctx) params.ulNumOutputSurfaces = 1; ret = nvdec_decoder_create(&ctx->decoder_ref, frames_ctx->device_ref, ¶ms, avctx); - if (ret < 0) + if (ret < 0) { + if (params.ulNumDecodeSurfaces > 32) { + av_log(avctx, AV_LOG_WARNING, "Using more than 32 (%d) decode surfaces might cause nvdec to fail.\n", + (int)params.ulNumDecodeSurfaces); + av_log(avctx, AV_LOG_WARNING, "Try lowering the amount of threads. Using %d right now.\n", + avctx->thread_count); + } return ret; + } pool = av_mallocz(sizeof(*pool)); if (!pool) { From 8bcf5840ea2a6a92c75ab3219f89fe0b8a53cf50 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sun, 12 Nov 2017 21:04:57 +0100 Subject: [PATCH 0888/2557] avcodec/nvdec: fix return value on error --- libavcodec/nvdec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index 5d65f1d3ddb38..ac68faca99242 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -414,8 +414,10 @@ int ff_nvdec_start_frame(AVCodecContext *avctx, AVFrame *frame) return AVERROR(ENOMEM); cf->decoder_ref = av_buffer_ref(ctx->decoder_ref); - if (!cf->decoder_ref) + if (!cf->decoder_ref) { + ret = AVERROR(ENOMEM); goto fail; + } cf->idx_ref = av_buffer_pool_get(ctx->decoder_pool); if (!cf->idx_ref) { From 237ccd8a165d2128e8c6bcb14c8c6c3e793cfe05 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Wed, 8 Nov 2017 19:17:45 +0100 Subject: [PATCH 0889/2557] lavfi/paletteuse: check get_color return value Fixes CID #1420396 --- libavfilter/vf_paletteuse.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index ed80ab04d5e9e..1980907e70eca 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -380,8 +380,11 @@ static av_always_inline int get_dst_color_err(PaletteUseContext *s, const uint8_t r = c >> 16 & 0xff; const uint8_t g = c >> 8 & 0xff; const uint8_t b = c & 0xff; + uint32_t dstc; const int dstx = color_get(s, c, a, r, g, b, search_method); - const uint32_t dstc = s->palette[dstx]; + if (dstx < 0) + return dstx; + dstc = s->palette[dstx]; *er = r - (dstc >> 16 & 0xff); *eg = g - (dstc >> 8 & 0xff); *eb = b - (dstc & 0xff); From 284b432662b6e137148ff9d13ef2b554cb14b4ae Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Wed, 8 Nov 2017 19:17:49 +0100 Subject: [PATCH 0890/2557] avformat/fitsenc: validate input pixel format Fixes CID #1416961 and #1416962 --- libavformat/fitsenc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/fitsenc.c b/libavformat/fitsenc.c index 7cb171596c4e2..cc3999aa8a0c7 100644 --- a/libavformat/fitsenc.c +++ b/libavformat/fitsenc.c @@ -106,6 +106,8 @@ static int write_image_header(AVFormatContext *s) } bzero = 32768; break; + default: + return AVERROR(EINVAL); } if (fitsctx->first_image) { @@ -166,7 +168,9 @@ static int write_image_header(AVFormatContext *s) static int fits_write_packet(AVFormatContext *s, AVPacket *pkt) { - write_image_header(s); + int ret = write_image_header(s); + if (ret < 0) + return ret; avio_write(s->pb, pkt->data, pkt->size); return 0; } From c7ded42d5dfc0124008b5b9b13a1a342324885ed Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Wed, 8 Nov 2017 19:17:51 +0100 Subject: [PATCH 0891/2557] avfilter/vf_premultiply: fix memory-leak on failure Fixes CID #1416352 --- libavfilter/vf_premultiply.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_premultiply.c b/libavfilter/vf_premultiply.c index 5120adc476693..df4f26578d114 100644 --- a/libavfilter/vf_premultiply.c +++ b/libavfilter/vf_premultiply.c @@ -607,9 +607,10 @@ static int activate(AVFilterContext *ctx) int64_t pts; if ((ret = ff_inlink_consume_frame(ctx->inputs[0], &frame)) > 0) { - if ((ret = filter_frame(ctx, &out, frame, frame)) < 0) - return ret; + ret = filter_frame(ctx, &out, frame, frame); av_frame_free(&frame); + if (ret < 0) + return ret; ret = ff_filter_frame(ctx->outputs[0], out); } if (ret < 0) { From de6a1e32fd483db05d957268d5e45e2b1be9cab4 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Wed, 8 Nov 2017 19:17:52 +0100 Subject: [PATCH 0892/2557] movenc-test: fix potential uninitialized read Fixes CID #1413023 --- libavformat/tests/movenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/tests/movenc.c b/libavformat/tests/movenc.c index 8e59b74259e92..ad6c92a94c96c 100644 --- a/libavformat/tests/movenc.c +++ b/libavformat/tests/movenc.c @@ -115,6 +115,7 @@ static int io_write_data_type(void *opaque, uint8_t *buf, int size, case AVIO_DATA_MARKER_BOUNDARY_POINT: str = "boundary"; break; case AVIO_DATA_MARKER_UNKNOWN: str = "unknown"; break; case AVIO_DATA_MARKER_TRAILER: str = "trailer"; break; + default: str = "unknown"; break; } if (time == AV_NOPTS_VALUE) snprintf(timebuf, sizeof(timebuf), "nopts"); From e7e7d56a850d34d710c45463607abac846972f57 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 13 Nov 2017 17:37:56 -0300 Subject: [PATCH 0893/2557] Makefile: fix distclean target It must imply clean. Regression since e0087a5624117a1d643e2cb433ecc4d536756dda. Signed-off-by: James Almer --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 28af3debef4c1..9defddebfdaed 100644 --- a/Makefile +++ b/Makefile @@ -138,7 +138,7 @@ clean:: $(RM) -r coverage-html $(RM) -rf coverage.info coverage.info.in lcov -distclean:: +distclean:: clean $(RM) .version avversion.h config.asm config.h mapfile \ ffbuild/.config ffbuild/config.* libavutil/avconfig.h \ version.h libavutil/ffversion.h libavcodec/codec_names.h \ From a36a3d7fecdfc50691f01eef984cad6cedb6fb3a Mon Sep 17 00:00:00 2001 From: Rodger Combs Date: Mon, 13 Nov 2017 14:46:17 -0600 Subject: [PATCH 0894/2557] lavf/tls_securetransport: handle incomplete reads gracefully Signed-off-by: Aman Gupta --- libavformat/tls_securetransport.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/libavformat/tls_securetransport.c b/libavformat/tls_securetransport.c index b862e0003a0d4..dc32eb1fa898d 100644 --- a/libavformat/tls_securetransport.c +++ b/libavformat/tls_securetransport.c @@ -54,7 +54,7 @@ static int print_tls_error(URLContext *h, int ret) TLSContext *c = h->priv_data; switch (ret) { case errSSLWouldBlock: - break; + return AVERROR(EAGAIN); case errSSLXCertChainInvalid: av_log(h, AV_LOG_ERROR, "Invalid certificate chain\n"); return AVERROR(EIO); @@ -197,7 +197,8 @@ static OSStatus tls_read_cb(SSLConnectionRef connection, void *data, size_t *dat { URLContext *h = (URLContext*)connection; TLSContext *c = h->priv_data; - int read = ffurl_read_complete(c->tls_shared.tcp, data, *dataLength); + size_t requested = *dataLength; + int read = ffurl_read(c->tls_shared.tcp, data, requested); if (read <= 0) { *dataLength = 0; switch(AVUNERROR(read)) { @@ -214,7 +215,10 @@ static OSStatus tls_read_cb(SSLConnectionRef connection, void *data, size_t *dat } } else { *dataLength = read; - return noErr; + if (read < requested) + return errSSLWouldBlock; + else + return noErr; } } @@ -326,12 +330,13 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op if (peerTrust) CFRelease(peerTrust); } - if (status == noErr) + if (status == noErr) { break; - - av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session: %i\n", (int)status); - ret = AVERROR(EIO); - goto fail; + } else if (status != errSSLWouldBlock) { + av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session: %i\n", (int)status); + ret = AVERROR(EIO); + goto fail; + } } return 0; @@ -348,6 +353,9 @@ static int map_ssl_error(OSStatus status, size_t processed) case errSSLClosedGraceful: case errSSLClosedNoNotify: return 0; + case errSSLWouldBlock: + if (processed > 0) + return processed; default: return (int)status; } From 9c8922acadb5187c274250d6cde653b7bad2559e Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 13 Nov 2017 15:02:44 -0600 Subject: [PATCH 0895/2557] This fixes a deadlock while reading a chunked https response, if multiple_requests=1 is also set. Without an EOF to signal the end of the last chunk, tls_read gets stuck forever trying to read more data than is available. This occurs with the http protocol reproducibly, because http.c always reads 4kb at a time, and the last chunk of an http response is often much smaller. After this commit, tls_read always returns any buffered plaintext first before attempting to read more encrypted data off the underlying tcp socket. Signed-off-by: Rodger Combs --- libavformat/tls_securetransport.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavformat/tls_securetransport.c b/libavformat/tls_securetransport.c index dc32eb1fa898d..37380541b11c9 100644 --- a/libavformat/tls_securetransport.c +++ b/libavformat/tls_securetransport.c @@ -364,8 +364,12 @@ static int map_ssl_error(OSStatus status, size_t processed) static int tls_read(URLContext *h, uint8_t *buf, int size) { TLSContext *c = h->priv_data; - size_t processed = 0; - int ret = SSLRead(c->ssl_context, buf, size, &processed); + size_t available = 0, processed = 0; + int ret; + SSLGetBufferedReadSize(c->ssl_context, &available); + if (available) + size = FFMIN(available, size); + ret = SSLRead(c->ssl_context, buf, size, &processed); ret = map_ssl_error(ret, processed); if (ret > 0) return ret; From 681c638fab4ed4699e7fd5cf119606910a1f75ba Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Mon, 13 Nov 2017 21:55:09 +0100 Subject: [PATCH 0896/2557] configure: fix cuda dependency on nvdec --- configure | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/configure b/configure index da6d6449007f5..3f0a7cd9d6b3b 100755 --- a/configure +++ b/configure @@ -2651,6 +2651,7 @@ cuda_deps_any="libdl LoadLibrary" cuvid_deps="cuda" d3d11va_deps="dxva_h ID3D11VideoDecoder ID3D11VideoContext" dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" +nvdec_deps="cuda" videotoolbox_hwaccel_deps="videotoolbox pthreads" videotoolbox_hwaccel_extralibs="-framework QuartzCore" xvmc_deps="X11_extensions_XvMClib_h" @@ -2669,7 +2670,7 @@ h264_dxva2_hwaccel_deps="dxva2" h264_dxva2_hwaccel_select="h264_decoder" h264_mediacodec_hwaccel_deps="mediacodec" h264_mmal_hwaccel_deps="mmal" -h264_nvdec_hwaccel_deps="cuda nvdec" +h264_nvdec_hwaccel_deps="nvdec" h264_nvdec_hwaccel_select="h264_decoder" h264_qsv_hwaccel_deps="libmfx" h264_vaapi_hwaccel_deps="vaapi" @@ -2687,7 +2688,7 @@ hevc_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" hevc_d3d11va2_hwaccel_select="hevc_decoder" hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC" hevc_dxva2_hwaccel_select="hevc_decoder" -hevc_nvdec_hwaccel_deps="cuda nvdec" +hevc_nvdec_hwaccel_deps="nvdec" hevc_nvdec_hwaccel_select="hevc_decoder" hevc_qsv_hwaccel_deps="libmfx" hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC" @@ -2764,7 +2765,7 @@ vp9_d3d11va2_hwaccel_select="vp9_decoder" vp9_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_VP9" vp9_dxva2_hwaccel_select="vp9_decoder" vp9_mediacodec_hwaccel_deps="mediacodec" -vp9_nvdec_hwaccel_deps="cuda nvdec" +vp9_nvdec_hwaccel_deps="nvdec" vp9_nvdec_hwaccel_select="vp9_decoder" vp9_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferVP9_bit_depth" vp9_vaapi_hwaccel_select="vp9_decoder" From 578addcff64f14783cce3171fdd158602edd757b Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Mon, 13 Nov 2017 22:01:53 +0100 Subject: [PATCH 0897/2557] configure: factorize nvdec dependencies --- configure | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/configure b/configure index 3f0a7cd9d6b3b..4418352d305cd 100755 --- a/configure +++ b/configure @@ -2660,7 +2660,6 @@ h263_vaapi_hwaccel_deps="vaapi" h263_vaapi_hwaccel_select="h263_decoder" h263_videotoolbox_hwaccel_deps="videotoolbox" h263_videotoolbox_hwaccel_select="h263_decoder" -h264_cuvid_hwaccel_deps="cuda cuvid" h264_cuvid_hwaccel_select="h264_cuvid_decoder" h264_d3d11va_hwaccel_deps="d3d11va" h264_d3d11va_hwaccel_select="h264_decoder" @@ -2679,7 +2678,6 @@ h264_vdpau_hwaccel_deps="vdpau" h264_vdpau_hwaccel_select="h264_decoder" h264_videotoolbox_hwaccel_deps="videotoolbox" h264_videotoolbox_hwaccel_select="h264_decoder" -hevc_cuvid_hwaccel_deps="cuda cuvid" hevc_cuvid_hwaccel_select="hevc_cuvid_decoder" hevc_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" hevc_d3d11va_hwaccel_select="hevc_decoder" @@ -2697,11 +2695,9 @@ hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC" hevc_vdpau_hwaccel_select="hevc_decoder" hevc_videotoolbox_hwaccel_deps="videotoolbox" hevc_videotoolbox_hwaccel_select="hevc_decoder" -mjpeg_cuvid_hwaccel_deps="cuda cuvid" mjpeg_cuvid_hwaccel_select="mjpeg_cuvid_decoder" mpeg_xvmc_hwaccel_deps="xvmc" mpeg_xvmc_hwaccel_select="mpeg2video_decoder" -mpeg1_cuvid_hwaccel_deps="cuda cuvid" mpeg1_cuvid_hwaccel_select="mpeg1_cuvid_decoder" mpeg1_vdpau_hwaccel_deps="vdpau" mpeg1_vdpau_hwaccel_select="mpeg1video_decoder" @@ -2709,7 +2705,6 @@ mpeg1_videotoolbox_hwaccel_deps="videotoolbox" mpeg1_videotoolbox_hwaccel_select="mpeg1video_decoder" mpeg1_xvmc_hwaccel_deps="xvmc" mpeg1_xvmc_hwaccel_select="mpeg1video_decoder" -mpeg2_cuvid_hwaccel_deps="cuda cuvid" mpeg2_cuvid_hwaccel_select="mpeg2_cuvid_decoder" mpeg2_d3d11va_hwaccel_deps="d3d11va" mpeg2_d3d11va_hwaccel_select="mpeg2video_decoder" @@ -2728,7 +2723,6 @@ mpeg2_videotoolbox_hwaccel_deps="videotoolbox" mpeg2_videotoolbox_hwaccel_select="mpeg2video_decoder" mpeg2_xvmc_hwaccel_deps="xvmc" mpeg2_xvmc_hwaccel_select="mpeg2video_decoder" -mpeg4_cuvid_hwaccel_deps="cuda cuvid" mpeg4_cuvid_hwaccel_select="mpeg4_cuvid_decoder" mpeg4_mediacodec_hwaccel_deps="mediacodec" mpeg4_mmal_hwaccel_deps="mmal" @@ -2738,7 +2732,6 @@ mpeg4_vdpau_hwaccel_deps="vdpau" mpeg4_vdpau_hwaccel_select="mpeg4_decoder" mpeg4_videotoolbox_hwaccel_deps="videotoolbox" mpeg4_videotoolbox_hwaccel_select="mpeg4_decoder" -vc1_cuvid_hwaccel_deps="cuda cuvid" vc1_cuvid_hwaccel_select="vc1_cuvid_decoder" vc1_d3d11va_hwaccel_deps="d3d11va" vc1_d3d11va_hwaccel_select="vc1_decoder" @@ -2752,9 +2745,7 @@ vc1_vaapi_hwaccel_deps="vaapi" vc1_vaapi_hwaccel_select="vc1_decoder" vc1_vdpau_hwaccel_deps="vdpau" vc1_vdpau_hwaccel_select="vc1_decoder" -vp8_cuvid_hwaccel_deps="cuda cuvid" vp8_cuvid_hwaccel_select="vp8_cuvid_decoder" -vp9_cuvid_hwaccel_deps="cuda cuvid" vp9_cuvid_hwaccel_select="vp9_cuvid_decoder" vp8_mediacodec_hwaccel_deps="mediacodec" vp8_qsv_hwaccel_deps="libmfx" @@ -2797,7 +2788,7 @@ nvenc_encoder_deps="nvenc" h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m" h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m" h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser" -h264_cuvid_decoder_deps="cuda cuvid" +h264_cuvid_decoder_deps="cuvid" h264_cuvid_decoder_select="h264_mp4toannexb_bsf" h264_mediacodec_decoder_deps="mediacodec" h264_mediacodec_decoder_select="h264_mp4toannexb_bsf h264_parser" @@ -2812,7 +2803,7 @@ h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" h264_vaapi_encoder_select="cbs_h264 vaapi_encode" h264_v4l2m2m_decoder_deps="v4l2_m2m h264_v4l2_m2m" h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m" -hevc_cuvid_decoder_deps="cuda cuvid" +hevc_cuvid_decoder_deps="cuvid" hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf" hevc_mediacodec_decoder_deps="mediacodec" hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser" @@ -2825,15 +2816,15 @@ hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" hevc_vaapi_encoder_select="cbs_h265 vaapi_encode" hevc_v4l2m2m_decoder_deps="v4l2_m2m hevc_v4l2_m2m" hevc_v4l2m2m_encoder_deps="v4l2_m2m hevc_v4l2_m2m" -mjpeg_cuvid_decoder_deps="cuda cuvid" +mjpeg_cuvid_decoder_deps="cuvid" mjpeg_qsv_encoder_deps="libmfx" mjpeg_qsv_encoder_select="qsvenc" mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG" mjpeg_vaapi_encoder_select="vaapi_encode jpegtables" -mpeg1_cuvid_decoder_deps="cuda cuvid" +mpeg1_cuvid_decoder_deps="cuvid" mpeg1_v4l2m2m_decoder_deps="v4l2_m2m mpeg1_v4l2_m2m" mpeg2_crystalhd_decoder_select="crystalhd" -mpeg2_cuvid_decoder_deps="cuda cuvid" +mpeg2_cuvid_decoder_deps="cuvid" mpeg2_mmal_decoder_deps="mmal" mpeg2_mediacodec_decoder_deps="mediacodec" mpeg2_qsv_decoder_select="qsvdec mpeg2_qsv_hwaccel" @@ -2842,7 +2833,7 @@ mpeg2_vaapi_encoder_deps="VAEncPictureParameterBufferMPEG2" mpeg2_vaapi_encoder_select="cbs_mpeg2 vaapi_encode" mpeg2_v4l2m2m_decoder_deps="v4l2_m2m mpeg2_v4l2_m2m" mpeg4_crystalhd_decoder_select="crystalhd" -mpeg4_cuvid_decoder_deps="cuda cuvid" +mpeg4_cuvid_decoder_deps="cuvid" mpeg4_mediacodec_decoder_deps="mediacodec" mpeg4_mmal_decoder_deps="mmal" mpeg4_omx_encoder_deps="omx" @@ -2852,11 +2843,11 @@ msmpeg4_crystalhd_decoder_select="crystalhd" nvenc_h264_encoder_select="h264_nvenc_encoder" nvenc_hevc_encoder_select="hevc_nvenc_encoder" vc1_crystalhd_decoder_select="crystalhd" -vc1_cuvid_decoder_deps="cuda cuvid" +vc1_cuvid_decoder_deps="cuvid" vc1_mmal_decoder_deps="mmal" vc1_qsv_decoder_select="qsvdec vc1_qsv_hwaccel vc1_parser" vc1_v4l2m2m_decoder_deps="v4l2_m2m vc1_v4l2_m2m" -vp8_cuvid_decoder_deps="cuda cuvid" +vp8_cuvid_decoder_deps="cuvid" vp8_mediacodec_decoder_deps="mediacodec" vp8_qsv_decoder_select="qsvdec vp8_qsv_hwaccel vp8_parser" vp8_rkmpp_decoder_deps="rkmpp" @@ -2864,7 +2855,7 @@ vp8_vaapi_encoder_deps="VAEncPictureParameterBufferVP8" vp8_vaapi_encoder_select="vaapi_encode" vp8_v4l2m2m_decoder_deps="v4l2_m2m vp8_v4l2_m2m" vp8_v4l2m2m_encoder_deps="v4l2_m2m vp8_v4l2_m2m" -vp9_cuvid_decoder_deps="cuda cuvid" +vp9_cuvid_decoder_deps="cuvid" vp9_mediacodec_decoder_deps="mediacodec" vp9_rkmpp_decoder_deps="rkmpp" vp9_vaapi_encoder_deps="VAEncPictureParameterBufferVP9" From e7a5249ab1775827a331c48e4d236eda52d51575 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Sun, 12 Nov 2017 10:19:17 -0800 Subject: [PATCH 0898/2557] avcodec/videotoolboxenc: add hevc_videotoolbox encoder Signed-off-by: Aman Gupta Reviewed-by: Rodger Combs --- configure | 2 + libavcodec/allcodecs.c | 1 + libavcodec/videotoolboxenc.c | 168 +++++++++++++++++++++++++++++------ 3 files changed, 146 insertions(+), 25 deletions(-) diff --git a/configure b/configure index 4418352d305cd..3788f26956ec7 100755 --- a/configure +++ b/configure @@ -2918,6 +2918,8 @@ pcm_mulaw_at_encoder_select="audio_frame_queue" chromaprint_muxer_deps="chromaprint" h264_videotoolbox_encoder_deps="pthreads" h264_videotoolbox_encoder_select="videotoolbox_encoder" +hevc_videotoolbox_encoder_deps="pthreads" +hevc_videotoolbox_encoder_select="videotoolbox_encoder" libcelt_decoder_deps="libcelt" libfdk_aac_decoder_deps="libfdk_aac" libfdk_aac_encoder_deps="libfdk_aac" diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 8ac9d9629d4bb..0781862de5126 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -671,6 +671,7 @@ static void register_all(void) REGISTER_ENCODER(HEVC_QSV, hevc_qsv); REGISTER_ENCODER(HEVC_V4L2M2M, hevc_v4l2m2m); REGISTER_ENCODER(HEVC_VAAPI, hevc_vaapi); + REGISTER_ENCODER(HEVC_VIDEOTOOLBOX, hevc_videotoolbox); REGISTER_ENCODER(LIBKVAZAAR, libkvazaar); REGISTER_DECODER(MJPEG_CUVID, mjpeg_cuvid); REGISTER_ENCODER(MJPEG_QSV, mjpeg_qsv); diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index eba6cc672f81d..7b50edbb8fa7a 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -35,6 +35,17 @@ #include "h264_sei.h" #include +#if !HAVE_KCMVIDEOCODECTYPE_HEVC +enum { kCMVideoCodecType_HEVC = 'hvc1' }; +#endif + +typedef OSStatus (*getParameterSetAtIndex)(CMFormatDescriptionRef videoDesc, + size_t parameterSetIndex, + const uint8_t * _Nullable *parameterSetPointerOut, + size_t *parameterSetSizeOut, + size_t *parameterSetCountOut, + int *NALUnitHeaderLengthOut); + //These symbols may not be present static struct{ CFStringRef kCVImageBufferColorPrimaries_ITU_R_2020; @@ -65,10 +76,15 @@ static struct{ CFStringRef kVTProfileLevel_H264_High_5_2; CFStringRef kVTProfileLevel_H264_High_AutoLevel; + CFStringRef kVTProfileLevel_HEVC_Main_AutoLevel; + CFStringRef kVTProfileLevel_HEVC_Main10_AutoLevel; + CFStringRef kVTCompressionPropertyKey_RealTime; CFStringRef kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder; CFStringRef kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder; + + getParameterSetAtIndex CMVideoFormatDescriptionGetHEVCParameterSetAtIndex; } compat_keys; #define GET_SYM(symbol, defaultVal) \ @@ -83,6 +99,12 @@ do{ \ static pthread_once_t once_ctrl = PTHREAD_ONCE_INIT; static void loadVTEncSymbols(){ + compat_keys.CMVideoFormatDescriptionGetHEVCParameterSetAtIndex = + (getParameterSetAtIndex)dlsym( + RTLD_DEFAULT, + "CMVideoFormatDescriptionGetHEVCParameterSetAtIndex" + ); + GET_SYM(kCVImageBufferColorPrimaries_ITU_R_2020, "ITU_R_2020"); GET_SYM(kCVImageBufferTransferFunction_ITU_R_2020, "ITU_R_2020"); GET_SYM(kCVImageBufferYCbCrMatrix_ITU_R_2020, "ITU_R_2020"); @@ -111,6 +133,9 @@ static void loadVTEncSymbols(){ GET_SYM(kVTProfileLevel_H264_High_5_2, "H264_High_5_2"); GET_SYM(kVTProfileLevel_H264_High_AutoLevel, "H264_High_AutoLevel"); + GET_SYM(kVTProfileLevel_HEVC_Main_AutoLevel, "HEVC_Main_AutoLevel"); + GET_SYM(kVTProfileLevel_HEVC_Main10_AutoLevel, "HEVC_Main10_AutoLevel"); + GET_SYM(kVTCompressionPropertyKey_RealTime, "RealTime"); GET_SYM(kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder, @@ -133,6 +158,13 @@ typedef enum VTH264Entropy{ VT_CABAC } VTH264Entropy; +typedef enum VT_HEVCProfile { + HEVC_PROF_AUTO, + HEVC_PROF_MAIN, + HEVC_PROF_MAIN10, + HEVC_PROF_COUNT +} VT_HEVCProfile; + static const uint8_t start_code[] = { 0, 0, 0, 1 }; typedef struct ExtraSEI { @@ -149,10 +181,12 @@ typedef struct BufNode { typedef struct VTEncContext { AVClass *class; + enum AVCodecID codec_id; VTCompressionSessionRef session; CFStringRef ycbcr_matrix; CFStringRef color_primaries; CFStringRef transfer_function; + getParameterSetAtIndex get_param_set_func; pthread_mutex_t lock; pthread_cond_t cv_sample_sent; @@ -348,6 +382,7 @@ static CMVideoCodecType get_cm_codec_type(enum AVCodecID id) { switch (id) { case AV_CODEC_ID_H264: return kCMVideoCodecType_H264; + case AV_CODEC_ID_HEVC: return kCMVideoCodecType_HEVC; default: return 0; } } @@ -365,12 +400,13 @@ static int get_params_size( CMVideoFormatDescriptionRef vid_fmt, size_t *size) { + VTEncContext *vtctx = avctx->priv_data; size_t total_size = 0; size_t ps_count; int is_count_bad = 0; size_t i; int status; - status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt, + status = vtctx->get_param_set_func(vid_fmt, 0, NULL, NULL, @@ -385,7 +421,7 @@ static int get_params_size( for (i = 0; i < ps_count || is_count_bad; i++) { const uint8_t *ps; size_t ps_size; - status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt, + status = vtctx->get_param_set_func(vid_fmt, i, &ps, &ps_size, @@ -419,13 +455,14 @@ static int copy_param_sets( uint8_t *dst, size_t dst_size) { + VTEncContext *vtctx = avctx->priv_data; size_t ps_count; int is_count_bad = 0; int status; size_t offset = 0; size_t i; - status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt, + status = vtctx->get_param_set_func(vid_fmt, 0, NULL, NULL, @@ -443,7 +480,7 @@ static int copy_param_sets( size_t ps_size; size_t next_offset; - status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt, + status = vtctx->get_param_set_func(vid_fmt, i, &ps, &ps_size, @@ -548,6 +585,7 @@ static int get_length_code_size( CMSampleBufferRef sample_buffer, size_t *size) { + VTEncContext *vtctx = avctx->priv_data; CMVideoFormatDescriptionRef vid_fmt; int isize; int status; @@ -558,7 +596,7 @@ static int get_length_code_size( return AVERROR_EXTERNAL; } - status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt, + status = vtctx->get_param_set_func(vid_fmt, 0, NULL, NULL, @@ -579,8 +617,8 @@ static int get_length_code_size( * If profile_level_val is NULL and this method returns true, don't specify the * profile/level to the encoder. */ -static bool get_vt_profile_level(AVCodecContext *avctx, - CFStringRef *profile_level_val) +static bool get_vt_h264_profile_level(AVCodecContext *avctx, + CFStringRef *profile_level_val) { VTEncContext *vtctx = avctx->priv_data; int64_t profile = vtctx->profile; @@ -670,6 +708,41 @@ static bool get_vt_profile_level(AVCodecContext *avctx, return true; } +/* + * Returns true on success. + * + * If profile_level_val is NULL and this method returns true, don't specify the + * profile/level to the encoder. + */ +static bool get_vt_hevc_profile_level(AVCodecContext *avctx, + CFStringRef *profile_level_val) +{ + VTEncContext *vtctx = avctx->priv_data; + int64_t profile = vtctx->profile; + + *profile_level_val = NULL; + + switch (profile) { + case HEVC_PROF_AUTO: + return true; + case HEVC_PROF_MAIN: + *profile_level_val = + compat_keys.kVTProfileLevel_HEVC_Main_AutoLevel; + break; + case HEVC_PROF_MAIN10: + *profile_level_val = + compat_keys.kVTProfileLevel_HEVC_Main10_AutoLevel; + break; + } + + if (!*profile_level_val) { + av_log(avctx, AV_LOG_ERROR, "Invalid Profile/Level.\n"); + return false; + } + + return true; +} + static int get_cv_pixel_format(AVCodecContext* avctx, enum AVPixelFormat fmt, enum AVColorRange range, @@ -944,6 +1017,8 @@ static int vtenc_create_encoder(AVCodecContext *avctx, return AVERROR_EXTERNAL; } + if (vtctx->codec_id == AV_CODEC_ID_H264) { + // kVTCompressionPropertyKey_DataRateLimits is not available for HEVC bytes_per_second_value = max_rate >> 3; bytes_per_second = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, @@ -959,10 +1034,10 @@ static int vtenc_create_encoder(AVCodecContext *avctx, CFRelease(bytes_per_second); return AVERROR(ENOMEM); } - nums[0] = bytes_per_second; - nums[1] = one_second; + nums[0] = (void *)bytes_per_second; + nums[1] = (void *)one_second; data_rate_limits = CFArrayCreate(kCFAllocatorDefault, - nums, + (const void **)nums, 2, &kCFTypeArrayCallBacks); @@ -992,6 +1067,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "Error setting profile/level property: %d\n", status); } } + } if (avctx->gop_size > 0) { CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault, @@ -1205,6 +1281,11 @@ static av_cold int vtenc_init(AVCodecContext *avctx) return AVERROR(EINVAL); } + vtctx->codec_id = avctx->codec_id; + + if (vtctx->codec_id == AV_CODEC_ID_H264) { + vtctx->get_param_set_func = CMVideoFormatDescriptionGetH264ParameterSetAtIndex; + vtctx->has_b_frames = avctx->max_b_frames > 0; if(vtctx->has_b_frames && vtctx->profile == H264_PROF_BASELINE){ av_log(avctx, AV_LOG_WARNING, "Cannot use B-frames with baseline profile. Output will not contain B-frames.\n"); @@ -1216,7 +1297,12 @@ static av_cold int vtenc_init(AVCodecContext *avctx) vtctx->entropy = VT_ENTROPY_NOT_SET; } - if (!get_vt_profile_level(avctx, &profile_level)) return AVERROR(EINVAL); + if (!get_vt_h264_profile_level(avctx, &profile_level)) return AVERROR(EINVAL); + } else { + vtctx->get_param_set_func = compat_keys.CMVideoFormatDescriptionGetHEVCParameterSetAtIndex; + if (!vtctx->get_param_set_func) return AVERROR(EINVAL); + if (!get_vt_hevc_profile_level(avctx, &profile_level)) return AVERROR(EINVAL); + } vtctx->session = NULL; @@ -2424,9 +2510,19 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_NONE }; -#define OFFSET(x) offsetof(VTEncContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM -static const AVOption options[] = { +#define COMMON_OPTIONS \ + { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL, \ + { .i64 = 0 }, 0, 1, VE }, \ + { "realtime", "Hint that encoding should happen in real-time if not faster (e.g. capturing from camera).", \ + OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \ + { "frames_before", "Other frames will come before the frames in this session. This helps smooth concatenation issues.", \ + OFFSET(frames_before), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \ + { "frames_after", "Other frames will come after the frames in this session. This helps smooth concatenation issues.", \ + OFFSET(frames_after), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + +#define OFFSET(x) offsetof(VTEncContext, x) +static const AVOption h264_options[] = { { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = H264_PROF_AUTO }, H264_PROF_AUTO, H264_PROF_COUNT, VE, "profile" }, { "baseline", "Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, @@ -2444,32 +2540,22 @@ static const AVOption options[] = { { "5.1", "Level 5.1", 0, AV_OPT_TYPE_CONST, { .i64 = 51 }, INT_MIN, INT_MAX, VE, "level" }, { "5.2", "Level 5.2", 0, AV_OPT_TYPE_CONST, { .i64 = 52 }, INT_MIN, INT_MAX, VE, "level" }, - { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL, - { .i64 = 0 }, 0, 1, VE }, - { "coder", "Entropy coding", OFFSET(entropy), AV_OPT_TYPE_INT, { .i64 = VT_ENTROPY_NOT_SET }, VT_ENTROPY_NOT_SET, VT_CABAC, VE, "coder" }, { "cavlc", "CAVLC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CAVLC }, INT_MIN, INT_MAX, VE, "coder" }, { "vlc", "CAVLC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CAVLC }, INT_MIN, INT_MAX, VE, "coder" }, { "cabac", "CABAC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CABAC }, INT_MIN, INT_MAX, VE, "coder" }, { "ac", "CABAC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CABAC }, INT_MIN, INT_MAX, VE, "coder" }, - { "realtime", "Hint that encoding should happen in real-time if not faster (e.g. capturing from camera).", - OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - - { "frames_before", "Other frames will come before the frames in this session. This helps smooth concatenation issues.", - OFFSET(frames_before), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - { "frames_after", "Other frames will come after the frames in this session. This helps smooth concatenation issues.", - OFFSET(frames_after), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - { "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, VE }, + COMMON_OPTIONS { NULL }, }; static const AVClass h264_videotoolbox_class = { .class_name = "h264_videotoolbox", .item_name = av_default_item_name, - .option = options, + .option = h264_options, .version = LIBAVUTIL_VERSION_INT, }; @@ -2488,3 +2574,35 @@ AVCodec ff_h264_videotoolbox_encoder = { .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; + +static const AVOption hevc_options[] = { + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = HEVC_PROF_AUTO }, HEVC_PROF_AUTO, HEVC_PROF_COUNT, VE, "profile" }, + { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = HEVC_PROF_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, + { "main10", "Main10 Profile", 0, AV_OPT_TYPE_CONST, { .i64 = HEVC_PROF_MAIN10 }, INT_MIN, INT_MAX, VE, "profile" }, + + COMMON_OPTIONS + { NULL }, +}; + +static const AVClass hevc_videotoolbox_class = { + .class_name = "hevc_videotoolbox", + .item_name = av_default_item_name, + .option = hevc_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_hevc_videotoolbox_encoder = { + .name = "hevc_videotoolbox", + .long_name = NULL_IF_CONFIG_SMALL("VideoToolbox H.265 Encoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .priv_data_size = sizeof(VTEncContext), + .pix_fmts = pix_fmts, + .init = vtenc_init, + .encode2 = vtenc_frame, + .close = vtenc_close, + .capabilities = AV_CODEC_CAP_DELAY, + .priv_class = &hevc_videotoolbox_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; From 230b91cdfdd1949f9b1719d5d91d77caad90aaae Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Sun, 12 Nov 2017 10:20:17 -0800 Subject: [PATCH 0899/2557] avcodec/videotoolboxenc: re-indent code Cosmetic change only. Signed-off-by: Aman Gupta --- libavcodec/videotoolboxenc.c | 158 +++++++++++++++++------------------ 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 7b50edbb8fa7a..93338eabde2a7 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -407,11 +407,11 @@ static int get_params_size( size_t i; int status; status = vtctx->get_param_set_func(vid_fmt, - 0, - NULL, - NULL, - &ps_count, - NULL); + 0, + NULL, + NULL, + &ps_count, + NULL); if (status) { is_count_bad = 1; ps_count = 0; @@ -422,11 +422,11 @@ static int get_params_size( const uint8_t *ps; size_t ps_size; status = vtctx->get_param_set_func(vid_fmt, - i, - &ps, - &ps_size, - NULL, - NULL); + i, + &ps, + &ps_size, + NULL, + NULL); if (status) { /* * When ps_count is invalid, status != 0 ends the loop normally @@ -463,11 +463,11 @@ static int copy_param_sets( size_t i; status = vtctx->get_param_set_func(vid_fmt, - 0, - NULL, - NULL, - &ps_count, - NULL); + 0, + NULL, + NULL, + &ps_count, + NULL); if (status) { is_count_bad = 1; ps_count = 0; @@ -481,11 +481,11 @@ static int copy_param_sets( size_t next_offset; status = vtctx->get_param_set_func(vid_fmt, - i, - &ps, - &ps_size, - NULL, - NULL); + i, + &ps, + &ps_size, + NULL, + NULL); if (status) { if (i > 0 && is_count_bad) status = 0; @@ -597,11 +597,11 @@ static int get_length_code_size( } status = vtctx->get_param_set_func(vid_fmt, - 0, - NULL, - NULL, - NULL, - &isize); + 0, + NULL, + NULL, + NULL, + &isize); if (status) { av_log(avctx, AV_LOG_ERROR, "Error getting length code size: %d\n", status); return AVERROR_EXTERNAL; @@ -1018,55 +1018,55 @@ static int vtenc_create_encoder(AVCodecContext *avctx, } if (vtctx->codec_id == AV_CODEC_ID_H264) { - // kVTCompressionPropertyKey_DataRateLimits is not available for HEVC - bytes_per_second_value = max_rate >> 3; - bytes_per_second = CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt64Type, - &bytes_per_second_value); - if (!bytes_per_second) { - return AVERROR(ENOMEM); - } - one_second_value = 1; - one_second = CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt64Type, - &one_second_value); - if (!one_second) { - CFRelease(bytes_per_second); - return AVERROR(ENOMEM); - } - nums[0] = (void *)bytes_per_second; - nums[1] = (void *)one_second; - data_rate_limits = CFArrayCreate(kCFAllocatorDefault, - (const void **)nums, - 2, - &kCFTypeArrayCallBacks); + // kVTCompressionPropertyKey_DataRateLimits is not available for HEVC + bytes_per_second_value = max_rate >> 3; + bytes_per_second = CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt64Type, + &bytes_per_second_value); + if (!bytes_per_second) { + return AVERROR(ENOMEM); + } + one_second_value = 1; + one_second = CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt64Type, + &one_second_value); + if (!one_second) { + CFRelease(bytes_per_second); + return AVERROR(ENOMEM); + } + nums[0] = (void *)bytes_per_second; + nums[1] = (void *)one_second; + data_rate_limits = CFArrayCreate(kCFAllocatorDefault, + (const void **)nums, + 2, + &kCFTypeArrayCallBacks); + + if (!data_rate_limits) { + CFRelease(bytes_per_second); + CFRelease(one_second); + return AVERROR(ENOMEM); + } + status = VTSessionSetProperty(vtctx->session, + kVTCompressionPropertyKey_DataRateLimits, + data_rate_limits); - if (!data_rate_limits) { CFRelease(bytes_per_second); CFRelease(one_second); - return AVERROR(ENOMEM); - } - status = VTSessionSetProperty(vtctx->session, - kVTCompressionPropertyKey_DataRateLimits, - data_rate_limits); - - CFRelease(bytes_per_second); - CFRelease(one_second); - CFRelease(data_rate_limits); - - if (status) { - av_log(avctx, AV_LOG_ERROR, "Error setting max bitrate property: %d\n", status); - return AVERROR_EXTERNAL; - } + CFRelease(data_rate_limits); - if (profile_level) { - status = VTSessionSetProperty(vtctx->session, - kVTCompressionPropertyKey_ProfileLevel, - profile_level); if (status) { - av_log(avctx, AV_LOG_ERROR, "Error setting profile/level property: %d\n", status); + av_log(avctx, AV_LOG_ERROR, "Error setting max bitrate property: %d\n", status); + return AVERROR_EXTERNAL; + } + + if (profile_level) { + status = VTSessionSetProperty(vtctx->session, + kVTCompressionPropertyKey_ProfileLevel, + profile_level); + if (status) { + av_log(avctx, AV_LOG_ERROR, "Error setting profile/level property: %d\n", status); + } } - } } if (avctx->gop_size > 0) { @@ -1284,20 +1284,20 @@ static av_cold int vtenc_init(AVCodecContext *avctx) vtctx->codec_id = avctx->codec_id; if (vtctx->codec_id == AV_CODEC_ID_H264) { - vtctx->get_param_set_func = CMVideoFormatDescriptionGetH264ParameterSetAtIndex; + vtctx->get_param_set_func = CMVideoFormatDescriptionGetH264ParameterSetAtIndex; - vtctx->has_b_frames = avctx->max_b_frames > 0; - if(vtctx->has_b_frames && vtctx->profile == H264_PROF_BASELINE){ - av_log(avctx, AV_LOG_WARNING, "Cannot use B-frames with baseline profile. Output will not contain B-frames.\n"); - vtctx->has_b_frames = false; - } + vtctx->has_b_frames = avctx->max_b_frames > 0; + if(vtctx->has_b_frames && vtctx->profile == H264_PROF_BASELINE){ + av_log(avctx, AV_LOG_WARNING, "Cannot use B-frames with baseline profile. Output will not contain B-frames.\n"); + vtctx->has_b_frames = false; + } - if (vtctx->entropy == VT_CABAC && vtctx->profile == H264_PROF_BASELINE) { - av_log(avctx, AV_LOG_WARNING, "CABAC entropy requires 'main' or 'high' profile, but baseline was requested. Encode will not use CABAC entropy.\n"); - vtctx->entropy = VT_ENTROPY_NOT_SET; - } + if (vtctx->entropy == VT_CABAC && vtctx->profile == H264_PROF_BASELINE) { + av_log(avctx, AV_LOG_WARNING, "CABAC entropy requires 'main' or 'high' profile, but baseline was requested. Encode will not use CABAC entropy.\n"); + vtctx->entropy = VT_ENTROPY_NOT_SET; + } - if (!get_vt_h264_profile_level(avctx, &profile_level)) return AVERROR(EINVAL); + if (!get_vt_h264_profile_level(avctx, &profile_level)) return AVERROR(EINVAL); } else { vtctx->get_param_set_func = compat_keys.CMVideoFormatDescriptionGetHEVCParameterSetAtIndex; if (!vtctx->get_param_set_func) return AVERROR(EINVAL); From 631296ff9922a6971de41640a0d937b1a2a52393 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 10 Nov 2017 11:59:05 -0800 Subject: [PATCH 0900/2557] avcodec/videotoolbox: use early return in videotoolbox_default_free Cosmetic change only. Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index f0790e7353834..5011f5201d266 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -849,15 +849,15 @@ static int videotoolbox_default_init(AVCodecContext *avctx) static void videotoolbox_default_free(AVCodecContext *avctx) { AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); + if (!videotoolbox) + return; - if (videotoolbox) { - if (videotoolbox->cm_fmt_desc) - CFRelease(videotoolbox->cm_fmt_desc); + if (videotoolbox->cm_fmt_desc) + CFRelease(videotoolbox->cm_fmt_desc); - if (videotoolbox->session) { - VTDecompressionSessionInvalidate(videotoolbox->session); - CFRelease(videotoolbox->session); - } + if (videotoolbox->session) { + VTDecompressionSessionInvalidate(videotoolbox->session); + CFRelease(videotoolbox->session); } } From b4b177049a886b67f8da84da95f55b81e11ba165 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 25 Sep 2017 16:32:11 -0700 Subject: [PATCH 0901/2557] avcodec/videotoolbox: extract videotoolbox_{start,stop} helpers These helpers will be used in later commits to automatically restart the decoder session when SPS changes are encountered. Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 5011f5201d266..f3d5f0aa4d46c 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -756,7 +756,7 @@ static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecT return cm_fmt_desc; } -static int videotoolbox_default_init(AVCodecContext *avctx) +static int videotoolbox_start(AVCodecContext *avctx) { AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); OSStatus status; @@ -794,6 +794,11 @@ static int videotoolbox_default_init(AVCodecContext *avctx) decoder_spec = videotoolbox_decoder_config_create(videotoolbox->cm_codec_type, avctx); + if (!decoder_spec) { + av_log(avctx, AV_LOG_ERROR, "decoder specification creation failed\n"); + return -1; + } + videotoolbox->cm_fmt_desc = videotoolbox_format_desc_create(videotoolbox->cm_codec_type, decoder_spec, avctx->width, @@ -846,18 +851,21 @@ static int videotoolbox_default_init(AVCodecContext *avctx) } } -static void videotoolbox_default_free(AVCodecContext *avctx) +static void videotoolbox_stop(AVCodecContext *avctx) { AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); if (!videotoolbox) return; - if (videotoolbox->cm_fmt_desc) + if (videotoolbox->cm_fmt_desc) { CFRelease(videotoolbox->cm_fmt_desc); + videotoolbox->cm_fmt_desc = NULL; + } if (videotoolbox->session) { VTDecompressionSessionInvalidate(videotoolbox->session); CFRelease(videotoolbox->session); + videotoolbox->session = NULL; } } @@ -870,7 +878,7 @@ static int videotoolbox_uninit(AVCodecContext *avctx) ff_videotoolbox_uninit(avctx); if (vtctx->vt_ctx) - videotoolbox_default_free(avctx); + videotoolbox_stop(avctx); av_buffer_unref(&vtctx->cached_hw_frames_ctx); av_freep(&vtctx->vt_ctx); @@ -936,7 +944,7 @@ static int videotoolbox_common_init(AVCodecContext *avctx) goto fail; } - err = videotoolbox_default_init(avctx); + err = videotoolbox_start(avctx); if (err < 0) goto fail; @@ -1072,13 +1080,13 @@ int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext * avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context(); if (!avctx->hwaccel_context) return AVERROR(ENOMEM); - return videotoolbox_default_init(avctx); + return videotoolbox_start(avctx); } void av_videotoolbox_default_free(AVCodecContext *avctx) { - videotoolbox_default_free(avctx); + videotoolbox_stop(avctx); av_freep(&avctx->hwaccel_context); } #endif /* CONFIG_VIDEOTOOLBOX */ From d869928ca6e61358adb916369cafd61366f6b064 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 25 Sep 2017 16:42:18 -0700 Subject: [PATCH 0902/2557] avcodec/videotoolbox: reset bitstream_size in end_frame This allows decode_slice to be invoked multiple times before end_frame, causing slices to accumulate before being fed into the VT decoder. An upcoming commit will re-use decode_slice for parameter NALUs, so they can be propagated into the VT decoder session along with slice data. Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index f3d5f0aa4d46c..67b742927478e 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -300,8 +300,6 @@ int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, VTContext *vtctx = avctx->internal->hwaccel_priv_data; H264Context *h = avctx->priv_data; - vtctx->bitstream_size = 0; - if (h->is_avc == 1) { return videotoolbox_buffer_copy(vtctx, buffer, size); } @@ -600,8 +598,10 @@ static int videotoolbox_h264_end_frame(AVCodecContext *avctx) { H264Context *h = avctx->priv_data; AVFrame *frame = h->cur_pic_ptr->f; - - return videotoolbox_common_end_frame(avctx, frame); + VTContext *vtctx = avctx->internal->hwaccel_priv_data; + int ret = videotoolbox_common_end_frame(avctx, frame); + vtctx->bitstream_size = 0; + return ret; } static int videotoolbox_hevc_end_frame(AVCodecContext *avctx) From 6515e2834a51e651aa9855d071291eeb8256dbb6 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 25 Sep 2017 16:44:47 -0700 Subject: [PATCH 0903/2557] avcodec/videotoolbox: print descriptive errors on decode failures Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 67b742927478e..4fe89a27e9641 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -572,9 +572,22 @@ static OSStatus videotoolbox_session_decode_frame(AVCodecContext *avctx) return status; } +static const char *videotoolbox_error_string(OSStatus status) +{ + switch (status) { + case kVTVideoDecoderBadDataErr: + return "bad data"; + case kVTVideoDecoderMalfunctionErr: + return "decoder malfunction"; + case kVTInvalidSessionErr: + return "invalid session"; + } + return "unknown"; +} + static int videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame) { - int status; + OSStatus status; AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); VTContext *vtctx = avctx->internal->hwaccel_priv_data; @@ -582,9 +595,8 @@ static int videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame) return AVERROR_INVALIDDATA; status = videotoolbox_session_decode_frame(avctx); - - if (status) { - av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status); + if (status != noErr) { + av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%s, %d)\n", videotoolbox_error_string(status), (int)status); return AVERROR_UNKNOWN; } From dad42bc5a134f60164eab2dfb0892b761603e1e1 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 25 Sep 2017 16:45:53 -0700 Subject: [PATCH 0904/2557] avcodec/h264, videotoolbox: return AVERROR_INVALIDDATA when no frames are produced The only reason videotoolbox wouldn't produce frames is if the data fed to it was invalid, so returning AVERROR_INVALIDDATA makes sense here. Further, it means AVERROR_EXTERNAL can be used in further commits to signal fatal VideoToolbox errors, letting the user know that they need to fallback to another decoder. Signed-off-by: Aman Gupta Reviewed-by: Michael Niedermayer --- libavcodec/h264dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index aed23c4fba1d7..517f6acc13e25 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -824,7 +824,7 @@ static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp) int ret; if (src->format == AV_PIX_FMT_VIDEOTOOLBOX && src->buf[0]->size == 1) - return AVERROR_EXTERNAL; + return AVERROR_INVALIDDATA; ret = av_frame_ref(dst, src); if (ret < 0) From 76f169368da4928308b932eaea528b841bc34f9e Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 10 Nov 2017 12:17:36 -0800 Subject: [PATCH 0905/2557] avcodec: add decode_params callback to AVHWAccel struct Signed-off-by: Aman Gupta --- libavcodec/avcodec.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 8c76c9f908587..74b097cdd8582 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3460,6 +3460,20 @@ typedef struct AVHWAccel { */ int (*start_frame)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size); + /** + * Callback for parameter data (SPS/PPS/VPS etc). + * + * Useful for hardware decoders which keep persistent state about the + * video parameters, and need to receive any changes to update that state. + * + * @param avctx the codec context + * @param type the nal unit type + * @param buf the nal unit data buffer + * @param buf_size the size of the nal unit in bytes + * @return zero if successful, a negative value otherwise + */ + int (*decode_params)(AVCodecContext *avctx, int type, const uint8_t *buf, uint32_t buf_size); + /** * Callback for each slice. * From 872add08540fb36b2d2ca75df86da7d8ac9579a1 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 10 Nov 2017 12:18:35 -0800 Subject: [PATCH 0906/2557] avcodec/h264: implement new decode_params callback for PPS/SPS This callback will be used by the VideoToolbox H264 hwaccel so that it can receive SPS and PPS NALUs. VideoToolbox requires PPS changes to be fed into the decoder session, and for the session to be recreated when the SPS changes. Signed-off-by: Aman Gupta --- libavcodec/h264dec.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 517f6acc13e25..be187eb5f4091 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -713,6 +713,14 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size) break; case H264_NAL_SPS: { GetBitContext tmp_gb = nal->gb; + if (avctx->hwaccel && avctx->hwaccel->decode_params) { + ret = avctx->hwaccel->decode_params(avctx, + nal->type, + nal->raw_data, + nal->raw_size); + if (ret < 0) + goto end; + } if (ff_h264_decode_seq_parameter_set(&tmp_gb, avctx, &h->ps, 0) >= 0) break; av_log(h->avctx, AV_LOG_DEBUG, @@ -724,6 +732,14 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size) break; } case H264_NAL_PPS: + if (avctx->hwaccel && avctx->hwaccel->decode_params) { + ret = avctx->hwaccel->decode_params(avctx, + nal->type, + nal->raw_data, + nal->raw_size); + if (ret < 0) + goto end; + } ret = ff_h264_decode_picture_parameter_set(&nal->gb, avctx, &h->ps, nal->size_bits); if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) From 9519983c0f39d01fd86544dc56adbbf15bdd3c3c Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 10 Nov 2017 12:25:39 -0800 Subject: [PATCH 0907/2557] avcodec/videotoolbox: use decode_params to propagate H264 PPS changes and restart on SPS changes This fixes decoding of H264 video samples with SPS and PPS changes. See for example https://s3.amazonaws.com/tmm1/videotoolbox/spschange.ts, which previously stalled the decoder and failed to produce any new frames after the SPS change. Also see https://s3.amazonaws.com/tmm1/videotoolbox/ppschange.ts, which uses multiple PPS and would previously cause VT decode failures. If the VideoToolbox session needs to be restarted, and videotoolbox_start() fails for some reason (for instance, if the video is interlaced and the decoder is running on iOS), avcodec will return AVERROR_EXTERNAL. This can be used by the API user to switch to another decoder. Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 43 +++++++++++++++++++++++++++++++++++++-- libavcodec/vt_internal.h | 6 ++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 4fe89a27e9641..c24f5aa3f399c 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -42,6 +42,9 @@ enum { kCMVideoCodecType_HEVC = 'hvc1' }; #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12 +static void videotoolbox_stop(AVCodecContext *avctx); +static int videotoolbox_start(AVCodecContext *avctx); + static void videotoolbox_buffer_release(void *opaque, uint8_t *data) { CVPixelBufferRef cv_buffer = (CVImageBufferRef)data; @@ -307,6 +310,27 @@ int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, return 0; } +static int videotoolbox_h264_decode_params(AVCodecContext *avctx, + int type, + const uint8_t *buffer, + uint32_t size) +{ + VTContext *vtctx = avctx->internal->hwaccel_priv_data; + + if (type == H264_NAL_SPS) { + if (!vtctx->sps || vtctx->sps_len != size || memcmp(buffer, vtctx->sps, size) != 0) { + vtctx->sps = av_fast_realloc(vtctx->sps, &vtctx->sps_capa, size); + if (vtctx->sps) + memcpy(vtctx->sps, buffer, size); + vtctx->reconfig_needed = true; + vtctx->sps_len = size; + } + } + + // pass-through new PPS to the decoder + return ff_videotoolbox_h264_decode_slice(avctx, buffer, size); +} + int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) @@ -339,6 +363,7 @@ int ff_videotoolbox_uninit(AVCodecContext *avctx) VTContext *vtctx = avctx->internal->hwaccel_priv_data; if (vtctx) { av_freep(&vtctx->bitstream); + av_freep(&vtctx->sps); if (vtctx->frame) CVPixelBufferRelease(vtctx->frame); } @@ -591,17 +616,30 @@ static int videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame) AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); VTContext *vtctx = avctx->internal->hwaccel_priv_data; - if (!videotoolbox->session || !vtctx->bitstream) + if (vtctx->reconfig_needed == true) { + vtctx->reconfig_needed = false; + av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox decoder needs reconfig, restarting..\n"); + videotoolbox_stop(avctx); + if (videotoolbox_start(avctx) != 0) { + return AVERROR_EXTERNAL; + } + } + + if (!videotoolbox->session || !vtctx->bitstream || !vtctx->bitstream_size) return AVERROR_INVALIDDATA; status = videotoolbox_session_decode_frame(avctx); if (status != noErr) { + if (status == kVTVideoDecoderMalfunctionErr || status == kVTInvalidSessionErr) + vtctx->reconfig_needed = true; av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%s, %d)\n", videotoolbox_error_string(status), (int)status); return AVERROR_UNKNOWN; } - if (!vtctx->frame) + if (!vtctx->frame) { + vtctx->reconfig_needed = true; return AVERROR_UNKNOWN; + } return videotoolbox_buffer_create(avctx, frame); } @@ -1018,6 +1056,7 @@ AVHWAccel ff_h264_videotoolbox_hwaccel = { .alloc_frame = ff_videotoolbox_alloc_frame, .start_frame = ff_videotoolbox_h264_start_frame, .decode_slice = ff_videotoolbox_h264_decode_slice, + .decode_params = videotoolbox_h264_decode_params, .end_frame = videotoolbox_h264_end_frame, .frame_params = videotoolbox_frame_params, .init = videotoolbox_common_init, diff --git a/libavcodec/vt_internal.h b/libavcodec/vt_internal.h index 607dd7a6d0999..fc27dad9f9411 100644 --- a/libavcodec/vt_internal.h +++ b/libavcodec/vt_internal.h @@ -38,6 +38,12 @@ typedef struct VTContext { // Non-NULL if the new hwaccel API is used. This is only a separate struct // to ease compatibility with the old API. struct AVVideotoolboxContext *vt_ctx; + + // Current H264 parameters (used to trigger decoder restart on SPS changes). + uint8_t *sps; + uint32_t sps_len; + unsigned int sps_capa; + bool reconfig_needed; } VTContext; int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame); From 403d10a8b3cd9c0c9a4a034b95a4cb5ffc4b1112 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 25 Sep 2017 16:52:35 -0700 Subject: [PATCH 0908/2557] avcodec/videotoolbox: create avcC even when h264 extradata is missing Removes the avctx->extradata_size requirement when creating avcC/hvcC, since avctx->extradata is only used in the esds code path. This fixes an issue where the VideoToolbox decoder would not work unless avformat_find_stream_info() was called. Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index c24f5aa3f399c..7e915a4e83b79 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -702,7 +702,7 @@ static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder, kCFBooleanTrue); - if (avctx->extradata_size) { + if (1) { CFMutableDictionaryRef avc_info; CFDataRef data = NULL; @@ -713,7 +713,8 @@ static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec switch (codec_type) { case kCMVideoCodecType_MPEG4Video : - data = videotoolbox_esds_extradata_create(avctx); + if (avctx->extradata_size) + data = videotoolbox_esds_extradata_create(avctx); if (data) CFDictionarySetValue(avc_info, CFSTR("esds"), data); break; From bd2d70c0b8f416cf1f70e910ed675c0d46fb0010 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 10 Nov 2017 11:52:38 -0800 Subject: [PATCH 0909/2557] avcodec/videotoolbox: remove unnecessary if statement Cosmetic change only. Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 68 +++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 7e915a4e83b79..1307e93bccde4 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -702,45 +702,43 @@ static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder, kCFBooleanTrue); - if (1) { - CFMutableDictionaryRef avc_info; - CFDataRef data = NULL; - - avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault, - 1, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - switch (codec_type) { - case kCMVideoCodecType_MPEG4Video : - if (avctx->extradata_size) - data = videotoolbox_esds_extradata_create(avctx); - if (data) - CFDictionarySetValue(avc_info, CFSTR("esds"), data); - break; - case kCMVideoCodecType_H264 : - data = ff_videotoolbox_avcc_extradata_create(avctx); - if (data) - CFDictionarySetValue(avc_info, CFSTR("avcC"), data); - break; - case kCMVideoCodecType_HEVC : - data = ff_videotoolbox_hvcc_extradata_create(avctx); - if (data) - CFDictionarySetValue(avc_info, CFSTR("hvcC"), data); - break; - default: - break; - } + CFMutableDictionaryRef avc_info; + CFDataRef data = NULL; - CFDictionarySetValue(config_info, - kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms, - avc_info); + avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault, + 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + switch (codec_type) { + case kCMVideoCodecType_MPEG4Video : + if (avctx->extradata_size) + data = videotoolbox_esds_extradata_create(avctx); if (data) - CFRelease(data); - - CFRelease(avc_info); + CFDictionarySetValue(avc_info, CFSTR("esds"), data); + break; + case kCMVideoCodecType_H264 : + data = ff_videotoolbox_avcc_extradata_create(avctx); + if (data) + CFDictionarySetValue(avc_info, CFSTR("avcC"), data); + break; + case kCMVideoCodecType_HEVC : + data = ff_videotoolbox_hvcc_extradata_create(avctx); + if (data) + CFDictionarySetValue(avc_info, CFSTR("hvcC"), data); + break; + default: + break; } + + CFDictionarySetValue(config_info, + kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms, + avc_info); + + if (data) + CFRelease(data); + + CFRelease(avc_info); return config_info; } From 3a91b3ae742425c25b9b80708f3c111537e570d3 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 10 Nov 2017 12:31:56 -0800 Subject: [PATCH 0910/2557] avcodec/hevc: implement new decode_params callback for VideoToolbox Signed-off-by: Aman Gupta --- libavcodec/hevcdec.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 6dd6d0c53cb95..75960912b184f 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2824,23 +2824,55 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) switch (s->nal_unit_type) { case HEVC_NAL_VPS: + if (s->avctx->hwaccel && s->avctx->hwaccel->decode_params) { + ret = s->avctx->hwaccel->decode_params(s->avctx, + nal->type, + nal->raw_data, + nal->raw_size); + if (ret < 0) + goto fail; + } ret = ff_hevc_decode_nal_vps(gb, s->avctx, &s->ps); if (ret < 0) goto fail; break; case HEVC_NAL_SPS: + if (s->avctx->hwaccel && s->avctx->hwaccel->decode_params) { + ret = s->avctx->hwaccel->decode_params(s->avctx, + nal->type, + nal->raw_data, + nal->raw_size); + if (ret < 0) + goto fail; + } ret = ff_hevc_decode_nal_sps(gb, s->avctx, &s->ps, s->apply_defdispwin); if (ret < 0) goto fail; break; case HEVC_NAL_PPS: + if (s->avctx->hwaccel && s->avctx->hwaccel->decode_params) { + ret = s->avctx->hwaccel->decode_params(s->avctx, + nal->type, + nal->raw_data, + nal->raw_size); + if (ret < 0) + goto fail; + } ret = ff_hevc_decode_nal_pps(gb, s->avctx, &s->ps); if (ret < 0) goto fail; break; case HEVC_NAL_SEI_PREFIX: case HEVC_NAL_SEI_SUFFIX: + if (s->avctx->hwaccel && s->avctx->hwaccel->decode_params) { + ret = s->avctx->hwaccel->decode_params(s->avctx, + nal->type, + nal->raw_data, + nal->raw_size); + if (ret < 0) + goto fail; + } ret = ff_hevc_decode_nal_sei(gb, s->avctx, &s->sei, &s->ps, s->nal_unit_type); if (ret < 0) goto fail; From 68ef503bb5f9f8bd4460191d6a9c9e2ec4179a26 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 10 Nov 2017 12:34:41 -0800 Subject: [PATCH 0911/2557] avcodec/videotoolbox: pass through hevc param changes to the decoder This includes the SEI_PREFIX/SEI_SUFFIX NALUs, which can contain updates like HEVC_SEI_TYPE_ACTIVE_PARAMETER_SETS. Previously, hevc samples with this SEI present would not playback correctly. See for example https://github.com/lhc70000/iina/issues/1123 Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 1307e93bccde4..3c9077bf346a7 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -654,6 +654,14 @@ static int videotoolbox_h264_end_frame(AVCodecContext *avctx) return ret; } +static int videotoolbox_hevc_decode_params(AVCodecContext *avctx, + int type, + const uint8_t *buffer, + uint32_t size) +{ + return ff_videotoolbox_h264_decode_slice(avctx, buffer, size); +} + static int videotoolbox_hevc_end_frame(AVCodecContext *avctx) { HEVCContext *h = avctx->priv_data; @@ -1040,6 +1048,7 @@ AVHWAccel ff_hevc_videotoolbox_hwaccel = { .alloc_frame = ff_videotoolbox_alloc_frame, .start_frame = ff_videotoolbox_h264_start_frame, .decode_slice = ff_videotoolbox_h264_decode_slice, + .decode_params = videotoolbox_hevc_decode_params, .end_frame = videotoolbox_hevc_end_frame, .frame_params = videotoolbox_frame_params, .init = videotoolbox_common_init, From c8b1a151cef685496b8171a5236f099e137c3a37 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 25 Sep 2017 16:15:09 -0700 Subject: [PATCH 0912/2557] avcodec/videotoolboxenc: remove spurious warning Signed-off-by: Aman Gupta --- libavcodec/videotoolboxenc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 93338eabde2a7..086beb41fcde3 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -1939,8 +1939,6 @@ static int get_cv_pixel_info( "Color range not set for %s. Using MPEG range.\n", av_get_pix_fmt_name(av_format)); } - - av_log(avctx, AV_LOG_WARNING, ""); } switch (av_format) { From 5e577c586b7825b4addd1d38cf20688d7d50010d Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 10 Nov 2017 12:02:23 -0800 Subject: [PATCH 0913/2557] avcodec/videotoolbox: fix whitespace Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 3c9077bf346a7..792db270b4e51 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -88,7 +88,7 @@ int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame) CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx) { - H264Context *h = avctx->priv_data; + H264Context *h = avctx->priv_data; CFDataRef data = NULL; uint8_t *p; int vt_extradata_size = 6 + 2 + h->ps.sps->data_size + 3 + h->ps.pps->data_size; @@ -897,7 +897,7 @@ static int videotoolbox_start(AVCodecContext *avctx) case kVTVideoDecoderMalfunctionErr: av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox malfunction.\n"); return AVERROR(EINVAL); - case kVTVideoDecoderBadDataErr : + case kVTVideoDecoderBadDataErr: av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox reported invalid data.\n"); return AVERROR_INVALIDDATA; case 0: From b7f963c4444d709a89156fb0f094c232fe1eacd6 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 13 Nov 2017 15:06:40 -0800 Subject: [PATCH 0914/2557] avcodec/videotoolbox: reorder functions to avoid forward declarations Cosmetic change only. Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 301 +++++++++++++++++++------------------- 1 file changed, 149 insertions(+), 152 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 792db270b4e51..4547ffef34d80 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -42,9 +42,6 @@ enum { kCMVideoCodecType_HEVC = 'hvc1' }; #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12 -static void videotoolbox_stop(AVCodecContext *avctx); -static int videotoolbox_start(AVCodecContext *avctx); - static void videotoolbox_buffer_release(void *opaque, uint8_t *data) { CVPixelBufferRef cv_buffer = (CVImageBufferRef)data; @@ -597,105 +594,67 @@ static OSStatus videotoolbox_session_decode_frame(AVCodecContext *avctx) return status; } -static const char *videotoolbox_error_string(OSStatus status) -{ - switch (status) { - case kVTVideoDecoderBadDataErr: - return "bad data"; - case kVTVideoDecoderMalfunctionErr: - return "decoder malfunction"; - case kVTInvalidSessionErr: - return "invalid session"; - } - return "unknown"; -} - -static int videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame) +static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType codec_type, + CFDictionaryRef decoder_spec, + int width, + int height) { + CMFormatDescriptionRef cm_fmt_desc; OSStatus status; - AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); - VTContext *vtctx = avctx->internal->hwaccel_priv_data; - if (vtctx->reconfig_needed == true) { - vtctx->reconfig_needed = false; - av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox decoder needs reconfig, restarting..\n"); - videotoolbox_stop(avctx); - if (videotoolbox_start(avctx) != 0) { - return AVERROR_EXTERNAL; - } - } - - if (!videotoolbox->session || !vtctx->bitstream || !vtctx->bitstream_size) - return AVERROR_INVALIDDATA; - - status = videotoolbox_session_decode_frame(avctx); - if (status != noErr) { - if (status == kVTVideoDecoderMalfunctionErr || status == kVTInvalidSessionErr) - vtctx->reconfig_needed = true; - av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%s, %d)\n", videotoolbox_error_string(status), (int)status); - return AVERROR_UNKNOWN; - } - - if (!vtctx->frame) { - vtctx->reconfig_needed = true; - return AVERROR_UNKNOWN; - } - - return videotoolbox_buffer_create(avctx, frame); -} + status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault, + codec_type, + width, + height, + decoder_spec, // Dictionary of extension + &cm_fmt_desc); -static int videotoolbox_h264_end_frame(AVCodecContext *avctx) -{ - H264Context *h = avctx->priv_data; - AVFrame *frame = h->cur_pic_ptr->f; - VTContext *vtctx = avctx->internal->hwaccel_priv_data; - int ret = videotoolbox_common_end_frame(avctx, frame); - vtctx->bitstream_size = 0; - return ret; -} + if (status) + return NULL; -static int videotoolbox_hevc_decode_params(AVCodecContext *avctx, - int type, - const uint8_t *buffer, - uint32_t size) -{ - return ff_videotoolbox_h264_decode_slice(avctx, buffer, size); + return cm_fmt_desc; } -static int videotoolbox_hevc_end_frame(AVCodecContext *avctx) +static CFDictionaryRef videotoolbox_buffer_attributes_create(int width, + int height, + OSType pix_fmt) { - HEVCContext *h = avctx->priv_data; - AVFrame *frame = h->ref->frame; - VTContext *vtctx = avctx->internal->hwaccel_priv_data; - int ret; - - ret = videotoolbox_common_end_frame(avctx, frame); - vtctx->bitstream_size = 0; - return ret; -} + CFMutableDictionaryRef buffer_attributes; + CFMutableDictionaryRef io_surface_properties; + CFNumberRef cv_pix_fmt; + CFNumberRef w; + CFNumberRef h; -static int videotoolbox_mpeg_start_frame(AVCodecContext *avctx, - const uint8_t *buffer, - uint32_t size) -{ - VTContext *vtctx = avctx->internal->hwaccel_priv_data; + w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width); + h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height); + cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pix_fmt); - return videotoolbox_buffer_copy(vtctx, buffer, size); -} + buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, + 4, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); -static int videotoolbox_mpeg_decode_slice(AVCodecContext *avctx, - const uint8_t *buffer, - uint32_t size) -{ - return 0; -} + if (pix_fmt) + CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt); + CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties); + CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey, w); + CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey, h); +#if TARGET_OS_IPHONE + CFDictionarySetValue(buffer_attributes, kCVPixelBufferOpenGLESCompatibilityKey, kCFBooleanTrue); +#else + CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfaceOpenGLTextureCompatibilityKey, kCFBooleanTrue); +#endif -static int videotoolbox_mpeg_end_frame(AVCodecContext *avctx) -{ - MpegEncContext *s = avctx->priv_data; - AVFrame *frame = s->current_picture_ptr->f; + CFRelease(io_surface_properties); + CFRelease(cv_pix_fmt); + CFRelease(w); + CFRelease(h); - return videotoolbox_common_end_frame(avctx, frame); + return buffer_attributes; } static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec_type, @@ -750,69 +709,6 @@ static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec return config_info; } -static CFDictionaryRef videotoolbox_buffer_attributes_create(int width, - int height, - OSType pix_fmt) -{ - CFMutableDictionaryRef buffer_attributes; - CFMutableDictionaryRef io_surface_properties; - CFNumberRef cv_pix_fmt; - CFNumberRef w; - CFNumberRef h; - - w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width); - h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height); - cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pix_fmt); - - buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, - 4, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - if (pix_fmt) - CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt); - CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties); - CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey, w); - CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey, h); -#if TARGET_OS_IPHONE - CFDictionarySetValue(buffer_attributes, kCVPixelBufferOpenGLESCompatibilityKey, kCFBooleanTrue); -#else - CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfaceOpenGLTextureCompatibilityKey, kCFBooleanTrue); -#endif - - CFRelease(io_surface_properties); - CFRelease(cv_pix_fmt); - CFRelease(w); - CFRelease(h); - - return buffer_attributes; -} - -static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType codec_type, - CFDictionaryRef decoder_spec, - int width, - int height) -{ - CMFormatDescriptionRef cm_fmt_desc; - OSStatus status; - - status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault, - codec_type, - width, - height, - decoder_spec, // Dictionary of extension - &cm_fmt_desc); - - if (status) - return NULL; - - return cm_fmt_desc; -} - static int videotoolbox_start(AVCodecContext *avctx) { AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); @@ -926,6 +822,107 @@ static void videotoolbox_stop(AVCodecContext *avctx) } } +static const char *videotoolbox_error_string(OSStatus status) +{ + switch (status) { + case kVTVideoDecoderBadDataErr: + return "bad data"; + case kVTVideoDecoderMalfunctionErr: + return "decoder malfunction"; + case kVTInvalidSessionErr: + return "invalid session"; + } + return "unknown"; +} + +static int videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame) +{ + OSStatus status; + AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); + VTContext *vtctx = avctx->internal->hwaccel_priv_data; + + if (vtctx->reconfig_needed == true) { + vtctx->reconfig_needed = false; + av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox decoder needs reconfig, restarting..\n"); + videotoolbox_stop(avctx); + if (videotoolbox_start(avctx) != 0) { + return AVERROR_EXTERNAL; + } + } + + if (!videotoolbox->session || !vtctx->bitstream || !vtctx->bitstream_size) + return AVERROR_INVALIDDATA; + + status = videotoolbox_session_decode_frame(avctx); + if (status != noErr) { + if (status == kVTVideoDecoderMalfunctionErr || status == kVTInvalidSessionErr) + vtctx->reconfig_needed = true; + av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%s, %d)\n", videotoolbox_error_string(status), (int)status); + return AVERROR_UNKNOWN; + } + + if (!vtctx->frame) { + vtctx->reconfig_needed = true; + return AVERROR_UNKNOWN; + } + + return videotoolbox_buffer_create(avctx, frame); +} + +static int videotoolbox_h264_end_frame(AVCodecContext *avctx) +{ + H264Context *h = avctx->priv_data; + AVFrame *frame = h->cur_pic_ptr->f; + VTContext *vtctx = avctx->internal->hwaccel_priv_data; + int ret = videotoolbox_common_end_frame(avctx, frame); + vtctx->bitstream_size = 0; + return ret; +} + +static int videotoolbox_hevc_decode_params(AVCodecContext *avctx, + int type, + const uint8_t *buffer, + uint32_t size) +{ + return ff_videotoolbox_h264_decode_slice(avctx, buffer, size); +} + +static int videotoolbox_hevc_end_frame(AVCodecContext *avctx) +{ + HEVCContext *h = avctx->priv_data; + AVFrame *frame = h->ref->frame; + VTContext *vtctx = avctx->internal->hwaccel_priv_data; + int ret; + + ret = videotoolbox_common_end_frame(avctx, frame); + vtctx->bitstream_size = 0; + return ret; +} + +static int videotoolbox_mpeg_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + VTContext *vtctx = avctx->internal->hwaccel_priv_data; + + return videotoolbox_buffer_copy(vtctx, buffer, size); +} + +static int videotoolbox_mpeg_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + return 0; +} + +static int videotoolbox_mpeg_end_frame(AVCodecContext *avctx) +{ + MpegEncContext *s = avctx->priv_data; + AVFrame *frame = s->current_picture_ptr->f; + + return videotoolbox_common_end_frame(avctx, frame); +} + static int videotoolbox_uninit(AVCodecContext *avctx) { VTContext *vtctx = avctx->internal->hwaccel_priv_data; From 9283a4f19b762b25bc8e5e8f402fefb9097a1397 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 31 Oct 2017 15:15:27 +0100 Subject: [PATCH 0915/2557] avcodec/videotoolbox: fix opaque_ref handling This is a partial fix - to fix videotoolbox fully (with multithreaded hwaccel decoding), much more work would be required. Before this change, an assertion failure would trigger: $ ffmpeg -hwaccel videotoolbox -hwaccel_output_format videotoolbox_vld -i h264.ts -f null -y /dev/null Assertion (frame->private_ref && frame->private_ref->size == sizeof(FrameDecodeData)) || !(avctx->codec->capabilities & (1 << 1)) failed at libavcodec/decode.c:620 Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 4547ffef34d80..9eeada30bae80 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -27,6 +27,7 @@ #include "libavutil/avutil.h" #include "libavutil/hwcontext.h" #include "bytestream.h" +#include "decode.h" #include "h264dec.h" #include "hevcdec.h" #include "mpegvideo.h" @@ -70,6 +71,10 @@ static int videotoolbox_buffer_copy(VTContext *vtctx, int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame) { + int ret = ff_attach_decode_data(frame); + if (ret < 0) + return ret; + frame->width = avctx->width; frame->height = avctx->height; frame->format = avctx->pix_fmt; From 8329ae781a75c1b665fc2ffe2e08be2c8207419e Mon Sep 17 00:00:00 2001 From: Muhammad Faiz Date: Tue, 24 Oct 2017 16:23:28 +0700 Subject: [PATCH 0916/2557] avutil/crc: use ff_thread_once at av_crc_get_table Fix tsan warnings. Signed-off-by: Muhammad Faiz --- libavutil/crc.c | 49 +++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/libavutil/crc.c b/libavutil/crc.c index 495732b1636b7..d44550c9c007b 100644 --- a/libavutil/crc.c +++ b/libavutil/crc.c @@ -20,6 +20,8 @@ #include "config.h" +#include "thread.h" +#include "avassert.h" #include "bswap.h" #include "common.h" #include "crc.h" @@ -291,20 +293,24 @@ static const AVCRC av_crc_table[AV_CRC_MAX][257] = { #else #define CRC_TABLE_SIZE 1024 #endif -static struct { - uint8_t le; - uint8_t bits; - uint32_t poly; -} av_crc_table_params[AV_CRC_MAX] = { - [AV_CRC_8_ATM] = { 0, 8, 0x07 }, - [AV_CRC_16_ANSI] = { 0, 16, 0x8005 }, - [AV_CRC_16_CCITT] = { 0, 16, 0x1021 }, - [AV_CRC_24_IEEE] = { 0, 24, 0x864CFB }, - [AV_CRC_32_IEEE] = { 0, 32, 0x04C11DB7 }, - [AV_CRC_32_IEEE_LE] = { 1, 32, 0xEDB88320 }, - [AV_CRC_16_ANSI_LE] = { 1, 16, 0xA001 }, -}; static AVCRC av_crc_table[AV_CRC_MAX][CRC_TABLE_SIZE]; + +#define DECLARE_CRC_INIT_TABLE_ONCE(id, le, bits, poly) \ +static AVOnce id ## _once_control = AV_ONCE_INIT; \ +static void id ## _init_table_once(void) \ +{ \ + av_assert0(av_crc_init(av_crc_table[id], le, bits, poly, sizeof(av_crc_table[id])) >= 0); \ +} + +#define CRC_INIT_TABLE_ONCE(id) ff_thread_once(&id ## _once_control, id ## _init_table_once) + +DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_8_ATM, 0, 8, 0x07) +DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_16_ANSI, 0, 16, 0x8005) +DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_16_CCITT, 0, 16, 0x1021) +DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_24_IEEE, 0, 24, 0x864CFB) +DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_32_IEEE, 0, 32, 0x04C11DB7) +DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_32_IEEE_LE, 1, 32, 0xEDB88320) +DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_16_ANSI_LE, 1, 16, 0xA001) #endif int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size) @@ -343,13 +349,16 @@ int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size) const AVCRC *av_crc_get_table(AVCRCId crc_id) { #if !CONFIG_HARDCODED_TABLES - if (!av_crc_table[crc_id][FF_ARRAY_ELEMS(av_crc_table[crc_id]) - 1]) - if (av_crc_init(av_crc_table[crc_id], - av_crc_table_params[crc_id].le, - av_crc_table_params[crc_id].bits, - av_crc_table_params[crc_id].poly, - sizeof(av_crc_table[crc_id])) < 0) - return NULL; + switch (crc_id) { + case AV_CRC_8_ATM: CRC_INIT_TABLE_ONCE(AV_CRC_8_ATM); break; + case AV_CRC_16_ANSI: CRC_INIT_TABLE_ONCE(AV_CRC_16_ANSI); break; + case AV_CRC_16_CCITT: CRC_INIT_TABLE_ONCE(AV_CRC_16_CCITT); break; + case AV_CRC_24_IEEE: CRC_INIT_TABLE_ONCE(AV_CRC_24_IEEE); break; + case AV_CRC_32_IEEE: CRC_INIT_TABLE_ONCE(AV_CRC_32_IEEE); break; + case AV_CRC_32_IEEE_LE: CRC_INIT_TABLE_ONCE(AV_CRC_32_IEEE_LE); break; + case AV_CRC_16_ANSI_LE: CRC_INIT_TABLE_ONCE(AV_CRC_16_ANSI_LE); break; + default: av_assert0(0); + } #endif return av_crc_table[crc_id]; } From 880b299381de1e66f8248abd6c320c7c490466a2 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 14 Nov 2017 10:31:26 +0800 Subject: [PATCH 0917/2557] avformat/hlsenc: write fmp4 init header after first AV frame fix ticket id: 6825 Signed-off-by: Steven Liu Tested-by: Aman Gupta --- libavformat/hlsenc.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index b571772f606b2..e0cef8b879585 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -108,6 +108,9 @@ typedef struct HLSContext { uint32_t start_sequence_source_type; // enum StartSequenceSourceType AVOutputFormat *oformat; AVOutputFormat *vtt_oformat; + AVIOContext *out; + int packets_written; + int init_range_length; AVFormatContext *avf; AVFormatContext *vtt_avf; @@ -598,6 +601,7 @@ static int hls_mux_init(AVFormatContext *s) st->time_base = s->streams[i]->time_base; av_dict_copy(&st->metadata, s->streams[i]->metadata, 0); } + hls->packets_written = 1; hls->start_pos = 0; hls->new_start = 1; hls->fmp4_init_mode = 0; @@ -607,9 +611,14 @@ static int hls_mux_init(AVFormatContext *s) av_log(s, AV_LOG_WARNING, "Multi-file byterange mode is currently unsupported in the HLS muxer.\n"); return AVERROR_PATCHWELCOME; } + hls->packets_written = 0; + hls->init_range_length = 0; hls->fmp4_init_mode = !byterange_mode; set_http_options(s, &options, hls); - if ((ret = s->io_open(s, &oc->pb, hls->base_output_dirname, AVIO_FLAG_WRITE, &options)) < 0) { + if ((ret = avio_open_dyn_buf(&oc->pb)) < 0) + return ret; + + if ((ret = s->io_open(s, &hls->out, hls->base_output_dirname, AVIO_FLAG_WRITE, &options)) < 0) { av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", hls->fmp4_init_filename); return ret; } @@ -634,6 +643,7 @@ static int hls_mux_init(AVFormatContext *s) av_dict_free(&options); return AVERROR(EINVAL); } + avio_flush(oc->pb); av_dict_free(&options); } return 0; @@ -1600,6 +1610,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) int is_ref_pkt = 1; int ret = 0, can_split = 1; int stream_index = 0; + int range_length = 0; + uint8_t *buffer = NULL; if (hls->sequence - hls->nb_entries > hls->start_sequence && hls->init_time > 0) { /* reset end_pts, hls->recording_time at end of the init hls list */ @@ -1645,7 +1657,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) } } - if (hls->fmp4_init_mode || can_split && av_compare_ts(pkt->pts - hls->start_pts, st->time_base, + if (hls->packets_written && can_split && av_compare_ts(pkt->pts - hls->start_pts, st->time_base, end_pts, AV_TIME_BASE_Q) >= 0) { int64_t new_start_pos; char *old_filename = av_strdup(hls->avf->filename); @@ -1661,7 +1673,17 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) hls->size = new_start_pos - hls->start_pos; if (!byterange_mode) { - ff_format_io_close(s, &oc->pb); + if (hls->segment_type == SEGMENT_TYPE_FMP4 && !hls->init_range_length) { + avio_flush(oc->pb); + range_length = avio_close_dyn_buf(oc->pb, &buffer); + avio_write(hls->out, buffer, range_length); + hls->init_range_length = range_length; + avio_open_dyn_buf(&oc->pb); + hls->packets_written = 0; + ff_format_io_close(s, &hls->out); + } else { + ff_format_io_close(s, &oc->pb); + } if (hls->vtt_avf) { ff_format_io_close(s, &hls->vtt_avf->pb); } @@ -1719,6 +1741,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) } } + hls->packets_written++; ret = ff_write_chained(oc, stream_index, pkt, s, 0); return ret; From 58cf31cee7a456057f337b3102a03206d833d5e8 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 13 Nov 2017 20:47:48 +0100 Subject: [PATCH 0918/2557] avcodec/x86/mpegvideodsp: Fix signedness bug in need_emu Fixes: out of array read Fixes: 3516/attachment-311488.dat Found-by: Insu Yun, Georgia Tech. Tested-by: wuninsu@gmail.com Signed-off-by: Michael Niedermayer --- libavcodec/x86/mpegvideodsp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/x86/mpegvideodsp.c b/libavcodec/x86/mpegvideodsp.c index e0498f3849620..6009b64e0769d 100644 --- a/libavcodec/x86/mpegvideodsp.c +++ b/libavcodec/x86/mpegvideodsp.c @@ -52,8 +52,9 @@ static void gmc_mmx(uint8_t *dst, uint8_t *src, const int dyh = (dyy - (1 << (16 + shift))) * (h - 1); const int dxh = dxy * (h - 1); const int dyw = dyx * (w - 1); - int need_emu = (unsigned) ix >= width - w || - (unsigned) iy >= height - h; + int need_emu = (unsigned) ix >= width - w || width < w || + (unsigned) iy >= height - h || height< h + ; if ( // non-constant fullpel offset (3% of blocks) ((ox ^ (ox + dxw)) | (ox ^ (ox + dxh)) | (ox ^ (ox + dxw + dxh)) | From 5c2a01f064d5ab2b309d25c7f46c6c4471838d90 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 13 Nov 2017 17:34:15 -0300 Subject: [PATCH 0919/2557] Makefile: fix distclean target It must imply clean. Regression since 7ebe7e8e7a76c0ce302f4f583ef0d14220031214. Signed-off-by: James Almer --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5f91294c8ec5a..cbccfd6ec1ac3 100644 --- a/Makefile +++ b/Makefile @@ -171,7 +171,7 @@ clean:: $(RM) $(addprefix compat/,$(CLEANSUFFIXES)) $(addprefix compat/*/,$(CLEANSUFFIXES)) $(RM) -rf coverage.info lcov -distclean:: +distclean: clean $(RM) .version avversion.h config.asm config.h mapfile \ avbuild/.config avbuild/config.* libavutil/avconfig.h \ libavcodec/bsf_list.c libavformat/protocol_list.c From 91a565e20f0c220a6bc37e58c11cea4a3590149c Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 13 Nov 2017 11:34:50 -0800 Subject: [PATCH 0920/2557] avformat/http: fix chunked response w/ multiple_requests=1 Currently if you use the multiple_requests=1 option and try to receive a chunked-encoded response, http_buf_read() will hang forever. After this patch, EOF is emulated once a 0-byte final chunk is received by setting a new flag. This flag is reset in ff_http_do_new_request(), which is used to make additional requests on the open socket. Reviewed-by: Ronald S. Bultje Signed-off-by: Aman Gupta --- libavformat/http.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libavformat/http.c b/libavformat/http.c index 29635eb546555..056d5f6583766 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -66,6 +66,7 @@ typedef struct HTTPContext { int http_code; /* Used if "Transfer-Encoding: chunked" otherwise -1. */ uint64_t chunksize; + int chunkend; uint64_t off, end_off, filesize; char *location; HTTPAuthState auth_state; @@ -305,6 +306,7 @@ int ff_http_do_new_request(URLContext *h, const char *uri) AVDictionary *options = NULL; int ret; + s->chunkend = 0; s->off = 0; s->icy_data_read = 0; av_free(s->location); @@ -1281,6 +1283,9 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size) int len; if (s->chunksize != UINT64_MAX) { + if (s->chunkend) { + return AVERROR_EOF; + } if (!s->chunksize) { char line[32]; int err; @@ -1296,7 +1301,12 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size) "Chunked encoding data size: %"PRIu64"\n", s->chunksize); - if (!s->chunksize) { + if (!s->chunksize && s->multiple_requests) { + http_get_line(s, line, sizeof(line)); // read empty chunk + s->chunkend = 1; + return 0; + } + else if (!s->chunksize) { av_log(h, AV_LOG_DEBUG, "Last chunk received, closing conn\n"); ffurl_closep(&s->hd); return 0; From 034e1f82d924bb3038873798b2cc8d84f9701f62 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 14 Nov 2017 10:02:20 -0800 Subject: [PATCH 0921/2557] avcodec: fix whitespace on AVPanScan struct definition --- libavcodec/avcodec.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 74b097cdd8582..0875ae3ba0e1f 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1049,7 +1049,7 @@ typedef struct RcOverride{ * This specifies the area which should be displayed. * Note there may be multiple such areas for one frame. */ -typedef struct AVPanScan{ +typedef struct AVPanScan { /** * id * - encoding: Set by user. @@ -1071,7 +1071,7 @@ typedef struct AVPanScan{ * - decoding: Set by libavcodec. */ int16_t position[3][2]; -}AVPanScan; +} AVPanScan; /** * This structure describes the bitrate properties of an encoded bitstream. It From e5f66a9ea40cf463ef40631b4704607182ceee3c Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Thu, 9 Nov 2017 10:47:28 +0530 Subject: [PATCH 0922/2557] avcodec/mips: cleanup unused macros Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_macros_msa.h | 37 ------------------------------- 1 file changed, 37 deletions(-) diff --git a/libavcodec/mips/hevc_macros_msa.h b/libavcodec/mips/hevc_macros_msa.h index 27c69ff89a2f4..ea53812b6490f 100644 --- a/libavcodec/mips/hevc_macros_msa.h +++ b/libavcodec/mips/hevc_macros_msa.h @@ -21,43 +21,6 @@ #ifndef AVCODEC_MIPS_HEVC_MACROS_MSA_H #define AVCODEC_MIPS_HEVC_MACROS_MSA_H -#define HEVC_PCK_SW_SB2(in0, in1, out) \ -{ \ - v8i16 tmp0_m; \ - \ - tmp0_m = __msa_pckev_h((v8i16) in0, (v8i16) in1); \ - out = (v4i32) __msa_pckev_b((v16i8) tmp0_m, (v16i8) tmp0_m); \ -} - -#define HEVC_PCK_SW_SB4(in0, in1, in2, in3, out) \ -{ \ - v8i16 tmp0_m, tmp1_m; \ - \ - PCKEV_H2_SH(in0, in1, in2, in3, tmp0_m, tmp1_m); \ - out = (v4i32) __msa_pckev_b((v16i8) tmp1_m, (v16i8) tmp0_m); \ -} - -#define HEVC_PCK_SW_SB8(in0, in1, in2, in3, in4, in5, in6, in7, out0, out1) \ -{ \ - v8i16 tmp0_m, tmp1_m, tmp2_m, tmp3_m; \ - \ - PCKEV_H4_SH(in0, in1, in2, in3, in4, in5, in6, in7, \ - tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ - PCKEV_B2_SW(tmp1_m, tmp0_m, tmp3_m, tmp2_m, out0, out1); \ -} - -#define HEVC_PCK_SW_SB12(in0, in1, in2, in3, in4, in5, in6, in7, \ - in8, in9, in10, in11, out0, out1, out2) \ -{ \ - v8i16 tmp0_m, tmp1_m, tmp2_m, tmp3_m, tmp4_m, tmp5_m; \ - \ - PCKEV_H4_SH(in0, in1, in2, in3, in4, in5, in6, in7, \ - tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ - PCKEV_H2_SH(in8, in9, in10, in11, tmp4_m, tmp5_m); \ - PCKEV_B2_SW(tmp1_m, tmp0_m, tmp3_m, tmp2_m, out0, out1); \ - out2 = (v4i32) __msa_pckev_b((v16i8) tmp5_m, (v16i8) tmp4_m); \ -} - #define HEVC_FILT_8TAP_SH(in0, in1, in2, in3, \ filt0, filt1, filt2, filt3) \ ( { \ From 143fc5f6e20b05ba5b45c807c990acaa87134e8b Mon Sep 17 00:00:00 2001 From: Kaustubh Raste Date: Thu, 9 Nov 2017 15:39:49 +0530 Subject: [PATCH 0923/2557] avcodec/mips: Improve hevc non-uni hz and vt mc msa functions Use mask buffer. Signed-off-by: Kaustubh Raste Reviewed-by: Manojkumar Bhosale Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevcdsp_msa.c | 541 ++++++++++++++++++++-------------- 1 file changed, 312 insertions(+), 229 deletions(-) diff --git a/libavcodec/mips/hevcdsp_msa.c b/libavcodec/mips/hevcdsp_msa.c index b17127c5f6bab..81db62b876d9b 100644 --- a/libavcodec/mips/hevcdsp_msa.c +++ b/libavcodec/mips/hevcdsp_msa.c @@ -456,7 +456,7 @@ static void hevc_hz_8t_4w_msa(uint8_t *src, int32_t src_stride, v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2, dst3; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); src -= 3; const_vec = __msa_ldi_h(128); @@ -511,7 +511,7 @@ static void hevc_hz_8t_8w_msa(uint8_t *src, int32_t src_stride, v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2, dst3; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); src -= 3; const_vec = __msa_ldi_h(128); @@ -559,8 +559,75 @@ static void hevc_hz_8t_12w_msa(uint8_t *src, int32_t src_stride, int16_t *dst, int32_t dst_stride, const int8_t *filter, int32_t height) { - hevc_hz_8t_8w_msa(src, src_stride, dst, dst_stride, filter, height); - hevc_hz_8t_4w_msa(src + 8, src_stride, dst + 8, dst_stride, filter, height); + uint32_t loop_cnt; + int64_t res0, res1, res2, res3; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7; + v16i8 mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask7; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5; + v8i16 filt0, filt1, filt2, filt3, dst0, dst1, dst2, dst3, dst4, dst5; + v8i16 filter_vec, const_vec; + + src -= 3; + const_vec = __msa_ldi_h(128); + const_vec <<= 6; + + filter_vec = LD_SH(filter); + SPLATI_H4_SH(filter_vec, 0, 1, 2, 3, filt0, filt1, filt2, filt3); + + mask0 = LD_SB(ff_hevc_mask_arr); + mask1 = mask0 + 2; + mask2 = mask0 + 4; + mask3 = mask0 + 6; + mask4 = LD_SB(ff_hevc_mask_arr + 16); + mask5 = mask4 + 2; + mask6 = mask4 + 4; + mask7 = mask4 + 6; + + for (loop_cnt = 4; loop_cnt--;) { + LD_SB4(src, src_stride, src0, src1, src2, src3); + LD_SB4(src + 8, src_stride, src4, src5, src6, src7); + src += (4 * src_stride); + XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); + + dst0 = const_vec; + dst1 = const_vec; + dst2 = const_vec; + dst3 = const_vec; + dst4 = const_vec; + dst5 = const_vec; + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); + VSHF_B2_SB(src4, src5, src6, src7, mask4, mask4, vec4, vec5); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + DPADD_SB2_SH(vec4, vec5, filt0, filt0, dst4, dst5); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2, vec3); + VSHF_B2_SB(src4, src5, src6, src7, mask5, mask5, vec4, vec5); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); + DPADD_SB2_SH(vec4, vec5, filt1, filt1, dst4, dst5); + VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec2, vec3); + VSHF_B2_SB(src4, src5, src6, src7, mask6, mask6, vec4, vec5); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, dst0, + dst1, dst2, dst3); + DPADD_SB2_SH(vec4, vec5, filt2, filt2, dst4, dst5); + VSHF_B2_SB(src0, src0, src1, src1, mask3, mask3, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask3, mask3, vec2, vec3); + VSHF_B2_SB(src4, src5, src6, src7, mask7, mask7, vec4, vec5); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt3, filt3, filt3, filt3, dst0, + dst1, dst2, dst3); + DPADD_SB2_SH(vec4, vec5, filt3, filt3, dst4, dst5); + + res0 = __msa_copy_s_d((v2i64) dst4, 0); + res1 = __msa_copy_s_d((v2i64) dst4, 1); + res2 = __msa_copy_s_d((v2i64) dst5, 0); + res3 = __msa_copy_s_d((v2i64) dst5, 1); + ST_SH4(dst0, dst1, dst2, dst3, dst, dst_stride); + SD4(res0, res1, res2, res3, (dst + 8), dst_stride); + dst += (4 * dst_stride); + } } static void hevc_hz_8t_16w_msa(uint8_t *src, int32_t src_stride, @@ -568,13 +635,13 @@ static void hevc_hz_8t_16w_msa(uint8_t *src, int32_t src_stride, const int8_t *filter, int32_t height) { uint32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7; + v16i8 src0, src1, src2, src3; v8i16 filt0, filt1, filt2, filt3; v16i8 mask1, mask2, mask3; v16i8 vec0, vec1, vec2, vec3; - v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v8i16 dst0, dst1, dst2, dst3; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); src -= 3; const_vec = __msa_ldi_h(128); @@ -587,56 +654,36 @@ static void hevc_hz_8t_16w_msa(uint8_t *src, int32_t src_stride, mask2 = mask0 + 4; mask3 = mask0 + 6; - for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB4(src, src_stride, src0, src2, src4, src6); - LD_SB4(src + 8, src_stride, src1, src3, src5, src7); - src += (4 * src_stride); - XORI_B8_128_SB(src0, src1, src2, src3, src4, src5, src6, src7); + for (loop_cnt = (height >> 1); loop_cnt--;) { + LD_SB2(src, src_stride, src0, src2); + LD_SB2(src + 8, src_stride, src1, src3); + src += (2 * src_stride); + XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); - VSHF_B4_SB(src4, src4, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); - dst4 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst4, dst4, dst4, dst4); - VSHF_B4_SB(src5, src5, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); - dst5 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst5, dst5, dst5, dst5); - VSHF_B4_SB(src6, src6, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); - dst6 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst6, dst6, dst6, dst6); - VSHF_B4_SB(src7, src7, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); - dst7 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst7, dst7, dst7, dst7); - - ST_SH4(dst0, dst2, dst4, dst6, dst, dst_stride); - ST_SH4(dst1, dst3, dst5, dst7, dst + 8, dst_stride); - dst += (4 * dst_stride); + VSHF_B2_SB(src0, src0, src1, src1, mask0, mask0, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask1, mask1, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask2, mask2, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src1, src1, mask3, mask3, vec0, vec1); + VSHF_B2_SB(src2, src2, src3, src3, mask3, mask3, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt3, filt3, filt3, filt3, dst0, + dst1, dst2, dst3); + + ST_SH2(dst0, dst2, dst, dst_stride); + ST_SH2(dst1, dst3, dst + 8, dst_stride); + dst += (2 * dst_stride); } } @@ -648,10 +695,10 @@ static void hevc_hz_8t_24w_msa(uint8_t *src, int32_t src_stride, v16i8 src0, src1, src2, src3; v8i16 filt0, filt1, filt2, filt3; v16i8 mask1, mask2, mask3, mask4, mask5, mask6, mask7; - v16i8 vec0, vec1, vec2, vec3; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); src -= 3; filter_vec = LD_SH(filter); @@ -675,36 +722,36 @@ static void hevc_hz_8t_24w_msa(uint8_t *src, int32_t src_stride, src += src_stride; XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - VSHF_B4_SB(src0, src1, mask4, mask5, mask6, mask7, - vec0, vec1, vec2, vec3); dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); - VSHF_B4_SB(src2, src3, mask4, mask5, mask6, mask7, - vec0, vec1, vec2, vec3); dst4 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst4, dst4, dst4, dst4); - VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst5 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst5, dst5, dst5, dst5); + VSHF_B2_SB(src0, src0, src0, src1, mask0, mask4, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask0, mask0, vec2, vec3); + VSHF_B2_SB(src2, src3, src3, src3, mask4, mask0, vec4, vec5); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + DPADD_SB2_SH(vec4, vec5, filt0, filt0, dst4, dst5); + VSHF_B2_SB(src0, src0, src0, src1, mask1, mask5, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask1, mask1, vec2, vec3); + VSHF_B2_SB(src2, src3, src3, src3, mask5, mask1, vec4, vec5); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); + DPADD_SB2_SH(vec4, vec5, filt1, filt1, dst4, dst5); + VSHF_B2_SB(src0, src0, src0, src1, mask2, mask6, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask2, mask2, vec2, vec3); + VSHF_B2_SB(src2, src3, src3, src3, mask6, mask2, vec4, vec5); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, dst0, + dst1, dst2, dst3); + DPADD_SB2_SH(vec4, vec5, filt2, filt2, dst4, dst5); + VSHF_B2_SB(src0, src0, src0, src1, mask3, mask7, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask3, mask3, vec2, vec3); + VSHF_B2_SB(src2, src3, src3, src3, mask7, mask3, vec4, vec5); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt3, filt3, filt3, filt3, dst0, + dst1, dst2, dst3); + DPADD_SB2_SH(vec4, vec5, filt3, filt3, dst4, dst5); ST_SH2(dst0, dst1, dst, 8); ST_SH(dst2, dst + 16); @@ -726,7 +773,7 @@ static void hevc_hz_8t_32w_msa(uint8_t *src, int32_t src_stride, v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2, dst3; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); src -= 3; filter_vec = LD_SH(filter); @@ -783,10 +830,10 @@ static void hevc_hz_8t_48w_msa(uint8_t *src, int32_t src_stride, v16i8 src0, src1, src2, src3; v8i16 filt0, filt1, filt2, filt3; v16i8 mask1, mask2, mask3, mask4, mask5, mask6, mask7; - v16i8 vec0, vec1, vec2, vec3; + v16i8 vec0, vec1, vec2, vec3, vec4, vec5; v8i16 dst0, dst1, dst2, dst3, dst4, dst5; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); src -= 3; filter_vec = LD_SH(filter); @@ -809,38 +856,39 @@ static void hevc_hz_8t_48w_msa(uint8_t *src, int32_t src_stride, src += src_stride; XORI_B4_128_SB(src0, src1, src2, src3); - VSHF_B4_SB(src0, src0, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst0 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst0, dst0, dst0, dst0); - VSHF_B4_SB(src0, src1, mask4, mask5, mask6, mask7, - vec0, vec1, vec2, vec3); dst1 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst1, dst1, dst1, dst1); - VSHF_B4_SB(src1, src1, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst2 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst2, dst2, dst2, dst2); - VSHF_B4_SB(src1, src2, mask4, mask5, mask6, mask7, - vec0, vec1, vec2, vec3); dst3 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst3, dst3, dst3, dst3); - VSHF_B4_SB(src2, src2, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst4 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst4, dst4, dst4, dst4); - VSHF_B4_SB(src3, src3, mask0, mask1, mask2, mask3, - vec0, vec1, vec2, vec3); dst5 = const_vec; - DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt1, filt2, filt3, - dst5, dst5, dst5, dst5); + VSHF_B2_SB(src0, src0, src0, src1, mask0, mask4, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src2, mask0, mask4, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask1, mask5, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src2, mask1, mask5, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask2, mask6, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src2, mask2, mask6, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt2, filt2, filt2, filt2, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask3, mask7, vec0, vec1); + VSHF_B2_SB(src1, src1, src1, src2, mask3, mask7, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt3, filt3, filt3, filt3, dst0, + dst1, dst2, dst3); + ST_SH4(dst0, dst1, dst2, dst3, dst, 8); - ST_SH6(dst0, dst1, dst2, dst3, dst4, dst5, dst, 8); + VSHF_B2_SB(src2, src2, src3, src3, mask0, mask0, vec4, vec5); + DPADD_SB2_SH(vec4, vec5, filt0, filt0, dst4, dst5); + VSHF_B2_SB(src2, src2, src3, src3, mask1, mask1, vec4, vec5); + DPADD_SB2_SH(vec4, vec5, filt1, filt1, dst4, dst5); + VSHF_B2_SB(src2, src2, src3, src3, mask2, mask2, vec4, vec5); + DPADD_SB2_SH(vec4, vec5, filt2, filt2, dst4, dst5); + VSHF_B2_SB(src2, src2, src3, src3, mask3, mask3, vec4, vec5); + DPADD_SB2_SH(vec4, vec5, filt3, filt3, dst4, dst5); + ST_SH2(dst4, dst5, (dst + 32), 8); dst += dst_stride; } } @@ -856,7 +904,7 @@ static void hevc_hz_8t_64w_msa(uint8_t *src, int32_t src_stride, v16i8 vec0, vec1, vec2, vec3; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); src -= 3; @@ -1805,7 +1853,7 @@ static void hevc_hz_4t_4x2_msa(uint8_t *src, v16i8 mask1, vec0, vec1; v8i16 dst0; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); src -= 1; @@ -1838,7 +1886,7 @@ static void hevc_hz_4t_4x4_msa(uint8_t *src, v16i8 mask1, vec0, vec1; v8i16 dst0, dst1; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); src -= 1; @@ -1877,7 +1925,7 @@ static void hevc_hz_4t_4x8multiple_msa(uint8_t *src, v16i8 mask1, vec0, vec1; v8i16 dst0, dst1, dst2, dst3; v8i16 filter_vec, const_vec; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr + 16); src -= 1; @@ -1942,7 +1990,7 @@ static void hevc_hz_4t_6w_msa(uint8_t *src, uint32_t dst_val_int0, dst_val_int1, dst_val_int2, dst_val_int3; v8i16 filt0, filt1, dst0, dst1, dst2, dst3; v16i8 src0, src1, src2, src3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; v16i8 vec0, vec1; v8i16 filter_vec, const_vec; @@ -1957,7 +2005,7 @@ static void hevc_hz_4t_6w_msa(uint8_t *src, const_vec = __msa_ldi_h(128); const_vec <<= 6; - for (loop_cnt = (height >> 2); loop_cnt--;) { + for (loop_cnt = 2; loop_cnt--;) { LD_SB4(src, src_stride, src0, src1, src2, src3); src += (4 * src_stride); @@ -2011,7 +2059,7 @@ static void hevc_hz_4t_8x2multiple_msa(uint8_t *src, uint32_t loop_cnt; v8i16 filt0, filt1, dst0, dst1; v16i8 src0, src1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; v16i8 vec0, vec1; v8i16 filter_vec, const_vec; @@ -2055,7 +2103,7 @@ static void hevc_hz_4t_8x4multiple_msa(uint8_t *src, uint32_t loop_cnt; v8i16 filt0, filt1; v16i8 src0, src1, src2, src3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; v16i8 vec0, vec1; v8i16 dst0, dst1, dst2, dst3; @@ -2129,7 +2177,7 @@ static void hevc_hz_4t_12w_msa(uint8_t *src, v8i16 dst0, dst1, dst2, dst3, dst4, dst5; v8i16 filter_vec, const_vec; v16i8 mask3; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask2 = { 8, 9, 9, 10, 10, 11, 11, 12, 24, 25, 25, 26, 26, 27, 27, 28 }; @@ -2186,7 +2234,7 @@ static void hevc_hz_4t_16w_msa(uint8_t *src, v16i8 src0, src1, src2, src3; v16i8 src4, src5, src6, src7; v8i16 filt0, filt1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1; v8i16 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; v16i8 vec0, vec1; @@ -2258,7 +2306,7 @@ static void hevc_hz_4t_24w_msa(uint8_t *src, int16_t *dst_tmp = dst + 16; v16i8 src0, src1, src2, src3, src4, src5, src6, src7; v8i16 filt0, filt1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1, mask00, mask11; v16i8 vec0, vec1; v8i16 dst0, dst1, dst2, dst3; @@ -2358,10 +2406,10 @@ static void hevc_hz_4t_32w_msa(uint8_t *src, uint32_t loop_cnt; v16i8 src0, src1, src2; v8i16 filt0, filt1; - v16i8 mask0 = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 }; + v16i8 mask0 = LD_SB(ff_hevc_mask_arr); v16i8 mask1, mask2, mask3; v8i16 dst0, dst1, dst2, dst3; - v16i8 vec0, vec1; + v16i8 vec0, vec1, vec2, vec3; v8i16 filter_vec, const_vec; src -= 1; @@ -2376,54 +2424,25 @@ static void hevc_hz_4t_32w_msa(uint8_t *src, mask2 = mask0 + 8; mask3 = mask0 + 10; - for (loop_cnt = (height >> 1); loop_cnt--;) { + for (loop_cnt = height; loop_cnt--;) { LD_SB2(src, 16, src0, src1); src2 = LD_SB(src + 24); src += src_stride; XORI_B3_128_SB(src0, src1, src2); - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - - VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - - ST_SH4(dst0, dst1, dst2, dst3, dst, 8); - dst += dst_stride; - - LD_SB2(src, 16, src0, src1); - src2 = LD_SB(src + 24); - src += src_stride; - - XORI_B3_128_SB(src0, src1, src2); - - VSHF_B2_SB(src0, src0, src0, src0, mask0, mask1, vec0, vec1); - dst0 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst0, dst0); - - VSHF_B2_SB(src0, src1, src0, src1, mask2, mask3, vec0, vec1); - dst1 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst1, dst1); - - VSHF_B2_SB(src1, src1, src1, src1, mask0, mask1, vec0, vec1); - dst2 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst2, dst2); - - VSHF_B2_SB(src2, src2, src2, src2, mask0, mask1, vec0, vec1); - dst3 = const_vec; - DPADD_SB2_SH(vec0, vec1, filt0, filt1, dst3, dst3); - + VSHF_B2_SB(src0, src0, src0, src1, mask0, mask2, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask0, mask0, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt0, filt0, filt0, filt0, dst0, + dst1, dst2, dst3); + VSHF_B2_SB(src0, src0, src0, src1, mask1, mask3, vec0, vec1); + VSHF_B2_SB(src1, src1, src2, src2, mask1, mask1, vec2, vec3); + DPADD_SB4_SH(vec0, vec1, vec2, vec3, filt1, filt1, filt1, filt1, dst0, + dst1, dst2, dst3); ST_SH4(dst0, dst1, dst2, dst3, dst, 8); dst += dst_stride; } @@ -2499,18 +2518,17 @@ static void hevc_vt_4t_4x4_msa(uint8_t *src, ST8x4_UB(dst10, dst32, dst, 2 * dst_stride); } -static void hevc_vt_4t_4x8multiple_msa(uint8_t *src, - int32_t src_stride, - int16_t *dst, - int32_t dst_stride, - const int8_t *filter, - int32_t height) +static void hevc_vt_4t_4x8_msa(uint8_t *src, + int32_t src_stride, + int16_t *dst, + int32_t dst_stride, + const int8_t *filter, + int32_t height) { - int32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9; + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; v16i8 src10_r, src32_r, src54_r, src76_r, src98_r; v16i8 src21_r, src43_r, src65_r, src87_r, src109_r; - v16i8 src2110, src4332, src6554, src8776; + v16i8 src2110, src4332, src6554, src8776, src10998; v8i16 dst10, dst32, dst54, dst76; v8i16 filt0, filt1; v8i16 filter_vec, const_vec; @@ -2529,35 +2547,96 @@ static void hevc_vt_4t_4x8multiple_msa(uint8_t *src, src2110 = (v16i8) __msa_ilvr_d((v2i64) src21_r, (v2i64) src10_r); src2110 = (v16i8) __msa_xori_b((v16u8) src2110, 128); - for (loop_cnt = (height >> 3); loop_cnt--;) { - LD_SB6(src, src_stride, src3, src4, src5, src6, src7, src8); - src += (6 * src_stride); + LD_SB8(src, src_stride, src3, src4, src5, src6, src7, src8, src9, src10); + src += (8 * src_stride); + ILVR_B4_SB(src3, src2, src4, src3, src5, src4, src6, src5, + src32_r, src43_r, src54_r, src65_r); + ILVR_B4_SB(src7, src6, src8, src7, src9, src8, src10, src9, + src76_r, src87_r, src98_r, src109_r); + ILVR_D4_SB(src43_r, src32_r, src65_r, src54_r, src87_r, src76_r, src109_r, + src98_r, src4332, src6554, src8776, src10998); + XORI_B4_128_SB(src4332, src6554, src8776, src10998); + dst10 = const_vec; + dst32 = const_vec; + dst54 = const_vec; + dst76 = const_vec; + DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst10, dst10); + DPADD_SB2_SH(src4332, src6554, filt0, filt1, dst32, dst32); + DPADD_SB2_SH(src6554, src8776, filt0, filt1, dst54, dst54); + DPADD_SB2_SH(src8776, src10998, filt0, filt1, dst76, dst76); + ST8x8_UB(dst10, dst32, dst54, dst76, dst, 2 * dst_stride); + dst += (8 * dst_stride); +} - ILVR_B4_SB(src3, src2, src4, src3, src5, src4, src6, src5, - src32_r, src43_r, src54_r, src65_r); - ILVR_B2_SB(src7, src6, src8, src7, src76_r, src87_r); - ILVR_D3_SB(src43_r, src32_r, src65_r, src54_r, src87_r, src76_r, - src4332, src6554, src8776); - XORI_B3_128_SB(src4332, src6554, src8776); +static void hevc_vt_4t_4x16_msa(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + v16i8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + v16i8 src10_r, src32_r, src54_r, src76_r, src98_r, src21_r, src43_r; + v16i8 src65_r, src87_r, src109_r, src2110, src4332, src6554, src8776; + v16i8 src10998; + v8i16 dst10, dst32, dst54, dst76, filt0, filt1, filter_vec, const_vec; - dst10 = const_vec; - DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst10, dst10); - dst32 = const_vec; - DPADD_SB2_SH(src4332, src6554, filt0, filt1, dst32, dst32); - dst54 = const_vec; - DPADD_SB2_SH(src6554, src8776, filt0, filt1, dst54, dst54); + src -= src_stride; + const_vec = __msa_ldi_h(128); + const_vec <<= 6; - LD_SB2(src, src_stride, src9, src2); - src += (2 * src_stride); - ILVR_B2_SB(src9, src8, src2, src9, src98_r, src109_r); - src2110 = (v16i8) __msa_ilvr_d((v2i64) src109_r, (v2i64) src98_r); - src2110 = (v16i8) __msa_xori_b((v16u8) src2110, 128); - dst76 = const_vec; - DPADD_SB2_SH(src8776, src2110, filt0, filt1, dst76, dst76); + filter_vec = LD_SH(filter); + SPLATI_H2_SH(filter_vec, 0, 1, filt0, filt1); - ST8x8_UB(dst10, dst32, dst54, dst76, dst, 2 * dst_stride); - dst += (8 * dst_stride); - } + LD_SB3(src, src_stride, src0, src1, src2); + src += (3 * src_stride); + + ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); + src2110 = (v16i8) __msa_ilvr_d((v2i64) src21_r, (v2i64) src10_r); + src2110 = (v16i8) __msa_xori_b((v16u8) src2110, 128); + + LD_SB8(src, src_stride, src3, src4, src5, src6, src7, src8, src9, src10); + src += (8 * src_stride); + ILVR_B4_SB(src3, src2, src4, src3, src5, src4, src6, src5, src32_r, src43_r, + src54_r, src65_r); + ILVR_B4_SB(src7, src6, src8, src7, src9, src8, src10, src9, src76_r, + src87_r, src98_r, src109_r); + ILVR_D4_SB(src43_r, src32_r, src65_r, src54_r, src87_r, src76_r, src109_r, + src98_r, src4332, src6554, src8776, src10998); + XORI_B4_128_SB(src4332, src6554, src8776, src10998); + + dst10 = const_vec; + dst32 = const_vec; + dst54 = const_vec; + dst76 = const_vec; + DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst10, dst10); + DPADD_SB2_SH(src4332, src6554, filt0, filt1, dst32, dst32); + DPADD_SB2_SH(src6554, src8776, filt0, filt1, dst54, dst54); + DPADD_SB2_SH(src8776, src10998, filt0, filt1, dst76, dst76); + ST8x8_UB(dst10, dst32, dst54, dst76, dst, 2 * dst_stride); + dst += (8 * dst_stride); + + src2 = src10; + src2110 = src10998; + + LD_SB8(src, src_stride, src3, src4, src5, src6, src7, src8, src9, src10); + src += (8 * src_stride); + + ILVR_B4_SB(src3, src2, src4, src3, src5, src4, src6, src5, src32_r, src43_r, + src54_r, src65_r); + ILVR_B4_SB(src7, src6, src8, src7, src9, src8, src10, src9, src76_r, + src87_r, src98_r, src109_r); + ILVR_D4_SB(src43_r, src32_r, src65_r, src54_r, src87_r, src76_r, src109_r, + src98_r, src4332, src6554, src8776, src10998); + XORI_B4_128_SB(src4332, src6554, src8776, src10998); + + dst10 = const_vec; + dst32 = const_vec; + dst54 = const_vec; + dst76 = const_vec; + DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst10, dst10); + DPADD_SB2_SH(src4332, src6554, filt0, filt1, dst32, dst32); + DPADD_SB2_SH(src6554, src8776, filt0, filt1, dst54, dst54); + DPADD_SB2_SH(src8776, src10998, filt0, filt1, dst76, dst76); + ST8x8_UB(dst10, dst32, dst54, dst76, dst, 2 * dst_stride); + dst += (8 * dst_stride); } static void hevc_vt_4t_4w_msa(uint8_t *src, @@ -2571,9 +2650,10 @@ static void hevc_vt_4t_4w_msa(uint8_t *src, hevc_vt_4t_4x2_msa(src, src_stride, dst, dst_stride, filter); } else if (4 == height) { hevc_vt_4t_4x4_msa(src, src_stride, dst, dst_stride, filter, height); - } else if (0 == (height % 8)) { - hevc_vt_4t_4x8multiple_msa(src, src_stride, dst, dst_stride, - filter, height); + } else if (8 == height) { + hevc_vt_4t_4x8_msa(src, src_stride, dst, dst_stride, filter, height); + } else if (16 == height) { + hevc_vt_4t_4x16_msa(src, src_stride, dst, dst_stride, filter, height); } } @@ -2756,9 +2836,9 @@ static void hevc_vt_4t_8x4multiple_msa(uint8_t *src, int32_t height) { int32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5; - v16i8 src10_r, src32_r, src21_r, src43_r; - v8i16 dst0_r, dst1_r; + v16i8 src0, src1, src2, src3, src4, src5, src6; + v16i8 src10_r, src32_r, src21_r, src43_r, src54_r, src65_r; + v8i16 dst0_r, dst1_r, dst2_r, dst3_r; v8i16 filt0, filt1; v8i16 filter_vec, const_vec; @@ -2775,29 +2855,25 @@ static void hevc_vt_4t_8x4multiple_msa(uint8_t *src, ILVR_B2_SB(src1, src0, src2, src1, src10_r, src21_r); for (loop_cnt = (height >> 2); loop_cnt--;) { - LD_SB2(src, src_stride, src3, src4); - src += (2 * src_stride); - XORI_B2_128_SB(src3, src4); + LD_SB4(src, src_stride, src3, src4, src5, src6); + src += (4 * src_stride); + XORI_B4_128_SB(src3, src4, src5, src6); ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); + ILVR_B2_SB(src5, src4, src6, src5, src54_r, src65_r); dst0_r = const_vec; - DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, dst0_r, dst0_r); dst1_r = const_vec; + dst2_r = const_vec; + dst3_r = const_vec; + DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, dst0_r, dst0_r); DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, dst1_r, dst1_r); + DPADD_SB2_SH(src32_r, src54_r, filt0, filt1, dst2_r, dst2_r); + DPADD_SB2_SH(src43_r, src65_r, filt0, filt1, dst3_r, dst3_r); + ST_SH4(dst0_r, dst1_r, dst2_r, dst3_r, dst, dst_stride); + dst += (4 * dst_stride); - ST_SH2(dst0_r, dst1_r, dst, dst_stride); - dst += (2 * dst_stride); - - LD_SB2(src, src_stride, src5, src2); - src += (2 * src_stride); - XORI_B2_128_SB(src5, src2); - ILVR_B2_SB(src5, src4, src2, src5, src10_r, src21_r); - dst0_r = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, dst0_r, dst0_r); - dst1_r = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, dst1_r, dst1_r); - - ST_SH2(dst0_r, dst1_r, dst, dst_stride); - dst += (2 * dst_stride); + src2 = src6; + src10_r = src54_r; + src21_r = src65_r; } } @@ -2826,11 +2902,12 @@ static void hevc_vt_4t_12w_msa(uint8_t *src, int32_t height) { int32_t loop_cnt; - v16i8 src0, src1, src2, src3, src4, src5; + v16i8 src0, src1, src2, src3, src4, src5, src6; v16i8 src10_r, src32_r, src21_r, src43_r; v8i16 dst0_r, dst1_r, dst2_r, dst3_r; v16i8 src10_l, src32_l, src54_l, src21_l, src43_l, src65_l; v16i8 src2110, src4332; + v16i8 src54_r, src65_r, src6554; v8i16 dst0_l, dst1_l; v8i16 filt0, filt1; v8i16 filter_vec, const_vec; @@ -2849,36 +2926,42 @@ static void hevc_vt_4t_12w_msa(uint8_t *src, ILVL_B2_SB(src1, src0, src2, src1, src10_l, src21_l); src2110 = (v16i8) __msa_ilvr_d((v2i64) src21_l, (v2i64) src10_l); - for (loop_cnt = (height >> 2); loop_cnt--;) { + for (loop_cnt = 4; loop_cnt--;) { LD_SB2(src, src_stride, src3, src4); src += (2 * src_stride); + LD_SB2(src, src_stride, src5, src6); + src += (2 * src_stride); XORI_B2_128_SB(src3, src4); + XORI_B2_128_SB(src5, src6); + ILVR_B2_SB(src3, src2, src4, src3, src32_r, src43_r); ILVL_B2_SB(src3, src2, src4, src3, src32_l, src43_l); src4332 = (v16i8) __msa_ilvr_d((v2i64) src43_l, (v2i64) src32_l); + ILVR_B2_SB(src5, src4, src6, src5, src54_r, src65_r); + ILVL_B2_SB(src5, src4, src6, src5, src54_l, src65_l); + src6554 = (v16i8) __msa_ilvr_d((v2i64) src65_l, (v2i64) src54_l); + dst0_r = const_vec; DPADD_SB2_SH(src10_r, src32_r, filt0, filt1, dst0_r, dst0_r); dst1_r = const_vec; DPADD_SB2_SH(src21_r, src43_r, filt0, filt1, dst1_r, dst1_r); - dst0_l = const_vec; - DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst0_l, dst0_l); - - LD_SB2(src, src_stride, src5, src2); - src += (2 * src_stride); - XORI_B2_128_SB(src5, src2); - ILVR_B2_SB(src5, src4, src2, src5, src10_r, src21_r); - ILVL_B2_SB(src5, src4, src2, src5, src54_l, src65_l); - src2110 = (v16i8) __msa_ilvr_d((v2i64) src65_l, (v2i64) src54_l); dst2_r = const_vec; - DPADD_SB2_SH(src32_r, src10_r, filt0, filt1, dst2_r, dst2_r); + DPADD_SB2_SH(src32_r, src54_r, filt0, filt1, dst2_r, dst2_r); dst3_r = const_vec; - DPADD_SB2_SH(src43_r, src21_r, filt0, filt1, dst3_r, dst3_r); + DPADD_SB2_SH(src43_r, src65_r, filt0, filt1, dst3_r, dst3_r); + dst0_l = const_vec; + DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst0_l, dst0_l); dst1_l = const_vec; - DPADD_SB2_SH(src4332, src2110, filt0, filt1, dst1_l, dst1_l); + DPADD_SB2_SH(src4332, src6554, filt0, filt1, dst1_l, dst1_l); ST_SH4(dst0_r, dst1_r, dst2_r, dst3_r, dst, dst_stride); ST8x4_UB(dst0_l, dst1_l, dst + 8, (2 * dst_stride)); dst += (4 * dst_stride); + + src2 = src6; + src10_r = src54_r; + src21_r = src65_r; + src2110 = src6554; } } From 57a422ea4c27dc699baf18ecf7f20353bec36090 Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Mon, 13 Nov 2017 08:09:30 -0800 Subject: [PATCH 0924/2557] fate/mov: add test for overlapping fragments Signed-off-by: Michael Niedermayer --- tests/fate/mov.mak | 4 ++ tests/ref/fate/mov-frag-overlap | 105 ++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 tests/ref/fate/mov-frag-overlap diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 76f66ff4988b0..a98372c5e1383 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -11,6 +11,7 @@ FATE_MOV = fate-mov-3elist \ fate-mov-440hz-10ms \ fate-mov-ibi-elst-starts-b \ fate-mov-elst-ends-betn-b-and-i \ + fate-mov-frag-overlap \ FATE_MOV_FFPROBE = fate-mov-aac-2048-priming \ fate-mov-zombie \ @@ -59,6 +60,9 @@ fate-mov-invalid-elst-entry-count: CMD = framemd5 -flags +bitexact -i $(TARGET_S # i.e. Pts Order: I-B-I fate-mov-ibi-elst-starts-b: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/mov/mov_ibi_elst_starts_b.mov +# Makes sure that we handle overlapping framgments +fate-mov-frag-overlap: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/frag_overlap.mp4 + fate-mov-aac-2048-priming: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_packets -print_format compact $(TARGET_SAMPLES)/mov/aac-2048-priming.mov fate-mov-zombie: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_streams -show_packets -show_frames -bitexact -print_format compact $(TARGET_SAMPLES)/mov/white_zombie_scrunch-part.mov diff --git a/tests/ref/fate/mov-frag-overlap b/tests/ref/fate/mov-frag-overlap new file mode 100644 index 0000000000000..265a93d7e6df5 --- /dev/null +++ b/tests/ref/fate/mov-frag-overlap @@ -0,0 +1,105 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1001/24000 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 640x360 +#sar 0: 1/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 345600, bb5e1ec37e1cb5a4ef2399c7b1c0ed08 +0, 1, 1, 1, 345600, 40455fa94b1f3b1cd199f127401fe187 +0, 2, 2, 1, 345600, 9147b59915250de3508f062b45dda499 +0, 3, 3, 1, 345600, bb9b9109ea61622f491c1e2aa21c503e +0, 4, 4, 1, 345600, eaceff4d694212b2eb6abf5e090d7b4c +0, 5, 5, 1, 345600, eaceff4d694212b2eb6abf5e090d7b4c +0, 6, 6, 1, 345600, f04ca4f64e7e990874c7ac9264ebbe65 +0, 7, 7, 1, 345600, f195d115e0ad6d5c240b08226d312cef +0, 8, 8, 1, 345600, 7585f3f325cc82028701fcd2360610e0 +0, 9, 9, 1, 345600, 7585f3f325cc82028701fcd2360610e0 +0, 10, 10, 1, 345600, 4e4a2d2d47881b238c4f423917c29182 +0, 11, 11, 1, 345600, 72609b459bde5644fe5815bb88fa537e +0, 12, 12, 1, 345600, 67569df185a64ec08498d71e94ab0197 +0, 13, 13, 1, 345600, 352e1d41fd8d5fb0a92b722782591066 +0, 14, 14, 1, 345600, f50f96f0ff0ee58ef8577cb9ce218be4 +0, 15, 15, 1, 345600, 9681c998992d20055388ae6c0d4f40e6 +0, 16, 16, 1, 345600, 4cd9c3056c0d1b2d6ed666d2fbabef45 +0, 17, 17, 1, 345600, 88d0c13cff5acb1746e7bb227e7ec81a +0, 18, 18, 1, 345600, 37a15a2d1d055a9c157a82d77cf48328 +0, 19, 19, 1, 345600, f30e43818a41242ca75caec4be7f366d +0, 20, 20, 1, 345600, e0441ca5e4137910ed94ea2d67f506ad +0, 21, 21, 1, 345600, 61cae30cdb5512610ba1ffb7b372be51 +0, 22, 22, 1, 345600, 28832e6ec917fece50ab94f8d6883d4b +0, 23, 23, 1, 345600, 07cfd60c53a4ede0de4f5eba749abae0 +0, 24, 24, 1, 345600, 254b072e2fe7017933738b8d43cd3f2e +0, 25, 25, 1, 345600, aa2ceef866576011653fc9e4add8c852 +0, 26, 26, 1, 345600, d5507e992763f69ef7da06bca2e5e0e4 +0, 27, 27, 1, 345600, 3d7fd83fab12dc9ca1bb5c0d09104174 +0, 28, 28, 1, 345600, 1fdc34d30f94bfa2acd5ab4791b3b6be +0, 29, 29, 1, 345600, a993a348279f71db20e48a879c718096 +0, 30, 30, 1, 345600, b999b6a51b3bdeb99df80aa88f2c43ff +0, 31, 31, 1, 345600, 2c851f444aaf1dd6f149ee8e6e1bdfa4 +0, 32, 32, 1, 345600, a50301d48d283e9881d142cd87128d86 +0, 33, 33, 1, 345600, 0ddffa560c6310a2ad1cb534336472ac +0, 34, 34, 1, 345600, 5f5565daeb737f3543a5d07ff9115d4a +0, 35, 35, 1, 345600, 91640f9887d074221e4e08f9a97a938b +0, 36, 36, 1, 345600, bc01f13d5c73a92895ca2ad13209628a +0, 37, 37, 1, 345600, 9750f282817c6df143565e2f57f9f85f +0, 38, 38, 1, 345600, a1803a3ce342d25b45f913cc8b9fe961 +0, 39, 39, 1, 345600, 4a0ae00d4e9df52c7df5bfb08236ae96 +0, 40, 40, 1, 345600, 819b12f2f7356b296bffd39e85c9b6be +0, 41, 41, 1, 345600, 40a5af89bff4b10a10d0a51ab5eeb4e0 +0, 42, 42, 1, 345600, 454a9b71be88d3c026cb7239988f3e37 +0, 43, 43, 1, 345600, c653e9c9d64c9495b764b0a6eb3bfbc9 +0, 44, 44, 1, 345600, 6a4facbf8e14ff6177fd4b0f6f659180 +0, 45, 45, 1, 345600, 843d5b77042e347c3d21d113ba2993fb +0, 46, 46, 1, 345600, 284785e924efba8ab17e6e1f75329287 +0, 47, 47, 1, 345600, 4f2b2d0f3dc4ad165e0bc56560930d49 +0, 48, 48, 1, 345600, 71154e17c2f5c316272e8904ef61c0bc +0, 49, 49, 1, 345600, 6b10588be4540b5dbbd765db406b8723 +0, 50, 50, 1, 345600, aaf62a95b621c8de2dca22f78594b8c7 +0, 51, 51, 1, 345600, bb508b634416287baf4406f70ca3693d +0, 52, 52, 1, 345600, 0551149846fca1ae1d164a7a7c64439f +0, 53, 53, 1, 345600, c3fad13ac1643744c4ea194763ae6cf7 +0, 54, 54, 1, 345600, 4c487adf3ec204c041a50cbf82abd8e8 +0, 55, 55, 1, 345600, dc48539225f4dc05588995d4288c71d0 +0, 56, 56, 1, 345600, be005c4f81422a775fc909dcee84094d +0, 57, 57, 1, 345600, a374c2ed0e644f03cbb8cd5456877cbb +0, 58, 58, 1, 345600, 9b7d5fac577cf0d82e11551cd9b280db +0, 59, 59, 1, 345600, c1d0551bc5cd1f53133e30ed811d8032 +0, 60, 60, 1, 345600, 6ab563cf2df92a2e9e1b8b90c0e0ec07 +0, 61, 61, 1, 345600, 19dadbe3c3638578fe8a3ed3f730858e +0, 62, 62, 1, 345600, e9810a12f7c14c4b8305a418e4bc3055 +0, 63, 63, 1, 345600, d45d74535cd471949238716bdc12c16f +0, 64, 64, 1, 345600, d1c2c19d0aba4170fe1a03f9c10b6863 +0, 65, 65, 1, 345600, 047c7fbfcce41fcaec6f1e1686db0429 +0, 66, 66, 1, 345600, 4adc1aa1017880f6baf4786ecd2c8ddb +0, 67, 67, 1, 345600, 90bad80d9e6c75784423f74984e40dd2 +0, 68, 68, 1, 345600, feb378d740e1e5f9312bf68c047040c3 +0, 69, 69, 1, 345600, 28b1de125fd6f6a9d42eb42300be7a3f +0, 70, 70, 1, 345600, 495043e65515c790c1fe026c9d2c0a49 +0, 71, 71, 1, 345600, fa6d5062932e7fc11fbfe31349ecbbfd +0, 72, 72, 1, 345600, 897952d332218f2dab7d760b2d2076eb +0, 73, 73, 1, 345600, 79dfce7ac29b96ef23c7f648e87a3e0b +0, 74, 74, 1, 345600, 94d11a85dc32b4693048a39a6227919b +0, 75, 75, 1, 345600, f9c149dbdc71c60f146cf68a673102d5 +0, 76, 76, 1, 345600, febddbb90b3f37cb29b07102575d844f +0, 77, 77, 1, 345600, b9e5cdfa63c2637f2204dcb885608bb9 +0, 78, 78, 1, 345600, 051773f40a3749b54c5a802f8a97128f +0, 79, 79, 1, 345600, 5fed52a298b8eef94ebe21c03313a5d7 +0, 80, 80, 1, 345600, f8a447cd738ec587fbacde061db51be5 +0, 81, 81, 1, 345600, 474cfd0529c0a5daffdcaed5183ee583 +0, 82, 82, 1, 345600, b0dd2ddd7037e70e774a7b3baad0b094 +0, 83, 83, 1, 345600, 86622696017283d3ce98e71d10f89f75 +0, 84, 84, 1, 345600, 20d6ae8b4dcf75ab31cc1f00002298ca +0, 85, 85, 1, 345600, a882528cd387fb3a55d6e184a33fe2c9 +0, 86, 86, 1, 345600, 6bfcb539ce16f3db0d7f24dab6166913 +0, 87, 87, 1, 345600, 6bfcb539ce16f3db0d7f24dab6166913 +0, 88, 88, 1, 345600, 3bde52ee85883e4f353d4736a47b3874 +0, 89, 89, 1, 345600, 6f20835eb29f824d6a3e1be0ce772f08 +0, 90, 90, 1, 345600, 7b99b15c1b8fbe0e643b75fda7b17b04 +0, 91, 91, 1, 345600, f0139cd28a0030d611d60e9d28837af0 +0, 92, 92, 1, 345600, f0139cd28a0030d611d60e9d28837af0 +0, 93, 93, 1, 345600, adf0a37ad23c38b54c7394871c876468 +0, 94, 94, 1, 345600, f0bd37bcb8299e90efd05a0e01c84029 +0, 95, 95, 1, 345600, 8a9d76bc611731eabc29bbf231e21528 From 01763144dcc1bc47fa4967d91d3fedb25e3ef556 Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Fri, 3 Nov 2017 17:10:55 -0700 Subject: [PATCH 0925/2557] Avoid corrupting diagnostic state with _Pragma changes. The macros for ICC and MSVC correctly push and pop the diagnostic state of the compiler when disabling deprecation warnings. The ones for clang/gcc should do the same. Without this, if a blanket deprecation warning is applied to the code base it'll be flipped back on incorrectly with FF_ENABLE_DEPRECATION_WARNINGS. Signed-off-by: Dale Curtis Signed-off-by: Michael Niedermayer --- libavutil/internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavutil/internal.h b/libavutil/internal.h index fef5089097ec8..72ae0ad89b2bc 100644 --- a/libavutil/internal.h +++ b/libavutil/internal.h @@ -81,8 +81,8 @@ # define FF_DISABLE_DEPRECATION_WARNINGS __pragma(warning(push)) __pragma(warning(disable:4996)) # define FF_ENABLE_DEPRECATION_WARNINGS __pragma(warning(pop)) # else -# define FF_DISABLE_DEPRECATION_WARNINGS _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -# define FF_ENABLE_DEPRECATION_WARNINGS _Pragma("GCC diagnostic warning \"-Wdeprecated-declarations\"") +# define FF_DISABLE_DEPRECATION_WARNINGS _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +# define FF_ENABLE_DEPRECATION_WARNINGS _Pragma("GCC diagnostic pop") # endif #else # define FF_DISABLE_DEPRECATION_WARNINGS From 54f8ac199fe38b2837146621963bb543868130be Mon Sep 17 00:00:00 2001 From: Sasi Inguva Date: Mon, 13 Nov 2017 18:09:28 -0800 Subject: [PATCH 0926/2557] lavf/mov.c: Don't correct edit list start to zero, when we can't find a frame before edit list start. After c2a8f0fcbe57ea9ccaa864130f078af10516c3c1 this can happen on normal edit lists starting on a B-frame. Signed-off-by: Sasi Inguva Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 4 +- tests/fate/mov.mak | 6 + tests/ref/fate/mov-bbi-elst-starts-b | 391 +++++++++++++++++++++++++++ 3 files changed, 398 insertions(+), 3 deletions(-) create mode 100644 tests/ref/fate/mov-bbi-elst-starts-b diff --git a/libavformat/mov.c b/libavformat/mov.c index fd170baa57f9e..79023ef369526 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3380,13 +3380,11 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) if (find_prev_closest_index(st, e_old, nb_old, ctts_data_old, ctts_count_old, search_timestamp, AVSEEK_FLAG_ANY, &index, &ctts_index_old, &ctts_sample_old) < 0) { av_log(mov->fc, AV_LOG_WARNING, - "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n" - "Rounding edit list media time to zero.\n", + "st: %d edit list %"PRId64" Cannot find an index entry before timestamp: %"PRId64".\n", st->index, edit_list_index, search_timestamp); index = 0; ctts_index_old = 0; ctts_sample_old = 0; - edit_list_media_time = 0; } } current = e_old + index; diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index a98372c5e1383..680baea7734c7 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -12,6 +12,7 @@ FATE_MOV = fate-mov-3elist \ fate-mov-ibi-elst-starts-b \ fate-mov-elst-ends-betn-b-and-i \ fate-mov-frag-overlap \ + fate-mov-bbi-elst-starts-b \ FATE_MOV_FFPROBE = fate-mov-aac-2048-priming \ fate-mov-zombie \ @@ -63,6 +64,11 @@ fate-mov-ibi-elst-starts-b: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES) # Makes sure that we handle overlapping framgments fate-mov-frag-overlap: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/frag_overlap.mp4 +# Makes sure that we pick the right frames according to edit list when there is no keyframe with PTS < edit list start. +# For example, when video starts on a B-frame, and edit list starts on that B-frame too. +# GOP structure : B B I in presentation order. +fate-mov-bbi-elst-starts-b: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/h264/twofields_packet.mp4 + fate-mov-aac-2048-priming: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_packets -print_format compact $(TARGET_SAMPLES)/mov/aac-2048-priming.mov fate-mov-zombie: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_streams -show_packets -show_frames -bitexact -print_format compact $(TARGET_SAMPLES)/mov/white_zombie_scrunch-part.mov diff --git a/tests/ref/fate/mov-bbi-elst-starts-b b/tests/ref/fate/mov-bbi-elst-starts-b new file mode 100644 index 0000000000000..d3ede1a86cada --- /dev/null +++ b/tests/ref/fate/mov-bbi-elst-starts-b @@ -0,0 +1,391 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1001/30000 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 1920x1080 +#sar 0: 1/1 +#tb 1: 1/48000 +#media_type 1: audio +#codec_id 1: pcm_s16le +#sample_rate 1: 48000 +#channel_layout 1: 3 +#channel_layout_name 1: stereo +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 3110400, e9454409af76038dbe56e834921d2fa8 +1, 0, 0, 1024, 4096, 620f0b67a91f7f74151bc5be745b7110 +1, 1024, 1024, 1024, 4096, 8ab1a8e40b154f577914e43ec6cdc674 +0, 1, 1, 1, 3110400, 37aa620e494d22ba248feea9a5a869a0 +1, 2048, 2048, 1024, 4096, 41f09b125271955596ef56436e5ae7b3 +1, 3072, 3072, 1024, 4096, e4934aa9fbaf7dcd578fe9f404bfdd39 +0, 2, 2, 1, 3110400, 7b8be9619e4e1d618ab1ed85aff3957b +1, 4096, 4096, 1024, 4096, 5321f9a453ff71e420b592c9188560f4 +0, 3, 3, 1, 3110400, 756a4551420853bc3ae444e6b86169f3 +1, 5120, 5120, 1024, 4096, fa45be5ec01b9c0ae78f876f290602e2 +1, 6144, 6144, 1024, 4096, bce7b47534cf6ae5db1fa27805fd52a6 +0, 4, 4, 1, 3110400, 94a93c1669a96ebf41a7258177849396 +1, 7168, 7168, 1024, 4096, 15f899020d6e186b2f2a15b60034fa26 +0, 5, 5, 1, 3110400, 5d1c49d3f43cd472683e4a039e376af5 +1, 8192, 8192, 1024, 4096, 9038d943078707eac0eff9126911b9d0 +1, 9216, 9216, 1024, 4096, 40dced7d76db2c011be7b04f1c6e9236 +0, 6, 6, 1, 3110400, e0e88cc34b0a9d7963cddf554a3909f0 +1, 10240, 10240, 1024, 4096, eadb875a43a9b7b89c371af7ca8da51d +0, 7, 7, 1, 3110400, 1f464f2427aa3842224803b6d67154f8 +1, 11264, 11264, 1024, 4096, 89cc2aaf68c534909f416174a8c78a55 +1, 12288, 12288, 1024, 4096, 4698d55945ef20b80f7750cc7c3ae4cc +0, 8, 8, 1, 3110400, e5d610b8e53203b5ccb01877acb3ac56 +1, 13312, 13312, 1024, 4096, 4c13aba7b37754180ccc37781f7f7071 +1, 14336, 14336, 1024, 4096, d5cbb68356d98fc9ba95d0f1a8b64982 +0, 9, 9, 1, 3110400, d1363fbdffbb85a0affe660bfd09b98c +1, 15360, 15360, 1024, 4096, a1434238bb68788c5a67718984f81386 +0, 10, 10, 1, 3110400, 130bb4c17e963b092a717325498c06c3 +1, 16384, 16384, 1024, 4096, ec4698b981291bbc6f68f0102459e10b +1, 17408, 17408, 1024, 4096, 290f2d4a4192950ce6f8d32d12ee9639 +0, 11, 11, 1, 3110400, a3cb7a37fef5d8a49815dd15970c1f3d +1, 18432, 18432, 1024, 4096, 7751f23e652fb0e900c818d7bbf6d439 +0, 12, 12, 1, 3110400, 7dc4a4334fa9bb61f2ad56b3d059b3f7 +1, 19456, 19456, 1024, 4096, d53b61ab050826349647c0eca80ba055 +1, 20480, 20480, 1024, 4096, a680a7614abcc7a1abcd1f9e3e2adecc +0, 13, 13, 1, 3110400, ccda106ec5899787c3bc8679ee052854 +1, 21504, 21504, 1024, 4096, eac237797a6cf2175dd20c9781558292 +0, 14, 14, 1, 3110400, 4254c7b01a67a0810bf234ba7b1f59d0 +1, 22528, 22528, 1024, 4096, fc5c373095e1160dc9d74e9cbdfb8c28 +1, 23552, 23552, 1024, 4096, 309f3dc4277470878ce57f5fd9973c5b +0, 15, 15, 1, 3110400, 6c0acd9781cfecaf9a10fe91f8d6ec41 +1, 24576, 24576, 1024, 4096, c5211b49eb51cea4c16079eb54df3d12 +1, 25600, 25600, 1024, 4096, 632bdda9a5f3b2cd6803cecb52354918 +0, 16, 16, 1, 3110400, 2a9d5db0bc2f54e2c66834db64386bb7 +1, 26624, 26624, 1024, 4096, b6a34f7a303ac78ea59b1bd585ca7e7a +0, 17, 17, 1, 3110400, 0140f515be87da399061764050d15b16 +1, 27648, 27648, 1024, 4096, 3f4ef420b203060179a9377b9494794e +1, 28672, 28672, 1024, 4096, 6a1469f30159027a20f29b457cdaf8ec +0, 18, 18, 1, 3110400, cad554fe221fbd8ee848facebd7b24d2 +1, 29696, 29696, 1024, 4096, 03cf0150f76f40a4becf6b24f852bb03 +0, 19, 19, 1, 3110400, 1e8474911cb1bd831808dc2beba540c0 +1, 30720, 30720, 1024, 4096, 9beb867892f94b7890368ef9232e9059 +1, 31744, 31744, 1024, 4096, 82b2ade2371db061c320948decb364dd +0, 20, 20, 1, 3110400, f39c483fbf3c598c38cf543abad2c03c +1, 32768, 32768, 1024, 4096, a70e4b5ce175aa77271de0236fffe581 +0, 21, 21, 1, 3110400, 3b21171a003827a203c0c5853c36893e +1, 33792, 33792, 1024, 4096, eb81a2d0ba1e33b9f482de7b18055d22 +1, 34816, 34816, 1024, 4096, bcf3a843ec8e3c7f147fb6de53148f3a +0, 22, 22, 1, 3110400, 40e8733f93c468cb58c3921c80f81c68 +1, 35840, 35840, 1024, 4096, 80e2259a1c660a1a7be3b60dc41b3d97 +0, 23, 23, 1, 3110400, a2d716f215af7d778bd605decae201dd +1, 36864, 36864, 1024, 4096, 48674a7c0fe9e07f24661ccb86a3337e +1, 37888, 37888, 1024, 4096, 743debd528abc74a584c6ce6f7254c0f +0, 24, 24, 1, 3110400, e6fb8d3f1c9747f185b50eded67ff0ab +1, 38912, 38912, 1024, 4096, 13df1fb081608357167356d5ec1634d7 +1, 39936, 39936, 1024, 4096, 0ef50ab373ffe390f301dca86a7ab831 +0, 25, 25, 1, 3110400, fe4e0cf566674672ad043f24eae02e63 +1, 40960, 40960, 1024, 4096, 3f7b13e5660491d3000b9af7752c0b9a +0, 26, 26, 1, 3110400, f57d4d32012dfcb14a270bdc90812e5e +1, 41984, 41984, 1024, 4096, 403dfa2233788e04297ba7b884b4938b +1, 43008, 43008, 1024, 4096, 87da545df36479d27f0584864e2fcf1c +0, 27, 27, 1, 3110400, fe7aa8c1754b9590fe75b783d4e126ed +1, 44032, 44032, 1024, 4096, 65b2599f40c24ff42f0b7f0f35e2588c +0, 28, 28, 1, 3110400, 29ae6e541021bf481c8937c37ac34570 +1, 45056, 45056, 1024, 4096, d090b8e24ad0b08953d9f7dca9d1d296 +1, 46080, 46080, 1024, 4096, 45a46389b5dfc99318327b4014162827 +0, 29, 29, 1, 3110400, 211e0803b5a704c7ef1c36fc5c182710 +1, 47104, 47104, 1024, 4096, 5a4f770dbaca63d1ae6580cb147c73f8 +0, 30, 30, 1, 3110400, a4ea3a4686d214ad54fcdce63f8c2dc0 +1, 48128, 48128, 1024, 4096, b365fa5a5642be5f7e426abed06adf3d +1, 49152, 49152, 1024, 4096, 5bb22433db0e71d8ad58abdb9713ec53 +0, 31, 31, 1, 3110400, 8af971cf637609534ec59b6f29a3666e +1, 50176, 50176, 1024, 4096, 59c753d1b4968588a6d25734b9d88487 +1, 51200, 51200, 1024, 4096, cdce1887048f4f14273da946e3eb3c18 +0, 32, 32, 1, 3110400, 8cfe93dfd76e4f97cc04a145bb559af5 +1, 52224, 52224, 1024, 4096, 0b21542c844fe587d32098bb5535a107 +0, 33, 33, 1, 3110400, 691fe61398016f767ea7ba781ef72953 +1, 53248, 53248, 1024, 4096, 67344ce61d0972a0d7e01d10154cc192 +1, 54272, 54272, 1024, 4096, 690b3d79c5689545992d9d427c202c80 +0, 34, 34, 1, 3110400, 7eaf5bc5e942f8218f46c9c505d7b58c +1, 55296, 55296, 1024, 4096, 48e8ab0926cac6d2097f7e74f7d87214 +0, 35, 35, 1, 3110400, feacc8282186935e310ec2dccbb79239 +1, 56320, 56320, 1024, 4096, 7d6d0f8705f4978abe4e501a19fae18d +1, 57344, 57344, 1024, 4096, 8b8069b4133f6b646f83c0c333ca08ee +0, 36, 36, 1, 3110400, a5dfb5c4c23e647e2c77dd117e4ed714 +1, 58368, 58368, 1024, 4096, 7738b55c8ee4c7fe9418b90aea2bc561 +0, 37, 37, 1, 3110400, da9306c2872788ba2a587eab7f597f13 +1, 59392, 59392, 1024, 4096, d5dfd403866781c8b8d5f7df7f8c7e86 +1, 60416, 60416, 1024, 4096, 841ca64b5056fadc91a18b65e5d368f3 +0, 38, 38, 1, 3110400, 19d14a655aa02cc2767afd9ed9bc2ff4 +1, 61440, 61440, 1024, 4096, 6de6157593f09a1b662ce8be40d4a64e +0, 39, 39, 1, 3110400, 4d9e6455fb71d5cd511dddf894b4f7d8 +1, 62464, 62464, 1024, 4096, d15b3a0f417815474cbca73d59fc78fb +1, 63488, 63488, 1024, 4096, 312408569a1e68f71cf7b31704641ed1 +0, 40, 40, 1, 3110400, 052c32c00bc1b40d5270f4b5c4d34d6b +1, 64512, 64512, 1024, 4096, e88ca9f4ded21e07ea0b4101c4d36f1c +1, 65536, 65536, 1024, 4096, 9fbdf5e0d8df6a4c699877a5d72e77d3 +0, 41, 41, 1, 3110400, 645e0c3eb8599c2cc712a97cbae9d1d3 +1, 66560, 66560, 1024, 4096, ec5daa820b0a67feeff3ed953a3c5bdd +0, 42, 42, 1, 3110400, d0b3fe092511fed0e384ffad85f6ae3c +1, 67584, 67584, 1024, 4096, b050ff15f06ca48c8c7820bb107232ff +1, 68608, 68608, 1024, 4096, 88751e60258f292e2fd927a492ddb9a6 +0, 43, 43, 1, 3110400, 131c090f806658ffbb4949b3310a6348 +1, 69632, 69632, 1024, 4096, da7d5b875c390e8d4e1f3103c0331340 +0, 44, 44, 1, 3110400, 71e8042ed01a1bbe971417d87685dda1 +1, 70656, 70656, 1024, 4096, 9e2c8e378228356c1a0e312875fee8a4 +1, 71680, 71680, 1024, 4096, d1ac505bd1922769852b32c6476e9c34 +0, 45, 45, 1, 3110400, 948cc8d7eceb2e512c8660063143557b +1, 72704, 72704, 1024, 4096, 8861798a4bae7045c78175b3e783654b +0, 46, 46, 1, 3110400, 8b580d4f620af52ac0a5702197f5e9d6 +1, 73728, 73728, 1024, 4096, e9021bdc21613b1325d0f735d5a06115 +1, 74752, 74752, 1024, 4096, 5cbb598627500e8b5d5e39ba3750f826 +0, 47, 47, 1, 3110400, a30bfc0727c6abb477751969c1b1450c +1, 75776, 75776, 1024, 4096, a605c5242d14724f36d7bd7ddec1a07c +1, 76800, 76800, 1024, 4096, 30a60b54960e9ce33566cdd6bab77ac1 +0, 48, 48, 1, 3110400, 28381142e60e9011d0cd75e7881c1956 +1, 77824, 77824, 1024, 4096, d534fd1afbadb92b2cd19046562bdecb +0, 49, 49, 1, 3110400, 1b4bdae40d76ed7625f85da7c5289360 +1, 78848, 78848, 1024, 4096, 95995add4ca88b76bb2a85c3078ffa45 +1, 79872, 79872, 1024, 4096, a1a06ef2915ba565110703180e31dda3 +0, 50, 50, 1, 3110400, 354fb545adf6082dc57b8077ba1466ad +1, 80896, 80896, 1024, 4096, 21ee5850fd1474bf820f607aad597b2f +0, 51, 51, 1, 3110400, c969f21be0dcbef6b232d3f0a9e3f189 +1, 81920, 81920, 1024, 4096, 4960c6db1ee2ea35d3c8b6dade2a8000 +1, 82944, 82944, 1024, 4096, 63031c5985de637b2ddeefaf8e3f1ffd +0, 52, 52, 1, 3110400, 4ff19ab89ebe466e8ce3df0ba25b6b0a +1, 83968, 83968, 1024, 4096, 537a6f30a21a0d8707fe8b7cb71ff094 +0, 53, 53, 1, 3110400, 49f601932c19ae8d405771e9cfd4f9e8 +1, 84992, 84992, 1024, 4096, d0c4c9c81b5e8525146049023b402889 +1, 86016, 86016, 1024, 4096, 0ef30a63997229bfa0f3f7958736c444 +0, 54, 54, 1, 3110400, c75d2221327d5953b013fdc9d36dbcd3 +1, 87040, 87040, 1024, 4096, eb6986d43812a3edee7f0a587422db77 +1, 88064, 88064, 1024, 4096, ab038bc9d57d2e5434d641dce5e7bb13 +0, 55, 55, 1, 3110400, 6c8b8c6012b6ac36c4c2a3ab5629ec61 +1, 89088, 89088, 1024, 4096, ee526f1ac04958177b545e714cde2a44 +0, 56, 56, 1, 3110400, 44a05705ad5cb730e7244c36b4f94771 +1, 90112, 90112, 1024, 4096, 77e99ace435ef96c6d258ec12bd1d8d8 +1, 91136, 91136, 1024, 4096, 7101832bf0a8bb43d36f0bd6107b0ae8 +0, 57, 57, 1, 3110400, 0ee53224814c84224525181aacbd9a39 +1, 92160, 92160, 1024, 4096, 9d6cbd4db1b588072bf0e9ababc40833 +0, 58, 58, 1, 3110400, cd7797aa75c96a2a71e939ea6b677310 +1, 93184, 93184, 1024, 4096, 5c0f3e20b1b9caae82496041b073f0e4 +1, 94208, 94208, 1024, 4096, 3a5a24363a702cc6775ca7fb29304c21 +0, 59, 59, 1, 3110400, ac2207156da29fd33ca1c66224445bbc +1, 95232, 95232, 1024, 4096, 519bb1e9f1a945e45a5e345764b55a03 +0, 60, 60, 1, 3110400, 1669c959bd2b6f245cc83ea00d0de83f +1, 96256, 96256, 1024, 4096, 58b434d59ac97a54fbc1a72a36841d93 +1, 97280, 97280, 1024, 4096, 36d327ce01b032197975d704481373ba +0, 61, 61, 1, 3110400, a74e6586842a4c877fa9a123e7b8ef94 +1, 98304, 98304, 1024, 4096, 966ebe56895a9fe4a231803276e7687c +0, 62, 62, 1, 3110400, 5af4edbf8a77ead17f4891cbac6d72be +1, 99328, 99328, 1024, 4096, dd92c3241e45d54cc072fc0307d1850c +1, 100352, 100352, 1024, 4096, af6face87dd545c52dbc0f8c085f66ee +0, 63, 63, 1, 3110400, 52598cb5f3cb75bc401370118bcb2c49 +1, 101376, 101376, 1024, 4096, 70f4ac8c2d680c3f66b3096bb169dd30 +1, 102400, 102400, 1024, 4096, a5b78e534c204a269c40d8a53da9a39a +0, 64, 64, 1, 3110400, d44aa05de89e71b3af23de9afbb2a3b1 +1, 103424, 103424, 1024, 4096, c0f82f0eebe9d9812cf3e38e3fbe6596 +0, 65, 65, 1, 3110400, 161fd1ff8b477a137e113ce7e6ac26f7 +1, 104448, 104448, 1024, 4096, eec373a11d6294d737548b0ff6fcffff +1, 105472, 105472, 1024, 4096, 9aa7b5313fb4d492c61ef93003cbe85d +0, 66, 66, 1, 3110400, b9b5efaf5f74954897882b0f09a5c088 +1, 106496, 106496, 1024, 4096, 85fe03553bd0ef3af6dbffb7efc5c2ad +0, 67, 67, 1, 3110400, 1405f3d5e75c2ffd390b46f7def70478 +1, 107520, 107520, 1024, 4096, a9ee3b7719229b9f772705c7cd804a58 +1, 108544, 108544, 1024, 4096, e392d92e74371656de53c0cca9004480 +0, 68, 68, 1, 3110400, 3bf19eda056d5fc609662bf5ca8e3b33 +1, 109568, 109568, 1024, 4096, 247a669c58d412878f89e9a99f46867f +0, 69, 69, 1, 3110400, 8ba1925dc6b38a340e51aa234b5ff4df +1, 110592, 110592, 1024, 4096, 32c437e01e7961977b02a2abe562b8bb +1, 111616, 111616, 1024, 4096, 2ce6fc2129f6d9eb7423c25539aa2cb7 +0, 70, 70, 1, 3110400, 301aecbe3f8bf3831d6de540a568abbc +1, 112640, 112640, 1024, 4096, cf1974b1dbe086c4299d8199614d0079 +1, 113664, 113664, 1024, 4096, ae311b2ef095c1467900ff4470b290de +0, 71, 71, 1, 3110400, 388565f088710aeb0f50ecdf8ef0ee86 +1, 114688, 114688, 1024, 4096, 00bdb308989a3219d178fb175e84b79e +0, 72, 72, 1, 3110400, df27196ff8da5085c58979deeae9c4a1 +1, 115712, 115712, 1024, 4096, 2ddfe844f921e3e0561bfce3790a8251 +1, 116736, 116736, 1024, 4096, 0c02111f1250fc674b2cb71770dbd1d3 +0, 73, 73, 1, 3110400, 750226c84aae270449e0a20751218217 +1, 117760, 117760, 1024, 4096, cf24fdd955d70a7872b27411f89bccd2 +0, 74, 74, 1, 3110400, 076d4246e5494e6d5cf8ffb09be3a751 +1, 118784, 118784, 1024, 4096, 7c5516c05815edae32bade8324974657 +1, 119808, 119808, 1024, 4096, 1e59ed977a9aecc9abe261db11ca2605 +0, 75, 75, 1, 3110400, 9f626289f18a3482628b511840deaa10 +1, 120832, 120832, 1024, 4096, 05a8dce0c37fcc6ab053ac73eb785b0b +0, 76, 76, 1, 3110400, f925e3ff4bda9962a313b6ac21a201f1 +1, 121856, 121856, 1024, 4096, 91a046c3d0ad3bbfdeb38dcd305d023a +1, 122880, 122880, 1024, 4096, 3f58f6172adc6a3166ec24ee820331ec +0, 77, 77, 1, 3110400, 1d893861545e804944c519e580204988 +1, 123904, 123904, 1024, 4096, 17dea588661e4c31aeb98522afc63ae9 +0, 78, 78, 1, 3110400, 4d42fca73082fde38020a8fec0b27db2 +1, 124928, 124928, 1024, 4096, 1e1dc5629306be84cc819a4bf6e64e7c +1, 125952, 125952, 1024, 4096, 44ce3b6d8a17cfebe54e924626f2af94 +0, 79, 79, 1, 3110400, ed88335480ef00aedcf73c3a8712705c +1, 126976, 126976, 1024, 4096, d10235d48b65a30f1b742153e1904699 +1, 128000, 128000, 1024, 4096, bca2dd5314938e30ae693b9690e38f11 +0, 80, 80, 1, 3110400, 968ba4c93f80cb8c6fbfaccb765c3d70 +1, 129024, 129024, 1024, 4096, c6e9c444ee31d2fe8e3cde7d089a08c8 +0, 81, 81, 1, 3110400, 01ef52b0a18f46556ba9e00d1b0c77af +1, 130048, 130048, 1024, 4096, 8952dfeace4fd2c84273151248641cbb +1, 131072, 131072, 1024, 4096, 70361338cc7d66a0b1d9fb4b9a106c72 +0, 82, 82, 1, 3110400, 54582f2ae6878b37cbd1b5c576fd09c7 +1, 132096, 132096, 1024, 4096, 5a6c251fb22fc88ebc346020b4a8fcd7 +0, 83, 83, 1, 3110400, fec6585d244257b52c90cfa19b22fd7c +1, 133120, 133120, 1024, 4096, 9f7558a3d28e5c2c67034496e71d6fca +1, 134144, 134144, 1024, 4096, 3669b9c3951716f471c279fef1baba1a +0, 84, 84, 1, 3110400, be1e0237c5d8bab98aa75a91e0d4bd9b +1, 135168, 135168, 1024, 4096, 3c749f168978e687c8b5986406977e8a +0, 85, 85, 1, 3110400, 1138a9f316d1a2a9ae3c42d777561595 +1, 136192, 136192, 1024, 4096, 2524384a99ff83fe4c4152a48ae41ed3 +1, 137216, 137216, 1024, 4096, 31074121ab228b6efce8e7d7bd3dce44 +0, 86, 86, 1, 3110400, 62da42e9e8643ec9b1299bbeaffa4be5 +1, 138240, 138240, 1024, 4096, b62106dc88181c36a57a5e4c133372f4 +1, 139264, 139264, 1024, 4096, 68e582cf173e2355fc0474614c3f3f00 +0, 87, 87, 1, 3110400, 55fc4dcfb7f8bab37518884fc6747416 +1, 140288, 140288, 1024, 4096, 061518430ba9d0fb160ecfab5f80181d +0, 88, 88, 1, 3110400, 51be69793bfae3fe078d04e8dee3a48b +1, 141312, 141312, 1024, 4096, 0b788c73ac083e5c35d8d6e23071e5a7 +1, 142336, 142336, 1024, 4096, 8e6538e8dce86832b06b78a6a1919a8a +0, 89, 89, 1, 3110400, 363b794880a2cc06e5be4626c6847c19 +1, 143360, 143360, 1024, 4096, 76a9f155449798cb858c7d33aab635d0 +0, 90, 90, 1, 3110400, cd1d585cf9cb68f72f7d6a0ec9ab96ab +1, 144384, 144384, 1024, 4096, b4b8c7c06577dc7ec8aa09041d741d15 +1, 145408, 145408, 1024, 4096, 69ef1d797c314b5e6f4ff63818bc4ae5 +0, 91, 91, 1, 3110400, 138f8686ee7294bf4af072cee7043f52 +1, 146432, 146432, 1024, 4096, a60e780917a71df71171c07fbae7ee8d +0, 92, 92, 1, 3110400, 137c1bdc2bb6fa1e181f84b09c14e0b6 +1, 147456, 147456, 1024, 4096, dc2f78381824b76fa9f2efa8436f91b9 +1, 148480, 148480, 1024, 4096, 1796b71e22f477f6312e1b16d046a778 +0, 93, 93, 1, 3110400, e7bc46739c46ec886fc5059af72f772a +1, 149504, 149504, 1024, 4096, cea89e76c0df3a9a61ed957beba0456b +1, 150528, 150528, 1024, 4096, 02fd38f6ace4f8ea8821160e37c2e829 +0, 94, 94, 1, 3110400, db4c2aa67c76573e4880b029bef59c8d +1, 151552, 151552, 1024, 4096, 15148b9aa2f3211c83c074b4bf94f02b +0, 95, 95, 1, 3110400, 3a287113ad2196420a0474243bd1813d +1, 152576, 152576, 1024, 4096, 4db71785b7d01e84ef2da2ca59f38774 +1, 153600, 153600, 1024, 4096, e1a43fdf9aad45826dcba84bd9fba837 +0, 96, 96, 1, 3110400, d3ed803ca1984f021802e6c7364cb57f +1, 154624, 154624, 1024, 4096, 30035e6811f6dadc043db12f83a701bc +0, 97, 97, 1, 3110400, 776d99c2973261c12e978fe9fe5c5794 +1, 155648, 155648, 1024, 4096, 42490702f73b2dc61898937ee4c5dea8 +1, 156672, 156672, 1024, 4096, 20d806b88965a107021abbb04cf3d9a3 +0, 98, 98, 1, 3110400, 62ee2ec1261db8544ded9db8c4442f15 +1, 157696, 157696, 1024, 4096, 0f1362440e64448b7bccead0028bd311 +0, 99, 99, 1, 3110400, 1bfabc7ab3701e112e76955a449431d7 +1, 158720, 158720, 1024, 4096, 7155472e706f3f46eec2443bba9e8245 +1, 159744, 159744, 1024, 4096, 5e00e0ee23c41794613ed6058e8ce338 +0, 100, 100, 1, 3110400, e03dfc70c25b77fc47ea42ddb8d5da5c +1, 160768, 160768, 1024, 4096, bdb9b47de0545d62966ce63d1852d5c8 +0, 101, 101, 1, 3110400, b0f0c308b49cb82fad3b4995cb60b6a1 +1, 161792, 161792, 1024, 4096, bed5fd9231e5d15b887356f6d17e2c69 +1, 162816, 162816, 1024, 4096, 7941bb3647bc685b4dedb0ae7257f6cd +0, 102, 102, 1, 3110400, 627c888ea94dabff2aaf96c800a85f7a +1, 163840, 163840, 1024, 4096, bfe15767e5b08f31e3e8c094a1014615 +1, 164864, 164864, 1024, 4096, 7898f2dc30f9f201dd1180e3bd2a9a67 +0, 103, 103, 1, 3110400, f2231eac6e5885f61f470a5c6b65ceea +1, 165888, 165888, 1024, 4096, 7a72c0f4eefd454af7d8ff720ff45e05 +0, 104, 104, 1, 3110400, ec873def59cde7c114fe27ba1b2c25a6 +1, 166912, 166912, 1024, 4096, 37f403392e90eaecbddf0d9f2790e8a3 +1, 167936, 167936, 1024, 4096, 6e014105203c7b5c862f85f1de5c9812 +0, 105, 105, 1, 3110400, 7a5e98b10b1f984b624bc6399a45dde2 +1, 168960, 168960, 1024, 4096, 66341b599fb6ca69429dd1a920029348 +0, 106, 106, 1, 3110400, 180d7b9ef69a8ee32e5fcc3b9579c11f +1, 169984, 169984, 1024, 4096, 035e13d7d5a6fa841677daeec3b18eef +1, 171008, 171008, 1024, 4096, 5d472d3fee3bcce4f2b160fa38cb126c +0, 107, 107, 1, 3110400, 8c0107e3bda4c993131b361d598b4b4d +1, 172032, 172032, 1024, 4096, fed4ed4953536004232aee9f3f30ee51 +0, 108, 108, 1, 3110400, 31e1ea32c3200a41814b5890b81c5211 +1, 173056, 173056, 1024, 4096, 95ff7c3c4ad69884d23c42bf0f27626b +1, 174080, 174080, 1024, 4096, 494881d4095a2d1f798b44b088b3653a +0, 109, 109, 1, 3110400, f6223221be5136d03c87333c7f2113c5 +1, 175104, 175104, 1024, 4096, 765ed05036c94cfe3e132b442c187857 +1, 176128, 176128, 1024, 4096, cc92716d9e076750090a67911fe759f9 +0, 110, 110, 1, 3110400, 325d0fb65e35826aebb0f80fc34f426f +1, 177152, 177152, 1024, 4096, 072b375052d0667ac2c7216653e7bbe5 +0, 111, 111, 1, 3110400, 1328e8c69419fe1c44fc6cfa1f648839 +1, 178176, 178176, 1024, 4096, 6a10a47420e4004eb8bf059394395249 +1, 179200, 179200, 1024, 4096, b405e274e3f13346862a09883dc27156 +0, 112, 112, 1, 3110400, b234f9aab6965e136bb283a2ad0fbb68 +1, 180224, 180224, 1024, 4096, 6a035de2ce67714cc256013fcaa6dc34 +0, 113, 113, 1, 3110400, 3961ef43173c69a28d2196f4fa11d37a +1, 181248, 181248, 1024, 4096, 07d43a968099c46e0696714abf0e46a4 +1, 182272, 182272, 1024, 4096, 0d24fc81f9c5d8b9b1560520e073d300 +0, 114, 114, 1, 3110400, 943c6dd42254d346d81fd55bfad60573 +1, 183296, 183296, 1024, 4096, fe4e8740a5ef9eb0dbeb44e7d3df3d09 +0, 115, 115, 1, 3110400, 0028c32eacb6f4d77cb98cf856d266e4 +1, 184320, 184320, 1024, 4096, e17bc55c8cb665aed6f304c8f51bf111 +1, 185344, 185344, 1024, 4096, 016964bc4828aaa33fae69cc46a511c9 +0, 116, 116, 1, 3110400, f478fe49fed80b92eaa182aa8e794077 +1, 186368, 186368, 1024, 4096, 0186f83d39b824d31300f2e702df2d55 +0, 117, 117, 1, 3110400, 9a52c061c135bd75ee317fe48a2cddf8 +1, 187392, 187392, 1024, 4096, f5df5e5b848a7ddb17e146c03bbcbdeb +1, 188416, 188416, 1024, 4096, f17507ae2559789a63fa688e8b30fafd +0, 118, 118, 1, 3110400, c327b95c8afa716f7719603d2b65679b +1, 189440, 189440, 1024, 4096, 1211a9da89a2fb95197f0229acaf998f +1, 190464, 190464, 1024, 4096, ae4e0feea34dd9f6dfb9981987cd9a99 +0, 119, 119, 1, 3110400, edd3b4c4fa157940b9c252a7d94e6f55 +1, 191488, 191488, 1024, 4096, 403e646272b9135422ba0e3a99fdd9e1 +0, 120, 120, 1, 3110400, 5ccdffe7356a73d2d11eb7767ddfa396 +1, 192512, 192512, 1024, 4096, 301db3a7c1a1c7c6a1594c5dc1f248bf +1, 193536, 193536, 1024, 4096, 3c804053fad95868b7fe412d385105b0 +0, 121, 121, 1, 3110400, 7c4d8083656581ccc666597da5559a46 +1, 194560, 194560, 1024, 4096, 517a23469cada9850e27e3b2c1dcb6c2 +0, 122, 122, 1, 3110400, 28cae533418f9a5d62869cbed0be384c +1, 195584, 195584, 1024, 4096, 087f72ac18ee46f75b73fe3fb6324f71 +1, 196608, 196608, 1024, 4096, 49aefd3f94d9e4783c6eab8fc877a8a9 +0, 123, 123, 1, 3110400, e9cf527a059c80461fd507bab4817069 +1, 197632, 197632, 1024, 4096, c927cf0b475a8790a8adce8b5c2b934a +0, 124, 124, 1, 3110400, a2f2518b8a25932afbb78523e8da289e +1, 198656, 198656, 1024, 4096, 7316a62c368936fa3a9905ee0f791cf9 +1, 199680, 199680, 1024, 4096, f6f14ff29ae4ba46bcdc7f13f7d94c0e +0, 125, 125, 1, 3110400, 8fcbddce7f2a6c3bc380ad4cec17e51c +1, 200704, 200704, 1024, 4096, fe187526a81876d845fe9908edca471a +1, 201728, 201728, 1024, 4096, 4959639fa30c838205aabdc00f23642c +0, 126, 126, 1, 3110400, 32ff7b550d09821b2b1eb64c288559ba +1, 202752, 202752, 1024, 4096, fda7cb19cc1efbbe1921ce981e0c7520 +0, 127, 127, 1, 3110400, 1eb4e9050a6657ab9290ac58ed3aa93f +1, 203776, 203776, 1024, 4096, fa3dc6a44013a4dd8d50103a75f4c983 +1, 204800, 204800, 1024, 4096, f59136f6a18fd40c52a2ae46058cfda0 +0, 128, 128, 1, 3110400, e45fd52e9ec3ad2d42740dd7cb5e971b +1, 205824, 205824, 1024, 4096, db5d39da79236eb59a29a372a68b640b +0, 129, 129, 1, 3110400, d625b970a797e37e465d9319471d40c3 +1, 206848, 206848, 1024, 4096, b5ad26b7f7fc2584993e2cdaa4a6b8b2 +1, 207872, 207872, 1024, 4096, d823d127304842b99b470fa4e9f5e5de +0, 130, 130, 1, 3110400, b98e4a8fd994915a3dde3def26a9b171 +1, 208896, 208896, 1024, 4096, 9e4e02881a76e858e6787f9c1d42a249 +0, 131, 131, 1, 3110400, a99b759bdfcf7f7cee8f1ee84ca2d66d +1, 209920, 209920, 1024, 4096, a476392ed5f666c03e89ab2da5ff7a58 +1, 210944, 210944, 1024, 4096, 7576416a29e679630a5233cc63e623d5 +0, 132, 132, 1, 3110400, 5439cd9643a76d21e5f1deb0aa4000a2 +1, 211968, 211968, 1024, 4096, 7239bc64a6723444d3d85dc246fafcff +1, 212992, 212992, 1024, 4096, 85ebb8c83070b65dda6e4aa2a0986825 +0, 133, 133, 1, 3110400, 383640e375fa6b46bba21acd556f0efd +1, 214016, 214016, 1024, 4096, 59f1301cc73828906b603ddfc6aa03dc +0, 134, 134, 1, 3110400, e91ba9ef2595fbee20fb0f1d5e0b92ba +1, 215040, 215040, 1024, 4096, f1b0c9d2289583354ff57376c8210644 +1, 216064, 216064, 1024, 4096, 8c52453179a06d060f5e05efed91056b +0, 135, 135, 1, 3110400, 9c8ce07f22215b8450b01e82fc085b3d +1, 217088, 217088, 1024, 4096, 6df87b285da88b1f119dd8f1d7129a39 +0, 136, 136, 1, 3110400, 4f11b553eaaa1feb682842a1123e1b43 +1, 218112, 218112, 1024, 4096, d38a17cb3b0d87d6344d87a958464046 +1, 219136, 219136, 1024, 4096, 2ba9b50d7634c431fa7001a4bfe5bc98 +0, 137, 137, 1, 3110400, 32e8823643ce4cb0154482611f4de51d +1, 220160, 220160, 1024, 4096, 5bac7eea4ea1f7fd21d01cadfaf525a7 +0, 138, 138, 1, 3110400, 207ee505f0cfb54a3fd1fd5256ba906a +1, 221184, 221184, 1024, 4096, 3ffc6fe54cbfdd2b3cd89042abd78593 +1, 222208, 222208, 1024, 4096, 223c7972f0728ebad37eec0ee5e390ef +0, 139, 139, 1, 3110400, f95de0e1f3cd2559b6a81a6dbe53ed5c +1, 223232, 223232, 1024, 4096, b65e7243cb88ce749c876beff4c23589 +0, 140, 140, 1, 3110400, 3c47b1ea481bdae7b7730084407fd22a +1, 224256, 224256, 1024, 4096, 451b0af4a0b663fe08cba704374fbe35 +1, 225280, 225280, 1024, 4096, e25d0a85ebc82d768f03dabbf28b5bf7 +0, 141, 141, 1, 3110400, fbec533f0cb4d79185e09c9917329473 +1, 226304, 226304, 1024, 4096, 5c0826fe1bd67f3ca1faeb72932e88d4 +1, 227328, 227328, 1024, 4096, bd17d92b344769f92f8ffffa1fb64fe5 +0, 142, 142, 1, 3110400, 5b9f1cf510bc72d42772a78d400d9831 +1, 228352, 228352, 1024, 4096, a8ab495cc3574c1f0f516de13a296d82 +0, 143, 143, 1, 3110400, 6b031f180439e753b6b0e36de46dc1a5 +1, 229376, 229376, 1024, 4096, b597385268405bf5fcbde4cb4c2431e0 +1, 230400, 230400, 1024, 4096, b27e1973871e6559908b71d01a3cfb44 +0, 144, 144, 1, 3110400, c09870b1e13efa8b685d89ebd781e835 +1, 231424, 231424, 1024, 4096, ede2d1664ba9685cc71a376cfce5aee4 +0, 145, 145, 1, 3110400, 439c6cc6f7157eaf046e06d9e55ddf69 +1, 232448, 232448, 1024, 4096, 6eaf360e7798b2949fda47bd906604b5 +1, 233472, 233472, 1024, 4096, 06de403c43e23b4cf650404ad5725591 +0, 146, 146, 1, 3110400, 7d5520c184c7bf3f175eea3526deb7a8 From bb4c9d0a8ead02f7d943c2bae3e36b30e605b30b Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Mon, 13 Nov 2017 21:11:27 -0800 Subject: [PATCH 0927/2557] avcodec: Don't assume separate u and v planes in ff_alloc_picture alloc_frame_buffer in ff_alloc_picture asserts that the linesize of planes 1 and 2 are the same. If the pixfmt has a single uv plane, like NV12, this won't be true. So, let's only do this check if there are more than 2 planes. We never hit this with previous hw formats because they don't set linesize to meaningful values, but the cuda hw format sets the values based on the underlying data layout. --- libavcodec/mpegpicture.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/mpegpicture.c b/libavcodec/mpegpicture.c index 9811a778b75e7..2b72346fb2498 100644 --- a/libavcodec/mpegpicture.c +++ b/libavcodec/mpegpicture.c @@ -22,6 +22,7 @@ #include "libavutil/avassert.h" #include "libavutil/common.h" +#include "libavutil/pixdesc.h" #include "avcodec.h" #include "motion_est.h" @@ -155,7 +156,8 @@ static int alloc_frame_buffer(AVCodecContext *avctx, Picture *pic, return -1; } - if (pic->f->linesize[1] != pic->f->linesize[2]) { + if (av_pix_fmt_count_planes(pic->f->format) > 2 && + pic->f->linesize[1] != pic->f->linesize[2]) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed (uv stride mismatch)\n"); ff_mpeg_unref_picture(avctx, pic); From 912ceba61b0d45caa8ba8664ddf7b18e2121ddf3 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Mon, 13 Nov 2017 21:09:27 -0800 Subject: [PATCH 0928/2557] avcodec: Implement vc1 nvdec hwaccel This hwaccel is interesting because it also works for wmv3/9 content, which is not supported by the nvidia parser used by cuviddec. --- Changelog | 2 +- configure | 3 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 2 + libavcodec/nvdec.c | 2 + libavcodec/nvdec_vc1.c | 184 +++++++++++++++++++++++++++++++++++++++++ libavcodec/vc1dec.c | 3 + libavcodec/version.h | 2 +- 8 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 libavcodec/nvdec_vc1.c diff --git a/Changelog b/Changelog index 68829f22a449e..d2b5530ad722d 100644 --- a/Changelog +++ b/Changelog @@ -13,7 +13,7 @@ version : - PCE support for extended channel layouts in the AAC encoder - native aptX encoder and decoder - Raw aptX muxer and demuxer -- NVIDIA NVDEC-accelerated H.264, HEVC and VP9 hwaccel decoding +- NVIDIA NVDEC-accelerated H.264, HEVC, VC1 and VP9 hwaccel decoding - Intel QSV-accelerated overlay filter diff --git a/configure b/configure index 3788f26956ec7..934ac3abfd9b3 100755 --- a/configure +++ b/configure @@ -2740,6 +2740,8 @@ vc1_d3d11va2_hwaccel_select="vc1_decoder" vc1_dxva2_hwaccel_deps="dxva2" vc1_dxva2_hwaccel_select="vc1_decoder" vc1_mmal_hwaccel_deps="mmal" +vc1_nvdec_hwaccel_deps="nvdec" +vc1_nvdec_hwaccel_select="vc1_decoder" vc1_qsv_hwaccel_deps="libmfx" vc1_vaapi_hwaccel_deps="vaapi" vc1_vaapi_hwaccel_select="vc1_decoder" @@ -2763,6 +2765,7 @@ vp9_vaapi_hwaccel_select="vp9_decoder" wmv3_d3d11va_hwaccel_select="vc1_d3d11va_hwaccel" wmv3_d3d11va2_hwaccel_select="vc1_d3d11va2_hwaccel" wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel" +wmv3_nvdec_hwaccel_select="vc1_nvdec_hwaccel" wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2476aecc4072e..631567257325b 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -864,6 +864,7 @@ OBJS-$(CONFIG_MPEG4_VDPAU_HWACCEL) += vdpau_mpeg4.o OBJS-$(CONFIG_MPEG4_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_VC1_D3D11VA_HWACCEL) += dxva2_vc1.o OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o +OBJS-$(CONFIG_VC1_NVDEC_HWACCEL) += nvdec_vc1.o OBJS-$(CONFIG_VC1_QSV_HWACCEL) += qsvdec_other.o OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 0781862de5126..e213f3757c0de 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -111,6 +111,7 @@ static void register_all(void) REGISTER_HWACCEL(VC1_D3D11VA, vc1_d3d11va); REGISTER_HWACCEL(VC1_D3D11VA2, vc1_d3d11va2); REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2); + REGISTER_HWACCEL(VC1_NVDEC, vc1_nvdec); REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi); REGISTER_HWACCEL(VC1_VDPAU, vc1_vdpau); REGISTER_HWACCEL(VC1_MMAL, vc1_mmal); @@ -128,6 +129,7 @@ static void register_all(void) REGISTER_HWACCEL(WMV3_D3D11VA, wmv3_d3d11va); REGISTER_HWACCEL(WMV3_D3D11VA2, wmv3_d3d11va2); REGISTER_HWACCEL(WMV3_DXVA2, wmv3_dxva2); + REGISTER_HWACCEL(WMV3_NVDEC, wmv3_nvdec); REGISTER_HWACCEL(WMV3_VAAPI, wmv3_vaapi); REGISTER_HWACCEL(WMV3_VDPAU, wmv3_vdpau); diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index ac68faca99242..20d7c3db275cf 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -54,7 +54,9 @@ static int map_avcodec_id(enum AVCodecID id) switch (id) { case AV_CODEC_ID_H264: return cudaVideoCodec_H264; case AV_CODEC_ID_HEVC: return cudaVideoCodec_HEVC; + case AV_CODEC_ID_VC1: return cudaVideoCodec_VC1; case AV_CODEC_ID_VP9: return cudaVideoCodec_VP9; + case AV_CODEC_ID_WMV3: return cudaVideoCodec_VC1; } return -1; } diff --git a/libavcodec/nvdec_vc1.c b/libavcodec/nvdec_vc1.c new file mode 100644 index 0000000000000..cf75ba5aca4f6 --- /dev/null +++ b/libavcodec/nvdec_vc1.c @@ -0,0 +1,184 @@ +/* + * VC1 HW decode acceleration through NVDEC + * + * Copyright (c) 2017 Philip Langdale + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "nvdec.h" +#include "decode.h" +#include "vc1.h" + +static unsigned char get_ref_idx(AVFrame *frame) +{ + FrameDecodeData *fdd; + NVDECFrame *cf; + + if (!frame || !frame->private_ref) + return 255; + + fdd = (FrameDecodeData*)frame->private_ref->data; + cf = (NVDECFrame*)fdd->hwaccel_priv; + + return cf->idx; +} + +static int nvdec_vc1_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + VC1Context *v = avctx->priv_data; + MpegEncContext *s = &v->s; + + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + CUVIDPICPARAMS *pp = &ctx->pic_params; + FrameDecodeData *fdd; + NVDECFrame *cf; + AVFrame *cur_frame = s->current_picture.f; + + int ret; + + ret = ff_nvdec_start_frame(avctx, cur_frame); + if (ret < 0) + return ret; + + fdd = (FrameDecodeData*)cur_frame->private_ref->data; + cf = (NVDECFrame*)fdd->hwaccel_priv; + + *pp = (CUVIDPICPARAMS) { + .PicWidthInMbs = (cur_frame->width + 15) / 16, + .FrameHeightInMbs = (cur_frame->height + 15) / 16, + .CurrPicIdx = cf->idx, + .field_pic_flag = v->field_mode, + .bottom_field_flag = v->cur_field_type, + .second_field = v->second_field, + + .intra_pic_flag = s->pict_type == AV_PICTURE_TYPE_I || + s->pict_type == AV_PICTURE_TYPE_BI, + .ref_pic_flag = s->pict_type == AV_PICTURE_TYPE_I || + s->pict_type == AV_PICTURE_TYPE_P, + + .CodecSpecific.vc1 = { + .ForwardRefIdx = get_ref_idx(s->last_picture.f), + .BackwardRefIdx = get_ref_idx(s->next_picture.f), + .FrameWidth = cur_frame->width, + .FrameHeight = cur_frame->height, + + .intra_pic_flag = s->pict_type == AV_PICTURE_TYPE_I || + s->pict_type == AV_PICTURE_TYPE_BI, + .ref_pic_flag = s->pict_type == AV_PICTURE_TYPE_I || + s->pict_type == AV_PICTURE_TYPE_P, + .progressive_fcm = v->fcm == 0, + + .profile = v->profile, + .postprocflag = v->postprocflag, + .pulldown = v->broadcast, + .interlace = v->interlace, + .tfcntrflag = v->tfcntrflag, + .finterpflag = v->finterpflag, + .psf = v->psf, + .multires = v->multires, + .syncmarker = v->resync_marker, + .rangered = v->rangered, + .maxbframes = s->max_b_frames, + + .panscan_flag = v->panscanflag, + .refdist_flag = v->refdist_flag, + .extended_mv = v->extended_mv, + .dquant = v->dquant, + .vstransform = v->vstransform, + .loopfilter = v->s.loop_filter, + .fastuvmc = v->fastuvmc, + .overlap = v->overlap, + .quantizer = v->quantizer_mode, + .extended_dmv = v->extended_dmv, + .range_mapy_flag = v->range_mapy_flag, + .range_mapy = v->range_mapy, + .range_mapuv_flag = v->range_mapuv_flag, + .range_mapuv = v->range_mapuv, + .rangeredfrm = v->rangeredfrm, + } + }; + + return 0; +} + +static int nvdec_vc1_end_frame(AVCodecContext *avctx) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + int ret = ff_nvdec_end_frame(avctx); + ctx->bitstream = NULL; + return ret; +} + +static int nvdec_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + void *tmp; + + tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated, + (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets)); + if (!tmp) + return AVERROR(ENOMEM); + ctx->slice_offsets = tmp; + + if (!ctx->bitstream) + ctx->bitstream = (uint8_t*)buffer; + + ctx->slice_offsets[ctx->nb_slices] = buffer - ctx->bitstream; + ctx->bitstream_len += size; + ctx->nb_slices++; + + return 0; +} + +static int nvdec_vc1_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) +{ + // Each frame can at most have one P and one B reference + return ff_nvdec_frame_params(avctx, hw_frames_ctx, 2); +} + +AVHWAccel ff_vc1_nvdec_hwaccel = { + .name = "vc1_nvdec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VC1, + .pix_fmt = AV_PIX_FMT_CUDA, + .start_frame = nvdec_vc1_start_frame, + .end_frame = nvdec_vc1_end_frame, + .decode_slice = nvdec_vc1_decode_slice, + .frame_params = nvdec_vc1_frame_params, + .init = ff_nvdec_decode_init, + .uninit = ff_nvdec_decode_uninit, + .priv_data_size = sizeof(NVDECContext), +}; + +#if CONFIG_WMV3_NVDEC_HWACCEL +AVHWAccel ff_wmv3_nvdec_hwaccel = { + .name = "wmv3_nvdec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV3, + .pix_fmt = AV_PIX_FMT_CUDA, + .start_frame = nvdec_vc1_start_frame, + .end_frame = nvdec_vc1_end_frame, + .decode_slice = nvdec_vc1_decode_slice, + .frame_params = nvdec_vc1_frame_params, + .init = ff_nvdec_decode_init, + .uninit = ff_nvdec_decode_uninit, + .priv_data_size = sizeof(NVDECContext), +}; +#endif diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 6bdaeca98e66e..96b8bb5364e0b 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -1119,6 +1119,9 @@ static const enum AVPixelFormat vc1_hwaccel_pixfmt_list_420[] = { AV_PIX_FMT_D3D11VA_VLD, AV_PIX_FMT_D3D11, #endif +#if CONFIG_VC1_NVDEC_HWACCEL + AV_PIX_FMT_CUDA, +#endif #if CONFIG_VC1_VAAPI_HWACCEL AV_PIX_FMT_VAAPI, #endif diff --git a/libavcodec/version.h b/libavcodec/version.h index 9d1b0ee4c83e9..88500e343fc09 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 3 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MICRO 102 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From c4131a0613c4b2c30c01b2550b41068815d27799 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 12 Nov 2017 23:57:38 -0300 Subject: [PATCH 0929/2557] avcodec: deprecate getters and setters for AVCodecContext and AVCodec fields The fields can be accessed directly, so these are not needed anymore. Signed-off-by: James Almer --- libavcodec/avcodec.h | 22 ++++++++++++++++++++++ libavcodec/utils.c | 2 ++ libavcodec/version.h | 3 +++ 3 files changed, 27 insertions(+) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 0875ae3ba0e1f..442b558d4bb15 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3235,22 +3235,41 @@ typedef struct AVCodecContext { int apply_cropping; } AVCodecContext; +#if FF_API_CODEC_GET_SET +/** + * Accessors for some AVCodecContext fields. These used to be provided for ABI + * compatibility, and do not need to be used anymore. + */ +attribute_deprecated AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); +attribute_deprecated void av_codec_set_pkt_timebase (AVCodecContext *avctx, AVRational val); +attribute_deprecated const AVCodecDescriptor *av_codec_get_codec_descriptor(const AVCodecContext *avctx); +attribute_deprecated void av_codec_set_codec_descriptor(AVCodecContext *avctx, const AVCodecDescriptor *desc); +attribute_deprecated unsigned av_codec_get_codec_properties(const AVCodecContext *avctx); +#if FF_API_LOWRES +attribute_deprecated int av_codec_get_lowres(const AVCodecContext *avctx); +attribute_deprecated void av_codec_set_lowres(AVCodecContext *avctx, int val); +#endif +attribute_deprecated int av_codec_get_seek_preroll(const AVCodecContext *avctx); +attribute_deprecated void av_codec_set_seek_preroll(AVCodecContext *avctx, int val); +attribute_deprecated uint16_t *av_codec_get_chroma_intra_matrix(const AVCodecContext *avctx); +attribute_deprecated void av_codec_set_chroma_intra_matrix(AVCodecContext *avctx, uint16_t *val); +#endif /** * AVProfile. @@ -3387,7 +3406,10 @@ typedef struct AVCodec { const char *bsfs; } AVCodec; +#if FF_API_CODEC_GET_SET +attribute_deprecated int av_codec_get_max_lowres(const AVCodec *codec); +#endif struct MpegEncContext; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index b3a578110bbf7..e50de6e89b047 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -552,6 +552,7 @@ enum AVPixelFormat avpriv_find_pix_fmt(const PixelFormatTag *tags, return AV_PIX_FMT_NONE; } +#if FF_API_CODEC_GET_SET MAKE_ACCESSORS(AVCodecContext, codec, AVRational, pkt_timebase) MAKE_ACCESSORS(AVCodecContext, codec, const AVCodecDescriptor *, codec_descriptor) MAKE_ACCESSORS(AVCodecContext, codec, int, lowres) @@ -567,6 +568,7 @@ int av_codec_get_max_lowres(const AVCodec *codec) { return codec->max_lowres; } +#endif int avpriv_codec_get_cap_skip_frame_fill_param(const AVCodec *codec){ return !!(codec->caps_internal & FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM); diff --git a/libavcodec/version.h b/libavcodec/version.h index 88500e343fc09..a75c88576836f 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -120,6 +120,9 @@ #ifndef FF_API_GETCHROMA #define FF_API_GETCHROMA (LIBAVCODEC_VERSION_MAJOR < 59) #endif +#ifndef FF_API_CODEC_GET_SET +#define FF_API_CODEC_GET_SET (LIBAVCODEC_VERSION_MAJOR < 59) +#endif #endif /* AVCODEC_VERSION_H */ From e9025beacb86dd4390a8448fb38671699d40e24c Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 13 Nov 2017 00:10:21 -0300 Subject: [PATCH 0930/2557] ffmpeg: remove usage of AVCodecContext accessors Signed-off-by: James Almer --- fftools/ffmpeg.c | 2 +- fftools/ffmpeg_opt.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index db391f7f7d327..babd85f7bccd6 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2877,7 +2877,7 @@ static int init_input_stream(int ist_index, char *error, int error_len) /* Useful for subtitles retiming by lavf (FIXME), skipping samples in * audio, and video decoders such as cuvid or mediacodec */ - av_codec_set_pkt_timebase(ist->dec_ctx, ist->st->time_base); + ist->dec_ctx->pkt_timebase = ist->st->time_base; if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0)) av_dict_set(&ist->decoder_opts, "threads", "auto", 0); diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index e50895e64cc1a..47d384166c082 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -794,8 +794,8 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) if(!ist->dec) ist->dec = avcodec_find_decoder(par->codec_id); #if FF_API_LOWRES - if (av_codec_get_lowres(st->codec)) { - av_codec_set_lowres(ist->dec_ctx, av_codec_get_lowres(st->codec)); + if (st->codec->lowres) { + ist->dec_ctx->lowres = st->codec->lowres; ist->dec_ctx->width = st->codec->width; ist->dec_ctx->height = st->codec->height; ist->dec_ctx->coded_width = st->codec->coded_width; @@ -1663,7 +1663,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in av_log(NULL, AV_LOG_FATAL, "Could not allocate memory for intra matrix.\n"); exit_program(1); } - av_codec_set_chroma_intra_matrix(video_enc, p); + video_enc->chroma_intra_matrix = p; parse_matrix_coeffs(p, chroma_intra_matrix); } MATCH_PER_STREAM_OPT(inter_matrices, str, inter_matrix, oc, st); From b2731bcd1dc7587d20b4b2ceee0bcbade29a6ea2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 13 Nov 2017 00:10:45 -0300 Subject: [PATCH 0931/2557] ffprobe: remove usage of AVCodecContext accessors Signed-off-by: James Almer --- fftools/ffprobe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 07ca842efa319..0e7a771517d43 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2910,7 +2910,7 @@ static int open_input_file(InputFile *ifile, const char *filename) av_dict_set(&codec_opts, "threads", "1", 0); } - av_codec_set_pkt_timebase(ist->dec_ctx, stream->time_base); + ist->dec_ctx->pkt_timebase = stream->time_base; ist->dec_ctx->framerate = stream->avg_frame_rate; if (avcodec_open2(ist->dec_ctx, codec, &opts) < 0) { From e61825d5b4c3ffb981c21bee23f6372a65218e9b Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 13 Nov 2017 00:10:49 -0300 Subject: [PATCH 0932/2557] ffplay: remove usage of AVCodecContext accessors Signed-off-by: James Almer --- fftools/ffplay.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index bd1457c7e3eb7..10a917194db31 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -609,7 +609,7 @@ static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) { if (ret >= 0) { AVRational tb = (AVRational){1, frame->sample_rate}; if (frame->pts != AV_NOPTS_VALUE) - frame->pts = av_rescale_q(frame->pts, av_codec_get_pkt_timebase(d->avctx), tb); + frame->pts = av_rescale_q(frame->pts, d->avctx->pkt_timebase, tb); else if (d->next_pts != AV_NOPTS_VALUE) frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb); if (frame->pts != AV_NOPTS_VALUE) { @@ -2563,7 +2563,7 @@ static int stream_component_open(VideoState *is, int stream_index) ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar); if (ret < 0) goto fail; - av_codec_set_pkt_timebase(avctx, ic->streams[stream_index]->time_base); + avctx->pkt_timebase = ic->streams[stream_index]->time_base; codec = avcodec_find_decoder(avctx->codec_id); @@ -2584,12 +2584,12 @@ static int stream_component_open(VideoState *is, int stream_index) } avctx->codec_id = codec->id; - if(stream_lowres > av_codec_get_max_lowres(codec)){ + if (stream_lowres > codec->max_lowres) { av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n", - av_codec_get_max_lowres(codec)); - stream_lowres = av_codec_get_max_lowres(codec); + codec->max_lowres); + stream_lowres = codec->max_lowres; } - av_codec_set_lowres(avctx, stream_lowres); + avctx->lowres = stream_lowres; if (fast) avctx->flags2 |= AV_CODEC_FLAG2_FAST; From 21add0c228e00b8ea89dd13082faa3dcb37912fb Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 13 Nov 2017 00:11:15 -0300 Subject: [PATCH 0933/2557] avcodec/pthread_frame: remove usage of AVCodecContext accessors Signed-off-by: James Almer --- libavcodec/pthread_frame.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index ddfd07d2922cb..e6e6d1f599cb6 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -246,7 +246,7 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, { int err = 0; - if (dst != src && (for_user || !(av_codec_get_codec_descriptor(src)->props & AV_CODEC_PROP_INTRA_ONLY))) { + if (dst != src && (for_user || !(src->codec_descriptor->props & AV_CODEC_PROP_INTRA_ONLY))) { dst->time_base = src->time_base; dst->framerate = src->framerate; dst->width = src->width; From 03dae121c0508bddeac30245042485420a0a3370 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 13 Nov 2017 00:11:34 -0300 Subject: [PATCH 0934/2557] avfilter/vf_subtitles: remove usage of AVCodecContext accessors Signed-off-by: James Almer --- libavfilter/vf_subtitles.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c index 66a564699a0b2..a7b02461f2dd4 100644 --- a/libavfilter/vf_subtitles.c +++ b/libavfilter/vf_subtitles.c @@ -413,7 +413,7 @@ static av_cold int init_subtitles(AVFilterContext *ctx) * * That API is old and needs to be reworked to match behaviour with A/V. */ - av_codec_set_pkt_timebase(dec_ctx, st->time_base); + dec_ctx->pkt_timebase = st->time_base; ret = avcodec_open2(dec_ctx, NULL, &codec_opts); if (ret < 0) From d8ea66ab33252a19eaa8ef83bec70e3b4e9e003b Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 13 Nov 2017 00:11:52 -0300 Subject: [PATCH 0935/2557] avformat/utils: remove usage of AVCodecContext accessors Signed-off-by: James Almer --- libavformat/utils.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index 87887063be7c7..ff5e14df6ca3c 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -4028,11 +4028,13 @@ FF_ENABLE_DEPRECATION_WARNINGS ret = avcodec_parameters_from_context(st->codecpar, st->internal->avctx); if (ret < 0) goto find_stream_info_err; +#if FF_API_LOWRES // The decoder might reduce the video size by the lowres factor. - if (av_codec_get_lowres(st->internal->avctx) && orig_w) { + if (st->internal->avctx->lowres && orig_w) { st->codecpar->width = orig_w; st->codecpar->height = orig_h; } +#endif } #if FF_API_LAVF_AVCTX @@ -4041,13 +4043,15 @@ FF_DISABLE_DEPRECATION_WARNINGS if (ret < 0) goto find_stream_info_err; +#if FF_API_LOWRES // The old API (AVStream.codec) "requires" the resolution to be adjusted // by the lowres factor. - if (av_codec_get_lowres(st->internal->avctx) && st->internal->avctx->width) { - av_codec_set_lowres(st->codec, av_codec_get_lowres(st->internal->avctx)); + if (st->internal->avctx->lowres && st->internal->avctx->width) { + st->codec->lowres = st->internal->avctx->lowres; st->codec->width = st->internal->avctx->width; st->codec->height = st->internal->avctx->height; } +#endif if (st->codec->codec_tag != MKTAG('t','m','c','d')) { st->codec->time_base = st->internal->avctx->time_base; @@ -4763,10 +4767,10 @@ void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, s->time_base = new_tb; #if FF_API_LAVF_AVCTX FF_DISABLE_DEPRECATION_WARNINGS - av_codec_set_pkt_timebase(s->codec, new_tb); + s->codec->pkt_timebase = new_tb; FF_ENABLE_DEPRECATION_WARNINGS #endif - av_codec_set_pkt_timebase(s->internal->avctx, new_tb); + s->internal->avctx->pkt_timebase = new_tb; s->pts_wrap_bits = pts_wrap_bits; } From 6fcbf39f9ec7dc21829577dd2b1906c7740d3fd1 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 11 Nov 2017 16:13:24 +0100 Subject: [PATCH 0936/2557] nvenc: factor context push/pop into functions This reduces code repetition, and will allow adding further push/pop refinement for D3D11 devices in future commits. --- libavcodec/nvenc.c | 171 ++++++++++++++++++++------------------------- 1 file changed, 76 insertions(+), 95 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index e1d3316de39cf..c685d973c1d37 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -166,6 +166,37 @@ static av_cold int nvenc_load_libraries(AVCodecContext *avctx) return 0; } +static int nvenc_push_context(AVCodecContext *avctx) +{ + NvencContext *ctx = avctx->priv_data; + NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; + CUresult cu_res; + + cu_res = dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context); + if (cu_res != CUDA_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "cuCtxPushCurrent failed\n"); + return AVERROR_EXTERNAL; + } + + return 0; +} + +static int nvenc_pop_context(AVCodecContext *avctx) +{ + NvencContext *ctx = avctx->priv_data; + NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; + CUresult cu_res; + CUcontext dummy; + + cu_res = dl_fn->cuda_dl->cuCtxPopCurrent(&dummy); + if (cu_res != CUDA_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "cuCtxPopCurrent failed\n"); + return AVERROR_EXTERNAL; + } + + return 0; +} + static av_cold int nvenc_open_session(AVCodecContext *avctx) { NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS params = { 0 }; @@ -335,7 +366,6 @@ static av_cold int nvenc_check_device(AVCodecContext *avctx, int idx) int major, minor, ret; CUresult cu_res; CUdevice cu_device; - CUcontext dummy; int loglevel = AV_LOG_VERBOSE; if (ctx->device == LIST_DEVICES) @@ -378,11 +408,8 @@ static av_cold int nvenc_check_device(AVCodecContext *avctx, int idx) ctx->cu_context = ctx->cu_context_internal; - cu_res = dl_fn->cuda_dl->cuCtxPopCurrent(&dummy); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_FATAL, "Failed popping CUDA context: 0x%x\n", (int)cu_res); + if ((ret = nvenc_pop_context(avctx)) < 0) goto fail2; - } if ((ret = nvenc_open_session(avctx)) < 0) goto fail2; @@ -398,20 +425,14 @@ static av_cold int nvenc_check_device(AVCodecContext *avctx, int idx) return 0; fail3: - cu_res = dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPushCurrent failed\n"); - return AVERROR_EXTERNAL; - } + if ((ret = nvenc_push_context(avctx)) < 0) + return ret; p_nvenc->nvEncDestroyEncoder(ctx->nvencoder); ctx->nvencoder = NULL; - cu_res = dl_fn->cuda_dl->cuCtxPopCurrent(&dummy); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPopCurrent failed\n"); - return AVERROR_EXTERNAL; - } + if ((ret = nvenc_pop_context(avctx)) < 0) + return ret; fail2: dl_fn->cuda_dl->cuCtxDestroy(ctx->cu_context_internal); @@ -1031,8 +1052,6 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx) NV_ENC_PRESET_CONFIG preset_config = { 0 }; NVENCSTATUS nv_status = NV_ENC_SUCCESS; AVCPBProperties *cpb_props; - CUresult cu_res; - CUcontext dummy; int res = 0; int dw, dh; @@ -1123,19 +1142,15 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx) if (res) return res; - cu_res = dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPushCurrent failed\n"); - return AVERROR_EXTERNAL; - } + res = nvenc_push_context(avctx); + if (res < 0) + return res; nv_status = p_nvenc->nvEncInitializeEncoder(ctx->nvencoder, &ctx->init_encode_params); - cu_res = dl_fn->cuda_dl->cuCtxPopCurrent(&dummy); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPopCurrent failed\n"); - return AVERROR_EXTERNAL; - } + res = nvenc_pop_context(avctx); + if (res < 0) + return res; if (nv_status != NV_ENC_SUCCESS) { return nvenc_print_error(avctx, nv_status, "InitializeEncoder failed"); @@ -1239,9 +1254,6 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx) { NvencContext *ctx = avctx->priv_data; - NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; - CUresult cu_res; - CUcontext dummy; int i, res; ctx->surfaces = av_mallocz_array(ctx->nb_surfaces, sizeof(*ctx->surfaces)); @@ -1263,29 +1275,21 @@ static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx) if (!ctx->output_surface_ready_queue) return AVERROR(ENOMEM); - cu_res = dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPushCurrent failed\n"); - return AVERROR_EXTERNAL; - } + res = nvenc_push_context(avctx); + if (res < 0) + return res; for (i = 0; i < ctx->nb_surfaces; i++) { if ((res = nvenc_alloc_surface(avctx, i)) < 0) { - cu_res = dl_fn->cuda_dl->cuCtxPopCurrent(&dummy); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPopCurrent failed\n"); - return AVERROR_EXTERNAL; - } + nvenc_pop_context(avctx); return res; } } - cu_res = dl_fn->cuda_dl->cuCtxPopCurrent(&dummy); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPopCurrent failed\n"); - return AVERROR_EXTERNAL; - } + res = nvenc_pop_context(avctx); + if (res < 0) + return res; return 0; } @@ -1328,20 +1332,16 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) NvencContext *ctx = avctx->priv_data; NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; - CUresult cu_res; - CUcontext dummy; - int i; + int i, res; /* the encoder has to be flushed before it can be closed */ if (ctx->nvencoder) { NV_ENC_PIC_PARAMS params = { .version = NV_ENC_PIC_PARAMS_VER, .encodePicFlags = NV_ENC_PIC_FLAG_EOS }; - cu_res = dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPushCurrent failed\n"); - return AVERROR_EXTERNAL; - } + res = nvenc_push_context(avctx); + if (res < 0) + return res; p_nvenc->nvEncEncodePicture(ctx->nvencoder, ¶ms); } @@ -1378,11 +1378,9 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) if (ctx->nvencoder) { p_nvenc->nvEncDestroyEncoder(ctx->nvencoder); - cu_res = dl_fn->cuda_dl->cuCtxPopCurrent(&dummy); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPopCurrent failed\n"); - return AVERROR_EXTERNAL; - } + res = nvenc_pop_context(avctx); + if (res < 0) + return res; } ctx->nvencoder = NULL; @@ -1810,10 +1808,8 @@ static int output_ready(AVCodecContext *avctx, int flush) int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) { NVENCSTATUS nv_status; - CUresult cu_res; - CUcontext dummy; NvencSurface *tmp_out_surf, *in_surf; - int res; + int res, res2; NvencContext *ctx = avctx->priv_data; NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; @@ -1833,19 +1829,15 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) if (!in_surf) return AVERROR(EAGAIN); - cu_res = dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPushCurrent failed\n"); - return AVERROR_EXTERNAL; - } + res = nvenc_push_context(avctx); + if (res < 0) + return res; res = nvenc_upload_frame(avctx, frame, in_surf); - cu_res = dl_fn->cuda_dl->cuCtxPopCurrent(&dummy); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPopCurrent failed\n"); - return AVERROR_EXTERNAL; - } + res2 = nvenc_pop_context(avctx); + if (res2 < 0) + return res2; if (res) return res; @@ -1881,19 +1873,15 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) ctx->encoder_flushing = 1; } - cu_res = dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPushCurrent failed\n"); - return AVERROR_EXTERNAL; - } + res = nvenc_push_context(avctx); + if (res < 0) + return res; nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params); - cu_res = dl_fn->cuda_dl->cuCtxPopCurrent(&dummy); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPopCurrent failed\n"); - return AVERROR_EXTERNAL; - } + res = nvenc_pop_context(avctx); + if (res < 0) + return res; if (nv_status != NV_ENC_SUCCESS && nv_status != NV_ENC_ERR_NEED_MORE_INPUT) @@ -1922,13 +1910,10 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt) { - CUresult cu_res; - CUcontext dummy; NvencSurface *tmp_out_surf; - int res; + int res, res2; NvencContext *ctx = avctx->priv_data; - NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; if (!ctx->cu_context || !ctx->nvencoder) return AVERROR(EINVAL); @@ -1936,19 +1921,15 @@ int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt) if (output_ready(avctx, ctx->encoder_flushing)) { av_fifo_generic_read(ctx->output_surface_ready_queue, &tmp_out_surf, sizeof(tmp_out_surf), NULL); - cu_res = dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPushCurrent failed\n"); - return AVERROR_EXTERNAL; - } + res = nvenc_push_context(avctx); + if (res < 0) + return res; res = process_output_surface(avctx, pkt, tmp_out_surf); - cu_res = dl_fn->cuda_dl->cuCtxPopCurrent(&dummy); - if (cu_res != CUDA_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "cuCtxPopCurrent failed\n"); - return AVERROR_EXTERNAL; - } + res2 = nvenc_pop_context(avctx); + if (res2 < 0) + return res2; if (res) return res; From bff6d98ba3e70bb27249579df600e2c845264b2c Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sat, 11 Nov 2017 16:51:58 +0100 Subject: [PATCH 0937/2557] nvenc: support d3d11 surface input --- libavcodec/nvenc.c | 103 ++++++++++++++++++++++++++++++++++++--------- libavcodec/nvenc.h | 11 ++++- 2 files changed, 92 insertions(+), 22 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index c685d973c1d37..0139e70c3bbcf 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -45,6 +45,9 @@ const enum AVPixelFormat ff_nvenc_pix_fmts[] = { AV_PIX_FMT_0RGB32, AV_PIX_FMT_0BGR32, AV_PIX_FMT_CUDA, +#if CONFIG_D3D11VA + AV_PIX_FMT_D3D11, +#endif AV_PIX_FMT_NONE }; @@ -172,6 +175,9 @@ static int nvenc_push_context(AVCodecContext *avctx) NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; CUresult cu_res; + if (ctx->d3d11_device) + return 0; + cu_res = dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context); if (cu_res != CUDA_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "cuCtxPushCurrent failed\n"); @@ -188,6 +194,9 @@ static int nvenc_pop_context(AVCodecContext *avctx) CUresult cu_res; CUcontext dummy; + if (ctx->d3d11_device) + return 0; + cu_res = dl_fn->cuda_dl->cuCtxPopCurrent(&dummy); if (cu_res != CUDA_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "cuCtxPopCurrent failed\n"); @@ -206,8 +215,13 @@ static av_cold int nvenc_open_session(AVCodecContext *avctx) params.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER; params.apiVersion = NVENCAPI_VERSION; - params.device = ctx->cu_context; - params.deviceType = NV_ENC_DEVICE_TYPE_CUDA; + if (ctx->d3d11_device) { + params.device = ctx->d3d11_device; + params.deviceType = NV_ENC_DEVICE_TYPE_DIRECTX; + } else { + params.device = ctx->cu_context; + params.deviceType = NV_ENC_DEVICE_TYPE_CUDA; + } ret = p_nvenc->nvEncOpenEncodeSessionEx(¶ms, &ctx->nvencoder); if (ret != NV_ENC_SUCCESS) { @@ -458,23 +472,48 @@ static av_cold int nvenc_setup_device(AVCodecContext *avctx) return AVERROR_BUG; } - if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->hw_frames_ctx || avctx->hw_device_ctx) { + if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11 || avctx->hw_frames_ctx || avctx->hw_device_ctx) { AVHWFramesContext *frames_ctx; AVHWDeviceContext *hwdev_ctx; - AVCUDADeviceContext *device_hwctx; + AVCUDADeviceContext *cuda_device_hwctx = NULL; +#if CONFIG_D3D11VA + AVD3D11VADeviceContext *d3d11_device_hwctx = NULL; +#endif int ret; if (avctx->hw_frames_ctx) { frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - device_hwctx = frames_ctx->device_ctx->hwctx; + if (frames_ctx->format == AV_PIX_FMT_CUDA) + cuda_device_hwctx = frames_ctx->device_ctx->hwctx; +#if CONFIG_D3D11VA + else if (frames_ctx->format == AV_PIX_FMT_D3D11) + d3d11_device_hwctx = frames_ctx->device_ctx->hwctx; +#endif + else + return AVERROR(EINVAL); } else if (avctx->hw_device_ctx) { hwdev_ctx = (AVHWDeviceContext*)avctx->hw_device_ctx->data; - device_hwctx = hwdev_ctx->hwctx; + if (hwdev_ctx->type == AV_HWDEVICE_TYPE_CUDA) + cuda_device_hwctx = hwdev_ctx->hwctx; +#if CONFIG_D3D11VA + else if (hwdev_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) + d3d11_device_hwctx = hwdev_ctx->hwctx; +#endif + else + return AVERROR(EINVAL); } else { return AVERROR(EINVAL); } - ctx->cu_context = device_hwctx->cuda_ctx; + if (cuda_device_hwctx) { + ctx->cu_context = cuda_device_hwctx->cuda_ctx; + } +#if CONFIG_D3D11VA + else if (d3d11_device_hwctx) { + ctx->d3d11_device = d3d11_device_hwctx->device; + ID3D11Device_AddRef(ctx->d3d11_device); + } +#endif ret = nvenc_open_session(avctx); if (ret < 0) @@ -1205,7 +1244,7 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) NV_ENC_CREATE_BITSTREAM_BUFFER allocOut = { 0 }; allocOut.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER; - if (avctx->pix_fmt == AV_PIX_FMT_CUDA) { + if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) { ctx->surfaces[idx].in_ref = av_frame_alloc(); if (!ctx->surfaces[idx].in_ref) return AVERROR(ENOMEM); @@ -1237,7 +1276,7 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) nv_status = p_nvenc->nvEncCreateBitstreamBuffer(ctx->nvencoder, &allocOut); if (nv_status != NV_ENC_SUCCESS) { int err = nvenc_print_error(avctx, nv_status, "CreateBitstreamBuffer failed"); - if (avctx->pix_fmt != AV_PIX_FMT_CUDA) + if (avctx->pix_fmt != AV_PIX_FMT_CUDA && avctx->pix_fmt != AV_PIX_FMT_D3D11) p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->surfaces[idx].input_surface); av_frame_free(&ctx->surfaces[idx].in_ref); return err; @@ -1351,7 +1390,7 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) av_fifo_freep(&ctx->output_surface_queue); av_fifo_freep(&ctx->unused_surface_queue); - if (ctx->surfaces && avctx->pix_fmt == AV_PIX_FMT_CUDA) { + if (ctx->surfaces && (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11)) { for (i = 0; i < ctx->nb_surfaces; ++i) { if (ctx->surfaces[i].input_surface) { p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->surfaces[i].in_map.mappedResource); @@ -1366,7 +1405,7 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) if (ctx->surfaces) { for (i = 0; i < ctx->nb_surfaces; ++i) { - if (avctx->pix_fmt != AV_PIX_FMT_CUDA) + if (avctx->pix_fmt != AV_PIX_FMT_CUDA && avctx->pix_fmt != AV_PIX_FMT_D3D11) p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->surfaces[i].input_surface); av_frame_free(&ctx->surfaces[i].in_ref); p_nvenc->nvEncDestroyBitstreamBuffer(ctx->nvencoder, ctx->surfaces[i].output_surface); @@ -1388,6 +1427,13 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) dl_fn->cuda_dl->cuCtxDestroy(ctx->cu_context_internal); ctx->cu_context = ctx->cu_context_internal = NULL; +#if CONFIG_D3D11VA + if (ctx->d3d11_device) { + ID3D11Device_Release(ctx->d3d11_device); + ctx->d3d11_device = NULL; + } +#endif + nvenc_free_functions(&dl_fn->nvenc_dl); cuda_free_functions(&dl_fn->cuda_dl); @@ -1403,7 +1449,7 @@ av_cold int ff_nvenc_encode_init(AVCodecContext *avctx) NvencContext *ctx = avctx->priv_data; int ret; - if (avctx->pix_fmt == AV_PIX_FMT_CUDA) { + if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) { AVHWFramesContext *frames_ctx; if (!avctx->hw_frames_ctx) { av_log(avctx, AV_LOG_ERROR, @@ -1411,6 +1457,11 @@ av_cold int ff_nvenc_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + if (frames_ctx->format != avctx->pix_fmt) { + av_log(avctx, AV_LOG_ERROR, + "hw_frames_ctx must match the GPU frame type\n"); + return AVERROR(EINVAL); + } ctx->data_pix_fmt = frames_ctx->sw_format; } else { ctx->data_pix_fmt = avctx->pix_fmt; @@ -1516,7 +1567,9 @@ static int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame) int i, idx, ret; for (i = 0; i < ctx->nb_registered_frames; i++) { - if (ctx->registered_frames[i].ptr == (CUdeviceptr)frame->data[0]) + if (avctx->pix_fmt == AV_PIX_FMT_CUDA && ctx->registered_frames[i].ptr == frame->data[0]) + return i; + else if (avctx->pix_fmt == AV_PIX_FMT_D3D11 && ctx->registered_frames[i].ptr == frame->data[0] && ctx->registered_frames[i].ptr_index == (intptr_t)frame->data[1]) return i; } @@ -1525,12 +1578,19 @@ static int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame) return idx; reg.version = NV_ENC_REGISTER_RESOURCE_VER; - reg.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR; reg.width = frames_ctx->width; reg.height = frames_ctx->height; reg.pitch = frame->linesize[0]; reg.resourceToRegister = frame->data[0]; + if (avctx->pix_fmt == AV_PIX_FMT_CUDA) { + reg.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR; + } + else if (avctx->pix_fmt == AV_PIX_FMT_D3D11) { + reg.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_DIRECTX; + reg.subResourceIndex = (intptr_t)frame->data[1]; + } + reg.bufferFormat = nvenc_map_buffer_format(frames_ctx->sw_format); if (reg.bufferFormat == NV_ENC_BUFFER_FORMAT_UNDEFINED) { av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format: %s\n", @@ -1544,8 +1604,9 @@ static int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame) return AVERROR_UNKNOWN; } - ctx->registered_frames[idx].ptr = (CUdeviceptr)frame->data[0]; - ctx->registered_frames[idx].regptr = reg.registeredResource; + ctx->registered_frames[idx].ptr = frame->data[0]; + ctx->registered_frames[idx].ptr_index = reg.subResourceIndex; + ctx->registered_frames[idx].regptr = reg.registeredResource; return idx; } @@ -1559,10 +1620,10 @@ static int nvenc_upload_frame(AVCodecContext *avctx, const AVFrame *frame, int res; NVENCSTATUS nv_status; - if (avctx->pix_fmt == AV_PIX_FMT_CUDA) { + if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) { int reg_idx = nvenc_register_frame(avctx, frame); if (reg_idx < 0) { - av_log(avctx, AV_LOG_ERROR, "Could not register an input CUDA frame\n"); + av_log(avctx, AV_LOG_ERROR, "Could not register an input HW frame\n"); return reg_idx; } @@ -1731,7 +1792,7 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur nvenc_print_error(avctx, nv_status, "Failed unlocking bitstream buffer, expect the gates of mordor to open"); - if (avctx->pix_fmt == AV_PIX_FMT_CUDA) { + if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) { p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, tmpoutsurf->in_map.mappedResource); av_frame_unref(tmpoutsurf->in_ref); ctx->registered_frames[tmpoutsurf->reg_idx].mapped = 0; @@ -1818,7 +1879,7 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) NV_ENC_PIC_PARAMS pic_params = { 0 }; pic_params.version = NV_ENC_PIC_PARAMS_VER; - if (!ctx->cu_context || !ctx->nvencoder) + if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder) return AVERROR(EINVAL); if (ctx->encoder_flushing) @@ -1915,7 +1976,7 @@ int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt) NvencContext *ctx = avctx->priv_data; - if (!ctx->cu_context || !ctx->nvencoder) + if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder) return AVERROR(EINVAL); if (output_ready(avctx, ctx->encoder_flushing)) { diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index afb93cc22caed..55ac5f220d967 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -27,6 +27,13 @@ #include "libavutil/fifo.h" #include "libavutil/opt.h" +#if CONFIG_D3D11VA +#define COBJMACROS +#include "libavutil/hwcontext_d3d11va.h" +#else +typedef void ID3D11Device; +#endif + #include "avcodec.h" #define MAX_REGISTERED_FRAMES 64 @@ -107,6 +114,7 @@ typedef struct NvencContext NV_ENC_CONFIG encode_config; CUcontext cu_context; CUcontext cu_context_internal; + ID3D11Device *d3d11_device; int nb_surfaces; NvencSurface *surfaces; @@ -119,7 +127,8 @@ typedef struct NvencContext int encoder_flushing; struct { - CUdeviceptr ptr; + void *ptr; + int ptr_index; NV_ENC_REGISTERED_PTR regptr; int mapped; } registered_frames[MAX_REGISTERED_FRAMES]; From 9e48de3cc86c732d9cebd496d6f0a2b7e7732754 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 24 Sep 2017 18:46:47 +0200 Subject: [PATCH 0938/2557] configure: Miscellaneous minor changes - Move a variable closer to where it is used - Add an explanatory comment - Simplify a crosscompile check - Minor SHFLAGS simplification - Coalesce some threads tests --- configure | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/configure b/configure index e608d26608b69..be9a3ee5cb6a0 100755 --- a/configure +++ b/configure @@ -347,8 +347,6 @@ EOF exit 0 } -quotes='""' - log(){ echo "$@" >> $logfile } @@ -2861,6 +2859,8 @@ done disabled logging && logfile=/dev/null +# command line configuration sanity checks + # we need to build at least one lib type if ! enabled_any static shared; then cat < $TMPV if test_ldflags -Wl,${version_script},$TMPV; then append SHFLAGS '-Wl,${version_script},\$(SUBDIR)lib\$(NAME).ver' + quotes='""' check_cc < Date: Fri, 6 Oct 2017 23:06:45 +0200 Subject: [PATCH 0939/2557] configure: Coalesce some arch configuration and PIC handling --- configure | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/configure b/configure index be9a3ee5cb6a0..3bad7fb72cf48 100755 --- a/configure +++ b/configure @@ -2595,6 +2595,7 @@ pkg_config_default=pkg-config ranlib="ranlib" strip="strip" version_script='--version-script' +objformat="elf32" # machine arch_default=$(uname -m) @@ -3766,45 +3767,42 @@ check_64bit(){ expr=$3 check_code cc "" "int test[2*($expr) - 1]" && subarch=$arch64 || subarch=$arch32 + enable $subarch } case "$arch" in aarch64|alpha|ia64) - spic=$shared + enabled shared && enable_weak pic ;; mips) check_64bit mips mips64 '_MIPS_SIM > 1' - spic=$shared + enabled shared && enable_weak pic ;; parisc) check_64bit parisc parisc64 'sizeof(void *) > 4' - spic=$shared + enabled shared && enable_weak pic ;; ppc) check_64bit ppc ppc64 'sizeof(void *) > 4' - spic=$shared + enabled shared && enable_weak pic ;; s390) check_64bit s390 s390x 'sizeof(void *) > 4' - spic=$shared + enabled shared && enable_weak pic ;; sparc) check_64bit sparc sparc64 'sizeof(void *) > 4' - spic=$shared + enabled shared && enable_weak pic ;; x86) check_64bit x86_32 x86_64 'sizeof(void *) > 4' - if test "$subarch" = "x86_64"; then - spic=$shared + if enabled x86_64; then + enabled shared && enable_weak pic + objformat=elf64 fi ;; esac -enable $subarch -enabled spic && enable_weak pic - -enabled x86_64 && objformat=elf64 || objformat="elf32" - # OS specific case $target_os in aix) From 380b48fb9fdc7b0c40d67e026f9b3accb12794eb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 21 Oct 2017 18:04:44 +0200 Subject: [PATCH 0940/2557] avcodec/h264dec: Fix potential array overread add padding before scantable arrays See: 522d850e68ec4b77d3477b3c8f55b1ba00a9d69a Signed-off-by: Michael Niedermayer --- libavcodec/h264dec.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h index b87b947f95b10..1d9723260dd3c 100644 --- a/libavcodec/h264dec.h +++ b/libavcodec/h264dec.h @@ -417,6 +417,7 @@ typedef struct H264Context { uint8_t (*mvd_table[2])[2]; uint8_t *direct_table; + uint8_t scan_padding[16]; uint8_t zigzag_scan[16]; uint8_t zigzag_scan8x8[64]; uint8_t zigzag_scan8x8_cavlc[64]; From eec67f7b24da5407cc2e8933ffe72358336811ab Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 4 Nov 2017 00:26:56 +0100 Subject: [PATCH 0941/2557] avcodec/dvbsubdec: Avoid re-computing clut Fixes: Timeout Fixes: 3218/clusterfuzz-testcase-5390672154591232 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/dvbsubdec.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c index 4e08dba35c544..a657b1d3d0f1b 100644 --- a/libavcodec/dvbsubdec.c +++ b/libavcodec/dvbsubdec.c @@ -96,6 +96,9 @@ typedef struct DVBSubRegion { int clut; int bgcolor; + uint8_t computed_clut[4*256]; + int has_computed_clut; + uint8_t *pbuf; int buf_size; int dirty; @@ -647,7 +650,7 @@ static int dvbsub_read_8bit_string(AVCodecContext *avctx, return pixels_read; } -static void compute_default_clut(AVSubtitleRect *rect, int w, int h) +static void compute_default_clut(uint8_t *clut, AVSubtitleRect *rect, int w, int h) { uint8_t list[256] = {0}; uint8_t list_inv[256]; @@ -703,7 +706,7 @@ static void compute_default_clut(AVSubtitleRect *rect, int w, int h) count = FFMAX(i - 1, 1); for (i--; i>=0; i--) { int v = i*255/count; - AV_WN32(rect->data[1] + 4*list_inv[i], RGBA(v/2,v,v/2,v)); + AV_WN32(clut + 4*list_inv[i], RGBA(v/2,v,v/2,v)); } } @@ -814,8 +817,14 @@ static int save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub, int *got_ou memcpy(rect->data[0], region->pbuf, region->buf_size); - if ((clut == &default_clut && ctx->compute_clut == -1) || ctx->compute_clut == 1) - compute_default_clut(rect, rect->w, rect->h); + if ((clut == &default_clut && ctx->compute_clut == -1) || ctx->compute_clut == 1) { + if (!region->has_computed_clut) { + compute_default_clut(region->computed_clut, rect, rect->w, rect->h); + region->has_computed_clut = 1; + } + + memcpy(rect->data[1], region->computed_clut, sizeof(region->computed_clut)); + } #if FF_API_AVPICTURE FF_DISABLE_DEPRECATION_WARNINGS @@ -964,6 +973,7 @@ static void dvbsub_parse_pixel_data_block(AVCodecContext *avctx, DVBSubObjectDis } } + region->has_computed_clut = 0; } static int dvbsub_parse_object_segment(AVCodecContext *avctx, From 6d00905f8134a2932e5c00dd1ec8b2a1f0a38035 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 15 Nov 2017 16:53:34 +0100 Subject: [PATCH 0942/2557] avcodec/vc2enc: Clear coef_buf on allocation Fixes: Use of uninitialized memory Fixes: assertion failure Reviewed-by: Signed-off-by: Michael Niedermayer --- libavcodec/vc2enc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c index 0a8c3633ef842..2f08441d55645 100644 --- a/libavcodec/vc2enc.c +++ b/libavcodec/vc2enc.c @@ -1173,7 +1173,7 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx) p->dwt_width = w = FFALIGN(p->width, (1 << s->wavelet_depth)); p->dwt_height = h = FFALIGN(p->height, (1 << s->wavelet_depth)); p->coef_stride = FFALIGN(p->dwt_width, 32); - p->coef_buf = av_malloc(p->coef_stride*p->dwt_height*sizeof(dwtcoef)); + p->coef_buf = av_mallocz(p->coef_stride*p->dwt_height*sizeof(dwtcoef)); if (!p->coef_buf) goto alloc_fail; for (level = s->wavelet_depth-1; level >= 0; level--) { From f399172d6e842fbdd05c599cdbbb1668c8c354be Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 15 Nov 2017 21:13:07 -0300 Subject: [PATCH 0943/2557] avcodec/proresdec: align dequantization matrix buffers Should fix ticket #6838 Signed-off-by: James Almer --- libavcodec/proresdec2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index e9e0153ee97f2..d97e264e4492b 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -517,8 +517,8 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int int luma_stride, chroma_stride; int y_data_size, u_data_size, v_data_size, a_data_size; uint8_t *dest_y, *dest_u, *dest_v, *dest_a; - int16_t qmat_luma_scaled[64]; - int16_t qmat_chroma_scaled[64]; + LOCAL_ALIGNED_16(int16_t, qmat_luma_scaled, [64]); + LOCAL_ALIGNED_16(int16_t, qmat_chroma_scaled,[64]); int mb_x_shift; int ret; From 3f1a540204a8c187f77b3805d2e1c97fa916a12b Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Wed, 15 Mar 2017 12:53:03 -0700 Subject: [PATCH 0944/2557] avcodec/mpeg12dec: parse A53 caption data embedded in SCTE-20 user data Signed-off-by: Michael Niedermayer --- libavcodec/mpeg12dec.c | 39 ++++++++++++++++++++++++++++++++++++ tests/fate/subtitles.mak | 3 +++ tests/ref/fate/sub-cc-scte20 | 15 ++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 tests/ref/fate/sub-cc-scte20 diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 82bb1286ff6c5..e2a7c3f2e0a68 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -2240,6 +2240,45 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx, avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; } return 1; + } else if (buf_size >= 2 && + p[0] == 0x03 && (p[1]&0x7f) == 0x01) { + /* extract SCTE-20 CC data */ + GetBitContext gb; + int cc_count = 0; + int i; + + init_get_bits(&gb, p + 2, buf_size - 2); + cc_count = get_bits(&gb, 5); + if (cc_count > 0) { + av_freep(&s1->a53_caption); + s1->a53_caption_size = cc_count * 3; + s1->a53_caption = av_mallocz(s1->a53_caption_size); + if (s1->a53_caption) { + uint8_t field, cc1, cc2; + uint8_t *cap = s1->a53_caption; + for (i = 0; i < cc_count && get_bits_left(&gb) >= 26; i++) { + skip_bits(&gb, 2); // priority + field = get_bits(&gb, 2); + skip_bits(&gb, 5); // line_offset + cc1 = get_bits(&gb, 8); + cc2 = get_bits(&gb, 8); + skip_bits(&gb, 1); // marker + + if (!field) { // forbidden + cap[0] = cap[1] = cap[2] = 0x00; + } else { + field = (field == 2 ? 1 : 0); + if (!s1->mpeg_enc_ctx.top_field_first) field = !field; + cap[0] = 0x04 | field; + cap[1] = ff_reverse[cc1]; + cap[2] = ff_reverse[cc2]; + } + cap += 3; + } + } + avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; + } + return 1; } else if (buf_size >= 11 && p[0] == 'C' && p[1] == 'C' && p[2] == 0x01 && p[3] == 0xf8) { /* extract DVD CC data diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak index 8c310adeff0c3..00429021617e5 100644 --- a/tests/fate/subtitles.mak +++ b/tests/fate/subtitles.mak @@ -7,6 +7,9 @@ fate-sub-cc: CMD = fmtstdout ass -f lavfi -i "movie=$(TARGET_SAMPLES)/sub/Closed FATE_SUBTITLES_ASS-$(call ALLYES, AVDEVICE LAVFI_INDEV CCAPTION_DECODER MOVIE_FILTER MPEGTS_DEMUXER) += fate-sub-cc-realtime fate-sub-cc-realtime: CMD = fmtstdout ass -real_time 1 -f lavfi -i "movie=$(TARGET_SAMPLES)/sub/Closedcaption_rollup.m2v[out0+subcc]" +FATE_SUBTITLES_ASS-$(call ALLYES, AVDEVICE LAVFI_INDEV CCAPTION_DECODER MOVIE_FILTER MPEGTS_DEMUXER) += fate-sub-cc-scte20 +fate-sub-cc-scte20: CMD = fmtstdout ass -f lavfi -i "movie=$(TARGET_SAMPLES)/sub/scte20.ts[out0+subcc]" + FATE_SUBTITLES_ASS-$(call DEMDEC, ASS, ASS) += fate-sub-ass-to-ass-transcode fate-sub-ass-to-ass-transcode: CMD = fmtstdout ass -i $(TARGET_SAMPLES)/sub/1ededcbd7b.ass diff --git a/tests/ref/fate/sub-cc-scte20 b/tests/ref/fate/sub-cc-scte20 new file mode 100644 index 0000000000000..71fc92bfc5da5 --- /dev/null +++ b/tests/ref/fate/sub-cc-scte20 @@ -0,0 +1,15 @@ +[Script Info] +; Script generated by FFmpeg/Lavc +ScriptType: v4.00+ +PlayResX: 384 +PlayResY: 288 + +[V4+ Styles] +Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding +Style: Default,Monospace,16,&Hffffff,&Hffffff,&H0,&H0,0,0,0,0,100,100,0,0,3,1,0,2,10,10,10,0 + +[Events] +Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text +Dialogue: 0,0:00:00.00,0:00:01.44,Default,,0,0,0,,{\an7}{\pos(48,182)}BESIDES THE +Dialogue: 0,0:00:01.43,0:00:03.93,Default,,0,0,0,,{\an7}{\pos(38,166)}\hBESIDES THE \N{\an7}{\pos(38,197)}SPENDING AND THIS, IS THAT CAR +Dialogue: 0,0:00:03.94,0:00:06.31,Default,,0,0,0,,{\an7}{\pos(38,182)}SPENDING AND THIS, IS THAT CAR \N{\an7}{\pos(38,197)}MANUFACTURERS ARE ABOUT AS From ff8f40a63092b184d7fe4416660adbba8d90849d Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Wed, 15 Mar 2017 12:53:04 -0700 Subject: [PATCH 0945/2557] avcodec/mpeg12dec: ensure a53_caption_size is reset on malloc failures Signed-off-by: Aman Gupta Reviewed-by: Michael Niedermayer --- libavcodec/mpeg12dec.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index e2a7c3f2e0a68..d5bc5f21b2ade 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -2235,8 +2235,11 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx, av_freep(&s1->a53_caption); s1->a53_caption_size = cc_count * 3; s1->a53_caption = av_malloc(s1->a53_caption_size); - if (s1->a53_caption) + if (!s1->a53_caption) { + s1->a53_caption_size = 0; + } else { memcpy(s1->a53_caption, p + 7, s1->a53_caption_size); + } avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; } return 1; @@ -2253,7 +2256,9 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx, av_freep(&s1->a53_caption); s1->a53_caption_size = cc_count * 3; s1->a53_caption = av_mallocz(s1->a53_caption_size); - if (s1->a53_caption) { + if (!s1->a53_caption) { + s1->a53_caption_size = 0; + } else { uint8_t field, cc1, cc2; uint8_t *cap = s1->a53_caption; for (i = 0; i < cc_count && get_bits_left(&gb) >= 26; i++) { @@ -2317,7 +2322,9 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx, av_freep(&s1->a53_caption); s1->a53_caption_size = cc_count * 6; s1->a53_caption = av_malloc(s1->a53_caption_size); - if (s1->a53_caption) { + if (!s1->a53_caption) { + s1->a53_caption_size = 0; + } else { uint8_t field1 = !!(p[4] & 0x80); uint8_t *cap = s1->a53_caption; p += 5; From bad7ce1d82f0b7da55086b8c6124eff0d35a1b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 16 Nov 2017 09:32:15 +0200 Subject: [PATCH 0946/2557] makedef: Pass EXTERN_PREFIX from configure to makedef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids having to use either "dumpbin -headers" to find out the current architecture, or pass $ARCH from configure to deduce it. When configuring with --disable-asm, ARCH is equal to "c", which doesn't give any indication of what symbol prefix is to be used. Signed-off-by: Martin Storsjö --- compat/windows/makedef | 28 +--------------------------- configure | 5 +++-- 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/compat/windows/makedef b/compat/windows/makedef index 0cd169c15c000..7258b94a92034 100755 --- a/compat/windows/makedef +++ b/compat/windows/makedef @@ -58,33 +58,7 @@ fi IFS=' ' -# Determine if we're building for x86 or x86_64 and -# set the symbol prefix accordingly. -prefix="" -if [ -n "$NM" ]; then - case $ARCH in - *86) - prefix="_" - ;; - *) - ;; - esac -else - arch=$(dumpbin -headers ${libname} | - tr '\t' ' ' | - grep '^ \+.\+machine \+(.\+)' | - head -1 | - sed -e 's/^ \{1,\}.\{1,\} \{1,\}machine \{1,\}(\(.\{3,5\}\)).*/\1/') - - if [ "${arch}" = "x86" ]; then - prefix="_" - else - if [ "${arch}" != "ARM" ] && [ "${arch}" != "x64" ] && [ "${arch}" != "ARM64" ]; then - echo "Unknown machine type." >&2 - exit 1 - fi - fi -fi +prefix="$EXTERN_PREFIX" started=0 regex="none" diff --git a/configure b/configure index 3bad7fb72cf48..fcffbce7f915f 100755 --- a/configure +++ b/configure @@ -3898,7 +3898,7 @@ case $target_os in SLIB_INSTALL_LINKS= SLIB_INSTALL_EXTRA_SHLIB='$(SLIBNAME:$(SLIBSUF)=.lib)' SLIB_INSTALL_EXTRA_LIB='lib$(SLIBNAME:$(SLIBSUF)=.dll.a) $(SLIBNAME_WITH_MAJOR:$(SLIBSUF)=.def)' - SLIB_CREATE_DEF_CMD='ARCH="$(ARCH)" AR="$(AR_CMD)" NM="$(NM_CMD)" $(SRC_PATH)/compat/windows/makedef $(SUBDIR)lib$(NAME).ver $(OBJS) > $$(@:$(SLIBSUF)=.def)' + SLIB_CREATE_DEF_CMD='EXTERN_PREFIX="$(EXTERN_PREFIX)" AR="$(AR_CMD)" NM="$(NM_CMD)" $(SRC_PATH)/compat/windows/makedef $(SUBDIR)lib$(NAME).ver $(OBJS) > $$(@:$(SLIBSUF)=.def)' SHFLAGS='-shared -Wl,--out-implib,$(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a) -Wl,--enable-auto-image-base $$(@:$(SLIBSUF)=.def)' enabled x86_64 && objformat="win64" || objformat="win32" ranlib=: @@ -3918,7 +3918,7 @@ case $target_os in SLIBSUF=".dll" SLIBNAME_WITH_VERSION='$(SLIBPREF)$(NAME)-$(LIBVERSION)$(SLIBSUF)' SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(NAME)-$(LIBMAJOR)$(SLIBSUF)' - SLIB_CREATE_DEF_CMD='$(SRC_PATH)/compat/windows/makedef $(SUBDIR)lib$(NAME).ver $(OBJS) > $$(@:$(SLIBSUF)=.def)' + SLIB_CREATE_DEF_CMD='EXTERN_PREFIX="$(EXTERN_PREFIX)" $(SRC_PATH)/compat/windows/makedef $(SUBDIR)lib$(NAME).ver $(OBJS) > $$(@:$(SLIBSUF)=.def)' SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)' SLIB_INSTALL_LINKS= SLIB_INSTALL_EXTRA_SHLIB='$(SLIBNAME:$(SLIBSUF)=.lib)' @@ -5210,6 +5210,7 @@ SRC_PATH=$source_path CC_IDENT=$cc_ident ARCH=$arch INTRINSICS=$intrinsics +EXTERN_PREFIX=$extern_prefix CC=$cc AS=$as OBJCC=$objcc From 4fb20d4e3a48b2008a13fc11ba75015ded2c2fc2 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Mon, 13 Nov 2017 23:43:51 +0100 Subject: [PATCH 0947/2557] configure: call flatten_extralibs in a subshell By putting the call in a subshell, the problem of it spilling cleanup-decision from a previous library to other libraries is avoided. For example, it could have already cleaned up cuda_extralibs in a previous library that depended on cuda. Then when it gets to avutil, it will never pick up the dependency of avutil to cuda, which depends on libdl, which in turn results in a missing -ldl extralib, resulting in link failures in certain configurations. --- configure | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 84f0a04925f34..c8e2e35192222 100755 --- a/configure +++ b/configure @@ -6495,6 +6495,15 @@ flatten_extralibs(){ fi } +flatten_extralibs_wrapper(){ + list_name=$1 + flatten_extralibs $list_name + unique $list_name + resolve $list_name + eval $list_name=\$\(\$ldflags_filter \$$list_name\) + eval printf \''%s'\' \""\$$list_name"\" +} + for linkunit in $LIBRARY_LIST; do unset current_extralibs eval components=\$$(toupper ${linkunit})_COMPONENTS_LIST @@ -6507,10 +6516,7 @@ for linkunit in $LIBRARY_LIST; do done for linkunit in $LIBRARY_LIST $PROGRAM_LIST $EXTRALIBS_LIST; do - flatten_extralibs ${linkunit}_extralibs - unique ${linkunit}_extralibs - resolve ${linkunit}_extralibs - eval ${linkunit}_extralibs=\$\(\$ldflags_filter \$${linkunit}_extralibs\) + eval ${linkunit}_extralibs=\$\(flatten_extralibs_wrapper ${linkunit}_extralibs\) done map 'enabled $v && intrinsics=${v#intrinsics_}' $INTRINSICS_LIST From ac922f942fa2eab80886563bf2fbbb4489b98d89 Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Wed, 15 Nov 2017 09:17:39 -0800 Subject: [PATCH 0948/2557] lavf/movenc: allow writing avc3 sample entry type The avc3 sample entry type is useful for adaptive streaming. It permits parameter sets to be written inline in the video stream. Signed-off-by: Michael Niedermayer --- libavformat/movenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index cc3fc19d9b662..01ae467fa1700 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -6513,6 +6513,7 @@ static const AVCodecTag codec_3gp_tags[] = { const AVCodecTag codec_mp4_tags[] = { { AV_CODEC_ID_MPEG4 , MKTAG('m', 'p', '4', 'v') }, { AV_CODEC_ID_H264 , MKTAG('a', 'v', 'c', '1') }, + { AV_CODEC_ID_H264 , MKTAG('a', 'v', 'c', '3') }, { AV_CODEC_ID_HEVC , MKTAG('h', 'e', 'v', '1') }, { AV_CODEC_ID_HEVC , MKTAG('h', 'v', 'c', '1') }, { AV_CODEC_ID_MPEG2VIDEO , MKTAG('m', 'p', '4', 'v') }, From a6fdd75fe6440d2f4150cb456a9078aa68b00fdb Mon Sep 17 00:00:00 2001 From: Fredrik Hubinette Date: Wed, 15 Nov 2017 17:24:30 -0800 Subject: [PATCH 0949/2557] avformat/mov: Check size of STSC allocation Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index 79023ef369526..d49d820d2b62d 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2595,6 +2595,8 @@ static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_rb24(pb); /* flags */ entries = avio_rb32(pb); + if ((uint64_t)entries * 12 + 4 > atom.size) + return AVERROR_INVALIDDATA; av_log(c->fc, AV_LOG_TRACE, "track[%u].stsc.entries = %u\n", c->fc->nb_streams - 1, entries); From e510a8251b3fc385dfe2f0482ece5643c7d66f06 Mon Sep 17 00:00:00 2001 From: Umair Khan Date: Mon, 13 Nov 2017 11:06:30 +0530 Subject: [PATCH 0950/2557] libavcodec/als: remove check for predictor order of a block Reverts commit 18f94df8, fixes ticket #5297. Signed-off-by: Umair Khan --- libavcodec/alsdec.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libavcodec/alsdec.c b/libavcodec/alsdec.c index 13bd52f297ff1..9a72686413fe5 100644 --- a/libavcodec/alsdec.c +++ b/libavcodec/alsdec.c @@ -704,11 +704,6 @@ static int read_var_block_data(ALSDecContext *ctx, ALSBlockData *bd) } else { *bd->opt_order = sconf->max_order; } - if (*bd->opt_order > bd->block_length) { - *bd->opt_order = bd->block_length; - av_log(avctx, AV_LOG_ERROR, "Predictor order too large.\n"); - return AVERROR_INVALIDDATA; - } opt_order = *bd->opt_order; if (opt_order) { From 55937bb4a7df157fb08f79e7e623a16280533275 Mon Sep 17 00:00:00 2001 From: Umair Khan Date: Mon, 13 Nov 2017 11:07:42 +0530 Subject: [PATCH 0951/2557] libavcodec/als: fix address sanitization error in decoder Signed-off-by: Umair Khan --- libavcodec/alsdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/alsdec.c b/libavcodec/alsdec.c index 9a72686413fe5..ca8701e6d0d85 100644 --- a/libavcodec/alsdec.c +++ b/libavcodec/alsdec.c @@ -920,7 +920,7 @@ static int decode_var_block_data(ALSDecContext *ctx, ALSBlockData *bd) // reconstruct all samples from residuals if (bd->ra_block) { - for (smp = 0; smp < opt_order; smp++) { + for (smp = 0; smp < FFMIN(opt_order, block_length); smp++) { y = 1 << 19; for (sb = 0; sb < smp; sb++) From ce001bb8fc6677541c401a614e05e5058d58dde1 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 31 Oct 2017 00:19:38 +0100 Subject: [PATCH 0952/2557] lavf/mxf: Support 60fps output. --- libavformat/mxf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/mxf.c b/libavformat/mxf.c index bfc3218b815a0..5994b09914b61 100644 --- a/libavformat/mxf.c +++ b/libavformat/mxf.c @@ -137,6 +137,7 @@ static const MXFSamplesPerFrame mxf_spf[] = { { { 1001, 60000 }, { 801, 801, 801, 801, 800, 0 } }, // NTSC 59.94 { { 1, 25 }, { 1920, 0, 0, 0, 0, 0 } }, // PAL 25 { { 1, 50 }, { 960, 0, 0, 0, 0, 0 } }, // PAL 50 + { { 1, 60 }, { 800, 0, 0, 0, 0, 0 } }, }; static const AVRational mxf_time_base[] = { @@ -146,6 +147,7 @@ static const AVRational mxf_time_base[] = { { 1001, 60000 }, { 1, 25 }, { 1, 50 }, + { 1, 60 }, { 0, 0} }; From 80bb81a8f34729443bdbcdb3bc2c89c221291fe6 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 13 Nov 2017 12:20:18 -0800 Subject: [PATCH 0953/2557] avformat/tcp: add option to enable TCP_NODELAY This can reduce latency and increase throughput, particularly on high latency networks. Signed-off-by: Aman Gupta Reviewed-by: Jeyapal, Karthick --- doc/protocols.texi | 3 +++ libavformat/network.h | 1 + libavformat/tcp.c | 5 +++++ 3 files changed, 9 insertions(+) diff --git a/doc/protocols.texi b/doc/protocols.texi index a7968ff56e3e1..4d48f8a411566 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -1242,6 +1242,9 @@ Set receive buffer size, expressed bytes. @item send_buffer_size=@var{bytes} Set send buffer size, expressed bytes. + +@item tcp_nodelay=@var{1|0} +Set TCP_NODELAY to disable Nagle's algorithm. Default value is 0. @end table The following example shows how to setup a listening TCP connection diff --git a/libavformat/network.h b/libavformat/network.h index f83c796a95a55..b78e3ad6ed888 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -59,6 +59,7 @@ int ff_neterrno(void); #include #include #include +#include #include #define ff_neterrno() AVERROR(errno) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index 07b4ed9fa3a8e..f3f9d4f431b99 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -41,6 +41,7 @@ typedef struct TCPContext { int listen_timeout; int recv_buffer_size; int send_buffer_size; + int tcp_nodelay; } TCPContext; #define OFFSET(x) offsetof(TCPContext, x) @@ -52,6 +53,7 @@ static const AVOption options[] = { { "listen_timeout", "Connection awaiting timeout (in milliseconds)", OFFSET(listen_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "send_buffer_size", "Socket send buffer size (in bytes)", OFFSET(send_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "recv_buffer_size", "Socket receive buffer size (in bytes)", OFFSET(recv_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "tcp_nodelay", "Use TCP_NODELAY to disable nagle's algorithm", OFFSET(tcp_nodelay), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E }, { NULL } }; @@ -148,6 +150,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags) if (s->send_buffer_size > 0) { setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &s->send_buffer_size, sizeof (s->send_buffer_size)); } + if (s->tcp_nodelay > 0) { + setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &s->tcp_nodelay, sizeof (s->tcp_nodelay)); + } if (s->listen == 2) { // multi-client From 5d7c76566cdd0544a4bda59b520be22bd7ad7f30 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 13 May 2017 11:57:42 +0200 Subject: [PATCH 0954/2557] avfilter: add multiband compand filter Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/filters.texi | 16 + libavfilter/Makefile | 1 + libavfilter/af_mcompand.c | 689 ++++++++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + libavfilter/version.h | 4 +- 6 files changed, 710 insertions(+), 2 deletions(-) create mode 100644 libavfilter/af_mcompand.c diff --git a/Changelog b/Changelog index d2b5530ad722d..119ab678e5e1c 100644 --- a/Changelog +++ b/Changelog @@ -15,6 +15,7 @@ version : - Raw aptX muxer and demuxer - NVIDIA NVDEC-accelerated H.264, HEVC, VC1 and VP9 hwaccel decoding - Intel QSV-accelerated overlay filter +- mcompand audio filter version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index 4a35c44c7b6ae..5d99437871b6c 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -3270,6 +3270,22 @@ lowpass=c=LFE @end example @end itemize +@section mcompand +Multiband Compress or expand the audio's dynamic range. + +The input audio is divided into bands using 4th order Linkwitz-Riley IIRs. +This is akin to the crossover of a loudspeaker, and results in flat frequency +response when absent compander action. + +It accepts the following parameters: + +@table @option +@item args +This option syntax is: +attack,decay,[attack,decay..] soft-knee points crossover_frequency [delay [initial_volume [gain]]] | attack,decay ... +For explanation of each item refer to compand filter documentation. +@end table + @anchor{pan} @section pan diff --git a/libavfilter/Makefile b/libavfilter/Makefile index b7ddcd226d711..9acae3ff5b74f 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -101,6 +101,7 @@ OBJS-$(CONFIG_JOIN_FILTER) += af_join.o OBJS-$(CONFIG_LADSPA_FILTER) += af_ladspa.o OBJS-$(CONFIG_LOUDNORM_FILTER) += af_loudnorm.o ebur128.o OBJS-$(CONFIG_LOWPASS_FILTER) += af_biquads.o +OBJS-$(CONFIG_MCOMPAND_FILTER) += af_mcompand.o OBJS-$(CONFIG_PAN_FILTER) += af_pan.o OBJS-$(CONFIG_REPLAYGAIN_FILTER) += af_replaygain.o OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o diff --git a/libavfilter/af_mcompand.c b/libavfilter/af_mcompand.c new file mode 100644 index 0000000000000..02f987a6a8630 --- /dev/null +++ b/libavfilter/af_mcompand.c @@ -0,0 +1,689 @@ +/* + * COpyright (c) 2002 Daniel Pouzzner + * Copyright (c) 1999 Chris Bagwell + * Copyright (c) 1999 Nick Bailey + * Copyright (c) 2007 Rob Sykes + * Copyright (c) 2013 Paul B Mahol + * Copyright (c) 2014 Andrew Kelley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * audio multiband compand filter + */ + +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/ffmath.h" +#include "libavutil/opt.h" +#include "libavutil/samplefmt.h" +#include "audio.h" +#include "avfilter.h" +#include "internal.h" + +typedef struct CompandSegment { + double x, y; + double a, b; +} CompandSegment; + +typedef struct CompandT { + CompandSegment *segments; + int nb_segments; + double in_min_lin; + double out_min_lin; + double curve_dB; + double gain_dB; +} CompandT; + +#define N 4 + +typedef struct PrevCrossover { + double in; + double out_low; + double out_high; +} PrevCrossover[N * 2]; + +typedef struct Crossover { + PrevCrossover *previous; + size_t pos; + double coefs[3 *(N+1)]; +} Crossover; + +typedef struct CompBand { + CompandT transfer_fn; + double *attack_rate; + double *decay_rate; + double *volume; + double delay; + double topfreq; + Crossover filter; + AVFrame *delay_buf; + size_t delay_size; + ptrdiff_t delay_buf_ptr; + size_t delay_buf_cnt; +} CompBand; + +typedef struct MCompandContext { + const AVClass *class; + + char *args; + + int nb_bands; + CompBand *bands; + AVFrame *band_buf1, *band_buf2, *band_buf3; + int band_samples; + size_t delay_buf_size; +} MCompandContext; + +#define OFFSET(x) offsetof(MCompandContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption mcompand_options[] = { + { "args", "set parameters for each band", OFFSET(args), AV_OPT_TYPE_STRING, { .str = "0.005,0.1 6 -47/-40,-34/-34,-17/-33 100 | 0.003,0.05 6 -47/-40,-34/-34,-17/-33 400 | 0.000625,0.0125 6 -47/-40,-34/-34,-15/-33 1600 | 0.0001,0.025 6 -47/-40,-34/-34,-31/-31,-0/-30 6400 | 0,0.025 6 -38/-31,-28/-28,-0/-25 22000" }, 0, 0, A }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(mcompand); + +static av_cold void uninit(AVFilterContext *ctx) +{ + MCompandContext *s = ctx->priv; + int i; + + av_frame_free(&s->band_buf1); + av_frame_free(&s->band_buf2); + av_frame_free(&s->band_buf3); + + if (s->bands) { + for (i = 0; i < s->nb_bands; i++) { + av_freep(&s->bands[i].attack_rate); + av_freep(&s->bands[i].decay_rate); + av_freep(&s->bands[i].volume); + av_freep(&s->bands[i].transfer_fn.segments); + av_freep(&s->bands[i].filter.previous); + av_frame_free(&s->bands[i].delay_buf); + } + } + av_freep(&s->bands); +} + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterChannelLayouts *layouts; + AVFilterFormats *formats; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE + }; + int ret; + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + formats = ff_all_samplerates(); + if (!formats) + return AVERROR(ENOMEM); + return ff_set_common_samplerates(ctx, formats); +} + +static void count_items(char *item_str, int *nb_items, char delimiter) +{ + char *p; + + *nb_items = 1; + for (p = item_str; *p; p++) { + if (*p == delimiter) + (*nb_items)++; + } +} + +static void update_volume(CompBand *cb, double in, int ch) +{ + double delta = in - cb->volume[ch]; + + if (delta > 0.0) + cb->volume[ch] += delta * cb->attack_rate[ch]; + else + cb->volume[ch] += delta * cb->decay_rate[ch]; +} + +static double get_volume(CompandT *s, double in_lin) +{ + CompandSegment *cs; + double in_log, out_log; + int i; + + if (in_lin <= s->in_min_lin) + return s->out_min_lin; + + in_log = log(in_lin); + + for (i = 1; i < s->nb_segments; i++) + if (in_log <= s->segments[i].x) + break; + cs = &s->segments[i - 1]; + in_log -= cs->x; + out_log = cs->y + in_log * (cs->a * in_log + cs->b); + + return exp(out_log); +} + +static int parse_points(char *points, int nb_points, double radius, + CompandT *s, AVFilterContext *ctx) +{ + int new_nb_items, num; + char *saveptr = NULL; + char *p = points; + int i; + +#define S(x) s->segments[2 * ((x) + 1)] + for (i = 0, new_nb_items = 0; i < nb_points; i++) { + char *tstr = av_strtok(p, ",", &saveptr); + p = NULL; + if (!tstr || sscanf(tstr, "%lf/%lf", &S(i).x, &S(i).y) != 2) { + av_log(ctx, AV_LOG_ERROR, + "Invalid and/or missing input/output value.\n"); + return AVERROR(EINVAL); + } + if (i && S(i - 1).x > S(i).x) { + av_log(ctx, AV_LOG_ERROR, + "Transfer function input values must be increasing.\n"); + return AVERROR(EINVAL); + } + S(i).y -= S(i).x; + av_log(ctx, AV_LOG_DEBUG, "%d: x=%f y=%f\n", i, S(i).x, S(i).y); + new_nb_items++; + } + num = new_nb_items; + + /* Add 0,0 if necessary */ + if (num == 0 || S(num - 1).x) + num++; + +#undef S +#define S(x) s->segments[2 * (x)] + /* Add a tail off segment at the start */ + S(0).x = S(1).x - 2 * s->curve_dB; + S(0).y = S(1).y; + num++; + + /* Join adjacent colinear segments */ + for (i = 2; i < num; i++) { + double g1 = (S(i - 1).y - S(i - 2).y) * (S(i - 0).x - S(i - 1).x); + double g2 = (S(i - 0).y - S(i - 1).y) * (S(i - 1).x - S(i - 2).x); + int j; + + if (fabs(g1 - g2)) + continue; + num--; + for (j = --i; j < num; j++) + S(j) = S(j + 1); + } + + for (i = 0; i < s->nb_segments; i += 2) { + s->segments[i].y += s->gain_dB; + s->segments[i].x *= M_LN10 / 20; + s->segments[i].y *= M_LN10 / 20; + } + +#define L(x) s->segments[i - (x)] + for (i = 4; i < s->nb_segments; i += 2) { + double x, y, cx, cy, in1, in2, out1, out2, theta, len, r; + + L(4).a = 0; + L(4).b = (L(2).y - L(4).y) / (L(2).x - L(4).x); + + L(2).a = 0; + L(2).b = (L(0).y - L(2).y) / (L(0).x - L(2).x); + + theta = atan2(L(2).y - L(4).y, L(2).x - L(4).x); + len = hypot(L(2).x - L(4).x, L(2).y - L(4).y); + r = FFMIN(radius, len); + L(3).x = L(2).x - r * cos(theta); + L(3).y = L(2).y - r * sin(theta); + + theta = atan2(L(0).y - L(2).y, L(0).x - L(2).x); + len = hypot(L(0).x - L(2).x, L(0).y - L(2).y); + r = FFMIN(radius, len / 2); + x = L(2).x + r * cos(theta); + y = L(2).y + r * sin(theta); + + cx = (L(3).x + L(2).x + x) / 3; + cy = (L(3).y + L(2).y + y) / 3; + + L(2).x = x; + L(2).y = y; + + in1 = cx - L(3).x; + out1 = cy - L(3).y; + in2 = L(2).x - L(3).x; + out2 = L(2).y - L(3).y; + L(3).a = (out2 / in2 - out1 / in1) / (in2 - in1); + L(3).b = out1 / in1 - L(3).a * in1; + } + L(3).x = 0; + L(3).y = L(2).y; + + s->in_min_lin = exp(s->segments[1].x); + s->out_min_lin = exp(s->segments[1].y); + + return 0; +} + +static void square_quadratic(double const *x, double *y) +{ + y[0] = x[0] * x[0]; + y[1] = 2 * x[0] * x[1]; + y[2] = 2 * x[0] * x[2] + x[1] * x[1]; + y[3] = 2 * x[1] * x[2]; + y[4] = x[2] * x[2]; +} + +static int crossover_setup(AVFilterLink *outlink, Crossover *p, double frequency) +{ + double w0 = 2 * M_PI * frequency / outlink->sample_rate; + double Q = sqrt(.5), alpha = sin(w0) / (2*Q); + double x[9], norm; + int i; + + if (w0 > M_PI) + return AVERROR(EINVAL); + + x[0] = (1 - cos(w0))/2; /* Cf. filter_LPF in biquads.c */ + x[1] = 1 - cos(w0); + x[2] = (1 - cos(w0))/2; + x[3] = (1 + cos(w0))/2; /* Cf. filter_HPF in biquads.c */ + x[4] = -(1 + cos(w0)); + x[5] = (1 + cos(w0))/2; + x[6] = 1 + alpha; + x[7] = -2*cos(w0); + x[8] = 1 - alpha; + + for (norm = x[6], i = 0; i < 9; ++i) + x[i] /= norm; + + square_quadratic(x , p->coefs); + square_quadratic(x + 3, p->coefs + 5); + square_quadratic(x + 6, p->coefs + 10); + + p->previous = av_calloc(outlink->channels, sizeof(*p->previous)); + if (!p->previous) + return AVERROR(ENOMEM); + + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + MCompandContext *s = ctx->priv; + int ret, ch, i, k, new_nb_items, nb_bands; + char *p = s->args, *saveptr = NULL; + int max_delay_size = 0; + + count_items(s->args, &nb_bands, '|'); + s->nb_bands = FFMAX(1, nb_bands); + + s->bands = av_calloc(nb_bands, sizeof(*s->bands)); + if (!s->bands) + return AVERROR(ENOMEM); + + for (i = 0, new_nb_items = 0; i < nb_bands; i++) { + int nb_points, nb_attacks, nb_items = 0; + char *tstr2, *tstr = av_strtok(p, "|", &saveptr); + char *p2, *p3, *saveptr2 = NULL, *saveptr3 = NULL; + double radius; + + if (!tstr) { + uninit(ctx); + return AVERROR(EINVAL); + } + p = NULL; + + p2 = tstr; + count_items(tstr, &nb_items, ' '); + tstr2 = av_strtok(p2, " ", &saveptr2); + if (!tstr2) { + av_log(ctx, AV_LOG_ERROR, "at least one attacks/decays rate is mandatory\n"); + uninit(ctx); + return AVERROR(EINVAL); + } + p2 = NULL; + p3 = tstr2; + + count_items(tstr2, &nb_attacks, ','); + if (!nb_attacks || nb_attacks & 1) { + av_log(ctx, AV_LOG_ERROR, "number of attacks rate plus decays rate must be even\n"); + uninit(ctx); + return AVERROR(EINVAL); + } + + s->bands[i].attack_rate = av_calloc(outlink->channels, sizeof(double)); + s->bands[i].decay_rate = av_calloc(outlink->channels, sizeof(double)); + s->bands[i].volume = av_calloc(outlink->channels, sizeof(double)); + for (k = 0; k < FFMIN(nb_attacks / 2, outlink->channels); k++) { + char *tstr3 = av_strtok(p3, ",", &saveptr3); + + p3 = NULL; + sscanf(tstr3, "%lf", &s->bands[i].attack_rate[k]); + tstr3 = av_strtok(p3, ",", &saveptr3); + sscanf(tstr3, "%lf", &s->bands[i].decay_rate[k]); + + if (s->bands[i].attack_rate[k] > 1.0 / outlink->sample_rate) { + s->bands[i].attack_rate[k] = 1.0 - exp(-1.0 / (outlink->sample_rate * s->bands[i].attack_rate[k])); + } else { + s->bands[i].attack_rate[k] = 1.0; + } + + if (s->bands[i].decay_rate[k] > 1.0 / outlink->sample_rate) { + s->bands[i].decay_rate[k] = 1.0 - exp(-1.0 / (outlink->sample_rate * s->bands[i].decay_rate[k])); + } else { + s->bands[i].decay_rate[k] = 1.0; + } + } + + for (ch = k; ch < outlink->channels; ch++) { + s->bands[i].attack_rate[ch] = s->bands[i].attack_rate[k - 1]; + s->bands[i].decay_rate[ch] = s->bands[i].decay_rate[k - 1]; + } + + tstr2 = av_strtok(p2, " ", &saveptr2); + if (!tstr2) { + av_log(ctx, AV_LOG_ERROR, "transfer function curve in dB must be set\n"); + uninit(ctx); + return AVERROR(EINVAL); + } + sscanf(tstr2, "%lf", &s->bands[i].transfer_fn.curve_dB); + + radius = s->bands[i].transfer_fn.curve_dB * M_LN10 / 20.0; + + tstr2 = av_strtok(p2, " ", &saveptr2); + if (!tstr2) { + av_log(ctx, AV_LOG_ERROR, "transfer points missing\n"); + uninit(ctx); + return AVERROR(EINVAL); + } + + count_items(tstr2, &nb_points, ','); + s->bands[i].transfer_fn.nb_segments = (nb_points + 4) * 2; + s->bands[i].transfer_fn.segments = av_calloc(s->bands[i].transfer_fn.nb_segments, + sizeof(CompandSegment)); + if (!s->bands[i].transfer_fn.segments) { + uninit(ctx); + return AVERROR(ENOMEM); + } + + ret = parse_points(tstr2, nb_points, radius, &s->bands[i].transfer_fn, ctx); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "transfer points parsing failed\n"); + uninit(ctx); + return ret; + } + + tstr2 = av_strtok(p2, " ", &saveptr2); + if (!tstr2) { + av_log(ctx, AV_LOG_ERROR, "crossover_frequency is missing\n"); + uninit(ctx); + return AVERROR(EINVAL); + } + + new_nb_items += sscanf(tstr2, "%lf", &s->bands[i].topfreq) == 1; + if (s->bands[i].topfreq < 0 || s->bands[i].topfreq >= outlink->sample_rate / 2) { + av_log(ctx, AV_LOG_ERROR, "crossover_frequency should be >=0 and lower than half of sample rate\n"); + uninit(ctx); + return AVERROR(EINVAL); + } + + if (s->bands[i].topfreq != 0) { + ret = crossover_setup(outlink, &s->bands[i].filter, s->bands[i].topfreq); + if (ret < 0) { + uninit(ctx); + return ret; + } + } + + tstr2 = av_strtok(p2, " ", &saveptr2); + if (tstr2) { + sscanf(tstr2, "%lf", &s->bands[i].delay); + max_delay_size = FFMAX(max_delay_size, s->bands[i].delay * outlink->sample_rate); + + tstr2 = av_strtok(p2, " ", &saveptr2); + if (tstr2) { + double initial_volume; + + sscanf(tstr2, "%lf", &initial_volume); + initial_volume = pow(10.0, initial_volume / 20); + + for (k = 0; k < outlink->channels; k++) { + s->bands[i].volume[k] = initial_volume; + } + + tstr2 = av_strtok(p2, " ", &saveptr2); + if (tstr2) { + sscanf(tstr2, "%lf", &s->bands[i].transfer_fn.gain_dB); + } + } + } + } + s->nb_bands = new_nb_items; + + for (i = 0; max_delay_size > 0 && i < s->nb_bands; i++) { + s->bands[i].delay_buf = ff_get_audio_buffer(outlink, max_delay_size); + if (!s->bands[i].delay_buf) + return AVERROR(ENOMEM); + } + s->delay_buf_size = max_delay_size; + + return 0; +} + +#define CONVOLVE _ _ _ _ + +static void crossover(int ch, Crossover *p, + double *ibuf, double *obuf_low, + double *obuf_high, size_t len) +{ + double out_low, out_high; + + while (len--) { + p->pos = p->pos ? p->pos - 1 : N - 1; +#define _ out_low += p->coefs[j] * p->previous[ch][p->pos + j].in \ + - p->coefs[2*N+2 + j] * p->previous[ch][p->pos + j].out_low, j++; + { + int j = 1; + out_low = p->coefs[0] * *ibuf; + CONVOLVE + *obuf_low++ = out_low; + } +#undef _ +#define _ out_high += p->coefs[j+N+1] * p->previous[ch][p->pos + j].in \ + - p->coefs[2*N+2 + j] * p->previous[ch][p->pos + j].out_high, j++; + { + int j = 1; + out_high = p->coefs[N+1] * *ibuf; + CONVOLVE + *obuf_high++ = out_high; + } + p->previous[ch][p->pos + N].in = p->previous[ch][p->pos].in = *ibuf++; + p->previous[ch][p->pos + N].out_low = p->previous[ch][p->pos].out_low = out_low; + p->previous[ch][p->pos + N].out_high = p->previous[ch][p->pos].out_high = out_high; + } +} + +static int mcompand_channel(MCompandContext *c, CompBand *l, double *ibuf, double *obuf, int len, int ch) +{ + int i; + + for (i = 0; i < len; i++) { + double level_in_lin, level_out_lin, checkbuf; + /* Maintain the volume fields by simulating a leaky pump circuit */ + update_volume(l, fabs(ibuf[i]), ch); + + /* Volume memory is updated: perform compand */ + level_in_lin = l->volume[ch]; + level_out_lin = get_volume(&l->transfer_fn, level_in_lin); + + if (c->delay_buf_size <= 0) { + checkbuf = ibuf[i] * level_out_lin; + obuf[i] = checkbuf; + } else { + double *delay_buf = (double *)l->delay_buf->extended_data[ch]; + + /* FIXME: note that this lookahead algorithm is really lame: + the response to a peak is released before the peak + arrives. */ + + /* because volume application delays differ band to band, but + total delay doesn't, the volume is applied in an iteration + preceding that in which the sample goes to obuf, except in + the band(s) with the longest vol app delay. + + the offset between delay_buf_ptr and the sample to apply + vol to, is a constant equal to the difference between this + band's delay and the longest delay of all the bands. */ + + if (l->delay_buf_cnt >= l->delay_size) { + checkbuf = + delay_buf[(l->delay_buf_ptr + + c->delay_buf_size - + l->delay_size) % c->delay_buf_size] * level_out_lin; + delay_buf[(l->delay_buf_ptr + c->delay_buf_size - + l->delay_size) % c->delay_buf_size] = checkbuf; + } + if (l->delay_buf_cnt >= c->delay_buf_size) { + obuf[i] = delay_buf[l->delay_buf_ptr]; + } else { + l->delay_buf_cnt++; + } + delay_buf[l->delay_buf_ptr++] = ibuf[i]; + l->delay_buf_ptr %= c->delay_buf_size; + } + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + MCompandContext *s = ctx->priv; + AVFrame *out, *abuf, *bbuf, *cbuf; + int ch, band, i; + + out = ff_get_audio_buffer(outlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + + if (s->band_samples < in->nb_samples) { + av_frame_free(&s->band_buf1); + av_frame_free(&s->band_buf2); + av_frame_free(&s->band_buf3); + + s->band_buf1 = ff_get_audio_buffer(outlink, in->nb_samples); + s->band_buf2 = ff_get_audio_buffer(outlink, in->nb_samples); + s->band_buf3 = ff_get_audio_buffer(outlink, in->nb_samples); + s->band_samples = in->nb_samples; + } + + for (ch = 0; ch < outlink->channels; ch++) { + double *a, *dst = (double *)out->extended_data[ch]; + + for (band = 0, abuf = in, bbuf = s->band_buf2, cbuf = s->band_buf1; band < s->nb_bands; band++) { + CompBand *b = &s->bands[band]; + + if (b->topfreq) { + crossover(ch, &b->filter, (double *)abuf->extended_data[ch], + (double *)bbuf->extended_data[ch], (double *)cbuf->extended_data[ch], in->nb_samples); + } else { + bbuf = abuf; + abuf = cbuf; + } + + if (abuf == in) + abuf = s->band_buf3; + mcompand_channel(s, b, (double *)bbuf->extended_data[ch], (double *)abuf->extended_data[ch], out->nb_samples, ch); + a = (double *)abuf->extended_data[ch]; + for (i = 0; i < out->nb_samples; i++) { + dst[i] += a[i]; + } + + FFSWAP(AVFrame *, abuf, cbuf); + } + } + + out->pts = in->pts; + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static int request_frame(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + int ret; + + ret = ff_request_frame(ctx->inputs[0]); + + return ret; +} + +static const AVFilterPad mcompand_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad mcompand_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .request_frame = request_frame, + .config_props = config_output, + }, + { NULL } +}; + + +AVFilter ff_af_mcompand = { + .name = "mcompand", + .description = NULL_IF_CONFIG_SMALL( + "Multiband Compress or expand audio dynamic range."), + .query_formats = query_formats, + .priv_size = sizeof(MCompandContext), + .priv_class = &mcompand_class, + .uninit = uninit, + .inputs = mcompand_inputs, + .outputs = mcompand_outputs, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 3647a111ec19b..a838309569cf1 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -112,6 +112,7 @@ static void register_all(void) REGISTER_FILTER(LADSPA, ladspa, af); REGISTER_FILTER(LOUDNORM, loudnorm, af); REGISTER_FILTER(LOWPASS, lowpass, af); + REGISTER_FILTER(MCOMPAND, mcompand, af); REGISTER_FILTER(PAN, pan, af); REGISTER_FILTER(REPLAYGAIN, replaygain, af); REGISTER_FILTER(RESAMPLE, resample, af); diff --git a/libavfilter/version.h b/libavfilter/version.h index 908dc4938a64d..33d9ad7bc7297 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,8 +30,8 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 0 -#define LIBAVFILTER_VERSION_MICRO 101 +#define LIBAVFILTER_VERSION_MINOR 1 +#define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ From c3b9bbcc6edf2d83fe4857484cfa0839872188c6 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 15 Nov 2017 21:17:15 +0100 Subject: [PATCH 0955/2557] avcodec/snowdec: Check intra block dc differences. Fixes: Timeout Fixes: 3142/clusterfuzz-testcase-5007853163118592 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/snowdec.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/libavcodec/snowdec.c b/libavcodec/snowdec.c index 727e908fb5a49..a8287696102e6 100644 --- a/libavcodec/snowdec.c +++ b/libavcodec/snowdec.c @@ -183,13 +183,22 @@ static int decode_q_branch(SnowContext *s, int level, int x, int y){ int my_context= av_log2(2*FFABS(left->my - top->my)) + 0*av_log2(2*FFABS(tr->my - top->my)); type= get_rac(&s->c, &s->block_state[1 + left->type + top->type]) ? BLOCK_INTRA : 0; - if(type){ + int ld, cbd, crd; pred_mv(s, &mx, &my, 0, left, top, tr); - l += get_symbol(&s->c, &s->block_state[32], 1); + ld = get_symbol(&s->c, &s->block_state[32], 1); + if (ld < -255 || ld > 255) { + return AVERROR_INVALIDDATA; + } + l += ld; if (s->nb_planes > 2) { - cb+= get_symbol(&s->c, &s->block_state[64], 1); - cr+= get_symbol(&s->c, &s->block_state[96], 1); + cbd = get_symbol(&s->c, &s->block_state[64], 1); + crd = get_symbol(&s->c, &s->block_state[96], 1); + if (cbd < -255 || cbd > 255 || crd < -255 || crd > 255) { + return AVERROR_INVALIDDATA; + } + cb += cbd; + cr += crd; } }else{ if(s->ref_frames > 1) From 4527ec2216109867498edc3ac8a17fd879b5d017 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 15 Nov 2017 21:17:16 +0100 Subject: [PATCH 0956/2557] avcodec/snowdec: Check for remaining bitstream in decode_blocks() Fixes: Timeout Fixes: 3142/clusterfuzz-testcase-5007853163118592 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/snowdec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/snowdec.c b/libavcodec/snowdec.c index a8287696102e6..a9bdb8da5ef0f 100644 --- a/libavcodec/snowdec.c +++ b/libavcodec/snowdec.c @@ -437,6 +437,8 @@ static int decode_blocks(SnowContext *s){ for(y=0; yc.bytestream >= s->c.bytestream_end) + return AVERROR_INVALIDDATA; if ((res = decode_q_branch(s, 0, x, y)) < 0) return res; } From 3071434f4d72323214ef262e3f4105da110ca878 Mon Sep 17 00:00:00 2001 From: James Zern Date: Mon, 13 Nov 2017 15:19:07 -0800 Subject: [PATCH 0957/2557] lavc/libvpxenc: add tune-content option this matches the vpxenc parameter Signed-off-by: James Zern --- doc/encoders.texi | 2 ++ libavcodec/libvpxenc.c | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index 431777c457859..23451b7b920ae 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -1681,6 +1681,8 @@ colorspaces: @end table @item row-mt @var{boolean} Enable row based multi-threading. +@item tune-content +Set content type: default (0), screen (1), film (2). @end table @end table diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index d720301cd13a0..fbb842499bbb1 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -109,6 +109,7 @@ typedef struct VPxEncoderContext { int vpx_cs; float level; int row_mt; + int tune_content; } VPxContext; /** String mappings for enum vp8e_enc_control_id */ @@ -143,6 +144,9 @@ static const char *const ctlidstr[] = { #ifdef VPX_CTRL_VP9E_SET_ROW_MT [VP9E_SET_ROW_MT] = "VP9E_SET_ROW_MT", #endif +#ifdef VPX_CTRL_VP9E_SET_TUNE_CONTENT + [VP9E_SET_TUNE_CONTENT] = "VP9E_SET_TUNE_CONTENT", +#endif #endif }; @@ -709,6 +713,10 @@ FF_ENABLE_DEPRECATION_WARNINGS #ifdef VPX_CTRL_VP9E_SET_ROW_MT if (ctx->row_mt >= 0) codecctl_int(avctx, VP9E_SET_ROW_MT, ctx->row_mt); +#endif +#ifdef VPX_CTRL_VP9E_SET_TUNE_CONTENT + if (ctx->tune_content >= 0) + codecctl_int(avctx, VP9E_SET_TUNE_CONTENT, ctx->tune_content); #endif } #endif @@ -1139,6 +1147,18 @@ static const AVOption vp9_options[] = { #endif #ifdef VPX_CTRL_VP9E_SET_ROW_MT {"row-mt", "Row based multi-threading", OFFSET(row_mt), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, +#endif +#ifdef VPX_CTRL_VP9E_SET_TUNE_CONTENT +#if VPX_ENCODER_ABI_VERSION >= 14 + { "tune-content", "Tune content type", OFFSET(tune_content), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, VE, "tune_content" }, +#else + { "tune-content", "Tune content type", OFFSET(tune_content), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE, "tune_content" }, +#endif + { "default", "Regular video content", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, VE, "tune_content" }, + { "screen", "Screen capture content", 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, VE, "tune_content" }, +#if VPX_ENCODER_ABI_VERSION >= 14 + { "film", "Film content; improves grain retention", 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE, "tune_content" }, +#endif #endif LEGACY_OPTIONS { NULL } From 1f28a991effadc64acd6915805b989ab43500f08 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Fri, 5 May 2017 14:29:59 -0700 Subject: [PATCH 0958/2557] libavcodec/h264_sei: Don't log random user data. This prevents terminal junk. --- libavcodec/h264_sei.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c index 332ae508606c0..ae5f39f77581b 100644 --- a/libavcodec/h264_sei.c +++ b/libavcodec/h264_sei.c @@ -257,9 +257,6 @@ static int decode_unregistered_user_data(H264SEIUnregistered *h, GetBitContext * if (e == 1 && build == 1 && !strncmp(user_data+16, "x264 - core 0000", 16)) h->x264_build = 67; - if (strlen(user_data + 16) > 0) - av_log(logctx, AV_LOG_DEBUG, "user data:\"%s\"\n", user_data + 16); - av_free(user_data); return 0; } From 6fb617077621236a34c2a1b6ae9e2ffc2ccd8902 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Wed, 15 Nov 2017 19:22:42 +0100 Subject: [PATCH 0959/2557] hwcontext_d3d11va: add missing stdint.h include This caused checkheaders to fail on cygwin on this file. --- libavutil/hwcontext_d3d11va.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h index 98db7ce34310d..9f91e9b1b67bf 100644 --- a/libavutil/hwcontext_d3d11va.h +++ b/libavutil/hwcontext_d3d11va.h @@ -37,6 +37,7 @@ */ #include +#include /** * This struct is allocated as AVHWDeviceContext.hwctx From 15b019e40adb1fdc25f7ba1aca8f473619d07ae7 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Wed, 15 Nov 2017 19:15:23 +0100 Subject: [PATCH 0960/2557] avcodec/nvenc: fix double defined GUID on cygwin --- compat/nvenc/nvEncodeAPI.h | 2 +- libavcodec/nvenc.h | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compat/nvenc/nvEncodeAPI.h b/compat/nvenc/nvEncodeAPI.h index c3a829421282d..e662880f4d94e 100644 --- a/compat/nvenc/nvEncodeAPI.h +++ b/compat/nvenc/nvEncodeAPI.h @@ -77,7 +77,7 @@ extern "C" { typedef RECT NVENC_RECT; #else // ========================================================================================= -#ifndef GUID +#if !defined(GUID) && !defined(GUID_DEFINED) /*! * \struct GUID * Abstracts the GUID structure for non-windows platforms. diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 55ac5f220d967..8c1769e768993 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -19,6 +19,13 @@ #ifndef AVCODEC_NVENC_H #define AVCODEC_NVENC_H +#if CONFIG_D3D11VA +#define COBJMACROS +#include "libavutil/hwcontext_d3d11va.h" +#else +typedef void ID3D11Device; +#endif + #include "compat/nvenc/nvEncodeAPI.h" #include "config.h" @@ -27,13 +34,6 @@ #include "libavutil/fifo.h" #include "libavutil/opt.h" -#if CONFIG_D3D11VA -#define COBJMACROS -#include "libavutil/hwcontext_d3d11va.h" -#else -typedef void ID3D11Device; -#endif - #include "avcodec.h" #define MAX_REGISTERED_FRAMES 64 From 4e93f00b06d9623ea9639ba7185cdacdf11c2672 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Wed, 15 Nov 2017 18:33:31 +0100 Subject: [PATCH 0961/2557] avcodec/nvenc: check pop_context return value --- libavcodec/nvenc.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 0139e70c3bbcf..e07280b568274 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -1293,7 +1293,7 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx) { NvencContext *ctx = avctx->priv_data; - int i, res; + int i, res = 0, res2; ctx->surfaces = av_mallocz_array(ctx->nb_surfaces, sizeof(*ctx->surfaces)); if (!ctx->surfaces) @@ -1320,17 +1320,15 @@ static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx) for (i = 0; i < ctx->nb_surfaces; i++) { if ((res = nvenc_alloc_surface(avctx, i)) < 0) - { - nvenc_pop_context(avctx); - return res; - } + goto fail; } - res = nvenc_pop_context(avctx); - if (res < 0) - return res; +fail: + res2 = nvenc_pop_context(avctx); + if (res2 < 0) + return res2; - return 0; + return res; } static av_cold int nvenc_setup_extradata(AVCodecContext *avctx) From f3af34f9ebd2e3f38fcf8fac099052668bd55224 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 14 Nov 2017 18:01:03 +0100 Subject: [PATCH 0962/2557] lavc/dnxhddata: Improve help output, mention yuv444p10 and gbrp10. Fixes ticket #6836. --- libavcodec/dnxhddata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/dnxhddata.c b/libavcodec/dnxhddata.c index d7d3331b4f8ad..e9dd29ce4c605 100644 --- a/libavcodec/dnxhddata.c +++ b/libavcodec/dnxhddata.c @@ -1158,7 +1158,7 @@ void ff_dnxhd_print_profiles(AVCodecContext *avctx, int loglevel) av_log(avctx, loglevel, "Frame size: %dx%d%c; bitrate: %dMbps; pixel format: %s\n", cid->width, cid->height, cid->flags & DNXHD_INTERLACED ? 'i' : 'p', cid->bit_rates[j], - cid->bit_depth == 10 ? "yuv422p10" : "yuv422p"); + cid->flags & DNXHD_444 ? "yuv444p10, gbrp10" : cid->bit_depth == 10 ? "yuv422p10" : "yuv422p"); } } } From 65e0a7c473f23f1833538ffecf53c81fe500b5e4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 17 Sep 2017 01:28:07 +0200 Subject: [PATCH 0963/2557] avcodec/wmv2dec: Check end of bitstream in parse_mb_skip() and ff_wmv2_decode_mb() Fixes: Timeout Fixes: 3200/clusterfuzz-testcase-5750022136135680 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/wmv2dec.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c index 261d291c97b47..ea0e0594b5063 100644 --- a/libavcodec/wmv2dec.c +++ b/libavcodec/wmv2dec.c @@ -30,7 +30,7 @@ #include "wmv2.h" -static void parse_mb_skip(Wmv2Context *w) +static int parse_mb_skip(Wmv2Context *w) { int mb_x, mb_y; MpegEncContext *const s = &w->s; @@ -45,6 +45,8 @@ static void parse_mb_skip(Wmv2Context *w) MB_TYPE_16x16 | MB_TYPE_L0; break; case SKIP_TYPE_MPEG: + if (get_bits_left(&s->gb) < s->mb_height * s->mb_width) + return AVERROR_INVALIDDATA; for (mb_y = 0; mb_y < s->mb_height; mb_y++) for (mb_x = 0; mb_x < s->mb_width; mb_x++) mb_type[mb_y * s->mb_stride + mb_x] = @@ -52,6 +54,8 @@ static void parse_mb_skip(Wmv2Context *w) break; case SKIP_TYPE_ROW: for (mb_y = 0; mb_y < s->mb_height; mb_y++) { + if (get_bits_left(&s->gb) < 1) + return AVERROR_INVALIDDATA; if (get_bits1(&s->gb)) { for (mb_x = 0; mb_x < s->mb_width; mb_x++) mb_type[mb_y * s->mb_stride + mb_x] = @@ -65,6 +69,8 @@ static void parse_mb_skip(Wmv2Context *w) break; case SKIP_TYPE_COL: for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + if (get_bits_left(&s->gb) < 1) + return AVERROR_INVALIDDATA; if (get_bits1(&s->gb)) { for (mb_y = 0; mb_y < s->mb_height; mb_y++) mb_type[mb_y * s->mb_stride + mb_x] = @@ -77,6 +83,7 @@ static void parse_mb_skip(Wmv2Context *w) } break; } + return 0; } static int decode_ext_header(Wmv2Context *w) @@ -170,9 +177,12 @@ int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s) } } else { int cbp_index; + int ret; w->j_type = 0; - parse_mb_skip(w); + ret = parse_mb_skip(w); + if (ret < 0) + return ret; cbp_index = decode012(&s->gb); w->cbp_table_index = wmv2_get_cbp_table_index(s, cbp_index); @@ -359,6 +369,8 @@ int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) w->hshift = 0; return 0; } + if (get_bits_left(&s->gb) <= 0) + return AVERROR_INVALIDDATA; code = get_vlc2(&s->gb, ff_mb_non_intra_vlc[w->cbp_table_index].table, MB_NON_INTRA_VLC_BITS, 3); @@ -369,6 +381,8 @@ int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) cbp = code & 0x3f; } else { s->mb_intra = 1; + if (get_bits_left(&s->gb) <= 0) + return AVERROR_INVALIDDATA; code = get_vlc2(&s->gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); if (code < 0) { av_log(s->avctx, AV_LOG_ERROR, From 73964680d7bce6d81ddc553a24d73e9a1c9156f9 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 14 Nov 2017 03:40:07 +0100 Subject: [PATCH 0964/2557] avcodec/dirac_dwt: Fix integer overflow in COMPOSE_DD137iL0() Fixes: 4035/clusterfuzz-testcase-minimized-6479308925173760 Fixes: runtime error: signed integer overflow: 9 * 402653183 cannot be represented in type 'int' Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/dirac_dwt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/dirac_dwt.h b/libavcodec/dirac_dwt.h index 35ed8857e9e80..f9a9e9e1b379c 100644 --- a/libavcodec/dirac_dwt.h +++ b/libavcodec/dirac_dwt.h @@ -102,7 +102,7 @@ void ff_spatial_idwt_slice2(DWTContext *d, int y); (b2 + ((int)(-b0 + 9U*b1 + 9U*b3 - b4 + 8) >> 4)) #define COMPOSE_DD137iL0(b0, b1, b2, b3, b4)\ - (b2 - ((-b0 + 9*b1 + 9*b3 - b4 + 16) >> 5)) + (b2 - ((int)(-b0 + 9U*b1 + 9U*b3 - b4 + 16) >> 5)) #define COMPOSE_HAARiL0(b0, b1)\ (b0 - ((b1 + 1) >> 1)) From 2ab9568a2c3349039eec29fb960fe39de354b514 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 15 Nov 2017 17:11:12 +0100 Subject: [PATCH 0965/2557] avcodec/zmbv: Check that the buffer is large enough for mvec Fixes: Timeout Fixes: 4143/clusterfuzz-testcase-4736864637419520 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/zmbv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/zmbv.c b/libavcodec/zmbv.c index b09dc41ebd2ae..f91d2e393179d 100644 --- a/libavcodec/zmbv.c +++ b/libavcodec/zmbv.c @@ -539,6 +539,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac } else { frame->key_frame = 0; frame->pict_type = AV_PICTURE_TYPE_P; + if (c->decomp_len < 2LL * ((c->width + c->bw - 1) / c->bw) * ((c->height + c->bh - 1) / c->bh)) + return AVERROR_INVALIDDATA; if (c->decomp_len) c->decode_xor(c); } From 4f7f70738e8dd77a698a5e28bba552ea7064af21 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 15 Nov 2017 03:38:37 +0100 Subject: [PATCH 0966/2557] avcodec/mlpdsp: Fix undefined shift ff_mlp_pack_output() Fixes: runtime error: left shift of negative value -7862264 Fixes: 4074/clusterfuzz-testcase-minimized-4516104123711488 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/mlpdsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mlpdsp.c b/libavcodec/mlpdsp.c index fbafa92d72cc3..4e3a16c781c4f 100644 --- a/libavcodec/mlpdsp.c +++ b/libavcodec/mlpdsp.c @@ -117,7 +117,7 @@ int32_t ff_mlp_pack_output(int32_t lossless_check_data, (1U << output_shift[mat_ch]); lossless_check_data ^= (sample & 0xffffff) << mat_ch; if (is32) - *data_32++ = sample << 8; + *data_32++ = sample * 256; else *data_16++ = sample >> 8; } From d073be2291e40129d107ca4573097d6d6d2dbf68 Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Fri, 17 Nov 2017 14:53:25 -0800 Subject: [PATCH 0967/2557] Fix leak of frame_duration_buffer in mov_fix_index(). Should be unconditionally freed at the end of mov_fix_index() in case it hasn't been used during the fix up. Signed-off-by: Dale Curtis Reviewed-by: Sasi Inguva Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index d49d820d2b62d..3eef043046003 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3553,6 +3553,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) // Free the old index and the old CTTS structures av_free(e_old); av_free(ctts_data_old); + av_freep(&frame_duration_buffer); // Null terminate the index ranges array current_index_range++; From 5eaaffaf64d1854493f0fe9ec822eed1b3cd9fe1 Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Fri, 17 Nov 2017 14:51:09 -0800 Subject: [PATCH 0968/2557] Use ff_thread_once for fixed, float table init. These tables are static so they should only be initialized once instead of on every call to ff_mpadsp_init(). Signed-off-by: Dale Curtis Signed-off-by: Michael Niedermayer --- libavcodec/mpegaudiodsp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpegaudiodsp.c b/libavcodec/mpegaudiodsp.c index a5d20df629095..3cafca27bfd8a 100644 --- a/libavcodec/mpegaudiodsp.c +++ b/libavcodec/mpegaudiodsp.c @@ -20,17 +20,21 @@ #include "config.h" #include "libavutil/attributes.h" +#include "libavutil/thread.h" #include "mpegaudiodsp.h" #include "dct.h" #include "dct32.h" +static AVOnce mpadsp_float_table_init = AV_ONCE_INIT; +static AVOnce mpadsp_fixed_table_init = AV_ONCE_INIT; + av_cold void ff_mpadsp_init(MPADSPContext *s) { DCTContext dct; ff_dct_init(&dct, 5, DCT_II); - ff_init_mpadsp_tabs_float(); - ff_init_mpadsp_tabs_fixed(); + ff_thread_once(&mpadsp_float_table_init, &ff_init_mpadsp_tabs_float); + ff_thread_once(&mpadsp_fixed_table_init, &ff_init_mpadsp_tabs_fixed); s->apply_window_float = ff_mpadsp_apply_window_float; s->apply_window_fixed = ff_mpadsp_apply_window_fixed; From 20c38f2e7085ce02c19df965d02ecdf5628f11b8 Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Fri, 17 Nov 2017 08:21:02 -0800 Subject: [PATCH 0969/2557] lavf/mov: don't read outside frag_index bounds Potentially fixes: https://bugs.chromium.org/p/chromium/issues/detail?id=786269#c1 In theory, the crash can be triggered by an invalid stream that has either tfdt or trun outside of the moof Reviewed-by: Dale Curtis Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index 3eef043046003..5c9f926bcefc4 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1188,6 +1188,10 @@ static void set_frag_stream(MOVFragmentIndex *frag_index, int id) static MOVFragmentStreamInfo * get_current_frag_stream_info( MOVFragmentIndex *frag_index) { + if (frag_index->current < 0 || + frag_index->current >= frag_index->nb_items) + return NULL; + MOVFragmentIndexItem * item = &frag_index->item[frag_index->current]; if (item->current >= 0 && item->current < item->nb_stream_info) return &item->stream_info[item->current]; From fb791d28766bdacbb685a77c381101afc98ed58b Mon Sep 17 00:00:00 2001 From: Jim DeLaHunt Date: Fri, 17 Nov 2017 01:45:27 -0800 Subject: [PATCH 0970/2557] Ignore libavcodec/tests/mpeg12framerate, a test program Add to libavcodec/tests/.gitignore an entry for test program libavcodec/tests/mpeg12framerate . Other similar test programs, e.g. jpeg2000dwt and dct, are ignored in a similar way. On initially checking out master, and doing "./configure" and "make clean", "git status" reports no untracked files. After running "make fate", "git status" reports untracked file "libavcodec/tests/mpeg12framerate". mpeg12framerate is a unit test program. It was apparently introduced in commit 278c308ceae6b8d7bac1dfc24518821aae603988, on Tue Sep 12 22:11:56 2017 +0100. It added a new function ff_mpeg12_find_best_frame_rate() to libavcodec/mpeg12framerate.c , and the code in libavcodec/tests/mpeg12framerate.c to exercise that function. This commit also added the new program to the FATE suite, but it omitted a .gitignore entry. Signed-off-by: Michael Niedermayer --- libavcodec/tests/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/tests/.gitignore b/libavcodec/tests/.gitignore index 7f9e3825b6148..350fb2990cd62 100644 --- a/libavcodec/tests/.gitignore +++ b/libavcodec/tests/.gitignore @@ -14,6 +14,7 @@ /mathops /mjpegenc_huffman /motion +/mpeg12framerate /options /rangecoder /snowenc From 5a0f6b099f3e8fcb95a80e3ffe52b3bf369efe24 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Thu, 16 Nov 2017 07:31:58 -0800 Subject: [PATCH 0971/2557] avcodec: Fix reference data type for nvdec vc1 hwaccel I took the reference lookup code from the vp9 hwaccel where the type is unsigned char, but for vc1, the type is signed int. This is particularly important because the value used when there's no reference is different (255 vs -1). It didn't seem to break anything, but for mpeg1/2/4, this mistake caused decode errors. --- libavcodec/nvdec_vc1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/nvdec_vc1.c b/libavcodec/nvdec_vc1.c index cf75ba5aca4f6..588a5b9d07b13 100644 --- a/libavcodec/nvdec_vc1.c +++ b/libavcodec/nvdec_vc1.c @@ -25,13 +25,13 @@ #include "decode.h" #include "vc1.h" -static unsigned char get_ref_idx(AVFrame *frame) +static int get_ref_idx(AVFrame *frame) { FrameDecodeData *fdd; NVDECFrame *cf; if (!frame || !frame->private_ref) - return 255; + return -1; fdd = (FrameDecodeData*)frame->private_ref->data; cf = (NVDECFrame*)fdd->hwaccel_priv; From 7c9f739d864c0ed8f1b433d6a7d9f674edda9cf5 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Thu, 16 Nov 2017 07:35:17 -0800 Subject: [PATCH 0972/2557] avcodec: Implement mpeg2 nvdec hwaccel This is mostly straight-forward. The weird part is that it should just work for mpeg1, but I see corruption in my test cases, so I'm going to try and fix that separately. --- Changelog | 2 +- configure | 2 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/mpeg12dec.c | 3 + libavcodec/nvdec.c | 11 +-- libavcodec/nvdec_mpeg12.c | 152 ++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 8 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 libavcodec/nvdec_mpeg12.c diff --git a/Changelog b/Changelog index 119ab678e5e1c..cda59166fc166 100644 --- a/Changelog +++ b/Changelog @@ -13,7 +13,7 @@ version : - PCE support for extended channel layouts in the AAC encoder - native aptX encoder and decoder - Raw aptX muxer and demuxer -- NVIDIA NVDEC-accelerated H.264, HEVC, VC1 and VP9 hwaccel decoding +- NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-2, VC1 and VP9 hwaccel decoding - Intel QSV-accelerated overlay filter - mcompand audio filter diff --git a/configure b/configure index c8e2e35192222..8b7b7e164b359 100755 --- a/configure +++ b/configure @@ -2713,6 +2713,8 @@ mpeg2_dxva2_hwaccel_deps="dxva2" mpeg2_dxva2_hwaccel_select="mpeg2video_decoder" mpeg2_mediacodec_hwaccel_deps="mediacodec" mpeg2_mmal_hwaccel_deps="mmal" +mpeg2_nvdec_hwaccel_deps="nvdec" +mpeg2_nvdec_hwaccel_select="mpeg2video_decoder" mpeg2_qsv_hwaccel_deps="libmfx" mpeg2_vaapi_hwaccel_deps="vaapi" mpeg2_vaapi_hwaccel_select="mpeg2video_decoder" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 631567257325b..494c76da76a65 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -854,6 +854,7 @@ OBJS-$(CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_MPEG1_XVMC_HWACCEL) += mpegvideo_xvmc.o OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL) += dxva2_mpeg2.o OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o +OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec_other.o OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index e213f3757c0de..e0adb7195131b 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -96,6 +96,7 @@ static void register_all(void) REGISTER_HWACCEL(MPEG2_D3D11VA2, mpeg2_d3d11va2); REGISTER_HWACCEL(MPEG2_DXVA2, mpeg2_dxva2); REGISTER_HWACCEL(MPEG2_MMAL, mpeg2_mmal); + REGISTER_HWACCEL(MPEG2_NVDEC, mpeg2_nvdec); REGISTER_HWACCEL(MPEG2_QSV, mpeg2_qsv); REGISTER_HWACCEL(MPEG2_VAAPI, mpeg2_vaapi); REGISTER_HWACCEL(MPEG2_VDPAU, mpeg2_vdpau); diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index d5bc5f21b2ade..2b213eebcd016 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -1141,6 +1141,9 @@ static const enum AVPixelFormat mpeg1_hwaccel_pixfmt_list_420[] = { }; static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = { +#if CONFIG_MPEG2_NVDEC_HWACCEL + AV_PIX_FMT_CUDA, +#endif #if CONFIG_MPEG2_XVMC_HWACCEL AV_PIX_FMT_XVMC, #endif diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index 20d7c3db275cf..3d62840e9f35b 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -52,11 +52,12 @@ typedef struct NVDECFramePool { static int map_avcodec_id(enum AVCodecID id) { switch (id) { - case AV_CODEC_ID_H264: return cudaVideoCodec_H264; - case AV_CODEC_ID_HEVC: return cudaVideoCodec_HEVC; - case AV_CODEC_ID_VC1: return cudaVideoCodec_VC1; - case AV_CODEC_ID_VP9: return cudaVideoCodec_VP9; - case AV_CODEC_ID_WMV3: return cudaVideoCodec_VC1; + case AV_CODEC_ID_H264: return cudaVideoCodec_H264; + case AV_CODEC_ID_HEVC: return cudaVideoCodec_HEVC; + case AV_CODEC_ID_MPEG2VIDEO: return cudaVideoCodec_MPEG2; + case AV_CODEC_ID_VC1: return cudaVideoCodec_VC1; + case AV_CODEC_ID_VP9: return cudaVideoCodec_VP9; + case AV_CODEC_ID_WMV3: return cudaVideoCodec_VC1; } return -1; } diff --git a/libavcodec/nvdec_mpeg12.c b/libavcodec/nvdec_mpeg12.c new file mode 100644 index 0000000000000..127e843d85154 --- /dev/null +++ b/libavcodec/nvdec_mpeg12.c @@ -0,0 +1,152 @@ +/* + * MPEG-2 HW decode acceleration through NVDEC + * + * Copyright (c) 2017 Philip Langdale + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "mpegvideo.h" +#include "nvdec.h" +#include "decode.h" + +static int get_ref_idx(AVFrame *frame) +{ + FrameDecodeData *fdd; + NVDECFrame *cf; + + if (!frame || !frame->private_ref) + return -1; + + fdd = (FrameDecodeData*)frame->private_ref->data; + cf = (NVDECFrame*)fdd->hwaccel_priv; + if (!cf) + return -1; + + return cf->idx; +} + +static int nvdec_mpeg12_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + MpegEncContext *s = avctx->priv_data; + + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + CUVIDPICPARAMS *pp = &ctx->pic_params; + CUVIDMPEG2PICPARAMS *ppc = &pp->CodecSpecific.mpeg2; + FrameDecodeData *fdd; + NVDECFrame *cf; + AVFrame *cur_frame = s->current_picture.f; + + int ret, i; + + ret = ff_nvdec_start_frame(avctx, cur_frame); + if (ret < 0) + return ret; + + fdd = (FrameDecodeData*)cur_frame->private_ref->data; + cf = (NVDECFrame*)fdd->hwaccel_priv; + + *pp = (CUVIDPICPARAMS) { + .PicWidthInMbs = (cur_frame->width + 15) / 16, + .FrameHeightInMbs = (cur_frame->height + 15) / 16, + .CurrPicIdx = cf->idx, + + .intra_pic_flag = s->pict_type == AV_PICTURE_TYPE_I, + .ref_pic_flag = s->pict_type == AV_PICTURE_TYPE_I || + s->pict_type == AV_PICTURE_TYPE_P, + + .CodecSpecific.mpeg2 = { + .ForwardRefIdx = get_ref_idx(s->last_picture.f), + .BackwardRefIdx = get_ref_idx(s->next_picture.f), + + .picture_coding_type = s->pict_type, + .full_pel_forward_vector = s->full_pel[0], + .full_pel_backward_vector = s->full_pel[1], + .f_code = { { s->mpeg_f_code[0][0], + s->mpeg_f_code[0][1] }, + { s->mpeg_f_code[1][0], + s->mpeg_f_code[1][1] } }, + .intra_dc_precision = s->intra_dc_precision, + .frame_pred_frame_dct = s->frame_pred_frame_dct, + .concealment_motion_vectors = s->concealment_motion_vectors, + .q_scale_type = s->q_scale_type, + .intra_vlc_format = s->intra_vlc_format, + .alternate_scan = s->alternate_scan, + .top_field_first = s->top_field_first, + } + }; + + for (i = 0; i < 64; ++i) { + ppc->QuantMatrixIntra[i] = s->intra_matrix[i]; + ppc->QuantMatrixInter[i] = s->inter_matrix[i]; + } + + return 0; +} + +static int nvdec_mpeg12_end_frame(AVCodecContext *avctx) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + int ret = ff_nvdec_end_frame(avctx); + ctx->bitstream = NULL; + return ret; +} + +static int nvdec_mpeg12_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + void *tmp; + + tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated, + (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets)); + if (!tmp) + return AVERROR(ENOMEM); + ctx->slice_offsets = tmp; + + if (!ctx->bitstream) + ctx->bitstream = (uint8_t*)buffer; + + ctx->slice_offsets[ctx->nb_slices] = buffer - ctx->bitstream; + ctx->bitstream_len += size; + ctx->nb_slices++; + + return 0; +} + +static int nvdec_mpeg12_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) +{ + // Each frame can at most have one P and one B reference + return ff_nvdec_frame_params(avctx, hw_frames_ctx, 2); +} + +#if CONFIG_MPEG2_NVDEC_HWACCEL +AVHWAccel ff_mpeg2_nvdec_hwaccel = { + .name = "mpeg2_nvdec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .pix_fmt = AV_PIX_FMT_CUDA, + .start_frame = nvdec_mpeg12_start_frame, + .end_frame = nvdec_mpeg12_end_frame, + .decode_slice = nvdec_mpeg12_decode_slice, + .frame_params = nvdec_mpeg12_frame_params, + .init = ff_nvdec_decode_init, + .uninit = ff_nvdec_decode_uninit, + .priv_data_size = sizeof(NVDECContext), +}; +#endif diff --git a/libavcodec/version.h b/libavcodec/version.h index a75c88576836f..5b25a9a8ac25b 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 3 -#define LIBAVCODEC_VERSION_MICRO 102 +#define LIBAVCODEC_VERSION_MICRO 103 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From c3b5ea753017d1acaecdbc4dc09dae16e53a9b91 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 12 Nov 2017 15:23:14 +0100 Subject: [PATCH 0973/2557] lavf/tcp: Fix the type of the optlen argument to getsockopt(). Fixes a warning on aix: libavformat/tcp.c:283:58: warning: passing argument 5 of 'getsockopt' from incompatible pointer type --- libavformat/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index f3f9d4f431b99..fef0729da683b 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -275,7 +275,7 @@ static int tcp_get_window_size(URLContext *h) { TCPContext *s = h->priv_data; int avail; - int avail_len = sizeof(avail); + socklen_t avail_len = sizeof(avail); #if HAVE_WINSOCK2_H /* SO_RCVBUF with winsock only reports the actual TCP window size when From 936a4c04b9fda79d824ab6c95591425b37e4086f Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 18 Nov 2017 14:55:29 -0300 Subject: [PATCH 0974/2557] avformat: remove unnecessary AVStreamParseType enum offset Signed-off-by: James Almer --- libavformat/avformat.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 3c6775d0f656d..322210fae0450 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -785,9 +785,9 @@ enum AVStreamParseType { AVSTREAM_PARSE_HEADERS, /**< Only parse headers, do not repack. */ AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on a packet boundary */ AVSTREAM_PARSE_FULL_ONCE, /**< full parsing and repack of the first frame only, only implemented for H.264 currently */ - AVSTREAM_PARSE_FULL_RAW=MKTAG(0,'R','A','W'), /**< full parsing and repack with timestamp and position generation by parser for raw - this assumes that each packet in the file contains no demuxer level headers and - just codec level data, otherwise position generation would fail */ + AVSTREAM_PARSE_FULL_RAW, /**< full parsing and repack with timestamp and position generation by parser for raw + this assumes that each packet in the file contains no demuxer level headers and + just codec level data, otherwise position generation would fail */ }; typedef struct AVIndexEntry { From ae61bcbdf83a509553445bf0cbce1dba5ac5b208 Mon Sep 17 00:00:00 2001 From: DHE Date: Thu, 16 Nov 2017 20:09:37 -0500 Subject: [PATCH 0975/2557] ffmpeg_filter: use nb_threads=1 on unused filtergraph Signed-off-by: DHE Signed-off-by: Michael Niedermayer --- fftools/ffmpeg_filter.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index aacc185059e65..877fd670e622a 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -340,6 +340,7 @@ int init_complex_filtergraph(FilterGraph *fg) graph = avfilter_graph_alloc(); if (!graph) return AVERROR(ENOMEM); + graph->nb_threads = 1; ret = avfilter_graph_parse2(graph, fg->graph_desc, &inputs, &outputs); if (ret < 0) From 80ef3c83601881ff2b6a90fa5c6e82c83aad768f Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Sat, 18 Nov 2017 10:36:51 +0300 Subject: [PATCH 0976/2557] ffmpeg: Allow "-to" on input files in addition to "-t" For some strange reason "-t" option was only implemented for input files while both "-t" and "-to" were available for use for output files. This made extracting a range from input file inconvenient. This patch enables -to option for input so one can do ffmpeg -ss 1:23:20 -to 1:27:22.3 -i myinput.mkv ... Signed-off-by: Vitaly _Vi Shukela Signed-off-by: Michael Niedermayer --- doc/ffmpeg.texi | 4 ++-- fftools/ffmpeg_opt.c | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 7db80ebf6a857..9a90d7327abb2 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -289,8 +289,8 @@ see @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) -to and -t are mutually exclusive and -t has priority. -@item -to @var{position} (@emph{output}) -Stop writing the output at @var{position}. +@item -to @var{position} (@emph{input/output}) +Stop writing the output or reading the input at @var{position}. @var{position} must be a time duration specification, see @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils}. diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 47d384166c082..f66f672c3c6be 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -976,6 +976,21 @@ static int open_input_file(OptionsContext *o, const char *filename) char * data_codec_name = NULL; int scan_all_pmts_set = 0; + if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) { + o->stop_time = INT64_MAX; + av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n"); + } + + if (o->stop_time != INT64_MAX && o->recording_time == INT64_MAX) { + int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time; + if (o->stop_time <= start_time) { + av_log(NULL, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n"); + exit_program(1); + } else { + o->recording_time = o->stop_time - start_time; + } + } + if (o->format) { if (!(file_iformat = av_find_input_format(o->format))) { av_log(NULL, AV_LOG_FATAL, "Unknown input format: '%s'\n", o->format); @@ -3407,7 +3422,7 @@ const OptionDef options[] = { OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(recording_time) }, "record or transcode \"duration\" seconds of audio/video", "duration" }, - { "to", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(stop_time) }, + { "to", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(stop_time) }, "record or transcode stop time", "time_stop" }, { "fs", HAS_ARG | OPT_INT64 | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(limit_filesize) }, "set the limit file size in bytes", "limit_size" }, From 0ecb1c53c8dc385cfc7453bac26522c1da1cb6ec Mon Sep 17 00:00:00 2001 From: James Cowgill Date: Sat, 18 Nov 2017 15:11:45 +0000 Subject: [PATCH 0977/2557] avformat/dashenc: fix min_seg_duration option size In the DASHContext structure, min_seg_duration is declared as an int, but the AVOption list claimed it was an INT64. Change the option list to use the correct size, which should fix some initialization errors seen on big-endian platforms. Signed-off-by: James Cowgill Signed-off-by: Michael Niedermayer --- libavformat/dashenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index d5554d1df072d..ddad3351fd9aa 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1181,7 +1181,7 @@ static const AVOption options[] = { { "adaptation_sets", "Adaptation sets. Syntax: id=0,streams=0,1,2 id=1,streams=3,4 and so on", OFFSET(adaptation_sets), AV_OPT_TYPE_STRING, { 0 }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E }, { "extra_window_size", "number of segments kept outside of the manifest before removing from disk", OFFSET(extra_window_size), AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX, E }, - { "min_seg_duration", "minimum segment duration (in microseconds)", OFFSET(min_seg_duration), AV_OPT_TYPE_INT64, { .i64 = 5000000 }, 0, INT_MAX, E }, + { "min_seg_duration", "minimum segment duration (in microseconds)", OFFSET(min_seg_duration), AV_OPT_TYPE_INT, { .i64 = 5000000 }, 0, INT_MAX, E }, { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E }, { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E }, From e679ac8d7c7468e68b3b4c54702adc9f8775fb79 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 18 Nov 2017 10:28:27 +0100 Subject: [PATCH 0978/2557] avfilter: add acontrast filter Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/filters.texi | 10 ++ libavfilter/Makefile | 1 + libavfilter/af_acontrast.c | 219 +++++++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- 6 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 libavfilter/af_acontrast.c diff --git a/Changelog b/Changelog index cda59166fc166..e1f8a648b0cb8 100644 --- a/Changelog +++ b/Changelog @@ -16,6 +16,7 @@ version : - NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-2, VC1 and VP9 hwaccel decoding - Intel QSV-accelerated overlay filter - mcompand audio filter +- acontrast audio filter version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index 5d99437871b6c..63ce899784ffa 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -429,6 +429,16 @@ How much to use compressed signal in output. Default is 1. Range is between 0 and 1. @end table +@section acontrast +Simple audio dynamic range commpression/expansion filter. + +The filter accepts the following options: + +@table @option +@item contrast +Set contrast. Default is 33. Allowed range is between 0 and 100. +@end table + @section acopy Copy the input audio source unchanged to the output. This is mainly useful for diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 9acae3ff5b74f..71c6333a52f73 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -31,6 +31,7 @@ OBJS-$(CONFIG_QSVVPP) += qsvvpp.o # audio filters OBJS-$(CONFIG_ABENCH_FILTER) += f_bench.o OBJS-$(CONFIG_ACOMPRESSOR_FILTER) += af_sidechaincompress.o +OBJS-$(CONFIG_ACONTRAST_FILTER) += af_acontrast.o OBJS-$(CONFIG_ACOPY_FILTER) += af_acopy.o OBJS-$(CONFIG_ACROSSFADE_FILTER) += af_afade.o OBJS-$(CONFIG_ACRUSHER_FILTER) += af_acrusher.o diff --git a/libavfilter/af_acontrast.c b/libavfilter/af_acontrast.c new file mode 100644 index 0000000000000..8b45bd5b2b0e0 --- /dev/null +++ b/libavfilter/af_acontrast.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2008 Rob Sykes + * Copyright (c) 2017 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "audio.h" +#include "formats.h" + +typedef struct AudioContrastContext { + const AVClass *class; + float contrast; + void (*filter)(void **dst, const void **src, + int nb_samples, int channels, float contrast); +} AudioContrastContext; + +#define OFFSET(x) offsetof(AudioContrastContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption acontrast_options[] = { + { "contrast", "set contrast", OFFSET(contrast), AV_OPT_TYPE_FLOAT, {.dbl=33}, 0, 100, A }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(acontrast); + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + AVFilterChannelLayouts *layouts = NULL; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE + }; + int ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_all_samplerates(); + return ff_set_common_samplerates(ctx, formats); +} + +static void filter_flt(void **d, const void **s, + int nb_samples, int channels, + float contrast) +{ + const float *src = s[0]; + float *dst = d[0]; + int n, c; + + for (n = 0; n < nb_samples; n++) { + for (c = 0; c < channels; c++) { + float d = src[c] * M_PI_2; + + dst[c] = sinf(d + contrast * sinf(d * 4)); + } + + dst += c; + src += c; + } +} + +static void filter_dbl(void **d, const void **s, + int nb_samples, int channels, + float contrast) +{ + const double *src = s[0]; + double *dst = d[0]; + int n, c; + + for (n = 0; n < nb_samples; n++) { + for (c = 0; c < channels; c++) { + double d = src[c] * M_PI_2; + + dst[c] = sin(d + contrast * sin(d * 4)); + } + + dst += c; + src += c; + } +} + +static void filter_fltp(void **d, const void **s, + int nb_samples, int channels, + float contrast) +{ + int n, c; + + for (c = 0; c < channels; c++) { + const float *src = s[c]; + float *dst = d[c]; + + for (n = 0; n < nb_samples; n++) { + float d = src[n] * M_PI_2; + + dst[n] = sinf(d + contrast * sinf(d * 4)); + } + } +} + +static void filter_dblp(void **d, const void **s, + int nb_samples, int channels, + float contrast) +{ + int n, c; + + for (c = 0; c < channels; c++) { + const double *src = s[c]; + double *dst = d[c]; + + for (n = 0; n < nb_samples; n++) { + double d = src[n] * M_PI_2; + + dst[n] = sin(d + contrast * sin(d * 4)); + } + } +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AudioContrastContext *s = ctx->priv; + + switch (inlink->format) { + case AV_SAMPLE_FMT_FLT: s->filter = filter_flt; break; + case AV_SAMPLE_FMT_DBL: s->filter = filter_dbl; break; + case AV_SAMPLE_FMT_FLTP: s->filter = filter_fltp; break; + case AV_SAMPLE_FMT_DBLP: s->filter = filter_dblp; break; + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AudioContrastContext *s = ctx->priv; + AVFrame *out; + + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_audio_buffer(inlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + + s->filter((void **)out->extended_data, (const void **)in->extended_data, + in->nb_samples, in->channels, s->contrast / 750); + + if (out != in) + av_frame_free(&in); + + return ff_filter_frame(outlink, out); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_acontrast = { + .name = "acontrast", + .description = NULL_IF_CONFIG_SMALL("Simple audio dynamic range compression/expansion filter."), + .query_formats = query_formats, + .priv_size = sizeof(AudioContrastContext), + .priv_class = &acontrast_class, + .inputs = inputs, + .outputs = outputs, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index a838309569cf1..6d92b3ab5a7d7 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -42,6 +42,7 @@ static void register_all(void) { REGISTER_FILTER(ABENCH, abench, af); REGISTER_FILTER(ACOMPRESSOR, acompressor, af); + REGISTER_FILTER(ACONTRAST, acontrast, af); REGISTER_FILTER(ACOPY, acopy, af); REGISTER_FILTER(ACROSSFADE, acrossfade, af); REGISTER_FILTER(ACRUSHER, acrusher, af); diff --git a/libavfilter/version.h b/libavfilter/version.h index 33d9ad7bc7297..d8484e42637c7 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 1 +#define LIBAVFILTER_VERSION_MINOR 2 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ From 0b7cd29d47a396d6afe01e5b4ef8382dc0ab6701 Mon Sep 17 00:00:00 2001 From: James Darnley Date: Sun, 19 Nov 2017 14:54:34 +0100 Subject: [PATCH 0979/2557] configure: add audio_frame_queue dependency for aptx codec --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index 8b7b7e164b359..48761934be542 100755 --- a/configure +++ b/configure @@ -2439,6 +2439,8 @@ amv_encoder_select="aandcttables jpegtables mpegvideoenc" ape_decoder_select="bswapdsp llauddsp" apng_decoder_select="zlib" apng_encoder_select="llvidencdsp zlib" +aptx_decoder_select="audio_frame_queue" +aptx_encoder_select="audio_frame_queue" asv1_decoder_select="blockdsp bswapdsp idctdsp" asv1_encoder_select="bswapdsp fdctdsp pixblockdsp" asv2_decoder_select="blockdsp bswapdsp idctdsp" From 4f4e19914ddca5096bf7639c7c99a9045e436e8b Mon Sep 17 00:00:00 2001 From: Michael Roitzsch Date: Sat, 18 Nov 2017 13:33:08 +0100 Subject: [PATCH 0980/2557] lavfi/af_pan: fix sign handling in channel coefficient parser When a channel formula ends with a subtraction, the next formula will otherwise have its first coefficient negated. --- libavfilter/af_pan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/af_pan.c b/libavfilter/af_pan.c index 23b29419b6350..d8a63a7952254 100644 --- a/libavfilter/af_pan.c +++ b/libavfilter/af_pan.c @@ -166,6 +166,7 @@ static av_cold int init(AVFilterContext *ctx) goto fail; } /* gains */ + sign = 1; while (1) { gain = 1; if (sscanf(arg, "%lf%n *%n", &gain, &len, &len)) From e75fe0ef213074381c09e074f1f9619012f1ffad Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Wed, 15 Nov 2017 17:36:19 +0530 Subject: [PATCH 0981/2557] avformat/subfile: allow to extract till EOF Users can set end offset as 0 to extract till end of file. Tested locally and documented. --- doc/protocols.texi | 6 ++++++ libavformat/subfile.c | 3 +++ 2 files changed, 9 insertions(+) diff --git a/doc/protocols.texi b/doc/protocols.texi index 4d48f8a411566..8661aea147f23 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -1186,6 +1186,7 @@ Accepted options: Start offset of the extracted segment, in bytes. @item end End offset of the extracted segment, in bytes. +If set to 0, extract till end of file. @end table Examples: @@ -1201,6 +1202,11 @@ Play an AVI file directly from a TAR archive: subfile,,start,183241728,end,366490624,,:archive.tar @end example +Play a MPEG-TS file from start offset till end: +@example +subfile,,start,32815239,end,0,,:video.ts +@end example + @section tee Writes the output to multiple protocols. The individual outputs are separated diff --git a/libavformat/subfile.c b/libavformat/subfile.c index 497cf852116fd..b527f2bee17e1 100644 --- a/libavformat/subfile.c +++ b/libavformat/subfile.c @@ -72,6 +72,9 @@ static int subfile_open(URLContext *h, const char *filename, int flags, SubfileContext *c = h->priv_data; int ret; + if (!c->end) + c->end = INT64_MAX; + if (c->end <= c->start) { av_log(h, AV_LOG_ERROR, "end before start\n"); return AVERROR(EINVAL); From 3152058bf1dca318898550efacf0286f4836cae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 14 Sep 2017 08:33:05 +0300 Subject: [PATCH 0982/2557] libavcodec: Don't use dllexport, only dllimport when building DLLs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only purpose of dllexport (which is set while building the library that exports the symbols) is to have the linker automatically export such symbols into a DLL without using a def file - it doesn't affect the generated code. For both MSVC and mingw builds, this isn't essential since we override what symbols to export via an autogenerated def file instead. Update a comment in configure to refer to the right concept. With lld, this avoids warnings about duplicate export directives, when some symbols are requested to be exported both via dllexport attributes and via the autogenerated def file. This also reduces the number of lines of code marginally. Signed-off-by: Martin Storsjö --- configure | 2 +- libavcodec/internal.h | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/configure b/configure index fcffbce7f915f..7f320fee18d63 100755 --- a/configure +++ b/configure @@ -3883,7 +3883,7 @@ case $target_os in mingw32*|mingw64*) target_os=mingw32 if enabled shared; then - # Cannot build both shared and static libs when using dllexport. + # Cannot build both shared and static libs when using dllimport. disable static fi check_ldflags -Wl,--nxcompat diff --git a/libavcodec/internal.h b/libavcodec/internal.h index da1b2fa7d12a2..868e3dfc541ed 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -285,12 +285,8 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame); */ AVCPBProperties *ff_add_cpb_side_data(AVCodecContext *avctx); -#if defined(_WIN32) && CONFIG_SHARED -#ifdef BUILDING_avcodec -# define av_export_avcodec __declspec(dllexport) -#else +#if defined(_WIN32) && CONFIG_SHARED && !defined(BUILDING_avcodec) # define av_export_avcodec __declspec(dllimport) -#endif #else # define av_export_avcodec #endif From 460df96904b714efed17820649bb53e1f941be1a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 19 Nov 2017 21:18:00 +0100 Subject: [PATCH 0983/2557] avfilter: fix indentation Signed-off-by: Paul B Mahol --- libavfilter/af_agate.c | 15 +++++++-------- libavfilter/af_sidechaincompress.c | 15 +++++++-------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/libavfilter/af_agate.c b/libavfilter/af_agate.c index 20905ccb19025..086a2f9cb93a4 100644 --- a/libavfilter/af_agate.c +++ b/libavfilter/af_agate.c @@ -323,14 +323,13 @@ static int activate(AVFilterContext *ctx) } FF_FILTER_FORWARD_STATUS(ctx->inputs[0], ctx->outputs[0]); FF_FILTER_FORWARD_STATUS(ctx->inputs[1], ctx->outputs[0]); - /* TODO reindent */ - if (ff_outlink_frame_wanted(ctx->outputs[0])) { - if (!av_audio_fifo_size(s->fifo[0])) - ff_inlink_request_frame(ctx->inputs[0]); - if (!av_audio_fifo_size(s->fifo[1])) - ff_inlink_request_frame(ctx->inputs[1]); - } - return 0; + if (ff_outlink_frame_wanted(ctx->outputs[0])) { + if (!av_audio_fifo_size(s->fifo[0])) + ff_inlink_request_frame(ctx->inputs[0]); + if (!av_audio_fifo_size(s->fifo[1])) + ff_inlink_request_frame(ctx->inputs[1]); + } + return 0; } static int scquery_formats(AVFilterContext *ctx) diff --git a/libavfilter/af_sidechaincompress.c b/libavfilter/af_sidechaincompress.c index 55bed438446c2..3c6458cd63883 100644 --- a/libavfilter/af_sidechaincompress.c +++ b/libavfilter/af_sidechaincompress.c @@ -241,14 +241,13 @@ static int activate(AVFilterContext *ctx) } FF_FILTER_FORWARD_STATUS(ctx->inputs[0], ctx->outputs[0]); FF_FILTER_FORWARD_STATUS(ctx->inputs[1], ctx->outputs[0]); - /* TODO reindent */ - if (ff_outlink_frame_wanted(ctx->outputs[0])) { - if (!av_audio_fifo_size(s->fifo[0])) - ff_inlink_request_frame(ctx->inputs[0]); - if (!av_audio_fifo_size(s->fifo[1])) - ff_inlink_request_frame(ctx->inputs[1]); - } - return 0; + if (ff_outlink_frame_wanted(ctx->outputs[0])) { + if (!av_audio_fifo_size(s->fifo[0])) + ff_inlink_request_frame(ctx->inputs[0]); + if (!av_audio_fifo_size(s->fifo[1])) + ff_inlink_request_frame(ctx->inputs[1]); + } + return 0; } static int query_formats(AVFilterContext *ctx) From 69cbebbd3d4474825b46b4f8bb7c87f8953ff7e5 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 19 Nov 2017 20:20:55 +0100 Subject: [PATCH 0984/2557] avfilter/af_surround: add some more layouts Signed-off-by: Paul B Mahol --- libavfilter/af_surround.c | 201 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) diff --git a/libavfilter/af_surround.c b/libavfilter/af_surround.c index c7122379d6049..e1cb2b3854b73 100644 --- a/libavfilter/af_surround.c +++ b/libavfilter/af_surround.c @@ -90,6 +90,15 @@ typedef struct AudioSurroundContext { float mag_total, float x, float y, int n); + void (*upmix_5_0)(AVFilterContext *ctx, + float c_re, float c_im, + float mag_totall, float mag_totalr, + float fl_phase, float fr_phase, + float bl_phase, float br_phase, + float sl_phase, float sr_phase, + float xl, float yl, + float xr, float yr, + int n); void (*upmix_5_1)(AVFilterContext *ctx, float c_re, float c_im, float lfe_re, float lfe_im, @@ -764,6 +773,66 @@ static void upmix_7_1(AVFilterContext *ctx, dstrs[2 * n + 1] = rs_mag * sinf(r_phase); } +static void upmix_7_1_5_0_side(AVFilterContext *ctx, + float c_re, float c_im, + float mag_totall, float mag_totalr, + float fl_phase, float fr_phase, + float bl_phase, float br_phase, + float sl_phase, float sr_phase, + float xl, float yl, + float xr, float yr, + int n) +{ + float fl_mag, fr_mag, ls_mag, rs_mag, lb_mag, rb_mag; + float *dstc, *dstl, *dstr, *dstls, *dstrs, *dstlb, *dstrb, *dstlfe; + float lfe_mag, c_phase, mag_total = (mag_totall + mag_totalr) * 0.5; + AudioSurroundContext *s = ctx->priv; + + dstl = (float *)s->output->extended_data[0]; + dstr = (float *)s->output->extended_data[1]; + dstc = (float *)s->output->extended_data[2]; + dstlfe = (float *)s->output->extended_data[3]; + dstlb = (float *)s->output->extended_data[4]; + dstrb = (float *)s->output->extended_data[5]; + dstls = (float *)s->output->extended_data[6]; + dstrs = (float *)s->output->extended_data[7]; + + c_phase = atan2f(c_im, c_re); + + get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total); + + fl_mag = sqrtf(.5f * (xl + 1.f)) * ((yl + 1.f) * .5f) * mag_totall; + fr_mag = sqrtf(.5f * (xr + 1.f)) * ((yr + 1.f) * .5f) * mag_totalr; + lb_mag = sqrtf(.5f * (-xl + 1.f)) * ((yl + 1.f) * .5f) * mag_totall; + rb_mag = sqrtf(.5f * (-xr + 1.f)) * ((yr + 1.f) * .5f) * mag_totalr; + ls_mag = sqrtf(1.f - fabsf(xl)) * ((yl + 1.f) * .5f) * mag_totall; + rs_mag = sqrtf(1.f - fabsf(xr)) * ((yr + 1.f) * .5f) * mag_totalr; + + dstl[2 * n ] = fl_mag * cosf(fl_phase); + dstl[2 * n + 1] = fl_mag * sinf(fl_phase); + + dstr[2 * n ] = fr_mag * cosf(fr_phase); + dstr[2 * n + 1] = fr_mag * sinf(fr_phase); + + dstc[2 * n ] = c_re; + dstc[2 * n + 1] = c_im; + + dstlfe[2 * n ] = lfe_mag * cosf(c_phase); + dstlfe[2 * n + 1] = lfe_mag * sinf(c_phase); + + dstlb[2 * n ] = lb_mag * cosf(bl_phase); + dstlb[2 * n + 1] = lb_mag * sinf(bl_phase); + + dstrb[2 * n ] = rb_mag * cosf(br_phase); + dstrb[2 * n + 1] = rb_mag * sinf(br_phase); + + dstls[2 * n ] = ls_mag * cosf(sl_phase); + dstls[2 * n + 1] = ls_mag * sinf(sl_phase); + + dstrs[2 * n ] = rs_mag * cosf(sr_phase); + dstrs[2 * n + 1] = rs_mag * sinf(sr_phase); +} + static void upmix_7_1_5_1(AVFilterContext *ctx, float c_re, float c_im, float lfe_re, float lfe_im, @@ -918,6 +987,118 @@ static void filter_2_1(AVFilterContext *ctx) } } +static void filter_5_0_side(AVFilterContext *ctx) +{ + AudioSurroundContext *s = ctx->priv; + float *srcl, *srcr, *srcc, *srcsl, *srcsr; + int n; + + srcl = (float *)s->input->extended_data[0]; + srcr = (float *)s->input->extended_data[1]; + srcc = (float *)s->input->extended_data[2]; + srcsl = (float *)s->input->extended_data[3]; + srcsr = (float *)s->input->extended_data[4]; + + for (n = 0; n < s->buf_size; n++) { + float fl_re = srcl[2 * n], fr_re = srcr[2 * n]; + float fl_im = srcl[2 * n + 1], fr_im = srcr[2 * n + 1]; + float c_re = srcc[2 * n], c_im = srcc[2 * n + 1]; + float sl_re = srcsl[2 * n], sl_im = srcsl[2 * n + 1]; + float sr_re = srcsr[2 * n], sr_im = srcsr[2 * n + 1]; + float fl_mag = hypotf(fl_re, fl_im); + float fr_mag = hypotf(fr_re, fr_im); + float fl_phase = atan2f(fl_im, fl_re); + float fr_phase = atan2f(fr_im, fr_re); + float sl_mag = hypotf(sl_re, sl_im); + float sr_mag = hypotf(sr_re, sr_im); + float sl_phase = atan2f(sl_im, sl_re); + float sr_phase = atan2f(sr_im, sr_re); + float phase_difl = fabsf(fl_phase - sl_phase); + float phase_difr = fabsf(fr_phase - sr_phase); + float mag_difl = (fl_mag - sl_mag) / (fl_mag + sl_mag); + float mag_difr = (fr_mag - sr_mag) / (fr_mag + sr_mag); + float mag_totall = hypotf(fl_mag, sl_mag); + float mag_totalr = hypotf(fr_mag, sr_mag); + float bl_phase = atan2f(fl_im + sl_im, fl_re + sl_re); + float br_phase = atan2f(fr_im + sr_im, fr_re + sr_re); + float xl, yl; + float xr, yr; + + if (phase_difl > M_PI) + phase_difl = 2 * M_PI - phase_difl; + + if (phase_difr > M_PI) + phase_difr = 2 * M_PI - phase_difr; + + stereo_position(mag_difl, phase_difl, &xl, &yl); + stereo_position(mag_difr, phase_difr, &xr, &yr); + + s->upmix_5_0(ctx, c_re, c_im, + mag_totall, mag_totalr, + fl_phase, fr_phase, + bl_phase, br_phase, + sl_phase, sr_phase, + xl, yl, xr, yr, n); + } +} + +static void filter_5_1_side(AVFilterContext *ctx) +{ + AudioSurroundContext *s = ctx->priv; + float *srcl, *srcr, *srcc, *srclfe, *srcsl, *srcsr; + int n; + + srcl = (float *)s->input->extended_data[0]; + srcr = (float *)s->input->extended_data[1]; + srcc = (float *)s->input->extended_data[2]; + srclfe = (float *)s->input->extended_data[3]; + srcsl = (float *)s->input->extended_data[4]; + srcsr = (float *)s->input->extended_data[5]; + + for (n = 0; n < s->buf_size; n++) { + float fl_re = srcl[2 * n], fr_re = srcr[2 * n]; + float fl_im = srcl[2 * n + 1], fr_im = srcr[2 * n + 1]; + float c_re = srcc[2 * n], c_im = srcc[2 * n + 1]; + float lfe_re = srclfe[2 * n], lfe_im = srclfe[2 * n + 1]; + float sl_re = srcsl[2 * n], sl_im = srcsl[2 * n + 1]; + float sr_re = srcsr[2 * n], sr_im = srcsr[2 * n + 1]; + float fl_mag = hypotf(fl_re, fl_im); + float fr_mag = hypotf(fr_re, fr_im); + float fl_phase = atan2f(fl_im, fl_re); + float fr_phase = atan2f(fr_im, fr_re); + float sl_mag = hypotf(sl_re, sl_im); + float sr_mag = hypotf(sr_re, sr_im); + float sl_phase = atan2f(sl_im, sl_re); + float sr_phase = atan2f(sr_im, sr_re); + float phase_difl = fabsf(fl_phase - sl_phase); + float phase_difr = fabsf(fr_phase - sr_phase); + float mag_difl = (fl_mag - sl_mag) / (fl_mag + sl_mag); + float mag_difr = (fr_mag - sr_mag) / (fr_mag + sr_mag); + float mag_totall = hypotf(fl_mag, sl_mag); + float mag_totalr = hypotf(fr_mag, sr_mag); + float bl_phase = atan2f(fl_im + sl_im, fl_re + sl_re); + float br_phase = atan2f(fr_im + sr_im, fr_re + sr_re); + float xl, yl; + float xr, yr; + + if (phase_difl > M_PI) + phase_difl = 2 * M_PI - phase_difl; + + if (phase_difr > M_PI) + phase_difr = 2 * M_PI - phase_difr; + + stereo_position(mag_difl, phase_difl, &xl, &yl); + stereo_position(mag_difr, phase_difr, &xr, &yr); + + s->upmix_5_1(ctx, c_re, c_im, lfe_re, lfe_im, + mag_totall, mag_totalr, + fl_phase, fr_phase, + bl_phase, br_phase, + sl_phase, sr_phase, + xl, yl, xr, yr, n); + } +} + static void filter_5_1_back(AVFilterContext *ctx) { AudioSurroundContext *s = ctx->priv; @@ -1063,6 +1244,26 @@ static int init(AVFilterContext *ctx) goto fail; } break; + case AV_CH_LAYOUT_5POINT0: + s->filter = filter_5_0_side; + switch (s->out_channel_layout) { + case AV_CH_LAYOUT_7POINT1: + s->upmix_5_0 = upmix_7_1_5_0_side; + break; + default: + goto fail; + } + break; + case AV_CH_LAYOUT_5POINT1: + s->filter = filter_5_1_side; + switch (s->out_channel_layout) { + case AV_CH_LAYOUT_7POINT1: + s->upmix_5_1 = upmix_7_1_5_1; + break; + default: + goto fail; + } + break; case AV_CH_LAYOUT_5POINT1_BACK: s->filter = filter_5_1_back; switch (s->out_channel_layout) { From c6f7eb86639f7efffa777c5732fa41d89fdd2ff9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 19 Nov 2017 15:23:02 -0300 Subject: [PATCH 0985/2557] configure: fix module dependencies on zlib select should not be used with external libraries. It's mean to soft enable internal modules/features. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- configure | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/configure b/configure index 48761934be542..efd7ffecdec6f 100755 --- a/configure +++ b/configure @@ -2437,8 +2437,9 @@ amrwb_decoder_select="lsp" amv_decoder_select="sp5x_decoder exif" amv_encoder_select="aandcttables jpegtables mpegvideoenc" ape_decoder_select="bswapdsp llauddsp" -apng_decoder_select="zlib" -apng_encoder_select="llvidencdsp zlib" +apng_decoder_deps="zlib" +apng_encoder_deps="zlib" +apng_encoder_select="llvidencdsp" aptx_decoder_select="audio_frame_queue" aptx_encoder_select="audio_frame_queue" asv1_decoder_select="blockdsp bswapdsp idctdsp" @@ -2467,14 +2468,14 @@ dnxhd_encoder_select="aandcttables blockdsp fdctdsp idctdsp mpegvideoenc pixbloc dolby_e_decoder_select="mdct" dvvideo_decoder_select="dvprofile idctdsp" dvvideo_encoder_select="dvprofile fdctdsp me_cmp pixblockdsp" -dxa_decoder_select="zlib" +dxa_decoder_deps="zlib" dxv_decoder_select="lzf texturedsp" eac3_decoder_select="ac3_decoder" eac3_encoder_select="ac3_encoder" eamad_decoder_select="aandcttables blockdsp bswapdsp idctdsp mpegvideo" eatgq_decoder_select="aandcttables" eatqi_decoder_select="aandcttables blockdsp bswapdsp idctdsp" -exr_decoder_select="zlib" +exr_decoder_deps="zlib" ffv1_decoder_select="rangecoder" ffv1_encoder_select="rangecoder" ffvhuff_decoder_select="huffyuv_decoder" @@ -2482,15 +2483,16 @@ ffvhuff_encoder_select="huffyuv_encoder" fic_decoder_select="golomb" flac_decoder_select="flacdsp" flac_encoder_select="bswapdsp flacdsp lpc" -flashsv2_decoder_select="zlib" -flashsv2_encoder_select="zlib" -flashsv_decoder_select="zlib" -flashsv_encoder_select="zlib" +flashsv2_decoder_deps="zlib" +flashsv2_encoder_deps="zlib" +flashsv_decoder_deps="zlib" +flashsv_encoder_deps="zlib" flv_decoder_select="h263_decoder" flv_encoder_select="h263_encoder" fourxm_decoder_select="blockdsp bswapdsp" fraps_decoder_select="bswapdsp huffman" -g2m_decoder_select="blockdsp idctdsp jpegtables zlib" +g2m_decoder_deps="zlib" +g2m_decoder_select="blockdsp idctdsp jpegtables" g729_decoder_select="audiodsp" h261_decoder_select="mpegvideo" h261_encoder_select="aandcttables mpegvideoenc" @@ -2548,7 +2550,7 @@ mpeg2video_encoder_select="aandcttables mpegvideoenc h263dsp" mpeg4_decoder_select="h263_decoder mpeg4video_parser" mpeg4_encoder_select="h263_encoder" msa1_decoder_select="mss34dsp" -mscc_decoder_select="zlib" +mscc_decoder_deps="zlib" msmpeg4v1_decoder_select="h263_decoder" msmpeg4v2_decoder_select="h263_decoder" msmpeg4v2_encoder_select="h263_encoder" @@ -2564,8 +2566,9 @@ on2avc_decoder_select="mdct" opus_decoder_deps="swresample" opus_decoder_select="mdct15" opus_encoder_select="audio_frame_queue mdct15" -png_decoder_select="zlib" -png_encoder_select="llvidencdsp zlib" +png_decoder_deps="zlib" +png_encoder_deps="zlib" +png_encoder_select="llvidencdsp" prores_decoder_select="blockdsp idctdsp" prores_encoder_select="fdctdsp" qcelp_decoder_select="lsp" @@ -2574,7 +2577,7 @@ ra_144_decoder_select="audiodsp" ra_144_encoder_select="audio_frame_queue lpc audiodsp" ralf_decoder_select="golomb" rawvideo_decoder_select="bswapdsp" -rscc_decoder_select="zlib" +rscc_decoder_deps="zlib" rtjpeg_decoder_select="me_cmp" rv10_decoder_select="h263_decoder" rv10_encoder_select="h263_encoder" @@ -2582,7 +2585,7 @@ rv20_decoder_select="h263_decoder" rv20_encoder_select="h263_encoder" rv30_decoder_select="golomb h264pred h264qpel mpegvideo rv34dsp" rv40_decoder_select="golomb h264pred h264qpel mpegvideo rv34dsp" -screenpresso_decoder_select="zlib" +screenpresso_decoder_deps="zlib" shorten_decoder_select="bswapdsp" sipr_decoder_select="lsp" snow_decoder_select="dwt h264qpel hpeldsp me_cmp rangecoder videodsp" @@ -2591,13 +2594,14 @@ sonic_decoder_select="golomb rangecoder" sonic_encoder_select="golomb rangecoder" sonic_ls_encoder_select="golomb rangecoder" sp5x_decoder_select="mjpeg_decoder" -srgc_decoder_select="zlib" +srgc_decoder_deps="zlib" svq1_decoder_select="hpeldsp" svq1_encoder_select="aandcttables hpeldsp me_cmp mpegvideoenc" svq3_decoder_select="golomb h264dsp h264parse h264pred hpeldsp tpeldsp videodsp" svq3_decoder_suggest="zlib" tak_decoder_select="audiodsp" -tdsc_decoder_select="zlib mjpeg_decoder" +tdsc_decoder_deps="zlib" +tdsc_decoder_select="mjpeg_decoder" theora_decoder_select="vp3_decoder" thp_decoder_select="mjpeg_decoder" tiff_decoder_suggest="zlib lzma" @@ -2606,7 +2610,7 @@ truehd_decoder_select="mlp_parser" truehd_encoder_select="lpc" truemotion2_decoder_select="bswapdsp" truespeech_decoder_select="bswapdsp" -tscc_decoder_select="zlib" +tscc_decoder_deps="zlib" twinvq_decoder_select="mdct lsp sinewin" txd_decoder_select="texturedsp" utvideo_decoder_select="bswapdsp llviddsp" @@ -2640,11 +2644,11 @@ wmv3_decoder_select="vc1_decoder" wmv3image_decoder_select="wmv3_decoder" xma1_decoder_select="wmapro_decoder" xma2_decoder_select="wmapro_decoder" -zerocodec_decoder_select="zlib" -zlib_decoder_select="zlib" -zlib_encoder_select="zlib" -zmbv_decoder_select="zlib" -zmbv_encoder_select="zlib" +zerocodec_decoder_deps="zlib" +zlib_decoder_deps="zlib" +zlib_encoder_deps="zlib" +zmbv_decoder_deps="zlib" +zmbv_encoder_deps="zlib" # hardware accelerators crystalhd_deps="libcrystalhd_libcrystalhd_if_h" From 3c113421ed36ab9d35a47c8ceb0993cc7c2a130e Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Mon, 20 Nov 2017 01:09:08 +0100 Subject: [PATCH 0986/2557] doc/codecs.texi: Remove documentation of removed codec flags. The flags were removed in b79a7da3 --- doc/codecs.texi | 8 -------- 1 file changed, 8 deletions(-) diff --git a/doc/codecs.texi b/doc/codecs.texi index 6f0aad21693a8..7e20374334093 100644 --- a/doc/codecs.texi +++ b/doc/codecs.texi @@ -44,12 +44,6 @@ Use 1/4 pel motion compensation. Use loop filter. @item qscale Use fixed qscale. -@item gmc -Use gmc. -@item mv0 -Always try a mb with mv=<0,0>. -@item input_preserved - @item pass1 Use internal 2pass ratecontrol in first pass mode. @item pass2 @@ -62,8 +56,6 @@ Do not draw edges. Set error[?] variables during encoding. @item truncated -@item naq -Normalize adaptive quantization. @item ildct Use interlaced DCT. @item low_delay From 54486e3f09dc6ddfbbb211e59c74733d7d84edea Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 19 Nov 2017 21:03:09 -0300 Subject: [PATCH 0987/2557] avcodec: remove unnecessary AVPacketSideDataType enum offset Signed-off-by: James Almer --- libavcodec/avcodec.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 442b558d4bb15..4cd72b59612f1 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1238,7 +1238,7 @@ enum AVPacketSideDataType { * u8 reason for end skip (0=padding silence, 1=convergence) * @endcode */ - AV_PKT_DATA_SKIP_SAMPLES=70, + AV_PKT_DATA_SKIP_SAMPLES, /** * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that @@ -1327,7 +1327,7 @@ enum AVPacketSideDataType { AV_PKT_DATA_A53_CC, /** - * The number of side data elements (in fact a bit more than it). + * The number of side data types. * This is not part of the public API/ABI in the sense that it may * change when new side data types are added. * This must stay the last enum value. From 77b6e3ee2787a82f27bee84130075b9e56d10bb7 Mon Sep 17 00:00:00 2001 From: pkviet Date: Sat, 18 Nov 2017 22:19:46 +0100 Subject: [PATCH 0988/2557] ffmpeg: add ui64 type to SpecifierOpt Adds ui64 (uint64_t) as a possible type for SpecifierOpt. This enables use of uint64_t options with SpecifierOpt such as channel_layout when expressed as a 64 bit channel mask. Signed-off-by: pkviet Signed-off-by: Michael Niedermayer --- fftools/cmdutils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 2997ee37b5afe..fa2b2551b2071 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -155,6 +155,7 @@ typedef struct SpecifierOpt { uint8_t *str; int i; int64_t i64; + uint64_t ui64; float f; double dbl; } u; From 1e5f9234166408daf536407117499d3affa34234 Mon Sep 17 00:00:00 2001 From: Dave Rice Date: Sat, 18 Nov 2017 21:19:17 -0500 Subject: [PATCH 0989/2557] avformat/movenc: correct ImageDescription for uncompressed ycbcr Per https://developer.apple.com/library/content/technotes/tn2162/_index.html Signed-off-by: Michael Niedermayer --- libavformat/movenc.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 01ae467fa1700..152fdb46c258c 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1832,6 +1832,13 @@ static int mov_write_video_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *tr char compressor_name[32] = { 0 }; int avid = 0; + int uncompressed_ycbcr = ((track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_UYVY422) + || (track->par->codec_id == AV_CODEC_ID_RAWVIDEO && track->par->format == AV_PIX_FMT_YUYV422) + || track->par->codec_id == AV_CODEC_ID_V308 + || track->par->codec_id == AV_CODEC_ID_V408 + || track->par->codec_id == AV_CODEC_ID_V410 + || track->par->codec_id == AV_CODEC_ID_V210); + avio_wb32(pb, 0); /* size */ if (mov->encryption_scheme != MOV_ENC_NONE) { ffio_wfourcc(pb, "encv"); @@ -1842,11 +1849,15 @@ static int mov_write_video_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *tr avio_wb16(pb, 0); /* Reserved */ avio_wb16(pb, 1); /* Data-reference index */ - avio_wb16(pb, 0); /* Codec stream version */ + if (uncompressed_ycbcr) { + avio_wb16(pb, 2); /* Codec stream version */ + } else { + avio_wb16(pb, 0); /* Codec stream version */ + } avio_wb16(pb, 0); /* Codec stream revision (=0) */ if (track->mode == MODE_MOV) { ffio_wfourcc(pb, "FFMP"); /* Vendor */ - if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO) { + if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO || uncompressed_ycbcr) { avio_wb32(pb, 0); /* Temporal Quality */ avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/ } else { @@ -1870,7 +1881,10 @@ static int mov_write_video_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *tr avio_w8(pb, strlen(compressor_name)); avio_write(pb, compressor_name, 31); - if (track->mode == MODE_MOV && track->par->bits_per_coded_sample) + if (track->mode == MODE_MOV && + (track->par->codec_id == AV_CODEC_ID_V410 || track->par->codec_id == AV_CODEC_ID_V210)) + avio_wb16(pb, 0x18); + else if (track->mode == MODE_MOV && track->par->bits_per_coded_sample) avio_wb16(pb, track->par->bits_per_coded_sample | (track->par->format == AV_PIX_FMT_GRAY8 ? 0x20 : 0)); else From 8f4702a93f87f9f76563e80f1ae2141a40029d9d Mon Sep 17 00:00:00 2001 From: Dave Rice Date: Sat, 18 Nov 2017 21:19:23 -0500 Subject: [PATCH 0990/2557] avformat/movenc: write clap atom for uncompressed yuv in mov fixes 6145 Signed-off-by: Michael Niedermayer --- libavformat/movenc.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 152fdb46c258c..0d924ad75848a 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1686,6 +1686,21 @@ static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMa return update_size(pb, sv3d_pos); } +static int mov_write_clap_tag(AVIOContext *pb, MOVTrack *track) +{ + avio_wb32(pb, 40); + ffio_wfourcc(pb, "clap"); + avio_wb32(pb, track->par->width); /* apertureWidth_N */ + avio_wb32(pb, 1); /* apertureWidth_D (= 1) */ + avio_wb32(pb, track->height); /* apertureHeight_N */ + avio_wb32(pb, 1); /* apertureHeight_D (= 1) */ + avio_wb32(pb, 0); /* horizOff_N (= 0) */ + avio_wb32(pb, 1); /* horizOff_D (= 1) */ + avio_wb32(pb, 0); /* vertOff_N (= 0) */ + avio_wb32(pb, 1); /* vertOff_D (= 1) */ + return 40; +} + static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track) { AVRational sar; @@ -1984,6 +1999,10 @@ static int mov_write_video_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *tr mov_write_pasp_tag(pb, track); } + if (uncompressed_ycbcr){ + mov_write_clap_tag(pb, track); + } + if (mov->encryption_scheme != MOV_ENC_NONE) { ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid); } From 92a32d0747b089d46ae9bfea9ff79c74fdc4416f Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Mon, 20 Nov 2017 10:02:11 +0800 Subject: [PATCH 0991/2557] avformat/hlsenc: creation of hls variant streams in a single hlsenc instance Reviewed-by: Steven Liu --- doc/muxers.texi | 31 ++ libavformat/hlsenc.c | 927 ++++++++++++++++++++++++++++-------------- libavformat/version.h | 2 +- 3 files changed, 653 insertions(+), 307 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 616568ebea6a5..7fa2a2381ddf1 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -797,6 +797,37 @@ files. @item http_user_agent Override User-Agent field in HTTP header. Applicable only for HTTP output. +@item var_stream_map +Map string which specifies how to group the audio, video and subtitle streams +into different variant streams. The variant stream groups are separated +by space. +Expected string format is like this "a:0,v:0 a:1,v:1 ....". Here a:, v:, s: are +the keys to specify audio, video and subtitle streams respectively. +Allowed values are 0 to 9 (limited just based on practical usage). + +@example +ffmpeg -re -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k -b:a:1 32k \ + -map 0:v -map 0:a -map 0:v -map 0:a -f hls -var_stream_map "v:0,a:0 v:1,a:1" \ + http://example.com/live/out.m3u8 +@end example +This example creates two hls variant streams. The first variant stream will +contain video stream of bitrate 1000k and audio stream of bitrate 64k and the +second variant stream will contain video stream of bitrate 256k and audio +stream of bitrate 32k. Here, two media playlist with file names out_1.m3u8 and +out_2.m3u8 will be created. +@example +ffmpeg -re -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k \ + -map 0:v -map 0:a -map 0:v -f hls -var_stream_map "v:0 a:0 v:1" \ + http://example.com/live/out.m3u8 +@end example +This example creates three hls variant streams. The first variant stream will +be a video only stream with video bitrate 1000k, the second variant stream will +be an audio only stream with bitrate 64k and the third variant stream will be a +video only stream with bitrate 256k. Here, three media playlist with file names +out_1.m3u8, out_2.m3u8 and out_3.m3u8 will be created. + +By default, a single hls variant containing all the encoded streams is created. + @end table @anchor{ico} diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index e0cef8b879585..1515b3f359ea6 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1,6 +1,7 @@ /* * Apple HTTP Live Streaming segmenter * Copyright (c) 2012, Luca Barbato + * Copyright (c) 2017 Akamai Technologies, Inc. * * This file is part of FFmpeg. * @@ -56,6 +57,7 @@ typedef enum { #define KEYSIZE 16 #define LINE_BUFFER_SIZE 1024 #define HLS_MICROSECOND_UNIT 1000000 +#define POSTFIX_PATTERN "_%d" typedef struct HLSSegment { char filename[1024]; @@ -100,12 +102,9 @@ typedef enum { PLAYLIST_TYPE_NB, } PlaylistType; -typedef struct HLSContext { - const AVClass *class; // Class for private options. +typedef struct VariantStream { unsigned number; int64_t sequence; - int64_t start_sequence; - uint32_t start_sequence_source_type; // enum StartSequenceSourceType AVOutputFormat *oformat; AVOutputFormat *vtt_oformat; AVIOContext *out; @@ -115,23 +114,6 @@ typedef struct HLSContext { AVFormatContext *avf; AVFormatContext *vtt_avf; - float time; // Set by a private option. - float init_time; // Set by a private option. - int max_nb_segments; // Set by a private option. -#if FF_API_HLS_WRAP - int wrap; // Set by a private option. -#endif - uint32_t flags; // enum HLSFlags - uint32_t pl_type; // enum PlaylistType - char *segment_filename; - char *fmp4_init_filename; - int segment_type; - int fmp4_init_mode; - - int use_localtime; ///< flag to expand filename with localtime - int use_localtime_mkdir;///< flag to mkdir dirname in timebased filename - int allowcache; - int64_t recording_time; int has_video; int has_subtitle; int new_start; @@ -141,7 +123,6 @@ typedef struct HLSContext { double duration; // last segment duration computed so far, in seconds int64_t start_pos; // last segment starting position int64_t size; // last segment size - int64_t max_seg_size; // every segment file max size int nb_entries; int discontinuity_set; int discontinuity; @@ -151,9 +132,45 @@ typedef struct HLSContext { HLSSegment *old_segments; char *basename; - char *base_output_dirname; char *vtt_basename; char *vtt_m3u8_name; + char *m3u8_name; + + double initial_prog_date_time; + char current_segment_final_filename_fmt[1024]; // when renaming segments + + char *fmp4_init_filename; + char *base_output_dirname; + int fmp4_init_mode; + + AVStream **streams; + unsigned int nb_streams; + char *baseurl; +} VariantStream; + +typedef struct HLSContext { + const AVClass *class; // Class for private options. + int64_t start_sequence; + uint32_t start_sequence_source_type; // enum StartSequenceSourceType + + float time; // Set by a private option. + float init_time; // Set by a private option. + int max_nb_segments; // Set by a private option. +#if FF_API_HLS_WRAP + int wrap; // Set by a private option. +#endif + uint32_t flags; // enum HLSFlags + uint32_t pl_type; // enum PlaylistType + char *segment_filename; + char *fmp4_init_filename; + int segment_type; + + int use_localtime; ///< flag to expand filename with localtime + int use_localtime_mkdir;///< flag to mkdir dirname in timebased filename + int allowcache; + int64_t recording_time; + int64_t max_seg_size; // every segment file max size + char *baseurl; char *format_options_str; char *vtt_format_options_str; @@ -165,6 +182,7 @@ typedef struct HLSContext { char *key_url; char *iv; char *key_basename; + int encrypt_started; char *key_info_file; char key_file[LINE_BUFFER_SIZE + 1]; @@ -174,10 +192,11 @@ typedef struct HLSContext { AVDictionary *vtt_format_options; char *method; - - double initial_prog_date_time; - char current_segment_final_filename_fmt[1024]; // when renaming segments char *user_agent; + + VariantStream *var_streams; + unsigned int nb_varstreams; + char *var_stream_map; /* user specified variant stream map string */ } HLSContext; static int get_int_from_double(double val) @@ -296,7 +315,8 @@ static void write_styp(AVIOContext *pb) ffio_wfourcc(pb, "msix"); } -static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls) { +static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, + VariantStream *vs) { HLSSegment *segment, *previous_segment = NULL; float playlist_duration = 0.0f; @@ -307,13 +327,13 @@ static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls) { AVIOContext *out = NULL; const char *proto = NULL; - segment = hls->segments; + segment = vs->segments; while (segment) { playlist_duration += segment->duration; segment = segment->next; } - segment = hls->old_segments; + segment = vs->old_segments; while (segment) { playlist_duration -= segment->duration; previous_segment = segment; @@ -328,7 +348,7 @@ static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls) { if (hls->segment_filename) { dirname = av_strdup(hls->segment_filename); } else { - dirname = av_strdup(hls->avf->filename); + dirname = av_strdup(vs->avf->filename); } if (!dirname) { ret = AVERROR(ENOMEM); @@ -358,9 +378,9 @@ static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls) { proto = avio_find_protocol_name(s->filename); if (hls->method || (proto && !av_strcasecmp(proto, "http"))) { av_dict_set(&options, "method", "DELETE", 0); - if ((ret = hls->avf->io_open(hls->avf, &out, path, AVIO_FLAG_WRITE, &options)) < 0) + if ((ret = vs->avf->io_open(vs->avf, &out, path, AVIO_FLAG_WRITE, &options)) < 0) goto fail; - ff_format_io_close(hls->avf, &out); + ff_format_io_close(vs->avf, &out); } else if (unlink(path) < 0) { av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n", path, strerror(errno)); @@ -379,11 +399,11 @@ static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls) { if (hls->method || (proto && !av_strcasecmp(proto, "http"))) { av_dict_set(&options, "method", "DELETE", 0); - if ((ret = hls->avf->io_open(hls->avf, &out, sub_path, AVIO_FLAG_WRITE, &options)) < 0) { + if ((ret = vs->avf->io_open(vs->avf, &out, sub_path, AVIO_FLAG_WRITE, &options)) < 0) { av_free(sub_path); goto fail; } - ff_format_io_close(hls->avf, &out); + ff_format_io_close(vs->avf, &out); } else if (unlink(sub_path) < 0) { av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n", sub_path, strerror(errno)); @@ -417,7 +437,7 @@ static int randomize(uint8_t *buf, int len) return AVERROR(EINVAL); } -static int do_encrypt(AVFormatContext *s) +static int do_encrypt(AVFormatContext *s, VariantStream *vs) { HLSContext *hls = s->priv_data; int ret; @@ -425,7 +445,7 @@ static int do_encrypt(AVFormatContext *s) AVIOContext *pb; uint8_t key[KEYSIZE]; - len = strlen(hls->basename) + 4 + 1; + len = strlen(s->filename) + 4 + 1; hls->key_basename = av_mallocz(len); if (!hls->key_basename) return AVERROR(ENOMEM); @@ -446,7 +466,7 @@ static int do_encrypt(AVFormatContext *s) char buf[33]; if (!hls->iv) { - AV_WB64(iv + 8, hls->sequence); + AV_WB64(iv + 8, vs->sequence); } else { memcpy(iv, hls->iv, sizeof(iv)); } @@ -546,7 +566,7 @@ static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) return len; } -static int hls_mux_init(AVFormatContext *s) +static int hls_mux_init(AVFormatContext *s, VariantStream *vs) { AVDictionary *options = NULL; HLSContext *hls = s->priv_data; @@ -555,13 +575,13 @@ static int hls_mux_init(AVFormatContext *s) int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); int i, ret; - ret = avformat_alloc_output_context2(&hls->avf, hls->oformat, NULL, NULL); + ret = avformat_alloc_output_context2(&vs->avf, vs->oformat, NULL, NULL); if (ret < 0) return ret; - oc = hls->avf; + oc = vs->avf; oc->filename[0] = '\0'; - oc->oformat = hls->oformat; + oc->oformat = vs->oformat; oc->interrupt_callback = s->interrupt_callback; oc->max_delay = s->max_delay; oc->opaque = s->opaque; @@ -569,57 +589,59 @@ static int hls_mux_init(AVFormatContext *s) oc->io_close = s->io_close; av_dict_copy(&oc->metadata, s->metadata, 0); - if(hls->vtt_oformat) { - ret = avformat_alloc_output_context2(&hls->vtt_avf, hls->vtt_oformat, NULL, NULL); + if(vs->vtt_oformat) { + ret = avformat_alloc_output_context2(&vs->vtt_avf, vs->vtt_oformat, NULL, NULL); if (ret < 0) return ret; - vtt_oc = hls->vtt_avf; - vtt_oc->oformat = hls->vtt_oformat; + vtt_oc = vs->vtt_avf; + vtt_oc->oformat = vs->vtt_oformat; av_dict_copy(&vtt_oc->metadata, s->metadata, 0); } - for (i = 0; i < s->nb_streams; i++) { + for (i = 0; i < vs->nb_streams; i++) { AVStream *st; AVFormatContext *loc; - if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) + if (vs->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) loc = vtt_oc; else loc = oc; if (!(st = avformat_new_stream(loc, NULL))) return AVERROR(ENOMEM); - avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar); + avcodec_parameters_copy(st->codecpar, vs->streams[i]->codecpar); if (!oc->oformat->codec_tag || - av_codec_get_id (oc->oformat->codec_tag, s->streams[i]->codecpar->codec_tag) == st->codecpar->codec_id || - av_codec_get_tag(oc->oformat->codec_tag, s->streams[i]->codecpar->codec_id) <= 0) { - st->codecpar->codec_tag = s->streams[i]->codecpar->codec_tag; + av_codec_get_id (oc->oformat->codec_tag, vs->streams[i]->codecpar->codec_tag) == st->codecpar->codec_id || + av_codec_get_tag(oc->oformat->codec_tag, vs->streams[i]->codecpar->codec_id) <= 0) { + st->codecpar->codec_tag = vs->streams[i]->codecpar->codec_tag; } else { st->codecpar->codec_tag = 0; } - st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; - st->time_base = s->streams[i]->time_base; - av_dict_copy(&st->metadata, s->streams[i]->metadata, 0); + st->sample_aspect_ratio = vs->streams[i]->sample_aspect_ratio; + st->time_base = vs->streams[i]->time_base; + av_dict_copy(&st->metadata, vs->streams[i]->metadata, 0); } - hls->packets_written = 1; - hls->start_pos = 0; - hls->new_start = 1; - hls->fmp4_init_mode = 0; + + vs->packets_written = 1; + vs->start_pos = 0; + vs->new_start = 1; + vs->fmp4_init_mode = 0; if (hls->segment_type == SEGMENT_TYPE_FMP4) { if (hls->max_seg_size > 0) { av_log(s, AV_LOG_WARNING, "Multi-file byterange mode is currently unsupported in the HLS muxer.\n"); return AVERROR_PATCHWELCOME; } - hls->packets_written = 0; - hls->init_range_length = 0; - hls->fmp4_init_mode = !byterange_mode; + + vs->packets_written = 0; + vs->init_range_length = 0; + vs->fmp4_init_mode = !byterange_mode; set_http_options(s, &options, hls); if ((ret = avio_open_dyn_buf(&oc->pb)) < 0) return ret; - if ((ret = s->io_open(s, &hls->out, hls->base_output_dirname, AVIO_FLAG_WRITE, &options)) < 0) { - av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", hls->fmp4_init_filename); + if ((ret = s->io_open(s, &vs->out, vs->base_output_dirname, AVIO_FLAG_WRITE, &options)) < 0) { + av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", vs->fmp4_init_filename); return ret; } @@ -659,19 +681,20 @@ static HLSSegment *find_segment_by_filename(HLSSegment *segment, const char *fil return (HLSSegment *) NULL; } -static int sls_flags_filename_process(struct AVFormatContext *s, HLSContext *hls, HLSSegment *en, double duration, - int64_t pos, int64_t size) +static int sls_flags_filename_process(struct AVFormatContext *s, HLSContext *hls, + VariantStream *vs, HLSSegment *en, + double duration, int64_t pos, int64_t size) { if ((hls->flags & (HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION)) && - strlen(hls->current_segment_final_filename_fmt)) { - av_strlcpy(hls->avf->filename, hls->current_segment_final_filename_fmt, sizeof(hls->avf->filename)); + strlen(vs->current_segment_final_filename_fmt)) { + av_strlcpy(vs->avf->filename, vs->current_segment_final_filename_fmt, sizeof(vs->avf->filename)); if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) { - char * filename = av_strdup(hls->avf->filename); // %%s will be %s after strftime + char * filename = av_strdup(vs->avf->filename); // %%s will be %s after strftime if (!filename) { av_free(en); return AVERROR(ENOMEM); } - if (replace_int_data_in_filename(hls->avf->filename, sizeof(hls->avf->filename), + if (replace_int_data_in_filename(vs->avf->filename, sizeof(vs->avf->filename), filename, 's', pos + size) < 1) { av_log(hls, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " @@ -684,12 +707,12 @@ static int sls_flags_filename_process(struct AVFormatContext *s, HLSContext *hls av_free(filename); } if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) { - char * filename = av_strdup(hls->avf->filename); // %%t will be %t after strftime + char * filename = av_strdup(vs->avf->filename); // %%t will be %t after strftime if (!filename) { av_free(en); return AVERROR(ENOMEM); } - if (replace_int_data_in_filename(hls->avf->filename, sizeof(hls->avf->filename), + if (replace_int_data_in_filename(vs->avf->filename, sizeof(vs->avf->filename), filename, 't', (int64_t)round(duration * HLS_MICROSECOND_UNIT)) < 1) { av_log(hls, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " @@ -728,9 +751,9 @@ static int sls_flag_check_duration_size_index(HLSContext *hls) return ret; } -static int sls_flag_check_duration_size(HLSContext *hls) +static int sls_flag_check_duration_size(HLSContext *hls, VariantStream *vs) { - const char *proto = avio_find_protocol_name(hls->basename); + const char *proto = avio_find_protocol_name(vs->basename); int segment_renaming_ok = proto && !strcmp(proto, "file"); int ret = 0; @@ -748,14 +771,14 @@ static int sls_flag_check_duration_size(HLSContext *hls) return ret; } -static void sls_flag_file_rename(HLSContext *hls, char *old_filename) { +static void sls_flag_file_rename(HLSContext *hls, VariantStream *vs, char *old_filename) { if ((hls->flags & (HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION)) && - strlen(hls->current_segment_final_filename_fmt)) { - ff_rename(old_filename, hls->avf->filename, hls); + strlen(vs->current_segment_final_filename_fmt)) { + ff_rename(old_filename, vs->avf->filename, hls); } } -static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c) +static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c, VariantStream *vs) { if (c->flags & HLS_SECOND_LEVEL_SEGMENT_INDEX) { char * filename = av_strdup(oc->filename); // %%d will be %d after strftime @@ -763,9 +786,9 @@ static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c) return AVERROR(ENOMEM); if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename), #if FF_API_HLS_WRAP - filename, 'd', c->wrap ? c->sequence % c->wrap : c->sequence) < 1) { + filename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) { #else - filename, 'd', c->sequence) < 1) { + filename, 'd', vs->sequence) < 1) { #endif av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_index flag\n", @@ -776,8 +799,8 @@ static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c) av_free(filename); } if (c->flags & (HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION)) { - av_strlcpy(c->current_segment_final_filename_fmt, oc->filename, - sizeof(c->current_segment_final_filename_fmt)); + av_strlcpy(vs->current_segment_final_filename_fmt, oc->filename, + sizeof(vs->current_segment_final_filename_fmt)); if (c->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) { char * filename = av_strdup(oc->filename); // %%s will be %s after strftime if (!filename) @@ -809,8 +832,9 @@ static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c) } /* Create a new segment and append it to the segment list */ -static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double duration, - int64_t pos, int64_t size) +static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, + VariantStream *vs, double duration, int64_t pos, + int64_t size) { HLSSegment *en = av_malloc(sizeof(*en)); const char *filename; @@ -820,24 +844,24 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double if (!en) return AVERROR(ENOMEM); - ret = sls_flags_filename_process(s, hls, en, duration, pos, size); + ret = sls_flags_filename_process(s, hls, vs, en, duration, pos, size); if (ret < 0) { return ret; } - filename = av_basename(hls->avf->filename); + filename = av_basename(vs->avf->filename); if (hls->use_localtime_mkdir) { - filename = hls->avf->filename; + filename = vs->avf->filename; } - if ((find_segment_by_filename(hls->segments, filename) || find_segment_by_filename(hls->old_segments, filename)) + if ((find_segment_by_filename(vs->segments, filename) || find_segment_by_filename(vs->old_segments, filename)) && !byterange_mode) { av_log(hls, AV_LOG_WARNING, "Duplicated segment filename detected: %s\n", filename); } av_strlcpy(en->filename, filename, sizeof(en->filename)); - if(hls->has_subtitle) - av_strlcpy(en->sub_filename, av_basename(hls->vtt_avf->filename), sizeof(en->sub_filename)); + if(vs->has_subtitle) + av_strlcpy(en->sub_filename, av_basename(vs->vtt_avf->filename), sizeof(en->sub_filename)); else en->sub_filename[0] = '\0'; @@ -847,9 +871,9 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double en->next = NULL; en->discont = 0; - if (hls->discontinuity) { + if (vs->discontinuity) { en->discont = 1; - hls->discontinuity = 0; + vs->discontinuity = 0; } if (hls->key_info_file || hls->encrypt) { @@ -857,45 +881,45 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double av_strlcpy(en->iv_string, hls->iv_string, sizeof(en->iv_string)); } - if (!hls->segments) - hls->segments = en; + if (!vs->segments) + vs->segments = en; else - hls->last_segment->next = en; + vs->last_segment->next = en; - hls->last_segment = en; + vs->last_segment = en; // EVENT or VOD playlists imply sliding window cannot be used if (hls->pl_type != PLAYLIST_TYPE_NONE) hls->max_nb_segments = 0; - if (hls->max_nb_segments && hls->nb_entries >= hls->max_nb_segments) { - en = hls->segments; - hls->initial_prog_date_time += en->duration; - hls->segments = en->next; + if (hls->max_nb_segments && vs->nb_entries >= hls->max_nb_segments) { + en = vs->segments; + vs->initial_prog_date_time += en->duration; + vs->segments = en->next; if (en && hls->flags & HLS_DELETE_SEGMENTS && #if FF_API_HLS_WRAP !(hls->flags & HLS_SINGLE_FILE || hls->wrap)) { #else !(hls->flags & HLS_SINGLE_FILE)) { #endif - en->next = hls->old_segments; - hls->old_segments = en; - if ((ret = hls_delete_old_segments(s, hls)) < 0) + en->next = vs->old_segments; + vs->old_segments = en; + if ((ret = hls_delete_old_segments(s, hls, vs)) < 0) return ret; } else av_free(en); } else - hls->nb_entries++; + vs->nb_entries++; if (hls->max_seg_size > 0) { return 0; } - hls->sequence++; + vs->sequence++; return 0; } -static int parse_playlist(AVFormatContext *s, const char *url) +static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs) { HLSContext *hls = s->priv_data; AVIOContext *in; @@ -916,26 +940,26 @@ static int parse_playlist(AVFormatContext *s, const char *url) goto fail; } - hls->discontinuity = 0; + vs->discontinuity = 0; while (!avio_feof(in)) { read_chomp_line(in, line, sizeof(line)); if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) { int64_t tmp_sequence = strtoll(ptr, NULL, 10); - if (tmp_sequence < hls->sequence) + if (tmp_sequence < vs->sequence) av_log(hls, AV_LOG_VERBOSE, "Found playlist sequence number was smaller """ "than specified start sequence number: %"PRId64" < %"PRId64", " "omitting\n", tmp_sequence, hls->start_sequence); else { av_log(hls, AV_LOG_DEBUG, "Found playlist sequence number: %"PRId64"\n", tmp_sequence); - hls->sequence = tmp_sequence; + vs->sequence = tmp_sequence; } } else if (av_strstart(line, "#EXT-X-DISCONTINUITY", &ptr)) { is_segment = 1; - hls->discontinuity = 1; + vs->discontinuity = 1; } else if (av_strstart(line, "#EXTINF:", &ptr)) { is_segment = 1; - hls->duration = atof(ptr); + vs->duration = atof(ptr); } else if (av_stristart(line, "#EXT-X-KEY:", &ptr)) { ptr = av_stristr(line, "URI=\""); if (ptr) { @@ -964,13 +988,13 @@ static int parse_playlist(AVFormatContext *s, const char *url) } else if (line[0]) { if (is_segment) { is_segment = 0; - new_start_pos = avio_tell(hls->avf->pb); - hls->size = new_start_pos - hls->start_pos; - av_strlcpy(hls->avf->filename, line, sizeof(line)); - ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size); + new_start_pos = avio_tell(vs->avf->pb); + vs->size = new_start_pos - vs->start_pos; + av_strlcpy(vs->avf->filename, line, sizeof(line)); + ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size); if (ret < 0) goto fail; - hls->start_pos = new_start_pos; + vs->start_pos = new_start_pos; } } } @@ -1015,7 +1039,7 @@ static void hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc) oc->filename[len-4] = '\0'; } -static int hls_window(AVFormatContext *s, int last) +static int hls_window(AVFormatContext *s, int last, VariantStream *vs) { HLSContext *hls = s->priv_data; HLSSegment *en; @@ -1024,7 +1048,7 @@ static int hls_window(AVFormatContext *s, int last) AVIOContext *out = NULL; AVIOContext *sub_out = NULL; char temp_filename[1024]; - int64_t sequence = FFMAX(hls->start_sequence, hls->sequence - hls->nb_entries); + int64_t sequence = FFMAX(hls->start_sequence, vs->sequence - vs->nb_entries); int version = 3; const char *proto = avio_find_protocol_name(s->filename); int use_rename = proto && !strcmp(proto, "file"); @@ -1032,7 +1056,7 @@ static int hls_window(AVFormatContext *s, int last) char *key_uri = NULL; char *iv_string = NULL; AVDictionary *options = NULL; - double prog_date_time = hls->initial_prog_date_time; + double prog_date_time = vs->initial_prog_date_time; int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); if (byterange_mode) { @@ -1048,16 +1072,16 @@ static int hls_window(AVFormatContext *s, int last) av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n"); set_http_options(s, &options, hls); - snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->filename); + snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", vs->m3u8_name); if ((ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, &options)) < 0) goto fail; - for (en = hls->segments; en; en = en->next) { + for (en = vs->segments; en; en = en->next) { if (target_duration <= en->duration) target_duration = get_int_from_double(en->duration); } - hls->discontinuity_set = 0; + vs->discontinuity_set = 0; write_m3u8_head_block(hls, out, version, target_duration, sequence); if (hls->pl_type == PLAYLIST_TYPE_EVENT) { avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n"); @@ -1065,11 +1089,11 @@ static int hls_window(AVFormatContext *s, int last) avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n"); } - if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && hls->discontinuity_set==0 ){ + if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && vs->discontinuity_set==0 ){ avio_printf(out, "#EXT-X-DISCONTINUITY\n"); - hls->discontinuity_set = 1; + vs->discontinuity_set = 1; } - for (en = hls->segments; en; en = en->next) { + for (en = vs->segments; en; en = en->next) { if ((hls->encrypt || hls->key_info_file) && (!key_uri || strcmp(en->key_uri, key_uri) || av_strcasecmp(en->iv_string, iv_string))) { avio_printf(out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri); @@ -1084,8 +1108,8 @@ static int hls_window(AVFormatContext *s, int last) avio_printf(out, "#EXT-X-DISCONTINUITY\n"); } - if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == hls->segments)) { - avio_printf(out, "#EXT-X-MAP:URI=\"%s\"", hls->fmp4_init_filename); + if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == vs->segments)) { + avio_printf(out, "#EXT-X-MAP:URI=\"%s\"", vs->fmp4_init_filename); if (hls->flags & HLS_SINGLE_FILE) { avio_printf(out, ",BYTERANGE=\"%"PRId64"@%"PRId64"\"", en->size, en->pos); } @@ -1123,26 +1147,26 @@ static int hls_window(AVFormatContext *s, int last) avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, milli, buf1); prog_date_time += en->duration; } - if (hls->baseurl) - avio_printf(out, "%s", hls->baseurl); + if (vs->baseurl) + avio_printf(out, "%s", vs->baseurl); avio_printf(out, "%s\n", en->filename); } if (last && (hls->flags & HLS_OMIT_ENDLIST)==0) avio_printf(out, "#EXT-X-ENDLIST\n"); - if( hls->vtt_m3u8_name ) { - if ((ret = s->io_open(s, &sub_out, hls->vtt_m3u8_name, AVIO_FLAG_WRITE, &options)) < 0) + if( vs->vtt_m3u8_name ) { + if ((ret = s->io_open(s, &sub_out, vs->vtt_m3u8_name, AVIO_FLAG_WRITE, &options)) < 0) goto fail; write_m3u8_head_block(hls, sub_out, version, target_duration, sequence); - for (en = hls->segments; en; en = en->next) { + for (en = vs->segments; en; en = en->next) { avio_printf(sub_out, "#EXTINF:%f,\n", en->duration); if (byterange_mode) avio_printf(sub_out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n", en->size, en->pos); - if (hls->baseurl) - avio_printf(sub_out, "%s", hls->baseurl); + if (vs->baseurl) + avio_printf(sub_out, "%s", vs->baseurl); avio_printf(sub_out, "%s\n", en->sub_filename); } @@ -1156,33 +1180,33 @@ static int hls_window(AVFormatContext *s, int last) ff_format_io_close(s, &out); ff_format_io_close(s, &sub_out); if (ret >= 0 && use_rename) - ff_rename(temp_filename, s->filename, s); + ff_rename(temp_filename, vs->m3u8_name, s); return ret; } -static int hls_start(AVFormatContext *s) +static int hls_start(AVFormatContext *s, VariantStream *vs) { HLSContext *c = s->priv_data; - AVFormatContext *oc = c->avf; - AVFormatContext *vtt_oc = c->vtt_avf; + AVFormatContext *oc = vs->avf; + AVFormatContext *vtt_oc = vs->vtt_avf; AVDictionary *options = NULL; char *filename, iv_string[KEYSIZE*2 + 1]; int err = 0; if (c->flags & HLS_SINGLE_FILE) { - av_strlcpy(oc->filename, c->basename, + av_strlcpy(oc->filename, vs->basename, sizeof(oc->filename)); - if (c->vtt_basename) - av_strlcpy(vtt_oc->filename, c->vtt_basename, + if (vs->vtt_basename) + av_strlcpy(vtt_oc->filename, vs->vtt_basename, sizeof(vtt_oc->filename)); } else if (c->max_seg_size > 0) { if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename), #if FF_API_HLS_WRAP - c->basename, 'd', c->wrap ? c->sequence % c->wrap : c->sequence) < 1) { + vs->basename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) { #else - c->basename, 'd', c->sequence) < 1) { + vs->basename, 'd', vs->sequence) < 1) { #endif - av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -use_localtime 1 with it\n", c->basename); + av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -use_localtime 1 with it\n", vs->basename); return AVERROR(EINVAL); } } else { @@ -1191,12 +1215,12 @@ static int hls_start(AVFormatContext *s) struct tm *tm, tmpbuf; time(&now0); tm = localtime_r(&now0, &tmpbuf); - if (!strftime(oc->filename, sizeof(oc->filename), c->basename, tm)) { + if (!strftime(oc->filename, sizeof(oc->filename), vs->basename, tm)) { av_log(oc, AV_LOG_ERROR, "Could not get segment filename with use_localtime\n"); return AVERROR(EINVAL); } - err = sls_flag_use_localtime_filename(oc, c); + err = sls_flag_use_localtime_filename(oc, c, vs); if (err < 0) { return AVERROR(ENOMEM); } @@ -1217,26 +1241,26 @@ static int hls_start(AVFormatContext *s) } } else if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename), #if FF_API_HLS_WRAP - c->basename, 'd', c->wrap ? c->sequence % c->wrap : c->sequence) < 1) { + vs->basename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) { #else - c->basename, 'd', c->sequence) < 1) { + vs->basename, 'd', vs->sequence) < 1) { #endif - av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -use_localtime 1 with it\n", c->basename); + av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -use_localtime 1 with it\n", vs->basename); return AVERROR(EINVAL); } - if( c->vtt_basename) { + if( vs->vtt_basename) { if (replace_int_data_in_filename(vtt_oc->filename, sizeof(vtt_oc->filename), #if FF_API_HLS_WRAP - c->vtt_basename, 'd', c->wrap ? c->sequence % c->wrap : c->sequence) < 1) { + vs->vtt_basename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) { #else - c->vtt_basename, 'd', c->sequence) < 1) { + vs->vtt_basename, 'd', vs->sequence) < 1) { #endif - av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->vtt_basename); + av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", vs->vtt_basename); return AVERROR(EINVAL); } } } - c->number++; + vs->number++; set_http_options(s, &options, c); @@ -1250,21 +1274,22 @@ static int hls_start(AVFormatContext *s) " will use -hls_key_info_file priority\n"); } - if (c->number <= 1 || (c->flags & HLS_PERIODIC_REKEY)) { + if (!c->encrypt_started || (c->flags & HLS_PERIODIC_REKEY)) { if (c->key_info_file) { if ((err = hls_encryption_start(s)) < 0) goto fail; } else { - if ((err = do_encrypt(s)) < 0) + if ((err = do_encrypt(s, vs)) < 0) goto fail; } + c->encrypt_started = 1; } if ((err = av_dict_set(&options, "encryption_key", c->key_string, 0)) < 0) goto fail; err = av_strlcpy(iv_string, c->iv_string, sizeof(iv_string)); if (!err) - snprintf(iv_string, sizeof(iv_string), "%032"PRIx64, c->sequence); + snprintf(iv_string, sizeof(iv_string), "%032"PRIx64, vs->sequence); if ((err = av_dict_set(&options, "encryption_iv", iv_string, 0)) < 0) goto fail; @@ -1281,7 +1306,7 @@ static int hls_start(AVFormatContext *s) } else if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, &options)) < 0) goto fail; - if (c->vtt_basename) { + if (vs->vtt_basename) { set_http_options(s, &options, c); if ((err = s->io_open(s, &vtt_oc->pb, vtt_oc->filename, AVIO_FLAG_WRITE, &options)) < 0) goto fail; @@ -1303,7 +1328,7 @@ static int hls_start(AVFormatContext *s) } } - if (c->vtt_basename) { + if (vs->vtt_basename) { err = avformat_write_header(vtt_oc,NULL); if (err < 0) return err; @@ -1332,19 +1357,186 @@ static const char * get_default_pattern_localtime_fmt(AVFormatContext *s) return (HAVE_LIBC_MSVCRT || !strftime(b, sizeof(b), "%s", p) || !strcmp(b, "%s")) ? "-%Y%m%d%H%M%S.ts" : "-%s.ts"; } +static int format_name(char *name, int name_buf_len, int i) +{ + char *p; + char extension[10] = {'\0'}; + + p = strrchr(name, '.'); + if (p) { + av_strlcpy(extension, p, sizeof(extension)); + *p = '\0'; + } + + snprintf(name + strlen(name), name_buf_len - strlen(name), POSTFIX_PATTERN, i); + + if (strlen(extension)) + av_strlcat(name, extension, name_buf_len); + + return 0; +} + +static int get_nth_codec_stream_index(AVFormatContext *s, + enum AVMediaType codec_type, + int stream_id) +{ + unsigned int stream_index, cnt; + if (stream_id < 0 || stream_id > s->nb_streams - 1) + return -1; + cnt = 0; + for (stream_index = 0; stream_index < s->nb_streams; stream_index++) { + if (s->streams[stream_index]->codecpar->codec_type != codec_type) + continue; + if (cnt == stream_id) + return stream_index; + cnt++; + } + return -1; +} + +static int parse_variant_stream_mapstring(AVFormatContext *s) +{ + HLSContext *hls = s->priv_data; + VariantStream *vs; + int stream_index; + enum AVMediaType codec_type; + int nb_varstreams, nb_streams; + char *p, *q, *saveptr1, *saveptr2, *varstr, *keyval; + const char *val; + + /** + * Expected format for var_stream_map string is as below: + * "a:0,v:0 a:1,v:1" + * This string specifies how to group the audio, video and subtitle streams + * into different variant streams. The variant stream groups are separated + * by space. + * + * a:, v:, s: are keys to specify audio, video and subtitle streams + * respectively. Allowed values are 0 to 9 digits (limited just based on + * practical usage) + * + */ + p = av_strdup(hls->var_stream_map); + q = p; + while(av_strtok(q, " \t", &saveptr1)) { + q = NULL; + hls->nb_varstreams++; + } + av_freep(&p); + + hls->var_streams = av_mallocz(sizeof(*hls->var_streams) * hls->nb_varstreams); + if (!hls->var_streams) + return AVERROR(ENOMEM); + + p = hls->var_stream_map; + nb_varstreams = 0; + while (varstr = av_strtok(p, " \t", &saveptr1)) { + p = NULL; + + if (nb_varstreams < hls->nb_varstreams) + vs = &(hls->var_streams[nb_varstreams++]); + else + return AVERROR(EINVAL); + + q = varstr; + while (q < varstr + strlen(varstr)) { + if (!av_strncasecmp(q, "a:", 2) || !av_strncasecmp(q, "v:", 2) || + !av_strncasecmp(q, "s:", 2)) + vs->nb_streams++; + q++; + } + vs->streams = av_mallocz(sizeof(AVStream *) * vs->nb_streams); + if (!vs->streams) + return AVERROR(ENOMEM); + + nb_streams = 0; + while (keyval = av_strtok(varstr, ",", &saveptr2)) { + varstr = NULL; + + if (av_strstart(keyval, "v:", &val)) { + codec_type = AVMEDIA_TYPE_VIDEO; + } else if (av_strstart(keyval, "a:", &val)) { + codec_type = AVMEDIA_TYPE_AUDIO; + } else if (av_strstart(keyval, "s:", &val)) { + codec_type = AVMEDIA_TYPE_SUBTITLE; + } else { + av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval); + return AVERROR(EINVAL); + } + + stream_index = -1; + if (av_isdigit(*val)) + stream_index = get_nth_codec_stream_index (s, codec_type, + atoi(val)); + + if (stream_index >= 0 && nb_streams < vs->nb_streams) { + vs->streams[nb_streams++] = s->streams[stream_index]; + } else { + av_log(s, AV_LOG_ERROR, "Unable to map stream at %s\n", keyval); + return AVERROR(EINVAL); + } + } + } + av_log(s, AV_LOG_DEBUG, "Number of variant streams %d\n", + hls->nb_varstreams); + + return 0; +} + +static int update_variant_stream_info(AVFormatContext *s) { + HLSContext *hls = s->priv_data; + unsigned int i; + + if (hls->var_stream_map) { + return parse_variant_stream_mapstring(s); + } else { + //By default, a single variant stream with all the codec streams is created + hls->nb_varstreams = 1; + hls->var_streams = av_mallocz(sizeof(*hls->var_streams) * + hls->nb_varstreams); + if (!hls->var_streams) + return AVERROR(ENOMEM); + + hls->var_streams[0].nb_streams = s->nb_streams; + hls->var_streams[0].streams = av_mallocz(sizeof(AVStream *) * + hls->var_streams[0].nb_streams); + if (!hls->var_streams[0].streams) + return AVERROR(ENOMEM); + + for (i = 0; i < s->nb_streams; i++) + hls->var_streams[0].streams[i] = s->streams[i]; + } + return 0; +} + static int hls_write_header(AVFormatContext *s) { HLSContext *hls = s->priv_data; - int ret, i; + int ret, i, j; char *p = NULL; const char *pattern = "%d.ts"; const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s); const char *vtt_pattern = "%d.vtt"; AVDictionary *options = NULL; int basename_size = 0; - int vtt_basename_size = 0; + int vtt_basename_size = 0, m3u8_name_size = 0; + VariantStream *vs = NULL; int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1; + ret = update_variant_stream_info(s); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n", + ret); + goto fail; + } + + //TODO: Updates needed to encryption functionality with periodic re-key when more than one variant streams are present + if (hls->nb_varstreams > 1 && hls->flags & HLS_PERIODIC_REKEY) { + ret = AVERROR(EINVAL); + av_log(s, AV_LOG_ERROR, "Periodic re-key not supported when more than one variant streams are present\n"); + goto fail; + } + if (hls->segment_type == SEGMENT_TYPE_FMP4) { pattern = "%d.m4s"; } @@ -1365,15 +1557,18 @@ static int hls_write_header(AVFormatContext *s) av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence); } - hls->sequence = hls->start_sequence; + for (i = 0; i < hls->nb_varstreams; i++) { + vs = &hls->var_streams[i]; + + vs->sequence = hls->start_sequence; hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE; - hls->start_pts = AV_NOPTS_VALUE; - hls->current_segment_final_filename_fmt[0] = '\0'; + vs->start_pts = AV_NOPTS_VALUE; + vs->current_segment_final_filename_fmt[0] = '\0'; if (hls->flags & HLS_PROGRAM_DATE_TIME) { time_t now0; time(&now0); - hls->initial_prog_date_time = now0; + vs->initial_prog_date_time = now0; } if (hls->format_options_str) { @@ -1384,43 +1579,49 @@ static int hls_write_header(AVFormatContext *s) } } - for (i = 0; i < s->nb_streams; i++) { - hls->has_video += - s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO; - hls->has_subtitle += - s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE; + for (j = 0; j < vs->nb_streams; j++) { + vs->has_video += + vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO; + vs->has_subtitle += + vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE; } - if (hls->has_video > 1) + if (vs->has_video > 1) av_log(s, AV_LOG_WARNING, "More than a single video stream present, " "expect issues decoding it.\n"); if (hls->segment_type == SEGMENT_TYPE_FMP4) { - hls->oformat = av_guess_format("mp4", NULL, NULL); + vs->oformat = av_guess_format("mp4", NULL, NULL); } else { - hls->oformat = av_guess_format("mpegts", NULL, NULL); + vs->oformat = av_guess_format("mpegts", NULL, NULL); } - if (!hls->oformat) { + if (!vs->oformat) { ret = AVERROR_MUXER_NOT_FOUND; goto fail; } - if(hls->has_subtitle) { - hls->vtt_oformat = av_guess_format("webvtt", NULL, NULL); - if (!hls->oformat) { + if(vs->has_subtitle) { + vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL); + if (!vs->oformat) { ret = AVERROR_MUXER_NOT_FOUND; goto fail; } } if (hls->segment_filename) { - hls->basename = av_strdup(hls->segment_filename); - if (!hls->basename) { + basename_size = strlen(hls->segment_filename) + 1; + if (hls->nb_varstreams > 1) { + basename_size += strlen(POSTFIX_PATTERN); + } + vs->basename = av_malloc(basename_size); + if (!vs->basename) { ret = AVERROR(ENOMEM); goto fail; } + + av_strlcpy(vs->basename, hls->segment_filename, basename_size); } else { if (hls->flags & HLS_SINGLE_FILE) { if (hls->segment_type == SEGMENT_TYPE_FMP4) { @@ -1435,52 +1636,96 @@ static int hls_write_header(AVFormatContext *s) } else { basename_size = strlen(s->filename) + strlen(pattern) + 1; } - hls->basename = av_malloc(basename_size); - if (!hls->basename) { + + if (hls->nb_varstreams > 1) { + basename_size += strlen(POSTFIX_PATTERN); + } + + vs->basename = av_malloc(basename_size); + if (!vs->basename) { ret = AVERROR(ENOMEM); goto fail; } - av_strlcpy(hls->basename, s->filename, basename_size); + av_strlcpy(vs->basename, s->filename, basename_size); - p = strrchr(hls->basename, '.'); + p = strrchr(vs->basename, '.'); if (p) *p = '\0'; if (hls->use_localtime) { - av_strlcat(hls->basename, pattern_localtime_fmt, basename_size); + av_strlcat(vs->basename, pattern_localtime_fmt, basename_size); } else { - av_strlcat(hls->basename, pattern, basename_size); + av_strlcat(vs->basename, pattern, basename_size); } } + m3u8_name_size = strlen(s->filename) + 1; + if (hls->nb_varstreams > 1) { + m3u8_name_size += strlen(POSTFIX_PATTERN); + } + + vs->m3u8_name = av_malloc(m3u8_name_size); + if (!vs->m3u8_name ) { + ret = AVERROR(ENOMEM); + goto fail; + } + + av_strlcpy(vs->m3u8_name, s->filename, m3u8_name_size); + + if (hls->nb_varstreams > 1) { + ret = format_name(vs->basename, basename_size, i); + if (ret < 0) + goto fail; + ret = format_name(vs->m3u8_name, m3u8_name_size, i); + if (ret < 0) + goto fail; + } + if (hls->segment_type == SEGMENT_TYPE_FMP4) { + if (hls->nb_varstreams > 1) + fmp4_init_filename_len += strlen(POSTFIX_PATTERN); + vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len); + if (!vs->fmp4_init_filename ) { + ret = AVERROR(ENOMEM); + goto fail; + } + av_strlcpy(vs->fmp4_init_filename, hls->fmp4_init_filename, + fmp4_init_filename_len); + if (hls->nb_varstreams > 1) { + ret = format_name(vs->fmp4_init_filename, fmp4_init_filename_len, i); + if (ret < 0) + goto fail; + } + if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) { - hls->base_output_dirname = av_malloc(fmp4_init_filename_len); - if (!hls->base_output_dirname) { + fmp4_init_filename_len = strlen(vs->fmp4_init_filename) + 1; + vs->base_output_dirname = av_malloc(fmp4_init_filename_len); + if (!vs->base_output_dirname) { ret = AVERROR(ENOMEM); goto fail; } - av_strlcpy(hls->base_output_dirname, hls->fmp4_init_filename, fmp4_init_filename_len); + av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, + fmp4_init_filename_len); } else { - if (basename_size > 0) { - hls->base_output_dirname = av_malloc(basename_size); - } else { - hls->base_output_dirname = av_malloc(strlen(hls->fmp4_init_filename) + 1); - } - if (!hls->base_output_dirname) { + fmp4_init_filename_len = strlen(vs->m3u8_name) + + strlen(vs->fmp4_init_filename) + 1; + + vs->base_output_dirname = av_malloc(fmp4_init_filename_len); + if (!vs->base_output_dirname) { ret = AVERROR(ENOMEM); goto fail; } - if (basename_size > 0) { - av_strlcpy(hls->base_output_dirname, s->filename, basename_size); - p = strrchr(hls->base_output_dirname, '/'); - } + av_strlcpy(vs->base_output_dirname, vs->m3u8_name, + fmp4_init_filename_len); + p = strrchr(vs->base_output_dirname, '/'); if (p) { *(p + 1) = '\0'; - av_strlcat(hls->base_output_dirname, hls->fmp4_init_filename, basename_size); + av_strlcat(vs->base_output_dirname, vs->fmp4_init_filename, + fmp4_init_filename_len); } else { - av_strlcpy(hls->base_output_dirname, hls->fmp4_init_filename, fmp4_init_filename_len); + av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, + fmp4_init_filename_len); } } } @@ -1491,54 +1736,78 @@ static int hls_write_header(AVFormatContext *s) goto fail; } } else { - ret = sls_flag_check_duration_size(hls); + ret = sls_flag_check_duration_size(hls, vs); if (ret < 0) { goto fail; } } - if(hls->has_subtitle) { + if(vs->has_subtitle) { if (hls->flags & HLS_SINGLE_FILE) vtt_pattern = ".vtt"; vtt_basename_size = strlen(s->filename) + strlen(vtt_pattern) + 1; - hls->vtt_basename = av_malloc(vtt_basename_size); - if (!hls->vtt_basename) { + if (hls->nb_varstreams > 1) { + vtt_basename_size += strlen(POSTFIX_PATTERN); + } + + vs->vtt_basename = av_malloc(vtt_basename_size); + if (!vs->vtt_basename) { ret = AVERROR(ENOMEM); goto fail; } - hls->vtt_m3u8_name = av_malloc(vtt_basename_size); - if (!hls->vtt_m3u8_name ) { + vs->vtt_m3u8_name = av_malloc(vtt_basename_size); + if (!vs->vtt_m3u8_name ) { ret = AVERROR(ENOMEM); goto fail; } - av_strlcpy(hls->vtt_basename, s->filename, vtt_basename_size); - p = strrchr(hls->vtt_basename, '.'); + av_strlcpy(vs->vtt_basename, s->filename, vtt_basename_size); + p = strrchr(vs->vtt_basename, '.'); if (p) *p = '\0'; if( hls->subtitle_filename ) { - strcpy(hls->vtt_m3u8_name, hls->subtitle_filename); + strcpy(vs->vtt_m3u8_name, hls->subtitle_filename); } else { - strcpy(hls->vtt_m3u8_name, hls->vtt_basename); - av_strlcat(hls->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size); + strcpy(vs->vtt_m3u8_name, vs->vtt_basename); + av_strlcat(vs->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size); } - av_strlcat(hls->vtt_basename, vtt_pattern, vtt_basename_size); + av_strlcat(vs->vtt_basename, vtt_pattern, vtt_basename_size); + + if (hls->nb_varstreams > 1) { + ret= format_name(vs->vtt_basename, vtt_basename_size, i); + if (ret < 0) + goto fail; + ret = format_name(vs->vtt_m3u8_name, vtt_basename_size, i); + if (ret < 0) + goto fail; + } + } + + if (hls->baseurl) { + int baseurl_len; + baseurl_len = strlen(hls->baseurl); + vs->baseurl = av_malloc(baseurl_len); + if (!vs->baseurl) { + ret = AVERROR(ENOMEM); + goto fail; + } + av_strlcpy(vs->baseurl, hls->baseurl, baseurl_len); } if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) { - hls->fmp4_init_filename = av_strdup(hls->basename); - if (!hls->fmp4_init_filename) { + vs->fmp4_init_filename = av_strdup(vs->basename); + if (!vs->fmp4_init_filename) { ret = AVERROR(ENOMEM); goto fail; } } - if ((ret = hls_mux_init(s)) < 0) + if ((ret = hls_mux_init(s, vs)) < 0) goto fail; if (hls->flags & HLS_APPEND_LIST) { - parse_playlist(s, s->filename); - hls->discontinuity = 1; + parse_playlist(s, vs->m3u8_name, vs); + vs->discontinuity = 1; if (hls->init_time > 0) { av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time," " hls_init_time value will have no effect\n"); @@ -1548,21 +1817,23 @@ static int hls_write_header(AVFormatContext *s) } if (hls->segment_type != SEGMENT_TYPE_FMP4 || hls->flags & HLS_SINGLE_FILE) { - if ((ret = hls_start(s)) < 0) + if ((ret = hls_start(s, vs)) < 0) goto fail; } av_dict_copy(&options, hls->format_options, 0); - ret = avformat_write_header(hls->avf, &options); + ret = avformat_write_header(vs->avf, &options); if (av_dict_count(options)) { av_log(s, AV_LOG_ERROR, "Some of provided format options in '%s' are not recognized\n", hls->format_options_str); ret = AVERROR(EINVAL); + av_dict_free(&options); goto fail; } + av_dict_free(&options); //av_assert0(s->nb_streams == hls->avf->nb_streams); - for (i = 0; i < s->nb_streams; i++) { + for (j = 0; j < vs->nb_streams; j++) { AVStream *inner_st; - AVStream *outer_st = s->streams[i]; + AVStream *outer_st = vs->streams[j]; if (hls->max_seg_size > 0) { if ((outer_st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && @@ -1574,9 +1845,9 @@ static int hls_write_header(AVFormatContext *s) } if (outer_st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) - inner_st = hls->avf->streams[i]; - else if (hls->vtt_avf) - inner_st = hls->vtt_avf->streams[0]; + inner_st = vs->avf->streams[j]; + else if (vs->vtt_avf) + inner_st = vs->vtt_avf->streams[0]; else { /* We have a subtitle stream, when the user does not want one */ inner_st = NULL; @@ -1584,19 +1855,27 @@ static int hls_write_header(AVFormatContext *s) } avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den); } + } fail: - av_dict_free(&options); if (ret < 0) { - av_freep(&hls->fmp4_init_filename); - av_freep(&hls->basename); - av_freep(&hls->vtt_basename); av_freep(&hls->key_basename); - if (hls->avf) - avformat_free_context(hls->avf); - if (hls->vtt_avf) - avformat_free_context(hls->vtt_avf); + for (i = 0; i < hls->nb_varstreams && hls->var_streams; i++) { + vs = &hls->var_streams[i]; + av_freep(&vs->basename); + av_freep(&vs->vtt_basename); + av_freep(&vs->fmp4_init_filename); + av_freep(&vs->m3u8_name); + av_freep(&vs->vtt_m3u8_name); + av_freep(&vs->streams); + av_freep(&vs->baseurl); + if (vs->avf) + avformat_free_context(vs->avf); + if (vs->vtt_avf) + avformat_free_context(vs->vtt_avf); + } + av_freep(&hls->var_streams); } return ret; } @@ -1606,34 +1885,54 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) HLSContext *hls = s->priv_data; AVFormatContext *oc = NULL; AVStream *st = s->streams[pkt->stream_index]; - int64_t end_pts = hls->recording_time * hls->number; + int64_t end_pts = 0; int is_ref_pkt = 1; - int ret = 0, can_split = 1; + int ret = 0, can_split = 1, i, j; int stream_index = 0; int range_length = 0; uint8_t *buffer = NULL; + VariantStream *vs = NULL; + + for (i = 0; i < hls->nb_varstreams; i++) { + vs = &hls->var_streams[i]; + for (j = 0; j < vs->nb_streams; j++) { + if (vs->streams[j] == st) { + if( st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE ) { + oc = vs->vtt_avf; + stream_index = 0; + } else { + oc = vs->avf; + stream_index = j; + } + break; + } + } + + if (oc) + break; + } + + if (!oc) { + av_log(s, AV_LOG_ERROR, "Unable to find mapping variant stream\n"); + return AVERROR(ENOMEM); + } + + end_pts = hls->recording_time * vs->number; - if (hls->sequence - hls->nb_entries > hls->start_sequence && hls->init_time > 0) { + if (vs->sequence - vs->nb_entries > hls->start_sequence && hls->init_time > 0) { /* reset end_pts, hls->recording_time at end of the init hls list */ - int init_list_dur = hls->init_time * hls->nb_entries * AV_TIME_BASE; - int after_init_list_dur = (hls->sequence - hls->nb_entries ) * hls->time * AV_TIME_BASE; + int init_list_dur = hls->init_time * vs->nb_entries * AV_TIME_BASE; + int after_init_list_dur = (vs->sequence - vs->nb_entries ) * hls->time * AV_TIME_BASE; hls->recording_time = hls->time * AV_TIME_BASE; end_pts = init_list_dur + after_init_list_dur ; } - if( st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE ) { - oc = hls->vtt_avf; - stream_index = 0; - } else { - oc = hls->avf; - stream_index = pkt->stream_index; - } - if (hls->start_pts == AV_NOPTS_VALUE) { - hls->start_pts = pkt->pts; - hls->end_pts = pkt->pts; + if (vs->start_pts == AV_NOPTS_VALUE) { + vs->start_pts = pkt->pts; + vs->end_pts = pkt->pts; } - if (hls->has_video) { + if (vs->has_video) { can_split = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ((pkt->flags & AV_PKT_FLAG_KEY) || (hls->flags & HLS_SPLIT_BY_TIME)); is_ref_pkt = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO; @@ -1642,92 +1941,92 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) is_ref_pkt = can_split = 0; if (is_ref_pkt) { - if (hls->new_start) { - hls->new_start = 0; - hls->duration = (double)(pkt->pts - hls->end_pts) + if (vs->new_start) { + vs->new_start = 0; + vs->duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den; - hls->dpp = (double)(pkt->duration) * st->time_base.num / st->time_base.den; + vs->dpp = (double)(pkt->duration) * st->time_base.num / st->time_base.den; } else { if (pkt->duration) { - hls->duration += (double)(pkt->duration) * st->time_base.num / st->time_base.den; + vs->duration += (double)(pkt->duration) * st->time_base.num / st->time_base.den; } else { av_log(s, AV_LOG_WARNING, "pkt->duration = 0, maybe the hls segment duration will not precise\n"); - hls->duration = (double)(pkt->pts - hls->end_pts) * st->time_base.num / st->time_base.den; + vs->duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den; } } } - if (hls->packets_written && can_split && av_compare_ts(pkt->pts - hls->start_pts, st->time_base, + + if (vs->packets_written && can_split && av_compare_ts(pkt->pts - vs->start_pts, st->time_base, end_pts, AV_TIME_BASE_Q) >= 0) { int64_t new_start_pos; - char *old_filename = av_strdup(hls->avf->filename); + char *old_filename = av_strdup(vs->avf->filename); int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); if (!old_filename) { return AVERROR(ENOMEM); } - av_write_frame(hls->avf, NULL); /* Flush any buffered data */ + av_write_frame(vs->avf, NULL); /* Flush any buffered data */ - new_start_pos = avio_tell(hls->avf->pb); - hls->size = new_start_pos - hls->start_pos; + new_start_pos = avio_tell(vs->avf->pb); + vs->size = new_start_pos - vs->start_pos; if (!byterange_mode) { - if (hls->segment_type == SEGMENT_TYPE_FMP4 && !hls->init_range_length) { + if (hls->segment_type == SEGMENT_TYPE_FMP4 && !vs->init_range_length) { avio_flush(oc->pb); range_length = avio_close_dyn_buf(oc->pb, &buffer); - avio_write(hls->out, buffer, range_length); - hls->init_range_length = range_length; + avio_write(vs->out, buffer, range_length); + vs->init_range_length = range_length; avio_open_dyn_buf(&oc->pb); - hls->packets_written = 0; - ff_format_io_close(s, &hls->out); + vs->packets_written = 0; + ff_format_io_close(s, &vs->out); } else { ff_format_io_close(s, &oc->pb); } - if (hls->vtt_avf) { - ff_format_io_close(s, &hls->vtt_avf->pb); + if (vs->vtt_avf) { + ff_format_io_close(s, &vs->vtt_avf->pb); } } if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) { if (!(hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size <= 0)) - if ((hls->avf->oformat->priv_class && hls->avf->priv_data) && hls->segment_type != SEGMENT_TYPE_FMP4) - av_opt_set(hls->avf->priv_data, "mpegts_flags", "resend_headers", 0); + if ((vs->avf->oformat->priv_class && vs->avf->priv_data) && hls->segment_type != SEGMENT_TYPE_FMP4) + av_opt_set(vs->avf->priv_data, "mpegts_flags", "resend_headers", 0); hls_rename_temp_file(s, oc); } - if (hls->fmp4_init_mode) { - hls->number--; + if (vs->fmp4_init_mode) { + vs->number--; } - if (!hls->fmp4_init_mode || byterange_mode) - ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size); - - hls->start_pos = new_start_pos; + if (!vs->fmp4_init_mode || byterange_mode) + ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size); + vs->start_pos = new_start_pos; if (ret < 0) { av_free(old_filename); return ret; } - hls->end_pts = pkt->pts; - hls->duration = 0; + vs->end_pts = pkt->pts; + vs->duration = 0; - hls->fmp4_init_mode = 0; + vs->fmp4_init_mode = 0; if (hls->flags & HLS_SINGLE_FILE) { - hls->number++; + vs->number++; } else if (hls->max_seg_size > 0) { - if (hls->start_pos >= hls->max_seg_size) { - hls->sequence++; - sls_flag_file_rename(hls, old_filename); - ret = hls_start(s); - hls->start_pos = 0; + if (vs->start_pos >= hls->max_seg_size) { + vs->sequence++; + sls_flag_file_rename(hls, vs, old_filename); + ret = hls_start(s, vs); + vs->start_pos = 0; /* When split segment by byte, the duration is short than hls_time, * so it is not enough one segment duration as hls_time, */ - hls->number--; + vs->number--; } - hls->number++; + vs->number++; } else { - sls_flag_file_rename(hls, old_filename); - ret = hls_start(s); + sls_flag_file_rename(hls, vs, old_filename); + ret = hls_start(s, vs); } av_free(old_filename); @@ -1735,13 +2034,13 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) return ret; } - if (!hls->fmp4_init_mode || byterange_mode) - if ((ret = hls_window(s, 0)) < 0) { + if (!vs->fmp4_init_mode || byterange_mode) + if ((ret = hls_window(s, 0, vs)) < 0) { return ret; } } - hls->packets_written++; + vs->packets_written++; ret = ff_write_chained(oc, stream_index, pkt, s, 0); return ret; @@ -1750,9 +2049,18 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) static int hls_write_trailer(struct AVFormatContext *s) { HLSContext *hls = s->priv_data; - AVFormatContext *oc = hls->avf; - AVFormatContext *vtt_oc = hls->vtt_avf; - char *old_filename = av_strdup(hls->avf->filename); + AVFormatContext *oc = NULL; + AVFormatContext *vtt_oc = NULL; + char *old_filename = NULL; + int i; + VariantStream *vs = NULL; + + for (i = 0; i < hls->nb_varstreams; i++) { + vs = &hls->var_streams[i]; + + oc = vs->avf; + vtt_oc = vs->vtt_avf; + old_filename = av_strdup(vs->avf->filename); if (!old_filename) { return AVERROR(ENOMEM); @@ -1761,7 +2069,7 @@ static int hls_write_trailer(struct AVFormatContext *s) av_write_trailer(oc); if (oc->pb) { - hls->size = avio_tell(hls->avf->pb) - hls->start_pos; + vs->size = avio_tell(vs->avf->pb) - vs->start_pos; ff_format_io_close(s, &oc->pb); if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) { @@ -1769,35 +2077,41 @@ static int hls_write_trailer(struct AVFormatContext *s) } /* after av_write_trailer, then duration + 1 duration per packet */ - hls_append_segment(s, hls, hls->duration + hls->dpp, hls->start_pos, hls->size); + hls_append_segment(s, hls, vs, vs->duration + vs->dpp, vs->start_pos, vs->size); } - sls_flag_file_rename(hls, old_filename); + sls_flag_file_rename(hls, vs, old_filename); if (vtt_oc) { if (vtt_oc->pb) av_write_trailer(vtt_oc); - hls->size = avio_tell(hls->vtt_avf->pb) - hls->start_pos; + vs->size = avio_tell(vs->vtt_avf->pb) - vs->start_pos; ff_format_io_close(s, &vtt_oc->pb); } - av_freep(&hls->basename); - av_freep(&hls->base_output_dirname); - av_freep(&hls->key_basename); + av_freep(&vs->basename); + av_freep(&vs->base_output_dirname); avformat_free_context(oc); - hls->avf = NULL; - hls_window(s, 1); + vs->avf = NULL; + hls_window(s, 1, vs); - av_freep(&hls->fmp4_init_filename); + av_freep(&vs->fmp4_init_filename); if (vtt_oc) { - av_freep(&hls->vtt_basename); - av_freep(&hls->vtt_m3u8_name); + av_freep(&vs->vtt_basename); + av_freep(&vs->vtt_m3u8_name); avformat_free_context(vtt_oc); } - hls_free_segments(hls->segments); - hls_free_segments(hls->old_segments); + hls_free_segments(vs->segments); + hls_free_segments(vs->old_segments); av_free(old_filename); + av_freep(&vs->m3u8_name); + av_freep(&vs->streams); + av_freep(&vs->baseurl); + } + + av_freep(&hls->key_basename); + av_freep(&hls->var_streams); return 0; } @@ -1852,6 +2166,7 @@ static const AVOption options[] = { {"epoch", "seconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, "start_sequence_source_type" }, {"datetime", "current datetime as YYYYMMDDhhmmss", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME }, INT_MIN, INT_MAX, E, "start_sequence_source_type" }, {"http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, + {"var_stream_map", "Variant stream map string", OFFSET(var_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, { NULL }, }; diff --git a/libavformat/version.h b/libavformat/version.h index 509a4839e9eb6..4b7ee260d7f8c 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -33,7 +33,7 @@ // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 #define LIBAVFORMAT_VERSION_MINOR 2 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From 77ab1d7baed9b266aca1c656db1b4f1e32bee0aa Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Mon, 20 Nov 2017 10:04:34 +0800 Subject: [PATCH 0992/2557] avformat/hlsenc: creation of hls master playlist file Reviewed-by: Steven Liu --- doc/muxers.texi | 20 +++++ libavformat/hlsenc.c | 182 ++++++++++++++++++++++++++++++++++++++++-- libavformat/version.h | 2 +- 3 files changed, 197 insertions(+), 7 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 7fa2a2381ddf1..067a40289bd07 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -828,6 +828,26 @@ out_1.m3u8, out_2.m3u8 and out_3.m3u8 will be created. By default, a single hls variant containing all the encoded streams is created. +@item master_pl_name +Create HLS master playlist with the given name. + +@example +ffmpeg -re -i in.ts -f hls -master_pl_name master.m3u8 http://example.com/live/out.m3u8 +@end example +This example creates HLS master playlist with name master.m3u8 and it is +published at http://example.com/live/ + +@item master_pl_publish_rate +Publish master play list repeatedly every after specified number of segment intervals. + +@example +ffmpeg -re -i in.ts -f hls -master_pl_name master.m3u8 \ +-hls_time 2 -master_pl_publish_rate 30 http://example.com/live/out.m3u8 +@end example + +This example creates HLS master playlist with name master.m3u8 and keep +publishing it repeatedly every after 30 segments i.e. every after 60s. + @end table @anchor{ico} diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 1515b3f359ea6..8cd5ed5937cfa 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -145,6 +145,7 @@ typedef struct VariantStream { AVStream **streams; unsigned int nb_streams; + int m3u8_created; /* status of media play-list creation */ char *baseurl; } VariantStream; @@ -196,7 +197,13 @@ typedef struct HLSContext { VariantStream *var_streams; unsigned int nb_varstreams; + + int master_m3u8_created; /* status of master play-list creation */ + char *master_m3u8_url; /* URL of the master m3u8 file */ + int version; /* HLS version */ char *var_stream_map; /* user specified variant stream map string */ + char *master_pl_name; + unsigned int master_publish_rate; } HLSContext; static int get_int_from_double(double val) @@ -1039,6 +1046,126 @@ static void hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc) oc->filename[len-4] = '\0'; } +static int get_relative_url(const char *master_url, const char *media_url, + char *rel_url, int rel_url_buf_size) +{ + char *p = NULL; + int base_len = -1; + p = strrchr(master_url, '/') ? strrchr(master_url, '/') :\ + strrchr(master_url, '\\'); + if (p) { + base_len = FFABS(p - master_url); + if (av_strncasecmp(master_url, media_url, base_len)) { + av_log(NULL, AV_LOG_WARNING, "Unable to find relative url\n"); + return AVERROR(EINVAL); + } + } + av_strlcpy(rel_url, &(media_url[base_len + 1]), rel_url_buf_size); + return 0; +} + +static int create_master_playlist(AVFormatContext *s, + VariantStream * const input_vs) +{ + HLSContext *hls = s->priv_data; + VariantStream *vs; + AVStream *vid_st, *aud_st; + AVIOContext *master_pb = 0; + AVDictionary *options = NULL; + unsigned int i, j; + int m3u8_name_size, ret, bandwidth; + char *m3U8_rel_name; + + input_vs->m3u8_created = 1; + if (!hls->master_m3u8_created) { + /* For the first time, wait until all the media playlists are created */ + for (i = 0; i < hls->nb_varstreams; i++) + if (!hls->var_streams[i].m3u8_created) + return 0; + } else { + /* Keep publishing the master playlist at the configured rate */ + if (&hls->var_streams[0] != input_vs || !hls->master_publish_rate || + input_vs->number % hls->master_publish_rate) + return 0; + } + + if (hls->user_agent) + av_dict_set(&options, "user-agent", hls->user_agent, 0); + + ret = s->io_open(s, &master_pb, hls->master_m3u8_url, AVIO_FLAG_WRITE,\ + &options); + av_dict_free(&options); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Failed to open master play list file '%s'\n", + hls->master_m3u8_url); + goto fail; + } + + avio_printf(master_pb, "#EXTM3U\n"); + avio_printf(master_pb, "#EXT-X-VERSION:%d\n", hls->version); + + /* For variant streams with video add #EXT-X-STREAM-INF tag with attributes*/ + for (i = 0; i < hls->nb_varstreams; i++) { + vs = &(hls->var_streams[i]); + + m3u8_name_size = strlen(vs->m3u8_name) + 1; + m3U8_rel_name = av_malloc(m3u8_name_size); + if (!m3U8_rel_name) { + ret = AVERROR(ENOMEM); + goto fail; + } + av_strlcpy(m3U8_rel_name, vs->m3u8_name, m3u8_name_size); + ret = get_relative_url(hls->master_m3u8_url, vs->m3u8_name, + m3U8_rel_name, m3u8_name_size); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Unable to find relative URL\n"); + goto fail; + } + + vid_st = NULL; + aud_st = NULL; + for (j = 0; j < vs->nb_streams; j++) { + if (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) + vid_st = vs->streams[j]; + else if (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) + aud_st = vs->streams[j]; + } + + if (!vid_st && !aud_st) { + av_log(NULL, AV_LOG_WARNING, "Media stream not found\n"); + continue; + } + + bandwidth = 0; + if (vid_st) + bandwidth += vid_st->codecpar->bit_rate; + if (aud_st) + bandwidth += aud_st->codecpar->bit_rate; + bandwidth += bandwidth / 10; + + if (!bandwidth) { + av_log(NULL, AV_LOG_WARNING, + "Bandwidth info not available, set audio and video bitrates\n"); + av_freep(&m3U8_rel_name); + continue; + } + + avio_printf(master_pb, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth); + if (vid_st && vid_st->codecpar->width > 0 && vid_st->codecpar->height > 0) + avio_printf(master_pb, ",RESOLUTION=%dx%d", vid_st->codecpar->width, + vid_st->codecpar->height); + avio_printf(master_pb, "\n%s\n\n", m3U8_rel_name); + + av_freep(&m3U8_rel_name); + } +fail: + if(ret >=0) + hls->master_m3u8_created = 1; + av_freep(&m3U8_rel_name); + ff_format_io_close(s, &master_pb); + return ret; +} + static int hls_window(AVFormatContext *s, int last, VariantStream *vs) { HLSContext *hls = s->priv_data; @@ -1049,7 +1176,6 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) AVIOContext *sub_out = NULL; char temp_filename[1024]; int64_t sequence = FFMAX(hls->start_sequence, vs->sequence - vs->nb_entries); - int version = 3; const char *proto = avio_find_protocol_name(s->filename); int use_rename = proto && !strcmp(proto, "file"); static unsigned warned_non_file; @@ -1059,13 +1185,14 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) double prog_date_time = vs->initial_prog_date_time; int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); + hls->version = 3; if (byterange_mode) { - version = 4; + hls->version = 4; sequence = 0; } if (hls->segment_type == SEGMENT_TYPE_FMP4) { - version = 7; + hls->version = 7; } if (!use_rename && !warned_non_file++) @@ -1082,7 +1209,7 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) } vs->discontinuity_set = 0; - write_m3u8_head_block(hls, out, version, target_duration, sequence); + write_m3u8_head_block(hls, out, hls->version, target_duration, sequence); if (hls->pl_type == PLAYLIST_TYPE_EVENT) { avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n"); } else if (hls->pl_type == PLAYLIST_TYPE_VOD) { @@ -1158,7 +1285,7 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) if( vs->vtt_m3u8_name ) { if ((ret = s->io_open(s, &sub_out, vs->vtt_m3u8_name, AVIO_FLAG_WRITE, &options)) < 0) goto fail; - write_m3u8_head_block(hls, sub_out, version, target_duration, sequence); + write_m3u8_head_block(hls, sub_out, hls->version, target_duration, sequence); for (en = vs->segments; en; en = en->next) { avio_printf(sub_out, "#EXTINF:%f,\n", en->duration); @@ -1181,6 +1308,11 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) ff_format_io_close(s, &sub_out); if (ret >= 0 && use_rename) ff_rename(temp_filename, vs->m3u8_name, s); + + if (ret >= 0 && hls->master_pl_name) + if (create_master_playlist(s, vs) < 0) + av_log(s, AV_LOG_WARNING, "Master playlist creation failed\n"); + return ret; } @@ -1509,6 +1641,32 @@ static int update_variant_stream_info(AVFormatContext *s) { return 0; } +static int update_master_pl_info(AVFormatContext *s) { + HLSContext *hls = s->priv_data; + int m3u8_name_size, ret; + char *p; + + m3u8_name_size = strlen(s->filename) + strlen(hls->master_pl_name) + 1; + hls->master_m3u8_url = av_malloc(m3u8_name_size); + if (!hls->master_m3u8_url) { + ret = AVERROR(ENOMEM); + return ret; + } + + av_strlcpy(hls->master_m3u8_url, s->filename, m3u8_name_size); + p = strrchr(hls->master_m3u8_url, '/') ? + strrchr(hls->master_m3u8_url, '/') : + strrchr(hls->master_m3u8_url, '\\'); + if (p) { + *(p + 1) = '\0'; + av_strlcat(hls->master_m3u8_url, hls->master_pl_name, m3u8_name_size); + } else { + av_strlcpy(hls->master_m3u8_url, hls->master_pl_name, m3u8_name_size); + } + + return 0; +} + static int hls_write_header(AVFormatContext *s) { HLSContext *hls = s->priv_data; @@ -1537,6 +1695,15 @@ static int hls_write_header(AVFormatContext *s) goto fail; } + if (hls->master_pl_name) { + ret = update_master_pl_info(s); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n", + ret); + goto fail; + } + } + if (hls->segment_type == SEGMENT_TYPE_FMP4) { pattern = "%d.m4s"; } @@ -1873,9 +2040,9 @@ static int hls_write_header(AVFormatContext *s) avformat_free_context(vs->avf); if (vs->vtt_avf) avformat_free_context(vs->vtt_avf); - } av_freep(&hls->var_streams); + av_freep(&hls->master_m3u8_url); } return ret; } @@ -2112,6 +2279,7 @@ static int hls_write_trailer(struct AVFormatContext *s) av_freep(&hls->key_basename); av_freep(&hls->var_streams); + av_freep(&hls->master_m3u8_url); return 0; } @@ -2167,6 +2335,8 @@ static const AVOption options[] = { {"datetime", "current datetime as YYYYMMDDhhmmss", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME }, INT_MIN, INT_MAX, E, "start_sequence_source_type" }, {"http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"var_stream_map", "Variant stream map string", OFFSET(var_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, + {"master_pl_name", "Create HLS master playlist with this name", OFFSET(master_pl_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, + {"master_pl_publish_rate", "Publish master play list every after this many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E}, { NULL }, }; diff --git a/libavformat/version.h b/libavformat/version.h index 4b7ee260d7f8c..feb1461c416d2 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -33,7 +33,7 @@ // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 #define LIBAVFORMAT_VERSION_MINOR 2 -#define LIBAVFORMAT_VERSION_MICRO 101 +#define LIBAVFORMAT_VERSION_MICRO 102 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From 218ce1f6237b39090015809468f8e933bb09d9b8 Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Mon, 20 Nov 2017 10:05:33 +0800 Subject: [PATCH 0993/2557] tests/fate: addition of test case for hls variant stream creation with master playlist Reviewed-by: Steven Liu --- tests/fate/filter-audio.mak | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak index bd8b3d3c351c2..675169c9ca09c 100644 --- a/tests/fate/filter-audio.mak +++ b/tests/fate/filter-audio.mak @@ -171,6 +171,17 @@ FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FIL fate-filter-hls-append: tests/data/hls-list-append.m3u8 fate-filter-hls-append: CMD = framecrc -flags +bitexact -i $(TARGET_PATH)/tests/data/hls-list-append.m3u8 -af asetpts=RTCTIME +tests/data/hls-vs-with-master.m3u8: TAG = GEN +tests/data/hls-vs-with-master.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -flags +bitexact -codec:a:0 mp2fixed -b:a:0 32k -codec:a:1 mp2fixed -b:a:1 128k -map 0 -map 0 \ + -f hls -var_stream_map "a:0 a:1" -hls_time 10 -master_pl_name hls-master.m3u8 -hls_segment_filename $(TARGET_PATH)/tests/data/hls-vs-with-master-%03d.ts \ + $(TARGET_PATH)/tests/data/hls-vs.m3u8 2>/dev/null + +FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-filter-hls-vs-with-master +fate-filter-hls-vs-with-master: tests/data/hls-vs-with-master.m3u8 +fate-filter-hls-vs-with-master: CMD = run $(FFMPEG) -nostdin -nostats -cpuflags all -flags +bitexact -hwaccel none -threads 1 -thread_type frame+slice -i $(TARGET_PATH)/tests/data/hls-vs_0.m3u8 -af asetpts=RTCTIME -flags +bitexact -fflags +bitexact -f framecrc -; run $(FFMPEG) -nostdin -nostats -cpuflags all -flags +bitexact -hwaccel none -threads 1 -thread_type frame+slice -i $(TARGET_PATH)/tests/data/hls-vs_1.m3u8 -af asetpts=RTCTIME -flags +bitexact -fflags +bitexact -f framecrc -; cat $(TARGET_PATH)/tests/data/hls-master.m3u8 + FATE_AMIX += fate-filter-amix-simple fate-filter-amix-simple: CMD = ffmpeg -filter_complex amix -i $(SRC) -ss 3 -i $(SRC1) -f f32le - fate-filter-amix-simple: REF = $(SAMPLES)/filter/amix_simple.pcm From a30085f5708f16fcf2d133a2120ddf50d8f59c44 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 20 Nov 2017 10:49:42 +0800 Subject: [PATCH 0994/2557] avformat/mp3dec: use FFABS to instead of abs Reviewed-by: Michael Niedermayer Signed-off-by: Steven Liu --- libavformat/mp3dec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/mp3dec.c b/libavformat/mp3dec.c index a5c4f2ea12720..a76fe32e5998a 100644 --- a/libavformat/mp3dec.c +++ b/libavformat/mp3dec.c @@ -508,9 +508,9 @@ static int64_t mp3_sync(AVFormatContext *s, int64_t target_pos, int flags) return AVERROR(EINVAL); } } - if ((target_pos - pos)*dir <= 0 && abs(MIN_VALID/2-j) < score) { + if ((target_pos - pos)*dir <= 0 && FFABS(MIN_VALID/2-j) < score) { candidate = pos; - score = abs(MIN_VALID/2-j); + score = FFABS(MIN_VALID/2-j); } pos += ret; } From cb259467d1ea0320b4150180f0d94b01c5b7e0ed Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 20 Nov 2017 10:50:30 +0800 Subject: [PATCH 0995/2557] avformat/mxf: use FFABS to instead of abs Signed-off-by: Steven Liu --- libavformat/mxf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mxf.c b/libavformat/mxf.c index 5994b09914b61..a909401f08b98 100644 --- a/libavformat/mxf.c +++ b/libavformat/mxf.c @@ -157,7 +157,7 @@ const MXFSamplesPerFrame *ff_mxf_get_samples_per_frame(AVFormatContext *s, int idx = av_find_nearest_q_idx(time_base, mxf_time_base); AVRational diff = av_sub_q(time_base, mxf_time_base[idx]); - diff.num = abs(diff.num); + diff.num = FFABS(diff.num); if (av_cmp_q(diff, (AVRational){1, 1000}) >= 0) return NULL; From 462a14b1e9373bc4e4c535b0417eae5773a6172a Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 20 Nov 2017 10:51:06 +0800 Subject: [PATCH 0996/2557] avformat/swfenc: use FFABS to instead of abs Reviewed-by: Michael Niedermayer Signed-off-by: Steven Liu --- libavformat/swfenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/swfenc.c b/libavformat/swfenc.c index cada45ef9a7bf..f53db0fb2b3ff 100644 --- a/libavformat/swfenc.c +++ b/libavformat/swfenc.c @@ -69,7 +69,7 @@ static inline void max_nbits(int *nbits_ptr, int val) if (val == 0) return; - val = abs(val); + val = FFABS(val); n = 1; while (val != 0) { n++; From 25aff9d8201a7586df2a77fb6914adfc49758b61 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 20 Nov 2017 10:51:57 +0800 Subject: [PATCH 0997/2557] avformat/hlsenc: use FFABS to instead of abs Reviewed-by: Michael Niedermayer Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 8cd5ed5937cfa..3c47ced30d96c 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1264,7 +1264,7 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) tm = gmtime_r(&tt, &tmpbuf); tm->tm_isdst = dst; wrongsecs = mktime(tm); - tz_min = (abs(wrongsecs - tt) + 30) / 60; + tz_min = (FFABS(wrongsecs - tt) + 30) / 60; snprintf(buf1, sizeof(buf1), "%c%02d%02d", wrongsecs <= tt ? '+' : '-', From 185af4ccb1702aa37f1f61fc77c2b37f1b2f4d8d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 20 Nov 2017 10:58:35 +0100 Subject: [PATCH 0998/2557] avfilter/af_extrastereo: fix filtering when clipping is disabled Signed-off-by: Paul B Mahol --- libavfilter/af_extrastereo.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavfilter/af_extrastereo.c b/libavfilter/af_extrastereo.c index a746006f7107f..b07c006f2c5ce 100644 --- a/libavfilter/af_extrastereo.c +++ b/libavfilter/af_extrastereo.c @@ -90,9 +90,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) right = average + mult * (right - average); if (s->clip) { - dst[n * 2 ] = av_clipf(left, -1, 1); - dst[n * 2 + 1] = av_clipf(right, -1, 1); + left = av_clipf(left, -1, 1); + right = av_clipf(right, -1, 1); } + + dst[n * 2 ] = left; + dst[n * 2 + 1] = right; } if (out != in) From 0f75d77a162d2702606c0b079fa9fb65a2629ccb Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Mon, 20 Nov 2017 13:48:28 +0100 Subject: [PATCH 0999/2557] lavf/mov: Do not mix variable declaration and code. Fixes a warning: libavformat/mov.c:1195:5: warning: ISO C90 forbids mixed declarations and code --- libavformat/mov.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 5c9f926bcefc4..0b8f8ad24b998 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1188,11 +1188,12 @@ static void set_frag_stream(MOVFragmentIndex *frag_index, int id) static MOVFragmentStreamInfo * get_current_frag_stream_info( MOVFragmentIndex *frag_index) { + MOVFragmentIndexItem *item; if (frag_index->current < 0 || frag_index->current >= frag_index->nb_items) return NULL; - MOVFragmentIndexItem * item = &frag_index->item[frag_index->current]; + item = &frag_index->item[frag_index->current]; if (item->current >= 0 && item->current < item->nb_stream_info) return &item->stream_info[item->current]; From 200f497997a123066f18eafe0c706516da2f1d4c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 20 Nov 2017 13:23:07 +0100 Subject: [PATCH 1000/2557] avfilter/af_surround: add missing error check Signed-off-by: Paul B Mahol --- libavfilter/af_surround.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libavfilter/af_surround.c b/libavfilter/af_surround.c index e1cb2b3854b73..460e18cd5ada0 100644 --- a/libavfilter/af_surround.c +++ b/libavfilter/af_surround.c @@ -1350,18 +1350,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; AudioSurroundContext *s = ctx->priv; + int ret; - av_audio_fifo_write(s->fifo, (void **)in->extended_data, - in->nb_samples); - - if (s->pts == AV_NOPTS_VALUE) + ret = av_audio_fifo_write(s->fifo, (void **)in->extended_data, + in->nb_samples); + if (ret >= 0 && s->pts == AV_NOPTS_VALUE) s->pts = in->pts; av_frame_free(&in); + if (ret < 0) + return ret; while (av_audio_fifo_size(s->fifo) >= s->buf_size) { AVFrame *out; - int ret; ret = av_audio_fifo_peek(s->fifo, (void **)s->input->extended_data, s->buf_size); if (ret < 0) From d1b284119bd5c6a52124443de2c45dbe569c25fc Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 20 Nov 2017 13:25:39 +0100 Subject: [PATCH 1001/2557] avfilter/af_afir: add missing error check Signed-off-by: Paul B Mahol --- libavfilter/af_afir.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/libavfilter/af_afir.c b/libavfilter/af_afir.c index c4443fdffdd4d..c81a1e22cf1de 100644 --- a/libavfilter/af_afir.c +++ b/libavfilter/af_afir.c @@ -267,11 +267,13 @@ static int read_ir(AVFilterLink *link, AVFrame *frame) { AVFilterContext *ctx = link->dst; AudioFIRContext *s = ctx->priv; - int nb_taps, max_nb_taps; + int nb_taps, max_nb_taps, ret; - av_audio_fifo_write(s->fifo[1], (void **)frame->extended_data, - frame->nb_samples); + ret = av_audio_fifo_write(s->fifo[1], (void **)frame->extended_data, + frame->nb_samples); av_frame_free(&frame); + if (ret < 0) + return ret; nb_taps = av_audio_fifo_size(s->fifo[1]); max_nb_taps = MAX_IR_DURATION * ctx->outputs[0]->sample_rate; @@ -288,15 +290,18 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame) AVFilterContext *ctx = link->dst; AudioFIRContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - int ret = 0; + int ret; - av_audio_fifo_write(s->fifo[0], (void **)frame->extended_data, - frame->nb_samples); - if (s->pts == AV_NOPTS_VALUE) + ret = av_audio_fifo_write(s->fifo[0], (void **)frame->extended_data, + frame->nb_samples); + if (ret > 0 && s->pts == AV_NOPTS_VALUE) s->pts = frame->pts; av_frame_free(&frame); + if (ret < 0) + return ret; + if (!s->have_coeffs && s->eof_coeffs) { ret = convert_coeffs(ctx); if (ret < 0) @@ -307,10 +312,10 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame) while (av_audio_fifo_size(s->fifo[0]) >= s->part_size) { ret = fir_frame(s, outlink); if (ret < 0) - break; + return ret; } } - return ret; + return 0; } static int request_frame(AVFilterLink *outlink) @@ -334,9 +339,11 @@ static int request_frame(AVFilterLink *outlink) if (!silence) return AVERROR(ENOMEM); - av_audio_fifo_write(s->fifo[0], (void **)silence->extended_data, - silence->nb_samples); + ret = av_audio_fifo_write(s->fifo[0], (void **)silence->extended_data, + silence->nb_samples); av_frame_free(&silence); + if (ret < 0) + return ret; s->need_padding = 0; } From 4073046089f59cb6d5d46a2a2ab28f8a59b0f428 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 20 Nov 2017 13:37:24 +0100 Subject: [PATCH 1002/2557] avfilter/af_headphone: add missing error check Signed-off-by: Paul B Mahol --- libavfilter/af_headphone.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/libavfilter/af_headphone.c b/libavfilter/af_headphone.c index 3b76d1d737054..2188f7ab24f56 100644 --- a/libavfilter/af_headphone.c +++ b/libavfilter/af_headphone.c @@ -324,16 +324,19 @@ static int read_ir(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; HeadphoneContext *s = ctx->priv; - int ir_len, max_ir_len, input_number; + int ir_len, max_ir_len, input_number, ret; for (input_number = 0; input_number < s->nb_inputs; input_number++) if (inlink == ctx->inputs[input_number]) break; - av_audio_fifo_write(s->in[input_number].fifo, (void **)frame->extended_data, - frame->nb_samples); + ret = av_audio_fifo_write(s->in[input_number].fifo, (void **)frame->extended_data, + frame->nb_samples); av_frame_free(&frame); + if (ret < 0) + return ret; + ir_len = av_audio_fifo_size(s->in[input_number].fifo); max_ir_len = 65536; if (ir_len > max_ir_len) { @@ -572,13 +575,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterLink *outlink = ctx->outputs[0]; int ret = 0; - av_audio_fifo_write(s->in[0].fifo, (void **)in->extended_data, - in->nb_samples); + ret = av_audio_fifo_write(s->in[0].fifo, (void **)in->extended_data, + in->nb_samples); if (s->pts == AV_NOPTS_VALUE) s->pts = in->pts; av_frame_free(&in); + if (ret < 0) + return ret; + if (!s->have_hrirs && s->eof_hrirs) { ret = convert_coeffs(ctx, inlink); if (ret < 0) @@ -589,10 +595,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) while (av_audio_fifo_size(s->in[0].fifo) >= s->size) { ret = headphone_frame(s, outlink); if (ret < 0) - break; + return ret; } } - return ret; + + return 0; } static int query_formats(AVFilterContext *ctx) From 5c7c0c5b580ea26c1aa83f94ec500105b5c07c31 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 20 Nov 2017 13:42:59 +0100 Subject: [PATCH 1003/2557] avfilter/af_afftfilt: add missing error check Signed-off-by: Paul B Mahol --- libavfilter/af_afftfilt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavfilter/af_afftfilt.c b/libavfilter/af_afftfilt.c index 52755a1fb42d3..7f28e1f77bcdf 100644 --- a/libavfilter/af_afftfilt.c +++ b/libavfilter/af_afftfilt.c @@ -197,8 +197,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) int ch, n, ret, i, j, k; int start = s->start, end = s->end; - av_audio_fifo_write(s->fifo, (void **)frame->extended_data, frame->nb_samples); + ret = av_audio_fifo_write(s->fifo, (void **)frame->extended_data, frame->nb_samples); av_frame_free(&frame); + if (ret < 0) + return ret; while (av_audio_fifo_size(s->fifo) >= window_size) { if (!in) { @@ -316,7 +318,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) } av_frame_free(&in); - return ret; + return ret < 0 ? ret : 0; } static int query_formats(AVFilterContext *ctx) From 16d67fabb1eb781d800b76e7843e39c349f15d24 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 19 Nov 2017 15:34:52 +0100 Subject: [PATCH 1004/2557] avfilter/avfiltergraph: pass correct audio/video flags Previously video flags where set for audio option. Signed-off-by: Paul B Mahol --- libavfilter/avfiltergraph.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index a009e0a760e11..a959a9ef3fdba 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -43,17 +43,19 @@ #include "thread.h" #define OFFSET(x) offsetof(AVFilterGraph, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define F AV_OPT_FLAG_FILTERING_PARAM +#define V AV_OPT_FLAG_VIDEO_PARAM +#define A AV_OPT_FLAG_AUDIO_PARAM static const AVOption filtergraph_options[] = { { "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, - { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, "thread_type" }, - { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .flags = FLAGS, .unit = "thread_type" }, + { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, F|V|A, "thread_type" }, + { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .flags = F|V|A, .unit = "thread_type" }, { "threads", "Maximum number of threads", OFFSET(nb_threads), - AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, F|V|A }, {"scale_sws_opts" , "default scale filter options" , OFFSET(scale_sws_opts) , - AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, + AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, F|V }, {"aresample_swr_opts" , "default aresample filter options" , OFFSET(aresample_swr_opts) , - AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, + AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, F|A }, { NULL }, }; From 4c7b023d56e09a78a587d036db1b64bf7c493b3d Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Sat, 18 Nov 2017 20:29:15 -0800 Subject: [PATCH 1005/2557] avcodec: Refactor common nvdec hwaccel logic The 'simple' hwaccels (not h.264 and hevc) all use the same bitstream management and reference lookup logic so let's refactor all that into common functions. I verified that casting a signed int -1 to unsigned char produces 255 according to the C language specification. --- libavcodec/nvdec.c | 46 ++++++++++++++++++++++++++++++++ libavcodec/nvdec.h | 4 +++ libavcodec/nvdec_mpeg12.c | 53 +++---------------------------------- libavcodec/nvdec_vc1.c | 55 +++++---------------------------------- libavcodec/nvdec_vp9.c | 53 ++++--------------------------------- 5 files changed, 65 insertions(+), 146 deletions(-) diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index 3d62840e9f35b..97ff605f0fc54 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -475,6 +475,36 @@ int ff_nvdec_end_frame(AVCodecContext *avctx) return ret; } +int ff_nvdec_simple_end_frame(AVCodecContext *avctx) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + int ret = ff_nvdec_end_frame(avctx); + ctx->bitstream = NULL; + return ret; +} + +int ff_nvdec_simple_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, + uint32_t size) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + void *tmp; + + tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated, + (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets)); + if (!tmp) + return AVERROR(ENOMEM); + ctx->slice_offsets = tmp; + + if (!ctx->bitstream) + ctx->bitstream = (uint8_t*)buffer; + + ctx->slice_offsets[ctx->nb_slices] = buffer - ctx->bitstream; + ctx->bitstream_len += size; + ctx->nb_slices++; + + return 0; +} + int ff_nvdec_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx, int dpb_size) @@ -520,3 +550,19 @@ int ff_nvdec_frame_params(AVCodecContext *avctx, return 0; } + +int ff_nvdec_get_ref_idx(AVFrame *frame) +{ + FrameDecodeData *fdd; + NVDECFrame *cf; + + if (!frame || !frame->private_ref) + return -1; + + fdd = (FrameDecodeData*)frame->private_ref->data; + cf = (NVDECFrame*)fdd->hwaccel_priv; + if (!cf) + return -1; + + return cf->idx; +} diff --git a/libavcodec/nvdec.h b/libavcodec/nvdec.h index 14d29ee94bae1..90578d5a1c4ee 100644 --- a/libavcodec/nvdec.h +++ b/libavcodec/nvdec.h @@ -58,8 +58,12 @@ int ff_nvdec_decode_init(AVCodecContext *avctx); int ff_nvdec_decode_uninit(AVCodecContext *avctx); int ff_nvdec_start_frame(AVCodecContext *avctx, AVFrame *frame); int ff_nvdec_end_frame(AVCodecContext *avctx); +int ff_nvdec_simple_end_frame(AVCodecContext *avctx); +int ff_nvdec_simple_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, + uint32_t size); int ff_nvdec_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx, int dpb_size); +int ff_nvdec_get_ref_idx(AVFrame *frame); #endif /* AVCODEC_NVDEC_H */ diff --git a/libavcodec/nvdec_mpeg12.c b/libavcodec/nvdec_mpeg12.c index 127e843d85154..db9cebeddd164 100644 --- a/libavcodec/nvdec_mpeg12.c +++ b/libavcodec/nvdec_mpeg12.c @@ -25,22 +25,6 @@ #include "nvdec.h" #include "decode.h" -static int get_ref_idx(AVFrame *frame) -{ - FrameDecodeData *fdd; - NVDECFrame *cf; - - if (!frame || !frame->private_ref) - return -1; - - fdd = (FrameDecodeData*)frame->private_ref->data; - cf = (NVDECFrame*)fdd->hwaccel_priv; - if (!cf) - return -1; - - return cf->idx; -} - static int nvdec_mpeg12_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { MpegEncContext *s = avctx->priv_data; @@ -71,8 +55,8 @@ static int nvdec_mpeg12_start_frame(AVCodecContext *avctx, const uint8_t *buffer s->pict_type == AV_PICTURE_TYPE_P, .CodecSpecific.mpeg2 = { - .ForwardRefIdx = get_ref_idx(s->last_picture.f), - .BackwardRefIdx = get_ref_idx(s->next_picture.f), + .ForwardRefIdx = ff_nvdec_get_ref_idx(s->last_picture.f), + .BackwardRefIdx = ff_nvdec_get_ref_idx(s->next_picture.f), .picture_coding_type = s->pict_type, .full_pel_forward_vector = s->full_pel[0], @@ -99,35 +83,6 @@ static int nvdec_mpeg12_start_frame(AVCodecContext *avctx, const uint8_t *buffer return 0; } -static int nvdec_mpeg12_end_frame(AVCodecContext *avctx) -{ - NVDECContext *ctx = avctx->internal->hwaccel_priv_data; - int ret = ff_nvdec_end_frame(avctx); - ctx->bitstream = NULL; - return ret; -} - -static int nvdec_mpeg12_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) -{ - NVDECContext *ctx = avctx->internal->hwaccel_priv_data; - void *tmp; - - tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated, - (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets)); - if (!tmp) - return AVERROR(ENOMEM); - ctx->slice_offsets = tmp; - - if (!ctx->bitstream) - ctx->bitstream = (uint8_t*)buffer; - - ctx->slice_offsets[ctx->nb_slices] = buffer - ctx->bitstream; - ctx->bitstream_len += size; - ctx->nb_slices++; - - return 0; -} - static int nvdec_mpeg12_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) { @@ -142,8 +97,8 @@ AVHWAccel ff_mpeg2_nvdec_hwaccel = { .id = AV_CODEC_ID_MPEG2VIDEO, .pix_fmt = AV_PIX_FMT_CUDA, .start_frame = nvdec_mpeg12_start_frame, - .end_frame = nvdec_mpeg12_end_frame, - .decode_slice = nvdec_mpeg12_decode_slice, + .end_frame = ff_nvdec_simple_end_frame, + .decode_slice = ff_nvdec_simple_decode_slice, .frame_params = nvdec_mpeg12_frame_params, .init = ff_nvdec_decode_init, .uninit = ff_nvdec_decode_uninit, diff --git a/libavcodec/nvdec_vc1.c b/libavcodec/nvdec_vc1.c index 588a5b9d07b13..c04b153a8615d 100644 --- a/libavcodec/nvdec_vc1.c +++ b/libavcodec/nvdec_vc1.c @@ -25,20 +25,6 @@ #include "decode.h" #include "vc1.h" -static int get_ref_idx(AVFrame *frame) -{ - FrameDecodeData *fdd; - NVDECFrame *cf; - - if (!frame || !frame->private_ref) - return -1; - - fdd = (FrameDecodeData*)frame->private_ref->data; - cf = (NVDECFrame*)fdd->hwaccel_priv; - - return cf->idx; -} - static int nvdec_vc1_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { VC1Context *v = avctx->priv_data; @@ -73,8 +59,8 @@ static int nvdec_vc1_start_frame(AVCodecContext *avctx, const uint8_t *buffer, u s->pict_type == AV_PICTURE_TYPE_P, .CodecSpecific.vc1 = { - .ForwardRefIdx = get_ref_idx(s->last_picture.f), - .BackwardRefIdx = get_ref_idx(s->next_picture.f), + .ForwardRefIdx = ff_nvdec_get_ref_idx(s->last_picture.f), + .BackwardRefIdx = ff_nvdec_get_ref_idx(s->next_picture.f), .FrameWidth = cur_frame->width, .FrameHeight = cur_frame->height, @@ -117,35 +103,6 @@ static int nvdec_vc1_start_frame(AVCodecContext *avctx, const uint8_t *buffer, u return 0; } -static int nvdec_vc1_end_frame(AVCodecContext *avctx) -{ - NVDECContext *ctx = avctx->internal->hwaccel_priv_data; - int ret = ff_nvdec_end_frame(avctx); - ctx->bitstream = NULL; - return ret; -} - -static int nvdec_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) -{ - NVDECContext *ctx = avctx->internal->hwaccel_priv_data; - void *tmp; - - tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated, - (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets)); - if (!tmp) - return AVERROR(ENOMEM); - ctx->slice_offsets = tmp; - - if (!ctx->bitstream) - ctx->bitstream = (uint8_t*)buffer; - - ctx->slice_offsets[ctx->nb_slices] = buffer - ctx->bitstream; - ctx->bitstream_len += size; - ctx->nb_slices++; - - return 0; -} - static int nvdec_vc1_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) { @@ -159,8 +116,8 @@ AVHWAccel ff_vc1_nvdec_hwaccel = { .id = AV_CODEC_ID_VC1, .pix_fmt = AV_PIX_FMT_CUDA, .start_frame = nvdec_vc1_start_frame, - .end_frame = nvdec_vc1_end_frame, - .decode_slice = nvdec_vc1_decode_slice, + .end_frame = ff_nvdec_simple_end_frame, + .decode_slice = ff_nvdec_simple_decode_slice, .frame_params = nvdec_vc1_frame_params, .init = ff_nvdec_decode_init, .uninit = ff_nvdec_decode_uninit, @@ -174,8 +131,8 @@ AVHWAccel ff_wmv3_nvdec_hwaccel = { .id = AV_CODEC_ID_WMV3, .pix_fmt = AV_PIX_FMT_CUDA, .start_frame = nvdec_vc1_start_frame, - .end_frame = nvdec_vc1_end_frame, - .decode_slice = nvdec_vc1_decode_slice, + .end_frame = ff_nvdec_simple_end_frame, + .decode_slice = ff_nvdec_simple_decode_slice, .frame_params = nvdec_vc1_frame_params, .init = ff_nvdec_decode_init, .uninit = ff_nvdec_decode_uninit, diff --git a/libavcodec/nvdec_vp9.c b/libavcodec/nvdec_vp9.c index 06c13e6f033b3..ed06d9141603e 100644 --- a/libavcodec/nvdec_vp9.c +++ b/libavcodec/nvdec_vp9.c @@ -28,20 +28,6 @@ #include "internal.h" #include "vp9shared.h" -static unsigned char get_ref_idx(AVFrame *frame) -{ - FrameDecodeData *fdd; - NVDECFrame *cf; - - if (!frame || !frame->private_ref) - return 255; - - fdd = (FrameDecodeData*)frame->private_ref->data; - cf = (NVDECFrame*)fdd->hwaccel_priv; - - return cf->idx; -} - static int nvdec_vp9_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { VP9SharedContext *h = avctx->priv_data; @@ -72,9 +58,9 @@ static int nvdec_vp9_start_frame(AVCodecContext *avctx, const uint8_t *buffer, u .width = cur_frame->width, .height = cur_frame->height, - .LastRefIdx = get_ref_idx(h->refs[h->h.refidx[0]].f), - .GoldenRefIdx = get_ref_idx(h->refs[h->h.refidx[1]].f), - .AltRefIdx = get_ref_idx(h->refs[h->h.refidx[2]].f), + .LastRefIdx = ff_nvdec_get_ref_idx(h->refs[h->h.refidx[0]].f), + .GoldenRefIdx = ff_nvdec_get_ref_idx(h->refs[h->h.refidx[1]].f), + .AltRefIdx = ff_nvdec_get_ref_idx(h->refs[h->h.refidx[2]].f), .profile = h->h.profile, .frameContextIdx = h->h.framectxid, @@ -176,35 +162,6 @@ static int nvdec_vp9_start_frame(AVCodecContext *avctx, const uint8_t *buffer, u return 0; } -static int nvdec_vp9_end_frame(AVCodecContext *avctx) -{ - NVDECContext *ctx = avctx->internal->hwaccel_priv_data; - int ret = ff_nvdec_end_frame(avctx); - ctx->bitstream = NULL; - return ret; -} - -static int nvdec_vp9_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) -{ - NVDECContext *ctx = avctx->internal->hwaccel_priv_data; - void *tmp; - - tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated, - (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets)); - if (!tmp) - return AVERROR(ENOMEM); - ctx->slice_offsets = tmp; - - if (!ctx->bitstream) - ctx->bitstream = (uint8_t*)buffer; - - ctx->slice_offsets[ctx->nb_slices] = buffer - ctx->bitstream; - ctx->bitstream_len += size; - ctx->nb_slices++; - - return 0; -} - static int nvdec_vp9_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) { @@ -218,8 +175,8 @@ AVHWAccel ff_vp9_nvdec_hwaccel = { .id = AV_CODEC_ID_VP9, .pix_fmt = AV_PIX_FMT_CUDA, .start_frame = nvdec_vp9_start_frame, - .end_frame = nvdec_vp9_end_frame, - .decode_slice = nvdec_vp9_decode_slice, + .end_frame = ff_nvdec_simple_end_frame, + .decode_slice = ff_nvdec_simple_decode_slice, .frame_params = nvdec_vp9_frame_params, .init = ff_nvdec_decode_init, .uninit = ff_nvdec_decode_uninit, From 8bca292c3045a7f372299f71c8d88b541fe2a816 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Thu, 16 Nov 2017 07:38:10 -0800 Subject: [PATCH 1006/2557] avcodec: Implement mpeg1 nvdec hwaccel Once I remembered that there's a separate decoder type for mpeg1, even though params struct is shared with mpeg2, everything worked. --- Changelog | 2 +- configure | 2 ++ libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/mpeg12dec.c | 3 +++ libavcodec/nvdec.c | 1 + libavcodec/nvdec_mpeg12.c | 18 +++++++++++++++++- libavcodec/version.h | 2 +- 8 files changed, 27 insertions(+), 3 deletions(-) diff --git a/Changelog b/Changelog index e1f8a648b0cb8..5a9d183aeda23 100644 --- a/Changelog +++ b/Changelog @@ -13,7 +13,7 @@ version : - PCE support for extended channel layouts in the AAC encoder - native aptX encoder and decoder - Raw aptX muxer and demuxer -- NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-2, VC1 and VP9 hwaccel decoding +- NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-1/2, VC1 and VP9 hwaccel decoding - Intel QSV-accelerated overlay filter - mcompand audio filter - acontrast audio filter diff --git a/configure b/configure index 8262358138b1c..7ac9a8d3918a2 100755 --- a/configure +++ b/configure @@ -2704,6 +2704,8 @@ mjpeg_cuvid_hwaccel_select="mjpeg_cuvid_decoder" mpeg_xvmc_hwaccel_deps="xvmc" mpeg_xvmc_hwaccel_select="mpeg2video_decoder" mpeg1_cuvid_hwaccel_select="mpeg1_cuvid_decoder" +mpeg1_nvdec_hwaccel_deps="nvdec" +mpeg1_nvdec_hwaccel_select="mpeg1video_decoder" mpeg1_vdpau_hwaccel_deps="vdpau" mpeg1_vdpau_hwaccel_select="mpeg1video_decoder" mpeg1_videotoolbox_hwaccel_deps="videotoolbox" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 494c76da76a65..0573454c7bff1 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -849,6 +849,7 @@ OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec_h2645.o OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o +OBJS-$(CONFIG_MPEG1_NVDEC_HWACCEL) += nvdec_mpeg12.o OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL) += vdpau_mpeg12.o OBJS-$(CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_MPEG1_XVMC_HWACCEL) += mpegvideo_xvmc.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index e0adb7195131b..e9df7049de2a1 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -87,6 +87,7 @@ static void register_all(void) REGISTER_HWACCEL(HEVC_VIDEOTOOLBOX, hevc_videotoolbox); REGISTER_HWACCEL(MJPEG_CUVID, mjpeg_cuvid); REGISTER_HWACCEL(MPEG1_CUVID, mpeg1_cuvid); + REGISTER_HWACCEL(MPEG1_NVDEC, mpeg1_nvdec); REGISTER_HWACCEL(MPEG1_XVMC, mpeg1_xvmc); REGISTER_HWACCEL(MPEG1_VDPAU, mpeg1_vdpau); REGISTER_HWACCEL(MPEG1_VIDEOTOOLBOX, mpeg1_videotoolbox); diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 2b213eebcd016..5a51d09bb07df 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -1130,6 +1130,9 @@ static void quant_matrix_rebuild(uint16_t *matrix, const uint8_t *old_perm, } static const enum AVPixelFormat mpeg1_hwaccel_pixfmt_list_420[] = { +#if CONFIG_MPEG1_NVDEC_HWACCEL + AV_PIX_FMT_CUDA, +#endif #if CONFIG_MPEG1_XVMC_HWACCEL AV_PIX_FMT_XVMC, #endif diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index 97ff605f0fc54..d5cf1058cb7b4 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -54,6 +54,7 @@ static int map_avcodec_id(enum AVCodecID id) switch (id) { case AV_CODEC_ID_H264: return cudaVideoCodec_H264; case AV_CODEC_ID_HEVC: return cudaVideoCodec_HEVC; + case AV_CODEC_ID_MPEG1VIDEO: return cudaVideoCodec_MPEG1; case AV_CODEC_ID_MPEG2VIDEO: return cudaVideoCodec_MPEG2; case AV_CODEC_ID_VC1: return cudaVideoCodec_VC1; case AV_CODEC_ID_VP9: return cudaVideoCodec_VP9; diff --git a/libavcodec/nvdec_mpeg12.c b/libavcodec/nvdec_mpeg12.c index db9cebeddd164..e29d085a79445 100644 --- a/libavcodec/nvdec_mpeg12.c +++ b/libavcodec/nvdec_mpeg12.c @@ -1,5 +1,5 @@ /* - * MPEG-2 HW decode acceleration through NVDEC + * MPEG-1/2 HW decode acceleration through NVDEC * * Copyright (c) 2017 Philip Langdale * @@ -105,3 +105,19 @@ AVHWAccel ff_mpeg2_nvdec_hwaccel = { .priv_data_size = sizeof(NVDECContext), }; #endif + +#if CONFIG_MPEG1_NVDEC_HWACCEL +AVHWAccel ff_mpeg1_nvdec_hwaccel = { + .name = "mpeg1_nvdec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG1VIDEO, + .pix_fmt = AV_PIX_FMT_CUDA, + .start_frame = nvdec_mpeg12_start_frame, + .end_frame = ff_nvdec_simple_end_frame, + .decode_slice = ff_nvdec_simple_decode_slice, + .frame_params = nvdec_mpeg12_frame_params, + .init = ff_nvdec_decode_init, + .uninit = ff_nvdec_decode_uninit, + .priv_data_size = sizeof(NVDECContext), +}; +#endif diff --git a/libavcodec/version.h b/libavcodec/version.h index 5b25a9a8ac25b..ff54670ea90b6 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 3 -#define LIBAVCODEC_VERSION_MICRO 103 +#define LIBAVCODEC_VERSION_MICRO 104 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 6b77a10e43e1a8ed8ead20f344485d400440055c Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Wed, 15 Nov 2017 20:59:29 -0800 Subject: [PATCH 1007/2557] avcodec: Implement mpeg4 nvdec hwaccel This was predictably nightmarish, given how ridiculous mpeg4 is. I had to stare at the cuvid parser output for a long time to work out what each field was supposed to be, and even then, I still don't fully understand some of them. Particularly: vop_coded: If I'm reading the decoder correctly, this flag will always be 1 as the decoder will not pass the hwaccel any frame where it is not 1. divx_flags: There's obviously no documentation on what the possible flags are. I simply observed that this is '0' for a normal bitstream and '5' for packed b-frames. gmc_enabled: I had a number of guesses as to what this mapped to. I picked the condition I did based on when the cuvid parser was setting flag. Also note that as with the vdpau hwaccel, the decoder needs to consume the entire frame and not the slice. --- Changelog | 2 +- configure | 2 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/h263dec.c | 3 + libavcodec/nvdec.c | 1 + libavcodec/nvdec_mpeg4.c | 121 +++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 8 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 libavcodec/nvdec_mpeg4.c diff --git a/Changelog b/Changelog index 5a9d183aeda23..74ed35cfe6ba8 100644 --- a/Changelog +++ b/Changelog @@ -13,7 +13,7 @@ version : - PCE support for extended channel layouts in the AAC encoder - native aptX encoder and decoder - Raw aptX muxer and demuxer -- NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-1/2, VC1 and VP9 hwaccel decoding +- NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-1/2/4, VC1 and VP9 hwaccel decoding - Intel QSV-accelerated overlay filter - mcompand audio filter - acontrast audio filter diff --git a/configure b/configure index 7ac9a8d3918a2..25c3124ca6021 100755 --- a/configure +++ b/configure @@ -2735,6 +2735,8 @@ mpeg2_xvmc_hwaccel_select="mpeg2video_decoder" mpeg4_cuvid_hwaccel_select="mpeg4_cuvid_decoder" mpeg4_mediacodec_hwaccel_deps="mediacodec" mpeg4_mmal_hwaccel_deps="mmal" +mpeg4_nvdec_hwaccel_deps="nvdec" +mpeg4_nvdec_hwaccel_select="mpeg4_decoder" mpeg4_vaapi_hwaccel_deps="vaapi" mpeg4_vaapi_hwaccel_select="mpeg4_decoder" mpeg4_vdpau_hwaccel_deps="vdpau" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 0573454c7bff1..2af957ab7279e 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -861,6 +861,7 @@ OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o OBJS-$(CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_MPEG2_XVMC_HWACCEL) += mpegvideo_xvmc.o +OBJS-$(CONFIG_MPEG4_NVDEC_HWACCEL) += nvdec_mpeg4.o OBJS-$(CONFIG_MPEG4_VAAPI_HWACCEL) += vaapi_mpeg4.o OBJS-$(CONFIG_MPEG4_VDPAU_HWACCEL) += vdpau_mpeg4.o OBJS-$(CONFIG_MPEG4_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index e9df7049de2a1..85c38c83aa467 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -106,6 +106,7 @@ static void register_all(void) REGISTER_HWACCEL(MPEG4_CUVID, mpeg4_cuvid); REGISTER_HWACCEL(MPEG4_MEDIACODEC, mpeg4_mediacodec); REGISTER_HWACCEL(MPEG4_MMAL, mpeg4_mmal); + REGISTER_HWACCEL(MPEG4_NVDEC, mpeg4_nvdec); REGISTER_HWACCEL(MPEG4_VAAPI, mpeg4_vaapi); REGISTER_HWACCEL(MPEG4_VDPAU, mpeg4_vdpau); REGISTER_HWACCEL(MPEG4_VIDEOTOOLBOX, mpeg4_videotoolbox); diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index c7cf4bc0c2e3f..b222de793b8c4 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -714,6 +714,9 @@ const enum AVPixelFormat ff_h263_hwaccel_pixfmt_list_420[] = { #if CONFIG_H263_VAAPI_HWACCEL || CONFIG_MPEG4_VAAPI_HWACCEL AV_PIX_FMT_VAAPI, #endif +#if CONFIG_MPEG4_NVDEC_HWACCEL + AV_PIX_FMT_CUDA, +#endif #if CONFIG_MPEG4_VDPAU_HWACCEL AV_PIX_FMT_VDPAU, #endif diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index d5cf1058cb7b4..efcd47a7f752e 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -56,6 +56,7 @@ static int map_avcodec_id(enum AVCodecID id) case AV_CODEC_ID_HEVC: return cudaVideoCodec_HEVC; case AV_CODEC_ID_MPEG1VIDEO: return cudaVideoCodec_MPEG1; case AV_CODEC_ID_MPEG2VIDEO: return cudaVideoCodec_MPEG2; + case AV_CODEC_ID_MPEG4: return cudaVideoCodec_MPEG4; case AV_CODEC_ID_VC1: return cudaVideoCodec_VC1; case AV_CODEC_ID_VP9: return cudaVideoCodec_VP9; case AV_CODEC_ID_WMV3: return cudaVideoCodec_VC1; diff --git a/libavcodec/nvdec_mpeg4.c b/libavcodec/nvdec_mpeg4.c new file mode 100644 index 0000000000000..a0f9280ea22e6 --- /dev/null +++ b/libavcodec/nvdec_mpeg4.c @@ -0,0 +1,121 @@ +/* + * MPEG-4 Part 2 HW decode acceleration through NVDEC + * + * Copyright (c) 2017 Philip Langdale + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "mpeg4video.h" +#include "nvdec.h" +#include "decode.h" + +static int nvdec_mpeg4_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + Mpeg4DecContext *m = avctx->priv_data; + MpegEncContext *s = &m->m; + + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + CUVIDPICPARAMS *pp = &ctx->pic_params; + CUVIDMPEG4PICPARAMS *ppc = &pp->CodecSpecific.mpeg4; + FrameDecodeData *fdd; + NVDECFrame *cf; + AVFrame *cur_frame = s->current_picture.f; + + int ret, i; + + ret = ff_nvdec_start_frame(avctx, cur_frame); + if (ret < 0) + return ret; + + fdd = (FrameDecodeData*)cur_frame->private_ref->data; + cf = (NVDECFrame*)fdd->hwaccel_priv; + + *pp = (CUVIDPICPARAMS) { + .PicWidthInMbs = (cur_frame->width + 15) / 16, + .FrameHeightInMbs = (cur_frame->height + 15) / 16, + .CurrPicIdx = cf->idx, + + .intra_pic_flag = s->pict_type == AV_PICTURE_TYPE_I, + .ref_pic_flag = s->pict_type == AV_PICTURE_TYPE_I || + s->pict_type == AV_PICTURE_TYPE_P || + s->pict_type == AV_PICTURE_TYPE_S, + + .CodecSpecific.mpeg4 = { + .ForwardRefIdx = ff_nvdec_get_ref_idx(s->last_picture.f), + .BackwardRefIdx = ff_nvdec_get_ref_idx(s->next_picture.f), + + .video_object_layer_width = s->width, + .video_object_layer_height = s->height, + .vop_time_increment_bitcount = m->time_increment_bits, + .top_field_first = s->top_field_first, + .resync_marker_disable = !m->resync_marker, + .quant_type = s->mpeg_quant, + .quarter_sample = s->quarter_sample, + .short_video_header = avctx->codec->id == AV_CODEC_ID_H263, + .divx_flags = s->divx_packed ? 5 : 0, + + .vop_coding_type = s->pict_type - AV_PICTURE_TYPE_I, + .vop_coded = 1, + .vop_rounding_type = s->no_rounding, + .alternate_vertical_scan_flag = s->alternate_scan, + .interlaced = !s->progressive_sequence, + .vop_fcode_forward = s->f_code, + .vop_fcode_backward = s->b_code, + .trd = { s->pp_time, s->pp_field_time >> 1 }, + .trb = { s->pb_time, s->pb_field_time >> 1 }, + + .gmc_enabled = s->pict_type == AV_PICTURE_TYPE_S && + m->vol_sprite_usage == GMC_SPRITE, + } + }; + + for (i = 0; i < 64; ++i) { + ppc->QuantMatrixIntra[i] = s->intra_matrix[i]; + ppc->QuantMatrixInter[i] = s->inter_matrix[i]; + } + + // We need to pass the full frame buffer and not just the slice + return ff_nvdec_simple_decode_slice(avctx, buffer, size); +} + +static int nvdec_mpeg4_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + return 0; +} + +static int nvdec_mpeg4_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) +{ + // Each frame can at most have one P and one B reference + return ff_nvdec_frame_params(avctx, hw_frames_ctx, 2); +} + +AVHWAccel ff_mpeg4_nvdec_hwaccel = { + .name = "mpeg4_nvdec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG4, + .pix_fmt = AV_PIX_FMT_CUDA, + .start_frame = nvdec_mpeg4_start_frame, + .end_frame = ff_nvdec_simple_end_frame, + .decode_slice = nvdec_mpeg4_decode_slice, + .frame_params = nvdec_mpeg4_frame_params, + .init = ff_nvdec_decode_init, + .uninit = ff_nvdec_decode_uninit, + .priv_data_size = sizeof(NVDECContext), +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index ff54670ea90b6..c8550bca9a575 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 3 -#define LIBAVCODEC_VERSION_MICRO 104 +#define LIBAVCODEC_VERSION_MICRO 105 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 3db5961727d300ed048f1fae87e3e4fd339b8456 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 20 Nov 2017 08:36:45 +0800 Subject: [PATCH 1008/2557] hwcontext_vaapi: add the fourcc of I420 format map. VA-API 2.0 have enable the I420, so enable this map. Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- libavutil/hwcontext_vaapi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 0382eb06f2ca8..fcff25dc9b822 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -101,7 +101,9 @@ static const struct { MAP(NV12, YUV420, NV12), MAP(YV12, YUV420, YUV420P), // With U/V planes swapped. MAP(IYUV, YUV420, YUV420P), - //MAP(I420, YUV420, YUV420P), // Not in libva but used by Intel driver. +#ifdef VA_FOURCC_I420 + MAP(I420, YUV420, YUV420P), +#endif #ifdef VA_FOURCC_YV16 MAP(YV16, YUV422, YUV422P), // With U/V planes swapped. #endif From 0f0b2ece38de61be28df270a27d1c959e44336d6 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Mon, 20 Nov 2017 04:14:32 -0500 Subject: [PATCH 1009/2557] lavu/qsv: remove unused variable Fixes build warning of "variable 's' is declared but not used" Signed-off-by: Zhong Li Signed-off-by: Mark Thompson --- libavutil/hwcontext_qsv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 8e43420e70426..9b6040ba9e6db 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -989,7 +989,6 @@ static int qsv_device_derive_from_child(AVHWDeviceContext *ctx, int flags) { AVQSVDeviceContext *hwctx = ctx->hwctx; - QSVDeviceContext *s = ctx->internal->priv; mfxVersion ver = { { 3, 1 } }; mfxHDL handle; From 81c615f0feb2a871b75c7fa6d895e7e92a570f7c Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Mon, 20 Nov 2017 04:14:33 -0500 Subject: [PATCH 1010/2557] lavf/qsv_overlay: check the return value of ff_formats_ref() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the build warning of "ignoring return value of ‘ff_formats_ref’, declared with attribute warn_unused_result" Signed-off-by: Zhong Li Reviewed-by: Carl Eugen Hoyos Signed-off-by: Mark Thompson --- libavfilter/vf_overlay_qsv.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_overlay_qsv.c b/libavfilter/vf_overlay_qsv.c index 1f50d4bb21469..6c3efdbeb5f5a 100644 --- a/libavfilter/vf_overlay_qsv.c +++ b/libavfilter/vf_overlay_qsv.c @@ -415,6 +415,7 @@ static void overlay_qsv_uninit(AVFilterContext *ctx) static int overlay_qsv_query_formats(AVFilterContext *ctx) { int i; + int ret; static const enum AVPixelFormat main_in_fmts[] = { AV_PIX_FMT_YUV420P, @@ -430,10 +431,15 @@ static int overlay_qsv_query_formats(AVFilterContext *ctx) AV_PIX_FMT_NONE }; - for (i = 0; i < ctx->nb_inputs; i++) - ff_formats_ref(ff_make_format_list(main_in_fmts), &ctx->inputs[i]->out_formats); + for (i = 0; i < ctx->nb_inputs; i++) { + ret = ff_formats_ref(ff_make_format_list(main_in_fmts), &ctx->inputs[i]->out_formats); + if (ret < 0) + return ret; + } - ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats); + ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats); + if (ret < 0) + return ret; return 0; } From f7d77b4112f70a15552fbce2ce3d10a4186571b1 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Mon, 20 Nov 2017 04:14:34 -0500 Subject: [PATCH 1011/2557] lavf/qsv_vpp: check the return value of ff_formats_ref() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the build warning of "ignoring return value of ‘ff_formats_ref’, declared with attribute warn_unused_result" Signed-off-by: Zhong Li Reviewed-by: Carl Eugen Hoyos Signed-off-by: Mark Thompson --- libavfilter/vf_vpp_qsv.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index eb2f1cc7eb8e5..bd5fc322991b7 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -332,6 +332,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) static int query_formats(AVFilterContext *ctx) { + int ret; AVFilterFormats *in_fmts, *out_fmts; static const enum AVPixelFormat in_pix_fmts[] = { AV_PIX_FMT_YUV420P, @@ -349,8 +350,12 @@ static int query_formats(AVFilterContext *ctx) in_fmts = ff_make_format_list(in_pix_fmts); out_fmts = ff_make_format_list(out_pix_fmts); - ff_formats_ref(in_fmts, &ctx->inputs[0]->out_formats); - ff_formats_ref(out_fmts, &ctx->outputs[0]->in_formats); + ret = ff_formats_ref(in_fmts, &ctx->inputs[0]->out_formats); + if (ret < 0) + return ret; + ret = ff_formats_ref(out_fmts, &ctx->outputs[0]->in_formats); + if (ret < 0) + return ret; return 0; } From 1dc483a6f2d88e22f47da8584ca74de38262b742 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 18 Nov 2017 17:16:14 +0000 Subject: [PATCH 1012/2557] compat/cuda: Pass a logging context to load functions Reviewed-by: Timo Rothenpieler --- compat/cuda/dynlink_loader.h | 18 +++++++++--------- libavcodec/cuviddec.c | 2 +- libavcodec/nvdec.c | 2 +- libavcodec/nvenc.c | 4 ++-- libavutil/hwcontext_cuda.c | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compat/cuda/dynlink_loader.h b/compat/cuda/dynlink_loader.h index 7d2c87449e1e0..fa43782c9ac48 100644 --- a/compat/cuda/dynlink_loader.h +++ b/compat/cuda/dynlink_loader.h @@ -59,29 +59,29 @@ #define LOAD_LIBRARY(l, path) \ do { \ if (!((l) = dlopen(path, RTLD_LAZY))) { \ - av_log(NULL, AV_LOG_ERROR, "Cannot load %s\n", path); \ + av_log(logctx, AV_LOG_ERROR, "Cannot load %s\n", path); \ ret = AVERROR_UNKNOWN; \ goto error; \ } \ - av_log(NULL, AV_LOG_TRACE, "Loaded lib: %s\n", path); \ + av_log(logctx, AV_LOG_TRACE, "Loaded lib: %s\n", path); \ } while (0) #define LOAD_SYMBOL(fun, tp, symbol) \ do { \ if (!((f->fun) = (tp*)dlsym(f->lib, symbol))) { \ - av_log(NULL, AV_LOG_ERROR, "Cannot load %s\n", symbol); \ + av_log(logctx, AV_LOG_ERROR, "Cannot load %s\n", symbol); \ ret = AVERROR_UNKNOWN; \ goto error; \ } \ - av_log(NULL, AV_LOG_TRACE, "Loaded sym: %s\n", symbol); \ + av_log(logctx, AV_LOG_TRACE, "Loaded sym: %s\n", symbol); \ } while (0) #define LOAD_SYMBOL_OPT(fun, tp, symbol) \ do { \ if (!((f->fun) = (tp*)dlsym(f->lib, symbol))) { \ - av_log(NULL, AV_LOG_DEBUG, "Cannot load optional %s\n", symbol); \ + av_log(logctx, AV_LOG_DEBUG, "Cannot load optional %s\n", symbol); \ } else { \ - av_log(NULL, AV_LOG_TRACE, "Loaded sym: %s\n", symbol); \ + av_log(logctx, AV_LOG_TRACE, "Loaded sym: %s\n", symbol); \ } \ } while (0) @@ -187,7 +187,7 @@ static inline void nvenc_free_functions(NvencFunctions **functions) } #ifdef AV_COMPAT_DYNLINK_CUDA_H -static inline int cuda_load_functions(CudaFunctions **functions) +static inline int cuda_load_functions(CudaFunctions **functions, void *logctx) { GENERIC_LOAD_FUNC_PREAMBLE(CudaFunctions, cuda, CUDA_LIBNAME); @@ -210,7 +210,7 @@ static inline int cuda_load_functions(CudaFunctions **functions) } #endif -static inline int cuvid_load_functions(CuvidFunctions **functions) +static inline int cuvid_load_functions(CuvidFunctions **functions, void *logctx) { GENERIC_LOAD_FUNC_PREAMBLE(CuvidFunctions, cuvid, NVCUVID_LIBNAME); @@ -244,7 +244,7 @@ static inline int cuvid_load_functions(CuvidFunctions **functions) GENERIC_LOAD_FUNC_FINALE(cuvid); } -static inline int nvenc_load_functions(NvencFunctions **functions) +static inline int nvenc_load_functions(NvencFunctions **functions, void *logctx) { GENERIC_LOAD_FUNC_PREAMBLE(NvencFunctions, nvenc, NVENC_LIBNAME); diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index 6370348639776..806dab2074e9d 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -835,7 +835,7 @@ static av_cold int cuvid_decode_init(AVCodecContext *avctx) goto error; } - ret = cuvid_load_functions(&ctx->cvdl); + ret = cuvid_load_functions(&ctx->cvdl, avctx); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Failed loading nvcuvid.\n"); goto error; diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index efcd47a7f752e..0a39927031c16 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -176,7 +176,7 @@ static int nvdec_decoder_create(AVBufferRef **out, AVBufferRef *hw_device_ref, decoder->cuda_ctx = device_hwctx->cuda_ctx; decoder->cudl = device_hwctx->internal->cuda_dl; - ret = cuvid_load_functions(&decoder->cvdl); + ret = cuvid_load_functions(&decoder->cvdl, logctx); if (ret < 0) { av_log(logctx, AV_LOG_ERROR, "Failed loading nvcuvid.\n"); goto fail; diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index e07280b568274..79f7dce5f137e 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -133,11 +133,11 @@ static av_cold int nvenc_load_libraries(AVCodecContext *avctx) uint32_t nvenc_max_ver; int ret; - ret = cuda_load_functions(&dl_fn->cuda_dl); + ret = cuda_load_functions(&dl_fn->cuda_dl, avctx); if (ret < 0) return ret; - ret = nvenc_load_functions(&dl_fn->nvenc_dl); + ret = nvenc_load_functions(&dl_fn->nvenc_dl, avctx); if (ret < 0) { nvenc_print_driver_requirement(avctx, AV_LOG_ERROR); return ret; diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c index dfb67bc941e27..37827a770c3a6 100644 --- a/libavutil/hwcontext_cuda.c +++ b/libavutil/hwcontext_cuda.c @@ -336,7 +336,7 @@ static int cuda_device_init(AVHWDeviceContext *ctx) } if (!hwctx->internal->cuda_dl) { - ret = cuda_load_functions(&hwctx->internal->cuda_dl); + ret = cuda_load_functions(&hwctx->internal->cuda_dl, ctx); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Could not dynamically load CUDA\n"); goto error; From 9302d77525da43b98b919cc78443768fc1798961 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 21 Nov 2017 00:22:25 +0800 Subject: [PATCH 1013/2557] Revert "tests/fate: addition of test case for hls variant stream creation with master playlist" This reverts commit 218ce1f6237b39090015809468f8e933bb09d9b8. --- tests/fate/filter-audio.mak | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak index 675169c9ca09c..bd8b3d3c351c2 100644 --- a/tests/fate/filter-audio.mak +++ b/tests/fate/filter-audio.mak @@ -171,17 +171,6 @@ FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FIL fate-filter-hls-append: tests/data/hls-list-append.m3u8 fate-filter-hls-append: CMD = framecrc -flags +bitexact -i $(TARGET_PATH)/tests/data/hls-list-append.m3u8 -af asetpts=RTCTIME -tests/data/hls-vs-with-master.m3u8: TAG = GEN -tests/data/hls-vs-with-master.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ - -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -flags +bitexact -codec:a:0 mp2fixed -b:a:0 32k -codec:a:1 mp2fixed -b:a:1 128k -map 0 -map 0 \ - -f hls -var_stream_map "a:0 a:1" -hls_time 10 -master_pl_name hls-master.m3u8 -hls_segment_filename $(TARGET_PATH)/tests/data/hls-vs-with-master-%03d.ts \ - $(TARGET_PATH)/tests/data/hls-vs.m3u8 2>/dev/null - -FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-filter-hls-vs-with-master -fate-filter-hls-vs-with-master: tests/data/hls-vs-with-master.m3u8 -fate-filter-hls-vs-with-master: CMD = run $(FFMPEG) -nostdin -nostats -cpuflags all -flags +bitexact -hwaccel none -threads 1 -thread_type frame+slice -i $(TARGET_PATH)/tests/data/hls-vs_0.m3u8 -af asetpts=RTCTIME -flags +bitexact -fflags +bitexact -f framecrc -; run $(FFMPEG) -nostdin -nostats -cpuflags all -flags +bitexact -hwaccel none -threads 1 -thread_type frame+slice -i $(TARGET_PATH)/tests/data/hls-vs_1.m3u8 -af asetpts=RTCTIME -flags +bitexact -fflags +bitexact -f framecrc -; cat $(TARGET_PATH)/tests/data/hls-master.m3u8 - FATE_AMIX += fate-filter-amix-simple fate-filter-amix-simple: CMD = ffmpeg -filter_complex amix -i $(SRC) -ss 3 -i $(SRC1) -f f32le - fate-filter-amix-simple: REF = $(SAMPLES)/filter/amix_simple.pcm From 259dc4e01381c0d01fb1dbb8509c5087d621a0d7 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Wed, 15 Nov 2017 12:50:31 -0800 Subject: [PATCH 1014/2557] libavcodec/videotoolbox: fix decoding of h264 streams with minor SPS changes Previously the codec kept an entire copy of the SPS, and restarted the VT decoder session whenever it changed. This fixed decoding errors in [1], as described in 9519983c. On further inspection, that sample features an SPS change from High/4.0 to High/3.2 while moving from one scene to another. Yesterday I received [2], which contains minor SPS changes where the profile and level do not change. These occur frequently and are not associated with scene changes. After 9519983c, the VT decoder session is recreated unnecessarily when these are encountered causing visual glitches. This commit simplifies the state kept in the VTContext to include just the first three bytes of the SPS, containing the profile and level details. This is populated initially when the VT decoder session is created, and used to detect changes and force a restart. This means minor SPS changes are fed directly into the existing decoder, whereas profile/level changes force the decoder session to be recreated with the new parameters. After this commit, both samples [1] and [2] playback as expected. [1] https://s3.amazonaws.com/tmm1/videotoolbox/spschange.ts [2] https://s3.amazonaws.com/tmm1/videotoolbox/spschange2.ts Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 15 ++++++++------- libavcodec/vt_internal.h | 4 +--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 9eeada30bae80..d29607363c098 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -90,6 +90,7 @@ int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame) CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx) { + VTContext *vtctx = avctx->internal->hwaccel_priv_data; H264Context *h = avctx->priv_data; CFDataRef data = NULL; uint8_t *p; @@ -116,6 +117,10 @@ CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx) p += 3 + h->ps.pps->data_size; av_assert0(p - vt_extradata == vt_extradata_size); + // save sps header (profile/level) used to create decoder session, + // so we can detect changes and recreate it. + memcpy(vtctx->sps, h->ps.sps->data + 1, 3); + data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size); av_free(vt_extradata); return data; @@ -320,16 +325,13 @@ static int videotoolbox_h264_decode_params(AVCodecContext *avctx, VTContext *vtctx = avctx->internal->hwaccel_priv_data; if (type == H264_NAL_SPS) { - if (!vtctx->sps || vtctx->sps_len != size || memcmp(buffer, vtctx->sps, size) != 0) { - vtctx->sps = av_fast_realloc(vtctx->sps, &vtctx->sps_capa, size); - if (vtctx->sps) - memcpy(vtctx->sps, buffer, size); + if (size > 4 && memcmp(vtctx->sps, buffer + 1, 3) != 0) { vtctx->reconfig_needed = true; - vtctx->sps_len = size; + memcpy(vtctx->sps, buffer + 1, 3); } } - // pass-through new PPS to the decoder + // pass-through SPS/PPS changes to the decoder return ff_videotoolbox_h264_decode_slice(avctx, buffer, size); } @@ -365,7 +367,6 @@ int ff_videotoolbox_uninit(AVCodecContext *avctx) VTContext *vtctx = avctx->internal->hwaccel_priv_data; if (vtctx) { av_freep(&vtctx->bitstream); - av_freep(&vtctx->sps); if (vtctx->frame) CVPixelBufferRelease(vtctx->frame); } diff --git a/libavcodec/vt_internal.h b/libavcodec/vt_internal.h index fc27dad9f9411..929fe423fcde5 100644 --- a/libavcodec/vt_internal.h +++ b/libavcodec/vt_internal.h @@ -40,9 +40,7 @@ typedef struct VTContext { struct AVVideotoolboxContext *vt_ctx; // Current H264 parameters (used to trigger decoder restart on SPS changes). - uint8_t *sps; - uint32_t sps_len; - unsigned int sps_capa; + uint8_t sps[3]; bool reconfig_needed; } VTContext; From 7d88586e4728e97349f98e07ff782bb168ab96c3 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 17 Nov 2017 22:01:29 +0100 Subject: [PATCH 1015/2557] avcodec/hevcdsp_template: Fix invalid shift in put_hevc_epel_bi_w_v() Fixes: runtime error: left shift of negative value -255 Fixes: 4037/clusterfuzz-testcase-minimized-5290998163832832 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevcdsp_template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/hevcdsp_template.c b/libavcodec/hevcdsp_template.c index e09c661759e50..46a0da204573f 100644 --- a/libavcodec/hevcdsp_template.c +++ b/libavcodec/hevcdsp_template.c @@ -1407,7 +1407,7 @@ static void FUNC(put_hevc_epel_bi_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = av_clip_pixel(((EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 + - ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); + ((ox0 + ox1 + 1) * (1 << log2Wd))) >> (log2Wd + 1)); src += srcstride; dst += dststride; src2 += MAX_PB_SIZE; From ca940ed2d5ad8b0f00d289f0216bb19f115bac85 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Wed, 15 Nov 2017 22:13:41 +0100 Subject: [PATCH 1016/2557] avformat/avio: remove must_flush from AVIOContext It is unused. Signed-off-by: Marton Balint --- libavformat/avio.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libavformat/avio.h b/libavformat/avio.h index 76ff7cd81ea7a..75912ce6bed97 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -236,7 +236,6 @@ typedef struct AVIOContext { int (*write_packet)(void *opaque, uint8_t *buf, int buf_size); int64_t (*seek)(void *opaque, int64_t offset, int whence); int64_t pos; /**< position in the file of the current buffer */ - int must_flush; /**< unused */ int eof_reached; /**< true if eof reached */ int write_flag; /**< true if open for writing */ int max_packet_size; From 20a93ea8d489304d5c522283d79ea5f9c8fdc804 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 19 Nov 2017 00:32:23 -0300 Subject: [PATCH 1017/2557] checkasm/jpeg2000dsp: refactor rct_int test Signed-off-by: James Almer --- tests/checkasm/jpeg2000dsp.c | 43 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/tests/checkasm/jpeg2000dsp.c b/tests/checkasm/jpeg2000dsp.c index 48559df085e41..4251f8982aa6d 100644 --- a/tests/checkasm/jpeg2000dsp.c +++ b/tests/checkasm/jpeg2000dsp.c @@ -29,43 +29,42 @@ #define randomize_buffers() \ do { \ int i; \ - for (i = 0; i < BUF_SIZE; i += 4) { \ - uint32_t r = rnd(); \ - AV_WN32A(ref0 + i, r); \ - AV_WN32A(new0 + i, r); \ - r = rnd(); \ - AV_WN32A(ref1 + i, r); \ - AV_WN32A(new1 + i, r); \ - r = rnd(); \ - AV_WN32A(ref2 + i, r); \ - AV_WN32A(new2 + i, r); \ - } \ + for (i = 0; i < BUF_SIZE*3; i++) \ + src[i] = rnd(); \ } while (0) -static void check_mct(uint8_t *ref0, uint8_t *ref1, uint8_t *ref2, - uint8_t *new0, uint8_t *new1, uint8_t *new2) { +static void check_rct_int(void) +{ + LOCAL_ALIGNED_32(int32_t, src, [BUF_SIZE*3]); + LOCAL_ALIGNED_32(int32_t, ref, [BUF_SIZE*3]); + LOCAL_ALIGNED_32(int32_t, new, [BUF_SIZE*3]); + int32_t *ref0 = &ref[BUF_SIZE*0], *new0 = &new[BUF_SIZE*0]; + int32_t *ref1 = &ref[BUF_SIZE*1], *new1 = &new[BUF_SIZE*1]; + int32_t *ref2 = &ref[BUF_SIZE*2], *new2 = &new[BUF_SIZE*2]; + declare_func(void, void *src0, void *src1, void *src2, int csize); randomize_buffers(); - call_ref(ref0, ref1, ref2, BUF_SIZE / sizeof(int32_t)); - call_new(new0, new1, new2, BUF_SIZE / sizeof(int32_t)); - if (memcmp(ref0, new0, BUF_SIZE) || memcmp(ref1, new1, BUF_SIZE) || - memcmp(ref2, new2, BUF_SIZE)) + memcpy(ref, src, BUF_SIZE * 3 * sizeof(*src)); + memcpy(new, src, BUF_SIZE * 3 * sizeof(*src)); + call_ref(ref0, ref1, ref2, BUF_SIZE); + call_new(new0, new1, new2, BUF_SIZE); + if (memcmp(ref0, new0, BUF_SIZE * sizeof(*src)) || + memcmp(ref1, new1, BUF_SIZE * sizeof(*src)) || + memcmp(ref2, new2, BUF_SIZE * sizeof(*src))) fail(); - bench_new(new0, new1, new2, BUF_SIZE / sizeof(int32_t)); + memcpy(new, src, BUF_SIZE * 3 * sizeof(*src)); + bench_new(new0, new1, new2, BUF_SIZE); } void checkasm_check_jpeg2000dsp(void) { - LOCAL_ALIGNED_32(uint8_t, ref, [BUF_SIZE*3]); - LOCAL_ALIGNED_32(uint8_t, new, [BUF_SIZE*3]); Jpeg2000DSPContext h; ff_jpeg2000dsp_init(&h); if (check_func(h.mct_decode[FF_DWT53], "jpeg2000_rct_int")) - check_mct(&ref[BUF_SIZE*0], &ref[BUF_SIZE*1], &ref[BUF_SIZE*2], - &new[BUF_SIZE*0], &new[BUF_SIZE*1], &new[BUF_SIZE*2]); + check_rct_int(); report("mct_decode"); } From 501435e5e6459643f37596f7ab849242d0227c23 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 19 Nov 2017 00:32:24 -0300 Subject: [PATCH 1018/2557] checkasm/jpeg2000dsp: add test for ict_float Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- tests/checkasm/jpeg2000dsp.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/checkasm/jpeg2000dsp.c b/tests/checkasm/jpeg2000dsp.c index 4251f8982aa6d..bce534dbaf6c5 100644 --- a/tests/checkasm/jpeg2000dsp.c +++ b/tests/checkasm/jpeg2000dsp.c @@ -33,6 +33,13 @@ src[i] = rnd(); \ } while (0) +#define randomize_buffers_float() \ + do { \ + int i; \ + for (i = 0; i < BUF_SIZE*3; i++) \ + src[i] = (float)rnd() / (UINT_MAX >> 5); \ + } while (0) + static void check_rct_int(void) { LOCAL_ALIGNED_32(int32_t, src, [BUF_SIZE*3]); @@ -57,6 +64,30 @@ static void check_rct_int(void) bench_new(new0, new1, new2, BUF_SIZE); } +static void check_ict_float(void) +{ + LOCAL_ALIGNED_32(float, src, [BUF_SIZE*3]); + LOCAL_ALIGNED_32(float, ref, [BUF_SIZE*3]); + LOCAL_ALIGNED_32(float, new, [BUF_SIZE*3]); + float *ref0 = &ref[BUF_SIZE*0], *new0 = &new[BUF_SIZE*0]; + float *ref1 = &ref[BUF_SIZE*1], *new1 = &new[BUF_SIZE*1]; + float *ref2 = &ref[BUF_SIZE*2], *new2 = &new[BUF_SIZE*2]; + + declare_func(void, void *src0, void *src1, void *src2, int csize); + + randomize_buffers_float(); + memcpy(ref, src, BUF_SIZE * 3 * sizeof(*src)); + memcpy(new, src, BUF_SIZE * 3 * sizeof(*src)); + call_ref(ref0, ref1, ref2, BUF_SIZE); + call_new(new0, new1, new2, BUF_SIZE); + if (!float_near_abs_eps_array(ref0, new0, 1.0e-5, BUF_SIZE) || + !float_near_abs_eps_array(ref1, new1, 1.0e-5, BUF_SIZE) || + !float_near_abs_eps_array(ref2, new2, 1.0e-5, BUF_SIZE)) + fail(); + memcpy(new, src, BUF_SIZE * 3 * sizeof(*src)); + bench_new(new0, new1, new2, BUF_SIZE); +} + void checkasm_check_jpeg2000dsp(void) { Jpeg2000DSPContext h; @@ -65,6 +96,8 @@ void checkasm_check_jpeg2000dsp(void) if (check_func(h.mct_decode[FF_DWT53], "jpeg2000_rct_int")) check_rct_int(); + if (check_func(h.mct_decode[FF_DWT97], "jpeg2000_ict_float")) + check_ict_float(); report("mct_decode"); } From aea0f06db74c1f924429d3cf9ff9f803d00feaf5 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 19 Nov 2017 00:32:25 -0300 Subject: [PATCH 1019/2557] x86/jpeg2000dsp: add ff_ict_float_{fma3,fma4} jpeg2000_ict_float_c: 2296.0 jpeg2000_ict_float_sse: 628.0 jpeg2000_ict_float_avx: 317.0 jpeg2000_ict_float_fma3: 262.0 Signed-off-by: James Almer --- libavcodec/x86/jpeg2000dsp.asm | 20 ++++++++++++++++++++ libavcodec/x86/jpeg2000dsp_init.c | 10 ++++++++++ 2 files changed, 30 insertions(+) diff --git a/libavcodec/x86/jpeg2000dsp.asm b/libavcodec/x86/jpeg2000dsp.asm index 56b5fbd6064df..61dfdd4f71ba4 100644 --- a/libavcodec/x86/jpeg2000dsp.asm +++ b/libavcodec/x86/jpeg2000dsp.asm @@ -74,6 +74,19 @@ align 16 movaps m1, [src1q+csizeq] movaps m2, [src2q+csizeq] +%if cpuflag(fma4) || cpuflag(fma3) +%if cpuflag(fma4) + fnmaddps m5, m1, ICT1, m0 + fmaddps m4, m2, ICT0, m0 +%else ; fma3 + movaps m5, m1 + movaps m4, m2 + fnmaddps m5, m5, ICT1, m0 + fmaddps m4, m4, ICT0, m0 +%endif + fmaddps m0, m1, ICT3, m0 + fnmaddps m5, m2, ICT2, m5 +%else ; non FMA %if cpuflag(avx) mulps m5, m1, ICT1 mulps m4, m2, ICT0 @@ -93,6 +106,7 @@ align 16 addps m4, m4, m0 addps m0, m0, m1 subps m5, m5, m2 +%endif movaps [src0q+csizeq], m4 movaps [src2q+csizeq], m0 @@ -106,6 +120,12 @@ INIT_XMM sse ICT_FLOAT 10 INIT_YMM avx ICT_FLOAT 9 +%if HAVE_FMA4_EXTERNAL +INIT_XMM fma4 +ICT_FLOAT 9 +%endif +INIT_YMM fma3 +ICT_FLOAT 9 ;*************************************************************************** ; ff_rct_int_(int32_t *src0, int32_t *src1, int32_t *src2, int csize) diff --git a/libavcodec/x86/jpeg2000dsp_init.c b/libavcodec/x86/jpeg2000dsp_init.c index baa81383eac20..7310a1d0e16ff 100644 --- a/libavcodec/x86/jpeg2000dsp_init.c +++ b/libavcodec/x86/jpeg2000dsp_init.c @@ -26,6 +26,8 @@ void ff_ict_float_sse(void *src0, void *src1, void *src2, int csize); void ff_ict_float_avx(void *src0, void *src1, void *src2, int csize); +void ff_ict_float_fma3(void *src0, void *src1, void *src2, int csize); +void ff_ict_float_fma4(void *src0, void *src1, void *src2, int csize); void ff_rct_int_sse2 (void *src0, void *src1, void *src2, int csize); void ff_rct_int_avx2 (void *src0, void *src1, void *src2, int csize); @@ -44,6 +46,14 @@ av_cold void ff_jpeg2000dsp_init_x86(Jpeg2000DSPContext *c) c->mct_decode[FF_DWT97] = ff_ict_float_avx; } + if (EXTERNAL_FMA4(cpu_flags)) { + c->mct_decode[FF_DWT97] = ff_ict_float_fma4; + } + + if (EXTERNAL_FMA3_FAST(cpu_flags)) { + c->mct_decode[FF_DWT97] = ff_ict_float_fma3; + } + if (EXTERNAL_AVX2_FAST(cpu_flags)) { c->mct_decode[FF_DWT53] = ff_rct_int_avx2; } From b765a04550ff6f954a57bf28158511d260f2e087 Mon Sep 17 00:00:00 2001 From: James Zern Date: Fri, 17 Nov 2017 17:24:07 -0800 Subject: [PATCH 1020/2557] configure: require libvpx-1.4.0 for vp[89] support this will simplify libvpxenc/dec.c and ensure more stable versions of the codecs are present. Reviewed-by: James Almer Signed-off-by: James Zern --- configure | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/configure b/configure index 25c3124ca6021..e8470ae236ba4 100755 --- a/configure +++ b/configure @@ -5907,22 +5907,22 @@ enabled libvorbis && require_pkg_config libvorbis vorbis vorbis/codec.h enabled libvpx && { enabled libvpx_vp8_decoder && { - check_pkg_config libvpx_vp8_decoder "vpx >= 0.9.1" "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp8_dx || - check_lib libvpx_vp8_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_dec_init_ver -lvpx || - die "ERROR: libvpx decoder version must be >=0.9.1"; + check_pkg_config libvpx_vp8_decoder "vpx >= 1.4.0" "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp8_dx || + check_lib libvpx_vp8_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_dec_init_ver VPX_IMG_FMT_HIGHBITDEPTH" -lvpx || + die "ERROR: libvpx decoder version must be >=1.4.0"; } enabled libvpx_vp8_encoder && { - check_pkg_config libvpx_vp8_encoder "vpx >= 0.9.7" "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp8_cx || - check_lib libvpx_vp8_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_enc_init_ver VP8E_SET_MAX_INTRA_BITRATE_PCT" -lvpx || - die "ERROR: libvpx encoder version must be >=0.9.7"; + check_pkg_config libvpx_vp8_encoder "vpx >= 1.4.0" "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp8_cx || + check_lib libvpx_vp8_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_enc_init_ver VPX_IMG_FMT_HIGHBITDEPTH" -lvpx || + die "ERROR: libvpx encoder version must be >=1.4.0"; } enabled libvpx_vp9_decoder && { - check_pkg_config libvpx_vp9_decoder "vpx >= 1.3.0" "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp9_dx || - check_lib libvpx_vp9_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_vp9_dx" -lvpx + check_pkg_config libvpx_vp9_decoder "vpx >= 1.4.0" "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp9_dx || + check_lib libvpx_vp9_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_vp9_dx VPX_IMG_FMT_HIGHBITDEPTH" -lvpx } enabled libvpx_vp9_encoder && { - check_pkg_config libvpx_vp9_encoder "vpx >= 1.3.0" "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp9_cx || - check_lib libvpx_vp9_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_vp9_cx VP9E_SET_AQ_MODE" -lvpx + check_pkg_config libvpx_vp9_encoder "vpx >= 1.4.0" "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp9_cx || + check_lib libvpx_vp9_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_vp9_cx VPX_IMG_FMT_HIGHBITDEPTH" -lvpx } if disabled_all libvpx_vp8_decoder libvpx_vp9_decoder libvpx_vp8_encoder libvpx_vp9_encoder; then die "libvpx enabled but no supported decoders found" From e54061ae6a5e22bad5c66ef4411acc8f778a9f90 Mon Sep 17 00:00:00 2001 From: James Zern Date: Fri, 17 Nov 2017 17:25:21 -0800 Subject: [PATCH 1021/2557] libvpx: remove pre-1.4.0 checks Reviewed-by: James Almer Signed-off-by: James Zern --- libavcodec/libvpx.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/libavcodec/libvpx.c b/libavcodec/libvpx.c index 1eca97a081f03..36f915a8e5710 100644 --- a/libavcodec/libvpx.c +++ b/libavcodec/libvpx.c @@ -40,9 +40,7 @@ static const enum AVPixelFormat vp9_pix_fmts_highcol[] = { AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, -#if VPX_IMAGE_ABI_VERSION >= 3 AV_PIX_FMT_GBRP, -#endif AV_PIX_FMT_NONE }; @@ -60,30 +58,22 @@ static const enum AVPixelFormat vp9_pix_fmts_highbd[] = { AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV440P12, AV_PIX_FMT_YUV444P12, -#if VPX_IMAGE_ABI_VERSION >= 3 AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, -#endif AV_PIX_FMT_NONE }; #endif av_cold void ff_vp9_init_static(AVCodec *codec) { - if ( vpx_codec_version_major() < 1 - || (vpx_codec_version_major() == 1 && vpx_codec_version_minor() < 3)) - codec->capabilities |= AV_CODEC_CAP_EXPERIMENTAL; codec->pix_fmts = vp9_pix_fmts_def; #if CONFIG_LIBVPX_VP9_ENCODER - if ( vpx_codec_version_major() > 1 - || (vpx_codec_version_major() == 1 && vpx_codec_version_minor() >= 4)) { -#ifdef VPX_CODEC_CAP_HIGHBITDEPTH + { vpx_codec_caps_t codec_caps = vpx_codec_get_caps(vpx_codec_vp9_cx()); if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) codec->pix_fmts = vp9_pix_fmts_highbd; else -#endif codec->pix_fmts = vp9_pix_fmts_highcol; } #endif From e60dbe421c7e9cd896d33e35a6a1b0cef953918e Mon Sep 17 00:00:00 2001 From: James Zern Date: Fri, 17 Nov 2017 17:25:59 -0800 Subject: [PATCH 1022/2557] libvpxdec: remove pre-1.4.0 checks Reviewed-by: James Almer Signed-off-by: James Zern --- libavcodec/libvpxdec.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c index ad0ea3b02aae8..2ae29d202a550 100644 --- a/libavcodec/libvpxdec.c +++ b/libavcodec/libvpxdec.c @@ -70,7 +70,6 @@ static av_cold int vpx_init(AVCodecContext *avctx, static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img, int has_alpha_channel) { -#if VPX_IMAGE_ABI_VERSION >= 3 static const enum AVColorSpace colorspaces[8] = { AVCOL_SPC_UNSPECIFIED, AVCOL_SPC_BT470BG, AVCOL_SPC_BT709, AVCOL_SPC_SMPTE170M, AVCOL_SPC_SMPTE240M, AVCOL_SPC_BT2020_NCL, AVCOL_SPC_RESERVED, AVCOL_SPC_RGB, @@ -82,7 +81,6 @@ static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img, avctx->color_range = color_ranges[img->range]; #endif avctx->colorspace = colorspaces[img->cs]; -#endif if (avctx->codec_id == AV_CODEC_ID_VP8 && img->fmt != VPX_IMG_FMT_I420) return AVERROR_INVALIDDATA; switch (img->fmt) { @@ -97,22 +95,15 @@ static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img, avctx->profile = FF_PROFILE_VP9_1; avctx->pix_fmt = AV_PIX_FMT_YUV422P; return 0; -#if VPX_IMAGE_ABI_VERSION >= 3 case VPX_IMG_FMT_I440: avctx->profile = FF_PROFILE_VP9_1; avctx->pix_fmt = AV_PIX_FMT_YUV440P; return 0; -#endif case VPX_IMG_FMT_I444: avctx->profile = FF_PROFILE_VP9_1; -#if VPX_IMAGE_ABI_VERSION >= 3 avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? AV_PIX_FMT_GBRP : AV_PIX_FMT_YUV444P; -#else - avctx->pix_fmt = AV_PIX_FMT_YUV444P; -#endif return 0; -#ifdef VPX_IMG_FMT_HIGHBITDEPTH case VPX_IMG_FMT_I42016: avctx->profile = FF_PROFILE_VP9_2; if (img->bit_depth == 10) { @@ -135,7 +126,6 @@ static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img, } else { return AVERROR_INVALIDDATA; } -#if VPX_IMAGE_ABI_VERSION >= 3 case VPX_IMG_FMT_I44016: avctx->profile = FF_PROFILE_VP9_3; if (img->bit_depth == 10) { @@ -147,29 +137,19 @@ static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img, } else { return AVERROR_INVALIDDATA; } -#endif case VPX_IMG_FMT_I44416: avctx->profile = FF_PROFILE_VP9_3; if (img->bit_depth == 10) { -#if VPX_IMAGE_ABI_VERSION >= 3 avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? AV_PIX_FMT_GBRP10 : AV_PIX_FMT_YUV444P10; -#else - avctx->pix_fmt = AV_PIX_FMT_YUV444P10; -#endif return 0; } else if (img->bit_depth == 12) { -#if VPX_IMAGE_ABI_VERSION >= 3 avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? AV_PIX_FMT_GBRP12 : AV_PIX_FMT_YUV444P12; -#else - avctx->pix_fmt = AV_PIX_FMT_YUV444P12; -#endif return 0; } else { return AVERROR_INVALIDDATA; } -#endif #endif default: return AVERROR_INVALIDDATA; @@ -252,13 +232,8 @@ static int vpx_decode(AVCodecContext *avctx, } if ((ret = set_pix_fmt(avctx, img, ctx->has_alpha_channel)) < 0) { -#ifdef VPX_IMG_FMT_HIGHBITDEPTH av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d) / bit_depth (%d)\n", img->fmt, img->bit_depth); -#else - av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d) / bit_depth (%d)\n", - img->fmt, 8); -#endif return ret; } From 753074721bd414874d18c372c491bdc6323fa3bf Mon Sep 17 00:00:00 2001 From: James Zern Date: Fri, 17 Nov 2017 17:25:40 -0800 Subject: [PATCH 1023/2557] libvpxenc: remove pre-1.4.0 checks Reviewed-by: James Almer Signed-off-by: James Zern --- libavcodec/libvpxenc.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index fbb842499bbb1..0258396d08a03 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -131,9 +131,7 @@ static const char *const ctlidstr[] = { [VP9E_SET_TILE_ROWS] = "VP9E_SET_TILE_ROWS", [VP9E_SET_FRAME_PARALLEL_DECODING] = "VP9E_SET_FRAME_PARALLEL_DECODING", [VP9E_SET_AQ_MODE] = "VP9E_SET_AQ_MODE", -#if VPX_ENCODER_ABI_VERSION > 8 [VP9E_SET_COLOR_SPACE] = "VP9E_SET_COLOR_SPACE", -#endif #if VPX_ENCODER_ABI_VERSION >= 11 [VP9E_SET_COLOR_RANGE] = "VP9E_SET_COLOR_RANGE", #endif @@ -170,7 +168,7 @@ static av_cold void dump_enc_cfg(AVCodecContext *avctx, av_log(avctx, level, "vpx_codec_enc_cfg\n"); av_log(avctx, level, "generic settings\n" " %*s%u\n %*s%u\n %*s%u\n %*s%u\n %*s%u\n" -#if CONFIG_LIBVPX_VP9_ENCODER && defined(VPX_IMG_FMT_HIGHBITDEPTH) +#if CONFIG_LIBVPX_VP9_ENCODER " %*s%u\n %*s%u\n" #endif " %*s{%u/%u}\n %*s%u\n %*s%d\n %*s%u\n", @@ -179,7 +177,7 @@ static av_cold void dump_enc_cfg(AVCodecContext *avctx, width, "g_profile:", cfg->g_profile, width, "g_w:", cfg->g_w, width, "g_h:", cfg->g_h, -#if CONFIG_LIBVPX_VP9_ENCODER && defined(VPX_IMG_FMT_HIGHBITDEPTH) +#if CONFIG_LIBVPX_VP9_ENCODER width, "g_bit_depth:", cfg->g_bit_depth, width, "g_input_bit_depth:", cfg->g_input_bit_depth, #endif @@ -324,9 +322,7 @@ static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps, vpx_img_fmt_t *img_fmt) { VPxContext av_unused *ctx = avctx->priv_data; -#ifdef VPX_IMG_FMT_HIGHBITDEPTH enccfg->g_bit_depth = enccfg->g_input_bit_depth = 8; -#endif switch (avctx->pix_fmt) { case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUVA420P: @@ -337,19 +333,16 @@ static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps, enccfg->g_profile = 1; *img_fmt = VPX_IMG_FMT_I422; return 0; -#if VPX_IMAGE_ABI_VERSION >= 3 case AV_PIX_FMT_YUV440P: enccfg->g_profile = 1; *img_fmt = VPX_IMG_FMT_I440; return 0; case AV_PIX_FMT_GBRP: ctx->vpx_cs = VPX_CS_SRGB; -#endif case AV_PIX_FMT_YUV444P: enccfg->g_profile = 1; *img_fmt = VPX_IMG_FMT_I444; return 0; -#ifdef VPX_IMG_FMT_HIGHBITDEPTH case AV_PIX_FMT_YUV420P10: case AV_PIX_FMT_YUV420P12: if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) { @@ -372,7 +365,6 @@ static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps, return 0; } break; -#if VPX_IMAGE_ABI_VERSION >= 3 case AV_PIX_FMT_YUV440P10: case AV_PIX_FMT_YUV440P12: if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) { @@ -387,7 +379,6 @@ static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps, case AV_PIX_FMT_GBRP10: case AV_PIX_FMT_GBRP12: ctx->vpx_cs = VPX_CS_SRGB; -#endif case AV_PIX_FMT_YUV444P10: case AV_PIX_FMT_YUV444P12: if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) { @@ -400,7 +391,6 @@ static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps, return 0; } break; -#endif default: break; } @@ -408,7 +398,6 @@ static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps, return AVERROR_INVALIDDATA; } -#if VPX_ENCODER_ABI_VERSION > 8 static void set_colorspace(AVCodecContext *avctx) { enum vpx_color_space vpx_cs; @@ -434,7 +423,6 @@ static void set_colorspace(AVCodecContext *avctx) } codecctl_int(avctx, VP9E_SET_COLOR_SPACE, vpx_cs); } -#endif #if VPX_ENCODER_ABI_VERSION >= 11 static void set_color_range(AVCodecContext *avctx) @@ -701,9 +689,7 @@ FF_ENABLE_DEPRECATION_WARNINGS codecctl_int(avctx, VP9E_SET_FRAME_PARALLEL_DECODING, ctx->frame_parallel); if (ctx->aq_mode >= 0) codecctl_int(avctx, VP9E_SET_AQ_MODE, ctx->aq_mode); -#if VPX_ENCODER_ABI_VERSION > 8 set_colorspace(avctx); -#endif #if VPX_ENCODER_ABI_VERSION >= 11 set_color_range(avctx); #endif @@ -726,7 +712,7 @@ FF_ENABLE_DEPRECATION_WARNINGS //provide dummy value to initialize wrapper, values will be updated each _encode() vpx_img_wrap(&ctx->rawimg, img_fmt, avctx->width, avctx->height, 1, (unsigned char*)1); -#if CONFIG_LIBVPX_VP9_ENCODER && defined(VPX_IMG_FMT_HIGHBITDEPTH) +#if CONFIG_LIBVPX_VP9_ENCODER if (avctx->codec_id == AV_CODEC_ID_VP9 && (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH)) ctx->rawimg.bit_depth = enccfg.g_bit_depth; #endif @@ -1067,11 +1053,6 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, #define OFFSET(x) offsetof(VPxContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM -#ifndef VPX_ERROR_RESILIENT_DEFAULT -#define VPX_ERROR_RESILIENT_DEFAULT 1 -#define VPX_ERROR_RESILIENT_PARTITIONS 2 -#endif - #define COMMON_OPTIONS \ { "auto-alt-ref", "Enable use of alternate reference " \ "frames (2-pass only)", OFFSET(auto_alt_ref), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, VE}, \ From 7010dd98b575d2e39fca947e609b85be7490b269 Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Fri, 17 Nov 2017 16:05:30 -0800 Subject: [PATCH 1024/2557] Fix undefined shift on assumed 8-bit input. decode_user_data() attempts to create an integer |build| value with 8 bits of spacing for 3 components. However each component is an int32_t, so shifting each component is undefined for values outside of the 8 bit range. This patch simply clamps input to 8-bits per component and prints out a warning that the values were clamped. Signed-off-by: Dale Curtis Signed-off-by: Michael Niedermayer --- libavcodec/mpeg4videodec.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 76247c3b8c5f1..11d4e08986ace 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -2153,8 +2153,15 @@ static int decode_user_data(Mpeg4DecContext *ctx, GetBitContext *gb) e = sscanf(buf, "FFmpeg v%d.%d.%d / libavcodec build: %d", &ver, &ver2, &ver3, &build); if (e != 4) { e = sscanf(buf, "Lavc%d.%d.%d", &ver, &ver2, &ver3) + 1; - if (e > 1) - build = (ver << 16) + (ver2 << 8) + ver3; + if (e > 1) { + if (ver > 0xFF || ver2 > 0xFF || ver3 > 0xFF) { + av_log(s->avctx, AV_LOG_WARNING, + "Unknown Lavc version string encountered, %d.%d.%d; " + "clamping sub-version values to 8-bits.\n", + ver, ver2, ver3); + } + build = ((ver & 0xFF) << 16) + ((ver2 & 0xFF) << 8) + (ver3 & 0xFF); + } } if (e != 4) { if (strcmp(buf, "ffmpeg") == 0) From bce8fc0754c4b31f574a4372c6d7996ed29f7c2a Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Mon, 20 Nov 2017 12:07:57 -0800 Subject: [PATCH 1025/2557] Close ogg stream upon error when using AV_EF_EXPLODE. Without this there can be multiple memory leaks for unrecognized ogg streams. Signed-off-by: Dale Curtis Signed-off-by: Michael Niedermayer --- libavformat/oggdec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 97ad1a27d15ce..193a286e43576 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -719,8 +719,10 @@ static int ogg_read_header(AVFormatContext *s) "Headers mismatch for stream %d: " "expected %d received %d.\n", i, os->codec->nb_header, os->nb_header); - if (s->error_recognition & AV_EF_EXPLODE) + if (s->error_recognition & AV_EF_EXPLODE) { + ogg_read_close(s); return AVERROR_INVALIDDATA; + } } if (os->start_granule != OGG_NOGRANULE_VALUE) os->lastpts = s->streams[i]->start_time = From 2d9cf3bf16b94cd9db10dabad695c69c5cff4f58 Mon Sep 17 00:00:00 2001 From: Jacob Trimble Date: Mon, 20 Nov 2017 12:05:02 -0800 Subject: [PATCH 1026/2557] avformat/mov: Propagate errors in mov_switch_root. Signed-off-by: Jacob Trimble Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 0b8f8ad24b998..b6cdf3a52a1a5 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -6753,6 +6753,7 @@ static int should_retry(AVIOContext *pb, int error_code) { static int mov_switch_root(AVFormatContext *s, int64_t target, int index) { + int ret; MOVContext *mov = s->priv_data; if (index >= 0 && index < mov->frag_index.nb_items) @@ -6775,8 +6776,10 @@ static int mov_switch_root(AVFormatContext *s, int64_t target, int index) mov->found_mdat = 0; - if (mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX }) < 0 || - avio_feof(s->pb)) + ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX }); + if (ret < 0) + return ret; + if (avio_feof(s->pb)) return AVERROR_EOF; av_log(s, AV_LOG_TRACE, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb)); From d24e08e978792e09d212018677d1c0b8208ecef8 Mon Sep 17 00:00:00 2001 From: Karthick J Date: Wed, 8 Nov 2017 14:52:54 +0530 Subject: [PATCH 1027/2557] avformat/dashenc: Added configuration to override HTTP User-Agent Reviewed-by: Steven Liu Signed-off-by: Michael Niedermayer --- doc/muxers.texi | 2 ++ libavformat/dashenc.c | 22 +++++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 067a40289bd07..0bb8ad2e2b97d 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -247,6 +247,8 @@ DASH-templated name to used for the initialization segment. Default is "init-str DASH-templated name to used for the media segments. Default is "chunk-stream$RepresentationID$-$Number%05d$.m4s" @item -utc_timing_url @var{utc_url} URL of the page that will return the UTC timestamp in ISO format. Example: "https://time.akamai.com/?iso" +@item -http_user_agent @var{user_agent} +Override User-Agent field in HTTP header. Applicable only for HTTP output. @item -adaptation_sets @var{adaptation_sets} Assign streams to AdaptationSets. Syntax is "id=x,streams=a,b,c id=y,streams=d,e" with x and y being the IDs of the adaptation sets and a,b,c,d and e are the indices of the mapped streams. diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index ddad3351fd9aa..201668a4a4321 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -100,6 +100,7 @@ typedef struct DASHContext { const char *init_seg_name; const char *media_seg_name; const char *utc_timing_url; + const char *user_agent; } DASHContext; static struct codec_string { @@ -210,6 +211,12 @@ static int flush_dynbuf(OutputStream *os, int *range_length) return avio_open_dyn_buf(&os->ctx->pb); } +static void set_http_options(AVDictionary **options, DASHContext *c) +{ + if (c->user_agent) + av_dict_set(options, "user_agent", c->user_agent, 0); +} + static int flush_init_segment(AVFormatContext *s, OutputStream *os) { DASHContext *c = s->priv_data; @@ -575,16 +582,19 @@ static int write_manifest(AVFormatContext *s, int final) int use_rename = proto && !strcmp(proto, "file"); static unsigned int warned_non_file = 0; AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0); + AVDictionary *opts = NULL; if (!use_rename && !warned_non_file++) av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n"); snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->filename); - ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL); + set_http_options(&opts, c); + ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, &opts); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename); return ret; } + av_dict_free(&opts); avio_printf(out, "\n"); avio_printf(out, "initfile, sizeof(os->initfile), c->init_seg_name, i, 0, os->bit_rate, 0); } snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile); - ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, NULL); + set_http_options(&opts, c); + ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, &opts); if (ret < 0) return ret; + av_dict_free(&opts); os->init_start_pos = 0; if (!strcmp(os->format_name, "mp4")) { @@ -974,12 +986,15 @@ static int dash_flush(AVFormatContext *s, int final, int stream) } if (!c->single_file) { + AVDictionary *opts = NULL; ff_dash_fill_tmpl_params(filename, sizeof(filename), c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts); snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename); snprintf(temp_path, sizeof(temp_path), use_rename ? "%s.tmp" : "%s", full_path); - ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE, NULL); + set_http_options(&opts, c); + ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE, &opts); if (ret < 0) break; + av_dict_free(&opts); if (!strcmp(os->format_name, "mp4")) write_styp(os->ctx->pb); } else { @@ -1190,6 +1205,7 @@ static const AVOption options[] = { { "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.m4s"}, 0, 0, E }, { "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.m4s"}, 0, 0, E }, { "utc_timing_url", "URL of the page that will return the UTC timestamp in ISO format", OFFSET(utc_timing_url), AV_OPT_TYPE_STRING, { 0 }, 0, 0, E }, + { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, { NULL }, }; From a5870cb37f7a694a8dc3d6b8f2deaa8fd788e17e Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Sat, 18 Nov 2017 13:24:24 +0800 Subject: [PATCH 1028/2557] ffmpeg: add return value check to supress the build warning. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add return value check to supress the build warning message like "warning: ignoring return value" when use attribute -Wunused-result. Signed-off-by: Jun Zhao Reviewed-by: 刘歧 Signed-off-by: Michael Niedermayer --- fftools/ffmpeg.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index babd85f7bccd6..0c16e75ab040b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -220,13 +220,18 @@ static void sub2video_push_ref(InputStream *ist, int64_t pts) { AVFrame *frame = ist->sub2video.frame; int i; + int ret; av_assert1(frame->data[0]); ist->sub2video.last_pts = frame->pts = pts; - for (i = 0; i < ist->nb_filters; i++) - av_buffersrc_add_frame_flags(ist->filters[i]->filter, frame, - AV_BUFFERSRC_FLAG_KEEP_REF | - AV_BUFFERSRC_FLAG_PUSH); + for (i = 0; i < ist->nb_filters; i++) { + ret = av_buffersrc_add_frame_flags(ist->filters[i]->filter, frame, + AV_BUFFERSRC_FLAG_KEEP_REF | + AV_BUFFERSRC_FLAG_PUSH); + if (ret != AVERROR_EOF && ret < 0) + av_log(NULL, AV_LOG_WARNING, "Error while add the frame to buffer source(%s).\n", + av_err2str(ret)); + } } void sub2video_update(InputStream *ist, AVSubtitle *sub) @@ -295,11 +300,15 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts) static void sub2video_flush(InputStream *ist) { int i; + int ret; if (ist->sub2video.end_pts < INT64_MAX) sub2video_update(ist, NULL); - for (i = 0; i < ist->nb_filters; i++) - av_buffersrc_add_frame(ist->filters[i]->filter, NULL); + for (i = 0; i < ist->nb_filters; i++) { + ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL); + if (ret != AVERROR_EOF && ret < 0) + av_log(NULL, AV_LOG_WARNING, "Flush the frame error.\n"); + } } /* end of sub2video hack */ @@ -327,13 +336,14 @@ static int main_return_code = 0; static void sigterm_handler(int sig) { + int ret; received_sigterm = sig; received_nb_signals++; term_exit_sigsafe(); if(received_nb_signals > 3) { - write(2/*STDERR_FILENO*/, "Received > 3 system signals, hard exiting\n", - strlen("Received > 3 system signals, hard exiting\n")); - + ret = write(2/*STDERR_FILENO*/, "Received > 3 system signals, hard exiting\n", + strlen("Received > 3 system signals, hard exiting\n")); + if (ret < 0) { /* Do nothing */ }; exit(123); } } From 6a7eb65e1b1f8daae035b7434c64a38865dc6428 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 08:31:12 +0100 Subject: [PATCH 1029/2557] checkasm : add utvideodsp test --- tests/checkasm/Makefile | 1 + tests/checkasm/checkasm.c | 3 ++ tests/checkasm/checkasm.h | 1 + tests/checkasm/utvideodsp.c | 105 ++++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 tests/checkasm/utvideodsp.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 74f07f11cd47c..b4386d06ad08f 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -22,6 +22,7 @@ AVCODECOBJS-$(CONFIG_EXR_DECODER) += exrdsp.o AVCODECOBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dsp.o AVCODECOBJS-$(CONFIG_PIXBLOCKDSP) += pixblockdsp.o AVCODECOBJS-$(CONFIG_HEVC_DECODER) += hevc_add_res.o hevc_idct.o +AVCODECOBJS-$(CONFIG_UTVIDEO_DECODER) += utvideodsp.o AVCODECOBJS-$(CONFIG_V210_ENCODER) += v210enc.o AVCODECOBJS-$(CONFIG_VP9_DECODER) += vp9dsp.o diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index b8b0e32dbd4b5..6855c93b0a641 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -126,6 +126,9 @@ static const struct { #if CONFIG_PIXBLOCKDSP { "pixblockdsp", checkasm_check_pixblockdsp }, #endif + #if CONFIG_UTVIDEO_DECODER + { "utvideodsp", checkasm_check_utvideodsp }, + #endif #if CONFIG_V210_ENCODER { "v210enc", checkasm_check_v210enc }, #endif diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index e5b1877dc00a3..933d868c02a6c 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -62,6 +62,7 @@ void checkasm_check_llviddsp(void); void checkasm_check_pixblockdsp(void); void checkasm_check_sbrdsp(void); void checkasm_check_synth_filter(void); +void checkasm_check_utvideodsp(void); void checkasm_check_v210enc(void); void checkasm_check_vp8dsp(void); void checkasm_check_vp9dsp(void); diff --git a/tests/checkasm/utvideodsp.c b/tests/checkasm/utvideodsp.c new file mode 100644 index 0000000000000..6ef2fb21f05f9 --- /dev/null +++ b/tests/checkasm/utvideodsp.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017 Jokyo Images + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "checkasm.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/utvideodsp.h" +#include "libavutil/intreadwrite.h" + +#define WIDTH 240 +#define HEIGHT 120 +#define WIDTH_PADDED (WIDTH+WIDTH%32) +#define BUFFER_SIZE (WIDTH_PADDED * HEIGHT) + + +#define randomize_plane(buf, type) \ + do { \ + int w, h; \ + type * tmp = buf; \ + for (h = 0; h < HEIGHT; h++) { \ + for (w = 0; w < WIDTH; w++) \ + tmp[w] = rnd() & 0xFF; \ + tmp += WIDTH_PADDED; \ + } \ + } while (0) + +#define cmp_plane(buf0, buf1, s) \ + do { \ + int h; \ + for (h = 0; h < HEIGHT; h++) { \ + if (memcmp(buf0 + h*WIDTH_PADDED, \ + buf1 + h*WIDTH_PADDED, WIDTH *s)) \ + fail();\ + } \ + } while (0) + + +#define CHECK_RESTORE(type)\ +LOCAL_ALIGNED_32(type, src_r0, [BUFFER_SIZE]); \ +LOCAL_ALIGNED_32(type, src_g0, [BUFFER_SIZE]); \ +LOCAL_ALIGNED_32(type, src_b0, [BUFFER_SIZE]); \ +LOCAL_ALIGNED_32(type, src_r1, [BUFFER_SIZE]); \ +LOCAL_ALIGNED_32(type, src_g1, [BUFFER_SIZE]); \ +LOCAL_ALIGNED_32(type, src_b1, [BUFFER_SIZE]); \ +memset(src_r0, 0, BUFFER_SIZE); \ +memset(src_g0, 0, BUFFER_SIZE); \ +memset(src_b0, 0, BUFFER_SIZE); \ +randomize_plane(src_r0, type); \ +randomize_plane(src_g0, type); \ +randomize_plane(src_b0, type); \ +memcpy(src_r1, src_r0, BUFFER_SIZE * sizeof(type)); \ +memcpy(src_g1, src_g0, BUFFER_SIZE * sizeof(type)); \ +memcpy(src_b1, src_b0, BUFFER_SIZE * sizeof(type)); \ +declare_func(void, type *src_r, type *src_g, type *src_b, \ + ptrdiff_t linesize_r, ptrdiff_t linesize_g, \ + ptrdiff_t linesize_b, int width, int height); \ +call_ref(src_r0, src_g0, src_b0, WIDTH_PADDED, WIDTH_PADDED, WIDTH_PADDED, WIDTH, HEIGHT);\ +call_new(src_r1, src_g1, src_b1, WIDTH_PADDED, WIDTH_PADDED, WIDTH_PADDED, WIDTH, HEIGHT);\ +cmp_plane(src_r0, src_r1, sizeof(type)); \ +cmp_plane(src_g0, src_g1, sizeof(type)); \ +cmp_plane(src_b0, src_b1, sizeof(type)); \ +bench_new(src_r1, src_g1, src_b1, WIDTH_PADDED, WIDTH_PADDED, WIDTH_PADDED, WIDTH, HEIGHT) + +static void check_restore_rgb_planes(void) { + CHECK_RESTORE(uint8_t); +} + +static void check_restore_rgb_planes10(void) { + CHECK_RESTORE(uint16_t); +} + +void checkasm_check_utvideodsp(void) +{ + UTVideoDSPContext h; + + ff_utvideodsp_init(&h); + + if (check_func(h.restore_rgb_planes, "restore_rgb_planes")) + check_restore_rgb_planes(); + + report("restore_rgb_planes"); + + if (check_func(h.restore_rgb_planes10, "restore_rgb_planes10")) + check_restore_rgb_planes10(); + + report("restore_rgb_planes10"); +} From 48b7c45b0c6fa8f48eaa265f60bc672489ae97ee Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 08:32:01 +0100 Subject: [PATCH 1030/2557] avcodec/x86/utvideodsp : make macro for func --- libavcodec/x86/utvideodsp.asm | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libavcodec/x86/utvideodsp.asm b/libavcodec/x86/utvideodsp.asm index e44c1ea4719de..55ef127ccb91a 100644 --- a/libavcodec/x86/utvideodsp.asm +++ b/libavcodec/x86/utvideodsp.asm @@ -29,11 +29,10 @@ pw_1023: times 8 dw 1023 SECTION .text -INIT_XMM sse2 - ; void restore_rgb_planes(uint8_t *src_r, uint8_t *src_g, uint8_t *src_b, ; ptrdiff_t linesize_r, ptrdiff_t linesize_g, ptrdiff_t linesize_b, ; int width, int height) +%macro RESTORE_RGB_PLANES 0 cglobal restore_rgb_planes, 7 + ARCH_X86_64, 7 + ARCH_X86_64 * 2, 4, src_r, src_g, src_b, linesize_r, linesize_g, linesize_b, w, h, x movsxdifnidn wq, wd add src_rq, wq @@ -68,7 +67,12 @@ DEFINE_ARGS src_r, src_g, src_b, linesize_r, linesize_g, linesize_b, x sub hd, 1 jg .nextrow REP_RET +%endmacro + +INIT_XMM sse2 +RESTORE_RGB_PLANES +%macro RESTORE_RGB_PLANES10 0 cglobal restore_rgb_planes10, 7 + ARCH_X86_64, 7 + ARCH_X86_64 * 2, 5, src_r, src_g, src_b, linesize_r, linesize_g, linesize_b, w, h, x shl wd, 1 shl linesize_rq, 1 @@ -109,3 +113,7 @@ DEFINE_ARGS src_r, src_g, src_b, linesize_r, linesize_g, linesize_b, x sub hd, 1 jg .nextrow REP_RET +%endmacro + +INIT_XMM sse2 +RESTORE_RGB_PLANES10 From b5ebe38443542c4d6ca285026670512da482d8e5 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 08:34:20 +0100 Subject: [PATCH 1031/2557] avcodec/utvideodsp : add avx2 version for the dsp --- libavcodec/x86/utvideodsp.asm | 20 ++++++++++++++++++++ libavcodec/x86/utvideodsp_init.c | 11 +++++++++++ 2 files changed, 31 insertions(+) diff --git a/libavcodec/x86/utvideodsp.asm b/libavcodec/x86/utvideodsp.asm index 55ef127ccb91a..b67a509ddad47 100644 --- a/libavcodec/x86/utvideodsp.asm +++ b/libavcodec/x86/utvideodsp.asm @@ -1,6 +1,7 @@ ;****************************************************************************** ;* SIMD-optimized UTVideo functions ;* Copyright (c) 2017 Paul B Mahol +;* Copyright (c) 2017 Jokyo Images ;* ;* This file is part of FFmpeg. ;* @@ -45,7 +46,11 @@ DEFINE_ARGS src_r, src_g, src_b, linesize_r, linesize_g, linesize_b, x %define wq r6m %define hd r7mp %endif +%if mmsize == 32 + vbroadcasti128 m3, [pb_128] +%else mova m3, [pb_128] +%endif .nextrow: mov xq, wq @@ -72,6 +77,11 @@ DEFINE_ARGS src_r, src_g, src_b, linesize_r, linesize_g, linesize_b, x INIT_XMM sse2 RESTORE_RGB_PLANES +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +RESTORE_RGB_PLANES +%endif + %macro RESTORE_RGB_PLANES10 0 cglobal restore_rgb_planes10, 7 + ARCH_X86_64, 7 + ARCH_X86_64 * 2, 5, src_r, src_g, src_b, linesize_r, linesize_g, linesize_b, w, h, x shl wd, 1 @@ -81,8 +91,13 @@ cglobal restore_rgb_planes10, 7 + ARCH_X86_64, 7 + ARCH_X86_64 * 2, 5, src_r, sr add src_rq, wq add src_gq, wq add src_bq, wq +%if mmsize == 32 + vbroadcasti128 m3, [pw_512] + vbroadcasti128 m4, [pw_1023] +%else mova m3, [pw_512] mova m4, [pw_1023] +%endif neg wq %if ARCH_X86_64 == 0 mov wm, wq @@ -117,3 +132,8 @@ DEFINE_ARGS src_r, src_g, src_b, linesize_r, linesize_g, linesize_b, x INIT_XMM sse2 RESTORE_RGB_PLANES10 + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +RESTORE_RGB_PLANES10 +%endif diff --git a/libavcodec/x86/utvideodsp_init.c b/libavcodec/x86/utvideodsp_init.c index f8b2a9b0749bb..2b436c6c5c079 100644 --- a/libavcodec/x86/utvideodsp_init.c +++ b/libavcodec/x86/utvideodsp_init.c @@ -28,9 +28,16 @@ void ff_restore_rgb_planes_sse2(uint8_t *src_r, uint8_t *src_g, uint8_t *src_b, ptrdiff_t linesize_r, ptrdiff_t linesize_g, ptrdiff_t linesize_b, int width, int height); +void ff_restore_rgb_planes_avx2(uint8_t *src_r, uint8_t *src_g, uint8_t *src_b, + ptrdiff_t linesize_r, ptrdiff_t linesize_g, + ptrdiff_t linesize_b, int width, int height); + void ff_restore_rgb_planes10_sse2(uint16_t *src_r, uint16_t *src_g, uint16_t *src_b, ptrdiff_t linesize_r, ptrdiff_t linesize_g, ptrdiff_t linesize_b, int width, int height); +void ff_restore_rgb_planes10_avx2(uint16_t *src_r, uint16_t *src_g, uint16_t *src_b, + ptrdiff_t linesize_r, ptrdiff_t linesize_g, + ptrdiff_t linesize_b, int width, int height); av_cold void ff_utvideodsp_init_x86(UTVideoDSPContext *c) { @@ -40,4 +47,8 @@ av_cold void ff_utvideodsp_init_x86(UTVideoDSPContext *c) c->restore_rgb_planes = ff_restore_rgb_planes_sse2; c->restore_rgb_planes10 = ff_restore_rgb_planes10_sse2; } + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + c->restore_rgb_planes = ff_restore_rgb_planes_avx2; + c->restore_rgb_planes10 = ff_restore_rgb_planes10_avx2; + } } From caf51a573d64e856e3dce6be40e15b265452dccc Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 08:36:00 +0100 Subject: [PATCH 1032/2557] avcodec/x86/utvideodsp.asm : cosmetic better func separator and add comment for the restore rgb planes10 declaration --- libavcodec/x86/utvideodsp.asm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/x86/utvideodsp.asm b/libavcodec/x86/utvideodsp.asm index b67a509ddad47..6e13de39aada1 100644 --- a/libavcodec/x86/utvideodsp.asm +++ b/libavcodec/x86/utvideodsp.asm @@ -30,9 +30,11 @@ pw_1023: times 8 dw 1023 SECTION .text +;------------------------------------------------------------------------------------------- ; void restore_rgb_planes(uint8_t *src_r, uint8_t *src_g, uint8_t *src_b, ; ptrdiff_t linesize_r, ptrdiff_t linesize_g, ptrdiff_t linesize_b, ; int width, int height) +;------------------------------------------------------------------------------------------- %macro RESTORE_RGB_PLANES 0 cglobal restore_rgb_planes, 7 + ARCH_X86_64, 7 + ARCH_X86_64 * 2, 4, src_r, src_g, src_b, linesize_r, linesize_g, linesize_b, w, h, x movsxdifnidn wq, wd @@ -82,6 +84,11 @@ INIT_YMM avx2 RESTORE_RGB_PLANES %endif +;------------------------------------------------------------------------------------------- +; void restore_rgb_planes10(uint16_t *src_r, uint16_t *src_g, uint16_t *src_b, +; ptrdiff_t linesize_r, ptrdiff_t linesize_g, ptrdiff_t linesize_b, +; int width, int height) +;------------------------------------------------------------------------------------------- %macro RESTORE_RGB_PLANES10 0 cglobal restore_rgb_planes10, 7 + ARCH_X86_64, 7 + ARCH_X86_64 * 2, 5, src_r, src_g, src_b, linesize_r, linesize_g, linesize_b, w, h, x shl wd, 1 From 4a6aa6d1b274875ab88dd9d25c4e27de2f00f281 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 09:09:42 +0100 Subject: [PATCH 1033/2557] checkasm : add test for huffyuvdsp add_int16 --- tests/checkasm/Makefile | 1 + tests/checkasm/checkasm.c | 3 ++ tests/checkasm/checkasm.h | 1 + tests/checkasm/huffyuvdsp.c | 81 +++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 tests/checkasm/huffyuvdsp.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index b4386d06ad08f..6add9ded12566 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -19,6 +19,7 @@ AVCODECOBJS-$(CONFIG_AAC_DECODER) += aacpsdsp.o \ AVCODECOBJS-$(CONFIG_ALAC_DECODER) += alacdsp.o AVCODECOBJS-$(CONFIG_DCA_DECODER) += synth_filter.o AVCODECOBJS-$(CONFIG_EXR_DECODER) += exrdsp.o +AVCODECOBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuvdsp.o AVCODECOBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dsp.o AVCODECOBJS-$(CONFIG_PIXBLOCKDSP) += pixblockdsp.o AVCODECOBJS-$(CONFIG_HEVC_DECODER) += hevc_add_res.o hevc_idct.o diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 6855c93b0a641..a8b34ba898f04 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -117,6 +117,9 @@ static const struct { { "hevc_add_res", checkasm_check_hevc_add_res }, { "hevc_idct", checkasm_check_hevc_idct }, #endif + #if CONFIG_HUFFYUV_DECODER + { "huffyuvdsp", checkasm_check_huffyuvdsp }, + #endif #if CONFIG_JPEG2000_DECODER { "jpeg2000dsp", checkasm_check_jpeg2000dsp }, #endif diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 933d868c02a6c..483f418cb5ab9 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -57,6 +57,7 @@ void checkasm_check_h264pred(void); void checkasm_check_h264qpel(void); void checkasm_check_hevc_add_res(void); void checkasm_check_hevc_idct(void); +void checkasm_check_huffyuvdsp(void); void checkasm_check_jpeg2000dsp(void); void checkasm_check_llviddsp(void); void checkasm_check_pixblockdsp(void); diff --git a/tests/checkasm/huffyuvdsp.c b/tests/checkasm/huffyuvdsp.c new file mode 100644 index 0000000000000..8392022c0488e --- /dev/null +++ b/tests/checkasm/huffyuvdsp.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016 Alexandra Hájková + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" + +#include "libavcodec/huffyuvdsp.h" + +#include "checkasm.h" + +#define randomize_buffers(buf, size) \ + do { \ + int j; \ + for (j = 0; j < size; j++) \ + buf[j] = rnd() & 0xFFFF; \ + } while (0) + +static void check_add_int16(HuffYUVDSPContext c, unsigned mask, int width, const char * name) +{ + uint16_t *src0 = av_mallocz(width * sizeof(uint16_t)); + uint16_t *src1 = av_mallocz(width * sizeof(uint16_t)); + uint16_t *dst0 = av_mallocz(width * sizeof(uint16_t)); + uint16_t *dst1 = av_mallocz(width * sizeof(uint16_t)); + + declare_func_emms(AV_CPU_FLAG_MMX, void, uint16_t *dst, uint16_t *src, unsigned mask, int w); + + if (!src0 || !src1 || !dst0 || !dst1) + fail(); + + randomize_buffers(src0, width); + memcpy(src1, src0, width * sizeof(uint16_t)); + + if (check_func(c.add_int16, "%s", name)) { + call_ref(dst0, src0, mask, width); + call_new(dst1, src1, mask, width); + if (memcmp(dst0, dst1, width * sizeof(uint16_t))) + fail(); + bench_new(dst1, src1, mask, width); + } + + av_free(src0); + av_free(src1); + av_free(dst0); + av_free(dst1); +} + +void checkasm_check_huffyuvdsp(void) +{ + HuffYUVDSPContext c; + int width = 16 * av_clip(rnd(), 16, 128); + + ff_huffyuvdsp_init(&c, AV_PIX_FMT_YUV422P); + + /*! test width not multiple of mmsize */ + check_add_int16(c, 65535, width, "add_int16_rnd_width"); + report("add_int16_rnd_width"); + + /*! test always with the same size (for perf test) */ + check_add_int16(c, 65535, 16*128, "add_int16_128"); + report("add_int16_128"); +} From 7f9b67bcb61d4ca012c67908d4f47cf28e5e22ae Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 09:10:52 +0100 Subject: [PATCH 1034/2557] avcodec/huffyuvdsp(enc) : move duplicate macro to a template file --- libavcodec/x86/huffyuvdsp.asm | 56 +------------------ libavcodec/x86/huffyuvdsp_init.c | 1 + libavcodec/x86/huffyuvdsp_template.asm | 76 ++++++++++++++++++++++++++ libavcodec/x86/huffyuvencdsp.asm | 56 +------------------ 4 files changed, 80 insertions(+), 109 deletions(-) create mode 100644 libavcodec/x86/huffyuvdsp_template.asm diff --git a/libavcodec/x86/huffyuvdsp.asm b/libavcodec/x86/huffyuvdsp.asm index 0d8cae354a504..623183354d527 100644 --- a/libavcodec/x86/huffyuvdsp.asm +++ b/libavcodec/x86/huffyuvdsp.asm @@ -24,61 +24,7 @@ SECTION .text - -%macro INT16_LOOP 2 ; %1 = a/u (aligned/unaligned), %2 = add/sub - movd m4, maskd - SPLATW m4, m4 - add wd, wd - test wq, 2*mmsize - 1 - jz %%.tomainloop - push tmpq -%%.wordloop: - sub wq, 2 -%ifidn %2, add - mov tmpw, [srcq+wq] - add tmpw, [dstq+wq] -%else - mov tmpw, [src1q+wq] - sub tmpw, [src2q+wq] -%endif - and tmpw, maskw - mov [dstq+wq], tmpw - test wq, 2*mmsize - 1 - jnz %%.wordloop - pop tmpq -%%.tomainloop: -%ifidn %2, add - add srcq, wq -%else - add src1q, wq - add src2q, wq -%endif - add dstq, wq - neg wq - jz %%.end -%%.loop: -%ifidn %2, add - mov%1 m0, [srcq+wq] - mov%1 m1, [dstq+wq] - mov%1 m2, [srcq+wq+mmsize] - mov%1 m3, [dstq+wq+mmsize] -%else - mov%1 m0, [src1q+wq] - mov%1 m1, [src2q+wq] - mov%1 m2, [src1q+wq+mmsize] - mov%1 m3, [src2q+wq+mmsize] -%endif - p%2w m0, m1 - p%2w m2, m3 - pand m0, m4 - pand m2, m4 - mov%1 [dstq+wq] , m0 - mov%1 [dstq+wq+mmsize], m2 - add wq, 2*mmsize - jl %%.loop -%%.end: - RET -%endmacro +%include "libavcodec/x86/huffyuvdsp_template.asm" %if ARCH_X86_32 INIT_MMX mmx diff --git a/libavcodec/x86/huffyuvdsp_init.c b/libavcodec/x86/huffyuvdsp_init.c index 26cf6214d8fb0..a522074565c25 100644 --- a/libavcodec/x86/huffyuvdsp_init.c +++ b/libavcodec/x86/huffyuvdsp_init.c @@ -28,6 +28,7 @@ void ff_add_int16_mmx(uint16_t *dst, const uint16_t *src, unsigned mask, int w); void ff_add_int16_sse2(uint16_t *dst, const uint16_t *src, unsigned mask, int w); + void ff_add_hfyu_left_pred_bgr32_mmx(uint8_t *dst, const uint8_t *src, intptr_t w, uint8_t *left); void ff_add_hfyu_left_pred_bgr32_sse2(uint8_t *dst, const uint8_t *src, diff --git a/libavcodec/x86/huffyuvdsp_template.asm b/libavcodec/x86/huffyuvdsp_template.asm new file mode 100644 index 0000000000000..7e14542671bd7 --- /dev/null +++ b/libavcodec/x86/huffyuvdsp_template.asm @@ -0,0 +1,76 @@ +;****************************************************************************** +;* SIMD-optimized HuffYUV functions +;* Copyright (c) 2008 Loren Merritt +;* Copyright (c) 2014 Christophe Gisquet +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%macro INT16_LOOP 2 ; %1 = a/u (aligned/unaligned), %2 = add/sub + movd m4, maskd + SPLATW m4, m4 + add wd, wd + test wq, 2*mmsize - 1 + jz %%.tomainloop + push tmpq +%%.wordloop: + sub wq, 2 +%ifidn %2, add + mov tmpw, [srcq+wq] + add tmpw, [dstq+wq] +%else + mov tmpw, [src1q+wq] + sub tmpw, [src2q+wq] +%endif + and tmpw, maskw + mov [dstq+wq], tmpw + test wq, 2*mmsize - 1 + jnz %%.wordloop + pop tmpq +%%.tomainloop: +%ifidn %2, add + add srcq, wq +%else + add src1q, wq + add src2q, wq +%endif + add dstq, wq + neg wq + jz %%.end +%%.loop: +%ifidn %2, add + mov%1 m0, [srcq+wq] + mov%1 m1, [dstq+wq] + mov%1 m2, [srcq+wq+mmsize] + mov%1 m3, [dstq+wq+mmsize] +%else + mov%1 m0, [src1q+wq] + mov%1 m1, [src2q+wq] + mov%1 m2, [src1q+wq+mmsize] + mov%1 m3, [src2q+wq+mmsize] +%endif + p%2w m0, m1 + p%2w m2, m3 + pand m0, m4 + pand m2, m4 + mov%1 [dstq+wq] , m0 + mov%1 [dstq+wq+mmsize], m2 + add wq, 2*mmsize + jl %%.loop +%%.end: + RET +%endmacro diff --git a/libavcodec/x86/huffyuvencdsp.asm b/libavcodec/x86/huffyuvencdsp.asm index eeef81ab8e584..6a7f1a0f49dda 100644 --- a/libavcodec/x86/huffyuvencdsp.asm +++ b/libavcodec/x86/huffyuvencdsp.asm @@ -27,62 +27,10 @@ SECTION .text +%include "libavcodec/x86/huffyuvdsp_template.asm" + ; void ff_diff_int16(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, ; unsigned mask, int w); -%macro INT16_LOOP 2 ; %1 = a/u (aligned/unaligned), %2 = add/sub - movd m4, maskd - SPLATW m4, m4 - add wd, wd - test wq, 2*mmsize - 1 - jz %%.tomainloop - push tmpq -%%.wordloop: - sub wq, 2 -%ifidn %2, add - mov tmpw, [srcq+wq] - add tmpw, [dstq+wq] -%else - mov tmpw, [src1q+wq] - sub tmpw, [src2q+wq] -%endif - and tmpw, maskw - mov [dstq+wq], tmpw - test wq, 2*mmsize - 1 - jnz %%.wordloop - pop tmpq -%%.tomainloop: -%ifidn %2, add - add srcq, wq -%else - add src1q, wq - add src2q, wq -%endif - add dstq, wq - neg wq - jz %%.end -%%.loop: -%ifidn %2, add - mov%1 m0, [srcq+wq] - mov%1 m1, [dstq+wq] - mov%1 m2, [srcq+wq+mmsize] - mov%1 m3, [dstq+wq+mmsize] -%else - mov%1 m0, [src1q+wq] - mov%1 m1, [src2q+wq] - mov%1 m2, [src1q+wq+mmsize] - mov%1 m3, [src2q+wq+mmsize] -%endif - p%2w m0, m1 - p%2w m2, m3 - pand m0, m4 - pand m2, m4 - mov%1 [dstq+wq] , m0 - mov%1 [dstq+wq+mmsize], m2 - add wq, 2*mmsize - jl %%.loop -%%.end: - RET -%endmacro %if ARCH_X86_32 INIT_MMX mmx From 6955e8842e248bec5adebd8527d2802fcc762493 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 09:11:36 +0100 Subject: [PATCH 1035/2557] avcodec/huffyuvdsp : reorganize add_int16 asm --- libavcodec/x86/huffyuvdsp.asm | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/libavcodec/x86/huffyuvdsp.asm b/libavcodec/x86/huffyuvdsp.asm index 623183354d527..6f038e17da612 100644 --- a/libavcodec/x86/huffyuvdsp.asm +++ b/libavcodec/x86/huffyuvdsp.asm @@ -26,21 +26,32 @@ SECTION .text %include "libavcodec/x86/huffyuvdsp_template.asm" -%if ARCH_X86_32 -INIT_MMX mmx -cglobal add_int16, 4,4,5, dst, src, mask, w, tmp - INT16_LOOP a, add -%endif +;------------------------------------------------------------------------------ +; void (*add_int16)(uint16_t *dst, const uint16_t *src, unsigned mask, int w); +;------------------------------------------------------------------------------ -INIT_XMM sse2 +%macro ADD_INT16 0 cglobal add_int16, 4,4,5, dst, src, mask, w, tmp +%if mmsize > 8 test srcq, mmsize-1 jnz .unaligned test dstq, mmsize-1 jnz .unaligned +%endif INT16_LOOP a, add +%if mmsize > 8 .unaligned: INT16_LOOP u, add +%endif +%endmacro + +%if ARCH_X86_32 +INIT_MMX mmx +ADD_INT16 +%endif + +INIT_XMM sse2 +ADD_INT16 ; void add_hfyu_left_pred_bgr32(uint8_t *dst, const uint8_t *src, ; intptr_t w, uint8_t *left) From e641c94190b6bc8a3278dd727cdfc8c6d9aca112 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 09:14:35 +0100 Subject: [PATCH 1036/2557] avcodec/huffyuvdsp : add add_int16 AVX2 func --- libavcodec/x86/huffyuvdsp.asm | 5 +++++ libavcodec/x86/huffyuvdsp_init.c | 5 +++++ libavcodec/x86/huffyuvdsp_template.asm | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libavcodec/x86/huffyuvdsp.asm b/libavcodec/x86/huffyuvdsp.asm index 6f038e17da612..a1231f1b22622 100644 --- a/libavcodec/x86/huffyuvdsp.asm +++ b/libavcodec/x86/huffyuvdsp.asm @@ -53,6 +53,11 @@ ADD_INT16 INIT_XMM sse2 ADD_INT16 +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +ADD_INT16 +%endif + ; void add_hfyu_left_pred_bgr32(uint8_t *dst, const uint8_t *src, ; intptr_t w, uint8_t *left) %macro LEFT_BGR32 0 diff --git a/libavcodec/x86/huffyuvdsp_init.c b/libavcodec/x86/huffyuvdsp_init.c index a522074565c25..eb10de383d23a 100644 --- a/libavcodec/x86/huffyuvdsp_init.c +++ b/libavcodec/x86/huffyuvdsp_init.c @@ -28,6 +28,7 @@ void ff_add_int16_mmx(uint16_t *dst, const uint16_t *src, unsigned mask, int w); void ff_add_int16_sse2(uint16_t *dst, const uint16_t *src, unsigned mask, int w); +void ff_add_int16_avx2(uint16_t *dst, const uint16_t *src, unsigned mask, int w); void ff_add_hfyu_left_pred_bgr32_mmx(uint8_t *dst, const uint8_t *src, intptr_t w, uint8_t *left); @@ -53,4 +54,8 @@ av_cold void ff_huffyuvdsp_init_x86(HuffYUVDSPContext *c, enum AVPixelFormat pix c->add_int16 = ff_add_int16_sse2; c->add_hfyu_left_pred_bgr32 = ff_add_hfyu_left_pred_bgr32_sse2; } + + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + c->add_int16 = ff_add_int16_avx2; + } } diff --git a/libavcodec/x86/huffyuvdsp_template.asm b/libavcodec/x86/huffyuvdsp_template.asm index 7e14542671bd7..89721f4ec3af1 100644 --- a/libavcodec/x86/huffyuvdsp_template.asm +++ b/libavcodec/x86/huffyuvdsp_template.asm @@ -21,8 +21,8 @@ ;****************************************************************************** %macro INT16_LOOP 2 ; %1 = a/u (aligned/unaligned), %2 = add/sub - movd m4, maskd - SPLATW m4, m4 + movd xm4, maskd + SPLATW m4, xm4 add wd, wd test wq, 2*mmsize - 1 jz %%.tomainloop From d189a426fa0e7b8a7bb62d797ed490ece868da28 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 09:16:18 +0100 Subject: [PATCH 1037/2557] avcodec/huffyuvdspenc : reorganize diff_int16 --- libavcodec/x86/huffyuvencdsp.asm | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/libavcodec/x86/huffyuvencdsp.asm b/libavcodec/x86/huffyuvencdsp.asm index 6a7f1a0f49dda..3f5a7df7ff427 100644 --- a/libavcodec/x86/huffyuvencdsp.asm +++ b/libavcodec/x86/huffyuvencdsp.asm @@ -29,26 +29,36 @@ SECTION .text %include "libavcodec/x86/huffyuvdsp_template.asm" +;------------------------------------------------------------------------------ ; void ff_diff_int16(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, ; unsigned mask, int w); +;------------------------------------------------------------------------------ -%if ARCH_X86_32 -INIT_MMX mmx -cglobal diff_int16, 5,5,5, dst, src1, src2, mask, w, tmp - INT16_LOOP a, sub -%endif - -INIT_XMM sse2 +%macro DIFF_INT16 0 cglobal diff_int16, 5,5,5, dst, src1, src2, mask, w, tmp +%if mmsize > 8 test src1q, mmsize-1 jnz .unaligned test src2q, mmsize-1 jnz .unaligned test dstq, mmsize-1 jnz .unaligned +%endif INT16_LOOP a, sub +%if mmsize > 8 .unaligned: INT16_LOOP u, sub +%endif +%endmacro + +%if ARCH_X86_32 +INIT_MMX mmx +DIFF_INT16 +%endif + +INIT_XMM sse2 +DIFF_INT16 + INIT_MMX mmxext cglobal sub_hfyu_median_pred_int16, 7,7,0, dst, src1, src2, mask, w, left, left_top From ba98f8463fd1345fab173fa405ac98aefd92ed06 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 09:17:44 +0100 Subject: [PATCH 1038/2557] avcodec/huffyuvdspenc : add diff_int16 AVX2 func --- libavcodec/x86/huffyuvencdsp.asm | 4 ++++ libavcodec/x86/huffyuvencdsp_init.c | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/libavcodec/x86/huffyuvencdsp.asm b/libavcodec/x86/huffyuvencdsp.asm index 3f5a7df7ff427..d994fd0fd6339 100644 --- a/libavcodec/x86/huffyuvencdsp.asm +++ b/libavcodec/x86/huffyuvencdsp.asm @@ -59,6 +59,10 @@ DIFF_INT16 INIT_XMM sse2 DIFF_INT16 +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +DIFF_INT16 +%endif INIT_MMX mmxext cglobal sub_hfyu_median_pred_int16, 7,7,0, dst, src1, src2, mask, w, left, left_top diff --git a/libavcodec/x86/huffyuvencdsp_init.c b/libavcodec/x86/huffyuvencdsp_init.c index f66bc8c4f0a79..6c6e068cf8fc3 100644 --- a/libavcodec/x86/huffyuvencdsp_init.c +++ b/libavcodec/x86/huffyuvencdsp_init.c @@ -32,6 +32,8 @@ void ff_diff_int16_mmx (uint16_t *dst, const uint16_t *src1, const uint16_t *src unsigned mask, int w); void ff_diff_int16_sse2(uint16_t *dst, const uint16_t *src1, const uint16_t *src2, unsigned mask, int w); +void ff_diff_int16_avx2(uint16_t *dst, const uint16_t *src1, const uint16_t *src2, + unsigned mask, int w); void ff_sub_hfyu_median_pred_int16_mmxext(uint16_t *dst, const uint16_t *src1, const uint16_t *src2, unsigned mask, int w, int *left, int *left_top); @@ -51,4 +53,8 @@ av_cold void ff_huffyuvencdsp_init_x86(HuffYUVEncDSPContext *c, AVCodecContext * if (EXTERNAL_SSE2(cpu_flags)) { c->diff_int16 = ff_diff_int16_sse2; } + + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + c->diff_int16 = ff_diff_int16_avx2; + } } From 518b9ee3d16fa0a04c2c11bc86a64fb46fc25702 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 11:55:37 +0100 Subject: [PATCH 1039/2557] avcodec/hapdec : reorganize code before adding multi-texture decoding --- libavcodec/hap.h | 2 ++ libavcodec/hapdec.c | 39 ++++++++++++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/libavcodec/hap.h b/libavcodec/hap.h index 0ee65335d913b..b80511d6a4b51 100644 --- a/libavcodec/hap.h +++ b/libavcodec/hap.h @@ -81,6 +81,8 @@ typedef struct HapContext { int slice_count; /* Number of slices for threaded operations */ + int texture_count; /* 2 for HAQA, 1 for other version */ + /* Pointer to the selected compress or decompress function */ int (*tex_fun)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); } HapContext; diff --git a/libavcodec/hapdec.c b/libavcodec/hapdec.c index fc9dff10f1923..e5b448112a053 100644 --- a/libavcodec/hapdec.c +++ b/libavcodec/hapdec.c @@ -266,8 +266,8 @@ static int decompress_chunks_thread(AVCodecContext *avctx, void *arg, return 0; } -static int decompress_texture_thread(AVCodecContext *avctx, void *arg, - int slice, int thread_nb) +static int decompress_texture_thread_internal(AVCodecContext *avctx, void *arg, + int slice, int thread_nb, int texture_num) { HapContext *ctx = avctx->priv_data; AVFrame *frame = arg; @@ -295,34 +295,50 @@ static int decompress_texture_thread(AVCodecContext *avctx, void *arg, uint8_t *p = frame->data[0] + y * frame->linesize[0] * TEXTURE_BLOCK_H; int off = y * w_block; for (x = 0; x < w_block; x++) { - ctx->tex_fun(p + x * 16, frame->linesize[0], - d + (off + x) * ctx->tex_rat); + if (texture_num == 0) { + ctx->tex_fun(p + x * 16, frame->linesize[0], + d + (off + x) * ctx->tex_rat); + } } } return 0; } +static int decompress_texture_thread(AVCodecContext *avctx, void *arg, + int slice, int thread_nb) +{ + return decompress_texture_thread_internal(avctx, arg, slice, thread_nb, 0); +} + static int hap_decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { HapContext *ctx = avctx->priv_data; ThreadFrame tframe; - int ret, i; + int ret, i, t; int tex_size; + int start_texture_section = 0; + int tex_rat[2] = {0, 0}; bytestream2_init(&ctx->gbc, avpkt->data, avpkt->size); - /* Check for section header */ - ret = hap_parse_frame_header(avctx); - if (ret < 0) - return ret; + tex_rat[0] = ctx->tex_rat; /* Get the output frame ready to receive data */ tframe.f = data; ret = ff_thread_get_buffer(avctx, &tframe, 0); if (ret < 0) return ret; + + for (t = 0; t < ctx->texture_count; t++) { + bytestream2_seek(&ctx->gbc, start_texture_section, SEEK_SET); + + /* Check for section header */ + ret = hap_parse_frame_header(avctx); + if (ret < 0) + return ret; + if (avctx->codec->update_thread_context) ff_thread_finish_setup(avctx); @@ -357,7 +373,10 @@ static int hap_decode(AVCodecContext *avctx, void *data, } /* Use the decompress function on the texture, one block per thread */ + if (t == 0){ avctx->execute2(avctx, decompress_texture_thread, tframe.f, NULL, ctx->slice_count); + } + } /* Frame is ready to be output */ tframe.f->pict_type = AV_PICTURE_TYPE_I; @@ -385,6 +404,8 @@ static av_cold int hap_init(AVCodecContext *avctx) ff_texturedsp_init(&ctx->dxtc); + ctx->texture_count = 1; + switch (avctx->codec_tag) { case MKTAG('H','a','p','1'): texture_name = "DXT1"; From fca89199615928a21cb0b5b7a0839eb04f972f55 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 11:55:56 +0100 Subject: [PATCH 1040/2557] avcodec/hapdec : indent after previous commit --- libavcodec/hapdec.c | 66 ++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/libavcodec/hapdec.c b/libavcodec/hapdec.c index e5b448112a053..6b6279b696b9e 100644 --- a/libavcodec/hapdec.c +++ b/libavcodec/hapdec.c @@ -334,47 +334,47 @@ static int hap_decode(AVCodecContext *avctx, void *data, for (t = 0; t < ctx->texture_count; t++) { bytestream2_seek(&ctx->gbc, start_texture_section, SEEK_SET); - /* Check for section header */ - ret = hap_parse_frame_header(avctx); - if (ret < 0) - return ret; - - if (avctx->codec->update_thread_context) - ff_thread_finish_setup(avctx); - - /* Unpack the DXT texture */ - if (hap_can_use_tex_in_place(ctx)) { - /* Only DXTC texture compression in a contiguous block */ - ctx->tex_data = ctx->gbc.buffer; - tex_size = bytestream2_get_bytes_left(&ctx->gbc); - } else { - /* Perform the second-stage decompression */ - ret = av_reallocp(&ctx->tex_buf, ctx->tex_size); + /* Check for section header */ + ret = hap_parse_frame_header(avctx); if (ret < 0) return ret; - avctx->execute2(avctx, decompress_chunks_thread, NULL, - ctx->chunk_results, ctx->chunk_count); + if (avctx->codec->update_thread_context) + ff_thread_finish_setup(avctx); - for (i = 0; i < ctx->chunk_count; i++) { - if (ctx->chunk_results[i] < 0) - return ctx->chunk_results[i]; - } + /* Unpack the DXT texture */ + if (hap_can_use_tex_in_place(ctx)) { + /* Only DXTC texture compression in a contiguous block */ + ctx->tex_data = ctx->gbc.buffer; + tex_size = bytestream2_get_bytes_left(&ctx->gbc); + } else { + /* Perform the second-stage decompression */ + ret = av_reallocp(&ctx->tex_buf, ctx->tex_size); + if (ret < 0) + return ret; - ctx->tex_data = ctx->tex_buf; - tex_size = ctx->tex_size; - } + avctx->execute2(avctx, decompress_chunks_thread, NULL, + ctx->chunk_results, ctx->chunk_count); - if (tex_size < (avctx->coded_width / TEXTURE_BLOCK_W) - *(avctx->coded_height / TEXTURE_BLOCK_H) - *ctx->tex_rat) { - av_log(avctx, AV_LOG_ERROR, "Insufficient data\n"); - return AVERROR_INVALIDDATA; - } + for (i = 0; i < ctx->chunk_count; i++) { + if (ctx->chunk_results[i] < 0) + return ctx->chunk_results[i]; + } + + ctx->tex_data = ctx->tex_buf; + tex_size = ctx->tex_size; + } + + if (tex_size < (avctx->coded_width / TEXTURE_BLOCK_W) + *(avctx->coded_height / TEXTURE_BLOCK_H) + *ctx->tex_rat) { + av_log(avctx, AV_LOG_ERROR, "Insufficient data\n"); + return AVERROR_INVALIDDATA; + } - /* Use the decompress function on the texture, one block per thread */ + /* Use the decompress function on the texture, one block per thread */ if (t == 0){ - avctx->execute2(avctx, decompress_texture_thread, tframe.f, NULL, ctx->slice_count); + avctx->execute2(avctx, decompress_texture_thread, tframe.f, NULL, ctx->slice_count); } } From 2053832d1caae1cb37250d8a2c08591e07c65774 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 11:59:02 +0100 Subject: [PATCH 1041/2557] avcodec/hapdec : add support for hapqa decoding --- libavcodec/hap.h | 3 +++ libavcodec/hapdec.c | 53 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/libavcodec/hap.h b/libavcodec/hap.h index b80511d6a4b51..4dfbb8cb16325 100644 --- a/libavcodec/hap.h +++ b/libavcodec/hap.h @@ -73,6 +73,7 @@ typedef struct HapContext { int *chunk_results; /* Results from threaded operations */ int tex_rat; /* Compression ratio */ + int tex_rat2; /* Compression ratio of the second texture */ const uint8_t *tex_data; /* Compressed texture */ uint8_t *tex_buf; /* Buffer for compressed texture */ size_t tex_size; /* Size of the compressed texture */ @@ -82,9 +83,11 @@ typedef struct HapContext { int slice_count; /* Number of slices for threaded operations */ int texture_count; /* 2 for HAQA, 1 for other version */ + int texture_section_size; /* size of the part of the texture section (for HAPQA) */ /* Pointer to the selected compress or decompress function */ int (*tex_fun)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*tex_fun2)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); } HapContext; /* diff --git a/libavcodec/hapdec.c b/libavcodec/hapdec.c index 6b6279b696b9e..a1abb3285f8d5 100644 --- a/libavcodec/hapdec.c +++ b/libavcodec/hapdec.c @@ -3,6 +3,8 @@ * Copyright (C) 2015 Vittorio Giovara * Copyright (C) 2015 Tom Butterworth * + * HapQA and HAPAlphaOnly added by Jokyo Images + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -157,14 +159,16 @@ static int hap_parse_frame_header(AVCodecContext *avctx) const char *compressorstr; int i, ret; - ret = parse_section_header(gbc, §ion_size, §ion_type); + ret = parse_section_header(gbc, &ctx->texture_section_size, §ion_type); if (ret != 0) return ret; if ((avctx->codec_tag == MKTAG('H','a','p','1') && (section_type & 0x0F) != HAP_FMT_RGBDXT1) || (avctx->codec_tag == MKTAG('H','a','p','5') && (section_type & 0x0F) != HAP_FMT_RGBADXT5) || (avctx->codec_tag == MKTAG('H','a','p','Y') && (section_type & 0x0F) != HAP_FMT_YCOCGDXT5) || - (avctx->codec_tag == MKTAG('H','a','p','A') && (section_type & 0x0F) != HAP_FMT_RGTC1)) { + (avctx->codec_tag == MKTAG('H','a','p','A') && (section_type & 0x0F) != HAP_FMT_RGTC1) || + ((avctx->codec_tag == MKTAG('H','a','p','M') && (section_type & 0x0F) != HAP_FMT_RGTC1) && + (section_type & 0x0F) != HAP_FMT_YCOCGDXT5)) { av_log(avctx, AV_LOG_ERROR, "Invalid texture format %#04x.\n", section_type & 0x0F); return AVERROR_INVALIDDATA; @@ -177,7 +181,7 @@ static int hap_parse_frame_header(AVCodecContext *avctx) if (ret == 0) { ctx->chunks[0].compressor = section_type & 0xF0; ctx->chunks[0].compressed_offset = 0; - ctx->chunks[0].compressed_size = section_size; + ctx->chunks[0].compressed_size = ctx->texture_section_size; } if (ctx->chunks[0].compressor == HAP_COMP_NONE) { compressorstr = "none"; @@ -298,6 +302,9 @@ static int decompress_texture_thread_internal(AVCodecContext *avctx, void *arg, if (texture_num == 0) { ctx->tex_fun(p + x * 16, frame->linesize[0], d + (off + x) * ctx->tex_rat); + } else { + ctx->tex_fun2(p + x * 16, frame->linesize[0], + d + (off + x) * ctx->tex_rat2); } } } @@ -311,6 +318,12 @@ static int decompress_texture_thread(AVCodecContext *avctx, void *arg, return decompress_texture_thread_internal(avctx, arg, slice, thread_nb, 0); } +static int decompress_texture2_thread(AVCodecContext *avctx, void *arg, + int slice, int thread_nb) +{ + return decompress_texture_thread_internal(avctx, arg, slice, thread_nb, 1); +} + static int hap_decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { @@ -318,6 +331,8 @@ static int hap_decode(AVCodecContext *avctx, void *data, ThreadFrame tframe; int ret, i, t; int tex_size; + int section_size; + enum HapSectionType section_type; int start_texture_section = 0; int tex_rat[2] = {0, 0}; @@ -325,6 +340,19 @@ static int hap_decode(AVCodecContext *avctx, void *data, tex_rat[0] = ctx->tex_rat; + /* check for multi texture header */ + if (ctx->texture_count == 2) { + ret = parse_section_header(&ctx->gbc, §ion_size, §ion_type); + if (ret != 0) + return ret; + if ((section_type & 0x0F) != 0x0D) { + av_log(avctx, AV_LOG_ERROR, "Invalid section type in 2 textures mode %#04x.\n", section_type); + return AVERROR_INVALIDDATA; + } + start_texture_section = 4; + tex_rat[1] = ctx->tex_rat2; + } + /* Get the output frame ready to receive data */ tframe.f = data; ret = ff_thread_get_buffer(avctx, &tframe, 0); @@ -339,6 +367,8 @@ static int hap_decode(AVCodecContext *avctx, void *data, if (ret < 0) return ret; + start_texture_section += ctx->texture_section_size + 4; + if (avctx->codec->update_thread_context) ff_thread_finish_setup(avctx); @@ -346,7 +376,7 @@ static int hap_decode(AVCodecContext *avctx, void *data, if (hap_can_use_tex_in_place(ctx)) { /* Only DXTC texture compression in a contiguous block */ ctx->tex_data = ctx->gbc.buffer; - tex_size = bytestream2_get_bytes_left(&ctx->gbc); + tex_size = FFMIN(ctx->texture_section_size, bytestream2_get_bytes_left(&ctx->gbc)); } else { /* Perform the second-stage decompression */ ret = av_reallocp(&ctx->tex_buf, ctx->tex_size); @@ -367,7 +397,7 @@ static int hap_decode(AVCodecContext *avctx, void *data, if (tex_size < (avctx->coded_width / TEXTURE_BLOCK_W) *(avctx->coded_height / TEXTURE_BLOCK_H) - *ctx->tex_rat) { + *tex_rat[t]) { av_log(avctx, AV_LOG_ERROR, "Insufficient data\n"); return AVERROR_INVALIDDATA; } @@ -375,6 +405,9 @@ static int hap_decode(AVCodecContext *avctx, void *data, /* Use the decompress function on the texture, one block per thread */ if (t == 0){ avctx->execute2(avctx, decompress_texture_thread, tframe.f, NULL, ctx->slice_count); + } else{ + tframe.f = data; + avctx->execute2(avctx, decompress_texture2_thread, tframe.f, NULL, ctx->slice_count); } } @@ -432,8 +465,14 @@ static av_cold int hap_init(AVCodecContext *avctx) avctx->pix_fmt = AV_PIX_FMT_RGB0; break; case MKTAG('H','a','p','M'): - avpriv_report_missing_feature(avctx, "HapQAlpha"); - return AVERROR_PATCHWELCOME; + texture_name = "DXT5-YCoCg-scaled / RGTC1"; + ctx->tex_rat = 16; + ctx->tex_rat2 = 8; + ctx->tex_fun = ctx->dxtc.dxt5ys_block; + ctx->tex_fun2 = ctx->dxtc.rgtc1u_alpha_block; + avctx->pix_fmt = AV_PIX_FMT_RGBA; + ctx->texture_count = 2; + break; default: return AVERROR_DECODER_NOT_FOUND; } From 37810bee7839f7524e68db83c3aef7b7474fce80 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 12:01:00 +0100 Subject: [PATCH 1042/2557] fate/hapdec : add test for hapqa decoding --- tests/fate/video.mak | 9 +++++++++ tests/ref/fate/hapqa-nosnappy-127x71 | 6 ++++++ tests/ref/fate/hapqa-snappy1-127x71 | 6 ++++++ tests/ref/fate/hapqa-snappy16-127x71 | 6 ++++++ 4 files changed, 27 insertions(+) create mode 100644 tests/ref/fate/hapqa-nosnappy-127x71 create mode 100644 tests/ref/fate/hapqa-snappy1-127x71 create mode 100644 tests/ref/fate/hapqa-snappy16-127x71 diff --git a/tests/fate/video.mak b/tests/fate/video.mak index c7f2dcea9e0f4..d2d5b60e9a2df 100644 --- a/tests/fate/video.mak +++ b/tests/fate/video.mak @@ -183,6 +183,15 @@ fate-hapy: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hapy.mov FATE_HAP += fate-hap-chunk fate-hap-chunk: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hapy-12-chunks.mov +FATE_HAP += fate-hapqa-nosnappy-127x71 +fate-hapqa-nosnappy-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_NoSnappy_127x1.mov + +FATE_HAP += fate-hapqa-snappy1-127x71 +fate-hapqa-snappy1-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_Snappy_1chunk_127x1.mov + +FATE_HAP += fate-hapqa-snappy16-127x71 +fate-hapqa-snappy16-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_Snappy_16chunk_127x1.mov + FATE_VIDEO-$(call DEMDEC, MOV, HAP) += $(FATE_HAP) fate-hap: $(FATE_HAP) diff --git a/tests/ref/fate/hapqa-nosnappy-127x71 b/tests/ref/fate/hapqa-nosnappy-127x71 new file mode 100644 index 0000000000000..36069b4849f7b --- /dev/null +++ b/tests/ref/fate/hapqa-nosnappy-127x71 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 127x71 +#sar 0: 1/1 +0, 0, 0, 1, 36068, 0x16c0a011 diff --git a/tests/ref/fate/hapqa-snappy1-127x71 b/tests/ref/fate/hapqa-snappy1-127x71 new file mode 100644 index 0000000000000..36069b4849f7b --- /dev/null +++ b/tests/ref/fate/hapqa-snappy1-127x71 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 127x71 +#sar 0: 1/1 +0, 0, 0, 1, 36068, 0x16c0a011 diff --git a/tests/ref/fate/hapqa-snappy16-127x71 b/tests/ref/fate/hapqa-snappy16-127x71 new file mode 100644 index 0000000000000..36069b4849f7b --- /dev/null +++ b/tests/ref/fate/hapqa-snappy16-127x71 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 127x71 +#sar 0: 1/1 +0, 0, 0, 1, 36068, 0x16c0a011 From afd2bf54c31b501244941e93bff364c6aa60e02c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 21 Nov 2017 12:07:13 +0100 Subject: [PATCH 1043/2557] avfilter/avf_avectorscope: add swap and mirror options Signed-off-by: Paul B Mahol --- doc/filters.texi | 20 ++++++++++++++++++++ libavfilter/avf_avectorscope.c | 17 +++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 63ce899784ffa..62f633c6f888a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -17232,6 +17232,26 @@ Cubic root. Logarithmic. @end table +@item swap +Swap left channel axis with right channel axis. + +@item mirror +Mirror axis. + +@table @samp +@item none +No mirror. + +@item x +Mirror only x axis. + +@item y +Mirror only y axis. + +@item xy +Mirror both axis. +@end table + @end table @subsection Examples diff --git a/libavfilter/avf_avectorscope.c b/libavfilter/avf_avectorscope.c index c8ff0698e3c4c..725ac8bbda1b8 100644 --- a/libavfilter/avf_avectorscope.c +++ b/libavfilter/avf_avectorscope.c @@ -65,6 +65,8 @@ typedef struct AudioVectorScopeContext { int contrast[4]; int fade[4]; double zoom; + int swap; + int mirror; unsigned prev_x, prev_y; AVRational frame_rate; } AudioVectorScopeContext; @@ -99,6 +101,12 @@ static const AVOption avectorscope_options[] = { { "sqrt", "square root", 0, AV_OPT_TYPE_CONST, {.i64=SQRT}, 0, 0, FLAGS, "scale" }, { "cbrt", "cube root", 0, AV_OPT_TYPE_CONST, {.i64=CBRT}, 0, 0, FLAGS, "scale" }, { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=LOG}, 0, 0, FLAGS, "scale" }, + { "swap", "swap x axis with y axis", OFFSET(swap), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, + { "mirror", "mirror axis", OFFSET(mirror), AV_OPT_TYPE_INT, {.i64=2}, 0, 3, FLAGS, "mirror" }, + { "none", "no mirror", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mirror" }, + { "x", "mirror x", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mirror" }, + { "y", "mirror y", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "mirror" }, + { "xy", "mirror both", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "mirror" }, { NULL } }; @@ -316,6 +324,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) break; } + if (s->mirror & 1) + src[0] = -src[0]; + + if (s->mirror & 2) + src[1] = -src[1]; + + if (s->swap) + FFSWAP(float, src[0], src[1]);; + if (s->mode == LISSAJOUS) { x = ((src[1] - src[0]) * zoom / 2 + 1) * hw; y = (1.0 - (src[0] + src[1]) * zoom / 2) * hh; From ebf352116b310d08d35b0eeae83686a6e739da1d Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 21 Nov 2017 10:57:03 -0300 Subject: [PATCH 1044/2557] x86/constants: make pb_80 32 byte wide Signed-off-by: James Almer --- libavcodec/x86/constants.c | 3 ++- libavcodec/x86/constants.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/x86/constants.c b/libavcodec/x86/constants.c index 47905c74a17c7..4bfb78cc36116 100644 --- a/libavcodec/x86/constants.c +++ b/libavcodec/x86/constants.c @@ -74,7 +74,8 @@ DECLARE_ALIGNED(32, const ymm_reg, ff_pb_2) = { 0x0202020202020202ULL, 0x020 DECLARE_ALIGNED(32, const ymm_reg, ff_pb_3) = { 0x0303030303030303ULL, 0x0303030303030303ULL, 0x0303030303030303ULL, 0x0303030303030303ULL }; DECLARE_ALIGNED(32, const xmm_reg, ff_pb_15) = { 0x0F0F0F0F0F0F0F0FULL, 0x0F0F0F0F0F0F0F0FULL }; -DECLARE_ALIGNED(16, const xmm_reg, ff_pb_80) = { 0x8080808080808080ULL, 0x8080808080808080ULL }; +DECLARE_ALIGNED(32, const ymm_reg, ff_pb_80) = { 0x8080808080808080ULL, 0x8080808080808080ULL, + 0x8080808080808080ULL, 0x8080808080808080ULL }; DECLARE_ALIGNED(32, const ymm_reg, ff_pb_FE) = { 0xFEFEFEFEFEFEFEFEULL, 0xFEFEFEFEFEFEFEFEULL, 0xFEFEFEFEFEFEFEFEULL, 0xFEFEFEFEFEFEFEFEULL }; DECLARE_ALIGNED(8, const uint64_t, ff_pb_FC) = 0xFCFCFCFCFCFCFCFCULL; diff --git a/libavcodec/x86/constants.h b/libavcodec/x86/constants.h index bbb0ef844aa92..85da38b7b948c 100644 --- a/libavcodec/x86/constants.h +++ b/libavcodec/x86/constants.h @@ -57,7 +57,7 @@ extern const ymm_reg ff_pb_0; extern const ymm_reg ff_pb_1; extern const ymm_reg ff_pb_2; extern const ymm_reg ff_pb_3; -extern const xmm_reg ff_pb_80; +extern const ymm_reg ff_pb_80; extern const ymm_reg ff_pb_FE; extern const uint64_t ff_pb_FC; From beb63baa6961698982e5e59037be1854e532425c Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 21 Nov 2017 10:57:06 -0300 Subject: [PATCH 1045/2557] x86/utvideodsp: reuse shared constants Remove the broadcast instructions as well now that they are wide enough. Signed-off-by: James Almer --- libavcodec/x86/utvideodsp.asm | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/libavcodec/x86/utvideodsp.asm b/libavcodec/x86/utvideodsp.asm index 6e13de39aada1..b799c44b64007 100644 --- a/libavcodec/x86/utvideodsp.asm +++ b/libavcodec/x86/utvideodsp.asm @@ -24,9 +24,9 @@ SECTION_RODATA -pb_128: times 16 db 128 -pw_512: times 8 dw 512 -pw_1023: times 8 dw 1023 +cextern pb_80 +cextern pw_512 +cextern pw_1023 SECTION .text @@ -48,11 +48,7 @@ DEFINE_ARGS src_r, src_g, src_b, linesize_r, linesize_g, linesize_b, x %define wq r6m %define hd r7mp %endif -%if mmsize == 32 - vbroadcasti128 m3, [pb_128] -%else - mova m3, [pb_128] -%endif + mova m3, [pb_80] .nextrow: mov xq, wq @@ -98,13 +94,8 @@ cglobal restore_rgb_planes10, 7 + ARCH_X86_64, 7 + ARCH_X86_64 * 2, 5, src_r, sr add src_rq, wq add src_gq, wq add src_bq, wq -%if mmsize == 32 - vbroadcasti128 m3, [pw_512] - vbroadcasti128 m4, [pw_1023] -%else mova m3, [pw_512] mova m4, [pw_1023] -%endif neg wq %if ARCH_X86_64 == 0 mov wm, wq From 9a05c873cf2c2f1f4e85e3df82cde1eb86b6752d Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 21 Nov 2017 11:13:24 -0300 Subject: [PATCH 1046/2557] checkasm/utvideodsp: fix mixed declarations and code Signed-off-by: James Almer --- tests/checkasm/utvideodsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/checkasm/utvideodsp.c b/tests/checkasm/utvideodsp.c index 6ef2fb21f05f9..e811f523e5cc7 100644 --- a/tests/checkasm/utvideodsp.c +++ b/tests/checkasm/utvideodsp.c @@ -60,6 +60,9 @@ LOCAL_ALIGNED_32(type, src_b0, [BUFFER_SIZE]); \ LOCAL_ALIGNED_32(type, src_r1, [BUFFER_SIZE]); \ LOCAL_ALIGNED_32(type, src_g1, [BUFFER_SIZE]); \ LOCAL_ALIGNED_32(type, src_b1, [BUFFER_SIZE]); \ +declare_func(void, type *src_r, type *src_g, type *src_b, \ + ptrdiff_t linesize_r, ptrdiff_t linesize_g, \ + ptrdiff_t linesize_b, int width, int height); \ memset(src_r0, 0, BUFFER_SIZE); \ memset(src_g0, 0, BUFFER_SIZE); \ memset(src_b0, 0, BUFFER_SIZE); \ @@ -69,9 +72,6 @@ randomize_plane(src_b0, type); \ memcpy(src_r1, src_r0, BUFFER_SIZE * sizeof(type)); \ memcpy(src_g1, src_g0, BUFFER_SIZE * sizeof(type)); \ memcpy(src_b1, src_b0, BUFFER_SIZE * sizeof(type)); \ -declare_func(void, type *src_r, type *src_g, type *src_b, \ - ptrdiff_t linesize_r, ptrdiff_t linesize_g, \ - ptrdiff_t linesize_b, int width, int height); \ call_ref(src_r0, src_g0, src_b0, WIDTH_PADDED, WIDTH_PADDED, WIDTH_PADDED, WIDTH, HEIGHT);\ call_new(src_r1, src_g1, src_b1, WIDTH_PADDED, WIDTH_PADDED, WIDTH_PADDED, WIDTH, HEIGHT);\ cmp_plane(src_r0, src_r1, sizeof(type)); \ From bea8eeaa2c0c97f76bdedc02a1a01296b5bcaa28 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 21 Nov 2017 11:14:33 -0300 Subject: [PATCH 1047/2557] checkasm/utvideodsp: zero initialize the entire buffer Signed-off-by: James Almer --- tests/checkasm/utvideodsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/checkasm/utvideodsp.c b/tests/checkasm/utvideodsp.c index e811f523e5cc7..618706a6e3b14 100644 --- a/tests/checkasm/utvideodsp.c +++ b/tests/checkasm/utvideodsp.c @@ -63,9 +63,9 @@ LOCAL_ALIGNED_32(type, src_b1, [BUFFER_SIZE]); \ declare_func(void, type *src_r, type *src_g, type *src_b, \ ptrdiff_t linesize_r, ptrdiff_t linesize_g, \ ptrdiff_t linesize_b, int width, int height); \ -memset(src_r0, 0, BUFFER_SIZE); \ -memset(src_g0, 0, BUFFER_SIZE); \ -memset(src_b0, 0, BUFFER_SIZE); \ +memset(src_r0, 0, BUFFER_SIZE * sizeof(type)); \ +memset(src_g0, 0, BUFFER_SIZE * sizeof(type)); \ +memset(src_b0, 0, BUFFER_SIZE * sizeof(type)); \ randomize_plane(src_r0, type); \ randomize_plane(src_g0, type); \ randomize_plane(src_b0, type); \ From 000836c2a98e1c6a2867dd9db0371c137609acf0 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 20 Nov 2017 14:02:28 +0100 Subject: [PATCH 1048/2557] avfilter/af_asetnsamples: add missing error check Signed-off-by: Paul B Mahol --- libavfilter/af_asetnsamples.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavfilter/af_asetnsamples.c b/libavfilter/af_asetnsamples.c index 3c2f66b30aa48..ecb76e64db4a4 100644 --- a/libavfilter/af_asetnsamples.c +++ b/libavfilter/af_asetnsamples.c @@ -140,11 +140,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) return -1; } } - av_audio_fifo_write(asns->fifo, (void **)insamples->extended_data, nb_samples); - if (asns->next_out_pts == AV_NOPTS_VALUE) + ret = av_audio_fifo_write(asns->fifo, (void **)insamples->extended_data, nb_samples); + if (ret > 0 && asns->next_out_pts == AV_NOPTS_VALUE) asns->next_out_pts = insamples->pts; av_frame_free(&insamples); + if (ret < 0) + return ret; + while (av_audio_fifo_size(asns->fifo) >= asns->nb_out_samples) push_samples(outlink); return 0; From 0e7865ce4152f8b04cda6a698bbee4fd4a94009d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 21 Nov 2017 03:15:53 +0100 Subject: [PATCH 1049/2557] avcodec/mpeg4videodec: Check also for negative versions in the validity check Signed-off-by: Michael Niedermayer --- libavcodec/mpeg4videodec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 11d4e08986ace..69f455e22677d 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -2154,7 +2154,7 @@ static int decode_user_data(Mpeg4DecContext *ctx, GetBitContext *gb) if (e != 4) { e = sscanf(buf, "Lavc%d.%d.%d", &ver, &ver2, &ver3) + 1; if (e > 1) { - if (ver > 0xFF || ver2 > 0xFF || ver3 > 0xFF) { + if (ver > 0xFFU || ver2 > 0xFFU || ver3 > 0xFFU) { av_log(s->avctx, AV_LOG_WARNING, "Unknown Lavc version string encountered, %d.%d.%d; " "clamping sub-version values to 8-bits.\n", From aa7b0329ff282ea8afb3c26dcbbc64209a280219 Mon Sep 17 00:00:00 2001 From: Karthick J Date: Tue, 7 Nov 2017 09:32:23 +0530 Subject: [PATCH 1050/2557] avdevice/decklink: refactor ff_decklink_set_format function This is done to enable input format autodetection in decklink_dec. Signed-off-by: Marton Balint --- libavdevice/decklink_common.cpp | 38 +++++++++++++++++++++------------ libavdevice/decklink_common.h | 1 + libavdevice/decklink_dec.cpp | 6 ++++++ libavdevice/decklink_enc.cpp | 4 ++++ 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp index 2bd63ac820c75..b952e749550f6 100644 --- a/libavdevice/decklink_common.cpp +++ b/libavdevice/decklink_common.cpp @@ -148,23 +148,12 @@ static DECKLINK_BOOL field_order_eq(enum AVFieldOrder field_order, BMDFieldDomin return false; } -int ff_decklink_set_format(AVFormatContext *avctx, - int width, int height, - int tb_num, int tb_den, - enum AVFieldOrder field_order, - decklink_direction_t direction, int num) -{ +int ff_decklink_set_configs(AVFormatContext *avctx, + decklink_direction_t direction) { struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; - BMDDisplayModeSupport support; - IDeckLinkDisplayModeIterator *itermode; - IDeckLinkDisplayMode *mode; - int i = 1; HRESULT res; - av_log(avctx, AV_LOG_DEBUG, "Trying to find mode for frame size %dx%d, frame timing %d/%d, field order %d, direction %d, mode number %d, format code %s\n", - width, height, tb_num, tb_den, field_order, direction, num, (cctx->format_code) ? cctx->format_code : "(unset)"); - if (ctx->duplex_mode) { DECKLINK_BOOL duplex_supported = false; @@ -181,7 +170,6 @@ int ff_decklink_set_format(AVFormatContext *avctx, av_log(avctx, AV_LOG_WARNING, "Unable to set duplex mode, because it is not supported.\n"); } } - if (direction == DIRECTION_IN) { int ret; ret = decklink_select_input(avctx, bmdDeckLinkConfigAudioInputConnection); @@ -190,6 +178,28 @@ int ff_decklink_set_format(AVFormatContext *avctx, ret = decklink_select_input(avctx, bmdDeckLinkConfigVideoInputConnection); if (ret < 0) return ret; + } + return 0; +} + +int ff_decklink_set_format(AVFormatContext *avctx, + int width, int height, + int tb_num, int tb_den, + enum AVFieldOrder field_order, + decklink_direction_t direction, int num) +{ + struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; + struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; + BMDDisplayModeSupport support; + IDeckLinkDisplayModeIterator *itermode; + IDeckLinkDisplayMode *mode; + int i = 1; + HRESULT res; + + av_log(avctx, AV_LOG_DEBUG, "Trying to find mode for frame size %dx%d, frame timing %d/%d, field order %d, direction %d, mode number %d, format code %s\n", + width, height, tb_num, tb_den, field_order, direction, num, (cctx->format_code) ? cctx->format_code : "(unset)"); + + if (direction == DIRECTION_IN) { res = ctx->dli->GetDisplayModeIterator (&itermode); } else { res = ctx->dlo->GetDisplayModeIterator (&itermode); diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index b6acb01bb92ca..4345156d8e535 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -134,6 +134,7 @@ static const BMDVideoConnection decklink_video_connection_map[] = { }; HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName); +int ff_decklink_set_configs(AVFormatContext *avctx, decklink_direction_t direction); int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, enum AVFieldOrder field_order, decklink_direction_t direction = DIRECTION_OUT, int num = 0); int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction, int num); int ff_decklink_list_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list, int show_inputs, int show_outputs); diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index e90b42811a904..03a049a21e43e 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -916,6 +916,12 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) goto error; } + if (ff_decklink_set_configs(avctx, DIRECTION_IN) < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set input configuration\n"); + ret = AVERROR(EIO); + goto error; + } + if (mode_num > 0 || cctx->format_code) { if (ff_decklink_set_format(avctx, DIRECTION_IN, mode_num) < 0) { av_log(avctx, AV_LOG_ERROR, "Could not set mode number %d or format code %s for %s\n", diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index 81df563b3bf66..c06ca4668f025 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -162,6 +162,10 @@ static int decklink_setup_video(AVFormatContext *avctx, AVStream *st) return -1; } + if (ff_decklink_set_configs(avctx, DIRECTION_OUT) < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set output configuration\n"); + return -1; + } if (ff_decklink_set_format(avctx, c->width, c->height, st->time_base.num, st->time_base.den, c->field_order)) { av_log(avctx, AV_LOG_ERROR, "Unsupported video size, framerate or field order!" From e8e9306b4f0017c3d2ae2a9f02136279c1a105e9 Mon Sep 17 00:00:00 2001 From: Karthick J Date: Fri, 27 Oct 2017 12:00:23 +0530 Subject: [PATCH 1051/2557] avdevice/decklink_dec: autodetect the video input format When -format_code is not specified autodetection will happen. Signed-off-by: Marton Balint --- doc/indevs.texi | 2 + libavdevice/decklink_common.cpp | 3 -- libavdevice/decklink_common.h | 7 +++ libavdevice/decklink_dec.cpp | 81 ++++++++++++++++++++++++++++----- 4 files changed, 79 insertions(+), 14 deletions(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index d308bbf7de9f1..56066bf23adf6 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -238,6 +238,8 @@ This sets the input video format to the format given by the FourCC. To see the supported values of your device(s) use @option{list_formats}. Note that there is a FourCC @option{'pal '} that can also be used as @option{pal} (3 letters). +Default behavior is autodetection of the input video format, if the hardware +supports it. @item bm_v210 This is a deprecated option, you can use @option{raw_format} instead. diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp index b952e749550f6..6ef2c529f446e 100644 --- a/libavdevice/decklink_common.cpp +++ b/libavdevice/decklink_common.cpp @@ -75,7 +75,6 @@ static char *dup_wchar_to_utf8(wchar_t *w) #define DECKLINK_STR OLECHAR * #define DECKLINK_STRDUP dup_wchar_to_utf8 #define DECKLINK_FREE(s) SysFreeString(s) -#define DECKLINK_BOOL BOOL #elif defined(__APPLE__) static char *dup_cfstring_to_utf8(CFStringRef w) { @@ -86,13 +85,11 @@ static char *dup_cfstring_to_utf8(CFStringRef w) #define DECKLINK_STR const __CFString * #define DECKLINK_STRDUP dup_cfstring_to_utf8 #define DECKLINK_FREE(s) CFRelease(s) -#define DECKLINK_BOOL bool #else #define DECKLINK_STR const char * #define DECKLINK_STRDUP av_strdup /* free() is needed for a string returned by the DeckLink SDL. */ #define DECKLINK_FREE(s) free((void *) s) -#define DECKLINK_BOOL bool #endif HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName) diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index 4345156d8e535..57ee7d1d689f6 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -28,6 +28,12 @@ #include "libavutil/thread.h" #include "decklink_common_c.h" +#ifdef _WIN32 +#define DECKLINK_BOOL BOOL +#else +#define DECKLINK_BOOL bool +#endif + class decklink_output_callback; class decklink_input_callback; @@ -95,6 +101,7 @@ struct decklink_ctx { pthread_mutex_t mutex; pthread_cond_t cond; int frames_buffer_available_spots; + int autodetect; int channels; int audio_depth; diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 03a049a21e43e..94dae2600328b 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -36,6 +36,7 @@ extern "C" { #include "libavutil/avutil.h" #include "libavutil/common.h" #include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" #include "libavutil/time.h" #include "libavutil/mathematics.h" #include "libavutil/reverse.h" @@ -49,6 +50,7 @@ extern "C" { #include "decklink_dec.h" #define MAX_WIDTH_VANC 1920 +const BMDDisplayMode AUTODETECT_DEFAULT_MODE = bmdModeNTSC; typedef struct VANCLineNumber { BMDDisplayMode mode; @@ -634,6 +636,15 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( BMDTimeValue frameDuration; int64_t wallclock = 0; + if (ctx->autodetect) { + if (videoFrame && !(videoFrame->GetFlags() & bmdFrameHasNoInputSource) && + ctx->bmd_mode == bmdModeUnknown) + { + ctx->bmd_mode = AUTODETECT_DEFAULT_MODE; + } + return S_OK; + } + ctx->frameCount++; if (ctx->audio_pts_source == PTS_SRC_WALLCLOCK || ctx->video_pts_source == PTS_SRC_WALLCLOCK) wallclock = av_gettime_relative(); @@ -794,17 +805,56 @@ HRESULT decklink_input_callback::VideoInputFormatChanged( BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *mode, BMDDetectedVideoInputFormatFlags) { + ctx->bmd_mode = mode->GetDisplayMode(); return S_OK; } -static HRESULT decklink_start_input(AVFormatContext *avctx) -{ - struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; +static int decklink_autodetect(struct decklink_cctx *cctx) { struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; + DECKLINK_BOOL autodetect_supported = false; + int i; + + if (ctx->attr->GetFlag(BMDDeckLinkSupportsInputFormatDetection, &autodetect_supported) != S_OK) + return -1; + if (autodetect_supported == false) + return -1; + + ctx->autodetect = 1; + ctx->bmd_mode = bmdModeUnknown; + if (ctx->dli->EnableVideoInput(AUTODETECT_DEFAULT_MODE, + bmdFormat8BitYUV, + bmdVideoInputEnableFormatDetection) != S_OK) { + return -1; + } + + if (ctx->dli->StartStreams() != S_OK) { + return -1; + } + + // 1 second timeout + for (i = 0; i < 10; i++) { + av_usleep(100000); + /* Sometimes VideoInputFrameArrived is called without the + * bmdFrameHasNoInputSource flag before VideoInputFormatChanged. + * So don't break for bmd_mode == AUTODETECT_DEFAULT_MODE. */ + if (ctx->bmd_mode != bmdModeUnknown && + ctx->bmd_mode != AUTODETECT_DEFAULT_MODE) + break; + } + + ctx->dli->PauseStreams(); + ctx->dli->FlushStreams(); + ctx->autodetect = 0; + if (ctx->bmd_mode != bmdModeUnknown) { + cctx->format_code = (char *)av_mallocz(5); + if (!cctx->format_code) + return -1; + AV_WB32(cctx->format_code, ctx->bmd_mode); + return 0; + } else { + return -1; + } - ctx->input_callback = new decklink_input_callback(avctx); - ctx->dli->SetCallback(ctx->input_callback); - return ctx->dli->StartStreams(); } extern "C" { @@ -922,13 +972,22 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) goto error; } - if (mode_num > 0 || cctx->format_code) { - if (ff_decklink_set_format(avctx, DIRECTION_IN, mode_num) < 0) { - av_log(avctx, AV_LOG_ERROR, "Could not set mode number %d or format code %s for %s\n", - mode_num, (cctx->format_code) ? cctx->format_code : "(unset)", fname); + ctx->input_callback = new decklink_input_callback(avctx); + ctx->dli->SetCallback(ctx->input_callback); + + if (mode_num == 0 && !cctx->format_code) { + if (decklink_autodetect(cctx) < 0) { + av_log(avctx, AV_LOG_ERROR, "Cannot Autodetect input stream or No signal\n"); ret = AVERROR(EIO); goto error; } + av_log(avctx, AV_LOG_INFO, "Autodetected the input mode\n"); + } + if (ff_decklink_set_format(avctx, DIRECTION_IN, mode_num) < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set mode number %d or format code %s for %s\n", + mode_num, (cctx->format_code) ? cctx->format_code : "(unset)", fname); + ret = AVERROR(EIO); + goto error; } #if !CONFIG_LIBZVBI @@ -1058,7 +1117,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) avpacket_queue_init (avctx, &ctx->queue); - if (decklink_start_input (avctx) != S_OK) { + if (ctx->dli->StartStreams() != S_OK) { av_log(avctx, AV_LOG_ERROR, "Cannot start input stream\n"); ret = AVERROR(EIO); goto error; From 3d5822d9cf07d08bce82903e4715658f46b01b5c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 18 Nov 2017 01:33:18 +0100 Subject: [PATCH 1052/2557] avcodec/jpeg2000: Dynamically allocate codeblock data Fixes: OOM Fixes: 3541/clusterfuzz-testcase-minimized-6469958596820992 Adds support for decoding codeblock data larger than 8kb Reduces decoder memory consumption Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 8 ++++++-- libavcodec/jpeg2000.c | 12 ++++++++++-- libavcodec/jpeg2000.h | 4 ++-- libavcodec/jpeg2000dec.c | 22 +++++++++++++++++++--- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 2135ece540300..362c7f0f496f3 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -663,7 +663,8 @@ static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context *t1, Jpeg20 bpno = cblk->nonzerobits - 1; } - ff_mqc_initenc(&t1->mqc, cblk->data); + cblk->data[0] = 0; + ff_mqc_initenc(&t1->mqc, cblk->data + 1); for (passno = 0; bpno >= 0; passno++){ nmsedec=0; @@ -796,7 +797,7 @@ static int encode_packet(Jpeg2000EncoderContext *s, Jpeg2000ResLevel *rlevel, in if (cblk->ninclpasses){ if (s->buf_end - s->buf < cblk->passes[cblk->ninclpasses-1].rate) return -1; - bytestream_put_buffer(&s->buf, cblk->data, cblk->passes[cblk->ninclpasses-1].rate + bytestream_put_buffer(&s->buf, cblk->data + 1, cblk->passes[cblk->ninclpasses-1].rate - cblk->passes[cblk->ninclpasses-1].flushed_len); bytestream_put_buffer(&s->buf, cblk->passes[cblk->ninclpasses-1].flushed, cblk->passes[cblk->ninclpasses-1].flushed_len); @@ -937,6 +938,9 @@ static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno } } } + prec->cblk[cblkno].data = av_malloc(1 + 8192); + if (!prec->cblk[cblkno].data) + return AVERROR(ENOMEM); encode_cblk(s, &t1, prec->cblk + cblkno, tile, xx1 - xx0, yy1 - yy0, bandpos, codsty->nreslevels - reslevelno - 1); xx0 = xx1; diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c index afeb9df27c408..8551cf8d6c965 100644 --- a/libavcodec/jpeg2000.c +++ b/libavcodec/jpeg2000.c @@ -357,7 +357,6 @@ static int init_prec(Jpeg2000Band *band, comp->reslevel[reslevelno-1].coord[1][0]; } - cblk->zero = 0; cblk->lblock = 3; cblk->length = 0; memset(cblk->lengthinc, 0, sizeof(cblk->lengthinc)); @@ -598,9 +597,18 @@ void ff_jpeg2000_cleanup(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty) for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++) { if (band->prec) { Jpeg2000Prec *prec = band->prec + precno; + int nb_code_blocks = prec->nb_codeblocks_height * prec->nb_codeblocks_width; + av_freep(&prec->zerobits); av_freep(&prec->cblkincl); - av_freep(&prec->cblk); + if (prec->cblk) { + int cblkno; + for (cblkno = 0; cblkno < nb_code_blocks; cblkno ++) { + Jpeg2000Cblk *cblk = &prec->cblk[cblkno]; + av_freep(&cblk->data); + } + av_freep(&prec->cblk); + } } } diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h index 8a022ad9188a8..eaf7faf3424e5 100644 --- a/libavcodec/jpeg2000.h +++ b/libavcodec/jpeg2000.h @@ -168,8 +168,8 @@ typedef struct Jpeg2000Cblk { uint16_t lengthinc[JPEG2000_MAX_PASSES]; uint8_t nb_lengthinc; uint8_t lblock; - uint8_t zero; - uint8_t data[8192]; + uint8_t *data; + size_t data_allocated; int nb_terminations; int nb_terminationsinc; int data_start[JPEG2000_MAX_PASSES]; diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 62b9009a82c15..0309b1f6fb217 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -1001,10 +1001,18 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, if ((ret = get_bits(s, av_log2(newpasses1) + cblk->lblock)) < 0) return ret; - if (ret > sizeof(cblk->data)) { + if (ret > cblk->data_allocated) { + size_t new_size = FFMAX(2*cblk->data_allocated, ret); + void *new = av_realloc(cblk->data, new_size); + if (new) { + cblk->data = new; + cblk->data_allocated = new_size; + } + } + if (ret > cblk->data_allocated) { avpriv_request_sample(s->avctx, "Block with lengthinc greater than %"SIZE_SPECIFIER"", - sizeof(cblk->data)); + cblk->data_allocated); return AVERROR_PATCHWELCOME; } cblk->lengthinc[cblk->nb_lengthinc++] = ret; @@ -1030,8 +1038,16 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) { Jpeg2000Cblk *cblk = prec->cblk + cblkno; for (cwsno = 0; cwsno < cblk->nb_lengthinc; cwsno ++) { + if (cblk->data_allocated < cblk->length + cblk->lengthinc[cwsno] + 4) { + size_t new_size = FFMAX(2*cblk->data_allocated, cblk->length + cblk->lengthinc[cwsno] + 4); + void *new = av_realloc(cblk->data, new_size); + if (new) { + cblk->data = new; + cblk->data_allocated = new_size; + } + } if ( bytestream2_get_bytes_left(&s->g) < cblk->lengthinc[cwsno] - || sizeof(cblk->data) < cblk->length + cblk->lengthinc[cwsno] + 4 + || cblk->data_allocated < cblk->length + cblk->lengthinc[cwsno] + 4 ) { av_log(s->avctx, AV_LOG_ERROR, "Block length %"PRIu16" or lengthinc %d is too large, left %d\n", From 6db511a7838830f856b4664958add937a4a0d49b Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Tue, 21 Nov 2017 15:40:22 -0800 Subject: [PATCH 1053/2557] avformat/mov: Increment stsd_count while processing stsd data; avoids leaks. In the event of ff_mov_read_stsd_entries() failure, sc->stsd_count is not updated, even if the function allocates extradata memory. Instead update the sc->stsd_count as entries are parsed so that mov_read_close() can do the right thing. Signed-off-by: Dale Curtis Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index b6cdf3a52a1a5..9e876efc8c3f0 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2464,8 +2464,10 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) } if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format, - size - (avio_tell(pb) - start_pos))) + size - (avio_tell(pb) - start_pos))) { + sc->stsd_count++; continue; + } sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id; sc->dref_id= dref_id; @@ -2517,6 +2519,7 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) av_freep(&st->codecpar->extradata); st->codecpar->extradata_size = 0; } + sc->stsd_count++; } if (pb->eof_reached) @@ -2566,8 +2569,6 @@ static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (ret < 0) goto fail; - sc->stsd_count = entries; - /* Restore back the primary extradata. */ av_freep(&st->codecpar->extradata); st->codecpar->extradata_size = sc->extradata_size[0]; From 152902f3799f24d0d392880f33a11c6920a30cf1 Mon Sep 17 00:00:00 2001 From: Jim DeLaHunt Date: Wed, 15 Nov 2017 00:43:30 -0800 Subject: [PATCH 1054/2557] doc: Add FAQs about running in background (rev 2) Add two FAQs about running FFmpeg in the background. The first explains the use of the -nostdin option in a straightforward way. Text revised based on review. The second FAQ starts from a confusing error message, and leads to the solution, use of the -nostdin option. The purpose of the second FAQ is to attract web searches from people having the problem, and offer them a solution. Add an anchor to the Main Options section of the ffmpeg documentation, so that the FAQs can link directly there. Signed-off-by: Michael Niedermayer --- doc/faq.texi | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ doc/ffmpeg.texi | 1 + 2 files changed, 66 insertions(+) diff --git a/doc/faq.texi b/doc/faq.texi index dcaf89c6d2c5f..73624c647e501 100644 --- a/doc/faq.texi +++ b/doc/faq.texi @@ -501,6 +501,71 @@ ffmpeg -i ega_screen.nut -vf setdar=4/3 ega_screen_anamorphic.nut ffmpeg -i ega_screen.nut -aspect 4/3 -c copy ega_screen_overridden.nut @end example +@anchor{background task} +@section How do I run ffmpeg as a background task? + +ffmpeg normally checks the console input, for entries like "q" to stop +and "?" to give help, while performing operations. ffmpeg does not have a way of +detecting when it is running as a background task. +When it checks the console input, that can cause the process running ffmpeg +in the background to suspend. + +To prevent those input checks, allowing ffmpeg to run as a background task, +use the @url{ffmpeg.html#stdin-option, @code{-nostdin} option} +in the ffmpeg invocation. This is effective whether you run ffmpeg in a shell +or invoke ffmpeg in its own process via an operating system API. + +As an alternative, when you are running ffmpeg in a shell, you can redirect +standard input to @code{/dev/null} (on Linux and Mac OS) +or @code{NUL} (on Windows). You can do this redirect either +on the ffmpeg invocation, or from a shell script which calls ffmpeg. + +For example: + +@example +ffmpeg -nostdin -i INPUT OUTPUT +@end example + +or (on Linux, Mac OS, and other UNIX-like shells): + +@example +ffmpeg -i INPUT OUTPUT ~/tmp/log.txt & +[1] 93352 +% +[1] + suspended (tty output) ffmpeg -i INPUT OUTPUT &> +@end example + +The message "tty output" notwithstanding, the problem here is that +ffmpeg normally checks the console input when it runs. The operating system +detects this, and suspends the process until you can bring it to the +foreground and attend to it. + +The solution is to use the right techniques to tell ffmpeg not to consult +console input. You can use the +@url{ffmpeg.html#stdin-option, @code{-nostdin} option}, +or redirect standard input with @code{< /dev/null}. +See FAQ +@ref{background task, @emph{How do I run ffmpeg as a background task?}} +for details. + @chapter Development @section Are there examples illustrating how to use the FFmpeg libraries, particularly libavcodec and libavformat? diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 9a90d7327abb2..d767e48c44f9b 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -470,6 +470,7 @@ the encoding process. It is made of "@var{key}=@var{value}" lines. @var{key} consists of only alphanumeric characters. The last key of a sequence of progress information is always "progress". +@anchor{stdin option} @item -stdin Enable interaction on standard input. On by default unless standard input is used as an input. To explicitly disable interaction you need to specify From a050f56c0903c718d8ef0b14dc09195785fdf564 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:46 +0000 Subject: [PATCH 1055/2557] lavu: Add OpenCL hardware pixfmt --- doc/APIchanges | 3 +++ libavutil/pixdesc.c | 4 ++++ libavutil/pixfmt.h | 7 +++++++ libavutil/version.h | 2 +- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index d336f6ce222b3..2464cc2e5f68b 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2017-11-xx - xxxxxxx - lavu 55.1.0 - pixfmt.h + Add AV_PIX_FMT_OPENCL. + 2017-xx-xx - xxxxxxx - lavc 58.3.100 - avcodec.h Add avcodec_get_hw_frames_parameters(). diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 3d21e67a785ba..e77d5f44b9cae 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -2181,6 +2181,10 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .name = "drm_prime", .flags = AV_PIX_FMT_FLAG_HWACCEL, }, + [AV_PIX_FMT_OPENCL] = { + .name = "opencl", + .flags = AV_PIX_FMT_FLAG_HWACCEL, + }, }; #if FF_API_PLUS1_MINUS1 FF_ENABLE_DEPRECATION_WARNINGS diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index a520028962872..4c530fead3eb7 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -322,6 +322,13 @@ enum AVPixelFormat { * data[0] points to an AVDRMFrameDescriptor. */ AV_PIX_FMT_DRM_PRIME, + /** + * Hardware surfaces for OpenCL. + * + * data[i] contain 2D image objects (typed in C as cl_mem, used + * in OpenCL as image2d_t) for each plane of the surface. + */ + AV_PIX_FMT_OPENCL, AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions }; diff --git a/libavutil/version.h b/libavutil/version.h index 1bc4b2a6cbea9..cf8ec498e4a28 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -80,7 +80,7 @@ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 0 +#define LIBAVUTIL_VERSION_MINOR 1 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From b25d8ef0a7a880443fb713603d7f4259e30b84dd Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:47 +0000 Subject: [PATCH 1056/2557] lavu: OpenCL hwcontext implementation --- configure | 4 +- doc/APIchanges | 4 + libavutil/Makefile | 2 + libavutil/hwcontext.c | 4 + libavutil/hwcontext.h | 1 + libavutil/hwcontext_internal.h | 1 + libavutil/hwcontext_opencl.c | 1303 ++++++++++++++++++++++++++++++++ libavutil/hwcontext_opencl.h | 96 +++ libavutil/version.h | 2 +- 9 files changed, 1414 insertions(+), 3 deletions(-) create mode 100644 libavutil/hwcontext_opencl.c create mode 100644 libavutil/hwcontext_opencl.h diff --git a/configure b/configure index e8470ae236ba4..74920c388d504 100755 --- a/configure +++ b/configure @@ -289,7 +289,7 @@ External library support: --enable-mediacodec enable Android MediaCodec support [no] --enable-libmysofa enable libmysofa, needed for sofalizer filter [no] --enable-openal enable OpenAL 1.1 capture support [no] - --enable-opencl enable OpenCL code + --enable-opencl enable OpenCL processing [no] --enable-opengl enable OpenGL rendering [no] --enable-openssl enable openssl, needed for https support if gnutls is not used [no] @@ -1633,7 +1633,6 @@ EXTERNAL_LIBRARY_LIST=" libzvbi mediacodec openal - opencl opengl " @@ -1669,6 +1668,7 @@ HWACCEL_LIBRARY_LIST=" libmfx mmal omx + opencl " DOCUMENT_LIST=" diff --git a/doc/APIchanges b/doc/APIchanges index 2464cc2e5f68b..6ace2d1876a8f 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2017-10-21 API changes, most recent first: +2017-11-xx - xxxxxxx - lavu 55.2.0 - hwcontext.h hwcontext_opencl.h + Add AV_HWDEVICE_TYPE_OPENCL and a new installed header with + OpenCL-specific hwcontext definitions. + 2017-11-xx - xxxxxxx - lavu 55.1.0 - pixfmt.h Add AV_PIX_FMT_OPENCL. diff --git a/libavutil/Makefile b/libavutil/Makefile index 65e285a70114a..cc70c4e29f594 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -165,6 +165,7 @@ OBJS-$(CONFIG_QSV) += hwcontext_qsv.o OBJS-$(CONFIG_LIBDRM) += hwcontext_drm.o OBJS-$(CONFIG_LZO) += lzo.o OBJS-$(CONFIG_OPENCL) += opencl.o opencl_internal.o +OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o OBJS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.o OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o @@ -179,6 +180,7 @@ SKIPHEADERS-$(CONFIG_CUDA) += hwcontext_cuda_internal.h SKIPHEADERS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.h SKIPHEADERS-$(CONFIG_DXVA2) += hwcontext_dxva2.h SKIPHEADERS-$(CONFIG_QSV) += hwcontext_qsv.h +SKIPHEADERS-$(CONFIG_OPENCL) += hwcontext_opencl.h SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.h SKIPHEADERS-$(CONFIG_VDPAU) += hwcontext_vdpau.h diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index 7f8e22736c9c5..b26e68fe77f76 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -41,6 +41,9 @@ static const HWContextType * const hw_table[] = { #if CONFIG_DXVA2 &ff_hwcontext_type_dxva2, #endif +#if CONFIG_OPENCL + &ff_hwcontext_type_opencl, +#endif #if CONFIG_QSV &ff_hwcontext_type_qsv, #endif @@ -61,6 +64,7 @@ static const char *const hw_type_names[] = { [AV_HWDEVICE_TYPE_DRM] = "drm", [AV_HWDEVICE_TYPE_DXVA2] = "dxva2", [AV_HWDEVICE_TYPE_D3D11VA] = "d3d11va", + [AV_HWDEVICE_TYPE_OPENCL] = "opencl", [AV_HWDEVICE_TYPE_QSV] = "qsv", [AV_HWDEVICE_TYPE_VAAPI] = "vaapi", [AV_HWDEVICE_TYPE_VDPAU] = "vdpau", diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h index d20810422c563..8d27b987dff9e 100644 --- a/libavutil/hwcontext.h +++ b/libavutil/hwcontext.h @@ -34,6 +34,7 @@ enum AVHWDeviceType { AV_HWDEVICE_TYPE_VIDEOTOOLBOX, AV_HWDEVICE_TYPE_D3D11VA, AV_HWDEVICE_TYPE_DRM, + AV_HWDEVICE_TYPE_OPENCL, }; typedef struct AVHWDeviceInternal AVHWDeviceInternal; diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h index 2d75d3db0877e..28ff0f9ee68c6 100644 --- a/libavutil/hwcontext_internal.h +++ b/libavutil/hwcontext_internal.h @@ -161,6 +161,7 @@ extern const HWContextType ff_hwcontext_type_cuda; extern const HWContextType ff_hwcontext_type_d3d11va; extern const HWContextType ff_hwcontext_type_drm; extern const HWContextType ff_hwcontext_type_dxva2; +extern const HWContextType ff_hwcontext_type_opencl; extern const HWContextType ff_hwcontext_type_qsv; extern const HWContextType ff_hwcontext_type_vaapi; extern const HWContextType ff_hwcontext_type_vdpau; diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c new file mode 100644 index 0000000000000..0fe25d9500883 --- /dev/null +++ b/libavutil/hwcontext_opencl.c @@ -0,0 +1,1303 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" + +#include "avassert.h" +#include "avstring.h" +#include "common.h" +#include "hwcontext.h" +#include "hwcontext_internal.h" +#include "hwcontext_opencl.h" +#include "mem.h" +#include "pixdesc.h" + + +typedef struct OpenCLDeviceContext { + // Default command queue to use for transfer/mapping operations on + // the device. If the user supplies one, this is a reference to it. + // Otherwise, it is newly-created. + cl_command_queue command_queue; + + // The platform the context exists on. This is needed to query and + // retrieve extension functions. + cl_platform_id platform_id; + + // Platform/device-specific functions. +} OpenCLDeviceContext; + +typedef struct OpenCLFramesContext { + // Command queue used for transfer/mapping operations on this frames + // context. If the user supplies one, this is a reference to it. + // Otherwise, it is a reference to the default command queue for the + // device. + cl_command_queue command_queue; +} OpenCLFramesContext; + + +static void opencl_error_callback(const char *errinfo, + const void *private_info, size_t cb, + void *user_data) +{ + AVHWDeviceContext *ctx = user_data; + av_log(ctx, AV_LOG_ERROR, "OpenCL error: %s\n", errinfo); +} + +static void opencl_device_free(AVHWDeviceContext *hwdev) +{ + AVOpenCLDeviceContext *hwctx = hwdev->hwctx; + cl_int cle; + + cle = clReleaseContext(hwctx->context); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to release OpenCL " + "context: %d.\n", cle); + } +} + +static struct { + const char *key; + cl_platform_info name; +} opencl_platform_params[] = { + { "platform_profile", CL_PLATFORM_PROFILE }, + { "platform_version", CL_PLATFORM_VERSION }, + { "platform_name", CL_PLATFORM_NAME }, + { "platform_vendor", CL_PLATFORM_VENDOR }, + { "platform_extensions", CL_PLATFORM_EXTENSIONS }, +}; + +static struct { + const char *key; + cl_device_info name; +} opencl_device_params[] = { + { "device_name", CL_DEVICE_NAME }, + { "device_vendor", CL_DEVICE_VENDOR }, + { "driver_version", CL_DRIVER_VERSION }, + { "device_version", CL_DEVICE_VERSION }, + { "device_profile", CL_DEVICE_PROFILE }, + { "device_extensions", CL_DEVICE_EXTENSIONS }, +}; + +static struct { + const char *key; + cl_device_type type; +} opencl_device_types[] = { + { "cpu", CL_DEVICE_TYPE_CPU }, + { "gpu", CL_DEVICE_TYPE_GPU }, + { "accelerator", CL_DEVICE_TYPE_ACCELERATOR }, + { "custom", CL_DEVICE_TYPE_CUSTOM }, + { "default", CL_DEVICE_TYPE_DEFAULT }, + { "all", CL_DEVICE_TYPE_ALL }, +}; + +static char *opencl_get_platform_string(cl_platform_id platform_id, + cl_platform_info key) +{ + char *str; + size_t size; + cl_int cle; + cle = clGetPlatformInfo(platform_id, key, 0, NULL, &size); + if (cle != CL_SUCCESS) + return NULL; + str = av_malloc(size); + if (!str) + return NULL; + cle = clGetPlatformInfo(platform_id, key, size, str, &size); + if (cle != CL_SUCCESS) { + av_free(str); + return NULL; + } + av_assert0(strlen(str) + 1 == size); + return str; +} + +static char *opencl_get_device_string(cl_device_id device_id, + cl_device_info key) +{ + char *str; + size_t size; + cl_int cle; + cle = clGetDeviceInfo(device_id, key, 0, NULL, &size); + if (cle != CL_SUCCESS) + return NULL; + str = av_malloc(size); + if (!str) + return NULL; + cle = clGetDeviceInfo(device_id, key, size, str, &size); + if (cle != CL_SUCCESS) { + av_free(str); + return NULL; + } + av_assert0(strlen(str) + 1== size); + return str; +} + +static int opencl_check_platform_extension(cl_platform_id platform_id, + const char *name) +{ + char *str; + int found = 0; + str = opencl_get_platform_string(platform_id, + CL_PLATFORM_EXTENSIONS); + if (str && strstr(str, name)) + found = 1; + av_free(str); + return found; +} + +static int opencl_check_device_extension(cl_device_id device_id, + const char *name) +{ + char *str; + int found = 0; + str = opencl_get_device_string(device_id, + CL_DEVICE_EXTENSIONS); + if (str && strstr(str, name)) + found = 1; + av_free(str); + return found; +} + +static av_unused int opencl_check_extension(AVHWDeviceContext *hwdev, + const char *name) +{ + AVOpenCLDeviceContext *hwctx = hwdev->hwctx; + OpenCLDeviceContext *priv = hwdev->internal->priv; + + if (opencl_check_platform_extension(priv->platform_id, name)) { + av_log(hwdev, AV_LOG_DEBUG, + "%s found as platform extension.\n", name); + return 1; + } + + if (opencl_check_device_extension(hwctx->device_id, name)) { + av_log(hwdev, AV_LOG_DEBUG, + "%s found as device extension.\n", name); + return 1; + } + + return 0; +} + +static int opencl_enumerate_platforms(AVHWDeviceContext *hwdev, + cl_uint *nb_platforms, + cl_platform_id **platforms, + void *context) +{ + cl_int cle; + + cle = clGetPlatformIDs(0, NULL, nb_platforms); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to get number of " + "OpenCL platforms: %d.\n", cle); + return AVERROR(ENODEV); + } + av_log(hwdev, AV_LOG_DEBUG, "%u OpenCL platforms found.\n", + *nb_platforms); + + *platforms = av_malloc_array(*nb_platforms, sizeof(**platforms)); + if (!*platforms) + return AVERROR(ENOMEM); + + cle = clGetPlatformIDs(*nb_platforms, *platforms, NULL); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to get list of OpenCL " + "platforms: %d.\n", cle); + av_freep(platforms); + return AVERROR(ENODEV); + } + + return 0; +} + +static int opencl_filter_platform(AVHWDeviceContext *hwdev, + cl_platform_id platform_id, + const char *platform_name, + void *context) +{ + AVDictionary *opts = context; + const AVDictionaryEntry *param; + char *str; + int i, ret = 0; + + for (i = 0; i < FF_ARRAY_ELEMS(opencl_platform_params); i++) { + param = av_dict_get(opts, opencl_platform_params[i].key, + NULL, 0); + if (!param) + continue; + + str = opencl_get_platform_string(platform_id, + opencl_platform_params[i].name); + if (!str) { + av_log(hwdev, AV_LOG_ERROR, "Failed to query %s " + "of platform \"%s\".\n", + opencl_platform_params[i].key, platform_name); + return AVERROR_UNKNOWN; + } + if (!av_stristr(str, param->value)) { + av_log(hwdev, AV_LOG_DEBUG, "%s does not match (\"%s\").\n", + param->key, str); + ret = 1; + } + av_free(str); + } + + return ret; +} + +static int opencl_enumerate_devices(AVHWDeviceContext *hwdev, + cl_platform_id platform_id, + const char *platform_name, + cl_uint *nb_devices, + cl_device_id **devices, + void *context) +{ + cl_int cle; + + cle = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL, + 0, NULL, nb_devices); + if (cle == CL_DEVICE_NOT_FOUND) { + av_log(hwdev, AV_LOG_DEBUG, "No devices found " + "on platform \"%s\".\n", platform_name); + *nb_devices = 0; + return 0; + } else if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices " + "on platform \"%s\": %d.\n", platform_name, cle); + return AVERROR(ENODEV); + } + av_log(hwdev, AV_LOG_DEBUG, "%u OpenCL devices found on " + "platform \"%s\".\n", *nb_devices, platform_name); + + *devices = av_malloc_array(*nb_devices, sizeof(**devices)); + if (!*devices) + return AVERROR(ENOMEM); + + cle = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL, + *nb_devices, *devices, NULL); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to get list of devices " + "on platform \"%s\": %d.\n", platform_name, cle); + av_freep(devices); + return AVERROR(ENODEV); + } + + return 0; +} + +static int opencl_filter_device(AVHWDeviceContext *hwdev, + cl_device_id device_id, + const char *device_name, + void *context) +{ + AVDictionary *opts = context; + const AVDictionaryEntry *param; + char *str; + int i, ret = 0; + + param = av_dict_get(opts, "device_type", NULL, 0); + if (param) { + cl_device_type match_type = 0, device_type; + cl_int cle; + + for (i = 0; i < FF_ARRAY_ELEMS(opencl_device_types); i++) { + if (!strcmp(opencl_device_types[i].key, param->value)) { + match_type = opencl_device_types[i].type; + break; + } + } + if (!match_type) { + av_log(hwdev, AV_LOG_ERROR, "Unknown device type %s.\n", + param->value); + return AVERROR(EINVAL); + } + + cle = clGetDeviceInfo(device_id, CL_DEVICE_TYPE, + sizeof(device_type), &device_type, NULL); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to query device type " + "of device \"%s\".\n", device_name); + return AVERROR_UNKNOWN; + } + + if (!(device_type & match_type)) { + av_log(hwdev, AV_LOG_DEBUG, "device_type does not match.\n"); + return 1; + } + } + + for (i = 0; i < FF_ARRAY_ELEMS(opencl_device_params); i++) { + param = av_dict_get(opts, opencl_device_params[i].key, + NULL, 0); + if (!param) + continue; + + str = opencl_get_device_string(device_id, + opencl_device_params[i].name); + if (!str) { + av_log(hwdev, AV_LOG_ERROR, "Failed to query %s " + "of device \"%s\".\n", + opencl_device_params[i].key, device_name); + return AVERROR_UNKNOWN; + } + if (!av_stristr(str, param->value)) { + av_log(hwdev, AV_LOG_DEBUG, "%s does not match (\"%s\").\n", + param->key, str); + ret = 1; + } + av_free(str); + } + + return ret; +} + +typedef struct OpenCLDeviceSelector { + int platform_index; + int device_index; + void *context; + int (*enumerate_platforms)(AVHWDeviceContext *hwdev, + cl_uint *nb_platforms, + cl_platform_id **platforms, + void *context); + int (*filter_platform) (AVHWDeviceContext *hwdev, + cl_platform_id platform_id, + const char *platform_name, + void *context); + int (*enumerate_devices) (AVHWDeviceContext *hwdev, + cl_platform_id platform_id, + const char *platform_name, + cl_uint *nb_devices, + cl_device_id **devices, + void *context); + int (*filter_device) (AVHWDeviceContext *hwdev, + cl_device_id device_id, + const char *device_name, + void *context); +} OpenCLDeviceSelector; + +static int opencl_device_create_internal(AVHWDeviceContext *hwdev, + const OpenCLDeviceSelector *selector, + cl_context_properties *props) +{ + cl_uint nb_platforms; + cl_platform_id *platforms = NULL; + cl_platform_id platform_id; + cl_uint nb_devices; + cl_device_id *devices = NULL; + AVOpenCLDeviceContext *hwctx = hwdev->hwctx; + cl_int cle; + cl_context_properties default_props[3]; + char *platform_name_src = NULL, + *device_name_src = NULL; + int err, found, p, d; + + err = selector->enumerate_platforms(hwdev, &nb_platforms, &platforms, + selector->context); + if (err) + return err; + + found = 0; + for (p = 0; p < nb_platforms; p++) { + const char *platform_name; + + if (selector->platform_index >= 0 && + selector->platform_index != p) + continue; + + av_freep(&platform_name_src); + platform_name_src = opencl_get_platform_string(platforms[p], + CL_PLATFORM_NAME); + if (platform_name_src) + platform_name = platform_name_src; + else + platform_name = "Unknown Platform"; + + if (selector->filter_platform) { + err = selector->filter_platform(hwdev, platforms[p], + platform_name, + selector->context); + if (err < 0) + goto fail; + if (err > 0) + continue; + } + + err = opencl_enumerate_devices(hwdev, platforms[p], platform_name, + &nb_devices, &devices, + selector->context); + if (err < 0) + continue; + + for (d = 0; d < nb_devices; d++) { + const char *device_name; + + if (selector->device_index >= 0 && + selector->device_index != d) + continue; + + av_freep(&device_name_src); + device_name_src = opencl_get_device_string(devices[d], + CL_DEVICE_NAME); + if (device_name_src) + device_name = device_name_src; + else + device_name = "Unknown Device"; + + if (selector->filter_device) { + err = selector->filter_device(hwdev, devices[d], + device_name, + selector->context); + if (err < 0) + goto fail; + if (err > 0) + continue; + } + + av_log(hwdev, AV_LOG_VERBOSE, "%d.%d: %s / %s\n", p, d, + platform_name, device_name); + + ++found; + platform_id = platforms[p]; + hwctx->device_id = devices[d]; + } + + av_freep(&devices); + } + + if (found == 0) { + av_log(hwdev, AV_LOG_ERROR, "No matching devices found.\n"); + err = AVERROR(ENODEV); + goto fail; + } + if (found > 1) { + av_log(hwdev, AV_LOG_ERROR, "More than one matching device found.\n"); + err = AVERROR(ENODEV); + goto fail; + } + + if (!props) { + props = default_props; + default_props[0] = CL_CONTEXT_PLATFORM; + default_props[1] = (intptr_t)platform_id; + default_props[2] = 0; + } else { + if (props[0] == CL_CONTEXT_PLATFORM && props[1] == 0) + props[1] = (intptr_t)platform_id; + } + + hwctx->context = clCreateContext(props, 1, &hwctx->device_id, + &opencl_error_callback, hwdev, &cle); + if (!hwctx->context) { + av_log(hwdev, AV_LOG_ERROR, "Failed to create OpenCL context: " + "%d.\n", cle); + err = AVERROR(ENODEV); + goto fail; + } + + hwdev->free = &opencl_device_free; + + err = 0; +fail: + av_freep(&platform_name_src); + av_freep(&device_name_src); + av_freep(&platforms); + av_freep(&devices); + return err; +} + +static int opencl_device_create(AVHWDeviceContext *hwdev, const char *device, + AVDictionary *opts, int flags) +{ + OpenCLDeviceSelector selector = { + .context = opts, + .enumerate_platforms = &opencl_enumerate_platforms, + .filter_platform = &opencl_filter_platform, + .enumerate_devices = &opencl_enumerate_devices, + .filter_device = &opencl_filter_device, + }; + + if (device && device[0]) { + // Match one or both indices for platform and device. + int d = -1, p = -1, ret; + if (device[0] == '.') + ret = sscanf(device, ".%d", &d); + else + ret = sscanf(device, "%d.%d", &p, &d); + if (ret < 1) { + av_log(hwdev, AV_LOG_ERROR, "Invalid OpenCL platform/device " + "index specification \"%s\".\n", device); + return AVERROR(EINVAL); + } + selector.platform_index = p; + selector.device_index = d; + } else { + selector.platform_index = -1; + selector.device_index = -1; + } + + return opencl_device_create_internal(hwdev, &selector, NULL); +} + +static int opencl_device_init(AVHWDeviceContext *hwdev) +{ + AVOpenCLDeviceContext *hwctx = hwdev->hwctx; + OpenCLDeviceContext *priv = hwdev->internal->priv; + cl_int cle; + + if (hwctx->command_queue) { + cle = clRetainCommandQueue(hwctx->command_queue); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to retain external " + "command queue: %d.\n", cle); + return AVERROR(EIO); + } + priv->command_queue = hwctx->command_queue; + } else { + priv->command_queue = clCreateCommandQueue(hwctx->context, + hwctx->device_id, + 0, &cle); + if (!priv->command_queue) { + av_log(hwdev, AV_LOG_ERROR, "Failed to create internal " + "command queue: %d.\n", cle); + return AVERROR(EIO); + } + } + + cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_PLATFORM, + sizeof(priv->platform_id), &priv->platform_id, + NULL); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to determine the OpenCL " + "platform containing the device.\n"); + return AVERROR(EIO); + } + + return 0; +} + +static void opencl_device_uninit(AVHWDeviceContext *hwdev) +{ + OpenCLDeviceContext *priv = hwdev->internal->priv; + cl_int cle; + + if (priv->command_queue) { + cle = clReleaseCommandQueue(priv->command_queue); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to release internal " + "command queue reference: %d.\n", cle); + } + } +} + +static int opencl_get_plane_format(enum AVPixelFormat pixfmt, + int plane, int width, int height, + cl_image_format *image_format, + cl_image_desc *image_desc) +{ + const AVPixFmtDescriptor *desc; + const AVComponentDescriptor *comp; + int channels = 0, order = 0, depth = 0, step = 0; + int wsub, hsub, alpha; + int c; + + if (plane >= AV_NUM_DATA_POINTERS) + return AVERROR(ENOENT); + + desc = av_pix_fmt_desc_get(pixfmt); + + // Only normal images are allowed. + if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | + AV_PIX_FMT_FLAG_HWACCEL | + AV_PIX_FMT_FLAG_PAL)) + return AVERROR(EINVAL); + + wsub = 1 << desc->log2_chroma_w; + hsub = 1 << desc->log2_chroma_h; + // Subsampled components must be exact. + if (width & wsub - 1 || height & hsub - 1) + return AVERROR(EINVAL); + + for (c = 0; c < desc->nb_components; c++) { + comp = &desc->comp[c]; + if (comp->plane != plane) + continue; + // The step size must be a power of two. + if (comp->step != 1 && comp->step != 2 && + comp->step != 4 && comp->step != 8) + return AVERROR(EINVAL); + // The bits in each component must be packed in the + // most-significant-bits of the relevant bytes. + if (comp->shift + comp->depth != 8 && + comp->shift + comp->depth != 16) + return AVERROR(EINVAL); + // The depth must not vary between components. + if (depth && comp->depth != depth) + return AVERROR(EINVAL); + // If a single data element crosses multiple bytes then + // it must match the native endianness. + if (comp->depth > 8 && + HAVE_BIGENDIAN == !(desc->flags & AV_PIX_FMT_FLAG_BE)) + return AVERROR(EINVAL); + // A single data element must not contain multiple samples + // from the same component. + if (step && comp->step != step) + return AVERROR(EINVAL); + order = order * 10 + c + 1; + depth = comp->depth; + step = comp->step; + alpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA && + c == desc->nb_components - 1); + ++channels; + } + if (channels == 0) + return AVERROR(ENOENT); + + memset(image_format, 0, sizeof(*image_format)); + memset(image_desc, 0, sizeof(*image_desc)); + image_desc->image_type = CL_MEM_OBJECT_IMAGE2D; + + if (plane == 0 || alpha) { + image_desc->image_width = width; + image_desc->image_height = height; + image_desc->image_row_pitch = step * width; + } else { + image_desc->image_width = width / wsub; + image_desc->image_height = height / hsub; + image_desc->image_row_pitch = step * width / wsub; + } + + if (depth <= 8) { + image_format->image_channel_data_type = CL_UNORM_INT8; + } else { + if (depth <= 16) + image_format->image_channel_data_type = CL_UNORM_INT16; + else + return AVERROR(EINVAL); + } + +#define CHANNEL_ORDER(order, type) \ + case order: image_format->image_channel_order = type; break; + switch (order) { + CHANNEL_ORDER(1, CL_R); + CHANNEL_ORDER(2, CL_R); + CHANNEL_ORDER(3, CL_R); + CHANNEL_ORDER(4, CL_R); + CHANNEL_ORDER(12, CL_RG); + CHANNEL_ORDER(23, CL_RG); + CHANNEL_ORDER(1234, CL_RGBA); + CHANNEL_ORDER(3214, CL_BGRA); + CHANNEL_ORDER(4123, CL_ARGB); +#ifdef CL_ABGR + CHANNEL_ORDER(4321, CL_ABGR); +#endif + default: + return AVERROR(EINVAL); + } +#undef CHANNEL_ORDER + + return 0; +} + +static int opencl_frames_get_constraints(AVHWDeviceContext *hwdev, + const void *hwconfig, + AVHWFramesConstraints *constraints) +{ + AVOpenCLDeviceContext *hwctx = hwdev->hwctx; + cl_uint nb_image_formats; + cl_image_format *image_formats = NULL; + cl_int cle; + enum AVPixelFormat pix_fmt; + int err, pix_fmts_found; + size_t max_width, max_height; + + cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_IMAGE2D_MAX_WIDTH, + sizeof(max_width), &max_width, NULL); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to query maximum " + "supported image width: %d.\n", cle); + } else { + constraints->max_width = max_width; + } + cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_IMAGE2D_MAX_HEIGHT, + sizeof(max_height), &max_height, NULL); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to query maximum " + "supported image height: %d.\n", cle); + } else { + constraints->max_height = max_height; + } + av_log(hwdev, AV_LOG_DEBUG, "Maximum supported image size %dx%d.\n", + constraints->max_width, constraints->max_height); + + cle = clGetSupportedImageFormats(hwctx->context, + CL_MEM_READ_WRITE, + CL_MEM_OBJECT_IMAGE2D, + 0, NULL, &nb_image_formats); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to query supported " + "image formats: %d.\n", cle); + err = AVERROR(ENOSYS); + goto fail; + } + if (nb_image_formats == 0) { + av_log(hwdev, AV_LOG_ERROR, "No image support in OpenCL " + "driver (zero supported image formats).\n"); + err = AVERROR(ENOSYS); + goto fail; + } + + image_formats = + av_malloc_array(nb_image_formats, sizeof(*image_formats)); + if (!image_formats) { + err = AVERROR(ENOMEM); + goto fail; + } + + cle = clGetSupportedImageFormats(hwctx->context, + CL_MEM_READ_WRITE, + CL_MEM_OBJECT_IMAGE2D, + nb_image_formats, + image_formats, NULL); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to query supported " + "image formats: %d.\n", cle); + err = AVERROR(ENOSYS); + goto fail; + } + + pix_fmts_found = 0; + for (pix_fmt = 0; pix_fmt < AV_PIX_FMT_NB; pix_fmt++) { + cl_image_format image_format; + cl_image_desc image_desc; + int plane, i; + + for (plane = 0;; plane++) { + err = opencl_get_plane_format(pix_fmt, plane, 0, 0, + &image_format, + &image_desc); + if (err < 0) + break; + + for (i = 0; i < nb_image_formats; i++) { + if (image_formats[i].image_channel_order == + image_format.image_channel_order && + image_formats[i].image_channel_data_type == + image_format.image_channel_data_type) + break; + } + if (i == nb_image_formats) { + err = AVERROR(EINVAL); + break; + } + } + if (err != AVERROR(ENOENT)) + continue; + + av_log(hwdev, AV_LOG_DEBUG, "Format %s supported.\n", + av_get_pix_fmt_name(pix_fmt)); + + err = av_reallocp_array(&constraints->valid_sw_formats, + pix_fmts_found + 2, + sizeof(*constraints->valid_sw_formats)); + if (err < 0) + goto fail; + constraints->valid_sw_formats[pix_fmts_found] = pix_fmt; + constraints->valid_sw_formats[pix_fmts_found + 1] = + AV_PIX_FMT_NONE; + ++pix_fmts_found; + } + + av_freep(&image_formats); + + constraints->valid_hw_formats = + av_malloc_array(2, sizeof(*constraints->valid_hw_formats)); + if (!constraints->valid_hw_formats) { + err = AVERROR(ENOMEM); + goto fail; + } + constraints->valid_hw_formats[0] = AV_PIX_FMT_OPENCL; + constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE; + + return 0; + +fail: + av_freep(&image_formats); + return err; +} + +static void opencl_pool_free(void *opaque, uint8_t *data) +{ + AVHWFramesContext *hwfc = opaque; + AVOpenCLFrameDescriptor *desc = (AVOpenCLFrameDescriptor*)data; + cl_int cle; + int p; + + for (p = 0; p < desc->nb_planes; p++) { + cle = clReleaseMemObject(desc->planes[p]); + if (cle != CL_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to release plane %d: " + "%d.\n", p, cle); + } + } + + av_free(desc); +} + +static AVBufferRef *opencl_pool_alloc(void *opaque, int size) +{ + AVHWFramesContext *hwfc = opaque; + AVOpenCLDeviceContext *hwctx = hwfc->device_ctx->hwctx; + AVOpenCLFrameDescriptor *desc; + cl_int cle; + cl_mem image; + cl_image_format image_format; + cl_image_desc image_desc; + int err, p; + AVBufferRef *ref; + + desc = av_mallocz(sizeof(*desc)); + if (!desc) + return NULL; + + for (p = 0;; p++) { + err = opencl_get_plane_format(hwfc->sw_format, p, + hwfc->width, hwfc->height, + &image_format, &image_desc); + if (err == AVERROR(ENOENT)) + break; + if (err < 0) + goto fail; + + // For generic image objects, the pitch is determined by the + // implementation. + image_desc.image_row_pitch = 0; + + image = clCreateImage(hwctx->context, CL_MEM_READ_WRITE, + &image_format, &image_desc, NULL, &cle); + if (!image) { + av_log(hwfc, AV_LOG_ERROR, "Failed to create image for " + "plane %d: %d.\n", p, cle); + goto fail; + } + + desc->planes[p] = image; + } + + desc->nb_planes = p; + + ref = av_buffer_create((uint8_t*)desc, sizeof(*desc), + &opencl_pool_free, hwfc, 0); + if (!ref) + goto fail; + + return ref; + +fail: + for (p = 0; desc->planes[p]; p++) + clReleaseMemObject(desc->planes[p]); + av_free(desc); + return NULL; +} + +static int opencl_frames_init_command_queue(AVHWFramesContext *hwfc) +{ + AVOpenCLFramesContext *hwctx = hwfc->hwctx; + OpenCLDeviceContext *devpriv = hwfc->device_ctx->internal->priv; + OpenCLFramesContext *priv = hwfc->internal->priv; + cl_int cle; + + priv->command_queue = hwctx->command_queue ? hwctx->command_queue + : devpriv->command_queue; + cle = clRetainCommandQueue(priv->command_queue); + if (cle != CL_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to retain frame " + "command queue: %d.\n", cle); + return AVERROR(EIO); + } + + return 0; +} + +static int opencl_frames_init(AVHWFramesContext *hwfc) +{ + if (!hwfc->pool) { + hwfc->internal->pool_internal = + av_buffer_pool_init2(sizeof(cl_mem), hwfc, + &opencl_pool_alloc, NULL); + if (!hwfc->internal->pool_internal) + return AVERROR(ENOMEM); + } + + return opencl_frames_init_command_queue(hwfc); +} + +static void opencl_frames_uninit(AVHWFramesContext *hwfc) +{ + OpenCLFramesContext *priv = hwfc->internal->priv; + cl_int cle; + + cle = clReleaseCommandQueue(priv->command_queue); + if (cle != CL_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to release frame " + "command queue: %d.\n", cle); + } +} + +static int opencl_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame) +{ + AVOpenCLFrameDescriptor *desc; + int p; + + frame->buf[0] = av_buffer_pool_get(hwfc->pool); + if (!frame->buf[0]) + return AVERROR(ENOMEM); + + desc = (AVOpenCLFrameDescriptor*)frame->buf[0]->data; + + for (p = 0; p < desc->nb_planes; p++) + frame->data[p] = (uint8_t*)desc->planes[p]; + + frame->format = AV_PIX_FMT_OPENCL; + frame->width = hwfc->width; + frame->height = hwfc->height; + + return 0; +} + +static int opencl_transfer_get_formats(AVHWFramesContext *hwfc, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats) +{ + enum AVPixelFormat *fmts; + + fmts = av_malloc_array(2, sizeof(*fmts)); + if (!fmts) + return AVERROR(ENOMEM); + + fmts[0] = hwfc->sw_format; + fmts[1] = AV_PIX_FMT_NONE; + + *formats = fmts; + return 0; +} + +static int opencl_wait_events(AVHWFramesContext *hwfc, + cl_event *events, int nb_events) +{ + cl_int cle; + int i; + + cle = clWaitForEvents(nb_events, events); + if (cle != CL_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to wait for event " + "completion: %d.\n", cle); + return AVERROR(EIO); + } + + for (i = 0; i < nb_events; i++) { + cle = clReleaseEvent(events[i]); + if (cle != CL_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to release " + "event: %d.\n", cle); + } + } + + return 0; +} + +static int opencl_transfer_data_from(AVHWFramesContext *hwfc, + AVFrame *dst, const AVFrame *src) +{ + OpenCLFramesContext *priv = hwfc->internal->priv; + cl_image_format image_format; + cl_image_desc image_desc; + cl_int cle; + size_t origin[3] = { 0, 0, 0 }; + size_t region[3]; + cl_event events[AV_NUM_DATA_POINTERS]; + int err, p; + + if (dst->format != hwfc->sw_format) + return AVERROR(EINVAL); + + for (p = 0;; p++) { + err = opencl_get_plane_format(hwfc->sw_format, p, + src->width, src->height, + &image_format, &image_desc); + if (err < 0) { + if (err == AVERROR(ENOENT)) + err = 0; + break; + } + + if (!dst->data[p]) { + av_log(hwfc, AV_LOG_ERROR, "Plane %d missing on " + "destination frame for transfer.\n", p); + err = AVERROR(EINVAL); + break; + } + + region[0] = image_desc.image_width; + region[1] = image_desc.image_height; + region[2] = 1; + + cle = clEnqueueReadImage(priv->command_queue, + (cl_mem)src->data[p], + CL_FALSE, origin, region, + dst->linesize[p], 0, + dst->data[p], + 0, NULL, &events[p]); + if (cle != CL_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to enqueue read of " + "OpenCL image plane %d: %d.\n", p, cle); + err = AVERROR(EIO); + break; + } + } + + opencl_wait_events(hwfc, events, p); + + return err; +} + +static int opencl_transfer_data_to(AVHWFramesContext *hwfc, + AVFrame *dst, const AVFrame *src) +{ + OpenCLFramesContext *priv = hwfc->internal->priv; + cl_image_format image_format; + cl_image_desc image_desc; + cl_int cle; + size_t origin[3] = { 0, 0, 0 }; + size_t region[3]; + cl_event events[AV_NUM_DATA_POINTERS]; + int err, p; + + if (src->format != hwfc->sw_format) + return AVERROR(EINVAL); + + for (p = 0;; p++) { + err = opencl_get_plane_format(hwfc->sw_format, p, + src->width, src->height, + &image_format, &image_desc); + if (err < 0) { + if (err == AVERROR(ENOENT)) + err = 0; + break; + } + + if (!src->data[p]) { + av_log(hwfc, AV_LOG_ERROR, "Plane %d missing on " + "source frame for transfer.\n", p); + err = AVERROR(EINVAL); + break; + } + + region[0] = image_desc.image_width; + region[1] = image_desc.image_height; + region[2] = 1; + + cle = clEnqueueWriteImage(priv->command_queue, + (cl_mem)dst->data[p], + CL_FALSE, origin, region, + src->linesize[p], 0, + src->data[p], + 0, NULL, &events[p]); + if (cle != CL_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to enqueue write of " + "OpenCL image plane %d: %d.\n", p, cle); + err = AVERROR(EIO); + break; + } + } + + opencl_wait_events(hwfc, events, p); + + return err; +} + +typedef struct OpenCLMapping { + // The mapped addresses for each plane. + // The destination frame is not available when we unmap, so these + // need to be stored separately. + void *address[AV_NUM_DATA_POINTERS]; +} OpenCLMapping; + +static void opencl_unmap_frame(AVHWFramesContext *hwfc, + HWMapDescriptor *hwmap) +{ + OpenCLFramesContext *priv = hwfc->internal->priv; + OpenCLMapping *map = hwmap->priv; + cl_event events[AV_NUM_DATA_POINTERS]; + int p, e; + cl_int cle; + + for (p = e = 0; p < FF_ARRAY_ELEMS(map->address); p++) { + if (!map->address[p]) + break; + + cle = clEnqueueUnmapMemObject(priv->command_queue, + (cl_mem)hwmap->source->data[p], + map->address[p], + 0, NULL, &events[e]); + if (cle != CL_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to unmap OpenCL " + "image plane %d: %d.\n", p, cle); + } + ++e; + } + + opencl_wait_events(hwfc, events, e); + + av_free(map); +} + +static int opencl_map_frame(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ + OpenCLFramesContext *priv = hwfc->internal->priv; + cl_map_flags map_flags; + cl_image_format image_format; + cl_image_desc image_desc; + cl_int cle; + OpenCLMapping *map; + size_t origin[3] = { 0, 0, 0 }; + size_t region[3]; + size_t row_pitch; + cl_event events[AV_NUM_DATA_POINTERS]; + int err, p; + + av_assert0(hwfc->sw_format == dst->format); + + if (flags & AV_HWFRAME_MAP_OVERWRITE && + !(flags & AV_HWFRAME_MAP_READ)) { + // This is mutually exclusive with the read/write flags, so + // there is no way to map with read here. + map_flags = CL_MAP_WRITE_INVALIDATE_REGION; + } else { + map_flags = 0; + if (flags & AV_HWFRAME_MAP_READ) + map_flags |= CL_MAP_READ; + if (flags & AV_HWFRAME_MAP_WRITE) + map_flags |= CL_MAP_WRITE; + } + + map = av_mallocz(sizeof(*map)); + if (!map) + return AVERROR(ENOMEM); + + for (p = 0;; p++) { + err = opencl_get_plane_format(hwfc->sw_format, p, + src->width, src->height, + &image_format, &image_desc); + if (err == AVERROR(ENOENT)) + break; + if (err < 0) + goto fail; + + region[0] = image_desc.image_width; + region[1] = image_desc.image_height; + region[2] = 1; + + map->address[p] = + clEnqueueMapImage(priv->command_queue, + (cl_mem)src->data[p], + CL_FALSE, map_flags, origin, region, + &row_pitch, NULL, 0, NULL, + &events[p], &cle); + if (!map->address[p]) { + av_log(hwfc, AV_LOG_ERROR, "Failed to map OpenCL " + "image plane %d: %d.\n", p, cle); + err = AVERROR(EIO); + goto fail; + } + + dst->data[p] = map->address[p]; + + av_log(hwfc, AV_LOG_DEBUG, "Map plane %d (%p -> %p).\n", + p, src->data[p], dst->data[p]); + } + + err = opencl_wait_events(hwfc, events, p); + if (err < 0) + goto fail; + + err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, + &opencl_unmap_frame, map); + if (err < 0) + goto fail; + + dst->width = src->width; + dst->height = src->height; + + return 0; + +fail: + for (p = 0; p < AV_NUM_DATA_POINTERS; p++) { + if (!map->address[p]) + break; + clEnqueueUnmapMemObject(priv->command_queue, + (cl_mem)src->data[p], + map->address[p], + 0, NULL, &events[p]); + } + if (p > 0) + opencl_wait_events(hwfc, events, p); + av_freep(&map); + return err; +} + +static int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ + av_assert0(src->format == AV_PIX_FMT_OPENCL); + if (hwfc->sw_format != dst->format) + return AVERROR(ENOSYS); + return opencl_map_frame(hwfc, dst, src, flags); +} + +const HWContextType ff_hwcontext_type_opencl = { + .type = AV_HWDEVICE_TYPE_OPENCL, + .name = "OpenCL", + + .device_hwctx_size = sizeof(AVOpenCLDeviceContext), + .device_priv_size = sizeof(OpenCLDeviceContext), + .frames_hwctx_size = sizeof(AVOpenCLFramesContext), + .frames_priv_size = sizeof(OpenCLFramesContext), + + .device_create = &opencl_device_create, + .device_init = &opencl_device_init, + .device_uninit = &opencl_device_uninit, + + .frames_get_constraints = &opencl_frames_get_constraints, + .frames_init = &opencl_frames_init, + .frames_uninit = &opencl_frames_uninit, + .frames_get_buffer = &opencl_get_buffer, + + .transfer_get_formats = &opencl_transfer_get_formats, + .transfer_data_to = &opencl_transfer_data_to, + .transfer_data_from = &opencl_transfer_data_from, + + .map_from = &opencl_map_from, + + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_OPENCL, + AV_PIX_FMT_NONE + }, +}; diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h new file mode 100644 index 0000000000000..8e34df44cd2e3 --- /dev/null +++ b/libavutil/hwcontext_opencl.h @@ -0,0 +1,96 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_OPENCL_H +#define AVUTIL_HWCONTEXT_OPENCL_H + +#include + +#include "frame.h" + +/** + * @file + * API-specific header for AV_HWDEVICE_TYPE_OPENCL. + * + * Pools allocated internally are always dynamic, and are primarily intended + * to be used in OpenCL-only cases. If interoperation is required, it is + * typically required to allocate frames in the other API and then map the + * frames context to OpenCL with av_hwframe_ctx_create_derived(). + */ + +/** + * OpenCL frame descriptor for pool allocation. + * + * In user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs + * with the data pointer pointing at an object of this type describing the + * planes of the frame. + */ +typedef struct AVOpenCLFrameDescriptor { + /** + * Number of planes in the frame. + */ + int nb_planes; + /** + * OpenCL image2d objects for each plane of the frame. + */ + cl_mem planes[AV_NUM_DATA_POINTERS]; +} AVOpenCLFrameDescriptor; + +/** + * OpenCL device details. + * + * Allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVOpenCLDeviceContext { + /** + * The primary device ID of the device. If multiple OpenCL devices + * are associated with the context then this is the one which will + * be used for all operations internal to FFmpeg. + */ + cl_device_id device_id; + /** + * The OpenCL context which will contain all operations and frames on + * this device. + */ + cl_context context; + /** + * The default command queue for this device, which will be used by all + * frames contexts which do not have their own command queue. If not + * intialised by the user, a default queue will be created on the + * primary device. + */ + cl_command_queue command_queue; +} AVOpenCLDeviceContext; + +/** + * OpenCL-specific data associated with a frame pool. + * + * Allocated as AVHWFramesContext.hwctx. + */ +typedef struct AVOpenCLFramesContext { + /** + * The command queue used for internal asynchronous operations on this + * device (av_hwframe_transfer_data(), av_hwframe_map()). + * + * If this is not set, the command queue from the associated device is + * used instead. + */ + cl_command_queue command_queue; +} AVOpenCLFramesContext; + +#endif /* AVUTIL_HWCONTEXT_OPENCL_H */ diff --git a/libavutil/version.h b/libavutil/version.h index cf8ec498e4a28..3328faebf52c1 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -80,7 +80,7 @@ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 1 +#define LIBAVUTIL_VERSION_MINOR 2 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From eb3e9f469a52638e896f9c7f4b1ce98614bcb1ea Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:48 +0000 Subject: [PATCH 1057/2557] hwcontext_opencl: VAAPI to OpenCL mapping for Intel i965+beignet Supports all surface formats in common between the two. --- configure | 6 + libavutil/hwcontext_opencl.c | 298 +++++++++++++++++++++++++++++++++++ 2 files changed, 304 insertions(+) diff --git a/configure b/configure index 74920c388d504..a05c5cf960a79 100755 --- a/configure +++ b/configure @@ -2120,6 +2120,7 @@ HAVE_LIST=" $TYPES_LIST makeinfo makeinfo_html + opencl_vaapi_beignet perl pod2man texi2html @@ -6155,6 +6156,11 @@ enabled vaapi && check_cpp_condition "va/va.h" "VA_CHECK_VERSION(1, 0, 0)" && enable vaapi_1 +if enabled_all opencl vaapi ; then + check_type "CL/cl_intel.h" "clCreateImageFromFdINTEL_fn" && + enable opencl_vaapi_beignet +fi + enabled vdpau && check_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || disable vdpau diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index 0fe25d9500883..7f99f5af3ff3a 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -29,6 +29,14 @@ #include "mem.h" #include "pixdesc.h" +#if HAVE_OPENCL_VAAPI_BEIGNET +#include +#include +#include +#include +#include "hwcontext_vaapi.h" +#endif + typedef struct OpenCLDeviceContext { // Default command queue to use for transfer/mapping operations on @@ -41,6 +49,10 @@ typedef struct OpenCLDeviceContext { cl_platform_id platform_id; // Platform/device-specific functions. +#if HAVE_OPENCL_VAAPI_BEIGNET + int vaapi_mapping_usable; + clCreateImageFromFdINTEL_fn clCreateImageFromFdINTEL; +#endif } OpenCLDeviceContext; typedef struct OpenCLFramesContext { @@ -589,6 +601,40 @@ static int opencl_device_init(AVHWDeviceContext *hwdev) return AVERROR(EIO); } +#define CL_FUNC(name, desc) do { \ + if (fail) \ + break; \ + priv->name = clGetExtensionFunctionAddressForPlatform( \ + priv->platform_id, #name); \ + if (!priv->name) { \ + av_log(hwdev, AV_LOG_VERBOSE, \ + desc " function not found (%s).\n", #name); \ + fail = 1; \ + } else { \ + av_log(hwdev, AV_LOG_VERBOSE, \ + desc " function found (%s).\n", #name); \ + } \ + } while (0) + +#if HAVE_OPENCL_VAAPI_BEIGNET + { + int fail = 0; + + CL_FUNC(clCreateImageFromFdINTEL, + "Intel DRM to OpenCL image mapping"); + + if (fail) { + av_log(hwdev, AV_LOG_WARNING, "VAAPI to OpenCL mapping " + "not usable.\n"); + priv->vaapi_mapping_usable = 0; + } else { + priv->vaapi_mapping_usable = 1; + } + } +#endif + +#undef CL_FUNC + return 0; } @@ -606,6 +652,52 @@ static void opencl_device_uninit(AVHWDeviceContext *hwdev) } } +static int opencl_device_derive(AVHWDeviceContext *hwdev, + AVHWDeviceContext *src_ctx, + int flags) +{ + int err; + switch (src_ctx->type) { + +#if HAVE_OPENCL_VAAPI_BEIGNET + case AV_HWDEVICE_TYPE_VAAPI: + { + // Surface mapping works via DRM PRIME fds with no special + // initialisation required in advance. This just finds the + // Beignet ICD by name. + AVDictionary *opts = NULL; + + err = av_dict_set(&opts, "platform_vendor", "Intel", 0); + if (err >= 0) + err = av_dict_set(&opts, "platform_version", "beignet", 0); + if (err >= 0) { + OpenCLDeviceSelector selector = { + .platform_index = -1, + .device_index = 0, + .context = opts, + .enumerate_platforms = &opencl_enumerate_platforms, + .filter_platform = &opencl_filter_platform, + .enumerate_devices = &opencl_enumerate_devices, + .filter_device = NULL, + }; + err = opencl_device_create_internal(hwdev, &selector, NULL); + } + av_dict_free(&opts); + } + break; +#endif + + default: + err = AVERROR(ENOSYS); + break; + } + + if (err < 0) + return err; + + return opencl_device_init(hwdev); +} + static int opencl_get_plane_format(enum AVPixelFormat pixfmt, int plane, int width, int height, cl_image_format *image_format, @@ -1263,6 +1355,177 @@ static int opencl_map_frame(AVHWFramesContext *hwfc, AVFrame *dst, return err; } +#if HAVE_OPENCL_VAAPI_BEIGNET + +typedef struct VAAPItoOpenCLMapping { + VAImage va_image; + VABufferInfo va_buffer_info; + + AVOpenCLFrameDescriptor frame; +} VAAPItoOpenCLMapping; + +static void opencl_unmap_from_vaapi(AVHWFramesContext *src_fc, + HWMapDescriptor *hwmap) +{ + VAAPItoOpenCLMapping *mapping = hwmap->priv; + AVVAAPIDeviceContext *src_dev = src_fc->device_ctx->hwctx; + VASurfaceID surface_id; + VAStatus vas; + cl_int cle; + int i; + + surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3]; + av_log(src_fc, AV_LOG_DEBUG, "Unmap VAAPI surface %#x from OpenCL.\n", + surface_id); + + for (i = 0; i < mapping->frame.nb_planes; i++) { + cle = clReleaseMemObject(mapping->frame.planes[i]); + if (cle != CL_SUCCESS) { + av_log(src_fc, AV_LOG_ERROR, "Failed to release CL " + "buffer of plane %d of VA image %#x (derived " + "from surface %#x): %d.\n", i, + mapping->va_image.buf, surface_id, cle); + } + } + + vas = vaReleaseBufferHandle(src_dev->display, + mapping->va_image.buf); + if (vas != VA_STATUS_SUCCESS) { + av_log(src_fc, AV_LOG_ERROR, "Failed to release buffer " + "handle of image %#x (derived from surface %#x): " + "%d (%s).\n", mapping->va_image.buf, surface_id, + vas, vaErrorStr(vas)); + } + + vas = vaDestroyImage(src_dev->display, + mapping->va_image.image_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(src_fc, AV_LOG_ERROR, "Failed to destroy image " + "derived from surface %#x: %d (%s).\n", + surface_id, vas, vaErrorStr(vas)); + } + + av_free(mapping); +} + +static int opencl_map_from_vaapi(AVHWFramesContext *dst_fc, AVFrame *dst, + const AVFrame *src, int flags) +{ + AVHWFramesContext *src_fc = + (AVHWFramesContext*)src->hw_frames_ctx->data; + AVVAAPIDeviceContext *src_dev = src_fc->device_ctx->hwctx; + AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; + OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv; + VAAPItoOpenCLMapping *mapping = NULL; + VASurfaceID surface_id; + VAStatus vas; + cl_int cle; + int err, p; + + surface_id = (VASurfaceID)(uintptr_t)src->data[3]; + av_log(src_fc, AV_LOG_DEBUG, "Map VAAPI surface %#x to OpenCL.\n", + surface_id); + + mapping = av_mallocz(sizeof(*mapping)); + if (!mapping) + return AVERROR(ENOMEM); + + vas = vaDeriveImage(src_dev->display, surface_id, + &mapping->va_image); + if (vas != VA_STATUS_SUCCESS) { + av_log(src_fc, AV_LOG_ERROR, "Failed to derive image from " + "surface %#x: %d (%s).\n", + surface_id, vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + mapping->va_buffer_info.mem_type = + VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; + + vas = vaAcquireBufferHandle(src_dev->display, + mapping->va_image.buf, + &mapping->va_buffer_info); + if (vas != VA_STATUS_SUCCESS) { + av_log(src_fc, AV_LOG_ERROR, "Failed to get buffer " + "handle from image %#x (derived from surface %#x): " + "%d (%s).\n", mapping->va_image.buf, surface_id, + vas, vaErrorStr(vas)); + vaDestroyImage(src_dev->display, mapping->va_image.buf); + err = AVERROR(EIO); + goto fail_derived; + } + + av_log(dst_fc, AV_LOG_DEBUG, "DRM PRIME fd is %ld.\n", + mapping->va_buffer_info.handle); + + mapping->frame.nb_planes = mapping->va_image.num_planes; + for (p = 0; p < mapping->frame.nb_planes; p++) { + cl_import_image_info_intel image_info = { + .fd = mapping->va_buffer_info.handle, + .size = mapping->va_buffer_info.mem_size, + .type = CL_MEM_OBJECT_IMAGE2D, + .offset = mapping->va_image.offsets[p], + .row_pitch = mapping->va_image.pitches[p], + }; + cl_image_desc image_desc; + + err = opencl_get_plane_format(src_fc->sw_format, p, + mapping->va_image.width, + mapping->va_image.height, + &image_info.fmt, + &image_desc); + if (err < 0) { + av_log(dst_fc, AV_LOG_ERROR, "VA %#x (derived from " + "surface %#x) has invalid parameters: %d.\n", + mapping->va_image.buf, surface_id, err); + goto fail_mapped; + } + image_info.width = image_desc.image_width; + image_info.height = image_desc.image_height; + + mapping->frame.planes[p] = + priv->clCreateImageFromFdINTEL(dst_dev->context, + &image_info, &cle); + if (!mapping->frame.planes[p]) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL image " + "from plane %d of VA image %#x (derived from " + "surface %#x): %d.\n", p, + mapping->va_image.buf, surface_id, cle); + err = AVERROR(EIO); + goto fail_mapped; + } + + dst->data[p] = (uint8_t*)mapping->frame.planes[p]; + } + + err = ff_hwframe_map_create(src->hw_frames_ctx, + dst, src, &opencl_unmap_from_vaapi, + mapping); + if (err < 0) + goto fail_mapped; + + dst->width = src->width; + dst->height = src->height; + + return 0; + +fail_mapped: + for (p = 0; p < mapping->frame.nb_planes; p++) { + if (mapping->frame.planes[p]) + clReleaseMemObject(mapping->frame.planes[p]); + } + vaReleaseBufferHandle(src_dev->display, mapping->va_image.buf); +fail_derived: + vaDestroyImage(src_dev->display, mapping->va_image.image_id); +fail: + av_freep(&mapping); + return err; +} + +#endif + + static int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { @@ -1272,6 +1535,38 @@ static int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst, return opencl_map_frame(hwfc, dst, src, flags); } +static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ + OpenCLDeviceContext *priv = hwfc->device_ctx->internal->priv; + av_assert0(dst->format == AV_PIX_FMT_OPENCL); + switch (src->format) { +#if HAVE_OPENCL_VAAPI_BEIGNET + case AV_PIX_FMT_VAAPI: + if (priv->vaapi_mapping_usable) + return opencl_map_from_vaapi(hwfc, dst, src, flags); +#endif + } + return AVERROR(ENOSYS); +} + +static int opencl_frames_derive_to(AVHWFramesContext *dst_fc, + AVHWFramesContext *src_fc, int flags) +{ + OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv; + switch (src_fc->device_ctx->type) { +#if HAVE_OPENCL_VAAPI_BEIGNET + case AV_HWDEVICE_TYPE_VAAPI: + if (!priv->vaapi_mapping_usable) + return AVERROR(ENOSYS); + break; +#endif + default: + return AVERROR(ENOSYS); + } + return opencl_frames_init_command_queue(dst_fc); +} + const HWContextType ff_hwcontext_type_opencl = { .type = AV_HWDEVICE_TYPE_OPENCL, .name = "OpenCL", @@ -1282,6 +1577,7 @@ const HWContextType ff_hwcontext_type_opencl = { .frames_priv_size = sizeof(OpenCLFramesContext), .device_create = &opencl_device_create, + .device_derive = &opencl_device_derive, .device_init = &opencl_device_init, .device_uninit = &opencl_device_uninit, @@ -1295,6 +1591,8 @@ const HWContextType ff_hwcontext_type_opencl = { .transfer_data_from = &opencl_transfer_data_from, .map_from = &opencl_map_from, + .map_to = &opencl_map_to, + .frames_derive_to = &opencl_frames_derive_to, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_OPENCL, From 403cde8e85101c8d4d99a3df4bde51e5a24cfded Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Mar 2017 23:57:49 +0000 Subject: [PATCH 1058/2557] hwcontext_opencl: QSV to OpenCL mapping for Intel Media SDK Uses the cl_intel_va_api_media_sharing extension, which supports only NV12 surfaces and only mapping from QSV to OpenCL. --- configure | 5 + libavutil/hwcontext_opencl.c | 365 +++++++++++++++++++++++++++++++++++ 2 files changed, 370 insertions(+) diff --git a/configure b/configure index a05c5cf960a79..34fe16f80e9f8 100755 --- a/configure +++ b/configure @@ -2121,6 +2121,7 @@ HAVE_LIST=" makeinfo makeinfo_html opencl_vaapi_beignet + opencl_vaapi_intel_media perl pod2man texi2html @@ -6159,6 +6160,10 @@ enabled vaapi && if enabled_all opencl vaapi ; then check_type "CL/cl_intel.h" "clCreateImageFromFdINTEL_fn" && enable opencl_vaapi_beignet + if enabled libmfx ; then + check_type "CL/cl.h CL/va_ext.h" "clCreateFromVA_APIMediaSurfaceINTEL_fn" && + enable opencl_vaapi_intel_media + fi fi enabled vdpau && diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index 7f99f5af3ff3a..ee6ebd18d1a93 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -37,6 +37,13 @@ #include "hwcontext_vaapi.h" #endif +#if HAVE_OPENCL_VAAPI_INTEL_MEDIA +#include +#include +#include +#include "hwcontext_vaapi.h" +#endif + typedef struct OpenCLDeviceContext { // Default command queue to use for transfer/mapping operations on @@ -53,6 +60,16 @@ typedef struct OpenCLDeviceContext { int vaapi_mapping_usable; clCreateImageFromFdINTEL_fn clCreateImageFromFdINTEL; #endif + +#if HAVE_OPENCL_VAAPI_INTEL_MEDIA + int qsv_mapping_usable; + clCreateFromVA_APIMediaSurfaceINTEL_fn + clCreateFromVA_APIMediaSurfaceINTEL; + clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn + clEnqueueAcquireVA_APIMediaSurfacesINTEL; + clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn + clEnqueueReleaseVA_APIMediaSurfacesINTEL; +#endif } OpenCLDeviceContext; typedef struct OpenCLFramesContext { @@ -633,6 +650,85 @@ static int opencl_device_init(AVHWDeviceContext *hwdev) } #endif +#if HAVE_OPENCL_VAAPI_INTEL_MEDIA + { + size_t props_size; + cl_context_properties *props = NULL; + VADisplay va_display; + const char *va_ext = "cl_intel_va_api_media_sharing"; + int i, fail = 0; + + if (!opencl_check_extension(hwdev, va_ext)) { + av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is " + "required for QSV to OpenCL mapping.\n", va_ext); + goto no_qsv; + } + + cle = clGetContextInfo(hwctx->context, CL_CONTEXT_PROPERTIES, + 0, NULL, &props_size); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_VERBOSE, "Failed to get context " + "properties: %d.\n", cle); + goto no_qsv; + } + if (props_size == 0) { + av_log(hwdev, AV_LOG_VERBOSE, "Media sharing must be " + "enabled on context creation to use QSV to " + "OpenCL mapping.\n"); + goto no_qsv; + } + + props = av_malloc(props_size); + if (!props) + return AVERROR(ENOMEM); + + cle = clGetContextInfo(hwctx->context, CL_CONTEXT_PROPERTIES, + props_size, props, NULL); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_VERBOSE, "Failed to get context " + "properties: %d.\n", cle); + goto no_qsv; + } + + va_display = NULL; + for (i = 0; i < (props_size / sizeof(*props) - 1); i++) { + if (props[i] == CL_CONTEXT_VA_API_DISPLAY_INTEL) { + va_display = (VADisplay)(intptr_t)props[i+1]; + break; + } + } + if (!va_display) { + av_log(hwdev, AV_LOG_VERBOSE, "Media sharing must be " + "enabled on context creation to use QSV to " + "OpenCL mapping.\n"); + goto no_qsv; + } + if (!vaDisplayIsValid(va_display)) { + av_log(hwdev, AV_LOG_VERBOSE, "A valid VADisplay is " + "required on context creation to use QSV to " + "OpenCL mapping.\n"); + goto no_qsv; + } + + CL_FUNC(clCreateFromVA_APIMediaSurfaceINTEL, + "Intel QSV to OpenCL mapping"); + CL_FUNC(clEnqueueAcquireVA_APIMediaSurfacesINTEL, + "Intel QSV in OpenCL acquire"); + CL_FUNC(clEnqueueReleaseVA_APIMediaSurfacesINTEL, + "Intel QSV in OpenCL release"); + + if (fail) { + no_qsv: + av_log(hwdev, AV_LOG_WARNING, "QSV to OpenCL mapping " + "not usable.\n"); + priv->qsv_mapping_usable = 0; + } else { + priv->qsv_mapping_usable = 1; + } + av_free(props); + } +#endif + #undef CL_FUNC return 0; @@ -652,6 +748,95 @@ static void opencl_device_uninit(AVHWDeviceContext *hwdev) } } +#if HAVE_OPENCL_VAAPI_INTEL_MEDIA +static int opencl_filter_intel_media_vaapi_platform(AVHWDeviceContext *hwdev, + cl_platform_id platform_id, + const char *platform_name, + void *context) +{ + // This doesn't exist as a platform extension, so just test whether + // the function we will use for device enumeration exists. + + if (!clGetExtensionFunctionAddressForPlatform(platform_id, + "clGetDeviceIDsFromVA_APIMediaAdapterINTEL")) { + av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not export the " + "VAAPI device enumeration function.\n", platform_name); + return 1; + } else { + return 0; + } +} + +static int opencl_enumerate_intel_media_vaapi_devices(AVHWDeviceContext *hwdev, + cl_platform_id platform_id, + const char *platform_name, + cl_uint *nb_devices, + cl_device_id **devices, + void *context) +{ + VADisplay va_display = context; + clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn + clGetDeviceIDsFromVA_APIMediaAdapterINTEL; + cl_int cle; + int err; + + clGetDeviceIDsFromVA_APIMediaAdapterINTEL = + clGetExtensionFunctionAddressForPlatform(platform_id, + "clGetDeviceIDsFromVA_APIMediaAdapterINTEL"); + if (!clGetDeviceIDsFromVA_APIMediaAdapterINTEL) { + av_log(hwdev, AV_LOG_ERROR, "Failed to get address of " + "clGetDeviceIDsFromVA_APIMediaAdapterINTEL().\n"); + return AVERROR_UNKNOWN; + } + + cle = clGetDeviceIDsFromVA_APIMediaAdapterINTEL( + platform_id, CL_VA_API_DISPLAY_INTEL, va_display, + CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, 0, NULL, nb_devices); + if (cle == CL_DEVICE_NOT_FOUND) { + av_log(hwdev, AV_LOG_DEBUG, "No VAAPI-supporting devices found " + "on platform \"%s\".\n", platform_name); + *nb_devices = 0; + return 0; + } else if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices " + "on platform \"%s\": %d.\n", platform_name, cle); + return AVERROR_UNKNOWN; + } + + *devices = av_malloc_array(*nb_devices, sizeof(**devices)); + if (!*devices) + return AVERROR(ENOMEM); + + cle = clGetDeviceIDsFromVA_APIMediaAdapterINTEL( + platform_id, CL_VA_API_DISPLAY_INTEL, va_display, + CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, *nb_devices, *devices, NULL); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to get list of VAAPI-supporting " + "devices on platform \"%s\": %d.\n", platform_name, cle); + av_freep(devices); + return AVERROR_UNKNOWN; + } + + return 0; +} + +static int opencl_filter_intel_media_vaapi_device(AVHWDeviceContext *hwdev, + cl_device_id device_id, + const char *device_name, + void *context) +{ + const char *va_ext = "cl_intel_va_api_media_sharing"; + + if (opencl_check_device_extension(device_id, va_ext)) { + return 0; + } else { + av_log(hwdev, AV_LOG_DEBUG, "Device %s does not support the " + "%s extension.\n", device_name, va_ext); + return 1; + } +} +#endif + static int opencl_device_derive(AVHWDeviceContext *hwdev, AVHWDeviceContext *src_ctx, int flags) @@ -687,6 +872,37 @@ static int opencl_device_derive(AVHWDeviceContext *hwdev, break; #endif +#if HAVE_OPENCL_VAAPI_INTEL_MEDIA + // The generic code automatically attempts to derive from all + // ancestors of the given device, so we can ignore QSV devices here + // and just consider the inner VAAPI device it was derived from. + case AV_HWDEVICE_TYPE_VAAPI: + { + AVVAAPIDeviceContext *src_hwctx = src_ctx->hwctx; + cl_context_properties props[7] = { + CL_CONTEXT_PLATFORM, + 0, + CL_CONTEXT_VA_API_DISPLAY_INTEL, + (intptr_t)src_hwctx->display, + CL_CONTEXT_INTEROP_USER_SYNC, + CL_FALSE, + 0, + }; + OpenCLDeviceSelector selector = { + .platform_index = -1, + .device_index = -1, + .context = src_hwctx->display, + .enumerate_platforms = &opencl_enumerate_platforms, + .filter_platform = &opencl_filter_intel_media_vaapi_platform, + .enumerate_devices = &opencl_enumerate_intel_media_vaapi_devices, + .filter_device = &opencl_filter_intel_media_vaapi_device, + }; + + err = opencl_device_create_internal(hwdev, &selector, props); + } + break; +#endif + default: err = AVERROR(ENOSYS); break; @@ -1525,6 +1741,142 @@ static int opencl_map_from_vaapi(AVHWFramesContext *dst_fc, AVFrame *dst, #endif +static inline cl_mem_flags opencl_mem_flags_for_mapping(int map_flags) +{ + if ((map_flags & AV_HWFRAME_MAP_READ) && + (map_flags & AV_HWFRAME_MAP_WRITE)) + return CL_MEM_READ_WRITE; + else if (map_flags & AV_HWFRAME_MAP_READ) + return CL_MEM_READ_ONLY; + else if (map_flags & AV_HWFRAME_MAP_WRITE) + return CL_MEM_WRITE_ONLY; + else + return 0; +} + +#if HAVE_OPENCL_VAAPI_INTEL_MEDIA + +static void opencl_unmap_from_qsv(AVHWFramesContext *dst_fc, + HWMapDescriptor *hwmap) +{ + AVOpenCLFrameDescriptor *desc = hwmap->priv; + OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; + OpenCLFramesContext *frames_priv = dst_fc->internal->priv; + cl_event event; + cl_int cle; + int p; + + av_log(dst_fc, AV_LOG_DEBUG, "Unmap QSV/VAAPI surface from OpenCL.\n"); + + cle = device_priv->clEnqueueReleaseVA_APIMediaSurfacesINTEL( + frames_priv->command_queue, desc->nb_planes, desc->planes, + 0, NULL, &event); + if (cle != CL_SUCCESS) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface " + "handles: %d.\n", cle); + } + + opencl_wait_events(dst_fc, &event, 1); + + for (p = 0; p < desc->nb_planes; p++) { + cle = clReleaseMemObject(desc->planes[p]); + if (cle != CL_SUCCESS) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to release CL " + "image of plane %d of QSV/VAAPI surface: %d\n", + p, cle); + } + } + + av_free(desc); +} + +static int opencl_map_from_qsv(AVHWFramesContext *dst_fc, AVFrame *dst, + const AVFrame *src, int flags) +{ + AVHWFramesContext *src_fc = + (AVHWFramesContext*)src->hw_frames_ctx->data; + AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; + OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; + OpenCLFramesContext *frames_priv = dst_fc->internal->priv; + AVOpenCLFrameDescriptor *desc; + VASurfaceID va_surface; + cl_mem_flags cl_flags; + cl_event event; + cl_int cle; + int err, p; + + if (src->format == AV_PIX_FMT_QSV) { + mfxFrameSurface1 *mfx_surface = (mfxFrameSurface1*)src->data[3]; + va_surface = *(VASurfaceID*)mfx_surface->Data.MemId; + } else if (src->format == AV_PIX_FMT_VAAPI) { + va_surface = (VASurfaceID)(uintptr_t)src->data[3]; + } else { + return AVERROR(ENOSYS); + } + + cl_flags = opencl_mem_flags_for_mapping(flags); + if (!cl_flags) + return AVERROR(EINVAL); + + av_log(src_fc, AV_LOG_DEBUG, "Map QSV/VAAPI surface %#x to " + "OpenCL.\n", va_surface); + + desc = av_mallocz(sizeof(*desc)); + if (!desc) + return AVERROR(ENOMEM); + + // The cl_intel_va_api_media_sharing extension only supports NV12 + // surfaces, so for now there are always exactly two planes. + desc->nb_planes = 2; + + for (p = 0; p < desc->nb_planes; p++) { + desc->planes[p] = + device_priv->clCreateFromVA_APIMediaSurfaceINTEL( + dst_dev->context, cl_flags, &va_surface, p, &cle); + if (!desc->planes[p]) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL " + "image from plane %d of QSV/VAAPI surface " + "%#x: %d.\n", p, va_surface, cle); + err = AVERROR(EIO); + goto fail; + } + + dst->data[p] = (uint8_t*)desc->planes[p]; + } + + cle = device_priv->clEnqueueAcquireVA_APIMediaSurfacesINTEL( + frames_priv->command_queue, desc->nb_planes, desc->planes, + 0, NULL, &event); + if (cle != CL_SUCCESS) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface " + "handles: %d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + + err = opencl_wait_events(dst_fc, &event, 1); + if (err < 0) + goto fail; + + err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, + &opencl_unmap_from_qsv, desc); + if (err < 0) + goto fail; + + dst->width = src->width; + dst->height = src->height; + + return 0; + +fail: + for (p = 0; p < desc->nb_planes; p++) + if (desc->planes[p]) + clReleaseMemObject(desc->planes[p]); + av_freep(&desc); + return err; +} + +#endif static int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) @@ -1545,6 +1897,12 @@ static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst, case AV_PIX_FMT_VAAPI: if (priv->vaapi_mapping_usable) return opencl_map_from_vaapi(hwfc, dst, src, flags); +#endif +#if HAVE_OPENCL_VAAPI_INTEL_MEDIA + case AV_PIX_FMT_QSV: + case AV_PIX_FMT_VAAPI: + if (priv->qsv_mapping_usable) + return opencl_map_from_qsv(hwfc, dst, src, flags); #endif } return AVERROR(ENOSYS); @@ -1560,6 +1918,13 @@ static int opencl_frames_derive_to(AVHWFramesContext *dst_fc, if (!priv->vaapi_mapping_usable) return AVERROR(ENOSYS); break; +#endif +#if HAVE_OPENCL_VAAPI_INTEL_MEDIA + case AV_HWDEVICE_TYPE_QSV: + case AV_HWDEVICE_TYPE_VAAPI: + if (!priv->qsv_mapping_usable) + return AVERROR(ENOSYS); + break; #endif default: return AVERROR(ENOSYS); From 9e7cda1b1e790c3d6a7507820a0b1e77804527ca Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 5 Mar 2017 16:21:41 +0000 Subject: [PATCH 1059/2557] hwcontext_opencl: DXVA2 to OpenCL mapping Using cl_khr_dx9_media_sharing. --- configure | 6 + libavutil/hwcontext_opencl.c | 397 +++++++++++++++++++++++++++++++++++ 2 files changed, 403 insertions(+) diff --git a/configure b/configure index 34fe16f80e9f8..9b0542b2f2239 100755 --- a/configure +++ b/configure @@ -2120,6 +2120,7 @@ HAVE_LIST=" $TYPES_LIST makeinfo makeinfo_html + opencl_dxva2 opencl_vaapi_beignet opencl_vaapi_intel_media perl @@ -6166,6 +6167,11 @@ if enabled_all opencl vaapi ; then fi fi +if enabled_all opencl dxva2 ; then + check_type "CL/cl_dx9_media_sharing.h" cl_dx9_surface_info_khr && + enable opencl_dxva2 +fi + enabled vdpau && check_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || disable vdpau diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index ee6ebd18d1a93..cbee32b94c465 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -44,6 +44,13 @@ #include "hwcontext_vaapi.h" #endif +#if HAVE_OPENCL_DXVA2 +#define COBJMACROS +#include +#include +#include "hwcontext_dxva2.h" +#endif + typedef struct OpenCLDeviceContext { // Default command queue to use for transfer/mapping operations on @@ -70,6 +77,18 @@ typedef struct OpenCLDeviceContext { clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn clEnqueueReleaseVA_APIMediaSurfacesINTEL; #endif + +#if HAVE_OPENCL_DXVA2 + int dxva2_mapping_usable; + cl_dx9_media_adapter_type_khr dx9_media_adapter_type; + + clCreateFromDX9MediaSurfaceKHR_fn + clCreateFromDX9MediaSurfaceKHR; + clEnqueueAcquireDX9MediaSurfacesKHR_fn + clEnqueueAcquireDX9MediaSurfacesKHR; + clEnqueueReleaseDX9MediaSurfacesKHR_fn + clEnqueueReleaseDX9MediaSurfacesKHR; +#endif } OpenCLDeviceContext; typedef struct OpenCLFramesContext { @@ -78,6 +97,14 @@ typedef struct OpenCLFramesContext { // Otherwise, it is a reference to the default command queue for the // device. cl_command_queue command_queue; + +#if HAVE_OPENCL_DXVA2 + // For mapping APIs which have separate creation and acquire/release + // steps, this stores the OpenCL memory objects corresponding to each + // frame. + int nb_mapped_frames; + AVOpenCLFrameDescriptor *mapped_frames; +#endif } OpenCLFramesContext; @@ -729,6 +756,28 @@ static int opencl_device_init(AVHWDeviceContext *hwdev) } #endif +#if HAVE_OPENCL_DXVA2 + { + int fail = 0; + + CL_FUNC(clCreateFromDX9MediaSurfaceKHR, + "DXVA2 to OpenCL mapping"); + CL_FUNC(clEnqueueAcquireDX9MediaSurfacesKHR, + "DXVA2 in OpenCL acquire"); + CL_FUNC(clEnqueueReleaseDX9MediaSurfacesKHR, + "DXVA2 in OpenCL release"); + + if (fail) { + av_log(hwdev, AV_LOG_WARNING, "DXVA2 to OpenCL mapping " + "not usable.\n"); + priv->dxva2_mapping_usable = 0; + } else { + priv->dx9_media_adapter_type = CL_ADAPTER_D3D9EX_KHR; + priv->dxva2_mapping_usable = 1; + } + } +#endif + #undef CL_FUNC return 0; @@ -837,6 +886,103 @@ static int opencl_filter_intel_media_vaapi_device(AVHWDeviceContext *hwdev, } #endif +#if HAVE_OPENCL_DXVA2 +static int opencl_filter_dxva2_platform(AVHWDeviceContext *hwdev, + cl_platform_id platform_id, + const char *platform_name, + void *context) +{ + const char *dx9_ext = "cl_khr_dx9_media_sharing"; + + if (opencl_check_platform_extension(platform_id, dx9_ext)) { + return 0; + } else { + av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not support the " + "%s extension.\n", platform_name, dx9_ext); + return 1; + } +} + +static int opencl_enumerate_dxva2_devices(AVHWDeviceContext *hwdev, + cl_platform_id platform_id, + const char *platform_name, + cl_uint *nb_devices, + cl_device_id **devices, + void *context) +{ + IDirect3DDevice9 *device = context; + clGetDeviceIDsFromDX9MediaAdapterKHR_fn + clGetDeviceIDsFromDX9MediaAdapterKHR; + cl_dx9_media_adapter_type_khr media_adapter_type = CL_ADAPTER_D3D9EX_KHR; + cl_int cle; + + clGetDeviceIDsFromDX9MediaAdapterKHR = + clGetExtensionFunctionAddressForPlatform(platform_id, + "clGetDeviceIDsFromDX9MediaAdapterKHR"); + if (!clGetDeviceIDsFromDX9MediaAdapterKHR) { + av_log(hwdev, AV_LOG_ERROR, "Failed to get address of " + "clGetDeviceIDsFromDX9MediaAdapterKHR().\n"); + return AVERROR_UNKNOWN; + } + + cle = clGetDeviceIDsFromDX9MediaAdapterKHR( + platform_id, 1, &media_adapter_type, (void**)&device, + CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, + 0, NULL, nb_devices); + if (cle == CL_DEVICE_NOT_FOUND) { + av_log(hwdev, AV_LOG_DEBUG, "No DXVA2-supporting devices found " + "on platform \"%s\".\n", platform_name); + *nb_devices = 0; + return 0; + } else if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices " + "on platform \"%s\": %d.\n", platform_name, cle); + return AVERROR_UNKNOWN; + } + + *devices = av_malloc_array(*nb_devices, sizeof(**devices)); + if (!*devices) + return AVERROR(ENOMEM); + + cle = clGetDeviceIDsFromDX9MediaAdapterKHR( + platform_id, 1, &media_adapter_type, (void**)&device, + CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, + *nb_devices, *devices, NULL); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to get list of DXVA2-supporting " + "devices on platform \"%s\": %d.\n", platform_name, cle); + av_freep(devices); + return AVERROR_UNKNOWN; + } + + return 0; +} + +static int opencl_filter_gpu_device(AVHWDeviceContext *hwdev, + cl_device_id device_id, + const char *device_name, + void *context) +{ + cl_device_type device_type; + cl_int cle; + + cle = clGetDeviceInfo(device_id, CL_DEVICE_TYPE, + sizeof(device_type), &device_type, NULL); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to query device type " + "of device \"%s\".\n", device_name); + return AVERROR_UNKNOWN; + } + if (!(device_type & CL_DEVICE_TYPE_GPU)) { + av_log(hwdev, AV_LOG_DEBUG, "Device %s skipped (not GPU).\n", + device_name); + return 1; + } + + return 0; +} +#endif + static int opencl_device_derive(AVHWDeviceContext *hwdev, AVHWDeviceContext *src_ctx, int flags) @@ -903,6 +1049,60 @@ static int opencl_device_derive(AVHWDeviceContext *hwdev, break; #endif +#if HAVE_OPENCL_DXVA2 + case AV_HWDEVICE_TYPE_DXVA2: + { + AVDXVA2DeviceContext *src_hwctx = src_ctx->hwctx; + IDirect3DDevice9 *device; + HANDLE device_handle; + HRESULT hr; + + hr = IDirect3DDeviceManager9_OpenDeviceHandle(src_hwctx->devmgr, + &device_handle); + if (FAILED(hr)) { + av_log(hwdev, AV_LOG_ERROR, "Failed to open device handle " + "for Direct3D9 device: %lx.\n", (unsigned long)hr); + err = AVERROR_UNKNOWN; + break; + } + + hr = IDirect3DDeviceManager9_LockDevice(src_hwctx->devmgr, + device_handle, + &device, FALSE); + if (SUCCEEDED(hr)) { + cl_context_properties props[5] = { + CL_CONTEXT_PLATFORM, + 0, + CL_CONTEXT_ADAPTER_D3D9EX_KHR, + (intptr_t)device, + 0, + }; + OpenCLDeviceSelector selector = { + .platform_index = -1, + .device_index = -1, + .context = device, + .enumerate_platforms = &opencl_enumerate_platforms, + .filter_platform = &opencl_filter_dxva2_platform, + .enumerate_devices = &opencl_enumerate_dxva2_devices, + .filter_device = &opencl_filter_gpu_device, + }; + + err = opencl_device_create_internal(hwdev, &selector, props); + + IDirect3DDeviceManager9_UnlockDevice(src_hwctx->devmgr, + device_handle, FALSE); + } else { + av_log(hwdev, AV_LOG_ERROR, "Failed to lock device handle " + "for Direct3D9 device: %lx.\n", (unsigned long)hr); + err = AVERROR_UNKNOWN; + } + + IDirect3DDeviceManager9_CloseDeviceHandle(src_hwctx->devmgr, + device_handle); + } + break; +#endif + default: err = AVERROR(ENOSYS); break; @@ -1261,6 +1461,22 @@ static void opencl_frames_uninit(AVHWFramesContext *hwfc) OpenCLFramesContext *priv = hwfc->internal->priv; cl_int cle; +#if HAVE_OPENCL_DXVA2 + int i, p; + for (i = 0; i < priv->nb_mapped_frames; i++) { + AVOpenCLFrameDescriptor *desc = &priv->mapped_frames[i]; + for (p = 0; p < desc->nb_planes; p++) { + cle = clReleaseMemObject(desc->planes[p]); + if (cle != CL_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to release mapped " + "frame object (frame %d plane %d): %d.\n", + i, p, cle); + } + } + } + av_freep(&priv->mapped_frames); +#endif + cle = clReleaseCommandQueue(priv->command_queue); if (cle != CL_SUCCESS) { av_log(hwfc, AV_LOG_ERROR, "Failed to release frame " @@ -1878,6 +2094,170 @@ static int opencl_map_from_qsv(AVHWFramesContext *dst_fc, AVFrame *dst, #endif +#if HAVE_OPENCL_DXVA2 + +static void opencl_unmap_from_dxva2(AVHWFramesContext *dst_fc, + HWMapDescriptor *hwmap) +{ + AVOpenCLFrameDescriptor *desc = hwmap->priv; + OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; + OpenCLFramesContext *frames_priv = dst_fc->device_ctx->internal->priv; + cl_event event; + cl_int cle; + + av_log(dst_fc, AV_LOG_DEBUG, "Unmap DXVA2 surface from OpenCL.\n"); + + cle = device_priv->clEnqueueReleaseDX9MediaSurfacesKHR( + frames_priv->command_queue, desc->nb_planes, desc->planes, + 0, NULL, &event); + if (cle != CL_SUCCESS) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface " + "handle: %d.\n", cle); + return; + } + + opencl_wait_events(dst_fc, &event, 1); +} + +static int opencl_map_from_dxva2(AVHWFramesContext *dst_fc, AVFrame *dst, + const AVFrame *src, int flags) +{ + AVHWFramesContext *src_fc = + (AVHWFramesContext*)src->hw_frames_ctx->data; + AVDXVA2FramesContext *src_hwctx = src_fc->hwctx; + OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; + OpenCLFramesContext *frames_priv = dst_fc->internal->priv; + AVOpenCLFrameDescriptor *desc; + cl_event event; + cl_int cle; + int err, i; + + av_log(dst_fc, AV_LOG_DEBUG, "Map DXVA2 surface %p to " + "OpenCL.\n", src->data[3]); + + for (i = 0; i < src_hwctx->nb_surfaces; i++) { + if (src_hwctx->surfaces[i] == (IDirect3DSurface9*)src->data[3]) + break; + } + if (i >= src_hwctx->nb_surfaces) { + av_log(dst_fc, AV_LOG_ERROR, "Trying to map from a surface which " + "is not in the mapped frames context.\n"); + return AVERROR(EINVAL); + } + + desc = &frames_priv->mapped_frames[i]; + + cle = device_priv->clEnqueueAcquireDX9MediaSurfacesKHR( + frames_priv->command_queue, desc->nb_planes, desc->planes, + 0, NULL, &event); + if (cle != CL_SUCCESS) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface " + "handle: %d.\n", cle); + return AVERROR(EIO); + } + + err = opencl_wait_events(dst_fc, &event, 1); + if (err < 0) + goto fail; + + for (i = 0; i < desc->nb_planes; i++) + dst->data[i] = (uint8_t*)desc->planes[i]; + + err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, + &opencl_unmap_from_dxva2, desc); + if (err < 0) + goto fail; + + dst->width = src->width; + dst->height = src->height; + + return 0; + +fail: + cle = device_priv->clEnqueueReleaseDX9MediaSurfacesKHR( + frames_priv->command_queue, desc->nb_planes, desc->planes, + 0, NULL, &event); + if (cle == CL_SUCCESS) + opencl_wait_events(dst_fc, &event, 1); + return err; +} + +static int opencl_frames_derive_from_dxva2(AVHWFramesContext *dst_fc, + AVHWFramesContext *src_fc, int flags) +{ + AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; + AVDXVA2FramesContext *src_hwctx = src_fc->hwctx; + OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; + OpenCLFramesContext *frames_priv = dst_fc->internal->priv; + cl_mem_flags cl_flags; + cl_int cle; + int err, i, p, nb_planes; + + if (src_fc->sw_format != AV_PIX_FMT_NV12) { + av_log(dst_fc, AV_LOG_ERROR, "Only NV12 textures are supported " + "for DXVA2 to OpenCL mapping.\n"); + return AVERROR(EINVAL); + } + nb_planes = 2; + + if (src_fc->initial_pool_size == 0) { + av_log(dst_fc, AV_LOG_ERROR, "Only fixed-size pools are supported " + "for DXVA2 to OpenCL mapping.\n"); + return AVERROR(EINVAL); + } + + cl_flags = opencl_mem_flags_for_mapping(flags); + if (!cl_flags) + return AVERROR(EINVAL); + + frames_priv->nb_mapped_frames = src_hwctx->nb_surfaces; + + frames_priv->mapped_frames = + av_mallocz_array(frames_priv->nb_mapped_frames, + sizeof(*frames_priv->mapped_frames)); + if (!frames_priv->mapped_frames) + return AVERROR(ENOMEM); + + for (i = 0; i < frames_priv->nb_mapped_frames; i++) { + AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i]; + cl_dx9_surface_info_khr surface_info = { + .resource = src_hwctx->surfaces[i], + .shared_handle = NULL, + }; + desc->nb_planes = nb_planes; + for (p = 0; p < nb_planes; p++) { + desc->planes[p] = + device_priv->clCreateFromDX9MediaSurfaceKHR( + dst_dev->context, cl_flags, + device_priv->dx9_media_adapter_type, + &surface_info, p, &cle); + if (!desc->planes[p]) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL " + "image from plane %d of DXVA2 surface %d: %d.\n", + p, i, cle); + err = AVERROR(EIO); + goto fail; + } + } + } + + return 0; + +fail: + for (i = 0; i < frames_priv->nb_mapped_frames; i++) { + AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i]; + for (p = 0; p < desc->nb_planes; p++) { + if (desc->planes[p]) + clReleaseMemObject(desc->planes[p]); + } + } + av_freep(&frames_priv->mapped_frames); + frames_priv->nb_mapped_frames = 0; + return err; +} + +#endif + static int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { @@ -1903,6 +2283,11 @@ static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst, case AV_PIX_FMT_VAAPI: if (priv->qsv_mapping_usable) return opencl_map_from_qsv(hwfc, dst, src, flags); +#endif +#if HAVE_OPENCL_DXVA2 + case AV_PIX_FMT_DXVA2_VLD: + if (priv->dxva2_mapping_usable) + return opencl_map_from_dxva2(hwfc, dst, src, flags); #endif } return AVERROR(ENOSYS); @@ -1925,6 +2310,18 @@ static int opencl_frames_derive_to(AVHWFramesContext *dst_fc, if (!priv->qsv_mapping_usable) return AVERROR(ENOSYS); break; +#endif +#if HAVE_OPENCL_DXVA2 + case AV_HWDEVICE_TYPE_DXVA2: + if (!priv->dxva2_mapping_usable) + return AVERROR(ENOSYS); + { + int err; + err = opencl_frames_derive_from_dxva2(dst_fc, src_fc, flags); + if (err < 0) + return err; + } + break; #endif default: return AVERROR(ENOSYS); From f06754e4f3c26ee8f2ff1df219ae3f5dfa99c580 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 25 Jun 2017 22:34:40 +0100 Subject: [PATCH 1060/2557] hwcontext_opencl: D3D11 to OpenCL mapping Using cl_khr_d3d11_sharing and cl_intel_d3d11_nv12_media_sharing. --- configure | 6 + libavutil/hwcontext_opencl.c | 321 ++++++++++++++++++++++++++++++++++- 2 files changed, 325 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 9b0542b2f2239..c4d6ad9d9d622 100755 --- a/configure +++ b/configure @@ -2120,6 +2120,7 @@ HAVE_LIST=" $TYPES_LIST makeinfo makeinfo_html + opencl_d3d11 opencl_dxva2 opencl_vaapi_beignet opencl_vaapi_intel_media @@ -6172,6 +6173,11 @@ if enabled_all opencl dxva2 ; then enable opencl_dxva2 fi +if enabled_all opencl d3d11va ; then + check_type "CL/cl_d3d11.h" clGetDeviceIDsFromD3D11KHR_fn && + enable opencl_d3d11 +fi + enabled vdpau && check_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || disable vdpau diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index cbee32b94c465..08b3ea90f7641 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -51,6 +51,11 @@ #include "hwcontext_dxva2.h" #endif +#if HAVE_OPENCL_D3D11 +#include +#include "hwcontext_d3d11va.h" +#endif + typedef struct OpenCLDeviceContext { // Default command queue to use for transfer/mapping operations on @@ -89,6 +94,16 @@ typedef struct OpenCLDeviceContext { clEnqueueReleaseDX9MediaSurfacesKHR_fn clEnqueueReleaseDX9MediaSurfacesKHR; #endif + +#if HAVE_OPENCL_D3D11 + int d3d11_mapping_usable; + clCreateFromD3D11Texture2DKHR_fn + clCreateFromD3D11Texture2DKHR; + clEnqueueAcquireD3D11ObjectsKHR_fn + clEnqueueAcquireD3D11ObjectsKHR; + clEnqueueReleaseD3D11ObjectsKHR_fn + clEnqueueReleaseD3D11ObjectsKHR; +#endif } OpenCLDeviceContext; typedef struct OpenCLFramesContext { @@ -98,7 +113,7 @@ typedef struct OpenCLFramesContext { // device. cl_command_queue command_queue; -#if HAVE_OPENCL_DXVA2 +#if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11 // For mapping APIs which have separate creation and acquire/release // steps, this stores the OpenCL memory objects corresponding to each // frame. @@ -778,6 +793,39 @@ static int opencl_device_init(AVHWDeviceContext *hwdev) } #endif +#if HAVE_OPENCL_D3D11 + { + const char *d3d11_ext = "cl_khr_d3d11_sharing"; + const char *nv12_ext = "cl_intel_d3d11_nv12_media_sharing"; + int fail = 0; + + if (!opencl_check_extension(hwdev, d3d11_ext)) { + av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is " + "required for D3D11 to OpenCL mapping.\n", d3d11_ext); + fail = 1; + } else if (!opencl_check_extension(hwdev, nv12_ext)) { + av_log(hwdev, AV_LOG_VERBOSE, "The %s extension may be " + "required for D3D11 to OpenCL mapping.\n", nv12_ext); + // Not fatal. + } + + CL_FUNC(clCreateFromD3D11Texture2DKHR, + "D3D11 to OpenCL mapping"); + CL_FUNC(clEnqueueAcquireD3D11ObjectsKHR, + "D3D11 in OpenCL acquire"); + CL_FUNC(clEnqueueReleaseD3D11ObjectsKHR, + "D3D11 in OpenCL release"); + + if (fail) { + av_log(hwdev, AV_LOG_WARNING, "D3D11 to OpenCL mapping " + "not usable.\n"); + priv->d3d11_mapping_usable = 0; + } else { + priv->d3d11_mapping_usable = 1; + } + } +#endif + #undef CL_FUNC return 0; @@ -957,7 +1005,80 @@ static int opencl_enumerate_dxva2_devices(AVHWDeviceContext *hwdev, return 0; } +#endif + +#if HAVE_OPENCL_D3D11 +static int opencl_filter_d3d11_platform(AVHWDeviceContext *hwdev, + cl_platform_id platform_id, + const char *platform_name, + void *context) +{ + const char *d3d11_ext = "cl_khr_d3d11_sharing"; + + if (opencl_check_platform_extension(platform_id, d3d11_ext)) { + return 0; + } else { + av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not support the " + "%s extension.\n", platform_name, d3d11_ext); + return 1; + } +} + +static int opencl_enumerate_d3d11_devices(AVHWDeviceContext *hwdev, + cl_platform_id platform_id, + const char *platform_name, + cl_uint *nb_devices, + cl_device_id **devices, + void *context) +{ + ID3D11Device *device = context; + clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR; + cl_int cle; + + clGetDeviceIDsFromD3D11KHR = + clGetExtensionFunctionAddressForPlatform(platform_id, + "clGetDeviceIDsFromD3D11KHR"); + if (!clGetDeviceIDsFromD3D11KHR) { + av_log(hwdev, AV_LOG_ERROR, "Failed to get address of " + "clGetDeviceIDsFromD3D11KHR().\n"); + return AVERROR_UNKNOWN; + } + + cle = clGetDeviceIDsFromD3D11KHR(platform_id, + CL_D3D11_DEVICE_KHR, device, + CL_PREFERRED_DEVICES_FOR_D3D11_KHR, + 0, NULL, nb_devices); + if (cle == CL_DEVICE_NOT_FOUND) { + av_log(hwdev, AV_LOG_DEBUG, "No D3D11-supporting devices found " + "on platform \"%s\".\n", platform_name); + *nb_devices = 0; + return 0; + } else if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices " + "on platform \"%s\": %d.\n", platform_name, cle); + return AVERROR_UNKNOWN; + } + + *devices = av_malloc_array(*nb_devices, sizeof(**devices)); + if (!*devices) + return AVERROR(ENOMEM); + + cle = clGetDeviceIDsFromD3D11KHR(platform_id, + CL_D3D11_DEVICE_KHR, device, + CL_PREFERRED_DEVICES_FOR_D3D11_KHR, + *nb_devices, *devices, NULL); + if (cle != CL_SUCCESS) { + av_log(hwdev, AV_LOG_ERROR, "Failed to get list of D3D11-supporting " + "devices on platform \"%s\": %d.\n", platform_name, cle); + av_freep(devices); + return AVERROR_UNKNOWN; + } + + return 0; +} +#endif +#if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11 static int opencl_filter_gpu_device(AVHWDeviceContext *hwdev, cl_device_id device_id, const char *device_name, @@ -1103,6 +1224,32 @@ static int opencl_device_derive(AVHWDeviceContext *hwdev, break; #endif +#if HAVE_OPENCL_D3D11 + case AV_HWDEVICE_TYPE_D3D11VA: + { + AVD3D11VADeviceContext *src_hwctx = src_ctx->hwctx; + cl_context_properties props[5] = { + CL_CONTEXT_PLATFORM, + 0, + CL_CONTEXT_D3D11_DEVICE_KHR, + (intptr_t)src_hwctx->device, + 0, + }; + OpenCLDeviceSelector selector = { + .platform_index = -1, + .device_index = -1, + .context = src_hwctx->device, + .enumerate_platforms = &opencl_enumerate_platforms, + .filter_platform = &opencl_filter_d3d11_platform, + .enumerate_devices = &opencl_enumerate_d3d11_devices, + .filter_device = &opencl_filter_gpu_device, + }; + + err = opencl_device_create_internal(hwdev, &selector, props); + } + break; +#endif + default: err = AVERROR(ENOSYS); break; @@ -1461,7 +1608,7 @@ static void opencl_frames_uninit(AVHWFramesContext *hwfc) OpenCLFramesContext *priv = hwfc->internal->priv; cl_int cle; -#if HAVE_OPENCL_DXVA2 +#if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11 int i, p; for (i = 0; i < priv->nb_mapped_frames; i++) { AVOpenCLFrameDescriptor *desc = &priv->mapped_frames[i]; @@ -2258,6 +2405,159 @@ static int opencl_frames_derive_from_dxva2(AVHWFramesContext *dst_fc, #endif +#if HAVE_OPENCL_D3D11 + +static void opencl_unmap_from_d3d11(AVHWFramesContext *dst_fc, + HWMapDescriptor *hwmap) +{ + AVOpenCLFrameDescriptor *desc = hwmap->priv; + OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; + OpenCLFramesContext *frames_priv = dst_fc->device_ctx->internal->priv; + cl_event event; + cl_int cle; + + cle = device_priv->clEnqueueReleaseD3D11ObjectsKHR( + frames_priv->command_queue, desc->nb_planes, desc->planes, + 0, NULL, &event); + if (cle != CL_SUCCESS) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface " + "handle: %d.\n", cle); + } + + opencl_wait_events(dst_fc, &event, 1); +} + +static int opencl_map_from_d3d11(AVHWFramesContext *dst_fc, AVFrame *dst, + const AVFrame *src, int flags) +{ + OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; + OpenCLFramesContext *frames_priv = dst_fc->internal->priv; + AVOpenCLFrameDescriptor *desc; + cl_event event; + cl_int cle; + int err, index, i; + + index = (intptr_t)src->data[1]; + if (index >= frames_priv->nb_mapped_frames) { + av_log(dst_fc, AV_LOG_ERROR, "Texture array index out of range for " + "mapping: %d >= %d.\n", index, frames_priv->nb_mapped_frames); + return AVERROR(EINVAL); + } + + av_log(dst_fc, AV_LOG_DEBUG, "Map D3D11 texture %d to OpenCL.\n", + index); + + desc = &frames_priv->mapped_frames[index]; + + cle = device_priv->clEnqueueAcquireD3D11ObjectsKHR( + frames_priv->command_queue, desc->nb_planes, desc->planes, + 0, NULL, &event); + if (cle != CL_SUCCESS) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface " + "handle: %d.\n", cle); + return AVERROR(EIO); + } + + err = opencl_wait_events(dst_fc, &event, 1); + if (err < 0) + goto fail; + + for (i = 0; i < desc->nb_planes; i++) + dst->data[i] = (uint8_t*)desc->planes[i]; + + err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, + &opencl_unmap_from_d3d11, desc); + if (err < 0) + goto fail; + + dst->width = src->width; + dst->height = src->height; + + return 0; + +fail: + cle = device_priv->clEnqueueReleaseD3D11ObjectsKHR( + frames_priv->command_queue, desc->nb_planes, desc->planes, + 0, NULL, &event); + if (cle == CL_SUCCESS) + opencl_wait_events(dst_fc, &event, 1); + return err; +} + +static int opencl_frames_derive_from_d3d11(AVHWFramesContext *dst_fc, + AVHWFramesContext *src_fc, int flags) +{ + AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; + AVD3D11VAFramesContext *src_hwctx = src_fc->hwctx; + OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; + OpenCLFramesContext *frames_priv = dst_fc->internal->priv; + cl_mem_flags cl_flags; + cl_int cle; + int err, i, p, nb_planes; + + if (src_fc->sw_format != AV_PIX_FMT_NV12) { + av_log(dst_fc, AV_LOG_ERROR, "Only NV12 textures are supported " + "for D3D11 to OpenCL mapping.\n"); + return AVERROR(EINVAL); + } + nb_planes = 2; + + if (src_fc->initial_pool_size == 0) { + av_log(dst_fc, AV_LOG_ERROR, "Only fixed-size pools are supported " + "for D3D11 to OpenCL mapping.\n"); + return AVERROR(EINVAL); + } + + cl_flags = opencl_mem_flags_for_mapping(flags); + if (!cl_flags) + return AVERROR(EINVAL); + + frames_priv->nb_mapped_frames = src_fc->initial_pool_size; + + frames_priv->mapped_frames = + av_mallocz_array(frames_priv->nb_mapped_frames, + sizeof(*frames_priv->mapped_frames)); + if (!frames_priv->mapped_frames) + return AVERROR(ENOMEM); + + for (i = 0; i < frames_priv->nb_mapped_frames; i++) { + AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i]; + desc->nb_planes = nb_planes; + for (p = 0; p < nb_planes; p++) { + UINT subresource = 2 * i + p; + + desc->planes[p] = + device_priv->clCreateFromD3D11Texture2DKHR( + dst_dev->context, cl_flags, src_hwctx->texture, + subresource, &cle); + if (!desc->planes[p]) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL " + "image from plane %d of D3D texture " + "index %d (subresource %u): %d.\n", + p, i, (unsigned int)subresource, cle); + err = AVERROR(EIO); + goto fail; + } + } + } + + return 0; + +fail: + for (i = 0; i < frames_priv->nb_mapped_frames; i++) { + AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i]; + for (p = 0; p < desc->nb_planes; p++) { + if (desc->planes[p]) + clReleaseMemObject(desc->planes[p]); + } + } + av_freep(&frames_priv->mapped_frames); + frames_priv->nb_mapped_frames = 0; + return err; +} + +#endif + static int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { @@ -2288,6 +2588,11 @@ static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst, case AV_PIX_FMT_DXVA2_VLD: if (priv->dxva2_mapping_usable) return opencl_map_from_dxva2(hwfc, dst, src, flags); +#endif +#if HAVE_OPENCL_D3D11 + case AV_PIX_FMT_D3D11: + if (priv->d3d11_mapping_usable) + return opencl_map_from_d3d11(hwfc, dst, src, flags); #endif } return AVERROR(ENOSYS); @@ -2322,6 +2627,18 @@ static int opencl_frames_derive_to(AVHWFramesContext *dst_fc, return err; } break; +#endif +#if HAVE_OPENCL_D3D11 + case AV_HWDEVICE_TYPE_D3D11VA: + if (!priv->d3d11_mapping_usable) + return AVERROR(ENOSYS); + { + int err; + err = opencl_frames_derive_from_d3d11(dst_fc, src_fc, flags); + if (err < 0) + return err; + } + break; #endif default: return AVERROR(ENOSYS); From 7faae6e745a3b22f81d522ea19164d3b2b3aa2cc Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 10 Sep 2017 13:37:20 +0100 Subject: [PATCH 1061/2557] hwcontext_opencl: DRM to OpenCL mapping for ARM Using cl_arm_import_memory. Unfortunately, despite this not being a standard extension, the function clImportMemoryARM() is not accessible via clGetExtensionFunctionAddressForPlatform(). This means that it has to be linked directly to the ARM OpenCL binary, so making a portable binary is not possible as it is with all other mapping extensions. --- configure | 6 + libavutil/hwcontext_opencl.c | 263 +++++++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+) diff --git a/configure b/configure index c4d6ad9d9d622..e03d68aa92bdb 100755 --- a/configure +++ b/configure @@ -2121,6 +2121,7 @@ HAVE_LIST=" makeinfo makeinfo_html opencl_d3d11 + opencl_drm_arm opencl_dxva2 opencl_vaapi_beignet opencl_vaapi_intel_media @@ -6178,6 +6179,11 @@ if enabled_all opencl d3d11va ; then enable opencl_d3d11 fi +if enabled_all opencl libdrm ; then + check_func_headers "CL/cl_ext.h" clImportMemoryARM && + enable opencl_drm_arm +fi + enabled vdpau && check_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || disable vdpau diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index 08b3ea90f7641..8754d739390ed 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -56,6 +56,12 @@ #include "hwcontext_d3d11va.h" #endif +#if HAVE_OPENCL_DRM_ARM +#include +#include +#include "hwcontext_drm.h" +#endif + typedef struct OpenCLDeviceContext { // Default command queue to use for transfer/mapping operations on @@ -104,6 +110,10 @@ typedef struct OpenCLDeviceContext { clEnqueueReleaseD3D11ObjectsKHR_fn clEnqueueReleaseD3D11ObjectsKHR; #endif + +#if HAVE_OPENCL_DRM_ARM + int drm_arm_mapping_usable; +#endif } OpenCLDeviceContext; typedef struct OpenCLFramesContext { @@ -826,6 +836,37 @@ static int opencl_device_init(AVHWDeviceContext *hwdev) } #endif +#if HAVE_OPENCL_DRM_ARM + { + const char *drm_arm_ext = "cl_arm_import_memory"; + const char *image_ext = "cl_khr_image2d_from_buffer"; + int fail = 0; + + if (!opencl_check_extension(hwdev, drm_arm_ext)) { + av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is " + "required for DRM to OpenCL mapping on ARM.\n", + drm_arm_ext); + fail = 1; + } + if (!opencl_check_extension(hwdev, image_ext)) { + av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is " + "required for DRM to OpenCL mapping on ARM.\n", + image_ext); + fail = 1; + } + + // clImportMemoryARM() is linked statically. + + if (fail) { + av_log(hwdev, AV_LOG_WARNING, "DRM to OpenCL mapping on ARM " + "not usable.\n"); + priv->drm_arm_mapping_usable = 0; + } else { + priv->drm_arm_mapping_usable = 1; + } + } +#endif + #undef CL_FUNC return 0; @@ -1104,6 +1145,40 @@ static int opencl_filter_gpu_device(AVHWDeviceContext *hwdev, } #endif +#if HAVE_OPENCL_DRM_ARM +static int opencl_filter_drm_arm_platform(AVHWDeviceContext *hwdev, + cl_platform_id platform_id, + const char *platform_name, + void *context) +{ + const char *drm_arm_ext = "cl_arm_import_memory"; + + if (opencl_check_platform_extension(platform_id, drm_arm_ext)) { + return 0; + } else { + av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not support the " + "%s extension.\n", platform_name, drm_arm_ext); + return 1; + } +} + +static int opencl_filter_drm_arm_device(AVHWDeviceContext *hwdev, + cl_device_id device_id, + const char *device_name, + void *context) +{ + const char *drm_arm_ext = "cl_arm_import_memory"; + + if (opencl_check_device_extension(device_id, drm_arm_ext)) { + return 0; + } else { + av_log(hwdev, AV_LOG_DEBUG, "Device %s does not support the " + "%s extension.\n", device_name, drm_arm_ext); + return 1; + } +} +#endif + static int opencl_device_derive(AVHWDeviceContext *hwdev, AVHWDeviceContext *src_ctx, int flags) @@ -1250,6 +1325,24 @@ static int opencl_device_derive(AVHWDeviceContext *hwdev, break; #endif +#if HAVE_OPENCL_DRM_ARM + case AV_HWDEVICE_TYPE_DRM: + { + OpenCLDeviceSelector selector = { + .platform_index = -1, + .device_index = -1, + .context = NULL, + .enumerate_platforms = &opencl_enumerate_platforms, + .filter_platform = &opencl_filter_drm_arm_platform, + .enumerate_devices = &opencl_enumerate_devices, + .filter_device = &opencl_filter_drm_arm_device, + }; + + err = opencl_device_create_internal(hwdev, &selector, NULL); + } + break; +#endif + default: err = AVERROR(ENOSYS); break; @@ -2558,6 +2651,165 @@ static int opencl_frames_derive_from_d3d11(AVHWFramesContext *dst_fc, #endif +#if HAVE_OPENCL_DRM_ARM + +typedef struct DRMARMtoOpenCLMapping { + int nb_objects; + cl_mem object_buffers[AV_DRM_MAX_PLANES]; + int nb_planes; + cl_mem plane_images[AV_DRM_MAX_PLANES]; +} DRMARMtoOpenCLMapping; + +static void opencl_unmap_from_drm_arm(AVHWFramesContext *dst_fc, + HWMapDescriptor *hwmap) +{ + DRMARMtoOpenCLMapping *mapping = hwmap->priv; + int i; + + for (i = 0; i < mapping->nb_planes; i++) + clReleaseMemObject(mapping->plane_images[i]); + + for (i = 0; i < mapping->nb_objects; i++) + clReleaseMemObject(mapping->object_buffers[i]); + + av_free(mapping); +} + +static int opencl_map_from_drm_arm(AVHWFramesContext *dst_fc, AVFrame *dst, + const AVFrame *src, int flags) +{ + AVHWFramesContext *src_fc = + (AVHWFramesContext*)src->hw_frames_ctx->data; + AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; + const AVDRMFrameDescriptor *desc; + DRMARMtoOpenCLMapping *mapping = NULL; + cl_mem_flags cl_flags; + const cl_import_properties_arm props[3] = { + CL_IMPORT_TYPE_ARM, CL_IMPORT_TYPE_DMA_BUF_ARM, 0, + }; + cl_int cle; + int err, i, j; + + desc = (const AVDRMFrameDescriptor*)src->data[0]; + + cl_flags = opencl_mem_flags_for_mapping(flags); + if (!cl_flags) + return AVERROR(EINVAL); + + mapping = av_mallocz(sizeof(*mapping)); + if (!mapping) + return AVERROR(ENOMEM); + + mapping->nb_objects = desc->nb_objects; + for (i = 0; i < desc->nb_objects; i++) { + int fd = desc->objects[i].fd; + + av_log(dst_fc, AV_LOG_DEBUG, "Map DRM PRIME fd %d to OpenCL.\n", fd); + + if (desc->objects[i].format_modifier) { + av_log(dst_fc, AV_LOG_DEBUG, "Warning: object %d fd %d has " + "nonzero format modifier %"PRId64", result may not " + "be as expected.\n", i, fd, + desc->objects[i].format_modifier); + } + + mapping->object_buffers[i] = + clImportMemoryARM(dst_dev->context, cl_flags, props, + &fd, desc->objects[i].size, &cle); + if (!mapping->object_buffers[i]) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL buffer " + "from object %d (fd %d, size %zu) of DRM frame: %d.\n", + i, fd, desc->objects[i].size, cle); + err = AVERROR(EIO); + goto fail; + } + } + + mapping->nb_planes = 0; + for (i = 0; i < desc->nb_layers; i++) { + const AVDRMLayerDescriptor *layer = &desc->layers[i]; + + for (j = 0; j < layer->nb_planes; j++) { + const AVDRMPlaneDescriptor *plane = &layer->planes[j]; + cl_mem plane_buffer; + cl_image_format image_format; + cl_image_desc image_desc; + cl_buffer_region region; + int p = mapping->nb_planes; + + err = opencl_get_plane_format(src_fc->sw_format, p, + src_fc->width, src_fc->height, + &image_format, &image_desc); + if (err < 0) { + av_log(dst_fc, AV_LOG_ERROR, "Invalid plane %d (DRM " + "layer %d plane %d): %d.\n", p, i, j, err); + goto fail; + } + + region.origin = plane->offset; + region.size = image_desc.image_row_pitch * + image_desc.image_height; + + plane_buffer = + clCreateSubBuffer(mapping->object_buffers[plane->object_index], + cl_flags, + CL_BUFFER_CREATE_TYPE_REGION, + ®ion, &cle); + if (!plane_buffer) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to create sub-buffer " + "for plane %d: %d.\n", p, cle); + err = AVERROR(EIO); + goto fail; + } + + image_desc.buffer = plane_buffer; + + mapping->plane_images[p] = + clCreateImage(dst_dev->context, cl_flags, + &image_format, &image_desc, NULL, &cle); + + // Unreference the sub-buffer immediately - we don't need it + // directly and a reference is held by the image. + clReleaseMemObject(plane_buffer); + + if (!mapping->plane_images[p]) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to create image " + "for plane %d: %d.\n", p, cle); + err = AVERROR(EIO); + goto fail; + } + + ++mapping->nb_planes; + } + } + + for (i = 0; i < mapping->nb_planes; i++) + dst->data[i] = (uint8_t*)mapping->plane_images[i]; + + err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, + &opencl_unmap_from_drm_arm, mapping); + if (err < 0) + goto fail; + + dst->width = src->width; + dst->height = src->height; + + return 0; + +fail: + for (i = 0; i < mapping->nb_planes; i++) { + clReleaseMemObject(mapping->plane_images[i]); + } + for (i = 0; i < mapping->nb_objects; i++) { + if (mapping->object_buffers[i]) + clReleaseMemObject(mapping->object_buffers[i]); + } + av_free(mapping); + return err; +} + +#endif + static int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { @@ -2593,6 +2845,11 @@ static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst, case AV_PIX_FMT_D3D11: if (priv->d3d11_mapping_usable) return opencl_map_from_d3d11(hwfc, dst, src, flags); +#endif +#if HAVE_OPENCL_DRM_ARM + case AV_PIX_FMT_DRM_PRIME: + if (priv->drm_arm_mapping_usable) + return opencl_map_from_drm_arm(hwfc, dst, src, flags); #endif } return AVERROR(ENOSYS); @@ -2639,6 +2896,12 @@ static int opencl_frames_derive_to(AVHWFramesContext *dst_fc, return err; } break; +#endif +#if HAVE_OPENCL_DRM_ARM + case AV_HWDEVICE_TYPE_DRM: + if (!priv->drm_arm_mapping_usable) + return AVERROR(ENOSYS); + break; #endif default: return AVERROR(ENOSYS); From 5c21c41b7da2bac069b09d5a30da6a53f72dbe96 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 27 Jun 2017 22:50:49 +0100 Subject: [PATCH 1062/2557] lavfi: Add some common code for OpenCL filtering --- libavfilter/opencl.c | 251 +++++++++++++++++++++++++++++++++++++++++++ libavfilter/opencl.h | 87 +++++++++++++++ 2 files changed, 338 insertions(+) create mode 100644 libavfilter/opencl.c create mode 100644 libavfilter/opencl.h diff --git a/libavfilter/opencl.c b/libavfilter/opencl.c new file mode 100644 index 0000000000000..005ad089e2137 --- /dev/null +++ b/libavfilter/opencl.c @@ -0,0 +1,251 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_opencl.h" +#include "libavutil/mem.h" + +#include "avfilter.h" +#include "formats.h" +#include "opencl.h" + +int ff_opencl_filter_query_formats(AVFilterContext *avctx) +{ + const static enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_OPENCL, + AV_PIX_FMT_NONE, + }; + AVFilterFormats *formats; + + formats = ff_make_format_list(pix_fmts); + if (!formats) + return AVERROR(ENOMEM); + + return ff_set_common_formats(avctx, formats); +} + +int ff_opencl_filter_config_input(AVFilterLink *inlink) +{ + AVFilterContext *avctx = inlink->dst; + OpenCLFilterContext *ctx = avctx->priv; + AVHWFramesContext *input_frames; + + if (!inlink->hw_frames_ctx) { + av_log(avctx, AV_LOG_ERROR, "OpenCL filtering requires a " + "hardware frames context on the input.\n"); + return AVERROR(EINVAL); + } + + // Extract the device and default output format from the first input. + if (avctx->inputs[0] != inlink) + return 0; + + input_frames = (AVHWFramesContext*)inlink->hw_frames_ctx->data; + + if (input_frames->format != AV_PIX_FMT_OPENCL) + return AVERROR(EINVAL); + + ctx->device_ref = av_buffer_ref(input_frames->device_ref); + if (!ctx->device_ref) + return AVERROR(ENOMEM); + ctx->device = input_frames->device_ctx; + ctx->hwctx = ctx->device->hwctx; + + // Default output parameters match input parameters. + if (ctx->output_format == AV_PIX_FMT_NONE) + ctx->output_format = input_frames->sw_format; + if (!ctx->output_width) + ctx->output_width = inlink->w; + if (!ctx->output_height) + ctx->output_height = inlink->h; + + return 0; +} + +int ff_opencl_filter_config_output(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + OpenCLFilterContext *ctx = avctx->priv; + AVBufferRef *output_frames_ref = NULL; + AVHWFramesContext *output_frames; + int err; + + av_buffer_unref(&outlink->hw_frames_ctx); + + output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref); + if (!output_frames_ref) { + err = AVERROR(ENOMEM); + goto fail; + } + output_frames = (AVHWFramesContext*)output_frames_ref->data; + + output_frames->format = AV_PIX_FMT_OPENCL; + output_frames->sw_format = ctx->output_format; + output_frames->width = ctx->output_width; + output_frames->height = ctx->output_height; + + err = av_hwframe_ctx_init(output_frames_ref); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to initialise output " + "frames: %d.\n", err); + goto fail; + } + + outlink->hw_frames_ctx = output_frames_ref; + outlink->w = ctx->output_width; + outlink->h = ctx->output_height; + + return 0; +fail: + av_buffer_unref(&output_frames_ref); + return err; +} + +int ff_opencl_filter_init(AVFilterContext *avctx) +{ + OpenCLFilterContext *ctx = avctx->priv; + + ctx->output_format = AV_PIX_FMT_NONE; + + return 0; +} + +void ff_opencl_filter_uninit(AVFilterContext *avctx) +{ + OpenCLFilterContext *ctx = avctx->priv; + cl_int cle; + + if (ctx->program) { + cle = clReleaseProgram(ctx->program); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "program: %d.\n", cle); + } + + av_buffer_unref(&ctx->device_ref); +} + +int ff_opencl_filter_load_program(AVFilterContext *avctx, + const char **program_source_array, + int nb_strings) +{ + OpenCLFilterContext *ctx = avctx->priv; + cl_int cle; + + ctx->program = clCreateProgramWithSource(ctx->hwctx->context, nb_strings, + program_source_array, + NULL, &cle); + if (!ctx->program) { + av_log(avctx, AV_LOG_ERROR, "Failed to create program: %d.\n", cle); + return AVERROR(EIO); + } + + cle = clBuildProgram(ctx->program, 1, &ctx->hwctx->device_id, + NULL, NULL, NULL); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to build program: %d.\n", cle); + + if (cle == CL_BUILD_PROGRAM_FAILURE) { + char *log; + size_t log_length; + + clGetProgramBuildInfo(ctx->program, ctx->hwctx->device_id, + CL_PROGRAM_BUILD_LOG, 0, NULL, &log_length); + + log = av_malloc(log_length); + if (log) { + cle = clGetProgramBuildInfo(ctx->program, + ctx->hwctx->device_id, + CL_PROGRAM_BUILD_LOG, + log_length, log, NULL); + if (cle == CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Build log:\n%s\n", log); + } + + av_free(log); + } + + clReleaseProgram(ctx->program); + ctx->program = NULL; + return AVERROR(EIO); + } + + return 0; +} + +int ff_opencl_filter_load_program_from_file(AVFilterContext *avctx, + const char *filename) +{ + FILE *file; + char *src = NULL; + size_t pos, len, rb; + const char *src_const; + int err; + + file = fopen(filename, "r"); + if (!file) { + av_log(avctx, AV_LOG_ERROR, "Unable to open program " + "source file \"%s\".\n", filename); + return AVERROR(ENOENT); + } + + len = 1 << 16; + pos = 0; + + err = av_reallocp(&src, len); + if (err < 0) + goto fail; + + err = snprintf(src, len, "#line 1 \"%s\"\n", filename); + if (err < 0) { + err = AVERROR(errno); + goto fail; + } + if (err > len / 2) { + err = AVERROR(EINVAL); + goto fail; + } + pos = err; + + while (1) { + rb = fread(src + pos, 1, len - pos - 1, file); + if (rb == 0 && ferror(file)) { + err = AVERROR(EIO); + goto fail; + } + pos += rb; + if (pos < len) + break; + len <<= 1; + err = av_reallocp(&src, len); + if (err < 0) + goto fail; + } + src[pos] = 0; + + src_const = src; + + err = ff_opencl_filter_load_program(avctx, &src_const, 1); +fail: + fclose(file); + av_freep(&src); + return err; +} diff --git a/libavfilter/opencl.h b/libavfilter/opencl.h new file mode 100644 index 0000000000000..4d740c18abaec --- /dev/null +++ b/libavfilter/opencl.h @@ -0,0 +1,87 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_OPENCL_H +#define AVFILTER_OPENCL_H + +#include "libavutil/buffer.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_opencl.h" +#include "libavutil/pixfmt.h" + +#include "avfilter.h" + +typedef struct OpenCLFilterContext { + const AVClass *class; + + AVBufferRef *device_ref; + AVHWDeviceContext *device; + AVOpenCLDeviceContext *hwctx; + + cl_program program; + + enum AVPixelFormat output_format; + int output_width; + int output_height; +} OpenCLFilterContext; + +/** + * Return that all inputs and outputs support only AV_PIX_FMT_OPENCL. + */ +int ff_opencl_filter_query_formats(AVFilterContext *avctx); + +/** + * Check that the input link contains a suitable hardware frames + * context and extract the device from it. + */ +int ff_opencl_filter_config_input(AVFilterLink *inlink); + +/** + * Create a suitable hardware frames context for the output. + */ +int ff_opencl_filter_config_output(AVFilterLink *outlink); + +/** + * Initialise an OpenCL filter context. + */ +int ff_opencl_filter_init(AVFilterContext *avctx); + +/** + * Uninitialise an OpenCL filter context. + */ +void ff_opencl_filter_uninit(AVFilterContext *avctx); + +/** + * Load a new OpenCL program from strings in memory. + * + * Creates a new program and compiles it for the current device. + * Will log any build errors if compilation fails. + */ +int ff_opencl_filter_load_program(AVFilterContext *avctx, + const char **program_source_array, + int nb_strings); + +/** + * Load a new OpenCL program from a file. + * + * Same as ff_opencl_filter_load_program(), but from a file. + */ +int ff_opencl_filter_load_program_from_file(AVFilterContext *avctx, + const char *filename); + +#endif /* AVFILTER_OPENCL_H */ From 59d6529333c4550701401d59d67b60454b164b1f Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 10 Sep 2017 21:53:35 +0100 Subject: [PATCH 1063/2557] lavfi: Add infrastructure for building OpenCL source into libavfilter --- libavfilter/Makefile | 6 ++++++ libavfilter/opencl_source.h | 22 ++++++++++++++++++++++ tools/cl2c | 20 ++++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 libavfilter/opencl_source.h create mode 100755 tools/cl2c diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 71c6333a52f73..545ef62e1aa26 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -405,3 +405,9 @@ TOOLS-$(CONFIG_LIBZMQ) += zmqsend clean:: $(RM) $(CLEANSUFFIXES:%=libavfilter/libmpcodecs/%) + +OPENCL = $(subst $(SRC_PATH)/,,$(wildcard $(SRC_PATH)/libavfilter/opencl/*.cl)) +.SECONDARY: $(OPENCL:.cl=.c) +libavfilter/opencl/%.c: TAG = OPENCL +libavfilter/opencl/%.c: $(SRC_PATH)/libavfilter/opencl/%.cl + $(M)$(SRC_PATH)/tools/cl2c $< $@ diff --git a/libavfilter/opencl_source.h b/libavfilter/opencl_source.h new file mode 100644 index 0000000000000..8674a03a94b99 --- /dev/null +++ b/libavfilter/opencl_source.h @@ -0,0 +1,22 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_OPENCL_SOURCE_H +#define AVFILTER_OPENCL_SOURCE_H + +#endif /* AVFILTER_OPENCL_SOURCE_H */ diff --git a/tools/cl2c b/tools/cl2c new file mode 100755 index 0000000000000..1ead940811c8e --- /dev/null +++ b/tools/cl2c @@ -0,0 +1,20 @@ +#!/bin/sh +# Convert an OpenCL source file into a C source file containing the +# OpenCL source as a C string. Also adds a #line directive so that +# compiler messages are useful. + +input="$1" +output="$2" + +name=$(basename "$input" | sed 's/.cl$//') + +cat >$output <>$output + +echo ";" >>$output From 9204b2deea85c834ba3d5fa2b0e92b86c24f45ae Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 10 Sep 2017 21:53:36 +0100 Subject: [PATCH 1064/2557] lavfi: Add OpenCL overlay filter Input and output formats must be the same, the overlay format must be the same as the input except possibly with an additional alpha component. --- Changelog | 1 + configure | 1 + libavfilter/Makefile | 2 + libavfilter/allfilters.c | 1 + libavfilter/opencl/overlay.cl | 104 +++++++++ libavfilter/opencl_source.h | 2 + libavfilter/version.h | 2 +- libavfilter/vf_overlay_opencl.c | 360 ++++++++++++++++++++++++++++++++ 8 files changed, 472 insertions(+), 1 deletion(-) create mode 100644 libavfilter/opencl/overlay.cl create mode 100644 libavfilter/vf_overlay_opencl.c diff --git a/Changelog b/Changelog index 74ed35cfe6ba8..f6b70c4a34919 100644 --- a/Changelog +++ b/Changelog @@ -17,6 +17,7 @@ version : - Intel QSV-accelerated overlay filter - mcompand audio filter - acontrast audio filter +- OpenCL overlay filter version 3.4: diff --git a/configure b/configure index e03d68aa92bdb..e8c605bb976e9 100755 --- a/configure +++ b/configure @@ -3239,6 +3239,7 @@ negate_filter_deps="lut_filter" nnedi_filter_deps="gpl" ocr_filter_deps="libtesseract" ocv_filter_deps="libopencv" +overlay_opencl_filter_deps="opencl" overlay_qsv_filter_deps="libmfx" overlay_qsv_filter_select="qsvvpp" owdenoise_filter_deps="gpl" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 545ef62e1aa26..77cc3acfcd68d 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -253,6 +253,8 @@ OBJS-$(CONFIG_OCV_FILTER) += vf_libopencv.o OBJS-$(CONFIG_OPENCL) += deshake_opencl.o unsharp_opencl.o OBJS-$(CONFIG_OSCILLOSCOPE_FILTER) += vf_datascope.o OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o framesync.o +OBJS-$(CONFIG_OVERLAY_OPENCL_FILTER) += vf_overlay_opencl.o opencl.o \ + opencl/overlay.o framesync.o OBJS-$(CONFIG_OVERLAY_QSV_FILTER) += vf_overlay_qsv.o OBJS-$(CONFIG_OWDENOISE_FILTER) += vf_owdenoise.o OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 6d92b3ab5a7d7..0db440d128198 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -262,6 +262,7 @@ static void register_all(void) REGISTER_FILTER(OCV, ocv, vf); REGISTER_FILTER(OSCILLOSCOPE, oscilloscope, vf); REGISTER_FILTER(OVERLAY, overlay, vf); + REGISTER_FILTER(OVERLAY_OPENCL, overlay_opencl, vf); REGISTER_FILTER(OVERLAY_QSV, overlay_qsv, vf); REGISTER_FILTER(OWDENOISE, owdenoise, vf); REGISTER_FILTER(PAD, pad, vf); diff --git a/libavfilter/opencl/overlay.cl b/libavfilter/opencl/overlay.cl new file mode 100644 index 0000000000000..8c783d0edceef --- /dev/null +++ b/libavfilter/opencl/overlay.cl @@ -0,0 +1,104 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +__kernel void overlay_no_alpha(__write_only image2d_t dst, + __read_only image2d_t main, + __read_only image2d_t overlay, + int x_position, + int y_position) +{ + const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_NEAREST); + + int2 overlay_size = get_image_dim(overlay); + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + + if (loc.x < x_position || + loc.y < y_position || + loc.x >= overlay_size.x + x_position || + loc.y >= overlay_size.y + y_position) { + float4 val = read_imagef(main, sampler, loc); + write_imagef(dst, loc, val); + } else { + int2 loc_overlay = (int2)(x_position, y_position); + float4 val = read_imagef(overlay, sampler, loc - loc_overlay); + write_imagef(dst, loc, val); + } +} + +__kernel void overlay_internal_alpha(__write_only image2d_t dst, + __read_only image2d_t main, + __read_only image2d_t overlay, + int x_position, + int y_position) +{ + const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_NEAREST); + + int2 overlay_size = get_image_dim(overlay); + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + + if (loc.x < x_position || + loc.y < y_position || + loc.x >= overlay_size.x + x_position || + loc.y >= overlay_size.y + y_position) { + float4 val = read_imagef(main, sampler, loc); + write_imagef(dst, loc, val); + } else { + int2 loc_overlay = (int2)(x_position, y_position); + float4 in_main = read_imagef(main, sampler, loc); + float4 in_overlay = read_imagef(overlay, sampler, loc - loc_overlay); + float4 val = in_overlay * in_overlay.w + in_main * (1.0f - in_overlay.w); + write_imagef(dst, loc, val); + } +} + +__kernel void overlay_external_alpha(__write_only image2d_t dst, + __read_only image2d_t main, + __read_only image2d_t overlay, + __read_only image2d_t alpha, + int x_position, + int y_position, + int alpha_adj_x, + int alpha_adj_y) +{ + const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_NEAREST); + + int2 overlay_size = get_image_dim(overlay); + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + + if (loc.x < x_position || + loc.y < y_position || + loc.x >= overlay_size.x + x_position || + loc.y >= overlay_size.y + y_position) { + float4 val = read_imagef(main, sampler, loc); + write_imagef(dst, loc, val); + } else { + int2 loc_overlay = (int2)(x_position, y_position); + float4 in_main = read_imagef(main, sampler, loc); + float4 in_overlay = read_imagef(overlay, sampler, loc - loc_overlay); + + int2 loc_alpha = (int2)(loc.x * alpha_adj_x, + loc.y * alpha_adj_y) - loc_overlay; + float4 in_alpha = read_imagef(alpha, sampler, loc_alpha); + + float4 val = in_overlay * in_alpha.x + in_main * (1.0f - in_alpha.x); + write_imagef(dst, loc, val); + } +} diff --git a/libavfilter/opencl_source.h b/libavfilter/opencl_source.h index 8674a03a94b99..e7af58bcfa84c 100644 --- a/libavfilter/opencl_source.h +++ b/libavfilter/opencl_source.h @@ -19,4 +19,6 @@ #ifndef AVFILTER_OPENCL_SOURCE_H #define AVFILTER_OPENCL_SOURCE_H +extern const char *ff_opencl_source_overlay; + #endif /* AVFILTER_OPENCL_SOURCE_H */ diff --git a/libavfilter/version.h b/libavfilter/version.h index d8484e42637c7..25087957eba9a 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #define LIBAVFILTER_VERSION_MAJOR 7 #define LIBAVFILTER_VERSION_MINOR 2 -#define LIBAVFILTER_VERSION_MICRO 100 +#define LIBAVFILTER_VERSION_MICRO 101 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ diff --git a/libavfilter/vf_overlay_opencl.c b/libavfilter/vf_overlay_opencl.c new file mode 100644 index 0000000000000..46ce42df847b3 --- /dev/null +++ b/libavfilter/vf_overlay_opencl.c @@ -0,0 +1,360 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/buffer.h" +#include "libavutil/common.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_opencl.h" +#include "libavutil/log.h" +#include "libavutil/mathematics.h" +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" + +#include "avfilter.h" +#include "framesync.h" +#include "internal.h" +#include "opencl.h" +#include "opencl_source.h" +#include "video.h" + +typedef struct OverlayOpenCLContext { + OpenCLFilterContext ocf; + + int initialised; + cl_kernel kernel; + cl_command_queue command_queue; + + FFFrameSync fs; + + int nb_planes; + int x_subsample; + int y_subsample; + int alpha_separate; + + int x_position; + int y_position; +} OverlayOpenCLContext; + +static int overlay_opencl_load(AVFilterContext *avctx, + enum AVPixelFormat main_format, + enum AVPixelFormat overlay_format) +{ + OverlayOpenCLContext *ctx = avctx->priv; + cl_int cle; + const char *source = ff_opencl_source_overlay; + const char *kernel; + const AVPixFmtDescriptor *main_desc, *overlay_desc; + int err, i, main_planes, overlay_planes; + + main_desc = av_pix_fmt_desc_get(main_format); + overlay_desc = av_pix_fmt_desc_get(overlay_format); + + main_planes = overlay_planes = 0; + for (i = 0; i < main_desc->nb_components; i++) + main_planes = FFMAX(main_planes, + main_desc->comp[i].plane + 1); + for (i = 0; i < overlay_desc->nb_components; i++) + overlay_planes = FFMAX(overlay_planes, + overlay_desc->comp[i].plane + 1); + + ctx->nb_planes = main_planes; + ctx->x_subsample = 1 << main_desc->log2_chroma_w; + ctx->y_subsample = 1 << main_desc->log2_chroma_h; + + if (ctx->x_position % ctx->x_subsample || + ctx->y_position % ctx->y_subsample) { + av_log(avctx, AV_LOG_WARNING, "Warning: overlay position (%d, %d) " + "does not match subsampling (%d, %d).\n", + ctx->x_position, ctx->y_position, + ctx->x_subsample, ctx->y_subsample); + } + + if (main_planes == overlay_planes) { + if (main_desc->nb_components == overlay_desc->nb_components) + kernel = "overlay_no_alpha"; + else + kernel = "overlay_internal_alpha"; + ctx->alpha_separate = 0; + } else { + kernel = "overlay_external_alpha"; + ctx->alpha_separate = 1; + } + + av_log(avctx, AV_LOG_DEBUG, "Using kernel %s.\n", kernel); + + err = ff_opencl_filter_load_program(avctx, &source, 1); + if (err < 0) + goto fail; + + ctx->command_queue = clCreateCommandQueue(ctx->ocf.hwctx->context, + ctx->ocf.hwctx->device_id, + 0, &cle); + if (!ctx->command_queue) { + av_log(avctx, AV_LOG_ERROR, "Failed to create OpenCL " + "command queue: %d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + + ctx->kernel = clCreateKernel(ctx->ocf.program, kernel, &cle); + if (!ctx->kernel) { + av_log(avctx, AV_LOG_ERROR, "Failed to create kernel: %d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + + ctx->initialised = 1; + return 0; + +fail: + if (ctx->command_queue) + clReleaseCommandQueue(ctx->command_queue); + if (ctx->kernel) + clReleaseKernel(ctx->kernel); + return err; +} + +static int overlay_opencl_blend(FFFrameSync *fs) +{ + AVFilterContext *avctx = fs->parent; + AVFilterLink *outlink = avctx->outputs[0]; + OverlayOpenCLContext *ctx = avctx->priv; + AVFrame *input_main, *input_overlay; + AVFrame *output; + cl_mem mem; + cl_int cle, x, y; + size_t global_work[2]; + int kernel_arg = 0; + int err, plane; + + err = ff_framesync_get_frame(fs, 0, &input_main, 0); + if (err < 0) + return err; + err = ff_framesync_get_frame(fs, 1, &input_overlay, 0); + if (err < 0) + return err; + + if (!ctx->initialised) { + AVHWFramesContext *main_fc = + (AVHWFramesContext*)input_main->hw_frames_ctx->data; + AVHWFramesContext *overlay_fc = + (AVHWFramesContext*)input_overlay->hw_frames_ctx->data; + + err = overlay_opencl_load(avctx, main_fc->sw_format, + overlay_fc->sw_format); + if (err < 0) + return err; + } + + output = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!output) { + err = AVERROR(ENOMEM); + goto fail; + } + + for (plane = 0; plane < ctx->nb_planes; plane++) { + kernel_arg = 0; + + mem = (cl_mem)output->data[plane]; + cle = clSetKernelArg(ctx->kernel, kernel_arg++, sizeof(cl_mem), &mem); + if (cle != CL_SUCCESS) + goto fail_kernel_arg; + + mem = (cl_mem)input_main->data[plane]; + cle = clSetKernelArg(ctx->kernel, kernel_arg++, sizeof(cl_mem), &mem); + if (cle != CL_SUCCESS) + goto fail_kernel_arg; + + mem = (cl_mem)input_overlay->data[plane]; + cle = clSetKernelArg(ctx->kernel, kernel_arg++, sizeof(cl_mem), &mem); + if (cle != CL_SUCCESS) + goto fail_kernel_arg; + + if (ctx->alpha_separate) { + mem = (cl_mem)input_overlay->data[ctx->nb_planes]; + cle = clSetKernelArg(ctx->kernel, kernel_arg++, sizeof(cl_mem), &mem); + if (cle != CL_SUCCESS) + goto fail_kernel_arg; + } + + x = ctx->x_position / (plane == 0 ? 1 : ctx->x_subsample); + y = ctx->y_position / (plane == 0 ? 1 : ctx->y_subsample); + + cle = clSetKernelArg(ctx->kernel, kernel_arg++, sizeof(cl_int), &x); + if (cle != CL_SUCCESS) + goto fail_kernel_arg; + cle = clSetKernelArg(ctx->kernel, kernel_arg++, sizeof(cl_int), &y); + if (cle != CL_SUCCESS) + goto fail_kernel_arg; + + if (ctx->alpha_separate) { + cl_int alpha_adj_x = plane == 0 ? 1 : ctx->x_subsample; + cl_int alpha_adj_y = plane == 0 ? 1 : ctx->y_subsample; + + cle = clSetKernelArg(ctx->kernel, kernel_arg++, sizeof(cl_int), &alpha_adj_x); + if (cle != CL_SUCCESS) + goto fail_kernel_arg; + cle = clSetKernelArg(ctx->kernel, kernel_arg++, sizeof(cl_int), &alpha_adj_y); + if (cle != CL_SUCCESS) + goto fail_kernel_arg; + } + + global_work[0] = output->width; + global_work[1] = output->height; + + cle = clEnqueueNDRangeKernel(ctx->command_queue, ctx->kernel, 2, NULL, + global_work, NULL, 0, NULL, NULL); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to enqueue " + "overlay kernel for plane %d: %d.\n", cle, plane); + err = AVERROR(EIO); + goto fail; + } + } + + cle = clFinish(ctx->command_queue); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to finish " + "command queue: %d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + + err = av_frame_copy_props(output, input_main); + + av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(output->format), + output->width, output->height, output->pts); + + return ff_filter_frame(outlink, output); + +fail_kernel_arg: + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel arg %d: %d.\n", + kernel_arg, cle); + err = AVERROR(EIO); +fail: + return err; +} + +static int overlay_opencl_config_output(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + OverlayOpenCLContext *ctx = avctx->priv; + int err; + + err = ff_opencl_filter_config_output(outlink); + if (err < 0) + return err; + + err = ff_framesync_init_dualinput(&ctx->fs, avctx); + if (err < 0) + return err; + + return ff_framesync_configure(&ctx->fs); +} + +static av_cold int overlay_opencl_init(AVFilterContext *avctx) +{ + OverlayOpenCLContext *ctx = avctx->priv; + + ctx->fs.on_event = &overlay_opencl_blend; + + return ff_opencl_filter_init(avctx); +} + +static int overlay_opencl_activate(AVFilterContext *avctx) +{ + OverlayOpenCLContext *ctx = avctx->priv; + + return ff_framesync_activate(&ctx->fs); +} + +static av_cold void overlay_opencl_uninit(AVFilterContext *avctx) +{ + OverlayOpenCLContext *ctx = avctx->priv; + cl_int cle; + + if (ctx->kernel) { + cle = clReleaseKernel(ctx->kernel); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "kernel: %d.\n", cle); + } + + if (ctx->command_queue) { + cle = clReleaseCommandQueue(ctx->command_queue); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "command queue: %d.\n", cle); + } + + ff_opencl_filter_uninit(avctx); + + ff_framesync_uninit(&ctx->fs); +} + +#define OFFSET(x) offsetof(OverlayOpenCLContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption overlay_opencl_options[] = { + { "x", "Overlay x position", + OFFSET(x_position), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, + { "y", "Overlay y position", + OFFSET(y_position), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(overlay_opencl); + +static const AVFilterPad overlay_opencl_inputs[] = { + { + .name = "main", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_opencl_filter_config_input, + }, + { + .name = "overlay", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_opencl_filter_config_input, + }, + { NULL } +}; + +static const AVFilterPad overlay_opencl_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &overlay_opencl_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_overlay_opencl = { + .name = "overlay_opencl", + .description = NULL_IF_CONFIG_SMALL("Overlay one video on top of another"), + .priv_size = sizeof(OverlayOpenCLContext), + .priv_class = &overlay_opencl_class, + .init = &overlay_opencl_init, + .uninit = &overlay_opencl_uninit, + .query_formats = &ff_opencl_filter_query_formats, + .activate = &overlay_opencl_activate, + .inputs = overlay_opencl_inputs, + .outputs = overlay_opencl_outputs, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From 7faa8d8b03832e9f1c67029c859db5af82897a48 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 14 Nov 2017 19:47:27 +0000 Subject: [PATCH 1065/2557] lavfi: Add OpenCL unsharp mask filter Intended to replace existing opencl mode of the unsharp filter. Supports many more pixel formats and works without immediate upload and download of frame data. The options are compatible with the existing filter. --- configure | 1 + libavfilter/Makefile | 2 + libavfilter/allfilters.c | 1 + libavfilter/opencl/unsharp.cl | 99 +++++++ libavfilter/opencl_source.h | 1 + libavfilter/version.h | 2 +- libavfilter/vf_unsharp_opencl.c | 482 ++++++++++++++++++++++++++++++++ 7 files changed, 587 insertions(+), 1 deletion(-) create mode 100644 libavfilter/opencl/unsharp.cl create mode 100644 libavfilter/vf_unsharp_opencl.c diff --git a/configure b/configure index e8c605bb976e9..c4de469664aee 100755 --- a/configure +++ b/configure @@ -3283,6 +3283,7 @@ tinterlace_filter_deps="gpl" tinterlace_merge_test_deps="tinterlace_filter" tinterlace_pad_test_deps="tinterlace_filter" tonemap_filter_deps="const_nan" +unsharp_opencl_filter_deps="opencl" uspp_filter_deps="gpl avcodec" unsharp_filter_suggest="opencl" vaguedenoiser_filter_deps="gpl" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 77cc3acfcd68d..30474ea77b240 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -331,6 +331,8 @@ OBJS-$(CONFIG_TRANSPOSE_FILTER) += vf_transpose.o OBJS-$(CONFIG_TRIM_FILTER) += trim.o OBJS-$(CONFIG_UNPREMULTIPLY_FILTER) += vf_premultiply.o framesync.o OBJS-$(CONFIG_UNSHARP_FILTER) += vf_unsharp.o +OBJS-$(CONFIG_UNSHARP_OPENCL_FILTER) += vf_unsharp_opencl.o opencl.o \ + opencl/unsharp.o OBJS-$(CONFIG_USPP_FILTER) += vf_uspp.o OBJS-$(CONFIG_VAGUEDENOISER_FILTER) += vf_vaguedenoiser.o OBJS-$(CONFIG_VECTORSCOPE_FILTER) += vf_vectorscope.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 0db440d128198..beacfce612d8a 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -339,6 +339,7 @@ static void register_all(void) REGISTER_FILTER(TRIM, trim, vf); REGISTER_FILTER(UNPREMULTIPLY, unpremultiply, vf); REGISTER_FILTER(UNSHARP, unsharp, vf); + REGISTER_FILTER(UNSHARP_OPENCL, unsharp_opencl, vf); REGISTER_FILTER(USPP, uspp, vf); REGISTER_FILTER(VAGUEDENOISER, vaguedenoiser, vf); REGISTER_FILTER(VECTORSCOPE, vectorscope, vf); diff --git a/libavfilter/opencl/unsharp.cl b/libavfilter/opencl/unsharp.cl new file mode 100644 index 0000000000000..e629834e50635 --- /dev/null +++ b/libavfilter/opencl/unsharp.cl @@ -0,0 +1,99 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +__kernel void unsharp_global(__write_only image2d_t dst, + __read_only image2d_t src, + int size_x, + int size_y, + float amount, + __constant float *coef_matrix) +{ + const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_NEAREST); + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + int2 centre = (int2)(size_x / 2, size_y / 2); + + float4 val = read_imagef(src, sampler, loc); + float4 sum = 0.0f; + int x, y; + + for (y = 0; y < size_y; y++) { + for (x = 0; x < size_x; x++) { + int2 pos = loc + (int2)(x, y) - centre; + sum += coef_matrix[y * size_x + x] * + read_imagef(src, sampler, pos); + } + } + + write_imagef(dst, loc, val + (val - sum) * amount); +} + +__kernel void unsharp_local(__write_only image2d_t dst, + __read_only image2d_t src, + int size_x, + int size_y, + float amount, + __constant float *coef_x, + __constant float *coef_y) +{ + const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_ADDRESS_CLAMP_TO_EDGE | + CLK_FILTER_NEAREST); + int2 block = (int2)(get_group_id(0), get_group_id(1)) * 16; + int2 pos = (int2)(get_local_id(0), get_local_id(1)); + + __local float4 tmp[32][32]; + + int rad_x = size_x / 2; + int rad_y = size_y / 2; + int x, y; + + for (y = 0; y <= 1; y++) { + for (x = 0; x <= 1; x++) { + tmp[pos.y + 16 * y][pos.x + 16 * x] = + read_imagef(src, sampler, block + pos + (int2)(16 * x - 8, 16 * y - 8)); + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + float4 val = tmp[pos.y + 8][pos.x + 8]; + + float4 horiz[2]; + for (y = 0; y <= 1; y++) { + horiz[y] = 0.0f; + for (x = 0; x < size_x; x++) + horiz[y] += coef_x[x] * tmp[pos.y + y * 16][pos.x + 8 + x - rad_x]; + } + + barrier(CLK_LOCAL_MEM_FENCE); + + for (y = 0; y <= 1; y++) { + tmp[pos.y + y * 16][pos.x + 8] = horiz[y]; + } + + barrier(CLK_LOCAL_MEM_FENCE); + + float4 sum = 0.0f; + for (y = 0; y < size_y; y++) + sum += coef_y[y] * tmp[pos.y + 8 + y - rad_y][pos.x + 8]; + + if (block.x + pos.x < get_image_width(dst) && + block.y + pos.y < get_image_height(dst)) + write_imagef(dst, block + pos, val + (val - sum) * amount); +} diff --git a/libavfilter/opencl_source.h b/libavfilter/opencl_source.h index e7af58bcfa84c..23cdfc6ac9e37 100644 --- a/libavfilter/opencl_source.h +++ b/libavfilter/opencl_source.h @@ -20,5 +20,6 @@ #define AVFILTER_OPENCL_SOURCE_H extern const char *ff_opencl_source_overlay; +extern const char *ff_opencl_source_unsharp; #endif /* AVFILTER_OPENCL_SOURCE_H */ diff --git a/libavfilter/version.h b/libavfilter/version.h index 25087957eba9a..b449fd821dda5 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #define LIBAVFILTER_VERSION_MAJOR 7 #define LIBAVFILTER_VERSION_MINOR 2 -#define LIBAVFILTER_VERSION_MICRO 101 +#define LIBAVFILTER_VERSION_MICRO 102 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ diff --git a/libavfilter/vf_unsharp_opencl.c b/libavfilter/vf_unsharp_opencl.c new file mode 100644 index 0000000000000..c2ebf70ad9f0e --- /dev/null +++ b/libavfilter/vf_unsharp_opencl.c @@ -0,0 +1,482 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "internal.h" +#include "opencl.h" +#include "opencl_source.h" +#include "video.h" + +#define MAX_DIAMETER 23 + +typedef struct UnsharpOpenCLContext { + OpenCLFilterContext ocf; + + int initialised; + cl_kernel kernel; + cl_command_queue command_queue; + + float luma_size_x; + float luma_size_y; + float luma_amount; + float chroma_size_x; + float chroma_size_y; + float chroma_amount; + + int global; + + int nb_planes; + struct { + float blur_x[MAX_DIAMETER]; + float blur_y[MAX_DIAMETER]; + + cl_mem matrix; + cl_mem coef_x; + cl_mem coef_y; + + cl_int size_x; + cl_int size_y; + cl_float amount; + cl_float threshold; + } plane[4]; +} UnsharpOpenCLContext; + + +static int unsharp_opencl_init(AVFilterContext *avctx) +{ + UnsharpOpenCLContext *ctx = avctx->priv; + cl_int cle; + int err; + + err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_unsharp, 1); + if (err < 0) + goto fail; + + ctx->command_queue = clCreateCommandQueue(ctx->ocf.hwctx->context, + ctx->ocf.hwctx->device_id, + 0, &cle); + if (!ctx->command_queue) { + av_log(avctx, AV_LOG_ERROR, "Failed to create OpenCL " + "command queue: %d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + + // Use global kernel if mask size will be too big for the local store.. + ctx->global = (ctx->luma_size_x > 17.0f || + ctx->luma_size_y > 17.0f || + ctx->chroma_size_x > 17.0f || + ctx->chroma_size_y > 17.0f); + + ctx->kernel = clCreateKernel(ctx->ocf.program, + ctx->global ? "unsharp_global" + : "unsharp_local", &cle); + if (!ctx->kernel) { + av_log(avctx, AV_LOG_ERROR, "Failed to create kernel: %d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + + ctx->initialised = 1; + return 0; + +fail: + if (ctx->command_queue) + clReleaseCommandQueue(ctx->command_queue); + if (ctx->kernel) + clReleaseKernel(ctx->kernel); + return err; +} + +static int unsharp_opencl_make_filter_params(AVFilterContext *avctx) +{ + UnsharpOpenCLContext *ctx = avctx->priv; + const AVPixFmtDescriptor *desc; + float *matrix; + double val, sum; + cl_int cle; + cl_mem buffer; + size_t matrix_bytes; + float diam_x, diam_y, amount; + int err, p, x, y, size_x, size_y; + + desc = av_pix_fmt_desc_get(ctx->ocf.output_format); + + ctx->nb_planes = 0; + for (p = 0; p < desc->nb_components; p++) + ctx->nb_planes = FFMAX(ctx->nb_planes, desc->comp[p].plane + 1); + + for (p = 0; p < ctx->nb_planes; p++) { + if (p == 0 || (desc->flags & AV_PIX_FMT_FLAG_RGB)) { + diam_x = ctx->luma_size_x; + diam_y = ctx->luma_size_y; + amount = ctx->luma_amount; + } else { + diam_x = ctx->chroma_size_x; + diam_y = ctx->chroma_size_y; + amount = ctx->chroma_amount; + } + size_x = (int)ceil(diam_x) | 1; + size_y = (int)ceil(diam_y) | 1; + matrix_bytes = size_x * size_y * sizeof(float); + + matrix = av_malloc(matrix_bytes); + if (!matrix) { + err = AVERROR(ENOMEM); + goto fail; + } + + sum = 0.0; + for (x = 0; x < size_x; x++) { + double dx = (double)(x - size_x / 2) / diam_x; + sum += ctx->plane[p].blur_x[x] = exp(-16.0 * (dx * dx)); + } + for (x = 0; x < size_x; x++) + ctx->plane[p].blur_x[x] /= sum; + + sum = 0.0; + for (y = 0; y < size_y; y++) { + double dy = (double)(y - size_y / 2) / diam_y; + sum += ctx->plane[p].blur_y[y] = exp(-16.0 * (dy * dy)); + } + for (y = 0; y < size_y; y++) + ctx->plane[p].blur_y[y] /= sum; + + for (y = 0; y < size_y; y++) { + for (x = 0; x < size_x; x++) { + val = ctx->plane[p].blur_x[x] * ctx->plane[p].blur_y[y]; + matrix[y * size_x + x] = val; + } + } + + if (ctx->global) { + buffer = clCreateBuffer(ctx->ocf.hwctx->context, + CL_MEM_READ_ONLY | + CL_MEM_COPY_HOST_PTR | + CL_MEM_HOST_NO_ACCESS, + matrix_bytes, matrix, &cle); + if (!buffer) { + av_log(avctx, AV_LOG_ERROR, "Failed to create matrix buffer: " + "%d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + ctx->plane[p].matrix = buffer; + } else { + buffer = clCreateBuffer(ctx->ocf.hwctx->context, + CL_MEM_READ_ONLY | + CL_MEM_COPY_HOST_PTR | + CL_MEM_HOST_NO_ACCESS, + sizeof(ctx->plane[p].blur_x), + ctx->plane[p].blur_x, &cle); + if (!buffer) { + av_log(avctx, AV_LOG_ERROR, "Failed to create x-coef buffer: " + "%d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + ctx->plane[p].coef_x = buffer; + + buffer = clCreateBuffer(ctx->ocf.hwctx->context, + CL_MEM_READ_ONLY | + CL_MEM_COPY_HOST_PTR | + CL_MEM_HOST_NO_ACCESS, + sizeof(ctx->plane[p].blur_y), + ctx->plane[p].blur_y, &cle); + if (!buffer) { + av_log(avctx, AV_LOG_ERROR, "Failed to create y-coef buffer: " + "%d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + ctx->plane[p].coef_y = buffer; + } + + av_freep(&matrix); + + ctx->plane[p].size_x = size_x; + ctx->plane[p].size_y = size_y; + ctx->plane[p].amount = amount; + } + + err = 0; +fail: + av_freep(&matrix); + return err; +} + +static int unsharp_opencl_filter_frame(AVFilterLink *inlink, AVFrame *input) +{ + AVFilterContext *avctx = inlink->dst; + AVFilterLink *outlink = avctx->outputs[0]; + UnsharpOpenCLContext *ctx = avctx->priv; + AVFrame *output = NULL; + cl_int cle; + size_t global_work[2]; + size_t local_work[2]; + cl_mem src, dst; + int err, p; + + av_log(ctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(input->format), + input->width, input->height, input->pts); + + if (!input->hw_frames_ctx) + return AVERROR(EINVAL); + + if (!ctx->initialised) { + err = unsharp_opencl_init(avctx); + if (err < 0) + goto fail; + + err = unsharp_opencl_make_filter_params(avctx); + if (err < 0) + goto fail; + } + + output = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!output) { + err = AVERROR(ENOMEM); + goto fail; + } + + for (p = 0; p < FF_ARRAY_ELEMS(output->data); p++) { + src = (cl_mem) input->data[p]; + dst = (cl_mem)output->data[p]; + + if (!dst) + break; + + cle = clSetKernelArg(ctx->kernel, 0, sizeof(cl_mem), &dst); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "destination image argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel, 1, sizeof(cl_mem), &src); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "source image argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel, 2, sizeof(cl_int), &ctx->plane[p].size_x); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "matrix size argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel, 3, sizeof(cl_int), &ctx->plane[p].size_y); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "matrix size argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel, 4, sizeof(cl_float), &ctx->plane[p].amount); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "amount argument: %d.\n", cle); + goto fail; + } + if (ctx->global) { + cle = clSetKernelArg(ctx->kernel, 5, sizeof(cl_mem), &ctx->plane[p].matrix); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "matrix argument: %d.\n", cle); + goto fail; + } + } else { + cle = clSetKernelArg(ctx->kernel, 5, sizeof(cl_mem), &ctx->plane[p].coef_x); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "x-coef argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel, 6, sizeof(cl_mem), &ctx->plane[p].coef_y); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "y-coef argument: %d.\n", cle); + goto fail; + } + } + + if (ctx->global) { + global_work[0] = output->width; + global_work[1] = output->height; + } else { + global_work[0] = FFALIGN(output->width, 16); + global_work[1] = FFALIGN(output->height, 16); + local_work[0] = 16; + local_work[1] = 16; + } + + av_log(avctx, AV_LOG_DEBUG, "Run kernel on plane %d " + "(%zux%zu).\n", p, global_work[0], global_work[1]); + + cle = clEnqueueNDRangeKernel(ctx->command_queue, ctx->kernel, 2, NULL, + global_work, ctx->global ? NULL : local_work, + 0, NULL, NULL); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to enqueue kernel: %d.\n", + cle); + err = AVERROR(EIO); + goto fail; + } + } + + cle = clFinish(ctx->command_queue); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to finish command queue: %d.\n", + cle); + err = AVERROR(EIO); + goto fail; + } + + err = av_frame_copy_props(output, input); + if (err < 0) + goto fail; + + av_frame_free(&input); + + av_log(ctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(output->format), + output->width, output->height, output->pts); + + return ff_filter_frame(outlink, output); + +fail: + clFinish(ctx->command_queue); + av_frame_free(&input); + av_frame_free(&output); + return err; +} + +static av_cold void unsharp_opencl_uninit(AVFilterContext *avctx) +{ + UnsharpOpenCLContext *ctx = avctx->priv; + cl_int cle; + int i; + + for (i = 0; i < ctx->nb_planes; i++) { + if (ctx->plane[i].matrix) + clReleaseMemObject(ctx->plane[i].matrix); + if (ctx->plane[i].coef_x) + clReleaseMemObject(ctx->plane[i].coef_x); + if (ctx->plane[i].coef_y) + clReleaseMemObject(ctx->plane[i].coef_y); + } + + if (ctx->kernel) { + cle = clReleaseKernel(ctx->kernel); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "kernel: %d.\n", cle); + } + + if (ctx->command_queue) { + cle = clReleaseCommandQueue(ctx->command_queue); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "command queue: %d.\n", cle); + } + + ff_opencl_filter_uninit(avctx); +} + +#define OFFSET(x) offsetof(UnsharpOpenCLContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption unsharp_opencl_options[] = { + { "luma_msize_x", "Set luma mask horizontal diameter (pixels)", + OFFSET(luma_size_x), AV_OPT_TYPE_FLOAT, + { .dbl = 5.0 }, 1, MAX_DIAMETER, FLAGS }, + { "lx", "Set luma mask horizontal diameter (pixels)", + OFFSET(luma_size_x), AV_OPT_TYPE_FLOAT, + { .dbl = 5.0 }, 1, MAX_DIAMETER, FLAGS }, + { "luma_msize_y", "Set luma mask vertical diameter (pixels)", + OFFSET(luma_size_y), AV_OPT_TYPE_FLOAT, + { .dbl = 5.0 }, 1, MAX_DIAMETER, FLAGS }, + { "ly", "Set luma mask vertical diameter (pixels)", + OFFSET(luma_size_y), AV_OPT_TYPE_FLOAT, + { .dbl = 5.0 }, 1, MAX_DIAMETER, FLAGS }, + { "luma_amount", "Set luma amount (multiplier)", + OFFSET(luma_amount), AV_OPT_TYPE_FLOAT, + { .dbl = 1.0 }, -10, 10, FLAGS }, + { "la", "Set luma amount (multiplier)", + OFFSET(luma_amount), AV_OPT_TYPE_FLOAT, + { .dbl = 1.0 }, -10, 10, FLAGS }, + + { "chroma_msize_x", "Set chroma mask horizontal diameter (pixels after subsampling)", + OFFSET(chroma_size_x), AV_OPT_TYPE_FLOAT, + { .dbl = 5.0 }, 1, MAX_DIAMETER, FLAGS }, + { "cx", "Set chroma mask horizontal diameter (pixels after subsampling)", + OFFSET(chroma_size_x), AV_OPT_TYPE_FLOAT, + { .dbl = 5.0 }, 1, MAX_DIAMETER, FLAGS }, + { "chroma_msize_y", "Set chroma mask vertical diameter (pixels after subsampling)", + OFFSET(chroma_size_y), AV_OPT_TYPE_FLOAT, + { .dbl = 5.0 }, 1, MAX_DIAMETER, FLAGS }, + { "cy", "Set chroma mask vertical diameter (pixels after subsampling)", + OFFSET(chroma_size_y), AV_OPT_TYPE_FLOAT, + { .dbl = 5.0 }, 1, MAX_DIAMETER, FLAGS }, + { "chroma_amount", "Set chroma amount (multiplier)", + OFFSET(chroma_amount), AV_OPT_TYPE_FLOAT, + { .dbl = 0.0 }, -10, 10, FLAGS }, + { "ca", "Set chroma amount (multiplier)", + OFFSET(chroma_amount), AV_OPT_TYPE_FLOAT, + { .dbl = 0.0 }, -10, 10, FLAGS }, + + { NULL } +}; + +AVFILTER_DEFINE_CLASS(unsharp_opencl); + +static const AVFilterPad unsharp_opencl_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &unsharp_opencl_filter_frame, + .config_props = &ff_opencl_filter_config_input, + }, + { NULL } +}; + +static const AVFilterPad unsharp_opencl_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_opencl_filter_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_unsharp_opencl = { + .name = "unsharp_opencl", + .description = NULL_IF_CONFIG_SMALL("Apply unsharp mask to input video"), + .priv_size = sizeof(UnsharpOpenCLContext), + .priv_class = &unsharp_opencl_class, + .init = &ff_opencl_filter_init, + .uninit = &unsharp_opencl_uninit, + .query_formats = &ff_opencl_filter_query_formats, + .inputs = unsharp_opencl_inputs, + .outputs = unsharp_opencl_outputs, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From 5514bab37a26f36753b756a2f0ceb837d055850f Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 25 Jun 2017 22:13:03 +0100 Subject: [PATCH 1066/2557] vf_hwmap: Pass mapping mode when deriving frames context on an existing device To match creation on a newly-derived device. (This was missed earlier because the mode is only used in some cases.) --- libavfilter/vf_hwmap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c index 8277241dc4e1f..d5fc3c46e6263 100644 --- a/libavfilter/vf_hwmap.c +++ b/libavfilter/vf_hwmap.c @@ -114,7 +114,8 @@ static int hwmap_config_output(AVFilterLink *outlink) err = av_hwframe_ctx_create_derived(&ctx->hwframes_ref, outlink->format, device, - inlink->hw_frames_ctx, 0); + inlink->hw_frames_ctx, + ctx->mode); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to create derived " "frames context: %d.\n", err); From 0f93cef2d6405f07b42719506cbde30f07dd8702 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 26 Jun 2017 20:28:07 +0100 Subject: [PATCH 1067/2557] hwcontext: Perform usual uninitialisation on derived frames contexts --- libavutil/hwcontext.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index b26e68fe77f76..f47158f811ca4 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -217,19 +217,16 @@ static void hwframe_ctx_free(void *opaque, uint8_t *data) { AVHWFramesContext *ctx = (AVHWFramesContext*)data; - if (ctx->internal->source_frames) { - av_buffer_unref(&ctx->internal->source_frames); + if (ctx->internal->pool_internal) + av_buffer_pool_uninit(&ctx->internal->pool_internal); - } else { - if (ctx->internal->pool_internal) - av_buffer_pool_uninit(&ctx->internal->pool_internal); + if (ctx->internal->hw_type->frames_uninit) + ctx->internal->hw_type->frames_uninit(ctx); - if (ctx->internal->hw_type->frames_uninit) - ctx->internal->hw_type->frames_uninit(ctx); + if (ctx->free) + ctx->free(ctx); - if (ctx->free) - ctx->free(ctx); - } + av_buffer_unref(&ctx->internal->source_frames); av_buffer_unref(&ctx->device_ref); From 3650cb2dfa644ff4260d226b783747ff9e020ad1 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 14 Nov 2017 19:47:30 +0000 Subject: [PATCH 1068/2557] lavu,lavfi,ffmpeg: Remove experimental OpenCL API This was added in early 2013 and abandoned several months later; as far as I can tell, there are no external users. Future OpenCL use will be via hwcontext, which requires neither special OpenCL-only API nor global state in libavutil. All internal users are also deleted - this is just the unsharp filter (replaced by unsharp_opencl, which is more flexible) and the deshake filter (no replacement). --- configure | 2 - doc/APIchanges | 3 + doc/filters.texi | 8 - doc/utils.texi | 30 - fftools/Makefile | 1 - fftools/cmdutils.h | 18 - fftools/cmdutils_opencl.c | 283 --------- libavfilter/Makefile | 3 - libavfilter/allfilters.c | 2 - libavfilter/deshake.h | 24 - libavfilter/deshake_opencl.c | 198 ------- libavfilter/deshake_opencl.h | 45 -- libavfilter/deshake_opencl_kernel.h | 225 ------- libavfilter/opencl_allkernels.c | 41 -- libavfilter/opencl_allkernels.h | 29 - libavfilter/unsharp.h | 31 - libavfilter/unsharp_opencl.c | 422 -------------- libavfilter/unsharp_opencl.h | 34 -- libavfilter/unsharp_opencl_kernel.h | 342 ----------- libavfilter/vf_deshake.c | 23 +- libavfilter/vf_unsharp.c | 26 +- libavutil/Makefile | 4 - libavutil/opencl.c | 875 ---------------------------- libavutil/opencl.h | 292 ---------- libavutil/opencl_internal.c | 59 -- libavutil/opencl_internal.h | 40 -- 26 files changed, 6 insertions(+), 3054 deletions(-) delete mode 100644 fftools/cmdutils_opencl.c delete mode 100644 libavfilter/deshake_opencl.c delete mode 100644 libavfilter/deshake_opencl.h delete mode 100644 libavfilter/deshake_opencl_kernel.h delete mode 100644 libavfilter/opencl_allkernels.c delete mode 100644 libavfilter/opencl_allkernels.h delete mode 100644 libavfilter/unsharp_opencl.c delete mode 100644 libavfilter/unsharp_opencl.h delete mode 100644 libavfilter/unsharp_opencl_kernel.h delete mode 100644 libavutil/opencl.c delete mode 100644 libavutil/opencl.h delete mode 100644 libavutil/opencl_internal.c delete mode 100644 libavutil/opencl_internal.h diff --git a/configure b/configure index c4de469664aee..3ec6407fb205f 100755 --- a/configure +++ b/configure @@ -3209,7 +3209,6 @@ deinterlace_qsv_filter_deps="libmfx" deinterlace_vaapi_filter_deps="vaapi" delogo_filter_deps="gpl" deshake_filter_select="pixelutils" -deshake_filter_suggest="opencl" drawtext_filter_deps="libfreetype" drawtext_filter_suggest="libfontconfig libfribidi" elbg_filter_deps="avcodec" @@ -3285,7 +3284,6 @@ tinterlace_pad_test_deps="tinterlace_filter" tonemap_filter_deps="const_nan" unsharp_opencl_filter_deps="opencl" uspp_filter_deps="gpl avcodec" -unsharp_filter_suggest="opencl" vaguedenoiser_filter_deps="gpl" vidstabdetect_filter_deps="libvidstab" vidstabtransform_filter_deps="libvidstab" diff --git a/doc/APIchanges b/doc/APIchanges index 6ace2d1876a8f..45276f734c745 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2017-11-xx - xxxxxxx - lavu 55.3.0 - opencl.h + Remove experiental OpenCL API (av_opencl_*). + 2017-11-xx - xxxxxxx - lavu 55.2.0 - hwcontext.h hwcontext_opencl.h Add AV_HWDEVICE_TYPE_OPENCL and a new installed header with OpenCL-specific hwcontext definitions. diff --git a/doc/filters.texi b/doc/filters.texi index 62f633c6f888a..04a8139c6de45 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6913,10 +6913,6 @@ Default value is @samp{exhaustive}. If set then a detailed log of the motion search is written to the specified file. -@item opencl -If set to 1, specify using OpenCL capabilities, only available if -FFmpeg was configured with @code{--enable-opencl}. Default value is 0. - @end table @section despill @@ -15048,10 +15044,6 @@ sharpen it, a value of zero will disable the effect. Default value is 0.0. -@item opencl -If set to 1, specify using OpenCL capabilities, only available if -FFmpeg was configured with @code{--enable-opencl}. Default value is 0. - @end table All parameters are optional and default to the equivalent of the diff --git a/doc/utils.texi b/doc/utils.texi index e635118565fdc..d55dd315c34fb 100644 --- a/doc/utils.texi +++ b/doc/utils.texi @@ -1057,33 +1057,3 @@ indication of the corresponding powers of 10 and of 2. @end table @c man end EXPRESSION EVALUATION - -@chapter OpenCL Options -@c man begin OPENCL OPTIONS - -When FFmpeg is configured with @code{--enable-opencl}, it is possible -to set the options for the global OpenCL context. - -The list of supported options follows: - -@table @option -@item build_options -Set build options used to compile the registered kernels. - -See reference "OpenCL Specification Version: 1.2 chapter 5.6.4". - -@item platform_idx -Select the index of the platform to run OpenCL code. - -The specified index must be one of the indexes in the device list -which can be obtained with @code{ffmpeg -opencl_bench} or @code{av_opencl_get_device_list()}. - -@item device_idx -Select the index of the device used to run OpenCL code. - -The specified index must be one of the indexes in the device list which -can be obtained with @code{ffmpeg -opencl_bench} or @code{av_opencl_get_device_list()}. - -@end table - -@c man end OPENCL OPTIONS diff --git a/fftools/Makefile b/fftools/Makefile index c867814a71cb7..8fbb898ce5e39 100644 --- a/fftools/Makefile +++ b/fftools/Makefile @@ -29,7 +29,6 @@ $(1)$(PROGSSUF)_g$(EXESUF): FF_EXTRALIBS += $(EXTRALIBS-$(1)) -include $$(OBJS-$(1):.o=.d) endef -$(foreach P,$(AVPROGS-yes),$(eval OBJS-$(P)-$(CONFIG_OPENCL) += fftools/cmdutils_opencl.o)) $(foreach P,$(AVPROGS-yes),$(eval $(call DOFFTOOL,$(P)))) all: $(AVPROGS) diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index fa2b2551b2071..87244891d4fac 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -105,12 +105,6 @@ int opt_max_alloc(void *optctx, const char *opt, const char *arg); int opt_codec_debug(void *optctx, const char *opt, const char *arg); -#if CONFIG_OPENCL -int opt_opencl(void *optctx, const char *opt, const char *arg); - -int opt_opencl_bench(void *optctx, const char *opt, const char *arg); -#endif - /** * Limit the execution time. */ @@ -207,17 +201,6 @@ typedef struct OptionDef { void show_help_options(const OptionDef *options, const char *msg, int req_flags, int rej_flags, int alt_flags); -#if CONFIG_OPENCL -#define CMDUTILS_COMMON_OPTIONS_OPENCL \ - { "opencl_bench", OPT_EXIT, {.func_arg = opt_opencl_bench}, \ - "run benchmark on all OpenCL devices and show results" }, \ - { "opencl_options", HAS_ARG, {.func_arg = opt_opencl}, \ - "set OpenCL environment options" }, \ - -#else -#define CMDUTILS_COMMON_OPTIONS_OPENCL -#endif - #if CONFIG_AVDEVICE #define CMDUTILS_COMMON_OPTIONS_AVDEVICE \ { "sources" , OPT_EXIT | HAS_ARG, { .func_arg = show_sources }, \ @@ -257,7 +240,6 @@ void show_help_options(const OptionDef *options, const char *msg, int req_flags, { "max_alloc", HAS_ARG, { .func_arg = opt_max_alloc }, "set maximum size of a single allocated block", "bytes" }, \ { "cpuflags", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "force specific cpu flags", "flags" }, \ { "hide_banner", OPT_BOOL | OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, \ - CMDUTILS_COMMON_OPTIONS_OPENCL \ CMDUTILS_COMMON_OPTIONS_AVDEVICE \ /** diff --git a/fftools/cmdutils_opencl.c b/fftools/cmdutils_opencl.c deleted file mode 100644 index 906aef4836314..0000000000000 --- a/fftools/cmdutils_opencl.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2013 Lenny Wang - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/opt.h" -#include "libavutil/time.h" -#include "libavutil/log.h" -#include "libavutil/opencl.h" -#include "libavutil/avstring.h" -#include "cmdutils.h" - -typedef struct { - int platform_idx; - int device_idx; - char device_name[64]; - int64_t runtime; -} OpenCLDeviceBenchmark; - -const char *ocl_bench_source = AV_OPENCL_KERNEL( -inline unsigned char clip_uint8(int a) -{ - if (a & (~0xFF)) - return (-a)>>31; - else - return a; -} - -kernel void unsharp_bench( - global unsigned char *src, - global unsigned char *dst, - global int *mask, - int width, - int height) -{ - int i, j, local_idx, lc_idx, sum = 0; - int2 thread_idx, block_idx, global_idx, lm_idx; - thread_idx.x = get_local_id(0); - thread_idx.y = get_local_id(1); - block_idx.x = get_group_id(0); - block_idx.y = get_group_id(1); - global_idx.x = get_global_id(0); - global_idx.y = get_global_id(1); - local uchar data[32][32]; - local int lc[128]; - - for (i = 0; i <= 1; i++) { - lm_idx.y = -8 + (block_idx.y + i) * 16 + thread_idx.y; - lm_idx.y = lm_idx.y < 0 ? 0 : lm_idx.y; - lm_idx.y = lm_idx.y >= height ? height - 1: lm_idx.y; - for (j = 0; j <= 1; j++) { - lm_idx.x = -8 + (block_idx.x + j) * 16 + thread_idx.x; - lm_idx.x = lm_idx.x < 0 ? 0 : lm_idx.x; - lm_idx.x = lm_idx.x >= width ? width - 1: lm_idx.x; - data[i*16 + thread_idx.y][j*16 + thread_idx.x] = src[lm_idx.y*width + lm_idx.x]; - } - } - local_idx = thread_idx.y*16 + thread_idx.x; - if (local_idx < 128) - lc[local_idx] = mask[local_idx]; - barrier(CLK_LOCAL_MEM_FENCE); - - \n#pragma unroll\n - for (i = -4; i <= 4; i++) { - lm_idx.y = 8 + i + thread_idx.y; - \n#pragma unroll\n - for (j = -4; j <= 4; j++) { - lm_idx.x = 8 + j + thread_idx.x; - lc_idx = (i + 4)*8 + j + 4; - sum += (int)data[lm_idx.y][lm_idx.x] * lc[lc_idx]; - } - } - int temp = (int)data[thread_idx.y + 8][thread_idx.x + 8]; - int res = temp + (((temp - (int)((sum + 1<<15) >> 16))) >> 16); - if (global_idx.x < width && global_idx.y < height) - dst[global_idx.x + global_idx.y*width] = clip_uint8(res); -} -); - -#define OCLCHECK(method, ... ) \ -do { \ - status = method(__VA_ARGS__); \ - if (status != CL_SUCCESS) { \ - av_log(NULL, AV_LOG_ERROR, # method " error '%s'\n", \ - av_opencl_errstr(status)); \ - ret = AVERROR_EXTERNAL; \ - goto end; \ - } \ -} while (0) - -#define CREATEBUF(out, flags, size) \ -do { \ - out = clCreateBuffer(ext_opencl_env->context, flags, size, NULL, &status); \ - if (status != CL_SUCCESS) { \ - av_log(NULL, AV_LOG_ERROR, "Could not create OpenCL buffer\n"); \ - ret = AVERROR_EXTERNAL; \ - goto end; \ - } \ -} while (0) - -static void fill_rand_int(int *data, int n) -{ - int i; - srand(av_gettime()); - for (i = 0; i < n; i++) - data[i] = rand(); -} - -#define OPENCL_NB_ITER 5 -static int64_t run_opencl_bench(AVOpenCLExternalEnv *ext_opencl_env) -{ - int i, arg = 0, width = 1920, height = 1088; - int64_t start, ret = 0; - cl_int status; - size_t kernel_len; - char *inbuf; - int *mask = NULL; - int buf_size = width * height * sizeof(char); - int mask_size = sizeof(uint32_t) * 128; - - cl_mem cl_mask = NULL, cl_inbuf = NULL, cl_outbuf = NULL; - cl_kernel kernel = NULL; - cl_program program = NULL; - size_t local_work_size_2d[2] = {16, 16}; - size_t global_work_size_2d[2] = {(size_t)width, (size_t)height}; - - if (!(inbuf = av_malloc(buf_size)) || !(mask = av_malloc(mask_size))) { - av_log(NULL, AV_LOG_ERROR, "Out of memory\n"); - ret = AVERROR(ENOMEM); - goto end; - } - fill_rand_int((int*)inbuf, buf_size/4); - fill_rand_int(mask, mask_size/4); - - CREATEBUF(cl_mask, CL_MEM_READ_ONLY, mask_size); - CREATEBUF(cl_inbuf, CL_MEM_READ_ONLY, buf_size); - CREATEBUF(cl_outbuf, CL_MEM_READ_WRITE, buf_size); - - kernel_len = strlen(ocl_bench_source); - program = clCreateProgramWithSource(ext_opencl_env->context, 1, &ocl_bench_source, - &kernel_len, &status); - if (status != CL_SUCCESS || !program) { - av_log(NULL, AV_LOG_ERROR, "OpenCL unable to create benchmark program\n"); - ret = AVERROR_EXTERNAL; - goto end; - } - status = clBuildProgram(program, 1, &(ext_opencl_env->device_id), NULL, NULL, NULL); - if (status != CL_SUCCESS) { - av_log(NULL, AV_LOG_ERROR, "OpenCL unable to build benchmark program\n"); - ret = AVERROR_EXTERNAL; - goto end; - } - kernel = clCreateKernel(program, "unsharp_bench", &status); - if (status != CL_SUCCESS) { - av_log(NULL, AV_LOG_ERROR, "OpenCL unable to create benchmark kernel\n"); - ret = AVERROR_EXTERNAL; - goto end; - } - - OCLCHECK(clEnqueueWriteBuffer, ext_opencl_env->command_queue, cl_inbuf, CL_TRUE, 0, - buf_size, inbuf, 0, NULL, NULL); - OCLCHECK(clEnqueueWriteBuffer, ext_opencl_env->command_queue, cl_mask, CL_TRUE, 0, - mask_size, mask, 0, NULL, NULL); - OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem), &cl_inbuf); - OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem), &cl_outbuf); - OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem), &cl_mask); - OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_int), &width); - OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_int), &height); - - start = av_gettime_relative(); - for (i = 0; i < OPENCL_NB_ITER; i++) - OCLCHECK(clEnqueueNDRangeKernel, ext_opencl_env->command_queue, kernel, 2, NULL, - global_work_size_2d, local_work_size_2d, 0, NULL, NULL); - clFinish(ext_opencl_env->command_queue); - ret = (av_gettime_relative() - start)/OPENCL_NB_ITER; -end: - if (kernel) - clReleaseKernel(kernel); - if (program) - clReleaseProgram(program); - if (cl_inbuf) - clReleaseMemObject(cl_inbuf); - if (cl_outbuf) - clReleaseMemObject(cl_outbuf); - if (cl_mask) - clReleaseMemObject(cl_mask); - av_free(inbuf); - av_free(mask); - return ret; -} - -static int compare_ocl_device_desc(const void *a, const void *b) -{ - const OpenCLDeviceBenchmark* va = (const OpenCLDeviceBenchmark*)a; - const OpenCLDeviceBenchmark* vb = (const OpenCLDeviceBenchmark*)b; - return FFDIFFSIGN(va->runtime , vb->runtime); -} - -int opt_opencl_bench(void *optctx, const char *opt, const char *arg) -{ - int i, j, nb_devices = 0, count = 0, ret = 0; - int64_t score = 0; - AVOpenCLDeviceList *device_list; - AVOpenCLDeviceNode *device_node = NULL; - OpenCLDeviceBenchmark *devices = NULL; - cl_platform_id platform; - - ret = av_opencl_get_device_list(&device_list); - if (ret < 0) { - return ret; - } - for (i = 0; i < device_list->platform_num; i++) - nb_devices += device_list->platform_node[i]->device_num; - if (!nb_devices) { - av_log(NULL, AV_LOG_ERROR, "No OpenCL device detected!\n"); - av_opencl_free_device_list(&device_list); - return AVERROR(EINVAL); - } - if (!(devices = av_malloc_array(nb_devices, sizeof(OpenCLDeviceBenchmark)))) { - av_log(NULL, AV_LOG_ERROR, "Could not allocate buffer\n"); - av_opencl_free_device_list(&device_list); - return AVERROR(ENOMEM); - } - - for (i = 0; i < device_list->platform_num; i++) { - for (j = 0; j < device_list->platform_node[i]->device_num; j++) { - device_node = device_list->platform_node[i]->device_node[j]; - platform = device_list->platform_node[i]->platform_id; - score = av_opencl_benchmark(device_node, platform, run_opencl_bench); - if (score > 0) { - devices[count].platform_idx = i; - devices[count].device_idx = j; - devices[count].runtime = score; - av_strlcpy(devices[count].device_name, device_node->device_name, - sizeof(devices[count].device_name)); - count++; - } - } - } - qsort(devices, count, sizeof(OpenCLDeviceBenchmark), compare_ocl_device_desc); - fprintf(stderr, "platform_idx\tdevice_idx\tdevice_name\truntime\n"); - for (i = 0; i < count; i++) - fprintf(stdout, "%d\t%d\t%s\t%"PRId64"\n", - devices[i].platform_idx, devices[i].device_idx, - devices[i].device_name, devices[i].runtime); - - av_opencl_free_device_list(&device_list); - av_free(devices); - return 0; -} - -int opt_opencl(void *optctx, const char *opt, const char *arg) -{ - char *key, *value; - const char *opts = arg; - int ret = 0; - while (*opts) { - ret = av_opt_get_key_value(&opts, "=", ":", 0, &key, &value); - if (ret < 0) - return ret; - ret = av_opencl_set_option(key, value); - if (ret < 0) - return ret; - if (*opts) - opts++; - } - return ret; -} diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 30474ea77b240..89737b5ad0db6 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -19,7 +19,6 @@ OBJS = allfilters.o \ framequeue.o \ graphdump.o \ graphparser.o \ - opencl_allkernels.o \ transform.o \ video.o \ @@ -250,7 +249,6 @@ OBJS-$(CONFIG_NOISE_FILTER) += vf_noise.o OBJS-$(CONFIG_NULL_FILTER) += vf_null.o OBJS-$(CONFIG_OCR_FILTER) += vf_ocr.o OBJS-$(CONFIG_OCV_FILTER) += vf_libopencv.o -OBJS-$(CONFIG_OPENCL) += deshake_opencl.o unsharp_opencl.o OBJS-$(CONFIG_OSCILLOSCOPE_FILTER) += vf_datascope.o OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o framesync.o OBJS-$(CONFIG_OVERLAY_OPENCL_FILTER) += vf_overlay_opencl.o opencl.o \ @@ -396,7 +394,6 @@ OBJS-$(CONFIG_MOVIE_FILTER) += src_movie.o SLIBOBJS-$(HAVE_GNU_WINDRES) += avfilterres.o SKIPHEADERS-$(CONFIG_LIBVIDSTAB) += vidstabutils.h -SKIPHEADERS-$(CONFIG_OPENCL) += opencl_internal.h deshake_opencl_kernel.h unsharp_opencl_kernel.h OBJS-$(CONFIG_SHARED) += log2_tab.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index beacfce612d8a..50e9d9a0cb129 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -22,7 +22,6 @@ #include "libavutil/thread.h" #include "avfilter.h" #include "config.h" -#include "opencl_allkernels.h" #define REGISTER_FILTER(X, x, y) \ @@ -407,7 +406,6 @@ static void register_all(void) REGISTER_FILTER_UNCONDITIONAL(vsink_buffer); REGISTER_FILTER_UNCONDITIONAL(af_afifo); REGISTER_FILTER_UNCONDITIONAL(vf_fifo); - ff_opencl_register_filter_kernel_code_all(); } void avfilter_register_all(void) diff --git a/libavfilter/deshake.h b/libavfilter/deshake.h index 5e25bb3a7af12..406cbab2f65f2 100644 --- a/libavfilter/deshake.h +++ b/libavfilter/deshake.h @@ -26,9 +26,6 @@ #include "avfilter.h" #include "transform.h" #include "libavutil/pixelutils.h" -#if CONFIG_OPENCL -#include "libavutil/opencl.h" -#endif enum SearchMethod { @@ -53,24 +50,6 @@ typedef struct Transform { double zoom; ///< Zoom percentage } Transform; -#if CONFIG_OPENCL - -typedef struct DeshakeOpenclContext { - cl_command_queue command_queue; - cl_program program; - cl_kernel kernel_luma; - cl_kernel kernel_chroma; - int in_plane_size[8]; - int out_plane_size[8]; - int plane_num; - cl_mem cl_inbuf; - size_t cl_inbuf_size; - cl_mem cl_outbuf; - size_t cl_outbuf_size; -} DeshakeOpenclContext; - -#endif - #define MAX_R 64 typedef struct DeshakeContext { @@ -96,9 +75,6 @@ typedef struct DeshakeContext { int cy; char *filename; ///< Motion search detailed log filename int opencl; -#if CONFIG_OPENCL - DeshakeOpenclContext opencl_ctx; -#endif int (* transform)(AVFilterContext *ctx, int width, int height, int cw, int ch, const float *matrix_y, const float *matrix_uv, enum InterpolateMethod interpolate, enum FillMethod fill, AVFrame *in, AVFrame *out); diff --git a/libavfilter/deshake_opencl.c b/libavfilter/deshake_opencl.c deleted file mode 100644 index 877ec1dc03fba..0000000000000 --- a/libavfilter/deshake_opencl.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (C) 2013 Wei Gao - * Copyright (C) 2013 Lenny Wang - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * transform input video - */ - -#include "libavutil/common.h" -#include "libavutil/dict.h" -#include "libavutil/pixdesc.h" -#include "deshake_opencl.h" -#include "libavutil/opencl_internal.h" - -#define PLANE_NUM 3 -#define ROUND_TO_16(a) (((((a) - 1)/16)+1)*16) - -int ff_opencl_transform(AVFilterContext *ctx, - int width, int height, int cw, int ch, - const float *matrix_y, const float *matrix_uv, - enum InterpolateMethod interpolate, - enum FillMethod fill, AVFrame *in, AVFrame *out) -{ - int ret = 0; - cl_int status; - DeshakeContext *deshake = ctx->priv; - float4 packed_matrix_lu = {matrix_y[0], matrix_y[1], matrix_y[2], matrix_y[5]}; - float4 packed_matrix_ch = {matrix_uv[0], matrix_uv[1], matrix_uv[2], matrix_uv[5]}; - size_t global_worksize_lu[2] = {(size_t)ROUND_TO_16(width), (size_t)ROUND_TO_16(height)}; - size_t global_worksize_ch[2] = {(size_t)ROUND_TO_16(cw), (size_t)(2*ROUND_TO_16(ch))}; - size_t local_worksize[2] = {16, 16}; - FFOpenclParam param_lu = {0}; - FFOpenclParam param_ch = {0}; - param_lu.ctx = param_ch.ctx = ctx; - param_lu.kernel = deshake->opencl_ctx.kernel_luma; - param_ch.kernel = deshake->opencl_ctx.kernel_chroma; - - if ((unsigned int)interpolate > INTERPOLATE_BIQUADRATIC) { - av_log(ctx, AV_LOG_ERROR, "Selected interpolate method is invalid\n"); - return AVERROR(EINVAL); - } - ret = avpriv_opencl_set_parameter(¶m_lu, - FF_OPENCL_PARAM_INFO(deshake->opencl_ctx.cl_inbuf), - FF_OPENCL_PARAM_INFO(deshake->opencl_ctx.cl_outbuf), - FF_OPENCL_PARAM_INFO(packed_matrix_lu), - FF_OPENCL_PARAM_INFO(interpolate), - FF_OPENCL_PARAM_INFO(fill), - FF_OPENCL_PARAM_INFO(in->linesize[0]), - FF_OPENCL_PARAM_INFO(out->linesize[0]), - FF_OPENCL_PARAM_INFO(height), - FF_OPENCL_PARAM_INFO(width), - NULL); - if (ret < 0) - return ret; - ret = avpriv_opencl_set_parameter(¶m_ch, - FF_OPENCL_PARAM_INFO(deshake->opencl_ctx.cl_inbuf), - FF_OPENCL_PARAM_INFO(deshake->opencl_ctx.cl_outbuf), - FF_OPENCL_PARAM_INFO(packed_matrix_ch), - FF_OPENCL_PARAM_INFO(interpolate), - FF_OPENCL_PARAM_INFO(fill), - FF_OPENCL_PARAM_INFO(in->linesize[0]), - FF_OPENCL_PARAM_INFO(out->linesize[0]), - FF_OPENCL_PARAM_INFO(in->linesize[1]), - FF_OPENCL_PARAM_INFO(out->linesize[1]), - FF_OPENCL_PARAM_INFO(height), - FF_OPENCL_PARAM_INFO(width), - FF_OPENCL_PARAM_INFO(ch), - FF_OPENCL_PARAM_INFO(cw), - NULL); - if (ret < 0) - return ret; - status = clEnqueueNDRangeKernel(deshake->opencl_ctx.command_queue, - deshake->opencl_ctx.kernel_luma, 2, NULL, - global_worksize_lu, local_worksize, 0, NULL, NULL); - status |= clEnqueueNDRangeKernel(deshake->opencl_ctx.command_queue, - deshake->opencl_ctx.kernel_chroma, 2, NULL, - global_worksize_ch, local_worksize, 0, NULL, NULL); - if (status != CL_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "OpenCL run kernel error occurred: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - ret = av_opencl_buffer_read_image(out->data, deshake->opencl_ctx.out_plane_size, - deshake->opencl_ctx.plane_num, deshake->opencl_ctx.cl_outbuf, - deshake->opencl_ctx.cl_outbuf_size); - if (ret < 0) - return ret; - return ret; -} - -int ff_opencl_deshake_init(AVFilterContext *ctx) -{ - int ret = 0; - DeshakeContext *deshake = ctx->priv; - ret = av_opencl_init(NULL); - if (ret < 0) - return ret; - deshake->opencl_ctx.plane_num = PLANE_NUM; - deshake->opencl_ctx.command_queue = av_opencl_get_command_queue(); - if (!deshake->opencl_ctx.command_queue) { - av_log(ctx, AV_LOG_ERROR, "Unable to get OpenCL command queue in filter 'deshake'\n"); - return AVERROR(EINVAL); - } - deshake->opencl_ctx.program = av_opencl_compile("avfilter_transform", NULL); - if (!deshake->opencl_ctx.program) { - av_log(ctx, AV_LOG_ERROR, "OpenCL failed to compile program 'avfilter_transform'\n"); - return AVERROR(EINVAL); - } - if (!deshake->opencl_ctx.kernel_luma) { - deshake->opencl_ctx.kernel_luma = clCreateKernel(deshake->opencl_ctx.program, - "avfilter_transform_luma", &ret); - if (ret != CL_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "OpenCL failed to create kernel 'avfilter_transform_luma'\n"); - return AVERROR(EINVAL); - } - } - if (!deshake->opencl_ctx.kernel_chroma) { - deshake->opencl_ctx.kernel_chroma = clCreateKernel(deshake->opencl_ctx.program, - "avfilter_transform_chroma", &ret); - if (ret != CL_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "OpenCL failed to create kernel 'avfilter_transform_chroma'\n"); - return AVERROR(EINVAL); - } - } - return ret; -} - -void ff_opencl_deshake_uninit(AVFilterContext *ctx) -{ - DeshakeContext *deshake = ctx->priv; - av_opencl_buffer_release(&deshake->opencl_ctx.cl_inbuf); - av_opencl_buffer_release(&deshake->opencl_ctx.cl_outbuf); - clReleaseKernel(deshake->opencl_ctx.kernel_luma); - clReleaseKernel(deshake->opencl_ctx.kernel_chroma); - clReleaseProgram(deshake->opencl_ctx.program); - deshake->opencl_ctx.command_queue = NULL; - av_opencl_uninit(); -} - -int ff_opencl_deshake_process_inout_buf(AVFilterContext *ctx, AVFrame *in, AVFrame *out) -{ - int ret = 0; - AVFilterLink *link = ctx->inputs[0]; - DeshakeContext *deshake = ctx->priv; - const int hshift = av_pix_fmt_desc_get(link->format)->log2_chroma_h; - int chroma_height = AV_CEIL_RSHIFT(link->h, hshift); - - if ((!deshake->opencl_ctx.cl_inbuf) || (!deshake->opencl_ctx.cl_outbuf)) { - deshake->opencl_ctx.in_plane_size[0] = (in->linesize[0] * in->height); - deshake->opencl_ctx.in_plane_size[1] = (in->linesize[1] * chroma_height); - deshake->opencl_ctx.in_plane_size[2] = (in->linesize[2] * chroma_height); - deshake->opencl_ctx.out_plane_size[0] = (out->linesize[0] * out->height); - deshake->opencl_ctx.out_plane_size[1] = (out->linesize[1] * chroma_height); - deshake->opencl_ctx.out_plane_size[2] = (out->linesize[2] * chroma_height); - deshake->opencl_ctx.cl_inbuf_size = deshake->opencl_ctx.in_plane_size[0] + - deshake->opencl_ctx.in_plane_size[1] + - deshake->opencl_ctx.in_plane_size[2]; - deshake->opencl_ctx.cl_outbuf_size = deshake->opencl_ctx.out_plane_size[0] + - deshake->opencl_ctx.out_plane_size[1] + - deshake->opencl_ctx.out_plane_size[2]; - if (!deshake->opencl_ctx.cl_inbuf) { - ret = av_opencl_buffer_create(&deshake->opencl_ctx.cl_inbuf, - deshake->opencl_ctx.cl_inbuf_size, - CL_MEM_READ_ONLY, NULL); - if (ret < 0) - return ret; - } - if (!deshake->opencl_ctx.cl_outbuf) { - ret = av_opencl_buffer_create(&deshake->opencl_ctx.cl_outbuf, - deshake->opencl_ctx.cl_outbuf_size, - CL_MEM_READ_WRITE, NULL); - if (ret < 0) - return ret; - } - } - ret = av_opencl_buffer_write_image(deshake->opencl_ctx.cl_inbuf, - deshake->opencl_ctx.cl_inbuf_size, - 0, in->data,deshake->opencl_ctx.in_plane_size, - deshake->opencl_ctx.plane_num); - return ret; -} diff --git a/libavfilter/deshake_opencl.h b/libavfilter/deshake_opencl.h deleted file mode 100644 index f3d96dc4e90f3..0000000000000 --- a/libavfilter/deshake_opencl.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 Wei Gao - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVFILTER_DESHAKE_OPENCL_H -#define AVFILTER_DESHAKE_OPENCL_H - -#include "deshake.h" - -typedef struct float4 { - float x; - float y; - float z; - float w; -} float4; - -int ff_opencl_deshake_init(AVFilterContext *ctx); - -void ff_opencl_deshake_uninit(AVFilterContext *ctx); - -int ff_opencl_deshake_process_inout_buf(AVFilterContext *ctx, AVFrame *in, AVFrame *out); - -int ff_opencl_transform(AVFilterContext *ctx, - int width, int height, int cw, int ch, - const float *matrix_y, const float *matrix_uv, - enum InterpolateMethod interpolate, - enum FillMethod fill, AVFrame *in, AVFrame *out); - -#endif /* AVFILTER_DESHAKE_OPENCL_H */ diff --git a/libavfilter/deshake_opencl_kernel.h b/libavfilter/deshake_opencl_kernel.h deleted file mode 100644 index dd45d6f60bab2..0000000000000 --- a/libavfilter/deshake_opencl_kernel.h +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2013 Wei Gao - * Copyright (C) 2013 Lenny Wang - * - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVFILTER_DESHAKE_OPENCL_KERNEL_H -#define AVFILTER_DESHAKE_OPENCL_KERNEL_H - -#include "libavutil/opencl.h" - -const char *ff_kernel_deshake_opencl = AV_OPENCL_KERNEL( -inline unsigned char pixel(global const unsigned char *src, int x, int y, - int w, int h,int stride, unsigned char def) -{ - return (x < 0 || y < 0 || x >= w || y >= h) ? def : src[x + y * stride]; -} - -unsigned char interpolate_nearest(float x, float y, global const unsigned char *src, - int width, int height, int stride, unsigned char def) -{ - return pixel(src, (int)(x + 0.5f), (int)(y + 0.5f), width, height, stride, def); -} - -unsigned char interpolate_bilinear(float x, float y, global const unsigned char *src, - int width, int height, int stride, unsigned char def) -{ - int x_c, x_f, y_c, y_f; - int v1, v2, v3, v4; - x_f = (int)x; - y_f = (int)y; - x_c = x_f + 1; - y_c = y_f + 1; - - if (x_f < -1 || x_f > width || y_f < -1 || y_f > height) { - return def; - } else { - v4 = pixel(src, x_f, y_f, width, height, stride, def); - v2 = pixel(src, x_c, y_f, width, height, stride, def); - v3 = pixel(src, x_f, y_c, width, height, stride, def); - v1 = pixel(src, x_c, y_c, width, height, stride, def); - return (v1*(x - x_f)*(y - y_f) + v2*((x - x_f)*(y_c - y)) + - v3*(x_c - x)*(y - y_f) + v4*((x_c - x)*(y_c - y))); - } -} - -unsigned char interpolate_biquadratic(float x, float y, global const unsigned char *src, - int width, int height, int stride, unsigned char def) -{ - int x_c, x_f, y_c, y_f; - unsigned char v1, v2, v3, v4; - float f1, f2, f3, f4; - x_f = (int)x; - y_f = (int)y; - x_c = x_f + 1; - y_c = y_f + 1; - - if (x_f < - 1 || x_f > width || y_f < -1 || y_f > height) - return def; - else { - v4 = pixel(src, x_f, y_f, width, height, stride, def); - v2 = pixel(src, x_c, y_f, width, height, stride, def); - v3 = pixel(src, x_f, y_c, width, height, stride, def); - v1 = pixel(src, x_c, y_c, width, height, stride, def); - - f1 = 1 - sqrt((x_c - x) * (y_c - y)); - f2 = 1 - sqrt((x_c - x) * (y - y_f)); - f3 = 1 - sqrt((x - x_f) * (y_c - y)); - f4 = 1 - sqrt((x - x_f) * (y - y_f)); - return (v1 * f1 + v2 * f2 + v3 * f3 + v4 * f4) / (f1 + f2 + f3 + f4); - } -} - -inline const float clipf(float a, float amin, float amax) -{ - if (a < amin) return amin; - else if (a > amax) return amax; - else return a; -} - -inline int mirror(int v, int m) -{ - while ((unsigned)v > (unsigned)m) { - v = -v; - if (v < 0) - v += 2 * m; - } - return v; -} - -kernel void avfilter_transform_luma(global unsigned char *src, - global unsigned char *dst, - float4 matrix, - int interpolate, - int fill, - int src_stride_lu, - int dst_stride_lu, - int height, - int width) -{ - int x = get_global_id(0); - int y = get_global_id(1); - int idx_dst = y * dst_stride_lu + x; - unsigned char def = 0; - float x_s = x * matrix.x + y * matrix.y + matrix.z; - float y_s = x * (-matrix.y) + y * matrix.x + matrix.w; - - if (x < width && y < height) { - switch (fill) { - case 0: //FILL_BLANK - def = 0; - break; - case 1: //FILL_ORIGINAL - def = src[y*src_stride_lu + x]; - break; - case 2: //FILL_CLAMP - y_s = clipf(y_s, 0, height - 1); - x_s = clipf(x_s, 0, width - 1); - def = src[(int)y_s * src_stride_lu + (int)x_s]; - break; - case 3: //FILL_MIRROR - y_s = mirror(y_s, height - 1); - x_s = mirror(x_s, width - 1); - def = src[(int)y_s * src_stride_lu + (int)x_s]; - break; - } - switch (interpolate) { - case 0: //INTERPOLATE_NEAREST - dst[idx_dst] = interpolate_nearest(x_s, y_s, src, width, height, src_stride_lu, def); - break; - case 1: //INTERPOLATE_BILINEAR - dst[idx_dst] = interpolate_bilinear(x_s, y_s, src, width, height, src_stride_lu, def); - break; - case 2: //INTERPOLATE_BIQUADRATIC - dst[idx_dst] = interpolate_biquadratic(x_s, y_s, src, width, height, src_stride_lu, def); - break; - default: - return; - } - } -} - -kernel void avfilter_transform_chroma(global unsigned char *src, - global unsigned char *dst, - float4 matrix, - int interpolate, - int fill, - int src_stride_lu, - int dst_stride_lu, - int src_stride_ch, - int dst_stride_ch, - int height, - int width, - int ch, - int cw) -{ - - int x = get_global_id(0); - int y = get_global_id(1); - int pad_ch = get_global_size(1)>>1; - global unsigned char *dst_u = dst + height * dst_stride_lu; - global unsigned char *src_u = src + height * src_stride_lu; - global unsigned char *dst_v = dst_u + ch * dst_stride_ch; - global unsigned char *src_v = src_u + ch * src_stride_ch; - src = y < pad_ch ? src_u : src_v; - dst = y < pad_ch ? dst_u : dst_v; - y = select(y - pad_ch, y, y < pad_ch); - float x_s = x * matrix.x + y * matrix.y + matrix.z; - float y_s = x * (-matrix.y) + y * matrix.x + matrix.w; - int idx_dst = y * dst_stride_ch + x; - unsigned char def; - - if (x < cw && y < ch) { - switch (fill) { - case 0: //FILL_BLANK - def = 0; - break; - case 1: //FILL_ORIGINAL - def = src[y*src_stride_ch + x]; - break; - case 2: //FILL_CLAMP - y_s = clipf(y_s, 0, ch - 1); - x_s = clipf(x_s, 0, cw - 1); - def = src[(int)y_s * src_stride_ch + (int)x_s]; - break; - case 3: //FILL_MIRROR - y_s = mirror(y_s, ch - 1); - x_s = mirror(x_s, cw - 1); - def = src[(int)y_s * src_stride_ch + (int)x_s]; - break; - } - switch (interpolate) { - case 0: //INTERPOLATE_NEAREST - dst[idx_dst] = interpolate_nearest(x_s, y_s, src, cw, ch, src_stride_ch, def); - break; - case 1: //INTERPOLATE_BILINEAR - dst[idx_dst] = interpolate_bilinear(x_s, y_s, src, cw, ch, src_stride_ch, def); - break; - case 2: //INTERPOLATE_BIQUADRATIC - dst[idx_dst] = interpolate_biquadratic(x_s, y_s, src, cw, ch, src_stride_ch, def); - break; - default: - return; - } - } -} -); - -#endif /* AVFILTER_DESHAKE_OPENCL_KERNEL_H */ diff --git a/libavfilter/opencl_allkernels.c b/libavfilter/opencl_allkernels.c deleted file mode 100644 index 6d80fa859838b..0000000000000 --- a/libavfilter/opencl_allkernels.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 Wei Gao - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "opencl_allkernels.h" -#if CONFIG_OPENCL -#include "libavutil/opencl.h" -#include "deshake_opencl_kernel.h" -#include "unsharp_opencl_kernel.h" -#endif - -#define OPENCL_REGISTER_KERNEL_CODE(X, x) \ - { \ - if (CONFIG_##X##_FILTER) { \ - av_opencl_register_kernel_code(ff_kernel_##x##_opencl); \ - } \ - } - -void ff_opencl_register_filter_kernel_code_all(void) -{ - #if CONFIG_OPENCL - OPENCL_REGISTER_KERNEL_CODE(DESHAKE, deshake); - OPENCL_REGISTER_KERNEL_CODE(UNSHARP, unsharp); - #endif -} diff --git a/libavfilter/opencl_allkernels.h b/libavfilter/opencl_allkernels.h deleted file mode 100644 index 57b650d27bec9..0000000000000 --- a/libavfilter/opencl_allkernels.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2013 Wei Gao - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVFILTER_OPENCL_ALLKERNELS_H -#define AVFILTER_OPENCL_ALLKERNELS_H - -#include "avfilter.h" -#include "config.h" - -void ff_opencl_register_filter_kernel_code_all(void); - -#endif /* AVFILTER_OPENCL_ALLKERNELS_H */ diff --git a/libavfilter/unsharp.h b/libavfilter/unsharp.h index 340a6a0caf41b..caff986fc1bd5 100644 --- a/libavfilter/unsharp.h +++ b/libavfilter/unsharp.h @@ -24,38 +24,10 @@ #include "config.h" #include "avfilter.h" -#if CONFIG_OPENCL -#include "libavutil/opencl.h" -#endif #define MIN_MATRIX_SIZE 3 #define MAX_MATRIX_SIZE 63 -#if CONFIG_OPENCL - -typedef struct UnsharpOpenclContext { - cl_command_queue command_queue; - cl_program program; - cl_kernel kernel_default; - cl_kernel kernel_luma; - cl_kernel kernel_chroma; - cl_mem cl_luma_mask; - cl_mem cl_chroma_mask; - cl_mem cl_luma_mask_x; - cl_mem cl_chroma_mask_x; - cl_mem cl_luma_mask_y; - cl_mem cl_chroma_mask_y; - int in_plane_size[8]; - int out_plane_size[8]; - int plane_num; - cl_mem cl_inbuf; - size_t cl_inbuf_size; - cl_mem cl_outbuf; - size_t cl_outbuf_size; - int use_fast_kernels; -} UnsharpOpenclContext; - -#endif typedef struct UnsharpFilterParam { int msize_x; ///< matrix width @@ -76,9 +48,6 @@ typedef struct UnsharpContext { UnsharpFilterParam chroma; ///< chroma parameters (width, height, amount) int hsub, vsub; int opencl; -#if CONFIG_OPENCL - UnsharpOpenclContext opencl_ctx; -#endif int (* apply_unsharp)(AVFilterContext *ctx, AVFrame *in, AVFrame *out); } UnsharpContext; diff --git a/libavfilter/unsharp_opencl.c b/libavfilter/unsharp_opencl.c deleted file mode 100644 index 15454558465fa..0000000000000 --- a/libavfilter/unsharp_opencl.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (C) 2013 Wei Gao - * Copyright (C) 2013 Lenny Wang - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * unsharp input video - */ - -#include "unsharp_opencl.h" -#include "libavutil/common.h" -#include "libavutil/opencl_internal.h" - -#define PLANE_NUM 3 -#define ROUND_TO_16(a) (((((a) - 1)/16)+1)*16) - -static inline void add_mask_counter(uint32_t *dst, uint32_t *counter1, uint32_t *counter2, int len) -{ - int i; - for (i = 0; i < len; i++) { - dst[i] = counter1[i] + counter2[i]; - } -} - -static int compute_mask(int step, uint32_t *mask) -{ - int i, z, ret = 0; - int counter_size = sizeof(uint32_t) * (2 * step + 1); - uint32_t *temp1_counter, *temp2_counter, **counter = NULL; - temp1_counter = av_mallocz(counter_size); - if (!temp1_counter) { - ret = AVERROR(ENOMEM); - goto end; - } - temp2_counter = av_mallocz(counter_size); - if (!temp2_counter) { - ret = AVERROR(ENOMEM); - goto end; - } - counter = av_mallocz_array(2 * step + 1, sizeof(uint32_t *)); - if (!counter) { - ret = AVERROR(ENOMEM); - goto end; - } - for (i = 0; i < 2 * step + 1; i++) { - counter[i] = av_mallocz(counter_size); - if (!counter[i]) { - ret = AVERROR(ENOMEM); - goto end; - } - } - for (i = 0; i < 2 * step + 1; i++) { - memset(temp1_counter, 0, counter_size); - temp1_counter[i] = 1; - for (z = 0; z < step * 2; z += 2) { - add_mask_counter(temp2_counter, counter[z], temp1_counter, step * 2); - memcpy(counter[z], temp1_counter, counter_size); - add_mask_counter(temp1_counter, counter[z + 1], temp2_counter, step * 2); - memcpy(counter[z + 1], temp2_counter, counter_size); - } - } - memcpy(mask, temp1_counter, counter_size); -end: - av_freep(&temp1_counter); - av_freep(&temp2_counter); - for (i = 0; counter && i < 2 * step + 1; i++) { - av_freep(&counter[i]); - } - av_freep(&counter); - return ret; -} - -static int copy_separable_masks(cl_mem cl_mask_x, cl_mem cl_mask_y, int step_x, int step_y) -{ - int ret = 0; - uint32_t *mask_x, *mask_y; - size_t size_mask_x = sizeof(uint32_t) * (2 * step_x + 1); - size_t size_mask_y = sizeof(uint32_t) * (2 * step_y + 1); - mask_x = av_mallocz_array(2 * step_x + 1, sizeof(uint32_t)); - if (!mask_x) { - ret = AVERROR(ENOMEM); - goto end; - } - mask_y = av_mallocz_array(2 * step_y + 1, sizeof(uint32_t)); - if (!mask_y) { - ret = AVERROR(ENOMEM); - goto end; - } - - ret = compute_mask(step_x, mask_x); - if (ret < 0) - goto end; - ret = compute_mask(step_y, mask_y); - if (ret < 0) - goto end; - - ret = av_opencl_buffer_write(cl_mask_x, (uint8_t *)mask_x, size_mask_x); - ret = av_opencl_buffer_write(cl_mask_y, (uint8_t *)mask_y, size_mask_y); -end: - av_freep(&mask_x); - av_freep(&mask_y); - - return ret; -} - -static int generate_mask(AVFilterContext *ctx) -{ - cl_mem masks[4]; - cl_mem mask_matrix[2]; - int i, ret = 0, step_x[2], step_y[2]; - - UnsharpContext *unsharp = ctx->priv; - mask_matrix[0] = unsharp->opencl_ctx.cl_luma_mask; - mask_matrix[1] = unsharp->opencl_ctx.cl_chroma_mask; - masks[0] = unsharp->opencl_ctx.cl_luma_mask_x; - masks[1] = unsharp->opencl_ctx.cl_luma_mask_y; - masks[2] = unsharp->opencl_ctx.cl_chroma_mask_x; - masks[3] = unsharp->opencl_ctx.cl_chroma_mask_y; - step_x[0] = unsharp->luma.steps_x; - step_x[1] = unsharp->chroma.steps_x; - step_y[0] = unsharp->luma.steps_y; - step_y[1] = unsharp->chroma.steps_y; - - /* use default kernel if any matrix dim larger than 8 due to limited local mem size */ - if (step_x[0]>8 || step_x[1]>8 || step_y[0]>8 || step_y[1]>8) - unsharp->opencl_ctx.use_fast_kernels = 0; - else - unsharp->opencl_ctx.use_fast_kernels = 1; - - if (!masks[0] || !masks[1] || !masks[2] || !masks[3]) { - av_log(ctx, AV_LOG_ERROR, "Luma mask and chroma mask should not be NULL\n"); - return AVERROR(EINVAL); - } - if (!mask_matrix[0] || !mask_matrix[1]) { - av_log(ctx, AV_LOG_ERROR, "Luma mask and chroma mask should not be NULL\n"); - return AVERROR(EINVAL); - } - for (i = 0; i < 2; i++) { - ret = copy_separable_masks(masks[2*i], masks[2*i+1], step_x[i], step_y[i]); - if (ret < 0) - return ret; - } - return ret; -} - -int ff_opencl_apply_unsharp(AVFilterContext *ctx, AVFrame *in, AVFrame *out) -{ - int ret; - AVFilterLink *link = ctx->inputs[0]; - UnsharpContext *unsharp = ctx->priv; - cl_int status; - FFOpenclParam kernel1 = {0}; - FFOpenclParam kernel2 = {0}; - int width = link->w; - int height = link->h; - int cw = AV_CEIL_RSHIFT(link->w, unsharp->hsub); - int ch = AV_CEIL_RSHIFT(link->h, unsharp->vsub); - size_t globalWorkSize1d = width * height + 2 * ch * cw; - size_t globalWorkSize2dLuma[2]; - size_t globalWorkSize2dChroma[2]; - size_t localWorkSize2d[2] = {16, 16}; - - if (unsharp->opencl_ctx.use_fast_kernels) { - globalWorkSize2dLuma[0] = (size_t)ROUND_TO_16(width); - globalWorkSize2dLuma[1] = (size_t)ROUND_TO_16(height); - globalWorkSize2dChroma[0] = (size_t)ROUND_TO_16(cw); - globalWorkSize2dChroma[1] = (size_t)(2*ROUND_TO_16(ch)); - - kernel1.ctx = ctx; - kernel1.kernel = unsharp->opencl_ctx.kernel_luma; - ret = avpriv_opencl_set_parameter(&kernel1, - FF_OPENCL_PARAM_INFO(unsharp->opencl_ctx.cl_inbuf), - FF_OPENCL_PARAM_INFO(unsharp->opencl_ctx.cl_outbuf), - FF_OPENCL_PARAM_INFO(unsharp->opencl_ctx.cl_luma_mask_x), - FF_OPENCL_PARAM_INFO(unsharp->opencl_ctx.cl_luma_mask_y), - FF_OPENCL_PARAM_INFO(unsharp->luma.amount), - FF_OPENCL_PARAM_INFO(unsharp->luma.scalebits), - FF_OPENCL_PARAM_INFO(unsharp->luma.halfscale), - FF_OPENCL_PARAM_INFO(in->linesize[0]), - FF_OPENCL_PARAM_INFO(out->linesize[0]), - FF_OPENCL_PARAM_INFO(width), - FF_OPENCL_PARAM_INFO(height), - NULL); - if (ret < 0) - return ret; - - kernel2.ctx = ctx; - kernel2.kernel = unsharp->opencl_ctx.kernel_chroma; - ret = avpriv_opencl_set_parameter(&kernel2, - FF_OPENCL_PARAM_INFO(unsharp->opencl_ctx.cl_inbuf), - FF_OPENCL_PARAM_INFO(unsharp->opencl_ctx.cl_outbuf), - FF_OPENCL_PARAM_INFO(unsharp->opencl_ctx.cl_chroma_mask_x), - FF_OPENCL_PARAM_INFO(unsharp->opencl_ctx.cl_chroma_mask_y), - FF_OPENCL_PARAM_INFO(unsharp->chroma.amount), - FF_OPENCL_PARAM_INFO(unsharp->chroma.scalebits), - FF_OPENCL_PARAM_INFO(unsharp->chroma.halfscale), - FF_OPENCL_PARAM_INFO(in->linesize[0]), - FF_OPENCL_PARAM_INFO(in->linesize[1]), - FF_OPENCL_PARAM_INFO(out->linesize[0]), - FF_OPENCL_PARAM_INFO(out->linesize[1]), - FF_OPENCL_PARAM_INFO(link->w), - FF_OPENCL_PARAM_INFO(link->h), - FF_OPENCL_PARAM_INFO(cw), - FF_OPENCL_PARAM_INFO(ch), - NULL); - if (ret < 0) - return ret; - status = clEnqueueNDRangeKernel(unsharp->opencl_ctx.command_queue, - unsharp->opencl_ctx.kernel_luma, 2, NULL, - globalWorkSize2dLuma, localWorkSize2d, 0, NULL, NULL); - status |=clEnqueueNDRangeKernel(unsharp->opencl_ctx.command_queue, - unsharp->opencl_ctx.kernel_chroma, 2, NULL, - globalWorkSize2dChroma, localWorkSize2d, 0, NULL, NULL); - if (status != CL_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "OpenCL run kernel error occurred: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - } else { /* use default kernel */ - kernel1.ctx = ctx; - kernel1.kernel = unsharp->opencl_ctx.kernel_default; - - ret = avpriv_opencl_set_parameter(&kernel1, - FF_OPENCL_PARAM_INFO(unsharp->opencl_ctx.cl_inbuf), - FF_OPENCL_PARAM_INFO(unsharp->opencl_ctx.cl_outbuf), - FF_OPENCL_PARAM_INFO(unsharp->opencl_ctx.cl_luma_mask), - FF_OPENCL_PARAM_INFO(unsharp->opencl_ctx.cl_chroma_mask), - FF_OPENCL_PARAM_INFO(unsharp->luma.amount), - FF_OPENCL_PARAM_INFO(unsharp->chroma.amount), - FF_OPENCL_PARAM_INFO(unsharp->luma.steps_x), - FF_OPENCL_PARAM_INFO(unsharp->luma.steps_y), - FF_OPENCL_PARAM_INFO(unsharp->chroma.steps_x), - FF_OPENCL_PARAM_INFO(unsharp->chroma.steps_y), - FF_OPENCL_PARAM_INFO(unsharp->luma.scalebits), - FF_OPENCL_PARAM_INFO(unsharp->chroma.scalebits), - FF_OPENCL_PARAM_INFO(unsharp->luma.halfscale), - FF_OPENCL_PARAM_INFO(unsharp->chroma.halfscale), - FF_OPENCL_PARAM_INFO(in->linesize[0]), - FF_OPENCL_PARAM_INFO(in->linesize[1]), - FF_OPENCL_PARAM_INFO(out->linesize[0]), - FF_OPENCL_PARAM_INFO(out->linesize[1]), - FF_OPENCL_PARAM_INFO(link->h), - FF_OPENCL_PARAM_INFO(link->w), - FF_OPENCL_PARAM_INFO(ch), - FF_OPENCL_PARAM_INFO(cw), - NULL); - if (ret < 0) - return ret; - status = clEnqueueNDRangeKernel(unsharp->opencl_ctx.command_queue, - unsharp->opencl_ctx.kernel_default, 1, NULL, - &globalWorkSize1d, NULL, 0, NULL, NULL); - if (status != CL_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "OpenCL run kernel error occurred: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - } - //blocking map is suffficient, no need for clFinish - //clFinish(unsharp->opencl_ctx.command_queue); - - return av_opencl_buffer_read_image(out->data, unsharp->opencl_ctx.out_plane_size, - unsharp->opencl_ctx.plane_num, unsharp->opencl_ctx.cl_outbuf, - unsharp->opencl_ctx.cl_outbuf_size); -} - -int ff_opencl_unsharp_init(AVFilterContext *ctx) -{ - int ret = 0; - char build_opts[96]; - UnsharpContext *unsharp = ctx->priv; - ret = av_opencl_init(NULL); - if (ret < 0) - return ret; - ret = av_opencl_buffer_create(&unsharp->opencl_ctx.cl_luma_mask, - sizeof(uint32_t) * (2 * unsharp->luma.steps_x + 1) * (2 * unsharp->luma.steps_y + 1), - CL_MEM_READ_ONLY, NULL); - if (ret < 0) - return ret; - ret = av_opencl_buffer_create(&unsharp->opencl_ctx.cl_chroma_mask, - sizeof(uint32_t) * (2 * unsharp->chroma.steps_x + 1) * (2 * unsharp->chroma.steps_y + 1), - CL_MEM_READ_ONLY, NULL); - // separable filters - if (ret < 0) - return ret; - ret = av_opencl_buffer_create(&unsharp->opencl_ctx.cl_luma_mask_x, - sizeof(uint32_t) * (2 * unsharp->luma.steps_x + 1), - CL_MEM_READ_ONLY, NULL); - if (ret < 0) - return ret; - ret = av_opencl_buffer_create(&unsharp->opencl_ctx.cl_luma_mask_y, - sizeof(uint32_t) * (2 * unsharp->luma.steps_y + 1), - CL_MEM_READ_ONLY, NULL); - if (ret < 0) - return ret; - ret = av_opencl_buffer_create(&unsharp->opencl_ctx.cl_chroma_mask_x, - sizeof(uint32_t) * (2 * unsharp->chroma.steps_x + 1), - CL_MEM_READ_ONLY, NULL); - if (ret < 0) - return ret; - ret = av_opencl_buffer_create(&unsharp->opencl_ctx.cl_chroma_mask_y, - sizeof(uint32_t) * (2 * unsharp->chroma.steps_y + 1), - CL_MEM_READ_ONLY, NULL); - if (ret < 0) - return ret; - ret = generate_mask(ctx); - if (ret < 0) - return ret; - unsharp->opencl_ctx.plane_num = PLANE_NUM; - unsharp->opencl_ctx.command_queue = av_opencl_get_command_queue(); - if (!unsharp->opencl_ctx.command_queue) { - av_log(ctx, AV_LOG_ERROR, "Unable to get OpenCL command queue in filter 'unsharp'\n"); - return AVERROR(EINVAL); - } - snprintf(build_opts, 96, "-D LU_RADIUS_X=%d -D LU_RADIUS_Y=%d -D CH_RADIUS_X=%d -D CH_RADIUS_Y=%d", - 2*unsharp->luma.steps_x+1, 2*unsharp->luma.steps_y+1, 2*unsharp->chroma.steps_x+1, 2*unsharp->chroma.steps_y+1); - unsharp->opencl_ctx.program = av_opencl_compile("unsharp", build_opts); - if (!unsharp->opencl_ctx.program) { - av_log(ctx, AV_LOG_ERROR, "OpenCL failed to compile program 'unsharp'\n"); - return AVERROR(EINVAL); - } - if (unsharp->opencl_ctx.use_fast_kernels) { - if (!unsharp->opencl_ctx.kernel_luma) { - unsharp->opencl_ctx.kernel_luma = clCreateKernel(unsharp->opencl_ctx.program, "unsharp_luma", &ret); - if (ret != CL_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "OpenCL failed to create kernel 'unsharp_luma'\n"); - return ret; - } - } - if (!unsharp->opencl_ctx.kernel_chroma) { - unsharp->opencl_ctx.kernel_chroma = clCreateKernel(unsharp->opencl_ctx.program, "unsharp_chroma", &ret); - if (ret < 0) { - av_log(ctx, AV_LOG_ERROR, "OpenCL failed to create kernel 'unsharp_chroma'\n"); - return ret; - } - } - } - else { - if (!unsharp->opencl_ctx.kernel_default) { - unsharp->opencl_ctx.kernel_default = clCreateKernel(unsharp->opencl_ctx.program, "unsharp_default", &ret); - if (ret < 0) { - av_log(ctx, AV_LOG_ERROR, "OpenCL failed to create kernel 'unsharp_default'\n"); - return ret; - } - } - } - return ret; -} - -void ff_opencl_unsharp_uninit(AVFilterContext *ctx) -{ - UnsharpContext *unsharp = ctx->priv; - av_opencl_buffer_release(&unsharp->opencl_ctx.cl_inbuf); - av_opencl_buffer_release(&unsharp->opencl_ctx.cl_outbuf); - av_opencl_buffer_release(&unsharp->opencl_ctx.cl_luma_mask); - av_opencl_buffer_release(&unsharp->opencl_ctx.cl_chroma_mask); - av_opencl_buffer_release(&unsharp->opencl_ctx.cl_luma_mask_x); - av_opencl_buffer_release(&unsharp->opencl_ctx.cl_chroma_mask_x); - av_opencl_buffer_release(&unsharp->opencl_ctx.cl_luma_mask_y); - av_opencl_buffer_release(&unsharp->opencl_ctx.cl_chroma_mask_y); - clReleaseKernel(unsharp->opencl_ctx.kernel_default); - clReleaseKernel(unsharp->opencl_ctx.kernel_luma); - clReleaseKernel(unsharp->opencl_ctx.kernel_chroma); - clReleaseProgram(unsharp->opencl_ctx.program); - unsharp->opencl_ctx.command_queue = NULL; - av_opencl_uninit(); -} - -int ff_opencl_unsharp_process_inout_buf(AVFilterContext *ctx, AVFrame *in, AVFrame *out) -{ - int ret = 0; - AVFilterLink *link = ctx->inputs[0]; - UnsharpContext *unsharp = ctx->priv; - int ch = AV_CEIL_RSHIFT(link->h, unsharp->vsub); - - if ((!unsharp->opencl_ctx.cl_inbuf) || (!unsharp->opencl_ctx.cl_outbuf)) { - unsharp->opencl_ctx.in_plane_size[0] = (in->linesize[0] * in->height); - unsharp->opencl_ctx.in_plane_size[1] = (in->linesize[1] * ch); - unsharp->opencl_ctx.in_plane_size[2] = (in->linesize[2] * ch); - unsharp->opencl_ctx.out_plane_size[0] = (out->linesize[0] * out->height); - unsharp->opencl_ctx.out_plane_size[1] = (out->linesize[1] * ch); - unsharp->opencl_ctx.out_plane_size[2] = (out->linesize[2] * ch); - unsharp->opencl_ctx.cl_inbuf_size = unsharp->opencl_ctx.in_plane_size[0] + - unsharp->opencl_ctx.in_plane_size[1] + - unsharp->opencl_ctx.in_plane_size[2]; - unsharp->opencl_ctx.cl_outbuf_size = unsharp->opencl_ctx.out_plane_size[0] + - unsharp->opencl_ctx.out_plane_size[1] + - unsharp->opencl_ctx.out_plane_size[2]; - if (!unsharp->opencl_ctx.cl_inbuf) { - ret = av_opencl_buffer_create(&unsharp->opencl_ctx.cl_inbuf, - unsharp->opencl_ctx.cl_inbuf_size, - CL_MEM_READ_ONLY, NULL); - if (ret < 0) - return ret; - } - if (!unsharp->opencl_ctx.cl_outbuf) { - ret = av_opencl_buffer_create(&unsharp->opencl_ctx.cl_outbuf, - unsharp->opencl_ctx.cl_outbuf_size, - CL_MEM_READ_WRITE, NULL); - if (ret < 0) - return ret; - } - } - return av_opencl_buffer_write_image(unsharp->opencl_ctx.cl_inbuf, - unsharp->opencl_ctx.cl_inbuf_size, - 0, in->data, unsharp->opencl_ctx.in_plane_size, - unsharp->opencl_ctx.plane_num); -} diff --git a/libavfilter/unsharp_opencl.h b/libavfilter/unsharp_opencl.h deleted file mode 100644 index 3aefab62e00e1..0000000000000 --- a/libavfilter/unsharp_opencl.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2013 Wei Gao - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVFILTER_UNSHARP_OPENCL_H -#define AVFILTER_UNSHARP_OPENCL_H - -#include "unsharp.h" - -int ff_opencl_unsharp_init(AVFilterContext *ctx); - -void ff_opencl_unsharp_uninit(AVFilterContext *ctx); - -int ff_opencl_unsharp_process_inout_buf(AVFilterContext *ctx, AVFrame *in, AVFrame *out); - -int ff_opencl_apply_unsharp(AVFilterContext *ctx, AVFrame *in, AVFrame *out); - -#endif /* AVFILTER_UNSHARP_OPENCL_H */ diff --git a/libavfilter/unsharp_opencl_kernel.h b/libavfilter/unsharp_opencl_kernel.h deleted file mode 100644 index 307d0f1814ca8..0000000000000 --- a/libavfilter/unsharp_opencl_kernel.h +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (C) 2013 Wei Gao - * Copyright (C) 2013 Lenny Wang - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVFILTER_UNSHARP_OPENCL_KERNEL_H -#define AVFILTER_UNSHARP_OPENCL_KERNEL_H - -#include "libavutil/opencl.h" - -const char *ff_kernel_unsharp_opencl = AV_OPENCL_KERNEL( -inline unsigned char clip_uint8(int a) -{ - if (a & (~0xFF)) - return (-a)>>31; - else - return a; -} - -kernel void unsharp_luma( - global unsigned char *src, - global unsigned char *dst, - global int *mask_x, - global int *mask_y, - int amount, - int scalebits, - int halfscale, - int src_stride, - int dst_stride, - int width, - int height) -{ - int2 threadIdx, blockIdx, globalIdx; - threadIdx.x = get_local_id(0); - threadIdx.y = get_local_id(1); - blockIdx.x = get_group_id(0); - blockIdx.y = get_group_id(1); - globalIdx.x = get_global_id(0); - globalIdx.y = get_global_id(1); - - if (!amount) { - if (globalIdx.x < width && globalIdx.y < height) - dst[globalIdx.x + globalIdx.y*dst_stride] = src[globalIdx.x + globalIdx.y*src_stride]; - return; - } - - local unsigned int l[32][32]; - local unsigned int lcx[LU_RADIUS_X]; - local unsigned int lcy[LU_RADIUS_Y]; - int indexIx, indexIy, i, j; - - //load up tile: actual workspace + halo of 8 points in x and y \n - for(i = 0; i <= 1; i++) { - indexIy = -8 + (blockIdx.y + i) * 16 + threadIdx.y; - indexIy = indexIy < 0 ? 0 : indexIy; - indexIy = indexIy >= height ? height - 1: indexIy; - for(j = 0; j <= 1; j++) { - indexIx = -8 + (blockIdx.x + j) * 16 + threadIdx.x; - indexIx = indexIx < 0 ? 0 : indexIx; - indexIx = indexIx >= width ? width - 1: indexIx; - l[i*16 + threadIdx.y][j*16 + threadIdx.x] = src[indexIy*src_stride + indexIx]; - } - } - - int indexL = threadIdx.y*16 + threadIdx.x; - if (indexL < LU_RADIUS_X) - lcx[indexL] = mask_x[indexL]; - if (indexL < LU_RADIUS_Y) - lcy[indexL] = mask_y[indexL]; - barrier(CLK_LOCAL_MEM_FENCE); - - //needed for unsharp mask application in the end \n - int orig_value = (int)l[threadIdx.y + 8][threadIdx.x + 8]; - - int idx, idy, maskIndex; - int temp[2] = {0}; - int steps_x = (LU_RADIUS_X-1)/2; - int steps_y = (LU_RADIUS_Y-1)/2; - - // compute the actual workspace + left&right halos \n - \n#pragma unroll\n - for (j = 0; j <=1; j++) { - //extra work to cover left and right halos \n - idx = 16*j + threadIdx.x; - \n#pragma unroll\n - for (i = -steps_y; i <= steps_y; i++) { - idy = 8 + i + threadIdx.y; - maskIndex = (i + steps_y); - temp[j] += (int)l[idy][idx] * lcy[maskIndex]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - //save results from the vertical filter in local memory \n - idy = 8 + threadIdx.y; - \n#pragma unroll\n - for (j = 0; j <=1; j++) { - idx = 16*j + threadIdx.x; - l[idy][idx] = temp[j]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - //compute results with the horizontal filter \n - int sum = 0; - idy = 8 + threadIdx.y; - \n#pragma unroll\n - for (j = -steps_x; j <= steps_x; j++) { - idx = 8 + j + threadIdx.x; - maskIndex = j + steps_x; - sum += (int)l[idy][idx] * lcx[maskIndex]; - } - - int res = orig_value + (((orig_value - (int)((sum + halfscale) >> scalebits)) * amount) >> 16); - - if (globalIdx.x < width && globalIdx.y < height) - dst[globalIdx.x + globalIdx.y*dst_stride] = clip_uint8(res); -} - -kernel void unsharp_chroma( - global unsigned char *src_y, - global unsigned char *dst_y, - global int *mask_x, - global int *mask_y, - int amount, - int scalebits, - int halfscale, - int src_stride_lu, - int src_stride_ch, - int dst_stride_lu, - int dst_stride_ch, - int width, - int height, - int cw, - int ch) -{ - global unsigned char *dst_u = dst_y + height * dst_stride_lu; - global unsigned char *dst_v = dst_u + ch * dst_stride_ch; - global unsigned char *src_u = src_y + height * src_stride_lu; - global unsigned char *src_v = src_u + ch * src_stride_ch; - int2 threadIdx, blockIdx, globalIdx; - threadIdx.x = get_local_id(0); - threadIdx.y = get_local_id(1); - blockIdx.x = get_group_id(0); - blockIdx.y = get_group_id(1); - globalIdx.x = get_global_id(0); - globalIdx.y = get_global_id(1); - int padch = get_global_size(1)/2; - global unsigned char *src = globalIdx.y>=padch ? src_v : src_u; - global unsigned char *dst = globalIdx.y>=padch ? dst_v : dst_u; - - blockIdx.y = globalIdx.y>=padch ? blockIdx.y - get_num_groups(1)/2 : blockIdx.y; - globalIdx.y = globalIdx.y>=padch ? globalIdx.y - padch : globalIdx.y; - - if (!amount) { - if (globalIdx.x < cw && globalIdx.y < ch) - dst[globalIdx.x + globalIdx.y*dst_stride_ch] = src[globalIdx.x + globalIdx.y*src_stride_ch]; - return; - } - - local unsigned int l[32][32]; - local unsigned int lcx[CH_RADIUS_X]; - local unsigned int lcy[CH_RADIUS_Y]; - int indexIx, indexIy, i, j; - for(i = 0; i <= 1; i++) { - indexIy = -8 + (blockIdx.y + i) * 16 + threadIdx.y; - indexIy = indexIy < 0 ? 0 : indexIy; - indexIy = indexIy >= ch ? ch - 1: indexIy; - for(j = 0; j <= 1; j++) { - indexIx = -8 + (blockIdx.x + j) * 16 + threadIdx.x; - indexIx = indexIx < 0 ? 0 : indexIx; - indexIx = indexIx >= cw ? cw - 1: indexIx; - l[i*16 + threadIdx.y][j*16 + threadIdx.x] = src[indexIy * src_stride_ch + indexIx]; - } - } - - int indexL = threadIdx.y*16 + threadIdx.x; - if (indexL < CH_RADIUS_X) - lcx[indexL] = mask_x[indexL]; - if (indexL < CH_RADIUS_Y) - lcy[indexL] = mask_y[indexL]; - barrier(CLK_LOCAL_MEM_FENCE); - - int orig_value = (int)l[threadIdx.y + 8][threadIdx.x + 8]; - - int idx, idy, maskIndex; - int steps_x = CH_RADIUS_X/2; - int steps_y = CH_RADIUS_Y/2; - int temp[2] = {0,0}; - - \n#pragma unroll\n - for (j = 0; j <= 1; j++) { - idx = 16*j + threadIdx.x; - \n#pragma unroll\n - for (i = -steps_y; i <= steps_y; i++) { - idy = 8 + i + threadIdx.y; - maskIndex = i + steps_y; - temp[j] += (int)l[idy][idx] * lcy[maskIndex]; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - idy = 8 + threadIdx.y; - \n#pragma unroll\n - for (j = 0; j <= 1; j++) { - idx = 16*j + threadIdx.x; - l[idy][idx] = temp[j]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - //compute results with the horizontal filter \n - int sum = 0; - idy = 8 + threadIdx.y; - \n#pragma unroll\n - for (j = -steps_x; j <= steps_x; j++) { - idx = 8 + j + threadIdx.x; - maskIndex = j + steps_x; - sum += (int)l[idy][idx] * lcx[maskIndex]; - } - - int res = orig_value + (((orig_value - (int)((sum + halfscale) >> scalebits)) * amount) >> 16); - - if (globalIdx.x < cw && globalIdx.y < ch) - dst[globalIdx.x + globalIdx.y*dst_stride_ch] = clip_uint8(res); -} - -kernel void unsharp_default(global unsigned char *src, - global unsigned char *dst, - const global unsigned int *mask_lu, - const global unsigned int *mask_ch, - int amount_lu, - int amount_ch, - int step_x_lu, - int step_y_lu, - int step_x_ch, - int step_y_ch, - int scalebits_lu, - int scalebits_ch, - int halfscale_lu, - int halfscale_ch, - int src_stride_lu, - int src_stride_ch, - int dst_stride_lu, - int dst_stride_ch, - int height, - int width, - int ch, - int cw) -{ - global unsigned char *dst_y = dst; - global unsigned char *dst_u = dst_y + height * dst_stride_lu; - global unsigned char *dst_v = dst_u + ch * dst_stride_ch; - - global unsigned char *src_y = src; - global unsigned char *src_u = src_y + height * src_stride_lu; - global unsigned char *src_v = src_u + ch * src_stride_ch; - - global unsigned char *temp_dst; - global unsigned char *temp_src; - const global unsigned int *temp_mask; - int global_id = get_global_id(0); - int i, j, x, y, temp_src_stride, temp_dst_stride, temp_height, temp_width, temp_steps_x, temp_steps_y, - temp_amount, temp_scalebits, temp_halfscale, sum, idx_x, idx_y, temp, res; - if (global_id < width * height) { - y = global_id / width; - x = global_id % width; - temp_dst = dst_y; - temp_src = src_y; - temp_src_stride = src_stride_lu; - temp_dst_stride = dst_stride_lu; - temp_height = height; - temp_width = width; - temp_steps_x = step_x_lu; - temp_steps_y = step_y_lu; - temp_mask = mask_lu; - temp_amount = amount_lu; - temp_scalebits = scalebits_lu; - temp_halfscale = halfscale_lu; - } else if ((global_id >= width * height) && (global_id < width * height + ch * cw)) { - y = (global_id - width * height) / cw; - x = (global_id - width * height) % cw; - temp_dst = dst_u; - temp_src = src_u; - temp_src_stride = src_stride_ch; - temp_dst_stride = dst_stride_ch; - temp_height = ch; - temp_width = cw; - temp_steps_x = step_x_ch; - temp_steps_y = step_y_ch; - temp_mask = mask_ch; - temp_amount = amount_ch; - temp_scalebits = scalebits_ch; - temp_halfscale = halfscale_ch; - } else { - y = (global_id - width * height - ch * cw) / cw; - x = (global_id - width * height - ch * cw) % cw; - temp_dst = dst_v; - temp_src = src_v; - temp_src_stride = src_stride_ch; - temp_dst_stride = dst_stride_ch; - temp_height = ch; - temp_width = cw; - temp_steps_x = step_x_ch; - temp_steps_y = step_y_ch; - temp_mask = mask_ch; - temp_amount = amount_ch; - temp_scalebits = scalebits_ch; - temp_halfscale = halfscale_ch; - } - if (temp_amount) { - sum = 0; - for (j = 0; j <= 2 * temp_steps_y; j++) { - idx_y = (y - temp_steps_y + j) <= 0 ? 0 : (y - temp_steps_y + j) >= temp_height ? temp_height-1 : y - temp_steps_y + j; - for (i = 0; i <= 2 * temp_steps_x; i++) { - idx_x = (x - temp_steps_x + i) <= 0 ? 0 : (x - temp_steps_x + i) >= temp_width ? temp_width-1 : x - temp_steps_x + i; - sum += temp_mask[i + j * (2 * temp_steps_x + 1)] * temp_src[idx_x + idx_y * temp_src_stride]; - } - } - temp = (int)temp_src[x + y * temp_src_stride]; - res = temp + (((temp - (int)((sum + temp_halfscale) >> temp_scalebits)) * temp_amount) >> 16); - temp_dst[x + y * temp_dst_stride] = clip_uint8(res); - } else { - temp_dst[x + y * temp_dst_stride] = temp_src[x + y * temp_src_stride]; - } -} -); - -#endif /* AVFILTER_UNSHARP_OPENCL_KERNEL_H */ diff --git a/libavfilter/vf_deshake.c b/libavfilter/vf_deshake.c index 64b48c6d02fde..fb4eb355b834e 100644 --- a/libavfilter/vf_deshake.c +++ b/libavfilter/vf_deshake.c @@ -60,7 +60,6 @@ #include "libavutil/qsort.h" #include "deshake.h" -#include "deshake_opencl.h" #define OFFSET(x) offsetof(DeshakeContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM @@ -83,7 +82,7 @@ static const AVOption deshake_options[] = { { "exhaustive", "exhaustive search", 0, AV_OPT_TYPE_CONST, {.i64=EXHAUSTIVE}, INT_MIN, INT_MAX, FLAGS, "smode" }, { "less", "less exhaustive search", 0, AV_OPT_TYPE_CONST, {.i64=SMART_EXHAUSTIVE}, INT_MIN, INT_MAX, FLAGS, "smode" }, { "filename", "set motion search detailed log file name", OFFSET(filename), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS }, - { "opencl", "use OpenCL filtering capabilities", OFFSET(opencl), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS }, + { "opencl", "ignored", OFFSET(opencl), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS }, { NULL } }; @@ -341,7 +340,6 @@ static int deshake_transform_c(AVFilterContext *ctx, static av_cold int init(AVFilterContext *ctx) { - int ret; DeshakeContext *deshake = ctx->priv; deshake->sad = av_pixelutils_get_sad_fn(4, 4, 1, deshake); // 16x16, 2nd source unaligned @@ -369,17 +367,7 @@ static av_cold int init(AVFilterContext *ctx) deshake->cx &= ~15; } deshake->transform = deshake_transform_c; - if (!CONFIG_OPENCL && deshake->opencl) { - av_log(ctx, AV_LOG_ERROR, "OpenCL support was not enabled in this build, cannot be selected\n"); - return AVERROR(EINVAL); - } - if (CONFIG_OPENCL && deshake->opencl) { - deshake->transform = ff_opencl_transform; - ret = ff_opencl_deshake_init(ctx); - if (ret < 0) - return ret; - } av_log(ctx, AV_LOG_VERBOSE, "cx: %d, cy: %d, cw: %d, ch: %d, rx: %d, ry: %d, edge: %d blocksize: %d contrast: %d search: %d\n", deshake->cx, deshake->cy, deshake->cw, deshake->ch, deshake->rx, deshake->ry, deshake->edge, deshake->blocksize * 2, deshake->contrast, deshake->search); @@ -416,9 +404,6 @@ static int config_props(AVFilterLink *link) static av_cold void uninit(AVFilterContext *ctx) { DeshakeContext *deshake = ctx->priv; - if (CONFIG_OPENCL && deshake->opencl) { - ff_opencl_deshake_uninit(ctx); - } av_frame_free(&deshake->ref); av_freep(&deshake->angles); deshake->angles_size = 0; @@ -447,12 +432,6 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) } av_frame_copy_props(out, in); - if (CONFIG_OPENCL && deshake->opencl) { - ret = ff_opencl_deshake_process_inout_buf(link->dst,in, out); - if (ret < 0) - goto fail; - } - if (deshake->cx < 0 || deshake->cy < 0 || deshake->cw < 0 || deshake->ch < 0) { // Find the most likely global motion for the current frame find_motion(deshake, (deshake->ref == NULL) ? in->data[0] : deshake->ref->data[0], in->data[0], link->w, link->h, in->linesize[0], &t); diff --git a/libavfilter/vf_unsharp.c b/libavfilter/vf_unsharp.c index 438ff6d8fb219..41ccc56942b69 100644 --- a/libavfilter/vf_unsharp.c +++ b/libavfilter/vf_unsharp.c @@ -46,7 +46,6 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "unsharp.h" -#include "unsharp_opencl.h" static void apply_unsharp( uint8_t *dst, int dst_stride, const uint8_t *src, int src_stride, @@ -134,10 +133,8 @@ static void set_filter_param(UnsharpFilterParam *fp, int msize_x, int msize_y, f static av_cold int init(AVFilterContext *ctx) { - int ret = 0; UnsharpContext *s = ctx->priv; - set_filter_param(&s->luma, s->lmsize_x, s->lmsize_y, s->lamount); set_filter_param(&s->chroma, s->cmsize_x, s->cmsize_y, s->camount); @@ -146,16 +143,6 @@ static av_cold int init(AVFilterContext *ctx) return AVERROR(EINVAL); } s->apply_unsharp = apply_unsharp_c; - if (!CONFIG_OPENCL && s->opencl) { - av_log(ctx, AV_LOG_ERROR, "OpenCL support was not enabled in this build, cannot be selected\n"); - return AVERROR(EINVAL); - } - if (CONFIG_OPENCL && s->opencl) { - s->apply_unsharp = ff_opencl_apply_unsharp; - ret = ff_opencl_unsharp_init(ctx); - if (ret < 0) - return ret; - } return 0; } @@ -227,10 +214,6 @@ static av_cold void uninit(AVFilterContext *ctx) { UnsharpContext *s = ctx->priv; - if (CONFIG_OPENCL && s->opencl) { - ff_opencl_unsharp_uninit(ctx); - } - free_filter_param(&s->luma); free_filter_param(&s->chroma); } @@ -248,14 +231,9 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) return AVERROR(ENOMEM); } av_frame_copy_props(out, in); - if (CONFIG_OPENCL && s->opencl) { - ret = ff_opencl_unsharp_process_inout_buf(link->dst, in, out); - if (ret < 0) - goto end; - } ret = s->apply_unsharp(link->dst, in, out); -end: + av_frame_free(&in); if (ret < 0) { @@ -282,7 +260,7 @@ static const AVOption unsharp_options[] = { { "cy", "set chroma matrix vertical size", OFFSET(cmsize_y), AV_OPT_TYPE_INT, { .i64 = 5 }, MIN_SIZE, MAX_SIZE, FLAGS }, { "chroma_amount", "set chroma effect strength", OFFSET(camount), AV_OPT_TYPE_FLOAT, { .dbl = 0 }, -2, 5, FLAGS }, { "ca", "set chroma effect strength", OFFSET(camount), AV_OPT_TYPE_FLOAT, { .dbl = 0 }, -2, 5, FLAGS }, - { "opencl", "use OpenCL filtering capabilities", OFFSET(opencl), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, + { "opencl", "ignored", OFFSET(opencl), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, { NULL } }; diff --git a/libavutil/Makefile b/libavutil/Makefile index cc70c4e29f594..721784086c1db 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -79,8 +79,6 @@ HEADERS = adler32.h \ HEADERS-$(CONFIG_LZO) += lzo.h -HEADERS-$(CONFIG_OPENCL) += opencl.h - ARCH_HEADERS = bswap.h \ intmath.h \ intreadwrite.h \ @@ -164,7 +162,6 @@ OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o OBJS-$(CONFIG_QSV) += hwcontext_qsv.o OBJS-$(CONFIG_LIBDRM) += hwcontext_drm.o OBJS-$(CONFIG_LZO) += lzo.o -OBJS-$(CONFIG_OPENCL) += opencl.o opencl_internal.o OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o OBJS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.o @@ -187,7 +184,6 @@ SKIPHEADERS-$(CONFIG_VDPAU) += hwcontext_vdpau.h SKIPHEADERS-$(HAVE_ATOMICS_GCC) += atomic_gcc.h SKIPHEADERS-$(HAVE_ATOMICS_SUNCC) += atomic_suncc.h SKIPHEADERS-$(HAVE_ATOMICS_WIN32) += atomic_win32.h -SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h TESTPROGS = adler32 \ aes \ diff --git a/libavutil/opencl.c b/libavutil/opencl.c deleted file mode 100644 index 202756516b005..0000000000000 --- a/libavutil/opencl.c +++ /dev/null @@ -1,875 +0,0 @@ -/* - * Copyright (C) 2012 Peng Gao - * Copyright (C) 2012 Li Cao - * Copyright (C) 2012 Wei Gao - * Copyright (C) 2013 Lenny Wang - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "opencl.h" -#include "avstring.h" -#include "log.h" -#include "avassert.h" -#include "opt.h" - -#if HAVE_THREADS -#include "thread.h" -#include "atomic.h" - -static pthread_mutex_t * volatile atomic_opencl_lock = NULL; -#define LOCK_OPENCL pthread_mutex_lock(atomic_opencl_lock) -#define UNLOCK_OPENCL pthread_mutex_unlock(atomic_opencl_lock) -#else -#define LOCK_OPENCL -#define UNLOCK_OPENCL -#endif - -#define MAX_KERNEL_CODE_NUM 200 - -typedef struct { - int is_compiled; - const char *kernel_string; -} KernelCode; - -typedef struct { - const AVClass *class; - int log_offset; - void *log_ctx; - int init_count; - int opt_init_flag; - /** - * if set to 1, the OpenCL environment was created by the user and - * passed as AVOpenCLExternalEnv when initing ,0:created by opencl wrapper. - */ - int is_user_created; - int platform_idx; - int device_idx; - cl_platform_id platform_id; - cl_device_type device_type; - cl_context context; - cl_device_id device_id; - cl_command_queue command_queue; - int kernel_code_count; - KernelCode kernel_code[MAX_KERNEL_CODE_NUM]; - AVOpenCLDeviceList device_list; -} OpenclContext; - -#define OFFSET(x) offsetof(OpenclContext, x) - -static const AVOption opencl_options[] = { - { "platform_idx", "set platform index value", OFFSET(platform_idx), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX}, - { "device_idx", "set device index value", OFFSET(device_idx), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX}, - { NULL } -}; - -static const AVClass openclutils_class = { - .class_name = "opencl", - .option = opencl_options, - .item_name = av_default_item_name, - .version = LIBAVUTIL_VERSION_INT, - .log_level_offset_offset = offsetof(OpenclContext, log_offset), - .parent_log_context_offset = offsetof(OpenclContext, log_ctx), -}; - -static OpenclContext opencl_ctx = {&openclutils_class}; - -static const cl_device_type device_type[] = {CL_DEVICE_TYPE_GPU, CL_DEVICE_TYPE_CPU}; - -typedef struct { - int err_code; - const char *err_str; -} OpenclErrorMsg; - -static const OpenclErrorMsg opencl_err_msg[] = { - {CL_DEVICE_NOT_FOUND, "DEVICE NOT FOUND"}, - {CL_DEVICE_NOT_AVAILABLE, "DEVICE NOT AVAILABLE"}, - {CL_COMPILER_NOT_AVAILABLE, "COMPILER NOT AVAILABLE"}, - {CL_MEM_OBJECT_ALLOCATION_FAILURE, "MEM OBJECT ALLOCATION FAILURE"}, - {CL_OUT_OF_RESOURCES, "OUT OF RESOURCES"}, - {CL_OUT_OF_HOST_MEMORY, "OUT OF HOST MEMORY"}, - {CL_PROFILING_INFO_NOT_AVAILABLE, "PROFILING INFO NOT AVAILABLE"}, - {CL_MEM_COPY_OVERLAP, "MEM COPY OVERLAP"}, - {CL_IMAGE_FORMAT_MISMATCH, "IMAGE FORMAT MISMATCH"}, - {CL_IMAGE_FORMAT_NOT_SUPPORTED, "IMAGE FORMAT NOT_SUPPORTED"}, - {CL_BUILD_PROGRAM_FAILURE, "BUILD PROGRAM FAILURE"}, - {CL_MAP_FAILURE, "MAP FAILURE"}, - {CL_MISALIGNED_SUB_BUFFER_OFFSET, "MISALIGNED SUB BUFFER OFFSET"}, - {CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST, "EXEC STATUS ERROR FOR EVENTS IN WAIT LIST"}, - {CL_COMPILE_PROGRAM_FAILURE, "COMPILE PROGRAM FAILURE"}, - {CL_LINKER_NOT_AVAILABLE, "LINKER NOT AVAILABLE"}, - {CL_LINK_PROGRAM_FAILURE, "LINK PROGRAM FAILURE"}, - {CL_DEVICE_PARTITION_FAILED, "DEVICE PARTITION FAILED"}, - {CL_KERNEL_ARG_INFO_NOT_AVAILABLE, "KERNEL ARG INFO NOT AVAILABLE"}, - {CL_INVALID_VALUE, "INVALID VALUE"}, - {CL_INVALID_DEVICE_TYPE, "INVALID DEVICE TYPE"}, - {CL_INVALID_PLATFORM, "INVALID PLATFORM"}, - {CL_INVALID_DEVICE, "INVALID DEVICE"}, - {CL_INVALID_CONTEXT, "INVALID CONTEXT"}, - {CL_INVALID_QUEUE_PROPERTIES, "INVALID QUEUE PROPERTIES"}, - {CL_INVALID_COMMAND_QUEUE, "INVALID COMMAND QUEUE"}, - {CL_INVALID_HOST_PTR, "INVALID HOST PTR"}, - {CL_INVALID_MEM_OBJECT, "INVALID MEM OBJECT"}, - {CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, "INVALID IMAGE FORMAT DESCRIPTOR"}, - {CL_INVALID_IMAGE_SIZE, "INVALID IMAGE SIZE"}, - {CL_INVALID_SAMPLER, "INVALID SAMPLER"}, - {CL_INVALID_BINARY, "INVALID BINARY"}, - {CL_INVALID_BUILD_OPTIONS, "INVALID BUILD OPTIONS"}, - {CL_INVALID_PROGRAM, "INVALID PROGRAM"}, - {CL_INVALID_PROGRAM_EXECUTABLE, "INVALID PROGRAM EXECUTABLE"}, - {CL_INVALID_KERNEL_NAME, "INVALID KERNEL NAME"}, - {CL_INVALID_KERNEL_DEFINITION, "INVALID KERNEL DEFINITION"}, - {CL_INVALID_KERNEL, "INVALID KERNEL"}, - {CL_INVALID_ARG_INDEX, "INVALID ARG INDEX"}, - {CL_INVALID_ARG_VALUE, "INVALID ARG VALUE"}, - {CL_INVALID_ARG_SIZE, "INVALID ARG_SIZE"}, - {CL_INVALID_KERNEL_ARGS, "INVALID KERNEL ARGS"}, - {CL_INVALID_WORK_DIMENSION, "INVALID WORK DIMENSION"}, - {CL_INVALID_WORK_GROUP_SIZE, "INVALID WORK GROUP SIZE"}, - {CL_INVALID_WORK_ITEM_SIZE, "INVALID WORK ITEM SIZE"}, - {CL_INVALID_GLOBAL_OFFSET, "INVALID GLOBAL OFFSET"}, - {CL_INVALID_EVENT_WAIT_LIST, "INVALID EVENT WAIT LIST"}, - {CL_INVALID_EVENT, "INVALID EVENT"}, - {CL_INVALID_OPERATION, "INVALID OPERATION"}, - {CL_INVALID_GL_OBJECT, "INVALID GL OBJECT"}, - {CL_INVALID_BUFFER_SIZE, "INVALID BUFFER SIZE"}, - {CL_INVALID_MIP_LEVEL, "INVALID MIP LEVEL"}, - {CL_INVALID_GLOBAL_WORK_SIZE, "INVALID GLOBAL WORK SIZE"}, - {CL_INVALID_PROPERTY, "INVALID PROPERTY"}, - {CL_INVALID_IMAGE_DESCRIPTOR, "INVALID IMAGE DESCRIPTOR"}, - {CL_INVALID_COMPILER_OPTIONS, "INVALID COMPILER OPTIONS"}, - {CL_INVALID_LINKER_OPTIONS, "INVALID LINKER OPTIONS"}, - {CL_INVALID_DEVICE_PARTITION_COUNT, "INVALID DEVICE PARTITION COUNT"}, -}; - -const char *av_opencl_errstr(cl_int status) -{ - int i; - for (i = 0; i < FF_ARRAY_ELEMS(opencl_err_msg); i++) { - if (opencl_err_msg[i].err_code == status) - return opencl_err_msg[i].err_str; - } - return "unknown error"; -} - -static void free_device_list(AVOpenCLDeviceList *device_list) -{ - int i, j; - if (!device_list || !device_list->platform_node) - return; - for (i = 0; i < device_list->platform_num; i++) { - if (!device_list->platform_node[i]) - continue; - for (j = 0; j < device_list->platform_node[i]->device_num; j++) { - av_freep(&(device_list->platform_node[i]->device_node[j]->device_name)); - av_freep(&(device_list->platform_node[i]->device_node[j])); - } - av_freep(&device_list->platform_node[i]->device_node); - av_freep(&(device_list->platform_node[i]->platform_name)); - av_freep(&device_list->platform_node[i]); - } - av_freep(&device_list->platform_node); - device_list->platform_num = 0; -} - -static int get_device_list(AVOpenCLDeviceList *device_list) -{ - cl_int status; - int i, j, k, device_num, total_devices_num, ret = 0; - int *devices_num; - cl_platform_id *platform_ids = NULL; - cl_device_id *device_ids = NULL; - AVOpenCLDeviceNode *device_node = NULL; - size_t platform_name_size = 0; - size_t device_name_size = 0; - status = clGetPlatformIDs(0, NULL, &device_list->platform_num); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not get OpenCL platform ids: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - platform_ids = av_mallocz_array(device_list->platform_num, sizeof(cl_platform_id)); - if (!platform_ids) - return AVERROR(ENOMEM); - status = clGetPlatformIDs(device_list->platform_num, platform_ids, NULL); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not get OpenCL platform ids: %s\n", av_opencl_errstr(status)); - ret = AVERROR_EXTERNAL; - goto end; - } - device_list->platform_node = av_mallocz_array(device_list->platform_num, sizeof(AVOpenCLPlatformNode *)); - if (!device_list->platform_node) { - ret = AVERROR(ENOMEM); - goto end; - } - devices_num = av_mallocz(sizeof(int) * FF_ARRAY_ELEMS(device_type)); - if (!devices_num) { - ret = AVERROR(ENOMEM); - goto end; - } - for (i = 0; i < device_list->platform_num; i++) { - device_list->platform_node[i] = av_mallocz(sizeof(AVOpenCLPlatformNode)); - if (!device_list->platform_node[i]) { - ret = AVERROR(ENOMEM); - goto end; - } - device_list->platform_node[i]->platform_id = platform_ids[i]; - status = clGetPlatformInfo(platform_ids[i], CL_PLATFORM_VENDOR, - 0, NULL, &platform_name_size); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_WARNING, - "Could not get size of platform name: %s\n", av_opencl_errstr(status)); - } else { - device_list->platform_node[i]->platform_name = av_malloc(platform_name_size * sizeof(char)); - if (!device_list->platform_node[i]->platform_name) { - av_log(&opencl_ctx, AV_LOG_WARNING, - "Could not allocate memory for device name: %s\n", av_opencl_errstr(status)); - } else { - status = clGetPlatformInfo(platform_ids[i], CL_PLATFORM_VENDOR, - platform_name_size * sizeof(char), - device_list->platform_node[i]->platform_name, NULL); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_WARNING, - "Could not get platform name: %s\n", av_opencl_errstr(status)); - } - } - } - total_devices_num = 0; - for (j = 0; j < FF_ARRAY_ELEMS(device_type); j++) { - status = clGetDeviceIDs(device_list->platform_node[i]->platform_id, - device_type[j], 0, NULL, &devices_num[j]); - total_devices_num += devices_num[j]; - } - device_list->platform_node[i]->device_node = av_mallocz_array(total_devices_num, sizeof(AVOpenCLDeviceNode *)); - if (!device_list->platform_node[i]->device_node) { - ret = AVERROR(ENOMEM); - goto end; - } - for (j = 0; j < FF_ARRAY_ELEMS(device_type); j++) { - if (devices_num[j]) { - device_ids = av_mallocz_array(devices_num[j], sizeof(cl_device_id)); - if (!device_ids) { - ret = AVERROR(ENOMEM); - goto end; - } - status = clGetDeviceIDs(device_list->platform_node[i]->platform_id, device_type[j], - devices_num[j], device_ids, NULL); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_WARNING, - "Could not get device ID: %s:\n", av_opencl_errstr(status)); - av_freep(&device_ids); - continue; - } - for (k = 0; k < devices_num[j]; k++) { - device_num = device_list->platform_node[i]->device_num; - device_list->platform_node[i]->device_node[device_num] = av_mallocz(sizeof(AVOpenCLDeviceNode)); - if (!device_list->platform_node[i]->device_node[device_num]) { - ret = AVERROR(ENOMEM); - goto end; - } - device_node = device_list->platform_node[i]->device_node[device_num]; - device_node->device_id = device_ids[k]; - device_node->device_type = device_type[j]; - status = clGetDeviceInfo(device_node->device_id, CL_DEVICE_NAME, - 0, NULL, &device_name_size); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_WARNING, - "Could not get size of device name: %s\n", av_opencl_errstr(status)); - continue; - } - device_node->device_name = av_malloc(device_name_size * sizeof(char)); - if (!device_node->device_name) { - av_log(&opencl_ctx, AV_LOG_WARNING, - "Could not allocate memory for device name: %s\n", av_opencl_errstr(status)); - continue; - } - status = clGetDeviceInfo(device_node->device_id, CL_DEVICE_NAME, - device_name_size * sizeof(char), - device_node->device_name, NULL); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_WARNING, - "Could not get device name: %s\n", av_opencl_errstr(status)); - continue; - } - device_list->platform_node[i]->device_num++; - } - av_freep(&device_ids); - } - } - } -end: - av_freep(&platform_ids); - av_freep(&devices_num); - av_freep(&device_ids); - if (ret < 0) - free_device_list(device_list); - return ret; -} - -int av_opencl_get_device_list(AVOpenCLDeviceList **device_list) -{ - int ret = 0; - *device_list = av_mallocz(sizeof(AVOpenCLDeviceList)); - if (!(*device_list)) { - av_log(&opencl_ctx, AV_LOG_ERROR, "Could not allocate opencl device list\n"); - return AVERROR(ENOMEM); - } - ret = get_device_list(*device_list); - if (ret < 0) { - av_log(&opencl_ctx, AV_LOG_ERROR, "Could not get device list from environment\n"); - free_device_list(*device_list); - av_freep(device_list); - return ret; - } - return ret; -} - -void av_opencl_free_device_list(AVOpenCLDeviceList **device_list) -{ - free_device_list(*device_list); - av_freep(device_list); -} - -static inline int init_opencl_mtx(void) -{ -#if HAVE_THREADS - if (!atomic_opencl_lock) { - int err; - pthread_mutex_t *tmp = av_malloc(sizeof(pthread_mutex_t)); - if (!tmp) - return AVERROR(ENOMEM); - if ((err = pthread_mutex_init(tmp, NULL))) { - av_free(tmp); - return AVERROR(err); - } - if (avpriv_atomic_ptr_cas((void * volatile *)&atomic_opencl_lock, NULL, tmp)) { - pthread_mutex_destroy(tmp); - av_free(tmp); - } - } -#endif - return 0; -} - -int av_opencl_set_option(const char *key, const char *val) -{ - int ret = init_opencl_mtx( ); - if (ret < 0) - return ret; - LOCK_OPENCL; - if (!opencl_ctx.opt_init_flag) { - av_opt_set_defaults(&opencl_ctx); - opencl_ctx.opt_init_flag = 1; - } - ret = av_opt_set(&opencl_ctx, key, val, 0); - UNLOCK_OPENCL; - return ret; -} - -int av_opencl_get_option(const char *key, uint8_t **out_val) -{ - int ret = 0; - LOCK_OPENCL; - ret = av_opt_get(&opencl_ctx, key, 0, out_val); - UNLOCK_OPENCL; - return ret; -} - -void av_opencl_free_option(void) -{ - /*FIXME: free openclutils context*/ - LOCK_OPENCL; - av_opt_free(&opencl_ctx); - UNLOCK_OPENCL; -} - -AVOpenCLExternalEnv *av_opencl_alloc_external_env(void) -{ - AVOpenCLExternalEnv *ext = av_mallocz(sizeof(AVOpenCLExternalEnv)); - if (!ext) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not malloc external opencl environment data space\n"); - } - return ext; -} - -void av_opencl_free_external_env(AVOpenCLExternalEnv **ext_opencl_env) -{ - av_freep(ext_opencl_env); -} - -int av_opencl_register_kernel_code(const char *kernel_code) -{ - int i, ret = init_opencl_mtx( ); - if (ret < 0) - return ret; - LOCK_OPENCL; - if (opencl_ctx.kernel_code_count >= MAX_KERNEL_CODE_NUM) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not register kernel code, maximum number of registered kernel code %d already reached\n", - MAX_KERNEL_CODE_NUM); - ret = AVERROR(EINVAL); - goto end; - } - for (i = 0; i < opencl_ctx.kernel_code_count; i++) { - if (opencl_ctx.kernel_code[i].kernel_string == kernel_code) { - av_log(&opencl_ctx, AV_LOG_WARNING, "Same kernel code has been registered\n"); - goto end; - } - } - opencl_ctx.kernel_code[opencl_ctx.kernel_code_count].kernel_string = kernel_code; - opencl_ctx.kernel_code[opencl_ctx.kernel_code_count].is_compiled = 0; - opencl_ctx.kernel_code_count++; -end: - UNLOCK_OPENCL; - return ret; -} - -cl_program av_opencl_compile(const char *program_name, const char *build_opts) -{ - int i; - cl_int status, build_status; - int kernel_code_idx = 0; - const char *kernel_source = NULL; - size_t kernel_code_len; - char* ptr = NULL; - cl_program program = NULL; - size_t log_size; - char *log = NULL; - - LOCK_OPENCL; - for (i = 0; i < opencl_ctx.kernel_code_count; i++) { - // identify a program using a unique name within the kernel source - ptr = av_stristr(opencl_ctx.kernel_code[i].kernel_string, program_name); - if (ptr && !opencl_ctx.kernel_code[i].is_compiled) { - kernel_source = opencl_ctx.kernel_code[i].kernel_string; - kernel_code_len = strlen(opencl_ctx.kernel_code[i].kernel_string); - kernel_code_idx = i; - break; - } - } - if (!kernel_source) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Unable to find OpenCL kernel source '%s'\n", program_name); - goto end; - } - - /* create a CL program from kernel source */ - program = clCreateProgramWithSource(opencl_ctx.context, 1, &kernel_source, &kernel_code_len, &status); - if(status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Unable to create OpenCL program '%s': %s\n", program_name, av_opencl_errstr(status)); - program = NULL; - goto end; - } - - build_status = clBuildProgram(program, 1, &(opencl_ctx.device_id), build_opts, NULL, NULL); - status = clGetProgramBuildInfo(program, opencl_ctx.device_id, - CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_WARNING, - "Failed to get compilation log: %s\n", - av_opencl_errstr(status)); - } else { - log = av_malloc(log_size); - if (log) { - status = clGetProgramBuildInfo(program, opencl_ctx.device_id, - CL_PROGRAM_BUILD_LOG, log_size, - log, NULL); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_WARNING, - "Failed to get compilation log: %s\n", - av_opencl_errstr(status)); - } else { - int level = build_status == CL_SUCCESS ? AV_LOG_DEBUG : - AV_LOG_ERROR; - av_log(&opencl_ctx, level, "Compilation log:\n%s\n", log); - } - } - av_freep(&log); - } - if (build_status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Compilation failed with OpenCL program '%s': %s\n", - program_name, av_opencl_errstr(build_status)); - program = NULL; - goto end; - } - - opencl_ctx.kernel_code[kernel_code_idx].is_compiled = 1; -end: - UNLOCK_OPENCL; - return program; -} - -cl_command_queue av_opencl_get_command_queue(void) -{ - return opencl_ctx.command_queue; -} - -static int init_opencl_env(OpenclContext *opencl_ctx, AVOpenCLExternalEnv *ext_opencl_env) -{ - cl_int status; - cl_context_properties cps[3]; - int i, ret = 0; - AVOpenCLDeviceNode *device_node = NULL; - - if (ext_opencl_env) { - if (opencl_ctx->is_user_created) - return 0; - opencl_ctx->platform_id = ext_opencl_env->platform_id; - opencl_ctx->is_user_created = 1; - opencl_ctx->command_queue = ext_opencl_env->command_queue; - opencl_ctx->context = ext_opencl_env->context; - opencl_ctx->device_id = ext_opencl_env->device_id; - opencl_ctx->device_type = ext_opencl_env->device_type; - } else { - if (!opencl_ctx->is_user_created) { - if (!opencl_ctx->device_list.platform_num) { - ret = get_device_list(&opencl_ctx->device_list); - if (ret < 0) { - return ret; - } - } - if (opencl_ctx->platform_idx >= 0) { - if (opencl_ctx->device_list.platform_num < opencl_ctx->platform_idx + 1) { - av_log(opencl_ctx, AV_LOG_ERROR, "User set platform index not exist\n"); - return AVERROR(EINVAL); - } - if (!opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->device_num) { - av_log(opencl_ctx, AV_LOG_ERROR, "No devices in user specific platform with index %d\n", - opencl_ctx->platform_idx); - return AVERROR(EINVAL); - } - opencl_ctx->platform_id = opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->platform_id; - } else { - /* get a usable platform by default*/ - for (i = 0; i < opencl_ctx->device_list.platform_num; i++) { - if (opencl_ctx->device_list.platform_node[i]->device_num) { - opencl_ctx->platform_id = opencl_ctx->device_list.platform_node[i]->platform_id; - opencl_ctx->platform_idx = i; - break; - } - } - } - if (!opencl_ctx->platform_id) { - av_log(opencl_ctx, AV_LOG_ERROR, "Could not get OpenCL platforms\n"); - return AVERROR_EXTERNAL; - } - /* get a usable device*/ - if (opencl_ctx->device_idx >= 0) { - if (opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->device_num < opencl_ctx->device_idx + 1) { - av_log(opencl_ctx, AV_LOG_ERROR, - "Could not get OpenCL device idx %d in the user set platform\n", opencl_ctx->platform_idx); - return AVERROR(EINVAL); - } - } else { - opencl_ctx->device_idx = 0; - } - - device_node = opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->device_node[opencl_ctx->device_idx]; - opencl_ctx->device_id = device_node->device_id; - opencl_ctx->device_type = device_node->device_type; - - /* - * Use available platform. - */ - av_log(opencl_ctx, AV_LOG_VERBOSE, "Platform Name: %s, Device Name: %s\n", - opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->platform_name, - device_node->device_name); - cps[0] = CL_CONTEXT_PLATFORM; - cps[1] = (cl_context_properties)opencl_ctx->platform_id; - cps[2] = 0; - - opencl_ctx->context = clCreateContextFromType(cps, opencl_ctx->device_type, - NULL, NULL, &status); - if (status != CL_SUCCESS) { - av_log(opencl_ctx, AV_LOG_ERROR, - "Could not get OpenCL context from device type: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - opencl_ctx->command_queue = clCreateCommandQueue(opencl_ctx->context, opencl_ctx->device_id, - 0, &status); - if (status != CL_SUCCESS) { - av_log(opencl_ctx, AV_LOG_ERROR, - "Could not create OpenCL command queue: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - } - } - return ret; -} - -int av_opencl_init(AVOpenCLExternalEnv *ext_opencl_env) -{ - int ret = init_opencl_mtx( ); - if (ret < 0) - return ret; - LOCK_OPENCL; - if (!opencl_ctx.init_count) { - if (!opencl_ctx.opt_init_flag) { - av_opt_set_defaults(&opencl_ctx); - opencl_ctx.opt_init_flag = 1; - } - ret = init_opencl_env(&opencl_ctx, ext_opencl_env); - if (ret < 0) - goto end; - if (opencl_ctx.kernel_code_count <= 0) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "No kernel code is registered, compile kernel file failed\n"); - ret = AVERROR(EINVAL); - goto end; - } - } - opencl_ctx.init_count++; -end: - UNLOCK_OPENCL; - return ret; -} - -void av_opencl_uninit(void) -{ - int i; - cl_int status; - LOCK_OPENCL; - opencl_ctx.init_count--; - if (opencl_ctx.is_user_created) - goto end; - if (opencl_ctx.init_count > 0) - goto end; - if (opencl_ctx.command_queue) { - status = clReleaseCommandQueue(opencl_ctx.command_queue); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not release OpenCL command queue: %s\n", av_opencl_errstr(status)); - } - opencl_ctx.command_queue = NULL; - } - if (opencl_ctx.context) { - status = clReleaseContext(opencl_ctx.context); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not release OpenCL context: %s\n", av_opencl_errstr(status)); - } - opencl_ctx.context = NULL; - } - for (i = 0; i < opencl_ctx.kernel_code_count; i++) { - opencl_ctx.kernel_code[i].is_compiled = 0; - } - free_device_list(&opencl_ctx.device_list); -end: - if (opencl_ctx.init_count <= 0) - av_opt_free(&opencl_ctx); //FIXME: free openclutils context - UNLOCK_OPENCL; -} - -int av_opencl_buffer_create(cl_mem *cl_buf, size_t cl_buf_size, int flags, void *host_ptr) -{ - cl_int status; - *cl_buf = clCreateBuffer(opencl_ctx.context, flags, cl_buf_size, host_ptr, &status); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, "Could not create OpenCL buffer: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - return 0; -} - -void av_opencl_buffer_release(cl_mem *cl_buf) -{ - cl_int status = 0; - if (!cl_buf) - return; - status = clReleaseMemObject(*cl_buf); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not release OpenCL buffer: %s\n", av_opencl_errstr(status)); - } - memset(cl_buf, 0, sizeof(*cl_buf)); -} - -int av_opencl_buffer_write(cl_mem dst_cl_buf, uint8_t *src_buf, size_t buf_size) -{ - cl_int status; - void *mapped = clEnqueueMapBuffer(opencl_ctx.command_queue, dst_cl_buf, - CL_TRUE, CL_MAP_WRITE, 0, sizeof(uint8_t) * buf_size, - 0, NULL, NULL, &status); - - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not map OpenCL buffer: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - memcpy(mapped, src_buf, buf_size); - - status = clEnqueueUnmapMemObject(opencl_ctx.command_queue, dst_cl_buf, mapped, 0, NULL, NULL); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not unmap OpenCL buffer: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - return 0; -} - -int av_opencl_buffer_read(uint8_t *dst_buf, cl_mem src_cl_buf, size_t buf_size) -{ - cl_int status; - void *mapped = clEnqueueMapBuffer(opencl_ctx.command_queue, src_cl_buf, - CL_TRUE, CL_MAP_READ, 0, buf_size, - 0, NULL, NULL, &status); - - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not map OpenCL buffer: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - memcpy(dst_buf, mapped, buf_size); - - status = clEnqueueUnmapMemObject(opencl_ctx.command_queue, src_cl_buf, mapped, 0, NULL, NULL); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not unmap OpenCL buffer: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - return 0; -} - -int av_opencl_buffer_write_image(cl_mem dst_cl_buf, size_t cl_buffer_size, int dst_cl_offset, - uint8_t **src_data, int *plane_size, int plane_num) -{ - int i, buffer_size = 0; - uint8_t *temp; - cl_int status; - void *mapped; - if ((unsigned int)plane_num > 8) { - return AVERROR(EINVAL); - } - for (i = 0;i < plane_num;i++) { - buffer_size += plane_size[i]; - } - if (buffer_size > cl_buffer_size) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Cannot write image to OpenCL buffer: buffer too small\n"); - return AVERROR(EINVAL); - } - mapped = clEnqueueMapBuffer(opencl_ctx.command_queue, dst_cl_buf, - CL_TRUE, CL_MAP_WRITE, 0, buffer_size + dst_cl_offset, - 0, NULL, NULL, &status); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not map OpenCL buffer: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - temp = mapped; - temp += dst_cl_offset; - for (i = 0; i < plane_num; i++) { - memcpy(temp, src_data[i], plane_size[i]); - temp += plane_size[i]; - } - status = clEnqueueUnmapMemObject(opencl_ctx.command_queue, dst_cl_buf, mapped, 0, NULL, NULL); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not unmap OpenCL buffer: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - return 0; -} - -int av_opencl_buffer_read_image(uint8_t **dst_data, int *plane_size, int plane_num, - cl_mem src_cl_buf, size_t cl_buffer_size) -{ - int i,buffer_size = 0,ret = 0; - uint8_t *temp; - void *mapped; - cl_int status; - if ((unsigned int)plane_num > 8) { - return AVERROR(EINVAL); - } - for (i = 0; i < plane_num; i++) { - buffer_size += plane_size[i]; - } - if (buffer_size > cl_buffer_size) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Cannot write image to CPU buffer: OpenCL buffer too small\n"); - return AVERROR(EINVAL); - } - mapped = clEnqueueMapBuffer(opencl_ctx.command_queue, src_cl_buf, - CL_TRUE, CL_MAP_READ, 0, buffer_size, - 0, NULL, NULL, &status); - - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not map OpenCL buffer: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - temp = mapped; - if (ret >= 0) { - for (i = 0; i < plane_num; i++) { - memcpy(dst_data[i], temp, plane_size[i]); - temp += plane_size[i]; - } - } - status = clEnqueueUnmapMemObject(opencl_ctx.command_queue, src_cl_buf, mapped, 0, NULL, NULL); - if (status != CL_SUCCESS) { - av_log(&opencl_ctx, AV_LOG_ERROR, - "Could not unmap OpenCL buffer: %s\n", av_opencl_errstr(status)); - return AVERROR_EXTERNAL; - } - return 0; -} - -int64_t av_opencl_benchmark(AVOpenCLDeviceNode *device_node, cl_platform_id platform, - int64_t (*benchmark)(AVOpenCLExternalEnv *ext_opencl_env)) -{ - int64_t ret = 0; - cl_int status; - cl_context_properties cps[3]; - AVOpenCLExternalEnv *ext_opencl_env = NULL; - - ext_opencl_env = av_opencl_alloc_external_env(); - ext_opencl_env->device_id = device_node->device_id; - ext_opencl_env->device_type = device_node->device_type; - av_log(&opencl_ctx, AV_LOG_VERBOSE, "Performing test on OpenCL device %s\n", - device_node->device_name); - - cps[0] = CL_CONTEXT_PLATFORM; - cps[1] = (cl_context_properties)platform; - cps[2] = 0; - ext_opencl_env->context = clCreateContextFromType(cps, ext_opencl_env->device_type, - NULL, NULL, &status); - if (status != CL_SUCCESS || !ext_opencl_env->context) { - ret = AVERROR_EXTERNAL; - goto end; - } - ext_opencl_env->command_queue = clCreateCommandQueue(ext_opencl_env->context, - ext_opencl_env->device_id, 0, &status); - if (status != CL_SUCCESS || !ext_opencl_env->command_queue) { - ret = AVERROR_EXTERNAL; - goto end; - } - ret = benchmark(ext_opencl_env); - if (ret < 0) - av_log(&opencl_ctx, AV_LOG_ERROR, "Benchmark failed with OpenCL device %s\n", - device_node->device_name); -end: - if (ext_opencl_env->command_queue) - clReleaseCommandQueue(ext_opencl_env->command_queue); - if (ext_opencl_env->context) - clReleaseContext(ext_opencl_env->context); - av_opencl_free_external_env(&ext_opencl_env); - return ret; -} diff --git a/libavutil/opencl.h b/libavutil/opencl.h deleted file mode 100644 index b709927c42739..0000000000000 --- a/libavutil/opencl.h +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (C) 2012 Peng Gao - * Copyright (C) 2012 Li Cao - * Copyright (C) 2012 Wei Gao - * Copyright (C) 2013 Lenny Wang - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * OpenCL wrapper - * - * This interface is considered still experimental and its API and ABI may - * change without prior notice. - */ - -#ifndef AVUTIL_OPENCL_H -#define AVUTIL_OPENCL_H - -#define CL_USE_DEPRECATED_OPENCL_1_2_APIS 1 -#ifdef __APPLE__ -#include -#else -#include -#endif -#include -#include "dict.h" - -#include "libavutil/version.h" - -#define AV_OPENCL_KERNEL( ... )# __VA_ARGS__ - -typedef struct { - int device_type; - char *device_name; - cl_device_id device_id; -} AVOpenCLDeviceNode; - -typedef struct { - cl_platform_id platform_id; - char *platform_name; - int device_num; - AVOpenCLDeviceNode **device_node; -} AVOpenCLPlatformNode; - -typedef struct { - int platform_num; - AVOpenCLPlatformNode **platform_node; -} AVOpenCLDeviceList; - -typedef struct { - cl_platform_id platform_id; - cl_device_type device_type; - cl_context context; - cl_device_id device_id; - cl_command_queue command_queue; - char *platform_name; -} AVOpenCLExternalEnv; - -/** - * Get OpenCL device list. - * - * It must be freed with av_opencl_free_device_list(). - * - * @param device_list pointer to OpenCL environment device list, - * should be released by av_opencl_free_device_list() - * - * @return >=0 on success, a negative error code in case of failure - */ -int av_opencl_get_device_list(AVOpenCLDeviceList **device_list); - -/** - * Free OpenCL device list. - * - * @param device_list pointer to OpenCL environment device list - * created by av_opencl_get_device_list() - */ -void av_opencl_free_device_list(AVOpenCLDeviceList **device_list); - -/** - * Set option in the global OpenCL context. - * - * This options affect the operation performed by the next - * av_opencl_init() operation. - * - * The currently accepted options are: - * - platform: set index of platform in device list - * - device: set index of device in device list - * - * See reference "OpenCL Specification Version: 1.2 chapter 5.6.4". - * - * @param key option key - * @param val option value - * @return >=0 on success, a negative error code in case of failure - * @see av_opencl_get_option() - */ -int av_opencl_set_option(const char *key, const char *val); - -/** - * Get option value from the global OpenCL context. - * - * @param key option key - * @param out_val pointer to location where option value will be - * written, must be freed with av_freep() - * @return >=0 on success, a negative error code in case of failure - * @see av_opencl_set_option() - */ -int av_opencl_get_option(const char *key, uint8_t **out_val); - -/** - * Free option values of the global OpenCL context. - * - */ -void av_opencl_free_option(void); - -/** - * Allocate OpenCL external environment. - * - * It must be freed with av_opencl_free_external_env(). - * - * @return pointer to allocated OpenCL external environment - */ -AVOpenCLExternalEnv *av_opencl_alloc_external_env(void); - -/** - * Free OpenCL external environment. - * - * @param ext_opencl_env pointer to OpenCL external environment - * created by av_opencl_alloc_external_env() - */ -void av_opencl_free_external_env(AVOpenCLExternalEnv **ext_opencl_env); - -/** - * Get OpenCL error string. - * - * @param status OpenCL error code - * @return OpenCL error string - */ -const char *av_opencl_errstr(cl_int status); - -/** - * Register kernel code. - * - * The registered kernel code is stored in a global context, and compiled - * in the runtime environment when av_opencl_init() is called. - * - * @param kernel_code kernel code to be compiled in the OpenCL runtime environment - * @return >=0 on success, a negative error code in case of failure - */ -int av_opencl_register_kernel_code(const char *kernel_code); - -/** - * Initialize the run time OpenCL environment - * - * @param ext_opencl_env external OpenCL environment, created by an - * application program, ignored if set to NULL - * @return >=0 on success, a negative error code in case of failure - */ -int av_opencl_init(AVOpenCLExternalEnv *ext_opencl_env); - -/** - * compile specific OpenCL kernel source - * - * @param program_name pointer to a program name used for identification - * @param build_opts pointer to a string that describes the preprocessor - * build options to be used for building the program - * @return a cl_program object - */ -cl_program av_opencl_compile(const char *program_name, const char* build_opts); - -/** - * get OpenCL command queue - * - * @return a cl_command_queue object - */ -cl_command_queue av_opencl_get_command_queue(void); - -/** - * Create OpenCL buffer. - * - * The buffer is used to save the data used or created by an OpenCL - * kernel. - * The created buffer must be released with av_opencl_buffer_release(). - * - * See clCreateBuffer() function reference for more information about - * the parameters. - * - * @param cl_buf pointer to OpenCL buffer - * @param cl_buf_size size in bytes of the OpenCL buffer to create - * @param flags flags used to control buffer attributes - * @param host_ptr host pointer of the OpenCL buffer - * @return >=0 on success, a negative error code in case of failure - */ -int av_opencl_buffer_create(cl_mem *cl_buf, size_t cl_buf_size, int flags, void *host_ptr); - -/** - * Write OpenCL buffer with data from src_buf. - * - * @param dst_cl_buf pointer to OpenCL destination buffer - * @param src_buf pointer to source buffer - * @param buf_size size in bytes of the source and destination buffers - * @return >=0 on success, a negative error code in case of failure - */ -int av_opencl_buffer_write(cl_mem dst_cl_buf, uint8_t *src_buf, size_t buf_size); - -/** - * Read data from OpenCL buffer to memory buffer. - * - * @param dst_buf pointer to destination buffer (CPU memory) - * @param src_cl_buf pointer to source OpenCL buffer - * @param buf_size size in bytes of the source and destination buffers - * @return >=0 on success, a negative error code in case of failure - */ -int av_opencl_buffer_read(uint8_t *dst_buf, cl_mem src_cl_buf, size_t buf_size); - -/** - * Write image data from memory to OpenCL buffer. - * - * The source must be an array of pointers to image plane buffers. - * - * @param dst_cl_buf pointer to destination OpenCL buffer - * @param dst_cl_buf_size size in bytes of OpenCL buffer - * @param dst_cl_buf_offset the offset of the OpenCL buffer start position - * @param src_data array of pointers to source plane buffers - * @param src_plane_sizes array of sizes in bytes of the source plane buffers - * @param src_plane_num number of source image planes - * @return >=0 on success, a negative error code in case of failure - */ -int av_opencl_buffer_write_image(cl_mem dst_cl_buf, size_t cl_buffer_size, int dst_cl_offset, - uint8_t **src_data, int *plane_size, int plane_num); - -/** - * Read image data from OpenCL buffer. - * - * @param dst_data array of pointers to destination plane buffers - * @param dst_plane_sizes array of pointers to destination plane buffers - * @param dst_plane_num number of destination image planes - * @param src_cl_buf pointer to source OpenCL buffer - * @param src_cl_buf_size size in bytes of OpenCL buffer - * @return >=0 on success, a negative error code in case of failure - */ -int av_opencl_buffer_read_image(uint8_t **dst_data, int *plane_size, int plane_num, - cl_mem src_cl_buf, size_t cl_buffer_size); - -/** - * Release OpenCL buffer. - * - * @param cl_buf pointer to OpenCL buffer to release, which was - * previously filled with av_opencl_buffer_create() - */ -void av_opencl_buffer_release(cl_mem *cl_buf); - -/** - * Release OpenCL environment. - * - * The OpenCL environment is effectively released only if all the created - * kernels had been released with av_opencl_release_kernel(). - */ -void av_opencl_uninit(void); - -/** - * Benchmark an OpenCL device with a user defined callback function. This function - * sets up an external OpenCL environment including context and command queue on - * the device then tears it down in the end. The callback function should perform - * the rest of the work. - * - * @param device pointer to the OpenCL device to be used - * @param platform cl_platform_id handle to which the device belongs to - * @param benchmark callback function to perform the benchmark, return a - * negative value in case of failure - * @return the score passed from the callback function, a negative error code in case - * of failure - */ -int64_t av_opencl_benchmark(AVOpenCLDeviceNode *device, cl_platform_id platform, - int64_t (*benchmark)(AVOpenCLExternalEnv *ext_opencl_env)); - -#endif /* AVUTIL_OPENCL_H */ diff --git a/libavutil/opencl_internal.c b/libavutil/opencl_internal.c deleted file mode 100644 index bdb41936faf49..0000000000000 --- a/libavutil/opencl_internal.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2012 Peng Gao - * Copyright (C) 2012 Li Cao - * Copyright (C) 2012 Wei Gao - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "opencl_internal.h" -#include "libavutil/log.h" - -int avpriv_opencl_set_parameter(FFOpenclParam *opencl_param, ...) -{ - int ret = 0; - va_list arg_ptr; - void *param; - size_t param_size; - cl_int status; - if (!opencl_param->kernel) { - av_log(opencl_param->ctx, AV_LOG_ERROR, "OpenCL kernel must be set\n"); - return AVERROR(EINVAL); - } - va_start(arg_ptr, opencl_param); - do { - param = va_arg(arg_ptr, void *); - if (!param) - break; - param_size = va_arg(arg_ptr, size_t); - if (!param_size) { - av_log(opencl_param->ctx, AV_LOG_ERROR, "Parameter size must not be 0\n"); - ret = AVERROR(EINVAL); - goto end; - } - status = clSetKernelArg(opencl_param->kernel, opencl_param->param_num, param_size, param); - if (status != CL_SUCCESS) { - av_log(opencl_param->ctx, AV_LOG_ERROR, "Cannot set kernel argument: %s\n", av_opencl_errstr(status)); - ret = AVERROR_EXTERNAL; - goto end; - } - opencl_param->param_num++; - } while (param && param_size); -end: - va_end(arg_ptr); - return ret; -} diff --git a/libavutil/opencl_internal.h b/libavutil/opencl_internal.h deleted file mode 100644 index 5cabb7b3eea99..0000000000000 --- a/libavutil/opencl_internal.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2012 Peng Gao - * Copyright (C) 2012 Li Cao - * Copyright (C) 2012 Wei Gao - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVUTIL_OPENCL_INTERNAL_H -#define AVUTIL_OPENCL_INTERNAL_H - -#include "attributes.h" -#include "opencl.h" - -#define FF_OPENCL_PARAM_INFO(a) ((void*)(&(a))), (sizeof(a)) - -typedef struct { - cl_kernel kernel; - int param_num; - void *ctx; -} FFOpenclParam; - -av_warn_unused_result -int avpriv_opencl_set_parameter(FFOpenclParam *opencl_param, ...); - -#endif /* AVUTIL_OPENCL_INTERNAL_H */ From 79a26ef802d66106af42ddc81b61fdac06433821 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 22 Nov 2017 23:55:03 +0000 Subject: [PATCH 1069/2557] tools/cl2c: Add a copyright header --- tools/cl2c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/cl2c b/tools/cl2c index 1ead940811c8e..e3f92bab1c6e9 100755 --- a/tools/cl2c +++ b/tools/cl2c @@ -3,6 +3,22 @@ # OpenCL source as a C string. Also adds a #line directive so that # compiler messages are useful. +# This file is part of FFmpeg. +# +# FFmpeg is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# FFmpeg is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with FFmpeg; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + input="$1" output="$2" From 6e0723470bea258ceb72ee4c4916cf8f80337f92 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Thu, 23 Nov 2017 00:58:36 +0000 Subject: [PATCH 1070/2557] opus_pvq: fix crashing on analysis of mono Signed-off-by: Rostislav Pehlivanov --- libavcodec/opus_pvq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/opus_pvq.c b/libavcodec/opus_pvq.c index f98b85d36fd33..2f7aa74da49ea 100644 --- a/libavcodec/opus_pvq.c +++ b/libavcodec/opus_pvq.c @@ -925,7 +925,8 @@ static float pvq_band_cost(CeltPVQ *pvq, CeltFrame *f, OpusRangeCoder *rc, int b for (i = 0; i < band_size; i++) { err_x += (X[i] - X_orig[i])*(X[i] - X_orig[i]); - err_y += (Y[i] - Y_orig[i])*(Y[i] - Y_orig[i]); + if (Y) + err_y += (Y[i] - Y_orig[i])*(Y[i] - Y_orig[i]); } dist = sqrtf(err_x) + sqrtf(err_y); From 8b62647a5fea94fd5fede91f8371e983e1bda40c Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Thu, 23 Nov 2017 02:57:24 +0100 Subject: [PATCH 1071/2557] lavf/mov: Read aspect ratio from AVID jpeg2000 mov files. --- libavformat/mov.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index 9e876efc8c3f0..f3e86dfc6df06 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1733,6 +1733,7 @@ static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom) par->width = 1440; return 0; } else if ((par->codec_tag == MKTAG('A', 'V', 'd', '1') || + par->codec_tag == MKTAG('A', 'V', 'j', '2') || par->codec_tag == MKTAG('A', 'V', 'd', 'n')) && atom.size >= 24) { int num, den; From 136e7cf64ce9e78de7158d6720539d51cb96b743 Mon Sep 17 00:00:00 2001 From: "Li, Zhong" Date: Fri, 10 Nov 2017 03:03:42 -0500 Subject: [PATCH 1072/2557] qsv/hevcdec: Load hw plugin by default on non-windows os Software plugin is not available on Linux, Only works on Windows. Similar changes have been applied to qsv hevc encoder by b05128f3c953bd66483e697d60a2e7e45ee9cfa0. Signed-off-by: Zhong Li Signed-off-by: Maxym Dmytrychenko --- libavcodec/qsvdec_h2645.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c index a2a6cc3c47464..e3184d87494d3 100644 --- a/libavcodec/qsvdec_h2645.c +++ b/libavcodec/qsvdec_h2645.c @@ -171,6 +171,12 @@ static void qsv_decode_flush(AVCodecContext *avctx) ff_qsv_decode_flush(avctx, &s->qsv); } +#if defined(_WIN32) +#define LOAD_PLUGIN_DEFAULT LOAD_PLUGIN_HEVC_SW +#else +#define LOAD_PLUGIN_DEFAULT LOAD_PLUGIN_HEVC_HW +#endif + #define OFFSET(x) offsetof(QSVH2645Context, x) #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM @@ -187,7 +193,7 @@ AVHWAccel ff_hevc_qsv_hwaccel = { static const AVOption hevc_options[] = { { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD }, - { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_HEVC_SW }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VD, "load_plugin" }, + { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_DEFAULT }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VD, "load_plugin" }, { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VD, "load_plugin" }, { "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VD, "load_plugin" }, { "hevc_hw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_HW }, 0, 0, VD, "load_plugin" }, From cce33ed10fdceda7e634ed8b01cf616d34505924 Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Wed, 22 Nov 2017 15:28:40 +0000 Subject: [PATCH 1073/2557] Revert "udp: fix compilation when HAVE_PTHREAD_CANCEL isnt defined" This was an mplayer-specific hack. This reverts commit a4f94f24b4f153c30bbcaa700bedfb2b3a581e5e. Signed-off-by: Derek Buitenhuis --- libavformat/udp.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavformat/udp.c b/libavformat/udp.c index 3835f989c42ba..0dde0353fbe82 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -64,10 +64,6 @@ #include #endif -#ifndef HAVE_PTHREAD_CANCEL -#define HAVE_PTHREAD_CANCEL 0 -#endif - #ifndef IPV6_ADD_MEMBERSHIP #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP From 515555af6c1737102d24b783f6316a1cdeca6511 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 22:02:07 +0100 Subject: [PATCH 1074/2557] avcodec/x86/exrdsp : use ymm constant for pb_80 speed seems to be similar, but simplify code --- libavcodec/x86/exrdsp.asm | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libavcodec/x86/exrdsp.asm b/libavcodec/x86/exrdsp.asm index 23c9397ef8f84..3bf240c8b1332 100644 --- a/libavcodec/x86/exrdsp.asm +++ b/libavcodec/x86/exrdsp.asm @@ -73,11 +73,7 @@ REORDER_PIXELS %macro PREDICTOR 0 cglobal predictor, 2,2,5, src, size -%if mmsize == 32 - vbroadcasti128 m0, [pb_80] -%else - mova xm0, [pb_80] -%endif + mova m0, [pb_80] mova xm1, [pb_15] mova xm2, xm0 add srcq, sizeq From 5f278620b82610588a4db208c020a32a32c6828c Mon Sep 17 00:00:00 2001 From: Werner Robitza Date: Thu, 23 Nov 2017 13:16:53 +0100 Subject: [PATCH 1075/2557] doc/filters.texi: explain infinite looping Explain how to achieve infinite looping with the loop / aloop filters. Signed-off-by: Werner Robitza --- doc/filters.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 04a8139c6de45..b8a4d032e0d59 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1144,7 +1144,7 @@ The filter accepts the following options: @table @option @item loop -Set the number of loops. +Set the number of loops. Setting this value to -1 will result in infinite loops. @item size Set maximal number of samples. @@ -9991,7 +9991,7 @@ The filter accepts the following options: @table @option @item loop -Set the number of loops. +Set the number of loops. Setting this value to -1 will result in infinite loops. @item size Set maximal size in number of frames. From a60b2425c3beaa214af59611988b9ae6c370933c Mon Sep 17 00:00:00 2001 From: Lou Logan Date: Thu, 23 Nov 2017 11:54:26 -0900 Subject: [PATCH 1076/2557] doc/filters: mention (a)loop defaults Signed-off-by: Lou Logan --- doc/filters.texi | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index b8a4d032e0d59..bee626e775bd3 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1145,12 +1145,13 @@ The filter accepts the following options: @table @option @item loop Set the number of loops. Setting this value to -1 will result in infinite loops. +Default is 0. @item size -Set maximal number of samples. +Set maximal number of samples. Default is 0. @item start -Set first sample of loop. +Set first sample of loop. Default is 0. @end table @anchor{amerge} @@ -9992,12 +9993,13 @@ The filter accepts the following options: @table @option @item loop Set the number of loops. Setting this value to -1 will result in infinite loops. +Default is 0. @item size -Set maximal size in number of frames. +Set maximal size in number of frames. Default is 0. @item start -Set first frame of loop. +Set first frame of loop. Default is 0. @end table @anchor{lut3d} From ef8979f1992fd7753c2a236ac219a7147b7fe99a Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 23 Nov 2017 19:11:17 -0300 Subject: [PATCH 1077/2557] avfilter/Makefile: skip building opencl.h when opencl is disabled Fixes make checkheaders. Signed-off-by: James Almer --- libavfilter/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 89737b5ad0db6..ec0deff86f7e9 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -398,6 +398,7 @@ SKIPHEADERS-$(CONFIG_LIBVIDSTAB) += vidstabutils.h OBJS-$(CONFIG_SHARED) += log2_tab.o SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h +SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h TOOLS = graph2dot TESTPROGS = drawutils filtfmts formats integral From f335efc0add8b32b0fe7223c3d897a5e41edbf64 Mon Sep 17 00:00:00 2001 From: Karthick J Date: Fri, 24 Nov 2017 06:41:25 +0800 Subject: [PATCH 1078/2557] avformat/hlsenc: Minor fix in setting http options for master playlist --- libavformat/hlsenc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 3c47ced30d96c..525605b8f564b 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1089,8 +1089,7 @@ static int create_master_playlist(AVFormatContext *s, return 0; } - if (hls->user_agent) - av_dict_set(&options, "user-agent", hls->user_agent, 0); + set_http_options(s, &options, hls); ret = s->io_open(s, &master_pb, hls->master_m3u8_url, AVIO_FLAG_WRITE,\ &options); From 241c1192d6b8db17f4ea6055573417a4830d5cc6 Mon Sep 17 00:00:00 2001 From: Karthick J Date: Fri, 24 Nov 2017 06:42:35 +0800 Subject: [PATCH 1079/2557] avformat/hlsenc: Refactor an inconsistent variable name --- libavformat/hlsenc.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 525605b8f564b..611cc99b6e4da 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1074,7 +1074,7 @@ static int create_master_playlist(AVFormatContext *s, AVDictionary *options = NULL; unsigned int i, j; int m3u8_name_size, ret, bandwidth; - char *m3U8_rel_name; + char *m3u8_rel_name; input_vs->m3u8_created = 1; if (!hls->master_m3u8_created) { @@ -1108,14 +1108,14 @@ static int create_master_playlist(AVFormatContext *s, vs = &(hls->var_streams[i]); m3u8_name_size = strlen(vs->m3u8_name) + 1; - m3U8_rel_name = av_malloc(m3u8_name_size); - if (!m3U8_rel_name) { + m3u8_rel_name = av_malloc(m3u8_name_size); + if (!m3u8_rel_name) { ret = AVERROR(ENOMEM); goto fail; } - av_strlcpy(m3U8_rel_name, vs->m3u8_name, m3u8_name_size); + av_strlcpy(m3u8_rel_name, vs->m3u8_name, m3u8_name_size); ret = get_relative_url(hls->master_m3u8_url, vs->m3u8_name, - m3U8_rel_name, m3u8_name_size); + m3u8_rel_name, m3u8_name_size); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Unable to find relative URL\n"); goto fail; @@ -1145,7 +1145,7 @@ static int create_master_playlist(AVFormatContext *s, if (!bandwidth) { av_log(NULL, AV_LOG_WARNING, "Bandwidth info not available, set audio and video bitrates\n"); - av_freep(&m3U8_rel_name); + av_freep(&m3u8_rel_name); continue; } @@ -1153,14 +1153,14 @@ static int create_master_playlist(AVFormatContext *s, if (vid_st && vid_st->codecpar->width > 0 && vid_st->codecpar->height > 0) avio_printf(master_pb, ",RESOLUTION=%dx%d", vid_st->codecpar->width, vid_st->codecpar->height); - avio_printf(master_pb, "\n%s\n\n", m3U8_rel_name); + avio_printf(master_pb, "\n%s\n\n", m3u8_rel_name); - av_freep(&m3U8_rel_name); + av_freep(&m3u8_rel_name); } fail: if(ret >=0) hls->master_m3u8_created = 1; - av_freep(&m3U8_rel_name); + av_freep(&m3u8_rel_name); ff_format_io_close(s, &master_pb); return ret; } From efb51c8ebbe21f701da816bb78aefc0ce98b378d Mon Sep 17 00:00:00 2001 From: Karthick J Date: Fri, 24 Nov 2017 06:57:36 +0800 Subject: [PATCH 1080/2557] avformat/hlsenc: Added option to add EXT-X-INDEPENDENT-SEGMENTS tag --- doc/muxers.texi | 4 ++++ libavformat/hlsenc.c | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/doc/muxers.texi b/doc/muxers.texi index 0bb8ad2e2b97d..9d9ca31cc4fb4 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -737,6 +737,10 @@ The file specified by @code{hls_key_info_file} will be checked periodically and detect updates to the encryption info. Be sure to replace this file atomically, including the file containing the AES encryption key. +@item independent_segments +Add the @code{#EXT-X-INDEPENDENT-SEGMENTS} to playlists that has video segments +and when all the segments of that playlist are guaranteed to start with a Key frame. + @item split_by_time Allow segments to start on frames other than keyframes. This improves behavior on some players when the time between keyframes is inconsistent, diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 611cc99b6e4da..30ccf73d76e77 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -88,6 +88,7 @@ typedef enum HLSFlags { HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) in segment filenames when use_localtime e.g.: %%014s HLS_TEMP_FILE = (1 << 11), HLS_PERIODIC_REKEY = (1 << 12), + HLS_INDEPENDENT_SEGMENTS = (1 << 13), } HLSFlags; typedef enum { @@ -1190,6 +1191,10 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) sequence = 0; } + if (hls->flags & HLS_INDEPENDENT_SEGMENTS) { + hls->version = 6; + } + if (hls->segment_type == SEGMENT_TYPE_FMP4) { hls->version = 7; } @@ -1219,6 +1224,9 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) avio_printf(out, "#EXT-X-DISCONTINUITY\n"); vs->discontinuity_set = 1; } + if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) { + avio_printf(out, "#EXT-X-INDEPENDENT-SEGMENTS\n"); + } for (en = vs->segments; en; en = en->next) { if ((hls->encrypt || hls->key_info_file) && (!key_uri || strcmp(en->key_uri, key_uri) || av_strcasecmp(en->iv_string, iv_string))) { @@ -1731,6 +1739,14 @@ static int hls_write_header(AVFormatContext *s) vs->start_pts = AV_NOPTS_VALUE; vs->current_segment_final_filename_fmt[0] = '\0'; + if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) { + // Independent segments cannot be guaranteed when splitting by time + hls->flags &= ~HLS_INDEPENDENT_SEGMENTS; + av_log(s, AV_LOG_WARNING, + "'split_by_time' and 'independent_segments' cannot be enabled together. " + "Disabling 'independent_segments' flag\n"); + } + if (hls->flags & HLS_PROGRAM_DATE_TIME) { time_t now0; time(&now0); @@ -2322,6 +2338,7 @@ static const AVOption options[] = { {"second_level_segment_duration", "include segment duration in segment filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SECOND_LEVEL_SEGMENT_DURATION }, 0, UINT_MAX, E, "flags"}, {"second_level_segment_size", "include segment size in segment filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SECOND_LEVEL_SEGMENT_SIZE }, 0, UINT_MAX, E, "flags"}, {"periodic_rekey", "reload keyinfo file periodically for re-keying", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PERIODIC_REKEY }, 0, UINT_MAX, E, "flags"}, + {"independent_segments", "add EXT-X-INDEPENDENT-SEGMENTS, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_INDEPENDENT_SEGMENTS }, 0, UINT_MAX, E, "flags"}, {"use_localtime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, {"use_localtime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, {"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type), AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E, "pl_type" }, From 7c191dfba76ce23e3605d2866f11d5c7ffcafd11 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 24 Nov 2017 03:49:55 +0100 Subject: [PATCH 1081/2557] avcodec/j2kenc: Only allocate cblk.data once Fixes: memleak Found-by: Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 362c7f0f496f3..32c7fddb7416c 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -938,7 +938,8 @@ static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno } } } - prec->cblk[cblkno].data = av_malloc(1 + 8192); + if (!prec->cblk[cblkno].data) + prec->cblk[cblkno].data = av_malloc(1 + 8192); if (!prec->cblk[cblkno].data) return AVERROR(ENOMEM); encode_cblk(s, &t1, prec->cblk + cblkno, tile, xx1 - xx0, yy1 - yy0, From 59365e634552e18bb7f844ba60cba2d62852fe88 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 24 Nov 2017 13:36:26 +0100 Subject: [PATCH 1082/2557] avfilter/af_ladspa: remove duplicate code lines Signed-off-by: Paul B Mahol --- libavfilter/af_ladspa.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavfilter/af_ladspa.c b/libavfilter/af_ladspa.c index 5532dacd73a71..3be26bc849db6 100644 --- a/libavfilter/af_ladspa.c +++ b/libavfilter/af_ladspa.c @@ -318,8 +318,6 @@ static int config_output(AVFilterLink *outlink) ret = 0; } else { - LADSPAContext *s = ctx->priv; - outlink->sample_rate = s->sample_rate; outlink->time_base = (AVRational){1, s->sample_rate}; From ec5328aa6f3c1650155dd2a257167f4130abb800 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 20 Nov 2017 19:58:44 +0100 Subject: [PATCH 1083/2557] avfilter: add mix filter Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/filters.texi | 28 ++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 4 +- libavfilter/vf_mix.c | 283 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 316 insertions(+), 2 deletions(-) create mode 100644 libavfilter/vf_mix.c diff --git a/Changelog b/Changelog index f6b70c4a34919..6ef144c315f36 100644 --- a/Changelog +++ b/Changelog @@ -18,6 +18,7 @@ version : - mcompand audio filter - acontrast audio filter - OpenCL overlay filter +- video mix filter version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index bee626e775bd3..76929e4db52f2 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -10569,6 +10569,34 @@ Default method is @samp{fdiff}. Scene change detection threshold. Default is @code{5.0}. @end table +@section mix + +Mix several video input streams into one video stream. + +A description of the accepted options follows. + +@table @option +@item nb_inputs +The number of inputs. If unspecified, it defaults to 2. + +@item weights +Specify weight of each input video stream as sequence. +Each weight is separated by space. + +@item duration +Specify how end of stream is determined. +@table @samp +@item longest +The duration of the longest input. (default) + +@item shortest +The duration of the shortest input. + +@item first +The duration of the first input. +@end table +@end table + @section mpdecimate Drop frames that do not differ greatly from the previous frame in diff --git a/libavfilter/Makefile b/libavfilter/Makefile index ec0deff86f7e9..c47373a65b802 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -240,6 +240,7 @@ OBJS-$(CONFIG_MESTIMATE_FILTER) += vf_mestimate.o motion_estimation OBJS-$(CONFIG_METADATA_FILTER) += f_metadata.o OBJS-$(CONFIG_MIDEQUALIZER_FILTER) += vf_midequalizer.o framesync.o OBJS-$(CONFIG_MINTERPOLATE_FILTER) += vf_minterpolate.o motion_estimation.o +OBJS-$(CONFIG_MIX_FILTER) += vf_mix.o OBJS-$(CONFIG_MPDECIMATE_FILTER) += vf_mpdecimate.o OBJS-$(CONFIG_NEGATE_FILTER) += vf_lut.o OBJS-$(CONFIG_NLMEANS_FILTER) += vf_nlmeans.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 50e9d9a0cb129..3a9cd00fdf7b6 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -250,6 +250,7 @@ static void register_all(void) REGISTER_FILTER(METADATA, metadata, vf); REGISTER_FILTER(MIDEQUALIZER, midequalizer, vf); REGISTER_FILTER(MINTERPOLATE, minterpolate, vf); + REGISTER_FILTER(MIX, mix, vf); REGISTER_FILTER(MPDECIMATE, mpdecimate, vf); REGISTER_FILTER(NEGATE, negate, vf); REGISTER_FILTER(NLMEANS, nlmeans, vf); diff --git a/libavfilter/version.h b/libavfilter/version.h index b449fd821dda5..3242c44618816 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,8 +30,8 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 2 -#define LIBAVFILTER_VERSION_MICRO 102 +#define LIBAVFILTER_VERSION_MINOR 3 +#define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ diff --git a/libavfilter/vf_mix.c b/libavfilter/vf_mix.c new file mode 100644 index 0000000000000..261ab066efc89 --- /dev/null +++ b/libavfilter/vf_mix.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2017 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "framesync.h" +#include "video.h" + +typedef struct MixContext { + const AVClass *class; + const AVPixFmtDescriptor *desc; + char *weights_str; + int nb_inputs; + int duration; + float *weights; + float wfactor; + + int depth; + int nb_planes; + int linesize[4]; + int height[4]; + + AVFrame **frames; + FFFrameSync fs; +} MixContext; + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *pix_fmts = NULL; + int fmt, ret; + + for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); + if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || + desc->flags & AV_PIX_FMT_FLAG_HWACCEL || + desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) && + (ret = ff_add_format(&pix_fmts, fmt)) < 0) + return ret; + } + + return ff_set_common_formats(ctx, pix_fmts); +} + +static av_cold int init(AVFilterContext *ctx) +{ + MixContext *s = ctx->priv; + char *p, *arg, *saveptr = NULL; + int i, ret; + + s->frames = av_calloc(s->nb_inputs, sizeof(*s->frames)); + if (!s->frames) + return AVERROR(ENOMEM); + + s->weights = av_calloc(s->nb_inputs, sizeof(*s->weights)); + if (!s->weights) + return AVERROR(ENOMEM); + + for (i = 0; i < s->nb_inputs; i++) { + AVFilterPad pad = { 0 }; + + pad.type = AVMEDIA_TYPE_VIDEO; + pad.name = av_asprintf("input%d", i); + if (!pad.name) + return AVERROR(ENOMEM); + + if ((ret = ff_insert_inpad(ctx, i, &pad)) < 0) { + av_freep(&pad.name); + return ret; + } + } + + p = s->weights_str; + for (i = 0; i < s->nb_inputs; i++) { + if (!(arg = av_strtok(p, " ", &saveptr))) + break; + + p = NULL; + sscanf(arg, "%f", &s->weights[i]); + s->wfactor += s->weights[i]; + } + s->wfactor = 1 / s->wfactor; + + return 0; +} + +static int process_frame(FFFrameSync *fs) +{ + AVFilterContext *ctx = fs->parent; + AVFilterLink *outlink = ctx->outputs[0]; + MixContext *s = fs->opaque; + AVFrame **in = s->frames; + AVFrame *out; + int i, p, ret, x, y; + + for (i = 0; i < s->nb_inputs; i++) { + if ((ret = ff_framesync_get_frame(&s->fs, i, &in[i], 0)) < 0) + return ret; + } + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) + return AVERROR(ENOMEM); + out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); + + if (s->depth <= 8) { + for (p = 0; p < s->nb_planes; p++) { + uint8_t *dst = out->data[p]; + + for (y = 0; y < s->height[p]; y++) { + for (x = 0; x < s->linesize[p]; x++) { + int val = 0; + + for (i = 0; i < s->nb_inputs; i++) { + uint8_t src = in[i]->data[p][y * s->linesize[p] + x]; + + val += src * s->weights[i]; + } + + dst[x] = val * s->wfactor; + } + + dst += out->linesize[p]; + } + } + } else { + for (p = 0; p < s->nb_planes; p++) { + uint16_t *dst = (uint16_t *)out->data[p]; + + for (y = 0; y < s->height[p]; y++) { + for (x = 0; x < s->linesize[p]; x++) { + int val = 0; + + for (i = 0; i < s->nb_inputs; i++) { + uint16_t src = AV_RN16(in[i]->data[p] + y * s->linesize[p] + x * 2); + + val += src * s->weights[i]; + } + + dst[x] = val * s->wfactor; + } + + dst += out->linesize[p] / 2; + } + } + } + + return ff_filter_frame(outlink, out); +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + MixContext *s = ctx->priv; + AVRational time_base = ctx->inputs[0]->time_base; + AVRational frame_rate = ctx->inputs[0]->frame_rate; + AVFilterLink *inlink = ctx->inputs[0]; + int height = ctx->inputs[0]->h; + int width = ctx->inputs[0]->w; + FFFrameSyncIn *in; + int i, ret; + + for (i = 1; i < s->nb_inputs; i++) { + if (ctx->inputs[i]->h != height || ctx->inputs[i]->w != width) { + av_log(ctx, AV_LOG_ERROR, "Input %d size (%dx%d) does not match input %d size (%dx%d).\n", i, ctx->inputs[i]->w, ctx->inputs[i]->h, 0, width, height); + return AVERROR(EINVAL); + } + } + + s->desc = av_pix_fmt_desc_get(outlink->format); + if (!s->desc) + return AVERROR_BUG; + s->nb_planes = av_pix_fmt_count_planes(outlink->format); + s->depth = s->desc->comp[0].depth; + + outlink->w = width; + outlink->h = height; + outlink->time_base = time_base; + outlink->frame_rate = frame_rate; + + if ((ret = ff_framesync_init(&s->fs, ctx, s->nb_inputs)) < 0) + return ret; + + in = s->fs.in; + s->fs.opaque = s; + s->fs.on_event = process_frame; + + if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) + return ret; + + s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h); + s->height[0] = s->height[3] = inlink->h; + + for (i = 0; i < s->nb_inputs; i++) { + AVFilterLink *inlink = ctx->inputs[i]; + + in[i].time_base = inlink->time_base; + in[i].sync = 1; + in[i].before = EXT_STOP; + in[i].after = (s->duration == 1 || (s->duration == 2 && i == 0)) ? EXT_STOP : EXT_INFINITY; + } + + return ff_framesync_configure(&s->fs); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + MixContext *s = ctx->priv; + int i; + + ff_framesync_uninit(&s->fs); + av_freep(&s->frames); + av_freep(&s->weights); + + for (i = 0; i < ctx->nb_inputs; i++) + av_freep(&ctx->input_pads[i].name); +} + +static int activate(AVFilterContext *ctx) +{ + MixContext *s = ctx->priv; + return ff_framesync_activate(&s->fs); +} + +#define OFFSET(x) offsetof(MixContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption mix_options[] = { + { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT_MAX, .flags = FLAGS }, + { "weights", "set weight for each input", OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, .flags = FLAGS }, + { "duration", "how to determine end of stream", OFFSET(duration), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, .flags = FLAGS, "duration" }, + { "longest", "Duration of longest input", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "duration" }, + { "shortest", "Duration of shortest input", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "duration" }, + { "first", "Duration of first input", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "duration" }, + { NULL }, +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(mix); + +AVFilter ff_vf_mix = { + .name = "mix", + .description = NULL_IF_CONFIG_SMALL("Mix video inputs."), + .priv_size = sizeof(MixContext), + .priv_class = &mix_class, + .query_formats = query_formats, + .outputs = outputs, + .init = init, + .uninit = uninit, + .activate = activate, + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, +}; From 63826a0b8288c464ef665bb140451f229cfae518 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 24 Nov 2017 17:09:48 +0100 Subject: [PATCH 1084/2557] avfilter/af_amix: make use of av_asprintf() Signed-off-by: Paul B Mahol --- libavfilter/af_amix.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavfilter/af_amix.c b/libavfilter/af_amix.c index 09848e5d91a92..ec764375c0b6a 100644 --- a/libavfilter/af_amix.c +++ b/libavfilter/af_amix.c @@ -490,12 +490,10 @@ static av_cold int init(AVFilterContext *ctx) int i, ret; for (i = 0; i < s->nb_inputs; i++) { - char name[32]; AVFilterPad pad = { 0 }; - snprintf(name, sizeof(name), "input%d", i); pad.type = AVMEDIA_TYPE_AUDIO; - pad.name = av_strdup(name); + pad.name = av_asprintf("input%d", i); if (!pad.name) return AVERROR(ENOMEM); From 03fbc0daa7e37af024f8b017a28105c32bbe25ca Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Fri, 17 Nov 2017 13:35:56 -0800 Subject: [PATCH 1085/2557] avformat/utils: Prevent undefined shift with wrap_bits > 64. 2LL << (wrap_bits=64 - 1) does not fit in int64_t; change the code to use a uint64_t (2ULL) and add an av_assert2() to ensure wrap_bits <= 64. Signed-off-by: Dale Curtis Signed-off-by: Michael Niedermayer --- libavformat/utils.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index ff5e14df6ca3c..e9ac89935c0a3 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1734,13 +1734,14 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) if (next_pkt->dts != AV_NOPTS_VALUE) { int wrap_bits = s->streams[next_pkt->stream_index]->pts_wrap_bits; + av_assert2(wrap_bits <= 64); // last dts seen for this stream. if any of packets following // current one had no dts, we will set this to AV_NOPTS_VALUE. int64_t last_dts = next_pkt->dts; while (pktl && next_pkt->pts == AV_NOPTS_VALUE) { if (pktl->pkt.stream_index == next_pkt->stream_index && - (av_compare_mod(next_pkt->dts, pktl->pkt.dts, 2LL << (wrap_bits - 1)) < 0)) { - if (av_compare_mod(pktl->pkt.pts, pktl->pkt.dts, 2LL << (wrap_bits - 1))) { + av_compare_mod(next_pkt->dts, pktl->pkt.dts, 2ULL << (wrap_bits - 1)) < 0) { + if (av_compare_mod(pktl->pkt.pts, pktl->pkt.dts, 2ULL << (wrap_bits - 1))) { // not B-frame next_pkt->pts = pktl->pkt.dts; } From 9648cc6d7fdbb0a260bed1e3e23300569cff9579 Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Wed, 22 Nov 2017 10:58:39 -0800 Subject: [PATCH 1086/2557] avcodec/vorbis: 1 << 31 > int32_t::max(), so use 1u << 31 instead. Signed-off-by: Dale Curtis Signed-off-by: Michael Niedermayer --- libavcodec/vorbis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vorbis.c b/libavcodec/vorbis.c index ce23b947f0835..5ccc37a2dff86 100644 --- a/libavcodec/vorbis.c +++ b/libavcodec/vorbis.c @@ -91,7 +91,7 @@ int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num) exit_at_level[i] = 0; // construct code (append 0s to end) and introduce new exits for (j = i + 1 ;j <= bits[p]; ++j) - exit_at_level[j] = code + (1 << (j - 1)); + exit_at_level[j] = code + (1u << (j - 1)); codes[p] = code; } From e97667c82f4c3ed813269383f8ea825ffb96204f Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 20 Nov 2017 16:16:11 -0300 Subject: [PATCH 1087/2557] avformat/ttaenc: buffer packets directly This is a bit more robust in case of OOM. Signed-off-by: James Almer --- libavformat/ttaenc.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/libavformat/ttaenc.c b/libavformat/ttaenc.c index fdce1e3dc1c0f..b05705b6b68f3 100644 --- a/libavformat/ttaenc.c +++ b/libavformat/ttaenc.c @@ -29,7 +29,7 @@ typedef struct TTAMuxContext { AVIOContext *seek_table; - AVIOContext *data; + AVPacketList *queue, *queue_end; uint32_t nb_samples; int frame_size; int last_frame; @@ -56,10 +56,6 @@ static int tta_write_header(AVFormatContext *s) if ((ret = avio_open_dyn_buf(&tta->seek_table)) < 0) return ret; - if ((ret = avio_open_dyn_buf(&tta->data)) < 0) { - ffio_free_dyn_buf(&tta->seek_table); - return ret; - } /* Ignore most extradata information if present. It can be innacurate if for example remuxing from Matroska */ @@ -84,8 +80,23 @@ static int tta_write_header(AVFormatContext *s) static int tta_write_packet(AVFormatContext *s, AVPacket *pkt) { TTAMuxContext *tta = s->priv_data; + AVPacketList *pktl = av_mallocz(sizeof(*pktl)); + int ret; + + if (!pktl) + return AVERROR(ENOMEM); + + ret = av_packet_ref(&pktl->pkt, pkt); + if (ret < 0) { + av_free(pktl); + return ret; + } + if (tta->queue_end) + tta->queue_end->next = pktl; + else + tta->queue = pktl; + tta->queue_end = pktl; - avio_write(tta->data, pkt->data, pkt->size); avio_wl32(tta->seek_table, pkt->size); tta->nb_samples += pkt->duration; @@ -106,6 +117,21 @@ static int tta_write_packet(AVFormatContext *s, AVPacket *pkt) return 0; } +static void tta_queue_flush(AVFormatContext *s) +{ + TTAMuxContext *tta = s->priv_data; + AVPacketList *pktl; + + while (pktl = tta->queue) { + AVPacket *pkt = &pktl->pkt; + avio_write(s->pb, pkt->data, pkt->size); + av_packet_unref(pkt); + tta->queue = pktl->next; + av_free(pktl); + } + tta->queue_end = NULL; +} + static int tta_write_trailer(AVFormatContext *s) { TTAMuxContext *tta = s->priv_data; @@ -125,9 +151,7 @@ static int tta_write_trailer(AVFormatContext *s) av_free(ptr); /* Write audio data */ - size = avio_close_dyn_buf(tta->data, &ptr); - avio_write(s->pb, ptr, size); - av_free(ptr); + tta_queue_flush(s); ff_ape_write_tag(s); avio_flush(s->pb); From fa4121507ca426d3640268cb87c8c1bc547a6103 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 20 Nov 2017 17:43:23 -0300 Subject: [PATCH 1088/2557] avformat/ttaenc: add tta_init() Signed-off-by: James Almer --- libavformat/ttaenc.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/libavformat/ttaenc.c b/libavformat/ttaenc.c index b05705b6b68f3..add15873d048f 100644 --- a/libavformat/ttaenc.c +++ b/libavformat/ttaenc.c @@ -35,16 +35,17 @@ typedef struct TTAMuxContext { int last_frame; } TTAMuxContext; -static int tta_write_header(AVFormatContext *s) +static int tta_init(AVFormatContext *s) { TTAMuxContext *tta = s->priv_data; - AVCodecParameters *par = s->streams[0]->codecpar; - int ret; + AVCodecParameters *par; if (s->nb_streams != 1) { av_log(s, AV_LOG_ERROR, "Only one stream is supported\n"); return AVERROR(EINVAL); } + par = s->streams[0]->codecpar; + if (par->codec_id != AV_CODEC_ID_TTA) { av_log(s, AV_LOG_ERROR, "Unsupported codec\n"); return AVERROR(EINVAL); @@ -54,6 +55,23 @@ static int tta_write_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } + /* Prevent overflow */ + if (par->sample_rate > 0x7FFFFFu) { + av_log(s, AV_LOG_ERROR, "Sample rate too large\n"); + return AVERROR(EINVAL); + } + tta->frame_size = par->sample_rate * 256 / 245; + avpriv_set_pts_info(s->streams[0], 64, 1, par->sample_rate); + + return 0; +} + +static int tta_write_header(AVFormatContext *s) +{ + TTAMuxContext *tta = s->priv_data; + AVCodecParameters *par = s->streams[0]->codecpar; + int ret; + if ((ret = avio_open_dyn_buf(&tta->seek_table)) < 0) return ret; @@ -66,13 +84,6 @@ static int tta_write_header(AVFormatContext *s) avio_wl16(s->pb, par->channels); avio_wl16(s->pb, par->bits_per_raw_sample); avio_wl32(s->pb, par->sample_rate); - /* Prevent overflow */ - if (par->sample_rate > 0x7FFFFFu) { - av_log(s, AV_LOG_ERROR, "Sample rate too large\n"); - return AVERROR(EINVAL); - } - tta->frame_size = par->sample_rate * 256 / 245; - avpriv_set_pts_info(s->streams[0], 64, 1, par->sample_rate); return 0; } @@ -167,6 +178,7 @@ AVOutputFormat ff_tta_muxer = { .priv_data_size = sizeof(TTAMuxContext), .audio_codec = AV_CODEC_ID_TTA, .video_codec = AV_CODEC_ID_NONE, + .init = tta_init, .write_header = tta_write_header, .write_packet = tta_write_packet, .write_trailer = tta_write_trailer, From b843b343d8a3210ae37a2342b1904a5bd1e5fc6e Mon Sep 17 00:00:00 2001 From: "Li, Zhong" Date: Mon, 27 Nov 2017 11:19:57 -0500 Subject: [PATCH 1089/2557] qsvenc: cavlc option is only available for h264 Moving option definition to h264 implementation and fixing command line defaults in order to properly respect cavlc input value Signed-off-by: Zhong Li Signed-off-by: Maxym Dmytrychenko --- libavcodec/qsvenc.c | 17 +++++++++-------- libavcodec/qsvenc.h | 3 +-- libavcodec/qsvenc_h264.c | 5 ++++- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index c7e5947361d9e..9db9eb375cf3f 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -540,19 +540,20 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) if (avctx->codec_id != AV_CODEC_ID_HEVC) { q->extco.Header.BufferId = MFX_EXTBUFF_CODING_OPTION; q->extco.Header.BufferSz = sizeof(q->extco); -#if FF_API_CODER_TYPE -FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->coder_type != 0) - q->cavlc = avctx->coder_type == FF_CODER_TYPE_VLC; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - q->extco.CAVLC = q->cavlc ? MFX_CODINGOPTION_ON - : MFX_CODINGOPTION_UNKNOWN; if (q->rdo >= 0) q->extco.RateDistortionOpt = q->rdo > 0 ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; if (avctx->codec_id == AV_CODEC_ID_H264) { +#if FF_API_CODER_TYPE +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->coder_type >= 0) + q->cavlc = avctx->coder_type == FF_CODER_TYPE_VLC; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + q->extco.CAVLC = q->cavlc ? MFX_CODINGOPTION_ON + : MFX_CODINGOPTION_UNKNOWN; + if (avctx->strict_std_compliance != FF_COMPLIANCE_NORMAL) q->extco.NalHrdConformance = avctx->strict_std_compliance > FF_COMPLIANCE_NORMAL ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index a6399040e91ce..9b0b84b919374 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -66,8 +66,7 @@ { "extbrc", "Extended bitrate control", OFFSET(qsv.extbrc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "adaptive_i", "Adaptive I-frame placement", OFFSET(qsv.adaptive_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "adaptive_b", "Adaptive B-frame placement", OFFSET(qsv.adaptive_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ -{ "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ -{ "cavlc", "Enable CAVLC", OFFSET(qsv.cavlc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, \ +{ "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, typedef struct QSVEncContext { AVCodecContext *avctx; diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index a968dcfdf5bc0..1365faccea063 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -67,6 +67,7 @@ static av_cold int qsv_enc_close(AVCodecContext *avctx) static const AVOption options[] = { QSV_COMMON_OPTS + { "cavlc", "Enable CAVLC", OFFSET(qsv.cavlc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, { "idr_interval", "Distance (in I-frames) between IDR frames", OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, { "single_sei_nal_unit", "Put all the SEI messages into one NALU", OFFSET(qsv.single_sei_nal_unit), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, { "max_dec_frame_buffering", "Maximum number of frames buffered in the DPB", OFFSET(qsv.max_dec_frame_buffering), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE }, @@ -106,7 +107,9 @@ static const AVCodecDefault qsv_enc_defaults[] = { // same as the x264 default { "g", "250" }, { "bf", "3" }, - { "coder", "ac" }, +#if FF_API_CODER_TYPE + { "coder", "-1" }, +#endif { "flags", "+cgop" }, #if FF_API_PRIVATE_OPT From 4186a77f26a82b4e15109d3286d6de98c2cfe7b6 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Fri, 24 Nov 2017 10:05:49 -0800 Subject: [PATCH 1090/2557] avcodec/nvdec: Round up odd width/height values nvdec will not produce odd width/height output, and while this is basically never an issue with most codecs, due to internal alignment requirements, you can get odd sized jpegs. If an odd-sized jpeg is encountered, nvdec will actually round down internally and produce output that is slightly smaller. This isn't the end of the world, as long as you know the output size doesn't match the original image resolution. However, with an hwaccel, we don't know. The decoder controls the reported output size and the hwaccel cannot change it. I was able to trigger an error in mpv where it tries to copy the output surface as part of rendering and triggers a cuda error because cuda knows the output frame is smaller than expected. To fix this, we can round up the configured width/height passed to nvdec so that the frames are always at least as large as the decoder's reported size, and data can be copied out safely. In this particular jpeg case, you end up with a blank (green) line at the bottom due to nvdec refusing to decode the last line, but the behaviour matches cuviddec, so it's as good as you're going to get. --- libavcodec/nvdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index 0a39927031c16..da4451a739dc4 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -532,8 +532,8 @@ int ff_nvdec_frame_params(AVCodecContext *avctx, } frames_ctx->format = AV_PIX_FMT_CUDA; - frames_ctx->width = avctx->coded_width; - frames_ctx->height = avctx->coded_height; + frames_ctx->width = (avctx->coded_width + 1) & ~1; + frames_ctx->height = (avctx->coded_height + 1) & ~1; frames_ctx->initial_pool_size = dpb_size; switch (sw_desc->comp[0].depth) { From 31de45d20b1ff90d4baf7c5a65e88f582efdb2a6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 24 Nov 2017 17:46:16 -0300 Subject: [PATCH 1091/2557] avformat/utils: fix mixed declarations and code Signed-off-by: James Almer --- libavformat/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index e9ac89935c0a3..84e49208b84eb 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1734,10 +1734,10 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) if (next_pkt->dts != AV_NOPTS_VALUE) { int wrap_bits = s->streams[next_pkt->stream_index]->pts_wrap_bits; - av_assert2(wrap_bits <= 64); // last dts seen for this stream. if any of packets following // current one had no dts, we will set this to AV_NOPTS_VALUE. int64_t last_dts = next_pkt->dts; + av_assert2(wrap_bits <= 64); while (pktl && next_pkt->pts == AV_NOPTS_VALUE) { if (pktl->pkt.stream_index == next_pkt->stream_index && av_compare_mod(next_pkt->dts, pktl->pkt.dts, 2ULL << (wrap_bits - 1)) < 0) { From 12a511f2c265d6319b7fdc332a6aa8aca1535309 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 22 Nov 2017 20:18:40 +0100 Subject: [PATCH 1092/2557] avcodec/sbrdsp_fixed: Fix integer overflow Fixes: signed integer overflow: 2147483598 + 64 cannot be represented in type 'int' Fixes: 4337/clusterfuzz-testcase-minimized-6192658616680448 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/sbrdsp_fixed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/sbrdsp_fixed.c b/libavcodec/sbrdsp_fixed.c index a0ef6859f1a71..57d98da97997f 100644 --- a/libavcodec/sbrdsp_fixed.c +++ b/libavcodec/sbrdsp_fixed.c @@ -133,7 +133,7 @@ static av_always_inline SoftFloat autocorr_calc(int64_t accu) round = 1U << (nz-1); mant = (int)((accu + round) >> nz); - mant = (mant + 0x40)>>7; + mant = (mant + 0x40LL)>>7; mant *= 64; expo = nz + 15; return av_int2sf(mant, 30 - expo); From a1f8f1340accda1a59d45f3344430e393badc963 Mon Sep 17 00:00:00 2001 From: Karthick J Date: Wed, 22 Nov 2017 13:50:03 +0530 Subject: [PATCH 1093/2557] avformat/dashenc: Associate mpd extension with dash muxer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: 刘歧 Signed-off-by: Michael Niedermayer --- libavformat/dashenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 201668a4a4321..0fee3cd86a6df 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1219,6 +1219,7 @@ static const AVClass dash_class = { AVOutputFormat ff_dash_muxer = { .name = "dash", .long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"), + .extensions = "mpd", .priv_data_size = sizeof(DASHContext), .audio_codec = AV_CODEC_ID_AAC, .video_codec = AV_CODEC_ID_H264, From bdddcb7b030d075dffa2989222d687106c06d50c Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Fri, 24 Nov 2017 08:18:16 -0800 Subject: [PATCH 1094/2557] lavf/mov: fix crash in mov_read_sidx Use correct index into streams Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index f3e86dfc6df06..ddb1e59b8569a 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4816,7 +4816,7 @@ static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom) MOVFragmentStreamInfo * si; si = &item->stream_info[j]; if (si->sidx_pts != AV_NOPTS_VALUE) { - ref_st = c->fc->streams[i]; + ref_st = c->fc->streams[j]; ref_sc = ref_st->priv_data; break; } From 279d2599dd6be8e2030a4543b4efa245fd75de5c Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 23 Nov 2017 20:22:56 +0100 Subject: [PATCH 1095/2557] ffmpeg libopusdec: fix missing include file in libopusdec.c This patch fixes the following error when compiling mplayer with libopus. libavcodec/libopusdec.c: In function 'libopus_decode_init': libavcodec/libopusdec.c:130:27: error: implicit declaration of function 'ff_exp10'; did you mean 'ff_exp2fi'? [-Werror=implicit-function-declaration] double gain_lin = ff_exp10(gain_db / (20.0 * 256)); ^~~~~~~~ ff_exp2fi Signed-off-by: Mikulas Patocka Signed-off-by: Michael Niedermayer --- libavcodec/libopusdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c index 9dab0fdf65c20..9b1e002cebc84 100644 --- a/libavcodec/libopusdec.c +++ b/libavcodec/libopusdec.c @@ -24,6 +24,7 @@ #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/ffmath.h" #include "avcodec.h" #include "internal.h" From 7d4fe0c5cb9501efc4a434053cec85a70cae156e Mon Sep 17 00:00:00 2001 From: Richard Ling Date: Tue, 21 Nov 2017 21:32:06 +1100 Subject: [PATCH 1096/2557] avfilter: add normalize filter --- Changelog | 1 + doc/filters.texi | 80 ++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- libavfilter/vf_normalize.c | 386 +++++++++++++++++++++++++++++++++++++ 6 files changed, 470 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_normalize.c diff --git a/Changelog b/Changelog index 6ef144c315f36..0b7e02392dfc2 100644 --- a/Changelog +++ b/Changelog @@ -19,6 +19,7 @@ version : - acontrast audio filter - OpenCL overlay filter - video mix filter +- video normalize filter version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index 76929e4db52f2..fda789630b2c2 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -10867,6 +10867,86 @@ Add temporal and uniform noise to input video: noise=alls=20:allf=t+u @end example +@section normalize + +Normalize RGB video (aka histogram stretching, contrast stretching). +See: https://en.wikipedia.org/wiki/Normalization_(image_processing) + +For each channel of each frame, the filter computes the input range and maps +it linearly to the user-specified output range. The output range defaults +to the full dynamic range from pure black to pure white. + +Temporal smoothing can be used on the input range to reduce flickering (rapid +changes in brightness) caused when small dark or bright objects enter or leave +the scene. This is similar to the auto-exposure (automatic gain control) on a +video camera, and, like a video camera, it may cause a period of over- or +under-exposure of the video. + +The R,G,B channels can be normalized independently, which may cause some +color shifting, or linked together as a single channel, which prevents +color shifting. Linked normalization preserves hue. Independent normalization +does not, so it can be used to remove some color casts. Independent and linked +normalization can be combined in any ratio. + +The normalize filter accepts the following options: + +@table @option +@item blackpt +@item whitept +Colors which define the output range. The minimum input value is mapped to +the @var{blackpt}. The maximum input value is mapped to the @var{whitept}. +The defaults are black and white respectively. Specifying white for +@var{blackpt} and black for @var{whitept} will give color-inverted, +normalized video. Shades of grey can be used to reduce the dynamic range +(contrast). Specifying saturated colors here can create some interesting +effects. + +@item smoothing +The number of previous frames to use for temporal smoothing. The input range +of each channel is smoothed using a rolling average over the current frame +and the @var{smoothing} previous frames. The default is 0 (no temporal +smoothing). + +@item independence +Controls the ratio of independent (color shifting) channel normalization to +linked (color preserving) normalization. 0.0 is fully linked, 1.0 is fully +independent. Defaults to 1.0 (fully independent). + +@item strength +Overall strength of the filter. 1.0 is full strength. 0.0 is a rather +expensive no-op. Defaults to 1.0 (full strength). + +@end table + +@subsection Examples + +Stretch video contrast to use the full dynamic range, with no temporal +smoothing; may flicker depending on the source content: +@example +normalize=blackpt=black:whitept=white:smoothing=0 +@end example + +As above, but with 50 frames of temporal smoothing; flicker should be +reduced, depending on the source content: +@example +normalize=blackpt=black:whitept=white:smoothing=50 +@end example + +As above, but with hue-preserving linked channel normalization: +@example +normalize=blackpt=black:whitept=white:smoothing=50:independence=0 +@end example + +As above, but with half strength: +@example +normalize=blackpt=black:whitept=white:smoothing=50:independence=0:strength=0.5 +@end example + +Map the darkest input color to red, the brightest input color to cyan: +@example +normalize=blackpt=red:whitept=cyan +@end example + @section null Pass the video source unchanged to the output. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index c47373a65b802..dd195d253848a 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -247,6 +247,7 @@ OBJS-$(CONFIG_NLMEANS_FILTER) += vf_nlmeans.o OBJS-$(CONFIG_NNEDI_FILTER) += vf_nnedi.o OBJS-$(CONFIG_NOFORMAT_FILTER) += vf_format.o OBJS-$(CONFIG_NOISE_FILTER) += vf_noise.o +OBJS-$(CONFIG_NORMALIZE_FILTER) += vf_normalize.o OBJS-$(CONFIG_NULL_FILTER) += vf_null.o OBJS-$(CONFIG_OCR_FILTER) += vf_ocr.o OBJS-$(CONFIG_OCV_FILTER) += vf_libopencv.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 3a9cd00fdf7b6..e09d8413875e3 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -257,6 +257,7 @@ static void register_all(void) REGISTER_FILTER(NNEDI, nnedi, vf); REGISTER_FILTER(NOFORMAT, noformat, vf); REGISTER_FILTER(NOISE, noise, vf); + REGISTER_FILTER(NORMALIZE, normalize, vf); REGISTER_FILTER(NULL, null, vf); REGISTER_FILTER(OCR, ocr, vf); REGISTER_FILTER(OCV, ocv, vf); diff --git a/libavfilter/version.h b/libavfilter/version.h index 3242c44618816..fdcf76befee2b 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 3 +#define LIBAVFILTER_VERSION_MINOR 4 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_normalize.c b/libavfilter/vf_normalize.c new file mode 100644 index 0000000000000..5c1fe98c60c23 --- /dev/null +++ b/libavfilter/vf_normalize.c @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2017 Richard Ling + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Normalize RGB video (aka histogram stretching, contrast stretching). + * See: https://en.wikipedia.org/wiki/Normalization_(image_processing) + * + * For each channel of each frame, the filter computes the input range and maps + * it linearly to the user-specified output range. The output range defaults + * to the full dynamic range from pure black to pure white. + * + * Naively maximising the dynamic range of each frame of video in isolation + * may cause flickering (rapid changes in brightness of static objects in the + * scene) when small dark or bright objects enter or leave the scene. This + * filter can apply temporal smoothing to the input range to reduce flickering. + * Temporal smoothing is similar to the auto-exposure (automatic gain control) + * on a video camera, which performs the same function; and, like a video + * camera, it may cause a period of over- or under-exposure of the video. + * + * The filter can normalize the R,G,B channels independently, which may cause + * color shifting, or link them together as a single channel, which prevents + * color shifting. More precisely, linked normalization preserves hue (as it's + * defined in HSV/HSL color spaces) while independent normalization does not. + * Independent normalization can be used to remove color casts, such as the + * blue cast from underwater video, restoring more natural colors. The filter + * can also combine independent and linked normalization in any ratio. + * + * Finally the overall strength of the filter can be adjusted, from no effect + * to full normalization. + * + * The 5 AVOptions are: + * blackpt, Colors which define the output range. The minimum input value + * whitept is mapped to the blackpt. The maximum input value is mapped to + * the whitept. The defaults are black and white respectively. + * Specifying white for blackpt and black for whitept will give + * color-inverted, normalized video. Shades of grey can be used + * to reduce the dynamic range (contrast). Specifying saturated + * colors here can create some interesting effects. + * + * smoothing The amount of temporal smoothing, expressed in frames (>=0). + * the minimum and maximum input values of each channel are + * smoothed using a rolling average over the current frame and + * that many previous frames of video. Defaults to 0 (no temporal + * smoothing). + * + * independence + * Controls the ratio of independent (color shifting) channel + * normalization to linked (color preserving) normalization. 0.0 + * is fully linked, 1.0 is fully independent. Defaults to fully + * independent. + * + * strength Overall strength of the filter. 1.0 is full strength. 0.0 is + * a rather expensive no-op. Values in between can give a gentle + * boost to low-contrast video without creating an artificial + * over-processed look. The default is full strength. + */ + +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct NormalizeContext { + const AVClass *class; + + // Storage for the corresponding AVOptions + uint8_t blackpt[4]; + uint8_t whitept[4]; + int smoothing; + float independence; + float strength; + + int co[4]; // Offsets to R,G,B,A bytes respectively in each pixel + int num_components; // Number of components in the pixel format + int history_len; // Number of frames to average; based on smoothing factor + int frame_num; // Increments on each frame, starting from 0. + + // Per-extremum, per-channel history, for temporal smoothing. + struct { + uint8_t *history; // History entries. + uint32_t history_sum; // Sum of history entries. + } min[3], max[3]; // Min and max for each channel in {R,G,B}. + uint8_t *history_mem; // Single allocation for above history entries + +} NormalizeContext; + +#define OFFSET(x) offsetof(NormalizeContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption normalize_options[] = { + { "blackpt", "output color to which darkest input color is mapped", OFFSET(blackpt), AV_OPT_TYPE_COLOR, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "whitept", "output color to which brightest input color is mapped", OFFSET(whitept), AV_OPT_TYPE_COLOR, { .str = "white" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "smoothing", "amount of temporal smoothing of the input range, to reduce flicker", OFFSET(smoothing), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX/8, FLAGS }, + { "independence", "proportion of independent to linked channel normalization", OFFSET(independence), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, 1.0, FLAGS }, + { "strength", "strength of filter, from no effect to full normalization", OFFSET(strength), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, 1.0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(normalize); + +// This function is the main guts of the filter. Normalizes the input frame +// into the output frame. The frames are known to have the same dimensions +// and pixel format. +static void normalize(NormalizeContext *s, AVFrame *in, AVFrame *out) +{ + // Per-extremum, per-channel local variables. + struct { + uint8_t in; // Original input byte value for this frame. + float smoothed; // Smoothed input value [0,255]. + float out; // Output value [0,255]. + } min[3], max[3]; // Min and max for each channel in {R,G,B}. + + float rgb_min_smoothed; // Min input range for linked normalization + float rgb_max_smoothed; // Max input range for linked normalization + uint8_t lut[3][256]; // Lookup table + int x, y, c; + + // First, scan the input frame to find, for each channel, the minimum + // (min.in) and maximum (max.in) values present in the channel. + for (c = 0; c < 3; c++) + min[c].in = max[c].in = in->data[0][s->co[c]]; + for (y = 0; y < in->height; y++) { + uint8_t *inp = in->data[0] + y * in->linesize[0]; + uint8_t *outp = out->data[0] + y * out->linesize[0]; + for (x = 0; x < in->width; x++) { + for (c = 0; c < 3; c++) { + min[c].in = FFMIN(min[c].in, inp[s->co[c]]); + max[c].in = FFMAX(max[c].in, inp[s->co[c]]); + } + inp += s->num_components; + outp += s->num_components; + } + } + + // Next, for each channel, push min.in and max.in into their respective + // histories, to determine the min.smoothed and max.smoothed for this frame. + { + int history_idx = s->frame_num % s->history_len; + // Assume the history is not yet full; num_history_vals is the number + // of frames received so far including the current frame. + int num_history_vals = s->frame_num + 1; + if (s->frame_num >= s->history_len) { + //The history is full; drop oldest value and cap num_history_vals. + for (c = 0; c < 3; c++) { + s->min[c].history_sum -= s->min[c].history[history_idx]; + s->max[c].history_sum -= s->max[c].history[history_idx]; + } + num_history_vals = s->history_len; + } + // For each extremum, update history_sum and calculate smoothed value + // as the rolling average of the history entries. + for (c = 0; c < 3; c++) { + s->min[c].history_sum += (s->min[c].history[history_idx] = min[c].in); + min[c].smoothed = s->min[c].history_sum / (float)num_history_vals; + s->max[c].history_sum += (s->max[c].history[history_idx] = max[c].in); + max[c].smoothed = s->max[c].history_sum / (float)num_history_vals; + } + } + + // Determine the input range for linked normalization. This is simply the + // minimum of the per-channel minimums, and the maximum of the per-channel + // maximums. + rgb_min_smoothed = FFMIN3(min[0].smoothed, min[1].smoothed, min[2].smoothed); + rgb_max_smoothed = FFMAX3(max[0].smoothed, max[1].smoothed, max[2].smoothed); + + // Now, process each channel to determine the input and output range and + // build the lookup tables. + for (c = 0; c < 3; c++) { + int in_val; + // Adjust the input range for this channel [min.smoothed,max.smoothed] + // by mixing in the correct proportion of the linked normalization + // input range [rgb_min_smoothed,rgb_max_smoothed]. + min[c].smoothed = (min[c].smoothed * s->independence) + + (rgb_min_smoothed * (1.0f - s->independence)); + max[c].smoothed = (max[c].smoothed * s->independence) + + (rgb_max_smoothed * (1.0f - s->independence)); + + // Calculate the output range [min.out,max.out] as a ratio of the full- + // strength output range [blackpt,whitept] and the original input range + // [min.in,max.in], based on the user-specified filter strength. + min[c].out = (s->blackpt[c] * s->strength) + + (min[c].in * (1.0f - s->strength)); + max[c].out = (s->whitept[c] * s->strength) + + (max[c].in * (1.0f - s->strength)); + + // Now, build a lookup table which linearly maps the adjusted input range + // [min.smoothed,max.smoothed] to the output range [min.out,max.out]. + // Perform the linear interpolation for each x: + // lut[x] = (int)(float(x - min.smoothed) * scale + max.out + 0.5) + // where scale = (max.out - min.out) / (max.smoothed - min.smoothed) + if (min[c].smoothed == max[c].smoothed) { + // There is no dynamic range to expand. No mapping for this channel. + for (in_val = min[c].in; in_val <= max[c].in; in_val++) + lut[c][in_val] = min[c].out; + } else { + // We must set lookup values for all values in the original input + // range [min.in,max.in]. Since the original input range may be + // larger than [min.smoothed,max.smoothed], some output values may + // fall outside the [0,255] dynamic range. We need to clamp them. + float scale = (max[c].out - min[c].out) / (max[c].smoothed - min[c].smoothed); + for (in_val = min[c].in; in_val <= max[c].in; in_val++) { + int out_val = (in_val - min[c].smoothed) * scale + min[c].out + 0.5f; + out_val = FFMAX(out_val, 0); + out_val = FFMIN(out_val, 255); + lut[c][in_val] = out_val; + } + } + } + + // Finally, process the pixels of the input frame using the lookup tables. + for (y = 0; y < in->height; y++) { + uint8_t *inp = in->data[0] + y * in->linesize[0]; + uint8_t *outp = out->data[0] + y * out->linesize[0]; + for (x = 0; x < in->width; x++) { + for (c = 0; c < 3; c++) + outp[s->co[c]] = lut[c][inp[s->co[c]]]; + if (s->num_components == 4) + // Copy alpha as-is. + outp[s->co[3]] = inp[s->co[3]]; + inp += s->num_components; + outp += s->num_components; + } + } + + s->frame_num++; +} + +// Now we define all the functions accessible from the ff_vf_normalize class, +// which is ffmpeg's interface to our filter. See doc/filter_design.txt and +// doc/writing_filters.txt for descriptions of what these interface functions +// are expected to do. + +// Set the pixel formats that our filter supports. We should be able to process +// any 8-bit RGB formats. 16-bit support might be useful one day. +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pixel_fmts[] = { + AV_PIX_FMT_RGB24, + AV_PIX_FMT_BGR24, + AV_PIX_FMT_ARGB, + AV_PIX_FMT_RGBA, + AV_PIX_FMT_ABGR, + AV_PIX_FMT_BGRA, + AV_PIX_FMT_0RGB, + AV_PIX_FMT_RGB0, + AV_PIX_FMT_0BGR, + AV_PIX_FMT_BGR0, + AV_PIX_FMT_NONE + }; + // According to filter_design.txt, using ff_set_common_formats() this way + // ensures the pixel formats of the input and output will be the same. That + // saves a bit of effort possibly needing to handle format conversions. + AVFilterFormats *formats = ff_make_format_list(pixel_fmts); + if (!formats) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, formats); +} + +// At this point we know the pixel format used for both input and output. We +// can also access the frame rate of the input video and allocate some memory +// appropriately +static int config_input(AVFilterLink *inlink) +{ + NormalizeContext *s = inlink->dst->priv; + // Store offsets to R,G,B,A bytes respectively in each pixel + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int c; + + for (c = 0; c < 4; ++c) + s->co[c] = desc->comp[c].offset; + s->num_components = desc->nb_components; + // Convert smoothing value to history_len (a count of frames to average, + // must be at least 1). Currently this is a direct assignment, but the + // smoothing value was originally envisaged as a number of seconds. In + // future it would be nice to set history_len using a number of seconds, + // but VFR video is currently an obstacle to doing so. + s->history_len = s->smoothing + 1; + // Allocate the history buffers -- there are 6 -- one for each extrema. + // s->smoothing is limited to INT_MAX/8, so that (s->history_len * 6) + // can't overflow on 32bit causing a too-small allocation. + s->history_mem = av_malloc(s->history_len * 6); + if (s->history_mem == NULL) + return AVERROR(ENOMEM); + + for (c = 0; c < 3; c++) { + s->min[c].history = s->history_mem + (c*2) * s->history_len; + s->max[c].history = s->history_mem + (c*2+1) * s->history_len; + } + return 0; +} + +// Free any memory allocations here +static av_cold void uninit(AVFilterContext *ctx) +{ + NormalizeContext *s = ctx->priv; + + av_freep(&s->history_mem); +} + +// This function is pretty much standard from doc/writing_filters.txt. It +// tries to do in-place filtering where possible, only allocating a new output +// frame when absolutely necessary. +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + NormalizeContext *s = ctx->priv; + AVFrame *out; + // Set 'direct' if we can modify the input frame in-place. Otherwise we + // need to retrieve a new frame from the output link. + int direct = av_frame_is_writable(in) && !ctx->is_disabled; + + if (direct) { + out = in; + } else { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + + // Now we've got the input and output frames (which may be the same frame) + // perform the filtering with our custom function. + normalize(s, in, out); + + if (ctx->is_disabled) { + av_frame_free(&out); + return ff_filter_frame(outlink, in); + } + + if (!direct) + av_frame_free(&in); + + return ff_filter_frame(outlink, out); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_normalize = { + .name = "normalize", + .description = NULL_IF_CONFIG_SMALL("Normalize RGB video."), + .priv_size = sizeof(NormalizeContext), + .priv_class = &normalize_class, + .uninit = uninit, + .query_formats = query_formats, + .inputs = inputs, + .outputs = outputs, +}; From e1d192442780a6b60f75b78092a862bd40141099 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Fri, 24 Nov 2017 12:36:09 +0000 Subject: [PATCH 1097/2557] lavu/pixfmt: Remove gap in the middle of enum AVPixelFormat This was added for compatibility with libav, by leaving a space for formats added in libav to be merged. Since that feature has been removed, we don't need a gap here. Reviewed-by: Michael Niedermayer --- libavutil/pixfmt.h | 2 +- libavutil/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 4c530fead3eb7..e184a56672dc5 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -230,7 +230,7 @@ enum AVPixelFormat { */ AV_PIX_FMT_CUDA, - AV_PIX_FMT_0RGB=0x123+4,///< packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined + AV_PIX_FMT_0RGB, ///< packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined AV_PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined AV_PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined AV_PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined diff --git a/libavutil/version.h b/libavutil/version.h index 3328faebf52c1..41dc6ad40bbf7 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -80,7 +80,7 @@ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 2 +#define LIBAVUTIL_VERSION_MINOR 3 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 89216895757c3dad40379eae939419bb2e736d9d Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 25 Nov 2017 14:51:55 +0000 Subject: [PATCH 1098/2557] doc/APIchanges: Fix lavu versions for OpenCL changes Also fix a typo and fill hashes and dates. --- doc/APIchanges | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 45276f734c745..fecd57387adb3 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,17 +15,17 @@ libavutil: 2017-10-21 API changes, most recent first: -2017-11-xx - xxxxxxx - lavu 55.3.0 - opencl.h - Remove experiental OpenCL API (av_opencl_*). +2017-11-22 - 3650cb2dfa - lavu 55.3.100 - opencl.h + Remove experimental OpenCL API (av_opencl_*). -2017-11-xx - xxxxxxx - lavu 55.2.0 - hwcontext.h hwcontext_opencl.h +2017-11-22 - b25d8ef0a7 - lavu 55.2.100 - hwcontext.h hwcontext_opencl.h Add AV_HWDEVICE_TYPE_OPENCL and a new installed header with OpenCL-specific hwcontext definitions. -2017-11-xx - xxxxxxx - lavu 55.1.0 - pixfmt.h +2017-11-22 - a050f56c09 - lavu 55.1.100 - pixfmt.h Add AV_PIX_FMT_OPENCL. -2017-xx-xx - xxxxxxx - lavc 58.3.100 - avcodec.h +2017-11-11 - 48e4eda11d - lavc 58.3.100 - avcodec.h Add avcodec_get_hw_frames_parameters(). -------- 8< --------- FFmpeg 3.4 was cut here -------- 8< --------- From 4af050c46e2a77fa86894cea5ba2d5f1d3e1f5ea Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 24 Nov 2017 22:48:24 -0300 Subject: [PATCH 1099/2557] configure: remove superfluous cuvid and nvdec checks Both are autodetected, and their dependency on cuda is checked elsewhere. Fixes ticket #6849. Reviewed-by: Philip Langdale Signed-off-by: James Almer --- configure | 4 ---- 1 file changed, 4 deletions(-) diff --git a/configure b/configure index 3ec6407fb205f..7769427ffbc7c 100755 --- a/configure +++ b/configure @@ -5816,10 +5816,6 @@ done # these are off by default, so fail if requested and not available enabled cuda_sdk && require cuda_sdk cuda.h cuCtxCreate -lcuda -enabled cuvid && { enabled cuda || - die "ERROR: CUVID requires CUDA"; } -enabled nvdec && { enabled cuda || - die "ERROR: NVDEC hwaccel requires CUDA"; } enabled chromaprint && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint enabled decklink && { require_header DeckLinkAPI.h && { check_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a060100" || die "ERROR: Decklink API version must be >= 10.6.1."; } } From 8bbf2dacbfb4ead1535dea411035994f507f517d Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 14 Nov 2017 13:02:26 +0000 Subject: [PATCH 1100/2557] hwcontext_d3d11: Log adapter details on device creation This is helpful to know what device has actually been used. --- libavutil/hwcontext_d3d11va.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 65dd6651fc1da..769c81fd77d6a 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -515,8 +515,15 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, hr = mD3D11CreateDevice(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0, D3D11_SDK_VERSION, &device_hwctx->device, NULL, NULL); - if (pAdapter) + if (pAdapter) { + DXGI_ADAPTER_DESC2 desc; + hr = IDXGIAdapter2_GetDesc(pAdapter, &desc); + if (!FAILED(hr)) { + av_log(ctx, AV_LOG_INFO, "Using device %04x:%04x (%ls).\n", + desc.VendorId, desc.DeviceId, desc.Description); + } IDXGIAdapter_Release(pAdapter); + } if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device (%lx)\n", (long)hr); return AVERROR_UNKNOWN; From f4e319d8a94697f21802e2682085599a93a39a57 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 25 Nov 2017 15:34:43 +0000 Subject: [PATCH 1101/2557] hwcontext_opencl: Reset internal command queue on device_uninit device_uninit can be called twice if device_init fails. --- libavutil/hwcontext_opencl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index 8754d739390ed..b00c1b6409f38 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -883,6 +883,7 @@ static void opencl_device_uninit(AVHWDeviceContext *hwdev) av_log(hwdev, AV_LOG_ERROR, "Failed to release internal " "command queue reference: %d.\n", cle); } + priv->command_queue = NULL; } } From fbdd78fa3e9949eb8b0cf6edc2548ed50e11bf71 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 23 Nov 2017 20:12:55 +0100 Subject: [PATCH 1102/2557] avcodec/fft: fix INTERL macro on 3dnow The commit b7c16a3f2c4921f613319938b8ee0e3d6fa83e8d ("x86: fft: Port to cpuflags") breaks the opus decoder in ffmpeg when compiling for 3dnow. The output is audible, but there's a lot of noise. The reason for the breakage is that the commit unintentionally changed the INTERL macro so that it is empty when compiling for 3dnow. This patch fixes it. Signed-off-by: Mikulas Patocka Signed-off-by: James Almer --- libavcodec/x86/fft.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/x86/fft.asm b/libavcodec/x86/fft.asm index 53cfd64b3aaca..a671e8f48e58e 100644 --- a/libavcodec/x86/fft.asm +++ b/libavcodec/x86/fft.asm @@ -199,7 +199,7 @@ SECTION .text vextractf128 %4 %+ H(%5), %3, 0 vextractf128 %4(%5 + 1), %2, 1 vextractf128 %4 %+ H(%5 + 1), %3, 1 -%elif cpuflag(sse) +%elif cpuflag(sse) || cpuflag(3dnow) mova %3, %2 unpcklps %2, %1 unpckhps %3, %1 From f6d49a0dc84aade2adf150c25afb66cbda1d5528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Fri, 24 Nov 2017 02:44:44 +0200 Subject: [PATCH 1103/2557] hwcontext_d3d11va: properly reset values after release/close Makes the uninit function re-entrable, which can be a common case when an API user first tries to initialize its context, fails, and then finally unrefs the AVHWDevice. Fixes a crash reported by sm2345 on IRC. --- libavutil/hwcontext_d3d11va.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 769c81fd77d6a..2f97156a54ce1 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -458,20 +458,31 @@ static void d3d11va_device_uninit(AVHWDeviceContext *hwdev) { AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx; - if (device_hwctx->device) + if (device_hwctx->device) { ID3D11Device_Release(device_hwctx->device); + device_hwctx->device = NULL; + } - if (device_hwctx->device_context) + if (device_hwctx->device_context) { ID3D11DeviceContext_Release(device_hwctx->device_context); + device_hwctx->device_context = NULL; + } - if (device_hwctx->video_device) + if (device_hwctx->video_device) { ID3D11VideoDevice_Release(device_hwctx->video_device); + device_hwctx->video_device = NULL; + } - if (device_hwctx->video_context) + if (device_hwctx->video_context) { ID3D11VideoContext_Release(device_hwctx->video_context); + device_hwctx->video_context = NULL; + } - if (device_hwctx->lock == d3d11va_default_lock) + if (device_hwctx->lock == d3d11va_default_lock) { CloseHandle(device_hwctx->lock_ctx); + device_hwctx->lock_ctx = INVALID_HANDLE_VALUE; + device_hwctx->lock = NULL; + } } static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, From 07e427aa56550bed2e2b7b401b4f4b3800e74217 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 25 Nov 2017 19:41:50 +0100 Subject: [PATCH 1104/2557] avcodec/texturedsp : add rgtc1u gray decoding decode rgtc1 block in gray8 picture --- libavcodec/texturedsp.c | 41 +++++++++++++++++++++++++++++------------ libavcodec/texturedsp.h | 1 + 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/libavcodec/texturedsp.c b/libavcodec/texturedsp.c index 6fc8e560ecec9..b7dd8baa12185 100644 --- a/libavcodec/texturedsp.c +++ b/libavcodec/texturedsp.c @@ -413,7 +413,7 @@ static int dxt5ys_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) static inline void rgtc_block_internal(uint8_t *dst, ptrdiff_t stride, const uint8_t *block, - const int *color_tab, int alpha) + const int *color_tab, int mono, int offset, int pix_size) { uint8_t indices[16]; int x, y; @@ -430,19 +430,19 @@ static inline void rgtc_block_internal(uint8_t *dst, ptrdiff_t stride, /* Interval expansion from [-1 1] or [0 1] to [0 255]. */ int c = color_tab[i]; - if (alpha){ - dst [x * 4 + y * stride + 3] = (uint8_t)c; + if (mono){ + dst [x * pix_size + y * stride + offset] = (uint8_t)c; } else{ uint32_t pixel = RGBA(c, c, c, 255U); - AV_WL32(dst + x * 4 + y * stride, pixel); + AV_WL32(dst + x * pix_size + y * stride, pixel); } } } } static inline void rgtc1_block_internal(uint8_t *dst, ptrdiff_t stride, - const uint8_t *block, int sign, int alpha) + const uint8_t *block, int sign, int mono, int offset, int pix_size) { int color_table[8]; int r0, r1; @@ -478,7 +478,7 @@ static inline void rgtc1_block_internal(uint8_t *dst, ptrdiff_t stride, color_table[7] = 255; /* max range */ // bit code 111 } - rgtc_block_internal(dst, stride, block, color_table, alpha); + rgtc_block_internal(dst, stride, block, color_table, mono, offset, pix_size); } /** @@ -492,7 +492,7 @@ static inline void rgtc1_block_internal(uint8_t *dst, ptrdiff_t stride, */ static int rgtc1s_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) { - rgtc1_block_internal(dst, stride, block, 1, 0); + rgtc1_block_internal(dst, stride, block, 1, 0, 0, 4); return 8; } @@ -508,13 +508,13 @@ static int rgtc1s_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) */ static int rgtc1u_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) { - rgtc1_block_internal(dst, stride, block, 0, 0); + rgtc1_block_internal(dst, stride, block, 0, 0, 0, 4); return 8; } /** - * Decompress one block of a RGRC1 texture with unsigned components + * Decompress one block of a RGTC1 texture with unsigned components * and overwrite the alpha component in 'dst' (RGBA data). * * @param dst output buffer. @@ -524,7 +524,23 @@ static int rgtc1u_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) */ static int rgtc1u_alpha_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) { - rgtc1_block_internal(dst, stride, block, 0, 1); + rgtc1_block_internal(dst, stride, block, 0, 1, 3, 4); + + return 8; +} + +/** + * Decompress one block of a RGTC1 texture with unsigned components + * to Gray 8. + * + * @param dst output buffer. + * @param stride scanline in bytes. + * @param block block to decompress. + * @return how much texture data has been consumed. + */ +static int rgtc1u_gray_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) +{ + rgtc1_block_internal(dst, stride, block, 0, 1, 0, 1); return 8; } @@ -538,8 +554,8 @@ static inline void rgtc2_block_internal(uint8_t *dst, ptrdiff_t stride, int x, y; /* Decompress the two channels separately and interleave them afterwards. */ - rgtc1_block_internal(c0, 16, block, sign, 0); - rgtc1_block_internal(c1, 16, block + 8, sign, 0); + rgtc1_block_internal(c0, 16, block, sign, 0, 0, 4); + rgtc1_block_internal(c1, 16, block + 8, sign, 0, 0, 4); /* B is rebuilt exactly like a normal map. */ for (y = 0; y < 4; y++) { @@ -630,6 +646,7 @@ av_cold void ff_texturedsp_init(TextureDSPContext *c) c->dxt5ys_block = dxt5ys_block; c->rgtc1s_block = rgtc1s_block; c->rgtc1u_block = rgtc1u_block; + c->rgtc1u_gray_block = rgtc1u_gray_block; c->rgtc1u_alpha_block = rgtc1u_alpha_block; c->rgtc2s_block = rgtc2s_block; c->rgtc2u_block = rgtc2u_block; diff --git a/libavcodec/texturedsp.h b/libavcodec/texturedsp.h index 9953cf589d799..90ceb2b6aa530 100644 --- a/libavcodec/texturedsp.h +++ b/libavcodec/texturedsp.h @@ -53,6 +53,7 @@ typedef struct TextureDSPContext { int (*dxt5ys_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); int (*rgtc1s_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); int (*rgtc1u_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*rgtc1u_gray_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); int (*rgtc1u_alpha_block)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); int (*rgtc2s_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); int (*rgtc2u_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); From 21c06c4095f53b2c343e1225ae52d83160e213f1 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 25 Nov 2017 19:46:48 +0100 Subject: [PATCH 1105/2557] avcodec/hapdec : use gray8 for HapAlphaOnly decoding instead of RGB0 --- libavcodec/hap.h | 1 + libavcodec/hapdec.c | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libavcodec/hap.h b/libavcodec/hap.h index 4dfbb8cb16325..74455f3dd9d6d 100644 --- a/libavcodec/hap.h +++ b/libavcodec/hap.h @@ -84,6 +84,7 @@ typedef struct HapContext { int texture_count; /* 2 for HAQA, 1 for other version */ int texture_section_size; /* size of the part of the texture section (for HAPQA) */ + int uncompress_pix_size; /* nb of byte / pixel for the target picture */ /* Pointer to the selected compress or decompress function */ int (*tex_fun)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); diff --git a/libavcodec/hapdec.c b/libavcodec/hapdec.c index a1abb3285f8d5..8fd4aa962c6cf 100644 --- a/libavcodec/hapdec.c +++ b/libavcodec/hapdec.c @@ -300,10 +300,10 @@ static int decompress_texture_thread_internal(AVCodecContext *avctx, void *arg, int off = y * w_block; for (x = 0; x < w_block; x++) { if (texture_num == 0) { - ctx->tex_fun(p + x * 16, frame->linesize[0], + ctx->tex_fun(p + x * 4 * ctx->uncompress_pix_size, frame->linesize[0], d + (off + x) * ctx->tex_rat); } else { - ctx->tex_fun2(p + x * 16, frame->linesize[0], + ctx->tex_fun2(p + x * 4 * ctx->uncompress_pix_size, frame->linesize[0], d + (off + x) * ctx->tex_rat2); } } @@ -438,6 +438,7 @@ static av_cold int hap_init(AVCodecContext *avctx) ff_texturedsp_init(&ctx->dxtc); ctx->texture_count = 1; + ctx->uncompress_pix_size = 4; switch (avctx->codec_tag) { case MKTAG('H','a','p','1'): @@ -461,8 +462,9 @@ static av_cold int hap_init(AVCodecContext *avctx) case MKTAG('H','a','p','A'): texture_name = "RGTC1"; ctx->tex_rat = 8; - ctx->tex_fun = ctx->dxtc.rgtc1u_block; - avctx->pix_fmt = AV_PIX_FMT_RGB0; + ctx->tex_fun = ctx->dxtc.rgtc1u_gray_block; + avctx->pix_fmt = AV_PIX_FMT_GRAY8; + ctx->uncompress_pix_size = 1; break; case MKTAG('H','a','p','M'): texture_name = "DXT5-YCoCg-scaled / RGTC1"; From 8794e0c0372c716ee1d97b59e8156c34d29fdc37 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 25 Nov 2017 19:47:06 +0100 Subject: [PATCH 1106/2557] fate/hapAlphaOnly : add test for hap alpha only decoding --- tests/fate/video.mak | 6 ++++++ tests/ref/fate/hap-alpha-only-nosnappy-128x72 | 6 ++++++ tests/ref/fate/hap-alpha-only-snappy-127x71 | 6 ++++++ 3 files changed, 18 insertions(+) create mode 100644 tests/ref/fate/hap-alpha-only-nosnappy-128x72 create mode 100644 tests/ref/fate/hap-alpha-only-snappy-127x71 diff --git a/tests/fate/video.mak b/tests/fate/video.mak index d2d5b60e9a2df..e7817d3d13afe 100644 --- a/tests/fate/video.mak +++ b/tests/fate/video.mak @@ -192,6 +192,12 @@ fate-hapqa-snappy1-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_Snappy_ FATE_HAP += fate-hapqa-snappy16-127x71 fate-hapqa-snappy16-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_Snappy_16chunk_127x1.mov +FATE_HAP += fate-hap-alpha-only-nosnappy-128x72 +fate-hap-alpha-only-nosnappy-128x72: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HapAlphaOnly_NoSnappy_128x72.mov -pix_fmt gray8 + +FATE_HAP += fate-hap-alpha-only-snappy-127x71 +fate-hap-alpha-only-snappy-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HapAlphaOnly_snappy1chunk_127x71.mov -pix_fmt gray8 + FATE_VIDEO-$(call DEMDEC, MOV, HAP) += $(FATE_HAP) fate-hap: $(FATE_HAP) diff --git a/tests/ref/fate/hap-alpha-only-nosnappy-128x72 b/tests/ref/fate/hap-alpha-only-nosnappy-128x72 new file mode 100644 index 0000000000000..d9b1b56147f69 --- /dev/null +++ b/tests/ref/fate/hap-alpha-only-nosnappy-128x72 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 128x72 +#sar 0: 1/1 +0, 0, 0, 1, 9216, 0x5967036f diff --git a/tests/ref/fate/hap-alpha-only-snappy-127x71 b/tests/ref/fate/hap-alpha-only-snappy-127x71 new file mode 100644 index 0000000000000..1559204ca229c --- /dev/null +++ b/tests/ref/fate/hap-alpha-only-snappy-127x71 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 127x71 +#sar 0: 1/1 +0, 0, 0, 1, 9017, 0xc390c38c From 08b294bf5f4e76ca9217e3206224441048d0f843 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 24 Nov 2017 17:55:05 -0300 Subject: [PATCH 1107/2557] avformat/isom: return proper error values in ff_mp4_read_dec_config_descr Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/isom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/isom.c b/libavformat/isom.c index 77983c5eaabbf..9d9f85885b0b4 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -524,7 +524,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if (tag == MP4DecSpecificDescrTag) { av_log(fc, AV_LOG_TRACE, "Specific MPEG-4 header len=%d\n", len); if (!len || (uint64_t)len > (1<<30)) - return -1; + return AVERROR_INVALIDDATA; av_free(st->codecpar->extradata); if ((ret = ff_get_extradata(fc, st->codecpar, pb, len)) < 0) return ret; From abf669479c0098ab5eb184a167e57a70aabb942b Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 24 Nov 2017 17:55:19 -0300 Subject: [PATCH 1108/2557] avformat/mov_esds: check return value of ff_mp4_read_dec_config_descr Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/mov_esds.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavformat/mov_esds.c b/libavformat/mov_esds.c index 2ecf03742f119..a444d969c65e4 100644 --- a/libavformat/mov_esds.c +++ b/libavformat/mov_esds.c @@ -23,7 +23,7 @@ int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb) { AVStream *st; - int tag; + int tag, ret = 0; if (fc->nb_streams < 1) return 0; @@ -38,6 +38,7 @@ int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb) ff_mp4_read_descr(fc, pb, &tag); if (tag == MP4DecConfigDescrTag) - ff_mp4_read_dec_config_descr(fc, st, pb); - return 0; + ret = ff_mp4_read_dec_config_descr(fc, st, pb); + + return ret; } From 3154f4417ab56cfd1e978e6abbb68a9f9f7600ed Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Fri, 24 Nov 2017 23:38:44 +0000 Subject: [PATCH 1109/2557] lavc/utils.c: use C11 atomics for entangled thread handling Signed-off-by: Rostislav Pehlivanov --- libavcodec/utils.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavcodec/utils.c b/libavcodec/utils.c index e50de6e89b047..3a0f3c11f5c85 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -56,6 +56,7 @@ #include "version.h" #include #include +#include #include #include #if CONFIG_ICONV @@ -114,7 +115,7 @@ static int (*lockmgr_cb)(void **mutex, enum AVLockOp op) = NULL; volatile int ff_avcodec_locked; -static int volatile entangled_thread_counter = 0; +static atomic_int entangled_thread_counter = ATOMIC_VAR_INIT(0); static void *codec_mutex; static void *avformat_mutex; @@ -1944,11 +1945,11 @@ int ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec) return -1; } - if (avpriv_atomic_int_add_and_fetch(&entangled_thread_counter, 1) != 1) { + if (atomic_fetch_add(&entangled_thread_counter, 1)) { av_log(log_ctx, AV_LOG_ERROR, "Insufficient thread locking. At least %d threads are " "calling avcodec_open2() at the same time right now.\n", - entangled_thread_counter); + atomic_load(&entangled_thread_counter)); if (!lockmgr_cb) av_log(log_ctx, AV_LOG_ERROR, "No lock manager is set, please see av_lockmgr_register()\n"); ff_avcodec_locked = 1; @@ -1967,7 +1968,7 @@ int ff_unlock_avcodec(const AVCodec *codec) av_assert0(ff_avcodec_locked); ff_avcodec_locked = 0; - avpriv_atomic_int_add_and_fetch(&entangled_thread_counter, -1); + atomic_fetch_add(&entangled_thread_counter, -1); if (lockmgr_cb) { if ((*lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE)) return -1; From 590136e78da3d091ea99ab5432543d47a559a461 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 25 Nov 2017 16:55:44 +0000 Subject: [PATCH 1110/2557] libavcodec/utils.c: simplify avcodec locking with atomics Also makes it more robust than using volatiles. Signed-off-by: Rostislav Pehlivanov --- libavcodec/internal.h | 1 - libavcodec/utils.c | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/libavcodec/internal.h b/libavcodec/internal.h index d3310b6afe562..1c54966f37a32 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -246,7 +246,6 @@ int ff_init_buffer_info(AVCodecContext *s, AVFrame *frame); void ff_color_frame(AVFrame *frame, const int color[4]); -extern volatile int ff_avcodec_locked; int ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec); int ff_unlock_avcodec(const AVCodec *codec); diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 3a0f3c11f5c85..c733709171486 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -114,7 +114,7 @@ static int (*lockmgr_cb)(void **mutex, enum AVLockOp op) = NULL; #endif -volatile int ff_avcodec_locked; +static atomic_bool ff_avcodec_locked; static atomic_int entangled_thread_counter = ATOMIC_VAR_INIT(0); static void *codec_mutex; static void *avformat_mutex; @@ -1937,6 +1937,7 @@ int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) int ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec) { + _Bool exp = 0; if (codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE || !codec->init) return 0; @@ -1952,22 +1953,21 @@ int ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec) atomic_load(&entangled_thread_counter)); if (!lockmgr_cb) av_log(log_ctx, AV_LOG_ERROR, "No lock manager is set, please see av_lockmgr_register()\n"); - ff_avcodec_locked = 1; + atomic_store(&ff_avcodec_locked, 1); ff_unlock_avcodec(codec); return AVERROR(EINVAL); } - av_assert0(!ff_avcodec_locked); - ff_avcodec_locked = 1; + av_assert0(atomic_compare_exchange_strong(&ff_avcodec_locked, &exp, 1)); return 0; } int ff_unlock_avcodec(const AVCodec *codec) { + _Bool exp = 1; if (codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE || !codec->init) return 0; - av_assert0(ff_avcodec_locked); - ff_avcodec_locked = 0; + av_assert0(atomic_compare_exchange_strong(&ff_avcodec_locked, &exp, 0)); atomic_fetch_add(&entangled_thread_counter, -1); if (lockmgr_cb) { if ((*lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE)) From 3701d499f8734ec5f3e7359de7311b15d92070b0 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Fri, 24 Nov 2017 23:34:16 +0000 Subject: [PATCH 1111/2557] error_resilience: remove avpriv_atomic usage Signed-off-by: Rostislav Pehlivanov --- libavcodec/error_resilience.c | 20 ++++++++++---------- libavcodec/error_resilience.h | 3 ++- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index 0c7f29d171e05..8f172beca61f1 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -807,7 +807,7 @@ void ff_er_frame_start(ERContext *s) memset(s->error_status_table, ER_MB_ERROR | VP_START | ER_MB_END, s->mb_stride * s->mb_height * sizeof(uint8_t)); - s->error_count = 3 * s->mb_num; + atomic_init(&s->error_count, 3 * s->mb_num); s->error_occurred = 0; } @@ -852,20 +852,20 @@ void ff_er_add_slice(ERContext *s, int startx, int starty, mask &= ~VP_START; if (status & (ER_AC_ERROR | ER_AC_END)) { mask &= ~(ER_AC_ERROR | ER_AC_END); - avpriv_atomic_int_add_and_fetch(&s->error_count, start_i - end_i - 1); + atomic_fetch_add(&s->error_count, start_i - end_i - 1); } if (status & (ER_DC_ERROR | ER_DC_END)) { mask &= ~(ER_DC_ERROR | ER_DC_END); - avpriv_atomic_int_add_and_fetch(&s->error_count, start_i - end_i - 1); + atomic_fetch_add(&s->error_count, start_i - end_i - 1); } if (status & (ER_MV_ERROR | ER_MV_END)) { mask &= ~(ER_MV_ERROR | ER_MV_END); - avpriv_atomic_int_add_and_fetch(&s->error_count, start_i - end_i - 1); + atomic_fetch_add(&s->error_count, start_i - end_i - 1); } if (status & ER_MB_ERROR) { s->error_occurred = 1; - avpriv_atomic_int_set(&s->error_count, INT_MAX); + atomic_store(&s->error_count, INT_MAX); } if (mask == ~0x7F) { @@ -878,7 +878,7 @@ void ff_er_add_slice(ERContext *s, int startx, int starty, } if (end_i == s->mb_num) - avpriv_atomic_int_set(&s->error_count, INT_MAX); + atomic_store(&s->error_count, INT_MAX); else { s->error_status_table[end_xy] &= mask; s->error_status_table[end_xy] |= status; @@ -893,7 +893,7 @@ void ff_er_add_slice(ERContext *s, int startx, int starty, prev_status &= ~ VP_START; if (prev_status != (ER_MV_END | ER_DC_END | ER_AC_END)) { s->error_occurred = 1; - avpriv_atomic_int_set(&s->error_count, INT_MAX); + atomic_store(&s->error_count, INT_MAX); } } } @@ -910,10 +910,10 @@ void ff_er_frame_end(ERContext *s) /* We do not support ER of field pictures yet, * though it should not crash if enabled. */ - if (!s->avctx->error_concealment || s->error_count == 0 || + if (!s->avctx->error_concealment || !atomic_load(&s->error_count) || s->avctx->lowres || !er_supported(s) || - s->error_count == 3 * s->mb_width * + atomic_load(&s->error_count) == 3 * s->mb_width * (s->avctx->skip_top + s->avctx->skip_bottom)) { return; } @@ -927,7 +927,7 @@ void ff_er_frame_end(ERContext *s) if ( mb_x == s->mb_width && s->avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO && (FFALIGN(s->avctx->height, 16)&16) - && s->error_count == 3 * s->mb_width * (s->avctx->skip_top + s->avctx->skip_bottom + 1) + && atomic_load(&s->error_count) == 3 * s->mb_width * (s->avctx->skip_top + s->avctx->skip_bottom + 1) ) { av_log(s->avctx, AV_LOG_DEBUG, "ignoring last missing slice\n"); return; diff --git a/libavcodec/error_resilience.h b/libavcodec/error_resilience.h index 27c20086948e9..664a765659272 100644 --- a/libavcodec/error_resilience.h +++ b/libavcodec/error_resilience.h @@ -20,6 +20,7 @@ #define AVCODEC_ERROR_RESILIENCE_H #include +#include #include "avcodec.h" #include "me_cmp.h" @@ -60,7 +61,7 @@ typedef struct ERContext { ptrdiff_t mb_stride; ptrdiff_t b8_stride; - volatile int error_count; + atomic_int error_count; int error_occurred; uint8_t *error_status_table; uint8_t *er_temp_buffer; From ffc01280be6316ae625972a0976fef077a3a0b51 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 23 Nov 2017 16:08:42 +0100 Subject: [PATCH 1112/2557] avfilter: add lv2 wrapper filter Signed-off-by: Paul B Mahol --- Changelog | 1 + configure | 4 + doc/filters.texi | 59 ++++ libavfilter/Makefile | 1 + libavfilter/af_lv2.c | 602 +++++++++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- 7 files changed, 669 insertions(+), 1 deletion(-) create mode 100644 libavfilter/af_lv2.c diff --git a/Changelog b/Changelog index 0b7e02392dfc2..e3092e211f4e2 100644 --- a/Changelog +++ b/Changelog @@ -20,6 +20,7 @@ version : - OpenCL overlay filter - video mix filter - video normalize filter +- audio lv2 wrapper filter version 3.4: diff --git a/configure b/configure index 7769427ffbc7c..0cc97ebbbbef3 100755 --- a/configure +++ b/configure @@ -283,6 +283,7 @@ External library support: --enable-libzimg enable z.lib, needed for zscale filter [no] --enable-libzmq enable message passing via libzmq [no] --enable-libzvbi enable teletext support via libzvbi [no] + --enable-lv2 enable LV2 audio filtering [no] --disable-lzma disable lzma [autodetect] --enable-decklink enable Blackmagic DeckLink I/O support [no] --enable-libndi_newtek enable Newteck NDI I/O support [no] @@ -1631,6 +1632,7 @@ EXTERNAL_LIBRARY_LIST=" libzimg libzmq libzvbi + lv2 mediacodec openal opengl @@ -3229,6 +3231,7 @@ hqdn3d_filter_deps="gpl" interlace_filter_deps="gpl" kerndeint_filter_deps="gpl" ladspa_filter_deps="ladspa libdl" +lv2_filter_deps="lv2" mcdeint_filter_deps="avcodec gpl" movie_filter_deps="avcodec avformat" mpdecimate_filter_deps="gpl" @@ -5825,6 +5828,7 @@ enabled gmp && require gmp gmp.h mpz_export -lgmp enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init enabled jni && { [ $target_os = "android" ] && check_header jni.h && enabled pthreads || die "ERROR: jni not found"; } enabled ladspa && require_header ladspa.h +enabled lv2 && require_pkg_config lv2 lilv-0 "lilv-0/lilv/lilv.h" lilv_world_new enabled libiec61883 && require libiec61883 libiec61883/iec61883.h iec61883_cmp_connect -lraw1394 -lavc1394 -lrom1394 -liec61883 enabled libass && require_pkg_config libass libass ass/ass.h ass_library_init enabled libbluray && require_pkg_config libbluray libbluray libbluray/bluray.h bd_open diff --git a/doc/filters.texi b/doc/filters.texi index fda789630b2c2..476f014ac8514 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -3281,6 +3281,65 @@ lowpass=c=LFE @end example @end itemize +@section lv2 + +Load a LV2 (LADSPA Version 2) plugin. + +To enable compilation of this filter you need to configure FFmpeg with +@code{--enable-lv2}. + +@table @option +@item plugin, p +Specifies the plugin URI. You may need to escape ':'. + +@item controls, c +Set the '|' separated list of controls which are zero or more floating point +values that determine the behavior of the loaded plugin (for example delay, +threshold or gain). +If @option{controls} is set to @code{help}, all available controls and +their valid ranges are printed. + +@item sample_rate, s +Specify the sample rate, default to 44100. Only used if plugin have +zero inputs. + +@item nb_samples, n +Set the number of samples per channel per each output frame, default +is 1024. Only used if plugin have zero inputs. + +@item duration, d +Set the minimum duration of the sourced audio. See +@ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils} +for the accepted syntax. +Note that the resulting duration may be greater than the specified duration, +as the generated audio is always cut at the end of a complete frame. +If not specified, or the expressed duration is negative, the audio is +supposed to be generated forever. +Only used if plugin have zero inputs. +@end table + +@subsection Examples + +@itemize +@item +Apply bass enhancer plugin from Calf: +@example +lv2=p=http\\\\://calf.sourceforge.net/plugins/BassEnhancer:c=amount=2 +@end example + +@item +Apply bass vinyl plugin from Calf: +@example +lv2=p=http\\\\://calf.sourceforge.net/plugins/Vinyl:c=drone=0.2|aging=0.5 +@end example + +@item +Apply bit crusher plugin from ArtyFX: +@example +lv2=p=http\\\\://www.openavproductions.com/artyfx#bitta:c=crush=0.3 +@end example +@end itemize + @section mcompand Multiband Compress or expand the audio's dynamic range. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index dd195d253848a..0b77d7a01f039 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -101,6 +101,7 @@ OBJS-$(CONFIG_JOIN_FILTER) += af_join.o OBJS-$(CONFIG_LADSPA_FILTER) += af_ladspa.o OBJS-$(CONFIG_LOUDNORM_FILTER) += af_loudnorm.o ebur128.o OBJS-$(CONFIG_LOWPASS_FILTER) += af_biquads.o +OBJS-$(CONFIG_LV2_FILTER) += af_lv2.o OBJS-$(CONFIG_MCOMPAND_FILTER) += af_mcompand.o OBJS-$(CONFIG_PAN_FILTER) += af_pan.o OBJS-$(CONFIG_REPLAYGAIN_FILTER) += af_replaygain.o diff --git a/libavfilter/af_lv2.c b/libavfilter/af_lv2.c new file mode 100644 index 0000000000000..8a0a6fd8883af --- /dev/null +++ b/libavfilter/af_lv2.c @@ -0,0 +1,602 @@ +/* + * Copyright (c) 2017 Paul B Mahol + * Copyright (c) 2007-2016 David Robillard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * LV2 wrapper + */ + +#include +#include +#include + +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/channel_layout.h" +#include "libavutil/opt.h" +#include "audio.h" +#include "avfilter.h" +#include "internal.h" + +typedef struct URITable { + char **uris; + size_t n_uris; +} URITable; + +typedef struct LV2Context { + const AVClass *class; + char *plugin_uri; + char *options; + + unsigned nb_inputs; + unsigned nb_inputcontrols; + unsigned nb_outputs; + + int sample_rate; + int nb_samples; + int64_t pts; + int64_t duration; + + LilvWorld *world; + const LilvPlugin *plugin; + uint32_t nb_ports; + float *values; + URITable uri_table; + LV2_URID_Map map; + LV2_Feature map_feature; + LV2_URID_Unmap unmap; + LV2_Feature unmap_feature; + LV2_Atom_Sequence seq_in[2]; + LV2_Atom_Sequence *seq_out; + const LV2_Feature *features[5]; + + float *mins; + float *maxes; + float *controls; + + LilvInstance *instance; + + LilvNode *atom_AtomPort; + LilvNode *atom_Sequence; + LilvNode *lv2_AudioPort; + LilvNode *lv2_CVPort; + LilvNode *lv2_ControlPort; + LilvNode *lv2_Optional; + LilvNode *lv2_InputPort; + LilvNode *lv2_OutputPort; + LilvNode *urid_map; + LilvNode *powerOf2BlockLength; + LilvNode *fixedBlockLength; + LilvNode *boundedBlockLength; +} LV2Context; + +#define OFFSET(x) offsetof(LV2Context, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption lv2_options[] = { + { "plugin", "set plugin uri", OFFSET(plugin_uri), AV_OPT_TYPE_STRING, .flags = FLAGS }, + { "p", "set plugin uri", OFFSET(plugin_uri), AV_OPT_TYPE_STRING, .flags = FLAGS }, + { "controls", "set plugin options", OFFSET(options), AV_OPT_TYPE_STRING, .flags = FLAGS }, + { "c", "set plugin options", OFFSET(options), AV_OPT_TYPE_STRING, .flags = FLAGS }, + { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT32_MAX, FLAGS }, + { "s", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT32_MAX, FLAGS }, + { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, FLAGS }, + { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, FLAGS }, + { "duration", "set audio duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=-1}, -1, INT64_MAX, FLAGS }, + { "d", "set audio duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=-1}, -1, INT64_MAX, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(lv2); + +static void uri_table_init(URITable *table) +{ + table->uris = NULL; + table->n_uris = 0; +} + +static void uri_table_destroy(URITable *table) +{ + int i; + + for (i = 0; i < table->n_uris; i++) { + av_freep(&table->uris[i]); + } + + av_freep(&table->uris); +} + +static LV2_URID uri_table_map(LV2_URID_Map_Handle handle, const char *uri) +{ + URITable *table = (URITable*)handle; + const size_t len = strlen(uri); + size_t i; + char **tmp; + + for (i = 0; i < table->n_uris; i++) { + if (!strcmp(table->uris[i], uri)) { + return i + 1; + } + } + + tmp = av_calloc(table->n_uris + 1, sizeof(char*)); + if (!tmp) + return table->n_uris; + memcpy(tmp, table->uris, table->n_uris * sizeof(char**)); + + av_free(table->uris); + table->uris = tmp; + table->uris[table->n_uris] = av_malloc(len + 1); + if (!table->uris[table->n_uris]) + return table->n_uris; + + memcpy(table->uris[table->n_uris], uri, len + 1); + table->n_uris++; + + return table->n_uris; +} + +static const char *uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid) +{ + URITable *table = (URITable*)handle; + + if (urid > 0 && urid <= table->n_uris) { + return table->uris[urid - 1]; + } + + return NULL; +} + +static void connect_ports(LV2Context *s, AVFrame *in, AVFrame *out) +{ + int ich = 0, och = 0, i; + + for (i = 0; i < s->nb_ports; i++) { + const LilvPort *port = lilv_plugin_get_port_by_index(s->plugin, i); + + if (lilv_port_is_a(s->plugin, port, s->lv2_AudioPort) || + lilv_port_is_a(s->plugin, port, s->lv2_CVPort)) { + if (lilv_port_is_a(s->plugin, port, s->lv2_InputPort)) { + lilv_instance_connect_port(s->instance, i, in->extended_data[ich++]); + } else if (lilv_port_is_a(s->plugin, port, s->lv2_OutputPort)) { + lilv_instance_connect_port(s->instance, i, out->extended_data[och++]); + } else { + av_log(s, AV_LOG_WARNING, "port %d neither input nor output, skipping\n", i); + } + } else if (lilv_port_is_a(s->plugin, port, s->atom_AtomPort)) { + if (lilv_port_is_a(s->plugin, port, s->lv2_InputPort)) { + lilv_instance_connect_port(s->instance, i, &s->seq_in); + } else { + lilv_instance_connect_port(s->instance, i, s->seq_out); + } + } else if (lilv_port_is_a(s->plugin, port, s->lv2_ControlPort)) { + lilv_instance_connect_port(s->instance, i, &s->controls[i]); + } + } + + s->seq_in[0].atom.size = sizeof(LV2_Atom_Sequence_Body); + s->seq_in[0].atom.type = uri_table_map(&s->uri_table, LV2_ATOM__Sequence); + s->seq_out->atom.size = 9624; + s->seq_out->atom.type = uri_table_map(&s->uri_table, LV2_ATOM__Chunk); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + LV2Context *s = ctx->priv; + AVFrame *out; + + if (!s->nb_outputs || + (av_frame_is_writable(in) && s->nb_inputs == s->nb_outputs)) { + out = in; + } else { + out = ff_get_audio_buffer(ctx->outputs[0], in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + + connect_ports(s, in, out); + + lilv_instance_run(s->instance, in->nb_samples); + + if (out != in) + av_frame_free(&in); + + return ff_filter_frame(ctx->outputs[0], out); +} + +static int request_frame(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + LV2Context *s = ctx->priv; + AVFrame *out; + int64_t t; + + if (ctx->nb_inputs) + return ff_request_frame(ctx->inputs[0]); + + t = av_rescale(s->pts, AV_TIME_BASE, s->sample_rate); + if (s->duration >= 0 && t >= s->duration) + return AVERROR_EOF; + + out = ff_get_audio_buffer(outlink, s->nb_samples); + if (!out) + return AVERROR(ENOMEM); + + connect_ports(s, out, out); + + lilv_instance_run(s->instance, out->nb_samples); + + out->sample_rate = s->sample_rate; + out->pts = s->pts; + s->pts += s->nb_samples; + + return ff_filter_frame(outlink, out); +} + +static const LV2_Feature buf_size_features[3] = { + { LV2_BUF_SIZE__powerOf2BlockLength, NULL }, + { LV2_BUF_SIZE__fixedBlockLength, NULL }, + { LV2_BUF_SIZE__boundedBlockLength, NULL }, +}; + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + LV2Context *s = ctx->priv; + char *p, *arg, *saveptr = NULL; + int i, sample_rate; + + uri_table_init(&s->uri_table); + s->map.handle = &s->uri_table; + s->map.map = uri_table_map; + s->map_feature.URI = LV2_URID_MAP_URI; + s->map_feature.data = &s->map; + s->unmap.handle = &s->uri_table; + s->unmap.unmap = uri_table_unmap; + s->unmap_feature.URI = LV2_URID_UNMAP_URI; + s->unmap_feature.data = &s->unmap; + s->features[0] = &s->map_feature; + s->features[1] = &s->unmap_feature; + s->features[2] = &buf_size_features[0]; + s->features[3] = &buf_size_features[1]; + s->features[4] = &buf_size_features[2]; + + if (ctx->nb_inputs) { + AVFilterLink *inlink = ctx->inputs[0]; + + outlink->format = inlink->format; + outlink->sample_rate = sample_rate = inlink->sample_rate; + if (s->nb_inputs == s->nb_outputs) { + outlink->channel_layout = inlink->channel_layout; + outlink->channels = inlink->channels; + } + + } else { + outlink->sample_rate = sample_rate = s->sample_rate; + outlink->time_base = (AVRational){1, s->sample_rate}; + } + + s->instance = lilv_plugin_instantiate(s->plugin, sample_rate, s->features); + if (!s->instance) { + av_log(s, AV_LOG_ERROR, "Failed to instantiate <%s>\n", lilv_node_as_uri(lilv_plugin_get_uri(s->plugin))); + return AVERROR(EINVAL); + } + + s->mins = av_calloc(s->nb_ports, sizeof(float)); + s->maxes = av_calloc(s->nb_ports, sizeof(float)); + s->controls = av_calloc(s->nb_ports, sizeof(float)); + + if (!s->mins || !s->maxes || !s->controls) + return AVERROR(ENOMEM); + + lilv_plugin_get_port_ranges_float(s->plugin, s->mins, s->maxes, s->controls); + s->seq_out = av_malloc(sizeof(LV2_Atom_Sequence) + 9624); + if (!s->seq_out) + return AVERROR(ENOMEM); + + if (s->options && !strcmp(s->options, "help")) { + if (!s->nb_inputcontrols) { + av_log(ctx, AV_LOG_INFO, + "The '%s' plugin does not have any input controls.\n", + s->plugin_uri); + } else { + av_log(ctx, AV_LOG_INFO, + "The '%s' plugin has the following input controls:\n", + s->plugin_uri); + for (i = 0; i < s->nb_ports; i++) { + const LilvPort *port = lilv_plugin_get_port_by_index(s->plugin, i); + const LilvNode *symbol = lilv_port_get_symbol(s->plugin, port); + LilvNode *name = lilv_port_get_name(s->plugin, port); + + if (lilv_port_is_a(s->plugin, port, s->lv2_InputPort) && + lilv_port_is_a(s->plugin, port, s->lv2_ControlPort)) { + av_log(ctx, AV_LOG_INFO, "%s\t\t (from %f to %f) (default %f)\t\t%s\n", + lilv_node_as_string(symbol), s->mins[i], s->maxes[i], s->controls[i], + lilv_node_as_string(name)); + } + + lilv_node_free(name); + } + } + return AVERROR_EXIT; + } + + p = s->options; + while (s->options) { + const LilvPort *port; + LilvNode *sym; + float val; + char *str, *vstr; + int index; + + if (!(arg = av_strtok(p, " |", &saveptr))) + break; + p = NULL; + + vstr = strstr(arg, "="); + if (vstr == NULL) { + av_log(ctx, AV_LOG_ERROR, "Invalid syntax.\n"); + return AVERROR(EINVAL); + } + + vstr[0] = 0; + str = arg; + val = atof(vstr+1); + sym = lilv_new_string(s->world, str); + port = lilv_plugin_get_port_by_symbol(s->plugin, sym); + lilv_node_free(sym); + if (!port) { + av_log(s, AV_LOG_WARNING, "Unknown option: <%s>\n", str); + } else { + index = lilv_port_get_index(s->plugin, port); + s->controls[index] = val; + } + } + + if (s->nb_inputs && + (lilv_plugin_has_feature(s->plugin, s->powerOf2BlockLength) || + lilv_plugin_has_feature(s->plugin, s->fixedBlockLength) || + lilv_plugin_has_feature(s->plugin, s->boundedBlockLength))) { + AVFilterLink *inlink = ctx->inputs[0]; + + inlink->partial_buf_size = inlink->min_samples = inlink->max_samples = 4096; + } + + return 0; +} + +static av_cold int init(AVFilterContext *ctx) +{ + LV2Context *s = ctx->priv; + const LilvPlugins *plugins; + const LilvPlugin *plugin; + AVFilterPad pad = { NULL }; + LilvNode *uri; + int i; + + s->world = lilv_world_new(); + if (!s->world) + return AVERROR(ENOMEM); + + uri = lilv_new_uri(s->world, s->plugin_uri); + if (!uri) { + av_log(s, AV_LOG_ERROR, "Invalid plugin URI <%s>\n", s->plugin_uri); + return AVERROR(EINVAL); + } + + lilv_world_load_all(s->world); + plugins = lilv_world_get_all_plugins(s->world); + plugin = lilv_plugins_get_by_uri(plugins, uri); + lilv_node_free(uri); + + if (!plugin) { + av_log(s, AV_LOG_ERROR, "Plugin <%s> not found\n", s->plugin_uri); + return AVERROR(EINVAL); + } + + s->plugin = plugin; + s->nb_ports = lilv_plugin_get_num_ports(s->plugin); + + s->lv2_InputPort = lilv_new_uri(s->world, LV2_CORE__InputPort); + s->lv2_OutputPort = lilv_new_uri(s->world, LV2_CORE__OutputPort); + s->lv2_AudioPort = lilv_new_uri(s->world, LV2_CORE__AudioPort); + s->lv2_ControlPort = lilv_new_uri(s->world, LV2_CORE__ControlPort); + s->lv2_Optional = lilv_new_uri(s->world, LV2_CORE__connectionOptional); + s->atom_AtomPort = lilv_new_uri(s->world, LV2_ATOM__AtomPort); + s->atom_Sequence = lilv_new_uri(s->world, LV2_ATOM__Sequence); + s->urid_map = lilv_new_uri(s->world, LV2_URID__map); + s->powerOf2BlockLength = lilv_new_uri(s->world, LV2_BUF_SIZE__powerOf2BlockLength); + s->fixedBlockLength = lilv_new_uri(s->world, LV2_BUF_SIZE__fixedBlockLength); + s->boundedBlockLength = lilv_new_uri(s->world, LV2_BUF_SIZE__boundedBlockLength); + + for (i = 0; i < s->nb_ports; i++) { + const LilvPort *lport = lilv_plugin_get_port_by_index(s->plugin, i); + int is_input = 0; + int is_optional = 0; + + is_optional = lilv_port_has_property(s->plugin, lport, s->lv2_Optional); + + if (lilv_port_is_a(s->plugin, lport, s->lv2_InputPort)) { + is_input = 1; + } else if (!lilv_port_is_a(s->plugin, lport, s->lv2_OutputPort) && !is_optional) { + return AVERROR(EINVAL); + } + + if (lilv_port_is_a(s->plugin, lport, s->lv2_ControlPort)) { + if (is_input) { + s->nb_inputcontrols++; + } + } else if (lilv_port_is_a(s->plugin, lport, s->lv2_AudioPort)) { + if (is_input) { + s->nb_inputs++; + } else { + s->nb_outputs++; + } + } + } + + pad.type = AVMEDIA_TYPE_AUDIO; + + if (s->nb_inputs) { + pad.name = av_asprintf("in0:%s:%u", s->plugin_uri, s->nb_inputs); + if (!pad.name) + return AVERROR(ENOMEM); + + pad.filter_frame = filter_frame; + if (ff_insert_inpad(ctx, ctx->nb_inputs, &pad) < 0) { + av_freep(&pad.name); + return AVERROR(ENOMEM); + } + } + + return 0; +} + +static int query_formats(AVFilterContext *ctx) +{ + LV2Context *s = ctx->priv; + AVFilterFormats *formats; + AVFilterChannelLayouts *layouts; + AVFilterLink *outlink = ctx->outputs[0]; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }; + int ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + if (s->nb_inputs) { + formats = ff_all_samplerates(); + if (!formats) + return AVERROR(ENOMEM); + + ret = ff_set_common_samplerates(ctx, formats); + if (ret < 0) + return ret; + } else { + int sample_rates[] = { s->sample_rate, -1 }; + + ret = ff_set_common_samplerates(ctx, ff_make_format_list(sample_rates)); + if (ret < 0) + return ret; + } + + if (s->nb_inputs == 2 && s->nb_outputs == 2) { + layouts = NULL; + ret = ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO); + if (ret < 0) + return ret; + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + } else { + if (s->nb_inputs >= 1) { + AVFilterLink *inlink = ctx->inputs[0]; + uint64_t inlayout = FF_COUNT2LAYOUT(s->nb_inputs); + + layouts = NULL; + ret = ff_add_channel_layout(&layouts, inlayout); + if (ret < 0) + return ret; + ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts); + if (ret < 0) + return ret; + + if (!s->nb_outputs) { + ret = ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts); + if (ret < 0) + return ret; + } + } + + if (s->nb_outputs >= 1) { + uint64_t outlayout = FF_COUNT2LAYOUT(s->nb_outputs); + + layouts = NULL; + ret = ff_add_channel_layout(&layouts, outlayout); + if (ret < 0) + return ret; + ret = ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + LV2Context *s = ctx->priv; + + lilv_node_free(s->powerOf2BlockLength); + lilv_node_free(s->fixedBlockLength); + lilv_node_free(s->boundedBlockLength); + lilv_node_free(s->urid_map); + lilv_node_free(s->atom_Sequence); + lilv_node_free(s->atom_AtomPort); + lilv_node_free(s->lv2_Optional); + lilv_node_free(s->lv2_ControlPort); + lilv_node_free(s->lv2_AudioPort); + lilv_node_free(s->lv2_OutputPort); + lilv_node_free(s->lv2_InputPort); + uri_table_destroy(&s->uri_table); + lilv_instance_free(s->instance); + lilv_world_free(s->world); + av_freep(&s->mins); + av_freep(&s->maxes); + av_freep(&s->controls); + av_freep(&s->seq_out); + + if (ctx->nb_inputs) + av_freep(&ctx->input_pads[0].name); +} + +static const AVFilterPad lv2_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + .request_frame = request_frame, + }, + { NULL } +}; + +AVFilter ff_af_lv2 = { + .name = "lv2", + .description = NULL_IF_CONFIG_SMALL("Apply LV2 effect."), + .priv_size = sizeof(LV2Context), + .priv_class = &lv2_class, + .init = init, + .uninit = uninit, + .query_formats = query_formats, + .inputs = 0, + .outputs = lv2_outputs, + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index e09d8413875e3..4c834f73815d8 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -112,6 +112,7 @@ static void register_all(void) REGISTER_FILTER(LADSPA, ladspa, af); REGISTER_FILTER(LOUDNORM, loudnorm, af); REGISTER_FILTER(LOWPASS, lowpass, af); + REGISTER_FILTER(LV2, lv2, af); REGISTER_FILTER(MCOMPAND, mcompand, af); REGISTER_FILTER(PAN, pan, af); REGISTER_FILTER(REPLAYGAIN, replaygain, af); diff --git a/libavfilter/version.h b/libavfilter/version.h index fdcf76befee2b..1d356a9a5af71 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 4 +#define LIBAVFILTER_VERSION_MINOR 5 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ From 52a44d50beb2ecf77213c9445649dcfd7ef44e92 Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Fri, 24 Nov 2017 18:21:57 +0000 Subject: [PATCH 1113/2557] h264_picture: Actually return error during alloc failure Fixes NULL dereference during alloc failure. Signed-off-by: Derek Buitenhuis --- libavcodec/h264_picture.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libavcodec/h264_picture.c b/libavcodec/h264_picture.c index e7dd84bc4713c..e833835a77a2b 100644 --- a/libavcodec/h264_picture.c +++ b/libavcodec/h264_picture.c @@ -78,24 +78,30 @@ int ff_h264_ref_picture(H264Context *h, H264Picture *dst, H264Picture *src) dst->qscale_table_buf = av_buffer_ref(src->qscale_table_buf); dst->mb_type_buf = av_buffer_ref(src->mb_type_buf); - if (!dst->qscale_table_buf || !dst->mb_type_buf) + if (!dst->qscale_table_buf || !dst->mb_type_buf) { + ret = AVERROR(ENOMEM); goto fail; + } dst->qscale_table = src->qscale_table; dst->mb_type = src->mb_type; for (i = 0; i < 2; i++) { dst->motion_val_buf[i] = av_buffer_ref(src->motion_val_buf[i]); dst->ref_index_buf[i] = av_buffer_ref(src->ref_index_buf[i]); - if (!dst->motion_val_buf[i] || !dst->ref_index_buf[i]) + if (!dst->motion_val_buf[i] || !dst->ref_index_buf[i]) { + ret = AVERROR(ENOMEM); goto fail; + } dst->motion_val[i] = src->motion_val[i]; dst->ref_index[i] = src->ref_index[i]; } if (src->hwaccel_picture_private) { dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); - if (!dst->hwaccel_priv_buf) + if (!dst->hwaccel_priv_buf) { + ret = AVERROR(ENOMEM); goto fail; + } dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data; } From 6e0e3e1d8ddc83984876ed0e534fef42e7870b41 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Fri, 24 Nov 2017 00:21:26 +0000 Subject: [PATCH 1114/2557] hwcontext_vaapi: Do not assume that sw_format is transferable Drivers can support a format for surfaces without also supporting it for images, so we can't assume that sw_format is usable for transfer. This would previously hit an assert in cases where it isn't. --- libavutil/hwcontext_vaapi.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index fcff25dc9b822..29698d1b27816 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -627,24 +627,31 @@ static int vaapi_transfer_get_formats(AVHWFramesContext *hwfc, enum AVPixelFormat **formats) { VAAPIDeviceContext *ctx = hwfc->device_ctx->internal->priv; - enum AVPixelFormat *pix_fmts, preferred_format; - int i, k; + enum AVPixelFormat *pix_fmts; + int i, k, sw_format_available; - preferred_format = hwfc->sw_format; + sw_format_available = 0; + for (i = 0; i < ctx->nb_formats; i++) { + if (ctx->formats[i].pix_fmt == hwfc->sw_format) + sw_format_available = 1; + } pix_fmts = av_malloc((ctx->nb_formats + 1) * sizeof(*pix_fmts)); if (!pix_fmts) return AVERROR(ENOMEM); - pix_fmts[0] = preferred_format; - k = 1; + if (sw_format_available) { + pix_fmts[0] = hwfc->sw_format; + k = 1; + } else { + k = 0; + } for (i = 0; i < ctx->nb_formats; i++) { - if (ctx->formats[i].pix_fmt == preferred_format) + if (ctx->formats[i].pix_fmt == hwfc->sw_format) continue; av_assert0(k < ctx->nb_formats); pix_fmts[k++] = ctx->formats[i].pix_fmt; } - av_assert0(k == ctx->nb_formats); pix_fmts[k] = AV_PIX_FMT_NONE; *formats = pix_fmts; From 3fbd4fc47621a5ef0a814814ea0c931821ee074e Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 25 Nov 2017 23:05:24 +0000 Subject: [PATCH 1115/2557] nvenc: Include config.h before checking for D3D11 support Reviewed-by: Timo Rothenpieler --- libavcodec/nvenc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 8c1769e768993..2e51f1e946f4b 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -19,6 +19,8 @@ #ifndef AVCODEC_NVENC_H #define AVCODEC_NVENC_H +#include "config.h" + #if CONFIG_D3D11VA #define COBJMACROS #include "libavutil/hwcontext_d3d11va.h" @@ -28,8 +30,6 @@ typedef void ID3D11Device; #include "compat/nvenc/nvEncodeAPI.h" -#include "config.h" - #include "compat/cuda/dynlink_loader.h" #include "libavutil/fifo.h" #include "libavutil/opt.h" From 022ddff0b2c2710a368f100cd481831b3649a15e Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 26 Nov 2017 10:29:24 +0000 Subject: [PATCH 1116/2557] doc/fftools: Remove documentation for old -opencl_bench option --- doc/fftools-common-opts.texi | 45 ------------------------------------ 1 file changed, 45 deletions(-) diff --git a/doc/fftools-common-opts.texi b/doc/fftools-common-opts.texi index 2eff33a36f59f..185ec218d5a18 100644 --- a/doc/fftools-common-opts.texi +++ b/doc/fftools-common-opts.texi @@ -315,51 +315,6 @@ Possible flags for this option are: @item k8 @end table @end table - -@item -opencl_bench -This option is used to benchmark all available OpenCL devices and print the -results. This option is only available when FFmpeg has been compiled with -@code{--enable-opencl}. - -When FFmpeg is configured with @code{--enable-opencl}, the options for the -global OpenCL context are set via @option{-opencl_options}. See the -"OpenCL Options" section in the ffmpeg-utils manual for the complete list of -supported options. Amongst others, these options include the ability to select -a specific platform and device to run the OpenCL code on. By default, FFmpeg -will run on the first device of the first platform. While the options for the -global OpenCL context provide flexibility to the user in selecting the OpenCL -device of their choice, most users would probably want to select the fastest -OpenCL device for their system. - -This option assists the selection of the most efficient configuration by -identifying the appropriate device for the user's system. The built-in -benchmark is run on all the OpenCL devices and the performance is measured for -each device. The devices in the results list are sorted based on their -performance with the fastest device listed first. The user can subsequently -invoke @command{ffmpeg} using the device deemed most appropriate via -@option{-opencl_options} to obtain the best performance for the OpenCL -accelerated code. - -Typical usage to use the fastest OpenCL device involve the following steps. - -Run the command: -@example -ffmpeg -opencl_bench -@end example -Note down the platform ID (@var{pidx}) and device ID (@var{didx}) of the first -i.e. fastest device in the list. -Select the platform and device using the command: -@example -ffmpeg -opencl_options platform_idx=@var{pidx}:device_idx=@var{didx} ... -@end example - -@item -opencl_options options (@emph{global}) -Set OpenCL environment options. This option is only available when -FFmpeg has been compiled with @code{--enable-opencl}. - -@var{options} must be a list of @var{key}=@var{value} option pairs -separated by ':'. See the ``OpenCL Options'' section in the -ffmpeg-utils manual for the list of supported options. @end table @section AVOptions From 37c57df18e7c46436fa791abf40f4c3031ab56f4 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 26 Nov 2017 15:35:27 +0000 Subject: [PATCH 1117/2557] doc/ffmpeg: Document opencl for -init_hw_device --- doc/ffmpeg.texi | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index d767e48c44f9b..ba1e62f06fa88 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -757,6 +757,43 @@ If not specified, @samp{auto_any} is used. platform-appropriate subdevice (@samp{dxva2} or @samp{vaapi}) and then deriving a QSV device from that.) +@item opencl +@var{device} selects the platform and device as @emph{platform_index.device_index}. + +The set of devices can also be filtered using the key-value pairs to find only +devices matching particular platform or device strings. + +The strings usable as filters are: +@table @option +@item platform_profile +@item platform_version +@item platform_name +@item platform_vendor +@item platform_extensions +@item device_name +@item device_vendor +@item driver_version +@item device_version +@item device_profile +@item device_extensions +@item device_type +@end table + +The indices and filters must together uniquely select a device. + +Examples: +@table @emph +@item -init_hw_device opencl:0.1 +Choose the second device on the first platform. + +@item -init_hw_device opencl:,device_name=Foo9000 +Choose the device with a name containing the string @emph{Foo9000}. + +@item -init_hw_device opencl:1,device_type=gpu,device_extensions=cl_khr_fp16 +Choose the GPU device on the second platform supporting the @emph{cl_khr_fp16} +extension. +@end table + @end table @item -init_hw_device @var{type}[=@var{name}]@@@var{source} From e7af1394ecd0e7c237db34ee9c149afff37641dd Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Fri, 24 Nov 2017 19:24:41 +0000 Subject: [PATCH 1118/2557] vorbisenc: Check the return value of av_frame_clone Prevents a segfault when alloc fails. Signed-off-by: Derek Buitenhuis --- libavcodec/vorbisenc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/vorbisenc.c b/libavcodec/vorbisenc.c index a4ecd8f754774..18a679f2dcadd 100644 --- a/libavcodec/vorbisenc.c +++ b/libavcodec/vorbisenc.c @@ -1093,9 +1093,13 @@ static int vorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, PutBitContext pb; if (frame) { + AVFrame *clone; if ((ret = ff_af_queue_add(&venc->afq, frame)) < 0) return ret; - ff_bufqueue_add(avctx, &venc->bufqueue, av_frame_clone(frame)); + clone = av_frame_clone(frame); + if (!clone) + return AVERROR(ENOMEM); + ff_bufqueue_add(avctx, &venc->bufqueue, clone); } else if (!venc->afq.remaining_samples) return 0; From 2b6964f764382742bb052a1ee3b7167cac35332f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 25 Nov 2017 03:15:16 +0100 Subject: [PATCH 1119/2557] avcodec/dirac_dwt: Fix integer overflow in COMPOSE_FIDELITYi* Fixes: runtime error: signed integer overflow: -2143827186 - 7404944 cannot be represented in type 'int' Fixes: 4354/clusterfuzz-testcase-minimized-4671122764201984 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/dirac_dwt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/dirac_dwt.h b/libavcodec/dirac_dwt.h index f9a9e9e1b379c..eb5aebc878af5 100644 --- a/libavcodec/dirac_dwt.h +++ b/libavcodec/dirac_dwt.h @@ -111,10 +111,10 @@ void ff_spatial_idwt_slice2(DWTContext *d, int y); (b0 + b1) #define COMPOSE_FIDELITYiL0(b0, b1, b2, b3, b4, b5, b6, b7, b8)\ - (b4 - ((int)(-8*(b0+(unsigned)b8) + 21*(b1+(unsigned)b7) - 46*(b2+(unsigned)b6) + 161*(b3+(unsigned)b5) + 128) >> 8)) + ((unsigned)b4 - ((int)(-8*(b0+(unsigned)b8) + 21*(b1+(unsigned)b7) - 46*(b2+(unsigned)b6) + 161*(b3+(unsigned)b5) + 128) >> 8)) #define COMPOSE_FIDELITYiH0(b0, b1, b2, b3, b4, b5, b6, b7, b8)\ - (b4 + ((int)(-2*(b0+(unsigned)b8) + 10*(b1+(unsigned)b7) - 25*(b2+(unsigned)b6) + 81*(b3+(unsigned)b5) + 128) >> 8)) + ((unsigned)b4 + ((int)(-2*(b0+(unsigned)b8) + 10*(b1+(unsigned)b7) - 25*(b2+(unsigned)b6) + 81*(b3+(unsigned)b5) + 128) >> 8)) #define COMPOSE_DAUB97iL1(b0, b1, b2)\ (b1 - ((int)(1817*(b0 + (unsigned)b2) + 2048) >> 12)) From 2779d33ed99898675e0b3884fabe1ce6839f36d1 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 25 Nov 2017 19:22:51 +0100 Subject: [PATCH 1120/2557] avformat/aacdec: Fix leak in adts_aac_read_packet() Fixes: chromium-773637/clusterfuzz-testcase-minimized-6418078673141760 Found-by: ossfuzz/chromium Reviewed-by: James Almer Signed-off-by: Michael Niedermayer --- libavformat/aacdec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/aacdec.c b/libavformat/aacdec.c index 364b33404fc07..36d558ff54cd2 100644 --- a/libavformat/aacdec.c +++ b/libavformat/aacdec.c @@ -139,7 +139,11 @@ static int adts_aac_read_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR_INVALIDDATA; } - return av_append_packet(s->pb, pkt, fsize - ADTS_HEADER_SIZE); + ret = av_append_packet(s->pb, pkt, fsize - ADTS_HEADER_SIZE); + if (ret < 0) + av_packet_unref(pkt); + + return ret; } AVInputFormat ff_aac_demuxer = { From 24cc0a53e99e281b0ff502e82e7cf857111eca3f Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:39 +0100 Subject: [PATCH 1121/2557] lavc: Add codec metadata to indicate hardware support --- doc/APIchanges | 3 ++ libavcodec/avcodec.h | 74 ++++++++++++++++++++++++++++++++++++++++++++ libavcodec/hwaccel.h | 18 +++++++++++ libavcodec/utils.c | 12 +++++++ libavcodec/version.h | 4 +-- 5 files changed, 109 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index fecd57387adb3..a0c8e709de415 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2017-11-xx - xxxxxxx - lavc 58.4.100 - avcodec.h + Add AVCodecHWConfig and avcodec_get_hw_config(). + 2017-11-22 - 3650cb2dfa - lavu 55.3.100 - opencl.h Remove experimental OpenCL API (av_opencl_*). diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 4cd72b59612f1..e2dc97d62fab9 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -36,6 +36,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/dict.h" #include "libavutil/frame.h" +#include "libavutil/hwcontext.h" #include "libavutil/log.h" #include "libavutil/pixfmt.h" #include "libavutil/rational.h" @@ -3279,6 +3280,61 @@ typedef struct AVProfile { const char *name; ///< short name for the profile } AVProfile; +enum { + /** + * The codec supports this format via the hw_device_ctx interface. + * + * When selecting this format, AVCodecContext.hw_device_ctx should + * have been set to a device of the specified type before calling + * avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01, + /** + * The codec supports this format via the hw_frames_ctx interface. + * + * When selecting this format for a decoder, + * AVCodecContext.hw_frames_ctx should be set to a suitable frames + * context inside the get_format() callback. The frames context + * must have been created on a device of the specified type. + */ + AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX = 0x02, + /** + * The codec supports this format by some internal method. + * + * This format can be selected without any additional configuration - + * no device or frames context is required. + */ + AV_CODEC_HW_CONFIG_METHOD_INTERNAL = 0x04, + /** + * The codec supports this format by some ad-hoc method. + * + * Additional settings and/or function calls are required. See the + * codec-specific documentation for details. (Methods requiring + * this sort of configuration are deprecated and others should be + * used in preference.) + */ + AV_CODEC_HW_CONFIG_METHOD_AD_HOC = 0x08, +}; + +typedef struct AVCodecHWConfig { + /** + * A hardware pixel format which the codec can use. + */ + enum AVPixelFormat pix_fmt; + /** + * Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible + * setup methods which can be used with this configuration. + */ + int methods; + /** + * The device type associated with the configuration. + * + * Must be set for AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX and + * AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, otherwise unused. + */ + enum AVHWDeviceType device_type; +} AVCodecHWConfig; + typedef struct AVCodecDefault AVCodecDefault; struct AVSubtitle; @@ -3404,6 +3460,15 @@ typedef struct AVCodec { * packets before decoding. */ const char *bsfs; + + /** + * Array of pointers to hardware configurations supported by the codec, + * or NULL if no hardware supported. The array is terminated by a NULL + * pointer. + * + * The user can only access this field via avcodec_get_hw_config(). + */ + const struct AVCodecHWConfigInternal **hw_configs; } AVCodec; #if FF_API_CODEC_GET_SET @@ -3413,6 +3478,15 @@ int av_codec_get_max_lowres(const AVCodec *codec); struct MpegEncContext; +/** + * Retrieve supported hardware configurations for a codec. + * + * Values of index from zero to some maximum return the indexed configuration + * descriptor; all other values return NULL. If the codec does not support + * any hardware configurations then it will always return NULL. + */ +const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index); + /** * @defgroup lavc_hwaccel AVHWAccel * @{ diff --git a/libavcodec/hwaccel.h b/libavcodec/hwaccel.h index 124fbbf1fdf61..0198c7f85833e 100644 --- a/libavcodec/hwaccel.h +++ b/libavcodec/hwaccel.h @@ -19,6 +19,24 @@ #ifndef AVCODEC_HWACCEL_H #define AVCODEC_HWACCEL_H +#include "avcodec.h" + + #define HWACCEL_CAP_ASYNC_SAFE (1 << 0) + +typedef struct AVCodecHWConfigInternal { + /** + * This is the structure which will be returned to the user by + * avcodec_get_hw_config(). + */ + AVCodecHWConfig public; + /** + * If this configuration uses a hwaccel, a pointer to it. + * If not, NULL. + */ + const AVHWAccel *hwaccel; +} AVCodecHWConfigInternal; + + #endif /* AVCODEC_HWACCEL_H */ diff --git a/libavcodec/utils.c b/libavcodec/utils.c index c733709171486..2a09ed4930e2f 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -45,6 +45,7 @@ #include "libavutil/thread.h" #include "avcodec.h" #include "decode.h" +#include "hwaccel.h" #include "libavutil/opt.h" #include "me_cmp.h" #include "mpegvideo.h" @@ -1886,6 +1887,17 @@ int ff_match_2uint16(const uint16_t(*tab)[2], int size, int a, int b) return i; } +const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index) +{ + int i; + if (!codec->hw_configs || index < 0) + return NULL; + for (i = 0; i <= index; i++) + if (!codec->hw_configs[i]) + return NULL; + return &codec->hw_configs[index]->public; +} + static AVHWAccel *first_hwaccel = NULL; static AVHWAccel **last_hwaccel = &first_hwaccel; diff --git a/libavcodec/version.h b/libavcodec/version.h index c8550bca9a575..8847737f37781 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 3 -#define LIBAVCODEC_VERSION_MICRO 105 +#define LIBAVCODEC_VERSION_MINOR 4 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 758fbc54fef2f31957b5c5f22e05e5fd9b04f631 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:40 +0100 Subject: [PATCH 1122/2557] lavc: Add hardware config metadata for decoders supporting hardware output This includes a pointer to the associated hwaccel for decoders using hwaccels - these will be used later to implement the hwaccel setup without needing a global list. Also added is a new file listing all hwaccels as external declarations - this will be used later to generate the hwaccel list at configure time. --- libavcodec/cuviddec.c | 15 ++++++++ libavcodec/h263dec.c | 13 +++++++ libavcodec/h264dec.c | 25 +++++++++++++ libavcodec/hevcdec.c | 25 +++++++++++++ libavcodec/hwaccel.h | 52 +++++++++++++++++++++++++++ libavcodec/hwaccels.h | 74 ++++++++++++++++++++++++++++++++++++++ libavcodec/mediacodecdec.c | 18 ++++++++++ libavcodec/mmaldec.c | 7 ++++ libavcodec/mpeg12dec.c | 45 ++++++++++++++++++++++- libavcodec/mpeg4videodec.c | 16 +++++++++ libavcodec/qsvdec.c | 13 +++++++ libavcodec/qsvdec.h | 3 ++ libavcodec/qsvdec_h2645.c | 2 ++ libavcodec/qsvdec_other.c | 3 ++ libavcodec/vc1dec.c | 43 ++++++++++++++++++++++ libavcodec/vp9.c | 19 ++++++++++ 16 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 libavcodec/hwaccels.h diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index 806dab2074e9d..3bd2409ea2930 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -32,6 +32,7 @@ #include "avcodec.h" #include "decode.h" +#include "hwaccel.h" #include "internal.h" typedef struct CuvidContext @@ -1094,6 +1095,19 @@ static const AVOption options[] = { { NULL } }; +static const AVCodecHWConfigInternal *cuvid_hw_configs[] = { + &(const AVCodecHWConfigInternal) { + .public = { + .pix_fmt = AV_PIX_FMT_CUDA, + .methods = AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX | + AV_CODEC_HW_CONFIG_METHOD_INTERNAL, + .device_type = AV_HWDEVICE_TYPE_CUDA + }, + .hwaccel = NULL, + }, + NULL +}; + #define DEFINE_CUVID_CODEC(x, X) \ static const AVClass x##_cuvid_class = { \ .class_name = #x "_cuvid", \ @@ -1127,6 +1141,7 @@ static const AVOption options[] = { AV_PIX_FMT_P010, \ AV_PIX_FMT_P016, \ AV_PIX_FMT_NONE }, \ + .hw_configs = cuvid_hw_configs, \ }; #if CONFIG_HEVC_CUVID_DECODER diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index b222de793b8c4..5608b6324564f 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -33,6 +33,7 @@ #include "flv.h" #include "h263.h" #include "h263_parser.h" +#include "hwaccel.h" #include "internal.h" #include "mpeg_er.h" #include "mpeg4video.h" @@ -759,4 +760,16 @@ AVCodec ff_h263p_decoder = { .flush = ff_mpeg_flush, .max_lowres = 3, .pix_fmts = ff_h263_hwaccel_pixfmt_list_420, + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_H263_VAAPI_HWACCEL + HWACCEL_VAAPI(h263), +#endif +#if CONFIG_MPEG4_VDPAU_HWACCEL + HWACCEL_VDPAU(mpeg4), +#endif +#if CONFIG_H263_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(h263), +#endif + NULL + }, }; diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index be187eb5f4091..b03024d4a35b9 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -47,6 +47,7 @@ #include "h264_mvpred.h" #include "h264_ps.h" #include "golomb.h" +#include "hwaccel.h" #include "mathops.h" #include "me_cmp.h" #include "mpegutils.h" @@ -1059,6 +1060,30 @@ AVCodec ff_h264_decoder = { .capabilities = /*AV_CODEC_CAP_DRAW_HORIZ_BAND |*/ AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_H264_DXVA2_HWACCEL + HWACCEL_DXVA2(h264), +#endif +#if CONFIG_H264_D3D11VA_HWACCEL + HWACCEL_D3D11VA(h264), +#endif +#if CONFIG_H264_D3D11VA2_HWACCEL + HWACCEL_D3D11VA2(h264), +#endif +#if CONFIG_H264_NVDEC_HWACCEL + HWACCEL_NVDEC(h264), +#endif +#if CONFIG_H264_VAAPI_HWACCEL + HWACCEL_VAAPI(h264), +#endif +#if CONFIG_H264_VDPAU_HWACCEL + HWACCEL_VDPAU(h264), +#endif +#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(h264), +#endif + NULL + }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING, .flush = flush_dpb, .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 75960912b184f..5ec6105d2fd79 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -41,6 +41,7 @@ #include "hevc_data.h" #include "hevc_parse.h" #include "hevcdec.h" +#include "hwaccel.h" #include "profiles.h" const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12] = 4, [16] = 5, [24] = 6, [32] = 7, [48] = 8, [64] = 9 }; @@ -3510,4 +3511,28 @@ AVCodec ff_hevc_decoder = { AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING, .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_HEVC_DXVA2_HWACCEL + HWACCEL_DXVA2(hevc), +#endif +#if CONFIG_HEVC_D3D11VA_HWACCEL + HWACCEL_D3D11VA(hevc), +#endif +#if CONFIG_HEVC_D3D11VA2_HWACCEL + HWACCEL_D3D11VA2(hevc), +#endif +#if CONFIG_HEVC_NVDEC_HWACCEL + HWACCEL_NVDEC(hevc), +#endif +#if CONFIG_HEVC_VAAPI_HWACCEL + HWACCEL_VAAPI(hevc), +#endif +#if CONFIG_HEVC_VDPAU_HWACCEL + HWACCEL_VDPAU(hevc), +#endif +#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(hevc), +#endif + NULL + }, }; diff --git a/libavcodec/hwaccel.h b/libavcodec/hwaccel.h index 0198c7f85833e..ae55527c2f3bb 100644 --- a/libavcodec/hwaccel.h +++ b/libavcodec/hwaccel.h @@ -20,6 +20,7 @@ #define AVCODEC_HWACCEL_H #include "avcodec.h" +#include "hwaccels.h" #define HWACCEL_CAP_ASYNC_SAFE (1 << 0) @@ -39,4 +40,55 @@ typedef struct AVCodecHWConfigInternal { } AVCodecHWConfigInternal; +// These macros are used to simplify AVCodecHWConfigInternal definitions. + +#define HW_CONFIG_HWACCEL(format, device, name) \ + &(const AVCodecHWConfigInternal) { \ + .public = { \ + .pix_fmt = AV_PIX_FMT_ ## format, \ + .methods = AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX | \ + AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, \ + .device_type = AV_HWDEVICE_TYPE_ ## device, \ + }, \ + .hwaccel = &name, \ + } + +#define HW_CONFIG_INTERNAL(format) \ + &(const AVCodecHWConfigInternal) { \ + .public = { \ + .pix_fmt = AV_PIX_FMT_ ## format, \ + .methods = AV_CODEC_HW_CONFIG_METHOD_INTERNAL, \ + .device_type = AV_HWDEVICE_TYPE_NONE, \ + }, \ + .hwaccel = NULL, \ + } + +#define HW_CONFIG_AD_HOC_HWACCEL(format, name) \ + &(const AVCodecHWConfigInternal) { \ + .public = { \ + .pix_fmt = AV_PIX_FMT_ ## format, \ + .methods = AV_CODEC_HW_CONFIG_METHOD_AD_HOC, \ + .device_type = AV_HWDEVICE_TYPE_NONE, \ + }, \ + .hwaccel = &name, \ + } + +#define HWACCEL_DXVA2(codec) \ + HW_CONFIG_HWACCEL(DXVA2_VLD, DXVA2, ff_ ## codec ## _dxva2_hwaccel) +#define HWACCEL_D3D11VA2(codec) \ + HW_CONFIG_HWACCEL(D3D11, D3D11VA, ff_ ## codec ## _d3d11va2_hwaccel) +#define HWACCEL_NVDEC(codec) \ + HW_CONFIG_HWACCEL(CUDA, CUDA, ff_ ## codec ## _nvdec_hwaccel) +#define HWACCEL_VAAPI(codec) \ + HW_CONFIG_HWACCEL(VAAPI, VAAPI, ff_ ## codec ## _vaapi_hwaccel) +#define HWACCEL_VDPAU(codec) \ + HW_CONFIG_HWACCEL(VDPAU, VDPAU, ff_ ## codec ## _vdpau_hwaccel) +#define HWACCEL_VIDEOTOOLBOX(codec) \ + HW_CONFIG_HWACCEL(VIDEOTOOLBOX, VIDEOTOOLBOX, ff_ ## codec ## _videotoolbox_hwaccel) + +#define HWACCEL_D3D11VA(codec) \ + HW_CONFIG_AD_HOC_HWACCEL(D3D11VA_VLD, ff_ ## codec ## _d3d11va_hwaccel) +#define HWACCEL_XVMC(codec) \ + HW_CONFIG_AD_HOC_HWACCEL(XVMC, ff_ ## codec ## _xvmc_hwaccel) + #endif /* AVCODEC_HWACCEL_H */ diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h new file mode 100644 index 0000000000000..9a3008a92ca18 --- /dev/null +++ b/libavcodec/hwaccels.h @@ -0,0 +1,74 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HWACCELS_H +#define AVCODEC_HWACCELS_H + +#include "avcodec.h" + +extern AVHWAccel ff_h263_vaapi_hwaccel; +extern AVHWAccel ff_h263_videotoolbox_hwaccel; +extern AVHWAccel ff_h264_d3d11va_hwaccel; +extern AVHWAccel ff_h264_d3d11va2_hwaccel; +extern AVHWAccel ff_h264_dxva2_hwaccel; +extern AVHWAccel ff_h264_nvdec_hwaccel; +extern AVHWAccel ff_h264_vaapi_hwaccel; +extern AVHWAccel ff_h264_vdpau_hwaccel; +extern AVHWAccel ff_h264_videotoolbox_hwaccel; +extern AVHWAccel ff_hevc_d3d11va_hwaccel; +extern AVHWAccel ff_hevc_d3d11va2_hwaccel; +extern AVHWAccel ff_hevc_dxva2_hwaccel; +extern AVHWAccel ff_hevc_nvdec_hwaccel; +extern AVHWAccel ff_hevc_vaapi_hwaccel; +extern AVHWAccel ff_hevc_vdpau_hwaccel; +extern AVHWAccel ff_hevc_videotoolbox_hwaccel; +extern AVHWAccel ff_mpeg1_nvdec_hwaccel; +extern AVHWAccel ff_mpeg1_vdpau_hwaccel; +extern AVHWAccel ff_mpeg1_videotoolbox_hwaccel; +extern AVHWAccel ff_mpeg1_xvmc_hwaccel; +extern AVHWAccel ff_mpeg2_d3d11va_hwaccel; +extern AVHWAccel ff_mpeg2_d3d11va2_hwaccel; +extern AVHWAccel ff_mpeg2_nvdec_hwaccel; +extern AVHWAccel ff_mpeg2_dxva2_hwaccel; +extern AVHWAccel ff_mpeg2_vaapi_hwaccel; +extern AVHWAccel ff_mpeg2_vdpau_hwaccel; +extern AVHWAccel ff_mpeg2_videotoolbox_hwaccel; +extern AVHWAccel ff_mpeg2_xvmc_hwaccel; +extern AVHWAccel ff_mpeg4_nvdec_hwaccel; +extern AVHWAccel ff_mpeg4_vaapi_hwaccel; +extern AVHWAccel ff_mpeg4_vdpau_hwaccel; +extern AVHWAccel ff_mpeg4_videotoolbox_hwaccel; +extern AVHWAccel ff_vc1_d3d11va_hwaccel; +extern AVHWAccel ff_vc1_d3d11va2_hwaccel; +extern AVHWAccel ff_vc1_dxva2_hwaccel; +extern AVHWAccel ff_vc1_nvdec_hwaccel; +extern AVHWAccel ff_vc1_vaapi_hwaccel; +extern AVHWAccel ff_vc1_vdpau_hwaccel; +extern AVHWAccel ff_vp9_d3d11va_hwaccel; +extern AVHWAccel ff_vp9_d3d11va2_hwaccel; +extern AVHWAccel ff_vp9_dxva2_hwaccel; +extern AVHWAccel ff_vp9_nvdec_hwaccel; +extern AVHWAccel ff_vp9_vaapi_hwaccel; +extern AVHWAccel ff_wmv3_d3d11va_hwaccel; +extern AVHWAccel ff_wmv3_d3d11va2_hwaccel; +extern AVHWAccel ff_wmv3_dxva2_hwaccel; +extern AVHWAccel ff_wmv3_nvdec_hwaccel; +extern AVHWAccel ff_wmv3_vaapi_hwaccel; +extern AVHWAccel ff_wmv3_vdpau_hwaccel; + +#endif /* AVCODEC_HWACCELS_H */ diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 0cf9419ea32b7..6d392adb3ab4f 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -515,6 +515,18 @@ static void mediacodec_decode_flush(AVCodecContext *avctx) ff_mediacodec_dec_flush(avctx, s->ctx); } +static const AVCodecHWConfigInternal *mediacodec_hw_configs[] = { + &(const AVCodecHWConfigInternal) { + .public = { + .pix_fmt = AV_PIX_FMT_MEDIACODEC, + .methods = AV_CODEC_HW_CONFIG_METHOD_AD_HOC, + .device_type = AV_HWDEVICE_TYPE_NONE, + }, + .hwaccel = NULL, + }, + NULL +}; + #if CONFIG_H264_MEDIACODEC_DECODER AVCodec ff_h264_mediacodec_decoder = { .name = "h264_mediacodec", @@ -529,6 +541,7 @@ AVCodec ff_h264_mediacodec_decoder = { .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, .bsfs = "h264_mp4toannexb", + .hw_configs = mediacodec_hw_configs, }; #endif @@ -546,6 +559,7 @@ AVCodec ff_hevc_mediacodec_decoder = { .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, .bsfs = "hevc_mp4toannexb", + .hw_configs = mediacodec_hw_configs, }; #endif @@ -562,6 +576,7 @@ AVCodec ff_mpeg2_mediacodec_decoder = { .close = mediacodec_decode_close, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, + .hw_configs = mediacodec_hw_configs, }; #endif @@ -578,6 +593,7 @@ AVCodec ff_mpeg4_mediacodec_decoder = { .close = mediacodec_decode_close, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, + .hw_configs = mediacodec_hw_configs, }; #endif @@ -594,6 +610,7 @@ AVCodec ff_vp8_mediacodec_decoder = { .close = mediacodec_decode_close, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, + .hw_configs = mediacodec_hw_configs, }; #endif @@ -610,5 +627,6 @@ AVCodec ff_vp9_mediacodec_decoder = { .close = mediacodec_decode_close, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, + .hw_configs = mediacodec_hw_configs, }; #endif diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index f2ee3557aa380..26e5fc9b6ab32 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -34,6 +34,7 @@ #include #include "avcodec.h" +#include "hwaccel.h" #include "internal.h" #include "libavutil/avassert.h" #include "libavutil/buffer.h" @@ -835,6 +836,11 @@ AVHWAccel ff_vc1_mmal_hwaccel = { .pix_fmt = AV_PIX_FMT_MMAL, }; +static const AVCodecHWConfigInternal *mmal_hw_configs[] = { + HW_CONFIG_INTERNAL(MMAL), + NULL +}; + static const AVOption options[]={ {"extra_buffers", "extra buffers", offsetof(MMALDecodeContext, extra_buffers), AV_OPT_TYPE_INT, {.i64 = 10}, 0, 256, 0}, {"extra_decoder_buffers", "extra MMAL internal buffered frames", offsetof(MMALDecodeContext, extra_decoder_buffers), AV_OPT_TYPE_INT, {.i64 = 10}, 0, 256, 0}, @@ -867,6 +873,7 @@ static const AVOption options[]={ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MMAL, \ AV_PIX_FMT_YUV420P, \ AV_PIX_FMT_NONE}, \ + .hw_configs = mmal_hw_configs, \ }; FFMMAL_DEC(h264, AV_CODEC_ID_H264) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 5a51d09bb07df..ac5ac4bca4d0d 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -36,6 +36,7 @@ #include "avcodec.h" #include "bytestream.h" #include "error_resilience.h" +#include "hwaccel.h" #include "idctdsp.h" #include "internal.h" #include "mpeg_er.h" @@ -2890,7 +2891,22 @@ AVCodec ff_mpeg1video_decoder = { .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = flush, .max_lowres = 3, - .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg_decode_update_thread_context) + .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg_decode_update_thread_context), + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_MPEG2_NVDEC_HWACCEL + HWACCEL_NVDEC(mpeg1), +#endif +#if CONFIG_MPEG1_VDPAU_HWACCEL + HWACCEL_VDPAU(mpeg1), +#endif +#if CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(mpeg1), +#endif +#if CONFIG_MPEG1_XVMC_HWACCEL + HWACCEL_XVMC(mpeg1), +#endif + NULL + }, }; AVCodec ff_mpeg2video_decoder = { @@ -2909,6 +2925,33 @@ AVCodec ff_mpeg2video_decoder = { .flush = flush, .max_lowres = 3, .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg2_video_profiles), + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_MPEG2_DXVA2_HWACCEL + HWACCEL_DXVA2(mpeg2), +#endif +#if CONFIG_MPEG2_D3D11VA_HWACCEL + HWACCEL_D3D11VA(mpeg2), +#endif +#if CONFIG_MPEG2_D3D11VA2_HWACCEL + HWACCEL_D3D11VA2(mpeg2), +#endif +#if CONFIG_MPEG2_NVDEC_HWACCEL + HWACCEL_NVDEC(mpeg2), +#endif +#if CONFIG_MPEG2_VAAPI_HWACCEL + HWACCEL_VAAPI(mpeg2), +#endif +#if CONFIG_MPEG2_VDPAU_HWACCEL + HWACCEL_VDPAU(mpeg2), +#endif +#if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(mpeg2), +#endif +#if CONFIG_MPEG2_XVMC_HWACCEL + HWACCEL_XVMC(mpeg2), +#endif + NULL + }, }; //legacy decoder diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 69f455e22677d..19fcc1bc8f755 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -25,6 +25,7 @@ #include "libavutil/internal.h" #include "libavutil/opt.h" #include "error_resilience.h" +#include "hwaccel.h" #include "idctdsp.h" #include "internal.h" #include "mpegutils.h" @@ -2855,4 +2856,19 @@ AVCodec ff_mpeg4_decoder = { .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg4_video_profiles), .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg4_update_thread_context), .priv_class = &mpeg4_class, + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_MPEG2_NVDEC_HWACCEL + HWACCEL_NVDEC(mpeg4), +#endif +#if CONFIG_MPEG4_VAAPI_HWACCEL + HWACCEL_VAAPI(mpeg4), +#endif +#if CONFIG_MPEG4_VDPAU_HWACCEL + HWACCEL_VDPAU(mpeg4), +#endif +#if CONFIG_MPEG4_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(mpeg4), +#endif + NULL + }, }; diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index c00817f1d93e5..55fe59b5319bb 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -41,6 +41,19 @@ #include "qsv_internal.h" #include "qsvdec.h" +const AVCodecHWConfigInternal *ff_qsv_hw_configs[] = { + &(const AVCodecHWConfigInternal) { + .public = { + .pix_fmt = AV_PIX_FMT_QSV, + .methods = AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX | + AV_CODEC_HW_CONFIG_METHOD_AD_HOC, + .device_type = AV_HWDEVICE_TYPE_QSV, + }, + .hwaccel = NULL, + }, + NULL +}; + static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session, AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref) { diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h index 4e86e4b7f8f89..5b7b03a48b5cd 100644 --- a/libavcodec/qsvdec.h +++ b/libavcodec/qsvdec.h @@ -33,6 +33,7 @@ #include "libavutil/pixfmt.h" #include "avcodec.h" +#include "hwaccel.h" #include "qsv_internal.h" typedef struct QSVContext { @@ -70,6 +71,8 @@ typedef struct QSVContext { int nb_ext_buffers; } QSVContext; +extern const AVCodecHWConfigInternal *ff_qsv_hw_configs[]; + int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, AVFrame *frame, int *got_frame, AVPacket *pkt); diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c index ea416a97deb36..ace2ec16d5c9b 100644 --- a/libavcodec/qsvdec_h2645.c +++ b/libavcodec/qsvdec_h2645.c @@ -226,6 +226,7 @@ AVCodec ff_hevc_qsv_decoder = { AV_PIX_FMT_P010, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, + .hw_configs = ff_qsv_hw_configs, .bsfs = "hevc_mp4toannexb", }; #endif @@ -268,6 +269,7 @@ AVCodec ff_h264_qsv_decoder = { AV_PIX_FMT_P010, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, + .hw_configs = ff_qsv_hw_configs, .bsfs = "h264_mp4toannexb", }; #endif diff --git a/libavcodec/qsvdec_other.c b/libavcodec/qsvdec_other.c index b94093d53c793..21aa56492f316 100644 --- a/libavcodec/qsvdec_other.c +++ b/libavcodec/qsvdec_other.c @@ -190,6 +190,7 @@ AVCodec ff_mpeg2_qsv_decoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, + .hw_configs = ff_qsv_hw_configs, }; #endif @@ -225,6 +226,7 @@ AVCodec ff_vc1_qsv_decoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, + .hw_configs = ff_qsv_hw_configs, }; #endif @@ -260,5 +262,6 @@ AVCodec ff_vp8_qsv_decoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, + .hw_configs = ff_qsv_hw_configs, }; #endif diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 96b8bb5364e0b..ac4cfed2c8e44 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "blockdsp.h" #include "get_bits.h" +#include "hwaccel.h" #include "internal.h" #include "mpeg_er.h" #include "mpegvideo.h" @@ -1144,6 +1145,27 @@ AVCodec ff_vc1_decoder = { .flush = ff_mpeg_flush, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .pix_fmts = vc1_hwaccel_pixfmt_list_420, + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_WMV3_DXVA2_HWACCEL + HWACCEL_DXVA2(wmv3), +#endif +#if CONFIG_WMV3_D3D11VA_HWACCEL + HWACCEL_D3D11VA(wmv3), +#endif +#if CONFIG_WMV3_D3D11VA2_HWACCEL + HWACCEL_D3D11VA2(wmv3), +#endif +#if CONFIG_WMV3_NVDEC_HWACCEL + HWACCEL_NVDEC(wmv3), +#endif +#if CONFIG_WMV3_VAAPI_HWACCEL + HWACCEL_VAAPI(wmv3), +#endif +#if CONFIG_WMV3_VDPAU_HWACCEL + HWACCEL_VDPAU(wmv3), +#endif + NULL + }, .profiles = NULL_IF_CONFIG_SMALL(ff_vc1_profiles) }; @@ -1160,6 +1182,27 @@ AVCodec ff_wmv3_decoder = { .flush = ff_mpeg_flush, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .pix_fmts = vc1_hwaccel_pixfmt_list_420, + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_VC1_DXVA2_HWACCEL + HWACCEL_DXVA2(wmv3), +#endif +#if CONFIG_VC1_D3D11VA_HWACCEL + HWACCEL_D3D11VA(wmv3), +#endif +#if CONFIG_VC1_D3D11VA2_HWACCEL + HWACCEL_D3D11VA2(wmv3), +#endif +#if CONFIG_VC1_NVDEC_HWACCEL + HWACCEL_NVDEC(wmv3), +#endif +#if CONFIG_VC1_VAAPI_HWACCEL + HWACCEL_VAAPI(wmv3), +#endif +#if CONFIG_VC1_VDPAU_HWACCEL + HWACCEL_VDPAU(wmv3), +#endif + NULL + }, .profiles = NULL_IF_CONFIG_SMALL(ff_vc1_profiles) }; #endif diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index 6ce9be61bb25a..1ea2869c4c138 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -23,6 +23,7 @@ #include "avcodec.h" #include "get_bits.h" +#include "hwaccel.h" #include "internal.h" #include "profiles.h" #include "thread.h" @@ -1794,4 +1795,22 @@ AVCodec ff_vp9_decoder = { .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp9_decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp9_decode_update_thread_context), .profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_VP9_DXVA2_HWACCEL + HWACCEL_DXVA2(vp9), +#endif +#if CONFIG_VP9_D3D11VA_HWACCEL + HWACCEL_D3D11VA(vp9), +#endif +#if CONFIG_VP9_D3D11VA2_HWACCEL + HWACCEL_D3D11VA2(vp9), +#endif +#if CONFIG_VP9_NVDEC_HWACCEL + HWACCEL_NVDEC(vp9), +#endif +#if CONFIG_VP9_VAAPI_HWACCEL + HWACCEL_VAAPI(vp9), +#endif + NULL + }, }; From 67e81d79ccfc6713c797ddb19a3b8aea476c947b Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:43 +0100 Subject: [PATCH 1123/2557] lavc: Use hardware config information in ff_get_format() This removes the dependency that hardware pixel formats previously had on AVHWAccel instances, meaning only those which actually do something need exist after this patch. Also updates avcodec_default_get_format() to be able to choose hardware formats if either a matching device has been supplied or no additional external configuration is required, and avcodec_get_hw_frames_parameters() to use the hardware config rather than searching the old hwaccel list. The FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS mechanism is deleted because it no longer does anything (the codec already contains the pointers to the matching hwaccels). --- libavcodec/avcodec.h | 7 -- libavcodec/cuviddec.c | 2 - libavcodec/decode.c | 285 ++++++++++++++++++++++++++++++------------ libavcodec/internal.h | 11 +- 4 files changed, 211 insertions(+), 94 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index e2dc97d62fab9..a78c69a708d49 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3652,13 +3652,6 @@ typedef struct AVHWAccel { * that avctx->hwaccel_priv_data is invalid. */ int (*frame_params)(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); - - /** - * Some hwaccels are ambiguous if only the id and pix_fmt fields are used. - * If non-NULL, the associated AVCodec must have - * FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS set. - */ - const AVClass *decoder_class; } AVHWAccel; /** diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index 3bd2409ea2930..33e9140f89970 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -1120,7 +1120,6 @@ static const AVCodecHWConfigInternal *cuvid_hw_configs[] = { .type = AVMEDIA_TYPE_VIDEO, \ .id = AV_CODEC_ID_##X, \ .pix_fmt = AV_PIX_FMT_CUDA, \ - .decoder_class = &x##_cuvid_class, \ }; \ AVCodec ff_##x##_cuvid_decoder = { \ .name = #x "_cuvid", \ @@ -1135,7 +1134,6 @@ static const AVCodecHWConfigInternal *cuvid_hw_configs[] = { .receive_frame = cuvid_output_frame, \ .flush = cuvid_flush, \ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ - .caps_internal = FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS, \ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA, \ AV_PIX_FMT_NV12, \ AV_PIX_FMT_P010, \ diff --git a/libavcodec/decode.c b/libavcodec/decode.c index a7f1e23fc2dca..f2a23735ace7d 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -40,6 +40,7 @@ #include "avcodec.h" #include "bytestream.h" #include "decode.h" +#include "hwaccel.h" #include "internal.h" #include "thread.h" @@ -1077,33 +1078,67 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, return ret; } -static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt) +enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *avctx, + const enum AVPixelFormat *fmt) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - return desc->flags & AV_PIX_FMT_FLAG_HWACCEL; -} - -enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat *fmt) -{ - while (*fmt != AV_PIX_FMT_NONE && is_hwaccel_pix_fmt(*fmt)) - ++fmt; - return fmt[0]; -} - -static AVHWAccel *find_hwaccel(AVCodecContext *avctx, - enum AVPixelFormat pix_fmt) -{ - AVHWAccel *hwaccel = NULL; - const AVClass *av_class = - (avctx->codec->caps_internal & FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS) - ? avctx->codec->priv_class : NULL; - - while ((hwaccel = av_hwaccel_next(hwaccel))) { - if (hwaccel->decoder_class == av_class && hwaccel->id == avctx->codec_id - && hwaccel->pix_fmt == pix_fmt) - return hwaccel; + const AVPixFmtDescriptor *desc; + const AVCodecHWConfig *config; + int i, n; + + // If a device was supplied when the codec was opened, assume that the + // user wants to use it. + if (avctx->hw_device_ctx && avctx->codec->hw_configs) { + AVHWDeviceContext *device_ctx = + (AVHWDeviceContext*)avctx->hw_device_ctx->data; + for (i = 0;; i++) { + config = &avctx->codec->hw_configs[i]->public; + if (!config) + break; + if (!(config->methods & + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) + continue; + if (device_ctx->type != config->device_type) + continue; + for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++) { + if (config->pix_fmt == fmt[n]) + return fmt[n]; + } + } } - return NULL; + // No device or other setup, so we have to choose from things which + // don't any other external information. + + // If the last element of the list is a software format, choose it + // (this should be best software format if any exist). + for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++); + desc = av_pix_fmt_desc_get(fmt[n - 1]); + if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) + return fmt[n - 1]; + + // Finally, traverse the list in order and choose the first entry + // with no external dependencies (if there is no hardware configuration + // information available then this just picks the first entry). + for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++) { + for (i = 0;; i++) { + config = avcodec_get_hw_config(avctx->codec, i); + if (!config) + break; + if (config->pix_fmt == fmt[n]) + break; + } + if (!config) { + // No specific config available, so the decoder must be able + // to handle this format without any additional setup. + return fmt[n]; + } + if (config->methods & AV_CODEC_HW_CONFIG_METHOD_INTERNAL) { + // Usable with only internal setup. + return fmt[n]; + } + } + + // Nothing is usable, give up. + return AV_PIX_FMT_NONE; } int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx, @@ -1167,9 +1202,19 @@ int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, AVBufferRef **out_frames_ref) { AVBufferRef *frames_ref = NULL; - AVHWAccel *hwa = find_hwaccel(avctx, hw_pix_fmt); - int ret; + const AVCodecHWConfigInternal *hw_config; + const AVHWAccel *hwa; + int i, ret; + for (i = 0;; i++) { + hw_config = avctx->codec->hw_configs[i]; + if (!hw_config) + return AVERROR(ENOENT); + if (hw_config->public.pix_fmt == hw_pix_fmt) + break; + } + + hwa = hw_config->hwaccel; if (!hwa || !hwa->frame_params) return AVERROR(ENOENT); @@ -1186,59 +1231,75 @@ int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, return ret; } -static int setup_hwaccel(AVCodecContext *avctx, - const enum AVPixelFormat fmt, - const char *name) +static int hwaccel_init(AVCodecContext *avctx, + const AVCodecHWConfigInternal *hw_config) { - AVHWAccel *hwa = find_hwaccel(avctx, fmt); - int ret = 0; + const AVHWAccel *hwaccel; + int err; - if (!hwa) { - av_log(avctx, AV_LOG_ERROR, - "Could not find an AVHWAccel for the pixel format: %s\n", - name); - return AVERROR(ENOENT); - } - - if (hwa->capabilities & AV_HWACCEL_CODEC_CAP_EXPERIMENTAL && + hwaccel = hw_config->hwaccel; + if (hwaccel->capabilities & AV_HWACCEL_CODEC_CAP_EXPERIMENTAL && avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { av_log(avctx, AV_LOG_WARNING, "Ignoring experimental hwaccel: %s\n", - hwa->name); + hwaccel->name); return AVERROR_PATCHWELCOME; } - if (hwa->priv_data_size) { - avctx->internal->hwaccel_priv_data = av_mallocz(hwa->priv_data_size); + if (hwaccel->priv_data_size) { + avctx->internal->hwaccel_priv_data = + av_mallocz(hwaccel->priv_data_size); if (!avctx->internal->hwaccel_priv_data) return AVERROR(ENOMEM); } - avctx->hwaccel = hwa; - if (hwa->init) { - ret = hwa->init(avctx); - if (ret < 0) { + avctx->hwaccel = (AVHWAccel*)hwaccel; + if (hwaccel->init) { + err = hwaccel->init(avctx); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed setup for format %s: " + "hwaccel initialisation returned error.\n", + av_get_pix_fmt_name(hw_config->public.pix_fmt)); av_freep(&avctx->internal->hwaccel_priv_data); avctx->hwaccel = NULL; - return ret; + return err; } } return 0; } +static void hwaccel_uninit(AVCodecContext *avctx) +{ + if (avctx->hwaccel && avctx->hwaccel->uninit) + avctx->hwaccel->uninit(avctx); + + av_freep(&avctx->internal->hwaccel_priv_data); + + avctx->hwaccel = NULL; + + av_buffer_unref(&avctx->hw_frames_ctx); +} + int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) { const AVPixFmtDescriptor *desc; enum AVPixelFormat *choices; - enum AVPixelFormat ret; - unsigned n = 0; - - while (fmt[n] != AV_PIX_FMT_NONE) - ++n; - + enum AVPixelFormat ret, user_choice; + const AVCodecHWConfigInternal *hw_config; + const AVCodecHWConfig *config; + int i, n, err; + + // Find end of list. + for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++); + // Must contain at least one entry. av_assert0(n >= 1); - avctx->sw_pix_fmt = fmt[n - 1]; - av_assert2(!is_hwaccel_pix_fmt(avctx->sw_pix_fmt)); + // If a software format is available, it must be the last entry. + desc = av_pix_fmt_desc_get(fmt[n - 1]); + if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) { + // No software format is available. + } else { + avctx->sw_pix_fmt = fmt[n - 1]; + } choices = av_malloc_array(n + 1, sizeof(*choices)); if (!choices) @@ -1247,44 +1308,108 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) memcpy(choices, fmt, (n + 1) * sizeof(*choices)); for (;;) { - if (avctx->hwaccel && avctx->hwaccel->uninit) - avctx->hwaccel->uninit(avctx); - av_freep(&avctx->internal->hwaccel_priv_data); - avctx->hwaccel = NULL; + // Remove the previous hwaccel, if there was one. + hwaccel_uninit(avctx); - av_buffer_unref(&avctx->hw_frames_ctx); - - ret = avctx->get_format(avctx, choices); + user_choice = avctx->get_format(avctx, choices); + if (user_choice == AV_PIX_FMT_NONE) { + // Explicitly chose nothing, give up. + ret = AV_PIX_FMT_NONE; + break; + } - desc = av_pix_fmt_desc_get(ret); + desc = av_pix_fmt_desc_get(user_choice); if (!desc) { + av_log(avctx, AV_LOG_ERROR, "Invalid format returned by " + "get_format() callback.\n"); ret = AV_PIX_FMT_NONE; break; } + av_log(avctx, AV_LOG_DEBUG, "Format %s chosen by get_format().\n", + desc->name); - if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) + for (i = 0; i < n; i++) { + if (choices[i] == user_choice) + break; + } + if (i == n) { + av_log(avctx, AV_LOG_ERROR, "Invalid return from get_format(): " + "%s not in possible list.\n", desc->name); break; + } - if (avctx->hw_frames_ctx) { - AVHWFramesContext *hw_frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - if (hw_frames_ctx->format != ret) { - av_log(avctx, AV_LOG_ERROR, "Format returned from get_buffer() " - "does not match the format of provided AVHWFramesContext\n"); - ret = AV_PIX_FMT_NONE; - break; + if (avctx->codec->hw_configs) { + for (i = 0;; i++) { + hw_config = avctx->codec->hw_configs[i]; + if (!hw_config) + break; + if (hw_config->public.pix_fmt == user_choice) + break; } + } else { + hw_config = NULL; } - if (!setup_hwaccel(avctx, ret, desc->name)) + if (!hw_config) { + // No config available, so no extra setup required. + ret = user_choice; break; + } + config = &hw_config->public; + + if (config->methods & + AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX && + avctx->hw_frames_ctx) { + const AVHWFramesContext *frames_ctx = + (AVHWFramesContext*)avctx->hw_frames_ctx->data; + if (frames_ctx->format != user_choice) { + av_log(avctx, AV_LOG_ERROR, "Invalid setup for format %s: " + "does not match the format of the provided frames " + "context.\n", desc->name); + goto try_again; + } + } else if (config->methods & + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX && + avctx->hw_device_ctx) { + const AVHWDeviceContext *device_ctx = + (AVHWDeviceContext*)avctx->hw_device_ctx->data; + if (device_ctx->type != config->device_type) { + av_log(avctx, AV_LOG_ERROR, "Invalid setup for format %s: " + "does not match the type of the provided device " + "context.\n", desc->name); + goto try_again; + } + } else if (config->methods & + AV_CODEC_HW_CONFIG_METHOD_INTERNAL) { + // Internal-only setup, no additional configuration. + } else if (config->methods & + AV_CODEC_HW_CONFIG_METHOD_AD_HOC) { + // Some ad-hoc configuration we can't see and can't check. + } else { + av_log(avctx, AV_LOG_ERROR, "Invalid setup for format %s: " + "missing configuration.\n", desc->name); + goto try_again; + } + if (hw_config->hwaccel) { + av_log(avctx, AV_LOG_DEBUG, "Format %s requires hwaccel " + "initialisation.\n", desc->name); + err = hwaccel_init(avctx, hw_config); + if (err < 0) + goto try_again; + } + ret = user_choice; + break; - /* Remove failed hwaccel from choices */ - for (n = 0; choices[n] != ret; n++) - av_assert0(choices[n] != AV_PIX_FMT_NONE); - - do - choices[n] = choices[n + 1]; - while (choices[n++] != AV_PIX_FMT_NONE); + try_again: + av_log(avctx, AV_LOG_DEBUG, "Format %s not usable, retrying " + "get_format() without it.\n", desc->name); + for (i = 0; i < n; i++) { + if (choices[i] == user_choice) + break; + } + for (; i + 1 < n; i++) + choices[i] = choices[i + 1]; + --n; } av_freep(&choices); diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 1c54966f37a32..6deaf1d204c84 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -69,11 +69,6 @@ */ #define FF_CODEC_CAP_SLICE_THREAD_HAS_MF (1 << 5) -/** - * Allow only AVHWAccels which have a matching decoder_class field. - */ -#define FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS (1 << 6) - #ifdef TRACE # define ff_tlog(ctx, ...) av_log(ctx, AV_LOG_TRACE, __VA_ARGS__) #else @@ -377,6 +372,12 @@ int ff_side_data_update_matrix_encoding(AVFrame *frame, * Select the (possibly hardware accelerated) pixel format. * This is a wrapper around AVCodecContext.get_format() and should be used * instead of calling get_format() directly. + * + * The list of pixel formats must contain at least one valid entry, and is + * terminated with AV_PIX_FMT_NONE. If it is possible to decode to software, + * the last entry in the list must be the most accurate software format. + * If it is not possible to decode to software, AVCodecContext.sw_pix_fmt + * must be set before calling this function. */ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt); From 3536a3efb9fde88d34d526a51b1080247326cd6e Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:44 +0100 Subject: [PATCH 1124/2557] lavc: Deprecate av_hwaccel_next() and av_register_hwaccel() --- doc/APIchanges | 4 ++++ libavcodec/avcodec.h | 14 +++++++++++++- libavcodec/utils.c | 16 +++++----------- libavcodec/version.h | 5 ++++- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index a0c8e709de415..457a76971bd45 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2017-10-21 API changes, most recent first: +2017-11-xx - xxxxxxx - lavc 58.5.100 - avcodec.h + Deprecate user visibility of the AVHWAccel structure and the functions + av_register_hwaccel() and av_hwaccel_next(). + 2017-11-xx - xxxxxxx - lavc 58.4.100 - avcodec.h Add AVCodecHWConfig and avcodec_get_hw_config(). diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index a78c69a708d49..1ae0344bb2e39 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3489,6 +3489,10 @@ const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index); /** * @defgroup lavc_hwaccel AVHWAccel + * + * @note Nothing in this structure should be accessed by the user. At some + * point in future it will not be externally visible at all. + * * @{ */ typedef struct AVHWAccel { @@ -3533,7 +3537,6 @@ typedef struct AVHWAccel { * New public fields should be added right above. ***************************************************************** */ - struct AVHWAccel *next; /** * Allocate a custom buffer @@ -5874,17 +5877,26 @@ void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size); */ unsigned int av_xiphlacing(unsigned char *s, unsigned int v); +#if FF_API_USER_VISIBLE_AVHWACCEL /** * Register the hardware accelerator hwaccel. + * + * @deprecated This function doesn't do anything. */ +attribute_deprecated void av_register_hwaccel(AVHWAccel *hwaccel); /** * If hwaccel is NULL, returns the first registered hardware accelerator, * if hwaccel is non-NULL, returns the next registered hardware accelerator * after hwaccel, or NULL if hwaccel is the last one. + * + * @deprecated AVHWaccel structures contain no user-serviceable parts, so + * this function should not be used. */ +attribute_deprecated AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel); +#endif /** diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 2a09ed4930e2f..baf09119fe70f 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -1898,22 +1898,16 @@ const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index) return &codec->hw_configs[index]->public; } -static AVHWAccel *first_hwaccel = NULL; -static AVHWAccel **last_hwaccel = &first_hwaccel; - -void av_register_hwaccel(AVHWAccel *hwaccel) +#if FF_API_USER_VISIBLE_AVHWACCEL +AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel) { - AVHWAccel **p = last_hwaccel; - hwaccel->next = NULL; - while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, hwaccel)) - p = &(*p)->next; - last_hwaccel = &hwaccel->next; + return NULL; } -AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel) +void av_register_hwaccel(AVHWAccel *hwaccel) { - return hwaccel ? hwaccel->next : first_hwaccel; } +#endif int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) { diff --git a/libavcodec/version.h b/libavcodec/version.h index 8847737f37781..ddab7c47a7804 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 4 +#define LIBAVCODEC_VERSION_MINOR 5 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ @@ -123,6 +123,9 @@ #ifndef FF_API_CODEC_GET_SET #define FF_API_CODEC_GET_SET (LIBAVCODEC_VERSION_MAJOR < 59) #endif +#ifndef FF_API_USER_VISIBLE_AVHWACCEL +#define FF_API_USER_VISIBLE_AVHWACCEL (LIBAVCODEC_VERSION_MAJOR < 59) +#endif #endif /* AVCODEC_VERSION_H */ From 9bd326ac465db2eee47301a1225d55dffd7bfe93 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:45 +0100 Subject: [PATCH 1125/2557] lavc: Remove register mechanism for hwaccels There is no longer any need for a list of them at runtime, because decoders now carry the pointers to their associated hwaccels internally. The file containing external declarations is now used to make the list of hwaccels for configure. --- configure | 2 +- libavcodec/allcodecs.c | 82 ------------------------------------------ 2 files changed, 1 insertion(+), 83 deletions(-) diff --git a/configure b/configure index 0cc97ebbbbef3..461f2e66aabbd 100755 --- a/configure +++ b/configure @@ -3527,7 +3527,6 @@ find_things(){ ENCODER_LIST=$(find_things encoder ENC libavcodec/allcodecs.c) DECODER_LIST=$(find_things decoder DEC libavcodec/allcodecs.c) -HWACCEL_LIST=$(find_things hwaccel HWACCEL libavcodec/allcodecs.c) PARSER_LIST=$(find_things parser PARSER libavcodec/allcodecs.c) MUXER_LIST=$(find_things muxer _MUX libavformat/allformats.c) DEMUXER_LIST=$(find_things demuxer DEMUX libavformat/allformats.c) @@ -3543,6 +3542,7 @@ find_things_extern(){ } BSF_LIST=$(find_things_extern bsf AVBitStreamFilter libavcodec/bitstream_filters.c) +HWACCEL_LIST=$(find_things_extern hwaccel AVHWAccel libavcodec/hwaccels.h) PROTOCOL_LIST=$(find_things_extern protocol URLProtocol libavformat/protocols.c) AVCODEC_COMPONENTS_LIST=" diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 85c38c83aa467..4a21687b202b1 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -29,13 +29,6 @@ #include "avcodec.h" #include "version.h" -#define REGISTER_HWACCEL(X, x) \ - { \ - extern AVHWAccel ff_##x##_hwaccel; \ - if (CONFIG_##X##_HWACCEL) \ - av_register_hwaccel(&ff_##x##_hwaccel); \ - } - #define REGISTER_ENCODER(X, x) \ { \ extern AVCodec ff_##x##_encoder; \ @@ -61,81 +54,6 @@ static void register_all(void) { - /* hardware accelerators */ - REGISTER_HWACCEL(H263_VAAPI, h263_vaapi); - REGISTER_HWACCEL(H263_VIDEOTOOLBOX, h263_videotoolbox); - REGISTER_HWACCEL(H264_CUVID, h264_cuvid); - REGISTER_HWACCEL(H264_D3D11VA, h264_d3d11va); - REGISTER_HWACCEL(H264_D3D11VA2, h264_d3d11va2); - REGISTER_HWACCEL(H264_DXVA2, h264_dxva2); - REGISTER_HWACCEL(H264_MEDIACODEC, h264_mediacodec); - REGISTER_HWACCEL(H264_MMAL, h264_mmal); - REGISTER_HWACCEL(H264_NVDEC, h264_nvdec); - REGISTER_HWACCEL(H264_QSV, h264_qsv); - REGISTER_HWACCEL(H264_VAAPI, h264_vaapi); - REGISTER_HWACCEL(H264_VDPAU, h264_vdpau); - REGISTER_HWACCEL(H264_VIDEOTOOLBOX, h264_videotoolbox); - REGISTER_HWACCEL(HEVC_CUVID, hevc_cuvid); - REGISTER_HWACCEL(HEVC_D3D11VA, hevc_d3d11va); - REGISTER_HWACCEL(HEVC_D3D11VA2, hevc_d3d11va2); - REGISTER_HWACCEL(HEVC_DXVA2, hevc_dxva2); - REGISTER_HWACCEL(HEVC_NVDEC, hevc_nvdec); - REGISTER_HWACCEL(HEVC_MEDIACODEC, hevc_mediacodec); - REGISTER_HWACCEL(HEVC_QSV, hevc_qsv); - REGISTER_HWACCEL(HEVC_VAAPI, hevc_vaapi); - REGISTER_HWACCEL(HEVC_VDPAU, hevc_vdpau); - REGISTER_HWACCEL(HEVC_VIDEOTOOLBOX, hevc_videotoolbox); - REGISTER_HWACCEL(MJPEG_CUVID, mjpeg_cuvid); - REGISTER_HWACCEL(MPEG1_CUVID, mpeg1_cuvid); - REGISTER_HWACCEL(MPEG1_NVDEC, mpeg1_nvdec); - REGISTER_HWACCEL(MPEG1_XVMC, mpeg1_xvmc); - REGISTER_HWACCEL(MPEG1_VDPAU, mpeg1_vdpau); - REGISTER_HWACCEL(MPEG1_VIDEOTOOLBOX, mpeg1_videotoolbox); - REGISTER_HWACCEL(MPEG2_CUVID, mpeg2_cuvid); - REGISTER_HWACCEL(MPEG2_XVMC, mpeg2_xvmc); - REGISTER_HWACCEL(MPEG2_D3D11VA, mpeg2_d3d11va); - REGISTER_HWACCEL(MPEG2_D3D11VA2, mpeg2_d3d11va2); - REGISTER_HWACCEL(MPEG2_DXVA2, mpeg2_dxva2); - REGISTER_HWACCEL(MPEG2_MMAL, mpeg2_mmal); - REGISTER_HWACCEL(MPEG2_NVDEC, mpeg2_nvdec); - REGISTER_HWACCEL(MPEG2_QSV, mpeg2_qsv); - REGISTER_HWACCEL(MPEG2_VAAPI, mpeg2_vaapi); - REGISTER_HWACCEL(MPEG2_VDPAU, mpeg2_vdpau); - REGISTER_HWACCEL(MPEG2_VIDEOTOOLBOX, mpeg2_videotoolbox); - REGISTER_HWACCEL(MPEG2_MEDIACODEC, mpeg2_mediacodec); - REGISTER_HWACCEL(MPEG4_CUVID, mpeg4_cuvid); - REGISTER_HWACCEL(MPEG4_MEDIACODEC, mpeg4_mediacodec); - REGISTER_HWACCEL(MPEG4_MMAL, mpeg4_mmal); - REGISTER_HWACCEL(MPEG4_NVDEC, mpeg4_nvdec); - REGISTER_HWACCEL(MPEG4_VAAPI, mpeg4_vaapi); - REGISTER_HWACCEL(MPEG4_VDPAU, mpeg4_vdpau); - REGISTER_HWACCEL(MPEG4_VIDEOTOOLBOX, mpeg4_videotoolbox); - REGISTER_HWACCEL(VC1_CUVID, vc1_cuvid); - REGISTER_HWACCEL(VC1_D3D11VA, vc1_d3d11va); - REGISTER_HWACCEL(VC1_D3D11VA2, vc1_d3d11va2); - REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2); - REGISTER_HWACCEL(VC1_NVDEC, vc1_nvdec); - REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi); - REGISTER_HWACCEL(VC1_VDPAU, vc1_vdpau); - REGISTER_HWACCEL(VC1_MMAL, vc1_mmal); - REGISTER_HWACCEL(VC1_QSV, vc1_qsv); - REGISTER_HWACCEL(VP8_CUVID, vp8_cuvid); - REGISTER_HWACCEL(VP8_MEDIACODEC, vp8_mediacodec); - REGISTER_HWACCEL(VP8_QSV, vp8_qsv); - REGISTER_HWACCEL(VP9_CUVID, vp9_cuvid); - REGISTER_HWACCEL(VP9_D3D11VA, vp9_d3d11va); - REGISTER_HWACCEL(VP9_D3D11VA2, vp9_d3d11va2); - REGISTER_HWACCEL(VP9_DXVA2, vp9_dxva2); - REGISTER_HWACCEL(VP9_MEDIACODEC, vp9_mediacodec); - REGISTER_HWACCEL(VP9_NVDEC, vp9_nvdec); - REGISTER_HWACCEL(VP9_VAAPI, vp9_vaapi); - REGISTER_HWACCEL(WMV3_D3D11VA, wmv3_d3d11va); - REGISTER_HWACCEL(WMV3_D3D11VA2, wmv3_d3d11va2); - REGISTER_HWACCEL(WMV3_DXVA2, wmv3_dxva2); - REGISTER_HWACCEL(WMV3_NVDEC, wmv3_nvdec); - REGISTER_HWACCEL(WMV3_VAAPI, wmv3_vaapi); - REGISTER_HWACCEL(WMV3_VDPAU, wmv3_vdpau); - /* video codecs */ REGISTER_ENCODER(A64MULTI, a64multi); REGISTER_ENCODER(A64MULTI5, a64multi5); From da4e02b1961572c15d7cd6a701d153155f196477 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:46 +0100 Subject: [PATCH 1126/2557] lavc: Delete all fake hwaccels They are now unused. --- configure | 34 ++++--------------------- libavcodec/cuviddec.c | 6 ----- libavcodec/mediacodec.c | 2 +- libavcodec/mediacodecdec_common.c | 42 ------------------------------- libavcodec/mmaldec.c | 28 --------------------- libavcodec/qsvdec_h2645.c | 18 ------------- libavcodec/qsvdec_other.c | 27 -------------------- 7 files changed, 6 insertions(+), 151 deletions(-) diff --git a/configure b/configure index 461f2e66aabbd..d6cb61fb4c479 100755 --- a/configure +++ b/configure @@ -2672,45 +2672,36 @@ h263_vaapi_hwaccel_deps="vaapi" h263_vaapi_hwaccel_select="h263_decoder" h263_videotoolbox_hwaccel_deps="videotoolbox" h263_videotoolbox_hwaccel_select="h263_decoder" -h264_cuvid_hwaccel_select="h264_cuvid_decoder" h264_d3d11va_hwaccel_deps="d3d11va" h264_d3d11va_hwaccel_select="h264_decoder" h264_d3d11va2_hwaccel_deps="d3d11va" h264_d3d11va2_hwaccel_select="h264_decoder" h264_dxva2_hwaccel_deps="dxva2" h264_dxva2_hwaccel_select="h264_decoder" -h264_mediacodec_hwaccel_deps="mediacodec" -h264_mmal_hwaccel_deps="mmal" h264_nvdec_hwaccel_deps="nvdec" h264_nvdec_hwaccel_select="h264_decoder" -h264_qsv_hwaccel_deps="libmfx" h264_vaapi_hwaccel_deps="vaapi" h264_vaapi_hwaccel_select="h264_decoder" h264_vdpau_hwaccel_deps="vdpau" h264_vdpau_hwaccel_select="h264_decoder" h264_videotoolbox_hwaccel_deps="videotoolbox" h264_videotoolbox_hwaccel_select="h264_decoder" -hevc_cuvid_hwaccel_select="hevc_cuvid_decoder" hevc_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" hevc_d3d11va_hwaccel_select="hevc_decoder" -hevc_mediacodec_hwaccel_deps="mediacodec" hevc_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" hevc_d3d11va2_hwaccel_select="hevc_decoder" hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC" hevc_dxva2_hwaccel_select="hevc_decoder" hevc_nvdec_hwaccel_deps="nvdec" hevc_nvdec_hwaccel_select="hevc_decoder" -hevc_qsv_hwaccel_deps="libmfx" hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC" hevc_vaapi_hwaccel_select="hevc_decoder" hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC" hevc_vdpau_hwaccel_select="hevc_decoder" hevc_videotoolbox_hwaccel_deps="videotoolbox" hevc_videotoolbox_hwaccel_select="hevc_decoder" -mjpeg_cuvid_hwaccel_select="mjpeg_cuvid_decoder" mpeg_xvmc_hwaccel_deps="xvmc" mpeg_xvmc_hwaccel_select="mpeg2video_decoder" -mpeg1_cuvid_hwaccel_select="mpeg1_cuvid_decoder" mpeg1_nvdec_hwaccel_deps="nvdec" mpeg1_nvdec_hwaccel_select="mpeg1video_decoder" mpeg1_vdpau_hwaccel_deps="vdpau" @@ -2719,18 +2710,14 @@ mpeg1_videotoolbox_hwaccel_deps="videotoolbox" mpeg1_videotoolbox_hwaccel_select="mpeg1video_decoder" mpeg1_xvmc_hwaccel_deps="xvmc" mpeg1_xvmc_hwaccel_select="mpeg1video_decoder" -mpeg2_cuvid_hwaccel_select="mpeg2_cuvid_decoder" mpeg2_d3d11va_hwaccel_deps="d3d11va" mpeg2_d3d11va_hwaccel_select="mpeg2video_decoder" mpeg2_d3d11va2_hwaccel_deps="d3d11va" mpeg2_d3d11va2_hwaccel_select="mpeg2video_decoder" mpeg2_dxva2_hwaccel_deps="dxva2" mpeg2_dxva2_hwaccel_select="mpeg2video_decoder" -mpeg2_mediacodec_hwaccel_deps="mediacodec" -mpeg2_mmal_hwaccel_deps="mmal" mpeg2_nvdec_hwaccel_deps="nvdec" mpeg2_nvdec_hwaccel_select="mpeg2video_decoder" -mpeg2_qsv_hwaccel_deps="libmfx" mpeg2_vaapi_hwaccel_deps="vaapi" mpeg2_vaapi_hwaccel_select="mpeg2video_decoder" mpeg2_vdpau_hwaccel_deps="vdpau" @@ -2739,9 +2726,6 @@ mpeg2_videotoolbox_hwaccel_deps="videotoolbox" mpeg2_videotoolbox_hwaccel_select="mpeg2video_decoder" mpeg2_xvmc_hwaccel_deps="xvmc" mpeg2_xvmc_hwaccel_select="mpeg2video_decoder" -mpeg4_cuvid_hwaccel_select="mpeg4_cuvid_decoder" -mpeg4_mediacodec_hwaccel_deps="mediacodec" -mpeg4_mmal_hwaccel_deps="mmal" mpeg4_nvdec_hwaccel_deps="nvdec" mpeg4_nvdec_hwaccel_select="mpeg4_decoder" mpeg4_vaapi_hwaccel_deps="vaapi" @@ -2750,32 +2734,24 @@ mpeg4_vdpau_hwaccel_deps="vdpau" mpeg4_vdpau_hwaccel_select="mpeg4_decoder" mpeg4_videotoolbox_hwaccel_deps="videotoolbox" mpeg4_videotoolbox_hwaccel_select="mpeg4_decoder" -vc1_cuvid_hwaccel_select="vc1_cuvid_decoder" vc1_d3d11va_hwaccel_deps="d3d11va" vc1_d3d11va_hwaccel_select="vc1_decoder" vc1_d3d11va2_hwaccel_deps="d3d11va" vc1_d3d11va2_hwaccel_select="vc1_decoder" vc1_dxva2_hwaccel_deps="dxva2" vc1_dxva2_hwaccel_select="vc1_decoder" -vc1_mmal_hwaccel_deps="mmal" vc1_nvdec_hwaccel_deps="nvdec" vc1_nvdec_hwaccel_select="vc1_decoder" -vc1_qsv_hwaccel_deps="libmfx" vc1_vaapi_hwaccel_deps="vaapi" vc1_vaapi_hwaccel_select="vc1_decoder" vc1_vdpau_hwaccel_deps="vdpau" vc1_vdpau_hwaccel_select="vc1_decoder" -vp8_cuvid_hwaccel_select="vp8_cuvid_decoder" -vp9_cuvid_hwaccel_select="vp9_cuvid_decoder" -vp8_mediacodec_hwaccel_deps="mediacodec" -vp8_qsv_hwaccel_deps="libmfx" vp9_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_VP9" vp9_d3d11va_hwaccel_select="vp9_decoder" vp9_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_VP9" vp9_d3d11va2_hwaccel_select="vp9_decoder" vp9_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_VP9" vp9_dxva2_hwaccel_select="vp9_decoder" -vp9_mediacodec_hwaccel_deps="mediacodec" vp9_nvdec_hwaccel_deps="nvdec" vp9_nvdec_hwaccel_select="vp9_decoder" vp9_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferVP9_bit_depth" @@ -2816,7 +2792,7 @@ h264_mediacodec_decoder_select="h264_mp4toannexb_bsf h264_parser" h264_mmal_decoder_deps="mmal" h264_nvenc_encoder_deps="nvenc" h264_omx_encoder_deps="omx" -h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec h264_qsv_hwaccel" +h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec" h264_qsv_encoder_select="qsvenc" h264_rkmpp_decoder_deps="rkmpp" h264_rkmpp_decoder_select="h264_mp4toannexb_bsf" @@ -2829,7 +2805,7 @@ hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf" hevc_mediacodec_decoder_deps="mediacodec" hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser" hevc_nvenc_encoder_deps="nvenc" -hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser qsvdec hevc_qsv_hwaccel" +hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser qsvdec" hevc_qsv_encoder_select="hevcparse qsvenc" hevc_rkmpp_decoder_deps="rkmpp" hevc_rkmpp_decoder_select="hevc_mp4toannexb_bsf" @@ -2848,7 +2824,7 @@ mpeg2_crystalhd_decoder_select="crystalhd" mpeg2_cuvid_decoder_deps="cuvid" mpeg2_mmal_decoder_deps="mmal" mpeg2_mediacodec_decoder_deps="mediacodec" -mpeg2_qsv_decoder_select="qsvdec mpeg2_qsv_hwaccel" +mpeg2_qsv_decoder_select="qsvdec mpegvideo_parser" mpeg2_qsv_encoder_select="qsvenc" mpeg2_vaapi_encoder_deps="VAEncPictureParameterBufferMPEG2" mpeg2_vaapi_encoder_select="cbs_mpeg2 vaapi_encode" @@ -2866,11 +2842,11 @@ nvenc_hevc_encoder_select="hevc_nvenc_encoder" vc1_crystalhd_decoder_select="crystalhd" vc1_cuvid_decoder_deps="cuvid" vc1_mmal_decoder_deps="mmal" -vc1_qsv_decoder_select="qsvdec vc1_qsv_hwaccel vc1_parser" +vc1_qsv_decoder_select="qsvdec vc1_parser" vc1_v4l2m2m_decoder_deps="v4l2_m2m vc1_v4l2_m2m" vp8_cuvid_decoder_deps="cuvid" vp8_mediacodec_decoder_deps="mediacodec" -vp8_qsv_decoder_select="qsvdec vp8_qsv_hwaccel vp8_parser" +vp8_qsv_decoder_select="qsvdec vp8_parser" vp8_rkmpp_decoder_deps="rkmpp" vp8_vaapi_encoder_deps="VAEncPictureParameterBufferVP8" vp8_vaapi_encoder_select="vaapi_encode" diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index 33e9140f89970..96d56f406a936 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -1115,12 +1115,6 @@ static const AVCodecHWConfigInternal *cuvid_hw_configs[] = { .option = options, \ .version = LIBAVUTIL_VERSION_INT, \ }; \ - AVHWAccel ff_##x##_cuvid_hwaccel = { \ - .name = #x "_cuvid", \ - .type = AVMEDIA_TYPE_VIDEO, \ - .id = AV_CODEC_ID_##X, \ - .pix_fmt = AV_PIX_FMT_CUDA, \ - }; \ AVCodec ff_##x##_cuvid_decoder = { \ .name = #x "_cuvid", \ .long_name = NULL_IF_CONFIG_SMALL("Nvidia CUVID " #X " decoder"), \ diff --git a/libavcodec/mediacodec.c b/libavcodec/mediacodec.c index 610bb49a733ba..d492eefe0b5ce 100644 --- a/libavcodec/mediacodec.c +++ b/libavcodec/mediacodec.c @@ -26,7 +26,7 @@ #include "mediacodec.h" -#if CONFIG_H264_MEDIACODEC_HWACCEL +#if CONFIG_MEDIACODEC #include diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index afa054f83e465..cb2f6ae5e5d3f 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -757,45 +757,3 @@ int ff_mediacodec_dec_is_flushing(AVCodecContext *avctx, MediaCodecDecContext *s { return s->flushing; } - -AVHWAccel ff_h264_mediacodec_hwaccel = { - .name = "mediacodec", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .pix_fmt = AV_PIX_FMT_MEDIACODEC, -}; - -AVHWAccel ff_hevc_mediacodec_hwaccel = { - .name = "mediacodec", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HEVC, - .pix_fmt = AV_PIX_FMT_MEDIACODEC, -}; - -AVHWAccel ff_mpeg2_mediacodec_hwaccel = { - .name = "mediacodec", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO, - .pix_fmt = AV_PIX_FMT_MEDIACODEC, -}; - -AVHWAccel ff_mpeg4_mediacodec_hwaccel = { - .name = "mediacodec", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG4, - .pix_fmt = AV_PIX_FMT_MEDIACODEC, -}; - -AVHWAccel ff_vp8_mediacodec_hwaccel = { - .name = "mediacodec", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP8, - .pix_fmt = AV_PIX_FMT_MEDIACODEC, -}; - -AVHWAccel ff_vp9_mediacodec_hwaccel = { - .name = "mediacodec", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP9, - .pix_fmt = AV_PIX_FMT_MEDIACODEC, -}; diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index 26e5fc9b6ab32..b3f0cca4b5c0e 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -808,34 +808,6 @@ static int ffmmal_decode(AVCodecContext *avctx, void *data, int *got_frame, return ret; } -AVHWAccel ff_h264_mmal_hwaccel = { - .name = "h264_mmal", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .pix_fmt = AV_PIX_FMT_MMAL, -}; - -AVHWAccel ff_mpeg2_mmal_hwaccel = { - .name = "mpeg2_mmal", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO, - .pix_fmt = AV_PIX_FMT_MMAL, -}; - -AVHWAccel ff_mpeg4_mmal_hwaccel = { - .name = "mpeg4_mmal", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG4, - .pix_fmt = AV_PIX_FMT_MMAL, -}; - -AVHWAccel ff_vc1_mmal_hwaccel = { - .name = "vc1_mmal", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VC1, - .pix_fmt = AV_PIX_FMT_MMAL, -}; - static const AVCodecHWConfigInternal *mmal_hw_configs[] = { HW_CONFIG_INTERNAL(MMAL), NULL diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c index ace2ec16d5c9b..6b4fc5e36e961 100644 --- a/libavcodec/qsvdec_h2645.c +++ b/libavcodec/qsvdec_h2645.c @@ -180,15 +180,6 @@ static void qsv_decode_flush(AVCodecContext *avctx) #define OFFSET(x) offsetof(QSVH2645Context, x) #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM -#if CONFIG_HEVC_QSV_HWACCEL -AVHWAccel ff_hevc_qsv_hwaccel = { - .name = "hevc_qsv", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HEVC, - .pix_fmt = AV_PIX_FMT_QSV, -}; -#endif - #if CONFIG_HEVC_QSV_DECODER static const AVOption hevc_options[] = { { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD }, @@ -231,15 +222,6 @@ AVCodec ff_hevc_qsv_decoder = { }; #endif -#if CONFIG_H264_QSV_HWACCEL -AVHWAccel ff_h264_qsv_hwaccel = { - .name = "h264_qsv", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .pix_fmt = AV_PIX_FMT_QSV, -}; -#endif - #if CONFIG_H264_QSV_DECODER static const AVOption options[] = { { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD }, diff --git a/libavcodec/qsvdec_other.c b/libavcodec/qsvdec_other.c index 21aa56492f316..f7691f95bf298 100644 --- a/libavcodec/qsvdec_other.c +++ b/libavcodec/qsvdec_other.c @@ -158,15 +158,6 @@ static const AVOption options[] = { { NULL }, }; -#if CONFIG_MPEG2_QSV_HWACCEL -AVHWAccel ff_mpeg2_qsv_hwaccel = { - .name = "mpeg2_qsv", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO, - .pix_fmt = AV_PIX_FMT_QSV, -}; -#endif - #if CONFIG_MPEG2_QSV_DECODER static const AVClass mpeg2_qsv_class = { .class_name = "mpeg2_qsv", @@ -194,15 +185,6 @@ AVCodec ff_mpeg2_qsv_decoder = { }; #endif -#if CONFIG_VC1_QSV_HWACCEL -AVHWAccel ff_vc1_qsv_hwaccel = { - .name = "vc1_qsv", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VC1, - .pix_fmt = AV_PIX_FMT_QSV, -}; -#endif - #if CONFIG_VC1_QSV_DECODER static const AVClass vc1_qsv_class = { .class_name = "vc1_qsv", @@ -230,15 +212,6 @@ AVCodec ff_vc1_qsv_decoder = { }; #endif -#if CONFIG_VP8_QSV_HWACCEL -AVHWAccel ff_vp8_qsv_hwaccel = { - .name = "vp8_qsv", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP8, - .pix_fmt = AV_PIX_FMT_QSV, -}; -#endif - #if CONFIG_VP8_QSV_DECODER static const AVClass vp8_qsv_class = { .class_name = "vp8_qsv", From 3a71bcc213f223428622ac3750fe1a923f2f3ab4 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Nov 2017 18:53:26 +0000 Subject: [PATCH 1127/2557] lavc: Mark all AVHWAccel structures as const --- doc/APIchanges | 3 ++ libavcodec/avcodec.h | 2 +- libavcodec/decode.c | 2 +- libavcodec/dxva2_h264.c | 6 +-- libavcodec/dxva2_hevc.c | 6 +-- libavcodec/dxva2_mpeg2.c | 6 +-- libavcodec/dxva2_vc1.c | 12 ++--- libavcodec/dxva2_vp9.c | 6 +-- libavcodec/hwaccels.h | 98 ++++++++++++++++++------------------- libavcodec/mpegvideo_xvmc.c | 4 +- libavcodec/nvdec_h264.c | 2 +- libavcodec/nvdec_hevc.c | 2 +- libavcodec/nvdec_mpeg12.c | 4 +- libavcodec/nvdec_mpeg4.c | 2 +- libavcodec/nvdec_vc1.c | 4 +- libavcodec/nvdec_vp9.c | 2 +- libavcodec/vaapi_h264.c | 2 +- libavcodec/vaapi_hevc.c | 2 +- libavcodec/vaapi_mpeg2.c | 2 +- libavcodec/vaapi_mpeg4.c | 4 +- libavcodec/vaapi_vc1.c | 4 +- libavcodec/vaapi_vp9.c | 2 +- libavcodec/vdpau_h264.c | 2 +- libavcodec/vdpau_hevc.c | 2 +- libavcodec/vdpau_mpeg12.c | 4 +- libavcodec/vdpau_mpeg4.c | 2 +- libavcodec/vdpau_vc1.c | 4 +- libavcodec/version.h | 2 +- libavcodec/videotoolbox.c | 12 ++--- 29 files changed, 104 insertions(+), 101 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 457a76971bd45..44a740e51f456 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavc 58.6.100 - avcodec.h + Add const to AVCodecContext.hwaccel. + 2017-11-xx - xxxxxxx - lavc 58.5.100 - avcodec.h Deprecate user visibility of the AVHWAccel structure and the functions av_register_hwaccel() and av_hwaccel_next(). diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 1ae0344bb2e39..0972df0bde238 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2635,7 +2635,7 @@ typedef struct AVCodecContext { * - encoding: unused. * - decoding: Set by libavcodec */ - struct AVHWAccel *hwaccel; + const struct AVHWAccel *hwaccel; /** * Hardware accelerator context. diff --git a/libavcodec/decode.c b/libavcodec/decode.c index f2a23735ace7d..3f5b086f7e4fb 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1252,7 +1252,7 @@ static int hwaccel_init(AVCodecContext *avctx, return AVERROR(ENOMEM); } - avctx->hwaccel = (AVHWAccel*)hwaccel; + avctx->hwaccel = hwaccel; if (hwaccel->init) { err = hwaccel->init(avctx); if (err < 0) { diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c index ee35b20e829ea..a4278c80b5258 100644 --- a/libavcodec/dxva2_h264.c +++ b/libavcodec/dxva2_h264.c @@ -518,7 +518,7 @@ static int dxva2_h264_end_frame(AVCodecContext *avctx) } #if CONFIG_H264_DXVA2_HWACCEL -AVHWAccel ff_h264_dxva2_hwaccel = { +const AVHWAccel ff_h264_dxva2_hwaccel = { .name = "h264_dxva2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, @@ -535,7 +535,7 @@ AVHWAccel ff_h264_dxva2_hwaccel = { #endif #if CONFIG_H264_D3D11VA_HWACCEL -AVHWAccel ff_h264_d3d11va_hwaccel = { +const AVHWAccel ff_h264_d3d11va_hwaccel = { .name = "h264_d3d11va", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, @@ -552,7 +552,7 @@ AVHWAccel ff_h264_d3d11va_hwaccel = { #endif #if CONFIG_H264_D3D11VA2_HWACCEL -AVHWAccel ff_h264_d3d11va2_hwaccel = { +const AVHWAccel ff_h264_d3d11va2_hwaccel = { .name = "h264_d3d11va2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c index 542afc383a6cf..0ae07d304f1b9 100644 --- a/libavcodec/dxva2_hevc.c +++ b/libavcodec/dxva2_hevc.c @@ -422,7 +422,7 @@ static int dxva2_hevc_end_frame(AVCodecContext *avctx) } #if CONFIG_HEVC_DXVA2_HWACCEL -AVHWAccel ff_hevc_dxva2_hwaccel = { +const AVHWAccel ff_hevc_dxva2_hwaccel = { .name = "hevc_dxva2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, @@ -439,7 +439,7 @@ AVHWAccel ff_hevc_dxva2_hwaccel = { #endif #if CONFIG_HEVC_D3D11VA_HWACCEL -AVHWAccel ff_hevc_d3d11va_hwaccel = { +const AVHWAccel ff_hevc_d3d11va_hwaccel = { .name = "hevc_d3d11va", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, @@ -456,7 +456,7 @@ AVHWAccel ff_hevc_d3d11va_hwaccel = { #endif #if CONFIG_HEVC_D3D11VA2_HWACCEL -AVHWAccel ff_hevc_d3d11va2_hwaccel = { +const AVHWAccel ff_hevc_d3d11va2_hwaccel = { .name = "hevc_d3d11va2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, diff --git a/libavcodec/dxva2_mpeg2.c b/libavcodec/dxva2_mpeg2.c index df5fe59a7d741..a57778b4271dd 100644 --- a/libavcodec/dxva2_mpeg2.c +++ b/libavcodec/dxva2_mpeg2.c @@ -317,7 +317,7 @@ static int dxva2_mpeg2_end_frame(AVCodecContext *avctx) } #if CONFIG_MPEG2_DXVA2_HWACCEL -AVHWAccel ff_mpeg2_dxva2_hwaccel = { +const AVHWAccel ff_mpeg2_dxva2_hwaccel = { .name = "mpeg2_dxva2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, @@ -334,7 +334,7 @@ AVHWAccel ff_mpeg2_dxva2_hwaccel = { #endif #if CONFIG_MPEG2_D3D11VA_HWACCEL -AVHWAccel ff_mpeg2_d3d11va_hwaccel = { +const AVHWAccel ff_mpeg2_d3d11va_hwaccel = { .name = "mpeg2_d3d11va", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, @@ -351,7 +351,7 @@ AVHWAccel ff_mpeg2_d3d11va_hwaccel = { #endif #if CONFIG_MPEG2_D3D11VA2_HWACCEL -AVHWAccel ff_mpeg2_d3d11va2_hwaccel = { +const AVHWAccel ff_mpeg2_d3d11va2_hwaccel = { .name = "mpeg2_d3d11va2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c index f21c5d5544f9c..f22c73cd1ebaf 100644 --- a/libavcodec/dxva2_vc1.c +++ b/libavcodec/dxva2_vc1.c @@ -378,7 +378,7 @@ static int dxva2_vc1_end_frame(AVCodecContext *avctx) } #if CONFIG_WMV3_DXVA2_HWACCEL -AVHWAccel ff_wmv3_dxva2_hwaccel = { +const AVHWAccel ff_wmv3_dxva2_hwaccel = { .name = "wmv3_dxva2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, @@ -395,7 +395,7 @@ AVHWAccel ff_wmv3_dxva2_hwaccel = { #endif #if CONFIG_VC1_DXVA2_HWACCEL -AVHWAccel ff_vc1_dxva2_hwaccel = { +const AVHWAccel ff_vc1_dxva2_hwaccel = { .name = "vc1_dxva2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, @@ -412,7 +412,7 @@ AVHWAccel ff_vc1_dxva2_hwaccel = { #endif #if CONFIG_WMV3_D3D11VA_HWACCEL -AVHWAccel ff_wmv3_d3d11va_hwaccel = { +const AVHWAccel ff_wmv3_d3d11va_hwaccel = { .name = "wmv3_d3d11va", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, @@ -429,7 +429,7 @@ AVHWAccel ff_wmv3_d3d11va_hwaccel = { #endif #if CONFIG_WMV3_D3D11VA2_HWACCEL -AVHWAccel ff_wmv3_d3d11va2_hwaccel = { +const AVHWAccel ff_wmv3_d3d11va2_hwaccel = { .name = "wmv3_d3d11va2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, @@ -446,7 +446,7 @@ AVHWAccel ff_wmv3_d3d11va2_hwaccel = { #endif #if CONFIG_VC1_D3D11VA_HWACCEL -AVHWAccel ff_vc1_d3d11va_hwaccel = { +const AVHWAccel ff_vc1_d3d11va_hwaccel = { .name = "vc1_d3d11va", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, @@ -463,7 +463,7 @@ AVHWAccel ff_vc1_d3d11va_hwaccel = { #endif #if CONFIG_VC1_D3D11VA2_HWACCEL -AVHWAccel ff_vc1_d3d11va2_hwaccel = { +const AVHWAccel ff_vc1_d3d11va2_hwaccel = { .name = "vc1_d3d11va2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, diff --git a/libavcodec/dxva2_vp9.c b/libavcodec/dxva2_vp9.c index a2e55f573644c..5a5b226422808 100644 --- a/libavcodec/dxva2_vp9.c +++ b/libavcodec/dxva2_vp9.c @@ -309,7 +309,7 @@ static int dxva2_vp9_end_frame(AVCodecContext *avctx) } #if CONFIG_VP9_DXVA2_HWACCEL -AVHWAccel ff_vp9_dxva2_hwaccel = { +const AVHWAccel ff_vp9_dxva2_hwaccel = { .name = "vp9_dxva2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VP9, @@ -326,7 +326,7 @@ AVHWAccel ff_vp9_dxva2_hwaccel = { #endif #if CONFIG_VP9_D3D11VA_HWACCEL -AVHWAccel ff_vp9_d3d11va_hwaccel = { +const AVHWAccel ff_vp9_d3d11va_hwaccel = { .name = "vp9_d3d11va", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VP9, @@ -343,7 +343,7 @@ AVHWAccel ff_vp9_d3d11va_hwaccel = { #endif #if CONFIG_VP9_D3D11VA2_HWACCEL -AVHWAccel ff_vp9_d3d11va2_hwaccel = { +const AVHWAccel ff_vp9_d3d11va2_hwaccel = { .name = "vp9_d3d11va2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VP9, diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h index 9a3008a92ca18..8a3c29e43597a 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -21,54 +21,54 @@ #include "avcodec.h" -extern AVHWAccel ff_h263_vaapi_hwaccel; -extern AVHWAccel ff_h263_videotoolbox_hwaccel; -extern AVHWAccel ff_h264_d3d11va_hwaccel; -extern AVHWAccel ff_h264_d3d11va2_hwaccel; -extern AVHWAccel ff_h264_dxva2_hwaccel; -extern AVHWAccel ff_h264_nvdec_hwaccel; -extern AVHWAccel ff_h264_vaapi_hwaccel; -extern AVHWAccel ff_h264_vdpau_hwaccel; -extern AVHWAccel ff_h264_videotoolbox_hwaccel; -extern AVHWAccel ff_hevc_d3d11va_hwaccel; -extern AVHWAccel ff_hevc_d3d11va2_hwaccel; -extern AVHWAccel ff_hevc_dxva2_hwaccel; -extern AVHWAccel ff_hevc_nvdec_hwaccel; -extern AVHWAccel ff_hevc_vaapi_hwaccel; -extern AVHWAccel ff_hevc_vdpau_hwaccel; -extern AVHWAccel ff_hevc_videotoolbox_hwaccel; -extern AVHWAccel ff_mpeg1_nvdec_hwaccel; -extern AVHWAccel ff_mpeg1_vdpau_hwaccel; -extern AVHWAccel ff_mpeg1_videotoolbox_hwaccel; -extern AVHWAccel ff_mpeg1_xvmc_hwaccel; -extern AVHWAccel ff_mpeg2_d3d11va_hwaccel; -extern AVHWAccel ff_mpeg2_d3d11va2_hwaccel; -extern AVHWAccel ff_mpeg2_nvdec_hwaccel; -extern AVHWAccel ff_mpeg2_dxva2_hwaccel; -extern AVHWAccel ff_mpeg2_vaapi_hwaccel; -extern AVHWAccel ff_mpeg2_vdpau_hwaccel; -extern AVHWAccel ff_mpeg2_videotoolbox_hwaccel; -extern AVHWAccel ff_mpeg2_xvmc_hwaccel; -extern AVHWAccel ff_mpeg4_nvdec_hwaccel; -extern AVHWAccel ff_mpeg4_vaapi_hwaccel; -extern AVHWAccel ff_mpeg4_vdpau_hwaccel; -extern AVHWAccel ff_mpeg4_videotoolbox_hwaccel; -extern AVHWAccel ff_vc1_d3d11va_hwaccel; -extern AVHWAccel ff_vc1_d3d11va2_hwaccel; -extern AVHWAccel ff_vc1_dxva2_hwaccel; -extern AVHWAccel ff_vc1_nvdec_hwaccel; -extern AVHWAccel ff_vc1_vaapi_hwaccel; -extern AVHWAccel ff_vc1_vdpau_hwaccel; -extern AVHWAccel ff_vp9_d3d11va_hwaccel; -extern AVHWAccel ff_vp9_d3d11va2_hwaccel; -extern AVHWAccel ff_vp9_dxva2_hwaccel; -extern AVHWAccel ff_vp9_nvdec_hwaccel; -extern AVHWAccel ff_vp9_vaapi_hwaccel; -extern AVHWAccel ff_wmv3_d3d11va_hwaccel; -extern AVHWAccel ff_wmv3_d3d11va2_hwaccel; -extern AVHWAccel ff_wmv3_dxva2_hwaccel; -extern AVHWAccel ff_wmv3_nvdec_hwaccel; -extern AVHWAccel ff_wmv3_vaapi_hwaccel; -extern AVHWAccel ff_wmv3_vdpau_hwaccel; +extern const AVHWAccel ff_h263_vaapi_hwaccel; +extern const AVHWAccel ff_h263_videotoolbox_hwaccel; +extern const AVHWAccel ff_h264_d3d11va_hwaccel; +extern const AVHWAccel ff_h264_d3d11va2_hwaccel; +extern const AVHWAccel ff_h264_dxva2_hwaccel; +extern const AVHWAccel ff_h264_nvdec_hwaccel; +extern const AVHWAccel ff_h264_vaapi_hwaccel; +extern const AVHWAccel ff_h264_vdpau_hwaccel; +extern const AVHWAccel ff_h264_videotoolbox_hwaccel; +extern const AVHWAccel ff_hevc_d3d11va_hwaccel; +extern const AVHWAccel ff_hevc_d3d11va2_hwaccel; +extern const AVHWAccel ff_hevc_dxva2_hwaccel; +extern const AVHWAccel ff_hevc_nvdec_hwaccel; +extern const AVHWAccel ff_hevc_vaapi_hwaccel; +extern const AVHWAccel ff_hevc_vdpau_hwaccel; +extern const AVHWAccel ff_hevc_videotoolbox_hwaccel; +extern const AVHWAccel ff_mpeg1_nvdec_hwaccel; +extern const AVHWAccel ff_mpeg1_vdpau_hwaccel; +extern const AVHWAccel ff_mpeg1_videotoolbox_hwaccel; +extern const AVHWAccel ff_mpeg1_xvmc_hwaccel; +extern const AVHWAccel ff_mpeg2_d3d11va_hwaccel; +extern const AVHWAccel ff_mpeg2_d3d11va2_hwaccel; +extern const AVHWAccel ff_mpeg2_nvdec_hwaccel; +extern const AVHWAccel ff_mpeg2_dxva2_hwaccel; +extern const AVHWAccel ff_mpeg2_vaapi_hwaccel; +extern const AVHWAccel ff_mpeg2_vdpau_hwaccel; +extern const AVHWAccel ff_mpeg2_videotoolbox_hwaccel; +extern const AVHWAccel ff_mpeg2_xvmc_hwaccel; +extern const AVHWAccel ff_mpeg4_nvdec_hwaccel; +extern const AVHWAccel ff_mpeg4_vaapi_hwaccel; +extern const AVHWAccel ff_mpeg4_vdpau_hwaccel; +extern const AVHWAccel ff_mpeg4_videotoolbox_hwaccel; +extern const AVHWAccel ff_vc1_d3d11va_hwaccel; +extern const AVHWAccel ff_vc1_d3d11va2_hwaccel; +extern const AVHWAccel ff_vc1_dxva2_hwaccel; +extern const AVHWAccel ff_vc1_nvdec_hwaccel; +extern const AVHWAccel ff_vc1_vaapi_hwaccel; +extern const AVHWAccel ff_vc1_vdpau_hwaccel; +extern const AVHWAccel ff_vp9_d3d11va_hwaccel; +extern const AVHWAccel ff_vp9_d3d11va2_hwaccel; +extern const AVHWAccel ff_vp9_dxva2_hwaccel; +extern const AVHWAccel ff_vp9_nvdec_hwaccel; +extern const AVHWAccel ff_vp9_vaapi_hwaccel; +extern const AVHWAccel ff_wmv3_d3d11va_hwaccel; +extern const AVHWAccel ff_wmv3_d3d11va2_hwaccel; +extern const AVHWAccel ff_wmv3_dxva2_hwaccel; +extern const AVHWAccel ff_wmv3_nvdec_hwaccel; +extern const AVHWAccel ff_wmv3_vaapi_hwaccel; +extern const AVHWAccel ff_wmv3_vdpau_hwaccel; #endif /* AVCODEC_HWACCELS_H */ diff --git a/libavcodec/mpegvideo_xvmc.c b/libavcodec/mpegvideo_xvmc.c index 519a4481614cf..f06583768c42f 100644 --- a/libavcodec/mpegvideo_xvmc.c +++ b/libavcodec/mpegvideo_xvmc.c @@ -348,7 +348,7 @@ static void ff_xvmc_decode_mb(struct MpegEncContext *s) } #if CONFIG_MPEG1_XVMC_HWACCEL -AVHWAccel ff_mpeg1_xvmc_hwaccel = { +const AVHWAccel ff_mpeg1_xvmc_hwaccel = { .name = "mpeg1_xvmc", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG1VIDEO, @@ -362,7 +362,7 @@ AVHWAccel ff_mpeg1_xvmc_hwaccel = { #endif #if CONFIG_MPEG2_XVMC_HWACCEL -AVHWAccel ff_mpeg2_xvmc_hwaccel = { +const AVHWAccel ff_mpeg2_xvmc_hwaccel = { .name = "mpeg2_xvmc", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, diff --git a/libavcodec/nvdec_h264.c b/libavcodec/nvdec_h264.c index b0e756c7344b2..35f54f2ed5f2a 100644 --- a/libavcodec/nvdec_h264.c +++ b/libavcodec/nvdec_h264.c @@ -163,7 +163,7 @@ static int nvdec_h264_frame_params(AVCodecContext *avctx, return ff_nvdec_frame_params(avctx, hw_frames_ctx, sps->ref_frame_count + sps->num_reorder_frames); } -AVHWAccel ff_h264_nvdec_hwaccel = { +const AVHWAccel ff_h264_nvdec_hwaccel = { .name = "h264_nvdec", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, diff --git a/libavcodec/nvdec_hevc.c b/libavcodec/nvdec_hevc.c index f02a7a15feb96..58f3fa9b45adb 100644 --- a/libavcodec/nvdec_hevc.c +++ b/libavcodec/nvdec_hevc.c @@ -266,7 +266,7 @@ static int nvdec_hevc_frame_params(AVCodecContext *avctx, return ff_nvdec_frame_params(avctx, hw_frames_ctx, sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering + 1); } -AVHWAccel ff_hevc_nvdec_hwaccel = { +const AVHWAccel ff_hevc_nvdec_hwaccel = { .name = "hevc_nvdec", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, diff --git a/libavcodec/nvdec_mpeg12.c b/libavcodec/nvdec_mpeg12.c index e29d085a79445..7293d50555480 100644 --- a/libavcodec/nvdec_mpeg12.c +++ b/libavcodec/nvdec_mpeg12.c @@ -91,7 +91,7 @@ static int nvdec_mpeg12_frame_params(AVCodecContext *avctx, } #if CONFIG_MPEG2_NVDEC_HWACCEL -AVHWAccel ff_mpeg2_nvdec_hwaccel = { +const AVHWAccel ff_mpeg2_nvdec_hwaccel = { .name = "mpeg2_nvdec", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, @@ -107,7 +107,7 @@ AVHWAccel ff_mpeg2_nvdec_hwaccel = { #endif #if CONFIG_MPEG1_NVDEC_HWACCEL -AVHWAccel ff_mpeg1_nvdec_hwaccel = { +const AVHWAccel ff_mpeg1_nvdec_hwaccel = { .name = "mpeg1_nvdec", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG1VIDEO, diff --git a/libavcodec/nvdec_mpeg4.c b/libavcodec/nvdec_mpeg4.c index a0f9280ea22e6..907af1391a929 100644 --- a/libavcodec/nvdec_mpeg4.c +++ b/libavcodec/nvdec_mpeg4.c @@ -106,7 +106,7 @@ static int nvdec_mpeg4_frame_params(AVCodecContext *avctx, return ff_nvdec_frame_params(avctx, hw_frames_ctx, 2); } -AVHWAccel ff_mpeg4_nvdec_hwaccel = { +const AVHWAccel ff_mpeg4_nvdec_hwaccel = { .name = "mpeg4_nvdec", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG4, diff --git a/libavcodec/nvdec_vc1.c b/libavcodec/nvdec_vc1.c index c04b153a8615d..7257692d66a35 100644 --- a/libavcodec/nvdec_vc1.c +++ b/libavcodec/nvdec_vc1.c @@ -110,7 +110,7 @@ static int nvdec_vc1_frame_params(AVCodecContext *avctx, return ff_nvdec_frame_params(avctx, hw_frames_ctx, 2); } -AVHWAccel ff_vc1_nvdec_hwaccel = { +const AVHWAccel ff_vc1_nvdec_hwaccel = { .name = "vc1_nvdec", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, @@ -125,7 +125,7 @@ AVHWAccel ff_vc1_nvdec_hwaccel = { }; #if CONFIG_WMV3_NVDEC_HWACCEL -AVHWAccel ff_wmv3_nvdec_hwaccel = { +const AVHWAccel ff_wmv3_nvdec_hwaccel = { .name = "wmv3_nvdec", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, diff --git a/libavcodec/nvdec_vp9.c b/libavcodec/nvdec_vp9.c index ed06d9141603e..3b665a9bc701c 100644 --- a/libavcodec/nvdec_vp9.c +++ b/libavcodec/nvdec_vp9.c @@ -169,7 +169,7 @@ static int nvdec_vp9_frame_params(AVCodecContext *avctx, return ff_nvdec_frame_params(avctx, hw_frames_ctx, 8); } -AVHWAccel ff_vp9_nvdec_hwaccel = { +const AVHWAccel ff_vp9_nvdec_hwaccel = { .name = "vp9_nvdec", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VP9, diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c index c7f9d7bcb416f..5854587a255a7 100644 --- a/libavcodec/vaapi_h264.c +++ b/libavcodec/vaapi_h264.c @@ -388,7 +388,7 @@ static int vaapi_h264_decode_slice(AVCodecContext *avctx, return 0; } -AVHWAccel ff_h264_vaapi_hwaccel = { +const AVHWAccel ff_h264_vaapi_hwaccel = { .name = "h264_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c index 718ccc92a2ea1..19aabcdb5218a 100644 --- a/libavcodec/vaapi_hevc.c +++ b/libavcodec/vaapi_hevc.c @@ -423,7 +423,7 @@ static int vaapi_hevc_decode_slice(AVCodecContext *avctx, return 0; } -AVHWAccel ff_hevc_vaapi_hwaccel = { +const AVHWAccel ff_hevc_vaapi_hwaccel = { .name = "hevc_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, diff --git a/libavcodec/vaapi_mpeg2.c b/libavcodec/vaapi_mpeg2.c index fd5be8d8aefaf..aaed434c88372 100644 --- a/libavcodec/vaapi_mpeg2.c +++ b/libavcodec/vaapi_mpeg2.c @@ -172,7 +172,7 @@ static int vaapi_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer return 0; } -AVHWAccel ff_mpeg2_vaapi_hwaccel = { +const AVHWAccel ff_mpeg2_vaapi_hwaccel = { .name = "mpeg2_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, diff --git a/libavcodec/vaapi_mpeg4.c b/libavcodec/vaapi_mpeg4.c index 3fe029186e8fd..11860ff747428 100644 --- a/libavcodec/vaapi_mpeg4.c +++ b/libavcodec/vaapi_mpeg4.c @@ -178,7 +178,7 @@ static int vaapi_mpeg4_decode_slice(AVCodecContext *avctx, const uint8_t *buffer } #if CONFIG_MPEG4_VAAPI_HWACCEL -AVHWAccel ff_mpeg4_vaapi_hwaccel = { +const AVHWAccel ff_mpeg4_vaapi_hwaccel = { .name = "mpeg4_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG4, @@ -196,7 +196,7 @@ AVHWAccel ff_mpeg4_vaapi_hwaccel = { #endif #if CONFIG_H263_VAAPI_HWACCEL -AVHWAccel ff_h263_vaapi_hwaccel = { +const AVHWAccel ff_h263_vaapi_hwaccel = { .name = "h263_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H263, diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c index 49675744cdbc2..525376790ec3a 100644 --- a/libavcodec/vaapi_vc1.c +++ b/libavcodec/vaapi_vc1.c @@ -388,7 +388,7 @@ static int vaapi_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, } #if CONFIG_WMV3_VAAPI_HWACCEL -AVHWAccel ff_wmv3_vaapi_hwaccel = { +const AVHWAccel ff_wmv3_vaapi_hwaccel = { .name = "wmv3_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, @@ -405,7 +405,7 @@ AVHWAccel ff_wmv3_vaapi_hwaccel = { }; #endif -AVHWAccel ff_vc1_vaapi_hwaccel = { +const AVHWAccel ff_vc1_vaapi_hwaccel = { .name = "vc1_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, diff --git a/libavcodec/vaapi_vp9.c b/libavcodec/vaapi_vp9.c index f295dc9ebb521..f384ba7873ad5 100644 --- a/libavcodec/vaapi_vp9.c +++ b/libavcodec/vaapi_vp9.c @@ -168,7 +168,7 @@ static int vaapi_vp9_decode_slice(AVCodecContext *avctx, return 0; } -AVHWAccel ff_vp9_vaapi_hwaccel = { +const AVHWAccel ff_vp9_vaapi_hwaccel = { .name = "vp9_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VP9, diff --git a/libavcodec/vdpau_h264.c b/libavcodec/vdpau_h264.c index 70f83d76f50a5..2a260f76abae4 100644 --- a/libavcodec/vdpau_h264.c +++ b/libavcodec/vdpau_h264.c @@ -262,7 +262,7 @@ static int vdpau_h264_init(AVCodecContext *avctx) return ff_vdpau_common_init(avctx, profile, level); } -AVHWAccel ff_h264_vdpau_hwaccel = { +const AVHWAccel ff_h264_vdpau_hwaccel = { .name = "h264_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, diff --git a/libavcodec/vdpau_hevc.c b/libavcodec/vdpau_hevc.c index 70e76cfcaa98e..421135bce25bf 100644 --- a/libavcodec/vdpau_hevc.c +++ b/libavcodec/vdpau_hevc.c @@ -413,7 +413,7 @@ static int vdpau_hevc_init(AVCodecContext *avctx) return ff_vdpau_common_init(avctx, profile, level); } -AVHWAccel ff_hevc_vdpau_hwaccel = { +const AVHWAccel ff_hevc_vdpau_hwaccel = { .name = "hevc_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, diff --git a/libavcodec/vdpau_mpeg12.c b/libavcodec/vdpau_mpeg12.c index 71fe889abf645..d286e7e57da2d 100644 --- a/libavcodec/vdpau_mpeg12.c +++ b/libavcodec/vdpau_mpeg12.c @@ -103,7 +103,7 @@ static int vdpau_mpeg1_init(AVCodecContext *avctx) VDP_DECODER_LEVEL_MPEG1_NA); } -AVHWAccel ff_mpeg1_vdpau_hwaccel = { +const AVHWAccel ff_mpeg1_vdpau_hwaccel = { .name = "mpeg1_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG1VIDEO, @@ -138,7 +138,7 @@ static int vdpau_mpeg2_init(AVCodecContext *avctx) return ff_vdpau_common_init(avctx, profile, VDP_DECODER_LEVEL_MPEG2_HL); } -AVHWAccel ff_mpeg2_vdpau_hwaccel = { +const AVHWAccel ff_mpeg2_vdpau_hwaccel = { .name = "mpeg2_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, diff --git a/libavcodec/vdpau_mpeg4.c b/libavcodec/vdpau_mpeg4.c index 653ef7e7e73f3..96f83026a8e4d 100644 --- a/libavcodec/vdpau_mpeg4.c +++ b/libavcodec/vdpau_mpeg4.c @@ -110,7 +110,7 @@ static int vdpau_mpeg4_init(AVCodecContext *avctx) return ff_vdpau_common_init(avctx, profile, avctx->level); } -AVHWAccel ff_mpeg4_vdpau_hwaccel = { +const AVHWAccel ff_mpeg4_vdpau_hwaccel = { .name = "mpeg4_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG4, diff --git a/libavcodec/vdpau_vc1.c b/libavcodec/vdpau_vc1.c index 73d83f65777ce..671baf96b4d7e 100644 --- a/libavcodec/vdpau_vc1.c +++ b/libavcodec/vdpau_vc1.c @@ -136,7 +136,7 @@ static int vdpau_vc1_init(AVCodecContext *avctx) } #if CONFIG_WMV3_VDPAU_HWACCEL -AVHWAccel ff_wmv3_vdpau_hwaccel = { +const AVHWAccel ff_wmv3_vdpau_hwaccel = { .name = "wm3_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, @@ -153,7 +153,7 @@ AVHWAccel ff_wmv3_vdpau_hwaccel = { }; #endif -AVHWAccel ff_vc1_vdpau_hwaccel = { +const AVHWAccel ff_vc1_vdpau_hwaccel = { .name = "vc1_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, diff --git a/libavcodec/version.h b/libavcodec/version.h index ddab7c47a7804..ba46721fb5880 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 5 +#define LIBAVCODEC_VERSION_MINOR 6 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index d29607363c098..c275e0111ec8e 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -1028,7 +1028,7 @@ static int videotoolbox_frame_params(AVCodecContext *avctx, return 0; } -AVHWAccel ff_h263_videotoolbox_hwaccel = { +const AVHWAccel ff_h263_videotoolbox_hwaccel = { .name = "h263_videotoolbox", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H263, @@ -1043,7 +1043,7 @@ AVHWAccel ff_h263_videotoolbox_hwaccel = { .priv_data_size = sizeof(VTContext), }; -AVHWAccel ff_hevc_videotoolbox_hwaccel = { +const AVHWAccel ff_hevc_videotoolbox_hwaccel = { .name = "hevc_videotoolbox", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, @@ -1059,7 +1059,7 @@ AVHWAccel ff_hevc_videotoolbox_hwaccel = { .priv_data_size = sizeof(VTContext), }; -AVHWAccel ff_h264_videotoolbox_hwaccel = { +const AVHWAccel ff_h264_videotoolbox_hwaccel = { .name = "h264_videotoolbox", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, @@ -1075,7 +1075,7 @@ AVHWAccel ff_h264_videotoolbox_hwaccel = { .priv_data_size = sizeof(VTContext), }; -AVHWAccel ff_mpeg1_videotoolbox_hwaccel = { +const AVHWAccel ff_mpeg1_videotoolbox_hwaccel = { .name = "mpeg1_videotoolbox", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG1VIDEO, @@ -1090,7 +1090,7 @@ AVHWAccel ff_mpeg1_videotoolbox_hwaccel = { .priv_data_size = sizeof(VTContext), }; -AVHWAccel ff_mpeg2_videotoolbox_hwaccel = { +const AVHWAccel ff_mpeg2_videotoolbox_hwaccel = { .name = "mpeg2_videotoolbox", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, @@ -1105,7 +1105,7 @@ AVHWAccel ff_mpeg2_videotoolbox_hwaccel = { .priv_data_size = sizeof(VTContext), }; -AVHWAccel ff_mpeg4_videotoolbox_hwaccel = { +const AVHWAccel ff_mpeg4_videotoolbox_hwaccel = { .name = "mpeg4_videotoolbox", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG4, From b0cd14fb1dab4b044f7fe6b53ac635409849de77 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:47 +0100 Subject: [PATCH 1128/2557] ffmpeg: Use codec hardware config to configure hwaccels Removes specific support for all hwaccels supported by the generic code (DXVA2, D3D11VA, NVDEC, VAAPI and VDPAU). --- fftools/ffmpeg.c | 77 ++++++++++---- fftools/ffmpeg.h | 9 +- fftools/ffmpeg_hw.c | 244 ++++++++++++++++++++++++++++++------------- fftools/ffmpeg_opt.c | 54 +++++----- 4 files changed, 251 insertions(+), 133 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 0c16e75ab040b..6aff3366c5617 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2792,45 +2792,77 @@ static void print_sdp(void) av_freep(&avc); } -static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt, enum HWAccelID selected_hwaccel_id) -{ - int i; - for (i = 0; hwaccels[i].name; i++) - if (hwaccels[i].pix_fmt == pix_fmt && - (!selected_hwaccel_id || selected_hwaccel_id == HWACCEL_AUTO || hwaccels[i].id == selected_hwaccel_id)) - return &hwaccels[i]; - return NULL; -} - static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) { InputStream *ist = s->opaque; const enum AVPixelFormat *p; int ret; - for (p = pix_fmts; *p != -1; p++) { + for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p); - const HWAccel *hwaccel; + const AVCodecHWConfig *config = NULL; + int i; if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) break; - hwaccel = get_hwaccel(*p, ist->hwaccel_id); - if (!hwaccel || - (ist->active_hwaccel_id && ist->active_hwaccel_id != hwaccel->id) || - (ist->hwaccel_id != HWACCEL_AUTO && ist->hwaccel_id != hwaccel->id)) - continue; + if (ist->hwaccel_id == HWACCEL_GENERIC || + ist->hwaccel_id == HWACCEL_AUTO) { + for (i = 0;; i++) { + config = avcodec_get_hw_config(s->codec, i); + if (!config) + break; + if (!(config->methods & + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) + continue; + if (config->pix_fmt == *p) + break; + } + } + if (config) { + if (config->device_type != ist->hwaccel_device_type) { + // Different hwaccel offered, ignore. + continue; + } - ret = hwaccel->init(s); - if (ret < 0) { - if (ist->hwaccel_id == hwaccel->id) { + ret = hwaccel_decode_init(s); + if (ret < 0) { + if (ist->hwaccel_id == HWACCEL_GENERIC) { + av_log(NULL, AV_LOG_FATAL, + "%s hwaccel requested for input stream #%d:%d, " + "but cannot be initialized.\n", + av_hwdevice_get_type_name(config->device_type), + ist->file_index, ist->st->index); + return AV_PIX_FMT_NONE; + } + continue; + } + } else { + const HWAccel *hwaccel = NULL; + int i; + for (i = 0; hwaccels[i].name; i++) { + if (hwaccels[i].pix_fmt == *p) { + hwaccel = &hwaccels[i]; + break; + } + } + if (!hwaccel) { + // No hwaccel supporting this pixfmt. + continue; + } + if (hwaccel->id != ist->hwaccel_id) { + // Does not match requested hwaccel. + continue; + } + + ret = hwaccel->init(s); + if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "%s hwaccel requested for input stream #%d:%d, " "but cannot be initialized.\n", hwaccel->name, ist->file_index, ist->st->index); return AV_PIX_FMT_NONE; } - continue; } if (ist->hw_frames_ctx) { @@ -2839,8 +2871,7 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat return AV_PIX_FMT_NONE; } - ist->active_hwaccel_id = hwaccel->id; - ist->hwaccel_pix_fmt = *p; + ist->hwaccel_pix_fmt = *p; break; } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index e0977e1bf16f2..4e73d59082e39 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -61,14 +61,10 @@ enum HWAccelID { HWACCEL_NONE = 0, HWACCEL_AUTO, - HWACCEL_VDPAU, - HWACCEL_DXVA2, + HWACCEL_GENERIC, HWACCEL_VIDEOTOOLBOX, HWACCEL_QSV, - HWACCEL_VAAPI, HWACCEL_CUVID, - HWACCEL_D3D11VA, - HWACCEL_NVDEC, }; typedef struct HWAccel { @@ -76,7 +72,6 @@ typedef struct HWAccel { int (*init)(AVCodecContext *s); enum HWAccelID id; enum AVPixelFormat pix_fmt; - enum AVHWDeviceType device_type; } HWAccel; typedef struct HWDevice { @@ -370,11 +365,11 @@ typedef struct InputStream { /* hwaccel options */ enum HWAccelID hwaccel_id; + enum AVHWDeviceType hwaccel_device_type; char *hwaccel_device; enum AVPixelFormat hwaccel_output_format; /* hwaccel context */ - enum HWAccelID active_hwaccel_id; void *hwaccel_ctx; void (*hwaccel_uninit)(AVCodecContext *s); int (*hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int flags); diff --git a/fftools/ffmpeg_hw.c b/fftools/ffmpeg_hw.c index a4d1cada591ed..2ec181385430b 100644 --- a/fftools/ffmpeg_hw.c +++ b/fftools/ffmpeg_hw.c @@ -64,6 +64,31 @@ static HWDevice *hw_device_add(void) return hw_devices[nb_hw_devices++]; } +static char *hw_device_default_name(enum AVHWDeviceType type) +{ + // Make an automatic name of the form "type%d". We arbitrarily + // limit at 1000 anonymous devices of the same type - there is + // probably something else very wrong if you get to this limit. + const char *type_name = av_hwdevice_get_type_name(type); + char *name; + size_t index_pos; + int index, index_limit = 1000; + index_pos = strlen(type_name); + name = av_malloc(index_pos + 4); + if (!name) + return NULL; + for (index = 0; index < index_limit; index++) { + snprintf(name, index_pos + 4, "%s%d", type_name, index); + if (!hw_device_get_by_name(name)) + break; + } + if (index >= index_limit) { + av_freep(&name); + return NULL; + } + return name; +} + int hw_device_init_from_string(const char *arg, HWDevice **dev_out) { // "type=name:device,key=value,key2=value2" @@ -111,27 +136,11 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out) p += 1 + k; } else { - // Give the device an automatic name of the form "type%d". - // We arbitrarily limit at 1000 anonymous devices of the same - // type - there is probably something else very wrong if you - // get to this limit. - size_t index_pos; - int index, index_limit = 1000; - index_pos = strlen(type_name); - name = av_malloc(index_pos + 4); + name = hw_device_default_name(type); if (!name) { err = AVERROR(ENOMEM); goto fail; } - for (index = 0; index < index_limit; index++) { - snprintf(name, index_pos + 4, "%s%d", type_name, index); - if (!hw_device_get_by_name(name)) - break; - } - if (index >= index_limit) { - errmsg = "too many devices"; - goto invalid; - } } if (!*p) { @@ -214,6 +223,49 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out) goto done; } +static int hw_device_init_from_type(enum AVHWDeviceType type, + const char *device, + HWDevice **dev_out) +{ + AVBufferRef *device_ref = NULL; + HWDevice *dev; + char *name; + int err; + + name = hw_device_default_name(type); + if (!name) { + err = AVERROR(ENOMEM); + goto fail; + } + + err = av_hwdevice_ctx_create(&device_ref, type, device, NULL, 0); + if (err < 0) { + av_log(NULL, AV_LOG_ERROR, + "Device creation failed: %d.\n", err); + goto fail; + } + + dev = hw_device_add(); + if (!dev) { + err = AVERROR(ENOMEM); + goto fail; + } + + dev->name = name; + dev->type = type; + dev->device_ref = device_ref; + + if (dev_out) + *dev_out = dev; + + return 0; + +fail: + av_freep(&name); + av_buffer_unref(&device_ref); + return err; +} + void hw_device_free_all(void) { int i; @@ -226,80 +278,130 @@ void hw_device_free_all(void) nb_hw_devices = 0; } -static enum AVHWDeviceType hw_device_match_type_by_hwaccel(enum HWAccelID hwaccel_id) +static HWDevice *hw_device_match_by_codec(const AVCodec *codec) { + const AVCodecHWConfig *config; + HWDevice *dev; int i; - if (hwaccel_id == HWACCEL_NONE) - return AV_HWDEVICE_TYPE_NONE; - for (i = 0; hwaccels[i].name; i++) { - if (hwaccels[i].id == hwaccel_id) - return hwaccels[i].device_type; + for (i = 0;; i++) { + config = avcodec_get_hw_config(codec, i); + if (!config) + return NULL; + if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) + continue; + dev = hw_device_get_by_type(config->device_type); + if (dev) + return dev; } - return AV_HWDEVICE_TYPE_NONE; -} - -static enum AVHWDeviceType hw_device_match_type_in_name(const char *codec_name) -{ - const char *type_name; - enum AVHWDeviceType type; - for (type = av_hwdevice_iterate_types(AV_HWDEVICE_TYPE_NONE); - type != AV_HWDEVICE_TYPE_NONE; - type = av_hwdevice_iterate_types(type)) { - type_name = av_hwdevice_get_type_name(type); - if (strstr(codec_name, type_name)) - return type; - } - return AV_HWDEVICE_TYPE_NONE; } int hw_device_setup_for_decode(InputStream *ist) { + const AVCodecHWConfig *config; enum AVHWDeviceType type; - HWDevice *dev; - int err; + HWDevice *dev = NULL; + int err, auto_device = 0; if (ist->hwaccel_device) { dev = hw_device_get_by_name(ist->hwaccel_device); if (!dev) { - char *tmp; - type = hw_device_match_type_by_hwaccel(ist->hwaccel_id); - if (type == AV_HWDEVICE_TYPE_NONE) { - // No match - this isn't necessarily invalid, though, - // because an explicit device might not be needed or - // the hwaccel setup could be handled elsewhere. + if (ist->hwaccel_id == HWACCEL_AUTO) { + auto_device = 1; + } else if (ist->hwaccel_id == HWACCEL_GENERIC) { + type = ist->hwaccel_device_type; + err = hw_device_init_from_type(type, ist->hwaccel_device, + &dev); + } else { + // This will be dealt with by API-specific initialisation + // (using hwaccel_device), so nothing further needed here. return 0; } - tmp = av_asprintf("%s:%s", av_hwdevice_get_type_name(type), - ist->hwaccel_device); - if (!tmp) - return AVERROR(ENOMEM); - err = hw_device_init_from_string(tmp, &dev); - av_free(tmp); - if (err < 0) - return err; + } else { + if (ist->hwaccel_id == HWACCEL_AUTO) { + ist->hwaccel_device_type = dev->type; + } else if (ist->hwaccel_device_type != dev->type) { + av_log(ist->dec_ctx, AV_LOG_ERROR, "Invalid hwaccel device " + "specified for decoder: device %s of type %s is not " + "usable with hwaccel %s.\n", dev->name, + av_hwdevice_get_type_name(dev->type), + av_hwdevice_get_type_name(ist->hwaccel_device_type)); + return AVERROR(EINVAL); + } } } else { - if (ist->hwaccel_id != HWACCEL_NONE) - type = hw_device_match_type_by_hwaccel(ist->hwaccel_id); - else - type = hw_device_match_type_in_name(ist->dec->name); - if (type != AV_HWDEVICE_TYPE_NONE) { + if (ist->hwaccel_id == HWACCEL_AUTO) { + auto_device = 1; + } else if (ist->hwaccel_id == HWACCEL_GENERIC) { + type = ist->hwaccel_device_type; dev = hw_device_get_by_type(type); + if (!dev) + err = hw_device_init_from_type(type, NULL, &dev); + } else { + dev = hw_device_match_by_codec(ist->dec); if (!dev) { - hw_device_init_from_string(av_hwdevice_get_type_name(type), + // No device for this codec, but not using generic hwaccel + // and therefore may well not need one - ignore. + return 0; + } + } + } + + if (auto_device) { + int i; + if (!avcodec_get_hw_config(ist->dec, 0)) { + // Decoder does not support any hardware devices. + return 0; + } + for (i = 0; !dev; i++) { + config = avcodec_get_hw_config(ist->dec, i); + if (!config) + break; + type = config->device_type; + dev = hw_device_get_by_type(type); + if (dev) { + av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto " + "hwaccel type %s with existing device %s.\n", + av_hwdevice_get_type_name(type), dev->name); + } + } + for (i = 0; !dev; i++) { + config = avcodec_get_hw_config(ist->dec, i); + if (!config) + break; + type = config->device_type; + // Try to make a new device of this type. + err = hw_device_init_from_type(type, ist->hwaccel_device, &dev); + if (err < 0) { + // Can't make a device of this type. + continue; + } + if (ist->hwaccel_device) { + av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto " + "hwaccel type %s with new device created " + "from %s.\n", av_hwdevice_get_type_name(type), + ist->hwaccel_device); + } else { + av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto " + "hwaccel type %s with new default device.\n", + av_hwdevice_get_type_name(type)); } + } + if (dev) { + ist->hwaccel_device_type = type; } else { - // No device required. + av_log(ist->dec_ctx, AV_LOG_INFO, "Auto hwaccel " + "disabled: no device found.\n"); + ist->hwaccel_id = HWACCEL_NONE; return 0; } } if (!dev) { - av_log(ist->dec_ctx, AV_LOG_WARNING, "No device available " - "for decoder (device type %s for codec %s).\n", + av_log(ist->dec_ctx, AV_LOG_ERROR, "No device available " + "for decoder: device type %s needed for codec %s.\n", av_hwdevice_get_type_name(type), ist->dec->name); - return 0; + return err; } ist->dec_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); @@ -311,24 +413,16 @@ int hw_device_setup_for_decode(InputStream *ist) int hw_device_setup_for_encode(OutputStream *ost) { - enum AVHWDeviceType type; HWDevice *dev; - type = hw_device_match_type_in_name(ost->enc->name); - if (type != AV_HWDEVICE_TYPE_NONE) { - dev = hw_device_get_by_type(type); - if (!dev) { - av_log(ost->enc_ctx, AV_LOG_WARNING, "No device available " - "for encoder (device type %s for codec %s).\n", - av_hwdevice_get_type_name(type), ost->enc->name); - return 0; - } + dev = hw_device_match_by_codec(ost->enc); + if (dev) { ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); if (!ost->enc_ctx->hw_device_ctx) return AVERROR(ENOMEM); return 0; } else { - // No device required. + // No device required, or no device available. return 0; } } diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index f66f672c3c6be..9445a2dd11823 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -66,37 +66,14 @@ } const HWAccel hwaccels[] = { -#if HAVE_VDPAU_X11 - { "vdpau", hwaccel_decode_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU, - AV_HWDEVICE_TYPE_VDPAU }, -#endif -#if CONFIG_D3D11VA - { "d3d11va", hwaccel_decode_init, HWACCEL_D3D11VA, AV_PIX_FMT_D3D11, - AV_HWDEVICE_TYPE_D3D11VA }, -#endif -#if CONFIG_DXVA2 - { "dxva2", hwaccel_decode_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD, - AV_HWDEVICE_TYPE_DXVA2 }, -#endif #if CONFIG_VIDEOTOOLBOX - { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX, - AV_HWDEVICE_TYPE_NONE }, + { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX }, #endif #if CONFIG_LIBMFX - { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV, - AV_HWDEVICE_TYPE_NONE }, -#endif -#if CONFIG_VAAPI - { "vaapi", hwaccel_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI, - AV_HWDEVICE_TYPE_VAAPI }, -#endif -#if CONFIG_NVDEC - { "nvdec", hwaccel_decode_init, HWACCEL_NVDEC, AV_PIX_FMT_CUDA, - AV_HWDEVICE_TYPE_CUDA }, + { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV }, #endif #if CONFIG_CUVID - { "cuvid", cuvid_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA, - AV_HWDEVICE_TYPE_NONE }, + { "cuvid", cuvid_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA }, #endif { 0 }, }; @@ -194,12 +171,15 @@ static void init_options(OptionsContext *o) static int show_hwaccels(void *optctx, const char *opt, const char *arg) { + enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE; int i; printf("Hardware acceleration methods:\n"); - for (i = 0; hwaccels[i].name; i++) { + while ((type = av_hwdevice_iterate_types(type)) != + AV_HWDEVICE_TYPE_NONE) + printf("%s\n", av_hwdevice_get_type_name(type)); + for (i = 0; hwaccels[i].name; i++) printf("%s\n", hwaccels[i].name); - } printf("\n"); return 0; } @@ -819,11 +799,16 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st); if (hwaccel) { + // The NVDEC hwaccels use a CUDA device, so remap the name here. + if (!strcmp(hwaccel, "nvdec")) + hwaccel = "cuda"; + if (!strcmp(hwaccel, "none")) ist->hwaccel_id = HWACCEL_NONE; else if (!strcmp(hwaccel, "auto")) ist->hwaccel_id = HWACCEL_AUTO; else { + enum AVHWDeviceType type; int i; for (i = 0; hwaccels[i].name; i++) { if (!strcmp(hwaccels[i].name, hwaccel)) { @@ -832,10 +817,23 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) } } + if (!ist->hwaccel_id) { + type = av_hwdevice_find_type_by_name(hwaccel); + if (type != AV_HWDEVICE_TYPE_NONE) { + ist->hwaccel_id = HWACCEL_GENERIC; + ist->hwaccel_device_type = type; + } + } + if (!ist->hwaccel_id) { av_log(NULL, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n", hwaccel); av_log(NULL, AV_LOG_FATAL, "Supported hwaccels: "); + type = AV_HWDEVICE_TYPE_NONE; + while ((type = av_hwdevice_iterate_types(type)) != + AV_HWDEVICE_TYPE_NONE) + av_log(NULL, AV_LOG_FATAL, "%s ", + av_hwdevice_get_type_name(type)); for (i = 0; hwaccels[i].name; i++) av_log(NULL, AV_LOG_FATAL, "%s ", hwaccels[i].name); av_log(NULL, AV_LOG_FATAL, "\n"); From efd0612fdcb7490ed371899f532d73ef8bb7cba0 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 9 Nov 2017 01:04:44 +0000 Subject: [PATCH 1129/2557] vaapi: Make the decode profile matching more explicit Also fixes a bug where it could attempt to decode with an unsupported codec if allow-profile-mismatch was set. --- libavcodec/vaapi_decode.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index d467bed874272..d36ef906a202d 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -287,8 +287,8 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, VAStatus vas; int err, i, j; const AVCodecDescriptor *codec_desc; - VAProfile profile, va_profile, *profile_list = NULL; - int profile_count, exact_match, alt_profile; + VAProfile *profile_list = NULL, matched_va_profile; + int profile_count, exact_match, matched_ff_profile; const AVPixFmtDescriptor *sw_desc, *desc; AVHWDeviceContext *device = (AVHWDeviceContext*)device_ref->data; @@ -317,7 +317,7 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, goto fail; } - profile = VAProfileNone; + matched_va_profile = VAProfileNone; exact_match = 0; for (i = 0; i < FF_ARRAY_ELEMS(vaapi_profile_map); i++) { @@ -326,23 +326,22 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, continue; if (avctx->profile == vaapi_profile_map[i].codec_profile) profile_match = 1; - profile = vaapi_profile_map[i].va_profile; for (j = 0; j < profile_count; j++) { - if (profile == profile_list[j]) { + if (vaapi_profile_map[i].va_profile == profile_list[j]) { exact_match = profile_match; break; } } if (j < profile_count) { + matched_va_profile = vaapi_profile_map[i].va_profile; + matched_ff_profile = vaapi_profile_map[i].codec_profile; if (exact_match) break; - alt_profile = vaapi_profile_map[i].codec_profile; - va_profile = vaapi_profile_map[i].va_profile; } } av_freep(&profile_list); - if (profile == VAProfileNone) { + if (matched_va_profile == VAProfileNone) { av_log(avctx, AV_LOG_ERROR, "No support for codec %s " "profile %d.\n", codec_desc->name, avctx->profile); err = AVERROR(ENOSYS); @@ -356,8 +355,7 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, codec_desc->name, avctx->profile); av_log(avctx, AV_LOG_WARNING, "Using possibly-" "incompatible profile %d instead.\n", - alt_profile); - profile = va_profile; + matched_ff_profile); } else { av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not " "supported for hardware decode.\n", @@ -367,7 +365,7 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, } } - vas = vaCreateConfig(hwctx->display, profile, + vas = vaCreateConfig(hwctx->display, matched_va_profile, VAEntrypointVLD, NULL, 0, va_config); if (vas != VA_STATUS_SUCCESS) { From 9f00fa536938130e3c7ad2640a61795770d419a1 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 18 Nov 2017 17:55:18 +0000 Subject: [PATCH 1130/2557] vp8: Add hwaccel hooks Also adds some extra fields to the main context structure that may be needed by a hwaccel decoder. The current behaviour of the WebP decoder is maintained by adding an additional field to the VP8 decoder private context to indicate that it is actually being used as WebP (no hwaccel is supported for that case). --- libavcodec/vp8.c | 206 +++++++++++++++++++++++++++++++--------------- libavcodec/vp8.h | 33 ++++++++ libavcodec/webp.c | 1 + 3 files changed, 172 insertions(+), 68 deletions(-) diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index 7841a9d964e72..31cd6a0d816bb 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -27,6 +27,7 @@ #include "libavutil/imgutils.h" #include "avcodec.h" +#include "hwaccel.h" #include "internal.h" #include "mathops.h" #include "rectangle.h" @@ -72,16 +73,30 @@ static int vp8_alloc_frame(VP8Context *s, VP8Frame *f, int ref) if ((ret = ff_thread_get_buffer(s->avctx, &f->tf, ref ? AV_GET_BUFFER_FLAG_REF : 0)) < 0) return ret; - if (!(f->seg_map = av_buffer_allocz(s->mb_width * s->mb_height))) { - ff_thread_release_buffer(s->avctx, &f->tf); - return AVERROR(ENOMEM); + if (!(f->seg_map = av_buffer_allocz(s->mb_width * s->mb_height))) + goto fail; + if (s->avctx->hwaccel) { + const AVHWAccel *hwaccel = s->avctx->hwaccel; + if (hwaccel->frame_priv_data_size) { + f->hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size); + if (!f->hwaccel_priv_buf) + goto fail; + f->hwaccel_picture_private = f->hwaccel_priv_buf->data; + } } return 0; + +fail: + av_buffer_unref(&f->seg_map); + ff_thread_release_buffer(s->avctx, &f->tf); + return AVERROR(ENOMEM); } static void vp8_release_frame(VP8Context *s, VP8Frame *f) { av_buffer_unref(&f->seg_map); + av_buffer_unref(&f->hwaccel_priv_buf); + f->hwaccel_picture_private = NULL; ff_thread_release_buffer(s->avctx, &f->tf); } @@ -99,6 +114,12 @@ static int vp8_ref_frame(VP8Context *s, VP8Frame *dst, VP8Frame *src) vp8_release_frame(s, dst); return AVERROR(ENOMEM); } + if (src->hwaccel_picture_private) { + dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); + if (!dst->hwaccel_priv_buf) + return AVERROR(ENOMEM); + dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data; + } return 0; } @@ -140,7 +161,7 @@ static VP8Frame *vp8_find_free_buffer(VP8Context *s) av_log(s->avctx, AV_LOG_FATAL, "Ran out of free frames!\n"); abort(); } - if (frame->tf.f->data[0]) + if (frame->tf.f->buf[0]) vp8_release_frame(s, frame); return frame; @@ -218,8 +239,9 @@ static void parse_segment_info(VP8Context *s) int i; s->segmentation.update_map = vp8_rac_get(c); + s->segmentation.update_feature_data = vp8_rac_get(c); - if (vp8_rac_get(c)) { // update segment feature data + if (s->segmentation.update_feature_data) { s->segmentation.absolute_vals = vp8_rac_get(c); for (i = 0; i < 4; i++) @@ -274,6 +296,7 @@ static int setup_partitions(VP8Context *s, const uint8_t *buf, int buf_size) int size = AV_RL24(sizes + 3 * i); if (buf_size - size < 0) return -1; + s->coeff_partition_size[i] = size; ret = ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, size); if (ret < 0) @@ -281,7 +304,11 @@ static int setup_partitions(VP8Context *s, const uint8_t *buf, int buf_size) buf += size; buf_size -= size; } - return ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, buf_size); + + s->coeff_partition_size[i] = buf_size; + ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, buf_size); + + return 0; } static void vp7_get_quants(VP8Context *s) @@ -308,28 +335,28 @@ static void vp8_get_quants(VP8Context *s) VP56RangeCoder *c = &s->c; int i, base_qi; - int yac_qi = vp8_rac_get_uint(c, 7); - int ydc_delta = vp8_rac_get_sint(c, 4); - int y2dc_delta = vp8_rac_get_sint(c, 4); - int y2ac_delta = vp8_rac_get_sint(c, 4); - int uvdc_delta = vp8_rac_get_sint(c, 4); - int uvac_delta = vp8_rac_get_sint(c, 4); + s->quant.yac_qi = vp8_rac_get_uint(c, 7); + s->quant.ydc_delta = vp8_rac_get_sint(c, 4); + s->quant.y2dc_delta = vp8_rac_get_sint(c, 4); + s->quant.y2ac_delta = vp8_rac_get_sint(c, 4); + s->quant.uvdc_delta = vp8_rac_get_sint(c, 4); + s->quant.uvac_delta = vp8_rac_get_sint(c, 4); for (i = 0; i < 4; i++) { if (s->segmentation.enabled) { base_qi = s->segmentation.base_quant[i]; if (!s->segmentation.absolute_vals) - base_qi += yac_qi; + base_qi += s->quant.yac_qi; } else - base_qi = yac_qi; + base_qi = s->quant.yac_qi; - s->qmat[i].luma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + ydc_delta, 7)]; + s->qmat[i].luma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.ydc_delta, 7)]; s->qmat[i].luma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi, 7)]; - s->qmat[i].luma_dc_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + y2dc_delta, 7)] * 2; + s->qmat[i].luma_dc_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.y2dc_delta, 7)] * 2; /* 101581>>16 is equivalent to 155/100 */ - s->qmat[i].luma_dc_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + y2ac_delta, 7)] * 101581 >> 16; - s->qmat[i].chroma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + uvdc_delta, 7)]; - s->qmat[i].chroma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + uvac_delta, 7)]; + s->qmat[i].luma_dc_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + s->quant.y2ac_delta, 7)] * 101581 >> 16; + s->qmat[i].chroma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.uvdc_delta, 7)]; + s->qmat[i].chroma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + s->quant.uvac_delta, 7)]; s->qmat[i].luma_dc_qmul[1] = FFMAX(s->qmat[i].luma_dc_qmul[1], 8); s->qmat[i].chroma_qmul[0] = FFMIN(s->qmat[i].chroma_qmul[0], 132); @@ -661,6 +688,8 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si buf += 3; buf_size -= 3; + s->header_partition_size = header_size; + if (s->profile > 3) av_log(s->avctx, AV_LOG_WARNING, "Unknown profile %d\n", s->profile); @@ -726,9 +755,11 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si s->filter.level = vp8_rac_get_uint(c, 6); s->filter.sharpness = vp8_rac_get_uint(c, 3); - if ((s->lf_delta.enabled = vp8_rac_get(c))) - if (vp8_rac_get(c)) + if ((s->lf_delta.enabled = vp8_rac_get(c))) { + s->lf_delta.update = vp8_rac_get(c); + if (s->lf_delta.update) update_lf_deltas(s); + } if (setup_partitions(s, buf, buf_size)) { av_log(s->avctx, AV_LOG_ERROR, "Invalid partitions\n"); @@ -768,6 +799,13 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si vp78_update_pred16x16_pred8x8_mvc_probabilities(s, VP8_MVC_SIZE); } + // Record the entropy coder state here so that hwaccels can use it. + s->c.code_word = vp56_rac_renorm(&s->c); + s->coder_state_at_header_end.input = s->c.buffer - (-s->c.bits / 8); + s->coder_state_at_header_end.range = s->c.high; + s->coder_state_at_header_end.value = s->c.code_word >> 16; + s->coder_state_at_header_end.bit_count = -s->c.bits % 8; + return 0; } @@ -2540,7 +2578,6 @@ static int vp8_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, return vp78_decode_mb_row_sliced(avctx, tdata, jobnr, threadnr, IS_VP8); } - static av_always_inline int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt, int is_vp7) @@ -2550,8 +2587,6 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, enum AVDiscard skip_thresh; VP8Frame *av_uninit(curframe), *prev_frame; - av_assert0(avctx->pix_fmt == AV_PIX_FMT_YUVA420P || avctx->pix_fmt == AV_PIX_FMT_YUV420P); - if (is_vp7) ret = vp7_decode_frame_header(s, avpkt->data, avpkt->size); else @@ -2560,6 +2595,22 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (ret < 0) goto err; + if (s->actually_webp) { + // avctx->pix_fmt already set in caller. + } else if (!is_vp7 && s->pix_fmt == AV_PIX_FMT_NONE) { + enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE, + }; + + s->pix_fmt = ff_get_format(s->avctx, pix_fmts); + if (s->pix_fmt < 0) { + ret = AVERROR(EINVAL); + goto err; + } + avctx->pix_fmt = s->pix_fmt; + } + prev_frame = s->framep[VP56_FRAME_CURRENT]; referenced = s->update_last || s->update_golden == VP56_FRAME_CURRENT || @@ -2578,7 +2629,7 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, // release no longer referenced frames for (i = 0; i < 5; i++) - if (s->frames[i].tf.f->data[0] && + if (s->frames[i].tf.f->buf[0] && &s->frames[i] != prev_frame && &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] && &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] && @@ -2631,55 +2682,69 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, s->next_framep[VP56_FRAME_CURRENT] = curframe; - if (avctx->codec->update_thread_context) - ff_thread_finish_setup(avctx); + ff_thread_finish_setup(avctx); - s->linesize = curframe->tf.f->linesize[0]; - s->uvlinesize = curframe->tf.f->linesize[1]; + if (avctx->hwaccel) { + ret = avctx->hwaccel->start_frame(avctx, avpkt->data, avpkt->size); + if (ret < 0) + goto err; - memset(s->top_nnz, 0, s->mb_width * sizeof(*s->top_nnz)); - /* Zero macroblock structures for top/top-left prediction - * from outside the frame. */ - if (!s->mb_layout) - memset(s->macroblocks + s->mb_height * 2 - 1, 0, - (s->mb_width + 1) * sizeof(*s->macroblocks)); - if (!s->mb_layout && s->keyframe) - memset(s->intra4x4_pred_mode_top, DC_PRED, s->mb_width * 4); + ret = avctx->hwaccel->decode_slice(avctx, avpkt->data, avpkt->size); + if (ret < 0) + goto err; - memset(s->ref_count, 0, sizeof(s->ref_count)); + ret = avctx->hwaccel->end_frame(avctx); + if (ret < 0) + goto err; - if (s->mb_layout == 1) { - // Make sure the previous frame has read its segmentation map, - // if we re-use the same map. - if (prev_frame && s->segmentation.enabled && - !s->segmentation.update_map) - ff_thread_await_progress(&prev_frame->tf, 1, 0); + } else { + s->linesize = curframe->tf.f->linesize[0]; + s->uvlinesize = curframe->tf.f->linesize[1]; + + memset(s->top_nnz, 0, s->mb_width * sizeof(*s->top_nnz)); + /* Zero macroblock structures for top/top-left prediction + * from outside the frame. */ + if (!s->mb_layout) + memset(s->macroblocks + s->mb_height * 2 - 1, 0, + (s->mb_width + 1) * sizeof(*s->macroblocks)); + if (!s->mb_layout && s->keyframe) + memset(s->intra4x4_pred_mode_top, DC_PRED, s->mb_width * 4); + + memset(s->ref_count, 0, sizeof(s->ref_count)); + + if (s->mb_layout == 1) { + // Make sure the previous frame has read its segmentation map, + // if we re-use the same map. + if (prev_frame && s->segmentation.enabled && + !s->segmentation.update_map) + ff_thread_await_progress(&prev_frame->tf, 1, 0); + if (is_vp7) + vp7_decode_mv_mb_modes(avctx, curframe, prev_frame); + else + vp8_decode_mv_mb_modes(avctx, curframe, prev_frame); + } + + if (avctx->active_thread_type == FF_THREAD_FRAME) + num_jobs = 1; + else + num_jobs = FFMIN(s->num_coeff_partitions, avctx->thread_count); + s->num_jobs = num_jobs; + s->curframe = curframe; + s->prev_frame = prev_frame; + s->mv_bounds.mv_min.y = -MARGIN; + s->mv_bounds.mv_max.y = ((s->mb_height - 1) << 6) + MARGIN; + for (i = 0; i < MAX_THREADS; i++) { + VP8ThreadData *td = &s->thread_data[i]; + atomic_init(&td->thread_mb_pos, 0); + atomic_init(&td->wait_mb_pos, INT_MAX); + } if (is_vp7) - vp7_decode_mv_mb_modes(avctx, curframe, prev_frame); + avctx->execute2(avctx, vp7_decode_mb_row_sliced, s->thread_data, NULL, + num_jobs); else - vp8_decode_mv_mb_modes(avctx, curframe, prev_frame); - } - - if (avctx->active_thread_type == FF_THREAD_FRAME) - num_jobs = 1; - else - num_jobs = FFMIN(s->num_coeff_partitions, avctx->thread_count); - s->num_jobs = num_jobs; - s->curframe = curframe; - s->prev_frame = prev_frame; - s->mv_bounds.mv_min.y = -MARGIN; - s->mv_bounds.mv_max.y = ((s->mb_height - 1) << 6) + MARGIN; - for (i = 0; i < MAX_THREADS; i++) { - VP8ThreadData *td = &s->thread_data[i]; - atomic_init(&td->thread_mb_pos, 0); - atomic_init(&td->wait_mb_pos, INT_MAX); + avctx->execute2(avctx, vp8_decode_mb_row_sliced, s->thread_data, NULL, + num_jobs); } - if (is_vp7) - avctx->execute2(avctx, vp7_decode_mb_row_sliced, s->thread_data, NULL, - num_jobs); - else - avctx->execute2(avctx, vp8_decode_mb_row_sliced, s->thread_data, NULL, - num_jobs); ff_thread_report_progress(&curframe->tf, INT_MAX, 0); memcpy(&s->framep[0], &s->next_framep[0], sizeof(s->framep[0]) * 4); @@ -2750,6 +2815,7 @@ int vp78_decode_init(AVCodecContext *avctx, int is_vp7) s->avctx = avctx; s->vp7 = avctx->codec->id == AV_CODEC_ID_VP7; + s->pix_fmt = AV_PIX_FMT_NONE; avctx->pix_fmt = AV_PIX_FMT_YUV420P; avctx->internal->allocate_progress = 1; @@ -2823,13 +2889,14 @@ static int vp8_decode_update_thread_context(AVCodecContext *dst, s->mb_height = s_src->mb_height; } + s->pix_fmt = s_src->pix_fmt; s->prob[0] = s_src->prob[!s_src->update_probabilities]; s->segmentation = s_src->segmentation; s->lf_delta = s_src->lf_delta; memcpy(s->sign_bias, s_src->sign_bias, sizeof(s->sign_bias)); for (i = 0; i < FF_ARRAY_ELEMS(s_src->frames); i++) { - if (s_src->frames[i].tf.f->data[0]) { + if (s_src->frames[i].tf.f->buf[0]) { int ret = vp8_ref_frame(s, &s->frames[i], &s_src->frames[i]); if (ret < 0) return ret; @@ -2876,5 +2943,8 @@ AVCodec ff_vp8_decoder = { .flush = vp8_decode_flush, .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp8_decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_context), + .hw_configs = (const AVCodecHWConfigInternal*[]) { + NULL + }, }; #endif /* CONFIG_VP7_DECODER */ diff --git a/libavcodec/vp8.h b/libavcodec/vp8.h index 8263997e3fcd4..70d21e3c60460 100644 --- a/libavcodec/vp8.h +++ b/libavcodec/vp8.h @@ -138,12 +138,18 @@ typedef struct VP8ThreadData { typedef struct VP8Frame { ThreadFrame tf; AVBufferRef *seg_map; + + AVBufferRef *hwaccel_priv_buf; + void *hwaccel_picture_private; } VP8Frame; #define MAX_THREADS 8 typedef struct VP8Context { VP8ThreadData *thread_data; AVCodecContext *avctx; + enum AVPixelFormat pix_fmt; + int actually_webp; + VP8Frame *framep[4]; VP8Frame *next_framep[4]; VP8Frame *curframe; @@ -172,6 +178,7 @@ typedef struct VP8Context { uint8_t enabled; uint8_t absolute_vals; uint8_t update_map; + uint8_t update_feature_data; int8_t base_quant[4]; int8_t filter_level[4]; ///< base loop filter level } segmentation; @@ -199,8 +206,19 @@ typedef struct VP8Context { int16_t chroma_qmul[2]; } qmat[4]; + // Raw quantisation values, which may be needed by hwaccel decode. + struct { + int yac_qi; + int ydc_delta; + int y2dc_delta; + int y2ac_delta; + int uvdc_delta; + int uvac_delta; + } quant; + struct { uint8_t enabled; ///< whether each mb can have a different strength based on mode/ref + uint8_t update; /** * filter strength adjustment for the following macroblock modes: @@ -228,6 +246,20 @@ typedef struct VP8Context { VP56RangeCoder c; ///< header context, includes mb modes and motion vectors + /* This contains the entropy coder state at the end of the header + * block, in the form specified by the standard. For use by + * hwaccels, so that a hardware decoder has the information to + * start decoding at the macroblock layer. + */ + struct { + const uint8_t *input; + uint32_t range; + uint32_t value; + int bit_count; + } coder_state_at_header_end; + + int header_partition_size; + /** * These are all of the updatable probabilities for binary decisions. * They are only implicitly reset on keyframes, making it quite likely @@ -265,6 +297,7 @@ typedef struct VP8Context { */ int num_coeff_partitions; VP56RangeCoder coeff_partition[8]; + int coeff_partition_size[8]; VideoDSPContext vdsp; VP8DSPContext vp8dsp; H264PredContext hpc; diff --git a/libavcodec/webp.c b/libavcodec/webp.c index c8475faa2d9ec..077bb06f85a7c 100644 --- a/libavcodec/webp.c +++ b/libavcodec/webp.c @@ -1335,6 +1335,7 @@ static int vp8_lossy_decode_frame(AVCodecContext *avctx, AVFrame *p, if (!s->initialized) { ff_vp8_decode_init(avctx); s->initialized = 1; + s->v.actually_webp = 1; } avctx->pix_fmt = s->has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P; s->lossless = 0; From 40b75a943bcb6a4af00c44ef6e52cbfc3e6580d8 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 18 Nov 2017 17:55:24 +0000 Subject: [PATCH 1131/2557] vaapi: Add VP8 decode hwaccel --- configure | 3 + libavcodec/Makefile | 1 + libavcodec/hwaccels.h | 1 + libavcodec/vaapi_vp8.c | 237 +++++++++++++++++++++++++++++++++++++++++ libavcodec/vp8.c | 6 ++ 5 files changed, 248 insertions(+) create mode 100644 libavcodec/vaapi_vp8.c diff --git a/configure b/configure index d6cb61fb4c479..fbff66669c9ed 100755 --- a/configure +++ b/configure @@ -2746,6 +2746,8 @@ vc1_vaapi_hwaccel_deps="vaapi" vc1_vaapi_hwaccel_select="vc1_decoder" vc1_vdpau_hwaccel_deps="vdpau" vc1_vdpau_hwaccel_select="vc1_decoder" +vp8_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferVP8" +vp8_vaapi_hwaccel_select="vp8_decoder" vp9_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_VP9" vp9_d3d11va_hwaccel_select="vp9_decoder" vp9_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_VP9" @@ -5719,6 +5721,7 @@ check_type "windows.h d3d11.h" "ID3D11VideoContext" check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602 check_type "va/va.h va/va_dec_hevc.h" "VAPictureParameterBufferHEVC" +check_type "va/va.h va/va_dec_vp8.h" "VAPictureParameterBufferVP8" check_struct "va/va.h" "VADecPictureParameterBufferVP9" bit_depth check_type "va/va.h va/va_vpp.h" "VAProcPipelineParameterBuffer" check_type "va/va.h va/va_enc_h264.h" "VAEncPictureParameterBufferH264" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2af957ab7279e..0ebd2820ebfee 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -871,6 +871,7 @@ OBJS-$(CONFIG_VC1_NVDEC_HWACCEL) += nvdec_vc1.o OBJS-$(CONFIG_VC1_QSV_HWACCEL) += qsvdec_other.o OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o +OBJS-$(CONFIG_VP8_VAAPI_HWACCEL) += vaapi_vp8.o OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL) += dxva2_vp9.o OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o OBJS-$(CONFIG_VP9_NVDEC_HWACCEL) += nvdec_vp9.o diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h index 8a3c29e43597a..afe728934191b 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -59,6 +59,7 @@ extern const AVHWAccel ff_vc1_dxva2_hwaccel; extern const AVHWAccel ff_vc1_nvdec_hwaccel; extern const AVHWAccel ff_vc1_vaapi_hwaccel; extern const AVHWAccel ff_vc1_vdpau_hwaccel; +extern const AVHWAccel ff_vp8_vaapi_hwaccel; extern const AVHWAccel ff_vp9_d3d11va_hwaccel; extern const AVHWAccel ff_vp9_d3d11va2_hwaccel; extern const AVHWAccel ff_vp9_dxva2_hwaccel; diff --git a/libavcodec/vaapi_vp8.c b/libavcodec/vaapi_vp8.c new file mode 100644 index 0000000000000..2426b30f13ca1 --- /dev/null +++ b/libavcodec/vaapi_vp8.c @@ -0,0 +1,237 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "hwaccel.h" +#include "vaapi_decode.h" +#include "vp8.h" + +static VASurfaceID vaapi_vp8_surface_id(VP8Frame *vf) +{ + if (vf) + return ff_vaapi_get_surface_id(vf->tf.f); + else + return VA_INVALID_SURFACE; +} + +static int vaapi_vp8_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + const VP8Context *s = avctx->priv_data; + VAAPIDecodePicture *pic = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; + VAPictureParameterBufferVP8 pp; + VAProbabilityDataBufferVP8 prob; + VAIQMatrixBufferVP8 quant; + int err, i, j, k; + + pic->output_surface = vaapi_vp8_surface_id(s->framep[VP56_FRAME_CURRENT]); + + pp = (VAPictureParameterBufferVP8) { + .frame_width = avctx->width, + .frame_height = avctx->height, + + .last_ref_frame = vaapi_vp8_surface_id(s->framep[VP56_FRAME_PREVIOUS]), + .golden_ref_frame = vaapi_vp8_surface_id(s->framep[VP56_FRAME_GOLDEN]), + .alt_ref_frame = vaapi_vp8_surface_id(s->framep[VP56_FRAME_GOLDEN2]), + .out_of_loop_frame = VA_INVALID_SURFACE, + + .pic_fields.bits = { + .key_frame = !s->keyframe, + .version = s->profile, + + .segmentation_enabled = s->segmentation.enabled, + .update_mb_segmentation_map = s->segmentation.update_map, + .update_segment_feature_data = s->segmentation.update_feature_data, + + .filter_type = s->filter.simple, + .sharpness_level = s->filter.sharpness, + + .loop_filter_adj_enable = s->lf_delta.enabled, + .mode_ref_lf_delta_update = s->lf_delta.update, + + .sign_bias_golden = s->sign_bias[VP56_FRAME_GOLDEN], + .sign_bias_alternate = s->sign_bias[VP56_FRAME_GOLDEN2], + + .mb_no_coeff_skip = s->mbskip_enabled, + .loop_filter_disable = s->filter.level == 0, + }, + + .prob_skip_false = s->prob->mbskip, + .prob_intra = s->prob->intra, + .prob_last = s->prob->last, + .prob_gf = s->prob->golden, + }; + + for (i = 0; i < 3; i++) + pp.mb_segment_tree_probs[i] = s->prob->segmentid[i]; + + for (i = 0; i < 4; i++) { + if (s->segmentation.enabled) { + pp.loop_filter_level[i] = s->segmentation.filter_level[i]; + if (!s->segmentation.absolute_vals) + pp.loop_filter_level[i] += s->filter.level; + } else { + pp.loop_filter_level[i] = s->filter.level; + } + pp.loop_filter_level[i] = av_clip_uintp2(pp.loop_filter_level[i], 6); + } + + for (i = 0; i < 4; i++) { + pp.loop_filter_deltas_ref_frame[i] = s->lf_delta.ref[i]; + pp.loop_filter_deltas_mode[i] = s->lf_delta.mode[i + 4]; + } + + if (s->keyframe) { + static const uint8_t keyframe_y_mode_probs[4] = { + 145, 156, 163, 128 + }; + static const uint8_t keyframe_uv_mode_probs[3] = { + 142, 114, 183 + }; + memcpy(pp.y_mode_probs, keyframe_y_mode_probs, 4); + memcpy(pp.uv_mode_probs, keyframe_uv_mode_probs, 3); + } else { + for (i = 0; i < 4; i++) + pp.y_mode_probs[i] = s->prob->pred16x16[i]; + for (i = 0; i < 3; i++) + pp.uv_mode_probs[i] = s->prob->pred8x8c[i]; + } + for (i = 0; i < 2; i++) + for (j = 0; j < 19; j++) + pp.mv_probs[i][j] = s->prob->mvc[i][j]; + + pp.bool_coder_ctx.range = s->coder_state_at_header_end.range; + pp.bool_coder_ctx.value = s->coder_state_at_header_end.value; + pp.bool_coder_ctx.count = s->coder_state_at_header_end.bit_count; + + err = ff_vaapi_decode_make_param_buffer(avctx, pic, + VAPictureParameterBufferType, + &pp, sizeof(pp)); + if (err < 0) + goto fail; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 8; j++) { + static const int coeff_bands_inverse[8] = { + 0, 1, 2, 3, 5, 6, 4, 15 + }; + int coeff_pos = coeff_bands_inverse[j]; + + for (k = 0; k < 3; k++) { + memcpy(prob.dct_coeff_probs[i][j][k], + s->prob->token[i][coeff_pos][k], 11); + } + } + } + + err = ff_vaapi_decode_make_param_buffer(avctx, pic, + VAProbabilityBufferType, + &prob, sizeof(prob)); + if (err < 0) + goto fail; + + for (i = 0; i < 4; i++) { + int base_qi = s->segmentation.base_quant[i]; + if (!s->segmentation.absolute_vals) + base_qi += s->quant.yac_qi; + + quant.quantization_index[i][0] = av_clip_uintp2(base_qi, 7); + quant.quantization_index[i][1] = av_clip_uintp2(base_qi + s->quant.ydc_delta, 7); + quant.quantization_index[i][2] = av_clip_uintp2(base_qi + s->quant.y2dc_delta, 7); + quant.quantization_index[i][3] = av_clip_uintp2(base_qi + s->quant.y2ac_delta, 7); + quant.quantization_index[i][4] = av_clip_uintp2(base_qi + s->quant.uvdc_delta, 7); + quant.quantization_index[i][5] = av_clip_uintp2(base_qi + s->quant.uvac_delta, 7); + } + + err = ff_vaapi_decode_make_param_buffer(avctx, pic, + VAIQMatrixBufferType, + &quant, sizeof(quant)); + if (err < 0) + goto fail; + + return 0; + +fail: + ff_vaapi_decode_cancel(avctx, pic); + return err; +} + +static int vaapi_vp8_end_frame(AVCodecContext *avctx) +{ + const VP8Context *s = avctx->priv_data; + VAAPIDecodePicture *pic = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; + + return ff_vaapi_decode_issue(avctx, pic); +} + +static int vaapi_vp8_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + const VP8Context *s = avctx->priv_data; + VAAPIDecodePicture *pic = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; + VASliceParameterBufferVP8 sp; + int err, i; + + unsigned int header_size = 3 + 7 * s->keyframe; + const uint8_t *data = buffer + header_size; + unsigned int data_size = size - header_size; + + sp = (VASliceParameterBufferVP8) { + .slice_data_size = data_size, + .slice_data_offset = 0, + .slice_data_flag = VA_SLICE_DATA_FLAG_ALL, + + .macroblock_offset = (8 * (s->coder_state_at_header_end.input - data) - + s->coder_state_at_header_end.bit_count - 8), + .num_of_partitions = s->num_coeff_partitions + 1, + }; + + sp.partition_size[0] = s->header_partition_size - ((sp.macroblock_offset + 7) / 8); + for (i = 0; i < 8; i++) + sp.partition_size[i+1] = s->coeff_partition_size[i]; + + err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &sp, sizeof(sp), data, data_size); + if (err) + goto fail; + + return 0; + +fail: + ff_vaapi_decode_cancel(avctx, pic); + return err; +} + +const AVHWAccel ff_vp8_vaapi_hwaccel = { + .name = "vp8_vaapi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP8, + .pix_fmt = AV_PIX_FMT_VAAPI, + .start_frame = &vaapi_vp8_start_frame, + .end_frame = &vaapi_vp8_end_frame, + .decode_slice = &vaapi_vp8_decode_slice, + .frame_priv_data_size = sizeof(VAAPIDecodePicture), + .init = &ff_vaapi_decode_init, + .uninit = &ff_vaapi_decode_uninit, + .frame_params = &ff_vaapi_common_frame_params, + .priv_data_size = sizeof(VAAPIDecodeContext), + .caps_internal = HWACCEL_CAP_ASYNC_SAFE, +}; diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index 31cd6a0d816bb..2b1cd155e24d0 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -2599,6 +2599,9 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, // avctx->pix_fmt already set in caller. } else if (!is_vp7 && s->pix_fmt == AV_PIX_FMT_NONE) { enum AVPixelFormat pix_fmts[] = { +#if CONFIG_VP8_VAAPI_HWACCEL + AV_PIX_FMT_VAAPI, +#endif AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE, }; @@ -2944,6 +2947,9 @@ AVCodec ff_vp8_decoder = { .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp8_decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_context), .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_VP8_VAAPI_HWACCEL + HWACCEL_VAAPI(vp8), +#endif NULL }, }; From f69e9365f6e0c43ac78bc0b2358591c54f0448b3 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 18 Nov 2017 17:52:27 +0000 Subject: [PATCH 1132/2557] vaapi_decode: Ignore the profile when not useful Enables VP8 decoding - the decoder places the the bitstream version in the profile field, which we want to ignore. --- libavcodec/vaapi_decode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index d36ef906a202d..572b3a40ac054 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -324,7 +324,8 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, int profile_match = 0; if (avctx->codec_id != vaapi_profile_map[i].codec_id) continue; - if (avctx->profile == vaapi_profile_map[i].codec_profile) + if (avctx->profile == vaapi_profile_map[i].codec_profile || + vaapi_profile_map[i].codec_profile == FF_PROFILE_UNKNOWN) profile_match = 1; for (j = 0; j < profile_count; j++) { if (vaapi_profile_map[i].va_profile == profile_list[j]) { From 1da9851e3470a019a35793c913a1de07f75dc3fc Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Sun, 19 Nov 2017 08:42:39 -0800 Subject: [PATCH 1133/2557] avcodec/nvdec: Implement vp8 hwaccel --- Changelog | 2 +- configure | 2 + libavcodec/Makefile | 1 + libavcodec/hwaccels.h | 1 + libavcodec/nvdec.c | 1 + libavcodec/nvdec_vp8.c | 97 ++++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- libavcodec/vp8.c | 6 +++ 8 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 libavcodec/nvdec_vp8.c diff --git a/Changelog b/Changelog index e3092e211f4e2..afead72f14c37 100644 --- a/Changelog +++ b/Changelog @@ -13,7 +13,7 @@ version : - PCE support for extended channel layouts in the AAC encoder - native aptX encoder and decoder - Raw aptX muxer and demuxer -- NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-1/2/4, VC1 and VP9 hwaccel decoding +- NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-1/2/4, VC1, VP8/9 hwaccel decoding - Intel QSV-accelerated overlay filter - mcompand audio filter - acontrast audio filter diff --git a/configure b/configure index fbff66669c9ed..6748ef8bc9af2 100755 --- a/configure +++ b/configure @@ -2746,6 +2746,8 @@ vc1_vaapi_hwaccel_deps="vaapi" vc1_vaapi_hwaccel_select="vc1_decoder" vc1_vdpau_hwaccel_deps="vdpau" vc1_vdpau_hwaccel_select="vc1_decoder" +vp8_nvdec_hwaccel_deps="nvdec" +vp8_nvdec_hwaccel_select="vp8_decoder" vp8_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferVP8" vp8_vaapi_hwaccel_select="vp8_decoder" vp9_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_VP9" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 0ebd2820ebfee..a6203d424b740 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -871,6 +871,7 @@ OBJS-$(CONFIG_VC1_NVDEC_HWACCEL) += nvdec_vc1.o OBJS-$(CONFIG_VC1_QSV_HWACCEL) += qsvdec_other.o OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o +OBJS-$(CONFIG_VP8_NVDEC_HWACCEL) += nvdec_vp8.o OBJS-$(CONFIG_VP8_VAAPI_HWACCEL) += vaapi_vp8.o OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL) += dxva2_vp9.o OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h index afe728934191b..fcfe4e088ec7b 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -59,6 +59,7 @@ extern const AVHWAccel ff_vc1_dxva2_hwaccel; extern const AVHWAccel ff_vc1_nvdec_hwaccel; extern const AVHWAccel ff_vc1_vaapi_hwaccel; extern const AVHWAccel ff_vc1_vdpau_hwaccel; +extern const AVHWAccel ff_vp8_nvdec_hwaccel; extern const AVHWAccel ff_vp8_vaapi_hwaccel; extern const AVHWAccel ff_vp9_d3d11va_hwaccel; extern const AVHWAccel ff_vp9_d3d11va2_hwaccel; diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index da4451a739dc4..c7a02ff40f616 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -58,6 +58,7 @@ static int map_avcodec_id(enum AVCodecID id) case AV_CODEC_ID_MPEG2VIDEO: return cudaVideoCodec_MPEG2; case AV_CODEC_ID_MPEG4: return cudaVideoCodec_MPEG4; case AV_CODEC_ID_VC1: return cudaVideoCodec_VC1; + case AV_CODEC_ID_VP8: return cudaVideoCodec_VP8; case AV_CODEC_ID_VP9: return cudaVideoCodec_VP9; case AV_CODEC_ID_WMV3: return cudaVideoCodec_VC1; } diff --git a/libavcodec/nvdec_vp8.c b/libavcodec/nvdec_vp8.c new file mode 100644 index 0000000000000..ceb3de2c3a4f8 --- /dev/null +++ b/libavcodec/nvdec_vp8.c @@ -0,0 +1,97 @@ +/* + * VP8 HW decode acceleration through NVDEC + * + * Copyright (c) 2017 Philip Langdale + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "nvdec.h" +#include "decode.h" +#include "internal.h" +#include "vp8.h" + +static unsigned char safe_get_ref_idx(VP8Frame *frame) +{ + return frame ? ff_nvdec_get_ref_idx(frame->tf.f) : 255; +} + +static int nvdec_vp8_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + VP8Context *h = avctx->priv_data; + + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + CUVIDPICPARAMS *pp = &ctx->pic_params; + FrameDecodeData *fdd; + NVDECFrame *cf; + AVFrame *cur_frame = h->framep[VP56_FRAME_CURRENT]->tf.f; + + int ret; + + ret = ff_nvdec_start_frame(avctx, cur_frame); + if (ret < 0) + return ret; + + fdd = (FrameDecodeData*)cur_frame->private_ref->data; + cf = (NVDECFrame*)fdd->hwaccel_priv; + + *pp = (CUVIDPICPARAMS) { + .PicWidthInMbs = (cur_frame->width + 15) / 16, + .FrameHeightInMbs = (cur_frame->height + 15) / 16, + .CurrPicIdx = cf->idx, + + .CodecSpecific.vp8 = { + .width = cur_frame->width, + .height = cur_frame->height, + + .first_partition_size = h->header_partition_size, + + .LastRefIdx = safe_get_ref_idx(h->framep[VP56_FRAME_PREVIOUS]), + .GoldenRefIdx = safe_get_ref_idx(h->framep[VP56_FRAME_GOLDEN]), + .AltRefIdx = safe_get_ref_idx(h->framep[VP56_FRAME_GOLDEN2]), + + .frame_type = !h->keyframe, + .version = h->profile, + .show_frame = !h->invisible, + .update_mb_segmentation_data = h->segmentation.enabled ? h->segmentation.update_feature_data : 0, + } + }; + + return 0; +} + +static int nvdec_vp8_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) +{ + // VP8 uses a fixed size pool of 3 possible reference frames + return ff_nvdec_frame_params(avctx, hw_frames_ctx, 3); +} + +AVHWAccel ff_vp8_nvdec_hwaccel = { + .name = "vp8_nvdec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP8, + .pix_fmt = AV_PIX_FMT_CUDA, + .start_frame = nvdec_vp8_start_frame, + .end_frame = ff_nvdec_simple_end_frame, + .decode_slice = ff_nvdec_simple_decode_slice, + .frame_params = nvdec_vp8_frame_params, + .init = ff_nvdec_decode_init, + .uninit = ff_nvdec_decode_uninit, + .priv_data_size = sizeof(NVDECContext), +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index ba46721fb5880..55bb5c5e01f6f 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 6 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index 2b1cd155e24d0..471c0bb89e244 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -2601,6 +2601,9 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, enum AVPixelFormat pix_fmts[] = { #if CONFIG_VP8_VAAPI_HWACCEL AV_PIX_FMT_VAAPI, +#endif +#if CONFIG_VP8_NVDEC_HWACCEL + AV_PIX_FMT_CUDA, #endif AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE, @@ -2949,6 +2952,9 @@ AVCodec ff_vp8_decoder = { .hw_configs = (const AVCodecHWConfigInternal*[]) { #if CONFIG_VP8_VAAPI_HWACCEL HWACCEL_VAAPI(vp8), +#endif +#if CONFIG_VP8_NVDEC_HWACCEL + HWACCEL_NVDEC(vp8), #endif NULL }, From 921d7af6e9e65fabade00e35a7d40a6b80b0a58b Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 26 Nov 2017 22:19:45 -0300 Subject: [PATCH 1134/2557] avcodec/mpeg4videodec: fix preprocessor check for the nvdec hwaccel Signed-off-by: James Almer --- libavcodec/mpeg4videodec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 19fcc1bc8f755..cdd7077f01e3d 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -2857,7 +2857,7 @@ AVCodec ff_mpeg4_decoder = { .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg4_update_thread_context), .priv_class = &mpeg4_class, .hw_configs = (const AVCodecHWConfigInternal*[]) { -#if CONFIG_MPEG2_NVDEC_HWACCEL +#if CONFIG_MPEG4_NVDEC_HWACCEL HWACCEL_NVDEC(mpeg4), #endif #if CONFIG_MPEG4_VAAPI_HWACCEL From 1eee394c7c84c3b755bc856a49607214de206ded Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 26 Nov 2017 22:22:17 -0300 Subject: [PATCH 1135/2557] avcodec/vc1dec: fix preprocessor checks and hw_configs lists for the hwaccels Signed-off-by: James Almer --- libavcodec/vc1dec.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index ac4cfed2c8e44..cbef89f254562 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -1146,23 +1146,23 @@ AVCodec ff_vc1_decoder = { .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .pix_fmts = vc1_hwaccel_pixfmt_list_420, .hw_configs = (const AVCodecHWConfigInternal*[]) { -#if CONFIG_WMV3_DXVA2_HWACCEL - HWACCEL_DXVA2(wmv3), +#if CONFIG_VC1_DXVA2_HWACCEL + HWACCEL_DXVA2(vc1), #endif -#if CONFIG_WMV3_D3D11VA_HWACCEL - HWACCEL_D3D11VA(wmv3), +#if CONFIG_VC1_D3D11VA_HWACCEL + HWACCEL_D3D11VA(vc1), #endif -#if CONFIG_WMV3_D3D11VA2_HWACCEL - HWACCEL_D3D11VA2(wmv3), +#if CONFIG_VC1_D3D11VA2_HWACCEL + HWACCEL_D3D11VA2(vc1), #endif -#if CONFIG_WMV3_NVDEC_HWACCEL - HWACCEL_NVDEC(wmv3), +#if CONFIG_VC1_NVDEC_HWACCEL + HWACCEL_NVDEC(vc1), #endif -#if CONFIG_WMV3_VAAPI_HWACCEL - HWACCEL_VAAPI(wmv3), +#if CONFIG_VC1_VAAPI_HWACCEL + HWACCEL_VAAPI(vc1), #endif -#if CONFIG_WMV3_VDPAU_HWACCEL - HWACCEL_VDPAU(wmv3), +#if CONFIG_VC1_VDPAU_HWACCEL + HWACCEL_VDPAU(vc1), #endif NULL }, @@ -1183,22 +1183,22 @@ AVCodec ff_wmv3_decoder = { .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .pix_fmts = vc1_hwaccel_pixfmt_list_420, .hw_configs = (const AVCodecHWConfigInternal*[]) { -#if CONFIG_VC1_DXVA2_HWACCEL +#if CONFIG_WMV3_DXVA2_HWACCEL HWACCEL_DXVA2(wmv3), #endif -#if CONFIG_VC1_D3D11VA_HWACCEL +#if CONFIG_WMV3_D3D11VA_HWACCEL HWACCEL_D3D11VA(wmv3), #endif -#if CONFIG_VC1_D3D11VA2_HWACCEL +#if CONFIG_WMV3_D3D11VA2_HWACCEL HWACCEL_D3D11VA2(wmv3), #endif -#if CONFIG_VC1_NVDEC_HWACCEL +#if CONFIG_WMV3_NVDEC_HWACCEL HWACCEL_NVDEC(wmv3), #endif -#if CONFIG_VC1_VAAPI_HWACCEL +#if CONFIG_WMV3_VAAPI_HWACCEL HWACCEL_VAAPI(wmv3), #endif -#if CONFIG_VC1_VDPAU_HWACCEL +#if CONFIG_WMV3_VDPAU_HWACCEL HWACCEL_VDPAU(wmv3), #endif NULL From 38f966b2222db4bfeeaca4642a63049253536c46 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 29 Oct 2017 15:26:50 +0100 Subject: [PATCH 1136/2557] tests/checkasm/float_dsp: Increase allowed difference for float_dsp.vector_dmul Tested for 10000 iterations on x86-32 Fixes: Ticket6848 Signed-off-by: Michael Niedermayer --- tests/checkasm/float_dsp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/checkasm/float_dsp.c b/tests/checkasm/float_dsp.c index 9b0a221c25d2c..2f999a3162571 100644 --- a/tests/checkasm/float_dsp.c +++ b/tests/checkasm/float_dsp.c @@ -165,7 +165,8 @@ static void test_vector_dmul_scalar(const double *src0, const double *src1) call_ref(cdst, src0, src1[0], LEN); call_new(odst, src0, src1[0], LEN); for (i = 0; i < LEN; i++) { - if (!double_near_abs_eps(cdst[i], odst[i], DBL_EPSILON)) { + double t = fabs(src1[0]) + fabs(src0[i]) + fabs(src1[0] * src0[i]) + 1.0; + if (!double_near_abs_eps(cdst[i], odst[i], t * 2 * DBL_EPSILON)) { fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n", i, cdst[i], odst[i], cdst[i] - odst[i]); fail(); From 3aad94bf2b140cfba8ae69d018da05d4948ef37f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 22 Nov 2017 20:14:54 +0100 Subject: [PATCH 1137/2557] avcodec/kgv1dec: Check that there is enough input for maximum RLE compression Fixes: Timeout Fixes: 4271/clusterfuzz-testcase-4676667768307712 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/kgv1dec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/kgv1dec.c b/libavcodec/kgv1dec.c index 5359411c76190..a6bd9400ac16f 100644 --- a/libavcodec/kgv1dec.c +++ b/libavcodec/kgv1dec.c @@ -62,6 +62,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, h = (buf[1] + 1) * 8; buf += 2; + if (avpkt->size < 2 + w*h / 513) + return AVERROR_INVALIDDATA; + if (w != avctx->width || h != avctx->height) { av_freep(&c->frame_buffer); av_freep(&c->last_frame_buffer); From 9cc926da7d9920d17b76584e7212309ab5c02387 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 20 Nov 2017 03:08:20 +0100 Subject: [PATCH 1138/2557] avcodec/h264idct_template: Fix integer overflow in ff_h264_idct8_add Fixes: signed integer overflow: 452986184 - -2113885312 cannot be represented in type 'int' Fixes: 4196/clusterfuzz-testcase-minimized-5580648594014208 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/h264idct_template.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/h264idct_template.c b/libavcodec/h264idct_template.c index 7526bdd812c3a..5993ae2e6e7da 100644 --- a/libavcodec/h264idct_template.c +++ b/libavcodec/h264idct_template.c @@ -76,10 +76,10 @@ void FUNCC(ff_h264_idct8_add)(uint8_t *_dst, int16_t *_block, int stride){ for( i = 0; i < 8; i++ ) { - const unsigned int a0 = block[i+0*8] + block[i+4*8]; - const unsigned int a2 = block[i+0*8] - block[i+4*8]; - const unsigned int a4 = (block[i+2*8]>>1) - block[i+6*8]; - const unsigned int a6 = (block[i+6*8]>>1) + block[i+2*8]; + const unsigned int a0 = block[i+0*8] + (unsigned)block[i+4*8]; + const unsigned int a2 = block[i+0*8] - (unsigned)block[i+4*8]; + const unsigned int a4 = (block[i+2*8]>>1) - (unsigned)block[i+6*8]; + const unsigned int a6 = (block[i+6*8]>>1) + (unsigned)block[i+2*8]; const unsigned int b0 = a0 + a6; const unsigned int b2 = a2 + a4; From 883de7e8b4fee252464b15e0351c6e5733e36e54 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 22 Nov 2017 12:16:57 +0100 Subject: [PATCH 1139/2557] libavformat/mov: Replace duplicate stream_nb check by assert Reviewed-by: Derek Buitenhuis Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index ddb1e59b8569a..f6c86635b1fdb 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2438,8 +2438,7 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) MOVStreamContext *sc; int pseudo_stream_id; - if (c->fc->nb_streams < 1) - return 0; + av_assert0 (c->fc->nb_streams >= 1); st = c->fc->streams[c->fc->nb_streams-1]; sc = st->priv_data; From 97c00edaa043043c29d985653e7e1687b56dfa23 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 20 Nov 2017 18:45:45 +0100 Subject: [PATCH 1140/2557] avcodec/mlpdsp: Fix signed integer overflow, 2nd try The outputted bits should match what is used in the lossless check Fixes: runtime error: signed integer overflow: -538697856 * 256 cannot be represented in type 'int' Fixes: 4326/clusterfuzz-testcase-minimized-5689449645080576 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/mlpdsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mlpdsp.c b/libavcodec/mlpdsp.c index 4e3a16c781c4f..32a4503b64ebe 100644 --- a/libavcodec/mlpdsp.c +++ b/libavcodec/mlpdsp.c @@ -117,7 +117,7 @@ int32_t ff_mlp_pack_output(int32_t lossless_check_data, (1U << output_shift[mat_ch]); lossless_check_data ^= (sample & 0xffffff) << mat_ch; if (is32) - *data_32++ = sample * 256; + *data_32++ = sample * 256U; else *data_16++ = sample >> 8; } From 8e7ac4f04903464e78b2cf374e0eacd1b531be18 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 22 Oct 2017 01:19:59 +0200 Subject: [PATCH 1141/2557] tests/fate-run: Use -bitexact Signed-off-by: Michael Niedermayer --- tests/fate-run.sh | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/fate-run.sh b/tests/fate-run.sh index e8d2e677091f8..05f4ca5e20bcf 100755 --- a/tests/fate-run.sh +++ b/tests/fate-run.sh @@ -127,15 +127,15 @@ ffmpeg(){ } framecrc(){ - ffmpeg "$@" -flags +bitexact -fflags +bitexact -f framecrc - + ffmpeg "$@" -bitexact -f framecrc - } ffmetadata(){ - ffmpeg "$@" -flags +bitexact -fflags +bitexact -f ffmetadata - + ffmpeg "$@" -bitexact -f ffmetadata - } framemd5(){ - ffmpeg "$@" -flags +bitexact -fflags +bitexact -f framemd5 - + ffmpeg "$@" -bitexact -f framemd5 - } crc(){ @@ -160,7 +160,7 @@ pcm(){ fmtstdout(){ fmt=$1 shift 1 - ffmpeg -flags +bitexact -fflags +bitexact "$@" -f $fmt - + ffmpeg -bitexact "$@" -f $fmt - } enc_dec_pcm(){ @@ -173,7 +173,7 @@ enc_dec_pcm(){ cleanfiles=$encfile encfile=$(target_path ${encfile}) ffmpeg -i $src_file "$@" -f $out_fmt -y ${encfile} || return - ffmpeg -flags +bitexact -fflags +bitexact -i ${encfile} -c:a pcm_${pcm_fmt} -fflags +bitexact -f ${dec_fmt} - + ffmpeg -bitexact -i ${encfile} -c:a pcm_${pcm_fmt} -fflags +bitexact -f ${dec_fmt} - } FLAGS="-flags +bitexact -sws_flags +accurate_rnd+bitexact -fflags +bitexact" @@ -294,16 +294,16 @@ gapless(){ cleanfiles="$cleanfiles $decfile1 $decfile2 $decfile3" # test packet data - ffmpeg $extra_args -i "$sample" -flags +bitexact -fflags +bitexact -c:a copy -f framecrc -y $decfile1 + ffmpeg $extra_args -i "$sample" -bitexact -c:a copy -f framecrc -y $decfile1 do_md5sum $decfile1 # test decoded (and cut) data - ffmpeg $extra_args -i "$sample" -flags +bitexact -fflags +bitexact -f wav md5: + ffmpeg $extra_args -i "$sample" -bitexact -f wav md5: # the same as above again, with seeking to the start - ffmpeg $extra_args -ss 0 -seek_timestamp 1 -i "$sample" -flags +bitexact -fflags +bitexact -c:a copy -f framecrc -y $decfile2 + ffmpeg $extra_args -ss 0 -seek_timestamp 1 -i "$sample" -bitexact -c:a copy -f framecrc -y $decfile2 do_md5sum $decfile2 - ffmpeg $extra_args -ss 0 -seek_timestamp 1 -i "$sample" -flags +bitexact -fflags +bitexact -f wav md5: + ffmpeg $extra_args -ss 0 -seek_timestamp 1 -i "$sample" -bitexact -f wav md5: # test packet data, with seeking to a specific position - ffmpeg $extra_args -ss 5 -seek_timestamp 1 -i "$sample" -flags +bitexact -fflags +bitexact -c:a copy -f framecrc -y $decfile3 + ffmpeg $extra_args -ss 5 -seek_timestamp 1 -i "$sample" -bitexact -c:a copy -f framecrc -y $decfile3 do_md5sum $decfile3 } @@ -316,7 +316,7 @@ gaplessenc(){ cleanfiles="$cleanfiles $file1" # test data after reencoding - ffmpeg -i "$sample" -flags +bitexact -fflags +bitexact -map 0:a -c:a $codec -f $format -y "$file1" + ffmpeg -i "$sample" -bitexact -map 0:a -c:a $codec -f $format -y "$file1" probegaplessinfo "$file1" } @@ -328,7 +328,7 @@ audio_match(){ decfile="${outdir}/${test}.wav" cleanfiles="$cleanfiles $decfile" - ffmpeg -i "$sample" -flags +bitexact -fflags +bitexact $extra_args -y $decfile + ffmpeg -i "$sample" -bitexact $extra_args -y $decfile tests/audiomatch $decfile $trefile } From b93d96a07be40f8e5d267d55fe961285586c0fd7 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Sun, 26 Nov 2017 20:40:32 -0800 Subject: [PATCH 1142/2557] avcodec/nvdec: Make vp8 initialisation more 'compatible' Ancient versions of gcc (pre 4.6) can't directly initialise members of anonymous inner unions/structs by name. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=10676 Unfortunately, RHEL 6 shipped with one of these ancient versions and so we're stuck with it until approximately the heat death of the universe. Putting explicit braces into the initialisation is possibly a work-around but the behaviour there was never fully understood before direct initialisation was made to work. So, this may or may not work. --- libavcodec/nvdec_vp8.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/libavcodec/nvdec_vp8.c b/libavcodec/nvdec_vp8.c index ceb3de2c3a4f8..f29a66ac723eb 100644 --- a/libavcodec/nvdec_vp8.c +++ b/libavcodec/nvdec_vp8.c @@ -64,11 +64,20 @@ static int nvdec_vp8_start_frame(AVCodecContext *avctx, const uint8_t *buffer, u .LastRefIdx = safe_get_ref_idx(h->framep[VP56_FRAME_PREVIOUS]), .GoldenRefIdx = safe_get_ref_idx(h->framep[VP56_FRAME_GOLDEN]), .AltRefIdx = safe_get_ref_idx(h->framep[VP56_FRAME_GOLDEN2]), - - .frame_type = !h->keyframe, - .version = h->profile, - .show_frame = !h->invisible, - .update_mb_segmentation_data = h->segmentation.enabled ? h->segmentation.update_feature_data : 0, + /* + * Explicit braces for anonymous inners to work around limitations + * in ancient versions of gcc. + */ + { + { + .frame_type = !h->keyframe, + .version = h->profile, + .show_frame = !h->invisible, + .update_mb_segmentation_data = h->segmentation.enabled ? + h->segmentation.update_feature_data : + 0, + } + } } }; From 0e93694e64cdc72f7ccb8a986171593e672b8dba Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Sun, 26 Nov 2017 22:18:22 -0800 Subject: [PATCH 1143/2557] avcodec/nvdec: More effort to make vp8 compile with gcc < 4.6 I'm told my prefix work-around wasn't enough to make it compile, although I'm not sure why; I did some basic testing and that approach appeared to work, but I'm not in a position to do a full compile on CentOS 6 so I can't be sure of anything. I have had it confirmed that the additional change to not use named initialisers is enough to make it compile, so let's throw that into the mix too. --- libavcodec/nvdec_vp8.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/libavcodec/nvdec_vp8.c b/libavcodec/nvdec_vp8.c index f29a66ac723eb..7b37445613b13 100644 --- a/libavcodec/nvdec_vp8.c +++ b/libavcodec/nvdec_vp8.c @@ -65,20 +65,19 @@ static int nvdec_vp8_start_frame(AVCodecContext *avctx, const uint8_t *buffer, u .GoldenRefIdx = safe_get_ref_idx(h->framep[VP56_FRAME_GOLDEN]), .AltRefIdx = safe_get_ref_idx(h->framep[VP56_FRAME_GOLDEN2]), /* - * Explicit braces for anonymous inners to work around limitations - * in ancient versions of gcc. + * Explicit braces for anonymous inners and unnamed fields + * to work around limitations in ancient versions of gcc. */ - { - { - .frame_type = !h->keyframe, - .version = h->profile, - .show_frame = !h->invisible, - .update_mb_segmentation_data = h->segmentation.enabled ? - h->segmentation.update_feature_data : - 0, + { // union + { // struct + !h->keyframe, // frame_type + h->profile, // version + !h->invisible, // show_frame + h->segmentation.enabled ? // update_mb_segmentation_data + h->segmentation.update_feature_data : 0, } } - } + } }; return 0; From 26c0c84784f1f4e73e2de25b09b659781f06b0f2 Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Mon, 27 Nov 2017 09:13:05 +0100 Subject: [PATCH 1144/2557] avformat/avienc: fix fields-per-frame value for interlaced video streams Writes one set of field framing information for progressive streams and two sets for interlaced streams. Fixes ticket #6383. Unfortunately the OpenDML v1.02 document is not very specific on what value to use for start_line when frame data is not coming from a capturing device, so this is just using 0/1 depending on the field order as a best-effort guess. Signed-off-by: Tobias Rapp --- libavformat/avienc.c | 41 +++++++++++++++++++++++--------- libavformat/version.h | 2 +- tests/ref/fate/copy-trac2211-avi | 4 ++-- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/libavformat/avienc.c b/libavformat/avienc.c index 483f5b54b1464..ac0f04c3547fd 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -501,8 +501,14 @@ static int avi_write_header(AVFormatContext *s) AVRational dar = av_mul_q(st->sample_aspect_ratio, (AVRational) { par->width, par->height }); - int num, den; + int num, den, fields, i; av_reduce(&num, &den, dar.num, dar.den, 0xFFFF); + if (par->field_order == AV_FIELD_TT || par->field_order == AV_FIELD_BB || + par->field_order == AV_FIELD_TB || par->field_order == AV_FIELD_BT) { + fields = 2; // interlaced + } else { + fields = 1; // progressive + } avio_wl32(pb, 0); // video format = unknown avio_wl32(pb, 0); // video standard = unknown @@ -514,17 +520,30 @@ static int avi_write_header(AVFormatContext *s) avio_wl16(pb, num); avio_wl32(pb, par->width); avio_wl32(pb, par->height); - avio_wl32(pb, 1); // progressive FIXME - - avio_wl32(pb, par->height); - avio_wl32(pb, par->width); - avio_wl32(pb, par->height); - avio_wl32(pb, par->width); - avio_wl32(pb, 0); - avio_wl32(pb, 0); + avio_wl32(pb, fields); // fields per frame + + for (i = 0; i < fields; i++) { + int start_line; + // OpenDML v1.02 is not very specific on what value to use for + // start_line when frame data is not coming from a capturing device, + // so just use 0/1 depending on the field order for interlaced frames + if (par->field_order == AV_FIELD_TT || par->field_order == AV_FIELD_TB) { + start_line = (i == 0) ? 0 : 1; + } else if (par->field_order == AV_FIELD_BB || par->field_order == AV_FIELD_BT) { + start_line = (i == 0) ? 1 : 0; + } else { + start_line = 0; + } - avio_wl32(pb, 0); - avio_wl32(pb, 0); + avio_wl32(pb, par->height / fields); // compressed bitmap height + avio_wl32(pb, par->width); // compressed bitmap width + avio_wl32(pb, par->height / fields); // valid bitmap height + avio_wl32(pb, par->width); // valid bitmap width + avio_wl32(pb, 0); // valid bitmap X offset + avio_wl32(pb, 0); // valid bitmap Y offset + avio_wl32(pb, 0); // valid X offset in T + avio_wl32(pb, start_line); // valid Y start line + } ff_end_tag(pb, vprp); } diff --git a/libavformat/version.h b/libavformat/version.h index feb1461c416d2..7fe3710a2c741 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -33,7 +33,7 @@ // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 #define LIBAVFORMAT_VERSION_MINOR 2 -#define LIBAVFORMAT_VERSION_MICRO 102 +#define LIBAVFORMAT_VERSION_MICRO 103 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ diff --git a/tests/ref/fate/copy-trac2211-avi b/tests/ref/fate/copy-trac2211-avi index 007349e572752..06d81e537d983 100644 --- a/tests/ref/fate/copy-trac2211-avi +++ b/tests/ref/fate/copy-trac2211-avi @@ -1,5 +1,5 @@ -6f6b211cbc8de9871e8e09e64048e2f9 *tests/data/fate/copy-trac2211-avi.avi -1777924 tests/data/fate/copy-trac2211-avi.avi +0920978f3f8196413c43f0033b55a5b6 *tests/data/fate/copy-trac2211-avi.avi +1777956 tests/data/fate/copy-trac2211-avi.avi #tb 0: 1/14 #media_type 0: video #codec_id 0: rawvideo From 9152bda839c55b568d416d1188590646ac9196c4 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 27 Nov 2017 13:38:33 +0100 Subject: [PATCH 1145/2557] avfilter/af_silenceremove: fix logic error in EOF case Signed-off-by: Paul B Mahol --- libavfilter/af_silenceremove.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index af504630598e4..b9a9e13caf3f4 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -469,7 +469,7 @@ static int request_frame(AVFilterLink *outlink) (AVRational){1, outlink->sample_rate}, outlink->time_base); - ret = ff_filter_frame(ctx->inputs[0], frame); + ret = ff_filter_frame(outlink, frame); } s->mode = SILENCE_STOP; } From b7324950c0fc84a93d4e7abdfd2b75ea647ec3fc Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Mon, 27 Nov 2017 14:05:28 +0100 Subject: [PATCH 1146/2557] lavd/alsa: Double maximum alsa buffer size. Fixes recording from ATI Wonder 600 USB adapter, regression since e35c674d. Reported and analyzed by: Marco Paolieri, paolieri at gmail --- libavdevice/alsa.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/alsa.h b/libavdevice/alsa.h index cd41d965f700b..1ed8c82199267 100644 --- a/libavdevice/alsa.h +++ b/libavdevice/alsa.h @@ -43,7 +43,7 @@ typedef void (*ff_reorder_func)(const void *, void *, int); -#define ALSA_BUFFER_SIZE_MAX 65536 +#define ALSA_BUFFER_SIZE_MAX 131072 typedef struct AlsaData { AVClass *class; From 2d1594a8d6a754a426cb53184dccf9cf8c8a94b0 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 27 Nov 2017 16:32:54 +0100 Subject: [PATCH 1147/2557] avfilter/af_silenceremove: fix possible crash if supplied duration is negative Signed-off-by: Paul B Mahol --- libavfilter/af_silenceremove.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index b9a9e13caf3f4..d826a22e9dea6 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -186,8 +186,17 @@ static int config_input(AVFilterLink *inlink) s->start_duration = av_rescale(s->start_duration, inlink->sample_rate, AV_TIME_BASE); + if (s->start_duration < 0) { + av_log(ctx, AV_LOG_WARNING, "start duration must be non-negative\n"); + s->start_duration = -s->start_duration; + } + s->stop_duration = av_rescale(s->stop_duration, inlink->sample_rate, AV_TIME_BASE); + if (s->stop_duration < 0) { + av_log(ctx, AV_LOG_WARNING, "stop duration must be non-negative\n"); + s->stop_duration = -s->stop_duration; + } s->start_holdoff = av_malloc_array(FFMAX(s->start_duration, 1), sizeof(*s->start_holdoff) * From 9d464dc3fccb53f1e7c83e3453084c1a7fb90503 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 27 Nov 2017 13:39:42 -0300 Subject: [PATCH 1148/2557] avformat/matroskaenc: actually enforce the stream limit Prevents out of array accesses. Adressess ticket #6873 Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/matroskaenc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index dad6d6c93f1bd..06126781f8a7e 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -1859,6 +1859,13 @@ static int mkv_write_header(AVFormatContext *s) av_dict_get(s->metadata, "alpha_mode", NULL, 0)) version = 4; + if (s->nb_streams > MAX_TRACKS) { + av_log(s, AV_LOG_ERROR, + "At most %d streams are supported for muxing in Matroska\n", + MAX_TRACKS); + return AVERROR(EINVAL); + } + for (i = 0; i < s->nb_streams; i++) { if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_ATRAC3 || s->streams[i]->codecpar->codec_id == AV_CODEC_ID_COOK || From eb86f72fcaf3abd6c7d243d7c85ab0440f752be5 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 27 Nov 2017 18:04:39 +0100 Subject: [PATCH 1149/2557] avfilter/vf_threshold: use correct linesize Signed-off-by: Paul B Mahol --- libavfilter/vf_threshold.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_threshold.c b/libavfilter/vf_threshold.c index 88f6ef28d78f0..76c3ddb892ce6 100644 --- a/libavfilter/vf_threshold.c +++ b/libavfilter/vf_threshold.c @@ -155,7 +155,7 @@ static void threshold8(const uint8_t *in, const uint8_t *threshold, in += ilinesize; threshold += tlinesize; min += flinesize; - max += flinesize; + max += slinesize; out += olinesize; } } @@ -183,7 +183,7 @@ static void threshold16(const uint8_t *iin, const uint8_t *tthreshold, in += ilinesize / 2; threshold += tlinesize / 2; min += flinesize / 2; - max += flinesize / 2; + max += slinesize / 2; out += olinesize / 2; } } From 5b4baf1506277863e9c1fa4bd302a4653e859669 Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Mon, 27 Nov 2017 09:30:53 +0800 Subject: [PATCH 1150/2557] libavformat/rtpenc_mpegts: check avformat_new_stream() return value The function avformat_new_stream() returns a NULL pointer on failure. However, in function rtp_mpegts_write_header(), its return value is not validated before it is dereferenced. Check the return value against NULL to avoid potential NULL dereference. Signed-off-by: Pan Bian Signed-off-by: Michael Niedermayer --- libavformat/rtpenc_mpegts.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/rtpenc_mpegts.c b/libavformat/rtpenc_mpegts.c index 7af02e0d2fba2..5f81e1a14533a 100644 --- a/libavformat/rtpenc_mpegts.c +++ b/libavformat/rtpenc_mpegts.c @@ -85,6 +85,10 @@ static int rtp_mpegts_write_header(AVFormatContext *s) } rtp_ctx->oformat = rtp_format; st = avformat_new_stream(rtp_ctx, NULL); + if (!st) { + ret = AVERROR(ENOMEM); + goto fail; + } st->time_base.num = 1; st->time_base.den = 90000; st->codecpar->codec_id = AV_CODEC_ID_MPEG2TS; From 2ba6d7cb8278970bb9971448706c1e44ba043a81 Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Mon, 27 Nov 2017 09:12:54 +0800 Subject: [PATCH 1151/2557] ffmpeg: Check read_ffserver_streams() return value The function avformat_alloc_context() will return a NULL pointer on failure. However, in function read_ffserver_streams(), its return value is not validated and the subsequent dereference may result in a bad memory access bug. Check its return value against NULL and avoid potential NULL dereference. Signed-off-by: Pan Bian Signed-off-by: Michael Niedermayer --- fftools/ffmpeg_opt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 9445a2dd11823..672054223aebb 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -2000,6 +2000,8 @@ static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch { int i, err; AVFormatContext *ic = avformat_alloc_context(); + if (!ic) + return AVERROR(ENOMEM); ic->interrupt_callback = int_cb; err = avformat_open_input(&ic, filename, NULL, NULL); From 9924f1bc34242bb9315c355108f3ce744c1f33c5 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 27 Nov 2017 14:11:21 -0300 Subject: [PATCH 1152/2557] avformat/matroskaenc: move some initialization checks to mkv_init It's the correct place for them. Reviewed-by: Carl Eugen Hoyos Signed-off-by: James Almer --- libavformat/matroskaenc.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 06126781f8a7e..35857bb02edf9 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -1859,25 +1859,7 @@ static int mkv_write_header(AVFormatContext *s) av_dict_get(s->metadata, "alpha_mode", NULL, 0)) version = 4; - if (s->nb_streams > MAX_TRACKS) { - av_log(s, AV_LOG_ERROR, - "At most %d streams are supported for muxing in Matroska\n", - MAX_TRACKS); - return AVERROR(EINVAL); - } - for (i = 0; i < s->nb_streams; i++) { - if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_ATRAC3 || - s->streams[i]->codecpar->codec_id == AV_CODEC_ID_COOK || - s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RA_288 || - s->streams[i]->codecpar->codec_id == AV_CODEC_ID_SIPR || - s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV10 || - s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV20) { - av_log(s, AV_LOG_ERROR, - "The Matroska muxer does not yet support muxing %s\n", - avcodec_get_name(s->streams[i]->codecpar->codec_id)); - return AVERROR_PATCHWELCOME; - } if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_OPUS || av_dict_get(s->streams[i]->metadata, "stereo_mode", NULL, 0) || av_dict_get(s->streams[i]->metadata, "alpha_mode", NULL, 0)) @@ -2656,6 +2638,27 @@ static int mkv_init(struct AVFormatContext *s) { int i; + if (s->nb_streams > MAX_TRACKS) { + av_log(s, AV_LOG_ERROR, + "At most %d streams are supported for muxing in Matroska\n", + MAX_TRACKS); + return AVERROR(EINVAL); + } + + for (i = 0; i < s->nb_streams; i++) { + if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_ATRAC3 || + s->streams[i]->codecpar->codec_id == AV_CODEC_ID_COOK || + s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RA_288 || + s->streams[i]->codecpar->codec_id == AV_CODEC_ID_SIPR || + s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV10 || + s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV20) { + av_log(s, AV_LOG_ERROR, + "The Matroska muxer does not yet support muxing %s\n", + avcodec_get_name(s->streams[i]->codecpar->codec_id)); + return AVERROR_PATCHWELCOME; + } + } + if (s->avoid_negative_ts < 0) { s->avoid_negative_ts = 1; s->internal->avoid_negative_ts_use_pts = 1; From 5f67073b4cb12abf21ed840948b271903d61bf3b Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 28 Nov 2017 01:23:23 -0300 Subject: [PATCH 1153/2557] avformat/matroskaenc: add missing allocation failure checks for stream durations Signed-off-by: James Almer --- libavformat/matroskaenc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 35857bb02edf9..f22c2ab70cced 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -1965,6 +1965,10 @@ static int mkv_write_header(AVFormatContext *s) // initialize stream_duration fields mkv->stream_durations = av_mallocz(s->nb_streams * sizeof(int64_t)); mkv->stream_duration_offsets = av_mallocz(s->nb_streams * sizeof(int64_t)); + if (!mkv->stream_durations || !mkv->stream_duration_offsets) { + ret = AVERROR(ENOMEM); + goto fail; + } ret = mkv_write_tracks(s); if (ret < 0) From 1204ce0b6371f5b51efdfe84d1b5aa5925809186 Mon Sep 17 00:00:00 2001 From: Rodger Combs Date: Mon, 27 Nov 2017 23:38:46 -0600 Subject: [PATCH 1154/2557] lavu/hwcontext_opencl.h: fix build on macOS --- libavutil/hwcontext_opencl.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavutil/hwcontext_opencl.h b/libavutil/hwcontext_opencl.h index 8e34df44cd2e3..ef54486c95f00 100644 --- a/libavutil/hwcontext_opencl.h +++ b/libavutil/hwcontext_opencl.h @@ -19,7 +19,11 @@ #ifndef AVUTIL_HWCONTEXT_OPENCL_H #define AVUTIL_HWCONTEXT_OPENCL_H +#ifdef __APPLE__ +#include +#else #include +#endif #include "frame.h" From 1dff9adcb934175fe1beb14ee139ad0636daa29d Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Sun, 19 Nov 2017 19:30:02 +0200 Subject: [PATCH 1155/2557] avformat/hls: Factor playlist need check to a common function --- libavformat/hls.c | 52 +++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 786934af032f3..4f8f6b0a80e43 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -111,7 +111,7 @@ struct playlist { int start_seq_no; int n_segments; struct segment **segments; - int needed, cur_needed; + int needed; int cur_seq_no; int64_t cur_seg_offset; int64_t last_load_time; @@ -1258,11 +1258,31 @@ static int64_t default_reload_interval(struct playlist *pls) pls->target_duration; } +static int playlist_needed(struct playlist *pls) +{ + int i; + + /* If there is no context or streams yet, the playlist is needed */ + if (!pls->ctx || !pls->n_main_streams) + return 1; + + /* check if any of the streams in the playlist are needed */ + for (i = 0; i < pls->n_main_streams; i++) { + if (pls->main_streams[i]->discard < AVDISCARD_ALL) { + /* some stream needed => playlist needed */ + return 1; + } + } + + /* No streams were needed */ + return 0; +} + static int read_data(void *opaque, uint8_t *buf, int buf_size) { struct playlist *v = opaque; HLSContext *c = v->parent->priv_data; - int ret, i; + int ret; int just_opened = 0; int reload_count = 0; @@ -1276,15 +1296,8 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) /* Check that the playlist is still needed before opening a new * segment. */ - if (v->ctx && v->ctx->nb_streams) { - v->needed = 0; - for (i = 0; i < v->n_main_streams; i++) { - if (v->main_streams[i]->discard < AVDISCARD_ALL) { - v->needed = 1; - break; - } - } - } + v->needed = playlist_needed(v); + if (!v->needed) { av_log(v->parent, AV_LOG_INFO, "No longer receiving playlist %d\n", v->index); @@ -1841,20 +1854,15 @@ static int recheck_discard_flags(AVFormatContext *s, int first) { HLSContext *c = s->priv_data; int i, changed = 0; + int cur_needed; /* Check if any new streams are needed */ - for (i = 0; i < c->n_playlists; i++) - c->playlists[i]->cur_needed = 0; - - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - struct playlist *pls = c->playlists[s->streams[i]->id]; - if (st->discard < AVDISCARD_ALL) - pls->cur_needed = 1; - } for (i = 0; i < c->n_playlists; i++) { struct playlist *pls = c->playlists[i]; - if (pls->cur_needed && !pls->needed) { + + cur_needed = playlist_needed(c->playlists[i]); + + if (cur_needed && !pls->needed) { pls->needed = 1; changed = 1; pls->cur_seq_no = select_cur_seq_no(c, pls); @@ -1866,7 +1874,7 @@ static int recheck_discard_flags(AVFormatContext *s, int first) pls->seek_stream_index = -1; } av_log(s, AV_LOG_INFO, "Now receiving playlist %d, segment %d\n", i, pls->cur_seq_no); - } else if (first && !pls->cur_needed && pls->needed) { + } else if (first && !cur_needed && pls->needed) { if (pls->input) ff_format_io_close(pls->parent, &pls->input); pls->needed = 0; From 143552095dae9698f3779e93dd08548f46dc5686 Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Sun, 19 Nov 2017 20:11:49 +0200 Subject: [PATCH 1156/2557] avformat/hls: Obey AVProgram discard flags Currently HLS demuxer only obeys AVStream discard flags but not AVProgram (which bandwidth variants appear as) discard flags. Fix that. --- libavformat/hls.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 4f8f6b0a80e43..ab6ff187a684e 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1260,7 +1260,10 @@ static int64_t default_reload_interval(struct playlist *pls) static int playlist_needed(struct playlist *pls) { - int i; + AVFormatContext *s = pls->parent; + int i, j; + int stream_needed = 0; + int first_st; /* If there is no context or streams yet, the playlist is needed */ if (!pls->ctx || !pls->n_main_streams) @@ -1269,12 +1272,35 @@ static int playlist_needed(struct playlist *pls) /* check if any of the streams in the playlist are needed */ for (i = 0; i < pls->n_main_streams; i++) { if (pls->main_streams[i]->discard < AVDISCARD_ALL) { - /* some stream needed => playlist needed */ - return 1; + stream_needed = 1; + break; + } + } + + /* If all streams in the playlist were discarded, the playlist is not + * needed (regardless of whether whole programs are discarded or not). */ + if (!stream_needed) + return 0; + + /* Otherwise, check if all the programs (variants) this playlist is in are + * discarded. Since all streams in the playlist are part of the same programs + * we can just check the programs of the first stream. */ + + first_st = pls->main_streams[0]->index; + + for (i = 0; i < s->nb_programs; i++) { + AVProgram *program = s->programs[i]; + if (program->discard < AVDISCARD_ALL) { + for (j = 0; j < program->nb_stream_indexes; j++) { + if (program->stream_index[j] == first_st) { + /* playlist is in an undiscarded program */ + return 1; + } + } } } - /* No streams were needed */ + /* some streams were not discarded but all the programs were */ return 0; } From d5d2632e3a0f1709290834fd35457cd05cf48bc8 Mon Sep 17 00:00:00 2001 From: Karthick J Date: Tue, 28 Nov 2017 20:03:15 +0800 Subject: [PATCH 1157/2557] avformat/hlsenc: Fixed initial setting for end_pts This patch fixes Bug #6868 Sometimes end_pts is getting initialized to audio stream's first pts, while the duration is calculated based on video stream's pts. In this patch the end_pts is initialized with the correct stream's first pts. Reviewed-by: Steven Liu Tested-by: beloko --- libavformat/hlsenc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 30ccf73d76e77..6997a5ced0dd6 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1737,6 +1737,7 @@ static int hls_write_header(AVFormatContext *s) vs->sequence = hls->start_sequence; hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE; vs->start_pts = AV_NOPTS_VALUE; + vs->end_pts = AV_NOPTS_VALUE; vs->current_segment_final_filename_fmt[0] = '\0'; if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) { @@ -2111,7 +2112,6 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) if (vs->start_pts == AV_NOPTS_VALUE) { vs->start_pts = pkt->pts; - vs->end_pts = pkt->pts; } if (vs->has_video) { @@ -2123,6 +2123,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) is_ref_pkt = can_split = 0; if (is_ref_pkt) { + if (vs->end_pts == AV_NOPTS_VALUE) + vs->end_pts = pkt->pts; if (vs->new_start) { vs->new_start = 0; vs->duration = (double)(pkt->pts - vs->end_pts) From b5d56d8ef1ef17487d827f1e35d02501f55218de Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 28 Nov 2017 08:49:21 -0800 Subject: [PATCH 1158/2557] avcodec/videotoolbox: fix SEGV when hwaccel decoding h264 with ffmpeg.c Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index c275e0111ec8e..afec1edf3f6a7 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -119,7 +119,8 @@ CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx) // save sps header (profile/level) used to create decoder session, // so we can detect changes and recreate it. - memcpy(vtctx->sps, h->ps.sps->data + 1, 3); + if (vtctx) + memcpy(vtctx->sps, h->ps.sps->data + 1, 3); data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size); av_free(vt_extradata); @@ -323,6 +324,11 @@ static int videotoolbox_h264_decode_params(AVCodecContext *avctx, uint32_t size) { VTContext *vtctx = avctx->internal->hwaccel_priv_data; + H264Context *h = avctx->priv_data; + + // save sps header (profile/level) used to create decoder session + if (!vtctx->sps[0]) + memcpy(vtctx->sps, h->ps.sps->data + 1, 3); if (type == H264_NAL_SPS) { if (size > 4 && memcmp(vtctx->sps, buffer + 1, 3) != 0) { From 755207dc53d6d18a4a9e07ffb0d3a10f75836f79 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 27 Sep 2017 15:52:52 -0400 Subject: [PATCH 1159/2557] prores: Always assume limited range As defined by the specification. --- libavcodec/proresdec_lgpl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/proresdec_lgpl.c b/libavcodec/proresdec_lgpl.c index bc5bdb5a4d5ee..c86d433f50728 100644 --- a/libavcodec/proresdec_lgpl.c +++ b/libavcodec/proresdec_lgpl.c @@ -177,6 +177,7 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, avctx->color_primaries = buf[14]; avctx->color_trc = buf[15]; avctx->colorspace = buf[16]; + avctx->color_range = AVCOL_RANGE_MPEG; ctx->qmat_changed = 0; ptr = buf + 20; From 10db42f117ed5cb5b662eef619ee6a92d868095a Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 4 Oct 2017 14:47:54 -0400 Subject: [PATCH 1160/2557] mov: Support mdcv and clli boxes for mastering display an color light level Signed-off-by: Vittorio Giovara --- libavformat/mov.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index f6c86635b1fdb..b3b800f898ea6 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -5081,6 +5081,51 @@ static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + MOVStreamContext *sc; + const int mapping[3] = {1, 2, 0}; + const int chroma_den = 50000; + const int luma_den = 10000; + int i; + + if (c->fc->nb_streams < 1) + return AVERROR_INVALIDDATA; + + sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data; + + if (atom.size < 24) { + av_log(c->fc, AV_LOG_ERROR, "Invalid Mastering Display Color Volume box\n"); + return AVERROR_INVALIDDATA; + } + + sc->mastering = av_mastering_display_metadata_alloc(); + if (!sc->mastering) + return AVERROR(ENOMEM); + + for (i = 0; i < 3; i++) { + const int j = mapping[i]; + sc->mastering->display_primaries[j][0].num = avio_rb16(pb); + sc->mastering->display_primaries[j][0].den = chroma_den; + sc->mastering->display_primaries[j][1].num = avio_rb16(pb); + sc->mastering->display_primaries[j][1].den = chroma_den; + } + sc->mastering->white_point[0].num = avio_rb16(pb); + sc->mastering->white_point[0].den = chroma_den; + sc->mastering->white_point[1].num = avio_rb16(pb); + sc->mastering->white_point[1].den = chroma_den; + + sc->mastering->max_luminance.num = avio_rb32(pb); + sc->mastering->max_luminance.den = luma_den; + sc->mastering->min_luminance.num = avio_rb32(pb); + sc->mastering->min_luminance.den = luma_den; + + sc->mastering->has_luminance = 1; + sc->mastering->has_primaries = 1; + + return 0; +} + static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom) { MOVStreamContext *sc; @@ -5113,6 +5158,30 @@ static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_clli(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + MOVStreamContext *sc; + + if (c->fc->nb_streams < 1) + return AVERROR_INVALIDDATA; + + sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data; + + if (atom.size < 4) { + av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level Info box\n"); + return AVERROR_INVALIDDATA; + } + + sc->coll = av_content_light_metadata_alloc(&sc->coll_size); + if (!sc->coll) + return AVERROR(ENOMEM); + + sc->coll->MaxCLL = avio_rb16(pb); + sc->coll->MaxFALL = avio_rb16(pb); + + return 0; +} + static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; @@ -5921,6 +5990,8 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('S','m','D','m'), mov_read_smdm }, { MKTAG('C','o','L','L'), mov_read_coll }, { MKTAG('v','p','c','C'), mov_read_vpcc }, +{ MKTAG('m','d','c','v'), mov_read_mdcv }, +{ MKTAG('c','l','l','i'), mov_read_clli }, { 0, NULL } }; From 3e0560b054dd4f548f41e5fb69b6350858e6d88d Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Tue, 28 Nov 2017 13:55:47 -0500 Subject: [PATCH 1161/2557] vf_zscale: Relax color properties maximum bounds This simplifies adding new values, which are already validated elsewhere. Signed-off-by: Vittorio Giovara --- libavfilter/vf_zscale.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libavfilter/vf_zscale.c b/libavfilter/vf_zscale.c index 09fd842fe55ba..972f720ee6507 100644 --- a/libavfilter/vf_zscale.c +++ b/libavfilter/vf_zscale.c @@ -735,8 +735,8 @@ static const AVOption zscale_options[] = { { "unknown", 0, 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, FLAGS, "range" }, { "tv", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_RANGE_LIMITED}, 0, 0, FLAGS, "range" }, { "pc", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_RANGE_FULL}, 0, 0, FLAGS, "range" }, - { "primaries", "set color primaries", OFFSET(primaries), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_PRIMARIES_ST432_1, FLAGS, "primaries" }, - { "p", "set color primaries", OFFSET(primaries), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_PRIMARIES_ST432_1, FLAGS, "primaries" }, + { "primaries", "set color primaries", OFFSET(primaries), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "primaries" }, + { "p", "set color primaries", OFFSET(primaries), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "primaries" }, { "input", 0, 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, FLAGS, "primaries" }, { "709", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_709}, 0, 0, FLAGS, "primaries" }, { "unspecified", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_UNSPECIFIED}, 0, 0, FLAGS, "primaries" }, @@ -749,8 +749,8 @@ static const AVOption zscale_options[] = { { "smpte240m", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_240M}, 0, 0, FLAGS, "primaries" }, { "bt2020", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_2020}, 0, 0, FLAGS, "primaries" }, { "smpte432", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_ST432_1}, 0, 0, FLAGS, "primaries" }, - { "transfer", "set transfer characteristic", OFFSET(trc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_TRANSFER_ARIB_B67, FLAGS, "transfer" }, - { "t", "set transfer characteristic", OFFSET(trc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_TRANSFER_ARIB_B67, FLAGS, "transfer" }, + { "transfer", "set transfer characteristic", OFFSET(trc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "transfer" }, + { "t", "set transfer characteristic", OFFSET(trc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "transfer" }, { "input", 0, 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, FLAGS, "transfer" }, { "709", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_709}, 0, 0, FLAGS, "transfer" }, { "unspecified", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_UNSPECIFIED}, 0, 0, FLAGS, "transfer" }, @@ -767,8 +767,8 @@ static const AVOption zscale_options[] = { { "smpte2084", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_ST2084}, 0, 0, FLAGS, "transfer" }, { "iec61966-2-1", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_IEC_61966_2_1},0, 0, FLAGS, "transfer" }, { "arib-std-b67", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_ARIB_B67}, 0, 0, FLAGS, "transfer" }, - { "matrix", "set colorspace matrix", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_MATRIX_2020_CL, FLAGS, "matrix" }, - { "m", "set colorspace matrix", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_MATRIX_2020_CL, FLAGS, "matrix" }, + { "matrix", "set colorspace matrix", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "matrix" }, + { "m", "set colorspace matrix", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "matrix" }, { "input", 0, 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, FLAGS, "matrix" }, { "709", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_709}, 0, 0, FLAGS, "matrix" }, { "unspecified", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_UNSPECIFIED}, 0, 0, FLAGS, "matrix" }, @@ -786,12 +786,12 @@ static const AVOption zscale_options[] = { { "in_range", "set input color range", OFFSET(range_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_RANGE_FULL, FLAGS, "range" }, { "rangein", "set input color range", OFFSET(range_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_RANGE_FULL, FLAGS, "range" }, { "rin", "set input color range", OFFSET(range_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_RANGE_FULL, FLAGS, "range" }, - { "primariesin", "set input color primaries", OFFSET(primaries_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_PRIMARIES_ST432_1, FLAGS, "primaries" }, - { "pin", "set input color primaries", OFFSET(primaries_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_PRIMARIES_ST432_1, FLAGS, "primaries" }, - { "transferin", "set input transfer characteristic", OFFSET(trc_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_TRANSFER_ARIB_B67, FLAGS, "transfer" }, - { "tin", "set input transfer characteristic", OFFSET(trc_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_TRANSFER_ARIB_B67, FLAGS, "transfer" }, - { "matrixin", "set input colorspace matrix", OFFSET(colorspace_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_MATRIX_2020_CL, FLAGS, "matrix" }, - { "min", "set input colorspace matrix", OFFSET(colorspace_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_MATRIX_2020_CL, FLAGS, "matrix" }, + { "primariesin", "set input color primaries", OFFSET(primaries_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "primaries" }, + { "pin", "set input color primaries", OFFSET(primaries_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "primaries" }, + { "transferin", "set input transfer characteristic", OFFSET(trc_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "transfer" }, + { "tin", "set input transfer characteristic", OFFSET(trc_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "transfer" }, + { "matrixin", "set input colorspace matrix", OFFSET(colorspace_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "matrix" }, + { "min", "set input colorspace matrix", OFFSET(colorspace_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "matrix" }, { "chromal", "set output chroma location", OFFSET(chromal), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_CHROMA_BOTTOM, FLAGS, "chroma" }, { "c", "set output chroma location", OFFSET(chromal), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_CHROMA_BOTTOM, FLAGS, "chroma" }, { "input", 0, 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, FLAGS, "chroma" }, From 002db7d49ada290db15334b7b41fa27eb376ec5c Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Tue, 28 Nov 2017 13:56:06 -0500 Subject: [PATCH 1162/2557] vf_zscale: Add more supported input properties Bump the minimum version necessary in the configure file. Signed-off-by: Vittorio Giovara --- configure | 2 +- libavfilter/vf_zscale.c | 51 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 6748ef8bc9af2..28902d41f5bca 100755 --- a/configure +++ b/configure @@ -5929,7 +5929,7 @@ enabled libx265 && require_pkg_config libx265 x265 x265.h x265_api_get require_cpp_condition x265.h "X265_BUILD >= 68" enabled libxavs && require libxavs "stdint.h xavs.h" xavs_encoder_encode "-lxavs $pthreads_extralibs $libm_extralibs" enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore -enabled libzimg && require_pkg_config libzimg "zimg >= 2.3.0" zimg.h zimg_get_api_version +enabled libzimg && require_pkg_config libzimg "zimg >= 2.6.2" zimg.h zimg_get_api_version enabled libzmq && require_pkg_config libzmq libzmq zmq.h zmq_ctx_new enabled libzvbi && require_pkg_config libzvbi zvbi-0.2 libzvbi.h vbi_decoder_new && { check_cpp_condition libzvbi.h "VBI_VERSION_MAJOR > 0 || VBI_VERSION_MINOR > 2 || VBI_VERSION_MINOR == 2 && VBI_VERSION_MICRO >= 28" || diff --git a/libavfilter/vf_zscale.c b/libavfilter/vf_zscale.c index 972f720ee6507..865910bd876f4 100644 --- a/libavfilter/vf_zscale.c +++ b/libavfilter/vf_zscale.c @@ -353,16 +353,26 @@ static int convert_matrix(enum AVColorSpace colorspace) return ZIMG_MATRIX_709; case AVCOL_SPC_UNSPECIFIED: return ZIMG_MATRIX_UNSPECIFIED; + case AVCOL_SPC_FCC: + return ZIMG_MATRIX_FCC; case AVCOL_SPC_BT470BG: return ZIMG_MATRIX_470BG; case AVCOL_SPC_SMPTE170M: return ZIMG_MATRIX_170M; + case AVCOL_SPC_SMPTE240M: + return ZIMG_MATRIX_240M; case AVCOL_SPC_YCGCO: return ZIMG_MATRIX_YCGCO; case AVCOL_SPC_BT2020_NCL: return ZIMG_MATRIX_2020_NCL; case AVCOL_SPC_BT2020_CL: return ZIMG_MATRIX_2020_CL; + case AVCOL_SPC_CHROMA_DERIVED_NCL: + return ZIMG_MATRIX_CHROMATICITY_DERIVED_NCL; + case AVCOL_SPC_CHROMA_DERIVED_CL: + return ZIMG_MATRIX_CHROMATICITY_DERIVED_CL; + case AVCOL_SPC_ICTCP: + return ZIMG_MATRIX_ICTCP; } return ZIMG_MATRIX_UNSPECIFIED; } @@ -374,10 +384,22 @@ static int convert_trc(enum AVColorTransferCharacteristic color_trc) return ZIMG_TRANSFER_UNSPECIFIED; case AVCOL_TRC_BT709: return ZIMG_TRANSFER_709; + case AVCOL_TRC_GAMMA22: + return ZIMG_TRANSFER_470_M; + case AVCOL_TRC_GAMMA28: + return ZIMG_TRANSFER_470_BG; case AVCOL_TRC_SMPTE170M: return ZIMG_TRANSFER_601; + case AVCOL_TRC_SMPTE240M: + return ZIMG_TRANSFER_240M; case AVCOL_TRC_LINEAR: return ZIMG_TRANSFER_LINEAR; + case AVCOL_TRC_LOG: + return ZIMG_TRANSFER_LOG_100; + case AVCOL_TRC_LOG_SQRT: + return ZIMG_TRANSFER_LOG_316; + case AVCOL_TRC_IEC61966_2_4: + return ZIMG_TRANSFER_IEC_61966_2_4; case AVCOL_TRC_BT2020_10: return ZIMG_TRANSFER_2020_10; case AVCOL_TRC_BT2020_12: @@ -399,14 +421,26 @@ static int convert_primaries(enum AVColorPrimaries color_primaries) return ZIMG_PRIMARIES_UNSPECIFIED; case AVCOL_PRI_BT709: return ZIMG_PRIMARIES_709; + case AVCOL_PRI_BT470M: + return ZIMG_PRIMARIES_470_M; + case AVCOL_PRI_BT470BG: + return ZIMG_PRIMARIES_470_BG; case AVCOL_PRI_SMPTE170M: return ZIMG_PRIMARIES_170M; case AVCOL_PRI_SMPTE240M: return ZIMG_PRIMARIES_240M; + case AVCOL_PRI_FILM: + return ZIMG_PRIMARIES_FILM; case AVCOL_PRI_BT2020: return ZIMG_PRIMARIES_2020; + case AVCOL_PRI_SMPTE428: + return ZIMG_PRIMARIES_ST428; + case AVCOL_PRI_SMPTE431: + return ZIMG_PRIMARIES_ST431_2; case AVCOL_PRI_SMPTE432: return ZIMG_PRIMARIES_ST432_1; + case AVCOL_PRI_JEDEC_P22: + return ZIMG_PRIMARIES_EBU3213_E; } return ZIMG_PRIMARIES_UNSPECIFIED; } @@ -745,10 +779,16 @@ static const AVOption zscale_options[] = { { "2020", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_2020}, 0, 0, FLAGS, "primaries" }, { "unknown", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_UNSPECIFIED}, 0, 0, FLAGS, "primaries" }, { "bt709", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_709}, 0, 0, FLAGS, "primaries" }, + { "bt470m", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_470_M}, 0, 0, FLAGS, "primaries" }, + { "bt470bg", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_470_BG}, 0, 0, FLAGS, "primaries" }, { "smpte170m", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_170M}, 0, 0, FLAGS, "primaries" }, { "smpte240m", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_240M}, 0, 0, FLAGS, "primaries" }, + { "film", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_FILM}, 0, 0, FLAGS, "primaries" }, { "bt2020", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_2020}, 0, 0, FLAGS, "primaries" }, + { "smpte428", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_ST428}, 0, 0, FLAGS, "primaries" }, + { "smpte431", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_ST431_2}, 0, 0, FLAGS, "primaries" }, { "smpte432", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_ST432_1}, 0, 0, FLAGS, "primaries" }, + { "jedec-p22", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_EBU3213_E}, 0, 0, FLAGS, "primaries" }, { "transfer", "set transfer characteristic", OFFSET(trc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "transfer" }, { "t", "set transfer characteristic", OFFSET(trc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "transfer" }, { "input", 0, 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, FLAGS, "transfer" }, @@ -759,12 +799,17 @@ static const AVOption zscale_options[] = { { "2020_10", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_2020_10}, 0, 0, FLAGS, "transfer" }, { "2020_12", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_2020_12}, 0, 0, FLAGS, "transfer" }, { "unknown", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_UNSPECIFIED}, 0, 0, FLAGS, "transfer" }, + { "bt470m", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_470_M}, 0, 0, FLAGS, "transfer" }, + { "bt470bg", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_470_BG}, 0, 0, FLAGS, "transfer" }, { "smpte170m", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_601}, 0, 0, FLAGS, "transfer" }, { "bt709", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_709}, 0, 0, FLAGS, "transfer" }, { "linear", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_LINEAR}, 0, 0, FLAGS, "transfer" }, + { "log100", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_LOG_100}, 0, 0, FLAGS, "transfer" }, + { "log316", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_LOG_316}, 0, 0, FLAGS, "transfer" }, { "bt2020-10", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_2020_10}, 0, 0, FLAGS, "transfer" }, { "bt2020-12", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_2020_12}, 0, 0, FLAGS, "transfer" }, { "smpte2084", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_ST2084}, 0, 0, FLAGS, "transfer" }, + { "iec61966-2-4", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_IEC_61966_2_4},0, 0, FLAGS, "transfer" }, { "iec61966-2-1", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_IEC_61966_2_1},0, 0, FLAGS, "transfer" }, { "arib-std-b67", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_TRANSFER_ARIB_B67}, 0, 0, FLAGS, "transfer" }, { "matrix", "set colorspace matrix", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "matrix" }, @@ -777,12 +822,18 @@ static const AVOption zscale_options[] = { { "2020_ncl", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_2020_NCL}, 0, 0, FLAGS, "matrix" }, { "2020_cl", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_2020_CL}, 0, 0, FLAGS, "matrix" }, { "unknown", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_UNSPECIFIED}, 0, 0, FLAGS, "matrix" }, + { "gbr", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_RGB}, 0, 0, FLAGS, "matrix" }, { "bt709", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_709}, 0, 0, FLAGS, "matrix" }, + { "fcc", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_FCC}, 0, 0, FLAGS, "matrix" }, { "bt470bg", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_470BG}, 0, 0, FLAGS, "matrix" }, { "smpte170m", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_170M}, 0, 0, FLAGS, "matrix" }, + { "smpte2400m", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_240M}, 0, 0, FLAGS, "matrix" }, { "ycgco", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_YCGCO}, 0, 0, FLAGS, "matrix" }, { "bt2020nc", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_2020_NCL}, 0, 0, FLAGS, "matrix" }, { "bt2020c", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_2020_CL}, 0, 0, FLAGS, "matrix" }, + { "chroma-derived-nc",0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_CHROMATICITY_DERIVED_NCL}, 0, 0, FLAGS, "matrix" }, + { "chroma-derived-c", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_CHROMATICITY_DERIVED_CL}, 0, 0, FLAGS, "matrix" }, + { "ictcp", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_MATRIX_ICTCP}, 0, 0, FLAGS, "matrix" }, { "in_range", "set input color range", OFFSET(range_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_RANGE_FULL, FLAGS, "range" }, { "rangein", "set input color range", OFFSET(range_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_RANGE_FULL, FLAGS, "range" }, { "rin", "set input color range", OFFSET(range_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_RANGE_FULL, FLAGS, "range" }, From 45d7be7f930cf707ead07416e10e2d0e061e99ce Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 27 Sep 2017 17:28:55 -0400 Subject: [PATCH 1163/2557] prores: Always assume limited range As defined by the specification. --- libavcodec/proresdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/proresdec.c b/libavcodec/proresdec.c index 8a53719d9fae9..1659927e66baf 100644 --- a/libavcodec/proresdec.c +++ b/libavcodec/proresdec.c @@ -176,6 +176,7 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, avctx->color_primaries = buf[14]; avctx->color_trc = buf[15]; avctx->colorspace = buf[16]; + avctx->color_range = AVCOL_RANGE_MPEG; ctx->qmat_changed = 0; ptr = buf + 20; From 99e9697e3a12ab4a6638a36b95edafd6a98f9eaa Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 25 Sep 2017 15:09:21 +0200 Subject: [PATCH 1164/2557] stereo3d: Support view type for frame sequence type Implement detection in h264 and hevc and insertion in framepack filter. Signed-off-by: Vittorio Giovara --- doc/APIchanges | 3 +++ libavcodec/h264_sei.c | 7 ++++--- libavcodec/h264_sei.h | 1 + libavcodec/h264_slice.c | 7 +++++++ libavcodec/hevc_sei.c | 9 +++++---- libavcodec/hevc_sei.h | 1 + libavcodec/hevcdec.c | 7 +++++++ libavfilter/vf_framepack.c | 2 ++ libavutil/stereo3d.h | 24 ++++++++++++++++++++++++ libavutil/version.h | 2 +- 10 files changed, 55 insertions(+), 8 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 9f3a1f2465810..a7ecbcdaaed40 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2017-03-23 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavu 56.7.0 - stereo3d.h + Add view field to AVStereo3D structure and AVStereo3DView enum. + 2017-xx-xx - xxxxxxx - lavc 58.5.0 - avcodec.h Add avcodec_get_hw_frames_parameters(). diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c index 03fca9017f9d1..da5d33c36c8de 100644 --- a/libavcodec/h264_sei.c +++ b/libavcodec/h264_sei.c @@ -314,10 +314,11 @@ static int decode_frame_packing_arrangement(H264SEIFramePacking *h, h->quincunx_subsampling = get_bits1(gb); h->content_interpretation_type = get_bits(gb, 6); - // the following skips: spatial_flipping_flag, frame0_flipped_flag, - // field_views_flag, current_frame_is_frame0_flag, + // spatial_flipping_flag, frame0_flipped_flag, field_views_flag + skip_bits(gb, 3); + h->current_frame_is_frame0_flag = get_bits1(gb); // frame0_self_contained_flag, frame1_self_contained_flag - skip_bits(gb, 6); + skip_bits(gb, 2); if (!h->quincunx_subsampling && h->arrangement_type != 5) skip_bits(gb, 16); // frame[01]_grid_position_[xy] diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h index f6ac6034daac1..c3a19dd831989 100644 --- a/libavcodec/h264_sei.h +++ b/libavcodec/h264_sei.h @@ -108,6 +108,7 @@ typedef struct H264SEIFramePacking { int arrangement_type; int content_interpretation_type; int quincunx_subsampling; + int current_frame_is_frame0_flag; } H264SEIFramePacking; typedef struct H264SEIDisplayOrientation { diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 5dd01d836e95b..1b968ebd509b2 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1112,6 +1112,13 @@ static int h264_export_frame_props(H264Context *h) if (fp->content_interpretation_type == 2) stereo->flags = AV_STEREO3D_FLAG_INVERT; + + if (fp->arrangement_type == 5) { + if (fp->current_frame_is_frame0_flag) + stereo->view = AV_STEREO3D_VIEW_LEFT; + else + stereo->view = AV_STEREO3D_VIEW_RIGHT; + } } if (h->sei.display_orientation.present && diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 0a5d4440bf4fb..2bf170601d7ba 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -57,10 +57,11 @@ static int decode_nal_sei_frame_packing_arrangement(HEVCSEIFramePacking *s, GetB s->quincunx_subsampling = get_bits1(gb); s->content_interpretation_type = get_bits(gb, 6); - // the following skips spatial_flipping_flag frame0_flipped_flag - // field_views_flag current_frame_is_frame0_flag - // frame0_self_contained_flag frame1_self_contained_flag - skip_bits(gb, 6); + // spatial_flipping_flag, frame0_flipped_flag, field_views_flag + skip_bits(gb, 3); + s->current_frame_is_frame0_flag = get_bits1(gb); + // frame0_self_contained_flag, frame1_self_contained_flag + skip_bits(gb, 2); if (!s->quincunx_subsampling && s->arrangement_type != 5) skip_bits(gb, 16); // frame[01]_grid_position_[xy] diff --git a/libavcodec/hevc_sei.h b/libavcodec/hevc_sei.h index e4aeac1fbe02e..8d4f5df69f9dd 100644 --- a/libavcodec/hevc_sei.h +++ b/libavcodec/hevc_sei.h @@ -67,6 +67,7 @@ typedef struct HEVCSEIFramePacking { int arrangement_type; int content_interpretation_type; int quincunx_subsampling; + int current_frame_is_frame0_flag; } HEVCSEIFramePacking; typedef struct HEVCSEIDisplayOrientation { diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index a1619cf4bd944..f1d1c774977fb 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2397,6 +2397,13 @@ static int set_side_data(HEVCContext *s) if (s->sei.frame_packing.content_interpretation_type == 2) stereo->flags = AV_STEREO3D_FLAG_INVERT; + + if (s->sei.frame_packing.arrangement_type == 5) { + if (s->sei.frame_packing.current_frame_is_frame0_flag) + stereo->view = AV_STEREO3D_VIEW_LEFT; + else + stereo->view = AV_STEREO3D_VIEW_RIGHT; + } } if (s->sei.display_orientation.present && diff --git a/libavfilter/vf_framepack.c b/libavfilter/vf_framepack.c index fd0c1897d5563..64457b450144c 100644 --- a/libavfilter/vf_framepack.c +++ b/libavfilter/vf_framepack.c @@ -310,6 +310,8 @@ static int request_frame(AVFilterLink *outlink) if (!stereo) return AVERROR(ENOMEM); stereo->type = s->format; + stereo->view = i == LEFT ? AV_STEREO3D_VIEW_LEFT + : AV_STEREO3D_VIEW_RIGHT; // filter the frame and immediately relinquish its pointer ret = ff_filter_frame(outlink, s->input_views[i]); diff --git a/libavutil/stereo3d.h b/libavutil/stereo3d.h index 0fa9f63a2ca63..2d7cb8d4aad6c 100644 --- a/libavutil/stereo3d.h +++ b/libavutil/stereo3d.h @@ -141,6 +141,25 @@ enum AVStereo3DType { AV_STEREO3D_COLUMNS, }; +/** + * List of possible view types. + */ +enum AVStereo3DView { + /** + * Frame contains two packed views. + */ + AV_STEREO3D_VIEW_PACKED, + + /** + * Frame contains only the left view. + */ + AV_STEREO3D_VIEW_LEFT, + + /** + * Frame contains only the right view. + */ + AV_STEREO3D_VIEW_RIGHT, +}; /** * Inverted views, Right/Bottom represents the left view. @@ -164,6 +183,11 @@ typedef struct AVStereo3D { * Additional information about the frame packing. */ int flags; + + /** + * Determines which views are packed. + */ + enum AVStereo3DView view; } AVStereo3D; /** diff --git a/libavutil/version.h b/libavutil/version.h index c258968b8e2f6..4a9fffef43303 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -54,7 +54,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 6 +#define LIBAVUTIL_VERSION_MINOR 7 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From b3cb9bd43fa33a8aaf7a63e43f8418975b3bf0de Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Mon, 20 Nov 2017 15:36:39 +0530 Subject: [PATCH 1165/2557] avfilter/drawbox: rename variable for maximum thickness The present value name for maximum thickness is 'max' which results in a parse error of any thickness expression containing 'max(val1,val2)'. Value renamed to 'fill'. Tested locally and documented. Signed-off-by: Michael Niedermayer --- doc/filters.texi | 5 +++-- libavfilter/vf_drawbox.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 476f014ac8514..4a4efc70c8ca9 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -7142,7 +7142,8 @@ value @code{invert} is used, the box edge color is the same as the video with inverted luma. @item thickness, t -The expression which sets the thickness of the box edge. Default value is @code{3}. +The expression which sets the thickness of the box edge. +A value of @code{fill} will create a filled box. Default value is @code{3}. See below for the list of accepted constants. @end table @@ -7205,7 +7206,7 @@ drawbox=x=10:y=20:w=200:h=60:color=red@@0.5 @item Fill the box with pink color: @example -drawbox=x=10:y=10:w=100:h=100:color=pink@@0.5:t=max +drawbox=x=10:y=10:w=100:h=100:color=pink@@0.5:t=fill @end example @item diff --git a/libavfilter/vf_drawbox.c b/libavfilter/vf_drawbox.c index 88bb9ae5c0105..d351846594c44 100644 --- a/libavfilter/vf_drawbox.c +++ b/libavfilter/vf_drawbox.c @@ -47,7 +47,7 @@ static const char *const var_names[] = { "h", ///< height of the rendered box "w", ///< width of the rendered box "t", - "max", + "fill", NULL }; From 96e340760824e537e2d034abf9a3b8be3e2b312c Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Tue, 21 Nov 2017 15:10:08 -0800 Subject: [PATCH 1166/2557] Free extradata before reallocating. Otherwise ff_alloc_extradata() just leaks any existing allocated memory. Signed-off-by: Dale Curtis Reviewed-by: Derek Buitenhuis Signed-off-by: Michael Niedermayer --- libavformat/oggparseogm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/oggparseogm.c b/libavformat/oggparseogm.c index e7a501b5a71e2..fad093b629ac1 100644 --- a/libavformat/oggparseogm.c +++ b/libavformat/oggparseogm.c @@ -110,6 +110,7 @@ ogm_header(AVFormatContext *s, int idx) size -= 52; if (bytestream2_get_bytes_left(&p) < size) return AVERROR_INVALIDDATA; + av_freep(&st->codecpar->extradata); if (ff_alloc_extradata(st->codecpar, size) < 0) return AVERROR(ENOMEM); bytestream2_get_buffer(&p, st->codecpar->extradata, st->codecpar->extradata_size); From 89f9332fdf8948daa50a29e1a9fa9488041351a3 Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Mon, 27 Nov 2017 20:41:10 +0800 Subject: [PATCH 1167/2557] avcodec: set correct return value in ff_mpeg_ref_picture In function ff_mpeg_ref_picture(), it returns 0 on the error path that the return value of av_buffer_ref() is NULL. 0 indicates success, which seems to deviate from the fact. Set ret to AVERROR(ENOMEM) to propagate the error status to the callers. Signed-off-by: Pan Bian Signed-off-by: Michael Niedermayer --- libavcodec/mpegpicture.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/mpegpicture.c b/libavcodec/mpegpicture.c index 2b72346fb2498..2be670cdbc230 100644 --- a/libavcodec/mpegpicture.c +++ b/libavcodec/mpegpicture.c @@ -375,8 +375,10 @@ int ff_mpeg_ref_picture(AVCodecContext *avctx, Picture *dst, Picture *src) if (src->hwaccel_picture_private) { dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); - if (!dst->hwaccel_priv_buf) + if (!dst->hwaccel_priv_buf) { + ret = AVERROR(ENOMEM); goto fail; + } dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data; } From 62f7f40caa70212cd017a66d514fc64f24a3adbc Mon Sep 17 00:00:00 2001 From: Mark Reid Date: Sun, 26 Nov 2017 21:42:16 -0800 Subject: [PATCH 1168/2557] avformat/mxfenc: pass MXFPackage around instead of type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Tomas Härdin Signed-off-by: Michael Niedermayer --- libavformat/mxfenc.c | 99 ++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 44 deletions(-) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 035e65ed43a0b..ed6ecbf541c8c 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -101,6 +101,12 @@ typedef struct MXFContainerEssenceEntry { void (*write_desc)(AVFormatContext *, AVStream *); } MXFContainerEssenceEntry; +typedef struct MXFPackage { + char *name; + enum MXFMetadataSetType type; + int instance; +} MXFPackage; + enum ULIndex { INDEX_MPEG2 = 0, INDEX_AES3, @@ -808,13 +814,14 @@ static void mxf_write_identification(AVFormatContext *s) avio_wb64(pb, mxf->timestamp); } -static void mxf_write_content_storage(AVFormatContext *s) +static void mxf_write_content_storage(AVFormatContext *s, MXFPackage *packages, int package_count) { AVIOContext *pb = s->pb; + int i; mxf_write_metadata_key(pb, 0x011800); PRINT_KEY(s, "content storage key", pb->buf_ptr - 16); - klv_encode_ber_length(pb, 92); + klv_encode_ber_length(pb, 60 + (16 * package_count)); // write uid mxf_write_local_tag(pb, 16, 0x3C0A); @@ -822,10 +829,11 @@ static void mxf_write_content_storage(AVFormatContext *s) PRINT_KEY(s, "content storage uid", pb->buf_ptr - 16); // write package reference - mxf_write_local_tag(pb, 16 * 2 + 8, 0x1901); - mxf_write_refs_count(pb, 2); - mxf_write_uuid(pb, MaterialPackage, 0); - mxf_write_uuid(pb, SourcePackage, 0); + mxf_write_local_tag(pb, 16 * package_count + 8, 0x1901); + mxf_write_refs_count(pb, package_count); + for (i = 0; i < package_count; i++) { + mxf_write_uuid(pb, packages[i].type, packages[i].instance); + } // write essence container data mxf_write_local_tag(pb, 8 + 16, 0x1902); @@ -833,7 +841,7 @@ static void mxf_write_content_storage(AVFormatContext *s) mxf_write_uuid(pb, EssenceContainerData, 0); } -static void mxf_write_track(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type) +static void mxf_write_track(AVFormatContext *s, AVStream *st, MXFPackage *package) { MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; @@ -845,7 +853,7 @@ static void mxf_write_track(AVFormatContext *s, AVStream *st, enum MXFMetadataSe // write track uid mxf_write_local_tag(pb, 16, 0x3C0A); - mxf_write_uuid(pb, type == MaterialPackage ? Track : Track + TypeBottom, st->index); + mxf_write_uuid(pb, package->type == MaterialPackage ? Track : Track + TypeBottom, st->index); PRINT_KEY(s, "track uid", pb->buf_ptr - 16); // write track id @@ -854,7 +862,7 @@ static void mxf_write_track(AVFormatContext *s, AVStream *st, enum MXFMetadataSe // write track number mxf_write_local_tag(pb, 4, 0x4804); - if (type == MaterialPackage) + if (package->type == MaterialPackage) avio_wb32(pb, 0); // track number of material package is 0 else avio_write(pb, sc->track_essence_element_key + 12, 4); @@ -876,7 +884,7 @@ static void mxf_write_track(AVFormatContext *s, AVStream *st, enum MXFMetadataSe // write sequence refs mxf_write_local_tag(pb, 16, 0x4803); - mxf_write_uuid(pb, type == MaterialPackage ? Sequence: Sequence + TypeBottom, st->index); + mxf_write_uuid(pb, package->type == MaterialPackage ? Sequence: Sequence + TypeBottom, st->index); } static const uint8_t smpte_12m_timecode_track_data_ul[] = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x01,0x01,0x00,0x00,0x00 }; @@ -905,7 +913,7 @@ static void mxf_write_common_fields(AVFormatContext *s, AVStream *st) } } -static void mxf_write_sequence(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type) +static void mxf_write_sequence(AVFormatContext *s, AVStream *st, MXFPackage *package) { MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; @@ -916,7 +924,7 @@ static void mxf_write_sequence(AVFormatContext *s, AVStream *st, enum MXFMetadat klv_encode_ber_length(pb, 80); mxf_write_local_tag(pb, 16, 0x3C0A); - mxf_write_uuid(pb, type == MaterialPackage ? Sequence: Sequence + TypeBottom, st->index); + mxf_write_uuid(pb, package->type == MaterialPackage ? Sequence: Sequence + TypeBottom, st->index); PRINT_KEY(s, "sequence uid", pb->buf_ptr - 16); mxf_write_common_fields(s, st); @@ -928,12 +936,12 @@ static void mxf_write_sequence(AVFormatContext *s, AVStream *st, enum MXFMetadat component = TimecodeComponent; else component = SourceClip; - if (type == SourcePackage) + if (package->type == SourcePackage) component += TypeBottom; mxf_write_uuid(pb, component, st->index); } -static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type) +static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, MXFPackage *package) { MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; @@ -943,7 +951,7 @@ static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, enum // UID mxf_write_local_tag(pb, 16, 0x3C0A); - mxf_write_uuid(pb, type == MaterialPackage ? TimecodeComponent : + mxf_write_uuid(pb, package->type == MaterialPackage ? TimecodeComponent : TimecodeComponent + TypeBottom, st->index); mxf_write_common_fields(s, st); @@ -961,7 +969,7 @@ static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, enum avio_w8(pb, !!(mxf->tc.flags & AV_TIMECODE_FLAG_DROPFRAME)); } -static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type) +static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, MXFPackage *package) { AVIOContext *pb = s->pb; int i; @@ -972,7 +980,7 @@ static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, enu // write uid mxf_write_local_tag(pb, 16, 0x3C0A); - mxf_write_uuid(pb, type == MaterialPackage ? SourceClip: SourceClip + TypeBottom, st->index); + mxf_write_uuid(pb, package->type == MaterialPackage ? SourceClip: SourceClip + TypeBottom, st->index); PRINT_KEY(s, "structural component uid", pb->buf_ptr - 16); mxf_write_common_fields(s, st); @@ -983,7 +991,7 @@ static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, enu // write source package uid, end of the reference mxf_write_local_tag(pb, 32, 0x1101); - if (type == SourcePackage) { + if (package->type == SourcePackage) { for (i = 0; i < 4; i++) avio_wb64(pb, 0); } else @@ -991,7 +999,7 @@ static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, enu // write source track id mxf_write_local_tag(pb, 4, 0x1102); - if (type == SourcePackage) + if (package->type == SourcePackage) avio_wb32(pb, 0); else avio_wb32(pb, st->index+2); @@ -1321,15 +1329,15 @@ static int mxf_write_user_comments(AVFormatContext *s, const AVDictionary *m) return count; } -static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type, const char *package_name) +static void mxf_write_package(AVFormatContext *s, MXFPackage *package) { MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; int i, track_count = s->nb_streams+1; - int name_size = mxf_utf16_local_tag_length(package_name); + int name_size = mxf_utf16_local_tag_length(package->name); int user_comment_count = 0; - if (type == MaterialPackage) { + if (package->type == MaterialPackage) { if (mxf->store_user_comments) user_comment_count = mxf_write_user_comments(s, s->metadata); mxf_write_metadata_key(pb, 0x013600); @@ -1343,18 +1351,18 @@ static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type, // write uid mxf_write_local_tag(pb, 16, 0x3C0A); - mxf_write_uuid(pb, type, 0); - av_log(s, AV_LOG_DEBUG, "package type:%d\n", type); + mxf_write_uuid(pb, package->type, package->instance); + av_log(s, AV_LOG_DEBUG, "package type:%d\n", package->type); PRINT_KEY(s, "package uid", pb->buf_ptr - 16); // write package umid mxf_write_local_tag(pb, 32, 0x4401); - mxf_write_umid(s, type == SourcePackage); + mxf_write_umid(s, package->type == SourcePackage); PRINT_KEY(s, "package umid second part", pb->buf_ptr - 16); // package name if (name_size) - mxf_write_local_tag_utf16(pb, 0x4402, package_name); + mxf_write_local_tag_utf16(pb, 0x4402, package->name); // package creation date mxf_write_local_tag(pb, 8, 0x4405); @@ -1367,10 +1375,10 @@ static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type, // write track refs mxf_write_local_tag(pb, track_count*16 + 8, 0x4403); mxf_write_refs_count(pb, track_count); - mxf_write_uuid(pb, type == MaterialPackage ? Track : + mxf_write_uuid(pb, package->type == MaterialPackage ? Track : Track + TypeBottom, -1); // timecode track for (i = 0; i < s->nb_streams; i++) - mxf_write_uuid(pb, type == MaterialPackage ? Track : Track + TypeBottom, i); + mxf_write_uuid(pb, package->type == MaterialPackage ? Track : Track + TypeBottom, i); // write user comment refs if (mxf->store_user_comments) { @@ -1381,7 +1389,7 @@ static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type, } // write multiple descriptor reference - if (type == SourcePackage) { + if (package->type == SourcePackage) { mxf_write_local_tag(pb, 16, 0x4701); if (s->nb_streams > 1) { mxf_write_uuid(pb, MultipleDescriptor, 0); @@ -1391,17 +1399,17 @@ static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type, } // write timecode track - mxf_write_track(s, mxf->timecode_track, type); - mxf_write_sequence(s, mxf->timecode_track, type); - mxf_write_timecode_component(s, mxf->timecode_track, type); + mxf_write_track(s, mxf->timecode_track, package); + mxf_write_sequence(s, mxf->timecode_track, package); + mxf_write_timecode_component(s, mxf->timecode_track, package); for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - mxf_write_track(s, st, type); - mxf_write_sequence(s, st, type); - mxf_write_structural_component(s, st, type); + mxf_write_track(s, st, package); + mxf_write_sequence(s, st, package); + mxf_write_structural_component(s, st, package); - if (type == SourcePackage) { + if (package->type == SourcePackage) { MXFStreamContext *sc = st->priv_data; mxf_essence_container_uls[sc->index].write_desc(s, st); } @@ -1432,23 +1440,26 @@ static int mxf_write_essence_container_data(AVFormatContext *s) static int mxf_write_header_metadata_sets(AVFormatContext *s) { - const char *material_package_name = NULL; - const char *file_package_name = NULL; AVDictionaryEntry *entry = NULL; AVStream *st = NULL; int i; + MXFPackage packages[2] = {}; + int package_count = 2; + packages[0].type = MaterialPackage; + packages[1].type = SourcePackage; + if (entry = av_dict_get(s->metadata, "material_package_name", NULL, 0)) - material_package_name = entry->value; + packages[0].name = entry->value; if (entry = av_dict_get(s->metadata, "file_package_name", NULL, 0)) { - file_package_name = entry->value; + packages[1].name = entry->value; } else { /* check if any of the streams contain a file_package_name */ for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; if (entry = av_dict_get(st->metadata, "file_package_name", NULL, 0)) { - file_package_name = entry->value; + packages[1].name = entry->value; break; } } @@ -1456,9 +1467,9 @@ static int mxf_write_header_metadata_sets(AVFormatContext *s) mxf_write_preface(s); mxf_write_identification(s); - mxf_write_content_storage(s); - mxf_write_package(s, MaterialPackage, material_package_name); - mxf_write_package(s, SourcePackage, file_package_name); + mxf_write_content_storage(s, packages, package_count); + for (i = 0; i < package_count; i++) + mxf_write_package(s, &packages[i]); mxf_write_essence_container_data(s); return 0; } From 3f81259f337ba57ab1a722566c8d8122dc705823 Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Mon, 27 Nov 2017 11:12:56 +0800 Subject: [PATCH 1169/2557] avformat/mov: set correct error code in mov_read_custom In function mov_read_custom(), it returns 0 on the path that av_malloc() returns a NULL pointer. 0 indicates success. An error code should be assigned to ret. Signed-off-by: Pan Bian Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index b3b800f898ea6..230a7f95d0469 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4176,8 +4176,10 @@ static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom) break; *p = av_malloc(len + 1); - if (!*p) + if (!*p) { + ret = AVERROR(ENOMEM); break; + } ret = ffio_read_size(pb, *p, len); if (ret < 0) { av_freep(p); From f63450c8e4c9c1f7af07869c4a25543e4e4d2626 Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Mon, 27 Nov 2017 11:13:05 +0800 Subject: [PATCH 1170/2557] avformat/mov: return correct value in mov_read_cmov On some failure paths, the error code is not correctly set. Signed-off-by: Pan Bian Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index 230a7f95d0469..c9018592e0592 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4894,6 +4894,7 @@ static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (ret < 0) goto free_and_return; + ret = AVERROR_INVALIDDATA; if (uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK) goto free_and_return; if (ffio_init_context(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0) From c5f3e85792d5f98d7974e8ca55cd30f80fe0c77c Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 28 Nov 2017 21:37:38 +0000 Subject: [PATCH 1171/2557] Changelog: add VAAPI VP8 decoder --- Changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog b/Changelog index afead72f14c37..bf74002f10006 100644 --- a/Changelog +++ b/Changelog @@ -21,6 +21,7 @@ version : - video mix filter - video normalize filter - audio lv2 wrapper filter +- VAAPI VP8 decoding version 3.4: From 23db3a1ae6d1be3438aec73c4dc91185d7958300 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 6 Nov 2017 14:45:27 +0800 Subject: [PATCH 1172/2557] examples: Add a VA-API encode example. Supports only raw NV12 input. Example use: ./vaapi_encode 1920 1080 test.yuv test.h264 Signed-off-by: Jun Zhao Signed-off-by: Liu, Kaixuan Signed-off-by: Mark Thompson --- configure | 2 + doc/examples/Makefile | 1 + doc/examples/vaapi_encode.c | 224 ++++++++++++++++++++++++++++++++++++ 3 files changed, 227 insertions(+) create mode 100644 doc/examples/vaapi_encode.c diff --git a/configure b/configure index 28902d41f5bca..11eeeaa609700 100755 --- a/configure +++ b/configure @@ -1522,6 +1522,7 @@ EXAMPLE_LIST=" scaling_video_example transcode_aac_example transcoding_example + vaapi_encode_example " EXTERNAL_AUTODETECT_LIBRARY_LIST=" @@ -3300,6 +3301,7 @@ resampling_audio_example_deps="avutil swresample" scaling_video_example_deps="avutil swscale" transcode_aac_example_deps="avcodec avformat swresample" transcoding_example_deps="avfilter avcodec avformat avutil" +vaapi_encode_example_deps="avcodec avutil" # EXTRALIBS_LIST cpu_init_extralibs="pthreads_extralibs" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index 58afd71b85bb9..da5af36532ba6 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -19,6 +19,7 @@ EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE) += resampling_audio EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE) += scaling_video EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac EXAMPLES-$(CONFIG_TRANSCODING_EXAMPLE) += transcoding +EXAMPLES-$(CONFIG_VAAPI_ENCODE_EXAMPLE) += vaapi_encode EXAMPLES := $(EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)$(EXESUF)) EXAMPLES_G := $(EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)_g$(EXESUF)) diff --git a/doc/examples/vaapi_encode.c b/doc/examples/vaapi_encode.c new file mode 100644 index 0000000000000..866b03d58c4c2 --- /dev/null +++ b/doc/examples/vaapi_encode.c @@ -0,0 +1,224 @@ +/* + * Video Acceleration API (video encoding) encode sample + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Intel VAAPI-accelerated encoding example. + * + * @example vaapi_encode.c + * This example shows how to do VAAPI-accelerated encoding. now only support NV12 + * raw file, usage like: vaapi_encode 1920 1080 input.yuv output.h264 + * + */ + +#include +#include +#include + +#include +#include +#include + +static int width, height; +static AVBufferRef *hw_device_ctx = NULL; + +static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx) +{ + AVBufferRef *hw_frames_ref; + AVHWFramesContext *frames_ctx = NULL; + int err = 0; + + if (!(hw_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx))) { + fprintf(stderr, "Failed to create VAAPI frame context.\n"); + return -1; + } + frames_ctx = (AVHWFramesContext *)(hw_frames_ref->data); + frames_ctx->format = AV_PIX_FMT_VAAPI; + frames_ctx->sw_format = AV_PIX_FMT_NV12; + frames_ctx->width = width; + frames_ctx->height = height; + frames_ctx->initial_pool_size = 20; + if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) { + fprintf(stderr, "Failed to initialize VAAPI frame context." + "Error code: %s\n",av_err2str(err)); + return err; + } + ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref); + if (!ctx->hw_frames_ctx) + err = AVERROR(ENOMEM); + + av_buffer_unref(&hw_frames_ref); + return err; +} + +static int encode_write(AVCodecContext *avctx, AVFrame *frame, FILE *fout) +{ + int ret = 0; + AVPacket enc_pkt; + + av_init_packet(&enc_pkt); + enc_pkt.data = NULL; + enc_pkt.size = 0; + + if ((ret = avcodec_send_frame(avctx, frame)) < 0) { + fprintf(stderr, "Error code: %s\n", av_err2str(ret)); + goto end; + } + while (1) { + ret = avcodec_receive_packet(avctx, &enc_pkt); + if (ret) + break; + + enc_pkt.stream_index = 0; + ret = fwrite(enc_pkt.data, enc_pkt.size, 1, fout); + av_packet_unref(&enc_pkt); + } + +end: + ret = ((ret == AVERROR(EAGAIN)) ? 0 : -1); + return ret; +} + +int main(int argc, char *argv[]) +{ + int size, err; + FILE *fin = NULL, *fout = NULL; + AVFrame *sw_frame = NULL, *hw_frame = NULL; + AVCodecContext *avctx = NULL; + AVCodec *codec = NULL; + const char *enc_name = "h264_vaapi"; + + if (argc < 5) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return -1; + } + + width = atoi(argv[1]); + height = atoi(argv[2]); + size = width * height; + + if (!(fin = fopen(argv[3], "r"))) { + fprintf(stderr, "Fail to open input file : %s\n", strerror(errno)); + return -1; + } + if (!(fout = fopen(argv[4], "w+b"))) { + fprintf(stderr, "Fail to open output file : %s\n", strerror(errno)); + err = -1; + goto close; + } + + avcodec_register_all(); + + err = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI, + NULL, NULL, 0); + if (err < 0) { + fprintf(stderr, "Failed to create a VAAPI device. Error code: %s\n", av_err2str(err)); + goto close; + } + + if (!(codec = avcodec_find_encoder_by_name(enc_name))) { + fprintf(stderr, "Could not find encoder.\n"); + err = -1; + goto close; + } + + if (!(avctx = avcodec_alloc_context3(codec))) { + err = AVERROR(ENOMEM); + goto close; + } + + avctx->width = width; + avctx->height = height; + avctx->time_base = (AVRational){1, 25}; + avctx->framerate = (AVRational){25, 1}; + avctx->sample_aspect_ratio = (AVRational){1, 1}; + avctx->pix_fmt = AV_PIX_FMT_VAAPI; + + /* set hw_frames_ctx for encoder's AVCodecContext */ + if ((err = set_hwframe_ctx(avctx, hw_device_ctx)) < 0) { + fprintf(stderr, "Failed to set hwframe context.\n"); + goto close; + } + + if ((err = avcodec_open2(avctx, codec, NULL)) < 0) { + fprintf(stderr, "Cannot open video encoder codec. Error code: %s\n", av_err2str(err)); + goto close; + } + + while (1) { + if (!(sw_frame = av_frame_alloc())) { + err = AVERROR(ENOMEM); + goto close; + } + /* read data into software frame, and transfer them into hw frame */ + sw_frame->width = width; + sw_frame->height = height; + sw_frame->format = AV_PIX_FMT_NV12; + if ((err = av_frame_get_buffer(sw_frame, 32)) < 0) + goto close; + if ((err = fread((uint8_t*)(sw_frame->data[0]), size, 1, fin)) <= 0) + break; + if ((err = fread((uint8_t*)(sw_frame->data[1]), size/2, 1, fin)) <= 0) + break; + + if (!(hw_frame = av_frame_alloc())) { + err = AVERROR(ENOMEM); + goto close; + } + if ((err = av_hwframe_get_buffer(avctx->hw_frames_ctx, hw_frame, 0)) < 0) { + fprintf(stderr, "Error code: %s.\n", av_err2str(err)); + goto close; + } + if (!hw_frame->hw_frames_ctx) { + err = AVERROR(ENOMEM); + goto close; + } + if ((err = av_hwframe_transfer_data(hw_frame, sw_frame, 0)) < 0) { + fprintf(stderr, "Error while transferring frame data to surface." + "Error code: %s.\n", av_err2str(err)); + goto close; + } + + if ((err = (encode_write(avctx, hw_frame, fout))) < 0) { + fprintf(stderr, "Failed to encode.\n"); + goto close; + } + av_frame_free(&hw_frame); + av_frame_free(&sw_frame); + } + + /* flush encoder */ + err = encode_write(avctx, NULL, fout); + if (err == AVERROR_EOF) + err = 0; + +close: + if (fin) + fclose(fin); + if (fout) + fclose(fout); + av_frame_free(&sw_frame); + av_frame_free(&hw_frame); + if (avctx) + avcodec_free_context(&avctx); + av_buffer_unref(&hw_device_ctx); + + return err; +} From 9ea6607d294526688ab1b1342cb36ee159683e88 Mon Sep 17 00:00:00 2001 From: Mikhail Mironov Date: Sun, 26 Nov 2017 21:36:06 -0500 Subject: [PATCH 1173/2557] Add HW H.264 and HEVC encoding for AMD GPUs based on AMF SDK Requires AMF headers for at least version 1.4.4.1. Signed-off-by: Mikhail Mironov Signed-off-by: Mark Thompson --- Changelog | 1 + configure | 10 + libavcodec/Makefile | 4 + libavcodec/allcodecs.c | 2 + libavcodec/amfenc.c | 604 +++++++++++++++++++++++++++++++++++++++ libavcodec/amfenc.h | 148 ++++++++++ libavcodec/amfenc_h264.c | 395 +++++++++++++++++++++++++ libavcodec/amfenc_hevc.c | 326 +++++++++++++++++++++ 8 files changed, 1490 insertions(+) create mode 100644 libavcodec/amfenc.c create mode 100644 libavcodec/amfenc.h create mode 100644 libavcodec/amfenc_h264.c create mode 100644 libavcodec/amfenc_hevc.c diff --git a/Changelog b/Changelog index bf74002f10006..9eaaedbcaba56 100644 --- a/Changelog +++ b/Changelog @@ -22,6 +22,7 @@ version : - video normalize filter - audio lv2 wrapper filter - VAAPI VP8 decoding +- AMD AMF H.264 and HEVC encoders version 3.4: diff --git a/configure b/configure index 11eeeaa609700..4e7254eaeb853 100755 --- a/configure +++ b/configure @@ -304,6 +304,7 @@ External library support: --disable-zlib disable zlib [autodetect] The following libraries provide various hardware acceleration features: + --disable-amf disable AMF video encoding code [autodetect] --disable-audiotoolbox disable Apple AudioToolbox code [autodetect] --disable-cuda disable dynamically linked Nvidia CUDA code [autodetect] --enable-cuda-sdk enable CUDA features that require the CUDA SDK [no] @@ -1640,6 +1641,7 @@ EXTERNAL_LIBRARY_LIST=" " HWACCEL_AUTODETECT_LIBRARY_LIST=" + amf audiotoolbox crystalhd cuda @@ -2783,12 +2785,14 @@ scale_npp_filter_deps="cuda libnpp" scale_cuda_filter_deps="cuda_sdk" thumbnail_cuda_filter_deps="cuda_sdk" +amf_deps_any="libdl LoadLibrary" nvenc_deps="cuda" nvenc_deps_any="libdl LoadLibrary" nvenc_encoder_deps="nvenc" h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m" h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m" +h264_amf_encoder_deps="amf" h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser" h264_cuvid_decoder_deps="cuvid" h264_cuvid_decoder_select="h264_mp4toannexb_bsf" @@ -2805,6 +2809,7 @@ h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" h264_vaapi_encoder_select="cbs_h264 vaapi_encode" h264_v4l2m2m_decoder_deps="v4l2_m2m h264_v4l2_m2m" h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m" +hevc_amf_encoder_deps="amf" hevc_cuvid_decoder_deps="cuvid" hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf" hevc_mediacodec_decoder_deps="mediacodec" @@ -6196,6 +6201,11 @@ void f(void) { struct { const GUID guid; } s[] = { { NV_ENC_PRESET_HQ_GUID } }; int main(void) { return 0; } EOF +enabled amf && + check_cpp_condition "AMF/core/Version.h" \ + "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400040001" || + disable amf + # Funny iconv installations are not unusual, so check it after all flags have been set if enabled libc_iconv; then check_func_headers iconv.h iconv diff --git a/libavcodec/Makefile b/libavcodec/Makefile index a6203d424b740..ab7893f560e79 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -55,6 +55,7 @@ OBJS = ac3_parser.o \ OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o OBJS-$(CONFIG_AC3DSP) += ac3dsp.o ac3.o ac3tab.o OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio.o +OBJS-$(CONFIG_AMF) += amfenc.o OBJS-$(CONFIG_AUDIO_FRAME_QUEUE) += audio_frame_queue.o OBJS-$(CONFIG_AUDIODSP) += audiodsp.o OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o @@ -337,6 +338,7 @@ OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264_cabac.o h264_cavlc.o \ h264_mb.o h264_picture.o \ h264_refs.o h264_sei.o \ h264_slice.o h264data.o +OBJS-$(CONFIG_H264_AMF_ENCODER) += amfenc_h264.o OBJS-$(CONFIG_H264_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_H264_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o @@ -356,6 +358,7 @@ OBJS-$(CONFIG_HAP_ENCODER) += hapenc.o hap.o OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o \ hevc_cabac.o hevc_refs.o hevcpred.o \ hevcdsp.o hevc_filter.o hevc_data.o +OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o @@ -1065,6 +1068,7 @@ SKIPHEADERS += %_tablegen.h \ aacenc_quantization_misc.h \ $(ARCH)/vp56_arith.h \ +SKIPHEADERS-$(CONFIG_AMF) += amfenc.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_JNI) += ffjni.h diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4a21687b202b1..ed1e7ab06e5ce 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -576,6 +576,7 @@ static void register_all(void) * above is available */ REGISTER_ENCODER(H263_V4L2M2M, h263_v4l2m2m); REGISTER_ENCDEC (LIBOPENH264, libopenh264); + REGISTER_ENCODER(H264_AMF, h264_amf); REGISTER_DECODER(H264_CUVID, h264_cuvid); REGISTER_ENCODER(H264_NVENC, h264_nvenc); REGISTER_ENCODER(H264_OMX, h264_omx); @@ -588,6 +589,7 @@ static void register_all(void) REGISTER_ENCODER(NVENC_H264, nvenc_h264); REGISTER_ENCODER(NVENC_HEVC, nvenc_hevc); #endif + REGISTER_ENCODER(HEVC_AMF, hevc_amf); REGISTER_DECODER(HEVC_CUVID, hevc_cuvid); REGISTER_DECODER(HEVC_MEDIACODEC, hevc_mediacodec); REGISTER_ENCODER(HEVC_NVENC, hevc_nvenc); diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c new file mode 100644 index 0000000000000..49d64e6946359 --- /dev/null +++ b/libavcodec/amfenc.c @@ -0,0 +1,604 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "libavutil/hwcontext.h" +#if CONFIG_D3D11VA +#include "libavutil/hwcontext_d3d11va.h" +#endif +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" +#include "libavutil/time.h" + +#include "amfenc.h" +#include "internal.h" + +#if CONFIG_D3D11VA +#include +#endif + +#ifdef _WIN32 +#include "compat/w32dlfcn.h" +#else +#include +#endif + +#define FFMPEG_AMF_WRITER_ID L"ffmpeg_amf" + +#define PTS_PROP L"PtsProp" + +const enum AVPixelFormat ff_amf_pix_fmts[] = { + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUV420P, +#if CONFIG_D3D11VA + AV_PIX_FMT_D3D11, +#endif + AV_PIX_FMT_NONE +}; + +typedef struct FormatMap { + enum AVPixelFormat av_format; + enum AMF_SURFACE_FORMAT amf_format; +} FormatMap; + +static const FormatMap format_map[] = +{ + { AV_PIX_FMT_NONE, AMF_SURFACE_UNKNOWN }, + { AV_PIX_FMT_NV12, AMF_SURFACE_NV12 }, + { AV_PIX_FMT_BGR0, AMF_SURFACE_BGRA }, + { AV_PIX_FMT_RGB0, AMF_SURFACE_RGBA }, + { AV_PIX_FMT_GRAY8, AMF_SURFACE_GRAY8 }, + { AV_PIX_FMT_YUV420P, AMF_SURFACE_YUV420P }, + { AV_PIX_FMT_YUYV422, AMF_SURFACE_YUY2 }, + { AV_PIX_FMT_D3D11, AMF_SURFACE_NV12 }, +}; + + +static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + return desc->flags & AV_PIX_FMT_FLAG_HWACCEL; +} + + +static enum AMF_SURFACE_FORMAT amf_av_to_amf_format(enum AVPixelFormat fmt) +{ + int i; + for (i = 0; i < amf_countof(format_map); i++) { + if (format_map[i].av_format == fmt) { + return format_map[i].amf_format; + } + } + return AMF_SURFACE_UNKNOWN; +} + +static void AMF_CDECL_CALL AMFTraceWriter_Write(AMFTraceWriter *pThis, + const wchar_t *scope, const wchar_t *message) +{ + AmfTraceWriter *tracer = (AmfTraceWriter*)pThis; + av_log(tracer->avctx, AV_LOG_DEBUG, "%ls: %ls", scope, message); // \n is provided from AMF +} + +static void AMF_CDECL_CALL AMFTraceWriter_Flush(AMFTraceWriter *pThis) +{ +} + +static AMFTraceWriterVtbl tracer_vtbl = +{ + .Write = AMFTraceWriter_Write, + .Flush = AMFTraceWriter_Flush, +}; + +static int amf_load_library(AVCodecContext *avctx) +{ + AmfContext *ctx = avctx->priv_data; + AMFInit_Fn init_fun = NULL; + AMFQueryVersion_Fn version_fun = NULL; + AMF_RESULT res = AMF_OK; + + ctx->eof = 0; + ctx->delayed_drain = 0; + ctx->hw_frames_ctx = NULL; + ctx->hw_device_ctx = NULL; + ctx->delayed_surface = NULL; + ctx->delayed_frame = av_frame_alloc(); + if (!ctx->delayed_frame) { + return AVERROR(ENOMEM); + } + // hardcoded to current HW queue size - will realloc in timestamp_queue_enqueue() if too small + ctx->timestamp_list = av_fifo_alloc((avctx->max_b_frames + 16) * sizeof(int64_t)); + if (!ctx->timestamp_list) { + return AVERROR(ENOMEM); + } + ctx->dts_delay = 0; + + + ctx->library = dlopen(AMF_DLL_NAMEA, RTLD_NOW | RTLD_LOCAL); + AMF_RETURN_IF_FALSE(ctx, ctx->library != NULL, + AVERROR_UNKNOWN, "DLL %s failed to open\n", AMF_DLL_NAMEA); + + init_fun = (AMFInit_Fn)dlsym(ctx->library, AMF_INIT_FUNCTION_NAME); + AMF_RETURN_IF_FALSE(ctx, init_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_INIT_FUNCTION_NAME); + + version_fun = (AMFQueryVersion_Fn)dlsym(ctx->library, AMF_QUERY_VERSION_FUNCTION_NAME); + AMF_RETURN_IF_FALSE(ctx, version_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_QUERY_VERSION_FUNCTION_NAME); + + res = version_fun(&ctx->version); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_QUERY_VERSION_FUNCTION_NAME, res); + res = init_fun(AMF_FULL_VERSION, &ctx->factory); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_INIT_FUNCTION_NAME, res); + res = ctx->factory->pVtbl->GetTrace(ctx->factory, &ctx->trace); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetTrace() failed with error %d\n", res); + res = ctx->factory->pVtbl->GetDebug(ctx->factory, &ctx->debug); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetDebug() failed with error %d\n", res); + return 0; +} + +static int amf_init_context(AVCodecContext *avctx) +{ + AmfContext *ctx = avctx->priv_data; + AMF_RESULT res = AMF_OK; + + // confugure AMF logger + // the return of these functions indicates old state and do not affect behaviour + ctx->trace->pVtbl->EnableWriter(ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, ctx->log_to_dbg != 0 ); + if (ctx->log_to_dbg) + ctx->trace->pVtbl->SetWriterLevel(ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, AMF_TRACE_TRACE); + ctx->trace->pVtbl->EnableWriter(ctx->trace, AMF_TRACE_WRITER_CONSOLE, 0); + ctx->trace->pVtbl->SetGlobalLevel(ctx->trace, AMF_TRACE_TRACE); + + // connect AMF logger to av_log + ctx->tracer.vtbl = &tracer_vtbl; + ctx->tracer.avctx = avctx; + ctx->trace->pVtbl->RegisterWriter(ctx->trace, FFMPEG_AMF_WRITER_ID,(AMFTraceWriter*)&ctx->tracer, 1); + ctx->trace->pVtbl->SetWriterLevel(ctx->trace, FFMPEG_AMF_WRITER_ID, AMF_TRACE_TRACE); + + res = ctx->factory->pVtbl->CreateContext(ctx->factory, &ctx->context); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext() failed with error %d\n", res); + // try to reuse existing DX device +#if CONFIG_D3D11VA + if (avctx->hw_frames_ctx) { + AVHWFramesContext *device_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + if (device_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { + if (amf_av_to_amf_format(device_ctx->sw_format) != AMF_SURFACE_UNKNOWN) { + if (device_ctx->device_ctx->hwctx) { + AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->device_ctx->hwctx; + res = ctx->context->pVtbl->InitDX11(ctx->context, device_d3d11->device, AMF_DX11_1); + if (res == AMF_OK) { + ctx->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx); + if (!ctx->hw_frames_ctx) { + return AVERROR(ENOMEM); + } + } else { + if(res == AMF_NOT_SUPPORTED) + av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n"); + else + av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has non-AMD device, switching to default\n"); + } + } + } else { + av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has format not uspported by AMF, switching to default\n"); + } + } + } else if (avctx->hw_device_ctx) { + AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data); + if (device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { + if (device_ctx->hwctx) { + AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->hwctx; + res = ctx->context->pVtbl->InitDX11(ctx->context, device_d3d11->device, AMF_DX11_1); + if (res == AMF_OK) { + ctx->hw_device_ctx = av_buffer_ref(avctx->hw_device_ctx); + if (!ctx->hw_device_ctx) { + return AVERROR(ENOMEM); + } + } else { + if (res == AMF_NOT_SUPPORTED) + av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n"); + else + av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has non-AMD device, switching to default\n"); + } + } + } + } +#endif + if (!ctx->hw_frames_ctx && !ctx->hw_device_ctx) { + res = ctx->context->pVtbl->InitDX11(ctx->context, NULL, AMF_DX11_1); + if (res != AMF_OK) { + res = ctx->context->pVtbl->InitDX9(ctx->context, NULL); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "InitDX9() failed with error %d\n", res); + } + } + return 0; +} + +static int amf_init_encoder(AVCodecContext *avctx) +{ + AmfContext *ctx = avctx->priv_data; + const wchar_t *codec_id = NULL; + AMF_RESULT res = AMF_OK; + + switch (avctx->codec->id) { + case AV_CODEC_ID_H264: + codec_id = AMFVideoEncoderVCE_AVC; + break; + case AV_CODEC_ID_HEVC: + codec_id = AMFVideoEncoder_HEVC; + break; + default: + break; + } + AMF_RETURN_IF_FALSE(ctx, codec_id != NULL, AVERROR(EINVAL), "Codec %d is not supported\n", avctx->codec->id); + + ctx->format = amf_av_to_amf_format(avctx->pix_fmt); + AMF_RETURN_IF_FALSE(ctx, ctx->format != AMF_SURFACE_UNKNOWN, AVERROR(EINVAL), "Format %d is not supported\n", avctx->pix_fmt); + + res = ctx->factory->pVtbl->CreateComponent(ctx->factory, ctx->context, codec_id, &ctx->encoder); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_ENCODER_NOT_FOUND, "CreateComponent(%ls) failed with error %d\n", codec_id, res); + + return 0; +} + +int av_cold ff_amf_encode_close(AVCodecContext *avctx) +{ + AmfContext *ctx = avctx->priv_data; + if (ctx->delayed_surface) + { + ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface); + ctx->delayed_surface = NULL; + } + + if (ctx->encoder) { + ctx->encoder->pVtbl->Terminate(ctx->encoder); + ctx->encoder->pVtbl->Release(ctx->encoder); + ctx->encoder = NULL; + } + + if (ctx->context) { + ctx->context->pVtbl->Terminate(ctx->context); + ctx->context->pVtbl->Release(ctx->context); + ctx->context = NULL; + } + av_buffer_unref(&ctx->hw_device_ctx); + av_buffer_unref(&ctx->hw_frames_ctx); + + if (ctx->trace) { + ctx->trace->pVtbl->UnregisterWriter(ctx->trace, FFMPEG_AMF_WRITER_ID); + } + if (ctx->library) { + dlclose(ctx->library); + ctx->library = NULL; + } + ctx->trace = NULL; + ctx->debug = NULL; + ctx->factory = NULL; + ctx->version = 0; + ctx->delayed_drain = 0; + av_frame_free(&ctx->delayed_frame); + av_fifo_freep(&ctx->timestamp_list); + + return 0; +} + +static int amf_copy_surface(AVCodecContext *avctx, const AVFrame *frame, + AMFSurface* surface) +{ + AVFrame *sw_frame = NULL; + AMFPlane *plane = NULL; + uint8_t *dst_data[4]; + int dst_linesize[4]; + int ret = 0; + int planes; + int i; + + if (frame->hw_frames_ctx && is_hwaccel_pix_fmt(frame->format)) { + if (!(sw_frame = av_frame_alloc())) { + av_log(avctx, AV_LOG_ERROR, "Can not alloc frame\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + if ((ret = av_hwframe_transfer_data(sw_frame, frame, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error transferring the data to system memory\n"); + goto fail; + } + frame = sw_frame; + } + planes = (int)surface->pVtbl->GetPlanesCount(surface); + if (planes > amf_countof(dst_data)) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of planes %d in surface\n", planes); + ret = AVERROR(EINVAL); + goto fail; + } + + for (i = 0; i < planes; i++) { + plane = surface->pVtbl->GetPlaneAt(surface, i); + dst_data[i] = plane->pVtbl->GetNative(plane); + dst_linesize[i] = plane->pVtbl->GetHPitch(plane); + } + av_image_copy(dst_data, dst_linesize, + (const uint8_t**)frame->data, frame->linesize, frame->format, + avctx->width, avctx->height); + +fail: + if (sw_frame) { + av_frame_free(&sw_frame); + } + return ret; +} + +static inline int timestamp_queue_enqueue(AVCodecContext *avctx, int64_t timestamp) +{ + AmfContext *ctx = avctx->priv_data; + if (av_fifo_space(ctx->timestamp_list) < sizeof(timestamp)) { + if (av_fifo_grow(ctx->timestamp_list, sizeof(timestamp)) < 0) { + return AVERROR(ENOMEM); + } + } + av_fifo_generic_write(ctx->timestamp_list, ×tamp, sizeof(timestamp), NULL); + return 0; +} + +static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buffer) +{ + AmfContext *ctx = avctx->priv_data; + int ret; + AMFVariantStruct var = {0}; + int64_t timestamp = AV_NOPTS_VALUE; + int64_t size = buffer->pVtbl->GetSize(buffer); + + if ((ret = ff_alloc_packet2(avctx, pkt, size, 0)) < 0) { + return ret; + } + memcpy(pkt->data, buffer->pVtbl->GetNative(buffer), size); + + switch (avctx->codec->id) { + case AV_CODEC_ID_H264: + buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE, &var); + if(var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR) { + pkt->flags = AV_PKT_FLAG_KEY; + } + break; + case AV_CODEC_ID_HEVC: + buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE, &var); + if (var.int64Value == AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_IDR) { + pkt->flags = AV_PKT_FLAG_KEY; + } + break; + default: + break; + } + + buffer->pVtbl->GetProperty(buffer, PTS_PROP, &var); + + pkt->pts = var.int64Value; // original pts + + + AMF_RETURN_IF_FALSE(ctx, av_fifo_size(ctx->timestamp_list) > 0, AVERROR_UNKNOWN, "timestamp_list is empty\n"); + + av_fifo_generic_read(ctx->timestamp_list, ×tamp, sizeof(timestamp), NULL); + + // calc dts shift if max_b_frames > 0 + if (avctx->max_b_frames > 0 && ctx->dts_delay == 0) { + int64_t timestamp_last = AV_NOPTS_VALUE; + AMF_RETURN_IF_FALSE(ctx, av_fifo_size(ctx->timestamp_list) > 0, AVERROR_UNKNOWN, + "timestamp_list is empty while max_b_frames = %d\n", avctx->max_b_frames); + av_fifo_generic_peek_at( + ctx->timestamp_list, + ×tamp_last, + (av_fifo_size(ctx->timestamp_list) / sizeof(timestamp) - 1) * sizeof(timestamp_last), + sizeof(timestamp_last), + NULL); + if (timestamp < 0 || timestamp_last < AV_NOPTS_VALUE) { + return AVERROR(ERANGE); + } + ctx->dts_delay = timestamp_last - timestamp; + } + pkt->dts = timestamp - ctx->dts_delay; + return 0; +} + +// amfenc API implmentation +int ff_amf_encode_init(AVCodecContext *avctx) +{ + AmfContext *ctx = avctx->priv_data; + int ret; + + ctx->factory = NULL; + ctx->debug = NULL; + ctx->trace = NULL; + ctx->context = NULL; + ctx->encoder = NULL; + ctx->library = NULL; + ctx->version = 0; + ctx->eof = 0; + ctx->format = 0; + ctx->tracer.vtbl = NULL; + ctx->tracer.avctx = NULL; + + if ((ret = amf_load_library(avctx)) == 0) { + if ((ret = amf_init_context(avctx)) == 0) { + if ((ret = amf_init_encoder(avctx)) == 0) { + return 0; + } + } + } + ff_amf_encode_close(avctx); + return ret; +} + + +int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame) +{ + AMF_RESULT res = AMF_OK; + AmfContext *ctx = avctx->priv_data; + AMFSurface *surface = NULL; + int ret; + + if (!ctx->encoder) + return AVERROR(EINVAL); + + if (!frame) { // submit drain + if (!ctx->eof) { // submit drain one time only + if (ctx->delayed_surface != NULL) { + ctx->delayed_drain = 1; // input queue is full: resubmit Drain() in ff_amf_receive_packet + } else if(!ctx->delayed_drain) { + res = ctx->encoder->pVtbl->Drain(ctx->encoder); + if (res == AMF_INPUT_FULL) { + ctx->delayed_drain = 1; // input queue is full: resubmit Drain() in ff_amf_receive_packet + } else { + if (res == AMF_OK) { + ctx->eof = 1; // drain started + } + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Drain() failed with error %d\n", res); + } + } + } else{ + return AVERROR_EOF; + } + } else { // submit frame + if (ctx->delayed_surface != NULL) { + return AVERROR(EAGAIN); // should not happen when called from ffmpeg, other clients may resubmit + } + // prepare surface from frame + if (frame->hw_frames_ctx && ( // HW frame detected + // check if the same hw_frames_ctx as used in initialization + (ctx->hw_frames_ctx && frame->hw_frames_ctx->data == ctx->hw_frames_ctx->data) || + // check if the same hw_device_ctx as used in initialization + (ctx->hw_device_ctx && ((AVHWFramesContext*)frame->hw_frames_ctx->data)->device_ctx == + (AVHWDeviceContext*)ctx->hw_device_ctx->data) + )) { +#if CONFIG_D3D11VA + static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } }; + ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // actual texture + int index = (int)(size_t)frame->data[1]; // index is a slice in texture array is - set to tell AMF which slice to use + texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID, sizeof(index), &index); + + res = ctx->context->pVtbl->CreateSurfaceFromDX11Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed with error %d\n", res); + + // input HW surfaces can be vertically aligned by 16; tell AMF the real size + surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height); +#endif + } else { + res = ctx->context->pVtbl->AllocSurface(ctx->context, AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res); + amf_copy_surface(avctx, frame, surface); + } + surface->pVtbl->SetPts(surface, frame->pts); + AMF_ASSIGN_PROPERTY_INT64(res, surface, PTS_PROP, frame->pts); + + switch (avctx->codec->id) { + case AV_CODEC_ID_H264: + AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_AUD, !!ctx->aud); + break; + case AV_CODEC_ID_HEVC: + AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!ctx->aud); + break; + default: + break; + } + + + // submit surface + res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)surface); + if (res == AMF_INPUT_FULL) { // handle full queue + //store surface for later submission + ctx->delayed_surface = surface; + if (surface->pVtbl->GetMemoryType(surface) == AMF_MEMORY_DX11) { + av_frame_ref(ctx->delayed_frame, frame); + } + } else { + surface->pVtbl->Release(surface); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res); + + if ((ret = timestamp_queue_enqueue(avctx, frame->pts)) < 0) { + return ret; + } + + } + } + return 0; +} +int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) +{ + int ret; + AMF_RESULT res; + AMF_RESULT res_query; + AmfContext *ctx = avctx->priv_data; + AMFData *data = NULL; + int block_and_wait; + + if (!ctx->encoder) + return AVERROR(EINVAL); + + do { + block_and_wait = 0; + // poll data + res_query = ctx->encoder->pVtbl->QueryOutput(ctx->encoder, &data); + if (data) { + // copy data to packet + AMFBuffer* buffer; + AMFGuid guid = IID_AMFBuffer(); + data->pVtbl->QueryInterface(data, &guid, (void**)&buffer); // query for buffer interface + ret = amf_copy_buffer(avctx, avpkt, buffer); + + buffer->pVtbl->Release(buffer); + data->pVtbl->Release(data); + + AMF_RETURN_IF_FALSE(ctx, ret >= 0, ret, "amf_copy_buffer() failed with error %d\n", ret); + + if (ctx->delayed_surface != NULL) { // try to resubmit frame + res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)ctx->delayed_surface); + if (res != AMF_INPUT_FULL) { + int64_t pts = ctx->delayed_surface->pVtbl->GetPts(ctx->delayed_surface); + ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface); + ctx->delayed_surface = NULL; + av_frame_unref(ctx->delayed_frame); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated SubmitInput() failed with error %d\n", res); + + if ((ret = timestamp_queue_enqueue(avctx, pts)) < 0) { + return ret; + } + } else { + av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed frame submission got AMF_INPUT_FULL- should not happen\n"); + } + } else if (ctx->delayed_drain) { // try to resubmit drain + res = ctx->encoder->pVtbl->Drain(ctx->encoder); + if (res != AMF_INPUT_FULL) { + ctx->delayed_drain = 0; + ctx->eof = 1; // drain started + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated Drain() failed with error %d\n", res); + } else { + av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed drain submission got AMF_INPUT_FULL- should not happen\n"); + } + } + } else if (ctx->delayed_surface != NULL || ctx->delayed_drain || (ctx->eof && res_query != AMF_EOF)) { + block_and_wait = 1; + av_usleep(1000); // wait and poll again + } + } while (block_and_wait); + + if (res_query == AMF_EOF) { + ret = AVERROR_EOF; + } else if (data == NULL) { + ret = AVERROR(EAGAIN); + } else { + ret = 0; + } + return ret; +} diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h new file mode 100644 index 0000000000000..8b59b506c54e6 --- /dev/null +++ b/libavcodec/amfenc.h @@ -0,0 +1,148 @@ +/* +* This file is part of FFmpeg. +* +* FFmpeg is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* FFmpeg is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with FFmpeg; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef AVCODEC_AMFENC_H +#define AVCODEC_AMFENC_H + +#include + +#include +#include + +#include "libavutil/fifo.h" + +#include "config.h" +#include "avcodec.h" + + +/** +* AMF trace writer callback class +* Used to capture all AMF logging +*/ + +typedef struct AmfTraceWriter { + AMFTraceWriterVtbl *vtbl; + AVCodecContext *avctx; +} AmfTraceWriter; + +/** +* AMF encoder context +*/ + +typedef struct AmfContext { + AVClass *avclass; + // access to AMF runtime + amf_handle library; ///< handle to DLL library + AMFFactory *factory; ///< pointer to AMF factory + AMFDebug *debug; ///< pointer to AMF debug interface + AMFTrace *trace; ///< pointer to AMF trace interface + + amf_uint64 version; ///< version of AMF runtime + AmfTraceWriter tracer; ///< AMF writer registered with AMF + AMFContext *context; ///< AMF context + //encoder + AMFComponent *encoder; ///< AMF encoder object + amf_bool eof; ///< flag indicating EOF happened + AMF_SURFACE_FORMAT format; ///< AMF surface format + + AVBufferRef *hw_device_ctx; ///< pointer to HW accelerator (decoder) + AVBufferRef *hw_frames_ctx; ///< pointer to HW accelerator (frame allocator) + + // helpers to handle async calls + int delayed_drain; + AMFSurface *delayed_surface; + AVFrame *delayed_frame; + + // shift dts back by max_b_frames in timing + AVFifoBuffer *timestamp_list; + int64_t dts_delay; + + // common encoder option options + + int log_to_dbg; + + // Static options, have to be set before Init() call + int usage; + int profile; + int level; + int preanalysis; + int quality; + int b_frame_delta_qp; + int ref_b_frame_delta_qp; + + // Dynamic options, can be set after Init() call + + int rate_control_mode; + int enforce_hrd; + int filler_data; + int enable_vbaq; + int skip_frame; + int qp_i; + int qp_p; + int qp_b; + int max_au_size; + int header_spacing; + int b_frame_ref; + int intra_refresh_mb; + int coding_mode; + int me_half_pel; + int me_quarter_pel; + int aud; + + // HEVC - specific options + + int gops_per_idr; + int header_insertion_mode; + int min_qp_i; + int max_qp_i; + int min_qp_p; + int max_qp_p; + int tier; +} AmfContext; + +/** +* Common encoder initization function +*/ +int ff_amf_encode_init(AVCodecContext *avctx); +/** +* Common encoder termination function +*/ +int ff_amf_encode_close(AVCodecContext *avctx); + +/** +* Ecoding one frame - common function for all AMF encoders +*/ + +int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame); +int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); + +/** +* Supported formats +*/ +extern const enum AVPixelFormat ff_amf_pix_fmts[]; + +/** +* Error handling helper +*/ +#define AMF_RETURN_IF_FALSE(avctx, exp, ret_value, /*message,*/ ...) \ + if (!(exp)) { \ + av_log(avctx, AV_LOG_ERROR, __VA_ARGS__); \ + return ret_value; \ + } + +#endif //AVCODEC_AMFENC_H diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c new file mode 100644 index 0000000000000..3cacf320e3c17 --- /dev/null +++ b/libavcodec/amfenc_h264.c @@ -0,0 +1,395 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "amfenc.h" +#include "internal.h" + +#define OFFSET(x) offsetof(AmfContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM + +static const AVOption options[] = { + // Static + /// Usage + { "usage", "Encoder Usage", OFFSET(usage), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_USAGE_TRANSCONDING }, AMF_VIDEO_ENCODER_USAGE_TRANSCONDING, AMF_VIDEO_ENCODER_USAGE_WEBCAM, VE, "usage" }, + { "transcoding", "Generic Transcoding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_TRANSCONDING }, 0, 0, VE, "usage" }, + { "ultralowlatency","", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY }, 0, 0, VE, "usage" }, + { "lowlatency", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY }, 0, 0, VE, "usage" }, + { "webcam", "Webcam", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_WEBCAM }, 0, 0, VE, "usage" }, + + /// Profile, + { "profile", "Profile", OFFSET(profile),AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_PROFILE_MAIN }, AMF_VIDEO_ENCODER_PROFILE_BASELINE, AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH, VE, "profile" }, + { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_MAIN }, 0, 0, VE, "profile" }, + { "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_HIGH }, 0, 0, VE, "profile" }, + { "constrained_baseline", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_BASELINE }, 0, 0, VE, "profile" }, + { "constrained_high", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH }, 0, 0, VE, "profile" }, + + /// Profile Level + { "level", "Profile Level", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 62, VE, "level" }, + { "auto", "", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "level" }, + { "1.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 10 }, 0, 0, VE, "level" }, + { "1.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 11 }, 0, 0, VE, "level" }, + { "1.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 12 }, 0, 0, VE, "level" }, + { "1.3", "", 0, AV_OPT_TYPE_CONST, { .i64 = 13 }, 0, 0, VE, "level" }, + { "2.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 20 }, 0, 0, VE, "level" }, + { "2.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 21 }, 0, 0, VE, "level" }, + { "2.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 22 }, 0, 0, VE, "level" }, + { "3.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 30 }, 0, 0, VE, "level" }, + { "3.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 31 }, 0, 0, VE, "level" }, + { "3.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 32 }, 0, 0, VE, "level" }, + { "4.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 40 }, 0, 0, VE, "level" }, + { "4.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 41 }, 0, 0, VE, "level" }, + { "4.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 42 }, 0, 0, VE, "level" }, + { "5.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 50 }, 0, 0, VE, "level" }, + { "5.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 51 }, 0, 0, VE, "level" }, + { "5.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 52 }, 0, 0, VE, "level" }, + { "6.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 60 }, 0, 0, VE, "level" }, + { "6.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 61 }, 0, 0, VE, "level" }, + { "6.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 62 }, 0, 0, VE, "level" }, + + + /// Quality Preset + { "quality", "Quality Preference", OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED }, AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED, AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY, VE, "quality" }, + { "speed", "Prefer Speed", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED }, 0, 0, VE, "quality" }, + { "balanced", "Balanced", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED }, 0, 0, VE, "quality" }, + { "quality", "Prefer Quality", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY }, 0, 0, VE, "quality" }, + + // Dynamic + /// Rate Control Method + { "rc", "Rate Control Method", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR, VE, "rc" }, + { "cqp", "Constant Quantization Parameter", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP }, 0, 0, VE, "rc" }, + { "cbr", "Constant Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR }, 0, 0, VE, "rc" }, + { "vbr_peak", "Peak Contrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + { "vbr_latency", "Latency Constrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + + /// Enforce HRD, Filler Data, VBAQ, Frame Skipping + { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "filler_data", "Filler Data Enable", OFFSET(filler_data), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "vbaq", "Enable VBAQ", OFFSET(enable_vbaq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "frame_skipping", "Rate Control Based Frame Skip", OFFSET(skip_frame), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + + /// QP Values + { "qp_i", "Quantization Parameter for I-Frame", OFFSET(qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "qp_p", "Quantization Parameter for P-Frame", OFFSET(qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "qp_b", "Quantization Parameter for B-Frame", OFFSET(qp_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + + /// Pre-Pass, Pre-Analysis, Two-Pass + { "preanalysis", "Pre-Analysis Mode", OFFSET(preanalysis), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE, NULL }, + + /// Maximum Access Unit Size + { "max_au_size", "Maximum Access Unit Size for rate control (in bits)", OFFSET(max_au_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, + + /// Header Insertion Spacing + { "header_spacing", "Header Insertion Spacing", OFFSET(header_spacing), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1000, VE }, + + /// B-Frames + // BPicturesPattern=bf + { "bf_delta_qp", "B-Picture Delta QP", OFFSET(b_frame_delta_qp), AV_OPT_TYPE_INT, { .i64 = 4 }, -10, 10, VE }, + { "bf_ref", "Enable Reference to B-Frames", OFFSET(b_frame_ref), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + { "bf_ref_delta_qp","Reference B-Picture Delta QP", OFFSET(ref_b_frame_delta_qp), AV_OPT_TYPE_INT, { .i64 = 4 }, -10, 10, VE }, + + /// Intra-Refresh + { "intra_refresh_mb","Intra Refresh MBs Number Per Slot in Macroblocks", OFFSET(intra_refresh_mb), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, + + /// coder + { "coder", "Coding Type", OFFSET(coding_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_UNDEFINED }, AMF_VIDEO_ENCODER_UNDEFINED, AMF_VIDEO_ENCODER_CALV, VE, "coder" }, + { "auto", "Automatic", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_UNDEFINED }, 0, 0, VE, "coder" }, + { "cavlc", "Context Adaptive Variable-Length Coding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_CALV }, 0, 0, VE, "coder" }, + { "cabac", "Context Adaptive Binary Arithmetic Coding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_CABAC }, 0, 0, VE, "coder" }, + + { "me_half_pel", "Enable ME Half Pixel", OFFSET(me_half_pel), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + { "me_quarter_pel", "Enable ME Quarter Pixel", OFFSET(me_quarter_pel),AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + + { "aud", "Inserts AU Delimiter NAL unit", OFFSET(aud) ,AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + + { "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg) , AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + + { NULL } +}; + +static av_cold int amf_encode_init_h264(AVCodecContext *avctx) +{ + int ret = 0; + AMF_RESULT res = AMF_OK; + AmfContext *ctx = avctx->priv_data; + AMFVariantStruct var = { 0 }; + amf_int64 profile = 0; + amf_int64 profile_level = 0; + AMFBuffer *buffer; + AMFGuid guid; + AMFRate framerate; + AMFSize framesize = AMFConstructSize(avctx->width, avctx->height); + int deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0; + + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); + } else { + framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num * avctx->ticks_per_frame); + } + + if ((ret = ff_amf_encode_init(avctx)) != 0) + return ret; + + // Static parameters + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_USAGE, ctx->usage); + + AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder, AMF_VIDEO_ENCODER_FRAMESIZE, framesize); + + AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_FRAMERATE, framerate); + + switch (avctx->profile) { + case FF_PROFILE_H264_BASELINE: + profile = AMF_VIDEO_ENCODER_PROFILE_BASELINE; + break; + case FF_PROFILE_H264_MAIN: + profile = AMF_VIDEO_ENCODER_PROFILE_MAIN; + break; + case FF_PROFILE_H264_HIGH: + profile = AMF_VIDEO_ENCODER_PROFILE_HIGH; + break; + case FF_PROFILE_H264_CONSTRAINED_BASELINE: + profile = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_BASELINE; + break; + case (FF_PROFILE_H264_HIGH | FF_PROFILE_H264_CONSTRAINED): + profile = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH; + break; + } + if (profile == 0) { + profile = ctx->profile; + } + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PROFILE, profile); + + profile_level = avctx->level; + if (profile_level == FF_LEVEL_UNKNOWN) { + profile_level = ctx->level; + } + if (profile_level != 0) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PROFILE_LEVEL, profile_level); + } + + // Maximum Reference Frames + if (avctx->refs != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_NUM_REFRAMES, avctx->refs); + } + if (avctx->sample_aspect_ratio.den && avctx->sample_aspect_ratio.num) { + AMFRatio ratio = AMFConstructRatio(avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den); + AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_ASPECT_RATIO, ratio); + } + + /// Color Range (Partial/TV/MPEG or Full/PC/JPEG) + if (avctx->color_range == AVCOL_RANGE_JPEG) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, 1); + } + + // autodetect rate control method + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN) { + if (ctx->qp_i != -1 || ctx->qp_p != -1 || ctx->qp_b != -1) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CQP\n"); + } else if (avctx->rc_max_rate > 0 ) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to Peak VBR\n"); + } else { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n"); + } + } + + + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE, AMF_VIDEO_ENCODER_PREENCODE_DISABLED); + if (ctx->preanalysis) + av_log(ctx, AV_LOG_WARNING, "Pre-Analysis is not supported by cqp Rate Control Method, automatically disabled\n"); + } else { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE, ctx->preanalysis); + } + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUALITY_PRESET, ctx->quality); + + // Initialize Encoder + res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); + + // Dynamic parmaters + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD, ctx->rate_control_mode); + + /// VBV Buffer + if (avctx->rc_buffer_size != 0) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_VBV_BUFFER_SIZE, avctx->rc_buffer_size); + if (avctx->rc_initial_buffer_occupancy != 0) { + int amf_buffer_fullness = avctx->rc_initial_buffer_occupancy * 64 / avctx->rc_buffer_size; + if (amf_buffer_fullness > 64) + amf_buffer_fullness = 64; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_INITIAL_VBV_BUFFER_FULLNESS, amf_buffer_fullness); + } + } + /// Maximum Access Unit Size + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_AU_SIZE, ctx->max_au_size); + + if (ctx->max_au_size) + ctx->enforce_hrd = 1; + + // QP Minimum / Maximum + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, 0); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, 51); + } else { + if (avctx->qmin != -1) { + int qval = avctx->qmin > 51 ? 51 : avctx->qmin; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, qval); + } + if (avctx->qmax != -1) { + int qval = avctx->qmax > 51 ? 51 : avctx->qmax; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, qval); + } + } + // QP Values + if (ctx->qp_i != -1) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_I, ctx->qp_i); + if (ctx->qp_p != -1) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_P, ctx->qp_p); + if (ctx->qp_b != -1) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_B, ctx->qp_b); + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_TARGET_BITRATE, avctx->bit_rate); + + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PEAK_BITRATE, avctx->bit_rate); + } + if (avctx->rc_max_rate) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PEAK_BITRATE, avctx->rc_max_rate); + } else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { + av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); + } + // Enforce HRD, Filler Data, VBAQ, Frame Skipping, Deblocking Filter + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENFORCE_HRD, !!ctx->enforce_hrd); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE, !!ctx->filler_data); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_SKIP_FRAME_ENABLE, !!ctx->skip_frame); + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, 0); + if (ctx->enable_vbaq) + av_log(ctx, AV_LOG_WARNING, "VBAQ is not supported by cqp Rate Control Method, automatically disabled\n"); + } else { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, !!ctx->enable_vbaq); + } + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, !!deblocking_filter); + + // B-Frames + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, avctx->max_b_frames); + if (res != AMF_OK) { + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, &var); + av_log(ctx, AV_LOG_WARNING, "B-frames=%d is not supported by this GPU, switched to %d\n", + avctx->max_b_frames, (int)var.int64Value); + avctx->max_b_frames = (int)var.int64Value; + } + if (avctx->max_b_frames) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_DELTA_QP, ctx->b_frame_delta_qp); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_B_REFERENCE_ENABLE, !!ctx->b_frame_ref); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP, ctx->ref_b_frame_delta_qp); + } + + // Keyframe Interval + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_IDR_PERIOD, avctx->gop_size); + + // Header Insertion Spacing + if (ctx->header_spacing >= 0) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEADER_INSERTION_SPACING, ctx->header_spacing); + + // Intra-Refresh, Slicing + if (ctx->intra_refresh_mb > 0) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_INTRA_REFRESH_NUM_MBS_PER_SLOT, ctx->intra_refresh_mb); + if (avctx->slices > 1) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_SLICES_PER_FRAME, avctx->slices); + + // Coding + if (ctx->coding_mode != 0) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_CABAC_ENABLE, ctx->coding_mode); + + // Motion Estimation + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_MOTION_HALF_PIXEL, !!ctx->me_half_pel); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_MOTION_QUARTERPIXEL, !!ctx->me_quarter_pel); + + // fill extradata + res = AMFVariantInit(&var); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res); + + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_EXTRADATA, &var); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) failed with error %d\n", res); + AMF_RETURN_IF_FALSE(ctx, var.pInterface != NULL, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) returned NULL\n"); + + guid = IID_AMFBuffer(); + + res = var.pInterface->pVtbl->QueryInterface(var.pInterface, &guid, (void**)&buffer); // query for buffer interface + if (res != AMF_OK) { + var.pInterface->pVtbl->Release(var.pInterface); + } + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "QueryInterface(IID_AMFBuffer) failed with error %d\n", res); + + avctx->extradata_size = (int)buffer->pVtbl->GetSize(buffer); + avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + buffer->pVtbl->Release(buffer); + var.pInterface->pVtbl->Release(var.pInterface); + return AVERROR(ENOMEM); + } + memcpy(avctx->extradata, buffer->pVtbl->GetNative(buffer), avctx->extradata_size); + + buffer->pVtbl->Release(buffer); + var.pInterface->pVtbl->Release(var.pInterface); + + return 0; +} + +static const AVCodecDefault defaults[] = { + { "refs", "-1" }, + { "aspect", "0" }, + { "sar", "0" }, + { "qmin", "-1" }, + { "qmax", "-1" }, + { "b", "2M" }, + { "g", "250" }, + { "slices", "1" }, + { NULL }, +}; + +static const AVClass h264_amf_class = { + .class_name = "h264_amf", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; +//TODO declare as HW encoder when available +AVCodec ff_h264_amf_encoder = { + .name = "h264_amf", + .long_name = NULL_IF_CONFIG_SMALL("AMD AMF H.264 Encoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .init = amf_encode_init_h264, + .send_frame = ff_amf_send_frame, + .receive_packet = ff_amf_receive_packet, + .close = ff_amf_encode_close, + .priv_data_size = sizeof(AmfContext), + .priv_class = &h264_amf_class, + .defaults = defaults, + .capabilities = AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .pix_fmts = ff_amf_pix_fmts, +}; diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c new file mode 100644 index 0000000000000..ced57b1e9abd0 --- /dev/null +++ b/libavcodec/amfenc_hevc.c @@ -0,0 +1,326 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "amfenc.h" +#include "internal.h" + +#define OFFSET(x) offsetof(AmfContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "usage", "Set the encoding usage", OFFSET(usage), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING }, AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING, AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM, VE, "usage" }, + { "transcoding", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING }, 0, 0, VE, "usage" }, + { "ultralowlatency","", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY }, 0, 0, VE, "usage" }, + { "lowlatency", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY }, 0, 0, VE, "usage" }, + { "webcam", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM }, 0, 0, VE, "usage" }, + + { "profile", "Set the profile (default main)", OFFSET(profile), AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN }, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN, VE, "profile" }, + { "main", "", 0, AV_OPT_TYPE_CONST,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN }, 0, 0, VE, "profile" }, + + { "profile_tier", "Set the profile tier (default main)", OFFSET(tier), AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN }, AMF_VIDEO_ENCODER_HEVC_TIER_MAIN, AMF_VIDEO_ENCODER_HEVC_TIER_HIGH, VE, "tier" }, + { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN }, 0, 0, VE, "tier" }, + { "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_HIGH }, 0, 0, VE, "tier" }, + + { "level", "Set the encoding level (default auto)", OFFSET(level), AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, AMF_LEVEL_6_2, VE, "level" }, + { "auto", "", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "level" }, + { "1.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_1 }, 0, 0, VE, "level" }, + { "2.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_2 }, 0, 0, VE, "level" }, + { "2.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_2_1 }, 0, 0, VE, "level" }, + { "3.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_3 }, 0, 0, VE, "level" }, + { "3.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_3_1 }, 0, 0, VE, "level" }, + { "4.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_4 }, 0, 0, VE, "level" }, + { "4.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_4_1 }, 0, 0, VE, "level" }, + { "5.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_5 }, 0, 0, VE, "level" }, + { "5.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_5_1 }, 0, 0, VE, "level" }, + { "5.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_5_2 }, 0, 0, VE, "level" }, + { "6.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_6 }, 0, 0, VE, "level" }, + { "6.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_6_1 }, 0, 0, VE, "level" }, + { "6.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_6_2 }, 0, 0, VE, "level" }, + + { "quality", "Set the encoding quality", OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED }, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED, VE, "quality" }, + { "balanced", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED }, 0, 0, VE, "quality" }, + { "speed", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED }, 0, 0, VE, "quality" }, + { "quality", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY }, 0, 0, VE, "quality" }, + + { "rc", "Set the rate control mode", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR, VE, "rc" }, + { "cqp", "Constant Quantization Parameter", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP }, 0, 0, VE, "rc" }, + { "cbr", "Constant Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR }, 0, 0, VE, "rc" }, + { "vbr_peak", "Peak Contrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + { "vbr_latency", "Latency Constrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + + { "header_insertion_mode", "Set header insertion mode", OFFSET(header_insertion_mode), AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE }, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED, VE, "hdrmode" }, + { "none", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE }, 0, 0, VE, "hdrmode" }, + { "gop", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, "hdrmode" }, + { "idr", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED }, 0, 0, VE, "hdrmode" }, + + { "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 60 }, 0, INT_MAX, VE }, + { "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, + { "vbaq", "Enable VBAQ", OFFSET(enable_vbaq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, + { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, + { "filler_data", "Filler Data Enable", OFFSET(filler_data), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, + { "max_au_size", "Maximum Access Unit Size for rate control (in bits)", OFFSET(max_au_size), AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, INT_MAX, VE}, + { "min_qp_i", "min quantization parameter for I-frame", OFFSET(min_qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "max_qp_i", "max quantization parameter for I-frame", OFFSET(max_qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "min_qp_p", "min quantization parameter for P-frame", OFFSET(min_qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "max_qp_p", "max quantization parameter for P-frame", OFFSET(max_qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "qp_p", "quantization parameter for P-frame", OFFSET(qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "qp_i", "quantization parameter for I-frame", OFFSET(qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "skip_frame", "Rate Control Based Frame Skip", OFFSET(skip_frame), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE }, + { "me_half_pel", "Enable ME Half Pixel", OFFSET(me_half_pel), AV_OPT_TYPE_BOOL,{ .i64 = 1 }, 0, 1, VE }, + { "me_quarter_pel", "Enable ME Quarter Pixel ", OFFSET(me_quarter_pel),AV_OPT_TYPE_BOOL,{ .i64 = 1 }, 0, 1, VE }, + + { "aud", "Inserts AU Delimiter NAL unit", OFFSET(aud) ,AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE }, + + { "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE }, + { NULL } +}; + +static av_cold int amf_encode_init_hevc(AVCodecContext *avctx) +{ + int ret = 0; + AMF_RESULT res = AMF_OK; + AmfContext *ctx = avctx->priv_data; + AMFVariantStruct var = {0}; + amf_int64 profile = 0; + amf_int64 profile_level = 0; + AMFBuffer *buffer; + AMFGuid guid; + AMFRate framerate; + AMFSize framesize = AMFConstructSize(avctx->width, avctx->height); + int deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0; + + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); + } else { + framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num * avctx->ticks_per_frame); + } + + if ((ret = ff_amf_encode_init(avctx)) < 0) + return ret; + + // init static parameters + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_USAGE, ctx->usage); + + AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FRAMESIZE, framesize); + + AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FRAMERATE, framerate); + + switch (avctx->profile) { + case FF_PROFILE_HEVC_MAIN: + profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN; + break; + default: + break; + } + if (profile == 0) { + profile = ctx->profile; + } + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PROFILE, profile); + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TIER, ctx->tier); + + profile_level = avctx->level; + if (profile_level == 0) { + profile_level = ctx->level; + } + if (profile_level != 0) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PROFILE_LEVEL, profile_level); + } + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET, ctx->quality); + // Maximum Reference Frames + if (avctx->refs != 0) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_NUM_REFRAMES, avctx->refs); + } + // Aspect Ratio + if (avctx->sample_aspect_ratio.den && avctx->sample_aspect_ratio.num) { + AMFRatio ratio = AMFConstructRatio(avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den); + AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO, ratio); + } + + // Picture control properties + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NUM_GOPS_PER_IDR, ctx->gops_per_idr); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, avctx->gop_size); + if (avctx->slices > 1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_SLICES_PER_FRAME, avctx->slices); + } + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_DE_BLOCKING_FILTER_DISABLE, deblocking_filter); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE, ctx->header_insertion_mode); + + // Rate control + // autodetect rate control method + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN) { + if (ctx->min_qp_i != -1 || ctx->max_qp_i != -1 || + ctx->min_qp_p != -1 || ctx->max_qp_p != -1 || + ctx->qp_i !=-1 || ctx->qp_p != -1) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CQP\n"); + } else if (avctx->rc_max_rate > 0) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to Peak VBR\n"); + } else { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n"); + } + } + + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD, ctx->rate_control_mode); + if (avctx->rc_buffer_size) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_VBV_BUFFER_SIZE, avctx->rc_buffer_size); + + if (avctx->rc_initial_buffer_occupancy != 0) { + int amf_buffer_fullness = avctx->rc_initial_buffer_occupancy * 64 / avctx->rc_buffer_size; + if (amf_buffer_fullness > 64) + amf_buffer_fullness = 64; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_INITIAL_VBV_BUFFER_FULLNESS, amf_buffer_fullness); + } + } + // Pre-Pass, Pre-Analysis, Two-Pass + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_PREANALYSIS_ENABLE, ctx->preanalysis); + + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, false); + if (ctx->enable_vbaq) + av_log(ctx, AV_LOG_WARNING, "VBAQ is not supported by cqp Rate Control Method, automatically disabled\n"); + } else { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, !!ctx->enable_vbaq); + } + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MOTION_HALF_PIXEL, ctx->me_half_pel); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MOTION_QUARTERPIXEL, ctx->me_quarter_pel); + + // init encoder + res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); + + // init dynamic rate control params + if (ctx->max_au_size) + ctx->enforce_hrd = 1; + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENFORCE_HRD, ctx->enforce_hrd); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FILLER_DATA_ENABLE, ctx->filler_data); + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TARGET_BITRATE, avctx->bit_rate); + + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE, avctx->bit_rate); + } + if (avctx->rc_max_rate) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE, avctx->rc_max_rate); + } else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { + av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); + } + + // init dynamic picture control params + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_AU_SIZE, ctx->max_au_size); + + if (ctx->min_qp_i != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, ctx->min_qp_i); + } else if (avctx->qmin != -1) { + int qval = avctx->qmin > 51 ? 51 : avctx->qmin; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, qval); + } + if (ctx->max_qp_i != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, ctx->max_qp_i); + } else if (avctx->qmax != -1) { + int qval = avctx->qmax > 51 ? 51 : avctx->qmax; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, qval); + } + if (ctx->min_qp_p != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, ctx->min_qp_p); + } else if (avctx->qmin != -1) { + int qval = avctx->qmin > 51 ? 51 : avctx->qmin; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, qval); + } + if (ctx->max_qp_p != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, ctx->max_qp_p); + } else if (avctx->qmax != -1) { + int qval = avctx->qmax > 51 ? 51 : avctx->qmax; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, qval); + } + + if (ctx->qp_p != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_I, ctx->qp_p); + } + if (ctx->qp_i != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_P, ctx->qp_i); + } + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_SKIP_FRAME_ENABLE, ctx->skip_frame); + + + // fill extradata + res = AMFVariantInit(&var); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res); + + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_HEVC_EXTRADATA, &var); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) failed with error %d\n", res); + AMF_RETURN_IF_FALSE(ctx, var.pInterface != NULL, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) returned NULL\n"); + + guid = IID_AMFBuffer(); + + res = var.pInterface->pVtbl->QueryInterface(var.pInterface, &guid, (void**)&buffer); // query for buffer interface + if (res != AMF_OK) { + var.pInterface->pVtbl->Release(var.pInterface); + } + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "QueryInterface(IID_AMFBuffer) failed with error %d\n", res); + + avctx->extradata_size = (int)buffer->pVtbl->GetSize(buffer); + avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + buffer->pVtbl->Release(buffer); + var.pInterface->pVtbl->Release(var.pInterface); + return AVERROR(ENOMEM); + } + memcpy(avctx->extradata, buffer->pVtbl->GetNative(buffer), avctx->extradata_size); + + buffer->pVtbl->Release(buffer); + var.pInterface->pVtbl->Release(var.pInterface); + + return 0; +} +static const AVCodecDefault defaults[] = { + { "refs", "-1" }, + { "aspect", "0" }, + { "sar", "0" }, + { "b", "2M" }, + { "g", "250" }, + { "slices", "1" }, + { NULL }, +}; +static const AVClass hevc_amf_class = { + .class_name = "hevc_amf", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; +//TODO declare as HW encoder when available +AVCodec ff_hevc_amf_encoder = { + .name = "hevc_amf", + .long_name = NULL_IF_CONFIG_SMALL("AMD AMF HEVC encoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .init = amf_encode_init_hevc, + .send_frame = ff_amf_send_frame, + .receive_packet = ff_amf_receive_packet, + .close = ff_amf_encode_close, + .priv_data_size = sizeof(AmfContext), + .priv_class = &hevc_amf_class, + .defaults = defaults, + .capabilities = AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .pix_fmts = ff_amf_pix_fmts, +}; From ed4a0c7923e8935d1829029a2c7eb980269f8ca3 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Mon, 27 Nov 2017 23:54:33 +0100 Subject: [PATCH 1174/2557] ffmpeg_opt: Constify hwaccel pointer. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes a warning: fftools/ffmpeg_opt.c:804:29: warning: assignment discards ‘const’ qualifier from pointer target type --- fftools/ffmpeg_opt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 672054223aebb..a6e36ac8229df 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -702,7 +702,8 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) AVStream *st = ic->streams[i]; AVCodecParameters *par = st->codecpar; InputStream *ist = av_mallocz(sizeof(*ist)); - char *framerate = NULL, *hwaccel = NULL, *hwaccel_device = NULL; + char *framerate = NULL, *hwaccel_device = NULL; + const char *hwaccel = NULL; char *hwaccel_output_format = NULL; char *codec_tag = NULL; char *next; From 86cead525633cd6114824b33a74d71be677f9546 Mon Sep 17 00:00:00 2001 From: James Zern Date: Mon, 20 Nov 2017 17:32:23 -0800 Subject: [PATCH 1175/2557] libvpxenc,vp9: add corpus-complexity option Corpus VBR mode is a variant of standard VBR where the complexity distribution midpoint is passed in rather than calculated for a specific clip or chunk. The valid range is [0, 10000]. 0 (default) uses standard VBR. Signed-off-by: James Zern --- doc/encoders.texi | 5 +++++ libavcodec/libvpxenc.c | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index 23451b7b920ae..88ef8f9b230b4 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -1683,6 +1683,11 @@ colorspaces: Enable row based multi-threading. @item tune-content Set content type: default (0), screen (1), film (2). +@item corpus-complexity +Corpus VBR mode is a variant of standard VBR where the complexity distribution +midpoint is passed in rather than calculated for a specific clip or chunk. + +The valid range is [0, 10000]. 0 (default) uses standard VBR. @end table @end table diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 0258396d08a03..9861e9d5ae164 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -110,6 +110,7 @@ typedef struct VPxEncoderContext { float level; int row_mt; int tune_content; + int corpus_complexity; } VPxContext; /** String mappings for enum vp8e_enc_control_id */ @@ -213,6 +214,10 @@ static av_cold void dump_enc_cfg(AVCodecContext *avctx, width, "rc_2pass_vbr_bias_pct:", cfg->rc_2pass_vbr_bias_pct, width, "rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct, width, "rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct); +#if VPX_ENCODER_ABI_VERSION >= 14 + av_log(avctx, level, " %*s%u\n", + width, "rc_2pass_vbr_corpus_complexity:", cfg->rc_2pass_vbr_corpus_complexity); +#endif av_log(avctx, level, "keyframing settings\n" " %*s%d\n %*s%u\n %*s%u\n", width, "kf_mode:", cfg->kf_mode, @@ -565,6 +570,14 @@ FF_ENABLE_DEPRECATION_WARNINGS if (avctx->rc_max_rate) enccfg.rc_2pass_vbr_maxsection_pct = avctx->rc_max_rate * 100LL / avctx->bit_rate; +#if CONFIG_LIBVPX_VP9_ENCODER + if (avctx->codec_id == AV_CODEC_ID_VP9) { +#if VPX_ENCODER_ABI_VERSION >= 14 + if (ctx->corpus_complexity >= 0) + enccfg.rc_2pass_vbr_corpus_complexity = ctx->corpus_complexity; +#endif + } +#endif if (avctx->rc_buffer_size) enccfg.rc_buf_sz = @@ -1140,6 +1153,9 @@ static const AVOption vp9_options[] = { #if VPX_ENCODER_ABI_VERSION >= 14 { "film", "Film content; improves grain retention", 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE, "tune_content" }, #endif +#endif +#if VPX_ENCODER_ABI_VERSION >= 14 + { "corpus-complexity", "corpus vbr complexity midpoint", OFFSET(corpus_complexity), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 10000, VE }, #endif LEGACY_OPTIONS { NULL } From a3a0b5bd0aaae314619d5b41fb918aacd908a5ae Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Tue, 28 Nov 2017 13:44:49 -0800 Subject: [PATCH 1176/2557] avformat/oggparseopus: Free opus extradata before reallocating. Otherwise ff_alloc_extradata() just leaks any existing allocated memory. Signed-off-by: Dale Curtis Signed-off-by: Michael Niedermayer --- libavformat/oggparseopus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/oggparseopus.c b/libavformat/oggparseopus.c index f45ad848744a4..cd34cf23ba62f 100644 --- a/libavformat/oggparseopus.c +++ b/libavformat/oggparseopus.c @@ -62,6 +62,7 @@ static int opus_header(AVFormatContext *avf, int idx) /*gain = AV_RL16(packet + 16);*/ /*channel_map = AV_RL8 (packet + 18);*/ + av_freep(&st->codecpar->extradata); if (ff_alloc_extradata(st->codecpar, os->psize)) return AVERROR(ENOMEM); From c5fd57f483d2ad8e34551b78509f1e14136f73c0 Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Tue, 28 Nov 2017 14:26:55 -0800 Subject: [PATCH 1177/2557] Don't manipulate duration when it's AV_NOPTS_VALUE. This leads to signed integer overflow. Signed-off-by: Dale Curtis Signed-off-by: James Almer --- libavformat/oggparsevp8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/oggparsevp8.c b/libavformat/oggparsevp8.c index c534ab117d94e..b76ac71cc5075 100644 --- a/libavformat/oggparsevp8.c +++ b/libavformat/oggparsevp8.c @@ -125,7 +125,7 @@ static int vp8_packet(AVFormatContext *s, int idx) os->lastdts = vp8_gptopts(s, idx, os->granule, NULL) - duration; if(s->streams[idx]->start_time == AV_NOPTS_VALUE) { s->streams[idx]->start_time = os->lastpts; - if (s->streams[idx]->duration) + if (s->streams[idx]->duration && s->streams[idx]->duration != AV_NOPTS_VALUE) s->streams[idx]->duration -= s->streams[idx]->start_time; } } From 62f63b24bfec22134bc5b9312bc6afe824e63199 Mon Sep 17 00:00:00 2001 From: "Jeyapal, Karthick" Date: Wed, 29 Nov 2017 14:31:34 +0800 Subject: [PATCH 1178/2557] libavformat/avio: Utility function to return URLContext --- libavformat/avio_internal.h | 8 ++++++++ libavformat/aviobuf.c | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h index c01835df96fc1..04c1ad5157bf1 100644 --- a/libavformat/avio_internal.h +++ b/libavformat/avio_internal.h @@ -132,6 +132,14 @@ int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size); */ int ffio_fdopen(AVIOContext **s, URLContext *h); +/** + * Return the URLContext associated with the AVIOContext + * + * @param s IO context + * @return pointer to URLContext or NULL. + */ +URLContext *ffio_geturlcontext(AVIOContext *s); + /** * Open a write-only fake memory stream. The written data is not stored * anywhere - this is only used for measuring the amount of data diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 3b4c8439d6ce1..86eb6579f43e4 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -980,6 +980,19 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) return AVERROR(ENOMEM); } +URLContext* ffio_geturlcontext(AVIOContext *s) +{ + AVIOInternal *internal; + if (!s) + return NULL; + + internal = s->opaque; + if (internal && s->read_packet == io_read_packet) + return internal->h; + else + return NULL; +} + int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size) { uint8_t *buffer; From 4ddf7476c009643e719993cb27411aeca6bf78e4 Mon Sep 17 00:00:00 2001 From: "Jeyapal, Karthick" Date: Wed, 29 Nov 2017 14:32:16 +0800 Subject: [PATCH 1179/2557] libavformat/http: Handled multiple_requests option during write --- libavformat/http.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index 056d5f6583766..cf86adc6171bd 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -171,6 +171,7 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, const char *hoststr, const char *auth, const char *proxyauth, int *new_location); static int http_read_header(URLContext *h, int *new_location); +static int http_shutdown(URLContext *h, int flags); void ff_http_init_auth_state(URLContext *dest, const URLContext *src) { @@ -306,6 +307,11 @@ int ff_http_do_new_request(URLContext *h, const char *uri) AVDictionary *options = NULL; int ret; + ret = http_shutdown(h, h->flags); + if (ret < 0) + return ret; + + s->end_chunked_post = 0; s->chunkend = 0; s->off = 0; s->icy_data_read = 0; From 815e34b5b4ed8fbb6c9d7b7b042ae49848bc170c Mon Sep 17 00:00:00 2001 From: "Jeyapal, Karthick" Date: Wed, 29 Nov 2017 14:33:07 +0800 Subject: [PATCH 1180/2557] libavformat/hlsenc: Persistent HTTP connections supported as an option --- doc/muxers.texi | 3 +++ libavformat/hlsenc.c | 48 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 9d9ca31cc4fb4..8ec48c20552f4 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -854,6 +854,9 @@ ffmpeg -re -i in.ts -f hls -master_pl_name master.m3u8 \ This example creates HLS master playlist with name master.m3u8 and keep publishing it repeatedly every after 30 segments i.e. every after 60s. +@item http_persistent +Use persistent HTTP connections. Applicable only for HTTP output. + @end table @anchor{ico} diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 6997a5ced0dd6..d5c732f472ad0 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -45,6 +45,7 @@ #include "avformat.h" #include "avio_internal.h" +#include "http.h" #include "internal.h" #include "os_support.h" @@ -205,6 +206,7 @@ typedef struct HLSContext { char *var_stream_map; /* user specified variant stream map string */ char *master_pl_name; unsigned int master_publish_rate; + int http_persistent; } HLSContext; static int get_int_from_double(double val) @@ -245,10 +247,38 @@ static int mkdir_p(const char *path) { return ret; } +static int is_http_proto(char *filename) { + const char *proto = avio_find_protocol_name(filename); + return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, "https")) : 0; +} + +static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, + AVDictionary **options) { + HLSContext *hls = s->priv_data; + int http_base_proto = is_http_proto(filename); + int err; + if (!*pb || !http_base_proto || !hls->http_persistent) { + err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options); + } else { + URLContext *http_url_context = ffio_geturlcontext(*pb); + av_assert0(http_url_context); + err = ff_http_do_new_request(http_url_context, filename); + } + return err; +} + +static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) { + HLSContext *hls = s->priv_data; + int http_base_proto = is_http_proto(filename); + + if (!http_base_proto || !hls->http_persistent || hls->key_info_file || hls->encrypt) { + ff_format_io_close(s, pb); + } +} + static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSContext *c) { - const char *proto = avio_find_protocol_name(s->filename); - int http_base_proto = proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, "https")) : 0; + int http_base_proto = is_http_proto(s->filename); if (c->method) { av_dict_set(options, "method", c->method, 0); @@ -258,6 +288,8 @@ static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSCont } if (c->user_agent) av_dict_set(options, "user_agent", c->user_agent, 0); + if (c->http_persistent) + av_dict_set_int(options, "multiple_requests", 1, 0); } @@ -1437,17 +1469,17 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) err = AVERROR(ENOMEM); goto fail; } - err = s->io_open(s, &oc->pb, filename, AVIO_FLAG_WRITE, &options); + err = hlsenc_io_open(s, &oc->pb, filename, &options); av_free(filename); av_dict_free(&options); if (err < 0) return err; } else - if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, &options)) < 0) + if ((err = hlsenc_io_open(s, &oc->pb, oc->filename, &options)) < 0) goto fail; if (vs->vtt_basename) { set_http_options(s, &options, c); - if ((err = s->io_open(s, &vtt_oc->pb, vtt_oc->filename, AVIO_FLAG_WRITE, &options)) < 0) + if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->filename, &options)) < 0) goto fail; } av_dict_free(&options); @@ -2165,11 +2197,12 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) avio_open_dyn_buf(&oc->pb); vs->packets_written = 0; ff_format_io_close(s, &vs->out); + hlsenc_io_close(s, &vs->out, vs->base_output_dirname); } else { - ff_format_io_close(s, &oc->pb); + hlsenc_io_close(s, &oc->pb, oc->filename); } if (vs->vtt_avf) { - ff_format_io_close(s, &vs->vtt_avf->pb); + hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->filename); } } if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) { @@ -2355,6 +2388,7 @@ static const AVOption options[] = { {"var_stream_map", "Variant stream map string", OFFSET(var_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"master_pl_name", "Create HLS master playlist with this name", OFFSET(master_pl_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"master_pl_publish_rate", "Publish master play list every after this many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E}, + {"http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, { NULL }, }; From eb69e7bed80a1c8afee9acf9f8daff6be5e9ea62 Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Mon, 27 Nov 2017 09:52:50 +0800 Subject: [PATCH 1181/2557] avcodec/nvenc: set correct error code In function process_output_surface(), the return value is 0 on the path that av_mallocz() returns a NULL pointer. 0 indicates success, which deviates from the fact. Return "AVERROR(ENOMEM)" instead of "0". Signed-off-by: Pan Bian Signed-off-by: Timo Rothenpieler --- libavcodec/nvenc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 79f7dce5f137e..4a91d9972014f 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -1763,8 +1763,10 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur } slice_offsets = av_mallocz(slice_mode_data * sizeof(*slice_offsets)); - if (!slice_offsets) + if (!slice_offsets) { + res = AVERROR(ENOMEM); goto error; + } lock_params.version = NV_ENC_LOCK_BITSTREAM_VER; From da49cdf6401ea3caa616c226f24dfb407633acd0 Mon Sep 17 00:00:00 2001 From: Karthick J Date: Wed, 29 Nov 2017 19:44:15 +0800 Subject: [PATCH 1182/2557] avformat/hlsenc: Modularized playlist creation to allow reuse --- libavformat/Makefile | 2 +- libavformat/hlsenc.c | 115 ++++++------------------------- libavformat/hlsplaylist.c | 138 ++++++++++++++++++++++++++++++++++++++ libavformat/hlsplaylist.h | 51 ++++++++++++++ 4 files changed, 211 insertions(+), 95 deletions(-) create mode 100644 libavformat/hlsplaylist.c create mode 100644 libavformat/hlsplaylist.h diff --git a/libavformat/Makefile b/libavformat/Makefile index b1e7b193f48e1..fd8b9f9899a06 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -215,7 +215,7 @@ OBJS-$(CONFIG_HDS_MUXER) += hdsenc.o OBJS-$(CONFIG_HEVC_DEMUXER) += hevcdec.o rawdec.o OBJS-$(CONFIG_HEVC_MUXER) += rawenc.o OBJS-$(CONFIG_HLS_DEMUXER) += hls.o -OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o +OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o hlsplaylist.o OBJS-$(CONFIG_HNM_DEMUXER) += hnm.o OBJS-$(CONFIG_ICO_DEMUXER) += icodec.o OBJS-$(CONFIG_ICO_MUXER) += icoenc.o diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index d5c732f472ad0..f63b08d7094ba 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -46,6 +46,7 @@ #include "avformat.h" #include "avio_internal.h" #include "http.h" +#include "hlsplaylist.h" #include "internal.h" #include "os_support.h" @@ -97,13 +98,6 @@ typedef enum { SEGMENT_TYPE_FMP4, } SegmentType; -typedef enum { - PLAYLIST_TYPE_NONE, - PLAYLIST_TYPE_EVENT, - PLAYLIST_TYPE_VOD, - PLAYLIST_TYPE_NB, -} PlaylistType; - typedef struct VariantStream { unsigned number; int64_t sequence; @@ -1055,19 +1049,6 @@ static void hls_free_segments(HLSSegment *p) } } -static void write_m3u8_head_block(HLSContext *hls, AVIOContext *out, int version, - int target_duration, int64_t sequence) -{ - avio_printf(out, "#EXTM3U\n"); - avio_printf(out, "#EXT-X-VERSION:%d\n", version); - if (hls->allowcache == 0 || hls->allowcache == 1) { - avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", hls->allowcache == 0 ? "NO" : "YES"); - } - avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration); - avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence); - av_log(hls, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence); -} - static void hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc) { size_t len = strlen(oc->filename); @@ -1133,8 +1114,7 @@ static int create_master_playlist(AVFormatContext *s, goto fail; } - avio_printf(master_pb, "#EXTM3U\n"); - avio_printf(master_pb, "#EXT-X-VERSION:%d\n", hls->version); + ff_hls_write_playlist_version(master_pb, hls->version); /* For variant streams with video add #EXT-X-STREAM-INF tag with attributes*/ for (i = 0; i < hls->nb_varstreams; i++) { @@ -1175,18 +1155,7 @@ static int create_master_playlist(AVFormatContext *s, bandwidth += aud_st->codecpar->bit_rate; bandwidth += bandwidth / 10; - if (!bandwidth) { - av_log(NULL, AV_LOG_WARNING, - "Bandwidth info not available, set audio and video bitrates\n"); - av_freep(&m3u8_rel_name); - continue; - } - - avio_printf(master_pb, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth); - if (vid_st && vid_st->codecpar->width > 0 && vid_st->codecpar->height > 0) - avio_printf(master_pb, ",RESOLUTION=%dx%d", vid_st->codecpar->width, - vid_st->codecpar->height); - avio_printf(master_pb, "\n%s\n\n", m3u8_rel_name); + ff_hls_write_stream_info(vid_st, master_pb, bandwidth, m3u8_rel_name); av_freep(&m3u8_rel_name); } @@ -1215,6 +1184,7 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) char *iv_string = NULL; AVDictionary *options = NULL; double prog_date_time = vs->initial_prog_date_time; + double *prog_date_time_p = (hls->flags & HLS_PROGRAM_DATE_TIME) ? &prog_date_time : NULL; int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); hls->version = 3; @@ -1245,12 +1215,8 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) } vs->discontinuity_set = 0; - write_m3u8_head_block(hls, out, hls->version, target_duration, sequence); - if (hls->pl_type == PLAYLIST_TYPE_EVENT) { - avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n"); - } else if (hls->pl_type == PLAYLIST_TYPE_VOD) { - avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n"); - } + ff_hls_write_playlist_header(out, hls->version, hls->allowcache, + target_duration, sequence, hls->pl_type); if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && vs->discontinuity_set==0 ){ avio_printf(out, "#EXT-X-DISCONTINUITY\n"); @@ -1270,74 +1236,35 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) iv_string = en->iv_string; } - if (en->discont) { - avio_printf(out, "#EXT-X-DISCONTINUITY\n"); - } - if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == vs->segments)) { - avio_printf(out, "#EXT-X-MAP:URI=\"%s\"", vs->fmp4_init_filename); - if (hls->flags & HLS_SINGLE_FILE) { - avio_printf(out, ",BYTERANGE=\"%"PRId64"@%"PRId64"\"", en->size, en->pos); - } - avio_printf(out, "\n"); + ff_hls_write_init_file(out, vs->fmp4_init_filename, + hls->flags & HLS_SINGLE_FILE, en->size, en->pos); } - if (hls->flags & HLS_ROUND_DURATIONS) - avio_printf(out, "#EXTINF:%ld,\n", lrint(en->duration)); - else - avio_printf(out, "#EXTINF:%f,\n", en->duration); - if (byterange_mode) - avio_printf(out, "#EXT-X-BYTERANGE:%"PRId64"@%"PRId64"\n", - en->size, en->pos); - - if (hls->flags & HLS_PROGRAM_DATE_TIME) { - time_t tt, wrongsecs; - int milli; - struct tm *tm, tmpbuf; - char buf0[128], buf1[128]; - tt = (int64_t)prog_date_time; - milli = av_clip(lrint(1000*(prog_date_time - tt)), 0, 999); - tm = localtime_r(&tt, &tmpbuf); - strftime(buf0, sizeof(buf0), "%Y-%m-%dT%H:%M:%S", tm); - if (!strftime(buf1, sizeof(buf1), "%z", tm) || buf1[1]<'0' ||buf1[1]>'2') { - int tz_min, dst = tm->tm_isdst; - tm = gmtime_r(&tt, &tmpbuf); - tm->tm_isdst = dst; - wrongsecs = mktime(tm); - tz_min = (FFABS(wrongsecs - tt) + 30) / 60; - snprintf(buf1, sizeof(buf1), - "%c%02d%02d", - wrongsecs <= tt ? '+' : '-', - tz_min / 60, - tz_min % 60); - } - avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, milli, buf1); - prog_date_time += en->duration; - } - if (vs->baseurl) - avio_printf(out, "%s", vs->baseurl); - avio_printf(out, "%s\n", en->filename); + + ff_hls_write_file_entry(out, en->discont, byterange_mode, + en->duration, hls->flags & HLS_ROUND_DURATIONS, + en->size, en->pos, vs->baseurl, + en->filename, prog_date_time_p); + } if (last && (hls->flags & HLS_OMIT_ENDLIST)==0) - avio_printf(out, "#EXT-X-ENDLIST\n"); + ff_hls_write_end_list(out); if( vs->vtt_m3u8_name ) { if ((ret = s->io_open(s, &sub_out, vs->vtt_m3u8_name, AVIO_FLAG_WRITE, &options)) < 0) goto fail; - write_m3u8_head_block(hls, sub_out, hls->version, target_duration, sequence); + ff_hls_write_playlist_header(sub_out, hls->version, hls->allowcache, + target_duration, sequence, PLAYLIST_TYPE_NONE); for (en = vs->segments; en; en = en->next) { - avio_printf(sub_out, "#EXTINF:%f,\n", en->duration); - if (byterange_mode) - avio_printf(sub_out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n", - en->size, en->pos); - if (vs->baseurl) - avio_printf(sub_out, "%s", vs->baseurl); - avio_printf(sub_out, "%s\n", en->sub_filename); + ff_hls_write_file_entry(sub_out, 0, byterange_mode, + en->duration, 0, en->size, en->pos, + vs->baseurl, en->sub_filename, NULL); } if (last) - avio_printf(sub_out, "#EXT-X-ENDLIST\n"); + ff_hls_write_end_list(sub_out); } diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c new file mode 100644 index 0000000000000..235e519a9ef0b --- /dev/null +++ b/libavformat/hlsplaylist.c @@ -0,0 +1,138 @@ +/* + * Apple HTTP Live Streaming segmenter + * Copyright (c) 2012, Luca Barbato + * Copyright (c) 2017 Akamai Technologies, Inc. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include + +#include "libavutil/time_internal.h" + +#include "avformat.h" +#include "hlsplaylist.h" + +void ff_hls_write_playlist_version(AVIOContext *out, int version) { + if (!out) + return; + avio_printf(out, "#EXTM3U\n"); + avio_printf(out, "#EXT-X-VERSION:%d\n", version); +} + +void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, + int bandwidth, char *filename) { + if (!out || !filename) + return; + + if (!bandwidth) { + av_log(NULL, AV_LOG_WARNING, + "Bandwidth info not available, set audio and video bitrates\n"); + return; + } + + avio_printf(out, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth); + if (st && st->codecpar->width > 0 && st->codecpar->height > 0) + avio_printf(out, ",RESOLUTION=%dx%d", st->codecpar->width, + st->codecpar->height); + avio_printf(out, "\n%s\n\n", filename); +} + +void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, + int target_duration, int64_t sequence, + uint32_t playlist_type) { + if (!out) + return; + ff_hls_write_playlist_version(out, version); + if (allowcache == 0 || allowcache == 1) { + avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", allowcache == 0 ? "NO" : "YES"); + } + avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration); + avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence); + av_log(NULL, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence); + + if (playlist_type == PLAYLIST_TYPE_EVENT) { + avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n"); + } else if (playlist_type == PLAYLIST_TYPE_VOD) { + avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n"); + } +} + +void ff_hls_write_init_file(AVIOContext *out, char *filename, + int byterange_mode, int64_t size, int64_t pos) { + avio_printf(out, "#EXT-X-MAP:URI=\"%s\"", filename); + if (byterange_mode) { + avio_printf(out, ",BYTERANGE=\"%"PRId64"@%"PRId64"\"", size, pos); + } + avio_printf(out, "\n"); +} + +void ff_hls_write_file_entry(AVIOContext *out, int insert_discont, + int byterange_mode, + double duration, int round_duration, + int64_t size, int64_t pos, //Used only if HLS_SINGLE_FILE flag is set + char *baseurl, //Ignored if NULL + char *filename, double *prog_date_time) { + if (!out || !filename) + return; + + if (insert_discont) { + avio_printf(out, "#EXT-X-DISCONTINUITY\n"); + } + if (round_duration) + avio_printf(out, "#EXTINF:%ld,\n", lrint(duration)); + else + avio_printf(out, "#EXTINF:%f,\n", duration); + if (byterange_mode) + avio_printf(out, "#EXT-X-BYTERANGE:%"PRId64"@%"PRId64"\n", size, pos); + + if (prog_date_time) { + time_t tt, wrongsecs; + int milli; + struct tm *tm, tmpbuf; + char buf0[128], buf1[128]; + tt = (int64_t)*prog_date_time; + milli = av_clip(lrint(1000*(*prog_date_time - tt)), 0, 999); + tm = localtime_r(&tt, &tmpbuf); + strftime(buf0, sizeof(buf0), "%Y-%m-%dT%H:%M:%S", tm); + if (!strftime(buf1, sizeof(buf1), "%z", tm) || buf1[1]<'0' ||buf1[1]>'2') { + int tz_min, dst = tm->tm_isdst; + tm = gmtime_r(&tt, &tmpbuf); + tm->tm_isdst = dst; + wrongsecs = mktime(tm); + tz_min = (FFABS(wrongsecs - tt) + 30) / 60; + snprintf(buf1, sizeof(buf1), + "%c%02d%02d", + wrongsecs <= tt ? '+' : '-', + tz_min / 60, + tz_min % 60); + } + avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, milli, buf1); + *prog_date_time += duration; + } + if (baseurl) + avio_printf(out, "%s", baseurl); + avio_printf(out, "%s\n", filename); +} + +void ff_hls_write_end_list (AVIOContext *out) { + if (!out) + return; + avio_printf(out, "#EXT-X-ENDLIST\n"); +} + diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h new file mode 100644 index 0000000000000..fd36c7e6c219b --- /dev/null +++ b/libavformat/hlsplaylist.h @@ -0,0 +1,51 @@ +/* + * Apple HTTP Live Streaming segmenter + * Copyright (c) 2012, Luca Barbato + * Copyright (c) 2017 Akamai Technologies, Inc. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_HLSPLAYLIST_H_ +#define AVFORMAT_HLSPLAYLIST_H_ + +#include "libavutil/common.h" + +typedef enum { + PLAYLIST_TYPE_NONE, + PLAYLIST_TYPE_EVENT, + PLAYLIST_TYPE_VOD, + PLAYLIST_TYPE_NB, +} PlaylistType; + +void ff_hls_write_playlist_version(AVIOContext *out, int version); +void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, + int bandwidth, char *filename); +void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, + int target_duration, int64_t sequence, + uint32_t playlist_type); +void ff_hls_write_init_file(AVIOContext *out, char *filename, + int byterange_mode, int64_t size, int64_t pos); +void ff_hls_write_file_entry(AVIOContext *out, int insert_discont, + int byterange_mode, + double duration, int round_duration, + int64_t size, int64_t pos, //Used only if HLS_SINGLE_FILE flag is set + char *baseurl, //Ignored if NULL + char *filename, double *prog_date_time); +void ff_hls_write_end_list (AVIOContext *out); + +#endif /* AVFORMAT_HLSPLAYLIST_H_ */ From 85b84e12433031efc11a079fa989d831a7b0099b Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 29 Nov 2017 13:02:37 -0300 Subject: [PATCH 1183/2557] avformat/hlsplaylist: fix header include guard Fixes fate-source Signed-off-by: James Almer --- libavformat/hlsplaylist.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index fd36c7e6c219b..3445b5f297b12 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -20,8 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVFORMAT_HLSPLAYLIST_H_ -#define AVFORMAT_HLSPLAYLIST_H_ +#ifndef AVFORMAT_HLSPLAYLIST_H +#define AVFORMAT_HLSPLAYLIST_H #include "libavutil/common.h" From 91127355f5863e1f830e0a718036ad7189f42df3 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 29 Nov 2017 13:09:23 -0300 Subject: [PATCH 1184/2557] avformat/hlsplaylist: add missing header includes Fixes checkheaders. Signed-off-by: James Almer --- libavformat/hlsplaylist.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index 3445b5f297b12..9263a6463b41b 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -23,7 +23,11 @@ #ifndef AVFORMAT_HLSPLAYLIST_H #define AVFORMAT_HLSPLAYLIST_H +#include + #include "libavutil/common.h" +#include "avformat.h" +#include "avio.h" typedef enum { PLAYLIST_TYPE_NONE, From a5679933c1b8b6bef5c5c3eb7c70d06c695066cf Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 17 Nov 2017 14:15:22 +0100 Subject: [PATCH 1185/2557] vp9: use superframe split BSF webm usually has invisible superframes merged with normal frames. (vpxenc muxes them in this form, which is evidence enough that this is the standard webm packet format. It's rather unclear whether ffmpeg is even allowed to remux them with split packets.) The vp9 decoder needs them to be in separate packets for multithreading to work. Add the BSF to the decoder, so the conversion happens automatically. This contains the important part of fa1749dd34c55fb9, which was apparently skipped in commit d417e95af76. This restores Libav API compatibility. --- libavcodec/version.h | 2 +- libavcodec/vp9.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 55bb5c5e01f6f..d67b689142f70 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 6 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MICRO 102 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index 1ea2869c4c138..6241f01de1175 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -1795,6 +1795,7 @@ AVCodec ff_vp9_decoder = { .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp9_decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp9_decode_update_thread_context), .profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), + .bsfs = "vp9_superframe_split", .hw_configs = (const AVCodecHWConfigInternal*[]) { #if CONFIG_VP9_DXVA2_HWACCEL HWACCEL_DXVA2(vp9), From 0c162854c1fa2a1e43ce5588b67842675f45e3c7 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 29 Nov 2017 17:07:26 +0100 Subject: [PATCH 1186/2557] vp9_parser: don't split superframes into separate packets We did this for the sake of the decoder. With the vp9 change, it's not necessary anymore. --- libavcodec/vp9_parser.c | 127 ++++------------------------------------ 1 file changed, 10 insertions(+), 117 deletions(-) diff --git a/libavcodec/vp9_parser.c b/libavcodec/vp9_parser.c index 9900e7ab1f796..9531f34a32531 100644 --- a/libavcodec/vp9_parser.c +++ b/libavcodec/vp9_parser.c @@ -25,21 +25,19 @@ #include "libavcodec/get_bits.h" #include "parser.h" -typedef struct VP9ParseContext { - int n_frames; // 1-8 - int size[8]; - int marker_size; - int64_t pts; -} VP9ParseContext; - -static int parse_frame(AVCodecParserContext *ctx, const uint8_t *buf, int size) +static int parse(AVCodecParserContext *ctx, + AVCodecContext *avctx, + const uint8_t **out_data, int *out_size, + const uint8_t *data, int size) { - VP9ParseContext *s = ctx->priv_data; GetBitContext gb; - int res, profile, keyframe, invisible; + int res, profile, keyframe; - if ((res = init_get_bits8(&gb, buf, size)) < 0) - return res; + *out_data = data; + *out_size = size; + + if ((res = init_get_bits8(&gb, data, size)) < 0) + return size; // parsers can't return errors get_bits(&gb, 2); // frame marker profile = get_bits1(&gb); profile |= get_bits1(&gb) << 1; @@ -47,10 +45,8 @@ static int parse_frame(AVCodecParserContext *ctx, const uint8_t *buf, int size) if (get_bits1(&gb)) { keyframe = 0; - invisible = 0; } else { keyframe = !get_bits1(&gb); - invisible = !get_bits1(&gb); } if (!keyframe) { @@ -61,113 +57,10 @@ static int parse_frame(AVCodecParserContext *ctx, const uint8_t *buf, int size) ctx->key_frame = 1; } - if (!invisible) { - if (ctx->pts == AV_NOPTS_VALUE) - ctx->pts = s->pts; - s->pts = AV_NOPTS_VALUE; - } else if (ctx->pts != AV_NOPTS_VALUE) { - s->pts = ctx->pts; - ctx->pts = AV_NOPTS_VALUE; - } - - return 0; -} - -static int parse(AVCodecParserContext *ctx, - AVCodecContext *avctx, - const uint8_t **out_data, int *out_size, - const uint8_t *data, int size) -{ - VP9ParseContext *s = ctx->priv_data; - int full_size = size; - int marker; - - if (size <= 0) { - *out_size = 0; - *out_data = data; - - return 0; - } - - if (s->n_frames > 0) { - int i; - int size_sum = 0; - - for (i = 0; i < s->n_frames ;i++) - size_sum += s->size[i]; - size_sum += s->marker_size; - - if (size_sum != size) { - av_log(avctx, AV_LOG_ERROR, "Inconsistent input frame sizes %d %d\n", - size_sum, size); - s->n_frames = 0; - } - } - - if (s->n_frames > 0) { - *out_data = data; - *out_size = s->size[--s->n_frames]; - parse_frame(ctx, *out_data, *out_size); - - return s->n_frames > 0 ? *out_size : size /* i.e. include idx tail */; - } - - marker = data[size - 1]; - if ((marker & 0xe0) == 0xc0) { - int nbytes = 1 + ((marker >> 3) & 0x3); - int n_frames = 1 + (marker & 0x7), idx_sz = 2 + n_frames * nbytes; - - if (size >= idx_sz && data[size - idx_sz] == marker) { - const uint8_t *idx = data + size + 1 - idx_sz; - int first = 1; - - switch (nbytes) { -#define case_n(a, rd) \ - case a: \ - while (n_frames--) { \ - unsigned sz = rd; \ - idx += a; \ - if (sz == 0 || sz > size) { \ - s->n_frames = 0; \ - *out_size = size; \ - *out_data = data; \ - av_log(avctx, AV_LOG_ERROR, \ - "Invalid superframe packet size: %u frame size: %d\n", \ - sz, size); \ - return full_size; \ - } \ - if (first) { \ - first = 0; \ - *out_data = data; \ - *out_size = sz; \ - s->n_frames = n_frames; \ - } else { \ - s->size[n_frames] = sz; \ - } \ - data += sz; \ - size -= sz; \ - } \ - s->marker_size = size; \ - parse_frame(ctx, *out_data, *out_size); \ - return s->n_frames > 0 ? *out_size : full_size - - case_n(1, *idx); - case_n(2, AV_RL16(idx)); - case_n(3, AV_RL24(idx)); - case_n(4, AV_RL32(idx)); - } - } - } - - *out_data = data; - *out_size = size; - parse_frame(ctx, data, size); - return size; } AVCodecParser ff_vp9_parser = { .codec_ids = { AV_CODEC_ID_VP9 }, - .priv_data_size = sizeof(VP9ParseContext), .parser_parse = parse, }; From a198c1386a4f90cd6ae06874d1cdc2e3c0891fb8 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 29 Nov 2017 14:24:08 -0300 Subject: [PATCH 1187/2557] avcodec/amfenc: move config.h include where it's needed Signed-off-by: James Almer --- libavcodec/amfenc.c | 2 ++ libavcodec/amfenc.h | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index 49d64e6946359..f8b68070ae1c9 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + #include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/hwcontext.h" diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h index 8b59b506c54e6..84f0aad2fa4f9 100644 --- a/libavcodec/amfenc.h +++ b/libavcodec/amfenc.h @@ -26,7 +26,6 @@ #include "libavutil/fifo.h" -#include "config.h" #include "avcodec.h" From 61bbc537ab2305392bd170a6f404ed6402bee4a8 Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Mon, 27 Nov 2017 14:56:32 +0800 Subject: [PATCH 1188/2557] avcodec/samidec: check av_strdup() return value In function sami_paragraph_to_ass(), the return value of av_strdup() is not checked. To avoid potential NULL dereference, the return value should be checked against NULL. Signed-off-by: Pan Bian --- libavcodec/samidec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/samidec.c b/libavcodec/samidec.c index 2620424750859..6a598060efd09 100644 --- a/libavcodec/samidec.c +++ b/libavcodec/samidec.c @@ -48,6 +48,9 @@ static int sami_paragraph_to_ass(AVCodecContext *avctx, const char *src) AVBPrint *dst_content = &sami->encoded_content; AVBPrint *dst_source = &sami->encoded_source; + if (!dupsrc) + return AVERROR(ENOMEM); + av_bprint_clear(&sami->encoded_content); av_bprint_clear(&sami->content); av_bprint_clear(&sami->encoded_source); From 8d51d10eb895bda02ab0f8b3af082b5c9a781690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Wed, 29 Nov 2017 22:23:36 +0100 Subject: [PATCH 1189/2557] lavc/samidec: properly raise errors from sami_paragraph_to_ass() --- libavcodec/samidec.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/samidec.c b/libavcodec/samidec.c index 6a598060efd09..e32f238c629ca 100644 --- a/libavcodec/samidec.c +++ b/libavcodec/samidec.c @@ -138,9 +138,12 @@ static int sami_decode_frame(AVCodecContext *avctx, const char *ptr = avpkt->data; SAMIContext *sami = avctx->priv_data; - if (ptr && avpkt->size > 0 && !sami_paragraph_to_ass(avctx, ptr)) { + if (ptr && avpkt->size > 0) { + int ret = sami_paragraph_to_ass(avctx, ptr); + if (ret < 0) + return ret; // TODO: pass escaped sami->encoded_source.str as source - int ret = ff_ass_add_rect(sub, sami->full.str, sami->readorder++, 0, NULL, NULL); + ret = ff_ass_add_rect(sub, sami->full.str, sami->readorder++, 0, NULL, NULL); if (ret < 0) return ret; } From b0d9eab7f202f439b7c28e23ed1852abc814cd52 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 28 Nov 2017 13:58:31 +0000 Subject: [PATCH 1190/2557] examples/hw_decode: Use hw-config information to find pixfmt This removes all remaining device-type specificity. --- doc/examples/hw_decode.c | 54 ++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/doc/examples/hw_decode.c b/doc/examples/hw_decode.c index 9c7adbf51a072..83a5808bf7f90 100644 --- a/doc/examples/hw_decode.c +++ b/doc/examples/hw_decode.c @@ -44,34 +44,6 @@ static AVBufferRef *hw_device_ctx = NULL; static enum AVPixelFormat hw_pix_fmt; static FILE *output_file = NULL; -static enum AVPixelFormat find_fmt_by_hw_type(const enum AVHWDeviceType type) -{ - enum AVPixelFormat fmt; - - switch (type) { - case AV_HWDEVICE_TYPE_VAAPI: - fmt = AV_PIX_FMT_VAAPI; - break; - case AV_HWDEVICE_TYPE_DXVA2: - fmt = AV_PIX_FMT_DXVA2_VLD; - break; - case AV_HWDEVICE_TYPE_D3D11VA: - fmt = AV_PIX_FMT_D3D11; - break; - case AV_HWDEVICE_TYPE_VDPAU: - fmt = AV_PIX_FMT_VDPAU; - break; - case AV_HWDEVICE_TYPE_VIDEOTOOLBOX: - fmt = AV_PIX_FMT_VIDEOTOOLBOX; - break; - default: - fmt = AV_PIX_FMT_NONE; - break; - } - - return fmt; -} - static int hw_decoder_init(AVCodecContext *ctx, const enum AVHWDeviceType type) { int err = 0; @@ -184,18 +156,22 @@ int main(int argc, char *argv[]) AVCodec *decoder = NULL; AVPacket packet; enum AVHWDeviceType type; + int i; if (argc < 4) { - fprintf(stderr, "Usage: %s \n", argv[0]); + fprintf(stderr, "Usage: %s \n", argv[0]); return -1; } av_register_all(); type = av_hwdevice_find_type_by_name(argv[1]); - hw_pix_fmt = find_fmt_by_hw_type(type); - if (hw_pix_fmt == -1) { - fprintf(stderr, "Cannot support '%s' in this example.\n", argv[1]); + if (type == AV_HWDEVICE_TYPE_NONE) { + fprintf(stderr, "Device type %s is not supported.\n", argv[1]); + fprintf(stderr, "Available device types:"); + while((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE) + fprintf(stderr, " %s", av_hwdevice_get_type_name(type)); + fprintf(stderr, "\n"); return -1; } @@ -218,6 +194,20 @@ int main(int argc, char *argv[]) } video_stream = ret; + for (i = 0;; i++) { + const AVCodecHWConfig *config = avcodec_get_hw_config(decoder, i); + if (!config) { + fprintf(stderr, "Decoder %s does not support device type %s.\n", + decoder->name, av_hwdevice_get_type_name(type)); + return -1; + } + if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX && + config->device_type == type) { + hw_pix_fmt = config->pix_fmt; + break; + } + } + if (!(decoder_ctx = avcodec_alloc_context3(decoder))) return AVERROR(ENOMEM); From c6a905b91d935f78f5c33f6ce2dbe294b3353b77 Mon Sep 17 00:00:00 2001 From: Steven Robertson Date: Tue, 28 Nov 2017 16:49:46 -0800 Subject: [PATCH 1191/2557] avcodec/dnxhddec: Do not overwrite colorspace if the container has set it. The existing logic overrides container metadata even in cases where the container metadata must be trusted (e.g. HDR). The original spec had no provision for specifying color volume, so many files rely on the assumption of Rec. 709. An update to the spec included a 'clv' field for explicitly signaling that the container should be trusted in an existing bitfield in the frame header, but the default of 0 from old encoders forces Rec. 709, which would break any HDR stream. Because there is no place in DNxHR for specifying a transfer function, DNxHR HDR files must include container-level color information. This patch maintains the existing behavior of choosing the 709 over the 601 matrix when container-level information is missing, and allows container-level information to win if present. Signed-off-by: Steven Robertson Signed-off-by: Michael Niedermayer --- libavcodec/dnxhddec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c index f46e41a456239..05f4458f991c1 100644 --- a/libavcodec/dnxhddec.c +++ b/libavcodec/dnxhddec.c @@ -93,7 +93,9 @@ static av_cold int dnxhd_decode_init(AVCodecContext *avctx) ctx->avctx = avctx; ctx->cid = -1; - avctx->colorspace = AVCOL_SPC_BT709; + if (avctx->colorspace == AVCOL_SPC_UNSPECIFIED) { + avctx->colorspace = AVCOL_SPC_BT709; + } avctx->coded_width = FFALIGN(avctx->width, 16); avctx->coded_height = FFALIGN(avctx->height, 16); From 3684b5e56a54b850bd725ffc63cb454e23fd79db Mon Sep 17 00:00:00 2001 From: Karthick J Date: Thu, 30 Nov 2017 10:54:54 +0800 Subject: [PATCH 1192/2557] avformat/hlsenc: Refactored 'get_int_from_double' function to allow reuse --- libavformat/hlsenc.c | 7 +------ libavformat/hlsplaylist.h | 5 +++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index f63b08d7094ba..cdfbf45823920 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -203,11 +203,6 @@ typedef struct HLSContext { int http_persistent; } HLSContext; -static int get_int_from_double(double val) -{ - return (int)((val - (int)val) >= 0.001) ? (int)(val + 1) : (int)val; -} - static int mkdir_p(const char *path) { int ret = 0; char *temp = av_strdup(path); @@ -1211,7 +1206,7 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) for (en = vs->segments; en; en = en->next) { if (target_duration <= en->duration) - target_duration = get_int_from_double(en->duration); + target_duration = hls_get_int_from_double(en->duration); } vs->discontinuity_set = 0; diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index 9263a6463b41b..4cbc8cacc9152 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -36,6 +36,11 @@ typedef enum { PLAYLIST_TYPE_NB, } PlaylistType; +static inline int hls_get_int_from_double(double val) +{ + return (int)((val - (int)val) >= 0.001) ? (int)(val + 1) : (int)val; +} + void ff_hls_write_playlist_version(AVIOContext *out, int version); void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, char *filename); From 8c2b37e678e3d5ab16fef471fffc741b88622a85 Mon Sep 17 00:00:00 2001 From: Karthick J Date: Thu, 30 Nov 2017 10:55:51 +0800 Subject: [PATCH 1193/2557] avformat/dashenc: Option to generate hls playlist as well This is to take full advantage of Common Media Application Format(CMAF). Now server can generate one content and serve both HLS and DASH players. Reviewed-by: Steven Liu --- doc/muxers.texi | 3 ++ libavformat/Makefile | 2 +- libavformat/dashenc.c | 110 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 108 insertions(+), 7 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 8ec48c20552f4..3d0c7bfbd3622 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -249,6 +249,9 @@ DASH-templated name to used for the media segments. Default is "chunk-stream$Rep URL of the page that will return the UTC timestamp in ISO format. Example: "https://time.akamai.com/?iso" @item -http_user_agent @var{user_agent} Override User-Agent field in HTTP header. Applicable only for HTTP output. +@item -hls_playlist @var{hls_playlist} +Generate HLS playlist files as well. The master playlist is generated with the filename master.m3u8. +One media playlist file is generated for each stream with filenames media_0.m3u8, media_1.m3u8, etc. @item -adaptation_sets @var{adaptation_sets} Assign streams to AdaptationSets. Syntax is "id=x,streams=a,b,c id=y,streams=d,e" with x and y being the IDs of the adaptation sets and a,b,c,d and e are the indices of the mapped streams. diff --git a/libavformat/Makefile b/libavformat/Makefile index fd8b9f9899a06..4bffdf2205a90 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -135,7 +135,7 @@ OBJS-$(CONFIG_CONCAT_DEMUXER) += concatdec.o OBJS-$(CONFIG_CRC_MUXER) += crcenc.o OBJS-$(CONFIG_DATA_DEMUXER) += rawdec.o OBJS-$(CONFIG_DATA_MUXER) += rawenc.o -OBJS-$(CONFIG_DASH_MUXER) += dash.o dashenc.o +OBJS-$(CONFIG_DASH_MUXER) += dash.o dashenc.o hlsplaylist.o OBJS-$(CONFIG_DASH_DEMUXER) += dash.o dashdec.o OBJS-$(CONFIG_DAUD_DEMUXER) += dauddec.o OBJS-$(CONFIG_DAUD_MUXER) += daudenc.o diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 0fee3cd86a6df..1783675d00f01 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -36,6 +36,7 @@ #include "avc.h" #include "avformat.h" #include "avio_internal.h" +#include "hlsplaylist.h" #include "internal.h" #include "isom.h" #include "os_support.h" @@ -101,6 +102,8 @@ typedef struct DASHContext { const char *media_seg_name; const char *utc_timing_url; const char *user_agent; + int hls_playlist; + int master_playlist_created; } DASHContext; static struct codec_string { @@ -217,6 +220,14 @@ static void set_http_options(AVDictionary **options, DASHContext *c) av_dict_set(options, "user_agent", c->user_agent, 0); } +static void get_hls_playlist_name(char *playlist_name, int string_size, + const char *base_url, int id) { + if (base_url) + snprintf(playlist_name, string_size, "%smedia_%d.m3u8", base_url, id); + else + snprintf(playlist_name, string_size, "media_%d.m3u8", id); +} + static int flush_init_segment(AVFormatContext *s, OutputStream *os) { DASHContext *c = s->priv_data; @@ -262,7 +273,8 @@ static void dash_free(AVFormatContext *s) av_freep(&c->streams); } -static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext *c) +static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext *c, + int representation_id, int final) { int i, start_index = 0, start_number = 1; if (c->window_size) { @@ -322,6 +334,55 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext } avio_printf(out, "\t\t\t\t\n"); } + if (c->hls_playlist && start_index < os->nb_segments) + { + int timescale = os->ctx->streams[0]->time_base.den; + char temp_filename_hls[1024]; + char filename_hls[1024]; + AVIOContext *out_hls = NULL; + AVDictionary *http_opts = NULL; + int target_duration = 0; + const char *proto = avio_find_protocol_name(c->dirname); + int use_rename = proto && !strcmp(proto, "file"); + + get_hls_playlist_name(filename_hls, sizeof(filename_hls), + c->dirname, representation_id); + + snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? "%s.tmp" : "%s", filename_hls); + + set_http_options(&http_opts, c); + avio_open2(&out_hls, temp_filename_hls, AVIO_FLAG_WRITE, NULL, &http_opts); + av_dict_free(&http_opts); + for (i = start_index; i < os->nb_segments; i++) { + Segment *seg = os->segments[i]; + double duration = (double) seg->duration / timescale; + if (target_duration <= duration) + target_duration = hls_get_int_from_double(duration); + } + + ff_hls_write_playlist_header(out_hls, 6, -1, target_duration, + start_number, PLAYLIST_TYPE_NONE); + + ff_hls_write_init_file(out_hls, os->initfile, c->single_file, + os->init_range_length, os->init_start_pos); + + for (i = start_index; i < os->nb_segments; i++) { + Segment *seg = os->segments[i]; + ff_hls_write_file_entry(out_hls, 0, c->single_file, + (double) seg->duration / timescale, 0, + seg->range_length, seg->start_pos, NULL, + c->single_file ? os->initfile : seg->file, + NULL); + } + + if (final) + ff_hls_write_end_list(out_hls); + + avio_close(out_hls); + if (use_rename) + avpriv_io_move(temp_filename_hls, filename_hls); + } + } static char *xmlescape(const char *str) { @@ -391,7 +452,8 @@ static void format_date_now(char *buf, int size) } } -static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_index) +static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_index, + int final) { DASHContext *c = s->priv_data; AdaptationSet *as = &c->as[as_index]; @@ -430,7 +492,7 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind avio_printf(out, "\t\t\t\t\n", s->streams[i]->codecpar->channels); } - output_segment_list(os, out, c); + output_segment_list(os, out, c, i, final); avio_printf(out, "\t\t\t\n"); } avio_printf(out, "\t\t\n"); @@ -650,7 +712,7 @@ static int write_manifest(AVFormatContext *s, int final) } for (i = 0; i < c->nb_as; i++) { - if ((ret = write_adaptation_set(s, out, i)) < 0) + if ((ret = write_adaptation_set(s, out, i, final)) < 0) return ret; } avio_printf(out, "\t\n"); @@ -662,8 +724,43 @@ static int write_manifest(AVFormatContext *s, int final) avio_flush(out); ff_format_io_close(s, &out); - if (use_rename) - return avpriv_io_move(temp_filename, s->filename); + if (use_rename) { + if ((ret = avpriv_io_move(temp_filename, s->filename)) < 0) + return ret; + } + + if (c->hls_playlist && !c->master_playlist_created) { + char filename_hls[1024]; + + if (*c->dirname) + snprintf(filename_hls, sizeof(filename_hls), "%s/master.m3u8", c->dirname); + else + snprintf(filename_hls, sizeof(filename_hls), "master.m3u8"); + + snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", filename_hls); + + set_http_options(&opts, c); + ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, NULL, &opts); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename); + return ret; + } + av_dict_free(&opts); + + ff_hls_write_playlist_version(out, 6); + + for (i = 0; i < s->nb_streams; i++) { + char playlist_file[64]; + AVStream *st = s->streams[i]; + get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i); + ff_hls_write_stream_info(st, out, st->codecpar->bit_rate, playlist_file); + } + avio_close(out); + if (use_rename) + if ((ret = avpriv_io_move(temp_filename, filename_hls)) < 0) + return ret; + c->master_playlist_created = 1; + } return 0; } @@ -1206,6 +1303,7 @@ static const AVOption options[] = { { "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.m4s"}, 0, 0, E }, { "utc_timing_url", "URL of the page that will return the UTC timestamp in ISO format", OFFSET(utc_timing_url), AV_OPT_TYPE_STRING, { 0 }, 0, 0, E }, { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, + { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { NULL }, }; From ae7df68edd79bce5c318810c6b307ee4e81cd2a6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 24 Nov 2017 19:42:50 -0300 Subject: [PATCH 1194/2557] avformat/avc: return an error in ff_isom_write_avcc if the buffer lenght is too small Signed-off-by: James Almer --- libavformat/avc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/avc.c b/libavformat/avc.c index 094a95821f396..5232ed55f8db3 100644 --- a/libavformat/avc.c +++ b/libavformat/avc.c @@ -105,7 +105,9 @@ int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size) int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) { - if (len > 6) { + if (len <= 6) + return AVERROR_INVALIDDATA; + /* check for H.264 start code */ if (AV_RB32(data) == 0x00000001 || AV_RB24(data) == 0x000001) { @@ -157,7 +159,6 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) } else { avio_write(pb, data, len); } - } return 0; } From 9cd361c5c1f3550df9b2d4bd13b02ea592727f7c Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 24 Nov 2017 19:45:54 -0300 Subject: [PATCH 1195/2557] avformat/avc: refactor ff_isom_write_avcc This lets us remove one indentation level. Signed-off-by: James Almer --- libavformat/avc.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/libavformat/avc.c b/libavformat/avc.c index 5232ed55f8db3..a764ec0422f60 100644 --- a/libavformat/avc.c +++ b/libavformat/avc.c @@ -105,17 +105,22 @@ int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size) int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) { + uint8_t *buf = NULL, *end, *start = NULL; + uint8_t *sps = NULL, *pps = NULL; + uint32_t sps_size = 0, pps_size = 0; + int ret; + if (len <= 6) return AVERROR_INVALIDDATA; /* check for H.264 start code */ - if (AV_RB32(data) == 0x00000001 || - AV_RB24(data) == 0x000001) { - uint8_t *buf=NULL, *end, *start; - uint32_t sps_size=0, pps_size=0; - uint8_t *sps=0, *pps=0; + if (AV_RB32(data) != 0x00000001 && + AV_RB24(data) != 0x000001) { + avio_write(pb, data, len); + return 0; + } - int ret = ff_avc_parse_nal_units_buf(data, &buf, &len); + ret = ff_avc_parse_nal_units_buf(data, &buf, &len); if (ret < 0) return ret; start = buf; @@ -156,9 +161,6 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) avio_wb16(pb, pps_size); avio_write(pb, pps, pps_size); av_free(start); - } else { - avio_write(pb, data, len); - } return 0; } From df20619b649e82598d0e6efab291b427922b8ca4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 24 Nov 2017 19:47:47 -0300 Subject: [PATCH 1196/2557] avformat/avc: reindent after the last commit Signed-off-by: James Almer --- libavformat/avc.c | 91 ++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/libavformat/avc.c b/libavformat/avc.c index a764ec0422f60..85441df8f772c 100644 --- a/libavformat/avc.c +++ b/libavformat/avc.c @@ -113,54 +113,55 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) if (len <= 6) return AVERROR_INVALIDDATA; - /* check for H.264 start code */ - if (AV_RB32(data) != 0x00000001 && - AV_RB24(data) != 0x000001) { - avio_write(pb, data, len); - return 0; + /* check for H.264 start code */ + if (AV_RB32(data) != 0x00000001 && + AV_RB24(data) != 0x000001) { + avio_write(pb, data, len); + return 0; + } + + ret = ff_avc_parse_nal_units_buf(data, &buf, &len); + if (ret < 0) + return ret; + start = buf; + end = buf + len; + + /* look for sps and pps */ + while (end - buf > 4) { + uint32_t size; + uint8_t nal_type; + size = FFMIN(AV_RB32(buf), end - buf - 4); + buf += 4; + nal_type = buf[0] & 0x1f; + + if (nal_type == 7) { /* SPS */ + sps = buf; + sps_size = size; + } else if (nal_type == 8) { /* PPS */ + pps = buf; + pps_size = size; } - ret = ff_avc_parse_nal_units_buf(data, &buf, &len); - if (ret < 0) - return ret; - start = buf; - end = buf + len; - - /* look for sps and pps */ - while (end - buf > 4) { - uint32_t size; - uint8_t nal_type; - size = FFMIN(AV_RB32(buf), end - buf - 4); - buf += 4; - nal_type = buf[0] & 0x1f; - - if (nal_type == 7) { /* SPS */ - sps = buf; - sps_size = size; - } else if (nal_type == 8) { /* PPS */ - pps = buf; - pps_size = size; - } - - buf += size; - } + buf += size; + } + + if (!sps || !pps || sps_size < 4 || sps_size > UINT16_MAX || pps_size > UINT16_MAX) + return AVERROR_INVALIDDATA; + + avio_w8(pb, 1); /* version */ + avio_w8(pb, sps[1]); /* profile */ + avio_w8(pb, sps[2]); /* profile compat */ + avio_w8(pb, sps[3]); /* level */ + avio_w8(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */ + avio_w8(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */ + + avio_wb16(pb, sps_size); + avio_write(pb, sps, sps_size); + avio_w8(pb, 1); /* number of pps */ + avio_wb16(pb, pps_size); + avio_write(pb, pps, pps_size); + av_free(start); - if (!sps || !pps || sps_size < 4 || sps_size > UINT16_MAX || pps_size > UINT16_MAX) - return AVERROR_INVALIDDATA; - - avio_w8(pb, 1); /* version */ - avio_w8(pb, sps[1]); /* profile */ - avio_w8(pb, sps[2]); /* profile compat */ - avio_w8(pb, sps[3]); /* level */ - avio_w8(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */ - avio_w8(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */ - - avio_wb16(pb, sps_size); - avio_write(pb, sps, sps_size); - avio_w8(pb, 1); /* number of pps */ - avio_wb16(pb, pps_size); - avio_write(pb, pps, pps_size); - av_free(start); return 0; } From d5af8afbe4698273b2ef9b57487489b40f7888b1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 24 Nov 2017 20:26:08 -0300 Subject: [PATCH 1197/2557] avformat/avc: free buffer in ff_isom_write_avcc on failure Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/avc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavformat/avc.c b/libavformat/avc.c index 85441df8f772c..d989594bb06f2 100644 --- a/libavformat/avc.c +++ b/libavformat/avc.c @@ -145,8 +145,10 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) buf += size; } - if (!sps || !pps || sps_size < 4 || sps_size > UINT16_MAX || pps_size > UINT16_MAX) - return AVERROR_INVALIDDATA; + if (!sps || !pps || sps_size < 4 || sps_size > UINT16_MAX || pps_size > UINT16_MAX) { + ret = AVERROR_INVALIDDATA; + goto fail; + } avio_w8(pb, 1); /* version */ avio_w8(pb, sps[1]); /* profile */ @@ -160,9 +162,11 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) avio_w8(pb, 1); /* number of pps */ avio_wb16(pb, pps_size); avio_write(pb, pps, pps_size); + +fail: av_free(start); - return 0; + return ret; } int ff_avc_write_annexb_extradata(const uint8_t *in, uint8_t **buf, int *size) From 8d33e8661694f45a4552d3a3eff736a0f0d17932 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 24 Nov 2017 22:36:22 -0300 Subject: [PATCH 1198/2557] avformat/avc: support writting more than one sps/pps in ff_isom_write_avcc Addresses ticket #6864 Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/avc.c | 51 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/libavformat/avc.c b/libavformat/avc.c index d989594bb06f2..ec50033a0420e 100644 --- a/libavformat/avc.c +++ b/libavformat/avc.c @@ -20,6 +20,7 @@ */ #include "libavutil/intreadwrite.h" +#include "libavcodec/h264.h" #include "avformat.h" #include "avio.h" #include "avc.h" @@ -105,10 +106,11 @@ int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size) int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) { + AVIOContext *sps_pb = NULL, *pps_pb = NULL; uint8_t *buf = NULL, *end, *start = NULL; uint8_t *sps = NULL, *pps = NULL; uint32_t sps_size = 0, pps_size = 0; - int ret; + int ret, nb_sps = 0, nb_pps = 0; if (len <= 6) return AVERROR_INVALIDDATA; @@ -126,6 +128,13 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) start = buf; end = buf + len; + ret = avio_open_dyn_buf(&sps_pb); + if (ret < 0) + goto fail; + ret = avio_open_dyn_buf(&pps_pb); + if (ret < 0) + goto fail; + /* look for sps and pps */ while (end - buf > 4) { uint32_t size; @@ -135,35 +144,51 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) nal_type = buf[0] & 0x1f; if (nal_type == 7) { /* SPS */ - sps = buf; - sps_size = size; + nb_sps++; + if (size > UINT16_MAX || nb_sps >= H264_MAX_SPS_COUNT) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + avio_wb16(sps_pb, size); + avio_write(sps_pb, buf, size); } else if (nal_type == 8) { /* PPS */ - pps = buf; - pps_size = size; + nb_pps++; + if (size > UINT16_MAX || nb_pps >= H264_MAX_PPS_COUNT) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + avio_wb16(pps_pb, size); + avio_write(pps_pb, buf, size); } buf += size; } + sps_size = avio_close_dyn_buf(sps_pb, &sps); + pps_size = avio_close_dyn_buf(pps_pb, &pps); - if (!sps || !pps || sps_size < 4 || sps_size > UINT16_MAX || pps_size > UINT16_MAX) { + if (sps_size < 6 || !pps_size) { ret = AVERROR_INVALIDDATA; goto fail; } avio_w8(pb, 1); /* version */ - avio_w8(pb, sps[1]); /* profile */ - avio_w8(pb, sps[2]); /* profile compat */ - avio_w8(pb, sps[3]); /* level */ + avio_w8(pb, sps[3]); /* profile */ + avio_w8(pb, sps[4]); /* profile compat */ + avio_w8(pb, sps[5]); /* level */ avio_w8(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */ - avio_w8(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */ + avio_w8(pb, 0xe0 | nb_sps); /* 3 bits reserved (111) + 5 bits number of sps */ - avio_wb16(pb, sps_size); avio_write(pb, sps, sps_size); - avio_w8(pb, 1); /* number of pps */ - avio_wb16(pb, pps_size); + avio_w8(pb, nb_pps); /* number of pps */ avio_write(pb, pps, pps_size); fail: + if (!sps) + avio_close_dyn_buf(sps_pb, &sps); + if (!pps) + avio_close_dyn_buf(pps_pb, &pps); + av_free(sps); + av_free(pps); av_free(start); return ret; From 5a366f9770dd7b02b0721b2857d6baa96acdb0af Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 30 Nov 2017 01:51:16 -0300 Subject: [PATCH 1199/2557] configure: select vp9_superframe_split_bsf when enabling vp9_decoder This is required since a5679933c1b8b6bef5c5c3eb7c70d06c695066cf Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 4e7254eaeb853..1fa16e9dbaa9c 100755 --- a/configure +++ b/configure @@ -2637,7 +2637,7 @@ vp6a_decoder_select="vp6_decoder" vp6f_decoder_select="vp6_decoder" vp7_decoder_select="h264pred videodsp vp8dsp" vp8_decoder_select="h264pred videodsp vp8dsp" -vp9_decoder_select="videodsp vp9_parser" +vp9_decoder_select="videodsp vp9_parser vp9_superframe_split_bsf" webp_decoder_select="vp8_decoder exif" wmalossless_decoder_select="llauddsp" wmapro_decoder_select="mdct sinewin wma_freqs" From d13b8f68d7cb1e03259faf2da54ff1a5da2b54e1 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Thu, 30 Nov 2017 14:13:15 +0100 Subject: [PATCH 1200/2557] lavfi/libvmaf: Rename local variable "main" as "master". Fixes the following warning: libavfilter/vf_libvmaf.c:179:14: warning: 'main' is usually a function Missed in 5d3e9357 --- libavfilter/vf_libvmaf.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavfilter/vf_libvmaf.c b/libavfilter/vf_libvmaf.c index 7670c51e2113b..e83b89b4f1b17 100644 --- a/libavfilter/vf_libvmaf.c +++ b/libavfilter/vf_libvmaf.c @@ -176,14 +176,14 @@ static int do_vmaf(FFFrameSync *fs) { AVFilterContext *ctx = fs->parent; LIBVMAFContext *s = ctx->priv; - AVFrame *main, *ref; + AVFrame *master, *ref; int ret; - ret = ff_framesync_dualinput_get(fs, &main, &ref); + ret = ff_framesync_dualinput_get(fs, &master, &ref); if (ret < 0) return ret; if (!ref) - return ff_filter_frame(ctx->outputs[0], main); + return ff_filter_frame(ctx->outputs[0], master); pthread_mutex_lock(&s->lock); @@ -192,14 +192,14 @@ static int do_vmaf(FFFrameSync *fs) } av_frame_ref(s->gref, ref); - av_frame_ref(s->gmain, main); + av_frame_ref(s->gmain, master); s->frame_set = 1; pthread_cond_signal(&s->cond); pthread_mutex_unlock(&s->lock); - return ff_filter_frame(ctx->outputs[0], main); + return ff_filter_frame(ctx->outputs[0], master); } static av_cold int init(AVFilterContext *ctx) From f6161fccf8c5720ceac1ed1df8ba60ff8fed69f5 Mon Sep 17 00:00:00 2001 From: Tristan Matthews Date: Wed, 29 Nov 2017 14:16:02 -0500 Subject: [PATCH 1201/2557] rtsp: only break on parse_rtsp_message on error Fix suggested by Luca Barbato. This was causing spurious EOFs when using -rtsp_transport udp, as reported in https://bugzilla.libav.org/show_bug.cgi?id=1103 Signed-off-by: Luca Barbato --- libavformat/rtsp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 17a25a310ecd2..8bf9d9e3c7b06 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1998,7 +1998,9 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, } #if CONFIG_RTSP_DEMUXER if (rt->rtsp_hd && p[0].revents & POLLIN) { - return parse_rtsp_message(s); + if ((ret = parse_rtsp_message(s)) < 0) { + return ret; + } } #endif } else if (n == 0 && ++timeout_cnt >= MAX_TIMEOUTS) { From 2d015d3bf9fed59c65a3819a35fedbb8b7dde623 Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Sun, 26 Nov 2017 07:32:30 -0800 Subject: [PATCH 1202/2557] lavf/mov: fix huge alloc in mov_read_ctts An invalid file may cause huge alloc. Delay expansion of ctts entries until the number of samples is known in mov_build_index. Fixes: 23 Found-by: zhao dongzhuo, AD-lab of Venustech Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index c9018592e0592..f7fab98dd87ba 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2895,7 +2895,7 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; MOVStreamContext *sc; - unsigned int i, j, entries, ctts_count = 0; + unsigned int i, entries, ctts_count = 0; if (c->fc->nb_streams < 1) return 0; @@ -2928,9 +2928,8 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom) continue; } - /* Expand entries such that we have a 1-1 mapping with samples. */ - for (j = 0; j < count; j++) - add_ctts_entry(&sc->ctts_data, &ctts_count, &sc->ctts_allocated_size, 1, duration); + add_ctts_entry(&sc->ctts_data, &ctts_count, &sc->ctts_allocated_size, + count, duration); av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n", count, duration); @@ -3579,6 +3578,8 @@ static void mov_build_index(MOVContext *mov, AVStream *st) unsigned int stps_index = 0; unsigned int i, j; uint64_t stream_size = 0; + MOVStts *ctts_data_old = sc->ctts_data; + unsigned int ctts_count_old = sc->ctts_count; if (sc->elst_count) { int i, edit_start_index = 0, multiple_edits = 0; @@ -3647,6 +3648,28 @@ static void mov_build_index(MOVContext *mov, AVStream *st) } st->index_entries_allocated_size = (st->nb_index_entries + sc->sample_count) * sizeof(*st->index_entries); + if (ctts_data_old) { + // Expand ctts entries such that we have a 1-1 mapping with samples + if (sc->sample_count >= UINT_MAX / sizeof(*sc->ctts_data)) + return; + sc->ctts_count = 0; + sc->ctts_allocated_size = 0; + sc->ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, + sc->sample_count * sizeof(*sc->ctts_data)); + if (!sc->ctts_data) { + av_free(ctts_data_old); + return; + } + for (i = 0; i < ctts_count_old && + sc->ctts_count < sc->sample_count; i++) + for (j = 0; j < ctts_data_old[i].count && + sc->ctts_count < sc->sample_count; j++) + add_ctts_entry(&sc->ctts_data, &sc->ctts_count, + &sc->ctts_allocated_size, 1, + ctts_data_old[i].duration); + av_free(ctts_data_old); + } + for (i = 0; i < sc->chunk_count; i++) { int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX; current_offset = sc->chunk_offsets[i]; From 83ecdc9a920d7f0b69d1a25d63757adb887a1f25 Mon Sep 17 00:00:00 2001 From: Jacob Trimble Date: Thu, 30 Nov 2017 14:58:59 -0800 Subject: [PATCH 1203/2557] configure: Fix dependencies of aac_at decoder. Signed-off-by: Jacob Trimble Signed-off-by: James Almer --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 1fa16e9dbaa9c..d05388638d20d 100755 --- a/configure +++ b/configure @@ -2890,6 +2890,7 @@ trace_headers_bsf_select="cbs_h264 cbs_h265 cbs_mpeg2" # external libraries aac_at_decoder_deps="audiotoolbox" +aac_at_decoder_select="aac_adtstoasc_bsf" ac3_at_decoder_deps="audiotoolbox" ac3_at_decoder_select="ac3_parser" adpcm_ima_qt_at_decoder_deps="audiotoolbox" From 5e9b39b373215104dbcf59e161b3755466f18859 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 1 Dec 2017 01:09:43 -0300 Subject: [PATCH 1204/2557] avcodec/h264_sei: remove redundant prefix to H264SEIFramePacking fields Cosmetic change. Signed-off-by: James Almer --- libavcodec/h264_parser.c | 2 +- libavcodec/h264_sei.c | 18 +++++++++--------- libavcodec/h264_sei.h | 8 ++++---- libavcodec/h264_slice.c | 6 +++--- libavcodec/h264dec.c | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index 39f97e00a6126..65d9d44b50a6f 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -259,7 +259,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN; ff_h264_sei_uninit(&p->sei); - p->sei.frame_packing.frame_packing_arrangement_cancel_flag = -1; + p->sei.frame_packing.arrangement_cancel_flag = -1; if (!buf_size) return 0; diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c index 27a37247b5e5f..9defcb80b9a44 100644 --- a/libavcodec/h264_sei.c +++ b/libavcodec/h264_sei.c @@ -313,12 +313,12 @@ static int decode_buffering_period(H264SEIBufferingPeriod *h, GetBitContext *gb, static int decode_frame_packing_arrangement(H264SEIFramePacking *h, GetBitContext *gb) { - h->frame_packing_arrangement_id = get_ue_golomb_long(gb); - h->frame_packing_arrangement_cancel_flag = get_bits1(gb); - h->present = !h->frame_packing_arrangement_cancel_flag; + h->arrangement_id = get_ue_golomb_long(gb); + h->arrangement_cancel_flag = get_bits1(gb); + h->present = !h->arrangement_cancel_flag; if (h->present) { - h->frame_packing_arrangement_type = get_bits(gb, 7); + h->arrangement_type = get_bits(gb, 7); h->quincunx_sampling_flag = get_bits1(gb); h->content_interpretation_type = get_bits(gb, 6); @@ -328,10 +328,10 @@ static int decode_frame_packing_arrangement(H264SEIFramePacking *h, // frame0_self_contained_flag, frame1_self_contained_flag skip_bits(gb, 2); - if (!h->quincunx_sampling_flag && h->frame_packing_arrangement_type != 5) + if (!h->quincunx_sampling_flag && h->arrangement_type != 5) skip_bits(gb, 16); // frame[01]_grid_position_[xy] skip_bits(gb, 8); // frame_packing_arrangement_reserved_byte - h->frame_packing_arrangement_repetition_period = get_ue_golomb_long(gb); + h->arrangement_repetition_period = get_ue_golomb_long(gb); } skip_bits1(gb); // frame_packing_arrangement_extension_flag @@ -465,8 +465,8 @@ int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb, const char *ff_h264_sei_stereo_mode(const H264SEIFramePacking *h) { - if (h->frame_packing_arrangement_cancel_flag == 0) { - switch (h->frame_packing_arrangement_type) { + if (h->arrangement_cancel_flag == 0) { + switch (h->arrangement_type) { case H264_SEI_FPA_TYPE_CHECKERBOARD: if (h->content_interpretation_type == 2) return "checkerboard_rl"; @@ -501,7 +501,7 @@ const char *ff_h264_sei_stereo_mode(const H264SEIFramePacking *h) default: return "mono"; } - } else if (h->frame_packing_arrangement_cancel_flag == 1) { + } else if (h->arrangement_cancel_flag == 1) { return "mono"; } else { return NULL; diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h index 817b4eaae99b6..9488382b9fabd 100644 --- a/libavcodec/h264_sei.h +++ b/libavcodec/h264_sei.h @@ -119,10 +119,10 @@ typedef struct H264SEIBufferingPeriod { typedef struct H264SEIFramePacking { int present; - int frame_packing_arrangement_id; - int frame_packing_arrangement_cancel_flag; ///< is previous arrangement canceled, -1 if never received - H264_SEI_FpaType frame_packing_arrangement_type; - int frame_packing_arrangement_repetition_period; + int arrangement_id; + int arrangement_cancel_flag; ///< is previous arrangement canceled, -1 if never received + H264_SEI_FpaType arrangement_type; + int arrangement_repetition_period; int content_interpretation_type; int quincunx_sampling_flag; int current_frame_is_frame0_flag; diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index fff3112649023..d9377a8a1c8d6 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1198,13 +1198,13 @@ static int h264_export_frame_props(H264Context *h) } if (h->sei.frame_packing.present && - h->sei.frame_packing.frame_packing_arrangement_type <= 6 && + h->sei.frame_packing.arrangement_type <= 6 && h->sei.frame_packing.content_interpretation_type > 0 && h->sei.frame_packing.content_interpretation_type < 3) { H264SEIFramePacking *fp = &h->sei.frame_packing; AVStereo3D *stereo = av_stereo3d_create_side_data(cur->f); if (stereo) { - switch (fp->frame_packing_arrangement_type) { + switch (fp->arrangement_type) { case 0: stereo->type = AV_STEREO3D_CHECKERBOARD; break; @@ -1234,7 +1234,7 @@ static int h264_export_frame_props(H264Context *h) if (fp->content_interpretation_type == 2) stereo->flags = AV_STEREO3D_FLAG_INVERT; - if (fp->frame_packing_arrangement_type == 5) { + if (fp->arrangement_type == 5) { if (fp->current_frame_is_frame0_flag) stereo->view = AV_STEREO3D_VIEW_LEFT; else diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index b03024d4a35b9..1d99ed5f4c2c5 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -319,7 +319,7 @@ static int h264_init_context(AVCodecContext *avctx, H264Context *h) h->x264_build = -1; h->frame_recovered = 0; h->poc.prev_frame_num = -1; - h->sei.frame_packing.frame_packing_arrangement_cancel_flag = -1; + h->sei.frame_packing.arrangement_cancel_flag = -1; h->sei.unregistered.x264_build = -1; h->next_outputed_poc = INT_MIN; From e01d2c00ae070c6486cdbe3a07546fcffb3ce6cb Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 1 Dec 2017 01:17:44 -0300 Subject: [PATCH 1205/2557] avcodec/h264_slice: use H264_SEI_FpaType enum constants Cosmetic change. Signed-off-by: James Almer --- libavcodec/h264_slice.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index d9377a8a1c8d6..aad54845888d0 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1205,28 +1205,28 @@ static int h264_export_frame_props(H264Context *h) AVStereo3D *stereo = av_stereo3d_create_side_data(cur->f); if (stereo) { switch (fp->arrangement_type) { - case 0: + case H264_SEI_FPA_TYPE_CHECKERBOARD: stereo->type = AV_STEREO3D_CHECKERBOARD; break; - case 1: + case H264_SEI_FPA_TYPE_INTERLEAVE_COLUMN: stereo->type = AV_STEREO3D_COLUMNS; break; - case 2: + case H264_SEI_FPA_TYPE_INTERLEAVE_ROW: stereo->type = AV_STEREO3D_LINES; break; - case 3: + case H264_SEI_FPA_TYPE_SIDE_BY_SIDE: if (fp->quincunx_sampling_flag) stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX; else stereo->type = AV_STEREO3D_SIDEBYSIDE; break; - case 4: + case H264_SEI_FPA_TYPE_TOP_BOTTOM: stereo->type = AV_STEREO3D_TOPBOTTOM; break; - case 5: + case H264_SEI_FPA_TYPE_INTERLEAVE_TEMPORAL: stereo->type = AV_STEREO3D_FRAMESEQUENCE; break; - case 6: + case H264_SEI_FPA_TYPE_2D: stereo->type = AV_STEREO3D_2D; break; } @@ -1234,7 +1234,7 @@ static int h264_export_frame_props(H264Context *h) if (fp->content_interpretation_type == 2) stereo->flags = AV_STEREO3D_FLAG_INVERT; - if (fp->arrangement_type == 5) { + if (fp->arrangement_type == H264_SEI_FPA_TYPE_INTERLEAVE_TEMPORAL) { if (fp->current_frame_is_frame0_flag) stereo->view = AV_STEREO3D_VIEW_LEFT; else From 2cfc8b172ce767928a6394e066cb0b2789efd395 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 17 Nov 2017 21:33:37 +0100 Subject: [PATCH 1206/2557] avfilter/vf_tile: add init_padding option Signed-off-by: Paul B Mahol --- doc/filters.texi | 5 +++++ libavfilter/vf_tile.c | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index 4a4efc70c8ca9..ec37b9dcb869f 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -14637,6 +14637,11 @@ is "black". @item overlap Set the number of frames to overlap when tiling several successive frames together. The value must be between @code{0} and @var{nb_frames - 1}. + +@item init_padding +Set the number of frames to initially be empty before displaying first output frame. +This controls how soon will one get first output frame. +The value must be between @code{0} and @var{nb_frames - 1}. @end table @subsection Examples diff --git a/libavfilter/vf_tile.c b/libavfilter/vf_tile.c index 7717ce12e72eb..439689a14d466 100644 --- a/libavfilter/vf_tile.c +++ b/libavfilter/vf_tile.c @@ -38,6 +38,7 @@ typedef struct TileContext { unsigned margin; unsigned padding; unsigned overlap; + unsigned init_padding; unsigned current; unsigned nb_frames; FFDrawContext draw; @@ -62,6 +63,8 @@ static const AVOption tile_options[] = { { "color", "set the color of the unused area", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str = "black"}, .flags = FLAGS }, { "overlap", "set how many frames to overlap for each render", OFFSET(overlap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS }, + { "init_padding", " set how many frames to initially pad", OFFSET(init_padding), + AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS }, { NULL } }; @@ -99,6 +102,12 @@ static av_cold int init(AVFilterContext *ctx) tile->overlap = tile->nb_frames - 1; } + if (tile->init_padding >= tile->nb_frames) { + av_log(ctx, AV_LOG_WARNING, "init_padding must be less than %d\n", tile->nb_frames); + } else { + tile->current = tile->init_padding; + } + return 0; } @@ -201,11 +210,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) tile->out_ref->height = outlink->h; /* fill surface once for margin/padding */ - if (tile->margin || tile->padding) + if (tile->margin || tile->padding || tile->init_padding) ff_fill_rectangle(&tile->draw, &tile->blank, tile->out_ref->data, tile->out_ref->linesize, 0, 0, outlink->w, outlink->h); + tile->init_padding = 0; } if (tile->prev_out_ref) { From 95bacb521af8cd28f146f045437c9f75717a493a Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Thu, 30 Nov 2017 12:20:36 -0800 Subject: [PATCH 1207/2557] avcodec/vorbis: Fix another 1 << 31 > int32_t::max() with 1u. Didn't notice this one when 9648cc6d was landed. Signed-off-by: Dale Curtis Signed-off-by: Michael Niedermayer --- libavcodec/vorbis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vorbis.c b/libavcodec/vorbis.c index 5ccc37a2dff86..cca2aa7c635bc 100644 --- a/libavcodec/vorbis.c +++ b/libavcodec/vorbis.c @@ -67,7 +67,7 @@ int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num) if (bits[p] > 32) return AVERROR_INVALIDDATA; for (i = 0; i < bits[p]; ++i) - exit_at_level[i+1] = 1 << i; + exit_at_level[i+1] = 1u << i; ++p; From e1dd97bd4c03d658f9b18a0d6269f1bc06f796c9 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 18 Nov 2017 18:18:39 +0100 Subject: [PATCH 1208/2557] avfilter: add fillborders filter Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/filters.texi | 42 ++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- libavfilter/vf_fillborders.c | 394 +++++++++++++++++++++++++++++++++++ 6 files changed, 440 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_fillborders.c diff --git a/Changelog b/Changelog index 9eaaedbcaba56..b00996157cc2a 100644 --- a/Changelog +++ b/Changelog @@ -23,6 +23,7 @@ version : - audio lv2 wrapper filter - VAAPI VP8 decoding - AMD AMF H.264 and HEVC encoders +- video fillborders filter version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index ec37b9dcb869f..f7c371592f0af 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -8610,6 +8610,48 @@ framework. It does not take parameters. +@section fillborders + +Fill borders of the input video, without changing video stream dimensions. +Sometimes video can have garbage at the four edges and you may not want to +crop video input to keep size multiple of some number. + +This filter accepts the following options: + +@table @option +@item left +Number of pixels to fill from left border. + +@item right +Number of pixels to fill from right border. + +@item top +Number of pixels to fill from top border. + +@item bottom +Number of pixels to fill from bottom border. + +@item mode +Set fill mode. + +It accepts the following values: +@table @samp +@item smear +fill pixels using outermost pixels + +@item mirror +fill pixels using mirroring + +@item fixed +fill pixels with constant value +@end table + +Default is @var{smear}. + +@item color +Set color for pixels in fixed mode. Default is @var{black}. +@end table + @section find_rect Find a rectangular object diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 0b77d7a01f039..1c0cc1da801da 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -192,6 +192,7 @@ OBJS-$(CONFIG_FIELD_FILTER) += vf_field.o OBJS-$(CONFIG_FIELDHINT_FILTER) += vf_fieldhint.o OBJS-$(CONFIG_FIELDMATCH_FILTER) += vf_fieldmatch.o OBJS-$(CONFIG_FIELDORDER_FILTER) += vf_fieldorder.o +OBJS-$(CONFIG_FILLBORDERS_FILTER) += vf_fillborders.o OBJS-$(CONFIG_FIND_RECT_FILTER) += vf_find_rect.o lavfutils.o OBJS-$(CONFIG_FLOODFILL_FILTER) += vf_floodfill.o OBJS-$(CONFIG_FORMAT_FILTER) += vf_format.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 4c834f73815d8..fc212e58db378 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -202,6 +202,7 @@ static void register_all(void) REGISTER_FILTER(FIELDHINT, fieldhint, vf); REGISTER_FILTER(FIELDMATCH, fieldmatch, vf); REGISTER_FILTER(FIELDORDER, fieldorder, vf); + REGISTER_FILTER(FILLBORDERS, fillborders, vf); REGISTER_FILTER(FIND_RECT, find_rect, vf); REGISTER_FILTER(FLOODFILL, floodfill, vf); REGISTER_FILTER(FORMAT, format, vf); diff --git a/libavfilter/version.h b/libavfilter/version.h index 1d356a9a5af71..6b8110c9de094 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 5 +#define LIBAVFILTER_VERSION_MINOR 6 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_fillborders.c b/libavfilter/vf_fillborders.c new file mode 100644 index 0000000000000..df883bc62e9e1 --- /dev/null +++ b/libavfilter/vf_fillborders.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2017 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/colorspace.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "drawutils.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +enum { Y, U, V, A }; +enum { R, G, B }; + +enum FillMode { FM_SMEAR, FM_MIRROR, FM_FIXED, FM_NB_MODES }; + +typedef struct Borders { + int left, right, top, bottom; +} Borders; + +typedef struct FillBordersContext { + const AVClass *class; + int left, right, top, bottom; + int mode; + + int nb_planes; + int depth; + Borders borders[4]; + int planewidth[4]; + int planeheight[4]; + uint8_t fill[4]; + uint8_t yuv_color[4]; + uint8_t rgba_color[4]; + + void (*fillborders)(struct FillBordersContext *s, AVFrame *frame); +} FillBordersContext; + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NONE + }; + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +static void smear_borders8(FillBordersContext *s, AVFrame *frame) +{ + int p, y; + + for (p = 0; p < s->nb_planes; p++) { + uint8_t *ptr = frame->data[p]; + int linesize = frame->linesize[p]; + + for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) { + memset(ptr + y * linesize, + *(ptr + y * linesize + s->borders[p].left), + s->borders[p].left); + memset(ptr + y * linesize + s->planewidth[p] - s->borders[p].right, + *(ptr + y * linesize + s->planewidth[p] - s->borders[p].right - 1), + s->borders[p].right); + } + + for (y = 0; y < s->borders[p].top; y++) { + memcpy(ptr + y * linesize, + ptr + s->borders[p].top * linesize, s->planewidth[p]); + } + + for (y = s->planeheight[p] - s->borders[p].bottom; y < s->planeheight[p]; y++) { + memcpy(ptr + y * linesize, + ptr + (s->planeheight[p] - s->borders[p].bottom - 1) * linesize, + s->planewidth[p]); + } + } +} + +static void smear_borders16(FillBordersContext *s, AVFrame *frame) +{ + int p, y, x; + + for (p = 0; p < s->nb_planes; p++) { + uint16_t *ptr = (uint16_t *)frame->data[p]; + int linesize = frame->linesize[p] / 2; + + for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) { + for (x = 0; x < s->borders[p].left; x++) { + ptr[y * linesize + x] = *(ptr + y * linesize + s->borders[p].left); + } + + for (x = 0; x < s->borders[p].right; x++) { + ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] = + *(ptr + y * linesize + s->planewidth[p] - s->borders[p].right - 1); + } + } + + for (y = 0; y < s->borders[p].top; y++) { + memcpy(ptr + y * linesize, + ptr + s->borders[p].top * linesize, s->planewidth[p] * 2); + } + + for (y = s->planeheight[p] - s->borders[p].bottom; y < s->planeheight[p]; y++) { + memcpy(ptr + y * linesize, + ptr + (s->planeheight[p] - s->borders[p].bottom - 1) * linesize, + s->planewidth[p] * 2); + } + } +} + +static void mirror_borders8(FillBordersContext *s, AVFrame *frame) +{ + int p, y, x; + + for (p = 0; p < s->nb_planes; p++) { + uint8_t *ptr = frame->data[p]; + int linesize = frame->linesize[p]; + + for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) { + for (x = 0; x < s->borders[p].left; x++) { + ptr[y * linesize + x] = ptr[y * linesize + s->borders[p].left * 2 - 1 - x]; + } + + for (x = 0; x < s->borders[p].right; x++) { + ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] = + ptr[y * linesize + s->planewidth[p] - s->borders[p].right - 1 - x]; + } + } + + for (y = 0; y < s->borders[p].top; y++) { + memcpy(ptr + y * linesize, + ptr + (s->borders[p].top * 2 - 1 - y) * linesize, + s->planewidth[p]); + } + + for (y = 0; y < s->borders[p].bottom; y++) { + memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize, + ptr + (s->planeheight[p] - s->borders[p].bottom - 1 - y) * linesize, + s->planewidth[p]); + } + } +} + +static void mirror_borders16(FillBordersContext *s, AVFrame *frame) +{ + int p, y, x; + + for (p = 0; p < s->nb_planes; p++) { + uint16_t *ptr = (uint16_t *)frame->data[p]; + int linesize = frame->linesize[p] / 2; + + for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) { + for (x = 0; x < s->borders[p].left; x++) { + ptr[y * linesize + x] = ptr[y * linesize + s->borders[p].left * 2 - 1 - x]; + } + + for (x = 0; x < s->borders[p].right; x++) { + ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] = + ptr[y * linesize + s->planewidth[p] - s->borders[p].right - 1 - x]; + } + } + + for (y = 0; y < s->borders[p].top; y++) { + memcpy(ptr + y * linesize, + ptr + (s->borders[p].top * 2 - 1 - y) * linesize, + s->planewidth[p] * 2); + } + + for (y = 0; y < s->borders[p].bottom; y++) { + memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize, + ptr + (s->planeheight[p] - s->borders[p].bottom - 1 - y) * linesize, + s->planewidth[p] * 2); + } + } +} + +static void fixed_borders8(FillBordersContext *s, AVFrame *frame) +{ + int p, y; + + for (p = 0; p < s->nb_planes; p++) { + uint8_t *ptr = frame->data[p]; + uint8_t fill = s->fill[p]; + int linesize = frame->linesize[p]; + + for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) { + memset(ptr + y * linesize, fill, s->borders[p].left); + memset(ptr + y * linesize + s->planewidth[p] - s->borders[p].right, fill, + s->borders[p].right); + } + + for (y = 0; y < s->borders[p].top; y++) { + memset(ptr + y * linesize, fill, s->planewidth[p]); + } + + for (y = s->planeheight[p] - s->borders[p].bottom; y < s->planeheight[p]; y++) { + memset(ptr + y * linesize, fill, s->planewidth[p]); + } + } +} + +static void fixed_borders16(FillBordersContext *s, AVFrame *frame) +{ + int p, y, x; + + for (p = 0; p < s->nb_planes; p++) { + uint16_t *ptr = (uint16_t *)frame->data[p]; + uint16_t fill = s->fill[p] << (s->depth - 8); + int linesize = frame->linesize[p] / 2; + + for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) { + for (x = 0; x < s->borders[p].left; x++) { + ptr[y * linesize + x] = fill; + } + + for (x = 0; x < s->borders[p].right; x++) { + ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] = fill; + } + } + + for (y = 0; y < s->borders[p].top; y++) { + for (x = 0; x < s->planewidth[p]; x++) { + ptr[y * linesize + x] = fill; + } + } + + for (y = s->planeheight[p] - s->borders[p].bottom; y < s->planeheight[p]; y++) { + for (x = 0; x < s->planewidth[p]; x++) { + ptr[y * linesize + x] = fill; + } + } + } +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + FillBordersContext *s = inlink->dst->priv; + + s->fillborders(s, frame); + + return ff_filter_frame(inlink->dst->outputs[0], frame); +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + FillBordersContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + + s->nb_planes = desc->nb_components; + s->depth = desc->comp[0].depth; + + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + + s->borders[0].left = s->borders[3].left = s->left; + s->borders[0].right = s->borders[3].right = s->right; + s->borders[0].top = s->borders[3].top = s->top; + s->borders[0].bottom = s->borders[3].bottom = s->bottom; + + s->borders[1].left = s->left >> desc->log2_chroma_w; + s->borders[1].right = s->right >> desc->log2_chroma_w; + s->borders[1].top = s->top >> desc->log2_chroma_h; + s->borders[1].bottom = s->bottom >> desc->log2_chroma_h; + + s->borders[2].left = s->left >> desc->log2_chroma_w; + s->borders[2].right = s->right >> desc->log2_chroma_w; + s->borders[2].top = s->top >> desc->log2_chroma_h; + s->borders[2].bottom = s->bottom >> desc->log2_chroma_h; + + if (inlink->w < s->left + s->right || + inlink->w <= s->left || + inlink->w <= s->right || + inlink->h < s->top + s->bottom || + inlink->h <= s->top || + inlink->h <= s->bottom || + inlink->w < s->left * 2 || + inlink->w < s->right * 2 || + inlink->h < s->top * 2 || + inlink->h < s->bottom * 2) { + av_log(ctx, AV_LOG_ERROR, "Borders are bigger than input frame size.\n"); + return AVERROR(EINVAL); + } + + switch (s->mode) { + case FM_SMEAR: s->fillborders = s->depth <= 8 ? smear_borders8 : smear_borders16; break; + case FM_MIRROR: s->fillborders = s->depth <= 8 ? mirror_borders8 : mirror_borders16; break; + case FM_FIXED: s->fillborders = s->depth <= 8 ? fixed_borders8 : fixed_borders16; break; + } + + s->yuv_color[Y] = RGB_TO_Y_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B]); + s->yuv_color[U] = RGB_TO_U_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B], 0); + s->yuv_color[V] = RGB_TO_V_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B], 0); + s->yuv_color[A] = s->rgba_color[A]; + + if (desc->flags & AV_PIX_FMT_FLAG_RGB) { + uint8_t rgba_map[4]; + int i; + + ff_fill_rgba_map(rgba_map, inlink->format); + for (i = 0; i < 4; i++) + s->fill[rgba_map[i]] = s->rgba_color[i]; + } else { + memcpy(s->fill, s->yuv_color, sizeof(s->yuv_color)); + } + + return 0; +} + +#define OFFSET(x) offsetof(FillBordersContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption fillborders_options[] = { + { "left", "set the left fill border", OFFSET(left), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, + { "right", "set the right fill border", OFFSET(right), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, + { "top", "set the top fill border", OFFSET(top), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, + { "bottom", "set the bottom fill border", OFFSET(bottom), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, + { "mode", "set the fill borders mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=FM_SMEAR}, 0, FM_NB_MODES-1, FLAGS, "mode" }, + { "smear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_SMEAR}, 0, 0, FLAGS, "mode" }, + { "mirror", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_MIRROR}, 0, 0, FLAGS, "mode" }, + { "fixed", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_FIXED}, 0, 0, FLAGS, "mode" }, + { "color", "set the color for the fixed mode", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str = "black"}, .flags = FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(fillborders); + +static const AVFilterPad fillborders_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + .filter_frame = filter_frame, + .needs_writable = 1, + }, + { NULL } +}; + +static const AVFilterPad fillborders_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_fillborders = { + .name = "fillborders", + .description = NULL_IF_CONFIG_SMALL("Fill borders of the input video."), + .priv_size = sizeof(FillBordersContext), + .priv_class = &fillborders_class, + .query_formats = query_formats, + .inputs = fillborders_inputs, + .outputs = fillborders_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, +}; From 9bed17cd0f02dda5e1211a7a61c24b8957a2e100 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 21 Nov 2017 22:01:42 +0100 Subject: [PATCH 1209/2557] checkasm/utvideo : be more explicit to the WIDTH_PADDED define --- tests/checkasm/utvideodsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/checkasm/utvideodsp.c b/tests/checkasm/utvideodsp.c index 618706a6e3b14..080b4287d73f8 100644 --- a/tests/checkasm/utvideodsp.c +++ b/tests/checkasm/utvideodsp.c @@ -27,7 +27,7 @@ #define WIDTH 240 #define HEIGHT 120 -#define WIDTH_PADDED (WIDTH+WIDTH%32) +#define WIDTH_PADDED (WIDTH + 16) /* padded to 32 */ #define BUFFER_SIZE (WIDTH_PADDED * HEIGHT) From 6939b3cb9d60a3159413d76c8656cb240c823412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Fri, 1 Dec 2017 22:21:54 +0200 Subject: [PATCH 1210/2557] mediacodecdec: fix build by including hwaccel.h Enables the decoder to utilize the type AVCodecHWConfigInternal. --- libavcodec/mediacodecdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 6d392adb3ab4f..39f5cbc045044 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -33,6 +33,7 @@ #include "avcodec.h" #include "h264_parse.h" #include "hevc_parse.h" +#include "hwaccel.h" #include "internal.h" #include "mediacodec_wrapper.h" #include "mediacodecdec_common.h" From a763d278274cfbda4e78e21b338b9b525fe22eab Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Fri, 1 Dec 2017 21:06:42 +0000 Subject: [PATCH 1211/2557] examples/vaapi_encode: Fix leak on hwframe init failure Fixes CID #1424882. --- doc/examples/vaapi_encode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/examples/vaapi_encode.c b/doc/examples/vaapi_encode.c index 866b03d58c4c2..f66a4a7c488dc 100644 --- a/doc/examples/vaapi_encode.c +++ b/doc/examples/vaapi_encode.c @@ -58,6 +58,7 @@ static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx) if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) { fprintf(stderr, "Failed to initialize VAAPI frame context." "Error code: %s\n",av_err2str(err)); + av_buffer_unref(&hw_frames_ref); return err; } ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref); From 0409d333115e623b5ccdbb364d64ca2a52fd8467 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Nov 2017 21:27:37 +0100 Subject: [PATCH 1212/2557] avcodec/hevcdsp_template: Fix undefined shift in put_hevc_epel_bi_w_h() Fixes: runtime error: left shift of negative value -127 Fixes: 4397/clusterfuzz-testcase-minimized-4779061080489984 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevcdsp_template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/hevcdsp_template.c b/libavcodec/hevcdsp_template.c index 46a0da204573f..0623cfad89688 100644 --- a/libavcodec/hevcdsp_template.c +++ b/libavcodec/hevcdsp_template.c @@ -1355,7 +1355,7 @@ static void FUNC(put_hevc_epel_bi_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = av_clip_pixel(((EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 + - ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); + ((ox0 + ox1 + 1) * (1 << log2Wd))) >> (log2Wd + 1)); src += srcstride; dst += dststride; src2 += MAX_PB_SIZE; From 0674087004538599797688785f6ac82358abc23b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Nov 2017 23:42:04 +0100 Subject: [PATCH 1213/2557] avcodec/j2kenc: Fix out of array access in encode_cblk() Fixes: 4427/clusterfuzz-testcase-minimized-5106919271301120 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 32c7fddb7416c..78ec88a6940fe 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -690,7 +690,8 @@ static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context *t1, Jpeg20 cblk->npasses = passno; cblk->ninclpasses = passno; - cblk->passes[passno-1].rate = ff_mqc_flush_to(&t1->mqc, cblk->passes[passno-1].flushed, &cblk->passes[passno-1].flushed_len); + if (passno) + cblk->passes[passno-1].rate = ff_mqc_flush_to(&t1->mqc, cblk->passes[passno-1].flushed, &cblk->passes[passno-1].flushed_len); } /* tier-2 routines: */ From b5587fd2c6ce39bad7a5e7ebb3bd86b6469648de Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 30 Nov 2017 21:51:56 +0100 Subject: [PATCH 1214/2557] avcodec/jpeg2000: Only allocate Jpeg2000Pass for the encoder Reduces memory needed. Fixes: OOM Fixes: 4427/clusterfuzz-testcase-minimized-5106919271301120 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/j2kenc.c | 4 +++- libavcodec/jpeg2000.c | 1 + libavcodec/jpeg2000.h | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index 78ec88a6940fe..3e542af3c66b6 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -941,7 +941,9 @@ static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno } if (!prec->cblk[cblkno].data) prec->cblk[cblkno].data = av_malloc(1 + 8192); - if (!prec->cblk[cblkno].data) + if (!prec->cblk[cblkno].passes) + prec->cblk[cblkno].passes = av_malloc_array(JPEG2000_MAX_PASSES, sizeof (*prec->cblk[cblkno].passes)); + if (!prec->cblk[cblkno].data || !prec->cblk[cblkno].passes) return AVERROR(ENOMEM); encode_cblk(s, &t1, prec->cblk + cblkno, tile, xx1 - xx0, yy1 - yy0, bandpos, codsty->nreslevels - reslevelno - 1); diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c index 8551cf8d6c965..5f3965047fba8 100644 --- a/libavcodec/jpeg2000.c +++ b/libavcodec/jpeg2000.c @@ -606,6 +606,7 @@ void ff_jpeg2000_cleanup(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty) for (cblkno = 0; cblkno < nb_code_blocks; cblkno ++) { Jpeg2000Cblk *cblk = &prec->cblk[cblkno]; av_freep(&cblk->data); + av_freep(&cblk->passes); } av_freep(&prec->cblk); } diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h index eaf7faf3424e5..752feae96bc25 100644 --- a/libavcodec/jpeg2000.h +++ b/libavcodec/jpeg2000.h @@ -173,7 +173,7 @@ typedef struct Jpeg2000Cblk { int nb_terminations; int nb_terminationsinc; int data_start[JPEG2000_MAX_PASSES]; - Jpeg2000Pass passes[JPEG2000_MAX_PASSES]; + Jpeg2000Pass *passes; int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} } Jpeg2000Cblk; // code block From bbfcb1b7c891319a3eb4420c144ddae471942631 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 12 Nov 2017 19:11:51 +0100 Subject: [PATCH 1215/2557] avfilter/vf_threshold: add x86 SIMD Signed-off-by: Paul B Mahol --- libavfilter/threshold.h | 51 +++++++++++++++++++++ libavfilter/vf_threshold.c | 28 +++--------- libavfilter/x86/Makefile | 2 + libavfilter/x86/vf_threshold.asm | 69 +++++++++++++++++++++++++++++ libavfilter/x86/vf_threshold_init.c | 41 +++++++++++++++++ 5 files changed, 169 insertions(+), 22 deletions(-) create mode 100644 libavfilter/threshold.h create mode 100644 libavfilter/x86/vf_threshold.asm create mode 100644 libavfilter/x86/vf_threshold_init.c diff --git a/libavfilter/threshold.h b/libavfilter/threshold.h new file mode 100644 index 0000000000000..8b55ad6ba1a33 --- /dev/null +++ b/libavfilter/threshold.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_THRESHOLD_H +#define AVFILTER_THRESHOLD_H + +#include "avfilter.h" +#include "framesync.h" + +typedef struct ThresholdContext { + const AVClass *class; + + int depth; + int planes; + int bpc; + + int nb_planes; + int width[4], height[4]; + + void (*threshold)(const uint8_t *in, const uint8_t *threshold, + const uint8_t *min, const uint8_t *max, + uint8_t *out, + ptrdiff_t ilinesize, ptrdiff_t tlinesize, + ptrdiff_t flinesize, ptrdiff_t slinesize, + ptrdiff_t olinesize, + int w, int h); + + AVFrame *frames[4]; + FFFrameSync fs; +} ThresholdContext; + +void ff_threshold_init_x86(ThresholdContext *s); + +#endif /* AVFILTER_THRESHOLD_H */ diff --git a/libavfilter/vf_threshold.c b/libavfilter/vf_threshold.c index 76c3ddb892ce6..4183b353d2cdf 100644 --- a/libavfilter/vf_threshold.c +++ b/libavfilter/vf_threshold.c @@ -31,27 +31,7 @@ #include "framesync.h" #include "internal.h" #include "video.h" - -typedef struct ThresholdContext { - const AVClass *class; - - int planes; - int bpc; - - int nb_planes; - int width[4], height[4]; - - void (*threshold)(const uint8_t *in, const uint8_t *threshold, - const uint8_t *min, const uint8_t *max, - uint8_t *out, - ptrdiff_t ilinesize, ptrdiff_t tlinesize, - ptrdiff_t flinesize, ptrdiff_t slinesize, - ptrdiff_t olinesize, - int w, int h); - - AVFrame *frames[4]; - FFFrameSync fs; -} ThresholdContext; +#include "threshold.h" #define OFFSET(x) offsetof(ThresholdContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM @@ -203,8 +183,9 @@ static int config_input(AVFilterLink *inlink) s->height[0] = s->height[3] = inlink->h; s->width[1] = s->width[2] = AV_CEIL_RSHIFT(inlink->w, hsub); s->width[0] = s->width[3] = inlink->w; + s->depth = desc->comp[0].depth; - if (desc->comp[0].depth == 8) { + if (s->depth == 8) { s->threshold = threshold8; s->bpc = 1; } else { @@ -212,6 +193,9 @@ static int config_input(AVFilterLink *inlink) s->bpc = 2; } + if (ARCH_X86) + ff_threshold_init_x86(s); + return 0; } diff --git a/libavfilter/x86/Makefile b/libavfilter/x86/Makefile index 34316258839cd..c10f4d553869b 100644 --- a/libavfilter/x86/Makefile +++ b/libavfilter/x86/Makefile @@ -20,6 +20,7 @@ OBJS-$(CONFIG_SPP_FILTER) += x86/vf_spp.o OBJS-$(CONFIG_SSIM_FILTER) += x86/vf_ssim_init.o OBJS-$(CONFIG_STEREO3D_FILTER) += x86/vf_stereo3d_init.o OBJS-$(CONFIG_TBLEND_FILTER) += x86/vf_blend_init.o +OBJS-$(CONFIG_THRESHOLD_FILTER) += x86/vf_threshold_init.o OBJS-$(CONFIG_TINTERLACE_FILTER) += x86/vf_tinterlace_init.o OBJS-$(CONFIG_VOLUME_FILTER) += x86/af_volume_init.o OBJS-$(CONFIG_W3FDIF_FILTER) += x86/vf_w3fdif_init.o @@ -46,6 +47,7 @@ X86ASM-OBJS-$(CONFIG_SHOWCQT_FILTER) += x86/avf_showcqt.o X86ASM-OBJS-$(CONFIG_SSIM_FILTER) += x86/vf_ssim.o X86ASM-OBJS-$(CONFIG_STEREO3D_FILTER) += x86/vf_stereo3d.o X86ASM-OBJS-$(CONFIG_TBLEND_FILTER) += x86/vf_blend.o +X86ASM-OBJS-$(CONFIG_THRESHOLD_FILTER) += x86/vf_threshold.o X86ASM-OBJS-$(CONFIG_TINTERLACE_FILTER) += x86/vf_interlace.o X86ASM-OBJS-$(CONFIG_VOLUME_FILTER) += x86/af_volume.o X86ASM-OBJS-$(CONFIG_W3FDIF_FILTER) += x86/vf_w3fdif.o diff --git a/libavfilter/x86/vf_threshold.asm b/libavfilter/x86/vf_threshold.asm new file mode 100644 index 0000000000000..9b0bfd8161790 --- /dev/null +++ b/libavfilter/x86/vf_threshold.asm @@ -0,0 +1,69 @@ +;***************************************************************************** +;* x86-optimized functions for threshold filter +;* +;* Copyright (C) 2017 Paul B Mahol +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;***************************************************************************** + +%include "libavutil/x86/x86util.asm" + +%if ARCH_X86_64 + +SECTION_RODATA + +pb_128: times 16 db 128 + +SECTION .text + +INIT_XMM sse4 +cglobal threshold8, 10, 13, 5, in, threshold, min, max, out, ilinesize, tlinesize, flinesize, slinesize, olinesize, w, h, x + mov wd, dword wm + mov hd, dword hm + mova m4, [pb_128] + add inq, wq + add thresholdq, wq + add minq, wq + add maxq, wq + add outq, wq + neg wq +.nextrow: + mov xq, wq + + .loop: + movu m1, [inq + xq] + movu m0, [thresholdq + xq] + movu m2, [minq + xq] + movu m3, [maxq + xq] + pxor m0, m4 + pxor m1, m4 + pcmpgtb m0, m1 + pblendvb m3, m2, m0 + movu [outq + xq], m3 + add xq, mmsize + jl .loop + + add inq, ilinesizeq + add thresholdq, tlinesizeq + add minq, flinesizeq + add maxq, slinesizeq + add outq, olinesizeq + sub hd, 1 + jg .nextrow +RET + +%endif diff --git a/libavfilter/x86/vf_threshold_init.c b/libavfilter/x86/vf_threshold_init.c new file mode 100644 index 0000000000000..e2bbae11d5891 --- /dev/null +++ b/libavfilter/x86/vf_threshold_init.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavfilter/threshold.h" + +void ff_threshold8_sse4(const uint8_t *in, const uint8_t *threshold, + const uint8_t *min, const uint8_t *max, + uint8_t *out, + ptrdiff_t ilinesize, ptrdiff_t tlinesize, + ptrdiff_t flinesize, ptrdiff_t slinesize, + ptrdiff_t olinesize, + int w, int h); + +av_cold void ff_threshold_init_x86(ThresholdContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (ARCH_X86_64 && EXTERNAL_SSE4(cpu_flags) && s->depth == 8) { + s->threshold = ff_threshold8_sse4; + } +} From 7bf3f380466eeff24916fd6218aca13e414c6240 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 9 Nov 2017 01:04:20 +0000 Subject: [PATCH 1216/2557] cbs: Add padding to slice data allocations These may be read by the bitstream reader, so they should include the necessary padding for overreads. --- libavcodec/cbs_h2645.c | 10 ++++++++-- libavcodec/cbs_mpeg2.c | 5 ++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 61729ccbb371d..00eed0f283609 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -781,13 +781,16 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, } slice->data_size = len - pos / 8; - slice->data = av_malloc(slice->data_size); + slice->data = av_malloc(slice->data_size + + AV_INPUT_BUFFER_PADDING_SIZE); if (!slice->data) { av_free(slice); return AVERROR(ENOMEM); } memcpy(slice->data, unit->data + pos / 8, slice->data_size); + memset(slice->data + slice->data_size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); slice->data_bit_start = pos % 8; unit->content = slice; @@ -943,13 +946,16 @@ static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx, } slice->data_size = len - pos / 8; - slice->data = av_malloc(slice->data_size); + slice->data = av_malloc(slice->data_size + + AV_INPUT_BUFFER_PADDING_SIZE); if (!slice->data) { av_free(slice); return AVERROR(ENOMEM); } memcpy(slice->data, unit->data + pos / 8, slice->data_size); + memset(slice->data + slice->data_size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); slice->data_bit_start = pos % 8; unit->content = slice; diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index 3c09377df3f0e..8a4da96a0ab4a 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -181,7 +181,8 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, len = unit->data_size; slice->data_size = len - pos / 8; - slice->data = av_malloc(slice->data_size); + slice->data = av_malloc(slice->data_size + + AV_INPUT_BUFFER_PADDING_SIZE); if (!slice->data) { av_free(slice); return AVERROR(ENOMEM); @@ -189,6 +190,8 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, memcpy(slice->data, unit->data + pos / 8, slice->data_size); + memset(slice->data + slice->data_size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); slice->data_bit_start = pos % 8; unit->content = slice; From e7adf2250b437165bc30c3b277bfce50875a0909 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Fri, 25 Aug 2017 15:56:51 +0800 Subject: [PATCH 1217/2557] vaapi_h265: Enable VBR mode To match vaapi_h264. From ffmpeg commit 385cafb07ac1e46433931ea9749a134efd7350be. Signed-off-by: Mark Thompson --- libavcodec/vaapi_encode_h265.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 477065e2cee61..0e5958d5315e1 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -839,13 +839,15 @@ static av_cold int vaapi_encode_h265_configure(AVCodecContext *avctx) "%d / %d / %d for IDR- / P- / B-frames.\n", priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b); - } else if (ctx->va_rc_mode == VA_RC_CBR) { + } else if (ctx->va_rc_mode == VA_RC_CBR || + ctx->va_rc_mode == VA_RC_VBR) { // These still need to be set for pic_init_qp/slice_qp_delta. priv->fixed_qp_idr = 30; priv->fixed_qp_p = 30; priv->fixed_qp_b = 30; - av_log(avctx, AV_LOG_DEBUG, "Using constant-bitrate = %d bps.\n", + av_log(avctx, AV_LOG_DEBUG, "Using %s-bitrate = %d bps.\n", + ctx->va_rc_mode == VA_RC_CBR ? "constant" : "variable", avctx->bit_rate); } else { @@ -905,9 +907,12 @@ static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx) } ctx->va_entrypoint = VAEntrypointEncSlice; - if (avctx->bit_rate > 0) - ctx->va_rc_mode = VA_RC_CBR; - else + if (avctx->bit_rate > 0) { + if (avctx->rc_max_rate == avctx->bit_rate) + ctx->va_rc_mode = VA_RC_CBR; + else + ctx->va_rc_mode = VA_RC_VBR; + } else ctx->va_rc_mode = VA_RC_CQP; ctx->va_packed_headers = From 5a6707e49b7710f48d658b2f2591b9a6337fb9b7 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 9 Nov 2017 01:04:25 +0000 Subject: [PATCH 1218/2557] cbs_mpeg2: Fix marker_bit type --- libavcodec/cbs_mpeg2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index 8a4da96a0ab4a..54875c2e1c379 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -54,7 +54,7 @@ xui(width, name, current->name) #define marker_bit() do { \ - av_unused int one = 1; \ + av_unused uint32_t one; \ CHECK(ff_cbs_read_unsigned(ctx, rw, 1, "marker_bit", &one, 1, 1)); \ } while (0) From 4b57f064477cd39e7236897bbbb90b909e6deed2 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Tue, 24 Oct 2017 13:25:21 +0800 Subject: [PATCH 1219/2557] vaapi_h264: Fix VUI max_dec_frame_buffering This should refer to the existing SPS structure, not the VAAPI sequence parameter buffer (which is not yet initialised). From ffmpeg commit f31478ba1472afe5c1eed60f219ae331816425a2. Signed-off-by: Mark Thompson --- libavcodec/vaapi_encode_h264.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 03605b05b29e8..e6a166698ba0b 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -453,7 +453,7 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) sps->vui.log2_max_mv_length_horizontal = 16; sps->vui.log2_max_mv_length_vertical = 16; sps->vui.max_num_reorder_frames = (ctx->b_per_p > 0); - sps->vui.max_dec_frame_buffering = vseq->max_num_ref_frames; + sps->vui.max_dec_frame_buffering = sps->max_num_ref_frames; pps->nal_unit_header.nal_ref_idc = 3; pps->nal_unit_header.nal_unit_type = H264_NAL_PPS; From e171022c24c42b1e88a51bb3b4c27f13c87c85cb Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 9 Nov 2017 01:04:44 +0000 Subject: [PATCH 1220/2557] vaapi: Make the decode profile matching more explicit Also fixes a bug where it could attempt to decode with an unsupported codec if allow-profile-mismatch was set. --- libavcodec/vaapi_decode.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index 02304191ff03e..cc79875ef1b43 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -284,8 +284,8 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, VAStatus vas; int err, i, j; const AVCodecDescriptor *codec_desc; - VAProfile profile, *profile_list = NULL; - int profile_count, exact_match, alt_profile; + VAProfile *profile_list = NULL, matched_va_profile; + int profile_count, exact_match, matched_ff_profile; const AVPixFmtDescriptor *sw_desc, *desc; AVHWDeviceContext *device = (AVHWDeviceContext*)device_ref->data; @@ -314,7 +314,7 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, goto fail; } - profile = VAProfileNone; + matched_va_profile = VAProfileNone; exact_match = 0; for (i = 0; i < FF_ARRAY_ELEMS(vaapi_profile_map); i++) { @@ -324,22 +324,22 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, if (avctx->profile == vaapi_profile_map[i].codec_profile || vaapi_profile_map[i].codec_profile == FF_PROFILE_UNKNOWN) profile_match = 1; - profile = vaapi_profile_map[i].va_profile; for (j = 0; j < profile_count; j++) { - if (profile == profile_list[j]) { + if (vaapi_profile_map[i].va_profile == profile_list[j]) { exact_match = profile_match; break; } } if (j < profile_count) { + matched_va_profile = vaapi_profile_map[i].va_profile; + matched_ff_profile = vaapi_profile_map[i].codec_profile; if (exact_match) break; - alt_profile = vaapi_profile_map[i].codec_profile; } } av_freep(&profile_list); - if (profile == VAProfileNone) { + if (matched_va_profile == VAProfileNone) { av_log(avctx, AV_LOG_ERROR, "No support for codec %s " "profile %d.\n", codec_desc->name, avctx->profile); err = AVERROR(ENOSYS); @@ -353,7 +353,7 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, codec_desc->name, avctx->profile); av_log(avctx, AV_LOG_WARNING, "Using possibly-" "incompatible profile %d instead.\n", - alt_profile); + matched_ff_profile); } else { av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not " "supported for hardware decode.\n", @@ -363,7 +363,7 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, } } - vas = vaCreateConfig(hwctx->display, profile, + vas = vaCreateConfig(hwctx->display, matched_va_profile, VAEntrypointVLD, NULL, 0, va_config); if (vas != VA_STATUS_SUCCESS) { From b37196adff750b49cdf2d2739deb069cfcbfd4eb Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 2 Dec 2017 18:22:14 +0100 Subject: [PATCH 1221/2557] avutil/x86util : add macro for loading a 128 bits constants in an xmm or in each part of an ymm in order to simplify avx2 asm func --- libavutil/x86/x86util.asm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavutil/x86/x86util.asm b/libavutil/x86/x86util.asm index 21419125d5e1e..d7cd996842f59 100644 --- a/libavutil/x86/x86util.asm +++ b/libavutil/x86/x86util.asm @@ -890,6 +890,14 @@ %endif %endmacro +%macro VBROADCASTI128 2 ; dst xmm/ymm, src : 128bits val +%if mmsize > 16 + vbroadcasti128 %1, %2 +%else + mova %1, %2 +%endif +%endmacro + %macro SHUFFLE_MASK_W 8 %rep 8 %if %1>=0x80 From be6d1f9632e24f1b74d83ad8896ee9d0da72854c Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 2 Dec 2017 18:22:32 +0100 Subject: [PATCH 1222/2557] avcodec/x86/bswapdsp : use macro for 128 bits constants loading in xmm or ymm --- libavcodec/x86/bswapdsp.asm | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libavcodec/x86/bswapdsp.asm b/libavcodec/x86/bswapdsp.asm index 213ffbde07fc0..31c6c48a21dee 100644 --- a/libavcodec/x86/bswapdsp.asm +++ b/libavcodec/x86/bswapdsp.asm @@ -104,11 +104,7 @@ SECTION .text %if cpuflag(ssse3)||cpuflag(avx2) cglobal bswap32_buf, 3,4,3 mov r3, r1 -%if cpuflag(avx2) - vbroadcasti128 m2, [pb_bswap32] -%else - mova m2, [pb_bswap32] -%endif + VBROADCASTI128 m2, [pb_bswap32] %else cglobal bswap32_buf, 3,4,5 mov r3, r1 From 53c492640c6b4690715793372454194379093d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Tue, 14 Nov 2017 18:26:49 +0000 Subject: [PATCH 1223/2557] avutil/mem: Add DECLARE_ASM_ALIGNED macro for DJGPP architecture. The macro was added in 43171a2a738f5114768d34a7278e56e5fde714bc, but I forgot to add it to the DJGPP architecture in that change. Signed-off-by: Michael Niedermayer --- libavutil/mem.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/mem.h b/libavutil/mem.h index 9e344bd2c3355..7e0b12a8a782c 100644 --- a/libavutil/mem.h +++ b/libavutil/mem.h @@ -106,6 +106,7 @@ #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v #elif defined(__DJGPP__) #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (FFMIN(n, 16)))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v #elif defined(__GNUC__) || defined(__clang__) #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v From 09494d098405738a5972e0052110af65b3ff7e72 Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Tue, 28 Nov 2017 13:40:20 -0800 Subject: [PATCH 1224/2557] avformat/oggdec: Respect AVERROR codes returned by ogg parsers. Fixes ticket #6804. All of the ogg header and packet parsers may return standard AVERROR codes; these return values should not be treated as success. Additionally changes oggparsevorbis, to not give up too early with certain types of poorly muxed files. Signed-off-by: Dale Curtis Signed-off-by: Michael Niedermayer --- libavformat/oggdec.c | 14 +++++++++++--- libavformat/oggparsevorbis.c | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 193a286e43576..38f60653f98fa 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -543,7 +543,11 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, os->incomplete = 0; if (os->header) { - os->header = os->codec->header(s, idx); + if ((ret = os->codec->header(s, idx)) < 0) { + av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret)); + return ret; + } + os->header = ret; if (!os->header) { os->segp = segp; os->psize = psize; @@ -574,8 +578,12 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, } else { os->pflags = 0; os->pduration = 0; - if (os->codec && os->codec->packet) - os->codec->packet(s, idx); + if (os->codec && os->codec->packet) { + if ((ret = os->codec->packet(s, idx)) < 0) { + av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret)); + return ret; + } + } if (sid) *sid = idx; if (dstart) diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c index 65b1998a02d92..29b1ab514e642 100644 --- a/libavformat/oggparsevorbis.c +++ b/libavformat/oggparsevorbis.c @@ -317,7 +317,7 @@ static int vorbis_header(AVFormatContext *s, int idx) if (priv->packet[pkt_type >> 1]) return AVERROR_INVALIDDATA; if (pkt_type > 1 && !priv->packet[0] || pkt_type > 3 && !priv->packet[1]) - return AVERROR_INVALIDDATA; + return priv->vp ? 0 : AVERROR_INVALIDDATA; priv->len[pkt_type >> 1] = os->psize; priv->packet[pkt_type >> 1] = av_mallocz(os->psize); From 00d454ed2ca3f8b4d454a837e95931afe604c53f Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Sun, 19 Nov 2017 12:46:30 -0800 Subject: [PATCH 1225/2557] lavf/movenc: add sdtp (sample dependency) box The sdtp is required by the AppleTV 4K in order to play 2160p60 video. Signed-off-by: Michael Niedermayer --- libavcodec/avcodec.h | 6 ++++++ libavformat/isom.h | 5 +++++ libavformat/movenc.c | 30 ++++++++++++++++++++++++++++++ libavformat/movenc.h | 2 ++ 4 files changed, 43 insertions(+) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 0972df0bde238..5db6a81320e54 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1444,6 +1444,12 @@ typedef struct AVPacket { * outside the packet may be followed. */ #define AV_PKT_FLAG_TRUSTED 0x0008 +/** + * Flag is used to indicate packets that contain frames that can + * be discarded by the decoder. I.e. Non-reference frames. + */ +#define AV_PKT_FLAG_DISPOSABLE 0x0010 + enum AVSideDataParamChangeFlags { AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, diff --git a/libavformat/isom.h b/libavformat/isom.h index ff08f5d090c85..65676fb0f55f7 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -318,6 +318,11 @@ void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id); #define MOV_TKHD_FLAG_IN_PREVIEW 0x0004 #define MOV_TKHD_FLAG_IN_POSTER 0x0008 +#define MOV_SAMPLE_DEPENDENCY_UNKNOWN 0x0 +#define MOV_SAMPLE_DEPENDENCY_YES 0x1 +#define MOV_SAMPLE_DEPENDENCY_NO 0x2 + + #define TAG_IS_AVCI(tag) \ ((tag) == MKTAG('a', 'i', '5', 'p') || \ (tag) == MKTAG('a', 'i', '5', 'q') || \ diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 0d924ad75848a..901577401eb53 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -252,6 +252,30 @@ static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag) return update_size(pb, pos); } +/* Sample dependency atom */ +static int mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track) +{ + int i; + uint8_t leading, dependent, reference, redundancy; + int64_t pos = avio_tell(pb); + avio_wb32(pb, 0); // size + ffio_wfourcc(pb, "sdtp"); + avio_wb32(pb, 0); // version & flags + for (i = 0; i < track->entry; i++) { + dependent = MOV_SAMPLE_DEPENDENCY_YES; + leading = reference = redundancy = MOV_SAMPLE_DEPENDENCY_UNKNOWN; + if (track->cluster[i].flags & MOV_DISPOSABLE_SAMPLE) { + reference = MOV_SAMPLE_DEPENDENCY_NO; + } + if (track->cluster[i].flags & MOV_SYNC_SAMPLE) { + dependent = MOV_SAMPLE_DEPENDENCY_NO; + } + avio_w8(pb, (leading << 6) | (dependent << 4) | + (reference << 2) | redundancy); + } + return update_size(pb, pos); +} + static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track) { avio_wb32(pb, 0x11); /* size */ @@ -2353,6 +2377,8 @@ static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext track->par->codec_tag == MKTAG('r','t','p',' ')) && track->has_keyframes && track->has_keyframes < track->entry) mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE); + if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->has_disposable) + mov_write_sdtp_tag(pb, track); if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS) mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE); if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && @@ -5316,6 +5342,10 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE) trk->has_keyframes++; } + if (pkt->flags & AV_PKT_FLAG_DISPOSABLE) { + trk->cluster[trk->entry].flags |= MOV_DISPOSABLE_SAMPLE; + trk->has_disposable++; + } trk->entry++; trk->sample_count += samples_in_chunk; mov->mdat_size += size; diff --git a/libavformat/movenc.h b/libavformat/movenc.h index cc2a155d79aa4..c4e966b7fb75f 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -53,6 +53,7 @@ typedef struct MOVIentry { int cts; #define MOV_SYNC_SAMPLE 0x0001 #define MOV_PARTIAL_SYNC_SAMPLE 0x0002 +#define MOV_DISPOSABLE_SAMPLE 0x0004 uint32_t flags; } MOVIentry; @@ -89,6 +90,7 @@ typedef struct MOVTrack { long sample_size; long chunkCount; int has_keyframes; + int has_disposable; #define MOV_TRACK_CTTS 0x0001 #define MOV_TRACK_STPS 0x0002 #define MOV_TRACK_ENABLED 0x0004 From 225341b20de609c651e0d375a79d29c2f5540dce Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 2 Dec 2017 23:29:49 +0100 Subject: [PATCH 1226/2557] avfilter/vf_stack: always copy SAR from first input Signed-off-by: Paul B Mahol --- libavfilter/vf_stack.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c index 2467302159f3f..b2b8c68041d21 100644 --- a/libavfilter/vf_stack.c +++ b/libavfilter/vf_stack.c @@ -105,6 +105,7 @@ static int process_frame(FFFrameSync *fs) if (!out) return AVERROR(ENOMEM); out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); + out->sample_aspect_ratio = outlink->sample_aspect_ratio; for (i = 0; i < s->nb_inputs; i++) { AVFilterLink *inlink = ctx->inputs[i]; @@ -147,6 +148,7 @@ static int config_output(AVFilterLink *outlink) StackContext *s = ctx->priv; AVRational time_base = ctx->inputs[0]->time_base; AVRational frame_rate = ctx->inputs[0]->frame_rate; + AVRational sar = ctx->inputs[0]->sample_aspect_ratio; int height = ctx->inputs[0]->h; int width = ctx->inputs[0]->w; FFFrameSyncIn *in; @@ -179,6 +181,7 @@ static int config_output(AVFilterLink *outlink) outlink->h = height; outlink->time_base = time_base; outlink->frame_rate = frame_rate; + outlink->sample_aspect_ratio = sar; if ((ret = ff_framesync_init(&s->fs, ctx, s->nb_inputs)) < 0) return ret; From 4bb7d72bcfb56ae4fe56055927cf53cf484f5df4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 25 Nov 2017 22:21:16 +0100 Subject: [PATCH 1227/2557] avcodec/h264_parse: Treat escaped and unescaped decoding error equal in decode_extradata_ps_mp4() Fixes: lorex.mp4 Fixes: ticket6762 Signed-off-by: Michael Niedermayer --- libavcodec/h264_parse.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c index a7c71d9bbbbed..fee28d90d990a 100644 --- a/libavcodec/h264_parse.c +++ b/libavcodec/h264_parse.c @@ -425,10 +425,9 @@ static int decode_extradata_ps_mp4(const uint8_t *buf, int buf_size, H264ParamSe escaped_buf_size = bytestream2_tell_p(&pbc); AV_WB16(escaped_buf, escaped_buf_size - 2); - ret = decode_extradata_ps(escaped_buf, escaped_buf_size, ps, 1, logctx); + (void)decode_extradata_ps(escaped_buf, escaped_buf_size, ps, 1, logctx); + // lorex.mp4 decodes ok even with extradata decoding failing av_freep(&escaped_buf); - if (ret < 0) - return ret; } return 0; From 42a22d01d1a0d49b83121228df816d8183f0b85c Mon Sep 17 00:00:00 2001 From: Jim DeLaHunt Date: Sun, 26 Nov 2017 00:31:11 -0800 Subject: [PATCH 1228/2557] doc: reorganize developer.texi chapter hierarchy Previously, the Developer Documentation contained a single chapter, "1. Developer Guide," with all content under that single chapter. Thus the document structure was one level deeper and more complicated than it needed to be. It differed from similar documents such as /faq.html, which have multiple chapters. Eliminate the single chapter, and promote each section underneath to chapter, and each subsection to section. Thus content and relative structure remains the same, but the overall structure is simpler. Anchors within the page remain the same. Signed-off-by: Jim DeLaHunt Signed-off-by: Timothy Gu --- doc/developer.texi | 53 +++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/doc/developer.texi b/doc/developer.texi index a7b4f1d7371d8..89124a295ca3d 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -10,9 +10,7 @@ @contents -@chapter Developers Guide - -@section Notes for external developers +@chapter Notes for external developers This document is mostly useful for internal FFmpeg developers. External developers who need to use the API in their application should @@ -30,7 +28,7 @@ For more detailed legal information about the use of FFmpeg in external programs read the @file{LICENSE} file in the source tree and consult @url{https://ffmpeg.org/legal.html}. -@section Contributing +@chapter Contributing There are 3 ways by which code gets into FFmpeg. @itemize @bullet @@ -47,9 +45,9 @@ The developer making the commit and the author are responsible for their changes and should try to fix issues their commit causes. @anchor{Coding Rules} -@section Coding Rules +@chapter Coding Rules -@subsection Code formatting conventions +@section Code formatting conventions There are the following guidelines regarding the indentation in files: @@ -74,7 +72,7 @@ The presentation is one inspired by 'indent -i4 -kr -nut'. The main priority in FFmpeg is simplicity and small code size in order to minimize the bug count. -@subsection Comments +@section Comments Use the JavaDoc/Doxygen format (see examples below) so that code documentation can be generated automatically. All nontrivial functions should have a comment above them explaining what the function does, even if it is just one sentence. @@ -114,7 +112,7 @@ int myfunc(int my_parameter) ... @end example -@subsection C language features +@section C language features FFmpeg is programmed in the ISO C90 language with a few additional features from ISO C99, namely: @@ -160,7 +158,7 @@ mixing statements and declarations; GCC statement expressions (@samp{(x = (@{ int y = 4; y; @})}). @end itemize -@subsection Naming conventions +@section Naming conventions All names should be composed with underscores (_), not CamelCase. For example, @samp{avfilter_get_video_buffer} is an acceptable function name and @samp{AVFilterGetVideo} is not. The exception from this are type names, like @@ -204,7 +202,7 @@ letter as they are reserved by the C standard. Names starting with @code{_} are reserved at the file level and may not be used for externally visible symbols. If in doubt, just avoid names starting with @code{_} altogether. -@subsection Miscellaneous conventions +@section Miscellaneous conventions @itemize @bullet @item @@ -216,7 +214,7 @@ Casts should be used only when necessary. Unneeded parentheses should also be avoided if they don't make the code easier to understand. @end itemize -@subsection Editor configuration +@section Editor configuration In order to configure Vim to follow FFmpeg formatting conventions, paste the following snippet into your @file{.vimrc}: @example @@ -249,9 +247,9 @@ For Emacs, add these roughly equivalent lines to your @file{.emacs.d/init.el}: (setq c-default-style "ffmpeg") @end lisp -@section Development Policy +@chapter Development Policy -@subsection Patches/Committing +@section Patches/Committing @subheading Licenses for patches must be compatible with FFmpeg. Contributions should be licensed under the @uref{http://www.gnu.org/licenses/lgpl-2.1.html, LGPL 2.1}, @@ -350,7 +348,7 @@ time-frame (12h for build failures and security fixes, 3 days small changes, 1 week for big patches) then commit your patch if you think it is OK. Also note, the maintainer can simply ask for more time to review! -@subsection Code +@section Code @subheading API/ABI changes should be discussed before they are made. Do not change behavior of the programs (renaming options etc) or public API or ABI without first discussing it on the ffmpeg-devel mailing list. @@ -381,7 +379,8 @@ Never write to unallocated memory, never write over the end of arrays, always check values read from some untrusted source before using them as array index or other risky things. -@subsection Documentation/Other +@section Documentation/Other + @subheading Subscribe to the ffmpeg-cvslog mailing list. It is important to do this as the diffs of all commits are sent there and reviewed by all the other developers. Bugs and possible improvements or @@ -406,7 +405,7 @@ finding a new maintainer and also don't forget to update the @file{MAINTAINERS} We think our rules are not too hard. If you have comments, contact us. -@section Code of conduct +@chapter Code of conduct Be friendly and respectful towards others and third parties. Treat others the way you yourself want to be treated. @@ -436,7 +435,7 @@ Finally, keep in mind the immortal words of Bill and Ted, "Be excellent to each other." @anchor{Submitting patches} -@section Submitting patches +@chapter Submitting patches First, read the @ref{Coding Rules} above if you did not yet, in particular the rules regarding patch submission. @@ -485,7 +484,7 @@ Give us a few days to react. But if some time passes without reaction, send a reminder by email. Your patch should eventually be dealt with. -@section New codecs or formats checklist +@chapter New codecs or formats checklist @enumerate @item @@ -537,7 +536,7 @@ Did you make sure it compiles standalone, i.e. with @end enumerate -@section patch submission checklist +@chapter Patch submission checklist @enumerate @item @@ -650,7 +649,7 @@ Test your code with valgrind and or Address Sanitizer to ensure it's free of leaks, out of array accesses, etc. @end enumerate -@section Patch review process +@chapter Patch review process All patches posted to ffmpeg-devel will be reviewed, unless they contain a clear note that the patch is not for the git master branch. @@ -681,7 +680,7 @@ to be reviewed, please consider helping to review other patches, that is a great way to get everyone's patches reviewed sooner. @anchor{Regression tests} -@section Regression tests +@chapter Regression tests Before submitting a patch (or committing to the repository), you should at least test that you did not break anything. @@ -692,7 +691,7 @@ Running 'make fate' accomplishes this, please see @url{fate.html} for details. this case, the reference results of the regression tests shall be modified accordingly]. -@subsection Adding files to the fate-suite dataset +@section Adding files to the fate-suite dataset When there is no muxer or encoder available to generate test media for a specific test then the media has to be included in the fate-suite. @@ -703,7 +702,7 @@ Once you have a working fate test and fate sample, provide in the commit message or introductory message for the patch series that you post to the ffmpeg-devel mailing list, a direct link to download the sample media. -@subsection Visualizing Test Coverage +@section Visualizing Test Coverage The FFmpeg build system allows visualizing the test coverage in an easy manner with the coverage tools @code{gcov}/@code{lcov}. This involves @@ -730,7 +729,7 @@ You can use the command @code{make lcov-reset} to reset the coverage measurements. You will need to rerun @code{make lcov} after running a new test. -@subsection Using Valgrind +@section Using Valgrind The configure script provides a shortcut for using valgrind to spot bugs related to memory handling. Just add the option @@ -744,7 +743,7 @@ In case you need finer control over how valgrind is invoked, use the your configure line instead. @anchor{Release process} -@section Release process +@chapter Release process FFmpeg maintains a set of @strong{release branches}, which are the recommended deliverable for system integrators and distributors (such as @@ -776,7 +775,7 @@ adjustments to the symbol versioning file. Please discuss such changes on the @strong{ffmpeg-devel} mailing list in time to allow forward planning. @anchor{Criteria for Point Releases} -@subsection Criteria for Point Releases +@section Criteria for Point Releases Changes that match the following criteria are valid candidates for inclusion into a point release: @@ -800,7 +799,7 @@ point releases of the same release branch. The order for checking the rules is (1 OR 2 OR 3) AND 4. -@subsection Release Checklist +@section Release Checklist The release process involves the following steps: From fa470384ea3f4bed8507495db19c187f69ed1307 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 3 Dec 2017 16:55:37 +0100 Subject: [PATCH 1229/2557] avfilter/vf_threshold : move context func init in ff_threshold_init --- libavfilter/threshold.h | 1 + libavfilter/vf_threshold.c | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libavfilter/threshold.h b/libavfilter/threshold.h index 8b55ad6ba1a33..775a9f9cae911 100644 --- a/libavfilter/threshold.h +++ b/libavfilter/threshold.h @@ -46,6 +46,7 @@ typedef struct ThresholdContext { FFFrameSync fs; } ThresholdContext; +void ff_threshold_init(ThresholdContext *s); void ff_threshold_init_x86(ThresholdContext *s); #endif /* AVFILTER_THRESHOLD_H */ diff --git a/libavfilter/vf_threshold.c b/libavfilter/vf_threshold.c index 4183b353d2cdf..58b5d148368d1 100644 --- a/libavfilter/vf_threshold.c +++ b/libavfilter/vf_threshold.c @@ -185,6 +185,13 @@ static int config_input(AVFilterLink *inlink) s->width[0] = s->width[3] = inlink->w; s->depth = desc->comp[0].depth; + ff_threshold_init(s); + + return 0; +} + +void ff_threshold_init(ThresholdContext *s) +{ if (s->depth == 8) { s->threshold = threshold8; s->bpc = 1; @@ -195,8 +202,6 @@ static int config_input(AVFilterLink *inlink) if (ARCH_X86) ff_threshold_init_x86(s); - - return 0; } static int config_output(AVFilterLink *outlink) From cfce4427503a1f17cddfcb32b9e414af508061b7 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 3 Dec 2017 16:56:25 +0100 Subject: [PATCH 1230/2557] checkasm/vf_threshold : add checkasm test for threshold8 --- tests/checkasm/Makefile | 1 + tests/checkasm/checkasm.c | 3 ++ tests/checkasm/checkasm.h | 1 + tests/checkasm/vf_threshold.c | 79 +++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+) create mode 100644 tests/checkasm/vf_threshold.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 6add9ded12566..f35359daa929e 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -32,6 +32,7 @@ CHECKASMOBJS-$(CONFIG_AVCODEC) += $(AVCODECOBJS-yes) # libavfilter tests AVFILTEROBJS-$(CONFIG_BLEND_FILTER) += vf_blend.o AVFILTEROBJS-$(CONFIG_COLORSPACE_FILTER) += vf_colorspace.o +AVFILTEROBJS-$(CONFIG_THRESHOLD_FILTER) += vf_threshold.o CHECKASMOBJS-$(CONFIG_AVFILTER) += $(AVFILTEROBJS-yes) diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index a8b34ba898f04..384092a2e4660 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -152,6 +152,9 @@ static const struct { #if CONFIG_COLORSPACE_FILTER { "vf_colorspace", checkasm_check_colorspace }, #endif + #if CONFIG_THRESHOLD_FILTER + { "vf_threshold", checkasm_check_vf_threshold }, + #endif #endif #if CONFIG_AVUTIL { "fixed_dsp", checkasm_check_fixed_dsp }, diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 483f418cb5ab9..8fe42d575086e 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -65,6 +65,7 @@ void checkasm_check_sbrdsp(void); void checkasm_check_synth_filter(void); void checkasm_check_utvideodsp(void); void checkasm_check_v210enc(void); +void checkasm_check_vf_threshold(void); void checkasm_check_vp8dsp(void); void checkasm_check_vp9dsp(void); void checkasm_check_videodsp(void); diff --git a/tests/checkasm/vf_threshold.c b/tests/checkasm/vf_threshold.c new file mode 100644 index 0000000000000..770f00ed3b4f5 --- /dev/null +++ b/tests/checkasm/vf_threshold.c @@ -0,0 +1,79 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "checkasm.h" +#include "libavfilter/threshold.h" +#include "libavutil/intreadwrite.h" + +#define WIDTH 256 +#define WIDTH_PADDED 256 + 32 + +#define randomize_buffers(buf, size) \ + do { \ + int j; \ + uint8_t *tmp_buf = (uint8_t *)buf;\ + for (j = 0; j < size; j++) \ + tmp_buf[j] = rnd() & 0xFF; \ + } while (0) + +static void check_threshold_8(void){ + LOCAL_ALIGNED_32(uint8_t, in , [WIDTH_PADDED]); + LOCAL_ALIGNED_32(uint8_t, threshold, [WIDTH_PADDED]); + LOCAL_ALIGNED_32(uint8_t, min , [WIDTH_PADDED]); + LOCAL_ALIGNED_32(uint8_t, max , [WIDTH_PADDED]); + LOCAL_ALIGNED_32(uint8_t, out_ref , [WIDTH_PADDED]); + LOCAL_ALIGNED_32(uint8_t, out_new , [WIDTH_PADDED]); + ptrdiff_t line_size = WIDTH_PADDED; + int w = WIDTH; + + ThresholdContext s; + s.depth = 8; + ff_threshold_init(&s); + + declare_func(void, const uint8_t *in, const uint8_t *threshold, + const uint8_t *min, const uint8_t *max, uint8_t *out, + ptrdiff_t ilinesize, ptrdiff_t tlinesize, + ptrdiff_t flinesize, ptrdiff_t slinesize, + ptrdiff_t olinesize, int w, int h); + + memset(in, 0, WIDTH_PADDED); + memset(threshold, 0, WIDTH_PADDED); + memset(min, 0, WIDTH_PADDED); + memset(max, 0, WIDTH_PADDED); + memset(out_ref, 0, WIDTH_PADDED); + memset(out_new, 0, WIDTH_PADDED); + randomize_buffers(in, WIDTH); + randomize_buffers(threshold, WIDTH); + randomize_buffers(min, WIDTH); + randomize_buffers(max, WIDTH); + + if (check_func(s.threshold, "threshold8")) { + call_ref(in, threshold, min, max, out_ref, line_size, line_size, line_size, line_size, line_size, w, 1); + call_new(in, threshold, min, max, out_new, line_size, line_size, line_size, line_size, line_size, w, 1); + if (memcmp(out_ref, out_new, w)) + fail(); + bench_new(in, threshold, min, max, out_new, line_size, line_size, line_size, line_size, line_size, w, 1); + } +} + +void checkasm_check_vf_threshold(void) +{ + check_threshold_8(); + report("threshold8"); +} From 51345cb1d5539027f2faa45b920cf97bbd9d5ff1 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 3 Dec 2017 16:58:09 +0100 Subject: [PATCH 1231/2557] avfilter/x86/vf_threshold : make macro for threshold8 in order to add avx2 version --- libavfilter/x86/vf_threshold.asm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavfilter/x86/vf_threshold.asm b/libavfilter/x86/vf_threshold.asm index 9b0bfd8161790..38499dcd044d9 100644 --- a/libavfilter/x86/vf_threshold.asm +++ b/libavfilter/x86/vf_threshold.asm @@ -30,7 +30,7 @@ pb_128: times 16 db 128 SECTION .text -INIT_XMM sse4 +%macro THRESHOLD_8 0 cglobal threshold8, 10, 13, 5, in, threshold, min, max, out, ilinesize, tlinesize, flinesize, slinesize, olinesize, w, h, x mov wd, dword wm mov hd, dword hm @@ -65,5 +65,9 @@ cglobal threshold8, 10, 13, 5, in, threshold, min, max, out, ilinesize, tlinesiz sub hd, 1 jg .nextrow RET +%endmacro + +INIT_XMM sse4 +THRESHOLD_8 %endif From 9719d57b34f2156dc26d7a46ba809b1f9427011c Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 3 Dec 2017 17:02:44 +0100 Subject: [PATCH 1232/2557] avfilter/x86/vf_threshold : add avx2 version for threshold 8 --- libavfilter/x86/vf_threshold.asm | 7 ++++++- libavfilter/x86/vf_threshold_init.c | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/libavfilter/x86/vf_threshold.asm b/libavfilter/x86/vf_threshold.asm index 38499dcd044d9..117cc98fe2262 100644 --- a/libavfilter/x86/vf_threshold.asm +++ b/libavfilter/x86/vf_threshold.asm @@ -34,7 +34,7 @@ SECTION .text cglobal threshold8, 10, 13, 5, in, threshold, min, max, out, ilinesize, tlinesize, flinesize, slinesize, olinesize, w, h, x mov wd, dword wm mov hd, dword hm - mova m4, [pb_128] + VBROADCASTI128 m4, [pb_128] add inq, wq add thresholdq, wq add minq, wq @@ -70,4 +70,9 @@ RET INIT_XMM sse4 THRESHOLD_8 +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +THRESHOLD_8 +%endif + %endif diff --git a/libavfilter/x86/vf_threshold_init.c b/libavfilter/x86/vf_threshold_init.c index e2bbae11d5891..f448cb4b39f96 100644 --- a/libavfilter/x86/vf_threshold_init.c +++ b/libavfilter/x86/vf_threshold_init.c @@ -30,12 +30,26 @@ void ff_threshold8_sse4(const uint8_t *in, const uint8_t *threshold, ptrdiff_t flinesize, ptrdiff_t slinesize, ptrdiff_t olinesize, int w, int h); +void ff_threshold8_avx2(const uint8_t *in, const uint8_t *threshold, + const uint8_t *min, const uint8_t *max, + uint8_t *out, + ptrdiff_t ilinesize, ptrdiff_t tlinesize, + ptrdiff_t flinesize, ptrdiff_t slinesize, + ptrdiff_t olinesize, + int w, int h); av_cold void ff_threshold_init_x86(ThresholdContext *s) { int cpu_flags = av_get_cpu_flags(); - if (ARCH_X86_64 && EXTERNAL_SSE4(cpu_flags) && s->depth == 8) { - s->threshold = ff_threshold8_sse4; + if (ARCH_X86_64) { + if (s->depth == 8) { + if (EXTERNAL_SSE4(cpu_flags)) { + s->threshold = ff_threshold8_sse4; + } + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + s->threshold = ff_threshold8_avx2; + } + } } } From 6e3e696591483747d99d7fda8da1b7f1f7932cab Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 3 Dec 2017 17:04:38 +0100 Subject: [PATCH 1233/2557] avfilter/x86/vf_threshold : cosmetic indent --- libavfilter/x86/vf_threshold.asm | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libavfilter/x86/vf_threshold.asm b/libavfilter/x86/vf_threshold.asm index 117cc98fe2262..fb008c376a8f8 100644 --- a/libavfilter/x86/vf_threshold.asm +++ b/libavfilter/x86/vf_threshold.asm @@ -32,15 +32,15 @@ SECTION .text %macro THRESHOLD_8 0 cglobal threshold8, 10, 13, 5, in, threshold, min, max, out, ilinesize, tlinesize, flinesize, slinesize, olinesize, w, h, x - mov wd, dword wm - mov hd, dword hm + mov wd, dword wm + mov hd, dword hm VBROADCASTI128 m4, [pb_128] - add inq, wq - add thresholdq, wq - add minq, wq - add maxq, wq - add outq, wq - neg wq + add inq, wq + add thresholdq, wq + add minq, wq + add maxq, wq + add outq, wq + neg wq .nextrow: mov xq, wq From 5a93a85fd0ad62c6c9cdf69415959f116c015f0e Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Thu, 23 Nov 2017 22:47:22 +0100 Subject: [PATCH 1234/2557] avformat/mxfdec: fix last packet timestamps The current edit unit cannot be reliably determined for the last packet of a video stream, because we can't query the start offset of the next edit unit from the index. This caused missing timestamps for the last video packet. Therefore from now on, we allow setting the PTS even if we are not sure of the current edit unit if mxf_set_current_edit_unit returned a specific failure, and the assumed current edit unit is the last. Fixes last packet timestamp of: ffprobe -fflags nofillin -show_packets tests/data/lavf/lavf.mxf -select_streams v Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 4 ++-- tests/ref/seek/lavf-mxf_d10 | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 118e3e40b44cf..3b8d4239066f7 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -2976,7 +2976,7 @@ static int64_t mxf_set_current_edit_unit(MXFContext *mxf, int64_t current_offset /* find mxf->current_edit_unit so that the next edit unit starts ahead of current_offset */ while (mxf->current_edit_unit >= 0) { if (mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit + 1, NULL, &next_ofs, 0) < 0) - return -1; + return -2; if (next_ofs <= last_ofs) { /* large next_ofs didn't change or current_edit_unit wrapped @@ -3065,7 +3065,7 @@ static int mxf_set_pts(MXFContext *mxf, AVStream *st, AVPacket *pkt, int64_t nex AVCodecParameters *par = st->codecpar; MXFTrack *track = st->priv_data; - if (par->codec_type == AVMEDIA_TYPE_VIDEO && next_ofs >= 0) { + if (par->codec_type == AVMEDIA_TYPE_VIDEO && (next_ofs >= 0 || next_ofs == -2 && st->duration == mxf->current_edit_unit + 1)) { /* mxf->current_edit_unit good - see if we have an * index table to derive timestamps from */ MXFIndexTable *t = &mxf->index_tables[0]; diff --git a/tests/ref/seek/lavf-mxf_d10 b/tests/ref/seek/lavf-mxf_d10 index 17cca29c03be4..5a682f0927e2a 100644 --- a/tests/ref/seek/lavf-mxf_d10 +++ b/tests/ref/seek/lavf-mxf_d10 @@ -8,9 +8,9 @@ ret: 0 st: 0 flags:1 dts: 0.800000 pts: 0.800000 pos:4265984 size:150000 ret: 0 st: 0 flags:1 ts:-0.320000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 ret: 0 st: 1 flags:0 ts: 2.576667 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:5117952 size:150000 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 ret: 0 st: 1 flags:1 ts: 1.470833 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:5117952 size:150000 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 ret: 0 st:-1 flags:0 ts: 0.365002 ret: 0 st: 0 flags:1 dts: 0.360000 pts: 0.360000 pos:1923072 size:150000 ret: 0 st:-1 flags:1 ts:-0.740831 @@ -22,7 +22,7 @@ ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 ret: 0 st: 1 flags:0 ts:-0.058333 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 ret: 0 st: 1 flags:1 ts: 2.835833 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:5117952 size:150000 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 ret: 0 st:-1 flags:0 ts: 1.730004 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 ret: 0 st:-1 flags:1 ts: 0.624171 @@ -32,7 +32,7 @@ ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 ret: 0 st: 0 flags:1 ts: 2.400000 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 ret: 0 st: 1 flags:0 ts: 1.306667 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:5117952 size:150000 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 ret: 0 st: 1 flags:1 ts: 0.200833 ret: 0 st: 0 flags:1 dts: 0.200000 pts: 0.200000 pos:1071104 size:150000 ret: 0 st:-1 flags:0 ts:-0.904994 @@ -44,9 +44,9 @@ ret: 0 st: 0 flags:1 dts: 0.880000 pts: 0.880000 pos:4691968 size:150000 ret: 0 st: 0 flags:1 ts:-0.240000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 ret: 0 st: 1 flags:0 ts: 2.671667 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:5117952 size:150000 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 ret: 0 st: 1 flags:1 ts: 1.565833 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:5117952 size:150000 +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 ret: 0 st:-1 flags:0 ts: 0.460008 ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos:2562048 size:150000 ret: 0 st:-1 flags:1 ts:-0.645825 From 894f1c399b5ffae41b44289d23aeead542093006 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Mon, 4 Dec 2017 04:15:49 +0100 Subject: [PATCH 1235/2557] lavf/mov: Fix missing newline. --- libavformat/mov.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index f7fab98dd87ba..0b3e673c0651c 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -5559,7 +5559,8 @@ static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (ret < 0) return ret; if (!sc->spherical) - av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n"); } + av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n"); + } return 0; } From 31b351ea81d0a7c0d0ed1982dcc6327b7f43b987 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Mon, 4 Dec 2017 12:00:13 +0800 Subject: [PATCH 1236/2557] avformat/hlsenc: fix baseurl missing last char Reviewed-by: Steven Liu --- libavformat/hlsenc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index cdfbf45823920..dc8bf48791f91 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1921,14 +1921,11 @@ static int hls_write_header(AVFormatContext *s) } if (hls->baseurl) { - int baseurl_len; - baseurl_len = strlen(hls->baseurl); - vs->baseurl = av_malloc(baseurl_len); + vs->baseurl = av_strdup(hls->baseurl); if (!vs->baseurl) { ret = AVERROR(ENOMEM); goto fail; } - av_strlcpy(vs->baseurl, hls->baseurl, baseurl_len); } if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) { From 071f47649ce39897f18ce034dd428067f29d9b66 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 4 Dec 2017 12:03:37 +0800 Subject: [PATCH 1237/2557] avformat/hlsplaylist: add int type of API ff_hls_write_file_entry Signed-off-by: Steven Liu --- libavformat/dashenc.c | 6 +++++- libavformat/hlsenc.c | 12 ++++++++---- libavformat/hlsplaylist.c | 6 ++++-- libavformat/hlsplaylist.h | 2 +- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 1783675d00f01..22ef3103dced6 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -342,6 +342,7 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext AVIOContext *out_hls = NULL; AVDictionary *http_opts = NULL; int target_duration = 0; + int ret = 0; const char *proto = avio_find_protocol_name(c->dirname); int use_rename = proto && !strcmp(proto, "file"); @@ -368,11 +369,14 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext for (i = start_index; i < os->nb_segments; i++) { Segment *seg = os->segments[i]; - ff_hls_write_file_entry(out_hls, 0, c->single_file, + ret = ff_hls_write_file_entry(out_hls, 0, c->single_file, (double) seg->duration / timescale, 0, seg->range_length, seg->start_pos, NULL, c->single_file ? os->initfile : seg->file, NULL); + if (ret < 0) { + av_log(os->ctx, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n"); + } } if (final) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index dc8bf48791f91..aeeed5bcd22d2 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1236,11 +1236,13 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) hls->flags & HLS_SINGLE_FILE, en->size, en->pos); } - ff_hls_write_file_entry(out, en->discont, byterange_mode, + ret = ff_hls_write_file_entry(out, en->discont, byterange_mode, en->duration, hls->flags & HLS_ROUND_DURATIONS, en->size, en->pos, vs->baseurl, en->filename, prog_date_time_p); - + if (ret < 0) { + av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n"); + } } if (last && (hls->flags & HLS_OMIT_ENDLIST)==0) @@ -1251,11 +1253,13 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) goto fail; ff_hls_write_playlist_header(sub_out, hls->version, hls->allowcache, target_duration, sequence, PLAYLIST_TYPE_NONE); - for (en = vs->segments; en; en = en->next) { - ff_hls_write_file_entry(sub_out, 0, byterange_mode, + ret = ff_hls_write_file_entry(sub_out, 0, byterange_mode, en->duration, 0, en->size, en->pos, vs->baseurl, en->sub_filename, NULL); + if (ret < 0) { + av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n"); + } } if (last) diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c index 235e519a9ef0b..96a8afbe1d87d 100644 --- a/libavformat/hlsplaylist.c +++ b/libavformat/hlsplaylist.c @@ -82,14 +82,14 @@ void ff_hls_write_init_file(AVIOContext *out, char *filename, avio_printf(out, "\n"); } -void ff_hls_write_file_entry(AVIOContext *out, int insert_discont, +int ff_hls_write_file_entry(AVIOContext *out, int insert_discont, int byterange_mode, double duration, int round_duration, int64_t size, int64_t pos, //Used only if HLS_SINGLE_FILE flag is set char *baseurl, //Ignored if NULL char *filename, double *prog_date_time) { if (!out || !filename) - return; + return AVERROR(EINVAL); if (insert_discont) { avio_printf(out, "#EXT-X-DISCONTINUITY\n"); @@ -128,6 +128,8 @@ void ff_hls_write_file_entry(AVIOContext *out, int insert_discont, if (baseurl) avio_printf(out, "%s", baseurl); avio_printf(out, "%s\n", filename); + + return 0; } void ff_hls_write_end_list (AVIOContext *out) { diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index 4cbc8cacc9152..48d71b7c776d9 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -49,7 +49,7 @@ void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, uint32_t playlist_type); void ff_hls_write_init_file(AVIOContext *out, char *filename, int byterange_mode, int64_t size, int64_t pos); -void ff_hls_write_file_entry(AVIOContext *out, int insert_discont, +int ff_hls_write_file_entry(AVIOContext *out, int insert_discont, int byterange_mode, double duration, int round_duration, int64_t size, int64_t pos, //Used only if HLS_SINGLE_FILE flag is set From ad6946b8189e5e17796f1d5bf86d97ee619009b8 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 4 Dec 2017 12:05:04 +0800 Subject: [PATCH 1238/2557] avformat/hlsplaylist: add return value check of strftime fix CID: 1424884 Signed-off-by: Steven Liu --- libavformat/hlsplaylist.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c index 96a8afbe1d87d..3349eb7ee33ee 100644 --- a/libavformat/hlsplaylist.c +++ b/libavformat/hlsplaylist.c @@ -109,7 +109,10 @@ int ff_hls_write_file_entry(AVIOContext *out, int insert_discont, tt = (int64_t)*prog_date_time; milli = av_clip(lrint(1000*(*prog_date_time - tt)), 0, 999); tm = localtime_r(&tt, &tmpbuf); - strftime(buf0, sizeof(buf0), "%Y-%m-%dT%H:%M:%S", tm); + if (!strftime(buf0, sizeof(buf0), "%Y-%m-%dT%H:%M:%S", tm)) { + av_log(NULL, AV_LOG_DEBUG, "strftime error in ff_hls_write_file_entry\n"); + return AVERROR_UNKNOWN; + } if (!strftime(buf1, sizeof(buf1), "%z", tm) || buf1[1]<'0' ||buf1[1]>'2') { int tz_min, dst = tm->tm_isdst; tm = gmtime_r(&tt, &tmpbuf); From 1cfde7abd0008e58fcd10f8804812e72a1a5295a Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 4 Dec 2017 12:06:26 +0800 Subject: [PATCH 1239/2557] avformat/dashenc: add avpriv_io_move return value check fix cid: 1424883 Suggested-by: Moritz Barsnick Signed-off-by: Steven Liu --- libavformat/dashenc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 22ef3103dced6..5687530f2d953 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -384,7 +384,9 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext avio_close(out_hls); if (use_rename) - avpriv_io_move(temp_filename_hls, filename_hls); + if (avpriv_io_move(temp_filename_hls, filename_hls) < 0) { + av_log(os->ctx, AV_LOG_WARNING, "renaming file %s to %s failed\n\n", temp_filename_hls, filename_hls); + } } } From b73304f79eba9164162c7faf2c2d06e60728893c Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 4 Dec 2017 02:20:52 -0300 Subject: [PATCH 1240/2557] x86vf_threshold/: use the PBLENDVB macro Fixes building with yasm Tested-by: stevenliu Signed-off-by: James Almer --- libavfilter/x86/vf_threshold.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/x86/vf_threshold.asm b/libavfilter/x86/vf_threshold.asm index fb008c376a8f8..5e595fa13f943 100644 --- a/libavfilter/x86/vf_threshold.asm +++ b/libavfilter/x86/vf_threshold.asm @@ -52,7 +52,7 @@ cglobal threshold8, 10, 13, 5, in, threshold, min, max, out, ilinesize, tlinesiz pxor m0, m4 pxor m1, m4 pcmpgtb m0, m1 - pblendvb m3, m2, m0 + PBLENDVB m3, m2, m0 movu [outq + xq], m3 add xq, mmsize jl .loop From 9b45bcf713e0bc30fff7d1e6c2facb539c27ec28 Mon Sep 17 00:00:00 2001 From: Andrew D'Addesio Date: Sat, 2 Dec 2017 11:36:24 -0600 Subject: [PATCH 1241/2557] libavutil: Add saturating subtraction functions Add av_sat_sub32 and av_sat_dsub32 as the subtraction analogues to av_sat_add32/av_sat_dadd32. Also clarify the formulas for dadd32/dsub32. Signed-off-by: Andrew D'Addesio --- libavutil/arm/intmath.h | 16 ++++++++++++++++ libavutil/common.h | 32 +++++++++++++++++++++++++++++++- libavutil/version.h | 2 +- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/libavutil/arm/intmath.h b/libavutil/arm/intmath.h index 65e42c5733d89..5311a7d52b17b 100644 --- a/libavutil/arm/intmath.h +++ b/libavutil/arm/intmath.h @@ -94,6 +94,22 @@ static av_always_inline int av_sat_dadd32_arm(int a, int b) return r; } +#define av_sat_sub32 av_sat_sub32_arm +static av_always_inline int av_sat_sub32_arm(int a, int b) +{ + int r; + __asm__ ("qsub %0, %1, %2" : "=r"(r) : "r"(a), "r"(b)); + return r; +} + +#define av_sat_dsub32 av_sat_dsub32_arm +static av_always_inline int av_sat_dsub32_arm(int a, int b) +{ + int r; + __asm__ ("qdsub %0, %1, %2" : "=r"(r) : "r"(a), "r"(b)); + return r; +} + #endif /* HAVE_ARMV6_INLINE */ #if HAVE_ASM_MOD_Q diff --git a/libavutil/common.h b/libavutil/common.h index 8142b31fdbb20..5e0382827b083 100644 --- a/libavutil/common.h +++ b/libavutil/common.h @@ -260,13 +260,37 @@ static av_always_inline int av_sat_add32_c(int a, int b) * * @param a first value * @param b value doubled and added to a - * @return sum with signed saturation + * @return sum sat(a + sat(2*b)) with signed saturation */ static av_always_inline int av_sat_dadd32_c(int a, int b) { return av_sat_add32(a, av_sat_add32(b, b)); } +/** + * Subtract two signed 32-bit values with saturation. + * + * @param a one value + * @param b another value + * @return difference with signed saturation + */ +static av_always_inline int av_sat_sub32_c(int a, int b) +{ + return av_clipl_int32((int64_t)a - b); +} + +/** + * Subtract a doubled value from another value with saturation at both stages. + * + * @param a first value + * @param b value doubled and subtracted from a + * @return difference sat(a - sat(2*b)) with signed saturation + */ +static av_always_inline int av_sat_dsub32_c(int a, int b) +{ + return av_sat_sub32(a, av_sat_add32(b, b)); +} + /** * Clip a float value into the amin-amax range. * @param a value to clip @@ -513,6 +537,12 @@ static av_always_inline av_const int av_parity_c(uint32_t v) #ifndef av_sat_dadd32 # define av_sat_dadd32 av_sat_dadd32_c #endif +#ifndef av_sat_sub32 +# define av_sat_sub32 av_sat_sub32_c +#endif +#ifndef av_sat_dsub32 +# define av_sat_dsub32 av_sat_dsub32_c +#endif #ifndef av_clipf # define av_clipf av_clipf_c #endif diff --git a/libavutil/version.h b/libavutil/version.h index 285d2f1cf98b4..498b5d8414fa5 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 4 +#define LIBAVUTIL_VERSION_MINOR 5 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 511e6f17f493719058229630c7db4d8d7c05aeac Mon Sep 17 00:00:00 2001 From: Andrew D'Addesio Date: Sat, 2 Dec 2017 11:36:25 -0600 Subject: [PATCH 1242/2557] opus_silk: Fix arithmetic overflow (per RFC8251) As per Sec.6 of RFC8251: Integer Wrap-Around in Inverse Gain Computation 32-bit integer overflow in Levinson recursion. Affects silk_is_lpc_stable(). Signed-off-by: Andrew D'Addesio --- libavcodec/opus_silk.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavcodec/opus_silk.c b/libavcodec/opus_silk.c index 3c9c849c21de9..344333cc180f0 100644 --- a/libavcodec/opus_silk.c +++ b/libavcodec/opus_silk.c @@ -185,8 +185,15 @@ static inline int silk_is_lpc_stable(const int16_t lpc[16], int order) row = lpc32[k & 1]; for (j = 0; j < k; j++) { - int x = prevrow[j] - ROUND_MULL(prevrow[k - j - 1], rc, 31); - row[j] = ROUND_MULL(x, gain, fbits); + int x = av_sat_sub32(prevrow[j], ROUND_MULL(prevrow[k - j - 1], rc, 31)); + int64_t tmp = ROUND_MULL(x, gain, fbits); + + /* per RFC 8251 section 6, if this calculation overflows, the filter + is considered unstable. */ + if (tmp < INT32_MIN || tmp > INT32_MAX) + return 0; + + row[j] = (int32_t)tmp; } } } From de052ea454e06f2c1aab4e06cca0012cf80f2630 Mon Sep 17 00:00:00 2001 From: Andrew D'Addesio Date: Sat, 2 Dec 2017 11:36:25 -0600 Subject: [PATCH 1243/2557] opus_celt: Fix arithmetic overflow (per RFC8251) As per Sec.8 of RFC8251: Cap on Band Energy NaN due to large log-energy value. Affects celt_denormalize(). Signed-off-by: Andrew D'Addesio --- libavcodec/opus_celt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/opus_celt.c b/libavcodec/opus_celt.c index 84d484753b361..ff56041ea69ce 100644 --- a/libavcodec/opus_celt.c +++ b/libavcodec/opus_celt.c @@ -481,7 +481,8 @@ static void celt_denormalize(CeltFrame *f, CeltBlock *block, float *data) for (i = f->start_band; i < f->end_band; i++) { float *dst = data + (ff_celt_freq_bands[i] << f->size); - float norm = exp2f(block->energy[i] + ff_celt_mean_energy[i]); + float log_norm = block->energy[i] + ff_celt_mean_energy[i]; + float norm = exp2f(FFMIN(log_norm, 32.0f)); for (j = 0; j < ff_celt_freq_range[i] << f->size; j++) dst[j] *= norm; From fe05f93013c4a3616926fa9370be2d9c93a94659 Mon Sep 17 00:00:00 2001 From: Andrew D'Addesio Date: Sat, 2 Dec 2017 11:46:58 -0600 Subject: [PATCH 1244/2557] opus: Add Special Hybrid Folding (per RFC8251) This decoder-side change, introduced in RFC 8251 (section 9), slightly improves the decoded quality of 16kbps speech in Hybrid Mode. Differences can be seen/heard in testvector05.bit, testvector06.bit, and testvector12.bit in the RFC 6716/8251 testvectors found here: https://people.xiph.org/~greg/opus_testvectors/ Signed-off-by: Andrew D'Addesio --- libavcodec/opus_celt.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libavcodec/opus_celt.c b/libavcodec/opus_celt.c index ff56041ea69ce..2bbb96bded5c4 100644 --- a/libavcodec/opus_celt.c +++ b/libavcodec/opus_celt.c @@ -712,10 +712,22 @@ static void celt_decode_bands(CeltFrame *f, OpusRangeCoder *rc) b = av_clip_uintp2(FFMIN(f->remaining2 + 1, f->pulses[i] + curr_balance), 14); } - if (ff_celt_freq_bands[i] - ff_celt_freq_range[i] >= ff_celt_freq_bands[f->start_band] && - (update_lowband || lowband_offset == 0)) + if ((ff_celt_freq_bands[i] - ff_celt_freq_range[i] >= ff_celt_freq_bands[f->start_band] || + i == f->start_band + 1) && (update_lowband || lowband_offset == 0)) lowband_offset = i; + if (i == f->start_band + 1) { + /* Special Hybrid Folding (RFC 8251 section 9). Copy the first band into + the second to ensure the second band never has to use the LCG. */ + int offset = 8 * ff_celt_freq_bands[i]; + int count = 8 * (ff_celt_freq_range[i] - ff_celt_freq_range[i-1]); + + memcpy(&norm[offset], &norm[offset - count], count * sizeof(float)); + + if (f->channels == 2) + memcpy(&norm2[offset], &norm2[offset - count], count * sizeof(float)); + } + /* Get a conservative estimate of the collapse_mask's for the bands we're going to be folding from. */ if (lowband_offset != 0 && (f->spread != CELT_SPREAD_AGGRESSIVE || @@ -728,7 +740,7 @@ static void celt_decode_bands(CeltFrame *f, OpusRangeCoder *rc) foldstart = lowband_offset; while (ff_celt_freq_bands[--foldstart] > effective_lowband); foldend = lowband_offset - 1; - while (ff_celt_freq_bands[++foldend] < effective_lowband + ff_celt_freq_range[i]); + while (++foldend < i && ff_celt_freq_bands[foldend] < effective_lowband + ff_celt_freq_range[i]); cm[0] = cm[1] = 0; for (j = foldstart; j < foldend; j++) { From 1b8649c2ce95da0a12d90f6acf7171b4fc6580db Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Mon, 4 Dec 2017 06:36:42 +0000 Subject: [PATCH 1245/2557] opus: add an option to toggle intensity stereo phase inversion Due to a somewhat high volume of complains, phase inversion has been made optional with RFC8251. This allows for better bass frequency response when partially downmixing to play on systems with an LFE speaker. Signed-off-by: Rostislav Pehlivanov --- libavcodec/opus.h | 2 ++ libavcodec/opus_celt.c | 4 +++- libavcodec/opus_celt.h | 4 +++- libavcodec/opus_pvq.c | 1 + libavcodec/opusdec.c | 17 ++++++++++++++++- 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/libavcodec/opus.h b/libavcodec/opus.h index c3cbaec35d60b..90b87ba5c4d2f 100644 --- a/libavcodec/opus.h +++ b/libavcodec/opus.h @@ -150,7 +150,9 @@ typedef struct ChannelMap { } ChannelMap; typedef struct OpusContext { + AVClass *av_class; OpusStreamContext *streams; + int apply_phase_inv; /* current output buffers for each streams */ float **out; diff --git a/libavcodec/opus_celt.c b/libavcodec/opus_celt.c index 2bbb96bded5c4..72b299a19c00b 100644 --- a/libavcodec/opus_celt.c +++ b/libavcodec/opus_celt.c @@ -997,7 +997,8 @@ void ff_celt_free(CeltFrame **f) av_freep(f); } -int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels) +int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels, + int apply_phase_inv) { CeltFrame *frm; int i, ret; @@ -1014,6 +1015,7 @@ int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels) frm->avctx = avctx; frm->output_channels = output_channels; + frm->apply_phase_inv = apply_phase_inv; for (i = 0; i < FF_ARRAY_ELEMS(frm->imdct); i++) if ((ret = ff_mdct15_init(&frm->imdct[i], 1, i + 3, -1.0f/32768)) < 0) diff --git a/libavcodec/opus_celt.h b/libavcodec/opus_celt.h index 45d50ab27b9f2..9289a1867af7e 100644 --- a/libavcodec/opus_celt.h +++ b/libavcodec/opus_celt.h @@ -98,6 +98,7 @@ struct CeltFrame { CeltPVQ *pvq; int channels; int output_channels; + int apply_phase_inv; enum CeltBlockSize size; int start_band; @@ -156,7 +157,8 @@ static av_always_inline void celt_renormalize_vector(float *X, int N, float gain X[i] *= g; } -int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels); +int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels, + int apply_phase_inv); void ff_celt_free(CeltFrame **f); diff --git a/libavcodec/opus_pvq.c b/libavcodec/opus_pvq.c index 2f7aa74da49ea..449215f814b01 100644 --- a/libavcodec/opus_pvq.c +++ b/libavcodec/opus_pvq.c @@ -643,6 +643,7 @@ static av_always_inline uint32_t quant_band_template(CeltPVQ *pvq, CeltFrame *f, } } else { inv = (b > 2 << 3 && f->remaining2 > 2 << 3) ? ff_opus_rc_dec_log(rc, 2) : 0; + inv = f->apply_phase_inv ? inv : 0; } itheta = 0; } diff --git a/libavcodec/opusdec.c b/libavcodec/opusdec.c index 5a7ba9dbb4354..03086dea99e2c 100644 --- a/libavcodec/opusdec.c +++ b/libavcodec/opusdec.c @@ -687,7 +687,7 @@ static av_cold int opus_decode_init(AVCodecContext *avctx) if (ret < 0) goto fail; - ret = ff_celt_init(avctx, &s->celt, s->output_channels); + ret = ff_celt_init(avctx, &s->celt, s->output_channels, c->apply_phase_inv); if (ret < 0) goto fail; @@ -712,9 +712,24 @@ static av_cold int opus_decode_init(AVCodecContext *avctx) return ret; } +#define OFFSET(x) offsetof(OpusContext, x) +#define AD AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption opus_options[] = { + { "apply_phase_inv", "Apply intensity stereo phase inversion", OFFSET(apply_phase_inv), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AD }, + { NULL }, +}; + +static const AVClass opus_class = { + .class_name = "Opus Decoder", + .item_name = av_default_item_name, + .option = opus_options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_opus_decoder = { .name = "opus", .long_name = NULL_IF_CONFIG_SMALL("Opus"), + .priv_class = &opus_class, .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_OPUS, .priv_data_size = sizeof(OpusContext), From d1d6f965d81bab2076d67cdc1dabd5a1f5bb2d30 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Mon, 4 Dec 2017 07:26:33 +0000 Subject: [PATCH 1246/2557] fate-opus: update to match the changes from RFC8251 Also change note to say that we compare against the officially decoded samples rather than our own, this was changed long ago. Signed-off-by: Rostislav Pehlivanov --- tests/fate/opus.mak | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/fate/opus.mak b/tests/fate/opus.mak index b13d86c138ecd..46e90168d6f8d 100644 --- a/tests/fate/opus.mak +++ b/tests/fate/opus.mak @@ -1,10 +1,6 @@ # The samples were produced by simply rewrapping the official test vectors from -# their custom format into Matroska. -# The reference files were created with our decoder and tested against the -# libopus output with the official opus_compare tool. We cannot use libopus -# output as reference directly, because the use of different resamplers would -# require too high fuzz values, which can hide bugs. -# Before adding new tests here, always make sure they pass opus_compare. +# their custom format into Matroska. The reference decoded outputs are from the +# newest testvectors file from RFC8251 OPUS_CELT_SAMPLES = $(addprefix testvector, 01 07 11) tron.6ch.tinypkts OPUS_HYBRID_SAMPLES = $(addprefix testvector, 05 06) @@ -28,11 +24,12 @@ FATE_OPUS := $(sort $(FATE_OPUS)) $(FATE_OPUS): CMP = stddev $(FATE_OPUS): CMP_UNIT = s16 $(FATE_OPUS): FUZZ = 3 +fate-opus-testvector01: CMP_TARGET = 1 fate-opus-testvector02: CMP_TARGET = 191 fate-opus-testvector03: CMP_TARGET = 139 fate-opus-testvector04: CMP_TARGET = 119 -fate-opus-testvector05: CMP_TARGET = 108 -fate-opus-testvector06: CMP_TARGET = 106 +fate-opus-testvector05: CMP_TARGET = 109 +fate-opus-testvector06: CMP_TARGET = 109 fate-opus-testvector08: CMP_TARGET = 6 fate-opus-testvector10: CMP_TARGET = 38 fate-opus-testvector12: CMP_TARGET = 160 From 86fda8be3f3892c48474a319e0ef7509dc137e3e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 1 Dec 2017 20:56:45 +0100 Subject: [PATCH 1247/2557] avfilter: add hflip x86 SIMD Signed-off-by: Paul B Mahol --- libavfilter/hflip.h | 38 +++++++++ libavfilter/vf_hflip.c | 133 +++++++++++++++++++++----------- libavfilter/x86/Makefile | 2 + libavfilter/x86/vf_hflip.asm | 108 ++++++++++++++++++++++++++ libavfilter/x86/vf_hflip_init.c | 41 ++++++++++ 5 files changed, 275 insertions(+), 47 deletions(-) create mode 100644 libavfilter/hflip.h create mode 100644 libavfilter/x86/vf_hflip.asm create mode 100644 libavfilter/x86/vf_hflip_init.c diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h new file mode 100644 index 0000000000000..cbe1fb3d8c7a7 --- /dev/null +++ b/libavfilter/hflip.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2007 Benoit Fouet + * Copyright (c) 2010 Stefano Sabatini + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_HFLIP_H +#define AVFILTER_HFLIP_H + +#include "avfilter.h" + +typedef struct FlipContext { + const AVClass *class; + int max_step[4]; ///< max pixel step for each plane, expressed as a number of bytes + int planewidth[4]; ///< width of each plane + int planeheight[4]; ///< height of each plane + + void (*flip_line[4])(const uint8_t *src, uint8_t *dst, int w); +} FlipContext; + +void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes); + +#endif /* AVFILTER_HFLIP_H */ diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c index cf20c193f7c10..957ddd9900321 100644 --- a/libavfilter/vf_hflip.c +++ b/libavfilter/vf_hflip.c @@ -29,6 +29,7 @@ #include "libavutil/opt.h" #include "avfilter.h" #include "formats.h" +#include "hflip.h" #include "internal.h" #include "video.h" #include "libavutil/pixdesc.h" @@ -36,13 +37,6 @@ #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" -typedef struct FlipContext { - const AVClass *class; - int max_step[4]; ///< max pixel step for each plane, expressed as a number of bytes - int planewidth[4]; ///< width of each plane - int planeheight[4]; ///< height of each plane -} FlipContext; - static const AVOption hflip_options[] = { { NULL } }; @@ -67,12 +61,77 @@ static int query_formats(AVFilterContext *ctx) return ff_set_common_formats(ctx, pix_fmts); } +static void hflip_byte_c(const uint8_t *src, uint8_t *dst, int w) +{ + int j; + + for (j = 0; j < w; j++) + dst[j] = src[-j]; +} + +static void hflip_short_c(const uint8_t *ssrc, uint8_t *ddst, int w) +{ + const uint16_t *src = (const uint16_t *)ssrc; + uint16_t *dst = (uint16_t *)ddst; + int j; + + for (j = 0; j < w; j++) + dst[j] = src[-j]; +} + +static void hflip_dword_c(const uint8_t *ssrc, uint8_t *ddst, int w) +{ + const uint32_t *src = (const uint32_t *)ssrc; + uint32_t *dst = (uint32_t *)ddst; + int j; + + for (j = 0; j < w; j++) + dst[j] = src[-j]; +} + +static void hflip_b24_c(const uint8_t *src, uint8_t *dst, int w) +{ + const uint8_t *in = src; + uint8_t *out = dst; + int j; + + for (j = 0; j < w; j++, out += 3, in -= 3) { + int32_t v = AV_RB24(in); + + AV_WB24(out, v); + } +} + +static void hflip_b48_c(const uint8_t *src, uint8_t *dst, int w) +{ + const uint8_t *in = src; + uint8_t *out = dst; + int j; + + for (j = 0; j < w; j++, out += 6, in -= 6) { + int64_t v = AV_RB48(in); + + AV_WB48(out, v); + } +} + +static void hflip_qword_c(const uint8_t *ssrc, uint8_t *ddst, int w) +{ + const uint64_t *src = (const uint64_t *)ssrc; + uint64_t *dst = (uint64_t *)ddst; + int j; + + for (j = 0; j < w; j++) + dst[j] = src[-j]; +} + static int config_props(AVFilterLink *inlink) { FlipContext *s = inlink->dst->priv; const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format); const int hsub = pix_desc->log2_chroma_w; const int vsub = pix_desc->log2_chroma_h; + int nb_planes, i; av_image_fill_max_pixsteps(s->max_step, NULL, pix_desc); s->planewidth[0] = s->planewidth[3] = inlink->w; @@ -80,6 +139,24 @@ static int config_props(AVFilterLink *inlink) s->planeheight[0] = s->planeheight[3] = inlink->h; s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, vsub); + nb_planes = av_pix_fmt_count_planes(inlink->format); + + for (i = 0; i < nb_planes; i++) { + switch (s->max_step[i]) { + case 1: s->flip_line[i] = hflip_byte_c; break; + case 2: s->flip_line[i] = hflip_short_c; break; + case 3: s->flip_line[i] = hflip_b24_c; break; + case 4: s->flip_line[i] = hflip_dword_c; break; + case 6: s->flip_line[i] = hflip_b48_c; break; + case 8: s->flip_line[i] = hflip_qword_c; break; + default: + return AVERROR_BUG; + } + } + + if (ARCH_X86) + ff_hflip_init_x86(s, s->max_step, nb_planes); + return 0; } @@ -94,7 +171,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) AVFrame *in = td->in; AVFrame *out = td->out; uint8_t *inrow, *outrow; - int i, j, plane, step; + int i, plane, step; for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) { const int width = s->planewidth[plane]; @@ -107,45 +184,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) outrow = out->data[plane] + start * out->linesize[plane]; inrow = in ->data[plane] + start * in->linesize[plane] + (width - 1) * step; for (i = start; i < end; i++) { - switch (step) { - case 1: - for (j = 0; j < width; j++) - outrow[j] = inrow[-j]; - break; - - case 2: - { - uint16_t *outrow16 = (uint16_t *)outrow; - uint16_t * inrow16 = (uint16_t *) inrow; - for (j = 0; j < width; j++) - outrow16[j] = inrow16[-j]; - } - break; - - case 3: - { - uint8_t *in = inrow; - uint8_t *out = outrow; - for (j = 0; j < width; j++, out += 3, in -= 3) { - int32_t v = AV_RB24(in); - AV_WB24(out, v); - } - } - break; - - case 4: - { - uint32_t *outrow32 = (uint32_t *)outrow; - uint32_t * inrow32 = (uint32_t *) inrow; - for (j = 0; j < width; j++) - outrow32[j] = inrow32[-j]; - } - break; - - default: - for (j = 0; j < width; j++) - memcpy(outrow + j*step, inrow - j*step, step); - } + s->flip_line[plane](inrow, outrow, width); inrow += in ->linesize[plane]; outrow += out->linesize[plane]; diff --git a/libavfilter/x86/Makefile b/libavfilter/x86/Makefile index c10f4d553869b..2fc5c62644dd6 100644 --- a/libavfilter/x86/Makefile +++ b/libavfilter/x86/Makefile @@ -5,6 +5,7 @@ OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp_init.o OBJS-$(CONFIG_EQ_FILTER) += x86/vf_eq.o OBJS-$(CONFIG_FSPP_FILTER) += x86/vf_fspp_init.o OBJS-$(CONFIG_GRADFUN_FILTER) += x86/vf_gradfun_init.o +OBJS-$(CONFIG_HFLIP_FILTER) += x86/vf_hflip_init.o OBJS-$(CONFIG_HQDN3D_FILTER) += x86/vf_hqdn3d_init.o OBJS-$(CONFIG_IDET_FILTER) += x86/vf_idet_init.o OBJS-$(CONFIG_INTERLACE_FILTER) += x86/vf_interlace_init.o @@ -32,6 +33,7 @@ X86ASM-OBJS-$(CONFIG_BWDIF_FILTER) += x86/vf_bwdif.o X86ASM-OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp.o X86ASM-OBJS-$(CONFIG_FSPP_FILTER) += x86/vf_fspp.o X86ASM-OBJS-$(CONFIG_GRADFUN_FILTER) += x86/vf_gradfun.o +X86ASM-OBJS-$(CONFIG_HFLIP_FILTER) += x86/vf_hflip.o X86ASM-OBJS-$(CONFIG_HQDN3D_FILTER) += x86/vf_hqdn3d.o X86ASM-OBJS-$(CONFIG_IDET_FILTER) += x86/vf_idet.o X86ASM-OBJS-$(CONFIG_INTERLACE_FILTER) += x86/vf_interlace.o diff --git a/libavfilter/x86/vf_hflip.asm b/libavfilter/x86/vf_hflip.asm new file mode 100644 index 0000000000000..867dcaeed5b66 --- /dev/null +++ b/libavfilter/x86/vf_hflip.asm @@ -0,0 +1,108 @@ +;***************************************************************************** +;* x86-optimized functions for hflip filter +;* +;* Copyright (C) 2017 Paul B Mahol +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;***************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +pb_flip_byte: db 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 +pb_flip_short: db 14,15,12,13,10,11,8,9,6,7,4,5,2,3,0,1 + +SECTION .text + +INIT_XMM ssse3 +cglobal hflip_byte, 3, 6, 3, src, dst, w, x, v, r + mova m0, [pb_flip_byte] + mov xq, 0 + mov wd, dword wm + mov rq, wq + and rq, 2 * mmsize - 1 + cmp wq, 2 * mmsize + jl .loop1 + sub wq, rq + + .loop0: + neg xq + movu m1, [srcq + xq - mmsize + 1] + movu m2, [srcq + xq - 2 * mmsize + 1] + pshufb m1, m0 + pshufb m2, m0 + neg xq + movu [dstq + xq ], m1 + movu [dstq + xq + mmsize], m2 + add xq, mmsize * 2 + cmp xq, wq + jl .loop0 + + cmp rq, 0 + je .end + add wq, rq + + .loop1: + neg xq + mov vb, [srcq + xq] + neg xq + mov [dstq + xq], vb + add xq, 1 + cmp xq, wq + jl .loop1 + .end: +RET + +cglobal hflip_short, 3, 6, 3, src, dst, w, x, v, r + mova m0, [pb_flip_short] + mov xq, 0 + mov wd, dword wm + add wq, wq + mov rq, wq + and rq, 2 * mmsize - 1 + cmp wq, 2 * mmsize + jl .loop1 + sub wq, rq + + .loop0: + neg xq + movu m1, [srcq + xq - mmsize + 2] + movu m2, [srcq + xq - 2 * mmsize + 2] + pshufb m1, m0 + pshufb m2, m0 + neg xq + movu [dstq + xq ], m1 + movu [dstq + xq + mmsize], m2 + add xq, mmsize * 2 + cmp xq, wq + jl .loop0 + + cmp rq, 0 + je .end + add wq, rq + + .loop1: + neg xq + mov vw, [srcq + xq] + neg xq + mov [dstq + xq], vw + add xq, 2 + cmp xq, wq + jl .loop1 + .end: +RET diff --git a/libavfilter/x86/vf_hflip_init.c b/libavfilter/x86/vf_hflip_init.c new file mode 100644 index 0000000000000..2b5c9d3bf3b13 --- /dev/null +++ b/libavfilter/x86/vf_hflip_init.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavfilter/hflip.h" + +void ff_hflip_byte_ssse3(const uint8_t *src, uint8_t *dst, int w); +void ff_hflip_short_ssse3(const uint8_t *src, uint8_t *dst, int w); + +av_cold void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes) +{ + int cpu_flags = av_get_cpu_flags(); + int i; + + for (i = 0; i < nb_planes; i++) { + if (EXTERNAL_SSSE3(cpu_flags) && step[i] == 1) { + s->flip_line[i] = ff_hflip_byte_ssse3; + } else if (EXTERNAL_SSSE3(cpu_flags) && step[i] == 2) { + s->flip_line[i] = ff_hflip_short_ssse3; + } + } +} From ce87e630fa009d0bf78cd7a7599e6efc221e6543 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Mon, 4 Dec 2017 08:55:45 +0000 Subject: [PATCH 1248/2557] opus_celt: deduplicate band quantization/dequantization function No point in having the same code twice to do exactly the same thing. Signed-off-by: Rostislav Pehlivanov --- libavcodec/opus.c | 111 +++++++++++++++++++++++++++++++++++++- libavcodec/opus.h | 3 ++ libavcodec/opus_celt.c | 114 +++------------------------------------ libavcodec/opus_pvq.c | 58 ++++++++++---------- libavcodec/opus_pvq.h | 6 +-- libavcodec/opusenc.c | 110 ++++--------------------------------- libavcodec/opusenc.h | 2 +- libavcodec/opusenc_psy.c | 2 +- 8 files changed, 162 insertions(+), 244 deletions(-) diff --git a/libavcodec/opus.c b/libavcodec/opus.c index 5847e88e11d3e..b791d749b4311 100644 --- a/libavcodec/opus.c +++ b/libavcodec/opus.c @@ -29,7 +29,8 @@ #include "libavutil/error.h" #include "libavutil/ffmath.h" -#include "opus.h" +#include "opus_celt.h" +#include "opustab.h" #include "vorbis.h" static const uint16_t opus_frame_duration[32] = { @@ -438,3 +439,111 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, return 0; } + +void ff_celt_quant_bands(CeltFrame *f, OpusRangeCoder *rc) +{ + float lowband_scratch[8 * 22]; + float norm1[2 * 8 * 100]; + float *norm2 = norm1 + 8 * 100; + + int totalbits = (f->framebits << 3) - f->anticollapse_needed; + + int update_lowband = 1; + int lowband_offset = 0; + + int i, j; + + for (i = f->start_band; i < f->end_band; i++) { + uint32_t cm[2] = { (1 << f->blocks) - 1, (1 << f->blocks) - 1 }; + int band_offset = ff_celt_freq_bands[i] << f->size; + int band_size = ff_celt_freq_range[i] << f->size; + float *X = f->block[0].coeffs + band_offset; + float *Y = (f->channels == 2) ? f->block[1].coeffs + band_offset : NULL; + float *norm_loc1, *norm_loc2; + + int consumed = opus_rc_tell_frac(rc); + int effective_lowband = -1; + int b = 0; + + /* Compute how many bits we want to allocate to this band */ + if (i != f->start_band) + f->remaining -= consumed; + f->remaining2 = totalbits - consumed - 1; + if (i <= f->coded_bands - 1) { + int curr_balance = f->remaining / FFMIN(3, f->coded_bands-i); + b = av_clip_uintp2(FFMIN(f->remaining2 + 1, f->pulses[i] + curr_balance), 14); + } + + if ((ff_celt_freq_bands[i] - ff_celt_freq_range[i] >= ff_celt_freq_bands[f->start_band] || + i == f->start_band + 1) && (update_lowband || lowband_offset == 0)) + lowband_offset = i; + + if (i == f->start_band + 1) { + /* Special Hybrid Folding (RFC 8251 section 9). Copy the first band into + the second to ensure the second band never has to use the LCG. */ + int offset = 8 * ff_celt_freq_bands[i]; + int count = 8 * (ff_celt_freq_range[i] - ff_celt_freq_range[i-1]); + + memcpy(&norm1[offset], &norm1[offset - count], count * sizeof(float)); + + if (f->channels == 2) + memcpy(&norm2[offset], &norm2[offset - count], count * sizeof(float)); + } + + /* Get a conservative estimate of the collapse_mask's for the bands we're + going to be folding from. */ + if (lowband_offset != 0 && (f->spread != CELT_SPREAD_AGGRESSIVE || + f->blocks > 1 || f->tf_change[i] < 0)) { + int foldstart, foldend; + + /* This ensures we never repeat spectral content within one band */ + effective_lowband = FFMAX(ff_celt_freq_bands[f->start_band], + ff_celt_freq_bands[lowband_offset] - ff_celt_freq_range[i]); + foldstart = lowband_offset; + while (ff_celt_freq_bands[--foldstart] > effective_lowband); + foldend = lowband_offset - 1; + while (++foldend < i && ff_celt_freq_bands[foldend] < effective_lowband + ff_celt_freq_range[i]); + + cm[0] = cm[1] = 0; + for (j = foldstart; j < foldend; j++) { + cm[0] |= f->block[0].collapse_masks[j]; + cm[1] |= f->block[f->channels - 1].collapse_masks[j]; + } + } + + if (f->dual_stereo && i == f->intensity_stereo) { + /* Switch off dual stereo to do intensity */ + f->dual_stereo = 0; + for (j = ff_celt_freq_bands[f->start_band] << f->size; j < band_offset; j++) + norm1[j] = (norm1[j] + norm2[j]) / 2; + } + + norm_loc1 = effective_lowband != -1 ? norm1 + (effective_lowband << f->size) : NULL; + norm_loc2 = effective_lowband != -1 ? norm2 + (effective_lowband << f->size) : NULL; + + if (f->dual_stereo) { + cm[0] = f->pvq->quant_band(f->pvq, f, rc, i, X, NULL, band_size, b >> 1, + f->blocks, norm_loc1, f->size, + norm1 + band_offset, 0, 1.0f, + lowband_scratch, cm[0]); + + cm[1] = f->pvq->quant_band(f->pvq, f, rc, i, Y, NULL, band_size, b >> 1, + f->blocks, norm_loc2, f->size, + norm2 + band_offset, 0, 1.0f, + lowband_scratch, cm[1]); + } else { + cm[0] = f->pvq->quant_band(f->pvq, f, rc, i, X, Y, band_size, b >> 0, + f->blocks, norm_loc1, f->size, + norm1 + band_offset, 0, 1.0f, + lowband_scratch, cm[0] | cm[1]); + cm[1] = cm[0]; + } + + f->block[0].collapse_masks[i] = (uint8_t)cm[0]; + f->block[f->channels - 1].collapse_masks[i] = (uint8_t)cm[1]; + f->remaining += f->pulses[i] + consumed; + + /* Update the folding position only as long as we have 1 bit/sample depth */ + update_lowband = (b > band_size << 3); + } +} diff --git a/libavcodec/opus.h b/libavcodec/opus.h index 90b87ba5c4d2f..a10db7f0e8345 100644 --- a/libavcodec/opus.h +++ b/libavcodec/opus.h @@ -191,4 +191,7 @@ int ff_silk_decode_superframe(SilkContext *s, OpusRangeCoder *rc, enum OpusBandwidth bandwidth, int coded_channels, int duration_ms); +/* Encode or decode CELT bands */ +void ff_celt_quant_bands(CeltFrame *f, OpusRangeCoder *rc); + #endif /* AVCODEC_OPUS_H */ diff --git a/libavcodec/opus_celt.c b/libavcodec/opus_celt.c index 72b299a19c00b..ff74e2f067955 100644 --- a/libavcodec/opus_celt.c +++ b/libavcodec/opus_celt.c @@ -676,110 +676,6 @@ static void process_anticollapse(CeltFrame *f, CeltBlock *block, float *X) } } -static void celt_decode_bands(CeltFrame *f, OpusRangeCoder *rc) -{ - float lowband_scratch[8 * 22]; - float norm[2 * 8 * 100]; - - int totalbits = (f->framebits << 3) - f->anticollapse_needed; - - int update_lowband = 1; - int lowband_offset = 0; - - int i, j; - - memset(f->block[0].coeffs, 0, sizeof(f->block[0].coeffs)); - memset(f->block[1].coeffs, 0, sizeof(f->block[0].coeffs)); - - for (i = f->start_band; i < f->end_band; i++) { - uint32_t cm[2] = { (1 << f->blocks) - 1, (1 << f->blocks) - 1 }; - int band_offset = ff_celt_freq_bands[i] << f->size; - int band_size = ff_celt_freq_range[i] << f->size; - float *X = f->block[0].coeffs + band_offset; - float *Y = (f->channels == 2) ? f->block[1].coeffs + band_offset : NULL; - - int consumed = opus_rc_tell_frac(rc); - float *norm2 = norm + 8 * 100; - int effective_lowband = -1; - int b = 0; - - /* Compute how many bits we want to allocate to this band */ - if (i != f->start_band) - f->remaining -= consumed; - f->remaining2 = totalbits - consumed - 1; - if (i <= f->coded_bands - 1) { - int curr_balance = f->remaining / FFMIN(3, f->coded_bands-i); - b = av_clip_uintp2(FFMIN(f->remaining2 + 1, f->pulses[i] + curr_balance), 14); - } - - if ((ff_celt_freq_bands[i] - ff_celt_freq_range[i] >= ff_celt_freq_bands[f->start_band] || - i == f->start_band + 1) && (update_lowband || lowband_offset == 0)) - lowband_offset = i; - - if (i == f->start_band + 1) { - /* Special Hybrid Folding (RFC 8251 section 9). Copy the first band into - the second to ensure the second band never has to use the LCG. */ - int offset = 8 * ff_celt_freq_bands[i]; - int count = 8 * (ff_celt_freq_range[i] - ff_celt_freq_range[i-1]); - - memcpy(&norm[offset], &norm[offset - count], count * sizeof(float)); - - if (f->channels == 2) - memcpy(&norm2[offset], &norm2[offset - count], count * sizeof(float)); - } - - /* Get a conservative estimate of the collapse_mask's for the bands we're - going to be folding from. */ - if (lowband_offset != 0 && (f->spread != CELT_SPREAD_AGGRESSIVE || - f->blocks > 1 || f->tf_change[i] < 0)) { - int foldstart, foldend; - - /* This ensures we never repeat spectral content within one band */ - effective_lowband = FFMAX(ff_celt_freq_bands[f->start_band], - ff_celt_freq_bands[lowband_offset] - ff_celt_freq_range[i]); - foldstart = lowband_offset; - while (ff_celt_freq_bands[--foldstart] > effective_lowband); - foldend = lowband_offset - 1; - while (++foldend < i && ff_celt_freq_bands[foldend] < effective_lowband + ff_celt_freq_range[i]); - - cm[0] = cm[1] = 0; - for (j = foldstart; j < foldend; j++) { - cm[0] |= f->block[0].collapse_masks[j]; - cm[1] |= f->block[f->channels - 1].collapse_masks[j]; - } - } - - if (f->dual_stereo && i == f->intensity_stereo) { - /* Switch off dual stereo to do intensity */ - f->dual_stereo = 0; - for (j = ff_celt_freq_bands[f->start_band] << f->size; j < band_offset; j++) - norm[j] = (norm[j] + norm2[j]) / 2; - } - - if (f->dual_stereo) { - cm[0] = f->pvq->decode_band(f->pvq, f, rc, i, X, NULL, band_size, b / 2, f->blocks, - effective_lowband != -1 ? norm + (effective_lowband << f->size) : NULL, f->size, - norm + band_offset, 0, 1.0f, lowband_scratch, cm[0]); - - cm[1] = f->pvq->decode_band(f->pvq, f, rc, i, Y, NULL, band_size, b/2, f->blocks, - effective_lowband != -1 ? norm2 + (effective_lowband << f->size) : NULL, f->size, - norm2 + band_offset, 0, 1.0f, lowband_scratch, cm[1]); - } else { - cm[0] = f->pvq->decode_band(f->pvq, f, rc, i, X, Y, band_size, b, f->blocks, - effective_lowband != -1 ? norm + (effective_lowband << f->size) : NULL, f->size, - norm + band_offset, 0, 1.0f, lowband_scratch, cm[0]|cm[1]); - cm[1] = cm[0]; - } - - f->block[0].collapse_masks[i] = (uint8_t)cm[0]; - f->block[f->channels - 1].collapse_masks[i] = (uint8_t)cm[1]; - f->remaining += f->pulses[i] + consumed; - - /* Update the folding position only as long as we have 1 bit/sample depth */ - update_lowband = (b > band_size << 3); - } -} - int ff_celt_decode_frame(CeltFrame *f, OpusRangeCoder *rc, float **output, int channels, int frame_size, int start_band, int end_band) @@ -819,8 +715,10 @@ int ff_celt_decode_frame(CeltFrame *f, OpusRangeCoder *rc, if (!f->output_channels) f->output_channels = channels; - memset(f->block[0].collapse_masks, 0, sizeof(f->block[0].collapse_masks)); - memset(f->block[1].collapse_masks, 0, sizeof(f->block[1].collapse_masks)); + for (i = 0; i < f->channels; i++) { + memset(f->block[i].coeffs, 0, sizeof(f->block[i].coeffs)); + memset(f->block[i].collapse_masks, 0, sizeof(f->block[i].collapse_masks)); + } consumed = opus_rc_tell(rc); @@ -857,7 +755,7 @@ int ff_celt_decode_frame(CeltFrame *f, OpusRangeCoder *rc, celt_decode_tf_changes (f, rc); celt_decode_allocation (f, rc); celt_decode_fine_energy (f, rc); - celt_decode_bands (f, rc); + ff_celt_quant_bands (f, rc); if (f->anticollapse_needed) f->anticollapse = ff_opus_rc_get_raw(rc, 1); @@ -1021,7 +919,7 @@ int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels, if ((ret = ff_mdct15_init(&frm->imdct[i], 1, i + 3, -1.0f/32768)) < 0) goto fail; - if ((ret = ff_celt_pvq_init(&frm->pvq)) < 0) + if ((ret = ff_celt_pvq_init(&frm->pvq, 0)) < 0) goto fail; frm->dsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); diff --git a/libavcodec/opus_pvq.c b/libavcodec/opus_pvq.c index 449215f814b01..f8668de379e4f 100644 --- a/libavcodec/opus_pvq.c +++ b/libavcodec/opus_pvq.c @@ -486,8 +486,7 @@ static av_always_inline uint32_t quant_band_template(CeltPVQ *pvq, CeltFrame *f, int duration, float *lowband_out, int level, float gain, float *lowband_scratch, - int fill, int quant, - QUANT_FN(*rec)) + int fill, int quant) { int i; const uint8_t *cache; @@ -700,8 +699,8 @@ static av_always_inline uint32_t quant_band_template(CeltPVQ *pvq, CeltFrame *f, sign = 1 - 2 * sign; /* We use orig_fill here because we want to fold the side, but if itheta==16384, we'll have cleared the low bits of fill. */ - cm = rec(pvq, f, rc, band, x2, NULL, N, mbits, blocks, lowband, duration, - lowband_out, level, gain, lowband_scratch, orig_fill); + cm = pvq->quant_band(pvq, f, rc, band, x2, NULL, N, mbits, blocks, lowband, duration, + lowband_out, level, gain, lowband_scratch, orig_fill); /* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse), and there's no need to worry about mixing with the other channel. */ y2[0] = -sign * x2[1]; @@ -753,24 +752,25 @@ static av_always_inline uint32_t quant_band_template(CeltPVQ *pvq, CeltFrame *f, if (mbits >= sbits) { /* In stereo mode, we do not apply a scaling to the mid * because we need the normalized mid for folding later */ - cm = rec(pvq, f, rc, band, X, NULL, N, mbits, blocks, lowband, - duration, next_lowband_out1, next_level, - stereo ? 1.0f : (gain * mid), lowband_scratch, fill); + cm = pvq->quant_band(pvq, f, rc, band, X, NULL, N, mbits, blocks, + lowband, duration, next_lowband_out1, next_level, + stereo ? 1.0f : (gain * mid), lowband_scratch, fill); rebalance = mbits - (rebalance - f->remaining2); if (rebalance > 3 << 3 && itheta != 0) sbits += rebalance - (3 << 3); /* For a stereo split, the high bits of fill are always zero, * so no folding will be done to the side. */ - cmt = rec(pvq, f, rc, band, Y, NULL, N, sbits, blocks, next_lowband2, - duration, NULL, next_level, gain * side, NULL, - fill >> blocks); + cmt = pvq->quant_band(pvq, f, rc, band, Y, NULL, N, sbits, blocks, + next_lowband2, duration, NULL, next_level, + gain * side, NULL, fill >> blocks); cm |= cmt << ((B0 >> 1) & (stereo - 1)); } else { /* For a stereo split, the high bits of fill are always zero, * so no folding will be done to the side. */ - cm = rec(pvq, f, rc, band, Y, NULL, N, sbits, blocks, next_lowband2, - duration, NULL, next_level, gain * side, NULL, fill >> blocks); + cm = pvq->quant_band(pvq, f, rc, band, Y, NULL, N, sbits, blocks, + next_lowband2, duration, NULL, next_level, + gain * side, NULL, fill >> blocks); cm <<= ((B0 >> 1) & (stereo - 1)); rebalance = sbits - (rebalance - f->remaining2); if (rebalance > 3 << 3 && itheta != 16384) @@ -778,9 +778,9 @@ static av_always_inline uint32_t quant_band_template(CeltPVQ *pvq, CeltFrame *f, /* In stereo mode, we do not apply a scaling to the mid because * we need the normalized mid for folding later */ - cm |= rec(pvq, f, rc, band, X, NULL, N, mbits, blocks, lowband, duration, - next_lowband_out1, next_level, stereo ? 1.0f : (gain * mid), - lowband_scratch, fill); + cm |= pvq->quant_band(pvq, f, rc, band, X, NULL, N, mbits, blocks, + lowband, duration, next_lowband_out1, next_level, + stereo ? 1.0f : (gain * mid), lowband_scratch, fill); } } } else { @@ -874,19 +874,16 @@ static av_always_inline uint32_t quant_band_template(CeltPVQ *pvq, CeltFrame *f, return cm; } - static QUANT_FN(pvq_decode_band) { return quant_band_template(pvq, f, rc, band, X, Y, N, b, blocks, lowband, duration, - lowband_out, level, gain, lowband_scratch, fill, 0, - pvq->decode_band); + lowband_out, level, gain, lowband_scratch, fill, 0); } static QUANT_FN(pvq_encode_band) { return quant_band_template(pvq, f, rc, band, X, Y, N, b, blocks, lowband, duration, - lowband_out, level, gain, lowband_scratch, fill, 1, - pvq->encode_band); + lowband_out, level, gain, lowband_scratch, fill, 1); } static float pvq_band_cost(CeltPVQ *pvq, CeltFrame *f, OpusRangeCoder *rc, int band, @@ -914,14 +911,14 @@ static float pvq_band_cost(CeltPVQ *pvq, CeltFrame *f, OpusRangeCoder *rc, int b } if (f->dual_stereo) { - pvq->encode_band(pvq, f, rc, band, X, NULL, band_size, b / 2, f->blocks, NULL, - f->size, norm1, 0, 1.0f, lowband_scratch, cm[0]); + pvq->quant_band(pvq, f, rc, band, X, NULL, band_size, b / 2, f->blocks, NULL, + f->size, norm1, 0, 1.0f, lowband_scratch, cm[0]); - pvq->encode_band(pvq, f, rc, band, Y, NULL, band_size, b / 2, f->blocks, NULL, - f->size, norm2, 0, 1.0f, lowband_scratch, cm[1]); + pvq->quant_band(pvq, f, rc, band, Y, NULL, band_size, b / 2, f->blocks, NULL, + f->size, norm2, 0, 1.0f, lowband_scratch, cm[1]); } else { - pvq->encode_band(pvq, f, rc, band, X, Y, band_size, b, f->blocks, NULL, f->size, - norm1, 0, 1.0f, lowband_scratch, cm[0] | cm[1]); + pvq->quant_band(pvq, f, rc, band, X, Y, band_size, b, f->blocks, NULL, f->size, + norm1, 0, 1.0f, lowband_scratch, cm[0] | cm[1]); } for (i = 0; i < band_size; i++) { @@ -939,16 +936,15 @@ static float pvq_band_cost(CeltPVQ *pvq, CeltFrame *f, OpusRangeCoder *rc, int b return lambda*dist*cost; } -int av_cold ff_celt_pvq_init(CeltPVQ **pvq) +int av_cold ff_celt_pvq_init(CeltPVQ **pvq, int encode) { CeltPVQ *s = av_malloc(sizeof(CeltPVQ)); if (!s) return AVERROR(ENOMEM); - s->pvq_search = ppp_pvq_search_c; - s->decode_band = pvq_decode_band; - s->encode_band = pvq_encode_band; - s->band_cost = pvq_band_cost; + s->pvq_search = ppp_pvq_search_c; + s->quant_band = encode ? pvq_encode_band : pvq_decode_band; + s->band_cost = pvq_band_cost; if (ARCH_X86) ff_opus_dsp_init_x86(s); diff --git a/libavcodec/opus_pvq.h b/libavcodec/opus_pvq.h index 92463373603bb..63cc8c921e655 100644 --- a/libavcodec/opus_pvq.h +++ b/libavcodec/opus_pvq.h @@ -38,14 +38,14 @@ struct CeltPVQ { float (*pvq_search)(float *X, int *y, int K, int N); - QUANT_FN(*decode_band); - QUANT_FN(*encode_band); + QUANT_FN(*quant_band); float (*band_cost)(struct CeltPVQ *pvq, CeltFrame *f, OpusRangeCoder *rc, int band, float *bits, float lambda); }; -int ff_celt_pvq_init (struct CeltPVQ **pvq); void ff_opus_dsp_init_x86(struct CeltPVQ *s); + +int ff_celt_pvq_init(struct CeltPVQ **pvq, int encode); void ff_celt_pvq_uninit(struct CeltPVQ **pvq); #endif /* AVCODEC_OPUS_PVQ_H */ diff --git a/libavcodec/opusenc.c b/libavcodec/opusenc.c index 79d20dc6e693c..93b2116e7bb57 100644 --- a/libavcodec/opusenc.c +++ b/libavcodec/opusenc.c @@ -255,7 +255,7 @@ static void celt_frame_mdct(OpusEncContext *s, CeltFrame *f) } } -static void celt_enc_tf(OpusRangeCoder *rc, CeltFrame *f) +static void celt_enc_tf(CeltFrame *f, OpusRangeCoder *rc) { int i, tf_select = 0, diff = 0, tf_changed = 0, tf_select_needed; int bits = f->transient ? 2 : 4; @@ -282,7 +282,7 @@ static void celt_enc_tf(OpusRangeCoder *rc, CeltFrame *f) f->tf_change[i] = ff_celt_tf_select[f->size][f->transient][tf_select][f->tf_change[i]]; } -void ff_celt_enc_bitalloc(OpusRangeCoder *rc, CeltFrame *f) +void ff_celt_enc_bitalloc(CeltFrame *f, OpusRangeCoder *rc) { int i, j, low, high, total, done, bandbits, remaining, tbits_8ths; int skip_startband = f->start_band; @@ -690,7 +690,7 @@ static void exp_quant_coarse(OpusRangeCoder *rc, CeltFrame *f, } } -static void celt_quant_coarse(OpusRangeCoder *rc, CeltFrame *f, +static void celt_quant_coarse(CeltFrame *f, OpusRangeCoder *rc, float last_energy[][CELT_MAX_BANDS]) { uint32_t inter, intra; @@ -710,7 +710,7 @@ static void celt_quant_coarse(OpusRangeCoder *rc, CeltFrame *f, } } -static void celt_quant_fine(OpusRangeCoder *rc, CeltFrame *f) +static void celt_quant_fine(CeltFrame *f, OpusRangeCoder *rc) { int i, ch; for (i = f->start_band; i < f->end_band; i++) { @@ -747,95 +747,6 @@ static void celt_quant_final(OpusEncContext *s, OpusRangeCoder *rc, CeltFrame *f } } -static void celt_quant_bands(OpusRangeCoder *rc, CeltFrame *f) -{ - float lowband_scratch[8 * 22]; - float norm[2 * 8 * 100]; - - int totalbits = (f->framebits << 3) - f->anticollapse_needed; - - int update_lowband = 1; - int lowband_offset = 0; - - int i, j; - - for (i = f->start_band; i < f->end_band; i++) { - uint32_t cm[2] = { (1 << f->blocks) - 1, (1 << f->blocks) - 1 }; - int band_offset = ff_celt_freq_bands[i] << f->size; - int band_size = ff_celt_freq_range[i] << f->size; - float *X = f->block[0].coeffs + band_offset; - float *Y = (f->channels == 2) ? f->block[1].coeffs + band_offset : NULL; - - int consumed = opus_rc_tell_frac(rc); - float *norm2 = norm + 8 * 100; - int effective_lowband = -1; - int b = 0; - - /* Compute how many bits we want to allocate to this band */ - if (i != f->start_band) - f->remaining -= consumed; - f->remaining2 = totalbits - consumed - 1; - if (i <= f->coded_bands - 1) { - int curr_balance = f->remaining / FFMIN(3, f->coded_bands-i); - b = av_clip_uintp2(FFMIN(f->remaining2 + 1, f->pulses[i] + curr_balance), 14); - } - - if (ff_celt_freq_bands[i] - ff_celt_freq_range[i] >= ff_celt_freq_bands[f->start_band] && - (update_lowband || lowband_offset == 0)) - lowband_offset = i; - - /* Get a conservative estimate of the collapse_mask's for the bands we're - going to be folding from. */ - if (lowband_offset != 0 && (f->spread != CELT_SPREAD_AGGRESSIVE || - f->blocks > 1 || f->tf_change[i] < 0)) { - int foldstart, foldend; - - /* This ensures we never repeat spectral content within one band */ - effective_lowband = FFMAX(ff_celt_freq_bands[f->start_band], - ff_celt_freq_bands[lowband_offset] - ff_celt_freq_range[i]); - foldstart = lowband_offset; - while (ff_celt_freq_bands[--foldstart] > effective_lowband); - foldend = lowband_offset - 1; - while (ff_celt_freq_bands[++foldend] < effective_lowband + ff_celt_freq_range[i]); - - cm[0] = cm[1] = 0; - for (j = foldstart; j < foldend; j++) { - cm[0] |= f->block[0].collapse_masks[j]; - cm[1] |= f->block[f->channels - 1].collapse_masks[j]; - } - } - - if (f->dual_stereo && i == f->intensity_stereo) { - /* Switch off dual stereo to do intensity */ - f->dual_stereo = 0; - for (j = ff_celt_freq_bands[f->start_band] << f->size; j < band_offset; j++) - norm[j] = (norm[j] + norm2[j]) / 2; - } - - if (f->dual_stereo) { - cm[0] = f->pvq->encode_band(f->pvq, f, rc, i, X, NULL, band_size, b / 2, f->blocks, - effective_lowband != -1 ? norm + (effective_lowband << f->size) : NULL, f->size, - norm + band_offset, 0, 1.0f, lowband_scratch, cm[0]); - - cm[1] = f->pvq->encode_band(f->pvq, f, rc, i, Y, NULL, band_size, b / 2, f->blocks, - effective_lowband != -1 ? norm2 + (effective_lowband << f->size) : NULL, f->size, - norm2 + band_offset, 0, 1.0f, lowband_scratch, cm[1]); - } else { - cm[0] = f->pvq->encode_band(f->pvq, f, rc, i, X, Y, band_size, b, f->blocks, - effective_lowband != -1 ? norm + (effective_lowband << f->size) : NULL, f->size, - norm + band_offset, 0, 1.0f, lowband_scratch, cm[0] | cm[1]); - cm[1] = cm[0]; - } - - f->block[0].collapse_masks[i] = (uint8_t)cm[0]; - f->block[f->channels - 1].collapse_masks[i] = (uint8_t)cm[1]; - f->remaining += f->pulses[i] + consumed; - - /* Update the folding position only as long as we have 1 bit/sample depth */ - update_lowband = (b > band_size << 3); - } -} - static void celt_encode_frame(OpusEncContext *s, OpusRangeCoder *rc, CeltFrame *f, int index) { @@ -883,11 +794,11 @@ static void celt_encode_frame(OpusEncContext *s, OpusRangeCoder *rc, ff_opus_rc_enc_log(rc, f->transient, 3); /* Main encoding */ - celt_quant_coarse(rc, f, s->last_quantized_energy); - celt_enc_tf (rc, f); - ff_celt_enc_bitalloc(rc, f); - celt_quant_fine (rc, f); - celt_quant_bands (rc, f); + celt_quant_coarse (f, rc, s->last_quantized_energy); + celt_enc_tf (f, rc); + ff_celt_enc_bitalloc(f, rc); + celt_quant_fine (f, rc); + ff_celt_quant_bands (f, rc); /* Anticollapse bit */ if (f->anticollapse_needed) @@ -1080,7 +991,7 @@ static av_cold int opus_encode_init(AVCodecContext *avctx) ff_af_queue_init(avctx, &s->afq); - if ((ret = ff_celt_pvq_init(&s->pvq)) < 0) + if ((ret = ff_celt_pvq_init(&s->pvq, 1)) < 0) return ret; if (!(s->dsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT))) @@ -1117,6 +1028,7 @@ static av_cold int opus_encode_init(AVCodecContext *avctx) s->frame[i].avctx = s->avctx; s->frame[i].seed = 0; s->frame[i].pvq = s->pvq; + s->frame[i].apply_phase_inv = 1; s->frame[i].block[0].emph_coeff = s->frame[i].block[1].emph_coeff = 0.0f; } diff --git a/libavcodec/opusenc.h b/libavcodec/opusenc.h index 3273d0a9a2a78..56e4af67e320b 100644 --- a/libavcodec/opusenc.h +++ b/libavcodec/opusenc.h @@ -51,6 +51,6 @@ typedef struct OpusPacketInfo { int frames; } OpusPacketInfo; -void ff_celt_enc_bitalloc(OpusRangeCoder *rc, CeltFrame *f); +void ff_celt_enc_bitalloc(CeltFrame *f, OpusRangeCoder *rc); #endif /* AVCODEC_OPUSENC_H */ diff --git a/libavcodec/opusenc_psy.c b/libavcodec/opusenc_psy.c index 1b108ecb873b6..dc549dc9a95ca 100644 --- a/libavcodec/opusenc_psy.c +++ b/libavcodec/opusenc_psy.c @@ -316,7 +316,7 @@ static int bands_dist(OpusPsyContext *s, CeltFrame *f, float *total_dist) OpusRangeCoder dump; ff_opus_rc_enc_init(&dump); - ff_celt_enc_bitalloc(&dump, f); + ff_celt_enc_bitalloc(f, &dump); for (i = 0; i < CELT_MAX_BANDS; i++) { float bits = 0.0f; From 7b46add7257628bffac96d3002308d1f9e1ed172 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Mon, 4 Dec 2017 08:57:45 +0000 Subject: [PATCH 1249/2557] opus_pvq: do not compile encoding/decoding code if the encoder/decoder is disabled This should save quite a bit of space if either has been disabled for size reasons. Could just check if the encoding flag is set during runtime on every single location, however the overhead of branch misses would somewhat decrease performance. Signed-off-by: Rostislav Pehlivanov --- libavcodec/opus_pvq.c | 59 ++++++---------------------------------- libavcodec/opus_pvq.h | 3 -- libavcodec/opusenc_psy.c | 52 ++++++++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 55 deletions(-) diff --git a/libavcodec/opus_pvq.c b/libavcodec/opus_pvq.c index f8668de379e4f..0dbf14184d11e 100644 --- a/libavcodec/opus_pvq.c +++ b/libavcodec/opus_pvq.c @@ -876,64 +876,22 @@ static av_always_inline uint32_t quant_band_template(CeltPVQ *pvq, CeltFrame *f, static QUANT_FN(pvq_decode_band) { +#if CONFIG_OPUS_DECODER return quant_band_template(pvq, f, rc, band, X, Y, N, b, blocks, lowband, duration, lowband_out, level, gain, lowband_scratch, fill, 0); +#else + return 0; +#endif } static QUANT_FN(pvq_encode_band) { +#if CONFIG_OPUS_ENCODER return quant_band_template(pvq, f, rc, band, X, Y, N, b, blocks, lowband, duration, lowband_out, level, gain, lowband_scratch, fill, 1); -} - -static float pvq_band_cost(CeltPVQ *pvq, CeltFrame *f, OpusRangeCoder *rc, int band, - float *bits, float lambda) -{ - int i, b = 0; - uint32_t cm[2] = { (1 << f->blocks) - 1, (1 << f->blocks) - 1 }; - const int band_size = ff_celt_freq_range[band] << f->size; - float buf[176 * 2], lowband_scratch[176], norm1[176], norm2[176]; - float dist, cost, err_x = 0.0f, err_y = 0.0f; - float *X = buf; - float *X_orig = f->block[0].coeffs + (ff_celt_freq_bands[band] << f->size); - float *Y = (f->channels == 2) ? &buf[176] : NULL; - float *Y_orig = f->block[1].coeffs + (ff_celt_freq_bands[band] << f->size); - OPUS_RC_CHECKPOINT_SPAWN(rc); - - memcpy(X, X_orig, band_size*sizeof(float)); - if (Y) - memcpy(Y, Y_orig, band_size*sizeof(float)); - - f->remaining2 = ((f->framebits << 3) - f->anticollapse_needed) - opus_rc_tell_frac(rc) - 1; - if (band <= f->coded_bands - 1) { - int curr_balance = f->remaining / FFMIN(3, f->coded_bands - band); - b = av_clip_uintp2(FFMIN(f->remaining2 + 1, f->pulses[band] + curr_balance), 14); - } - - if (f->dual_stereo) { - pvq->quant_band(pvq, f, rc, band, X, NULL, band_size, b / 2, f->blocks, NULL, - f->size, norm1, 0, 1.0f, lowband_scratch, cm[0]); - - pvq->quant_band(pvq, f, rc, band, Y, NULL, band_size, b / 2, f->blocks, NULL, - f->size, norm2, 0, 1.0f, lowband_scratch, cm[1]); - } else { - pvq->quant_band(pvq, f, rc, band, X, Y, band_size, b, f->blocks, NULL, f->size, - norm1, 0, 1.0f, lowband_scratch, cm[0] | cm[1]); - } - - for (i = 0; i < band_size; i++) { - err_x += (X[i] - X_orig[i])*(X[i] - X_orig[i]); - if (Y) - err_y += (Y[i] - Y_orig[i])*(Y[i] - Y_orig[i]); - } - - dist = sqrtf(err_x) + sqrtf(err_y); - cost = OPUS_RC_CHECKPOINT_BITS(rc)/8.0f; - *bits += cost; - - OPUS_RC_CHECKPOINT_ROLLBACK(rc); - - return lambda*dist*cost; +#else + return 0; +#endif } int av_cold ff_celt_pvq_init(CeltPVQ **pvq, int encode) @@ -944,7 +902,6 @@ int av_cold ff_celt_pvq_init(CeltPVQ **pvq, int encode) s->pvq_search = ppp_pvq_search_c; s->quant_band = encode ? pvq_encode_band : pvq_decode_band; - s->band_cost = pvq_band_cost; if (ARCH_X86) ff_opus_dsp_init_x86(s); diff --git a/libavcodec/opus_pvq.h b/libavcodec/opus_pvq.h index 63cc8c921e655..e2f01a01b5c68 100644 --- a/libavcodec/opus_pvq.h +++ b/libavcodec/opus_pvq.h @@ -37,10 +37,7 @@ struct CeltPVQ { DECLARE_ALIGNED(32, float, hadamard_tmp)[256]; float (*pvq_search)(float *X, int *y, int K, int N); - QUANT_FN(*quant_band); - float (*band_cost)(struct CeltPVQ *pvq, CeltFrame *f, OpusRangeCoder *rc, - int band, float *bits, float lambda); }; void ff_opus_dsp_init_x86(struct CeltPVQ *s); diff --git a/libavcodec/opusenc_psy.c b/libavcodec/opusenc_psy.c index dc549dc9a95ca..5393c9d7deaba 100644 --- a/libavcodec/opusenc_psy.c +++ b/libavcodec/opusenc_psy.c @@ -25,6 +25,56 @@ #include "mdct15.h" #include "libavutil/qsort.h" +static float pvq_band_cost(CeltPVQ *pvq, CeltFrame *f, OpusRangeCoder *rc, int band, + float *bits, float lambda) +{ + int i, b = 0; + uint32_t cm[2] = { (1 << f->blocks) - 1, (1 << f->blocks) - 1 }; + const int band_size = ff_celt_freq_range[band] << f->size; + float buf[176 * 2], lowband_scratch[176], norm1[176], norm2[176]; + float dist, cost, err_x = 0.0f, err_y = 0.0f; + float *X = buf; + float *X_orig = f->block[0].coeffs + (ff_celt_freq_bands[band] << f->size); + float *Y = (f->channels == 2) ? &buf[176] : NULL; + float *Y_orig = f->block[1].coeffs + (ff_celt_freq_bands[band] << f->size); + OPUS_RC_CHECKPOINT_SPAWN(rc); + + memcpy(X, X_orig, band_size*sizeof(float)); + if (Y) + memcpy(Y, Y_orig, band_size*sizeof(float)); + + f->remaining2 = ((f->framebits << 3) - f->anticollapse_needed) - opus_rc_tell_frac(rc) - 1; + if (band <= f->coded_bands - 1) { + int curr_balance = f->remaining / FFMIN(3, f->coded_bands - band); + b = av_clip_uintp2(FFMIN(f->remaining2 + 1, f->pulses[band] + curr_balance), 14); + } + + if (f->dual_stereo) { + pvq->quant_band(pvq, f, rc, band, X, NULL, band_size, b / 2, f->blocks, NULL, + f->size, norm1, 0, 1.0f, lowband_scratch, cm[0]); + + pvq->quant_band(pvq, f, rc, band, Y, NULL, band_size, b / 2, f->blocks, NULL, + f->size, norm2, 0, 1.0f, lowband_scratch, cm[1]); + } else { + pvq->quant_band(pvq, f, rc, band, X, Y, band_size, b, f->blocks, NULL, f->size, + norm1, 0, 1.0f, lowband_scratch, cm[0] | cm[1]); + } + + for (i = 0; i < band_size; i++) { + err_x += (X[i] - X_orig[i])*(X[i] - X_orig[i]); + if (Y) + err_y += (Y[i] - Y_orig[i])*(Y[i] - Y_orig[i]); + } + + dist = sqrtf(err_x) + sqrtf(err_y); + cost = OPUS_RC_CHECKPOINT_BITS(rc)/8.0f; + *bits += cost; + + OPUS_RC_CHECKPOINT_ROLLBACK(rc); + + return lambda*dist*cost; +} + /* Populate metrics without taking into consideration neighbouring steps */ static void step_collect_psy_metrics(OpusPsyContext *s, int index) { @@ -320,7 +370,7 @@ static int bands_dist(OpusPsyContext *s, CeltFrame *f, float *total_dist) for (i = 0; i < CELT_MAX_BANDS; i++) { float bits = 0.0f; - float dist = f->pvq->band_cost(f->pvq, f, &dump, i, &bits, s->lambda); + float dist = pvq_band_cost(f->pvq, f, &dump, i, &bits, s->lambda); tdist += dist; } From e836a0b3fd6943f77f54d65ee4ac1005e71d1162 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Mon, 4 Dec 2017 10:50:23 +0000 Subject: [PATCH 1250/2557] fate-opus: update tests to use new decoder outputs Can't overwrite old ones. Signed-off-by: Rostislav Pehlivanov --- tests/fate/opus.mak | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/fate/opus.mak b/tests/fate/opus.mak index 46e90168d6f8d..36221ec26587f 100644 --- a/tests/fate/opus.mak +++ b/tests/fate/opus.mak @@ -2,21 +2,21 @@ # their custom format into Matroska. The reference decoded outputs are from the # newest testvectors file from RFC8251 -OPUS_CELT_SAMPLES = $(addprefix testvector, 01 07 11) tron.6ch.tinypkts +OPUS_CELT_SAMPLES = $(addprefix testvector, 11) tron.6ch.tinypkts OPUS_HYBRID_SAMPLES = $(addprefix testvector, 05 06) OPUS_SILK_SAMPLES = $(addprefix testvector, 02 03 04) -OPUS_SAMPLES = $(addprefix testvector, 08 09 10 12) +OPUS_SAMPLES = $(addprefix testvector, 08 10 12) define FATE_OPUS_TEST FATE_OPUS += fate-opus-$(1) FATE_OPUS$(2) += fate-opus-$(1) fate-opus-$(1): CMD = ffmpeg -i $(TARGET_SAMPLES)/opus/$(1).mka -f s16le - -fate-opus-$(1): REF = $(SAMPLES)/opus/$(1).dec +fate-opus-$(1): REF = $(SAMPLES)/opus/$(1)$(2).dec endef -$(foreach N,$(OPUS_CELT_SAMPLES), $(eval $(call FATE_OPUS_TEST,$(N),_CELT))) -$(foreach N,$(OPUS_HYBRID_SAMPLES),$(eval $(call FATE_OPUS_TEST,$(N),_HYBRID))) -$(foreach N,$(OPUS_SILK_SAMPLES), $(eval $(call FATE_OPUS_TEST,$(N),_SILK))) +$(foreach N,$(OPUS_CELT_SAMPLES), $(eval $(call FATE_OPUS_TEST,$(N)))) +$(foreach N,$(OPUS_HYBRID_SAMPLES),$(eval $(call FATE_OPUS_TEST,$(N),_v2))) +$(foreach N,$(OPUS_SILK_SAMPLES), $(eval $(call FATE_OPUS_TEST,$(N)))) $(foreach N,$(OPUS_SAMPLES), $(eval $(call FATE_OPUS_TEST,$(N),))) FATE_OPUS := $(sort $(FATE_OPUS)) @@ -24,7 +24,6 @@ FATE_OPUS := $(sort $(FATE_OPUS)) $(FATE_OPUS): CMP = stddev $(FATE_OPUS): CMP_UNIT = s16 $(FATE_OPUS): FUZZ = 3 -fate-opus-testvector01: CMP_TARGET = 1 fate-opus-testvector02: CMP_TARGET = 191 fate-opus-testvector03: CMP_TARGET = 139 fate-opus-testvector04: CMP_TARGET = 119 From 5ff0d2acaef87950a254cea9c75153f48caaa729 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 4 Dec 2017 15:08:43 +0100 Subject: [PATCH 1251/2557] avfilter/x86/vf_hflip.asm: fix building on x32 Signed-off-by: Paul B Mahol --- libavfilter/x86/vf_hflip.asm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavfilter/x86/vf_hflip.asm b/libavfilter/x86/vf_hflip.asm index 867dcaeed5b66..d14cc086e564c 100644 --- a/libavfilter/x86/vf_hflip.asm +++ b/libavfilter/x86/vf_hflip.asm @@ -30,7 +30,7 @@ pb_flip_short: db 14,15,12,13,10,11,8,9,6,7,4,5,2,3,0,1 SECTION .text INIT_XMM ssse3 -cglobal hflip_byte, 3, 6, 3, src, dst, w, x, v, r +cglobal hflip_byte, 3, 5, 3, src, dst, w, r, x mova m0, [pb_flip_byte] mov xq, 0 mov wd, dword wm @@ -59,16 +59,16 @@ cglobal hflip_byte, 3, 6, 3, src, dst, w, x, v, r .loop1: neg xq - mov vb, [srcq + xq] + mov rb, [srcq + xq] neg xq - mov [dstq + xq], vb + mov [dstq + xq], rb add xq, 1 cmp xq, wq jl .loop1 .end: RET -cglobal hflip_short, 3, 6, 3, src, dst, w, x, v, r +cglobal hflip_short, 3, 5, 3, src, dst, w, r, x mova m0, [pb_flip_short] mov xq, 0 mov wd, dword wm @@ -98,9 +98,9 @@ cglobal hflip_short, 3, 6, 3, src, dst, w, x, v, r .loop1: neg xq - mov vw, [srcq + xq] + mov rw, [srcq + xq] neg xq - mov [dstq + xq], vw + mov [dstq + xq], rw add xq, 2 cmp xq, wq jl .loop1 From d67c1dda403288bcfd30b5d4a0412582728c2c79 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 4 Dec 2017 23:52:17 +0800 Subject: [PATCH 1252/2557] avformat/hlsenc: fix compiling error when disable-network --- libavformat/hlsenc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index aeeed5bcd22d2..7dc8f4237b636 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -45,7 +45,9 @@ #include "avformat.h" #include "avio_internal.h" +#if CONFIG_HTTP_PROTOCOL #include "http.h" +#endif #include "hlsplaylist.h" #include "internal.h" #include "os_support.h" @@ -245,13 +247,15 @@ static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, AVDictionary **options) { HLSContext *hls = s->priv_data; int http_base_proto = is_http_proto(filename); - int err; + int err = AVERROR_MUXER_NOT_FOUND; if (!*pb || !http_base_proto || !hls->http_persistent) { err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options); +#if CONFIG_HTTP_PROTOCOL } else { URLContext *http_url_context = ffio_geturlcontext(*pb); av_assert0(http_url_context); err = ff_http_do_new_request(http_url_context, filename); +#endif } return err; } From 942eafcf08c440eb23f08c10bd7b56d1c27fd21c Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 30 Nov 2017 23:58:02 +0100 Subject: [PATCH 1253/2557] libavcodec/hevc_filter: support for all skip_loop_filter levels. Continues where commit 52c75d486ed5f75cbb79e5dbd07b7aef24f3071f left off. Signed-off-by: Michael Niedermayer --- doc/decoders.texi | 7 ------- libavcodec/hevc_filter.c | 29 +++++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/doc/decoders.texi b/doc/decoders.texi index d149d2bea5142..a9510bdf02d19 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -25,13 +25,6 @@ enabled decoders. A description of some of the currently available video decoders follows. -@section hevc - -HEVC / H.265 decoder. - -Note: the @option{skip_loop_filter} option has effect only at level -@code{all}. - @section rawvideo Raw video decoder. diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c index b53f4cc72129b..94fb7cd3d16e1 100644 --- a/libavcodec/hevc_filter.c +++ b/libavcodec/hevc_filter.c @@ -842,9 +842,34 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) { int x_end = x >= s->ps.sps->width - ctb_size; - if (s->avctx->skip_loop_filter < AVDISCARD_ALL) + int skip = 0, is_n = 0; + switch (s->nal_unit_type) { + case HEVC_NAL_TRAIL_N: + case HEVC_NAL_TSA_N: + case HEVC_NAL_STSA_N: + case HEVC_NAL_RADL_N: + case HEVC_NAL_RASL_N: + case HEVC_NAL_VCL_N10: + case HEVC_NAL_VCL_N12: + case HEVC_NAL_VCL_N14: + case HEVC_NAL_BLA_N_LP: + case HEVC_NAL_IDR_N_LP: + is_n = 1; + break; + default: break; + } + if (s->avctx->skip_loop_filter >= AVDISCARD_ALL || + (s->avctx->skip_loop_filter >= AVDISCARD_NONKEY && !IS_IDR(s)) || + (s->avctx->skip_loop_filter >= AVDISCARD_NONINTRA && + s->sh.slice_type != HEVC_SLICE_I) || + (s->avctx->skip_loop_filter >= AVDISCARD_BIDIR && + s->sh.slice_type == HEVC_SLICE_B) || + (s->avctx->skip_loop_filter >= AVDISCARD_NONREF && is_n)) + skip = 1; + + if (!skip) deblocking_filter_CTB(s, x, y); - if (s->ps.sps->sao_enabled) { + if (s->ps.sps->sao_enabled && !skip) { int y_end = y >= s->ps.sps->height - ctb_size; if (y && x) sao_filter_CTB(s, x - ctb_size, y - ctb_size); From 1b324700e3a1cb7894bfbd76f5591cf643dc0371 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 4 Dec 2017 15:26:34 -0300 Subject: [PATCH 1254/2557] checkasm/vf_threshold: fix mixed code and declarations Signed-off-by: James Almer --- tests/checkasm/vf_threshold.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/checkasm/vf_threshold.c b/tests/checkasm/vf_threshold.c index 770f00ed3b4f5..3709f2671e049 100644 --- a/tests/checkasm/vf_threshold.c +++ b/tests/checkasm/vf_threshold.c @@ -42,16 +42,16 @@ static void check_threshold_8(void){ ptrdiff_t line_size = WIDTH_PADDED; int w = WIDTH; - ThresholdContext s; - s.depth = 8; - ff_threshold_init(&s); - declare_func(void, const uint8_t *in, const uint8_t *threshold, const uint8_t *min, const uint8_t *max, uint8_t *out, ptrdiff_t ilinesize, ptrdiff_t tlinesize, ptrdiff_t flinesize, ptrdiff_t slinesize, ptrdiff_t olinesize, int w, int h); + ThresholdContext s; + s.depth = 8; + ff_threshold_init(&s); + memset(in, 0, WIDTH_PADDED); memset(threshold, 0, WIDTH_PADDED); memset(min, 0, WIDTH_PADDED); From bfd7f07b650b0414683c2c2554870e4e74d5c083 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 4 Dec 2017 15:39:19 -0300 Subject: [PATCH 1255/2557] fate/checkasm: add missing target for vf_threshold test Signed-off-by: James Almer --- tests/fate/checkasm.mak | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index fe0fd9729f504..3db745366cd2f 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -22,6 +22,7 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp \ fate-checkasm-v210enc \ fate-checkasm-vf_blend \ fate-checkasm-vf_colorspace \ + fate-checkasm-vf_threshold \ fate-checkasm-videodsp \ fate-checkasm-vp8dsp \ fate-checkasm-vp9dsp \ From cc2ba526d4140829e9b3a8d5919b8cfe449972c3 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 4 Dec 2017 15:04:43 -0300 Subject: [PATCH 1256/2557] x86/vf_threshold: make threshold8 functions work on x86_32 Signed-off-by: James Almer --- libavfilter/x86/vf_threshold.asm | 15 +++++++++++---- libavfilter/x86/vf_threshold_init.c | 14 ++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/libavfilter/x86/vf_threshold.asm b/libavfilter/x86/vf_threshold.asm index 5e595fa13f943..56a6c242d8f83 100644 --- a/libavfilter/x86/vf_threshold.asm +++ b/libavfilter/x86/vf_threshold.asm @@ -22,8 +22,6 @@ %include "libavutil/x86/x86util.asm" -%if ARCH_X86_64 - SECTION_RODATA pb_128: times 16 db 128 @@ -31,9 +29,20 @@ pb_128: times 16 db 128 SECTION .text %macro THRESHOLD_8 0 +%if ARCH_X86_64 cglobal threshold8, 10, 13, 5, in, threshold, min, max, out, ilinesize, tlinesize, flinesize, slinesize, olinesize, w, h, x mov wd, dword wm mov hd, dword hm +%else +cglobal threshold8, 5, 7, 5, in, threshold, min, max, out, w, x + mov wd, r10m +%define ilinesizeq r5mp +%define tlinesizeq r6mp +%define flinesizeq r7mp +%define slinesizeq r8mp +%define olinesizeq r9mp +%define hd r11mp +%endif VBROADCASTI128 m4, [pb_128] add inq, wq add thresholdq, wq @@ -74,5 +83,3 @@ THRESHOLD_8 INIT_YMM avx2 THRESHOLD_8 %endif - -%endif diff --git a/libavfilter/x86/vf_threshold_init.c b/libavfilter/x86/vf_threshold_init.c index f448cb4b39f96..db0559533d410 100644 --- a/libavfilter/x86/vf_threshold_init.c +++ b/libavfilter/x86/vf_threshold_init.c @@ -42,14 +42,12 @@ av_cold void ff_threshold_init_x86(ThresholdContext *s) { int cpu_flags = av_get_cpu_flags(); - if (ARCH_X86_64) { - if (s->depth == 8) { - if (EXTERNAL_SSE4(cpu_flags)) { - s->threshold = ff_threshold8_sse4; - } - if (EXTERNAL_AVX2_FAST(cpu_flags)) { - s->threshold = ff_threshold8_avx2; - } + if (s->depth == 8) { + if (EXTERNAL_SSE4(cpu_flags)) { + s->threshold = ff_threshold8_sse4; + } + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + s->threshold = ff_threshold8_avx2; } } } From 312b00de8f8b15f416daf90865da3be9180a09c8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 4 Dec 2017 21:32:29 +0100 Subject: [PATCH 1257/2557] avfilter/vf_convolution: add 7x7 filter Signed-off-by: Paul B Mahol --- doc/filters.texi | 4 +- libavfilter/vf_convolution.c | 175 ++++++++++++++++++++++++++++++++++- 2 files changed, 172 insertions(+), 7 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index f7c371592f0af..8bffb708d24dc 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6025,7 +6025,7 @@ colorspace=smpte240m @section convolution -Apply convolution 3x3 or 5x5 filter. +Apply convolution 3x3, 5x5 or 7x7 filter. The filter accepts the following options: @@ -6035,7 +6035,7 @@ The filter accepts the following options: @item 2m @item 3m Set matrix for each plane. -Matrix is sequence of 9 or 25 signed integers. +Matrix is sequence of 9, 25 or 49 signed integers. @item 0rdiv @item 1rdiv diff --git a/libavfilter/vf_convolution.c b/libavfilter/vf_convolution.c index 602031999f338..d7f8bf8a65102 100644 --- a/libavfilter/vf_convolution.c +++ b/libavfilter/vf_convolution.c @@ -48,7 +48,7 @@ typedef struct ConvolutionContext { int nb_threads; int planewidth[4]; int planeheight[4]; - int matrix[4][25]; + int matrix[4][49]; int matrix_length[4]; int copy[4]; @@ -86,6 +86,14 @@ static const int same5x5[25] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const int same7x7[49] = {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, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0}; + static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { @@ -585,6 +593,81 @@ static int filter16_5x5(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) return 0; } +static int filter16_7x7(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ConvolutionContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + const int plane = td->plane; + const int peak = (1 << s->depth) - 1; + const int stride = in->linesize[plane] / 2; + const int bstride = s->bstride; + const int height = s->planeheight[plane]; + const int width = s->planewidth[plane]; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr+1)) / nb_jobs; + const uint16_t *src = (const uint16_t *)in->data[plane] + slice_start * stride; + uint16_t *dst = (uint16_t *)out->data[plane] + slice_start * (out->linesize[plane] / 2); + uint16_t *p0 = (uint16_t *)s->bptrs[jobnr] + 32; + uint16_t *p1 = p0 + bstride; + uint16_t *p2 = p1 + bstride; + uint16_t *p3 = p2 + bstride; + uint16_t *p4 = p3 + bstride; + uint16_t *p5 = p4 + bstride; + uint16_t *p6 = p5 + bstride; + uint16_t *orig = p0, *end = p6; + const int *matrix = s->matrix[plane]; + float rdiv = s->rdiv[plane]; + float bias = s->bias[plane]; + int y, x, i; + + line_copy16(p0, src + 3 * stride * (slice_start < 3 ? 1 : -1), width, 3); + line_copy16(p1, src + 2 * stride * (slice_start < 2 ? 1 : -1), width, 3); + line_copy16(p2, src + stride * (slice_start == 0 ? 1 : -1), width, 3); + line_copy16(p3, src, width, 3); + src += stride; + line_copy16(p4, src, width, 3); + src += stride; + line_copy16(p5, src, width, 3); + + for (y = slice_start; y < slice_end; y++) { + uint16_t *array[] = { + p0 - 3, p0 - 2, p0 - 1, p0, p0 + 1, p0 + 2, p0 + 3, + p1 - 3, p1 - 2, p1 - 1, p1, p1 + 1, p1 + 2, p1 + 3, + p2 - 3, p2 - 2, p2 - 1, p2, p2 + 1, p2 + 2, p2 + 3, + p3 - 3, p3 - 2, p3 - 1, p3, p3 + 1, p3 + 2, p3 + 3, + p4 - 3, p4 - 2, p4 - 1, p4, p4 + 1, p4 + 2, p4 + 3, + p5 - 3, p5 - 2, p5 - 1, p5, p5 + 1, p5 + 2, p5 + 3, + p6 - 3, p6 - 2, p6 - 1, p6, p6 + 1, p6 + 2, p6 + 3, + }; + + src += stride * (y < height - 3 ? 1 : -1); + line_copy16(p6, src, width, 3); + + for (x = 0; x < width; x++) { + int sum = 0; + + for (i = 0; i < 25; i++) { + sum += *(array[i] + x) * matrix[i]; + } + sum = (int)(sum * rdiv + bias + 0.5f); + dst[x] = av_clip(sum, 0, peak); + } + + p0 = p1; + p1 = p2; + p2 = p3; + p3 = p4; + p4 = p5; + p5 = p6; + p6 = (p6 == end) ? orig: p6 + bstride; + dst += out->linesize[plane] / 2; + } + + return 0; +} + static int filter_3x3(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ConvolutionContext *s = ctx->priv; @@ -705,6 +788,80 @@ static int filter_5x5(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) return 0; } +static int filter_7x7(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ConvolutionContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + const int plane = td->plane; + const int stride = in->linesize[plane]; + const int bstride = s->bstride; + const int height = s->planeheight[plane]; + const int width = s->planewidth[plane]; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr+1)) / nb_jobs; + const uint8_t *src = in->data[plane] + slice_start * stride; + uint8_t *dst = out->data[plane] + slice_start * out->linesize[plane]; + uint8_t *p0 = s->bptrs[jobnr] + 32; + uint8_t *p1 = p0 + bstride; + uint8_t *p2 = p1 + bstride; + uint8_t *p3 = p2 + bstride; + uint8_t *p4 = p3 + bstride; + uint8_t *p5 = p4 + bstride; + uint8_t *p6 = p5 + bstride; + uint8_t *orig = p0, *end = p6; + const int *matrix = s->matrix[plane]; + float rdiv = s->rdiv[plane]; + float bias = s->bias[plane]; + int y, x, i; + + line_copy8(p0, src + 3 * stride * (slice_start < 3 ? 1 : -1), width, 3); + line_copy8(p1, src + 2 * stride * (slice_start < 2 ? 1 : -1), width, 3); + line_copy8(p2, src + stride * (slice_start == 0 ? 1 : -1), width, 3); + line_copy8(p3, src, width, 3); + src += stride; + line_copy8(p4, src, width, 3); + src += stride; + line_copy8(p5, src, width, 3); + + for (y = slice_start; y < slice_end; y++) { + uint8_t *array[] = { + p0 - 3, p0 - 2, p0 - 1, p0, p0 + 1, p0 + 2, p0 + 3, + p1 - 3, p1 - 2, p1 - 1, p1, p1 + 1, p1 + 2, p1 + 3, + p2 - 3, p2 - 2, p2 - 1, p2, p2 + 1, p2 + 2, p2 + 3, + p3 - 3, p3 - 2, p3 - 1, p3, p3 + 1, p3 + 2, p3 + 3, + p4 - 3, p4 - 2, p4 - 1, p4, p4 + 1, p4 + 2, p4 + 3, + p5 - 3, p5 - 2, p5 - 1, p5, p5 + 1, p5 + 2, p5 + 3, + p6 - 3, p6 - 2, p6 - 1, p6, p6 + 1, p6 + 2, p6 + 3, + }; + + src += stride * (y < height - 3 ? 1 : -1); + line_copy8(p6, src, width, 3); + + for (x = 0; x < width; x++) { + int sum = 0; + + for (i = 0; i < 49; i++) { + sum += *(array[i] + x) * matrix[i]; + } + sum = (int)(sum * rdiv + bias + 0.5f); + dst[x] = av_clip_uint8(sum); + } + + p0 = p1; + p1 = p2; + p2 = p3; + p3 = p4; + p4 = p5; + p5 = p6; + p6 = (p6 == end) ? orig: p6 + bstride; + dst += out->linesize[plane]; + } + + return 0; +} + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -725,14 +882,14 @@ static int config_input(AVFilterLink *inlink) if (!s->bptrs) return AVERROR(ENOMEM); - s->bstride = s->planewidth[0] + 32; + s->bstride = s->planewidth[0] + 64; s->bpc = (s->depth + 7) / 8; - s->buffer = av_malloc_array(5 * s->bstride * s->nb_threads, s->bpc); + s->buffer = av_malloc_array(7 * s->bstride * s->nb_threads, s->bpc); if (!s->buffer) return AVERROR(ENOMEM); for (p = 0; p < s->nb_threads; p++) { - s->bptrs[p] = s->buffer + 5 * s->bstride * s->bpc * p; + s->bptrs[p] = s->buffer + 7 * s->bstride * s->bpc * p; } if (!strcmp(ctx->filter->name, "convolution")) { @@ -742,6 +899,8 @@ static int config_input(AVFilterLink *inlink) s->filter[p] = filter16_3x3; else if (s->size[p] == 5) s->filter[p] = filter16_5x5; + else if (s->size[p] == 7) + s->filter[p] = filter16_7x7; } } } else if (!strcmp(ctx->filter->name, "prewitt")) { @@ -808,7 +967,7 @@ static av_cold int init(AVFilterContext *ctx) char *p, *arg, *saveptr = NULL; p = s->matrix_str[i]; - while (s->matrix_length[i] < 25) { + while (s->matrix_length[i] < 49) { if (!(arg = av_strtok(p, " ", &saveptr))) break; @@ -829,6 +988,12 @@ static av_cold int init(AVFilterContext *ctx) s->copy[i] = 1; else s->filter[i] = filter_5x5; + } else if (s->matrix_length[i] == 49) { + s->size[i] = 7; + if (!memcmp(matrix, same7x7, sizeof(same7x7))) + s->copy[i] = 1; + else + s->filter[i] = filter_7x7; } else { return AVERROR(EINVAL); } From 9f7cc87baf2ce407cd1d537777e572ebb4eaa13c Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Fri, 1 Dec 2017 22:01:41 +0000 Subject: [PATCH 1258/2557] rkmpp: Add hardware config information This is not strictly required here because the rkmpp decoder does not call ff_get_format(), but it may be helpful metadata for users. --- libavcodec/rkmppdec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c index bdf4dc4208c3c..4ec61cbb35eb6 100644 --- a/libavcodec/rkmppdec.c +++ b/libavcodec/rkmppdec.c @@ -28,6 +28,7 @@ #include "avcodec.h" #include "decode.h" +#include "hwaccel.h" #include "internal.h" #include "libavutil/buffer.h" #include "libavutil/common.h" @@ -563,6 +564,10 @@ static void rkmpp_flush(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "Failed to reset MPI (code = %d)\n", ret); } +static const AVCodecHWConfigInternal *rkmpp_hw_configs[] = { + HW_CONFIG_INTERNAL(DRM_PRIME), + NULL +}; #define RKMPP_DEC_CLASS(NAME) \ static const AVClass rkmpp_##NAME##_dec_class = { \ @@ -587,6 +592,7 @@ static void rkmpp_flush(AVCodecContext *avctx) .caps_internal = AV_CODEC_CAP_AVOID_PROBING, \ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ AV_PIX_FMT_NONE}, \ + .hw_configs = rkmpp_hw_configs, \ .bsfs = BSFS, \ }; From c490fc9536dcea7fdf1245a340bf075533610bc2 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 29 Nov 2017 21:31:11 +0000 Subject: [PATCH 1259/2557] vaapi_h264: Add named options for setting profile and level --- libavcodec/vaapi_encode_h264.c | 48 ++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 5fd0bf7796d73..6940823b8ebfd 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -93,6 +93,8 @@ typedef struct VAAPIEncodeH264Options { int coder; int aud; int sei; + int profile; + int level; } VAAPIEncodeH264Options; @@ -886,6 +888,11 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx) ctx->codec = &vaapi_encode_type_h264; + if (avctx->profile == FF_PROFILE_UNKNOWN) + avctx->profile = opt->profile; + if (avctx->level == FF_LEVEL_UNKNOWN) + avctx->level = opt->level; + switch (avctx->profile) { case FF_PROFILE_H264_BASELINE: av_log(avctx, AV_LOG_WARNING, "H.264 baseline profile is not " @@ -1010,12 +1017,49 @@ static const AVOption vaapi_encode_h264_options[] = { { "recovery_point", "Include recovery points where appropriate", 0, AV_OPT_TYPE_CONST, { .i64 = SEI_RECOVERY_POINT }, INT_MIN, INT_MAX, FLAGS, "sei" }, + + { "profile", "Set profile (profile_idc and constraint_set*_flag)", + OFFSET(profile), AV_OPT_TYPE_INT, + { .i64 = FF_PROFILE_H264_HIGH }, 0x0000, 0xffff, FLAGS, "profile" }, + +#define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = value }, 0, 0, FLAGS, "profile" + { PROFILE("constrained_baseline", FF_PROFILE_H264_CONSTRAINED_BASELINE) }, + { PROFILE("main", FF_PROFILE_H264_MAIN) }, + { PROFILE("high", FF_PROFILE_H264_HIGH) }, +#undef PROFILE + + { "level", "Set level (level_idc)", + OFFSET(level), AV_OPT_TYPE_INT, + { .i64 = 51 }, 0x00, 0xff, FLAGS, "level" }, + +#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = value }, 0, 0, FLAGS, "level" + { LEVEL("1", 10) }, + { LEVEL("1.1", 11) }, + { LEVEL("1.2", 12) }, + { LEVEL("1.3", 13) }, + { LEVEL("2", 20) }, + { LEVEL("2.1", 21) }, + { LEVEL("2.2", 22) }, + { LEVEL("3", 30) }, + { LEVEL("3.1", 31) }, + { LEVEL("3.2", 32) }, + { LEVEL("4", 40) }, + { LEVEL("4.1", 41) }, + { LEVEL("4.2", 42) }, + { LEVEL("5", 50) }, + { LEVEL("5.1", 51) }, + { LEVEL("5.2", 52) }, + { LEVEL("6", 60) }, + { LEVEL("6.1", 61) }, + { LEVEL("6.2", 62) }, +#undef LEVEL + { NULL }, }; static const AVCodecDefault vaapi_encode_h264_defaults[] = { - { "profile", "100" }, - { "level", "51" }, { "b", "0" }, { "bf", "2" }, { "g", "120" }, From 71421f382f5c53b1a109489a906a80c1b7e3eed7 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 29 Nov 2017 21:31:53 +0000 Subject: [PATCH 1260/2557] vaapi_h265: Add named options for setting profile and level Also fixes the default, which previously contained a nonsense value. --- libavcodec/vaapi_encode_h265.c | 44 +++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 3ae92a7a09a24..8e98b0230d0f4 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -63,6 +63,8 @@ typedef struct VAAPIEncodeH265Context { typedef struct VAAPIEncodeH265Options { int qp; int aud; + int profile; + int level; } VAAPIEncodeH265Options; @@ -880,10 +882,17 @@ static const VAAPIEncodeType vaapi_encode_type_h265 = { static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx) { - VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Options *opt = + (VAAPIEncodeH265Options*)ctx->codec_options_data; ctx->codec = &vaapi_encode_type_h265; + if (avctx->profile == FF_PROFILE_UNKNOWN) + avctx->profile = opt->profile; + if (avctx->level == FF_LEVEL_UNKNOWN) + avctx->level = opt->level; + switch (avctx->profile) { case FF_PROFILE_HEVC_MAIN: case FF_PROFILE_UNKNOWN: @@ -946,12 +955,41 @@ static const AVOption vaapi_encode_h265_options[] = { { "aud", "Include AUD", OFFSET(aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, + { "profile", "Set profile (general_profile_idc)", + OFFSET(profile), AV_OPT_TYPE_INT, + { .i64 = FF_PROFILE_HEVC_MAIN }, 0x00, 0xff, FLAGS, "profile" }, + +#define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = value }, 0, 0, FLAGS, "profile" + { PROFILE("main", FF_PROFILE_HEVC_MAIN) }, + { PROFILE("main10", FF_PROFILE_HEVC_MAIN_10) }, +#undef PROFILE + + { "level", "Set level (general_level_idc)", + OFFSET(level), AV_OPT_TYPE_INT, + { .i64 = 153 }, 0x00, 0xff, FLAGS, "level" }, + +#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = value }, 0, 0, FLAGS, "level" + { LEVEL("1", 30) }, + { LEVEL("2", 60) }, + { LEVEL("2.1", 63) }, + { LEVEL("3", 90) }, + { LEVEL("3.1", 93) }, + { LEVEL("4", 120) }, + { LEVEL("4.1", 123) }, + { LEVEL("5", 150) }, + { LEVEL("5.1", 153) }, + { LEVEL("5.2", 156) }, + { LEVEL("6", 180) }, + { LEVEL("6.1", 183) }, + { LEVEL("6.2", 186) }, +#undef LEVEL + { NULL }, }; static const AVCodecDefault vaapi_encode_h265_defaults[] = { - { "profile", "1" }, - { "level", "51" }, { "b", "0" }, { "bf", "2" }, { "g", "120" }, From d1266d9fa3e83be98f2638beb528cf50bf78e8a9 Mon Sep 17 00:00:00 2001 From: Jim DeLaHunt Date: Sun, 3 Dec 2017 23:09:02 -0800 Subject: [PATCH 1261/2557] doc/developer: revise mailing list section The Developer Documentation had instructions to subscribe to the ffmpeg-cvslog email list. But that is no longer accurate. For the purposes in this section -- review of patches, discussion of development issues -- ffmpeg_devel is the appropriate email list. Some developers may want to monitor ffmpeg-cvslog, but it is not mandatory. This is v3 of this doc, based on discussion in thread and in response to docs Maintainer comments in . 1. In doc/developer.texi, add a new section about ffmpeg-devel, based on existing text from ffmpeg-cvslog section regarding discussion of patches and of development issues. Reflect wording from discussion at but with copy-editing to make wording more concise. 2. In doc/developer.texi, rewrite the ffmpeg-cvslog section to match the current usage of ffmpeg-cvslog. Some developers choose to follow this list, but it is not mandatory. There are a lot of improvements possible to the Developer Documentation page, beyond this refactoring. However, making those improvements is a much bigger and more difficult task. This change is "low hanging fruit". Signed-off-by: Jim DeLaHunt Signed-off-by: Timothy Gu --- doc/developer.texi | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/doc/developer.texi b/doc/developer.texi index 89124a295ca3d..66b24633063f7 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -380,12 +380,28 @@ always check values read from some untrusted source before using them as array index or other risky things. @section Documentation/Other +@subheading Subscribe to the ffmpeg-devel mailing list. +It is important to be subscribed to the +@uref{https://lists.ffmpeg.org/mailman/listinfo/ffmpeg-devel, ffmpeg-devel} +mailing list. Almost any non-trivial patch is to be sent there for review. +Other developers may have comments about your contribution. We expect you see +those comments, and to improve it if requested. (N.B. Experienced committers +have other channels, and may sometimes skip review for trivial fixes.) Also, +discussion here about bug fixes and FFmpeg improvements by other developers may +be helpful information for you. Finally, by being a list subscriber, your +contribution will be posted immediately to the list, without the moderation +hold which messages from non-subscribers experience. + +However, it is more important to the project that we receive your patch than +that you be subscribed to the ffmpeg-devel list. If you have a patch, and don't +want to subscribe and discuss the patch, then please do send it to the list +anyway. @subheading Subscribe to the ffmpeg-cvslog mailing list. -It is important to do this as the diffs of all commits are sent there and -reviewed by all the other developers. Bugs and possible improvements or -general questions regarding commits are discussed there. We expect you to -react if problems with your code are uncovered. +Diffs of all commits are sent to the +@uref{https://lists.ffmpeg.org/mailman/listinfo/ffmpeg-cvslog, ffmpeg-cvslog} +mailing list. Some developers read this list to review all code base changes +from all sources. Subscribing to this list is not mandatory. @subheading Keep the documentation up to date. Update the documentation if you change behavior or add features. If you are From d3a2100c67a04bf4dfee558b6326e70715424434 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 5 Dec 2017 12:47:47 +0100 Subject: [PATCH 1262/2557] fate/hevc: add skip_loop_filter test Signed-off-by: Michael Niedermayer --- tests/fate/hevc.mak | 3 +++ tests/ref/fate/hevc-skiploopfilter | 14 ++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 tests/ref/fate/hevc-skiploopfilter diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak index 5a3c156ee6f5a..0e8859307d3f2 100644 --- a/tests/fate/hevc.mak +++ b/tests/fate/hevc.mak @@ -239,6 +239,9 @@ fate-hevc-bsf-mp4toannexb: CMD = md5 -i $(TARGET_PATH)/tests/data/hevc-mp4.mov - fate-hevc-bsf-mp4toannexb: CMP = oneline fate-hevc-bsf-mp4toannexb: REF = 1873662a3af1848c37e4eb25722c8df9 +fate-hevc-skiploopfilter: CMD = framemd5 -skip_loop_filter nokey -i $(TARGET_SAMPLES)/hevc-conformance/SAO_D_Samsung_5.bit -sws_flags bitexact +FATE_HEVC += fate-hevc-skiploopfilter + FATE_HEVC-$(call DEMDEC, HEVC, HEVC) += $(FATE_HEVC) # this sample has two stsd entries and needs to reload extradata diff --git a/tests/ref/fate/hevc-skiploopfilter b/tests/ref/fate/hevc-skiploopfilter new file mode 100644 index 0000000000000..9c29909c51735 --- /dev/null +++ b/tests/ref/fate/hevc-skiploopfilter @@ -0,0 +1,14 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 1920x1080 +#sar 0: 0/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 3110400, 076c9288843ef1197a8cbef7f9a13fee +0, 1, 1, 1, 3110400, 6190eeea952805ebde69d22961aaeb45 +0, 2, 2, 1, 3110400, 9aaa5111d5e6b25dcf5ddd19c58f17f7 +0, 3, 3, 1, 3110400, 52a487e5f71b314e33e6632b4496f0a6 +0, 4, 4, 1, 3110400, 13abb1c78313705b57a8298dc1e6c0e2 From c8bd2c7d09bfc71795e91f0a9aeb4b8a6833eff2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 6 Dec 2017 01:03:28 +0100 Subject: [PATCH 1263/2557] tests/fate/mov: Fix fate-mov-invalid-elst-entry-count failure on ARM Signed-off-by: Michael Niedermayer --- tests/fate/mov.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 680baea7734c7..220f99064e18d 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -52,7 +52,7 @@ fate-mov-elst-ends-betn-b-and-i: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/elst_en fate-mov-440hz-10ms: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/440hz-10ms.m4a # Makes sure that we handle invalid edit list entry count correctly. -fate-mov-invalid-elst-entry-count: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/mov/invalid_elst_entry_count.mov +fate-mov-invalid-elst-entry-count: CMD = framemd5 -idct simple -flags +bitexact -i $(TARGET_SAMPLES)/mov/invalid_elst_entry_count.mov # Makes sure that 1st key-frame is picked when, # i) One B-frame between 2 key-frames From 53855e3c040a4a7315f137682a6285729ceddc8e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 3 Dec 2017 11:59:58 +0100 Subject: [PATCH 1264/2557] avfilter: add setrange filter Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/filters.texi | 31 ++++++++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- libavfilter/vf_setparams.c | 83 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_setparams.c diff --git a/Changelog b/Changelog index b00996157cc2a..a1a755737cc28 100644 --- a/Changelog +++ b/Changelog @@ -24,6 +24,7 @@ version : - VAAPI VP8 decoding - AMD AMF H.264 and HEVC encoders - video fillborders filter +- video setrange filter version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index 8bffb708d24dc..0ec7d652a38f6 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -18496,6 +18496,37 @@ asetpts=N/SR/TB @end itemize +@section setrange + +Force color range for the output video frame. + +The @code{setrange} filter marks the color range property for the +output frames. It does not change the input frame, but only sets the +corresponding property, which affects how the frame is treated by +following filters. + +The filter accepts the following options: + +@table @option + +@item range +Available values are: + +@table @samp +@item auto +Keep the same color range property. + +@item unspecified, unknown +Set the color range as unspecified. + +@item limited, tv, mpeg +Set the color range as limited. + +@item full, pc, jpeg +Set the color range as full. +@end table +@end table + @section settb, asettb Set the timebase to use for the output frames timestamps. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 1c0cc1da801da..6b06d57234ed6 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -300,6 +300,7 @@ OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += vf_separatefields.o OBJS-$(CONFIG_SETDAR_FILTER) += vf_aspect.o OBJS-$(CONFIG_SETFIELD_FILTER) += vf_setfield.o OBJS-$(CONFIG_SETPTS_FILTER) += setpts.o +OBJS-$(CONFIG_SETRANGE_FILTER) += vf_setparams.o OBJS-$(CONFIG_SETSAR_FILTER) += vf_aspect.o OBJS-$(CONFIG_SETTB_FILTER) += settb.o OBJS-$(CONFIG_SHOWINFO_FILTER) += vf_showinfo.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index fc212e58db378..707faad777676 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -309,6 +309,7 @@ static void register_all(void) REGISTER_FILTER(SETDAR, setdar, vf); REGISTER_FILTER(SETFIELD, setfield, vf); REGISTER_FILTER(SETPTS, setpts, vf); + REGISTER_FILTER(SETRANGE, setrange, vf); REGISTER_FILTER(SETSAR, setsar, vf); REGISTER_FILTER(SETTB, settb, vf); REGISTER_FILTER(SHOWINFO, showinfo, vf); diff --git a/libavfilter/version.h b/libavfilter/version.h index 6b8110c9de094..b0009e83ea0df 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 6 +#define LIBAVFILTER_VERSION_MINOR 7 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_setparams.c b/libavfilter/vf_setparams.c new file mode 100644 index 0000000000000..8427f98ba824a --- /dev/null +++ b/libavfilter/vf_setparams.c @@ -0,0 +1,83 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/pixfmt.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "internal.h" +#include "video.h" + +typedef struct SetParamsContext { + const AVClass *class; + int color_range; +} SetParamsContext; + +#define OFFSET(x) offsetof(SetParamsContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption setrange_options[] = { + {"range", "select color range", OFFSET(color_range), AV_OPT_TYPE_INT, {.i64=-1},-1, AVCOL_RANGE_NB-1, FLAGS, "range"}, + {"auto", "keep the same color range", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "range"}, + {"unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_UNSPECIFIED}, 0, 0, FLAGS, "range"}, + {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_UNSPECIFIED}, 0, 0, FLAGS, "range"}, + {"limited", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, FLAGS, "range"}, + {"tv", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, FLAGS, "range"}, + {"mpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, FLAGS, "range"}, + {"full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, FLAGS, "range"}, + {"pc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, FLAGS, "range"}, + {"jpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, FLAGS, "range"}, + {NULL} +}; + +AVFILTER_DEFINE_CLASS(setrange); + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + SetParamsContext *s = ctx->priv; + + if (s->color_range >= 0) + frame->color_range = s->color_range; + return ff_filter_frame(ctx->outputs[0], frame); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_setrange = { + .name = "setrange", + .description = NULL_IF_CONFIG_SMALL("Force color range for the output video frame."), + .priv_size = sizeof(SetParamsContext), + .priv_class = &setrange_class, + .inputs = inputs, + .outputs = outputs, +}; From 5a412a5c3cc216ae1d15e6b884bda7214b73a5b0 Mon Sep 17 00:00:00 2001 From: Nikolas Bowe Date: Tue, 5 Dec 2017 15:11:26 -0800 Subject: [PATCH 1265/2557] avcodec/extract_extradata_bsf: Fix leak discovered via fuzzing Signed-off-by: Michael Niedermayer --- libavcodec/extract_extradata_bsf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c index ed6509c681add..d40907a675c55 100644 --- a/libavcodec/extract_extradata_bsf.c +++ b/libavcodec/extract_extradata_bsf.c @@ -78,7 +78,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, ret = ff_h2645_packet_split(&h2645_pkt, pkt->data, pkt->size, ctx, 0, 0, ctx->par_in->codec_id, 1); if (ret < 0) - return ret; + goto fail; for (i = 0; i < h2645_pkt.nb_nals; i++) { H2645NAL *nal = &h2645_pkt.nals[i]; From d6d605eb05c3ca32f591016c345eb2ad9e81c554 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 26 Nov 2017 16:47:26 -0300 Subject: [PATCH 1266/2557] avformat/mux: stop delaying writing the header Every bitstream filter behaves as intended now, so there's no need to wait for the first packet of every stream. Signed-off-by: James Almer --- libavformat/avformat.h | 2 +- libavformat/internal.h | 6 ---- libavformat/mux.c | 52 +++++++--------------------------- libavformat/options_table.h | 2 +- libavformat/tests/fifo_muxer.c | 52 ---------------------------------- tests/ref/fate/fifo-muxer-tst | 1 - tests/ref/fate/rgb24-mkv | 4 +-- 7 files changed, 14 insertions(+), 105 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 322210fae0450..4f2798a871683 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1449,7 +1449,7 @@ typedef struct AVFormatContext { #endif #define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats #define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops. -#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Wait for packet data before writing a header, and add bitstream filters as requested by the muxer +#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Add bitstream filters as requested by the muxer /** * Maximum size of the data read from input for determining diff --git a/libavformat/internal.h b/libavformat/internal.h index fcd47840a5c72..36a57214cede9 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -120,12 +120,6 @@ struct AVFormatInternal { int avoid_negative_ts_use_pts; - /** - * Whether or not a header has already been written - */ - int header_written; - int write_header_ret; - /** * Timestamp of the end of the shortest stream. */ diff --git a/libavformat/mux.c b/libavformat/mux.c index b1244c67f3ba0..effcc1152f78a 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -458,25 +458,6 @@ static void flush_if_needed(AVFormatContext *s) } } -static int write_header_internal(AVFormatContext *s) -{ - if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) - avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER); - if (s->oformat->write_header) { - int ret = s->oformat->write_header(s); - if (ret >= 0 && s->pb && s->pb->error < 0) - ret = s->pb->error; - s->internal->write_header_ret = ret; - if (ret < 0) - return ret; - flush_if_needed(s); - } - s->internal->header_written = 1; - if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) - avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_UNKNOWN); - return 0; -} - int avformat_init_output(AVFormatContext *s, AVDictionary **options) { int ret = 0; @@ -515,11 +496,18 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options) if ((ret = avformat_init_output(s, options)) < 0) return ret; - if (!(s->oformat->check_bitstream && s->flags & AVFMT_FLAG_AUTO_BSF)) { - ret = write_header_internal(s); + if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER); + if (s->oformat->write_header) { + ret = s->oformat->write_header(s); + if (ret >= 0 && s->pb && s->pb->error < 0) + ret = s->pb->error; if (ret < 0) goto fail; + flush_if_needed(s); } + if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_UNKNOWN); if (!s->internal->streams_initialized) { if ((ret = init_pts(s)) < 0) @@ -739,12 +727,6 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) } } - if (!s->internal->header_written) { - ret = s->internal->write_header_ret ? s->internal->write_header_ret : write_header_internal(s); - if (ret < 0) - goto fail; - } - if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) { AVFrame *frame = (AVFrame *)pkt->data; av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE); @@ -760,8 +742,6 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) ret = s->pb->error; } -fail: - if (ret < 0) { pkt->pts = pts_backup; pkt->dts = dts_backup; @@ -894,11 +874,6 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt) if (!pkt) { if (s->oformat->flags & AVFMT_ALLOW_FLUSH) { - if (!s->internal->header_written) { - ret = s->internal->write_header_ret ? s->internal->write_header_ret : write_header_internal(s); - if (ret < 0) - return ret; - } ret = s->oformat->write_packet(s, NULL); flush_if_needed(s); if (ret >= 0 && s->pb && s->pb->error < 0) @@ -1282,14 +1257,8 @@ int av_write_trailer(AVFormatContext *s) goto fail; } - if (!s->internal->header_written) { - ret = s->internal->write_header_ret ? s->internal->write_header_ret : write_header_internal(s); - if (ret < 0) - goto fail; - } - fail: - if (s->internal->header_written && s->oformat->write_trailer) { + if (s->oformat->write_trailer) { if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER); if (ret >= 0) { @@ -1302,7 +1271,6 @@ int av_write_trailer(AVFormatContext *s) if (s->oformat->deinit) s->oformat->deinit(s); - s->internal->header_written = s->internal->initialized = s->internal->streams_initialized = 0; diff --git a/libavformat/options_table.h b/libavformat/options_table.h index b60d031f67e3c..b8fa47c6fd335 100644 --- a/libavformat/options_table.h +++ b/libavformat/options_table.h @@ -57,7 +57,7 @@ static const AVOption avformat_options[] = { {"seek2any", "allow seeking to non-keyframes on demuxer level when supported", OFFSET(seek2any), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, D}, {"bitexact", "do not write random/volatile data", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_BITEXACT }, 0, 0, E, "fflags" }, {"shortest", "stop muxing with the shortest stream", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_SHORTEST }, 0, 0, E, "fflags" }, -{"autobsf", "add needed bsfs automatically (delays header until each stream's first packet is written)", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_AUTO_BSF }, 0, 0, E, "fflags" }, +{"autobsf", "add needed bsfs automatically", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_AUTO_BSF }, 0, 0, E, "fflags" }, {"analyzeduration", "specify how many microseconds are analyzed to probe the input", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, D}, {"cryptokey", "decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D}, {"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), AV_OPT_TYPE_INT, {.i64 = 1<<20 }, 0, INT_MAX, D}, diff --git a/libavformat/tests/fifo_muxer.c b/libavformat/tests/fifo_muxer.c index e20bd6e7b2b1c..4b63df085e2b3 100644 --- a/libavformat/tests/fifo_muxer.c +++ b/libavformat/tests/fifo_muxer.c @@ -238,54 +238,6 @@ static int fifo_basic_test(AVFormatContext *oc, AVDictionary **opts, return ret; } -static int fifo_write_header_err_tst(AVFormatContext *oc, AVDictionary **opts, - const FailingMuxerPacketData *pkt_data) -{ - int ret = 0, i; - AVPacket pkt; - - av_init_packet(&pkt); - - ret = avformat_write_header(oc, opts); - if (ret) { - fprintf(stderr, "Unexpected write_header failure: %s\n", - av_err2str(ret)); - goto fail; - } - - for (i = 0; i < MAX_TST_PACKETS; i++ ) { - ret = prepare_packet(&pkt, pkt_data, i); - if (ret < 0) { - fprintf(stderr, "Failed to prepare test packet: %s\n", - av_err2str(ret)); - goto write_trailer_and_fail; - } - ret = av_write_frame(oc, &pkt); - av_packet_unref(&pkt); - if (ret < 0) { - break; - } - } - - if (!ret) { - fprintf(stderr, "write_packet not failed when supposed to.\n"); - goto fail; - } else if (ret != -1) { - fprintf(stderr, "Unexpected write_packet error: %s\n", av_err2str(ret)); - goto fail; - } - - ret = av_write_trailer(oc); - if (ret < 0) - fprintf(stderr, "Unexpected write_trailer error: %s\n", av_err2str(ret)); - - return ret; -write_trailer_and_fail: - av_write_trailer(oc); -fail: - return ret; -} - static int fifo_overflow_drop_test(AVFormatContext *oc, AVDictionary **opts, const FailingMuxerPacketData *data) { @@ -403,10 +355,6 @@ const TestCase tests[] = { * exactly what was on input */ {fifo_basic_test, "nonfail test", NULL,1, 0, 0, {0, 0, 0}}, - /* Test that we receive delayed write_header error from one of the write_packet - * calls. */ - {fifo_write_header_err_tst, "write header error test", NULL, 0, -1, 0, {0, 0, 0}}, - /* Each write_packet will fail 3 times before operation is successful. If recovery * Since recovery is on, fifo muxer should not return any errors. */ {fifo_basic_test, "recovery test", "attempt_recovery=1:recovery_wait_time=0", diff --git a/tests/ref/fate/fifo-muxer-tst b/tests/ref/fate/fifo-muxer-tst index ca7e294860eac..e1139ee0a81c0 100644 --- a/tests/ref/fate/fifo-muxer-tst +++ b/tests/ref/fate/fifo-muxer-tst @@ -2,7 +2,6 @@ flush count: 1 pts seen nr: 15 pts seen: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 nonfail test: ok -write header error test: ok recovery test: ok flush count: 1 pts seen nr: 15 diff --git a/tests/ref/fate/rgb24-mkv b/tests/ref/fate/rgb24-mkv index 4c357accaf2b7..439b2bc5e91e8 100644 --- a/tests/ref/fate/rgb24-mkv +++ b/tests/ref/fate/rgb24-mkv @@ -1,5 +1,5 @@ -55270be3b5d393d770a1dfcb19b68271 *tests/data/fate/rgb24-mkv.matroska -58345 tests/data/fate/rgb24-mkv.matroska +09ee413b2d92a6be5e3b18e9e20a1f74 *tests/data/fate/rgb24-mkv.matroska +58342 tests/data/fate/rgb24-mkv.matroska #tb 0: 1/10 #media_type 0: video #codec_id 0: rawvideo From 5e9a13a5a33bf7566591216e335f2529612100bb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 2 Dec 2017 21:48:04 +0100 Subject: [PATCH 1267/2557] avcodec/dirac_dwt: Fix integer overflows in COMPOSE_DAUB97* Fixes: 4478/clusterfuzz-testcase-minimized-4752113767809024 Fixes: runtime error: signed integer overflow: -2147483626 + -319489 cannot be represented in type 'int' Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/dirac_dwt.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/dirac_dwt.h b/libavcodec/dirac_dwt.h index eb5aebc878af5..50c8b1e394649 100644 --- a/libavcodec/dirac_dwt.h +++ b/libavcodec/dirac_dwt.h @@ -117,16 +117,16 @@ void ff_spatial_idwt_slice2(DWTContext *d, int y); ((unsigned)b4 + ((int)(-2*(b0+(unsigned)b8) + 10*(b1+(unsigned)b7) - 25*(b2+(unsigned)b6) + 81*(b3+(unsigned)b5) + 128) >> 8)) #define COMPOSE_DAUB97iL1(b0, b1, b2)\ - (b1 - ((int)(1817*(b0 + (unsigned)b2) + 2048) >> 12)) + ((unsigned)(b1) - ((int)(1817*(b0 + (unsigned)b2) + 2048) >> 12)) #define COMPOSE_DAUB97iH1(b0, b1, b2)\ - (b1 - ((int)( 113*(b0 + (unsigned)b2) + 64) >> 7)) + ((unsigned)(b1) - ((int)( 113*(b0 + (unsigned)b2) + 64) >> 7)) #define COMPOSE_DAUB97iL0(b0, b1, b2)\ - (b1 + ((int)( 217*(b0 + (unsigned)b2) + 2048) >> 12)) + ((unsigned)(b1) + ((int)( 217*(b0 + (unsigned)b2) + 2048) >> 12)) #define COMPOSE_DAUB97iH0(b0, b1, b2)\ - (b1 + ((int)(6497*(b0 + (unsigned)b2) + 2048) >> 12)) + ((unsigned)(b1) + ((int)(6497*(b0 + (unsigned)b2) + 2048) >> 12)) #endif /* AVCODEC_DWT_H */ From 610dd74502a58e8bb0f1d8fcbc7015f86b78d70e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 2 Dec 2017 21:53:22 +0100 Subject: [PATCH 1268/2557] avcodec/diracdsp: Fix integer overflow in PUT_SIGNED_RECT_CLAMPED() Fixes: runtime error: signed integer overflow: 2147483646 + 2048 cannot be represented in type 'int' Fixes: 4479/clusterfuzz-testcase-minimized-6529894147162112 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/diracdsp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/diracdsp.c b/libavcodec/diracdsp.c index 8bc79b788ce6c..2dd56f83f33ce 100644 --- a/libavcodec/diracdsp.c +++ b/libavcodec/diracdsp.c @@ -159,10 +159,10 @@ static void put_signed_rect_clamped_ ## PX ## bit_c(uint8_t *_dst, int dst_strid int32_t *src = (int32_t *)_src; \ for (y = 0; y < height; y++) { \ for (x = 0; x < width; x+=4) { \ - dst[x ] = av_clip_uintp2(src[x ] + (1 << (PX - 1)), PX); \ - dst[x+1] = av_clip_uintp2(src[x+1] + (1 << (PX - 1)), PX); \ - dst[x+2] = av_clip_uintp2(src[x+2] + (1 << (PX - 1)), PX); \ - dst[x+3] = av_clip_uintp2(src[x+3] + (1 << (PX - 1)), PX); \ + dst[x ] = av_clip_uintp2(src[x ] + (1U << (PX - 1)), PX); \ + dst[x+1] = av_clip_uintp2(src[x+1] + (1U << (PX - 1)), PX); \ + dst[x+2] = av_clip_uintp2(src[x+2] + (1U << (PX - 1)), PX); \ + dst[x+3] = av_clip_uintp2(src[x+3] + (1U << (PX - 1)), PX); \ } \ dst += dst_stride >> 1; \ src += src_stride >> 2; \ From dc7d5f9f1904faebab73f5de60f2c360c8255333 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Tue, 5 Dec 2017 13:17:53 +0530 Subject: [PATCH 1269/2557] avcodec/libx265 - Add named option to set profile Adds call to x265_param_apply_profile after x265_param_parse. Added as private option since HEVC profiles other than Main, Main 10 and MSP in AVCodecContext are consolidated in a single constant. Reviewed-by: Hendrik Leppkes Reviewed-by: Derek Buitenhuis Reviewed-by: Lou Logan --- libavcodec/libx265.c | 14 ++++++++++++++ libavcodec/version.h | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 4456e300f2e4d..cbb106aeed8d8 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -45,6 +45,7 @@ typedef struct libx265Context { int forced_idr; char *preset; char *tune; + char *profile; char *x265_opts; } libx265Context; @@ -220,6 +221,18 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) } } + if (ctx->profile) { + if (ctx->api->param_apply_profile(ctx->params, ctx->profile) < 0) { + int i; + av_log(avctx, AV_LOG_ERROR, "Invalid or incompatible profile set: %s.\n", ctx->profile); + av_log(avctx, AV_LOG_INFO, "Possible profiles:"); + for (i = 0; x265_profile_names[i]; i++) + av_log(avctx, AV_LOG_INFO, " %s", x265_profile_names[i]); + av_log(avctx, AV_LOG_INFO, "\n"); + return AVERROR(EINVAL); + } + } + ctx->encoder = ctx->api->encoder_open(ctx->params); if (!ctx->encoder) { av_log(avctx, AV_LOG_ERROR, "Cannot open libx265 encoder.\n"); @@ -392,6 +405,7 @@ static const AVOption options[] = { { "forced-idr", "if forcing keyframes, force them as IDR frames", OFFSET(forced_idr),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "preset", "set the x265 preset", OFFSET(preset), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { "tune", "set the x265 tune parameter", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, + { "profile", "set the x265 profile", OFFSET(profile), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { "x265-params", "set the x265 configuration using a :-separated list of key=value parameters", OFFSET(x265_opts), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { NULL } }; diff --git a/libavcodec/version.h b/libavcodec/version.h index d67b689142f70..3b5c3000becd0 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 6 -#define LIBAVCODEC_VERSION_MICRO 102 +#define LIBAVCODEC_VERSION_MICRO 103 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 6679654efe15af7156a94e9abc754098dfccd10e Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 29 Nov 2017 21:31:11 +0000 Subject: [PATCH 1270/2557] vaapi_h264: Add named options for setting profile and level --- libavcodec/vaapi_encode_h264.c | 48 ++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index e6a166698ba0b..6b47d932b6d70 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -91,6 +91,8 @@ typedef struct VAAPIEncodeH264Options { int low_power; int aud; int sei; + int profile; + int level; } VAAPIEncodeH264Options; @@ -882,6 +884,11 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx) ctx->codec = &vaapi_encode_type_h264; + if (avctx->profile == FF_PROFILE_UNKNOWN) + avctx->profile = opt->profile; + if (avctx->level == FF_LEVEL_UNKNOWN) + avctx->level = opt->level; + switch (avctx->profile) { case FF_PROFILE_H264_BASELINE: av_log(avctx, AV_LOG_WARNING, "H.264 baseline profile is not " @@ -995,12 +1002,49 @@ static const AVOption vaapi_encode_h264_options[] = { { "recovery_point", "Include recovery points where appropriate", 0, AV_OPT_TYPE_CONST, { .i64 = SEI_RECOVERY_POINT }, INT_MIN, INT_MAX, FLAGS, "sei" }, + + { "profile", "Set profile (profile_idc and constraint_set*_flag)", + OFFSET(profile), AV_OPT_TYPE_INT, + { .i64 = FF_PROFILE_H264_HIGH }, 0x0000, 0xffff, FLAGS, "profile" }, + +#define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = value }, 0, 0, FLAGS, "profile" + { PROFILE("constrained_baseline", FF_PROFILE_H264_CONSTRAINED_BASELINE) }, + { PROFILE("main", FF_PROFILE_H264_MAIN) }, + { PROFILE("high", FF_PROFILE_H264_HIGH) }, +#undef PROFILE + + { "level", "Set level (level_idc)", + OFFSET(level), AV_OPT_TYPE_INT, + { .i64 = 51 }, 0x00, 0xff, FLAGS, "level" }, + +#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = value }, 0, 0, FLAGS, "level" + { LEVEL("1", 10) }, + { LEVEL("1.1", 11) }, + { LEVEL("1.2", 12) }, + { LEVEL("1.3", 13) }, + { LEVEL("2", 20) }, + { LEVEL("2.1", 21) }, + { LEVEL("2.2", 22) }, + { LEVEL("3", 30) }, + { LEVEL("3.1", 31) }, + { LEVEL("3.2", 32) }, + { LEVEL("4", 40) }, + { LEVEL("4.1", 41) }, + { LEVEL("4.2", 42) }, + { LEVEL("5", 50) }, + { LEVEL("5.1", 51) }, + { LEVEL("5.2", 52) }, + { LEVEL("6", 60) }, + { LEVEL("6.1", 61) }, + { LEVEL("6.2", 62) }, +#undef LEVEL + { NULL }, }; static const AVCodecDefault vaapi_encode_h264_defaults[] = { - { "profile", "100" }, - { "level", "51" }, { "b", "0" }, { "bf", "2" }, { "g", "120" }, From 3ff8fbbf5a7bc40c09db74d4952364997fd3c611 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 29 Nov 2017 21:31:53 +0000 Subject: [PATCH 1271/2557] vaapi_h265: Add named options for setting profile and level Also fixes the default, which previously contained a nonsense value. --- libavcodec/vaapi_encode_h265.c | 44 +++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 0e5958d5315e1..8fa277bf94e5a 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -63,6 +63,8 @@ typedef struct VAAPIEncodeH265Context { typedef struct VAAPIEncodeH265Options { int qp; int aud; + int profile; + int level; } VAAPIEncodeH265Options; @@ -880,10 +882,17 @@ static const VAAPIEncodeType vaapi_encode_type_h265 = { static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx) { - VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Options *opt = + (VAAPIEncodeH265Options*)ctx->codec_options_data; ctx->codec = &vaapi_encode_type_h265; + if (avctx->profile == FF_PROFILE_UNKNOWN) + avctx->profile = opt->profile; + if (avctx->level == FF_LEVEL_UNKNOWN) + avctx->level = opt->level; + switch (avctx->profile) { case FF_PROFILE_HEVC_MAIN: case FF_PROFILE_UNKNOWN: @@ -946,12 +955,41 @@ static const AVOption vaapi_encode_h265_options[] = { { "aud", "Include AUD", OFFSET(aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, + { "profile", "Set profile (general_profile_idc)", + OFFSET(profile), AV_OPT_TYPE_INT, + { .i64 = FF_PROFILE_HEVC_MAIN }, 0x00, 0xff, FLAGS, "profile" }, + +#define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = value }, 0, 0, FLAGS, "profile" + { PROFILE("main", FF_PROFILE_HEVC_MAIN) }, + { PROFILE("main10", FF_PROFILE_HEVC_MAIN_10) }, +#undef PROFILE + + { "level", "Set level (general_level_idc)", + OFFSET(level), AV_OPT_TYPE_INT, + { .i64 = 153 }, 0x00, 0xff, FLAGS, "level" }, + +#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = value }, 0, 0, FLAGS, "level" + { LEVEL("1", 30) }, + { LEVEL("2", 60) }, + { LEVEL("2.1", 63) }, + { LEVEL("3", 90) }, + { LEVEL("3.1", 93) }, + { LEVEL("4", 120) }, + { LEVEL("4.1", 123) }, + { LEVEL("5", 150) }, + { LEVEL("5.1", 153) }, + { LEVEL("5.2", 156) }, + { LEVEL("6", 180) }, + { LEVEL("6.1", 183) }, + { LEVEL("6.2", 186) }, +#undef LEVEL + { NULL }, }; static const AVCodecDefault vaapi_encode_h265_defaults[] = { - { "profile", "1" }, - { "level", "51" }, { "b", "0" }, { "bf", "2" }, { "g", "120" }, From 79a744768aa6f498e4f46fca4ff01cd04eade9a5 Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Tue, 5 Dec 2017 16:36:58 -0800 Subject: [PATCH 1272/2557] lavc/libx265: mark disposable frames Used by movenc to fill sdtp box Signed-off-by: Michael Niedermayer --- libavcodec/libx265.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index cbb106aeed8d8..25ccb02fcb6b8 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -342,6 +342,13 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif +#if X265_BUILD >= 130 + if (x265pic_out.sliceType == X265_TYPE_B) +#else + if (x265pic_out.frameData.sliceType == 'b') +#endif + pkt->flags |= AV_PKT_FLAG_DISPOSABLE; + *got_packet = 1; return 0; } From dc33fe1d0080e932faa9fe3c7fb4850dfde161a8 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 7 Dec 2017 18:09:00 -0300 Subject: [PATCH 1273/2557] x86/vf_hflip: don't load the width argument twice Signed-off-by: James Almer --- libavfilter/x86/vf_hflip.asm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavfilter/x86/vf_hflip.asm b/libavfilter/x86/vf_hflip.asm index d14cc086e564c..9f262ece5c0d0 100644 --- a/libavfilter/x86/vf_hflip.asm +++ b/libavfilter/x86/vf_hflip.asm @@ -33,7 +33,7 @@ INIT_XMM ssse3 cglobal hflip_byte, 3, 5, 3, src, dst, w, r, x mova m0, [pb_flip_byte] mov xq, 0 - mov wd, dword wm + movsxdifnidn wq, wd mov rq, wq and rq, 2 * mmsize - 1 cmp wq, 2 * mmsize @@ -71,8 +71,7 @@ RET cglobal hflip_short, 3, 5, 3, src, dst, w, r, x mova m0, [pb_flip_short] mov xq, 0 - mov wd, dword wm - add wq, wq + add wd, wd mov rq, wq and rq, 2 * mmsize - 1 cmp wq, 2 * mmsize From f2aa0ce5a059cf02ee4cbd68111dd2ad622edc85 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 7 Dec 2017 19:28:19 -0300 Subject: [PATCH 1274/2557] x86/vf_hflip: use xor to zero initialize registers Signed-off-by: James Almer --- libavfilter/x86/vf_hflip.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/x86/vf_hflip.asm b/libavfilter/x86/vf_hflip.asm index 9f262ece5c0d0..89d6d0c69bb1f 100644 --- a/libavfilter/x86/vf_hflip.asm +++ b/libavfilter/x86/vf_hflip.asm @@ -32,7 +32,7 @@ SECTION .text INIT_XMM ssse3 cglobal hflip_byte, 3, 5, 3, src, dst, w, r, x mova m0, [pb_flip_byte] - mov xq, 0 + xor xq, xq movsxdifnidn wq, wd mov rq, wq and rq, 2 * mmsize - 1 @@ -70,7 +70,7 @@ RET cglobal hflip_short, 3, 5, 3, src, dst, w, r, x mova m0, [pb_flip_short] - mov xq, 0 + xor xq, xq add wd, wd mov rq, wq and rq, 2 * mmsize - 1 From c67c7191b1c2fa0ff0a9785f52e86a5cdfc1d36f Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Tue, 5 Dec 2017 02:03:15 +0000 Subject: [PATCH 1275/2557] fate-opus: run and test inactive samples Signed-off-by: Rostislav Pehlivanov --- tests/fate/opus.mak | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/fate/opus.mak b/tests/fate/opus.mak index 36221ec26587f..9e0c9e6bba12f 100644 --- a/tests/fate/opus.mak +++ b/tests/fate/opus.mak @@ -2,10 +2,10 @@ # their custom format into Matroska. The reference decoded outputs are from the # newest testvectors file from RFC8251 -OPUS_CELT_SAMPLES = $(addprefix testvector, 11) tron.6ch.tinypkts +OPUS_CELT_SAMPLES = $(addprefix testvector, 01 11) tron.6ch.tinypkts OPUS_HYBRID_SAMPLES = $(addprefix testvector, 05 06) OPUS_SILK_SAMPLES = $(addprefix testvector, 02 03 04) -OPUS_SAMPLES = $(addprefix testvector, 08 10 12) +OPUS_SAMPLES = $(addprefix testvector, 07 08 09 10 12) define FATE_OPUS_TEST FATE_OPUS += fate-opus-$(1) @@ -24,13 +24,17 @@ FATE_OPUS := $(sort $(FATE_OPUS)) $(FATE_OPUS): CMP = stddev $(FATE_OPUS): CMP_UNIT = s16 $(FATE_OPUS): FUZZ = 3 +fate-opus-testvector01: CMP_TARGET = 0 fate-opus-testvector02: CMP_TARGET = 191 fate-opus-testvector03: CMP_TARGET = 139 fate-opus-testvector04: CMP_TARGET = 119 fate-opus-testvector05: CMP_TARGET = 109 fate-opus-testvector06: CMP_TARGET = 109 +fate-opus-testvector07: CMP_TARGET = 0 fate-opus-testvector08: CMP_TARGET = 6 +fate-opus-testvector09: CMP_TARGET = 0 fate-opus-testvector10: CMP_TARGET = 38 +fate-opus-testvector11: CMP_TARGET = 0 fate-opus-testvector12: CMP_TARGET = 160 $(FATE_OPUS_CELT): CMP = oneoff From 4678339e745dac8fa4288541b79f1577f19bb4c2 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Fri, 8 Dec 2017 03:40:41 +0000 Subject: [PATCH 1276/2557] opus: fix hybrid folding indexing during band quantization Resulted in valgrind errors due to uninitialized memory. Also updates fate and makes it use the tron sample result. Signed-off-by: Rostislav Pehlivanov --- libavcodec/opus.c | 7 +++---- tests/fate/opus.mak | 25 +++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/libavcodec/opus.c b/libavcodec/opus.c index b791d749b4311..46b749cae67c8 100644 --- a/libavcodec/opus.c +++ b/libavcodec/opus.c @@ -481,13 +481,12 @@ void ff_celt_quant_bands(CeltFrame *f, OpusRangeCoder *rc) if (i == f->start_band + 1) { /* Special Hybrid Folding (RFC 8251 section 9). Copy the first band into the second to ensure the second band never has to use the LCG. */ - int offset = 8 * ff_celt_freq_bands[i]; - int count = 8 * (ff_celt_freq_range[i] - ff_celt_freq_range[i-1]); + int count = (ff_celt_freq_range[i] - ff_celt_freq_range[i-1]) << f->size; - memcpy(&norm1[offset], &norm1[offset - count], count * sizeof(float)); + memcpy(&norm1[band_offset], &norm1[band_offset - count], count * sizeof(float)); if (f->channels == 2) - memcpy(&norm2[offset], &norm2[offset - count], count * sizeof(float)); + memcpy(&norm2[band_offset], &norm2[band_offset - count], count * sizeof(float)); } /* Get a conservative estimate of the collapse_mask's for the bands we're diff --git a/tests/fate/opus.mak b/tests/fate/opus.mak index 9e0c9e6bba12f..7f289455cf5d8 100644 --- a/tests/fate/opus.mak +++ b/tests/fate/opus.mak @@ -24,18 +24,19 @@ FATE_OPUS := $(sort $(FATE_OPUS)) $(FATE_OPUS): CMP = stddev $(FATE_OPUS): CMP_UNIT = s16 $(FATE_OPUS): FUZZ = 3 -fate-opus-testvector01: CMP_TARGET = 0 -fate-opus-testvector02: CMP_TARGET = 191 -fate-opus-testvector03: CMP_TARGET = 139 -fate-opus-testvector04: CMP_TARGET = 119 -fate-opus-testvector05: CMP_TARGET = 109 -fate-opus-testvector06: CMP_TARGET = 109 -fate-opus-testvector07: CMP_TARGET = 0 -fate-opus-testvector08: CMP_TARGET = 6 -fate-opus-testvector09: CMP_TARGET = 0 -fate-opus-testvector10: CMP_TARGET = 38 -fate-opus-testvector11: CMP_TARGET = 0 -fate-opus-testvector12: CMP_TARGET = 160 +fate-opus-testvector01: CMP_TARGET = 0 +fate-opus-testvector02: CMP_TARGET = 191 +fate-opus-testvector03: CMP_TARGET = 139 +fate-opus-testvector04: CMP_TARGET = 119 +fate-opus-testvector05: CMP_TARGET = 108 +fate-opus-testvector06: CMP_TARGET = 106 +fate-opus-testvector07: CMP_TARGET = 0 +fate-opus-testvector08: CMP_TARGET = 6 +fate-opus-testvector09: CMP_TARGET = 0 +fate-opus-testvector10: CMP_TARGET = 38 +fate-opus-testvector11: CMP_TARGET = 0 +fate-opus-testvector12: CMP_TARGET = 160 +fate-opus-tron.6ch.tinypkts: CMP_TARGET = 0 $(FATE_OPUS_CELT): CMP = oneoff $(FATE_OPUS_CELT): FUZZ = 6 From 299a6222976646f27a83773f40bc9668f96e6828 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 8 Dec 2017 12:31:01 +0100 Subject: [PATCH 1277/2557] avfilter/vf_waveform: add default case when picking input formats Should silence compiler warnings. Signed-off-by: Paul B Mahol --- libavfilter/vf_waveform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vf_waveform.c b/libavfilter/vf_waveform.c index 0c574742a0a4d..02a7046f33d43 100644 --- a/libavfilter/vf_waveform.c +++ b/libavfilter/vf_waveform.c @@ -295,6 +295,7 @@ static int query_formats(AVFilterContext *ctx) case FLAT: in_pix_fmts = in_flat_pix_fmts; break; case ACOLOR: case COLOR: in_pix_fmts = in_color_pix_fmts; break; + default: return AVERROR_BUG; } if (!ctx->inputs[0]->out_formats) { From a41a5db797660b3a2d24ff3516ae2e07b0f55678 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 1 Dec 2017 15:15:13 +0100 Subject: [PATCH 1278/2557] avformat: add NSP demuxer Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/general.texi | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/nspdec.c | 108 +++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 4 +- 6 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 libavformat/nspdec.c diff --git a/Changelog b/Changelog index a1a755737cc28..d60cf7b03d8f7 100644 --- a/Changelog +++ b/Changelog @@ -25,6 +25,7 @@ version : - AMD AMF H.264 and HEVC encoders - video fillborders filter - video setrange filter +- nsp demuxer version 3.4: diff --git a/doc/general.texi b/doc/general.texi index efd4a92495e32..26919c9287c9c 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -425,6 +425,7 @@ library: @item NC camera feed @tab @tab X @tab NC (AVIP NC4600) camera streams @item NIST SPeech HEader REsources @tab @tab X +@item Computerized Speech Lab NSP @tab @tab X @item NTT TwinVQ (VQF) @tab @tab X @tab Nippon Telegraph and Telephone Corporation TwinVQ. @item Nullsoft Streaming Video @tab @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index 4bffdf2205a90..734b7038627cc 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -331,6 +331,7 @@ OBJS-$(CONFIG_MXF_MUXER) += mxfenc.o mxf.o audiointerleave.o OBJS-$(CONFIG_MXG_DEMUXER) += mxg.o OBJS-$(CONFIG_NC_DEMUXER) += ncdec.o OBJS-$(CONFIG_NISTSPHERE_DEMUXER) += nistspheredec.o pcm.o +OBJS-$(CONFIG_NSP_DEMUXER) += nspdec.o OBJS-$(CONFIG_NSV_DEMUXER) += nsvdec.o OBJS-$(CONFIG_NULL_MUXER) += nullenc.o OBJS-$(CONFIG_NUT_DEMUXER) += nutdec.o nut.o isom.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 9213af9301fa5..6a9b9883c97f1 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -224,6 +224,7 @@ static void register_all(void) REGISTER_DEMUXER (MXG, mxg); REGISTER_DEMUXER (NC, nc); REGISTER_DEMUXER (NISTSPHERE, nistsphere); + REGISTER_DEMUXER (NSP, nsp); REGISTER_DEMUXER (NSV, nsv); REGISTER_MUXER (NULL, null); REGISTER_MUXDEMUX(NUT, nut); diff --git a/libavformat/nspdec.c b/libavformat/nspdec.c new file mode 100644 index 0000000000000..34c747b65ea8a --- /dev/null +++ b/libavformat/nspdec.c @@ -0,0 +1,108 @@ +/* + * NSP demuxer + * Copyright (c) 2017 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "internal.h" +#include "pcm.h" + +static int nsp_probe(AVProbeData *p) +{ + if (AV_RB32(p->buf) == AV_RB32("FORM") && + AV_RB32(p->buf + 4) == AV_RB32("DS16")) + return AVPROBE_SCORE_MAX; + return 0; +} + +static int nsp_read_header(AVFormatContext *s) +{ + int channels = 0, rate = 0; + uint32_t chunk, size; + AVStream *st; + int64_t pos; + + avio_skip(s->pb, 12); + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + while (!avio_feof(s->pb)) { + char value[1024]; + + chunk = avio_rb32(s->pb); + size = avio_rl32(s->pb); + pos = avio_tell(s->pb); + + switch (chunk) { + case MKBETAG('H', 'E', 'D', 'R'): + case MKBETAG('H', 'D', 'R', '8'): + if (size < 32) + return AVERROR_INVALIDDATA; + avio_skip(s->pb, 20); + rate = avio_rl32(s->pb); + avio_skip(s->pb, size - (avio_tell(s->pb) - pos)); + break; + case MKBETAG('N', 'O', 'T', 'E'): + avio_get_str(s->pb, size, value, sizeof(value)); + av_dict_set(&s->metadata, "Comment", value, 0); + avio_skip(s->pb, size & 1); + break; + case MKBETAG('S', 'D', 'A', 'B'): + channels = 2; + break; + case MKBETAG('S', 'D', '_', '2'): + case MKBETAG('S', 'D', '_', '3'): + case MKBETAG('S', 'D', '_', '4'): + case MKBETAG('S', 'D', '_', '5'): + case MKBETAG('S', 'D', '_', '6'): + case MKBETAG('S', 'D', '_', '7'): + case MKBETAG('S', 'D', '_', '8'): + av_log(s, AV_LOG_WARNING, "Unsupported chunk!\n"); + case MKBETAG('S', 'D', 'A', '_'): + case MKBETAG('S', 'D', '_', 'A'): + channels = 1; + break; + } + + if (channels) + break; + } + + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->channels = channels; + st->codecpar->sample_rate = rate; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; + st->codecpar->block_align = 2 * channels; + + return 0; +} + +AVInputFormat ff_nsp_demuxer = { + .name = "nsp", + .long_name = NULL_IF_CONFIG_SMALL("Computerized Speech Lab NSP"), + .read_probe = nsp_probe, + .read_header = nsp_read_header, + .read_packet = ff_pcm_read_packet, + .read_seek = ff_pcm_read_seek, + .extensions = "nsp", + .flags = AVFMT_GENERIC_INDEX, +}; diff --git a/libavformat/version.h b/libavformat/version.h index 7fe3710a2c741..5ced041f0a433 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,8 +32,8 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 2 -#define LIBAVFORMAT_VERSION_MICRO 103 +#define LIBAVFORMAT_VERSION_MINOR 3 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From bc38c8f4424982617a92d1cefa7fdcb640a80234 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Thu, 7 Dec 2017 16:32:22 -0500 Subject: [PATCH 1279/2557] vf_zscale: Fix alpha destination graph for floating point pixel formats This was setting the input pixel type instead of the output one, leading to incorrect data being fed to the library. Signed-off-by: Vittorio Giovara --- libavfilter/vf_zscale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_zscale.c b/libavfilter/vf_zscale.c index 865910bd876f4..6e1d36cb4cf23 100644 --- a/libavfilter/vf_zscale.c +++ b/libavfilter/vf_zscale.c @@ -615,7 +615,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) s->alpha_dst_format.width = out->width; s->alpha_dst_format.height = out->height; s->alpha_dst_format.depth = odesc->comp[0].depth; - s->alpha_dst_format.pixel_type = (desc->flags & AV_PIX_FMT_FLAG_FLOAT) ? ZIMG_PIXEL_FLOAT : odesc->comp[0].depth > 8 ? ZIMG_PIXEL_WORD : ZIMG_PIXEL_BYTE; + s->alpha_dst_format.pixel_type = (odesc->flags & AV_PIX_FMT_FLAG_FLOAT) ? ZIMG_PIXEL_FLOAT : odesc->comp[0].depth > 8 ? ZIMG_PIXEL_WORD : ZIMG_PIXEL_BYTE; s->alpha_dst_format.color_family = ZIMG_COLOR_GREY; zimg_filter_graph_free(s->alpha_graph); From 2fdc9f7c4939f83a6c9d1f9d85b6d37ce0bab714 Mon Sep 17 00:00:00 2001 From: Jacob Trimble Date: Thu, 30 Nov 2017 12:35:50 -0800 Subject: [PATCH 1280/2557] avcodec/nvdec: Fix capability check with old drivers. Copied the check from cuviddec.c (*_cuvid decoders) to allow the capability check to be optional for older drivers. Signed-off-by: Jacob Trimble Signed-off-by: Timo Rothenpieler --- libavcodec/nvdec.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index c7a02ff40f616..e9e6ea0f8b9d0 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -91,6 +91,18 @@ static int nvdec_test_capabilities(NVDECDecoder *decoder, caps.eChromaFormat = params->ChromaFormat; caps.nBitDepthMinus8 = params->bitDepthMinus8; + if (!decoder->cvdl->cuvidGetDecoderCaps) { + av_log(logctx, AV_LOG_WARNING, "Used Nvidia driver is too old to perform a capability check.\n"); + av_log(logctx, AV_LOG_WARNING, "The minimum required version is " +#if defined(_WIN32) || defined(__CYGWIN__) + "378.66" +#else + "378.13" +#endif + ". Continuing blind.\n"); + return 0; + } + err = decoder->cvdl->cuvidGetDecoderCaps(&caps); if (err != CUDA_SUCCESS) { av_log(logctx, AV_LOG_ERROR, "Failed querying decoder capabilities\n"); From a428f2fcd95906cdfca1eff574369fb32169317e Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 7 Dec 2017 20:37:48 +0100 Subject: [PATCH 1281/2557] libavcodec/hevc_filter: move AVDISCARD_NONREF switch-case into function In preparation for implementation of skip_frame. Signed-off-by: Michael Niedermayer --- libavcodec/hevc_filter.c | 20 +++----------------- libavcodec/hevcdec.h | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c index 94fb7cd3d16e1..6b9824088c3ce 100644 --- a/libavcodec/hevc_filter.c +++ b/libavcodec/hevc_filter.c @@ -842,29 +842,15 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size) { int x_end = x >= s->ps.sps->width - ctb_size; - int skip = 0, is_n = 0; - switch (s->nal_unit_type) { - case HEVC_NAL_TRAIL_N: - case HEVC_NAL_TSA_N: - case HEVC_NAL_STSA_N: - case HEVC_NAL_RADL_N: - case HEVC_NAL_RASL_N: - case HEVC_NAL_VCL_N10: - case HEVC_NAL_VCL_N12: - case HEVC_NAL_VCL_N14: - case HEVC_NAL_BLA_N_LP: - case HEVC_NAL_IDR_N_LP: - is_n = 1; - break; - default: break; - } + int skip = 0; if (s->avctx->skip_loop_filter >= AVDISCARD_ALL || (s->avctx->skip_loop_filter >= AVDISCARD_NONKEY && !IS_IDR(s)) || (s->avctx->skip_loop_filter >= AVDISCARD_NONINTRA && s->sh.slice_type != HEVC_SLICE_I) || (s->avctx->skip_loop_filter >= AVDISCARD_BIDIR && s->sh.slice_type == HEVC_SLICE_B) || - (s->avctx->skip_loop_filter >= AVDISCARD_NONREF && is_n)) + (s->avctx->skip_loop_filter >= AVDISCARD_NONREF && + ff_hevc_nal_is_nonref(s->nal_unit_type))) skip = 1; if (!skip) diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index ef918f4fb2984..b311edc8aeef3 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -548,6 +548,26 @@ int ff_hevc_frame_nb_refs(HEVCContext *s); int ff_hevc_set_new_ref(HEVCContext *s, AVFrame **frame, int poc); +static av_always_inline int ff_hevc_nal_is_nonref(enum HEVCNALUnitType type) +{ + switch (type) { + case HEVC_NAL_TRAIL_N: + case HEVC_NAL_TSA_N: + case HEVC_NAL_STSA_N: + case HEVC_NAL_RADL_N: + case HEVC_NAL_RASL_N: + case HEVC_NAL_VCL_N10: + case HEVC_NAL_VCL_N12: + case HEVC_NAL_VCL_N14: + case HEVC_NAL_BLA_N_LP: + case HEVC_NAL_IDR_N_LP: + return 1; + break; + default: break; + } + return 0; +} + /** * Find next frame in output order and put a reference to it in frame. * @return 1 if a frame was output, 0 otherwise From ad2641c36bf65d4fc8bfea4c14e282bb0ed5db27 Mon Sep 17 00:00:00 2001 From: Mark Reid Date: Mon, 4 Dec 2017 20:46:21 -0800 Subject: [PATCH 1282/2557] avformat/mxfenc: use track count to generate component instance uuid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Tomas Härdin Signed-off-by: Michael Niedermayer --- libavformat/mxf.h | 1 - libavformat/mxfenc.c | 42 +++++++++++++++++++++------------ tests/ref/fate/copy-trac4914 | 2 +- tests/ref/fate/time_base | 2 +- tests/ref/lavf/mxf | 6 ++--- tests/ref/lavf/mxf_d10 | 2 +- tests/ref/lavf/mxf_dv25 | 2 +- tests/ref/lavf/mxf_dvcpro50 | 2 +- tests/ref/lavf/mxf_opatom | 2 +- tests/ref/lavf/mxf_opatom_audio | 2 +- 10 files changed, 37 insertions(+), 26 deletions(-) diff --git a/libavformat/mxf.h b/libavformat/mxf.h index f3db1f939bbd7..2d5b44943b93a 100644 --- a/libavformat/mxf.h +++ b/libavformat/mxf.h @@ -45,7 +45,6 @@ enum MXFMetadataSetType { SubDescriptor, IndexTableSegment, EssenceContainerData, - TypeBottom,// add metadata type before this EssenceGroup, TaggedValue, }; diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index ed6ecbf541c8c..c9694f2a4efc6 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -386,6 +386,7 @@ typedef struct MXFContext { uint32_t tagged_value_count; AVRational audio_edit_rate; int store_user_comments; + int track_instance_count; // used to generate MXFTrack uuids } MXFContext; static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd }; @@ -853,7 +854,7 @@ static void mxf_write_track(AVFormatContext *s, AVStream *st, MXFPackage *packag // write track uid mxf_write_local_tag(pb, 16, 0x3C0A); - mxf_write_uuid(pb, package->type == MaterialPackage ? Track : Track + TypeBottom, st->index); + mxf_write_uuid(pb, Track, mxf->track_instance_count); PRINT_KEY(s, "track uid", pb->buf_ptr - 16); // write track id @@ -884,7 +885,7 @@ static void mxf_write_track(AVFormatContext *s, AVStream *st, MXFPackage *packag // write sequence refs mxf_write_local_tag(pb, 16, 0x4803); - mxf_write_uuid(pb, package->type == MaterialPackage ? Sequence: Sequence + TypeBottom, st->index); + mxf_write_uuid(pb, Sequence, mxf->track_instance_count); } static const uint8_t smpte_12m_timecode_track_data_ul[] = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x01,0x01,0x00,0x00,0x00 }; @@ -924,7 +925,7 @@ static void mxf_write_sequence(AVFormatContext *s, AVStream *st, MXFPackage *pac klv_encode_ber_length(pb, 80); mxf_write_local_tag(pb, 16, 0x3C0A); - mxf_write_uuid(pb, package->type == MaterialPackage ? Sequence: Sequence + TypeBottom, st->index); + mxf_write_uuid(pb, Sequence, mxf->track_instance_count); PRINT_KEY(s, "sequence uid", pb->buf_ptr - 16); mxf_write_common_fields(s, st); @@ -936,9 +937,8 @@ static void mxf_write_sequence(AVFormatContext *s, AVStream *st, MXFPackage *pac component = TimecodeComponent; else component = SourceClip; - if (package->type == SourcePackage) - component += TypeBottom; - mxf_write_uuid(pb, component, st->index); + + mxf_write_uuid(pb, component, mxf->track_instance_count); } static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, MXFPackage *package) @@ -951,8 +951,7 @@ static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, MXFPa // UID mxf_write_local_tag(pb, 16, 0x3C0A); - mxf_write_uuid(pb, package->type == MaterialPackage ? TimecodeComponent : - TimecodeComponent + TypeBottom, st->index); + mxf_write_uuid(pb, TimecodeComponent, mxf->track_instance_count); mxf_write_common_fields(s, st); @@ -971,6 +970,7 @@ static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, MXFPa static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, MXFPackage *package) { + MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; int i; @@ -980,7 +980,7 @@ static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, MXF // write uid mxf_write_local_tag(pb, 16, 0x3C0A); - mxf_write_uuid(pb, package->type == MaterialPackage ? SourceClip: SourceClip + TypeBottom, st->index); + mxf_write_uuid(pb, SourceClip, mxf->track_instance_count); PRINT_KEY(s, "structural component uid", pb->buf_ptr - 16); mxf_write_common_fields(s, st); @@ -1357,7 +1357,7 @@ static void mxf_write_package(AVFormatContext *s, MXFPackage *package) // write package umid mxf_write_local_tag(pb, 32, 0x4401); - mxf_write_umid(s, package->type == SourcePackage); + mxf_write_umid(s, package->instance); PRINT_KEY(s, "package umid second part", pb->buf_ptr - 16); // package name @@ -1375,10 +1375,9 @@ static void mxf_write_package(AVFormatContext *s, MXFPackage *package) // write track refs mxf_write_local_tag(pb, track_count*16 + 8, 0x4403); mxf_write_refs_count(pb, track_count); - mxf_write_uuid(pb, package->type == MaterialPackage ? Track : - Track + TypeBottom, -1); // timecode track - for (i = 0; i < s->nb_streams; i++) - mxf_write_uuid(pb, package->type == MaterialPackage ? Track : Track + TypeBottom, i); + // these are the uuids of the tracks the will be written in mxf_write_track + for (i = 0; i < track_count; i++) + mxf_write_uuid(pb, Track, mxf->track_instance_count + i); // write user comment refs if (mxf->store_user_comments) { @@ -1398,16 +1397,26 @@ static void mxf_write_package(AVFormatContext *s, MXFPackage *package) mxf_write_uuid(pb, SubDescriptor, 0); } + /* + * for every 1 track in a package there is 1 sequence and 1 component. + * all 3 of these elements share the same instance number for generating + * there instance uuids. mxf->track_instance_count stores this value. + * mxf->track_instance_count is incremented after a group of all 3 of + * these elements are written. + */ + // write timecode track mxf_write_track(s, mxf->timecode_track, package); mxf_write_sequence(s, mxf->timecode_track, package); mxf_write_timecode_component(s, mxf->timecode_track, package); + mxf->track_instance_count++; for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; mxf_write_track(s, st, package); mxf_write_sequence(s, st, package); mxf_write_structural_component(s, st, package); + mxf->track_instance_count++; if (package->type == SourcePackage) { MXFStreamContext *sc = st->priv_data; @@ -1440,14 +1449,16 @@ static int mxf_write_essence_container_data(AVFormatContext *s) static int mxf_write_header_metadata_sets(AVFormatContext *s) { + MXFContext *mxf = s->priv_data; AVDictionaryEntry *entry = NULL; AVStream *st = NULL; int i; - MXFPackage packages[2] = {}; + MXFPackage packages[2] = {{0}}; int package_count = 2; packages[0].type = MaterialPackage; packages[1].type = SourcePackage; + packages[1].instance = 1; if (entry = av_dict_get(s->metadata, "material_package_name", NULL, 0)) packages[0].name = entry->value; @@ -1468,6 +1479,7 @@ static int mxf_write_header_metadata_sets(AVFormatContext *s) mxf_write_preface(s); mxf_write_identification(s); mxf_write_content_storage(s, packages, package_count); + mxf->track_instance_count = 0; for (i = 0; i < package_count; i++) mxf_write_package(s, &packages[i]); mxf_write_essence_container_data(s); diff --git a/tests/ref/fate/copy-trac4914 b/tests/ref/fate/copy-trac4914 index e0864a0035ca9..a8f287fafae17 100644 --- a/tests/ref/fate/copy-trac4914 +++ b/tests/ref/fate/copy-trac4914 @@ -1,4 +1,4 @@ -d51f6bcc96885a2ce8517ae8c774f610 *tests/data/fate/copy-trac4914.mxf +05fdc4a6e28abb2c26e96224682d2684 *tests/data/fate/copy-trac4914.mxf 560697 tests/data/fate/copy-trac4914.mxf #tb 0: 1001/30000 #media_type 0: video diff --git a/tests/ref/fate/time_base b/tests/ref/fate/time_base index 7923556b351a9..4dd14084d370a 100644 --- a/tests/ref/fate/time_base +++ b/tests/ref/fate/time_base @@ -1 +1 @@ -d26a35b141551b36c5b8bd716451cfcb +f97551f884df5ab709c5869c66c7b9bc diff --git a/tests/ref/lavf/mxf b/tests/ref/lavf/mxf index b9c37334a9735..7318447ecb793 100644 --- a/tests/ref/lavf/mxf +++ b/tests/ref/lavf/mxf @@ -1,9 +1,9 @@ -1c06a9d69b6e309579784db5ecb0b69f *./tests/data/lavf/lavf.mxf +d4140129463dec64bdb4a7d7ad1b0c82 *./tests/data/lavf/lavf.mxf 525369 ./tests/data/lavf/lavf.mxf ./tests/data/lavf/lavf.mxf CRC=0x8dddfaab -50b4f9ca0493e6d83f4c52dc3aa2b7a5 *./tests/data/lavf/lavf.mxf +a27bb8cd5e185ea13b0a8daa4eb221cd *./tests/data/lavf/lavf.mxf 560697 ./tests/data/lavf/lavf.mxf ./tests/data/lavf/lavf.mxf CRC=0xf21b1b48 -4b71b154ae37364c8028cb50850a54c5 *./tests/data/lavf/lavf.mxf +395bf0047c97ceca96935357166b94c7 *./tests/data/lavf/lavf.mxf 525369 ./tests/data/lavf/lavf.mxf ./tests/data/lavf/lavf.mxf CRC=0x8dddfaab diff --git a/tests/ref/lavf/mxf_d10 b/tests/ref/lavf/mxf_d10 index 134db876d5bc2..2384d427b024d 100644 --- a/tests/ref/lavf/mxf_d10 +++ b/tests/ref/lavf/mxf_d10 @@ -1,3 +1,3 @@ -73c0cb416548c33d0651c59519a8f7e2 *./tests/data/lavf/lavf.mxf_d10 +f4694941b0cd5b5e3c91064d84dbd345 *./tests/data/lavf/lavf.mxf_d10 5330989 ./tests/data/lavf/lavf.mxf_d10 ./tests/data/lavf/lavf.mxf_d10 CRC=0x6c74d488 diff --git a/tests/ref/lavf/mxf_dv25 b/tests/ref/lavf/mxf_dv25 index 85094828d15f7..e836b14240aef 100644 --- a/tests/ref/lavf/mxf_dv25 +++ b/tests/ref/lavf/mxf_dv25 @@ -1,3 +1,3 @@ -1871bd11947924116776201f24fd0adf *./tests/data/lavf/lavf.mxf_dv25 +1ca8143bf6cf322fd39f6e856959d502 *./tests/data/lavf/lavf.mxf_dv25 3833389 ./tests/data/lavf/lavf.mxf_dv25 ./tests/data/lavf/lavf.mxf_dv25 CRC=0xbdaf7f52 diff --git a/tests/ref/lavf/mxf_dvcpro50 b/tests/ref/lavf/mxf_dvcpro50 index 1d0cf79996196..bb3d6b928a812 100644 --- a/tests/ref/lavf/mxf_dvcpro50 +++ b/tests/ref/lavf/mxf_dvcpro50 @@ -1,3 +1,3 @@ -6c9cb62911ac16c3b55f0ad0b052c05b *./tests/data/lavf/lavf.mxf_dvcpro50 +987fd4b2abb36433fba0e35f4092efc6 *./tests/data/lavf/lavf.mxf_dvcpro50 7430189 ./tests/data/lavf/lavf.mxf_dvcpro50 ./tests/data/lavf/lavf.mxf_dvcpro50 CRC=0xe3bbe4b4 diff --git a/tests/ref/lavf/mxf_opatom b/tests/ref/lavf/mxf_opatom index ea1190c06ae51..1cc612e627517 100644 --- a/tests/ref/lavf/mxf_opatom +++ b/tests/ref/lavf/mxf_opatom @@ -1,3 +1,3 @@ -962c2cd582340f8961a8283636093abf *./tests/data/lavf/lavf.mxf_opatom +b8fe60f7457b83709f33357d04c8db0c *./tests/data/lavf/lavf.mxf_opatom 4717113 ./tests/data/lavf/lavf.mxf_opatom ./tests/data/lavf/lavf.mxf_opatom CRC=0xf55aa22a diff --git a/tests/ref/lavf/mxf_opatom_audio b/tests/ref/lavf/mxf_opatom_audio index 953df9094fd6d..deed55e52692d 100644 --- a/tests/ref/lavf/mxf_opatom_audio +++ b/tests/ref/lavf/mxf_opatom_audio @@ -1,3 +1,3 @@ -d4ad5a0faf410a9d9e99b3328143e89d *./tests/data/lavf/lavf.mxf_opatom_audio +e7da52bd591e6eddb4e1af381a4e5bd4 *./tests/data/lavf/lavf.mxf_opatom_audio 101945 ./tests/data/lavf/lavf.mxf_opatom_audio ./tests/data/lavf/lavf.mxf_opatom_audio CRC=0xd155c6ff From 901d87aa83aa1686f02bb4750c74d4d7cb6086db Mon Sep 17 00:00:00 2001 From: Mark Reid Date: Mon, 4 Dec 2017 20:46:22 -0800 Subject: [PATCH 1283/2557] avformat/mxfenc: write reel_name if metadata key is present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Tomas Härdin Signed-off-by: Michael Niedermayer --- libavformat/mxf.h | 1 + libavformat/mxfenc.c | 42 +++++++++++++++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/libavformat/mxf.h b/libavformat/mxf.h index 2d5b44943b93a..ffcc429a8b4d7 100644 --- a/libavformat/mxf.h +++ b/libavformat/mxf.h @@ -47,6 +47,7 @@ enum MXFMetadataSetType { EssenceContainerData, EssenceGroup, TaggedValue, + TapeDescriptor, }; enum MXFFrameLayout { diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index c9694f2a4efc6..3bb70326fe973 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -105,6 +105,7 @@ typedef struct MXFPackage { char *name; enum MXFMetadataSetType type; int instance; + struct MXFPackage *ref; } MXFPackage; enum ULIndex { @@ -991,20 +992,33 @@ static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, MXF // write source package uid, end of the reference mxf_write_local_tag(pb, 32, 0x1101); - if (package->type == SourcePackage) { + if (!package->ref) { for (i = 0; i < 4; i++) avio_wb64(pb, 0); } else - mxf_write_umid(s, 1); + mxf_write_umid(s, package->ref->instance); // write source track id mxf_write_local_tag(pb, 4, 0x1102); - if (package->type == SourcePackage) + if (package->type == SourcePackage && !package->ref) avio_wb32(pb, 0); else avio_wb32(pb, st->index+2); } +static void mxf_write_tape_descriptor(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + + mxf_write_metadata_key(pb, 0x012e00); + PRINT_KEY(s, "tape descriptor key", pb->buf_ptr - 16); + klv_encode_ber_length(pb, 20); + mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_uuid(pb, TapeDescriptor, 0); + PRINT_KEY(s, "tape_desc uid", pb->buf_ptr - 16); +} + + static void mxf_write_multi_descriptor(AVFormatContext *s) { MXFContext *mxf = s->priv_data; @@ -1388,13 +1402,17 @@ static void mxf_write_package(AVFormatContext *s, MXFPackage *package) } // write multiple descriptor reference - if (package->type == SourcePackage) { + if (package->type == SourcePackage && package->instance == 1) { mxf_write_local_tag(pb, 16, 0x4701); if (s->nb_streams > 1) { mxf_write_uuid(pb, MultipleDescriptor, 0); mxf_write_multi_descriptor(s); } else mxf_write_uuid(pb, SubDescriptor, 0); + } else if (package->type == SourcePackage && package->instance == 2) { + mxf_write_local_tag(pb, 16, 0x4701); + mxf_write_uuid(pb, TapeDescriptor, 0); + mxf_write_tape_descriptor(s); } /* @@ -1418,7 +1436,7 @@ static void mxf_write_package(AVFormatContext *s, MXFPackage *package) mxf_write_structural_component(s, st, package); mxf->track_instance_count++; - if (package->type == SourcePackage) { + if (package->type == SourcePackage && package->instance == 1) { MXFStreamContext *sc = st->priv_data; mxf_essence_container_uls[sc->index].write_desc(s, st); } @@ -1453,12 +1471,13 @@ static int mxf_write_header_metadata_sets(AVFormatContext *s) AVDictionaryEntry *entry = NULL; AVStream *st = NULL; int i; - - MXFPackage packages[2] = {{0}}; + MXFPackage packages[3] = {{0}}; int package_count = 2; packages[0].type = MaterialPackage; packages[1].type = SourcePackage; packages[1].instance = 1; + packages[0].ref = &packages[1]; + if (entry = av_dict_get(s->metadata, "material_package_name", NULL, 0)) packages[0].name = entry->value; @@ -1476,6 +1495,15 @@ static int mxf_write_header_metadata_sets(AVFormatContext *s) } } + entry = av_dict_get(s->metadata, "reel_name", NULL, 0); + if (entry) { + packages[2].name = entry->value; + packages[2].type = SourcePackage; + packages[2].instance = 2; + packages[1].ref = &packages[2]; + package_count = 3; + } + mxf_write_preface(s); mxf_write_identification(s); mxf_write_content_storage(s, packages, package_count); From 0091a54f64874c9a76faad361dc8f147333d2821 Mon Sep 17 00:00:00 2001 From: Mark Reid Date: Mon, 4 Dec 2017 20:46:23 -0800 Subject: [PATCH 1284/2557] fate/mxf: add reel name test Signed-off-by: Michael Niedermayer --- tests/fate/mxf.mak | 8 ++++++-- tests/ref/fate/mxf-reel_name | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 tests/ref/fate/mxf-reel_name diff --git a/tests/fate/mxf.mak b/tests/fate/mxf.mak index 7714b61569461..dce23d522ea65 100644 --- a/tests/fate/mxf.mak +++ b/tests/fate/mxf.mak @@ -33,9 +33,13 @@ FATE_MXF_PROBE-$(call ENCDEC2, DVVIDEO, PCM_S16LE, MXF) += fate-mxf-probe-dv25 fate-mxf-probe-dv25: SRC = $(TARGET_SAMPLES)/mxf/Avid-00005.mxf fate-mxf-probe-dv25: CMD = run $(PROBE_FORMAT_STREAMS_COMMAND) -i "$(SRC)" +FATE_MXF_REEL_NAME-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += fate-mxf-reel_name +fate-mxf-reel_name: $(TARGET_SAMPLES)/mxf/Sony-00001.mxf +fate-mxf-reel_name: CMD = md5 -y -i $(TARGET_SAMPLES)/mxf/Sony-00001.mxf -c copy -timecode 00:00:00:00 -metadata "reel_name=test_reel" -fflags +bitexact -f mxf + FATE_MXF-$(CONFIG_MXF_DEMUXER) += $(FATE_MXF) -FATE_SAMPLES_AVCONV += $(FATE_MXF-yes) +FATE_SAMPLES_AVCONV += $(FATE_MXF-yes) $(FATE_MXF_REEL_NAME-yes) FATE_SAMPLES_FFPROBE += $(FATE_MXF_PROBE-yes) -fate-mxf: $(FATE_MXF-yes) $(FATE_MXF_PROBE-yes) +fate-mxf: $(FATE_MXF-yes) $(FATE_MXF_PROBE-yes) $(FATE_MXF_REEL_NAME-yes) diff --git a/tests/ref/fate/mxf-reel_name b/tests/ref/fate/mxf-reel_name new file mode 100644 index 0000000000000..fb9586097a16d --- /dev/null +++ b/tests/ref/fate/mxf-reel_name @@ -0,0 +1 @@ +dda6c54b642b8794a87d809fdb361f95 From b404d41b1962d753ff3886fd82fffb9a16542a29 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 8 Dec 2017 16:58:10 +0100 Subject: [PATCH 1285/2557] fate: Fix fate-mov-bbi-elst-starts-b on ARM --- tests/fate/mov.mak | 2 +- tests/ref/fate/mov-bbi-elst-starts-b | 452 +++++++++++++-------------- 2 files changed, 227 insertions(+), 227 deletions(-) diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 220f99064e18d..19b01304fbc55 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -67,7 +67,7 @@ fate-mov-frag-overlap: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/frag_overlap.mp4 # Makes sure that we pick the right frames according to edit list when there is no keyframe with PTS < edit list start. # For example, when video starts on a B-frame, and edit list starts on that B-frame too. # GOP structure : B B I in presentation order. -fate-mov-bbi-elst-starts-b: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/h264/twofields_packet.mp4 +fate-mov-bbi-elst-starts-b: CMD = framemd5 -flags +bitexact -acodec aac_fixed -i $(TARGET_SAMPLES)/h264/twofields_packet.mp4 fate-mov-aac-2048-priming: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_packets -print_format compact $(TARGET_SAMPLES)/mov/aac-2048-priming.mov diff --git a/tests/ref/fate/mov-bbi-elst-starts-b b/tests/ref/fate/mov-bbi-elst-starts-b index d3ede1a86cada..3ba28b5e755d0 100644 --- a/tests/ref/fate/mov-bbi-elst-starts-b +++ b/tests/ref/fate/mov-bbi-elst-starts-b @@ -15,377 +15,377 @@ #stream#, dts, pts, duration, size, hash 0, 0, 0, 1, 3110400, e9454409af76038dbe56e834921d2fa8 1, 0, 0, 1024, 4096, 620f0b67a91f7f74151bc5be745b7110 -1, 1024, 1024, 1024, 4096, 8ab1a8e40b154f577914e43ec6cdc674 +1, 1024, 1024, 1024, 4096, 4963ab641585142fbac06502873fb6d3 0, 1, 1, 1, 3110400, 37aa620e494d22ba248feea9a5a869a0 -1, 2048, 2048, 1024, 4096, 41f09b125271955596ef56436e5ae7b3 -1, 3072, 3072, 1024, 4096, e4934aa9fbaf7dcd578fe9f404bfdd39 +1, 2048, 2048, 1024, 4096, 80649ae10d2587264fcb43c7dc25e61b +1, 3072, 3072, 1024, 4096, 01ec94c18060be08988e8b9b1c9de822 0, 2, 2, 1, 3110400, 7b8be9619e4e1d618ab1ed85aff3957b -1, 4096, 4096, 1024, 4096, 5321f9a453ff71e420b592c9188560f4 +1, 4096, 4096, 1024, 4096, 3f8342da3124e22b89211c2f233eb5b2 0, 3, 3, 1, 3110400, 756a4551420853bc3ae444e6b86169f3 -1, 5120, 5120, 1024, 4096, fa45be5ec01b9c0ae78f876f290602e2 -1, 6144, 6144, 1024, 4096, bce7b47534cf6ae5db1fa27805fd52a6 +1, 5120, 5120, 1024, 4096, 4832d1a3f7d8aaceb0489c1ca0706d31 +1, 6144, 6144, 1024, 4096, 7e89f1e8318ed54d81e4efe3c679515f 0, 4, 4, 1, 3110400, 94a93c1669a96ebf41a7258177849396 -1, 7168, 7168, 1024, 4096, 15f899020d6e186b2f2a15b60034fa26 +1, 7168, 7168, 1024, 4096, d73468c68e92c9e2939eb30d66a45bc2 0, 5, 5, 1, 3110400, 5d1c49d3f43cd472683e4a039e376af5 -1, 8192, 8192, 1024, 4096, 9038d943078707eac0eff9126911b9d0 -1, 9216, 9216, 1024, 4096, 40dced7d76db2c011be7b04f1c6e9236 +1, 8192, 8192, 1024, 4096, 72e1020c1bb961cb1c177f97e427edb9 +1, 9216, 9216, 1024, 4096, 1a4773af7080bd904a3b14c12a8028fa 0, 6, 6, 1, 3110400, e0e88cc34b0a9d7963cddf554a3909f0 -1, 10240, 10240, 1024, 4096, eadb875a43a9b7b89c371af7ca8da51d +1, 10240, 10240, 1024, 4096, d39ae1809032c4807efe41520302bd37 0, 7, 7, 1, 3110400, 1f464f2427aa3842224803b6d67154f8 -1, 11264, 11264, 1024, 4096, 89cc2aaf68c534909f416174a8c78a55 -1, 12288, 12288, 1024, 4096, 4698d55945ef20b80f7750cc7c3ae4cc +1, 11264, 11264, 1024, 4096, e26af86998d1a9579127a97dbe45890b +1, 12288, 12288, 1024, 4096, 148e1ab102c1c62d9018095c7e934eea 0, 8, 8, 1, 3110400, e5d610b8e53203b5ccb01877acb3ac56 -1, 13312, 13312, 1024, 4096, 4c13aba7b37754180ccc37781f7f7071 -1, 14336, 14336, 1024, 4096, d5cbb68356d98fc9ba95d0f1a8b64982 +1, 13312, 13312, 1024, 4096, 96582c941184ad967e9e91198775e61f +1, 14336, 14336, 1024, 4096, 8d2371bb1524d9d007ae44519b55a055 0, 9, 9, 1, 3110400, d1363fbdffbb85a0affe660bfd09b98c -1, 15360, 15360, 1024, 4096, a1434238bb68788c5a67718984f81386 +1, 15360, 15360, 1024, 4096, 6034c9e409d8dcdfd032b44f631e2362 0, 10, 10, 1, 3110400, 130bb4c17e963b092a717325498c06c3 -1, 16384, 16384, 1024, 4096, ec4698b981291bbc6f68f0102459e10b -1, 17408, 17408, 1024, 4096, 290f2d4a4192950ce6f8d32d12ee9639 +1, 16384, 16384, 1024, 4096, 3649e9edc65a042c4c913c06c3f3bff7 +1, 17408, 17408, 1024, 4096, a4cdb0c4bed48d1f7c4918e5590a542d 0, 11, 11, 1, 3110400, a3cb7a37fef5d8a49815dd15970c1f3d -1, 18432, 18432, 1024, 4096, 7751f23e652fb0e900c818d7bbf6d439 +1, 18432, 18432, 1024, 4096, a130e8ba9a47df0c76edf5c3ece5762f 0, 12, 12, 1, 3110400, 7dc4a4334fa9bb61f2ad56b3d059b3f7 -1, 19456, 19456, 1024, 4096, d53b61ab050826349647c0eca80ba055 -1, 20480, 20480, 1024, 4096, a680a7614abcc7a1abcd1f9e3e2adecc +1, 19456, 19456, 1024, 4096, cf76a132c205c29a0b7042599973fda4 +1, 20480, 20480, 1024, 4096, b9b7d819599bb6d7cd53cc1bc0810ca7 0, 13, 13, 1, 3110400, ccda106ec5899787c3bc8679ee052854 -1, 21504, 21504, 1024, 4096, eac237797a6cf2175dd20c9781558292 +1, 21504, 21504, 1024, 4096, 3d0d6ef8318a94416a56108248e6cad3 0, 14, 14, 1, 3110400, 4254c7b01a67a0810bf234ba7b1f59d0 -1, 22528, 22528, 1024, 4096, fc5c373095e1160dc9d74e9cbdfb8c28 -1, 23552, 23552, 1024, 4096, 309f3dc4277470878ce57f5fd9973c5b +1, 22528, 22528, 1024, 4096, a8a082b4c521d2e7fc990f54e3580a9e +1, 23552, 23552, 1024, 4096, 60b36c268bc98093f35a7c90c64b507c 0, 15, 15, 1, 3110400, 6c0acd9781cfecaf9a10fe91f8d6ec41 1, 24576, 24576, 1024, 4096, c5211b49eb51cea4c16079eb54df3d12 -1, 25600, 25600, 1024, 4096, 632bdda9a5f3b2cd6803cecb52354918 +1, 25600, 25600, 1024, 4096, dddd55a31e8a65110a89de1af67861b0 0, 16, 16, 1, 3110400, 2a9d5db0bc2f54e2c66834db64386bb7 -1, 26624, 26624, 1024, 4096, b6a34f7a303ac78ea59b1bd585ca7e7a +1, 26624, 26624, 1024, 4096, 0c220f1d405bb463469b54fa126a2c41 0, 17, 17, 1, 3110400, 0140f515be87da399061764050d15b16 -1, 27648, 27648, 1024, 4096, 3f4ef420b203060179a9377b9494794e -1, 28672, 28672, 1024, 4096, 6a1469f30159027a20f29b457cdaf8ec +1, 27648, 27648, 1024, 4096, 11d740234a9a4dd28e3191e258fc8e3b +1, 28672, 28672, 1024, 4096, e456943c722a9807669f57776dcb8c5d 0, 18, 18, 1, 3110400, cad554fe221fbd8ee848facebd7b24d2 -1, 29696, 29696, 1024, 4096, 03cf0150f76f40a4becf6b24f852bb03 +1, 29696, 29696, 1024, 4096, 3c13165d648f46c3e3e699b874da372a 0, 19, 19, 1, 3110400, 1e8474911cb1bd831808dc2beba540c0 -1, 30720, 30720, 1024, 4096, 9beb867892f94b7890368ef9232e9059 -1, 31744, 31744, 1024, 4096, 82b2ade2371db061c320948decb364dd +1, 30720, 30720, 1024, 4096, 7e7a46e3360f884507c95f640cd6f532 +1, 31744, 31744, 1024, 4096, 420d047ee4d55b7af2d97c5116e25d37 0, 20, 20, 1, 3110400, f39c483fbf3c598c38cf543abad2c03c -1, 32768, 32768, 1024, 4096, a70e4b5ce175aa77271de0236fffe581 +1, 32768, 32768, 1024, 4096, b3334bcd2ed3b2ab32ac13c24a8d1322 0, 21, 21, 1, 3110400, 3b21171a003827a203c0c5853c36893e -1, 33792, 33792, 1024, 4096, eb81a2d0ba1e33b9f482de7b18055d22 -1, 34816, 34816, 1024, 4096, bcf3a843ec8e3c7f147fb6de53148f3a +1, 33792, 33792, 1024, 4096, 1472898e0d4fafd52fc0adb789e06987 +1, 34816, 34816, 1024, 4096, f3e7c33d92578fa5eb90933491106c37 0, 22, 22, 1, 3110400, 40e8733f93c468cb58c3921c80f81c68 -1, 35840, 35840, 1024, 4096, 80e2259a1c660a1a7be3b60dc41b3d97 +1, 35840, 35840, 1024, 4096, 7d7f8e8f542be9291b7895472f8cf0a7 0, 23, 23, 1, 3110400, a2d716f215af7d778bd605decae201dd -1, 36864, 36864, 1024, 4096, 48674a7c0fe9e07f24661ccb86a3337e -1, 37888, 37888, 1024, 4096, 743debd528abc74a584c6ce6f7254c0f +1, 36864, 36864, 1024, 4096, 66e2e35d40beb6e1df30d4d180661d4b +1, 37888, 37888, 1024, 4096, 8fc0c16fc3ec5db47e437263b429406b 0, 24, 24, 1, 3110400, e6fb8d3f1c9747f185b50eded67ff0ab -1, 38912, 38912, 1024, 4096, 13df1fb081608357167356d5ec1634d7 -1, 39936, 39936, 1024, 4096, 0ef50ab373ffe390f301dca86a7ab831 +1, 38912, 38912, 1024, 4096, dd6331f430abf41dade4e4a85784745f +1, 39936, 39936, 1024, 4096, 5c693b37419fe43fb83b715d4f7083ec 0, 25, 25, 1, 3110400, fe4e0cf566674672ad043f24eae02e63 -1, 40960, 40960, 1024, 4096, 3f7b13e5660491d3000b9af7752c0b9a +1, 40960, 40960, 1024, 4096, 9e13b054c07feac0fad601ed4823996e 0, 26, 26, 1, 3110400, f57d4d32012dfcb14a270bdc90812e5e -1, 41984, 41984, 1024, 4096, 403dfa2233788e04297ba7b884b4938b -1, 43008, 43008, 1024, 4096, 87da545df36479d27f0584864e2fcf1c +1, 41984, 41984, 1024, 4096, dbffea22781b35088859868189e270aa +1, 43008, 43008, 1024, 4096, 59f1a985d7a96273bf48be9dc8a7d4d2 0, 27, 27, 1, 3110400, fe7aa8c1754b9590fe75b783d4e126ed -1, 44032, 44032, 1024, 4096, 65b2599f40c24ff42f0b7f0f35e2588c +1, 44032, 44032, 1024, 4096, b07e02d0bfecbde9b48e6e83952aa3c7 0, 28, 28, 1, 3110400, 29ae6e541021bf481c8937c37ac34570 -1, 45056, 45056, 1024, 4096, d090b8e24ad0b08953d9f7dca9d1d296 -1, 46080, 46080, 1024, 4096, 45a46389b5dfc99318327b4014162827 +1, 45056, 45056, 1024, 4096, d0dfca31885ac1d21fe42bb26e3b11ec +1, 46080, 46080, 1024, 4096, 5479670aea3a4d07a61b9edcc2113c7b 0, 29, 29, 1, 3110400, 211e0803b5a704c7ef1c36fc5c182710 -1, 47104, 47104, 1024, 4096, 5a4f770dbaca63d1ae6580cb147c73f8 +1, 47104, 47104, 1024, 4096, 0118d7fc0d0f8462647f37aa6d82c8fc 0, 30, 30, 1, 3110400, a4ea3a4686d214ad54fcdce63f8c2dc0 -1, 48128, 48128, 1024, 4096, b365fa5a5642be5f7e426abed06adf3d -1, 49152, 49152, 1024, 4096, 5bb22433db0e71d8ad58abdb9713ec53 +1, 48128, 48128, 1024, 4096, cc2b22d4c7497accb6b194968b407e10 +1, 49152, 49152, 1024, 4096, fe8d30c082a3608b8ccf5e3d6f4b0ddb 0, 31, 31, 1, 3110400, 8af971cf637609534ec59b6f29a3666e -1, 50176, 50176, 1024, 4096, 59c753d1b4968588a6d25734b9d88487 -1, 51200, 51200, 1024, 4096, cdce1887048f4f14273da946e3eb3c18 +1, 50176, 50176, 1024, 4096, ed15a6aa2d87395b47888f744f41df30 +1, 51200, 51200, 1024, 4096, 8d4971ee25d274822cceaa00cc8df1a1 0, 32, 32, 1, 3110400, 8cfe93dfd76e4f97cc04a145bb559af5 -1, 52224, 52224, 1024, 4096, 0b21542c844fe587d32098bb5535a107 +1, 52224, 52224, 1024, 4096, 799f1c9cac6c3cedaac80cc6b26df827 0, 33, 33, 1, 3110400, 691fe61398016f767ea7ba781ef72953 -1, 53248, 53248, 1024, 4096, 67344ce61d0972a0d7e01d10154cc192 -1, 54272, 54272, 1024, 4096, 690b3d79c5689545992d9d427c202c80 +1, 53248, 53248, 1024, 4096, 40cbefbb455231c0f21af129e2504395 +1, 54272, 54272, 1024, 4096, 05eb1731cb93ff68815e92f0a528d4d7 0, 34, 34, 1, 3110400, 7eaf5bc5e942f8218f46c9c505d7b58c -1, 55296, 55296, 1024, 4096, 48e8ab0926cac6d2097f7e74f7d87214 +1, 55296, 55296, 1024, 4096, de96fa062c59b6b3b88731e60e02d040 0, 35, 35, 1, 3110400, feacc8282186935e310ec2dccbb79239 -1, 56320, 56320, 1024, 4096, 7d6d0f8705f4978abe4e501a19fae18d -1, 57344, 57344, 1024, 4096, 8b8069b4133f6b646f83c0c333ca08ee +1, 56320, 56320, 1024, 4096, 14d38d89079c1b7801987c5315477d11 +1, 57344, 57344, 1024, 4096, 9a0029ae7fc7e029402ec29536288cff 0, 36, 36, 1, 3110400, a5dfb5c4c23e647e2c77dd117e4ed714 -1, 58368, 58368, 1024, 4096, 7738b55c8ee4c7fe9418b90aea2bc561 +1, 58368, 58368, 1024, 4096, 83925a6ebf953e6b711d3042c95ffe51 0, 37, 37, 1, 3110400, da9306c2872788ba2a587eab7f597f13 -1, 59392, 59392, 1024, 4096, d5dfd403866781c8b8d5f7df7f8c7e86 -1, 60416, 60416, 1024, 4096, 841ca64b5056fadc91a18b65e5d368f3 +1, 59392, 59392, 1024, 4096, 5b332b22a2a8ae72cbf8154d2cfd9b5d +1, 60416, 60416, 1024, 4096, 8dcd5041b49036e43f74819439a6db63 0, 38, 38, 1, 3110400, 19d14a655aa02cc2767afd9ed9bc2ff4 -1, 61440, 61440, 1024, 4096, 6de6157593f09a1b662ce8be40d4a64e +1, 61440, 61440, 1024, 4096, 90ea3ac56003b4f1c0242a611746b76a 0, 39, 39, 1, 3110400, 4d9e6455fb71d5cd511dddf894b4f7d8 -1, 62464, 62464, 1024, 4096, d15b3a0f417815474cbca73d59fc78fb -1, 63488, 63488, 1024, 4096, 312408569a1e68f71cf7b31704641ed1 +1, 62464, 62464, 1024, 4096, 6ed9f815739e6e3b8ed125688f693d5f +1, 63488, 63488, 1024, 4096, e056b91f4875029af3c29a26e37380a1 0, 40, 40, 1, 3110400, 052c32c00bc1b40d5270f4b5c4d34d6b -1, 64512, 64512, 1024, 4096, e88ca9f4ded21e07ea0b4101c4d36f1c -1, 65536, 65536, 1024, 4096, 9fbdf5e0d8df6a4c699877a5d72e77d3 +1, 64512, 64512, 1024, 4096, 36ff82cb34ffc9ea60b1fbc8d3edd9f1 +1, 65536, 65536, 1024, 4096, 975c2d6080532645be510241d52b788c 0, 41, 41, 1, 3110400, 645e0c3eb8599c2cc712a97cbae9d1d3 -1, 66560, 66560, 1024, 4096, ec5daa820b0a67feeff3ed953a3c5bdd +1, 66560, 66560, 1024, 4096, 9a53c620f19d5bb733c8bd068137ba3a 0, 42, 42, 1, 3110400, d0b3fe092511fed0e384ffad85f6ae3c -1, 67584, 67584, 1024, 4096, b050ff15f06ca48c8c7820bb107232ff -1, 68608, 68608, 1024, 4096, 88751e60258f292e2fd927a492ddb9a6 +1, 67584, 67584, 1024, 4096, 482365611c86663b70a13511d8194282 +1, 68608, 68608, 1024, 4096, 4f9002718a7103a4b15b96e9e08a2cfd 0, 43, 43, 1, 3110400, 131c090f806658ffbb4949b3310a6348 -1, 69632, 69632, 1024, 4096, da7d5b875c390e8d4e1f3103c0331340 +1, 69632, 69632, 1024, 4096, 2301e3336164fe298b85006b0e7dc0b8 0, 44, 44, 1, 3110400, 71e8042ed01a1bbe971417d87685dda1 -1, 70656, 70656, 1024, 4096, 9e2c8e378228356c1a0e312875fee8a4 -1, 71680, 71680, 1024, 4096, d1ac505bd1922769852b32c6476e9c34 +1, 70656, 70656, 1024, 4096, d8b4c47bb3f58a70109d70edaea9916b +1, 71680, 71680, 1024, 4096, ff87ca54ad112c083b1cc25043429410 0, 45, 45, 1, 3110400, 948cc8d7eceb2e512c8660063143557b -1, 72704, 72704, 1024, 4096, 8861798a4bae7045c78175b3e783654b +1, 72704, 72704, 1024, 4096, eee9c7fd3c78681fcfcdf40ed7ee2c6b 0, 46, 46, 1, 3110400, 8b580d4f620af52ac0a5702197f5e9d6 -1, 73728, 73728, 1024, 4096, e9021bdc21613b1325d0f735d5a06115 -1, 74752, 74752, 1024, 4096, 5cbb598627500e8b5d5e39ba3750f826 +1, 73728, 73728, 1024, 4096, d05a2d810e2c201cff9e115c48cff977 +1, 74752, 74752, 1024, 4096, 5ef14640b86062c99427e0177b33657c 0, 47, 47, 1, 3110400, a30bfc0727c6abb477751969c1b1450c -1, 75776, 75776, 1024, 4096, a605c5242d14724f36d7bd7ddec1a07c -1, 76800, 76800, 1024, 4096, 30a60b54960e9ce33566cdd6bab77ac1 +1, 75776, 75776, 1024, 4096, 92398dd17af6362aa81fe8a9aad0af01 +1, 76800, 76800, 1024, 4096, 131b910e0af30e5250726b3d4a5f4f10 0, 48, 48, 1, 3110400, 28381142e60e9011d0cd75e7881c1956 -1, 77824, 77824, 1024, 4096, d534fd1afbadb92b2cd19046562bdecb +1, 77824, 77824, 1024, 4096, 50157f3541acd42d2c460e125a9f2393 0, 49, 49, 1, 3110400, 1b4bdae40d76ed7625f85da7c5289360 -1, 78848, 78848, 1024, 4096, 95995add4ca88b76bb2a85c3078ffa45 -1, 79872, 79872, 1024, 4096, a1a06ef2915ba565110703180e31dda3 +1, 78848, 78848, 1024, 4096, 266fd18529d95b7347e9a019271056fc +1, 79872, 79872, 1024, 4096, 2f9a347ce750501f2e4d0a36c95bc8b0 0, 50, 50, 1, 3110400, 354fb545adf6082dc57b8077ba1466ad -1, 80896, 80896, 1024, 4096, 21ee5850fd1474bf820f607aad597b2f +1, 80896, 80896, 1024, 4096, 0f8b0626ef01d0e941914d7810945aa1 0, 51, 51, 1, 3110400, c969f21be0dcbef6b232d3f0a9e3f189 -1, 81920, 81920, 1024, 4096, 4960c6db1ee2ea35d3c8b6dade2a8000 -1, 82944, 82944, 1024, 4096, 63031c5985de637b2ddeefaf8e3f1ffd +1, 81920, 81920, 1024, 4096, 51da6b0c3d5daddb8f4635d692b0e8ba +1, 82944, 82944, 1024, 4096, aac8a7152103243dabd94e2a37caf53f 0, 52, 52, 1, 3110400, 4ff19ab89ebe466e8ce3df0ba25b6b0a -1, 83968, 83968, 1024, 4096, 537a6f30a21a0d8707fe8b7cb71ff094 +1, 83968, 83968, 1024, 4096, 50c8d5b0a373c07ecb66ca33e087a299 0, 53, 53, 1, 3110400, 49f601932c19ae8d405771e9cfd4f9e8 -1, 84992, 84992, 1024, 4096, d0c4c9c81b5e8525146049023b402889 -1, 86016, 86016, 1024, 4096, 0ef30a63997229bfa0f3f7958736c444 +1, 84992, 84992, 1024, 4096, 2abd975868c9805fa456a08f1ab16c91 +1, 86016, 86016, 1024, 4096, 56309326bc80a6216b048934713db907 0, 54, 54, 1, 3110400, c75d2221327d5953b013fdc9d36dbcd3 -1, 87040, 87040, 1024, 4096, eb6986d43812a3edee7f0a587422db77 -1, 88064, 88064, 1024, 4096, ab038bc9d57d2e5434d641dce5e7bb13 +1, 87040, 87040, 1024, 4096, 470fd4997793f53ad2b21b47c6b98bb1 +1, 88064, 88064, 1024, 4096, 1aed57e8ba33350711e1ff668c906953 0, 55, 55, 1, 3110400, 6c8b8c6012b6ac36c4c2a3ab5629ec61 -1, 89088, 89088, 1024, 4096, ee526f1ac04958177b545e714cde2a44 +1, 89088, 89088, 1024, 4096, 9e910446a3b8d30f270c05aca011704d 0, 56, 56, 1, 3110400, 44a05705ad5cb730e7244c36b4f94771 -1, 90112, 90112, 1024, 4096, 77e99ace435ef96c6d258ec12bd1d8d8 -1, 91136, 91136, 1024, 4096, 7101832bf0a8bb43d36f0bd6107b0ae8 +1, 90112, 90112, 1024, 4096, af6c036d66dd5bb5c250f16207173180 +1, 91136, 91136, 1024, 4096, de76d587f349fe597e65cb1f51bdcc34 0, 57, 57, 1, 3110400, 0ee53224814c84224525181aacbd9a39 -1, 92160, 92160, 1024, 4096, 9d6cbd4db1b588072bf0e9ababc40833 +1, 92160, 92160, 1024, 4096, 7abab5bffebfcc801a11f6b7905a13c9 0, 58, 58, 1, 3110400, cd7797aa75c96a2a71e939ea6b677310 -1, 93184, 93184, 1024, 4096, 5c0f3e20b1b9caae82496041b073f0e4 -1, 94208, 94208, 1024, 4096, 3a5a24363a702cc6775ca7fb29304c21 +1, 93184, 93184, 1024, 4096, 3567caaaea75b1cda5920fd6dbf2a016 +1, 94208, 94208, 1024, 4096, 2a6848418d829a273b85620e5b59cabe 0, 59, 59, 1, 3110400, ac2207156da29fd33ca1c66224445bbc -1, 95232, 95232, 1024, 4096, 519bb1e9f1a945e45a5e345764b55a03 +1, 95232, 95232, 1024, 4096, 79d0c213acefa2bc00de4fd455b34df9 0, 60, 60, 1, 3110400, 1669c959bd2b6f245cc83ea00d0de83f -1, 96256, 96256, 1024, 4096, 58b434d59ac97a54fbc1a72a36841d93 -1, 97280, 97280, 1024, 4096, 36d327ce01b032197975d704481373ba +1, 96256, 96256, 1024, 4096, 267414473e0e7c75c7c1dde7be001762 +1, 97280, 97280, 1024, 4096, 893107ddb969cbc25a5aa8c564559836 0, 61, 61, 1, 3110400, a74e6586842a4c877fa9a123e7b8ef94 -1, 98304, 98304, 1024, 4096, 966ebe56895a9fe4a231803276e7687c +1, 98304, 98304, 1024, 4096, 1555a7117d5254afef3e36b1d0a9edd2 0, 62, 62, 1, 3110400, 5af4edbf8a77ead17f4891cbac6d72be 1, 99328, 99328, 1024, 4096, dd92c3241e45d54cc072fc0307d1850c -1, 100352, 100352, 1024, 4096, af6face87dd545c52dbc0f8c085f66ee +1, 100352, 100352, 1024, 4096, 95c55b1767ddea9af80edbb32e2b4dbc 0, 63, 63, 1, 3110400, 52598cb5f3cb75bc401370118bcb2c49 -1, 101376, 101376, 1024, 4096, 70f4ac8c2d680c3f66b3096bb169dd30 -1, 102400, 102400, 1024, 4096, a5b78e534c204a269c40d8a53da9a39a +1, 101376, 101376, 1024, 4096, 1d133e7a83f0cf96a6e9cee90d17975a +1, 102400, 102400, 1024, 4096, b71b82a4abcde640a46fcc3bd6930d51 0, 64, 64, 1, 3110400, d44aa05de89e71b3af23de9afbb2a3b1 -1, 103424, 103424, 1024, 4096, c0f82f0eebe9d9812cf3e38e3fbe6596 +1, 103424, 103424, 1024, 4096, 57697c6f8e32dda304b77b2881b5011d 0, 65, 65, 1, 3110400, 161fd1ff8b477a137e113ce7e6ac26f7 -1, 104448, 104448, 1024, 4096, eec373a11d6294d737548b0ff6fcffff -1, 105472, 105472, 1024, 4096, 9aa7b5313fb4d492c61ef93003cbe85d +1, 104448, 104448, 1024, 4096, 592725ee5ee2adfc02e8c189f402a3d9 +1, 105472, 105472, 1024, 4096, 2b1073734ea08c0cfeeaab15ad04aa60 0, 66, 66, 1, 3110400, b9b5efaf5f74954897882b0f09a5c088 -1, 106496, 106496, 1024, 4096, 85fe03553bd0ef3af6dbffb7efc5c2ad +1, 106496, 106496, 1024, 4096, 18f2a5daef2293e690fe0915127cb795 0, 67, 67, 1, 3110400, 1405f3d5e75c2ffd390b46f7def70478 -1, 107520, 107520, 1024, 4096, a9ee3b7719229b9f772705c7cd804a58 -1, 108544, 108544, 1024, 4096, e392d92e74371656de53c0cca9004480 +1, 107520, 107520, 1024, 4096, 4fa75ff788019d99f6ab0ad2ee5cc3d4 +1, 108544, 108544, 1024, 4096, d40f1172149821d84130990d5acd9395 0, 68, 68, 1, 3110400, 3bf19eda056d5fc609662bf5ca8e3b33 -1, 109568, 109568, 1024, 4096, 247a669c58d412878f89e9a99f46867f +1, 109568, 109568, 1024, 4096, edae14a39d1034cfce5655337df2206e 0, 69, 69, 1, 3110400, 8ba1925dc6b38a340e51aa234b5ff4df -1, 110592, 110592, 1024, 4096, 32c437e01e7961977b02a2abe562b8bb -1, 111616, 111616, 1024, 4096, 2ce6fc2129f6d9eb7423c25539aa2cb7 +1, 110592, 110592, 1024, 4096, 574a6a3b427314c2eb48226d2d7ce67d +1, 111616, 111616, 1024, 4096, ebf13ab2795c091f15b9086d5bf2e11e 0, 70, 70, 1, 3110400, 301aecbe3f8bf3831d6de540a568abbc -1, 112640, 112640, 1024, 4096, cf1974b1dbe086c4299d8199614d0079 -1, 113664, 113664, 1024, 4096, ae311b2ef095c1467900ff4470b290de +1, 112640, 112640, 1024, 4096, 074c63c81345804c7437de33cb5e355f +1, 113664, 113664, 1024, 4096, 58da9edb5e278e292cebebf6b26435b0 0, 71, 71, 1, 3110400, 388565f088710aeb0f50ecdf8ef0ee86 -1, 114688, 114688, 1024, 4096, 00bdb308989a3219d178fb175e84b79e +1, 114688, 114688, 1024, 4096, ce75fd079a21e0637900ac491c4fbc36 0, 72, 72, 1, 3110400, df27196ff8da5085c58979deeae9c4a1 -1, 115712, 115712, 1024, 4096, 2ddfe844f921e3e0561bfce3790a8251 -1, 116736, 116736, 1024, 4096, 0c02111f1250fc674b2cb71770dbd1d3 +1, 115712, 115712, 1024, 4096, 92153c14aeabfb4b4546c340201202b0 +1, 116736, 116736, 1024, 4096, f02e8d23ee0ca80713b4458873ce724f 0, 73, 73, 1, 3110400, 750226c84aae270449e0a20751218217 -1, 117760, 117760, 1024, 4096, cf24fdd955d70a7872b27411f89bccd2 +1, 117760, 117760, 1024, 4096, 0adec04349d269f7dde27c59c7077954 0, 74, 74, 1, 3110400, 076d4246e5494e6d5cf8ffb09be3a751 -1, 118784, 118784, 1024, 4096, 7c5516c05815edae32bade8324974657 -1, 119808, 119808, 1024, 4096, 1e59ed977a9aecc9abe261db11ca2605 +1, 118784, 118784, 1024, 4096, 4408d6824ca6c2080fd76c1ab840382c +1, 119808, 119808, 1024, 4096, c3603730a05cff479148d9b69b7ed2e8 0, 75, 75, 1, 3110400, 9f626289f18a3482628b511840deaa10 -1, 120832, 120832, 1024, 4096, 05a8dce0c37fcc6ab053ac73eb785b0b +1, 120832, 120832, 1024, 4096, 25a6af5ef98aae3c40610e58ca65b8a9 0, 76, 76, 1, 3110400, f925e3ff4bda9962a313b6ac21a201f1 -1, 121856, 121856, 1024, 4096, 91a046c3d0ad3bbfdeb38dcd305d023a -1, 122880, 122880, 1024, 4096, 3f58f6172adc6a3166ec24ee820331ec +1, 121856, 121856, 1024, 4096, 5ad875e4437059157f0f3a5ec911e741 +1, 122880, 122880, 1024, 4096, cfc06fdc755579be7440fca797d81191 0, 77, 77, 1, 3110400, 1d893861545e804944c519e580204988 -1, 123904, 123904, 1024, 4096, 17dea588661e4c31aeb98522afc63ae9 +1, 123904, 123904, 1024, 4096, 7c783d7b973bb8048eeaa568297cfa35 0, 78, 78, 1, 3110400, 4d42fca73082fde38020a8fec0b27db2 -1, 124928, 124928, 1024, 4096, 1e1dc5629306be84cc819a4bf6e64e7c -1, 125952, 125952, 1024, 4096, 44ce3b6d8a17cfebe54e924626f2af94 +1, 124928, 124928, 1024, 4096, cae22b99b2c6fea527fb5c038d3765f8 +1, 125952, 125952, 1024, 4096, fc4b5ef5a5a28102bf782b8732fc2993 0, 79, 79, 1, 3110400, ed88335480ef00aedcf73c3a8712705c -1, 126976, 126976, 1024, 4096, d10235d48b65a30f1b742153e1904699 -1, 128000, 128000, 1024, 4096, bca2dd5314938e30ae693b9690e38f11 +1, 126976, 126976, 1024, 4096, e278968277ccc64992ba6bb73ad9909d +1, 128000, 128000, 1024, 4096, e2eb81d30fe7fa901eaf295fca8bc8b8 0, 80, 80, 1, 3110400, 968ba4c93f80cb8c6fbfaccb765c3d70 -1, 129024, 129024, 1024, 4096, c6e9c444ee31d2fe8e3cde7d089a08c8 +1, 129024, 129024, 1024, 4096, 5a9b99c0639bd80ef7f20971590e23c7 0, 81, 81, 1, 3110400, 01ef52b0a18f46556ba9e00d1b0c77af -1, 130048, 130048, 1024, 4096, 8952dfeace4fd2c84273151248641cbb -1, 131072, 131072, 1024, 4096, 70361338cc7d66a0b1d9fb4b9a106c72 +1, 130048, 130048, 1024, 4096, 2765d109f09efa2f2661dfd2e666f25c +1, 131072, 131072, 1024, 4096, 1ff52d5870cd667388fe69f48e228fc6 0, 82, 82, 1, 3110400, 54582f2ae6878b37cbd1b5c576fd09c7 -1, 132096, 132096, 1024, 4096, 5a6c251fb22fc88ebc346020b4a8fcd7 +1, 132096, 132096, 1024, 4096, 3612470a58bb5eab26239fbd3d097866 0, 83, 83, 1, 3110400, fec6585d244257b52c90cfa19b22fd7c -1, 133120, 133120, 1024, 4096, 9f7558a3d28e5c2c67034496e71d6fca -1, 134144, 134144, 1024, 4096, 3669b9c3951716f471c279fef1baba1a +1, 133120, 133120, 1024, 4096, be170a1e3eba4c53b0e2fc8b795c7767 +1, 134144, 134144, 1024, 4096, abb85ab4987c50e05ecab0e831d53fd6 0, 84, 84, 1, 3110400, be1e0237c5d8bab98aa75a91e0d4bd9b -1, 135168, 135168, 1024, 4096, 3c749f168978e687c8b5986406977e8a +1, 135168, 135168, 1024, 4096, 2e9b5c17dcaf77f171544c0eee6cf191 0, 85, 85, 1, 3110400, 1138a9f316d1a2a9ae3c42d777561595 -1, 136192, 136192, 1024, 4096, 2524384a99ff83fe4c4152a48ae41ed3 -1, 137216, 137216, 1024, 4096, 31074121ab228b6efce8e7d7bd3dce44 +1, 136192, 136192, 1024, 4096, 54c1c5d9c706e1999b2243828736c98d +1, 137216, 137216, 1024, 4096, 7b482f85e123981e8eb37c364b2f4bbe 0, 86, 86, 1, 3110400, 62da42e9e8643ec9b1299bbeaffa4be5 -1, 138240, 138240, 1024, 4096, b62106dc88181c36a57a5e4c133372f4 -1, 139264, 139264, 1024, 4096, 68e582cf173e2355fc0474614c3f3f00 +1, 138240, 138240, 1024, 4096, 0be223967283ac3a0029fad458176155 +1, 139264, 139264, 1024, 4096, 8ec0c4054d484ebf8d68e32c3ffb5924 0, 87, 87, 1, 3110400, 55fc4dcfb7f8bab37518884fc6747416 -1, 140288, 140288, 1024, 4096, 061518430ba9d0fb160ecfab5f80181d +1, 140288, 140288, 1024, 4096, 0308762a4362acbf1c9e1e62e5055880 0, 88, 88, 1, 3110400, 51be69793bfae3fe078d04e8dee3a48b -1, 141312, 141312, 1024, 4096, 0b788c73ac083e5c35d8d6e23071e5a7 -1, 142336, 142336, 1024, 4096, 8e6538e8dce86832b06b78a6a1919a8a +1, 141312, 141312, 1024, 4096, 56a18f795b25ef93d27a53a9f6a87ec9 +1, 142336, 142336, 1024, 4096, ad46ed8c3ac23b79bbd066e43b77f4e6 0, 89, 89, 1, 3110400, 363b794880a2cc06e5be4626c6847c19 -1, 143360, 143360, 1024, 4096, 76a9f155449798cb858c7d33aab635d0 +1, 143360, 143360, 1024, 4096, 62719a7d4521ac82957ce3f52ba21854 0, 90, 90, 1, 3110400, cd1d585cf9cb68f72f7d6a0ec9ab96ab -1, 144384, 144384, 1024, 4096, b4b8c7c06577dc7ec8aa09041d741d15 -1, 145408, 145408, 1024, 4096, 69ef1d797c314b5e6f4ff63818bc4ae5 +1, 144384, 144384, 1024, 4096, 8854128aa8377ad5e52af990d4642ef5 +1, 145408, 145408, 1024, 4096, 38827bf7a129f92062b90fcf03ba80c1 0, 91, 91, 1, 3110400, 138f8686ee7294bf4af072cee7043f52 -1, 146432, 146432, 1024, 4096, a60e780917a71df71171c07fbae7ee8d +1, 146432, 146432, 1024, 4096, 24d4e112b275116dcb512e6b283487e3 0, 92, 92, 1, 3110400, 137c1bdc2bb6fa1e181f84b09c14e0b6 -1, 147456, 147456, 1024, 4096, dc2f78381824b76fa9f2efa8436f91b9 -1, 148480, 148480, 1024, 4096, 1796b71e22f477f6312e1b16d046a778 +1, 147456, 147456, 1024, 4096, 03c374d9d72df87f99427fe1045be8da +1, 148480, 148480, 1024, 4096, c0c5a8fd24d5a9f535118ec266468976 0, 93, 93, 1, 3110400, e7bc46739c46ec886fc5059af72f772a -1, 149504, 149504, 1024, 4096, cea89e76c0df3a9a61ed957beba0456b -1, 150528, 150528, 1024, 4096, 02fd38f6ace4f8ea8821160e37c2e829 +1, 149504, 149504, 1024, 4096, 3381472e14c42a06cdcf35774a0b3a9a +1, 150528, 150528, 1024, 4096, 4c07a7a02831675a686c6f31e2809e4a 0, 94, 94, 1, 3110400, db4c2aa67c76573e4880b029bef59c8d -1, 151552, 151552, 1024, 4096, 15148b9aa2f3211c83c074b4bf94f02b +1, 151552, 151552, 1024, 4096, adde928f734ffe6c07446c9d70214f74 0, 95, 95, 1, 3110400, 3a287113ad2196420a0474243bd1813d -1, 152576, 152576, 1024, 4096, 4db71785b7d01e84ef2da2ca59f38774 -1, 153600, 153600, 1024, 4096, e1a43fdf9aad45826dcba84bd9fba837 +1, 152576, 152576, 1024, 4096, f1ff82fec1ef096090acbf60212b2b69 +1, 153600, 153600, 1024, 4096, e3b271991cc2cd4fdb56616443c9f3e8 0, 96, 96, 1, 3110400, d3ed803ca1984f021802e6c7364cb57f -1, 154624, 154624, 1024, 4096, 30035e6811f6dadc043db12f83a701bc +1, 154624, 154624, 1024, 4096, 025c3272bfb9f24ab687bc818d57d853 0, 97, 97, 1, 3110400, 776d99c2973261c12e978fe9fe5c5794 -1, 155648, 155648, 1024, 4096, 42490702f73b2dc61898937ee4c5dea8 -1, 156672, 156672, 1024, 4096, 20d806b88965a107021abbb04cf3d9a3 +1, 155648, 155648, 1024, 4096, 8bb2de059194408962be4dfdd88775fc +1, 156672, 156672, 1024, 4096, eb61bcbcc9897d01f5645a0662dfbd6d 0, 98, 98, 1, 3110400, 62ee2ec1261db8544ded9db8c4442f15 -1, 157696, 157696, 1024, 4096, 0f1362440e64448b7bccead0028bd311 +1, 157696, 157696, 1024, 4096, 48a3c897183538de9920e94417f54733 0, 99, 99, 1, 3110400, 1bfabc7ab3701e112e76955a449431d7 -1, 158720, 158720, 1024, 4096, 7155472e706f3f46eec2443bba9e8245 -1, 159744, 159744, 1024, 4096, 5e00e0ee23c41794613ed6058e8ce338 +1, 158720, 158720, 1024, 4096, ffe159d137e51d8fd4d5b3639df563a3 +1, 159744, 159744, 1024, 4096, 7702e58e4ae075b6e12e863f8c5d908e 0, 100, 100, 1, 3110400, e03dfc70c25b77fc47ea42ddb8d5da5c -1, 160768, 160768, 1024, 4096, bdb9b47de0545d62966ce63d1852d5c8 +1, 160768, 160768, 1024, 4096, 2e2b497643e1b6bf13dd5e585ecd9092 0, 101, 101, 1, 3110400, b0f0c308b49cb82fad3b4995cb60b6a1 -1, 161792, 161792, 1024, 4096, bed5fd9231e5d15b887356f6d17e2c69 -1, 162816, 162816, 1024, 4096, 7941bb3647bc685b4dedb0ae7257f6cd +1, 161792, 161792, 1024, 4096, fcce76ebba5166966db792dfc77fda3d +1, 162816, 162816, 1024, 4096, ccf5a819e00ce8c5197ae5b2b827f3e5 0, 102, 102, 1, 3110400, 627c888ea94dabff2aaf96c800a85f7a -1, 163840, 163840, 1024, 4096, bfe15767e5b08f31e3e8c094a1014615 -1, 164864, 164864, 1024, 4096, 7898f2dc30f9f201dd1180e3bd2a9a67 +1, 163840, 163840, 1024, 4096, 2385c9e205cfdd5e0b2ac54e9ef0f525 +1, 164864, 164864, 1024, 4096, 40214ba3f9bdc1bbb7d59e1fdb9def2f 0, 103, 103, 1, 3110400, f2231eac6e5885f61f470a5c6b65ceea -1, 165888, 165888, 1024, 4096, 7a72c0f4eefd454af7d8ff720ff45e05 +1, 165888, 165888, 1024, 4096, 52516e860beca0af0d80f79266c761cc 0, 104, 104, 1, 3110400, ec873def59cde7c114fe27ba1b2c25a6 -1, 166912, 166912, 1024, 4096, 37f403392e90eaecbddf0d9f2790e8a3 -1, 167936, 167936, 1024, 4096, 6e014105203c7b5c862f85f1de5c9812 +1, 166912, 166912, 1024, 4096, a25848945235fd70d1021b9a92dafd8d +1, 167936, 167936, 1024, 4096, 38c7a26c7a545df5fa1721ee3e820309 0, 105, 105, 1, 3110400, 7a5e98b10b1f984b624bc6399a45dde2 -1, 168960, 168960, 1024, 4096, 66341b599fb6ca69429dd1a920029348 +1, 168960, 168960, 1024, 4096, 506d3c3b34f060a0516011ca237cb6a5 0, 106, 106, 1, 3110400, 180d7b9ef69a8ee32e5fcc3b9579c11f -1, 169984, 169984, 1024, 4096, 035e13d7d5a6fa841677daeec3b18eef -1, 171008, 171008, 1024, 4096, 5d472d3fee3bcce4f2b160fa38cb126c +1, 169984, 169984, 1024, 4096, 2ef3cd56dfc870a251bb97f4d474be84 +1, 171008, 171008, 1024, 4096, 383c82e600ebadddd0467cc3a9575f3e 0, 107, 107, 1, 3110400, 8c0107e3bda4c993131b361d598b4b4d -1, 172032, 172032, 1024, 4096, fed4ed4953536004232aee9f3f30ee51 +1, 172032, 172032, 1024, 4096, b99763cdc1d5412f89e7d1fcb3bd1c35 0, 108, 108, 1, 3110400, 31e1ea32c3200a41814b5890b81c5211 -1, 173056, 173056, 1024, 4096, 95ff7c3c4ad69884d23c42bf0f27626b -1, 174080, 174080, 1024, 4096, 494881d4095a2d1f798b44b088b3653a +1, 173056, 173056, 1024, 4096, 7b3ecb91c63f7f86d6e96f305b3bd507 +1, 174080, 174080, 1024, 4096, 6945621a1ee0fbc68e7db786bc837f53 0, 109, 109, 1, 3110400, f6223221be5136d03c87333c7f2113c5 -1, 175104, 175104, 1024, 4096, 765ed05036c94cfe3e132b442c187857 -1, 176128, 176128, 1024, 4096, cc92716d9e076750090a67911fe759f9 +1, 175104, 175104, 1024, 4096, fb1de71ab0d840699834d583fbd3468e +1, 176128, 176128, 1024, 4096, 2a3b2d299d87f5b982156ae740fb7b46 0, 110, 110, 1, 3110400, 325d0fb65e35826aebb0f80fc34f426f -1, 177152, 177152, 1024, 4096, 072b375052d0667ac2c7216653e7bbe5 +1, 177152, 177152, 1024, 4096, 6462952e8555172110c37c579d45f63c 0, 111, 111, 1, 3110400, 1328e8c69419fe1c44fc6cfa1f648839 -1, 178176, 178176, 1024, 4096, 6a10a47420e4004eb8bf059394395249 -1, 179200, 179200, 1024, 4096, b405e274e3f13346862a09883dc27156 +1, 178176, 178176, 1024, 4096, 279537a0668d254a6710c935f2a7b8d7 +1, 179200, 179200, 1024, 4096, 286a27fee95bf8773ee8ea03621e9502 0, 112, 112, 1, 3110400, b234f9aab6965e136bb283a2ad0fbb68 -1, 180224, 180224, 1024, 4096, 6a035de2ce67714cc256013fcaa6dc34 +1, 180224, 180224, 1024, 4096, 343413b110fe48674dddeba071440707 0, 113, 113, 1, 3110400, 3961ef43173c69a28d2196f4fa11d37a -1, 181248, 181248, 1024, 4096, 07d43a968099c46e0696714abf0e46a4 -1, 182272, 182272, 1024, 4096, 0d24fc81f9c5d8b9b1560520e073d300 +1, 181248, 181248, 1024, 4096, 66265d80629369fc9fffddbbe6ef104d +1, 182272, 182272, 1024, 4096, 3ff193da4d2168f97f17841f9669d33e 0, 114, 114, 1, 3110400, 943c6dd42254d346d81fd55bfad60573 -1, 183296, 183296, 1024, 4096, fe4e8740a5ef9eb0dbeb44e7d3df3d09 +1, 183296, 183296, 1024, 4096, dd4074398b101502c29009687686e78d 0, 115, 115, 1, 3110400, 0028c32eacb6f4d77cb98cf856d266e4 -1, 184320, 184320, 1024, 4096, e17bc55c8cb665aed6f304c8f51bf111 -1, 185344, 185344, 1024, 4096, 016964bc4828aaa33fae69cc46a511c9 +1, 184320, 184320, 1024, 4096, 562be444896543f259527081c7795597 +1, 185344, 185344, 1024, 4096, 145b4b260f2393ec1e3464d79c87fe8e 0, 116, 116, 1, 3110400, f478fe49fed80b92eaa182aa8e794077 -1, 186368, 186368, 1024, 4096, 0186f83d39b824d31300f2e702df2d55 +1, 186368, 186368, 1024, 4096, 6884ebc820bb41e61dc54a87bd55011e 0, 117, 117, 1, 3110400, 9a52c061c135bd75ee317fe48a2cddf8 -1, 187392, 187392, 1024, 4096, f5df5e5b848a7ddb17e146c03bbcbdeb -1, 188416, 188416, 1024, 4096, f17507ae2559789a63fa688e8b30fafd +1, 187392, 187392, 1024, 4096, d2d8b2fd7a140a3f32d5649f8e507637 +1, 188416, 188416, 1024, 4096, 767071a409e0b07bd2cdb250c3c89607 0, 118, 118, 1, 3110400, c327b95c8afa716f7719603d2b65679b -1, 189440, 189440, 1024, 4096, 1211a9da89a2fb95197f0229acaf998f -1, 190464, 190464, 1024, 4096, ae4e0feea34dd9f6dfb9981987cd9a99 +1, 189440, 189440, 1024, 4096, 64c4eed5e1b85e0728b1b0e3de30ffa1 +1, 190464, 190464, 1024, 4096, 11ffef7e85d9925a4032b3bcd9740e20 0, 119, 119, 1, 3110400, edd3b4c4fa157940b9c252a7d94e6f55 -1, 191488, 191488, 1024, 4096, 403e646272b9135422ba0e3a99fdd9e1 +1, 191488, 191488, 1024, 4096, 99893421a493664be17085567e160280 0, 120, 120, 1, 3110400, 5ccdffe7356a73d2d11eb7767ddfa396 -1, 192512, 192512, 1024, 4096, 301db3a7c1a1c7c6a1594c5dc1f248bf -1, 193536, 193536, 1024, 4096, 3c804053fad95868b7fe412d385105b0 +1, 192512, 192512, 1024, 4096, ea422077bc582aef4af5bf3ca3aa062a +1, 193536, 193536, 1024, 4096, a9e7ab9c45faf39f3cd1eee69c95d647 0, 121, 121, 1, 3110400, 7c4d8083656581ccc666597da5559a46 -1, 194560, 194560, 1024, 4096, 517a23469cada9850e27e3b2c1dcb6c2 +1, 194560, 194560, 1024, 4096, fc19b6642df3b85c7ebe684e705bf29d 0, 122, 122, 1, 3110400, 28cae533418f9a5d62869cbed0be384c -1, 195584, 195584, 1024, 4096, 087f72ac18ee46f75b73fe3fb6324f71 -1, 196608, 196608, 1024, 4096, 49aefd3f94d9e4783c6eab8fc877a8a9 +1, 195584, 195584, 1024, 4096, 39420620aea9d61b240691dada0f3063 +1, 196608, 196608, 1024, 4096, 5ad516a55655cdc2a3348badc2c7e5a1 0, 123, 123, 1, 3110400, e9cf527a059c80461fd507bab4817069 -1, 197632, 197632, 1024, 4096, c927cf0b475a8790a8adce8b5c2b934a +1, 197632, 197632, 1024, 4096, fa4f3d45c1cfc88088b4cd6f2924184d 0, 124, 124, 1, 3110400, a2f2518b8a25932afbb78523e8da289e -1, 198656, 198656, 1024, 4096, 7316a62c368936fa3a9905ee0f791cf9 -1, 199680, 199680, 1024, 4096, f6f14ff29ae4ba46bcdc7f13f7d94c0e +1, 198656, 198656, 1024, 4096, 689be1d6f84b136537df11b8ed22b540 +1, 199680, 199680, 1024, 4096, 9612dad6c93c75b6911f21997f2f7aee 0, 125, 125, 1, 3110400, 8fcbddce7f2a6c3bc380ad4cec17e51c -1, 200704, 200704, 1024, 4096, fe187526a81876d845fe9908edca471a -1, 201728, 201728, 1024, 4096, 4959639fa30c838205aabdc00f23642c +1, 200704, 200704, 1024, 4096, defe4b66e5dd9c6a527aeb9ebec04cdf +1, 201728, 201728, 1024, 4096, 0c39b71be01611d6be02b796aec2c6de 0, 126, 126, 1, 3110400, 32ff7b550d09821b2b1eb64c288559ba -1, 202752, 202752, 1024, 4096, fda7cb19cc1efbbe1921ce981e0c7520 +1, 202752, 202752, 1024, 4096, 2150a3d6fdec61cd587b83217f9bbb2c 0, 127, 127, 1, 3110400, 1eb4e9050a6657ab9290ac58ed3aa93f -1, 203776, 203776, 1024, 4096, fa3dc6a44013a4dd8d50103a75f4c983 -1, 204800, 204800, 1024, 4096, f59136f6a18fd40c52a2ae46058cfda0 +1, 203776, 203776, 1024, 4096, 4be35b36d46ca56b778ae0afdd1e4200 +1, 204800, 204800, 1024, 4096, fb79d3d9d0e4d590882cbd023bbcd00d 0, 128, 128, 1, 3110400, e45fd52e9ec3ad2d42740dd7cb5e971b -1, 205824, 205824, 1024, 4096, db5d39da79236eb59a29a372a68b640b +1, 205824, 205824, 1024, 4096, d4295a4a32d647a04ec0eab639c0d9fc 0, 129, 129, 1, 3110400, d625b970a797e37e465d9319471d40c3 -1, 206848, 206848, 1024, 4096, b5ad26b7f7fc2584993e2cdaa4a6b8b2 -1, 207872, 207872, 1024, 4096, d823d127304842b99b470fa4e9f5e5de +1, 206848, 206848, 1024, 4096, f03478b7689af9bdf6e67d271a4b3114 +1, 207872, 207872, 1024, 4096, 9fd97010278dc9147d8b73be9aacfb35 0, 130, 130, 1, 3110400, b98e4a8fd994915a3dde3def26a9b171 -1, 208896, 208896, 1024, 4096, 9e4e02881a76e858e6787f9c1d42a249 +1, 208896, 208896, 1024, 4096, 2b9670707ad661b2125620d2156f11f6 0, 131, 131, 1, 3110400, a99b759bdfcf7f7cee8f1ee84ca2d66d -1, 209920, 209920, 1024, 4096, a476392ed5f666c03e89ab2da5ff7a58 -1, 210944, 210944, 1024, 4096, 7576416a29e679630a5233cc63e623d5 +1, 209920, 209920, 1024, 4096, e1b2afbfcb5edb8e4b88ae9c08848c30 +1, 210944, 210944, 1024, 4096, 58c8914fd4ec12bfe13f388050b251e8 0, 132, 132, 1, 3110400, 5439cd9643a76d21e5f1deb0aa4000a2 -1, 211968, 211968, 1024, 4096, 7239bc64a6723444d3d85dc246fafcff -1, 212992, 212992, 1024, 4096, 85ebb8c83070b65dda6e4aa2a0986825 +1, 211968, 211968, 1024, 4096, 4d8e0b0d4cd31f98eb4ca9922bba1497 +1, 212992, 212992, 1024, 4096, 02b1c362c2f1939fa41a4cc8d4b25d6a 0, 133, 133, 1, 3110400, 383640e375fa6b46bba21acd556f0efd -1, 214016, 214016, 1024, 4096, 59f1301cc73828906b603ddfc6aa03dc +1, 214016, 214016, 1024, 4096, 10d3b076171713e9978c67515fdd4304 0, 134, 134, 1, 3110400, e91ba9ef2595fbee20fb0f1d5e0b92ba -1, 215040, 215040, 1024, 4096, f1b0c9d2289583354ff57376c8210644 -1, 216064, 216064, 1024, 4096, 8c52453179a06d060f5e05efed91056b +1, 215040, 215040, 1024, 4096, 726450c85dbd838bc00c6866d4c10786 +1, 216064, 216064, 1024, 4096, 3479045f30a97faaed2f241478ea0447 0, 135, 135, 1, 3110400, 9c8ce07f22215b8450b01e82fc085b3d -1, 217088, 217088, 1024, 4096, 6df87b285da88b1f119dd8f1d7129a39 +1, 217088, 217088, 1024, 4096, 63d5ca0f8d7e086dfae54e86a75f8971 0, 136, 136, 1, 3110400, 4f11b553eaaa1feb682842a1123e1b43 -1, 218112, 218112, 1024, 4096, d38a17cb3b0d87d6344d87a958464046 -1, 219136, 219136, 1024, 4096, 2ba9b50d7634c431fa7001a4bfe5bc98 +1, 218112, 218112, 1024, 4096, 41953b97d8f2d3e5c05827c670e3c562 +1, 219136, 219136, 1024, 4096, 50709f01bf8dbe8e40f5b414211e7dbe 0, 137, 137, 1, 3110400, 32e8823643ce4cb0154482611f4de51d -1, 220160, 220160, 1024, 4096, 5bac7eea4ea1f7fd21d01cadfaf525a7 +1, 220160, 220160, 1024, 4096, 03d813116d70fed14987e17ebcaeed3e 0, 138, 138, 1, 3110400, 207ee505f0cfb54a3fd1fd5256ba906a -1, 221184, 221184, 1024, 4096, 3ffc6fe54cbfdd2b3cd89042abd78593 -1, 222208, 222208, 1024, 4096, 223c7972f0728ebad37eec0ee5e390ef +1, 221184, 221184, 1024, 4096, d695e2905aac1dee39a8f35e3a4b7fed +1, 222208, 222208, 1024, 4096, 35c5c7a9cfe5cfb08d3dd269aec9b901 0, 139, 139, 1, 3110400, f95de0e1f3cd2559b6a81a6dbe53ed5c -1, 223232, 223232, 1024, 4096, b65e7243cb88ce749c876beff4c23589 +1, 223232, 223232, 1024, 4096, 2a4f3699775e0d67651c4c40913c9059 0, 140, 140, 1, 3110400, 3c47b1ea481bdae7b7730084407fd22a -1, 224256, 224256, 1024, 4096, 451b0af4a0b663fe08cba704374fbe35 -1, 225280, 225280, 1024, 4096, e25d0a85ebc82d768f03dabbf28b5bf7 +1, 224256, 224256, 1024, 4096, bb561814ffb5b76a1faf7df4375c233e +1, 225280, 225280, 1024, 4096, a3c632a0d54e07e3928aec8ef169fd11 0, 141, 141, 1, 3110400, fbec533f0cb4d79185e09c9917329473 -1, 226304, 226304, 1024, 4096, 5c0826fe1bd67f3ca1faeb72932e88d4 -1, 227328, 227328, 1024, 4096, bd17d92b344769f92f8ffffa1fb64fe5 +1, 226304, 226304, 1024, 4096, a805c35e91615f17669130ec58191b75 +1, 227328, 227328, 1024, 4096, 0858806663f6430219b68df7ff83a932 0, 142, 142, 1, 3110400, 5b9f1cf510bc72d42772a78d400d9831 -1, 228352, 228352, 1024, 4096, a8ab495cc3574c1f0f516de13a296d82 +1, 228352, 228352, 1024, 4096, 59339810dea47a705ab9e0913f7a88d5 0, 143, 143, 1, 3110400, 6b031f180439e753b6b0e36de46dc1a5 -1, 229376, 229376, 1024, 4096, b597385268405bf5fcbde4cb4c2431e0 -1, 230400, 230400, 1024, 4096, b27e1973871e6559908b71d01a3cfb44 +1, 229376, 229376, 1024, 4096, 6d9cdd81e0ba85ad4e00c34e2a096611 +1, 230400, 230400, 1024, 4096, cd6dd8dd0dc5198b7bf0b45d4ecc2608 0, 144, 144, 1, 3110400, c09870b1e13efa8b685d89ebd781e835 -1, 231424, 231424, 1024, 4096, ede2d1664ba9685cc71a376cfce5aee4 +1, 231424, 231424, 1024, 4096, c2dd972eb34af27a210bcfa3e5f8da93 0, 145, 145, 1, 3110400, 439c6cc6f7157eaf046e06d9e55ddf69 -1, 232448, 232448, 1024, 4096, 6eaf360e7798b2949fda47bd906604b5 -1, 233472, 233472, 1024, 4096, 06de403c43e23b4cf650404ad5725591 +1, 232448, 232448, 1024, 4096, 0993bc45c9582048d6982beeaec6b72e +1, 233472, 233472, 1024, 4096, ae93c593fd775ae997c43eef40fe8d0e 0, 146, 146, 1, 3110400, 7d5520c184c7bf3f175eea3526deb7a8 From 713f9c5b5d646c4be55b04d691bac21ecbd74089 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 8 Dec 2017 20:35:08 +0100 Subject: [PATCH 1286/2557] avfilter/vf_scale: add more aliases for "range" options Signed-off-by: Paul B Mahol --- doc/filters.texi | 4 ++-- libavfilter/vf_scale.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 0ec7d652a38f6..33464382314fe 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -13086,13 +13086,13 @@ a specific value used for the output and encoder. If not specified, the range depends on the pixel format. Possible values: @table @samp -@item auto +@item auto/unknown Choose automatically. @item jpeg/full/pc Set full range (0-255 in case of 8-bit luma). -@item mpeg/tv +@item mpeg/limited/tv Set "MPEG" range (16-235 in case of 8-bit luma). @end table diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 2fd9c90d84f33..9f45032e85522 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -578,7 +578,9 @@ static const AVOption scale_options[] = { { "in_range", "set input color range", OFFSET( in_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 2, FLAGS, "range" }, { "out_range", "set output color range", OFFSET(out_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 2, FLAGS, "range" }, { "auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 0, FLAGS, "range" }, + { "unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 0, FLAGS, "range" }, { "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_JPEG}, 0, 0, FLAGS, "range" }, + { "limited",NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_MPEG}, 0, 0, FLAGS, "range" }, { "jpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_JPEG}, 0, 0, FLAGS, "range" }, { "mpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_MPEG}, 0, 0, FLAGS, "range" }, { "tv", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_MPEG}, 0, 0, FLAGS, "range" }, From 7993ec19af394fdc58ec64165bc0b12619543a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= Date: Sun, 3 Dec 2017 09:15:23 +0100 Subject: [PATCH 1287/2557] hevc: Add hevc_get_pixel_4/8/12/16/24/32/48/64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checkasm timings: block size bitdepth C NEON 4 8 bit: 146.7 48.7 10 bit: 146.7 52.7 8 8 bit: 430.3 84.4 10 bit: 430.4 119.5 12 8 bit: 812.8 141.0 10 bit: 812.8 195.0 16 8 bit: 1499.1 268.0 10 bit: 1498.9 368.4 24 8 bit: 4394.2 574.8 10 bit: 3696.3 804.8 32 8 bit: 5108.6 568.9 10 bit: 4249.6 918.8 48 8 bit: 16819.6 2304.9 10 bit: 13882.0 3178.5 64 8 bit: 13490.8 1799.5 10 bit: 11018.5 2519.4 Signed-off-by: Martin Storsjö --- libavcodec/arm/Makefile | 3 +- libavcodec/arm/hevc_mc.S | 395 ++++++++++++++++++++++++++++++ libavcodec/arm/hevcdsp_init_arm.c | 67 +++++ 3 files changed, 464 insertions(+), 1 deletion(-) create mode 100644 libavcodec/arm/hevc_mc.S diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile index b48745ad40aca..49e17ce0df189 100644 --- a/libavcodec/arm/Makefile +++ b/libavcodec/arm/Makefile @@ -135,7 +135,8 @@ NEON-OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_neon.o \ NEON-OBJS-$(CONFIG_APE_DECODER) += arm/apedsp_neon.o NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_neon.o \ arm/synth_filter_neon.o -NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevc_idct.o +NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevc_idct.o \ + arm/hevc_mc.o NEON-OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_neon.o NEON-OBJS-$(CONFIG_RV40_DECODER) += arm/rv34dsp_neon.o \ arm/rv40dsp_neon.o diff --git a/libavcodec/arm/hevc_mc.S b/libavcodec/arm/hevc_mc.S new file mode 100644 index 0000000000000..f499d294b92a8 --- /dev/null +++ b/libavcodec/arm/hevc_mc.S @@ -0,0 +1,395 @@ +/* + * ARM NEON optimised MC functions for HEVC decoding + * + * Copyright (c) 2017 Alexandra Hájková + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +.macro get_pixels4 bitdepth +function ff_hevc_get_pixels_4_\bitdepth\()_neon, export=1 +@r0 dst, r1 dststride, r2 src, r3 srcstride + ldr r12, [sp] @height + cmp r12, #0 + it eq + bxeq lr + +1: + .if \bitdepth == 8 + vld1.32 {d0[0]}, [r2], r3 + vld1.32 {d1[0]}, [r2], r3 + vld1.32 {d2[0]}, [r2], r3 + vld1.32 {d3[0]}, [r2], r3 + vshll.u8 q8, d0, #6 + vshll.u8 q9, d1, #6 + vshll.u8 q10, d2, #6 + vshll.u8 q11, d3, #6 + .else + vld1.16 {d0}, [r2], r3 + vld1.16 {d1}, [r2], r3 + vld1.16 {d2}, [r2], r3 + vld1.16 {d3}, [r2], r3 + vshl.i16 d16, d0, #4 + vshl.i16 d18, d1, #4 + vshl.i16 d20, d2, #4 + vshl.i16 d22, d3, #4 + .endif + + vst1.16 {d16}, [r0, :64], r1 + vst1.16 {d18}, [r0, :64], r1 + vst1.16 {d20}, [r0, :64], r1 + vst1.16 {d22}, [r0, :64], r1 + subs r12, #4 + bgt 1b + + bx lr +endfunc +.endm + +.macro get_pixels8 bitdepth +function ff_hevc_get_pixels_8_\bitdepth\()_neon, export=1 +@r0 dst, r1 dststride, r2 src, r3 srcstride + ldr r12, [sp] @height + cmp r12, #0 + it eq + bxeq lr + +1: + .if \bitdepth == 8 + vld1.8 {d0}, [r2], r3 + vld1.8 {d1}, [r2], r3 + vld1.8 {d2}, [r2], r3 + vld1.8 {d3}, [r2], r3 + vshll.u8 q8, d0, #6 + vshll.u8 q9, d1, #6 + vshll.u8 q10, d2, #6 + vshll.u8 q11, d3, #6 + .else + vld1.16 {d16-d17}, [r2], r3 + vld1.16 {d18-d19}, [r2], r3 + vld1.16 {d20-d21}, [r2], r3 + vld1.16 {d22-d23}, [r2], r3 + vshl.i16 q8, q8, #4 + vshl.i16 q9, q9, #4 + vshl.i16 q10, q10, #4 + vshl.i16 q11, q11, #4 + .endif + + vst1.16 {d16-d17}, [r0, :64], r1 + vst1.16 {d18-d19}, [r0, :64], r1 + vst1.16 {d20-d21}, [r0, :64], r1 + vst1.16 {d22-d23}, [r0, :64], r1 + subs r12, #4 + bgt 1b + + bx lr +endfunc +.endm + +.macro get_pixels12 bitdepth +function ff_hevc_get_pixels_12_\bitdepth\()_neon, export=1 +@r0 - dst, r1 - dststride, r2 - src, r3 - srcstride + ldr r12, [sp] @height + cmp r12, #0 + it eq + bxeq lr + push {r4-r5, lr} + add r4, r0, #16 + +1: + .if \bitdepth == 8 + add r5, r2, #8 + vld1.8 {d0}, [r2], r3 + vld1.32 {d4[0]}, [r5], r3 + vld1.8 {d1}, [r2], r3 + vld1.32 {d5[0]}, [r5], r3 + vld1.8 {d2}, [r2], r3 + vld1.32 {d6[0]}, [r5], r3 + vld1.8 {d3}, [r2], r3 + vld1.32 {d7[0]}, [r5], r3 + vshll.u8 q8, d0, #6 + vshll.u8 q12, d4, #6 + vshll.u8 q9, d1, #6 + vshll.u8 q13, d5, #6 + vshll.u8 q10, d2, #6 + vshll.u8 q14, d6, #6 + vshll.u8 q11, d3, #6 + vshll.u8 q15, d7, #6 + .else + add r5, r2, #16 + vld1.16 {d16-d17}, [r2], r3 + vld1.16 {d24}, [r5], r3 + vld1.16 {d18-d19}, [r2], r3 + vld1.16 {d26}, [r5], r3 + vld1.16 {d20-d21}, [r2], r3 + vld1.16 {d28}, [r5], r3 + vld1.16 {d22-d23}, [r2], r3 + vld1.16 {d30}, [r5], r3 + vshl.i16 q8, q8, #4 + vshl.i16 d24, d24, #4 + vshl.i16 q9, q9, #4 + vshl.i16 d26, d26, #4 + vshl.i16 q10, q10, #4 + vshl.i16 d28, d28, #4 + vshl.i16 q11, q11, #4 + vshl.i16 d30, d30, #4 + .endif + + vst1.16 {d16-d17}, [r0, :64], r1 + vst1.16 {d24}, [r4, :64], r1 + vst1.16 {d18-d19}, [r0, :64], r1 + vst1.16 {d26}, [r4, :64], r1 + vst1.16 {d20-d21}, [r0, :64], r1 + vst1.16 {d28}, [r4, :64], r1 + vst1.16 {d22-d23}, [r0, :64], r1 + vst1.16 {d30}, [r4, :64], r1 + subs r12, #4 + bgt 1b + + pop {r4-r5, pc} +endfunc +.endm + +@8 bitdepth case +.macro process_8 load + vld1.8 {d0-d1}, [\load], r3 + vld1.8 {d2-d3}, [\load], r3 + vld1.8 {d4-d5}, [\load], r3 + vld1.8 {d6-d7}, [\load], r3 + vshll.u8 q8, d0, #6 + vshll.u8 q9, d1, #6 + vshll.u8 q10, d2, #6 + vshll.u8 q11, d3, #6 + vshll.u8 q12, d4, #6 + vshll.u8 q13, d5, #6 + vshll.u8 q14, d6, #6 + vshll.u8 q15, d7, #6 +.endm + +@10 bitdepth case +.macro process_10 load + vld1.16 {d16-d19}, [\load], r3 + vld1.16 {d20-d23}, [\load], r3 + vld1.16 {d24-d27}, [\load], r3 + vld1.16 {d28-d31}, [\load], r3 + vshl.i16 q8, q8, #4 + vshl.i16 q9, q9, #4 + vshl.i16 q10, q10, #4 + vshl.i16 q11, q11, #4 + vshl.i16 q12, q12, #4 + vshl.i16 q13, q13, #4 + vshl.i16 q14, q14, #4 + vshl.i16 q15, q15, #4 +.endm + +.macro store_4x16 store + vst1.16 {d16-d19}, [\store, :128], r1 + vst1.16 {d20-d23}, [\store, :128], r1 + vst1.16 {d24-d27}, [\store, :128], r1 + vst1.16 {d28-d31}, [\store, :128], r1 +.endm + +.macro get_pixels16 bitdepth +function ff_hevc_get_pixels_16_\bitdepth\()_neon, export=1 +@r0 dst, r1 dststride, r2 src, r3 srcstride + ldr r12, [sp] @height + cmp r12, #0 + it eq + bxeq lr + +1: + .if \bitdepth == 8 + process_8 r2 + .else + process_10 r2 + .endif + + store_4x16 r0 + subs r12, #4 + bgt 1b + + bx lr +endfunc +.endm + +.macro get_pixels24 bitdepth +function ff_hevc_get_pixels_24_\bitdepth\()_neon, export=1 +@r0 dst, r1 dststride, r2 src, r3 srcstride + ldr r12, [sp] @height + cmp r12, #0 + it eq + bxeq lr + + push {r0-r4, lr} + push {r12} + bl X(ff_hevc_get_pixels_8_\bitdepth\()_neon) + pop {r12} + pop {r0-r4, lr} + + .if \bitdepth == 8 + add r2, #8 + .else + add r2, #16 + .endif + add r0, #16 + b X(ff_hevc_get_pixels_16_\bitdepth\()_neon) +endfunc +.endm + +.macro get_pixels32 bitdepth +function ff_hevc_get_pixels_32_\bitdepth\()_neon, export=1 +@r0 dst, r1 dststride, r2 src, r3 srcstride + ldr r12, [sp] @height + cmp r12, #0 + it eq + bxeq lr + push {r4-r5, lr} + .if \bitdepth == 8 + add r4, r2, #16 + .else + add r4, r2, #32 + .endif + add r5, r0, #32 + +1: + .if \bitdepth == 8 + process_8 r2 + .else + process_10 r2 + .endif + store_4x16 r0 + + .if \bitdepth == 8 + process_8 r4 + .else + process_10 r4 + .endif + store_4x16 r5 + + subs r12, #4 + bgt 1b + + pop {r4-r5, pc} +endfunc +.endm + +.macro get_pixels48 bitdepth +function ff_hevc_get_pixels_48_\bitdepth\()_neon, export=1 +@r0 dst, r1 dststride, r2 src, r3 srcstride + ldr r12, [sp] @height + cmp r12, #0 + it eq + bxeq lr + + push {r0-r4, lr} + push {r12} + bl X(ff_hevc_get_pixels_16_\bitdepth\()_neon) + pop {r12} + pop {r0-r4, lr} + + .if \bitdepth == 8 + add r2, #16 + .else + add r2, #32 + .endif + add r0, #32 + b X(ff_hevc_get_pixels_32_\bitdepth\()_neon) +endfunc +.endm + +.macro get_pixels64 bitdepth +function ff_hevc_get_pixels_64_\bitdepth\()_neon, export=1 +@r0 dst, r1 dststride, r2 src, r3 srcstride + ldr r12, [sp] @height + cmp r12, #0 + it eq + bxeq lr + push {r4-r9, lr} + .if \bitdepth == 8 + add r4, r2, #16 + add r6, r4, #16 + add r8, r6, #16 + .else + add r4, r2, #32 + add r6, r4, #32 + add r8, r6, #32 + .endif + add r5, r0, #32 + add r7, r5, #32 + add r9, r7, #32 + +1: + .if \bitdepth == 8 + process_8 r2 + .else + process_10 r2 + .endif + store_4x16 r0 + + .if \bitdepth == 8 + process_8 r4 + .else + process_10 r4 + .endif + store_4x16 r5 + + .if \bitdepth == 8 + process_8 r6 + .else + process_10 r6 + .endif + store_4x16 r7 + .if \bitdepth == 8 + process_8 r8 + .else + process_10 r8 + .endif + store_4x16 r9 + + subs r12, #4 + bgt 1b + + pop {r4-r9, pc} + +endfunc +.endm + +get_pixels4 8 +get_pixels4 10 + +get_pixels8 8 +get_pixels8 10 + +get_pixels12 8 +get_pixels12 10 + +get_pixels16 8 +get_pixels16 10 + +get_pixels24 8 +get_pixels24 10 + +get_pixels32 8 +get_pixels32 10 + +get_pixels48 8 +get_pixels48 10 + +get_pixels64 8 +get_pixels64 10 diff --git a/libavcodec/arm/hevcdsp_init_arm.c b/libavcodec/arm/hevcdsp_init_arm.c index a8b03eb3567ba..60c211de25a50 100644 --- a/libavcodec/arm/hevcdsp_init_arm.c +++ b/libavcodec/arm/hevcdsp_init_arm.c @@ -61,6 +61,55 @@ void ff_hevc_idct_8x8_10_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_16x16_10_neon(int16_t *coeffs, int col_limit); void ff_hevc_idct_32x32_10_neon(int16_t *coeffs, int col_limit); +void ff_hevc_get_pixels_4_8_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_4_10_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_8_8_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_8_10_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_12_8_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_12_10_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_16_8_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_16_10_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_24_8_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_24_10_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_32_8_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_32_10_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_48_8_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_48_10_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_64_8_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); +void ff_hevc_get_pixels_64_10_neon(int16_t *dst, ptrdiff_t dststride, uint8_t *src, + ptrdiff_t srcstride, int height, int mx, int my, + int16_t *mcbuffer); + av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, int bit_depth) { int cpu_flags = av_get_cpu_flags(); @@ -81,6 +130,15 @@ av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, int bit_depth) c->idct[1] = ff_hevc_idct_8x8_8_neon; c->idct[2] = ff_hevc_idct_16x16_8_neon; c->idct[3] = ff_hevc_idct_32x32_8_neon; + + c->put_hevc_qpel[0][0][0] = ff_hevc_get_pixels_4_8_neon; + c->put_hevc_qpel[0][0][1] = ff_hevc_get_pixels_8_8_neon; + c->put_hevc_qpel[0][0][2] = ff_hevc_get_pixels_12_8_neon; + c->put_hevc_qpel[0][0][3] = ff_hevc_get_pixels_16_8_neon; + c->put_hevc_qpel[0][0][4] = ff_hevc_get_pixels_24_8_neon; + c->put_hevc_qpel[0][0][5] = ff_hevc_get_pixels_32_8_neon; + c->put_hevc_qpel[0][0][6] = ff_hevc_get_pixels_48_8_neon; + c->put_hevc_qpel[0][0][7] = ff_hevc_get_pixels_64_8_neon; } if (bit_depth == 10) { c->add_residual[0] = ff_hevc_add_residual_4x4_10_neon; @@ -97,6 +155,15 @@ av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, int bit_depth) c->idct[1] = ff_hevc_idct_8x8_10_neon; c->idct[2] = ff_hevc_idct_16x16_10_neon; c->idct[3] = ff_hevc_idct_32x32_10_neon; + + c->put_hevc_qpel[0][0][0] = ff_hevc_get_pixels_4_10_neon; + c->put_hevc_qpel[0][0][1] = ff_hevc_get_pixels_8_10_neon; + c->put_hevc_qpel[0][0][2] = ff_hevc_get_pixels_12_10_neon; + c->put_hevc_qpel[0][0][3] = ff_hevc_get_pixels_16_10_neon; + c->put_hevc_qpel[0][0][4] = ff_hevc_get_pixels_24_10_neon; + c->put_hevc_qpel[0][0][5] = ff_hevc_get_pixels_32_10_neon; + c->put_hevc_qpel[0][0][6] = ff_hevc_get_pixels_48_10_neon; + c->put_hevc_qpel[0][0][7] = ff_hevc_get_pixels_64_10_neon; } } } From 869efbf971208faccfdd88680178afaf5b1d4e77 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Thu, 7 Dec 2017 22:01:54 +0100 Subject: [PATCH 1288/2557] avfilter/x86/vf_threshold : add threshold16 SIMD (SSE4 and AVX2) --- libavfilter/x86/vf_threshold.asm | 21 ++++++++++++------ libavfilter/x86/vf_threshold_init.c | 34 +++++++++++++++++------------ 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/libavfilter/x86/vf_threshold.asm b/libavfilter/x86/vf_threshold.asm index 56a6c242d8f83..098069b0835b6 100644 --- a/libavfilter/x86/vf_threshold.asm +++ b/libavfilter/x86/vf_threshold.asm @@ -25,16 +25,18 @@ SECTION_RODATA pb_128: times 16 db 128 +pb_128_0 : times 8 db 0, 128 SECTION .text -%macro THRESHOLD_8 0 +;%1 depth (8 or 16) ; %2 b or w ; %3 constant +%macro THRESHOLD 3 %if ARCH_X86_64 -cglobal threshold8, 10, 13, 5, in, threshold, min, max, out, ilinesize, tlinesize, flinesize, slinesize, olinesize, w, h, x +cglobal threshold%1, 10, 13, 5, in, threshold, min, max, out, ilinesize, tlinesize, flinesize, slinesize, olinesize, w, h, x mov wd, dword wm mov hd, dword hm %else -cglobal threshold8, 5, 7, 5, in, threshold, min, max, out, w, x +cglobal threshold%1, 5, 7, 5, in, threshold, min, max, out, w, x mov wd, r10m %define ilinesizeq r5mp %define tlinesizeq r6mp @@ -43,7 +45,10 @@ cglobal threshold8, 5, 7, 5, in, threshold, min, max, out, w, x %define olinesizeq r9mp %define hd r11mp %endif - VBROADCASTI128 m4, [pb_128] + VBROADCASTI128 m4, [%3] +%if %1 == 16 + add wq, wq ; w *= 2 (16 bits instead of 8) +%endif add inq, wq add thresholdq, wq add minq, wq @@ -60,7 +65,7 @@ cglobal threshold8, 5, 7, 5, in, threshold, min, max, out, w, x movu m3, [maxq + xq] pxor m0, m4 pxor m1, m4 - pcmpgtb m0, m1 + pcmpgt%2 m0, m1 PBLENDVB m3, m2, m0 movu [outq + xq], m3 add xq, mmsize @@ -77,9 +82,11 @@ RET %endmacro INIT_XMM sse4 -THRESHOLD_8 +THRESHOLD 8, b, pb_128 +THRESHOLD 16, w, pb_128_0 %if HAVE_AVX2_EXTERNAL INIT_YMM avx2 -THRESHOLD_8 +THRESHOLD 8, b, pb_128 +THRESHOLD 16, w, pb_128_0 %endif diff --git a/libavfilter/x86/vf_threshold_init.c b/libavfilter/x86/vf_threshold_init.c index db0559533d410..8e4229679194b 100644 --- a/libavfilter/x86/vf_threshold_init.c +++ b/libavfilter/x86/vf_threshold_init.c @@ -23,20 +23,19 @@ #include "libavutil/x86/cpu.h" #include "libavfilter/threshold.h" -void ff_threshold8_sse4(const uint8_t *in, const uint8_t *threshold, - const uint8_t *min, const uint8_t *max, - uint8_t *out, - ptrdiff_t ilinesize, ptrdiff_t tlinesize, - ptrdiff_t flinesize, ptrdiff_t slinesize, - ptrdiff_t olinesize, - int w, int h); -void ff_threshold8_avx2(const uint8_t *in, const uint8_t *threshold, - const uint8_t *min, const uint8_t *max, - uint8_t *out, - ptrdiff_t ilinesize, ptrdiff_t tlinesize, - ptrdiff_t flinesize, ptrdiff_t slinesize, - ptrdiff_t olinesize, - int w, int h); +#define THRESHOLD_FUNC(depth, opt) \ +void ff_threshold##depth##_##opt(const uint8_t *in, const uint8_t *threshold,\ + const uint8_t *min, const uint8_t *max, \ + uint8_t *out, \ + ptrdiff_t ilinesize, ptrdiff_t tlinesize, \ + ptrdiff_t flinesize, ptrdiff_t slinesize, \ + ptrdiff_t olinesize, \ + int w, int h); + +THRESHOLD_FUNC(8, sse4) +THRESHOLD_FUNC(8, avx2) +THRESHOLD_FUNC(16, sse4) +THRESHOLD_FUNC(16, avx2) av_cold void ff_threshold_init_x86(ThresholdContext *s) { @@ -49,5 +48,12 @@ av_cold void ff_threshold_init_x86(ThresholdContext *s) if (EXTERNAL_AVX2_FAST(cpu_flags)) { s->threshold = ff_threshold8_avx2; } + } else if (s->depth == 16) { + if (EXTERNAL_SSE4(cpu_flags)) { + s->threshold = ff_threshold16_sse4; + } + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + s->threshold = ff_threshold16_avx2; + } } } From 179a2f04eb2bd6df7221883a92dc4e00cf94394b Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Thu, 7 Dec 2017 22:03:44 +0100 Subject: [PATCH 1289/2557] checkasm/vf_threshold : add test for threshold16 --- tests/checkasm/vf_threshold.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/checkasm/vf_threshold.c b/tests/checkasm/vf_threshold.c index 3709f2671e049..5a2fc0e4ee4f8 100644 --- a/tests/checkasm/vf_threshold.c +++ b/tests/checkasm/vf_threshold.c @@ -32,7 +32,7 @@ tmp_buf[j] = rnd() & 0xFF; \ } while (0) -static void check_threshold_8(void){ +static void check_threshold(int depth){ LOCAL_ALIGNED_32(uint8_t, in , [WIDTH_PADDED]); LOCAL_ALIGNED_32(uint8_t, threshold, [WIDTH_PADDED]); LOCAL_ALIGNED_32(uint8_t, min , [WIDTH_PADDED]); @@ -49,7 +49,7 @@ static void check_threshold_8(void){ ptrdiff_t olinesize, int w, int h); ThresholdContext s; - s.depth = 8; + s.depth = depth; ff_threshold_init(&s); memset(in, 0, WIDTH_PADDED); @@ -63,10 +63,13 @@ static void check_threshold_8(void){ randomize_buffers(min, WIDTH); randomize_buffers(max, WIDTH); - if (check_func(s.threshold, "threshold8")) { + if (depth == 16) + w /= 2; + + if (check_func(s.threshold, "threshold%d", depth)) { call_ref(in, threshold, min, max, out_ref, line_size, line_size, line_size, line_size, line_size, w, 1); call_new(in, threshold, min, max, out_new, line_size, line_size, line_size, line_size, line_size, w, 1); - if (memcmp(out_ref, out_new, w)) + if (memcmp(out_ref, out_new, WIDTH)) fail(); bench_new(in, threshold, min, max, out_new, line_size, line_size, line_size, line_size, line_size, w, 1); } @@ -74,6 +77,9 @@ static void check_threshold_8(void){ void checkasm_check_vf_threshold(void) { - check_threshold_8(); + check_threshold(8); report("threshold8"); + + check_threshold(16); + report("threshold16"); } From 9e1c9633cc7b025f6b04e39fdd7f9983a73b5bfa Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 26 Nov 2017 19:18:48 +0100 Subject: [PATCH 1290/2557] avcodec/utvideodec : use dsp add_median_pred for second line process start of the line in scalar, before call dsp (dsp need align 16) --- libavcodec/utvideodec.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 83dbae99b1aab..d2da825fbf3c5 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -373,12 +373,16 @@ static void restore_median_planar(UtvideoContext *c, uint8_t *src, ptrdiff_t str C = bsrc[-stride]; bsrc[0] += C; A = bsrc[0]; - for (i = 1; i < width; i++) { + for (i = 1; i < FFMIN(width, 16); i++) { /* scalar loop (DSP need align 16) */ B = bsrc[i - stride]; bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C)); C = B; A = bsrc[i]; } + if (width > 16) + c->llviddsp.add_median_pred(bsrc + 16, bsrc - stride + 16, + bsrc + 16, width - 16, &A, &B); + bsrc += stride; // the rest of lines use continuous median prediction for (j = 2; j < slice_height; j++) { @@ -424,12 +428,16 @@ static void restore_median_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_t C = bsrc[-stride2]; bsrc[0] += C; A = bsrc[0]; - for (i = 1; i < width; i++) { + for (i = 1; i < FFMIN(width, 16); i++) { /* scalar loop (DSP need align 16) */ B = bsrc[i - stride2]; bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C)); C = B; A = bsrc[i]; } + if (width > 16) + c->llviddsp.add_median_pred(bsrc + 16, bsrc - stride2 + 16, + bsrc + 16, width - 16, &A, &B); + c->llviddsp.add_median_pred(bsrc + stride, bsrc - stride, bsrc + stride, width, &A, &B); bsrc += stride2; From 57877f2b449f265ae1dd070b46aaadff4f0b3e34 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 2 Dec 2017 18:30:26 +0100 Subject: [PATCH 1291/2557] avcodec/huffyuvenc : increase scalar loop count in order to try to call dsp in aligned mode (diff_int16 have AVX2 now) --- libavcodec/huffyuvenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/huffyuvenc.c b/libavcodec/huffyuvenc.c index 89639b75df05a..4f3a28e033cf4 100644 --- a/libavcodec/huffyuvenc.c +++ b/libavcodec/huffyuvenc.c @@ -80,12 +80,12 @@ static inline int sub_left_prediction(HYuvContext *s, uint8_t *dst, } return left; } else { - for (i = 0; i < 16; i++) { + for (i = 0; i < 32; i++) { const int temp = src16[i]; dst16[i] = temp - left; left = temp; } - s->hencdsp.diff_int16(dst16 + 16, src16 + 16, src16 + 15, s->n - 1, w - 16); + s->hencdsp.diff_int16(dst16 + 32, src16 + 32, src16 + 31, s->n - 1, w - 32); return src16[w-1]; } } From 001173b8ff8eae862822fdfb101ce3cc15372937 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 2 Dec 2017 18:32:05 +0100 Subject: [PATCH 1292/2557] avcodec/huffyuvenc : remove code duplication in sub_left_prediction start of the line (before dsp call), can be merge with width < 32 part --- libavcodec/huffyuvenc.c | 48 ++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/libavcodec/huffyuvenc.c b/libavcodec/huffyuvenc.c index 4f3a28e033cf4..6e2e83bd3e0a8 100644 --- a/libavcodec/huffyuvenc.c +++ b/libavcodec/huffyuvenc.c @@ -52,42 +52,30 @@ static inline int sub_left_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *src, int w, int left) { int i; + int min_width = FFMIN(w, 32); + if (s->bps <= 8) { - if (w < 32) { - for (i = 0; i < w; i++) { - const int temp = src[i]; - dst[i] = temp - left; - left = temp; - } - return left; - } else { - for (i = 0; i < 32; i++) { - const int temp = src[i]; - dst[i] = temp - left; - left = temp; - } - s->llvidencdsp.diff_bytes(dst + 32, src + 32, src + 31, w - 32); - return src[w-1]; + for (i = 0; i < min_width; i++) { /* scalar loop before dsp call */ + const int temp = src[i]; + dst[i] = temp - left; + left = temp; } + if (w < 32) + return left; + s->llvidencdsp.diff_bytes(dst + 32, src + 32, src + 31, w - 32); + return src[w-1]; } else { const uint16_t *src16 = (const uint16_t *)src; uint16_t *dst16 = ( uint16_t *)dst; - if (w < 32) { - for (i = 0; i < w; i++) { - const int temp = src16[i]; - dst16[i] = temp - left; - left = temp; - } - return left; - } else { - for (i = 0; i < 32; i++) { - const int temp = src16[i]; - dst16[i] = temp - left; - left = temp; - } - s->hencdsp.diff_int16(dst16 + 32, src16 + 32, src16 + 31, s->n - 1, w - 32); - return src16[w-1]; + for (i = 0; i < min_width; i++) { /* scalar loop before dsp call */ + const int temp = src16[i]; + dst16[i] = temp - left; + left = temp; } + if (w < 32) + return left; + s->hencdsp.diff_int16(dst16 + 32, src16 + 32, src16 + 31, s->n - 1, w - 32); + return src16[w-1]; } } From dc9a187c3d1bcc14b9f1e04632c5912b2fef313d Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 2 Dec 2017 18:33:25 +0100 Subject: [PATCH 1293/2557] avcodec/huffyuvenc : sub_left_prediction_bgr32, call dsp after 32 first byte of the line in order to try to call the align version (diff bytes have avx2 version) --- libavcodec/huffyuvenc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/huffyuvenc.c b/libavcodec/huffyuvenc.c index 6e2e83bd3e0a8..aa71d20fcce75 100644 --- a/libavcodec/huffyuvenc.c +++ b/libavcodec/huffyuvenc.c @@ -90,8 +90,9 @@ static inline void sub_left_prediction_bgr32(HYuvContext *s, uint8_t *dst, g = *green; b = *blue; a = *alpha; + int min_width = FFMIN(w, 8); - for (i = 0; i < FFMIN(w, 4); i++) { + for (i = 0; i < min_width; i++) { const int rt = src[i * 4 + R]; const int gt = src[i * 4 + G]; const int bt = src[i * 4 + B]; @@ -106,7 +107,7 @@ static inline void sub_left_prediction_bgr32(HYuvContext *s, uint8_t *dst, a = at; } - s->llvidencdsp.diff_bytes(dst + 16, src + 16, src + 12, w * 4 - 16); + s->llvidencdsp.diff_bytes(dst + 32, src + 32, src + 32 - 4, w * 4 - 32); *red = src[(w - 1) * 4 + R]; *green = src[(w - 1) * 4 + G]; From 5bda11e70ef109f55a766bdd4ae14b3afb2c2ecc Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 2 Dec 2017 19:03:30 +0100 Subject: [PATCH 1294/2557] checkasm/llviddsp : test return of add_left_pred(16) --- tests/checkasm/llviddsp.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tests/checkasm/llviddsp.c b/tests/checkasm/llviddsp.c index 4c763ecf1b9bc..3c987ac9ad398 100644 --- a/tests/checkasm/llviddsp.c +++ b/tests/checkasm/llviddsp.c @@ -109,11 +109,12 @@ static void check_add_median_pred(LLVidDSPContext c, int width) { static void check_add_left_pred(LLVidDSPContext c, int width, int acc, const char * report) { + int res0, res1; uint8_t *dst0 = av_mallocz(width); uint8_t *dst1 = av_mallocz(width); uint8_t *src0 = av_mallocz_array(width, sizeof(uint8_t)); uint8_t *src1 = av_mallocz_array(width, sizeof(uint8_t)); - declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, uint8_t *src, ptrdiff_t w, int acc); + declare_func_emms(AV_CPU_FLAG_MMX, int, uint8_t *dst, uint8_t *src, ptrdiff_t w, int acc); init_buffer(src0, src1, uint8_t, width); @@ -121,9 +122,10 @@ static void check_add_left_pred(LLVidDSPContext c, int width, int acc, const cha fail(); if (check_func(c.add_left_pred, "%s", report)) { - call_ref(dst0, src0, width, acc); - call_new(dst1, src1, width, acc); - if (memcmp(dst0, dst1, width)) + res0 = call_ref(dst0, src0, width, acc); + res1 = call_new(dst1, src1, width, acc); + if ((res0 & 0xFF) != (res1 & 0xFF)||\ + memcmp(dst0, dst1, width)) fail(); bench_new(dst1, src1, width, acc); } @@ -136,11 +138,12 @@ static void check_add_left_pred(LLVidDSPContext c, int width, int acc, const cha static void check_add_left_pred_16(LLVidDSPContext c, unsigned mask, int width, unsigned acc, const char * report) { + int res0, res1; uint16_t *dst0 = av_mallocz_array(width, sizeof(uint16_t)); uint16_t *dst1 = av_mallocz_array(width, sizeof(uint16_t)); uint16_t *src0 = av_mallocz_array(width, sizeof(uint16_t)); uint16_t *src1 = av_mallocz_array(width, sizeof(uint16_t)); - declare_func_emms(AV_CPU_FLAG_MMX, void, uint16_t *dst, uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc); + declare_func_emms(AV_CPU_FLAG_MMX, int, uint16_t *dst, uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc); init_buffer(src0, src1, uint16_t, width); @@ -148,9 +151,10 @@ static void check_add_left_pred_16(LLVidDSPContext c, unsigned mask, int width, fail(); if (check_func(c.add_left_pred_int16, "%s", report)) { - call_ref(dst0, src0, mask, width, acc); - call_new(dst1, src1, mask, width, acc); - if (memcmp(dst0, dst1, width)) + res0 = call_ref(dst0, src0, mask, width, acc); + res1 = call_new(dst1, src1, mask, width, acc); + if ((res0 &0xFFFF) != (res1 &0xFFFF)||\ + memcmp(dst0, dst1, width)) fail(); bench_new(dst1, src1, mask, width, acc); } From cfbcea1cca7f4d5b92a17778f78427794057eb29 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 2 Dec 2017 19:04:11 +0100 Subject: [PATCH 1295/2557] avcodec/x86/lossless_videodsp.asm : make macro for add_left_pred_unaligned in order to add avx2 version --- libavcodec/x86/lossless_videodsp.asm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/x86/lossless_videodsp.asm b/libavcodec/x86/lossless_videodsp.asm index ba4d4f0153de4..663bf6153e9cf 100644 --- a/libavcodec/x86/lossless_videodsp.asm +++ b/libavcodec/x86/lossless_videodsp.asm @@ -164,7 +164,7 @@ cglobal add_left_pred, 3,3,7, dst, src, w, left psllq m0, 56 ADD_LEFT_LOOP 1, 1 -INIT_XMM ssse3 +%macro ADD_LEFT_PRED_UNALIGNED 0 cglobal add_left_pred_unaligned, 3,3,7, dst, src, w, left mova m5, [pb_15] mova m6, [pb_zzzzzzzz77777777] @@ -181,6 +181,10 @@ cglobal add_left_pred_unaligned, 3,3,7, dst, src, w, left ADD_LEFT_LOOP 0, 1 .src_unaligned: ADD_LEFT_LOOP 0, 0 +%endmacro + +INIT_XMM ssse3 +ADD_LEFT_PRED_UNALIGNED ;------------------------------------------------------------------------------ ; void ff_add_bytes(uint8_t *dst, uint8_t *src, ptrdiff_t w); From 4353c3506742c9fecce4cf9f68cc6a7ab7ea05b1 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 2 Dec 2017 19:09:58 +0100 Subject: [PATCH 1296/2557] avcodec/x86/lossless_videodsp : add avx2 version for add_left_pred --- libavcodec/x86/lossless_videodsp.asm | 63 ++++++++++++++++--------- libavcodec/x86/lossless_videodsp_init.c | 3 ++ 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/libavcodec/x86/lossless_videodsp.asm b/libavcodec/x86/lossless_videodsp.asm index 663bf6153e9cf..cfa0620fd153c 100644 --- a/libavcodec/x86/lossless_videodsp.asm +++ b/libavcodec/x86/lossless_videodsp.asm @@ -114,40 +114,54 @@ MEDIAN_PRED add dstq, wq neg wq %%.loop: + pshufb xm0, xm5 %if %2 mova m1, [srcq+wq] %else movu m1, [srcq+wq] %endif - mova m2, m1 - psllw m1, 8 + psllw m2, m1, 8 paddb m1, m2 - mova m2, m1 - pshufb m1, m3 + pshufb m2, m1, m3 paddb m1, m2 - pshufb m0, m5 - mova m2, m1 - pshufb m1, m4 + pshufb m2, m1, m4 paddb m1, m2 -%if mmsize == 16 - mova m2, m1 - pshufb m1, m6 +%if mmsize >= 16 + pshufb m2, m1, m6 paddb m1, m2 %endif - paddb m0, m1 + paddb xm0, xm1 %if %1 - mova [dstq+wq], m0 + mova [dstq+wq], xm0 %else - movq [dstq+wq], m0 - movhps [dstq+wq+8], m0 + movq [dstq+wq], xm0 + movhps [dstq+wq+8], xm0 +%endif + +%if mmsize == 32 + vextracti128 xm2, m1, 1 ; get second lane of the ymm + pshufb xm0, xm5 ; set alls val to last val of the first lane + paddb xm0, xm2 +;store val +%if %1 + mova [dstq+wq+16], xm0 +%else; + movq [dstq+wq+16], xm0 + movhps [dstq+wq+16+8], xm0 +%endif %endif add wq, mmsize jl %%.loop +%if mmsize == 32 + mov eax, [dstq -1] + and eax, 0xff +%else; mov eax, mmsize-1 sub eax, wd movd m1, eax pshufb m0, m1 movd eax, m0 +%endif RET %endmacro @@ -166,15 +180,15 @@ cglobal add_left_pred, 3,3,7, dst, src, w, left %macro ADD_LEFT_PRED_UNALIGNED 0 cglobal add_left_pred_unaligned, 3,3,7, dst, src, w, left - mova m5, [pb_15] - mova m6, [pb_zzzzzzzz77777777] - mova m4, [pb_zzzz3333zzzzbbbb] - mova m3, [pb_zz11zz55zz99zzdd] - movd m0, leftm - pslldq m0, 15 - test srcq, 15 + mova xm5, [pb_15] + VBROADCASTI128 m6, [pb_zzzzzzzz77777777] + VBROADCASTI128 m4, [pb_zzzz3333zzzzbbbb] + VBROADCASTI128 m3, [pb_zz11zz55zz99zzdd] + movd xm0, leftm + pslldq xm0, 15 + test srcq, mmsize - 1 jnz .src_unaligned - test dstq, 15 + test dstq, mmsize - 1 jnz .dst_unaligned ADD_LEFT_LOOP 1, 1 .dst_unaligned: @@ -186,6 +200,11 @@ cglobal add_left_pred_unaligned, 3,3,7, dst, src, w, left INIT_XMM ssse3 ADD_LEFT_PRED_UNALIGNED +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +ADD_LEFT_PRED_UNALIGNED +%endif + ;------------------------------------------------------------------------------ ; void ff_add_bytes(uint8_t *dst, uint8_t *src, ptrdiff_t w); ;------------------------------------------------------------------------------ diff --git a/libavcodec/x86/lossless_videodsp_init.c b/libavcodec/x86/lossless_videodsp_init.c index 4f20c1ce920a3..beae317cc2b73 100644 --- a/libavcodec/x86/lossless_videodsp_init.c +++ b/libavcodec/x86/lossless_videodsp_init.c @@ -38,6 +38,8 @@ int ff_add_left_pred_ssse3(uint8_t *dst, const uint8_t *src, ptrdiff_t w, int left); int ff_add_left_pred_unaligned_ssse3(uint8_t *dst, const uint8_t *src, ptrdiff_t w, int left); +int ff_add_left_pred_unaligned_avx2(uint8_t *dst, const uint8_t *src, + ptrdiff_t w, int left); int ff_add_left_pred_int16_ssse3(uint16_t *dst, const uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc); int ff_add_left_pred_int16_sse4(uint16_t *dst, const uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc); @@ -118,5 +120,6 @@ void ff_llviddsp_init_x86(LLVidDSPContext *c) } if (EXTERNAL_AVX2_FAST(cpu_flags)) { c->add_bytes = ff_add_bytes_avx2; + c->add_left_pred = ff_add_left_pred_unaligned_avx2; } } From 630967ef63d0f2a5cc12b06815af0ec6cb5c9d2a Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 2 Dec 2017 19:46:42 +0100 Subject: [PATCH 1297/2557] avcodec/utvideodec : add SIMD (SSSE3 and AVX2) for gradient_pred --- libavcodec/lossless_videodsp.c | 11 ++++ libavcodec/lossless_videodsp.h | 1 + libavcodec/utvideodec.c | 5 +- libavcodec/x86/lossless_videodsp.asm | 80 +++++++++++++++++++++++++ libavcodec/x86/lossless_videodsp_init.c | 5 ++ 5 files changed, 101 insertions(+), 1 deletion(-) diff --git a/libavcodec/lossless_videodsp.c b/libavcodec/lossless_videodsp.c index b5b96e612966d..cff94c234ddf1 100644 --- a/libavcodec/lossless_videodsp.c +++ b/libavcodec/lossless_videodsp.c @@ -98,6 +98,16 @@ static int add_left_pred_int16_c(uint16_t *dst, const uint16_t *src, unsigned ma return acc; } +static void add_gradient_pred_c(uint8_t *src, const ptrdiff_t stride, const ptrdiff_t width){ + int A, B, C, i; + + for (i = 0; i < width; i++) { + A = src[i - stride]; + B = src[i - (stride + 1)]; + C = src[i - 1]; + src[i] = (A - B + C + src[i]) & 0xFF; + } +} void ff_llviddsp_init(LLVidDSPContext *c) { @@ -106,6 +116,7 @@ void ff_llviddsp_init(LLVidDSPContext *c) c->add_left_pred = add_left_pred_c; c->add_left_pred_int16 = add_left_pred_int16_c; + c->add_gradient_pred = add_gradient_pred_c; if (ARCH_PPC) ff_llviddsp_init_ppc(c); diff --git a/libavcodec/lossless_videodsp.h b/libavcodec/lossless_videodsp.h index ccab39bac6594..8077898d1a7ad 100644 --- a/libavcodec/lossless_videodsp.h +++ b/libavcodec/lossless_videodsp.h @@ -39,6 +39,7 @@ typedef struct LLVidDSPContext { int (*add_left_pred_int16)(uint16_t *dst, const uint16_t *src, unsigned mask, ptrdiff_t w, unsigned left); + void (*add_gradient_pred)(uint8_t *src /* align 32 */, const ptrdiff_t stride, const ptrdiff_t width); } LLVidDSPContext; void ff_llviddsp_init(LLVidDSPContext *llviddsp); diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index d2da825fbf3c5..b85cb5daa6df4 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -460,6 +460,7 @@ static void restore_gradient_planar(UtvideoContext *c, uint8_t *src, ptrdiff_t s uint8_t *bsrc; int slice_start, slice_height; const int cmask = ~rmode; + int min_width = FFMIN(width, 32); for (slice = 0; slice < slices; slice++) { slice_start = ((slice * height) / slices) & cmask; @@ -479,12 +480,14 @@ static void restore_gradient_planar(UtvideoContext *c, uint8_t *src, ptrdiff_t s for (j = 1; j < slice_height; j++) { // second line - first element has top prediction, the rest uses gradient bsrc[0] = (bsrc[0] + bsrc[-stride]) & 0xFF; - for (i = 1; i < width; i++) { + for (i = 1; i < min_width; i++) { /* dsp need align 32 */ A = bsrc[i - stride]; B = bsrc[i - (stride + 1)]; C = bsrc[i - 1]; bsrc[i] = (A - B + C + bsrc[i]) & 0xFF; } + if (width > 32) + c->llviddsp.add_gradient_pred(bsrc + 32, stride, width - 32); bsrc += stride; } } diff --git a/libavcodec/x86/lossless_videodsp.asm b/libavcodec/x86/lossless_videodsp.asm index cfa0620fd153c..9a169fe3149a5 100644 --- a/libavcodec/x86/lossless_videodsp.asm +++ b/libavcodec/x86/lossless_videodsp.asm @@ -2,6 +2,7 @@ ;* SIMD lossless video DSP utils ;* Copyright (c) 2008 Loren Merritt ;* Copyright (c) 2014 Michael Niedermayer +;* Copyright (c) 2017 Jokyo Images ;* ;* This file is part of FFmpeg. ;* @@ -325,3 +326,82 @@ cglobal add_left_pred_int16, 4,4,8, dst, src, mask, w, left ADD_HFYU_LEFT_LOOP_INT16 u, a .src_unaligned: ADD_HFYU_LEFT_LOOP_INT16 u, u + + +;--------------------------------------------------------------------------------------------- +; void add_gradient_pred(uint8_t *src, const ptrdiff_t stride, const ptrdiff_t width) +;--------------------------------------------------------------------------------------------- +%macro ADD_GRADIENT_PRED 0 +cglobal add_gradient_pred, 3,4,5, src, stride, width, tmp + mova xm0, [pb_15] + +;load src - 1 in xm1 + movd xm1, [srcq-1] +%if cpuflag(avx2) + vpbroadcastb xm1, xm1 +%else + pxor xm2, xm2 + pshufb xm1, xm2 +%endif + + add srcq, widthq + neg widthq + neg strideq + +.loop: + lea tmpq, [srcq + strideq] + mova m2, [tmpq + widthq] ; A = src[x-stride] + movu m3, [tmpq + widthq - 1] ; B = src[x - (stride + 1)] + mova m4, [srcq + widthq] ; current val (src[x]) + + psubb m2, m3; A - B + +; prefix sum A-B + pslldq m3, m2, 1 + paddb m2, m3 + pslldq m3, m2, 2 + paddb m2, m3 + pslldq m3, m2, 4 + paddb m2, m3 + pslldq m3, m2, 8 + paddb m2, m3 + +; prefix sum current val + pslldq m3, m4, 1 + paddb m4, m3 + pslldq m3, m4, 2 + paddb m4, m3 + pslldq m3, m4, 4 + paddb m4, m3 + pslldq m3, m4, 8 + paddb m4, m3 + +; last sum + paddb m2, m4 ; current + (A - B) + + paddb xm1, xm2 ; += C + mova [srcq + widthq], xm1 ; store + + pshufb xm1, xm0 ; put last val in all val of xm1 + +%if mmsize == 32 + vextracti128 xm2, m2, 1 ; get second lane of the ymm + paddb xm1, xm2; += C + + mova [srcq + widthq + 16], xm1 ; store + pshufb xm1, xm0 ; put last val in all val of m1 +%endif + + add widthq, mmsize + jl .loop + RET + +%endmacro + +INIT_XMM ssse3 +ADD_GRADIENT_PRED + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +ADD_GRADIENT_PRED +%endif diff --git a/libavcodec/x86/lossless_videodsp_init.c b/libavcodec/x86/lossless_videodsp_init.c index beae317cc2b73..e3063de4623d5 100644 --- a/libavcodec/x86/lossless_videodsp_init.c +++ b/libavcodec/x86/lossless_videodsp_init.c @@ -44,6 +44,9 @@ int ff_add_left_pred_unaligned_avx2(uint8_t *dst, const uint8_t *src, int ff_add_left_pred_int16_ssse3(uint16_t *dst, const uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc); int ff_add_left_pred_int16_sse4(uint16_t *dst, const uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc); +void ff_add_gradient_pred_ssse3(uint8_t *src, const ptrdiff_t stride, const ptrdiff_t width); +void ff_add_gradient_pred_avx2(uint8_t *src, const ptrdiff_t stride, const ptrdiff_t width); + #if HAVE_INLINE_ASM && HAVE_7REGS && ARCH_X86_32 static void add_median_pred_cmov(uint8_t *dst, const uint8_t *top, const uint8_t *diff, ptrdiff_t w, @@ -109,6 +112,7 @@ void ff_llviddsp_init_x86(LLVidDSPContext *c) if (EXTERNAL_SSSE3(cpu_flags)) { c->add_left_pred = ff_add_left_pred_ssse3; c->add_left_pred_int16 = ff_add_left_pred_int16_ssse3; + c->add_gradient_pred = ff_add_gradient_pred_ssse3; } if (EXTERNAL_SSSE3_FAST(cpu_flags)) { @@ -121,5 +125,6 @@ void ff_llviddsp_init_x86(LLVidDSPContext *c) if (EXTERNAL_AVX2_FAST(cpu_flags)) { c->add_bytes = ff_add_bytes_avx2; c->add_left_pred = ff_add_left_pred_unaligned_avx2; + c->add_gradient_pred = ff_add_gradient_pred_avx2; } } From e1121f9723b1f6eabc80e7f3c9eca69a70fd2f8d Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 2 Dec 2017 19:47:24 +0100 Subject: [PATCH 1298/2557] checkasm/llviddsp : add test for add_gradient_pred --- tests/checkasm/llviddsp.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/checkasm/llviddsp.c b/tests/checkasm/llviddsp.c index 3c987ac9ad398..be63809a4b416 100644 --- a/tests/checkasm/llviddsp.c +++ b/tests/checkasm/llviddsp.c @@ -165,6 +165,33 @@ static void check_add_left_pred_16(LLVidDSPContext c, unsigned mask, int width, av_free(dst1); } +static void check_add_gradient_pred(LLVidDSPContext c, int w) { + int src_size, stride; + uint8_t *src0, *src1; + stride = w + 32; + src_size = (stride + 32) * 2; /* dsp need previous line, and ignore the start of the line */ + src0 = av_mallocz(src_size); + src1 = av_mallocz(src_size); + + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *src, const ptrdiff_t stride, + const ptrdiff_t width); + + init_buffer(src0, src1, uint8_t, src_size); + + if (check_func(c.add_gradient_pred, "add_gradient_pred")) { + call_ref(src0 + stride + 32, stride, w); + call_new(src1 + stride + 32, stride, w); + if (memcmp(src0, src1, stride)||/* previous line doesn't change */ + memcmp(src0+stride, src1 + stride, w + 32)) { + fail(); + } + bench_new(src1 + stride + 32, stride, w); + } + + av_free(src0); + av_free(src1); +} + void checkasm_check_llviddsp(void) { LLVidDSPContext c; @@ -187,4 +214,7 @@ void checkasm_check_llviddsp(void) check_add_left_pred_16(c, 255, width, accRnd, "add_left_pred_int16"); report("add_left_pred_int16"); + + check_add_gradient_pred(c, width); + report("add_gradient_pred"); } From 36de24d5b7d67ab323ed41c7dc06fa0345404227 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 8 Dec 2017 19:14:13 -0300 Subject: [PATCH 1299/2557] arm/hevc_idct: fix compilation on Android Compilation error "out of range" fixed for armeabi-v7a. Compilation failed trying to build libvlc.aar for ARM7 android on ubuntu 16.04 host. Error messages is "Offset out of range". The reason of the error is assembler LDR directives in function "ff_hevc_transform_luma_4x4_neon_8" need local storage in range <1k, but no such storage provided. Based on a patch by Ihor Bobalo Suggested-by: wbs Signed-off-by: James Almer --- libavcodec/arm/hevcdsp_idct_neon.S | 119 +++++++++++++++-------------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/libavcodec/arm/hevcdsp_idct_neon.S b/libavcodec/arm/hevcdsp_idct_neon.S index 139029a256837..75795e6a6ae22 100644 --- a/libavcodec/arm/hevcdsp_idct_neon.S +++ b/libavcodec/arm/hevcdsp_idct_neon.S @@ -229,65 +229,6 @@ function ff_hevc_add_residual_32x32_10_neon, export=1 bx lr endfunc -/* uses registers q2 - q9 for temp values */ -/* TODO: reorder */ -.macro tr4_luma_shift r0, r1, r2, r3, shift - vaddl.s16 q5, \r0, \r2 // c0 = src0 + src2 - vaddl.s16 q2, \r2, \r3 // c1 = src2 + src3 - vsubl.s16 q4, \r0, \r3 // c2 = src0 - src3 - vmull.s16 q6, \r1, d0[0] // c3 = 74 * src1 - - vaddl.s16 q7, \r0, \r3 // src0 + src3 - vsubw.s16 q7, q7, \r2 // src0 - src2 + src3 - vmul.s32 q7, q7, d0[0] // dst2 = 74 * (src0 - src2 + src3) - - vmul.s32 q8, q5, d0[1] // 29 * c0 - vmul.s32 q9, q2, d1[0] // 55 * c1 - vadd.s32 q8, q9 // 29 * c0 + 55 * c1 - vadd.s32 q8, q6 // dst0 = 29 * c0 + 55 * c1 + c3 - - vmul.s32 q2, q2, d0[1] // 29 * c1 - vmul.s32 q9, q4, d1[0] // 55 * c2 - vsub.s32 q9, q2 // 55 * c2 - 29 * c1 - vadd.s32 q9, q6 // dst1 = 55 * c2 - 29 * c1 + c3 - - vmul.s32 q5, q5, d1[0] // 55 * c0 - vmul.s32 q4, q4, d0[1] // 29 * c2 - vadd.s32 q5, q4 // 55 * c0 + 29 * c2 - vsub.s32 q5, q6 // dst3 = 55 * c0 + 29 * c2 - c3 - - vqrshrn.s32 \r0, q8, \shift - vqrshrn.s32 \r1, q9, \shift - vqrshrn.s32 \r2, q7, \shift - vqrshrn.s32 \r3, q5, \shift -.endm - -function ff_hevc_transform_luma_4x4_neon_8, export=1 - vpush {d8-d15} - vld1.16 {q14, q15}, [r0] // coeffs - ldr r3, =0x4a // 74 - vmov.32 d0[0], r3 - ldr r3, =0x1d // 29 - vmov.32 d0[1], r3 - ldr r3, =0x37 // 55 - vmov.32 d1[0], r3 - - tr4_luma_shift d28, d29, d30, d31, #7 - - vtrn.16 d28, d29 - vtrn.16 d30, d31 - vtrn.32 q14, q15 - - tr4_luma_shift d28, d29, d30, d31, #12 - - vtrn.16 d28, d29 - vtrn.16 d30, d31 - vtrn.32 q14, q15 - vst1.16 {q14, q15}, [r0] - vpop {d8-d15} - bx lr -endfunc - .macro idct_4x4_dc bitdepth function ff_hevc_idct_4x4_dc_\bitdepth\()_neon, export=1 ldrsh r1, [r0] @@ -1040,3 +981,63 @@ idct_32x32 8 idct_32x32_dc 8 idct_32x32 10 idct_32x32_dc 10 + +/* uses registers q2 - q9 for temp values */ +/* TODO: reorder */ +.macro tr4_luma_shift r0, r1, r2, r3, shift + vaddl.s16 q5, \r0, \r2 // c0 = src0 + src2 + vaddl.s16 q2, \r2, \r3 // c1 = src2 + src3 + vsubl.s16 q4, \r0, \r3 // c2 = src0 - src3 + vmull.s16 q6, \r1, d0[0] // c3 = 74 * src1 + + vaddl.s16 q7, \r0, \r3 // src0 + src3 + vsubw.s16 q7, q7, \r2 // src0 - src2 + src3 + vmul.s32 q7, q7, d0[0] // dst2 = 74 * (src0 - src2 + src3) + + vmul.s32 q8, q5, d0[1] // 29 * c0 + vmul.s32 q9, q2, d1[0] // 55 * c1 + vadd.s32 q8, q9 // 29 * c0 + 55 * c1 + vadd.s32 q8, q6 // dst0 = 29 * c0 + 55 * c1 + c3 + + vmul.s32 q2, q2, d0[1] // 29 * c1 + vmul.s32 q9, q4, d1[0] // 55 * c2 + vsub.s32 q9, q2 // 55 * c2 - 29 * c1 + vadd.s32 q9, q6 // dst1 = 55 * c2 - 29 * c1 + c3 + + vmul.s32 q5, q5, d1[0] // 55 * c0 + vmul.s32 q4, q4, d0[1] // 29 * c2 + vadd.s32 q5, q4 // 55 * c0 + 29 * c2 + vsub.s32 q5, q6 // dst3 = 55 * c0 + 29 * c2 - c3 + + vqrshrn.s32 \r0, q8, \shift + vqrshrn.s32 \r1, q9, \shift + vqrshrn.s32 \r2, q7, \shift + vqrshrn.s32 \r3, q5, \shift +.endm + +.ltorg +function ff_hevc_transform_luma_4x4_neon_8, export=1 + vpush {d8-d15} + vld1.16 {q14, q15}, [r0] // coeffs + ldr r3, =0x4a // 74 + vmov.32 d0[0], r3 + ldr r3, =0x1d // 29 + vmov.32 d0[1], r3 + ldr r3, =0x37 // 55 + vmov.32 d1[0], r3 + + tr4_luma_shift d28, d29, d30, d31, #7 + + vtrn.16 d28, d29 + vtrn.16 d30, d31 + vtrn.32 q14, q15 + + tr4_luma_shift d28, d29, d30, d31, #12 + + vtrn.16 d28, d29 + vtrn.16 d30, d31 + vtrn.32 q14, q15 + vst1.16 {q14, q15}, [r0] + vpop {d8-d15} + bx lr +endfunc From 02ba4b91b5616ecbebee5c9565e1be7af2a6b980 Mon Sep 17 00:00:00 2001 From: James Cowgill Date: Thu, 9 Nov 2017 12:21:23 +0000 Subject: [PATCH 1300/2557] avcodec/decode: reset codec on receiving packet after EOF in compat_decode In commit 061a0c14bb57 ("decode: restructure the core decoding code"), the deprecated avcodec_decode_* APIs were reworked so that they called into the new avcodec_send_packet / avcodec_receive_frame API. This had the side effect of prohibiting sending new packets containing data after a drain packet, but in previous versions of FFmpeg this "worked" and some applications relied on it. To restore some compatibility, reset the codec if we receive a new non-drain packet using the old API after draining has completed. While this does not give the same behaviour as the old API did, in the majority of cases it works and it does not require changes to any other part of the decoding code. Fixes ticket #6775 Signed-off-by: James Cowgill Signed-off-by: Marton Balint --- libavcodec/decode.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 3f5b086f7e4fb..f67b2147591ec 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -749,6 +749,11 @@ static int compat_decode(AVCodecContext *avctx, AVFrame *frame, av_assert0(avci->compat_decode_consumed == 0); + if (avci->draining_done && pkt && pkt->size != 0) { + av_log(avctx, AV_LOG_WARNING, "Got unexpected packet after EOF\n"); + avcodec_flush_buffers(avctx); + } + *got_frame = 0; avci->compat_decode = 1; From b38f222165f97af19f5bfc2c3e9217b5d1b25cfb Mon Sep 17 00:00:00 2001 From: Jacob Trimble Date: Thu, 7 Dec 2017 11:05:46 -0800 Subject: [PATCH 1301/2557] avcodec/Makefile: Fix opus parser dependency. The opus.c file uses ff_celt_freq_range and ff_celt_freq_bands which are defined in opustab.c. The opus parser needs to include that file to avoid linker errors when not including the opus encoder/decoder. Signed-off-by: Jacob Trimble Signed-off-by: Michael Niedermayer --- libavcodec/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index ab7893f560e79..ca72138c028b6 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1005,7 +1005,7 @@ OBJS-$(CONFIG_PNG_PARSER) += png_parser.o OBJS-$(CONFIG_MPEGAUDIO_PARSER) += mpegaudio_parser.o OBJS-$(CONFIG_MPEGVIDEO_PARSER) += mpegvideo_parser.o \ mpeg12.o mpeg12data.o -OBJS-$(CONFIG_OPUS_PARSER) += opus_parser.o opus.o vorbis_data.o +OBJS-$(CONFIG_OPUS_PARSER) += opus_parser.o opus.o opustab.o vorbis_data.o OBJS-$(CONFIG_PNG_PARSER) += png_parser.o OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o From ab651587a715dc59775650a4c8af3cddcdfd26f8 Mon Sep 17 00:00:00 2001 From: "tiejun.peng" Date: Sat, 9 Dec 2017 00:28:41 +0800 Subject: [PATCH 1302/2557] lavf/mov: add some useful warning log of eof Signed-off-by: tiejun.peng Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 0b3e673c0651c..48ec45254f24e 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1991,8 +1991,10 @@ static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->chunk_count = i; - if (pb->eof_reached) + if (pb->eof_reached) { + av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STCO atom\n"); return AVERROR_EOF; + } return 0; } @@ -2522,8 +2524,10 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) sc->stsd_count++; } - if (pb->eof_reached) + if (pb->eof_reached) { + av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSD atom\n"); return AVERROR_EOF; + } return 0; } @@ -2624,8 +2628,10 @@ static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->stsc_count = i; - if (pb->eof_reached) + if (pb->eof_reached) { + av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n"); return AVERROR_EOF; + } return 0; } @@ -2676,8 +2682,10 @@ static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->stps_count = i; - if (pb->eof_reached) + if (pb->eof_reached) { + av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STPS atom\n"); return AVERROR_EOF; + } return 0; } @@ -2723,8 +2731,10 @@ static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->keyframe_count = i; - if (pb->eof_reached) + if (pb->eof_reached) { + av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSS atom\n"); return AVERROR_EOF; + } return 0; } @@ -2808,8 +2818,10 @@ static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_free(buf); - if (pb->eof_reached) + if (pb->eof_reached) { + av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSZ atom\n"); return AVERROR_EOF; + } return 0; } @@ -2870,8 +2882,10 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->duration_for_fps += duration; sc->nb_frames_for_fps += total_sample_count; - if (pb->eof_reached) + if (pb->eof_reached) { + av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n"); return AVERROR_EOF; + } st->nb_frames= total_sample_count; if (duration) @@ -2947,8 +2961,10 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->ctts_count = ctts_count; - if (pb->eof_reached) + if (pb->eof_reached) { + av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted CTTS atom\n"); return AVERROR_EOF; + } av_log(c->fc, AV_LOG_TRACE, "dts shift %d\n", sc->dts_shift); @@ -2994,7 +3010,12 @@ static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->rap_group_count = i; - return pb->eof_reached ? AVERROR_EOF : 0; + if (pb->eof_reached) { + av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n"); + return AVERROR_EOF; + } + + return 0; } /** @@ -4743,8 +4764,10 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) fix_frag_index_entries(&c->frag_index, next_frag_index, frag->track_id, entries); - if (pb->eof_reached) + if (pb->eof_reached) { + av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted TRUN atom\n"); return AVERROR_EOF; + } frag->implicit_offset = offset; From 6bf5d69b2ffa8de1b6548eec6ba761118175b216 Mon Sep 17 00:00:00 2001 From: "tiejun.peng" Date: Sat, 9 Dec 2017 00:39:29 +0800 Subject: [PATCH 1303/2557] lavf/mov: modify code indentation Signed-off-by: tiejun.peng Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 48ec45254f24e..57fcda01547d5 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -6654,13 +6654,13 @@ static int mov_read_header(AVFormatContext *s) /* check MOV header */ do { - if (mov->moov_retry) - avio_seek(pb, 0, SEEK_SET); - if ((err = mov_read_default(mov, pb, atom)) < 0) { - av_log(s, AV_LOG_ERROR, "error reading header\n"); - mov_read_close(s); - return err; - } + if (mov->moov_retry) + avio_seek(pb, 0, SEEK_SET); + if ((err = mov_read_default(mov, pb, atom)) < 0) { + av_log(s, AV_LOG_ERROR, "error reading header\n"); + mov_read_close(s); + return err; + } } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mov->found_moov && !mov->moov_retry++); if (!mov->found_moov) { av_log(s, AV_LOG_ERROR, "moov atom not found\n"); From f20c8f6ec9ec982d15a8acc0a38103919780b48a Mon Sep 17 00:00:00 2001 From: "Mironov, Mikhail" Date: Fri, 8 Dec 2017 19:23:38 +0000 Subject: [PATCH 1304/2557] amf: fix wrong profile level after auto-correction in H264 and HEVC Moved bitrate parameters set before Init() call because bitrate is used in profile level correction code inside Init(). Signed-off-by: Mikhail Mironov Signed-off-by: Michael Niedermayer --- libavcodec/amfenc_h264.c | 10 +++++----- libavcodec/amfenc_hevc.c | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c index 3cacf320e3c17..96e4e952da930 100644 --- a/libavcodec/amfenc_h264.c +++ b/libavcodec/amfenc_h264.c @@ -213,7 +213,6 @@ static av_cold int amf_encode_init_h264(AVCodecContext *avctx) } } - if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE, AMF_VIDEO_ENCODER_PREENCODE_DISABLED); if (ctx->preanalysis) @@ -224,10 +223,6 @@ static av_cold int amf_encode_init_h264(AVCodecContext *avctx) AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUALITY_PRESET, ctx->quality); - // Initialize Encoder - res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); - // Dynamic parmaters AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD, ctx->rate_control_mode); @@ -279,6 +274,11 @@ static av_cold int amf_encode_init_h264(AVCodecContext *avctx) } else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); } + + // Initialize Encoder + res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); + // Enforce HRD, Filler Data, VBAQ, Frame Skipping, Deblocking Filter AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENFORCE_HRD, !!ctx->enforce_hrd); AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE, !!ctx->filler_data); diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c index ced57b1e9abd0..3956b2d178594 100644 --- a/libavcodec/amfenc_hevc.c +++ b/libavcodec/amfenc_hevc.c @@ -204,10 +204,6 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx) AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MOTION_HALF_PIXEL, ctx->me_half_pel); AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MOTION_QUARTERPIXEL, ctx->me_quarter_pel); - // init encoder - res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); - // init dynamic rate control params if (ctx->max_au_size) ctx->enforce_hrd = 1; @@ -225,6 +221,10 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx) av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); } + // init encoder + res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); + // init dynamic picture control params AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_AU_SIZE, ctx->max_au_size); From a4fc63c0f9eb803340c47479dcc5403b6fe3316d Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 10 Dec 2017 00:38:05 -0300 Subject: [PATCH 1305/2557] x86/lossless_videodsp: don't overread the dst buffer in ff_add_left_pred_unaligned_avx2 Fixes valgrind Signed-off-by: James Almer --- libavcodec/x86/lossless_videodsp.asm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/x86/lossless_videodsp.asm b/libavcodec/x86/lossless_videodsp.asm index 9a169fe3149a5..74fc95e84b0d9 100644 --- a/libavcodec/x86/lossless_videodsp.asm +++ b/libavcodec/x86/lossless_videodsp.asm @@ -154,8 +154,7 @@ MEDIAN_PRED add wq, mmsize jl %%.loop %if mmsize == 32 - mov eax, [dstq -1] - and eax, 0xff + movzx eax, byte [dstq - 1] %else; mov eax, mmsize-1 sub eax, wd From 438f884fc48b4b956fa713df2a722bd484f5646b Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 10 Dec 2017 00:51:01 -0300 Subject: [PATCH 1306/2557] x86/lossless_videodsp: rename ff_add_left_pred_int16_sse4 to ff_add_left_pred_int16_unaligned_ssse3 SSSE3_FAST is the proper check for it. Signed-off-by: James Almer --- libavcodec/x86/lossless_videodsp.asm | 4 ++-- libavcodec/x86/lossless_videodsp_init.c | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/libavcodec/x86/lossless_videodsp.asm b/libavcodec/x86/lossless_videodsp.asm index 74fc95e84b0d9..0a1b7091c954d 100644 --- a/libavcodec/x86/lossless_videodsp.asm +++ b/libavcodec/x86/lossless_videodsp.asm @@ -307,8 +307,8 @@ cglobal add_left_pred_int16, 4,4,8, dst, src, mask, w, left SPLATW m7 ,m7 ADD_HFYU_LEFT_LOOP_INT16 a, a -INIT_XMM sse4 -cglobal add_left_pred_int16, 4,4,8, dst, src, mask, w, left +INIT_XMM ssse3 +cglobal add_left_pred_int16_unaligned, 4,4,8, dst, src, mask, w, left mova m5, [pb_ef] mova m4, [pb_zzzzzzzz67676767] mova m3, [pb_zzzz2323zzzzabab] diff --git a/libavcodec/x86/lossless_videodsp_init.c b/libavcodec/x86/lossless_videodsp_init.c index e3063de4623d5..6d71f14e7f9cf 100644 --- a/libavcodec/x86/lossless_videodsp_init.c +++ b/libavcodec/x86/lossless_videodsp_init.c @@ -42,7 +42,7 @@ int ff_add_left_pred_unaligned_avx2(uint8_t *dst, const uint8_t *src, ptrdiff_t w, int left); int ff_add_left_pred_int16_ssse3(uint16_t *dst, const uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc); -int ff_add_left_pred_int16_sse4(uint16_t *dst, const uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc); +int ff_add_left_pred_int16_unaligned_ssse3(uint16_t *dst, const uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc); void ff_add_gradient_pred_ssse3(uint8_t *src, const ptrdiff_t stride, const ptrdiff_t width); void ff_add_gradient_pred_avx2(uint8_t *src, const ptrdiff_t stride, const ptrdiff_t width); @@ -117,11 +117,9 @@ void ff_llviddsp_init_x86(LLVidDSPContext *c) if (EXTERNAL_SSSE3_FAST(cpu_flags)) { c->add_left_pred = ff_add_left_pred_unaligned_ssse3; + c->add_left_pred_int16 = ff_add_left_pred_int16_unaligned_ssse3; } - if (EXTERNAL_SSE4(cpu_flags)) { - c->add_left_pred_int16 = ff_add_left_pred_int16_sse4; - } if (EXTERNAL_AVX2_FAST(cpu_flags)) { c->add_bytes = ff_add_bytes_avx2; c->add_left_pred = ff_add_left_pred_unaligned_avx2; From 1215889bc189e1787d7135dd628b9591d237d737 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 10 Dec 2017 00:51:35 -0300 Subject: [PATCH 1307/2557] checkasm/llviddsp: fix mixed code and declarations Signed-off-by: James Almer --- tests/checkasm/llviddsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/checkasm/llviddsp.c b/tests/checkasm/llviddsp.c index be63809a4b416..4f75ffc4593b6 100644 --- a/tests/checkasm/llviddsp.c +++ b/tests/checkasm/llviddsp.c @@ -168,14 +168,14 @@ static void check_add_left_pred_16(LLVidDSPContext c, unsigned mask, int width, static void check_add_gradient_pred(LLVidDSPContext c, int w) { int src_size, stride; uint8_t *src0, *src1; + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *src, const ptrdiff_t stride, + const ptrdiff_t width); + stride = w + 32; src_size = (stride + 32) * 2; /* dsp need previous line, and ignore the start of the line */ src0 = av_mallocz(src_size); src1 = av_mallocz(src_size); - declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *src, const ptrdiff_t stride, - const ptrdiff_t width); - init_buffer(src0, src1, uint8_t, src_size); if (check_func(c.add_gradient_pred, "add_gradient_pred")) { From 149268b47c4b0f9c584771e41d266d10cf7e3bf0 Mon Sep 17 00:00:00 2001 From: Mateusz Date: Fri, 8 Dec 2017 08:46:52 +0100 Subject: [PATCH 1308/2557] fix MSVC compilation errors After commit 3701d49 'error_resilience: remove avpriv_atomic usage' we have included windows.h in much more files and we should avoid conflicts with defines/function declarations. Signed-off-by: Mateusz Brzostek Signed-off-by: Michael Niedermayer --- libavcodec/jpegls.h | 2 ++ libavcodec/mjpegdec.h | 2 ++ libavcodec/mss2.c | 6 +++--- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libavcodec/jpegls.h b/libavcodec/jpegls.h index c8997c786185c..6b89b2afa3dfe 100644 --- a/libavcodec/jpegls.h +++ b/libavcodec/jpegls.h @@ -32,6 +32,8 @@ #include "avcodec.h" #include "internal.h" +#undef near /* This file uses struct member 'near' which in windows.h is defined as empty. */ + typedef struct JpeglsContext { AVCodecContext *avctx; } JpeglsContext; diff --git a/libavcodec/mjpegdec.h b/libavcodec/mjpegdec.h index c84a40aa6e649..c36fba5f2281a 100644 --- a/libavcodec/mjpegdec.h +++ b/libavcodec/mjpegdec.h @@ -39,6 +39,8 @@ #include "hpeldsp.h" #include "idctdsp.h" +#undef near /* This file uses struct member 'near' which in windows.h is defined as empty. */ + #define MAX_COMPONENTS 4 typedef struct MJpegDecodeContext { diff --git a/libavcodec/mss2.c b/libavcodec/mss2.c index 9e7cc466decd6..3180af1d607bd 100644 --- a/libavcodec/mss2.c +++ b/libavcodec/mss2.c @@ -464,9 +464,9 @@ static int decode_wmv9(AVCodecContext *avctx, const uint8_t *buf, int buf_size, return 0; } -typedef struct Rectangle { +struct Rectangle { int coded, x, y, w, h; -} Rectangle; +}; #define MAX_WMV9_RECTANGLES 20 #define ARITH2_PADDING 2 @@ -485,7 +485,7 @@ static int mss2_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, int keyframe, has_wmv9, has_mv, is_rle, is_555, ret; - Rectangle wmv9rects[MAX_WMV9_RECTANGLES], *r; + struct Rectangle wmv9rects[MAX_WMV9_RECTANGLES], *r; int used_rects = 0, i, implicit_rect = 0, av_uninit(wmv9_mask); if ((ret = init_get_bits8(&gb, buf, buf_size)) < 0) From 84936f68ede265cfa3b9315f908bfe76e81fae6e Mon Sep 17 00:00:00 2001 From: Thomas Guillem Date: Fri, 8 Dec 2017 15:59:39 +0000 Subject: [PATCH 1309/2557] lavc: Make hardware config method support more explicit for hwaccels This fixes the use of old ad-hoc methods which are still supported by some hwaccels which also support newer methods (DXVA2, VAAPI, VDPAU, videotoolbox) - without the method being visible here, ff_get_format() would refuse to use it. Signed-off-by: Mark Thompson --- libavcodec/hwaccel.h | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/libavcodec/hwaccel.h b/libavcodec/hwaccel.h index ae55527c2f3bb..3aaa92571c414 100644 --- a/libavcodec/hwaccel.h +++ b/libavcodec/hwaccel.h @@ -42,13 +42,14 @@ typedef struct AVCodecHWConfigInternal { // These macros are used to simplify AVCodecHWConfigInternal definitions. -#define HW_CONFIG_HWACCEL(format, device, name) \ +#define HW_CONFIG_HWACCEL(device, frames, ad_hoc, format, device_type_, name) \ &(const AVCodecHWConfigInternal) { \ .public = { \ .pix_fmt = AV_PIX_FMT_ ## format, \ - .methods = AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX | \ - AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, \ - .device_type = AV_HWDEVICE_TYPE_ ## device, \ + .methods = (device ? AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX : 0) | \ + (frames ? AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX : 0) | \ + (ad_hoc ? AV_CODEC_HW_CONFIG_METHOD_AD_HOC : 0), \ + .device_type = AV_HWDEVICE_TYPE_ ## device_type_, \ }, \ .hwaccel = &name, \ } @@ -63,32 +64,21 @@ typedef struct AVCodecHWConfigInternal { .hwaccel = NULL, \ } -#define HW_CONFIG_AD_HOC_HWACCEL(format, name) \ - &(const AVCodecHWConfigInternal) { \ - .public = { \ - .pix_fmt = AV_PIX_FMT_ ## format, \ - .methods = AV_CODEC_HW_CONFIG_METHOD_AD_HOC, \ - .device_type = AV_HWDEVICE_TYPE_NONE, \ - }, \ - .hwaccel = &name, \ - } - #define HWACCEL_DXVA2(codec) \ - HW_CONFIG_HWACCEL(DXVA2_VLD, DXVA2, ff_ ## codec ## _dxva2_hwaccel) + HW_CONFIG_HWACCEL(1, 1, 1, DXVA2_VLD, DXVA2, ff_ ## codec ## _dxva2_hwaccel) #define HWACCEL_D3D11VA2(codec) \ - HW_CONFIG_HWACCEL(D3D11, D3D11VA, ff_ ## codec ## _d3d11va2_hwaccel) + HW_CONFIG_HWACCEL(1, 1, 0, D3D11, D3D11VA, ff_ ## codec ## _d3d11va2_hwaccel) #define HWACCEL_NVDEC(codec) \ - HW_CONFIG_HWACCEL(CUDA, CUDA, ff_ ## codec ## _nvdec_hwaccel) + HW_CONFIG_HWACCEL(1, 1, 0, CUDA, CUDA, ff_ ## codec ## _nvdec_hwaccel) #define HWACCEL_VAAPI(codec) \ - HW_CONFIG_HWACCEL(VAAPI, VAAPI, ff_ ## codec ## _vaapi_hwaccel) + HW_CONFIG_HWACCEL(1, 1, 1, VAAPI, VAAPI, ff_ ## codec ## _vaapi_hwaccel) #define HWACCEL_VDPAU(codec) \ - HW_CONFIG_HWACCEL(VDPAU, VDPAU, ff_ ## codec ## _vdpau_hwaccel) + HW_CONFIG_HWACCEL(1, 1, 1, VDPAU, VDPAU, ff_ ## codec ## _vdpau_hwaccel) #define HWACCEL_VIDEOTOOLBOX(codec) \ - HW_CONFIG_HWACCEL(VIDEOTOOLBOX, VIDEOTOOLBOX, ff_ ## codec ## _videotoolbox_hwaccel) - + HW_CONFIG_HWACCEL(1, 1, 1, VIDEOTOOLBOX, VIDEOTOOLBOX, ff_ ## codec ## _videotoolbox_hwaccel) #define HWACCEL_D3D11VA(codec) \ - HW_CONFIG_AD_HOC_HWACCEL(D3D11VA_VLD, ff_ ## codec ## _d3d11va_hwaccel) + HW_CONFIG_HWACCEL(0, 0, 1, D3D11VA_VLD, NONE, ff_ ## codec ## _d3d11va_hwaccel) #define HWACCEL_XVMC(codec) \ - HW_CONFIG_AD_HOC_HWACCEL(XVMC, ff_ ## codec ## _xvmc_hwaccel) + HW_CONFIG_HWACCEL(0, 0, 1, XVMC, NONE, ff_ ## codec ## _xvmc_hwaccel) #endif /* AVCODEC_HWACCEL_H */ From 2adfb10921668f01eb4c3e08ce57375be6d084de Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 10 Dec 2017 17:15:06 +0000 Subject: [PATCH 1310/2557] configure: Move V4L2 M2M help line to the hardware library section --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index d05388638d20d..d5bbb5b7a9915 100755 --- a/configure +++ b/configure @@ -185,7 +185,6 @@ Individual component options: --enable-filter=NAME enable filter NAME --disable-filter=NAME disable filter NAME --disable-filters disable all filters - --disable-v4l2_m2m disable V4L2 mem2mem code [autodetect] External library support: @@ -320,6 +319,7 @@ External library support: --enable-omx enable OpenMAX IL code [no] --enable-omx-rpi enable OpenMAX IL code for Raspberry Pi [no] --enable-rkmpp enable Rockchip Media Process Platform code [no] + --disable-v4l2-m2m disable V4L2 mem2mem code [autodetect] --disable-vaapi disable Video Acceleration API (mainly Unix/Intel) code [autodetect] --disable-vdpau disable Nvidia Video Decode and Presentation API for Unix code [autodetect] --disable-videotoolbox disable VideoToolbox code [autodetect] From 1d0817d56b66797118880358ea7d7a2acfdca429 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 7 Dec 2017 15:32:54 +0100 Subject: [PATCH 1311/2557] avcodec/amrwbdec: Fix division by 0 in voice_factor() The added value matches "Digital cellular telecommunications system (Phase 2+) (GSM); Universal Mobile Telecommunications System (UMTS); LTE; Extended Adaptive Multi-Rate - Wideband (AMR-WB+) codec; Floating-point ANSI-C code (3GPP TS 26.304 version 14.0.0 Release 14) Extended Adaptive Multi-Rate - Wideband (AMR-WB+) codec; Floating-point ANSI-C code" Fixes: runtime error: division by zero Fixes: 4415/clusterfuzz-testcase-minimized-4677752314658816 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/amrwbdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/amrwbdec.c b/libavcodec/amrwbdec.c index 57aed874cc467..7f2874d35f39c 100644 --- a/libavcodec/amrwbdec.c +++ b/libavcodec/amrwbdec.c @@ -611,7 +611,7 @@ static float voice_factor(float *p_vector, float p_gain, AMRWB_SFR_SIZE) * f_gain * f_gain; - return (p_ener - f_ener) / (p_ener + f_ener); + return (p_ener - f_ener) / (p_ener + f_ener + 0.01); } /** From eaff5fcb7cde8d1614755269773d471d3a3d1bfc Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 6 Dec 2017 22:42:05 +0100 Subject: [PATCH 1312/2557] avcodec/vp9_superframe_split_bsf: Fix integer overflow in frame_size/total_size checks Fixes: signed integer overflow: -1698586465 + -551542752 cannot be represented in type 'int' Fixes: 4490/clusterfuzz-testcase-minimized-5210014592532480 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/vp9_superframe_split_bsf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/vp9_superframe_split_bsf.c b/libavcodec/vp9_superframe_split_bsf.c index 6d6d8e664d0ac..0d2523ebf7580 100644 --- a/libavcodec/vp9_superframe_split_bsf.c +++ b/libavcodec/vp9_superframe_split_bsf.c @@ -59,7 +59,7 @@ static int vp9_superframe_split_filter(AVBSFContext *ctx, AVPacket *out) if (in->size >= idx_size && in->data[in->size - idx_size] == marker) { GetByteContext bc; - int total_size = 0; + int64_t total_size = 0; bytestream2_init(&bc, in->data + in->size + 1 - idx_size, nb_frames * length_size); @@ -70,7 +70,7 @@ static int vp9_superframe_split_filter(AVBSFContext *ctx, AVPacket *out) frame_size |= bytestream2_get_byte(&bc) << (j * 8); total_size += frame_size; - if (total_size > in->size - idx_size) { + if (frame_size < 0 || total_size > in->size - idx_size) { av_log(ctx, AV_LOG_ERROR, "Invalid frame size in a superframe: %d\n", frame_size); ret = AVERROR(EINVAL); From 514cf22a0d3abb5126d24b44f4291394e8ef8e39 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 10 Dec 2017 20:46:55 +0100 Subject: [PATCH 1313/2557] lavc/huffyuvenc: Move a variable declaration up. Fixes a warning with gcc-6.3: libavcodec/huffyuvenc.c:93:5: warning: ISO C90 forbids mixed declarations and code --- libavcodec/huffyuvenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/huffyuvenc.c b/libavcodec/huffyuvenc.c index aa71d20fcce75..8be752844b029 100644 --- a/libavcodec/huffyuvenc.c +++ b/libavcodec/huffyuvenc.c @@ -86,11 +86,11 @@ static inline void sub_left_prediction_bgr32(HYuvContext *s, uint8_t *dst, { int i; int r, g, b, a; + int min_width = FFMIN(w, 8); r = *red; g = *green; b = *blue; a = *alpha; - int min_width = FFMIN(w, 8); for (i = 0; i < min_width; i++) { const int rt = src[i * 4 + R]; From bad51e9287188ec61cc72e33b689e4a90690dfe8 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 10 Dec 2017 21:03:28 -0300 Subject: [PATCH 1314/2557] doc/libav-merge: add a line about the skipped HEVC MC arm functions Signed-off-by: James Almer --- doc/libav-merge.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/libav-merge.txt b/doc/libav-merge.txt index 37839a97a7c21..5eed8ce777b5f 100644 --- a/doc/libav-merge.txt +++ b/doc/libav-merge.txt @@ -94,6 +94,7 @@ Stuff that didn't reach the codebase: - a853388d2 hevc: change the stride of the MC buffer to be in bytes instead of elements - 0cef06df0 checkasm: add HEVC MC tests - e7078e842 hevcdsp: add x86 SIMD for MC + - 7993ec19a hevc: Add hevc_get_pixel_4/8/12/16/24/32/48/64 - VAAPI VP8 decode hwaccel (currently under review: http://ffmpeg.org/pipermail/ffmpeg-devel/2017-February/thread.html#207348) - Removal of the custom atomic API (5cc0057f49, see http://ffmpeg.org/pipermail/ffmpeg-devel/2017-March/209003.html) - new bitstream reader (see http://ffmpeg.org/pipermail/ffmpeg-devel/2017-April/209609.html) From a83a03af9a841e91b41e6adc1def7a363893a68a Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Mon, 11 Dec 2017 00:04:44 +0000 Subject: [PATCH 1315/2557] libavcodec: Move ff_print_debug_info2 to mpegutils.c --- libavcodec/mpegutils.c | 313 ++++++++++++++++++++++++++++++++++++++++ libavcodec/mpegutils.h | 8 ++ libavcodec/mpegvideo.c | 314 ----------------------------------------- libavcodec/mpegvideo.h | 4 - 4 files changed, 321 insertions(+), 318 deletions(-) diff --git a/libavcodec/mpegutils.c b/libavcodec/mpegutils.c index 62cc36aa6e0ca..3f945406162b4 100644 --- a/libavcodec/mpegutils.c +++ b/libavcodec/mpegutils.c @@ -23,10 +23,31 @@ #include "libavutil/common.h" #include "libavutil/frame.h" #include "libavutil/pixdesc.h" +#include "libavutil/motion_vector.h" +#include "libavutil/avassert.h" #include "avcodec.h" #include "mpegutils.h" +static int add_mb(AVMotionVector *mb, uint32_t mb_type, + int dst_x, int dst_y, + int motion_x, int motion_y, int motion_scale, + int direction) +{ + mb->w = IS_8X8(mb_type) || IS_8X16(mb_type) ? 8 : 16; + mb->h = IS_8X8(mb_type) || IS_16X8(mb_type) ? 8 : 16; + mb->motion_x = motion_x; + mb->motion_y = motion_y; + mb->motion_scale = motion_scale; + mb->dst_x = dst_x; + mb->dst_y = dst_y; + mb->src_x = dst_x + motion_x / motion_scale; + mb->src_y = dst_y + motion_y / motion_scale; + mb->source = direction ? 1 : -1; + mb->flags = 0; // XXX: does mb_type contain extra information that could be exported here? + return 1; +} + void ff_draw_horiz_band(AVCodecContext *avctx, AVFrame *cur, AVFrame *last, int y, int h, int picture_structure, @@ -78,3 +99,295 @@ void ff_draw_horiz_band(AVCodecContext *avctx, y, picture_structure, h); } } + +void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_table, + uint32_t *mbtype_table, int8_t *qscale_table, int16_t (*motion_val[2])[2], + int *low_delay, + int mb_width, int mb_height, int mb_stride, int quarter_sample) +{ + if ((avctx->flags2 & AV_CODEC_FLAG2_EXPORT_MVS) && mbtype_table && motion_val[0]) { + const int shift = 1 + quarter_sample; + const int scale = 1 << shift; + const int mv_sample_log2 = avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_SVQ3 ? 2 : 1; + const int mv_stride = (mb_width << mv_sample_log2) + + (avctx->codec->id == AV_CODEC_ID_H264 ? 0 : 1); + int mb_x, mb_y, mbcount = 0; + + /* size is width * height * 2 * 4 where 2 is for directions and 4 is + * for the maximum number of MB (4 MB in case of IS_8x8) */ + AVMotionVector *mvs = av_malloc_array(mb_width * mb_height, 2 * 4 * sizeof(AVMotionVector)); + if (!mvs) + return; + + for (mb_y = 0; mb_y < mb_height; mb_y++) { + for (mb_x = 0; mb_x < mb_width; mb_x++) { + int i, direction, mb_type = mbtype_table[mb_x + mb_y * mb_stride]; + for (direction = 0; direction < 2; direction++) { + if (!USES_LIST(mb_type, direction)) + continue; + if (IS_8X8(mb_type)) { + for (i = 0; i < 4; i++) { + int sx = mb_x * 16 + 4 + 8 * (i & 1); + int sy = mb_y * 16 + 4 + 8 * (i >> 1); + int xy = (mb_x * 2 + (i & 1) + + (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1); + int mx = motion_val[direction][xy][0]; + int my = motion_val[direction][xy][1]; + mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction); + } + } else if (IS_16X8(mb_type)) { + for (i = 0; i < 2; i++) { + int sx = mb_x * 16 + 8; + int sy = mb_y * 16 + 4 + 8 * i; + int xy = (mb_x * 2 + (mb_y * 2 + i) * mv_stride) << (mv_sample_log2 - 1); + int mx = motion_val[direction][xy][0]; + int my = motion_val[direction][xy][1]; + + if (IS_INTERLACED(mb_type)) + my *= 2; + + mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction); + } + } else if (IS_8X16(mb_type)) { + for (i = 0; i < 2; i++) { + int sx = mb_x * 16 + 4 + 8 * i; + int sy = mb_y * 16 + 8; + int xy = (mb_x * 2 + i + mb_y * 2 * mv_stride) << (mv_sample_log2 - 1); + int mx = motion_val[direction][xy][0]; + int my = motion_val[direction][xy][1]; + + if (IS_INTERLACED(mb_type)) + my *= 2; + + mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction); + } + } else { + int sx = mb_x * 16 + 8; + int sy = mb_y * 16 + 8; + int xy = (mb_x + mb_y * mv_stride) << mv_sample_log2; + int mx = motion_val[direction][xy][0]; + int my = motion_val[direction][xy][1]; + mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction); + } + } + } + } + + if (mbcount) { + AVFrameSideData *sd; + + av_log(avctx, AV_LOG_DEBUG, "Adding %d MVs info to frame %d\n", mbcount, avctx->frame_number); + sd = av_frame_new_side_data(pict, AV_FRAME_DATA_MOTION_VECTORS, mbcount * sizeof(AVMotionVector)); + if (!sd) { + av_freep(&mvs); + return; + } + memcpy(sd->data, mvs, mbcount * sizeof(AVMotionVector)); + } + + av_freep(&mvs); + } + + /* TODO: export all the following to make them accessible for users (and filters) */ + if (avctx->hwaccel || !mbtype_table) + return; + + + if (avctx->debug & (FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)) { + int x,y; + + av_log(avctx, AV_LOG_DEBUG, "New frame, type: %c\n", + av_get_picture_type_char(pict->pict_type)); + for (y = 0; y < mb_height; y++) { + for (x = 0; x < mb_width; x++) { + if (avctx->debug & FF_DEBUG_SKIP) { + int count = mbskip_table ? mbskip_table[x + y * mb_stride] : 0; + if (count > 9) + count = 9; + av_log(avctx, AV_LOG_DEBUG, "%1d", count); + } + if (avctx->debug & FF_DEBUG_QP) { + av_log(avctx, AV_LOG_DEBUG, "%2d", + qscale_table[x + y * mb_stride]); + } + if (avctx->debug & FF_DEBUG_MB_TYPE) { + int mb_type = mbtype_table[x + y * mb_stride]; + // Type & MV direction + if (IS_PCM(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "P"); + else if (IS_INTRA(mb_type) && IS_ACPRED(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "A"); + else if (IS_INTRA4x4(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "i"); + else if (IS_INTRA16x16(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "I"); + else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "d"); + else if (IS_DIRECT(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "D"); + else if (IS_GMC(mb_type) && IS_SKIP(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "g"); + else if (IS_GMC(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "G"); + else if (IS_SKIP(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "S"); + else if (!USES_LIST(mb_type, 1)) + av_log(avctx, AV_LOG_DEBUG, ">"); + else if (!USES_LIST(mb_type, 0)) + av_log(avctx, AV_LOG_DEBUG, "<"); + else { + av_assert2(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); + av_log(avctx, AV_LOG_DEBUG, "X"); + } + + // segmentation + if (IS_8X8(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "+"); + else if (IS_16X8(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "-"); + else if (IS_8X16(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "|"); + else if (IS_INTRA(mb_type) || IS_16X16(mb_type)) + av_log(avctx, AV_LOG_DEBUG, " "); + else + av_log(avctx, AV_LOG_DEBUG, "?"); + + + if (IS_INTERLACED(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "="); + else + av_log(avctx, AV_LOG_DEBUG, " "); + } + } + av_log(avctx, AV_LOG_DEBUG, "\n"); + } + } + +#if FF_API_DEBUG_MV + if ((avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || + (avctx->debug_mv)) { + int mb_y; + int i, ret; + int h_chroma_shift, v_chroma_shift, block_height; + const int mv_sample_log2 = avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_SVQ3 ? 2 : 1; + const int mv_stride = (mb_width << mv_sample_log2) + + (avctx->codec->id == AV_CODEC_ID_H264 ? 0 : 1); + + if (low_delay) + *low_delay = 0; // needed to see the vectors without trashing the buffers + + ret = av_pix_fmt_get_chroma_sub_sample (avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift); + if (ret) + return ret; + + av_frame_make_writable(pict); + + pict->opaque = NULL; + block_height = 16 >> v_chroma_shift; + + for (mb_y = 0; mb_y < mb_height; mb_y++) { + int mb_x; + for (mb_x = 0; mb_x < mb_width; mb_x++) { + const int mb_index = mb_x + mb_y * mb_stride; + if ((avctx->debug & FF_DEBUG_VIS_QP)) { + uint64_t c = (qscale_table[mb_index] * 128 / 31) * + 0x0101010101010101ULL; + int y; + for (y = 0; y < block_height; y++) { + *(uint64_t *)(pict->data[1] + 8 * mb_x + + (block_height * mb_y + y) * + pict->linesize[1]) = c; + *(uint64_t *)(pict->data[2] + 8 * mb_x + + (block_height * mb_y + y) * + pict->linesize[2]) = c; + } + } + if ((avctx->debug & FF_DEBUG_VIS_MB_TYPE) && + motion_val[0]) { + int mb_type = mbtype_table[mb_index]; + uint64_t u,v; + int y; +#define COLOR(theta, r) \ + u = (int)(128 + r * cos(theta * M_PI / 180)); \ + v = (int)(128 + r * sin(theta * M_PI / 180)); + + + u = v = 128; + if (IS_PCM(mb_type)) { + COLOR(120, 48) + } else if ((IS_INTRA(mb_type) && IS_ACPRED(mb_type)) || + IS_INTRA16x16(mb_type)) { + COLOR(30, 48) + } else if (IS_INTRA4x4(mb_type)) { + COLOR(90, 48) + } else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type)) { + // COLOR(120, 48) + } else if (IS_DIRECT(mb_type)) { + COLOR(150, 48) + } else if (IS_GMC(mb_type) && IS_SKIP(mb_type)) { + COLOR(170, 48) + } else if (IS_GMC(mb_type)) { + COLOR(190, 48) + } else if (IS_SKIP(mb_type)) { + // COLOR(180, 48) + } else if (!USES_LIST(mb_type, 1)) { + COLOR(240, 48) + } else if (!USES_LIST(mb_type, 0)) { + COLOR(0, 48) + } else { + av_assert2(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); + COLOR(300,48) + } + + u *= 0x0101010101010101ULL; + v *= 0x0101010101010101ULL; + for (y = 0; y < block_height; y++) { + *(uint64_t *)(pict->data[1] + 8 * mb_x + + (block_height * mb_y + y) * pict->linesize[1]) = u; + *(uint64_t *)(pict->data[2] + 8 * mb_x + + (block_height * mb_y + y) * pict->linesize[2]) = v; + } + + // segmentation + if (IS_8X8(mb_type) || IS_16X8(mb_type)) { + *(uint64_t *)(pict->data[0] + 16 * mb_x + 0 + + (16 * mb_y + 8) * pict->linesize[0]) ^= 0x8080808080808080ULL; + *(uint64_t *)(pict->data[0] + 16 * mb_x + 8 + + (16 * mb_y + 8) * pict->linesize[0]) ^= 0x8080808080808080ULL; + } + if (IS_8X8(mb_type) || IS_8X16(mb_type)) { + for (y = 0; y < 16; y++) + pict->data[0][16 * mb_x + 8 + (16 * mb_y + y) * + pict->linesize[0]] ^= 0x80; + } + if (IS_8X8(mb_type) && mv_sample_log2 >= 2) { + int dm = 1 << (mv_sample_log2 - 2); + for (i = 0; i < 4; i++) { + int sx = mb_x * 16 + 8 * (i & 1); + int sy = mb_y * 16 + 8 * (i >> 1); + int xy = (mb_x * 2 + (i & 1) + + (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1); + // FIXME bidir + int32_t *mv = (int32_t *) &motion_val[0][xy]; + if (mv[0] != mv[dm] || + mv[dm * mv_stride] != mv[dm * (mv_stride + 1)]) + for (y = 0; y < 8; y++) + pict->data[0][sx + 4 + (sy + y) * pict->linesize[0]] ^= 0x80; + if (mv[0] != mv[dm * mv_stride] || mv[dm] != mv[dm * (mv_stride + 1)]) + *(uint64_t *)(pict->data[0] + sx + (sy + 4) * + pict->linesize[0]) ^= 0x8080808080808080ULL; + } + } + + if (IS_INTERLACED(mb_type) && + avctx->codec->id == AV_CODEC_ID_H264) { + // hmm + } + } + if (mbskip_table) + mbskip_table[mb_index] = 0; + } + } + } +#endif +} diff --git a/libavcodec/mpegutils.h b/libavcodec/mpegutils.h index 1bf73fea02416..1ed21c19be6ef 100644 --- a/libavcodec/mpegutils.h +++ b/libavcodec/mpegutils.h @@ -137,4 +137,12 @@ void ff_draw_horiz_band(AVCodecContext *avctx, AVFrame *cur, AVFrame *last, int y, int h, int picture_structure, int first_field, int low_delay); +/** + * Print debugging info for the given picture. + */ +void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_table, + uint32_t *mbtype_table, int8_t *qscale_table, int16_t (*motion_val[2])[2], + int *low_delay, + int mb_width, int mb_height, int mb_stride, int quarter_sample); + #endif /* AVCODEC_MPEGUTILS_H */ diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 2eb19c21bb387..18c3a87edaa13 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -1419,320 +1419,6 @@ void ff_mpv_frame_end(MpegEncContext *s) ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); } -static int add_mb(AVMotionVector *mb, uint32_t mb_type, - int dst_x, int dst_y, - int motion_x, int motion_y, int motion_scale, - int direction) -{ - mb->w = IS_8X8(mb_type) || IS_8X16(mb_type) ? 8 : 16; - mb->h = IS_8X8(mb_type) || IS_16X8(mb_type) ? 8 : 16; - mb->motion_x = motion_x; - mb->motion_y = motion_y; - mb->motion_scale = motion_scale; - mb->dst_x = dst_x; - mb->dst_y = dst_y; - mb->src_x = dst_x + motion_x / motion_scale; - mb->src_y = dst_y + motion_y / motion_scale; - mb->source = direction ? 1 : -1; - mb->flags = 0; // XXX: does mb_type contain extra information that could be exported here? - return 1; -} - -/** - * Print debugging info for the given picture. - */ -void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_table, - uint32_t *mbtype_table, int8_t *qscale_table, int16_t (*motion_val[2])[2], - int *low_delay, - int mb_width, int mb_height, int mb_stride, int quarter_sample) -{ - if ((avctx->flags2 & AV_CODEC_FLAG2_EXPORT_MVS) && mbtype_table && motion_val[0]) { - const int shift = 1 + quarter_sample; - const int scale = 1 << shift; - const int mv_sample_log2 = avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_SVQ3 ? 2 : 1; - const int mv_stride = (mb_width << mv_sample_log2) + - (avctx->codec->id == AV_CODEC_ID_H264 ? 0 : 1); - int mb_x, mb_y, mbcount = 0; - - /* size is width * height * 2 * 4 where 2 is for directions and 4 is - * for the maximum number of MB (4 MB in case of IS_8x8) */ - AVMotionVector *mvs = av_malloc_array(mb_width * mb_height, 2 * 4 * sizeof(AVMotionVector)); - if (!mvs) - return; - - for (mb_y = 0; mb_y < mb_height; mb_y++) { - for (mb_x = 0; mb_x < mb_width; mb_x++) { - int i, direction, mb_type = mbtype_table[mb_x + mb_y * mb_stride]; - for (direction = 0; direction < 2; direction++) { - if (!USES_LIST(mb_type, direction)) - continue; - if (IS_8X8(mb_type)) { - for (i = 0; i < 4; i++) { - int sx = mb_x * 16 + 4 + 8 * (i & 1); - int sy = mb_y * 16 + 4 + 8 * (i >> 1); - int xy = (mb_x * 2 + (i & 1) + - (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1); - int mx = motion_val[direction][xy][0]; - int my = motion_val[direction][xy][1]; - mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction); - } - } else if (IS_16X8(mb_type)) { - for (i = 0; i < 2; i++) { - int sx = mb_x * 16 + 8; - int sy = mb_y * 16 + 4 + 8 * i; - int xy = (mb_x * 2 + (mb_y * 2 + i) * mv_stride) << (mv_sample_log2 - 1); - int mx = motion_val[direction][xy][0]; - int my = motion_val[direction][xy][1]; - - if (IS_INTERLACED(mb_type)) - my *= 2; - - mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction); - } - } else if (IS_8X16(mb_type)) { - for (i = 0; i < 2; i++) { - int sx = mb_x * 16 + 4 + 8 * i; - int sy = mb_y * 16 + 8; - int xy = (mb_x * 2 + i + mb_y * 2 * mv_stride) << (mv_sample_log2 - 1); - int mx = motion_val[direction][xy][0]; - int my = motion_val[direction][xy][1]; - - if (IS_INTERLACED(mb_type)) - my *= 2; - - mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction); - } - } else { - int sx = mb_x * 16 + 8; - int sy = mb_y * 16 + 8; - int xy = (mb_x + mb_y * mv_stride) << mv_sample_log2; - int mx = motion_val[direction][xy][0]; - int my = motion_val[direction][xy][1]; - mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction); - } - } - } - } - - if (mbcount) { - AVFrameSideData *sd; - - av_log(avctx, AV_LOG_DEBUG, "Adding %d MVs info to frame %d\n", mbcount, avctx->frame_number); - sd = av_frame_new_side_data(pict, AV_FRAME_DATA_MOTION_VECTORS, mbcount * sizeof(AVMotionVector)); - if (!sd) { - av_freep(&mvs); - return; - } - memcpy(sd->data, mvs, mbcount * sizeof(AVMotionVector)); - } - - av_freep(&mvs); - } - - /* TODO: export all the following to make them accessible for users (and filters) */ - if (avctx->hwaccel || !mbtype_table) - return; - - - if (avctx->debug & (FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)) { - int x,y; - - av_log(avctx, AV_LOG_DEBUG, "New frame, type: %c\n", - av_get_picture_type_char(pict->pict_type)); - for (y = 0; y < mb_height; y++) { - for (x = 0; x < mb_width; x++) { - if (avctx->debug & FF_DEBUG_SKIP) { - int count = mbskip_table ? mbskip_table[x + y * mb_stride] : 0; - if (count > 9) - count = 9; - av_log(avctx, AV_LOG_DEBUG, "%1d", count); - } - if (avctx->debug & FF_DEBUG_QP) { - av_log(avctx, AV_LOG_DEBUG, "%2d", - qscale_table[x + y * mb_stride]); - } - if (avctx->debug & FF_DEBUG_MB_TYPE) { - int mb_type = mbtype_table[x + y * mb_stride]; - // Type & MV direction - if (IS_PCM(mb_type)) - av_log(avctx, AV_LOG_DEBUG, "P"); - else if (IS_INTRA(mb_type) && IS_ACPRED(mb_type)) - av_log(avctx, AV_LOG_DEBUG, "A"); - else if (IS_INTRA4x4(mb_type)) - av_log(avctx, AV_LOG_DEBUG, "i"); - else if (IS_INTRA16x16(mb_type)) - av_log(avctx, AV_LOG_DEBUG, "I"); - else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type)) - av_log(avctx, AV_LOG_DEBUG, "d"); - else if (IS_DIRECT(mb_type)) - av_log(avctx, AV_LOG_DEBUG, "D"); - else if (IS_GMC(mb_type) && IS_SKIP(mb_type)) - av_log(avctx, AV_LOG_DEBUG, "g"); - else if (IS_GMC(mb_type)) - av_log(avctx, AV_LOG_DEBUG, "G"); - else if (IS_SKIP(mb_type)) - av_log(avctx, AV_LOG_DEBUG, "S"); - else if (!USES_LIST(mb_type, 1)) - av_log(avctx, AV_LOG_DEBUG, ">"); - else if (!USES_LIST(mb_type, 0)) - av_log(avctx, AV_LOG_DEBUG, "<"); - else { - av_assert2(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); - av_log(avctx, AV_LOG_DEBUG, "X"); - } - - // segmentation - if (IS_8X8(mb_type)) - av_log(avctx, AV_LOG_DEBUG, "+"); - else if (IS_16X8(mb_type)) - av_log(avctx, AV_LOG_DEBUG, "-"); - else if (IS_8X16(mb_type)) - av_log(avctx, AV_LOG_DEBUG, "|"); - else if (IS_INTRA(mb_type) || IS_16X16(mb_type)) - av_log(avctx, AV_LOG_DEBUG, " "); - else - av_log(avctx, AV_LOG_DEBUG, "?"); - - - if (IS_INTERLACED(mb_type)) - av_log(avctx, AV_LOG_DEBUG, "="); - else - av_log(avctx, AV_LOG_DEBUG, " "); - } - } - av_log(avctx, AV_LOG_DEBUG, "\n"); - } - } - -#if FF_API_DEBUG_MV - if ((avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || - (avctx->debug_mv)) { - int mb_y; - int i, ret; - int h_chroma_shift, v_chroma_shift, block_height; - const int mv_sample_log2 = avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_SVQ3 ? 2 : 1; - const int mv_stride = (mb_width << mv_sample_log2) + - (avctx->codec->id == AV_CODEC_ID_H264 ? 0 : 1); - - if (low_delay) - *low_delay = 0; // needed to see the vectors without trashing the buffers - - ret = av_pix_fmt_get_chroma_sub_sample (avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift); - if (ret) - return ret; - - av_frame_make_writable(pict); - - pict->opaque = NULL; - block_height = 16 >> v_chroma_shift; - - for (mb_y = 0; mb_y < mb_height; mb_y++) { - int mb_x; - for (mb_x = 0; mb_x < mb_width; mb_x++) { - const int mb_index = mb_x + mb_y * mb_stride; - if ((avctx->debug & FF_DEBUG_VIS_QP)) { - uint64_t c = (qscale_table[mb_index] * 128 / 31) * - 0x0101010101010101ULL; - int y; - for (y = 0; y < block_height; y++) { - *(uint64_t *)(pict->data[1] + 8 * mb_x + - (block_height * mb_y + y) * - pict->linesize[1]) = c; - *(uint64_t *)(pict->data[2] + 8 * mb_x + - (block_height * mb_y + y) * - pict->linesize[2]) = c; - } - } - if ((avctx->debug & FF_DEBUG_VIS_MB_TYPE) && - motion_val[0]) { - int mb_type = mbtype_table[mb_index]; - uint64_t u,v; - int y; -#define COLOR(theta, r) \ - u = (int)(128 + r * cos(theta * M_PI / 180)); \ - v = (int)(128 + r * sin(theta * M_PI / 180)); - - - u = v = 128; - if (IS_PCM(mb_type)) { - COLOR(120, 48) - } else if ((IS_INTRA(mb_type) && IS_ACPRED(mb_type)) || - IS_INTRA16x16(mb_type)) { - COLOR(30, 48) - } else if (IS_INTRA4x4(mb_type)) { - COLOR(90, 48) - } else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type)) { - // COLOR(120, 48) - } else if (IS_DIRECT(mb_type)) { - COLOR(150, 48) - } else if (IS_GMC(mb_type) && IS_SKIP(mb_type)) { - COLOR(170, 48) - } else if (IS_GMC(mb_type)) { - COLOR(190, 48) - } else if (IS_SKIP(mb_type)) { - // COLOR(180, 48) - } else if (!USES_LIST(mb_type, 1)) { - COLOR(240, 48) - } else if (!USES_LIST(mb_type, 0)) { - COLOR(0, 48) - } else { - av_assert2(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); - COLOR(300,48) - } - - u *= 0x0101010101010101ULL; - v *= 0x0101010101010101ULL; - for (y = 0; y < block_height; y++) { - *(uint64_t *)(pict->data[1] + 8 * mb_x + - (block_height * mb_y + y) * pict->linesize[1]) = u; - *(uint64_t *)(pict->data[2] + 8 * mb_x + - (block_height * mb_y + y) * pict->linesize[2]) = v; - } - - // segmentation - if (IS_8X8(mb_type) || IS_16X8(mb_type)) { - *(uint64_t *)(pict->data[0] + 16 * mb_x + 0 + - (16 * mb_y + 8) * pict->linesize[0]) ^= 0x8080808080808080ULL; - *(uint64_t *)(pict->data[0] + 16 * mb_x + 8 + - (16 * mb_y + 8) * pict->linesize[0]) ^= 0x8080808080808080ULL; - } - if (IS_8X8(mb_type) || IS_8X16(mb_type)) { - for (y = 0; y < 16; y++) - pict->data[0][16 * mb_x + 8 + (16 * mb_y + y) * - pict->linesize[0]] ^= 0x80; - } - if (IS_8X8(mb_type) && mv_sample_log2 >= 2) { - int dm = 1 << (mv_sample_log2 - 2); - for (i = 0; i < 4; i++) { - int sx = mb_x * 16 + 8 * (i & 1); - int sy = mb_y * 16 + 8 * (i >> 1); - int xy = (mb_x * 2 + (i & 1) + - (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1); - // FIXME bidir - int32_t *mv = (int32_t *) &motion_val[0][xy]; - if (mv[0] != mv[dm] || - mv[dm * mv_stride] != mv[dm * (mv_stride + 1)]) - for (y = 0; y < 8; y++) - pict->data[0][sx + 4 + (sy + y) * pict->linesize[0]] ^= 0x80; - if (mv[0] != mv[dm * mv_stride] || mv[dm] != mv[dm * (mv_stride + 1)]) - *(uint64_t *)(pict->data[0] + sx + (sy + 4) * - pict->linesize[0]) ^= 0x8080808080808080ULL; - } - } - - if (IS_INTERLACED(mb_type) && - avctx->codec->id == AV_CODEC_ID_H264) { - // hmm - } - } - if (mbskip_table) - mbskip_table[mb_index] = 0; - } - } - } -#endif -} - void ff_print_debug_info(MpegEncContext *s, Picture *p, AVFrame *pict) { ff_print_debug_info2(s->avctx, pict, s->mbskip_table, p->mb_type, diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 6f20336bb5e05..c5e3359458df7 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -696,10 +696,6 @@ void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h); void ff_mpeg_flush(AVCodecContext *avctx); void ff_print_debug_info(MpegEncContext *s, Picture *p, AVFrame *pict); -void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_table, - uint32_t *mbtype_table, int8_t *qscale_table, int16_t (*motion_val[2])[2], - int *low_delay, - int mb_width, int mb_height, int mb_stride, int quarter_sample); int ff_mpv_export_qp_table(MpegEncContext *s, AVFrame *f, Picture *p, int qp_type); From 918de766f545008cb1ab3d62febe71fa064f8ca7 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Sun, 10 Dec 2017 23:51:37 +0000 Subject: [PATCH 1316/2557] h264dec: Remove mpeg4video.h header dependency --- libavcodec/h264dec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 1d99ed5f4c2c5..1e98765439c16 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -51,7 +51,6 @@ #include "mathops.h" #include "me_cmp.h" #include "mpegutils.h" -#include "mpeg4video.h" #include "profiles.h" #include "rectangle.h" #include "thread.h" From 08d28ee1823a7232541526770657dc49a218ad8f Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 11 Dec 2017 11:03:25 +0800 Subject: [PATCH 1317/2557] avformat/hlsenc: move init operations from write_header to init Reviewed-by: Vishwanath Dixit Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 681 ++++++++++++++++++++++--------------------- 1 file changed, 345 insertions(+), 336 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 7dc8f4237b636..dd09739651618 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1640,329 +1640,12 @@ static int hls_write_header(AVFormatContext *s) { HLSContext *hls = s->priv_data; int ret, i, j; - char *p = NULL; - const char *pattern = "%d.ts"; - const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s); - const char *vtt_pattern = "%d.vtt"; AVDictionary *options = NULL; - int basename_size = 0; - int vtt_basename_size = 0, m3u8_name_size = 0; VariantStream *vs = NULL; - int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1; - - ret = update_variant_stream_info(s); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n", - ret); - goto fail; - } - - //TODO: Updates needed to encryption functionality with periodic re-key when more than one variant streams are present - if (hls->nb_varstreams > 1 && hls->flags & HLS_PERIODIC_REKEY) { - ret = AVERROR(EINVAL); - av_log(s, AV_LOG_ERROR, "Periodic re-key not supported when more than one variant streams are present\n"); - goto fail; - } - - if (hls->master_pl_name) { - ret = update_master_pl_info(s); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n", - ret); - goto fail; - } - } - - if (hls->segment_type == SEGMENT_TYPE_FMP4) { - pattern = "%d.m4s"; - } - if ((hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) || - (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME)) { - time_t t = time(NULL); // we will need it in either case - if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) { - hls->start_sequence = (int64_t)t; - } else if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME) { - char b[15]; - struct tm *p, tmbuf; - if (!(p = localtime_r(&t, &tmbuf))) - return AVERROR(ENOMEM); - if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p)) - return AVERROR(ENOMEM); - hls->start_sequence = strtoll(b, NULL, 10); - } - av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence); - } for (i = 0; i < hls->nb_varstreams; i++) { vs = &hls->var_streams[i]; - vs->sequence = hls->start_sequence; - hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE; - vs->start_pts = AV_NOPTS_VALUE; - vs->end_pts = AV_NOPTS_VALUE; - vs->current_segment_final_filename_fmt[0] = '\0'; - - if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) { - // Independent segments cannot be guaranteed when splitting by time - hls->flags &= ~HLS_INDEPENDENT_SEGMENTS; - av_log(s, AV_LOG_WARNING, - "'split_by_time' and 'independent_segments' cannot be enabled together. " - "Disabling 'independent_segments' flag\n"); - } - - if (hls->flags & HLS_PROGRAM_DATE_TIME) { - time_t now0; - time(&now0); - vs->initial_prog_date_time = now0; - } - - if (hls->format_options_str) { - ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n", hls->format_options_str); - goto fail; - } - } - - for (j = 0; j < vs->nb_streams; j++) { - vs->has_video += - vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO; - vs->has_subtitle += - vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE; - } - - if (vs->has_video > 1) - av_log(s, AV_LOG_WARNING, - "More than a single video stream present, " - "expect issues decoding it.\n"); - - if (hls->segment_type == SEGMENT_TYPE_FMP4) { - vs->oformat = av_guess_format("mp4", NULL, NULL); - } else { - vs->oformat = av_guess_format("mpegts", NULL, NULL); - } - - if (!vs->oformat) { - ret = AVERROR_MUXER_NOT_FOUND; - goto fail; - } - - if(vs->has_subtitle) { - vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL); - if (!vs->oformat) { - ret = AVERROR_MUXER_NOT_FOUND; - goto fail; - } - } - - if (hls->segment_filename) { - basename_size = strlen(hls->segment_filename) + 1; - if (hls->nb_varstreams > 1) { - basename_size += strlen(POSTFIX_PATTERN); - } - vs->basename = av_malloc(basename_size); - if (!vs->basename) { - ret = AVERROR(ENOMEM); - goto fail; - } - - av_strlcpy(vs->basename, hls->segment_filename, basename_size); - } else { - if (hls->flags & HLS_SINGLE_FILE) { - if (hls->segment_type == SEGMENT_TYPE_FMP4) { - pattern = ".m4s"; - } else { - pattern = ".ts"; - } - } - - if (hls->use_localtime) { - basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1; - } else { - basename_size = strlen(s->filename) + strlen(pattern) + 1; - } - - if (hls->nb_varstreams > 1) { - basename_size += strlen(POSTFIX_PATTERN); - } - - vs->basename = av_malloc(basename_size); - if (!vs->basename) { - ret = AVERROR(ENOMEM); - goto fail; - } - - av_strlcpy(vs->basename, s->filename, basename_size); - - p = strrchr(vs->basename, '.'); - if (p) - *p = '\0'; - if (hls->use_localtime) { - av_strlcat(vs->basename, pattern_localtime_fmt, basename_size); - } else { - av_strlcat(vs->basename, pattern, basename_size); - } - } - - m3u8_name_size = strlen(s->filename) + 1; - if (hls->nb_varstreams > 1) { - m3u8_name_size += strlen(POSTFIX_PATTERN); - } - - vs->m3u8_name = av_malloc(m3u8_name_size); - if (!vs->m3u8_name ) { - ret = AVERROR(ENOMEM); - goto fail; - } - - av_strlcpy(vs->m3u8_name, s->filename, m3u8_name_size); - - if (hls->nb_varstreams > 1) { - ret = format_name(vs->basename, basename_size, i); - if (ret < 0) - goto fail; - ret = format_name(vs->m3u8_name, m3u8_name_size, i); - if (ret < 0) - goto fail; - } - - if (hls->segment_type == SEGMENT_TYPE_FMP4) { - if (hls->nb_varstreams > 1) - fmp4_init_filename_len += strlen(POSTFIX_PATTERN); - vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len); - if (!vs->fmp4_init_filename ) { - ret = AVERROR(ENOMEM); - goto fail; - } - av_strlcpy(vs->fmp4_init_filename, hls->fmp4_init_filename, - fmp4_init_filename_len); - if (hls->nb_varstreams > 1) { - ret = format_name(vs->fmp4_init_filename, fmp4_init_filename_len, i); - if (ret < 0) - goto fail; - } - - if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) { - fmp4_init_filename_len = strlen(vs->fmp4_init_filename) + 1; - vs->base_output_dirname = av_malloc(fmp4_init_filename_len); - if (!vs->base_output_dirname) { - ret = AVERROR(ENOMEM); - goto fail; - } - av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, - fmp4_init_filename_len); - } else { - fmp4_init_filename_len = strlen(vs->m3u8_name) + - strlen(vs->fmp4_init_filename) + 1; - - vs->base_output_dirname = av_malloc(fmp4_init_filename_len); - if (!vs->base_output_dirname) { - ret = AVERROR(ENOMEM); - goto fail; - } - - av_strlcpy(vs->base_output_dirname, vs->m3u8_name, - fmp4_init_filename_len); - p = strrchr(vs->base_output_dirname, '/'); - if (p) { - *(p + 1) = '\0'; - av_strlcat(vs->base_output_dirname, vs->fmp4_init_filename, - fmp4_init_filename_len); - } else { - av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, - fmp4_init_filename_len); - } - } - } - - if (!hls->use_localtime) { - ret = sls_flag_check_duration_size_index(hls); - if (ret < 0) { - goto fail; - } - } else { - ret = sls_flag_check_duration_size(hls, vs); - if (ret < 0) { - goto fail; - } - } - if(vs->has_subtitle) { - - if (hls->flags & HLS_SINGLE_FILE) - vtt_pattern = ".vtt"; - vtt_basename_size = strlen(s->filename) + strlen(vtt_pattern) + 1; - if (hls->nb_varstreams > 1) { - vtt_basename_size += strlen(POSTFIX_PATTERN); - } - - vs->vtt_basename = av_malloc(vtt_basename_size); - if (!vs->vtt_basename) { - ret = AVERROR(ENOMEM); - goto fail; - } - vs->vtt_m3u8_name = av_malloc(vtt_basename_size); - if (!vs->vtt_m3u8_name ) { - ret = AVERROR(ENOMEM); - goto fail; - } - av_strlcpy(vs->vtt_basename, s->filename, vtt_basename_size); - p = strrchr(vs->vtt_basename, '.'); - if (p) - *p = '\0'; - - if( hls->subtitle_filename ) { - strcpy(vs->vtt_m3u8_name, hls->subtitle_filename); - } else { - strcpy(vs->vtt_m3u8_name, vs->vtt_basename); - av_strlcat(vs->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size); - } - av_strlcat(vs->vtt_basename, vtt_pattern, vtt_basename_size); - - if (hls->nb_varstreams > 1) { - ret= format_name(vs->vtt_basename, vtt_basename_size, i); - if (ret < 0) - goto fail; - ret = format_name(vs->vtt_m3u8_name, vtt_basename_size, i); - if (ret < 0) - goto fail; - } - } - - if (hls->baseurl) { - vs->baseurl = av_strdup(hls->baseurl); - if (!vs->baseurl) { - ret = AVERROR(ENOMEM); - goto fail; - } - } - - if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) { - vs->fmp4_init_filename = av_strdup(vs->basename); - if (!vs->fmp4_init_filename) { - ret = AVERROR(ENOMEM); - goto fail; - } - } - - if ((ret = hls_mux_init(s, vs)) < 0) - goto fail; - - if (hls->flags & HLS_APPEND_LIST) { - parse_playlist(s, vs->m3u8_name, vs); - vs->discontinuity = 1; - if (hls->init_time > 0) { - av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time," - " hls_init_time value will have no effect\n"); - hls->init_time = 0; - hls->recording_time = hls->time * AV_TIME_BASE; - } - } - - if (hls->segment_type != SEGMENT_TYPE_FMP4 || hls->flags & HLS_SINGLE_FILE) { - if ((ret = hls_start(s, vs)) < 0) - goto fail; - } - av_dict_copy(&options, hls->format_options, 0); ret = avformat_write_header(vs->avf, &options); if (av_dict_count(options)) { @@ -2000,25 +1683,6 @@ static int hls_write_header(AVFormatContext *s) } fail: - if (ret < 0) { - av_freep(&hls->key_basename); - for (i = 0; i < hls->nb_varstreams && hls->var_streams; i++) { - vs = &hls->var_streams[i]; - av_freep(&vs->basename); - av_freep(&vs->vtt_basename); - av_freep(&vs->fmp4_init_filename); - av_freep(&vs->m3u8_name); - av_freep(&vs->vtt_m3u8_name); - av_freep(&vs->streams); - av_freep(&vs->baseurl); - if (vs->avf) - avformat_free_context(vs->avf); - if (vs->vtt_avf) - avformat_free_context(vs->vtt_avf); - } - av_freep(&hls->var_streams); - av_freep(&hls->master_m3u8_url); - } return ret; } @@ -2260,6 +1924,350 @@ static int hls_write_trailer(struct AVFormatContext *s) return 0; } + +static int hls_init(AVFormatContext *s) +{ + int ret = 0; + int i = 0; + int j = 0; + HLSContext *hls = s->priv_data; + const char *pattern = "%d.ts"; + VariantStream *vs = NULL; + int basename_size = 0; + const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s); + const char *vtt_pattern = "%d.vtt"; + char *p = NULL; + int vtt_basename_size = 0, m3u8_name_size = 0; + int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1; + + ret = update_variant_stream_info(s); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n", + ret); + goto fail; + } + //TODO: Updates needed to encryption functionality with periodic re-key when more than one variant streams are present + if (hls->nb_varstreams > 1 && hls->flags & HLS_PERIODIC_REKEY) { + ret = AVERROR(EINVAL); + av_log(s, AV_LOG_ERROR, "Periodic re-key not supported when more than one variant streams are present\n"); + goto fail; + } + + if (hls->master_pl_name) { + ret = update_master_pl_info(s); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n", + ret); + goto fail; + } + } + + if (hls->segment_type == SEGMENT_TYPE_FMP4) { + pattern = "%d.m4s"; + } + if ((hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) || + (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME)) { + time_t t = time(NULL); // we will need it in either case + if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) { + hls->start_sequence = (int64_t)t; + } else if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME) { + char b[15]; + struct tm *p, tmbuf; + if (!(p = localtime_r(&t, &tmbuf))) + return AVERROR(ENOMEM); + if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p)) + return AVERROR(ENOMEM); + hls->start_sequence = strtoll(b, NULL, 10); + } + av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence); + } + + hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE; + for (i = 0; i < hls->nb_varstreams; i++) { + vs = &hls->var_streams[i]; + vs->sequence = hls->start_sequence; + vs->start_pts = AV_NOPTS_VALUE; + vs->end_pts = AV_NOPTS_VALUE; + vs->current_segment_final_filename_fmt[0] = '\0'; + + if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) { + // Independent segments cannot be guaranteed when splitting by time + hls->flags &= ~HLS_INDEPENDENT_SEGMENTS; + av_log(s, AV_LOG_WARNING, + "'split_by_time' and 'independent_segments' cannot be enabled together. " + "Disabling 'independent_segments' flag\n"); + } + + if (hls->flags & HLS_PROGRAM_DATE_TIME) { + time_t now0; + time(&now0); + vs->initial_prog_date_time = now0; + } + if (hls->format_options_str) { + ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n", hls->format_options_str); + goto fail; + } + } + + for (j = 0; j < vs->nb_streams; j++) { + vs->has_video += vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO; + vs->has_subtitle += vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE; + } + + if (vs->has_video > 1) + av_log(s, AV_LOG_WARNING, "More than a single video stream present, expect issues decoding it.\n"); + if (hls->segment_type == SEGMENT_TYPE_FMP4) { + vs->oformat = av_guess_format("mp4", NULL, NULL); + } else { + vs->oformat = av_guess_format("mpegts", NULL, NULL); + } + + if (!vs->oformat) { + ret = AVERROR_MUXER_NOT_FOUND; + goto fail; + } + + if (vs->has_subtitle) { + vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL); + if (!vs->oformat) { + ret = AVERROR_MUXER_NOT_FOUND; + goto fail; + } + } + if (hls->segment_filename) { + basename_size = strlen(hls->segment_filename) + 1; + if (hls->nb_varstreams > 1) { + basename_size += strlen(POSTFIX_PATTERN); + } + vs->basename = av_malloc(basename_size); + if (!vs->basename) { + ret = AVERROR(ENOMEM); + goto fail; + } + + av_strlcpy(vs->basename, hls->segment_filename, basename_size); + } else { + if (hls->flags & HLS_SINGLE_FILE) { + if (hls->segment_type == SEGMENT_TYPE_FMP4) { + pattern = ".m4s"; + } else { + pattern = ".ts"; + } + } + + if (hls->use_localtime) { + basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1; + } else { + basename_size = strlen(s->filename) + strlen(pattern) + 1; + } + + if (hls->nb_varstreams > 1) { + basename_size += strlen(POSTFIX_PATTERN); + } + + vs->basename = av_malloc(basename_size); + if (!vs->basename) { + ret = AVERROR(ENOMEM); + goto fail; + } + + av_strlcpy(vs->basename, s->filename, basename_size); + + p = strrchr(vs->basename, '.'); + if (p) + *p = '\0'; + if (hls->use_localtime) { + av_strlcat(vs->basename, pattern_localtime_fmt, basename_size); + } else { + av_strlcat(vs->basename, pattern, basename_size); + } + } + + m3u8_name_size = strlen(s->filename) + 1; + if (hls->nb_varstreams > 1) { + m3u8_name_size += strlen(POSTFIX_PATTERN); + } + + vs->m3u8_name = av_malloc(m3u8_name_size); + if (!vs->m3u8_name ) { + ret = AVERROR(ENOMEM); + goto fail; + } + + av_strlcpy(vs->m3u8_name, s->filename, m3u8_name_size); + + if (hls->nb_varstreams > 1) { + ret = format_name(vs->basename, basename_size, i); + if (ret < 0) + goto fail; + ret = format_name(vs->m3u8_name, m3u8_name_size, i); + if (ret < 0) + goto fail; + } + + if (hls->segment_type == SEGMENT_TYPE_FMP4) { + if (hls->nb_varstreams > 1) + fmp4_init_filename_len += strlen(POSTFIX_PATTERN); + vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len); + if (!vs->fmp4_init_filename ) { + ret = AVERROR(ENOMEM); + goto fail; + } + av_strlcpy(vs->fmp4_init_filename, hls->fmp4_init_filename, + fmp4_init_filename_len); + if (hls->nb_varstreams > 1) { + ret = format_name(vs->fmp4_init_filename, fmp4_init_filename_len, i); + if (ret < 0) + goto fail; + } + + if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) { + fmp4_init_filename_len = strlen(vs->fmp4_init_filename) + 1; + vs->base_output_dirname = av_malloc(fmp4_init_filename_len); + if (!vs->base_output_dirname) { + ret = AVERROR(ENOMEM); + goto fail; + } + av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, + fmp4_init_filename_len); + } else { + fmp4_init_filename_len = strlen(vs->m3u8_name) + + strlen(vs->fmp4_init_filename) + 1; + + vs->base_output_dirname = av_malloc(fmp4_init_filename_len); + if (!vs->base_output_dirname) { + ret = AVERROR(ENOMEM); + goto fail; + } + + av_strlcpy(vs->base_output_dirname, vs->m3u8_name, + fmp4_init_filename_len); + p = strrchr(vs->base_output_dirname, '/'); + if (p) { + *(p + 1) = '\0'; + av_strlcat(vs->base_output_dirname, vs->fmp4_init_filename, + fmp4_init_filename_len); + } else { + av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, + fmp4_init_filename_len); + } + } + } + + if (!hls->use_localtime) { + ret = sls_flag_check_duration_size_index(hls); + if (ret < 0) { + goto fail; + } + } else { + ret = sls_flag_check_duration_size(hls, vs); + if (ret < 0) { + goto fail; + } + } + if (vs->has_subtitle) { + + if (hls->flags & HLS_SINGLE_FILE) + vtt_pattern = ".vtt"; + vtt_basename_size = strlen(s->filename) + strlen(vtt_pattern) + 1; + if (hls->nb_varstreams > 1) { + vtt_basename_size += strlen(POSTFIX_PATTERN); + } + + vs->vtt_basename = av_malloc(vtt_basename_size); + if (!vs->vtt_basename) { + ret = AVERROR(ENOMEM); + goto fail; + } + vs->vtt_m3u8_name = av_malloc(vtt_basename_size); + if (!vs->vtt_m3u8_name ) { + ret = AVERROR(ENOMEM); + goto fail; + } + av_strlcpy(vs->vtt_basename, s->filename, vtt_basename_size); + p = strrchr(vs->vtt_basename, '.'); + if (p) + *p = '\0'; + + if ( hls->subtitle_filename ) { + strcpy(vs->vtt_m3u8_name, hls->subtitle_filename); + } else { + strcpy(vs->vtt_m3u8_name, vs->vtt_basename); + av_strlcat(vs->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size); + } + av_strlcat(vs->vtt_basename, vtt_pattern, vtt_basename_size); + + if (hls->nb_varstreams > 1) { + ret= format_name(vs->vtt_basename, vtt_basename_size, i); + if (ret < 0) + goto fail; + ret = format_name(vs->vtt_m3u8_name, vtt_basename_size, i); + if (ret < 0) + goto fail; + } + } + + if (hls->baseurl) { + vs->baseurl = av_strdup(hls->baseurl); + if (!vs->baseurl) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + + if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) { + vs->fmp4_init_filename = av_strdup(vs->basename); + if (!vs->fmp4_init_filename) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + if ((ret = hls_mux_init(s, vs)) < 0) + goto fail; + + if (hls->flags & HLS_APPEND_LIST) { + parse_playlist(s, vs->m3u8_name, vs); + vs->discontinuity = 1; + if (hls->init_time > 0) { + av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time," + " hls_init_time value will have no effect\n"); + hls->init_time = 0; + hls->recording_time = hls->time * AV_TIME_BASE; + } + } + + if (hls->segment_type != SEGMENT_TYPE_FMP4 || hls->flags & HLS_SINGLE_FILE) { + if ((ret = hls_start(s, vs)) < 0) + goto fail; + } + } + +fail: + if (ret < 0) { + av_freep(&hls->key_basename); + for (i = 0; i < hls->nb_varstreams && hls->var_streams; i++) { + vs = &hls->var_streams[i]; + av_freep(&vs->basename); + av_freep(&vs->vtt_basename); + av_freep(&vs->fmp4_init_filename); + av_freep(&vs->m3u8_name); + av_freep(&vs->vtt_m3u8_name); + av_freep(&vs->streams); + av_freep(&vs->baseurl); + if (vs->avf) + avformat_free_context(vs->avf); + if (vs->vtt_avf) + avformat_free_context(vs->vtt_avf); + } + av_freep(&hls->var_streams); + av_freep(&hls->master_m3u8_url); + } + + return ret; +} + #define OFFSET(x) offsetof(HLSContext, x) #define E AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { @@ -2336,6 +2344,7 @@ AVOutputFormat ff_hls_muxer = { .video_codec = AV_CODEC_ID_H264, .subtitle_codec = AV_CODEC_ID_WEBVTT, .flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, + .init = hls_init, .write_header = hls_write_header, .write_packet = hls_write_packet, .write_trailer = hls_write_trailer, From c7a5e80f569d312c9d2f0dc534e07630eecd5a34 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 11 Dec 2017 00:42:26 -0300 Subject: [PATCH 1318/2557] avcodec/libvpx: remove disabled code Signed-off-by: James Almer --- libavcodec/libvpx.c | 57 --------------------------------------------- 1 file changed, 57 deletions(-) diff --git a/libavcodec/libvpx.c b/libavcodec/libvpx.c index 36f915a8e5710..cc055a0032626 100644 --- a/libavcodec/libvpx.c +++ b/libavcodec/libvpx.c @@ -78,60 +78,3 @@ av_cold void ff_vp9_init_static(AVCodec *codec) } #endif } -#if 0 -enum AVPixelFormat ff_vpx_imgfmt_to_pixfmt(vpx_img_fmt_t img) -{ - switch (img) { - case VPX_IMG_FMT_RGB24: return AV_PIX_FMT_RGB24; - case VPX_IMG_FMT_RGB565: return AV_PIX_FMT_RGB565BE; - case VPX_IMG_FMT_RGB555: return AV_PIX_FMT_RGB555BE; - case VPX_IMG_FMT_UYVY: return AV_PIX_FMT_UYVY422; - case VPX_IMG_FMT_YUY2: return AV_PIX_FMT_YUYV422; - case VPX_IMG_FMT_YVYU: return AV_PIX_FMT_YVYU422; - case VPX_IMG_FMT_BGR24: return AV_PIX_FMT_BGR24; - case VPX_IMG_FMT_ARGB: return AV_PIX_FMT_ARGB; - case VPX_IMG_FMT_ARGB_LE: return AV_PIX_FMT_BGRA; - case VPX_IMG_FMT_RGB565_LE: return AV_PIX_FMT_RGB565LE; - case VPX_IMG_FMT_RGB555_LE: return AV_PIX_FMT_RGB555LE; - case VPX_IMG_FMT_I420: return AV_PIX_FMT_YUV420P; - case VPX_IMG_FMT_I422: return AV_PIX_FMT_YUV422P; - case VPX_IMG_FMT_I444: return AV_PIX_FMT_YUV444P; - case VPX_IMG_FMT_444A: return AV_PIX_FMT_YUVA444P; -#if VPX_IMAGE_ABI_VERSION >= 3 - case VPX_IMG_FMT_I440: return AV_PIX_FMT_YUV440P; - case VPX_IMG_FMT_I42016: return AV_PIX_FMT_YUV420P16BE; - case VPX_IMG_FMT_I42216: return AV_PIX_FMT_YUV422P16BE; - case VPX_IMG_FMT_I44416: return AV_PIX_FMT_YUV444P16BE; -#endif - default: return AV_PIX_FMT_NONE; - } -} - -vpx_img_fmt_t ff_vpx_pixfmt_to_imgfmt(enum AVPixelFormat pix) -{ - switch (pix) { - case AV_PIX_FMT_RGB24: return VPX_IMG_FMT_RGB24; - case AV_PIX_FMT_RGB565BE: return VPX_IMG_FMT_RGB565; - case AV_PIX_FMT_RGB555BE: return VPX_IMG_FMT_RGB555; - case AV_PIX_FMT_UYVY422: return VPX_IMG_FMT_UYVY; - case AV_PIX_FMT_YUYV422: return VPX_IMG_FMT_YUY2; - case AV_PIX_FMT_YVYU422: return VPX_IMG_FMT_YVYU; - case AV_PIX_FMT_BGR24: return VPX_IMG_FMT_BGR24; - case AV_PIX_FMT_ARGB: return VPX_IMG_FMT_ARGB; - case AV_PIX_FMT_BGRA: return VPX_IMG_FMT_ARGB_LE; - case AV_PIX_FMT_RGB565LE: return VPX_IMG_FMT_RGB565_LE; - case AV_PIX_FMT_RGB555LE: return VPX_IMG_FMT_RGB555_LE; - case AV_PIX_FMT_YUV420P: return VPX_IMG_FMT_I420; - case AV_PIX_FMT_YUV422P: return VPX_IMG_FMT_I422; - case AV_PIX_FMT_YUV444P: return VPX_IMG_FMT_I444; - case AV_PIX_FMT_YUVA444P: return VPX_IMG_FMT_444A; -#if VPX_IMAGE_ABI_VERSION >= 3 - case AV_PIX_FMT_YUV440P: return VPX_IMG_FMT_I440; - case AV_PIX_FMT_YUV420P16BE: return VPX_IMG_FMT_I42016; - case AV_PIX_FMT_YUV422P16BE: return VPX_IMG_FMT_I42216; - case AV_PIX_FMT_YUV444P16BE: return VPX_IMG_FMT_I44416; -#endif - default: return VPX_IMG_FMT_NONE; - } -} -#endif From fd542b6f2026f1aa163882ee0283958598a97c31 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Mon, 11 Dec 2017 20:59:56 +0100 Subject: [PATCH 1319/2557] Revert "libavcodec/utils.c: simplify avcodec locking with atomics" This reverts commit 590136e78da3d091ea99ab5432543d47a559a461. Atomics are not required for this variable, because it is protected through the lock manager, and the use of atomics here is not compatible with the c11 emulation wrappersi. Fixes FATE on MSVC, among other setups which use the compat wrappers. --- libavcodec/internal.h | 1 + libavcodec/utils.c | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 6deaf1d204c84..30cb9a0de1df4 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -241,6 +241,7 @@ int ff_init_buffer_info(AVCodecContext *s, AVFrame *frame); void ff_color_frame(AVFrame *frame, const int color[4]); +extern volatile int ff_avcodec_locked; int ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec); int ff_unlock_avcodec(const AVCodec *codec); diff --git a/libavcodec/utils.c b/libavcodec/utils.c index baf09119fe70f..873f39f9bda4f 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -115,7 +115,7 @@ static int (*lockmgr_cb)(void **mutex, enum AVLockOp op) = NULL; #endif -static atomic_bool ff_avcodec_locked; +volatile int ff_avcodec_locked; static atomic_int entangled_thread_counter = ATOMIC_VAR_INIT(0); static void *codec_mutex; static void *avformat_mutex; @@ -1943,7 +1943,6 @@ int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) int ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec) { - _Bool exp = 0; if (codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE || !codec->init) return 0; @@ -1959,21 +1958,22 @@ int ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec) atomic_load(&entangled_thread_counter)); if (!lockmgr_cb) av_log(log_ctx, AV_LOG_ERROR, "No lock manager is set, please see av_lockmgr_register()\n"); - atomic_store(&ff_avcodec_locked, 1); + ff_avcodec_locked = 1; ff_unlock_avcodec(codec); return AVERROR(EINVAL); } - av_assert0(atomic_compare_exchange_strong(&ff_avcodec_locked, &exp, 1)); + av_assert0(!ff_avcodec_locked); + ff_avcodec_locked = 1; return 0; } int ff_unlock_avcodec(const AVCodec *codec) { - _Bool exp = 1; if (codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE || !codec->init) return 0; - av_assert0(atomic_compare_exchange_strong(&ff_avcodec_locked, &exp, 0)); + av_assert0(ff_avcodec_locked); + ff_avcodec_locked = 0; atomic_fetch_add(&entangled_thread_counter, -1); if (lockmgr_cb) { if ((*lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE)) From cbd524b26cd825af8bf4b4565a29f4ed2d3f4728 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 11 Dec 2017 22:39:26 +0100 Subject: [PATCH 1320/2557] avfilter/avfiltergraph: remove ugly dead code Remnant of old merge. Signed-off-by: Paul B Mahol --- libavfilter/avfiltergraph.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index a959a9ef3fdba..4cc6892404317 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -518,7 +518,6 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) AVFilterContext *convert; const AVFilter *filter; AVFilterLink *inlink, *outlink; - char scale_args[256]; char inst_name[30]; if (graph->disable_auto_convert) { @@ -555,10 +554,6 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) snprintf(inst_name, sizeof(inst_name), "auto_resampler_%d", resampler_count++); - scale_args[0] = '\0'; - if (graph->aresample_swr_opts) - snprintf(scale_args, sizeof(scale_args), "%s", - graph->aresample_swr_opts); if ((ret = avfilter_graph_create_filter(&convert, filter, inst_name, graph->aresample_swr_opts, NULL, graph)) < 0) From 555119bd762540a9f17a61bdd92329c8b8feb1e0 Mon Sep 17 00:00:00 2001 From: Lou Logan Date: Mon, 11 Dec 2017 12:46:02 -0900 Subject: [PATCH 1321/2557] doc/filters: re-arrange options for testsrc family Additionally: * Mention that allrgb and allyuv do not support the "size" option. * Separate examples into subsection. Fixes ticket #6906. Signed-off-by: Lou Logan --- doc/filters.texi | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 33464382314fe..f304bbf9491aa 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -17099,28 +17099,24 @@ The sources accept the following parameters: @table @option -@item alpha -Specify the alpha (opacity) of the background, only available in the -@code{testsrc2} source. The value must be between 0 (fully transparent) and -255 (fully opaque, the default). - -@item color, c -Specify the color of the source, only available in the @code{color} -source. For the syntax of this option, check the "Color" section in the -ffmpeg-utils manual. - @item level Specify the level of the Hald CLUT, only available in the @code{haldclutsrc} source. A level of @code{N} generates a picture of @code{N*N*N} by @code{N*N*N} pixels to be used as identity matrix for 3D lookup tables. Each component is coded on a @code{1/(N*N)} scale. +@item color, c +Specify the color of the source, only available in the @code{color} +source. For the syntax of this option, check the "Color" section in the +ffmpeg-utils manual. + @item size, s Specify the size of the sourced video. For the syntax of this option, check the @ref{video size syntax,,"Video size" section in the ffmpeg-utils manual,ffmpeg-utils}. The default value is @code{320x240}. -This option is not available with the @code{haldclutsrc} filter. +This option is not available with the @code{allrgb}, @code{allyuv}, and +@code{haldclutsrc} filters. @item rate, r Specify the frame rate of the sourced video, as the number of frames @@ -17129,9 +17125,6 @@ generated per second. It has to be a string in the format number or a valid video frame rate abbreviation. The default value is "25". -@item sar -Set the sample aspect ratio of the sourced video. - @item duration, d Set the duration of the sourced video. See @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils} @@ -17140,6 +17133,14 @@ for the accepted syntax. If not specified, or the expressed duration is negative, the video is supposed to be generated forever. +@item sar +Set the sample aspect ratio of the sourced video. + +@item alpha +Specify the alpha (opacity) of the background, only available in the +@code{testsrc2} source. The value must be between 0 (fully transparent) and +255 (fully opaque, the default). + @item decimals, n Set the number of decimals to show in the timestamp, only available in the @code{testsrc} source. @@ -17149,27 +17150,32 @@ timestamp value multiplied by the power of 10 of the specified value. Default value is 0. @end table -For example the following: +@subsection Examples + +@itemize +@item +Generate a video with a duration of 5.3 seconds, with size +176x144 and a frame rate of 10 frames per second: @example testsrc=duration=5.3:size=qcif:rate=10 @end example -will generate a video with a duration of 5.3 seconds, with size -176x144 and a frame rate of 10 frames per second. - +@item The following graph description will generate a red source with an opacity of 0.2, with size "qcif" and a frame rate of 10 -frames per second. +frames per second: @example color=c=red@@0.2:s=qcif:r=10 @end example +@item If the input content is to be ignored, @code{nullsrc} can be used. The following command generates noise in the luminance plane by employing the @code{geq} filter: @example nullsrc=s=256x256, geq=random(1)*255:128:128 @end example +@end itemize @subsection Commands From 0e5260226a72fc9da2967ded99624f5dfb1ed135 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 12 Dec 2017 11:50:23 +0800 Subject: [PATCH 1322/2557] avformat/hlsenc: reindent after previous commits --- libavformat/hlsenc.c | 60 ++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index dd09739651618..fdf614bdd1937 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1646,40 +1646,40 @@ static int hls_write_header(AVFormatContext *s) for (i = 0; i < hls->nb_varstreams; i++) { vs = &hls->var_streams[i]; - av_dict_copy(&options, hls->format_options, 0); - ret = avformat_write_header(vs->avf, &options); - if (av_dict_count(options)) { - av_log(s, AV_LOG_ERROR, "Some of provided format options in '%s' are not recognized\n", hls->format_options_str); - ret = AVERROR(EINVAL); + av_dict_copy(&options, hls->format_options, 0); + ret = avformat_write_header(vs->avf, &options); + if (av_dict_count(options)) { + av_log(s, AV_LOG_ERROR, "Some of provided format options in '%s' are not recognized\n", hls->format_options_str); + ret = AVERROR(EINVAL); + av_dict_free(&options); + goto fail; + } av_dict_free(&options); - goto fail; - } - av_dict_free(&options); - //av_assert0(s->nb_streams == hls->avf->nb_streams); - for (j = 0; j < vs->nb_streams; j++) { - AVStream *inner_st; - AVStream *outer_st = vs->streams[j]; - - if (hls->max_seg_size > 0) { - if ((outer_st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && - (outer_st->codecpar->bit_rate > hls->max_seg_size)) { - av_log(s, AV_LOG_WARNING, "Your video bitrate is bigger than hls_segment_size, " - "(%"PRId64 " > %"PRId64 "), the result maybe not be what you want.", - outer_st->codecpar->bit_rate, hls->max_seg_size); + //av_assert0(s->nb_streams == hls->avf->nb_streams); + for (j = 0; j < vs->nb_streams; j++) { + AVStream *inner_st; + AVStream *outer_st = vs->streams[j]; + + if (hls->max_seg_size > 0) { + if ((outer_st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && + (outer_st->codecpar->bit_rate > hls->max_seg_size)) { + av_log(s, AV_LOG_WARNING, "Your video bitrate is bigger than hls_segment_size, " + "(%"PRId64 " > %"PRId64 "), the result maybe not be what you want.", + outer_st->codecpar->bit_rate, hls->max_seg_size); + } } - } - if (outer_st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) - inner_st = vs->avf->streams[j]; - else if (vs->vtt_avf) - inner_st = vs->vtt_avf->streams[0]; - else { - /* We have a subtitle stream, when the user does not want one */ - inner_st = NULL; - continue; + if (outer_st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) + inner_st = vs->avf->streams[j]; + else if (vs->vtt_avf) + inner_st = vs->vtt_avf->streams[0]; + else { + /* We have a subtitle stream, when the user does not want one */ + inner_st = NULL; + continue; + } + avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den); } - avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den); - } } fail: From 18a0f420269ff4c730422361c5c4d8eea096e900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 11 Dec 2017 22:25:16 +0200 Subject: [PATCH 1323/2557] checkasm: Use LOCAL_ALIGNED for aligned variables on the stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes fate-checkasm-hevc_mc on ARMCC 5.0 after adding NEON HEVC MC assembly. Signed-off-by: Martin Storsjö --- tests/checkasm/hevc_mc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/checkasm/hevc_mc.c b/tests/checkasm/hevc_mc.c index 70f35ce78a14a..c3fbfebe72d48 100644 --- a/tests/checkasm/hevc_mc.c +++ b/tests/checkasm/hevc_mc.c @@ -291,13 +291,13 @@ static void check_qpel(HEVCDSPContext *h, int16_t *dst0, int16_t *dst1, void checkasm_check_hevc_mc(void) { - DECLARE_ALIGNED(16, uint8_t, buf8_0)[BUF_SIZE]; - DECLARE_ALIGNED(16, uint8_t, buf8_1)[BUF_SIZE]; + LOCAL_ALIGNED(16, uint8_t, buf8_0, [BUF_SIZE]); + LOCAL_ALIGNED(16, uint8_t, buf8_1, [BUF_SIZE]); - DECLARE_ALIGNED(16, int16_t, buf16_0)[BUF_SIZE]; - DECLARE_ALIGNED(16, int16_t, buf16_1)[BUF_SIZE]; + LOCAL_ALIGNED(16, int16_t, buf16_0, [BUF_SIZE]); + LOCAL_ALIGNED(16, int16_t, buf16_1, [BUF_SIZE]); - DECLARE_ALIGNED(16, int16_t, mcbuffer)[BUF_SIZE]; + LOCAL_ALIGNED(16, int16_t, mcbuffer, [BUF_SIZE]); HEVCDSPContext h; int bit_depth; From 6ff29343b01923e9b125fe7404ac8701cdfb1fe5 Mon Sep 17 00:00:00 2001 From: "Li, Zhong" Date: Fri, 1 Dec 2017 16:48:45 +0800 Subject: [PATCH 1324/2557] lavc/qsvenc: set HRD buffer size Hypothetical Reference Decoding (HRD) model assumes that data flows into a buffer of the fixed size BufferSizeInKB with a constant bitrate. Smaller BufferSizeInKB means smaller frame size variations, but more difficult to maintain HRD. Signed-off-by: Zhong Li Signed-off-by: Maxym Dmytrychenko --- libavcodec/qsvenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 9db9eb375cf3f..f6034c443dc28 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -503,6 +503,7 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) #if QSV_HAVE_VCM case MFX_RATECONTROL_VCM: #endif + q->param.mfx.BufferSizeInKB = avctx->rc_buffer_size / 8000; q->param.mfx.InitialDelayInKB = avctx->rc_initial_buffer_occupancy / 1000; q->param.mfx.TargetKbps = avctx->bit_rate / 1000; q->param.mfx.MaxKbps = avctx->rc_max_rate / 1000; From bddb2ce179c57db6e3c79fdc3363c165d90850b0 Mon Sep 17 00:00:00 2001 From: "Li, Zhong" Date: Thu, 7 Dec 2017 14:44:26 +0800 Subject: [PATCH 1325/2557] lavc/qsvenc: ICQ/VCM/QVBR are not avilable on Linux Signed-off-by: Zhong Li Signed-off-by: Maxym Dmytrychenko --- libavcodec/qsvenc.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 9b0b84b919374..7f11460d0893f 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -43,9 +43,16 @@ #define QSV_HAVE_LA QSV_VERSION_ATLEAST(1, 7) #define QSV_HAVE_LA_HRD QSV_VERSION_ATLEAST(1, 11) + +#if defined(_WIN32) #define QSV_HAVE_ICQ QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_VCM QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_QVBR QSV_VERSION_ATLEAST(1, 11) +#else +#define QSV_HAVE_ICQ 0 +#define QSV_HAVE_VCM 0 +#define QSV_HAVE_QVBR 0 +#endif #define QSV_COMMON_OPTS \ { "async_depth", "Maximum processing parallelism", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VE }, \ From 7c65a76b16bc3a44f1592acde2176f187a058797 Mon Sep 17 00:00:00 2001 From: "Li, Zhong" Date: Thu, 7 Dec 2017 14:44:27 +0800 Subject: [PATCH 1326/2557] lavc/qsvenc: add error messeage if ICQ unsupported. Signed-off-by: Zhong Li Signed-off-by: Maxym Dmytrychenko --- libavcodec/qsvenc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index f6034c443dc28..5eacf3ca883d9 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -295,6 +295,12 @@ static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) return AVERROR(EINVAL); } + if (!want_qscale && avctx->global_quality > 0 && !QSV_HAVE_ICQ){ + av_log(avctx, AV_LOG_ERROR, + "ICQ ratecontrol mode requested, but is not supported by this SDK version\n"); + return AVERROR(ENOSYS); + } + if (want_qscale) { rc_mode = MFX_RATECONTROL_CQP; rc_desc = "constant quantization parameter (CQP)"; From f2e9a0ecbef5027f9532c49ffcdfc11d199f6150 Mon Sep 17 00:00:00 2001 From: "Li, Zhong" Date: Thu, 7 Dec 2017 15:26:38 +0800 Subject: [PATCH 1327/2557] qsv/vp8dec: fixes memory leak issue Signed-off-by: Zhong Li Signed-off-by: Maxym Dmytrychenko --- libavcodec/qsvdec_other.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/qsvdec_other.c b/libavcodec/qsvdec_other.c index 3ea1859bf8afd..97a763579a043 100644 --- a/libavcodec/qsvdec_other.c +++ b/libavcodec/qsvdec_other.c @@ -60,6 +60,11 @@ static av_cold int qsv_decode_close(AVCodecContext *avctx) { QSVOtherContext *s = avctx->priv_data; +#if CONFIG_VP8_QSV_DECODER + if (avctx->codec_id == AV_CODEC_ID_VP8) + av_freep(&s->qsv.load_plugins); +#endif + ff_qsv_decode_close(&s->qsv); qsv_clear_buffers(s); From 508378556631dc18d32247b4a4e35703758e1ca9 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 12 Dec 2017 14:27:52 +0000 Subject: [PATCH 1328/2557] qsv: Support explicit lookahead downscaling --- libavcodec/qsvenc.c | 4 ++++ libavcodec/qsvenc.h | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 5eacf3ca883d9..24d9ec4d714be 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -604,6 +604,10 @@ FF_ENABLE_DEPRECATION_WARNINGS q->extco2.Trellis = q->trellis; #endif +#if QSV_HAVE_LA_DS + q->extco2.LookAheadDS = q->la_ds; +#endif + #if QSV_HAVE_BREF_TYPE #if FF_API_PRIVATE_OPT FF_DISABLE_DEPRECATION_WARNINGS diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 7f11460d0893f..088a61de548bb 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -42,6 +42,7 @@ #define QSV_HAVE_BREF_TYPE QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_LA QSV_VERSION_ATLEAST(1, 7) +#define QSV_HAVE_LA_DS QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_LA_HRD QSV_VERSION_ATLEAST(1, 11) #if defined(_WIN32) @@ -54,6 +55,12 @@ #define QSV_HAVE_QVBR 0 #endif +#if !QSV_HAVE_LA_DS +#define MFX_LOOKAHEAD_DS_OFF 0 +#define MFX_LOOKAHEAD_DS_2x 0 +#define MFX_LOOKAHEAD_DS_4x 0 +#endif + #define QSV_COMMON_OPTS \ { "async_depth", "Maximum processing parallelism", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VE }, \ { "avbr_accuracy", "Accuracy of the AVBR ratecontrol", OFFSET(qsv.avbr_accuracy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, \ @@ -64,6 +71,11 @@ { "slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_QUALITY }, INT_MIN, INT_MAX, VE, "preset" }, \ { "la_depth", "Number of frames to analyze before encoding.", OFFSET(qsv.la_depth), AV_OPT_TYPE_INT, { .i64 = 9 }, 9, 100, VE, "la_depth" }, \ { "unset", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 9 }, INT_MIN, INT_MAX, VE, "la_depth" }, \ +{ "la_ds", "Downscaling factor for the frames saved for the lookahead analysis", OFFSET(qsv.la_ds), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, MFX_LOOKAHEAD_DS_4x, VE, "la_ds" }, \ +{ "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, VE, "la_ds" }, \ +{ "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_OFF }, INT_MIN, INT_MAX, VE, "la_ds" }, \ +{ "2x", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_2x }, INT_MIN, INT_MAX, VE, "la_ds" }, \ +{ "4x", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_4x }, INT_MIN, INT_MAX, VE, "la_ds" }, \ { "vcm", "Use the video conferencing mode ratecontrol", OFFSET(qsv.vcm), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, \ { "rdo", "Enable rate distortion optimization", OFFSET(qsv.rdo), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "max_frame_size", "Maximum encoded frame size in bytes", OFFSET(qsv.max_frame_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, \ @@ -116,6 +128,7 @@ typedef struct QSVEncContext { int avbr_accuracy; int avbr_convergence; int la_depth; + int la_ds; int vcm; int rdo; int max_frame_size; From a0e4c41d086bbc32dfefef0b81ed0f59fe04d4ab Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 12 Dec 2017 19:31:50 +0100 Subject: [PATCH 1329/2557] avfilter/vf_pseudocolor: add support for more formats Signed-off-by: Paul B Mahol --- libavfilter/vf_pseudocolor.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_pseudocolor.c b/libavfilter/vf_pseudocolor.c index f8f5372752904..2e7a3a95f808f 100644 --- a/libavfilter/vf_pseudocolor.c +++ b/libavfilter/vf_pseudocolor.c @@ -94,7 +94,7 @@ static const AVOption pseudocolor_options[] = { }; static const enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY16, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_GBRP, @@ -114,7 +114,10 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, + AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; @@ -531,11 +534,17 @@ static int config_input(AVFilterLink *inlink) case AV_PIX_FMT_YUV444P14: case AV_PIX_FMT_YUV444P16: case AV_PIX_FMT_YUVA444P16: + case AV_PIX_FMT_GBRP9: case AV_PIX_FMT_GBRP10: - case AV_PIX_FMT_GBRAP10: + case AV_PIX_FMT_GBRP12: + case AV_PIX_FMT_GBRP14: case AV_PIX_FMT_GBRP16: + case AV_PIX_FMT_GBRAP10: + case AV_PIX_FMT_GBRAP12: case AV_PIX_FMT_GBRAP16: + case AV_PIX_FMT_GRAY9: case AV_PIX_FMT_GRAY10: + case AV_PIX_FMT_GRAY12: case AV_PIX_FMT_GRAY16: s->filter[0] = s->filter[1] = s->filter[2] = s->filter[3] = pseudocolor_filter_16; break; From 0e2fbd68e2796e7ed3cc7b327cd03908802045c1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 11 Dec 2017 01:02:30 -0300 Subject: [PATCH 1330/2557] avformat/mux: factorize AVFormatContext->avoid_negative_ts initialization Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/mux.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index effcc1152f78a..ea9f13fdf5a90 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -445,6 +445,14 @@ static int init_pts(AVFormatContext *s) } } + if (s->avoid_negative_ts < 0) { + av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO); + if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) { + s->avoid_negative_ts = 0; + } else + s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE; + } + return 0; } @@ -472,14 +480,6 @@ int avformat_init_output(AVFormatContext *s, AVDictionary **options) if ((ret = init_pts(s)) < 0) return ret; - if (s->avoid_negative_ts < 0) { - av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO); - if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) { - s->avoid_negative_ts = 0; - } else - s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE; - } - return AVSTREAM_INIT_IN_INIT_OUTPUT; } @@ -512,14 +512,6 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options) if (!s->internal->streams_initialized) { if ((ret = init_pts(s)) < 0) goto fail; - - if (s->avoid_negative_ts < 0) { - av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO); - if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) { - s->avoid_negative_ts = 0; - } else - s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE; - } } return streams_already_initialized; From 4280948702bc256e21c375790b889c735d233b0d Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 4 Dec 2017 12:50:34 +0800 Subject: [PATCH 1331/2557] avfilter/formats: fix wrong function name in error message Use perdefined micro __FUNCTION__ rather than hard coding function name to fix wrong function name in error message. Signed-off-by: Jun Zhao Signed-off-by: Michael Niedermayer --- libavfilter/formats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/formats.c b/libavfilter/formats.c index d4de862237503..20a2c89719983 100644 --- a/libavfilter/formats.c +++ b/libavfilter/formats.c @@ -72,7 +72,7 @@ do { for (j = 0; j < b->nb; j++) \ if (a->fmts[i] == b->fmts[j]) { \ if(k >= FFMIN(a->nb, b->nb)){ \ - av_log(NULL, AV_LOG_ERROR, "Duplicate formats in avfilter_merge_formats() detected\n"); \ + av_log(NULL, AV_LOG_ERROR, "Duplicate formats in %s detected\n", __FUNCTION__); \ av_free(ret->fmts); \ av_free(ret); \ return NULL; \ From 88e2dc7d0448d1d4656c78454bc5f17063b867e7 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Wed, 6 Dec 2017 14:54:12 -0800 Subject: [PATCH 1332/2557] libavcodec/mpegvideo_parser: improve detection of progressive mpeg2 Previously many progressive mpeg2video samples were detected as interlaced by ffmpeg/ffprobe. For example, https://tmm1.s3.amazonaws.com/720p.ts Before: Input #0, mpegts, from 'https://tmm1.s3.amazonaws.com/720p.ts': Duration: 00:00:08.62, start: 18974.073233, bitrate: 9734 kb/s Program 2 Stream #0:0[0x12eb]: Video: mpeg2video (Main), yuv420p(tv, bottom first), 1280x720 ... After: Input #0, mpegts, from 'https://tmm1.s3.amazonaws.com/720p.ts': Duration: 00:00:08.62, start: 18974.073233, bitrate: 9734 kb/s Program 2 Stream #0:0[0x12eb]: Video: mpeg2video (Main), yuv420p(tv, progressive), 1280x720 ... Signed-off-by: Michael Niedermayer --- libavcodec/mpegvideo_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c index de70cd5632da9..be240b68908ea 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -131,7 +131,7 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, } } - if (!pc->progressive_sequence) { + if (!pc->progressive_sequence && !progressive_frame) { if (top_field_first) s->field_order = AV_FIELD_TT; else From 46f534bdee3439a1a803392b83fb867fcbc0adce Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 11 Dec 2017 11:22:56 +0100 Subject: [PATCH 1333/2557] avfilter/vf_hflip : move context func init in ff_hflip_init --- libavfilter/hflip.h | 1 + libavfilter/vf_hflip.c | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h index cbe1fb3d8c7a7..204090dbb4e2c 100644 --- a/libavfilter/hflip.h +++ b/libavfilter/hflip.h @@ -33,6 +33,7 @@ typedef struct FlipContext { void (*flip_line[4])(const uint8_t *src, uint8_t *dst, int w); } FlipContext; +int ff_hflip_init(FlipContext *s, int step[4], int nb_planes); void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes); #endif /* AVFILTER_HFLIP_H */ diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c index 957ddd9900321..b77afc77fc9ec 100644 --- a/libavfilter/vf_hflip.c +++ b/libavfilter/vf_hflip.c @@ -131,7 +131,7 @@ static int config_props(AVFilterLink *inlink) const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format); const int hsub = pix_desc->log2_chroma_w; const int vsub = pix_desc->log2_chroma_h; - int nb_planes, i; + int nb_planes; av_image_fill_max_pixsteps(s->max_step, NULL, pix_desc); s->planewidth[0] = s->planewidth[3] = inlink->w; @@ -141,8 +141,15 @@ static int config_props(AVFilterLink *inlink) nb_planes = av_pix_fmt_count_planes(inlink->format); + return ff_hflip_init(s, s->max_step, nb_planes); +} + +int ff_hflip_init(FlipContext *s, int step[4], int nb_planes) +{ + int i; + for (i = 0; i < nb_planes; i++) { - switch (s->max_step[i]) { + switch (step[i]) { case 1: s->flip_line[i] = hflip_byte_c; break; case 2: s->flip_line[i] = hflip_short_c; break; case 3: s->flip_line[i] = hflip_b24_c; break; @@ -153,9 +160,8 @@ static int config_props(AVFilterLink *inlink) return AVERROR_BUG; } } - if (ARCH_X86) - ff_hflip_init_x86(s, s->max_step, nb_planes); + ff_hflip_init_x86(s, step, nb_planes); return 0; } From cefb7e00608d691e7c0396c636195135c55ce231 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 11 Dec 2017 11:26:44 +0100 Subject: [PATCH 1334/2557] checkasm/vf_hflip : add test for vf_hflip byte and short simd --- tests/checkasm/Makefile | 1 + tests/checkasm/checkasm.c | 3 ++ tests/checkasm/checkasm.h | 1 + tests/checkasm/vf_hflip.c | 76 +++++++++++++++++++++++++++++++++++++++ tests/fate/checkasm.mak | 1 + 5 files changed, 82 insertions(+) create mode 100644 tests/checkasm/vf_hflip.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index f35359daa929e..35250945451fc 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -32,6 +32,7 @@ CHECKASMOBJS-$(CONFIG_AVCODEC) += $(AVCODECOBJS-yes) # libavfilter tests AVFILTEROBJS-$(CONFIG_BLEND_FILTER) += vf_blend.o AVFILTEROBJS-$(CONFIG_COLORSPACE_FILTER) += vf_colorspace.o +AVFILTEROBJS-$(CONFIG_HFLIP_FILTER) += vf_hflip.o AVFILTEROBJS-$(CONFIG_THRESHOLD_FILTER) += vf_threshold.o CHECKASMOBJS-$(CONFIG_AVFILTER) += $(AVFILTEROBJS-yes) diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 384092a2e4660..45a70aa87f4f9 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -152,6 +152,9 @@ static const struct { #if CONFIG_COLORSPACE_FILTER { "vf_colorspace", checkasm_check_colorspace }, #endif + #if CONFIG_HFLIP_FILTER + { "vf_hflip", checkasm_check_vf_hflip }, + #endif #if CONFIG_THRESHOLD_FILTER { "vf_threshold", checkasm_check_vf_threshold }, #endif diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 8fe42d575086e..cfe9bfb35500f 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -65,6 +65,7 @@ void checkasm_check_sbrdsp(void); void checkasm_check_synth_filter(void); void checkasm_check_utvideodsp(void); void checkasm_check_v210enc(void); +void checkasm_check_vf_hflip(void); void checkasm_check_vf_threshold(void); void checkasm_check_vp8dsp(void); void checkasm_check_vp9dsp(void); diff --git a/tests/checkasm/vf_hflip.c b/tests/checkasm/vf_hflip.c new file mode 100644 index 0000000000000..6bb4d09d64e6d --- /dev/null +++ b/tests/checkasm/vf_hflip.c @@ -0,0 +1,76 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "checkasm.h" +#include "libavfilter/hflip.h" +#include "libavutil/intreadwrite.h" + +#define WIDTH 256 +#define WIDTH_PADDED 256 + 32 + +#define randomize_buffers(buf, size) \ + do { \ + int j; \ + uint8_t *tmp_buf = (uint8_t *)buf;\ + for (j = 0; j < size; j++) \ + tmp_buf[j] = rnd() & 0xFF; \ + } while (0) + +static void check_hflip(int step, const char * report_name){ + LOCAL_ALIGNED_32(uint8_t, src, [WIDTH_PADDED]); + LOCAL_ALIGNED_32(uint8_t, dst_ref, [WIDTH_PADDED]); + LOCAL_ALIGNED_32(uint8_t, dst_new, [WIDTH_PADDED]); + int w = WIDTH; + int i; + int step_array[4] = {1, 1, 1, 1}; + FlipContext s; + + declare_func(void, const uint8_t *src, uint8_t *dst, int w); + + memset(src, 0, WIDTH_PADDED); + memset(dst_ref, 0, WIDTH_PADDED); + memset(dst_new, 0, WIDTH_PADDED); + randomize_buffers(src, WIDTH_PADDED); + + if (step == 2) { + w /= 2; + for (i = 0; i < 4; i++) + step_array[i] = step; + } + + ff_hflip_init(&s, step_array, 4); + + if (check_func(s.flip_line[0], "hflip_%s", report_name)) { + for (i = 1; i < w; i++) { + call_ref(src + (w - 1) * step, dst_ref, i); + call_new(src + (w - 1) * step, dst_new, i); + if (memcmp(dst_ref, dst_new, i * step)) + fail(); + } + bench_new(src + (w - 1) * step, dst_new, w); + } +} +void checkasm_check_vf_hflip(void) +{ + check_hflip(1, "byte"); + report("hflip_byte"); + + check_hflip(2, "short"); + report("hflip_short"); +} diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index 3db745366cd2f..9216c71cb8ede 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -22,6 +22,7 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp \ fate-checkasm-v210enc \ fate-checkasm-vf_blend \ fate-checkasm-vf_colorspace \ + fate-checkasm-vf_hflip \ fate-checkasm-vf_threshold \ fate-checkasm-videodsp \ fate-checkasm-vp8dsp \ From bc219082bb04b9a4725bfe7e78ce0950244e6e84 Mon Sep 17 00:00:00 2001 From: Kelly Ledford Date: Tue, 12 Dec 2017 11:31:23 -0800 Subject: [PATCH 1335/2557] libavfilter/af_dcshift.c: Fixed repeated spelling error 'threshhold' should be 'threshold' Signed-off-by: Kelly Ledford Signed-off-by: Michael Niedermayer --- libavfilter/af_dcshift.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libavfilter/af_dcshift.c b/libavfilter/af_dcshift.c index 6d33daee0b62b..e007efe05e446 100644 --- a/libavfilter/af_dcshift.c +++ b/libavfilter/af_dcshift.c @@ -28,7 +28,7 @@ typedef struct DCShiftContext { const AVClass *class; double dcshift; - double limiterthreshhold; + double limiterthreshold; double limitergain; } DCShiftContext; @@ -47,7 +47,7 @@ static av_cold int init(AVFilterContext *ctx) { DCShiftContext *s = ctx->priv; - s->limiterthreshhold = INT32_MAX * (1.0 - (fabs(s->dcshift) - s->limitergain)); + s->limiterthreshold = INT32_MAX * (1.0 - (fabs(s->dcshift) - s->limitergain)); return 0; } @@ -111,14 +111,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) d = src[j]; - if (d > s->limiterthreshhold && dcshift > 0) { - d = (d - s->limiterthreshhold) * s->limitergain / - (INT32_MAX - s->limiterthreshhold) + - s->limiterthreshhold + dcshift; - } else if (d < -s->limiterthreshhold && dcshift < 0) { - d = (d + s->limiterthreshhold) * s->limitergain / - (INT32_MAX - s->limiterthreshhold) - - s->limiterthreshhold + dcshift; + if (d > s->limiterthreshold && dcshift > 0) { + d = (d - s->limiterthreshold) * s->limitergain / + (INT32_MAX - s->limiterthreshold) + + s->limiterthreshold + dcshift; + } else if (d < -s->limiterthreshold && dcshift < 0) { + d = (d + s->limiterthreshold) * s->limitergain / + (INT32_MAX - s->limiterthreshold) - + s->limiterthreshold + dcshift; } else { d = dcshift * INT32_MAX + d; } From 309ddcbe61662282d91098029e7f9796acec208c Mon Sep 17 00:00:00 2001 From: Kelly Ledford Date: Tue, 12 Dec 2017 11:31:24 -0800 Subject: [PATCH 1336/2557] patcheck: Add 'threshhold' to common typo list Signed-off-by: Kelly Ledford Signed-off-by: Michael Niedermayer --- tools/patcheck | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/patcheck b/tools/patcheck index 26137d6b218b0..101a542ff3219 100755 --- a/tools/patcheck +++ b/tools/patcheck @@ -68,7 +68,7 @@ $EGREP $OPT '^\+ *(const *|)static' $*| $EGREP --color=always '[^=]= *(0|NULL)[^ cat $TMP hiegrep '# *ifdef * (HAVE|CONFIG)_' 'ifdefs that should be #if' $* -hiegrep '\b(awnser|cant|dont|wont|doesnt|usefull|successfull|occured|teh|alot|wether|skiped|skiping|heigth|informations|colums|loosy|loosing|ouput|seperate|preceed|upto|paket|posible|unkown|inpossible|dimention|acheive|funtions|overriden|outputing|seperation|initalize|compatibilty|bistream|knwon|unknwon|choosen|additonal|gurantee|availble|wich|begining|milisecond|missmatch)\b' 'common typos' $* +hiegrep '\b(awnser|cant|dont|wont|doesnt|usefull|successfull|occured|teh|alot|wether|skiped|skiping|heigth|informations|colums|loosy|loosing|ouput|seperate|preceed|upto|paket|posible|unkown|inpossible|dimention|acheive|funtions|overriden|outputing|seperation|initalize|compatibilty|bistream|knwon|unknwon|choosen|additonal|gurantee|availble|wich|begining|milisecond|missmatch|threshhold)\b' 'common typos' $* hiegrep 'av_log\( *NULL' 'Missing context in av_log' $* hiegrep '[^sn]printf' 'Please use av_log' $* From e8f0a463b0d27a4d74c0d9f1857e72a8033d1069 Mon Sep 17 00:00:00 2001 From: Tristan Matthews Date: Sun, 10 Dec 2017 18:28:50 -0500 Subject: [PATCH 1337/2557] ivfenc: add AV1 support libaom tools work with ivf files. --- libavformat/ivfenc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c index fdc0ee03e1640..f591327a218c2 100644 --- a/libavformat/ivfenc.c +++ b/libavformat/ivfenc.c @@ -37,14 +37,17 @@ static int ivf_write_header(AVFormatContext *s) } par = s->streams[0]->codecpar; if (par->codec_type != AVMEDIA_TYPE_VIDEO || - !(par->codec_id == AV_CODEC_ID_VP8 || par->codec_id == AV_CODEC_ID_VP9)) { - av_log(s, AV_LOG_ERROR, "Currently only VP8 and VP9 are supported!\n"); + !(par->codec_id == AV_CODEC_ID_VP8 || par->codec_id == AV_CODEC_ID_VP9 || + par->codec_id == AV_CODEC_ID_AV1)) { + av_log(s, AV_LOG_ERROR, "Currently only VP8, VP9 and AV1 are supported!\n"); return AVERROR(EINVAL); } avio_write(pb, "DKIF", 4); avio_wl16(pb, 0); // version avio_wl16(pb, 32); // header length - avio_wl32(pb, par->codec_tag ? par->codec_tag : par->codec_id == AV_CODEC_ID_VP9 ? AV_RL32("VP90") : AV_RL32("VP80")); + avio_wl32(pb, par->codec_tag ? par->codec_tag : + par->codec_id == AV_CODEC_ID_VP9 ? AV_RL32("VP90") : + par->codec_id == AV_CODEC_ID_VP8 ? AV_RL32("VP80") : AV_RL32("AV01")); avio_wl16(pb, par->width); avio_wl16(pb, par->height); avio_wl32(pb, s->streams[0]->time_base.den); @@ -100,6 +103,7 @@ static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) static const AVCodecTag codec_ivf_tags[] = { { AV_CODEC_ID_VP8, MKTAG('V', 'P', '8', '0') }, { AV_CODEC_ID_VP9, MKTAG('V', 'P', '9', '0') }, + { AV_CODEC_ID_AV1, MKTAG('A', 'V', '0', '1') }, { AV_CODEC_ID_NONE, 0 } }; From f7617d4b83c08958b373324d270c0504aa1be8ee Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 13 Dec 2017 21:51:31 +0100 Subject: [PATCH 1338/2557] libavcodec/decode: remove duplicate includes Signed-off-by: Michael Niedermayer --- libavcodec/decode.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/decode.h b/libavcodec/decode.h index 424e85e91429b..15271c529ab64 100644 --- a/libavcodec/decode.h +++ b/libavcodec/decode.h @@ -21,9 +21,6 @@ #ifndef AVCODEC_DECODE_H #define AVCODEC_DECODE_H -#include "libavutil/buffer.h" -#include "libavutil/frame.h" - #include "libavutil/buffer.h" #include "libavutil/frame.h" #include "libavutil/hwcontext.h" From 2e391a576c1fc2e8816990924c6e4c21ccf75a82 Mon Sep 17 00:00:00 2001 From: Rodger Combs Date: Thu, 19 Oct 2017 01:58:10 -0500 Subject: [PATCH 1339/2557] lavf/mpegts: mark packets with TEI flag as corrupted --- libavformat/mpegts.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 53cbcfb543bf3..0a3ad05726447 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -2296,6 +2296,14 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) } } + if (packet[1] & 0x80) { + av_log(ts->stream, AV_LOG_DEBUG, "Packet had TEI flag set; marking as corrupt\n"); + if (tss->type == MPEGTS_PES) { + PESContext *pc = tss->u.pes_filter.opaque; + pc->flags |= AV_PKT_FLAG_CORRUPT; + } + } + p = packet + 4; if (has_adaptation) { int64_t pcr_h; From 47687a2f8aca3f65b6fdd117b1cb66a7409a7fd1 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 12 Dec 2017 11:03:43 +0100 Subject: [PATCH 1340/2557] avcodec: add metadata to identify wrappers and hardware decoders Explicitly identify decoder/encoder wrappers with a common name. This saves API users from guessing by the name suffix. For example, they don't have to guess that "h264_qsv" is the h264 QSV implementation, and instead they can just check the AVCodec .codec and .wrapper_name fields. Explicitly mark AVCodec entries that are hardware decoders or most likely hardware decoders with new AV_CODEC_CAPs. The purpose is allowing API users listing hardware decoders in a more generic way. The proposed AVCodecHWConfig does not provide this information fully, because it's concerned with decoder configuration, not information about the fact whether the hardware is used or not. AV_CODEC_CAP_HYBRID exists specifically for QSV, which can have software implementations in case the hardware is not capable. Based on a patch by Philip Langdale . Signed-off-by: Luca Barbato --- libavcodec/avcodec.h | 25 +++++++++++++++++++++++++ libavcodec/libdcadec.c | 1 + libavcodec/libfaac.c | 1 + libavcodec/libfdk-aacdec.c | 1 + libavcodec/libfdk-aacenc.c | 1 + libavcodec/libgsmdec.c | 2 ++ libavcodec/libgsmenc.c | 2 ++ libavcodec/libilbc.c | 1 + libavcodec/libkvazaar.c | 2 ++ libavcodec/libmp3lame.c | 1 + libavcodec/libopencore-amr.c | 1 + libavcodec/libopenh264dec.c | 1 + libavcodec/libopenh264enc.c | 1 + libavcodec/libopenjpegdec.c | 1 + libavcodec/libopenjpegenc.c | 1 + libavcodec/libopusdec.c | 1 + libavcodec/libopusenc.c | 1 + libavcodec/libschroedingerdec.c | 1 + libavcodec/libschroedingerenc.c | 1 + libavcodec/libspeexdec.c | 1 + libavcodec/libspeexenc.c | 1 + libavcodec/libtheoraenc.c | 1 + libavcodec/libtwolame.c | 1 + libavcodec/libvo-aacenc.c | 1 + libavcodec/libvo-amrwbenc.c | 1 + libavcodec/libvorbis.c | 1 + libavcodec/libvpxdec.c | 2 ++ libavcodec/libvpxenc.c | 2 ++ libavcodec/libwavpackenc.c | 1 + libavcodec/libwebpenc.c | 1 + libavcodec/libx264.c | 2 ++ libavcodec/libx265.c | 1 + libavcodec/libxavs.c | 1 + libavcodec/libxvid.c | 1 + libavcodec/mmaldec.c | 3 ++- libavcodec/qsvdec_h2645.c | 6 ++++-- libavcodec/qsvdec_other.c | 9 ++++++--- libavcodec/qsvenc_h264.c | 3 ++- libavcodec/qsvenc_hevc.c | 3 ++- libavcodec/qsvenc_jpeg.c | 3 ++- libavcodec/qsvenc_mpeg2.c | 3 ++- libavcodec/vaapi_encode_h264.c | 3 ++- libavcodec/vaapi_encode_h265.c | 3 ++- libavcodec/vaapi_encode_mjpeg.c | 2 ++ libavcodec/vaapi_encode_mpeg2.c | 3 ++- libavcodec/vaapi_encode_vp8.c | 3 ++- libavcodec/vaapi_encode_vp9.c | 3 ++- 47 files changed, 96 insertions(+), 15 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 5624835023ea4..ec952dd0e830c 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -885,6 +885,19 @@ typedef struct RcOverride{ */ #define AV_CODEC_CAP_VARIABLE_FRAME_SIZE (1 << 16) +/** + * Codec is backed by a hardware implementation. Typically used to + * identify a non-hwaccel hardware decoder. + */ +#define AV_CODEC_CAP_HARDWARE (1 << 17) + +/** + * Codec is potentially backed by a hardware implementation, but not + * necessarily. This is used instead of AV_CODEC_CAP_HARDWARE, if the + * implementation provides some sort of internal fallback. + */ +#define AV_CODEC_CAP_HYBRID (1 << 18) + /** * Pan Scan area. * This specifies the area which should be displayed. @@ -2770,6 +2783,18 @@ typedef struct AVCodec { const AVClass *priv_class; ///< AVClass for the private context const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN} + /** + * Group name of the codec implementation. + * This is a short symbolic name of the wrapper backing this codec. A + * wrapper uses some kind of external implementation for the codec, such + * as an external library, or a codec implementation provided by the OS or + * the hardware. + * If this field is NULL, this is a builtin, libavcodec native decoder. + * If non-NULL, this will be the suffix in AVCodec.name in most cases + * (usually AVCodec.name will be of the form "_"). + */ + const char *wrapper_name; + /***************************************************************** * No fields below this line are part of the public API. They * may not be used outside of libavcodec and can be changed and diff --git a/libavcodec/libdcadec.c b/libavcodec/libdcadec.c index b88f80763b682..d44f4d931e450 100644 --- a/libavcodec/libdcadec.c +++ b/libavcodec/libdcadec.c @@ -202,4 +202,5 @@ AVCodec ff_libdcadec_decoder = { .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, .profiles = NULL_IF_CONFIG_SMALL(profiles), + .wrapper_name = "libdcadec", }; diff --git a/libavcodec/libfaac.c b/libavcodec/libfaac.c index 5cdbe2768643a..db04a377011d3 100644 --- a/libavcodec/libfaac.c +++ b/libavcodec/libfaac.c @@ -237,4 +237,5 @@ AVCodec ff_libfaac_encoder = { AV_SAMPLE_FMT_NONE }, .profiles = NULL_IF_CONFIG_SMALL(profiles), .channel_layouts = faac_channel_layouts, + .wrapper_name = "libfaac", }; diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c index aa30f93ef6dc1..3be65155b5f54 100644 --- a/libavcodec/libfdk-aacdec.c +++ b/libavcodec/libfdk-aacdec.c @@ -386,4 +386,5 @@ AVCodec ff_libfdk_aac_decoder = { .priv_class = &fdk_aac_dec_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "libfdk", }; diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c index 03879bbf5adbc..26dfb6dc0b45c 100644 --- a/libavcodec/libfdk-aacenc.c +++ b/libavcodec/libfdk-aacenc.c @@ -430,4 +430,5 @@ AVCodec ff_libfdk_aac_encoder = { .profiles = profiles, .supported_samplerates = aac_sample_rates, .channel_layouts = aac_channel_layout, + .wrapper_name = "libfdk", }; diff --git a/libavcodec/libgsmdec.c b/libavcodec/libgsmdec.c index e06fe52762284..419f36489b38e 100644 --- a/libavcodec/libgsmdec.c +++ b/libavcodec/libgsmdec.c @@ -130,6 +130,7 @@ AVCodec ff_libgsm_decoder = { .decode = libgsm_decode_frame, .flush = libgsm_flush, .capabilities = AV_CODEC_CAP_DR1, + .wrapper_name = "libgsm", }; AVCodec ff_libgsm_ms_decoder = { @@ -143,4 +144,5 @@ AVCodec ff_libgsm_ms_decoder = { .decode = libgsm_decode_frame, .flush = libgsm_flush, .capabilities = AV_CODEC_CAP_DR1, + .wrapper_name = "libgsm", }; diff --git a/libavcodec/libgsmenc.c b/libavcodec/libgsmenc.c index 4bb4075b2fdc3..1d039b1983a44 100644 --- a/libavcodec/libgsmenc.c +++ b/libavcodec/libgsmenc.c @@ -117,6 +117,7 @@ AVCodec ff_libgsm_encoder = { .close = libgsm_encode_close, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .wrapper_name = "libgsm", }; AVCodec ff_libgsm_ms_encoder = { @@ -129,4 +130,5 @@ AVCodec ff_libgsm_ms_encoder = { .close = libgsm_encode_close, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .wrapper_name = "libgsm", }; diff --git a/libavcodec/libilbc.c b/libavcodec/libilbc.c index 80b69a562cbf5..4b1619936ec2d 100644 --- a/libavcodec/libilbc.c +++ b/libavcodec/libilbc.c @@ -197,4 +197,5 @@ AVCodec ff_libilbc_encoder = { AV_SAMPLE_FMT_NONE }, .defaults = ilbc_encode_defaults, .priv_class = &ilbc_enc_class, + .wrapper_name = "libbilbc", }; diff --git a/libavcodec/libkvazaar.c b/libavcodec/libkvazaar.c index efc98f1f65b55..fa64bf59df49f 100644 --- a/libavcodec/libkvazaar.c +++ b/libavcodec/libkvazaar.c @@ -301,4 +301,6 @@ AVCodec ff_libkvazaar_encoder = { .close = libkvazaar_close, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + + .wrapper_name = "libkvazaar", }; diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index e4d0e001032dd..1fe26d12a0843 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -315,4 +315,5 @@ AVCodec ff_libmp3lame_encoder = { 0 }, .priv_class = &libmp3lame_class, .defaults = libmp3lame_defaults, + .wrapper_name = "libmp3lame", }; diff --git a/libavcodec/libopencore-amr.c b/libavcodec/libopencore-amr.c index 8200f6719c647..8ce5a712db23c 100644 --- a/libavcodec/libopencore-amr.c +++ b/libavcodec/libopencore-amr.c @@ -379,6 +379,7 @@ AVCodec ff_libopencore_amrwb_decoder = { .close = amr_wb_decode_close, .decode = amr_wb_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .wrapper_name = "libopencore_amrwb", }; #endif /* CONFIG_LIBOPENCORE_AMRWB_DECODER */ diff --git a/libavcodec/libopenh264dec.c b/libavcodec/libopenh264dec.c index d65d63914c640..cdb8d527cf92f 100644 --- a/libavcodec/libopenh264dec.c +++ b/libavcodec/libopenh264dec.c @@ -145,4 +145,5 @@ AVCodec ff_libopenh264_decoder = { .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .bsfs = "h264_mp4toannexb", + .wrapper_name = "libopenh264", }; diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index 3b32790bae5ee..d075cb08545cc 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -301,4 +301,5 @@ AVCodec ff_libopenh264_encoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &class, + .wrapper_name = "libopenh264", }; diff --git a/libavcodec/libopenjpegdec.c b/libavcodec/libopenjpegdec.c index 6b8e210ac69e5..798b33f13f475 100644 --- a/libavcodec/libopenjpegdec.c +++ b/libavcodec/libopenjpegdec.c @@ -438,4 +438,5 @@ AVCodec ff_libopenjpeg_decoder = { .decode = libopenjpeg_decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .priv_class = &class, + .wrapper_name = "libopenjpeg", }; diff --git a/libavcodec/libopenjpegenc.c b/libavcodec/libopenjpegenc.c index d1af0210e3207..953d733c374d2 100644 --- a/libavcodec/libopenjpegenc.c +++ b/libavcodec/libopenjpegenc.c @@ -426,4 +426,5 @@ AVCodec ff_libopenjpeg_encoder = { AV_PIX_FMT_NONE }, .priv_class = &class, + .wrapper_name = "libopenjpeg", }; diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c index 781635615c488..1dac1a01ab69e 100644 --- a/libavcodec/libopusdec.c +++ b/libavcodec/libopusdec.c @@ -177,4 +177,5 @@ AVCodec ff_libopus_decoder = { .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .wrapper_name = "libopus", }; diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c index 500e58c85e3de..823cab176aeae 100644 --- a/libavcodec/libopusenc.c +++ b/libavcodec/libopusenc.c @@ -422,4 +422,5 @@ AVCodec ff_libopus_encoder = { .supported_samplerates = libopus_sample_rates, .priv_class = &libopus_class, .defaults = libopus_defaults, + .wrapper_name = "libopus", }; diff --git a/libavcodec/libschroedingerdec.c b/libavcodec/libschroedingerdec.c index 69eed01ce0e8c..246ac486f448b 100644 --- a/libavcodec/libschroedingerdec.c +++ b/libavcodec/libschroedingerdec.c @@ -393,4 +393,5 @@ AVCodec ff_libschroedinger_decoder = { .decode = libschroedinger_decode_frame, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, .flush = libschroedinger_flush, + .wrapper_name = "libschroedinger", }; diff --git a/libavcodec/libschroedingerenc.c b/libavcodec/libschroedingerenc.c index bf03cb78fcbd2..4a1be9407b8cd 100644 --- a/libavcodec/libschroedingerenc.c +++ b/libavcodec/libschroedingerenc.c @@ -481,4 +481,5 @@ AVCodec ff_libschroedinger_encoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, + .wrapper_name = "libschroedinger", }; diff --git a/libavcodec/libspeexdec.c b/libavcodec/libspeexdec.c index 949a9344c1ce8..e8775fd146b75 100644 --- a/libavcodec/libspeexdec.c +++ b/libavcodec/libspeexdec.c @@ -179,4 +179,5 @@ AVCodec ff_libspeex_decoder = { .decode = libspeex_decode_frame, .flush = libspeex_decode_flush, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .wrapper_name = "libspeex", }; diff --git a/libavcodec/libspeexenc.c b/libavcodec/libspeexenc.c index eb02e8ec6d8bb..b17761fd311bd 100644 --- a/libavcodec/libspeexenc.c +++ b/libavcodec/libspeexenc.c @@ -366,4 +366,5 @@ AVCodec ff_libspeex_encoder = { .supported_samplerates = (const int[]){ 8000, 16000, 32000, 0 }, .priv_class = &class, .defaults = defaults, + .wrapper_name = "libspeex", }; diff --git a/libavcodec/libtheoraenc.c b/libavcodec/libtheoraenc.c index b329ed3b347ed..2676df42337af 100644 --- a/libavcodec/libtheoraenc.c +++ b/libavcodec/libtheoraenc.c @@ -382,4 +382,5 @@ AVCodec ff_libtheora_encoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, + .wrapper_name = "libtheora", }; diff --git a/libavcodec/libtwolame.c b/libavcodec/libtwolame.c index 714c30acdee9a..9b0fe165bc572 100644 --- a/libavcodec/libtwolame.c +++ b/libavcodec/libtwolame.c @@ -222,4 +222,5 @@ AVCodec ff_libtwolame_encoder = { AV_CH_LAYOUT_STEREO, 0 }, .supported_samplerates = twolame_samplerates, + .wrapper_name = "libtwolame", }; diff --git a/libavcodec/libvo-aacenc.c b/libavcodec/libvo-aacenc.c index 876ef4c197b75..ae3b54e716dfe 100644 --- a/libavcodec/libvo-aacenc.c +++ b/libavcodec/libvo-aacenc.c @@ -191,4 +191,5 @@ AVCodec ff_libvo_aacenc_encoder = { .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .wrapper_name = "libvo_aacenc", }; diff --git a/libavcodec/libvo-amrwbenc.c b/libavcodec/libvo-amrwbenc.c index 5439d661103d4..7be14c260d8a6 100644 --- a/libavcodec/libvo-amrwbenc.c +++ b/libavcodec/libvo-amrwbenc.c @@ -154,4 +154,5 @@ AVCodec ff_libvo_amrwbenc_encoder = { .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .priv_class = &class, + .wrapper_name = "libvo_amrwbenc", }; diff --git a/libavcodec/libvorbis.c b/libavcodec/libvorbis.c index 3dfd589476d16..972ca6a59e5c9 100644 --- a/libavcodec/libvorbis.c +++ b/libavcodec/libvorbis.c @@ -356,4 +356,5 @@ AVCodec ff_libvorbis_encoder = { AV_SAMPLE_FMT_NONE }, .priv_class = &class, .defaults = defaults, + .wrapper_name = "libvorbis", }; diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c index 6d3b29fefaf5e..84806702fb229 100644 --- a/libavcodec/libvpxdec.c +++ b/libavcodec/libvpxdec.c @@ -137,6 +137,7 @@ AVCodec ff_libvpx_vp8_decoder = { .close = vp8_free, .decode = vp8_decode, .capabilities = AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_DR1, + .wrapper_name = "libvpx", }; #endif /* CONFIG_LIBVPX_VP8_DECODER */ @@ -156,5 +157,6 @@ AVCodec ff_libvpx_vp9_decoder = { .close = vp8_free, .decode = vp8_decode, .capabilities = AV_CODEC_CAP_AUTO_THREADS, + .wrapper_name = "libvpx", }; #endif /* CONFIG_LIBVPX_VP9_DECODER */ diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 7e971fd97f184..74d5a0c0978c1 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -649,6 +649,7 @@ AVCodec ff_libvpx_vp8_encoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &class_vp8, .defaults = defaults, + .wrapper_name = "libvpx", }; #endif /* CONFIG_LIBVPX_VP8_ENCODER */ @@ -695,5 +696,6 @@ AVCodec ff_libvpx_vp9_encoder = { .profiles = NULL_IF_CONFIG_SMALL(profiles), .priv_class = &class_vp9, .defaults = defaults, + .wrapper_name = "libvpx", }; #endif /* CONFIG_LIBVPX_VP9_ENCODER */ diff --git a/libavcodec/libwavpackenc.c b/libavcodec/libwavpackenc.c index 1455d91b218b6..3f4fc7c608717 100644 --- a/libavcodec/libwavpackenc.c +++ b/libavcodec/libwavpackenc.c @@ -191,4 +191,5 @@ AVCodec ff_libwavpack_encoder = { .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, + .wrapper_name = "libwavpack", }; diff --git a/libavcodec/libwebpenc.c b/libavcodec/libwebpenc.c index ef311b75921f6..29683d7884c06 100644 --- a/libavcodec/libwebpenc.c +++ b/libavcodec/libwebpenc.c @@ -286,4 +286,5 @@ AVCodec ff_libwebp_encoder = { }, .priv_class = &class, .defaults = libwebp_defaults, + .wrapper_name = "libwebp", }; diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 4448d977cf9bd..0dec12edd29d1 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -826,6 +826,7 @@ AVCodec ff_libx264_encoder = { .init_static_data = X264_init_static, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "libx264", }; #endif @@ -852,5 +853,6 @@ AVCodec ff_libx262_encoder = { .pix_fmts = pix_fmts_8bit, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "libx264", }; #endif diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index add05692c5e18..fd5452193b9d9 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -382,4 +382,5 @@ AVCodec ff_libx265_encoder = { .priv_class = &class, .defaults = x265_defaults, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .wrapper_name = "libx265", }; diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c index 24ddd22e5fd87..1a80b1a32ca9c 100644 --- a/libavcodec/libxavs.c +++ b/libavcodec/libxavs.c @@ -480,4 +480,5 @@ AVCodec ff_libxavs_encoder = { .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &class, .defaults = xavs_defaults, + .wrapper_name = "libxavs", }; diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c index 896935d31eee8..ab2e67629a0b7 100644 --- a/libavcodec/libxvid.c +++ b/libavcodec/libxvid.c @@ -925,4 +925,5 @@ AVCodec ff_libxvid_encoder = { .priv_class = &xvid_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "libxvid", }; diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index 023ebe80de564..3e480ab49abe1 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -835,11 +835,12 @@ static const AVOption options[]={ .decode = ffmmal_decode, \ .flush = ffmmal_flush, \ .priv_class = &ffmmal_##NAME##_dec_class, \ - .capabilities = AV_CODEC_CAP_DELAY, \ + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \ .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, \ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MMAL, \ AV_PIX_FMT_YUV420P, \ AV_PIX_FMT_NONE}, \ + .wrapper_name = "mmal", \ }; FFMMAL_DEC(h264, AV_CODEC_ID_H264) diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c index e3184d87494d3..03ba303c95382 100644 --- a/libavcodec/qsvdec_h2645.c +++ b/libavcodec/qsvdec_h2645.c @@ -220,13 +220,14 @@ AVCodec ff_hevc_qsv_decoder = { .decode = qsv_decode_frame, .flush = qsv_decode_flush, .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_HYBRID, .priv_class = &hevc_class, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_P010, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, .bsfs = "hevc_mp4toannexb", + .wrapper_name = "qsv", }; #endif @@ -262,12 +263,13 @@ AVCodec ff_h264_qsv_decoder = { .decode = qsv_decode_frame, .flush = qsv_decode_flush, .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_HYBRID, .priv_class = &class, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_P010, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, .bsfs = "h264_mp4toannexb", + .wrapper_name = "qsv", }; #endif diff --git a/libavcodec/qsvdec_other.c b/libavcodec/qsvdec_other.c index 97a763579a043..0cea4eee92887 100644 --- a/libavcodec/qsvdec_other.c +++ b/libavcodec/qsvdec_other.c @@ -190,11 +190,12 @@ AVCodec ff_mpeg2_qsv_decoder = { .decode = qsv_decode_frame, .flush = qsv_decode_flush, .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_HYBRID, .priv_class = &mpeg2_qsv_class, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, + .wrapper_name = "qsv", }; #endif @@ -225,11 +226,12 @@ AVCodec ff_vc1_qsv_decoder = { .decode = qsv_decode_frame, .flush = qsv_decode_flush, .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_HYBRID, .priv_class = &vc1_qsv_class, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, + .wrapper_name = "qsv", }; #endif @@ -260,10 +262,11 @@ AVCodec ff_vp8_qsv_decoder = { .decode = qsv_decode_frame, .flush = qsv_decode_flush, .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_HYBRID, .priv_class = &vp8_qsv_class, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, + .wrapper_name = "qsv", }; #endif diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index 1365faccea063..1552d7691dff7 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -127,7 +127,7 @@ AVCodec ff_h264_qsv_encoder = { .init = qsv_enc_init, .encode2 = qsv_enc_frame, .close = qsv_enc_close, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_P010, AV_PIX_FMT_QSV, @@ -135,4 +135,5 @@ AVCodec ff_h264_qsv_encoder = { .priv_class = &class, .defaults = qsv_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "qsv", }; diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index dbb55e2f18285..471d1748737f2 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -272,7 +272,7 @@ AVCodec ff_hevc_qsv_encoder = { .init = qsv_enc_init, .encode2 = qsv_enc_frame, .close = qsv_enc_close, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_P010, AV_PIX_FMT_QSV, @@ -280,4 +280,5 @@ AVCodec ff_hevc_qsv_encoder = { .priv_class = &class, .defaults = qsv_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "qsv", }; diff --git a/libavcodec/qsvenc_jpeg.c b/libavcodec/qsvenc_jpeg.c index 3fa17f13abb68..e11b74dc9ff37 100644 --- a/libavcodec/qsvenc_jpeg.c +++ b/libavcodec/qsvenc_jpeg.c @@ -83,9 +83,10 @@ AVCodec ff_mjpeg_qsv_encoder = { .init = qsv_enc_init, .encode2 = qsv_enc_frame, .close = qsv_enc_close, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, .priv_class = &class, + .wrapper_name = "qsv", }; diff --git a/libavcodec/qsvenc_mpeg2.c b/libavcodec/qsvenc_mpeg2.c index f29f445182d98..9986d8b1e4fd4 100644 --- a/libavcodec/qsvenc_mpeg2.c +++ b/libavcodec/qsvenc_mpeg2.c @@ -104,11 +104,12 @@ AVCodec ff_mpeg2_qsv_encoder = { .init = qsv_enc_init, .encode2 = qsv_enc_frame, .close = qsv_enc_close, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, .priv_class = &class, .defaults = qsv_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "qsv", }; diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 6b47d932b6d70..b7eee756e129e 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -1074,10 +1074,11 @@ AVCodec ff_h264_vaapi_encoder = { .encode2 = &ff_vaapi_encode2, .close = &vaapi_encode_h264_close, .priv_class = &vaapi_encode_h264_class, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .defaults = vaapi_encode_h264_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 8fa277bf94e5a..a9853a3aa0a6a 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -1018,10 +1018,11 @@ AVCodec ff_hevc_vaapi_encoder = { .encode2 = &ff_vaapi_encode2, .close = &vaapi_encode_h265_close, .priv_class = &vaapi_encode_h265_class, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .defaults = vaapi_encode_h265_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c index b96715146dde4..a3cd8caea6744 100644 --- a/libavcodec/vaapi_encode_mjpeg.c +++ b/libavcodec/vaapi_encode_mjpeg.c @@ -422,9 +422,11 @@ AVCodec ff_mjpeg_vaapi_encoder = { .encode2 = &ff_vaapi_encode2, .close = &ff_vaapi_encode_close, .priv_class = &vaapi_encode_mjpeg_class, + .capabilities = AV_CODEC_CAP_HARDWARE, .defaults = vaapi_encode_mjpeg_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_mpeg2.c b/libavcodec/vaapi_encode_mpeg2.c index 8b956eb3e0e38..954b60733c1fa 100644 --- a/libavcodec/vaapi_encode_mpeg2.c +++ b/libavcodec/vaapi_encode_mpeg2.c @@ -669,10 +669,11 @@ AVCodec ff_mpeg2_vaapi_encoder = { .init = &vaapi_encode_mpeg2_init, .encode2 = &ff_vaapi_encode2, .close = &vaapi_encode_mpeg2_close, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .defaults = vaapi_encode_mpeg2_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_vp8.c b/libavcodec/vaapi_encode_vp8.c index d1a8087b82352..857054dc6485b 100644 --- a/libavcodec/vaapi_encode_vp8.c +++ b/libavcodec/vaapi_encode_vp8.c @@ -259,10 +259,11 @@ AVCodec ff_vp8_vaapi_encoder = { .encode2 = &ff_vaapi_encode2, .close = &ff_vaapi_encode_close, .priv_class = &vaapi_encode_vp8_class, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .defaults = vaapi_encode_vp8_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c index 5d3eec1775dcc..6d9899d2a73a3 100644 --- a/libavcodec/vaapi_encode_vp9.c +++ b/libavcodec/vaapi_encode_vp9.c @@ -302,10 +302,11 @@ AVCodec ff_vp9_vaapi_encoder = { .encode2 = &ff_vaapi_encode2, .close = &ff_vaapi_encode_close, .priv_class = &vaapi_encode_vp9_class, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .defaults = vaapi_encode_vp9_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .wrapper_name = "vaapi", }; From b945fed629a872d393f59d16fc5773574126ca88 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 11 Dec 2017 16:18:44 +0100 Subject: [PATCH 1341/2557] avcodec: add metadata to identify wrappers and hardware decoders Explicitly identify decoder/encoder wrappers with a common name. This saves API users from guessing by the name suffix. For example, they don't have to guess that "h264_qsv" is the h264 QSV implementation, and instead they can just check the AVCodec .codec and .wrapper_name fields. Explicitly mark AVCodec entries that are hardware decoders or most likely hardware decoders with new AV_CODEC_CAPs. The purpose is allowing API users listing hardware decoders in a more generic way. The proposed AVCodecHWConfig does not provide this information fully, because it's concerned with decoder configuration, not information about the fact whether the hardware is used or not. AV_CODEC_CAP_HYBRID exists specifically for QSV, which can have software implementations in case the hardware is not capable. Based on a patch by Philip Langdale . Merges Libav commit 47687a2f8aca3f65b6fdd117b1cb66a7409a7fd1. --- doc/APIchanges | 4 ++++ libavcodec/audiotoolboxdec.c | 1 + libavcodec/audiotoolboxenc.c | 1 + libavcodec/avcodec.h | 26 ++++++++++++++++++++++++++ libavcodec/crystalhd.c | 3 ++- libavcodec/cuviddec.c | 3 ++- libavcodec/libcelt_dec.c | 1 + libavcodec/libfdk-aacdec.c | 1 + libavcodec/libfdk-aacenc.c | 1 + libavcodec/libgsmdec.c | 2 ++ libavcodec/libgsmenc.c | 2 ++ libavcodec/libilbc.c | 1 + libavcodec/libkvazaar.c | 2 ++ libavcodec/libmp3lame.c | 1 + libavcodec/libopencore-amr.c | 1 + libavcodec/libopenh264dec.c | 1 + libavcodec/libopenh264enc.c | 1 + libavcodec/libopenjpegdec.c | 1 + libavcodec/libopenjpegenc.c | 1 + libavcodec/libopusdec.c | 1 + libavcodec/libopusenc.c | 1 + libavcodec/librsvgdec.c | 1 + libavcodec/libshine.c | 1 + libavcodec/libspeexdec.c | 1 + libavcodec/libspeexenc.c | 1 + libavcodec/libtheoraenc.c | 1 + libavcodec/libtwolame.c | 1 + libavcodec/libvo-amrwbenc.c | 1 + libavcodec/libvorbisenc.c | 1 + libavcodec/libvpxdec.c | 2 ++ libavcodec/libvpxenc.c | 2 ++ libavcodec/libwavpackenc.c | 1 + libavcodec/libwebpenc.c | 1 + libavcodec/libwebpenc_animencoder.c | 1 + libavcodec/libx264.c | 3 +++ libavcodec/libx265.c | 1 + libavcodec/libxavs.c | 1 + libavcodec/libxvid.c | 1 + libavcodec/libzvbi-teletextdec.c | 1 + libavcodec/mediacodecdec.c | 18 ++++++++++++------ libavcodec/mmaldec.c | 3 ++- libavcodec/nvenc_h264.c | 9 ++++++--- libavcodec/nvenc_hevc.c | 6 ++++-- libavcodec/qsvdec_h2645.c | 6 ++++-- libavcodec/qsvdec_other.c | 9 ++++++--- libavcodec/qsvenc_h264.c | 3 ++- libavcodec/qsvenc_hevc.c | 3 ++- libavcodec/qsvenc_jpeg.c | 3 ++- libavcodec/qsvenc_mpeg2.c | 3 ++- libavcodec/rkmppdec.c | 3 ++- libavcodec/v4l2_m2m_dec.c | 2 ++ libavcodec/v4l2_m2m_enc.c | 2 ++ libavcodec/vaapi_encode_h264.c | 3 ++- libavcodec/vaapi_encode_h265.c | 3 ++- libavcodec/vaapi_encode_mjpeg.c | 2 ++ libavcodec/vaapi_encode_mpeg2.c | 3 ++- libavcodec/vaapi_encode_vp8.c | 3 ++- libavcodec/vaapi_encode_vp9.c | 3 ++- libavcodec/version.h | 4 ++-- libavcodec/videotoolboxenc.c | 3 ++- 60 files changed, 140 insertions(+), 32 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 4af69c64bdf2a..b4451ab193a63 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2017-10-21 API changes, most recent first: +2017-xx-xx - xxxxxxc - lavc 58.7.100 - avcodec.h + Add AV_CODEC_CAP_HARDWARE, AV_CODEC_CAP_HYBRID, and AVCodec.wrapper_name, + and mark all AVCodecs accordingly. + 2017-xx-xx - xxxxxxx - lavu 56.4.100 / 56.7.0 - stereo3d.h Add view field to AVStereo3D structure and AVStereo3DView enum. diff --git a/libavcodec/audiotoolboxdec.c b/libavcodec/audiotoolboxdec.c index 3711665bbdca7..5c0a9de8f636f 100644 --- a/libavcodec/audiotoolboxdec.c +++ b/libavcodec/audiotoolboxdec.c @@ -597,6 +597,7 @@ static av_cold int ffat_close_decoder(AVCodecContext *avctx) .bsfs = bsf_name, \ .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, \ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, \ + .wrapper_name = "at", \ }; FFAT_DEC(aac, AV_CODEC_ID_AAC, "aac_adtstoasc") diff --git a/libavcodec/audiotoolboxenc.c b/libavcodec/audiotoolboxenc.c index c47fbd1b2d264..71885d153001e 100644 --- a/libavcodec/audiotoolboxenc.c +++ b/libavcodec/audiotoolboxenc.c @@ -619,6 +619,7 @@ static const AVOption options[] = { }, \ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \ .profiles = PROFILES, \ + .wrapper_name = "at", \ }; static const uint64_t aac_at_channel_layouts[] = { diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 5db6a81320e54..ce089b7c4ab04 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1045,6 +1045,20 @@ typedef struct RcOverride{ */ #define AV_CODEC_CAP_LOSSLESS 0x80000000 +/** + * Codec is backed by a hardware implementation. Typically used to + * identify a non-hwaccel hardware decoder. For information about hwaccels, use + * avcodec_get_hw_config() instead. + */ +#define AV_CODEC_CAP_HARDWARE (1 << 18) + +/** + * Codec is potentially backed by a hardware implementation, but not + * necessarily. This is used instead of AV_CODEC_CAP_HARDWARE, if the + * implementation provides some sort of internal fallback. + */ +#define AV_CODEC_CAP_HYBRID (1 << 19) + /** * Pan Scan area. * This specifies the area which should be displayed. @@ -3377,6 +3391,18 @@ typedef struct AVCodec { const AVClass *priv_class; ///< AVClass for the private context const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN} + /** + * Group name of the codec implementation. + * This is a short symbolic name of the wrapper backing this codec. A + * wrapper uses some kind of external implementation for the codec, such + * as an external library, or a codec implementation provided by the OS or + * the hardware. + * If this field is NULL, this is a builtin, libavcodec native codec. + * If non-NULL, this will be the suffix in AVCodec.name in most cases + * (usually AVCodec.name will be of the form "_"). + */ + const char *wrapper_name; + /***************************************************************** * No fields below this line are part of the public API. They * may not be used outside of libavcodec and can be changed and diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c index 83bc8bf364107..e3c5955969e16 100644 --- a/libavcodec/crystalhd.c +++ b/libavcodec/crystalhd.c @@ -786,8 +786,9 @@ static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame) .receive_frame = crystalhd_receive_frame, \ .flush = flush, \ .bsfs = bsf_name, \ - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE}, \ + .wrapper_name = "crystalhd", \ }; #if CONFIG_H264_CRYSTALHD_DECODER diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index 96d56f406a936..c23033c7e3182 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -1127,13 +1127,14 @@ static const AVCodecHWConfigInternal *cuvid_hw_configs[] = { .decode = cuvid_decode_frame, \ .receive_frame = cuvid_output_frame, \ .flush = cuvid_flush, \ - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA, \ AV_PIX_FMT_NV12, \ AV_PIX_FMT_P010, \ AV_PIX_FMT_P016, \ AV_PIX_FMT_NONE }, \ .hw_configs = cuvid_hw_configs, \ + .wrapper_name = "cuvid", \ }; #if CONFIG_HEVC_CUVID_DECODER diff --git a/libavcodec/libcelt_dec.c b/libavcodec/libcelt_dec.c index 878e4cc673cb4..75b438b285519 100644 --- a/libavcodec/libcelt_dec.c +++ b/libavcodec/libcelt_dec.c @@ -137,4 +137,5 @@ AVCodec ff_libcelt_decoder = { .close = libcelt_dec_close, .decode = libcelt_dec_decode, .capabilities = AV_CODEC_CAP_DR1, + .wrapper_name = "libcelt", }; diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c index a0110da62b49a..677b11088b16c 100644 --- a/libavcodec/libfdk-aacdec.c +++ b/libavcodec/libfdk-aacdec.c @@ -385,4 +385,5 @@ AVCodec ff_libfdk_aac_decoder = { .priv_class = &fdk_aac_dec_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "libfdk", }; diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c index ca0f4bf72293c..d47137b227a6d 100644 --- a/libavcodec/libfdk-aacenc.c +++ b/libavcodec/libfdk-aacenc.c @@ -428,4 +428,5 @@ AVCodec ff_libfdk_aac_encoder = { .profiles = profiles, .supported_samplerates = aac_sample_rates, .channel_layouts = aac_channel_layout, + .wrapper_name = "libfdk", }; diff --git a/libavcodec/libgsmdec.c b/libavcodec/libgsmdec.c index a503215f679b0..89e1de0fed763 100644 --- a/libavcodec/libgsmdec.c +++ b/libavcodec/libgsmdec.c @@ -135,6 +135,7 @@ AVCodec ff_libgsm_decoder = { .decode = libgsm_decode_frame, .flush = libgsm_flush, .capabilities = AV_CODEC_CAP_DR1, + .wrapper_name = "libgsm", }; #endif #if CONFIG_LIBGSM_MS_DECODER @@ -149,5 +150,6 @@ AVCodec ff_libgsm_ms_decoder = { .decode = libgsm_decode_frame, .flush = libgsm_flush, .capabilities = AV_CODEC_CAP_DR1, + .wrapper_name = "libgsm", }; #endif diff --git a/libavcodec/libgsmenc.c b/libavcodec/libgsmenc.c index e25db95181009..c9e7ba056e1e4 100644 --- a/libavcodec/libgsmenc.c +++ b/libavcodec/libgsmenc.c @@ -126,6 +126,7 @@ AVCodec ff_libgsm_encoder = { .close = libgsm_encode_close, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .wrapper_name = "libgsm", }; #endif #if CONFIG_LIBGSM_MS_ENCODER @@ -139,5 +140,6 @@ AVCodec ff_libgsm_ms_encoder = { .close = libgsm_encode_close, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .wrapper_name = "libgsm", }; #endif diff --git a/libavcodec/libilbc.c b/libavcodec/libilbc.c index c4c054fa5d4f2..9a56cc8785476 100644 --- a/libavcodec/libilbc.c +++ b/libavcodec/libilbc.c @@ -193,4 +193,5 @@ AVCodec ff_libilbc_encoder = { AV_SAMPLE_FMT_NONE }, .defaults = ilbc_encode_defaults, .priv_class = &ilbc_enc_class, + .wrapper_name = "libbilbc", }; diff --git a/libavcodec/libkvazaar.c b/libavcodec/libkvazaar.c index 25e7b32f5f043..41a1bbb45e70a 100644 --- a/libavcodec/libkvazaar.c +++ b/libavcodec/libkvazaar.c @@ -305,4 +305,6 @@ AVCodec ff_libkvazaar_encoder = { .close = libkvazaar_close, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + + .wrapper_name = "libkvazaar", }; diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 5e26743f297db..ecdd2e334c6d4 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -349,4 +349,5 @@ AVCodec ff_libmp3lame_encoder = { 0 }, .priv_class = &libmp3lame_class, .defaults = libmp3lame_defaults, + .wrapper_name = "libmp3lame", }; diff --git a/libavcodec/libopencore-amr.c b/libavcodec/libopencore-amr.c index d509804315252..516f625720ff1 100644 --- a/libavcodec/libopencore-amr.c +++ b/libavcodec/libopencore-amr.c @@ -378,6 +378,7 @@ AVCodec ff_libopencore_amrwb_decoder = { .close = amr_wb_decode_close, .decode = amr_wb_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .wrapper_name = "libopencore_amrwb", }; #endif /* CONFIG_LIBOPENCORE_AMRWB_DECODER */ diff --git a/libavcodec/libopenh264dec.c b/libavcodec/libopenh264dec.c index d12e7151172a0..b7ed85d17596b 100644 --- a/libavcodec/libopenh264dec.c +++ b/libavcodec/libopenh264dec.c @@ -147,4 +147,5 @@ AVCodec ff_libopenh264_decoder = { .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .bsfs = "h264_mp4toannexb", + .wrapper_name = "libopenh264", }; diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index 1152d0036fd69..fdadb101f513a 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -301,4 +301,5 @@ AVCodec ff_libopenh264_encoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &class, + .wrapper_name = "libopenh264", }; diff --git a/libavcodec/libopenjpegdec.c b/libavcodec/libopenjpegdec.c index daf0a1c565fac..5e66cd99cc3c7 100644 --- a/libavcodec/libopenjpegdec.c +++ b/libavcodec/libopenjpegdec.c @@ -512,4 +512,5 @@ AVCodec ff_libopenjpeg_decoder = { .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .max_lowres = 31, .priv_class = &openjpeg_class, + .wrapper_name = "libopenjpeg", }; diff --git a/libavcodec/libopenjpegenc.c b/libavcodec/libopenjpegenc.c index 59fe52d64a232..7c7d0aa6b2a4c 100644 --- a/libavcodec/libopenjpegenc.c +++ b/libavcodec/libopenjpegenc.c @@ -778,4 +778,5 @@ AVCodec ff_libopenjpeg_encoder = { AV_PIX_FMT_NONE }, .priv_class = &openjpeg_class, + .wrapper_name = "libopenjpeg", }; diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c index 9b1e002cebc84..4f7f4755c242a 100644 --- a/libavcodec/libopusdec.c +++ b/libavcodec/libopusdec.c @@ -223,4 +223,5 @@ AVCodec ff_libopus_decoder = { .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .wrapper_name = "libopus", }; diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c index 3d88c296d3289..b449497d15fbe 100644 --- a/libavcodec/libopusenc.c +++ b/libavcodec/libopusenc.c @@ -566,4 +566,5 @@ AVCodec ff_libopus_encoder = { .supported_samplerates = libopus_sample_rates, .priv_class = &libopus_class, .defaults = libopus_defaults, + .wrapper_name = "libopus", }; diff --git a/libavcodec/librsvgdec.c b/libavcodec/librsvgdec.c index 77c771003ce04..e57070f8e44ec 100644 --- a/libavcodec/librsvgdec.c +++ b/libavcodec/librsvgdec.c @@ -124,4 +124,5 @@ AVCodec ff_librsvg_decoder = { .decode = librsvg_decode_frame, .priv_data_size = sizeof(LibRSVGContext), .capabilities = AV_CODEC_CAP_LOSSLESS | AV_CODEC_CAP_DR1, + .wrapper_name = "librsvg", }; diff --git a/libavcodec/libshine.c b/libavcodec/libshine.c index f4cf5981bcb79..7056fcd2e3d29 100644 --- a/libavcodec/libshine.c +++ b/libavcodec/libshine.c @@ -146,4 +146,5 @@ AVCodec ff_libshine_encoder = { .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, 0 }, + .wrapper_name = "libshine", }; diff --git a/libavcodec/libspeexdec.c b/libavcodec/libspeexdec.c index 044883af73860..d67c68c7f9243 100644 --- a/libavcodec/libspeexdec.c +++ b/libavcodec/libspeexdec.c @@ -200,4 +200,5 @@ AVCodec ff_libspeex_decoder = { .decode = libspeex_decode_frame, .flush = libspeex_decode_flush, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .wrapper_name = "libspeex", }; diff --git a/libavcodec/libspeexenc.c b/libavcodec/libspeexenc.c index 5264899fd7bfb..6a37dbc76cc28 100644 --- a/libavcodec/libspeexenc.c +++ b/libavcodec/libspeexenc.c @@ -365,4 +365,5 @@ AVCodec ff_libspeex_encoder = { .supported_samplerates = (const int[]){ 8000, 16000, 32000, 0 }, .priv_class = &speex_class, .defaults = defaults, + .wrapper_name = "libspeex", }; diff --git a/libavcodec/libtheoraenc.c b/libavcodec/libtheoraenc.c index d4c39283a60c8..16966ed433dc0 100644 --- a/libavcodec/libtheoraenc.c +++ b/libavcodec/libtheoraenc.c @@ -385,4 +385,5 @@ AVCodec ff_libtheora_encoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, + .wrapper_name = "libtheora", }; diff --git a/libavcodec/libtwolame.c b/libavcodec/libtwolame.c index 12d71e7acbb72..030f88868fb5b 100644 --- a/libavcodec/libtwolame.c +++ b/libavcodec/libtwolame.c @@ -226,4 +226,5 @@ AVCodec ff_libtwolame_encoder = { AV_CH_LAYOUT_STEREO, 0 }, .supported_samplerates = twolame_samplerates, + .wrapper_name = "libtwolame", }; diff --git a/libavcodec/libvo-amrwbenc.c b/libavcodec/libvo-amrwbenc.c index f7569408796be..77d0ccef15acf 100644 --- a/libavcodec/libvo-amrwbenc.c +++ b/libavcodec/libvo-amrwbenc.c @@ -152,4 +152,5 @@ AVCodec ff_libvo_amrwbenc_encoder = { .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .priv_class = &amrwb_class, + .wrapper_name = "libvo_amrwbenc", }; diff --git a/libavcodec/libvorbisenc.c b/libavcodec/libvorbisenc.c index 3ca5b55e8e617..f78f872fe2ead 100644 --- a/libavcodec/libvorbisenc.c +++ b/libavcodec/libvorbisenc.c @@ -377,4 +377,5 @@ AVCodec ff_libvorbis_encoder = { AV_SAMPLE_FMT_NONE }, .priv_class = &vorbis_class, .defaults = defaults, + .wrapper_name = "libvorbis", }; diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c index 2ae29d202a550..04f27d3396107 100644 --- a/libavcodec/libvpxdec.c +++ b/libavcodec/libvpxdec.c @@ -289,6 +289,7 @@ AVCodec ff_libvpx_vp8_decoder = { .close = vpx_free, .decode = vpx_decode, .capabilities = AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_DR1, + .wrapper_name = "libvpx", }; #endif /* CONFIG_LIBVPX_VP8_DECODER */ @@ -310,5 +311,6 @@ AVCodec ff_libvpx_vp9_decoder = { .capabilities = AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_DR1, .init_static_data = ff_vp9_init_static, .profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), + .wrapper_name = "libvpx", }; #endif /* CONFIG_LIBVPX_VP9_DECODER */ diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 9861e9d5ae164..d0bd1e997abd3 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -1199,6 +1199,7 @@ AVCodec ff_libvpx_vp8_encoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE }, .priv_class = &class_vp8, .defaults = defaults, + .wrapper_name = "libvpx", }; #endif /* CONFIG_LIBVPX_VP8_ENCODER */ @@ -1229,5 +1230,6 @@ AVCodec ff_libvpx_vp9_encoder = { .priv_class = &class_vp9, .defaults = defaults, .init_static_data = ff_vp9_init_static, + .wrapper_name = "libvpx", }; #endif /* CONFIG_LIBVPX_VP9_ENCODER */ diff --git a/libavcodec/libwavpackenc.c b/libavcodec/libwavpackenc.c index 6d5708985afde..e84b0748936d5 100644 --- a/libavcodec/libwavpackenc.c +++ b/libavcodec/libwavpackenc.c @@ -191,4 +191,5 @@ AVCodec ff_libwavpack_encoder = { .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, + .wrapper_name = "libwavpack", }; diff --git a/libavcodec/libwebpenc.c b/libavcodec/libwebpenc.c index 0bcf628e58076..48f45b6320852 100644 --- a/libavcodec/libwebpenc.c +++ b/libavcodec/libwebpenc.c @@ -109,4 +109,5 @@ AVCodec ff_libwebp_encoder = { }, .priv_class = &class, .defaults = libwebp_defaults, + .wrapper_name = "libwebp", }; diff --git a/libavcodec/libwebpenc_animencoder.c b/libavcodec/libwebpenc_animencoder.c index 91bf64ca8b8b0..7f35a0b93913d 100644 --- a/libavcodec/libwebpenc_animencoder.c +++ b/libavcodec/libwebpenc_animencoder.c @@ -148,4 +148,5 @@ AVCodec ff_libwebp_anim_encoder = { }, .priv_class = &class, .defaults = libwebp_defaults, + .wrapper_name = "libwebp", }; diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 9c67c91f33daf..e2455e18dec6a 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -1026,6 +1026,7 @@ AVCodec ff_libx264_encoder = { .init_static_data = X264_init_static, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "libx264", }; #endif @@ -1050,6 +1051,7 @@ AVCodec ff_libx264rgb_encoder = { .priv_class = &rgbclass, .defaults = x264_defaults, .pix_fmts = pix_fmts_8bit_rgb, + .wrapper_name = "libx264", }; #endif @@ -1076,5 +1078,6 @@ AVCodec ff_libx262_encoder = { .pix_fmts = pix_fmts_8bit, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "libx264", }; #endif diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 25ccb02fcb6b8..52ad2312a3d76 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -442,4 +442,5 @@ AVCodec ff_libx265_encoder = { .priv_class = &class, .defaults = x265_defaults, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .wrapper_name = "libx265", }; diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c index 865b5f62ef1d2..801a05dbb581a 100644 --- a/libavcodec/libxavs.c +++ b/libavcodec/libxavs.c @@ -478,4 +478,5 @@ AVCodec ff_libxavs_encoder = { .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &xavs_class, .defaults = xavs_defaults, + .wrapper_name = "libxavs", }; diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c index 5c05fa6d872ae..cdaae2094e57f 100644 --- a/libavcodec/libxvid.c +++ b/libavcodec/libxvid.c @@ -934,4 +934,5 @@ AVCodec ff_libxvid_encoder = { .priv_class = &xvid_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "libxvid", }; diff --git a/libavcodec/libzvbi-teletextdec.c b/libavcodec/libzvbi-teletextdec.c index 687b6af1293b0..30d05934305f2 100644 --- a/libavcodec/libzvbi-teletextdec.c +++ b/libavcodec/libzvbi-teletextdec.c @@ -573,4 +573,5 @@ AVCodec ff_libzvbi_teletext_decoder = { .capabilities = AV_CODEC_CAP_DELAY, .flush = teletext_flush, .priv_class= &teletext_class, + .wrapper_name = "libzvbi", }; diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 39f5cbc045044..1b5ae4ad59ccf 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -539,10 +539,11 @@ AVCodec ff_h264_mediacodec_decoder = { .decode = mediacodec_decode_frame, .flush = mediacodec_decode_flush, .close = mediacodec_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, .bsfs = "h264_mp4toannexb", .hw_configs = mediacodec_hw_configs, + .wrapper_name = "mediacodec", }; #endif @@ -557,10 +558,11 @@ AVCodec ff_hevc_mediacodec_decoder = { .decode = mediacodec_decode_frame, .flush = mediacodec_decode_flush, .close = mediacodec_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, .bsfs = "hevc_mp4toannexb", .hw_configs = mediacodec_hw_configs, + .wrapper_name = "mediacodec", }; #endif @@ -575,9 +577,10 @@ AVCodec ff_mpeg2_mediacodec_decoder = { .decode = mediacodec_decode_frame, .flush = mediacodec_decode_flush, .close = mediacodec_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, .hw_configs = mediacodec_hw_configs, + .wrapper_name = "mediacodec", }; #endif @@ -592,9 +595,10 @@ AVCodec ff_mpeg4_mediacodec_decoder = { .decode = mediacodec_decode_frame, .flush = mediacodec_decode_flush, .close = mediacodec_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, .hw_configs = mediacodec_hw_configs, + .wrapper_name = "mediacodec", }; #endif @@ -609,9 +613,10 @@ AVCodec ff_vp8_mediacodec_decoder = { .decode = mediacodec_decode_frame, .flush = mediacodec_decode_flush, .close = mediacodec_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, .hw_configs = mediacodec_hw_configs, + .wrapper_name = "mediacodec", }; #endif @@ -626,8 +631,9 @@ AVCodec ff_vp9_mediacodec_decoder = { .decode = mediacodec_decode_frame, .flush = mediacodec_decode_flush, .close = mediacodec_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, .hw_configs = mediacodec_hw_configs, + .wrapper_name = "mediacodec", }; #endif diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index b3f0cca4b5c0e..647a22ef7c07c 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -840,12 +840,13 @@ static const AVOption options[]={ .decode = ffmmal_decode, \ .flush = ffmmal_flush, \ .priv_class = &ffmmal_##NAME##_dec_class, \ - .capabilities = AV_CODEC_CAP_DELAY, \ + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \ .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, \ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MMAL, \ AV_PIX_FMT_YUV420P, \ AV_PIX_FMT_NONE}, \ .hw_configs = mmal_hw_configs, \ + .wrapper_name = "mmal", \ }; FFMMAL_DEC(h264, AV_CODEC_ID_H264) diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index c3b4bac7494dc..bc7bbcddeb73b 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -171,9 +171,10 @@ AVCodec ff_nvenc_encoder = { .priv_data_size = sizeof(NvencContext), .priv_class = &nvenc_class, .defaults = defaults, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = ff_nvenc_pix_fmts, + .wrapper_name = "nvenc", }; #endif @@ -199,9 +200,10 @@ AVCodec ff_nvenc_h264_encoder = { .priv_data_size = sizeof(NvencContext), .priv_class = &nvenc_h264_class, .defaults = defaults, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = ff_nvenc_pix_fmts, + .wrapper_name = "nvenc", }; #endif @@ -227,7 +229,8 @@ AVCodec ff_h264_nvenc_encoder = { .priv_data_size = sizeof(NvencContext), .priv_class = &h264_nvenc_class, .defaults = defaults, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = ff_nvenc_pix_fmts, + .wrapper_name = "nvenc", }; diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index 89e8c3e53a433..0df7eab8cd2b0 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -161,8 +161,9 @@ AVCodec ff_nvenc_hevc_encoder = { .priv_class = &nvenc_hevc_class, .defaults = defaults, .pix_fmts = ff_nvenc_pix_fmts, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "nvenc", }; #endif @@ -188,6 +189,7 @@ AVCodec ff_hevc_nvenc_encoder = { .priv_class = &hevc_nvenc_class, .defaults = defaults, .pix_fmts = ff_nvenc_pix_fmts, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "nvenc", }; diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c index 6b4fc5e36e961..5e0067335e882 100644 --- a/libavcodec/qsvdec_h2645.c +++ b/libavcodec/qsvdec_h2645.c @@ -211,7 +211,7 @@ AVCodec ff_hevc_qsv_decoder = { .decode = qsv_decode_frame, .flush = qsv_decode_flush, .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, .priv_class = &hevc_class, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_P010, @@ -219,6 +219,7 @@ AVCodec ff_hevc_qsv_decoder = { AV_PIX_FMT_NONE }, .hw_configs = ff_qsv_hw_configs, .bsfs = "hevc_mp4toannexb", + .wrapper_name = "qsv", }; #endif @@ -245,7 +246,7 @@ AVCodec ff_h264_qsv_decoder = { .decode = qsv_decode_frame, .flush = qsv_decode_flush, .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, .priv_class = &class, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_P010, @@ -253,5 +254,6 @@ AVCodec ff_h264_qsv_decoder = { AV_PIX_FMT_NONE }, .hw_configs = ff_qsv_hw_configs, .bsfs = "h264_mp4toannexb", + .wrapper_name = "qsv", }; #endif diff --git a/libavcodec/qsvdec_other.c b/libavcodec/qsvdec_other.c index f7691f95bf298..416e4c81647bb 100644 --- a/libavcodec/qsvdec_other.c +++ b/libavcodec/qsvdec_other.c @@ -176,12 +176,13 @@ AVCodec ff_mpeg2_qsv_decoder = { .decode = qsv_decode_frame, .flush = qsv_decode_flush, .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, .priv_class = &mpeg2_qsv_class, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, .hw_configs = ff_qsv_hw_configs, + .wrapper_name = "qsv", }; #endif @@ -203,12 +204,13 @@ AVCodec ff_vc1_qsv_decoder = { .decode = qsv_decode_frame, .flush = qsv_decode_flush, .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, .priv_class = &vc1_qsv_class, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, .hw_configs = ff_qsv_hw_configs, + .wrapper_name = "qsv", }; #endif @@ -230,11 +232,12 @@ AVCodec ff_vp8_qsv_decoder = { .decode = qsv_decode_frame, .flush = qsv_decode_flush, .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, .priv_class = &vp8_qsv_class, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, .hw_configs = ff_qsv_hw_configs, + .wrapper_name = "qsv", }; #endif diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index 3242062b40047..77fb2823d40c9 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -175,7 +175,7 @@ AVCodec ff_h264_qsv_encoder = { .init = qsv_enc_init, .encode2 = qsv_enc_frame, .close = qsv_enc_close, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_P010, AV_PIX_FMT_QSV, @@ -183,4 +183,5 @@ AVCodec ff_h264_qsv_encoder = { .priv_class = &class, .defaults = qsv_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "qsv", }; diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index f132a26c1ad89..4339b316a3d5a 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -277,7 +277,7 @@ AVCodec ff_hevc_qsv_encoder = { .init = qsv_enc_init, .encode2 = qsv_enc_frame, .close = qsv_enc_close, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_P010, AV_PIX_FMT_QSV, @@ -285,4 +285,5 @@ AVCodec ff_hevc_qsv_encoder = { .priv_class = &class, .defaults = qsv_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "qsv", }; diff --git a/libavcodec/qsvenc_jpeg.c b/libavcodec/qsvenc_jpeg.c index 731ec9a014b2d..c18fe91940bb3 100644 --- a/libavcodec/qsvenc_jpeg.c +++ b/libavcodec/qsvenc_jpeg.c @@ -83,9 +83,10 @@ AVCodec ff_mjpeg_qsv_encoder = { .init = qsv_enc_init, .encode2 = qsv_enc_frame, .close = qsv_enc_close, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, .priv_class = &class, + .wrapper_name = "qsv", }; diff --git a/libavcodec/qsvenc_mpeg2.c b/libavcodec/qsvenc_mpeg2.c index 5b583fb4911a3..a7427d81099a9 100644 --- a/libavcodec/qsvenc_mpeg2.c +++ b/libavcodec/qsvenc_mpeg2.c @@ -104,11 +104,12 @@ AVCodec ff_mpeg2_qsv_encoder = { .init = qsv_enc_init, .encode2 = qsv_enc_frame, .close = qsv_enc_close, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, .priv_class = &class, .defaults = qsv_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "qsv", }; diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c index 4ec61cbb35eb6..fa522ce2edce9 100644 --- a/libavcodec/rkmppdec.c +++ b/libavcodec/rkmppdec.c @@ -588,12 +588,13 @@ static const AVCodecHWConfigInternal *rkmpp_hw_configs[] = { .receive_frame = rkmpp_receive_frame, \ .flush = rkmpp_flush, \ .priv_class = &rkmpp_##NAME##_dec_class, \ - .capabilities = AV_CODEC_CAP_DELAY, \ + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \ .caps_internal = AV_CODEC_CAP_AVOID_PROBING, \ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ AV_PIX_FMT_NONE}, \ .hw_configs = rkmpp_hw_configs, \ .bsfs = BSFS, \ + .wrapper_name = "rkmpp", \ }; RKMPP_DEC(h264, AV_CODEC_ID_H264, "h264_mp4toannexb") diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index 958cdc522b91a..c4ea20ea834c8 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -215,6 +215,8 @@ AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \ .receive_frame = v4l2_receive_frame,\ .close = ff_v4l2_m2m_codec_end,\ .bsfs = bsf_name, \ + .capabilities = AV_CODEC_CAP_HARDWARE, \ + .wrapper_name = "v4l2m2m", \ }; M2MDEC(h264, "H.264", AV_CODEC_ID_H264, "h264_mp4toannexb"); diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c index 76ce85fdaac5e..f62ce7cdb5a34 100644 --- a/libavcodec/v4l2_m2m_enc.c +++ b/libavcodec/v4l2_m2m_enc.c @@ -335,6 +335,8 @@ AVCodec ff_ ## NAME ## _v4l2m2m_encoder = { \ .send_frame = v4l2_send_frame,\ .receive_packet = v4l2_receive_packet,\ .close = ff_v4l2_m2m_codec_end,\ + .capabilities = AV_CODEC_CAP_HARDWARE, \ + .wrapper_name = "v4l2m2m", \ }; M2MENC(mpeg4,"MPEG4", AV_CODEC_ID_MPEG4); diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 6940823b8ebfd..a7f9a602533be 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -1089,10 +1089,11 @@ AVCodec ff_h264_vaapi_encoder = { .encode2 = &ff_vaapi_encode2, .close = &vaapi_encode_h264_close, .priv_class = &vaapi_encode_h264_class, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .defaults = vaapi_encode_h264_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 8e98b0230d0f4..f3b4f6c7e26af 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -1018,10 +1018,11 @@ AVCodec ff_hevc_vaapi_encoder = { .encode2 = &ff_vaapi_encode2, .close = &vaapi_encode_h265_close, .priv_class = &vaapi_encode_h265_class, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .defaults = vaapi_encode_h265_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c index 2cbf7925f248f..c949e89646110 100644 --- a/libavcodec/vaapi_encode_mjpeg.c +++ b/libavcodec/vaapi_encode_mjpeg.c @@ -422,9 +422,11 @@ AVCodec ff_mjpeg_vaapi_encoder = { .encode2 = &ff_vaapi_encode2, .close = &ff_vaapi_encode_close, .priv_class = &vaapi_encode_mjpeg_class, + .capabilities = AV_CODEC_CAP_HARDWARE, .defaults = vaapi_encode_mjpeg_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_mpeg2.c b/libavcodec/vaapi_encode_mpeg2.c index 02eca30dc5126..4537955c40a3a 100644 --- a/libavcodec/vaapi_encode_mpeg2.c +++ b/libavcodec/vaapi_encode_mpeg2.c @@ -669,10 +669,11 @@ AVCodec ff_mpeg2_vaapi_encoder = { .init = &vaapi_encode_mpeg2_init, .encode2 = &ff_vaapi_encode2, .close = &vaapi_encode_mpeg2_close, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .defaults = vaapi_encode_mpeg2_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_vp8.c b/libavcodec/vaapi_encode_vp8.c index 423f7483e8866..b4c5521d1f7c3 100644 --- a/libavcodec/vaapi_encode_vp8.c +++ b/libavcodec/vaapi_encode_vp8.c @@ -260,10 +260,11 @@ AVCodec ff_vp8_vaapi_encoder = { .encode2 = &ff_vaapi_encode2, .close = &ff_vaapi_encode_close, .priv_class = &vaapi_encode_vp8_class, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .defaults = vaapi_encode_vp8_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c index a987d1cd71924..9108699ac383a 100644 --- a/libavcodec/vaapi_encode_vp9.c +++ b/libavcodec/vaapi_encode_vp9.c @@ -304,10 +304,11 @@ AVCodec ff_vp9_vaapi_encoder = { .encode2 = &ff_vaapi_encode2, .close = &ff_vaapi_encode_close, .priv_class = &vaapi_encode_vp9_class, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .defaults = vaapi_encode_vp9_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .wrapper_name = "vaapi", }; diff --git a/libavcodec/version.h b/libavcodec/version.h index 3b5c3000becd0..b529f00227bae 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 6 -#define LIBAVCODEC_VERSION_MICRO 103 +#define LIBAVCODEC_VERSION_MINOR 7 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 086beb41fcde3..7796a685c25ee 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -2599,8 +2599,9 @@ AVCodec ff_hevc_videotoolbox_encoder = { .init = vtenc_init, .encode2 = vtenc_frame, .close = vtenc_close, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .priv_class = &hevc_videotoolbox_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "videotoolbox", }; From 1c76134fe37ac20695627e3f5ce1f2bbf1245fcc Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Mon, 11 Dec 2017 22:35:18 +0530 Subject: [PATCH 1342/2557] avfilter/drawbox+drawgrid - add option to prevent overwriting of source pixels If the user-supplied color in drawbox and drawgrid filters is non-opaque, the box & grid painting overwrites the input's pixels (including alpha). Users typically expect the alpha of the specified color to only act as a key for compositing on top of the main input. Added option allows users to select between replacement and composition. Tested and documented. --- doc/filters.texi | 10 ++++++++++ libavfilter/vf_drawbox.c | 7 +++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index f304bbf9491aa..af0c3be2ec7d1 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -7146,6 +7146,11 @@ The expression which sets the thickness of the box edge. A value of @code{fill} will create a filled box. Default value is @code{3}. See below for the list of accepted constants. + +@item replace +Applicable if the input has alpha. With value @code{1}, the pixels of the painted box +will overwrite the video's color and alpha pixels. +Default is @code{0}, which composites the box onto the input, leaving the video's alpha intact. @end table The parameters for @var{x}, @var{y}, @var{w} and @var{h} and @var{t} are expressions containing the @@ -7243,6 +7248,11 @@ video with inverted luma. The expression which sets the thickness of the grid line. Default value is @code{1}. See below for the list of accepted constants. + +@item replace +Applicable if the input has alpha. With @code{1} the pixels of the painted grid +will overwrite the video's color and alpha pixels. +Default is @code{0}, which composites the grid onto the input, leaving the video's alpha intact. @end table The parameters for @var{x}, @var{y}, @var{w} and @var{h} and @var{t} are expressions containing the diff --git a/libavfilter/vf_drawbox.c b/libavfilter/vf_drawbox.c index d351846594c44..c9cb63dbd1344 100644 --- a/libavfilter/vf_drawbox.c +++ b/libavfilter/vf_drawbox.c @@ -80,6 +80,7 @@ typedef struct DrawBoxContext { char *w_expr, *h_expr; ///< expression for width and height char *t_expr; ///< expression for thickness int have_alpha; + int replace; } DrawBoxContext; static const int NUM_EXPR_EVALS = 5; @@ -213,7 +214,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) int plane, x, y, xb = s->x, yb = s->y; unsigned char *row[4]; - if (s->have_alpha) { + if (s->have_alpha && s->replace) { for (y = FFMAX(yb, 0); y < frame->height && y < (yb + s->h); y++) { row[0] = frame->data[0] + y * frame->linesize[0]; row[3] = frame->data[3] + y * frame->linesize[3]; @@ -286,6 +287,7 @@ static const AVOption drawbox_options[] = { { "c", "set color of the box", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS }, { "thickness", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, CHAR_MIN, CHAR_MAX, FLAGS }, { "t", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "replace", "replace color & alpha", OFFSET(replace), AV_OPT_TYPE_BOOL, { .i64=0 }, 0, 1, FLAGS }, { NULL } }; @@ -354,7 +356,7 @@ static int drawgrid_filter_frame(AVFilterLink *inlink, AVFrame *frame) int plane, x, y; uint8_t *row[4]; - if (drawgrid->have_alpha) { + if (drawgrid->have_alpha && drawgrid->replace) { for (y = 0; y < frame->height; y++) { row[0] = frame->data[0] + y * frame->linesize[0]; row[3] = frame->data[3] + y * frame->linesize[3]; @@ -418,6 +420,7 @@ static const AVOption drawgrid_options[] = { { "c", "set color of the grid", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS }, { "thickness", "set grid line thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, {.str="1"}, CHAR_MIN, CHAR_MAX, FLAGS }, { "t", "set grid line thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, {.str="1"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "replace", "replace color & alpha", OFFSET(replace), AV_OPT_TYPE_BOOL, { .i64=0 }, 0, 1, FLAGS }, { NULL } }; From 5e03eea673a9da2253ed15152e46b1422b35d145 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 14 Dec 2017 02:02:55 +0100 Subject: [PATCH 1343/2557] avcodec/vp9: mark frame as finished on decode_tiles() failure Fixes deadlock with framethreads Fixes: Netflix_Aerial_1080p_60fps_8bit_420.y4m.vp9.noaltref.webm.ivf.s69372_r01-05_b6-.ivf Fixes: Netflix_Aerial_1080p_60fps_10bit_420.y4m.vp9.noaltref.webm.ivf.s149104_r01-05_b6-.ivf Fixes: ducks_take_off_444_720p50.y4m.vp9.webm.ivf.s107375_r01-05_b6-.ivf Reported-by: James Zern Reviewed-by: James Zern Signed-off-by: Michael Niedermayer --- libavcodec/vp9.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index 6241f01de1175..0fac638ec943d 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -1644,8 +1644,10 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif { ret = decode_tiles(avctx, data, size); - if (ret < 0) + if (ret < 0) { + ff_thread_report_progress(&s->s.frames[CUR_FRAME].tf, INT_MAX, 0); return ret; + } } // Sum all counts fields into td[0].counts for tile threading From 2d131fc31bcd3a6cd0ddee689d1e4fc9741dc32e Mon Sep 17 00:00:00 2001 From: Steven Robertson Date: Thu, 14 Dec 2017 11:52:45 -0800 Subject: [PATCH 1344/2557] avformat/movenc: Add support for more colorspaces With FCPX 10.4, Apple has expanded the set of colorspace, primaries, and trc flags officially supported in QuickTime files. The expanded set matches the codepoints used in ffmpeg and many other specs. Signed-off-by: Michael Niedermayer --- libavformat/movenc.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 901577401eb53..a597b0853d86c 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1809,23 +1809,30 @@ static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track) ffio_wfourcc(pb, "nclc"); switch (track->par->color_primaries) { case AVCOL_PRI_BT709: avio_wb16(pb, 1); break; + case AVCOL_PRI_BT470BG: avio_wb16(pb, 5); break; case AVCOL_PRI_SMPTE170M: case AVCOL_PRI_SMPTE240M: avio_wb16(pb, 6); break; - case AVCOL_PRI_BT470BG: avio_wb16(pb, 5); break; + case AVCOL_PRI_BT2020: avio_wb16(pb, 9); break; + case AVCOL_PRI_SMPTE431: avio_wb16(pb, 11); break; + case AVCOL_PRI_SMPTE432: avio_wb16(pb, 12); break; default: avio_wb16(pb, 2); } switch (track->par->color_trc) { - case AVCOL_TRC_BT709: avio_wb16(pb, 1); break; - case AVCOL_TRC_SMPTE170M: avio_wb16(pb, 1); break; // remapped - case AVCOL_TRC_SMPTE240M: avio_wb16(pb, 7); break; - default: avio_wb16(pb, 2); + case AVCOL_TRC_BT709: avio_wb16(pb, 1); break; + case AVCOL_TRC_SMPTE170M: avio_wb16(pb, 1); break; // remapped + case AVCOL_TRC_SMPTE240M: avio_wb16(pb, 7); break; + case AVCOL_TRC_SMPTEST2084: avio_wb16(pb, 16); break; + case AVCOL_TRC_SMPTE428: avio_wb16(pb, 17); break; + case AVCOL_TRC_ARIB_STD_B67: avio_wb16(pb, 18); break; + default: avio_wb16(pb, 2); } switch (track->par->color_space) { - case AVCOL_SPC_BT709: avio_wb16(pb, 1); break; + case AVCOL_SPC_BT709: avio_wb16(pb, 1); break; case AVCOL_SPC_BT470BG: - case AVCOL_SPC_SMPTE170M: avio_wb16(pb, 6); break; - case AVCOL_SPC_SMPTE240M: avio_wb16(pb, 7); break; - default: avio_wb16(pb, 2); + case AVCOL_SPC_SMPTE170M: avio_wb16(pb, 6); break; + case AVCOL_SPC_SMPTE240M: avio_wb16(pb, 7); break; + case AVCOL_SPC_BT2020_NCL: avio_wb16(pb, 9); break; + default: avio_wb16(pb, 2); } if (track->mode == MODE_MP4) { From 49dced9fd0c8a8d2f3676533914fda7417435df2 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Thu, 14 Dec 2017 16:49:55 +0100 Subject: [PATCH 1345/2557] avfilter/x86/vf_interlace : avoid crash when data are unaligned ticket 6491 --- libavfilter/x86/vf_interlace.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/x86/vf_interlace.asm b/libavfilter/x86/vf_interlace.asm index 7c0065d4d9489..f83538872df1b 100644 --- a/libavfilter/x86/vf_interlace.asm +++ b/libavfilter/x86/vf_interlace.asm @@ -40,8 +40,8 @@ SECTION .text pcmpeq%1 m6, m6 .loop: - mova m0, [mrefq+hq] - mova m1, [mrefq+hq+mmsize] + movu m0, [mrefq+hq] + movu m1, [mrefq+hq+mmsize] pavg%1 m0, [prefq+hq] pavg%1 m1, [prefq+hq+mmsize] pxor m0, m6 From 3c6dc270355f27645cf931fae1ed2dc1405507f8 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Thu, 14 Dec 2017 17:55:11 +0100 Subject: [PATCH 1346/2557] avfilter/x86/vf_interlace : avfilter/x86/vf_interlace : fix crash when using unaligned data in low_pass complex related to ticket 6491 --- libavfilter/x86/vf_interlace.asm | 47 +++++++++++++++++--------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/libavfilter/x86/vf_interlace.asm b/libavfilter/x86/vf_interlace.asm index f83538872df1b..06b269828a27e 100644 --- a/libavfilter/x86/vf_interlace.asm +++ b/libavfilter/x86/vf_interlace.asm @@ -73,8 +73,8 @@ cglobal lowpass_line_16, 5, 5, 7, dst, h, src, mref, pref cglobal lowpass_line_complex, 5, 5, 8, dst, h, src, mref, pref pxor m7, m7 .loop: - mova m0, [srcq+mrefq] - mova m2, [srcq+prefq] + movu m0, [srcq+mrefq] + movu m2, [srcq+prefq] mova m1, m0 mova m3, m2 punpcklbw m0, m7 @@ -85,7 +85,7 @@ cglobal lowpass_line_complex, 5, 5, 8, dst, h, src, mref, pref paddw m1, m3 mova m6, m0 mova m5, m1 - mova m2, [srcq] + movu m2, [srcq] mova m3, m2 punpcklbw m2, m7 punpckhbw m3, m7 @@ -100,8 +100,8 @@ cglobal lowpass_line_complex, 5, 5, 8, dst, h, src, mref, pref pcmpgtw m6, m2 pcmpgtw m5, m3 packsswb m6, m5 - mova m2, [srcq+mrefq*2] - mova m4, [srcq+prefq*2] + movu m2, [srcq+mrefq*2] + movu m4, [srcq+prefq*2] mova m3, m2 mova m5, m4 punpcklbw m2, m7 @@ -118,8 +118,9 @@ cglobal lowpass_line_complex, 5, 5, 8, dst, h, src, mref, pref psrlw m1, 3 packuswb m0, m1 mova m1, m0 - pmaxub m0, [srcq] - pminub m1, [srcq] + movu m2, [srcq] + pmaxub m0, m2 + pminub m1, m2 pand m0, m6 pandn m6, m1 por m0, m6 @@ -134,18 +135,18 @@ REP_RET cglobal lowpass_line_complex_12, 5, 5, 8, 16, dst, h, src, mref, pref, clip_max movd m7, DWORD clip_maxm SPLATW m7, m7, 0 - mova [rsp], m7 + movu [rsp], m7 .loop: - mova m0, [srcq+mrefq] - mova m1, [srcq+mrefq+mmsize] - mova m2, [srcq+prefq] - mova m3, [srcq+prefq+mmsize] + movu m0, [srcq+mrefq] + movu m1, [srcq+mrefq+mmsize] + movu m2, [srcq+prefq] + movu m3, [srcq+prefq+mmsize] paddw m0, m2 paddw m1, m3 mova m6, m0 mova m7, m1 - mova m2, [srcq] - mova m3, [srcq+mmsize] + movu m2, [srcq] + movu m3, [srcq+mmsize] paddw m0, m2 paddw m1, m3 psllw m2, 1 @@ -156,10 +157,10 @@ cglobal lowpass_line_complex_12, 5, 5, 8, 16, dst, h, src, mref, pref, clip_max psllw m1, 1 pcmpgtw m6, m2 pcmpgtw m7, m3 - mova m2, [srcq+2*mrefq] - mova m3, [srcq+2*mrefq+mmsize] - mova m4, [srcq+2*prefq] - mova m5, [srcq+2*prefq+mmsize] + movu m2, [srcq+2*mrefq] + movu m3, [srcq+2*mrefq+mmsize] + movu m4, [srcq+2*prefq] + movu m5, [srcq+2*prefq+mmsize] paddw m2, m4 paddw m3, m5 paddw m0, [pw_4] @@ -172,10 +173,12 @@ cglobal lowpass_line_complex_12, 5, 5, 8, 16, dst, h, src, mref, pref, clip_max pminsw m1, [rsp] mova m2, m0 mova m3, m1 - pmaxsw m0, [srcq] - pmaxsw m1, [srcq+mmsize] - pminsw m2, [srcq] - pminsw m3, [srcq+mmsize] + movu m4, [srcq] + pmaxsw m0, m4 + pminsw m2, m4 + movu m4, [srcq + mmsize] + pmaxsw m1, m4 + pminsw m3, m4 pand m0, m6 pand m1, m7 pandn m6, m2 From deceb7d9aeb7d00bc0078638925a38614c3f607b Mon Sep 17 00:00:00 2001 From: Karthick J Date: Fri, 15 Dec 2017 21:24:08 +0800 Subject: [PATCH 1347/2557] avformat/hlsenc: Call avio_flush during persistent http connections Since close is not called, during http persistent connection, flush needs to be called so that output is written on time. Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index fdf614bdd1937..30d0285c32059 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -266,6 +266,8 @@ static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename if (!http_base_proto || !hls->http_persistent || hls->key_info_file || hls->encrypt) { ff_format_io_close(s, pb); + } else { + avio_flush(*pb); } } From 6ae18228cd89b93bbdd2e42a8d181335d981051d Mon Sep 17 00:00:00 2001 From: Karthick J Date: Fri, 15 Dec 2017 22:08:31 +0800 Subject: [PATCH 1348/2557] avformat/hlsenc: Handle NULL input in IO open and close utility functions Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 30d0285c32059..af9d949501e35 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -246,7 +246,7 @@ static int is_http_proto(char *filename) { static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, AVDictionary **options) { HLSContext *hls = s->priv_data; - int http_base_proto = is_http_proto(filename); + int http_base_proto = filename ? is_http_proto(filename) : 0; int err = AVERROR_MUXER_NOT_FOUND; if (!*pb || !http_base_proto || !hls->http_persistent) { err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options); @@ -262,7 +262,7 @@ static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) { HLSContext *hls = s->priv_data; - int http_base_proto = is_http_proto(filename); + int http_base_proto = filename ? is_http_proto(filename) : 0; if (!http_base_proto || !hls->http_persistent || hls->key_info_file || hls->encrypt) { ff_format_io_close(s, pb); From b2d27d912ba91450c410e4dcaa9ed28cb66ad9a8 Mon Sep 17 00:00:00 2001 From: Karthick J Date: Fri, 15 Dec 2017 22:11:12 +0800 Subject: [PATCH 1349/2557] avformat/hlsenc: Extend persistent http connections to playlists Before this patch persistent http connections would work only for media segments. The playlists were still opening a new connection everytime. This patch extends persistent http connections to playlists as well. Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 56 +++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index af9d949501e35..e3442c368fa8d 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -203,6 +203,8 @@ typedef struct HLSContext { char *master_pl_name; unsigned int master_publish_rate; int http_persistent; + AVIOContext *m3u8_out; + AVIOContext *sub_m3u8_out; } HLSContext; static int mkdir_p(const char *path) { @@ -1085,7 +1087,6 @@ static int create_master_playlist(AVFormatContext *s, HLSContext *hls = s->priv_data; VariantStream *vs; AVStream *vid_st, *aud_st; - AVIOContext *master_pb = 0; AVDictionary *options = NULL; unsigned int i, j; int m3u8_name_size, ret, bandwidth; @@ -1106,8 +1107,7 @@ static int create_master_playlist(AVFormatContext *s, set_http_options(s, &options, hls); - ret = s->io_open(s, &master_pb, hls->master_m3u8_url, AVIO_FLAG_WRITE,\ - &options); + ret = hlsenc_io_open(s, &hls->m3u8_out, hls->master_m3u8_url, &options); av_dict_free(&options); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to open master play list file '%s'\n", @@ -1115,7 +1115,7 @@ static int create_master_playlist(AVFormatContext *s, goto fail; } - ff_hls_write_playlist_version(master_pb, hls->version); + ff_hls_write_playlist_version(hls->m3u8_out, hls->version); /* For variant streams with video add #EXT-X-STREAM-INF tag with attributes*/ for (i = 0; i < hls->nb_varstreams; i++) { @@ -1156,7 +1156,7 @@ static int create_master_playlist(AVFormatContext *s, bandwidth += aud_st->codecpar->bit_rate; bandwidth += bandwidth / 10; - ff_hls_write_stream_info(vid_st, master_pb, bandwidth, m3u8_rel_name); + ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name); av_freep(&m3u8_rel_name); } @@ -1164,7 +1164,7 @@ static int create_master_playlist(AVFormatContext *s, if(ret >=0) hls->master_m3u8_created = 1; av_freep(&m3u8_rel_name); - ff_format_io_close(s, &master_pb); + hlsenc_io_close(s, &hls->m3u8_out, hls->master_m3u8_url); return ret; } @@ -1174,8 +1174,6 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) HLSSegment *en; int target_duration = 0; int ret = 0; - AVIOContext *out = NULL; - AVIOContext *sub_out = NULL; char temp_filename[1024]; int64_t sequence = FFMAX(hls->start_sequence, vs->sequence - vs->nb_entries); const char *proto = avio_find_protocol_name(s->filename); @@ -1207,7 +1205,7 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) set_http_options(s, &options, hls); snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", vs->m3u8_name); - if ((ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, &options)) < 0) + if ((ret = hlsenc_io_open(s, &hls->m3u8_out, temp_filename, &options)) < 0) goto fail; for (en = vs->segments; en; en = en->next) { @@ -1216,67 +1214,67 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) } vs->discontinuity_set = 0; - ff_hls_write_playlist_header(out, hls->version, hls->allowcache, + ff_hls_write_playlist_header(hls->m3u8_out, hls->version, hls->allowcache, target_duration, sequence, hls->pl_type); if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && vs->discontinuity_set==0 ){ - avio_printf(out, "#EXT-X-DISCONTINUITY\n"); + avio_printf(hls->m3u8_out, "#EXT-X-DISCONTINUITY\n"); vs->discontinuity_set = 1; } if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) { - avio_printf(out, "#EXT-X-INDEPENDENT-SEGMENTS\n"); + avio_printf(hls->m3u8_out, "#EXT-X-INDEPENDENT-SEGMENTS\n"); } for (en = vs->segments; en; en = en->next) { if ((hls->encrypt || hls->key_info_file) && (!key_uri || strcmp(en->key_uri, key_uri) || av_strcasecmp(en->iv_string, iv_string))) { - avio_printf(out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri); + avio_printf(hls->m3u8_out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri); if (*en->iv_string) - avio_printf(out, ",IV=0x%s", en->iv_string); - avio_printf(out, "\n"); + avio_printf(hls->m3u8_out, ",IV=0x%s", en->iv_string); + avio_printf(hls->m3u8_out, "\n"); key_uri = en->key_uri; iv_string = en->iv_string; } if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == vs->segments)) { - ff_hls_write_init_file(out, vs->fmp4_init_filename, + ff_hls_write_init_file(hls->m3u8_out, vs->fmp4_init_filename, hls->flags & HLS_SINGLE_FILE, en->size, en->pos); } - ret = ff_hls_write_file_entry(out, en->discont, byterange_mode, - en->duration, hls->flags & HLS_ROUND_DURATIONS, - en->size, en->pos, vs->baseurl, - en->filename, prog_date_time_p); + ret = ff_hls_write_file_entry(hls->m3u8_out, en->discont, byterange_mode, + en->duration, hls->flags & HLS_ROUND_DURATIONS, + en->size, en->pos, vs->baseurl, + en->filename, prog_date_time_p); if (ret < 0) { av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n"); } } if (last && (hls->flags & HLS_OMIT_ENDLIST)==0) - ff_hls_write_end_list(out); + ff_hls_write_end_list(hls->m3u8_out); if( vs->vtt_m3u8_name ) { - if ((ret = s->io_open(s, &sub_out, vs->vtt_m3u8_name, AVIO_FLAG_WRITE, &options)) < 0) + if ((ret = hlsenc_io_open(s, &hls->sub_m3u8_out, vs->vtt_m3u8_name, &options)) < 0) goto fail; - ff_hls_write_playlist_header(sub_out, hls->version, hls->allowcache, + ff_hls_write_playlist_header(hls->sub_m3u8_out, hls->version, hls->allowcache, target_duration, sequence, PLAYLIST_TYPE_NONE); for (en = vs->segments; en; en = en->next) { - ret = ff_hls_write_file_entry(sub_out, 0, byterange_mode, - en->duration, 0, en->size, en->pos, - vs->baseurl, en->sub_filename, NULL); + ret = ff_hls_write_file_entry(hls->sub_m3u8_out, 0, byterange_mode, + en->duration, 0, en->size, en->pos, + vs->baseurl, en->sub_filename, NULL); if (ret < 0) { av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n"); } } if (last) - ff_hls_write_end_list(sub_out); + ff_hls_write_end_list(hls->sub_m3u8_out); } fail: av_dict_free(&options); - ff_format_io_close(s, &out); - ff_format_io_close(s, &sub_out); + hlsenc_io_close(s, &hls->m3u8_out, temp_filename); + hlsenc_io_close(s, &hls->sub_m3u8_out, vs->vtt_m3u8_name); if (ret >= 0 && use_rename) ff_rename(temp_filename, vs->m3u8_name, s); From d228d52f1cc958e25f3017945ad06382ab1db7a6 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Thu, 30 Nov 2017 07:53:53 +0800 Subject: [PATCH 1350/2557] lavc/vp8: Support resolution changes in the VP8 decoder hwaccel Use the following command to reproduce this issue: make fate-vp8-size-change HWACCEL="vaapi -vaapi_device \ /dev/dri/renderD128 -hwaccel_output_format yuv420p" SAMPLES=../fate-suite/. At the same time, reconstruct the public logic as a function. Signed-off-by: Yun Zhou Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- libavcodec/vp8.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index 471c0bb89e244..7f71a75e4ba06 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -167,6 +167,22 @@ static VP8Frame *vp8_find_free_buffer(VP8Context *s) return frame; } +static enum AVPixelFormat get_pixel_format(VP8Context *s) +{ + enum AVPixelFormat pix_fmts[] = { +#if CONFIG_VP8_VAAPI_HWACCEL + AV_PIX_FMT_VAAPI, +#endif +#if CONFIG_VP8_NVDEC_HWACCEL + AV_PIX_FMT_CUDA, +#endif + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE, + }; + + return ff_get_format(s->avctx, pix_fmts); +} + static av_always_inline int update_dimensions(VP8Context *s, int width, int height, int is_vp7) { @@ -182,6 +198,13 @@ int update_dimensions(VP8Context *s, int width, int height, int is_vp7) return ret; } + if (!s->actually_webp && !is_vp7) { + s->pix_fmt = get_pixel_format(s); + if (s->pix_fmt < 0) + return AVERROR(EINVAL); + avctx->pix_fmt = s->pix_fmt; + } + s->mb_width = (s->avctx->coded_width + 15) / 16; s->mb_height = (s->avctx->coded_height + 15) / 16; @@ -2598,18 +2621,7 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (s->actually_webp) { // avctx->pix_fmt already set in caller. } else if (!is_vp7 && s->pix_fmt == AV_PIX_FMT_NONE) { - enum AVPixelFormat pix_fmts[] = { -#if CONFIG_VP8_VAAPI_HWACCEL - AV_PIX_FMT_VAAPI, -#endif -#if CONFIG_VP8_NVDEC_HWACCEL - AV_PIX_FMT_CUDA, -#endif - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_NONE, - }; - - s->pix_fmt = ff_get_format(s->avctx, pix_fmts); + s->pix_fmt = get_pixel_format(s); if (s->pix_fmt < 0) { ret = AVERROR(EINVAL); goto err; From 07e1bd7e2d7b63da6b36162eecb2b445d797ba0a Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Fri, 15 Dec 2017 16:53:13 +0000 Subject: [PATCH 1351/2557] doc/libav-merge: Remove VAAPI VP8 decode hwaccel merge note Done in 9f00fa536938130e3c7ad2640a61795770d419a1 and 40b75a943bcb6a4af00c44ef6e52cbfc3e6580d8. --- doc/libav-merge.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/libav-merge.txt b/doc/libav-merge.txt index 5eed8ce777b5f..a41d87995fff1 100644 --- a/doc/libav-merge.txt +++ b/doc/libav-merge.txt @@ -95,7 +95,6 @@ Stuff that didn't reach the codebase: - 0cef06df0 checkasm: add HEVC MC tests - e7078e842 hevcdsp: add x86 SIMD for MC - 7993ec19a hevc: Add hevc_get_pixel_4/8/12/16/24/32/48/64 -- VAAPI VP8 decode hwaccel (currently under review: http://ffmpeg.org/pipermail/ffmpeg-devel/2017-February/thread.html#207348) - Removal of the custom atomic API (5cc0057f49, see http://ffmpeg.org/pipermail/ffmpeg-devel/2017-March/209003.html) - new bitstream reader (see http://ffmpeg.org/pipermail/ffmpeg-devel/2017-April/209609.html) - use of the bsf instead of our parser for vp9 superframes (see fa1749dd34) From 5450972be4a79f173744ba5cda88a2a17ccdec28 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 15 Dec 2017 14:38:55 -0300 Subject: [PATCH 1352/2557] doc/libav-merge: remove line about VP9 superframe parsing It was addressed in a5679933c1b8b6bef5c5c3eb7c70d06c695066cf, 0c162854c1fa2a1e43ce5588b67842675f45e3c7 and 5a366f9770dd7b02b0721b2857d6baa96acdb0af. Signed-off-by: James Almer --- doc/libav-merge.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/libav-merge.txt b/doc/libav-merge.txt index a41d87995fff1..2477d90e7b9a0 100644 --- a/doc/libav-merge.txt +++ b/doc/libav-merge.txt @@ -97,7 +97,6 @@ Stuff that didn't reach the codebase: - 7993ec19a hevc: Add hevc_get_pixel_4/8/12/16/24/32/48/64 - Removal of the custom atomic API (5cc0057f49, see http://ffmpeg.org/pipermail/ffmpeg-devel/2017-March/209003.html) - new bitstream reader (see http://ffmpeg.org/pipermail/ffmpeg-devel/2017-April/209609.html) -- use of the bsf instead of our parser for vp9 superframes (see fa1749dd34) - use av_cpu_max_align() instead of hardcoding alignment requirements (see https://ffmpeg.org/pipermail/ffmpeg-devel/2017-September/215834.html) - f44ec22e0 lavc: use av_cpu_max_align() instead of hardcoding alignment requirements - 4de220d2e frame: allow align=0 (meaning automatic) for av_frame_get_buffer() From e4d9f05ca79909e2853834c8f80a52bc9cf0e6b6 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Sun, 3 Dec 2017 17:32:21 -0800 Subject: [PATCH 1353/2557] lavu/hwcontext: add AV_HWDEVICE_TYPE_MEDIACODEC Signed-off-by: Matthieu Bouron --- doc/APIchanges | 4 +++ libavutil/Makefile | 2 ++ libavutil/hwcontext.c | 4 +++ libavutil/hwcontext.h | 1 + libavutil/hwcontext_internal.h | 1 + libavutil/hwcontext_mediacodec.c | 50 ++++++++++++++++++++++++++++++++ libavutil/hwcontext_mediacodec.h | 36 +++++++++++++++++++++++ libavutil/version.h | 2 +- 8 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 libavutil/hwcontext_mediacodec.c create mode 100644 libavutil/hwcontext_mediacodec.h diff --git a/doc/APIchanges b/doc/APIchanges index b4451ab193a63..811568196d0d2 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2017-10-21 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavu 56.6.100 - hwcontext.h hwcontext_mediacodec.h + Add AV_HWDEVICE_TYPE_MEDIACODEC and a new installed header with + MediaCodec-specific hwcontext definitions. + 2017-xx-xx - xxxxxxc - lavc 58.7.100 - avcodec.h Add AV_CODEC_CAP_HARDWARE, AV_CODEC_CAP_HYBRID, and AVCodec.wrapper_name, and mark all AVCodecs accordingly. diff --git a/libavutil/Makefile b/libavutil/Makefile index 721784086c1db..66b894d66e749 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -37,6 +37,7 @@ HEADERS = adler32.h \ hwcontext_drm.h \ hwcontext_dxva2.h \ hwcontext_qsv.h \ + hwcontext_mediacodec.h \ hwcontext_vaapi.h \ hwcontext_videotoolbox.h \ hwcontext_vdpau.h \ @@ -166,6 +167,7 @@ OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o OBJS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.o OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o +OBJS-$(CONFIG_MEDIACODEC) += hwcontext_mediacodec.o OBJS += $(COMPAT_OBJS:%=../compat/%) diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index f47158f811ca4..31ac12807bfdb 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -55,6 +55,9 @@ static const HWContextType * const hw_table[] = { #endif #if CONFIG_VIDEOTOOLBOX &ff_hwcontext_type_videotoolbox, +#endif +#if CONFIG_MEDIACODEC + &ff_hwcontext_type_mediacodec, #endif NULL, }; @@ -69,6 +72,7 @@ static const char *const hw_type_names[] = { [AV_HWDEVICE_TYPE_VAAPI] = "vaapi", [AV_HWDEVICE_TYPE_VDPAU] = "vdpau", [AV_HWDEVICE_TYPE_VIDEOTOOLBOX] = "videotoolbox", + [AV_HWDEVICE_TYPE_MEDIACODEC] = "mediacodec", }; enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name) diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h index 8d27b987dff9e..f5a4b62387747 100644 --- a/libavutil/hwcontext.h +++ b/libavutil/hwcontext.h @@ -35,6 +35,7 @@ enum AVHWDeviceType { AV_HWDEVICE_TYPE_D3D11VA, AV_HWDEVICE_TYPE_DRM, AV_HWDEVICE_TYPE_OPENCL, + AV_HWDEVICE_TYPE_MEDIACODEC, }; typedef struct AVHWDeviceInternal AVHWDeviceInternal; diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h index 28ff0f9ee68c6..332062ddaa06d 100644 --- a/libavutil/hwcontext_internal.h +++ b/libavutil/hwcontext_internal.h @@ -166,5 +166,6 @@ extern const HWContextType ff_hwcontext_type_qsv; extern const HWContextType ff_hwcontext_type_vaapi; extern const HWContextType ff_hwcontext_type_vdpau; extern const HWContextType ff_hwcontext_type_videotoolbox; +extern const HWContextType ff_hwcontext_type_mediacodec; #endif /* AVUTIL_HWCONTEXT_INTERNAL_H */ diff --git a/libavutil/hwcontext_mediacodec.c b/libavutil/hwcontext_mediacodec.c new file mode 100644 index 0000000000000..b0d8993e15888 --- /dev/null +++ b/libavutil/hwcontext_mediacodec.c @@ -0,0 +1,50 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "buffer.h" +#include "common.h" +#include "hwcontext.h" +#include "hwcontext_internal.h" +#include "hwcontext_mediacodec.h" + +static int mc_device_create(AVHWDeviceContext *ctx, const char *device, + AVDictionary *opts, int flags) +{ + if (device && device[0]) { + av_log(ctx, AV_LOG_ERROR, "Device selection unsupported.\n"); + return AVERROR_UNKNOWN; + } + + return 0; +} + +const HWContextType ff_hwcontext_type_mediacodec = { + .type = AV_HWDEVICE_TYPE_MEDIACODEC, + .name = "mediacodec", + + .device_hwctx_size = sizeof(AVMediaCodecDeviceContext), + + .device_create = mc_device_create, + + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_MEDIACODEC, + AV_PIX_FMT_NONE + }, +}; diff --git a/libavutil/hwcontext_mediacodec.h b/libavutil/hwcontext_mediacodec.h new file mode 100644 index 0000000000000..101a9806d59e3 --- /dev/null +++ b/libavutil/hwcontext_mediacodec.h @@ -0,0 +1,36 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_MEDIACODEC_H +#define AVUTIL_HWCONTEXT_MEDIACODEC_H + +/** + * MediaCodec details. + * + * Allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVMediaCodecDeviceContext { + /** + * android/view/Surface handle, to be filled by the user. + * + * This is the default surface used by decoders on this device. + */ + void *surface; +} AVMediaCodecDeviceContext; + +#endif /* AVUTIL_HWCONTEXT_MEDIACODEC_H */ diff --git a/libavutil/version.h b/libavutil/version.h index 498b5d8414fa5..9ae9768d4d80f 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 5 +#define LIBAVUTIL_VERSION_MINOR 6 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 8bf4e6d3ce25723832625dddbf1c06ab20ab5828 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Sun, 3 Dec 2017 17:32:22 -0800 Subject: [PATCH 1354/2557] lavc/mediacodec: use AVMediaCodecDeviceContext hw_device_ctx if set Signed-off-by: Matthieu Bouron --- doc/APIchanges | 3 +++ libavcodec/mediacodecdec.c | 5 +++-- libavcodec/mediacodecdec_common.c | 14 +++++++++++++- libavcodec/version.h | 2 +- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 811568196d0d2..da444ffb7c0d9 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavc 58.8.100 - avcodec.h + The MediaCodec decoders now support AVCodecContext.hw_device_ctx. + 2017-xx-xx - xxxxxxx - lavu 56.6.100 - hwcontext.h hwcontext_mediacodec.h Add AV_HWDEVICE_TYPE_MEDIACODEC and a new installed header with MediaCodec-specific hwcontext definitions. diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 1b5ae4ad59ccf..b698ceaef92df 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -520,8 +520,9 @@ static const AVCodecHWConfigInternal *mediacodec_hw_configs[] = { &(const AVCodecHWConfigInternal) { .public = { .pix_fmt = AV_PIX_FMT_MEDIACODEC, - .methods = AV_CODEC_HW_CONFIG_METHOD_AD_HOC, - .device_type = AV_HWDEVICE_TYPE_NONE, + .methods = AV_CODEC_HW_CONFIG_METHOD_AD_HOC | + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX, + .device_type = AV_HWDEVICE_TYPE_MEDIACODEC, }, .hwaccel = NULL, }, diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index cb2f6ae5e5d3f..a9147f3a086cb 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -24,6 +24,7 @@ #include #include "libavutil/common.h" +#include "libavutil/hwcontext_mediacodec.h" #include "libavutil/mem.h" #include "libavutil/log.h" #include "libavutil/pixfmt.h" @@ -476,7 +477,18 @@ int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s, if (pix_fmt == AV_PIX_FMT_MEDIACODEC) { AVMediaCodecContext *user_ctx = avctx->hwaccel_context; - if (user_ctx && user_ctx->surface) { + if (avctx->hw_device_ctx) { + AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data); + if (device_ctx->type == AV_HWDEVICE_TYPE_MEDIACODEC) { + if (device_ctx->hwctx) { + AVMediaCodecDeviceContext *mediacodec_ctx = (AVMediaCodecDeviceContext *)device_ctx->hwctx; + s->surface = ff_mediacodec_surface_ref(mediacodec_ctx->surface, avctx); + av_log(avctx, AV_LOG_INFO, "Using surface %p\n", s->surface); + } + } + } + + if (!s->surface && user_ctx && user_ctx->surface) { s->surface = ff_mediacodec_surface_ref(user_ctx->surface, avctx); av_log(avctx, AV_LOG_INFO, "Using surface %p\n", s->surface); } diff --git a/libavcodec/version.h b/libavcodec/version.h index b529f00227bae..d55de897972d7 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 7 +#define LIBAVCODEC_VERSION_MINOR 8 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From f3cffd121b990717996d8ddd646bd555c1db135b Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Wed, 13 Dec 2017 13:49:58 +0100 Subject: [PATCH 1355/2557] lavc/mediacodec_wrapper: factorize MediaCodec creation functions --- libavcodec/mediacodec_wrapper.c | 162 ++++++-------------------------- 1 file changed, 29 insertions(+), 133 deletions(-) diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c index f34450a6d8fd1..329a5eb8960d5 100644 --- a/libavcodec/mediacodec_wrapper.c +++ b/libavcodec/mediacodec_wrapper.c @@ -1132,13 +1132,18 @@ static int codec_init_static_fields(FFAMediaCodec *codec) return ret; } -FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name) +#define CREATE_CODEC_BY_NAME 0 +#define CREATE_DECODER_BY_TYPE 1 +#define CREATE_ENCODER_BY_TYPE 2 + +static inline FFAMediaCodec *codec_create(int method, const char *arg) { int ret = -1; JNIEnv *env = NULL; FFAMediaCodec *codec = NULL; - jstring codec_name = NULL; + jstring jarg = NULL; jobject object = NULL; + jmethodID create_id = NULL; codec = av_mallocz(sizeof(FFAMediaCodec)); if (!codec) { @@ -1156,77 +1161,23 @@ FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name) goto fail; } - codec_name = ff_jni_utf_chars_to_jstring(env, name, codec); - if (!codec_name) { - goto fail; - } - - object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_by_codec_name_id, codec_name); - if (ff_jni_exception_check(env, 1, codec) < 0) { - goto fail; - } - - codec->object = (*env)->NewGlobalRef(env, object); - if (!codec->object) { - goto fail; - } - - if (codec_init_static_fields(codec) < 0) { - goto fail; - } - - if (codec->jfields.get_input_buffer_id && codec->jfields.get_output_buffer_id) { - codec->has_get_i_o_buffer = 1; - } - - ret = 0; -fail: - if (codec_name) { - (*env)->DeleteLocalRef(env, codec_name); - } - - if (object) { - (*env)->DeleteLocalRef(env, object); - } - - if (ret < 0) { - ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec); - av_freep(&codec); - } - - return codec; -} - -FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime) -{ - int ret = -1; - JNIEnv *env = NULL; - FFAMediaCodec *codec = NULL; - jstring mime_type = NULL; - jobject object = NULL; - - codec = av_mallocz(sizeof(FFAMediaCodec)); - if (!codec) { - return NULL; - } - codec->class = &amediacodec_class; - - env = ff_jni_get_env(codec); - if (!env) { - av_freep(&codec); - return NULL; - } - - if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) { + jarg = ff_jni_utf_chars_to_jstring(env, arg, codec); + if (!jarg) { goto fail; } - mime_type = ff_jni_utf_chars_to_jstring(env, mime, codec); - if (!mime_type) { - goto fail; + switch (method) { + case CREATE_CODEC_BY_NAME: create_id = codec->jfields.create_by_codec_name_id; break; + case CREATE_DECODER_BY_TYPE: create_id = codec->jfields.create_decoder_by_type_id; break; + case CREATE_ENCODER_BY_TYPE: create_id = codec->jfields.create_encoder_by_type_id; break; + default: + av_assert0(0); } - object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_decoder_by_type_id, mime_type); + object = (*env)->CallStaticObjectMethod(env, + codec->jfields.mediacodec_class, + create_id, + jarg); if (ff_jni_exception_check(env, 1, codec) < 0) { goto fail; } @@ -1246,8 +1197,8 @@ FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime) ret = 0; fail: - if (mime_type) { - (*env)->DeleteLocalRef(env, mime_type); + if (jarg) { + (*env)->DeleteLocalRef(env, jarg); } if (object) { @@ -1262,70 +1213,15 @@ FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime) return codec; } -FFAMediaCodec* ff_AMediaCodec_createEncoderByType(const char *mime) -{ - int ret = -1; - JNIEnv *env = NULL; - FFAMediaCodec *codec = NULL; - jstring mime_type = NULL; - jobject object = NULL; +#define DECLARE_FF_AMEDIACODEC_CREATE_FUNC(name, method) \ +FFAMediaCodec *ff_AMediaCodec_##name(const char *arg) \ +{ \ + return codec_create(method, arg); \ +} \ - codec = av_mallocz(sizeof(FFAMediaCodec)); - if (!codec) { - return NULL; - } - codec->class = &amediacodec_class; - - env = ff_jni_get_env(codec); - if (!env) { - av_freep(&codec); - return NULL; - } - - if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) { - goto fail; - } - - mime_type = ff_jni_utf_chars_to_jstring(env, mime, codec); - if (!mime_type) { - goto fail; - } - - object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_encoder_by_type_id, mime_type); - if (ff_jni_exception_check(env, 1, codec) < 0) { - goto fail; - } - - codec->object = (*env)->NewGlobalRef(env, object); - if (!codec->object) { - goto fail; - } - - if (codec_init_static_fields(codec) < 0) { - goto fail; - } - - if (codec->jfields.get_input_buffer_id && codec->jfields.get_output_buffer_id) { - codec->has_get_i_o_buffer = 1; - } - - ret = 0; -fail: - if (mime_type) { - (*env)->DeleteLocalRef(env, mime_type); - } - - if (object) { - (*env)->DeleteLocalRef(env, object); - } - - if (ret < 0) { - ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec); - av_freep(&codec); - } - - return codec; -} +DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createCodecByName, CREATE_CODEC_BY_NAME) +DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createDecoderByType, CREATE_DECODER_BY_TYPE) +DECLARE_FF_AMEDIACODEC_CREATE_FUNC(createEncoderByType, CREATE_ENCODER_BY_TYPE) int ff_AMediaCodec_delete(FFAMediaCodec* codec) { From 1f1207145a0f2d26e5e3525bea6cc417a3ec39cf Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Sat, 16 Dec 2017 00:16:02 +0100 Subject: [PATCH 1356/2557] lavc/mediacodec_wrapper: fix potential jni global reference leak --- libavcodec/mediacodec_wrapper.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c index 329a5eb8960d5..d9f0e27a7d894 100644 --- a/libavcodec/mediacodec_wrapper.c +++ b/libavcodec/mediacodec_wrapper.c @@ -1206,6 +1206,9 @@ static inline FFAMediaCodec *codec_create(int method, const char *arg) } if (ret < 0) { + if (codec->object) { + (*env)->DeleteGlobalRef(env, codec->object); + } ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec); av_freep(&codec); } From ee2dfa34a25e0c5bf85f464be64e5bc78489abf9 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 28 Oct 2017 23:15:23 +0200 Subject: [PATCH 1357/2557] libavcodec/magicyuvenc : fix warning --- libavcodec/magicyuvenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/magicyuvenc.c b/libavcodec/magicyuvenc.c index a30922f57077a..c784221e1cf07 100644 --- a/libavcodec/magicyuvenc.c +++ b/libavcodec/magicyuvenc.c @@ -337,7 +337,7 @@ static int encode_table(AVCodecContext *avctx, uint8_t *dst, int width, int height, PutBitContext *pb, HuffEntry *he) { - PTable counts[256] = { 0 }; + PTable counts[256] = { {0} }; int i; count_usage(dst, width, height, counts); From dc08caa8f727fe32b55eaaaf6771b14f1bed92a0 Mon Sep 17 00:00:00 2001 From: wang-bin Date: Fri, 15 Dec 2017 15:05:13 +0800 Subject: [PATCH 1358/2557] configure: fix probing armv6zk clang reports 6kz: https://reviews.llvm.org/D14568 Signed-off-by: Michael Niedermayer --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index d5bbb5b7a9915..6065f01c5ceaf 100755 --- a/configure +++ b/configure @@ -4521,6 +4521,7 @@ elif enabled arm; then elif check_arm_arch 6J; then echo armv6j elif check_arm_arch 6K; then echo armv6k elif check_arm_arch 6Z; then echo armv6z + elif check_arm_arch 6KZ; then echo armv6zk elif check_arm_arch 6ZK; then echo armv6zk elif check_arm_arch 6T2; then echo armv6t2 elif check_arm_arch 7; then echo armv7 From d29f784a54f2c91a0cdd3a2cc3bb000a99244f49 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 1 Aug 2017 12:34:44 +0200 Subject: [PATCH 1359/2557] avfilter/vf_overlay: add premultiplied alpha mode Signed-off-by: Paul B Mahol --- doc/filters.texi | 4 + libavfilter/vf_overlay.c | 162 +++++++++++++++++++++++++++++++++------ 2 files changed, 141 insertions(+), 25 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index af0c3be2ec7d1..da6cb9da7748b 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -11338,6 +11338,10 @@ Default value is @samp{yuv420}. @item repeatlast See @ref{framesync}. + +@item alpha +Set format of alpha of the overlaid video, it can be @var{straight} or +@var{premultiplied}. Default is @var{straight}. @end table The @option{x}, and @option{y} expressions can contain the following diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index 5bf3d66cf1f2b..a7d3906016996 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -109,6 +109,7 @@ typedef struct OverlayContext { uint8_t overlay_rgba_map[4]; uint8_t overlay_has_alpha; int format; ///< OverlayFormat + int alpha_format; int eval_mode; ///< EvalMode FFFrameSync fs; @@ -401,9 +402,10 @@ static int config_output(AVFilterLink *outlink) * Blend image in src to destination buffer dst at position (x, y). */ -static void blend_image_packed_rgb(AVFilterContext *ctx, +static av_always_inline void blend_image_packed_rgb(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, - int main_has_alpha, int x, int y) + int main_has_alpha, int x, int y, + int is_straight) { OverlayContext *s = ctx->priv; int i, imax, j, jmax; @@ -454,9 +456,9 @@ static void blend_image_packed_rgb(AVFilterContext *ctx, default: // main_value = main_value * (1 - alpha) + overlay_value * alpha // since alpha is in the range 0-255, the result must divided by 255 - d[dr] = FAST_DIV255(d[dr] * (255 - alpha) + S[sr] * alpha); - d[dg] = FAST_DIV255(d[dg] * (255 - alpha) + S[sg] * alpha); - d[db] = FAST_DIV255(d[db] * (255 - alpha) + S[sb] * alpha); + d[dr] = is_straight ? FAST_DIV255(d[dr] * (255 - alpha) + S[sr] * alpha) : FAST_DIV255(d[dr] * (255 - alpha) + S[sr]); + d[dg] = is_straight ? FAST_DIV255(d[dg] * (255 - alpha) + S[sg] * alpha) : FAST_DIV255(d[dr] * (255 - alpha) + S[sr]); + d[db] = is_straight ? FAST_DIV255(d[db] * (255 - alpha) + S[sb] * alpha) : FAST_DIV255(d[dr] * (255 - alpha) + S[sr]); } if (main_has_alpha) { switch (alpha) { @@ -487,7 +489,9 @@ static av_always_inline void blend_plane(AVFilterContext *ctx, int main_has_alpha, int dst_plane, int dst_offset, - int dst_step) + int dst_step, + int straight, + int yuv) { int src_wp = AV_CEIL_RSHIFT(src_w, hsub); int src_hp = AV_CEIL_RSHIFT(src_h, vsub); @@ -546,7 +550,14 @@ static av_always_inline void blend_plane(AVFilterContext *ctx, alpha_d = da[0]; alpha = UNPREMULTIPLY_ALPHA(alpha, alpha_d); } - *d = FAST_DIV255(*d * (255 - alpha) + *s * alpha); + if (straight) { + *d = FAST_DIV255(*d * (255 - alpha) + *s * alpha); + } else { + if (i && yuv) + *d = av_clip(FAST_DIV255((*d - 128) * (255 - alpha)) + *s - 128, -128, 128) + 128; + else + *d = FFMIN(FAST_DIV255(*d * (255 - alpha)) + *s, 255); + } s++; d += dst_step; da += 1 << hsub; @@ -605,7 +616,8 @@ static av_always_inline void blend_image_yuv(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int hsub, int vsub, int main_has_alpha, - int x, int y) + int x, int y, + int is_straight) { OverlayContext *s = ctx->priv; const int src_w = src->width; @@ -614,11 +626,11 @@ static av_always_inline void blend_image_yuv(AVFilterContext *ctx, const int dst_h = dst->height; blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 0, 0, 0, x, y, main_has_alpha, - s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, s->main_desc->comp[0].step); + s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, s->main_desc->comp[0].step, is_straight, 1); blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 1, hsub, vsub, x, y, main_has_alpha, - s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, s->main_desc->comp[1].step); + s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, s->main_desc->comp[1].step, is_straight, 1); blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 2, hsub, vsub, x, y, main_has_alpha, - s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, s->main_desc->comp[2].step); + s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, s->main_desc->comp[2].step, is_straight, 1); if (main_has_alpha) alpha_composite(src, dst, src_w, src_h, dst_w, dst_h, x, y); @@ -628,7 +640,8 @@ static av_always_inline void blend_image_planar_rgb(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int hsub, int vsub, int main_has_alpha, - int x, int y) + int x, int y, + int is_straight) { OverlayContext *s = ctx->priv; const int src_w = src->width; @@ -637,11 +650,11 @@ static av_always_inline void blend_image_planar_rgb(AVFilterContext *ctx, const int dst_h = dst->height; blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 0, 0, 0, x, y, main_has_alpha, - s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, s->main_desc->comp[1].step); + s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, s->main_desc->comp[1].step, is_straight, 0); blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 1, hsub, vsub, x, y, main_has_alpha, - s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, s->main_desc->comp[2].step); + s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, s->main_desc->comp[2].step, is_straight, 0); blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 2, hsub, vsub, x, y, main_has_alpha, - s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, s->main_desc->comp[0].step); + s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, s->main_desc->comp[0].step, is_straight, 0); if (main_has_alpha) alpha_composite(src, dst, src_w, src_h, dst_w, dst_h, x, y); @@ -649,52 +662,102 @@ static av_always_inline void blend_image_planar_rgb(AVFilterContext *ctx, static void blend_image_yuv420(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_yuv(ctx, dst, src, 1, 1, 0, x, y); + blend_image_yuv(ctx, dst, src, 1, 1, 0, x, y, 1); } static void blend_image_yuva420(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_yuv(ctx, dst, src, 1, 1, 1, x, y); + blend_image_yuv(ctx, dst, src, 1, 1, 1, x, y, 1); } static void blend_image_yuv422(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_yuv(ctx, dst, src, 1, 0, 0, x, y); + blend_image_yuv(ctx, dst, src, 1, 0, 0, x, y, 1); } static void blend_image_yuva422(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_yuv(ctx, dst, src, 1, 0, 1, x, y); + blend_image_yuv(ctx, dst, src, 1, 0, 1, x, y, 1); } static void blend_image_yuv444(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_yuv(ctx, dst, src, 0, 0, 0, x, y); + blend_image_yuv(ctx, dst, src, 0, 0, 0, x, y, 1); } static void blend_image_yuva444(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_yuv(ctx, dst, src, 0, 0, 1, x, y); + blend_image_yuv(ctx, dst, src, 0, 0, 1, x, y, 1); } static void blend_image_gbrp(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_planar_rgb(ctx, dst, src, 0, 0, 0, x, y); + blend_image_planar_rgb(ctx, dst, src, 0, 0, 0, x, y, 1); } static void blend_image_gbrap(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_planar_rgb(ctx, dst, src, 0, 0, 1, x, y); + blend_image_planar_rgb(ctx, dst, src, 0, 0, 1, x, y, 1); +} + +static void blend_image_yuv420_pm(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_yuv(ctx, dst, src, 1, 1, 0, x, y, 0); +} + +static void blend_image_yuva420_pm(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_yuv(ctx, dst, src, 1, 1, 1, x, y, 0); +} + +static void blend_image_yuv422_pm(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_yuv(ctx, dst, src, 1, 0, 0, x, y, 0); +} + +static void blend_image_yuva422_pm(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_yuv(ctx, dst, src, 1, 0, 1, x, y, 0); +} + +static void blend_image_yuv444_pm(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_yuv(ctx, dst, src, 0, 0, 0, x, y, 0); +} + +static void blend_image_yuva444_pm(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_yuv(ctx, dst, src, 0, 0, 1, x, y, 0); +} + +static void blend_image_gbrp_pm(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_planar_rgb(ctx, dst, src, 0, 0, 0, x, y, 0); +} + +static void blend_image_gbrap_pm(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_planar_rgb(ctx, dst, src, 0, 0, 1, x, y, 0); } static void blend_image_rgb(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_packed_rgb(ctx, dst, src, 0, x, y); + blend_image_packed_rgb(ctx, dst, src, 0, x, y, 0); } static void blend_image_rgba(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_packed_rgb(ctx, dst, src, 1, x, y); + blend_image_packed_rgb(ctx, dst, src, 1, x, y, 0); +} + +static void blend_image_rgb_pm(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_packed_rgb(ctx, dst, src, 0, x, y, 1); +} + +static void blend_image_rgba_pm(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) +{ + blend_image_packed_rgb(ctx, dst, src, 1, x, y, 1); } static int config_input_main(AVFilterLink *inlink) @@ -754,6 +817,52 @@ static int config_input_main(AVFilterLink *inlink) } break; } + + if (!s->alpha_format) + return 0; + + switch (s->format) { + case OVERLAY_FORMAT_YUV420: + s->blend_image = s->main_has_alpha ? blend_image_yuva420_pm : blend_image_yuv420_pm; + break; + case OVERLAY_FORMAT_YUV422: + s->blend_image = s->main_has_alpha ? blend_image_yuva422_pm : blend_image_yuv422_pm; + break; + case OVERLAY_FORMAT_YUV444: + s->blend_image = s->main_has_alpha ? blend_image_yuva444_pm : blend_image_yuv444_pm; + break; + case OVERLAY_FORMAT_RGB: + s->blend_image = s->main_has_alpha ? blend_image_rgba_pm : blend_image_rgb_pm; + break; + case OVERLAY_FORMAT_GBRP: + s->blend_image = s->main_has_alpha ? blend_image_gbrap_pm : blend_image_gbrp_pm; + break; + case OVERLAY_FORMAT_AUTO: + switch (inlink->format) { + case AV_PIX_FMT_YUVA420P: + s->blend_image = blend_image_yuva420_pm; + break; + case AV_PIX_FMT_YUVA422P: + s->blend_image = blend_image_yuva422_pm; + break; + case AV_PIX_FMT_YUVA444P: + s->blend_image = blend_image_yuva444_pm; + break; + case AV_PIX_FMT_ARGB: + case AV_PIX_FMT_RGBA: + case AV_PIX_FMT_BGRA: + case AV_PIX_FMT_ABGR: + s->blend_image = blend_image_rgba_pm; + break; + case AV_PIX_FMT_GBRAP: + s->blend_image = blend_image_gbrap_pm; + break; + default: + av_assert0(0); + break; + } + break; + } return 0; } @@ -835,6 +944,9 @@ static const AVOption overlay_options[] = { { "gbrp", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_GBRP}, .flags = FLAGS, .unit = "format" }, { "auto", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_AUTO}, .flags = FLAGS, .unit = "format" }, { "repeatlast", "repeat overlay of the last overlay frame", OFFSET(fs.opt_repeatlast), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, + { "alpha", "alpha format", OFFSET(alpha_format), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "alpha_format" }, + { "straight", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, .flags = FLAGS, .unit = "alpha_format" }, + { "premultiplied", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, .flags = FLAGS, .unit = "alpha_format" }, { NULL } }; From 439fbb9c8b2a90e97c44c7c57245e01ca84c865d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 15 Dec 2017 13:06:30 +0100 Subject: [PATCH 1360/2557] avcodec/hevcdsp_template: Fix undefined shift in put_hevc_qpel_bi_w_hv() Fixes: runtime error: left shift of negative value -3 Fixes: 4524/clusterfuzz-testcase-minimized-6055590120914944 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevcdsp_template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/hevcdsp_template.c b/libavcodec/hevcdsp_template.c index 0623cfad89688..4017af8eb0b18 100644 --- a/libavcodec/hevcdsp_template.c +++ b/libavcodec/hevcdsp_template.c @@ -1051,7 +1051,7 @@ static void FUNC(put_hevc_qpel_bi_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uin for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = av_clip_pixel(((QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) * wx1 + src2[x] * wx0 + - ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); + ((ox0 + ox1 + 1) * (1 << log2Wd))) >> (log2Wd + 1)); tmp += MAX_PB_SIZE; dst += dststride; src2 += MAX_PB_SIZE; From 991ef6e5b9a6a9d95e274ff6bff52db1c82b3808 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 15 Dec 2017 17:50:12 +0100 Subject: [PATCH 1361/2557] avcodec/hevc_sei: Fix integer overflows in decode_nal_sei_message() Fixes: signed integer overflow: 2147483520 + 255 cannot be represented in type 'int' Fixes: 4554/clusterfuzz-testcase-minimized-4843714515042304 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevc_sei.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 8dd975508ac9f..c59bd4321e272 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -324,11 +324,15 @@ static int decode_nal_sei_message(GetBitContext *gb, void *logctx, HEVCSEI *s, av_log(logctx, AV_LOG_DEBUG, "Decoding SEI\n"); while (byte == 0xFF) { + if (get_bits_left(gb) < 16 || payload_type > INT_MAX - 255) + return AVERROR_INVALIDDATA; byte = get_bits(gb, 8); payload_type += byte; } byte = 0xFF; while (byte == 0xFF) { + if (get_bits_left(gb) < 8 + 8LL*payload_size) + return AVERROR_INVALIDDATA; byte = get_bits(gb, 8); payload_size += byte; } From 0ee143558d55b590774dba69cff5a16eda089a4d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 15 Dec 2017 18:17:13 +0100 Subject: [PATCH 1362/2557] avcodec/hevc_cabac: Fix integer overflow in ff_hevc_cu_qp_delta_abs() Fixes: signed integer overflow: 2147483647 + 1073741824 cannot be represented in type 'int' Fixes: 4555/clusterfuzz-testcase-minimized-4505532481142784 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevc_cabac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c index 853fd3f72297c..5b5da1165a786 100644 --- a/libavcodec/hevc_cabac.c +++ b/libavcodec/hevc_cabac.c @@ -646,8 +646,10 @@ int ff_hevc_cu_qp_delta_abs(HEVCContext *s) suffix_val += 1 << k; k++; } - if (k == CABAC_MAX_BIN) + if (k == CABAC_MAX_BIN) { av_log(s->avctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", k); + return AVERROR_INVALIDDATA; + } while (k--) suffix_val += get_cabac_bypass(&s->HEVClc->cc) << k; From 387ee1d6aa651e07e95ffe00ca4bfd14873613ad Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sat, 4 Nov 2017 15:45:16 +0100 Subject: [PATCH 1363/2557] libavformat: LibreSSL (libtls) support Signed-off-by: sfan5 --- Changelog | 1 + configure | 16 ++- doc/protocols.texi | 2 +- libavformat/Makefile | 1 + libavformat/tls_libtls.c | 207 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 221 insertions(+), 6 deletions(-) create mode 100644 libavformat/tls_libtls.c diff --git a/Changelog b/Changelog index d60cf7b03d8f7..ee48876128118 100644 --- a/Changelog +++ b/Changelog @@ -26,6 +26,7 @@ version : - video fillborders filter - video setrange filter - nsp demuxer +- support LibreSSL (via libtls) version 3.4: diff --git a/configure b/configure index 6065f01c5ceaf..2f7db05faae01 100755 --- a/configure +++ b/configure @@ -214,7 +214,7 @@ External library support: --enable-gmp enable gmp, needed for rtmp(t)e support if openssl or librtmp is not used [no] --enable-gnutls enable gnutls, needed for https support - if openssl is not used [no] + if openssl or libtls is not used [no] --disable-iconv disable iconv [autodetect] --enable-jni enable JNI support [no] --enable-ladspa enable LADSPA audio filtering [no] @@ -259,6 +259,8 @@ External library support: --enable-libssh enable SFTP protocol via libssh [no] --enable-libtesseract enable Tesseract, needed for ocr filter [no] --enable-libtheora enable Theora encoding via libtheora [no] + --enable-libtls enable LibreSSL (via libtls), needed for https support + if openssl or gnutls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] @@ -292,7 +294,7 @@ External library support: --enable-opencl enable OpenCL processing [no] --enable-opengl enable OpenGL rendering [no] --enable-openssl enable openssl, needed for https support - if gnutls is not used [no] + if gnutls or libtls is not used [no] --disable-sndio disable sndio support [autodetect] --disable-schannel disable SChannel SSP, needed for TLS support on Windows if openssl and gnutls are not used [autodetect] @@ -1563,6 +1565,7 @@ EXTERNAL_LIBRARY_NONFREE_LIST=" libndi_newtek libfdk_aac openssl + libtls " EXTERNAL_LIBRARY_VERSION3_LIST=" @@ -3143,6 +3146,7 @@ librtmpt_protocol_deps="librtmp" librtmpte_protocol_deps="librtmp" libsmbclient_protocol_deps="libsmbclient gplv3" libssh_protocol_deps="libssh" +libtls_conflict="openssl gnutls" mmsh_protocol_select="http_protocol" mmst_protocol_select="network" rtmp_protocol_conflict="librtmp_protocol" @@ -3160,13 +3164,13 @@ rtmpte_protocol_suggest="zlib" rtmpts_protocol_select="ffrtmphttp_protocol https_protocol" rtmpts_protocol_suggest="zlib" rtp_protocol_select="udp_protocol" -schannel_conflict="openssl gnutls" +schannel_conflict="openssl gnutls libtls" sctp_protocol_deps="struct_sctp_event_subscribe struct_msghdr_msg_flags" sctp_protocol_select="network" -securetransport_conflict="openssl gnutls" +securetransport_conflict="openssl gnutls libtls" srtp_protocol_select="rtp_protocol srtp" tcp_protocol_select="network" -tls_protocol_deps_any="gnutls openssl schannel securetransport" +tls_protocol_deps_any="gnutls openssl schannel securetransport libtls" tls_protocol_select="tcp_protocol" udp_protocol_select="network" udplite_protocol_select="network" @@ -5890,6 +5894,8 @@ enabled libssh && require_pkg_config libssh libssh libssh/sftp.h sftp enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init enabled libtesseract && require_pkg_config libtesseract tesseract tesseract/capi.h TessBaseAPICreate enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg +enabled libtls && { use_pkg_config libtls libtls tls.h tls_configure || + require libtls tls.h tls_configure -ltls; } enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } diff --git a/doc/protocols.texi b/doc/protocols.texi index 8661aea147f23..ca2f9ad63d38c 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -1286,7 +1286,7 @@ If enabled, try to verify the peer that we are communicating with. Note, if using OpenSSL, this currently only makes sure that the peer certificate is signed by one of the root certificates in the CA database, but it does not validate that the certificate actually -matches the host name we are trying to connect to. (With GnuTLS, +matches the host name we are trying to connect to. (With other backends, the host name is validated as well.) This is disabled by default since it requires a CA database to be diff --git a/libavformat/Makefile b/libavformat/Makefile index 734b7038627cc..cb70eac9208e4 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -593,6 +593,7 @@ OBJS-$(CONFIG_SUBFILE_PROTOCOL) += subfile.o OBJS-$(CONFIG_TEE_PROTOCOL) += teeproto.o tee_common.o OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o TLS-OBJS-$(CONFIG_GNUTLS) += tls_gnutls.o +TLS-OBJS-$(CONFIG_LIBTLS) += tls_libtls.o TLS-OBJS-$(CONFIG_OPENSSL) += tls_openssl.o TLS-OBJS-$(CONFIG_SECURETRANSPORT) += tls_securetransport.o TLS-OBJS-$(CONFIG_SCHANNEL) += tls_schannel.o diff --git a/libavformat/tls_libtls.c b/libavformat/tls_libtls.c new file mode 100644 index 0000000000000..1321f79229f8f --- /dev/null +++ b/libavformat/tls_libtls.c @@ -0,0 +1,207 @@ +/* + * TLS/SSL Protocol + * Copyright (c) 2011 Martin Storsjo + * Copyright (c) 2017 sfan5 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" +#include "internal.h" +#include "network.h" +#include "url.h" +#include "tls.h" +#include "libavcodec/internal.h" +#include "libavutil/avutil.h" +#include "libavutil/opt.h" + +#include + +typedef struct TLSContext { + const AVClass *class; + TLSShared tls_shared; + struct tls *ctx; +} TLSContext; + +static int ff_tls_close(URLContext *h) +{ + TLSContext *p = h->priv_data; + if (p->ctx) { + tls_close(p->ctx); + tls_free(p->ctx); + } + if (p->tls_shared.tcp) + ffurl_close(p->tls_shared.tcp); + return 0; +} + +static ssize_t tls_read_callback(struct tls *ctx, void *buf, size_t buflen, void *cb_arg) +{ + URLContext *h = (URLContext*) cb_arg; + int ret = ffurl_read(h, buf, buflen); + if (ret == AVERROR(EAGAIN)) + return TLS_WANT_POLLIN; + else if (ret == AVERROR_EXIT) + return 0; + return ret >= 0 ? ret : -1; +} + +static ssize_t tls_write_callback(struct tls *ctx, const void *buf, size_t buflen, void *cb_arg) +{ + URLContext *h = (URLContext*) cb_arg; + int ret = ffurl_write(h, buf, buflen); + if (ret == AVERROR(EAGAIN)) + return TLS_WANT_POLLOUT; + else if (ret == AVERROR_EXIT) + return 0; + return ret >= 0 ? ret : -1; +} + +static int ff_tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options) +{ + TLSContext *p = h->priv_data; + TLSShared *c = &p->tls_shared; + struct tls_config *cfg = NULL; + int ret; + + if (tls_init() == -1) { + ret = AVERROR(EIO); + goto fail; + } + + if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0) + goto fail; + + p->ctx = !c->listen ? tls_client() : tls_server(); + if (!p->ctx) { + ret = AVERROR(EIO); + goto fail; + } + + cfg = tls_config_new(); + if (!p->ctx) { + ret = AVERROR(EIO); + goto fail; + } + if (tls_config_set_protocols(cfg, TLS_PROTOCOLS_ALL) == -1) + goto err_config; + // While TLSv1.0 and TLSv1.1 are already enabled by the above, + // we need to be less strict with ciphers so it works in practice. + if (tls_config_set_ciphers(cfg, "compat") == -1) + goto err_config; + if (c->ca_file && tls_config_set_ca_file(cfg, c->ca_file) == -1) + goto err_config; + if (c->cert_file && tls_config_set_cert_file(cfg, c->cert_file) == -1) + goto err_config; + if (c->key_file && tls_config_set_key_file(cfg, c->key_file) == -1) + goto err_config; + if (!c->verify) { + tls_config_insecure_noverifycert(cfg); + tls_config_insecure_noverifyname(cfg); + tls_config_insecure_noverifytime(cfg); + } + if (tls_configure(p->ctx, cfg) == -1) + goto err_ctx; + + if (!c->listen) { + ret = tls_connect_cbs(p->ctx, tls_read_callback, tls_write_callback, + c->tcp, !c->numerichost ? c->host : NULL); + } else { + struct tls *ctx_new; + ret = tls_accept_cbs(p->ctx, &ctx_new, tls_read_callback, + tls_write_callback, c->tcp); + if (ret == 0) { + // free "server" context and replace by "connection" context + tls_free(p->ctx); + p->ctx = ctx_new; + } + } + if (ret == -1) + goto err_ctx; + + tls_config_free(cfg); + return 0; +err_config: + av_log(h, AV_LOG_ERROR, "%s\n", tls_config_error(cfg)); + ret = AVERROR(EIO); + goto fail; +err_ctx: + av_log(h, AV_LOG_ERROR, "%s\n", tls_error(p->ctx)); + ret = AVERROR(EIO); + /* fallthrough */ +fail: + if (cfg) + tls_config_free(cfg); + ff_tls_close(h); + return ret; +} + +static int ff_tls_read(URLContext *h, uint8_t *buf, int size) +{ + TLSContext *p = h->priv_data; + ssize_t ret; + ret = tls_read(p->ctx, buf, size); + if (ret > 0) + return ret; + else if (ret == 0) + return AVERROR_EOF; + av_log(h, AV_LOG_ERROR, "%s\n", tls_error(p->ctx)); + return AVERROR(EIO); +} + +static int ff_tls_write(URLContext *h, const uint8_t *buf, int size) +{ + TLSContext *p = h->priv_data; + ssize_t ret; + ret = tls_write(p->ctx, buf, size); + if (ret > 0) + return ret; + else if (ret == 0) + return AVERROR_EOF; + av_log(h, AV_LOG_ERROR, "%s\n", tls_error(p->ctx)); + return AVERROR(EIO); +} + +static int tls_get_file_handle(URLContext *h) +{ + TLSContext *c = h->priv_data; + return ffurl_get_file_handle(c->tls_shared.tcp); +} + +static const AVOption options[] = { + TLS_COMMON_OPTIONS(TLSContext, tls_shared), + { NULL } +}; + +static const AVClass tls_class = { + .class_name = "tls", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const URLProtocol ff_tls_protocol = { + .name = "tls", + .url_open2 = ff_tls_open, + .url_read = ff_tls_read, + .url_write = ff_tls_write, + .url_close = ff_tls_close, + .url_get_file_handle = tls_get_file_handle, + .priv_data_size = sizeof(TLSContext), + .flags = URL_PROTOCOL_FLAG_NETWORK, + .priv_data_class = &tls_class, +}; From ce626f26959a1ab56c99fc3fe224c91d14f5b4c8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 17 Dec 2017 16:37:12 +0100 Subject: [PATCH 1364/2557] avfilter/av_biquads: add support for commands Signed-off-by: Paul B Mahol --- libavfilter/af_biquads.c | 121 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 2 deletions(-) diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index c4f619a423930..e1a0339fa55b5 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -237,7 +237,7 @@ BIQUAD_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) BIQUAD_FILTER(flt, float, -1., 1., 0) BIQUAD_FILTER(dbl, double, -1., 1., 0) -static int config_output(AVFilterLink *outlink) +static int config_filter(AVFilterLink *outlink, int reset) { AVFilterContext *ctx = outlink->src; BiquadsContext *s = ctx->priv; @@ -380,7 +380,8 @@ static int config_output(AVFilterLink *outlink) s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->channels); if (!s->cache) return AVERROR(ENOMEM); - memset(s->cache, 0, sizeof(ChanCache) * inlink->channels); + if (reset) + memset(s->cache, 0, sizeof(ChanCache) * inlink->channels); switch (inlink->format) { case AV_SAMPLE_FMT_S16P: s->filter = biquad_s16; break; @@ -395,6 +396,11 @@ static int config_output(AVFilterLink *outlink) return 0; } +static int config_output(AVFilterLink *outlink) +{ + return config_filter(outlink, 1); +} + static int filter_frame(AVFilterLink *inlink, AVFrame *buf) { AVFilterContext *ctx = inlink->dst; @@ -438,6 +444,116 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) return ff_filter_frame(outlink, out_buf); } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + BiquadsContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + if ((!strcmp(cmd, "frequency") || !strcmp(cmd, "f")) && + (s->filter_type == equalizer || + s->filter_type == bass || + s->filter_type == treble || + s->filter_type == bandpass || + s->filter_type == bandreject|| + s->filter_type == lowpass || + s->filter_type == highpass || + s->filter_type == allpass)) { + double freq; + + if (sscanf(args, "%lf", &freq) != 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid frequency value.\n"); + return AVERROR(EINVAL); + } + + s->frequency = freq; + } else if ((!strcmp(cmd, "gain") || !strcmp(cmd, "g")) && + (s->filter_type == equalizer || + s->filter_type == bass || + s->filter_type == treble)) { + double gain; + + if (sscanf(args, "%lf", &gain) != 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid gain value.\n"); + return AVERROR(EINVAL); + } + + s->gain = gain; + } else if ((!strcmp(cmd, "width") || !strcmp(cmd, "w")) && + (s->filter_type == equalizer || + s->filter_type == bass || + s->filter_type == treble || + s->filter_type == bandpass || + s->filter_type == bandreject|| + s->filter_type == lowpass || + s->filter_type == highpass || + s->filter_type == allpass)) { + double width; + + if (sscanf(args, "%lf", &width) != 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid width value.\n"); + return AVERROR(EINVAL); + } + + s->width = width; + } else if ((!strcmp(cmd, "width_type") || !strcmp(cmd, "t")) && + (s->filter_type == equalizer || + s->filter_type == bass || + s->filter_type == treble || + s->filter_type == bandpass || + s->filter_type == bandreject|| + s->filter_type == lowpass || + s->filter_type == highpass || + s->filter_type == allpass)) { + char width_type; + + if (sscanf(args, "%c", &width_type) != 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid width_type value.\n"); + return AVERROR(EINVAL); + } + + switch (width_type) { + case 'h': width_type = HERTZ; + case 'q': width_type = QFACTOR; + case 'o': width_type = OCTAVE; + case 's': width_type = SLOPE; + default: + av_log(ctx, AV_LOG_ERROR, "Invalid width_type value: %c\n", width_type); + return AVERROR(EINVAL); + } + + s->width_type = width_type; + } else if ((!strcmp(cmd, "a0") || + !strcmp(cmd, "a1") || + !strcmp(cmd, "a2") || + !strcmp(cmd, "b0") || + !strcmp(cmd, "b1") || + !strcmp(cmd, "b2")) && + s->filter_type == biquad) { + double value; + + if (sscanf(args, "%lf", &value) != 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid biquad value.\n"); + return AVERROR(EINVAL); + } + + if (!strcmp(cmd, "a0")) + s->a0 = value; + else if (!strcmp(cmd, "a1")) + s->a1 = value; + else if (!strcmp(cmd, "a2")) + s->a2 = value; + else if (!strcmp(cmd, "b0")) + s->b0 = value; + else if (!strcmp(cmd, "b1")) + s->b1 = value; + else if (!strcmp(cmd, "b2")) + s->b2 = value; + } + + return config_filter(outlink, 0); +} + static av_cold void uninit(AVFilterContext *ctx) { BiquadsContext *s = ctx->priv; @@ -486,6 +602,7 @@ AVFilter ff_af_##name_ = { \ .inputs = inputs, \ .outputs = outputs, \ .priv_class = &name_##_class, \ + .process_command = process_command, \ } #if CONFIG_EQUALIZER_FILTER From 600c8729e23b380f75252c0f8ecbdcc2e66e2e6a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 17 Dec 2017 16:38:07 +0100 Subject: [PATCH 1365/2557] avfilter/af_biquads: remove unused enum item Signed-off-by: Paul B Mahol --- libavfilter/af_biquads.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index e1a0339fa55b5..289116d48f0ec 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -73,7 +73,6 @@ enum FilterType { equalizer, bass, treble, - band, bandpass, bandreject, allpass, From 9b79c65ec06f2bbe4f44c615b9df70db23126250 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 17 Dec 2017 18:03:47 +0100 Subject: [PATCH 1366/2557] lavu/lavc/lavf/lavfi: Do not use type modifier %zu on Windows MSVCRT. --- libavcodec/cbs_h2645.c | 2 +- libavcodec/cbs_mpeg2.c | 2 +- libavfilter/vf_showinfo.c | 4 +++- libavfilter/vf_unsharp_opencl.c | 3 ++- libavformat/dump.c | 4 +++- libavutil/hwcontext_opencl.c | 2 +- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 742857bd199a9..2f96e4f20eb5d 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -1237,7 +1237,7 @@ static int cbs_h2645_write_nal_unit(CodedBitstreamContext *ctx, if (err < 0) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a " "sufficiently large write buffer (last attempt " - "%zu bytes).\n", priv->write_buffer_size); + "%"SIZE_SPECIFIER" bytes).\n", priv->write_buffer_size); return err; } } diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index 8fb5375e3b918..642a9c99b1a70 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -305,7 +305,7 @@ static int cbs_mpeg2_write_unit(CodedBitstreamContext *ctx, if (err < 0) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a " "sufficiently large write buffer (last attempt " - "%zu bytes).\n", priv->write_buffer_size); + "%"SIZE_SPECIFIER" bytes).\n", priv->write_buffer_size); return err; } } diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index e0b3223801d26..d1d1415c0b791 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -68,7 +68,9 @@ static void dump_spherical(AVFilterContext *ctx, AVFrame *frame, AVFrameSideData size_t l, t, r, b; av_spherical_tile_bounds(spherical, frame->width, frame->height, &l, &t, &r, &b); - av_log(ctx, AV_LOG_INFO, "[%zu, %zu, %zu, %zu] ", l, t, r, b); + av_log(ctx, AV_LOG_INFO, + "[%"SIZE_SPECIFIER", %"SIZE_SPECIFIER", %"SIZE_SPECIFIER", %"SIZE_SPECIFIER"] ", + l, t, r, b); } else if (spherical->projection == AV_SPHERICAL_CUBEMAP) { av_log(ctx, AV_LOG_INFO, "[pad %"PRIu32"] ", spherical->padding); } diff --git a/libavfilter/vf_unsharp_opencl.c b/libavfilter/vf_unsharp_opencl.c index c2ebf70ad9f0e..6a453c014bbe8 100644 --- a/libavfilter/vf_unsharp_opencl.c +++ b/libavfilter/vf_unsharp_opencl.c @@ -331,7 +331,8 @@ static int unsharp_opencl_filter_frame(AVFilterLink *inlink, AVFrame *input) } av_log(avctx, AV_LOG_DEBUG, "Run kernel on plane %d " - "(%zux%zu).\n", p, global_work[0], global_work[1]); + "(%"SIZE_SPECIFIER"x%"SIZE_SPECIFIER").\n", + p, global_work[0], global_work[1]); cle = clEnqueueNDRangeKernel(ctx->command_queue, ctx->kernel, 2, NULL, global_work, ctx->global ? NULL : local_work, diff --git a/libavformat/dump.c b/libavformat/dump.c index 77043e3fdbff4..ef143fd4e2208 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -372,7 +372,9 @@ static void dump_spherical(void *ctx, AVCodecParameters *par, AVPacketSideData * size_t l, t, r, b; av_spherical_tile_bounds(spherical, par->width, par->height, &l, &t, &r, &b); - av_log(ctx, AV_LOG_INFO, "[%zu, %zu, %zu, %zu] ", l, t, r, b); + av_log(ctx, AV_LOG_INFO, + "[%"SIZE_SPECIFIER", %"SIZE_SPECIFIER", %"SIZE_SPECIFIER", %"SIZE_SPECIFIER"] ", + l, t, r, b); } else if (spherical->projection == AV_SPHERICAL_CUBEMAP) { av_log(ctx, AV_LOG_INFO, "[pad %"PRIu32"] ", spherical->padding); } diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index b00c1b6409f38..a725a491e25f6 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -2719,7 +2719,7 @@ static int opencl_map_from_drm_arm(AVHWFramesContext *dst_fc, AVFrame *dst, &fd, desc->objects[i].size, &cle); if (!mapping->object_buffers[i]) { av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL buffer " - "from object %d (fd %d, size %zu) of DRM frame: %d.\n", + "from object %d (fd %d, size %"SIZE_SPECIFIER") of DRM frame: %d.\n", i, fd, desc->objects[i].size, cle); err = AVERROR(EIO); goto fail; From 9dcecbf04c656ffbfdfbeb7580d701d36071d876 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 17 Dec 2017 19:23:37 +0100 Subject: [PATCH 1367/2557] avfilter/af_biquads: add missing break statements Signed-off-by: Paul B Mahol --- libavfilter/af_biquads.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index 289116d48f0ec..3159bd6db09cd 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -512,10 +512,10 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar } switch (width_type) { - case 'h': width_type = HERTZ; - case 'q': width_type = QFACTOR; - case 'o': width_type = OCTAVE; - case 's': width_type = SLOPE; + case 'h': width_type = HERTZ; break; + case 'q': width_type = QFACTOR; break; + case 'o': width_type = OCTAVE; break; + case 's': width_type = SLOPE; break; default: av_log(ctx, AV_LOG_ERROR, "Invalid width_type value: %c\n", width_type); return AVERROR(EINVAL); From 3f887440677328c9cfed97ad81d14051ffa32aae Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sun, 17 Dec 2017 23:06:48 +0100 Subject: [PATCH 1368/2557] aptx: add codec cap SMALL_LAST_FRAME and INIT_THREADSAFE as appropriate --- libavcodec/aptx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/aptx.c b/libavcodec/aptx.c index d09ce8f83897c..a35d2861c175d 100644 --- a/libavcodec/aptx.c +++ b/libavcodec/aptx.c @@ -836,6 +836,7 @@ AVCodec ff_aptx_decoder = { .decode = aptx_decode_frame, .close = aptx_close, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, @@ -852,6 +853,8 @@ AVCodec ff_aptx_encoder = { .init = aptx_init, .encode2 = aptx_encode_frame, .close = aptx_close, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, From df3222d4bb18cbceda443def17b1b29067ed6e3f Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Mon, 18 Dec 2017 07:59:39 -0500 Subject: [PATCH 1369/2557] libvmaf: exit gracefully if the library fails. Fixes trac issue #6884 and Netflix/vmaf issue #124. --- libavfilter/vf_libvmaf.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/libavfilter/vf_libvmaf.c b/libavfilter/vf_libvmaf.c index e83b89b4f1b17..dfe474c40cb2a 100644 --- a/libavfilter/vf_libvmaf.c +++ b/libavfilter/vf_libvmaf.c @@ -61,6 +61,7 @@ typedef struct LIBVMAFContext { int ssim; int ms_ssim; char *pool; + int error; } LIBVMAFContext; #define OFFSET(x) offsetof(LIBVMAFContext, x) @@ -158,18 +159,26 @@ static void compute_vmaf_score(LIBVMAFContext *s) format = (char *) s->desc->name; - s->vmaf_score = compute_vmaf(format, s->width, s->height, read_frame, s, - s->model_path, s->log_path, s->log_fmt, 0, 0, - s->enable_transform, s->phone_model, s->psnr, - s->ssim, s->ms_ssim, s->pool); + s->error = compute_vmaf(&s->vmaf_score, format, s->width, s->height, + read_frame, s, s->model_path, s->log_path, + s->log_fmt, 0, 0, s->enable_transform, + s->phone_model, s->psnr, s->ssim, + s->ms_ssim, s->pool); } static void *call_vmaf(void *ctx) { LIBVMAFContext *s = (LIBVMAFContext *) ctx; compute_vmaf_score(s); - av_log(ctx, AV_LOG_INFO, "VMAF score: %f\n",s->vmaf_score); + if (!s->error) { + av_log(ctx, AV_LOG_INFO, "VMAF score: %f\n",s->vmaf_score); + } else { + pthread_mutex_lock(&s->lock); + pthread_cond_signal(&s->cond); + pthread_mutex_unlock(&s->lock); + } pthread_exit(NULL); + return NULL; } static int do_vmaf(FFFrameSync *fs) @@ -187,10 +196,17 @@ static int do_vmaf(FFFrameSync *fs) pthread_mutex_lock(&s->lock); - while (s->frame_set != 0) { + while (s->frame_set && !s->error) { pthread_cond_wait(&s->cond, &s->lock); } + if (s->error) { + av_log(ctx, AV_LOG_ERROR, + "libvmaf encountered an error, check log for details\n"); + pthread_mutex_unlock(&s->lock); + return AVERROR(EINVAL); + } + av_frame_ref(s->gref, ref); av_frame_ref(s->gmain, master); @@ -208,6 +224,7 @@ static av_cold int init(AVFilterContext *ctx) s->gref = av_frame_alloc(); s->gmain = av_frame_alloc(); + s->error = 0; pthread_mutex_init(&s->lock, NULL); pthread_cond_init (&s->cond, NULL); From 6260ab60a80fd8baebf79f9ce9299b0db72333b5 Mon Sep 17 00:00:00 2001 From: Mateusz Date: Mon, 18 Dec 2017 04:02:25 +0100 Subject: [PATCH 1370/2557] avfilter/vf_overlay: fix packed_rgb case Signed-off-by: Mateusz Brzostek --- libavfilter/vf_overlay.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index a7d3906016996..aa5835ae3abf4 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -456,9 +456,12 @@ static av_always_inline void blend_image_packed_rgb(AVFilterContext *ctx, default: // main_value = main_value * (1 - alpha) + overlay_value * alpha // since alpha is in the range 0-255, the result must divided by 255 - d[dr] = is_straight ? FAST_DIV255(d[dr] * (255 - alpha) + S[sr] * alpha) : FAST_DIV255(d[dr] * (255 - alpha) + S[sr]); - d[dg] = is_straight ? FAST_DIV255(d[dg] * (255 - alpha) + S[sg] * alpha) : FAST_DIV255(d[dr] * (255 - alpha) + S[sr]); - d[db] = is_straight ? FAST_DIV255(d[db] * (255 - alpha) + S[sb] * alpha) : FAST_DIV255(d[dr] * (255 - alpha) + S[sr]); + d[dr] = is_straight ? FAST_DIV255(d[dr] * (255 - alpha) + S[sr] * alpha) : + FFMIN(FAST_DIV255(d[dr] * (255 - alpha)) + S[sr], 255); + d[dg] = is_straight ? FAST_DIV255(d[dg] * (255 - alpha) + S[sg] * alpha) : + FFMIN(FAST_DIV255(d[dg] * (255 - alpha)) + S[sg], 255); + d[db] = is_straight ? FAST_DIV255(d[db] * (255 - alpha) + S[sb] * alpha) : + FFMIN(FAST_DIV255(d[db] * (255 - alpha)) + S[sb], 255); } if (main_has_alpha) { switch (alpha) { @@ -742,22 +745,22 @@ static void blend_image_gbrap_pm(AVFilterContext *ctx, AVFrame *dst, const AVFra static void blend_image_rgb(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_packed_rgb(ctx, dst, src, 0, x, y, 0); + blend_image_packed_rgb(ctx, dst, src, 0, x, y, 1); } static void blend_image_rgba(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_packed_rgb(ctx, dst, src, 1, x, y, 0); + blend_image_packed_rgb(ctx, dst, src, 1, x, y, 1); } static void blend_image_rgb_pm(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_packed_rgb(ctx, dst, src, 0, x, y, 1); + blend_image_packed_rgb(ctx, dst, src, 0, x, y, 0); } static void blend_image_rgba_pm(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, int x, int y) { - blend_image_packed_rgb(ctx, dst, src, 1, x, y, 1); + blend_image_packed_rgb(ctx, dst, src, 1, x, y, 0); } static int config_input_main(AVFilterLink *inlink) From 5f2c4d044f769c598d7443b6c8fb7e9402f83de8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 18 Dec 2017 15:24:00 +0100 Subject: [PATCH 1371/2557] doc/filters: update biquad filters with commands section Signed-off-by: Paul B Mahol --- doc/filters.texi | 162 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index da6cb9da7748b..fc912b6716415 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1136,6 +1136,23 @@ Specify the band-width of a filter in width_type units. Specify which channels to filter, by default all available are filtered. @end table +@subsection Commands + +This filter supports the following commands: +@table @option +@item frequency, f +Change allpass frequency. +Syntax for the command is : "@var{frequency}" + +@item width_type, t +Change allpass width_type. +Syntax for the command is : "@var{width_type}" + +@item width, w +Change allpass width. +Syntax for the command is : "@var{width}" +@end table + @section aloop Loop audio samples. @@ -1876,6 +1893,23 @@ Specify the band-width of a filter in width_type units. Specify which channels to filter, by default all available are filtered. @end table +@subsection Commands + +This filter supports the following commands: +@table @option +@item frequency, f +Change bandpass frequency. +Syntax for the command is : "@var{frequency}" + +@item width_type, t +Change bandpass width_type. +Syntax for the command is : "@var{width_type}" + +@item width, w +Change bandpass width. +Syntax for the command is : "@var{width}" +@end table + @section bandreject Apply a two-pole Butterworth band-reject filter with central @@ -1908,6 +1942,23 @@ Specify the band-width of a filter in width_type units. Specify which channels to filter, by default all available are filtered. @end table +@subsection Commands + +This filter supports the following commands: +@table @option +@item frequency, f +Change bandreject frequency. +Syntax for the command is : "@var{frequency}" + +@item width_type, t +Change bandreject width_type. +Syntax for the command is : "@var{width_type}" + +@item width, w +Change bandreject width. +Syntax for the command is : "@var{width}" +@end table + @section bass Boost or cut the bass (lower) frequencies of the audio using a two-pole @@ -1947,6 +1998,27 @@ Determine how steep is the filter's shelf transition. Specify which channels to filter, by default all available are filtered. @end table +@subsection Commands + +This filter supports the following commands: +@table @option +@item frequency, f +Change bass frequency. +Syntax for the command is : "@var{frequency}" + +@item width_type, t +Change bass width_type. +Syntax for the command is : "@var{width_type}" + +@item width, w +Change bass width. +Syntax for the command is : "@var{width}" + +@item gain, g +Change bass gain. +Syntax for the command is : "@var{gain}" +@end table + @section biquad Apply a biquad IIR filter with the given coefficients. @@ -1955,6 +2027,20 @@ are the numerator and denominator coefficients respectively. and @var{channels}, @var{c} specify which channels to filter, by default all available are filtered. +@subsection Commands + +This filter supports the following commands: +@table @option +@item a0 +@item a1 +@item a2 +@item b0 +@item b1 +@item b2 +Change biquad parameter. +Syntax for the command is : "@var{value}" +@end table + @section bs2b Bauer stereo to binaural transformation, which improves headphone listening of stereo audio records. @@ -2584,6 +2670,27 @@ equalizer=f=1000:t=q:w=1:g=2,equalizer=f=100:t=q:w=2:g=-5 @end example @end itemize +@subsection Commands + +This filter supports the following commands: +@table @option +@item frequency, f +Change equalizer frequency. +Syntax for the command is : "@var{frequency}" + +@item width_type, t +Change equalizer width_type. +Syntax for the command is : "@var{width_type}" + +@item width, w +Change equalizer width. +Syntax for the command is : "@var{width}" + +@item gain, g +Change equalizer gain. +Syntax for the command is : "@var{gain}" +@end table + @section extrastereo Linearly increases the difference between left and right channels which @@ -2983,6 +3090,23 @@ The default is 0.707q and gives a Butterworth response. Specify which channels to filter, by default all available are filtered. @end table +@subsection Commands + +This filter supports the following commands: +@table @option +@item frequency, f +Change highpass frequency. +Syntax for the command is : "@var{frequency}" + +@item width_type, t +Change highpass width_type. +Syntax for the command is : "@var{width_type}" + +@item width, w +Change highpass width. +Syntax for the command is : "@var{width}" +@end table + @section join Join multiple input streams into one multi-channel stream. @@ -3281,6 +3405,23 @@ lowpass=c=LFE @end example @end itemize +@subsection Commands + +This filter supports the following commands: +@table @option +@item frequency, f +Change lowpass frequency. +Syntax for the command is : "@var{frequency}" + +@item width_type, t +Change lowpass width_type. +Syntax for the command is : "@var{width_type}" + +@item width, w +Change lowpass width. +Syntax for the command is : "@var{width}" +@end table + @section lv2 Load a LV2 (LADSPA Version 2) plugin. @@ -4162,6 +4303,27 @@ Determine how steep is the filter's shelf transition. Specify which channels to filter, by default all available are filtered. @end table +@subsection Commands + +This filter supports the following commands: +@table @option +@item frequency, f +Change treble frequency. +Syntax for the command is : "@var{frequency}" + +@item width_type, t +Change treble width_type. +Syntax for the command is : "@var{width_type}" + +@item width, w +Change treble width. +Syntax for the command is : "@var{width}" + +@item gain, g +Change treble gain. +Syntax for the command is : "@var{gain}" +@end table + @section tremolo Sinusoidal amplitude modulation. From 74f408cc8e9ab637e22e1fe9c892854eeb275542 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 18 Dec 2017 12:32:22 +0100 Subject: [PATCH 1372/2557] avformat/mov: Fix the the typo Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 57fcda01547d5..28d60289aa712 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3536,7 +3536,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) if ((curr_cts + frame_duration >= (edit_list_duration + edit_list_media_time)) && ((flags & AVINDEX_KEYFRAME) || ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)))) { if (ctts_data_old) { - // If we have CTTS and this is the the first keyframe after edit elist, + // If we have CTTS and this is the first keyframe after edit elist, // wait for one more, because there might be trailing B-frames after this I-frame // that do belong to the edit. if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO && found_keyframe_after_edit == 0) { From b178278c7b4b494d21bbd0cc59bb6a0df2c5ffa9 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 19 Dec 2017 17:33:26 +0100 Subject: [PATCH 1373/2557] configure: fix pkg-config check for libtls This was not accounted for during merge and is required due to the refactor in commit 93ccba96df6340249b0db227d5bc3297010797a4. Signed-off-by: sfan5 Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 2f7db05faae01..c01f414f9a8ca 100755 --- a/configure +++ b/configure @@ -5894,7 +5894,7 @@ enabled libssh && require_pkg_config libssh libssh libssh/sftp.h sftp enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init enabled libtesseract && require_pkg_config libtesseract tesseract tesseract/capi.h TessBaseAPICreate enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg -enabled libtls && { use_pkg_config libtls libtls tls.h tls_configure || +enabled libtls && { check_pkg_config libtls libtls tls.h tls_configure || require libtls tls.h tls_configure -ltls; } enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || From b1781caf9e36edd4b84428c1e6aad8c4937c35d8 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 19 Dec 2017 18:45:27 +0100 Subject: [PATCH 1374/2557] configure: remove libtls fallback check This check is not needed for any supported version of libtls and causes issues with static builds (libtls links to -lssl -lcrypto). Signed-off-by: sfan5 Signed-off-by: James Almer --- configure | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure b/configure index c01f414f9a8ca..1b07dc2ce719b 100755 --- a/configure +++ b/configure @@ -5894,8 +5894,7 @@ enabled libssh && require_pkg_config libssh libssh libssh/sftp.h sftp enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init enabled libtesseract && require_pkg_config libtesseract tesseract tesseract/capi.h TessBaseAPICreate enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg -enabled libtls && { check_pkg_config libtls libtls tls.h tls_configure || - require libtls tls.h tls_configure -ltls; } +enabled libtls && require_pkg_config libtls libtls tls.h tls_configure enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } From f2e9156eb62b4e862c08ffaf8054b546a7cc591f Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 9 Dec 2017 19:26:08 +0100 Subject: [PATCH 1375/2557] avcodec/utvideodec : use gradient_pred dsp in interlace decoding --- libavcodec/utvideodec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index b85cb5daa6df4..c6076811d10a5 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -502,6 +502,7 @@ static void restore_gradient_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_ int slice_start, slice_height; const int cmask = ~(rmode ? 3 : 1); const ptrdiff_t stride2 = stride << 1; + int min_width = FFMIN(width, 32); for (slice = 0; slice < slices; slice++) { slice_start = ((slice * height) / slices) & cmask; @@ -523,12 +524,15 @@ static void restore_gradient_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_ for (j = 1; j < slice_height; j++) { // second line - first element has top prediction, the rest uses gradient bsrc[0] = (bsrc[0] + bsrc[-stride2]) & 0xFF; - for (i = 1; i < width; i++) { + for (i = 1; i < min_width; i++) { /* dsp need align 32 */ A = bsrc[i - stride2]; B = bsrc[i - (stride2 + 1)]; C = bsrc[i - 1]; bsrc[i] = (A - B + C + bsrc[i]) & 0xFF; } + if (width > 32) + c->llviddsp.add_gradient_pred(bsrc + 32, stride2, width - 32); + A = bsrc[-stride]; B = bsrc[-(1 + stride + stride - width)]; C = bsrc[width - 1]; From c76cf303ce1131ca3ac249bb9328567797761e41 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 9 Dec 2017 19:26:47 +0100 Subject: [PATCH 1376/2557] avcodec/magicyuv : use gradient_pred dsp func for 8 bits gradient mode --- libavcodec/magicyuv.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/magicyuv.c b/libavcodec/magicyuv.c index 195df121cdb99..9c6e1ba1b1483 100644 --- a/libavcodec/magicyuv.c +++ b/libavcodec/magicyuv.c @@ -345,7 +345,7 @@ static int magy_decode_slice(AVCodecContext *avctx, void *tdata, MagicYUVContext *s = avctx->priv_data; int interlaced = s->interlaced; AVFrame *p = s->p; - int i, k, x; + int i, k, x, min_width; GetBitContext gb; uint8_t *dst; @@ -413,16 +413,19 @@ static int magy_decode_slice(AVCodecContext *avctx, void *tdata, s->llviddsp.add_left_pred(dst, dst, width, 0); dst += stride; } + min_width = FFMIN(width, 32); for (k = 1 + interlaced; k < height; k++) { top = dst[-fake_stride]; left = top + dst[0]; dst[0] = left; - for (x = 1; x < width; x++) { + for (x = 1; x < min_width; x++) { /* dsp need aligned 32 */ top = dst[x - fake_stride]; lefttop = dst[x - (fake_stride + 1)]; left += top - lefttop + dst[x]; dst[x] = left; } + if (width > 32) + s->llviddsp.add_gradient_pred(dst + 32, fake_stride, width - 32); dst += stride; } break; From d31770d9a603596a0ae970328a34c1bf5cff1715 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 18 Dec 2017 11:18:14 +0100 Subject: [PATCH 1377/2557] avfilter/vf_interlace : move func init in ff_interlace_init and add depth arg for ff_interlace_init_x86 --- libavfilter/interlace.h | 3 ++- libavfilter/vf_interlace.c | 35 ++++++++++++++++------------- libavfilter/x86/vf_interlace_init.c | 4 ++-- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/libavfilter/interlace.h b/libavfilter/interlace.h index 90a0198bdc4aa..b41f0d5706fab 100644 --- a/libavfilter/interlace.h +++ b/libavfilter/interlace.h @@ -62,6 +62,7 @@ typedef struct InterlaceContext { ptrdiff_t mref, ptrdiff_t pref, int clip_max); } InterlaceContext; -void ff_interlace_init_x86(InterlaceContext *interlace); +void ff_interlace_init(InterlaceContext *interlace, int depth); +void ff_interlace_init_x86(InterlaceContext *interlace, int depth); #endif /* AVFILTER_INTERLACE_H */ diff --git a/libavfilter/vf_interlace.c b/libavfilter/vf_interlace.c index 731069818f227..24c422ded2665 100644 --- a/libavfilter/vf_interlace.c +++ b/libavfilter/vf_interlace.c @@ -185,6 +185,25 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&s->next); } +void ff_interlace_init(InterlaceContext *s, int depth) +{ + if (s->lowpass) { + if (s->lowpass == VLPF_LIN) { + if (depth > 8) + s->lowpass_line = lowpass_line_c_16; + else + s->lowpass_line = lowpass_line_c; + } else if (s->lowpass == VLPF_CMP) { + if (depth > 8) + s->lowpass_line = lowpass_line_complex_c_16; + else + s->lowpass_line = lowpass_line_complex_c; + } + if (ARCH_X86) + ff_interlace_init_x86(s, depth); + } +} + static int config_out_props(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -210,21 +229,7 @@ static int config_out_props(AVFilterLink *outlink) outlink->frame_rate.den *= 2; s->csp = av_pix_fmt_desc_get(outlink->format); - if (s->lowpass) { - if (s->lowpass == VLPF_LIN) { - if (s->csp->comp[0].depth > 8) - s->lowpass_line = lowpass_line_c_16; - else - s->lowpass_line = lowpass_line_c; - } else if (s->lowpass == VLPF_CMP) { - if (s->csp->comp[0].depth > 8) - s->lowpass_line = lowpass_line_complex_c_16; - else - s->lowpass_line = lowpass_line_complex_c; - } - if (ARCH_X86) - ff_interlace_init_x86(s); - } + ff_interlace_init(s, s->csp->comp[0].depth); av_log(ctx, AV_LOG_VERBOSE, "%s interlacing %s lowpass filter\n", s->scan == MODE_TFF ? "tff" : "bff", (s->lowpass) ? "with" : "without"); diff --git a/libavfilter/x86/vf_interlace_init.c b/libavfilter/x86/vf_interlace_init.c index 70fe86ccff046..b024b61735749 100644 --- a/libavfilter/x86/vf_interlace_init.c +++ b/libavfilter/x86/vf_interlace_init.c @@ -48,11 +48,11 @@ void ff_lowpass_line_complex_12_sse2(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); -av_cold void ff_interlace_init_x86(InterlaceContext *s) +av_cold void ff_interlace_init_x86(InterlaceContext *s, int depth) { int cpu_flags = av_get_cpu_flags(); - if (s->csp->comp[0].depth > 8) { + if (depth > 8) { if (EXTERNAL_SSE2(cpu_flags)) { if (s->lowpass == VLPF_LIN) s->lowpass_line = ff_lowpass_line_16_sse2; From adff97be5e2ff51c0bb66080c2f904ed40b6c571 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 18 Dec 2017 11:18:51 +0100 Subject: [PATCH 1378/2557] checkasm/vf_interlace : add test for lowpass_line 8 and 16 --- tests/checkasm/Makefile | 1 + tests/checkasm/checkasm.c | 3 ++ tests/checkasm/checkasm.h | 1 + tests/checkasm/vf_interlace.c | 78 +++++++++++++++++++++++++++++++++++ tests/fate/checkasm.mak | 1 + 5 files changed, 84 insertions(+) create mode 100644 tests/checkasm/vf_interlace.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 35250945451fc..6b5b1684a7e09 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -33,6 +33,7 @@ CHECKASMOBJS-$(CONFIG_AVCODEC) += $(AVCODECOBJS-yes) AVFILTEROBJS-$(CONFIG_BLEND_FILTER) += vf_blend.o AVFILTEROBJS-$(CONFIG_COLORSPACE_FILTER) += vf_colorspace.o AVFILTEROBJS-$(CONFIG_HFLIP_FILTER) += vf_hflip.o +AVFILTEROBJS-$(CONFIG_INTERLACE_FILTER) += vf_interlace.o AVFILTEROBJS-$(CONFIG_THRESHOLD_FILTER) += vf_threshold.o CHECKASMOBJS-$(CONFIG_AVFILTER) += $(AVFILTEROBJS-yes) diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 45a70aa87f4f9..8a9480c3cae8c 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -155,6 +155,9 @@ static const struct { #if CONFIG_HFLIP_FILTER { "vf_hflip", checkasm_check_vf_hflip }, #endif + #if CONFIG_INTERLACE_FILTER + { "vf_interlace", checkasm_check_vf_interlace }, + #endif #if CONFIG_THRESHOLD_FILTER { "vf_threshold", checkasm_check_vf_threshold }, #endif diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index cfe9bfb35500f..ec57c8a26f257 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -66,6 +66,7 @@ void checkasm_check_synth_filter(void); void checkasm_check_utvideodsp(void); void checkasm_check_v210enc(void); void checkasm_check_vf_hflip(void); +void checkasm_check_vf_interlace(void); void checkasm_check_vf_threshold(void); void checkasm_check_vp8dsp(void); void checkasm_check_vp9dsp(void); diff --git a/tests/checkasm/vf_interlace.c b/tests/checkasm/vf_interlace.c new file mode 100644 index 0000000000000..d5984c0fc1a29 --- /dev/null +++ b/tests/checkasm/vf_interlace.c @@ -0,0 +1,78 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "checkasm.h" +#include "libavfilter/interlace.h" +#include "libavutil/intreadwrite.h" + +#define WIDTH 256 +#define WIDTH_PADDED 256 + 32 +#define SRC_SIZE WIDTH_PADDED*3 + +#define randomize_buffers(buf, size) \ + do { \ + int j; \ + uint8_t *tmp_buf = (uint8_t *)buf;\ + for (j = 0; j < size; j++) \ + tmp_buf[j] = rnd() & 0xFF; \ + } while (0) + +static void check_lowpass_line(int depth){ + LOCAL_ALIGNED_32(uint8_t, src, [SRC_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst_ref, [WIDTH_PADDED]); + LOCAL_ALIGNED_32(uint8_t, dst_new, [WIDTH_PADDED]); + int w = WIDTH; + int mref = WIDTH_PADDED * -1; + int pref = WIDTH_PADDED; + int i, depth_byte; + InterlaceContext s; + + declare_func(void, uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, + ptrdiff_t mref, ptrdiff_t pref, int clip_max); + + s.lowpass = 1; + s.lowpass = VLPF_LIN; + depth_byte = depth >> 3; + w /= depth_byte; + + memset(src, 0, SRC_SIZE); + memset(dst_ref, 0, WIDTH_PADDED); + memset(dst_new, 0, WIDTH_PADDED); + randomize_buffers(src, SRC_SIZE); + + ff_interlace_init(&s, depth); + + if (check_func(s.lowpass_line, "lowpass_line_%d", depth)) { + for (i = 0; i < 32; i++) { /* simulate crop */ + call_ref(dst_ref, w, src + WIDTH_PADDED, mref - i*depth_byte, pref, 0); + call_new(dst_new, w, src + WIDTH_PADDED, mref - i*depth_byte, pref, 0); + if (memcmp(dst_ref, dst_new, WIDTH - i)) + fail(); + } + bench_new(dst_new, w, src + WIDTH_PADDED, mref, pref, 0); + } +} +void checkasm_check_vf_interlace(void) +{ + check_lowpass_line(8); + report("lowpass_line_8"); + + check_lowpass_line(16); + report("lowpass_line_16"); +} diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index 9216c71cb8ede..03f640b31f357 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -23,6 +23,7 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp \ fate-checkasm-vf_blend \ fate-checkasm-vf_colorspace \ fate-checkasm-vf_hflip \ + fate-checkasm-vf_interlace \ fate-checkasm-vf_threshold \ fate-checkasm-videodsp \ fate-checkasm-vp8dsp \ From 1a5865b6dcc97754a1d7eedc130fb58237d2a715 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 18 Dec 2017 11:19:17 +0100 Subject: [PATCH 1379/2557] avfilter/vf_interlace : add AVX2 for lowpass_line 8 and 16 --- libavfilter/x86/vf_interlace.asm | 5 +++++ libavfilter/x86/vf_interlace_init.c | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/libavfilter/x86/vf_interlace.asm b/libavfilter/x86/vf_interlace.asm index 06b269828a27e..99ec9e05425ff 100644 --- a/libavfilter/x86/vf_interlace.asm +++ b/libavfilter/x86/vf_interlace.asm @@ -201,5 +201,10 @@ LOWPASS_LINE INIT_XMM avx LOWPASS_LINE +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +LOWPASS_LINE +%endif + INIT_XMM sse2 LOWPASS_LINE_COMPLEX diff --git a/libavfilter/x86/vf_interlace_init.c b/libavfilter/x86/vf_interlace_init.c index b024b61735749..0de0fea382e53 100644 --- a/libavfilter/x86/vf_interlace_init.c +++ b/libavfilter/x86/vf_interlace_init.c @@ -32,6 +32,9 @@ void ff_lowpass_line_sse2(uint8_t *dstp, ptrdiff_t linesize, void ff_lowpass_line_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); +void ff_lowpass_line_avx2 (uint8_t *dstp, ptrdiff_t linesize, + const uint8_t *srcp, ptrdiff_t mref, + ptrdiff_t pref, int clip_max); void ff_lowpass_line_16_sse2(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, @@ -39,6 +42,9 @@ void ff_lowpass_line_16_sse2(uint8_t *dstp, ptrdiff_t linesize, void ff_lowpass_line_16_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); +void ff_lowpass_line_16_avx2 (uint8_t *dstp, ptrdiff_t linesize, + const uint8_t *srcp, ptrdiff_t mref, + ptrdiff_t pref, int clip_max); void ff_lowpass_line_complex_sse2(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, @@ -62,6 +68,9 @@ av_cold void ff_interlace_init_x86(InterlaceContext *s, int depth) if (EXTERNAL_AVX(cpu_flags)) if (s->lowpass == VLPF_LIN) s->lowpass_line = ff_lowpass_line_16_avx; + if (EXTERNAL_AVX2_FAST(cpu_flags)) + if (s->lowpass == VLPF_LIN) + s->lowpass_line = ff_lowpass_line_16_avx2; } else { if (EXTERNAL_SSE2(cpu_flags)) { if (s->lowpass == VLPF_LIN) @@ -72,5 +81,8 @@ av_cold void ff_interlace_init_x86(InterlaceContext *s, int depth) if (EXTERNAL_AVX(cpu_flags)) if (s->lowpass == VLPF_LIN) s->lowpass_line = ff_lowpass_line_avx; + if (EXTERNAL_AVX2_FAST(cpu_flags)) + if (s->lowpass == VLPF_LIN) + s->lowpass_line = ff_lowpass_line_avx2; } } From 8fb1d63d919286971b8e6afad372730d6d6f25c8 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 18 Dec 2017 11:30:31 +0100 Subject: [PATCH 1380/2557] avfilter/vf_tinterlace : add AVX2 func for lowpass_line 8 and 16 --- libavfilter/x86/vf_tinterlace_init.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libavfilter/x86/vf_tinterlace_init.c b/libavfilter/x86/vf_tinterlace_init.c index 209812964d0ed..2c9b1de581f37 100644 --- a/libavfilter/x86/vf_tinterlace_init.c +++ b/libavfilter/x86/vf_tinterlace_init.c @@ -33,6 +33,9 @@ void ff_lowpass_line_sse2(uint8_t *dstp, ptrdiff_t linesize, void ff_lowpass_line_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); +void ff_lowpass_line_avx2 (uint8_t *dstp, ptrdiff_t linesize, + const uint8_t *srcp, ptrdiff_t mref, + ptrdiff_t pref, int clip_max); void ff_lowpass_line_16_sse2(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, @@ -40,6 +43,9 @@ void ff_lowpass_line_16_sse2(uint8_t *dstp, ptrdiff_t linesize, void ff_lowpass_line_16_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); +void ff_lowpass_line_16_avx2 (uint8_t *dstp, ptrdiff_t linesize, + const uint8_t *srcp, ptrdiff_t mref, + ptrdiff_t pref, int clip_max); void ff_lowpass_line_complex_sse2(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, @@ -63,6 +69,11 @@ av_cold void ff_tinterlace_init_x86(TInterlaceContext *s) if (EXTERNAL_AVX(cpu_flags)) if (!(s->flags & TINTERLACE_FLAG_CVLPF)) s->lowpass_line = ff_lowpass_line_16_avx; + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + if (!(s->flags & TINTERLACE_FLAG_CVLPF)) { + s->lowpass_line = ff_lowpass_line_16_avx2; + } + } } else { if (EXTERNAL_SSE2(cpu_flags)) { if (!(s->flags & TINTERLACE_FLAG_CVLPF)) @@ -73,5 +84,10 @@ av_cold void ff_tinterlace_init_x86(TInterlaceContext *s) if (EXTERNAL_AVX(cpu_flags)) if (!(s->flags & TINTERLACE_FLAG_CVLPF)) s->lowpass_line = ff_lowpass_line_avx; + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + if (!(s->flags & TINTERLACE_FLAG_CVLPF)) { + s->lowpass_line = ff_lowpass_line_avx2; + } + } } } From a4a4179e83e61a36cf6900a1ca2a61b9efb03350 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 19 Dec 2017 21:04:29 +0100 Subject: [PATCH 1381/2557] avfilter/x86/vf_hflip : merge hflip byte and hflip short to one macro --- libavfilter/x86/vf_hflip.asm | 61 ++++++++++-------------------------- 1 file changed, 17 insertions(+), 44 deletions(-) diff --git a/libavfilter/x86/vf_hflip.asm b/libavfilter/x86/vf_hflip.asm index 89d6d0c69bb1f..82e1154d21f98 100644 --- a/libavfilter/x86/vf_hflip.asm +++ b/libavfilter/x86/vf_hflip.asm @@ -29,11 +29,16 @@ pb_flip_short: db 14,15,12,13,10,11,8,9,6,7,4,5,2,3,0,1 SECTION .text -INIT_XMM ssse3 -cglobal hflip_byte, 3, 5, 3, src, dst, w, r, x - mova m0, [pb_flip_byte] +;%1 byte or short, %2 b or w, %3 size in byte (1 for byte, 2 for short) +%macro HFLIP 3 +cglobal hflip_%1, 3, 5, 3, src, dst, w, r, x + mova m0, [pb_flip_%1] xor xq, xq +%if %3 == 1 movsxdifnidn wq, wd +%else ; short + add wd, wd +%endif mov rq, wq and rq, 2 * mmsize - 1 cmp wq, 2 * mmsize @@ -42,8 +47,8 @@ cglobal hflip_byte, 3, 5, 3, src, dst, w, r, x .loop0: neg xq - movu m1, [srcq + xq - mmsize + 1] - movu m2, [srcq + xq - 2 * mmsize + 1] + movu m1, [srcq + xq - mmsize + %3] + movu m2, [srcq + xq - 2 * mmsize + %3] pshufb m1, m0 pshufb m2, m0 neg xq @@ -59,49 +64,17 @@ cglobal hflip_byte, 3, 5, 3, src, dst, w, r, x .loop1: neg xq - mov rb, [srcq + xq] + mov r%2, [srcq + xq] neg xq - mov [dstq + xq], rb - add xq, 1 + mov [dstq + xq], r%2 + add xq, %3 cmp xq, wq jl .loop1 .end: RET +%endmacro -cglobal hflip_short, 3, 5, 3, src, dst, w, r, x - mova m0, [pb_flip_short] - xor xq, xq - add wd, wd - mov rq, wq - and rq, 2 * mmsize - 1 - cmp wq, 2 * mmsize - jl .loop1 - sub wq, rq - - .loop0: - neg xq - movu m1, [srcq + xq - mmsize + 2] - movu m2, [srcq + xq - 2 * mmsize + 2] - pshufb m1, m0 - pshufb m2, m0 - neg xq - movu [dstq + xq ], m1 - movu [dstq + xq + mmsize], m2 - add xq, mmsize * 2 - cmp xq, wq - jl .loop0 - - cmp rq, 0 - je .end - add wq, rq +INIT_XMM ssse3 +HFLIP byte, b, 1 +HFLIP short, w, 2 - .loop1: - neg xq - mov rw, [srcq + xq] - neg xq - mov [dstq + xq], rw - add xq, 2 - cmp xq, wq - jl .loop1 - .end: -RET From f181648176c0d93851d4a89410bbdd9c85e1fa7c Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 19 Dec 2017 21:06:01 +0100 Subject: [PATCH 1382/2557] avfilter/x86/vf_hflip : add avx2 version for hflip_byte and hflip_short --- libavfilter/x86/vf_hflip.asm | 12 +++++++++++- libavfilter/x86/vf_hflip_init.c | 20 ++++++++++++++++---- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/libavfilter/x86/vf_hflip.asm b/libavfilter/x86/vf_hflip.asm index 82e1154d21f98..6bd1782da4e83 100644 --- a/libavfilter/x86/vf_hflip.asm +++ b/libavfilter/x86/vf_hflip.asm @@ -32,7 +32,7 @@ SECTION .text ;%1 byte or short, %2 b or w, %3 size in byte (1 for byte, 2 for short) %macro HFLIP 3 cglobal hflip_%1, 3, 5, 3, src, dst, w, r, x - mova m0, [pb_flip_%1] + VBROADCASTI128 m0, [pb_flip_%1] xor xq, xq %if %3 == 1 movsxdifnidn wq, wd @@ -47,8 +47,13 @@ cglobal hflip_%1, 3, 5, 3, src, dst, w, r, x .loop0: neg xq +%if mmsize == 32 + vpermq m1, [srcq + xq - mmsize + %3], 0x4e; flip each lane at load + vpermq m2, [srcq + xq - 2 * mmsize + %3], 0x4e; flip each lane at load +%else movu m1, [srcq + xq - mmsize + %3] movu m2, [srcq + xq - 2 * mmsize + %3] +%endif pshufb m1, m0 pshufb m2, m0 neg xq @@ -78,3 +83,8 @@ INIT_XMM ssse3 HFLIP byte, b, 1 HFLIP short, w, 2 +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +HFLIP byte, b, 1 +HFLIP short, w, 2 +%endif diff --git a/libavfilter/x86/vf_hflip_init.c b/libavfilter/x86/vf_hflip_init.c index 2b5c9d3bf3b13..0ac399b0d415e 100644 --- a/libavfilter/x86/vf_hflip_init.c +++ b/libavfilter/x86/vf_hflip_init.c @@ -24,7 +24,9 @@ #include "libavfilter/hflip.h" void ff_hflip_byte_ssse3(const uint8_t *src, uint8_t *dst, int w); +void ff_hflip_byte_avx2(const uint8_t *src, uint8_t *dst, int w); void ff_hflip_short_ssse3(const uint8_t *src, uint8_t *dst, int w); +void ff_hflip_short_avx2(const uint8_t *src, uint8_t *dst, int w); av_cold void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes) { @@ -32,10 +34,20 @@ av_cold void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes) int i; for (i = 0; i < nb_planes; i++) { - if (EXTERNAL_SSSE3(cpu_flags) && step[i] == 1) { - s->flip_line[i] = ff_hflip_byte_ssse3; - } else if (EXTERNAL_SSSE3(cpu_flags) && step[i] == 2) { - s->flip_line[i] = ff_hflip_short_ssse3; + if (step[i] == 1) { + if (EXTERNAL_SSSE3(cpu_flags)) { + s->flip_line[i] = ff_hflip_byte_ssse3; + } + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + s->flip_line[i] = ff_hflip_byte_avx2; + } + } else if (step[i] == 2) { + if (EXTERNAL_SSSE3(cpu_flags)) { + s->flip_line[i] = ff_hflip_short_ssse3; + } + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + s->flip_line[i] = ff_hflip_short_avx2; + } } } } From 3df6e61dad85d44956b66a630f32bd7c86f41b30 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Tue, 19 Dec 2017 21:07:10 +0100 Subject: [PATCH 1383/2557] avfilter/x86/vf_hflip : indent based on patch by Paul B Mahol --- libavfilter/x86/vf_hflip.asm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavfilter/x86/vf_hflip.asm b/libavfilter/x86/vf_hflip.asm index 6bd1782da4e83..285618954f219 100644 --- a/libavfilter/x86/vf_hflip.asm +++ b/libavfilter/x86/vf_hflip.asm @@ -33,7 +33,7 @@ SECTION .text %macro HFLIP 3 cglobal hflip_%1, 3, 5, 3, src, dst, w, r, x VBROADCASTI128 m0, [pb_flip_%1] - xor xq, xq + xor xq, xq %if %3 == 1 movsxdifnidn wq, wd %else ; short @@ -63,9 +63,9 @@ cglobal hflip_%1, 3, 5, 3, src, dst, w, r, x cmp xq, wq jl .loop0 - cmp rq, 0 - je .end - add wq, rq + cmp rq, 0 + je .end + add wq, rq .loop1: neg xq @@ -76,7 +76,7 @@ cglobal hflip_%1, 3, 5, 3, src, dst, w, r, x cmp xq, wq jl .loop1 .end: -RET + RET %endmacro INIT_XMM ssse3 From c12c2739cd1eb3a84177a1dd39b526cbd5400927 Mon Sep 17 00:00:00 2001 From: Felix Matouschek Date: Tue, 12 Dec 2017 10:42:40 +0100 Subject: [PATCH 1384/2557] configure: Fix detection of vp9 decoder/encoder At least on Android the vp9 decoder/encoder needs $libm_extralibs to successfully link, it was missing in the check_lib calls for vp9 Signed-off-by: Felix Matouschek Signed-off-by: James Almer --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 1b07dc2ce719b..4d7eae8f5a809 100755 --- a/configure +++ b/configure @@ -5918,11 +5918,11 @@ enabled libvpx && { } enabled libvpx_vp9_decoder && { check_pkg_config libvpx_vp9_decoder "vpx >= 1.4.0" "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp9_dx || - check_lib libvpx_vp9_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_vp9_dx VPX_IMG_FMT_HIGHBITDEPTH" -lvpx + check_lib libvpx_vp9_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_vp9_dx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs" } enabled libvpx_vp9_encoder && { check_pkg_config libvpx_vp9_encoder "vpx >= 1.4.0" "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp9_cx || - check_lib libvpx_vp9_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_vp9_cx VPX_IMG_FMT_HIGHBITDEPTH" -lvpx + check_lib libvpx_vp9_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_vp9_cx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs" } if disabled_all libvpx_vp8_decoder libvpx_vp9_decoder libvpx_vp8_encoder libvpx_vp9_encoder; then die "libvpx enabled but no supported decoders found" From 2b38900cb377c56d855807012d931c7c40d215ed Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 18 Dec 2017 08:59:58 +0800 Subject: [PATCH 1385/2557] tests/audiomatch: Add return value check for fread. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check fread return value to fix build warning as "ignoring return value of ‘fread’" Signed-off-by: Jun Zhao Signed-off-by: Michael Niedermayer --- tests/audiomatch.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/audiomatch.c b/tests/audiomatch.c index ca56df09b302e..e63e494addeb5 100644 --- a/tests/audiomatch.c +++ b/tests/audiomatch.c @@ -80,8 +80,10 @@ int main(int argc, char **argv){ data = malloc(datlen * sizeof(*data)); signal = malloc(siglen * sizeof(*signal)); - fread(data , 1, datlen, f[0]); - fread(signal, 1, siglen, f[1]); + if (fread(data , 1, datlen, f[0]) != datlen) + return 1; + if (fread(signal, 1, siglen, f[1]) != siglen) + return 1; datlen /= 2; siglen /= 2; From e72b8549920feae3366c4d3030afd1ccb80da48e Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 18 Dec 2017 09:16:52 +0800 Subject: [PATCH 1386/2557] tests/audiomatch: Whitespace refinement Refine the coding style. Signed-off-by: Michael Niedermayer --- tests/audiomatch.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/audiomatch.c b/tests/audiomatch.c index e63e494addeb5..c17227859aaf7 100644 --- a/tests/audiomatch.c +++ b/tests/audiomatch.c @@ -25,23 +25,23 @@ #define FFMIN(a,b) ((a) > (b) ? (b) : (a)) #define FFMAX(a,b) ((a) > (b) ? (a) : (b)) -static int64_t fsize(FILE *f){ - int64_t end, pos= ftell(f); +static int64_t fsize(FILE *f) { + int64_t end, pos = ftell(f); fseek(f, 0, SEEK_END); end = ftell(f); fseek(f, pos, SEEK_SET); return end; } -int main(int argc, char **argv){ +int main(int argc, char **argv) { FILE *f[2]; int i, pos; int siglen, datlen; int bestpos = 0; - double bestc=0; - double sigamp= 0; + double bestc = 0; + double sigamp = 0; int16_t *signal, *data; - int maxshift= 16384; + int maxshift = 16384; if (argc < 3) { printf("audiomatch \n"); @@ -87,24 +87,24 @@ int main(int argc, char **argv){ datlen /= 2; siglen /= 2; - for(i=0; i sigamp * 0.94) + if (fabs(c) > sigamp * 0.94) maxshift = FFMIN(maxshift, fabs(pos)+32); - if(fabs(c)>fabs(bestc)){ - bestc= c; + if (fabs(c) > fabs(bestc)) { + bestc = c; bestpos = pos; } } From 65da5c56e661a839e017db4c51c73d6f3d8a8fcb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 19 Dec 2017 21:05:40 +0100 Subject: [PATCH 1387/2557] tests/audiomatch: Add missing return code at the end of main() Signed-off-by: Michael Niedermayer --- tests/audiomatch.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/audiomatch.c b/tests/audiomatch.c index c17227859aaf7..d44c4070e072f 100644 --- a/tests/audiomatch.c +++ b/tests/audiomatch.c @@ -109,4 +109,6 @@ int main(int argc, char **argv) { } } printf("presig: %d postsig:%d c:%7.4f lenerr:%d\n", bestpos, datlen - siglen - bestpos, bestc / sigamp, datlen - siglen); + + return 0; } From 8e0e4384b097864fbff84ed93438d33f4f15e02c Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 19 Dec 2017 19:04:25 -0300 Subject: [PATCH 1388/2557] Revert "avfilter/vf_interlace : add AVX2 for lowpass_line 8 and 16" This reverts commits 1a5865b6dcc97754a1d7eedc130fb58237d2a715 and 8fb1d63d919286971b8e6afad372730d6d6f25c8. They made fate interlace tests fail when AVX2 was used. Signed-off-by: James Almer --- libavfilter/x86/vf_interlace.asm | 5 ----- libavfilter/x86/vf_interlace_init.c | 12 ------------ libavfilter/x86/vf_tinterlace_init.c | 16 ---------------- 3 files changed, 33 deletions(-) diff --git a/libavfilter/x86/vf_interlace.asm b/libavfilter/x86/vf_interlace.asm index 99ec9e05425ff..06b269828a27e 100644 --- a/libavfilter/x86/vf_interlace.asm +++ b/libavfilter/x86/vf_interlace.asm @@ -201,10 +201,5 @@ LOWPASS_LINE INIT_XMM avx LOWPASS_LINE -%if HAVE_AVX2_EXTERNAL -INIT_YMM avx2 -LOWPASS_LINE -%endif - INIT_XMM sse2 LOWPASS_LINE_COMPLEX diff --git a/libavfilter/x86/vf_interlace_init.c b/libavfilter/x86/vf_interlace_init.c index 0de0fea382e53..b024b61735749 100644 --- a/libavfilter/x86/vf_interlace_init.c +++ b/libavfilter/x86/vf_interlace_init.c @@ -32,9 +32,6 @@ void ff_lowpass_line_sse2(uint8_t *dstp, ptrdiff_t linesize, void ff_lowpass_line_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); -void ff_lowpass_line_avx2 (uint8_t *dstp, ptrdiff_t linesize, - const uint8_t *srcp, ptrdiff_t mref, - ptrdiff_t pref, int clip_max); void ff_lowpass_line_16_sse2(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, @@ -42,9 +39,6 @@ void ff_lowpass_line_16_sse2(uint8_t *dstp, ptrdiff_t linesize, void ff_lowpass_line_16_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); -void ff_lowpass_line_16_avx2 (uint8_t *dstp, ptrdiff_t linesize, - const uint8_t *srcp, ptrdiff_t mref, - ptrdiff_t pref, int clip_max); void ff_lowpass_line_complex_sse2(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, @@ -68,9 +62,6 @@ av_cold void ff_interlace_init_x86(InterlaceContext *s, int depth) if (EXTERNAL_AVX(cpu_flags)) if (s->lowpass == VLPF_LIN) s->lowpass_line = ff_lowpass_line_16_avx; - if (EXTERNAL_AVX2_FAST(cpu_flags)) - if (s->lowpass == VLPF_LIN) - s->lowpass_line = ff_lowpass_line_16_avx2; } else { if (EXTERNAL_SSE2(cpu_flags)) { if (s->lowpass == VLPF_LIN) @@ -81,8 +72,5 @@ av_cold void ff_interlace_init_x86(InterlaceContext *s, int depth) if (EXTERNAL_AVX(cpu_flags)) if (s->lowpass == VLPF_LIN) s->lowpass_line = ff_lowpass_line_avx; - if (EXTERNAL_AVX2_FAST(cpu_flags)) - if (s->lowpass == VLPF_LIN) - s->lowpass_line = ff_lowpass_line_avx2; } } diff --git a/libavfilter/x86/vf_tinterlace_init.c b/libavfilter/x86/vf_tinterlace_init.c index 2c9b1de581f37..209812964d0ed 100644 --- a/libavfilter/x86/vf_tinterlace_init.c +++ b/libavfilter/x86/vf_tinterlace_init.c @@ -33,9 +33,6 @@ void ff_lowpass_line_sse2(uint8_t *dstp, ptrdiff_t linesize, void ff_lowpass_line_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); -void ff_lowpass_line_avx2 (uint8_t *dstp, ptrdiff_t linesize, - const uint8_t *srcp, ptrdiff_t mref, - ptrdiff_t pref, int clip_max); void ff_lowpass_line_16_sse2(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, @@ -43,9 +40,6 @@ void ff_lowpass_line_16_sse2(uint8_t *dstp, ptrdiff_t linesize, void ff_lowpass_line_16_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); -void ff_lowpass_line_16_avx2 (uint8_t *dstp, ptrdiff_t linesize, - const uint8_t *srcp, ptrdiff_t mref, - ptrdiff_t pref, int clip_max); void ff_lowpass_line_complex_sse2(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, @@ -69,11 +63,6 @@ av_cold void ff_tinterlace_init_x86(TInterlaceContext *s) if (EXTERNAL_AVX(cpu_flags)) if (!(s->flags & TINTERLACE_FLAG_CVLPF)) s->lowpass_line = ff_lowpass_line_16_avx; - if (EXTERNAL_AVX2_FAST(cpu_flags)) { - if (!(s->flags & TINTERLACE_FLAG_CVLPF)) { - s->lowpass_line = ff_lowpass_line_16_avx2; - } - } } else { if (EXTERNAL_SSE2(cpu_flags)) { if (!(s->flags & TINTERLACE_FLAG_CVLPF)) @@ -84,10 +73,5 @@ av_cold void ff_tinterlace_init_x86(TInterlaceContext *s) if (EXTERNAL_AVX(cpu_flags)) if (!(s->flags & TINTERLACE_FLAG_CVLPF)) s->lowpass_line = ff_lowpass_line_avx; - if (EXTERNAL_AVX2_FAST(cpu_flags)) { - if (!(s->flags & TINTERLACE_FLAG_CVLPF)) { - s->lowpass_line = ff_lowpass_line_avx2; - } - } } } From da032427786d9db4ab21014998cb1245083d6c85 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 19 Dec 2017 19:07:24 -0300 Subject: [PATCH 1389/2557] Revert "checkasm/vf_interlace : add test for lowpass_line 8 and 16" This reverts commit adff97be5e2ff51c0bb66080c2f904ed40b6c571. It currently fails on Windows targets. Signed-off-by: James Almer --- tests/checkasm/Makefile | 1 - tests/checkasm/checkasm.c | 3 -- tests/checkasm/checkasm.h | 1 - tests/checkasm/vf_interlace.c | 78 ----------------------------------- tests/fate/checkasm.mak | 1 - 5 files changed, 84 deletions(-) delete mode 100644 tests/checkasm/vf_interlace.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 6b5b1684a7e09..35250945451fc 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -33,7 +33,6 @@ CHECKASMOBJS-$(CONFIG_AVCODEC) += $(AVCODECOBJS-yes) AVFILTEROBJS-$(CONFIG_BLEND_FILTER) += vf_blend.o AVFILTEROBJS-$(CONFIG_COLORSPACE_FILTER) += vf_colorspace.o AVFILTEROBJS-$(CONFIG_HFLIP_FILTER) += vf_hflip.o -AVFILTEROBJS-$(CONFIG_INTERLACE_FILTER) += vf_interlace.o AVFILTEROBJS-$(CONFIG_THRESHOLD_FILTER) += vf_threshold.o CHECKASMOBJS-$(CONFIG_AVFILTER) += $(AVFILTEROBJS-yes) diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 8a9480c3cae8c..45a70aa87f4f9 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -155,9 +155,6 @@ static const struct { #if CONFIG_HFLIP_FILTER { "vf_hflip", checkasm_check_vf_hflip }, #endif - #if CONFIG_INTERLACE_FILTER - { "vf_interlace", checkasm_check_vf_interlace }, - #endif #if CONFIG_THRESHOLD_FILTER { "vf_threshold", checkasm_check_vf_threshold }, #endif diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index ec57c8a26f257..cfe9bfb35500f 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -66,7 +66,6 @@ void checkasm_check_synth_filter(void); void checkasm_check_utvideodsp(void); void checkasm_check_v210enc(void); void checkasm_check_vf_hflip(void); -void checkasm_check_vf_interlace(void); void checkasm_check_vf_threshold(void); void checkasm_check_vp8dsp(void); void checkasm_check_vp9dsp(void); diff --git a/tests/checkasm/vf_interlace.c b/tests/checkasm/vf_interlace.c deleted file mode 100644 index d5984c0fc1a29..0000000000000 --- a/tests/checkasm/vf_interlace.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with FFmpeg; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include "checkasm.h" -#include "libavfilter/interlace.h" -#include "libavutil/intreadwrite.h" - -#define WIDTH 256 -#define WIDTH_PADDED 256 + 32 -#define SRC_SIZE WIDTH_PADDED*3 - -#define randomize_buffers(buf, size) \ - do { \ - int j; \ - uint8_t *tmp_buf = (uint8_t *)buf;\ - for (j = 0; j < size; j++) \ - tmp_buf[j] = rnd() & 0xFF; \ - } while (0) - -static void check_lowpass_line(int depth){ - LOCAL_ALIGNED_32(uint8_t, src, [SRC_SIZE]); - LOCAL_ALIGNED_32(uint8_t, dst_ref, [WIDTH_PADDED]); - LOCAL_ALIGNED_32(uint8_t, dst_new, [WIDTH_PADDED]); - int w = WIDTH; - int mref = WIDTH_PADDED * -1; - int pref = WIDTH_PADDED; - int i, depth_byte; - InterlaceContext s; - - declare_func(void, uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, - ptrdiff_t mref, ptrdiff_t pref, int clip_max); - - s.lowpass = 1; - s.lowpass = VLPF_LIN; - depth_byte = depth >> 3; - w /= depth_byte; - - memset(src, 0, SRC_SIZE); - memset(dst_ref, 0, WIDTH_PADDED); - memset(dst_new, 0, WIDTH_PADDED); - randomize_buffers(src, SRC_SIZE); - - ff_interlace_init(&s, depth); - - if (check_func(s.lowpass_line, "lowpass_line_%d", depth)) { - for (i = 0; i < 32; i++) { /* simulate crop */ - call_ref(dst_ref, w, src + WIDTH_PADDED, mref - i*depth_byte, pref, 0); - call_new(dst_new, w, src + WIDTH_PADDED, mref - i*depth_byte, pref, 0); - if (memcmp(dst_ref, dst_new, WIDTH - i)) - fail(); - } - bench_new(dst_new, w, src + WIDTH_PADDED, mref, pref, 0); - } -} -void checkasm_check_vf_interlace(void) -{ - check_lowpass_line(8); - report("lowpass_line_8"); - - check_lowpass_line(16); - report("lowpass_line_16"); -} diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index 03f640b31f357..9216c71cb8ede 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -23,7 +23,6 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp \ fate-checkasm-vf_blend \ fate-checkasm-vf_colorspace \ fate-checkasm-vf_hflip \ - fate-checkasm-vf_interlace \ fate-checkasm-vf_threshold \ fate-checkasm-videodsp \ fate-checkasm-vp8dsp \ From a31a48261164f2ec7d218f541891086f930b090b Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Tue, 19 Dec 2017 14:13:58 +0800 Subject: [PATCH 1390/2557] lavc/vaapi_encode: give a debug message if attrs unsupported. Give a debug message when query attribute get VA_ATTRIB_NOT_SUPPORTED, it's will help to trace and debug some issue. Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- libavcodec/vaapi_encode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 590f4be4ed041..550ea47991d3e 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1036,6 +1036,8 @@ static av_cold int vaapi_encode_config_attributes(AVCodecContext *avctx) // Unfortunately we have to treat this as "don't know" and hope // for the best, because the Intel MJPEG encoder returns this // for all the interesting attributes. + av_log(avctx, AV_LOG_DEBUG, "Attribute (%d) is not supported.\n", + attr[i].type); continue; } switch (attr[i].type) { From 720cf4e6e7dcaa4032b9448cb6b6cc4671a6f108 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:39 +0100 Subject: [PATCH 1391/2557] lavc: Add codec metadata to indicate hardware support --- doc/APIchanges | 3 ++ libavcodec/avcodec.h | 74 ++++++++++++++++++++++++++++++++++++++++++++ libavcodec/hwaccel.h | 18 +++++++++++ libavcodec/utils.c | 12 +++++++ libavcodec/version.h | 2 +- 5 files changed, 108 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index a7ecbcdaaed40..f5f15c49a1e3c 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2017-03-23 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavc 58.6.0 - avcodec.h + Add AVCodecHWConfig and avcodec_get_hw_config(). + 2017-xx-xx - xxxxxxx - lavu 56.7.0 - stereo3d.h Add view field to AVStereo3D structure and AVStereo3DView enum. diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index ec952dd0e830c..cf9f9dfe84dfc 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -35,6 +35,7 @@ #include "libavutil/cpu.h" #include "libavutil/dict.h" #include "libavutil/frame.h" +#include "libavutil/hwcontext.h" #include "libavutil/log.h" #include "libavutil/pixfmt.h" #include "libavutil/rational.h" @@ -2748,6 +2749,61 @@ typedef struct AVProfile { const char *name; ///< short name for the profile } AVProfile; +enum { + /** + * The codec supports this format via the hw_device_ctx interface. + * + * When selecting this format, AVCodecContext.hw_device_ctx should + * have been set to a device of the specified type before calling + * avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01, + /** + * The codec supports this format via the hw_frames_ctx interface. + * + * When selecting this format for a decoder, + * AVCodecContext.hw_frames_ctx should be set to a suitable frames + * context inside the get_format() callback. The frames context + * must have been created on a device of the specified type. + */ + AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX = 0x02, + /** + * The codec supports this format by some internal method. + * + * This format can be selected without any additional configuration - + * no device or frames context is required. + */ + AV_CODEC_HW_CONFIG_METHOD_INTERNAL = 0x04, + /** + * The codec supports this format by some ad-hoc method. + * + * Additional settings and/or function calls are required. See the + * codec-specific documentation for details. (Methods requiring + * this sort of configuration are deprecated and others should be + * used in preference.) + */ + AV_CODEC_HW_CONFIG_METHOD_AD_HOC = 0x08, +}; + +typedef struct AVCodecHWConfig { + /** + * A hardware pixel format which the codec can use. + */ + enum AVPixelFormat pix_fmt; + /** + * Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible + * setup methods which can be used with this configuration. + */ + int methods; + /** + * The device type associated with the configuration. + * + * Must be set for AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX and + * AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, otherwise unused. + */ + enum AVHWDeviceType device_type; +} AVCodecHWConfig; + typedef struct AVCodecDefault AVCodecDefault; struct AVSubtitle; @@ -2884,8 +2940,26 @@ typedef struct AVCodec { * packets before decoding. */ const char *bsfs; + + /** + * Array of pointers to hardware configurations supported by the codec, + * or NULL if no hardware supported. The array is terminated by a NULL + * pointer. + * + * The user can only access this field via avcodec_get_hw_config(). + */ + const struct AVCodecHWConfigInternal **hw_configs; } AVCodec; +/** + * Retrieve supported hardware configurations for a codec. + * + * Values of index from zero to some maximum return the indexed configuration + * descriptor; all other values return NULL. If the codec does not support + * any hardware configurations then it will always return NULL. + */ +const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index); + /** * @defgroup lavc_hwaccel AVHWAccel * @{ diff --git a/libavcodec/hwaccel.h b/libavcodec/hwaccel.h index 60dbe81c8bcd8..b6d5662482240 100644 --- a/libavcodec/hwaccel.h +++ b/libavcodec/hwaccel.h @@ -19,6 +19,24 @@ #ifndef AVCODEC_HWACCEL_H #define AVCODEC_HWACCEL_H +#include "avcodec.h" + + #define HWACCEL_CAP_ASYNC_SAFE (1 << 0) + +typedef struct AVCodecHWConfigInternal { + /** + * This is the structure which will be returned to the user by + * avcodec_get_hw_config(). + */ + AVCodecHWConfig public; + /** + * If this configuration uses a hwaccel, a pointer to it. + * If not, NULL. + */ + const AVHWAccel *hwaccel; +} AVCodecHWConfigInternal; + + #endif /* AVCODEC_HWACCEL_H */ diff --git a/libavcodec/utils.c b/libavcodec/utils.c index bc421f67f8141..3d6b35fa41c99 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -41,6 +41,7 @@ #include "libavutil/dict.h" #include "avcodec.h" #include "decode.h" +#include "hwaccel.h" #include "libavutil/opt.h" #include "me_cmp.h" #include "mpegvideo.h" @@ -1335,6 +1336,17 @@ int ff_match_2uint16(const uint16_t(*tab)[2], int size, int a, int b) return i; } +const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index) +{ + int i; + if (!codec->hw_configs || index < 0) + return NULL; + for (i = 0; i <= index; i++) + if (!codec->hw_configs[i]) + return NULL; + return &codec->hw_configs[index]->public; +} + static AVHWAccel *first_hwaccel = NULL; void av_register_hwaccel(AVHWAccel *hwaccel) diff --git a/libavcodec/version.h b/libavcodec/version.h index aa6cdcd6bc4c8..e6edd5c867557 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 5 +#define LIBAVCODEC_VERSION_MINOR 6 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From 2fcb0090115f7fc7648ad241a5903f866760d4b6 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:40 +0100 Subject: [PATCH 1392/2557] lavc: Add hardware config metadata for decoders supporting hardware output This includes a pointer to the associated hwaccel for decoders using hwaccels - these will be used later to implement the hwaccel setup without needing a global list. Also added is a new file listing all hwaccels as external declarations - this will be used later to generate the hwaccel list at configure time. --- libavcodec/h263dec.c | 10 +++++++ libavcodec/h264dec.c | 28 ++++++++++++++++++ libavcodec/hevcdec.c | 22 ++++++++++++++ libavcodec/hwaccel.h | 38 ++++++++++++++++++++++++ libavcodec/hwaccels.h | 59 ++++++++++++++++++++++++++++++++++++++ libavcodec/mmaldec.c | 7 +++++ libavcodec/mpeg12dec.c | 27 ++++++++++++++++- libavcodec/mpeg4videodec.c | 10 +++++++ libavcodec/qsvdec.c | 13 +++++++++ libavcodec/qsvdec.h | 3 ++ libavcodec/qsvdec_h2645.c | 2 ++ libavcodec/qsvdec_other.c | 3 ++ libavcodec/vc1dec.c | 37 ++++++++++++++++++++++++ libavcodec/vp8.c | 7 +++++ 14 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 libavcodec/hwaccels.h diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 921ff5fb98557..b0000883c1767 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -31,6 +31,7 @@ #include "flv.h" #include "h263.h" #include "h263_parser.h" +#include "hwaccel.h" #include "internal.h" #include "mpeg_er.h" #include "mpeg4video.h" @@ -677,4 +678,13 @@ AVCodec ff_h263_decoder = { AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY, .flush = ff_mpeg_flush, .pix_fmts = ff_h263_hwaccel_pixfmt_list_420, + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_H263_VAAPI_HWACCEL + HWACCEL_VAAPI(h263), +#endif +#if CONFIG_MPEG4_VDPAU_HWACCEL + HWACCEL_VDPAU(mpeg4), +#endif + NULL + }, }; diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 7a8293efa5f8a..4bfd78962d9ec 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -44,6 +44,7 @@ #include "h264chroma.h" #include "h264_mvpred.h" #include "h264_ps.h" +#include "hwaccel.h" #include "mathops.h" #include "me_cmp.h" #include "mpegutils.h" @@ -786,6 +787,33 @@ AVCodec ff_h264_decoder = { .capabilities = /*AV_CODEC_CAP_DRAW_HORIZ_BAND |*/ AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_H264_CUVID_HWACCEL + HWACCEL_CUVID(h264), +#endif +#if CONFIG_H264_DXVA2_HWACCEL + HWACCEL_DXVA2(h264), +#endif +#if CONFIG_H264_D3D11VA_HWACCEL + HWACCEL_D3D11VA(h264), +#endif +#if CONFIG_H264_D3D11VA2_HWACCEL + HWACCEL_D3D11VA2(h264), +#endif +#if CONFIG_H264_VAAPI_HWACCEL + HWACCEL_VAAPI(h264), +#endif +#if CONFIG_H264_VDPAU_HWACCEL + HWACCEL_VDPAU(h264), +#endif +#if CONFIG_H264_VDA_HWACCEL + HW_CONFIG_HWACCEL(0, 0, 1, VDA, NONE, ff_h264_vda_hwaccel), +#endif +#if CONFIG_H264_VDA_OLD_HWACCEL + HW_CONFIG_HWACCEL(0, 0, 1, VDA_VLD, NONE, ff_h264_vda_old_hwaccel), +#endif + NULL + }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING, .flush = flush_dpb, .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index f1d1c774977fb..130b99f77e7ce 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -39,6 +39,7 @@ #include "hevc.h" #include "hevc_data.h" #include "hevcdec.h" +#include "hwaccel.h" #include "profiles.h" const uint8_t ff_hevc_qpel_extra_before[4] = { 0, 3, 3, 3 }; @@ -3120,4 +3121,25 @@ AVCodec ff_hevc_decoder = { AV_CODEC_CAP_FRAME_THREADS, .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), .caps_internal = FF_CODEC_CAP_EXPORTS_CROPPING | FF_CODEC_CAP_INIT_THREADSAFE, + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_HEVC_CUVID_HWACCEL + HWACCEL_CUVID(hevc), +#endif +#if CONFIG_HEVC_DXVA2_HWACCEL + HWACCEL_DXVA2(hevc), +#endif +#if CONFIG_HEVC_D3D11VA_HWACCEL + HWACCEL_D3D11VA(hevc), +#endif +#if CONFIG_HEVC_D3D11VA2_HWACCEL + HWACCEL_D3D11VA2(hevc), +#endif +#if CONFIG_HEVC_VAAPI_HWACCEL + HWACCEL_VAAPI(hevc), +#endif +#if CONFIG_HEVC_VDPAU_HWACCEL + HWACCEL_VDPAU(hevc), +#endif + NULL + }, }; diff --git a/libavcodec/hwaccel.h b/libavcodec/hwaccel.h index b6d5662482240..e215736c2ce4e 100644 --- a/libavcodec/hwaccel.h +++ b/libavcodec/hwaccel.h @@ -20,6 +20,7 @@ #define AVCODEC_HWACCEL_H #include "avcodec.h" +#include "hwaccels.h" #define HWACCEL_CAP_ASYNC_SAFE (1 << 0) @@ -39,4 +40,41 @@ typedef struct AVCodecHWConfigInternal { } AVCodecHWConfigInternal; +// These macros are used to simplify AVCodecHWConfigInternal definitions. + +#define HW_CONFIG_HWACCEL(device, frames, ad_hoc, format, device_type_, name) \ + &(const AVCodecHWConfigInternal) { \ + .public = { \ + .pix_fmt = AV_PIX_FMT_ ## format, \ + .methods = (device ? AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX : 0) | \ + (frames ? AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX : 0) | \ + (ad_hoc ? AV_CODEC_HW_CONFIG_METHOD_AD_HOC : 0), \ + .device_type = AV_HWDEVICE_TYPE_ ## device_type_, \ + }, \ + .hwaccel = &name, \ + } + +#define HW_CONFIG_INTERNAL(format) \ + &(const AVCodecHWConfigInternal) { \ + .public = { \ + .pix_fmt = AV_PIX_FMT_ ## format, \ + .methods = AV_CODEC_HW_CONFIG_METHOD_INTERNAL, \ + .device_type = AV_HWDEVICE_TYPE_NONE, \ + }, \ + .hwaccel = NULL, \ + } + +#define HWACCEL_CUVID(codec) \ + HW_CONFIG_HWACCEL(1, 1, 0, CUDA, CUDA, ff_ ## codec ## _cuvid_hwaccel) +#define HWACCEL_DXVA2(codec) \ + HW_CONFIG_HWACCEL(1, 1, 1, DXVA2_VLD, DXVA2, ff_ ## codec ## _dxva2_hwaccel) +#define HWACCEL_D3D11VA2(codec) \ + HW_CONFIG_HWACCEL(1, 1, 0, D3D11, D3D11VA, ff_ ## codec ## _d3d11va2_hwaccel) +#define HWACCEL_VAAPI(codec) \ + HW_CONFIG_HWACCEL(1, 1, 1, VAAPI, VAAPI, ff_ ## codec ## _vaapi_hwaccel) +#define HWACCEL_VDPAU(codec) \ + HW_CONFIG_HWACCEL(1, 1, 1, VDPAU, VDPAU, ff_ ## codec ## _vdpau_hwaccel) +#define HWACCEL_D3D11VA(codec) \ + HW_CONFIG_HWACCEL(0, 0, 1, D3D11VA_VLD, NONE, ff_ ## codec ## _d3d11va_hwaccel) + #endif /* AVCODEC_HWACCEL_H */ diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h new file mode 100644 index 0000000000000..6dee94b44ff81 --- /dev/null +++ b/libavcodec/hwaccels.h @@ -0,0 +1,59 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HWACCELS_H +#define AVCODEC_HWACCELS_H + +#include "avcodec.h" + +extern AVHWAccel ff_h263_vaapi_hwaccel; +extern AVHWAccel ff_h264_cuvid_hwaccel; +extern AVHWAccel ff_h264_d3d11va_hwaccel; +extern AVHWAccel ff_h264_d3d11va2_hwaccel; +extern AVHWAccel ff_h264_dxva2_hwaccel; +extern AVHWAccel ff_h264_vaapi_hwaccel; +extern AVHWAccel ff_h264_vda_hwaccel; +extern AVHWAccel ff_h264_vda_old_hwaccel; +extern AVHWAccel ff_h264_vdpau_hwaccel; +extern AVHWAccel ff_hevc_cuvid_hwaccel; +extern AVHWAccel ff_hevc_d3d11va_hwaccel; +extern AVHWAccel ff_hevc_d3d11va2_hwaccel; +extern AVHWAccel ff_hevc_dxva2_hwaccel; +extern AVHWAccel ff_hevc_vaapi_hwaccel; +extern AVHWAccel ff_hevc_vdpau_hwaccel; +extern AVHWAccel ff_mpeg1_vdpau_hwaccel; +extern AVHWAccel ff_mpeg2_d3d11va_hwaccel; +extern AVHWAccel ff_mpeg2_d3d11va2_hwaccel; +extern AVHWAccel ff_mpeg2_dxva2_hwaccel; +extern AVHWAccel ff_mpeg2_vaapi_hwaccel; +extern AVHWAccel ff_mpeg2_vdpau_hwaccel; +extern AVHWAccel ff_mpeg4_vaapi_hwaccel; +extern AVHWAccel ff_mpeg4_vdpau_hwaccel; +extern AVHWAccel ff_vc1_d3d11va_hwaccel; +extern AVHWAccel ff_vc1_d3d11va2_hwaccel; +extern AVHWAccel ff_vc1_dxva2_hwaccel; +extern AVHWAccel ff_vc1_vaapi_hwaccel; +extern AVHWAccel ff_vc1_vdpau_hwaccel; +extern AVHWAccel ff_vp8_vaapi_hwaccel; +extern AVHWAccel ff_wmv3_d3d11va_hwaccel; +extern AVHWAccel ff_wmv3_d3d11va2_hwaccel; +extern AVHWAccel ff_wmv3_dxva2_hwaccel; +extern AVHWAccel ff_wmv3_vaapi_hwaccel; +extern AVHWAccel ff_wmv3_vdpau_hwaccel; + +#endif /* AVCODEC_HWACCELS_H */ diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index 3e480ab49abe1..9ed8e61371852 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -34,6 +34,7 @@ #include #include "avcodec.h" +#include "hwaccel.h" #include "internal.h" #include "libavutil/avassert.h" #include "libavutil/buffer.h" @@ -808,6 +809,11 @@ AVHWAccel ff_vc1_mmal_hwaccel = { .pix_fmt = AV_PIX_FMT_MMAL, }; +static const AVCodecHWConfigInternal *mmal_hw_configs = { + HW_CONFIG_INTERNAL(MMAL), + NULL +}; + static const AVOption options[]={ {"extra_buffers", "extra buffers", offsetof(MMALDecodeContext, extra_buffers), AV_OPT_TYPE_INT, {.i64 = 10}, 0, 256, 0}, {"extra_decoder_buffers", "extra MMAL internal buffered frames", offsetof(MMALDecodeContext, extra_decoder_buffers), AV_OPT_TYPE_INT, {.i64 = 10}, 0, 256, 0}, @@ -840,6 +846,7 @@ static const AVOption options[]={ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MMAL, \ AV_PIX_FMT_YUV420P, \ AV_PIX_FMT_NONE}, \ + .hw_configs = mmal_hw_configs, \ .wrapper_name = "mmal", \ }; diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 9a9a92701a824..532934ccba3d7 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -34,6 +34,7 @@ #include "avcodec.h" #include "bytestream.h" #include "error_resilience.h" +#include "hwaccel.h" #include "idctdsp.h" #include "internal.h" #include "mpeg_er.h" @@ -2594,7 +2595,13 @@ AVCodec ff_mpeg1video_decoder = { AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, .flush = flush, - .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg_decode_update_thread_context) + .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg_decode_update_thread_context), + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_MPEG1_VDPAU_HWACCEL + HWACCEL_VDPAU(mpeg1), +#endif + NULL + }, }; AVCodec ff_mpeg2video_decoder = { @@ -2611,4 +2618,22 @@ AVCodec ff_mpeg2video_decoder = { AV_CODEC_CAP_SLICE_THREADS, .flush = flush, .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg2_video_profiles), + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_MPEG2_DXVA2_HWACCEL + HWACCEL_DXVA2(mpeg2), +#endif +#if CONFIG_MPEG2_D3D11VA_HWACCEL + HWACCEL_D3D11VA(mpeg2), +#endif +#if CONFIG_MPEG2_D3D11VA2_HWACCEL + HWACCEL_D3D11VA2(mpeg2), +#endif +#if CONFIG_MPEG2_VAAPI_HWACCEL + HWACCEL_VAAPI(mpeg2), +#endif +#if CONFIG_MPEG2_VDPAU_HWACCEL + HWACCEL_VDPAU(mpeg2), +#endif + NULL + }, }; diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index eb1b67273bc9c..566fd3a898589 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -21,6 +21,7 @@ */ #include "error_resilience.h" +#include "hwaccel.h" #include "idctdsp.h" #include "internal.h" #include "mpegutils.h" @@ -2625,6 +2626,15 @@ AVCodec ff_mpeg4_decoder = { .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_FRAME_THREADS, + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_MPEG4_VAAPI_HWACCEL + HWACCEL_VAAPI(mpeg4), +#endif +#if CONFIG_MPEG4_VDPAU_HWACCEL + HWACCEL_VDPAU(mpeg4), +#endif + NULL + }, .flush = ff_mpeg_flush, .pix_fmts = ff_h263_hwaccel_pixfmt_list_420, .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg4_video_profiles), diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 2c90436a177cd..c74ec6836987c 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -41,6 +41,19 @@ #include "qsv_internal.h" #include "qsvdec.h" +const AVCodecHWConfigInternal *ff_qsv_hw_configs[] = { + &(const AVCodecHWConfigInternal) { + .public = { + .pix_fmt = AV_PIX_FMT_QSV, + .methods = AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX | + AV_CODEC_HW_CONFIG_METHOD_AD_HOC, + .device_type = AV_HWDEVICE_TYPE_QSV, + }, + .hwaccel = NULL, + }, + NULL +}; + static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session, AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref) { diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h index c6ec99af1528e..e25c4d6c93481 100644 --- a/libavcodec/qsvdec.h +++ b/libavcodec/qsvdec.h @@ -33,6 +33,7 @@ #include "libavutil/pixfmt.h" #include "avcodec.h" +#include "hwaccel.h" #include "qsv_internal.h" typedef struct QSVContext { @@ -70,6 +71,8 @@ typedef struct QSVContext { int nb_ext_buffers; } QSVContext; +extern const AVCodecHWConfigInternal *ff_qsv_hw_configs[]; + int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, AVFrame *frame, int *got_frame, AVPacket *pkt); diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c index 03ba303c95382..a7b39da6bf763 100644 --- a/libavcodec/qsvdec_h2645.c +++ b/libavcodec/qsvdec_h2645.c @@ -226,6 +226,7 @@ AVCodec ff_hevc_qsv_decoder = { AV_PIX_FMT_P010, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, + .hw_configs = ff_qsv_hw_configs, .bsfs = "hevc_mp4toannexb", .wrapper_name = "qsv", }; @@ -269,6 +270,7 @@ AVCodec ff_h264_qsv_decoder = { AV_PIX_FMT_P010, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, + .hw_configs = ff_qsv_hw_configs, .bsfs = "h264_mp4toannexb", .wrapper_name = "qsv", }; diff --git a/libavcodec/qsvdec_other.c b/libavcodec/qsvdec_other.c index 0cea4eee92887..63cc113c5cbe2 100644 --- a/libavcodec/qsvdec_other.c +++ b/libavcodec/qsvdec_other.c @@ -195,6 +195,7 @@ AVCodec ff_mpeg2_qsv_decoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, + .hw_configs = ff_qsv_hw_configs, .wrapper_name = "qsv", }; #endif @@ -231,6 +232,7 @@ AVCodec ff_vc1_qsv_decoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, + .hw_configs = ff_qsv_hw_configs, .wrapper_name = "qsv", }; #endif @@ -267,6 +269,7 @@ AVCodec ff_vp8_qsv_decoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, + .hw_configs = ff_qsv_hw_configs, .wrapper_name = "qsv", }; #endif diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 5e00a33e3d929..890211019a1c8 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "blockdsp.h" #include "get_bits.h" +#include "hwaccel.h" #include "internal.h" #include "mpeg_er.h" #include "mpegvideo.h" @@ -986,6 +987,24 @@ AVCodec ff_vc1_decoder = { .flush = ff_mpeg_flush, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .pix_fmts = vc1_hwaccel_pixfmt_list_420, + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_VC1_DXVA2_HWACCEL + HWACCEL_DXVA2(vc1), +#endif +#if CONFIG_VC1_D3D11VA_HWACCEL + HWACCEL_D3D11VA(vc1), +#endif +#if CONFIG_VC1_D3D11VA2_HWACCEL + HWACCEL_D3D11VA2(vc1), +#endif +#if CONFIG_VC1_VAAPI_HWACCEL + HWACCEL_VAAPI(vc1), +#endif +#if CONFIG_VC1_VDPAU_HWACCEL + HWACCEL_VDPAU(vc1), +#endif + NULL + }, .profiles = NULL_IF_CONFIG_SMALL(ff_vc1_profiles) }; @@ -1002,6 +1021,24 @@ AVCodec ff_wmv3_decoder = { .flush = ff_mpeg_flush, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .pix_fmts = vc1_hwaccel_pixfmt_list_420, + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_WMV3_DXVA2_HWACCEL + HWACCEL_DXVA2(wmv3), +#endif +#if CONFIG_WMV3_D3D11VA_HWACCEL + HWACCEL_D3D11VA(wmv3), +#endif +#if CONFIG_WMV3_D3D11VA2_HWACCEL + HWACCEL_D3D11VA2(wmv3), +#endif +#if CONFIG_WMV3_VAAPI_HWACCEL + HWACCEL_VAAPI(wmv3), +#endif +#if CONFIG_WMV3_VDPAU_HWACCEL + HWACCEL_VDPAU(wmv3), +#endif + NULL + }, .profiles = NULL_IF_CONFIG_SMALL(ff_vc1_profiles) }; #endif diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index 43580a3a813e0..6d1a399304d32 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -27,6 +27,7 @@ #include "libavutil/imgutils.h" #include "avcodec.h" +#include "hwaccel.h" #include "internal.h" #include "mathops.h" #include "rectangle.h" @@ -2851,6 +2852,12 @@ AVCodec ff_vp8_decoder = { .decode = ff_vp8_decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, + .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_VP8_VAAPI_HWACCEL + HWACCEL_VAAPI(vp8), +#endif + NULL + }, .flush = vp8_decode_flush, .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp8_decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_context), From 57623cba1301ee7874687dd7e04c611051638e9d Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:42 +0100 Subject: [PATCH 1393/2557] webp: Fix alpha initialisation ff_get_format() in the next patch will reject formats which aren't in the offered list, so the hack in 7cb9296db872c4221453e5411f242ebcfca62664 is no longer valid. Change the hack by adding a new field in the VP8 decoder context to indicate that it's actually WebP and don't call ff_get_format() at all in that case. --- libavcodec/vp8.c | 4 +++- libavcodec/vp8.h | 1 + libavcodec/webp.c | 16 +++++----------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index 6d1a399304d32..5c0b4749ad22f 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -2515,7 +2515,9 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (ret < 0) goto err; - if (!is_vp7 && s->pix_fmt == AV_PIX_FMT_NONE) { + if (s->actually_webp) { + // avctx->pix_fmt already set in caller. + } else if (!is_vp7 && s->pix_fmt == AV_PIX_FMT_NONE) { enum AVPixelFormat pix_fmts[] = { #if CONFIG_VP8_VAAPI_HWACCEL AV_PIX_FMT_VAAPI, diff --git a/libavcodec/vp8.h b/libavcodec/vp8.h index 1870705ad2e6b..1bf7561d05635 100644 --- a/libavcodec/vp8.h +++ b/libavcodec/vp8.h @@ -140,6 +140,7 @@ typedef struct VP8Context { VP8ThreadData *thread_data; AVCodecContext *avctx; enum AVPixelFormat pix_fmt; + int actually_webp; VP8Frame *framep[4]; VP8Frame *next_framep[4]; diff --git a/libavcodec/webp.c b/libavcodec/webp.c index 18d68e914020e..0e769c307d380 100644 --- a/libavcodec/webp.c +++ b/libavcodec/webp.c @@ -1288,16 +1288,6 @@ static int vp8_lossy_decode_alpha(AVCodecContext *avctx, AVFrame *p, return 0; } -static enum AVPixelFormat webp_get_format(AVCodecContext *avctx, - const enum AVPixelFormat *formats) -{ - WebPContext *s = avctx->priv_data; - if (s->has_alpha) - return AV_PIX_FMT_YUVA420P; - else - return AV_PIX_FMT_YUV420P; -} - static int vp8_lossy_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, uint8_t *data_start, unsigned int data_size) @@ -1309,7 +1299,11 @@ static int vp8_lossy_decode_frame(AVCodecContext *avctx, AVFrame *p, if (!s->initialized) { ff_vp8_decode_init(avctx); s->initialized = 1; - avctx->get_format = webp_get_format; + s->v.actually_webp = 1; + if (s->has_alpha) + avctx->pix_fmt = AV_PIX_FMT_YUVA420P; + else + avctx->pix_fmt = AV_PIX_FMT_YUV420P; } s->lossless = 0; From 39056b5240524e4119fa630240f9b45ea0230aad Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:43 +0100 Subject: [PATCH 1394/2557] lavc: Use hardware config information in ff_get_format() This removes the dependency that hardware pixel formats previously had on AVHWAccel instances, meaning only those which actually do something need exist after this patch. Also updates avcodec_default_get_format() to be able to choose hardware formats if either a matching device has been supplied or no additional external configuration is required, and avcodec_get_hw_frames_parameters() to use the hardware config rather than searching the old hwaccel list. --- libavcodec/decode.c | 281 ++++++++++++++++++++++++++++++------------ libavcodec/internal.h | 6 + 2 files changed, 210 insertions(+), 77 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 27f75d73e3e8a..bc2208a3fd104 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -34,6 +34,7 @@ #include "avcodec.h" #include "bytestream.h" #include "decode.h" +#include "hwaccel.h" #include "internal.h" #include "thread.h" @@ -644,29 +645,67 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, return ret; } -static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt) +enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *avctx, + const enum AVPixelFormat *fmt) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - return desc->flags & AV_PIX_FMT_FLAG_HWACCEL; -} - -enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat *fmt) -{ - while (*fmt != AV_PIX_FMT_NONE && is_hwaccel_pix_fmt(*fmt)) - ++fmt; - return fmt[0]; -} - -static AVHWAccel *find_hwaccel(enum AVCodecID codec_id, - enum AVPixelFormat pix_fmt) -{ - AVHWAccel *hwaccel = NULL; + const AVPixFmtDescriptor *desc; + const AVCodecHWConfig *config; + int i, n; + + // If a device was supplied when the codec was opened, assume that the + // user wants to use it. + if (avctx->hw_device_ctx && avctx->codec->hw_configs) { + AVHWDeviceContext *device_ctx = + (AVHWDeviceContext*)avctx->hw_device_ctx->data; + for (i = 0;; i++) { + config = &avctx->codec->hw_configs[i]->public; + if (!config) + break; + if (!(config->methods & + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) + continue; + if (device_ctx->type != config->device_type) + continue; + for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++) { + if (config->pix_fmt == fmt[n]) + return fmt[n]; + } + } + } + // No device or other setup, so we have to choose from things which + // don't any other external information. + + // If the last element of the list is a software format, choose it + // (this should be best software format if any exist). + for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++); + desc = av_pix_fmt_desc_get(fmt[n - 1]); + if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) + return fmt[n - 1]; + + // Finally, traverse the list in order and choose the first entry + // with no external dependencies (if there is no hardware configuration + // information available then this just picks the first entry). + for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++) { + for (i = 0;; i++) { + config = avcodec_get_hw_config(avctx->codec, i); + if (!config) + break; + if (config->pix_fmt == fmt[n]) + break; + } + if (!config) { + // No specific config available, so the decoder must be able + // to handle this format without any additional setup. + return fmt[n]; + } + if (config->methods & AV_CODEC_HW_CONFIG_METHOD_INTERNAL) { + // Usable with only internal setup. + return fmt[n]; + } + } - while ((hwaccel = av_hwaccel_next(hwaccel))) - if (hwaccel->id == codec_id - && hwaccel->pix_fmt == pix_fmt) - return hwaccel; - return NULL; + // Nothing is usable, give up. + return AV_PIX_FMT_NONE; } int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx, @@ -730,9 +769,19 @@ int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, AVBufferRef **out_frames_ref) { AVBufferRef *frames_ref = NULL; - AVHWAccel *hwa = find_hwaccel(avctx->codec_id, hw_pix_fmt); - int ret; + const AVCodecHWConfigInternal *hw_config; + const AVHWAccel *hwa; + int i, ret; + + for (i = 0;; i++) { + hw_config = avctx->codec->hw_configs[i]; + if (!hw_config) + return AVERROR(ENOENT); + if (hw_config->public.pix_fmt == hw_pix_fmt) + break; + } + hwa = hw_config->hwaccel; if (!hwa || !hwa->frame_params) return AVERROR(ENOENT); @@ -749,52 +798,66 @@ int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, return ret; } -static int setup_hwaccel(AVCodecContext *avctx, - const enum AVPixelFormat fmt, - const char *name) +static int hwaccel_init(AVCodecContext *avctx, + const AVCodecHWConfigInternal *hw_config) { - AVHWAccel *hwa = find_hwaccel(avctx->codec_id, fmt); - int ret = 0; - - if (!hwa) { - av_log(avctx, AV_LOG_ERROR, - "Could not find an AVHWAccel for the pixel format: %s", - name); - return AVERROR(ENOENT); - } + const AVHWAccel *hwaccel; + int err; - if (hwa->priv_data_size) { - avctx->internal->hwaccel_priv_data = av_mallocz(hwa->priv_data_size); + hwaccel = hw_config->hwaccel; + if (hwaccel->priv_data_size) { + avctx->internal->hwaccel_priv_data = + av_mallocz(hwaccel->priv_data_size); if (!avctx->internal->hwaccel_priv_data) return AVERROR(ENOMEM); } - avctx->hwaccel = hwa; - if (hwa->init) { - ret = hwa->init(avctx); - if (ret < 0) { - av_freep(&avctx->internal->hwaccel_priv_data); - avctx->hwaccel = NULL; - return ret; - } + avctx->hwaccel = (AVHWAccel*)hwaccel; + err = hwaccel->init(avctx); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed setup for format %s: " + "hwaccel initialisation returned error.\n", + av_get_pix_fmt_name(hw_config->public.pix_fmt)); + av_freep(&avctx->internal->hwaccel_priv_data); + avctx->hwaccel = NULL; + return err; } return 0; } +static void hwaccel_uninit(AVCodecContext *avctx) +{ + if (avctx->hwaccel && avctx->hwaccel->uninit) + avctx->hwaccel->uninit(avctx); + + av_freep(&avctx->internal->hwaccel_priv_data); + + avctx->hwaccel = NULL; + + av_buffer_unref(&avctx->hw_frames_ctx); +} + int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) { const AVPixFmtDescriptor *desc; enum AVPixelFormat *choices; - enum AVPixelFormat ret; - unsigned n = 0; - - while (fmt[n] != AV_PIX_FMT_NONE) - ++n; - + enum AVPixelFormat ret, user_choice; + const AVCodecHWConfigInternal *hw_config; + const AVCodecHWConfig *config; + int i, n, err; + + // Find end of list. + for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++); + // Must contain at least one entry. av_assert0(n >= 1); - avctx->sw_pix_fmt = fmt[n - 1]; - av_assert2(!is_hwaccel_pix_fmt(avctx->sw_pix_fmt)); + // If a software format is available, it must be the last entry. + desc = av_pix_fmt_desc_get(fmt[n - 1]); + if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) { + // No software format is available. + } else { + avctx->sw_pix_fmt = fmt[n - 1]; + } choices = av_malloc_array(n + 1, sizeof(*choices)); if (!choices) @@ -803,44 +866,108 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) memcpy(choices, fmt, (n + 1) * sizeof(*choices)); for (;;) { - if (avctx->hwaccel && avctx->hwaccel->uninit) - avctx->hwaccel->uninit(avctx); - av_freep(&avctx->internal->hwaccel_priv_data); - avctx->hwaccel = NULL; - - av_buffer_unref(&avctx->hw_frames_ctx); + // Remove the previous hwaccel, if there was one. + hwaccel_uninit(avctx); - ret = avctx->get_format(avctx, choices); + user_choice = avctx->get_format(avctx, choices); + if (user_choice == AV_PIX_FMT_NONE) { + // Explicitly chose nothing, give up. + ret = AV_PIX_FMT_NONE; + break; + } - desc = av_pix_fmt_desc_get(ret); + desc = av_pix_fmt_desc_get(user_choice); if (!desc) { + av_log(avctx, AV_LOG_ERROR, "Invalid format returned by " + "get_format() callback.\n"); ret = AV_PIX_FMT_NONE; break; } + av_log(avctx, AV_LOG_DEBUG, "Format %s chosen by get_format().\n", + desc->name); - if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) + for (i = 0; i < n; i++) { + if (choices[i] == user_choice) + break; + } + if (i == n) { + av_log(avctx, AV_LOG_ERROR, "Invalid return from get_format(): " + "%s not in possible list.\n", desc->name); break; + } - if (avctx->hw_frames_ctx) { - AVHWFramesContext *hw_frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - if (hw_frames_ctx->format != ret) { - av_log(avctx, AV_LOG_ERROR, "Format returned from get_buffer() " - "does not match the format of provided AVHWFramesContext\n"); - ret = AV_PIX_FMT_NONE; - break; + if (avctx->codec->hw_configs) { + for (i = 0;; i++) { + hw_config = avctx->codec->hw_configs[i]; + if (!hw_config) + break; + if (hw_config->public.pix_fmt == user_choice) + break; } + } else { + hw_config = NULL; } - if (!setup_hwaccel(avctx, ret, desc->name)) + if (!hw_config) { + // No config available, so no extra setup required. + ret = user_choice; break; + } + config = &hw_config->public; + + if (config->methods & + AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX && + avctx->hw_frames_ctx) { + const AVHWFramesContext *frames_ctx = + (AVHWFramesContext*)avctx->hw_frames_ctx->data; + if (frames_ctx->format != user_choice) { + av_log(avctx, AV_LOG_ERROR, "Invalid setup for format %s: " + "does not match the format of the provided frames " + "context.\n", desc->name); + goto try_again; + } + } else if (config->methods & + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX && + avctx->hw_device_ctx) { + const AVHWDeviceContext *device_ctx = + (AVHWDeviceContext*)avctx->hw_device_ctx->data; + if (device_ctx->type != config->device_type) { + av_log(avctx, AV_LOG_ERROR, "Invalid setup for format %s: " + "does not match the type of the provided device " + "context.\n", desc->name); + goto try_again; + } + } else if (config->methods & + AV_CODEC_HW_CONFIG_METHOD_INTERNAL) { + // Internal-only setup, no additional configuration. + } else if (config->methods & + AV_CODEC_HW_CONFIG_METHOD_AD_HOC) { + // Some ad-hoc configuration we can't see and can't check. + } else { + av_log(avctx, AV_LOG_ERROR, "Invalid setup for format %s: " + "missing configuration.\n", desc->name); + goto try_again; + } + if (hw_config->hwaccel) { + av_log(avctx, AV_LOG_DEBUG, "Format %s requires hwaccel " + "initialisation.\n", desc->name); + err = hwaccel_init(avctx, hw_config); + if (err < 0) + goto try_again; + } + ret = user_choice; + break; - /* Remove failed hwaccel from choices */ - for (n = 0; choices[n] != ret; n++) - av_assert0(choices[n] != AV_PIX_FMT_NONE); - - do - choices[n] = choices[n + 1]; - while (choices[n++] != AV_PIX_FMT_NONE); + try_again: + av_log(avctx, AV_LOG_DEBUG, "Format %s not usable, retrying " + "get_format() without it.\n", desc->name); + for (i = 0; i < n; i++) { + if (choices[i] == user_choice) + break; + } + for (; i + 1 < n; i++) + choices[i] = choices[i + 1]; + --n; } av_freep(&choices); diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 868e3dfc541ed..a619e977f6eec 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -272,6 +272,12 @@ int ff_side_data_update_matrix_encoding(AVFrame *frame, * Select the (possibly hardware accelerated) pixel format. * This is a wrapper around AVCodecContext.get_format() and should be used * instead of calling get_format() directly. + * + * The list of pixel formats must contain at least one valid entry, and is + * terminated with AV_PIX_FMT_NONE. If it is possible to decode to software, + * the last entry in the list must be the most accurate software format. + * If it is not possible to decode to software, AVCodecContext.sw_pix_fmt + * must be set before calling this function. */ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt); From e2d575543ceeee72f12ac911e72f802bc6cba32e Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:44 +0100 Subject: [PATCH 1395/2557] lavc: Deprecate av_hwaccel_next() and av_register_hwaccel() --- doc/APIchanges | 4 ++++ libavcodec/avcodec.h | 13 +++++++++++++ libavcodec/utils.c | 15 +++++---------- libavcodec/version.h | 5 ++++- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index f5f15c49a1e3c..e29fb241721e9 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,10 @@ libavutil: 2017-03-23 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavc 58.7.0 - avcodec.h + Deprecate user visibility of the AVHWAccel structure and the functions + av_register_hwaccel() and av_hwaccel_next(). + 2017-xx-xx - xxxxxxx - lavc 58.6.0 - avcodec.h Add AVCodecHWConfig and avcodec_get_hw_config(). diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index cf9f9dfe84dfc..53b5a7c4d4aeb 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2962,6 +2962,10 @@ const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index); /** * @defgroup lavc_hwaccel AVHWAccel + * + * @note Nothing in this structure should be accessed by the user. At some + * point in future it will not be externally visible at all. + * * @{ */ typedef struct AVHWAccel { @@ -5040,17 +5044,26 @@ void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size); */ unsigned int av_xiphlacing(unsigned char *s, unsigned int v); +#if FF_API_USER_VISIBLE_AVHWACCEL /** * Register the hardware accelerator hwaccel. + * + * @deprecated This function doesn't do anything. */ +attribute_deprecated void av_register_hwaccel(AVHWAccel *hwaccel); /** * If hwaccel is NULL, returns the first registered hardware accelerator, * if hwaccel is non-NULL, returns the next registered hardware accelerator * after hwaccel, or NULL if hwaccel is the last one. + * + * @deprecated AVHWaccel structures contain no user-serviceable parts, so + * this function should not be used. */ +attribute_deprecated AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel); +#endif /** diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 3d6b35fa41c99..ba3457664ae5c 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -1347,21 +1347,16 @@ const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index) return &codec->hw_configs[index]->public; } -static AVHWAccel *first_hwaccel = NULL; - -void av_register_hwaccel(AVHWAccel *hwaccel) +#if FF_API_USER_VISIBLE_AVHWACCEL +AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel) { - AVHWAccel **p = &first_hwaccel; - while (*p) - p = &(*p)->next; - *p = hwaccel; - hwaccel->next = NULL; + return NULL; } -AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel) +void av_register_hwaccel(AVHWAccel *hwaccel) { - return hwaccel ? hwaccel->next : first_hwaccel; } +#endif int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) { diff --git a/libavcodec/version.h b/libavcodec/version.h index e6edd5c867557..7ef743dc69ee4 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 6 +#define LIBAVCODEC_VERSION_MINOR 7 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ @@ -95,5 +95,8 @@ #ifndef FF_API_VAAPI_CONTEXT #define FF_API_VAAPI_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 59) #endif +#ifndef FF_API_USER_VISIBLE_AVHWACCEL +#define FF_API_USER_VISIBLE_AVHWACCEL (LIBAVCODEC_VERSION_MAJOR < 60) +#endif #endif /* AVCODEC_VERSION_H */ From 433522a1b985ef03bdb3ea77714f708b8ee014ae Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:45 +0100 Subject: [PATCH 1396/2557] lavc: Remove register mechanism for hwaccels There is no longer any need for a list of them at runtime, because decoders now carry the pointers to their associated hwaccels internally. The file containing external declarations is now used to make the list of hwaccels for configure. --- configure | 2 +- libavcodec/allcodecs.c | 51 ------------------------------------------ 2 files changed, 1 insertion(+), 52 deletions(-) diff --git a/configure b/configure index 7f320fee18d63..d0e1980dc1b7f 100755 --- a/configure +++ b/configure @@ -2704,7 +2704,6 @@ find_things(){ ENCODER_LIST=$(find_things encoder ENC libavcodec/allcodecs.c) DECODER_LIST=$(find_things decoder DEC libavcodec/allcodecs.c) -HWACCEL_LIST=$(find_things hwaccel HWACCEL libavcodec/allcodecs.c) PARSER_LIST=$(find_things parser PARSER libavcodec/allcodecs.c) MUXER_LIST=$(find_things muxer _MUX libavformat/allformats.c) DEMUXER_LIST=$(find_things demuxer DEMUX libavformat/allformats.c) @@ -2719,6 +2718,7 @@ find_things_extern(){ } BSF_LIST=$(find_things_extern bsf AVBitStreamFilter libavcodec/bitstream_filters.c) +HWACCEL_LIST=$(find_things_extern hwaccel AVHWAccel libavcodec/hwaccels.h) PROTOCOL_LIST=$(find_things_extern protocol URLProtocol libavformat/protocols.c) AVCODEC_COMPONENTS_LIST=" diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4ece4307a09d9..50a87493eab91 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -28,13 +28,6 @@ #include "avcodec.h" #include "version.h" -#define REGISTER_HWACCEL(X, x) \ - { \ - extern AVHWAccel ff_##x##_hwaccel; \ - if (CONFIG_##X##_HWACCEL) \ - av_register_hwaccel(&ff_##x##_hwaccel); \ - } - #define REGISTER_ENCODER(X, x) \ { \ extern AVCodec ff_##x##_encoder; \ @@ -66,50 +59,6 @@ void avcodec_register_all(void) return; initialized = 1; - /* hardware accelerators */ - REGISTER_HWACCEL(H263_VAAPI, h263_vaapi); - REGISTER_HWACCEL(H264_CUVID, h264_cuvid); - REGISTER_HWACCEL(H264_D3D11VA, h264_d3d11va); - REGISTER_HWACCEL(H264_D3D11VA2, h264_d3d11va2); - REGISTER_HWACCEL(H264_DXVA2, h264_dxva2); - REGISTER_HWACCEL(H264_MMAL, h264_mmal); - REGISTER_HWACCEL(H264_QSV, h264_qsv); - REGISTER_HWACCEL(H264_VAAPI, h264_vaapi); - REGISTER_HWACCEL(H264_VDA, h264_vda); - REGISTER_HWACCEL(H264_VDA_OLD, h264_vda_old); - REGISTER_HWACCEL(H264_VDPAU, h264_vdpau); - REGISTER_HWACCEL(HEVC_CUVID, hevc_cuvid); - REGISTER_HWACCEL(HEVC_D3D11VA, hevc_d3d11va); - REGISTER_HWACCEL(HEVC_D3D11VA2, hevc_d3d11va2); - REGISTER_HWACCEL(HEVC_DXVA2, hevc_dxva2); - REGISTER_HWACCEL(HEVC_QSV, hevc_qsv); - REGISTER_HWACCEL(HEVC_VAAPI, hevc_vaapi); - REGISTER_HWACCEL(HEVC_VDPAU, hevc_vdpau); - REGISTER_HWACCEL(MPEG1_VDPAU, mpeg1_vdpau); - REGISTER_HWACCEL(MPEG2_D3D11VA, mpeg2_d3d11va); - REGISTER_HWACCEL(MPEG2_D3D11VA2, mpeg2_d3d11va2); - REGISTER_HWACCEL(MPEG2_DXVA2, mpeg2_dxva2); - REGISTER_HWACCEL(MPEG2_MMAL, mpeg2_mmal); - REGISTER_HWACCEL(MPEG2_QSV, mpeg2_qsv); - REGISTER_HWACCEL(MPEG2_VAAPI, mpeg2_vaapi); - REGISTER_HWACCEL(MPEG2_VDPAU, mpeg2_vdpau); - REGISTER_HWACCEL(MPEG4_VAAPI, mpeg4_vaapi); - REGISTER_HWACCEL(MPEG4_VDPAU, mpeg4_vdpau); - REGISTER_HWACCEL(VC1_D3D11VA, vc1_d3d11va); - REGISTER_HWACCEL(VC1_D3D11VA2, vc1_d3d11va2); - REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2); - REGISTER_HWACCEL(VC1_QSV, vc1_qsv); - REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi); - REGISTER_HWACCEL(VC1_VDPAU, vc1_vdpau); - REGISTER_HWACCEL(VC1_MMAL, vc1_mmal); - REGISTER_HWACCEL(VP8_QSV, vp8_qsv); - REGISTER_HWACCEL(VP8_VAAPI, vp8_vaapi); - REGISTER_HWACCEL(WMV3_D3D11VA, wmv3_d3d11va); - REGISTER_HWACCEL(WMV3_D3D11VA2, wmv3_d3d11va2); - REGISTER_HWACCEL(WMV3_DXVA2, wmv3_dxva2); - REGISTER_HWACCEL(WMV3_VAAPI, wmv3_vaapi); - REGISTER_HWACCEL(WMV3_VDPAU, wmv3_vdpau); - /* video codecs */ REGISTER_ENCODER(A64MULTI, a64multi); REGISTER_ENCODER(A64MULTI5, a64multi5); From 2a4d34d462d60799e045c370dc9b2505f18365e7 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:46 +0100 Subject: [PATCH 1397/2557] lavc: Delete all fake hwaccels They are now unused. --- configure | 18 +++++------------- libavcodec/mmaldec.c | 21 --------------------- libavcodec/qsvdec_h2645.c | 18 ------------------ libavcodec/qsvdec_other.c | 27 --------------------------- 4 files changed, 5 insertions(+), 79 deletions(-) diff --git a/configure b/configure index d0e1980dc1b7f..d31cb56588c5b 100755 --- a/configure +++ b/configure @@ -2183,8 +2183,6 @@ h264_d3d11va2_hwaccel_deps="d3d11va" h264_d3d11va2_hwaccel_select="h264_decoder" h264_dxva2_hwaccel_deps="dxva2" h264_dxva2_hwaccel_select="h264_decoder" -h264_mmal_hwaccel_deps="mmal" -h264_qsv_hwaccel_deps="libmfx" h264_vaapi_hwaccel_deps="vaapi" h264_vaapi_hwaccel_select="h264_decoder" h264_vda_hwaccel_deps="vda" @@ -2201,7 +2199,6 @@ hevc_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" hevc_d3d11va2_hwaccel_select="hevc_decoder" hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC" hevc_dxva2_hwaccel_select="hevc_decoder" -hevc_qsv_hwaccel_deps="libmfx" hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC" hevc_vaapi_hwaccel_select="hevc_decoder" hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC" @@ -2214,8 +2211,6 @@ mpeg2_d3d11va2_hwaccel_deps="d3d11va" mpeg2_d3d11va2_hwaccel_select="mpeg2video_decoder" mpeg2_dxva2_hwaccel_deps="dxva2" mpeg2_dxva2_hwaccel_select="mpeg2video_decoder" -mpeg2_mmal_hwaccel_deps="mmal" -mpeg2_qsv_hwaccel_deps="libmfx" mpeg2_vaapi_hwaccel_deps="vaapi" mpeg2_vaapi_hwaccel_select="mpeg2video_decoder" mpeg2_vdpau_hwaccel_deps="vdpau" @@ -2230,13 +2225,10 @@ vc1_d3d11va2_hwaccel_deps="d3d11va" vc1_d3d11va2_hwaccel_select="vc1_decoder" vc1_dxva2_hwaccel_deps="dxva2" vc1_dxva2_hwaccel_select="vc1_decoder" -vc1_mmal_hwaccel_deps="mmal" -vc1_qsv_hwaccel_deps="libmfx" vc1_vaapi_hwaccel_deps="vaapi" vc1_vaapi_hwaccel_select="vc1_decoder" vc1_vdpau_hwaccel_deps="vdpau" vc1_vdpau_hwaccel_select="vc1_decoder" -vp8_qsv_hwaccel_deps="libmfx" vp8_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferVP8" vp8_vaapi_hwaccel_select="vp8_decoder" wmv3_d3d11va_hwaccel_select="vc1_d3d11va_hwaccel" @@ -2261,12 +2253,12 @@ scale_npp_filter_deps="cuda libnpp" h264_mmal_decoder_deps="mmal" h264_nvenc_encoder_deps="nvenc" h264_omx_encoder_deps="omx" -h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec h264_qsv_hwaccel" +h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec" h264_qsv_encoder_select="qsvenc" h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" h264_vaapi_encoder_select="cbs_h264 vaapi_encode" hevc_nvenc_encoder_deps="nvenc" -hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser hevc_qsv_hwaccel qsvdec" +hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser qsvdec" hevc_qsv_encoder_select="hevcparse qsvenc" hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" hevc_vaapi_encoder_select="cbs_h265 vaapi_encode" @@ -2275,14 +2267,14 @@ mjpeg_qsv_encoder_select="qsvenc" mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG" mjpeg_vaapi_encoder_select="vaapi_encode jpegtables" mpeg2_mmal_decoder_deps="mmal" -mpeg2_qsv_decoder_select="qsvdec mpeg2_qsv_hwaccel mpegvideo_parser" +mpeg2_qsv_decoder_select="qsvdec mpegvideo_parser" mpeg2_qsv_encoder_select="qsvenc" mpeg2_vaapi_encoder_deps="VAEncPictureParameterBufferMPEG2" mpeg2_vaapi_encoder_select="cbs_mpeg2 vaapi_encode" mpeg4_omx_encoder_deps="omx" vc1_mmal_decoder_deps="mmal" -vc1_qsv_decoder_select="qsvdec vc1_qsv_hwaccel vc1_parser" -vp8_qsv_decoder_select="qsvdec vp8_qsv_hwaccel vp8_parser" +vc1_qsv_decoder_select="qsvdec vc1_parser" +vp8_qsv_decoder_select="qsvdec vp8_parser" vp8_vaapi_encoder_deps="VAEncPictureParameterBufferVP8" vp8_vaapi_encoder_select="vaapi_encode" vp9_vaapi_encoder_deps="VAEncPictureParameterBufferVP9" diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index 9ed8e61371852..10a48d3e0f748 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -788,27 +788,6 @@ static int ffmmal_decode(AVCodecContext *avctx, void *data, int *got_frame, return ret; } -AVHWAccel ff_h264_mmal_hwaccel = { - .name = "h264_mmal", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .pix_fmt = AV_PIX_FMT_MMAL, -}; - -AVHWAccel ff_mpeg2_mmal_hwaccel = { - .name = "mpeg2_mmal", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO, - .pix_fmt = AV_PIX_FMT_MMAL, -}; - -AVHWAccel ff_vc1_mmal_hwaccel = { - .name = "vc1_mmal", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VC1, - .pix_fmt = AV_PIX_FMT_MMAL, -}; - static const AVCodecHWConfigInternal *mmal_hw_configs = { HW_CONFIG_INTERNAL(MMAL), NULL diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c index a7b39da6bf763..83880dc085e2c 100644 --- a/libavcodec/qsvdec_h2645.c +++ b/libavcodec/qsvdec_h2645.c @@ -180,15 +180,6 @@ static void qsv_decode_flush(AVCodecContext *avctx) #define OFFSET(x) offsetof(QSVH2645Context, x) #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM -#if CONFIG_HEVC_QSV_HWACCEL -AVHWAccel ff_hevc_qsv_hwaccel = { - .name = "hevc_qsv", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HEVC, - .pix_fmt = AV_PIX_FMT_QSV, -}; -#endif - #if CONFIG_HEVC_QSV_DECODER static const AVOption hevc_options[] = { { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD }, @@ -232,15 +223,6 @@ AVCodec ff_hevc_qsv_decoder = { }; #endif -#if CONFIG_H264_QSV_HWACCEL -AVHWAccel ff_h264_qsv_hwaccel = { - .name = "h264_qsv", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .pix_fmt = AV_PIX_FMT_QSV, -}; -#endif - #if CONFIG_H264_QSV_DECODER static const AVOption options[] = { { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD }, diff --git a/libavcodec/qsvdec_other.c b/libavcodec/qsvdec_other.c index 63cc113c5cbe2..90693ed31728f 100644 --- a/libavcodec/qsvdec_other.c +++ b/libavcodec/qsvdec_other.c @@ -163,15 +163,6 @@ static const AVOption options[] = { { NULL }, }; -#if CONFIG_MPEG2_QSV_HWACCEL -AVHWAccel ff_mpeg2_qsv_hwaccel = { - .name = "mpeg2_qsv", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO, - .pix_fmt = AV_PIX_FMT_QSV, -}; -#endif - #if CONFIG_MPEG2_QSV_DECODER static const AVClass mpeg2_qsv_class = { .class_name = "mpeg2_qsv", @@ -200,15 +191,6 @@ AVCodec ff_mpeg2_qsv_decoder = { }; #endif -#if CONFIG_VC1_QSV_HWACCEL -AVHWAccel ff_vc1_qsv_hwaccel = { - .name = "vc1_qsv", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VC1, - .pix_fmt = AV_PIX_FMT_QSV, -}; -#endif - #if CONFIG_VC1_QSV_DECODER static const AVClass vc1_qsv_class = { .class_name = "vc1_qsv", @@ -237,15 +219,6 @@ AVCodec ff_vc1_qsv_decoder = { }; #endif -#if CONFIG_VP8_QSV_HWACCEL -AVHWAccel ff_vp8_qsv_hwaccel = { - .name = "vp8_qsv", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP8, - .pix_fmt = AV_PIX_FMT_QSV, -}; -#endif - #if CONFIG_VP8_QSV_DECODER static const AVClass vp8_qsv_class = { .class_name = "vp8_qsv", From 2117725dc56e0d20da641a3311939cf4e2ed9549 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 4 Nov 2017 18:53:26 +0000 Subject: [PATCH 1398/2557] lavc: Mark all AVHWAccel structures as const --- doc/APIchanges | 3 ++ libavcodec/avcodec.h | 2 +- libavcodec/cuvid_h264.c | 2 +- libavcodec/cuvid_hevc.c | 2 +- libavcodec/decode.c | 2 +- libavcodec/dxva2_h264.c | 6 ++-- libavcodec/dxva2_hevc.c | 6 ++-- libavcodec/dxva2_mpeg2.c | 6 ++-- libavcodec/dxva2_vc1.c | 12 +++---- libavcodec/hwaccels.h | 68 +++++++++++++++++++-------------------- libavcodec/vaapi_h264.c | 2 +- libavcodec/vaapi_hevc.c | 2 +- libavcodec/vaapi_mpeg2.c | 2 +- libavcodec/vaapi_mpeg4.c | 4 +-- libavcodec/vaapi_vc1.c | 4 +-- libavcodec/vaapi_vp8.c | 2 +- libavcodec/vda_h264.c | 4 +-- libavcodec/vdpau_h264.c | 2 +- libavcodec/vdpau_hevc.c | 2 +- libavcodec/vdpau_mpeg12.c | 4 +-- libavcodec/vdpau_mpeg4.c | 2 +- libavcodec/vdpau_vc1.c | 4 +-- libavcodec/version.h | 2 +- 23 files changed, 74 insertions(+), 71 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index e29fb241721e9..0bde3a052d43c 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2017-03-23 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavc 58.8.0 - avcodec.h + Add const to AVCodecContext.hwaccel. + 2017-xx-xx - xxxxxxx - lavc 58.7.0 - avcodec.h Deprecate user visibility of the AVHWAccel structure and the functions av_register_hwaccel() and av_hwaccel_next(). diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 53b5a7c4d4aeb..7eaa0c9277318 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2307,7 +2307,7 @@ typedef struct AVCodecContext { * - encoding: unused. * - decoding: Set by libavcodec */ - struct AVHWAccel *hwaccel; + const struct AVHWAccel *hwaccel; /** * Hardware accelerator context. diff --git a/libavcodec/cuvid_h264.c b/libavcodec/cuvid_h264.c index a83e4ffba0bdc..4f36e922be7d7 100644 --- a/libavcodec/cuvid_h264.c +++ b/libavcodec/cuvid_h264.c @@ -163,7 +163,7 @@ static int cuvid_h264_decode_init(AVCodecContext *avctx) return ff_cuvid_decode_init(avctx, sps->ref_frame_count + sps->num_reorder_frames); } -AVHWAccel ff_h264_cuvid_hwaccel = { +const AVHWAccel ff_h264_cuvid_hwaccel = { .name = "h264_cuvid", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, diff --git a/libavcodec/cuvid_hevc.c b/libavcodec/cuvid_hevc.c index 5de9bca4836c1..fcf20bbcfaa0f 100644 --- a/libavcodec/cuvid_hevc.c +++ b/libavcodec/cuvid_hevc.c @@ -266,7 +266,7 @@ static int cuvid_hevc_decode_init(AVCodecContext *avctx) return ff_cuvid_decode_init(avctx, sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering + 1); } -AVHWAccel ff_hevc_cuvid_hwaccel = { +const AVHWAccel ff_hevc_cuvid_hwaccel = { .name = "hevc_cuvid", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, diff --git a/libavcodec/decode.c b/libavcodec/decode.c index bc2208a3fd104..12a95d4221b8b 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -812,7 +812,7 @@ static int hwaccel_init(AVCodecContext *avctx, return AVERROR(ENOMEM); } - avctx->hwaccel = (AVHWAccel*)hwaccel; + avctx->hwaccel = hwaccel; err = hwaccel->init(avctx); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed setup for format %s: " diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c index 8ce8c358c5c43..50e7863bf2bba 100644 --- a/libavcodec/dxva2_h264.c +++ b/libavcodec/dxva2_h264.c @@ -513,7 +513,7 @@ static int dxva2_h264_end_frame(AVCodecContext *avctx) } #if CONFIG_H264_DXVA2_HWACCEL -AVHWAccel ff_h264_dxva2_hwaccel = { +const AVHWAccel ff_h264_dxva2_hwaccel = { .name = "h264_dxva2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, @@ -530,7 +530,7 @@ AVHWAccel ff_h264_dxva2_hwaccel = { #endif #if CONFIG_H264_D3D11VA_HWACCEL -AVHWAccel ff_h264_d3d11va_hwaccel = { +const AVHWAccel ff_h264_d3d11va_hwaccel = { .name = "h264_d3d11va", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, @@ -547,7 +547,7 @@ AVHWAccel ff_h264_d3d11va_hwaccel = { #endif #if CONFIG_H264_D3D11VA2_HWACCEL -AVHWAccel ff_h264_d3d11va2_hwaccel = { +const AVHWAccel ff_h264_d3d11va2_hwaccel = { .name = "h264_d3d11va2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c index 1d665f07d19cd..02d3b9b1526eb 100644 --- a/libavcodec/dxva2_hevc.c +++ b/libavcodec/dxva2_hevc.c @@ -422,7 +422,7 @@ static int dxva2_hevc_end_frame(AVCodecContext *avctx) } #if CONFIG_HEVC_DXVA2_HWACCEL -AVHWAccel ff_hevc_dxva2_hwaccel = { +const AVHWAccel ff_hevc_dxva2_hwaccel = { .name = "hevc_dxva2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, @@ -439,7 +439,7 @@ AVHWAccel ff_hevc_dxva2_hwaccel = { #endif #if CONFIG_HEVC_D3D11VA_HWACCEL -AVHWAccel ff_hevc_d3d11va_hwaccel = { +const AVHWAccel ff_hevc_d3d11va_hwaccel = { .name = "hevc_d3d11va", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, @@ -456,7 +456,7 @@ AVHWAccel ff_hevc_d3d11va_hwaccel = { #endif #if CONFIG_HEVC_D3D11VA2_HWACCEL -AVHWAccel ff_hevc_d3d11va2_hwaccel = { +const AVHWAccel ff_hevc_d3d11va2_hwaccel = { .name = "hevc_d3d11va2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, diff --git a/libavcodec/dxva2_mpeg2.c b/libavcodec/dxva2_mpeg2.c index 036d5baac5a02..6e5dff308fa9e 100644 --- a/libavcodec/dxva2_mpeg2.c +++ b/libavcodec/dxva2_mpeg2.c @@ -318,7 +318,7 @@ static int dxva2_mpeg2_end_frame(AVCodecContext *avctx) } #if CONFIG_MPEG2_DXVA2_HWACCEL -AVHWAccel ff_mpeg2_dxva2_hwaccel = { +const AVHWAccel ff_mpeg2_dxva2_hwaccel = { .name = "mpeg2_dxva2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, @@ -335,7 +335,7 @@ AVHWAccel ff_mpeg2_dxva2_hwaccel = { #endif #if CONFIG_MPEG2_D3D11VA_HWACCEL -AVHWAccel ff_mpeg2_d3d11va_hwaccel = { +const AVHWAccel ff_mpeg2_d3d11va_hwaccel = { .name = "mpeg2_d3d11va", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, @@ -352,7 +352,7 @@ AVHWAccel ff_mpeg2_d3d11va_hwaccel = { #endif #if CONFIG_MPEG2_D3D11VA2_HWACCEL -AVHWAccel ff_mpeg2_d3d11va2_hwaccel = { +const AVHWAccel ff_mpeg2_d3d11va2_hwaccel = { .name = "mpeg2_d3d11va2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c index 79f758a3b962c..247ea47825259 100644 --- a/libavcodec/dxva2_vc1.c +++ b/libavcodec/dxva2_vc1.c @@ -318,7 +318,7 @@ static int dxva2_vc1_end_frame(AVCodecContext *avctx) } #if CONFIG_WMV3_DXVA2_HWACCEL -AVHWAccel ff_wmv3_dxva2_hwaccel = { +const AVHWAccel ff_wmv3_dxva2_hwaccel = { .name = "wmv3_dxva2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, @@ -335,7 +335,7 @@ AVHWAccel ff_wmv3_dxva2_hwaccel = { #endif #if CONFIG_VC1_DXVA2_HWACCEL -AVHWAccel ff_vc1_dxva2_hwaccel = { +const AVHWAccel ff_vc1_dxva2_hwaccel = { .name = "vc1_dxva2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, @@ -352,7 +352,7 @@ AVHWAccel ff_vc1_dxva2_hwaccel = { #endif #if CONFIG_WMV3_D3D11VA_HWACCEL -AVHWAccel ff_wmv3_d3d11va_hwaccel = { +const AVHWAccel ff_wmv3_d3d11va_hwaccel = { .name = "wmv3_d3d11va", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, @@ -369,7 +369,7 @@ AVHWAccel ff_wmv3_d3d11va_hwaccel = { #endif #if CONFIG_WMV3_D3D11VA2_HWACCEL -AVHWAccel ff_wmv3_d3d11va2_hwaccel = { +const AVHWAccel ff_wmv3_d3d11va2_hwaccel = { .name = "wmv3_d3d11va2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, @@ -386,7 +386,7 @@ AVHWAccel ff_wmv3_d3d11va2_hwaccel = { #endif #if CONFIG_VC1_D3D11VA_HWACCEL -AVHWAccel ff_vc1_d3d11va_hwaccel = { +const AVHWAccel ff_vc1_d3d11va_hwaccel = { .name = "vc1_d3d11va", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, @@ -403,7 +403,7 @@ AVHWAccel ff_vc1_d3d11va_hwaccel = { #endif #if CONFIG_VC1_D3D11VA2_HWACCEL -AVHWAccel ff_vc1_d3d11va2_hwaccel = { +const AVHWAccel ff_vc1_d3d11va2_hwaccel = { .name = "vc1_d3d11va2", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h index 6dee94b44ff81..afa86f14e496f 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -21,39 +21,39 @@ #include "avcodec.h" -extern AVHWAccel ff_h263_vaapi_hwaccel; -extern AVHWAccel ff_h264_cuvid_hwaccel; -extern AVHWAccel ff_h264_d3d11va_hwaccel; -extern AVHWAccel ff_h264_d3d11va2_hwaccel; -extern AVHWAccel ff_h264_dxva2_hwaccel; -extern AVHWAccel ff_h264_vaapi_hwaccel; -extern AVHWAccel ff_h264_vda_hwaccel; -extern AVHWAccel ff_h264_vda_old_hwaccel; -extern AVHWAccel ff_h264_vdpau_hwaccel; -extern AVHWAccel ff_hevc_cuvid_hwaccel; -extern AVHWAccel ff_hevc_d3d11va_hwaccel; -extern AVHWAccel ff_hevc_d3d11va2_hwaccel; -extern AVHWAccel ff_hevc_dxva2_hwaccel; -extern AVHWAccel ff_hevc_vaapi_hwaccel; -extern AVHWAccel ff_hevc_vdpau_hwaccel; -extern AVHWAccel ff_mpeg1_vdpau_hwaccel; -extern AVHWAccel ff_mpeg2_d3d11va_hwaccel; -extern AVHWAccel ff_mpeg2_d3d11va2_hwaccel; -extern AVHWAccel ff_mpeg2_dxva2_hwaccel; -extern AVHWAccel ff_mpeg2_vaapi_hwaccel; -extern AVHWAccel ff_mpeg2_vdpau_hwaccel; -extern AVHWAccel ff_mpeg4_vaapi_hwaccel; -extern AVHWAccel ff_mpeg4_vdpau_hwaccel; -extern AVHWAccel ff_vc1_d3d11va_hwaccel; -extern AVHWAccel ff_vc1_d3d11va2_hwaccel; -extern AVHWAccel ff_vc1_dxva2_hwaccel; -extern AVHWAccel ff_vc1_vaapi_hwaccel; -extern AVHWAccel ff_vc1_vdpau_hwaccel; -extern AVHWAccel ff_vp8_vaapi_hwaccel; -extern AVHWAccel ff_wmv3_d3d11va_hwaccel; -extern AVHWAccel ff_wmv3_d3d11va2_hwaccel; -extern AVHWAccel ff_wmv3_dxva2_hwaccel; -extern AVHWAccel ff_wmv3_vaapi_hwaccel; -extern AVHWAccel ff_wmv3_vdpau_hwaccel; +extern const AVHWAccel ff_h263_vaapi_hwaccel; +extern const AVHWAccel ff_h264_cuvid_hwaccel; +extern const AVHWAccel ff_h264_d3d11va_hwaccel; +extern const AVHWAccel ff_h264_d3d11va2_hwaccel; +extern const AVHWAccel ff_h264_dxva2_hwaccel; +extern const AVHWAccel ff_h264_vaapi_hwaccel; +extern const AVHWAccel ff_h264_vda_hwaccel; +extern const AVHWAccel ff_h264_vda_old_hwaccel; +extern const AVHWAccel ff_h264_vdpau_hwaccel; +extern const AVHWAccel ff_hevc_cuvid_hwaccel; +extern const AVHWAccel ff_hevc_d3d11va_hwaccel; +extern const AVHWAccel ff_hevc_d3d11va2_hwaccel; +extern const AVHWAccel ff_hevc_dxva2_hwaccel; +extern const AVHWAccel ff_hevc_vaapi_hwaccel; +extern const AVHWAccel ff_hevc_vdpau_hwaccel; +extern const AVHWAccel ff_mpeg1_vdpau_hwaccel; +extern const AVHWAccel ff_mpeg2_d3d11va_hwaccel; +extern const AVHWAccel ff_mpeg2_d3d11va2_hwaccel; +extern const AVHWAccel ff_mpeg2_dxva2_hwaccel; +extern const AVHWAccel ff_mpeg2_vaapi_hwaccel; +extern const AVHWAccel ff_mpeg2_vdpau_hwaccel; +extern const AVHWAccel ff_mpeg4_vaapi_hwaccel; +extern const AVHWAccel ff_mpeg4_vdpau_hwaccel; +extern const AVHWAccel ff_vc1_d3d11va_hwaccel; +extern const AVHWAccel ff_vc1_d3d11va2_hwaccel; +extern const AVHWAccel ff_vc1_dxva2_hwaccel; +extern const AVHWAccel ff_vc1_vaapi_hwaccel; +extern const AVHWAccel ff_vc1_vdpau_hwaccel; +extern const AVHWAccel ff_vp8_vaapi_hwaccel; +extern const AVHWAccel ff_wmv3_d3d11va_hwaccel; +extern const AVHWAccel ff_wmv3_d3d11va2_hwaccel; +extern const AVHWAccel ff_wmv3_dxva2_hwaccel; +extern const AVHWAccel ff_wmv3_vaapi_hwaccel; +extern const AVHWAccel ff_wmv3_vdpau_hwaccel; #endif /* AVCODEC_HWACCELS_H */ diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c index 0a5c0dfc76756..97d4387d717fe 100644 --- a/libavcodec/vaapi_h264.c +++ b/libavcodec/vaapi_h264.c @@ -388,7 +388,7 @@ static int vaapi_h264_decode_slice(AVCodecContext *avctx, return 0; } -AVHWAccel ff_h264_vaapi_hwaccel = { +const AVHWAccel ff_h264_vaapi_hwaccel = { .name = "h264_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c index 085d84142d246..71fab776550d7 100644 --- a/libavcodec/vaapi_hevc.c +++ b/libavcodec/vaapi_hevc.c @@ -423,7 +423,7 @@ static int vaapi_hevc_decode_slice(AVCodecContext *avctx, return 0; } -AVHWAccel ff_hevc_vaapi_hwaccel = { +const AVHWAccel ff_hevc_vaapi_hwaccel = { .name = "hevc_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, diff --git a/libavcodec/vaapi_mpeg2.c b/libavcodec/vaapi_mpeg2.c index 5c0a79788fb55..4cca00c862650 100644 --- a/libavcodec/vaapi_mpeg2.c +++ b/libavcodec/vaapi_mpeg2.c @@ -173,7 +173,7 @@ static int vaapi_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer return 0; } -AVHWAccel ff_mpeg2_vaapi_hwaccel = { +const AVHWAccel ff_mpeg2_vaapi_hwaccel = { .name = "mpeg2_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, diff --git a/libavcodec/vaapi_mpeg4.c b/libavcodec/vaapi_mpeg4.c index 258ae68568399..5dc94a4c2df1f 100644 --- a/libavcodec/vaapi_mpeg4.c +++ b/libavcodec/vaapi_mpeg4.c @@ -189,7 +189,7 @@ static int vaapi_mpeg4_decode_slice(AVCodecContext *avctx, const uint8_t *buffer } #if CONFIG_MPEG4_VAAPI_HWACCEL -AVHWAccel ff_mpeg4_vaapi_hwaccel = { +const AVHWAccel ff_mpeg4_vaapi_hwaccel = { .name = "mpeg4_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG4, @@ -207,7 +207,7 @@ AVHWAccel ff_mpeg4_vaapi_hwaccel = { #endif #if CONFIG_H263_VAAPI_HWACCEL -AVHWAccel ff_h263_vaapi_hwaccel = { +const AVHWAccel ff_h263_vaapi_hwaccel = { .name = "h263_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H263, diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c index 8df219f7e2a8d..8b7d49facf615 100644 --- a/libavcodec/vaapi_vc1.c +++ b/libavcodec/vaapi_vc1.c @@ -388,7 +388,7 @@ static int vaapi_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, } #if CONFIG_WMV3_VAAPI_HWACCEL -AVHWAccel ff_wmv3_vaapi_hwaccel = { +const AVHWAccel ff_wmv3_vaapi_hwaccel = { .name = "wmv3_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, @@ -405,7 +405,7 @@ AVHWAccel ff_wmv3_vaapi_hwaccel = { }; #endif -AVHWAccel ff_vc1_vaapi_hwaccel = { +const AVHWAccel ff_vc1_vaapi_hwaccel = { .name = "vc1_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, diff --git a/libavcodec/vaapi_vp8.c b/libavcodec/vaapi_vp8.c index 3ccc2bd0abc10..e18b1cb2df86f 100644 --- a/libavcodec/vaapi_vp8.c +++ b/libavcodec/vaapi_vp8.c @@ -220,7 +220,7 @@ static int vaapi_vp8_decode_slice(AVCodecContext *avctx, return err; } -AVHWAccel ff_vp8_vaapi_hwaccel = { +const AVHWAccel ff_vp8_vaapi_hwaccel = { .name = "vp8_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VP8, diff --git a/libavcodec/vda_h264.c b/libavcodec/vda_h264.c index 037715da81021..4dfe532f8af73 100644 --- a/libavcodec/vda_h264.c +++ b/libavcodec/vda_h264.c @@ -247,7 +247,7 @@ static int vda_h264_uninit(AVCodecContext *avctx) return 0; } -AVHWAccel ff_h264_vda_old_hwaccel = { +const AVHWAccel ff_h264_vda_old_hwaccel = { .name = "h264_vda", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, @@ -483,7 +483,7 @@ static int vda_h264_alloc_frame(AVCodecContext *avctx, AVFrame *frame) return 0; } -AVHWAccel ff_h264_vda_hwaccel = { +const AVHWAccel ff_h264_vda_hwaccel = { .name = "h264_vda", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, diff --git a/libavcodec/vdpau_h264.c b/libavcodec/vdpau_h264.c index 8edbc44021459..7c4c977b408d1 100644 --- a/libavcodec/vdpau_h264.c +++ b/libavcodec/vdpau_h264.c @@ -262,7 +262,7 @@ static int vdpau_h264_init(AVCodecContext *avctx) return ff_vdpau_common_init(avctx, profile, level); } -AVHWAccel ff_h264_vdpau_hwaccel = { +const AVHWAccel ff_h264_vdpau_hwaccel = { .name = "h264_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, diff --git a/libavcodec/vdpau_hevc.c b/libavcodec/vdpau_hevc.c index a177c00e43ba1..3b575eb7862b6 100644 --- a/libavcodec/vdpau_hevc.c +++ b/libavcodec/vdpau_hevc.c @@ -413,7 +413,7 @@ static int vdpau_hevc_init(AVCodecContext *avctx) return ff_vdpau_common_init(avctx, profile, level); } -AVHWAccel ff_hevc_vdpau_hwaccel = { +const AVHWAccel ff_hevc_vdpau_hwaccel = { .name = "hevc_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, diff --git a/libavcodec/vdpau_mpeg12.c b/libavcodec/vdpau_mpeg12.c index db1ba34e03e3c..bc9ff5da8cd54 100644 --- a/libavcodec/vdpau_mpeg12.c +++ b/libavcodec/vdpau_mpeg12.c @@ -103,7 +103,7 @@ static int vdpau_mpeg1_init(AVCodecContext *avctx) VDP_DECODER_LEVEL_MPEG1_NA); } -AVHWAccel ff_mpeg1_vdpau_hwaccel = { +const AVHWAccel ff_mpeg1_vdpau_hwaccel = { .name = "mpeg1_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG1VIDEO, @@ -138,7 +138,7 @@ static int vdpau_mpeg2_init(AVCodecContext *avctx) return ff_vdpau_common_init(avctx, profile, VDP_DECODER_LEVEL_MPEG2_HL); } -AVHWAccel ff_mpeg2_vdpau_hwaccel = { +const AVHWAccel ff_mpeg2_vdpau_hwaccel = { .name = "mpeg2_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, diff --git a/libavcodec/vdpau_mpeg4.c b/libavcodec/vdpau_mpeg4.c index 519866cf0a1c7..87db6a767c276 100644 --- a/libavcodec/vdpau_mpeg4.c +++ b/libavcodec/vdpau_mpeg4.c @@ -107,7 +107,7 @@ static int vdpau_mpeg4_init(AVCodecContext *avctx) return ff_vdpau_common_init(avctx, profile, avctx->level); } -AVHWAccel ff_mpeg4_vdpau_hwaccel = { +const AVHWAccel ff_mpeg4_vdpau_hwaccel = { .name = "mpeg4_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG4, diff --git a/libavcodec/vdpau_vc1.c b/libavcodec/vdpau_vc1.c index 45b51304c6d83..1b555888cec50 100644 --- a/libavcodec/vdpau_vc1.c +++ b/libavcodec/vdpau_vc1.c @@ -132,7 +132,7 @@ static int vdpau_vc1_init(AVCodecContext *avctx) } #if CONFIG_WMV3_VDPAU_HWACCEL -AVHWAccel ff_wmv3_vdpau_hwaccel = { +const AVHWAccel ff_wmv3_vdpau_hwaccel = { .name = "wm3_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WMV3, @@ -149,7 +149,7 @@ AVHWAccel ff_wmv3_vdpau_hwaccel = { }; #endif -AVHWAccel ff_vc1_vdpau_hwaccel = { +const AVHWAccel ff_vc1_vdpau_hwaccel = { .name = "vc1_vdpau", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_VC1, diff --git a/libavcodec/version.h b/libavcodec/version.h index 7ef743dc69ee4..9b47110301a9b 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 7 +#define LIBAVCODEC_VERSION_MINOR 8 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From ddea22a684611c1fec9d8b5c70d835e983a9252e Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 26 Oct 2017 00:18:47 +0100 Subject: [PATCH 1399/2557] avconv: Use codec hardware config to configure hwaccels Removes specific support for all hwaccels supported by the generic code (CUVID, DXVA2, D3D11VA, VAAPI and VDPAU). --- avtools/avconv.c | 76 +++++++++---- avtools/avconv.h | 9 +- avtools/avconv_hw.c | 249 +++++++++++++++++++++++++++++-------------- avtools/avconv_opt.c | 47 ++++---- 4 files changed, 246 insertions(+), 135 deletions(-) diff --git a/avtools/avconv.c b/avtools/avconv.c index cee7a7b452515..ac15464a8d0a4 100644 --- a/avtools/avconv.c +++ b/avtools/avconv.c @@ -1631,44 +1631,77 @@ static void print_sdp(void) av_freep(&avc); } -static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt) -{ - int i; - for (i = 0; hwaccels[i].name; i++) - if (hwaccels[i].pix_fmt == pix_fmt) - return &hwaccels[i]; - return NULL; -} - static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) { InputStream *ist = s->opaque; const enum AVPixelFormat *p; int ret; - for (p = pix_fmts; *p != -1; p++) { + for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p); - const HWAccel *hwaccel; + const AVCodecHWConfig *config = NULL; + int i; if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) break; - hwaccel = get_hwaccel(*p); - if (!hwaccel || - (ist->active_hwaccel_id && ist->active_hwaccel_id != hwaccel->id) || - (ist->hwaccel_id != HWACCEL_AUTO && ist->hwaccel_id != hwaccel->id)) - continue; + if (ist->hwaccel_id == HWACCEL_GENERIC || + ist->hwaccel_id == HWACCEL_AUTO) { + for (i = 0;; i++) { + config = avcodec_get_hw_config(s->codec, i); + if (!config) + break; + if (!(config->methods & + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) + continue; + if (config->pix_fmt == *p) + break; + } + } + if (config) { + if (config->device_type != ist->hwaccel_device_type) { + // Different hwaccel offered, ignore. + continue; + } - ret = hwaccel->init(s); - if (ret < 0) { - if (ist->hwaccel_id == hwaccel->id) { + ret = hwaccel_decode_init(s); + if (ret < 0) { + if (ist->hwaccel_id == HWACCEL_GENERIC) { + av_log(NULL, AV_LOG_FATAL, + "%s hwaccel requested for input stream #%d:%d, " + "but cannot be initialized.\n", + av_hwdevice_get_type_name(config->device_type), + ist->file_index, ist->st->index); + return AV_PIX_FMT_NONE; + } + continue; + } + } else { + const HWAccel *hwaccel = NULL; + int i; + for (i = 0; hwaccels[i].name; i++) { + if (hwaccels[i].pix_fmt == *p) { + hwaccel = &hwaccels[i]; + break; + } + } + if (!hwaccel) { + // No hwaccel supporting this pixfmt. + continue; + } + if (hwaccel->id != ist->hwaccel_id) { + // Does not match requested hwaccel. + continue; + } + + ret = hwaccel->init(s); + if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "%s hwaccel requested for input stream #%d:%d, " "but cannot be initialized.\n", hwaccel->name, ist->file_index, ist->st->index); return AV_PIX_FMT_NONE; } - continue; } if (ist->hw_frames_ctx) { @@ -1677,8 +1710,7 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat return AV_PIX_FMT_NONE; } - ist->active_hwaccel_id = hwaccel->id; - ist->hwaccel_pix_fmt = *p; + ist->hwaccel_pix_fmt = *p; break; } diff --git a/avtools/avconv.h b/avtools/avconv.h index b5843fbc039f4..0d24c71a749aa 100644 --- a/avtools/avconv.h +++ b/avtools/avconv.h @@ -52,13 +52,9 @@ enum HWAccelID { HWACCEL_NONE = 0, HWACCEL_AUTO, - HWACCEL_VDPAU, - HWACCEL_DXVA2, + HWACCEL_GENERIC, HWACCEL_VDA, HWACCEL_QSV, - HWACCEL_VAAPI, - HWACCEL_D3D11VA, - HWACCEL_CUVID, }; typedef struct HWAccel { @@ -66,7 +62,6 @@ typedef struct HWAccel { int (*init)(AVCodecContext *s); enum HWAccelID id; enum AVPixelFormat pix_fmt; - enum AVHWDeviceType device_type; } HWAccel; typedef struct HWDevice { @@ -301,11 +296,11 @@ typedef struct InputStream { /* hwaccel options */ enum HWAccelID hwaccel_id; + enum AVHWDeviceType hwaccel_device_type; char *hwaccel_device; enum AVPixelFormat hwaccel_output_format; /* hwaccel context */ - enum HWAccelID active_hwaccel_id; void *hwaccel_ctx; void (*hwaccel_uninit)(AVCodecContext *s); int (*hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int flags); diff --git a/avtools/avconv_hw.c b/avtools/avconv_hw.c index 36ef86692778c..7e223bf102547 100644 --- a/avtools/avconv_hw.c +++ b/avtools/avconv_hw.c @@ -62,6 +62,31 @@ static HWDevice *hw_device_add(void) return hw_devices[nb_hw_devices++]; } +static char *hw_device_default_name(enum AVHWDeviceType type) +{ + // Make an automatic name of the form "type%d". We arbitrarily + // limit at 1000 anonymous devices of the same type - there is + // probably something else very wrong if you get to this limit. + const char *type_name = av_hwdevice_get_type_name(type); + char *name; + size_t index_pos; + int index, index_limit = 1000; + index_pos = strlen(type_name); + name = av_malloc(index_pos + 4); + if (!name) + return NULL; + for (index = 0; index < index_limit; index++) { + snprintf(name, index_pos + 4, "%s%d", type_name, index); + if (!hw_device_get_by_name(name)) + break; + } + if (index >= index_limit) { + av_freep(&name); + return NULL; + } + return name; +} + int hw_device_init_from_string(const char *arg, HWDevice **dev_out) { // "type=name:device,key=value,key2=value2" @@ -109,27 +134,11 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out) p += 1 + k; } else { - // Give the device an automatic name of the form "type%d". - // We arbitrarily limit at 1000 anonymous devices of the same - // type - there is probably something else very wrong if you - // get to this limit. - size_t index_pos; - int index, index_limit = 1000; - index_pos = strlen(type_name); - name = av_malloc(index_pos + 4); + name = hw_device_default_name(type); if (!name) { err = AVERROR(ENOMEM); goto fail; } - for (index = 0; index < index_limit; index++) { - snprintf(name, index_pos + 4, "%s%d", type_name, index); - if (!hw_device_get_by_name(name)) - break; - } - if (index >= index_limit) { - errmsg = "too many devices"; - goto invalid; - } } if (!*p) { @@ -212,6 +221,49 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out) goto done; } +static int hw_device_init_from_type(enum AVHWDeviceType type, + const char *device, + HWDevice **dev_out) +{ + AVBufferRef *device_ref = NULL; + HWDevice *dev; + char *name; + int err; + + name = hw_device_default_name(type); + if (!name) { + err = AVERROR(ENOMEM); + goto fail; + } + + err = av_hwdevice_ctx_create(&device_ref, type, device, NULL, 0); + if (err < 0) { + av_log(NULL, AV_LOG_ERROR, + "Device creation failed: %d.\n", err); + goto fail; + } + + dev = hw_device_add(); + if (!dev) { + err = AVERROR(ENOMEM); + goto fail; + } + + dev->name = name; + dev->type = type; + dev->device_ref = device_ref; + + if (dev_out) + *dev_out = dev; + + return 0; + +fail: + av_freep(&name); + av_buffer_unref(&device_ref); + return err; +} + void hw_device_free_all(void) { int i; @@ -224,85 +276,130 @@ void hw_device_free_all(void) nb_hw_devices = 0; } -static enum AVHWDeviceType hw_device_match_type_by_hwaccel(enum HWAccelID hwaccel_id) +static HWDevice *hw_device_match_by_codec(const AVCodec *codec) { + const AVCodecHWConfig *config; + HWDevice *dev; int i; - if (hwaccel_id == HWACCEL_NONE) - return AV_HWDEVICE_TYPE_NONE; - for (i = 0; hwaccels[i].name; i++) { - if (hwaccels[i].id == hwaccel_id) - return hwaccels[i].device_type; + for (i = 0;; i++) { + config = avcodec_get_hw_config(codec, i); + if (!config) + return NULL; + if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) + continue; + dev = hw_device_get_by_type(config->device_type); + if (dev) + return dev; } - return AV_HWDEVICE_TYPE_NONE; -} - -static enum AVHWDeviceType hw_device_match_type_in_name(const char *codec_name) -{ - const char *type_name; - enum AVHWDeviceType type; - for (type = av_hwdevice_iterate_types(AV_HWDEVICE_TYPE_NONE); - type != AV_HWDEVICE_TYPE_NONE; - type = av_hwdevice_iterate_types(type)) { - type_name = av_hwdevice_get_type_name(type); - if (strstr(codec_name, type_name)) - return type; - } - return AV_HWDEVICE_TYPE_NONE; } int hw_device_setup_for_decode(InputStream *ist) { + const AVCodecHWConfig *config; enum AVHWDeviceType type; - HWDevice *dev; - const char *type_name; - int err; + HWDevice *dev = NULL; + int err, auto_device = 0; if (ist->hwaccel_device) { dev = hw_device_get_by_name(ist->hwaccel_device); if (!dev) { - char *tmp; - size_t len; - type = hw_device_match_type_by_hwaccel(ist->hwaccel_id); - if (type == AV_HWDEVICE_TYPE_NONE) { - // No match - this isn't necessarily invalid, though, - // because an explicit device might not be needed or - // the hwaccel setup could be handled elsewhere. + if (ist->hwaccel_id == HWACCEL_AUTO) { + auto_device = 1; + } else if (ist->hwaccel_id == HWACCEL_GENERIC) { + type = ist->hwaccel_device_type; + err = hw_device_init_from_type(type, ist->hwaccel_device, + &dev); + } else { + // This will be dealt with by API-specific initialisation + // (using hwaccel_device), so nothing further needed here. return 0; } - type_name = av_hwdevice_get_type_name(type); - len = strlen(type_name) + 1 + - strlen(ist->hwaccel_device) + 1; - tmp = av_malloc(len); - if (!tmp) - return AVERROR(ENOMEM); - snprintf(tmp, len, "%s:%s", type_name, ist->hwaccel_device); - err = hw_device_init_from_string(tmp, &dev); - av_free(tmp); - if (err < 0) - return err; + } else { + if (ist->hwaccel_id == HWACCEL_AUTO) { + ist->hwaccel_device_type = dev->type; + } else if (ist->hwaccel_device_type != dev->type) { + av_log(ist->dec_ctx, AV_LOG_ERROR, "Invalid hwaccel device " + "specified for decoder: device %s of type %s is not " + "usable with hwaccel %s.\n", dev->name, + av_hwdevice_get_type_name(dev->type), + av_hwdevice_get_type_name(ist->hwaccel_device_type)); + return AVERROR(EINVAL); + } } } else { - if (ist->hwaccel_id != HWACCEL_NONE) - type = hw_device_match_type_by_hwaccel(ist->hwaccel_id); - else - type = hw_device_match_type_in_name(ist->dec->name); - if (type != AV_HWDEVICE_TYPE_NONE) { + if (ist->hwaccel_id == HWACCEL_AUTO) { + auto_device = 1; + } else if (ist->hwaccel_id == HWACCEL_GENERIC) { + type = ist->hwaccel_device_type; dev = hw_device_get_by_type(type); + if (!dev) + err = hw_device_init_from_type(type, NULL, &dev); + } else { + dev = hw_device_match_by_codec(ist->dec); if (!dev) { - hw_device_init_from_string(av_hwdevice_get_type_name(type), + // No device for this codec, but not using generic hwaccel + // and therefore may well not need one - ignore. + return 0; + } + } + } + + if (auto_device) { + int i; + if (!avcodec_get_hw_config(ist->dec, 0)) { + // Decoder does not support any hardware devices. + return 0; + } + for (i = 0; !dev; i++) { + config = avcodec_get_hw_config(ist->dec, i); + if (!config) + break; + type = config->device_type; + dev = hw_device_get_by_type(type); + if (dev) { + av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto " + "hwaccel type %s with existing device %s.\n", + av_hwdevice_get_type_name(type), dev->name); + } + } + for (i = 0; !dev; i++) { + config = avcodec_get_hw_config(ist->dec, i); + if (!config) + break; + type = config->device_type; + // Try to make a new device of this type. + err = hw_device_init_from_type(type, ist->hwaccel_device, &dev); + if (err < 0) { + // Can't make a device of this type. + continue; + } + if (ist->hwaccel_device) { + av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto " + "hwaccel type %s with new device created " + "from %s.\n", av_hwdevice_get_type_name(type), + ist->hwaccel_device); + } else { + av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto " + "hwaccel type %s with new default device.\n", + av_hwdevice_get_type_name(type)); } + } + if (dev) { + ist->hwaccel_device_type = type; } else { - // No device required. + av_log(ist->dec_ctx, AV_LOG_INFO, "Auto hwaccel " + "disabled: no device found.\n"); + ist->hwaccel_id = HWACCEL_NONE; return 0; } } if (!dev) { - av_log(ist->dec_ctx, AV_LOG_WARNING, "No device available " - "for decoder (device type %s for codec %s).\n", + av_log(ist->dec_ctx, AV_LOG_ERROR, "No device available " + "for decoder: device type %s needed for codec %s.\n", av_hwdevice_get_type_name(type), ist->dec->name); - return 0; + return err; } ist->dec_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); @@ -314,24 +411,16 @@ int hw_device_setup_for_decode(InputStream *ist) int hw_device_setup_for_encode(OutputStream *ost) { - enum AVHWDeviceType type; HWDevice *dev; - type = hw_device_match_type_in_name(ost->enc->name); - if (type != AV_HWDEVICE_TYPE_NONE) { - dev = hw_device_get_by_type(type); - if (!dev) { - av_log(ost->enc_ctx, AV_LOG_WARNING, "No device available " - "for encoder (device type %s for codec %s).\n", - av_hwdevice_get_type_name(type), ost->enc->name); - return 0; - } + dev = hw_device_match_by_codec(ost->enc); + if (dev) { ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); if (!ost->enc_ctx->hw_device_ctx) return AVERROR(ENOMEM); return 0; } else { - // No device required. + // No device required, or no device available. return 0; } } diff --git a/avtools/avconv_opt.c b/avtools/avconv_opt.c index df693360a776f..a4a225c3e9c5d 100644 --- a/avtools/avconv_opt.c +++ b/avtools/avconv_opt.c @@ -56,33 +56,11 @@ } const HWAccel hwaccels[] = { -#if HAVE_VDPAU_X11 - { "vdpau", hwaccel_decode_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU, - AV_HWDEVICE_TYPE_VDPAU }, -#endif -#if CONFIG_D3D11VA - { "d3d11va", hwaccel_decode_init, HWACCEL_D3D11VA, AV_PIX_FMT_D3D11, - AV_HWDEVICE_TYPE_D3D11VA }, -#endif -#if CONFIG_DXVA2 - { "dxva2", hwaccel_decode_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD, - AV_HWDEVICE_TYPE_DXVA2 }, -#endif #if CONFIG_VDA - { "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA, - AV_HWDEVICE_TYPE_NONE }, + { "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA }, #endif #if CONFIG_LIBMFX - { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV, - AV_HWDEVICE_TYPE_NONE }, -#endif -#if CONFIG_VAAPI - { "vaapi", hwaccel_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI, - AV_HWDEVICE_TYPE_VAAPI }, -#endif -#if CONFIG_CUVID - { "cuvid", hwaccel_decode_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA, - AV_HWDEVICE_TYPE_CUDA }, + { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV }, #endif { 0 }, }; @@ -201,12 +179,15 @@ static double parse_frame_aspect_ratio(const char *arg) static int show_hwaccels(void *optctx, const char *opt, const char *arg) { + enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE; int i; printf("Supported hardware acceleration:\n"); - for (i = 0; hwaccels[i].name; i++) { + while ((type = av_hwdevice_iterate_types(type)) != + AV_HWDEVICE_TYPE_NONE) + printf("%s\n", av_hwdevice_get_type_name(type)); + for (i = 0; hwaccels[i].name; i++) printf("%s\n", hwaccels[i].name); - } printf("\n"); return 0; } @@ -623,6 +604,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) else if (!strcmp(hwaccel, "auto")) ist->hwaccel_id = HWACCEL_AUTO; else { + enum AVHWDeviceType type; int i; for (i = 0; hwaccels[i].name; i++) { if (!strcmp(hwaccels[i].name, hwaccel)) { @@ -631,10 +613,23 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) } } + if (!ist->hwaccel_id) { + type = av_hwdevice_find_type_by_name(hwaccel); + if (type != AV_HWDEVICE_TYPE_NONE) { + ist->hwaccel_id = HWACCEL_GENERIC; + ist->hwaccel_device_type = type; + } + } + if (!ist->hwaccel_id) { av_log(NULL, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n", hwaccel); av_log(NULL, AV_LOG_FATAL, "Supported hwaccels: "); + type = AV_HWDEVICE_TYPE_NONE; + while ((type = av_hwdevice_iterate_types(type)) != + AV_HWDEVICE_TYPE_NONE) + av_log(NULL, AV_LOG_FATAL, "%s ", + av_hwdevice_get_type_name(type)); for (i = 0; hwaccels[i].name; i++) av_log(NULL, AV_LOG_FATAL, "%s ", hwaccels[i].name); av_log(NULL, AV_LOG_FATAL, "\n"); From c94b09485811b58a49e6769943509880922ff0bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20P=C3=B6schel?= Date: Sat, 16 Dec 2017 16:50:45 +0100 Subject: [PATCH 1400/2557] configure: Fix case of static libmp3lame Fixes #6918. Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 4d7eae8f5a809..6e04ee67069b6 100755 --- a/configure +++ b/configure @@ -5858,7 +5858,7 @@ enabled libkvazaar && require_pkg_config libkvazaar "kvazaar >= 0.8.1" kv enabled libmfx && { check_pkg_config libmfx libmfx "mfx/mfxvideo.h" MFXInit || { require libmfx "mfx/mfxvideo.h" MFXInit "-llibmfx $advapi32_extralibs" && warn "using libmfx without pkg-config"; } } enabled libmodplug && require_pkg_config libmodplug libmodplug libmodplug/modplug.h ModPlug_Load -enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame +enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame $libm_extralibs enabled libmysofa && require libmysofa "mysofa.h" mysofa_load -lmysofa $zlib_extralibs enabled libnpp && { check_lib libnpp npp.h nppGetLibVersion -lnppig -lnppicc -lnppc || check_lib libnpp npp.h nppGetLibVersion -lnppi -lnppc || From 2beba58e0e4bda688bf96e12413231607ceafdd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 20 Dec 2017 09:45:14 +0200 Subject: [PATCH 1401/2557] mmaldec: Fix compilation after 2fcb0090 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/mmaldec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index 10a48d3e0f748..504e765d073d9 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -788,7 +788,7 @@ static int ffmmal_decode(AVCodecContext *avctx, void *data, int *got_frame, return ret; } -static const AVCodecHWConfigInternal *mmal_hw_configs = { +static const AVCodecHWConfigInternal *mmal_hw_configs[] = { HW_CONFIG_INTERNAL(MMAL), NULL }; From cfd52094c027a3e31ee6ea9aafeb4a2e3c152ec1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 20 Dec 2017 12:45:21 +0100 Subject: [PATCH 1402/2557] avfilter/vf_psnr: add more gbrap formats Signed-off-by: Paul B Mahol --- libavfilter/vf_psnr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_psnr.c b/libavfilter/vf_psnr.c index 493a501a7a41e..153d694b7f0f0 100644 --- a/libavfilter/vf_psnr.c +++ b/libavfilter/vf_psnr.c @@ -270,7 +270,7 @@ static int query_formats(AVFilterContext *ctx) AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, - AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; From 05c1c79d3779ae53c50007c4812ec5195dc2c264 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 7 Dec 2017 20:40:35 +0100 Subject: [PATCH 1403/2557] libavcodec/hevcdec: implement skip_frame Signed-off-by: Michael Niedermayer --- libavcodec/hevcdec.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 433a7056ea7ad..4bfae8c12b190 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2905,6 +2905,13 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) if (ret < 0) return ret; + if ( + (s->avctx->skip_frame >= AVDISCARD_BIDIR && s->sh.slice_type == HEVC_SLICE_B) || + (s->avctx->skip_frame >= AVDISCARD_NONINTRA && s->sh.slice_type != HEVC_SLICE_I) || + (s->avctx->skip_frame >= AVDISCARD_NONKEY && !IS_IDR(s))) { + break; + } + if (s->sh.first_slice_in_pic_flag) { if (s->max_ra == INT_MAX) { if (s->nal_unit_type == HEVC_NAL_CRA_NUT || IS_BLA(s)) { @@ -3028,7 +3035,14 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) /* decode the NAL units */ for (i = 0; i < s->pkt.nb_nals; i++) { - ret = decode_nal_unit(s, &s->pkt.nals[i]); + H2645NAL *nal = &s->pkt.nals[i]; + + if (s->avctx->skip_frame >= AVDISCARD_ALL || + (s->avctx->skip_frame >= AVDISCARD_NONREF + && ff_hevc_nal_is_nonref(nal->type))) + continue; + + ret = decode_nal_unit(s, nal); if (ret < 0) { av_log(s->avctx, AV_LOG_WARNING, "Error parsing NAL unit #%d.\n", i); From 58a25aeb8e69532aae6ed1762fe7e0b260990010 Mon Sep 17 00:00:00 2001 From: Sasi Inguva Date: Mon, 18 Dec 2017 15:31:16 -0800 Subject: [PATCH 1404/2557] lavf/mov.c: Guess video codec delay based on PTS while parsing MOV header. Signed-off-by: Sasi Inguva Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 56 ++++++++++++++++++++++++++++++++ tests/fate/mov.mak | 7 ++++ tests/ref/fate/mov-guess-delay-1 | 3 ++ tests/ref/fate/mov-guess-delay-2 | 3 ++ tests/ref/fate/mov-guess-delay-3 | 3 ++ 5 files changed, 72 insertions(+) create mode 100644 tests/ref/fate/mov-guess-delay-1 create mode 100644 tests/ref/fate/mov-guess-delay-2 create mode 100644 tests/ref/fate/mov-guess-delay-3 diff --git a/libavformat/mov.c b/libavformat/mov.c index 28d60289aa712..480e506370a69 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3241,6 +3241,60 @@ static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, uns return *ctts_count; } +#define MAX_REORDER_DELAY 16 +static void mov_estimate_video_delay(MOVContext *c, AVStream* st) { + MOVStreamContext *msc = st->priv_data; + int ind; + int ctts_ind = 0; + int ctts_sample = 0; + int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts. + int buf_start = 0; + int buf_size = 0; + int j, r, num_swaps; + + if (st->codecpar->video_delay <= 0 && msc->ctts_data && + st->codecpar->codec_id == AV_CODEC_ID_H264) { + st->codecpar->video_delay = 0; + for(ind = 0; ind < st->nb_index_entries && ctts_ind < msc->ctts_count; ++ind) { + if (buf_size == (MAX_REORDER_DELAY + 1)) { + // If circular buffer is full, then move the first element forward. + buf_start = (buf_start + 1) % buf_size; + } else { + ++buf_size; + } + + // Point j to the last elem of the buffer and insert the current pts there. + j = (buf_start + buf_size - 1) % buf_size; + pts_buf[j] = st->index_entries[ind].timestamp + msc->ctts_data[ctts_ind].duration; + + // The timestamps that are already in the sorted buffer, and are greater than the + // current pts, are exactly the timestamps that need to be buffered to output PTS + // in correct sorted order. + // Hence the video delay (which is the buffer size used to sort DTS and output PTS), + // can be computed as the maximum no. of swaps any particular timestamp needs to + // go through, to keep this buffer in sorted order. + num_swaps = 0; + while (j != buf_start) { + r = (j - 1 + buf_size) % buf_size; + if (pts_buf[j] < pts_buf[r]) { + FFSWAP(int64_t, pts_buf[j], pts_buf[r]); + ++num_swaps; + } + j = r; + } + st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps); + + ctts_sample++; + if (ctts_sample == msc->ctts_data[ctts_ind].count) { + ctts_ind++; + ctts_sample = 0; + } + } + av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n", + st->codecpar->video_delay, st->index); + } +} + static void mov_current_sample_inc(MOVStreamContext *sc) { sc->current_sample++; @@ -3897,6 +3951,8 @@ static void mov_build_index(MOVContext *mov, AVStream *st) // Fix index according to edit lists. mov_fix_index(mov, st); } + + mov_estimate_video_delay(mov, st); } static int test_same_origin(const char *src, const char *ref) { diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 19b01304fbc55..907dfa0b695a5 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -13,6 +13,9 @@ FATE_MOV = fate-mov-3elist \ fate-mov-elst-ends-betn-b-and-i \ fate-mov-frag-overlap \ fate-mov-bbi-elst-starts-b \ + fate-mov-guess-delay-1 \ + fate-mov-guess-delay-2 \ + fate-mov-guess-delay-3 \ FATE_MOV_FFPROBE = fate-mov-aac-2048-priming \ fate-mov-zombie \ @@ -82,3 +85,7 @@ fate-mov-spherical-mono: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries str fate-mov-gpmf-remux: CMD = md5 -i $(TARGET_SAMPLES)/mov/fake-gp-media-with-real-gpmf.mp4 -map 0 -c copy -fflags +bitexact -f mp4 fate-mov-gpmf-remux: CMP = oneline fate-mov-gpmf-remux: REF = 8f48e435ee1f6b7e173ea756141eabf3 + +fate-mov-guess-delay-1: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=has_b_frames -select_streams v $(TARGET_SAMPLES)/h264/h264_3bf_nopyramid_nobsrestriction.mp4 +fate-mov-guess-delay-2: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=has_b_frames -select_streams v $(TARGET_SAMPLES)/h264/h264_3bf_pyramid_nobsrestriction.mp4 +fate-mov-guess-delay-3: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=has_b_frames -select_streams v $(TARGET_SAMPLES)/h264/h264_4bf_pyramid_nobsrestriction.mp4 diff --git a/tests/ref/fate/mov-guess-delay-1 b/tests/ref/fate/mov-guess-delay-1 new file mode 100644 index 0000000000000..96cb67be0c9f0 --- /dev/null +++ b/tests/ref/fate/mov-guess-delay-1 @@ -0,0 +1,3 @@ +[STREAM] +has_b_frames=1 +[/STREAM] diff --git a/tests/ref/fate/mov-guess-delay-2 b/tests/ref/fate/mov-guess-delay-2 new file mode 100644 index 0000000000000..248de1c3ea718 --- /dev/null +++ b/tests/ref/fate/mov-guess-delay-2 @@ -0,0 +1,3 @@ +[STREAM] +has_b_frames=2 +[/STREAM] diff --git a/tests/ref/fate/mov-guess-delay-3 b/tests/ref/fate/mov-guess-delay-3 new file mode 100644 index 0000000000000..248de1c3ea718 --- /dev/null +++ b/tests/ref/fate/mov-guess-delay-3 @@ -0,0 +1,3 @@ +[STREAM] +has_b_frames=2 +[/STREAM] From 8318f60845bbbc4d33a39eee45e4daff0e5dacfb Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 21 Dec 2017 11:14:32 +0800 Subject: [PATCH 1405/2557] avformat/hlsenc: fix first fragment mp4 do not split bug fix ticket id: 6888 Tested-by: beloko Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 72 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index e3442c368fa8d..f51fec103089e 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -352,6 +352,29 @@ static void write_styp(AVIOContext *pb) ffio_wfourcc(pb, "msix"); } +static int flush_dynbuf(VariantStream *vs, int *range_length) +{ + AVFormatContext *ctx = vs->avf; + uint8_t *buffer; + + if (!ctx->pb) { + return AVERROR(EINVAL); + } + + // flush + av_write_frame(ctx, NULL); + avio_flush(ctx->pb); + + // write out to file + *range_length = avio_close_dyn_buf(ctx->pb, &buffer); + ctx->pb = NULL; + avio_write(vs->out, buffer, *range_length); + av_free(buffer); + + // re-open buffer + return avio_open_dyn_buf(&ctx->pb); +} + static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, VariantStream *vs) { @@ -677,7 +700,9 @@ static int hls_mux_init(AVFormatContext *s, VariantStream *vs) if ((ret = avio_open_dyn_buf(&oc->pb)) < 0) return ret; - if ((ret = s->io_open(s, &vs->out, vs->base_output_dirname, AVIO_FLAG_WRITE, &options)) < 0) { + ret = hlsenc_io_open(s, &vs->out, vs->base_output_dirname, &options); + av_dict_free(&options); + if (ret < 0) { av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", vs->fmp4_init_filename); return ret; } @@ -1404,9 +1429,10 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) av_dict_free(&options); if (err < 0) return err; - } else + } else if (c->segment_type != SEGMENT_TYPE_FMP4) { if ((err = hlsenc_io_open(s, &oc->pb, oc->filename, &options)) < 0) goto fail; + } if (vs->vtt_basename) { set_http_options(s, &options, c); if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->filename, &options)) < 0) @@ -1414,9 +1440,7 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) } av_dict_free(&options); - if (c->segment_type == SEGMENT_TYPE_FMP4 && !(c->flags & HLS_SINGLE_FILE)) { - write_styp(oc->pb); - } else { + if (c->segment_type != SEGMENT_TYPE_FMP4) { /* We only require one PAT/PMT per segment. */ if (oc->oformat->priv_class && oc->priv_data) { char period[21]; @@ -1780,7 +1804,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) vs->size = new_start_pos - vs->start_pos; if (!byterange_mode) { - if (hls->segment_type == SEGMENT_TYPE_FMP4 && !vs->init_range_length) { + if (hls->segment_type == SEGMENT_TYPE_FMP4) { + if (!vs->init_range_length) { avio_flush(oc->pb); range_length = avio_close_dyn_buf(oc->pb, &buffer); avio_write(vs->out, buffer, range_length); @@ -1789,6 +1814,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) vs->packets_written = 0; ff_format_io_close(s, &vs->out); hlsenc_io_close(s, &vs->out, vs->base_output_dirname); + } } else { hlsenc_io_close(s, &oc->pb, oc->filename); } @@ -1807,7 +1833,20 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) vs->number--; } - if (!vs->fmp4_init_mode || byterange_mode) + if (hls->segment_type == SEGMENT_TYPE_FMP4) { + ret = hlsenc_io_open(s, &vs->out, vs->avf->filename, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", + vs->avf->filename); + return ret; + } + write_styp(vs->out); + ret = flush_dynbuf(vs, &range_length); + if (ret < 0) { + return ret; + } + ff_format_io_close(s, &vs->out); + } ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size); vs->start_pos = new_start_pos; if (ret < 0) { @@ -1861,6 +1900,7 @@ static int hls_write_trailer(struct AVFormatContext *s) AVFormatContext *vtt_oc = NULL; char *old_filename = NULL; int i; + int ret = 0; VariantStream *vs = NULL; for (i = 0; i < hls->nb_varstreams; i++) { @@ -1873,11 +1913,25 @@ static int hls_write_trailer(struct AVFormatContext *s) if (!old_filename) { return AVERROR(ENOMEM); } - + if ( hls->segment_type == SEGMENT_TYPE_FMP4) { + int range_length = 0; + ret = hlsenc_io_open(s, &vs->out, vs->avf->filename, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", vs->avf->filename); + return AVERROR(ENOENT); + } + write_styp(vs->out); + ret = flush_dynbuf(vs, &range_length); + if (ret < 0) { + return ret; + } + ff_format_io_close(s, &vs->out); + } av_write_trailer(oc); if (oc->pb) { vs->size = avio_tell(vs->avf->pb) - vs->start_pos; + if (hls->segment_type != SEGMENT_TYPE_FMP4) ff_format_io_close(s, &oc->pb); if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) { @@ -2238,10 +2292,8 @@ static int hls_init(AVFormatContext *s) } } - if (hls->segment_type != SEGMENT_TYPE_FMP4 || hls->flags & HLS_SINGLE_FILE) { if ((ret = hls_start(s, vs)) < 0) goto fail; - } } fail: From 7feae7be5b08916e1d563ad16388a3dd6d40114b Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 21 Dec 2017 11:17:08 +0800 Subject: [PATCH 1406/2557] avformat/hlsenc: reindent after previous commits Reviewed-by: Karthick J Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index f51fec103089e..0eebcb44621f5 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1806,14 +1806,14 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) if (!byterange_mode) { if (hls->segment_type == SEGMENT_TYPE_FMP4) { if (!vs->init_range_length) { - avio_flush(oc->pb); - range_length = avio_close_dyn_buf(oc->pb, &buffer); - avio_write(vs->out, buffer, range_length); - vs->init_range_length = range_length; - avio_open_dyn_buf(&oc->pb); - vs->packets_written = 0; - ff_format_io_close(s, &vs->out); - hlsenc_io_close(s, &vs->out, vs->base_output_dirname); + avio_flush(oc->pb); + range_length = avio_close_dyn_buf(oc->pb, &buffer); + avio_write(vs->out, buffer, range_length); + vs->init_range_length = range_length; + avio_open_dyn_buf(&oc->pb); + vs->packets_written = 0; + ff_format_io_close(s, &vs->out); + hlsenc_io_close(s, &vs->out, vs->base_output_dirname); } } else { hlsenc_io_close(s, &oc->pb, oc->filename); @@ -1847,7 +1847,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) } ff_format_io_close(s, &vs->out); } - ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size); + ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size); vs->start_pos = new_start_pos; if (ret < 0) { av_free(old_filename); @@ -1932,7 +1932,7 @@ static int hls_write_trailer(struct AVFormatContext *s) if (oc->pb) { vs->size = avio_tell(vs->avf->pb) - vs->start_pos; if (hls->segment_type != SEGMENT_TYPE_FMP4) - ff_format_io_close(s, &oc->pb); + ff_format_io_close(s, &oc->pb); if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) { hls_rename_temp_file(s, oc); @@ -2292,8 +2292,8 @@ static int hls_init(AVFormatContext *s) } } - if ((ret = hls_start(s, vs)) < 0) - goto fail; + if ((ret = hls_start(s, vs)) < 0) + goto fail; } fail: From 3ac76d890d91905925a4d7f66a43e0023e13e149 Mon Sep 17 00:00:00 2001 From: Karthick J Date: Thu, 21 Dec 2017 11:39:24 +0800 Subject: [PATCH 1407/2557] avformat/hlsenc: Fix a memory leak when http_persistent is 1 Reviewed-by: Steven Liu --- libavformat/hlsenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 0eebcb44621f5..29fc1d4122b63 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1972,6 +1972,8 @@ static int hls_write_trailer(struct AVFormatContext *s) av_freep(&vs->baseurl); } + ff_format_io_close(s, &hls->m3u8_out); + ff_format_io_close(s, &hls->sub_m3u8_out); av_freep(&hls->key_basename); av_freep(&hls->var_streams); av_freep(&hls->master_m3u8_url); From 22ae33fb4083c75f7b817211e28c467cbcd72a00 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 21 Dec 2017 00:47:51 -0300 Subject: [PATCH 1408/2557] configure: fix minimum required version of libzimg The new input properties added in 002db7d49ada290db15334b7b41fa27eb376ec5c were introduced to libzimg for the upcoming release 2.7.x Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 6e04ee67069b6..d09eec4155a0c 100755 --- a/configure +++ b/configure @@ -5943,7 +5943,7 @@ enabled libx265 && require_pkg_config libx265 x265 x265.h x265_api_get require_cpp_condition x265.h "X265_BUILD >= 68" enabled libxavs && require libxavs "stdint.h xavs.h" xavs_encoder_encode "-lxavs $pthreads_extralibs $libm_extralibs" enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore -enabled libzimg && require_pkg_config libzimg "zimg >= 2.6.2" zimg.h zimg_get_api_version +enabled libzimg && require_pkg_config libzimg "zimg >= 2.7.0" zimg.h zimg_get_api_version enabled libzmq && require_pkg_config libzmq libzmq zmq.h zmq_ctx_new enabled libzvbi && require_pkg_config libzvbi zvbi-0.2 libzvbi.h vbi_decoder_new && { check_cpp_condition libzvbi.h "VBI_VERSION_MAJOR > 0 || VBI_VERSION_MINOR > 2 || VBI_VERSION_MINOR == 2 && VBI_VERSION_MICRO >= 28" || From bc10260f49d594b552926b5f81e0282dfdebc503 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 21 Dec 2017 01:23:17 -0300 Subject: [PATCH 1409/2557] avformat/mov: simplify parsing of mdcv atom using av_make_q() Signed-off-by: James Almer --- libavformat/mov.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 480e506370a69..20644734dc489 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -5210,20 +5210,14 @@ static int mov_read_mdcv(MOVContext *c, AVIOContext *pb, MOVAtom atom) for (i = 0; i < 3; i++) { const int j = mapping[i]; - sc->mastering->display_primaries[j][0].num = avio_rb16(pb); - sc->mastering->display_primaries[j][0].den = chroma_den; - sc->mastering->display_primaries[j][1].num = avio_rb16(pb); - sc->mastering->display_primaries[j][1].den = chroma_den; - } - sc->mastering->white_point[0].num = avio_rb16(pb); - sc->mastering->white_point[0].den = chroma_den; - sc->mastering->white_point[1].num = avio_rb16(pb); - sc->mastering->white_point[1].den = chroma_den; - - sc->mastering->max_luminance.num = avio_rb32(pb); - sc->mastering->max_luminance.den = luma_den; - sc->mastering->min_luminance.num = avio_rb32(pb); - sc->mastering->min_luminance.den = luma_den; + sc->mastering->display_primaries[j][0] = av_make_q(avio_rb16(pb), chroma_den); + sc->mastering->display_primaries[j][1] = av_make_q(avio_rb16(pb), chroma_den); + } + sc->mastering->white_point[0] = av_make_q(avio_rb16(pb), chroma_den); + sc->mastering->white_point[1] = av_make_q(avio_rb16(pb), chroma_den); + + sc->mastering->max_luminance = av_make_q(avio_rb32(pb), luma_den); + sc->mastering->min_luminance = av_make_q(avio_rb32(pb), luma_den); sc->mastering->has_luminance = 1; sc->mastering->has_primaries = 1; From c99ed89f89619a4f7c078fa5590ebf6532fdbcc0 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 21 Dec 2017 11:40:38 +0100 Subject: [PATCH 1410/2557] avfilter/af_biquads: add kHz width_type Signed-off-by: Paul B Mahol --- doc/filters.texi | 16 +++++++++++++ libavfilter/af_biquads.c | 50 +++++++++++++++++++++++++--------------- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index fc912b6716415..6a6d5a334ee6e 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1127,6 +1127,8 @@ Q-Factor octave @item s slope +@item k +kHz @end table @item width, w @@ -1884,6 +1886,8 @@ Q-Factor octave @item s slope +@item k +kHz @end table @item width, w @@ -1933,6 +1937,8 @@ Q-Factor octave @item s slope +@item k +kHz @end table @item width, w @@ -1989,6 +1995,8 @@ Q-Factor octave @item s slope +@item k +kHz @end table @item width, w @@ -2642,6 +2650,8 @@ Q-Factor octave @item s slope +@item k +kHz @end table @item width, w @@ -3079,6 +3089,8 @@ Q-Factor octave @item s slope +@item k +kHz @end table @item width, w @@ -3385,6 +3397,8 @@ Q-Factor octave @item s slope +@item k +kHz @end table @item width, w @@ -4294,6 +4308,8 @@ Q-Factor octave @item s slope +@item k +kHz @end table @item width, w diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index 3159bd6db09cd..c04d03f191163 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -86,6 +86,8 @@ enum WidthType { OCTAVE, QFACTOR, SLOPE, + KHERTZ, + NB_WTYPE, }; typedef struct ChanCache { @@ -259,6 +261,9 @@ static int config_filter(AVFilterLink *outlink, int reset) case HERTZ: alpha = sin(w0) / (2 * s->frequency / s->width); break; + case KHERTZ: + alpha = sin(w0) / (2 * s->frequency / (s->width * 1000)); + break; case OCTAVE: alpha = sin(w0) * sinh(log(2.) / 2 * s->width * w0 / sin(w0)); break; @@ -516,6 +521,7 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar case 'q': width_type = QFACTOR; break; case 'o': width_type = OCTAVE; break; case 's': width_type = SLOPE; break; + case 'k': width_type = KHERTZ; break; default: av_log(ctx, AV_LOG_ERROR, "Invalid width_type value: %c\n", width_type); return AVERROR(EINVAL); @@ -608,12 +614,13 @@ AVFilter ff_af_##name_ = { \ static const AVOption equalizer_options[] = { {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS}, {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS}, - {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, - {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, + {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, + {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, + {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 999, FLAGS}, {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 999, FLAGS}, {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, @@ -629,12 +636,13 @@ DEFINE_BIQUAD_FILTER(equalizer, "Apply two-pole peaking equalization (EQ) filter static const AVOption bass_options[] = { {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS}, {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS}, - {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, - {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, + {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, + {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, + {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, @@ -650,12 +658,13 @@ DEFINE_BIQUAD_FILTER(bass, "Boost or cut lower frequencies."); static const AVOption treble_options[] = { {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, - {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, - {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, + {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, + {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, + {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, @@ -671,14 +680,15 @@ DEFINE_BIQUAD_FILTER(treble, "Boost or cut upper frequencies."); static const AVOption bandpass_options[] = { {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, - {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, - {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, + {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, + {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, - {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, - {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, + {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, + {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, + {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, {"csg", "use constant skirt gain", OFFSET(csg), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, @@ -691,12 +701,13 @@ DEFINE_BIQUAD_FILTER(bandpass, "Apply a two-pole Butterworth band-pass filter.") static const AVOption bandreject_options[] = { {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, - {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, - {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, + {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, + {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, + {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, @@ -710,12 +721,13 @@ DEFINE_BIQUAD_FILTER(bandreject, "Apply a two-pole Butterworth band-reject filte static const AVOption lowpass_options[] = { {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS}, {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS}, - {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, - {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, + {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, + {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, + {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, @@ -731,12 +743,13 @@ DEFINE_BIQUAD_FILTER(lowpass, "Apply a low-pass filter with 3dB point frequency. static const AVOption highpass_options[] = { {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, - {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, - {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, + {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, + {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, + {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, @@ -752,12 +765,13 @@ DEFINE_BIQUAD_FILTER(highpass, "Apply a high-pass filter with 3dB point frequenc static const AVOption allpass_options[] = { {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, - {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, SLOPE, FLAGS, "width_type"}, - {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, SLOPE, FLAGS, "width_type"}, + {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, + {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, + {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, {"width", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS}, {"w", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, From 7fc89f226fb645c9701c8998a047a243a29f24fa Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 21 Dec 2017 11:44:22 +0100 Subject: [PATCH 1411/2557] avfilter/af_biquads: increase width range Signed-off-by: Paul B Mahol --- libavfilter/af_biquads.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index c04d03f191163..72e1074303e60 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -621,8 +621,8 @@ static const AVOption equalizer_options[] = { {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, - {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 999, FLAGS}, - {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 999, FLAGS}, + {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 99999, FLAGS}, + {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 99999, FLAGS}, {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, @@ -708,8 +708,8 @@ static const AVOption bandreject_options[] = { {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, - {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, - {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, + {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, + {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {NULL} @@ -783,12 +783,12 @@ DEFINE_BIQUAD_FILTER(allpass, "Apply a two-pole all-pass filter."); #endif /* CONFIG_ALLPASS_FILTER */ #if CONFIG_BIQUAD_FILTER static const AVOption biquad_options[] = { - {"a0", NULL, OFFSET(a0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, - {"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, - {"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, - {"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, - {"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, - {"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, + {"a0", NULL, OFFSET(a0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, + {"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, + {"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, + {"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, + {"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, + {"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {NULL} From 5a6e753bc62f0773f44069a9a8e10e9c13326d6a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 21 Dec 2017 12:06:21 +0100 Subject: [PATCH 1412/2557] avfilter/af_biquads: change defaults for biquad filter Signed-off-by: Paul B Mahol --- libavfilter/af_biquads.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index 72e1074303e60..1d72cd57518ab 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -784,11 +784,11 @@ DEFINE_BIQUAD_FILTER(allpass, "Apply a two-pole all-pass filter."); #if CONFIG_BIQUAD_FILTER static const AVOption biquad_options[] = { {"a0", NULL, OFFSET(a0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, - {"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, - {"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, - {"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, - {"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, - {"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, + {"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {NULL} From 55eebf2a11d28146658565948d6649311f20c0e1 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 14 Dec 2017 19:46:52 +0100 Subject: [PATCH 1413/2557] v4l_m2m: add missing AV_CODEC_CAP_DELAY flags This is pretty much a requirement for any codec that handles modern codecs like h264, but it was missing. Potentially could lead to issues like missing frames at the end of a stream. Tested-by: Jorge Ramirez --- libavcodec/v4l2_m2m_dec.c | 2 +- libavcodec/v4l2_m2m_enc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index c4ea20ea834c8..8308613978ded 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -215,7 +215,7 @@ AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \ .receive_frame = v4l2_receive_frame,\ .close = ff_v4l2_m2m_codec_end,\ .bsfs = bsf_name, \ - .capabilities = AV_CODEC_CAP_HARDWARE, \ + .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \ .wrapper_name = "v4l2m2m", \ }; diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c index f62ce7cdb5a34..7e88f4d2e6f67 100644 --- a/libavcodec/v4l2_m2m_enc.c +++ b/libavcodec/v4l2_m2m_enc.c @@ -335,7 +335,7 @@ AVCodec ff_ ## NAME ## _v4l2m2m_encoder = { \ .send_frame = v4l2_send_frame,\ .receive_packet = v4l2_receive_packet,\ .close = ff_v4l2_m2m_codec_end,\ - .capabilities = AV_CODEC_CAP_HARDWARE, \ + .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \ .wrapper_name = "v4l2m2m", \ }; From 1083859cb8c9d9b3bcee970dd33b71015a0a11bc Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 14 Dec 2017 19:47:18 +0100 Subject: [PATCH 1414/2557] rkmppdec: move AV_CODEC_CAP_AVOID_PROBING to the correct field AVCodec.caps_internal doesn't hold this field. (Untested.) --- libavcodec/rkmppdec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c index fa522ce2edce9..c57a6ded380bb 100644 --- a/libavcodec/rkmppdec.c +++ b/libavcodec/rkmppdec.c @@ -588,8 +588,7 @@ static const AVCodecHWConfigInternal *rkmpp_hw_configs[] = { .receive_frame = rkmpp_receive_frame, \ .flush = rkmpp_flush, \ .priv_class = &rkmpp_##NAME##_dec_class, \ - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \ - .caps_internal = AV_CODEC_CAP_AVOID_PROBING, \ + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ AV_PIX_FMT_NONE}, \ .hw_configs = rkmpp_hw_configs, \ From 42274db1c623d2c0acd616cc0d3a0e5489e3bdb2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 17 Dec 2017 18:29:45 +0100 Subject: [PATCH 1415/2557] avcodec/jpeg2000dec: Allocate lengthinc and data_start arrays as needed Decreases memory requirements Fixes: OOM Fixes: 4525/clusterfuzz-testcase-minimized-6400713073623040 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/jpeg2000.c | 3 ++- libavcodec/jpeg2000.h | 4 ++-- libavcodec/jpeg2000dec.c | 9 +++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c index 5f3965047fba8..e7f03bd0df53d 100644 --- a/libavcodec/jpeg2000.c +++ b/libavcodec/jpeg2000.c @@ -359,7 +359,6 @@ static int init_prec(Jpeg2000Band *band, cblk->lblock = 3; cblk->length = 0; - memset(cblk->lengthinc, 0, sizeof(cblk->lengthinc)); cblk->npasses = 0; } @@ -607,6 +606,8 @@ void ff_jpeg2000_cleanup(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty) Jpeg2000Cblk *cblk = &prec->cblk[cblkno]; av_freep(&cblk->data); av_freep(&cblk->passes); + av_freep(&cblk->lengthinc); + av_freep(&cblk->data_start); } av_freep(&prec->cblk); } diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h index 752feae96bc25..c429ca5996175 100644 --- a/libavcodec/jpeg2000.h +++ b/libavcodec/jpeg2000.h @@ -165,14 +165,14 @@ typedef struct Jpeg2000Cblk { uint8_t ninclpasses; // number coding of passes included in codestream uint8_t nonzerobits; uint16_t length; - uint16_t lengthinc[JPEG2000_MAX_PASSES]; + uint16_t *lengthinc; uint8_t nb_lengthinc; uint8_t lblock; uint8_t *data; size_t data_allocated; int nb_terminations; int nb_terminationsinc; - int data_start[JPEG2000_MAX_PASSES]; + int *data_start; Jpeg2000Pass *passes; int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} } Jpeg2000Cblk; // code block diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 0309b1f6fb217..617273b36bb12 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -949,6 +949,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) { Jpeg2000Cblk *cblk = prec->cblk + cblkno; int incl, newpasses, llen; + void *tmp; if (cblk->npasses) incl = get_bits(s, 1); @@ -988,6 +989,14 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, cblk->nb_lengthinc = 0; cblk->nb_terminationsinc = 0; + av_free(cblk->lengthinc); + cblk->lengthinc = av_mallocz_array(newpasses , sizeof(*cblk->lengthinc)); + if (!cblk->lengthinc) + return AVERROR(ENOMEM); + tmp = av_realloc_array(cblk->data_start, cblk->nb_terminations + newpasses + 1, sizeof(*cblk->data_start)); + if (!tmp) + return AVERROR(ENOMEM); + cblk->data_start = tmp; do { int newpasses1 = 0; From 4b2a186ef02c1fbe7f7cae30a2bdfff72bcc75f7 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 10 Dec 2017 15:01:43 +0100 Subject: [PATCH 1416/2557] avcodec/mpeg4videodec: Add support for parsing and exporting video_range Signed-off-by: Michael Niedermayer --- libavcodec/mpeg4video.h | 3 +++ libavcodec/mpeg4videodec.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/libavcodec/mpeg4video.h b/libavcodec/mpeg4video.h index 515b008ae45e7..0ba502d50bdd5 100644 --- a/libavcodec/mpeg4video.h +++ b/libavcodec/mpeg4video.h @@ -43,6 +43,9 @@ #define ACE_VO_TYPE 12 #define ADV_SIMPLE_VO_TYPE 17 +#define VOT_VIDEO_ID 1 +#define VOT_STILL_TEXTURE_ID 2 + // aspect_ratio_info #define EXTENDED_PAR 15 diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index cdd7077f01e3d..e9cba25dd0ffe 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -1754,6 +1754,37 @@ static int mpeg4_decode_profile_level(MpegEncContext *s, GetBitContext *gb) return 0; } +static int mpeg4_decode_visual_object(MpegEncContext *s, GetBitContext *gb) +{ + int visual_object_type; + int is_visual_object_identifier = get_bits1(gb); + + if (is_visual_object_identifier) { + skip_bits(gb, 4+3); + } + visual_object_type = get_bits(gb, 4); + + if (visual_object_type == VOT_VIDEO_ID || + visual_object_type == VOT_STILL_TEXTURE_ID) { + int video_signal_type = get_bits1(gb); + if (video_signal_type) { + int video_format = get_bits(gb, 3); + int video_range = get_bits1(gb); + int color_description = get_bits1(gb); + + s->avctx->color_range = video_range ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; + + if (color_description) { + s->avctx->color_primaries = get_bits(gb, 8); + s->avctx->color_trc = get_bits(gb, 8); + s->avctx->colorspace = get_bits(gb, 8); + } + } + } + + return 0; +} + static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) { MpegEncContext *s = &ctx->m; @@ -2684,6 +2715,8 @@ int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb) mpeg4_decode_gop_header(s, gb); } else if (startcode == VOS_STARTCODE) { mpeg4_decode_profile_level(s, gb); + } else if (startcode == VISUAL_OBJ_STARTCODE) { + mpeg4_decode_visual_object(s, gb); } else if (startcode == VOP_STARTCODE) { break; } From 80344959f064c7ea10d023862e0f6b79835de9de Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 17 Dec 2017 23:35:26 +0100 Subject: [PATCH 1417/2557] avcodec/jpeg2000dec: Free lengthinc earlier Reduces memory needed Signed-off-by: Michael Niedermayer --- libavcodec/jpeg2000dec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 617273b36bb12..8071dc3c84a5f 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -1046,6 +1046,8 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, nb_code_blocks = prec->nb_codeblocks_height * prec->nb_codeblocks_width; for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) { Jpeg2000Cblk *cblk = prec->cblk + cblkno; + if (!cblk->nb_terminationsinc && !cblk->lengthinc) + continue; for (cwsno = 0; cwsno < cblk->nb_lengthinc; cwsno ++) { if (cblk->data_allocated < cblk->length + cblk->lengthinc[cwsno] + 4) { size_t new_size = FFMAX(2*cblk->data_allocated, cblk->length + cblk->lengthinc[cwsno] + 4); @@ -1075,6 +1077,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, cblk->data_start[cblk->nb_terminations] = cblk->length; } } + av_freep(&cblk->lengthinc); } } return 0; From d6a8e46f9788810392555d891fc2f0db342a6a44 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 10 Dec 2017 00:07:17 +0100 Subject: [PATCH 1418/2557] fate: add 12 bit framerate filter tests Signed-off-by: Marton Balint --- tests/fate/filter-video.mak | 4 ++ tests/ref/fate/filter-framerate-12bit-down | 55 +++++++++++++++++++ tests/ref/fate/filter-framerate-12bit-up | 64 ++++++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 tests/ref/fate/filter-framerate-12bit-down create mode 100644 tests/ref/fate/filter-framerate-12bit-up diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index c19f301ff8dfc..39442f6717f21 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -113,6 +113,10 @@ FATE_FILTER-$(call ALLYES, FRAMERATE_FILTER TESTSRC2_FILTER) += fate-filter-fram fate-filter-framerate-up: CMD = framecrc -lavfi testsrc2=r=2:d=10,framerate=fps=10 -t 1 fate-filter-framerate-down: CMD = framecrc -lavfi testsrc2=r=2:d=10,framerate=fps=1 -t 1 +FATE_FILTER-$(call ALLYES, FRAMERATE_FILTER TESTSRC2_FILTER FORMAT_FILTER) += fate-filter-framerate-12bit-up fate-filter-framerate-12bit-down +fate-filter-framerate-12bit-up: CMD = framecrc -lavfi testsrc2=r=50:d=1,format=pix_fmts=yuv422p12,framerate=fps=60 -t 1 +fate-filter-framerate-12bit-down: CMD = framecrc -lavfi testsrc2=r=60:d=1,format=pix_fmts=yuv422p12,framerate=fps=50 -t 1 + FATE_FILTER_VSYNTH-$(CONFIG_BOXBLUR_FILTER) += fate-filter-boxblur fate-filter-boxblur: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf boxblur=2:1 diff --git a/tests/ref/fate/filter-framerate-12bit-down b/tests/ref/fate/filter-framerate-12bit-down new file mode 100644 index 0000000000000..7a5a7b8e14f6d --- /dev/null +++ b/tests/ref/fate/filter-framerate-12bit-down @@ -0,0 +1,55 @@ +#tb 0: 1/50 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 307200, 0xb49cf016 +0, 1, 1, 1, 307200, 0xfe025c7f +0, 2, 2, 1, 307200, 0x4d458da1 +0, 3, 3, 1, 307200, 0x35d4d8ea +0, 4, 4, 1, 307200, 0x88f88697 +0, 5, 5, 1, 307200, 0xaf71e7fc +0, 6, 6, 1, 307200, 0x1290a487 +0, 7, 7, 1, 307200, 0xaf0cf5ee +0, 8, 8, 1, 307200, 0x9fe73a9b +0, 9, 9, 1, 307200, 0xb7965b77 +0, 10, 10, 1, 307200, 0x9f84df5d +0, 11, 11, 1, 307200, 0xf60b8c87 +0, 12, 12, 1, 307200, 0xe2eac3a7 +0, 13, 13, 1, 307200, 0xefbbc67a +0, 14, 14, 1, 307200, 0xb293001a +0, 15, 15, 1, 307200, 0xab2162fc +0, 16, 16, 1, 307200, 0xdc90848a +0, 17, 17, 1, 307200, 0x29f79f4b +0, 18, 18, 1, 307200, 0x62aee029 +0, 19, 19, 1, 307200, 0xcb6de0e9 +0, 20, 20, 1, 307200, 0xf2b12fe5 +0, 21, 21, 1, 307200, 0x1de67e13 +0, 22, 22, 1, 307200, 0xfc1f7774 +0, 23, 23, 1, 307200, 0x707fe832 +0, 24, 24, 1, 307200, 0xe2dc0742 +0, 25, 25, 1, 307200, 0x4693ab03 +0, 26, 26, 1, 307200, 0x7295ef7a +0, 27, 27, 1, 307200, 0xf442a5df +0, 28, 28, 1, 307200, 0x3019dbbc +0, 29, 29, 1, 307200, 0xd82a394d +0, 30, 30, 1, 307200, 0x8a512668 +0, 31, 31, 1, 307200, 0x69e7b43e +0, 32, 32, 1, 307200, 0x6c5343ca +0, 33, 33, 1, 307200, 0x8aac4531 +0, 34, 34, 1, 307200, 0x4b7f5b63 +0, 35, 35, 1, 307200, 0x4e24d659 +0, 36, 36, 1, 307200, 0x7a25b546 +0, 37, 37, 1, 307200, 0x9b7e8e8f +0, 38, 38, 1, 307200, 0x94ec9d3d +0, 39, 39, 1, 307200, 0x856ea560 +0, 40, 40, 1, 307200, 0xb6505ff0 +0, 41, 41, 1, 307200, 0x12562a42 +0, 42, 42, 1, 307200, 0x3335e451 +0, 43, 43, 1, 307200, 0x7f0374c9 +0, 44, 44, 1, 307200, 0x487e798a +0, 45, 45, 1, 307200, 0x4fda2634 +0, 46, 46, 1, 307200, 0x5b48d624 +0, 47, 47, 1, 307200, 0xa9505af8 +0, 48, 48, 1, 307200, 0xce7248b5 +0, 49, 49, 1, 307200, 0x8fbc1bec diff --git a/tests/ref/fate/filter-framerate-12bit-up b/tests/ref/fate/filter-framerate-12bit-up new file mode 100644 index 0000000000000..8f57e6d06661f --- /dev/null +++ b/tests/ref/fate/filter-framerate-12bit-up @@ -0,0 +1,64 @@ +#tb 0: 1/60 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 307200, 0xb49cf016 +0, 1, 1, 1, 307200, 0xc74259b4 +0, 2, 2, 1, 307200, 0xe4ca172c +0, 3, 3, 1, 307200, 0x5378b13c +0, 4, 4, 1, 307200, 0x2a7d4840 +0, 5, 5, 1, 307200, 0x68f620cd +0, 6, 6, 1, 307200, 0x83dbe321 +0, 7, 7, 1, 307200, 0xcd73c6ab +0, 8, 8, 1, 307200, 0xc69a864a +0, 9, 9, 1, 307200, 0xc5c8b0f8 +0, 10, 10, 1, 307200, 0xf08a6033 +0, 11, 11, 1, 307200, 0xab36763c +0, 12, 12, 1, 307200, 0xcba4c6bb +0, 13, 13, 1, 307200, 0x8dabc7b5 +0, 14, 14, 1, 307200, 0x63339757 +0, 15, 15, 1, 307200, 0x4bdfd3ca +0, 16, 16, 1, 307200, 0x699c9c83 +0, 17, 17, 1, 307200, 0x5dc7c711 +0, 18, 18, 1, 307200, 0xda8c6c41 +0, 19, 19, 1, 307200, 0xeb4ac99c +0, 20, 20, 1, 307200, 0x5d8b76ab +0, 21, 21, 1, 307200, 0xe2337c57 +0, 22, 22, 1, 307200, 0x84531dcf +0, 23, 23, 1, 307200, 0xf0df5ea3 +0, 24, 24, 1, 307200, 0x4237e892 +0, 25, 25, 1, 307200, 0xc111a9eb +0, 26, 26, 1, 307200, 0x2ba55745 +0, 27, 27, 1, 307200, 0x0e058165 +0, 28, 28, 1, 307200, 0xd184f860 +0, 29, 29, 1, 307200, 0xab562bfe +0, 30, 30, 1, 307200, 0x0b58bcf7 +0, 31, 31, 1, 307200, 0x044f4a16 +0, 32, 32, 1, 307200, 0xb466f1d6 +0, 33, 33, 1, 307200, 0x3ed6b5d8 +0, 34, 34, 1, 307200, 0xb8b82049 +0, 35, 35, 1, 307200, 0xbfb20efc +0, 36, 36, 1, 307200, 0xbd67248a +0, 37, 37, 1, 307200, 0x76e11928 +0, 38, 38, 1, 307200, 0x6ec5bbb1 +0, 39, 39, 1, 307200, 0x0e4455cd +0, 40, 40, 1, 307200, 0x5ccf33fb +0, 41, 41, 1, 307200, 0x976f6900 +0, 42, 42, 1, 307200, 0x58adad3f +0, 43, 43, 1, 307200, 0x1f791403 +0, 44, 44, 1, 307200, 0x49163226 +0, 45, 45, 1, 307200, 0xaac8e1ca +0, 46, 46, 1, 307200, 0x7fe784f7 +0, 47, 47, 1, 307200, 0xbf85c994 +0, 48, 48, 1, 307200, 0x22ed5b5a +0, 49, 49, 1, 307200, 0xdbeee1f3 +0, 50, 50, 1, 307200, 0x3a21b4d2 +0, 51, 51, 1, 307200, 0xbd5edb2d +0, 52, 52, 1, 307200, 0xc66d8b27 +0, 53, 53, 1, 307200, 0x02c7e528 +0, 54, 54, 1, 307200, 0xba073e6f +0, 55, 55, 1, 307200, 0xf745ded7 +0, 56, 56, 1, 307200, 0x8cf55128 +0, 57, 57, 1, 307200, 0x4e740b42 +0, 58, 58, 1, 307200, 0x7906723a From 1eb926dc02684e0d4036b1edd2cba6b809451301 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 9 Dec 2017 22:46:27 +0100 Subject: [PATCH 1419/2557] avfilter/vf_framerate: add threaded blending operations Signed-off-by: Marton Balint --- libavfilter/vf_framerate.c | 202 +++++++++++++++++++++++-------------- 1 file changed, 125 insertions(+), 77 deletions(-) diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index dc8b05f40f261..d505c5a8a44a8 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -210,6 +210,117 @@ static double get_scene_score(AVFilterContext *ctx, AVFrame *crnt, AVFrame *next return ret; } +typedef struct ThreadData { + AVFrame *copy_src1, *copy_src2; + uint16_t src1_factor, src2_factor; +} ThreadData; + +static int filter_slice8(AVFilterContext *ctx, void *arg, int job, int nb_jobs) +{ + FrameRateContext *s = ctx->priv; + ThreadData *td = arg; + uint16_t src1_factor = td->src1_factor; + uint16_t src2_factor = td->src2_factor; + int plane, line, pixel; + + for (plane = 0; plane < 4 && td->copy_src1->data[plane] && td->copy_src2->data[plane]; plane++) { + int cpy_line_width = s->line_size[plane]; + uint8_t *cpy_src1_data = td->copy_src1->data[plane]; + int cpy_src1_line_size = td->copy_src1->linesize[plane]; + uint8_t *cpy_src2_data = td->copy_src2->data[plane]; + int cpy_src2_line_size = td->copy_src2->linesize[plane]; + int cpy_src_h = (plane > 0 && plane < 3) ? (td->copy_src1->height >> s->vsub) : (td->copy_src1->height); + uint8_t *cpy_dst_data = s->work->data[plane]; + int cpy_dst_line_size = s->work->linesize[plane]; + const int start = (cpy_src_h * job ) / nb_jobs; + const int end = (cpy_src_h * (job+1)) / nb_jobs; + cpy_src1_data += start * cpy_src1_line_size; + cpy_src2_data += start * cpy_src2_line_size; + cpy_dst_data += start * cpy_dst_line_size; + + if (plane <1 || plane >2) { + // luma or alpha + for (line = start; line < end; line++) { + for (pixel = 0; pixel < cpy_line_width; pixel++) { + // integer version of (src1 * src1_factor) + (src2 + src2_factor) + 0.5 + // 0.5 is for rounding + // 128 is the integer representation of 0.5 << 8 + cpy_dst_data[pixel] = ((cpy_src1_data[pixel] * src1_factor) + (cpy_src2_data[pixel] * src2_factor) + 128) >> 8; + } + cpy_src1_data += cpy_src1_line_size; + cpy_src2_data += cpy_src2_line_size; + cpy_dst_data += cpy_dst_line_size; + } + } else { + // chroma + for (line = start; line < end; line++) { + for (pixel = 0; pixel < cpy_line_width; pixel++) { + // as above + // because U and V are based around 128 we have to subtract 128 from the components. + // 32896 is the integer representation of 128.5 << 8 + cpy_dst_data[pixel] = (((cpy_src1_data[pixel] - 128) * src1_factor) + ((cpy_src2_data[pixel] - 128) * src2_factor) + 32896) >> 8; + } + cpy_src1_data += cpy_src1_line_size; + cpy_src2_data += cpy_src2_line_size; + cpy_dst_data += cpy_dst_line_size; + } + } + } + + return 0; +} + +static int filter_slice16(AVFilterContext *ctx, void *arg, int job, int nb_jobs) +{ + FrameRateContext *s = ctx->priv; + ThreadData *td = arg; + uint16_t src1_factor = td->src1_factor; + uint16_t src2_factor = td->src2_factor; + const int half = s->max / 2; + const int uv = (s->max + 1) * half; + const int shift = s->bitdepth; + int plane, line, pixel; + + for (plane = 0; plane < 4 && td->copy_src1->data[plane] && td->copy_src2->data[plane]; plane++) { + int cpy_line_width = s->line_size[plane]; + const uint16_t *cpy_src1_data = (const uint16_t *)td->copy_src1->data[plane]; + int cpy_src1_line_size = td->copy_src1->linesize[plane] / 2; + const uint16_t *cpy_src2_data = (const uint16_t *)td->copy_src2->data[plane]; + int cpy_src2_line_size = td->copy_src2->linesize[plane] / 2; + int cpy_src_h = (plane > 0 && plane < 3) ? (td->copy_src1->height >> s->vsub) : (td->copy_src1->height); + uint16_t *cpy_dst_data = (uint16_t *)s->work->data[plane]; + int cpy_dst_line_size = s->work->linesize[plane] / 2; + const int start = (cpy_src_h * job ) / nb_jobs; + const int end = (cpy_src_h * (job+1)) / nb_jobs; + cpy_src1_data += start * cpy_src1_line_size; + cpy_src2_data += start * cpy_src2_line_size; + cpy_dst_data += start * cpy_dst_line_size; + + if (plane <1 || plane >2) { + // luma or alpha + for (line = start; line < end; line++) { + for (pixel = 0; pixel < cpy_line_width; pixel++) + cpy_dst_data[pixel] = ((cpy_src1_data[pixel] * src1_factor) + (cpy_src2_data[pixel] * src2_factor) + half) >> shift; + cpy_src1_data += cpy_src1_line_size; + cpy_src2_data += cpy_src2_line_size; + cpy_dst_data += cpy_dst_line_size; + } + } else { + // chroma + for (line = start; line < end; line++) { + for (pixel = 0; pixel < cpy_line_width; pixel++) { + cpy_dst_data[pixel] = (((cpy_src1_data[pixel] - half) * src1_factor) + ((cpy_src2_data[pixel] - half) * src2_factor) + uv) >> shift; + } + cpy_src1_data += cpy_src1_line_size; + cpy_src2_data += cpy_src2_line_size; + cpy_dst_data += cpy_dst_line_size; + } + } + } + + return 0; +} + static int blend_frames16(AVFilterContext *ctx, float interpolate, AVFrame *copy_src1, AVFrame *copy_src2) { @@ -223,12 +334,11 @@ static int blend_frames16(AVFilterContext *ctx, float interpolate, } // decide if the shot-change detection allows us to blend two frames if (interpolate_scene_score < s->scene_score && copy_src2) { - uint16_t src2_factor = fabsf(interpolate) * (1 << (s->bitdepth - 8)); - uint16_t src1_factor = s->max - src2_factor; - const int half = s->max / 2; - const int uv = (s->max + 1) * half; - const int shift = s->bitdepth; - int plane, line, pixel; + ThreadData td; + td.copy_src1 = copy_src1; + td.copy_src2 = copy_src2; + td.src2_factor = fabsf(interpolate) * (1 << (s->bitdepth - 8)); + td.src1_factor = s->max - td.src2_factor; // get work-space for output frame s->work = ff_get_video_buffer(outlink, outlink->w, outlink->h); @@ -238,37 +348,7 @@ static int blend_frames16(AVFilterContext *ctx, float interpolate, av_frame_copy_props(s->work, s->srce[s->crnt]); ff_dlog(ctx, "blend_frames16() INTERPOLATE to create work frame\n"); - for (plane = 0; plane < 4 && copy_src1->data[plane] && copy_src2->data[plane]; plane++) { - int cpy_line_width = s->line_size[plane]; - const uint16_t *cpy_src1_data = (const uint16_t *)copy_src1->data[plane]; - int cpy_src1_line_size = copy_src1->linesize[plane] / 2; - const uint16_t *cpy_src2_data = (const uint16_t *)copy_src2->data[plane]; - int cpy_src2_line_size = copy_src2->linesize[plane] / 2; - int cpy_src_h = (plane > 0 && plane < 3) ? (copy_src1->height >> s->vsub) : (copy_src1->height); - uint16_t *cpy_dst_data = (uint16_t *)s->work->data[plane]; - int cpy_dst_line_size = s->work->linesize[plane] / 2; - - if (plane <1 || plane >2) { - // luma or alpha - for (line = 0; line < cpy_src_h; line++) { - for (pixel = 0; pixel < cpy_line_width; pixel++) - cpy_dst_data[pixel] = ((cpy_src1_data[pixel] * src1_factor) + (cpy_src2_data[pixel] * src2_factor) + half) >> shift; - cpy_src1_data += cpy_src1_line_size; - cpy_src2_data += cpy_src2_line_size; - cpy_dst_data += cpy_dst_line_size; - } - } else { - // chroma - for (line = 0; line < cpy_src_h; line++) { - for (pixel = 0; pixel < cpy_line_width; pixel++) { - cpy_dst_data[pixel] = (((cpy_src1_data[pixel] - half) * src1_factor) + ((cpy_src2_data[pixel] - half) * src2_factor) + uv) >> shift; - } - cpy_src1_data += cpy_src1_line_size; - cpy_src2_data += cpy_src2_line_size; - cpy_dst_data += cpy_dst_line_size; - } - } - } + ctx->internal->execute(ctx, filter_slice16, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); return 1; } return 0; @@ -287,9 +367,11 @@ static int blend_frames8(AVFilterContext *ctx, float interpolate, } // decide if the shot-change detection allows us to blend two frames if (interpolate_scene_score < s->scene_score && copy_src2) { - uint16_t src2_factor = fabsf(interpolate); - uint16_t src1_factor = 256 - src2_factor; - int plane, line, pixel; + ThreadData td; + td.copy_src1 = copy_src1; + td.copy_src2 = copy_src2; + td.src2_factor = fabsf(interpolate); + td.src1_factor = 256 - td.src2_factor; // get work-space for output frame s->work = ff_get_video_buffer(outlink, outlink->w, outlink->h); @@ -299,43 +381,8 @@ static int blend_frames8(AVFilterContext *ctx, float interpolate, av_frame_copy_props(s->work, s->srce[s->crnt]); ff_dlog(ctx, "blend_frames8() INTERPOLATE to create work frame\n"); - for (plane = 0; plane < 4 && copy_src1->data[plane] && copy_src2->data[plane]; plane++) { - int cpy_line_width = s->line_size[plane]; - uint8_t *cpy_src1_data = copy_src1->data[plane]; - int cpy_src1_line_size = copy_src1->linesize[plane]; - uint8_t *cpy_src2_data = copy_src2->data[plane]; - int cpy_src2_line_size = copy_src2->linesize[plane]; - int cpy_src_h = (plane > 0 && plane < 3) ? (copy_src1->height >> s->vsub) : (copy_src1->height); - uint8_t *cpy_dst_data = s->work->data[plane]; - int cpy_dst_line_size = s->work->linesize[plane]; - if (plane <1 || plane >2) { - // luma or alpha - for (line = 0; line < cpy_src_h; line++) { - for (pixel = 0; pixel < cpy_line_width; pixel++) { - // integer version of (src1 * src1_factor) + (src2 + src2_factor) + 0.5 - // 0.5 is for rounding - // 128 is the integer representation of 0.5 << 8 - cpy_dst_data[pixel] = ((cpy_src1_data[pixel] * src1_factor) + (cpy_src2_data[pixel] * src2_factor) + 128) >> 8; - } - cpy_src1_data += cpy_src1_line_size; - cpy_src2_data += cpy_src2_line_size; - cpy_dst_data += cpy_dst_line_size; - } - } else { - // chroma - for (line = 0; line < cpy_src_h; line++) { - for (pixel = 0; pixel < cpy_line_width; pixel++) { - // as above - // because U and V are based around 128 we have to subtract 128 from the components. - // 32896 is the integer representation of 128.5 << 8 - cpy_dst_data[pixel] = (((cpy_src1_data[pixel] - 128) * src1_factor) + ((cpy_src2_data[pixel] - 128) * src2_factor) + 32896) >> 8; - } - cpy_src1_data += cpy_src1_line_size; - cpy_src2_data += cpy_src2_line_size; - cpy_dst_data += cpy_dst_line_size; - } - } - } + ctx->internal->execute(ctx, filter_slice8, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); + return 1; } return 0; @@ -738,4 +785,5 @@ AVFilter ff_vf_framerate = { .query_formats = query_formats, .inputs = framerate_inputs, .outputs = framerate_outputs, + .flags = AVFILTER_FLAG_SLICE_THREADS, }; From 090b740680f91e0f2bf07423c36df7166740e8f6 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 9 Dec 2017 23:00:57 +0100 Subject: [PATCH 1420/2557] avfilter/vf_framerate: factorize blend_frames Signed-off-by: Marton Balint --- libavfilter/vf_framerate.c | 54 +++++--------------------------------- 1 file changed, 7 insertions(+), 47 deletions(-) diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index d505c5a8a44a8..f931a6f51244d 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -73,8 +73,6 @@ typedef struct FrameRateContext { int64_t srce_pts_dest[N_SRCE]; ///< pts for source frames scaled to output timebase int64_t pts; ///< pts of frame we are working on - int (*blend_frames)(AVFilterContext *ctx, float interpolate, - AVFrame *copy_src1, AVFrame *copy_src2); int max; int bitdepth; AVFrame *work; @@ -321,16 +319,16 @@ static int filter_slice16(AVFilterContext *ctx, void *arg, int job, int nb_jobs) return 0; } -static int blend_frames16(AVFilterContext *ctx, float interpolate, - AVFrame *copy_src1, AVFrame *copy_src2) +static int blend_frames(AVFilterContext *ctx, float interpolate, + AVFrame *copy_src1, AVFrame *copy_src2) { FrameRateContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; double interpolate_scene_score = 0; if ((s->flags & FRAMERATE_FLAG_SCD) && copy_src2) { - interpolate_scene_score = get_scene_score16(ctx, copy_src1, copy_src2); - ff_dlog(ctx, "blend_frames16() interpolate scene score:%f\n", interpolate_scene_score); + interpolate_scene_score = s->bitdepth == 8 ? get_scene_score(ctx, copy_src1, copy_src2) : get_scene_score16(ctx, copy_src1, copy_src2); + ff_dlog(ctx, "blend_frames() interpolate scene score:%f\n", interpolate_scene_score); } // decide if the shot-change detection allows us to blend two frames if (interpolate_scene_score < s->scene_score && copy_src2) { @@ -347,42 +345,8 @@ static int blend_frames16(AVFilterContext *ctx, float interpolate, av_frame_copy_props(s->work, s->srce[s->crnt]); - ff_dlog(ctx, "blend_frames16() INTERPOLATE to create work frame\n"); - ctx->internal->execute(ctx, filter_slice16, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); - return 1; - } - return 0; -} - -static int blend_frames8(AVFilterContext *ctx, float interpolate, - AVFrame *copy_src1, AVFrame *copy_src2) -{ - FrameRateContext *s = ctx->priv; - AVFilterLink *outlink = ctx->outputs[0]; - double interpolate_scene_score = 0; - - if ((s->flags & FRAMERATE_FLAG_SCD) && copy_src2) { - interpolate_scene_score = get_scene_score(ctx, copy_src1, copy_src2); - ff_dlog(ctx, "blend_frames8() interpolate scene score:%f\n", interpolate_scene_score); - } - // decide if the shot-change detection allows us to blend two frames - if (interpolate_scene_score < s->scene_score && copy_src2) { - ThreadData td; - td.copy_src1 = copy_src1; - td.copy_src2 = copy_src2; - td.src2_factor = fabsf(interpolate); - td.src1_factor = 256 - td.src2_factor; - - // get work-space for output frame - s->work = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!s->work) - return AVERROR(ENOMEM); - - av_frame_copy_props(s->work, s->srce[s->crnt]); - - ff_dlog(ctx, "blend_frames8() INTERPOLATE to create work frame\n"); - ctx->internal->execute(ctx, filter_slice8, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); - + ff_dlog(ctx, "blend_frames() INTERPOLATE to create work frame\n"); + ctx->internal->execute(ctx, s->bitdepth == 8 ? filter_slice8 : filter_slice16, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); return 1; } return 0; @@ -458,7 +422,7 @@ static int process_work_frame(AVFilterContext *ctx, int stop) ff_dlog(ctx, "process_work_frame() interpolate source is:PREV\n"); copy_src2 = s->srce[s->prev]; } - if (s->blend_frames(ctx, interpolate, copy_src1, copy_src2)) + if (blend_frames(ctx, interpolate, copy_src1, copy_src2)) goto copy_done; else ff_dlog(ctx, "process_work_frame() CUT - DON'T INTERPOLATE\n"); @@ -622,10 +586,6 @@ static int config_input(AVFilterLink *inlink) s->srce_time_base = inlink->time_base; - if (s->bitdepth == 8) - s->blend_frames = blend_frames8; - else - s->blend_frames = blend_frames16; s->max = 1 << (s->bitdepth); return 0; From be15304ee610252636120f5e09fad4b015b34a31 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 10 Dec 2017 00:00:52 +0100 Subject: [PATCH 1421/2557] avfilter/vf_framerate: factorize get_scene_score Signed-off-by: Marton Balint --- libavfilter/vf_framerate.c | 78 +++++++++++++++----------------------- 1 file changed, 31 insertions(+), 47 deletions(-) diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index f931a6f51244d..1cad2305ade44 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -133,41 +133,35 @@ static av_always_inline int64_t sad_8x8_16(const uint16_t *src1, ptrdiff_t strid return sum; } -static double get_scene_score16(AVFilterContext *ctx, AVFrame *crnt, AVFrame *next) +static int64_t scene_sad16(FrameRateContext *s, const uint16_t *p1, int p1_linesize, const uint16_t* p2, int p2_linesize, int height) { - FrameRateContext *s = ctx->priv; - double ret = 0; - - ff_dlog(ctx, "get_scene_score16()\n"); + int64_t sad; + int x, y; + for (sad = y = 0; y < height; y += 8) { + for (x = 0; x < p1_linesize; x += 8) { + sad += sad_8x8_16(p1 + y * p1_linesize + x, + p1_linesize, + p2 + y * p2_linesize + x, + p2_linesize); + } + } + return sad; +} - if (crnt && - crnt->height == next->height && - crnt->width == next->width) { - int x, y; - int64_t sad; - double mafd, diff; - const uint16_t *p1 = (const uint16_t *)crnt->data[0]; - const uint16_t *p2 = (const uint16_t *)next->data[0]; - const int p1_linesize = crnt->linesize[0] / 2; - const int p2_linesize = next->linesize[0] / 2; - - ff_dlog(ctx, "get_scene_score16() process\n"); - - for (sad = y = 0; y < crnt->height; y += 8) { - for (x = 0; x < p1_linesize; x += 8) { - sad += sad_8x8_16(p1 + y * p1_linesize + x, - p1_linesize, - p2 + y * p2_linesize + x, - p2_linesize); - } +static int64_t scene_sad8(FrameRateContext *s, uint8_t *p1, int p1_linesize, uint8_t* p2, int p2_linesize, int height) +{ + int64_t sad; + int x, y; + for (sad = y = 0; y < height; y += 8) { + for (x = 0; x < p1_linesize; x += 8) { + sad += s->sad(p1 + y * p1_linesize + x, + p1_linesize, + p2 + y * p2_linesize + x, + p2_linesize); } - mafd = sad / (crnt->height * crnt->width * 3); - diff = fabs(mafd - s->prev_mafd); - ret = av_clipf(FFMIN(mafd, diff), 0, 100.0); - s->prev_mafd = mafd; } - ff_dlog(ctx, "get_scene_score16() result is:%f\n", ret); - return ret; + emms_c(); + return sad; } static double get_scene_score(AVFilterContext *ctx, AVFrame *crnt, AVFrame *next) @@ -180,31 +174,21 @@ static double get_scene_score(AVFilterContext *ctx, AVFrame *crnt, AVFrame *next if (crnt && crnt->height == next->height && crnt->width == next->width) { - int x, y; int64_t sad; double mafd, diff; - uint8_t *p1 = crnt->data[0]; - uint8_t *p2 = next->data[0]; - const int p1_linesize = crnt->linesize[0]; - const int p2_linesize = next->linesize[0]; ff_dlog(ctx, "get_scene_score() process\n"); + if (s->bitdepth == 8) + sad = scene_sad8(s, crnt->data[0], crnt->linesize[0], next->data[0], next->linesize[0], crnt->height); + else + sad = scene_sad16(s, (const uint16_t*)crnt->data[0], crnt->linesize[0] >> 1, (const uint16_t*)next->data[0], next->linesize[0] >> 1, crnt->height); - for (sad = y = 0; y < crnt->height; y += 8) { - for (x = 0; x < p1_linesize; x += 8) { - sad += s->sad(p1 + y * p1_linesize + x, - p1_linesize, - p2 + y * p2_linesize + x, - p2_linesize); - } - } - emms_c(); mafd = sad / (crnt->height * crnt->width * 3); diff = fabs(mafd - s->prev_mafd); ret = av_clipf(FFMIN(mafd, diff), 0, 100.0); s->prev_mafd = mafd; } - ff_dlog(ctx, "get_scene_score() result is:%f\n", ret); + ff_dlog(ctx, "get_scene_score() result is:%f\n", ret); return ret; } @@ -327,7 +311,7 @@ static int blend_frames(AVFilterContext *ctx, float interpolate, double interpolate_scene_score = 0; if ((s->flags & FRAMERATE_FLAG_SCD) && copy_src2) { - interpolate_scene_score = s->bitdepth == 8 ? get_scene_score(ctx, copy_src1, copy_src2) : get_scene_score16(ctx, copy_src1, copy_src2); + interpolate_scene_score = get_scene_score(ctx, copy_src1, copy_src2); ff_dlog(ctx, "blend_frames() interpolate scene score:%f\n", interpolate_scene_score); } // decide if the shot-change detection allows us to blend two frames From e1113a83ccb6bb30e3ad865956fe9eed0d650394 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 10 Dec 2017 00:29:12 +0100 Subject: [PATCH 1422/2557] avfilter/vf_framerate: fix scene change detection score - normalize score to [0..100] instead of [0..85] - change the default score to 8.2 to roughly keep existing behaviour - take into account bit depth - do not truncate to integer Signed-off-by: Marton Balint --- doc/filters.texi | 2 +- libavfilter/vf_framerate.c | 4 ++-- tests/ref/fate/filter-framerate-12bit-down | 2 +- tests/ref/fate/filter-framerate-12bit-up | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 6a6d5a334ee6e..45515966e8953 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -9121,7 +9121,7 @@ Specify the level at which a scene change is detected as a value between 0 and 100 to indicate a new scene; a low value reflects a low probability for the current frame to introduce a new scene, while a higher value means the current frame is more likely to be one. -The default is @code{7}. +The default is @code{8.2}. @item flags Specify flags influencing the filter process. diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index 1cad2305ade44..dd106f8e5b791 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -88,7 +88,7 @@ static const AVOption framerate_options[] = { {"interp_start", "point to start linear interpolation", OFFSET(interp_start), AV_OPT_TYPE_INT, {.i64=15}, 0, 255, V|F }, {"interp_end", "point to end linear interpolation", OFFSET(interp_end), AV_OPT_TYPE_INT, {.i64=240}, 0, 255, V|F }, - {"scene", "scene change level", OFFSET(scene_score), AV_OPT_TYPE_DOUBLE, {.dbl=7.0}, 0, INT_MAX, V|F }, + {"scene", "scene change level", OFFSET(scene_score), AV_OPT_TYPE_DOUBLE, {.dbl=8.2}, 0, INT_MAX, V|F }, {"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, INT_MAX, V|F, "flags" }, {"scene_change_detect", "enable scene change detection", 0, AV_OPT_TYPE_CONST, {.i64=FRAMERATE_FLAG_SCD}, INT_MIN, INT_MAX, V|F, "flags" }, @@ -183,7 +183,7 @@ static double get_scene_score(AVFilterContext *ctx, AVFrame *crnt, AVFrame *next else sad = scene_sad16(s, (const uint16_t*)crnt->data[0], crnt->linesize[0] >> 1, (const uint16_t*)next->data[0], next->linesize[0] >> 1, crnt->height); - mafd = sad / (crnt->height * crnt->width * 3); + mafd = (double)sad * 100.0 / (crnt->height * crnt->width) / (1 << s->bitdepth); diff = fabs(mafd - s->prev_mafd); ret = av_clipf(FFMIN(mafd, diff), 0, 100.0); s->prev_mafd = mafd; diff --git a/tests/ref/fate/filter-framerate-12bit-down b/tests/ref/fate/filter-framerate-12bit-down index 7a5a7b8e14f6d..0a9aea0ce1f11 100644 --- a/tests/ref/fate/filter-framerate-12bit-down +++ b/tests/ref/fate/filter-framerate-12bit-down @@ -4,7 +4,7 @@ #dimensions 0: 320x240 #sar 0: 1/1 0, 0, 0, 1, 307200, 0xb49cf016 -0, 1, 1, 1, 307200, 0xfe025c7f +0, 1, 1, 1, 307200, 0xc3be6971 0, 2, 2, 1, 307200, 0x4d458da1 0, 3, 3, 1, 307200, 0x35d4d8ea 0, 4, 4, 1, 307200, 0x88f88697 diff --git a/tests/ref/fate/filter-framerate-12bit-up b/tests/ref/fate/filter-framerate-12bit-up index 8f57e6d06661f..8f5f95b275cab 100644 --- a/tests/ref/fate/filter-framerate-12bit-up +++ b/tests/ref/fate/filter-framerate-12bit-up @@ -4,7 +4,7 @@ #dimensions 0: 320x240 #sar 0: 1/1 0, 0, 0, 1, 307200, 0xb49cf016 -0, 1, 1, 1, 307200, 0xc74259b4 +0, 1, 1, 1, 307200, 0x59cb92c7 0, 2, 2, 1, 307200, 0xe4ca172c 0, 3, 3, 1, 307200, 0x5378b13c 0, 4, 4, 1, 307200, 0x2a7d4840 From c6a65ed67088fd61017f14691b5fcecd133d9eeb Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 10 Dec 2017 03:18:49 +0100 Subject: [PATCH 1423/2557] avfilter/vf_framerate: do not calculate scene change score multiple times for the same frame This speeds up the filter, and also fixes scene change detection score which is reduced based on the difference of the current MAFD to the preivous MAFD. Obviously if we compare two frames twice, the difference will be 0... Signed-off-by: Marton Balint --- libavfilter/vf_framerate.c | 45 +++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index dd106f8e5b791..a6cb5bd212f3d 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -71,6 +71,7 @@ typedef struct FrameRateContext { AVFrame *srce[N_SRCE]; ///< buffered source frames int64_t srce_pts_dest[N_SRCE]; ///< pts for source frames scaled to output timebase + double srce_score[N_SRCE]; ///< scene change score compared to the next srce frame int64_t pts; ///< pts of frame we are working on int max; @@ -113,9 +114,11 @@ static void next_source(AVFilterContext *ctx) for (i = s->last; i > s->frst; i--) { ff_dlog(ctx, "next_source() copy %d to %d\n", i - 1, i); s->srce[i] = s->srce[i - 1]; + s->srce_score[i] = s->srce_score[i - 1]; } ff_dlog(ctx, "next_source() make %d null\n", s->frst); s->srce[s->frst] = NULL; + s->srce_score[s->frst] = -1.0; } static av_always_inline int64_t sad_8x8_16(const uint16_t *src1, ptrdiff_t stride1, @@ -171,8 +174,7 @@ static double get_scene_score(AVFilterContext *ctx, AVFrame *crnt, AVFrame *next ff_dlog(ctx, "get_scene_score()\n"); - if (crnt && - crnt->height == next->height && + if (crnt->height == next->height && crnt->width == next->width) { int64_t sad; double mafd, diff; @@ -304,21 +306,26 @@ static int filter_slice16(AVFilterContext *ctx, void *arg, int job, int nb_jobs) } static int blend_frames(AVFilterContext *ctx, float interpolate, - AVFrame *copy_src1, AVFrame *copy_src2) + int src1, int src2) { FrameRateContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; double interpolate_scene_score = 0; - if ((s->flags & FRAMERATE_FLAG_SCD) && copy_src2) { - interpolate_scene_score = get_scene_score(ctx, copy_src1, copy_src2); + if ((s->flags & FRAMERATE_FLAG_SCD) && s->srce[src1] && s->srce[src2]) { + int i1 = src1 < src2 ? src1 : src2; + int i2 = src1 < src2 ? src2 : src1; + if (i2 == i1 + 1 && s->srce_score[i1] >= 0.0) + interpolate_scene_score = s->srce_score[i1]; + else + interpolate_scene_score = s->srce_score[i1] = get_scene_score(ctx, s->srce[i1], s->srce[i2]); ff_dlog(ctx, "blend_frames() interpolate scene score:%f\n", interpolate_scene_score); } // decide if the shot-change detection allows us to blend two frames - if (interpolate_scene_score < s->scene_score && copy_src2) { + if (interpolate_scene_score < s->scene_score && s->srce[src2]) { ThreadData td; - td.copy_src1 = copy_src1; - td.copy_src2 = copy_src2; + td.copy_src1 = s->srce[src1]; + td.copy_src2 = s->srce[src2]; td.src2_factor = fabsf(interpolate) * (1 << (s->bitdepth - 8)); td.src1_factor = s->max - td.src2_factor; @@ -340,8 +347,8 @@ static int process_work_frame(AVFilterContext *ctx, int stop) { FrameRateContext *s = ctx->priv; int64_t work_next_pts; - AVFrame *copy_src1; float interpolate; + int src1, src2; ff_dlog(ctx, "process_work_frame()\n"); @@ -385,28 +392,26 @@ static int process_work_frame(AVFilterContext *ctx, int stop) // calculate interpolation interpolate = ((s->pts - s->srce_pts_dest[s->crnt]) * 256.0 / s->average_srce_pts_dest_delta); ff_dlog(ctx, "process_work_frame() interpolate:%f/256\n", interpolate); - copy_src1 = s->srce[s->crnt]; + src1 = s->crnt; if (interpolate > s->interp_end) { ff_dlog(ctx, "process_work_frame() source is:NEXT\n"); - copy_src1 = s->srce[s->next]; + src1 = s->next; } if (s->srce[s->prev] && interpolate < -s->interp_end) { ff_dlog(ctx, "process_work_frame() source is:PREV\n"); - copy_src1 = s->srce[s->prev]; + src1 = s->prev; } // decide whether to blend two frames if ((interpolate >= s->interp_start && interpolate <= s->interp_end) || (interpolate <= -s->interp_start && interpolate >= -s->interp_end)) { - AVFrame *copy_src2; - if (interpolate > 0) { ff_dlog(ctx, "process_work_frame() interpolate source is:NEXT\n"); - copy_src2 = s->srce[s->next]; + src2 = s->next; } else { ff_dlog(ctx, "process_work_frame() interpolate source is:PREV\n"); - copy_src2 = s->srce[s->prev]; + src2 = s->prev; } - if (blend_frames(ctx, interpolate, copy_src1, copy_src2)) + if (blend_frames(ctx, interpolate, src1, src2)) goto copy_done; else ff_dlog(ctx, "process_work_frame() CUT - DON'T INTERPOLATE\n"); @@ -414,7 +419,7 @@ static int process_work_frame(AVFilterContext *ctx, int stop) ff_dlog(ctx, "process_work_frame() COPY to the work frame\n"); // copy the frame we decided is our base source - s->work = av_frame_clone(copy_src1); + s->work = av_frame_clone(s->srce[src1]); if (!s->work) return AVERROR(ENOMEM); @@ -504,6 +509,7 @@ static void set_work_frame_pts(AVFilterContext *ctx) static av_cold int init(AVFilterContext *ctx) { FrameRateContext *s = ctx->priv; + int i; s->dest_frame_num = 0; @@ -513,6 +519,9 @@ static av_cold int init(AVFilterContext *ctx) s->next = s->crnt - 1; s->prev = s->crnt + 1; + for (i = 0; i < N_SRCE; i++) + s->srce_score[i] = -1.0; + return 0; } From e403e4bdbea08af0c4a068eb560b577d1b64cf7a Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 10 Dec 2017 19:01:03 +0100 Subject: [PATCH 1424/2557] avfilter/vf_framerate: fix scene score with negative linesize Also, do not overread input if linesize > width, or linesize is not divisible by 8, and use the proper rounded width/height for MAFD calculation. Signed-off-by: Marton Balint --- libavfilter/vf_framerate.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index a6cb5bd212f3d..1336ea04695af 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -136,12 +136,12 @@ static av_always_inline int64_t sad_8x8_16(const uint16_t *src1, ptrdiff_t strid return sum; } -static int64_t scene_sad16(FrameRateContext *s, const uint16_t *p1, int p1_linesize, const uint16_t* p2, int p2_linesize, int height) +static int64_t scene_sad16(FrameRateContext *s, const uint16_t *p1, int p1_linesize, const uint16_t* p2, int p2_linesize, const int width, const int height) { int64_t sad; int x, y; - for (sad = y = 0; y < height; y += 8) { - for (x = 0; x < p1_linesize; x += 8) { + for (sad = y = 0; y < height - 7; y += 8) { + for (x = 0; x < width - 7; x += 8) { sad += sad_8x8_16(p1 + y * p1_linesize + x, p1_linesize, p2 + y * p2_linesize + x, @@ -151,12 +151,12 @@ static int64_t scene_sad16(FrameRateContext *s, const uint16_t *p1, int p1_lines return sad; } -static int64_t scene_sad8(FrameRateContext *s, uint8_t *p1, int p1_linesize, uint8_t* p2, int p2_linesize, int height) +static int64_t scene_sad8(FrameRateContext *s, uint8_t *p1, int p1_linesize, uint8_t* p2, int p2_linesize, const int width, const int height) { int64_t sad; int x, y; - for (sad = y = 0; y < height; y += 8) { - for (x = 0; x < p1_linesize; x += 8) { + for (sad = y = 0; y < height - 7; y += 8) { + for (x = 0; x < width - 7; x += 8) { sad += s->sad(p1 + y * p1_linesize + x, p1_linesize, p2 + y * p2_linesize + x, @@ -181,11 +181,11 @@ static double get_scene_score(AVFilterContext *ctx, AVFrame *crnt, AVFrame *next ff_dlog(ctx, "get_scene_score() process\n"); if (s->bitdepth == 8) - sad = scene_sad8(s, crnt->data[0], crnt->linesize[0], next->data[0], next->linesize[0], crnt->height); + sad = scene_sad8(s, crnt->data[0], crnt->linesize[0], next->data[0], next->linesize[0], crnt->width, crnt->height); else - sad = scene_sad16(s, (const uint16_t*)crnt->data[0], crnt->linesize[0] >> 1, (const uint16_t*)next->data[0], next->linesize[0] >> 1, crnt->height); + sad = scene_sad16(s, (const uint16_t*)crnt->data[0], crnt->linesize[0] / 2, (const uint16_t*)next->data[0], next->linesize[0] / 2, crnt->width, crnt->height); - mafd = (double)sad * 100.0 / (crnt->height * crnt->width) / (1 << s->bitdepth); + mafd = (double)sad * 100.0 / FFMAX(1, (crnt->height & ~7) * (crnt->width & ~7)) / (1 << s->bitdepth); diff = fabs(mafd - s->prev_mafd); ret = av_clipf(FFMIN(mafd, diff), 0, 100.0); s->prev_mafd = mafd; From 93a0e478768e9bafc44b8956b94c27fe8e3486f3 Mon Sep 17 00:00:00 2001 From: Karthick J Date: Fri, 22 Dec 2017 07:43:54 +0800 Subject: [PATCH 1425/2557] avformat/hlsenc: set EXT-X-TARGETDURATION use lrint(EXTINF) --- libavformat/hlsenc.c | 2 +- libavformat/hlsplaylist.h | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 29fc1d4122b63..0095ca43390e5 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1235,7 +1235,7 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) for (en = vs->segments; en; en = en->next) { if (target_duration <= en->duration) - target_duration = hls_get_int_from_double(en->duration); + target_duration = lrint(en->duration); } vs->discontinuity_set = 0; diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index 48d71b7c776d9..fe19f34368382 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -36,11 +36,6 @@ typedef enum { PLAYLIST_TYPE_NB, } PlaylistType; -static inline int hls_get_int_from_double(double val) -{ - return (int)((val - (int)val) >= 0.001) ? (int)(val + 1) : (int)val; -} - void ff_hls_write_playlist_version(AVIOContext *out, int version); void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, char *filename); From e3b2c8502b33c180e0f053ac2ef32ee782224c2e Mon Sep 17 00:00:00 2001 From: Karthick J Date: Fri, 22 Dec 2017 07:44:51 +0800 Subject: [PATCH 1426/2557] avformat/dashenc: avformat/dashenc: Fix the EXT-X-TARGETDURATION as per the hls specification --- libavformat/dashenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 5687530f2d953..5368a2334c2ac 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -358,7 +358,7 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext Segment *seg = os->segments[i]; double duration = (double) seg->duration / timescale; if (target_duration <= duration) - target_duration = hls_get_int_from_double(duration); + target_duration = lrint(duration); } ff_hls_write_playlist_header(out_hls, 6, -1, target_duration, From d2a2bc9a9f305008e417d72432322fcf48400b33 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 22 Dec 2017 10:51:48 +0100 Subject: [PATCH 1427/2557] avfilter/vf_lut: add support for gray formats Signed-off-by: Paul B Mahol --- libavfilter/vf_lut.c | 6 +++++- tests/ref/fate/filter-pixfmts-lut | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c index 11c039ead771a..26f2945c847f0 100644 --- a/libavfilter/vf_lut.c +++ b/libavfilter/vf_lut.c @@ -135,9 +135,13 @@ static av_cold void uninit(AVFilterContext *ctx) AV_PIX_FMT_GBRP16LE, AV_PIX_FMT_GBRAP12LE, \ AV_PIX_FMT_GBRAP16LE +#define GRAY_FORMATS \ + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9LE, AV_PIX_FMT_GRAY10LE, \ + AV_PIX_FMT_GRAY12LE, AV_PIX_FMT_GRAY16LE + static const enum AVPixelFormat yuv_pix_fmts[] = { YUV_FORMATS, AV_PIX_FMT_NONE }; static const enum AVPixelFormat rgb_pix_fmts[] = { RGB_FORMATS, AV_PIX_FMT_NONE }; -static const enum AVPixelFormat all_pix_fmts[] = { RGB_FORMATS, YUV_FORMATS, AV_PIX_FMT_NONE }; +static const enum AVPixelFormat all_pix_fmts[] = { RGB_FORMATS, YUV_FORMATS, GRAY_FORMATS, AV_PIX_FMT_NONE }; static int query_formats(AVFilterContext *ctx) { diff --git a/tests/ref/fate/filter-pixfmts-lut b/tests/ref/fate/filter-pixfmts-lut index db3fd417b7d69..6cf798ad77f95 100644 --- a/tests/ref/fate/filter-pixfmts-lut +++ b/tests/ref/fate/filter-pixfmts-lut @@ -12,6 +12,11 @@ gbrp12le c5a4b89571f7095eb737ad9fd6b1ee08 gbrp14le bdfdfd6f36c60497d1cdae791f3cc117 gbrp16le df095ef3a20995935cfcaf144afc68b6 gbrp9le a8c4e29f4cb627db81ba053e0853e702 +gray 20b14b5e26cd11300ed1249e04082170 +gray10le 8f4140b55e847cc423002b89666db5ea +gray12le ea89c02f6b3af49ddaf13364ed33d86d +gray16le aa10599924fb2440fa12b76e90f57dcb +gray9le 7d9cc9ad6118674c547a54281d10cf05 rgb24 a356171207723a580e7d277078072005 rgb48le 5c7dd8575836d18c91e09f1915cf9aa9 rgba 7bc854c2698b78af3e9159a19c2d9d21 From 28358e466d4f4bc54f8137e0597057f33100b236 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 12 Dec 2017 15:50:44 -0800 Subject: [PATCH 1428/2557] avformat/http: return EINVAL from ff_http_do_new_request() if re-used with different hostname This will prevent improper use of ff_http_do_new_request() if the user tries to send a request for a different host to a previously connected persistent http/1.1 connection. Signed-off-by: Aman Gupta Signed-off-by: Karthick J --- libavformat/http.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index cf86adc6171bd..a3c36423fc525 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -306,6 +306,22 @@ int ff_http_do_new_request(URLContext *h, const char *uri) HTTPContext *s = h->priv_data; AVDictionary *options = NULL; int ret; + char hostname1[1024], hostname2[1024], proto1[10], proto2[10]; + int port1, port2; + + av_url_split(proto1, sizeof(proto1), NULL, 0, + hostname1, sizeof(hostname1), &port1, + NULL, 0, s->location); + av_url_split(proto2, sizeof(proto2), NULL, 0, + hostname2, sizeof(hostname2), &port2, + NULL, 0, uri); + if (port1 != port2 || strncmp(hostname1, hostname2, sizeof(hostname2)) != 0) { + av_log(h, AV_LOG_ERROR, "Cannot reuse HTTP connection for different host: %s:%d != %s:%d\n", + hostname1, port1, + hostname2, port2 + ); + return AVERROR(EINVAL); + } ret = http_shutdown(h, h->flags); if (ret < 0) From 9395e44b8d20d1d4c72dd5b42d28721ca191d957 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 12 Dec 2017 16:02:09 -0800 Subject: [PATCH 1429/2557] avformat/http: add "Opening" info logging to ff_http_do_new_request This mimics logging that was added in 53e0d5d7247 for security purposes. Signed-off-by: Aman Gupta Signed-off-by: Michael Niedermayer --- libavformat/http.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/http.c b/libavformat/http.c index a3c36423fc525..ffdf11cf7efd3 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -336,6 +336,7 @@ int ff_http_do_new_request(URLContext *h, const char *uri) if (!s->location) return AVERROR(ENOMEM); + av_log(s, AV_LOG_INFO, "Opening \'%s\' for %s\n", uri, h->flags & AVIO_FLAG_WRITE ? "writing" : "reading"); ret = http_open_cnx(h, &options); av_dict_free(&options); return ret; From b7d6c0cd48dac7869b9e6803e2d47d05a4fa373b Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Wed, 4 Oct 2017 14:52:52 -0700 Subject: [PATCH 1430/2557] avformat/hls: add http_persistent option This teaches the HLS demuxer to use the HTTP protocols multiple_requests=1 option, to take advantage of "Connection: Keep-Alive" when downloading playlists and segments from the HLS server. With the new option, you can avoid TCP connection and TLS negotiation overhead, which is particularly beneficial when streaming via a high-latency internet connection. Similar to the http_persistent option recently implemented in hlsenc.c Signed-off-by: Aman Gupta Signed-off-by: Anssi Hannula --- doc/demuxers.texi | 4 +++ libavformat/hls.c | 72 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 73dc0feec194a..f76829adfe863 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -316,6 +316,10 @@ segment index to start live streams at (negative values are from the end). @item max_reload Maximum number of times a insufficient list is attempted to be reloaded. Default value is 1000. + +@item http_persistent +Use persistent HTTP connections. Applicable only for HTTP streams. +Enabled by default. @end table @section image2 diff --git a/libavformat/hls.c b/libavformat/hls.c index ab6ff187a684e..1de04620d946e 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -26,6 +26,7 @@ * http://tools.ietf.org/html/draft-pantos-http-live-streaming */ +#include "libavformat/http.h" #include "libavutil/avstring.h" #include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" @@ -94,6 +95,7 @@ struct playlist { AVIOContext pb; uint8_t* read_buffer; AVIOContext *input; + int input_read_done; AVFormatContext *parent; int index; AVFormatContext *ctx; @@ -206,6 +208,8 @@ typedef struct HLSContext { int strict_std_compliance; char *allowed_extensions; int max_reload; + int http_persistent; + AVIOContext *playlist_pb; } HLSContext; static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) @@ -256,6 +260,7 @@ static void free_playlist_list(HLSContext *c) av_freep(&pls->pb.buffer); if (pls->input) ff_format_io_close(c->ctx, &pls->input); + pls->input_read_done = 0; if (pls->ctx) { pls->ctx->pb = NULL; avformat_close_input(&pls->ctx); @@ -597,6 +602,20 @@ static void update_options(char **dest, const char *name, void *src) av_freep(dest); } +static int open_url_keepalive(AVFormatContext *s, AVIOContext **pb, + const char *url) +{ + int ret; + URLContext *uc = ffio_geturlcontext(*pb); + av_assert0(uc); + (*pb)->eof_reached = 0; + ret = ff_http_do_new_request(uc, url); + if (ret < 0) { + ff_format_io_close(s, pb); + } + return ret; +} + static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, AVDictionary *opts, AVDictionary *opts2, int *is_http) { @@ -640,7 +659,19 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) return AVERROR_INVALIDDATA; - ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); + if (c->http_persistent && *pb && av_strstart(proto_name, "http", NULL)) { + ret = open_url_keepalive(c->ctx, pb, url); + if (ret == AVERROR_EXIT) { + return ret; + } else if (ret < 0) { + av_log(s, AV_LOG_WARNING, + "keepalive request failed for '%s', retrying with new connection: %s\n", + url, av_err2str(ret)); + ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); + } + } else { + ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); + } if (ret >= 0) { // update cookies on http response with setcookies. char *new_cookies = NULL; @@ -683,10 +714,22 @@ static int parse_playlist(HLSContext *c, const char *url, char tmp_str[MAX_URL_SIZE]; struct segment *cur_init_section = NULL; + if (!in && c->http_persistent && c->playlist_pb) { + in = c->playlist_pb; + ret = open_url_keepalive(c->ctx, &c->playlist_pb, url); + if (ret == AVERROR_EXIT) { + return ret; + } else if (ret < 0) { + av_log(c->ctx, AV_LOG_WARNING, + "keepalive request failed for '%s', retrying with new connection: %s\n", + url, av_err2str(ret)); + in = NULL; + } + } + if (!in) { #if 1 AVDictionary *opts = NULL; - close_in = 1; /* Some HLS servers don't like being sent the range header */ av_dict_set(&opts, "seekable", "0", 0); @@ -696,10 +739,18 @@ static int parse_playlist(HLSContext *c, const char *url, av_dict_set(&opts, "headers", c->headers, 0); av_dict_set(&opts, "http_proxy", c->http_proxy, 0); + if (c->http_persistent) + av_dict_set(&opts, "multiple_requests", "1", 0); + ret = c->ctx->io_open(c->ctx, &in, url, AVIO_FLAG_READ, &opts); av_dict_free(&opts); if (ret < 0) return ret; + + if (c->http_persistent) + c->playlist_pb = in; + else + close_in = 1; #else ret = open_in(c, &in, url); if (ret < 0) @@ -1111,6 +1162,9 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg) av_dict_set(&opts, "http_proxy", c->http_proxy, 0); av_dict_set(&opts, "seekable", "0", 0); + if (c->http_persistent) + av_dict_set(&opts, "multiple_requests", "1", 0); + if (seg->size >= 0) { /* try to restrict the HTTP request to the part we want * (if this is in fact a HTTP request) */ @@ -1316,7 +1370,7 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) if (!v->needed) return AVERROR_EOF; - if (!v->input) { + if (!v->input || (c->http_persistent && v->input_read_done)) { int64_t reload_interval; struct segment *seg; @@ -1368,6 +1422,7 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) goto reload; } + v->input_read_done = 0; seg = current_segment(v); /* load/update Media Initialization Section, if any */ @@ -1405,7 +1460,11 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) return ret; } - ff_format_io_close(v->parent, &v->input); + if (c->http_persistent) { + v->input_read_done = 1; + } else { + ff_format_io_close(v->parent, &v->input); + } v->cur_seq_no++; c->cur_seq_no = v->cur_seq_no; @@ -1666,6 +1725,7 @@ static int hls_close(AVFormatContext *s) free_rendition_list(c); av_dict_free(&c->avio_opts); + ff_format_io_close(c->ctx, &c->playlist_pb); return 0; } @@ -1903,6 +1963,7 @@ static int recheck_discard_flags(AVFormatContext *s, int first) } else if (first && !cur_needed && pls->needed) { if (pls->input) ff_format_io_close(pls->parent, &pls->input); + pls->input_read_done = 0; pls->needed = 0; changed = 1; av_log(s, AV_LOG_INFO, "No longer receiving playlist %d\n", i); @@ -2137,6 +2198,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, struct playlist *pls = c->playlists[i]; if (pls->input) ff_format_io_close(pls->parent, &pls->input); + pls->input_read_done = 0; av_packet_unref(&pls->pkt); reset_packet(&pls->pkt); pls->pb.eof_reached = 0; @@ -2191,6 +2253,8 @@ static const AVOption hls_options[] = { INT_MIN, INT_MAX, FLAGS}, {"max_reload", "Maximum number of times a insufficient list is attempted to be reloaded", OFFSET(max_reload), AV_OPT_TYPE_INT, {.i64 = 1000}, 0, INT_MAX, FLAGS}, + {"http_persistent", "Use persistent HTTP connections", + OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, {NULL} }; From 03765aa6fa9c519571586db87d4dade1102c4c86 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 12 Dec 2017 15:21:29 -0800 Subject: [PATCH 1431/2557] avformat/hls: allow open_input to be re-used Signed-off-by: Aman Gupta Signed-off-by: Anssi Hannula --- libavformat/hls.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 1de04620d946e..e1846ad773c16 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1149,7 +1149,7 @@ static void intercept_id3(struct playlist *pls, uint8_t *buf, pls->is_id3_timestamped = (pls->id3_mpegts_timestamp != AV_NOPTS_VALUE); } -static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg) +static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg, AVIOContext **in) { AVDictionary *opts = NULL; int ret; @@ -1176,7 +1176,7 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg) seg->url, seg->url_offset, pls->index); if (seg->key_type == KEY_NONE) { - ret = open_url(pls->parent, &pls->input, seg->url, c->avio_opts, opts, &is_http); + ret = open_url(pls->parent, in, seg->url, c->avio_opts, opts, &is_http); } else if (seg->key_type == KEY_AES_128) { AVDictionary *opts2 = NULL; char iv[33], key[33], url[MAX_URL_SIZE]; @@ -1207,7 +1207,7 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg) av_dict_set(&opts2, "key", key, 0); av_dict_set(&opts2, "iv", iv, 0); - ret = open_url(pls->parent, &pls->input, url, opts2, opts, &is_http); + ret = open_url(pls->parent, in, url, opts2, opts, &is_http); av_dict_free(&opts2); @@ -1234,11 +1234,11 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg) * noticed without the call, though. */ if (ret == 0 && !is_http && seg->key_type == KEY_NONE && seg->url_offset) { - int64_t seekret = avio_seek(pls->input, seg->url_offset, SEEK_SET); + int64_t seekret = avio_seek(*in, seg->url_offset, SEEK_SET); if (seekret < 0) { av_log(pls->parent, AV_LOG_ERROR, "Unable to seek to offset %"PRId64" of HLS segment '%s'\n", seg->url_offset, seg->url); ret = seekret; - ff_format_io_close(pls->parent, &pls->input); + ff_format_io_close(pls->parent, in); } } @@ -1264,7 +1264,7 @@ static int update_init_section(struct playlist *pls, struct segment *seg) if (!seg->init_section) return 0; - ret = open_input(c, pls, seg->init_section); + ret = open_input(c, pls, seg->init_section, &pls->input); if (ret < 0) { av_log(pls->parent, AV_LOG_WARNING, "Failed to open an initialization section in playlist %d\n", @@ -1430,7 +1430,7 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) if (ret) return ret; - ret = open_input(c, v, seg); + ret = open_input(c, v, seg, &v->input); if (ret < 0) { if (ff_check_interrupt(c->interrupt_callback)) return AVERROR_EXIT; From 1f0eaa02aa7141f371e095540ac285698a0bdf46 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 12 Dec 2017 15:25:46 -0800 Subject: [PATCH 1432/2557] avformat/hls: add http_multiple option This improves network throughput of the hls demuxer by avoiding the latency introduced by downloading segments one at a time. The problem is particularly noticable over high-latency network connections: for instance, if RTT is 250ms, there will a 250ms idle period between when one segment response is read and the next one starts. The obvious solution to this is to use HTTP pipelining, where a second request can be sent (on the persistent http/1.1 connection) before the first response is fully read. Unfortunately the way the http protocol is implemented in avformat makes implementing pipleining very complex. Instead, this commit simulates pipelining using two separate persistent http connections. This has the advantage of working independently of the http_persistent option, and can be used with http/1.0 servers as well. The pair of connections is swapped every time a new segment starts downloading, and a request for the next segment is sent on the secondary connection right away. This means the second response will be ready and waiting by the time the current response is fully read. Signed-off-by: Aman Gupta Signed-off-by: Anssi Hannula --- doc/demuxers.texi | 4 ++++ libavformat/hls.c | 49 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index f76829adfe863..81ab399cdc215 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -320,6 +320,10 @@ Default value is 1000. @item http_persistent Use persistent HTTP connections. Applicable only for HTTP streams. Enabled by default. + +@item http_multiple +Use multiple HTTP connections for downloading HTTP segments. +Enabled by default. @end table @section image2 diff --git a/libavformat/hls.c b/libavformat/hls.c index e1846ad773c16..26bf61c805273 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -96,6 +96,8 @@ struct playlist { uint8_t* read_buffer; AVIOContext *input; int input_read_done; + AVIOContext *input_next; + int input_next_requested; AVFormatContext *parent; int index; AVFormatContext *ctx; @@ -209,6 +211,7 @@ typedef struct HLSContext { char *allowed_extensions; int max_reload; int http_persistent; + int http_multiple; AVIOContext *playlist_pb; } HLSContext; @@ -261,6 +264,9 @@ static void free_playlist_list(HLSContext *c) if (pls->input) ff_format_io_close(c->ctx, &pls->input); pls->input_read_done = 0; + if (pls->input_next) + ff_format_io_close(c->ctx, &pls->input_next); + pls->input_next_requested = 0; if (pls->ctx) { pls->ctx->pb = NULL; avformat_close_input(&pls->ctx); @@ -924,6 +930,14 @@ static struct segment *current_segment(struct playlist *pls) return pls->segments[pls->cur_seq_no - pls->start_seq_no]; } +static struct segment *next_segment(struct playlist *pls) +{ + int n = pls->cur_seq_no - pls->start_seq_no + 1; + if (n >= pls->n_segments) + return NULL; + return pls->segments[n]; +} + enum ReadFromURLMode { READ_NORMAL, READ_COMPLETE, @@ -1365,6 +1379,7 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) int ret; int just_opened = 0; int reload_count = 0; + struct segment *seg; restart: if (!v->needed) @@ -1372,7 +1387,6 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) if (!v->input || (c->http_persistent && v->input_read_done)) { int64_t reload_interval; - struct segment *seg; /* Check that the playlist is still needed before opening a new * segment. */ @@ -1430,11 +1444,18 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) if (ret) return ret; - ret = open_input(c, v, seg, &v->input); + if (c->http_multiple && av_strstart(seg->url, "http", NULL) && v->input_next_requested) { + FFSWAP(AVIOContext *, v->input, v->input_next); + v->input_next_requested = 0; + ret = 0; + } else { + ret = open_input(c, v, seg, &v->input); + } if (ret < 0) { if (ff_check_interrupt(c->interrupt_callback)) return AVERROR_EXIT; - av_log(v->parent, AV_LOG_WARNING, "Failed to open segment of playlist %d\n", + av_log(v->parent, AV_LOG_WARNING, "Failed to open segment %d of playlist %d\n", + v->cur_seq_no, v->index); v->cur_seq_no += 1; goto reload; @@ -1442,6 +1463,20 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) just_opened = 1; } + seg = next_segment(v); + if (c->http_multiple && !v->input_next_requested && seg) { + ret = open_input(c, v, seg, &v->input_next); + if (ret < 0) { + if (ff_check_interrupt(c->interrupt_callback)) + return AVERROR_EXIT; + av_log(v->parent, AV_LOG_WARNING, "Failed to open segment %d of playlist %d\n", + v->cur_seq_no + 1, + v->index); + } else { + v->input_next_requested = 1; + } + } + if (v->init_sec_buf_read_offset < v->init_sec_data_len) { /* Push init section out first before first actual segment */ int copy_size = FFMIN(v->init_sec_data_len - v->init_sec_buf_read_offset, buf_size); @@ -1964,6 +1999,9 @@ static int recheck_discard_flags(AVFormatContext *s, int first) if (pls->input) ff_format_io_close(pls->parent, &pls->input); pls->input_read_done = 0; + if (pls->input_next) + ff_format_io_close(pls->parent, &pls->input_next); + pls->input_next_requested = 0; pls->needed = 0; changed = 1; av_log(s, AV_LOG_INFO, "No longer receiving playlist %d\n", i); @@ -2199,6 +2237,9 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, if (pls->input) ff_format_io_close(pls->parent, &pls->input); pls->input_read_done = 0; + if (pls->input_next) + ff_format_io_close(pls->parent, &pls->input_next); + pls->input_next_requested = 0; av_packet_unref(&pls->pkt); reset_packet(&pls->pkt); pls->pb.eof_reached = 0; @@ -2255,6 +2296,8 @@ static const AVOption hls_options[] = { OFFSET(max_reload), AV_OPT_TYPE_INT, {.i64 = 1000}, 0, INT_MAX, FLAGS}, {"http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, + {"http_multiple", "Use multiple HTTP connections for fetching segments", + OFFSET(http_multiple), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS}, {NULL} }; From 54d0ef1738ff30c05e2edb5b019dbd44b694ebe6 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 22 Dec 2017 16:29:41 -0800 Subject: [PATCH 1433/2557] avformat/http: return EOF from ff_http_do_new_request if previous response said Connection:close This fixes a deadlock when using the hls demuxer's new http_persistent feature to stream a youtube live stream over HTTPS. The youtube servers are http/1.1 compliant, but return a "Connecton: close". Before this commit, the demuxer would attempt to send a new request on the partially shutdown connection and cause a deadlock in the tls protocol. Signed-off-by: Aman Gupta --- libavformat/http.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index ffdf11cf7efd3..7a68378acb25f 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -327,6 +327,9 @@ int ff_http_do_new_request(URLContext *h, const char *uri) if (ret < 0) return ret; + if (s->willclose) + return AVERROR_EOF; + s->end_chunked_post = 0; s->chunkend = 0; s->off = 0; From 5f4a32a6e343d2683d90843506ecfc98cc7c8ed4 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 22 Dec 2017 16:30:42 -0800 Subject: [PATCH 1434/2557] avformat/hls: hide misleading warning when http reconnect is required AVERROR_EOF is an internal error which means the http socket is no longer valid for new requests. It informs the caller that a new connection must be established, and as such does not need to be surfaced to the user as a warning. Signed-off-by: Aman Gupta --- libavformat/hls.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 26bf61c805273..f718f2e6c1c61 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -670,9 +670,10 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, if (ret == AVERROR_EXIT) { return ret; } else if (ret < 0) { - av_log(s, AV_LOG_WARNING, - "keepalive request failed for '%s', retrying with new connection: %s\n", - url, av_err2str(ret)); + if (ret != AVERROR_EOF) + av_log(s, AV_LOG_WARNING, + "keepalive request failed for '%s', retrying with new connection: %s\n", + url, av_err2str(ret)); ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); } } else { @@ -726,9 +727,10 @@ static int parse_playlist(HLSContext *c, const char *url, if (ret == AVERROR_EXIT) { return ret; } else if (ret < 0) { - av_log(c->ctx, AV_LOG_WARNING, - "keepalive request failed for '%s', retrying with new connection: %s\n", - url, av_err2str(ret)); + if (ret != AVERROR_EOF) + av_log(c->ctx, AV_LOG_WARNING, + "keepalive request failed for '%s', retrying with new connection: %s\n", + url, av_err2str(ret)); in = NULL; } } From 4c78bbd3136a43347a112dd45ac60685c61bf425 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 22 Dec 2017 15:17:15 -0800 Subject: [PATCH 1435/2557] avformat/internal: log underlying error with ff_rename failure Signed-off-by: Aman Gupta Signed-off-by: wm4 --- libavformat/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/internal.h b/libavformat/internal.h index 36a57214cede9..de4b7846343f1 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -542,7 +542,7 @@ static inline int ff_rename(const char *oldpath, const char *newpath, void *logc if (rename(oldpath, newpath) == -1) { ret = AVERROR(errno); if (logctx) - av_log(logctx, AV_LOG_ERROR, "failed to rename file %s to %s\n", oldpath, newpath); + av_log(logctx, AV_LOG_ERROR, "failed to rename file %s to %s: %s\n", oldpath, newpath, av_err2str(ret)); } return ret; } From d02289c386ecf1c07f2441674c550008cb869d50 Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Sat, 23 Dec 2017 13:42:00 +0800 Subject: [PATCH 1436/2557] avformat/hlsenc:addition of #EXT-X-MEDIA tag and AUDIO attribute Signed-off-by: Steven Liu --- doc/muxers.texi | 12 ++++++++ libavformat/dashenc.c | 3 +- libavformat/hlsenc.c | 64 +++++++++++++++++++++++++++++++++++++-- libavformat/hlsplaylist.c | 4 ++- libavformat/hlsplaylist.h | 2 +- 5 files changed, 79 insertions(+), 6 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 3d0c7bfbd3622..93db54926589c 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -834,6 +834,18 @@ be a video only stream with video bitrate 1000k, the second variant stream will be an audio only stream with bitrate 64k and the third variant stream will be a video only stream with bitrate 256k. Here, three media playlist with file names out_1.m3u8, out_2.m3u8 and out_3.m3u8 will be created. +@example +ffmpeg -re -i in.ts -b:a:0 32k -b:a:1 64k -b:v:0 1000k -b:v:1 3000k \ + -map 0:a -map 0:a -map 0:v -map 0:v -f hls \ + -var_stream_map "a:0,agroup:aud_low a:1,agroup:aud_high v:0,agroup:aud_low v:1,agroup:aud_high" \ + -master_pl_name master.m3u8 \ + http://example.com/live/out.m3u8 +@end example +This example creates two audio only and two video only variant streams. In +addition to the #EXT-X-STREAM-INF tag for each variant stream in the master +playlist, #EXT-X-MEDIA tag is also added for the two audio only variant streams +and they are mapped to the two video only variant streams with audio group names +'aud_low' and 'aud_high'. By default, a single hls variant containing all the encoded streams is created. diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 5368a2334c2ac..478a384f555de 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -759,7 +759,8 @@ static int write_manifest(AVFormatContext *s, int final) char playlist_file[64]; AVStream *st = s->streams[i]; get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i); - ff_hls_write_stream_info(st, out, st->codecpar->bit_rate, playlist_file); + ff_hls_write_stream_info(st, out, st->codecpar->bit_rate, + playlist_file, NULL); } avio_close(out); if (use_rename) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 0095ca43390e5..bbc2742dc7dcb 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -144,6 +144,7 @@ typedef struct VariantStream { AVStream **streams; unsigned int nb_streams; int m3u8_created; /* status of media play-list creation */ + char *agroup; /* audio group name */ char *baseurl; } VariantStream; @@ -1110,7 +1111,7 @@ static int create_master_playlist(AVFormatContext *s, VariantStream * const input_vs) { HLSContext *hls = s->priv_data; - VariantStream *vs; + VariantStream *vs, *temp_vs; AVStream *vid_st, *aud_st; AVDictionary *options = NULL; unsigned int i, j; @@ -1142,6 +1143,34 @@ static int create_master_playlist(AVFormatContext *s, ff_hls_write_playlist_version(hls->m3u8_out, hls->version); + /* For audio only variant streams add #EXT-X-MEDIA tag with attributes*/ + for (i = 0; i < hls->nb_varstreams; i++) { + vs = &(hls->var_streams[i]); + + if (vs->has_video || vs->has_subtitle || !vs->agroup) + continue; + + m3u8_name_size = strlen(vs->m3u8_name) + 1; + m3u8_rel_name = av_malloc(m3u8_name_size); + if (!m3u8_rel_name) { + ret = AVERROR(ENOMEM); + goto fail; + } + av_strlcpy(m3u8_rel_name, vs->m3u8_name, m3u8_name_size); + ret = get_relative_url(hls->master_m3u8_url, vs->m3u8_name, + m3u8_rel_name, m3u8_name_size); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n"); + goto fail; + } + + avio_printf(hls->m3u8_out, "#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"group_%s\"", + vs->agroup); + avio_printf(hls->m3u8_out, ",NAME=\"audio_0\",DEFAULT=YES,URI=\"%s\"\n", + m3u8_rel_name); + av_freep(&m3u8_rel_name); + } + /* For variant streams with video add #EXT-X-STREAM-INF tag with attributes*/ for (i = 0; i < hls->nb_varstreams; i++) { vs = &(hls->var_streams[i]); @@ -1174,6 +1203,25 @@ static int create_master_playlist(AVFormatContext *s, continue; } + /** + * Traverse through the list of audio only rendition streams and find + * the rendition which has highest bitrate in the same audio group + */ + if (vs->agroup) { + for (j = 0; j < hls->nb_varstreams; j++) { + temp_vs = &(hls->var_streams[j]); + if (!temp_vs->has_video && !temp_vs->has_subtitle && + temp_vs->agroup && + !av_strcasecmp(temp_vs->agroup, vs->agroup)) { + if (!aud_st) + aud_st = temp_vs->streams[0]; + if (temp_vs->streams[0]->codecpar->bit_rate > + aud_st->codecpar->bit_rate) + aud_st = temp_vs->streams[0]; + } + } + } + bandwidth = 0; if (vid_st) bandwidth += vid_st->codecpar->bit_rate; @@ -1181,7 +1229,8 @@ static int create_master_playlist(AVFormatContext *s, bandwidth += aud_st->codecpar->bit_rate; bandwidth += bandwidth / 10; - ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name); + ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name, + aud_st ? vs->agroup : NULL); av_freep(&m3u8_rel_name); } @@ -1532,6 +1581,7 @@ static int parse_variant_stream_mapstring(AVFormatContext *s) /** * Expected format for var_stream_map string is as below: * "a:0,v:0 a:1,v:1" + * "a:0,agroup:a0 a:1,agroup:a1 v:0,agroup:a0 v:1,agroup:a1" * This string specifies how to group the audio, video and subtitle streams * into different variant streams. The variant stream groups are separated * by space. @@ -1540,6 +1590,7 @@ static int parse_variant_stream_mapstring(AVFormatContext *s) * respectively. Allowed values are 0 to 9 digits (limited just based on * practical usage) * + * agroup: is key to specify audio group. A string can be given as value. */ p = av_strdup(hls->var_stream_map); q = p; @@ -1578,7 +1629,12 @@ static int parse_variant_stream_mapstring(AVFormatContext *s) while (keyval = av_strtok(varstr, ",", &saveptr2)) { varstr = NULL; - if (av_strstart(keyval, "v:", &val)) { + if (av_strstart(keyval, "agroup:", &val)) { + vs->agroup = av_strdup(val); + if (!vs->agroup) + return AVERROR(ENOMEM); + continue; + } else if (av_strstart(keyval, "v:", &val)) { codec_type = AVMEDIA_TYPE_VIDEO; } else if (av_strstart(keyval, "a:", &val)) { codec_type = AVMEDIA_TYPE_AUDIO; @@ -1969,6 +2025,7 @@ static int hls_write_trailer(struct AVFormatContext *s) av_free(old_filename); av_freep(&vs->m3u8_name); av_freep(&vs->streams); + av_freep(&vs->agroup); av_freep(&vs->baseurl); } @@ -2309,6 +2366,7 @@ static int hls_init(AVFormatContext *s) av_freep(&vs->m3u8_name); av_freep(&vs->vtt_m3u8_name); av_freep(&vs->streams); + av_freep(&vs->agroup); av_freep(&vs->baseurl); if (vs->avf) avformat_free_context(vs->avf); diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c index 3349eb7ee33ee..42f059aec92be 100644 --- a/libavformat/hlsplaylist.c +++ b/libavformat/hlsplaylist.c @@ -36,7 +36,7 @@ void ff_hls_write_playlist_version(AVIOContext *out, int version) { } void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, - int bandwidth, char *filename) { + int bandwidth, char *filename, char *agroup) { if (!out || !filename) return; @@ -50,6 +50,8 @@ void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, if (st && st->codecpar->width > 0 && st->codecpar->height > 0) avio_printf(out, ",RESOLUTION=%dx%d", st->codecpar->width, st->codecpar->height); + if (agroup && strlen(agroup) > 0) + avio_printf(out, ",AUDIO=\"group_%s\"", agroup); avio_printf(out, "\n%s\n\n", filename); } diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index fe19f34368382..ac03550651eaf 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -38,7 +38,7 @@ typedef enum { void ff_hls_write_playlist_version(AVIOContext *out, int version); void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, - int bandwidth, char *filename); + int bandwidth, char *filename, char *agroup); void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, int target_duration, int64_t sequence, uint32_t playlist_type); From 4754d70a23255bb378975258eff296d9bdebb687 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 7 Dec 2017 10:22:32 +0100 Subject: [PATCH 1437/2557] avfilter/video: pick sar from link It should not be needed for each filter that sets sample aspect ratio to set it explicitly also for each and every frame, instead that is automatically done in get_buffer call. Signed-off-by: Paul B Mahol --- libavfilter/video.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libavfilter/video.c b/libavfilter/video.c index 6f9020b9fe0e2..7a8e587798839 100644 --- a/libavfilter/video.c +++ b/libavfilter/video.c @@ -43,6 +43,7 @@ AVFrame *ff_null_get_video_buffer(AVFilterLink *link, int w, int h) AVFrame *ff_default_get_video_buffer(AVFilterLink *link, int w, int h) { + AVFrame *frame = NULL; int pool_width = 0; int pool_height = 0; int pool_align = 0; @@ -86,7 +87,13 @@ AVFrame *ff_default_get_video_buffer(AVFilterLink *link, int w, int h) } } - return ff_frame_pool_get(link->frame_pool); + frame = ff_frame_pool_get(link->frame_pool); + if (!frame) + return NULL; + + frame->sample_aspect_ratio = link->sample_aspect_ratio; + + return frame; } AVFrame *ff_get_video_buffer(AVFilterLink *link, int w, int h) From f6608f47255306c92c5be324c46af3ba0c45cbd8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 10 Dec 2017 21:48:41 +0100 Subject: [PATCH 1438/2557] avfilter/vf_aspect: change outlink sample aspect ratio instead of inlink Signed-off-by: Paul B Mahol --- libavfilter/vf_aspect.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/libavfilter/vf_aspect.c b/libavfilter/vf_aspect.c index 4c93639554765..c042698ef7acc 100644 --- a/libavfilter/vf_aspect.c +++ b/libavfilter/vf_aspect.c @@ -125,9 +125,11 @@ static int get_aspect_ratio(AVFilterLink *inlink, AVRational *aspect_ratio) #if CONFIG_SETDAR_FILTER -static int setdar_config_props(AVFilterLink *inlink) +static int setdar_config_props(AVFilterLink *outlink) { - AspectContext *s = inlink->dst->priv; + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; + AspectContext *s = ctx->priv; AVRational dar; AVRational old_dar; AVRational old_sar = inlink->sample_aspect_ratio; @@ -140,17 +142,17 @@ static int setdar_config_props(AVFilterLink *inlink) av_reduce(&s->sar.num, &s->sar.den, s->dar.num * inlink->h, s->dar.den * inlink->w, INT_MAX); - inlink->sample_aspect_ratio = s->sar; + outlink->sample_aspect_ratio = s->sar; dar = s->dar; } else { - inlink->sample_aspect_ratio = (AVRational){ 1, 1 }; + outlink->sample_aspect_ratio = (AVRational){ 1, 1 }; dar = (AVRational){ inlink->w, inlink->h }; } compute_dar(&old_dar, old_sar, inlink->w, inlink->h); - av_log(inlink->dst, AV_LOG_VERBOSE, "w:%d h:%d dar:%d/%d sar:%d/%d -> dar:%d/%d sar:%d/%d\n", + av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d dar:%d/%d sar:%d/%d -> dar:%d/%d sar:%d/%d\n", inlink->w, inlink->h, old_dar.num, old_dar.den, old_sar.num, old_sar.den, - dar.num, dar.den, inlink->sample_aspect_ratio.num, inlink->sample_aspect_ratio.den); + dar.num, dar.den, outlink->sample_aspect_ratio.num, outlink->sample_aspect_ratio.den); return 0; } @@ -169,7 +171,6 @@ static const AVFilterPad avfilter_vf_setdar_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .config_props = setdar_config_props, .filter_frame = filter_frame, }, { NULL } @@ -179,6 +180,7 @@ static const AVFilterPad avfilter_vf_setdar_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, + .config_props = setdar_config_props, }, { NULL } }; @@ -196,9 +198,11 @@ AVFilter ff_vf_setdar = { #if CONFIG_SETSAR_FILTER -static int setsar_config_props(AVFilterLink *inlink) +static int setsar_config_props(AVFilterLink *outlink) { - AspectContext *s = inlink->dst->priv; + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; + AspectContext *s = ctx->priv; AVRational old_sar = inlink->sample_aspect_ratio; AVRational old_dar, dar; int ret; @@ -206,13 +210,13 @@ static int setsar_config_props(AVFilterLink *inlink) if ((ret = get_aspect_ratio(inlink, &s->sar))) return ret; - inlink->sample_aspect_ratio = s->sar; + outlink->sample_aspect_ratio = s->sar; compute_dar(&old_dar, old_sar, inlink->w, inlink->h); compute_dar(&dar, s->sar, inlink->w, inlink->h); - av_log(inlink->dst, AV_LOG_VERBOSE, "w:%d h:%d sar:%d/%d dar:%d/%d -> sar:%d/%d dar:%d/%d\n", + av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d sar:%d/%d dar:%d/%d -> sar:%d/%d dar:%d/%d\n", inlink->w, inlink->h, old_sar.num, old_sar.den, old_dar.num, old_dar.den, - inlink->sample_aspect_ratio.num, inlink->sample_aspect_ratio.den, dar.num, dar.den); + outlink->sample_aspect_ratio.num, outlink->sample_aspect_ratio.den, dar.num, dar.den); return 0; } @@ -231,7 +235,6 @@ static const AVFilterPad avfilter_vf_setsar_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .config_props = setsar_config_props, .filter_frame = filter_frame, }, { NULL } @@ -241,6 +244,7 @@ static const AVFilterPad avfilter_vf_setsar_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, + .config_props = setsar_config_props, }, { NULL } }; From b943bc343de0aba21a06447cef695b42f5db102d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 23 Dec 2017 11:33:18 +0100 Subject: [PATCH 1439/2557] avfilter/vf_fftfilt: support >8 bit depth formats Signed-off-by: Paul B Mahol --- libavfilter/vf_fftfilt.c | 65 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_fftfilt.c b/libavfilter/vf_fftfilt.c index 7f60ca1f87b7e..af44b1e22ee62 100644 --- a/libavfilter/vf_fftfilt.c +++ b/libavfilter/vf_fftfilt.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015 Arwa Arif + * Copyright (c) 2017 Paul B Mahol * * This file is part of FFmpeg. * @@ -64,6 +65,8 @@ typedef struct FFTFILTContext { AVExpr *weight_expr[MAX_PLANES]; double *weight[MAX_PLANES]; + void (*rdft_horizontal)(struct FFTFILTContext *s, AVFrame *in, int w, int h, int plane); + void (*irdft_horizontal)(struct FFTFILTContext *s, AVFrame *out, int w, int h, int plane); } FFTFILTContext; static const char *const var_names[] = { "X", "Y", "W", "H", "N", NULL }; @@ -111,7 +114,7 @@ static void copy_rev (FFTSample *dest, int w, int w2) } /*Horizontal pass - RDFT*/ -static void rdft_horizontal(FFTFILTContext *s, AVFrame *in, int w, int h, int plane) +static void rdft_horizontal8(FFTFILTContext *s, AVFrame *in, int w, int h, int plane) { int i, j; @@ -126,6 +129,23 @@ static void rdft_horizontal(FFTFILTContext *s, AVFrame *in, int w, int h, int pl av_rdft_calc(s->hrdft[plane], s->rdft_hdata[plane] + i * s->rdft_hlen[plane]); } +static void rdft_horizontal16(FFTFILTContext *s, AVFrame *in, int w, int h, int plane) +{ + const uint16_t *src = (const uint16_t *)in->data[plane]; + int linesize = in->linesize[plane] / 2; + int i, j; + + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) + s->rdft_hdata[plane][i * s->rdft_hlen[plane] + j] = *(src + linesize * i + j); + + copy_rev(s->rdft_hdata[plane] + i * s->rdft_hlen[plane], w, s->rdft_hlen[plane]); + } + + for (i = 0; i < h; i++) + av_rdft_calc(s->hrdft[plane], s->rdft_hdata[plane] + i * s->rdft_hlen[plane]); +} + /*Vertical pass - RDFT*/ static void rdft_vertical(FFTFILTContext *s, int h, int plane) { @@ -156,7 +176,7 @@ static void irdft_vertical(FFTFILTContext *s, int h, int plane) } /*Horizontal pass - IRDFT*/ -static void irdft_horizontal(FFTFILTContext *s, AVFrame *out, int w, int h, int plane) +static void irdft_horizontal8(FFTFILTContext *s, AVFrame *out, int w, int h, int plane) { int i, j; @@ -171,6 +191,24 @@ static void irdft_horizontal(FFTFILTContext *s, AVFrame *out, int w, int h, int s->rdft_vlen[plane]), 0, 255); } +static void irdft_horizontal16(FFTFILTContext *s, AVFrame *out, int w, int h, int plane) +{ + uint16_t *dst = (uint16_t *)out->data[plane]; + int linesize = out->linesize[plane] / 2; + int max = (1 << s->depth) - 1; + int i, j; + + for (i = 0; i < h; i++) + av_rdft_calc(s->ihrdft[plane], s->rdft_hdata[plane] + i * s->rdft_hlen[plane]); + + for (i = 0; i < h; i++) + for (j = 0; j < w; j++) + *(dst + linesize * i + j) = av_clip(s->rdft_hdata[plane][i + *s->rdft_hlen[plane] + j] * 4 / + (s->rdft_hlen[plane] * + s->rdft_vlen[plane]), 0, max); +} + static av_cold int initialize(AVFilterContext *ctx) { FFTFILTContext *s = ctx->priv; @@ -276,6 +314,16 @@ static int config_props(AVFilterLink *inlink) if (s->eval_mode == EVAL_MODE_INIT) do_eval(s, inlink, plane); } + + if (s->depth <= 8) { + s->rdft_horizontal = rdft_horizontal8; + s->irdft_horizontal = irdft_horizontal8; + } else if (s->depth > 8) { + s->rdft_horizontal = rdft_horizontal16; + s->irdft_horizontal = irdft_horizontal16; + } else { + return AVERROR_BUG; + } return 0; } @@ -302,7 +350,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->eval_mode == EVAL_MODE_FRAME) do_eval(s, inlink, plane); - rdft_horizontal(s, in, w, h, plane); + s->rdft_horizontal(s, in, w, h, plane); rdft_vertical(s, h, plane); /*Change user defined parameters*/ @@ -314,7 +362,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->rdft_vdata[plane][0] += s->rdft_hlen[plane] * s->rdft_vlen[plane] * s->dc[plane]; irdft_vertical(s, h, plane); - irdft_horizontal(s, out, w, h, plane); + s->irdft_horizontal(s, out, w, h, plane); } av_frame_free(&in); @@ -344,6 +392,15 @@ static int query_formats(AVFilterContext *ctx) AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV420P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV420P16, + AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV422P10, + AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV422P14, + AV_PIX_FMT_YUV422P16, + AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV444P16, AV_PIX_FMT_NONE }; From b5958ff82eedc8112d28b9d8c5aaee6b3329fa81 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 23 Dec 2017 16:27:39 +0100 Subject: [PATCH 1440/2557] avfilter/vf_convolve: unbreak non-power of 2 width&height filtering Signed-off-by: Paul B Mahol --- libavfilter/vf_convolve.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c index e00a44d63d776..46119a3d1f2f8 100644 --- a/libavfilter/vf_convolve.c +++ b/libavfilter/vf_convolve.c @@ -112,11 +112,13 @@ static int config_input_main(AVFilterLink *inlink) for (i = 0; i < s->nb_planes; i++) { int w = s->planewidth[i]; int h = s->planeheight[i]; - int n = FFMAX(w, h) * 10/9; + int n = FFMAX(w, h); + + n += n / 2; for (fft_bits = 1; 1 << fft_bits < n; fft_bits++); - s->fft_bits[i] = fft_bits; + s->fft_bits[i] = fft_bits + 1; s->fft_len[i] = 1 << s->fft_bits[i]; if (!(s->fft_hdata[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(FFTComplex)))) @@ -173,7 +175,20 @@ static void fft_horizontal(ConvolveContext *s, FFTComplex *fft_hdata, fft_hdata[y * n + x].im = 0; } } + + for (; x < n / 2; x++) { + fft_hdata[y * n + x].re = 0; + fft_hdata[y * n + x].im = 0; + } + for (; x < n; x++) { + fft_hdata[y * n + x].re = fft_hdata[y * n + n - x - 1].re; + fft_hdata[y * n + x].im = 0; + } + } + + for (; y < n / 2; y++) { + for (x = 0; x < n; x++) { fft_hdata[y * n + x].re = 0; fft_hdata[y * n + x].im = 0; } @@ -181,7 +196,7 @@ static void fft_horizontal(ConvolveContext *s, FFTComplex *fft_hdata, for (; y < n; y++) { for (x = 0; x < n; x++) { - fft_hdata[y * n + x].re = 0; + fft_hdata[y * n + x].re = fft_hdata[(n - y - 1) * n + x].re; fft_hdata[y * n + x].im = 0; } } @@ -202,10 +217,7 @@ static void fft_vertical(ConvolveContext *s, FFTComplex *fft_hdata, FFTComplex * fft_vdata[y * n + x].re = fft_hdata[x * n + y].re; fft_vdata[y * n + x].im = fft_hdata[x * n + y].im; } - for (; x < n; x++) { - fft_vdata[y * n + x].re = 0; - fft_vdata[y * n + x].im = 0; - } + av_fft_permute(s->fft[plane], fft_vdata + y * n); av_fft_calc(s->fft[plane], fft_vdata + y * n); } @@ -218,6 +230,7 @@ static void ifft_vertical(ConvolveContext *s, int n, int plane) for (y = 0; y < n; y++) { av_fft_permute(s->ifft[plane], s->fft_vdata[plane] + y * n); av_fft_calc(s->ifft[plane], s->fft_vdata[plane] + y * n); + for (x = 0; x < n; x++) { s->fft_hdata[plane][x * n + y].re = s->fft_vdata[plane][y * n + x].re; s->fft_hdata[plane][x * n + y].im = s->fft_vdata[plane][y * n + x].im; From 9e5e3236f4f2004a505533228cf6a6dd65b0101c Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Sat, 23 Dec 2017 12:34:50 -0800 Subject: [PATCH 1441/2557] avformat/internal: fix compile error with some versions of g++ Fixes #6926 Signed-off-by: Aman Gupta --- libavformat/internal.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavformat/internal.h b/libavformat/internal.h index de4b7846343f1..e76ac12371d78 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -541,8 +541,11 @@ static inline int ff_rename(const char *oldpath, const char *newpath, void *logc int ret = 0; if (rename(oldpath, newpath) == -1) { ret = AVERROR(errno); - if (logctx) - av_log(logctx, AV_LOG_ERROR, "failed to rename file %s to %s: %s\n", oldpath, newpath, av_err2str(ret)); + if (logctx) { + char err[AV_ERROR_MAX_STRING_SIZE] = {0}; + av_make_error_string(err, AV_ERROR_MAX_STRING_SIZE, ret); + av_log(logctx, AV_LOG_ERROR, "failed to rename file %s to %s: %s\n", oldpath, newpath, err); + } } return ret; } From 175122fcd5e6116a11203a938680de0dd4fd5747 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 24 Dec 2017 10:15:26 +0100 Subject: [PATCH 1442/2557] avfilter/vf_convolve: fix convolution of borders Signed-off-by: Paul B Mahol --- libavfilter/vf_convolve.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c index 46119a3d1f2f8..8d71899637cbd 100644 --- a/libavfilter/vf_convolve.c +++ b/libavfilter/vf_convolve.c @@ -121,16 +121,16 @@ static int config_input_main(AVFilterLink *inlink) s->fft_bits[i] = fft_bits + 1; s->fft_len[i] = 1 << s->fft_bits[i]; - if (!(s->fft_hdata[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(FFTComplex)))) + if (!(s->fft_hdata[i] = av_calloc(s->fft_len[i], (s->fft_len[i] + 1) * sizeof(FFTComplex)))) return AVERROR(ENOMEM); - if (!(s->fft_vdata[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(FFTComplex)))) + if (!(s->fft_vdata[i] = av_calloc(s->fft_len[i], (s->fft_len[i] + 1) * sizeof(FFTComplex)))) return AVERROR(ENOMEM); - if (!(s->fft_hdata_impulse[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(FFTComplex)))) + if (!(s->fft_hdata_impulse[i] = av_calloc(s->fft_len[i], (s->fft_len[i] + 1)* sizeof(FFTComplex)))) return AVERROR(ENOMEM); - if (!(s->fft_vdata_impulse[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(FFTComplex)))) + if (!(s->fft_vdata_impulse[i] = av_calloc(s->fft_len[i], (s->fft_len[i] + 1) * sizeof(FFTComplex)))) return AVERROR(ENOMEM); } @@ -321,6 +321,9 @@ static int do_convolve(FFFrameSync *fs) } for (y = 0; y < n; y++) { + + s->fft_vdata[plane][y*n + n].re = s->fft_vdata[plane][y*n + 0].im; + s->fft_vdata[plane][y*n + 0].im = 0; for (x = 0; x < n; x++) { FFTSample re, im, ire, iim; @@ -332,6 +335,8 @@ static int do_convolve(FFFrameSync *fs) s->fft_vdata[plane][y*n + x].re = ire * re - iim * im; s->fft_vdata[plane][y*n + x].im = iim * re + ire * im; } + s->fft_vdata[plane][y*n + n].re = s->fft_vdata[plane][y*n + 0].im * s->fft_vdata_impulse[plane][y*n + 0].im; + s->fft_vdata[plane][y*n + 0].im = s->fft_vdata[plane][y*n + n].re; } ifft_vertical(s, n, plane); From 5533cbfc84ea120f35cc0fd62bc58fcb2cd3fbfc Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 24 Dec 2017 16:09:23 +0100 Subject: [PATCH 1443/2557] avfilter/vf_convolve: fix various issues Signed-off-by: Paul B Mahol --- libavfilter/vf_convolve.c | 137 +++++++++++++++++++++++++------------- 1 file changed, 92 insertions(+), 45 deletions(-) diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c index 8d71899637cbd..6eb954845650c 100644 --- a/libavfilter/vf_convolve.c +++ b/libavfilter/vf_convolve.c @@ -114,23 +114,21 @@ static int config_input_main(AVFilterLink *inlink) int h = s->planeheight[i]; int n = FFMAX(w, h); - n += n / 2; - for (fft_bits = 1; 1 << fft_bits < n; fft_bits++); - s->fft_bits[i] = fft_bits + 1; + s->fft_bits[i] = fft_bits; s->fft_len[i] = 1 << s->fft_bits[i]; - if (!(s->fft_hdata[i] = av_calloc(s->fft_len[i], (s->fft_len[i] + 1) * sizeof(FFTComplex)))) + if (!(s->fft_hdata[i] = av_calloc(s->fft_len[i] + 1, s->fft_len[i] * sizeof(FFTComplex)))) return AVERROR(ENOMEM); - if (!(s->fft_vdata[i] = av_calloc(s->fft_len[i], (s->fft_len[i] + 1) * sizeof(FFTComplex)))) + if (!(s->fft_vdata[i] = av_calloc(s->fft_len[i] + 1, s->fft_len[i] * sizeof(FFTComplex)))) return AVERROR(ENOMEM); - if (!(s->fft_hdata_impulse[i] = av_calloc(s->fft_len[i], (s->fft_len[i] + 1)* sizeof(FFTComplex)))) + if (!(s->fft_hdata_impulse[i] = av_calloc(s->fft_len[i] + 1, s->fft_len[i] * sizeof(FFTComplex)))) return AVERROR(ENOMEM); - if (!(s->fft_vdata_impulse[i] = av_calloc(s->fft_len[i], (s->fft_len[i] + 1) * sizeof(FFTComplex)))) + if (!(s->fft_vdata_impulse[i] = av_calloc(s->fft_len[i] + 1, s->fft_len[i] * sizeof(FFTComplex)))) return AVERROR(ENOMEM); } @@ -157,47 +155,71 @@ static int config_input_impulse(AVFilterLink *inlink) static void fft_horizontal(ConvolveContext *s, FFTComplex *fft_hdata, AVFrame *in, int w, int h, int n, int plane, float scale) { + const int iw = (n - w) / 2, ih = (n - h) / 2; int y, x; - for (y = 0; y < h; y++) { - if (s->depth == 8) { + for (y = 0; y < n; y++) { + for (x = 0; x < n; x++) { + fft_hdata[y * n + x].re = 0; + fft_hdata[y * n + x].im = 0; + } + } + + if (s->depth == 8) { + for (y = 0; y < h; y++) { const uint8_t *src = in->data[plane] + in->linesize[plane] * y; for (x = 0; x < w; x++) { - fft_hdata[y * n + x].re = src[x] * scale; - fft_hdata[y * n + x].im = 0; + fft_hdata[(y + ih) * n + iw + x].re = src[x] * scale; } - } else { - const uint16_t *src = (const uint16_t *)(in->data[plane] + in->linesize[plane] * y); - for (x = 0; x < w; x++) { - fft_hdata[y * n + x].re = src[x] * scale; - fft_hdata[y * n + x].im = 0; + for (x = 0; x < iw; x++) { + fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + iw].re; + } + + for (x = n - iw; x < n; x++) { + fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + n - iw - 1].re; } } - for (; x < n / 2; x++) { - fft_hdata[y * n + x].re = 0; - fft_hdata[y * n + x].im = 0; + for (y = 0; y < ih; y++) { + for (x = 0; x < n; x++) { + fft_hdata[y * n + x].re = fft_hdata[ih * n + x].re; + } } - for (; x < n; x++) { - fft_hdata[y * n + x].re = fft_hdata[y * n + n - x - 1].re; - fft_hdata[y * n + x].im = 0; + for (y = n - ih; y < n; y++) { + for (x = 0; x < n; x++) { + fft_hdata[y * n + x].re = fft_hdata[(n - ih - 1) * n + x].re; + } } - } + } else { + for (y = 0; y < h; y++) { + const uint16_t *src = (const uint16_t *)(in->data[plane] + in->linesize[plane] * y); - for (; y < n / 2; y++) { - for (x = 0; x < n; x++) { - fft_hdata[y * n + x].re = 0; - fft_hdata[y * n + x].im = 0; + for (x = 0; x < w; x++) { + fft_hdata[(y + ih) * n + iw + x].re = src[x] * scale; + } + + for (x = 0; x < iw; x++) { + fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + iw].re; + } + + for (x = n - iw; x < n; x++) { + fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + n - iw - 1].re; + } } - } - for (; y < n; y++) { - for (x = 0; x < n; x++) { - fft_hdata[y * n + x].re = fft_hdata[(n - y - 1) * n + x].re; - fft_hdata[y * n + x].im = 0; + for (y = 0; y < ih; y++) { + for (x = 0; x < n; x++) { + fft_hdata[y * n + x].re = fft_hdata[ih * n + x].re; + } + } + + for (y = n - ih; y < n; y++) { + for (x = 0; x < n; x++) { + fft_hdata[y * n + x].re = fft_hdata[(n - ih - 1) * n + x].re; + } } } @@ -243,8 +265,8 @@ static void ifft_horizontal(ConvolveContext *s, AVFrame *out, { const float scale = 1.f / (n * n); const int max = (1 << s->depth) - 1; - const int oh = h / 2; - const int ow = w / 2; + const int hh = h / 2; + const int hw = w / 2; int y, x; for (y = 0; y < n; y++) { @@ -253,16 +275,46 @@ static void ifft_horizontal(ConvolveContext *s, AVFrame *out, } if (s->depth == 8) { - for (y = 0; y < h; y++) { + for (y = 0; y < hh; y++) { + uint8_t *dst = out->data[plane] + (y + hh) * out->linesize[plane] + hw; + for (x = 0; x < hw; x++) + dst[x] = av_clip_uint8(s->fft_hdata[plane][y * n + x].re * scale); + } + for (y = 0; y < hh; y++) { + uint8_t *dst = out->data[plane] + (y + hh) * out->linesize[plane]; + for (x = 0; x < hw; x++) + dst[x] = av_clip_uint8(s->fft_hdata[plane][y * n + n - hw + x].re * scale); + } + for (y = 0; y < hh; y++) { + uint8_t *dst = out->data[plane] + y * out->linesize[plane] + hw; + for (x = 0; x < hw; x++) + dst[x] = av_clip_uint8(s->fft_hdata[plane][(n - hh + y) * n + x].re * scale); + } + for (y = 0; y < hh; y++) { uint8_t *dst = out->data[plane] + y * out->linesize[plane]; - for (x = 0; x < w; x++) - dst[x] = av_clip_uint8(s->fft_hdata[plane][(y+oh) * n + x+ow].re * scale); + for (x = 0; x < hw; x++) + dst[x] = av_clip_uint8(s->fft_hdata[plane][(n - hh + y) * n + n - hw + x].re * scale); } } else { - for (y = 0; y < h; y++) { + for (y = 0; y < hh; y++) { + uint16_t *dst = (uint16_t *)(out->data[plane] + (y + hh) * out->linesize[plane] + hw * 2); + for (x = 0; x < hw; x++) + dst[x] = av_clip(s->fft_hdata[plane][y * n + x].re * scale, 0, max); + } + for (y = 0; y < hh; y++) { + uint16_t *dst = (uint16_t *)(out->data[plane] + (y + hh) * out->linesize[plane]); + for (x = 0; x < hw; x++) + dst[x] = av_clip(s->fft_hdata[plane][y * n + n - hw + x].re * scale, 0, max); + } + for (y = 0; y < hh; y++) { + uint16_t *dst = (uint16_t *)(out->data[plane] + y * out->linesize[plane] + hw * 2); + for (x = 0; x < hw; x++) + dst[x] = av_clip(s->fft_hdata[plane][(n - hh + y) * n + x].re * scale, 0, max); + } + for (y = 0; y < hh; y++) { uint16_t *dst = (uint16_t *)(out->data[plane] + y * out->linesize[plane]); - for (x = 0; x < w; x++) - dst[x] = av_clip(s->fft_hdata[plane][(y+oh) * n + x+ow].re * scale, 0, max); + for (x = 0; x < hw; x++) + dst[x] = av_clip(s->fft_hdata[plane][(n - hh + y) * n + n - hw + x].re * scale, 0, max); } } } @@ -321,9 +373,6 @@ static int do_convolve(FFFrameSync *fs) } for (y = 0; y < n; y++) { - - s->fft_vdata[plane][y*n + n].re = s->fft_vdata[plane][y*n + 0].im; - s->fft_vdata[plane][y*n + 0].im = 0; for (x = 0; x < n; x++) { FFTSample re, im, ire, iim; @@ -335,8 +384,6 @@ static int do_convolve(FFFrameSync *fs) s->fft_vdata[plane][y*n + x].re = ire * re - iim * im; s->fft_vdata[plane][y*n + x].im = iim * re + ire * im; } - s->fft_vdata[plane][y*n + n].re = s->fft_vdata[plane][y*n + 0].im * s->fft_vdata_impulse[plane][y*n + 0].im; - s->fft_vdata[plane][y*n + 0].im = s->fft_vdata[plane][y*n + n].re; } ifft_vertical(s, n, plane); From 3d95868d1bf2197597fbcbddd984eac175325a14 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Sun, 24 Dec 2017 11:58:30 -0800 Subject: [PATCH 1444/2557] avformat/hls: fix CID 1426930 Signed-off-by: Aman Gupta --- libavformat/hls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index f718f2e6c1c61..5dadcfcc29092 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1197,7 +1197,7 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg, AVDictionary *opts2 = NULL; char iv[33], key[33], url[MAX_URL_SIZE]; if (strcmp(seg->key, pls->key_url)) { - AVIOContext *pb; + AVIOContext *pb = NULL; if (open_url(pls->parent, &pb, seg->key, c->avio_opts, opts, NULL) == 0) { ret = avio_read(pb, pls->key, sizeof(pls->key)); if (ret != sizeof(pls->key)) { From b33cf735071cfe07ac60fd8f95e7f1f984005f45 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Sun, 24 Dec 2017 11:59:32 -0800 Subject: [PATCH 1445/2557] avformat/hls: fix memory leak with non-http segments Signed-off-by: Aman Gupta --- libavformat/hls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 5dadcfcc29092..3805ed6dbaf58 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1497,7 +1497,7 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) return ret; } - if (c->http_persistent) { + if (c->http_persistent && av_strstart(seg->url, "http", NULL)) { v->input_read_done = 1; } else { ff_format_io_close(v->parent, &v->input); From 207e98b4e502edc17c2e0fcba91bf122892f718c Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Sun, 24 Dec 2017 12:31:27 -0800 Subject: [PATCH 1446/2557] avformat/hls: fix SEGV in previous commit Signed-off-by: Aman Gupta --- libavformat/hls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 3805ed6dbaf58..f00e22dfefbe5 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1487,7 +1487,8 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) return copy_size; } - ret = read_from_url(v, current_segment(v), buf, buf_size, READ_NORMAL); + seg = current_segment(v); + ret = read_from_url(v, seg, buf, buf_size, READ_NORMAL); if (ret > 0) { if (just_opened && v->is_id3_timestamped != 0) { /* Intercept ID3 tags here, elementary audio streams are required From b7a3d1f249c9da9f21d10ea9137e304961da02ba Mon Sep 17 00:00:00 2001 From: James Darnley Date: Thu, 26 Oct 2017 19:45:50 +0200 Subject: [PATCH 1447/2557] configure: test whether x86 assembler supports AVX-512 --- configure | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure b/configure index d09eec4155a0c..07fb825f91d02 100755 --- a/configure +++ b/configure @@ -411,6 +411,7 @@ Optimization options (experts only): --disable-fma3 disable FMA3 optimizations --disable-fma4 disable FMA4 optimizations --disable-avx2 disable AVX2 optimizations + --disable-avx512 disable AVX-512 optimizations --disable-aesni disable AESNI optimizations --disable-armv5te disable armv5te optimizations --disable-armv6 disable armv6 optimizations @@ -1846,6 +1847,7 @@ ARCH_EXT_LIST_X86_SIMD=" amd3dnowext avx avx2 + avx512 fma3 fma4 mmx @@ -2373,6 +2375,7 @@ xop_deps="avx" fma3_deps="avx" fma4_deps="avx" avx2_deps="avx" +avx512_deps="avx2" mmx_external_deps="x86asm" mmx_inline_deps="inline_asm x86" @@ -5545,6 +5548,7 @@ EOF elf*) enabled debug && append X86ASMFLAGS $x86asm_debug ;; esac + check_x86asm "vmovdqa32 [eax]{k1}{z}, zmm0" || disable avx512_external check_x86asm "vextracti128 xmm0, ymm0, 0" || disable avx2_external check_x86asm "vpmacsdd xmm0, xmm1, xmm2, xmm3" || disable xop_external check_x86asm "vfmaddps ymm0, ymm1, ymm2, ymm3" || disable fma4_external @@ -6690,6 +6694,7 @@ if enabled x86; then echo "AESNI enabled ${aesni-no}" echo "AVX enabled ${avx-no}" echo "AVX2 enabled ${avx2-no}" + echo "AVX-512 enabled ${avx512-no}" echo "XOP enabled ${xop-no}" echo "FMA3 enabled ${fma3-no}" echo "FMA4 enabled ${fma4-no}" From 8b81eabe5789105cf4dcf223c9d758ca19278cab Mon Sep 17 00:00:00 2001 From: James Darnley Date: Thu, 26 Oct 2017 19:48:26 +0200 Subject: [PATCH 1448/2557] avutil: add AVX-512 flags --- Changelog | 1 + doc/APIchanges | 3 +++ libavutil/cpu.c | 6 +++++- libavutil/cpu.h | 1 + libavutil/tests/cpu.c | 1 + libavutil/version.h | 2 +- libavutil/x86/cpu.h | 2 ++ 7 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index ee48876128118..f44cec679f493 100644 --- a/Changelog +++ b/Changelog @@ -27,6 +27,7 @@ version : - video setrange filter - nsp demuxer - support LibreSSL (via libtls) +- AVX-512/ZMM support added version 3.4: diff --git a/doc/APIchanges b/doc/APIchanges index da444ffb7c0d9..df79758e863f3 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2017-12-xx - xxxxxxx - lavu 56.7.100 - cpu.h + AVX-512 flags added. + 2017-xx-xx - xxxxxxx - lavc 58.8.100 - avcodec.h The MediaCodec decoders now support AVCodecContext.hw_device_ctx. diff --git a/libavutil/cpu.c b/libavutil/cpu.c index c8401b825809b..6548cc3042aa8 100644 --- a/libavutil/cpu.c +++ b/libavutil/cpu.c @@ -80,7 +80,8 @@ void av_force_cpu_flags(int arg){ AV_CPU_FLAG_XOP | AV_CPU_FLAG_FMA3 | AV_CPU_FLAG_FMA4 | - AV_CPU_FLAG_AVX2 )) + AV_CPU_FLAG_AVX2 | + AV_CPU_FLAG_AVX512 )) && !(arg & AV_CPU_FLAG_MMX)) { av_log(NULL, AV_LOG_WARNING, "MMX implied by specified flags\n"); arg |= AV_CPU_FLAG_MMX; @@ -126,6 +127,7 @@ int av_parse_cpu_flags(const char *s) #define CPUFLAG_AVX2 (AV_CPU_FLAG_AVX2 | CPUFLAG_AVX) #define CPUFLAG_BMI2 (AV_CPU_FLAG_BMI2 | AV_CPU_FLAG_BMI1) #define CPUFLAG_AESNI (AV_CPU_FLAG_AESNI | CPUFLAG_SSE42) +#define CPUFLAG_AVX512 (AV_CPU_FLAG_AVX512 | CPUFLAG_AVX2) static const AVOption cpuflags_opts[] = { { "flags" , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" }, #if ARCH_PPC @@ -154,6 +156,7 @@ int av_parse_cpu_flags(const char *s) { "3dnowext", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_3DNOWEXT }, .unit = "flags" }, { "cmov", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_CMOV }, .unit = "flags" }, { "aesni" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_AESNI }, .unit = "flags" }, + { "avx512" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_AVX512 }, .unit = "flags" }, #elif ARCH_ARM { "armv5te", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV5TE }, .unit = "flags" }, { "armv6", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV6 }, .unit = "flags" }, @@ -216,6 +219,7 @@ int av_parse_cpu_caps(unsigned *flags, const char *s) { "3dnowext", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_3DNOWEXT }, .unit = "flags" }, { "cmov", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_CMOV }, .unit = "flags" }, { "aesni", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_AESNI }, .unit = "flags" }, + { "avx512" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_AVX512 }, .unit = "flags" }, #define CPU_FLAG_P2 AV_CPU_FLAG_CMOV | AV_CPU_FLAG_MMX #define CPU_FLAG_P3 CPU_FLAG_P2 | AV_CPU_FLAG_MMX2 | AV_CPU_FLAG_SSE diff --git a/libavutil/cpu.h b/libavutil/cpu.h index 9e5d40affef65..8bb9eb606bf2a 100644 --- a/libavutil/cpu.h +++ b/libavutil/cpu.h @@ -55,6 +55,7 @@ #define AV_CPU_FLAG_FMA3 0x10000 ///< Haswell FMA3 functions #define AV_CPU_FLAG_BMI1 0x20000 ///< Bit Manipulation Instruction Set 1 #define AV_CPU_FLAG_BMI2 0x40000 ///< Bit Manipulation Instruction Set 2 +#define AV_CPU_FLAG_AVX512 0x100000 ///< AVX-512 functions: requires OS support even if YMM/ZMM registers aren't used #define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard #define AV_CPU_FLAG_VSX 0x0002 ///< ISA 2.06 diff --git a/libavutil/tests/cpu.c b/libavutil/tests/cpu.c index f02a54cbbb146..ce45b715a0d77 100644 --- a/libavutil/tests/cpu.c +++ b/libavutil/tests/cpu.c @@ -73,6 +73,7 @@ static const struct { { AV_CPU_FLAG_BMI1, "bmi1" }, { AV_CPU_FLAG_BMI2, "bmi2" }, { AV_CPU_FLAG_AESNI, "aesni" }, + { AV_CPU_FLAG_AVX512, "avx512" }, #endif { 0 } }; diff --git a/libavutil/version.h b/libavutil/version.h index 9ae9768d4d80f..d81ec6fa7bf9e 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 6 +#define LIBAVUTIL_VERSION_MINOR 7 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libavutil/x86/cpu.h b/libavutil/x86/cpu.h index 309b8e746c56e..7f4e5d08bb249 100644 --- a/libavutil/x86/cpu.h +++ b/libavutil/x86/cpu.h @@ -50,6 +50,7 @@ #define X86_FMA4(flags) CPUEXT(flags, FMA4) #define X86_AVX2(flags) CPUEXT(flags, AVX2) #define X86_AESNI(flags) CPUEXT(flags, AESNI) +#define X86_AVX512(flags) CPUEXT(flags, AVX512) #define EXTERNAL_AMD3DNOW(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, AMD3DNOW) #define EXTERNAL_AMD3DNOWEXT(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, AMD3DNOWEXT) @@ -79,6 +80,7 @@ #define EXTERNAL_AVX2_FAST(flags) CPUEXT_SUFFIX_FAST2(flags, _EXTERNAL, AVX2, AVX) #define EXTERNAL_AVX2_SLOW(flags) CPUEXT_SUFFIX_SLOW2(flags, _EXTERNAL, AVX2, AVX) #define EXTERNAL_AESNI(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, AESNI) +#define EXTERNAL_AVX512(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, AVX512) #define INLINE_AMD3DNOW(flags) CPUEXT_SUFFIX(flags, _INLINE, AMD3DNOW) #define INLINE_AMD3DNOWEXT(flags) CPUEXT_SUFFIX(flags, _INLINE, AMD3DNOWEXT) From 4783a01c113b727164588ada47b3145ce5d2c367 Mon Sep 17 00:00:00 2001 From: James Darnley Date: Thu, 26 Oct 2017 19:51:02 +0200 Subject: [PATCH 1449/2557] avutil: detect when AVX-512 is available --- libavutil/x86/cpu.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index f33088c8c7385..8097b6d146cc8 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -97,6 +97,7 @@ int ff_get_cpu_flags_x86(void) int max_std_level, max_ext_level, std_caps = 0, ext_caps = 0; int family = 0, model = 0; union { int i[3]; char c[12]; } vendor; + int xcr0_lo = 0, xcr0_hi = 0; if (!cpuid_test()) return 0; /* CPUID not supported */ @@ -132,8 +133,8 @@ int ff_get_cpu_flags_x86(void) /* Check OXSAVE and AVX bits */ if ((ecx & 0x18000000) == 0x18000000) { /* Check for OS support */ - xgetbv(0, eax, edx); - if ((eax & 0x6) == 0x6) { + xgetbv(0, xcr0_lo, xcr0_hi); + if ((xcr0_lo & 0x6) == 0x6) { rval |= AV_CPU_FLAG_AVX; if (ecx & 0x00001000) rval |= AV_CPU_FLAG_FMA3; @@ -147,6 +148,13 @@ int ff_get_cpu_flags_x86(void) #if HAVE_AVX2 if ((rval & AV_CPU_FLAG_AVX) && (ebx & 0x00000020)) rval |= AV_CPU_FLAG_AVX2; +#if HAVE_AVX512 /* F, CD, BW, DQ, VL */ + if ((xcr0_lo & 0xe0) == 0xe0) { /* OPMASK/ZMM state */ + if ((rval & AV_CPU_FLAG_AVX2) && (ebx & 0xd0030000) == 0xd0030000) + rval |= AV_CPU_FLAG_AVX512; + + } +#endif /* HAVE_AVX512 */ #endif /* HAVE_AVX2 */ /* BMI1/2 don't need OS support */ if (ebx & 0x00000008) { From e2218ed8ce6e2f208b9279acc80b7e2b7f1eae6c Mon Sep 17 00:00:00 2001 From: James Darnley Date: Thu, 26 Oct 2017 19:51:37 +0200 Subject: [PATCH 1450/2557] avutil: add alignment needed for AVX-512 --- libavutil/mem.c | 2 +- libavutil/x86/cpu.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libavutil/mem.c b/libavutil/mem.c index 6ad409daf44f6..79e8b597f1672 100644 --- a/libavutil/mem.c +++ b/libavutil/mem.c @@ -61,7 +61,7 @@ void free(void *ptr); #include "mem_internal.h" -#define ALIGN (HAVE_AVX ? 32 : 16) +#define ALIGN (HAVE_AVX512 ? 64 : (HAVE_AVX ? 32 : 16)) /* NOTE: if you want to override these functions with your own * implementations (not recommended) you have to link libav* as diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index 8097b6d146cc8..aca893174ea41 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -246,6 +246,8 @@ size_t ff_get_cpu_max_align_x86(void) { int flags = av_get_cpu_flags(); + if (flags & AV_CPU_FLAG_AVX512) + return 64; if (flags & (AV_CPU_FLAG_AVX2 | AV_CPU_FLAG_AVX | AV_CPU_FLAG_XOP | From 8f86e6623811f7713d5e72c13797e20fffb3df62 Mon Sep 17 00:00:00 2001 From: James Darnley Date: Mon, 6 Nov 2017 15:43:39 +0100 Subject: [PATCH 1451/2557] avcodec: add stride alignment needed for AVX-512 --- configure | 2 ++ libavcodec/internal.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 07fb825f91d02..d3187d71eda3b 100755 --- a/configure +++ b/configure @@ -1892,6 +1892,7 @@ ARCH_FEATURES=" local_aligned simd_align_16 simd_align_32 + simd_align_64 " BUILTIN_LIST=" @@ -2394,6 +2395,7 @@ fast_clz_if_any="aarch64 alpha avr32 mips ppc x86" fast_unaligned_if_any="aarch64 ppc x86" simd_align_16_if_any="altivec neon sse" simd_align_32_if_any="avx" +simd_align_64_if_any="avx512" # system capabilities symver_if_any="symver_asm_label symver_gnu_asm" diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 30cb9a0de1df4..fcbdb6c04d61e 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -87,7 +87,9 @@ #define FF_SIGNBIT(x) ((x) >> CHAR_BIT * sizeof(x) - 1) -#if HAVE_SIMD_ALIGN_32 +#if HAVE_SIMD_ALIGN_64 +# define STRIDE_ALIGN 64 /* AVX-512 */ +#elif HAVE_SIMD_ALIGN_32 # define STRIDE_ALIGN 32 #elif HAVE_SIMD_ALIGN_16 # define STRIDE_ALIGN 16 From f7197f68dc61753be67ff68b27bbd3b15fe43da6 Mon Sep 17 00:00:00 2001 From: Henrik Gramner Date: Sat, 25 Mar 2017 10:16:09 +0100 Subject: [PATCH 1452/2557] x86inc: AVX-512 support AVX-512 consists of a plethora of different extensions, but in order to keep things a bit more manageable we group together the following extensions under a single baseline cpu flag which should cover SKL-X and future CPUs: * AVX-512 Foundation (F) * AVX-512 Conflict Detection Instructions (CD) * AVX-512 Byte and Word Instructions (BW) * AVX-512 Doubleword and Quadword Instructions (DQ) * AVX-512 Vector Length Extensions (VL) On x86-64 AVX-512 provides 16 additional vector registers, prefer using those over existing ones since it allows us to avoid using `vzeroupper` unless more than 16 vector registers are required. They also happen to be volatile on Windows which means that we don't need to save and restore existing xmm register contents unless more than 22 vector registers are required. Big thanks to Intel for their support. --- libavutil/x86/x86inc.asm | 172 +++++++++++++++++++++++++++++++-------- 1 file changed, 139 insertions(+), 33 deletions(-) diff --git a/libavutil/x86/x86inc.asm b/libavutil/x86/x86inc.asm index 6a054a3e0925a..f3dd2b788a048 100644 --- a/libavutil/x86/x86inc.asm +++ b/libavutil/x86/x86inc.asm @@ -337,6 +337,8 @@ DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 %endmacro %define required_stack_alignment ((mmsize + 15) & ~15) +%define vzeroupper_required (mmsize > 16 && (ARCH_X86_64 == 0 || xmm_regs_used > 16 || notcpuflag(avx512))) +%define high_mm_regs (16*cpuflag(avx512)) %macro ALLOC_STACK 1-2 0 ; stack_size, n_xmm_regs (for win64 only) %ifnum %1 @@ -450,15 +452,16 @@ DECLARE_REG 14, R13, 120 %macro WIN64_PUSH_XMM 0 ; Use the shadow space to store XMM6 and XMM7, the rest needs stack space allocated. - %if xmm_regs_used > 6 + %if xmm_regs_used > 6 + high_mm_regs movaps [rstk + stack_offset + 8], xmm6 %endif - %if xmm_regs_used > 7 + %if xmm_regs_used > 7 + high_mm_regs movaps [rstk + stack_offset + 24], xmm7 %endif - %if xmm_regs_used > 8 + %assign %%xmm_regs_on_stack xmm_regs_used - high_mm_regs - 8 + %if %%xmm_regs_on_stack > 0 %assign %%i 8 - %rep xmm_regs_used-8 + %rep %%xmm_regs_on_stack movaps [rsp + (%%i-8)*16 + stack_size + 32], xmm %+ %%i %assign %%i %%i+1 %endrep @@ -467,10 +470,11 @@ DECLARE_REG 14, R13, 120 %macro WIN64_SPILL_XMM 1 %assign xmm_regs_used %1 - ASSERT xmm_regs_used <= 16 - %if xmm_regs_used > 8 + ASSERT xmm_regs_used <= 16 + high_mm_regs + %assign %%xmm_regs_on_stack xmm_regs_used - high_mm_regs - 8 + %if %%xmm_regs_on_stack > 0 ; Allocate stack space for callee-saved xmm registers plus shadow space and align the stack. - %assign %%pad (xmm_regs_used-8)*16 + 32 + %assign %%pad %%xmm_regs_on_stack*16 + 32 %assign stack_size_padded %%pad + ((-%%pad-stack_offset-gprsize) & (STACK_ALIGNMENT-1)) SUB rsp, stack_size_padded %endif @@ -479,9 +483,10 @@ DECLARE_REG 14, R13, 120 %macro WIN64_RESTORE_XMM_INTERNAL 0 %assign %%pad_size 0 - %if xmm_regs_used > 8 - %assign %%i xmm_regs_used - %rep xmm_regs_used-8 + %assign %%xmm_regs_on_stack xmm_regs_used - high_mm_regs - 8 + %if %%xmm_regs_on_stack > 0 + %assign %%i xmm_regs_used - high_mm_regs + %rep %%xmm_regs_on_stack %assign %%i %%i-1 movaps xmm %+ %%i, [rsp + (%%i-8)*16 + stack_size + 32] %endrep @@ -494,10 +499,10 @@ DECLARE_REG 14, R13, 120 %assign %%pad_size stack_size_padded %endif %endif - %if xmm_regs_used > 7 + %if xmm_regs_used > 7 + high_mm_regs movaps xmm7, [rsp + stack_offset - %%pad_size + 24] %endif - %if xmm_regs_used > 6 + %if xmm_regs_used > 6 + high_mm_regs movaps xmm6, [rsp + stack_offset - %%pad_size + 8] %endif %endmacro @@ -509,12 +514,12 @@ DECLARE_REG 14, R13, 120 %assign xmm_regs_used 0 %endmacro -%define has_epilogue regs_used > 7 || xmm_regs_used > 6 || mmsize == 32 || stack_size > 0 +%define has_epilogue regs_used > 7 || stack_size > 0 || vzeroupper_required || xmm_regs_used > 6+high_mm_regs %macro RET 0 WIN64_RESTORE_XMM_INTERNAL POP_IF_USED 14, 13, 12, 11, 10, 9, 8, 7 - %if mmsize == 32 + %if vzeroupper_required vzeroupper %endif AUTO_REP_RET @@ -538,9 +543,10 @@ DECLARE_REG 12, R15, 56 DECLARE_REG 13, R12, 64 DECLARE_REG 14, R13, 72 -%macro PROLOGUE 2-5+ ; #args, #regs, #xmm_regs, [stack_size,] arg_names... +%macro PROLOGUE 2-5+ 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names... %assign num_args %1 %assign regs_used %2 + %assign xmm_regs_used %3 ASSERT regs_used >= num_args SETUP_STACK_POINTER %4 ASSERT regs_used <= 15 @@ -550,7 +556,7 @@ DECLARE_REG 14, R13, 72 DEFINE_ARGS_INTERNAL %0, %4, %5 %endmacro -%define has_epilogue regs_used > 9 || mmsize == 32 || stack_size > 0 +%define has_epilogue regs_used > 9 || stack_size > 0 || vzeroupper_required %macro RET 0 %if stack_size_padded > 0 @@ -561,7 +567,7 @@ DECLARE_REG 14, R13, 72 %endif %endif POP_IF_USED 14, 13, 12, 11, 10, 9 - %if mmsize == 32 + %if vzeroupper_required vzeroupper %endif AUTO_REP_RET @@ -606,7 +612,7 @@ DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14 DEFINE_ARGS_INTERNAL %0, %4, %5 %endmacro -%define has_epilogue regs_used > 3 || mmsize == 32 || stack_size > 0 +%define has_epilogue regs_used > 3 || stack_size > 0 || vzeroupper_required %macro RET 0 %if stack_size_padded > 0 @@ -617,7 +623,7 @@ DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14 %endif %endif POP_IF_USED 6, 5, 4, 3 - %if mmsize == 32 + %if vzeroupper_required vzeroupper %endif AUTO_REP_RET @@ -727,7 +733,7 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %assign stack_offset 0 ; stack pointer offset relative to the return address %assign stack_size 0 ; amount of stack space that can be freely used inside a function %assign stack_size_padded 0 ; total amount of allocated stack space, including space for callee-saved xmm registers on WIN64 and alignment padding - %assign xmm_regs_used 0 ; number of XMM registers requested, used for dealing with callee-saved registers on WIN64 + %assign xmm_regs_used 0 ; number of XMM registers requested, used for dealing with callee-saved registers on WIN64 and vzeroupper %ifnidn %3, "" PROLOGUE %3 %endif @@ -803,12 +809,13 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %assign cpuflags_bmi1 (1<<17)| cpuflags_avx|cpuflags_lzcnt %assign cpuflags_bmi2 (1<<18)| cpuflags_bmi1 %assign cpuflags_avx2 (1<<19)| cpuflags_fma3|cpuflags_bmi2 +%assign cpuflags_avx512 (1<<20)| cpuflags_avx2 ; F, CD, BW, DQ, VL -%assign cpuflags_cache32 (1<<20) -%assign cpuflags_cache64 (1<<21) -%assign cpuflags_slowctz (1<<22) -%assign cpuflags_aligned (1<<23) ; not a cpu feature, but a function variant -%assign cpuflags_atom (1<<24) +%assign cpuflags_cache32 (1<<21) +%assign cpuflags_cache64 (1<<22) +%assign cpuflags_slowctz (1<<23) +%assign cpuflags_aligned (1<<24) ; not a cpu feature, but a function variant +%assign cpuflags_atom (1<<25) ; Returns a boolean value expressing whether or not the specified cpuflag is enabled. %define cpuflag(x) (((((cpuflags & (cpuflags_ %+ x)) ^ (cpuflags_ %+ x)) - 1) >> 31) & 1) @@ -856,11 +863,12 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %endif %endmacro -; Merge mmx and sse* +; Merge mmx, sse*, and avx* ; m# is a simd register of the currently selected size ; xm# is the corresponding xmm register if mmsize >= 16, otherwise the same as m# ; ym# is the corresponding ymm register if mmsize >= 32, otherwise the same as m# -; (All 3 remain in sync through SWAP.) +; zm# is the corresponding zmm register if mmsize >= 64, otherwise the same as m# +; (All 4 remain in sync through SWAP.) %macro CAT_XDEFINE 3 %xdefine %1%2 %3 @@ -870,6 +878,18 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %undef %1%2 %endmacro +; Prefer registers 16-31 over 0-15 to avoid having to use vzeroupper +%macro AVX512_MM_PERMUTATION 0-1 0 ; start_reg + %if ARCH_X86_64 && cpuflag(avx512) + %assign %%i %1 + %rep 16-%1 + %assign %%i_high %%i+16 + SWAP %%i, %%i_high + %assign %%i %%i+1 + %endrep + %endif +%endmacro + %macro INIT_MMX 0-1+ %assign avx_enabled 0 %define RESET_MM_PERMUTATION INIT_MMX %1 @@ -885,7 +905,7 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, CAT_XDEFINE nnmm, %%i, %%i %assign %%i %%i+1 %endrep - %rep 8 + %rep 24 CAT_UNDEF m, %%i CAT_UNDEF nnmm, %%i %assign %%i %%i+1 @@ -899,7 +919,7 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %define mmsize 16 %define num_mmregs 8 %if ARCH_X86_64 - %define num_mmregs 16 + %define num_mmregs 32 %endif %define mova movdqa %define movu movdqu @@ -912,6 +932,10 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %assign %%i %%i+1 %endrep INIT_CPUFLAGS %1 + %if WIN64 + ; Swap callee-saved registers with volatile registers + AVX512_MM_PERMUTATION 6 + %endif %endmacro %macro INIT_YMM 0-1+ @@ -920,7 +944,7 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %define mmsize 32 %define num_mmregs 8 %if ARCH_X86_64 - %define num_mmregs 16 + %define num_mmregs 32 %endif %define mova movdqa %define movu movdqu @@ -933,6 +957,29 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %assign %%i %%i+1 %endrep INIT_CPUFLAGS %1 + AVX512_MM_PERMUTATION +%endmacro + +%macro INIT_ZMM 0-1+ + %assign avx_enabled 1 + %define RESET_MM_PERMUTATION INIT_ZMM %1 + %define mmsize 64 + %define num_mmregs 8 + %if ARCH_X86_64 + %define num_mmregs 32 + %endif + %define mova movdqa + %define movu movdqu + %undef movh + %define movnta movntdq + %assign %%i 0 + %rep num_mmregs + CAT_XDEFINE m, %%i, zmm %+ %%i + CAT_XDEFINE nnzmm, %%i, %%i + %assign %%i %%i+1 + %endrep + INIT_CPUFLAGS %1 + AVX512_MM_PERMUTATION %endmacro INIT_XMM @@ -941,18 +988,26 @@ INIT_XMM %define mmmm%1 mm%1 %define mmxmm%1 mm%1 %define mmymm%1 mm%1 + %define mmzmm%1 mm%1 %define xmmmm%1 mm%1 %define xmmxmm%1 xmm%1 %define xmmymm%1 xmm%1 + %define xmmzmm%1 xmm%1 %define ymmmm%1 mm%1 %define ymmxmm%1 xmm%1 %define ymmymm%1 ymm%1 + %define ymmzmm%1 ymm%1 + %define zmmmm%1 mm%1 + %define zmmxmm%1 xmm%1 + %define zmmymm%1 ymm%1 + %define zmmzmm%1 zmm%1 %define xm%1 xmm %+ m%1 %define ym%1 ymm %+ m%1 + %define zm%1 zmm %+ m%1 %endmacro %assign i 0 -%rep 16 +%rep 32 DECLARE_MMCAST i %assign i i+1 %endrep @@ -1087,12 +1142,17 @@ INIT_XMM ;============================================================================= %assign i 0 -%rep 16 +%rep 32 %if i < 8 CAT_XDEFINE sizeofmm, i, 8 + CAT_XDEFINE regnumofmm, i, i %endif CAT_XDEFINE sizeofxmm, i, 16 CAT_XDEFINE sizeofymm, i, 32 + CAT_XDEFINE sizeofzmm, i, 64 + CAT_XDEFINE regnumofxmm, i, i + CAT_XDEFINE regnumofymm, i, i + CAT_XDEFINE regnumofzmm, i, i %assign i i+1 %endrep %undef i @@ -1209,7 +1269,7 @@ INIT_XMM %endmacro %endmacro -; Instructions with both VEX and non-VEX encodings +; Instructions with both VEX/EVEX and legacy encodings ; Non-destructive instructions are written without parameters AVX_INSTR addpd, sse2, 1, 0, 1 AVX_INSTR addps, sse, 1, 0, 1 @@ -1545,6 +1605,52 @@ FMA4_INSTR fmsubadd, pd, ps FMA4_INSTR fnmadd, pd, ps, sd, ss FMA4_INSTR fnmsub, pd, ps, sd, ss +; Macros for converting VEX instructions to equivalent EVEX ones. +%macro EVEX_INSTR 2-3 0 ; vex, evex, prefer_evex + %macro %1 2-7 fnord, fnord, %1, %2, %3 + %ifidn %3, fnord + %define %%args %1, %2 + %elifidn %4, fnord + %define %%args %1, %2, %3 + %else + %define %%args %1, %2, %3, %4 + %endif + %assign %%evex_required cpuflag(avx512) & %7 + %ifnum regnumof%1 + %if regnumof%1 >= 16 || sizeof%1 > 32 + %assign %%evex_required 1 + %endif + %endif + %ifnum regnumof%2 + %if regnumof%2 >= 16 || sizeof%2 > 32 + %assign %%evex_required 1 + %endif + %endif + %if %%evex_required + %6 %%args + %else + %5 %%args ; Prefer VEX over EVEX due to shorter instruction length + %endif + %endmacro +%endmacro + +EVEX_INSTR vbroadcastf128, vbroadcastf32x4 +EVEX_INSTR vbroadcasti128, vbroadcasti32x4 +EVEX_INSTR vextractf128, vextractf32x4 +EVEX_INSTR vextracti128, vextracti32x4 +EVEX_INSTR vinsertf128, vinsertf32x4 +EVEX_INSTR vinserti128, vinserti32x4 +EVEX_INSTR vmovdqa, vmovdqa32 +EVEX_INSTR vmovdqu, vmovdqu32 +EVEX_INSTR vpand, vpandd +EVEX_INSTR vpandn, vpandnd +EVEX_INSTR vpor, vpord +EVEX_INSTR vpxor, vpxord +EVEX_INSTR vrcpps, vrcp14ps, 1 ; EVEX versions have higher precision +EVEX_INSTR vrcpss, vrcp14ss, 1 +EVEX_INSTR vrsqrtps, vrsqrt14ps, 1 +EVEX_INSTR vrsqrtss, vrsqrt14ss, 1 + ; workaround: vpbroadcastq is broken in x86_32 due to a yasm bug (fixed in 1.3.0) %ifdef __YASM_VER__ %if __YASM_VERSION_ID__ < 0x01030000 && ARCH_X86_64 == 0 From 40d4b13228bf234a2b9649674d9ed25bd020f226 Mon Sep 17 00:00:00 2001 From: James Darnley Date: Mon, 30 Oct 2017 13:04:59 +0100 Subject: [PATCH 1453/2557] checkasm: support for AVX-512 functions --- tests/checkasm/checkasm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 45a70aa87f4f9..ff0ca5b68d374 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -204,6 +204,7 @@ static const struct { { "FMA3", "fma3", AV_CPU_FLAG_FMA3 }, { "FMA4", "fma4", AV_CPU_FLAG_FMA4 }, { "AVX2", "avx2", AV_CPU_FLAG_AVX2 }, + { "AVX-512", "avx512", AV_CPU_FLAG_AVX512 }, #endif { NULL } }; From 90d216cb90398ffb92e9e8361656ad619a985b64 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 24 Dec 2017 21:34:19 -0300 Subject: [PATCH 1454/2557] x86inc: set the correct amount of simd regs in x86_64 when avx512 is enabled but not used Fixes compilation of libavresample/x86/audio_mix.asm Reviewed-by: Gramner Signed-off-by: James Almer --- libavutil/x86/x86inc.asm | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/libavutil/x86/x86inc.asm b/libavutil/x86/x86inc.asm index f3dd2b788a048..196374c34827a 100644 --- a/libavutil/x86/x86inc.asm +++ b/libavutil/x86/x86inc.asm @@ -917,21 +917,24 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %assign avx_enabled 0 %define RESET_MM_PERMUTATION INIT_XMM %1 %define mmsize 16 - %define num_mmregs 8 - %if ARCH_X86_64 - %define num_mmregs 32 - %endif %define mova movdqa %define movu movdqu %define movh movq %define movnta movntdq + INIT_CPUFLAGS %1 + %define num_mmregs 8 + %if ARCH_X86_64 + %define num_mmregs 16 + %if cpuflag(avx512) + %define num_mmregs 32 + %endif + %endif %assign %%i 0 %rep num_mmregs CAT_XDEFINE m, %%i, xmm %+ %%i CAT_XDEFINE nnxmm, %%i, %%i %assign %%i %%i+1 %endrep - INIT_CPUFLAGS %1 %if WIN64 ; Swap callee-saved registers with volatile registers AVX512_MM_PERMUTATION 6 @@ -942,21 +945,24 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %assign avx_enabled 1 %define RESET_MM_PERMUTATION INIT_YMM %1 %define mmsize 32 - %define num_mmregs 8 - %if ARCH_X86_64 - %define num_mmregs 32 - %endif %define mova movdqa %define movu movdqu %undef movh %define movnta movntdq + INIT_CPUFLAGS %1 + %define num_mmregs 8 + %if ARCH_X86_64 + %define num_mmregs 16 + %if cpuflag(avx512) + %define num_mmregs 32 + %endif + %endif %assign %%i 0 %rep num_mmregs CAT_XDEFINE m, %%i, ymm %+ %%i CAT_XDEFINE nnymm, %%i, %%i %assign %%i %%i+1 %endrep - INIT_CPUFLAGS %1 AVX512_MM_PERMUTATION %endmacro From 6848201f704b5e8e1ebdc911dba94ebc1e52c6b0 Mon Sep 17 00:00:00 2001 From: Karthick Jeyapal Date: Mon, 25 Dec 2017 12:07:43 +0800 Subject: [PATCH 1455/2557] avformat/http: Avoid calling http_shutdown() if end of chunk is signalled already --- libavformat/http.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavformat/http.c b/libavformat/http.c index 7a68378acb25f..c15ca522c4080 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -323,9 +323,11 @@ int ff_http_do_new_request(URLContext *h, const char *uri) return AVERROR(EINVAL); } - ret = http_shutdown(h, h->flags); - if (ret < 0) - return ret; + if (!s->end_chunked_post) { + ret = http_shutdown(h, h->flags); + if (ret < 0) + return ret; + } if (s->willclose) return AVERROR_EOF; From be2da4c52221c5ec0769ccea675a896e324d1f41 Mon Sep 17 00:00:00 2001 From: Karthick Jeyapal Date: Mon, 25 Dec 2017 12:08:06 +0800 Subject: [PATCH 1456/2557] avformat/hlsenc: Signal http end of chunk(http_shutdown) during hlsenc_io_close() Currently http end of chunk is signalled implicitly in hlsenc_io_open(). This mean playlists http writes would have to wait upto a segment duration to signal end of chunk causing delays. This patch will fix that problem and improve performance. --- libavformat/hlsenc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index bbc2742dc7dcb..b850b1a320549 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -269,8 +269,13 @@ static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename if (!http_base_proto || !hls->http_persistent || hls->key_info_file || hls->encrypt) { ff_format_io_close(s, pb); +#if CONFIG_HTTP_PROTOCOL } else { + URLContext *http_url_context = ffio_geturlcontext(*pb); + av_assert0(http_url_context); avio_flush(*pb); + ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE); +#endif } } From ec6608f51b2d5a979b59d0dcc6a06629a0f8bd81 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 25 Dec 2017 10:04:59 +0100 Subject: [PATCH 1457/2557] avfilter/vf_convolve: clear coefficients only when needed Signed-off-by: Paul B Mahol --- libavfilter/vf_convolve.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c index 6eb954845650c..2af9df5983a75 100644 --- a/libavfilter/vf_convolve.c +++ b/libavfilter/vf_convolve.c @@ -158,39 +158,37 @@ static void fft_horizontal(ConvolveContext *s, FFTComplex *fft_hdata, const int iw = (n - w) / 2, ih = (n - h) / 2; int y, x; - for (y = 0; y < n; y++) { - for (x = 0; x < n; x++) { - fft_hdata[y * n + x].re = 0; - fft_hdata[y * n + x].im = 0; - } - } - if (s->depth == 8) { for (y = 0; y < h; y++) { const uint8_t *src = in->data[plane] + in->linesize[plane] * y; for (x = 0; x < w; x++) { fft_hdata[(y + ih) * n + iw + x].re = src[x] * scale; + fft_hdata[(y + ih) * n + iw + x].im = 0; } for (x = 0; x < iw; x++) { fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + iw].re; + fft_hdata[(y + ih) * n + x].im = 0; } for (x = n - iw; x < n; x++) { fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + n - iw - 1].re; + fft_hdata[(y + ih) * n + x].im = 0; } } for (y = 0; y < ih; y++) { for (x = 0; x < n; x++) { fft_hdata[y * n + x].re = fft_hdata[ih * n + x].re; + fft_hdata[y * n + x].im = 0; } } for (y = n - ih; y < n; y++) { for (x = 0; x < n; x++) { fft_hdata[y * n + x].re = fft_hdata[(n - ih - 1) * n + x].re; + fft_hdata[y * n + x].im = 0; } } } else { @@ -199,26 +197,31 @@ static void fft_horizontal(ConvolveContext *s, FFTComplex *fft_hdata, for (x = 0; x < w; x++) { fft_hdata[(y + ih) * n + iw + x].re = src[x] * scale; + fft_hdata[(y + ih) * n + iw + x].im = 0; } for (x = 0; x < iw; x++) { fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + iw].re; + fft_hdata[(y + ih) * n + x].im = 0; } for (x = n - iw; x < n; x++) { fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + n - iw - 1].re; + fft_hdata[(y + ih) * n + x].im = 0; } } for (y = 0; y < ih; y++) { for (x = 0; x < n; x++) { fft_hdata[y * n + x].re = fft_hdata[ih * n + x].re; + fft_hdata[y * n + x].im = 0; } } for (y = n - ih; y < n; y++) { for (x = 0; x < n; x++) { fft_hdata[y * n + x].re = fft_hdata[(n - ih - 1) * n + x].re; + fft_hdata[y * n + x].im = 0; } } } From 86e3eebfb763855e9be873cc71b8569f6dd2b52f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 25 Dec 2017 10:19:47 +0100 Subject: [PATCH 1458/2557] avfilter/vf_convolve: use shorter variants for pointers Signed-off-by: Paul B Mahol --- libavfilter/vf_convolve.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c index 2af9df5983a75..b1577ef5ae966 100644 --- a/libavfilter/vf_convolve.c +++ b/libavfilter/vf_convolve.c @@ -266,6 +266,7 @@ static void ifft_vertical(ConvolveContext *s, int n, int plane) static void ifft_horizontal(ConvolveContext *s, AVFrame *out, int w, int h, int n, int plane) { + FFTComplex *input = s->fft_hdata[plane]; const float scale = 1.f / (n * n); const int max = (1 << s->depth) - 1; const int hh = h / 2; @@ -273,51 +274,51 @@ static void ifft_horizontal(ConvolveContext *s, AVFrame *out, int y, x; for (y = 0; y < n; y++) { - av_fft_permute(s->ifft[plane], s->fft_hdata[plane] + y * n); - av_fft_calc(s->ifft[plane], s->fft_hdata[plane] + y * n); + av_fft_permute(s->ifft[plane], input + y * n); + av_fft_calc(s->ifft[plane], input + y * n); } if (s->depth == 8) { for (y = 0; y < hh; y++) { uint8_t *dst = out->data[plane] + (y + hh) * out->linesize[plane] + hw; for (x = 0; x < hw; x++) - dst[x] = av_clip_uint8(s->fft_hdata[plane][y * n + x].re * scale); + dst[x] = av_clip_uint8(input[y * n + x].re * scale); } for (y = 0; y < hh; y++) { uint8_t *dst = out->data[plane] + (y + hh) * out->linesize[plane]; for (x = 0; x < hw; x++) - dst[x] = av_clip_uint8(s->fft_hdata[plane][y * n + n - hw + x].re * scale); + dst[x] = av_clip_uint8(input[y * n + n - hw + x].re * scale); } for (y = 0; y < hh; y++) { uint8_t *dst = out->data[plane] + y * out->linesize[plane] + hw; for (x = 0; x < hw; x++) - dst[x] = av_clip_uint8(s->fft_hdata[plane][(n - hh + y) * n + x].re * scale); + dst[x] = av_clip_uint8(input[(n - hh + y) * n + x].re * scale); } for (y = 0; y < hh; y++) { uint8_t *dst = out->data[plane] + y * out->linesize[plane]; for (x = 0; x < hw; x++) - dst[x] = av_clip_uint8(s->fft_hdata[plane][(n - hh + y) * n + n - hw + x].re * scale); + dst[x] = av_clip_uint8(input[(n - hh + y) * n + n - hw + x].re * scale); } } else { for (y = 0; y < hh; y++) { uint16_t *dst = (uint16_t *)(out->data[plane] + (y + hh) * out->linesize[plane] + hw * 2); for (x = 0; x < hw; x++) - dst[x] = av_clip(s->fft_hdata[plane][y * n + x].re * scale, 0, max); + dst[x] = av_clip(input[y * n + x].re * scale, 0, max); } for (y = 0; y < hh; y++) { uint16_t *dst = (uint16_t *)(out->data[plane] + (y + hh) * out->linesize[plane]); for (x = 0; x < hw; x++) - dst[x] = av_clip(s->fft_hdata[plane][y * n + n - hw + x].re * scale, 0, max); + dst[x] = av_clip(input[y * n + n - hw + x].re * scale, 0, max); } for (y = 0; y < hh; y++) { uint16_t *dst = (uint16_t *)(out->data[plane] + y * out->linesize[plane] + hw * 2); for (x = 0; x < hw; x++) - dst[x] = av_clip(s->fft_hdata[plane][(n - hh + y) * n + x].re * scale, 0, max); + dst[x] = av_clip(input[(n - hh + y) * n + x].re * scale, 0, max); } for (y = 0; y < hh; y++) { uint16_t *dst = (uint16_t *)(out->data[plane] + y * out->linesize[plane]); for (x = 0; x < hw; x++) - dst[x] = av_clip(s->fft_hdata[plane][(n - hh + y) * n + n - hw + x].re * scale, 0, max); + dst[x] = av_clip(input[(n - hh + y) * n + n - hw + x].re * scale, 0, max); } } } @@ -337,6 +338,8 @@ static int do_convolve(FFFrameSync *fs) return ff_filter_frame(outlink, mainpic); for (plane = 0; plane < s->nb_planes; plane++) { + FFTComplex *filter = s->fft_vdata_impulse[plane]; + FFTComplex *input = s->fft_vdata[plane]; const int n = s->fft_len[plane]; const int w = s->planewidth[plane]; const int h = s->planeheight[plane]; @@ -376,16 +379,18 @@ static int do_convolve(FFFrameSync *fs) } for (y = 0; y < n; y++) { + int yn = y * n; + for (x = 0; x < n; x++) { FFTSample re, im, ire, iim; - re = s->fft_vdata[plane][y*n + x].re; - im = s->fft_vdata[plane][y*n + x].im; - ire = s->fft_vdata_impulse[plane][y*n + x].re; - iim = s->fft_vdata_impulse[plane][y*n + x].im; + re = input[yn + x].re; + im = input[yn + x].im; + ire = filter[yn + x].re; + iim = filter[yn + x].im; - s->fft_vdata[plane][y*n + x].re = ire * re - iim * im; - s->fft_vdata[plane][y*n + x].im = iim * re + ire * im; + input[yn + x].re = ire * re - iim * im; + input[yn + x].im = iim * re + ire * im; } } From f9f1b2a9274f1c58e1695fcf584646e2c6e9f756 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 25 Dec 2017 11:05:26 +0100 Subject: [PATCH 1459/2557] avfilter/vf_convolve: split input/output operations from fft Signed-off-by: Paul B Mahol --- libavfilter/vf_convolve.c | 47 ++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c index b1577ef5ae966..e3d0c5fa2aea3 100644 --- a/libavfilter/vf_convolve.c +++ b/libavfilter/vf_convolve.c @@ -153,7 +153,18 @@ static int config_input_impulse(AVFilterLink *inlink) } static void fft_horizontal(ConvolveContext *s, FFTComplex *fft_hdata, - AVFrame *in, int w, int h, int n, int plane, float scale) + int n, int plane) +{ + int y; + + for (y = 0; y < n; y++) { + av_fft_permute(s->fft[plane], fft_hdata + y * n); + av_fft_calc(s->fft[plane], fft_hdata + y * n); + } +} + +static void get_input(ConvolveContext *s, FFTComplex *fft_hdata, + AVFrame *in, int w, int h, int n, int plane, float scale) { const int iw = (n - w) / 2, ih = (n - h) / 2; int y, x; @@ -225,11 +236,6 @@ static void fft_horizontal(ConvolveContext *s, FFTComplex *fft_hdata, } } } - - for (y = 0; y < n; y++) { - av_fft_permute(s->fft[plane], fft_hdata + y * n); - av_fft_calc(s->fft[plane], fft_hdata + y * n); - } } static void fft_vertical(ConvolveContext *s, FFTComplex *fft_hdata, FFTComplex *fft_vdata, @@ -263,20 +269,26 @@ static void ifft_vertical(ConvolveContext *s, int n, int plane) } } -static void ifft_horizontal(ConvolveContext *s, AVFrame *out, - int w, int h, int n, int plane) +static void ifft_horizontal(ConvolveContext *s, int n, int plane) { FFTComplex *input = s->fft_hdata[plane]; - const float scale = 1.f / (n * n); - const int max = (1 << s->depth) - 1; - const int hh = h / 2; - const int hw = w / 2; - int y, x; + int y; for (y = 0; y < n; y++) { av_fft_permute(s->ifft[plane], input + y * n); av_fft_calc(s->ifft[plane], input + y * n); } +} + +static void get_output(ConvolveContext *s, AVFrame *out, + int w, int h, int n, int plane) +{ + FFTComplex *input = s->fft_hdata[plane]; + const float scale = 1.f / (n * n); + const int max = (1 << s->depth) - 1; + const int hh = h / 2; + const int hw = w / 2; + int y, x; if (s->depth == 8) { for (y = 0; y < hh; y++) { @@ -349,7 +361,8 @@ static int do_convolve(FFFrameSync *fs) continue; } - fft_horizontal(s, s->fft_hdata[plane], mainpic, w, h, n, plane, 1.f); + get_input(s, s->fft_hdata[plane], mainpic, w, h, n, plane, 1.f); + fft_horizontal(s, s->fft_hdata[plane], n, plane); fft_vertical(s, s->fft_hdata[plane], s->fft_vdata[plane], n, plane); @@ -371,7 +384,8 @@ static int do_convolve(FFFrameSync *fs) } total = FFMAX(1, total); - fft_horizontal(s, s->fft_hdata_impulse[plane], impulsepic, w, h, n, plane, 1 / total); + get_input(s, s->fft_hdata_impulse[plane], impulsepic, w, h, n, plane, 1 / total); + fft_horizontal(s, s->fft_hdata_impulse[plane], n, plane); fft_vertical(s, s->fft_hdata_impulse[plane], s->fft_vdata_impulse[plane], n, plane); @@ -395,7 +409,8 @@ static int do_convolve(FFFrameSync *fs) } ifft_vertical(s, n, plane); - ifft_horizontal(s, mainpic, w, h, n, plane); + ifft_horizontal(s, n, plane); + get_output(s, mainpic, w, h, n, plane); } return ff_filter_frame(outlink, mainpic); From c59e49f9b2f30184e6d74255f3c1b2a1a89c6520 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 25 Dec 2017 11:53:54 +0100 Subject: [PATCH 1460/2557] avfilter/vf_convolve: implement slice threading Signed-off-by: Paul B Mahol --- libavfilter/vf_convolve.c | 142 +++++++++++++++++++++++++++----------- 1 file changed, 100 insertions(+), 42 deletions(-) diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c index e3d0c5fa2aea3..de58cdff8f171 100644 --- a/libavfilter/vf_convolve.c +++ b/libavfilter/vf_convolve.c @@ -29,12 +29,14 @@ #include "internal.h" #include "video.h" +#define MAX_THREADS 16 + typedef struct ConvolveContext { const AVClass *class; FFFrameSync fs; - FFTContext *fft[4]; - FFTContext *ifft[4]; + FFTContext *fft[4][MAX_THREADS]; + FFTContext *ifft[4][MAX_THREADS]; int fft_bits[4]; int fft_len[4]; @@ -152,15 +154,28 @@ static int config_input_impulse(AVFilterLink *inlink) return 0; } -static void fft_horizontal(ConvolveContext *s, FFTComplex *fft_hdata, - int n, int plane) +typedef struct ThreadData { + FFTComplex *hdata, *vdata; + int plane, n; +} ThreadData; + +static int fft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { + ConvolveContext *s = ctx->priv; + ThreadData *td = arg; + FFTComplex *hdata = td->hdata; + const int plane = td->plane; + const int n = td->n; + int start = (n * jobnr ) / nb_jobs; + int end = (n * (jobnr+1)) / nb_jobs; int y; - for (y = 0; y < n; y++) { - av_fft_permute(s->fft[plane], fft_hdata + y * n); - av_fft_calc(s->fft[plane], fft_hdata + y * n); + for (y = start; y < end; y++) { + av_fft_permute(s->fft[plane][jobnr], hdata + y * n); + av_fft_calc(s->fft[plane][jobnr], hdata + y * n); } + + return 0; } static void get_input(ConvolveContext *s, FFTComplex *fft_hdata, @@ -238,46 +253,73 @@ static void get_input(ConvolveContext *s, FFTComplex *fft_hdata, } } -static void fft_vertical(ConvolveContext *s, FFTComplex *fft_hdata, FFTComplex *fft_vdata, - int n, int plane) +static int fft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { + ConvolveContext *s = ctx->priv; + ThreadData *td = arg; + FFTComplex *hdata = td->hdata; + FFTComplex *vdata = td->vdata; + const int plane = td->plane; + const int n = td->n; + int start = (n * jobnr ) / nb_jobs; + int end = (n * (jobnr+1)) / nb_jobs; int y, x; - for (y = 0; y < n; y++) { + for (y = start; y < end; y++) { for (x = 0; x < n; x++) { - fft_vdata[y * n + x].re = fft_hdata[x * n + y].re; - fft_vdata[y * n + x].im = fft_hdata[x * n + y].im; + vdata[y * n + x].re = hdata[x * n + y].re; + vdata[y * n + x].im = hdata[x * n + y].im; } - av_fft_permute(s->fft[plane], fft_vdata + y * n); - av_fft_calc(s->fft[plane], fft_vdata + y * n); + av_fft_permute(s->fft[plane][jobnr], vdata + y * n); + av_fft_calc(s->fft[plane][jobnr], vdata + y * n); } + + return 0; } -static void ifft_vertical(ConvolveContext *s, int n, int plane) +static int ifft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { + ConvolveContext *s = ctx->priv; + ThreadData *td = arg; + FFTComplex *hdata = td->hdata; + FFTComplex *vdata = td->vdata; + const int plane = td->plane; + const int n = td->n; + int start = (n * jobnr ) / nb_jobs; + int end = (n * (jobnr+1)) / nb_jobs; int y, x; - for (y = 0; y < n; y++) { - av_fft_permute(s->ifft[plane], s->fft_vdata[plane] + y * n); - av_fft_calc(s->ifft[plane], s->fft_vdata[plane] + y * n); + for (y = start; y < end; y++) { + av_fft_permute(s->ifft[plane][jobnr], vdata + y * n); + av_fft_calc(s->ifft[plane][jobnr], vdata + y * n); for (x = 0; x < n; x++) { - s->fft_hdata[plane][x * n + y].re = s->fft_vdata[plane][y * n + x].re; - s->fft_hdata[plane][x * n + y].im = s->fft_vdata[plane][y * n + x].im; + hdata[x * n + y].re = vdata[y * n + x].re; + hdata[x * n + y].im = vdata[y * n + x].im; } } + + return 0; } -static void ifft_horizontal(ConvolveContext *s, int n, int plane) +static int ifft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - FFTComplex *input = s->fft_hdata[plane]; + ConvolveContext *s = ctx->priv; + ThreadData *td = arg; + FFTComplex *hdata = td->hdata; + const int plane = td->plane; + const int n = td->n; + int start = (n * jobnr ) / nb_jobs; + int end = (n * (jobnr+1)) / nb_jobs; int y; - for (y = 0; y < n; y++) { - av_fft_permute(s->ifft[plane], input + y * n); - av_fft_calc(s->ifft[plane], input + y * n); + for (y = start; y < end; y++) { + av_fft_permute(s->ifft[plane][jobnr], hdata + y * n); + av_fft_calc(s->ifft[plane][jobnr], hdata + y * n); } + + return 0; } static void get_output(ConvolveContext *s, AVFrame *out, @@ -356,15 +398,20 @@ static int do_convolve(FFFrameSync *fs) const int w = s->planewidth[plane]; const int h = s->planeheight[plane]; float total = 0; + ThreadData td; if (!(s->planes & (1 << plane))) { continue; } + td.plane = plane, td.n = n; get_input(s, s->fft_hdata[plane], mainpic, w, h, n, plane, 1.f); - fft_horizontal(s, s->fft_hdata[plane], n, plane); - fft_vertical(s, s->fft_hdata[plane], s->fft_vdata[plane], - n, plane); + + td.hdata = s->fft_hdata[plane]; + td.vdata = s->fft_vdata[plane]; + + ctx->internal->execute(ctx, fft_horizontal, &td, NULL, FFMIN3(MAX_THREADS, n, ff_filter_get_nb_threads(ctx))); + ctx->internal->execute(ctx, fft_vertical, &td, NULL, FFMIN3(MAX_THREADS, n, ff_filter_get_nb_threads(ctx))); if ((!s->impulse && !s->got_impulse[plane]) || s->impulse) { if (s->depth == 8) { @@ -385,9 +432,12 @@ static int do_convolve(FFFrameSync *fs) total = FFMAX(1, total); get_input(s, s->fft_hdata_impulse[plane], impulsepic, w, h, n, plane, 1 / total); - fft_horizontal(s, s->fft_hdata_impulse[plane], n, plane); - fft_vertical(s, s->fft_hdata_impulse[plane], s->fft_vdata_impulse[plane], - n, plane); + + td.hdata = s->fft_hdata_impulse[plane]; + td.vdata = s->fft_vdata_impulse[plane]; + + ctx->internal->execute(ctx, fft_horizontal, &td, NULL, FFMIN3(MAX_THREADS, n, ff_filter_get_nb_threads(ctx))); + ctx->internal->execute(ctx, fft_vertical, &td, NULL, FFMIN3(MAX_THREADS, n, ff_filter_get_nb_threads(ctx))); s->got_impulse[plane] = 1; } @@ -408,8 +458,11 @@ static int do_convolve(FFFrameSync *fs) } } - ifft_vertical(s, n, plane); - ifft_horizontal(s, n, plane); + td.hdata = s->fft_hdata[plane]; + td.vdata = s->fft_vdata[plane]; + + ctx->internal->execute(ctx, ifft_vertical, &td, NULL, FFMIN3(MAX_THREADS, n, ff_filter_get_nb_threads(ctx))); + ctx->internal->execute(ctx, ifft_horizontal, &td, NULL, FFMIN3(MAX_THREADS, n, ff_filter_get_nb_threads(ctx))); get_output(s, mainpic, w, h, n, plane); } @@ -421,7 +474,7 @@ static int config_output(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; ConvolveContext *s = ctx->priv; AVFilterLink *mainlink = ctx->inputs[0]; - int ret, i; + int ret, i, j; s->fs.on_event = do_convolve; ret = ff_framesync_init_dualinput(&s->fs, ctx); @@ -437,10 +490,12 @@ static int config_output(AVFilterLink *outlink) return ret; for (i = 0; i < s->nb_planes; i++) { - s->fft[i] = av_fft_init(s->fft_bits[i], 0); - s->ifft[i] = av_fft_init(s->fft_bits[i], 1); - if (!s->fft[i] || !s->ifft[i]) - return AVERROR(ENOMEM); + for (j = 0; j < MAX_THREADS; j++) { + s->fft[i][j] = av_fft_init(s->fft_bits[i], 0); + s->ifft[i][j] = av_fft_init(s->fft_bits[i], 1); + if (!s->fft[i][j] || !s->ifft[i][j]) + return AVERROR(ENOMEM); + } } return 0; @@ -455,15 +510,18 @@ static int activate(AVFilterContext *ctx) static av_cold void uninit(AVFilterContext *ctx) { ConvolveContext *s = ctx->priv; - int i; + int i, j; for (i = 0; i < 4; i++) { av_freep(&s->fft_hdata[i]); av_freep(&s->fft_vdata[i]); av_freep(&s->fft_hdata_impulse[i]); av_freep(&s->fft_vdata_impulse[i]); - av_fft_end(s->fft[i]); - av_fft_end(s->ifft[i]); + + for (j = 0; j < MAX_THREADS; j++) { + av_fft_end(s->fft[i][j]); + av_fft_end(s->ifft[i][j]); + } } ff_framesync_uninit(&s->fs); @@ -502,5 +560,5 @@ AVFilter ff_vf_convolve = { .priv_class = &convolve_class, .inputs = convolve_inputs, .outputs = convolve_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, }; From e712d301736106002264d631cff925a92dfe891d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 25 Dec 2017 15:46:04 +0100 Subject: [PATCH 1461/2557] avfilter/vf_convolve: add threading for complex multiplication Signed-off-by: Paul B Mahol --- libavfilter/vf_convolve.c | 46 +++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c index de58cdff8f171..88ae884a19578 100644 --- a/libavfilter/vf_convolve.c +++ b/libavfilter/vf_convolve.c @@ -377,6 +377,35 @@ static void get_output(ConvolveContext *s, AVFrame *out, } } +static int complex_multiply(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ThreadData *td = arg; + FFTComplex *input = td->hdata; + FFTComplex *filter = td->vdata; + const int n = td->n; + int start = (n * jobnr ) / nb_jobs; + int end = (n * (jobnr+1)) / nb_jobs; + int y, x; + + for (y = start; y < end; y++) { + int yn = y * n; + + for (x = 0; x < n; x++) { + FFTSample re, im, ire, iim; + + re = input[yn + x].re; + im = input[yn + x].im; + ire = filter[yn + x].re; + iim = filter[yn + x].im; + + input[yn + x].re = ire * re - iim * im; + input[yn + x].im = iim * re + ire * im; + } + } + + return 0; +} + static int do_convolve(FFFrameSync *fs) { AVFilterContext *ctx = fs->parent; @@ -442,21 +471,10 @@ static int do_convolve(FFFrameSync *fs) s->got_impulse[plane] = 1; } - for (y = 0; y < n; y++) { - int yn = y * n; + td.hdata = input; + td.vdata = filter; - for (x = 0; x < n; x++) { - FFTSample re, im, ire, iim; - - re = input[yn + x].re; - im = input[yn + x].im; - ire = filter[yn + x].re; - iim = filter[yn + x].im; - - input[yn + x].re = ire * re - iim * im; - input[yn + x].im = iim * re + ire * im; - } - } + ctx->internal->execute(ctx, complex_multiply, &td, NULL, FFMIN3(MAX_THREADS, n, ff_filter_get_nb_threads(ctx))); td.hdata = s->fft_hdata[plane]; td.vdata = s->fft_vdata[plane]; From 2aee5a87233277027bb281372f888b5246a58e77 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 25 Dec 2017 23:51:25 +0800 Subject: [PATCH 1462/2557] avformat/hlsenc: fix resource leak fix CID: 1426931 1426929 --- libavformat/hlsenc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index b850b1a320549..74f66ce6bdd87 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1899,11 +1899,13 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", vs->avf->filename); + av_free(old_filename); return ret; } write_styp(vs->out); ret = flush_dynbuf(vs, &range_length); if (ret < 0) { + av_free(old_filename); return ret; } ff_format_io_close(s, &vs->out); @@ -1979,16 +1981,17 @@ static int hls_write_trailer(struct AVFormatContext *s) ret = hlsenc_io_open(s, &vs->out, vs->avf->filename, NULL); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", vs->avf->filename); - return AVERROR(ENOENT); + goto failed; } write_styp(vs->out); ret = flush_dynbuf(vs, &range_length); if (ret < 0) { - return ret; + goto failed; } ff_format_io_close(s, &vs->out); } +failed: av_write_trailer(oc); if (oc->pb) { vs->size = avio_tell(vs->avf->pb) - vs->start_pos; From 9b121dfc32810250938021952aab4172a988cb56 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 21 Dec 2017 20:23:14 +0100 Subject: [PATCH 1463/2557] w32pthreads: always use Vista+ API, drop XP support This removes the XP compatibility code, and switches entirely to SWR locks, which are available starting at Windows Vista. This removes CRITICAL_SECTION use, which allows us to add PTHREAD_MUTEX_INITIALIZER, which will be useful later. Windows XP is hereby not a supported build target anymore. It was decided in a project vote that this is OK. --- Changelog | 2 + compat/w32pthreads.h | 266 ++----------------------------------- configure | 13 +- libavcodec/pthread_frame.c | 4 - libavcodec/pthread_slice.c | 4 - libavfilter/pthread.c | 4 - libavutil/slicethread.c | 4 - 7 files changed, 19 insertions(+), 278 deletions(-) diff --git a/Changelog b/Changelog index f44cec679f493..2ebdf00ff199c 100644 --- a/Changelog +++ b/Changelog @@ -28,6 +28,8 @@ version : - nsp demuxer - support LibreSSL (via libtls) - AVX-512/ZMM support added +- Dropped support for building for Windows XP. The minimum supported Windows + version is Windows Vista. version 3.4: diff --git a/compat/w32pthreads.h b/compat/w32pthreads.h index eeead6051f2da..237cab5677247 100644 --- a/compat/w32pthreads.h +++ b/compat/w32pthreads.h @@ -56,19 +56,12 @@ typedef struct pthread_t { void *ret; } pthread_t; -/* the conditional variable api for windows 6.0+ uses critical sections and - * not mutexes */ -typedef CRITICAL_SECTION pthread_mutex_t; - -/* This is the CONDITION_VARIABLE typedef for using Windows' native - * conditional variables on kernels 6.0+. */ -#if HAVE_CONDITION_VARIABLE_PTR +/* use light weight mutex/condition variable API for Windows Vista and later */ +typedef SRWLOCK pthread_mutex_t; typedef CONDITION_VARIABLE pthread_cond_t; -#else -typedef struct pthread_cond_t { - void *Ptr; -} pthread_cond_t; -#endif + +#define PTHREAD_MUTEX_INITIALIZER SRWLOCK_INIT +#define PTHREAD_COND_INITIALIZER CONDITION_VARIABLE_INIT #if _WIN32_WINNT >= 0x0600 #define InitializeCriticalSection(x) InitializeCriticalSectionEx(x, 0, 0) @@ -114,26 +107,25 @@ static av_unused int pthread_join(pthread_t thread, void **value_ptr) static inline int pthread_mutex_init(pthread_mutex_t *m, void* attr) { - InitializeCriticalSection(m); + InitializeSRWLock(m); return 0; } static inline int pthread_mutex_destroy(pthread_mutex_t *m) { - DeleteCriticalSection(m); + /* Unlocked SWR locks use no resources */ return 0; } static inline int pthread_mutex_lock(pthread_mutex_t *m) { - EnterCriticalSection(m); + AcquireSRWLockExclusive(m); return 0; } static inline int pthread_mutex_unlock(pthread_mutex_t *m) { - LeaveCriticalSection(m); + ReleaseSRWLockExclusive(m); return 0; } -#if _WIN32_WINNT >= 0x0600 typedef INIT_ONCE pthread_once_t; #define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT @@ -167,7 +159,7 @@ static inline int pthread_cond_broadcast(pthread_cond_t *cond) static inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { - SleepConditionVariableCS(cond, mutex, INFINITE); + SleepConditionVariableSRW(cond, mutex, INFINITE, 0); return 0; } @@ -177,242 +169,4 @@ static inline int pthread_cond_signal(pthread_cond_t *cond) return 0; } -#else // _WIN32_WINNT < 0x0600 - -/* atomic init state of dynamically loaded functions */ -static LONG w32thread_init_state = 0; -static av_unused void w32thread_init(void); - -/* for pre-Windows 6.0 platforms, define INIT_ONCE struct, - * compatible to the one used in the native API */ - -typedef union pthread_once_t { - void * Ptr; ///< For the Windows 6.0+ native functions - LONG state; ///< For the pre-Windows 6.0 compat code -} pthread_once_t; - -#define PTHREAD_ONCE_INIT {0} - -/* function pointers to init once API on windows 6.0+ kernels */ -static BOOL (WINAPI *initonce_begin)(pthread_once_t *lpInitOnce, DWORD dwFlags, BOOL *fPending, void **lpContext); -static BOOL (WINAPI *initonce_complete)(pthread_once_t *lpInitOnce, DWORD dwFlags, void *lpContext); - -/* pre-Windows 6.0 compat using a spin-lock */ -static inline void w32thread_once_fallback(LONG volatile *state, void (*init_routine)(void)) -{ - switch (InterlockedCompareExchange(state, 1, 0)) { - /* Initial run */ - case 0: - init_routine(); - InterlockedExchange(state, 2); - break; - /* Another thread is running init */ - case 1: - while (1) { - MemoryBarrier(); - if (*state == 2) - break; - Sleep(0); - } - break; - /* Initialization complete */ - case 2: - break; - } -} - -static av_unused int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) -{ - w32thread_once_fallback(&w32thread_init_state, w32thread_init); - - /* Use native functions on Windows 6.0+ */ - if (initonce_begin && initonce_complete) { - BOOL pending = FALSE; - initonce_begin(once_control, 0, &pending, NULL); - if (pending) - init_routine(); - initonce_complete(once_control, 0, NULL); - return 0; - } - - w32thread_once_fallback(&once_control->state, init_routine); - return 0; -} - -/* for pre-Windows 6.0 platforms we need to define and use our own condition - * variable and api */ - -typedef struct win32_cond_t { - pthread_mutex_t mtx_broadcast; - pthread_mutex_t mtx_waiter_count; - volatile int waiter_count; - HANDLE semaphore; - HANDLE waiters_done; - volatile int is_broadcast; -} win32_cond_t; - -/* function pointers to conditional variable API on windows 6.0+ kernels */ -static void (WINAPI *cond_broadcast)(pthread_cond_t *cond); -static void (WINAPI *cond_init)(pthread_cond_t *cond); -static void (WINAPI *cond_signal)(pthread_cond_t *cond); -static BOOL (WINAPI *cond_wait)(pthread_cond_t *cond, pthread_mutex_t *mutex, - DWORD milliseconds); - -static av_unused int pthread_cond_init(pthread_cond_t *cond, const void *unused_attr) -{ - win32_cond_t *win32_cond = NULL; - - w32thread_once_fallback(&w32thread_init_state, w32thread_init); - - if (cond_init) { - cond_init(cond); - return 0; - } - - /* non native condition variables */ - win32_cond = (win32_cond_t*)av_mallocz(sizeof(win32_cond_t)); - if (!win32_cond) - return ENOMEM; - cond->Ptr = win32_cond; - win32_cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); - if (!win32_cond->semaphore) - return ENOMEM; - win32_cond->waiters_done = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!win32_cond->waiters_done) - return ENOMEM; - - pthread_mutex_init(&win32_cond->mtx_waiter_count, NULL); - pthread_mutex_init(&win32_cond->mtx_broadcast, NULL); - return 0; -} - -static av_unused int pthread_cond_destroy(pthread_cond_t *cond) -{ - win32_cond_t *win32_cond = (win32_cond_t*)cond->Ptr; - /* native condition variables do not destroy */ - if (cond_init) - return 0; - - /* non native condition variables */ - CloseHandle(win32_cond->semaphore); - CloseHandle(win32_cond->waiters_done); - pthread_mutex_destroy(&win32_cond->mtx_waiter_count); - pthread_mutex_destroy(&win32_cond->mtx_broadcast); - av_freep(&win32_cond); - cond->Ptr = NULL; - return 0; -} - -static av_unused int pthread_cond_broadcast(pthread_cond_t *cond) -{ - win32_cond_t *win32_cond = (win32_cond_t*)cond->Ptr; - int have_waiter; - - if (cond_broadcast) { - cond_broadcast(cond); - return 0; - } - - /* non native condition variables */ - pthread_mutex_lock(&win32_cond->mtx_broadcast); - pthread_mutex_lock(&win32_cond->mtx_waiter_count); - have_waiter = 0; - - if (win32_cond->waiter_count) { - win32_cond->is_broadcast = 1; - have_waiter = 1; - } - - if (have_waiter) { - ReleaseSemaphore(win32_cond->semaphore, win32_cond->waiter_count, NULL); - pthread_mutex_unlock(&win32_cond->mtx_waiter_count); - WaitForSingleObject(win32_cond->waiters_done, INFINITE); - ResetEvent(win32_cond->waiters_done); - win32_cond->is_broadcast = 0; - } else - pthread_mutex_unlock(&win32_cond->mtx_waiter_count); - pthread_mutex_unlock(&win32_cond->mtx_broadcast); - return 0; -} - -static av_unused int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) -{ - win32_cond_t *win32_cond = (win32_cond_t*)cond->Ptr; - int last_waiter; - if (cond_wait) { - cond_wait(cond, mutex, INFINITE); - return 0; - } - - /* non native condition variables */ - pthread_mutex_lock(&win32_cond->mtx_broadcast); - pthread_mutex_lock(&win32_cond->mtx_waiter_count); - win32_cond->waiter_count++; - pthread_mutex_unlock(&win32_cond->mtx_waiter_count); - pthread_mutex_unlock(&win32_cond->mtx_broadcast); - - // unlock the external mutex - pthread_mutex_unlock(mutex); - WaitForSingleObject(win32_cond->semaphore, INFINITE); - - pthread_mutex_lock(&win32_cond->mtx_waiter_count); - win32_cond->waiter_count--; - last_waiter = !win32_cond->waiter_count || !win32_cond->is_broadcast; - pthread_mutex_unlock(&win32_cond->mtx_waiter_count); - - if (last_waiter) - SetEvent(win32_cond->waiters_done); - - // lock the external mutex - return pthread_mutex_lock(mutex); -} - -static av_unused int pthread_cond_signal(pthread_cond_t *cond) -{ - win32_cond_t *win32_cond = (win32_cond_t*)cond->Ptr; - int have_waiter; - if (cond_signal) { - cond_signal(cond); - return 0; - } - - pthread_mutex_lock(&win32_cond->mtx_broadcast); - - /* non-native condition variables */ - pthread_mutex_lock(&win32_cond->mtx_waiter_count); - have_waiter = win32_cond->waiter_count; - pthread_mutex_unlock(&win32_cond->mtx_waiter_count); - - if (have_waiter) { - ReleaseSemaphore(win32_cond->semaphore, 1, NULL); - WaitForSingleObject(win32_cond->waiters_done, INFINITE); - ResetEvent(win32_cond->waiters_done); - } - - pthread_mutex_unlock(&win32_cond->mtx_broadcast); - return 0; -} -#endif - -static av_unused void w32thread_init(void) -{ -#if _WIN32_WINNT < 0x0600 - HMODULE kernel_dll = GetModuleHandle(TEXT("kernel32.dll")); - /* if one is available, then they should all be available */ - cond_init = (void (WINAPI*)(pthread_cond_t *)) - GetProcAddress(kernel_dll, "InitializeConditionVariable"); - cond_broadcast = (void (WINAPI*)(pthread_cond_t *)) - GetProcAddress(kernel_dll, "WakeAllConditionVariable"); - cond_signal = (void (WINAPI*)(pthread_cond_t *)) - GetProcAddress(kernel_dll, "WakeConditionVariable"); - cond_wait = (BOOL (WINAPI*)(pthread_cond_t *, pthread_mutex_t *, DWORD)) - GetProcAddress(kernel_dll, "SleepConditionVariableCS"); - initonce_begin = (BOOL (WINAPI*)(pthread_once_t *, DWORD, BOOL *, void **)) - GetProcAddress(kernel_dll, "InitOnceBeginInitialize"); - initonce_complete = (BOOL (WINAPI*)(pthread_once_t *, DWORD, void *)) - GetProcAddress(kernel_dll, "InitOnceComplete"); -#endif - -} - #endif /* COMPAT_W32PTHREADS_H */ diff --git a/configure b/configure index d3187d71eda3b..19a0f310cff55 100755 --- a/configure +++ b/configure @@ -2092,7 +2092,6 @@ TOOLCHAIN_FEATURES=" " TYPES_LIST=" - CONDITION_VARIABLE_Ptr kCMVideoCodecType_HEVC socklen_t struct_addrinfo @@ -5159,6 +5158,8 @@ probe_libc(){ add_${pfx}cppflags -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO=1 eval test \$${pfx_no_}cc_type = "gcc" && add_${pfx}cppflags -D__printf__=__gnu_printf__ + check_${pfx}cpp_condition windows.h "!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600" && + add_${pfx}cppflags -D_WIN32_WINNT=0x0600 elif check_${pfx}cpp_condition _mingw.h "defined __MINGW_VERSION" || check_${pfx}cpp_condition _mingw.h "defined __MINGW32_VERSION"; then eval ${pfx}libc_type=mingw32 @@ -5168,8 +5169,8 @@ probe_libc(){ add_${pfx}cppflags -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO=1 check_${pfx}cpp_condition _mingw.h "__MSVCRT_VERSION__ < 0x0700" && add_${pfx}cppflags -D__MSVCRT_VERSION__=0x0700 - check_${pfx}cpp_condition windows.h "defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0502" && - add_${pfx}cppflags -D_WIN32_WINNT=0x0502 + check_${pfx}cpp_condition windows.h "!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600" && + add_${pfx}cppflags -D_WIN32_WINNT=0x0600 eval test \$${pfx_no_}cc_type = "gcc" && add_${pfx}cppflags -D__printf__=__gnu_printf__ elif check_${pfx}cpp_condition crtversion.h "defined _VC_CRT_MAJOR_VERSION"; then @@ -5189,14 +5190,14 @@ probe_libc(){ # 0x601 by default unless something else is set by the user. # This can easily lead to us detecting functions only present # in such new versions and producing binaries requiring windows 7.0. - # Therefore explicitly set the default to XP unless the user has + # Therefore explicitly set the default to Vista unless the user has # set something else on the command line. # Don't do this if WINAPI_FAMILY is set and is set to a non-desktop # family. For these cases, configure is free to use any functions # found in the SDK headers by default. (Alternatively, we could force # _WIN32_WINNT to 0x0602 in that case.) check_${pfx}cpp_condition stdlib.h "defined(_WIN32_WINNT)" || - { check_${pfx}cpp < #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) @@ -5674,7 +5675,6 @@ check_func_headers windows.h SetConsoleTextAttribute check_func_headers windows.h SetConsoleCtrlHandler check_func_headers windows.h Sleep check_func_headers windows.h VirtualAlloc -check_struct windows.h "CONDITION_VARIABLE" Ptr check_func_headers glob.h glob enabled xlib && check_func_headers "X11/Xlib.h X11/extensions/Xvlib.h" XvGetPortAttribute -lXv -lX11 -lXext @@ -5758,6 +5758,7 @@ check_cpp_condition windows.h "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP if ! disabled w32threads && ! enabled pthreads; then check_func_headers "windows.h process.h" _beginthreadex && + check_type "windows.h" CONDITION_VARIABLE && enable w32threads || disable w32threads if ! enabled w32threads && enabled winrt; then check_func_headers "windows.h" CreateThread && diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index e6e6d1f599cb6..25aa3e2cd22c9 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -728,10 +728,6 @@ int ff_frame_thread_init(AVCodecContext *avctx) FrameThreadContext *fctx; int i, err = 0; -#if HAVE_W32THREADS - w32thread_init(); -#endif - if (!thread_count) { int nb_cpus = av_cpu_count(); #if FF_API_DEBUG_MV diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c index d659f9b0ba809..77cfe3c9f69b7 100644 --- a/libavcodec/pthread_slice.c +++ b/libavcodec/pthread_slice.c @@ -132,10 +132,6 @@ int ff_slice_thread_init(AVCodecContext *avctx) int thread_count = avctx->thread_count; static void (*mainfunc)(void *); -#if HAVE_W32THREADS - w32thread_init(); -#endif - // We cannot do this in the encoder init as the threads are created before if (av_codec_is_encoder(avctx->codec) && avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO && diff --git a/libavfilter/pthread.c b/libavfilter/pthread.c index 567dd4c178c93..7e37c73ca34a6 100644 --- a/libavfilter/pthread.c +++ b/libavfilter/pthread.c @@ -85,10 +85,6 @@ int ff_graph_thread_init(AVFilterGraph *graph) { int ret; -#if HAVE_W32THREADS - w32thread_init(); -#endif - if (graph->nb_threads == 1) { graph->thread_type = 0; return 0; diff --git a/libavutil/slicethread.c b/libavutil/slicethread.c index c43f87a2aa4aa..dfbe551ef2062 100644 --- a/libavutil/slicethread.c +++ b/libavutil/slicethread.c @@ -99,10 +99,6 @@ int avpriv_slicethread_create(AVSliceThread **pctx, void *priv, AVSliceThread *ctx; int nb_workers, i; -#if HAVE_W32THREADS - w32thread_init(); -#endif - av_assert0(nb_threads >= 0); if (!nb_threads) { int nb_cpus = av_cpu_count(); From a04c2c707de2ce850f79870e84ac9d7ec7aa9143 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 21 Dec 2017 22:39:24 +0100 Subject: [PATCH 1464/2557] lavc: replace and deprecate the lock manager Use static mutexes instead of requiring a lock manager. The behavior should be roughly the same before and after this change for API users which did not set the lock manager at all (except that a minor memory leak disappears). --- doc/APIchanges | 5 ++ libavcodec/avcodec.h | 8 +++- libavcodec/utils.c | 107 ++++--------------------------------------- libavcodec/version.h | 5 +- libavutil/thread.h | 2 + 5 files changed, 28 insertions(+), 99 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index df79758e863f3..3c9f237596e7b 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,11 @@ libavutil: 2017-10-21 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavc 58.9.100 - avcodec.h + Deprecate av_lockmgr_register(). You need to build FFmpeg with threading + support enabled to get basic thread-safety (which is the default build + configuration). + 2017-12-xx - xxxxxxx - lavu 56.7.100 - cpu.h AVX-512 flags added. diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index ce089b7c4ab04..a9182a9e3daa1 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -5930,10 +5930,11 @@ attribute_deprecated AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel); #endif - +#if FF_API_LOCKMGR /** * Lock operation used by lockmgr */ +attribute_deprecated enum AVLockOp { AV_LOCK_CREATE, ///< Create a mutex AV_LOCK_OBTAIN, ///< Lock the mutex @@ -5963,8 +5964,13 @@ enum AVLockOp { * mechanism (i.e. do not use a single static object to * implement your lock manager). If cb is set to NULL the * lockmgr will be unregistered. + * + * @deprecated This function does nothing, and always returns 0. Be sure to + * build with thread support to get basic thread safety. */ +attribute_deprecated int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)); +#endif /** * Get the type of the given codec. diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 873f39f9bda4f..eec4437693563 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -67,58 +67,10 @@ #include "libavutil/ffversion.h" const char av_codec_ffversion[] = "FFmpeg version " FFMPEG_VERSION; -#if HAVE_PTHREADS || HAVE_W32THREADS || HAVE_OS2THREADS -static int default_lockmgr_cb(void **arg, enum AVLockOp op) -{ - void * volatile * mutex = arg; - int err; - - switch (op) { - case AV_LOCK_CREATE: - return 0; - case AV_LOCK_OBTAIN: - if (!*mutex) { - pthread_mutex_t *tmp = av_malloc(sizeof(pthread_mutex_t)); - if (!tmp) - return AVERROR(ENOMEM); - if ((err = pthread_mutex_init(tmp, NULL))) { - av_free(tmp); - return AVERROR(err); - } - if (avpriv_atomic_ptr_cas(mutex, NULL, tmp)) { - pthread_mutex_destroy(tmp); - av_free(tmp); - } - } - - if ((err = pthread_mutex_lock(*mutex))) - return AVERROR(err); - - return 0; - case AV_LOCK_RELEASE: - if ((err = pthread_mutex_unlock(*mutex))) - return AVERROR(err); - - return 0; - case AV_LOCK_DESTROY: - if (*mutex) - pthread_mutex_destroy(*mutex); - av_free(*mutex); - avpriv_atomic_ptr_cas(mutex, *mutex, NULL); - return 0; - } - return 1; -} -static int (*lockmgr_cb)(void **mutex, enum AVLockOp op) = default_lockmgr_cb; -#else -static int (*lockmgr_cb)(void **mutex, enum AVLockOp op) = NULL; -#endif - - volatile int ff_avcodec_locked; static atomic_int entangled_thread_counter = ATOMIC_VAR_INIT(0); -static void *codec_mutex; -static void *avformat_mutex; +static AVMutex codec_mutex = AV_MUTEX_INITIALIZER; +static AVMutex avformat_mutex = AV_MUTEX_INITIALIZER; void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size) { @@ -1909,55 +1861,26 @@ void av_register_hwaccel(AVHWAccel *hwaccel) } #endif +#if FF_API_LOCKMGR int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) { - if (lockmgr_cb) { - // There is no good way to rollback a failure to destroy the - // mutex, so we ignore failures. - lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY); - lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY); - lockmgr_cb = NULL; - codec_mutex = NULL; - avformat_mutex = NULL; - } - - if (cb) { - void *new_codec_mutex = NULL; - void *new_avformat_mutex = NULL; - int err; - if (err = cb(&new_codec_mutex, AV_LOCK_CREATE)) { - return err > 0 ? AVERROR_UNKNOWN : err; - } - if (err = cb(&new_avformat_mutex, AV_LOCK_CREATE)) { - // Ignore failures to destroy the newly created mutex. - cb(&new_codec_mutex, AV_LOCK_DESTROY); - return err > 0 ? AVERROR_UNKNOWN : err; - } - lockmgr_cb = cb; - codec_mutex = new_codec_mutex; - avformat_mutex = new_avformat_mutex; - } - return 0; } +#endif int ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec) { if (codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE || !codec->init) return 0; - if (lockmgr_cb) { - if ((*lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN)) - return -1; - } + if (ff_mutex_lock(&codec_mutex)) + return -1; if (atomic_fetch_add(&entangled_thread_counter, 1)) { av_log(log_ctx, AV_LOG_ERROR, "Insufficient thread locking. At least %d threads are " "calling avcodec_open2() at the same time right now.\n", atomic_load(&entangled_thread_counter)); - if (!lockmgr_cb) - av_log(log_ctx, AV_LOG_ERROR, "No lock manager is set, please see av_lockmgr_register()\n"); ff_avcodec_locked = 1; ff_unlock_avcodec(codec); return AVERROR(EINVAL); @@ -1975,30 +1898,20 @@ int ff_unlock_avcodec(const AVCodec *codec) av_assert0(ff_avcodec_locked); ff_avcodec_locked = 0; atomic_fetch_add(&entangled_thread_counter, -1); - if (lockmgr_cb) { - if ((*lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE)) - return -1; - } + if (ff_mutex_unlock(&codec_mutex)) + return -1; return 0; } int avpriv_lock_avformat(void) { - if (lockmgr_cb) { - if ((*lockmgr_cb)(&avformat_mutex, AV_LOCK_OBTAIN)) - return -1; - } - return 0; + return ff_mutex_lock(&avformat_mutex) ? -1 : 0; } int avpriv_unlock_avformat(void) { - if (lockmgr_cb) { - if ((*lockmgr_cb)(&avformat_mutex, AV_LOCK_RELEASE)) - return -1; - } - return 0; + return ff_mutex_unlock(&avformat_mutex) ? -1 : 0; } unsigned int avpriv_toupper4(unsigned int x) diff --git a/libavcodec/version.h b/libavcodec/version.h index d55de897972d7..47a15d52b8f09 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 8 +#define LIBAVCODEC_VERSION_MINOR 9 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ @@ -126,6 +126,9 @@ #ifndef FF_API_USER_VISIBLE_AVHWACCEL #define FF_API_USER_VISIBLE_AVHWACCEL (LIBAVCODEC_VERSION_MAJOR < 59) #endif +#ifndef FF_API_LOCKMGR +#define FF_API_LOCKMGR (LIBAVCODEC_VERSION_MAJOR < 59) +#endif #endif /* AVCODEC_VERSION_H */ diff --git a/libavutil/thread.h b/libavutil/thread.h index 309414aa7dd82..cc5272d379345 100644 --- a/libavutil/thread.h +++ b/libavutil/thread.h @@ -134,6 +134,7 @@ static inline int strict_pthread_once(pthread_once_t *once_control, void (*init_ #endif #define AVMutex pthread_mutex_t +#define AV_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER #define ff_mutex_init pthread_mutex_init #define ff_mutex_lock pthread_mutex_lock @@ -148,6 +149,7 @@ static inline int strict_pthread_once(pthread_once_t *once_control, void (*init_ #else #define AVMutex char +#define AV_MUTEX_INITIALIZER 0 static inline int ff_mutex_init(AVMutex *mutex, const void *attr){ return 0; } static inline int ff_mutex_lock(AVMutex *mutex){ return 0; } From e24f192a9fd6013e272df1bfaeaba31e8ca49f92 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 21 Dec 2017 22:43:43 +0100 Subject: [PATCH 1465/2557] ffplay: drop lock manager use Deprecated and useless. --- fftools/ffplay.c | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 10a917194db31..9bfa3e6ceabd3 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -1284,7 +1284,6 @@ static void do_exit(VideoState *is) SDL_DestroyRenderer(renderer); if (window) SDL_DestroyWindow(window); - av_lockmgr_register(NULL); uninit_opts(); #if CONFIG_AVFILTER av_freep(&vfilters_list); @@ -3641,27 +3640,6 @@ void show_help_default(const char *opt, const char *arg) ); } -static int lockmgr(void **mtx, enum AVLockOp op) -{ - switch(op) { - case AV_LOCK_CREATE: - *mtx = SDL_CreateMutex(); - if(!*mtx) { - av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); - return 1; - } - return 0; - case AV_LOCK_OBTAIN: - return !!SDL_LockMutex(*mtx); - case AV_LOCK_RELEASE: - return !!SDL_UnlockMutex(*mtx); - case AV_LOCK_DESTROY: - SDL_DestroyMutex(*mtx); - return 0; - } - return 1; -} - /* Called from the main */ int main(int argc, char **argv) { @@ -3723,11 +3701,6 @@ int main(int argc, char **argv) SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE); SDL_EventState(SDL_USEREVENT, SDL_IGNORE); - if (av_lockmgr_register(lockmgr)) { - av_log(NULL, AV_LOG_FATAL, "Could not initialize lock manager!\n"); - do_exit(NULL); - } - av_init_packet(&flush_pkt); flush_pkt.data = (uint8_t *)&flush_pkt; From 86a13bf2ffb40d44260d5747a4782a42a43a1ed8 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 21 Dec 2017 22:54:06 +0100 Subject: [PATCH 1466/2557] lavc, lavf: move avformat static mutex from avcodec to avformat It's completely absurd that libavcodec would care about libavformat locking, but it was there because the lock manager was in libavcodec. This is more stright forward. Changes ABI, but we don't require ABI compatibility currently. --- libavcodec/internal.h | 3 --- libavcodec/utils.c | 11 ----------- libavformat/avisynth.c | 10 +++++----- libavformat/chromaprint.c | 9 +++++---- libavformat/internal.h | 4 ++++ libavformat/tls_gnutls.c | 8 ++++---- libavformat/tls_openssl.c | 10 +++++----- libavformat/utils.c | 13 +++++++++++++ 8 files changed, 36 insertions(+), 32 deletions(-) diff --git a/libavcodec/internal.h b/libavcodec/internal.h index fcbdb6c04d61e..30614bb2b177e 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -247,9 +247,6 @@ extern volatile int ff_avcodec_locked; int ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec); int ff_unlock_avcodec(const AVCodec *codec); -int avpriv_lock_avformat(void); -int avpriv_unlock_avformat(void); - /** * Maximum size in bytes of extradata. * This value was chosen such that every bit of the buffer is diff --git a/libavcodec/utils.c b/libavcodec/utils.c index eec4437693563..9c631c4fb03da 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -70,7 +70,6 @@ const char av_codec_ffversion[] = "FFmpeg version " FFMPEG_VERSION; volatile int ff_avcodec_locked; static atomic_int entangled_thread_counter = ATOMIC_VAR_INIT(0); static AVMutex codec_mutex = AV_MUTEX_INITIALIZER; -static AVMutex avformat_mutex = AV_MUTEX_INITIALIZER; void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size) { @@ -1904,16 +1903,6 @@ int ff_unlock_avcodec(const AVCodec *codec) return 0; } -int avpriv_lock_avformat(void) -{ - return ff_mutex_lock(&avformat_mutex) ? -1 : 0; -} - -int avpriv_unlock_avformat(void) -{ - return ff_mutex_unlock(&avformat_mutex) ? -1 : 0; -} - unsigned int avpriv_toupper4(unsigned int x) { return av_toupper(x & 0xFF) + diff --git a/libavformat/avisynth.c b/libavformat/avisynth.c index 56700288f77be..250a489321edc 100644 --- a/libavformat/avisynth.c +++ b/libavformat/avisynth.c @@ -774,15 +774,15 @@ static av_cold int avisynth_read_header(AVFormatContext *s) int ret; // Calling library must implement a lock for thread-safe opens. - if (ret = avpriv_lock_avformat()) + if (ret = ff_lock_avformat()) return ret; if (ret = avisynth_open_file(s)) { - avpriv_unlock_avformat(); + ff_unlock_avformat(); return ret; } - avpriv_unlock_avformat(); + ff_unlock_avformat(); return 0; } @@ -818,11 +818,11 @@ static int avisynth_read_packet(AVFormatContext *s, AVPacket *pkt) static av_cold int avisynth_read_close(AVFormatContext *s) { - if (avpriv_lock_avformat()) + if (ff_lock_avformat()) return AVERROR_UNKNOWN; avisynth_context_destroy(s->priv_data); - avpriv_unlock_avformat(); + ff_unlock_avformat(); return 0; } diff --git a/libavformat/chromaprint.c b/libavformat/chromaprint.c index 4da02bef7622e..f39c09ddb92b9 100644 --- a/libavformat/chromaprint.c +++ b/libavformat/chromaprint.c @@ -20,6 +20,7 @@ */ #include "avformat.h" +#include "internal.h" #include "libavutil/opt.h" #include "libavcodec/internal.h" #include @@ -49,9 +50,9 @@ typedef struct ChromaprintMuxContext { static void cleanup(ChromaprintMuxContext *cpr) { if (cpr->ctx) { - avpriv_lock_avformat(); + ff_lock_avformat(); chromaprint_free(cpr->ctx); - avpriv_unlock_avformat(); + ff_unlock_avformat(); } } @@ -60,9 +61,9 @@ static int write_header(AVFormatContext *s) ChromaprintMuxContext *cpr = s->priv_data; AVStream *st; - avpriv_lock_avformat(); + ff_lock_avformat(); cpr->ctx = chromaprint_new(cpr->algorithm); - avpriv_unlock_avformat(); + ff_unlock_avformat(); if (!cpr->ctx) { av_log(s, AV_LOG_ERROR, "Failed to create chromaprint context.\n"); diff --git a/libavformat/internal.h b/libavformat/internal.h index e76ac12371d78..30715b3f500eb 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -684,4 +684,8 @@ int ff_bprint_to_codecpar_extradata(AVCodecParameters *par, struct AVBPrint *buf int ff_interleaved_peek(AVFormatContext *s, int stream, AVPacket *pkt, int add_offset); + +int ff_lock_avformat(void); +int ff_unlock_avformat(void); + #endif /* AVFORMAT_INTERNAL_H */ diff --git a/libavformat/tls_gnutls.c b/libavformat/tls_gnutls.c index 0cef9575ec454..e3c43683be57a 100644 --- a/libavformat/tls_gnutls.c +++ b/libavformat/tls_gnutls.c @@ -55,20 +55,20 @@ typedef struct TLSContext { void ff_gnutls_init(void) { - avpriv_lock_avformat(); + ff_lock_avformat(); #if HAVE_THREADS && GNUTLS_VERSION_NUMBER < 0x020b00 if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0) gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); #endif gnutls_global_init(); - avpriv_unlock_avformat(); + ff_unlock_avformat(); } void ff_gnutls_deinit(void) { - avpriv_lock_avformat(); + ff_lock_avformat(); gnutls_global_deinit(); - avpriv_unlock_avformat(); + ff_unlock_avformat(); } static int print_tls_error(URLContext *h, int ret) diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c index 1443e9025aa83..59a86150a793d 100644 --- a/libavformat/tls_openssl.c +++ b/libavformat/tls_openssl.c @@ -68,7 +68,7 @@ static unsigned long openssl_thread_id(void) int ff_openssl_init(void) { - avpriv_lock_avformat(); + ff_lock_avformat(); if (!openssl_init) { SSL_library_init(); SSL_load_error_strings(); @@ -77,7 +77,7 @@ int ff_openssl_init(void) int i; openssl_mutexes = av_malloc_array(sizeof(pthread_mutex_t), CRYPTO_num_locks()); if (!openssl_mutexes) { - avpriv_unlock_avformat(); + ff_unlock_avformat(); return AVERROR(ENOMEM); } @@ -91,14 +91,14 @@ int ff_openssl_init(void) #endif } openssl_init++; - avpriv_unlock_avformat(); + ff_unlock_avformat(); return 0; } void ff_openssl_deinit(void) { - avpriv_lock_avformat(); + ff_lock_avformat(); openssl_init--; if (!openssl_init) { #if HAVE_THREADS @@ -111,7 +111,7 @@ void ff_openssl_deinit(void) } #endif } - avpriv_unlock_avformat(); + ff_unlock_avformat(); } static int print_tls_error(URLContext *h, int ret) diff --git a/libavformat/utils.c b/libavformat/utils.c index 84e49208b84eb..9b46bd6737310 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -32,6 +32,7 @@ #include "libavutil/opt.h" #include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" +#include "libavutil/thread.h" #include "libavutil/time.h" #include "libavutil/time_internal.h" #include "libavutil/timestamp.h" @@ -55,6 +56,8 @@ #include "libavutil/ffversion.h" const char av_format_ffversion[] = "FFmpeg version " FFMPEG_VERSION; +static AVMutex avformat_mutex = AV_MUTEX_INITIALIZER; + /** * @file * various utility functions for use within FFmpeg @@ -77,6 +80,16 @@ const char *avformat_license(void) return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; } +int ff_lock_avformat(void) +{ + return ff_mutex_lock(&avformat_mutex) ? -1 : 0; +} + +int ff_unlock_avformat(void) +{ + return ff_mutex_unlock(&avformat_mutex) ? -1 : 0; +} + #define RELATIVE_TS_BASE (INT64_MAX - (1LL<<48)) static int is_relative(int64_t ts) { From 4ed66517c62c599701b3793fa2843d5a8530a4f4 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 21 Dec 2017 23:03:24 +0100 Subject: [PATCH 1467/2557] lavc: remove complex debug code around avcodec init locking This is just a lot of complicated and confusing code that had no purpose anymore. Also, the functions return values were checked only sometimes. Locking shouldn't fail anyway, so remove the return values. Barely any other pthread lock calls check the return value (including more important code that is more likely to fail horribly if locking fails). It could be argued that it might be helpful in some debugging situations, or when the user built FFmpeg without thread support against all good advice. But there are dummy atomics too, so the atomic check won't help with ensuring correctness absolutely. You gain very little. Also, for debugging, you can just raise the ASSERT_LEVEL, and then libavutil/thread.h will redefine the locking functions to explicitly check the return values. --- libavcodec/internal.h | 4 ---- libavcodec/utils.c | 55 +++++++++++-------------------------------- 2 files changed, 14 insertions(+), 45 deletions(-) diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 30614bb2b177e..16bd10128495b 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -243,10 +243,6 @@ int ff_init_buffer_info(AVCodecContext *s, AVFrame *frame); void ff_color_frame(AVFrame *frame, const int color[4]); -extern volatile int ff_avcodec_locked; -int ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec); -int ff_unlock_avcodec(const AVCodec *codec); - /** * Maximum size in bytes of extradata. * This value was chosen such that every bit of the buffer is diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 9c631c4fb03da..dfbfe98d639d3 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -67,8 +67,6 @@ #include "libavutil/ffversion.h" const char av_codec_ffversion[] = "FFmpeg version " FFMPEG_VERSION; -volatile int ff_avcodec_locked; -static atomic_int entangled_thread_counter = ATOMIC_VAR_INIT(0); static AVMutex codec_mutex = AV_MUTEX_INITIALIZER; void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size) @@ -550,6 +548,19 @@ static int64_t get_bit_rate(AVCodecContext *ctx) return bit_rate; } + +static void ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec) +{ + if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) + ff_mutex_lock(&codec_mutex); +} + +static void ff_unlock_avcodec(const AVCodec *codec) +{ + if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) + ff_mutex_unlock(&codec_mutex); +} + int attribute_align_arg ff_codec_open2_recursive(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options) { int ret = 0; @@ -589,9 +600,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code if (options) av_dict_copy(&tmp, *options, 0); - ret = ff_lock_avcodec(avctx, codec); - if (ret < 0) - return ret; + ff_lock_avcodec(avctx, codec); avctx->internal = av_mallocz(sizeof(AVCodecInternal)); if (!avctx->internal) { @@ -1867,42 +1876,6 @@ int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) } #endif -int ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec) -{ - if (codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE || !codec->init) - return 0; - - if (ff_mutex_lock(&codec_mutex)) - return -1; - - if (atomic_fetch_add(&entangled_thread_counter, 1)) { - av_log(log_ctx, AV_LOG_ERROR, - "Insufficient thread locking. At least %d threads are " - "calling avcodec_open2() at the same time right now.\n", - atomic_load(&entangled_thread_counter)); - ff_avcodec_locked = 1; - ff_unlock_avcodec(codec); - return AVERROR(EINVAL); - } - av_assert0(!ff_avcodec_locked); - ff_avcodec_locked = 1; - return 0; -} - -int ff_unlock_avcodec(const AVCodec *codec) -{ - if (codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE || !codec->init) - return 0; - - av_assert0(ff_avcodec_locked); - ff_avcodec_locked = 0; - atomic_fetch_add(&entangled_thread_counter, -1); - if (ff_mutex_unlock(&codec_mutex)) - return -1; - - return 0; -} - unsigned int avpriv_toupper4(unsigned int x) { return av_toupper(x & 0xFF) + From cf57cb3ae4364ab8e70af37beea7a45a86de90e9 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 23 Dec 2017 03:13:00 +0100 Subject: [PATCH 1468/2557] h264: add AVOption to set x264_build default This provides a generic way to the API user to deal with files that either lack this SEI, or which have the SEI only in packets not passed to the decoder (such as the common case of the SEI being in the very firsat video packet, but decoding is started somewhere in the middle of the file). Bugs like 840b41b2a643fc8f0617c0370125a19c02c6b586 make this somewhat of a necessity. This intentionally uses the version in the SEI instead, if any is found. --- libavcodec/h264dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 1e98765439c16..8c9c6d9f3bfb2 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -315,7 +315,6 @@ static int h264_init_context(AVCodecContext *avctx, H264Context *h) h->flags = avctx->flags; h->poc.prev_poc_msb = 1 << 16; h->recovery_frame = -1; - h->x264_build = -1; h->frame_recovered = 0; h->poc.prev_frame_num = -1; h->sei.frame_packing.arrangement_cancel_flag = -1; @@ -1037,6 +1036,7 @@ static const AVOption h264_options[] = { { "is_avc", "is avc", OFFSET(is_avc), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, 0 }, { "nal_length_size", "nal_length_size", OFFSET(nal_length_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 4, 0 }, { "enable_er", "Enable error resilience on damaged frames (unsafe)", OFFSET(enable_er), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VD }, + { "x264_build", "Assume this x264 version if no x264 version found in any SEI", OFFSET(x264_build), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VD }, { NULL }, }; From 613f789c19153edadb1fcc11866192f6b296ee58 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 25 Dec 2017 23:17:23 -0300 Subject: [PATCH 1469/2557] w32pthreads: remove some remaining superfluous checks Signed-off-by: James Almer --- compat/w32pthreads.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/compat/w32pthreads.h b/compat/w32pthreads.h index 237cab5677247..21acfd2ba1a94 100644 --- a/compat/w32pthreads.h +++ b/compat/w32pthreads.h @@ -39,11 +39,6 @@ #include #include -#if _WIN32_WINNT < 0x0600 && defined(__MINGW32__) -#undef MemoryBarrier -#define MemoryBarrier __sync_synchronize -#endif - #include "libavutil/attributes.h" #include "libavutil/common.h" #include "libavutil/internal.h" @@ -63,10 +58,8 @@ typedef CONDITION_VARIABLE pthread_cond_t; #define PTHREAD_MUTEX_INITIALIZER SRWLOCK_INIT #define PTHREAD_COND_INITIALIZER CONDITION_VARIABLE_INIT -#if _WIN32_WINNT >= 0x0600 #define InitializeCriticalSection(x) InitializeCriticalSectionEx(x, 0, 0) #define WaitForSingleObject(a, b) WaitForSingleObjectEx(a, b, FALSE) -#endif static av_unused unsigned __stdcall attribute_align_arg win32thread_worker(void *arg) { From 89f704cabab446afc8ba6ecea76714a51b1df32b Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 25 Dec 2017 19:40:42 -0300 Subject: [PATCH 1470/2557] avcodec/libx264: use the pixfmt descriptor to check for high bit depths The x264_bit_depth constant has been removed in newer x264 builds. Signed-off-by: James Almer --- libavcodec/libx264.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index e2455e18dec6a..2d36c5e566662 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -272,6 +272,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { X264Context *x4 = ctx->priv_data; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(ctx->pix_fmt); x264_nal_t *nal; int nnal, i, ret; x264_picture_t pic_out = {0}; @@ -279,7 +280,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, x264_picture_init( &x4->pic ); x4->pic.img.i_csp = x4->params.i_csp; - if (x264_bit_depth > 8) + if (desc->comp[0].depth > 8) x4->pic.img.i_csp |= X264_CSP_HIGH_DEPTH; x4->pic.img.i_plane = avfmt2_num_planes(ctx->pix_fmt); From 2a111c99a60fdf4fe5eea2b073901630190c6c93 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 25 Dec 2017 19:41:09 -0300 Subject: [PATCH 1471/2557] avcodec/libx264: fix compilation with x264 builds >= 153 x264 now supports multibitdepth builds, with a slightly changed API to request bitdepth during initialization. Reviewed-by: Ricardo Constantino Signed-off-by: James Almer --- libavcodec/libx264.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 2d36c5e566662..754383e080df9 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -724,6 +724,9 @@ FF_ENABLE_DEPRECATION_WARNINGS x4->params.i_width = avctx->width; x4->params.i_height = avctx->height; +#if X264_BUILD >= 153 + x4->params.i_bitdepth = av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth; +#endif av_reduce(&sw, &sh, avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den, 4096); x4->params.vui.i_sar_width = sw; x4->params.vui.i_sar_height = sh; @@ -837,6 +840,24 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; } +static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUV420P10, + AV_PIX_FMT_YUV422P10, + AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_NV12, + AV_PIX_FMT_NV16, + AV_PIX_FMT_NV20, +#ifdef X264_CSP_NV21 + AV_PIX_FMT_NV21, +#endif + AV_PIX_FMT_NONE +}; static const enum AVPixelFormat pix_fmts_8bit[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVJ420P, @@ -874,12 +895,14 @@ static const enum AVPixelFormat pix_fmts_8bit_rgb[] = { static av_cold void X264_init_static(AVCodec *codec) { - if (x264_bit_depth == 8) + if (X264_BIT_DEPTH == 8) codec->pix_fmts = pix_fmts_8bit; - else if (x264_bit_depth == 9) + else if (X264_BIT_DEPTH == 9) codec->pix_fmts = pix_fmts_9bit; - else if (x264_bit_depth == 10) + else if (X264_BIT_DEPTH == 10) codec->pix_fmts = pix_fmts_10bit; + else /* X264_BIT_DEPTH == 0 */ + codec->pix_fmts = pix_fmts; } #define OFFSET(x) offsetof(X264Context, x) From 4d70fbeec8cbab072b3a9b9f760b8deaaef240f2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 22 Dec 2017 03:06:14 +0100 Subject: [PATCH 1472/2557] avcodec/dirac_dwt: Fix integer overflow in COMPOSE_DD97iH0() and COMPOSE_DD137iL0() Fixes: runtime error: signed integer overflow: 2147483646 + 33554433 cannot be represented in type 'int' Fixes: 4563/clusterfuzz-testcase-minimized-5438979567517696 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/dirac_dwt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/dirac_dwt.h b/libavcodec/dirac_dwt.h index 50c8b1e394649..f9828d95a493b 100644 --- a/libavcodec/dirac_dwt.h +++ b/libavcodec/dirac_dwt.h @@ -99,10 +99,10 @@ void ff_spatial_idwt_slice2(DWTContext *d, int y); (b1 + ((int)(b0 + (unsigned)(b2) + 1) >> 1)) #define COMPOSE_DD97iH0(b0, b1, b2, b3, b4)\ - (b2 + ((int)(-b0 + 9U*b1 + 9U*b3 - b4 + 8) >> 4)) + (int)(((unsigned)(b2) + ((int)(-b0 + 9U*b1 + 9U*b3 - b4 + 8) >> 4))) #define COMPOSE_DD137iL0(b0, b1, b2, b3, b4)\ - (b2 - ((int)(-b0 + 9U*b1 + 9U*b3 - b4 + 16) >> 5)) + (int)(((unsigned)(b2) - ((int)(-b0 + 9U*b1 + 9U*b3 - b4 + 16) >> 5))) #define COMPOSE_HAARiL0(b0, b1)\ (b0 - ((b1 + 1) >> 1)) From 0c9ab5ef9c1ee852c80c859c9e07efe8730b57ed Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 22 Dec 2017 03:12:03 +0100 Subject: [PATCH 1473/2557] avcodec/hevcdsp_template.c: Fix undefined shift in FUNC(dequant) Fixes: runtime error: left shift of negative value -180 Fixes: 4626/clusterfuzz-testcase-minimized-5647837887987712 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevcdsp_template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/hevcdsp_template.c b/libavcodec/hevcdsp_template.c index 4017af8eb0b18..903aa3fe9557e 100644 --- a/libavcodec/hevcdsp_template.c +++ b/libavcodec/hevcdsp_template.c @@ -121,7 +121,7 @@ static void FUNC(dequant)(int16_t *coeffs, int16_t log2_size) } else { for (y = 0; y < size; y++) { for (x = 0; x < size; x++) { - *coeffs = *coeffs << -shift; + *coeffs = *(uint16_t*)coeffs << -shift; coeffs++; } } From e6a1dfc9ce81a443b16776a5fbd841284efa3613 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 21 Dec 2017 19:54:56 +0000 Subject: [PATCH 1474/2557] mpeg4videodec: Fix unused variable warning video_format is not used. --- libavcodec/mpeg4videodec.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index e9cba25dd0ffe..12755b5e8a40f 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -1768,9 +1768,10 @@ static int mpeg4_decode_visual_object(MpegEncContext *s, GetBitContext *gb) visual_object_type == VOT_STILL_TEXTURE_ID) { int video_signal_type = get_bits1(gb); if (video_signal_type) { - int video_format = get_bits(gb, 3); - int video_range = get_bits1(gb); - int color_description = get_bits1(gb); + int video_range, color_description; + skip_bits(gb, 3); // video_format + video_range = get_bits1(gb); + color_description = get_bits1(gb); s->avctx->color_range = video_range ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; From 7e60c74329353db28db00552028bc88cd2a52346 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 26 Dec 2017 19:40:27 -0300 Subject: [PATCH 1475/2557] avcodec/libx264: set supported pix_fmts at runtime rather than build time This partially reverts a change in behavior introduced in 2a111c99a60fdf4fe5eea2b073901630190c6c93. Signed-off-by: James Almer --- libavcodec/libx264.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 754383e080df9..0e714f16152e8 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -895,14 +895,16 @@ static const enum AVPixelFormat pix_fmts_8bit_rgb[] = { static av_cold void X264_init_static(AVCodec *codec) { - if (X264_BIT_DEPTH == 8) +#if X264_BUILD < 153 + if (x264_bit_depth == 8) codec->pix_fmts = pix_fmts_8bit; - else if (X264_BIT_DEPTH == 9) + else if (x264_bit_depth == 9) codec->pix_fmts = pix_fmts_9bit; - else if (X264_BIT_DEPTH == 10) + else if (x264_bit_depth == 10) codec->pix_fmts = pix_fmts_10bit; - else /* X264_BIT_DEPTH == 0 */ - codec->pix_fmts = pix_fmts; +#else + codec->pix_fmts = pix_fmts; +#endif } #define OFFSET(x) offsetof(X264Context, x) From 2f9ca64556cba9a7edcca9a1c55923a60022937d Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 26 Dec 2017 14:29:03 -0800 Subject: [PATCH 1476/2557] avformat/hls: remove repeated http proto_name checks in open_url() Signed-off-by: Aman Gupta --- libavformat/hls.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index f00e22dfefbe5..d2cbb47f15d45 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -623,12 +623,13 @@ static int open_url_keepalive(AVFormatContext *s, AVIOContext **pb, } static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, - AVDictionary *opts, AVDictionary *opts2, int *is_http) + AVDictionary *opts, AVDictionary *opts2, int *is_http_out) { HLSContext *c = s->priv_data; AVDictionary *tmp = NULL; const char *proto_name = NULL; int ret; + int is_http = 0; av_dict_copy(&tmp, opts, 0); av_dict_copy(&tmp, opts2, 0); @@ -654,7 +655,7 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, return AVERROR_INVALIDDATA; } } else if (av_strstart(proto_name, "http", NULL)) { - ; + is_http = 1; } else return AVERROR_INVALIDDATA; @@ -665,7 +666,7 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) return AVERROR_INVALIDDATA; - if (c->http_persistent && *pb && av_strstart(proto_name, "http", NULL)) { + if (is_http && c->http_persistent && *pb) { ret = open_url_keepalive(c->ctx, pb, url); if (ret == AVERROR_EXIT) { return ret; @@ -696,8 +697,8 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, av_dict_free(&tmp); - if (is_http) - *is_http = av_strstart(proto_name, "http", NULL); + if (is_http_out) + *is_http_out = is_http; return ret; } From a232a72d77cf32766e7f42f892b983f5e496653f Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 25 Dec 2017 11:33:06 -0800 Subject: [PATCH 1477/2557] avformat/hls: return AVERROR_PROTOCOL_NOT_FOUND when http protocol is not available Fixes compile error when building with network or protocols disabled. This code would never be reached (because the demuxer fails much earlier on http playlists or segments), so it doesn't matter much what we do here as long as it compiles. Signed-off-by: Aman Gupta --- libavformat/hls.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/hls.c b/libavformat/hls.c index d2cbb47f15d45..c0bade0e84476 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -611,6 +611,9 @@ static void update_options(char **dest, const char *name, void *src) static int open_url_keepalive(AVFormatContext *s, AVIOContext **pb, const char *url) { +#if !CONFIG_HTTP_PROTOCOL + return AVERROR_PROTOCOL_NOT_FOUND; +#else int ret; URLContext *uc = ffio_geturlcontext(*pb); av_assert0(uc); @@ -620,6 +623,7 @@ static int open_url_keepalive(AVFormatContext *s, AVIOContext **pb, ff_format_io_close(s, pb); } return ret; +#endif } static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, From 11f989945e1748fbe9b2a5abd68a25d3091acc5d Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 25 Dec 2017 11:35:26 -0800 Subject: [PATCH 1478/2557] avformat/http: avoid ff_http_do_new_request after http/1.0 response This makes do_new_request fail early when dealing with a http/1.0 server, avoiding unnecessary "reconnecting" warnings shown to the user. Signed-off-by: Aman Gupta --- libavformat/http.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index c15ca522c4080..213b6bb245902 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -917,6 +917,8 @@ static int process_line(URLContext *h, char *line, int line_count, } av_log(h, AV_LOG_TRACE, "HTTP version string: %s\n", version); } else { + if (av_strncasecmp(p, "HTTP/1.0", 8) == 0) + s->willclose = 1; while (!av_isspace(*p) && *p != '\0') p++; while (av_isspace(*p)) From ac19e63b184570c0ade4d3a8a785f64441d9cac8 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 25 Dec 2017 18:25:13 -0800 Subject: [PATCH 1479/2557] avformat/hls: respect http_persistent only for http playlist urls Fixes a segfault when reading a live playlist (without end tag) from non-http url (like a file on disk). Signed-off-by: Aman Gupta --- libavformat/hls.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index c0bade0e84476..2d46c2ac69273 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -725,8 +725,9 @@ static int parse_playlist(HLSContext *c, const char *url, struct variant_info variant_info; char tmp_str[MAX_URL_SIZE]; struct segment *cur_init_section = NULL; + int is_http = av_strstart(url, "http", NULL); - if (!in && c->http_persistent && c->playlist_pb) { + if (is_http && !in && c->http_persistent && c->playlist_pb) { in = c->playlist_pb; ret = open_url_keepalive(c->ctx, &c->playlist_pb, url); if (ret == AVERROR_EXIT) { @@ -760,7 +761,7 @@ static int parse_playlist(HLSContext *c, const char *url, if (ret < 0) return ret; - if (c->http_persistent) + if (is_http && c->http_persistent) c->playlist_pb = in; else close_in = 1; From 039007c928b4207b8bdde31c80c57dc7b917dd2f Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 25 Dec 2017 20:21:15 -0800 Subject: [PATCH 1480/2557] avformat/http: export http_version from response Can be used by the api user to figure out what http features the server supports based on the response received. Signed-off-by: Aman Gupta --- doc/protocols.texi | 3 +++ libavformat/http.c | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/doc/protocols.texi b/doc/protocols.texi index ca2f9ad63d38c..1ededa81c861b 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -321,6 +321,9 @@ Sets the maximum delay in seconds after which to give up reconnecting @item mime_type Export the MIME type. +@item http_version +Exports the HTTP response version number. Usually "1.0" or "1.1". + @item icy If set to 1 request ICY (SHOUTcast) metadata from the server. If the server supports this, the metadata has to be retrieved by the application by reading diff --git a/libavformat/http.c b/libavformat/http.c index 213b6bb245902..a376f1a488468 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -74,6 +74,7 @@ typedef struct HTTPContext { char *http_proxy; char *headers; char *mime_type; + char *http_version; char *user_agent; #if FF_API_HTTP_USER_AGENT char *user_agent_deprecated; @@ -144,6 +145,7 @@ static const AVOption options[] = { { "multiple_requests", "use persistent connections", OFFSET(multiple_requests), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D | E }, { "post_data", "set custom HTTP post data", OFFSET(post_data), AV_OPT_TYPE_BINARY, .flags = D | E }, { "mime_type", "export the MIME type", OFFSET(mime_type), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY }, + { "http_version", "export the http response version", OFFSET(http_version), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY }, { "cookies", "set cookies to be sent in applicable future requests, use newline delimited Set-Cookie HTTP field value syntax", OFFSET(cookies), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, { "icy", "request ICY metadata", OFFSET(icy), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, D }, { "icy_metadata_headers", "return ICY metadata headers", OFFSET(icy_metadata_headers), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_EXPORT }, @@ -919,6 +921,12 @@ static int process_line(URLContext *h, char *line, int line_count, } else { if (av_strncasecmp(p, "HTTP/1.0", 8) == 0) s->willclose = 1; + while (*p != '/' && *p != '\0') + p++; + while (*p == '/') + p++; + av_freep(&s->http_version); + s->http_version = av_strndup(p, 3); while (!av_isspace(*p) && *p != '\0') p++; while (av_isspace(*p)) From 1dd82edea5ab689f9a94e14cb2cf6d382cbf9ee6 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 25 Dec 2017 20:37:55 -0800 Subject: [PATCH 1481/2557] avformat/hls: enable http_multiple only for http/1.1 servers Some http/1.0 implementations, like python's SimpleHTTPServer, can only support one client connection at a time. Making a second request while the first is still connected leads to a deadlock. This change enables multiple connections for http/1.1 servers only, which need to support keepalive by default and should have no problem with concurrent requests. Signed-off-by: Aman Gupta --- doc/demuxers.texi | 2 +- libavformat/hls.c | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 81ab399cdc215..6080167233d97 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -323,7 +323,7 @@ Enabled by default. @item http_multiple Use multiple HTTP connections for downloading HTTP segments. -Enabled by default. +Enabled by default for HTTP/1.1 servers. @end table @section image2 diff --git a/libavformat/hls.c b/libavformat/hls.c index 2d46c2ac69273..dccc7c7dd2c3f 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1452,7 +1452,7 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) if (ret) return ret; - if (c->http_multiple && av_strstart(seg->url, "http", NULL) && v->input_next_requested) { + if (c->http_multiple == 1 && v->input_next_requested) { FFSWAP(AVIOContext *, v->input, v->input_next); v->input_next_requested = 0; ret = 0; @@ -1471,8 +1471,15 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) just_opened = 1; } + if (c->http_multiple == -1) { + uint8_t *http_version_opt = NULL; + av_opt_get(v->input, "http_version", AV_OPT_SEARCH_CHILDREN, &http_version_opt); + c->http_multiple = http_version_opt && strncmp((const char *)http_version_opt, "1.1", 3) == 0; + } + seg = next_segment(v); - if (c->http_multiple && !v->input_next_requested && seg) { + if (c->http_multiple == 1 && !v->input_next_requested && + seg && av_strstart(seg->url, "http", NULL)) { ret = open_input(c, v, seg, &v->input_next); if (ret < 0) { if (ff_check_interrupt(c->interrupt_callback)) @@ -2306,7 +2313,7 @@ static const AVOption hls_options[] = { {"http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, {"http_multiple", "Use multiple HTTP connections for fetching segments", - OFFSET(http_multiple), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS}, + OFFSET(http_multiple), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, FLAGS}, {NULL} }; From 8f9024f2ca4740c4ed80dea1e9c890c9217013bd Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 27 Dec 2017 03:47:28 +0100 Subject: [PATCH 1482/2557] lavc: remove uneffective attribute_deprecated on enum Does not work. Even emits a warning with some compilers that the attribute does not work on enums. It's likely that there is way to make it work, but not worth the trouble. --- libavcodec/avcodec.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index a9182a9e3daa1..c13deb599fc21 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -5933,8 +5933,9 @@ AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel); #if FF_API_LOCKMGR /** * Lock operation used by lockmgr + * + * @deprecated Deprecated together with av_lockmgr_register(). */ -attribute_deprecated enum AVLockOp { AV_LOCK_CREATE, ///< Create a mutex AV_LOCK_OBTAIN, ///< Lock the mutex From caacbfa773fc1cc6dbeb4a47e0a5a0616fa09549 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 27 Dec 2017 11:08:57 +0100 Subject: [PATCH 1483/2557] avfilter/vf_convolve: cosmetics Signed-off-by: Paul B Mahol --- libavfilter/vf_convolve.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c index 88ae884a19578..d7e2305cf746e 100644 --- a/libavfilter/vf_convolve.c +++ b/libavfilter/vf_convolve.c @@ -166,7 +166,7 @@ static int fft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_job FFTComplex *hdata = td->hdata; const int plane = td->plane; const int n = td->n; - int start = (n * jobnr ) / nb_jobs; + int start = (n * jobnr) / nb_jobs; int end = (n * (jobnr+1)) / nb_jobs; int y; @@ -261,7 +261,7 @@ static int fft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) FFTComplex *vdata = td->vdata; const int plane = td->plane; const int n = td->n; - int start = (n * jobnr ) / nb_jobs; + int start = (n * jobnr) / nb_jobs; int end = (n * (jobnr+1)) / nb_jobs; int y, x; @@ -286,7 +286,7 @@ static int ifft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs FFTComplex *vdata = td->vdata; const int plane = td->plane; const int n = td->n; - int start = (n * jobnr ) / nb_jobs; + int start = (n * jobnr) / nb_jobs; int end = (n * (jobnr+1)) / nb_jobs; int y, x; @@ -310,7 +310,7 @@ static int ifft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo FFTComplex *hdata = td->hdata; const int plane = td->plane; const int n = td->n; - int start = (n * jobnr ) / nb_jobs; + int start = (n * jobnr) / nb_jobs; int end = (n * (jobnr+1)) / nb_jobs; int y; @@ -383,7 +383,7 @@ static int complex_multiply(AVFilterContext *ctx, void *arg, int jobnr, int nb_j FFTComplex *input = td->hdata; FFTComplex *filter = td->vdata; const int n = td->n; - int start = (n * jobnr ) / nb_jobs; + int start = (n * jobnr) / nb_jobs; int end = (n * (jobnr+1)) / nb_jobs; int y, x; From 87f148d526348a591716c66c40b3c294880ffc63 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 27 Dec 2017 11:10:12 +0100 Subject: [PATCH 1484/2557] avfilter/vf_convolve: remove padding, its unused and not needed Signed-off-by: Paul B Mahol --- libavfilter/vf_convolve.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c index d7e2305cf746e..0f9970b869a53 100644 --- a/libavfilter/vf_convolve.c +++ b/libavfilter/vf_convolve.c @@ -121,16 +121,16 @@ static int config_input_main(AVFilterLink *inlink) s->fft_bits[i] = fft_bits; s->fft_len[i] = 1 << s->fft_bits[i]; - if (!(s->fft_hdata[i] = av_calloc(s->fft_len[i] + 1, s->fft_len[i] * sizeof(FFTComplex)))) + if (!(s->fft_hdata[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(FFTComplex)))) return AVERROR(ENOMEM); - if (!(s->fft_vdata[i] = av_calloc(s->fft_len[i] + 1, s->fft_len[i] * sizeof(FFTComplex)))) + if (!(s->fft_vdata[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(FFTComplex)))) return AVERROR(ENOMEM); - if (!(s->fft_hdata_impulse[i] = av_calloc(s->fft_len[i] + 1, s->fft_len[i] * sizeof(FFTComplex)))) + if (!(s->fft_hdata_impulse[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(FFTComplex)))) return AVERROR(ENOMEM); - if (!(s->fft_vdata_impulse[i] = av_calloc(s->fft_len[i] + 1, s->fft_len[i] * sizeof(FFTComplex)))) + if (!(s->fft_vdata_impulse[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(FFTComplex)))) return AVERROR(ENOMEM); } From 8c9a91ac82b9be729fc37d7bdc69608b3c70a5aa Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 25 Dec 2017 15:59:44 +0100 Subject: [PATCH 1485/2557] avfilter: add deconvolve filter Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/filters.texi | 23 ++++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- libavfilter/vf_convolve.c | 109 ++++++++++++++++++++++++++++++++++---- 6 files changed, 126 insertions(+), 11 deletions(-) diff --git a/Changelog b/Changelog index 2ebdf00ff199c..720d478f002b9 100644 --- a/Changelog +++ b/Changelog @@ -30,6 +30,7 @@ version : - AVX-512/ZMM support added - Dropped support for building for Windows XP. The minimum supported Windows version is Windows Vista. +- deconvolve video filter version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index 45515966e8953..f651f1234d77b 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6937,6 +6937,29 @@ Set whether or not chroma is considered in the metric calculations. Default is @code{1}. @end table +@section deconvolve + +Apply 2D deconvolution of video stream in frequency domain using second stream +as impulse. + +The filter accepts the following options: + +@table @option +@item planes +Set which planes to process. + +@item impulse +Set which impulse video frames will be processed, can be @var{first} +or @var{all}. Default is @var{all}. + +@item noise +Set noise when doing divisions. Default is @var{0.0000001}. Useful when width +and height are not same and not power of 2 or if stream prior to convolving +had noise. +@end table + +The @code{deconvolve} filter also supports the @ref{framesync} options. + @section deflate Apply deflate effect to the video. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 6b06d57234ed6..8bde542163e08 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -165,6 +165,7 @@ OBJS-$(CONFIG_DATASCOPE_FILTER) += vf_datascope.o OBJS-$(CONFIG_DCTDNOIZ_FILTER) += vf_dctdnoiz.o OBJS-$(CONFIG_DEBAND_FILTER) += vf_deband.o OBJS-$(CONFIG_DECIMATE_FILTER) += vf_decimate.o +OBJS-$(CONFIG_DECONVOLVE_FILTER) += vf_convolve.o framesync.o OBJS-$(CONFIG_DEFLATE_FILTER) += vf_neighbor.o OBJS-$(CONFIG_DEFLICKER_FILTER) += vf_deflicker.o OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER) += vf_deinterlace_qsv.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 707faad777676..67c073091fb7d 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -175,6 +175,7 @@ static void register_all(void) REGISTER_FILTER(DCTDNOIZ, dctdnoiz, vf); REGISTER_FILTER(DEBAND, deband, vf); REGISTER_FILTER(DECIMATE, decimate, vf); + REGISTER_FILTER(DECONVOLVE, deconvolve, vf); REGISTER_FILTER(DEFLATE, deflate, vf); REGISTER_FILTER(DEFLICKER, deflicker, vf); REGISTER_FILTER(DEINTERLACE_QSV,deinterlace_qsv,vf); diff --git a/libavfilter/version.h b/libavfilter/version.h index b0009e83ea0df..85bc6d35f8ffe 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 7 +#define LIBAVFILTER_VERSION_MINOR 8 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c index 0f9970b869a53..982eda1cbcf03 100644 --- a/libavfilter/vf_convolve.c +++ b/libavfilter/vf_convolve.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -51,8 +53,11 @@ typedef struct ConvolveContext { int depth; int planes; int impulse; + float noise; int nb_planes; int got_impulse[4]; + + int (*filter)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } ConvolveContext; #define OFFSET(x) offsetof(ConvolveContext, x) @@ -63,11 +68,10 @@ static const AVOption convolve_options[] = { { "impulse", "when to process impulses", OFFSET(impulse), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "impulse" }, { "first", "process only first impulse, ignore rest", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "impulse" }, { "all", "process all impulses", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "impulse" }, + { "noise", "set noise", OFFSET(noise), AV_OPT_TYPE_FLOAT, {.dbl=0.0000001}, 0, 1, FLAGS }, { NULL }, }; -FRAMESYNC_DEFINE_CLASS(convolve, ConvolveContext, fs); - static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pixel_fmts_fftfilt[] = { @@ -322,11 +326,9 @@ static int ifft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo return 0; } -static void get_output(ConvolveContext *s, AVFrame *out, - int w, int h, int n, int plane) +static void get_output(ConvolveContext *s, FFTComplex *input, AVFrame *out, + int w, int h, int n, int plane, float scale) { - FFTComplex *input = s->fft_hdata[plane]; - const float scale = 1.f / (n * n); const int max = (1 << s->depth) - 1; const int hh = h / 2; const int hw = w / 2; @@ -379,9 +381,11 @@ static void get_output(ConvolveContext *s, AVFrame *out, static int complex_multiply(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { + ConvolveContext *s = ctx->priv; ThreadData *td = arg; FFTComplex *input = td->hdata; FFTComplex *filter = td->vdata; + const float noise = s->noise; const int n = td->n; int start = (n * jobnr) / nb_jobs; int end = (n * (jobnr+1)) / nb_jobs; @@ -395,7 +399,7 @@ static int complex_multiply(AVFilterContext *ctx, void *arg, int jobnr, int nb_j re = input[yn + x].re; im = input[yn + x].im; - ire = filter[yn + x].re; + ire = filter[yn + x].re + noise; iim = filter[yn + x].im; input[yn + x].re = ire * re - iim * im; @@ -406,6 +410,38 @@ static int complex_multiply(AVFilterContext *ctx, void *arg, int jobnr, int nb_j return 0; } +static int complex_divide(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ConvolveContext *s = ctx->priv; + ThreadData *td = arg; + FFTComplex *input = td->hdata; + FFTComplex *filter = td->vdata; + const float noise = s->noise; + const int n = td->n; + int start = (n * jobnr) / nb_jobs; + int end = (n * (jobnr+1)) / nb_jobs; + int y, x; + + for (y = start; y < end; y++) { + int yn = y * n; + + for (x = 0; x < n; x++) { + FFTSample re, im, ire, iim, div; + + re = input[yn + x].re; + im = input[yn + x].im; + ire = filter[yn + x].re; + iim = filter[yn + x].im; + div = ire * ire + iim * iim + noise; + + input[yn + x].re = (ire * re + iim * im) / div; + input[yn + x].im = (ire * im - iim * re) / div; + } + } + + return 0; +} + static int do_convolve(FFFrameSync *fs) { AVFilterContext *ctx = fs->parent; @@ -460,7 +496,7 @@ static int do_convolve(FFFrameSync *fs) } total = FFMAX(1, total); - get_input(s, s->fft_hdata_impulse[plane], impulsepic, w, h, n, plane, 1 / total); + get_input(s, s->fft_hdata_impulse[plane], impulsepic, w, h, n, plane, 1.f / total); td.hdata = s->fft_hdata_impulse[plane]; td.vdata = s->fft_vdata_impulse[plane]; @@ -474,14 +510,15 @@ static int do_convolve(FFFrameSync *fs) td.hdata = input; td.vdata = filter; - ctx->internal->execute(ctx, complex_multiply, &td, NULL, FFMIN3(MAX_THREADS, n, ff_filter_get_nb_threads(ctx))); + ctx->internal->execute(ctx, s->filter, &td, NULL, FFMIN3(MAX_THREADS, n, ff_filter_get_nb_threads(ctx))); td.hdata = s->fft_hdata[plane]; td.vdata = s->fft_vdata[plane]; ctx->internal->execute(ctx, ifft_vertical, &td, NULL, FFMIN3(MAX_THREADS, n, ff_filter_get_nb_threads(ctx))); ctx->internal->execute(ctx, ifft_horizontal, &td, NULL, FFMIN3(MAX_THREADS, n, ff_filter_get_nb_threads(ctx))); - get_output(s, mainpic, w, h, n, plane); + + get_output(s, s->fft_hdata[plane], mainpic, w, h, n, plane, 1.f / (n * n)); } return ff_filter_frame(outlink, mainpic); @@ -525,6 +562,21 @@ static int activate(AVFilterContext *ctx) return ff_framesync_activate(&s->fs); } +static av_cold int init(AVFilterContext *ctx) +{ + ConvolveContext *s = ctx->priv; + + if (!strcmp(ctx->filter->name, "convolve")) { + s->filter = complex_multiply; + } else if (!strcmp(ctx->filter->name, "deconvolve")) { + s->filter = complex_divide; + } else { + return AVERROR_BUG; + } + + return 0; +} + static av_cold void uninit(AVFilterContext *ctx) { ConvolveContext *s = ctx->priv; @@ -567,10 +619,15 @@ static const AVFilterPad convolve_outputs[] = { { NULL } }; +#if CONFIG_CONVOLVE_FILTER + +FRAMESYNC_DEFINE_CLASS(convolve, ConvolveContext, fs); + AVFilter ff_vf_convolve = { .name = "convolve", .description = NULL_IF_CONFIG_SMALL("Convolve first video stream with second video stream."), .preinit = convolve_framesync_preinit, + .init = init, .uninit = uninit, .query_formats = query_formats, .activate = activate, @@ -580,3 +637,35 @@ AVFilter ff_vf_convolve = { .outputs = convolve_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, }; + +#endif /* CONFIG_CONVOLVE_FILTER */ + +#if CONFIG_DECONVOLVE_FILTER + +static const AVOption deconvolve_options[] = { + { "planes", "set planes to deconvolve", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGS }, + { "impulse", "when to process impulses", OFFSET(impulse), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "impulse" }, + { "first", "process only first impulse, ignore rest", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "impulse" }, + { "all", "process all impulses", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "impulse" }, + { "noise", "set noise", OFFSET(noise), AV_OPT_TYPE_FLOAT, {.dbl=0.0000001}, 0, 1, FLAGS }, + { NULL }, +}; + +FRAMESYNC_DEFINE_CLASS(deconvolve, ConvolveContext, fs); + +AVFilter ff_vf_deconvolve = { + .name = "deconvolve", + .description = NULL_IF_CONFIG_SMALL("Deconvolve first video stream with second video stream."), + .preinit = deconvolve_framesync_preinit, + .init = init, + .uninit = uninit, + .query_formats = query_formats, + .activate = activate, + .priv_size = sizeof(ConvolveContext), + .priv_class = &deconvolve_class, + .inputs = convolve_inputs, + .outputs = convolve_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, +}; + +#endif /* CONFIG_DECONVOLVE_FILTER */ From aff167847754d61987703ebaa0e461612e72a858 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 27 Dec 2017 12:31:43 +0100 Subject: [PATCH 1486/2557] configure: note (de)convolve filter dependency Signed-off-by: Paul B Mahol --- configure | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure b/configure index 19a0f310cff55..89f6331d00915 100755 --- a/configure +++ b/configure @@ -3196,12 +3196,16 @@ blackframe_filter_deps="gpl" boxblur_filter_deps="gpl" bs2b_filter_deps="libbs2b" colormatrix_filter_deps="gpl" +convolve_filter_deps="avcodec" +convolve_filter_select="fft" coreimage_filter_deps="coreimage appkit" coreimage_filter_extralibs="-framework OpenGL" coreimagesrc_filter_deps="coreimage appkit" coreimagesrc_filter_extralibs="-framework OpenGL" cover_rect_filter_deps="avcodec avformat gpl" cropdetect_filter_deps="gpl" +deconvolve_filter_deps="avcodec" +deconvolve_filter_select="fft" deinterlace_qsv_filter_deps="libmfx" deinterlace_vaapi_filter_deps="vaapi" delogo_filter_deps="gpl" From c6558e8840fbb2386bf8742e4d68dd6e067d262e Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 26 Dec 2017 12:32:42 +0100 Subject: [PATCH 1487/2557] x264: Support version 153 It has native simultaneus 8 and 10 bit support. --- libavcodec/libx264.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 0dec12edd29d1..3dc53aaf3847b 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -243,7 +243,11 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, x264_picture_init( &x4->pic ); x4->pic.img.i_csp = x4->params.i_csp; +#if X264_BUILD >= 153 + if (x4->params.i_bitdepth > 8) +#else if (x264_bit_depth > 8) +#endif x4->pic.img.i_csp |= X264_CSP_HIGH_DEPTH; x4->pic.img.i_plane = 3; @@ -395,6 +399,9 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.p_log_private = avctx; x4->params.i_log_level = X264_LOG_DEBUG; x4->params.i_csp = convert_pix_fmt(avctx->pix_fmt); +#if X264_BUILD >= 153 + x4->params.i_bitdepth = av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth; +#endif if (avctx->bit_rate) { x4->params.rc.i_bitrate = avctx->bit_rate / 1000; @@ -659,6 +666,7 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; } +#if X264_BUILD < 153 static const enum AVPixelFormat pix_fmts_8bit[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVJ420P, @@ -685,15 +693,37 @@ static const enum AVPixelFormat pix_fmts_10bit[] = { AV_PIX_FMT_NV20, AV_PIX_FMT_NONE }; +#else +static const enum AVPixelFormat pix_fmts_all[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_NV12, + AV_PIX_FMT_NV16, + AV_PIX_FMT_NV21, + AV_PIX_FMT_YUV420P10, + AV_PIX_FMT_YUV422P10, + AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_NV20, + AV_PIX_FMT_NONE +}; +#endif static av_cold void X264_init_static(AVCodec *codec) { +#if X264_BUILD < 153 if (x264_bit_depth == 8) codec->pix_fmts = pix_fmts_8bit; else if (x264_bit_depth == 9) codec->pix_fmts = pix_fmts_9bit; else if (x264_bit_depth == 10) codec->pix_fmts = pix_fmts_10bit; +#else + codec->pix_fmts = pix_fmts_all; +#endif } #define OFFSET(x) offsetof(X264Context, x) From efb63e4316c20093d03e51659a60804382eb867c Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 27 Dec 2017 15:38:13 -0300 Subject: [PATCH 1488/2557] configure: add missing avcodec dep to avfilter for de/convolve filters --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index 89f6331d00915..70de780f82a39 100755 --- a/configure +++ b/configure @@ -6611,6 +6611,8 @@ enabled amovie_filter && prepend avfilter_deps "avformat avcodec" enabled aresample_filter && prepend avfilter_deps "swresample" enabled atempo_filter && prepend avfilter_deps "avcodec" enabled cover_rect_filter && prepend avfilter_deps "avformat avcodec" +enabled convolve_filter && prepend avfilter_deps "avcodec" +enabled deconvolve_filter && prepend avfilter_deps "avcodec" enabled ebur128_filter && enabled swresample && prepend avfilter_deps "swresample" enabled elbg_filter && prepend avfilter_deps "avcodec" enabled fftfilt_filter && prepend avfilter_deps "avcodec" From ad73b32d2922f4237405043d19763229aee0e59e Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 3 Dec 2017 05:26:25 +0100 Subject: [PATCH 1489/2557] lavfi/minterpolate: Split struct Pixel to allow higher resolutions. Raises the maximum resolution from 2716x2707 to approximately 4096x4095. Fixes ticket #6795. --- libavfilter/vf_minterpolate.c | 120 +++++++++++++++++++++------------- 1 file changed, 75 insertions(+), 45 deletions(-) diff --git a/libavfilter/vf_minterpolate.c b/libavfilter/vf_minterpolate.c index 6c5c26400557d..d53431593d136 100644 --- a/libavfilter/vf_minterpolate.c +++ b/libavfilter/vf_minterpolate.c @@ -145,12 +145,18 @@ typedef struct Block { struct Block *subs; } Block; -typedef struct Pixel { +typedef struct PixelMVS { int16_t mvs[NB_PIXEL_MVS][2]; +} PixelMVS; + +typedef struct PixelWeights { uint32_t weights[NB_PIXEL_MVS]; +} PixelWeights; + +typedef struct PixelRefs { int8_t refs[NB_PIXEL_MVS]; int nb; -} Pixel; +} PixelRefs; typedef struct Frame { AVFrame *avf; @@ -172,7 +178,9 @@ typedef struct MIContext { Frame frames[NB_FRAMES]; Cluster clusters[NB_CLUSTERS]; Block *int_blocks; - Pixel *pixels; + PixelMVS *pixel_mvs; + PixelWeights *pixel_weights; + PixelRefs *pixel_refs; int (*mv_table[3])[2][2]; int64_t out_pts; int b_width, b_height, b_count; @@ -331,7 +339,7 @@ static int config_input(AVFilterLink *inlink) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); const int height = inlink->h; const int width = inlink->w; - int i; + int i, ret = 0; mi_ctx->log2_chroma_h = desc->log2_chroma_h; mi_ctx->log2_chroma_w = desc->log2_chroma_w; @@ -353,8 +361,13 @@ static int config_input(AVFilterLink *inlink) } if (mi_ctx->mi_mode == MI_MODE_MCI) { - if (!(mi_ctx->pixels = av_mallocz_array(width * height, sizeof(Pixel)))) - return AVERROR(ENOMEM); + mi_ctx->pixel_mvs = av_mallocz_array(width * height, sizeof(PixelMVS)); + mi_ctx->pixel_weights = av_mallocz_array(width * height, sizeof(PixelWeights)); + mi_ctx->pixel_refs = av_mallocz_array(width * height, sizeof(PixelRefs)); + if (!mi_ctx->pixel_mvs || !mi_ctx->pixel_weights || !mi_ctx->pixel_refs) { + ret = AVERROR(ENOMEM); + goto fail; + } if (mi_ctx->me_mode == ME_MODE_BILAT) if (!(mi_ctx->int_blocks = av_mallocz_array(mi_ctx->b_count, sizeof(Block)))) @@ -383,6 +396,13 @@ static int config_input(AVFilterLink *inlink) me_ctx->get_cost = &get_sbad_ob; return 0; +fail: + for (i = 0; i < NB_FRAMES; i++) + av_freep(&mi_ctx->frames[i].blocks); + av_freep(&mi_ctx->pixel_mvs); + av_freep(&mi_ctx->pixel_weights); + av_freep(&mi_ctx->pixel_refs); + return ret; } static int config_output(AVFilterLink *outlink) @@ -833,18 +853,18 @@ static int detect_scene_change(MIContext *mi_ctx) #define ADD_PIXELS(b_weight, mv_x, mv_y)\ do {\ - if (!b_weight || pixel->nb + 1 >= NB_PIXEL_MVS)\ + if (!b_weight || pixel_refs->nb + 1 >= NB_PIXEL_MVS)\ continue;\ - pixel->refs[pixel->nb] = 1;\ - pixel->weights[pixel->nb] = b_weight * (ALPHA_MAX - alpha);\ - pixel->mvs[pixel->nb][0] = av_clip((mv_x * alpha) / ALPHA_MAX, x_min, x_max);\ - pixel->mvs[pixel->nb][1] = av_clip((mv_y * alpha) / ALPHA_MAX, y_min, y_max);\ - pixel->nb++;\ - pixel->refs[pixel->nb] = 2;\ - pixel->weights[pixel->nb] = b_weight * alpha;\ - pixel->mvs[pixel->nb][0] = av_clip(-mv_x * (ALPHA_MAX - alpha) / ALPHA_MAX, x_min, x_max);\ - pixel->mvs[pixel->nb][1] = av_clip(-mv_y * (ALPHA_MAX - alpha) / ALPHA_MAX, y_min, y_max);\ - pixel->nb++;\ + pixel_refs->refs[pixel_refs->nb] = 1;\ + pixel_weights->weights[pixel_refs->nb] = b_weight * (ALPHA_MAX - alpha);\ + pixel_mvs->mvs[pixel_refs->nb][0] = av_clip((mv_x * alpha) / ALPHA_MAX, x_min, x_max);\ + pixel_mvs->mvs[pixel_refs->nb][1] = av_clip((mv_y * alpha) / ALPHA_MAX, y_min, y_max);\ + pixel_refs->nb++;\ + pixel_refs->refs[pixel_refs->nb] = 2;\ + pixel_weights->weights[pixel_refs->nb] = b_weight * alpha;\ + pixel_mvs->mvs[pixel_refs->nb][0] = av_clip(-mv_x * (ALPHA_MAX - alpha) / ALPHA_MAX, x_min, x_max);\ + pixel_mvs->mvs[pixel_refs->nb][1] = av_clip(-mv_y * (ALPHA_MAX - alpha) / ALPHA_MAX, y_min, y_max);\ + pixel_refs->nb++;\ } while(0) static void bidirectional_obmc(MIContext *mi_ctx, int alpha) @@ -856,7 +876,7 @@ static void bidirectional_obmc(MIContext *mi_ctx, int alpha) for (y = 0; y < height; y++) for (x = 0; x < width; x++) - mi_ctx->pixels[x + y * width].nb = 0; + mi_ctx->pixel_refs[x + y * width].nb = 0; for (dir = 0; dir < 2; dir++) for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++) @@ -887,7 +907,9 @@ static void bidirectional_obmc(MIContext *mi_ctx, int alpha) int x_min = -x; int x_max = width - x - 1; int obmc_weight = obmc_tab_linear[4 - mi_ctx->log2_mb_size][(x - start_x) + ((y - start_y) << (mi_ctx->log2_mb_size + 1))]; - Pixel *pixel = &mi_ctx->pixels[x + y * width]; + PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * width]; + PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * width]; + PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * width]; ADD_PIXELS(obmc_weight, mv_x, mv_y); } @@ -909,36 +931,38 @@ static void set_frame_data(MIContext *mi_ctx, int alpha, AVFrame *avf_out) int x_mv, y_mv; int weight_sum = 0; int i, val = 0; - Pixel *pixel = &mi_ctx->pixels[x + y * avf_out->width]; - - for (i = 0; i < pixel->nb; i++) - weight_sum += pixel->weights[i]; - - if (!weight_sum || !pixel->nb) { - pixel->weights[0] = ALPHA_MAX - alpha; - pixel->refs[0] = 1; - pixel->mvs[0][0] = 0; - pixel->mvs[0][1] = 0; - pixel->weights[1] = alpha; - pixel->refs[1] = 2; - pixel->mvs[1][0] = 0; - pixel->mvs[1][1] = 0; - pixel->nb = 2; + PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * avf_out->width]; + PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * avf_out->width]; + PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * avf_out->width]; + + for (i = 0; i < pixel_refs->nb; i++) + weight_sum += pixel_weights->weights[i]; + + if (!weight_sum || !pixel_refs->nb) { + pixel_weights->weights[0] = ALPHA_MAX - alpha; + pixel_refs->refs[0] = 1; + pixel_mvs->mvs[0][0] = 0; + pixel_mvs->mvs[0][1] = 0; + pixel_weights->weights[1] = alpha; + pixel_refs->refs[1] = 2; + pixel_mvs->mvs[1][0] = 0; + pixel_mvs->mvs[1][1] = 0; + pixel_refs->nb = 2; weight_sum = ALPHA_MAX; } - for (i = 0; i < pixel->nb; i++) { - Frame *frame = &mi_ctx->frames[pixel->refs[i]]; + for (i = 0; i < pixel_refs->nb; i++) { + Frame *frame = &mi_ctx->frames[pixel_refs->refs[i]]; if (chroma) { - x_mv = (x >> mi_ctx->log2_chroma_w) + pixel->mvs[i][0] / (1 << mi_ctx->log2_chroma_w); - y_mv = (y >> mi_ctx->log2_chroma_h) + pixel->mvs[i][1] / (1 << mi_ctx->log2_chroma_h); + x_mv = (x >> mi_ctx->log2_chroma_w) + pixel_mvs->mvs[i][0] / (1 << mi_ctx->log2_chroma_w); + y_mv = (y >> mi_ctx->log2_chroma_h) + pixel_mvs->mvs[i][1] / (1 << mi_ctx->log2_chroma_h); } else { - x_mv = x + pixel->mvs[i][0]; - y_mv = y + pixel->mvs[i][1]; + x_mv = x + pixel_mvs->mvs[i][0]; + y_mv = y + pixel_mvs->mvs[i][1]; } - val += pixel->weights[i] * frame->avf->data[plane][x_mv + y_mv * frame->avf->linesize[plane]]; + val += pixel_weights->weights[i] * frame->avf->data[plane][x_mv + y_mv * frame->avf->linesize[plane]]; } val = ROUNDED_DIV(val, weight_sum); @@ -979,7 +1003,9 @@ static void var_size_bmc(MIContext *mi_ctx, Block *block, int x_mb, int y_mb, in for (x = start_x; x < end_x; x++) { int x_min = -x; int x_max = width - x - 1; - Pixel *pixel = &mi_ctx->pixels[x + y * width]; + PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * width]; + PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * width]; + PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * width]; ADD_PIXELS(PX_WEIGHT_MAX, mv_x, mv_y); } @@ -1028,7 +1054,9 @@ static void bilateral_obmc(MIContext *mi_ctx, Block *block, int mb_x, int mb_y, int x_min = -x; int x_max = width - x - 1; int obmc_weight = obmc_tab_linear[4 - mi_ctx->log2_mb_size][(x - start_x) + ((y - start_y) << (mi_ctx->log2_mb_size + 1))]; - Pixel *pixel = &mi_ctx->pixels[x + y * width]; + PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * width]; + PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * width]; + PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * width]; if (mi_ctx->mc_mode == MC_MODE_AOBMC) { nb_x = (((x - start_x) >> (mi_ctx->log2_mb_size - 1)) * 2 - 3) / 2; @@ -1112,7 +1140,7 @@ static void interpolate(AVFilterLink *inlink, AVFrame *avf_out) for (y = 0; y < mi_ctx->frames[0].avf->height; y++) for (x = 0; x < mi_ctx->frames[0].avf->width; x++) - mi_ctx->pixels[x + y * mi_ctx->frames[0].avf->width].nb = 0; + mi_ctx->pixel_refs[x + y * mi_ctx->frames[0].avf->width].nb = 0; for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++) for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++) { @@ -1195,7 +1223,9 @@ static av_cold void uninit(AVFilterContext *ctx) MIContext *mi_ctx = ctx->priv; int i, m; - av_freep(&mi_ctx->pixels); + av_freep(&mi_ctx->pixel_mvs); + av_freep(&mi_ctx->pixel_weights); + av_freep(&mi_ctx->pixel_refs); if (mi_ctx->int_blocks) for (m = 0; m < mi_ctx->b_count; m++) free_blocks(&mi_ctx->int_blocks[m], 0); From 658bdc67715b3fbf75f92c7a459272149e3859df Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Wed, 27 Dec 2017 23:18:58 +0100 Subject: [PATCH 1490/2557] lavc/jpeg2000dec: Support reading 64-bit atom size. Fixes ticket #6935. --- libavcodec/jpeg2000dec.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 8071dc3c84a5f..01fe4b3949330 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -2009,7 +2009,16 @@ static int jp2_find_codestream(Jpeg2000DecoderContext *s) bytestream2_get_bytes_left(&s->g) >= 8) { atom_size = bytestream2_get_be32u(&s->g); atom = bytestream2_get_be32u(&s->g); - atom_end = bytestream2_tell(&s->g) + atom_size - 8; + if (atom_size == 1) { + if (bytestream2_get_be32u(&s->g)) { + avpriv_request_sample(s->avctx, "Huge atom"); + return 0; + } + atom_size = bytestream2_get_be32u(&s->g); + atom_end = bytestream2_tell(&s->g) + atom_size - 16; + } else { + atom_end = bytestream2_tell(&s->g) + atom_size - 8; + } if (atom == JP2_CODESTREAM) return 1; From be4dfbf7b71e44a53ca8da882a081e35ea134c83 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 28 Dec 2017 12:07:22 +0800 Subject: [PATCH 1491/2557] avformat/avio: check input URLContext value NULL Reviewed-by: Michael Niedermayer Reviewed-by: Karthick Jeyapal --- libavformat/avio.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavformat/avio.c b/libavformat/avio.c index 4dc468350c943..63e82872f7ce0 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -625,13 +625,15 @@ int64_t ffurl_size(URLContext *h) int ffurl_get_file_handle(URLContext *h) { - if (!h->prot->url_get_file_handle) + if (!h || !h->prot || !h->prot->url_get_file_handle) return -1; return h->prot->url_get_file_handle(h); } int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles) { + if (!h || !h->prot) + return AVERROR(ENOSYS); if (!h->prot->url_get_multi_file_handle) { if (!h->prot->url_get_file_handle) return AVERROR(ENOSYS); @@ -647,15 +649,15 @@ int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles) int ffurl_get_short_seek(URLContext *h) { - if (!h->prot->url_get_short_seek) + if (!h || !h->prot || !h->prot->url_get_short_seek) return AVERROR(ENOSYS); return h->prot->url_get_short_seek(h); } int ffurl_shutdown(URLContext *h, int flags) { - if (!h->prot->url_shutdown) - return AVERROR(EINVAL); + if (!h || !h->prot || !h->prot->url_shutdown) + return AVERROR(ENOSYS); return h->prot->url_shutdown(h, flags); } From 560daf88913b0de59a4d845bcd19254b406388dd Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 26 Dec 2017 23:24:43 +0100 Subject: [PATCH 1492/2557] avcodec/flacdec: avoid undefined shift Fixes: shift exponent 32 is too large for 32-bit type 'unsigned int' Fixes: 4688/clusterfuzz-testcase-minimized-6572210748653568 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/flacdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c index 6c8ba157773b9..64bea76f98df6 100644 --- a/libavcodec/flacdec.c +++ b/libavcodec/flacdec.c @@ -460,7 +460,7 @@ static inline int decode_subframe(FLACContext *s, int channel) return AVERROR_INVALIDDATA; } - if (wasted) { + if (wasted && wasted < 32) { int i; for (i = 0; i < s->blocksize; i++) decoded[i] = (unsigned)decoded[i] << wasted; From d135f3c514ac1723256c8e0f5cdd466fe98a2578 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 26 Dec 2017 23:24:45 +0100 Subject: [PATCH 1493/2557] avcodec/hevcdsp_template: Fix Invalid shifts in put_hevc_qpel_bi_w_h() and put_hevc_qpel_bi_w_w() Fixes: left shift of negative value -1 Fixes: 4690/clusterfuzz-testcase-minimized-6117482428366848 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevcdsp_template.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/hevcdsp_template.c b/libavcodec/hevcdsp_template.c index 903aa3fe9557e..56cd9e605d313 100644 --- a/libavcodec/hevcdsp_template.c +++ b/libavcodec/hevcdsp_template.c @@ -915,7 +915,7 @@ static void FUNC(put_hevc_qpel_bi_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = av_clip_pixel(((QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 + - ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); + ((ox0 + ox1 + 1) * (1 << log2Wd))) >> (log2Wd + 1)); src += srcstride; dst += dststride; src2 += MAX_PB_SIZE; @@ -970,7 +970,7 @@ static void FUNC(put_hevc_qpel_bi_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint for (y = 0; y < height; y++) { for (x = 0; x < width; x++) dst[x] = av_clip_pixel(((QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 + - ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1)); + ((ox0 + ox1 + 1) * (1 << log2Wd))) >> (log2Wd + 1)); src += srcstride; dst += dststride; src2 += MAX_PB_SIZE; From 3d23f7a0969bf76ad6dcdc2c4a5cd3ae884745a8 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 26 Dec 2017 23:24:44 +0100 Subject: [PATCH 1494/2557] avcodec/flacdec: Fix overflow in multiplication in decode_subframe_fixed() Fixes: signed integer overflow: 2 * 1629495328 cannot be represented in type 'int' Fixes: 4716/clusterfuzz-testcase-minimized-5835915940331520 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/flacdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c index 64bea76f98df6..c8eb456049db0 100644 --- a/libavcodec/flacdec.c +++ b/libavcodec/flacdec.c @@ -302,7 +302,7 @@ static int decode_subframe_fixed(FLACContext *s, int32_t *decoded, if (pred_order > 2) c = b - decoded[pred_order-2] + decoded[pred_order-3]; if (pred_order > 3) - d = c - decoded[pred_order-2] + 2*decoded[pred_order-3] - decoded[pred_order-4]; + d = c - decoded[pred_order-2] + 2U*decoded[pred_order-3] - decoded[pred_order-4]; switch (pred_order) { case 0: From e867b7b11a28a32ddbe769c12dbe5128a8a5872a Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Fri, 29 Dec 2017 01:54:59 +0100 Subject: [PATCH 1495/2557] fate: Fix ffprobe dependency for fate-mov-guess-delay-*. --- tests/fate/mov.mak | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 907dfa0b695a5..64f92e9488aa1 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -13,15 +13,15 @@ FATE_MOV = fate-mov-3elist \ fate-mov-elst-ends-betn-b-and-i \ fate-mov-frag-overlap \ fate-mov-bbi-elst-starts-b \ - fate-mov-guess-delay-1 \ - fate-mov-guess-delay-2 \ - fate-mov-guess-delay-3 \ FATE_MOV_FFPROBE = fate-mov-aac-2048-priming \ fate-mov-zombie \ fate-mov-init-nonkeyframe \ fate-mov-displaymatrix \ fate-mov-spherical-mono \ + fate-mov-guess-delay-1 \ + fate-mov-guess-delay-2 \ + fate-mov-guess-delay-3 \ FATE_SAMPLES_AVCONV += $(FATE_MOV) FATE_SAMPLES_FFPROBE += $(FATE_MOV_FFPROBE) From d01eeef4a2297dcc1fd9f125bed6bd8d1bed3b29 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 26 Nov 2017 14:29:27 +0100 Subject: [PATCH 1496/2557] configure: libvmaf depends on pthreads. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 70de780f82a39..688f6ab803856 100755 --- a/configure +++ b/configure @@ -3289,7 +3289,7 @@ uspp_filter_deps="gpl avcodec" vaguedenoiser_filter_deps="gpl" vidstabdetect_filter_deps="libvidstab" vidstabtransform_filter_deps="libvidstab" -libvmaf_filter_deps="libvmaf" +libvmaf_filter_deps="libvmaf pthreads" zmq_filter_deps="libzmq" zoompan_filter_deps="swscale" zscale_filter_deps="libzimg const_nan" From 9e25fe420410c0e1b77cc68f53cc0cd2f79ba30a Mon Sep 17 00:00:00 2001 From: Karthick Jeyapal Date: Fri, 29 Dec 2017 13:45:31 +0800 Subject: [PATCH 1497/2557] avformat/hlsenc: Modularized audio rendition playlist write to allow reuse Reviewed-by: Steven Liu --- libavformat/hlsenc.c | 6 ++---- libavformat/hlsplaylist.c | 9 +++++++++ libavformat/hlsplaylist.h | 1 + 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 74f66ce6bdd87..fe531fb43df85 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1169,10 +1169,8 @@ static int create_master_playlist(AVFormatContext *s, goto fail; } - avio_printf(hls->m3u8_out, "#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"group_%s\"", - vs->agroup); - avio_printf(hls->m3u8_out, ",NAME=\"audio_0\",DEFAULT=YES,URI=\"%s\"\n", - m3u8_rel_name); + ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name); + av_freep(&m3u8_rel_name); } diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c index 42f059aec92be..a065eda59db15 100644 --- a/libavformat/hlsplaylist.c +++ b/libavformat/hlsplaylist.c @@ -35,6 +35,15 @@ void ff_hls_write_playlist_version(AVIOContext *out, int version) { avio_printf(out, "#EXT-X-VERSION:%d\n", version); } +void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, + char *filename) { + if (!out || !agroup || !filename) + return; + + avio_printf(out, "#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"group_%s\"", agroup); + avio_printf(out, ",NAME=\"audio_0\",DEFAULT=YES,URI=\"%s\"\n", filename); +} + void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, char *filename, char *agroup) { if (!out || !filename) diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index ac03550651eaf..518cfc256b276 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -37,6 +37,7 @@ typedef enum { } PlaylistType; void ff_hls_write_playlist_version(AVIOContext *out, int version); +void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, char *filename); void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, char *filename, char *agroup); void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, From 8fd2bdd07207cc7e055915f470302596bcfebeea Mon Sep 17 00:00:00 2001 From: Karthick Jeyapal Date: Fri, 29 Dec 2017 13:47:12 +0800 Subject: [PATCH 1498/2557] avformat/hlsplaylist: Audio rendition's name and defaultness made configurable Reviewed-by: Steven Liu --- libavformat/hlsenc.c | 2 +- libavformat/hlsplaylist.c | 5 +++-- libavformat/hlsplaylist.h | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index fe531fb43df85..5cff3b4bf6432 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1169,7 +1169,7 @@ static int create_master_playlist(AVFormatContext *s, goto fail; } - ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name); + ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name, 0, 1); av_freep(&m3u8_rel_name); } diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c index a065eda59db15..098dc8917032d 100644 --- a/libavformat/hlsplaylist.c +++ b/libavformat/hlsplaylist.c @@ -36,12 +36,13 @@ void ff_hls_write_playlist_version(AVIOContext *out, int version) { } void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, - char *filename) { + char *filename, int name_id, int is_default) { if (!out || !agroup || !filename) return; avio_printf(out, "#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"group_%s\"", agroup); - avio_printf(out, ",NAME=\"audio_0\",DEFAULT=YES,URI=\"%s\"\n", filename); + avio_printf(out, ",NAME=\"audio_%d\",DEFAULT=%s,URI=\"%s\"\n", name_id, + is_default ? "YES" : "NO", filename); } void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index 518cfc256b276..9969315e00501 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -37,7 +37,8 @@ typedef enum { } PlaylistType; void ff_hls_write_playlist_version(AVIOContext *out, int version); -void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, char *filename); +void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, + char *filename, int name_id, int is_default); void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, char *filename, char *agroup); void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, From 5297ae96a13f615431c9a4cc38cac13c4140b07e Mon Sep 17 00:00:00 2001 From: Karthick Jeyapal Date: Fri, 29 Dec 2017 13:47:53 +0800 Subject: [PATCH 1499/2557] avformat/dashenc: Addition of #EXT-X-MEDIA tag and AUDIO attribute This is required for AV playout from master.m3u8. Otherwise master.m3u8 lists only video-only and/or audio-only streams. Reviewed-by: Steven Liu --- libavformat/dashenc.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 478a384f555de..a3eb522c38e72 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -737,6 +737,9 @@ static int write_manifest(AVFormatContext *s, int final) if (c->hls_playlist && !c->master_playlist_created) { char filename_hls[1024]; + const char *audio_group = "A1"; + int is_default = 1; + int max_audio_bitrate = 0; if (*c->dirname) snprintf(filename_hls, sizeof(filename_hls), "%s/master.m3u8", c->dirname); @@ -758,9 +761,26 @@ static int write_manifest(AVFormatContext *s, int final) for (i = 0; i < s->nb_streams; i++) { char playlist_file[64]; AVStream *st = s->streams[i]; + if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) + continue; + get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i); + ff_hls_write_audio_rendition(out, (char *)audio_group, + playlist_file, i, is_default); + max_audio_bitrate = FFMAX(st->codecpar->bit_rate, max_audio_bitrate); + is_default = 0; + } + + for (i = 0; i < s->nb_streams; i++) { + char playlist_file[64]; + AVStream *st = s->streams[i]; + char *agroup = NULL; + int stream_bitrate = st->codecpar->bit_rate; + if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && max_audio_bitrate) { + agroup = (char *)audio_group; + stream_bitrate += max_audio_bitrate; + } get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i); - ff_hls_write_stream_info(st, out, st->codecpar->bit_rate, - playlist_file, NULL); + ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, agroup); } avio_close(out); if (use_rename) From e8f71ef338998458bbbaf09a11bc07f07fbc7954 Mon Sep 17 00:00:00 2001 From: Karthick Jeyapal Date: Fri, 29 Dec 2017 18:11:09 +0800 Subject: [PATCH 1500/2557] avformat/hlsenc, utils: Moved is_http_proto from hlsenc to utils for re-use Reviewed-by: Aman Gupta Reviewed-by: Steven Liu --- libavformat/hlsenc.c | 12 +++--------- libavformat/internal.h | 8 ++++++++ libavformat/utils.c | 5 +++++ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 5cff3b4bf6432..e6f3241765176 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -241,15 +241,10 @@ static int mkdir_p(const char *path) { return ret; } -static int is_http_proto(char *filename) { - const char *proto = avio_find_protocol_name(filename); - return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, "https")) : 0; -} - static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, AVDictionary **options) { HLSContext *hls = s->priv_data; - int http_base_proto = filename ? is_http_proto(filename) : 0; + int http_base_proto = filename ? ff_is_http_proto(filename) : 0; int err = AVERROR_MUXER_NOT_FOUND; if (!*pb || !http_base_proto || !hls->http_persistent) { err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options); @@ -265,8 +260,7 @@ static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) { HLSContext *hls = s->priv_data; - int http_base_proto = filename ? is_http_proto(filename) : 0; - + int http_base_proto = filename ? ff_is_http_proto(filename) : 0; if (!http_base_proto || !hls->http_persistent || hls->key_info_file || hls->encrypt) { ff_format_io_close(s, pb); #if CONFIG_HTTP_PROTOCOL @@ -281,7 +275,7 @@ static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSContext *c) { - int http_base_proto = is_http_proto(s->filename); + int http_base_proto = ff_is_http_proto(s->filename); if (c->method) { av_dict_set(options, "method", c->method, 0); diff --git a/libavformat/internal.h b/libavformat/internal.h index 30715b3f500eb..0cd0556dc799e 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -621,6 +621,14 @@ int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **op */ void ff_format_io_close(AVFormatContext *s, AVIOContext **pb); +/** + * Utility function to check if the file uses http or https protocol + * + * @param s AVFormatContext + * @param filename URL or file name to open for writing + */ +int ff_is_http_proto(char *filename); + /** * Parse creation_time in AVFormatContext metadata if exists and warn if the * parsing fails. diff --git a/libavformat/utils.c b/libavformat/utils.c index 9b46bd6737310..2185a6f05b089 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -5472,6 +5472,11 @@ void ff_format_io_close(AVFormatContext *s, AVIOContext **pb) *pb = NULL; } +int ff_is_http_proto(char *filename) { + const char *proto = avio_find_protocol_name(filename); + return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, "https")) : 0; +} + int ff_parse_creation_time_metadata(AVFormatContext *s, int64_t *timestamp, int return_seconds) { AVDictionaryEntry *entry; From 0c78b6a416c661afed745d44495b5194f714fb96 Mon Sep 17 00:00:00 2001 From: Karthick Jeyapal Date: Fri, 29 Dec 2017 18:12:32 +0800 Subject: [PATCH 1501/2557] avformat/dashenc: Persistent HTTP connections supported as an option Reviewed-by: Aman Gupta Reviewed-by: Steven Liu --- doc/muxers.texi | 2 ++ libavformat/dashenc.c | 67 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 93db54926589c..8ce964b0a0f13 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -249,6 +249,8 @@ DASH-templated name to used for the media segments. Default is "chunk-stream$Rep URL of the page that will return the UTC timestamp in ISO format. Example: "https://time.akamai.com/?iso" @item -http_user_agent @var{user_agent} Override User-Agent field in HTTP header. Applicable only for HTTP output. +@item -http_persistent @var{http_persistent} +Use persistent HTTP connections. Applicable only for HTTP output. @item -hls_playlist @var{hls_playlist} Generate HLS playlist files as well. The master playlist is generated with the filename master.m3u8. One media playlist file is generated for each stream with filenames media_0.m3u8, media_1.m3u8, etc. diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index a3eb522c38e72..3345b89118d77 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -37,6 +37,9 @@ #include "avformat.h" #include "avio_internal.h" #include "hlsplaylist.h" +#if CONFIG_HTTP_PROTOCOL +#include "http.h" +#endif #include "internal.h" #include "isom.h" #include "os_support.h" @@ -103,7 +106,10 @@ typedef struct DASHContext { const char *utc_timing_url; const char *user_agent; int hls_playlist; + int http_persistent; int master_playlist_created; + AVIOContext *mpd_out; + AVIOContext *m3u8_out; } DASHContext; static struct codec_string { @@ -117,6 +123,36 @@ static struct codec_string { { 0, NULL } }; +static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, + AVDictionary **options) { + DASHContext *c = s->priv_data; + int http_base_proto = filename ? ff_is_http_proto(filename) : 0; + int err = AVERROR_MUXER_NOT_FOUND; + if (!*pb || !http_base_proto || !c->http_persistent) { + err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options); +#if CONFIG_HTTP_PROTOCOL + } else { + URLContext *http_url_context = ffio_geturlcontext(*pb); + av_assert0(http_url_context); + err = ff_http_do_new_request(http_url_context, filename); +#endif + } + return err; +} + +static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) { + DASHContext *c = s->priv_data; + int http_base_proto = filename ? ff_is_http_proto(filename) : 0; + + if (!http_base_proto || !c->http_persistent) { + ff_format_io_close(s, pb); +#if CONFIG_HTTP_PROTOCOL + } else { + avio_flush(*pb); +#endif + } +} + static void set_codec_str(AVFormatContext *s, AVCodecParameters *par, char *str, int size) { @@ -218,6 +254,8 @@ static void set_http_options(AVDictionary **options, DASHContext *c) { if (c->user_agent) av_dict_set(options, "user_agent", c->user_agent, 0); + if (c->http_persistent) + av_dict_set_int(options, "multiple_requests", 1, 0); } static void get_hls_playlist_name(char *playlist_name, int string_size, @@ -273,9 +311,10 @@ static void dash_free(AVFormatContext *s) av_freep(&c->streams); } -static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext *c, +static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatContext *s, int representation_id, int final) { + DASHContext *c = s->priv_data; int i, start_index = 0, start_number = 1; if (c->window_size) { start_index = FFMAX(os->nb_segments - c->window_size, 0); @@ -339,7 +378,6 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext int timescale = os->ctx->streams[0]->time_base.den; char temp_filename_hls[1024]; char filename_hls[1024]; - AVIOContext *out_hls = NULL; AVDictionary *http_opts = NULL; int target_duration = 0; int ret = 0; @@ -352,7 +390,7 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? "%s.tmp" : "%s", filename_hls); set_http_options(&http_opts, c); - avio_open2(&out_hls, temp_filename_hls, AVIO_FLAG_WRITE, NULL, &http_opts); + dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts); av_dict_free(&http_opts); for (i = start_index; i < os->nb_segments; i++) { Segment *seg = os->segments[i]; @@ -361,15 +399,15 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext target_duration = lrint(duration); } - ff_hls_write_playlist_header(out_hls, 6, -1, target_duration, + ff_hls_write_playlist_header(c->m3u8_out, 6, -1, target_duration, start_number, PLAYLIST_TYPE_NONE); - ff_hls_write_init_file(out_hls, os->initfile, c->single_file, + ff_hls_write_init_file(c->m3u8_out, os->initfile, c->single_file, os->init_range_length, os->init_start_pos); for (i = start_index; i < os->nb_segments; i++) { Segment *seg = os->segments[i]; - ret = ff_hls_write_file_entry(out_hls, 0, c->single_file, + ret = ff_hls_write_file_entry(c->m3u8_out, 0, c->single_file, (double) seg->duration / timescale, 0, seg->range_length, seg->start_pos, NULL, c->single_file ? os->initfile : seg->file, @@ -380,9 +418,10 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext } if (final) - ff_hls_write_end_list(out_hls); + ff_hls_write_end_list(c->m3u8_out); + + dashenc_io_close(s, &c->m3u8_out, temp_filename_hls); - avio_close(out_hls); if (use_rename) if (avpriv_io_move(temp_filename_hls, filename_hls) < 0) { av_log(os->ctx, AV_LOG_WARNING, "renaming file %s to %s failed\n\n", temp_filename_hls, filename_hls); @@ -498,7 +537,7 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind avio_printf(out, "\t\t\t\t\n", s->streams[i]->codecpar->channels); } - output_segment_list(os, out, c, i, final); + output_segment_list(os, out, s, i, final); avio_printf(out, "\t\t\t\n"); } avio_printf(out, "\t\t\n"); @@ -657,11 +696,12 @@ static int write_manifest(AVFormatContext *s, int final) snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->filename); set_http_options(&opts, c); - ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, &opts); + ret = dashenc_io_open(s, &c->mpd_out, temp_filename, &opts); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename); return ret; } + out = c->mpd_out; av_dict_free(&opts); avio_printf(out, "\n"); avio_printf(out, "\n"); avio_flush(out); - ff_format_io_close(s, &out); + dashenc_io_close(s, &c->mpd_out, temp_filename); if (use_rename) { if ((ret = avpriv_io_move(temp_filename, s->filename)) < 0) @@ -1115,7 +1155,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename); snprintf(temp_path, sizeof(temp_path), use_rename ? "%s.tmp" : "%s", full_path); set_http_options(&opts, c); - ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE, &opts); + ret = dashenc_io_open(s, &os->out, temp_path, &opts); if (ret < 0) break; av_dict_free(&opts); @@ -1133,7 +1173,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) if (c->single_file) { find_index_range(s, full_path, os->pos, &index_length); } else { - ff_format_io_close(s, &os->out); + dashenc_io_close(s, &os->out, temp_path); if (use_rename) { ret = avpriv_io_move(temp_path, full_path); @@ -1330,6 +1370,7 @@ static const AVOption options[] = { { "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.m4s"}, 0, 0, E }, { "utc_timing_url", "URL of the page that will return the UTC timestamp in ISO format", OFFSET(utc_timing_url), AV_OPT_TYPE_STRING, { 0 }, 0, 0, E }, { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, + { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { NULL }, }; From e23190269fb6e8217d080918893641ba3e0e3556 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Thu, 28 Dec 2017 17:38:32 +0800 Subject: [PATCH 1502/2557] lavu/qsv: add log message for libmfx version It is benefit to diagnose issues related to different libmfx version. Signed-off-by: Zhong Li Signed-off-by: Luca Barbato --- libavutil/hwcontext_qsv.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 5018a05b9aec5..9270b2258f591 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -1036,6 +1036,10 @@ static int qsv_device_derive_from_child(AVHWDeviceContext *ctx, goto fail; } + av_log(ctx, AV_LOG_VERBOSE, + "Initialize MFX session: API version is %d.%d, implementation version is %d.%d\n", + MFX_VERSION_MAJOR, MFX_VERSION_MINOR, ver.Major, ver.Minor); + MFXClose(hwctx->session); err = MFXInit(implementation, &ver, &hwctx->session); From 1efbbfedcaf4a3cecab980273ad809ba3ade2f74 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Thu, 28 Dec 2017 17:38:33 +0800 Subject: [PATCH 1503/2557] examples/qsvdec: do not set the deprecated field refcounted_frames It is used by the deprecated API avcodec_decode_video2 and ignored by the new decode APIs (avcodec_send_packet/avcodec_receive_frame). Signed-off-by: Zhong Li Signed-off-by: Luca Barbato --- doc/examples/qsvdec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/examples/qsvdec.c b/doc/examples/qsvdec.c index 46e6ddcb0dc63..cede6153bed3b 100644 --- a/doc/examples/qsvdec.c +++ b/doc/examples/qsvdec.c @@ -210,7 +210,6 @@ int main(int argc, char **argv) video_st->codecpar->extradata_size); decoder_ctx->extradata_size = video_st->codecpar->extradata_size; } - decoder_ctx->refcounted_frames = 1; decoder_ctx->opaque = &decode; decoder_ctx->get_format = get_format; From 51027d0b8b2835d4c70c9cb7b2ab5e28d5e3f22f Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 30 Dec 2017 17:02:54 +0000 Subject: [PATCH 1504/2557] opus: merge encoder and decoder bitallocation functions into one There's no difference apart from which entropy coding functions get called. Signed-off-by: Rostislav Pehlivanov --- libavcodec/opus.c | 348 +++++++++++++++++++++++++++++++++++++++ libavcodec/opus.h | 3 + libavcodec/opus_celt.c | 334 +------------------------------------ libavcodec/opusenc.c | 337 +------------------------------------ libavcodec/opusenc.h | 2 - libavcodec/opusenc_psy.c | 2 +- 6 files changed, 358 insertions(+), 668 deletions(-) diff --git a/libavcodec/opus.c b/libavcodec/opus.c index 46b749cae67c8..9cbf4aed92868 100644 --- a/libavcodec/opus.c +++ b/libavcodec/opus.c @@ -546,3 +546,351 @@ void ff_celt_quant_bands(CeltFrame *f, OpusRangeCoder *rc) update_lowband = (b > band_size << 3); } } + +#define NORMC(bits) ((bits) << (f->channels - 1) << f->size >> 2) + +void ff_celt_bitalloc(CeltFrame *f, OpusRangeCoder *rc, int encode) +{ + int i, j, low, high, total, done, bandbits, remaining, tbits_8ths; + int skip_startband = f->start_band; + int skip_bit = 0; + int intensitystereo_bit = 0; + int dualstereo_bit = 0; + int dynalloc = 6; + int extrabits = 0; + + int boost[CELT_MAX_BANDS] = { 0 }; + int trim_offset[CELT_MAX_BANDS]; + int threshold[CELT_MAX_BANDS]; + int bits1[CELT_MAX_BANDS]; + int bits2[CELT_MAX_BANDS]; + + /* Spread */ + if (opus_rc_tell(rc) + 4 <= f->framebits) + if (encode) + ff_opus_rc_enc_cdf(rc, f->spread, ff_celt_model_spread); + else + f->spread = ff_opus_rc_dec_cdf(rc, ff_celt_model_spread); + else + f->spread = CELT_SPREAD_NORMAL; + + /* Initialize static allocation caps */ + for (i = 0; i < CELT_MAX_BANDS; i++) + f->caps[i] = NORMC((ff_celt_static_caps[f->size][f->channels - 1][i] + 64) * ff_celt_freq_range[i]); + + /* Band boosts */ + tbits_8ths = f->framebits << 3; + for (i = f->start_band; i < f->end_band; i++) { + int quanta = ff_celt_freq_range[i] << (f->channels - 1) << f->size; + int b_dynalloc = dynalloc; + int boost_amount = f->alloc_boost[i]; + quanta = FFMIN(quanta << 3, FFMAX(6 << 3, quanta)); + + while (opus_rc_tell_frac(rc) + (b_dynalloc << 3) < tbits_8ths && boost[i] < f->caps[i]) { + int is_boost; + if (encode) { + is_boost = boost_amount--; + ff_opus_rc_enc_log(rc, is_boost, b_dynalloc); + } else { + is_boost = ff_opus_rc_dec_log(rc, b_dynalloc); + } + + if (!is_boost) + break; + + boost[i] += quanta; + tbits_8ths -= quanta; + + b_dynalloc = 1; + } + + if (boost[i]) + dynalloc = FFMAX(dynalloc - 1, 2); + } + + /* Allocation trim */ + if (opus_rc_tell_frac(rc) + (6 << 3) <= tbits_8ths) + if (encode) + ff_opus_rc_enc_cdf(rc, f->alloc_trim, ff_celt_model_alloc_trim); + else + f->alloc_trim = ff_opus_rc_dec_cdf(rc, ff_celt_model_alloc_trim); + + /* Anti-collapse bit reservation */ + tbits_8ths = (f->framebits << 3) - opus_rc_tell_frac(rc) - 1; + f->anticollapse_needed = 0; + if (f->transient && f->size >= 2 && tbits_8ths >= ((f->size + 2) << 3)) + f->anticollapse_needed = 1 << 3; + tbits_8ths -= f->anticollapse_needed; + + /* Band skip bit reservation */ + if (tbits_8ths >= 1 << 3) + skip_bit = 1 << 3; + tbits_8ths -= skip_bit; + + /* Intensity/dual stereo bit reservation */ + if (f->channels == 2) { + intensitystereo_bit = ff_celt_log2_frac[f->end_band - f->start_band]; + if (intensitystereo_bit <= tbits_8ths) { + tbits_8ths -= intensitystereo_bit; + if (tbits_8ths >= 1 << 3) { + dualstereo_bit = 1 << 3; + tbits_8ths -= 1 << 3; + } + } else { + intensitystereo_bit = 0; + } + } + + /* Trim offsets */ + for (i = f->start_band; i < f->end_band; i++) { + int trim = f->alloc_trim - 5 - f->size; + int band = ff_celt_freq_range[i] * (f->end_band - i - 1); + int duration = f->size + 3; + int scale = duration + f->channels - 1; + + /* PVQ minimum allocation threshold, below this value the band is + * skipped */ + threshold[i] = FFMAX(3 * ff_celt_freq_range[i] << duration >> 4, + f->channels << 3); + + trim_offset[i] = trim * (band << scale) >> 6; + + if (ff_celt_freq_range[i] << f->size == 1) + trim_offset[i] -= f->channels << 3; + } + + /* Bisection */ + low = 1; + high = CELT_VECTORS - 1; + while (low <= high) { + int center = (low + high) >> 1; + done = total = 0; + + for (i = f->end_band - 1; i >= f->start_band; i--) { + bandbits = NORMC(ff_celt_freq_range[i] * ff_celt_static_alloc[center][i]); + + if (bandbits) + bandbits = FFMAX(bandbits + trim_offset[i], 0); + bandbits += boost[i]; + + if (bandbits >= threshold[i] || done) { + done = 1; + total += FFMIN(bandbits, f->caps[i]); + } else if (bandbits >= f->channels << 3) { + total += f->channels << 3; + } + } + + if (total > tbits_8ths) + high = center - 1; + else + low = center + 1; + } + high = low--; + + /* Bisection */ + for (i = f->start_band; i < f->end_band; i++) { + bits1[i] = NORMC(ff_celt_freq_range[i] * ff_celt_static_alloc[low][i]); + bits2[i] = high >= CELT_VECTORS ? f->caps[i] : + NORMC(ff_celt_freq_range[i] * ff_celt_static_alloc[high][i]); + + if (bits1[i]) + bits1[i] = FFMAX(bits1[i] + trim_offset[i], 0); + if (bits2[i]) + bits2[i] = FFMAX(bits2[i] + trim_offset[i], 0); + + if (low) + bits1[i] += boost[i]; + bits2[i] += boost[i]; + + if (boost[i]) + skip_startband = i; + bits2[i] = FFMAX(bits2[i] - bits1[i], 0); + } + + /* Bisection */ + low = 0; + high = 1 << CELT_ALLOC_STEPS; + for (i = 0; i < CELT_ALLOC_STEPS; i++) { + int center = (low + high) >> 1; + done = total = 0; + + for (j = f->end_band - 1; j >= f->start_band; j--) { + bandbits = bits1[j] + (center * bits2[j] >> CELT_ALLOC_STEPS); + + if (bandbits >= threshold[j] || done) { + done = 1; + total += FFMIN(bandbits, f->caps[j]); + } else if (bandbits >= f->channels << 3) + total += f->channels << 3; + } + if (total > tbits_8ths) + high = center; + else + low = center; + } + + /* Bisection */ + done = total = 0; + for (i = f->end_band - 1; i >= f->start_band; i--) { + bandbits = bits1[i] + (low * bits2[i] >> CELT_ALLOC_STEPS); + + if (bandbits >= threshold[i] || done) + done = 1; + else + bandbits = (bandbits >= f->channels << 3) ? + f->channels << 3 : 0; + + bandbits = FFMIN(bandbits, f->caps[i]); + f->pulses[i] = bandbits; + total += bandbits; + } + + /* Band skipping */ + for (f->coded_bands = f->end_band; ; f->coded_bands--) { + int allocation; + j = f->coded_bands - 1; + + if (j == skip_startband) { + /* all remaining bands are not skipped */ + tbits_8ths += skip_bit; + break; + } + + /* determine the number of bits available for coding "do not skip" markers */ + remaining = tbits_8ths - total; + bandbits = remaining / (ff_celt_freq_bands[j+1] - ff_celt_freq_bands[f->start_band]); + remaining -= bandbits * (ff_celt_freq_bands[j+1] - ff_celt_freq_bands[f->start_band]); + allocation = f->pulses[j] + bandbits * ff_celt_freq_range[j]; + allocation += FFMAX(remaining - (ff_celt_freq_bands[j] - ff_celt_freq_bands[f->start_band]), 0); + + /* a "do not skip" marker is only coded if the allocation is + * above the chosen threshold */ + if (allocation >= FFMAX(threshold[j], (f->channels + 1) << 3)) { + int do_not_skip; + if (encode) { + do_not_skip = f->coded_bands <= f->skip_band_floor; + ff_opus_rc_enc_log(rc, do_not_skip, 1); + } else { + do_not_skip = ff_opus_rc_dec_log(rc, 1); + } + + if (do_not_skip) + break; + + total += 1 << 3; + allocation -= 1 << 3; + } + + /* the band is skipped, so reclaim its bits */ + total -= f->pulses[j]; + if (intensitystereo_bit) { + total -= intensitystereo_bit; + intensitystereo_bit = ff_celt_log2_frac[j - f->start_band]; + total += intensitystereo_bit; + } + + total += f->pulses[j] = (allocation >= f->channels << 3) ? f->channels << 3 : 0; + } + + /* IS start band */ + if (encode) { + if (intensitystereo_bit) { + f->intensity_stereo = FFMIN(f->intensity_stereo, f->coded_bands); + ff_opus_rc_enc_uint(rc, f->intensity_stereo, f->coded_bands + 1 - f->start_band); + } + } else { + f->intensity_stereo = f->dual_stereo = 0; + if (intensitystereo_bit) + f->intensity_stereo = f->start_band + ff_opus_rc_dec_uint(rc, f->coded_bands + 1 - f->start_band); + } + + /* DS flag */ + if (f->intensity_stereo <= f->start_band) + tbits_8ths += dualstereo_bit; /* no intensity stereo means no dual stereo */ + else if (dualstereo_bit) + if (encode) + ff_opus_rc_enc_log(rc, f->dual_stereo, 1); + else + f->dual_stereo = ff_opus_rc_dec_log(rc, 1); + + /* Supply the remaining bits in this frame to lower bands */ + remaining = tbits_8ths - total; + bandbits = remaining / (ff_celt_freq_bands[f->coded_bands] - ff_celt_freq_bands[f->start_band]); + remaining -= bandbits * (ff_celt_freq_bands[f->coded_bands] - ff_celt_freq_bands[f->start_band]); + for (i = f->start_band; i < f->coded_bands; i++) { + const int bits = FFMIN(remaining, ff_celt_freq_range[i]); + f->pulses[i] += bits + bandbits * ff_celt_freq_range[i]; + remaining -= bits; + } + + /* Finally determine the allocation */ + for (i = f->start_band; i < f->coded_bands; i++) { + int N = ff_celt_freq_range[i] << f->size; + int prev_extra = extrabits; + f->pulses[i] += extrabits; + + if (N > 1) { + int dof; /* degrees of freedom */ + int temp; /* dof * channels * log(dof) */ + int fine_bits; + int max_bits; + int offset; /* fine energy quantization offset, i.e. + * extra bits assigned over the standard + * totalbits/dof */ + + extrabits = FFMAX(f->pulses[i] - f->caps[i], 0); + f->pulses[i] -= extrabits; + + /* intensity stereo makes use of an extra degree of freedom */ + dof = N * f->channels + (f->channels == 2 && N > 2 && !f->dual_stereo && i < f->intensity_stereo); + temp = dof * (ff_celt_log_freq_range[i] + (f->size << 3)); + offset = (temp >> 1) - dof * CELT_FINE_OFFSET; + if (N == 2) /* dof=2 is the only case that doesn't fit the model */ + offset += dof << 1; + + /* grant an additional bias for the first and second pulses */ + if (f->pulses[i] + offset < 2 * (dof << 3)) + offset += temp >> 2; + else if (f->pulses[i] + offset < 3 * (dof << 3)) + offset += temp >> 3; + + fine_bits = (f->pulses[i] + offset + (dof << 2)) / (dof << 3); + max_bits = FFMIN((f->pulses[i] >> 3) >> (f->channels - 1), CELT_MAX_FINE_BITS); + max_bits = FFMAX(max_bits, 0); + f->fine_bits[i] = av_clip(fine_bits, 0, max_bits); + + /* If fine_bits was rounded down or capped, + * give priority for the final fine energy pass */ + f->fine_priority[i] = (f->fine_bits[i] * (dof << 3) >= f->pulses[i] + offset); + + /* the remaining bits are assigned to PVQ */ + f->pulses[i] -= f->fine_bits[i] << (f->channels - 1) << 3; + } else { + /* all bits go to fine energy except for the sign bit */ + extrabits = FFMAX(f->pulses[i] - (f->channels << 3), 0); + f->pulses[i] -= extrabits; + f->fine_bits[i] = 0; + f->fine_priority[i] = 1; + } + + /* hand back a limited number of extra fine energy bits to this band */ + if (extrabits > 0) { + int fineextra = FFMIN(extrabits >> (f->channels + 2), + CELT_MAX_FINE_BITS - f->fine_bits[i]); + f->fine_bits[i] += fineextra; + + fineextra <<= f->channels + 2; + f->fine_priority[i] = (fineextra >= extrabits - prev_extra); + extrabits -= fineextra; + } + } + f->remaining = extrabits; + + /* skipped bands dedicate all of their bits for fine energy */ + for (; i < f->end_band; i++) { + f->fine_bits[i] = f->pulses[i] >> (f->channels - 1) >> 3; + f->pulses[i] = 0; + f->fine_priority[i] = f->fine_bits[i] < 1; + } +} diff --git a/libavcodec/opus.h b/libavcodec/opus.h index a10db7f0e8345..edbaab5ce7d06 100644 --- a/libavcodec/opus.h +++ b/libavcodec/opus.h @@ -194,4 +194,7 @@ int ff_silk_decode_superframe(SilkContext *s, OpusRangeCoder *rc, /* Encode or decode CELT bands */ void ff_celt_quant_bands(CeltFrame *f, OpusRangeCoder *rc); +/* Encode or decode CELT bitallocation */ +void ff_celt_bitalloc(CeltFrame *f, OpusRangeCoder *rc, int encode); + #endif /* AVCODEC_OPUS_H */ diff --git a/libavcodec/opus_celt.c b/libavcodec/opus_celt.c index ff74e2f067955..115dd8c63e5b2 100644 --- a/libavcodec/opus_celt.c +++ b/libavcodec/opus_celt.c @@ -143,338 +143,6 @@ static void celt_decode_tf_changes(CeltFrame *f, OpusRangeCoder *rc) } } -static void celt_decode_allocation(CeltFrame *f, OpusRangeCoder *rc) -{ - // approx. maximum bit allocation for each band before boost/trim - int cap[CELT_MAX_BANDS]; - int boost[CELT_MAX_BANDS]; - int threshold[CELT_MAX_BANDS]; - int bits1[CELT_MAX_BANDS]; - int bits2[CELT_MAX_BANDS]; - int trim_offset[CELT_MAX_BANDS]; - - int skip_start_band = f->start_band; - int dynalloc = 6; - int alloctrim = 5; - int extrabits = 0; - - int skip_bit = 0; - int intensity_stereo_bit = 0; - int dual_stereo_bit = 0; - - int remaining, bandbits; - int low, high, total, done; - int totalbits; - int consumed; - int i, j; - - consumed = opus_rc_tell(rc); - - /* obtain spread flag */ - f->spread = CELT_SPREAD_NORMAL; - if (consumed + 4 <= f->framebits) - f->spread = ff_opus_rc_dec_cdf(rc, ff_celt_model_spread); - - /* generate static allocation caps */ - for (i = 0; i < CELT_MAX_BANDS; i++) { - cap[i] = (ff_celt_static_caps[f->size][f->channels - 1][i] + 64) - * ff_celt_freq_range[i] << (f->channels - 1) << f->size >> 2; - } - - /* obtain band boost */ - totalbits = f->framebits << 3; // convert to 1/8 bits - consumed = opus_rc_tell_frac(rc); - for (i = f->start_band; i < f->end_band; i++) { - int quanta, band_dynalloc; - - boost[i] = 0; - - quanta = ff_celt_freq_range[i] << (f->channels - 1) << f->size; - quanta = FFMIN(quanta << 3, FFMAX(6 << 3, quanta)); - band_dynalloc = dynalloc; - while (consumed + (band_dynalloc<<3) < totalbits && boost[i] < cap[i]) { - int add = ff_opus_rc_dec_log(rc, band_dynalloc); - consumed = opus_rc_tell_frac(rc); - if (!add) - break; - - boost[i] += quanta; - totalbits -= quanta; - band_dynalloc = 1; - } - /* dynalloc is more likely to occur if it's already been used for earlier bands */ - if (boost[i]) - dynalloc = FFMAX(2, dynalloc - 1); - } - - /* obtain allocation trim */ - if (consumed + (6 << 3) <= totalbits) - alloctrim = ff_opus_rc_dec_cdf(rc, ff_celt_model_alloc_trim); - - /* anti-collapse bit reservation */ - totalbits = (f->framebits << 3) - opus_rc_tell_frac(rc) - 1; - f->anticollapse_needed = 0; - if (f->blocks > 1 && f->size >= 2 && - totalbits >= ((f->size + 2) << 3)) - f->anticollapse_needed = 1 << 3; - totalbits -= f->anticollapse_needed; - - /* band skip bit reservation */ - if (totalbits >= 1 << 3) - skip_bit = 1 << 3; - totalbits -= skip_bit; - - /* intensity/dual stereo bit reservation */ - if (f->channels == 2) { - intensity_stereo_bit = ff_celt_log2_frac[f->end_band - f->start_band]; - if (intensity_stereo_bit <= totalbits) { - totalbits -= intensity_stereo_bit; - if (totalbits >= 1 << 3) { - dual_stereo_bit = 1 << 3; - totalbits -= 1 << 3; - } - } else - intensity_stereo_bit = 0; - } - - for (i = f->start_band; i < f->end_band; i++) { - int trim = alloctrim - 5 - f->size; - int band = ff_celt_freq_range[i] * (f->end_band - i - 1); - int duration = f->size + 3; - int scale = duration + f->channels - 1; - - /* PVQ minimum allocation threshold, below this value the band is - * skipped */ - threshold[i] = FFMAX(3 * ff_celt_freq_range[i] << duration >> 4, - f->channels << 3); - - trim_offset[i] = trim * (band << scale) >> 6; - - if (ff_celt_freq_range[i] << f->size == 1) - trim_offset[i] -= f->channels << 3; - } - - /* bisection */ - low = 1; - high = CELT_VECTORS - 1; - while (low <= high) { - int center = (low + high) >> 1; - done = total = 0; - - for (i = f->end_band - 1; i >= f->start_band; i--) { - bandbits = ff_celt_freq_range[i] * ff_celt_static_alloc[center][i] - << (f->channels - 1) << f->size >> 2; - - if (bandbits) - bandbits = FFMAX(0, bandbits + trim_offset[i]); - bandbits += boost[i]; - - if (bandbits >= threshold[i] || done) { - done = 1; - total += FFMIN(bandbits, cap[i]); - } else if (bandbits >= f->channels << 3) - total += f->channels << 3; - } - - if (total > totalbits) - high = center - 1; - else - low = center + 1; - } - high = low--; - - for (i = f->start_band; i < f->end_band; i++) { - bits1[i] = ff_celt_freq_range[i] * ff_celt_static_alloc[low][i] - << (f->channels - 1) << f->size >> 2; - bits2[i] = high >= CELT_VECTORS ? cap[i] : - ff_celt_freq_range[i] * ff_celt_static_alloc[high][i] - << (f->channels - 1) << f->size >> 2; - - if (bits1[i]) - bits1[i] = FFMAX(0, bits1[i] + trim_offset[i]); - if (bits2[i]) - bits2[i] = FFMAX(0, bits2[i] + trim_offset[i]); - if (low) - bits1[i] += boost[i]; - bits2[i] += boost[i]; - - if (boost[i]) - skip_start_band = i; - bits2[i] = FFMAX(0, bits2[i] - bits1[i]); - } - - /* bisection */ - low = 0; - high = 1 << CELT_ALLOC_STEPS; - for (i = 0; i < CELT_ALLOC_STEPS; i++) { - int center = (low + high) >> 1; - done = total = 0; - - for (j = f->end_band - 1; j >= f->start_band; j--) { - bandbits = bits1[j] + (center * bits2[j] >> CELT_ALLOC_STEPS); - - if (bandbits >= threshold[j] || done) { - done = 1; - total += FFMIN(bandbits, cap[j]); - } else if (bandbits >= f->channels << 3) - total += f->channels << 3; - } - if (total > totalbits) - high = center; - else - low = center; - } - - done = total = 0; - for (i = f->end_band - 1; i >= f->start_band; i--) { - bandbits = bits1[i] + (low * bits2[i] >> CELT_ALLOC_STEPS); - - if (bandbits >= threshold[i] || done) - done = 1; - else - bandbits = (bandbits >= f->channels << 3) ? - f->channels << 3 : 0; - - bandbits = FFMIN(bandbits, cap[i]); - f->pulses[i] = bandbits; - total += bandbits; - } - - /* band skipping */ - for (f->coded_bands = f->end_band; ; f->coded_bands--) { - int allocation; - j = f->coded_bands - 1; - - if (j == skip_start_band) { - /* all remaining bands are not skipped */ - totalbits += skip_bit; - break; - } - - /* determine the number of bits available for coding "do not skip" markers */ - remaining = totalbits - total; - bandbits = remaining / (ff_celt_freq_bands[j+1] - ff_celt_freq_bands[f->start_band]); - remaining -= bandbits * (ff_celt_freq_bands[j+1] - ff_celt_freq_bands[f->start_band]); - allocation = f->pulses[j] + bandbits * ff_celt_freq_range[j] - + FFMAX(0, remaining - (ff_celt_freq_bands[j] - ff_celt_freq_bands[f->start_band])); - - /* a "do not skip" marker is only coded if the allocation is - above the chosen threshold */ - if (allocation >= FFMAX(threshold[j], (f->channels + 1) <<3 )) { - if (ff_opus_rc_dec_log(rc, 1)) - break; - - total += 1 << 3; - allocation -= 1 << 3; - } - - /* the band is skipped, so reclaim its bits */ - total -= f->pulses[j]; - if (intensity_stereo_bit) { - total -= intensity_stereo_bit; - intensity_stereo_bit = ff_celt_log2_frac[j - f->start_band]; - total += intensity_stereo_bit; - } - - total += f->pulses[j] = (allocation >= f->channels << 3) ? - f->channels << 3 : 0; - } - - /* obtain stereo flags */ - f->intensity_stereo = 0; - f->dual_stereo = 0; - if (intensity_stereo_bit) - f->intensity_stereo = f->start_band + - ff_opus_rc_dec_uint(rc, f->coded_bands + 1 - f->start_band); - if (f->intensity_stereo <= f->start_band) - totalbits += dual_stereo_bit; /* no intensity stereo means no dual stereo */ - else if (dual_stereo_bit) - f->dual_stereo = ff_opus_rc_dec_log(rc, 1); - - /* supply the remaining bits in this frame to lower bands */ - remaining = totalbits - total; - bandbits = remaining / (ff_celt_freq_bands[f->coded_bands] - ff_celt_freq_bands[f->start_band]); - remaining -= bandbits * (ff_celt_freq_bands[f->coded_bands] - ff_celt_freq_bands[f->start_band]); - for (i = f->start_band; i < f->coded_bands; i++) { - int bits = FFMIN(remaining, ff_celt_freq_range[i]); - - f->pulses[i] += bits + bandbits * ff_celt_freq_range[i]; - remaining -= bits; - } - - for (i = f->start_band; i < f->coded_bands; i++) { - int N = ff_celt_freq_range[i] << f->size; - int prev_extra = extrabits; - f->pulses[i] += extrabits; - - if (N > 1) { - int dof; // degrees of freedom - int temp; // dof * channels * log(dof) - int offset; // fine energy quantization offset, i.e. - // extra bits assigned over the standard - // totalbits/dof - int fine_bits, max_bits; - - extrabits = FFMAX(0, f->pulses[i] - cap[i]); - f->pulses[i] -= extrabits; - - /* intensity stereo makes use of an extra degree of freedom */ - dof = N * f->channels - + (f->channels == 2 && N > 2 && !f->dual_stereo && i < f->intensity_stereo); - temp = dof * (ff_celt_log_freq_range[i] + (f->size<<3)); - offset = (temp >> 1) - dof * CELT_FINE_OFFSET; - if (N == 2) /* dof=2 is the only case that doesn't fit the model */ - offset += dof<<1; - - /* grant an additional bias for the first and second pulses */ - if (f->pulses[i] + offset < 2 * (dof << 3)) - offset += temp >> 2; - else if (f->pulses[i] + offset < 3 * (dof << 3)) - offset += temp >> 3; - - fine_bits = (f->pulses[i] + offset + (dof << 2)) / (dof << 3); - max_bits = FFMIN((f->pulses[i]>>3) >> (f->channels - 1), - CELT_MAX_FINE_BITS); - - max_bits = FFMAX(max_bits, 0); - - f->fine_bits[i] = av_clip(fine_bits, 0, max_bits); - - /* if fine_bits was rounded down or capped, - give priority for the final fine energy pass */ - f->fine_priority[i] = (f->fine_bits[i] * (dof<<3) >= f->pulses[i] + offset); - - /* the remaining bits are assigned to PVQ */ - f->pulses[i] -= f->fine_bits[i] << (f->channels - 1) << 3; - } else { - /* all bits go to fine energy except for the sign bit */ - extrabits = FFMAX(0, f->pulses[i] - (f->channels << 3)); - f->pulses[i] -= extrabits; - f->fine_bits[i] = 0; - f->fine_priority[i] = 1; - } - - /* hand back a limited number of extra fine energy bits to this band */ - if (extrabits > 0) { - int fineextra = FFMIN(extrabits >> (f->channels + 2), - CELT_MAX_FINE_BITS - f->fine_bits[i]); - f->fine_bits[i] += fineextra; - - fineextra <<= f->channels + 2; - f->fine_priority[i] = (fineextra >= extrabits - prev_extra); - extrabits -= fineextra; - } - } - f->remaining = extrabits; - - /* skipped bands dedicate all of their bits for fine energy */ - for (; i < f->end_band; i++) { - f->fine_bits[i] = f->pulses[i] >> (f->channels - 1) >> 3; - f->pulses[i] = 0; - f->fine_priority[i] = f->fine_bits[i] < 1; - } -} - static void celt_denormalize(CeltFrame *f, CeltBlock *block, float *data) { int i, j; @@ -753,7 +421,7 @@ int ff_celt_decode_frame(CeltFrame *f, OpusRangeCoder *rc, celt_decode_coarse_energy(f, rc); celt_decode_tf_changes (f, rc); - celt_decode_allocation (f, rc); + ff_celt_bitalloc (f, rc, 0); celt_decode_fine_energy (f, rc); ff_celt_quant_bands (f, rc); diff --git a/libavcodec/opusenc.c b/libavcodec/opusenc.c index 93b2116e7bb57..4068c4359470e 100644 --- a/libavcodec/opusenc.c +++ b/libavcodec/opusenc.c @@ -282,333 +282,6 @@ static void celt_enc_tf(CeltFrame *f, OpusRangeCoder *rc) f->tf_change[i] = ff_celt_tf_select[f->size][f->transient][tf_select][f->tf_change[i]]; } -void ff_celt_enc_bitalloc(CeltFrame *f, OpusRangeCoder *rc) -{ - int i, j, low, high, total, done, bandbits, remaining, tbits_8ths; - int skip_startband = f->start_band; - int skip_bit = 0; - int intensitystereo_bit = 0; - int dualstereo_bit = 0; - int dynalloc = 6; - int extrabits = 0; - - int *cap = f->caps; - int boost[CELT_MAX_BANDS]; - int trim_offset[CELT_MAX_BANDS]; - int threshold[CELT_MAX_BANDS]; - int bits1[CELT_MAX_BANDS]; - int bits2[CELT_MAX_BANDS]; - - /* Tell the spread to the decoder */ - if (opus_rc_tell(rc) + 4 <= f->framebits) - ff_opus_rc_enc_cdf(rc, f->spread, ff_celt_model_spread); - else - f->spread = CELT_SPREAD_NORMAL; - - /* Generate static allocation caps */ - for (i = 0; i < CELT_MAX_BANDS; i++) { - cap[i] = (ff_celt_static_caps[f->size][f->channels - 1][i] + 64) - * ff_celt_freq_range[i] << (f->channels - 1) << f->size >> 2; - } - - /* Band boosts */ - tbits_8ths = f->framebits << 3; - for (i = f->start_band; i < f->end_band; i++) { - int quanta, b_dynalloc, boost_amount = f->alloc_boost[i]; - - boost[i] = 0; - - quanta = ff_celt_freq_range[i] << (f->channels - 1) << f->size; - quanta = FFMIN(quanta << 3, FFMAX(6 << 3, quanta)); - b_dynalloc = dynalloc; - - while (opus_rc_tell_frac(rc) + (b_dynalloc << 3) < tbits_8ths && boost[i] < cap[i]) { - int is_boost = boost_amount--; - - ff_opus_rc_enc_log(rc, is_boost, b_dynalloc); - if (!is_boost) - break; - - boost[i] += quanta; - tbits_8ths -= quanta; - - b_dynalloc = 1; - } - - if (boost[i]) - dynalloc = FFMAX(2, dynalloc - 1); - } - - /* Put allocation trim */ - if (opus_rc_tell_frac(rc) + (6 << 3) <= tbits_8ths) - ff_opus_rc_enc_cdf(rc, f->alloc_trim, ff_celt_model_alloc_trim); - - /* Anti-collapse bit reservation */ - tbits_8ths = (f->framebits << 3) - opus_rc_tell_frac(rc) - 1; - f->anticollapse_needed = 0; - if (f->transient && f->size >= 2 && tbits_8ths >= ((f->size + 2) << 3)) - f->anticollapse_needed = 1 << 3; - tbits_8ths -= f->anticollapse_needed; - - /* Band skip bit reservation */ - if (tbits_8ths >= 1 << 3) - skip_bit = 1 << 3; - tbits_8ths -= skip_bit; - - /* Intensity/dual stereo bit reservation */ - if (f->channels == 2) { - intensitystereo_bit = ff_celt_log2_frac[f->end_band - f->start_band]; - if (intensitystereo_bit <= tbits_8ths) { - tbits_8ths -= intensitystereo_bit; - if (tbits_8ths >= 1 << 3) { - dualstereo_bit = 1 << 3; - tbits_8ths -= 1 << 3; - } - } else { - intensitystereo_bit = 0; - } - } - - /* Trim offsets */ - for (i = f->start_band; i < f->end_band; i++) { - int trim = f->alloc_trim - 5 - f->size; - int band = ff_celt_freq_range[i] * (f->end_band - i - 1); - int duration = f->size + 3; - int scale = duration + f->channels - 1; - - /* PVQ minimum allocation threshold, below this value the band is - * skipped */ - threshold[i] = FFMAX(3 * ff_celt_freq_range[i] << duration >> 4, - f->channels << 3); - - trim_offset[i] = trim * (band << scale) >> 6; - - if (ff_celt_freq_range[i] << f->size == 1) - trim_offset[i] -= f->channels << 3; - } - - /* Bisection */ - low = 1; - high = CELT_VECTORS - 1; - while (low <= high) { - int center = (low + high) >> 1; - done = total = 0; - - for (i = f->end_band - 1; i >= f->start_band; i--) { - bandbits = ff_celt_freq_range[i] * ff_celt_static_alloc[center][i] - << (f->channels - 1) << f->size >> 2; - - if (bandbits) - bandbits = FFMAX(0, bandbits + trim_offset[i]); - bandbits += boost[i]; - - if (bandbits >= threshold[i] || done) { - done = 1; - total += FFMIN(bandbits, cap[i]); - } else if (bandbits >= f->channels << 3) - total += f->channels << 3; - } - - if (total > tbits_8ths) - high = center - 1; - else - low = center + 1; - } - high = low--; - - /* Bisection */ - for (i = f->start_band; i < f->end_band; i++) { - bits1[i] = ff_celt_freq_range[i] * ff_celt_static_alloc[low][i] - << (f->channels - 1) << f->size >> 2; - bits2[i] = high >= CELT_VECTORS ? cap[i] : - ff_celt_freq_range[i] * ff_celt_static_alloc[high][i] - << (f->channels - 1) << f->size >> 2; - - if (bits1[i]) - bits1[i] = FFMAX(0, bits1[i] + trim_offset[i]); - if (bits2[i]) - bits2[i] = FFMAX(0, bits2[i] + trim_offset[i]); - if (low) - bits1[i] += boost[i]; - bits2[i] += boost[i]; - - if (boost[i]) - skip_startband = i; - bits2[i] = FFMAX(0, bits2[i] - bits1[i]); - } - - /* Bisection */ - low = 0; - high = 1 << CELT_ALLOC_STEPS; - for (i = 0; i < CELT_ALLOC_STEPS; i++) { - int center = (low + high) >> 1; - done = total = 0; - - for (j = f->end_band - 1; j >= f->start_band; j--) { - bandbits = bits1[j] + (center * bits2[j] >> CELT_ALLOC_STEPS); - - if (bandbits >= threshold[j] || done) { - done = 1; - total += FFMIN(bandbits, cap[j]); - } else if (bandbits >= f->channels << 3) - total += f->channels << 3; - } - if (total > tbits_8ths) - high = center; - else - low = center; - } - - /* Bisection */ - done = total = 0; - for (i = f->end_band - 1; i >= f->start_band; i--) { - bandbits = bits1[i] + (low * bits2[i] >> CELT_ALLOC_STEPS); - - if (bandbits >= threshold[i] || done) - done = 1; - else - bandbits = (bandbits >= f->channels << 3) ? - f->channels << 3 : 0; - - bandbits = FFMIN(bandbits, cap[i]); - f->pulses[i] = bandbits; - total += bandbits; - } - - /* Band skipping */ - for (f->coded_bands = f->end_band; ; f->coded_bands--) { - int allocation; - j = f->coded_bands - 1; - - if (j == skip_startband) { - /* all remaining bands are not skipped */ - tbits_8ths += skip_bit; - break; - } - - /* determine the number of bits available for coding "do not skip" markers */ - remaining = tbits_8ths - total; - bandbits = remaining / (ff_celt_freq_bands[j+1] - ff_celt_freq_bands[f->start_band]); - remaining -= bandbits * (ff_celt_freq_bands[j+1] - ff_celt_freq_bands[f->start_band]); - allocation = f->pulses[j] + bandbits * ff_celt_freq_range[j] - + FFMAX(0, remaining - (ff_celt_freq_bands[j] - ff_celt_freq_bands[f->start_band])); - - /* a "do not skip" marker is only coded if the allocation is - above the chosen threshold */ - if (allocation >= FFMAX(threshold[j], (f->channels + 1) << 3)) { - const int do_not_skip = f->coded_bands <= f->skip_band_floor; - ff_opus_rc_enc_log(rc, do_not_skip, 1); - if (do_not_skip) - break; - - total += 1 << 3; - allocation -= 1 << 3; - } - - /* the band is skipped, so reclaim its bits */ - total -= f->pulses[j]; - if (intensitystereo_bit) { - total -= intensitystereo_bit; - intensitystereo_bit = ff_celt_log2_frac[j - f->start_band]; - total += intensitystereo_bit; - } - - total += f->pulses[j] = (allocation >= f->channels << 3) ? f->channels << 3 : 0; - } - - /* Encode stereo flags */ - if (intensitystereo_bit) { - f->intensity_stereo = FFMIN(f->intensity_stereo, f->coded_bands); - ff_opus_rc_enc_uint(rc, f->intensity_stereo, f->coded_bands + 1 - f->start_band); - } - if (f->intensity_stereo <= f->start_band) - tbits_8ths += dualstereo_bit; /* no intensity stereo means no dual stereo */ - else if (dualstereo_bit) - ff_opus_rc_enc_log(rc, f->dual_stereo, 1); - - /* Supply the remaining bits in this frame to lower bands */ - remaining = tbits_8ths - total; - bandbits = remaining / (ff_celt_freq_bands[f->coded_bands] - ff_celt_freq_bands[f->start_band]); - remaining -= bandbits * (ff_celt_freq_bands[f->coded_bands] - ff_celt_freq_bands[f->start_band]); - for (i = f->start_band; i < f->coded_bands; i++) { - int bits = FFMIN(remaining, ff_celt_freq_range[i]); - - f->pulses[i] += bits + bandbits * ff_celt_freq_range[i]; - remaining -= bits; - } - - /* Finally determine the allocation */ - for (i = f->start_band; i < f->coded_bands; i++) { - int N = ff_celt_freq_range[i] << f->size; - int prev_extra = extrabits; - f->pulses[i] += extrabits; - - if (N > 1) { - int dof; // degrees of freedom - int temp; // dof * channels * log(dof) - int offset; // fine energy quantization offset, i.e. - // extra bits assigned over the standard - // totalbits/dof - int fine_bits, max_bits; - - extrabits = FFMAX(0, f->pulses[i] - cap[i]); - f->pulses[i] -= extrabits; - - /* intensity stereo makes use of an extra degree of freedom */ - dof = N * f->channels + (f->channels == 2 && N > 2 && !f->dual_stereo && i < f->intensity_stereo); - temp = dof * (ff_celt_log_freq_range[i] + (f->size << 3)); - offset = (temp >> 1) - dof * CELT_FINE_OFFSET; - if (N == 2) /* dof=2 is the only case that doesn't fit the model */ - offset += dof << 1; - - /* grant an additional bias for the first and second pulses */ - if (f->pulses[i] + offset < 2 * (dof << 3)) - offset += temp >> 2; - else if (f->pulses[i] + offset < 3 * (dof << 3)) - offset += temp >> 3; - - fine_bits = (f->pulses[i] + offset + (dof << 2)) / (dof << 3); - max_bits = FFMIN((f->pulses[i] >> 3) >> (f->channels - 1), CELT_MAX_FINE_BITS); - - max_bits = FFMAX(max_bits, 0); - - f->fine_bits[i] = av_clip(fine_bits, 0, max_bits); - - /* if fine_bits was rounded down or capped, - give priority for the final fine energy pass */ - f->fine_priority[i] = (f->fine_bits[i] * (dof << 3) >= f->pulses[i] + offset); - - /* the remaining bits are assigned to PVQ */ - f->pulses[i] -= f->fine_bits[i] << (f->channels - 1) << 3; - } else { - /* all bits go to fine energy except for the sign bit */ - extrabits = FFMAX(0, f->pulses[i] - (f->channels << 3)); - f->pulses[i] -= extrabits; - f->fine_bits[i] = 0; - f->fine_priority[i] = 1; - } - - /* hand back a limited number of extra fine energy bits to this band */ - if (extrabits > 0) { - int fineextra = FFMIN(extrabits >> (f->channels + 2), - CELT_MAX_FINE_BITS - f->fine_bits[i]); - f->fine_bits[i] += fineextra; - - fineextra <<= f->channels + 2; - f->fine_priority[i] = (fineextra >= extrabits - prev_extra); - extrabits -= fineextra; - } - } - f->remaining = extrabits; - - /* skipped bands dedicate all of their bits for fine energy */ - for (; i < f->end_band; i++) { - f->fine_bits[i] = f->pulses[i] >> (f->channels - 1) >> 3; - f->pulses[i] = 0; - f->fine_priority[i] = f->fine_bits[i] < 1; - } -} - static void celt_enc_quant_pfilter(OpusRangeCoder *rc, CeltFrame *f) { float gain = f->pf_gain; @@ -794,11 +467,11 @@ static void celt_encode_frame(OpusEncContext *s, OpusRangeCoder *rc, ff_opus_rc_enc_log(rc, f->transient, 3); /* Main encoding */ - celt_quant_coarse (f, rc, s->last_quantized_energy); - celt_enc_tf (f, rc); - ff_celt_enc_bitalloc(f, rc); - celt_quant_fine (f, rc); - ff_celt_quant_bands (f, rc); + celt_quant_coarse (f, rc, s->last_quantized_energy); + celt_enc_tf (f, rc); + ff_celt_bitalloc (f, rc, 1); + celt_quant_fine (f, rc); + ff_celt_quant_bands(f, rc); /* Anticollapse bit */ if (f->anticollapse_needed) diff --git a/libavcodec/opusenc.h b/libavcodec/opusenc.h index 56e4af67e320b..b9162ebec64ce 100644 --- a/libavcodec/opusenc.h +++ b/libavcodec/opusenc.h @@ -51,6 +51,4 @@ typedef struct OpusPacketInfo { int frames; } OpusPacketInfo; -void ff_celt_enc_bitalloc(CeltFrame *f, OpusRangeCoder *rc); - #endif /* AVCODEC_OPUSENC_H */ diff --git a/libavcodec/opusenc_psy.c b/libavcodec/opusenc_psy.c index 5393c9d7deaba..50890c65d68ed 100644 --- a/libavcodec/opusenc_psy.c +++ b/libavcodec/opusenc_psy.c @@ -366,7 +366,7 @@ static int bands_dist(OpusPsyContext *s, CeltFrame *f, float *total_dist) OpusRangeCoder dump; ff_opus_rc_enc_init(&dump); - ff_celt_enc_bitalloc(f, &dump); + ff_celt_bitalloc(f, &dump, 1); for (i = 0; i < CELT_MAX_BANDS; i++) { float bits = 0.0f; From c0b08ef94f037572876448990dca840b85432262 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 29 Dec 2017 15:25:14 -0800 Subject: [PATCH 1505/2557] avformat/http: return EINVAL if ff_http_do_new_request is called with non-http URLContext Signed-off-by: Aman Gupta --- libavformat/http.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index a376f1a488468..8f7e56de54d33 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -311,6 +311,11 @@ int ff_http_do_new_request(URLContext *h, const char *uri) char hostname1[1024], hostname2[1024], proto1[10], proto2[10]; int port1, port2; + if (!h->prot || + !(!strcmp(h->prot->name, "http") || + !strcmp(h->prot->name, "https"))) + return AVERROR(EINVAL); + av_url_split(proto1, sizeof(proto1), NULL, 0, hostname1, sizeof(hostname1), &port1, NULL, 0, s->location); From 903be5e4f66268273dc6e3c42a7fdeaab32066ef Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 29 Dec 2017 03:00:19 +0100 Subject: [PATCH 1506/2557] avcodec/exr: Check buf_size more completely Fixes: Out of heap array read Fixes: 4683/clusterfuzz-testcase-minimized-6152313673613312 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/exr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index b1ecde4ebd37d..454dc74cfb14c 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -1051,7 +1051,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata, line_offset = AV_RL64(s->gb.buffer + jobnr * 8); if (s->is_tile) { - if (line_offset > buf_size - 20) + if (buf_size < 20 || line_offset > buf_size - 20) return AVERROR_INVALIDDATA; src = buf + line_offset + 20; @@ -1062,7 +1062,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata, tile_level_y = AV_RL32(src - 8); data_size = AV_RL32(src - 4); - if (data_size <= 0 || data_size > buf_size) + if (data_size <= 0 || data_size > buf_size - line_offset - 20) return AVERROR_INVALIDDATA; if (tile_level_x || tile_level_y) { /* tile level, is not the full res level */ @@ -1095,7 +1095,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata, td->channel_line_size = td->xsize * s->current_channel_offset;/* uncompress size of one line */ uncompressed_size = td->channel_line_size * (uint64_t)td->ysize;/* uncompress size of the block */ } else { - if (line_offset > buf_size - 8) + if (buf_size < 8 || line_offset > buf_size - 8) return AVERROR_INVALIDDATA; src = buf + line_offset + 8; @@ -1105,7 +1105,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata, return AVERROR_INVALIDDATA; data_size = AV_RL32(src - 4); - if (data_size <= 0 || data_size > buf_size) + if (data_size <= 0 || data_size > buf_size - line_offset - 8) return AVERROR_INVALIDDATA; td->ysize = FFMIN(s->scan_lines_per_block, s->ymax - line + 1); /* s->ydelta - line ?? */ From 97b89432e4566a5d620f97bfdf4c8ae9c83d94e8 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 29 Dec 2017 15:30:55 -0800 Subject: [PATCH 1507/2557] avformat/hls: ignore http_persistent for segments requring crypto Encrypted HLS segments have regular http:// urls, but open_input() actually prefixes them with crypto+ before calling open_url(), so they end up using the crypto protocol and not the http protocol. This means invoking ff_http_do_new_request will fail, so we avoid calling it in the first place. After the earlier http.c commit, the failure results in a warning printed to the user. In earlier versions, the failure would cause a segfault. Signed-off-by: Aman Gupta --- libavformat/hls.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index dccc7c7dd2c3f..d9f7c6de4dcac 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1479,7 +1479,7 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) seg = next_segment(v); if (c->http_multiple == 1 && !v->input_next_requested && - seg && av_strstart(seg->url, "http", NULL)) { + seg && seg->key_type == KEY_NONE && av_strstart(seg->url, "http", NULL)) { ret = open_input(c, v, seg, &v->input_next); if (ret < 0) { if (ff_check_interrupt(c->interrupt_callback)) @@ -1511,7 +1511,8 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) return ret; } - if (c->http_persistent && av_strstart(seg->url, "http", NULL)) { + if (c->http_persistent && + seg->key_type == KEY_NONE && av_strstart(seg->url, "http", NULL)) { v->input_read_done = 1; } else { ff_format_io_close(v->parent, &v->input); From e45f7bca735ff7ba965ec1e441199dc7aeb0c8fc Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Sat, 30 Dec 2017 12:17:08 +0100 Subject: [PATCH 1508/2557] lavf/concatdec: properly init streams timestamp parameters. pts_wrap_bits defaults to 33 (like MPEG), that causes valid timestamps to be unwrapped and become invalid. Inspired by a patch by Wu Zhiqiang . --- libavformat/concatdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 0e189012adf27..bd5174ada2540 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -185,8 +185,8 @@ static int copy_stream_props(AVStream *st, AVStream *source_st) return ret; st->r_frame_rate = source_st->r_frame_rate; st->avg_frame_rate = source_st->avg_frame_rate; - st->time_base = source_st->time_base; st->sample_aspect_ratio = source_st->sample_aspect_ratio; + avpriv_set_pts_info(st, 64, source_st->time_base.num, source_st->time_base.den); av_dict_copy(&st->metadata, source_st->metadata, 0); return 0; From 0e1f771d2200d14d298df09c91e14f51e418fd3a Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 30 Dec 2017 17:44:03 +0100 Subject: [PATCH 1509/2557] tcp: properly return EOF There is no POSIX error code for EOF - recv() signals EOF by simply returning 0. But libavformat recently changed its conventions and requires an explicit AVERROR_EOF, or it might get into an endless retry loop, consuming 100% CPU while doing nothing. --- libavformat/tcp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index fef0729da683b..8773493df1efe 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -225,6 +225,8 @@ static int tcp_read(URLContext *h, uint8_t *buf, int size) return ret; } ret = recv(s->fd, buf, size, 0); + if (ret == 0) + return AVERROR_EOF; return ret < 0 ? ff_neterrno() : ret; } From f3552c3b9d517e278ec45d5e2bd53bf3e7dc754b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 31 Dec 2017 19:09:07 +0100 Subject: [PATCH 1510/2557] avfilter/af_afir: rework FIR gain measurement Signed-off-by: Paul B Mahol --- libavfilter/af_afir.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/libavfilter/af_afir.c b/libavfilter/af_afir.c index c81a1e22cf1de..6687242631673 100644 --- a/libavfilter/af_afir.c +++ b/libavfilter/af_afir.c @@ -105,7 +105,7 @@ static int fir_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) if (out) { float *ptr = (float *)out->extended_data[ch]; - s->fdsp->vector_fmul_scalar(ptr, dst, s->gain * s->wet_gain, FFALIGN(out->nb_samples, 4)); + s->fdsp->vector_fmul_scalar(ptr, dst, s->wet_gain, FFALIGN(out->nb_samples, 4)); emms_c(); } @@ -166,7 +166,6 @@ static int convert_coeffs(AVFilterContext *ctx) { AudioFIRContext *s = ctx->priv; int i, ch, n, N; - float power = 0; s->nb_taps = av_audio_fifo_size(s->fifo[1]); if (s->nb_taps <= 0) @@ -217,13 +216,29 @@ static int convert_coeffs(AVFilterContext *ctx) av_audio_fifo_read(s->fifo[1], (void **)s->in[1]->extended_data, s->nb_taps); + if (s->again) { + float power = 0; + + for (ch = 0; ch < ctx->inputs[1]->channels; ch++) { + float *time = (float *)s->in[1]->extended_data[!s->one2many * ch]; + + for (i = 0; i < s->nb_taps; i++) + power += FFABS(time[i]); + } + + s->gain = sqrtf(1.f / (ctx->inputs[1]->channels * power)) / (sqrtf(ctx->inputs[1]->channels)); + for (ch = 0; ch < ctx->inputs[1]->channels; ch++) { + float *time = (float *)s->in[1]->extended_data[!s->one2many * ch]; + + s->fdsp->vector_fmul_scalar(time, time, s->gain, FFALIGN(s->nb_taps, 4)); + } + } + for (ch = 0; ch < ctx->inputs[1]->channels; ch++) { float *time = (float *)s->in[1]->extended_data[!s->one2many * ch]; float *block = s->block[ch]; FFTComplex *coeff = s->coeff[ch]; - power += s->fdsp->scalarproduct_float(time, time, s->nb_taps); - for (i = FFMAX(1, s->length * s->nb_taps); i < s->nb_taps; i++) time[i] = 0; @@ -252,7 +267,6 @@ static int convert_coeffs(AVFilterContext *ctx) } av_frame_free(&s->in[1]); - s->gain = s->again ? 1.f / sqrtf(power / ctx->inputs[1]->channels) : 1.f; av_log(ctx, AV_LOG_DEBUG, "nb_taps: %d\n", s->nb_taps); av_log(ctx, AV_LOG_DEBUG, "nb_partitions: %d\n", s->nb_partitions); av_log(ctx, AV_LOG_DEBUG, "partition size: %d\n", s->part_size); From 2906363d1bb804994cf741ad2c99d8c76efff5f0 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Sat, 30 Dec 2017 20:42:13 +0800 Subject: [PATCH 1511/2557] avformat/hls: release mem resource to fix memleak fix CID: 1426991 Signed-off-by: Steven Liu Signed-off-by: Aman Gupta Signed-off-by: Derek Buitenhuis --- libavformat/hls.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index d9f7c6de4dcac..950cc4c3bd1af 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1473,8 +1473,11 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) if (c->http_multiple == -1) { uint8_t *http_version_opt = NULL; - av_opt_get(v->input, "http_version", AV_OPT_SEARCH_CHILDREN, &http_version_opt); - c->http_multiple = http_version_opt && strncmp((const char *)http_version_opt, "1.1", 3) == 0; + int r = av_opt_get(v->input, "http_version", AV_OPT_SEARCH_CHILDREN, &http_version_opt); + if (r >= 0) { + c->http_multiple = strncmp((const char *)http_version_opt, "1.1", 3) == 0; + av_freep(&http_version_opt); + } } seg = next_segment(v); From 7b0b5bc810cdb9ef100492c9a9f2d30602c04336 Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Mon, 1 Jan 2018 02:51:51 -0500 Subject: [PATCH 1512/2557] cmdutils: update copyright year to 2018 --- avtools/cmdutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avtools/cmdutils.c b/avtools/cmdutils.c index 727e2835eb3ae..cf8a4c8c1c664 100644 --- a/avtools/cmdutils.c +++ b/avtools/cmdutils.c @@ -59,7 +59,7 @@ struct SwsContext *sws_opts; AVDictionary *format_opts, *codec_opts, *resample_opts; -static const int this_year = 2017; +static const int this_year = 2018; void init_opts(void) { From bddf31ba7570325dd2c8d033eae3d0dd74127f96 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Mon, 1 Jan 2018 18:05:55 +0100 Subject: [PATCH 1513/2557] configure: bump year Happy new year! --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 688f6ab803856..606cdd0004ea8 100755 --- a/configure +++ b/configure @@ -6959,7 +6959,7 @@ cat > $TMPH < Date: Mon, 1 Jan 2018 19:55:25 +0000 Subject: [PATCH 1514/2557] lavc/Makefile: fix opus_parser dependencies Fix suggested by RiCON. Signed-off-by: Rostislav Pehlivanov --- libavcodec/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index ca72138c028b6..cfacd6b70ce48 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1005,7 +1005,8 @@ OBJS-$(CONFIG_PNG_PARSER) += png_parser.o OBJS-$(CONFIG_MPEGAUDIO_PARSER) += mpegaudio_parser.o OBJS-$(CONFIG_MPEGVIDEO_PARSER) += mpegvideo_parser.o \ mpeg12.o mpeg12data.o -OBJS-$(CONFIG_OPUS_PARSER) += opus_parser.o opus.o opustab.o vorbis_data.o +OBJS-$(CONFIG_OPUS_PARSER) += opus_parser.o opus.o opustab.o \ + opus_rc.o vorbis_data.o OBJS-$(CONFIG_PNG_PARSER) += png_parser.o OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o From 9f7dbaad7e36e11237ab76ed5e1932af7dfd2df2 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 1 Jan 2018 21:53:10 +0100 Subject: [PATCH 1515/2557] avfilter/af_crystalizer: use outlink instead of inlink Doesn't change anything but is more correct. Signed-off-by: Paul B Mahol --- libavfilter/af_crystalizer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/af_crystalizer.c b/libavfilter/af_crystalizer.c index dec30aa5f48a3..5b27e1fb797db 100644 --- a/libavfilter/af_crystalizer.c +++ b/libavfilter/af_crystalizer.c @@ -173,7 +173,7 @@ static void filter_dblp(void **d, void **p, const void **s, static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; - CrystalizerContext *s = ctx->priv; + CrystalizerContext *s = ctx->priv; switch (inlink->format) { case AV_SAMPLE_FMT_FLT: s->filter = filter_flt; break; @@ -203,7 +203,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); From 1112ba012df38d486694154b03f5007341f43b24 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 31 Dec 2017 22:30:57 +0100 Subject: [PATCH 1516/2557] lavf/mov: Use av_fast_realloc() in mov_read_stts(). Avoids large allocations for short files with invalid stts entry. Fixes bugzilla 1102. --- libavformat/mov.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 20644734dc489..22faecfc1774d 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2830,7 +2830,7 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; MOVStreamContext *sc; - unsigned int i, entries; + unsigned int i, entries, alloc_size = 0; int64_t duration=0; int64_t total_sample_count=0; @@ -2848,15 +2848,24 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (sc->stts_data) av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n"); - av_free(sc->stts_data); + av_freep(&sc->stts_data); sc->stts_count = 0; - sc->stts_data = av_malloc_array(entries, sizeof(*sc->stts_data)); - if (!sc->stts_data) + if (entries >= INT_MAX / sizeof(*sc->stts_data)) return AVERROR(ENOMEM); for (i = 0; i < entries && !pb->eof_reached; i++) { int sample_duration; unsigned int sample_count; + unsigned min_entries = FFMIN(FFMAX(i, 1024 * 1024), entries); + MOVStts *stts_data = av_fast_realloc(sc->stts_data, &alloc_size, + min_entries * sizeof(*sc->stts_data)); + if (!stts_data) { + av_freep(&sc->stts_data); + sc->stts_count = 0; + return AVERROR(ENOMEM); + } + sc->stts_count = min_entries; + sc->stts_data = stts_data; sample_count=avio_rb32(pb); sample_duration = avio_rb32(pb); From 21b5990da461e4f83cf53994715ed42e22cce9e0 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sat, 30 Dec 2017 14:38:33 +0100 Subject: [PATCH 1517/2557] lavu/mem: Do not realloc in av_fast_realloc() if size == min_size. This can avoid OOM for min_size close to FFmpeg's arbitrary alloc limits. --- libavutil/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/mem.c b/libavutil/mem.c index 79e8b597f1672..0729e1dd50684 100644 --- a/libavutil/mem.c +++ b/libavutil/mem.c @@ -463,7 +463,7 @@ void av_memcpy_backptr(uint8_t *dst, int back, int cnt) void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size) { - if (min_size < *size) + if (min_size <= *size) return ptr; min_size = FFMAX(min_size + min_size / 16 + 32, min_size); From 26e1efb04f3864b813c74eaf85fbe1ea352bb7f0 Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Tue, 2 Jan 2018 10:45:28 +0800 Subject: [PATCH 1518/2557] avformat/hlsenc: revamped master playlist url creation logic --- libavformat/hlsenc.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index e6f3241765176..3ea16c6d7dc1b 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1689,28 +1689,30 @@ static int update_variant_stream_info(AVFormatContext *s) { static int update_master_pl_info(AVFormatContext *s) { HLSContext *hls = s->priv_data; - int m3u8_name_size, ret; - char *p; + const char *dir; + char *fn; + int ret = 0; - m3u8_name_size = strlen(s->filename) + strlen(hls->master_pl_name) + 1; - hls->master_m3u8_url = av_malloc(m3u8_name_size); - if (!hls->master_m3u8_url) { + fn = av_strdup(s->filename); + if (!fn) { ret = AVERROR(ENOMEM); - return ret; + goto fail; } - av_strlcpy(hls->master_m3u8_url, s->filename, m3u8_name_size); - p = strrchr(hls->master_m3u8_url, '/') ? - strrchr(hls->master_m3u8_url, '/') : - strrchr(hls->master_m3u8_url, '\\'); - if (p) { - *(p + 1) = '\0'; - av_strlcat(hls->master_m3u8_url, hls->master_pl_name, m3u8_name_size); - } else { - av_strlcpy(hls->master_m3u8_url, hls->master_pl_name, m3u8_name_size); + dir = av_dirname(fn); + if (dir && strcmp(dir, ".")) + hls->master_m3u8_url = av_append_path_component(dir, hls->master_pl_name); + else + hls->master_m3u8_url = av_strdup(hls->master_pl_name); + + if (!hls->master_m3u8_url) { + ret = AVERROR(ENOMEM); + goto fail; } - return 0; +fail: + av_freep(&fn); + return ret; } static int hls_write_header(AVFormatContext *s) From e872befdb5974bb609e337c895cefbf9bb51187c Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Tue, 2 Jan 2018 10:46:17 +0800 Subject: [PATCH 1519/2557] avformat/hlsenc: configurable variant stream index position in filenames --- doc/muxers.texi | 31 +++++++-- libavformat/hlsenc.c | 153 ++++++++++++++++++++++++++++--------------- 2 files changed, 126 insertions(+), 58 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 8ce964b0a0f13..553765cff8f70 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -577,6 +577,17 @@ Should a relative path be specified, the path of the created segment files will be relative to the current working directory. When use_localtime_mkdir is set, the whole expanded value of @var{filename} will be written into the m3u8 segment list. +When @code{var_stream_map} is set with two or more variant streams, the +@var{filename} pattern must contain the string "%v", this string specifies +the position of variant stream index in the generated segment file names. +@example +ffmpeg -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k -b:a:1 32k \ + -map 0:v -map 0:a -map 0:v -map 0:a -f hls -var_stream_map "v:0,a:0 v:1,a:1" \ + -hls_segment_filename 'file_%v_%03d.ts' out_%v.m3u8 +@end example +This example will produce the playlists segment file sets: +@file{file_0_000.ts}, @file{file_0_001.ts}, @file{file_0_002.ts}, etc. and +@file{file_1_000.ts}, @file{file_1_001.ts}, @file{file_1_002.ts}, etc. @item use_localtime Use strftime() on @var{filename} to expand the segment filename with localtime. @@ -703,6 +714,10 @@ the fmp4 files is used in hls after version 7. @item hls_fmp4_init_filename @var{filename} set filename to the fragment files header file, default filename is @file{init.mp4}. +When @code{var_stream_map} is set with two or more variant streams, the +@var{filename} pattern must contain the string "%v", this string specifies +the position of variant stream index in the generated init file names. + @item hls_flags @var{flags} Possible values: @@ -816,32 +831,36 @@ Expected string format is like this "a:0,v:0 a:1,v:1 ....". Here a:, v:, s: are the keys to specify audio, video and subtitle streams respectively. Allowed values are 0 to 9 (limited just based on practical usage). +When there are two or more variant streams, the output filename pattern must +contain the string "%v", this string specifies the position of variant stream +index in the output media playlist filenames. + @example ffmpeg -re -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k -b:a:1 32k \ -map 0:v -map 0:a -map 0:v -map 0:a -f hls -var_stream_map "v:0,a:0 v:1,a:1" \ - http://example.com/live/out.m3u8 + http://example.com/live/out_%v.m3u8 @end example This example creates two hls variant streams. The first variant stream will contain video stream of bitrate 1000k and audio stream of bitrate 64k and the second variant stream will contain video stream of bitrate 256k and audio -stream of bitrate 32k. Here, two media playlist with file names out_1.m3u8 and -out_2.m3u8 will be created. +stream of bitrate 32k. Here, two media playlist with file names out_0.m3u8 and +out_1.m3u8 will be created. @example ffmpeg -re -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k \ -map 0:v -map 0:a -map 0:v -f hls -var_stream_map "v:0 a:0 v:1" \ - http://example.com/live/out.m3u8 + http://example.com/live/out_%v.m3u8 @end example This example creates three hls variant streams. The first variant stream will be a video only stream with video bitrate 1000k, the second variant stream will be an audio only stream with bitrate 64k and the third variant stream will be a video only stream with bitrate 256k. Here, three media playlist with file names -out_1.m3u8, out_2.m3u8 and out_3.m3u8 will be created. +out_0.m3u8, out_1.m3u8 and out_2.m3u8 will be created. @example ffmpeg -re -i in.ts -b:a:0 32k -b:a:1 64k -b:v:0 1000k -b:v:1 3000k \ -map 0:a -map 0:a -map 0:v -map 0:v -f hls \ -var_stream_map "a:0,agroup:aud_low a:1,agroup:aud_high v:0,agroup:aud_low v:1,agroup:aud_high" \ -master_pl_name master.m3u8 \ - http://example.com/live/out.m3u8 + http://example.com/live/out_%v.m3u8 @end example This example creates two audio only and two video only variant streams. In addition to the #EXT-X-STREAM-INF tag for each variant stream in the master diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 3ea16c6d7dc1b..e1dd606a61578 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1528,7 +1528,7 @@ static const char * get_default_pattern_localtime_fmt(AVFormatContext *s) return (HAVE_LIBC_MSVCRT || !strftime(b, sizeof(b), "%s", p) || !strcmp(b, "%s")) ? "-%Y%m%d%H%M%S.ts" : "-%s.ts"; } -static int format_name(char *name, int name_buf_len, int i) +static int append_postfix(char *name, int name_buf_len, int i) { char *p; char extension[10] = {'\0'}; @@ -1547,6 +1547,53 @@ static int format_name(char *name, int name_buf_len, int i) return 0; } +static int validate_name(int nb_vs, const char *fn) +{ + const char *filename; + int ret = 0; + + if (!fn) { + ret = AVERROR(EINVAL); + goto fail; + } + + filename = av_basename(fn); + + if (nb_vs > 1 && !av_stristr(filename, "%v")) { + av_log(NULL, AV_LOG_ERROR, "More than 1 variant streams are present, %%v is expected in the filename %s\n", + fn); + ret = AVERROR(EINVAL); + goto fail; + } + +fail: + return ret; +} + +static int format_name(char *buf, int buf_len, int index) +{ + char *orig_buf_dup = NULL; + int ret = 0; + + if (!av_stristr(buf, "%v")) + return ret; + + orig_buf_dup = av_strdup(buf); + if (!orig_buf_dup) { + ret = AVERROR(ENOMEM); + goto fail; + } + + if (replace_int_data_in_filename(buf, buf_len, orig_buf_dup, 'v', index) < 1) { + ret = AVERROR(EINVAL); + goto fail; + } + +fail: + av_freep(&orig_buf_dup); + return ret; +} + static int get_nth_codec_stream_index(AVFormatContext *s, enum AVMediaType codec_type, int stream_id) @@ -1690,7 +1737,7 @@ static int update_variant_stream_info(AVFormatContext *s) { static int update_master_pl_info(AVFormatContext *s) { HLSContext *hls = s->priv_data; const char *dir; - char *fn; + char *fn = NULL; int ret = 0; fn = av_strdup(s->filename); @@ -2052,7 +2099,7 @@ static int hls_init(AVFormatContext *s) const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s); const char *vtt_pattern = "%d.vtt"; char *p = NULL; - int vtt_basename_size = 0, m3u8_name_size = 0; + int vtt_basename_size = 0; int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1; ret = update_variant_stream_info(s); @@ -2068,6 +2115,28 @@ static int hls_init(AVFormatContext *s) goto fail; } + ret = validate_name(hls->nb_varstreams, s->filename); + if (ret < 0) + goto fail; + + if (hls->segment_filename) { + ret = validate_name(hls->nb_varstreams, hls->segment_filename); + if (ret < 0) + goto fail; + } + + if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) { + ret = validate_name(hls->nb_varstreams, hls->fmp4_init_filename); + if (ret < 0) + goto fail; + } + + if (hls->subtitle_filename) { + ret = validate_name(hls->nb_varstreams, hls->subtitle_filename); + if (ret < 0) + goto fail; + } + if (hls->master_pl_name) { ret = update_master_pl_info(s); if (ret < 0) { @@ -2100,6 +2169,16 @@ static int hls_init(AVFormatContext *s) hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE; for (i = 0; i < hls->nb_varstreams; i++) { vs = &hls->var_streams[i]; + + vs->m3u8_name = av_strdup(s->filename); + if (!vs->m3u8_name ) { + ret = AVERROR(ENOMEM); + goto fail; + } + ret = format_name(vs->m3u8_name, strlen(s->filename) + 1, i); + if (ret < 0) + goto fail; + vs->sequence = hls->start_sequence; vs->start_pts = AV_NOPTS_VALUE; vs->end_pts = AV_NOPTS_VALUE; @@ -2153,9 +2232,6 @@ static int hls_init(AVFormatContext *s) } if (hls->segment_filename) { basename_size = strlen(hls->segment_filename) + 1; - if (hls->nb_varstreams > 1) { - basename_size += strlen(POSTFIX_PATTERN); - } vs->basename = av_malloc(basename_size); if (!vs->basename) { ret = AVERROR(ENOMEM); @@ -2163,6 +2239,9 @@ static int hls_init(AVFormatContext *s) } av_strlcpy(vs->basename, hls->segment_filename, basename_size); + ret = format_name(vs->basename, basename_size, i); + if (ret < 0) + goto fail; } else { if (hls->flags & HLS_SINGLE_FILE) { if (hls->segment_type == SEGMENT_TYPE_FMP4) { @@ -2173,13 +2252,9 @@ static int hls_init(AVFormatContext *s) } if (hls->use_localtime) { - basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1; + basename_size = strlen(vs->m3u8_name) + strlen(pattern_localtime_fmt) + 1; } else { - basename_size = strlen(s->filename) + strlen(pattern) + 1; - } - - if (hls->nb_varstreams > 1) { - basename_size += strlen(POSTFIX_PATTERN); + basename_size = strlen(vs->m3u8_name) + strlen(pattern) + 1; } vs->basename = av_malloc(basename_size); @@ -2188,7 +2263,7 @@ static int hls_init(AVFormatContext *s) goto fail; } - av_strlcpy(vs->basename, s->filename, basename_size); + av_strlcpy(vs->basename, vs->m3u8_name, basename_size); p = strrchr(vs->basename, '.'); if (p) @@ -2200,28 +2275,6 @@ static int hls_init(AVFormatContext *s) } } - m3u8_name_size = strlen(s->filename) + 1; - if (hls->nb_varstreams > 1) { - m3u8_name_size += strlen(POSTFIX_PATTERN); - } - - vs->m3u8_name = av_malloc(m3u8_name_size); - if (!vs->m3u8_name ) { - ret = AVERROR(ENOMEM); - goto fail; - } - - av_strlcpy(vs->m3u8_name, s->filename, m3u8_name_size); - - if (hls->nb_varstreams > 1) { - ret = format_name(vs->basename, basename_size, i); - if (ret < 0) - goto fail; - ret = format_name(vs->m3u8_name, m3u8_name_size, i); - if (ret < 0) - goto fail; - } - if (hls->segment_type == SEGMENT_TYPE_FMP4) { if (hls->nb_varstreams > 1) fmp4_init_filename_len += strlen(POSTFIX_PATTERN); @@ -2232,13 +2285,12 @@ static int hls_init(AVFormatContext *s) } av_strlcpy(vs->fmp4_init_filename, hls->fmp4_init_filename, fmp4_init_filename_len); - if (hls->nb_varstreams > 1) { + + if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) { ret = format_name(vs->fmp4_init_filename, fmp4_init_filename_len, i); if (ret < 0) goto fail; - } - if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) { fmp4_init_filename_len = strlen(vs->fmp4_init_filename) + 1; vs->base_output_dirname = av_malloc(fmp4_init_filename_len); if (!vs->base_output_dirname) { @@ -2248,6 +2300,12 @@ static int hls_init(AVFormatContext *s) av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, fmp4_init_filename_len); } else { + if (hls->nb_varstreams > 1) { + ret = append_postfix(vs->fmp4_init_filename, fmp4_init_filename_len, i); + if (ret < 0) + goto fail; + } + fmp4_init_filename_len = strlen(vs->m3u8_name) + strlen(vs->fmp4_init_filename) + 1; @@ -2286,10 +2344,7 @@ static int hls_init(AVFormatContext *s) if (hls->flags & HLS_SINGLE_FILE) vtt_pattern = ".vtt"; - vtt_basename_size = strlen(s->filename) + strlen(vtt_pattern) + 1; - if (hls->nb_varstreams > 1) { - vtt_basename_size += strlen(POSTFIX_PATTERN); - } + vtt_basename_size = strlen(vs->m3u8_name) + strlen(vtt_pattern) + 1; vs->vtt_basename = av_malloc(vtt_basename_size); if (!vs->vtt_basename) { @@ -2301,27 +2356,21 @@ static int hls_init(AVFormatContext *s) ret = AVERROR(ENOMEM); goto fail; } - av_strlcpy(vs->vtt_basename, s->filename, vtt_basename_size); + av_strlcpy(vs->vtt_basename, vs->m3u8_name, vtt_basename_size); p = strrchr(vs->vtt_basename, '.'); if (p) *p = '\0'; if ( hls->subtitle_filename ) { strcpy(vs->vtt_m3u8_name, hls->subtitle_filename); + ret = format_name(vs->vtt_m3u8_name, vtt_basename_size, i); + if (ret < 0) + goto fail; } else { strcpy(vs->vtt_m3u8_name, vs->vtt_basename); av_strlcat(vs->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size); } av_strlcat(vs->vtt_basename, vtt_pattern, vtt_basename_size); - - if (hls->nb_varstreams > 1) { - ret= format_name(vs->vtt_basename, vtt_basename_size, i); - if (ret < 0) - goto fail; - ret = format_name(vs->vtt_m3u8_name, vtt_basename_size, i); - if (ret < 0) - goto fail; - } } if (hls->baseurl) { From 41e51fbcd9ed3fd3d9e8f98a017b152506a965d2 Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Tue, 2 Jan 2018 10:46:48 +0800 Subject: [PATCH 1520/2557] avformat/hlsenc: creation of variant streams in subdirectories Reviewed-by: Steven Liu --- doc/muxers.texi | 33 ++++++++++++++++++++- libavformat/hlsenc.c | 68 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 92 insertions(+), 9 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 553765cff8f70..b060c4f36014f 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -589,6 +589,20 @@ This example will produce the playlists segment file sets: @file{file_0_000.ts}, @file{file_0_001.ts}, @file{file_0_002.ts}, etc. and @file{file_1_000.ts}, @file{file_1_001.ts}, @file{file_1_002.ts}, etc. +The string "%v" may be present in the filename or in the last directory name +containing the file. If the string is present in the directory name, then +sub-directories are created after expanding the directory name pattern. This +enables creation of segments corresponding to different variant streams in +subdirectories. +@example +ffmpeg -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k -b:a:1 32k \ + -map 0:v -map 0:a -map 0:v -map 0:a -f hls -var_stream_map "v:0,a:0 v:1,a:1" \ + -hls_segment_filename 'vs%v/file_%03d.ts' vs%v/out.m3u8 +@end example +This example will produce the playlists segment file sets: +@file{vs0/file_000.ts}, @file{vs0/file_001.ts}, @file{vs0/file_002.ts}, etc. and +@file{vs1/file_000.ts}, @file{vs1/file_001.ts}, @file{vs1/file_002.ts}, etc. + @item use_localtime Use strftime() on @var{filename} to expand the segment filename with localtime. The segment number is also available in this mode, but to use it, you need to specify second_level_segment_index @@ -717,6 +731,11 @@ set filename to the fragment files header file, default filename is @file{init.m When @code{var_stream_map} is set with two or more variant streams, the @var{filename} pattern must contain the string "%v", this string specifies the position of variant stream index in the generated init file names. +The string "%v" may be present in the filename or in the last directory name +containing the file. If the string is present in the directory name, then +sub-directories are created after expanding the directory name pattern. This +enables creation of init files corresponding to different variant streams in +subdirectories. @item hls_flags @var{flags} Possible values: @@ -833,7 +852,11 @@ Allowed values are 0 to 9 (limited just based on practical usage). When there are two or more variant streams, the output filename pattern must contain the string "%v", this string specifies the position of variant stream -index in the output media playlist filenames. +index in the output media playlist filenames. The string "%v" may be present in +the filename or in the last directory name containing the file. If the string is +present in the directory name, then sub-directories are created after expanding +the directory name pattern. This enables creation of variant streams in +subdirectories. @example ffmpeg -re -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k -b:a:1 32k \ @@ -856,6 +879,14 @@ be an audio only stream with bitrate 64k and the third variant stream will be a video only stream with bitrate 256k. Here, three media playlist with file names out_0.m3u8, out_1.m3u8 and out_2.m3u8 will be created. @example +ffmpeg -re -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k -b:a:1 32k \ + -map 0:v -map 0:a -map 0:v -map 0:a -f hls -var_stream_map "v:0,a:0 v:1,a:1" \ + http://example.com/live/vs_%v/out.m3u8 +@end example +This example creates the variant streams in subdirectories. Here, the first +media playlist is created at @file{http://example.com/live/vs_0/out.m3u8} and +the second one at @file{http://example.com/live/vs_1/out.m3u8}. +@example ffmpeg -re -i in.ts -b:a:0 32k -b:a:1 64k -b:v:0 1000k -b:v:1 3000k \ -map 0:a -map 0:a -map 0:v -map 0:v -f hls \ -var_stream_map "a:0,agroup:aud_low a:1,agroup:aud_high v:0,agroup:aud_low v:1,agroup:aud_high" \ diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index e1dd606a61578..e36120c320631 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1549,7 +1549,8 @@ static int append_postfix(char *name, int name_buf_len, int i) static int validate_name(int nb_vs, const char *fn) { - const char *filename; + const char *filename, *subdir_name; + char *fn_dup = NULL; int ret = 0; if (!fn) { @@ -1557,22 +1558,38 @@ static int validate_name(int nb_vs, const char *fn) goto fail; } + fn_dup = av_strdup(fn); + if (!fn_dup) { + ret = AVERROR(ENOMEM); + goto fail; + } + filename = av_basename(fn); + subdir_name = av_dirname(fn_dup); - if (nb_vs > 1 && !av_stristr(filename, "%v")) { + if (nb_vs > 1 && !av_stristr(filename, "%v") && !av_stristr(subdir_name, "%v")) { av_log(NULL, AV_LOG_ERROR, "More than 1 variant streams are present, %%v is expected in the filename %s\n", fn); ret = AVERROR(EINVAL); goto fail; } + if (av_stristr(filename, "%v") && av_stristr(subdir_name, "%v")) { + av_log(NULL, AV_LOG_ERROR, "%%v is expected either in filename or in the sub-directory name of file %s\n", + fn); + ret = AVERROR(EINVAL); + goto fail; + } + fail: + av_freep(&fn_dup); return ret; } static int format_name(char *buf, int buf_len, int index) { - char *orig_buf_dup = NULL; + const char *proto, *dir; + char *orig_buf_dup = NULL, *mod_buf_dup = NULL; int ret = 0; if (!av_stristr(buf, "%v")) @@ -1589,8 +1606,27 @@ static int format_name(char *buf, int buf_len, int index) goto fail; } + proto = avio_find_protocol_name(orig_buf_dup); + dir = av_dirname(orig_buf_dup); + + /* if %v is present in the file's directory, create sub-directory */ + if (av_stristr(dir, "%v") && proto && !strcmp(proto, "file")) { + mod_buf_dup = av_strdup(buf); + if (!mod_buf_dup) { + ret = AVERROR(ENOMEM); + goto fail; + } + + dir = av_dirname(mod_buf_dup); + if (mkdir_p(dir) == -1 && errno != EEXIST) { + ret = AVERROR(errno); + goto fail; + } + } + fail: av_freep(&orig_buf_dup); + av_freep(&mod_buf_dup); return ret; } @@ -1737,16 +1773,30 @@ static int update_variant_stream_info(AVFormatContext *s) { static int update_master_pl_info(AVFormatContext *s) { HLSContext *hls = s->priv_data; const char *dir; - char *fn = NULL; + char *fn1= NULL, *fn2 = NULL; int ret = 0; - fn = av_strdup(s->filename); - if (!fn) { + fn1 = av_strdup(s->filename); + if (!fn1) { ret = AVERROR(ENOMEM); goto fail; } - dir = av_dirname(fn); + dir = av_dirname(fn1); + + /** + * if output file's directory has %v, variants are created in sub-directories + * then master is created at the sub-directories level + */ + if (dir && av_stristr(av_basename(dir), "%v")) { + fn2 = av_strdup(dir); + if (!fn2) { + ret = AVERROR(ENOMEM); + goto fail; + } + dir = av_dirname(fn2); + } + if (dir && strcmp(dir, ".")) hls->master_m3u8_url = av_append_path_component(dir, hls->master_pl_name); else @@ -1758,7 +1808,9 @@ static int update_master_pl_info(AVFormatContext *s) { } fail: - av_freep(&fn); + av_freep(&fn1); + av_freep(&fn2); + return ret; } From 92b32664cdc064523c60ddba5ed139855e08470c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 29 Dec 2017 21:25:39 +0100 Subject: [PATCH 1521/2557] avcodec/utvideodec: add support for UMH2, UMY2, UMH4, UMY4, UMRA, UMRG These are new modes which are supposed to be more SIMD friendly. Signed-off-by: Paul B Mahol --- libavcodec/utvideo.h | 8 +- libavcodec/utvideodec.c | 214 +++++++++++++++++++++++++++++++++------- libavformat/riff.c | 6 ++ 3 files changed, 189 insertions(+), 39 deletions(-) diff --git a/libavcodec/utvideo.h b/libavcodec/utvideo.h index a8117851a7c39..cf0bb28c44e10 100644 --- a/libavcodec/utvideo.h +++ b/libavcodec/utvideo.h @@ -72,17 +72,23 @@ typedef struct UtvideoContext { LLVidDSPContext llviddsp; LLVidEncDSPContext llvidencdsp; - uint32_t frame_info_size, flags, frame_info; + uint32_t frame_info_size, flags, frame_info, offset; int planes; int slices; int compression; int interlaced; int frame_pred; int pro; + int pack; ptrdiff_t slice_stride; uint8_t *slice_bits, *slice_buffer[4]; int slice_bits_size; + + const uint8_t *packed_stream[4][256]; + size_t packed_stream_size[4][256]; + const uint8_t *control_stream[4][256]; + size_t control_stream_size[4][256]; } UtvideoContext; typedef struct HuffEntry { diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index c6076811d10a5..608c8c4998a15 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -247,9 +247,50 @@ static int decode_plane(UtvideoContext *c, int plane_no, int sstart, send; VLC vlc; GetBitContext gb; - int prev, fsym; + int ret, prev, fsym; const int cmask = compute_cmask(plane_no, c->interlaced, c->avctx->pix_fmt); + if (c->pack) { + send = 0; + for (slice = 0; slice < c->slices; slice++) { + GetBitContext cbit, pbit; + uint8_t *dest, *p; + + ret = init_get_bits8(&cbit, c->control_stream[plane_no][slice], c->control_stream_size[plane_no][slice]); + if (ret < 0) + return ret; + + ret = init_get_bits8(&pbit, c->packed_stream[plane_no][slice], c->packed_stream_size[plane_no][slice]); + if (ret < 0) + return ret; + + sstart = send; + send = (height * (slice + 1) / c->slices) & cmask; + dest = dst + sstart * stride; + + for (p = dest; p < dst + send * stride; p += 8) { + int bits = get_bits_le(&cbit, 3); + + if (bits == 0) { + *(uint64_t *) p = 0; + } else { + uint32_t sub = 0x80 >> (8 - (bits + 1)), add; + int k; + + for (k = 0; k < 8; k++) { + + p[k] = get_bits_le(&pbit, bits + 1); + add = (~p[k] & sub) << (8 - bits); + p[k] -= sub; + p[k] += add; + } + } + } + } + + return 0; + } + if (build_huff(src, &vlc, &fsym)) { av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); return AVERROR_INVALIDDATA; @@ -566,7 +607,58 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, /* parse plane structure to get frame flags and validate slice offsets */ bytestream2_init(&gb, buf, buf_size); - if (c->pro) { + + if (c->pack) { + const uint8_t *packed_stream; + const uint8_t *control_stream; + GetByteContext pb; + uint32_t nb_cbs; + int left; + + c->frame_info = PRED_GRADIENT << 8; + + if (bytestream2_get_byte(&gb) != 1) + return AVERROR_INVALIDDATA; + bytestream2_skip(&gb, 3); + c->offset = bytestream2_get_le32(&gb); + + if (buf_size <= c->offset + 8LL) + return AVERROR_INVALIDDATA; + + bytestream2_init(&pb, buf + 8 + c->offset, buf_size - 8 - c->offset); + + nb_cbs = bytestream2_get_le32(&pb); + if (nb_cbs > c->offset) + return AVERROR_INVALIDDATA; + + packed_stream = buf + 8; + control_stream = packed_stream + (c->offset - nb_cbs); + left = control_stream - packed_stream; + + for (i = 0; i < c->planes; i++) { + for (j = 0; j < c->slices; j++) { + c->packed_stream[i][j] = packed_stream; + c->packed_stream_size[i][j] = bytestream2_get_le32(&pb); + left -= c->packed_stream_size[i][j]; + if (left < 0) + return AVERROR_INVALIDDATA; + packed_stream += c->packed_stream_size[i][j]; + } + } + + left = buf + buf_size - control_stream; + + for (i = 0; i < c->planes; i++) { + for (j = 0; j < c->slices; j++) { + c->control_stream[i][j] = control_stream; + c->control_stream_size[i][j] = bytestream2_get_le32(&pb); + left -= c->control_stream_size[i][j]; + if (left < 0) + return AVERROR_INVALIDDATA; + control_stream += c->control_stream_size[i][j]; + } + } + } else if (c->pro) { if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) { av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n"); return AVERROR_INVALIDDATA; @@ -635,12 +727,14 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, max_slice_size += 4*avctx->width; - av_fast_malloc(&c->slice_bits, &c->slice_bits_size, - max_slice_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!c->pack) { + av_fast_malloc(&c->slice_bits, &c->slice_bits_size, + max_slice_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!c->slice_bits) { - av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n"); - return AVERROR(ENOMEM); + if (!c->slice_bits) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n"); + return AVERROR(ENOMEM); + } } switch (c->avctx->pix_fmt) { @@ -819,37 +913,6 @@ static av_cold int decode_init(AVCodecContext *avctx) ff_bswapdsp_init(&c->bdsp); ff_llviddsp_init(&c->llviddsp); - if (avctx->extradata_size >= 16) { - av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", - avctx->extradata[3], avctx->extradata[2], - avctx->extradata[1], avctx->extradata[0]); - av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", - AV_RB32(avctx->extradata + 4)); - c->frame_info_size = AV_RL32(avctx->extradata + 8); - c->flags = AV_RL32(avctx->extradata + 12); - - if (c->frame_info_size != 4) - avpriv_request_sample(avctx, "Frame info not 4 bytes"); - av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08"PRIX32"\n", c->flags); - c->slices = (c->flags >> 24) + 1; - c->compression = c->flags & 1; - c->interlaced = c->flags & 0x800; - } else if (avctx->extradata_size == 8) { - av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", - avctx->extradata[3], avctx->extradata[2], - avctx->extradata[1], avctx->extradata[0]); - av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", - AV_RB32(avctx->extradata + 4)); - c->interlaced = 0; - c->pro = 1; - c->frame_info_size = 4; - } else { - av_log(avctx, AV_LOG_ERROR, - "Insufficient extradata size %d, should be at least 16\n", - avctx->extradata_size); - return AVERROR_INVALIDDATA; - } - c->slice_bits_size = 0; switch (avctx->codec_tag) { @@ -903,12 +966,87 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->pix_fmt = AV_PIX_FMT_YUV444P; avctx->colorspace = AVCOL_SPC_BT709; break; + case MKTAG('U', 'M', 'Y', '2'): + c->planes = 3; + c->pack = 1; + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + avctx->colorspace = AVCOL_SPC_BT470BG; + break; + case MKTAG('U', 'M', 'H', '2'): + c->planes = 3; + c->pack = 1; + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + avctx->colorspace = AVCOL_SPC_BT709; + break; + case MKTAG('U', 'M', 'Y', '4'): + c->planes = 3; + c->pack = 1; + avctx->pix_fmt = AV_PIX_FMT_YUV444P; + avctx->colorspace = AVCOL_SPC_BT470BG; + break; + case MKTAG('U', 'M', 'H', '4'): + c->planes = 3; + c->pack = 1; + avctx->pix_fmt = AV_PIX_FMT_YUV444P; + avctx->colorspace = AVCOL_SPC_BT709; + break; + case MKTAG('U', 'M', 'R', 'G'): + c->planes = 3; + c->pack = 1; + avctx->pix_fmt = AV_PIX_FMT_GBRP; + break; + case MKTAG('U', 'M', 'R', 'A'): + c->planes = 4; + c->pack = 1; + avctx->pix_fmt = AV_PIX_FMT_GBRAP; + break; default: av_log(avctx, AV_LOG_ERROR, "Unknown Ut Video FOURCC provided (%08X)\n", avctx->codec_tag); return AVERROR_INVALIDDATA; } + if (c->pack && avctx->extradata_size >= 16) { + av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", + avctx->extradata[3], avctx->extradata[2], + avctx->extradata[1], avctx->extradata[0]); + av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", + AV_RB32(avctx->extradata + 4)); + c->compression = avctx->extradata[8]; + if (c->compression != 2) + avpriv_request_sample(avctx, "Unknown compression type"); + c->slices = avctx->extradata[9] + 1; + } else if (avctx->extradata_size >= 16) { + av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", + avctx->extradata[3], avctx->extradata[2], + avctx->extradata[1], avctx->extradata[0]); + av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", + AV_RB32(avctx->extradata + 4)); + c->frame_info_size = AV_RL32(avctx->extradata + 8); + c->flags = AV_RL32(avctx->extradata + 12); + + if (c->frame_info_size != 4) + avpriv_request_sample(avctx, "Frame info not 4 bytes"); + av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08"PRIX32"\n", c->flags); + c->slices = (c->flags >> 24) + 1; + c->compression = c->flags & 1; + c->interlaced = c->flags & 0x800; + } else if (avctx->extradata_size == 8) { + av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", + avctx->extradata[3], avctx->extradata[2], + avctx->extradata[1], avctx->extradata[0]); + av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", + AV_RB32(avctx->extradata + 4)); + c->interlaced = 0; + c->pro = 1; + c->frame_info_size = 4; + } else { + av_log(avctx, AV_LOG_ERROR, + "Insufficient extradata size %d, should be at least 16\n", + avctx->extradata_size); + return AVERROR_INVALIDDATA; + } + return 0; } diff --git a/libavformat/riff.c b/libavformat/riff.c index 3f0b390774fc7..89117250d4ef4 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -404,6 +404,12 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'Y', '2') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'R', 'A') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'R', 'G') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'M', 'Y', '2') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'M', 'H', '2') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'M', 'Y', '4') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'M', 'H', '4') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'M', 'R', 'A') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'M', 'R', 'G') }, { AV_CODEC_ID_VBLE, MKTAG('V', 'B', 'L', 'E') }, { AV_CODEC_ID_ESCAPE130, MKTAG('E', '1', '3', '0') }, { AV_CODEC_ID_DXTORY, MKTAG('x', 't', 'o', 'r') }, From 57d0c24132c544441266b3f561d9af15d4f8cf42 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 31 Dec 2017 10:47:27 +0100 Subject: [PATCH 1522/2557] avcodec/utvideoenc: switch to planar RGB formats Signed-off-by: Paul B Mahol --- libavcodec/utvideoenc.c | 47 ++++++------ tests/fate/utvideo.mak | 12 ++-- tests/ref/fate/utvideoenc_rgb_left | 100 +++++++++++++------------- tests/ref/fate/utvideoenc_rgb_median | 100 +++++++++++++------------- tests/ref/fate/utvideoenc_rgb_none | 100 +++++++++++++------------- tests/ref/fate/utvideoenc_rgba_left | 100 +++++++++++++------------- tests/ref/fate/utvideoenc_rgba_median | 100 +++++++++++++------------- tests/ref/fate/utvideoenc_rgba_none | 100 +++++++++++++------------- 8 files changed, 333 insertions(+), 326 deletions(-) diff --git a/libavcodec/utvideoenc.c b/libavcodec/utvideoenc.c index 840742caf7130..a829b7aaac59e 100644 --- a/libavcodec/utvideoenc.c +++ b/libavcodec/utvideoenc.c @@ -67,12 +67,12 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) c->slice_stride = FFALIGN(avctx->width, 32); switch (avctx->pix_fmt) { - case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_GBRP: c->planes = 3; avctx->codec_tag = MKTAG('U', 'L', 'R', 'G'); original_format = UTVIDEO_RGB; break; - case AV_PIX_FMT_RGBA: + case AV_PIX_FMT_GBRAP: c->planes = 4; avctx->codec_tag = MKTAG('U', 'L', 'R', 'A'); original_format = UTVIDEO_RGBA; @@ -243,36 +243,43 @@ FF_ENABLE_DEPRECATION_WARNINGS } static void mangle_rgb_planes(uint8_t *dst[4], ptrdiff_t dst_stride, - uint8_t *src, int step, ptrdiff_t stride, + uint8_t *const src[4], int planes, const int stride[4], int width, int height) { int i, j; int k = 2 * dst_stride; + const uint8_t *sg = src[0]; + const uint8_t *sb = src[1]; + const uint8_t *sr = src[2]; + const uint8_t *sa = src[3]; unsigned int g; for (j = 0; j < height; j++) { - if (step == 3) { - for (i = 0; i < width * step; i += step) { - g = src[i + 1]; + if (planes == 3) { + for (i = 0; i < width; i++) { + g = sg[i]; dst[0][k] = g; g += 0x80; - dst[1][k] = src[i + 2] - g; - dst[2][k] = src[i + 0] - g; + dst[1][k] = sb[i] - g; + dst[2][k] = sr[i] - g; k++; } } else { - for (i = 0; i < width * step; i += step) { - g = src[i + 1]; + for (i = 0; i < width; i++) { + g = sg[i]; dst[0][k] = g; g += 0x80; - dst[1][k] = src[i + 2] - g; - dst[2][k] = src[i + 0] - g; - dst[3][k] = src[i + 3]; + dst[1][k] = sb[i] - g; + dst[2][k] = sr[i] - g; + dst[3][k] = sa[i]; k++; } + sa += stride[3]; } k += dst_stride - width; - src += stride; + sg += stride[0]; + sb += stride[1]; + sr += stride[2]; } } @@ -572,14 +579,14 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } /* In case of RGB, mangle the planes to Ut Video's format */ - if (avctx->pix_fmt == AV_PIX_FMT_RGBA || avctx->pix_fmt == AV_PIX_FMT_RGB24) - mangle_rgb_planes(c->slice_buffer, c->slice_stride, pic->data[0], - c->planes, pic->linesize[0], width, height); + if (avctx->pix_fmt == AV_PIX_FMT_GBRAP || avctx->pix_fmt == AV_PIX_FMT_GBRP) + mangle_rgb_planes(c->slice_buffer, c->slice_stride, pic->data, + c->planes, pic->linesize, width, height); /* Deal with the planes */ switch (avctx->pix_fmt) { - case AV_PIX_FMT_RGB24: - case AV_PIX_FMT_RGBA: + case AV_PIX_FMT_GBRP: + case AV_PIX_FMT_GBRAP: for (i = 0; i < c->planes; i++) { ret = encode_plane(avctx, c->slice_buffer[i] + 2 * c->slice_stride, c->slice_buffer[i], c->slice_stride, i, @@ -690,7 +697,7 @@ AVCodec ff_utvideo_encoder = { .close = utvideo_encode_close, .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, .pix_fmts = (const enum AVPixelFormat[]) { - AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, }; diff --git a/tests/fate/utvideo.mak b/tests/fate/utvideo.mak index 929a4ee6e2f27..23224718ee61a 100644 --- a/tests/fate/utvideo.mak +++ b/tests/fate/utvideo.mak @@ -70,22 +70,22 @@ fate-utvideo: $(FATE_UTVIDEO) fate-utvideoenc%: CMD = framemd5 -f image2 -c:v pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -c:v utvideo -slices 1 -sws_flags +accurate_rnd+bitexact ${OPTS} FATE_UTVIDEOENC += fate-utvideoenc_rgba_left -fate-utvideoenc_rgba_left: OPTS = -pix_fmt rgba -pred left +fate-utvideoenc_rgba_left: OPTS = -pix_fmt gbrap -pred left FATE_UTVIDEOENC += fate-utvideoenc_rgba_median -fate-utvideoenc_rgba_median: OPTS = -pix_fmt rgba -pred median +fate-utvideoenc_rgba_median: OPTS = -pix_fmt gbrap -pred median FATE_UTVIDEOENC += fate-utvideoenc_rgba_none -fate-utvideoenc_rgba_none: OPTS = -pix_fmt rgba -pred none +fate-utvideoenc_rgba_none: OPTS = -pix_fmt gbrap -pred none FATE_UTVIDEOENC += fate-utvideoenc_rgb_left -fate-utvideoenc_rgb_left: OPTS = -pix_fmt rgb24 -pred left +fate-utvideoenc_rgb_left: OPTS = -pix_fmt gbrp -pred left FATE_UTVIDEOENC += fate-utvideoenc_rgb_median -fate-utvideoenc_rgb_median: OPTS = -pix_fmt rgb24 -pred median +fate-utvideoenc_rgb_median: OPTS = -pix_fmt gbrp -pred median FATE_UTVIDEOENC += fate-utvideoenc_rgb_none -fate-utvideoenc_rgb_none: OPTS = -pix_fmt rgb24 -pred none +fate-utvideoenc_rgb_none: OPTS = -pix_fmt gbrp -pred none FATE_UTVIDEOENC += fate-utvideoenc_yuv420_left fate-utvideoenc_yuv420_left: OPTS = -pix_fmt yuv420p -pred left diff --git a/tests/ref/fate/utvideoenc_rgb_left b/tests/ref/fate/utvideoenc_rgb_left index a1d200096a641..1ee7c5856433d 100644 --- a/tests/ref/fate/utvideoenc_rgb_left +++ b/tests/ref/fate/utvideoenc_rgb_left @@ -8,53 +8,53 @@ #dimensions 0: 352x288 #sar 0: 0/1 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 182328, cd084b244939d7e0008d8e5ab3429dc1 -0, 1, 1, 1, 182336, c9c40672750f372134185901147fb776 -0, 2, 2, 1, 182956, c728911ca73225f2dc7453533c9be95e -0, 3, 3, 1, 182384, 54521f709b461a25198db755bce582fa -0, 4, 4, 1, 181704, 5e03ab58b4480a6613f54857f10c39e5 -0, 5, 5, 1, 182136, c623fb06b90fdd7a5ba0b4f217b6a388 -0, 6, 6, 1, 181552, 5d03be9dfc01ad99364fc3cc8378af72 -0, 7, 7, 1, 182292, fc90878278c82b2f835151dc6d43dd47 -0, 8, 8, 1, 181424, 9b6339a0d3af2d3034162183cd4d79e4 -0, 9, 9, 1, 182316, 7e45bb5ffe57f98a433420abaffe78cc -0, 10, 10, 1, 182064, d9525605a7d7d75a8e33502f61733af1 -0, 11, 11, 1, 182596, 62e87fa5c33a8d208deaa8719682b9a5 -0, 12, 12, 1, 180900, 149059d3d56c55358c7044c7d569730f -0, 13, 13, 1, 181920, 0d20f588c27471a038e159a131e9c8ea -0, 14, 14, 1, 182824, a301a411ff11042ecb583e1e3b12dbda -0, 15, 15, 1, 182452, 0ee2a9ed39fb8569a8d6c2b3afb8f80a -0, 16, 16, 1, 182312, 68dd3b820adf2cbc6686a7d48fa22c6e -0, 17, 17, 1, 181856, 1897926cfe9b7acaf9c21714c449ce41 -0, 18, 18, 1, 181108, 15d2af460733fdd896078632cdfef9fd -0, 19, 19, 1, 181388, 8b8e7a4b7d355f41f7e836120c4792ac -0, 20, 20, 1, 180936, e18e27aa027f2470bfa95c536a0a89af -0, 21, 21, 1, 180900, eb663ae3c5ffa8e751280e0dbb260e02 -0, 22, 22, 1, 181936, 7514bbe06cee027f54710dc900297863 -0, 23, 23, 1, 182304, 8cb2dcdbd4c919b4c977f45bee46c54c -0, 24, 24, 1, 182580, 9185ed53b7e8339b61d3abe230bbab71 -0, 25, 25, 1, 182572, 81f8bdd3255b91d6621e9ebd3c9d7679 -0, 26, 26, 1, 182356, 1f9ff40700881054c62e33acde06910d -0, 27, 27, 1, 181532, 10d2477aa1e319a61e517d25fd6c95d0 -0, 28, 28, 1, 179580, 3012480c43d15866ccc4a81d56650ee2 -0, 29, 29, 1, 179528, 5e0fbd62a164dc72cf511023da792175 -0, 30, 30, 1, 180760, 679f430c86dca203456f532e978dffc2 -0, 31, 31, 1, 181564, 64d31faf01cb7b52d7d7e20280e6652b -0, 32, 32, 1, 181428, 04961d71aa3c81b33d28b39ead20ee1d -0, 33, 33, 1, 182980, 51361c802005721002f5f4924f081708 -0, 34, 34, 1, 182624, 67c5582c45e3ee7e6aca49fdc0a980b8 -0, 35, 35, 1, 182352, 4fade9db12f2d6ce633556fdb8914971 -0, 36, 36, 1, 181336, ac8fbab67b36d58c4e8374bfb07458e7 -0, 37, 37, 1, 181528, f798157b6d4d04c767ecb76346922ddc -0, 38, 38, 1, 179776, 01d407ed0b86eeb2c3ee3c24dd452d8d -0, 39, 39, 1, 180100, 062e4af150100d7accf86a907a4b99b5 -0, 40, 40, 1, 180228, 23c617b76ef8f274bd089016fb8516c7 -0, 41, 41, 1, 180592, 5cd3d93597325196079dc019556f6933 -0, 42, 42, 1, 181188, d39d52f5b690661434b1abd8717b3e30 -0, 43, 43, 1, 181300, 9e202444287234bafd103fab83b1a974 -0, 44, 44, 1, 180812, 602165271de71594132cce98af56a7b2 -0, 45, 45, 1, 178816, c427d67196f43ece6bf3855e1256d7bb -0, 46, 46, 1, 178196, 0d05902e2870a85333a216c723077e98 -0, 47, 47, 1, 178772, 57f528eb984b5b7181c89b48b58271f3 -0, 48, 48, 1, 178652, 5cd1031b0ada3ba9c2d4c2f2b7c8e277 -0, 49, 49, 1, 178512, d3c0c84fc63f1e32a4a026e2cd39b161 +0, 0, 0, 1, 197832, 11da778d3d904fcd2ad6daf84b227e6b +0, 1, 1, 1, 197840, e89c967c27d7cd9963c9f12f9df2c268 +0, 2, 2, 1, 198632, b2c59f9834024d1e4b829e540a91814e +0, 3, 3, 1, 197100, b21b344d42da10ef6730fed553fb3f2f +0, 4, 4, 1, 196236, e61de0e4ff879b6630ae8eb63d063b7f +0, 5, 5, 1, 197352, efd21105f5f98cbd5953e85a10091531 +0, 6, 6, 1, 197252, 0e2444a9185f68294c16f034dd522666 +0, 7, 7, 1, 197204, 0254750d85c474c13fe3c0e4e3c272cf +0, 8, 8, 1, 197084, 4c89a99df233575978d9bcd8936e4588 +0, 9, 9, 1, 197692, 681a76f67892f9d05be72abaa403bc32 +0, 10, 10, 1, 197456, bba96b8520eaa5b6612b5c48d6409938 +0, 11, 11, 1, 197024, b9ea3dcc0cb8cf552e536765c5bb31f6 +0, 12, 12, 1, 195132, 2664b79397af76081b7ddd5c3507d579 +0, 13, 13, 1, 196796, d6128308c1fc3493ebc2cece7ed785cb +0, 14, 14, 1, 198708, 6b3e50d5d47f29dfb38e178ffb9036c5 +0, 15, 15, 1, 198000, a3d6be893edb02e44f65f7a06aa8eeed +0, 16, 16, 1, 197568, 1ed7a01f810770d62aed3d12d10cd12c +0, 17, 17, 1, 197396, 515e13befb9eebf92f77574d6cd9fec4 +0, 18, 18, 1, 196680, ac1835b9a426927855e3e5dbab28c177 +0, 19, 19, 1, 196784, 56fa26a339c69df17d003fb00b335baa +0, 20, 20, 1, 195980, 853744fb2a2de76858d32f35f8b3d836 +0, 21, 21, 1, 196120, e9c50124d92e261f7a98599cb9a20e36 +0, 22, 22, 1, 196620, e750eaed752d09874d823ee40a8904c4 +0, 23, 23, 1, 197528, 6671598014db402b70e2753efda028d1 +0, 24, 24, 1, 198204, 6e471eb9c354d6be4e0d8a691313e23e +0, 25, 25, 1, 197512, 7e415738fb7889dee478f63900f47e7c +0, 26, 26, 1, 196832, 0e30afab6de602d099d88edd6276f1de +0, 27, 27, 1, 196396, 13880ad888c9cf3504e2eb087767602e +0, 28, 28, 1, 194220, aa9007687cade8c9a872de063bed0755 +0, 29, 29, 1, 194428, 78ab57958ef8914095477e58ee4461c2 +0, 30, 30, 1, 195676, a7d0779dcda7f93da5601482bb68625b +0, 31, 31, 1, 196352, 668c525c910000aab7d9285be6ac7ed1 +0, 32, 32, 1, 196468, 9c124995d63f2a548e640811e9391951 +0, 33, 33, 1, 198188, 1cb600005e68d1ef1418b1b42e463f0a +0, 34, 34, 1, 197556, 80f6223aba2d6cfab3cb596f372243f2 +0, 35, 35, 1, 197020, b1890bbb734c016103190a9c043e9fe2 +0, 36, 36, 1, 196208, 7adf4b08c90231eddec16aff65cc138f +0, 37, 37, 1, 196448, de69c81a605c9e173a7ac65077d0396d +0, 38, 38, 1, 194072, 8b3afb6897210f1660b4427df0d9cc51 +0, 39, 39, 1, 194036, 1827f1deef659426939ffd94b73575bc +0, 40, 40, 1, 194436, 46f3ad01e18a2a24d720e78f9bdb532d +0, 41, 41, 1, 195696, a160ff1e281959147fe11606754ecc7d +0, 42, 42, 1, 196044, 37f15771f5c04c13b02c0127bd977fed +0, 43, 43, 1, 196384, fc43c356e577555757e220bee7e8a232 +0, 44, 44, 1, 195424, 6820346735e390b86d9564298c934101 +0, 45, 45, 1, 193688, 5f346f622f8e0d33d7f662e9dfbcccb5 +0, 46, 46, 1, 193000, 15eb6569d9fd39a343d110b965a97277 +0, 47, 47, 1, 193592, d41d561eb927b8e0d608177af90d0e1d +0, 48, 48, 1, 193512, 35112e23e238beff03c769674db40399 +0, 49, 49, 1, 192528, 3a3ac1b24fb8fc72174970d668c30292 diff --git a/tests/ref/fate/utvideoenc_rgb_median b/tests/ref/fate/utvideoenc_rgb_median index b1558d7f53330..6c4d2f808a8ca 100644 --- a/tests/ref/fate/utvideoenc_rgb_median +++ b/tests/ref/fate/utvideoenc_rgb_median @@ -8,53 +8,53 @@ #dimensions 0: 352x288 #sar 0: 0/1 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 182160, abcf4f477f74b696faca2fcff1f62aa9 -0, 1, 1, 1, 182104, 7cbcf339fa40c24522067295b39d637f -0, 2, 2, 1, 183108, dfc2c418f4379a89654c16b34ff19446 -0, 3, 3, 1, 182320, 62a4647b05709d86c51a18be16877e98 -0, 4, 4, 1, 181920, 61d63520703503f6e17fad67cbc08794 -0, 5, 5, 1, 182424, f467638396feabe613b3c851289452d8 -0, 6, 6, 1, 182248, 8a0cba950d6c5d63ba9603212ca95b0e -0, 7, 7, 1, 181876, 91432f472cf373d5d4036bd100950f3e -0, 8, 8, 1, 182104, 1c8852d82a48c1b01911ffbedf0ac1f4 -0, 9, 9, 1, 182540, f36b9d48123b55f2141ae10dd26e1ca0 -0, 10, 10, 1, 182120, e6ecdb9af6591916153ca9aeba76b9d0 -0, 11, 11, 1, 182136, 7dc7b828a5b7c652df612474fad66f6b -0, 12, 12, 1, 181296, 347eac6563435a62f75298cefe13d3a6 -0, 13, 13, 1, 182136, 3bbcd8afacdf9549da9ebd736df548a7 -0, 14, 14, 1, 182412, 17f8c6ef692b4085624ce1ef7efbc963 -0, 15, 15, 1, 182732, 9212760fa11fe4fa193ba1aa259e9765 -0, 16, 16, 1, 181944, 7dd6d6a7084f97a77ec09ec6c62f0ab8 -0, 17, 17, 1, 182232, 518552687d47ae93726679f0ed962ef4 -0, 18, 18, 1, 181512, 29a66924742add13a0cae65d93d38ea9 -0, 19, 19, 1, 181424, 67c965637248333f92da9d493bf7546e -0, 20, 20, 1, 180764, 298457c6c2b3f4ebcda87a12579f094d -0, 21, 21, 1, 181072, 493ea592b7d59eebf01c002e7e22fc43 -0, 22, 22, 1, 181160, e30195fcc16ecfbb9348943cff01623f -0, 23, 23, 1, 182156, d26cfac33e19b4ca11210c9e6cb91955 -0, 24, 24, 1, 182260, 963c157d3f0023b49d23099d53d60c8b -0, 25, 25, 1, 181976, 2494d481bf2be97692eaeda95f279b0d -0, 26, 26, 1, 181832, f1be95c840d4fcb0c8d4b7aed5b197c5 -0, 27, 27, 1, 181424, 03d92e89358a8b9b9e7cf302edde307e -0, 28, 28, 1, 180632, 09f9e162fdaf28342c442172179a75c9 -0, 29, 29, 1, 180624, 481e7f7730ab3ba67c06faa620a8bd5e -0, 30, 30, 1, 181024, 7a1d1b06b73d2bf41563eb749805780c -0, 31, 31, 1, 181844, 8a6ce6dd6f79e423a3bb6c2b163adc55 -0, 32, 32, 1, 181712, a68007bbdf0169c9ed2dffae3dc63221 -0, 33, 33, 1, 182008, f37dd0635de369761e2de979ee799c3a -0, 34, 34, 1, 181800, 14029ba1c364eca476559ce553919e99 -0, 35, 35, 1, 181840, ee227d15f15c3cd564dcad2160453fb7 -0, 36, 36, 1, 181848, 13b5d0892cc76a25b4914f2d706a0ad5 -0, 37, 37, 1, 181976, 1a0be9f2cefe0d867c5c03d6b3987ad8 -0, 38, 38, 1, 181216, 79795d735f9e0f92091203bf8b9eb9ed -0, 39, 39, 1, 181236, 2d006c8c4ba448ca7841df76e44ffa88 -0, 40, 40, 1, 180672, ed5210abdae49042fcae9bde2f65a057 -0, 41, 41, 1, 181324, fbbc7839c595cd0f0efc0917edfed2c3 -0, 42, 42, 1, 180980, c6120b5a9440f4a0d83731627eb96d98 -0, 43, 43, 1, 181204, ac4371912d16f657c90e8a00cfafdfd2 -0, 44, 44, 1, 180720, d392d95c67349296d922dbf53ec3f832 -0, 45, 45, 1, 180028, 37a2717fbd5aaeb128812298484f8267 -0, 46, 46, 1, 179704, e8716f4856e4ccdc541632a218894f62 -0, 47, 47, 1, 179648, e99cbe5d1bbd7bce241ae500b4de06c2 -0, 48, 48, 1, 179424, 6f8a5e356fb77b61d9dfcabdf97340b9 -0, 49, 49, 1, 178980, 75a7700b822236b0ecb169fd692910f1 +0, 0, 0, 1, 194232, 96431f57c15dfce7894563df186457c7 +0, 1, 1, 1, 194256, f7617d88a5bb862047dd62a3618eca2c +0, 2, 2, 1, 195048, 77aa5446e64733aa29bf5ba4ad92073d +0, 3, 3, 1, 194012, 4a73e8b156eebc15de299c57087639a5 +0, 4, 4, 1, 193268, a0afb35be4f9f91366d848b0600c949d +0, 5, 5, 1, 194168, b0580fbf05dc9a2abc053f2deb48b8c9 +0, 6, 6, 1, 194240, 5f5adb862a13843123e27f01d1870799 +0, 7, 7, 1, 193512, 71dca88d3fdf753858887006ac3cc13b +0, 8, 8, 1, 193952, 7efa7d138fa412343741ccbeb18acd18 +0, 9, 9, 1, 194700, ffddf410e5b8e49cf0462baf7bc9e179 +0, 10, 10, 1, 193984, c71b59a9699f2832e8c3d76e5d5e4f0c +0, 11, 11, 1, 193640, 598bdf3a814db44775ad703d674e9ab9 +0, 12, 12, 1, 192900, de83dd60e69a305ab0a79c4a859d444d +0, 13, 13, 1, 193780, 7858349baa970794b0353e011f751259 +0, 14, 14, 1, 194564, 9470359eb6f09d5a1db5dc199e910bcf +0, 15, 15, 1, 194856, c15823765a9d4d1583f2dd7b63534c95 +0, 16, 16, 1, 194056, 5f60ee32c9e06f080dcd0b4025576d5b +0, 17, 17, 1, 194124, a10815c6603e375ab0b21331e03651de +0, 18, 18, 1, 193508, 54a5762f2717ce1be3b9193b930d1b1f +0, 19, 19, 1, 193412, 782b07b8ac3bd1a86ad562ef7d7ebca5 +0, 20, 20, 1, 192472, 96f7f1983d6ac34c591e33045c5ba3dc +0, 21, 21, 1, 192844, b56bec01d69b3e073ac9823b2bf4c2f5 +0, 22, 22, 1, 192668, 3071c2d282672a597bee4682cef304ff +0, 23, 23, 1, 194108, 3484d2ca748c20d87280f5333054552d +0, 24, 24, 1, 194552, b05a90da02c18ee880234d620259361d +0, 25, 25, 1, 193860, 08617a493d2abe75b438a35315aef7a0 +0, 26, 26, 1, 193452, 958eaccd55d6a55832ec9cb6ce201fc4 +0, 27, 27, 1, 193364, 8cab6850866ce9c0ecf818cc4630bdb3 +0, 28, 28, 1, 192064, 03ce30fadf6b80d0b901c0f53f09e23b +0, 29, 29, 1, 192464, 7bf3364a095cbea2a032f6762d3433bf +0, 30, 30, 1, 192880, 6176bcbdf42f787aa4c21791fd3d73e2 +0, 31, 31, 1, 193672, 0760b04edf969c5b0914fcae82ee7ee3 +0, 32, 32, 1, 193636, a08c905e46e35d575001e570389a9b70 +0, 33, 33, 1, 193976, dff151dc2dfa5a86103bddc11484a38f +0, 34, 34, 1, 193456, 86f44e4a438ad150baee14facdebb701 +0, 35, 35, 1, 193768, 5645f55ed8154a0c913890a11b6f1261 +0, 36, 36, 1, 193584, 023ca364d9a88ccb2bae08008c6c3098 +0, 37, 37, 1, 193844, be83062bffff72ba0c442f502c41a187 +0, 38, 38, 1, 193008, 6e1dd8f2d18145ee199395d34c0e55ff +0, 39, 39, 1, 192680, 27256f3f1111554a75d7b7366b77457f +0, 40, 40, 1, 192188, d86ea5fafc41d57e320479f54fd1286a +0, 41, 41, 1, 193200, a37553416c0187b364ce2b64ece22975 +0, 42, 42, 1, 193052, 8e3c81d246b744c2aed9b735015ee93f +0, 43, 43, 1, 193032, dd8e2b350d8181c6a73832c868ea99f4 +0, 44, 44, 1, 192444, 6844e2dc435f417028644d3314b94c4f +0, 45, 45, 1, 191824, fc01e22ba45bca6eac69ba76043e1484 +0, 46, 46, 1, 191772, 5e2bedda3828d590d25caa14f96ba7b0 +0, 47, 47, 1, 191720, edaae522f8a975bbef0e909ef09e7fc7 +0, 48, 48, 1, 191528, f2d98179f5cf0752ecbd6d39c4457283 +0, 49, 49, 1, 190692, 74cd0f762371781712e2ff2e3f60ac57 diff --git a/tests/ref/fate/utvideoenc_rgb_none b/tests/ref/fate/utvideoenc_rgb_none index 403c807a4a7cf..27df8badca105 100644 --- a/tests/ref/fate/utvideoenc_rgb_none +++ b/tests/ref/fate/utvideoenc_rgb_none @@ -8,53 +8,53 @@ #dimensions 0: 352x288 #sar 0: 0/1 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 301024, 44de62472f485410819707c44b53f276 -0, 1, 1, 1, 301036, ff3c28c23b15834a84c57b304610924f -0, 2, 2, 1, 300812, 72f02a697464f5fdd54ae2e054c131d1 -0, 3, 3, 1, 300876, 8879becf8b3d5001b196f45b7817ef6b -0, 4, 4, 1, 300880, 2edeed55c4d84dea1fc9386553d7503f -0, 5, 5, 1, 300904, f799f26eae30e1796bd62f9cdbcb2b17 -0, 6, 6, 1, 300908, bc606ee3ab284d3567a3fbd476d674f0 -0, 7, 7, 1, 301012, 404f55be9ec860a1ab3d15711965c9ba -0, 8, 8, 1, 301048, 112394db28656101b4e8ba3621b437ae -0, 9, 9, 1, 301008, 8945bb7668b4a529844e68e1f6b6522b -0, 10, 10, 1, 300908, a9097c5f0bd7ddea711a25aa74696f70 -0, 11, 11, 1, 300876, 579de317d166295088530c78f403611d -0, 12, 12, 1, 301012, d97e3627c494012d6167a30ec8192360 -0, 13, 13, 1, 300928, fd20066b7f31363751328aefedfae04c -0, 14, 14, 1, 300836, d9bdd5606f4426b503f19a674e8058a3 -0, 15, 15, 1, 300848, 6c8f2cbd75646592876f8138a017c1ce -0, 16, 16, 1, 300988, 54e19940011b3bfed809a0edc12c3dd7 -0, 17, 17, 1, 301040, b1d5f39215f305953a846fb01dbc2f24 -0, 18, 18, 1, 301164, 9dde74f0ee3626eeea41c538fd80e1fb -0, 19, 19, 1, 301196, fdf22d2c35c7ab72416a268bf6612650 -0, 20, 20, 1, 301148, 275261bc1c1dec0bf712dcf05213def2 -0, 21, 21, 1, 301144, 66ccea6fce9d6d7016dafb3b349fa163 -0, 22, 22, 1, 301080, d6dc6ce0708dfdf74e936271a98c19e9 -0, 23, 23, 1, 301028, 48e610b9d798e0642825919fab233524 -0, 24, 24, 1, 301100, aed8f8f0a9d96ab9906ea8175e18c9ff -0, 25, 25, 1, 301116, fe9e1eccb9ccc92b4041228ea2c56c8e -0, 26, 26, 1, 301052, 3ec2f76b41fd8a6eafaa6bb14b94c153 -0, 27, 27, 1, 301200, 60d608bbe0ca285a7d8a1a4822a84c4d -0, 28, 28, 1, 301120, 6d2cec50ee32e76eb6dff76a4976d221 -0, 29, 29, 1, 301188, 8faa69fd62e0646e4eb85c1601827364 -0, 30, 30, 1, 301192, eb1fa109c5e9b89f29be7cf363649acd -0, 31, 31, 1, 301128, 32ba1797f5dee6643712688621984326 -0, 32, 32, 1, 301088, a1bfa70314c40f60a0823beef74e233e -0, 33, 33, 1, 301064, b18d84efa0091199dd9167bbdb36b873 -0, 34, 34, 1, 300964, a2ae8d3dd655403bcfdace40aaa1d78b -0, 35, 35, 1, 301124, 8ece60df0f0ef4f3d887eac16c23cad6 -0, 36, 36, 1, 301200, 13eb4b5ec7471837aadce38848e48cb2 -0, 37, 37, 1, 301196, b5fdef211755134f8e7998793a0ab0c0 -0, 38, 38, 1, 301260, 2f7e2046bae9e664e74bc56a3596743c -0, 39, 39, 1, 301264, 2cfc013c9e66a5dd0229c6551febd658 -0, 40, 40, 1, 301272, 47e8ff02a8f054c66687e2b613e46cf5 -0, 41, 41, 1, 301236, f4d766155eeeb7b03687a3141840bf32 -0, 42, 42, 1, 301312, 8fe134aefc02b6910dc2054447fd9c37 -0, 43, 43, 1, 301272, 9ec57db275fca2b596734c48a50c28bc -0, 44, 44, 1, 301256, 17bae207d8d6f5b2b500885e3058185f -0, 45, 45, 1, 301308, 9f8e91f3fbbdd0ca17b2ad0ffe888d5a -0, 46, 46, 1, 301400, 8184e55eb5432516547df512175c15fc -0, 47, 47, 1, 301408, dd0c0aa1426427549e9cbb22ef82f930 -0, 48, 48, 1, 301424, c65025dc3fa21fad98118ab0386b910e -0, 49, 49, 1, 301408, 2982b49e94aa25b8ef30f81769650f15 +0, 0, 0, 1, 303768, c37d23b5bc1dcceacafcebd0a5054590 +0, 1, 1, 1, 303764, a6a8b445323c00ab56ad1077a90b34bf +0, 2, 2, 1, 303672, 029048769e006f2a2357f373cfc0b6bf +0, 3, 3, 1, 303672, e13433d7e8f75a26eeca86523d47d0cf +0, 4, 4, 1, 303724, 4c3d437c158255e398071bdd2e699d9e +0, 5, 5, 1, 303672, 11e335df4fdfcfb7563305a33740058e +0, 6, 6, 1, 303676, 594a7a6101fbf884bb3bc309479bdf18 +0, 7, 7, 1, 303764, 09f91a05f8f507f6338d15591df34002 +0, 8, 8, 1, 303772, 1e177889c188fdd783815103c1987e5e +0, 9, 9, 1, 303700, f6da8873c69fb6365764327305a36840 +0, 10, 10, 1, 303684, 6810c80719058078b7d40a787fabee70 +0, 11, 11, 1, 303696, f8dcad694c276074f5022276e4067694 +0, 12, 12, 1, 303720, d1f764aaf14e78b64b182503342df764 +0, 13, 13, 1, 303676, 43066ddba20726f57d76230891f76730 +0, 14, 14, 1, 303548, 6512bff050521cd6343e5b2f4b18be6c +0, 15, 15, 1, 303604, 76c91368e8db8c18591c7cb569774e12 +0, 16, 16, 1, 303748, 365805842ee3cefee8d5feb169075ecf +0, 17, 17, 1, 303740, e6bbc34d7057d812cd994473b93ccadb +0, 18, 18, 1, 303788, 48bcbbc3bf805586c34ff23ebeaa28ea +0, 19, 19, 1, 303808, 29f268867c4522551e6f73dd4afb36e1 +0, 20, 20, 1, 303808, effd1cf0a61501f427e47c76c469ff32 +0, 21, 21, 1, 303832, 0ea84576612a4b0b8f9e14b3ecf10861 +0, 22, 22, 1, 303800, 4b4d24ce4f176de4c34ec85656ea1e49 +0, 23, 23, 1, 303716, 58845ad1c9a07d62f83414662eaf1181 +0, 24, 24, 1, 303780, 8db647c5324b3c061aa2cdae7527ec8d +0, 25, 25, 1, 303824, 7a2ddbe9d1af3d34d7538ba10a0aae3c +0, 26, 26, 1, 303796, a8444e8ec7b64c3481766ebcafd2e7b7 +0, 27, 27, 1, 303816, bf78e04e04429aab3527baacd51da1b0 +0, 28, 28, 1, 303872, 02d9693cc78af1b9d4a17b5361daa325 +0, 29, 29, 1, 303900, 065cde35c0ac49675a9ee8e047bb1471 +0, 30, 30, 1, 303876, 0888dd5201864a9f34f784b7959563ba +0, 31, 31, 1, 303828, 6837a1a3f4ae04c9601fa9f4c27098b2 +0, 32, 32, 1, 303720, 8c90fc8481d745b020c325134bf0047d +0, 33, 33, 1, 303704, d37bd88a42e4b84a98f0e51208a3877d +0, 34, 34, 1, 303640, 2444c069427bf6a847113fd16e7a863f +0, 35, 35, 1, 303780, 7a9aa1d7d43bcb22a754fa5e7ee911a0 +0, 36, 36, 1, 303828, 4a0ab1bbea88697950bbafe566a03b52 +0, 37, 37, 1, 303860, 6d2073d28e226286e1e78df92bc27154 +0, 38, 38, 1, 303884, 74c43f24d636de3fd6afd1d0ab098e57 +0, 39, 39, 1, 303876, 329a1d1558ffc42b7cdb1f141e042431 +0, 40, 40, 1, 303912, 6b1f3c35f28ab1182354b33ea9e37331 +0, 41, 41, 1, 303856, ec00db5b019a3f72c3fc934d3811cad7 +0, 42, 42, 1, 303880, 6d291f829145c07f0002631b0e22a1f9 +0, 43, 43, 1, 303856, c438ae4db7f897c9e2a1bc6526bb43e1 +0, 44, 44, 1, 303828, d9e5870cf4598577e4ba0ac468ef25db +0, 45, 45, 1, 303936, 6c90dbca317295010024cc4ec70d3f87 +0, 46, 46, 1, 303940, 025d9173ff307f89c3edf43074a261e9 +0, 47, 47, 1, 303948, 48e7ab65fb9c7a35e4933a7658935726 +0, 48, 48, 1, 303944, 925eb3c42b865d0861ae0348136fc18c +0, 49, 49, 1, 303924, 83ae105d9d301ea900f004d274adf894 diff --git a/tests/ref/fate/utvideoenc_rgba_left b/tests/ref/fate/utvideoenc_rgba_left index eb3305d61a57f..11bde1e63f9c9 100644 --- a/tests/ref/fate/utvideoenc_rgba_left +++ b/tests/ref/fate/utvideoenc_rgba_left @@ -8,53 +8,53 @@ #dimensions 0: 352x288 #sar 0: 0/1 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 195260, a8fdb226460f210542e7aca6c12b0874 -0, 1, 1, 1, 195268, 45f098764ccba85dc641b7e401461c0a -0, 2, 2, 1, 195888, e922261672c7de46a302abad3a3fe450 -0, 3, 3, 1, 195316, f8febd5af0fed000fab2943cc649975f -0, 4, 4, 1, 194636, d90985ad8afd2f969afa842510085852 -0, 5, 5, 1, 195068, 909adb44bd049186a959f2803e641520 -0, 6, 6, 1, 194484, 547772233e653daccc6610fcb6369da7 -0, 7, 7, 1, 195224, aa82b75f6230b2e948abdfe36bce1150 -0, 8, 8, 1, 194356, d67fb1208532137252701ddcbf7bfc2e -0, 9, 9, 1, 195248, 7b08698d2a911fba5231c0fef0ded4c2 -0, 10, 10, 1, 194996, 570e7d9caec52975dec1c2a5dbf7cdef -0, 11, 11, 1, 195528, 7309c0531b942902c691781f2a6da1a1 -0, 12, 12, 1, 193832, 40954ceb87370cac3db5c8c2d7c001d1 -0, 13, 13, 1, 194852, 538382c377f0c6e9070ec0b8c5fb3e39 -0, 14, 14, 1, 195756, d002a80346f3460380abb794f2d56a62 -0, 15, 15, 1, 195384, 1a4f58b3c710f2fedaf746c281556b4c -0, 16, 16, 1, 195244, 218832dab1251e1dc852e6839a48b3fc -0, 17, 17, 1, 194788, a035acf428bd9565a4c3fec25dfc6f4f -0, 18, 18, 1, 194040, 6dbfeb949bdeeb055a4f7ebf78af9a85 -0, 19, 19, 1, 194320, 8b4aa3f6f05aa684d9e4adfa4cdce814 -0, 20, 20, 1, 193868, 98cd8b150784f6695f8dea163cecf286 -0, 21, 21, 1, 193832, 27a8db33014c4bc6a8da356c4b1a3e4f -0, 22, 22, 1, 194868, f1e1460dca9127197c0a40e659924616 -0, 23, 23, 1, 195236, a012f8548e92243334edcd7c8f57aa52 -0, 24, 24, 1, 195512, bf3d4e968d126231baa6618d3344ef81 -0, 25, 25, 1, 195504, adf4b49d8721f1b323fa518f2f0d4750 -0, 26, 26, 1, 195288, aa16dd087a73a9cadc5abfc0a46ccdd4 -0, 27, 27, 1, 194464, 2e3f07244999cbe949495b57adcabe69 -0, 28, 28, 1, 192512, 2d6ce0d29a929e0208e1578e95c9d388 -0, 29, 29, 1, 192460, 081d18cd138eead0cd4b25f54a7c7540 -0, 30, 30, 1, 193692, 546b6ad28b612c2f601c7d87b265ba95 -0, 31, 31, 1, 194496, b2b2ae3b1d67e332295456e6c7bdd381 -0, 32, 32, 1, 194360, 0837b122d85abc4d704d40629266c58d -0, 33, 33, 1, 195912, b7a4bbe436d63394cee70d40e8a8a4cf -0, 34, 34, 1, 195556, 1b9a3eb6cda9bbd44bbdd0dc26a74252 -0, 35, 35, 1, 195284, f28d780d43fa6979379dd21fcb12e906 -0, 36, 36, 1, 194268, 5508989dad06fa05ee4054e759cdfd4b -0, 37, 37, 1, 194460, cb65a0e97c03b2fbe69caa6ac1660070 -0, 38, 38, 1, 192708, 4125ee86cf4b8ca6d891c176662e584f -0, 39, 39, 1, 193032, 096ee24b3e35049480e28171693fbd85 -0, 40, 40, 1, 193160, c01aef63b8bc792d08355ce6d68affee -0, 41, 41, 1, 193524, 57af47b7bfe132cf58eab2807996b3fe -0, 42, 42, 1, 194120, 9a4e2d72f4526815b253b3acce2dd49c -0, 43, 43, 1, 194232, e575508ffbd2a53871e817cd8947e2d2 -0, 44, 44, 1, 193744, 95d8eefbfbf5a7354ecbf35835243e44 -0, 45, 45, 1, 191748, de2eedebb28491e59700300635af1f90 -0, 46, 46, 1, 191128, 652670f6881419be5068f2de6ac2d91e -0, 47, 47, 1, 191704, 070f46dc278230528aa6b40256a6d891 -0, 48, 48, 1, 191584, e4b76fcf344e125729c339e360a14b15 -0, 49, 49, 1, 191444, 6a33b374a8b48549094a24543d81d999 +0, 0, 0, 1, 210764, 7c17cd8382580fcfd6dac1ddaa644c8d +0, 1, 1, 1, 210772, 4c6bcde52e58d800927620df9e0e03b8 +0, 2, 2, 1, 211564, c0754e5c821ae0c0ca0bae78ad8fe1aa +0, 3, 3, 1, 210032, 6ea988397d00f553c6e5ddbca7a08af9 +0, 4, 4, 1, 209168, c2d1fcee61bfdb5e3925aca342550ae5 +0, 5, 5, 1, 210284, dc92cc07ac1211e664a24c701c410e0e +0, 6, 6, 1, 210184, 0977e253355bff82f0efd330e94cec6c +0, 7, 7, 1, 210136, d81c28cfef7dd47abf2ac951b6a948e7 +0, 8, 8, 1, 210016, d378efd0efe103407afa8b8f45d17e24 +0, 9, 9, 1, 210624, 1a7e4a4c7b4ccbd10b9238b22dbc953b +0, 10, 10, 1, 210388, 607fdb29b0bf5846cbbb776459840401 +0, 11, 11, 1, 209956, c4c4c18b83db1983b1d9268024027025 +0, 12, 12, 1, 208064, f1a73d7fe1dfdeb33758c9d7c61fa81b +0, 13, 13, 1, 209728, ce7b81e19d940ebddeef93e281fed00d +0, 14, 14, 1, 211640, 0d6929d8d034f8accd00f58b887073f5 +0, 15, 15, 1, 210932, b895f81c00f959868e24944ee816e0df +0, 16, 16, 1, 210500, c43494420a45bb8fb0a907d3169d30b7 +0, 17, 17, 1, 210328, 5e4d72389e2733d8ce274f0c9a7cf7aa +0, 18, 18, 1, 209612, 59d368acc1ea2c0f28ed0787fe5bad4a +0, 19, 19, 1, 209716, 77a331effc0bb544ef1445fd5c42cfe2 +0, 20, 20, 1, 208912, 1de694210d8e781ce8ea29add190ad06 +0, 21, 21, 1, 209052, b48927d6e1658b5df335c34bf0fc0dc9 +0, 22, 22, 1, 209552, 1c00ad79bcf1efdb633baa040f5e1400 +0, 23, 23, 1, 210460, 755c6daf2681ba0aed4e4c962faa288c +0, 24, 24, 1, 211136, e6a5687e05a70fc7c741f2ef7afb93b9 +0, 25, 25, 1, 210444, 6fe3ec5657f092b009a7bcc4815fc5b3 +0, 26, 26, 1, 209764, 19bc9792b30711fb7276a9f74d423c3e +0, 27, 27, 1, 209328, 0144894411a4c5f14c66a393a46bb3b4 +0, 28, 28, 1, 207152, 61bbd2676caf8fbe6582274fe8add09d +0, 29, 29, 1, 207360, 9663a6d131b029c9ad7469d67a381823 +0, 30, 30, 1, 208608, a0908484dfeead74fb351bb1ba3b514a +0, 31, 31, 1, 209284, 00dda733e216eb968cfdf97f6138294d +0, 32, 32, 1, 209400, 7f7e4d3546ab89ba5eaed835a2fabf64 +0, 33, 33, 1, 211120, 3b281fadbc1eed3b4d0e6b14deb4a18f +0, 34, 34, 1, 210488, f3fb93f6504ffee9984574a7b6854d89 +0, 35, 35, 1, 209952, 1ccf5aa118c8cd51e099749289fdc374 +0, 36, 36, 1, 209140, 4e4c0f0a38608f1ff760a7ada9d44a6f +0, 37, 37, 1, 209380, dac76683c0ce9e1008fe1490dc1479bf +0, 38, 38, 1, 207004, e914b5454210fc6b4c39d22b7daf16da +0, 39, 39, 1, 206968, 0a9566c879a6897536ec094100f32fbf +0, 40, 40, 1, 207368, a644c2b3b8c89ec01b2b51576a5b09b5 +0, 41, 41, 1, 208628, 2ce6ca69d5f6e29641f5a907ffac9bb0 +0, 42, 42, 1, 208976, d3be7fe389e80df517eafd0c861947a2 +0, 43, 43, 1, 209316, c5148e0073cebd50d8f619d4875874dd +0, 44, 44, 1, 208356, 54e0082cdc1aa7fcbb8c655e94fbd410 +0, 45, 45, 1, 206620, 77ec6d3714a0dcbf0cdd5349df0951fc +0, 46, 46, 1, 205932, 7857acd2afd3169126a5428ddef97abd +0, 47, 47, 1, 206524, c903ec677106ec1f7f583bb813a1120a +0, 48, 48, 1, 206444, ea549da62a460b50811cb3f182fe5c19 +0, 49, 49, 1, 205460, 81d823633491b13a31dfdbc5f33d79f4 diff --git a/tests/ref/fate/utvideoenc_rgba_median b/tests/ref/fate/utvideoenc_rgba_median index 0cdab8d41af17..a2118c276f3d3 100644 --- a/tests/ref/fate/utvideoenc_rgba_median +++ b/tests/ref/fate/utvideoenc_rgba_median @@ -8,53 +8,53 @@ #dimensions 0: 352x288 #sar 0: 0/1 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 195092, d32d5a3dc88b9aef0826b565ee5dfbc6 -0, 1, 1, 1, 195036, ea13e3522d1f3aeddd47117c91eccc55 -0, 2, 2, 1, 196040, 21c2c9abe791bed2a9bf02e539caa787 -0, 3, 3, 1, 195252, 58d5e081127f246f711f5b8ee1c760ff -0, 4, 4, 1, 194852, 8ceb3824ec628a73e1c08e498f369484 -0, 5, 5, 1, 195356, 30ea64094f29d670e2ff8f43b50578d6 -0, 6, 6, 1, 195180, 08b406b9f3063a54681d7195fb53e953 -0, 7, 7, 1, 194808, e28c43ef3aef174f0f9b9d7a702ca747 -0, 8, 8, 1, 195036, 66247b40b0def9373bf6fdda9ef832f7 -0, 9, 9, 1, 195472, efa8a624d6b0fa69e0c1c746baed0b33 -0, 10, 10, 1, 195052, fdfc784aed661cb76bc5b3ef1863bd89 -0, 11, 11, 1, 195068, 040ad503d18a36d4f1cdaec64998138a -0, 12, 12, 1, 194228, 1cd168427d022825a801b232cb23ca12 -0, 13, 13, 1, 195068, e4082f833d3bf75af24e1bb5f06d94fe -0, 14, 14, 1, 195344, 19638340e93d4f1f7099deda34d28e3f -0, 15, 15, 1, 195664, 001a801c5c5ceb197576c0f7b793850d -0, 16, 16, 1, 194876, 9550b3cf6133997bf7557483f346b036 -0, 17, 17, 1, 195164, eb7220caf48ab2605ec971ca1297a7ae -0, 18, 18, 1, 194444, a2ac812e6307a92ecd09d4282367a9d4 -0, 19, 19, 1, 194356, ee4d250226ab2a34cef0e3ed8920f7b2 -0, 20, 20, 1, 193696, 4bff0fc871969d17ad1f7391bbd543b2 -0, 21, 21, 1, 194004, 080e2a91fe768fd1725a8400bc6a1331 -0, 22, 22, 1, 194092, 5b9d65275695372e1f6b9c0a23f1ffa0 -0, 23, 23, 1, 195088, a4060bf595c877476a5952b335526d57 -0, 24, 24, 1, 195192, 17b55735834f291ecae399c317007d2c -0, 25, 25, 1, 194908, fc78d797bd5740f4fec8f3d34bc2ff1b -0, 26, 26, 1, 194764, d229a9e4d1c782504cad617d2b00802b -0, 27, 27, 1, 194356, f987a587cb9fdcd04e36d9382c4d9139 -0, 28, 28, 1, 193564, bdfa512e3a0a46aabf289c22dbaee0b9 -0, 29, 29, 1, 193556, 341708f3181ba4b37114d6dbffc65e63 -0, 30, 30, 1, 193956, f97693469ae6f49c3995794d00430c4a -0, 31, 31, 1, 194776, 970c96fe0f733683ce4f2b478af21b88 -0, 32, 32, 1, 194644, 8a96248e2821040e4d0d6d32d0a4f1a9 -0, 33, 33, 1, 194940, 70a462d8de0da8b5718bf8fb8034fa38 -0, 34, 34, 1, 194732, 2fb3437abbc0a85b6c46e1b1edd922c9 -0, 35, 35, 1, 194772, 0a0f54e266438e1a840247e1af2fb1f1 -0, 36, 36, 1, 194780, c4d516a459523b1c150d8aad1d5e3a6d -0, 37, 37, 1, 194908, e09db67196513400dd55397a525b73c2 -0, 38, 38, 1, 194148, f3cc9fc8597f8806fbc2a0c13af5b9ba -0, 39, 39, 1, 194168, 2bb82f80c239984fe7c1091ab6afb332 -0, 40, 40, 1, 193604, 6fd128240c540a0655e8f27ff6a50ee9 -0, 41, 41, 1, 194256, 9b49275154b4538abdebbddffe010105 -0, 42, 42, 1, 193912, 6acff798f9cca91347e36ee1ea86183c -0, 43, 43, 1, 194136, f24ca78d9b813ab8bfc720bad2682e7b -0, 44, 44, 1, 193652, d7d927faf59a3b82bd1cce418c13c430 -0, 45, 45, 1, 192960, 8a813fce1d21dd4ad474d06d890a3de5 -0, 46, 46, 1, 192636, 6bbe157ec4f799cfd47a69c5a5cbb0fc -0, 47, 47, 1, 192580, 1c17bf08a3928533a0036bda1fb08ecb -0, 48, 48, 1, 192356, a5b34ac48c82e79ff827f72dddbfc6b0 -0, 49, 49, 1, 191912, afceb467ddffd9697c9566c43f2576f9 +0, 0, 0, 1, 207164, 91bd0a04c522e4a449a2b2729cceb273 +0, 1, 1, 1, 207188, 8a9a23c32503fe30df47a598d319591e +0, 2, 2, 1, 207980, fac02289d860c485b09053119a259772 +0, 3, 3, 1, 206944, bc0251f0a3ad5881cb402d1d071cbfe8 +0, 4, 4, 1, 206200, e3b811ea58b790b171b75c9af46a3637 +0, 5, 5, 1, 207100, 076ca542190996d4ff4380bfff1b8707 +0, 6, 6, 1, 207172, 87d8540012df5c62ffcec97ac4255e44 +0, 7, 7, 1, 206444, 8a4a787dd73b93653ab69622b3fcaa6d +0, 8, 8, 1, 206884, e4ce5916ecee62387a44257f9f7e309f +0, 9, 9, 1, 207632, 67f343e24f47b1eddb47e59831752aab +0, 10, 10, 1, 206916, 6a1d003a2b3c10bd87d5b71a0ecb6fae +0, 11, 11, 1, 206572, 8939adde46e92bf02be301590de578ae +0, 12, 12, 1, 205832, ac36ce0cc201b89aa85aea9f8f85b654 +0, 13, 13, 1, 206712, 1d85faa22ef18e060354d2e2931f78f3 +0, 14, 14, 1, 207496, 2459b868050730ba3c3152443f119e59 +0, 15, 15, 1, 207788, 27616d7494e570814378a35fd72b3d4a +0, 16, 16, 1, 206988, 4f0daddba744ae0ebeea8b55ebc6778b +0, 17, 17, 1, 207056, e2340667064a25a75f67e261fe96baf7 +0, 18, 18, 1, 206440, d487795c5f4a3f338cebfd36b264a760 +0, 19, 19, 1, 206344, 0cd1a4c459402e82d7c89a131d6f75fe +0, 20, 20, 1, 205404, 52ea62992efacc4bf4234507752cd4ed +0, 21, 21, 1, 205776, 7712e82b94fd155c1e0dfec1db19a298 +0, 22, 22, 1, 205600, ec081ebb4e12f35aa47e673c5cd8c858 +0, 23, 23, 1, 207040, 637d7b20ab169db4671d76abc986c20d +0, 24, 24, 1, 207484, a776de1269ad564e1dc21ead94dcc71e +0, 25, 25, 1, 206792, 6aaa68388fb12b2e70eb542819902a97 +0, 26, 26, 1, 206384, b4c4d079d7c75b03e2d3915a8676a64d +0, 27, 27, 1, 206296, 521647a00535f63c241b54699b5d803a +0, 28, 28, 1, 204996, 892f0c216d04dfa120576c0cbbbdb0a2 +0, 29, 29, 1, 205396, fa1b2301c765bb1ca1c85828918462b9 +0, 30, 30, 1, 205812, e40d8da60a07f19b43ab27a13928b87d +0, 31, 31, 1, 206604, 2a06b115a3a400a73ad06b69c90a0768 +0, 32, 32, 1, 206568, e6d367cc3d7bd17a6c470fe86591e56d +0, 33, 33, 1, 206908, 8d53fe57b1043562c50a2fd63fa2ebfa +0, 34, 34, 1, 206388, 3a5544a0a814dbba171d0384c91ea566 +0, 35, 35, 1, 206700, bfe43124bcbbaef9884893c32396f316 +0, 36, 36, 1, 206516, a93e303f30a9269c6d6b59882b668630 +0, 37, 37, 1, 206776, 3044d9c98555d3415fc75b085f8aab0a +0, 38, 38, 1, 205940, 870403f6326de73750a57692a288bc2d +0, 39, 39, 1, 205612, f97b94da7b565f67cb476c73c2196bb1 +0, 40, 40, 1, 205120, 78341e169158f97791ec9a88ee936048 +0, 41, 41, 1, 206132, 83d31e0b40f2850b0767fbd162b4aabd +0, 42, 42, 1, 205984, ba029595b56087c55f324a54cb5e20a6 +0, 43, 43, 1, 205964, d067932b507acda9020837ed271eb09e +0, 44, 44, 1, 205376, 62b45f4949405875f947cd6d5133b76d +0, 45, 45, 1, 204756, ec45bcef0601faff97d89f89bfede4f3 +0, 46, 46, 1, 204704, 59c9d309aa381e39f3b236d332ae516a +0, 47, 47, 1, 204652, c44f8fba96dfb305cdc797ddfa033899 +0, 48, 48, 1, 204460, d0116d06128babcf8ec55205ce89d46a +0, 49, 49, 1, 203624, bbd3523ac263c622541aa67825601fd2 diff --git a/tests/ref/fate/utvideoenc_rgba_none b/tests/ref/fate/utvideoenc_rgba_none index 65f07289d117d..f388c9101d91a 100644 --- a/tests/ref/fate/utvideoenc_rgba_none +++ b/tests/ref/fate/utvideoenc_rgba_none @@ -8,53 +8,53 @@ #dimensions 0: 352x288 #sar 0: 0/1 #stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 301284, 55e84c6e1f41e48f47dcefb63e3c1efd -0, 1, 1, 1, 301296, 12dab23dfd2c2d5b48bed2292b876688 -0, 2, 2, 1, 301072, cc2e2889403dcc5d8e36868f07918b9d -0, 3, 3, 1, 301136, 9813d60e613a3a14e639f9af0a5b1fe7 -0, 4, 4, 1, 301140, 58554bb6749e8bbd9476335ac1cb0076 -0, 5, 5, 1, 301164, 37a249286019761a4a3e498e977f9da1 -0, 6, 6, 1, 301168, f3aa11b419ec6f683ad906e7f7a36342 -0, 7, 7, 1, 301272, f489654640f0e42225815ea9c9681201 -0, 8, 8, 1, 301308, f10eb3c1d0324b59bd25c8bc6556aca0 -0, 9, 9, 1, 301268, 2163aa992afef5210d677953d81adb17 -0, 10, 10, 1, 301168, 684d19d14212615ebffa1748a9c552ed -0, 11, 11, 1, 301136, a5c47c30d12dbc679ce932a5988b32e5 -0, 12, 12, 1, 301272, 3a51dc37d7e5ecb4a8db948eade2e0fa -0, 13, 13, 1, 301188, f9f9ed41c233e791e6cd75a34e52edf8 -0, 14, 14, 1, 301096, 63bbfbee6f0fa6745e143dfae40ce7ff -0, 15, 15, 1, 301108, 1fb3340dd1804d27fb40aea6b073e9ce -0, 16, 16, 1, 301248, 476d27f29da8e74db696ff38e81743fc -0, 17, 17, 1, 301300, 84a7f5804a856b7ef640838320634568 -0, 18, 18, 1, 301424, f34006fb55745aac29e265e0362434bf -0, 19, 19, 1, 301456, d9207e54e261d184ddd02f3706e63103 -0, 20, 20, 1, 301408, 89b5a6804bad85025a6a3d23dc539426 -0, 21, 21, 1, 301404, 5987d22d6e3bf18cd2ebea98a1915f57 -0, 22, 22, 1, 301340, 43ff13bb237a7899ecb04fa7d27e94ab -0, 23, 23, 1, 301288, 01b3e148ed6b8a0d05ee628fb21fa4a5 -0, 24, 24, 1, 301360, aa7704007e3c437cfcad4fb83a69594a -0, 25, 25, 1, 301376, 4dea983f0b4a012ba6875aa857d02e91 -0, 26, 26, 1, 301312, e263f1cb0fb19b50751e9a214a4c9d81 -0, 27, 27, 1, 301460, 85ad441664c99c591d6dc427910faa19 -0, 28, 28, 1, 301380, 86ffe8273011763d800dbf6c89942a70 -0, 29, 29, 1, 301448, 500862ea62e1982325d653d4853dcbcd -0, 30, 30, 1, 301452, 91c4390a805e02d1924bd75946bc0b63 -0, 31, 31, 1, 301388, 4eb3040d65948355c4506ee8e8e041ca -0, 32, 32, 1, 301348, ece814a764470f1d80973743a7adaa4b -0, 33, 33, 1, 301324, 2ae0b9af5380c8f98087b90c646af813 -0, 34, 34, 1, 301224, d6a3ba0b543534bd7de9dd82107c468c -0, 35, 35, 1, 301384, 4f4919c1b2502c6e03ddaa83f4c03f15 -0, 36, 36, 1, 301460, b45189bc89e6583f4426c390622fa1fc -0, 37, 37, 1, 301456, db0c5e2bc705c825e554c2da54314746 -0, 38, 38, 1, 301520, 8d01037b2dcbba39d4746758fd53323c -0, 39, 39, 1, 301524, 0a78af44bf49520ae8830060e6011898 -0, 40, 40, 1, 301532, da9032ac97b76ec10f94d74ee878cf41 -0, 41, 41, 1, 301496, 9a22b2a9a3ad897406fc7c3137d41a3b -0, 42, 42, 1, 301572, a14a80ab416cf4a9a1ec24bfc72602a1 -0, 43, 43, 1, 301532, 71ea5a240540a2e08ced8ad78c1a0676 -0, 44, 44, 1, 301516, fffe101d036ed5afee9b6f86267c2a0c -0, 45, 45, 1, 301568, 58ea3a6edaee760d98eadb072fb30796 -0, 46, 46, 1, 301660, 9886e77f5df35d8bd164d598d0f87514 -0, 47, 47, 1, 301668, 1f326eb789974fc853e1db57115ef58b -0, 48, 48, 1, 301684, 08b2eb620b9a7be1bded4744cd4c88db -0, 49, 49, 1, 301668, bfcce1ce5f7c30230aae9a2d67fc8a70 +0, 0, 0, 1, 304028, e1687f63bd131ace3866b61881e8e9a1 +0, 1, 1, 1, 304024, 93067fdad1470b1c2f2fd4ae603a3afe +0, 2, 2, 1, 303932, 2fef08ce570f581373bd48b3a4773acb +0, 3, 3, 1, 303932, 8623d4635239deac16d56085edb8aec1 +0, 4, 4, 1, 303984, ef0a1be76f7c854e5f2724d7a6707f54 +0, 5, 5, 1, 303932, 0e57009f6e93c2e5ce80d6109d9a66f3 +0, 6, 6, 1, 303936, db988d8d6e9ee0383cfc69a201de62e2 +0, 7, 7, 1, 304024, 963e86c081fafed2f757c4aafc9186df +0, 8, 8, 1, 304032, e867c068706bff34a561a4b2c4622fd3 +0, 9, 9, 1, 303960, 0dd6d1cbe6a9fb07e3f3cb4a12c2821a +0, 10, 10, 1, 303944, 424612ce8850b378171ee8bfca5d91ce +0, 11, 11, 1, 303956, f26d5065818f98bbf97aae56fe07b057 +0, 12, 12, 1, 303980, dfd1a61b5a717805a06f19ee899c3917 +0, 13, 13, 1, 303936, 2223f98ac58078c49489811171c713e1 +0, 14, 14, 1, 303808, 6a63bd7cd4cafe5e64dc8dc46f9f3760 +0, 15, 15, 1, 303864, a355699c989795379d1ef2089c98e619 +0, 16, 16, 1, 304008, 07a0c41088846ed77fedc565cfeaeba7 +0, 17, 17, 1, 304000, dbb37a1af0bb534112aac9269b7d7c2c +0, 18, 18, 1, 304048, 3129997c9ba84a0c91ff9d1c48d12d7e +0, 19, 19, 1, 304068, 620b4c964daca105cd1b6bf8d55e86ae +0, 20, 20, 1, 304068, bafaf53530f76d525eafb75a3866b5e7 +0, 21, 21, 1, 304092, 678138b93f07ef8f30ad373499a9caa3 +0, 22, 22, 1, 304060, 4bf8174ff9ee62c13bde29ad5bba3fc9 +0, 23, 23, 1, 303976, e6e926057f49e69e2ea8e679871e449a +0, 24, 24, 1, 304040, f81ba4d36df7e8967a16e7de5c7a023b +0, 25, 25, 1, 304084, a5a63a22e6bc3a54bfbd60852ca9da60 +0, 26, 26, 1, 304056, df9bd50b9dd7437afb3671c99e2e1746 +0, 27, 27, 1, 304076, 785a2a7de44e83f1111e66165b3d0765 +0, 28, 28, 1, 304132, ab01bacd7aee91ab80b30a48f54ec4d7 +0, 29, 29, 1, 304160, 4893296140e7ee6f2d194bc279f928f3 +0, 30, 30, 1, 304136, 6046c7516a5e8db2f4dd3b1286ad46c0 +0, 31, 31, 1, 304088, e6dbc1ec86cb678bab6a1ca0e93888d0 +0, 32, 32, 1, 303980, 66db98674c107af297a3de01c047ebce +0, 33, 33, 1, 303964, e2ce0a2ee5ba8de50960873a8405c001 +0, 34, 34, 1, 303900, 7ae96a39e66e0abe63e298f45477c0ec +0, 35, 35, 1, 304040, d5fc8f7809470bc40935285d4ed69a80 +0, 36, 36, 1, 304088, efae0966a7e421c3107016df862b0429 +0, 37, 37, 1, 304120, c6a3bf8991bf2b559f27d5ea9ae76d08 +0, 38, 38, 1, 304144, 588ac89c403c5d3ca9289fbd339fdb74 +0, 39, 39, 1, 304136, a3824537484dd2fc25dde9ec2974068c +0, 40, 40, 1, 304172, e1a024aa9faba0ee0cb98e41cef254c9 +0, 41, 41, 1, 304116, c26c4c053d53b70c97cbf989cb51a15d +0, 42, 42, 1, 304140, 4d13ee2a3b32ba3f080fffa7ca2db6e6 +0, 43, 43, 1, 304116, fb02b57f9a9fafa7bc6d2a35a68548fc +0, 44, 44, 1, 304088, 6daa494c1ed11c9ea8da6c83eb473ce7 +0, 45, 45, 1, 304196, 8886953ff026efef28f4af12ce5239b6 +0, 46, 46, 1, 304200, 51ff2c8552b8b044a1a183330a188d62 +0, 47, 47, 1, 304208, 72fcd3dbf45284bb434ad3660f8a1ddf +0, 48, 48, 1, 304204, 1d5e2170963d70acea2ad01e1486d490 +0, 49, 49, 1, 304184, 6eec23c3d4402f7a0ab4de16fde86462 From 500a9bb5ba94201dd53bd714794fc33e5ffe3773 Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Wed, 27 Dec 2017 11:11:23 -0500 Subject: [PATCH 1523/2557] lavc/options: Remove unneeded header Signed-off-by: Derek Buitenhuis --- libavcodec/options.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/options.c b/libavcodec/options.c index 82e12179a6b5c..41b60521cc444 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -30,7 +30,6 @@ #include "libavutil/internal.h" #include "libavutil/mem.h" #include "libavutil/opt.h" -#include /* FLT_MIN, FLT_MAX */ #include FF_DISABLE_DEPRECATION_WARNINGS From 6470abc740367cc881c181db866891f8dd1d342f Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Mon, 1 Jan 2018 11:28:36 -0500 Subject: [PATCH 1524/2557] vf_paletteuse: Add error checking to apply_palette This fixes a segfault caused by passing NULL to ff_filter_frame when an error occurs. Signed-off-by: Derek Buitenhuis --- libavfilter/vf_paletteuse.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 1980907e70eca..961b55726dcbd 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -894,9 +894,9 @@ static void set_processing_window(enum diff_mode diff_mode, *hp = height; } -static AVFrame *apply_palette(AVFilterLink *inlink, AVFrame *in) +static int apply_palette(AVFilterLink *inlink, AVFrame *in, AVFrame **outf) { - int x, y, w, h; + int x, y, w, h, ret; AVFilterContext *ctx = inlink->dst; PaletteUseContext *s = ctx->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; @@ -904,7 +904,8 @@ static AVFrame *apply_palette(AVFilterLink *inlink, AVFrame *in) AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); - return NULL; + *outf = NULL; + return AVERROR(ENOMEM); } av_frame_copy_props(out, in); @@ -918,21 +919,25 @@ static AVFrame *apply_palette(AVFilterLink *inlink, AVFrame *in) av_frame_make_writable(s->last_in) < 0) { av_frame_free(&in); av_frame_free(&out); - return NULL; + *outf = NULL; + return AVERROR(ENOMEM); } ff_dlog(ctx, "%dx%d rect: (%d;%d) -> (%d,%d) [area:%dx%d]\n", w, h, x, y, x+w, y+h, in->width, in->height); - if (s->set_frame(s, out, in, x, y, w, h) < 0) { + ret = s->set_frame(s, out, in, x, y, w, h); + if (ret < 0) { av_frame_free(&out); - return NULL; + *outf = NULL; + return ret; } memcpy(out->data[1], s->palette, AVPALETTE_SIZE); if (s->calc_mean_err) debug_mean_error(s, in, out, inlink->frame_count_out); av_frame_free(&in); - return out; + *outf = out; + return 0; } static int config_output(AVFilterLink *outlink) @@ -1011,7 +1016,7 @@ static int load_apply_palette(FFFrameSync *fs) AVFilterContext *ctx = fs->parent; AVFilterLink *inlink = ctx->inputs[0]; PaletteUseContext *s = ctx->priv; - AVFrame *master, *second, *out; + AVFrame *master, *second, *out = NULL; int ret; // writable for error diffusal dithering @@ -1025,7 +1030,9 @@ static int load_apply_palette(FFFrameSync *fs) if (!s->palette_loaded) { load_palette(s, second); } - out = apply_palette(inlink, master); + ret = apply_palette(inlink, master, &out); + if (ret < 0) + goto error; return ff_filter_frame(ctx->outputs[0], out); error: From 631fa0432be8968e0fd372595749b918224946df Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Mon, 1 Jan 2018 11:28:37 -0500 Subject: [PATCH 1525/2557] vf_paletteuse: Don't free the second frame from ff_framesync_dualinput_get_writable on error This fixes a double free in he error case. Signed-off-by: Derek Buitenhuis --- libavfilter/vf_paletteuse.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 961b55726dcbd..604a8af29c655 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -1037,7 +1037,6 @@ static int load_apply_palette(FFFrameSync *fs) error: av_frame_free(&master); - av_frame_free(&second); return ret; } From 09b24a807ad23b4fec25049775075cc63c0c1fa3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 27 Dec 2017 18:51:23 +0100 Subject: [PATCH 1526/2557] avfilter: add entropy filter Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/filters.texi | 14 +++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- libavfilter/vf_entropy.c | 206 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_entropy.c diff --git a/Changelog b/Changelog index 720d478f002b9..d1620e0df46bb 100644 --- a/Changelog +++ b/Changelog @@ -31,6 +31,7 @@ version : - Dropped support for building for Windows XP. The minimum supported Windows version is Windows Vista. - deconvolve video filter +- entropy video filter version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index f651f1234d77b..477f8334496d4 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -8220,6 +8220,20 @@ Set pal8 output pixel format. This option does not work with codebook length greater than 256. @end table +@section entropy + +Measure graylevel entropy in histogram of color channels of video frames. + +It accepts the following parameters: + +@table @option +@item mode +Can be either @var{normal} or @var{diff}. Default is @var{normal}. + +@var{diff} mode measures entropy of histogram delta values, absolute differences +between neighbour histogram values. +@end table + @section fade Apply a fade-in/out effect to the input video. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 8bde542163e08..7d9f2330ca992 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -184,6 +184,7 @@ OBJS-$(CONFIG_DRAWGRID_FILTER) += vf_drawbox.o OBJS-$(CONFIG_DRAWTEXT_FILTER) += vf_drawtext.o OBJS-$(CONFIG_EDGEDETECT_FILTER) += vf_edgedetect.o OBJS-$(CONFIG_ELBG_FILTER) += vf_elbg.o +OBJS-$(CONFIG_ENTROPY_FILTER) += vf_entropy.o OBJS-$(CONFIG_EQ_FILTER) += vf_eq.o OBJS-$(CONFIG_EROSION_FILTER) += vf_neighbor.o OBJS-$(CONFIG_EXTRACTPLANES_FILTER) += vf_extractplanes.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 67c073091fb7d..7635a8a5831b0 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -194,6 +194,7 @@ static void register_all(void) REGISTER_FILTER(DRAWTEXT, drawtext, vf); REGISTER_FILTER(EDGEDETECT, edgedetect, vf); REGISTER_FILTER(ELBG, elbg, vf); + REGISTER_FILTER(ENTROPY, entropy, vf); REGISTER_FILTER(EQ, eq, vf); REGISTER_FILTER(EROSION, erosion, vf); REGISTER_FILTER(EXTRACTPLANES, extractplanes, vf); diff --git a/libavfilter/version.h b/libavfilter/version.h index 85bc6d35f8ffe..c41dfc178eb40 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 8 +#define LIBAVFILTER_VERSION_MINOR 9 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_entropy.c b/libavfilter/vf_entropy.c new file mode 100644 index 0000000000000..e6002ce27a27e --- /dev/null +++ b/libavfilter/vf_entropy.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2017 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "drawutils.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct EntropyContext { + const AVClass *class; + + int mode; + + int nb_planes; + int planeheight[4]; + int planewidth[4]; + int depth; + int is_rgb; + uint8_t rgba_map[4]; + char planenames[4]; + int64_t *histogram; +} EntropyContext; + +#define OFFSET(x) offsetof(EntropyContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +static const AVOption entropy_options[] = { + { "mode", "set kind of histogram entropy measurement", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "mode" }, + { "normal", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, + { "diff", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(entropy); + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pixfmts[] = { + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9, + AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV420P16, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *formats = ff_make_format_list(pixfmts); + if (!formats) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, formats); +} + +static int config_input(AVFilterLink *inlink) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + AVFilterContext *ctx = inlink->dst; + EntropyContext *s = ctx->priv; + + s->nb_planes = desc->nb_components; + + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + + s->depth = desc->comp[0].depth; + s->is_rgb = ff_fill_rgba_map(s->rgba_map, inlink->format) >= 0; + + s->planenames[0] = s->is_rgb ? 'R' : 'Y'; + s->planenames[1] = s->is_rgb ? 'G' : 'U'; + s->planenames[2] = s->is_rgb ? 'B' : 'V'; + s->planenames[3] = 'A'; + + s->histogram = av_malloc_array(1 << s->depth, sizeof(*s->histogram)); + if (!s->histogram) + return AVERROR(ENOMEM); + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + EntropyContext *s = ctx->priv; + int plane, y, x; + + for (plane = 0; plane < s->nb_planes; plane++) { + int cidx = s->is_rgb ? s->rgba_map[plane] : plane; + const uint8_t *src8 = in->data[plane]; + const uint16_t *src16 = (const uint16_t *)in->data[plane]; + float total = s->planewidth[plane] * s->planeheight[plane]; + float entropy = 0; + char metabuf[128]; + char key[128]; + + memset(s->histogram, 0, (1 << s->depth) * sizeof(*s->histogram)); + + if (s->depth <= 8) { + for (y = 0; y < s->planeheight[plane]; y++) { + for (x = 0; x < s->planewidth[plane]; x++) { + s->histogram[src8[x]]++; + } + + src8 += in->linesize[plane]; + } + } else { + for (y = 0; y < s->planeheight[plane]; y++) { + for (x = 0; x < s->planewidth[plane]; x++) { + s->histogram[src16[x]]++; + } + + src16 += in->linesize[plane] / 2; + } + } + + for (y = 0; y < 1 << s->depth; y++) { + if (s->mode == 0) { + if (s->histogram[y]) { + float p = s->histogram[y] / total; + entropy += -log2(p) * p; + } + } else if (s->mode == 1) { + if (y && (s->histogram[y] - s->histogram[y - 1]) != 0) { + float p = FFABS(s->histogram[y] - s->histogram[y - 1]) / total; + entropy += -log2(p) * p; + } + } + } + + snprintf(key, sizeof(key), "lavfi.entropy.entropy.%s.%c", s->mode ? "diff" : "normal", s->planenames[cidx]); + snprintf(metabuf, sizeof(metabuf), "%f", entropy); + av_dict_set(&in->metadata, key, metabuf, 0); + snprintf(key, sizeof(key), "lavfi.entropy.normalized_entropy.%s.%c", s->mode ? "diff" : "normal", s->planenames[cidx]); + snprintf(metabuf, sizeof(metabuf), "%f", entropy / log2(1 << s->depth)); + av_dict_set(&in->metadata, key, metabuf, 0); + } + + return ff_filter_frame(outlink, in); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + EntropyContext *s = ctx->priv; + + av_freep(&s->histogram); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_entropy = { + .name = "entropy", + .description = NULL_IF_CONFIG_SMALL("Measure video frames entropy."), + .priv_size = sizeof(EntropyContext), + .uninit = uninit, + .query_formats = query_formats, + .inputs = inputs, + .outputs = outputs, + .priv_class = &entropy_class, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, +}; From 9ace76697ac1e43aa4da4c7333ec4a296907c336 Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Tue, 2 Jan 2018 14:50:59 +0100 Subject: [PATCH 1527/2557] lavfi/framesync: document frame ownership for dualinput. --- libavfilter/framesync.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavfilter/framesync.h b/libavfilter/framesync.h index 9fdc4d1ae2db0..abf3bf552b99c 100644 --- a/libavfilter/framesync.h +++ b/libavfilter/framesync.h @@ -286,6 +286,9 @@ int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent); * @param f0 used to return the main frame * @param f1 used to return the second frame, or NULL if disabled * @return >=0 for success or AVERROR code + * @note The frame returned in f0 belongs to the caller (get = 1 in + * ff_framesync_get_frame()) while the frame returned in f1 is still owned + * by the framesync structure. */ int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1); From 29b5f3115d9f217758bebd1d00e541aa3e739d2a Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Tue, 2 Jan 2018 14:51:18 +0100 Subject: [PATCH 1528/2557] lavfi/framesync: remove an invalid free. --- libavfilter/framesync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/framesync.c b/libavfilter/framesync.c index 82d715750c4bc..da12c58a618aa 100644 --- a/libavfilter/framesync.c +++ b/libavfilter/framesync.c @@ -406,7 +406,7 @@ int ff_framesync_dualinput_get_writable(FFFrameSync *fs, AVFrame **f0, AVFrame * ret = ff_inlink_make_frame_writable(fs->parent->inputs[0], f0); if (ret < 0) { av_frame_free(f0); - av_frame_free(f1); + *f1 = NULL; return ret; } return 0; From 677701c6b319d2d3b95a27179fde6ec2a863bf72 Mon Sep 17 00:00:00 2001 From: Jiejun Zhang Date: Wed, 3 Jan 2018 12:54:20 +0800 Subject: [PATCH 1529/2557] lavc/audiotoolboxenc: fix noise in encoded audio This fixes #6940 Although undocumented, AudioToolbox seems to require the data supplied by the callback (i.e. ffat_encode_callback) being unchanged until the next time the callback is called. In the old implementation, the AVBuffer backing the frame is recycled after the frame is freed, and somebody else (maybe the decoder) will write into the AVBuffer and change the data. AudioToolbox then encodes some wrong data and noise is produced. Retaining a frame reference solves this problem. Signed-off-by: James Almer --- libavcodec/audiotoolboxenc.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libavcodec/audiotoolboxenc.c b/libavcodec/audiotoolboxenc.c index 71885d153001e..2c1891693e21c 100644 --- a/libavcodec/audiotoolboxenc.c +++ b/libavcodec/audiotoolboxenc.c @@ -48,6 +48,8 @@ typedef struct ATDecodeContext { AudioFrameQueue afq; int eof; int frame_size; + + AVFrame* encoding_frame; } ATDecodeContext; static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile) @@ -442,6 +444,10 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx) ff_af_queue_init(avctx, &at->afq); + at->encoding_frame = av_frame_alloc(); + if (!at->encoding_frame) + return AVERROR(ENOMEM); + return 0; } @@ -453,6 +459,7 @@ static OSStatus ffat_encode_callback(AudioConverterRef converter, UInt32 *nb_pac AVCodecContext *avctx = inctx; ATDecodeContext *at = avctx->priv_data; AVFrame *frame; + int ret; if (!at->frame_queue.available) { if (at->eof) { @@ -475,6 +482,13 @@ static OSStatus ffat_encode_callback(AudioConverterRef converter, UInt32 *nb_pac if (*nb_packets > frame->nb_samples) *nb_packets = frame->nb_samples; + av_frame_unref(at->encoding_frame); + ret = av_frame_ref(at->encoding_frame, frame); + if (ret < 0) { + *nb_packets = 0; + return ret; + } + ff_bufqueue_add(avctx, &at->used_frame_queue, frame); return 0; @@ -565,6 +579,7 @@ static av_cold int ffat_close_encoder(AVCodecContext *avctx) ff_bufqueue_discard_all(&at->frame_queue); ff_bufqueue_discard_all(&at->used_frame_queue); ff_af_queue_close(&at->afq); + av_frame_free(&at->encoding_frame); return 0; } From 88cbd25b193dddb852bc1921b733c5dde5fee2fe Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 3 Jan 2018 22:47:40 +0100 Subject: [PATCH 1530/2557] avfilter: pass outlink to ff_get_audio_buffer() This is more correct. Signed-off-by: Paul B Mahol --- libavfilter/af_acontrast.c | 2 +- libavfilter/af_adelay.c | 2 +- libavfilter/af_aecho.c | 2 +- libavfilter/af_aemphasis.c | 2 +- libavfilter/af_afade.c | 2 +- libavfilter/af_agate.c | 2 +- libavfilter/af_alimiter.c | 2 +- libavfilter/af_aphaser.c | 2 +- libavfilter/af_biquads.c | 2 +- libavfilter/af_bs2b.c | 2 +- libavfilter/af_chorus.c | 2 +- libavfilter/af_compand.c | 4 ++-- libavfilter/af_compensationdelay.c | 2 +- libavfilter/af_crossfeed.c | 2 +- libavfilter/af_earwax.c | 2 +- libavfilter/af_extrastereo.c | 2 +- libavfilter/af_flanger.c | 2 +- libavfilter/af_haas.c | 2 +- libavfilter/af_loudnorm.c | 2 +- libavfilter/af_replaygain.c | 2 +- libavfilter/af_rubberband.c | 4 ++-- libavfilter/af_sidechaincompress.c | 2 +- libavfilter/af_stereotools.c | 2 +- libavfilter/af_stereowiden.c | 2 +- libavfilter/af_tremolo.c | 2 +- libavfilter/af_vibrato.c | 2 +- libavfilter/af_volume.c | 2 +- 27 files changed, 29 insertions(+), 29 deletions(-) diff --git a/libavfilter/af_acontrast.c b/libavfilter/af_acontrast.c index 8b45bd5b2b0e0..e08053146e345 100644 --- a/libavfilter/af_acontrast.c +++ b/libavfilter/af_acontrast.c @@ -173,7 +173,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_adelay.c b/libavfilter/af_adelay.c index 983f089c21bcf..d6d81ba7d803f 100644 --- a/libavfilter/af_adelay.c +++ b/libavfilter/af_adelay.c @@ -192,7 +192,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) if (ctx->is_disabled || !s->delays) return ff_filter_frame(ctx->outputs[0], frame); - out_frame = ff_get_audio_buffer(inlink, frame->nb_samples); + out_frame = ff_get_audio_buffer(ctx->outputs[0], frame->nb_samples); if (!out_frame) { av_frame_free(&frame); return AVERROR(ENOMEM); diff --git a/libavfilter/af_aecho.c b/libavfilter/af_aecho.c index cfaea3de43057..b9ac18d3a462b 100644 --- a/libavfilter/af_aecho.c +++ b/libavfilter/af_aecho.c @@ -279,7 +279,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) if (av_frame_is_writable(frame)) { out_frame = frame; } else { - out_frame = ff_get_audio_buffer(inlink, frame->nb_samples); + out_frame = ff_get_audio_buffer(ctx->outputs[0], frame->nb_samples); if (!out_frame) { av_frame_free(&frame); return AVERROR(ENOMEM); diff --git a/libavfilter/af_aemphasis.c b/libavfilter/af_aemphasis.c index a5b8e3058a2e4..e1fa93affcaf4 100644 --- a/libavfilter/af_aemphasis.c +++ b/libavfilter/af_aemphasis.c @@ -96,7 +96,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_afade.c b/libavfilter/af_afade.c index 7ad124e887bd5..4d0b31eac7536 100644 --- a/libavfilter/af_afade.c +++ b/libavfilter/af_afade.c @@ -282,7 +282,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) if (av_frame_is_writable(buf)) { out_buf = buf; } else { - out_buf = ff_get_audio_buffer(inlink, nb_samples); + out_buf = ff_get_audio_buffer(outlink, nb_samples); if (!out_buf) return AVERROR(ENOMEM); av_frame_copy_props(out_buf, buf); diff --git a/libavfilter/af_agate.c b/libavfilter/af_agate.c index 086a2f9cb93a4..ba96863a688a5 100644 --- a/libavfilter/af_agate.c +++ b/libavfilter/af_agate.c @@ -214,7 +214,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_alimiter.c b/libavfilter/af_alimiter.c index 46211a710ada8..0fc8e6baa3fb7 100644 --- a/libavfilter/af_alimiter.c +++ b/libavfilter/af_alimiter.c @@ -135,7 +135,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_aphaser.c b/libavfilter/af_aphaser.c index dcffc216dd3dc..bf46cc8fab775 100644 --- a/libavfilter/af_aphaser.c +++ b/libavfilter/af_aphaser.c @@ -247,7 +247,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inbuf) if (av_frame_is_writable(inbuf)) { outbuf = inbuf; } else { - outbuf = ff_get_audio_buffer(inlink, inbuf->nb_samples); + outbuf = ff_get_audio_buffer(outlink, inbuf->nb_samples); if (!outbuf) { av_frame_free(&inbuf); return AVERROR(ENOMEM); diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index 1d72cd57518ab..b0772b9fdc7bf 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -417,7 +417,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) if (av_frame_is_writable(buf)) { out_buf = buf; } else { - out_buf = ff_get_audio_buffer(inlink, nb_samples); + out_buf = ff_get_audio_buffer(outlink, nb_samples); if (!out_buf) { av_frame_free(&buf); return AVERROR(ENOMEM); diff --git a/libavfilter/af_bs2b.c b/libavfilter/af_bs2b.c index 0942d540a6867..c01b983cd3668 100644 --- a/libavfilter/af_bs2b.c +++ b/libavfilter/af_bs2b.c @@ -135,7 +135,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) if (av_frame_is_writable(frame)) { out_frame = frame; } else { - out_frame = ff_get_audio_buffer(inlink, frame->nb_samples); + out_frame = ff_get_audio_buffer(outlink, frame->nb_samples); if (!out_frame) { av_frame_free(&frame); return AVERROR(ENOMEM); diff --git a/libavfilter/af_chorus.c b/libavfilter/af_chorus.c index 87c82900970ba..29c47ab14a6c8 100644 --- a/libavfilter/af_chorus.c +++ b/libavfilter/af_chorus.c @@ -247,7 +247,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) if (av_frame_is_writable(frame)) { out_frame = frame; } else { - out_frame = ff_get_audio_buffer(inlink, frame->nb_samples); + out_frame = ff_get_audio_buffer(ctx->outputs[0], frame->nb_samples); if (!out_frame) { av_frame_free(&frame); return AVERROR(ENOMEM); diff --git a/libavfilter/af_compand.c b/libavfilter/af_compand.c index 8589b1ef094b5..c138f0b1d8f97 100644 --- a/libavfilter/af_compand.c +++ b/libavfilter/af_compand.c @@ -185,7 +185,7 @@ static int compand_nodelay(AVFilterContext *ctx, AVFrame *frame) if (av_frame_is_writable(frame)) { out_frame = frame; } else { - out_frame = ff_get_audio_buffer(inlink, nb_samples); + out_frame = ff_get_audio_buffer(ctx->outputs[0], nb_samples); if (!out_frame) { av_frame_free(&frame); return AVERROR(ENOMEM); @@ -249,7 +249,7 @@ static int compand_delay(AVFilterContext *ctx, AVFrame *frame) if (count >= s->delay_samples) { if (!out_frame) { - out_frame = ff_get_audio_buffer(inlink, nb_samples - i); + out_frame = ff_get_audio_buffer(ctx->outputs[0], nb_samples - i); if (!out_frame) { av_frame_free(&frame); return AVERROR(ENOMEM); diff --git a/libavfilter/af_compensationdelay.c b/libavfilter/af_compensationdelay.c index d5a3484317163..05285cd29757b 100644 --- a/libavfilter/af_compensationdelay.c +++ b/libavfilter/af_compensationdelay.c @@ -131,7 +131,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFrame *out; int n, ch; - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(ctx->outputs[0], in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_crossfeed.c b/libavfilter/af_crossfeed.c index d3def92fb39a9..a0af280432600 100644 --- a/libavfilter/af_crossfeed.c +++ b/libavfilter/af_crossfeed.c @@ -99,7 +99,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_earwax.c b/libavfilter/af_earwax.c index 7b880c86c6e20..cdd2b4fc49c50 100644 --- a/libavfilter/af_earwax.c +++ b/libavfilter/af_earwax.c @@ -115,7 +115,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) { AVFilterLink *outlink = inlink->dst->outputs[0]; int16_t *taps, *endin, *in, *out; - AVFrame *outsamples = ff_get_audio_buffer(inlink, insamples->nb_samples); + AVFrame *outsamples = ff_get_audio_buffer(outlink, insamples->nb_samples); int len; if (!outsamples) { diff --git a/libavfilter/af_extrastereo.c b/libavfilter/af_extrastereo.c index b07c006f2c5ce..13c6f4777679e 100644 --- a/libavfilter/af_extrastereo.c +++ b/libavfilter/af_extrastereo.c @@ -71,7 +71,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_flanger.c b/libavfilter/af_flanger.c index a92367c97a391..b7497a12eda7e 100644 --- a/libavfilter/af_flanger.c +++ b/libavfilter/af_flanger.c @@ -148,7 +148,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) if (av_frame_is_writable(frame)) { out_frame = frame; } else { - out_frame = ff_get_audio_buffer(inlink, frame->nb_samples); + out_frame = ff_get_audio_buffer(ctx->outputs[0], frame->nb_samples); if (!out_frame) { av_frame_free(&frame); return AVERROR(ENOMEM); diff --git a/libavfilter/af_haas.c b/libavfilter/af_haas.c index 691c251f54e08..0cfc93a7d1f24 100644 --- a/libavfilter/af_haas.c +++ b/libavfilter/af_haas.c @@ -144,7 +144,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_loudnorm.c b/libavfilter/af_loudnorm.c index e3e815e2723fc..a7f11cbe6e22b 100644 --- a/libavfilter/af_loudnorm.c +++ b/libavfilter/af_loudnorm.c @@ -423,7 +423,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_replaygain.c b/libavfilter/af_replaygain.c index c8f6f9666d6ce..97617346edfed 100644 --- a/libavfilter/af_replaygain.c +++ b/libavfilter/af_replaygain.c @@ -554,7 +554,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) uint32_t level; AVFrame *out; - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_rubberband.c b/libavfilter/af_rubberband.c index ded25449ddfe7..ea6f4ff2c9c85 100644 --- a/libavfilter/af_rubberband.c +++ b/libavfilter/af_rubberband.c @@ -128,7 +128,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) nb_samples = rubberband_available(s->rbs); if (nb_samples > 0) { - out = ff_get_audio_buffer(inlink, nb_samples); + out = ff_get_audio_buffer(outlink, nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); @@ -187,7 +187,7 @@ static int request_frame(AVFilterLink *outlink) nb_samples = rubberband_available(s->rbs); if (nb_samples > 0) { - out = ff_get_audio_buffer(inlink, nb_samples); + out = ff_get_audio_buffer(outlink, nb_samples); if (!out) return AVERROR(ENOMEM); out->pts = av_rescale_q(s->nb_samples_out, diff --git a/libavfilter/af_sidechaincompress.c b/libavfilter/af_sidechaincompress.c index 3c6458cd63883..888049eaf0e0f 100644 --- a/libavfilter/af_sidechaincompress.c +++ b/libavfilter/af_sidechaincompress.c @@ -367,7 +367,7 @@ static int acompressor_filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_stereotools.c b/libavfilter/af_stereotools.c index a5e0b427f1e32..7e529783d5950 100644 --- a/libavfilter/af_stereotools.c +++ b/libavfilter/af_stereotools.c @@ -166,7 +166,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_stereowiden.c b/libavfilter/af_stereowiden.c index 24146ff1df006..ef16fcec73b8d 100644 --- a/libavfilter/af_stereowiden.c +++ b/libavfilter/af_stereowiden.c @@ -98,7 +98,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_tremolo.c b/libavfilter/af_tremolo.c index 572e9e3b56082..8cbc79892d123 100644 --- a/libavfilter/af_tremolo.c +++ b/libavfilter/af_tremolo.c @@ -57,7 +57,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_vibrato.c b/libavfilter/af_vibrato.c index c7691f2f2a8ee..22bbab6239b95 100644 --- a/libavfilter/af_vibrato.c +++ b/libavfilter/af_vibrato.c @@ -63,7 +63,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (av_frame_is_writable(in)) { out = in; } else { - out = ff_get_audio_buffer(inlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c index 3d76f12f2cc66..b106ed8cf4aa8 100644 --- a/libavfilter/af_volume.c +++ b/libavfilter/af_volume.c @@ -410,7 +410,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) && (vol->precision != PRECISION_FIXED || vol->volume_i > 0)) { out_buf = buf; } else { - out_buf = ff_get_audio_buffer(inlink, nb_samples); + out_buf = ff_get_audio_buffer(outlink, nb_samples); if (!out_buf) { av_frame_free(&buf); return AVERROR(ENOMEM); From c29038f3041a4080342b2e333c1967d136749c0f Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Mon, 25 Dec 2017 02:05:52 +0000 Subject: [PATCH 1531/2557] lavr: deprecate the entire library Deprecate the entire library. Merged years ago to provide compatibility with Libav, it remained unmaintained by the FFmpeg project and duplicated functionality provided by libswresample. In order to improve consistency and reduce attack surface, as well as to ease burden on maintainers, it has been deprecated. Users of this library are asked to migrate to libswresample, which, as well as providing more functionality, is faster and has higher accuracy. Signed-off-by: Rostislav Pehlivanov --- configure | 4 +- doc/APIchanges | 9 ++++ libavresample/avresample.h | 106 ++++++++++++++++++++++++++++++++++--- 3 files changed, 110 insertions(+), 9 deletions(-) diff --git a/configure b/configure index 606cdd0004ea8..1d2fffa132928 100755 --- a/configure +++ b/configure @@ -133,7 +133,7 @@ Component options: --disable-swscale disable libswscale build --disable-postproc disable libpostproc build --disable-avfilter disable libavfilter build - --enable-avresample enable libavresample build [no] + --enable-avresample enable libavresample build (deprecated) [no] --disable-pthreads disable pthreads [autodetect] --disable-w32threads disable Win32 threads [autodetect] --disable-os2threads disable OS/2 threads [autodetect] @@ -6521,7 +6521,7 @@ check_deps $CONFIG_LIST \ $ALL_COMPONENTS \ enabled threads && ! enabled pthreads && ! enabled atomics_native && die "non pthread threading without atomics not supported, try adding --enable-pthreads or --cpu=i486 or higher if you are on x86" - +enabled avresample && warn "Building with deprecated library libavresample" if test $target_os = "haiku"; then disable memalign diff --git a/doc/APIchanges b/doc/APIchanges index 3c9f237596e7b..38c1be61c7a47 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,15 @@ libavutil: 2017-10-21 API changes, most recent first: +2017-xx-xx - xxxxxxx - lavr 4.0.0 - avresample.h + Deprecate the entire library. Merged years ago to provide compatibility + with Libav, it remained unmaintained by the FFmpeg project and duplicated + functionality provided by libswresample. + + In order to improve consistency and reduce attack surface, it has been deprecated. + Users of this library are asked to migrate to libswresample, which, as well as + providing more functionality, is faster and has higher accuracy. + 2017-xx-xx - xxxxxxx - lavc 58.9.100 - avcodec.h Deprecate av_lockmgr_register(). You need to build FFmpeg with threading support enabled to get basic thread-safety (which is the default build diff --git a/libavresample/avresample.h b/libavresample/avresample.h index 193443e2a6b17..440e1a16e749e 100644 --- a/libavresample/avresample.h +++ b/libavresample/avresample.h @@ -103,24 +103,33 @@ #define AVRESAMPLE_MAX_CHANNELS 32 -typedef struct AVAudioResampleContext AVAudioResampleContext; +typedef attribute_deprecated struct AVAudioResampleContext AVAudioResampleContext; -/** Mixing Coefficient Types */ -enum AVMixCoeffType { +/** + * @deprecated use libswresample + * + * Mixing Coefficient Types */ +enum attribute_deprecated AVMixCoeffType { AV_MIX_COEFF_TYPE_Q8, /** 16-bit 8.8 fixed-point */ AV_MIX_COEFF_TYPE_Q15, /** 32-bit 17.15 fixed-point */ AV_MIX_COEFF_TYPE_FLT, /** floating-point */ AV_MIX_COEFF_TYPE_NB, /** Number of coeff types. Not part of ABI */ }; -/** Resampling Filter Types */ -enum AVResampleFilterType { +/** + * @deprecated use libswresample + * + * Resampling Filter Types */ +enum attribute_deprecated AVResampleFilterType { AV_RESAMPLE_FILTER_TYPE_CUBIC, /**< Cubic */ AV_RESAMPLE_FILTER_TYPE_BLACKMAN_NUTTALL, /**< Blackman Nuttall Windowed Sinc */ AV_RESAMPLE_FILTER_TYPE_KAISER, /**< Kaiser Windowed Sinc */ }; -enum AVResampleDitherMethod { +/** + * @deprecated use libswresample + */ +enum attribute_deprecated AVResampleDitherMethod { AV_RESAMPLE_DITHER_NONE, /**< Do not use dithering */ AV_RESAMPLE_DITHER_RECTANGULAR, /**< Rectangular Dither */ AV_RESAMPLE_DITHER_TRIANGULAR, /**< Triangular Dither*/ @@ -130,22 +139,37 @@ enum AVResampleDitherMethod { }; /** + * + * @deprecated use libswresample + * * Return the LIBAVRESAMPLE_VERSION_INT constant. */ +attribute_deprecated unsigned avresample_version(void); /** + * + * @deprecated use libswresample + * * Return the libavresample build-time configuration. * @return configure string */ +attribute_deprecated const char *avresample_configuration(void); /** + * + * @deprecated use libswresample + * * Return the libavresample license. */ +attribute_deprecated const char *avresample_license(void); /** + * + * @deprecated use libswresample + * * Get the AVClass for AVAudioResampleContext. * * Can be used in combination with AV_OPT_SEARCH_FAKE_OBJ for examining options @@ -155,16 +179,24 @@ const char *avresample_license(void); * * @return AVClass for AVAudioResampleContext */ +attribute_deprecated const AVClass *avresample_get_class(void); /** + * + * @deprecated use libswresample + * * Allocate AVAudioResampleContext and set options. * * @return allocated audio resample context, or NULL on failure */ +attribute_deprecated AVAudioResampleContext *avresample_alloc_context(void); /** + * + * @deprecated use libswresample + * * Initialize AVAudioResampleContext. * @note The context must be configured using the AVOption API. * @note The fields "in_channel_layout", "out_channel_layout", @@ -178,17 +210,25 @@ AVAudioResampleContext *avresample_alloc_context(void); * @param avr audio resample context * @return 0 on success, negative AVERROR code on failure */ +attribute_deprecated int avresample_open(AVAudioResampleContext *avr); /** + * + * @deprecated use libswresample + * * Check whether an AVAudioResampleContext is open or closed. * * @param avr AVAudioResampleContext to check * @return 1 if avr is open, 0 if avr is closed. */ +attribute_deprecated int avresample_is_open(AVAudioResampleContext *avr); /** + * + * @deprecated use libswresample + * * Close AVAudioResampleContext. * * This closes the context, but it does not change the parameters. The context @@ -201,18 +241,26 @@ int avresample_is_open(AVAudioResampleContext *avr); * * @param avr audio resample context */ +attribute_deprecated void avresample_close(AVAudioResampleContext *avr); /** + * + * @deprecated use libswresample + * * Free AVAudioResampleContext and associated AVOption values. * * This also calls avresample_close() before freeing. * * @param avr audio resample context */ +attribute_deprecated void avresample_free(AVAudioResampleContext **avr); /** + * + * @deprecated use libswresample + * * Generate a channel mixing matrix. * * This function is the one used internally by libavresample for building the @@ -234,12 +282,16 @@ void avresample_free(AVAudioResampleContext **avr); * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii) * @return 0 on success, negative AVERROR code on failure */ +attribute_deprecated int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout, double center_mix_level, double surround_mix_level, double lfe_mix_level, int normalize, double *matrix, int stride, enum AVMatrixEncoding matrix_encoding); /** + * + * @deprecated use libswresample + * * Get the current channel mixing matrix. * * If no custom matrix has been previously set or the AVAudioResampleContext is @@ -251,10 +303,14 @@ int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout, * @param stride distance between adjacent input channels in the matrix array * @return 0 on success, negative AVERROR code on failure */ +attribute_deprecated int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix, int stride); /** + * + * @deprecated use libswresample + * * Set channel mixing matrix. * * Allows for setting a custom mixing matrix, overriding the default matrix @@ -272,10 +328,14 @@ int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix, * @param stride distance between adjacent input channels in the matrix array * @return 0 on success, negative AVERROR code on failure */ +attribute_deprecated int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix, int stride); /** + * + * @deprecated use libswresample + * * Set a customized input channel mapping. * * This function can only be called when the allocated context is not open. @@ -302,10 +362,14 @@ int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix, * @param channel_map customized input channel mapping * @return 0 on success, negative AVERROR code on failure */ +attribute_deprecated int avresample_set_channel_mapping(AVAudioResampleContext *avr, const int *channel_map); /** + * + * @deprecated use libswresample + * * Set compensation for resampling. * * This can be called anytime after avresample_open(). If resampling is not @@ -318,10 +382,14 @@ int avresample_set_channel_mapping(AVAudioResampleContext *avr, * @param compensation_distance compensation distance, in samples * @return 0 on success, negative AVERROR code on failure */ +attribute_deprecated int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta, int compensation_distance); /** + * + * @deprecated use libswresample + * * Provide the upper bound on the number of samples the configured * conversion would output. * @@ -331,10 +399,13 @@ int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta, * @return number of samples or AVERROR(EINVAL) if the value * would exceed INT_MAX */ - +attribute_deprecated int avresample_get_out_samples(AVAudioResampleContext *avr, int in_nb_samples); /** + * + * @deprecated use libswresample + * * Convert input samples and write them to the output FIFO. * * The upper bound on the number of output samples can be obtained through @@ -376,12 +447,16 @@ int avresample_get_out_samples(AVAudioResampleContext *avr, int in_nb_samples); * not including converted samples added to the internal * output FIFO */ +attribute_deprecated int avresample_convert(AVAudioResampleContext *avr, uint8_t **output, int out_plane_size, int out_samples, uint8_t * const *input, int in_plane_size, int in_samples); /** + * + * @deprecated use libswresample + * * Return the number of samples currently in the resampling delay buffer. * * When resampling, there may be a delay between the input and output. Any @@ -394,9 +469,13 @@ int avresample_convert(AVAudioResampleContext *avr, uint8_t **output, * @param avr audio resample context * @return number of samples currently in the resampling delay buffer */ +attribute_deprecated int avresample_get_delay(AVAudioResampleContext *avr); /** + * + * @deprecated use libswresample + * * Return the number of available samples in the output FIFO. * * During conversion, if the user does not specify an output buffer or @@ -411,9 +490,13 @@ int avresample_get_delay(AVAudioResampleContext *avr); * @param avr audio resample context * @return number of samples available for reading */ +attribute_deprecated int avresample_available(AVAudioResampleContext *avr); /** + * + * @deprecated use libswresample + * * Read samples from the output FIFO. * * During conversion, if the user does not specify an output buffer or @@ -430,9 +513,13 @@ int avresample_available(AVAudioResampleContext *avr); * @param nb_samples number of samples to read from the FIFO * @return the number of samples written to output */ +attribute_deprecated int avresample_read(AVAudioResampleContext *avr, uint8_t **output, int nb_samples); /** + * + * @deprecated use libswresample + * * Convert the samples in the input AVFrame and write them to the output AVFrame. * * Input and output AVFrames must have channel_layout, sample_rate and format set. @@ -476,10 +563,14 @@ int avresample_read(AVAudioResampleContext *avr, uint8_t **output, int nb_sample * @return 0 on success, AVERROR on failure or nonmatching * configuration. */ +attribute_deprecated int avresample_convert_frame(AVAudioResampleContext *avr, AVFrame *output, AVFrame *input); /** + * + * @deprecated use libswresample + * * Configure or reconfigure the AVAudioResampleContext using the information * provided by the AVFrames. * @@ -494,6 +585,7 @@ int avresample_convert_frame(AVAudioResampleContext *avr, * @param in input AVFrame * @return 0 on success, AVERROR on failure. */ +attribute_deprecated int avresample_config(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in); /** From f141b353e60f1081185927a1e74a9ab46cae8bef Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Thu, 4 Jan 2018 02:52:40 +0000 Subject: [PATCH 1532/2557] opusenc_psy: disable stereo searches for mono streams Fixes a crash which happened when someone tried to encode mono. Signed-off-by: Rostislav Pehlivanov --- libavcodec/opusenc_psy.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/opusenc_psy.c b/libavcodec/opusenc_psy.c index 50890c65d68ed..b7126033441e3 100644 --- a/libavcodec/opusenc_psy.c +++ b/libavcodec/opusenc_psy.c @@ -383,6 +383,10 @@ static void celt_search_for_dual_stereo(OpusPsyContext *s, CeltFrame *f) { float td1, td2; f->dual_stereo = 0; + + if (s->avctx->channels < 2) + return; + bands_dist(s, f, &td1); f->dual_stereo = 1; bands_dist(s, f, &td2); @@ -396,6 +400,9 @@ static void celt_search_for_intensity(OpusPsyContext *s, CeltFrame *f) int i, best_band = CELT_MAX_BANDS - 1; float dist, best_dist = FLT_MAX; + if (s->avctx->channels < 2) + return; + /* TODO: fix, make some heuristic up here using the lambda value */ float end_band = 0; From 695b1d81117d6708a5db2d7115b73ef7c6e1a090 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 2 Jan 2018 01:58:35 +0100 Subject: [PATCH 1533/2557] lavu/mem: Allow allocations close to max_alloc_size with av_fast_realloc(). --- libavutil/mem.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavutil/mem.c b/libavutil/mem.c index 0729e1dd50684..6149755a6b88e 100644 --- a/libavutil/mem.c +++ b/libavutil/mem.c @@ -466,7 +466,12 @@ void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size) if (min_size <= *size) return ptr; - min_size = FFMAX(min_size + min_size / 16 + 32, min_size); + if (min_size > max_alloc_size - 32) { + *size = 0; + return NULL; + } + + min_size = FFMIN(max_alloc_size - 32, FFMAX(min_size + min_size / 16 + 32, min_size)); ptr = av_realloc(ptr, min_size); /* we could set this to the unmodified min_size but this is safer From 89bbf5c7ec18a3dff2e2505883a662d182ca6c3a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 1 Jan 2018 15:34:02 +0100 Subject: [PATCH 1534/2557] avfilter: add hilbert source FIR filter Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/filters.texi | 28 ++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/asrc_hilbert.c | 199 +++++++++++++++++++++++++++++++++++++ libavfilter/version.h | 2 +- 6 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 libavfilter/asrc_hilbert.c diff --git a/Changelog b/Changelog index d1620e0df46bb..3d966c202b060 100644 --- a/Changelog +++ b/Changelog @@ -32,6 +32,7 @@ version : version is Windows Vista. - deconvolve video filter - entropy video filter +- hilbert audio filter source version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index 477f8334496d4..73537c524fdc4 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -926,6 +926,7 @@ afftfilt="1-clip((b/nb)*b,0,1)" @end example @end itemize +@anchor{afir} @section afir Apply an arbitrary Frequency Impulse Response filter. @@ -4873,6 +4874,33 @@ anoisesrc=d=60:c=pink:r=44100:a=0.5 @end example @end itemize +@section hilbert + +Generate odd-tap Hilbert transform FIR coefficients. + +The resulting stream can be used with @ref{afir} filter for phase-shifting +the signal by 90 degrees. + +This is used in many matrix coding schemes and for analytic signal generation. +The process is often written as a multiplication by i (or j), the imaginary unit. + +The filter accepts the following options: + +@table @option + +@item sample_rate, s +Set sample rate, default is 44100. + +@item taps, t +Set length of FIR filter, default is 22051. + +@item nb_samples, n +Set number of samples per each frame. + +@item win_func, w +Set window function to be used when generating FIR coefficients. +@end table + @section sine Generate an audio signal made of a sine wave with amplitude 1/8. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 7d9f2330ca992..8a103d4f338aa 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -126,6 +126,7 @@ OBJS-$(CONFIG_AEVALSRC_FILTER) += aeval.o OBJS-$(CONFIG_ANOISESRC_FILTER) += asrc_anoisesrc.o OBJS-$(CONFIG_ANULLSRC_FILTER) += asrc_anullsrc.o OBJS-$(CONFIG_FLITE_FILTER) += asrc_flite.o +OBJS-$(CONFIG_HILBERT_FILTER) += asrc_hilbert.o OBJS-$(CONFIG_SINE_FILTER) += asrc_sine.o OBJS-$(CONFIG_ANULLSINK_FILTER) += asink_anullsink.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 7635a8a5831b0..8c4ed6bd03366 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -137,6 +137,7 @@ static void register_all(void) REGISTER_FILTER(ANOISESRC, anoisesrc, asrc); REGISTER_FILTER(ANULLSRC, anullsrc, asrc); REGISTER_FILTER(FLITE, flite, asrc); + REGISTER_FILTER(HILBERT, hilbert, asrc); REGISTER_FILTER(SINE, sine, asrc); REGISTER_FILTER(ANULLSINK, anullsink, asink); diff --git a/libavfilter/asrc_hilbert.c b/libavfilter/asrc_hilbert.c new file mode 100644 index 0000000000000..a3a395254fef3 --- /dev/null +++ b/libavfilter/asrc_hilbert.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2018 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/opt.h" +#include "audio.h" +#include "avfilter.h" +#include "internal.h" +#include "window_func.h" + +typedef struct HilbertContext { + const AVClass *class; + + int sample_rate; + int nb_taps; + int nb_samples; + int win_func; + + float *taps; + int64_t pts; +} HilbertContext; + +#define OFFSET(x) offsetof(HilbertContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption hilbert_options[] = { + { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS }, + { "r", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS }, + { "taps", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=22051}, 11, UINT16_MAX, FLAGS }, + { "t", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=22051}, 11, UINT16_MAX, FLAGS }, + { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS }, + { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS }, + { "win_func", "set window function", OFFSET(win_func), AV_OPT_TYPE_INT, {.i64=WFUNC_BLACKMAN}, 0, NB_WFUNC-1, FLAGS, "win_func" }, + { "w", "set window function", OFFSET(win_func), AV_OPT_TYPE_INT, {.i64=WFUNC_BLACKMAN}, 0, NB_WFUNC-1, FLAGS, "win_func" }, + { "rect", "Rectangular", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_RECT}, 0, 0, FLAGS, "win_func" }, + { "bartlett", "Bartlett", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BARTLETT}, 0, 0, FLAGS, "win_func" }, + { "hanning", "Hanning", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HANNING}, 0, 0, FLAGS, "win_func" }, + { "hamming", "Hamming", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HAMMING}, 0, 0, FLAGS, "win_func" }, + { "blackman", "Blackman", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BLACKMAN}, 0, 0, FLAGS, "win_func" }, + { "welch", "Welch", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_WELCH}, 0, 0, FLAGS, "win_func" }, + { "flattop", "Flat-top", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_FLATTOP}, 0, 0, FLAGS, "win_func" }, + { "bharris", "Blackman-Harris", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BHARRIS}, 0, 0, FLAGS, "win_func" }, + { "bnuttall", "Blackman-Nuttall", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BNUTTALL}, 0, 0, FLAGS, "win_func" }, + { "bhann", "Bartlett-Hann", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BHANN}, 0, 0, FLAGS, "win_func" }, + { "sine", "Sine", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_SINE}, 0, 0, FLAGS, "win_func" }, + { "nuttall", "Nuttall", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_NUTTALL}, 0, 0, FLAGS, "win_func" }, + { "lanczos", "Lanczos", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_LANCZOS}, 0, 0, FLAGS, "win_func" }, + { "gauss", "Gauss", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_GAUSS}, 0, 0, FLAGS, "win_func" }, + { "tukey", "Tukey", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_TUKEY}, 0, 0, FLAGS, "win_func" }, + { "dolph", "Dolph-Chebyshev", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_DOLPH}, 0, 0, FLAGS, "win_func" }, + { "cauchy", "Cauchy", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_CAUCHY}, 0, 0, FLAGS, "win_func" }, + { "parzen", "Parzen", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_PARZEN}, 0, 0, FLAGS, "win_func" }, + { "poisson", "Poisson", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_POISSON}, 0, 0, FLAGS, "win_func" }, + {NULL} +}; + +AVFILTER_DEFINE_CLASS(hilbert); + +static av_cold int init(AVFilterContext *ctx) +{ + HilbertContext *s = ctx->priv; + + if (!(s->nb_taps & 1)) { + av_log(s, AV_LOG_ERROR, "Number of taps %d must be odd length.\n", s->nb_taps); + return AVERROR(EINVAL); + } + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + HilbertContext *s = ctx->priv; + + av_freep(&s->taps); +} + +static av_cold int query_formats(AVFilterContext *ctx) +{ + HilbertContext *s = ctx->priv; + static const int64_t chlayouts[] = { AV_CH_LAYOUT_MONO, -1 }; + int sample_rates[] = { s->sample_rate, -1 }; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_NONE + }; + + AVFilterFormats *formats; + AVFilterChannelLayouts *layouts; + int ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats (ctx, formats); + if (ret < 0) + return ret; + + layouts = avfilter_make_format64_list(chlayouts); + if (!layouts) + return AVERROR(ENOMEM); + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_make_format_list(sample_rates); + if (!formats) + return AVERROR(ENOMEM); + return ff_set_common_samplerates(ctx, formats); +} + +static av_cold int config_props(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + HilbertContext *s = ctx->priv; + float overlap; + int i; + + s->taps = av_malloc_array(s->nb_taps, sizeof(*s->taps)); + if (!s->taps) + return AVERROR(ENOMEM); + + generate_window_func(s->taps, s->nb_taps, s->win_func, &overlap); + + for (i = 0; i < s->nb_taps; i++) { + int k = -(s->nb_taps / 2) + i; + + if (k & 1) { + float pk = M_PI * k; + + s->taps[i] *= (1.f - cosf(pk)) / pk; + } else { + s->taps[i] = 0.f; + } + } + + s->pts = 0; + + return 0; +} + +static int request_frame(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + HilbertContext *s = ctx->priv; + AVFrame *frame; + int nb_samples; + + nb_samples = FFMIN(s->nb_samples, s->nb_taps - s->pts); + if (!nb_samples) + return AVERROR_EOF; + + if (!(frame = ff_get_audio_buffer(outlink, nb_samples))) + return AVERROR(ENOMEM); + + memcpy(frame->data[0], s->taps + s->pts, nb_samples * sizeof(float)); + + frame->pts = s->pts; + s->pts += nb_samples; + return ff_filter_frame(outlink, frame); +} + +static const AVFilterPad hilbert_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .request_frame = request_frame, + .config_props = config_props, + }, + { NULL } +}; + +AVFilter ff_asrc_hilbert = { + .name = "hilbert", + .description = NULL_IF_CONFIG_SMALL("Generate a Hilbert transform FIR coefficients."), + .query_formats = query_formats, + .init = init, + .uninit = uninit, + .priv_size = sizeof(HilbertContext), + .inputs = NULL, + .outputs = hilbert_outputs, + .priv_class = &hilbert_class, +}; diff --git a/libavfilter/version.h b/libavfilter/version.h index c41dfc178eb40..ac8bec4cb8198 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 9 +#define LIBAVFILTER_VERSION_MINOR 10 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ From 8a108bdea06fac43af9f44b6d2538f357451167a Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 2 Jan 2018 17:05:03 +0100 Subject: [PATCH 1535/2557] http: block while waiting for reconnecting It makes no sense to return an error after the first reconnect, and then somehow resume the next time it's called. Usually this will lead to demuxer errors. Make reconnecting block instead, until it has either successfully reconnected, or given up. Also make the wait reasonably interruptible. Since there is no mechanism for this in the API, polling is the best we can do. This behaves roughly the same as other interruptible network functions in libavformat. (The original code would work if it returned AVERROR(EAGAIN) or so, which would make retry_transfer_wrapper() repeat the read call. But I think having an explicit loop for this is better anyway.) I also snuck in a fix for reconnect_at_eof. It has to check for AVERROR_EOF, not 0. --- libavformat/http.c | 19 ++++++++++--------- libavformat/network.c | 18 ++++++++++++++++++ libavformat/network.h | 9 +++++++++ 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/libavformat/http.c b/libavformat/http.c index 8f7e56de54d33..5eff87f8bb9e2 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -117,7 +117,6 @@ typedef struct HTTPContext { int reconnect; int reconnect_at_eof; int reconnect_streamed; - int reconnect_delay; int reconnect_delay_max; int listen; char *resource; @@ -1433,6 +1432,7 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) HTTPContext *s = h->priv_data; int err, new_location, read_ret; int64_t seek_ret; + int reconnect_delay = 0; if (!s->hd) return AVERROR_EOF; @@ -1448,25 +1448,26 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) return http_buf_read_compressed(h, buf, size); #endif /* CONFIG_ZLIB */ read_ret = http_buf_read(h, buf, size); - if ( (read_ret < 0 && s->reconnect && (!h->is_streamed || s->reconnect_streamed) && s->filesize > 0 && s->off < s->filesize) - || (read_ret == 0 && s->reconnect_at_eof && (!h->is_streamed || s->reconnect_streamed))) { + while ((read_ret < 0 && s->reconnect && (!h->is_streamed || s->reconnect_streamed) && s->filesize > 0 && s->off < s->filesize) + || (read_ret == AVERROR_EOF && s->reconnect_at_eof && (!h->is_streamed || s->reconnect_streamed))) { uint64_t target = h->is_streamed ? 0 : s->off; - if (s->reconnect_delay > s->reconnect_delay_max) + if (reconnect_delay > s->reconnect_delay_max) return AVERROR(EIO); av_log(h, AV_LOG_INFO, "Will reconnect at %"PRIu64" error=%s.\n", s->off, av_err2str(read_ret)); - av_usleep(1000U*1000*s->reconnect_delay); - s->reconnect_delay = 1 + 2*s->reconnect_delay; + err = ff_network_sleep_interruptible(1000U*1000*reconnect_delay, &h->interrupt_callback); + if (err != AVERROR(ETIMEDOUT)) + return err; + reconnect_delay = 1 + 2*reconnect_delay; seek_ret = http_seek_internal(h, target, SEEK_SET, 1); - if (seek_ret != target) { + if (seek_ret >= 0 && seek_ret != target) { av_log(h, AV_LOG_ERROR, "Failed to reconnect at %"PRIu64".\n", target); return read_ret; } read_ret = http_buf_read(h, buf, size); - } else - s->reconnect_delay = 0; + } return read_ret; } diff --git a/libavformat/network.c b/libavformat/network.c index 6c3d9def3b79a..e9eb4b443a0e6 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -103,6 +103,24 @@ int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterrupt } } +int ff_network_sleep_interruptible(int64_t timeout, AVIOInterruptCB *int_cb) +{ + int64_t wait_start = av_gettime_relative(); + + while (1) { + int64_t time_left; + + if (ff_check_interrupt(int_cb)) + return AVERROR_EXIT; + + time_left = timeout - (av_gettime_relative() - wait_start); + if (time_left <= 0) + return AVERROR(ETIMEDOUT); + + av_usleep(FFMIN(time_left, POLLING_TIME * 1000)); + } +} + void ff_network_close(void) { #if HAVE_WINSOCK2_H diff --git a/libavformat/network.h b/libavformat/network.h index b78e3ad6ed888..a663115541864 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -96,6 +96,15 @@ int ff_network_wait_fd(int fd, int write); */ int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb); +/** + * Waits for up to 'timeout' microseconds. If the usert's int_cb is set and + * triggered, return before that. + * @timeout Timeout in microseconds. Maybe have lower actual precision. + * @param int_cb Interrupt callback, is checked regularly. + * @return AVERROR(ETIMEDOUT) if timeout expirted, AVERROR_EXIT if interrupted by int_cb + */ +int ff_network_sleep_interruptible(int64_t timeout, AVIOInterruptCB *int_cb); + int ff_inet_aton (const char * str, struct in_addr * add); #if !HAVE_STRUCT_SOCKADDR_STORAGE From 1b283c4a0dde1060ca1745f59a15cb8b77dfdaa5 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 2 Jan 2018 17:17:41 +0100 Subject: [PATCH 1536/2557] http: bump message level for reconnect message and log timeout --- libavformat/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/http.c b/libavformat/http.c index 5eff87f8bb9e2..eb029e33a08b0 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -1455,7 +1455,7 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) if (reconnect_delay > s->reconnect_delay_max) return AVERROR(EIO); - av_log(h, AV_LOG_INFO, "Will reconnect at %"PRIu64" error=%s.\n", s->off, av_err2str(read_ret)); + av_log(h, AV_LOG_WARNING, "Will reconnect at %"PRIu64" in %d second(s), error=%s.\n", s->off, reconnect_delay, av_err2str(read_ret)); err = ff_network_sleep_interruptible(1000U*1000*reconnect_delay, &h->interrupt_callback); if (err != AVERROR(ETIMEDOUT)) return err; From 59b126f92225316e0cd77bb952d630553801dc85 Mon Sep 17 00:00:00 2001 From: Humberto Ribeiro Date: Wed, 3 Jan 2018 15:22:15 -0800 Subject: [PATCH 1537/2557] libavutil/hwcontext_dxva2: Add check for possible errors from GetAdapterDisplayModeEx This prevents a possible crash in CreateDeviceEx when using faulty response from GetAdapterDisplayModeEx and allows ffmpeg to fallback to classic d3d9. Signed-off-by: wm4 --- libavutil/hwcontext_dxva2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_dxva2.c b/libavutil/hwcontext_dxva2.c index 2ddd4be7b1df8..44ebdbca9586a 100644 --- a/libavutil/hwcontext_dxva2.c +++ b/libavutil/hwcontext_dxva2.c @@ -485,7 +485,11 @@ static int dxva2_device_create9ex(AVHWDeviceContext *ctx, UINT adapter) if (FAILED(hr)) return AVERROR_UNKNOWN; - IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, adapter, &modeex, NULL); + hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, adapter, &modeex, NULL); + if (FAILED(hr)) { + IDirect3D9Ex_Release(d3d9ex); + return AVERROR_UNKNOWN; + } d3dpp.BackBufferFormat = modeex.Format; From 18fbfd7bf86effb49c0341b37b9c1d73940d688e Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 4 Jan 2018 15:52:46 +0100 Subject: [PATCH 1538/2557] hwcontext_dxva2: initialize D3DDISPLAYMODEEX correctly --- libavutil/hwcontext_dxva2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_dxva2.c b/libavutil/hwcontext_dxva2.c index 44ebdbca9586a..665c2d6d746ad 100644 --- a/libavutil/hwcontext_dxva2.c +++ b/libavutil/hwcontext_dxva2.c @@ -485,6 +485,7 @@ static int dxva2_device_create9ex(AVHWDeviceContext *ctx, UINT adapter) if (FAILED(hr)) return AVERROR_UNKNOWN; + modeex.Size = sizeof(D3DDISPLAYMODEEX); hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, adapter, &modeex, NULL); if (FAILED(hr)) { IDirect3D9Ex_Release(d3d9ex); From 2477bfe22121f04eff9e4ba2475f1f999c17ea36 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 4 Jan 2018 17:06:52 +0100 Subject: [PATCH 1539/2557] http: avoid logging reconnect warning if stream was aborted If the stream was aborted using the libavformat interrupt callback, we don't want it to log the reconnect warning. (Exiting after logging this warning worked well, so this is only for avoiding the ugly warning.) --- libavformat/http.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index eb029e33a08b0..4806b1e59b38f 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -1452,6 +1452,9 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) || (read_ret == AVERROR_EOF && s->reconnect_at_eof && (!h->is_streamed || s->reconnect_streamed))) { uint64_t target = h->is_streamed ? 0 : s->off; + if (read_ret == AVERROR_EXIT) + return read_ret; + if (reconnect_delay > s->reconnect_delay_max) return AVERROR(EIO); From 34c113335b53d83ed343de49741f0823aa1f8cc6 Mon Sep 17 00:00:00 2001 From: Michael Wootton Date: Wed, 3 Jan 2018 12:55:53 -0500 Subject: [PATCH 1540/2557] Add support for H.264 and HEVC hardware encoding for AMD GPUs based on AMF SDK Requires AMF headers for at least version 1.4.4.1. Signed-off-by: Mikhail Mironov Signed-off-by: Luca Barbato --- configure | 10 + doc/general.texi | 10 + libavcodec/Makefile | 4 + libavcodec/allcodecs.c | 2 + libavcodec/amfenc.c | 608 +++++++++++++++++++++++++++++++++++++++ libavcodec/amfenc.h | 158 ++++++++++ libavcodec/amfenc_h264.c | 400 ++++++++++++++++++++++++++ libavcodec/amfenc_hevc.c | 332 +++++++++++++++++++++ 8 files changed, 1524 insertions(+) create mode 100644 libavcodec/amfenc.c create mode 100644 libavcodec/amfenc.h create mode 100644 libavcodec/amfenc_h264.c create mode 100644 libavcodec/amfenc_hevc.c diff --git a/configure b/configure index d31cb56588c5b..593064f8788df 100755 --- a/configure +++ b/configure @@ -231,6 +231,7 @@ External library support: --enable-zlib compression [autodetect] The following libraries provide various hardware acceleration features: + --enable-amf AMF video encoding code [auto] --enable-cuda Nvidia CUDA (dynamically linked) --enable-cuvid Nvidia CUVID video decode acceleration --enable-d3d11va Microsoft Direct3D 11 video acceleration [auto] @@ -1255,6 +1256,7 @@ HWACCEL_LIBRARY_NONFREE_LIST=" " HWACCEL_LIBRARY_LIST=" $HWACCEL_LIBRARY_NONFREE_LIST + amf d3d11va dxva2 libmfx @@ -2238,6 +2240,7 @@ wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" # hardware-accelerated codecs +amf_deps_any="libdl LoadLibrary" nvenc_deps_any="libdl LoadLibrary" omx_deps="libdl pthreads" omx_rpi_select="omx" @@ -2250,6 +2253,7 @@ vaapi_encode_deps="vaapi" hwupload_cuda_filter_deps="cuda" scale_npp_filter_deps="cuda libnpp" +h264_amf_encoder_deps="amf" h264_mmal_decoder_deps="mmal" h264_nvenc_encoder_deps="nvenc" h264_omx_encoder_deps="omx" @@ -2257,6 +2261,7 @@ h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec" h264_qsv_encoder_select="qsvenc" h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" h264_vaapi_encoder_select="cbs_h264 vaapi_encode" +hevc_amf_encoder_deps="amf" hevc_nvenc_encoder_deps="nvenc" hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser qsvdec" hevc_qsv_encoder_select="hevcparse qsvenc" @@ -4573,6 +4578,11 @@ for func in $MATH_FUNCS; do done # these are off by default, so fail if requested and not available + +enabled amf && + check_cpp_condition "AMF/core/Version.h" \ + "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400040001" || + disable amf enabled avisynth && require_header avisynth/avisynth_c.h enabled avxsynth && require_header avxsynth/avxsynth_c.h enabled cuda && require cuda cuda.h cuInit -lcuda diff --git a/doc/general.texi b/doc/general.texi index 6e39d5c1a0e87..0c92761a49cf8 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -237,6 +237,16 @@ The dispatcher is open source and can be downloaded from with the @code{--enable-libmfx} option and @code{pkg-config} needs to be able to locate the dispatcher's @code{.pc} files. +@section AMD VCE + +Libav can use the AMD Advanced Media Framework library for accelerated H.264 and HEVC encoding on VCE enabled hardware under Windows. + +To enable support you must obtain the AMF framework header files from @url{https://github.com/GPUOpen-LibrariesAndSDKs/AMF.git}. + +Create an @code{AMF/} directory in the system include path. +Copy the contents of @code{AMF/amf/public/include/} into that directory. +Then Configure Libav with @code{--enable-amf}. + @chapter Supported File Formats and Codecs You can use the @code{-formats} and @code{-codecs} options to have an exhaustive list. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index d04902be08940..99969ac779720 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -48,6 +48,7 @@ OBJS = ac3_parser.o \ OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o OBJS-$(CONFIG_AC3DSP) += ac3dsp.o OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio.o +OBJS-$(CONFIG_AMF) += amfenc.o OBJS-$(CONFIG_AUDIO_FRAME_QUEUE) += audio_frame_queue.o OBJS-$(CONFIG_AUDIODSP) += audiodsp.o OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o @@ -271,6 +272,7 @@ OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264_cabac.o h264_cavlc.o \ h264_mb.o h264_picture.o \ h264_refs.o h264_sei.o \ h264_slice.o h264data.o +OBJS-$(CONFIG_H264_AMF_ENCODER) += amfenc_h264.o OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o OBJS-$(CONFIG_H264_OMX_ENCODER) += omx.o @@ -282,6 +284,7 @@ OBJS-$(CONFIG_HAP_ENCODER) += hapenc.o hap.o OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o hevc_sei.o \ hevc_cabac.o hevc_refs.o hevcpred.o \ hevcdsp.o hevc_filter.o hevc_data.o +OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec_h2645.o OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \ @@ -808,6 +811,7 @@ SKIPHEADERS += %_tablegen.h \ $(ARCH)/vp56_arith.h \ SKIPHEADERS-$(CONFIG_CUVID) += cuvid.h +SKIPHEADERS-$(CONFIG_AMF) += amfenc.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 50a87493eab91..efde5a2b0e6b7 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -452,11 +452,13 @@ void avcodec_register_all(void) /* external libraries, that shouldn't be used by default if one of the * above is available */ REGISTER_ENCDEC (LIBOPENH264, libopenh264); + REGISTER_ENCODER(H264_AMF, h264_amf); REGISTER_ENCODER(H264_NVENC, h264_nvenc); REGISTER_ENCODER(H264_OMX, h264_omx); REGISTER_ENCODER(H264_QSV, h264_qsv); REGISTER_ENCODER(H264_VAAPI, h264_vaapi); REGISTER_ENCODER(LIBKVAZAAR, libkvazaar); + REGISTER_ENCODER(HEVC_AMF, hevc_amf); REGISTER_ENCODER(HEVC_NVENC, hevc_nvenc); REGISTER_ENCODER(HEVC_QSV, hevc_qsv); REGISTER_ENCODER(HEVC_VAAPI, hevc_vaapi); diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c new file mode 100644 index 0000000000000..f305a48bf7d11 --- /dev/null +++ b/libavcodec/amfenc.c @@ -0,0 +1,608 @@ +/* + * AMD AMF support + * Copyright (C) 2017 Luca Barbato + * Copyright (C) 2017 Mikhail Mironov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "libavutil/hwcontext.h" +#include "internal.h" +#if CONFIG_D3D11VA +#include "libavutil/hwcontext_d3d11va.h" +#endif +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" +#include "libavutil/time.h" + +#include "amfenc.h" + +#if CONFIG_D3D11VA +#include +#endif + +#if HAVE_WINDOWS_H +#include +#define dlopen(filename, flags) LoadLibrary((filename)) +#define dlsym(handle, symbol) GetProcAddress(handle, symbol) +#define dlclose(handle) FreeLibrary(handle) +#else +#include +#endif + +#define PTS_PROP L"PtsProp" + +const enum AVPixelFormat ff_amf_pix_fmts[] = { + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUV420P, +#if CONFIG_D3D11VA + AV_PIX_FMT_D3D11, +#endif + AV_PIX_FMT_NONE +}; + +typedef struct FormatMap { + enum AVPixelFormat av_format; + enum AMF_SURFACE_FORMAT amf_format; +} FormatMap; + +static const FormatMap format_map[] = +{ + { AV_PIX_FMT_NONE, AMF_SURFACE_UNKNOWN }, + { AV_PIX_FMT_NV12, AMF_SURFACE_NV12 }, +// { AV_PIX_FMT_BGR0, AMF_SURFACE_BGRA }, +// { AV_PIX_FMT_RGB0, AMF_SURFACE_RGBA }, + { AV_PIX_FMT_GRAY8, AMF_SURFACE_GRAY8 }, + { AV_PIX_FMT_YUV420P, AMF_SURFACE_YUV420P }, + { AV_PIX_FMT_YUYV422, AMF_SURFACE_YUY2 }, + { AV_PIX_FMT_D3D11, AMF_SURFACE_NV12 }, +}; + + +static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + return desc->flags & AV_PIX_FMT_FLAG_HWACCEL; +} + + +static enum AMF_SURFACE_FORMAT amf_av_to_amf_format(enum AVPixelFormat fmt) +{ + int i; + for (i = 0; i < amf_countof(format_map); i++) { + if (format_map[i].av_format == fmt) { + return format_map[i].amf_format; + } + } + return AMF_SURFACE_UNKNOWN; +} + +static void AMF_CDECL_CALL AMFTraceWriter_Write(AMFTraceWriter *pThis, + const wchar_t *scope, const wchar_t *message) +{ + AmfTraceWriter *tracer = (AmfTraceWriter*)pThis; + av_log(tracer->avctx, AV_LOG_DEBUG, "%ls: %ls", scope, message); // \n is provided from AMF +} + +static void AMF_CDECL_CALL AMFTraceWriter_Flush(AMFTraceWriter *pThis) +{ +} + +static AMFTraceWriterVtbl tracer_vtbl = +{ + .Write = AMFTraceWriter_Write, + .Flush = AMFTraceWriter_Flush, +}; + +static int amf_load_library(AVCodecContext *avctx) +{ + AmfContext *ctx = avctx->priv_data; + AMFInit_Fn init_fun = NULL; + AMFQueryVersion_Fn version_fun = NULL; + AMF_RESULT res = AMF_OK; + + ctx->eof = 0; + ctx->delayed_drain = 0; + ctx->hw_frames_ctx = NULL; + ctx->hw_device_ctx = NULL; + ctx->delayed_surface = NULL; + ctx->delayed_frame = av_frame_alloc(); + if (!ctx->delayed_frame) { + return AVERROR(ENOMEM); + } + // hardcoded to current HW queue size - will realloc in timestamp_queue_enqueue() if too small + ctx->timestamp_list = av_fifo_alloc((avctx->max_b_frames + 16) * sizeof(int64_t)); + if (!ctx->timestamp_list) { + return AVERROR(ENOMEM); + } + ctx->dts_delay = 0; + + + ctx->library = dlopen(AMF_DLL_NAMEA, RTLD_NOW | RTLD_LOCAL); + AMF_RETURN_IF_FALSE(ctx, ctx->library != NULL, + AVERROR_UNKNOWN, "DLL %s failed to open\n", AMF_DLL_NAMEA); + + init_fun = (AMFInit_Fn)dlsym(ctx->library, AMF_INIT_FUNCTION_NAME); + AMF_RETURN_IF_FALSE(ctx, init_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_INIT_FUNCTION_NAME); + + version_fun = (AMFQueryVersion_Fn)dlsym(ctx->library, AMF_QUERY_VERSION_FUNCTION_NAME); + AMF_RETURN_IF_FALSE(ctx, version_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_QUERY_VERSION_FUNCTION_NAME); + + res = version_fun(&ctx->version); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_QUERY_VERSION_FUNCTION_NAME, res); + res = init_fun(AMF_FULL_VERSION, &ctx->factory); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_INIT_FUNCTION_NAME, res); + res = ctx->factory->pVtbl->GetTrace(ctx->factory, &ctx->trace); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetTrace() failed with error %d\n", res); + res = ctx->factory->pVtbl->GetDebug(ctx->factory, &ctx->debug); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetDebug() failed with error %d\n", res); + return 0; +} + +static int amf_init_context(AVCodecContext *avctx) +{ + AmfContext *ctx = avctx->priv_data; + AMF_RESULT res = AMF_OK; + + // configure AMF logger + // the return of these functions indicates old state and do not affect behaviour + ctx->trace->pVtbl->EnableWriter(ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, ctx->log_to_dbg != 0 ); + if (ctx->log_to_dbg) + ctx->trace->pVtbl->SetWriterLevel(ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, AMF_TRACE_TRACE); + ctx->trace->pVtbl->EnableWriter(ctx->trace, AMF_TRACE_WRITER_CONSOLE, 0); + ctx->trace->pVtbl->SetGlobalLevel(ctx->trace, AMF_TRACE_TRACE); + + // connect AMF logger to av_log + ctx->tracer.vtbl = &tracer_vtbl; + ctx->tracer.avctx = avctx; + ctx->trace->pVtbl->RegisterWriter(ctx->trace, ctx->writer_id, (AMFTraceWriter*)&ctx->tracer, 1); + ctx->trace->pVtbl->SetWriterLevel(ctx->trace, ctx->writer_id, AMF_TRACE_TRACE); + + res = ctx->factory->pVtbl->CreateContext(ctx->factory, &ctx->context); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext() failed with error %d\n", res); + // try to reuse existing DX device +#if CONFIG_D3D11VA + if (avctx->hw_frames_ctx) { + AVHWFramesContext *device_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + if (device_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { + if (amf_av_to_amf_format(device_ctx->sw_format) != AMF_SURFACE_UNKNOWN) { + if (device_ctx->device_ctx->hwctx) { + AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->device_ctx->hwctx; + res = ctx->context->pVtbl->InitDX11(ctx->context, device_d3d11->device, AMF_DX11_1); + if (res == AMF_OK) { + ctx->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx); + if (!ctx->hw_frames_ctx) { + return AVERROR(ENOMEM); + } + } else { + if(res == AMF_NOT_SUPPORTED) + av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n"); + else + av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has non-AMD device, switching to default\n"); + } + } + } else { + av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has format not uspported by AMF, switching to default\n"); + } + } + } else if (avctx->hw_device_ctx) { + AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data); + if (device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { + if (device_ctx->hwctx) { + AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->hwctx; + res = ctx->context->pVtbl->InitDX11(ctx->context, device_d3d11->device, AMF_DX11_1); + if (res == AMF_OK) { + ctx->hw_device_ctx = av_buffer_ref(avctx->hw_device_ctx); + if (!ctx->hw_device_ctx) { + return AVERROR(ENOMEM); + } + } else { + if (res == AMF_NOT_SUPPORTED) + av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n"); + else + av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has non-AMD device, switching to default\n"); + } + } + } + } +#endif + if (!ctx->hw_frames_ctx && !ctx->hw_device_ctx) { + res = ctx->context->pVtbl->InitDX11(ctx->context, NULL, AMF_DX11_1); + if (res != AMF_OK) { + res = ctx->context->pVtbl->InitDX9(ctx->context, NULL); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "InitDX9() failed with error %d\n", res); + } + } + return 0; +} + +static int amf_init_encoder(AVCodecContext *avctx) +{ + AmfContext *ctx = avctx->priv_data; + const wchar_t *codec_id = NULL; + AMF_RESULT res = AMF_OK; + + switch (avctx->codec->id) { + case AV_CODEC_ID_H264: + codec_id = AMFVideoEncoderVCE_AVC; + break; + case AV_CODEC_ID_HEVC: + codec_id = AMFVideoEncoder_HEVC; + break; + default: + break; + } + AMF_RETURN_IF_FALSE(ctx, codec_id != NULL, AVERROR(EINVAL), "Codec %d is not supported\n", avctx->codec->id); + + ctx->format = amf_av_to_amf_format(avctx->pix_fmt); + AMF_RETURN_IF_FALSE(ctx, ctx->format != AMF_SURFACE_UNKNOWN, AVERROR(EINVAL), "Format %d is not supported\n", avctx->pix_fmt); + + res = ctx->factory->pVtbl->CreateComponent(ctx->factory, ctx->context, codec_id, &ctx->encoder); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_ENCODER_NOT_FOUND, "CreateComponent(%ls) failed with error %d\n", codec_id, res); + + return 0; +} + +int av_cold ff_amf_encode_close(AVCodecContext *avctx) +{ + AmfContext *ctx = avctx->priv_data; + if (ctx->delayed_surface) + { + ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface); + ctx->delayed_surface = NULL; + } + + if (ctx->encoder) { + ctx->encoder->pVtbl->Terminate(ctx->encoder); + ctx->encoder->pVtbl->Release(ctx->encoder); + ctx->encoder = NULL; + } + + if (ctx->context) { + ctx->context->pVtbl->Terminate(ctx->context); + ctx->context->pVtbl->Release(ctx->context); + ctx->context = NULL; + } + av_buffer_unref(&ctx->hw_device_ctx); + av_buffer_unref(&ctx->hw_frames_ctx); + + if (ctx->trace) { + ctx->trace->pVtbl->UnregisterWriter(ctx->trace, ctx->writer_id); + } + if (ctx->library) { + dlclose(ctx->library); + ctx->library = NULL; + } + ctx->trace = NULL; + ctx->debug = NULL; + ctx->factory = NULL; + ctx->version = 0; + ctx->delayed_drain = 0; + av_frame_free(&ctx->delayed_frame); + av_fifo_free(ctx->timestamp_list); + ctx->timestamp_list = NULL; + ctx->timestamp_last = 0; + + return 0; +} + +static int amf_copy_surface(AVCodecContext *avctx, const AVFrame *frame, + AMFSurface* surface) +{ + AVFrame *sw_frame = NULL; + AMFPlane *plane = NULL; + uint8_t *dst_data[4]; + int dst_linesize[4]; + int ret = 0; + int planes; + int i; + + if (frame->hw_frames_ctx && is_hwaccel_pix_fmt(frame->format)) { + if (!(sw_frame = av_frame_alloc())) { + av_log(avctx, AV_LOG_ERROR, "Can not alloc frame\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + if ((ret = av_hwframe_transfer_data(sw_frame, frame, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error transferring the data to system memory\n"); + goto fail; + } + frame = sw_frame; + } + planes = (int)surface->pVtbl->GetPlanesCount(surface); + if (planes > amf_countof(dst_data)) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of planes %d in surface\n", planes); + ret = AVERROR(EINVAL); + goto fail; + } + + for (i = 0; i < planes; i++) { + plane = surface->pVtbl->GetPlaneAt(surface, i); + dst_data[i] = plane->pVtbl->GetNative(plane); + dst_linesize[i] = plane->pVtbl->GetHPitch(plane); + } + av_image_copy(dst_data, dst_linesize, + (const uint8_t**)frame->data, frame->linesize, frame->format, + avctx->width, avctx->height); + +fail: + if (sw_frame) { + av_frame_free(&sw_frame); + } + return ret; +} + +static inline int timestamp_queue_enqueue(AVCodecContext *avctx, int64_t timestamp) +{ + AmfContext *ctx = avctx->priv_data; + if (av_fifo_space(ctx->timestamp_list) < sizeof(timestamp)) { + int size = av_fifo_size(ctx->timestamp_list); + if (INT_MAX / 2 - size < sizeof(timestamp)) + return AVERROR(EINVAL); + av_fifo_realloc2(ctx->timestamp_list, (size + sizeof(timestamp)) * 2); + } + av_fifo_generic_write(ctx->timestamp_list, ×tamp, sizeof(timestamp), NULL); + ctx->timestamp_last = timestamp; + return 0; +} + +static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buffer) +{ + AmfContext *ctx = avctx->priv_data; + int ret; + AMFVariantStruct var = {0}; + int64_t timestamp = AV_NOPTS_VALUE; + int64_t size = buffer->pVtbl->GetSize(buffer); + + //if ((ret = ff_alloc_packet2(avctx, pkt, size, 0)) < 0) { + if (ret = ff_alloc_packet(pkt, size)) { + return ret; + } + memcpy(pkt->data, buffer->pVtbl->GetNative(buffer), size); + + switch (avctx->codec->id) { + case AV_CODEC_ID_H264: + buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE, &var); + if(var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR) { + pkt->flags = AV_PKT_FLAG_KEY; + } + break; + case AV_CODEC_ID_HEVC: + buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE, &var); + if (var.int64Value == AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_IDR) { + pkt->flags = AV_PKT_FLAG_KEY; + } + break; + default: + break; + } + + buffer->pVtbl->GetProperty(buffer, PTS_PROP, &var); + + pkt->pts = var.int64Value; // original pts + + + AMF_RETURN_IF_FALSE(ctx, av_fifo_size(ctx->timestamp_list) > 0, AVERROR_UNKNOWN, "timestamp_list is empty\n"); + + av_fifo_generic_read(ctx->timestamp_list, ×tamp, sizeof(timestamp), NULL); + + // calc dts shift if max_b_frames > 0 + if (avctx->max_b_frames > 0 && ctx->dts_delay == 0) { + AMF_RETURN_IF_FALSE(ctx, av_fifo_size(ctx->timestamp_list) > 0, AVERROR_UNKNOWN, + "timestamp_list is empty while max_b_frames = %d\n", avctx->max_b_frames); + + if (timestamp < 0 || ctx->timestamp_last < AV_NOPTS_VALUE) { + return AVERROR(ERANGE); + } + ctx->dts_delay = ctx->timestamp_last - timestamp; + } + pkt->dts = timestamp - ctx->dts_delay; + return 0; +} + +// amfenc API implementation +int ff_amf_encode_init(AVCodecContext *avctx) +{ + AmfContext *ctx = avctx->priv_data; + int ret; + + ctx->factory = NULL; + ctx->debug = NULL; + ctx->trace = NULL; + ctx->context = NULL; + ctx->encoder = NULL; + ctx->library = NULL; + ctx->version = 0; + ctx->eof = 0; + ctx->format = 0; + ctx->tracer.vtbl = NULL; + ctx->tracer.avctx = NULL; + + if ((ret = amf_load_library(avctx)) == 0) { + if ((ret = amf_init_context(avctx)) == 0) { + if ((ret = amf_init_encoder(avctx)) == 0) { + return 0; + } + } + } + ff_amf_encode_close(avctx); + return ret; +} + + +int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame) +{ + AMF_RESULT res = AMF_OK; + AmfContext *ctx = avctx->priv_data; + AMFSurface *surface = NULL; + int ret; + + if (!ctx->encoder) + return AVERROR(EINVAL); + + if (!frame) { // submit drain + if (!ctx->eof) { // submit drain one time only + if (ctx->delayed_surface != NULL) { + ctx->delayed_drain = 1; // input queue is full: resubmit Drain() in ff_amf_receive_packet + } else if(!ctx->delayed_drain) { + res = ctx->encoder->pVtbl->Drain(ctx->encoder); + if (res == AMF_INPUT_FULL) { + ctx->delayed_drain = 1; // input queue is full: resubmit Drain() in ff_amf_receive_packet + } else { + if (res == AMF_OK) { + ctx->eof = 1; // drain started + } + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Drain() failed with error %d\n", res); + } + } + } else{ + return AVERROR_EOF; + } + } else { // submit frame + if (ctx->delayed_surface != NULL) { + return AVERROR(EAGAIN); // should not happen when called from ffmpeg, other clients may resubmit + } + // prepare surface from frame + if (frame->hw_frames_ctx && ( // HW frame detected + // check if the same hw_frames_ctx as used in initialization + (ctx->hw_frames_ctx && frame->hw_frames_ctx->data == ctx->hw_frames_ctx->data) || + // check if the same hw_device_ctx as used in initialization + (ctx->hw_device_ctx && ((AVHWFramesContext*)frame->hw_frames_ctx->data)->device_ctx == + (AVHWDeviceContext*)ctx->hw_device_ctx->data) + )) { +#if CONFIG_D3D11VA + static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } }; + ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // actual texture + int index = (int)(size_t)frame->data[1]; // index is a slice in texture array is - set to tell AMF which slice to use + texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID, sizeof(index), &index); + + res = ctx->context->pVtbl->CreateSurfaceFromDX11Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed with error %d\n", res); + + // input HW surfaces can be vertically aligned by 16; tell AMF the real size + surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height); +#endif + } else { + res = ctx->context->pVtbl->AllocSurface(ctx->context, AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res); + amf_copy_surface(avctx, frame, surface); + } + surface->pVtbl->SetPts(surface, frame->pts); + AMF_ASSIGN_PROPERTY_INT64(res, surface, PTS_PROP, frame->pts); + + switch (avctx->codec->id) { + case AV_CODEC_ID_H264: + AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_AUD, !!ctx->aud); + break; + case AV_CODEC_ID_HEVC: + AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!ctx->aud); + break; + default: + break; + } + + + // submit surface + res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)surface); + if (res == AMF_INPUT_FULL) { // handle full queue + //store surface for later submission + ctx->delayed_surface = surface; + if (surface->pVtbl->GetMemoryType(surface) == AMF_MEMORY_DX11) { + av_frame_ref(ctx->delayed_frame, frame); + } + } else { + surface->pVtbl->Release(surface); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res); + + if ((ret = timestamp_queue_enqueue(avctx, frame->pts)) < 0) { + return ret; + } + + } + } + return 0; +} +int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) +{ + int ret; + AMF_RESULT res; + AMF_RESULT res_query; + AmfContext *ctx = avctx->priv_data; + AMFData *data = NULL; + int block_and_wait; + + if (!ctx->encoder) + return AVERROR(EINVAL); + + do { + block_and_wait = 0; + // poll data + res_query = ctx->encoder->pVtbl->QueryOutput(ctx->encoder, &data); + if (data) { + // copy data to packet + AMFBuffer* buffer; + AMFGuid guid = IID_AMFBuffer(); + data->pVtbl->QueryInterface(data, &guid, (void**)&buffer); // query for buffer interface + ret = amf_copy_buffer(avctx, avpkt, buffer); + + buffer->pVtbl->Release(buffer); + data->pVtbl->Release(data); + + AMF_RETURN_IF_FALSE(ctx, ret >= 0, ret, "amf_copy_buffer() failed with error %d\n", ret); + + if (ctx->delayed_surface != NULL) { // try to resubmit frame + res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)ctx->delayed_surface); + if (res != AMF_INPUT_FULL) { + int64_t pts = ctx->delayed_surface->pVtbl->GetPts(ctx->delayed_surface); + ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface); + ctx->delayed_surface = NULL; + av_frame_unref(ctx->delayed_frame); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated SubmitInput() failed with error %d\n", res); + + if ((ret = timestamp_queue_enqueue(avctx, pts)) < 0) { + return ret; + } + } else { + av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed frame submission got AMF_INPUT_FULL- should not happen\n"); + } + } else if (ctx->delayed_drain) { // try to resubmit drain + res = ctx->encoder->pVtbl->Drain(ctx->encoder); + if (res != AMF_INPUT_FULL) { + ctx->delayed_drain = 0; + ctx->eof = 1; // drain started + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated Drain() failed with error %d\n", res); + } else { + av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed drain submission got AMF_INPUT_FULL- should not happen\n"); + } + } + } else if (ctx->delayed_surface != NULL || ctx->delayed_drain || (ctx->eof && res_query != AMF_EOF)) { + block_and_wait = 1; + av_usleep(1000); // wait and poll again + } + } while (block_and_wait); + + if (res_query == AMF_EOF) { + ret = AVERROR_EOF; + } else if (data == NULL) { + ret = AVERROR(EAGAIN); + } else { + ret = 0; + } + return ret; +} diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h new file mode 100644 index 0000000000000..f3b82be7704fe --- /dev/null +++ b/libavcodec/amfenc.h @@ -0,0 +1,158 @@ +/* + * AMD AMF support + * Copyright (C) 2017 Luca Barbato + * Copyright (C) 2017 Mikhail Mironov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef AVCODEC_AMFENC_H +#define AVCODEC_AMFENC_H + +#include + +#include +#include + +#include "libavutil/fifo.h" + +#include "config.h" +#include "avcodec.h" + + +/** +* AMF trace writer callback class +* Used to capture all AMF logging +*/ + +typedef struct AmfTraceWriter { + AMFTraceWriterVtbl *vtbl; + AVCodecContext *avctx; +} AmfTraceWriter; + +/** +* AMF encoder context +*/ + +typedef struct AmfContext { + AVClass *avclass; + // access to AMF runtime + amf_handle library; ///< handle to DLL library + AMFFactory *factory; ///< pointer to AMF factory + AMFDebug *debug; ///< pointer to AMF debug interface + AMFTrace *trace; ///< pointer to AMF trace interface + + amf_uint64 version; ///< version of AMF runtime + AmfTraceWriter tracer; ///< AMF writer registered with AMF + AMFContext *context; ///< AMF context + //encoder + AMFComponent *encoder; ///< AMF encoder object + amf_bool eof; ///< flag indicating EOF happened + AMF_SURFACE_FORMAT format; ///< AMF surface format + + AVBufferRef *hw_device_ctx; ///< pointer to HW accelerator (decoder) + AVBufferRef *hw_frames_ctx; ///< pointer to HW accelerator (frame allocator) + + // helpers to handle async calls + int delayed_drain; + AMFSurface *delayed_surface; + AVFrame *delayed_frame; + + // shift dts back by max_b_frames in timing + AVFifoBuffer *timestamp_list; + int64_t timestamp_last; + int64_t dts_delay; + + // common encoder options + int log_to_dbg; + char *writer_id; + + // Static options, have to be set before Init() call + int usage; + int profile; + int level; + int preanalysis; + int quality; + int b_frame_delta_qp; + int ref_b_frame_delta_qp; + + // Dynamic options, can be set after Init() call + + int rate_control_mode; + int enforce_hrd; + int filler_data; + int enable_vbaq; + int skip_frame; + int qp_i; + int qp_p; + int qp_b; + int max_au_size; + int header_spacing; + int b_frame_ref; + int intra_refresh_mb; + int coding_mode; + int me_half_pel; + int me_quarter_pel; + int aud; + + // HEVC - specific options + + int gops_per_idr; + int header_insertion_mode; + int min_qp_i; + int max_qp_i; + int min_qp_p; + int max_qp_p; + int tier; +} AmfContext; + +/** +* Common encoder initization function +*/ +int ff_amf_encode_init(AVCodecContext *avctx); +/** +* Common encoder termination function +*/ +int ff_amf_encode_close(AVCodecContext *avctx); + +/** +* Ecoding one frame - common function for all AMF encoders +*/ + +int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame); +int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); + +/** +* Supported formats +*/ +extern const enum AVPixelFormat ff_amf_pix_fmts[]; + +/** +* Error handling helper +*/ +#define AMF_RETURN_IF_FALSE(avctx, exp, ret_value, /*message,*/ ...) \ + if (!(exp)) { \ + av_log(avctx, AV_LOG_ERROR, __VA_ARGS__); \ + return ret_value; \ + } + +#define AMF_COMMON_OPTIONS \ + { "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, \ + { "writer_id", "Enable AMF logging to writer id", OFFSET(writer_id), AV_OPT_TYPE_STRING, { .str = "libavcodec" }, 0, 1, VE } \ + +#endif //AVCODEC_AMFENC_H diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c new file mode 100644 index 0000000000000..01b0c3a56241f --- /dev/null +++ b/libavcodec/amfenc_h264.c @@ -0,0 +1,400 @@ +/* + * AMD AMF support + * Copyright (C) 2017 Luca Barbato + * Copyright (C) 2017 Mikhail Mironov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "amfenc.h" +#include "internal.h" + +#define OFFSET(x) offsetof(AmfContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM + +static const AVOption options[] = { + // Static + /// Usage + { "usage", "Encoder Usage", OFFSET(usage), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_USAGE_TRANSCONDING }, AMF_VIDEO_ENCODER_USAGE_TRANSCONDING, AMF_VIDEO_ENCODER_USAGE_WEBCAM, VE, "usage" }, + { "transcoding", "Generic Transcoding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_TRANSCONDING }, 0, 0, VE, "usage" }, + { "ultralowlatency","", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY }, 0, 0, VE, "usage" }, + { "lowlatency", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY }, 0, 0, VE, "usage" }, + { "webcam", "Webcam", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_WEBCAM }, 0, 0, VE, "usage" }, + + /// Profile, + { "profile", "Profile", OFFSET(profile),AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_PROFILE_MAIN }, AMF_VIDEO_ENCODER_PROFILE_BASELINE, AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH, VE, "profile" }, + { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_MAIN }, 0, 0, VE, "profile" }, + { "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_HIGH }, 0, 0, VE, "profile" }, + { "constrained_baseline", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_BASELINE }, 0, 0, VE, "profile" }, + { "constrained_high", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH }, 0, 0, VE, "profile" }, + + /// Profile Level + { "level", "Profile Level", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 62, VE, "level" }, + { "auto", "", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "level" }, + { "1.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 10 }, 0, 0, VE, "level" }, + { "1.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 11 }, 0, 0, VE, "level" }, + { "1.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 12 }, 0, 0, VE, "level" }, + { "1.3", "", 0, AV_OPT_TYPE_CONST, { .i64 = 13 }, 0, 0, VE, "level" }, + { "2.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 20 }, 0, 0, VE, "level" }, + { "2.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 21 }, 0, 0, VE, "level" }, + { "2.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 22 }, 0, 0, VE, "level" }, + { "3.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 30 }, 0, 0, VE, "level" }, + { "3.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 31 }, 0, 0, VE, "level" }, + { "3.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 32 }, 0, 0, VE, "level" }, + { "4.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 40 }, 0, 0, VE, "level" }, + { "4.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 41 }, 0, 0, VE, "level" }, + { "4.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 42 }, 0, 0, VE, "level" }, + { "5.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 50 }, 0, 0, VE, "level" }, + { "5.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 51 }, 0, 0, VE, "level" }, + { "5.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 52 }, 0, 0, VE, "level" }, + { "6.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 60 }, 0, 0, VE, "level" }, + { "6.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 61 }, 0, 0, VE, "level" }, + { "6.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 62 }, 0, 0, VE, "level" }, + + + /// Quality Preset + { "quality_preset", "Quality Preference", OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED }, AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED, AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY, VE, "quality_preset" }, + { "speed", "Prefer Speed", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED }, 0, 0, VE, "quality_preset" }, + { "balanced", "Balanced", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED }, 0, 0, VE, "quality_preset" }, + { "quality", "Prefer Quality", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY }, 0, 0, VE, "quality_preset" }, + + // Dynamic + /// Rate Control Method + { "rc", "Rate Control Method", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR, VE, "rc" }, + { "cqp", "Constant Quantization Parameter", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP }, 0, 0, VE, "rc" }, + { "cbr", "Constant Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR }, 0, 0, VE, "rc" }, + { "vbr_peak", "Peak Contrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + { "vbr_latency", "Latency Constrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + + /// Enforce HRD, Filler Data, VBAQ, Frame Skipping + { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "filler_data", "Filler Data Enable", OFFSET(filler_data), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "vbaq", "Enable VBAQ", OFFSET(enable_vbaq), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "frame_skipping", "Rate Control Based Frame Skip", OFFSET(skip_frame), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + + /// QP Values + { "qp_i", "Quantization Parameter for I-Frame", OFFSET(qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "qp_p", "Quantization Parameter for P-Frame", OFFSET(qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "qp_b", "Quantization Parameter for B-Frame", OFFSET(qp_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + + /// Pre-Pass, Pre-Analysis, Two-Pass + { "preanalysis", "Pre-Analysis Mode", OFFSET(preanalysis), AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, 1, VE, NULL }, + + /// Maximum Access Unit Size + { "max_au_size", "Maximum Access Unit Size for rate control (in bits)", OFFSET(max_au_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, + + /// Header Insertion Spacing + { "header_spacing", "Header Insertion Spacing", OFFSET(header_spacing), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1000, VE }, + + /// B-Frames + // BPicturesPattern=bf + { "bf_delta_qp", "B-Picture Delta QP", OFFSET(b_frame_delta_qp), AV_OPT_TYPE_INT, { .i64 = 4 }, -10, 10, VE }, + { "bf_ref", "Enable Reference to B-Frames", OFFSET(b_frame_ref), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, + { "bf_ref_delta_qp","Reference B-Picture Delta QP", OFFSET(ref_b_frame_delta_qp), AV_OPT_TYPE_INT, { .i64 = 4 }, -10, 10, VE }, + + /// Intra-Refresh + { "intra_refresh_mb","Intra Refresh MBs Number Per Slot in Macroblocks", OFFSET(intra_refresh_mb), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, + + /// coder + { "coder", "Coding Type", OFFSET(coding_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_UNDEFINED }, AMF_VIDEO_ENCODER_UNDEFINED, AMF_VIDEO_ENCODER_CALV, VE, "coder" }, + { "auto", "Automatic", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_UNDEFINED }, 0, 0, VE, "coder" }, + { "cavlc", "Context Adaptive Variable-Length Coding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_CALV }, 0, 0, VE, "coder" }, + { "cabac", "Context Adaptive Binary Arithmetic Coding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_CABAC }, 0, 0, VE, "coder" }, + + { "me_half_pel", "Enable ME Half Pixel", OFFSET(me_half_pel), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, + { "me_quarter_pel", "Enable ME Quarter Pixel", OFFSET(me_quarter_pel),AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, + + { "aud", "Inserts AU Delimiter NAL unit", OFFSET(aud) ,AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + + AMF_COMMON_OPTIONS, + + { NULL } +}; + +static av_cold int amf_encode_init_h264(AVCodecContext *avctx) +{ + int ret = 0; + AMF_RESULT res = AMF_OK; + AmfContext *ctx = avctx->priv_data; + AMFVariantStruct var = { 0 }; + amf_int64 profile = 0; + amf_int64 profile_level = 0; + AMFBuffer *buffer; + AMFGuid guid; + AMFRate framerate; + AMFSize framesize = AMFConstructSize(avctx->width, avctx->height); + int deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0; + + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); + } else { + framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num * avctx->ticks_per_frame); + } + + if ((ret = ff_amf_encode_init(avctx)) != 0) + return ret; + + // Static parameters + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_USAGE, ctx->usage); + + AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder, AMF_VIDEO_ENCODER_FRAMESIZE, framesize); + + AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_FRAMERATE, framerate); + + switch (avctx->profile) { + case FF_PROFILE_H264_BASELINE: + profile = AMF_VIDEO_ENCODER_PROFILE_BASELINE; + break; + case FF_PROFILE_H264_MAIN: + profile = AMF_VIDEO_ENCODER_PROFILE_MAIN; + break; + case FF_PROFILE_H264_HIGH: + profile = AMF_VIDEO_ENCODER_PROFILE_HIGH; + break; + case FF_PROFILE_H264_CONSTRAINED_BASELINE: + profile = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_BASELINE; + break; + case (FF_PROFILE_H264_HIGH | FF_PROFILE_H264_CONSTRAINED): + profile = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH; + break; + } + if (profile == 0) { + profile = ctx->profile; + } + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PROFILE, profile); + + profile_level = avctx->level; + if (profile_level == FF_LEVEL_UNKNOWN) { + profile_level = ctx->level; + } + if (profile_level != 0) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PROFILE_LEVEL, profile_level); + } + + // Maximum Reference Frames + if (avctx->refs != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_NUM_REFRAMES, avctx->refs); + } + if (avctx->sample_aspect_ratio.den && avctx->sample_aspect_ratio.num) { + AMFRatio ratio = AMFConstructRatio(avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den); + AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_ASPECT_RATIO, ratio); + } + + /// Color Range (Partial/TV/MPEG or Full/PC/JPEG) + if (avctx->color_range == AVCOL_RANGE_JPEG) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, 1); + } + + // autodetect rate control method + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN) { + if (ctx->qp_i != -1 || ctx->qp_p != -1 || ctx->qp_b != -1) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CQP\n"); + } else if (avctx->rc_max_rate > 0 ) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to Peak VBR\n"); + } else { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n"); + } + } + + + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE, AMF_VIDEO_ENCODER_PREENCODE_DISABLED); + if (ctx->preanalysis) + av_log(ctx, AV_LOG_WARNING, "Pre-Analysis is not supported by cqp Rate Control Method, automatically disabled\n"); + } else { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE, ctx->preanalysis); + } + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUALITY_PRESET, ctx->quality); + + // Dynamic parmaters + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD, ctx->rate_control_mode); + + /// VBV Buffer + if (avctx->rc_buffer_size != 0) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_VBV_BUFFER_SIZE, avctx->rc_buffer_size); + if (avctx->rc_initial_buffer_occupancy != 0) { + int amf_buffer_fullness = avctx->rc_initial_buffer_occupancy * 64 / avctx->rc_buffer_size; + if (amf_buffer_fullness > 64) + amf_buffer_fullness = 64; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_INITIAL_VBV_BUFFER_FULLNESS, amf_buffer_fullness); + } + } + /// Maximum Access Unit Size + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_AU_SIZE, ctx->max_au_size); + + if (ctx->max_au_size) + ctx->enforce_hrd = 1; + + // QP Minimum / Maximum + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, 0); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, 51); + } else { + if (avctx->qmin != -1) { + int qval = avctx->qmin > 51 ? 51 : avctx->qmin; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, qval); + } + if (avctx->qmax != -1) { + int qval = avctx->qmax > 51 ? 51 : avctx->qmax; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, qval); + } + } + // QP Values + if (ctx->qp_i != -1) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_I, ctx->qp_i); + if (ctx->qp_p != -1) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_P, ctx->qp_p); + if (ctx->qp_b != -1) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_B, ctx->qp_b); + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_TARGET_BITRATE, avctx->bit_rate); + + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PEAK_BITRATE, avctx->bit_rate); + } + if (avctx->rc_max_rate) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PEAK_BITRATE, avctx->rc_max_rate); + } else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { + av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); + } + + // Initialize Encoder + res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); + + // Enforce HRD, Filler Data, VBAQ, Frame Skipping, Deblocking Filter + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENFORCE_HRD, !!ctx->enforce_hrd); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE, !!ctx->filler_data); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_SKIP_FRAME_ENABLE, !!ctx->skip_frame); + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, 0); + if (ctx->enable_vbaq) + av_log(ctx, AV_LOG_WARNING, "VBAQ is not supported by cqp Rate Control Method, automatically disabled\n"); + } else { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, !!ctx->enable_vbaq); + } + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, !!deblocking_filter); + + // B-Frames + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, avctx->max_b_frames); + if (res != AMF_OK) { + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, &var); + av_log(ctx, AV_LOG_WARNING, "B-frames=%d is not supported by this GPU, switched to %d\n", + avctx->max_b_frames, (int)var.int64Value); + avctx->max_b_frames = (int)var.int64Value; + } + if (avctx->max_b_frames) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_DELTA_QP, ctx->b_frame_delta_qp); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_B_REFERENCE_ENABLE, !!ctx->b_frame_ref); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP, ctx->ref_b_frame_delta_qp); + } + + // Keyframe Interval + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_IDR_PERIOD, avctx->gop_size); + + // Header Insertion Spacing + if (ctx->header_spacing >= 0) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEADER_INSERTION_SPACING, ctx->header_spacing); + + // Intra-Refresh, Slicing + if (ctx->intra_refresh_mb > 0) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_INTRA_REFRESH_NUM_MBS_PER_SLOT, ctx->intra_refresh_mb); + if (avctx->slices > 1) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_SLICES_PER_FRAME, avctx->slices); + + // Coding + if (ctx->coding_mode != 0) + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_CABAC_ENABLE, ctx->coding_mode); + + // Motion Estimation + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_MOTION_HALF_PIXEL, !!ctx->me_half_pel); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_MOTION_QUARTERPIXEL, !!ctx->me_quarter_pel); + + // fill extradata + res = AMFVariantInit(&var); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res); + + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_EXTRADATA, &var); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) failed with error %d\n", res); + AMF_RETURN_IF_FALSE(ctx, var.pInterface != NULL, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) returned NULL\n"); + + guid = IID_AMFBuffer(); + + res = var.pInterface->pVtbl->QueryInterface(var.pInterface, &guid, (void**)&buffer); // query for buffer interface + if (res != AMF_OK) { + var.pInterface->pVtbl->Release(var.pInterface); + } + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "QueryInterface(IID_AMFBuffer) failed with error %d\n", res); + + avctx->extradata_size = (int)buffer->pVtbl->GetSize(buffer); + avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + buffer->pVtbl->Release(buffer); + var.pInterface->pVtbl->Release(var.pInterface); + return AVERROR(ENOMEM); + } + memcpy(avctx->extradata, buffer->pVtbl->GetNative(buffer), avctx->extradata_size); + + buffer->pVtbl->Release(buffer); + var.pInterface->pVtbl->Release(var.pInterface); + + return 0; +} + +static const AVCodecDefault defaults[] = { + { "refs", "-1" }, + { "aspect", "0" }, + { "qmin", "-1" }, + { "qmax", "-1" }, + { "b", "2M" }, + { "g", "250" }, + { "slices", "1" }, + { NULL }, +}; + +static const AVClass h264_amf_class = { + .class_name = "h264_amf", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_h264_amf_encoder = { + .name = "h264_amf", + .long_name = NULL_IF_CONFIG_SMALL("AMD AMF H.264 Encoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .init = amf_encode_init_h264, + .send_frame = ff_amf_send_frame, + .receive_packet = ff_amf_receive_packet, + .close = ff_amf_encode_close, + .priv_data_size = sizeof(AmfContext), + .priv_class = &h264_amf_class, + .defaults = defaults, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .pix_fmts = ff_amf_pix_fmts, + .wrapper_name = "amf", +}; diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c new file mode 100644 index 0000000000000..fc64decde38d3 --- /dev/null +++ b/libavcodec/amfenc_hevc.c @@ -0,0 +1,332 @@ +/* + * AMD AMF support + * Copyright (C) 2017 Luca Barbato + * Copyright (C) 2017 Mikhail Mironov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "amfenc.h" +#include "internal.h" + +#define OFFSET(x) offsetof(AmfContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "usage", "Set the encoding usage", OFFSET(usage), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING }, AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING, AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM, VE, "usage" }, + { "transcoding", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING }, 0, 0, VE, "usage" }, + { "ultralowlatency","", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY }, 0, 0, VE, "usage" }, + { "lowlatency", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY }, 0, 0, VE, "usage" }, + { "webcam", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM }, 0, 0, VE, "usage" }, + + { "profile", "Set the profile (default main)", OFFSET(profile), AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN }, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN, VE, "profile" }, + { "main", "", 0, AV_OPT_TYPE_CONST,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN }, 0, 0, VE, "profile" }, + + { "profile_tier", "Set the profile tier (default main)", OFFSET(tier), AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN }, AMF_VIDEO_ENCODER_HEVC_TIER_MAIN, AMF_VIDEO_ENCODER_HEVC_TIER_HIGH, VE, "tier" }, + { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN }, 0, 0, VE, "tier" }, + { "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_HIGH }, 0, 0, VE, "tier" }, + + { "level", "Set the encoding level (default auto)", OFFSET(level), AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, AMF_LEVEL_6_2, VE, "level" }, + { "auto", "", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "level" }, + { "1.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_1 }, 0, 0, VE, "level" }, + { "2.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_2 }, 0, 0, VE, "level" }, + { "2.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_2_1 }, 0, 0, VE, "level" }, + { "3.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_3 }, 0, 0, VE, "level" }, + { "3.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_3_1 }, 0, 0, VE, "level" }, + { "4.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_4 }, 0, 0, VE, "level" }, + { "4.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_4_1 }, 0, 0, VE, "level" }, + { "5.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_5 }, 0, 0, VE, "level" }, + { "5.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_5_1 }, 0, 0, VE, "level" }, + { "5.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_5_2 }, 0, 0, VE, "level" }, + { "6.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_6 }, 0, 0, VE, "level" }, + { "6.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_6_1 }, 0, 0, VE, "level" }, + { "6.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_6_2 }, 0, 0, VE, "level" }, + + { "quality_preset", "Set the encoding quality", OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED }, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED, VE, "quality_preset" }, + { "balanced", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED }, 0, 0, VE, "quality_preset" }, + { "speed", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED }, 0, 0, VE, "quality_preset" }, + { "quality", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY }, 0, 0, VE, "quality_preset" }, + + { "rc", "Set the rate control mode", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR, VE, "rc" }, + { "cqp", "Constant Quantization Parameter", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP }, 0, 0, VE, "rc" }, + { "cbr", "Constant Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR }, 0, 0, VE, "rc" }, + { "vbr_peak", "Peak Contrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + { "vbr_latency", "Latency Constrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + + { "header_insertion_mode", "Set header insertion mode", OFFSET(header_insertion_mode), AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE }, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED, VE, "hdrmode" }, + { "none", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE }, 0, 0, VE, "hdrmode" }, + { "gop", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, "hdrmode" }, + { "idr", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED }, 0, 0, VE, "hdrmode" }, + + { "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 60 }, 0, INT_MAX, VE }, + { "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, + { "vbaq", "Enable VBAQ", OFFSET(enable_vbaq), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, + { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, + { "filler_data", "Filler Data Enable", OFFSET(filler_data), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, + { "max_au_size", "Maximum Access Unit Size for rate control (in bits)", OFFSET(max_au_size), AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, INT_MAX, VE}, + { "min_qp_i", "min quantization parameter for I-frame", OFFSET(min_qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "max_qp_i", "max quantization parameter for I-frame", OFFSET(max_qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "min_qp_p", "min quantization parameter for P-frame", OFFSET(min_qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "max_qp_p", "max quantization parameter for P-frame", OFFSET(max_qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "qp_p", "quantization parameter for P-frame", OFFSET(qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "qp_i", "quantization parameter for I-frame", OFFSET(qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "skip_frame", "Rate Control Based Frame Skip", OFFSET(skip_frame), AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, 1, VE }, + { "me_half_pel", "Enable ME Half Pixel", OFFSET(me_half_pel), AV_OPT_TYPE_INT,{ .i64 = 1 }, 0, 1, VE }, + { "me_quarter_pel", "Enable ME Quarter Pixel ", OFFSET(me_quarter_pel),AV_OPT_TYPE_INT,{ .i64 = 1 }, 0, 1, VE }, + + { "aud", "Inserts AU Delimiter NAL unit", OFFSET(aud) ,AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, 1, VE }, + + AMF_COMMON_OPTIONS, + + { NULL } +}; + +static av_cold int amf_encode_init_hevc(AVCodecContext *avctx) +{ + int ret = 0; + AMF_RESULT res = AMF_OK; + AmfContext *ctx = avctx->priv_data; + AMFVariantStruct var = {0}; + amf_int64 profile = 0; + amf_int64 profile_level = 0; + AMFBuffer *buffer; + AMFGuid guid; + AMFRate framerate; + AMFSize framesize = AMFConstructSize(avctx->width, avctx->height); + int deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0; + + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); + } else { + framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num * avctx->ticks_per_frame); + } + + if ((ret = ff_amf_encode_init(avctx)) < 0) + return ret; + + // init static parameters + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_USAGE, ctx->usage); + + AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FRAMESIZE, framesize); + + AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FRAMERATE, framerate); + + switch (avctx->profile) { + case FF_PROFILE_HEVC_MAIN: + profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN; + break; + default: + break; + } + if (profile == 0) { + profile = ctx->profile; + } + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PROFILE, profile); + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TIER, ctx->tier); + + profile_level = avctx->level; + if (profile_level == 0) { + profile_level = ctx->level; + } + if (profile_level != 0) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PROFILE_LEVEL, profile_level); + } + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET, ctx->quality); + // Maximum Reference Frames + if (avctx->refs != 0) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_NUM_REFRAMES, avctx->refs); + } + // Aspect Ratio + if (avctx->sample_aspect_ratio.den && avctx->sample_aspect_ratio.num) { + AMFRatio ratio = AMFConstructRatio(avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den); + AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO, ratio); + } + + // Picture control properties + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NUM_GOPS_PER_IDR, ctx->gops_per_idr); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, avctx->gop_size); + if (avctx->slices > 1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_SLICES_PER_FRAME, avctx->slices); + } + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_DE_BLOCKING_FILTER_DISABLE, deblocking_filter); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE, ctx->header_insertion_mode); + + // Rate control + // autodetect rate control method + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN) { + if (ctx->min_qp_i != -1 || ctx->max_qp_i != -1 || + ctx->min_qp_p != -1 || ctx->max_qp_p != -1 || + ctx->qp_i !=-1 || ctx->qp_p != -1) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CQP\n"); + } else if (avctx->rc_max_rate > 0) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to Peak VBR\n"); + } else { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n"); + } + } + + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD, ctx->rate_control_mode); + if (avctx->rc_buffer_size) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_VBV_BUFFER_SIZE, avctx->rc_buffer_size); + + if (avctx->rc_initial_buffer_occupancy != 0) { + int amf_buffer_fullness = avctx->rc_initial_buffer_occupancy * 64 / avctx->rc_buffer_size; + if (amf_buffer_fullness > 64) + amf_buffer_fullness = 64; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_INITIAL_VBV_BUFFER_FULLNESS, amf_buffer_fullness); + } + } + // Pre-Pass, Pre-Analysis, Two-Pass + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_PREANALYSIS_ENABLE, ctx->preanalysis); + + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, false); + if (ctx->enable_vbaq) + av_log(ctx, AV_LOG_WARNING, "VBAQ is not supported by cqp Rate Control Method, automatically disabled\n"); + } else { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, !!ctx->enable_vbaq); + } + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MOTION_HALF_PIXEL, ctx->me_half_pel); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MOTION_QUARTERPIXEL, ctx->me_quarter_pel); + + // init dynamic rate control params + if (ctx->max_au_size) + ctx->enforce_hrd = 1; + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENFORCE_HRD, ctx->enforce_hrd); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FILLER_DATA_ENABLE, ctx->filler_data); + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TARGET_BITRATE, avctx->bit_rate); + + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE, avctx->bit_rate); + } + if (avctx->rc_max_rate) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE, avctx->rc_max_rate); + } else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { + av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); + } + + // init encoder + res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); + + // init dynamic picture control params + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_AU_SIZE, ctx->max_au_size); + + if (ctx->min_qp_i != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, ctx->min_qp_i); + } else if (avctx->qmin != -1) { + int qval = avctx->qmin > 51 ? 51 : avctx->qmin; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, qval); + } + if (ctx->max_qp_i != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, ctx->max_qp_i); + } else if (avctx->qmax != -1) { + int qval = avctx->qmax > 51 ? 51 : avctx->qmax; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, qval); + } + if (ctx->min_qp_p != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, ctx->min_qp_p); + } else if (avctx->qmin != -1) { + int qval = avctx->qmin > 51 ? 51 : avctx->qmin; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, qval); + } + if (ctx->max_qp_p != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, ctx->max_qp_p); + } else if (avctx->qmax != -1) { + int qval = avctx->qmax > 51 ? 51 : avctx->qmax; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, qval); + } + + if (ctx->qp_p != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_I, ctx->qp_p); + } + if (ctx->qp_i != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_P, ctx->qp_i); + } + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_SKIP_FRAME_ENABLE, ctx->skip_frame); + + + // fill extradata + res = AMFVariantInit(&var); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res); + + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_HEVC_EXTRADATA, &var); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) failed with error %d\n", res); + AMF_RETURN_IF_FALSE(ctx, var.pInterface != NULL, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) returned NULL\n"); + + guid = IID_AMFBuffer(); + + res = var.pInterface->pVtbl->QueryInterface(var.pInterface, &guid, (void**)&buffer); // query for buffer interface + if (res != AMF_OK) { + var.pInterface->pVtbl->Release(var.pInterface); + } + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "QueryInterface(IID_AMFBuffer) failed with error %d\n", res); + + avctx->extradata_size = (int)buffer->pVtbl->GetSize(buffer); + avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + buffer->pVtbl->Release(buffer); + var.pInterface->pVtbl->Release(var.pInterface); + return AVERROR(ENOMEM); + } + memcpy(avctx->extradata, buffer->pVtbl->GetNative(buffer), avctx->extradata_size); + + buffer->pVtbl->Release(buffer); + var.pInterface->pVtbl->Release(var.pInterface); + + return 0; +} +static const AVCodecDefault defaults[] = { + { "refs", "-1" }, + { "aspect", "0" }, + { "b", "2M" }, + { "g", "250" }, + { "slices", "1" }, + { NULL }, +}; +static const AVClass hevc_amf_class = { + .class_name = "hevc_amf", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_hevc_amf_encoder = { + .name = "hevc_amf", + .long_name = NULL_IF_CONFIG_SMALL("AMD AMF HEVC encoder"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HEVC, + .init = amf_encode_init_hevc, + .send_frame = ff_amf_send_frame, + .receive_packet = ff_amf_receive_packet, + .close = ff_amf_encode_close, + .priv_data_size = sizeof(AmfContext), + .priv_class = &hevc_amf_class, + .defaults = defaults, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .pix_fmts = ff_amf_pix_fmts, + .wrapper_name = "amf", +}; From b4eeffffc8933f04d3a951577b9b8e0b128ef580 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 4 Jan 2018 01:34:14 -0300 Subject: [PATCH 1541/2557] configure: update minimum required version of libvmaf At least version 0.6.2 is needed since commit df3222d4bb18cbceda443def17b1b29067ed6e3f. Reviewed-by: Ronald S. Bultje Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 1d2fffa132928..26da82072d349 100755 --- a/configure +++ b/configure @@ -5911,7 +5911,7 @@ enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit -enabled libvmaf && require_pkg_config libvmaf libvmaf libvmaf.h compute_vmaf +enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 0.6.2" libvmaf.h compute_vmaf enabled libvo_amrwbenc && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc enabled libvorbis && require_pkg_config libvorbis vorbis vorbis/codec.h vorbis_info_init && require_pkg_config libvorbisenc vorbisenc vorbis/vorbisenc.h vorbis_encode_init From 414a49d6710d90c0943c152a8d7bd521e1627125 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 4 Jan 2018 00:46:33 -0300 Subject: [PATCH 1542/2557] ffmpeg: use thread wrappers for the thread message functionality Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- fftools/ffmpeg.c | 19 ++++++++----------- fftools/ffmpeg.h | 7 ++----- fftools/ffmpeg_opt.c | 2 +- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 6aff3366c5617..528849a2c6636 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -61,6 +61,7 @@ #include "libavutil/timestamp.h" #include "libavutil/bprint.h" #include "libavutil/time.h" +#include "libavutil/thread.h" #include "libavutil/threadmessage.h" #include "libavcodec/mathops.h" #include "libavformat/os_support.h" @@ -98,10 +99,6 @@ #include #endif -#if HAVE_PTHREADS -#include -#endif - #include #include "ffmpeg.h" @@ -161,7 +158,7 @@ static struct termios oldtty; static int restore_tty; #endif -#if HAVE_PTHREADS +#if HAVE_THREADS static void free_input_threads(void); #endif @@ -578,7 +575,7 @@ static void ffmpeg_cleanup(int ret) av_freep(&output_streams[i]); } -#if HAVE_PTHREADS +#if HAVE_THREADS free_input_threads(); #endif for (i = 0; i < nb_input_files; i++) { @@ -3996,7 +3993,7 @@ static int check_keyboard_interaction(int64_t cur_time) return 0; } -#if HAVE_PTHREADS +#if HAVE_THREADS static void *input_thread(void *arg) { InputFile *f = arg; @@ -4106,7 +4103,7 @@ static int get_input_packet(InputFile *f, AVPacket *pkt) } } -#if HAVE_PTHREADS +#if HAVE_THREADS if (nb_input_files > 1) return get_input_packet_mt(f, pkt); #endif @@ -4615,7 +4612,7 @@ static int transcode(void) timer_start = av_gettime_relative(); -#if HAVE_PTHREADS +#if HAVE_THREADS if ((ret = init_input_threads()) < 0) goto fail; #endif @@ -4646,7 +4643,7 @@ static int transcode(void) /* dump report by using the output first video and audio streams */ print_report(0, timer_start, cur_time); } -#if HAVE_PTHREADS +#if HAVE_THREADS free_input_threads(); #endif @@ -4712,7 +4709,7 @@ static int transcode(void) ret = 0; fail: -#if HAVE_PTHREADS +#if HAVE_THREADS free_input_threads(); #endif diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 4e73d59082e39..8195f73e8b25e 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -25,10 +25,6 @@ #include #include -#if HAVE_PTHREADS -#include -#endif - #include "cmdutils.h" #include "libavformat/avformat.h" @@ -45,6 +41,7 @@ #include "libavutil/hwcontext.h" #include "libavutil/pixfmt.h" #include "libavutil/rational.h" +#include "libavutil/thread.h" #include "libavutil/threadmessage.h" #include "libswresample/swresample.h" @@ -415,7 +412,7 @@ typedef struct InputFile { int rate_emu; int accurate_seek; -#if HAVE_PTHREADS +#if HAVE_THREADS AVThreadMessageQueue *in_thread_queue; pthread_t thread; /* thread reading from this file */ int non_blocking; /* reading packets from the thread should not block */ diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index a6e36ac8229df..754c297b93f62 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1161,7 +1161,7 @@ static int open_input_file(OptionsContext *o, const char *filename) f->loop = o->loop; f->duration = 0; f->time_base = (AVRational){ 1, 1 }; -#if HAVE_PTHREADS +#if HAVE_THREADS f->thread_queue_size = o->thread_queue_size > 0 ? o->thread_queue_size : 8; #endif From 8d9c9775b248b0a0f43bd96a242b5311fcc28b72 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 4 Jan 2018 01:11:43 -0300 Subject: [PATCH 1543/2557] avutil/log: use thread wrappers for the locking functionality w32threads and os2threads both support static mutex initialization now, so don't limit it to pthreads only. Reviewed-by: wm4 Signed-off-by: James Almer --- libavutil/log.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/libavutil/log.c b/libavutil/log.c index 7a6dd936e55f3..bd47f2a25f3f6 100644 --- a/libavutil/log.c +++ b/libavutil/log.c @@ -39,11 +39,9 @@ #include "common.h" #include "internal.h" #include "log.h" +#include "thread.h" -#if HAVE_PTHREADS -#include -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -#endif +static AVMutex mutex = AV_MUTEX_INITIALIZER; #define LINE_SZ 1024 @@ -317,9 +315,7 @@ void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl) if (level > av_log_level) return; -#if HAVE_PTHREADS - pthread_mutex_lock(&mutex); -#endif + ff_mutex_lock(&mutex); format_line(ptr, level, fmt, vl, part, &print_prefix, type); snprintf(line, sizeof(line), "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str); @@ -356,9 +352,7 @@ void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl) #endif end: av_bprint_finalize(part+3, NULL); -#if HAVE_PTHREADS - pthread_mutex_unlock(&mutex); -#endif + ff_mutex_unlock(&mutex); } static void (*av_log_callback)(void*, int, const char*, va_list) = From fde057dfb25e2b6917fc896a0b2dfec0f336b1ce Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Wed, 3 Jan 2018 19:14:22 +1100 Subject: [PATCH 1544/2557] aiff: add support for XA ADPCM Certain AIFF files encode XA ADPCM compressed audio using a chunk with the tag `APCM`. Aside from this custom chunk type, they're otherwise standard AIFF files. I've only observed these files in the Sega Saturn game Sonic Jam so far. Signed-off-by: Michael Niedermayer --- libavformat/aiffdec.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index 99e05c78ecac3..a6c180fc8da72 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -325,6 +325,13 @@ static int aiff_read_header(AVFormatContext *s) if(ff_mov_read_chan(s, pb, st, size) < 0) return AVERROR_INVALIDDATA; break; + case MKTAG('A','P','C','M'): /* XA ADPCM compressed sound chunk */ + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_XA; + aiff->data_end = avio_tell(pb) + size; + offset = avio_tell(pb) + 8; + /* This field is unknown and its data seems to be irrelevant */ + avio_rb32(pb); + st->codecpar->block_align = avio_rb32(pb); case 0: if (offset > 0 && st->codecpar->block_align) // COMM && SSND goto got_sound; From f528c49c7cd10bfb7f639c467e11bb624be71eef Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Fri, 22 Dec 2017 00:18:25 +0100 Subject: [PATCH 1545/2557] avfilter/vf_framerate: calculate interpolation as integer It was truncated to int later on anyway. Fate test changes are due to rounding instead of truncation. Fixes fate test failures on x86-32 (gcc 4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1)) after 090b740680f91e0f2bf07423c36df7166740e8f6. Signed-off-by: Marton Balint --- libavfilter/vf_framerate.c | 22 +++++++----- tests/ref/fate/filter-framerate-12bit-down | 40 +++++++++++----------- tests/ref/fate/filter-framerate-12bit-up | 40 +++++++++++----------- tests/ref/fate/filter-framerate-up | 4 +-- 4 files changed, 55 insertions(+), 51 deletions(-) diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index 1336ea04695af..38f45a8033c13 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -47,8 +47,10 @@ typedef struct FrameRateContext { AVRational dest_frame_rate; ///< output frames per second int flags; ///< flags affecting frame rate conversion algorithm double scene_score; ///< score that denotes a scene change has happened - int interp_start; ///< start of range to apply linear interpolation - int interp_end; ///< end of range to apply linear interpolation + int interp_start; ///< start of range to apply linear interpolation (same bitdepth as input) + int interp_end; ///< end of range to apply linear interpolation (same bitdepth as input) + int interp_start_param; ///< start of range to apply linear interpolation + int interp_end_param; ///< end of range to apply linear interpolation int line_size[4]; ///< bytes of pixel data per line for each plane int vsub; @@ -87,8 +89,8 @@ typedef struct FrameRateContext { static const AVOption framerate_options[] = { {"fps", "required output frames per second rate", OFFSET(dest_frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="50"}, 0, INT_MAX, V|F }, - {"interp_start", "point to start linear interpolation", OFFSET(interp_start), AV_OPT_TYPE_INT, {.i64=15}, 0, 255, V|F }, - {"interp_end", "point to end linear interpolation", OFFSET(interp_end), AV_OPT_TYPE_INT, {.i64=240}, 0, 255, V|F }, + {"interp_start", "point to start linear interpolation", OFFSET(interp_start_param),AV_OPT_TYPE_INT, {.i64=15}, 0, 255, V|F }, + {"interp_end", "point to end linear interpolation", OFFSET(interp_end_param), AV_OPT_TYPE_INT, {.i64=240}, 0, 255, V|F }, {"scene", "scene change level", OFFSET(scene_score), AV_OPT_TYPE_DOUBLE, {.dbl=8.2}, 0, INT_MAX, V|F }, {"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, INT_MAX, V|F, "flags" }, @@ -305,7 +307,7 @@ static int filter_slice16(AVFilterContext *ctx, void *arg, int job, int nb_jobs) return 0; } -static int blend_frames(AVFilterContext *ctx, float interpolate, +static int blend_frames(AVFilterContext *ctx, int interpolate, int src1, int src2) { FrameRateContext *s = ctx->priv; @@ -326,7 +328,7 @@ static int blend_frames(AVFilterContext *ctx, float interpolate, ThreadData td; td.copy_src1 = s->srce[src1]; td.copy_src2 = s->srce[src2]; - td.src2_factor = fabsf(interpolate) * (1 << (s->bitdepth - 8)); + td.src2_factor = FFABS(interpolate); td.src1_factor = s->max - td.src2_factor; // get work-space for output frame @@ -347,7 +349,7 @@ static int process_work_frame(AVFilterContext *ctx, int stop) { FrameRateContext *s = ctx->priv; int64_t work_next_pts; - float interpolate; + int interpolate; int src1, src2; ff_dlog(ctx, "process_work_frame()\n"); @@ -390,8 +392,8 @@ static int process_work_frame(AVFilterContext *ctx, int stop) } // calculate interpolation - interpolate = ((s->pts - s->srce_pts_dest[s->crnt]) * 256.0 / s->average_srce_pts_dest_delta); - ff_dlog(ctx, "process_work_frame() interpolate:%f/256\n", interpolate); + interpolate = av_rescale(s->pts - s->srce_pts_dest[s->crnt], s->max, s->average_srce_pts_dest_delta); + ff_dlog(ctx, "process_work_frame() interpolate:%d/%d\n", interpolate, s->max); src1 = s->crnt; if (interpolate > s->interp_end) { ff_dlog(ctx, "process_work_frame() source is:NEXT\n"); @@ -572,6 +574,8 @@ static int config_input(AVFilterLink *inlink) s->bitdepth = pix_desc->comp[0].depth; s->vsub = pix_desc->log2_chroma_h; + s->interp_start = s->interp_start_param << (s->bitdepth - 8); + s->interp_end = s->interp_end_param << (s->bitdepth - 8); s->sad = av_pixelutils_get_sad_fn(3, 3, 2, s); // 8x8 both sources aligned if (!s->sad) diff --git a/tests/ref/fate/filter-framerate-12bit-down b/tests/ref/fate/filter-framerate-12bit-down index 0a9aea0ce1f11..49dcb1e5fa492 100644 --- a/tests/ref/fate/filter-framerate-12bit-down +++ b/tests/ref/fate/filter-framerate-12bit-down @@ -6,50 +6,50 @@ 0, 0, 0, 1, 307200, 0xb49cf016 0, 1, 1, 1, 307200, 0xc3be6971 0, 2, 2, 1, 307200, 0x4d458da1 -0, 3, 3, 1, 307200, 0x35d4d8ea -0, 4, 4, 1, 307200, 0x88f88697 +0, 3, 3, 1, 307200, 0xb49ed940 +0, 4, 4, 1, 307200, 0x1577849f 0, 5, 5, 1, 307200, 0xaf71e7fc 0, 6, 6, 1, 307200, 0x1290a487 0, 7, 7, 1, 307200, 0xaf0cf5ee -0, 8, 8, 1, 307200, 0x9fe73a9b -0, 9, 9, 1, 307200, 0xb7965b77 +0, 8, 8, 1, 307200, 0x6ffb3abb +0, 9, 9, 1, 307200, 0x9e65597e 0, 10, 10, 1, 307200, 0x9f84df5d 0, 11, 11, 1, 307200, 0xf60b8c87 0, 12, 12, 1, 307200, 0xe2eac3a7 -0, 13, 13, 1, 307200, 0xefbbc67a -0, 14, 14, 1, 307200, 0xb293001a +0, 13, 13, 1, 307200, 0x2c4ac771 +0, 14, 14, 1, 307200, 0xf4d9003d 0, 15, 15, 1, 307200, 0xab2162fc 0, 16, 16, 1, 307200, 0xdc90848a 0, 17, 17, 1, 307200, 0x29f79f4b -0, 18, 18, 1, 307200, 0x62aee029 -0, 19, 19, 1, 307200, 0xcb6de0e9 +0, 18, 18, 1, 307200, 0x45b1e01b +0, 19, 19, 1, 307200, 0x43baddc2 0, 20, 20, 1, 307200, 0xf2b12fe5 0, 21, 21, 1, 307200, 0x1de67e13 0, 22, 22, 1, 307200, 0xfc1f7774 -0, 23, 23, 1, 307200, 0x707fe832 -0, 24, 24, 1, 307200, 0xe2dc0742 +0, 23, 23, 1, 307200, 0x5552e7f2 +0, 24, 24, 1, 307200, 0xb1d60366 0, 25, 25, 1, 307200, 0x4693ab03 0, 26, 26, 1, 307200, 0x7295ef7a 0, 27, 27, 1, 307200, 0xf442a5df -0, 28, 28, 1, 307200, 0x3019dbbc -0, 29, 29, 1, 307200, 0xd82a394d +0, 28, 28, 1, 307200, 0x01e0dbb8 +0, 29, 29, 1, 307200, 0xf10c3549 0, 30, 30, 1, 307200, 0x8a512668 0, 31, 31, 1, 307200, 0x69e7b43e 0, 32, 32, 1, 307200, 0x6c5343ca -0, 33, 33, 1, 307200, 0x8aac4531 -0, 34, 34, 1, 307200, 0x4b7f5b63 +0, 33, 33, 1, 307200, 0xf323456c +0, 34, 34, 1, 307200, 0xeead5632 0, 35, 35, 1, 307200, 0x4e24d659 0, 36, 36, 1, 307200, 0x7a25b546 0, 37, 37, 1, 307200, 0x9b7e8e8f -0, 38, 38, 1, 307200, 0x94ec9d3d -0, 39, 39, 1, 307200, 0x856ea560 +0, 38, 38, 1, 307200, 0x9d059d4c +0, 39, 39, 1, 307200, 0x21c4a16f 0, 40, 40, 1, 307200, 0xb6505ff0 0, 41, 41, 1, 307200, 0x12562a42 0, 42, 42, 1, 307200, 0x3335e451 -0, 43, 43, 1, 307200, 0x7f0374c9 -0, 44, 44, 1, 307200, 0x487e798a +0, 43, 43, 1, 307200, 0x6f1274cf +0, 44, 44, 1, 307200, 0xa52e71d2 0, 45, 45, 1, 307200, 0x4fda2634 0, 46, 46, 1, 307200, 0x5b48d624 0, 47, 47, 1, 307200, 0xa9505af8 -0, 48, 48, 1, 307200, 0xce7248b5 -0, 49, 49, 1, 307200, 0x8fbc1bec +0, 48, 48, 1, 307200, 0xc2624880 +0, 49, 49, 1, 307200, 0x4eb317a5 diff --git a/tests/ref/fate/filter-framerate-12bit-up b/tests/ref/fate/filter-framerate-12bit-up index 8f5f95b275cab..686fe8e82bd71 100644 --- a/tests/ref/fate/filter-framerate-12bit-up +++ b/tests/ref/fate/filter-framerate-12bit-up @@ -4,61 +4,61 @@ #dimensions 0: 320x240 #sar 0: 1/1 0, 0, 0, 1, 307200, 0xb49cf016 -0, 1, 1, 1, 307200, 0x59cb92c7 +0, 1, 1, 1, 307200, 0xbe4390ed 0, 2, 2, 1, 307200, 0xe4ca172c 0, 3, 3, 1, 307200, 0x5378b13c -0, 4, 4, 1, 307200, 0x2a7d4840 +0, 4, 4, 1, 307200, 0xe742454c 0, 5, 5, 1, 307200, 0x68f620cd 0, 6, 6, 1, 307200, 0x83dbe321 -0, 7, 7, 1, 307200, 0xcd73c6ab +0, 7, 7, 1, 307200, 0x7135c77d 0, 8, 8, 1, 307200, 0xc69a864a 0, 9, 9, 1, 307200, 0xc5c8b0f8 -0, 10, 10, 1, 307200, 0xf08a6033 +0, 10, 10, 1, 307200, 0xf6ee5d1c 0, 11, 11, 1, 307200, 0xab36763c 0, 12, 12, 1, 307200, 0xcba4c6bb -0, 13, 13, 1, 307200, 0x8dabc7b5 +0, 13, 13, 1, 307200, 0xb379c679 0, 14, 14, 1, 307200, 0x63339757 0, 15, 15, 1, 307200, 0x4bdfd3ca -0, 16, 16, 1, 307200, 0x699c9c83 +0, 16, 16, 1, 307200, 0x14e09691 0, 17, 17, 1, 307200, 0x5dc7c711 0, 18, 18, 1, 307200, 0xda8c6c41 -0, 19, 19, 1, 307200, 0xeb4ac99c +0, 19, 19, 1, 307200, 0xe187c6b6 0, 20, 20, 1, 307200, 0x5d8b76ab 0, 21, 21, 1, 307200, 0xe2337c57 -0, 22, 22, 1, 307200, 0x84531dcf +0, 22, 22, 1, 307200, 0x492117d7 0, 23, 23, 1, 307200, 0xf0df5ea3 0, 24, 24, 1, 307200, 0x4237e892 -0, 25, 25, 1, 307200, 0xc111a9eb +0, 25, 25, 1, 307200, 0x4f61a7d7 0, 26, 26, 1, 307200, 0x2ba55745 0, 27, 27, 1, 307200, 0x0e058165 -0, 28, 28, 1, 307200, 0xd184f860 +0, 28, 28, 1, 307200, 0xe371f352 0, 29, 29, 1, 307200, 0xab562bfe 0, 30, 30, 1, 307200, 0x0b58bcf7 -0, 31, 31, 1, 307200, 0x044f4a16 +0, 31, 31, 1, 307200, 0xf1a04a1e 0, 32, 32, 1, 307200, 0xb466f1d6 0, 33, 33, 1, 307200, 0x3ed6b5d8 -0, 34, 34, 1, 307200, 0xb8b82049 +0, 34, 34, 1, 307200, 0x05091a43 0, 35, 35, 1, 307200, 0xbfb20efc 0, 36, 36, 1, 307200, 0xbd67248a -0, 37, 37, 1, 307200, 0x76e11928 +0, 37, 37, 1, 307200, 0x58001b29 0, 38, 38, 1, 307200, 0x6ec5bbb1 0, 39, 39, 1, 307200, 0x0e4455cd -0, 40, 40, 1, 307200, 0x5ccf33fb +0, 40, 40, 1, 307200, 0x5c2c3213 0, 41, 41, 1, 307200, 0x976f6900 0, 42, 42, 1, 307200, 0x58adad3f -0, 43, 43, 1, 307200, 0x1f791403 +0, 43, 43, 1, 307200, 0x8dbb14f0 0, 44, 44, 1, 307200, 0x49163226 0, 45, 45, 1, 307200, 0xaac8e1ca -0, 46, 46, 1, 307200, 0x7fe784f7 +0, 46, 46, 1, 307200, 0x07cc8404 0, 47, 47, 1, 307200, 0xbf85c994 0, 48, 48, 1, 307200, 0x22ed5b5a -0, 49, 49, 1, 307200, 0xdbeee1f3 +0, 49, 49, 1, 307200, 0x1bf7df1e 0, 50, 50, 1, 307200, 0x3a21b4d2 0, 51, 51, 1, 307200, 0xbd5edb2d -0, 52, 52, 1, 307200, 0xc66d8b27 +0, 52, 52, 1, 307200, 0x336a8437 0, 53, 53, 1, 307200, 0x02c7e528 0, 54, 54, 1, 307200, 0xba073e6f -0, 55, 55, 1, 307200, 0xf745ded7 +0, 55, 55, 1, 307200, 0x9e25ddfe 0, 56, 56, 1, 307200, 0x8cf55128 0, 57, 57, 1, 307200, 0x4e740b42 -0, 58, 58, 1, 307200, 0x7906723a +0, 58, 58, 1, 307200, 0x8e7e705c diff --git a/tests/ref/fate/filter-framerate-up b/tests/ref/fate/filter-framerate-up index b2af9cb879df5..15bf6d815ba09 100644 --- a/tests/ref/fate/filter-framerate-up +++ b/tests/ref/fate/filter-framerate-up @@ -6,10 +6,10 @@ 0, 0, 0, 1, 115200, 0x3744b3ed 0, 1, 1, 1, 115200, 0xc44bdc65 0, 2, 2, 1, 115200, 0xa17f0d74 -0, 3, 3, 1, 115200, 0xb0c83274 +0, 3, 3, 1, 115200, 0xd72532a9 0, 4, 4, 1, 115200, 0x232d6368 0, 5, 5, 1, 115200, 0x6e318ba0 0, 6, 6, 1, 115200, 0x247e846e 0, 7, 7, 1, 115200, 0x89e27599 -0, 8, 8, 1, 115200, 0x31c5704e +0, 8, 8, 1, 115200, 0x68536eac 0, 9, 9, 1, 115200, 0x97e45fec From d36335bda5e5eff317240c098337cbfc57906897 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 4 Jan 2018 15:11:32 -0300 Subject: [PATCH 1546/2557] avcodec/parser: use a mutex instead of atomics in av_register_codec_parser() Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavcodec/parser.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libavcodec/parser.c b/libavcodec/parser.c index 670680ea7c1d4..747ea2ee8aaca 100644 --- a/libavcodec/parser.c +++ b/libavcodec/parser.c @@ -25,9 +25,9 @@ #include #include "libavutil/avassert.h" -#include "libavutil/atomic.h" #include "libavutil/internal.h" #include "libavutil/mem.h" +#include "libavutil/thread.h" #include "internal.h" #include "parser.h" @@ -42,11 +42,14 @@ AVCodecParser *av_parser_next(const AVCodecParser *p) return av_first_parser; } +static AVMutex parser_register_mutex = AV_MUTEX_INITIALIZER; + void av_register_codec_parser(AVCodecParser *parser) { - do { - parser->next = av_first_parser; - } while (parser->next != avpriv_atomic_ptr_cas((void * volatile *)&av_first_parser, parser->next, parser)); + ff_mutex_lock(&parser_register_mutex); + parser->next = av_first_parser; + av_first_parser = parser; + ff_mutex_unlock(&parser_register_mutex); } AVCodecParserContext *av_parser_init(int codec_id) From 206b25f9f45a7a0e408338f9f6ab022ff2efb196 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Thu, 30 Nov 2017 10:31:38 +0100 Subject: [PATCH 1547/2557] avfilter: reorder variable definition in geq Signed-off-by: Michael Niedermayer --- libavfilter/vf_geq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_geq.c b/libavfilter/vf_geq.c index 36dbd421ce16c..0bd81fd586449 100644 --- a/libavfilter/vf_geq.c +++ b/libavfilter/vf_geq.c @@ -33,6 +33,9 @@ #include "libavutil/pixdesc.h" #include "internal.h" +static const char *const var_names[] = { "X", "Y", "W", "H", "N", "SW", "SH", "T", NULL }; +enum { VAR_X, VAR_Y, VAR_W, VAR_H, VAR_N, VAR_SW, VAR_SH, VAR_T, VAR_VARS_NB }; + typedef struct GEQContext { const AVClass *class; AVExpr *e[4]; ///< expressions for each plane @@ -107,9 +110,6 @@ static double cb(void *priv, double x, double y) { return getpix(priv, x, y, 1) static double cr(void *priv, double x, double y) { return getpix(priv, x, y, 2); } static double alpha(void *priv, double x, double y) { return getpix(priv, x, y, 3); } -static const char *const var_names[] = { "X", "Y", "W", "H", "N", "SW", "SH", "T", NULL }; -enum { VAR_X, VAR_Y, VAR_W, VAR_H, VAR_N, VAR_SW, VAR_SH, VAR_T, VAR_VARS_NB }; - static av_cold int geq_init(AVFilterContext *ctx) { GEQContext *geq = ctx->priv; From ac6b0bba79fe4de1281e0f2058646bee23d90224 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Thu, 4 Jan 2018 08:49:55 +0100 Subject: [PATCH 1548/2557] avfilter: slice processing for geq Signed-off-by: Michael Niedermayer --- libavfilter/vf_geq.c | 111 +++++++++++++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 31 deletions(-) diff --git a/libavfilter/vf_geq.c b/libavfilter/vf_geq.c index 0bd81fd586449..0651ed0b36aba 100644 --- a/libavfilter/vf_geq.c +++ b/libavfilter/vf_geq.c @@ -41,6 +41,9 @@ typedef struct GEQContext { AVExpr *e[4]; ///< expressions for each plane char *expr_str[4+3]; ///< expression strings for each plane AVFrame *picref; ///< current input buffer + uint8_t *dst; ///< reference pointer to the 8bits output + uint16_t *dst16; ///< reference pointer to the 16bits output + double values[VAR_VARS_NB]; ///< expression values int hsub, vsub; ///< chroma subsampling int planes; ///< number of planes int is_rgb; @@ -226,8 +229,62 @@ static int geq_config_props(AVFilterLink *inlink) geq->hsub = desc->log2_chroma_w; geq->vsub = desc->log2_chroma_h; + geq->bps = desc->comp[0].depth; geq->planes = desc->nb_components; - geq->bps = desc->comp[0].depth; + return 0; +} + +typedef struct ThreadData { + int height; + int width; + int plane; + int linesize; +} ThreadData; + +static int slice_geq_filter(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + GEQContext *geq = ctx->priv; + ThreadData *td = arg; + const int height = td->height; + const int width = td->width; + const int plane = td->plane; + const int linesize = td->linesize; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr+1)) / nb_jobs; + int x, y; + uint8_t *ptr; + uint16_t *ptr16; + + double values[VAR_VARS_NB]; + values[VAR_W] = geq->values[VAR_W]; + values[VAR_H] = geq->values[VAR_H]; + values[VAR_N] = geq->values[VAR_N]; + values[VAR_SW] = geq->values[VAR_SW]; + values[VAR_SH] = geq->values[VAR_SH]; + values[VAR_T] = geq->values[VAR_T]; + + if (geq->bps == 8) { + for (y = slice_start; y < slice_end; y++) { + ptr = geq->dst + linesize * y; + values[VAR_Y] = y; + + for (x = 0; x < width; x++) { + values[VAR_X] = x; + ptr[x] = av_expr_eval(geq->e[plane], values, geq); + } + ptr += linesize; + } + } + else { + for (y = slice_start; y < slice_end; y++) { + ptr16 = geq->dst16 + (linesize/2) * y; + values[VAR_Y] = y; + for (x = 0; x < width; x++) { + values[VAR_X] = x; + ptr16[x] = av_expr_eval(geq->e[plane], values, geq); + } + } + } return 0; } @@ -235,13 +292,14 @@ static int geq_config_props(AVFilterLink *inlink) static int geq_filter_frame(AVFilterLink *inlink, AVFrame *in) { int plane; - GEQContext *geq = inlink->dst->priv; + AVFilterContext *ctx = inlink->dst; + const int nb_threads = ff_filter_get_nb_threads(ctx); + GEQContext *geq = ctx->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; AVFrame *out; - double values[VAR_VARS_NB] = { - [VAR_N] = inlink->frame_count_out, - [VAR_T] = in->pts == AV_NOPTS_VALUE ? NAN : in->pts * av_q2d(inlink->time_base), - }; + + geq->values[VAR_N] = inlink->frame_count_out, + geq->values[VAR_T] = in->pts == AV_NOPTS_VALUE ? NAN : in->pts * av_q2d(inlink->time_base), geq->picref = in; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); @@ -252,34 +310,25 @@ static int geq_filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); for (plane = 0; plane < geq->planes && out->data[plane]; plane++) { - int x, y; - uint8_t *dst = out->data[plane]; - uint16_t *dst16 = (uint16_t*)out->data[plane]; - const int linesize = out->linesize[plane]; const int w = (plane == 1 || plane == 2) ? AV_CEIL_RSHIFT(inlink->w, geq->hsub) : inlink->w; const int h = (plane == 1 || plane == 2) ? AV_CEIL_RSHIFT(inlink->h, geq->vsub) : inlink->h; + const int linesize = out->linesize[plane]; + ThreadData td; - values[VAR_W] = w; - values[VAR_H] = h; - values[VAR_SW] = w / (double)inlink->w; - values[VAR_SH] = h / (double)inlink->h; + geq->dst = out->data[plane]; + geq->dst16 = (uint16_t*)out->data[plane]; - for (y = 0; y < h; y++) { - values[VAR_Y] = y; - if (geq->bps > 8) { - for (x = 0; x < w; x++) { - values[VAR_X] = x; - dst16[x] = av_expr_eval(geq->e[plane], values, geq); - } - dst16 += linesize / 2; - } else { - for (x = 0; x < w; x++) { - values[VAR_X] = x; - dst[x] = av_expr_eval(geq->e[plane], values, geq); - } - dst += linesize; - } - } + geq->values[VAR_W] = w; + geq->values[VAR_H] = h; + geq->values[VAR_SW] = w / (double)inlink->w; + geq->values[VAR_SH] = h / (double)inlink->h; + + td.width = w; + td.height = h; + td.plane = plane; + td.linesize = linesize; + + ctx->internal->execute(ctx, slice_geq_filter, &td, NULL, FFMIN(h, nb_threads)); } av_frame_free(&geq->picref); @@ -323,5 +372,5 @@ AVFilter ff_vf_geq = { .inputs = geq_inputs, .outputs = geq_outputs, .priv_class = &geq_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, }; From e425047a47b68dd21d50f0d83cfd7ae816268f57 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Thu, 4 Jan 2018 08:50:51 +0100 Subject: [PATCH 1549/2557] avfilter: rename variables in geq Signed-off-by: Michael Niedermayer --- libavfilter/vf_geq.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libavfilter/vf_geq.c b/libavfilter/vf_geq.c index 0651ed0b36aba..2aa1259c9a780 100644 --- a/libavfilter/vf_geq.c +++ b/libavfilter/vf_geq.c @@ -310,25 +310,25 @@ static int geq_filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); for (plane = 0; plane < geq->planes && out->data[plane]; plane++) { - const int w = (plane == 1 || plane == 2) ? AV_CEIL_RSHIFT(inlink->w, geq->hsub) : inlink->w; - const int h = (plane == 1 || plane == 2) ? AV_CEIL_RSHIFT(inlink->h, geq->vsub) : inlink->h; + const int width = (plane == 1 || plane == 2) ? AV_CEIL_RSHIFT(inlink->w, geq->hsub) : inlink->w; + const int height = (plane == 1 || plane == 2) ? AV_CEIL_RSHIFT(inlink->h, geq->vsub) : inlink->h; const int linesize = out->linesize[plane]; ThreadData td; geq->dst = out->data[plane]; geq->dst16 = (uint16_t*)out->data[plane]; - geq->values[VAR_W] = w; - geq->values[VAR_H] = h; - geq->values[VAR_SW] = w / (double)inlink->w; - geq->values[VAR_SH] = h / (double)inlink->h; + geq->values[VAR_W] = width; + geq->values[VAR_H] = height; + geq->values[VAR_SW] = width / (double)inlink->w; + geq->values[VAR_SH] = height / (double)inlink->h; - td.width = w; - td.height = h; + td.width = width; + td.height = height; td.plane = plane; td.linesize = linesize; - ctx->internal->execute(ctx, slice_geq_filter, &td, NULL, FFMIN(h, nb_threads)); + ctx->internal->execute(ctx, slice_geq_filter, &td, NULL, FFMIN(height, nb_threads)); } av_frame_free(&geq->picref); From b2be76c0a472b729756ed7a91225c209d0dd1d2e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 3 Jan 2018 23:42:00 +0100 Subject: [PATCH 1550/2557] avcodec/dnxhddec: Check dc vlc Fixes: signed integer overflow: 1024 + 2147483640 cannot be represented in type 'int' Fixes: 4671/clusterfuzz-testcase-minimized-6027464343027712 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer --- libavcodec/dnxhddec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c index 05f4458f991c1..11d0bf424aae4 100644 --- a/libavcodec/dnxhddec.c +++ b/libavcodec/dnxhddec.c @@ -383,6 +383,10 @@ static av_always_inline int dnxhd_decode_dct_block(const DNXHDContext *ctx, UPDATE_CACHE(bs, &row->gb); GET_VLC(len, bs, &row->gb, ctx->dc_vlc.table, DNXHD_DC_VLC_BITS, 1); + if (len < 0) { + ret = len; + goto error; + } if (len) { level = GET_CACHE(bs, &row->gb); LAST_SKIP_BITS(bs, &row->gb, len); @@ -436,7 +440,7 @@ static av_always_inline int dnxhd_decode_dct_block(const DNXHDContext *ctx, GET_VLC(index1, bs, &row->gb, ctx->ac_vlc.table, DNXHD_VLC_BITS, 2); } - +error: CLOSE_READER(bs, &row->gb); return ret; } From 7bb1be9af0ea41d6f342655e1d15e30f662fe0f3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 2 Jan 2018 14:30:54 +0100 Subject: [PATCH 1551/2557] avfilter: add arbitrary audio IIR filter Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/filters.texi | 35 ++++ libavfilter/Makefile | 1 + libavfilter/af_aiir.c | 334 +++++++++++++++++++++++++++++++++++++++ libavfilter/af_biquads.c | 2 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- 7 files changed, 375 insertions(+), 1 deletion(-) create mode 100644 libavfilter/af_aiir.c diff --git a/Changelog b/Changelog index 3d966c202b060..56a3d684d6be1 100644 --- a/Changelog +++ b/Changelog @@ -33,6 +33,7 @@ version : - deconvolve video filter - entropy video filter - hilbert audio filter source +- aiir audio filter version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index 73537c524fdc4..1a2a93b97a1a3 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1060,6 +1060,41 @@ the reduction. Default is @code{average}. Can be @code{average} or @code{maximum}. @end table +@section aiir + +Apply an arbitrary Infinite Impulse Response filter. + +It accepts the following parameters: + +@table @option +@item a +Set denominator/poles coefficients. + +@item b +Set nominator/zeros coefficients. + +@item dry_gain +Set input gain. + +@item wet_gain +Set output gain. +@end table + +Coefficients are separated by spaces and are in ascending order. +Different coefficients can be provided for every channel, in such case +use '|' to separate coefficients. Last provided coefficients will be +used for all remaining channels. + +@subsection Examples + +@itemize +@item +Apply 2 pole elliptic notch at arround 5000Hz for 48000 Hz sample rate: +@example +aiir=b=7.957584807809675810E-1 -2.575128568908332300 3.674839853930788710 -2.57512875289799137 7.957586296317130880E-1:a=1 -2.86950072432325953 3.63022088054647218 -2.28075678147272232 6.361362326477423500E-1 +@end example +@end itemize + @section alimiter The limiter prevents an input signal from rising over a desired threshold. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 8a103d4f338aa..256dfabd665fa 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -43,6 +43,7 @@ OBJS-$(CONFIG_AFFTFILT_FILTER) += af_afftfilt.o OBJS-$(CONFIG_AFIR_FILTER) += af_afir.o OBJS-$(CONFIG_AFORMAT_FILTER) += af_aformat.o OBJS-$(CONFIG_AGATE_FILTER) += af_agate.o +OBJS-$(CONFIG_AIIR_FILTER) += af_aiir.o OBJS-$(CONFIG_AINTERLEAVE_FILTER) += f_interleave.o OBJS-$(CONFIG_ALIMITER_FILTER) += af_alimiter.o OBJS-$(CONFIG_ALLPASS_FILTER) += af_biquads.o diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c new file mode 100644 index 0000000000000..29010bde2924f --- /dev/null +++ b/libavfilter/af_aiir.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2018 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/opt.h" +#include "audio.h" +#include "avfilter.h" +#include "internal.h" + +typedef struct AudioIIRContext { + const AVClass *class; + char *a_str, *b_str; + double dry_gain, wet_gain; + + int *nb_a, *nb_b; + double **a, **b; + double **input, **output; + int clippings; + int channels; + + void (*iir_frame)(AVFilterContext *ctx, AVFrame *in, AVFrame *out); +} AudioIIRContext; + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats; + AVFilterChannelLayouts *layouts; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE + }; + int ret; + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + formats = ff_all_samplerates(); + if (!formats) + return AVERROR(ENOMEM); + return ff_set_common_samplerates(ctx, formats); +} + +#define IIR_FRAME(name, type, min, max, need_clipping) \ +static void iir_frame_## name(AVFilterContext *ctx, AVFrame *in, AVFrame *out) \ +{ \ + AudioIIRContext *s = ctx->priv; \ + const double ig = s->dry_gain; \ + const double og = s->wet_gain; \ + int ch, n; \ + \ + for (ch = 0; ch < out->channels; ch++) { \ + const type *src = (const type *)in->extended_data[ch]; \ + double *ic = (double *)s->input[ch]; \ + double *oc = (double *)s->output[ch]; \ + const int nb_a = s->nb_a[ch]; \ + const int nb_b = s->nb_b[ch]; \ + const double *a = s->a[ch]; \ + const double *b = s->b[ch]; \ + type *dst = (type *)out->extended_data[ch]; \ + \ + for (n = 0; n < in->nb_samples; n++) { \ + double sample = 0.; \ + int x; \ + \ + memmove(&ic[1], &ic[0], (nb_b - 1) * sizeof(*ic)); \ + memmove(&oc[1], &oc[0], (nb_a - 1) * sizeof(*oc)); \ + ic[0] = src[n] * ig; \ + for (x = 0; x < nb_b; x++) \ + sample += b[x] * ic[x]; \ + \ + for (x = 1; x < nb_a; x++) \ + sample -= a[x] * oc[x]; \ + \ + oc[0] = sample; \ + sample *= og; \ + if (need_clipping && sample < min) { \ + s->clippings++; \ + dst[n] = min; \ + } else if (need_clipping && sample > max) { \ + s->clippings++; \ + dst[n] = max; \ + } else { \ + dst[n] = sample; \ + } \ + } \ + } \ +} + +IIR_FRAME(s16p, int16_t, INT16_MIN, INT16_MAX, 1) +IIR_FRAME(s32p, int32_t, INT32_MIN, INT32_MAX, 1) +IIR_FRAME(fltp, float, -1., 1., 0) +IIR_FRAME(dblp, double, -1., 1., 0) + +static void count_coefficients(char *item_str, int *nb_items) +{ + char *p; + + *nb_items = 1; + for (p = item_str; *p && *p != '|'; p++) { + if (*p == ' ') + (*nb_items)++; + } +} + +static int read_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, double *dst) +{ + char *p, *arg, *old_str, *saveptr = NULL; + int i; + + p = old_str = av_strdup(item_str); + if (!p) + return AVERROR(ENOMEM); + for (i = 0; i < nb_items; i++) { + if (!(arg = av_strtok(p, " ", &saveptr))) + break; + + p = NULL; + if (sscanf(arg, "%lf", &dst[i]) != 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid coefficients supplied: %s\n", arg); + return AVERROR(EINVAL); + } + } + + av_freep(&old_str); + + return 0; +} + +static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, int *nb, double **c, double **cache) +{ + char *p, *arg, *old_str, *prev_arg = NULL, *saveptr = NULL; + int i, ret; + + p = old_str = av_strdup(item_str); + if (!p) + return AVERROR(ENOMEM); + for (i = 0; i < channels; i++) { + if (!(arg = av_strtok(p, "|", &saveptr))) + arg = prev_arg; + + p = NULL; + count_coefficients(arg, &nb[i]); + cache[i] = av_calloc(nb[i], sizeof(cache[i])); + c[i] = av_calloc(nb[i], sizeof(c[i])); + if (!c[i] || !cache[i]) + return AVERROR(ENOMEM); + + ret = read_coefficients(ctx, arg, nb[i], c[i]); + if (ret < 0) + return ret; + prev_arg = arg; + } + + av_freep(&old_str); + + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AudioIIRContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + int ch, ret, i; + + s->channels = inlink->channels; + s->a = av_calloc(inlink->channels, sizeof(*s->a)); + s->b = av_calloc(inlink->channels, sizeof(*s->b)); + s->nb_a = av_calloc(inlink->channels, sizeof(*s->nb_a)); + s->nb_b = av_calloc(inlink->channels, sizeof(*s->nb_b)); + s->input = av_calloc(inlink->channels, sizeof(*s->input)); + s->output = av_calloc(inlink->channels, sizeof(*s->output)); + if (!s->a || !s->b || !s->nb_a || !s->nb_b || !s->input || !s->output) + return AVERROR(ENOMEM); + + ret = read_channels(ctx, inlink->channels, s->a_str, s->nb_a, s->a, s->output); + if (ret < 0) + return ret; + + ret = read_channels(ctx, inlink->channels, s->b_str, s->nb_b, s->b, s->input); + if (ret < 0) + return ret; + + for (ch = 0; ch < inlink->channels; ch++) { + for (i = 1; i < s->nb_a[ch]; i++) { + s->a[ch][i] /= s->a[ch][0]; + } + + for (i = 0; i < s->nb_b[ch]; i++) { + s->b[ch][i] /= s->a[ch][0]; + } + } + + switch (inlink->format) { + case AV_SAMPLE_FMT_DBLP: s->iir_frame = iir_frame_dblp; break; + case AV_SAMPLE_FMT_FLTP: s->iir_frame = iir_frame_fltp; break; + case AV_SAMPLE_FMT_S32P: s->iir_frame = iir_frame_s32p; break; + case AV_SAMPLE_FMT_S16P: s->iir_frame = iir_frame_s16p; break; + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AudioIIRContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_audio_buffer(outlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + + s->iir_frame(ctx, in, out); + + if (s->clippings > 0) + av_log(ctx, AV_LOG_WARNING, "clipping %d times. Please reduce gain.\n", s->clippings); + s->clippings = 0; + + if (in != out) + av_frame_free(&in); + + return ff_filter_frame(outlink, out); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioIIRContext *s = ctx->priv; + int ch; + + if (s->a) { + for (ch = 0; ch < s->channels; ch++) { + av_freep(&s->a[ch]); + av_freep(&s->output[ch]); + } + } + av_freep(&s->a); + + if (s->b) { + for (ch = 0; ch < s->channels; ch++) { + av_freep(&s->b[ch]); + av_freep(&s->input[ch]); + } + } + av_freep(&s->b); + + av_freep(&s->input); + av_freep(&s->output); + + av_freep(&s->nb_a); + av_freep(&s->nb_b); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + }, + { NULL } +}; + +#define OFFSET(x) offsetof(AudioIIRContext, x) +#define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption aiir_options[] = { + { "a", "set A/denominator/poles coefficients", OFFSET(a_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, AF }, + { "b", "set B/numerator/zeros coefficients", OFFSET(b_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, AF }, + { "dry", "set dry gain", OFFSET(dry_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, + { "wet", "set wet gain", OFFSET(wet_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(aiir); + +AVFilter ff_af_aiir = { + .name = "aiir", + .description = NULL_IF_CONFIG_SMALL("Apply Infinite Impulse Response filter with supplied coefficients."), + .priv_size = sizeof(AudioIIRContext), + .uninit = uninit, + .query_formats = query_formats, + .inputs = inputs, + .outputs = outputs, + .priv_class = &aiir_class, +}; diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index b0772b9fdc7bf..6e60e3b1b7bcd 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -375,6 +375,8 @@ static int config_filter(AVFilterLink *outlink, int reset) av_assert0(0); } + av_log(ctx, AV_LOG_VERBOSE, "a=%lf %lf %lf:b=%lf %lf %lf\n", s->a0, s->a1, s->a2, s->b0, s->b1, s->b2); + s->a1 /= s->a0; s->a2 /= s->a0; s->b0 /= s->a0; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 8c4ed6bd03366..753ae968aa786 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -54,6 +54,7 @@ static void register_all(void) REGISTER_FILTER(AFIR, afir, af); REGISTER_FILTER(AFORMAT, aformat, af); REGISTER_FILTER(AGATE, agate, af); + REGISTER_FILTER(AIIR, aiir, af); REGISTER_FILTER(AINTERLEAVE, ainterleave, af); REGISTER_FILTER(ALIMITER, alimiter, af); REGISTER_FILTER(ALLPASS, allpass, af); diff --git a/libavfilter/version.h b/libavfilter/version.h index ac8bec4cb8198..c07f4d30d923c 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 10 +#define LIBAVFILTER_VERSION_MINOR 11 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ From 9ed4ebc530dde681943389b1f97db90b546ad38d Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 4 Jan 2018 15:11:31 -0300 Subject: [PATCH 1552/2557] avcodec/util: use a mutex instead of atomics in avcodec_register() Reviewed-by: wm4 Signed-off-by: James Almer --- libavcodec/utils.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libavcodec/utils.c b/libavcodec/utils.c index dfbfe98d639d3..4d736d2e7d2fd 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -26,7 +26,6 @@ */ #include "config.h" -#include "libavutil/atomic.h" #include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" @@ -127,17 +126,24 @@ int av_codec_is_decoder(const AVCodec *codec) return codec && (codec->decode || codec->receive_frame); } +static AVMutex codec_register_mutex = AV_MUTEX_INITIALIZER; + av_cold void avcodec_register(AVCodec *codec) { AVCodec **p; avcodec_init(); + + ff_mutex_lock(&codec_register_mutex); p = last_avcodec; - codec->next = NULL; - while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, codec)) + while (*p) p = &(*p)->next; + *p = codec; + codec->next = NULL; last_avcodec = &codec->next; + ff_mutex_unlock(&codec_register_mutex); + if (codec->init_static_data) codec->init_static_data(codec); } From 57960b1f2800e59a46de2b03f7b37ef6ef1c1e52 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 4 Jan 2018 15:12:53 -0300 Subject: [PATCH 1553/2557] avformat: use mutexes instead of atomics in av_register_{input,output}_format() Reviewed-by: wm4 Signed-off-by: James Almer --- libavformat/format.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/libavformat/format.c b/libavformat/format.c index 38ca2a3465aff..759b5b1ab498c 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/atomic.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/opt.h" +#include "libavutil/thread.h" #include "avio_internal.h" #include "avformat.h" @@ -58,28 +58,40 @@ AVOutputFormat *av_oformat_next(const AVOutputFormat *f) return first_oformat; } +static AVMutex iformat_register_mutex = AV_MUTEX_INITIALIZER; + void av_register_input_format(AVInputFormat *format) { - AVInputFormat **p = last_iformat; + AVInputFormat **p; + + ff_mutex_lock(&iformat_register_mutex); + p = last_iformat; - // Note, format could be added after the first 2 checks but that implies that *p is no longer NULL - while(p != &format->next && !format->next && avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format)) + while (*p) p = &(*p)->next; + *p = format; + format->next = NULL; + last_iformat = &format->next; - if (!format->next) - last_iformat = &format->next; + ff_mutex_unlock(&iformat_register_mutex); } +static AVMutex oformat_register_mutex = AV_MUTEX_INITIALIZER; + void av_register_output_format(AVOutputFormat *format) { - AVOutputFormat **p = last_oformat; + AVOutputFormat **p; + + ff_mutex_lock(&oformat_register_mutex); + p = last_oformat; - // Note, format could be added after the first 2 checks but that implies that *p is no longer NULL - while(p != &format->next && !format->next && avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format)) + while (*p) p = &(*p)->next; + *p = format; + format->next = NULL; + last_oformat = &format->next; - if (!format->next) - last_oformat = &format->next; + ff_mutex_unlock(&oformat_register_mutex); } int av_match_ext(const char *filename, const char *extensions) From 167e659b289f6c2236c905ee7b8c50857457c858 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 4 Jan 2018 15:15:21 -0300 Subject: [PATCH 1554/2557] avfilter: use a mutex instead of atomics in avfilter_register() Reviewed-by: wm4 Signed-off-by: James Almer --- libavfilter/avfilter.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index b98b32bacb51b..ff7df672fdbb5 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/atomic.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/buffer.h" @@ -33,6 +32,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/rational.h" #include "libavutil/samplefmt.h" +#include "libavutil/thread.h" #define FF_INTERNAL_FIELDS 1 #include "framequeue.h" @@ -590,19 +590,26 @@ const AVFilter *avfilter_get_by_name(const char *name) return NULL; } +static AVMutex filter_register_mutex = AV_MUTEX_INITIALIZER; + int avfilter_register(AVFilter *filter) { - AVFilter **f = last_filter; + AVFilter **f; /* the filter must select generic or internal exclusively */ av_assert0((filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE) != AVFILTER_FLAG_SUPPORT_TIMELINE); - filter->next = NULL; + ff_mutex_lock(&filter_register_mutex); + f = last_filter; - while(*f || avpriv_atomic_ptr_cas((void * volatile *)f, NULL, filter)) + while (*f) f = &(*f)->next; + *f = filter; + filter->next = NULL; last_filter = &filter->next; + ff_mutex_unlock(&filter_register_mutex); + return 0; } From dcbf034a0fd28b0b894d275c86ebcdb2e766a804 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 5 Jan 2018 14:04:02 -0300 Subject: [PATCH 1555/2557] avcodec/error_resilience: remove unused header Signed-off-by: James Almer --- libavcodec/error_resilience.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index 8f172beca61f1..55f77961c51ea 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -27,7 +27,6 @@ #include -#include "libavutil/atomic.h" #include "libavutil/internal.h" #include "avcodec.h" #include "error_resilience.h" From 89b84cb18b54d3af281643bcad8bba365a702e96 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 5 Jan 2018 14:06:02 -0300 Subject: [PATCH 1556/2557] It has been replaced by C11 stdatomic.h and is now unused. (cherry picked from commit 5cc0057f4910c8c72421b812c8f337ef6c43696c) Signed-off-by: James Almer --- configure | 2 - libavutil/Makefile | 6 --- libavutil/atomic.c | 109 --------------------------------------- libavutil/atomic.h | 79 ---------------------------- libavutil/atomic_gcc.h | 61 ---------------------- libavutil/atomic_suncc.h | 54 ------------------- libavutil/atomic_win32.h | 54 ------------------- libavutil/tests/atomic.c | 38 -------------- tests/fate/libavutil.mak | 5 -- 9 files changed, 408 deletions(-) delete mode 100644 libavutil/atomic.c delete mode 100644 libavutil/atomic.h delete mode 100644 libavutil/atomic_gcc.h delete mode 100644 libavutil/atomic_suncc.h delete mode 100644 libavutil/atomic_win32.h delete mode 100644 libavutil/tests/atomic.c diff --git a/configure b/configure index 26da82072d349..86d81e3cc343e 100755 --- a/configure +++ b/configure @@ -1998,7 +1998,6 @@ MATH_FUNCS=" " SYSTEM_FEATURES=" - atomics_native dos_paths libc_msvcrt MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS @@ -2114,7 +2113,6 @@ HAVE_LIST=" $(add_suffix _external $ARCH_EXT_LIST) $(add_suffix _inline $ARCH_EXT_LIST) $ARCH_FEATURES - $ATOMICS_LIST $BUILTIN_LIST $COMPLEX_FUNCS $HAVE_LIST_CMDLINE diff --git a/libavutil/Makefile b/libavutil/Makefile index 66b894d66e749..d7474f59e4859 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -155,8 +155,6 @@ OBJS = adler32.o \ xtea.o \ tea.o \ -OBJS-$(!HAVE_ATOMICS_NATIVE) += atomic.o \ - OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o OBJS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.o OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o @@ -183,14 +181,10 @@ SKIPHEADERS-$(CONFIG_OPENCL) += hwcontext_opencl.h SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.h SKIPHEADERS-$(CONFIG_VDPAU) += hwcontext_vdpau.h -SKIPHEADERS-$(HAVE_ATOMICS_GCC) += atomic_gcc.h -SKIPHEADERS-$(HAVE_ATOMICS_SUNCC) += atomic_suncc.h -SKIPHEADERS-$(HAVE_ATOMICS_WIN32) += atomic_win32.h TESTPROGS = adler32 \ aes \ aes_ctr \ - atomic \ audio_fifo \ avstring \ base64 \ diff --git a/libavutil/atomic.c b/libavutil/atomic.c deleted file mode 100644 index 64cff2576fd30..0000000000000 --- a/libavutil/atomic.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2012 Ronald S. Bultje - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" -#include "atomic.h" - -#if !HAVE_ATOMICS_NATIVE - -#if HAVE_PTHREADS - -#include - -static pthread_mutex_t atomic_lock = PTHREAD_MUTEX_INITIALIZER; - -int avpriv_atomic_int_get(volatile int *ptr) -{ - int res; - - pthread_mutex_lock(&atomic_lock); - res = *ptr; - pthread_mutex_unlock(&atomic_lock); - - return res; -} - -void avpriv_atomic_int_set(volatile int *ptr, int val) -{ - pthread_mutex_lock(&atomic_lock); - *ptr = val; - pthread_mutex_unlock(&atomic_lock); -} - -int avpriv_atomic_int_add_and_fetch(volatile int *ptr, int inc) -{ - int res; - - pthread_mutex_lock(&atomic_lock); - *ptr += inc; - res = *ptr; - pthread_mutex_unlock(&atomic_lock); - - return res; -} - -void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval) -{ - void *ret; - pthread_mutex_lock(&atomic_lock); - ret = *ptr; - if (ret == oldval) - *ptr = newval; - pthread_mutex_unlock(&atomic_lock); - return ret; -} - -#elif !HAVE_THREADS - -int avpriv_atomic_int_get(volatile int *ptr) -{ - return *ptr; -} - -void avpriv_atomic_int_set(volatile int *ptr, int val) -{ - *ptr = val; -} - -int avpriv_atomic_int_add_and_fetch(volatile int *ptr, int inc) -{ - *ptr += inc; - return *ptr; -} - -void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval) -{ - if (*ptr == oldval) { - *ptr = newval; - return oldval; - } - return *ptr; -} - -#else /* HAVE_THREADS */ - -/* This should never trigger, unless a new threading implementation - * without correct atomics dependencies in configure or a corresponding - * atomics implementation is added. */ -#error "Threading is enabled, but there is no implementation of atomic operations available" - -#endif /* HAVE_PTHREADS */ - -#endif /* !HAVE_ATOMICS_NATIVE */ diff --git a/libavutil/atomic.h b/libavutil/atomic.h deleted file mode 100644 index 15906d24c9cb8..0000000000000 --- a/libavutil/atomic.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2012 Ronald S. Bultje - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVUTIL_ATOMIC_H -#define AVUTIL_ATOMIC_H - -#include "config.h" - -#if HAVE_ATOMICS_NATIVE - -#if HAVE_ATOMICS_GCC -#include "atomic_gcc.h" -#elif HAVE_ATOMICS_WIN32 -#include "atomic_win32.h" -#elif HAVE_ATOMICS_SUNCC -#include "atomic_suncc.h" -#endif - -#else - -/** - * Load the current value stored in an atomic integer. - * - * @param ptr atomic integer - * @return the current value of the atomic integer - * @note This acts as a memory barrier. - */ -int avpriv_atomic_int_get(volatile int *ptr); - -/** - * Store a new value in an atomic integer. - * - * @param ptr atomic integer - * @param val the value to store in the atomic integer - * @note This acts as a memory barrier. - */ -void avpriv_atomic_int_set(volatile int *ptr, int val); - -/** - * Add a value to an atomic integer. - * - * @param ptr atomic integer - * @param inc the value to add to the atomic integer (may be negative) - * @return the new value of the atomic integer. - * @note This does NOT act as a memory barrier. This is primarily - * intended for reference counting. - */ -int avpriv_atomic_int_add_and_fetch(volatile int *ptr, int inc); - -/** - * Atomic pointer compare and swap. - * - * @param ptr pointer to the pointer to operate on - * @param oldval do the swap if the current value of *ptr equals to oldval - * @param newval value to replace *ptr with - * @return the value of *ptr before comparison - */ -void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval); - -#endif /* HAVE_ATOMICS_NATIVE */ - -#endif /* AVUTIL_ATOMIC_H */ diff --git a/libavutil/atomic_gcc.h b/libavutil/atomic_gcc.h deleted file mode 100644 index 2bb43c3cea0e8..0000000000000 --- a/libavutil/atomic_gcc.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2012 Ronald S. Bultje - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVUTIL_ATOMIC_GCC_H -#define AVUTIL_ATOMIC_GCC_H - -#include - -#include "atomic.h" - -#define avpriv_atomic_int_get atomic_int_get_gcc -static inline int atomic_int_get_gcc(volatile int *ptr) -{ - __sync_synchronize(); - return *ptr; -} - -#define avpriv_atomic_int_set atomic_int_set_gcc -static inline void atomic_int_set_gcc(volatile int *ptr, int val) -{ - *ptr = val; - __sync_synchronize(); -} - -#define avpriv_atomic_int_add_and_fetch atomic_int_add_and_fetch_gcc -static inline int atomic_int_add_and_fetch_gcc(volatile int *ptr, int inc) -{ - return __sync_add_and_fetch(ptr, inc); -} - -#define avpriv_atomic_ptr_cas atomic_ptr_cas_gcc -static inline void *atomic_ptr_cas_gcc(void * volatile *ptr, - void *oldval, void *newval) -{ -#ifdef __ARMCC_VERSION - // armcc will throw an error if ptr is not an integer type - volatile uintptr_t *tmp = (volatile uintptr_t*)ptr; - return (void*)__sync_val_compare_and_swap(tmp, oldval, newval); -#else - return __sync_val_compare_and_swap(ptr, oldval, newval); -#endif -} - -#endif /* AVUTIL_ATOMIC_GCC_H */ diff --git a/libavutil/atomic_suncc.h b/libavutil/atomic_suncc.h deleted file mode 100644 index a75a37b47eb72..0000000000000 --- a/libavutil/atomic_suncc.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVUTIL_ATOMIC_SUNCC_H -#define AVUTIL_ATOMIC_SUNCC_H - -#include -#include - -#include "atomic.h" - -#define avpriv_atomic_int_get atomic_int_get_suncc -static inline int atomic_int_get_suncc(volatile int *ptr) -{ - __machine_rw_barrier(); - return *ptr; -} - -#define avpriv_atomic_int_set atomic_int_set_suncc -static inline void atomic_int_set_suncc(volatile int *ptr, int val) -{ - *ptr = val; - __machine_rw_barrier(); -} - -#define avpriv_atomic_int_add_and_fetch atomic_int_add_and_fetch_suncc -static inline int atomic_int_add_and_fetch_suncc(volatile int *ptr, int inc) -{ - return atomic_add_int_nv(ptr, inc); -} - -#define avpriv_atomic_ptr_cas atomic_ptr_cas_suncc -static inline void *atomic_ptr_cas_suncc(void * volatile *ptr, - void *oldval, void *newval) -{ - return atomic_cas_ptr(ptr, oldval, newval); -} - -#endif /* AVUTIL_ATOMIC_SUNCC_H */ diff --git a/libavutil/atomic_win32.h b/libavutil/atomic_win32.h deleted file mode 100644 index f7299336f6b10..0000000000000 --- a/libavutil/atomic_win32.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2012 Ronald S. Bultje - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVUTIL_ATOMIC_WIN32_H -#define AVUTIL_ATOMIC_WIN32_H - -#define WIN32_LEAN_AND_MEAN -#include - -#define avpriv_atomic_int_get atomic_int_get_win32 -static inline int atomic_int_get_win32(volatile int *ptr) -{ - MemoryBarrier(); - return *ptr; -} - -#define avpriv_atomic_int_set atomic_int_set_win32 -static inline void atomic_int_set_win32(volatile int *ptr, int val) -{ - *ptr = val; - MemoryBarrier(); -} - -#define avpriv_atomic_int_add_and_fetch atomic_int_add_and_fetch_win32 -static inline int atomic_int_add_and_fetch_win32(volatile int *ptr, int inc) -{ - return inc + InterlockedExchangeAdd(ptr, inc); -} - -#define avpriv_atomic_ptr_cas atomic_ptr_cas_win32 -static inline void *atomic_ptr_cas_win32(void * volatile *ptr, - void *oldval, void *newval) -{ - return InterlockedCompareExchangePointer(ptr, newval, oldval); -} - -#endif /* AVUTIL_ATOMIC_WIN32_H */ diff --git a/libavutil/tests/atomic.c b/libavutil/tests/atomic.c deleted file mode 100644 index e41bf5a2b94cd..0000000000000 --- a/libavutil/tests/atomic.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/atomic.h" -#include "libavutil/avassert.h" - -int main(void) -{ - volatile int val = 1; - void *tmp1 = (int *)&val; - void * volatile *tmp2 = &tmp1; - int res; - - res = avpriv_atomic_int_add_and_fetch(&val, 1); - av_assert0(res == 2); - avpriv_atomic_int_set(&val, 3); - res = avpriv_atomic_int_get(&val); - av_assert0(res == 3); - avpriv_atomic_ptr_cas(tmp2, tmp1, &res); - av_assert0(*tmp2 == &res); - - return 0; -} diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak index 591cab9b583d0..2ec5650c0f8fd 100644 --- a/tests/fate/libavutil.mak +++ b/tests/fate/libavutil.mak @@ -23,11 +23,6 @@ fate-cast5: libavutil/tests/cast5$(EXESUF) fate-cast5: CMD = run libavutil/tests/cast5 fate-cast5: CMP = null -FATE_LIBAVUTIL += fate-atomic -fate-atomic: libavutil/tests/atomic$(EXESUF) -fate-atomic: CMD = run libavutil/tests/atomic -fate-atomic: CMP = null - FATE_LIBAVUTIL += fate-audio_fifo fate-audio_fifo: libavutil/tests/audio_fifo$(EXESUF) fate-audio_fifo: CMD = run libavutil/tests/audio_fifo From 52c959a2376614e4c9089145b8ee69334b663257 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 5 Jan 2018 19:55:09 +0100 Subject: [PATCH 1557/2557] avfilter/af_aiir: do not crash with invalid options Signed-off-by: Paul B Mahol --- libavfilter/af_aiir.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c index 29010bde2924f..e14e464211513 100644 --- a/libavfilter/af_aiir.c +++ b/libavfilter/af_aiir.c @@ -127,6 +127,9 @@ static void count_coefficients(char *item_str, int *nb_items) { char *p; + if (!item_str) + return; + *nb_items = 1; for (p = item_str; *p && *p != '|'; p++) { if (*p == ' ') @@ -170,10 +173,14 @@ static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, if (!(arg = av_strtok(p, "|", &saveptr))) arg = prev_arg; - p = NULL; + if (!arg) + return AVERROR(EINVAL); + count_coefficients(arg, &nb[i]); - cache[i] = av_calloc(nb[i], sizeof(cache[i])); - c[i] = av_calloc(nb[i], sizeof(c[i])); + + p = NULL; + cache[i] = av_calloc(nb[i] + 1, sizeof(double)); + c[i] = av_calloc(nb[i], sizeof(double)); if (!c[i] || !cache[i]) return AVERROR(ENOMEM); @@ -263,6 +270,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return ff_filter_frame(outlink, out); } +static av_cold int init(AVFilterContext *ctx) +{ + AudioIIRContext *s = ctx->priv; + + if (!s->a_str || !s->b_str) { + av_log(ctx, AV_LOG_ERROR, "Valid coefficients are mandatory.\n"); + return AVERROR(EINVAL); + } + + return 0; +} + static av_cold void uninit(AVFilterContext *ctx) { AudioIIRContext *s = ctx->priv; @@ -326,6 +345,7 @@ AVFilter ff_af_aiir = { .name = "aiir", .description = NULL_IF_CONFIG_SMALL("Apply Infinite Impulse Response filter with supplied coefficients."), .priv_size = sizeof(AudioIIRContext), + .init = init, .uninit = uninit, .query_formats = query_formats, .inputs = inputs, From b9ad04b19c0c7244cc3788f3fa45e9fbe0b620a8 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 9 Oct 2017 21:07:31 -0300 Subject: [PATCH 1558/2557] fate: add PERSIST_RPARAM_A_RExt_Sony_3 hevc conformance test The PERSIST_RPARAM_A_RExt_Sony_1 bitstream has an out-of-range value and has therefore been superseded. It is otherwise identical, and decodes the same. Signed-off-by: James Almer --- tests/fate/hevc.mak | 1 + .../ref/fate/hevc-conformance-PERSIST_RPARAM_A_RExt_Sony_3 | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 tests/ref/fate/hevc-conformance-PERSIST_RPARAM_A_RExt_Sony_3 diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak index 0e8859307d3f2..184349e5dd6c2 100644 --- a/tests/fate/hevc.mak +++ b/tests/fate/hevc.mak @@ -168,6 +168,7 @@ HEVC_SAMPLES_444_8BIT = \ HEVC_SAMPLES_444_12BIT = \ IPCM_B_RExt_NEC \ PERSIST_RPARAM_A_RExt_Sony_1\ + PERSIST_RPARAM_A_RExt_Sony_3\ SAO_A_RExt_MediaTek_1 \ diff --git a/tests/ref/fate/hevc-conformance-PERSIST_RPARAM_A_RExt_Sony_3 b/tests/ref/fate/hevc-conformance-PERSIST_RPARAM_A_RExt_Sony_3 new file mode 100644 index 0000000000000..54f4db8c5f184 --- /dev/null +++ b/tests/ref/fate/hevc-conformance-PERSIST_RPARAM_A_RExt_Sony_3 @@ -0,0 +1,7 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 400x384 +#sar 0: 0/1 +0, 0, 0, 1, 921600, 0x702f0d67 +0, 1, 1, 1, 921600, 0x99822b52 From 798dcf2432999f449c76c0e0fe2d7a4ee5eabbc2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 5 Jan 2018 17:49:09 -0300 Subject: [PATCH 1559/2557] avfilter: deprecate avfilter_link_get_channels() And move the channels field to the public section of the struct. Signed-off-by: James Almer --- doc/APIchanges | 4 ++++ libavfilter/avfilter.c | 2 ++ libavfilter/avfilter.h | 15 ++++++++++----- libavfilter/version.h | 5 ++++- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 38c1be61c7a47..6e48c8707eefa 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-01-xx - xxxxxxx - lavfi 7.11.101 - avfilter.h + Deprecate avfilter_link_get_channels(), and make AVFilterLink->channels + public. + 2017-xx-xx - xxxxxxx - lavr 4.0.0 - avresample.h Deprecate the entire library. Merged years ago to provide compatibility with Libav, it remained unmaintained by the FFmpeg project and duplicated diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index ff7df672fdbb5..ea75467a758f3 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -183,10 +183,12 @@ void avfilter_link_free(AVFilterLink **link) av_freep(link); } +#if FF_API_FILTER_GET_SET int avfilter_link_get_channels(AVFilterLink *link) { return link->channels; } +#endif void ff_filter_set_ready(AVFilterContext *filter, unsigned priority) { diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 47546c15e51d0..410d8bbdd711e 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -448,6 +448,11 @@ struct AVFilterLink { */ AVRational time_base; + /** + * Number of channels. + */ + int channels; + /***************************************************************** * All fields below this line are not part of the public API. They * may not be used outside of libavfilter and can be changed and @@ -551,11 +556,6 @@ struct AVFilterLink { */ int max_samples; - /** - * Number of channels. - */ - int channels; - /** * Link processing flags. */ @@ -647,10 +647,15 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, */ void avfilter_link_free(AVFilterLink **link); +#if FF_API_FILTER_GET_SET /** * Get the number of channels of a link. + * @deprecated This accessor used to be provided for ABI compatibility, and + * does not need to be used anymore. */ +attribute_deprecated int avfilter_link_get_channels(AVFilterLink *link); +#endif /** * Set the closed field of a link. diff --git a/libavfilter/version.h b/libavfilter/version.h index c07f4d30d923c..0f1172182253a 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #define LIBAVFILTER_VERSION_MAJOR 7 #define LIBAVFILTER_VERSION_MINOR 11 -#define LIBAVFILTER_VERSION_MICRO 100 +#define LIBAVFILTER_VERSION_MICRO 101 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ @@ -55,5 +55,8 @@ #ifndef FF_API_LAVR_OPTS #define FF_API_LAVR_OPTS (LIBAVFILTER_VERSION_MAJOR < 8) #endif +#ifndef FF_API_FILTER_GET_SET +#define FF_API_FILTER_GET_SET (LIBAVFILTER_VERSION_MAJOR < 8) +#endif #endif /* AVFILTER_VERSION_H */ From 01c21653eee53a353ae887a47cd2b48165902383 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 5 Jan 2018 17:49:27 -0300 Subject: [PATCH 1560/2557] tools/uncoded_frame: remove usage of avfilter_link_get_channels() Signed-off-by: James Almer --- tools/uncoded_frame.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/uncoded_frame.c b/tools/uncoded_frame.c index 3ca2ba4bbef58..c04474170188e 100644 --- a/tools/uncoded_frame.c +++ b/tools/uncoded_frame.c @@ -178,7 +178,7 @@ int main(int argc, char **argv) break; case AVMEDIA_TYPE_AUDIO: st->stream->codec->channel_layout = st->link->channel_layout; - st->stream->codec->channels = avfilter_link_get_channels(st->link); + st->stream->codec->channels = st->link->channels; st->stream->codec->sample_rate = st->link->sample_rate; st->stream->codec->sample_fmt = st->link->format; st->stream->codec->codec_id = From 077fe9eb0679ccba53b1814ac5e687ea3eb2a3c1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 5 Jan 2018 22:09:39 -0300 Subject: [PATCH 1561/2557] doc/libav-merge: remove line about libavutil atomics API See 89b84cb18b54d3af281643bcad8bba365a702e96. Signed-off-by: James Almer --- doc/libav-merge.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/libav-merge.txt b/doc/libav-merge.txt index 2477d90e7b9a0..4ba08fc588f9e 100644 --- a/doc/libav-merge.txt +++ b/doc/libav-merge.txt @@ -95,7 +95,6 @@ Stuff that didn't reach the codebase: - 0cef06df0 checkasm: add HEVC MC tests - e7078e842 hevcdsp: add x86 SIMD for MC - 7993ec19a hevc: Add hevc_get_pixel_4/8/12/16/24/32/48/64 -- Removal of the custom atomic API (5cc0057f49, see http://ffmpeg.org/pipermail/ffmpeg-devel/2017-March/209003.html) - new bitstream reader (see http://ffmpeg.org/pipermail/ffmpeg-devel/2017-April/209609.html) - use av_cpu_max_align() instead of hardcoding alignment requirements (see https://ffmpeg.org/pipermail/ffmpeg-devel/2017-September/215834.html) - f44ec22e0 lavc: use av_cpu_max_align() instead of hardcoding alignment requirements From 503164b54ba2f4fcc3ba829ee4ece43333998b15 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 5 Jan 2018 22:12:14 -0300 Subject: [PATCH 1562/2557] Revert "tools/uncoded_frame: remove usage of avfilter_link_get_channels()" This reverts commit 01c21653eee53a353ae887a47cd2b48165902383. It was applied by accident before it could be reviewed. --- tools/uncoded_frame.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/uncoded_frame.c b/tools/uncoded_frame.c index c04474170188e..3ca2ba4bbef58 100644 --- a/tools/uncoded_frame.c +++ b/tools/uncoded_frame.c @@ -178,7 +178,7 @@ int main(int argc, char **argv) break; case AVMEDIA_TYPE_AUDIO: st->stream->codec->channel_layout = st->link->channel_layout; - st->stream->codec->channels = st->link->channels; + st->stream->codec->channels = avfilter_link_get_channels(st->link); st->stream->codec->sample_rate = st->link->sample_rate; st->stream->codec->sample_fmt = st->link->format; st->stream->codec->codec_id = From da5b05c8335d2c29355b95257f466211d04ab81d Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 5 Jan 2018 22:13:28 -0300 Subject: [PATCH 1563/2557] Revert "avfilter: deprecate avfilter_link_get_channels()" This reverts commit 798dcf2432999f449c76c0e0fe2d7a4ee5eabbc2. It was applied by accident before it could be reviewed. --- doc/APIchanges | 4 ---- libavfilter/avfilter.c | 2 -- libavfilter/avfilter.h | 15 +++++---------- libavfilter/version.h | 5 +---- 4 files changed, 6 insertions(+), 20 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 6e48c8707eefa..38c1be61c7a47 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,10 +15,6 @@ libavutil: 2017-10-21 API changes, most recent first: -2018-01-xx - xxxxxxx - lavfi 7.11.101 - avfilter.h - Deprecate avfilter_link_get_channels(), and make AVFilterLink->channels - public. - 2017-xx-xx - xxxxxxx - lavr 4.0.0 - avresample.h Deprecate the entire library. Merged years ago to provide compatibility with Libav, it remained unmaintained by the FFmpeg project and duplicated diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index ea75467a758f3..ff7df672fdbb5 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -183,12 +183,10 @@ void avfilter_link_free(AVFilterLink **link) av_freep(link); } -#if FF_API_FILTER_GET_SET int avfilter_link_get_channels(AVFilterLink *link) { return link->channels; } -#endif void ff_filter_set_ready(AVFilterContext *filter, unsigned priority) { diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 410d8bbdd711e..47546c15e51d0 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -448,11 +448,6 @@ struct AVFilterLink { */ AVRational time_base; - /** - * Number of channels. - */ - int channels; - /***************************************************************** * All fields below this line are not part of the public API. They * may not be used outside of libavfilter and can be changed and @@ -556,6 +551,11 @@ struct AVFilterLink { */ int max_samples; + /** + * Number of channels. + */ + int channels; + /** * Link processing flags. */ @@ -647,15 +647,10 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, */ void avfilter_link_free(AVFilterLink **link); -#if FF_API_FILTER_GET_SET /** * Get the number of channels of a link. - * @deprecated This accessor used to be provided for ABI compatibility, and - * does not need to be used anymore. */ -attribute_deprecated int avfilter_link_get_channels(AVFilterLink *link); -#endif /** * Set the closed field of a link. diff --git a/libavfilter/version.h b/libavfilter/version.h index 0f1172182253a..c07f4d30d923c 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #define LIBAVFILTER_VERSION_MAJOR 7 #define LIBAVFILTER_VERSION_MINOR 11 -#define LIBAVFILTER_VERSION_MICRO 101 +#define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ @@ -55,8 +55,5 @@ #ifndef FF_API_LAVR_OPTS #define FF_API_LAVR_OPTS (LIBAVFILTER_VERSION_MAJOR < 8) #endif -#ifndef FF_API_FILTER_GET_SET -#define FF_API_FILTER_GET_SET (LIBAVFILTER_VERSION_MAJOR < 8) -#endif #endif /* AVFILTER_VERSION_H */ From fba00b7465b23d1c96fe01a8298afeda01a5d8eb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 1 Jan 2018 13:17:18 +0100 Subject: [PATCH 1564/2557] doc/fate: Document how to upload samples to the fate suite Suggested-by: Compn Signed-off-by: Michael Niedermayer --- doc/fate.texi | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/doc/fate.texi b/doc/fate.texi index 7a96c25c72ad8..c9c0d3aea9842 100644 --- a/doc/fate.texi +++ b/doc/fate.texi @@ -147,6 +147,26 @@ process. The only thing left is to automate the execution of the fate.sh script and the synchronisation of the samples directory. +@chapter Uploading new samples to the fate suite + +This is for developers who have an account on the fate suite server. +If you upload new samples, please make sure they are as small as possible, +space on each client, network bandwidth and so on benefit from smaller test cases. +Also keep in mind older checkouts use existing sample files, that means in +practice generally do not replace, remove or overwrite files as it likely would +break older checkouts or releases. + +@example +#First update your local samples copy: +rsync -vauL --chmod=Dg+s,Duo+x,ug+rw,o+r,o-w,+X fate-suite.ffmpeg.org:/home/samples/fate-suite/ ~/fate-suite + +#Then do a dry run checking what would be uploaded: +rsync -vanL --no-g --chmod=Dg+s,Duo+x,ug+rw,o+r,o-w,+X ~/fate-suite/ fate-suite.ffmpeg.org:/home/samples/fate-suite + +#Upload the files: +rsync -vaL --no-g --chmod=Dg+s,Duo+x,ug+rw,o+r,o-w,+X ~/fate-suite/ fate-suite.ffmpeg.org:/home/samples/fate-suite +@end example + @chapter FATE makefile targets and variables From 94e6b5ac3914c391912b717e6aba2cb40cc717b7 Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Fri, 5 Jan 2018 20:06:48 +1100 Subject: [PATCH 1565/2557] adpcm: consume remainder after consuming XA chunks Signed-off-by: Michael Niedermayer --- libavcodec/adpcm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index be206c55ba439..cd3bbd33c2e44 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -1115,6 +1115,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, int16_t *out1 = samples_p[1]; int samples_per_block = 28 * (3 - avctx->channels) * 4; int sample_offset = 0; + int bytes_remaining; while (bytestream2_get_bytes_left(&gb) >= 128) { if ((ret = xa_decode(avctx, out0, out1, buf + bytestream2_tell(&gb), &c->status[0], &c->status[1], @@ -1123,6 +1124,12 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, bytestream2_skipu(&gb, 128); sample_offset += samples_per_block; } + /* Less than a full block of data left, e.g. when reading from + * 2324 byte per sector XA; the remainder is padding */ + bytes_remaining = bytestream2_get_bytes_left(&gb); + if (bytes_remaining > 0) { + bytestream2_skip(&gb, bytes_remaining); + } break; } case AV_CODEC_ID_ADPCM_IMA_EA_EACS: From bfe397e4313c640e2f05c90a2ff1541f50524094 Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Fri, 5 Jan 2018 20:06:49 +1100 Subject: [PATCH 1566/2557] aiff: add explicit goto got_sound Signed-off-by: Michael Niedermayer --- Changelog | 1 + libavformat/aiffdec.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Changelog b/Changelog index 56a3d684d6be1..2f92638d3621d 100644 --- a/Changelog +++ b/Changelog @@ -34,6 +34,7 @@ version : - entropy video filter - hilbert audio filter source - aiir audio filter +- aiff: add support for CD-ROM XA ADPCM version 3.4: diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index a6c180fc8da72..e87fbc5661c1f 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -332,6 +332,9 @@ static int aiff_read_header(AVFormatContext *s) /* This field is unknown and its data seems to be irrelevant */ avio_rb32(pb); st->codecpar->block_align = avio_rb32(pb); + + goto got_sound; + break; case 0: if (offset > 0 && st->codecpar->block_align) // COMM && SSND goto got_sound; From 50b3cd22dd70658b39abd0ced31b495d4d0a4b1b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 6 Jan 2018 14:58:00 +0100 Subject: [PATCH 1567/2557] avfilter/av_biquads: scale a0 too Fixes bug when using commands to alter coefficients. Signed-off-by: Paul B Mahol --- libavfilter/af_biquads.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index 6e60e3b1b7bcd..d5c3823e6446c 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -382,6 +382,7 @@ static int config_filter(AVFilterLink *outlink, int reset) s->b0 /= s->a0; s->b1 /= s->a0; s->b2 /= s->a0; + s->a0 /= s->a0; s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->channels); if (!s->cache) From b2c42fc6dc3502a8b6cae441c54d898972a51cff Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 5 Jan 2018 17:49:09 -0300 Subject: [PATCH 1568/2557] avfilter: deprecate avfilter_link_get_channels() Reviewed-by: Nicolas George Signed-off-by: James Almer --- doc/APIchanges | 3 +++ libavfilter/avfilter.c | 2 ++ libavfilter/avfilter.h | 4 ++++ libavfilter/version.h | 5 ++++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 38c1be61c7a47..d66c842521d56 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-01-xx - xxxxxxx - lavfi 7.11.101 - avfilter.h + Deprecate avfilter_link_get_channels(). Use av_buffersink_get_channels(). + 2017-xx-xx - xxxxxxx - lavr 4.0.0 - avresample.h Deprecate the entire library. Merged years ago to provide compatibility with Libav, it remained unmaintained by the FFmpeg project and duplicated diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index ff7df672fdbb5..ea75467a758f3 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -183,10 +183,12 @@ void avfilter_link_free(AVFilterLink **link) av_freep(link); } +#if FF_API_FILTER_GET_SET int avfilter_link_get_channels(AVFilterLink *link) { return link->channels; } +#endif void ff_filter_set_ready(AVFilterContext *filter, unsigned priority) { diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 47546c15e51d0..62eed2168f001 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -647,10 +647,14 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, */ void avfilter_link_free(AVFilterLink **link); +#if FF_API_FILTER_GET_SET /** * Get the number of channels of a link. + * @deprecated Use av_buffersink_get_channels() */ +attribute_deprecated int avfilter_link_get_channels(AVFilterLink *link); +#endif /** * Set the closed field of a link. diff --git a/libavfilter/version.h b/libavfilter/version.h index c07f4d30d923c..0f1172182253a 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #define LIBAVFILTER_VERSION_MAJOR 7 #define LIBAVFILTER_VERSION_MINOR 11 -#define LIBAVFILTER_VERSION_MICRO 100 +#define LIBAVFILTER_VERSION_MICRO 101 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ @@ -55,5 +55,8 @@ #ifndef FF_API_LAVR_OPTS #define FF_API_LAVR_OPTS (LIBAVFILTER_VERSION_MAJOR < 8) #endif +#ifndef FF_API_FILTER_GET_SET +#define FF_API_FILTER_GET_SET (LIBAVFILTER_VERSION_MAJOR < 8) +#endif #endif /* AVFILTER_VERSION_H */ From 34dfe36971aafd2b3bef04f1e78b2813e2f0b73f Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Sat, 6 Jan 2018 14:14:04 +0100 Subject: [PATCH 1569/2557] tools/uncoded_frame: use buffersink accessors. No longer access buffersink's link structure directly. --- tools/uncoded_frame.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/tools/uncoded_frame.c b/tools/uncoded_frame.c index 3ca2ba4bbef58..f346b21916d53 100644 --- a/tools/uncoded_frame.c +++ b/tools/uncoded_frame.c @@ -11,7 +11,6 @@ typedef struct { AVFormatContext *mux; AVStream *stream; AVFilterContext *sink; - AVFilterLink *link; } Stream; static int create_sink(Stream *st, AVFilterGraph *graph, @@ -36,7 +35,6 @@ static int create_sink(Stream *st, AVFilterGraph *graph, ret = avfilter_link(f, idx, st->sink, 0); if (ret < 0) return ret; - st->link = st->sink->inputs[0]; return 0; } @@ -163,24 +161,24 @@ int main(int argc, char **argv) av_log(NULL, AV_LOG_ERROR, "Failed to create output stream\n"); goto fail; } - st->stream->codec->codec_type = st->link->type; + st->stream->codec->codec_type = av_buffersink_get_type(st->sink); st->stream->time_base = st->stream->codec->time_base = - st->link->time_base; - switch (st->link->type) { + av_buffersink_get_time_base(st->sink); + switch (av_buffersink_get_type(st->sink)) { case AVMEDIA_TYPE_VIDEO: st->stream->codec->codec_id = AV_CODEC_ID_RAWVIDEO; st->stream->avg_frame_rate = st->stream-> r_frame_rate = av_buffersink_get_frame_rate(st->sink); - st->stream->codec->width = st->link->w; - st->stream->codec->height = st->link->h; - st->stream->codec->sample_aspect_ratio = st->link->sample_aspect_ratio; - st->stream->codec->pix_fmt = st->link->format; + st->stream->codec->width = av_buffersink_get_w(st->sink); + st->stream->codec->height = av_buffersink_get_h(st->sink); + st->stream->codec->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(st->sink); + st->stream->codec->pix_fmt = av_buffersink_get_format(st->sink); break; case AVMEDIA_TYPE_AUDIO: - st->stream->codec->channel_layout = st->link->channel_layout; - st->stream->codec->channels = avfilter_link_get_channels(st->link); - st->stream->codec->sample_rate = st->link->sample_rate; - st->stream->codec->sample_fmt = st->link->format; + st->stream->codec->channel_layout = av_buffersink_get_channel_layout(st->sink); + st->stream->codec->channels = av_buffersink_get_channels(st->sink); + st->stream->codec->sample_rate = av_buffersink_get_sample_rate(st->sink); + st->stream->codec->sample_fmt = av_buffersink_get_format(st->sink); st->stream->codec->codec_id = av_get_pcm_codec(st->stream->codec->sample_fmt, -1); break; @@ -240,7 +238,7 @@ int main(int argc, char **argv) } if (frame->pts != AV_NOPTS_VALUE) frame->pts = av_rescale_q(frame->pts, - st->link ->time_base, + av_buffersink_get_time_base(st->sink), st->stream->time_base); ret = av_interleaved_write_uncoded_frame(st->mux, st->stream->index, From 01735b4852c65081eaead3d9d405ef30fbb5a6ee Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Sat, 6 Jan 2018 14:34:00 +0100 Subject: [PATCH 1570/2557] tools/uncoded_frame: remove use of AVStream.codec. --- tools/uncoded_frame.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/tools/uncoded_frame.c b/tools/uncoded_frame.c index f346b21916d53..606bdb746ae3a 100644 --- a/tools/uncoded_frame.c +++ b/tools/uncoded_frame.c @@ -161,26 +161,24 @@ int main(int argc, char **argv) av_log(NULL, AV_LOG_ERROR, "Failed to create output stream\n"); goto fail; } - st->stream->codec->codec_type = av_buffersink_get_type(st->sink); - st->stream->time_base = st->stream->codec->time_base = - av_buffersink_get_time_base(st->sink); + st->stream->codecpar->codec_type = av_buffersink_get_type(st->sink); + st->stream->time_base = av_buffersink_get_time_base(st->sink); switch (av_buffersink_get_type(st->sink)) { case AVMEDIA_TYPE_VIDEO: - st->stream->codec->codec_id = AV_CODEC_ID_RAWVIDEO; + st->stream->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; st->stream->avg_frame_rate = st->stream-> r_frame_rate = av_buffersink_get_frame_rate(st->sink); - st->stream->codec->width = av_buffersink_get_w(st->sink); - st->stream->codec->height = av_buffersink_get_h(st->sink); - st->stream->codec->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(st->sink); - st->stream->codec->pix_fmt = av_buffersink_get_format(st->sink); + st->stream->codecpar->width = av_buffersink_get_w(st->sink); + st->stream->codecpar->height = av_buffersink_get_h(st->sink); + st->stream->codecpar->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(st->sink); + st->stream->codecpar->format = av_buffersink_get_format(st->sink); break; case AVMEDIA_TYPE_AUDIO: - st->stream->codec->channel_layout = av_buffersink_get_channel_layout(st->sink); - st->stream->codec->channels = av_buffersink_get_channels(st->sink); - st->stream->codec->sample_rate = av_buffersink_get_sample_rate(st->sink); - st->stream->codec->sample_fmt = av_buffersink_get_format(st->sink); - st->stream->codec->codec_id = - av_get_pcm_codec(st->stream->codec->sample_fmt, -1); + st->stream->codecpar->channel_layout = av_buffersink_get_channel_layout(st->sink); + st->stream->codecpar->channels = av_buffersink_get_channels(st->sink); + st->stream->codecpar->sample_rate = av_buffersink_get_sample_rate(st->sink); + st->stream->codecpar->format = av_buffersink_get_format(st->sink); + st->stream->codecpar->codec_id = av_get_pcm_codec(st->stream->codecpar->format, -1); break; default: av_assert0(!"reached"); @@ -245,7 +243,7 @@ int main(int argc, char **argv) frame); frame = NULL; if (ret < 0) { - av_log(st->stream->codec, AV_LOG_ERROR, + av_log(st->mux, AV_LOG_ERROR, "Error writing frame: %s\n", av_err2str(ret)); goto fail; } From c6f84106366c6f243a8b07dbffcc7880009aa904 Mon Sep 17 00:00:00 2001 From: LongChair Date: Sat, 6 Jan 2018 09:36:58 +0100 Subject: [PATCH 1571/2557] avcodec/rkmpp : Fix broken build due to missing control operation This patch is taking care of https://trac.ffmpeg.org/ticket/6834. It seems that one of the control operations that was available to get the free decoders input slots was removed. There is another control operation to retrieve the used slots. Given that the input slot count is hardcoded to 4 in mpp at this point, replacing the old control operation by the other one. This was tested on Rockchip ROCK64. Signed-off-by: wm4 --- configure | 6 ++---- libavcodec/rkmppdec.c | 10 ++++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 86d81e3cc343e..455f9dc3fe85e 100755 --- a/configure +++ b/configure @@ -5993,10 +5993,8 @@ enabled openssl && { check_pkg_config openssl openssl openssl/ssl.h OP check_lib openssl openssl/ssl.h SSL_library_init -lssl32 -leay32 || check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 || die "ERROR: openssl not found"; } -enabled rkmpp && { { require_pkg_config rkmpp rockchip_mpp rockchip/rk_mpi.h mpp_create || - die "ERROR : Rockchip MPP was not found."; } && - { check_func_headers rockchip/rk_mpi_cmd.h "MPP_DEC_GET_FREE_PACKET_SLOT_COUNT" || - die "ERROR: Rockchip MPP is outdated, please get a more recent one."; } && +enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp rockchip/rk_mpi.h mpp_create && + require_pkg_config rockchip_mpp "rockchip_mpp >= 1.3.7" rockchip/rk_mpi.h mpp_create && { enabled libdrm || die "ERROR: rkmpp requires --enable-libdrm"; } } diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c index c57a6ded380bb..946b827918a63 100644 --- a/libavcodec/rkmppdec.c +++ b/libavcodec/rkmppdec.c @@ -40,6 +40,7 @@ #define RECEIVE_FRAME_TIMEOUT 100 #define FRAMEGROUP_MAX_FRAMES 16 +#define INPUT_MAX_PACKETS 4 typedef struct { MppCtx ctx; @@ -515,16 +516,17 @@ static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame) RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; int ret = MPP_NOK; AVPacket pkt = {0}; - RK_S32 freeslots; + RK_S32 usedslots, freeslots; if (!decoder->eos_reached) { // we get the available slots in decoder - ret = decoder->mpi->control(decoder->ctx, MPP_DEC_GET_FREE_PACKET_SLOT_COUNT, &freeslots); + ret = decoder->mpi->control(decoder->ctx, MPP_DEC_GET_STREAM_COUNT, &usedslots); if (ret != MPP_OK) { - av_log(avctx, AV_LOG_ERROR, "Failed to get decoder free slots (code = %d).\n", ret); + av_log(avctx, AV_LOG_ERROR, "Failed to get decoder used slots (code = %d).\n", ret); return ret; } + freeslots = INPUT_MAX_PACKETS - usedslots; if (freeslots > 0) { ret = ff_decode_get_packet(avctx, &pkt); if (ret < 0 && ret != AVERROR_EOF) { @@ -541,7 +543,7 @@ static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame) } // make sure we keep decoder full - if (freeslots > 1 && decoder->first_frame) + if (freeslots > 1) return AVERROR(EAGAIN); } From 2ca65fc7b74444edd51d5803a2c1e05a801a6023 Mon Sep 17 00:00:00 2001 From: LongChair Date: Tue, 2 Jan 2018 12:38:01 +0100 Subject: [PATCH 1572/2557] avcodec/rkmpp : remove stream start retries before first frame. those were needed because of some odd mpp behavior that seems to have been fixed. Makes the code cleaner. Signed-off-by: wm4 --- libavcodec/rkmppdec.c | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c index 946b827918a63..143d05bd51753 100644 --- a/libavcodec/rkmppdec.c +++ b/libavcodec/rkmppdec.c @@ -47,7 +47,6 @@ typedef struct { MppApi *mpi; MppBufferGroup frame_group; - char first_frame; char first_packet; char eos_reached; @@ -329,28 +328,14 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame) MppBuffer buffer = NULL; AVDRMFrameDescriptor *desc = NULL; AVDRMLayerDescriptor *layer = NULL; - int retrycount = 0; int mode; MppFrameFormat mppformat; uint32_t drmformat; - // on start of decoding, MPP can return -1, which is supposed to be expected - // this is due to some internal MPP init which is not completed, that will - // only happen in the first few frames queries, but should not be interpreted - // as an error, Therefore we need to retry a couple times when we get -1 - // in order to let it time to complete it's init, then we sleep a bit between retries. -retry_get_frame: ret = decoder->mpi->decode_get_frame(decoder->ctx, &mppframe); - if (ret != MPP_OK && ret != MPP_ERR_TIMEOUT && !decoder->first_frame) { - if (retrycount < 5) { - av_log(avctx, AV_LOG_DEBUG, "Failed to get a frame, retrying (code = %d, retrycount = %d)\n", ret, retrycount); - usleep(10000); - retrycount++; - goto retry_get_frame; - } else { - av_log(avctx, AV_LOG_ERROR, "Failed to get a frame from MPP (code = %d)\n", ret); - goto fail; - } + if (ret != MPP_OK && ret != MPP_ERR_TIMEOUT) { + av_log(avctx, AV_LOG_ERROR, "Failed to get a frame from MPP (code = %d)\n", ret); + goto fail; } if (mppframe) { @@ -366,7 +351,6 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame) avctx->height = mpp_frame_get_height(mppframe); decoder->mpi->control(decoder->ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL); - decoder->first_frame = 1; av_buffer_unref(&decoder->frames_ref); @@ -480,7 +464,6 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame) goto fail; } - decoder->first_frame = 0; return 0; } else { av_log(avctx, AV_LOG_ERROR, "Failed to retrieve the frame buffer, frame is dropped (code = %d)\n", ret); @@ -560,7 +543,6 @@ static void rkmpp_flush(AVCodecContext *avctx) ret = decoder->mpi->reset(decoder->ctx); if (ret == MPP_OK) { - decoder->first_frame = 1; decoder->first_packet = 1; } else av_log(avctx, AV_LOG_ERROR, "Failed to reset MPI (code = %d)\n", ret); From 6b35a83214f1bc3fb38c9ea9c2cd3676f28709fa Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 21 Oct 2017 19:31:44 +0100 Subject: [PATCH 1573/2557] Remove the ffserver program Signed-off-by: Rostislav Pehlivanov --- .gitignore | 1 - Changelog | 1 + MAINTAINERS | 3 - README.md | 2 - configure | 4 - doc/ffmpeg-bitstream-filters.texi | 4 +- doc/ffmpeg-codecs.texi | 4 +- doc/ffmpeg-devices.texi | 4 +- doc/ffmpeg-filters.texi | 4 +- doc/ffmpeg-formats.texi | 4 +- doc/ffmpeg-protocols.texi | 4 +- doc/ffmpeg-resampler.texi | 4 +- doc/ffmpeg-scaler.texi | 4 +- doc/ffmpeg-utils.texi | 4 +- doc/ffmpeg.texi | 18 +- doc/ffplay.texi | 4 +- doc/ffprobe.texi | 4 +- doc/ffserver.conf | 372 --- doc/ffserver.texi | 923 ------- doc/issue_tracker.txt | 3 - doc/libavcodec.texi | 4 +- doc/libavdevice.texi | 4 +- doc/libavfilter.texi | 4 +- doc/libavformat.texi | 4 +- doc/libavutil.texi | 4 +- doc/libswresample.texi | 4 +- doc/libswscale.texi | 4 +- doc/mailing-list-faq.texi | 3 +- doc/protocols.texi | 2 +- fftools/Makefile | 4 +- fftools/ffmpeg_opt.c | 97 +- fftools/ffserver.c | 4022 ----------------------------- fftools/ffserver_config.c | 1323 ---------- fftools/ffserver_config.h | 155 -- tests/Makefile | 10 - tests/ffserver-regression.sh | 45 - tests/ffserver.conf | 311 --- tests/ffserver.regression.ref | 11 - tools/bisect-create | 2 +- 39 files changed, 44 insertions(+), 7340 deletions(-) delete mode 100644 doc/ffserver.conf delete mode 100644 doc/ffserver.texi delete mode 100644 fftools/ffserver.c delete mode 100644 fftools/ffserver_config.c delete mode 100644 fftools/ffserver_config.h delete mode 100755 tests/ffserver-regression.sh delete mode 100644 tests/ffserver.conf delete mode 100644 tests/ffserver.regression.ref diff --git a/.gitignore b/.gitignore index dabb51762d32d..0e57cb0b4c4c4 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,6 @@ /ffmpeg /ffplay /ffprobe -/ffserver /config.asm /config.h /coverage.info diff --git a/Changelog b/Changelog index 2f92638d3621d..028c20f4828dd 100644 --- a/Changelog +++ b/Changelog @@ -35,6 +35,7 @@ version : - hilbert audio filter source - aiir audio filter - aiff: add support for CD-ROM XA ADPCM +- Removed the ffserver program version 3.4: diff --git a/MAINTAINERS b/MAINTAINERS index 6a92b5190df52..e5839261af714 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -29,9 +29,6 @@ ffplay: ffprobe: ffprobe.c Stefano Sabatini -ffserver: - ffserver.c Reynaldo H. Verdejo Pinochet - Commandline utility code: cmdutils.c, cmdutils.h Michael Niedermayer diff --git a/README.md b/README.md index 7d5a7efe9eaa9..447347c70064a 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,6 @@ such as audio, video, subtitles and related metadata. * [ffplay](https://ffmpeg.org/ffplay.html) is a minimalistic multimedia player. * [ffprobe](https://ffmpeg.org/ffprobe.html) is a simple analysis tool to inspect multimedia content. -* [ffserver](https://ffmpeg.org/ffserver.html) is a multimedia streaming server - for live broadcasts. * Additional small tools such as `aviocat`, `ismindex` and `qt-faststart`. ## Documentation diff --git a/configure b/configure index 455f9dc3fe85e..c95b52e77d17e 100755 --- a/configure +++ b/configure @@ -116,7 +116,6 @@ Program options: --disable-ffmpeg disable ffmpeg build --disable-ffplay disable ffplay build --disable-ffprobe disable ffprobe build - --disable-ffserver disable ffserver build Documentation options: --disable-doc do not build documentation @@ -1722,7 +1721,6 @@ LICENSE_LIST=" PROGRAM_LIST=" ffplay ffprobe - ffserver ffmpeg " @@ -3358,8 +3356,6 @@ ffplay_select="rdft crop_filter transpose_filter hflip_filter vflip_filter rotat ffplay_suggest="shell32" ffprobe_deps="avcodec avformat" ffprobe_suggest="shell32" -ffserver_deps="avformat fork sarestart" -ffserver_select="ffm_muxer rtp_protocol rtsp_demuxer" # documentation podpages_deps="perl" diff --git a/doc/ffmpeg-bitstream-filters.texi b/doc/ffmpeg-bitstream-filters.texi index bbde25708fcf9..63c0b33a32ebe 100644 --- a/doc/ffmpeg-bitstream-filters.texi +++ b/doc/ffmpeg-bitstream-filters.texi @@ -26,12 +26,12 @@ bitstream level modifications without performing decoding. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{libavcodec.html,libavcodec} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavcodec(3) +ffmpeg(1), ffplay(1), ffprobe(1), libavcodec(3) @end ifnothtml @include authors.texi diff --git a/doc/ffmpeg-codecs.texi b/doc/ffmpeg-codecs.texi index 7df4391ae7bee..e46cd3aeb8f7e 100644 --- a/doc/ffmpeg-codecs.texi +++ b/doc/ffmpeg-codecs.texi @@ -23,12 +23,12 @@ the libavcodec library. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{libavcodec.html,libavcodec} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavcodec(3) +ffmpeg(1), ffplay(1), ffprobe(1), libavcodec(3) @end ifnothtml @include authors.texi diff --git a/doc/ffmpeg-devices.texi b/doc/ffmpeg-devices.texi index 721c0df800b0a..a51de0014ab4b 100644 --- a/doc/ffmpeg-devices.texi +++ b/doc/ffmpeg-devices.texi @@ -23,12 +23,12 @@ libavdevice library. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{libavdevice.html,libavdevice} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavdevice(3) +ffmpeg(1), ffplay(1), ffprobe(1), libavdevice(3) @end ifnothtml @include authors.texi diff --git a/doc/ffmpeg-filters.texi b/doc/ffmpeg-filters.texi index b643f2c02754e..a8ababa9cfbc8 100644 --- a/doc/ffmpeg-filters.texi +++ b/doc/ffmpeg-filters.texi @@ -23,12 +23,12 @@ libavfilter library. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{libavfilter.html,libavfilter} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavfilter(3) +ffmpeg(1), ffplay(1), ffprobe(1), libavfilter(3) @end ifnothtml @include authors.texi diff --git a/doc/ffmpeg-formats.texi b/doc/ffmpeg-formats.texi index d916ee84b72cd..a1917a7267a79 100644 --- a/doc/ffmpeg-formats.texi +++ b/doc/ffmpeg-formats.texi @@ -23,12 +23,12 @@ provided by the libavformat library. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{libavformat.html,libavformat} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavformat(3) +ffmpeg(1), ffplay(1), ffprobe(1), libavformat(3) @end ifnothtml @include authors.texi diff --git a/doc/ffmpeg-protocols.texi b/doc/ffmpeg-protocols.texi index f3a09f6a6957e..7f0e62ac6550d 100644 --- a/doc/ffmpeg-protocols.texi +++ b/doc/ffmpeg-protocols.texi @@ -23,12 +23,12 @@ libavformat library. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{libavformat.html,libavformat} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavformat(3) +ffmpeg(1), ffplay(1), ffprobe(1), libavformat(3) @end ifnothtml @include authors.texi diff --git a/doc/ffmpeg-resampler.texi b/doc/ffmpeg-resampler.texi index be3784f3ed1b4..0e9a3dd950f2f 100644 --- a/doc/ffmpeg-resampler.texi +++ b/doc/ffmpeg-resampler.texi @@ -25,12 +25,12 @@ and convert audio format and packing layout. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{libswresample.html,libswresample} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libswresample(3) +ffmpeg(1), ffplay(1), ffprobe(1), libswresample(3) @end ifnothtml @include authors.texi diff --git a/doc/ffmpeg-scaler.texi b/doc/ffmpeg-scaler.texi index 9ab12a1f95625..d259da9035242 100644 --- a/doc/ffmpeg-scaler.texi +++ b/doc/ffmpeg-scaler.texi @@ -24,12 +24,12 @@ image rescaling and pixel format conversion. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{libswscale.html,libswscale} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libswscale(3) +ffmpeg(1), ffplay(1), ffprobe(1), libswscale(3) @end ifnothtml @include authors.texi diff --git a/doc/ffmpeg-utils.texi b/doc/ffmpeg-utils.texi index e39cfa85ec572..d8e08841ef700 100644 --- a/doc/ffmpeg-utils.texi +++ b/doc/ffmpeg-utils.texi @@ -23,12 +23,12 @@ by the libavutil library. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{libavutil.html,libavutil} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), libavutil(3) +ffmpeg(1), ffplay(1), ffprobe(1), libavutil(3) @end ifnothtml @include authors.texi diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index ba1e62f06fa88..25a0707dc1b18 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1167,10 +1167,6 @@ loss). By default @command{ffmpeg} attempts to read the input(s) as fast as possible. This option will slow down the reading of the input(s) to the native frame rate of the input(s). It is useful for real-time output (e.g. live streaming). -@item -loop_input -Loop over the input stream. Currently it works only for image -streams. This option is used for automatic FFserver testing. -This option is deprecated, use -loop 1. @item -loop_output @var{number_of_times} Repeatedly loop output for formats that support looping such as animated GIF (0 will loop the output infinitely). @@ -1412,16 +1408,6 @@ file or device. With low latency / high rate live streams, packets may be discarded if they are not read in a timely manner; raising this value can avoid it. -@item -override_ffserver (@emph{global}) -Overrides the input specifications from @command{ffserver}. Using this -option you can map any input stream to @command{ffserver} and control -many aspects of the encoding from @command{ffmpeg}. Without this -option @command{ffmpeg} will transmit to @command{ffserver} what is -requested by @command{ffserver}. - -The option is intended for cases where features are needed that cannot be -specified to @command{ffserver} but can be to @command{ffmpeg}. - @item -sdp_file @var{file} (@emph{global}) Print sdp information for an output stream to @var{file}. This allows dumping sdp information when at least one output isn't an @@ -1776,7 +1762,7 @@ ffmpeg -i src.ext -lmax 21*QP2LAMBDA dst.ext @ifset config-not-all @url{ffmpeg-all.html,ffmpeg-all}, @end ifset -@url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffmpeg-utils.html,ffmpeg-utils}, @url{ffmpeg-scaler.html,ffmpeg-scaler}, @url{ffmpeg-resampler.html,ffmpeg-resampler}, @@ -1795,7 +1781,7 @@ ffmpeg(1), @ifset config-not-all ffmpeg-all(1), @end ifset -ffplay(1), ffprobe(1), ffserver(1), +ffplay(1), ffprobe(1), ffmpeg-utils(1), ffmpeg-scaler(1), ffmpeg-resampler(1), ffmpeg-codecs(1), ffmpeg-bitstream-filters(1), ffmpeg-formats(1), ffmpeg-devices(1), ffmpeg-protocols(1), ffmpeg-filters(1) diff --git a/doc/ffplay.texi b/doc/ffplay.texi index a76bed4663a46..c95956ea170ad 100644 --- a/doc/ffplay.texi +++ b/doc/ffplay.texi @@ -291,7 +291,7 @@ Toggle full screen. @ifset config-not-all @url{ffplay-all.html,ffmpeg-all}, @end ifset -@url{ffmpeg.html,ffmpeg}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffprobe.html,ffprobe}, @url{ffmpeg-utils.html,ffmpeg-utils}, @url{ffmpeg-scaler.html,ffmpeg-scaler}, @url{ffmpeg-resampler.html,ffmpeg-resampler}, @@ -310,7 +310,7 @@ ffplay(1), @ifset config-not-all ffplay-all(1), @end ifset -ffmpeg(1), ffprobe(1), ffserver(1), +ffmpeg(1), ffprobe(1), ffmpeg-utils(1), ffmpeg-scaler(1), ffmpeg-resampler(1), ffmpeg-codecs(1), ffmpeg-bitstream-filters(1), ffmpeg-formats(1), ffmpeg-devices(1), ffmpeg-protocols(1), ffmpeg-filters(1) diff --git a/doc/ffprobe.texi b/doc/ffprobe.texi index e3c34babdc7a0..4e9f184a1db83 100644 --- a/doc/ffprobe.texi +++ b/doc/ffprobe.texi @@ -653,7 +653,7 @@ DV, GXF and AVI timecodes are available in format metadata @ifset config-not-all @url{ffprobe-all.html,ffprobe-all}, @end ifset -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffmpeg-utils.html,ffmpeg-utils}, @url{ffmpeg-scaler.html,ffmpeg-scaler}, @url{ffmpeg-resampler.html,ffmpeg-resampler}, @@ -672,7 +672,7 @@ ffprobe(1), @ifset config-not-all ffprobe-all(1), @end ifset -ffmpeg(1), ffplay(1), ffserver(1), +ffmpeg(1), ffplay(1), ffmpeg-utils(1), ffmpeg-scaler(1), ffmpeg-resampler(1), ffmpeg-codecs(1), ffmpeg-bitstream-filters(1), ffmpeg-formats(1), ffmpeg-devices(1), ffmpeg-protocols(1), ffmpeg-filters(1) diff --git a/doc/ffserver.conf b/doc/ffserver.conf deleted file mode 100644 index e3f99bbfb3d72..0000000000000 --- a/doc/ffserver.conf +++ /dev/null @@ -1,372 +0,0 @@ -# Port on which the server is listening. You must select a different -# port from your standard HTTP web server if it is running on the same -# computer. -HTTPPort 8090 - -# Address on which the server is bound. Only useful if you have -# several network interfaces. -HTTPBindAddress 0.0.0.0 - -# Number of simultaneous HTTP connections that can be handled. It has -# to be defined *before* the MaxClients parameter, since it defines the -# MaxClients maximum limit. -MaxHTTPConnections 2000 - -# Number of simultaneous requests that can be handled. Since FFServer -# is very fast, it is more likely that you will want to leave this high -# and use MaxBandwidth, below. -MaxClients 1000 - -# This the maximum amount of kbit/sec that you are prepared to -# consume when streaming to clients. -MaxBandwidth 1000 - -# Access log file (uses standard Apache log file format) -# '-' is the standard output. -CustomLog - - -################################################################## -# Definition of the live feeds. Each live feed contains one video -# and/or audio sequence coming from an ffmpeg encoder or another -# ffserver. This sequence may be encoded simultaneously with several -# codecs at several resolutions. - - - -# You must use 'ffmpeg' to send a live feed to ffserver. In this -# example, you can type: -# -# ffmpeg http://localhost:8090/feed1.ffm - -# ffserver can also do time shifting. It means that it can stream any -# previously recorded live stream. The request should contain: -# "http://xxxx?date=[YYYY-MM-DDT][[HH:]MM:]SS[.m...]".You must specify -# a path where the feed is stored on disk. You also specify the -# maximum size of the feed, where zero means unlimited. Default: -# File=/tmp/feed_name.ffm FileMaxSize=5M -File /tmp/feed1.ffm -FileMaxSize 200K - -# You could specify -# ReadOnlyFile /saved/specialvideo.ffm -# This marks the file as readonly and it will not be deleted or updated. - -# Specify launch in order to start ffmpeg automatically. -# First ffmpeg must be defined with an appropriate path if needed, -# after that options can follow, but avoid adding the http:// field -#Launch ffmpeg - -# Only allow connections from localhost to the feed. -ACL allow 127.0.0.1 - - - - -################################################################## -# Now you can define each stream which will be generated from the -# original audio and video stream. Each format has a filename (here -# 'test1.mpg'). FFServer will send this stream when answering a -# request containing this filename. - - - -# coming from live feed 'feed1' -Feed feed1.ffm - -# Format of the stream : you can choose among: -# mpeg : MPEG-1 multiplexed video and audio -# mpegvideo : only MPEG-1 video -# mp2 : MPEG-2 audio (use AudioCodec to select layer 2 and 3 codec) -# ogg : Ogg format (Vorbis audio codec) -# rm : RealNetworks-compatible stream. Multiplexed audio and video. -# ra : RealNetworks-compatible stream. Audio only. -# mpjpeg : Multipart JPEG (works with Netscape without any plugin) -# jpeg : Generate a single JPEG image. -# mjpeg : Generate a M-JPEG stream. -# asf : ASF compatible streaming (Windows Media Player format). -# swf : Macromedia Flash compatible stream -# avi : AVI format (MPEG-4 video, MPEG audio sound) -Format mpeg - -# Bitrate for the audio stream. Codecs usually support only a few -# different bitrates. -AudioBitRate 32 - -# Number of audio channels: 1 = mono, 2 = stereo -AudioChannels 1 - -# Sampling frequency for audio. When using low bitrates, you should -# lower this frequency to 22050 or 11025. The supported frequencies -# depend on the selected audio codec. -AudioSampleRate 44100 - -# Bitrate for the video stream -VideoBitRate 64 - -# Ratecontrol buffer size -VideoBufferSize 40 - -# Number of frames per second -VideoFrameRate 3 - -# Size of the video frame: WxH (default: 160x128) -# The following abbreviations are defined: sqcif, qcif, cif, 4cif, qqvga, -# qvga, vga, svga, xga, uxga, qxga, sxga, qsxga, hsxga, wvga, wxga, wsxga, -# wuxga, woxga, wqsxga, wquxga, whsxga, whuxga, cga, ega, hd480, hd720, -# hd1080 -VideoSize 160x128 - -# Transmit only intra frames (useful for low bitrates, but kills frame rate). -#VideoIntraOnly - -# If non-intra only, an intra frame is transmitted every VideoGopSize -# frames. Video synchronization can only begin at an intra frame. -VideoGopSize 12 - -# More MPEG-4 parameters -# VideoHighQuality -# Video4MotionVector - -# Choose your codecs: -#AudioCodec mp2 -#VideoCodec mpeg1video - -# Suppress audio -#NoAudio - -# Suppress video -#NoVideo - -#VideoQMin 3 -#VideoQMax 31 - -# Set this to the number of seconds backwards in time to start. Note that -# most players will buffer 5-10 seconds of video, and also you need to allow -# for a keyframe to appear in the data stream. -#Preroll 15 - -# ACL: - -# You can allow ranges of addresses (or single addresses) -#ACL ALLOW - -# You can deny ranges of addresses (or single addresses) -#ACL DENY - -# You can repeat the ACL allow/deny as often as you like. It is on a per -# stream basis. The first match defines the action. If there are no matches, -# then the default is the inverse of the last ACL statement. -# -# Thus 'ACL allow localhost' only allows access from localhost. -# 'ACL deny 1.0.0.0 1.255.255.255' would deny the whole of network 1 and -# allow everybody else. - - - - -################################################################## -# Example streams - - -# Multipart JPEG - -# -#Feed feed1.ffm -#Format mpjpeg -#VideoFrameRate 2 -#VideoIntraOnly -#NoAudio -#Strict -1 -# - - -# Single JPEG - -# -#Feed feed1.ffm -#Format jpeg -#VideoFrameRate 2 -#VideoIntraOnly -##VideoSize 352x240 -#NoAudio -#Strict -1 -# - - -# Flash - -# -#Feed feed1.ffm -#Format swf -#VideoFrameRate 2 -#VideoIntraOnly -#NoAudio -# - - -# ASF compatible - - -Feed feed1.ffm -Format asf -VideoFrameRate 15 -VideoSize 352x240 -VideoBitRate 256 -VideoBufferSize 40 -VideoGopSize 30 -AudioBitRate 64 -StartSendOnKey - - - -# MP3 audio - -# -#Feed feed1.ffm -#Format mp2 -#AudioCodec mp3 -#AudioBitRate 64 -#AudioChannels 1 -#AudioSampleRate 44100 -#NoVideo -# - - -# Ogg Vorbis audio - -# -#Feed feed1.ffm -#Metadata title "Stream title" -#AudioBitRate 64 -#AudioChannels 2 -#AudioSampleRate 44100 -#NoVideo -# - - -# Real with audio only at 32 kbits - -# -#Feed feed1.ffm -#Format rm -#AudioBitRate 32 -#NoVideo -#NoAudio -# - - -# Real with audio and video at 64 kbits - -# -#Feed feed1.ffm -#Format rm -#AudioBitRate 32 -#VideoBitRate 128 -#VideoFrameRate 25 -#VideoGopSize 25 -#NoAudio -# - - -################################################################## -# A stream coming from a file: you only need to set the input -# filename and optionally a new format. Supported conversions: -# AVI -> ASF - -# -#File "/usr/local/httpd/htdocs/tlive.rm" -#NoAudio -# - -# -#File "/usr/local/httpd/htdocs/test.asf" -#NoAudio -#Metadata author "Me" -#Metadata copyright "Super MegaCorp" -#Metadata title "Test stream from disk" -#Metadata comment "Test comment" -# - - -################################################################## -# RTSP examples -# -# You can access this stream with the RTSP URL: -# rtsp://localhost:5454/test1-rtsp.mpg -# -# A non-standard RTSP redirector is also created. Its URL is: -# http://localhost:8090/test1-rtsp.rtsp - -# -#Format rtp -#File "/usr/local/httpd/htdocs/test1.mpg" -# - - -# Transcode an incoming live feed to another live feed, -# using libx264 and video presets - -# -#Format rtp -#Feed feed1.ffm -#VideoCodec libx264 -#VideoFrameRate 24 -#VideoBitRate 100 -#VideoSize 480x272 -#AVPresetVideo default -#AVPresetVideo baseline -#AVOptionVideo flags +global_header -# -#AudioCodec aac -#AudioBitRate 32 -#AudioChannels 2 -#AudioSampleRate 22050 -#AVOptionAudio flags +global_header -# - -################################################################## -# SDP/multicast examples -# -# If you want to send your stream in multicast, you must set the -# multicast address with MulticastAddress. The port and the TTL can -# also be set. -# -# An SDP file is automatically generated by ffserver by adding the -# 'sdp' extension to the stream name (here -# http://localhost:8090/test1-sdp.sdp). You should usually give this -# file to your player to play the stream. -# -# The 'NoLoop' option can be used to avoid looping when the stream is -# terminated. - -# -#Format rtp -#File "/usr/local/httpd/htdocs/test1.mpg" -#MulticastAddress 224.124.0.1 -#MulticastPort 5000 -#MulticastTTL 16 -#NoLoop -# - - -################################################################## -# Special streams - -# Server status - - -Format status - -# Only allow local people to get the status -ACL allow localhost -ACL allow 192.168.0.0 192.168.255.255 - -#FaviconURL http://pond1.gladstonefamily.net:8080/favicon.ico - - - -# Redirect index.html to the appropriate site - - -URL http://www.ffmpeg.org/ - diff --git a/doc/ffserver.texi b/doc/ffserver.texi deleted file mode 100644 index b3e1f1d7ef9a7..0000000000000 --- a/doc/ffserver.texi +++ /dev/null @@ -1,923 +0,0 @@ -\input texinfo @c -*- texinfo -*- -@documentencoding UTF-8 - -@settitle ffserver Documentation -@titlepage -@center @titlefont{ffserver Documentation} -@end titlepage - -@top - -@contents - -@chapter Synopsis - -ffserver [@var{options}] - -@chapter Description -@c man begin DESCRIPTION - -@command{ffserver} is a streaming server for both audio and video. -It supports several live feeds, streaming from files and time shifting -on live feeds. You can seek to positions in the past on each live -feed, provided you specify a big enough feed storage. - -@command{ffserver} is configured through a configuration file, which -is read at startup. If not explicitly specified, it will read from -@file{/etc/ffserver.conf}. - -@command{ffserver} receives prerecorded files or FFM streams from some -@command{ffmpeg} instance as input, then streams them over -RTP/RTSP/HTTP. - -An @command{ffserver} instance will listen on some port as specified -in the configuration file. You can launch one or more instances of -@command{ffmpeg} and send one or more FFM streams to the port where -ffserver is expecting to receive them. Alternately, you can make -@command{ffserver} launch such @command{ffmpeg} instances at startup. - -Input streams are called feeds, and each one is specified by a -@code{} section in the configuration file. - -For each feed you can have different output streams in various -formats, each one specified by a @code{} section in the -configuration file. - -@chapter Detailed description - -@command{ffserver} works by forwarding streams encoded by -@command{ffmpeg}, or pre-recorded streams which are read from disk. - -Precisely, @command{ffserver} acts as an HTTP server, accepting POST -requests from @command{ffmpeg} to acquire the stream to publish, and -serving RTSP clients or HTTP clients GET requests with the stream -media content. - -A feed is an @ref{FFM} stream created by @command{ffmpeg}, and sent to -a port where @command{ffserver} is listening. - -Each feed is identified by a unique name, corresponding to the name -of the resource published on @command{ffserver}, and is configured by -a dedicated @code{Feed} section in the configuration file. - -The feed publish URL is given by: -@example -http://@var{ffserver_ip_address}:@var{http_port}/@var{feed_name} -@end example - -where @var{ffserver_ip_address} is the IP address of the machine where -@command{ffserver} is installed, @var{http_port} is the port number of -the HTTP server (configured through the @option{HTTPPort} option), and -@var{feed_name} is the name of the corresponding feed defined in the -configuration file. - -Each feed is associated to a file which is stored on disk. This stored -file is used to send pre-recorded data to a player as fast as -possible when new content is added in real-time to the stream. - -A "live-stream" or "stream" is a resource published by -@command{ffserver}, and made accessible through the HTTP protocol to -clients. - -A stream can be connected to a feed, or to a file. In the first case, -the published stream is forwarded from the corresponding feed -generated by a running instance of @command{ffmpeg}, in the second -case the stream is read from a pre-recorded file. - -Each stream is identified by a unique name, corresponding to the name -of the resource served by @command{ffserver}, and is configured by -a dedicated @code{Stream} section in the configuration file. - -The stream access HTTP URL is given by: -@example -http://@var{ffserver_ip_address}:@var{http_port}/@var{stream_name}[@var{options}] -@end example - -The stream access RTSP URL is given by: -@example -http://@var{ffserver_ip_address}:@var{rtsp_port}/@var{stream_name}[@var{options}] -@end example - -@var{stream_name} is the name of the corresponding stream defined in -the configuration file. @var{options} is a list of options specified -after the URL which affects how the stream is served by -@command{ffserver}. @var{http_port} and @var{rtsp_port} are the HTTP -and RTSP ports configured with the options @var{HTTPPort} and -@var{RTSPPort} respectively. - -In case the stream is associated to a feed, the encoding parameters -must be configured in the stream configuration. They are sent to -@command{ffmpeg} when setting up the encoding. This allows -@command{ffserver} to define the encoding parameters used by -the @command{ffmpeg} encoders. - -The @command{ffmpeg} @option{override_ffserver} commandline option -allows one to override the encoding parameters set by the server. - -Multiple streams can be connected to the same feed. - -For example, you can have a situation described by the following -graph: - -@verbatim - _________ __________ - | | | | -ffmpeg 1 -----| feed 1 |-----| stream 1 | - \ |_________|\ |__________| - \ \ - \ \ __________ - \ \ | | - \ \| stream 2 | - \ |__________| - \ - \ _________ __________ - \ | | | | - \| feed 2 |-----| stream 3 | - |_________| |__________| - - _________ __________ - | | | | -ffmpeg 2 -----| feed 3 |-----| stream 4 | - |_________| |__________| - - _________ __________ - | | | | - | file 1 |-----| stream 5 | - |_________| |__________| - -@end verbatim - -@anchor{FFM} -@section FFM, FFM2 formats - -FFM and FFM2 are formats used by ffserver. They allow storing a wide variety of -video and audio streams and encoding options, and can store a moving time segment -of an infinite movie or a whole movie. - -FFM is version specific, and there is limited compatibility of FFM files -generated by one version of ffmpeg/ffserver and another version of -ffmpeg/ffserver. It may work but it is not guaranteed to work. - -FFM2 is extensible while maintaining compatibility and should work between -differing versions of tools. FFM2 is the default. - -@section Status stream - -@command{ffserver} supports an HTTP interface which exposes the -current status of the server. - -Simply point your browser to the address of the special status stream -specified in the configuration file. - -For example if you have: -@example - -Format status - -# Only allow local people to get the status -ACL allow localhost -ACL allow 192.168.0.0 192.168.255.255 - -@end example - -then the server will post a page with the status information when -the special stream @file{status.html} is requested. - -@section How do I make it work? - -As a simple test, just run the following two command lines where INPUTFILE -is some file which you can decode with ffmpeg: - -@example -ffserver -f doc/ffserver.conf & -ffmpeg -i INPUTFILE http://localhost:8090/feed1.ffm -@end example - -At this point you should be able to go to your Windows machine and fire up -Windows Media Player (WMP). Go to Open URL and enter - -@example - http://:8090/test.asf -@end example - -You should (after a short delay) see video and hear audio. - -WARNING: trying to stream test1.mpg doesn't work with WMP as it tries to -transfer the entire file before starting to play. -The same is true of AVI files. - -You should edit the @file{ffserver.conf} file to suit your needs (in -terms of frame rates etc). Then install @command{ffserver} and -@command{ffmpeg}, write a script to start them up, and off you go. - -@section What else can it do? - -You can replay video from .ffm files that was recorded earlier. -However, there are a number of caveats, including the fact that the -ffserver parameters must match the original parameters used to record the -file. If they do not, then ffserver deletes the file before recording into it. -(Now that I write this, it seems broken). - -You can fiddle with many of the codec choices and encoding parameters, and -there are a bunch more parameters that you cannot control. Post a message -to the mailing list if there are some 'must have' parameters. Look in -ffserver.conf for a list of the currently available controls. - -It will automatically generate the ASX or RAM files that are often used -in browsers. These files are actually redirections to the underlying ASF -or RM file. The reason for this is that the browser often fetches the -entire file before starting up the external viewer. The redirection files -are very small and can be transferred quickly. [The stream itself is -often 'infinite' and thus the browser tries to download it and never -finishes.] - -@section Tips - -* When you connect to a live stream, most players (WMP, RA, etc) want to -buffer a certain number of seconds of material so that they can display the -signal continuously. However, ffserver (by default) starts sending data -in realtime. This means that there is a pause of a few seconds while the -buffering is being done by the player. The good news is that this can be -cured by adding a '?buffer=5' to the end of the URL. This means that the -stream should start 5 seconds in the past -- and so the first 5 seconds -of the stream are sent as fast as the network will allow. It will then -slow down to real time. This noticeably improves the startup experience. - -You can also add a 'Preroll 15' statement into the ffserver.conf that will -add the 15 second prebuffering on all requests that do not otherwise -specify a time. In addition, ffserver will skip frames until a key_frame -is found. This further reduces the startup delay by not transferring data -that will be discarded. - -@section Why does the ?buffer / Preroll stop working after a time? - -It turns out that (on my machine at least) the number of frames successfully -grabbed is marginally less than the number that ought to be grabbed. This -means that the timestamp in the encoded data stream gets behind realtime. -This means that if you say 'Preroll 10', then when the stream gets 10 -or more seconds behind, there is no Preroll left. - -Fixing this requires a change in the internals of how timestamps are -handled. - -@section Does the @code{?date=} stuff work. - -Yes (subject to the limitation outlined above). Also note that whenever you -start ffserver, it deletes the ffm file (if any parameters have changed), -thus wiping out what you had recorded before. - -The format of the @code{?date=xxxxxx} is fairly flexible. You should use one -of the following formats (the 'T' is literal): - -@example -* YYYY-MM-DDTHH:MM:SS (localtime) -* YYYY-MM-DDTHH:MM:SSZ (UTC) -@end example - -You can omit the YYYY-MM-DD, and then it refers to the current day. However -note that @samp{?date=16:00:00} refers to 16:00 on the current day -- this -may be in the future and so is unlikely to be useful. - -You use this by adding the ?date= to the end of the URL for the stream. -For example: @samp{http://localhost:8080/test.asf?date=2002-07-26T23:05:00}. -@c man end - -@chapter Options -@c man begin OPTIONS - -@include fftools-common-opts.texi - -@section Main options - -@table @option -@item -f @var{configfile} -Read configuration file @file{configfile}. If not specified it will -read by default from @file{/etc/ffserver.conf}. - -@item -n -Enable no-launch mode. This option disables all the @code{Launch} -directives within the various @code{} sections. Since -@command{ffserver} will not launch any @command{ffmpeg} instances, you -will have to launch them manually. - -@item -d -Enable debug mode. This option increases log verbosity, and directs -log messages to stdout. When specified, the @option{CustomLog} option -is ignored. -@end table - -@chapter Configuration file syntax - -@command{ffserver} reads a configuration file containing global -options and settings for each stream and feed. - -The configuration file consists of global options and dedicated -sections, which must be introduced by "<@var{SECTION_NAME} -@var{ARGS}>" on a separate line and must be terminated by a line in -the form "". @var{ARGS} is optional. - -Currently the following sections are recognized: @samp{Feed}, -@samp{Stream}, @samp{Redirect}. - -A line starting with @code{#} is ignored and treated as a comment. - -Name of options and sections are case-insensitive. - -@section ACL syntax -An ACL (Access Control List) specifies the address which are allowed -to access a given stream, or to write a given feed. - -It accepts the following forms -@itemize -@item -Allow/deny access to @var{address}. -@example -ACL ALLOW
-ACL DENY
-@end example - -@item -Allow/deny access to ranges of addresses from @var{first_address} to -@var{last_address}. -@example -ACL ALLOW -ACL DENY -@end example -@end itemize - -You can repeat the ACL allow/deny as often as you like. It is on a per -stream basis. The first match defines the action. If there are no matches, -then the default is the inverse of the last ACL statement. - -Thus 'ACL allow localhost' only allows access from localhost. -'ACL deny 1.0.0.0 1.255.255.255' would deny the whole of network 1 and -allow everybody else. - -@section Global options -@table @option -@item HTTPPort @var{port_number} -@item Port @var{port_number} -@item RTSPPort @var{port_number} - -@var{HTTPPort} sets the HTTP server listening TCP port number, -@var{RTSPPort} sets the RTSP server listening TCP port number. - -@var{Port} is the equivalent of @var{HTTPPort} and is deprecated. - -You must select a different port from your standard HTTP web server if -it is running on the same computer. - -If not specified, no corresponding server will be created. - -@item HTTPBindAddress @var{ip_address} -@item BindAddress @var{ip_address} -@item RTSPBindAddress @var{ip_address} -Set address on which the HTTP/RTSP server is bound. Only useful if you -have several network interfaces. - -@var{BindAddress} is the equivalent of @var{HTTPBindAddress} and is -deprecated. - -@item MaxHTTPConnections @var{n} -Set number of simultaneous HTTP connections that can be handled. It -has to be defined @emph{before} the @option{MaxClients} parameter, -since it defines the @option{MaxClients} maximum limit. - -Default value is 2000. - -@item MaxClients @var{n} -Set number of simultaneous requests that can be handled. Since -@command{ffserver} is very fast, it is more likely that you will want -to leave this high and use @option{MaxBandwidth}. - -Default value is 5. - -@item MaxBandwidth @var{kbps} -Set the maximum amount of kbit/sec that you are prepared to consume -when streaming to clients. - -Default value is 1000. - -@item CustomLog @var{filename} -Set access log file (uses standard Apache log file format). '-' is the -standard output. - -If not specified @command{ffserver} will produce no log. - -In case the commandline option @option{-d} is specified this option is -ignored, and the log is written to standard output. - -@item NoDaemon -Set no-daemon mode. This option is currently ignored since now -@command{ffserver} will always work in no-daemon mode, and is -deprecated. - -@item UseDefaults -@item NoDefaults -Control whether default codec options are used for the all streams or not. -Each stream may overwrite this setting for its own. Default is @var{UseDefaults}. -The last occurrence overrides the previous if multiple definitions exist. -@end table - -@section Feed section - -A Feed section defines a feed provided to @command{ffserver}. - -Each live feed contains one video and/or audio sequence coming from an -@command{ffmpeg} encoder or another @command{ffserver}. This sequence -may be encoded simultaneously with several codecs at several -resolutions. - -A feed instance specification is introduced by a line in the form: -@example - -@end example - -where @var{FEED_FILENAME} specifies the unique name of the FFM stream. - -The following options are recognized within a Feed section. - -@table @option -@item File @var{filename} -@item ReadOnlyFile @var{filename} -Set the path where the feed file is stored on disk. - -If not specified, the @file{/tmp/FEED.ffm} is assumed, where -@var{FEED} is the feed name. - -If @option{ReadOnlyFile} is used the file is marked as read-only and -it will not be deleted or updated. - -@item Truncate -Truncate the feed file, rather than appending to it. By default -@command{ffserver} will append data to the file, until the maximum -file size value is reached (see @option{FileMaxSize} option). - -@item FileMaxSize @var{size} -Set maximum size of the feed file in bytes. 0 means unlimited. The -postfixes @code{K} (2^10), @code{M} (2^20), and @code{G} (2^30) are -recognized. - -Default value is 5M. - -@item Launch @var{args} -Launch an @command{ffmpeg} command when creating @command{ffserver}. - -@var{args} must be a sequence of arguments to be provided to an -@command{ffmpeg} instance. The first provided argument is ignored, and -it is replaced by a path with the same dirname of the @command{ffserver} -instance, followed by the remaining argument and terminated with a -path corresponding to the feed. - -When the launched process exits, @command{ffserver} will launch -another program instance. - -In case you need a more complex @command{ffmpeg} configuration, -e.g. if you need to generate multiple FFM feeds with a single -@command{ffmpeg} instance, you should launch @command{ffmpeg} by hand. - -This option is ignored in case the commandline option @option{-n} is -specified. - -@item ACL @var{spec} -Specify the list of IP address which are allowed or denied to write -the feed. Multiple ACL options can be specified. -@end table - -@section Stream section - -A Stream section defines a stream provided by @command{ffserver}, and -identified by a single name. - -The stream is sent when answering a request containing the stream -name. - -A stream section must be introduced by the line: -@example - -@end example - -where @var{STREAM_NAME} specifies the unique name of the stream. - -The following options are recognized within a Stream section. - -Encoding options are marked with the @emph{encoding} tag, and they are -used to set the encoding parameters, and are mapped to libavcodec -encoding options. Not all encoding options are supported, in -particular it is not possible to set encoder private options. In order -to override the encoding options specified by @command{ffserver}, you -can use the @command{ffmpeg} @option{override_ffserver} commandline -option. - -Only one of the @option{Feed} and @option{File} options should be set. - -@table @option -@item Feed @var{feed_name} -Set the input feed. @var{feed_name} must correspond to an existing -feed defined in a @code{Feed} section. - -When this option is set, encoding options are used to setup the -encoding operated by the remote @command{ffmpeg} process. - -@item File @var{filename} -Set the filename of the pre-recorded input file to stream. - -When this option is set, encoding options are ignored and the input -file content is re-streamed as is. - -@item Format @var{format_name} -Set the format of the output stream. - -Must be the name of a format recognized by FFmpeg. If set to -@samp{status}, it is treated as a status stream. - -@item InputFormat @var{format_name} -Set input format. If not specified, it is automatically guessed. - -@item Preroll @var{n} -Set this to the number of seconds backwards in time to start. Note that -most players will buffer 5-10 seconds of video, and also you need to allow -for a keyframe to appear in the data stream. - -Default value is 0. - -@item StartSendOnKey -Do not send stream until it gets the first key frame. By default -@command{ffserver} will send data immediately. - -@item MaxTime @var{n} -Set the number of seconds to run. This value set the maximum duration -of the stream a client will be able to receive. - -A value of 0 means that no limit is set on the stream duration. - -@item ACL @var{spec} -Set ACL for the stream. - -@item DynamicACL @var{spec} - -@item RTSPOption @var{option} - -@item MulticastAddress @var{address} - -@item MulticastPort @var{port} - -@item MulticastTTL @var{integer} - -@item NoLoop - -@item FaviconURL @var{url} -Set favicon (favourite icon) for the server status page. It is ignored -for regular streams. - -@item Author @var{value} -@item Comment @var{value} -@item Copyright @var{value} -@item Title @var{value} -Set metadata corresponding to the option. All these options are -deprecated in favor of @option{Metadata}. - -@item Metadata @var{key} @var{value} -Set metadata value on the output stream. - -@item UseDefaults -@item NoDefaults -Control whether default codec options are used for the stream or not. -Default is @var{UseDefaults} unless disabled globally. - -@item NoAudio -@item NoVideo -Suppress audio/video. - -@item AudioCodec @var{codec_name} (@emph{encoding,audio}) -Set audio codec. - -@item AudioBitRate @var{rate} (@emph{encoding,audio}) -Set bitrate for the audio stream in kbits per second. - -@item AudioChannels @var{n} (@emph{encoding,audio}) -Set number of audio channels. - -@item AudioSampleRate @var{n} (@emph{encoding,audio}) -Set sampling frequency for audio. When using low bitrates, you should -lower this frequency to 22050 or 11025. The supported frequencies -depend on the selected audio codec. - -@item AVOptionAudio [@var{codec}:]@var{option} @var{value} (@emph{encoding,audio}) -Set generic or private option for audio stream. -Private option must be prefixed with codec name or codec must be defined before. - -@item AVPresetAudio @var{preset} (@emph{encoding,audio}) -Set preset for audio stream. - -@item VideoCodec @var{codec_name} (@emph{encoding,video}) -Set video codec. - -@item VideoBitRate @var{n} (@emph{encoding,video}) -Set bitrate for the video stream in kbits per second. - -@item VideoBitRateRange @var{range} (@emph{encoding,video}) -Set video bitrate range. - -A range must be specified in the form @var{minrate}-@var{maxrate}, and -specifies the @option{minrate} and @option{maxrate} encoding options -expressed in kbits per second. - -@item VideoBitRateRangeTolerance @var{n} (@emph{encoding,video}) -Set video bitrate tolerance in kbits per second. - -@item PixelFormat @var{pixel_format} (@emph{encoding,video}) -Set video pixel format. - -@item Debug @var{integer} (@emph{encoding,video}) -Set video @option{debug} encoding option. - -@item Strict @var{integer} (@emph{encoding,video}) -Set video @option{strict} encoding option. - -@item VideoBufferSize @var{n} (@emph{encoding,video}) -Set ratecontrol buffer size, expressed in KB. - -@item VideoFrameRate @var{n} (@emph{encoding,video}) -Set number of video frames per second. - -@item VideoSize (@emph{encoding,video}) -Set size of the video frame, must be an abbreviation or in the form -@var{W}x@var{H}. See @ref{video size syntax,,the Video size section -in the ffmpeg-utils(1) manual,ffmpeg-utils}. - -Default value is @code{160x128}. - -@item VideoIntraOnly (@emph{encoding,video}) -Transmit only intra frames (useful for low bitrates, but kills frame rate). - -@item VideoGopSize @var{n} (@emph{encoding,video}) -If non-intra only, an intra frame is transmitted every VideoGopSize -frames. Video synchronization can only begin at an intra frame. - -@item VideoTag @var{tag} (@emph{encoding,video}) -Set video tag. - -@item VideoHighQuality (@emph{encoding,video}) -@item Video4MotionVector (@emph{encoding,video}) - -@item BitExact (@emph{encoding,video}) -Set bitexact encoding flag. - -@item IdctSimple (@emph{encoding,video}) -Set simple IDCT algorithm. - -@item Qscale @var{n} (@emph{encoding,video}) -Enable constant quality encoding, and set video qscale (quantization -scale) value, expressed in @var{n} QP units. - -@item VideoQMin @var{n} (@emph{encoding,video}) -@item VideoQMax @var{n} (@emph{encoding,video}) -Set video qmin/qmax. - -@item VideoQDiff @var{integer} (@emph{encoding,video}) -Set video @option{qdiff} encoding option. - -@item LumiMask @var{float} (@emph{encoding,video}) -@item DarkMask @var{float} (@emph{encoding,video}) -Set @option{lumi_mask}/@option{dark_mask} encoding options. - -@item AVOptionVideo [@var{codec}:]@var{option} @var{value} (@emph{encoding,video}) -Set generic or private option for video stream. -Private option must be prefixed with codec name or codec must be defined before. - -@item AVPresetVideo @var{preset} (@emph{encoding,video}) -Set preset for video stream. - -@var{preset} must be the path of a preset file. -@end table - -@subsection Server status stream - -A server status stream is a special stream which is used to show -statistics about the @command{ffserver} operations. - -It must be specified setting the option @option{Format} to -@samp{status}. - -@section Redirect section - -A redirect section specifies where to redirect the requested URL to -another page. - -A redirect section must be introduced by the line: -@example - -@end example - -where @var{NAME} is the name of the page which should be redirected. - -It only accepts the option @option{URL}, which specify the redirection -URL. - -@chapter Stream examples - -@itemize -@item -Multipart JPEG -@example - -Feed feed1.ffm -Format mpjpeg -VideoFrameRate 2 -VideoIntraOnly -NoAudio -Strict -1 - -@end example - -@item -Single JPEG -@example - -Feed feed1.ffm -Format jpeg -VideoFrameRate 2 -VideoIntraOnly -VideoSize 352x240 -NoAudio -Strict -1 - -@end example - -@item -Flash -@example - -Feed feed1.ffm -Format swf -VideoFrameRate 2 -VideoIntraOnly -NoAudio - -@end example - -@item -ASF compatible -@example - -Feed feed1.ffm -Format asf -VideoFrameRate 15 -VideoSize 352x240 -VideoBitRate 256 -VideoBufferSize 40 -VideoGopSize 30 -AudioBitRate 64 -StartSendOnKey - -@end example - -@item -MP3 audio -@example - -Feed feed1.ffm -Format mp2 -AudioCodec mp3 -AudioBitRate 64 -AudioChannels 1 -AudioSampleRate 44100 -NoVideo - -@end example - -@item -Ogg Vorbis audio -@example - -Feed feed1.ffm -Metadata title "Stream title" -AudioBitRate 64 -AudioChannels 2 -AudioSampleRate 44100 -NoVideo - -@end example - -@item -Real with audio only at 32 kbits -@example - -Feed feed1.ffm -Format rm -AudioBitRate 32 -NoVideo - -@end example - -@item -Real with audio and video at 64 kbits -@example - -Feed feed1.ffm -Format rm -AudioBitRate 32 -VideoBitRate 128 -VideoFrameRate 25 -VideoGopSize 25 - -@end example - -@item -For stream coming from a file: you only need to set the input filename -and optionally a new format. - -@example - -File "/usr/local/httpd/htdocs/tlive.rm" -NoAudio - -@end example - -@example - -File "/usr/local/httpd/htdocs/test.asf" -NoAudio -Metadata author "Me" -Metadata copyright "Super MegaCorp" -Metadata title "Test stream from disk" -Metadata comment "Test comment" - -@end example -@end itemize - -@c man end - -@include config.texi -@ifset config-all -@ifset config-avutil -@include utils.texi -@end ifset -@ifset config-avcodec -@include codecs.texi -@include bitstream_filters.texi -@end ifset -@ifset config-avformat -@include formats.texi -@include protocols.texi -@end ifset -@ifset config-avdevice -@include devices.texi -@end ifset -@ifset config-swresample -@include resampler.texi -@end ifset -@ifset config-swscale -@include scaler.texi -@end ifset -@ifset config-avfilter -@include filters.texi -@end ifset -@end ifset - -@chapter See Also - -@ifhtml -@ifset config-all -@url{ffserver.html,ffserver}, -@end ifset -@ifset config-not-all -@url{ffserver-all.html,ffserver-all}, -@end ifset -the @file{doc/ffserver.conf} example, -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, -@url{ffmpeg-utils.html,ffmpeg-utils}, -@url{ffmpeg-scaler.html,ffmpeg-scaler}, -@url{ffmpeg-resampler.html,ffmpeg-resampler}, -@url{ffmpeg-codecs.html,ffmpeg-codecs}, -@url{ffmpeg-bitstream-filters.html,ffmpeg-bitstream-filters}, -@url{ffmpeg-formats.html,ffmpeg-formats}, -@url{ffmpeg-devices.html,ffmpeg-devices}, -@url{ffmpeg-protocols.html,ffmpeg-protocols}, -@url{ffmpeg-filters.html,ffmpeg-filters} -@end ifhtml - -@ifnothtml -@ifset config-all -ffserver(1), -@end ifset -@ifset config-not-all -ffserver-all(1), -@end ifset -the @file{doc/ffserver.conf} example, ffmpeg(1), ffplay(1), ffprobe(1), -ffmpeg-utils(1), ffmpeg-scaler(1), ffmpeg-resampler(1), -ffmpeg-codecs(1), ffmpeg-bitstream-filters(1), ffmpeg-formats(1), -ffmpeg-devices(1), ffmpeg-protocols(1), ffmpeg-filters(1) -@end ifnothtml - -@include authors.texi - -@ignore - -@setfilename ffserver -@settitle ffserver video server - -@end ignore - -@bye diff --git a/doc/issue_tracker.txt b/doc/issue_tracker.txt index e8e85304b378c..5d9805a4b9708 100644 --- a/doc/issue_tracker.txt +++ b/doc/issue_tracker.txt @@ -193,9 +193,6 @@ ffplay ffprobe issues in or related to ffprobe.c -ffserver - issues in or related to ffserver.c - postproc issues in libpostproc/* diff --git a/doc/libavcodec.texi b/doc/libavcodec.texi index 87b90db48c479..b22c47ae87c77 100644 --- a/doc/libavcodec.texi +++ b/doc/libavcodec.texi @@ -26,13 +26,13 @@ implementing robust and fast codecs as well as for experimentation. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffmpeg-codecs.html,ffmpeg-codecs}, @url{ffmpeg-bitstream-filters.html,bitstream-filters}, @url{libavutil.html,libavutil} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), +ffmpeg(1), ffplay(1), ffprobe(1), ffmpeg-codecs(1), ffmpeg-bitstream-filters(1), libavutil(3) @end ifnothtml diff --git a/doc/libavdevice.texi b/doc/libavdevice.texi index 9b10282cde8be..0abdaaff06f0d 100644 --- a/doc/libavdevice.texi +++ b/doc/libavdevice.texi @@ -23,13 +23,13 @@ VfW, DShow, and ALSA. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffmpeg-devices.html,ffmpeg-devices}, @url{libavutil.html,libavutil}, @url{libavcodec.html,libavcodec}, @url{libavformat.html,libavformat} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), +ffmpeg(1), ffplay(1), ffprobe(1), ffmpeg-devices(1), libavutil(3), libavcodec(3), libavformat(3) @end ifnothtml diff --git a/doc/libavfilter.texi b/doc/libavfilter.texi index 52e075369cf49..d9472eb0ad3b8 100644 --- a/doc/libavfilter.texi +++ b/doc/libavfilter.texi @@ -21,14 +21,14 @@ framework containing several filters, sources and sinks. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffmpeg-filters.html,ffmpeg-filters}, @url{libavutil.html,libavutil}, @url{libswscale.html,libswscale}, @url{libswresample.html,libswresample}, @url{libavcodec.html,libavcodec}, @url{libavformat.html,libavformat}, @url{libavdevice.html,libavdevice} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), +ffmpeg(1), ffplay(1), ffprobe(1), ffmpeg-filters(1), libavutil(3), libswscale(3), libswresample(3), libavcodec(3), libavformat(3), libavdevice(3) @end ifnothtml diff --git a/doc/libavformat.texi b/doc/libavformat.texi index d505d644f698f..7cf41fdfd4552 100644 --- a/doc/libavformat.texi +++ b/doc/libavformat.texi @@ -26,13 +26,13 @@ resource. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffmpeg-formats.html,ffmpeg-formats}, @url{ffmpeg-protocols.html,ffmpeg-protocols}, @url{libavutil.html,libavutil}, @url{libavcodec.html,libavcodec} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), +ffmpeg(1), ffplay(1), ffprobe(1), ffmpeg-formats(1), ffmpeg-protocols(1), libavutil(3), libavcodec(3) @end ifnothtml diff --git a/doc/libavutil.texi b/doc/libavutil.texi index 7a1c332b81743..ee50362f69487 100644 --- a/doc/libavutil.texi +++ b/doc/libavutil.texi @@ -42,12 +42,12 @@ It should avoid useless features that almost no one needs. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffmpeg-utils.html,ffmpeg-utils} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), +ffmpeg(1), ffplay(1), ffprobe(1), ffmpeg-utils(1) @end ifnothtml diff --git a/doc/libswresample.texi b/doc/libswresample.texi index bb57278314b22..3108cb1ba490a 100644 --- a/doc/libswresample.texi +++ b/doc/libswresample.texi @@ -48,13 +48,13 @@ enabled through dedicated options. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffmpeg-resampler.html,ffmpeg-resampler}, @url{libavutil.html,libavutil} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), +ffmpeg(1), ffplay(1), ffprobe(1), ffmpeg-resampler(1), libavutil(3) @end ifnothtml diff --git a/doc/libswscale.texi b/doc/libswscale.texi index 757fd24139677..e137c24a499ab 100644 --- a/doc/libswscale.texi +++ b/doc/libswscale.texi @@ -41,13 +41,13 @@ colorspaces differ. @chapter See Also @ifhtml -@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffserver.html,ffserver}, +@url{ffmpeg.html,ffmpeg}, @url{ffplay.html,ffplay}, @url{ffprobe.html,ffprobe}, @url{ffmpeg-scaler.html,ffmpeg-scaler}, @url{libavutil.html,libavutil} @end ifhtml @ifnothtml -ffmpeg(1), ffplay(1), ffprobe(1), ffserver(1), +ffmpeg(1), ffplay(1), ffprobe(1), ffmpeg-scaler(1), libavutil(3) @end ifnothtml diff --git a/doc/mailing-list-faq.texi b/doc/mailing-list-faq.texi index fe2171e42e875..9af89815d5254 100644 --- a/doc/mailing-list-faq.texi +++ b/doc/mailing-list-faq.texi @@ -27,8 +27,7 @@ for examples. @item @url{https://lists.ffmpeg.org/mailman/listinfo/ffmpeg-user/, ffmpeg-user}: For questions involving unscripted usage or compilation of the FFmpeg -command-line tools (@command{ffmpeg}, @command{ffprobe}, @command{ffplay}, -@command{ffserver}). +command-line tools (@command{ffmpeg}, @command{ffprobe}, @command{ffplay}). @item @url{https://lists.ffmpeg.org/mailman/listinfo/libav-user/, libav-user}: diff --git a/doc/protocols.texi b/doc/protocols.texi index 1ededa81c861b..98deb73005bc2 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -366,7 +366,7 @@ If set to 1 enables experimental HTTP server. This can be used to send data when used as an output option, or read data from a client with HTTP POST when used as an input option. If set to 2 enables experimental multi-client HTTP server. This is not yet implemented -in ffmpeg.c or ffserver.c and thus must not be used as a command line option. +in ffmpeg.c and thus must not be used as a command line option. @example # Server side (sending): ffmpeg -i somefile.ogg -c copy -listen 1 -f ogg http://@var{server}:@var{port} diff --git a/fftools/Makefile b/fftools/Makefile index 8fbb898ce5e39..c3a0ff340b0d4 100644 --- a/fftools/Makefile +++ b/fftools/Makefile @@ -1,12 +1,11 @@ AVPROGS-$(CONFIG_FFMPEG) += ffmpeg AVPROGS-$(CONFIG_FFPLAY) += ffplay AVPROGS-$(CONFIG_FFPROBE) += ffprobe -AVPROGS-$(CONFIG_FFSERVER) += ffserver AVPROGS := $(AVPROGS-yes:%=%$(PROGSSUF)$(EXESUF)) PROGS += $(AVPROGS) -AVBASENAMES = ffmpeg ffplay ffprobe ffserver +AVBASENAMES = ffmpeg ffplay ffprobe ALLAVPROGS = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF)) ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF)) @@ -17,7 +16,6 @@ ifndef CONFIG_VIDEOTOOLBOX OBJS-ffmpeg-$(CONFIG_VDA) += fftools/ffmpeg_videotoolbox.o endif OBJS-ffmpeg-$(CONFIG_VIDEOTOOLBOX) += fftools/ffmpeg_videotoolbox.o -OBJS-ffserver += fftools/ffserver_config.o define DOFFTOOL OBJS-$(1) += fftools/cmdutils.o fftools/$(1).o $(OBJS-$(1)-yes) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 754c297b93f62..4fe78fa757ffd 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -117,7 +117,6 @@ static int file_overwrite = 0; static int no_file_overwrite = 0; static int do_psnr = 0; static int input_sync; -static int override_ffserver = 0; static int input_stream_potentially_available = 0; static int ignore_unknown_streams = 0; static int copy_unknown_streams = 0; @@ -1997,58 +1996,6 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata) return 0; } -static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename) -{ - int i, err; - AVFormatContext *ic = avformat_alloc_context(); - if (!ic) - return AVERROR(ENOMEM); - - ic->interrupt_callback = int_cb; - err = avformat_open_input(&ic, filename, NULL, NULL); - if (err < 0) - return err; - /* copy stream format */ - for(i=0;inb_streams;i++) { - AVStream *st; - OutputStream *ost; - AVCodec *codec; - const char *enc_config; - - codec = avcodec_find_encoder(ic->streams[i]->codecpar->codec_id); - if (!codec) { - av_log(s, AV_LOG_ERROR, "no encoder found for codec id %i\n", ic->streams[i]->codecpar->codec_id); - return AVERROR(EINVAL); - } - if (codec->type == AVMEDIA_TYPE_AUDIO) - opt_audio_codec(o, "c:a", codec->name); - else if (codec->type == AVMEDIA_TYPE_VIDEO) - opt_video_codec(o, "c:v", codec->name); - ost = new_output_stream(o, s, codec->type, -1); - st = ost->st; - - avcodec_get_context_defaults3(st->codec, codec); - enc_config = av_stream_get_recommended_encoder_configuration(ic->streams[i]); - if (enc_config) { - AVDictionary *opts = NULL; - av_dict_parse_string(&opts, enc_config, "=", ",", 0); - av_opt_set_dict2(st->codec, &opts, AV_OPT_SEARCH_CHILDREN); - av_dict_free(&opts); - } - - if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy) - choose_sample_fmt(st, codec); - else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy) - choose_pixel_fmt(st, st->codec, codec, st->codecpar->format); - avcodec_copy_context(ost->enc_ctx, st->codec); - if (enc_config) - av_dict_parse_string(&ost->encoder_opts, enc_config, "=", ",", 0); - } - - avformat_close_input(&ic); - return err; -} - static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, AVFormatContext *oc) { @@ -2187,47 +2134,7 @@ static int open_output_file(OptionsContext *o, const char *filename) } } - /* ffserver seeking with date=... needs a date reference */ - if (!strcmp(file_oformat->name, "ffm") && - !(format_flags & AVFMT_FLAG_BITEXACT) && - av_strstart(filename, "http:", NULL)) { - int err = parse_option(o, "metadata", "creation_time=now", options); - if (err < 0) { - print_error(filename, err); - exit_program(1); - } - } - - if (!strcmp(file_oformat->name, "ffm") && !override_ffserver && - av_strstart(filename, "http:", NULL)) { - int j; - /* special case for files sent to ffserver: we get the stream - parameters from ffserver */ - int err = read_ffserver_streams(o, oc, filename); - if (err < 0) { - print_error(filename, err); - exit_program(1); - } - for(j = nb_output_streams - oc->nb_streams; j < nb_output_streams; j++) { - ost = output_streams[j]; - for (i = 0; i < nb_input_streams; i++) { - ist = input_streams[i]; - if(ist->st->codecpar->codec_type == ost->st->codecpar->codec_type){ - ost->sync_ist= ist; - ost->source_index= i; - if(ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ost->avfilter = av_strdup("anull"); - if(ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) ost->avfilter = av_strdup("null"); - ist->discard = 0; - ist->st->discard = ist->user_set_discard; - break; - } - } - if(!ost->sync_ist){ - av_log(NULL, AV_LOG_FATAL, "Missing %s stream which is required by this ffm\n", av_get_media_type_string(ost->st->codecpar->codec_type)); - exit_program(1); - } - } - } else if (!o->nb_stream_maps) { + if (!o->nb_stream_maps) { char *subtitle_codec_name = NULL; /* pick the "best" stream of each type */ @@ -3719,8 +3626,6 @@ const OptionDef options[] = { "set the maximum demux-decode delay", "seconds" }, { "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(mux_preload) }, "set the initial demux-decode delay", "seconds" }, - { "override_ffserver", OPT_BOOL | OPT_EXPERT | OPT_OUTPUT, { &override_ffserver }, - "override the options from ffserver", "" }, { "sdp_file", HAS_ARG | OPT_EXPERT | OPT_OUTPUT, { .func_arg = opt_sdp_file }, "specify a file in which to print sdp information", "file" }, diff --git a/fftools/ffserver.c b/fftools/ffserver.c deleted file mode 100644 index 7f8b2387bd0c8..0000000000000 --- a/fftools/ffserver.c +++ /dev/null @@ -1,4022 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002 Fabrice Bellard - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * multiple format streaming server based on the FFmpeg libraries - */ - -#include "config.h" -#if !HAVE_CLOSESOCKET -#define closesocket close -#endif -#include -#include -#include -#include "libavformat/avformat.h" -/* FIXME: those are internal headers, ffserver _really_ shouldn't use them */ -#include "libavformat/rtpproto.h" -#include "libavformat/rtsp.h" -#include "libavformat/avio_internal.h" -#include "libavformat/internal.h" - -#include "libavutil/avassert.h" -#include "libavutil/avstring.h" -#include "libavutil/lfg.h" -#include "libavutil/dict.h" -#include "libavutil/intreadwrite.h" -#include "libavutil/mathematics.h" -#include "libavutil/random_seed.h" -#include "libavutil/rational.h" -#include "libavutil/parseutils.h" -#include "libavutil/opt.h" -#include "libavutil/time.h" - -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_POLL_H -#include -#endif -#include -#include -#include -#include - -#include "cmdutils.h" -#include "ffserver_config.h" - -#define PATH_LENGTH 1024 - -const char program_name[] = "ffserver"; -const int program_birth_year = 2000; - -static const OptionDef options[]; - -enum HTTPState { - HTTPSTATE_WAIT_REQUEST, - HTTPSTATE_SEND_HEADER, - HTTPSTATE_SEND_DATA_HEADER, - HTTPSTATE_SEND_DATA, /* sending TCP or UDP data */ - HTTPSTATE_SEND_DATA_TRAILER, - HTTPSTATE_RECEIVE_DATA, - HTTPSTATE_WAIT_FEED, /* wait for data from the feed */ - HTTPSTATE_READY, - - RTSPSTATE_WAIT_REQUEST, - RTSPSTATE_SEND_REPLY, - RTSPSTATE_SEND_PACKET, -}; - -static const char * const http_state[] = { - "HTTP_WAIT_REQUEST", - "HTTP_SEND_HEADER", - - "SEND_DATA_HEADER", - "SEND_DATA", - "SEND_DATA_TRAILER", - "RECEIVE_DATA", - "WAIT_FEED", - "READY", - - "RTSP_WAIT_REQUEST", - "RTSP_SEND_REPLY", - "RTSP_SEND_PACKET", -}; - -#define IOBUFFER_INIT_SIZE 8192 - -/* timeouts are in ms */ -#define HTTP_REQUEST_TIMEOUT (15 * 1000) -#define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000) - -#define SYNC_TIMEOUT (10 * 1000) - -typedef struct RTSPActionServerSetup { - uint32_t ipaddr; - char transport_option[512]; -} RTSPActionServerSetup; - -typedef struct { - int64_t count1, count2; - int64_t time1, time2; -} DataRateData; - -/* context associated with one connection */ -typedef struct HTTPContext { - enum HTTPState state; - int fd; /* socket file descriptor */ - struct sockaddr_in from_addr; /* origin */ - struct pollfd *poll_entry; /* used when polling */ - int64_t timeout; - uint8_t *buffer_ptr, *buffer_end; - int http_error; - int post; - int chunked_encoding; - int chunk_size; /* 0 if it needs to be read */ - struct HTTPContext *next; - int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */ - int64_t data_count; - /* feed input */ - int feed_fd; - /* input format handling */ - AVFormatContext *fmt_in; - int64_t start_time; /* In milliseconds - this wraps fairly often */ - int64_t first_pts; /* initial pts value */ - int64_t cur_pts; /* current pts value from the stream in us */ - int64_t cur_frame_duration; /* duration of the current frame in us */ - int cur_frame_bytes; /* output frame size, needed to compute - the time at which we send each - packet */ - int pts_stream_index; /* stream we choose as clock reference */ - int64_t cur_clock; /* current clock reference value in us */ - /* output format handling */ - struct FFServerStream *stream; - /* -1 is invalid stream */ - int feed_streams[FFSERVER_MAX_STREAMS]; /* index of streams in the feed */ - int switch_feed_streams[FFSERVER_MAX_STREAMS]; /* index of streams in the feed */ - int switch_pending; - AVFormatContext *pfmt_ctx; /* instance of FFServerStream for one user */ - int last_packet_sent; /* true if last data packet was sent */ - int suppress_log; - DataRateData datarate; - int wmp_client_id; - char protocol[16]; - char method[16]; - char url[128]; - char clean_url[128*7]; - int buffer_size; - uint8_t *buffer; - int is_packetized; /* if true, the stream is packetized */ - int packet_stream_index; /* current stream for output in state machine */ - - /* RTSP state specific */ - uint8_t *pb_buffer; /* XXX: use that in all the code */ - AVIOContext *pb; - int seq; /* RTSP sequence number */ - - /* RTP state specific */ - enum RTSPLowerTransport rtp_protocol; - char session_id[32]; /* session id */ - AVFormatContext *rtp_ctx[FFSERVER_MAX_STREAMS]; - - /* RTP/UDP specific */ - URLContext *rtp_handles[FFSERVER_MAX_STREAMS]; - - /* RTP/TCP specific */ - struct HTTPContext *rtsp_c; - uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end; -} HTTPContext; - -static HTTPContext *first_http_ctx; - -static FFServerConfig config = { - .nb_max_http_connections = 2000, - .nb_max_connections = 5, - .max_bandwidth = 1000, - .use_defaults = 1, -}; - -static void new_connection(int server_fd, int is_rtsp); -static void close_connection(HTTPContext *c); - -/* HTTP handling */ -static int handle_connection(HTTPContext *c); -static inline void print_stream_params(AVIOContext *pb, FFServerStream *stream); -static void compute_status(HTTPContext *c); -static int open_input_stream(HTTPContext *c, const char *info); -static int http_parse_request(HTTPContext *c); -static int http_send_data(HTTPContext *c); -static int http_start_receive_data(HTTPContext *c); -static int http_receive_data(HTTPContext *c); - -/* RTSP handling */ -static int rtsp_parse_request(HTTPContext *c); -static void rtsp_cmd_describe(HTTPContext *c, const char *url); -static void rtsp_cmd_options(HTTPContext *c, const char *url); -static void rtsp_cmd_setup(HTTPContext *c, const char *url, - RTSPMessageHeader *h); -static void rtsp_cmd_play(HTTPContext *c, const char *url, - RTSPMessageHeader *h); -static void rtsp_cmd_interrupt(HTTPContext *c, const char *url, - RTSPMessageHeader *h, int pause_only); - -/* SDP handling */ -static int prepare_sdp_description(FFServerStream *stream, uint8_t **pbuffer, - struct in_addr my_ip); - -/* RTP handling */ -static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr, - FFServerStream *stream, - const char *session_id, - enum RTSPLowerTransport rtp_protocol); -static int rtp_new_av_stream(HTTPContext *c, - int stream_index, struct sockaddr_in *dest_addr, - HTTPContext *rtsp_c); -/* utils */ -static size_t htmlencode (const char *src, char **dest); -static inline void cp_html_entity (char *buffer, const char *entity); -static inline int check_codec_match(LayeredAVStream *ccf, AVStream *ccs, int stream); - -static const char *my_program_name; - -static int no_launch; -static int need_to_start_children; - -/* maximum number of simultaneous HTTP connections */ -static unsigned int nb_connections; - -static uint64_t current_bandwidth; - -/* Making this global saves on passing it around everywhere */ -static int64_t cur_time; - -static AVLFG random_state; - -static FILE *logfile = NULL; - -static void unlayer_stream(AVStream *st, LayeredAVStream *lst) -{ - avcodec_free_context(&st->codec); - avcodec_parameters_free(&st->codecpar); -#define COPY(a) st->a = lst->a; - COPY(index) - COPY(id) - COPY(codec) - COPY(codecpar) - COPY(time_base) - COPY(pts_wrap_bits) - COPY(sample_aspect_ratio) - COPY(recommended_encoder_configuration) -} - -static inline void cp_html_entity (char *buffer, const char *entity) { - if (!buffer || !entity) - return; - while (*entity) - *buffer++ = *entity++; -} - -/** - * Substitutes known conflicting chars on a text string with - * their corresponding HTML entities. - * - * Returns the number of bytes in the 'encoded' representation - * not including the terminating NUL. - */ -static size_t htmlencode (const char *src, char **dest) { - const char *amp = "&"; - const char *lt = "<"; - const char *gt = ">"; - const char *start; - char *tmp; - size_t final_size = 0; - - if (!src) - return 0; - - start = src; - - /* Compute needed dest size */ - while (*src != '\0') { - switch(*src) { - case 38: /* & */ - final_size += 5; - break; - case 60: /* < */ - case 62: /* > */ - final_size += 4; - break; - default: - final_size++; - } - src++; - } - - src = start; - *dest = av_mallocz(final_size + 1); - if (!*dest) - return 0; - - /* Build dest */ - tmp = *dest; - while (*src != '\0') { - switch(*src) { - case 38: /* & */ - cp_html_entity (tmp, amp); - tmp += 5; - break; - case 60: /* < */ - cp_html_entity (tmp, lt); - tmp += 4; - break; - case 62: /* > */ - cp_html_entity (tmp, gt); - tmp += 4; - break; - default: - *tmp = *src; - tmp += 1; - } - src++; - } - *tmp = '\0'; - - return final_size; -} - -static int64_t ffm_read_write_index(int fd) -{ - uint8_t buf[8]; - - if (lseek(fd, 8, SEEK_SET) < 0) - return AVERROR(EIO); - if (read(fd, buf, 8) != 8) - return AVERROR(EIO); - return AV_RB64(buf); -} - -static int ffm_write_write_index(int fd, int64_t pos) -{ - uint8_t buf[8]; - int i; - - for(i=0;i<8;i++) - buf[i] = (pos >> (56 - i * 8)) & 0xff; - if (lseek(fd, 8, SEEK_SET) < 0) - goto bail_eio; - if (write(fd, buf, 8) != 8) - goto bail_eio; - - return 8; - -bail_eio: - return AVERROR(EIO); -} - -static void ffm_set_write_index(AVFormatContext *s, int64_t pos, - int64_t file_size) -{ - av_opt_set_int(s, "server_attached", 1, AV_OPT_SEARCH_CHILDREN); - av_opt_set_int(s, "ffm_write_index", pos, AV_OPT_SEARCH_CHILDREN); - av_opt_set_int(s, "ffm_file_size", file_size, AV_OPT_SEARCH_CHILDREN); -} - -static char *ctime1(char *buf2, size_t buf_size) -{ - time_t ti; - char *p; - - ti = time(NULL); - p = ctime(&ti); - if (!p || !*p) { - *buf2 = '\0'; - return buf2; - } - av_strlcpy(buf2, p, buf_size); - p = buf2 + strlen(buf2) - 1; - if (*p == '\n') - *p = '\0'; - return buf2; -} - -static void http_vlog(const char *fmt, va_list vargs) -{ - static int print_prefix = 1; - char buf[32]; - - if (!logfile) - return; - - if (print_prefix) { - ctime1(buf, sizeof(buf)); - fprintf(logfile, "%s ", buf); - } - print_prefix = strstr(fmt, "\n") != NULL; - vfprintf(logfile, fmt, vargs); - fflush(logfile); -} - -#ifdef __GNUC__ -__attribute__ ((format (printf, 1, 2))) -#endif -static void http_log(const char *fmt, ...) -{ - va_list vargs; - va_start(vargs, fmt); - http_vlog(fmt, vargs); - va_end(vargs); -} - -static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs) -{ - static int print_prefix = 1; - AVClass *avc = ptr ? *(AVClass**)ptr : NULL; - if (level > av_log_get_level()) - return; - if (print_prefix && avc) - http_log("[%s @ %p]", avc->item_name(ptr), ptr); - print_prefix = strstr(fmt, "\n") != NULL; - http_vlog(fmt, vargs); -} - -static void log_connection(HTTPContext *c) -{ - if (c->suppress_log) - return; - - http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n", - inet_ntoa(c->from_addr.sin_addr), c->method, c->url, - c->protocol, (c->http_error ? c->http_error : 200), c->data_count); -} - -static void update_datarate(DataRateData *drd, int64_t count) -{ - if (!drd->time1 && !drd->count1) { - drd->time1 = drd->time2 = cur_time; - drd->count1 = drd->count2 = count; - } else if (cur_time - drd->time2 > 5000) { - drd->time1 = drd->time2; - drd->count1 = drd->count2; - drd->time2 = cur_time; - drd->count2 = count; - } -} - -/* In bytes per second */ -static int compute_datarate(DataRateData *drd, int64_t count) -{ - if (cur_time == drd->time1) - return 0; - - return ((count - drd->count1) * 1000) / (cur_time - drd->time1); -} - - -static void start_children(FFServerStream *feed) -{ - char *pathname; - char *dirname, *prog; - int i; - size_t cmd_length; - - if (no_launch) - return; - - cmd_length = strlen(my_program_name); - - /** - * FIXME: WIP Safeguard. Remove after clearing all harcoded - * '1024' path lengths - */ - if (cmd_length > PATH_LENGTH - 1) { - http_log("Could not start children. Command line: '%s' exceeds " - "path length limit (%d)\n", my_program_name, PATH_LENGTH); - return; - } - - /* use "ffmpeg" in the path of current program. Ignore user provided path */ - prog = av_strdup(my_program_name); - if (prog) { - dirname = av_dirname(prog); - pathname = *dirname ? av_asprintf("%s/%s", dirname, "ffmpeg") - : av_asprintf("ffmpeg"); - av_free(prog); - } - if (!prog || !pathname) { - http_log("Could not allocate memory for children cmd line\n"); - return; - } - - for (; feed; feed = feed->next) { - - if (!feed->child_argv || feed->pid) - continue; - - feed->pid_start = time(0); - - feed->pid = fork(); - if (feed->pid < 0) { - http_log("Unable to create children: %s\n", strerror(errno)); - av_free (pathname); - exit(EXIT_FAILURE); - } - - if (feed->pid) - continue; - - /* In child */ - - http_log("Launch command line: "); - http_log("%s ", pathname); - - for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++) - http_log("%s ", feed->child_argv[i]); - http_log("\n"); - - for (i = 3; i < 256; i++) - close(i); - - if (!config.debug) { - if (!freopen("/dev/null", "r", stdin)) - http_log("failed to redirect STDIN to /dev/null\n;"); - if (!freopen("/dev/null", "w", stdout)) - http_log("failed to redirect STDOUT to /dev/null\n;"); - if (!freopen("/dev/null", "w", stderr)) - http_log("failed to redirect STDERR to /dev/null\n;"); - } - - signal(SIGPIPE, SIG_DFL); - execvp(pathname, feed->child_argv); - av_free (pathname); - _exit(1); - } - av_free (pathname); -} - -/* open a listening socket */ -static int socket_open_listen(struct sockaddr_in *my_addr) -{ - int server_fd, tmp; - - server_fd = socket(AF_INET,SOCK_STREAM,0); - if (server_fd < 0) { - perror ("socket"); - return -1; - } - - tmp = 1; - if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp))) - av_log(NULL, AV_LOG_WARNING, "setsockopt SO_REUSEADDR failed\n"); - - my_addr->sin_family = AF_INET; - if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) { - char bindmsg[32]; - snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", - ntohs(my_addr->sin_port)); - perror (bindmsg); - goto fail; - } - - if (listen (server_fd, 5) < 0) { - perror ("listen"); - goto fail; - } - - if (ff_socket_nonblock(server_fd, 1) < 0) - av_log(NULL, AV_LOG_WARNING, "ff_socket_nonblock failed\n"); - - return server_fd; - -fail: - closesocket(server_fd); - return -1; -} - -/* start all multicast streams */ -static void start_multicast(void) -{ - FFServerStream *stream; - char session_id[32]; - HTTPContext *rtp_c; - struct sockaddr_in dest_addr = {0}; - int default_port, stream_index; - unsigned int random0, random1; - - default_port = 6000; - for(stream = config.first_stream; stream; stream = stream->next) { - - if (!stream->is_multicast) - continue; - - random0 = av_lfg_get(&random_state); - random1 = av_lfg_get(&random_state); - - /* open the RTP connection */ - snprintf(session_id, sizeof(session_id), "%08x%08x", random0, random1); - - /* choose a port if none given */ - if (stream->multicast_port == 0) { - stream->multicast_port = default_port; - default_port += 100; - } - - dest_addr.sin_family = AF_INET; - dest_addr.sin_addr = stream->multicast_ip; - dest_addr.sin_port = htons(stream->multicast_port); - - rtp_c = rtp_new_connection(&dest_addr, stream, session_id, - RTSP_LOWER_TRANSPORT_UDP_MULTICAST); - if (!rtp_c) - continue; - - if (open_input_stream(rtp_c, "") < 0) { - http_log("Could not open input stream for stream '%s'\n", - stream->filename); - continue; - } - - /* open each RTP stream */ - for(stream_index = 0; stream_index < stream->nb_streams; - stream_index++) { - dest_addr.sin_port = htons(stream->multicast_port + - 2 * stream_index); - if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) >= 0) - continue; - - http_log("Could not open output stream '%s/streamid=%d'\n", - stream->filename, stream_index); - exit(1); - } - - rtp_c->state = HTTPSTATE_SEND_DATA; - } -} - -/* main loop of the HTTP server */ -static int http_server(void) -{ - int server_fd = 0, rtsp_server_fd = 0; - int ret, delay; - struct pollfd *poll_table, *poll_entry; - HTTPContext *c, *c_next; - - poll_table = av_mallocz_array(config.nb_max_http_connections + 2, - sizeof(*poll_table)); - if(!poll_table) { - http_log("Impossible to allocate a poll table handling %d " - "connections.\n", config.nb_max_http_connections); - return -1; - } - - if (config.http_addr.sin_port) { - server_fd = socket_open_listen(&config.http_addr); - if (server_fd < 0) - goto quit; - } - - if (config.rtsp_addr.sin_port) { - rtsp_server_fd = socket_open_listen(&config.rtsp_addr); - if (rtsp_server_fd < 0) { - closesocket(server_fd); - goto quit; - } - } - - if (!rtsp_server_fd && !server_fd) { - http_log("HTTP and RTSP disabled.\n"); - goto quit; - } - - http_log("FFserver started.\n"); - - start_children(config.first_feed); - - start_multicast(); - - for(;;) { - poll_entry = poll_table; - if (server_fd) { - poll_entry->fd = server_fd; - poll_entry->events = POLLIN; - poll_entry++; - } - if (rtsp_server_fd) { - poll_entry->fd = rtsp_server_fd; - poll_entry->events = POLLIN; - poll_entry++; - } - - /* wait for events on each HTTP handle */ - c = first_http_ctx; - delay = 1000; - while (c) { - int fd; - fd = c->fd; - switch(c->state) { - case HTTPSTATE_SEND_HEADER: - case RTSPSTATE_SEND_REPLY: - case RTSPSTATE_SEND_PACKET: - c->poll_entry = poll_entry; - poll_entry->fd = fd; - poll_entry->events = POLLOUT; - poll_entry++; - break; - case HTTPSTATE_SEND_DATA_HEADER: - case HTTPSTATE_SEND_DATA: - case HTTPSTATE_SEND_DATA_TRAILER: - if (!c->is_packetized) { - /* for TCP, we output as much as we can - * (may need to put a limit) */ - c->poll_entry = poll_entry; - poll_entry->fd = fd; - poll_entry->events = POLLOUT; - poll_entry++; - } else { - /* when ffserver is doing the timing, we work by - * looking at which packet needs to be sent every - * 10 ms (one tick wait XXX: 10 ms assumed) */ - if (delay > 10) - delay = 10; - } - break; - case HTTPSTATE_WAIT_REQUEST: - case HTTPSTATE_RECEIVE_DATA: - case HTTPSTATE_WAIT_FEED: - case RTSPSTATE_WAIT_REQUEST: - /* need to catch errors */ - c->poll_entry = poll_entry; - poll_entry->fd = fd; - poll_entry->events = POLLIN;/* Maybe this will work */ - poll_entry++; - break; - default: - c->poll_entry = NULL; - break; - } - c = c->next; - } - - /* wait for an event on one connection. We poll at least every - * second to handle timeouts */ - do { - ret = poll(poll_table, poll_entry - poll_table, delay); - if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) && - ff_neterrno() != AVERROR(EINTR)) { - goto quit; - } - } while (ret < 0); - - cur_time = av_gettime() / 1000; - - if (need_to_start_children) { - need_to_start_children = 0; - start_children(config.first_feed); - } - - /* now handle the events */ - for(c = first_http_ctx; c; c = c_next) { - c_next = c->next; - if (handle_connection(c) < 0) { - log_connection(c); - /* close and free the connection */ - close_connection(c); - } - } - - poll_entry = poll_table; - if (server_fd) { - /* new HTTP connection request ? */ - if (poll_entry->revents & POLLIN) - new_connection(server_fd, 0); - poll_entry++; - } - if (rtsp_server_fd) { - /* new RTSP connection request ? */ - if (poll_entry->revents & POLLIN) - new_connection(rtsp_server_fd, 1); - } - } - -quit: - av_free(poll_table); - return -1; -} - -/* start waiting for a new HTTP/RTSP request */ -static void start_wait_request(HTTPContext *c, int is_rtsp) -{ - c->buffer_ptr = c->buffer; - c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */ - - c->state = is_rtsp ? RTSPSTATE_WAIT_REQUEST : HTTPSTATE_WAIT_REQUEST; - c->timeout = cur_time + - (is_rtsp ? RTSP_REQUEST_TIMEOUT : HTTP_REQUEST_TIMEOUT); -} - -static void http_send_too_busy_reply(int fd) -{ - char buffer[400]; - int len = snprintf(buffer, sizeof(buffer), - "HTTP/1.0 503 Server too busy\r\n" - "Content-type: text/html\r\n" - "\r\n" - "\n" - "Too busy\r\n" - "

The server is too busy to serve your request at " - "this time.

\r\n" - "

The number of current connections is %u, and this " - "exceeds the limit of %u.

\r\n" - "\r\n", - nb_connections, config.nb_max_connections); - av_assert0(len < sizeof(buffer)); - if (send(fd, buffer, len, 0) < len) - av_log(NULL, AV_LOG_WARNING, - "Could not send too-busy reply, send() failed\n"); -} - - -static void new_connection(int server_fd, int is_rtsp) -{ - struct sockaddr_in from_addr; - socklen_t len; - int fd; - HTTPContext *c = NULL; - - len = sizeof(from_addr); - fd = accept(server_fd, (struct sockaddr *)&from_addr, - &len); - if (fd < 0) { - http_log("error during accept %s\n", strerror(errno)); - return; - } - if (ff_socket_nonblock(fd, 1) < 0) - av_log(NULL, AV_LOG_WARNING, "ff_socket_nonblock failed\n"); - - if (nb_connections >= config.nb_max_connections) { - http_send_too_busy_reply(fd); - goto fail; - } - - /* add a new connection */ - c = av_mallocz(sizeof(HTTPContext)); - if (!c) - goto fail; - - c->fd = fd; - c->poll_entry = NULL; - c->from_addr = from_addr; - c->buffer_size = IOBUFFER_INIT_SIZE; - c->buffer = av_malloc(c->buffer_size); - if (!c->buffer) - goto fail; - - c->next = first_http_ctx; - first_http_ctx = c; - nb_connections++; - - start_wait_request(c, is_rtsp); - - return; - - fail: - if (c) { - av_freep(&c->buffer); - av_free(c); - } - closesocket(fd); -} - -static void close_connection(HTTPContext *c) -{ - HTTPContext **cp, *c1; - int i, nb_streams; - AVFormatContext *ctx; - AVStream *st; - - /* remove connection from list */ - cp = &first_http_ctx; - while (*cp) { - c1 = *cp; - if (c1 == c) - *cp = c->next; - else - cp = &c1->next; - } - - /* remove references, if any (XXX: do it faster) */ - for(c1 = first_http_ctx; c1; c1 = c1->next) { - if (c1->rtsp_c == c) - c1->rtsp_c = NULL; - } - - /* remove connection associated resources */ - if (c->fd >= 0) - closesocket(c->fd); - if (c->fmt_in) { - /* close each frame parser */ - for(i=0;ifmt_in->nb_streams;i++) { - st = c->fmt_in->streams[i]; - if (st->codec->codec) - avcodec_close(st->codec); - } - avformat_close_input(&c->fmt_in); - } - - /* free RTP output streams if any */ - nb_streams = 0; - if (c->stream) - nb_streams = c->stream->nb_streams; - - for(i=0;irtp_ctx[i]; - if (ctx) { - av_write_trailer(ctx); - av_dict_free(&ctx->metadata); - av_freep(&ctx->streams[0]); - av_freep(&ctx); - } - ffurl_close(c->rtp_handles[i]); - } - - ctx = c->pfmt_ctx; - - if (ctx) { - if (!c->last_packet_sent && c->state == HTTPSTATE_SEND_DATA_TRAILER) { - /* prepare header */ - if (ctx->oformat && avio_open_dyn_buf(&ctx->pb) >= 0) { - av_write_trailer(ctx); - av_freep(&c->pb_buffer); - avio_close_dyn_buf(ctx->pb, &c->pb_buffer); - } - } - for(i=0; inb_streams; i++) - av_freep(&ctx->streams[i]); - av_freep(&ctx->streams); - av_freep(&ctx->priv_data); - } - - if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE) - current_bandwidth -= c->stream->bandwidth; - - /* signal that there is no feed if we are the feeder socket */ - if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) { - c->stream->feed_opened = 0; - close(c->feed_fd); - } - - av_freep(&c->pb_buffer); - av_freep(&c->packet_buffer); - av_freep(&c->buffer); - av_free(c); - nb_connections--; -} - -static int handle_connection(HTTPContext *c) -{ - int len, ret; - uint8_t *ptr; - - switch(c->state) { - case HTTPSTATE_WAIT_REQUEST: - case RTSPSTATE_WAIT_REQUEST: - /* timeout ? */ - if ((c->timeout - cur_time) < 0) - return -1; - if (c->poll_entry->revents & (POLLERR | POLLHUP)) - return -1; - - /* no need to read if no events */ - if (!(c->poll_entry->revents & POLLIN)) - return 0; - /* read the data */ - read_loop: - if (!(len = recv(c->fd, c->buffer_ptr, 1, 0))) - return -1; - - if (len < 0) { - if (ff_neterrno() != AVERROR(EAGAIN) && - ff_neterrno() != AVERROR(EINTR)) - return -1; - break; - } - /* search for end of request. */ - c->buffer_ptr += len; - ptr = c->buffer_ptr; - if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) || - (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) { - /* request found : parse it and reply */ - if (c->state == HTTPSTATE_WAIT_REQUEST) - ret = http_parse_request(c); - else - ret = rtsp_parse_request(c); - - if (ret < 0) - return -1; - } else if (ptr >= c->buffer_end) { - /* request too long: cannot do anything */ - return -1; - } else goto read_loop; - - break; - - case HTTPSTATE_SEND_HEADER: - if (c->poll_entry->revents & (POLLERR | POLLHUP)) - return -1; - - /* no need to write if no events */ - if (!(c->poll_entry->revents & POLLOUT)) - return 0; - len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0); - if (len < 0) { - if (ff_neterrno() != AVERROR(EAGAIN) && - ff_neterrno() != AVERROR(EINTR)) { - goto close_connection; - } - break; - } - c->buffer_ptr += len; - if (c->stream) - c->stream->bytes_served += len; - c->data_count += len; - if (c->buffer_ptr >= c->buffer_end) { - av_freep(&c->pb_buffer); - /* if error, exit */ - if (c->http_error) - return -1; - /* all the buffer was sent : synchronize to the incoming - * stream */ - c->state = HTTPSTATE_SEND_DATA_HEADER; - c->buffer_ptr = c->buffer_end = c->buffer; - } - break; - - case HTTPSTATE_SEND_DATA: - case HTTPSTATE_SEND_DATA_HEADER: - case HTTPSTATE_SEND_DATA_TRAILER: - /* for packetized output, we consider we can always write (the - * input streams set the speed). It may be better to verify - * that we do not rely too much on the kernel queues */ - if (!c->is_packetized) { - if (c->poll_entry->revents & (POLLERR | POLLHUP)) - return -1; - - /* no need to read if no events */ - if (!(c->poll_entry->revents & POLLOUT)) - return 0; - } - if (http_send_data(c) < 0) - return -1; - /* close connection if trailer sent */ - if (c->state == HTTPSTATE_SEND_DATA_TRAILER) - return -1; - /* Check if it is a single jpeg frame 123 */ - if (c->stream->single_frame && c->data_count > c->cur_frame_bytes && c->cur_frame_bytes > 0) { - close_connection(c); - } - break; - case HTTPSTATE_RECEIVE_DATA: - /* no need to read if no events */ - if (c->poll_entry->revents & (POLLERR | POLLHUP)) - return -1; - if (!(c->poll_entry->revents & POLLIN)) - return 0; - if (http_receive_data(c) < 0) - return -1; - break; - case HTTPSTATE_WAIT_FEED: - /* no need to read if no events */ - if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP)) - return -1; - - /* nothing to do, we'll be waken up by incoming feed packets */ - break; - - case RTSPSTATE_SEND_REPLY: - if (c->poll_entry->revents & (POLLERR | POLLHUP)) - goto close_connection; - /* no need to write if no events */ - if (!(c->poll_entry->revents & POLLOUT)) - return 0; - len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0); - if (len < 0) { - if (ff_neterrno() != AVERROR(EAGAIN) && - ff_neterrno() != AVERROR(EINTR)) { - goto close_connection; - } - break; - } - c->buffer_ptr += len; - c->data_count += len; - if (c->buffer_ptr >= c->buffer_end) { - /* all the buffer was sent : wait for a new request */ - av_freep(&c->pb_buffer); - start_wait_request(c, 1); - } - break; - case RTSPSTATE_SEND_PACKET: - if (c->poll_entry->revents & (POLLERR | POLLHUP)) { - av_freep(&c->packet_buffer); - return -1; - } - /* no need to write if no events */ - if (!(c->poll_entry->revents & POLLOUT)) - return 0; - len = send(c->fd, c->packet_buffer_ptr, - c->packet_buffer_end - c->packet_buffer_ptr, 0); - if (len < 0) { - if (ff_neterrno() != AVERROR(EAGAIN) && - ff_neterrno() != AVERROR(EINTR)) { - /* error : close connection */ - av_freep(&c->packet_buffer); - return -1; - } - break; - } - c->packet_buffer_ptr += len; - if (c->packet_buffer_ptr >= c->packet_buffer_end) { - /* all the buffer was sent : wait for a new request */ - av_freep(&c->packet_buffer); - c->state = RTSPSTATE_WAIT_REQUEST; - } - break; - case HTTPSTATE_READY: - /* nothing to do */ - break; - default: - return -1; - } - return 0; - -close_connection: - av_freep(&c->pb_buffer); - return -1; -} - -static int extract_rates(char *rates, int ratelen, const char *request) -{ - const char *p; - - for (p = request; *p && *p != '\r' && *p != '\n'; ) { - if (av_strncasecmp(p, "Pragma:", 7) == 0) { - const char *q = p + 7; - - while (*q && *q != '\n' && av_isspace(*q)) - q++; - - if (av_strncasecmp(q, "stream-switch-entry=", 20) == 0) { - int stream_no; - int rate_no; - - q += 20; - - memset(rates, 0xff, ratelen); - - while (1) { - while (*q && *q != '\n' && *q != ':') - q++; - - if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2) - break; - - stream_no--; - if (stream_no < ratelen && stream_no >= 0) - rates[stream_no] = rate_no; - - while (*q && *q != '\n' && !av_isspace(*q)) - q++; - } - - return 1; - } - } - p = strchr(p, '\n'); - if (!p) - break; - - p++; - } - - return 0; -} - -static int find_stream_in_feed(FFServerStream *feed, AVCodecParameters *codec, - int bit_rate) -{ - int i; - int best_bitrate = 100000000; - int best = -1; - - for (i = 0; i < feed->nb_streams; i++) { - AVCodecParameters *feed_codec = feed->streams[i]->codecpar; - - if (feed_codec->codec_id != codec->codec_id || - feed_codec->sample_rate != codec->sample_rate || - feed_codec->width != codec->width || - feed_codec->height != codec->height) - continue; - - /* Potential stream */ - - /* We want the fastest stream less than bit_rate, or the slowest - * faster than bit_rate - */ - - if (feed_codec->bit_rate <= bit_rate) { - if (best_bitrate > bit_rate || - feed_codec->bit_rate > best_bitrate) { - best_bitrate = feed_codec->bit_rate; - best = i; - } - continue; - } - if (feed_codec->bit_rate < best_bitrate) { - best_bitrate = feed_codec->bit_rate; - best = i; - } - } - return best; -} - -static int modify_current_stream(HTTPContext *c, char *rates) -{ - int i; - FFServerStream *req = c->stream; - int action_required = 0; - - /* Not much we can do for a feed */ - if (!req->feed) - return 0; - - for (i = 0; i < req->nb_streams; i++) { - AVCodecParameters *codec = req->streams[i]->codecpar; - - switch(rates[i]) { - case 0: - c->switch_feed_streams[i] = req->feed_streams[i]; - break; - case 1: - c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2); - break; - case 2: - /* Wants off or slow */ - c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4); -#ifdef WANTS_OFF - /* This doesn't work well when it turns off the only stream! */ - c->switch_feed_streams[i] = -2; - c->feed_streams[i] = -2; -#endif - break; - } - - if (c->switch_feed_streams[i] >= 0 && - c->switch_feed_streams[i] != c->feed_streams[i]) { - action_required = 1; - } - } - - return action_required; -} - -static void get_word(char *buf, int buf_size, const char **pp) -{ - const char *p; - char *q; - -#define SPACE_CHARS " \t\r\n" - - p = *pp; - p += strspn(p, SPACE_CHARS); - q = buf; - while (!av_isspace(*p) && *p != '\0') { - if ((q - buf) < buf_size - 1) - *q++ = *p; - p++; - } - if (buf_size > 0) - *q = '\0'; - *pp = p; -} - -static FFServerIPAddressACL* parse_dynamic_acl(FFServerStream *stream, - HTTPContext *c) -{ - FILE* f; - char line[1024]; - char cmd[1024]; - FFServerIPAddressACL *acl = NULL; - int line_num = 0; - const char *p; - - f = fopen(stream->dynamic_acl, "r"); - if (!f) { - perror(stream->dynamic_acl); - return NULL; - } - - acl = av_mallocz(sizeof(FFServerIPAddressACL)); - if (!acl) { - fclose(f); - return NULL; - } - - /* Build ACL */ - while (fgets(line, sizeof(line), f)) { - line_num++; - p = line; - while (av_isspace(*p)) - p++; - if (*p == '\0' || *p == '#') - continue; - ffserver_get_arg(cmd, sizeof(cmd), &p); - - if (!av_strcasecmp(cmd, "ACL")) - ffserver_parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, - line_num); - } - fclose(f); - return acl; -} - - -static void free_acl_list(FFServerIPAddressACL *in_acl) -{ - FFServerIPAddressACL *pacl, *pacl2; - - pacl = in_acl; - while(pacl) { - pacl2 = pacl; - pacl = pacl->next; - av_freep(pacl2); - } -} - -static int validate_acl_list(FFServerIPAddressACL *in_acl, HTTPContext *c) -{ - enum FFServerIPAddressAction last_action = IP_DENY; - FFServerIPAddressACL *acl; - struct in_addr *src = &c->from_addr.sin_addr; - unsigned long src_addr = src->s_addr; - - for (acl = in_acl; acl; acl = acl->next) { - if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr) - return (acl->action == IP_ALLOW) ? 1 : 0; - last_action = acl->action; - } - - /* Nothing matched, so return not the last action */ - return (last_action == IP_DENY) ? 1 : 0; -} - -static int validate_acl(FFServerStream *stream, HTTPContext *c) -{ - int ret = 0; - FFServerIPAddressACL *acl; - - /* if stream->acl is null validate_acl_list will return 1 */ - ret = validate_acl_list(stream->acl, c); - - if (stream->dynamic_acl[0]) { - acl = parse_dynamic_acl(stream, c); - ret = validate_acl_list(acl, c); - free_acl_list(acl); - } - - return ret; -} - -/** - * compute the real filename of a file by matching it without its - * extensions to all the stream's filenames - */ -static void compute_real_filename(char *filename, int max_size) -{ - char file1[1024]; - char file2[1024]; - char *p; - FFServerStream *stream; - - av_strlcpy(file1, filename, sizeof(file1)); - p = strrchr(file1, '.'); - if (p) - *p = '\0'; - for(stream = config.first_stream; stream; stream = stream->next) { - av_strlcpy(file2, stream->filename, sizeof(file2)); - p = strrchr(file2, '.'); - if (p) - *p = '\0'; - if (!strcmp(file1, file2)) { - av_strlcpy(filename, stream->filename, max_size); - break; - } - } -} - -enum RedirType { - REDIR_NONE, - REDIR_ASX, - REDIR_RAM, - REDIR_ASF, - REDIR_RTSP, - REDIR_SDP, -}; - -/* parse HTTP request and prepare header */ -static int http_parse_request(HTTPContext *c) -{ - const char *p; - char *p1; - enum RedirType redir_type; - char cmd[32]; - char info[1024], filename[1024]; - char url[1024], *q; - char protocol[32]; - char msg[1024]; - char *encoded_msg = NULL; - const char *mime_type; - FFServerStream *stream; - int i; - char ratebuf[32]; - const char *useragent = 0; - - p = c->buffer; - get_word(cmd, sizeof(cmd), &p); - av_strlcpy(c->method, cmd, sizeof(c->method)); - - if (!strcmp(cmd, "GET")) - c->post = 0; - else if (!strcmp(cmd, "POST")) - c->post = 1; - else - return -1; - - get_word(url, sizeof(url), &p); - av_strlcpy(c->url, url, sizeof(c->url)); - - get_word(protocol, sizeof(protocol), (const char **)&p); - if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1")) - return -1; - - av_strlcpy(c->protocol, protocol, sizeof(c->protocol)); - - if (config.debug) - http_log("%s - - New connection: %s %s\n", - inet_ntoa(c->from_addr.sin_addr), cmd, url); - - /* find the filename and the optional info string in the request */ - p1 = strchr(url, '?'); - if (p1) { - av_strlcpy(info, p1, sizeof(info)); - *p1 = '\0'; - } else - info[0] = '\0'; - - av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1); - - for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) { - if (av_strncasecmp(p, "User-Agent:", 11) == 0) { - useragent = p + 11; - if (*useragent && *useragent != '\n' && av_isspace(*useragent)) - useragent++; - break; - } - p = strchr(p, '\n'); - if (!p) - break; - - p++; - } - - redir_type = REDIR_NONE; - if (av_match_ext(filename, "asx")) { - redir_type = REDIR_ASX; - filename[strlen(filename)-1] = 'f'; - } else if (av_match_ext(filename, "asf") && - (!useragent || av_strncasecmp(useragent, "NSPlayer", 8))) { - /* if this isn't WMP or lookalike, return the redirector file */ - redir_type = REDIR_ASF; - } else if (av_match_ext(filename, "rpm,ram")) { - redir_type = REDIR_RAM; - strcpy(filename + strlen(filename)-2, "m"); - } else if (av_match_ext(filename, "rtsp")) { - redir_type = REDIR_RTSP; - compute_real_filename(filename, sizeof(filename) - 1); - } else if (av_match_ext(filename, "sdp")) { - redir_type = REDIR_SDP; - compute_real_filename(filename, sizeof(filename) - 1); - } - - /* "redirect" request to index.html */ - if (!strlen(filename)) - av_strlcpy(filename, "index.html", sizeof(filename) - 1); - - stream = config.first_stream; - while (stream) { - if (!strcmp(stream->filename, filename) && validate_acl(stream, c)) - break; - stream = stream->next; - } - if (!stream) { - snprintf(msg, sizeof(msg), "File '%s' not found", url); - http_log("File '%s' not found\n", url); - goto send_error; - } - - c->stream = stream; - memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams)); - memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams)); - - if (stream->stream_type == STREAM_TYPE_REDIRECT) { - c->http_error = 301; - q = c->buffer; - snprintf(q, c->buffer_size, - "HTTP/1.0 301 Moved\r\n" - "Location: %s\r\n" - "Content-type: text/html\r\n" - "\r\n" - "\n" - "Moved\r\n" - "You should be
redirected.\r\n" - "\r\n", - stream->feed_filename, stream->feed_filename); - q += strlen(q); - /* prepare output buffer */ - c->buffer_ptr = c->buffer; - c->buffer_end = q; - c->state = HTTPSTATE_SEND_HEADER; - return 0; - } - - /* If this is WMP, get the rate information */ - if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) { - if (modify_current_stream(c, ratebuf)) { - for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) { - if (c->switch_feed_streams[i] >= 0) - c->switch_feed_streams[i] = -1; - } - } - } - - if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE) - current_bandwidth += stream->bandwidth; - - /* If already streaming this feed, do not let another feeder start */ - if (stream->feed_opened) { - snprintf(msg, sizeof(msg), "This feed is already being received."); - http_log("Feed '%s' already being received\n", stream->feed_filename); - goto send_error; - } - - if (c->post == 0 && config.max_bandwidth < current_bandwidth) { - c->http_error = 503; - q = c->buffer; - snprintf(q, c->buffer_size, - "HTTP/1.0 503 Server too busy\r\n" - "Content-type: text/html\r\n" - "\r\n" - "\n" - "Too busy\r\n" - "

The server is too busy to serve your request at " - "this time.

\r\n" - "

The bandwidth being served (including your stream) " - "is %"PRIu64"kbit/s, and this exceeds the limit of " - "%"PRIu64"kbit/s.

\r\n" - "\r\n", - current_bandwidth, config.max_bandwidth); - q += strlen(q); - /* prepare output buffer */ - c->buffer_ptr = c->buffer; - c->buffer_end = q; - c->state = HTTPSTATE_SEND_HEADER; - return 0; - } - - if (redir_type != REDIR_NONE) { - const char *hostinfo = 0; - - for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) { - if (av_strncasecmp(p, "Host:", 5) == 0) { - hostinfo = p + 5; - break; - } - p = strchr(p, '\n'); - if (!p) - break; - - p++; - } - - if (hostinfo) { - char *eoh; - char hostbuf[260]; - - while (av_isspace(*hostinfo)) - hostinfo++; - - eoh = strchr(hostinfo, '\n'); - if (eoh) { - if (eoh[-1] == '\r') - eoh--; - - if (eoh - hostinfo < sizeof(hostbuf) - 1) { - memcpy(hostbuf, hostinfo, eoh - hostinfo); - hostbuf[eoh - hostinfo] = 0; - - c->http_error = 200; - q = c->buffer; - switch(redir_type) { - case REDIR_ASX: - snprintf(q, c->buffer_size, - "HTTP/1.0 200 ASX Follows\r\n" - "Content-type: video/x-ms-asf\r\n" - "\r\n" - "\r\n" - //"\r\n" - "\r\n" - "\r\n", hostbuf, filename, info); - q += strlen(q); - break; - case REDIR_RAM: - snprintf(q, c->buffer_size, - "HTTP/1.0 200 RAM Follows\r\n" - "Content-type: audio/x-pn-realaudio\r\n" - "\r\n" - "# Autogenerated by ffserver\r\n" - "http://%s/%s%s\r\n", hostbuf, filename, info); - q += strlen(q); - break; - case REDIR_ASF: - snprintf(q, c->buffer_size, - "HTTP/1.0 200 ASF Redirect follows\r\n" - "Content-type: video/x-ms-asf\r\n" - "\r\n" - "[Reference]\r\n" - "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info); - q += strlen(q); - break; - case REDIR_RTSP: - { - char hostname[256], *p; - /* extract only hostname */ - av_strlcpy(hostname, hostbuf, sizeof(hostname)); - p = strrchr(hostname, ':'); - if (p) - *p = '\0'; - snprintf(q, c->buffer_size, - "HTTP/1.0 200 RTSP Redirect follows\r\n" - /* XXX: incorrect MIME type ? */ - "Content-type: application/x-rtsp\r\n" - "\r\n" - "rtsp://%s:%d/%s\r\n", hostname, ntohs(config.rtsp_addr.sin_port), filename); - q += strlen(q); - } - break; - case REDIR_SDP: - { - uint8_t *sdp_data; - int sdp_data_size; - socklen_t len; - struct sockaddr_in my_addr; - - snprintf(q, c->buffer_size, - "HTTP/1.0 200 OK\r\n" - "Content-type: application/sdp\r\n" - "\r\n"); - q += strlen(q); - - len = sizeof(my_addr); - - /* XXX: Should probably fail? */ - if (getsockname(c->fd, (struct sockaddr *)&my_addr, &len)) - http_log("getsockname() failed\n"); - - /* XXX: should use a dynamic buffer */ - sdp_data_size = prepare_sdp_description(stream, - &sdp_data, - my_addr.sin_addr); - if (sdp_data_size > 0) { - memcpy(q, sdp_data, sdp_data_size); - q += sdp_data_size; - *q = '\0'; - av_freep(&sdp_data); - } - } - break; - default: - abort(); - break; - } - - /* prepare output buffer */ - c->buffer_ptr = c->buffer; - c->buffer_end = q; - c->state = HTTPSTATE_SEND_HEADER; - return 0; - } - } - } - - snprintf(msg, sizeof(msg), "ASX/RAM file not handled"); - goto send_error; - } - - stream->conns_served++; - - /* XXX: add there authenticate and IP match */ - - if (c->post) { - /* if post, it means a feed is being sent */ - if (!stream->is_feed) { - /* However it might be a status report from WMP! Let us log the - * data as it might come handy one day. */ - const char *logline = 0; - int client_id = 0; - - for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) { - if (av_strncasecmp(p, "Pragma: log-line=", 17) == 0) { - logline = p; - break; - } - if (av_strncasecmp(p, "Pragma: client-id=", 18) == 0) - client_id = strtol(p + 18, 0, 10); - p = strchr(p, '\n'); - if (!p) - break; - - p++; - } - - if (logline) { - char *eol = strchr(logline, '\n'); - - logline += 17; - - if (eol) { - if (eol[-1] == '\r') - eol--; - http_log("%.*s\n", (int) (eol - logline), logline); - c->suppress_log = 1; - } - } - -#ifdef DEBUG - http_log("\nGot request:\n%s\n", c->buffer); -#endif - - if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) { - HTTPContext *wmpc; - - /* Now we have to find the client_id */ - for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) { - if (wmpc->wmp_client_id == client_id) - break; - } - - if (wmpc && modify_current_stream(wmpc, ratebuf)) - wmpc->switch_pending = 1; - } - - snprintf(msg, sizeof(msg), "POST command not handled"); - c->stream = 0; - goto send_error; - } - if (http_start_receive_data(c) < 0) { - snprintf(msg, sizeof(msg), "could not open feed"); - goto send_error; - } - c->http_error = 0; - c->state = HTTPSTATE_RECEIVE_DATA; - return 0; - } - -#ifdef DEBUG - if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0) - http_log("\nGot request:\n%s\n", c->buffer); -#endif - - if (c->stream->stream_type == STREAM_TYPE_STATUS) - goto send_status; - - /* open input stream */ - if (open_input_stream(c, info) < 0) { - snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url); - goto send_error; - } - - /* prepare HTTP header */ - c->buffer[0] = 0; - av_strlcatf(c->buffer, c->buffer_size, "HTTP/1.0 200 OK\r\n"); - mime_type = c->stream->fmt->mime_type; - if (!mime_type) - mime_type = "application/x-octet-stream"; - av_strlcatf(c->buffer, c->buffer_size, "Pragma: no-cache\r\n"); - - /* for asf, we need extra headers */ - if (!strcmp(c->stream->fmt->name,"asf_stream")) { - /* Need to allocate a client id */ - - c->wmp_client_id = av_lfg_get(&random_state); - - av_strlcatf(c->buffer, c->buffer_size, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=%d\r\nPragma: features=\"broadcast\"\r\n", c->wmp_client_id); - } - av_strlcatf(c->buffer, c->buffer_size, "Content-Type: %s\r\n", mime_type); - av_strlcatf(c->buffer, c->buffer_size, "\r\n"); - q = c->buffer + strlen(c->buffer); - - /* prepare output buffer */ - c->http_error = 0; - c->buffer_ptr = c->buffer; - c->buffer_end = q; - c->state = HTTPSTATE_SEND_HEADER; - return 0; - send_error: - c->http_error = 404; - q = c->buffer; - if (!htmlencode(msg, &encoded_msg)) { - http_log("Could not encode filename '%s' as HTML\n", msg); - } - snprintf(q, c->buffer_size, - "HTTP/1.0 404 Not Found\r\n" - "Content-type: text/html\r\n" - "\r\n" - "\n" - "\n" - "\n" - "\n" - "404 Not Found\n" - "\n" - "%s\n" - "\n", encoded_msg? encoded_msg : "File not found"); - q += strlen(q); - /* prepare output buffer */ - c->buffer_ptr = c->buffer; - c->buffer_end = q; - c->state = HTTPSTATE_SEND_HEADER; - av_freep(&encoded_msg); - return 0; - send_status: - compute_status(c); - /* horrible: we use this value to avoid - * going to the send data state */ - c->http_error = 200; - c->state = HTTPSTATE_SEND_HEADER; - return 0; -} - -static void fmt_bytecount(AVIOContext *pb, int64_t count) -{ - static const char suffix[] = " kMGTP"; - const char *s; - - for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++); - - avio_printf(pb, "%"PRId64"%c", count, *s); -} - -static inline void print_stream_params(AVIOContext *pb, FFServerStream *stream) -{ - int i, stream_no; - const char *type = "unknown"; - char parameters[64]; - LayeredAVStream *st; - AVCodec *codec; - - stream_no = stream->nb_streams; - - avio_printf(pb, "
Stream" - "typekbit/scodec" - "Parameters\n"); - - for (i = 0; i < stream_no; i++) { - st = stream->streams[i]; - codec = avcodec_find_encoder(st->codecpar->codec_id); - - parameters[0] = 0; - - switch(st->codecpar->codec_type) { - case AVMEDIA_TYPE_AUDIO: - type = "audio"; - snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", - st->codecpar->channels, st->codecpar->sample_rate); - break; - case AVMEDIA_TYPE_VIDEO: - type = "video"; - snprintf(parameters, sizeof(parameters), - "%dx%d, q=%d-%d, fps=%d", st->codecpar->width, - st->codecpar->height, st->codec->qmin, st->codec->qmax, - st->time_base.den / st->time_base.num); - break; - default: - abort(); - } - - avio_printf(pb, "
%d%s%"PRId64 - "%s%s\n", - i, type, st->codecpar->bit_rate/1000, - codec ? codec->name : "", parameters); - } - - avio_printf(pb, "
\n"); -} - -static void clean_html(char *clean, int clean_len, char *dirty) -{ - int i, o; - - for (o = i = 0; o+10 < clean_len && dirty[i];) { - int len = strspn(dirty+i, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$-_.+!*(),?/ :;%"); - if (len) { - if (o + len >= clean_len) - break; - memcpy(clean + o, dirty + i, len); - i += len; - o += len; - } else { - int c = dirty[i++]; - switch (c) { - case '&': av_strlcat(clean+o, "&" , clean_len - o); break; - case '<': av_strlcat(clean+o, "<" , clean_len - o); break; - case '>': av_strlcat(clean+o, ">" , clean_len - o); break; - case '\'': av_strlcat(clean+o, "'" , clean_len - o); break; - case '\"': av_strlcat(clean+o, """ , clean_len - o); break; - default: av_strlcat(clean+o, "☹", clean_len - o); break; - } - o += strlen(clean+o); - } - } - clean[o] = 0; -} - -static void compute_status(HTTPContext *c) -{ - HTTPContext *c1; - FFServerStream *stream; - char *p; - time_t ti; - int i, len; - AVIOContext *pb; - - if (avio_open_dyn_buf(&pb) < 0) { - /* XXX: return an error ? */ - c->buffer_ptr = c->buffer; - c->buffer_end = c->buffer; - return; - } - - avio_printf(pb, "HTTP/1.0 200 OK\r\n"); - avio_printf(pb, "Content-type: text/html\r\n"); - avio_printf(pb, "Pragma: no-cache\r\n"); - avio_printf(pb, "\r\n"); - - avio_printf(pb, "\n"); - avio_printf(pb, "%s Status\n", program_name); - if (c->stream->feed_filename[0]) - avio_printf(pb, "\n", - c->stream->feed_filename); - avio_printf(pb, "\n"); - avio_printf(pb, "

%s Status

\n", program_name); - /* format status */ - avio_printf(pb, "

Available Streams

\n"); - avio_printf(pb, "\n"); - avio_printf(pb, "
PathServed
Conns

bytes
FormatBit rate
kbit/s
Video
kbit/s

Codec
Audio
kbit/s

Codec
Feed\n"); - stream = config.first_stream; - while (stream) { - char sfilename[1024]; - char *eosf; - - if (stream->feed == stream) { - stream = stream->next; - continue; - } - - av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10); - eosf = sfilename + strlen(sfilename); - if (eosf - sfilename >= 4) { - if (strcmp(eosf - 4, ".asf") == 0) - strcpy(eosf - 4, ".asx"); - else if (strcmp(eosf - 3, ".rm") == 0) - strcpy(eosf - 3, ".ram"); - else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) { - /* generate a sample RTSP director if - * unicast. Generate an SDP redirector if - * multicast */ - eosf = strrchr(sfilename, '.'); - if (!eosf) - eosf = sfilename + strlen(sfilename); - if (stream->is_multicast) - strcpy(eosf, ".sdp"); - else - strcpy(eosf, ".rtsp"); - } - } - - avio_printf(pb, "
%s ", - sfilename, stream->filename); - avio_printf(pb, " %d ", - stream->conns_served); - // TODO: Investigate if we can make http bitexact so it always produces the same count of bytes - if (!config.bitexact) - fmt_bytecount(pb, stream->bytes_served); - - switch(stream->stream_type) { - case STREAM_TYPE_LIVE: { - int audio_bit_rate = 0; - int video_bit_rate = 0; - const char *audio_codec_name = ""; - const char *video_codec_name = ""; - const char *audio_codec_name_extra = ""; - const char *video_codec_name_extra = ""; - - for(i=0;inb_streams;i++) { - LayeredAVStream *st = stream->streams[i]; - AVCodec *codec = avcodec_find_encoder(st->codecpar->codec_id); - - switch(st->codecpar->codec_type) { - case AVMEDIA_TYPE_AUDIO: - audio_bit_rate += st->codecpar->bit_rate; - if (codec) { - if (*audio_codec_name) - audio_codec_name_extra = "..."; - audio_codec_name = codec->name; - } - break; - case AVMEDIA_TYPE_VIDEO: - video_bit_rate += st->codecpar->bit_rate; - if (codec) { - if (*video_codec_name) - video_codec_name_extra = "..."; - video_codec_name = codec->name; - } - break; - case AVMEDIA_TYPE_DATA: - video_bit_rate += st->codecpar->bit_rate; - break; - default: - abort(); - } - } - - avio_printf(pb, " %s %d %d %s %s " - "%d %s %s", - stream->fmt->name, stream->bandwidth, - video_bit_rate / 1000, video_codec_name, - video_codec_name_extra, audio_bit_rate / 1000, - audio_codec_name, audio_codec_name_extra); - - if (stream->feed) - avio_printf(pb, "%s", stream->feed->filename); - else - avio_printf(pb, "%s", stream->feed_filename); - avio_printf(pb, "\n"); - } - break; - default: - avio_printf(pb, " - - " - " - - \n"); - break; - } - stream = stream->next; - } - avio_printf(pb, "
\n"); - - stream = config.first_stream; - while (stream) { - - if (stream->feed != stream) { - stream = stream->next; - continue; - } - - avio_printf(pb, "

Feed %s

", stream->filename); - if (stream->pid) { - avio_printf(pb, "Running as pid %"PRId64".\n", (int64_t) stream->pid); - -#if defined(linux) - { - FILE *pid_stat; - char ps_cmd[64]; - - /* This is somewhat linux specific I guess */ - snprintf(ps_cmd, sizeof(ps_cmd), - "ps -o \"%%cpu,cputime\" --no-headers %"PRId64"", - (int64_t) stream->pid); - - pid_stat = popen(ps_cmd, "r"); - if (pid_stat) { - char cpuperc[10]; - char cpuused[64]; - - if (fscanf(pid_stat, "%9s %63s", cpuperc, cpuused) == 2) { - avio_printf(pb, "Currently using %s%% of the cpu. " - "Total time used %s.\n", - cpuperc, cpuused); - } - fclose(pid_stat); - } - } -#endif - - avio_printf(pb, "

"); - } - - print_stream_params(pb, stream); - stream = stream->next; - } - - /* connection status */ - avio_printf(pb, "

Connection Status

\n"); - - avio_printf(pb, "Number of connections: %d / %d
\n", - nb_connections, config.nb_max_connections); - - avio_printf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k
\n", - current_bandwidth, config.max_bandwidth); - - avio_printf(pb, "\n"); - avio_printf(pb, "
#FileIPURLProtoStateTarget " - "bit/sActual bit/sBytes transferred\n"); - c1 = first_http_ctx; - i = 0; - while (c1) { - int bitrate; - int j; - - bitrate = 0; - if (c1->stream) { - for (j = 0; j < c1->stream->nb_streams; j++) { - if (!c1->stream->feed) - bitrate += c1->stream->streams[j]->codecpar->bit_rate; - else if (c1->feed_streams[j] >= 0) - bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codecpar->bit_rate; - } - } - - i++; - p = inet_ntoa(c1->from_addr.sin_addr); - clean_html(c1->clean_url, sizeof(c1->clean_url), c1->url); - avio_printf(pb, "
%d%s%s%s%s%s%s" - "", - i, c1->stream ? c1->stream->filename : "", - c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "", - p, - c1->clean_url, - c1->protocol, http_state[c1->state]); - fmt_bytecount(pb, bitrate); - avio_printf(pb, ""); - fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8); - avio_printf(pb, ""); - fmt_bytecount(pb, c1->data_count); - avio_printf(pb, "\n"); - c1 = c1->next; - } - avio_printf(pb, "
\n"); - - if (!config.bitexact) { - /* date */ - ti = time(NULL); - p = ctime(&ti); - avio_printf(pb, "
Generated at %s", p); - } - avio_printf(pb, "\n\n"); - - len = avio_close_dyn_buf(pb, &c->pb_buffer); - c->buffer_ptr = c->pb_buffer; - c->buffer_end = c->pb_buffer + len; -} - -static int open_input_stream(HTTPContext *c, const char *info) -{ - char buf[128]; - char input_filename[1024]; - AVFormatContext *s = NULL; - int buf_size, i, ret; - int64_t stream_pos; - - /* find file name */ - if (c->stream->feed) { - strcpy(input_filename, c->stream->feed->feed_filename); - buf_size = FFM_PACKET_SIZE; - /* compute position (absolute time) */ - if (av_find_info_tag(buf, sizeof(buf), "date", info)) { - if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0) { - http_log("Invalid date specification '%s' for stream\n", buf); - return ret; - } - } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) { - int prebuffer = strtol(buf, 0, 10); - stream_pos = av_gettime() - prebuffer * (int64_t)1000000; - } else - stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000; - } else { - strcpy(input_filename, c->stream->feed_filename); - buf_size = 0; - /* compute position (relative time) */ - if (av_find_info_tag(buf, sizeof(buf), "date", info)) { - if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0) { - http_log("Invalid date specification '%s' for stream\n", buf); - return ret; - } - } else - stream_pos = 0; - } - if (!input_filename[0]) { - http_log("No filename was specified for stream\n"); - return AVERROR(EINVAL); - } - - /* open stream */ - ret = avformat_open_input(&s, input_filename, c->stream->ifmt, - &c->stream->in_opts); - if (ret < 0) { - http_log("Could not open input '%s': %s\n", - input_filename, av_err2str(ret)); - return ret; - } - - /* set buffer size */ - if (buf_size > 0) { - ret = ffio_set_buf_size(s->pb, buf_size); - if (ret < 0) { - http_log("Failed to set buffer size\n"); - return ret; - } - } - - s->flags |= AVFMT_FLAG_GENPTS; - c->fmt_in = s; - if (strcmp(s->iformat->name, "ffm") && - (ret = avformat_find_stream_info(c->fmt_in, NULL)) < 0) { - http_log("Could not find stream info for input '%s'\n", input_filename); - avformat_close_input(&s); - return ret; - } - - /* choose stream as clock source (we favor the video stream if - * present) for packet sending */ - c->pts_stream_index = 0; - for(i=0;istream->nb_streams;i++) { - if (c->pts_stream_index == 0 && - c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - c->pts_stream_index = i; - } - } - - if (c->fmt_in->iformat->read_seek) - av_seek_frame(c->fmt_in, -1, stream_pos, 0); - /* set the start time (needed for maxtime and RTP packet timing) */ - c->start_time = cur_time; - c->first_pts = AV_NOPTS_VALUE; - return 0; -} - -/* return the server clock (in us) */ -static int64_t get_server_clock(HTTPContext *c) -{ - /* compute current pts value from system time */ - return (cur_time - c->start_time) * 1000; -} - -/* return the estimated time (in us) at which the current packet must be sent */ -static int64_t get_packet_send_clock(HTTPContext *c) -{ - int bytes_left, bytes_sent, frame_bytes; - - frame_bytes = c->cur_frame_bytes; - if (frame_bytes <= 0) - return c->cur_pts; - - bytes_left = c->buffer_end - c->buffer_ptr; - bytes_sent = frame_bytes - bytes_left; - return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes; -} - - -static int http_prepare_data(HTTPContext *c) -{ - int i, len, ret; - AVFormatContext *ctx; - - av_freep(&c->pb_buffer); - switch(c->state) { - case HTTPSTATE_SEND_DATA_HEADER: - ctx = avformat_alloc_context(); - if (!ctx) - return AVERROR(ENOMEM); - c->pfmt_ctx = ctx; - av_dict_copy(&(c->pfmt_ctx->metadata), c->stream->metadata, 0); - - for(i=0;istream->nb_streams;i++) { - LayeredAVStream *src; - AVStream *st = avformat_new_stream(c->pfmt_ctx, NULL); - if (!st) - return AVERROR(ENOMEM); - - /* if file or feed, then just take streams from FFServerStream - * struct */ - if (!c->stream->feed || - c->stream->feed == c->stream) - src = c->stream->streams[i]; - else - src = c->stream->feed->streams[c->stream->feed_streams[i]]; - - unlayer_stream(c->pfmt_ctx->streams[i], src); //TODO we no longer copy st->internal, does this matter? - av_assert0(!c->pfmt_ctx->streams[i]->priv_data); - - if (src->codec->flags & AV_CODEC_FLAG_BITEXACT) - c->pfmt_ctx->flags |= AVFMT_FLAG_BITEXACT; - } - /* set output format parameters */ - c->pfmt_ctx->oformat = c->stream->fmt; - av_assert0(c->pfmt_ctx->nb_streams == c->stream->nb_streams); - - c->got_key_frame = 0; - - /* prepare header and save header data in a stream */ - if (avio_open_dyn_buf(&c->pfmt_ctx->pb) < 0) { - /* XXX: potential leak */ - return -1; - } - c->pfmt_ctx->pb->seekable = 0; - - /* - * HACK to avoid MPEG-PS muxer to spit many underflow errors - * Default value from FFmpeg - * Try to set it using configuration option - */ - c->pfmt_ctx->max_delay = (int)(0.7*AV_TIME_BASE); - - if ((ret = avformat_write_header(c->pfmt_ctx, NULL)) < 0) { - http_log("Error writing output header for stream '%s': %s\n", - c->stream->filename, av_err2str(ret)); - return ret; - } - av_dict_free(&c->pfmt_ctx->metadata); - - len = avio_close_dyn_buf(c->pfmt_ctx->pb, &c->pb_buffer); - c->buffer_ptr = c->pb_buffer; - c->buffer_end = c->pb_buffer + len; - - c->state = HTTPSTATE_SEND_DATA; - c->last_packet_sent = 0; - break; - case HTTPSTATE_SEND_DATA: - /* find a new packet */ - /* read a packet from the input stream */ - if (c->stream->feed) - ffm_set_write_index(c->fmt_in, - c->stream->feed->feed_write_index, - c->stream->feed->feed_size); - - if (c->stream->max_time && - c->stream->max_time + c->start_time - cur_time < 0) - /* We have timed out */ - c->state = HTTPSTATE_SEND_DATA_TRAILER; - else { - AVPacket pkt; - redo: - ret = av_read_frame(c->fmt_in, &pkt); - if (ret < 0) { - if (c->stream->feed) { - /* if coming from feed, it means we reached the end of the - * ffm file, so must wait for more data */ - c->state = HTTPSTATE_WAIT_FEED; - return 1; /* state changed */ - } - if (ret == AVERROR(EAGAIN)) { - /* input not ready, come back later */ - return 0; - } - if (c->stream->loop) { - avformat_close_input(&c->fmt_in); - if (open_input_stream(c, "") < 0) - goto no_loop; - goto redo; - } else { - no_loop: - /* must send trailer now because EOF or error */ - c->state = HTTPSTATE_SEND_DATA_TRAILER; - } - } else { - int source_index = pkt.stream_index; - /* update first pts if needed */ - if (c->first_pts == AV_NOPTS_VALUE && pkt.dts != AV_NOPTS_VALUE) { - c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q); - c->start_time = cur_time; - } - /* send it to the appropriate stream */ - if (c->stream->feed) { - /* if coming from a feed, select the right stream */ - if (c->switch_pending) { - c->switch_pending = 0; - for(i=0;istream->nb_streams;i++) { - if (c->switch_feed_streams[i] == pkt.stream_index) - if (pkt.flags & AV_PKT_FLAG_KEY) - c->switch_feed_streams[i] = -1; - if (c->switch_feed_streams[i] >= 0) - c->switch_pending = 1; - } - } - for(i=0;istream->nb_streams;i++) { - if (c->stream->feed_streams[i] == pkt.stream_index) { - AVStream *st = c->fmt_in->streams[source_index]; - pkt.stream_index = i; - if (pkt.flags & AV_PKT_FLAG_KEY && - (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || - c->stream->nb_streams == 1)) - c->got_key_frame = 1; - if (!c->stream->send_on_key || c->got_key_frame) - goto send_it; - } - } - } else { - AVStream *ist, *ost; - send_it: - ist = c->fmt_in->streams[source_index]; - /* specific handling for RTP: we use several - * output streams (one for each RTP connection). - * XXX: need more abstract handling */ - if (c->is_packetized) { - /* compute send time and duration */ - if (pkt.dts != AV_NOPTS_VALUE) { - c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q); - c->cur_pts -= c->first_pts; - } - c->cur_frame_duration = av_rescale_q(pkt.duration, ist->time_base, AV_TIME_BASE_Q); - /* find RTP context */ - c->packet_stream_index = pkt.stream_index; - ctx = c->rtp_ctx[c->packet_stream_index]; - if(!ctx) { - av_packet_unref(&pkt); - break; - } - /* only one stream per RTP connection */ - pkt.stream_index = 0; - } else { - ctx = c->pfmt_ctx; - /* Fudge here */ - } - - if (c->is_packetized) { - int max_packet_size; - if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) - max_packet_size = RTSP_TCP_MAX_PACKET_SIZE; - else - max_packet_size = c->rtp_handles[c->packet_stream_index]->max_packet_size; - ret = ffio_open_dyn_packet_buf(&ctx->pb, - max_packet_size); - } else - ret = avio_open_dyn_buf(&ctx->pb); - - if (ret < 0) { - /* XXX: potential leak */ - return -1; - } - ost = ctx->streams[pkt.stream_index]; - - ctx->pb->seekable = 0; - if (pkt.dts != AV_NOPTS_VALUE) - pkt.dts = av_rescale_q(pkt.dts, ist->time_base, - ost->time_base); - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts = av_rescale_q(pkt.pts, ist->time_base, - ost->time_base); - pkt.duration = av_rescale_q(pkt.duration, ist->time_base, - ost->time_base); - if ((ret = av_write_frame(ctx, &pkt)) < 0) { - http_log("Error writing frame to output for stream '%s': %s\n", - c->stream->filename, av_err2str(ret)); - c->state = HTTPSTATE_SEND_DATA_TRAILER; - } - - av_freep(&c->pb_buffer); - len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer); - ctx->pb = NULL; - c->cur_frame_bytes = len; - c->buffer_ptr = c->pb_buffer; - c->buffer_end = c->pb_buffer + len; - - if (len == 0) { - av_packet_unref(&pkt); - goto redo; - } - } - av_packet_unref(&pkt); - } - } - break; - default: - case HTTPSTATE_SEND_DATA_TRAILER: - /* last packet test ? */ - if (c->last_packet_sent || c->is_packetized) - return -1; - ctx = c->pfmt_ctx; - /* prepare header */ - if (avio_open_dyn_buf(&ctx->pb) < 0) { - /* XXX: potential leak */ - return -1; - } - c->pfmt_ctx->pb->seekable = 0; - av_write_trailer(ctx); - len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer); - c->buffer_ptr = c->pb_buffer; - c->buffer_end = c->pb_buffer + len; - - c->last_packet_sent = 1; - break; - } - return 0; -} - -/* should convert the format at the same time */ -/* send data starting at c->buffer_ptr to the output connection - * (either UDP or TCP) - */ -static int http_send_data(HTTPContext *c) -{ - int len, ret; - - for(;;) { - if (c->buffer_ptr >= c->buffer_end) { - ret = http_prepare_data(c); - if (ret < 0) - return -1; - else if (ret) - /* state change requested */ - break; - } else { - if (c->is_packetized) { - /* RTP data output */ - len = c->buffer_end - c->buffer_ptr; - if (len < 4) { - /* fail safe - should never happen */ - fail1: - c->buffer_ptr = c->buffer_end; - return 0; - } - len = (c->buffer_ptr[0] << 24) | - (c->buffer_ptr[1] << 16) | - (c->buffer_ptr[2] << 8) | - (c->buffer_ptr[3]); - if (len > (c->buffer_end - c->buffer_ptr)) - goto fail1; - if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) { - /* nothing to send yet: we can wait */ - return 0; - } - - c->data_count += len; - update_datarate(&c->datarate, c->data_count); - if (c->stream) - c->stream->bytes_served += len; - - if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) { - /* RTP packets are sent inside the RTSP TCP connection */ - AVIOContext *pb; - int interleaved_index, size; - uint8_t header[4]; - HTTPContext *rtsp_c; - - rtsp_c = c->rtsp_c; - /* if no RTSP connection left, error */ - if (!rtsp_c) - return -1; - /* if already sending something, then wait. */ - if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST) - break; - if (avio_open_dyn_buf(&pb) < 0) - goto fail1; - interleaved_index = c->packet_stream_index * 2; - /* RTCP packets are sent at odd indexes */ - if (c->buffer_ptr[1] == 200) - interleaved_index++; - /* write RTSP TCP header */ - header[0] = '$'; - header[1] = interleaved_index; - header[2] = len >> 8; - header[3] = len; - avio_write(pb, header, 4); - /* write RTP packet data */ - c->buffer_ptr += 4; - avio_write(pb, c->buffer_ptr, len); - size = avio_close_dyn_buf(pb, &c->packet_buffer); - /* prepare asynchronous TCP sending */ - rtsp_c->packet_buffer_ptr = c->packet_buffer; - rtsp_c->packet_buffer_end = c->packet_buffer + size; - c->buffer_ptr += len; - - /* send everything we can NOW */ - len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr, - rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0); - if (len > 0) - rtsp_c->packet_buffer_ptr += len; - if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) { - /* if we could not send all the data, we will - * send it later, so a new state is needed to - * "lock" the RTSP TCP connection */ - rtsp_c->state = RTSPSTATE_SEND_PACKET; - break; - } else - /* all data has been sent */ - av_freep(&c->packet_buffer); - } else { - /* send RTP packet directly in UDP */ - c->buffer_ptr += 4; - ffurl_write(c->rtp_handles[c->packet_stream_index], - c->buffer_ptr, len); - c->buffer_ptr += len; - /* here we continue as we can send several packets - * per 10 ms slot */ - } - } else { - /* TCP data output */ - len = send(c->fd, c->buffer_ptr, - c->buffer_end - c->buffer_ptr, 0); - if (len < 0) { - if (ff_neterrno() != AVERROR(EAGAIN) && - ff_neterrno() != AVERROR(EINTR)) - /* error : close connection */ - return -1; - else - return 0; - } - c->buffer_ptr += len; - - c->data_count += len; - update_datarate(&c->datarate, c->data_count); - if (c->stream) - c->stream->bytes_served += len; - break; - } - } - } /* for(;;) */ - return 0; -} - -static int http_start_receive_data(HTTPContext *c) -{ - int fd; - int ret; - int64_t ret64; - - if (c->stream->feed_opened) { - http_log("Stream feed '%s' was not opened\n", - c->stream->feed_filename); - return AVERROR(EINVAL); - } - - /* Don't permit writing to this one */ - if (c->stream->readonly) { - http_log("Cannot write to read-only file '%s'\n", - c->stream->feed_filename); - return AVERROR(EINVAL); - } - - /* open feed */ - fd = open(c->stream->feed_filename, O_RDWR); - if (fd < 0) { - ret = AVERROR(errno); - http_log("Could not open feed file '%s': %s\n", - c->stream->feed_filename, strerror(errno)); - return ret; - } - c->feed_fd = fd; - - if (c->stream->truncate) { - /* truncate feed file */ - ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE); - http_log("Truncating feed file '%s'\n", c->stream->feed_filename); - if (ftruncate(c->feed_fd, FFM_PACKET_SIZE) < 0) { - ret = AVERROR(errno); - http_log("Error truncating feed file '%s': %s\n", - c->stream->feed_filename, strerror(errno)); - return ret; - } - } else { - ret64 = ffm_read_write_index(fd); - if (ret64 < 0) { - http_log("Error reading write index from feed file '%s': %s\n", - c->stream->feed_filename, strerror(errno)); - return ret64; - } - c->stream->feed_write_index = ret64; - } - - c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), - FFM_PACKET_SIZE); - c->stream->feed_size = lseek(fd, 0, SEEK_END); - lseek(fd, 0, SEEK_SET); - - /* init buffer input */ - c->buffer_ptr = c->buffer; - c->buffer_end = c->buffer + FFM_PACKET_SIZE; - c->stream->feed_opened = 1; - c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked"); - return 0; -} - -static int http_receive_data(HTTPContext *c) -{ - HTTPContext *c1; - int len, loop_run = 0; - - while (c->chunked_encoding && !c->chunk_size && - c->buffer_end > c->buffer_ptr) { - /* read chunk header, if present */ - len = recv(c->fd, c->buffer_ptr, 1, 0); - - if (len < 0) { - if (ff_neterrno() != AVERROR(EAGAIN) && - ff_neterrno() != AVERROR(EINTR)) - /* error : close connection */ - goto fail; - return 0; - } else if (len == 0) { - /* end of connection : close it */ - goto fail; - } else if (c->buffer_ptr - c->buffer >= 2 && - !memcmp(c->buffer_ptr - 1, "\r\n", 2)) { - c->chunk_size = strtol(c->buffer, 0, 16); - if (c->chunk_size <= 0) { // end of stream or invalid chunk size - c->chunk_size = 0; - goto fail; - } - c->buffer_ptr = c->buffer; - break; - } else if (++loop_run > 10) - /* no chunk header, abort */ - goto fail; - else - c->buffer_ptr++; - } - - if (c->buffer_end > c->buffer_ptr) { - len = recv(c->fd, c->buffer_ptr, - FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0); - if (len < 0) { - if (ff_neterrno() != AVERROR(EAGAIN) && - ff_neterrno() != AVERROR(EINTR)) - /* error : close connection */ - goto fail; - } else if (len == 0) - /* end of connection : close it */ - goto fail; - else { - av_assert0(len <= c->chunk_size); - c->chunk_size -= len; - c->buffer_ptr += len; - c->data_count += len; - update_datarate(&c->datarate, c->data_count); - } - } - - if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) { - if (c->buffer[0] != 'f' || - c->buffer[1] != 'm') { - http_log("Feed stream has become desynchronized -- disconnecting\n"); - goto fail; - } - } - - if (c->buffer_ptr >= c->buffer_end) { - FFServerStream *feed = c->stream; - /* a packet has been received : write it in the store, except - * if header */ - if (c->data_count > FFM_PACKET_SIZE) { - /* XXX: use llseek or url_seek - * XXX: Should probably fail? */ - if (lseek(c->feed_fd, feed->feed_write_index, SEEK_SET) == -1) - http_log("Seek to %"PRId64" failed\n", feed->feed_write_index); - - if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) { - http_log("Error writing to feed file: %s\n", strerror(errno)); - goto fail; - } - - feed->feed_write_index += FFM_PACKET_SIZE; - /* update file size */ - if (feed->feed_write_index > c->stream->feed_size) - feed->feed_size = feed->feed_write_index; - - /* handle wrap around if max file size reached */ - if (c->stream->feed_max_size && - feed->feed_write_index >= c->stream->feed_max_size) - feed->feed_write_index = FFM_PACKET_SIZE; - - /* write index */ - if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) { - http_log("Error writing index to feed file: %s\n", - strerror(errno)); - goto fail; - } - - /* wake up any waiting connections */ - for(c1 = first_http_ctx; c1; c1 = c1->next) { - if (c1->state == HTTPSTATE_WAIT_FEED && - c1->stream->feed == c->stream->feed) - c1->state = HTTPSTATE_SEND_DATA; - } - } else { - /* We have a header in our hands that contains useful data */ - AVFormatContext *s = avformat_alloc_context(); - AVIOContext *pb; - AVInputFormat *fmt_in; - int i; - - if (!s) - goto fail; - - /* use feed output format name to find corresponding input format */ - fmt_in = av_find_input_format(feed->fmt->name); - if (!fmt_in) - goto fail; - - pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer, - 0, NULL, NULL, NULL, NULL); - if (!pb) - goto fail; - - pb->seekable = 0; - - s->pb = pb; - if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) { - av_freep(&pb); - goto fail; - } - - /* Now we have the actual streams */ - if (s->nb_streams != feed->nb_streams) { - avformat_close_input(&s); - av_freep(&pb); - http_log("Feed '%s' stream number does not match registered feed\n", - c->stream->feed_filename); - goto fail; - } - - for (i = 0; i < s->nb_streams; i++) { - LayeredAVStream *fst = feed->streams[i]; - AVStream *st = s->streams[i]; - avcodec_parameters_to_context(fst->codec, st->codecpar); - avcodec_parameters_from_context(fst->codecpar, fst->codec); - } - - avformat_close_input(&s); - av_freep(&pb); - } - c->buffer_ptr = c->buffer; - } - - return 0; - fail: - c->stream->feed_opened = 0; - close(c->feed_fd); - /* wake up any waiting connections to stop waiting for feed */ - for(c1 = first_http_ctx; c1; c1 = c1->next) { - if (c1->state == HTTPSTATE_WAIT_FEED && - c1->stream->feed == c->stream->feed) - c1->state = HTTPSTATE_SEND_DATA_TRAILER; - } - return -1; -} - -/********************************************************************/ -/* RTSP handling */ - -static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number) -{ - const char *str; - time_t ti; - struct tm *tm; - char buf2[32]; - - str = RTSP_STATUS_CODE2STRING(error_number); - if (!str) - str = "Unknown Error"; - - avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str); - avio_printf(c->pb, "CSeq: %d\r\n", c->seq); - - /* output GMT time */ - ti = time(NULL); - tm = gmtime(&ti); - strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm); - avio_printf(c->pb, "Date: %s GMT\r\n", buf2); -} - -static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number) -{ - rtsp_reply_header(c, error_number); - avio_printf(c->pb, "\r\n"); -} - -static int rtsp_parse_request(HTTPContext *c) -{ - const char *p, *p1, *p2; - char cmd[32]; - char url[1024]; - char protocol[32]; - char line[1024]; - int len; - RTSPMessageHeader header1 = { 0 }, *header = &header1; - - c->buffer_ptr[0] = '\0'; - p = c->buffer; - - get_word(cmd, sizeof(cmd), &p); - get_word(url, sizeof(url), &p); - get_word(protocol, sizeof(protocol), &p); - - av_strlcpy(c->method, cmd, sizeof(c->method)); - av_strlcpy(c->url, url, sizeof(c->url)); - av_strlcpy(c->protocol, protocol, sizeof(c->protocol)); - - if (avio_open_dyn_buf(&c->pb) < 0) { - /* XXX: cannot do more */ - c->pb = NULL; /* safety */ - return -1; - } - - /* check version name */ - if (strcmp(protocol, "RTSP/1.0")) { - rtsp_reply_error(c, RTSP_STATUS_VERSION); - goto the_end; - } - - /* parse each header line */ - /* skip to next line */ - while (*p != '\n' && *p != '\0') - p++; - if (*p == '\n') - p++; - while (*p != '\0') { - p1 = memchr(p, '\n', (char *)c->buffer_ptr - p); - if (!p1) - break; - p2 = p1; - if (p2 > p && p2[-1] == '\r') - p2--; - /* skip empty line */ - if (p2 == p) - break; - len = p2 - p; - if (len > sizeof(line) - 1) - len = sizeof(line) - 1; - memcpy(line, p, len); - line[len] = '\0'; - ff_rtsp_parse_line(NULL, header, line, NULL, NULL); - p = p1 + 1; - } - - /* handle sequence number */ - c->seq = header->seq; - - if (!strcmp(cmd, "DESCRIBE")) - rtsp_cmd_describe(c, url); - else if (!strcmp(cmd, "OPTIONS")) - rtsp_cmd_options(c, url); - else if (!strcmp(cmd, "SETUP")) - rtsp_cmd_setup(c, url, header); - else if (!strcmp(cmd, "PLAY")) - rtsp_cmd_play(c, url, header); - else if (!strcmp(cmd, "PAUSE")) - rtsp_cmd_interrupt(c, url, header, 1); - else if (!strcmp(cmd, "TEARDOWN")) - rtsp_cmd_interrupt(c, url, header, 0); - else - rtsp_reply_error(c, RTSP_STATUS_METHOD); - - the_end: - len = avio_close_dyn_buf(c->pb, &c->pb_buffer); - c->pb = NULL; /* safety */ - if (len < 0) - /* XXX: cannot do more */ - return -1; - - c->buffer_ptr = c->pb_buffer; - c->buffer_end = c->pb_buffer + len; - c->state = RTSPSTATE_SEND_REPLY; - return 0; -} - -static int prepare_sdp_description(FFServerStream *stream, uint8_t **pbuffer, - struct in_addr my_ip) -{ - AVFormatContext *avc; - AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL); - AVDictionaryEntry *entry = av_dict_get(stream->metadata, "title", NULL, 0); - int i; - - *pbuffer = NULL; - - avc = avformat_alloc_context(); - if (!avc || !rtp_format) - return -1; - - avc->oformat = rtp_format; - av_dict_set(&avc->metadata, "title", - entry ? entry->value : "No Title", 0); - if (stream->is_multicast) { - snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d", - inet_ntoa(stream->multicast_ip), - stream->multicast_port, stream->multicast_ttl); - } else - snprintf(avc->filename, 1024, "rtp://0.0.0.0"); - - for(i = 0; i < stream->nb_streams; i++) { - AVStream *st = avformat_new_stream(avc, NULL); - if (!st) - goto sdp_done; - avcodec_parameters_from_context(stream->streams[i]->codecpar, stream->streams[i]->codec); - unlayer_stream(st, stream->streams[i]); - } -#define PBUFFER_SIZE 2048 - *pbuffer = av_mallocz(PBUFFER_SIZE); - if (!*pbuffer) - goto sdp_done; - av_sdp_create(&avc, 1, *pbuffer, PBUFFER_SIZE); - - sdp_done: - av_freep(&avc->streams); - av_dict_free(&avc->metadata); - av_free(avc); - - return *pbuffer ? strlen(*pbuffer) : AVERROR(ENOMEM); -} - -static void rtsp_cmd_options(HTTPContext *c, const char *url) -{ - /* rtsp_reply_header(c, RTSP_STATUS_OK); */ - avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK"); - avio_printf(c->pb, "CSeq: %d\r\n", c->seq); - avio_printf(c->pb, "Public: %s\r\n", - "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE"); - avio_printf(c->pb, "\r\n"); -} - -static void rtsp_cmd_describe(HTTPContext *c, const char *url) -{ - FFServerStream *stream; - char path1[1024]; - const char *path; - uint8_t *content; - int content_length; - socklen_t len; - struct sockaddr_in my_addr; - - /* find which URL is asked */ - av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); - path = path1; - if (*path == '/') - path++; - - for(stream = config.first_stream; stream; stream = stream->next) { - if (!stream->is_feed && - stream->fmt && !strcmp(stream->fmt->name, "rtp") && - !strcmp(path, stream->filename)) { - goto found; - } - } - /* no stream found */ - rtsp_reply_error(c, RTSP_STATUS_NOT_FOUND); - return; - - found: - /* prepare the media description in SDP format */ - - /* get the host IP */ - len = sizeof(my_addr); - getsockname(c->fd, (struct sockaddr *)&my_addr, &len); - content_length = prepare_sdp_description(stream, &content, - my_addr.sin_addr); - if (content_length < 0) { - rtsp_reply_error(c, RTSP_STATUS_INTERNAL); - return; - } - rtsp_reply_header(c, RTSP_STATUS_OK); - avio_printf(c->pb, "Content-Base: %s/\r\n", url); - avio_printf(c->pb, "Content-Type: application/sdp\r\n"); - avio_printf(c->pb, "Content-Length: %d\r\n", content_length); - avio_printf(c->pb, "\r\n"); - avio_write(c->pb, content, content_length); - av_free(content); -} - -static HTTPContext *find_rtp_session(const char *session_id) -{ - HTTPContext *c; - - if (session_id[0] == '\0') - return NULL; - - for(c = first_http_ctx; c; c = c->next) { - if (!strcmp(c->session_id, session_id)) - return c; - } - return NULL; -} - -static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport) -{ - RTSPTransportField *th; - int i; - - for(i=0;inb_transports;i++) { - th = &h->transports[i]; - if (th->lower_transport == lower_transport) - return th; - } - return NULL; -} - -static void rtsp_cmd_setup(HTTPContext *c, const char *url, - RTSPMessageHeader *h) -{ - FFServerStream *stream; - int stream_index, rtp_port, rtcp_port; - char buf[1024]; - char path1[1024]; - const char *path; - HTTPContext *rtp_c; - RTSPTransportField *th; - struct sockaddr_in dest_addr; - RTSPActionServerSetup setup; - - /* find which URL is asked */ - av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); - path = path1; - if (*path == '/') - path++; - - /* now check each stream */ - for(stream = config.first_stream; stream; stream = stream->next) { - if (stream->is_feed || !stream->fmt || - strcmp(stream->fmt->name, "rtp")) { - continue; - } - /* accept aggregate filenames only if single stream */ - if (!strcmp(path, stream->filename)) { - if (stream->nb_streams != 1) { - rtsp_reply_error(c, RTSP_STATUS_AGGREGATE); - return; - } - stream_index = 0; - goto found; - } - - for(stream_index = 0; stream_index < stream->nb_streams; - stream_index++) { - snprintf(buf, sizeof(buf), "%s/streamid=%d", - stream->filename, stream_index); - if (!strcmp(path, buf)) - goto found; - } - } - /* no stream found */ - rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */ - return; - found: - - /* generate session id if needed */ - if (h->session_id[0] == '\0') { - unsigned random0 = av_lfg_get(&random_state); - unsigned random1 = av_lfg_get(&random_state); - snprintf(h->session_id, sizeof(h->session_id), "%08x%08x", - random0, random1); - } - - /* find RTP session, and create it if none found */ - rtp_c = find_rtp_session(h->session_id); - if (!rtp_c) { - /* always prefer UDP */ - th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP); - if (!th) { - th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP); - if (!th) { - rtsp_reply_error(c, RTSP_STATUS_TRANSPORT); - return; - } - } - - rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id, - th->lower_transport); - if (!rtp_c) { - rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH); - return; - } - - /* open input stream */ - if (open_input_stream(rtp_c, "") < 0) { - rtsp_reply_error(c, RTSP_STATUS_INTERNAL); - return; - } - } - - /* test if stream is OK (test needed because several SETUP needs - * to be done for a given file) */ - if (rtp_c->stream != stream) { - rtsp_reply_error(c, RTSP_STATUS_SERVICE); - return; - } - - /* test if stream is already set up */ - if (rtp_c->rtp_ctx[stream_index]) { - rtsp_reply_error(c, RTSP_STATUS_STATE); - return; - } - - /* check transport */ - th = find_transport(h, rtp_c->rtp_protocol); - if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP && - th->client_port_min <= 0)) { - rtsp_reply_error(c, RTSP_STATUS_TRANSPORT); - return; - } - - /* setup default options */ - setup.transport_option[0] = '\0'; - dest_addr = rtp_c->from_addr; - dest_addr.sin_port = htons(th->client_port_min); - - /* setup stream */ - if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) { - rtsp_reply_error(c, RTSP_STATUS_TRANSPORT); - return; - } - - /* now everything is OK, so we can send the connection parameters */ - rtsp_reply_header(c, RTSP_STATUS_OK); - /* session ID */ - avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id); - - switch(rtp_c->rtp_protocol) { - case RTSP_LOWER_TRANSPORT_UDP: - rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]); - rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]); - avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;" - "client_port=%d-%d;server_port=%d-%d", - th->client_port_min, th->client_port_max, - rtp_port, rtcp_port); - break; - case RTSP_LOWER_TRANSPORT_TCP: - avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d", - stream_index * 2, stream_index * 2 + 1); - break; - default: - break; - } - if (setup.transport_option[0] != '\0') - avio_printf(c->pb, ";%s", setup.transport_option); - avio_printf(c->pb, "\r\n"); - - - avio_printf(c->pb, "\r\n"); -} - - -/** - * find an RTP connection by using the session ID. Check consistency - * with filename - */ -static HTTPContext *find_rtp_session_with_url(const char *url, - const char *session_id) -{ - HTTPContext *rtp_c; - char path1[1024]; - const char *path; - char buf[1024]; - int s, len; - - rtp_c = find_rtp_session(session_id); - if (!rtp_c) - return NULL; - - /* find which URL is asked */ - av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); - path = path1; - if (*path == '/') - path++; - if(!strcmp(path, rtp_c->stream->filename)) return rtp_c; - for(s=0; sstream->nb_streams; ++s) { - snprintf(buf, sizeof(buf), "%s/streamid=%d", - rtp_c->stream->filename, s); - if(!strncmp(path, buf, sizeof(buf))) - /* XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE - * if nb_streams>1? */ - return rtp_c; - } - len = strlen(path); - if (len > 0 && path[len - 1] == '/' && - !strncmp(path, rtp_c->stream->filename, len - 1)) - return rtp_c; - return NULL; -} - -static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h) -{ - HTTPContext *rtp_c; - - rtp_c = find_rtp_session_with_url(url, h->session_id); - if (!rtp_c) { - rtsp_reply_error(c, RTSP_STATUS_SESSION); - return; - } - - if (rtp_c->state != HTTPSTATE_SEND_DATA && - rtp_c->state != HTTPSTATE_WAIT_FEED && - rtp_c->state != HTTPSTATE_READY) { - rtsp_reply_error(c, RTSP_STATUS_STATE); - return; - } - - rtp_c->state = HTTPSTATE_SEND_DATA; - - /* now everything is OK, so we can send the connection parameters */ - rtsp_reply_header(c, RTSP_STATUS_OK); - /* session ID */ - avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id); - avio_printf(c->pb, "\r\n"); -} - -static void rtsp_cmd_interrupt(HTTPContext *c, const char *url, - RTSPMessageHeader *h, int pause_only) -{ - HTTPContext *rtp_c; - - rtp_c = find_rtp_session_with_url(url, h->session_id); - if (!rtp_c) { - rtsp_reply_error(c, RTSP_STATUS_SESSION); - return; - } - - if (pause_only) { - if (rtp_c->state != HTTPSTATE_SEND_DATA && - rtp_c->state != HTTPSTATE_WAIT_FEED) { - rtsp_reply_error(c, RTSP_STATUS_STATE); - return; - } - rtp_c->state = HTTPSTATE_READY; - rtp_c->first_pts = AV_NOPTS_VALUE; - } - - /* now everything is OK, so we can send the connection parameters */ - rtsp_reply_header(c, RTSP_STATUS_OK); - /* session ID */ - avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id); - avio_printf(c->pb, "\r\n"); - - if (!pause_only) - close_connection(rtp_c); -} - -/********************************************************************/ -/* RTP handling */ - -static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr, - FFServerStream *stream, - const char *session_id, - enum RTSPLowerTransport rtp_protocol) -{ - HTTPContext *c = NULL; - const char *proto_str; - - /* XXX: should output a warning page when coming - * close to the connection limit */ - if (nb_connections >= config.nb_max_connections) - goto fail; - - /* add a new connection */ - c = av_mallocz(sizeof(HTTPContext)); - if (!c) - goto fail; - - c->fd = -1; - c->poll_entry = NULL; - c->from_addr = *from_addr; - c->buffer_size = IOBUFFER_INIT_SIZE; - c->buffer = av_malloc(c->buffer_size); - if (!c->buffer) - goto fail; - nb_connections++; - c->stream = stream; - av_strlcpy(c->session_id, session_id, sizeof(c->session_id)); - c->state = HTTPSTATE_READY; - c->is_packetized = 1; - c->rtp_protocol = rtp_protocol; - - /* protocol is shown in statistics */ - switch(c->rtp_protocol) { - case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: - proto_str = "MCAST"; - break; - case RTSP_LOWER_TRANSPORT_UDP: - proto_str = "UDP"; - break; - case RTSP_LOWER_TRANSPORT_TCP: - proto_str = "TCP"; - break; - default: - proto_str = "???"; - break; - } - av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol)); - av_strlcat(c->protocol, proto_str, sizeof(c->protocol)); - - current_bandwidth += stream->bandwidth; - - c->next = first_http_ctx; - first_http_ctx = c; - return c; - - fail: - if (c) { - av_freep(&c->buffer); - av_free(c); - } - return NULL; -} - -/** - * add a new RTP stream in an RTP connection (used in RTSP SETUP - * command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is - * used. - */ -static int rtp_new_av_stream(HTTPContext *c, - int stream_index, struct sockaddr_in *dest_addr, - HTTPContext *rtsp_c) -{ - AVFormatContext *ctx; - AVStream *st; - char *ipaddr; - URLContext *h = NULL; - uint8_t *dummy_buf; - int max_packet_size; - void *st_internal; - - /* now we can open the relevant output stream */ - ctx = avformat_alloc_context(); - if (!ctx) - return -1; - ctx->oformat = av_guess_format("rtp", NULL, NULL); - - st = avformat_new_stream(ctx, NULL); - if (!st) - goto fail; - - st_internal = st->internal; - - if (!c->stream->feed || - c->stream->feed == c->stream) - unlayer_stream(st, c->stream->streams[stream_index]); - else - unlayer_stream(st, - c->stream->feed->streams[c->stream->feed_streams[stream_index]]); - av_assert0(st->priv_data == NULL); - av_assert0(st->internal == st_internal); - - /* build destination RTP address */ - ipaddr = inet_ntoa(dest_addr->sin_addr); - - switch(c->rtp_protocol) { - case RTSP_LOWER_TRANSPORT_UDP: - case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: - /* RTP/UDP case */ - - /* XXX: also pass as parameter to function ? */ - if (c->stream->is_multicast) { - int ttl; - ttl = c->stream->multicast_ttl; - if (!ttl) - ttl = 16; - snprintf(ctx->filename, sizeof(ctx->filename), - "rtp://%s:%d?multicast=1&ttl=%d", - ipaddr, ntohs(dest_addr->sin_port), ttl); - } else { - snprintf(ctx->filename, sizeof(ctx->filename), - "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port)); - } - - if (ffurl_open(&h, ctx->filename, AVIO_FLAG_WRITE, NULL, NULL) < 0) - goto fail; - c->rtp_handles[stream_index] = h; - max_packet_size = h->max_packet_size; - break; - case RTSP_LOWER_TRANSPORT_TCP: - /* RTP/TCP case */ - c->rtsp_c = rtsp_c; - max_packet_size = RTSP_TCP_MAX_PACKET_SIZE; - break; - default: - goto fail; - } - - http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n", - ipaddr, ntohs(dest_addr->sin_port), - c->stream->filename, stream_index, c->protocol); - - /* normally, no packets should be output here, but the packet size may - * be checked */ - if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) - /* XXX: close stream */ - goto fail; - - if (avformat_write_header(ctx, NULL) < 0) { - fail: - if (h) - ffurl_close(h); - av_free(st); - av_free(ctx); - return -1; - } - avio_close_dyn_buf(ctx->pb, &dummy_buf); - ctx->pb = NULL; - av_free(dummy_buf); - - c->rtp_ctx[stream_index] = ctx; - return 0; -} - -/********************************************************************/ -/* ffserver initialization */ - -/* FIXME: This code should use avformat_new_stream() */ -static LayeredAVStream *add_av_stream1(FFServerStream *stream, - AVCodecContext *codec, int copy) -{ - LayeredAVStream *fst; - - if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams)) - return NULL; - - fst = av_mallocz(sizeof(*fst)); - if (!fst) - return NULL; - if (copy) { - fst->codec = avcodec_alloc_context3(codec->codec); - if (!fst->codec) { - av_free(fst); - return NULL; - } - avcodec_copy_context(fst->codec, codec); - } else - /* live streams must use the actual feed's codec since it may be - * updated later to carry extradata needed by them. - */ - fst->codec = codec; - - //NOTE we previously allocated internal & internal->avctx, these seemed uneeded though - fst->codecpar = avcodec_parameters_alloc(); - fst->index = stream->nb_streams; - fst->time_base = codec->time_base; - fst->pts_wrap_bits = 33; - fst->sample_aspect_ratio = codec->sample_aspect_ratio; - stream->streams[stream->nb_streams++] = fst; - return fst; -} - -/* return the stream number in the feed */ -static int add_av_stream(FFServerStream *feed, LayeredAVStream *st) -{ - LayeredAVStream *fst; - AVCodecContext *av, *av1; - int i; - - av = st->codec; - for(i=0;inb_streams;i++) { - av1 = feed->streams[i]->codec; - if (av1->codec_id == av->codec_id && - av1->codec_type == av->codec_type && - av1->bit_rate == av->bit_rate) { - - switch(av->codec_type) { - case AVMEDIA_TYPE_AUDIO: - if (av1->channels == av->channels && - av1->sample_rate == av->sample_rate) - return i; - break; - case AVMEDIA_TYPE_VIDEO: - if (av1->width == av->width && - av1->height == av->height && - av1->time_base.den == av->time_base.den && - av1->time_base.num == av->time_base.num && - av1->gop_size == av->gop_size) - return i; - break; - default: - abort(); - } - } - } - - fst = add_av_stream1(feed, av, 0); - if (!fst) - return -1; - if (st->recommended_encoder_configuration) - fst->recommended_encoder_configuration = - av_strdup(st->recommended_encoder_configuration); - return feed->nb_streams - 1; -} - -static void remove_stream(FFServerStream *stream) -{ - FFServerStream **ps; - ps = &config.first_stream; - while (*ps) { - if (*ps == stream) - *ps = (*ps)->next; - else - ps = &(*ps)->next; - } -} - -/* compute the needed AVStream for each file */ -static void build_file_streams(void) -{ - FFServerStream *stream; - AVFormatContext *infile; - int i, ret; - - /* gather all streams */ - for(stream = config.first_stream; stream; stream = stream->next) { - infile = NULL; - - if (stream->stream_type != STREAM_TYPE_LIVE || stream->feed) - continue; - - /* the stream comes from a file */ - /* try to open the file */ - /* open stream */ - - - /* specific case: if transport stream output to RTP, - * we use a raw transport stream reader */ - if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) - av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0); - - if (!stream->feed_filename[0]) { - http_log("Unspecified feed file for stream '%s'\n", - stream->filename); - goto fail; - } - - http_log("Opening feed file '%s' for stream '%s'\n", - stream->feed_filename, stream->filename); - - ret = avformat_open_input(&infile, stream->feed_filename, - stream->ifmt, &stream->in_opts); - if (ret < 0) { - http_log("Could not open '%s': %s\n", stream->feed_filename, - av_err2str(ret)); - /* remove stream (no need to spend more time on it) */ - fail: - remove_stream(stream); - } else { - /* find all the AVStreams inside and reference them in - * 'stream' */ - if (avformat_find_stream_info(infile, NULL) < 0) { - http_log("Could not find codec parameters from '%s'\n", - stream->feed_filename); - avformat_close_input(&infile); - goto fail; - } - - for(i=0;inb_streams;i++) - add_av_stream1(stream, infile->streams[i]->codec, 1); - - avformat_close_input(&infile); - } - } -} - -static inline -int check_codec_match(LayeredAVStream *ccf, AVStream *ccs, int stream) -{ - int matches = 1; - -/* FIXME: Missed check on AVCodecContext.flags */ -#define CHECK_CODEC(x) (ccf->codecpar->x != ccs->codecpar->x) - if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) { - http_log("Codecs do not match for stream %d\n", stream); - matches = 0; - } else if (CHECK_CODEC(bit_rate)) { - http_log("Codec bitrates do not match for stream %d\n", stream); - matches = 0; - } else if (ccf->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - if (av_cmp_q(ccf->time_base, ccs->time_base) || - CHECK_CODEC(width) || CHECK_CODEC(height)) { - http_log("Codec width, height or framerate do not match for stream %d\n", stream); - matches = 0; - } - } else if (ccf->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - if (CHECK_CODEC(sample_rate) || - CHECK_CODEC(channels) || - CHECK_CODEC(frame_size)) { - http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", stream); - matches = 0; - } - } else { - http_log("Unknown codec type for stream %d\n", stream); - matches = 0; - } - - return matches; -} - -/* compute the needed AVStream for each feed */ -static int build_feed_streams(void) -{ - FFServerStream *stream, *feed; - int i, fd; - - /* gather all streams */ - for(stream = config.first_stream; stream; stream = stream->next) { - feed = stream->feed; - if (!feed) - continue; - - if (stream->is_feed) { - for(i=0;inb_streams;i++) - stream->feed_streams[i] = i; - continue; - } - /* we handle a stream coming from a feed */ - for(i=0;inb_streams;i++) - stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]); - } - - /* create feed files if needed */ - for(feed = config.first_feed; feed; feed = feed->next_feed) { - - if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) { - AVFormatContext *s = NULL; - int matches = 0; - - /* See if it matches */ - - if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) < 0) { - http_log("Deleting feed file '%s' as it appears " - "to be corrupt\n", - feed->feed_filename); - goto drop; - } - - /* set buffer size */ - if (ffio_set_buf_size(s->pb, FFM_PACKET_SIZE) < 0) { - http_log("Failed to set buffer size\n"); - avformat_close_input(&s); - goto bail; - } - - /* Now see if it matches */ - if (s->nb_streams != feed->nb_streams) { - http_log("Deleting feed file '%s' as stream counts " - "differ (%d != %d)\n", - feed->feed_filename, s->nb_streams, feed->nb_streams); - goto drop; - } - - matches = 1; - for(i=0;inb_streams;i++) { - AVStream *ss; - LayeredAVStream *sf; - - sf = feed->streams[i]; - ss = s->streams[i]; - - if (sf->index != ss->index || sf->id != ss->id) { - http_log("Index & Id do not match for stream %d (%s)\n", - i, feed->feed_filename); - matches = 0; - break; - } - - matches = check_codec_match (sf, ss, i); - if (!matches) - break; - } - -drop: - if (s) - avformat_close_input(&s); - - if (!matches) { - if (feed->readonly) { - http_log("Unable to delete read-only feed file '%s'\n", - feed->feed_filename); - goto bail; - } - unlink(feed->feed_filename); - } - } - - if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) { - AVFormatContext *s = avformat_alloc_context(); - - if (!s) { - http_log("Failed to allocate context\n"); - goto bail; - } - - if (feed->readonly) { - http_log("Unable to create feed file '%s' as it is " - "marked readonly\n", - feed->feed_filename); - avformat_free_context(s); - goto bail; - } - - /* only write the header of the ffm file */ - if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) { - http_log("Could not open output feed file '%s'\n", - feed->feed_filename); - avformat_free_context(s); - goto bail; - } - s->oformat = feed->fmt; - for (i = 0; inb_streams; i++) { - AVStream *st = avformat_new_stream(s, NULL); // FIXME free this - if (!st) { - http_log("Failed to allocate stream\n"); - goto bail; - } - unlayer_stream(st, feed->streams[i]); - } - if (avformat_write_header(s, NULL) < 0) { - http_log("Container doesn't support the required parameters\n"); - avio_closep(&s->pb); - s->streams = NULL; - s->nb_streams = 0; - avformat_free_context(s); - goto bail; - } - /* XXX: need better API */ - av_freep(&s->priv_data); - avio_closep(&s->pb); - s->streams = NULL; - s->nb_streams = 0; - avformat_free_context(s); - } - - /* get feed size and write index */ - fd = open(feed->feed_filename, O_RDONLY); - if (fd < 0) { - http_log("Could not open output feed file '%s'\n", - feed->feed_filename); - goto bail; - } - - feed->feed_write_index = FFMAX(ffm_read_write_index(fd), - FFM_PACKET_SIZE); - feed->feed_size = lseek(fd, 0, SEEK_END); - /* ensure that we do not wrap before the end of file */ - if (feed->feed_max_size && feed->feed_max_size < feed->feed_size) - feed->feed_max_size = feed->feed_size; - - close(fd); - } - return 0; - -bail: - return -1; -} - -/* compute the bandwidth used by each stream */ -static void compute_bandwidth(void) -{ - unsigned bandwidth; - int i; - FFServerStream *stream; - - for(stream = config.first_stream; stream; stream = stream->next) { - bandwidth = 0; - for(i=0;inb_streams;i++) { - LayeredAVStream *st = stream->streams[i]; - switch(st->codec->codec_type) { - case AVMEDIA_TYPE_AUDIO: - case AVMEDIA_TYPE_VIDEO: - bandwidth += st->codec->bit_rate; - break; - default: - break; - } - } - stream->bandwidth = (bandwidth + 999) / 1000; - } -} - -static void handle_child_exit(int sig) -{ - pid_t pid; - int status; - time_t uptime; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { - FFServerStream *feed; - - for (feed = config.first_feed; feed; feed = feed->next) { - if (feed->pid != pid) - continue; - - uptime = time(0) - feed->pid_start; - feed->pid = 0; - fprintf(stderr, - "%s: Pid %"PRId64" exited with status %d after %"PRId64" " - "seconds\n", - feed->filename, (int64_t) pid, status, (int64_t)uptime); - - if (uptime < 30) - /* Turn off any more restarts */ - ffserver_free_child_args(&feed->child_argv); - } - } - - need_to_start_children = 1; -} - -static void opt_debug(void) -{ - config.debug = 1; - snprintf(config.logfilename, sizeof(config.logfilename), "-"); -} - -void show_help_default(const char *opt, const char *arg) -{ - printf("usage: ffserver [options]\n" - "Hyper fast multi format Audio/Video streaming server\n"); - printf("\n"); - show_help_options(options, "Main options:", 0, 0, 0); -} - -static const OptionDef options[] = { - CMDUTILS_COMMON_OPTIONS - { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" }, - { "d", 0, {(void*)opt_debug}, "enable debug mode" }, - { "f", HAS_ARG | OPT_STRING, {(void*)&config.filename }, "use configfile instead of /etc/ffserver.conf", "configfile" }, - { NULL }, -}; - -int main(int argc, char **argv) -{ - struct sigaction sigact = { { 0 } }; - int cfg_parsed; - int ret = EXIT_FAILURE; - - init_dynload(); - - config.filename = av_strdup("/etc/ffserver.conf"); - - parse_loglevel(argc, argv, options); - av_register_all(); - avformat_network_init(); - - show_banner(argc, argv, options); - - my_program_name = argv[0]; - - parse_options(NULL, argc, argv, options, NULL); - - unsetenv("http_proxy"); /* Kill the http_proxy */ - - av_lfg_init(&random_state, av_get_random_seed()); - - sigact.sa_handler = handle_child_exit; - sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART; - sigaction(SIGCHLD, &sigact, 0); - - if ((cfg_parsed = ffserver_parse_ffconfig(config.filename, &config)) < 0) { - fprintf(stderr, "Error reading configuration file '%s': %s\n", - config.filename, av_err2str(cfg_parsed)); - goto bail; - } - - /* open log file if needed */ - if (config.logfilename[0] != '\0') { - if (!strcmp(config.logfilename, "-")) - logfile = stdout; - else - logfile = fopen(config.logfilename, "a"); - av_log_set_callback(http_av_log); - } - - build_file_streams(); - - if (build_feed_streams() < 0) { - http_log("Could not setup feed streams\n"); - goto bail; - } - - compute_bandwidth(); - - /* signal init */ - signal(SIGPIPE, SIG_IGN); - - if (http_server() < 0) { - http_log("Could not start server\n"); - goto bail; - } - - ret=EXIT_SUCCESS; - -bail: - av_freep (&config.filename); - avformat_network_deinit(); - return ret; -} diff --git a/fftools/ffserver_config.c b/fftools/ffserver_config.c deleted file mode 100644 index 71b50106beb8c..0000000000000 --- a/fftools/ffserver_config.c +++ /dev/null @@ -1,1323 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002 Fabrice Bellard - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include "libavutil/opt.h" -#include "libavutil/parseutils.h" -#include "libavutil/avstring.h" -#include "libavutil/pixdesc.h" -#include "libavutil/avassert.h" - -#include "cmdutils.h" -#include "ffserver_config.h" - -#define MAX_CHILD_ARGS 64 - -static int ffserver_save_avoption(const char *opt, const char *arg, int type, - FFServerConfig *config); -static void vreport_config_error(const char *filename, int line_num, - int log_level, int *errors, const char *fmt, - va_list vl); -static void report_config_error(const char *filename, int line_num, - int log_level, int *errors, const char *fmt, - ...); - -#define ERROR(...) report_config_error(config->filename, config->line_num,\ - AV_LOG_ERROR, &config->errors, __VA_ARGS__) -#define WARNING(...) report_config_error(config->filename, config->line_num,\ - AV_LOG_WARNING, &config->warnings, __VA_ARGS__) - -/* FIXME: make ffserver work with IPv6 */ -/* resolve host with also IP address parsing */ -static int resolve_host(struct in_addr *sin_addr, const char *hostname) -{ - - if (!ff_inet_aton(hostname, sin_addr)) { -#if HAVE_GETADDRINFO - struct addrinfo *ai, *cur; - struct addrinfo hints = { 0 }; - hints.ai_family = AF_INET; - if (getaddrinfo(hostname, NULL, &hints, &ai)) - return -1; - /* getaddrinfo returns a linked list of addrinfo structs. - * Even if we set ai_family = AF_INET above, make sure - * that the returned one actually is of the correct type. */ - for (cur = ai; cur; cur = cur->ai_next) { - if (cur->ai_family == AF_INET) { - *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr; - freeaddrinfo(ai); - return 0; - } - } - freeaddrinfo(ai); - return -1; -#else - struct hostent *hp; - hp = gethostbyname(hostname); - if (!hp) - return -1; - memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr)); -#endif - } - return 0; -} - -void ffserver_get_arg(char *buf, int buf_size, const char **pp) -{ - const char *p; - char *q; - int quote = 0; - - p = *pp; - q = buf; - - while (av_isspace(*p)) p++; - - if (*p == '\"' || *p == '\'') - quote = *p++; - - while (*p != '\0') { - if (quote && *p == quote || !quote && av_isspace(*p)) - break; - if ((q - buf) < buf_size - 1) - *q++ = *p; - p++; - } - - *q = '\0'; - if (quote && *p == quote) - p++; - *pp = p; -} - -void ffserver_parse_acl_row(FFServerStream *stream, FFServerStream* feed, - FFServerIPAddressACL *ext_acl, - const char *p, const char *filename, int line_num) -{ - char arg[1024]; - FFServerIPAddressACL acl; - FFServerIPAddressACL *nacl; - FFServerIPAddressACL **naclp; - - ffserver_get_arg(arg, sizeof(arg), &p); - if (av_strcasecmp(arg, "allow") == 0) - acl.action = IP_ALLOW; - else if (av_strcasecmp(arg, "deny") == 0) - acl.action = IP_DENY; - else { - fprintf(stderr, "%s:%d: ACL action '%s' should be ALLOW or DENY.\n", - filename, line_num, arg); - goto bail; - } - - ffserver_get_arg(arg, sizeof(arg), &p); - - if (resolve_host(&acl.first, arg)) { - fprintf(stderr, - "%s:%d: ACL refers to invalid host or IP address '%s'\n", - filename, line_num, arg); - goto bail; - } - - acl.last = acl.first; - - ffserver_get_arg(arg, sizeof(arg), &p); - - if (arg[0]) { - if (resolve_host(&acl.last, arg)) { - fprintf(stderr, - "%s:%d: ACL refers to invalid host or IP address '%s'\n", - filename, line_num, arg); - goto bail; - } - } - - nacl = av_mallocz(sizeof(*nacl)); - if (!nacl) { - fprintf(stderr, "Failed to allocate FFServerIPAddressACL\n"); - goto bail; - } - - naclp = 0; - - acl.next = 0; - *nacl = acl; - - if (stream) - naclp = &stream->acl; - else if (feed) - naclp = &feed->acl; - else if (ext_acl) - naclp = &ext_acl; - else - fprintf(stderr, "%s:%d: ACL found not in or \n", - filename, line_num); - - if (naclp) { - while (*naclp) - naclp = &(*naclp)->next; - - *naclp = nacl; - } else - av_free(nacl); - -bail: - return; - -} - -/* add a codec and set the default parameters */ -static void add_codec(FFServerStream *stream, AVCodecContext *av, - FFServerConfig *config) -{ - LayeredAVStream *st; - AVDictionary **opts, *recommended = NULL; - char *enc_config; - - if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams)) - return; - - opts = av->codec_type == AVMEDIA_TYPE_AUDIO ? - &config->audio_opts : &config->video_opts; - av_dict_copy(&recommended, *opts, 0); - av_opt_set_dict2(av->priv_data, opts, AV_OPT_SEARCH_CHILDREN); - av_opt_set_dict2(av, opts, AV_OPT_SEARCH_CHILDREN); - - if (av_dict_count(*opts)) - av_log(NULL, AV_LOG_WARNING, - "Something is wrong, %d options are not set!\n", - av_dict_count(*opts)); - - if (!config->stream_use_defaults) { - switch(av->codec_type) { - case AVMEDIA_TYPE_AUDIO: - if (av->bit_rate == 0) - report_config_error(config->filename, config->line_num, - AV_LOG_ERROR, &config->errors, - "audio bit rate is not set\n"); - if (av->sample_rate == 0) - report_config_error(config->filename, config->line_num, - AV_LOG_ERROR, &config->errors, - "audio sample rate is not set\n"); - break; - case AVMEDIA_TYPE_VIDEO: - if (av->width == 0 || av->height == 0) - report_config_error(config->filename, config->line_num, - AV_LOG_ERROR, &config->errors, - "video size is not set\n"); - break; - default: - av_assert0(0); - } - goto done; - } - - /* stream_use_defaults = true */ - - /* compute default parameters */ - switch(av->codec_type) { - case AVMEDIA_TYPE_AUDIO: - if (!av_dict_get(recommended, "b", NULL, 0)) { - av->bit_rate = 64000; - av_dict_set_int(&recommended, "b", av->bit_rate, 0); - WARNING("Setting default value for audio bit rate = %d. " - "Use NoDefaults to disable it.\n", - av->bit_rate); - } - if (!av_dict_get(recommended, "ar", NULL, 0)) { - av->sample_rate = 22050; - av_dict_set_int(&recommended, "ar", av->sample_rate, 0); - WARNING("Setting default value for audio sample rate = %d. " - "Use NoDefaults to disable it.\n", - av->sample_rate); - } - if (!av_dict_get(recommended, "ac", NULL, 0)) { - av->channels = 1; - av_dict_set_int(&recommended, "ac", av->channels, 0); - WARNING("Setting default value for audio channel count = %d. " - "Use NoDefaults to disable it.\n", - av->channels); - } - break; - case AVMEDIA_TYPE_VIDEO: - if (!av_dict_get(recommended, "b", NULL, 0)) { - av->bit_rate = 64000; - av_dict_set_int(&recommended, "b", av->bit_rate, 0); - WARNING("Setting default value for video bit rate = %d. " - "Use NoDefaults to disable it.\n", - av->bit_rate); - } - if (!av_dict_get(recommended, "time_base", NULL, 0)){ - av->time_base.den = 5; - av->time_base.num = 1; - av_dict_set(&recommended, "time_base", "1/5", 0); - WARNING("Setting default value for video frame rate = %d. " - "Use NoDefaults to disable it.\n", - av->time_base.den); - } - if (!av_dict_get(recommended, "video_size", NULL, 0)) { - av->width = 160; - av->height = 128; - av_dict_set(&recommended, "video_size", "160x128", 0); - WARNING("Setting default value for video size = %dx%d. " - "Use NoDefaults to disable it.\n", - av->width, av->height); - } - /* Bitrate tolerance is less for streaming */ - if (!av_dict_get(recommended, "bt", NULL, 0)) { - av->bit_rate_tolerance = FFMAX(av->bit_rate / 4, - (int64_t)av->bit_rate*av->time_base.num/av->time_base.den); - av_dict_set_int(&recommended, "bt", av->bit_rate_tolerance, 0); - WARNING("Setting default value for video bit rate tolerance = %d. " - "Use NoDefaults to disable it.\n", - av->bit_rate_tolerance); - } - - if (!av_dict_get(recommended, "rc_eq", NULL, 0)) { - av_dict_set(&recommended, "rc_eq", "tex^qComp", 0); - WARNING("Setting default value for video rate control equation = " - "tex^qComp. Use NoDefaults to disable it.\n"); - } - if (!av_dict_get(recommended, "maxrate", NULL, 0)) { - av->rc_max_rate = av->bit_rate * 2; - av_dict_set_int(&recommended, "maxrate", av->rc_max_rate, 0); - WARNING("Setting default value for video max rate = %d. " - "Use NoDefaults to disable it.\n", - av->rc_max_rate); - } - - if (av->rc_max_rate && !av_dict_get(recommended, "bufsize", NULL, 0)) { - av->rc_buffer_size = av->rc_max_rate; - av_dict_set_int(&recommended, "bufsize", av->rc_buffer_size, 0); - WARNING("Setting default value for video buffer size = %d. " - "Use NoDefaults to disable it.\n", - av->rc_buffer_size); - } - break; - default: - abort(); - } - -done: - st = av_mallocz(sizeof(*st)); - if (!st) - return; - av_dict_get_string(recommended, &enc_config, '=', ','); - av_dict_free(&recommended); - st->recommended_encoder_configuration = enc_config; - st->codec = av; - st->codecpar = avcodec_parameters_alloc(); - avcodec_parameters_from_context(st->codecpar, av); - stream->streams[stream->nb_streams++] = st; -} - -static int ffserver_set_codec(AVCodecContext *ctx, const char *codec_name, - FFServerConfig *config) -{ - int ret; - AVCodec *codec = avcodec_find_encoder_by_name(codec_name); - if (!codec || codec->type != ctx->codec_type) { - report_config_error(config->filename, config->line_num, AV_LOG_ERROR, - &config->errors, - "Invalid codec name: '%s'\n", codec_name); - return 0; - } - if (ctx->codec_id == AV_CODEC_ID_NONE && !ctx->priv_data) { - if ((ret = avcodec_get_context_defaults3(ctx, codec)) < 0) - return ret; - ctx->codec = codec; - } - if (ctx->codec_id != codec->id) - report_config_error(config->filename, config->line_num, AV_LOG_ERROR, - &config->errors, - "Inconsistent configuration: trying to set '%s' " - "codec option, but '%s' codec is used previously\n", - codec_name, avcodec_get_name(ctx->codec_id)); - return 0; -} - -static int ffserver_opt_preset(const char *arg, int type, FFServerConfig *config) -{ - FILE *f=NULL; - char filename[1000], tmp[1000], tmp2[1000], line[1000]; - int ret = 0; - AVCodecContext *avctx; - const AVCodec *codec; - - switch(type) { - case AV_OPT_FLAG_AUDIO_PARAM: - avctx = config->dummy_actx; - break; - case AV_OPT_FLAG_VIDEO_PARAM: - avctx = config->dummy_vctx; - break; - default: - av_assert0(0); - } - codec = avcodec_find_encoder(avctx->codec_id); - - if (!(f = get_preset_file(filename, sizeof(filename), arg, 0, - codec ? codec->name : NULL))) { - av_log(NULL, AV_LOG_ERROR, "File for preset '%s' not found\n", arg); - return AVERROR(EINVAL); - } - - while(!feof(f)){ - int e= fscanf(f, "%999[^\n]\n", line) - 1; - if(line[0] == '#' && !e) - continue; - e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2; - if(e){ - av_log(NULL, AV_LOG_ERROR, "%s: Invalid syntax: '%s'\n", filename, - line); - ret = AVERROR(EINVAL); - break; - } - if (!strcmp(tmp, "acodec") && avctx->codec_type == AVMEDIA_TYPE_AUDIO || - !strcmp(tmp, "vcodec") && avctx->codec_type == AVMEDIA_TYPE_VIDEO) - { - if (ffserver_set_codec(avctx, tmp2, config) < 0) - break; - } else if (!strcmp(tmp, "scodec")) { - av_log(NULL, AV_LOG_ERROR, "Subtitles preset found.\n"); - ret = AVERROR(EINVAL); - break; - } else if (ffserver_save_avoption(tmp, tmp2, type, config) < 0) - break; - } - - fclose(f); - - return ret; -} - -static AVOutputFormat *ffserver_guess_format(const char *short_name, - const char *filename, - const char *mime_type) -{ - AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type); - - if (fmt) { - AVOutputFormat *stream_fmt; - char stream_format_name[64]; - - snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", - fmt->name); - stream_fmt = av_guess_format(stream_format_name, NULL, NULL); - - if (stream_fmt) - fmt = stream_fmt; - } - - return fmt; -} - -static void vreport_config_error(const char *filename, int line_num, - int log_level, int *errors, const char *fmt, - va_list vl) -{ - av_log(NULL, log_level, "%s:%d: ", filename, line_num); - av_vlog(NULL, log_level, fmt, vl); - if (errors) - (*errors)++; -} - -static void report_config_error(const char *filename, int line_num, - int log_level, int *errors, - const char *fmt, ...) -{ - va_list vl; - va_start(vl, fmt); - vreport_config_error(filename, line_num, log_level, errors, fmt, vl); - va_end(vl); -} - -static int ffserver_set_int_param(int *dest, const char *value, int factor, - int min, int max, FFServerConfig *config, - const char *error_msg, ...) -{ - int tmp; - char *tailp; - if (!value || !value[0]) - goto error; - errno = 0; - tmp = strtol(value, &tailp, 0); - if (tmp < min || tmp > max) - goto error; - if (factor) { - if (tmp == INT_MIN || FFABS(tmp) > INT_MAX / FFABS(factor)) - goto error; - tmp *= factor; - } - if (tailp[0] || errno) - goto error; - if (dest) - *dest = tmp; - return 0; - error: - if (config) { - va_list vl; - va_start(vl, error_msg); - vreport_config_error(config->filename, config->line_num, AV_LOG_ERROR, - &config->errors, error_msg, vl); - va_end(vl); - } - return AVERROR(EINVAL); -} - -static int ffserver_set_float_param(float *dest, const char *value, - float factor, float min, float max, - FFServerConfig *config, - const char *error_msg, ...) -{ - double tmp; - char *tailp; - if (!value || !value[0]) - goto error; - errno = 0; - tmp = strtod(value, &tailp); - if (tmp < min || tmp > max) - goto error; - if (factor) - tmp *= factor; - if (tailp[0] || errno) - goto error; - if (dest) - *dest = tmp; - return 0; - error: - if (config) { - va_list vl; - va_start(vl, error_msg); - vreport_config_error(config->filename, config->line_num, AV_LOG_ERROR, - &config->errors, error_msg, vl); - va_end(vl); - } - return AVERROR(EINVAL); -} - -static int ffserver_save_avoption(const char *opt, const char *arg, int type, - FFServerConfig *config) -{ - static int hinted = 0; - int ret = 0; - AVDictionaryEntry *e; - const AVOption *o = NULL; - const char *option = NULL; - const char *codec_name = NULL; - char buff[1024]; - AVCodecContext *ctx; - AVDictionary **dict; - enum AVCodecID guessed_codec_id; - - switch (type) { - case AV_OPT_FLAG_VIDEO_PARAM: - ctx = config->dummy_vctx; - dict = &config->video_opts; - guessed_codec_id = config->guessed_video_codec_id != AV_CODEC_ID_NONE ? - config->guessed_video_codec_id : AV_CODEC_ID_H264; - break; - case AV_OPT_FLAG_AUDIO_PARAM: - ctx = config->dummy_actx; - dict = &config->audio_opts; - guessed_codec_id = config->guessed_audio_codec_id != AV_CODEC_ID_NONE ? - config->guessed_audio_codec_id : AV_CODEC_ID_AAC; - break; - default: - av_assert0(0); - } - - if (strchr(opt, ':')) { - //explicit private option - snprintf(buff, sizeof(buff), "%s", opt); - codec_name = buff; - if(!(option = strchr(buff, ':'))){ - report_config_error(config->filename, config->line_num, - AV_LOG_ERROR, &config->errors, - "Syntax error. Unmatched ':'\n"); - return -1; - - } - buff[option - buff] = '\0'; - option++; - if ((ret = ffserver_set_codec(ctx, codec_name, config)) < 0) - return ret; - if (!ctx->codec || !ctx->priv_data) - return -1; - } else { - option = opt; - } - - o = av_opt_find(ctx, option, NULL, type | AV_OPT_FLAG_ENCODING_PARAM, - AV_OPT_SEARCH_CHILDREN); - if (!o && - (!strcmp(option, "time_base") || !strcmp(option, "pixel_format") || - !strcmp(option, "video_size") || !strcmp(option, "codec_tag"))) - o = av_opt_find(ctx, option, NULL, 0, 0); - if (!o) { - report_config_error(config->filename, config->line_num, AV_LOG_ERROR, - &config->errors, "Option not found: '%s'\n", opt); - if (!hinted && ctx->codec_id == AV_CODEC_ID_NONE) { - hinted = 1; - report_config_error(config->filename, config->line_num, - AV_LOG_ERROR, NULL, "If '%s' is a codec private" - "option, then prefix it with codec name, for " - "example '%s:%s %s' or define codec earlier.\n", - opt, avcodec_get_name(guessed_codec_id) ,opt, - arg); - } - } else if ((ret = av_opt_set(ctx, option, arg, AV_OPT_SEARCH_CHILDREN)) < 0) { - report_config_error(config->filename, config->line_num, AV_LOG_ERROR, - &config->errors, "Invalid value for option %s (%s): %s\n", opt, - arg, av_err2str(ret)); - } else if ((e = av_dict_get(*dict, option, NULL, 0))) { - if ((o->type == AV_OPT_TYPE_FLAGS) && arg && - (arg[0] == '+' || arg[0] == '-')) - return av_dict_set(dict, option, arg, AV_DICT_APPEND); - report_config_error(config->filename, config->line_num, AV_LOG_ERROR, - &config->errors, "Redeclaring value of option '%s'." - "Previous value was: '%s'.\n", opt, e->value); - } else if (av_dict_set(dict, option, arg, 0) < 0) { - return AVERROR(ENOMEM); - } - return 0; -} - -static int ffserver_save_avoption_int(const char *opt, int64_t arg, - int type, FFServerConfig *config) -{ - char buf[22]; - snprintf(buf, sizeof(buf), "%"PRId64, arg); - return ffserver_save_avoption(opt, buf, type, config); -} - -static int ffserver_parse_config_global(FFServerConfig *config, const char *cmd, - const char **p) -{ - int val; - char arg[1024]; - if (!av_strcasecmp(cmd, "Port") || !av_strcasecmp(cmd, "HTTPPort")) { - if (!av_strcasecmp(cmd, "Port")) - WARNING("Port option is deprecated. Use HTTPPort instead.\n"); - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_set_int_param(&val, arg, 0, 1, 65535, config, - "Invalid port: %s\n", arg); - if (val < 1024) - WARNING("Trying to use IETF assigned system port: '%d'\n", val); - config->http_addr.sin_port = htons(val); - } else if (!av_strcasecmp(cmd, "HTTPBindAddress") || - !av_strcasecmp(cmd, "BindAddress")) { - if (!av_strcasecmp(cmd, "BindAddress")) - WARNING("BindAddress option is deprecated. Use HTTPBindAddress " - "instead.\n"); - ffserver_get_arg(arg, sizeof(arg), p); - if (resolve_host(&config->http_addr.sin_addr, arg)) - ERROR("Invalid host/IP address: '%s'\n", arg); - } else if (!av_strcasecmp(cmd, "NoDaemon")) { - WARNING("NoDaemon option has no effect. You should remove it.\n"); - } else if (!av_strcasecmp(cmd, "RTSPPort")) { - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_set_int_param(&val, arg, 0, 1, 65535, config, - "Invalid port: %s\n", arg); - config->rtsp_addr.sin_port = htons(val); - } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (resolve_host(&config->rtsp_addr.sin_addr, arg)) - ERROR("Invalid host/IP address: %s\n", arg); - } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) { - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_set_int_param(&val, arg, 0, 1, 65535, config, - "Invalid MaxHTTPConnections: %s\n", arg); - config->nb_max_http_connections = val; - if (config->nb_max_connections > config->nb_max_http_connections) { - ERROR("Inconsistent configuration: MaxClients(%d) > " - "MaxHTTPConnections(%d)\n", config->nb_max_connections, - config->nb_max_http_connections); - } - } else if (!av_strcasecmp(cmd, "MaxClients")) { - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_set_int_param(&val, arg, 0, 1, 65535, config, - "Invalid MaxClients: '%s'\n", arg); - config->nb_max_connections = val; - if (config->nb_max_connections > config->nb_max_http_connections) { - ERROR("Inconsistent configuration: MaxClients(%d) > " - "MaxHTTPConnections(%d)\n", config->nb_max_connections, - config->nb_max_http_connections); - } - } else if (!av_strcasecmp(cmd, "MaxBandwidth")) { - int64_t llval; - char *tailp; - ffserver_get_arg(arg, sizeof(arg), p); - errno = 0; - llval = strtoll(arg, &tailp, 10); - if (llval < 10 || llval > 10000000 || tailp[0] || errno) - ERROR("Invalid MaxBandwidth: '%s'\n", arg); - else - config->max_bandwidth = llval; - } else if (!av_strcasecmp(cmd, "CustomLog")) { - if (!config->debug) { - ffserver_get_arg(config->logfilename, sizeof(config->logfilename), - p); - } - } else if (!av_strcasecmp(cmd, "LoadModule")) { - ERROR("Loadable modules are no longer supported\n"); - } else if (!av_strcasecmp(cmd, "NoDefaults")) { - config->use_defaults = 0; - } else if (!av_strcasecmp(cmd, "UseDefaults")) { - config->use_defaults = 1; - } else - ERROR("Incorrect keyword: '%s'\n", cmd); - return 0; -} - -static int ffserver_parse_config_feed(FFServerConfig *config, const char *cmd, - const char **p, FFServerStream **pfeed) -{ - FFServerStream *feed; - char arg[1024]; - av_assert0(pfeed); - feed = *pfeed; - if (!av_strcasecmp(cmd, "filename, sizeof(feed->filename), p); - q = strrchr(feed->filename, '>'); - if (*q) - *q = '\0'; - - for (s = config->first_feed; s; s = s->next) { - if (!strcmp(feed->filename, s->filename)) - ERROR("Feed '%s' already registered\n", s->filename); - } - - feed->fmt = av_guess_format("ffm", NULL, NULL); - /* default feed file */ - snprintf(feed->feed_filename, sizeof(feed->feed_filename), - "/tmp/%s.ffm", feed->filename); - feed->feed_max_size = 5 * 1024 * 1024; - feed->is_feed = 1; - feed->feed = feed; /* self feeding :-) */ - *pfeed = feed; - return 0; - } - av_assert0(feed); - if (!av_strcasecmp(cmd, "Launch")) { - int i; - - feed->child_argv = av_mallocz_array(MAX_CHILD_ARGS, sizeof(char *)); - if (!feed->child_argv) - return AVERROR(ENOMEM); - for (i = 0; i < MAX_CHILD_ARGS - 2; i++) { - ffserver_get_arg(arg, sizeof(arg), p); - if (!arg[0]) - break; - - feed->child_argv[i] = av_strdup(arg); - if (!feed->child_argv[i]) - return AVERROR(ENOMEM); - } - - feed->child_argv[i] = - av_asprintf("http://%s:%d/%s", - (config->http_addr.sin_addr.s_addr == INADDR_ANY) ? - "127.0.0.1" : inet_ntoa(config->http_addr.sin_addr), - ntohs(config->http_addr.sin_port), feed->filename); - if (!feed->child_argv[i]) - return AVERROR(ENOMEM); - } else if (!av_strcasecmp(cmd, "ACL")) { - ffserver_parse_acl_row(NULL, feed, NULL, *p, config->filename, - config->line_num); - } else if (!av_strcasecmp(cmd, "File") || - !av_strcasecmp(cmd, "ReadOnlyFile")) { - ffserver_get_arg(feed->feed_filename, sizeof(feed->feed_filename), p); - feed->readonly = !av_strcasecmp(cmd, "ReadOnlyFile"); - } else if (!av_strcasecmp(cmd, "Truncate")) { - ffserver_get_arg(arg, sizeof(arg), p); - /* assume Truncate is true in case no argument is specified */ - if (!arg[0]) { - feed->truncate = 1; - } else { - WARNING("Truncate N syntax in configuration file is deprecated. " - "Use Truncate alone with no arguments.\n"); - feed->truncate = strtod(arg, NULL); - } - } else if (!av_strcasecmp(cmd, "FileMaxSize")) { - char *p1; - double fsize; - - ffserver_get_arg(arg, sizeof(arg), p); - p1 = arg; - fsize = strtod(p1, &p1); - switch(av_toupper(*p1)) { - case 'K': - fsize *= 1024; - break; - case 'M': - fsize *= 1024 * 1024; - break; - case 'G': - fsize *= 1024 * 1024 * 1024; - break; - default: - ERROR("Invalid file size: '%s'\n", arg); - break; - } - feed->feed_max_size = (int64_t)fsize; - if (feed->feed_max_size < FFM_PACKET_SIZE*4) { - ERROR("Feed max file size is too small. Must be at least %d.\n", - FFM_PACKET_SIZE*4); - } - } else if (!av_strcasecmp(cmd, "")) { - *pfeed = NULL; - } else { - ERROR("Invalid entry '%s' inside \n", cmd); - } - return 0; -} - -static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd, - const char **p, - FFServerStream **pstream) -{ - char arg[1024], arg2[1024]; - FFServerStream *stream; - int val; - - av_assert0(pstream); - stream = *pstream; - - if (!av_strcasecmp(cmd, "dummy_actx = avcodec_alloc_context3(NULL); - config->dummy_vctx = avcodec_alloc_context3(NULL); - if (!config->dummy_vctx || !config->dummy_actx) { - av_free(stream); - avcodec_free_context(&config->dummy_vctx); - avcodec_free_context(&config->dummy_actx); - return AVERROR(ENOMEM); - } - config->dummy_actx->codec_type = AVMEDIA_TYPE_AUDIO; - config->dummy_vctx->codec_type = AVMEDIA_TYPE_VIDEO; - ffserver_get_arg(stream->filename, sizeof(stream->filename), p); - q = strrchr(stream->filename, '>'); - if (q) - *q = '\0'; - - for (s = config->first_stream; s; s = s->next) { - if (!strcmp(stream->filename, s->filename)) - ERROR("Stream '%s' already registered\n", s->filename); - } - - stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL); - if (stream->fmt) { - config->guessed_audio_codec_id = stream->fmt->audio_codec; - config->guessed_video_codec_id = stream->fmt->video_codec; - } else { - config->guessed_audio_codec_id = AV_CODEC_ID_NONE; - config->guessed_video_codec_id = AV_CODEC_ID_NONE; - } - config->stream_use_defaults = config->use_defaults; - *pstream = stream; - return 0; - } - av_assert0(stream); - if (!av_strcasecmp(cmd, "Feed")) { - FFServerStream *sfeed; - ffserver_get_arg(arg, sizeof(arg), p); - sfeed = config->first_feed; - while (sfeed) { - if (!strcmp(sfeed->filename, arg)) - break; - sfeed = sfeed->next_feed; - } - if (!sfeed) - ERROR("Feed with name '%s' for stream '%s' is not defined\n", arg, - stream->filename); - else - stream->feed = sfeed; - } else if (!av_strcasecmp(cmd, "Format")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (!strcmp(arg, "status")) { - stream->stream_type = STREAM_TYPE_STATUS; - stream->fmt = NULL; - } else { - stream->stream_type = STREAM_TYPE_LIVE; - /* JPEG cannot be used here, so use single frame MJPEG */ - if (!strcmp(arg, "jpeg")) { - strcpy(arg, "singlejpeg"); - stream->single_frame=1; - } - stream->fmt = ffserver_guess_format(arg, NULL, NULL); - if (!stream->fmt) - ERROR("Unknown Format: '%s'\n", arg); - } - if (stream->fmt) { - config->guessed_audio_codec_id = stream->fmt->audio_codec; - config->guessed_video_codec_id = stream->fmt->video_codec; - } - } else if (!av_strcasecmp(cmd, "InputFormat")) { - ffserver_get_arg(arg, sizeof(arg), p); - stream->ifmt = av_find_input_format(arg); - if (!stream->ifmt) - ERROR("Unknown input format: '%s'\n", arg); - } else if (!av_strcasecmp(cmd, "FaviconURL")) { - if (stream->stream_type == STREAM_TYPE_STATUS) - ffserver_get_arg(stream->feed_filename, - sizeof(stream->feed_filename), p); - else - ERROR("FaviconURL only permitted for status streams\n"); - } else if (!av_strcasecmp(cmd, "Author") || - !av_strcasecmp(cmd, "Comment") || - !av_strcasecmp(cmd, "Copyright") || - !av_strcasecmp(cmd, "Title")) { - char key[32]; - int i; - ffserver_get_arg(arg, sizeof(arg), p); - for (i = 0; i < strlen(cmd); i++) - key[i] = av_tolower(cmd[i]); - key[i] = 0; - WARNING("Deprecated '%s' option in configuration file. Use " - "'Metadata %s VALUE' instead.\n", cmd, key); - if (av_dict_set(&stream->metadata, key, arg, 0) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "Metadata")) { - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_get_arg(arg2, sizeof(arg2), p); - if (av_dict_set(&stream->metadata, arg, arg2, 0) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "Preroll")) { - ffserver_get_arg(arg, sizeof(arg), p); - stream->prebuffer = atof(arg) * 1000; - } else if (!av_strcasecmp(cmd, "StartSendOnKey")) { - stream->send_on_key = 1; - } else if (!av_strcasecmp(cmd, "AudioCodec")) { - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_set_codec(config->dummy_actx, arg, config); - } else if (!av_strcasecmp(cmd, "VideoCodec")) { - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_set_codec(config->dummy_vctx, arg, config); - } else if (!av_strcasecmp(cmd, "MaxTime")) { - ffserver_get_arg(arg, sizeof(arg), p); - stream->max_time = atof(arg) * 1000; - } else if (!av_strcasecmp(cmd, "AudioBitRate")) { - float f; - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_set_float_param(&f, arg, 1000, -FLT_MAX, FLT_MAX, config, - "Invalid %s: '%s'\n", cmd, arg); - if (ffserver_save_avoption_int("b", (int64_t)lrintf(f), - AV_OPT_FLAG_AUDIO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "AudioChannels")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (ffserver_save_avoption("ac", arg, AV_OPT_FLAG_AUDIO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "AudioSampleRate")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (ffserver_save_avoption("ar", arg, AV_OPT_FLAG_AUDIO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) { - int minrate, maxrate; - char *dash; - ffserver_get_arg(arg, sizeof(arg), p); - dash = strchr(arg, '-'); - if (dash) { - *dash = '\0'; - dash++; - if (ffserver_set_int_param(&minrate, arg, 1000, 0, INT_MAX, config, "Invalid %s: '%s'", cmd, arg) >= 0 && - ffserver_set_int_param(&maxrate, dash, 1000, 0, INT_MAX, config, "Invalid %s: '%s'", cmd, arg) >= 0) { - if (ffserver_save_avoption_int("minrate", minrate, AV_OPT_FLAG_VIDEO_PARAM, config) < 0 || - ffserver_save_avoption_int("maxrate", maxrate, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } - } else - ERROR("Incorrect format for VideoBitRateRange. It should be " - "-: '%s'.\n", arg); - } else if (!av_strcasecmp(cmd, "Debug")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (ffserver_save_avoption("debug", arg, AV_OPT_FLAG_AUDIO_PARAM, config) < 0 || - ffserver_save_avoption("debug", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "Strict")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (ffserver_save_avoption("strict", arg, AV_OPT_FLAG_AUDIO_PARAM, config) < 0 || - ffserver_save_avoption("strict", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "VideoBufferSize")) { - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_set_int_param(&val, arg, 8*1024, 0, INT_MAX, config, - "Invalid %s: '%s'", cmd, arg); - if (ffserver_save_avoption_int("bufsize", val, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) { - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_set_int_param(&val, arg, 1000, INT_MIN, INT_MAX, config, - "Invalid %s: '%s'", cmd, arg); - if (ffserver_save_avoption_int("bt", val, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "VideoBitRate")) { - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_set_int_param(&val, arg, 1000, INT_MIN, INT_MAX, config, - "Invalid %s: '%s'", cmd, arg); - if (ffserver_save_avoption_int("b", val, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "VideoSize")) { - int ret, w, h; - ffserver_get_arg(arg, sizeof(arg), p); - ret = av_parse_video_size(&w, &h, arg); - if (ret < 0) - ERROR("Invalid video size '%s'\n", arg); - else { - if (w % 2 || h % 2) - WARNING("Image size is not a multiple of 2\n"); - if (ffserver_save_avoption("video_size", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } - } else if (!av_strcasecmp(cmd, "VideoFrameRate")) { - ffserver_get_arg(&arg[2], sizeof(arg) - 2, p); - arg[0] = '1'; arg[1] = '/'; - if (ffserver_save_avoption("time_base", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "PixelFormat")) { - enum AVPixelFormat pix_fmt; - ffserver_get_arg(arg, sizeof(arg), p); - pix_fmt = av_get_pix_fmt(arg); - if (pix_fmt == AV_PIX_FMT_NONE) - ERROR("Unknown pixel format: '%s'\n", arg); - else if (ffserver_save_avoption("pixel_format", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "VideoGopSize")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (ffserver_save_avoption("g", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) { - if (ffserver_save_avoption("g", "1", AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "VideoHighQuality")) { - if (ffserver_save_avoption("mbd", "+bits", AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "Video4MotionVector")) { - if (ffserver_save_avoption("mbd", "+bits", AV_OPT_FLAG_VIDEO_PARAM, config) < 0 || //FIXME remove - ffserver_save_avoption("flags", "+mv4", AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "AVOptionVideo") || - !av_strcasecmp(cmd, "AVOptionAudio")) { - int ret; - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_get_arg(arg2, sizeof(arg2), p); - if (!av_strcasecmp(cmd, "AVOptionVideo")) - ret = ffserver_save_avoption(arg, arg2, AV_OPT_FLAG_VIDEO_PARAM, - config); - else - ret = ffserver_save_avoption(arg, arg2, AV_OPT_FLAG_AUDIO_PARAM, - config); - if (ret < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "AVPresetVideo") || - !av_strcasecmp(cmd, "AVPresetAudio")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (!av_strcasecmp(cmd, "AVPresetVideo")) - ffserver_opt_preset(arg, AV_OPT_FLAG_VIDEO_PARAM, config); - else - ffserver_opt_preset(arg, AV_OPT_FLAG_AUDIO_PARAM, config); - } else if (!av_strcasecmp(cmd, "VideoTag")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (strlen(arg) == 4 && - ffserver_save_avoption_int("codec_tag", - MKTAG(arg[0], arg[1], arg[2], arg[3]), - AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "BitExact")) { - config->bitexact = 1; - if (ffserver_save_avoption("flags", "+bitexact", AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "DctFastint")) { - if (ffserver_save_avoption("dct", "fastint", AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "IdctSimple")) { - if (ffserver_save_avoption("idct", "simple", AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "Qscale")) { - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_set_int_param(&val, arg, 0, INT_MIN, INT_MAX, config, - "Invalid Qscale: '%s'\n", arg); - if (ffserver_save_avoption("flags", "+qscale", AV_OPT_FLAG_VIDEO_PARAM, config) < 0 || - ffserver_save_avoption_int("global_quality", FF_QP2LAMBDA * val, - AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "VideoQDiff")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (ffserver_save_avoption("qdiff", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "VideoQMax")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (ffserver_save_avoption("qmax", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "VideoQMin")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (ffserver_save_avoption("qmin", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "LumiMask")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (ffserver_save_avoption("lumi_mask", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "DarkMask")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (ffserver_save_avoption("dark_mask", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0) - goto nomem; - } else if (!av_strcasecmp(cmd, "NoVideo")) { - config->no_video = 1; - } else if (!av_strcasecmp(cmd, "NoAudio")) { - config->no_audio = 1; - } else if (!av_strcasecmp(cmd, "ACL")) { - ffserver_parse_acl_row(stream, NULL, NULL, *p, config->filename, - config->line_num); - } else if (!av_strcasecmp(cmd, "DynamicACL")) { - ffserver_get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), p); - } else if (!av_strcasecmp(cmd, "RTSPOption")) { - ffserver_get_arg(arg, sizeof(arg), p); - av_freep(&stream->rtsp_option); - stream->rtsp_option = av_strdup(arg); - } else if (!av_strcasecmp(cmd, "MulticastAddress")) { - ffserver_get_arg(arg, sizeof(arg), p); - if (resolve_host(&stream->multicast_ip, arg)) - ERROR("Invalid host/IP address: '%s'\n", arg); - stream->is_multicast = 1; - stream->loop = 1; /* default is looping */ - } else if (!av_strcasecmp(cmd, "MulticastPort")) { - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_set_int_param(&val, arg, 0, 1, 65535, config, - "Invalid MulticastPort: '%s'\n", arg); - stream->multicast_port = val; - } else if (!av_strcasecmp(cmd, "MulticastTTL")) { - ffserver_get_arg(arg, sizeof(arg), p); - ffserver_set_int_param(&val, arg, 0, INT_MIN, INT_MAX, config, - "Invalid MulticastTTL: '%s'\n", arg); - stream->multicast_ttl = val; - } else if (!av_strcasecmp(cmd, "NoLoop")) { - stream->loop = 0; - } else if (!av_strcasecmp(cmd, "")) { - config->stream_use_defaults &= 1; - if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm")) { - if (config->dummy_actx->codec_id == AV_CODEC_ID_NONE) - config->dummy_actx->codec_id = config->guessed_audio_codec_id; - if (!config->no_audio && - config->dummy_actx->codec_id != AV_CODEC_ID_NONE) { - AVCodecContext *audio_enc = avcodec_alloc_context3(avcodec_find_encoder(config->dummy_actx->codec_id)); - add_codec(stream, audio_enc, config); - } - if (config->dummy_vctx->codec_id == AV_CODEC_ID_NONE) - config->dummy_vctx->codec_id = config->guessed_video_codec_id; - if (!config->no_video && - config->dummy_vctx->codec_id != AV_CODEC_ID_NONE) { - AVCodecContext *video_enc = avcodec_alloc_context3(avcodec_find_encoder(config->dummy_vctx->codec_id)); - add_codec(stream, video_enc, config); - } - } - av_dict_free(&config->video_opts); - av_dict_free(&config->audio_opts); - avcodec_free_context(&config->dummy_vctx); - avcodec_free_context(&config->dummy_actx); - config->no_video = 0; - config->no_audio = 0; - *pstream = NULL; - } else if (!av_strcasecmp(cmd, "File") || - !av_strcasecmp(cmd, "ReadOnlyFile")) { - ffserver_get_arg(stream->feed_filename, sizeof(stream->feed_filename), - p); - } else if (!av_strcasecmp(cmd, "UseDefaults")) { - if (config->stream_use_defaults > 1) - WARNING("Multiple UseDefaults/NoDefaults entries.\n"); - config->stream_use_defaults = 3; - } else if (!av_strcasecmp(cmd, "NoDefaults")) { - if (config->stream_use_defaults > 1) - WARNING("Multiple UseDefaults/NoDefaults entries.\n"); - config->stream_use_defaults = 2; - } else { - ERROR("Invalid entry '%s' inside \n", cmd); - } - return 0; - nomem: - av_log(NULL, AV_LOG_ERROR, "Out of memory. Aborting.\n"); - av_dict_free(&config->video_opts); - av_dict_free(&config->audio_opts); - avcodec_free_context(&config->dummy_vctx); - avcodec_free_context(&config->dummy_actx); - return AVERROR(ENOMEM); -} - -static int ffserver_parse_config_redirect(FFServerConfig *config, - const char *cmd, const char **p, - FFServerStream **predirect) -{ - FFServerStream *redirect; - av_assert0(predirect); - redirect = *predirect; - - if (!av_strcasecmp(cmd, "filename, sizeof(redirect->filename), p); - q = strrchr(redirect->filename, '>'); - if (*q) - *q = '\0'; - redirect->stream_type = STREAM_TYPE_REDIRECT; - *predirect = redirect; - return 0; - } - av_assert0(redirect); - if (!av_strcasecmp(cmd, "URL")) { - ffserver_get_arg(redirect->feed_filename, - sizeof(redirect->feed_filename), p); - } else if (!av_strcasecmp(cmd, "")) { - if (!redirect->feed_filename[0]) - ERROR("No URL found for \n"); - *predirect = NULL; - } else { - ERROR("Invalid entry '%s' inside \n", cmd); - } - return 0; -} - -int ffserver_parse_ffconfig(const char *filename, FFServerConfig *config) -{ - FILE *f; - char line[1024]; - char cmd[64]; - const char *p; - FFServerStream **last_stream, *stream = NULL, *redirect = NULL; - FFServerStream **last_feed, *feed = NULL; - int ret = 0; - - av_assert0(config); - - f = fopen(filename, "r"); - if (!f) { - ret = AVERROR(errno); - av_log(NULL, AV_LOG_ERROR, - "Could not open the configuration file '%s'\n", filename); - return ret; - } - - config->first_stream = NULL; - config->first_feed = NULL; - config->errors = config->warnings = 0; - - last_stream = &config->first_stream; - last_feed = &config->first_feed; - - config->line_num = 0; - while (fgets(line, sizeof(line), f) != NULL) { - config->line_num++; - p = line; - while (av_isspace(*p)) - p++; - if (*p == '\0' || *p == '#') - continue; - - ffserver_get_arg(cmd, sizeof(cmd), &p); - - if (feed || !av_strcasecmp(cmd, "next; - last_feed = &feed->next_feed; - } - } - } else if (stream || !av_strcasecmp(cmd, "next; - } - } - } else if (redirect || !av_strcasecmp(cmd, "next; - } - } - } else { - ffserver_parse_config_global(config, cmd, &p); - } - } - if (stream || feed || redirect) - ERROR("Missing closing tag\n", - stream ? "Stream" : (feed ? "Feed" : "Redirect")); - - fclose(f); - if (ret < 0) - return ret; - if (config->errors) - return AVERROR(EINVAL); - else - return 0; -} - -#undef ERROR -#undef WARNING - -void ffserver_free_child_args(void *argsp) -{ - int i; - char **args; - if (!argsp) - return; - args = *(char ***)argsp; - if (!args) - return; - for (i = 0; i < MAX_CHILD_ARGS; i++) - av_free(args[i]); - av_freep(argsp); -} diff --git a/fftools/ffserver_config.h b/fftools/ffserver_config.h deleted file mode 100644 index 089b8484da310..0000000000000 --- a/fftools/ffserver_config.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2000, 2001, 2002 Fabrice Bellard - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef FFTOOLS_FFSERVER_CONFIG_H -#define FFTOOLS_FFSERVER_CONFIG_H - -#define FFM_PACKET_SIZE 4096 - -#include "libavutil/dict.h" -#include "libavformat/avformat.h" -#include "libavformat/network.h" - -#define FFSERVER_MAX_STREAMS 20 - -/* each generated stream is described here */ -enum FFServerStreamType { - STREAM_TYPE_LIVE, - STREAM_TYPE_STATUS, - STREAM_TYPE_REDIRECT, -}; - -enum FFServerIPAddressAction { - IP_ALLOW = 1, - IP_DENY, -}; - -typedef struct FFServerIPAddressACL { - struct FFServerIPAddressACL *next; - enum FFServerIPAddressAction action; - /* These are in host order */ - struct in_addr first; - struct in_addr last; -} FFServerIPAddressACL; - -/** - * This holds the stream parameters for an AVStream, it cannot be a AVStream - * because AVStreams cannot be instanciated without a AVFormatContext, especially - * not outside libavformat. - * - * The fields of this struct have the same semantics as the fields of an AVStream. - */ -typedef struct LayeredAVStream { - int index; - int id; - AVCodecParameters *codecpar; - AVCodecContext *codec; - AVRational time_base; - int pts_wrap_bits; - AVRational sample_aspect_ratio; - char *recommended_encoder_configuration; -} LayeredAVStream; - -/* description of each stream of the ffserver.conf file */ -typedef struct FFServerStream { - enum FFServerStreamType stream_type; - char filename[1024]; /* stream filename */ - struct FFServerStream *feed; /* feed we are using (can be null if coming from file) */ - AVDictionary *in_opts; /* input parameters */ - AVDictionary *metadata; /* metadata to set on the stream */ - AVInputFormat *ifmt; /* if non NULL, force input format */ - AVOutputFormat *fmt; - FFServerIPAddressACL *acl; - char dynamic_acl[1024]; - int nb_streams; - int prebuffer; /* Number of milliseconds early to start */ - int64_t max_time; /* Number of milliseconds to run */ - int send_on_key; - LayeredAVStream *streams[FFSERVER_MAX_STREAMS]; - int feed_streams[FFSERVER_MAX_STREAMS]; /* index of streams in the feed */ - char feed_filename[1024]; /* file name of the feed storage, or - input file name for a stream */ - pid_t pid; /* Of ffmpeg process */ - time_t pid_start; /* Of ffmpeg process */ - char **child_argv; - struct FFServerStream *next; - unsigned bandwidth; /* bandwidth, in kbits/s */ - /* RTSP options */ - char *rtsp_option; - /* multicast specific */ - int is_multicast; - struct in_addr multicast_ip; - int multicast_port; /* first port used for multicast */ - int multicast_ttl; - int loop; /* if true, send the stream in loops (only meaningful if file) */ - char single_frame; /* only single frame */ - - /* feed specific */ - int feed_opened; /* true if someone is writing to the feed */ - int is_feed; /* true if it is a feed */ - int readonly; /* True if writing is prohibited to the file */ - int truncate; /* True if feeder connection truncate the feed file */ - int conns_served; - int64_t bytes_served; - int64_t feed_max_size; /* maximum storage size, zero means unlimited */ - int64_t feed_write_index; /* current write position in feed (it wraps around) */ - int64_t feed_size; /* current size of feed */ - struct FFServerStream *next_feed; -} FFServerStream; - -typedef struct FFServerConfig { - char *filename; - FFServerStream *first_feed; /* contains only feeds */ - FFServerStream *first_stream; /* contains all streams, including feeds */ - unsigned int nb_max_http_connections; - unsigned int nb_max_connections; - uint64_t max_bandwidth; - int debug; - int bitexact; - char logfilename[1024]; - struct sockaddr_in http_addr; - struct sockaddr_in rtsp_addr; - int errors; - int warnings; - int use_defaults; - // Following variables MUST NOT be used outside configuration parsing code. - enum AVCodecID guessed_audio_codec_id; - enum AVCodecID guessed_video_codec_id; - AVDictionary *video_opts; /* AVOptions for video encoder */ - AVDictionary *audio_opts; /* AVOptions for audio encoder */ - AVCodecContext *dummy_actx; /* Used internally to test audio AVOptions. */ - AVCodecContext *dummy_vctx; /* Used internally to test video AVOptions. */ - int no_audio; - int no_video; - int line_num; - int stream_use_defaults; -} FFServerConfig; - -void ffserver_get_arg(char *buf, int buf_size, const char **pp); - -void ffserver_parse_acl_row(FFServerStream *stream, FFServerStream* feed, - FFServerIPAddressACL *ext_acl, - const char *p, const char *filename, int line_num); - -int ffserver_parse_ffconfig(const char *filename, FFServerConfig *config); - -void ffserver_free_child_args(void *argsp); - -#endif /* FFTOOLS_FFSERVER_CONFIG_H */ diff --git a/tests/Makefile b/tests/Makefile index fd3713fe81f50..14b9601378c2d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,5 +1,3 @@ -FFSERVER_REFFILE = $(SRC_PATH)/tests/ffserver.regression.ref - THREADS = 1 VREF = tests/vsynth1/00.pgm AREF = tests/data/asynth1.sw @@ -11,14 +9,6 @@ FFMPEG=ffmpeg$(PROGSSUF)$(EXESUF) $(AREF): CMP= -ffservertest: export PROGSUF = $(PROGSSUF) -ffservertest: ffserver$(PROGSSUF)$(EXESUF) ffmpeg$(PROGSSUF)$(EXESUF) tests/vsynth1/00.pgm tests/data/asynth1.sw - @echo - @echo "Unfortunately ffserver is broken and therefore its regression" - @echo "test fails randomly. Treat the results accordingly." - @echo - $(SRC_PATH)/tests/ffserver-regression.sh $(FFSERVER_REFFILE) $(SRC_PATH)/tests/ffserver.conf "$(TARGET_SAMPLES)" "$(TARGET_EXEC)" "$(TARGET_PATH)" - APITESTSDIR := tests/api OBJDIRS += tests/data tests/vsynth1 tests/data/filtergraphs $(APITESTSDIR)/ diff --git a/tests/ffserver-regression.sh b/tests/ffserver-regression.sh deleted file mode 100755 index 9007fe37ca8ff..0000000000000 --- a/tests/ffserver-regression.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh - -target_samples=$3 -target_exec=$4 -target_path=$5 - -#perl -e 'chomp($wd = `pwd`); print map { s!tests/data/!!; "\nFile $wd/tests/data/$_\n\n\n" } @ARGV' tests/data/a* >> tests/data/ffserver.conf -#perl -e 'chomp($wd = `pwd`); print map { s!tests/data/!!; "\nFile $wd/tests/data/$_\n\n\n" } @ARGV' tests/data/a* >> tests/data/ffserver.conf - -. $(dirname $0)/md5.sh - -FILES=$(sed -n 's/^[^#]*.*/\1/p' $2 | grep -v html) - -rm -f tests/feed1.ffm -$target_exec ${target_path}/ffserver${PROGSUF} -f "$2" & -FFSERVER_PID=$! -echo "Waiting for feeds to startup..." -sleep 2 -( - cd tests/data || exit $? - rm -f ff-* ffserver.regression - WGET_OPTIONS="--user-agent=NSPlayer -q --proxy=off -e verbose=off -e server_response=off -T3 --tries=1" - for file in $FILES; do - if [ $(expr $file : "a-*") != 0 ]; then - wget $WGET_OPTIONS -O - http://localhost:9999/$file > ff-$file - else - wget $WGET_OPTIONS -O - http://localhost:9999/$file?date=19700101T000000Z | dd bs=1 count=100000 > ff-$file 2>/dev/null - fi - do_md5sum ff-$file >>ffserver.regression - done - wget $WGET_OPTIONS -O - 'http://localhost:9999/teststat.html?abc' > ff-stat 2>/dev/null - do_md5sum ff-stat >>ffserver.regression -) -kill $FFSERVER_PID -wait > /dev/null 2>&1 -rm -f tests/feed1.ffm -if diff -u "$1" tests/data/ffserver.regression; then - echo - echo Server regression test succeeded. - exit 0 -else - echo - echo Server regression test: Error. - exit 1 -fi diff --git a/tests/ffserver.conf b/tests/ffserver.conf deleted file mode 100644 index 3495d959e2577..0000000000000 --- a/tests/ffserver.conf +++ /dev/null @@ -1,311 +0,0 @@ -# -# This is a test configuration file. You can invoke it with -# ../ffserver -f ffserver.conf -# when in the tests directory and once the vsynth1 subdirectory -# has been populated. Then point your browser at http://whatever:9999/teststat.html -# and you can look at the streams -# - -# -# Port on which the server is listening. You must select a different -# port from your standard http web server if it is running on the same -# computer. - -HTTPPort 9999 -RTSPPort 9990 - -# Address on which the server is bound. Only useful if you have -# several network interfaces. - -HTTPBindAddress 0.0.0.0 - -# Number of simultaneous requests that can be handled. Since FFServer -# is very fast, this limit is determined mainly by your Internet -# connection speed. - -MaxClients 1000 - -MaxBandwidth 100000 - -# Access Log file (uses standard Apache log file format) -# '-' is the standard output - -CustomLog - - -################################################################## -# Definition of the live feeds. Each live feed contains one video -# and/or audio sequence coming from an ffmpeg encoder or another -# ffserver. This sequence may be encoded simultaneously with several -# codecs at several resolutions. - - - -# You must use 'ffmpeg' to send a live feed to ffserver. In this -# example, you can type: -# -# ffmpeg http://localhost:8090/feed1.ffm - -# ffserver can also do time shifting. It means that it can stream any -# previously recorded live stream. The request should contain: -# "http://xxxx?date=[YYYY-MM-DDT][[HH:]MM:]SS[.m...]".You must specify -# a path where the feed is stored on disk. You also specify the -# maximum size of the feed (100M bytes here). Default: -# File=/tmp/feed_name.ffm FileMaxSize=5M - -File tests/feed1.ffm -FileMaxSize 100M - -# Fire up ffmpeg pointing at this stream - -Launch ./ffmpeg -v 0 -y -f image2 -flags +bitexact -fflags +bitexact -i tests/vsynth1/%02d.pgm -flags +bitexact -fflags +bitexact - -ACL allow localhost - - -################################################################## -# Now you can define each stream which will be generated from the -# original audio and video stream. Each format has a filename (here -# 'test128.mpg'). FFServer will send this stream when answering a -# request containing this filename. - - -Feed feed1.ffm -Format avi -# -BitExact -DctFastint -IdctSimple -VideoFrameRate 10 -VideoSize 352x288 -VideoBitRate 100 -VideoGopSize 30 -NoAudio - -PreRoll 10 -StartSendOnKey -MaxTime 100 - - - - -Feed feed1.ffm -Format avi -# -BitExact -DctFastint -IdctSimple -VideoFrameRate 2 -VideoSize 320x240 -VideoBitRate 40 -VideoGopSize 20 -NoAudio - -PreRoll 20 -StartSendOnKey -MaxTime 100 - - - -# -#Feed feed1.ffm -# -#VideoFrameRate 10 -#VideoSize 352x288 -#VideoBitRate 100 -#VideoGopSize 30 -#NoAudio - -#PreRoll 10 -#StartSendOnKey -#MaxTime 100 -# -# -# -# -#Feed feed1.ffm -## -#VideoFrameRate 2 -#VideoSize 320x240 -#VideoBitRate 40 -#VideoGopSize 20 -#NoAudio -# -#PreRoll 20 -#StartSendOnKey -#MaxTime 100 -# -# -# - -Feed feed1.ffm -# -BitExact -DctFastint -IdctSimple -Qscale 10 -VideoFrameRate 10 -VideoSize 352x288 -VideoBitRate 100 -VideoGopSize 30 -NoAudio - -PreRoll 10 -StartSendOnKey -MaxTime 100 - - - - -Feed feed1.ffm -Format asf -# -BitExact -DctFastint -IdctSimple -Qscale 10 -VideoFrameRate 10 -VideoSize 320x240 -VideoBitRate 100 -VideoGopSize 30 -NoAudio - -PreRoll 10 -StartSendOnKey -MaxTime 100 - -AVOptionVideo flags +global_header - -Metadata title "Test data stream" - - - - -Feed feed1.ffm -Format asf -# -BitExact -DctFastint -IdctSimple -Qscale 10 -VideoFrameRate 2 -VideoSize 320x240 -VideoBitRate 40 -VideoGopSize 20 -NoAudio - -PreRoll 20 -StartSendOnKey -MaxTime 100 - -AVOptionVideo flags +global_header - -Metadata title "Test data stream" - - - - - -Feed feed1.ffm -Format rm - -BitExact -DctFastint -IdctSimple -Qscale 10 -VideoBitRate 100 -VideoFrameRate 10 -VideoGopSize 30 -VideoSize 320x240 -NoAudio - -PreRoll 10 -StartSendOnKey -MaxTime 100 - - - - - -Feed feed1.ffm -Format rm - -BitExact -DctFastint -IdctSimple -Qscale 10 -VideoBitRate 40 -VideoFrameRate 2 -VideoGopSize 20 -VideoSize 320x240 -NoAudio - -PreRoll 20 -StartSendOnKey -MaxTime 100 - - - - - - -Feed feed1.ffm -Format jpeg -Strict -1 - -BitExact -DctFastint -IdctSimple -VideoFrameRate 1 -VideoSize 352x288 -NoAudio - -PreRoll 2 - - - - - -Feed feed1.ffm -Format jpeg -Strict -1 - -BitExact -DctFastint -IdctSimple -VideoFrameRate 1 -VideoSize 160x128 -NoAudio - -PreRoll 2 - - - - - -Feed feed1.ffm -Format mpjpeg -Strict -1 - -BitExact -DctFastint -IdctSimple -VideoFrameRate 1 -VideoSize 320x240 -NoAudio -StartSendOnKey - -PreRoll 1 -MaxTime 100 - - - - -################################################################## -# Special stream : server status - - - -Format status - - - diff --git a/tests/ffserver.regression.ref b/tests/ffserver.regression.ref deleted file mode 100644 index fd8536c853f97..0000000000000 --- a/tests/ffserver.regression.ref +++ /dev/null @@ -1,11 +0,0 @@ -0c9639f09decbc54c9f091dcf1ca0e8f *ff-test_h.avi -e28ba75853caf975e06d92955c9f7f73 *ff-test_l.avi -a767dbdf5d1bded3450279f812f97b37 *ff-test.swf -ca209a0c67afbd3bc3bcde0840f313fc *ff-test_h.asf -f97a91609bfc8a1857455f17c5ec101c *ff-test_l.asf -06f5a6a4c5d1c6735f4d0068e825c91f *ff-test_h.rm -1f57580f02f0317407b3b82a3d5e093f *ff-test_l.rm -e04e6ebf9584654df131f5eec881ac38 *ff-test.jpg -f15d43e9d3630601b61a024023249bb8 *ff-test_small.jpg -4735c72cde67000f12e9d1dbfbd975a7 *ff-test.mjpg -fd038af80560e15271ce42651093ee43 *ff-stat diff --git a/tools/bisect-create b/tools/bisect-create index fc60e86669711..ee6ec3feb82f4 100755 --- a/tools/bisect-create +++ b/tools/bisect-create @@ -20,7 +20,7 @@ fi case "$1" in need) case $2 in - ffmpeg|ffplay|ffprobe|ffserver) + ffmpeg|ffplay|ffprobe) echo $2.c >> tools/bisect.need ;; esac From c17f4761443b471f47fa8f0a5bcff078cdff9479 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 21 Oct 2017 19:38:59 +0100 Subject: [PATCH 1574/2557] libavformat: remove the ffmenc and ffmdec muxer and demuxers Used only by ffserver. Signed-off-by: Rostislav Pehlivanov --- Changelog | 1 + libavformat/Makefile | 2 - libavformat/allformats.c | 1 - libavformat/ffm.h | 62 --- libavformat/ffmdec.c | 878 --------------------------------------- libavformat/ffmenc.c | 362 ---------------- 6 files changed, 1 insertion(+), 1305 deletions(-) delete mode 100644 libavformat/ffm.h delete mode 100644 libavformat/ffmdec.c delete mode 100644 libavformat/ffmenc.c diff --git a/Changelog b/Changelog index 028c20f4828dd..c87977d6a9318 100644 --- a/Changelog +++ b/Changelog @@ -36,6 +36,7 @@ version : - aiir audio filter - aiff: add support for CD-ROM XA ADPCM - Removed the ffserver program +- Removed the ffmenc and ffmdec muxer and demuxer version 3.4: diff --git a/libavformat/Makefile b/libavformat/Makefile index cb70eac9208e4..de0de921c2d3b 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -161,8 +161,6 @@ OBJS-$(CONFIG_EA_DEMUXER) += electronicarts.o OBJS-$(CONFIG_EAC3_DEMUXER) += ac3dec.o rawdec.o OBJS-$(CONFIG_EAC3_MUXER) += rawenc.o OBJS-$(CONFIG_EPAF_DEMUXER) += epafdec.o pcm.o -OBJS-$(CONFIG_FFM_DEMUXER) += ffmdec.o -OBJS-$(CONFIG_FFM_MUXER) += ffmenc.o OBJS-$(CONFIG_FFMETADATA_DEMUXER) += ffmetadec.o OBJS-$(CONFIG_FFMETADATA_MUXER) += ffmetaenc.o OBJS-$(CONFIG_FIFO_MUXER) += fifo.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 6a9b9883c97f1..ec8409630e592 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -120,7 +120,6 @@ static void register_all(void) REGISTER_MUXDEMUX(EAC3, eac3); REGISTER_DEMUXER (EPAF, epaf); REGISTER_MUXER (F4V, f4v); - REGISTER_MUXDEMUX(FFM, ffm); REGISTER_MUXDEMUX(FFMETADATA, ffmetadata); REGISTER_MUXER (FIFO, fifo); REGISTER_MUXDEMUX(FILMSTRIP, filmstrip); diff --git a/libavformat/ffm.h b/libavformat/ffm.h deleted file mode 100644 index c445f472f7362..0000000000000 --- a/libavformat/ffm.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * FFM (ffserver live feed) common header - * Copyright (c) 2001 Fabrice Bellard - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVFORMAT_FFM_H -#define AVFORMAT_FFM_H - -#include -#include "avformat.h" -#include "avio.h" - -/* The FFM file is made of blocks of fixed size */ -#define FFM_HEADER_SIZE 14 -#define FFM_PACKET_SIZE 4096 -#define PACKET_ID 0x666d - -/* each packet contains frames (which can span several packets */ -#define FRAME_HEADER_SIZE 16 -#define FLAG_KEY_FRAME 0x01 -#define FLAG_DTS 0x02 - -enum { - READ_HEADER, - READ_DATA, -}; - -typedef struct FFMContext { - const AVClass *class; - /* only reading mode */ - int64_t write_index, file_size; - int read_state; - uint8_t header[FRAME_HEADER_SIZE+4]; - - /* read and write */ - int first_packet; /* true if first packet, needed to set the discontinuity tag */ - int packet_size; - int frame_offset; - int64_t dts; - uint8_t *packet_ptr, *packet_end; - uint8_t packet[FFM_PACKET_SIZE]; - int64_t start_time; - int server_attached; -} FFMContext; - -#endif /* AVFORMAT_FFM_H */ diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c deleted file mode 100644 index de6ac272523d9..0000000000000 --- a/libavformat/ffmdec.c +++ /dev/null @@ -1,878 +0,0 @@ -/* - * FFM (ffserver live feed) demuxer - * Copyright (c) 2001 Fabrice Bellard - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "libavutil/imgutils.h" -#include "libavutil/internal.h" -#include "libavutil/intreadwrite.h" -#include "libavutil/intfloat.h" -#include "libavutil/opt.h" -#include "libavutil/avassert.h" -#include "libavutil/avstring.h" -#include "libavutil/pixdesc.h" -#include "libavcodec/internal.h" -#include "avformat.h" -#include "internal.h" -#include "ffm.h" -#include "avio_internal.h" - -static int ffm_is_avail_data(AVFormatContext *s, int size) -{ - FFMContext *ffm = s->priv_data; - int64_t pos, avail_size; - ptrdiff_t len; - - len = ffm->packet_end - ffm->packet_ptr; - if (size <= len) - return 1; - pos = avio_tell(s->pb); - if (!ffm->write_index) { - if (pos == ffm->file_size) - return AVERROR_EOF; - avail_size = ffm->file_size - pos; - } else { - if (pos == ffm->write_index) { - /* exactly at the end of stream */ - if (ffm->server_attached) - return AVERROR(EAGAIN); - else - return AVERROR_INVALIDDATA; - } else if (pos < ffm->write_index) { - avail_size = ffm->write_index - pos; - } else { - avail_size = (ffm->file_size - pos) + (ffm->write_index - FFM_PACKET_SIZE); - } - } - avail_size = (avail_size / ffm->packet_size) * (ffm->packet_size - FFM_HEADER_SIZE) + len; - if (size <= avail_size) - return 1; - else if (ffm->server_attached) - return AVERROR(EAGAIN); - else - return AVERROR_INVALIDDATA; -} - -static int ffm_resync(AVFormatContext *s, uint32_t state) -{ - av_log(s, AV_LOG_ERROR, "resyncing\n"); - while (state != PACKET_ID) { - if (avio_feof(s->pb)) { - av_log(s, AV_LOG_ERROR, "cannot find FFM syncword\n"); - return -1; - } - state = (state << 8) | avio_r8(s->pb); - } - return 0; -} - -/* first is true if we read the frame header */ -static int ffm_read_data(AVFormatContext *s, - uint8_t *buf, int size, int header) -{ - FFMContext *ffm = s->priv_data; - AVIOContext *pb = s->pb; - int fill_size, size1, frame_offset; - uint32_t id; - ptrdiff_t len; - int64_t last_pos = -1; - - size1 = size; - while (size > 0) { - redo: - len = ffm->packet_end - ffm->packet_ptr; - if (len < 0) - return -1; - if (len > size) - len = size; - if (len == 0) { - if (avio_tell(pb) == ffm->file_size) { - if (ffm->server_attached) { - avio_seek(pb, ffm->packet_size, SEEK_SET); - } else - return AVERROR_EOF; - } - retry_read: - if (pb->buffer_size != ffm->packet_size) { - int64_t tell = avio_tell(pb); - int ret = ffio_set_buf_size(pb, ffm->packet_size); - if (ret < 0) - return ret; - avio_seek(pb, tell, SEEK_SET); - } - id = avio_rb16(pb); /* PACKET_ID */ - if (id != PACKET_ID) { - if (ffm_resync(s, id) < 0) - return -1; - last_pos = avio_tell(pb); - } - fill_size = avio_rb16(pb); - ffm->dts = avio_rb64(pb); - frame_offset = avio_rb16(pb); - avio_read(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE); - if (ffm->packet_size < FFM_HEADER_SIZE + fill_size || frame_offset < 0) { - return -1; - } - ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size); - /* if first packet or resynchronization packet, we must - handle it specifically */ - if (ffm->first_packet || (frame_offset & 0x8000)) { - if (!frame_offset) { - /* This packet has no frame headers in it */ - if (avio_tell(pb) >= ffm->packet_size * 3LL) { - int64_t seekback = FFMIN(ffm->packet_size * 2LL, avio_tell(pb) - last_pos); - seekback = FFMAX(seekback, 0); - avio_seek(pb, -seekback, SEEK_CUR); - goto retry_read; - } - /* This is bad, we cannot find a valid frame header */ - return 0; - } - ffm->first_packet = 0; - if ((frame_offset & 0x7fff) < FFM_HEADER_SIZE) { - ffm->packet_end = ffm->packet_ptr; - return -1; - } - ffm->packet_ptr = ffm->packet + (frame_offset & 0x7fff) - FFM_HEADER_SIZE; - if (!header) - break; - } else { - ffm->packet_ptr = ffm->packet; - } - goto redo; - } - memcpy(buf, ffm->packet_ptr, len); - buf += len; - ffm->packet_ptr += len; - size -= len; - header = 0; - } - return size1 - size; -} - -/* ensure that actual seeking happens between FFM_PACKET_SIZE - and file_size - FFM_PACKET_SIZE */ -static int64_t ffm_seek1(AVFormatContext *s, int64_t pos1) -{ - FFMContext *ffm = s->priv_data; - AVIOContext *pb = s->pb; - int64_t pos; - - pos = FFMIN(pos1, ffm->file_size - FFM_PACKET_SIZE); - pos = FFMAX(pos, FFM_PACKET_SIZE); - ff_dlog(s, "seek to %"PRIx64" -> %"PRIx64"\n", pos1, pos); - return avio_seek(pb, pos, SEEK_SET); -} - -static int64_t get_dts(AVFormatContext *s, int64_t pos) -{ - AVIOContext *pb = s->pb; - int64_t dts; - - ffm_seek1(s, pos); - avio_skip(pb, 4); - dts = avio_rb64(pb); - ff_dlog(s, "dts=%0.6f\n", dts / 1000000.0); - return dts; -} - -static void adjust_write_index(AVFormatContext *s) -{ - FFMContext *ffm = s->priv_data; - AVIOContext *pb = s->pb; - int64_t pts; - //int64_t orig_write_index = ffm->write_index; - int64_t pos_min, pos_max; - int64_t pts_start; - int64_t ptr = avio_tell(pb); - - - pos_min = 0; - pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE; - - pts_start = get_dts(s, pos_min); - - pts = get_dts(s, pos_max); - - if (pts - 100000 > pts_start) - goto end; - - ffm->write_index = FFM_PACKET_SIZE; - - pts_start = get_dts(s, pos_min); - - pts = get_dts(s, pos_max); - - if (pts - 100000 <= pts_start) { - while (1) { - int64_t newpos; - int64_t newpts; - - newpos = ((pos_max + pos_min) / (2 * FFM_PACKET_SIZE)) * FFM_PACKET_SIZE; - - if (newpos == pos_min) - break; - - newpts = get_dts(s, newpos); - - if (newpts - 100000 <= pts) { - pos_max = newpos; - pts = newpts; - } else { - pos_min = newpos; - } - } - ffm->write_index += pos_max; - } - - end: - avio_seek(pb, ptr, SEEK_SET); -} - - -static int ffm_append_recommended_configuration(AVStream *st, char **conf) -{ - int ret; - size_t newsize; - av_assert0(conf && st); - if (!*conf) - return 0; - if (!st->recommended_encoder_configuration) { - st->recommended_encoder_configuration = *conf; - *conf = 0; - return 0; - } - newsize = strlen(*conf) + strlen(st->recommended_encoder_configuration) + 2; - if ((ret = av_reallocp(&st->recommended_encoder_configuration, newsize)) < 0) - return ret; - av_strlcat(st->recommended_encoder_configuration, ",", newsize); - av_strlcat(st->recommended_encoder_configuration, *conf, newsize); - av_freep(conf); - return 0; -} - -#define VALIDATE_PARAMETER(parameter, name, check) { \ - if (check) { \ - av_log(s, AV_LOG_ERROR, "Invalid " name " %d\n", codecpar->parameter); \ - ret = AVERROR_INVALIDDATA; \ - goto fail; \ - } \ -} - -static int ffm2_read_header(AVFormatContext *s) -{ - FFMContext *ffm = s->priv_data; - AVStream *st = NULL; - AVIOContext *pb = s->pb; - AVCodecContext *dummy_codec = NULL; - AVCodecParameters *codecpar = NULL; - const AVCodecDescriptor *codec_desc; - int ret; - int f_main = 0, f_cprv = -1, f_stvi = -1, f_stau = -1; - AVCodec *enc; - char *buffer; - - ffm->packet_size = avio_rb32(pb); - if (ffm->packet_size != FFM_PACKET_SIZE) { - av_log(s, AV_LOG_ERROR, "Invalid packet size %d, expected size was %d\n", - ffm->packet_size, FFM_PACKET_SIZE); - ret = AVERROR_INVALIDDATA; - goto fail; - } - - ffm->write_index = avio_rb64(pb); - /* get also filesize */ - if (pb->seekable & AVIO_SEEKABLE_NORMAL) { - ffm->file_size = avio_size(pb); - if (ffm->write_index && 0) - adjust_write_index(s); - } else { - ffm->file_size = (UINT64_C(1) << 63) - 1; - } - dummy_codec = avcodec_alloc_context3(NULL); - - while(!avio_feof(pb)) { - unsigned id = avio_rb32(pb); - unsigned size = avio_rb32(pb); - int64_t next = avio_tell(pb) + size; - char rc_eq_buf[128]; - int flags; - - if(!id) - break; - - switch(id) { - case MKBETAG('M', 'A', 'I', 'N'): - if (f_main++) { - ret = AVERROR(EINVAL); - goto fail; - } - avio_rb32(pb); /* nb_streams */ - avio_rb32(pb); /* total bitrate */ - break; - case MKBETAG('C', 'O', 'M', 'M'): - f_cprv = f_stvi = f_stau = 0; - st = avformat_new_stream(s, NULL); - if (!st) { - ret = AVERROR(ENOMEM); - goto fail; - } - - avpriv_set_pts_info(st, 64, 1, 1000000); - - codecpar = st->codecpar; - /* generic info */ - codecpar->codec_id = avio_rb32(pb); - codec_desc = avcodec_descriptor_get(codecpar->codec_id); - if (!codec_desc) { - av_log(s, AV_LOG_ERROR, "Invalid codec id: %d\n", codecpar->codec_id); - codecpar->codec_id = AV_CODEC_ID_NONE; - ret = AVERROR_INVALIDDATA; - goto fail; - } - codecpar->codec_type = avio_r8(pb); - if (codecpar->codec_type != codec_desc->type) { - av_log(s, AV_LOG_ERROR, "Codec type mismatch: expected %d, found %d\n", - codec_desc->type, codecpar->codec_type); - codecpar->codec_id = AV_CODEC_ID_NONE; - codecpar->codec_type = AVMEDIA_TYPE_UNKNOWN; - ret = AVERROR_INVALIDDATA; - goto fail; - } - codecpar->bit_rate = avio_rb32(pb); - if (codecpar->bit_rate < 0) { - av_log(s, AV_LOG_ERROR, "Invalid bit rate %"PRId64"\n", codecpar->bit_rate); - ret = AVERROR_INVALIDDATA; - goto fail; - } - flags = avio_rb32(pb); -#if FF_API_LAVF_AVCTX -FF_DISABLE_DEPRECATION_WARNINGS - st->codec->flags = flags; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - avio_rb32(pb); // flags2 - avio_rb32(pb); // debug - if (flags & AV_CODEC_FLAG_GLOBAL_HEADER) { - int size = avio_rb32(pb); - if (size < 0 || size >= FF_MAX_EXTRADATA_SIZE) { - av_log(s, AV_LOG_ERROR, "Invalid extradata size %d\n", size); - ret = AVERROR_INVALIDDATA; - goto fail; - } - codecpar->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!codecpar->extradata) { - ret = AVERROR(ENOMEM); - goto fail; - } - codecpar->extradata_size = size; - avio_read(pb, codecpar->extradata, size); - } - break; - case MKBETAG('S', 'T', 'V', 'I'): - if (f_stvi++ || codecpar->codec_type != AVMEDIA_TYPE_VIDEO) { - ret = AVERROR(EINVAL); - goto fail; - } - avio_rb32(pb); // time_base.num - avio_rb32(pb); // time_base.den - codecpar->width = avio_rb16(pb); - codecpar->height = avio_rb16(pb); - ret = av_image_check_size(codecpar->width, codecpar->height, 0, s); - if (ret < 0) - goto fail; - avio_rb16(pb); // gop_size - codecpar->format = avio_rb32(pb); - if (!av_pix_fmt_desc_get(codecpar->format)) { - av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codecpar->format); - codecpar->format = AV_PIX_FMT_NONE; - ret = AVERROR_INVALIDDATA; - goto fail; - } - avio_r8(pb); // qmin - avio_r8(pb); // qmax - avio_r8(pb); // max_qdiff - avio_rb16(pb); // qcompress / 10000.0 - avio_rb16(pb); // qblur / 10000.0 - avio_rb32(pb); // bit_rate_tolerance - avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf)); - - avio_rb32(pb); // rc_max_rate - avio_rb32(pb); // rc_min_rate - avio_rb32(pb); // rc_buffer_size - avio_rb64(pb); // i_quant_factor - avio_rb64(pb); // b_quant_factor - avio_rb64(pb); // i_quant_offset - avio_rb64(pb); // b_quant_offset - avio_rb32(pb); // dct_algo - avio_rb32(pb); // strict_std_compliance - avio_rb32(pb); // max_b_frames - avio_rb32(pb); // mpeg_quant - avio_rb32(pb); // intra_dc_precision - avio_rb32(pb); // me_method - avio_rb32(pb); // mb_decision - avio_rb32(pb); // nsse_weight - avio_rb32(pb); // frame_skip_cmp - avio_rb64(pb); // rc_buffer_aggressivity - codecpar->codec_tag = avio_rb32(pb); - avio_r8(pb); // thread_count - avio_rb32(pb); // coder_type - avio_rb32(pb); // me_cmp - avio_rb32(pb); // me_subpel_quality - avio_rb32(pb); // me_range - avio_rb32(pb); // keyint_min - avio_rb32(pb); // scenechange_threshold - avio_rb32(pb); // b_frame_strategy - avio_rb64(pb); // qcompress - avio_rb64(pb); // qblur - avio_rb32(pb); // max_qdiff - avio_rb32(pb); // refs - break; - case MKBETAG('S', 'T', 'A', 'U'): - if (f_stau++ || codecpar->codec_type != AVMEDIA_TYPE_AUDIO) { - ret = AVERROR(EINVAL); - goto fail; - } - codecpar->sample_rate = avio_rb32(pb); - VALIDATE_PARAMETER(sample_rate, "sample rate", codecpar->sample_rate < 0) - codecpar->channels = avio_rl16(pb); - VALIDATE_PARAMETER(channels, "number of channels", codecpar->channels < 0) - codecpar->frame_size = avio_rl16(pb); - VALIDATE_PARAMETER(frame_size, "frame size", codecpar->frame_size < 0) - break; - case MKBETAG('C', 'P', 'R', 'V'): - if (f_cprv++) { - ret = AVERROR(EINVAL); - goto fail; - } - enc = avcodec_find_encoder(codecpar->codec_id); - if (enc && enc->priv_data_size && enc->priv_class) { - buffer = av_malloc(size + 1); - if (!buffer) { - ret = AVERROR(ENOMEM); - goto fail; - } - avio_get_str(pb, size, buffer, size + 1); - if ((ret = ffm_append_recommended_configuration(st, &buffer)) < 0) - goto fail; - } - break; - case MKBETAG('S', '2', 'V', 'I'): - if (f_stvi++ || !size || codecpar->codec_type != AVMEDIA_TYPE_VIDEO) { - ret = AVERROR(EINVAL); - goto fail; - } - buffer = av_malloc(size); - if (!buffer) { - ret = AVERROR(ENOMEM); - goto fail; - } - avio_get_str(pb, INT_MAX, buffer, size); - // The lack of AVOptions support in AVCodecParameters makes this back and forth copying needed - avcodec_parameters_to_context(dummy_codec, codecpar); - av_set_options_string(dummy_codec, buffer, "=", ","); - avcodec_parameters_from_context(codecpar, dummy_codec); - if ((ret = ffm_append_recommended_configuration(st, &buffer)) < 0) - goto fail; - break; - case MKBETAG('S', '2', 'A', 'U'): - if (f_stau++ || !size || codecpar->codec_type != AVMEDIA_TYPE_AUDIO) { - ret = AVERROR(EINVAL); - goto fail; - } - buffer = av_malloc(size); - if (!buffer) { - ret = AVERROR(ENOMEM); - goto fail; - } - avio_get_str(pb, INT_MAX, buffer, size); - // The lack of AVOptions support in AVCodecParameters makes this back and forth copying needed - avcodec_parameters_to_context(dummy_codec, codecpar); - av_set_options_string(dummy_codec, buffer, "=", ","); - avcodec_parameters_from_context(codecpar, dummy_codec); - if ((ret = ffm_append_recommended_configuration(st, &buffer)) < 0) - goto fail; - break; - } - avio_seek(pb, next, SEEK_SET); - } - - /* get until end of block reached */ - while ((avio_tell(pb) % ffm->packet_size) != 0 && !pb->eof_reached) - avio_r8(pb); - - /* init packet demux */ - ffm->packet_ptr = ffm->packet; - ffm->packet_end = ffm->packet; - ffm->frame_offset = 0; - ffm->dts = 0; - ffm->read_state = READ_HEADER; - ffm->first_packet = 1; - avcodec_free_context(&dummy_codec); - return 0; - fail: - avcodec_free_context(&dummy_codec); - return ret; -} - -static int ffm_read_header(AVFormatContext *s) -{ - FFMContext *ffm = s->priv_data; - AVStream *st; - AVIOContext *pb = s->pb; - AVCodecContext *dummy_codec = NULL; - AVCodecParameters *codecpar; - const AVCodecDescriptor *codec_desc; - int i, nb_streams, ret; - uint32_t tag; - - /* header */ - tag = avio_rl32(pb); - if (tag == MKTAG('F', 'F', 'M', '2')) - return ffm2_read_header(s); - if (tag != MKTAG('F', 'F', 'M', '1')) { - ret = AVERROR_INVALIDDATA; - goto fail; - } - ffm->packet_size = avio_rb32(pb); - if (ffm->packet_size != FFM_PACKET_SIZE) { - ret = AVERROR_INVALIDDATA; - goto fail; - } - ffm->write_index = avio_rb64(pb); - /* get also filesize */ - if (pb->seekable & AVIO_SEEKABLE_NORMAL) { - ffm->file_size = avio_size(pb); - if (ffm->write_index && 0) - adjust_write_index(s); - } else { - ffm->file_size = (UINT64_C(1) << 63) - 1; - } - dummy_codec = avcodec_alloc_context3(NULL); - - nb_streams = avio_rb32(pb); - avio_rb32(pb); /* total bitrate */ - /* read each stream */ - for(i=0;icodecpar; - /* generic info */ - codecpar->codec_id = avio_rb32(pb); - codec_desc = avcodec_descriptor_get(codecpar->codec_id); - if (!codec_desc) { - av_log(s, AV_LOG_ERROR, "Invalid codec id: %d\n", codecpar->codec_id); - codecpar->codec_id = AV_CODEC_ID_NONE; - ret = AVERROR_INVALIDDATA; - goto fail; - } - codecpar->codec_type = avio_r8(pb); /* codec_type */ - if (codecpar->codec_type != codec_desc->type) { - av_log(s, AV_LOG_ERROR, "Codec type mismatch: expected %d, found %d\n", - codec_desc->type, codecpar->codec_type); - codecpar->codec_id = AV_CODEC_ID_NONE; - codecpar->codec_type = AVMEDIA_TYPE_UNKNOWN; - ret = AVERROR_INVALIDDATA; - goto fail; - } - codecpar->bit_rate = avio_rb32(pb); - if (codecpar->bit_rate < 0) { - av_log(s, AV_LOG_WARNING, "Invalid bit rate %"PRId64"\n", codecpar->bit_rate); - ret = AVERROR_INVALIDDATA; - goto fail; - } - flags = avio_rb32(pb); -#if FF_API_LAVF_AVCTX -FF_DISABLE_DEPRECATION_WARNINGS - st->codec->flags = flags; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - avio_rb32(pb); // flags2 - avio_rb32(pb); // debug - /* specific info */ - switch(codecpar->codec_type) { - case AVMEDIA_TYPE_VIDEO: - avio_rb32(pb); // time_base.num - avio_rb32(pb); // time_base.den - codecpar->width = avio_rb16(pb); - codecpar->height = avio_rb16(pb); - if ((ret = av_image_check_size(codecpar->width, codecpar->height, 0, s)) < 0) - goto fail; - avio_rb16(pb); // gop_size - codecpar->format = avio_rb32(pb); - if (!av_pix_fmt_desc_get(codecpar->format)) { - av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codecpar->format); - codecpar->format = AV_PIX_FMT_NONE; - ret = AVERROR_INVALIDDATA; - goto fail; - } - avio_r8(pb); // qmin - avio_r8(pb); // qmax - avio_r8(pb); // max_qdiff - avio_rb16(pb); // qcompress / 10000.0 - avio_rb16(pb); // qblur / 10000.0 - avio_rb32(pb); // bit_rate_tolerance - avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf)); - - avio_rb32(pb); // rc_max_rate - avio_rb32(pb); // rc_min_rate - avio_rb32(pb); // rc_buffer_size - avio_rb64(pb); // i_quant_factor - avio_rb64(pb); // b_quant_factor - avio_rb64(pb); // i_quant_offset - avio_rb64(pb); // b_quant_offset - avio_rb32(pb); // dct_algo - avio_rb32(pb); // strict_std_compliance - avio_rb32(pb); // max_b_frames - avio_rb32(pb); // mpeg_quant - avio_rb32(pb); // intra_dc_precision - avio_rb32(pb); // me_method - avio_rb32(pb); // mb_decision - avio_rb32(pb); // nsse_weight - avio_rb32(pb); // frame_skip_cmp - avio_rb64(pb); // rc_buffer_aggressivity - codecpar->codec_tag = avio_rb32(pb); - avio_r8(pb); // thread_count - avio_rb32(pb); // coder_type - avio_rb32(pb); // me_cmp - avio_rb32(pb); // me_subpel_quality - avio_rb32(pb); // me_range - avio_rb32(pb); // keyint_min - avio_rb32(pb); // scenechange_threshold - avio_rb32(pb); // b_frame_strategy - avio_rb64(pb); // qcompress - avio_rb64(pb); // qblur - avio_rb32(pb); // max_qdiff - avio_rb32(pb); // refs - break; - case AVMEDIA_TYPE_AUDIO: - codecpar->sample_rate = avio_rb32(pb); - VALIDATE_PARAMETER(sample_rate, "sample rate", codecpar->sample_rate < 0) - codecpar->channels = avio_rl16(pb); - VALIDATE_PARAMETER(channels, "number of channels", codecpar->channels < 0) - codecpar->frame_size = avio_rl16(pb); - VALIDATE_PARAMETER(frame_size, "frame size", codecpar->frame_size < 0) - break; - default: - ret = AVERROR_INVALIDDATA; - goto fail; - } - if (flags & AV_CODEC_FLAG_GLOBAL_HEADER) { - int size = avio_rb32(pb); - if (size < 0 || size >= FF_MAX_EXTRADATA_SIZE) { - av_log(s, AV_LOG_ERROR, "Invalid extradata size %d\n", size); - ret = AVERROR_INVALIDDATA; - goto fail; - } - codecpar->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!codecpar->extradata) { - ret = AVERROR(ENOMEM); - goto fail; - } - codecpar->extradata_size = size; - avio_read(pb, codecpar->extradata, size); - } - } - - /* get until end of block reached */ - while ((avio_tell(pb) % ffm->packet_size) != 0 && !pb->eof_reached) - avio_r8(pb); - - /* init packet demux */ - ffm->packet_ptr = ffm->packet; - ffm->packet_end = ffm->packet; - ffm->frame_offset = 0; - ffm->dts = 0; - ffm->read_state = READ_HEADER; - ffm->first_packet = 1; - avcodec_free_context(&dummy_codec); - return 0; - fail: - avcodec_free_context(&dummy_codec); - return ret; -} - -/* return < 0 if eof */ -static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt) -{ - int size; - FFMContext *ffm = s->priv_data; - int duration, ret; - - switch(ffm->read_state) { - case READ_HEADER: - if ((ret = ffm_is_avail_data(s, FRAME_HEADER_SIZE+4)) < 0) - return ret; - - ff_dlog(s, "pos=%08"PRIx64" spos=%"PRIx64", write_index=%"PRIx64" size=%"PRIx64"\n", - avio_tell(s->pb), s->pb->pos, ffm->write_index, ffm->file_size); - if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) != - FRAME_HEADER_SIZE) - return -1; - if (ffm->header[1] & FLAG_DTS) - if (ffm_read_data(s, ffm->header+16, 4, 1) != 4) - return -1; - ffm->read_state = READ_DATA; - /* fall through */ - case READ_DATA: - size = AV_RB24(ffm->header + 2); - if ((ret = ffm_is_avail_data(s, size)) < 0) - return ret; - - duration = AV_RB24(ffm->header + 5); - - if (av_new_packet(pkt, size) < 0) { - return AVERROR(ENOMEM); - } - pkt->stream_index = ffm->header[0]; - if ((unsigned)pkt->stream_index >= s->nb_streams) { - av_log(s, AV_LOG_ERROR, "invalid stream index %d\n", pkt->stream_index); - av_packet_unref(pkt); - ffm->read_state = READ_HEADER; - return -1; - } - pkt->pos = avio_tell(s->pb); - if (ffm->header[1] & FLAG_KEY_FRAME) - pkt->flags |= AV_PKT_FLAG_KEY; - - ffm->read_state = READ_HEADER; - if (ffm_read_data(s, pkt->data, size, 0) != size) { - /* bad case: desynchronized packet. we cancel all the packet loading */ - av_packet_unref(pkt); - return -1; - } - pkt->pts = AV_RB64(ffm->header+8); - if (ffm->header[1] & FLAG_DTS) - pkt->dts = pkt->pts - AV_RB32(ffm->header+16); - else - pkt->dts = pkt->pts; - pkt->duration = duration; - break; - } - return 0; -} - -/* seek to a given time in the file. The file read pointer is - positioned at or before pts. XXX: the following code is quite - approximative */ -static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, int flags) -{ - FFMContext *ffm = s->priv_data; - int64_t pos_min, pos_max, pos; - int64_t pts_min, pts_max, pts; - double pos1; - - ff_dlog(s, "wanted_pts=%0.6f\n", wanted_pts / 1000000.0); - /* find the position using linear interpolation (better than - dichotomy in typical cases) */ - if (ffm->write_index && ffm->write_index < ffm->file_size) { - if (get_dts(s, FFM_PACKET_SIZE) < wanted_pts) { - pos_min = FFM_PACKET_SIZE; - pos_max = ffm->write_index - FFM_PACKET_SIZE; - } else { - pos_min = ffm->write_index; - pos_max = ffm->file_size - FFM_PACKET_SIZE; - } - } else { - pos_min = FFM_PACKET_SIZE; - pos_max = ffm->file_size - FFM_PACKET_SIZE; - } - while (pos_min <= pos_max) { - pts_min = get_dts(s, pos_min); - pts_max = get_dts(s, pos_max); - if (pts_min > wanted_pts || pts_max <= wanted_pts) { - pos = pts_min > wanted_pts ? pos_min : pos_max; - goto found; - } - /* linear interpolation */ - pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) / - (double)(pts_max - pts_min); - pos = (((int64_t)pos1) / FFM_PACKET_SIZE) * FFM_PACKET_SIZE; - if (pos <= pos_min) - pos = pos_min; - else if (pos >= pos_max) - pos = pos_max; - pts = get_dts(s, pos); - /* check if we are lucky */ - if (pts == wanted_pts) { - goto found; - } else if (pts > wanted_pts) { - pos_max = pos - FFM_PACKET_SIZE; - } else { - pos_min = pos + FFM_PACKET_SIZE; - } - } - pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max; - - found: - if (ffm_seek1(s, pos) < 0) - return -1; - - /* reset read state */ - ffm->read_state = READ_HEADER; - ffm->packet_ptr = ffm->packet; - ffm->packet_end = ffm->packet; - ffm->first_packet = 1; - - return 0; -} - -static int ffm_probe(AVProbeData *p) -{ - if ( - p->buf[0] == 'F' && p->buf[1] == 'F' && p->buf[2] == 'M' && - (p->buf[3] == '1' || p->buf[3] == '2')) - return AVPROBE_SCORE_MAX + 1; - return 0; -} - -static const AVOption options[] = { - {"server_attached", NULL, offsetof(FFMContext, server_attached), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_EXPORT }, - {"ffm_write_index", NULL, offsetof(FFMContext, write_index), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, AV_OPT_FLAG_EXPORT }, - {"ffm_file_size", NULL, offsetof(FFMContext, file_size), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, AV_OPT_FLAG_EXPORT }, - { NULL }, -}; - -static const AVClass ffm_class = { - .class_name = "ffm demuxer", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; -AVInputFormat ff_ffm_demuxer = { - .name = "ffm", - .long_name = NULL_IF_CONFIG_SMALL("FFM (FFserver live feed)"), - .priv_data_size = sizeof(FFMContext), - .read_probe = ffm_probe, - .read_header = ffm_read_header, - .read_packet = ffm_read_packet, - .read_seek = ffm_seek, - .priv_class = &ffm_class, -}; diff --git a/libavformat/ffmenc.c b/libavformat/ffmenc.c deleted file mode 100644 index ef7dc3a03113a..0000000000000 --- a/libavformat/ffmenc.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * FFM (ffserver live feed) muxer - * Copyright (c) 2001 Fabrice Bellard - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/intreadwrite.h" -#include "libavutil/intfloat.h" -#include "libavutil/avassert.h" -#include "libavutil/parseutils.h" -#include "libavutil/opt.h" -#include "avformat.h" -#include "avio_internal.h" -#include "internal.h" -#include "ffm.h" - -static void flush_packet(AVFormatContext *s) -{ - FFMContext *ffm = s->priv_data; - int fill_size, h; - AVIOContext *pb = s->pb; - - fill_size = ffm->packet_end - ffm->packet_ptr; - memset(ffm->packet_ptr, 0, fill_size); - - av_assert1(avio_tell(pb) % ffm->packet_size == 0); - - /* put header */ - avio_wb16(pb, PACKET_ID); - avio_wb16(pb, fill_size); - avio_wb64(pb, ffm->dts); - h = ffm->frame_offset; - if (ffm->first_packet) - h |= 0x8000; - avio_wb16(pb, h); - avio_write(pb, ffm->packet, ffm->packet_end - ffm->packet); - avio_flush(pb); - - /* prepare next packet */ - ffm->frame_offset = 0; /* no key frame */ - ffm->packet_ptr = ffm->packet; - ffm->first_packet = 0; -} - -/* 'first' is true if first data of a frame */ -static void ffm_write_data(AVFormatContext *s, - const uint8_t *buf, int size, - int64_t dts, int header) -{ - FFMContext *ffm = s->priv_data; - int len; - - if (header && ffm->frame_offset == 0) { - ffm->frame_offset = ffm->packet_ptr - ffm->packet + FFM_HEADER_SIZE; - ffm->dts = dts; - } - - /* write as many packets as needed */ - while (size > 0) { - len = ffm->packet_end - ffm->packet_ptr; - if (len > size) - len = size; - memcpy(ffm->packet_ptr, buf, len); - - ffm->packet_ptr += len; - buf += len; - size -= len; - if (ffm->packet_ptr >= ffm->packet_end) - flush_packet(s); - } -} - -static void write_header_chunk(AVIOContext *pb, AVIOContext *dpb, unsigned id) -{ - uint8_t *dyn_buf; - int dyn_size= avio_close_dyn_buf(dpb, &dyn_buf); - avio_wb32(pb, id); - avio_wb32(pb, dyn_size); - avio_write(pb, dyn_buf, dyn_size); - av_free(dyn_buf); -} - -static int ffm_write_header_codec_ctx(AVIOContext *pb, AVCodecParameters *ctxpar, unsigned tag, int type) -{ - AVIOContext *tmp; - char *buf = NULL; - int ret, need_coma = 0; - AVCodecContext *ctx = NULL; - -#define SKIP_DEFAULTS AV_OPT_SERIALIZE_SKIP_DEFAULTS -#define OPT_FLAGS_EXACT AV_OPT_SERIALIZE_OPT_FLAGS_EXACT -#define ENC AV_OPT_FLAG_ENCODING_PARAM - - if (avio_open_dyn_buf(&tmp) < 0) - return AVERROR(ENOMEM); - - // AVCodecParameters does not suport AVOptions, we thus must copy it over to a context that does - // otherwise it could be used directly and this would be much simpler - ctx = avcodec_alloc_context3(NULL); - if (!ctx) { - ret = AVERROR(ENOMEM); - goto fail; - } - avcodec_parameters_to_context(ctx, ctxpar); - - if ((ret = av_opt_serialize(ctx, ENC | type, SKIP_DEFAULTS, &buf, '=', ',')) < 0) - goto fail; - if (buf && strlen(buf)) { - avio_write(tmp, buf, strlen(buf)); - av_freep(&buf); - need_coma = 1; - } - if ((ret = av_opt_serialize(ctx, 0, SKIP_DEFAULTS | OPT_FLAGS_EXACT, &buf, '=', ',')) < 0) - goto fail; - if (buf && strlen(buf)) { - if (need_coma) - avio_w8(tmp, ','); - avio_write(tmp, buf, strlen(buf)); - } - av_freep(&buf); - avio_w8(tmp, 0); - write_header_chunk(pb, tmp, tag); - avcodec_free_context(&ctx); - return 0; - fail: - av_free(buf); - ffio_free_dyn_buf(&tmp); - avcodec_free_context(&ctx); - return ret; - -#undef SKIP_DEFAULTS -#undef OPT_FLAGS_EXACT -#undef ENC -} - -static int ffm_write_recommended_config(AVIOContext *pb, AVCodecParameters *codecpar, unsigned tag, - const char *configuration) -{ - int ret; - const AVCodec *enc = avcodec_find_encoder(codecpar->codec_id); - AVIOContext *tmp; - AVDictionaryEntry *t = NULL; - AVDictionary *all = NULL, *comm = NULL, *prv = NULL; - char *buf = NULL; - - if (!enc || !enc->priv_class || !enc->priv_data_size) { - /* codec is not known/has no private options, so save everything as common options */ - if (avio_open_dyn_buf(&tmp) < 0) - return AVERROR(ENOMEM); - avio_put_str(tmp, configuration); - write_header_chunk(pb, tmp, tag); - return 0; - } - - if ((ret = av_dict_parse_string(&all, configuration, "=", ",", 0)) < 0) - return ret; - - while ((t = av_dict_get(all, "", t, AV_DICT_IGNORE_SUFFIX))) { - if (av_opt_find((void *)&enc->priv_class, t->key, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)) { - if ((ret = av_dict_set(&prv, t->key, t->value, 0)) < 0) - goto fail; - } else if ((ret = av_dict_set(&comm, t->key, t->value, 0)) < 0) - goto fail; - } - - if (comm) { - if ((ret = av_dict_get_string(comm, &buf, '=', ',')) < 0 || - (ret = avio_open_dyn_buf(&tmp)) < 0) - goto fail; - avio_put_str(tmp, buf); - av_freep(&buf); - write_header_chunk(pb, tmp, tag); - } - if (prv) { - if ((ret = av_dict_get_string(prv, &buf, '=', ',')) < 0 || - (ret = avio_open_dyn_buf(&tmp)) < 0) - goto fail; - avio_put_str(tmp, buf); - write_header_chunk(pb, tmp, MKBETAG('C', 'P', 'R', 'V')); - } - - fail: - av_free(buf); - av_dict_free(&all); - av_dict_free(&comm); - av_dict_free(&prv); - return ret; -} - -static int ffm_write_header(AVFormatContext *s) -{ - FFMContext *ffm = s->priv_data; - AVStream *st; - AVIOContext *pb = s->pb; - AVCodecParameters *codecpar; - int bit_rate, i, ret; - - if ((ret = ff_parse_creation_time_metadata(s, &ffm->start_time, 0)) < 0) - return ret; - - ffm->packet_size = FFM_PACKET_SIZE; - - /* header */ - avio_wl32(pb, MKTAG('F', 'F', 'M', '2')); - avio_wb32(pb, ffm->packet_size); - avio_wb64(pb, 0); /* current write position */ - - if(avio_open_dyn_buf(&pb) < 0) - return AVERROR(ENOMEM); - - avio_wb32(pb, s->nb_streams); - bit_rate = 0; - for(i=0;inb_streams;i++) { - st = s->streams[i]; - bit_rate += st->codecpar->bit_rate; - } - avio_wb32(pb, bit_rate); - - write_header_chunk(s->pb, pb, MKBETAG('M', 'A', 'I', 'N')); - - /* list of streams */ - for(i=0;inb_streams;i++) { - int flags = 0; - st = s->streams[i]; - avpriv_set_pts_info(st, 64, 1, 1000000); - if(avio_open_dyn_buf(&pb) < 0) - return AVERROR(ENOMEM); - - codecpar = st->codecpar; - /* generic info */ - avio_wb32(pb, codecpar->codec_id); - avio_w8(pb, codecpar->codec_type); - avio_wb32(pb, codecpar->bit_rate); - if (codecpar->extradata_size) - flags |= AV_CODEC_FLAG_GLOBAL_HEADER; - - // If the user is not providing us with a configuration we have to fill it in as we cannot access the encoder - if (!st->recommended_encoder_configuration) { - if (s->flags & AVFMT_FLAG_BITEXACT) - flags |= AV_CODEC_FLAG_BITEXACT; - } - - avio_wb32(pb, flags); - avio_wb32(pb, 0); // flags2 - avio_wb32(pb, 0); // debug - if (codecpar->extradata_size) { - avio_wb32(pb, codecpar->extradata_size); - avio_write(pb, codecpar->extradata, codecpar->extradata_size); - } - write_header_chunk(s->pb, pb, MKBETAG('C', 'O', 'M', 'M')); - /* specific info */ - switch(codecpar->codec_type) { - case AVMEDIA_TYPE_VIDEO: - if (st->recommended_encoder_configuration) { - av_log(NULL, AV_LOG_DEBUG, "writing recommended configuration: %s\n", - st->recommended_encoder_configuration); - if ((ret = ffm_write_recommended_config(s->pb, codecpar, MKBETAG('S', '2', 'V', 'I'), - st->recommended_encoder_configuration)) < 0) - return ret; - } else if ((ret = ffm_write_header_codec_ctx(s->pb, codecpar, MKBETAG('S', '2', 'V', 'I'), AV_OPT_FLAG_VIDEO_PARAM)) < 0) - return ret; - break; - case AVMEDIA_TYPE_AUDIO: - if (st->recommended_encoder_configuration) { - av_log(NULL, AV_LOG_DEBUG, "writing recommended configuration: %s\n", - st->recommended_encoder_configuration); - if ((ret = ffm_write_recommended_config(s->pb, codecpar, MKBETAG('S', '2', 'A', 'U'), - st->recommended_encoder_configuration)) < 0) - return ret; - } else if ((ret = ffm_write_header_codec_ctx(s->pb, codecpar, MKBETAG('S', '2', 'A', 'U'), AV_OPT_FLAG_AUDIO_PARAM)) < 0) - return ret; - break; - default: - return -1; - } - } - pb = s->pb; - - avio_wb64(pb, 0); // end of header - - /* flush until end of block reached */ - while ((avio_tell(pb) % ffm->packet_size) != 0) - avio_w8(pb, 0); - - avio_flush(pb); - - /* init packet mux */ - ffm->packet_ptr = ffm->packet; - ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE; - av_assert0(ffm->packet_end >= ffm->packet); - ffm->frame_offset = 0; - ffm->dts = 0; - ffm->first_packet = 1; - - return 0; -} - -static int ffm_write_packet(AVFormatContext *s, AVPacket *pkt) -{ - FFMContext *ffm = s->priv_data; - int64_t dts; - uint8_t header[FRAME_HEADER_SIZE+4]; - int header_size = FRAME_HEADER_SIZE; - - dts = ffm->start_time + pkt->dts; - /* packet size & key_frame */ - header[0] = pkt->stream_index; - header[1] = 0; - if (pkt->flags & AV_PKT_FLAG_KEY) - header[1] |= FLAG_KEY_FRAME; - AV_WB24(header+2, pkt->size); - AV_WB24(header+5, pkt->duration); - AV_WB64(header+8, ffm->start_time + pkt->pts); - if (pkt->pts != pkt->dts) { - header[1] |= FLAG_DTS; - AV_WB32(header+16, pkt->pts - pkt->dts); - header_size += 4; - } - ffm_write_data(s, header, header_size, dts, 1); - ffm_write_data(s, pkt->data, pkt->size, dts, 0); - - return 0; -} - -static int ffm_write_trailer(AVFormatContext *s) -{ - FFMContext *ffm = s->priv_data; - - /* flush packets */ - if (ffm->packet_ptr > ffm->packet) - flush_packet(s); - - return 0; -} - -AVOutputFormat ff_ffm_muxer = { - .name = "ffm", - .long_name = NULL_IF_CONFIG_SMALL("FFM (FFserver live feed)"), - .extensions = "ffm", - .priv_data_size = sizeof(FFMContext), - .audio_codec = AV_CODEC_ID_MP2, - .video_codec = AV_CODEC_ID_MPEG1VIDEO, - .write_header = ffm_write_header, - .write_packet = ffm_write_packet, - .write_trailer = ffm_write_trailer, - .flags = AVFMT_TS_NEGATIVE, -}; From 9396ed0f291509e62235e12cd064d5b13b2473c2 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 21 Oct 2017 19:40:50 +0100 Subject: [PATCH 1575/2557] libavformat: unexpose the ff_inet_aton function Used only by ffserver. Signed-off-by: Rostislav Pehlivanov --- libavformat/libavformat.v | 1 - libavformat/network.h | 2 -- libavformat/os_support.c | 6 +++--- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/libavformat/libavformat.v b/libavformat/libavformat.v index 291a38f8e7714..e838f2918adf4 100644 --- a/libavformat/libavformat.v +++ b/libavformat/libavformat.v @@ -2,7 +2,6 @@ LIBAVFORMAT_MAJOR { global: av*; #FIXME those are for ffserver - ff_inet_aton; ff_socket_nonblock; ff_rtsp_parse_line; ff_rtp_get_local_rtp_port; diff --git a/libavformat/network.h b/libavformat/network.h index a663115541864..3c0f8732799fe 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -105,8 +105,6 @@ int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterrupt */ int ff_network_sleep_interruptible(int64_t timeout, AVIOInterruptCB *int_cb); -int ff_inet_aton (const char * str, struct in_addr * add); - #if !HAVE_STRUCT_SOCKADDR_STORAGE struct sockaddr_storage { #if HAVE_STRUCT_SOCKADDR_SA_LEN diff --git a/libavformat/os_support.c b/libavformat/os_support.c index 47445854c61b0..6bdfc0409784a 100644 --- a/libavformat/os_support.c +++ b/libavformat/os_support.c @@ -46,7 +46,7 @@ #if !HAVE_INET_ATON #include -int ff_inet_aton(const char *str, struct in_addr *add) +static int inet_aton(const char *str, struct in_addr *add) { unsigned int add1 = 0, add2 = 0, add3 = 0, add4 = 0; @@ -61,7 +61,7 @@ int ff_inet_aton(const char *str, struct in_addr *add) return 1; } #else -int ff_inet_aton(const char *str, struct in_addr *add) +static int inet_aton(const char *str, struct in_addr *add) { return inet_aton(str, add); } @@ -82,7 +82,7 @@ int ff_getaddrinfo(const char *node, const char *service, sin->sin_family = AF_INET; if (node) { - if (!ff_inet_aton(node, &sin->sin_addr)) { + if (!inet_aton(node, &sin->sin_addr)) { if (hints && (hints->ai_flags & AI_NUMERICHOST)) { av_free(sin); return EAI_FAIL; From d41de90d440ae389262e13fb6c4dc3fdf7261b57 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 21 Oct 2017 19:45:09 +0100 Subject: [PATCH 1576/2557] libavformat: remove the ff_rtp_get_local_rtcp_port function Only used by ffserver Signed-off-by: Rostislav Pehlivanov --- libavformat/libavformat.v | 1 - libavformat/rtpproto.c | 6 ------ libavformat/rtpproto.h | 1 - 3 files changed, 8 deletions(-) diff --git a/libavformat/libavformat.v b/libavformat/libavformat.v index e838f2918adf4..42b3e0c8e283c 100644 --- a/libavformat/libavformat.v +++ b/libavformat/libavformat.v @@ -5,7 +5,6 @@ LIBAVFORMAT_MAJOR { ff_socket_nonblock; ff_rtsp_parse_line; ff_rtp_get_local_rtp_port; - ff_rtp_get_local_rtcp_port; ffio_open_dyn_packet_buf; ffio_set_buf_size; ffurl_close; diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index 0706cae25f379..c01d9cea183ad 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -636,12 +636,6 @@ int ff_rtp_get_local_rtp_port(URLContext *h) * @return the local port number */ -int ff_rtp_get_local_rtcp_port(URLContext *h) -{ - RTPContext *s = h->priv_data; - return ff_udp_get_local_port(s->rtcp_hd); -} - static int rtp_get_file_handle(URLContext *h) { RTPContext *s = h->priv_data; diff --git a/libavformat/rtpproto.h b/libavformat/rtpproto.h index 5b243fb2486b8..131aac5f3c461 100644 --- a/libavformat/rtpproto.h +++ b/libavformat/rtpproto.h @@ -26,6 +26,5 @@ int ff_rtp_set_remote_url(URLContext *h, const char *uri); int ff_rtp_get_local_rtp_port(URLContext *h); -int ff_rtp_get_local_rtcp_port(URLContext *h); #endif /* AVFORMAT_RTPPROTO_H */ From 8788e82c04fee409d6b56751a0925d4ee17d2f68 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 6 Jan 2018 18:37:06 +0000 Subject: [PATCH 1577/2557] libavformat: unexpose private ff_ functions needed by ffserver Signed-off-by: Rostislav Pehlivanov --- libavformat/libavformat.v | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libavformat/libavformat.v b/libavformat/libavformat.v index 42b3e0c8e283c..47d5ddcdb13e3 100644 --- a/libavformat/libavformat.v +++ b/libavformat/libavformat.v @@ -1,15 +1,6 @@ LIBAVFORMAT_MAJOR { global: av*; - #FIXME those are for ffserver - ff_socket_nonblock; - ff_rtsp_parse_line; - ff_rtp_get_local_rtp_port; - ffio_open_dyn_packet_buf; - ffio_set_buf_size; - ffurl_close; - ffurl_open; - ffurl_write; local: *; }; From 7c6125cbcc6e805711feff9cbf35329adcb6e313 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 21 Oct 2017 19:52:04 +0100 Subject: [PATCH 1578/2557] libavformat/mpjpeg: use "ffmpeg" instead of "ffserver" as boundary tag Signed-off-by: Rostislav Pehlivanov --- libavformat/mpjpeg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mpjpeg.c b/libavformat/mpjpeg.c index 3904ccb2b43f3..80f83c58719d6 100644 --- a/libavformat/mpjpeg.c +++ b/libavformat/mpjpeg.c @@ -23,7 +23,7 @@ /* Multipart JPEG */ -#define BOUNDARY_TAG "ffserver" +#define BOUNDARY_TAG "ffmpeg" typedef struct MPJPEGContext { AVClass *class; From c693af1951a0074a29ce39b69736ff0cf33b41d2 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 6 Jan 2018 18:59:46 +0000 Subject: [PATCH 1579/2557] libavformat/network: fix function duplication Since the function used to be exposed for ffserver's sake, it was renamed to the same name as a system's aton function which caused a collision. Signed-off-by: Rostislav Pehlivanov --- libavformat/os_support.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libavformat/os_support.c b/libavformat/os_support.c index 6bdfc0409784a..099d7b501f439 100644 --- a/libavformat/os_support.c +++ b/libavformat/os_support.c @@ -60,11 +60,6 @@ static int inet_aton(const char *str, struct in_addr *add) return 1; } -#else -static int inet_aton(const char *str, struct in_addr *add) -{ - return inet_aton(str, add); -} #endif /* !HAVE_INET_ATON */ #if !HAVE_GETADDRINFO From 8bbd8c8d52dbcb15773717d3512f8fb68e860bf2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 6 Jan 2018 16:14:52 -0300 Subject: [PATCH 1580/2557] fate: remove missing references to ffm Missed in c17f4761443b471f47fa8f0a5bcff078cdff9479. Signed-off-by: James Almer --- tests/fate/avformat.mak | 1 - tests/fate/seek.mak | 2 -- 2 files changed, 3 deletions(-) diff --git a/tests/fate/avformat.mak b/tests/fate/avformat.mak index c9ea99ad1b1fa..a12f9ccc71169 100644 --- a/tests/fate/avformat.mak +++ b/tests/fate/avformat.mak @@ -9,7 +9,6 @@ FATE_LAVF-$(call ENCDEC, BMP, IMAGE2) += bmp FATE_LAVF-$(call ENCDEC, PCM_S16BE, CAF) += caf FATE_LAVF-$(call ENCDEC, DPX, IMAGE2) += dpx FATE_LAVF-$(call ENCDEC2, DVVIDEO, PCM_S16LE, AVI) += dv_fmt -FATE_LAVF-$(call ENCDEC2, MPEG1VIDEO, MP2, FFM) += ffm FATE_LAVF-$(call ENCDEC, FITS, FITS) += fits FATE_LAVF-$(call ENCDEC, RAWVIDEO, FILMSTRIP) += flm FATE_LAVF-$(call ENCDEC, FLV, FLV) += flv_fmt diff --git a/tests/fate/seek.mak b/tests/fate/seek.mak index c863b2aaa454b..751873baa4ede 100644 --- a/tests/fate/seek.mak +++ b/tests/fate/seek.mak @@ -168,7 +168,6 @@ FATE_SEEK_LAVF-$(call ENCDEC, PCM_S16BE, AU) += au FATE_SEEK_LAVF-$(call ENCDEC2, MPEG4, MP2, AVI) += avi FATE_SEEK_LAVF-$(call ENCDEC, BMP, IMAGE2) += bmp FATE_SEEK_LAVF-$(call ENCDEC2, DVVIDEO, PCM_S16LE, AVI) += dv_fmt -FATE_SEEK_LAVF-$(call ENCDEC2, MPEG1VIDEO, MP2, FFM) += ffm FATE_SEEK_LAVF-$(call ENCDEC, FLV, FLV) += flv_fmt FATE_SEEK_LAVF-$(call ENCDEC, GIF, IMAGE2) += gif FATE_SEEK_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, GXF) += gxf @@ -210,7 +209,6 @@ fate-seek-lavf-au: SRC = lavf/lavf.au fate-seek-lavf-avi: SRC = lavf/lavf.avi fate-seek-lavf-bmp: SRC = images/bmp/%02d.bmp fate-seek-lavf-dv_fmt: SRC = lavf/lavf.dv -fate-seek-lavf-ffm: SRC = lavf/lavf.ffm fate-seek-lavf-flv_fmt: SRC = lavf/lavf.flv fate-seek-lavf-gif: SRC = lavf/lavf.gif fate-seek-lavf-gxf: SRC = lavf/lavf.gxf From 9d9835017f67db7e37b6b5a42a247e17b05bf8fc Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Thu, 28 Dec 2017 17:33:14 -0800 Subject: [PATCH 1581/2557] lavc/mediacodecdec: switch to new decoding API Using the new API gives the decoder the ability to produce N frames per input packet. This is particularly useful with mpeg2 decoders on some android devices, which automatically deinterlace video and produce one frame per field. Signed-off-by: Aman Gupta Signed-off-by: Matthieu Bouron --- libavcodec/mediacodecdec.c | 80 +++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index b698ceaef92df..35a9e34861021 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -31,6 +31,7 @@ #include "libavutil/pixfmt.h" #include "avcodec.h" +#include "decode.h" #include "h264_parse.h" #include "hevc_parse.h" #include "hwaccel.h" @@ -424,29 +425,13 @@ static int mediacodec_process_data(AVCodecContext *avctx, AVFrame *frame, return ff_mediacodec_dec_decode(avctx, s->ctx, frame, got_frame, pkt); } -static int mediacodec_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame, AVPacket *avpkt) +static int mediacodec_receive_frame(AVCodecContext *avctx, AVFrame *frame) { MediaCodecH264DecContext *s = avctx->priv_data; - AVFrame *frame = data; int ret; - - /* buffer the input packet */ - if (avpkt->size) { - AVPacket input_pkt = { 0 }; - - if (av_fifo_space(s->fifo) < sizeof(input_pkt)) { - ret = av_fifo_realloc2(s->fifo, - av_fifo_size(s->fifo) + sizeof(input_pkt)); - if (ret < 0) - return ret; - } - - ret = av_packet_ref(&input_pkt, avpkt); - if (ret < 0) - return ret; - av_fifo_generic_write(s->fifo, &input_pkt, sizeof(input_pkt), NULL); - } + int got_frame = 0; + int is_eof = 0; + AVPacket pkt = { 0 }; /* * MediaCodec.flush() discards both input and output buffers, thus we @@ -470,26 +455,57 @@ static int mediacodec_decode_frame(AVCodecContext *avctx, void *data, */ if (ff_mediacodec_dec_is_flushing(avctx, s->ctx)) { if (!ff_mediacodec_dec_flush(avctx, s->ctx)) { - return avpkt->size; + return AVERROR(EAGAIN); } } + ret = ff_decode_get_packet(avctx, &pkt); + if (ret == AVERROR_EOF) + is_eof = 1; + else if (ret == AVERROR(EAGAIN)) + ; /* no input packet, but fallthrough to check for pending frames */ + else if (ret < 0) + return ret; + + /* buffer the input packet */ + if (pkt.size) { + if (av_fifo_space(s->fifo) < sizeof(pkt)) { + ret = av_fifo_realloc2(s->fifo, + av_fifo_size(s->fifo) + sizeof(pkt)); + if (ret < 0) { + av_packet_unref(&pkt); + return ret; + } + } + av_fifo_generic_write(s->fifo, &pkt, sizeof(pkt), NULL); + } + /* process buffered data */ - while (!*got_frame) { + while (!got_frame) { /* prepare the input data */ if (s->buffered_pkt.size <= 0) { av_packet_unref(&s->buffered_pkt); /* no more data */ if (av_fifo_size(s->fifo) < sizeof(AVPacket)) { - return avpkt->size ? avpkt->size : - ff_mediacodec_dec_decode(avctx, s->ctx, frame, got_frame, avpkt); + AVPacket null_pkt = { 0 }; + if (is_eof) { + ret = ff_mediacodec_dec_decode(avctx, s->ctx, frame, + &got_frame, &null_pkt); + if (ret < 0) + return ret; + else if (got_frame) + return 0; + else + return AVERROR_EOF; + } + return AVERROR(EAGAIN); } av_fifo_generic_read(s->fifo, &s->buffered_pkt, sizeof(s->buffered_pkt), NULL); } - ret = mediacodec_process_data(avctx, frame, got_frame, &s->buffered_pkt); + ret = mediacodec_process_data(avctx, frame, &got_frame, &s->buffered_pkt); if (ret < 0) return ret; @@ -497,7 +513,7 @@ static int mediacodec_decode_frame(AVCodecContext *avctx, void *data, s->buffered_pkt.data += ret; } - return avpkt->size; + return 0; } static void mediacodec_decode_flush(AVCodecContext *avctx) @@ -537,7 +553,7 @@ AVCodec ff_h264_mediacodec_decoder = { .id = AV_CODEC_ID_H264, .priv_data_size = sizeof(MediaCodecH264DecContext), .init = mediacodec_decode_init, - .decode = mediacodec_decode_frame, + .receive_frame = mediacodec_receive_frame, .flush = mediacodec_decode_flush, .close = mediacodec_decode_close, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, @@ -556,7 +572,7 @@ AVCodec ff_hevc_mediacodec_decoder = { .id = AV_CODEC_ID_HEVC, .priv_data_size = sizeof(MediaCodecH264DecContext), .init = mediacodec_decode_init, - .decode = mediacodec_decode_frame, + .receive_frame = mediacodec_receive_frame, .flush = mediacodec_decode_flush, .close = mediacodec_decode_close, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, @@ -575,7 +591,7 @@ AVCodec ff_mpeg2_mediacodec_decoder = { .id = AV_CODEC_ID_MPEG2VIDEO, .priv_data_size = sizeof(MediaCodecH264DecContext), .init = mediacodec_decode_init, - .decode = mediacodec_decode_frame, + .receive_frame = mediacodec_receive_frame, .flush = mediacodec_decode_flush, .close = mediacodec_decode_close, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, @@ -593,7 +609,7 @@ AVCodec ff_mpeg4_mediacodec_decoder = { .id = AV_CODEC_ID_MPEG4, .priv_data_size = sizeof(MediaCodecH264DecContext), .init = mediacodec_decode_init, - .decode = mediacodec_decode_frame, + .receive_frame = mediacodec_receive_frame, .flush = mediacodec_decode_flush, .close = mediacodec_decode_close, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, @@ -611,7 +627,7 @@ AVCodec ff_vp8_mediacodec_decoder = { .id = AV_CODEC_ID_VP8, .priv_data_size = sizeof(MediaCodecH264DecContext), .init = mediacodec_decode_init, - .decode = mediacodec_decode_frame, + .receive_frame = mediacodec_receive_frame, .flush = mediacodec_decode_flush, .close = mediacodec_decode_close, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, @@ -629,7 +645,7 @@ AVCodec ff_vp9_mediacodec_decoder = { .id = AV_CODEC_ID_VP9, .priv_data_size = sizeof(MediaCodecH264DecContext), .init = mediacodec_decode_init, - .decode = mediacodec_decode_frame, + .receive_frame = mediacodec_receive_frame, .flush = mediacodec_decode_flush, .close = mediacodec_decode_close, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, From d19174c673b8788de825a936d8d7c9340aefcd56 Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Wed, 3 Jan 2018 13:10:58 +0100 Subject: [PATCH 1582/2557] lavc/mediacodecdec: remove mediacodec_process_data() indirection --- libavcodec/mediacodecdec.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 35a9e34861021..6c5d3ddd799a4 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -416,15 +416,6 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx) return ret; } - -static int mediacodec_process_data(AVCodecContext *avctx, AVFrame *frame, - int *got_frame, AVPacket *pkt) -{ - MediaCodecH264DecContext *s = avctx->priv_data; - - return ff_mediacodec_dec_decode(avctx, s->ctx, frame, got_frame, pkt); -} - static int mediacodec_receive_frame(AVCodecContext *avctx, AVFrame *frame) { MediaCodecH264DecContext *s = avctx->priv_data; @@ -505,7 +496,7 @@ static int mediacodec_receive_frame(AVCodecContext *avctx, AVFrame *frame) av_fifo_generic_read(s->fifo, &s->buffered_pkt, sizeof(s->buffered_pkt), NULL); } - ret = mediacodec_process_data(avctx, frame, &got_frame, &s->buffered_pkt); + ret = ff_mediacodec_dec_decode(avctx, s->ctx, frame, &got_frame, &s->buffered_pkt); if (ret < 0) return ret; From e30b46b1aeea03fc5cbcecc03f7103cf204090f0 Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Wed, 3 Jan 2018 13:54:34 +0100 Subject: [PATCH 1583/2557] lavc/mediacodec_wrapper: allocate MediaCodec.BufferInfo once --- libavcodec/mediacodec_wrapper.c | 61 ++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c index d9f0e27a7d894..dbc37bf4639bf 100644 --- a/libavcodec/mediacodec_wrapper.c +++ b/libavcodec/mediacodec_wrapper.c @@ -274,6 +274,7 @@ struct FFAMediaCodec { struct JNIAMediaCodecFields jfields; jobject object; + jobject buffer_info; jobject input_buffers; jobject output_buffers; @@ -1143,6 +1144,7 @@ static inline FFAMediaCodec *codec_create(int method, const char *arg) FFAMediaCodec *codec = NULL; jstring jarg = NULL; jobject object = NULL; + jobject buffer_info = NULL; jmethodID create_id = NULL; codec = av_mallocz(sizeof(FFAMediaCodec)); @@ -1195,6 +1197,16 @@ static inline FFAMediaCodec *codec_create(int method, const char *arg) codec->has_get_i_o_buffer = 1; } + buffer_info = (*env)->NewObject(env, codec->jfields.mediainfo_class, codec->jfields.init_id); + if (ff_jni_exception_check(env, 1, codec) < 0) { + goto fail; + } + + codec->buffer_info = (*env)->NewGlobalRef(env, buffer_info); + if (!codec->buffer_info) { + goto fail; + } + ret = 0; fail: if (jarg) { @@ -1205,10 +1217,19 @@ static inline FFAMediaCodec *codec_create(int method, const char *arg) (*env)->DeleteLocalRef(env, object); } + if (buffer_info) { + (*env)->DeleteLocalRef(env, buffer_info); + } + if (ret < 0) { if (codec->object) { (*env)->DeleteGlobalRef(env, codec->object); } + + if (codec->buffer_info) { + (*env)->DeleteGlobalRef(env, codec->buffer_info); + } + ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec); av_freep(&codec); } @@ -1246,6 +1267,9 @@ int ff_AMediaCodec_delete(FFAMediaCodec* codec) (*env)->DeleteGlobalRef(env, codec->object); codec->object = NULL; + (*env)->DeleteGlobalRef(env, codec->buffer_info); + codec->buffer_info = NULL; + ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec); av_freep(&codec); @@ -1413,48 +1437,31 @@ ssize_t ff_AMediaCodec_dequeueOutputBuffer(FFAMediaCodec* codec, FFAMediaCodecBu int ret = 0; JNIEnv *env = NULL; - jobject mediainfo = NULL; - JNI_GET_ENV_OR_RETURN(env, codec, AVERROR_EXTERNAL); - mediainfo = (*env)->NewObject(env, codec->jfields.mediainfo_class, codec->jfields.init_id); + ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_output_buffer_id, codec->buffer_info, timeoutUs); if (ff_jni_exception_check(env, 1, codec) < 0) { - ret = AVERROR_EXTERNAL; - goto fail; + return AVERROR_EXTERNAL; } - ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_output_buffer_id, mediainfo, timeoutUs); + info->flags = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.flags_id); if (ff_jni_exception_check(env, 1, codec) < 0) { - ret = AVERROR_EXTERNAL; - goto fail; + return AVERROR_EXTERNAL; } - info->flags = (*env)->GetIntField(env, mediainfo, codec->jfields.flags_id); + info->offset = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.offset_id); if (ff_jni_exception_check(env, 1, codec) < 0) { - ret = AVERROR_EXTERNAL; - goto fail; + return AVERROR_EXTERNAL; } - info->offset = (*env)->GetIntField(env, mediainfo, codec->jfields.offset_id); + info->presentationTimeUs = (*env)->GetLongField(env, codec->buffer_info, codec->jfields.presentation_time_us_id); if (ff_jni_exception_check(env, 1, codec) < 0) { - ret = AVERROR_EXTERNAL; - goto fail; + return AVERROR_EXTERNAL; } - info->presentationTimeUs = (*env)->GetLongField(env, mediainfo, codec->jfields.presentation_time_us_id); + info->size = (*env)->GetIntField(env, codec->buffer_info, codec->jfields.size_id); if (ff_jni_exception_check(env, 1, codec) < 0) { - ret = AVERROR_EXTERNAL; - goto fail; - } - - info->size = (*env)->GetIntField(env, mediainfo, codec->jfields.size_id); - if (ff_jni_exception_check(env, 1, codec) < 0) { - ret = AVERROR_EXTERNAL; - goto fail; - } -fail: - if (mediainfo) { - (*env)->DeleteLocalRef(env, mediainfo); + return AVERROR_EXTERNAL; } return ret; From cc90ee0b7e47bcdb0405789aa6435db906d0774e Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Sat, 6 Jan 2018 15:30:07 -0800 Subject: [PATCH 1584/2557] Changelog: add VideoToolbox HEVC support Signed-off-by: Aman Gupta --- Changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog b/Changelog index c87977d6a9318..61075b3392297 100644 --- a/Changelog +++ b/Changelog @@ -37,6 +37,7 @@ version : - aiff: add support for CD-ROM XA ADPCM - Removed the ffserver program - Removed the ffmenc and ffmdec muxer and demuxer +- VideoToolbox HEVC encoder and hwaccel version 3.4: From 6ec91319204bd9836eb095a9da3150afebebf228 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 6 Jan 2018 22:21:35 -0300 Subject: [PATCH 1585/2557] fate: remove ffm reference files Missed in c17f4761443b471f47fa8f0a5bcff078cdff9479 and 8bbd8c8d52dbcb15773717d3512f8fb68e860bf2 Signed-off-by: James Almer --- tests/ref/lavf/ffm | 3 --- tests/ref/seek/lavf-ffm | 53 ----------------------------------------- 2 files changed, 56 deletions(-) delete mode 100644 tests/ref/lavf/ffm delete mode 100644 tests/ref/seek/lavf-ffm diff --git a/tests/ref/lavf/ffm b/tests/ref/lavf/ffm deleted file mode 100644 index d9fa8d52cbcf5..0000000000000 --- a/tests/ref/lavf/ffm +++ /dev/null @@ -1,3 +0,0 @@ -ca2a450cd0d1e299514a345923b4c82a *./tests/data/lavf/lavf.ffm -376832 ./tests/data/lavf/lavf.ffm -./tests/data/lavf/lavf.ffm CRC=0x000e23ae diff --git a/tests/ref/seek/lavf-ffm b/tests/ref/seek/lavf-ffm deleted file mode 100644 index eceed1a2c2791..0000000000000 --- a/tests/ref/seek/lavf-ffm +++ /dev/null @@ -1,53 +0,0 @@ -ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24663 -ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24663 -ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209 -ret: 0 st: 0 flags:0 ts: 0.788334 -ret: 0 st: 1 flags:1 dts: 0.825011 pts: 0.825011 pos: 327680 size: 209 -ret: 0 st: 0 flags:1 ts:-0.317499 -ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24663 -ret: 0 st: 1 flags:0 ts: 2.576668 -ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209 -ret: 0 st: 1 flags:1 ts: 1.470835 -ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209 -ret: 0 st:-1 flags:0 ts: 0.365002 -ret: 0 st: 1 flags:1 dts: 0.380930 pts: 0.380930 pos: 163840 size: 209 -ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24663 -ret: 0 st: 0 flags:0 ts: 2.153336 -ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209 -ret: 0 st: 0 flags:1 ts: 1.047503 -ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209 -ret: 0 st: 1 flags:0 ts:-0.058330 -ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24663 -ret: 0 st: 1 flags:1 ts: 2.835837 -ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209 -ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209 -ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 1 flags:1 dts: 0.642154 pts: 0.642154 pos: 274432 size: 209 -ret: 0 st: 0 flags:0 ts:-0.481662 -ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24663 -ret: 0 st: 0 flags:1 ts: 2.412505 -ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209 -ret: 0 st: 1 flags:0 ts: 1.306672 -ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209 -ret: 0 st: 1 flags:1 ts: 0.200839 -ret: 0 st: 1 flags:1 dts: 0.224195 pts: 0.224195 pos: 114688 size: 209 -ret: 0 st:-1 flags:0 ts:-0.904994 -ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24663 -ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209 -ret: 0 st: 0 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:0 dts: 0.880000 pts: 0.920000 pos: 339968 size: 12307 -ret: 0 st: 0 flags:1 ts:-0.222493 -ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24663 -ret: 0 st: 1 flags:0 ts: 2.671674 -ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209 -ret: 0 st: 1 flags:1 ts: 1.565841 -ret: 0 st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size: 209 -ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 1 flags:1 dts: 0.485420 pts: 0.485420 pos: 221184 size: 209 -ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos: 8192 size: 24663 From 9e68f472ec5d07538ea2f86c66f6ff534583028c Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 6 Jan 2018 22:22:12 -0300 Subject: [PATCH 1586/2557] configure: remove check for SA_RESTART It's not used anymore. Signed-off-by: James Almer --- configure | 2 -- 1 file changed, 2 deletions(-) diff --git a/configure b/configure index c95b52e77d17e..d2a03da129c2d 100755 --- a/configure +++ b/configure @@ -1899,7 +1899,6 @@ BUILTIN_LIST=" MemoryBarrier mm_empty rdtsc - sarestart sem_timedwait sync_val_compare_and_swap " @@ -5612,7 +5611,6 @@ fi check_builtin atomic_cas_ptr atomic.h "void **ptr; void *oldval, *newval; atomic_cas_ptr(ptr, oldval, newval)" check_builtin machine_rw_barrier mbarrier.h "__machine_rw_barrier()" check_builtin MemoryBarrier windows.h "MemoryBarrier()" -check_builtin sarestart signal.h "SA_RESTART" check_builtin sync_val_compare_and_swap "" "int *ptr; int oldval, newval; __sync_val_compare_and_swap(ptr, oldval, newval)" check_builtin gmtime_r time.h "time_t *time; struct tm *tm; gmtime_r(time, tm)" check_builtin localtime_r time.h "time_t *time; struct tm *tm; localtime_r(time, tm)" From d03c39b46b21c893d6549a532289b7fb9935b3fc Mon Sep 17 00:00:00 2001 From: KO Myung-Hun Date: Thu, 28 Dec 2017 23:41:30 +0900 Subject: [PATCH 1587/2557] configure: check SDL2 function with a header SDL2 uses SDLCALL to specify a calling convention. On OS/2, it's defined to `_System' which is similar to `_cdecl' but does not prepend '_'. After all, without a header, a function is used without `_System'. And linker will try to `_func' but fail because the function is `func' not `_func'. Reviewed-by: Derek Buitenhuis Signed-off-by: James Almer --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index d2a03da129c2d..ab05b9c7f3b24 100755 --- a/configure +++ b/configure @@ -6009,14 +6009,14 @@ fi if enabled sdl2; then SDL2_CONFIG="${cross_prefix}sdl2-config" if test_pkg_config sdl2 "sdl2 >= 2.0.1 sdl2 < 2.1.0" SDL_events.h SDL_PollEvent; then - check_func SDL_Init $sdl2_extralibs $sdl2_cflags || + check_func_headers SDL.h SDL_Init $sdl2_extralibs $sdl2_cflags || disable sdl2 elif "${SDL2_CONFIG}" --version > /dev/null 2>&1; then sdl2_cflags=$("${SDL2_CONFIG}" --cflags) sdl2_extralibs=$("${SDL2_CONFIG}" --libs) check_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) >= 0x020001" $sdl2_cflags && check_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) < 0x020100" $sdl2_cflags && - check_func SDL_Init $sdl2_extralibs $sdl2_cflags && + check_func_headers SDL.h SDL_Init $sdl2_extralibs $sdl2_cflags && enable sdl2 fi if test $target_os = "mingw32"; then From 3c0a081a1e9fc4101252af0aeb6be020ecda43ed Mon Sep 17 00:00:00 2001 From: KO Myung-Hun Date: Thu, 28 Dec 2017 22:03:56 +0900 Subject: [PATCH 1588/2557] compat/os2threads: support static mutexes Reviewed-by: wm4 Signed-off-by: James Almer --- compat/os2threads.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/compat/os2threads.h b/compat/os2threads.h index 40a119ffe1751..2177a033ecbb0 100644 --- a/compat/os2threads.h +++ b/compat/os2threads.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 KO Myung-Hun + * Copyright (c) 2011-2017 KO Myung-Hun * * This file is part of FFmpeg. * @@ -46,9 +46,11 @@ typedef struct { typedef void pthread_attr_t; -typedef HMTX pthread_mutex_t; +typedef _fmutex pthread_mutex_t; typedef void pthread_mutexattr_t; +#define PTHREAD_MUTEX_INITIALIZER _FMUTEX_INITIALIZER + typedef struct { HEV event_sem; HEV ack_sem; @@ -98,28 +100,28 @@ static av_always_inline int pthread_join(pthread_t thread, void **value_ptr) static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { - DosCreateMutexSem(NULL, (PHMTX)mutex, 0, FALSE); + _fmutex_create(mutex, 0); return 0; } static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex) { - DosCloseMutexSem(*(PHMTX)mutex); + _fmutex_close(mutex); return 0; } static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex) { - DosRequestMutexSem(*(PHMTX)mutex, SEM_INDEFINITE_WAIT); + _fmutex_request(mutex, 0); return 0; } static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex) { - DosReleaseMutexSem(*(PHMTX)mutex); + _fmutex_release(mutex); return 0; } From 476665d4de989dba48ec1195215ccc8db54538f4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 3 Jan 2018 23:42:01 +0100 Subject: [PATCH 1589/2557] avcodec/h264_slice: Do not attempt to render into frames already output Fixes: null pointer dereference Fixes: 4698/clusterfuzz-testcase-minimized-5096956322906112 This testcase does not reproduce the issue before 03b82b3ab9883cef017e513c7d0b3b986b3b3e7b Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/h264_slice.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index aad54845888d0..e6b7998834c9a 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1571,6 +1571,12 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl, * one except for reference purposes. */ h->first_field = 1; h->cur_pic_ptr = NULL; + } else if (h->cur_pic_ptr->reference & DELAYED_PIC_REF) { + /* This frame was already output, we cannot draw into it + * anymore. + */ + h->first_field = 1; + h->cur_pic_ptr = NULL; } else { /* Second field in complementary pair */ h->first_field = 0; From 6c65de3db06c5379f2ca9173175bfb5f1553518b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 7 Jan 2018 09:43:50 +0100 Subject: [PATCH 1590/2557] avfilter/af_aiir: add support for alternative coefficients format Support for zeros/poles syntax on Z-plane. Signed-off-by: Paul B Mahol --- doc/filters.texi | 23 ++++++- libavfilter/af_aiir.c | 153 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 167 insertions(+), 9 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 1a2a93b97a1a3..69c59d74a60c0 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1071,16 +1071,27 @@ It accepts the following parameters: Set denominator/poles coefficients. @item b -Set nominator/zeros coefficients. +Set numerator/zeros coefficients. @item dry_gain Set input gain. @item wet_gain Set output gain. + +@item f +Set coefficients format. +Can be @code{tf} - transfer function or @code{zp} - Z-plane zeros/poles. @end table -Coefficients are separated by spaces and are in ascending order. +Coefficients in @code{tf} format are separated by spaces and are in ascending +order. + +Coefficients in @code{zp} format are separated by spaces and order of coefficients +doesn't matter. Coefficients in @code{zp} format are complex numbers with @var{i} +imaginary unit, also first number in numerator, option @var{b}, is not complex but +real number and sets overall gain for channel. + Different coefficients can be provided for every channel, in such case use '|' to separate coefficients. Last provided coefficients will be used for all remaining channels. @@ -1091,7 +1102,13 @@ used for all remaining channels. @item Apply 2 pole elliptic notch at arround 5000Hz for 48000 Hz sample rate: @example -aiir=b=7.957584807809675810E-1 -2.575128568908332300 3.674839853930788710 -2.57512875289799137 7.957586296317130880E-1:a=1 -2.86950072432325953 3.63022088054647218 -2.28075678147272232 6.361362326477423500E-1 +aiir=b=7.957584807809675810E-1 -2.575128568908332300 3.674839853930788710 -2.57512875289799137 7.957586296317130880E-1:a=1 -2.86950072432325953 3.63022088054647218 -2.28075678147272232 6.361362326477423500E-1:f=tf +@end example + +@item +Same as above but in @code{zp} format: +@example +aiir=b=0.79575848078096756 0.80918701+0.58773007i 0.80918701-0.58773007i 0.80884700+0.58784055i 0.80884700-0.58784055i:a=0.63892345+0.59951235i 0.63892345-0.59951235i 0.79582691+0.44198673i 0.79582691-0.44198673i:f=zp @end example @end itemize diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c index e14e464211513..62ad7ebfa15ae 100644 --- a/libavfilter/af_aiir.c +++ b/libavfilter/af_aiir.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/opt.h" @@ -29,6 +31,7 @@ typedef struct AudioIIRContext { const AVClass *class; char *a_str, *b_str; double dry_gain, wet_gain; + int format; int *nb_a, *nb_b; double **a, **b; @@ -137,7 +140,7 @@ static void count_coefficients(char *item_str, int *nb_items) } } -static int read_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, double *dst) +static int read_tf_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, double *dst) { char *p, *arg, *old_str, *saveptr = NULL; int i; @@ -161,8 +164,40 @@ static int read_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, return 0; } -static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, int *nb, double **c, double **cache) +static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, double *dst, int is_zeros) { + char *p, *arg, *old_str, *saveptr = NULL; + int i; + + p = old_str = av_strdup(item_str); + if (!p) + return AVERROR(ENOMEM); + for (i = 0; i < nb_items; i++) { + if (!(arg = av_strtok(p, " ", &saveptr))) + break; + + p = NULL; + if (i == 0 && is_zeros) { + if (sscanf(arg, "%lf", &dst[i]) != 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid gain supplied: %s\n", arg); + return AVERROR(EINVAL); + } + } else { + if (sscanf(arg, "%lf %lfi", &dst[i*2], &dst[i*2+1]) != 2) { + av_log(ctx, AV_LOG_ERROR, "Invalid coefficients supplied: %s\n", arg); + return AVERROR(EINVAL); + } + } + } + + av_freep(&old_str); + + return 0; +} + +static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, int *nb, double **c, double **cache, int is_zeros) +{ + AudioIIRContext *s = ctx->priv; char *p, *arg, *old_str, *prev_arg = NULL, *saveptr = NULL; int i, ret; @@ -180,11 +215,17 @@ static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, p = NULL; cache[i] = av_calloc(nb[i] + 1, sizeof(double)); - c[i] = av_calloc(nb[i], sizeof(double)); + c[i] = av_calloc(nb[i] * (s->format + 1), sizeof(double)); if (!c[i] || !cache[i]) return AVERROR(ENOMEM); - ret = read_coefficients(ctx, arg, nb[i], c[i]); + if (s->format) { + ret = read_zp_coefficients(ctx, arg, nb[i], c[i], is_zeros); + if (is_zeros) + nb[i]--; + } else { + ret = read_tf_coefficients(ctx, arg, nb[i], c[i]); + } if (ret < 0) return ret; prev_arg = arg; @@ -195,6 +236,97 @@ static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, return 0; } +static void multiply(double wre, double wim, int npz, double *coeffs) +{ + double nwre = -wre, nwim = -wim; + double cre, cim; + int i; + + for (i = npz; i >= 1; i--) { + cre = coeffs[2 * i + 0]; + cim = coeffs[2 * i + 1]; + + coeffs[2 * i + 0] = (nwre * cre - nwim * cim) + coeffs[2 * (i - 1) + 0]; + coeffs[2 * i + 1] = (nwre * cim + nwim * cre) + coeffs[2 * (i - 1) + 1]; + } + + cre = coeffs[0]; + cim = coeffs[1]; + coeffs[0] = nwre * cre - nwim * cim; + coeffs[1] = nwre * cim + nwim * cre; +} + +static int expand(AVFilterContext *ctx, double *pz, int nb, double *coeffs) +{ + int i; + + coeffs[0] = 1.0; + coeffs[1] = 0.0; + + for (i = 0; i < nb; i++) { + coeffs[2 * (i + 1) ] = 0.0; + coeffs[2 * (i + 1) + 1] = 0.0; + } + + for (i = 0; i < nb; i++) + multiply(pz[2 * i], pz[2 * i + 1], nb, coeffs); + + for (i = 0; i < nb + 1; i++) { + if (fabs(coeffs[2 * i + 1]) > DBL_EPSILON) { + av_log(ctx, AV_LOG_ERROR, "coeff: %lf of z^%d is not real; poles/zeros are not complex conjugates.\n", + coeffs[2 * i + i], i); + return AVERROR(EINVAL); + } + } + + return 0; +} + +static int convert_zp2tf(AVFilterContext *ctx, int channels) +{ + AudioIIRContext *s = ctx->priv; + int ch, i, j, ret; + + for (ch = 0; ch < channels; ch++) { + double *topc, *botc, gain; + + topc = av_calloc((s->nb_b[ch] + 1) * 2, sizeof(*topc)); + botc = av_calloc((s->nb_a[ch] + 1) * 2, sizeof(*botc)); + if (!topc || !botc) + return AVERROR(ENOMEM); + + ret = expand(ctx, s->a[ch], s->nb_a[ch], botc); + if (ret < 0) { + av_free(topc); + av_free(botc); + return ret; + } + + ret = expand(ctx, &s->b[ch][2], s->nb_b[ch], topc); + if (ret < 0) { + av_free(topc); + av_free(botc); + return ret; + } + + gain = s->b[ch][0]; + for (j = 0, i = s->nb_b[ch]; i >= 0; j++, i--) { + s->b[ch][j] = topc[2 * i] * gain; + } + s->nb_b[ch]++; + + for (j = 0, i = s->nb_a[ch]; i >= 0; j++, i--) { + s->a[ch][j] = botc[2 * i]; + } + s->nb_a[ch]++; + + av_free(topc); + av_free(botc); + } + + return 0; +} + static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -212,14 +344,20 @@ static int config_output(AVFilterLink *outlink) if (!s->a || !s->b || !s->nb_a || !s->nb_b || !s->input || !s->output) return AVERROR(ENOMEM); - ret = read_channels(ctx, inlink->channels, s->a_str, s->nb_a, s->a, s->output); + ret = read_channels(ctx, inlink->channels, s->a_str, s->nb_a, s->a, s->output, 0); if (ret < 0) return ret; - ret = read_channels(ctx, inlink->channels, s->b_str, s->nb_b, s->b, s->input); + ret = read_channels(ctx, inlink->channels, s->b_str, s->nb_b, s->b, s->input, 1); if (ret < 0) return ret; + if (s->format) { + ret = convert_zp2tf(ctx, inlink->channels); + if (ret < 0) + return ret; + } + for (ch = 0; ch < inlink->channels; ch++) { for (i = 1; i < s->nb_a[ch]; i++) { s->a[ch][i] /= s->a[ch][0]; @@ -336,6 +474,9 @@ static const AVOption aiir_options[] = { { "b", "set B/numerator/zeros coefficients", OFFSET(b_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, AF }, { "dry", "set dry gain", OFFSET(dry_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, { "wet", "set wet gain", OFFSET(wet_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, + { "f", "set coefficients format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "format" }, + { "tf", "transfer function", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "format" }, + { "zp", "Z-plane zeros/poles", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "format" }, { NULL }, }; From 2d3df8e2e9e60829c6cd392e334bf0302b8b59bb Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 7 Jan 2018 21:16:25 +0100 Subject: [PATCH 1591/2557] avfilter/af_aiir: rename options, provide gains in separate option This way it can be also used for other format. Signed-off-by: Paul B Mahol --- doc/filters.texi | 20 +++++---- libavfilter/af_aiir.c | 95 ++++++++++++++++++++++++++++++------------- 2 files changed, 77 insertions(+), 38 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 69c59d74a60c0..f6954c947c0c4 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1067,11 +1067,14 @@ Apply an arbitrary Infinite Impulse Response filter. It accepts the following parameters: @table @option -@item a +@item z +Set numerator/zeros coefficients. + +@item p Set denominator/poles coefficients. -@item b -Set numerator/zeros coefficients. +@item k +Set channels gains. @item dry_gain Set input gain. @@ -1089,11 +1092,10 @@ order. Coefficients in @code{zp} format are separated by spaces and order of coefficients doesn't matter. Coefficients in @code{zp} format are complex numbers with @var{i} -imaginary unit, also first number in numerator, option @var{b}, is not complex but -real number and sets overall gain for channel. +imaginary unit. -Different coefficients can be provided for every channel, in such case -use '|' to separate coefficients. Last provided coefficients will be +Different coefficients and gains can be provided for every channel, in such case +use '|' to separate coefficients or gains. Last provided coefficients will be used for all remaining channels. @subsection Examples @@ -1102,13 +1104,13 @@ used for all remaining channels. @item Apply 2 pole elliptic notch at arround 5000Hz for 48000 Hz sample rate: @example -aiir=b=7.957584807809675810E-1 -2.575128568908332300 3.674839853930788710 -2.57512875289799137 7.957586296317130880E-1:a=1 -2.86950072432325953 3.63022088054647218 -2.28075678147272232 6.361362326477423500E-1:f=tf +aiir=k=1:z=7.957584807809675810E-1 -2.575128568908332300 3.674839853930788710 -2.57512875289799137 7.957586296317130880E-1:p=1 -2.86950072432325953 3.63022088054647218 -2.28075678147272232 6.361362326477423500E-1:f=tf @end example @item Same as above but in @code{zp} format: @example -aiir=b=0.79575848078096756 0.80918701+0.58773007i 0.80918701-0.58773007i 0.80884700+0.58784055i 0.80884700-0.58784055i:a=0.63892345+0.59951235i 0.63892345-0.59951235i 0.79582691+0.44198673i 0.79582691-0.44198673i:f=zp +aiir=k=0.79575848078096756:z=0.80918701+0.58773007i 0.80918701-0.58773007i 0.80884700+0.58784055i 0.80884700-0.58784055i:p=0.63892345+0.59951235i 0.63892345-0.59951235i 0.79582691+0.44198673i 0.79582691-0.44198673i:f=zp @end example @end itemize diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c index 62ad7ebfa15ae..87c3dadac8ac7 100644 --- a/libavfilter/af_aiir.c +++ b/libavfilter/af_aiir.c @@ -29,12 +29,13 @@ typedef struct AudioIIRContext { const AVClass *class; - char *a_str, *b_str; + char *a_str, *b_str, *g_str; double dry_gain, wet_gain; int format; int *nb_a, *nb_b; double **a, **b; + double *g; double **input, **output; int clippings; int channels; @@ -140,6 +141,38 @@ static void count_coefficients(char *item_str, int *nb_items) } } +static int read_gains(AVFilterContext *ctx, char *item_str, int nb_items, double *dst) +{ + char *p, *arg, *old_str, *prev_arg = NULL, *saveptr = NULL; + int i; + + p = old_str = av_strdup(item_str); + if (!p) + return AVERROR(ENOMEM); + for (i = 0; i < nb_items; i++) { + if (!(arg = av_strtok(p, "|", &saveptr))) + arg = prev_arg; + + if (!arg) { + av_freep(&old_str); + return AVERROR(EINVAL); + } + + p = NULL; + if (sscanf(arg, "%lf", &dst[i]) != 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid gains supplied: %s\n", arg); + av_freep(&old_str); + return AVERROR(EINVAL); + } + + prev_arg = arg; + } + + av_freep(&old_str); + + return 0; +} + static int read_tf_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, double *dst) { char *p, *arg, *old_str, *saveptr = NULL; @@ -155,6 +188,7 @@ static int read_tf_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite p = NULL; if (sscanf(arg, "%lf", &dst[i]) != 1) { av_log(ctx, AV_LOG_ERROR, "Invalid coefficients supplied: %s\n", arg); + av_freep(&old_str); return AVERROR(EINVAL); } } @@ -164,7 +198,7 @@ static int read_tf_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite return 0; } -static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, double *dst, int is_zeros) +static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, double *dst) { char *p, *arg, *old_str, *saveptr = NULL; int i; @@ -177,16 +211,10 @@ static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite break; p = NULL; - if (i == 0 && is_zeros) { - if (sscanf(arg, "%lf", &dst[i]) != 1) { - av_log(ctx, AV_LOG_ERROR, "Invalid gain supplied: %s\n", arg); - return AVERROR(EINVAL); - } - } else { - if (sscanf(arg, "%lf %lfi", &dst[i*2], &dst[i*2+1]) != 2) { - av_log(ctx, AV_LOG_ERROR, "Invalid coefficients supplied: %s\n", arg); - return AVERROR(EINVAL); - } + if (sscanf(arg, "%lf %lfi", &dst[i*2], &dst[i*2+1]) != 2) { + av_log(ctx, AV_LOG_ERROR, "Invalid coefficients supplied: %s\n", arg); + av_freep(&old_str); + return AVERROR(EINVAL); } } @@ -195,7 +223,7 @@ static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite return 0; } -static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, int *nb, double **c, double **cache, int is_zeros) +static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, int *nb, double **c, double **cache) { AudioIIRContext *s = ctx->priv; char *p, *arg, *old_str, *prev_arg = NULL, *saveptr = NULL; @@ -208,26 +236,30 @@ static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, if (!(arg = av_strtok(p, "|", &saveptr))) arg = prev_arg; - if (!arg) + if (!arg) { + av_freep(&old_str); return AVERROR(EINVAL); + } count_coefficients(arg, &nb[i]); p = NULL; cache[i] = av_calloc(nb[i] + 1, sizeof(double)); c[i] = av_calloc(nb[i] * (s->format + 1), sizeof(double)); - if (!c[i] || !cache[i]) + if (!c[i] || !cache[i]) { + av_freep(&old_str); return AVERROR(ENOMEM); + } if (s->format) { - ret = read_zp_coefficients(ctx, arg, nb[i], c[i], is_zeros); - if (is_zeros) - nb[i]--; + ret = read_zp_coefficients(ctx, arg, nb[i], c[i]); } else { ret = read_tf_coefficients(ctx, arg, nb[i], c[i]); } - if (ret < 0) + if (ret < 0) { + av_freep(&old_str); return ret; + } prev_arg = arg; } @@ -288,7 +320,7 @@ static int convert_zp2tf(AVFilterContext *ctx, int channels) int ch, i, j, ret; for (ch = 0; ch < channels; ch++) { - double *topc, *botc, gain; + double *topc, *botc; topc = av_calloc((s->nb_b[ch] + 1) * 2, sizeof(*topc)); botc = av_calloc((s->nb_a[ch] + 1) * 2, sizeof(*botc)); @@ -302,16 +334,15 @@ static int convert_zp2tf(AVFilterContext *ctx, int channels) return ret; } - ret = expand(ctx, &s->b[ch][2], s->nb_b[ch], topc); + ret = expand(ctx, s->b[ch], s->nb_b[ch], topc); if (ret < 0) { av_free(topc); av_free(botc); return ret; } - gain = s->b[ch][0]; for (j = 0, i = s->nb_b[ch]; i >= 0; j++, i--) { - s->b[ch][j] = topc[2 * i] * gain; + s->b[ch][j] = topc[2 * i]; } s->nb_b[ch]++; @@ -337,6 +368,7 @@ static int config_output(AVFilterLink *outlink) s->channels = inlink->channels; s->a = av_calloc(inlink->channels, sizeof(*s->a)); s->b = av_calloc(inlink->channels, sizeof(*s->b)); + s->g = av_calloc(inlink->channels, sizeof(*s->g)); s->nb_a = av_calloc(inlink->channels, sizeof(*s->nb_a)); s->nb_b = av_calloc(inlink->channels, sizeof(*s->nb_b)); s->input = av_calloc(inlink->channels, sizeof(*s->input)); @@ -344,11 +376,15 @@ static int config_output(AVFilterLink *outlink) if (!s->a || !s->b || !s->nb_a || !s->nb_b || !s->input || !s->output) return AVERROR(ENOMEM); - ret = read_channels(ctx, inlink->channels, s->a_str, s->nb_a, s->a, s->output, 0); + ret = read_gains(ctx, s->g_str, inlink->channels, s->g); + if (ret < 0) + return ret; + + ret = read_channels(ctx, inlink->channels, s->a_str, s->nb_a, s->a, s->output); if (ret < 0) return ret; - ret = read_channels(ctx, inlink->channels, s->b_str, s->nb_b, s->b, s->input, 1); + ret = read_channels(ctx, inlink->channels, s->b_str, s->nb_b, s->b, s->input); if (ret < 0) return ret; @@ -364,7 +400,7 @@ static int config_output(AVFilterLink *outlink) } for (i = 0; i < s->nb_b[ch]; i++) { - s->b[ch][i] /= s->a[ch][0]; + s->b[ch][i] *= s->g[ch] / s->a[ch][0]; } } @@ -412,7 +448,7 @@ static av_cold int init(AVFilterContext *ctx) { AudioIIRContext *s = ctx->priv; - if (!s->a_str || !s->b_str) { + if (!s->a_str || !s->b_str || !s->g_str) { av_log(ctx, AV_LOG_ERROR, "Valid coefficients are mandatory.\n"); return AVERROR(EINVAL); } @@ -470,8 +506,9 @@ static const AVFilterPad outputs[] = { #define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption aiir_options[] = { - { "a", "set A/denominator/poles coefficients", OFFSET(a_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, AF }, - { "b", "set B/numerator/zeros coefficients", OFFSET(b_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, AF }, + { "z", "set B/numerator/zeros coefficients", OFFSET(b_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, AF }, + { "p", "set A/denominator/poles coefficients", OFFSET(a_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, AF }, + { "k", "set channels gains", OFFSET(g_str), AV_OPT_TYPE_STRING, {.str="1|1"}, 0, 0, AF }, { "dry", "set dry gain", OFFSET(dry_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, { "wet", "set wet gain", OFFSET(wet_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, { "f", "set coefficients format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "format" }, From 6874945fbfcd08c959b046b44bbf3be152d51fa0 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Mon, 8 Jan 2018 00:17:00 +0100 Subject: [PATCH 1592/2557] fftools/ffmpeg_opt: Remove a write-only variable. Fixes a warning: fftools/ffmpeg_opt.c:2057:21: warning: variable 'file_oformat' set but not used --- fftools/ffmpeg_opt.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 4fe78fa757ffd..92199b3ac28f2 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -2054,7 +2054,6 @@ static int open_output_file(OptionsContext *o, const char *filename) { AVFormatContext *oc; int i, j, err; - AVOutputFormat *file_oformat; OutputFile *of; OutputStream *ost; InputStream *ist; @@ -2103,7 +2102,6 @@ static int open_output_file(OptionsContext *o, const char *filename) if (o->recording_time != INT64_MAX) oc->duration = o->recording_time; - file_oformat= oc->oformat; oc->interrupt_callback = int_cb; e = av_dict_get(o->g->format_opts, "fflags", NULL, 0); From 202b59cd3d0138921fc6fb6a940fd2a022e33b0a Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 2 Jan 2018 23:12:57 +0000 Subject: [PATCH 1593/2557] lavfi/opencl: Use filter device if no input device is available This allows implementing sources as well as filters. --- libavfilter/opencl.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/libavfilter/opencl.c b/libavfilter/opencl.c index 005ad089e2137..37afc41f8b25a 100644 --- a/libavfilter/opencl.c +++ b/libavfilter/opencl.c @@ -42,11 +42,29 @@ int ff_opencl_filter_query_formats(AVFilterContext *avctx) return ff_set_common_formats(avctx, formats); } +static int opencl_filter_set_device(AVFilterContext *avctx, + AVBufferRef *device) +{ + OpenCLFilterContext *ctx = avctx->priv; + + av_buffer_unref(&ctx->device_ref); + + ctx->device_ref = av_buffer_ref(device); + if (!ctx->device_ref) + return AVERROR(ENOMEM); + + ctx->device = (AVHWDeviceContext*)ctx->device_ref->data; + ctx->hwctx = ctx->device->hwctx; + + return 0; +} + int ff_opencl_filter_config_input(AVFilterLink *inlink) { AVFilterContext *avctx = inlink->dst; OpenCLFilterContext *ctx = avctx->priv; AVHWFramesContext *input_frames; + int err; if (!inlink->hw_frames_ctx) { av_log(avctx, AV_LOG_ERROR, "OpenCL filtering requires a " @@ -59,15 +77,12 @@ int ff_opencl_filter_config_input(AVFilterLink *inlink) return 0; input_frames = (AVHWFramesContext*)inlink->hw_frames_ctx->data; - if (input_frames->format != AV_PIX_FMT_OPENCL) return AVERROR(EINVAL); - ctx->device_ref = av_buffer_ref(input_frames->device_ref); - if (!ctx->device_ref) - return AVERROR(ENOMEM); - ctx->device = input_frames->device_ctx; - ctx->hwctx = ctx->device->hwctx; + err = opencl_filter_set_device(avctx, input_frames->device_ref); + if (err < 0) + return err; // Default output parameters match input parameters. if (ctx->output_format == AV_PIX_FMT_NONE) @@ -90,6 +105,18 @@ int ff_opencl_filter_config_output(AVFilterLink *outlink) av_buffer_unref(&outlink->hw_frames_ctx); + if (!ctx->device_ref) { + if (!avctx->hw_device_ctx) { + av_log(avctx, AV_LOG_ERROR, "OpenCL filtering requires an " + "OpenCL device.\n"); + return AVERROR(EINVAL); + } + + err = opencl_filter_set_device(avctx, avctx->hw_device_ctx); + if (err < 0) + return err; + } + output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref); if (!output_frames_ref) { err = AVERROR(ENOMEM); From dfdc14616112acd1586f1c5c709d3adeb60e0086 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 2 Jan 2018 23:17:32 +0000 Subject: [PATCH 1594/2557] lavfi: Add filters to run arbitrary OpenCL programs --- configure | 2 + libavfilter/Makefile | 2 + libavfilter/allfilters.c | 2 + libavfilter/vf_program_opencl.c | 441 ++++++++++++++++++++++++++++++++ 4 files changed, 447 insertions(+) create mode 100644 libavfilter/vf_program_opencl.c diff --git a/configure b/configure index ab05b9c7f3b24..1c3e505b041cd 100755 --- a/configure +++ b/configure @@ -3235,6 +3235,7 @@ negate_filter_deps="lut_filter" nnedi_filter_deps="gpl" ocr_filter_deps="libtesseract" ocv_filter_deps="libopencv" +openclsrc_filter_deps="opencl" overlay_opencl_filter_deps="opencl" overlay_qsv_filter_deps="libmfx" overlay_qsv_filter_select="qsvvpp" @@ -3244,6 +3245,7 @@ perspective_filter_deps="gpl" phase_filter_deps="gpl" pp7_filter_deps="gpl" pp_filter_deps="gpl postproc" +program_opencl_filter_deps="opencl" pullup_filter_deps="gpl" removelogo_filter_deps="avcodec avformat swscale" repeatfields_filter_deps="gpl" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 256dfabd665fa..ef4729dd3ffaf 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -275,6 +275,7 @@ OBJS-$(CONFIG_PP_FILTER) += vf_pp.o OBJS-$(CONFIG_PP7_FILTER) += vf_pp7.o OBJS-$(CONFIG_PREMULTIPLY_FILTER) += vf_premultiply.o framesync.o OBJS-$(CONFIG_PREWITT_FILTER) += vf_convolution.o +OBJS-$(CONFIG_PROGRAM_OPENCL_FILTER) += vf_program_opencl.o opencl.o framesync.o OBJS-$(CONFIG_PSEUDOCOLOR_FILTER) += vf_pseudocolor.o OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o framesync.o OBJS-$(CONFIG_PULLUP_FILTER) += vf_pullup.o @@ -370,6 +371,7 @@ OBJS-$(CONFIG_LIFE_FILTER) += vsrc_life.o OBJS-$(CONFIG_MANDELBROT_FILTER) += vsrc_mandelbrot.o OBJS-$(CONFIG_MPTESTSRC_FILTER) += vsrc_mptestsrc.o OBJS-$(CONFIG_NULLSRC_FILTER) += vsrc_testsrc.o +OBJS-$(CONFIG_OPENCLSRC_FILTER) += vf_program_opencl.o opencl.o OBJS-$(CONFIG_RGBTESTSRC_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_SMPTEBARS_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_SMPTEHDBARS_FILTER) += vsrc_testsrc.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 753ae968aa786..42516bbdf9fc9 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -284,6 +284,7 @@ static void register_all(void) REGISTER_FILTER(PP7, pp7, vf); REGISTER_FILTER(PREMULTIPLY, premultiply, vf); REGISTER_FILTER(PREWITT, prewitt, vf); + REGISTER_FILTER(PROGRAM_OPENCL, program_opencl, vf); REGISTER_FILTER(PSEUDOCOLOR, pseudocolor, vf); REGISTER_FILTER(PSNR, psnr, vf); REGISTER_FILTER(PULLUP, pullup, vf); @@ -378,6 +379,7 @@ static void register_all(void) REGISTER_FILTER(MANDELBROT, mandelbrot, vsrc); REGISTER_FILTER(MPTESTSRC, mptestsrc, vsrc); REGISTER_FILTER(NULLSRC, nullsrc, vsrc); + REGISTER_FILTER(OPENCLSRC, openclsrc, vsrc); REGISTER_FILTER(RGBTESTSRC, rgbtestsrc, vsrc); REGISTER_FILTER(SMPTEBARS, smptebars, vsrc); REGISTER_FILTER(SMPTEHDBARS, smptehdbars, vsrc); diff --git a/libavfilter/vf_program_opencl.c b/libavfilter/vf_program_opencl.c new file mode 100644 index 0000000000000..d49365aa55889 --- /dev/null +++ b/libavfilter/vf_program_opencl.c @@ -0,0 +1,441 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "libavutil/buffer.h" +#include "libavutil/common.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_opencl.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" + +#include "avfilter.h" +#include "framesync.h" +#include "internal.h" +#include "opencl.h" +#include "video.h" + +typedef struct ProgramOpenCLContext { + OpenCLFilterContext ocf; + + int loaded; + cl_uint index; + cl_kernel kernel; + cl_command_queue command_queue; + + FFFrameSync fs; + AVFrame **frames; + + const char *source_file; + const char *kernel_name; + int nb_inputs; + int width, height; + enum AVPixelFormat source_format; + AVRational source_rate; +} ProgramOpenCLContext; + +static int program_opencl_load(AVFilterContext *avctx) +{ + ProgramOpenCLContext *ctx = avctx->priv; + cl_int cle; + int err; + + err = ff_opencl_filter_load_program_from_file(avctx, ctx->source_file); + if (err < 0) + return err; + + ctx->command_queue = clCreateCommandQueue(ctx->ocf.hwctx->context, + ctx->ocf.hwctx->device_id, + 0, &cle); + if (!ctx->command_queue) { + av_log(avctx, AV_LOG_ERROR, "Failed to create OpenCL " + "command queue: %d.\n", cle); + return AVERROR(EIO); + } + + ctx->kernel = clCreateKernel(ctx->ocf.program, ctx->kernel_name, &cle); + if (!ctx->kernel) { + if (cle == CL_INVALID_KERNEL_NAME) { + av_log(avctx, AV_LOG_ERROR, "Kernel function '%s' not found in " + "program.\n", ctx->kernel_name); + } else { + av_log(avctx, AV_LOG_ERROR, "Failed to create kernel: %d.\n", cle); + } + return AVERROR(EIO); + } + + ctx->loaded = 1; + return 0; +} + +static int program_opencl_run(AVFilterContext *avctx) +{ + AVFilterLink *outlink = avctx->outputs[0]; + ProgramOpenCLContext *ctx = avctx->priv; + AVFrame *output = NULL; + cl_int cle; + size_t global_work[2]; + cl_mem src, dst; + int err, input, plane; + + if (!ctx->loaded) { + err = program_opencl_load(avctx); + if (err < 0) + return err; + } + + output = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!output) { + err = AVERROR(ENOMEM); + goto fail; + } + + for (plane = 0; plane < FF_ARRAY_ELEMS(output->data); plane++) { + dst = (cl_mem)output->data[plane]; + if (!dst) + break; + + cle = clSetKernelArg(ctx->kernel, 0, sizeof(cl_mem), &dst); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "destination image argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel, 1, sizeof(cl_uint), &ctx->index); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "index argument: %d.\n", cle); + goto fail; + } + + for (input = 0; input < ctx->nb_inputs; input++) { + av_assert0(ctx->frames[input]); + + src = (cl_mem)ctx->frames[input]->data[plane]; + av_assert0(src); + + cle = clSetKernelArg(ctx->kernel, 2 + input, sizeof(cl_mem), &src); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "source image argument %d: %d.\n", input, cle); + goto fail; + } + } + + cle = clGetImageInfo(dst, CL_IMAGE_WIDTH, sizeof(size_t), + &global_work[0], NULL); + cle = clGetImageInfo(dst, CL_IMAGE_HEIGHT, sizeof(size_t), + &global_work[1], NULL); + + av_log(avctx, AV_LOG_DEBUG, "Run kernel on plane %d " + "(%zux%zu).\n", plane, global_work[0], global_work[1]); + + cle = clEnqueueNDRangeKernel(ctx->command_queue, ctx->kernel, 2, NULL, + global_work, NULL, 0, NULL, NULL); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to enqueue kernel: %d.\n", + cle); + err = AVERROR(EIO); + goto fail; + } + } + + cle = clFinish(ctx->command_queue); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to finish command queue: %d.\n", + cle); + err = AVERROR(EIO); + goto fail; + } + + if (ctx->nb_inputs > 0) { + err = av_frame_copy_props(output, ctx->frames[0]); + if (err < 0) + goto fail; + } else { + output->pts = ctx->index; + } + ++ctx->index; + + av_log(ctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(output->format), + output->width, output->height, output->pts); + + return ff_filter_frame(outlink, output); + +fail: + clFinish(ctx->command_queue); + av_frame_free(&output); + return err; +} + +static int program_opencl_request_frame(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + + return program_opencl_run(avctx); +} + +static int program_opencl_filter(FFFrameSync *fs) +{ + AVFilterContext *avctx = fs->parent; + ProgramOpenCLContext *ctx = avctx->priv; + int err, i; + + for (i = 0; i < ctx->nb_inputs; i++) { + err = ff_framesync_get_frame(&ctx->fs, i, &ctx->frames[i], 0); + if (err < 0) + return err; + } + + return program_opencl_run(avctx); +} + +static int program_opencl_activate(AVFilterContext *avctx) +{ + ProgramOpenCLContext *ctx = avctx->priv; + + av_assert0(ctx->nb_inputs > 0); + + return ff_framesync_activate(&ctx->fs); +} + +static int program_opencl_config_output(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + ProgramOpenCLContext *ctx = avctx->priv; + int err; + + err = ff_opencl_filter_config_output(outlink); + if (err < 0) + return err; + + if (ctx->nb_inputs > 0) { + FFFrameSyncIn *in; + int i; + + err = ff_framesync_init(&ctx->fs, avctx, ctx->nb_inputs); + if (err < 0) + return err; + + ctx->fs.opaque = ctx; + ctx->fs.on_event = &program_opencl_filter; + + in = ctx->fs.in; + for (i = 0; i < ctx->nb_inputs; i++) { + const AVFilterLink *inlink = avctx->inputs[i]; + + in[i].time_base = inlink->time_base; + in[i].sync = 1; + in[i].before = EXT_STOP; + in[i].after = EXT_INFINITY; + } + + err = ff_framesync_configure(&ctx->fs); + if (err < 0) + return err; + + } else { + outlink->time_base = av_inv_q(ctx->source_rate); + } + + return 0; +} + +static av_cold int program_opencl_init(AVFilterContext *avctx) +{ + ProgramOpenCLContext *ctx = avctx->priv; + int err; + + ff_opencl_filter_init(avctx); + + ctx->ocf.output_width = ctx->width; + ctx->ocf.output_height = ctx->height; + + if (!strcmp(avctx->filter->name, "openclsrc")) { + if (!ctx->ocf.output_width || !ctx->ocf.output_height) { + av_log(avctx, AV_LOG_ERROR, "OpenCL source requires output " + "dimensions to be specified.\n"); + return AVERROR(EINVAL); + } + + ctx->nb_inputs = 0; + ctx->ocf.output_format = ctx->source_format; + } else { + int i; + + ctx->frames = av_mallocz_array(ctx->nb_inputs, + sizeof(*ctx->frames)); + if (!ctx->frames) + return AVERROR(ENOMEM); + + for (i = 0; i < ctx->nb_inputs; i++) { + AVFilterPad input; + memset(&input, 0, sizeof(input)); + + input.type = AVMEDIA_TYPE_VIDEO; + input.name = av_asprintf("input%d", i); + if (!input.name) + return AVERROR(ENOMEM); + + input.config_props = &ff_opencl_filter_config_input; + + err = ff_insert_inpad(avctx, i, &input); + if (err < 0) { + av_freep(&input.name); + return err; + } + } + } + + return 0; +} + +static av_cold void program_opencl_uninit(AVFilterContext *avctx) +{ + ProgramOpenCLContext *ctx = avctx->priv; + cl_int cle; + int i; + + if (ctx->nb_inputs > 0) { + ff_framesync_uninit(&ctx->fs); + + av_freep(&ctx->frames); + for (i = 0; i < avctx->nb_inputs; i++) + av_freep(&avctx->input_pads[i].name); + } + + if (ctx->kernel) { + cle = clReleaseKernel(ctx->kernel); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "kernel: %d.\n", cle); + } + + if (ctx->command_queue) { + cle = clReleaseCommandQueue(ctx->command_queue); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "command queue: %d.\n", cle); + } + + ff_opencl_filter_uninit(avctx); +} + +#define OFFSET(x) offsetof(ProgramOpenCLContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) + +#if CONFIG_PROGRAM_OPENCL_FILTER + +static const AVOption program_opencl_options[] = { + { "source", "OpenCL program source file", OFFSET(source_file), + AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, + { "kernel", "Kernel name in program", OFFSET(kernel_name), + AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, + + { "inputs", "Number of inputs", OFFSET(nb_inputs), + AV_OPT_TYPE_INT, { .i64 = 1 }, 1, INT_MAX, FLAGS }, + + { "size", "Video size", OFFSET(width), + AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, 0, FLAGS }, + { "s", "Video size", OFFSET(width), + AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, 0, FLAGS }, + + { NULL }, +}; + +FRAMESYNC_DEFINE_CLASS(program_opencl, ProgramOpenCLContext, fs); + +static const AVFilterPad program_opencl_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &program_opencl_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_program_opencl = { + .name = "program_opencl", + .description = NULL_IF_CONFIG_SMALL("Filter video using an OpenCL program"), + .priv_size = sizeof(ProgramOpenCLContext), + .priv_class = &program_opencl_class, + .preinit = &program_opencl_framesync_preinit, + .init = &program_opencl_init, + .uninit = &program_opencl_uninit, + .query_formats = &ff_opencl_filter_query_formats, + .activate = &program_opencl_activate, + .inputs = NULL, + .outputs = program_opencl_outputs, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; + +#endif + +#if CONFIG_OPENCLSRC_FILTER + +static const AVOption openclsrc_options[] = { + { "source", "OpenCL program source file", OFFSET(source_file), + AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, + { "kernel", "Kernel name in program", OFFSET(kernel_name), + AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, + + { "size", "Video size", OFFSET(width), + AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, 0, FLAGS }, + { "s", "Video size", OFFSET(width), + AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, 0, FLAGS }, + + { "format", "Video format", OFFSET(source_format), + AV_OPT_TYPE_PIXEL_FMT, { .i64 = AV_PIX_FMT_NONE }, -1, INT_MAX, FLAGS }, + + { "rate", "Video frame rate", OFFSET(source_rate), + AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, 0, INT_MAX, FLAGS }, + { "r", "Video frame rate", OFFSET(source_rate), + AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, 0, INT_MAX, FLAGS }, + + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(openclsrc); + +static const AVFilterPad openclsrc_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &program_opencl_config_output, + .request_frame = &program_opencl_request_frame, + }, + { NULL } +}; + +AVFilter ff_vsrc_openclsrc = { + .name = "openclsrc", + .description = NULL_IF_CONFIG_SMALL("Generate video using an OpenCL program"), + .priv_size = sizeof(ProgramOpenCLContext), + .priv_class = &openclsrc_class, + .init = &program_opencl_init, + .uninit = &program_opencl_uninit, + .query_formats = &ff_opencl_filter_query_formats, + .inputs = NULL, + .outputs = openclsrc_outputs, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; + +#endif From 03c08d59fb2b998106829063b3840e63c2837923 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 3 Jan 2018 22:43:53 +0000 Subject: [PATCH 1595/2557] doc/filters: Document OpenCL program filters Include some example programs. --- doc/filters.texi | 202 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index f6954c947c0c4..a13aef21960c2 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -12524,6 +12524,136 @@ Set value which will be multiplied with filtered result. Set value which will be added to filtered result. @end table +@anchor{program_opencl} +@section program_opencl + +Filter video using an OpenCL program. + +@table @option + +@item source +OpenCL program source file. + +@item kernel +Kernel name in program. + +@item inputs +Number of inputs to the filter. Defaults to 1. + +@item size, s +Size of output frames. Defaults to the same as the first input. + +@end table + +The program source file must contain a kernel function with the given name, +which will be run once for each plane of the output. Each run on a plane +gets enqueued as a separate 2D global NDRange with one work-item for each +pixel to be generated. The global ID offset for each work-item is therefore +the coordinates of a pixel in the destination image. + +The kernel function needs to take the following arguments: +@itemize +@item +Destination image, @var{__write_only image2d_t}. + +This image will become the output; the kernel should write all of it. +@item +Frame index, @var{unsigned int}. + +This is a counter starting from zero and increasing by one for each frame. +@item +Source images, @var{__read_only image2d_t}. + +These are the most recent images on each input. The kernel may read from +them to generate the output, but they can't be written to. +@end itemize + +Example programs: + +@itemize +@item +Copy the input to the output (output must be the same size as the input). +@verbatim +__kernel void copy(__write_only image2d_t destination, + unsigned int index, + __read_only image2d_t source) +{ + const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE; + + int2 location = (int2)(get_global_id(0), get_global_id(1)); + + float4 value = read_imagef(source, sampler, location); + + write_imagef(destination, location, value); +} +@end verbatim + +@item +Apply a simple transformation, rotating the input by an amount increasing +with the index counter. Pixel values are linearly interpolated by the +sampler, and the output need not have the same dimensions as the input. +@verbatim +__kernel void rotate_image(__write_only image2d_t dst, + unsigned int index, + __read_only image2d_t src) +{ + const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_LINEAR); + + float angle = (float)index / 100.0f; + + float2 dst_dim = convert_float2(get_image_dim(dst)); + float2 src_dim = convert_float2(get_image_dim(src)); + + float2 dst_cen = dst_dim / 2.0f; + float2 src_cen = src_dim / 2.0f; + + int2 dst_loc = (int2)(get_global_id(0), get_global_id(1)); + + float2 dst_pos = convert_float2(dst_loc) - dst_cen; + float2 src_pos = { + cos(angle) * dst_pos.x - sin(angle) * dst_pos.y, + sin(angle) * dst_pos.x + cos(angle) * dst_pos.y + }; + src_pos = src_pos * src_dim / dst_dim; + + float2 src_loc = src_pos + src_cen; + + if (src_loc.x < 0.0f || src_loc.y < 0.0f || + src_loc.x > src_dim.x || src_loc.y > src_dim.y) + write_imagef(dst, dst_loc, 0.5f); + else + write_imagef(dst, dst_loc, read_imagef(src, sampler, src_loc)); +} +@end verbatim + +@item +Blend two inputs together, with the amount of each input used varying +with the index counter. +@verbatim +__kernel void blend_images(__write_only image2d_t dst, + unsigned int index, + __read_only image2d_t src1, + __read_only image2d_t src2) +{ + const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_LINEAR); + + float blend = (cos((float)index / 50.0f) + 1.0f) / 2.0f; + + int2 dst_loc = (int2)(get_global_id(0), get_global_id(1)); + int2 src1_loc = dst_loc * get_image_dim(src1) / get_image_dim(dst); + int2 src2_loc = dst_loc * get_image_dim(src2) / get_image_dim(dst); + + float4 val1 = read_imagef(src1, sampler, src1_loc); + float4 val2 = read_imagef(src2, sampler, src2_loc); + + write_imagef(dst, dst_loc, val1 * blend + val2 * (1.0f - blend)); +} +@end verbatim + +@end itemize + @section pseudocolor Alter frame colors in video with pseudocolors. @@ -17498,6 +17628,78 @@ Set the color of the created image. Accepts the same syntax of the corresponding @option{color} option. @end table +@section openclsrc + +Generate video using an OpenCL program. + +@table @option + +@item source +OpenCL program source file. + +@item kernel +Kernel name in program. + +@item size, s +Size of frames to generate. This must be set. + +@item format +Pixel format to use for the generated frames. This must be set. + +@item rate, r +Number of frames generated every second. Default value is '25'. + +@end table + +For details of how the program loading works, see the @ref{program_opencl} +filter. + +Example programs: + +@itemize +@item +Generate a colour ramp by setting pixel values from the position of the pixel +in the output image. (Note that this will work with all pixel formats, but +the generated output will not be the same.) +@verbatim +__kernel void ramp(__write_only image2d_t dst, + unsigned int index) +{ + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + + float4 val; + val.xy = val.zw = convert_float2(loc) / convert_float2(get_image_dim(dst)); + + write_imagef(dst, loc, val); +} +@end verbatim + +@item +Generate a Sierpinski carpet pattern, panning by a single pixel each frame. +@verbatim +__kernel void sierpinski_carpet(__write_only image2d_t dst, + unsigned int index) +{ + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + + float4 value = 0.0f; + int x = loc.x + index; + int y = loc.y + index; + while (x > 0 || y > 0) { + if (x % 3 == 1 && y % 3 == 1) { + value = 1.0f; + break; + } + x /= 3; + y /= 3; + } + + write_imagef(dst, loc, value); +} +@end verbatim + +@end itemize + @c man end VIDEO SOURCES @chapter Video Sinks From 9d68c0191cdd570ece2c4d006b20230ac08085fe Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 7 Jan 2018 00:28:44 -0300 Subject: [PATCH 1596/2557] fate/filter-video: fix 12 bit framerate filter tests on big endian targets Tested-by: Michael Niedermayer Signed-off-by: James Almer --- tests/fate/filter-video.mak | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 39442f6717f21..bf6e2c6f84cdb 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -114,8 +114,8 @@ fate-filter-framerate-up: CMD = framecrc -lavfi testsrc2=r=2:d=10,framerate=fps= fate-filter-framerate-down: CMD = framecrc -lavfi testsrc2=r=2:d=10,framerate=fps=1 -t 1 FATE_FILTER-$(call ALLYES, FRAMERATE_FILTER TESTSRC2_FILTER FORMAT_FILTER) += fate-filter-framerate-12bit-up fate-filter-framerate-12bit-down -fate-filter-framerate-12bit-up: CMD = framecrc -lavfi testsrc2=r=50:d=1,format=pix_fmts=yuv422p12,framerate=fps=60 -t 1 -fate-filter-framerate-12bit-down: CMD = framecrc -lavfi testsrc2=r=60:d=1,format=pix_fmts=yuv422p12,framerate=fps=50 -t 1 +fate-filter-framerate-12bit-up: CMD = framecrc -lavfi testsrc2=r=50:d=1,format=pix_fmts=yuv422p12le,framerate=fps=60 -t 1 -pix_fmt yuv422p12le +fate-filter-framerate-12bit-down: CMD = framecrc -lavfi testsrc2=r=60:d=1,format=pix_fmts=yuv422p12le,framerate=fps=50 -t 1 -pix_fmt yuv422p12le FATE_FILTER_VSYNTH-$(CONFIG_BOXBLUR_FILTER) += fate-filter-boxblur fate-filter-boxblur: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf boxblur=2:1 From 205046420d5a4d389adb705538df3d6158be1fdb Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 8 Jan 2018 08:43:42 +0100 Subject: [PATCH 1597/2557] avfilter/af_aiir: fix typo which may cause overread Signed-off-by: Paul B Mahol --- libavfilter/af_aiir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c index 87c3dadac8ac7..6ff48e45aa135 100644 --- a/libavfilter/af_aiir.c +++ b/libavfilter/af_aiir.c @@ -306,7 +306,7 @@ static int expand(AVFilterContext *ctx, double *pz, int nb, double *coeffs) for (i = 0; i < nb + 1; i++) { if (fabs(coeffs[2 * i + 1]) > DBL_EPSILON) { av_log(ctx, AV_LOG_ERROR, "coeff: %lf of z^%d is not real; poles/zeros are not complex conjugates.\n", - coeffs[2 * i + i], i); + coeffs[2 * i + 1], i); return AVERROR(EINVAL); } } From 3f234a0b22bc19c45bb5b6ed3e663d081a0ea1ae Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 8 Jan 2018 11:22:21 +0100 Subject: [PATCH 1598/2557] avfilter/af_aiir: do not forget to free gains too Signed-off-by: Paul B Mahol --- libavfilter/af_aiir.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c index 6ff48e45aa135..f4485b019470e 100644 --- a/libavfilter/af_aiir.c +++ b/libavfilter/af_aiir.c @@ -477,6 +477,8 @@ static av_cold void uninit(AVFilterContext *ctx) } av_freep(&s->b); + av_freep(&s->g); + av_freep(&s->input); av_freep(&s->output); From e8f7171a342efe3b067c3a3c474dd73b531fd6fc Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Mon, 8 Jan 2018 13:20:13 +0100 Subject: [PATCH 1599/2557] lavf/oggparseogm: Remove an unneeded assert. Suggested-by: Reimar --- libavformat/oggparseogm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavformat/oggparseogm.c b/libavformat/oggparseogm.c index fad093b629ac1..3c5c7abbda7da 100644 --- a/libavformat/oggparseogm.c +++ b/libavformat/oggparseogm.c @@ -106,7 +106,6 @@ ogm_header(AVFormatContext *s, int idx) size -= 4; } if (size > 52) { - av_assert0(AV_INPUT_BUFFER_PADDING_SIZE <= 52); size -= 52; if (bytestream2_get_bytes_left(&p) < size) return AVERROR_INVALIDDATA; From ed03fad2cc523480a7ec385fb3e9bf876769acce Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Mon, 8 Jan 2018 14:36:18 +0100 Subject: [PATCH 1600/2557] lavf/oggparseogm: Remove an unneeded include. Forgotten in e8f7171a --- libavformat/oggparseogm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavformat/oggparseogm.c b/libavformat/oggparseogm.c index 3c5c7abbda7da..ca6b62669d5a5 100644 --- a/libavformat/oggparseogm.c +++ b/libavformat/oggparseogm.c @@ -24,7 +24,6 @@ #include -#include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" #include "libavcodec/bytestream.h" From b3192c64b5bdcb0474cda437d2d5f9421d68811e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 7 Jan 2018 04:12:57 +0100 Subject: [PATCH 1601/2557] avcodec/jpeg2000dsp: Fix integer overflows in ict_int() Fixes: signed integer overflow: 46802 * -71230 cannot be represented in type 'int' Fixes: 4756/clusterfuzz-testcase-minimized-4812495563784192 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/jpeg2000dsp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/jpeg2000dsp.c b/libavcodec/jpeg2000dsp.c index 85a12d0e9b715..90e73b1e202de 100644 --- a/libavcodec/jpeg2000dsp.c +++ b/libavcodec/jpeg2000dsp.c @@ -64,9 +64,9 @@ static void ict_int(void *_src0, void *_src1, void *_src2, int csize) int i; for (i = 0; i < csize; i++) { - i0 = *src0 + *src2 + (((26345 * *src2) + (1 << 15)) >> 16); + i0 = *src0 + *src2 + ((int)((26345U * *src2) + (1 << 15)) >> 16); i1 = *src0 - ((int)(((unsigned)i_ict_params[1] * *src1) + (1 << 15)) >> 16) - - (((i_ict_params[2] * *src2) + (1 << 15)) >> 16); + - ((int)(((unsigned)i_ict_params[2] * *src2) + (1 << 15)) >> 16); i2 = *src0 + (2 * *src1) + ((int)((-14942U * *src1) + (1 << 15)) >> 16); *src0++ = i0; *src1++ = i1; From cbe28bc069dde1d53d937ee10700bb123279c7c8 Mon Sep 17 00:00:00 2001 From: Maxym Dmytrychenko Date: Mon, 8 Jan 2018 15:10:23 +0100 Subject: [PATCH 1602/2557] qsv: better to use alignment by 16 and HEVC 10b requires alignment by 32 --- libavcodec/qsvdec.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index c74ec6836987c..9741f33109434 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -475,6 +475,7 @@ int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, uint8_t *dummy_data; int dummy_size; int ret; + const AVPixFmtDescriptor *desc; if (!q->avctx_internal) { q->avctx_internal = avcodec_alloc_context3(NULL); @@ -511,8 +512,8 @@ int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, /* TODO: flush delayed frames on reinit */ if (q->parser->format != q->orig_pix_fmt || - q->parser->coded_width != avctx->coded_width || - q->parser->coded_height != avctx->coded_height) { + FFALIGN(q->parser->coded_width, 16) != FFALIGN(avctx->coded_width, 16) || + FFALIGN(q->parser->coded_height, 16) != FFALIGN(avctx->coded_height, 16)) { enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_QSV, AV_PIX_FMT_NONE, AV_PIX_FMT_NONE }; @@ -531,8 +532,8 @@ int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, avctx->pix_fmt = pix_fmts[1] = qsv_format; avctx->width = q->parser->width; avctx->height = q->parser->height; - avctx->coded_width = q->parser->coded_width; - avctx->coded_height = q->parser->coded_height; + avctx->coded_width = FFALIGN(q->parser->coded_width, 16); + avctx->coded_height = FFALIGN(q->parser->coded_height, 16); avctx->field_order = q->parser->field_order; avctx->level = q->avctx_internal->level; avctx->profile = q->avctx_internal->profile; @@ -543,6 +544,15 @@ int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, avctx->pix_fmt = ret; + desc = av_pix_fmt_desc_get(avctx->pix_fmt); + if (!desc) + goto reinit_fail; + + if (desc->comp[0].depth > 8) { + avctx->coded_width = FFALIGN(q->parser->coded_width, 32); + avctx->coded_height = FFALIGN(q->parser->coded_height, 32); + } + ret = qsv_decode_init(avctx, q); if (ret < 0) goto reinit_fail; From 1bcd7fefcb3c1ec47978fdc64a9e8dfb9512ae62 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 5 Jan 2018 22:12:07 +0100 Subject: [PATCH 1603/2557] avcodec/opus_parser: Check payload_len in parse_opus_ts_header() Fixes: clusterfuzz-testcase-minimized-6134545979277312 Fixes: crbug 797469 Reported-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavcodec/opus_parser.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/libavcodec/opus_parser.c b/libavcodec/opus_parser.c index 893573eb82298..28b093390099e 100644 --- a/libavcodec/opus_parser.c +++ b/libavcodec/opus_parser.c @@ -43,6 +43,7 @@ static const uint8_t *parse_opus_ts_header(const uint8_t *start, int *payload_le const uint8_t *buf = start + 1; int start_trim_flag, end_trim_flag, control_extension_flag, control_extension_length; uint8_t flags; + uint64_t payload_len_tmp; GetByteContext gb; bytestream2_init(&gb, buf, buf_len); @@ -52,11 +53,11 @@ static const uint8_t *parse_opus_ts_header(const uint8_t *start, int *payload_le end_trim_flag = (flags >> 3) & 1; control_extension_flag = (flags >> 2) & 1; - *payload_len = 0; + payload_len_tmp = *payload_len = 0; while (bytestream2_peek_byte(&gb) == 0xff) - *payload_len += bytestream2_get_byte(&gb); + payload_len_tmp += bytestream2_get_byte(&gb); - *payload_len += bytestream2_get_byte(&gb); + payload_len_tmp += bytestream2_get_byte(&gb); if (start_trim_flag) bytestream2_skip(&gb, 2); @@ -67,6 +68,11 @@ static const uint8_t *parse_opus_ts_header(const uint8_t *start, int *payload_le bytestream2_skip(&gb, control_extension_length); } + if (bytestream2_tell(&gb) + payload_len_tmp > buf_len) + return NULL; + + *payload_len = payload_len_tmp; + return buf + bytestream2_tell(&gb); } @@ -104,6 +110,10 @@ static int opus_find_frame_end(AVCodecParserContext *ctx, AVCodecContext *avctx, state = (state << 8) | payload[i]; if ((state & OPUS_TS_MASK) == OPUS_TS_HEADER) { payload = parse_opus_ts_header(payload, &payload_len, buf_size - i); + if (!payload) { + av_log(avctx, AV_LOG_ERROR, "Error parsing Ogg TS header.\n"); + return AVERROR_INVALIDDATA; + } *header_len = payload - buf; start_found = 1; break; From eaa93175895568ef6c2542b13104874907d9c4ef Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 7 Jan 2018 20:43:24 +0100 Subject: [PATCH 1604/2557] avcodec/diracdec: Fix integer overflow with quant Fixes: signed integer overflow: 2 + 2147483646 cannot be represented in type 'int' Fixes: 4792/clusterfuzz-testcase-minimized-6322450775146496 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/diracdec.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/diracdec.c b/libavcodec/diracdec.c index 7157357d593c6..530e1c6ffd269 100644 --- a/libavcodec/diracdec.c +++ b/libavcodec/diracdec.c @@ -509,16 +509,16 @@ static inline void codeblock(DiracContext *s, SubBand *b, } if (s->codeblock_mode && !(s->old_delta_quant && blockcnt_one)) { - int quant = b->quant; + int quant; if (is_arith) - quant += dirac_get_arith_int(c, CTX_DELTA_Q_F, CTX_DELTA_Q_DATA); + quant = dirac_get_arith_int(c, CTX_DELTA_Q_F, CTX_DELTA_Q_DATA); else - quant += dirac_get_se_golomb(gb); - if (quant < 0) { + quant = dirac_get_se_golomb(gb); + if (quant > INT_MAX - b->quant || b->quant + quant < 0) { av_log(s->avctx, AV_LOG_ERROR, "Invalid quant\n"); return; } - b->quant = quant; + b->quant += quant; } if (b->quant > (DIRAC_MAX_QUANT_INDEX - 1)) { From 0e62a2373475f58c72c0faf5568be00b26909585 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 7 Jan 2018 20:58:49 +0100 Subject: [PATCH 1605/2557] avcodec/dirac_dwt: Fix overflows in COMPOSE_HAARiH0/COMPOSE_HAARiL0 Fixes: 4830/clusterfuzz-testcase-minimized-5255392054476800 Fixes: signed integer overflow: 2147483646 - -7 cannot be represented in type 'int' Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/dirac_dwt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/dirac_dwt.h b/libavcodec/dirac_dwt.h index f9828d95a493b..1af41e07025fe 100644 --- a/libavcodec/dirac_dwt.h +++ b/libavcodec/dirac_dwt.h @@ -105,10 +105,10 @@ void ff_spatial_idwt_slice2(DWTContext *d, int y); (int)(((unsigned)(b2) - ((int)(-b0 + 9U*b1 + 9U*b3 - b4 + 16) >> 5))) #define COMPOSE_HAARiL0(b0, b1)\ - (b0 - ((b1 + 1) >> 1)) + ((int)(b0 - (unsigned)((int)(b1 + 1U) >> 1))) #define COMPOSE_HAARiH0(b0, b1)\ - (b0 + b1) + ((int)(b0 + (unsigned)(b1))) #define COMPOSE_FIDELITYiL0(b0, b1, b2, b3, b4, b5, b6, b7, b8)\ ((unsigned)b4 - ((int)(-8*(b0+(unsigned)b8) + 21*(b1+(unsigned)b7) - 46*(b2+(unsigned)b6) + 161*(b3+(unsigned)b5) + 128) >> 8)) From d6945aeee419a8417b8019c7c92227e12e45b7ad Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 7 Jan 2018 03:48:43 +0100 Subject: [PATCH 1606/2557] avcodec/h264addpx_template: Fixes integer overflows Fixes: signed integer overflow: 512 + 2147483491 cannot be represented in type 'int' Fixes: 4780/clusterfuzz-testcase-minimized-4709066174627840 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/h264addpx_template.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libavcodec/h264addpx_template.c b/libavcodec/h264addpx_template.c index b71aaea439480..9a1e6a2f2f603 100644 --- a/libavcodec/h264addpx_template.c +++ b/libavcodec/h264addpx_template.c @@ -35,10 +35,10 @@ static void FUNCC(ff_h264_add_pixels4)(uint8_t *_dst, int16_t *_src, int stride) stride /= sizeof(pixel); for (i = 0; i < 4; i++) { - dst[0] += src[0]; - dst[1] += src[1]; - dst[2] += src[2]; - dst[3] += src[3]; + dst[0] += (unsigned)src[0]; + dst[1] += (unsigned)src[1]; + dst[2] += (unsigned)src[2]; + dst[3] += (unsigned)src[3]; dst += stride; src += 4; @@ -55,14 +55,14 @@ static void FUNCC(ff_h264_add_pixels8)(uint8_t *_dst, int16_t *_src, int stride) stride /= sizeof(pixel); for (i = 0; i < 8; i++) { - dst[0] += src[0]; - dst[1] += src[1]; - dst[2] += src[2]; - dst[3] += src[3]; - dst[4] += src[4]; - dst[5] += src[5]; - dst[6] += src[6]; - dst[7] += src[7]; + dst[0] += (unsigned)src[0]; + dst[1] += (unsigned)src[1]; + dst[2] += (unsigned)src[2]; + dst[3] += (unsigned)src[3]; + dst[4] += (unsigned)src[4]; + dst[5] += (unsigned)src[5]; + dst[6] += (unsigned)src[6]; + dst[7] += (unsigned)src[7]; dst += stride; src += 8; From 42a5fe340fb30042fa9b2212459de7cbbda15b73 Mon Sep 17 00:00:00 2001 From: Kyle Swanson Date: Mon, 8 Jan 2018 16:35:23 -0800 Subject: [PATCH 1607/2557] doc/filters: correct typo in psnr filter docs Signed-off-by: Kyle Swanson --- doc/filters.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index a13aef21960c2..217a2af42b563 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -12785,7 +12785,7 @@ sequential number of the input frame, starting from 1 Mean Square Error pixel-by-pixel average difference of the compared frames, averaged over all the image components. -@item mse_y, mse_u, mse_v, mse_r, mse_g, mse_g, mse_a +@item mse_y, mse_u, mse_v, mse_r, mse_g, mse_b, mse_a Mean Square Error pixel-by-pixel average difference of the compared frames for the component specified by the suffix. From 7add1ca2b5afb1ef85359ff481475c518456a8c8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 8 Jan 2018 21:14:23 +0100 Subject: [PATCH 1608/2557] avfilter/af_aiir: add cascaded biquads support Also add precision option. Signed-off-by: Paul B Mahol --- libavfilter/af_aiir.c | 264 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 253 insertions(+), 11 deletions(-) diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c index f4485b019470e..01d9cd8494871 100644 --- a/libavfilter/af_aiir.c +++ b/libavfilter/af_aiir.c @@ -27,31 +27,44 @@ #include "avfilter.h" #include "internal.h" +typedef struct Pair { + int a, b; +} Pair; + +typedef struct BiquadContext { + double a0, a1, a2; + double b0, b1, b2; + double i1, i2; + double o1, o2; +} BiquadContext; + typedef struct AudioIIRContext { const AVClass *class; char *a_str, *b_str, *g_str; double dry_gain, wet_gain; int format; + int process; + int precision; int *nb_a, *nb_b; double **a, **b; double *g; double **input, **output; + BiquadContext **biquads; int clippings; int channels; + enum AVSampleFormat sample_format; void (*iir_frame)(AVFilterContext *ctx, AVFrame *in, AVFrame *out); } AudioIIRContext; static int query_formats(AVFilterContext *ctx) { + AudioIIRContext *s = ctx->priv; AVFilterFormats *formats; AVFilterChannelLayouts *layouts; - static const enum AVSampleFormat sample_fmts[] = { + enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_DBLP, - AV_SAMPLE_FMT_FLTP, - AV_SAMPLE_FMT_S32P, - AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }; int ret; @@ -63,6 +76,7 @@ static int query_formats(AVFilterContext *ctx) if (ret < 0) return ret; + sample_fmts[0] = s->sample_format; formats = ff_make_format_list(sample_fmts); if (!formats) return AVERROR(ENOMEM); @@ -127,6 +141,63 @@ IIR_FRAME(s32p, int32_t, INT32_MIN, INT32_MAX, 1) IIR_FRAME(fltp, float, -1., 1., 0) IIR_FRAME(dblp, double, -1., 1., 0) +#define SERIAL_IIR_FRAME(name, type, min, max, need_clipping) \ +static void iir_frame_serial_## name(AVFilterContext *ctx, AVFrame *in, AVFrame *out) \ +{ \ + AudioIIRContext *s = ctx->priv; \ + const double ig = s->dry_gain; \ + const double og = s->wet_gain; \ + int ch, n, i; \ + \ + for (ch = 0; ch < out->channels; ch++) { \ + const type *src = (const type *)in->extended_data[ch]; \ + type *dst = (type *)out->extended_data[ch]; \ + int nb_biquads = (FFMAX(s->nb_a[ch], s->nb_b[ch]) + 1) / 2; \ + \ + for (i = 0; i < nb_biquads; i++) { \ + const double a1 = -s->biquads[ch][i].a1; \ + const double a2 = -s->biquads[ch][i].a2; \ + const double b0 = s->biquads[ch][i].b0; \ + const double b1 = s->biquads[ch][i].b1; \ + const double b2 = s->biquads[ch][i].b2; \ + double i1 = s->biquads[ch][i].i1; \ + double i2 = s->biquads[ch][i].i2; \ + double o1 = s->biquads[ch][i].o1; \ + double o2 = s->biquads[ch][i].o2; \ + \ + for (n = 0; n < in->nb_samples; n++) { \ + double sample = ig * (i ? dst[n] : src[n]); \ + double o0 = sample * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2; \ + \ + i2 = i1; \ + i1 = src[n]; \ + o2 = o1; \ + o1 = o0; \ + o0 *= og; \ + \ + if (need_clipping && o0 < min) { \ + s->clippings++; \ + dst[n] = min; \ + } else if (need_clipping && o0 > max) { \ + s->clippings++; \ + dst[n] = max; \ + } else { \ + dst[n] = o0; \ + } \ + } \ + s->biquads[ch][i].i1 = i1; \ + s->biquads[ch][i].i2 = i2; \ + s->biquads[ch][i].o1 = o1; \ + s->biquads[ch][i].o2 = o2; \ + } \ + } \ +} + +SERIAL_IIR_FRAME(s16p, int16_t, INT16_MIN, INT16_MAX, 1) +SERIAL_IIR_FRAME(s32p, int32_t, INT32_MIN, INT32_MAX, 1) +SERIAL_IIR_FRAME(fltp, float, -1., 1., 0) +SERIAL_IIR_FRAME(dblp, double, -1., 1., 0) + static void count_coefficients(char *item_str, int *nb_items) { char *p; @@ -304,7 +375,7 @@ static int expand(AVFilterContext *ctx, double *pz, int nb, double *coeffs) multiply(pz[2 * i], pz[2 * i + 1], nb, coeffs); for (i = 0; i < nb + 1; i++) { - if (fabs(coeffs[2 * i + 1]) > DBL_EPSILON) { + if (fabs(coeffs[2 * i + 1]) > FLT_EPSILON) { av_log(ctx, AV_LOG_ERROR, "coeff: %lf of z^%d is not real; poles/zeros are not complex conjugates.\n", coeffs[2 * i + 1], i); return AVERROR(EINVAL); @@ -358,6 +429,144 @@ static int convert_zp2tf(AVFilterContext *ctx, int channels) return 0; } +static int decompose_zp2biquads(AVFilterContext *ctx, int channels) +{ + AudioIIRContext *s = ctx->priv; + int ch, ret; + + for (ch = 0; ch < channels; ch++) { + int nb_biquads = (FFMAX(s->nb_a[ch], s->nb_b[ch]) + 1) / 2; + int current_biquad = 0; + + s->biquads[ch] = av_calloc(nb_biquads, sizeof(BiquadContext)); + if (!s->biquads[ch]) + return AVERROR(ENOMEM); + + while (nb_biquads--) { + Pair outmost_pole = { -1, -1 }; + Pair nearest_zero = { -1, -1 }; + double zeros[4] = { 0 }; + double poles[4] = { 0 }; + double b[6] = { 0 }; + double a[6] = { 0 }; + double min_distance = DBL_MAX; + double max_mag = 0; + int i; + + for (i = 0; i < s->nb_a[ch]; i++) { + double mag; + + if (isnan(s->a[ch][2 * i]) || isnan(s->a[ch][2 * i + 1])) + continue; + mag = hypot(s->a[ch][2 * i], s->a[ch][2 * i + 1]); + + if (mag > max_mag) { + max_mag = mag; + outmost_pole.a = i; + } + } + + for (i = 0; i < s->nb_a[ch]; i++) { + if (isnan(s->a[ch][2 * i]) || isnan(s->a[ch][2 * i + 1])) + continue; + + if (s->a[ch][2 * i ] == s->a[ch][2 * outmost_pole.a ] && + s->a[ch][2 * i + 1] == -s->a[ch][2 * outmost_pole.a + 1]) { + outmost_pole.b = i; + break; + } + } + + av_log(ctx, AV_LOG_VERBOSE, "outmost_pole is %d.%d\n", outmost_pole.a, outmost_pole.b); + + if (outmost_pole.a < 0 || outmost_pole.b < 0) + return AVERROR(EINVAL); + + for (i = 0; i < s->nb_b[ch]; i++) { + double distance; + + if (isnan(s->b[ch][2 * i]) || isnan(s->b[ch][2 * i + 1])) + continue; + distance = hypot(s->a[ch][2 * outmost_pole.a ] - s->b[ch][2 * i ], + s->a[ch][2 * outmost_pole.a + 1] - s->b[ch][2 * i + 1]); + + if (distance < min_distance) { + min_distance = distance; + nearest_zero.a = i; + } + } + + for (i = 0; i < s->nb_b[ch]; i++) { + if (isnan(s->b[ch][2 * i]) || isnan(s->b[ch][2 * i + 1])) + continue; + + if (s->b[ch][2 * i ] == s->b[ch][2 * nearest_zero.a ] && + s->b[ch][2 * i + 1] == -s->b[ch][2 * nearest_zero.a + 1]) { + nearest_zero.b = i; + break; + } + } + + av_log(ctx, AV_LOG_VERBOSE, "nearest_zero is %d.%d\n", nearest_zero.a, nearest_zero.b); + + if (nearest_zero.a < 0 || nearest_zero.b < 0) + return AVERROR(EINVAL); + + poles[0] = s->a[ch][2 * outmost_pole.a ]; + poles[1] = s->a[ch][2 * outmost_pole.a + 1]; + + zeros[0] = s->b[ch][2 * nearest_zero.a ]; + zeros[1] = s->b[ch][2 * nearest_zero.a + 1]; + + if (nearest_zero.a == nearest_zero.b && outmost_pole.a == outmost_pole.b) { + zeros[2] = 0; + zeros[3] = 0; + + poles[2] = 0; + poles[3] = 0; + } else { + poles[2] = s->a[ch][2 * outmost_pole.b ]; + poles[3] = s->a[ch][2 * outmost_pole.b + 1]; + + zeros[2] = s->b[ch][2 * nearest_zero.b ]; + zeros[3] = s->b[ch][2 * nearest_zero.b + 1]; + } + + ret = expand(ctx, zeros, 2, b); + if (ret < 0) + return ret; + + ret = expand(ctx, poles, 2, a); + if (ret < 0) + return ret; + + s->a[ch][2 * outmost_pole.a] = s->a[ch][2 * outmost_pole.a + 1] = NAN; + s->a[ch][2 * outmost_pole.b] = s->a[ch][2 * outmost_pole.b + 1] = NAN; + s->b[ch][2 * nearest_zero.a] = s->b[ch][2 * nearest_zero.a + 1] = NAN; + s->b[ch][2 * nearest_zero.b] = s->b[ch][2 * nearest_zero.b + 1] = NAN; + + s->biquads[ch][current_biquad].a0 = 1.0; + s->biquads[ch][current_biquad].a1 = a[2] / a[4]; + s->biquads[ch][current_biquad].a2 = a[0] / a[4]; + s->biquads[ch][current_biquad].b0 = b[4] / a[4] * (current_biquad ? 1.0 : s->g[ch]); + s->biquads[ch][current_biquad].b1 = b[2] / a[4] * (current_biquad ? 1.0 : s->g[ch]); + s->biquads[ch][current_biquad].b2 = b[0] / a[4] * (current_biquad ? 1.0 : s->g[ch]); + + av_log(ctx, AV_LOG_VERBOSE, "a=%lf %lf %lf:b=%lf %lf %lf\n", + s->biquads[ch][current_biquad].a0, + s->biquads[ch][current_biquad].a1, + s->biquads[ch][current_biquad].a2, + s->biquads[ch][current_biquad].b0, + s->biquads[ch][current_biquad].b1, + s->biquads[ch][current_biquad].b2); + + current_biquad++; + } + } + + return 0; +} + static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -388,10 +597,20 @@ static int config_output(AVFilterLink *outlink) if (ret < 0) return ret; - if (s->format) { + if (s->format == 1 && s->process == 0) { ret = convert_zp2tf(ctx, inlink->channels); if (ret < 0) return ret; + } else if (s->format == 0 && s->process == 1) { + av_log(ctx, AV_LOG_ERROR, "Serial cascading is not implemented for transfer function.\n"); + return AVERROR_PATCHWELCOME; + } else if (s->format == 1 && s->process == 1) { + s->biquads = av_calloc(inlink->channels, sizeof(*s->biquads)); + if (!s->biquads) + return AVERROR(ENOMEM); + ret = decompose_zp2biquads(ctx, inlink->channels); + if (ret < 0) + return ret; } for (ch = 0; ch < inlink->channels; ch++) { @@ -405,10 +624,10 @@ static int config_output(AVFilterLink *outlink) } switch (inlink->format) { - case AV_SAMPLE_FMT_DBLP: s->iir_frame = iir_frame_dblp; break; - case AV_SAMPLE_FMT_FLTP: s->iir_frame = iir_frame_fltp; break; - case AV_SAMPLE_FMT_S32P: s->iir_frame = iir_frame_s32p; break; - case AV_SAMPLE_FMT_S16P: s->iir_frame = iir_frame_s16p; break; + case AV_SAMPLE_FMT_DBLP: s->iir_frame = s->process == 1 ? iir_frame_serial_dblp : iir_frame_dblp; break; + case AV_SAMPLE_FMT_FLTP: s->iir_frame = s->process == 1 ? iir_frame_serial_fltp : iir_frame_fltp; break; + case AV_SAMPLE_FMT_S32P: s->iir_frame = s->process == 1 ? iir_frame_serial_s32p : iir_frame_s32p; break; + case AV_SAMPLE_FMT_S16P: s->iir_frame = s->process == 1 ? iir_frame_serial_s16p : iir_frame_s16p; break; } return 0; @@ -453,6 +672,14 @@ static av_cold int init(AVFilterContext *ctx) return AVERROR(EINVAL); } + switch (s->precision) { + case 0: s->sample_format = AV_SAMPLE_FMT_DBLP; break; + case 1: s->sample_format = AV_SAMPLE_FMT_FLTP; break; + case 2: s->sample_format = AV_SAMPLE_FMT_S32P; break; + case 3: s->sample_format = AV_SAMPLE_FMT_S16P; break; + default: return AVERROR_BUG; + } + return 0; } @@ -482,6 +709,13 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->input); av_freep(&s->output); + if (s->biquads) { + for (ch = 0; ch < s->channels; ch++) { + av_freep(&s->biquads[ch]); + } + } + av_freep(&s->biquads); + av_freep(&s->nb_a); av_freep(&s->nb_b); } @@ -513,9 +747,17 @@ static const AVOption aiir_options[] = { { "k", "set channels gains", OFFSET(g_str), AV_OPT_TYPE_STRING, {.str="1|1"}, 0, 0, AF }, { "dry", "set dry gain", OFFSET(dry_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, { "wet", "set wet gain", OFFSET(wet_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, - { "f", "set coefficients format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "format" }, + { "f", "set coefficients format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, AF, "format" }, { "tf", "transfer function", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "format" }, { "zp", "Z-plane zeros/poles", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "format" }, + { "r", "set kind of processing", OFFSET(process), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "process" }, + { "d", "direct", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "process" }, + { "s", "serial cascading", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "process" }, + { "e", "set precision", OFFSET(precision),AV_OPT_TYPE_INT, {.i64=0}, 0, 3, AF, "precision" }, + { "dbl", "double-precision floating-point", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision" }, + { "flt", "single-precision floating-point", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision" }, + { "i32", "32-bit integers", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision" }, + { "i16", "16-bit integers", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision" }, { NULL }, }; From d9a3074b93aca99fa223deab641af90e962d5daf Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 9 Jan 2018 10:32:14 +0100 Subject: [PATCH 1609/2557] avfilter/af_aiir: add slice threading support Signed-off-by: Paul B Mahol --- libavfilter/af_aiir.c | 201 +++++++++++++++++++++++------------------- 1 file changed, 108 insertions(+), 93 deletions(-) diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c index 01d9cd8494871..1d6153d8fc8b9 100644 --- a/libavfilter/af_aiir.c +++ b/libavfilter/af_aiir.c @@ -27,6 +27,10 @@ #include "avfilter.h" #include "internal.h" +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + typedef struct Pair { int a, b; } Pair; @@ -51,11 +55,11 @@ typedef struct AudioIIRContext { double *g; double **input, **output; BiquadContext **biquads; - int clippings; + int *clippings; int channels; enum AVSampleFormat sample_format; - void (*iir_frame)(AVFilterContext *ctx, AVFrame *in, AVFrame *out); + int (*iir_channel)(AVFilterContext *ctx, void *arg, int ch, int nb_jobs); } AudioIIRContext; static int query_formats(AVFilterContext *ctx) @@ -90,113 +94,115 @@ static int query_formats(AVFilterContext *ctx) return ff_set_common_samplerates(ctx, formats); } -#define IIR_FRAME(name, type, min, max, need_clipping) \ -static void iir_frame_## name(AVFilterContext *ctx, AVFrame *in, AVFrame *out) \ +#define IIR_CH(name, type, min, max, need_clipping) \ +static int iir_ch_## name(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) \ { \ AudioIIRContext *s = ctx->priv; \ const double ig = s->dry_gain; \ const double og = s->wet_gain; \ - int ch, n; \ - \ - for (ch = 0; ch < out->channels; ch++) { \ - const type *src = (const type *)in->extended_data[ch]; \ - double *ic = (double *)s->input[ch]; \ - double *oc = (double *)s->output[ch]; \ - const int nb_a = s->nb_a[ch]; \ - const int nb_b = s->nb_b[ch]; \ - const double *a = s->a[ch]; \ - const double *b = s->b[ch]; \ - type *dst = (type *)out->extended_data[ch]; \ + ThreadData *td = arg; \ + AVFrame *in = td->in, *out = td->out; \ + const type *src = (const type *)in->extended_data[ch]; \ + double *ic = (double *)s->input[ch]; \ + double *oc = (double *)s->output[ch]; \ + const int nb_a = s->nb_a[ch]; \ + const int nb_b = s->nb_b[ch]; \ + const double *a = s->a[ch]; \ + const double *b = s->b[ch]; \ + type *dst = (type *)out->extended_data[ch]; \ + int n; \ \ - for (n = 0; n < in->nb_samples; n++) { \ - double sample = 0.; \ - int x; \ + for (n = 0; n < in->nb_samples; n++) { \ + double sample = 0.; \ + int x; \ \ - memmove(&ic[1], &ic[0], (nb_b - 1) * sizeof(*ic)); \ - memmove(&oc[1], &oc[0], (nb_a - 1) * sizeof(*oc)); \ - ic[0] = src[n] * ig; \ - for (x = 0; x < nb_b; x++) \ - sample += b[x] * ic[x]; \ + memmove(&ic[1], &ic[0], (nb_b - 1) * sizeof(*ic)); \ + memmove(&oc[1], &oc[0], (nb_a - 1) * sizeof(*oc)); \ + ic[0] = src[n] * ig; \ + for (x = 0; x < nb_b; x++) \ + sample += b[x] * ic[x]; \ \ - for (x = 1; x < nb_a; x++) \ - sample -= a[x] * oc[x]; \ + for (x = 1; x < nb_a; x++) \ + sample -= a[x] * oc[x]; \ \ - oc[0] = sample; \ - sample *= og; \ - if (need_clipping && sample < min) { \ - s->clippings++; \ - dst[n] = min; \ - } else if (need_clipping && sample > max) { \ - s->clippings++; \ - dst[n] = max; \ - } else { \ - dst[n] = sample; \ - } \ + oc[0] = sample; \ + sample *= og; \ + if (need_clipping && sample < min) { \ + s->clippings[ch]++; \ + dst[n] = min; \ + } else if (need_clipping && sample > max) { \ + s->clippings[ch]++; \ + dst[n] = max; \ + } else { \ + dst[n] = sample; \ } \ } \ + \ + return 0; \ } -IIR_FRAME(s16p, int16_t, INT16_MIN, INT16_MAX, 1) -IIR_FRAME(s32p, int32_t, INT32_MIN, INT32_MAX, 1) -IIR_FRAME(fltp, float, -1., 1., 0) -IIR_FRAME(dblp, double, -1., 1., 0) +IIR_CH(s16p, int16_t, INT16_MIN, INT16_MAX, 1) +IIR_CH(s32p, int32_t, INT32_MIN, INT32_MAX, 1) +IIR_CH(fltp, float, -1., 1., 0) +IIR_CH(dblp, double, -1., 1., 0) -#define SERIAL_IIR_FRAME(name, type, min, max, need_clipping) \ -static void iir_frame_serial_## name(AVFilterContext *ctx, AVFrame *in, AVFrame *out) \ +#define SERIAL_IIR_CH(name, type, min, max, need_clipping) \ +static int iir_ch_serial_## name(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) \ { \ AudioIIRContext *s = ctx->priv; \ const double ig = s->dry_gain; \ const double og = s->wet_gain; \ - int ch, n, i; \ - \ - for (ch = 0; ch < out->channels; ch++) { \ - const type *src = (const type *)in->extended_data[ch]; \ - type *dst = (type *)out->extended_data[ch]; \ - int nb_biquads = (FFMAX(s->nb_a[ch], s->nb_b[ch]) + 1) / 2; \ + ThreadData *td = arg; \ + AVFrame *in = td->in, *out = td->out; \ + const type *src = (const type *)in->extended_data[ch]; \ + type *dst = (type *)out->extended_data[ch]; \ + int nb_biquads = (FFMAX(s->nb_a[ch], s->nb_b[ch]) + 1) / 2; \ + int n, i; \ \ - for (i = 0; i < nb_biquads; i++) { \ - const double a1 = -s->biquads[ch][i].a1; \ - const double a2 = -s->biquads[ch][i].a2; \ - const double b0 = s->biquads[ch][i].b0; \ - const double b1 = s->biquads[ch][i].b1; \ - const double b2 = s->biquads[ch][i].b2; \ - double i1 = s->biquads[ch][i].i1; \ - double i2 = s->biquads[ch][i].i2; \ - double o1 = s->biquads[ch][i].o1; \ - double o2 = s->biquads[ch][i].o2; \ + for (i = 0; i < nb_biquads; i++) { \ + const double a1 = -s->biquads[ch][i].a1; \ + const double a2 = -s->biquads[ch][i].a2; \ + const double b0 = s->biquads[ch][i].b0; \ + const double b1 = s->biquads[ch][i].b1; \ + const double b2 = s->biquads[ch][i].b2; \ + double i1 = s->biquads[ch][i].i1; \ + double i2 = s->biquads[ch][i].i2; \ + double o1 = s->biquads[ch][i].o1; \ + double o2 = s->biquads[ch][i].o2; \ \ - for (n = 0; n < in->nb_samples; n++) { \ - double sample = ig * (i ? dst[n] : src[n]); \ - double o0 = sample * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2; \ + for (n = 0; n < in->nb_samples; n++) { \ + double sample = ig * (i ? dst[n] : src[n]); \ + double o0 = sample * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2; \ \ - i2 = i1; \ - i1 = src[n]; \ - o2 = o1; \ - o1 = o0; \ - o0 *= og; \ + i2 = i1; \ + i1 = src[n]; \ + o2 = o1; \ + o1 = o0; \ + o0 *= og; \ \ - if (need_clipping && o0 < min) { \ - s->clippings++; \ - dst[n] = min; \ - } else if (need_clipping && o0 > max) { \ - s->clippings++; \ - dst[n] = max; \ - } else { \ - dst[n] = o0; \ - } \ + if (need_clipping && o0 < min) { \ + s->clippings[ch]++; \ + dst[n] = min; \ + } else if (need_clipping && o0 > max) { \ + s->clippings[ch]++; \ + dst[n] = max; \ + } else { \ + dst[n] = o0; \ } \ - s->biquads[ch][i].i1 = i1; \ - s->biquads[ch][i].i2 = i2; \ - s->biquads[ch][i].o1 = o1; \ - s->biquads[ch][i].o2 = o2; \ } \ + s->biquads[ch][i].i1 = i1; \ + s->biquads[ch][i].i2 = i2; \ + s->biquads[ch][i].o1 = o1; \ + s->biquads[ch][i].o2 = o2; \ } \ + \ + return 0; \ } -SERIAL_IIR_FRAME(s16p, int16_t, INT16_MIN, INT16_MAX, 1) -SERIAL_IIR_FRAME(s32p, int32_t, INT32_MIN, INT32_MAX, 1) -SERIAL_IIR_FRAME(fltp, float, -1., 1., 0) -SERIAL_IIR_FRAME(dblp, double, -1., 1., 0) +SERIAL_IIR_CH(s16p, int16_t, INT16_MIN, INT16_MAX, 1) +SERIAL_IIR_CH(s32p, int32_t, INT32_MIN, INT32_MAX, 1) +SERIAL_IIR_CH(fltp, float, -1., 1., 0) +SERIAL_IIR_CH(dblp, double, -1., 1., 0) static void count_coefficients(char *item_str, int *nb_items) { @@ -582,7 +588,8 @@ static int config_output(AVFilterLink *outlink) s->nb_b = av_calloc(inlink->channels, sizeof(*s->nb_b)); s->input = av_calloc(inlink->channels, sizeof(*s->input)); s->output = av_calloc(inlink->channels, sizeof(*s->output)); - if (!s->a || !s->b || !s->nb_a || !s->nb_b || !s->input || !s->output) + s->clippings = av_calloc(inlink->channels, sizeof(*s->clippings)); + if (!s->a || !s->b || !s->nb_a || !s->nb_b || !s->input || !s->output || !s->clippings) return AVERROR(ENOMEM); ret = read_gains(ctx, s->g_str, inlink->channels, s->g); @@ -624,10 +631,10 @@ static int config_output(AVFilterLink *outlink) } switch (inlink->format) { - case AV_SAMPLE_FMT_DBLP: s->iir_frame = s->process == 1 ? iir_frame_serial_dblp : iir_frame_dblp; break; - case AV_SAMPLE_FMT_FLTP: s->iir_frame = s->process == 1 ? iir_frame_serial_fltp : iir_frame_fltp; break; - case AV_SAMPLE_FMT_S32P: s->iir_frame = s->process == 1 ? iir_frame_serial_s32p : iir_frame_s32p; break; - case AV_SAMPLE_FMT_S16P: s->iir_frame = s->process == 1 ? iir_frame_serial_s16p : iir_frame_s16p; break; + case AV_SAMPLE_FMT_DBLP: s->iir_channel = s->process == 1 ? iir_ch_serial_dblp : iir_ch_dblp; break; + case AV_SAMPLE_FMT_FLTP: s->iir_channel = s->process == 1 ? iir_ch_serial_fltp : iir_ch_fltp; break; + case AV_SAMPLE_FMT_S32P: s->iir_channel = s->process == 1 ? iir_ch_serial_s32p : iir_ch_s32p; break; + case AV_SAMPLE_FMT_S16P: s->iir_channel = s->process == 1 ? iir_ch_serial_s16p : iir_ch_s16p; break; } return 0; @@ -638,7 +645,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterContext *ctx = inlink->dst; AudioIIRContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + ThreadData td; AVFrame *out; + int ch; if (av_frame_is_writable(in)) { out = in; @@ -651,11 +660,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); } - s->iir_frame(ctx, in, out); + td.in = in; + td.out = out; + ctx->internal->execute(ctx, s->iir_channel, &td, NULL, outlink->channels); - if (s->clippings > 0) - av_log(ctx, AV_LOG_WARNING, "clipping %d times. Please reduce gain.\n", s->clippings); - s->clippings = 0; + for (ch = 0; ch < outlink->channels; ch++) { + if (s->clippings[ch] > 0) + av_log(ctx, AV_LOG_WARNING, "Channel %d clipping %d times. Please reduce gain.\n", ch, s->clippings[ch]); + s->clippings[ch] = 0; + } if (in != out) av_frame_free(&in); @@ -705,6 +718,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->b); av_freep(&s->g); + av_freep(&s->clippings); av_freep(&s->input); av_freep(&s->output); @@ -767,10 +781,11 @@ AVFilter ff_af_aiir = { .name = "aiir", .description = NULL_IF_CONFIG_SMALL("Apply Infinite Impulse Response filter with supplied coefficients."), .priv_size = sizeof(AudioIIRContext), + .priv_class = &aiir_class, .init = init, .uninit = uninit, .query_formats = query_formats, .inputs = inputs, .outputs = outputs, - .priv_class = &aiir_class, + .flags = AVFILTER_FLAG_SLICE_THREADS, }; From 21c99f4b40de07c2390803d47f4dd247175e08a3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 9 Jan 2018 12:55:49 +0100 Subject: [PATCH 1610/2557] avfilter/af_aiir: make default processing to serially cascaded Also add several helpfull log messages. Signed-off-by: Paul B Mahol --- libavfilter/af_aiir.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c index 1d6153d8fc8b9..c805c8e770cdd 100644 --- a/libavfilter/af_aiir.c +++ b/libavfilter/af_aiir.c @@ -604,7 +604,12 @@ static int config_output(AVFilterLink *outlink) if (ret < 0) return ret; + if (s->format == 0) + av_log(ctx, AV_LOG_WARNING, "tf coefficients format is not recommended for too high number of zeros/poles.\n"); + if (s->format == 1 && s->process == 0) { + av_log(ctx, AV_LOG_WARNING, "Direct processsing is not recommended for zp coefficients format.\n"); + ret = convert_zp2tf(ctx, inlink->channels); if (ret < 0) return ret; @@ -612,6 +617,9 @@ static int config_output(AVFilterLink *outlink) av_log(ctx, AV_LOG_ERROR, "Serial cascading is not implemented for transfer function.\n"); return AVERROR_PATCHWELCOME; } else if (s->format == 1 && s->process == 1) { + if (inlink->format == AV_SAMPLE_FMT_S16P) + av_log(ctx, AV_LOG_WARNING, "Serial cascading is not recommended for i16 precision.\n"); + s->biquads = av_calloc(inlink->channels, sizeof(*s->biquads)); if (!s->biquads) return AVERROR(ENOMEM); @@ -756,15 +764,15 @@ static const AVFilterPad outputs[] = { #define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption aiir_options[] = { - { "z", "set B/numerator/zeros coefficients", OFFSET(b_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, AF }, - { "p", "set A/denominator/poles coefficients", OFFSET(a_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, AF }, + { "z", "set B/numerator/zeros coefficients", OFFSET(b_str), AV_OPT_TYPE_STRING, {.str="1+0i 1-0i"}, 0, 0, AF }, + { "p", "set A/denominator/poles coefficients", OFFSET(a_str), AV_OPT_TYPE_STRING, {.str="1+0i 1-0i"}, 0, 0, AF }, { "k", "set channels gains", OFFSET(g_str), AV_OPT_TYPE_STRING, {.str="1|1"}, 0, 0, AF }, { "dry", "set dry gain", OFFSET(dry_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, { "wet", "set wet gain", OFFSET(wet_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, { "f", "set coefficients format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, AF, "format" }, { "tf", "transfer function", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "format" }, { "zp", "Z-plane zeros/poles", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "format" }, - { "r", "set kind of processing", OFFSET(process), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "process" }, + { "r", "set kind of processing", OFFSET(process), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, AF, "process" }, { "d", "direct", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "process" }, { "s", "serial cascading", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "process" }, { "e", "set precision", OFFSET(precision),AV_OPT_TYPE_INT, {.i64=0}, 0, 3, AF, "precision" }, From ded409b7c9c242df5954f582f7d8b180f9291793 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 4 Jan 2018 15:35:59 -0300 Subject: [PATCH 1611/2557] avresample: remove deprecated attribute from the AVAudioResampleContext struct Having all the public functions marked as deprecated is enough. This gets rid of a warning spam when compiling any file including libavresample/avresample.h even when avresample is not enabled, like it's the case with fftools/cmdutils.c Signed-off-by: James Almer --- libavresample/avresample.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavresample/avresample.h b/libavresample/avresample.h index 440e1a16e749e..5ac9adb44b9de 100644 --- a/libavresample/avresample.h +++ b/libavresample/avresample.h @@ -103,7 +103,7 @@ #define AVRESAMPLE_MAX_CHANNELS 32 -typedef attribute_deprecated struct AVAudioResampleContext AVAudioResampleContext; +typedef struct AVAudioResampleContext AVAudioResampleContext; /** * @deprecated use libswresample From e9edd61965da9d1b907fa2685fa5caec595ad687 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 9 Jan 2018 17:46:27 +0100 Subject: [PATCH 1612/2557] avfilter/af_aiir: refactor code so it uses IIRChannel struct Signed-off-by: Paul B Mahol --- libavfilter/af_aiir.c | 267 ++++++++++++++++++++---------------------- 1 file changed, 126 insertions(+), 141 deletions(-) diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c index c805c8e770cdd..0bf9e4f84411e 100644 --- a/libavfilter/af_aiir.c +++ b/libavfilter/af_aiir.c @@ -42,6 +42,15 @@ typedef struct BiquadContext { double o1, o2; } BiquadContext; +typedef struct IIRChannel { + int nb_ab[2]; + double *ab[2]; + double g; + double *cache[2]; + BiquadContext *biquads; + int clippings; +} IIRChannel; + typedef struct AudioIIRContext { const AVClass *class; char *a_str, *b_str, *g_str; @@ -50,12 +59,7 @@ typedef struct AudioIIRContext { int process; int precision; - int *nb_a, *nb_b; - double **a, **b; - double *g; - double **input, **output; - BiquadContext **biquads; - int *clippings; + IIRChannel *iir; int channels; enum AVSampleFormat sample_format; @@ -103,12 +107,13 @@ static int iir_ch_## name(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) ThreadData *td = arg; \ AVFrame *in = td->in, *out = td->out; \ const type *src = (const type *)in->extended_data[ch]; \ - double *ic = (double *)s->input[ch]; \ - double *oc = (double *)s->output[ch]; \ - const int nb_a = s->nb_a[ch]; \ - const int nb_b = s->nb_b[ch]; \ - const double *a = s->a[ch]; \ - const double *b = s->b[ch]; \ + double *ic = (double *)s->iir[ch].cache[0]; \ + double *oc = (double *)s->iir[ch].cache[1]; \ + const int nb_a = s->iir[ch].nb_ab[0]; \ + const int nb_b = s->iir[ch].nb_ab[1]; \ + const double *a = s->iir[ch].ab[0]; \ + const double *b = s->iir[ch].ab[1]; \ + int *clippings = &s->iir[ch].clippings; \ type *dst = (type *)out->extended_data[ch]; \ int n; \ \ @@ -128,10 +133,10 @@ static int iir_ch_## name(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) oc[0] = sample; \ sample *= og; \ if (need_clipping && sample < min) { \ - s->clippings[ch]++; \ + *clippings++; \ dst[n] = min; \ } else if (need_clipping && sample > max) { \ - s->clippings[ch]++; \ + *clippings++; \ dst[n] = max; \ } else { \ dst[n] = sample; \ @@ -156,19 +161,21 @@ static int iir_ch_serial_## name(AVFilterContext *ctx, void *arg, int ch, int nb AVFrame *in = td->in, *out = td->out; \ const type *src = (const type *)in->extended_data[ch]; \ type *dst = (type *)out->extended_data[ch]; \ - int nb_biquads = (FFMAX(s->nb_a[ch], s->nb_b[ch]) + 1) / 2; \ + IIRChannel *iir = &s->iir[ch]; \ + int *clippings = &iir->clippings; \ + int nb_biquads = (FFMAX(iir->nb_ab[0], iir->nb_ab[1]) + 1) / 2; \ int n, i; \ \ for (i = 0; i < nb_biquads; i++) { \ - const double a1 = -s->biquads[ch][i].a1; \ - const double a2 = -s->biquads[ch][i].a2; \ - const double b0 = s->biquads[ch][i].b0; \ - const double b1 = s->biquads[ch][i].b1; \ - const double b2 = s->biquads[ch][i].b2; \ - double i1 = s->biquads[ch][i].i1; \ - double i2 = s->biquads[ch][i].i2; \ - double o1 = s->biquads[ch][i].o1; \ - double o2 = s->biquads[ch][i].o2; \ + const double a1 = -iir->biquads[i].a1; \ + const double a2 = -iir->biquads[i].a2; \ + const double b0 = iir->biquads[i].b0; \ + const double b1 = iir->biquads[i].b1; \ + const double b2 = iir->biquads[i].b2; \ + double i1 = iir->biquads[i].i1; \ + double i2 = iir->biquads[i].i2; \ + double o1 = iir->biquads[i].o1; \ + double o2 = iir->biquads[i].o2; \ \ for (n = 0; n < in->nb_samples; n++) { \ double sample = ig * (i ? dst[n] : src[n]); \ @@ -181,19 +188,19 @@ static int iir_ch_serial_## name(AVFilterContext *ctx, void *arg, int ch, int nb o0 *= og; \ \ if (need_clipping && o0 < min) { \ - s->clippings[ch]++; \ + *clippings++; \ dst[n] = min; \ } else if (need_clipping && o0 > max) { \ - s->clippings[ch]++; \ + *clippings++; \ dst[n] = max; \ } else { \ dst[n] = o0; \ } \ } \ - s->biquads[ch][i].i1 = i1; \ - s->biquads[ch][i].i2 = i2; \ - s->biquads[ch][i].o1 = o1; \ - s->biquads[ch][i].o2 = o2; \ + iir->biquads[i].i1 = i1; \ + iir->biquads[i].i2 = i2; \ + iir->biquads[i].o1 = o1; \ + iir->biquads[i].o2 = o2; \ } \ \ return 0; \ @@ -218,8 +225,9 @@ static void count_coefficients(char *item_str, int *nb_items) } } -static int read_gains(AVFilterContext *ctx, char *item_str, int nb_items, double *dst) +static int read_gains(AVFilterContext *ctx, char *item_str, int nb_items) { + AudioIIRContext *s = ctx->priv; char *p, *arg, *old_str, *prev_arg = NULL, *saveptr = NULL; int i; @@ -236,7 +244,7 @@ static int read_gains(AVFilterContext *ctx, char *item_str, int nb_items, double } p = NULL; - if (sscanf(arg, "%lf", &dst[i]) != 1) { + if (sscanf(arg, "%lf", &s->iir[i].g) != 1) { av_log(ctx, AV_LOG_ERROR, "Invalid gains supplied: %s\n", arg); av_freep(&old_str); return AVERROR(EINVAL); @@ -300,7 +308,7 @@ static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite return 0; } -static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, int *nb, double **c, double **cache) +static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, int ab) { AudioIIRContext *s = ctx->priv; char *p, *arg, *old_str, *prev_arg = NULL, *saveptr = NULL; @@ -310,6 +318,8 @@ static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, if (!p) return AVERROR(ENOMEM); for (i = 0; i < channels; i++) { + IIRChannel *iir = &s->iir[i]; + if (!(arg = av_strtok(p, "|", &saveptr))) arg = prev_arg; @@ -318,20 +328,20 @@ static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, return AVERROR(EINVAL); } - count_coefficients(arg, &nb[i]); + count_coefficients(arg, &iir->nb_ab[ab]); p = NULL; - cache[i] = av_calloc(nb[i] + 1, sizeof(double)); - c[i] = av_calloc(nb[i] * (s->format + 1), sizeof(double)); - if (!c[i] || !cache[i]) { + iir->cache[ab] = av_calloc(iir->nb_ab[ab] + 1, sizeof(double)); + iir->ab[ab] = av_calloc(iir->nb_ab[ab] * (s->format + 1), sizeof(double)); + if (!iir->ab[ab] || !iir->cache[ab]) { av_freep(&old_str); return AVERROR(ENOMEM); } if (s->format) { - ret = read_zp_coefficients(ctx, arg, nb[i], c[i]); + ret = read_zp_coefficients(ctx, arg, iir->nb_ab[ab], iir->ab[ab]); } else { - ret = read_tf_coefficients(ctx, arg, nb[i], c[i]); + ret = read_tf_coefficients(ctx, arg, iir->nb_ab[ab], iir->ab[ab]); } if (ret < 0) { av_freep(&old_str); @@ -397,36 +407,37 @@ static int convert_zp2tf(AVFilterContext *ctx, int channels) int ch, i, j, ret; for (ch = 0; ch < channels; ch++) { + IIRChannel *iir = &s->iir[ch]; double *topc, *botc; - topc = av_calloc((s->nb_b[ch] + 1) * 2, sizeof(*topc)); - botc = av_calloc((s->nb_a[ch] + 1) * 2, sizeof(*botc)); + topc = av_calloc((iir->nb_ab[0] + 1) * 2, sizeof(*topc)); + botc = av_calloc((iir->nb_ab[1] + 1) * 2, sizeof(*botc)); if (!topc || !botc) return AVERROR(ENOMEM); - ret = expand(ctx, s->a[ch], s->nb_a[ch], botc); + ret = expand(ctx, iir->ab[0], iir->nb_ab[0], botc); if (ret < 0) { av_free(topc); av_free(botc); return ret; } - ret = expand(ctx, s->b[ch], s->nb_b[ch], topc); + ret = expand(ctx, iir->ab[1], iir->nb_ab[1], topc); if (ret < 0) { av_free(topc); av_free(botc); return ret; } - for (j = 0, i = s->nb_b[ch]; i >= 0; j++, i--) { - s->b[ch][j] = topc[2 * i]; + for (j = 0, i = iir->nb_ab[1]; i >= 0; j++, i--) { + iir->ab[1][j] = topc[2 * i]; } - s->nb_b[ch]++; + iir->nb_ab[1]++; - for (j = 0, i = s->nb_a[ch]; i >= 0; j++, i--) { - s->a[ch][j] = botc[2 * i]; + for (j = 0, i = iir->nb_ab[0]; i >= 0; j++, i--) { + iir->ab[0][j] = botc[2 * i]; } - s->nb_a[ch]++; + iir->nb_ab[0]++; av_free(topc); av_free(botc); @@ -441,11 +452,12 @@ static int decompose_zp2biquads(AVFilterContext *ctx, int channels) int ch, ret; for (ch = 0; ch < channels; ch++) { - int nb_biquads = (FFMAX(s->nb_a[ch], s->nb_b[ch]) + 1) / 2; + IIRChannel *iir = &s->iir[ch]; + int nb_biquads = (FFMAX(iir->nb_ab[0], iir->nb_ab[1]) + 1) / 2; int current_biquad = 0; - s->biquads[ch] = av_calloc(nb_biquads, sizeof(BiquadContext)); - if (!s->biquads[ch]) + iir->biquads = av_calloc(nb_biquads, sizeof(BiquadContext)); + if (!iir->biquads) return AVERROR(ENOMEM); while (nb_biquads--) { @@ -459,12 +471,12 @@ static int decompose_zp2biquads(AVFilterContext *ctx, int channels) double max_mag = 0; int i; - for (i = 0; i < s->nb_a[ch]; i++) { + for (i = 0; i < iir->nb_ab[0]; i++) { double mag; - if (isnan(s->a[ch][2 * i]) || isnan(s->a[ch][2 * i + 1])) + if (isnan(iir->ab[0][2 * i]) || isnan(iir->ab[0][2 * i + 1])) continue; - mag = hypot(s->a[ch][2 * i], s->a[ch][2 * i + 1]); + mag = hypot(iir->ab[0][2 * i], iir->ab[0][2 * i + 1]); if (mag > max_mag) { max_mag = mag; @@ -472,12 +484,12 @@ static int decompose_zp2biquads(AVFilterContext *ctx, int channels) } } - for (i = 0; i < s->nb_a[ch]; i++) { - if (isnan(s->a[ch][2 * i]) || isnan(s->a[ch][2 * i + 1])) + for (i = 0; i < iir->nb_ab[1]; i++) { + if (isnan(iir->ab[0][2 * i]) || isnan(iir->ab[0][2 * i + 1])) continue; - if (s->a[ch][2 * i ] == s->a[ch][2 * outmost_pole.a ] && - s->a[ch][2 * i + 1] == -s->a[ch][2 * outmost_pole.a + 1]) { + if (iir->ab[0][2 * i ] == iir->ab[0][2 * outmost_pole.a ] && + iir->ab[0][2 * i + 1] == -iir->ab[0][2 * outmost_pole.a + 1]) { outmost_pole.b = i; break; } @@ -488,13 +500,13 @@ static int decompose_zp2biquads(AVFilterContext *ctx, int channels) if (outmost_pole.a < 0 || outmost_pole.b < 0) return AVERROR(EINVAL); - for (i = 0; i < s->nb_b[ch]; i++) { + for (i = 0; i < iir->nb_ab[1]; i++) { double distance; - if (isnan(s->b[ch][2 * i]) || isnan(s->b[ch][2 * i + 1])) + if (isnan(iir->ab[1][2 * i]) || isnan(iir->ab[1][2 * i + 1])) continue; - distance = hypot(s->a[ch][2 * outmost_pole.a ] - s->b[ch][2 * i ], - s->a[ch][2 * outmost_pole.a + 1] - s->b[ch][2 * i + 1]); + distance = hypot(iir->ab[0][2 * outmost_pole.a ] - iir->ab[1][2 * i ], + iir->ab[0][2 * outmost_pole.a + 1] - iir->ab[1][2 * i + 1]); if (distance < min_distance) { min_distance = distance; @@ -502,12 +514,12 @@ static int decompose_zp2biquads(AVFilterContext *ctx, int channels) } } - for (i = 0; i < s->nb_b[ch]; i++) { - if (isnan(s->b[ch][2 * i]) || isnan(s->b[ch][2 * i + 1])) + for (i = 0; i < iir->nb_ab[1]; i++) { + if (isnan(iir->ab[1][2 * i]) || isnan(iir->ab[1][2 * i + 1])) continue; - if (s->b[ch][2 * i ] == s->b[ch][2 * nearest_zero.a ] && - s->b[ch][2 * i + 1] == -s->b[ch][2 * nearest_zero.a + 1]) { + if (iir->ab[1][2 * i ] == iir->ab[1][2 * nearest_zero.a ] && + iir->ab[1][2 * i + 1] == -iir->ab[1][2 * nearest_zero.a + 1]) { nearest_zero.b = i; break; } @@ -518,11 +530,11 @@ static int decompose_zp2biquads(AVFilterContext *ctx, int channels) if (nearest_zero.a < 0 || nearest_zero.b < 0) return AVERROR(EINVAL); - poles[0] = s->a[ch][2 * outmost_pole.a ]; - poles[1] = s->a[ch][2 * outmost_pole.a + 1]; + poles[0] = iir->ab[0][2 * outmost_pole.a ]; + poles[1] = iir->ab[0][2 * outmost_pole.a + 1]; - zeros[0] = s->b[ch][2 * nearest_zero.a ]; - zeros[1] = s->b[ch][2 * nearest_zero.a + 1]; + zeros[0] = iir->ab[1][2 * nearest_zero.a ]; + zeros[1] = iir->ab[1][2 * nearest_zero.a + 1]; if (nearest_zero.a == nearest_zero.b && outmost_pole.a == outmost_pole.b) { zeros[2] = 0; @@ -531,11 +543,11 @@ static int decompose_zp2biquads(AVFilterContext *ctx, int channels) poles[2] = 0; poles[3] = 0; } else { - poles[2] = s->a[ch][2 * outmost_pole.b ]; - poles[3] = s->a[ch][2 * outmost_pole.b + 1]; + poles[2] = iir->ab[0][2 * outmost_pole.b ]; + poles[3] = iir->ab[0][2 * outmost_pole.b + 1]; - zeros[2] = s->b[ch][2 * nearest_zero.b ]; - zeros[3] = s->b[ch][2 * nearest_zero.b + 1]; + zeros[2] = iir->ab[1][2 * nearest_zero.b ]; + zeros[3] = iir->ab[1][2 * nearest_zero.b + 1]; } ret = expand(ctx, zeros, 2, b); @@ -546,25 +558,25 @@ static int decompose_zp2biquads(AVFilterContext *ctx, int channels) if (ret < 0) return ret; - s->a[ch][2 * outmost_pole.a] = s->a[ch][2 * outmost_pole.a + 1] = NAN; - s->a[ch][2 * outmost_pole.b] = s->a[ch][2 * outmost_pole.b + 1] = NAN; - s->b[ch][2 * nearest_zero.a] = s->b[ch][2 * nearest_zero.a + 1] = NAN; - s->b[ch][2 * nearest_zero.b] = s->b[ch][2 * nearest_zero.b + 1] = NAN; + iir->ab[0][2 * outmost_pole.a] = iir->ab[0][2 * outmost_pole.a + 1] = NAN; + iir->ab[0][2 * outmost_pole.b] = iir->ab[0][2 * outmost_pole.b + 1] = NAN; + iir->ab[1][2 * nearest_zero.a] = iir->ab[1][2 * nearest_zero.a + 1] = NAN; + iir->ab[1][2 * nearest_zero.b] = iir->ab[1][2 * nearest_zero.b + 1] = NAN; - s->biquads[ch][current_biquad].a0 = 1.0; - s->biquads[ch][current_biquad].a1 = a[2] / a[4]; - s->biquads[ch][current_biquad].a2 = a[0] / a[4]; - s->biquads[ch][current_biquad].b0 = b[4] / a[4] * (current_biquad ? 1.0 : s->g[ch]); - s->biquads[ch][current_biquad].b1 = b[2] / a[4] * (current_biquad ? 1.0 : s->g[ch]); - s->biquads[ch][current_biquad].b2 = b[0] / a[4] * (current_biquad ? 1.0 : s->g[ch]); + iir->biquads[current_biquad].a0 = 1.0; + iir->biquads[current_biquad].a1 = a[2] / a[4]; + iir->biquads[current_biquad].a2 = a[0] / a[4]; + iir->biquads[current_biquad].b0 = b[4] / a[4] * (current_biquad ? 1.0 : iir->g); + iir->biquads[current_biquad].b1 = b[2] / a[4] * (current_biquad ? 1.0 : iir->g); + iir->biquads[current_biquad].b2 = b[0] / a[4] * (current_biquad ? 1.0 : iir->g); av_log(ctx, AV_LOG_VERBOSE, "a=%lf %lf %lf:b=%lf %lf %lf\n", - s->biquads[ch][current_biquad].a0, - s->biquads[ch][current_biquad].a1, - s->biquads[ch][current_biquad].a2, - s->biquads[ch][current_biquad].b0, - s->biquads[ch][current_biquad].b1, - s->biquads[ch][current_biquad].b2); + iir->biquads[current_biquad].a0, + iir->biquads[current_biquad].a1, + iir->biquads[current_biquad].a2, + iir->biquads[current_biquad].b0, + iir->biquads[current_biquad].b1, + iir->biquads[current_biquad].b2); current_biquad++; } @@ -581,26 +593,19 @@ static int config_output(AVFilterLink *outlink) int ch, ret, i; s->channels = inlink->channels; - s->a = av_calloc(inlink->channels, sizeof(*s->a)); - s->b = av_calloc(inlink->channels, sizeof(*s->b)); - s->g = av_calloc(inlink->channels, sizeof(*s->g)); - s->nb_a = av_calloc(inlink->channels, sizeof(*s->nb_a)); - s->nb_b = av_calloc(inlink->channels, sizeof(*s->nb_b)); - s->input = av_calloc(inlink->channels, sizeof(*s->input)); - s->output = av_calloc(inlink->channels, sizeof(*s->output)); - s->clippings = av_calloc(inlink->channels, sizeof(*s->clippings)); - if (!s->a || !s->b || !s->nb_a || !s->nb_b || !s->input || !s->output || !s->clippings) + s->iir = av_calloc(s->channels, sizeof(*s->iir)); + if (!s->iir) return AVERROR(ENOMEM); - ret = read_gains(ctx, s->g_str, inlink->channels, s->g); + ret = read_gains(ctx, s->g_str, inlink->channels); if (ret < 0) return ret; - ret = read_channels(ctx, inlink->channels, s->a_str, s->nb_a, s->a, s->output); + ret = read_channels(ctx, inlink->channels, s->a_str, 0); if (ret < 0) return ret; - ret = read_channels(ctx, inlink->channels, s->b_str, s->nb_b, s->b, s->input); + ret = read_channels(ctx, inlink->channels, s->b_str, 1); if (ret < 0) return ret; @@ -620,21 +625,20 @@ static int config_output(AVFilterLink *outlink) if (inlink->format == AV_SAMPLE_FMT_S16P) av_log(ctx, AV_LOG_WARNING, "Serial cascading is not recommended for i16 precision.\n"); - s->biquads = av_calloc(inlink->channels, sizeof(*s->biquads)); - if (!s->biquads) - return AVERROR(ENOMEM); ret = decompose_zp2biquads(ctx, inlink->channels); if (ret < 0) return ret; } for (ch = 0; ch < inlink->channels; ch++) { - for (i = 1; i < s->nb_a[ch]; i++) { - s->a[ch][i] /= s->a[ch][0]; + IIRChannel *iir = &s->iir[ch]; + + for (i = 1; i < iir->nb_ab[0]; i++) { + iir->ab[0][i] /= iir->ab[0][0]; } - for (i = 0; i < s->nb_b[ch]; i++) { - s->b[ch][i] *= s->g[ch] / s->a[ch][0]; + for (i = 0; i < iir->nb_ab[1]; i++) { + iir->ab[1][i] *= iir->g / iir->ab[0][0]; } } @@ -673,9 +677,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) ctx->internal->execute(ctx, s->iir_channel, &td, NULL, outlink->channels); for (ch = 0; ch < outlink->channels; ch++) { - if (s->clippings[ch] > 0) - av_log(ctx, AV_LOG_WARNING, "Channel %d clipping %d times. Please reduce gain.\n", ch, s->clippings[ch]); - s->clippings[ch] = 0; + if (s->iir[ch].clippings > 0) + av_log(ctx, AV_LOG_WARNING, "Channel %d clipping %d times. Please reduce gain.\n", + ch, s->iir[ch].clippings); + s->iir[ch].clippings = 0; } if (in != out) @@ -709,37 +714,17 @@ static av_cold void uninit(AVFilterContext *ctx) AudioIIRContext *s = ctx->priv; int ch; - if (s->a) { + if (s->iir) { for (ch = 0; ch < s->channels; ch++) { - av_freep(&s->a[ch]); - av_freep(&s->output[ch]); + IIRChannel *iir = &s->iir[ch]; + av_freep(&iir->ab[0]); + av_freep(&iir->ab[1]); + av_freep(&iir->cache[0]); + av_freep(&iir->cache[1]); + av_freep(&iir->biquads); } } - av_freep(&s->a); - - if (s->b) { - for (ch = 0; ch < s->channels; ch++) { - av_freep(&s->b[ch]); - av_freep(&s->input[ch]); - } - } - av_freep(&s->b); - - av_freep(&s->g); - av_freep(&s->clippings); - - av_freep(&s->input); - av_freep(&s->output); - - if (s->biquads) { - for (ch = 0; ch < s->channels; ch++) { - av_freep(&s->biquads[ch]); - } - } - av_freep(&s->biquads); - - av_freep(&s->nb_a); - av_freep(&s->nb_b); + av_freep(&s->iir); } static const AVFilterPad inputs[] = { From d38a223943d12c603c87ce806023ab4f4c0769c9 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 9 Jan 2018 18:01:44 +0100 Subject: [PATCH 1613/2557] doc/filters: update aiir filter documentation Signed-off-by: Paul B Mahol --- doc/filters.texi | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 217a2af42b563..d29c40080f179 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1085,6 +1085,26 @@ Set output gain. @item f Set coefficients format. Can be @code{tf} - transfer function or @code{zp} - Z-plane zeros/poles. +Default is @code{zp}. + +@item r +Set kind of processing. +Can be @code{d} - direct or @code{s} - serial cascading. Defauls is @code{s}. + +@item e +Set filtering precision. + +@table @option +@item dbl +double-precision floating-point (default) +@item flt +single-precision floating-point +@item i32 +32-bit integers +@item i16 +16-bit integers +@end table + @end table Coefficients in @code{tf} format are separated by spaces and are in ascending From 32f85056b3eae97ddd149d9312b48449f22cff51 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 7 Jan 2018 17:58:33 -0300 Subject: [PATCH 1614/2557] configure: don't use SDL.h in check_func_headers when checking for SDL2 check_func_headers() defines a main() function, which clashes with a redefinition done by said SDL header. Check for SDL_PollEvent using SDL_events.h only instead, where the redefinition doesn't happen. Fixes a regression since d03c39b46b21c893d6549a532289b7fb9935b3fc. Tested-by: RiCON Signed-off-by: James Almer --- configure | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/configure b/configure index 1c3e505b041cd..84d20538d90d5 100755 --- a/configure +++ b/configure @@ -6010,15 +6010,13 @@ fi if enabled sdl2; then SDL2_CONFIG="${cross_prefix}sdl2-config" - if test_pkg_config sdl2 "sdl2 >= 2.0.1 sdl2 < 2.1.0" SDL_events.h SDL_PollEvent; then - check_func_headers SDL.h SDL_Init $sdl2_extralibs $sdl2_cflags || - disable sdl2 - elif "${SDL2_CONFIG}" --version > /dev/null 2>&1; then + test_pkg_config sdl2 "sdl2 >= 2.0.1 sdl2 < 2.1.0" SDL_events.h SDL_PollEvent + if disabled sdl2 && "${SDL2_CONFIG}" --version > /dev/null 2>&1; then sdl2_cflags=$("${SDL2_CONFIG}" --cflags) sdl2_extralibs=$("${SDL2_CONFIG}" --libs) check_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) >= 0x020001" $sdl2_cflags && check_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) < 0x020100" $sdl2_cflags && - check_func_headers SDL.h SDL_Init $sdl2_extralibs $sdl2_cflags && + check_func_headers SDL_events.h SDL_PollEvent $sdl2_extralibs $sdl2_cflags && enable sdl2 fi if test $target_os = "mingw32"; then From 16ba6a8ad14183d2f8947e58a8cb9bae519bc430 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 Jan 2018 15:51:27 +0100 Subject: [PATCH 1615/2557] avformat/wavdec: make fact chunk parsing for w64 more robust Signed-off-by: Paul B Mahol --- libavformat/wavdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c index b016185a1b733..e280be4d44e65 100644 --- a/libavformat/wavdec.c +++ b/libavformat/wavdec.c @@ -822,6 +822,7 @@ static int w64_read_header(AVFormatContext *s) samples = avio_rl64(pb); if (samples > 0) st->duration = samples; + avio_skip(pb, FFALIGN(size, INT64_C(8)) - 32); } else if (!memcmp(guid, ff_w64_guid_data, 16)) { wav->data_end = avio_tell(pb) + size - 24; From 3c29f68b4db316c5d2b126619220cfa4255eacd6 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 Jan 2018 18:38:01 +0100 Subject: [PATCH 1616/2557] avfilter/af_aiir: do not leak memory on failure in convert_zp2tf() Signed-off-by: Paul B Mahol --- libavfilter/af_aiir.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c index 0bf9e4f84411e..c60f3394110e2 100644 --- a/libavfilter/af_aiir.c +++ b/libavfilter/af_aiir.c @@ -404,7 +404,7 @@ static int expand(AVFilterContext *ctx, double *pz, int nb, double *coeffs) static int convert_zp2tf(AVFilterContext *ctx, int channels) { AudioIIRContext *s = ctx->priv; - int ch, i, j, ret; + int ch, i, j, ret = 0; for (ch = 0; ch < channels; ch++) { IIRChannel *iir = &s->iir[ch]; @@ -412,21 +412,19 @@ static int convert_zp2tf(AVFilterContext *ctx, int channels) topc = av_calloc((iir->nb_ab[0] + 1) * 2, sizeof(*topc)); botc = av_calloc((iir->nb_ab[1] + 1) * 2, sizeof(*botc)); - if (!topc || !botc) - return AVERROR(ENOMEM); + if (!topc || !botc) { + ret = AVERROR(ENOMEM); + goto fail; + } ret = expand(ctx, iir->ab[0], iir->nb_ab[0], botc); if (ret < 0) { - av_free(topc); - av_free(botc); - return ret; + goto fail; } ret = expand(ctx, iir->ab[1], iir->nb_ab[1], topc); if (ret < 0) { - av_free(topc); - av_free(botc); - return ret; + goto fail; } for (j = 0, i = iir->nb_ab[1]; i >= 0; j++, i--) { @@ -439,11 +437,14 @@ static int convert_zp2tf(AVFilterContext *ctx, int channels) } iir->nb_ab[0]++; +fail: av_free(topc); av_free(botc); + if (ret < 0) + break; } - return 0; + return ret; } static int decompose_zp2biquads(AVFilterContext *ctx, int channels) From ea25b7b41cb121adaa2234fe7511d2f2d98dd1e6 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 Jan 2018 18:46:29 +0100 Subject: [PATCH 1617/2557] doc/filters: fix examples for aiir filter Signed-off-by: Paul B Mahol --- doc/filters.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index d29c40080f179..a52f6ff57873c 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1124,13 +1124,13 @@ used for all remaining channels. @item Apply 2 pole elliptic notch at arround 5000Hz for 48000 Hz sample rate: @example -aiir=k=1:z=7.957584807809675810E-1 -2.575128568908332300 3.674839853930788710 -2.57512875289799137 7.957586296317130880E-1:p=1 -2.86950072432325953 3.63022088054647218 -2.28075678147272232 6.361362326477423500E-1:f=tf +aiir=k=1:z=7.957584807809675810E-1 -2.575128568908332300 3.674839853930788710 -2.57512875289799137 7.957586296317130880E-1:p=1 -2.86950072432325953 3.63022088054647218 -2.28075678147272232 6.361362326477423500E-1:f=tf:r=d @end example @item Same as above but in @code{zp} format: @example -aiir=k=0.79575848078096756:z=0.80918701+0.58773007i 0.80918701-0.58773007i 0.80884700+0.58784055i 0.80884700-0.58784055i:p=0.63892345+0.59951235i 0.63892345-0.59951235i 0.79582691+0.44198673i 0.79582691-0.44198673i:f=zp +aiir=k=0.79575848078096756:z=0.80918701+0.58773007i 0.80918701-0.58773007i 0.80884700+0.58784055i 0.80884700-0.58784055i:p=0.63892345+0.59951235i 0.63892345-0.59951235i 0.79582691+0.44198673i 0.79582691-0.44198673i:f=zp:r=s @end example @end itemize From de5b12c93f85098407e9a5c59806c5309e7ea13b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 Jan 2018 19:24:41 +0100 Subject: [PATCH 1618/2557] avfilter/af_aiir: unbreak clipping detection Signed-off-by: Paul B Mahol --- libavfilter/af_aiir.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c index c60f3394110e2..46b1c7e698d98 100644 --- a/libavfilter/af_aiir.c +++ b/libavfilter/af_aiir.c @@ -133,10 +133,10 @@ static int iir_ch_## name(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) oc[0] = sample; \ sample *= og; \ if (need_clipping && sample < min) { \ - *clippings++; \ + (*clippings)++; \ dst[n] = min; \ } else if (need_clipping && sample > max) { \ - *clippings++; \ + (*clippings)++; \ dst[n] = max; \ } else { \ dst[n] = sample; \ @@ -188,10 +188,10 @@ static int iir_ch_serial_## name(AVFilterContext *ctx, void *arg, int ch, int nb o0 *= og; \ \ if (need_clipping && o0 < min) { \ - *clippings++; \ + (*clippings)++; \ dst[n] = min; \ } else if (need_clipping && o0 > max) { \ - *clippings++; \ + (*clippings)++; \ dst[n] = max; \ } else { \ dst[n] = o0; \ From de8a1d8d4d0bbcb4c8500965ea8611bf754c4321 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 Jan 2018 20:25:50 +0100 Subject: [PATCH 1619/2557] avfilter/af_aiir: add polar zeros/poles format variant Signed-off-by: Paul B Mahol --- doc/filters.texi | 15 +++++++-- libavfilter/af_aiir.c | 78 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index a52f6ff57873c..618eb28e28ee2 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1084,8 +1084,17 @@ Set output gain. @item f Set coefficients format. -Can be @code{tf} - transfer function or @code{zp} - Z-plane zeros/poles. -Default is @code{zp}. + +@table @samp +@item tf +transfer function +@item zp +Z-plane zeros/poles, cartesian (default) +@item zpr +Z-plane zeros/poles, polar radians +@item zpd +Z-plane zeros/poles, polar degrees +@end table @item r Set kind of processing. @@ -1094,7 +1103,7 @@ Can be @code{d} - direct or @code{s} - serial cascading. Defauls is @code{s}. @item e Set filtering precision. -@table @option +@table @samp @item dbl double-precision floating-point (default) @item flt diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c index 46b1c7e698d98..1f2a568c1d906 100644 --- a/libavfilter/af_aiir.c +++ b/libavfilter/af_aiir.c @@ -283,7 +283,7 @@ static int read_tf_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite return 0; } -static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, double *dst) +static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, double *dst, const char *format) { char *p, *arg, *old_str, *saveptr = NULL; int i; @@ -296,7 +296,7 @@ static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite break; p = NULL; - if (sscanf(arg, "%lf %lfi", &dst[i*2], &dst[i*2+1]) != 2) { + if (sscanf(arg, format, &dst[i*2], &dst[i*2+1]) != 2) { av_log(ctx, AV_LOG_ERROR, "Invalid coefficients supplied: %s\n", arg); av_freep(&old_str); return AVERROR(EINVAL); @@ -308,6 +308,8 @@ static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite return 0; } +static const char *format[] = { "%lf", "%lf %lfi", "%lf %lfr", "%lf %lfd" }; + static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, int ab) { AudioIIRContext *s = ctx->priv; @@ -332,14 +334,14 @@ static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, p = NULL; iir->cache[ab] = av_calloc(iir->nb_ab[ab] + 1, sizeof(double)); - iir->ab[ab] = av_calloc(iir->nb_ab[ab] * (s->format + 1), sizeof(double)); + iir->ab[ab] = av_calloc(iir->nb_ab[ab] * (!!s->format + 1), sizeof(double)); if (!iir->ab[ab] || !iir->cache[ab]) { av_freep(&old_str); return AVERROR(ENOMEM); } if (s->format) { - ret = read_zp_coefficients(ctx, arg, iir->nb_ab[ab], iir->ab[ab]); + ret = read_zp_coefficients(ctx, arg, iir->nb_ab[ab], iir->ab[ab], format[s->format]); } else { ret = read_tf_coefficients(ctx, arg, iir->nb_ab[ab], iir->ab[ab]); } @@ -586,6 +588,60 @@ static int decompose_zp2biquads(AVFilterContext *ctx, int channels) return 0; } +static void convert_pr2zp(AVFilterContext *ctx, int channels) +{ + AudioIIRContext *s = ctx->priv; + int ch; + + for (ch = 0; ch < channels; ch++) { + IIRChannel *iir = &s->iir[ch]; + int n; + + for (n = 0; n < iir->nb_ab[0]; n++) { + double r = iir->ab[0][2*n]; + double angle = iir->ab[0][2*n+1]; + + iir->ab[0][2*n] = r * cos(angle); + iir->ab[0][2*n+1] = r * sin(angle); + } + + for (n = 0; n < iir->nb_ab[1]; n++) { + double r = iir->ab[1][2*n]; + double angle = iir->ab[1][2*n+1]; + + iir->ab[1][2*n] = r * cos(angle); + iir->ab[1][2*n+1] = r * sin(angle); + } + } +} + +static void convert_pd2zp(AVFilterContext *ctx, int channels) +{ + AudioIIRContext *s = ctx->priv; + int ch; + + for (ch = 0; ch < channels; ch++) { + IIRChannel *iir = &s->iir[ch]; + int n; + + for (n = 0; n < iir->nb_ab[0]; n++) { + double r = iir->ab[0][2*n]; + double angle = M_PI*iir->ab[0][2*n+1]/180.; + + iir->ab[0][2*n] = r * cos(angle); + iir->ab[0][2*n+1] = r * sin(angle); + } + + for (n = 0; n < iir->nb_ab[1]; n++) { + double r = iir->ab[1][2*n]; + double angle = M_PI*iir->ab[1][2*n+1]/180.; + + iir->ab[1][2*n] = r * cos(angle); + iir->ab[1][2*n+1] = r * sin(angle); + } + } +} + static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -610,10 +666,16 @@ static int config_output(AVFilterLink *outlink) if (ret < 0) return ret; + if (s->format == 2) { + convert_pr2zp(ctx, inlink->channels); + } else if (s->format == 3) { + convert_pd2zp(ctx, inlink->channels); + } + if (s->format == 0) av_log(ctx, AV_LOG_WARNING, "tf coefficients format is not recommended for too high number of zeros/poles.\n"); - if (s->format == 1 && s->process == 0) { + if (s->format > 0 && s->process == 0) { av_log(ctx, AV_LOG_WARNING, "Direct processsing is not recommended for zp coefficients format.\n"); ret = convert_zp2tf(ctx, inlink->channels); @@ -622,7 +684,7 @@ static int config_output(AVFilterLink *outlink) } else if (s->format == 0 && s->process == 1) { av_log(ctx, AV_LOG_ERROR, "Serial cascading is not implemented for transfer function.\n"); return AVERROR_PATCHWELCOME; - } else if (s->format == 1 && s->process == 1) { + } else if (s->format > 0 && s->process == 1) { if (inlink->format == AV_SAMPLE_FMT_S16P) av_log(ctx, AV_LOG_WARNING, "Serial cascading is not recommended for i16 precision.\n"); @@ -755,9 +817,11 @@ static const AVOption aiir_options[] = { { "k", "set channels gains", OFFSET(g_str), AV_OPT_TYPE_STRING, {.str="1|1"}, 0, 0, AF }, { "dry", "set dry gain", OFFSET(dry_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, { "wet", "set wet gain", OFFSET(wet_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, - { "f", "set coefficients format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, AF, "format" }, + { "f", "set coefficients format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=1}, 0, 3, AF, "format" }, { "tf", "transfer function", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "format" }, { "zp", "Z-plane zeros/poles", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "format" }, + { "pr", "Z-plane zeros/poles (polar radians)", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "format" }, + { "pd", "Z-plane zeros/poles (polar degrees)", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "format" }, { "r", "set kind of processing", OFFSET(process), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, AF, "process" }, { "d", "direct", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "process" }, { "s", "serial cascading", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "process" }, From 6cc44c058396c51a52e868c4293692b43047e8f4 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 Jan 2018 20:32:22 +0100 Subject: [PATCH 1620/2557] doc/filters: fix error in aiir options names Signed-off-by: Paul B Mahol --- doc/filters.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 618eb28e28ee2..bd93e0ab84f39 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1090,9 +1090,9 @@ Set coefficients format. transfer function @item zp Z-plane zeros/poles, cartesian (default) -@item zpr +@item pr Z-plane zeros/poles, polar radians -@item zpd +@item pd Z-plane zeros/poles, polar degrees @end table From 9b4611a1c1f2ac5d1bfd75f7e6e41aa0bc15ca39 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 10 Jan 2018 23:25:56 +0000 Subject: [PATCH 1621/2557] vf_overlay_opencl: Don't leak output frame on error Fixes CID #1423277. --- libavfilter/vf_overlay_opencl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/vf_overlay_opencl.c b/libavfilter/vf_overlay_opencl.c index 46ce42df847b3..ee8381dfee2df 100644 --- a/libavfilter/vf_overlay_opencl.c +++ b/libavfilter/vf_overlay_opencl.c @@ -250,6 +250,7 @@ static int overlay_opencl_blend(FFFrameSync *fs) kernel_arg, cle); err = AVERROR(EIO); fail: + av_frame_free(&output); return err; } From 526a87b47124bfd2d57901d1b9abd6d322eaf293 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 10 Jan 2018 23:27:19 +0000 Subject: [PATCH 1622/2557] vf_program_opencl: Add missing error code returns Fixes CID #1427285. --- libavfilter/vf_program_opencl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavfilter/vf_program_opencl.c b/libavfilter/vf_program_opencl.c index d49365aa55889..4ee9668236c24 100644 --- a/libavfilter/vf_program_opencl.c +++ b/libavfilter/vf_program_opencl.c @@ -116,12 +116,14 @@ static int program_opencl_run(AVFilterContext *avctx) if (cle != CL_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " "destination image argument: %d.\n", cle); + err = AVERROR_UNKNOWN; goto fail; } cle = clSetKernelArg(ctx->kernel, 1, sizeof(cl_uint), &ctx->index); if (cle != CL_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " "index argument: %d.\n", cle); + err = AVERROR_UNKNOWN; goto fail; } @@ -135,6 +137,7 @@ static int program_opencl_run(AVFilterContext *avctx) if (cle != CL_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " "source image argument %d: %d.\n", input, cle); + err = AVERROR_UNKNOWN; goto fail; } } From 7fcbebbeafd106d5bab82b272076f7ceb5bc4a73 Mon Sep 17 00:00:00 2001 From: Eduard Sinelnikov Date: Mon, 8 Jan 2018 14:03:40 +0000 Subject: [PATCH 1623/2557] avformat/aiffdec: AIFF fix in case of ANNO Apple's AIFF protocol clearly states that each chucnk which is odd sized a padding should be added. In the old version of aiffdec adding of padding was done in `get_meta`. And in case of unknown chunk name it was done in defalut case. The new version has deleted the padding in default case and added padding adding after the switch. But the new version didn't removed the padding adding in the `get_meta` function so in some cases padding was added twice which leaded to a bug. Fixes: sample.aiff Signed-off-by: Michael Niedermayer --- libavformat/aiffdec.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index e87fbc5661c1f..7c701e0c70076 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -81,11 +81,10 @@ static void get_meta(AVFormatContext *s, const char *key, int size) av_free(str); return; } - size += (size&1)-res; + size -= res; str[res] = 0; av_dict_set(&s->metadata, key, str, AV_DICT_DONT_STRDUP_VAL); - }else - size+= size&1; + } avio_skip(s->pb, size); } From af964baf090616fbd858e8937d95bf1f1d8be277 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Thu, 11 Jan 2018 11:12:38 +0100 Subject: [PATCH 1624/2557] configure: Simplify detection of static x264 on systems without pkg-config. Fixes a regression since 6dfcbd80. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 84d20538d90d5..5d533621ae114 100755 --- a/configure +++ b/configure @@ -5939,7 +5939,7 @@ enabled libwebp && { enabled libwebp_encoder && require_pkg_config libwebp "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion enabled libwebp_anim_encoder && check_pkg_config libwebp_anim_encoder "libwebpmux >= 0.4.0" webp/mux.h WebPAnimEncoderOptionsInit; } enabled libx264 && { check_pkg_config libx264 x264 "stdint.h x264.h" x264_encoder_encode || - { require libx264 "stdint.h x264.h" x264_encoder_encode -lx264 && + { require libx264 "stdint.h x264.h" x264_encoder_encode "-lx264 $pthreads_extralibs $libm_extralibs" && warn "using libx264 without pkg-config"; } } && require_cpp_condition x264.h "X264_BUILD >= 118" && { check_cpp_condition x264.h "X264_MPEG2" && From ef21033c327a32a23c893d077148d4116c3cb0f7 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 11 Jan 2018 11:35:51 -0300 Subject: [PATCH 1625/2557] avutil/mastering_display_metadata: fix copyright header wrongly formated as doxy Signed-off-by: James Almer --- libavutil/mastering_display_metadata.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/mastering_display_metadata.h b/libavutil/mastering_display_metadata.h index 847b0b62c6cf5..c23b07c3cd80d 100644 --- a/libavutil/mastering_display_metadata.h +++ b/libavutil/mastering_display_metadata.h @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016 Neil Birkbeck * * This file is part of FFmpeg. From b94cd55155d8c061f1e1faca9076afe540149c27 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 30 Dec 2017 19:30:56 +0100 Subject: [PATCH 1626/2557] avfilter/x86/vf_interlace : add AVX2 version --- libavfilter/x86/vf_interlace.asm | 23 ++++++++++++++++++++++- libavfilter/x86/vf_interlace_init.c | 12 ++++++++++++ libavfilter/x86/vf_tinterlace_init.c | 16 ++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/libavfilter/x86/vf_interlace.asm b/libavfilter/x86/vf_interlace.asm index 06b269828a27e..a6c65b805dc26 100644 --- a/libavfilter/x86/vf_interlace.asm +++ b/libavfilter/x86/vf_interlace.asm @@ -39,6 +39,20 @@ SECTION .text pcmpeq%1 m6, m6 + test hq, mmsize + je .loop + + ;process 1 * mmsize + movu m0, [mrefq+hq] + pavg%1 m0, [prefq+hq] + pxor m0, m6 + pxor m2, m6, [srcq+hq] + pavg%1 m0, m2 + pxor m0, m6 + mova [dstq+hq], m0 + add hq, mmsize + jge .end + .loop: movu m0, [mrefq+hq] movu m1, [mrefq+hq+mmsize] @@ -57,7 +71,9 @@ SECTION .text add hq, 2*mmsize jl .loop -REP_RET + +.end: + REP_RET %endmacro %macro LOWPASS_LINE 0 @@ -201,5 +217,10 @@ LOWPASS_LINE INIT_XMM avx LOWPASS_LINE +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +LOWPASS_LINE +%endif + INIT_XMM sse2 LOWPASS_LINE_COMPLEX diff --git a/libavfilter/x86/vf_interlace_init.c b/libavfilter/x86/vf_interlace_init.c index b024b61735749..0de0fea382e53 100644 --- a/libavfilter/x86/vf_interlace_init.c +++ b/libavfilter/x86/vf_interlace_init.c @@ -32,6 +32,9 @@ void ff_lowpass_line_sse2(uint8_t *dstp, ptrdiff_t linesize, void ff_lowpass_line_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); +void ff_lowpass_line_avx2 (uint8_t *dstp, ptrdiff_t linesize, + const uint8_t *srcp, ptrdiff_t mref, + ptrdiff_t pref, int clip_max); void ff_lowpass_line_16_sse2(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, @@ -39,6 +42,9 @@ void ff_lowpass_line_16_sse2(uint8_t *dstp, ptrdiff_t linesize, void ff_lowpass_line_16_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); +void ff_lowpass_line_16_avx2 (uint8_t *dstp, ptrdiff_t linesize, + const uint8_t *srcp, ptrdiff_t mref, + ptrdiff_t pref, int clip_max); void ff_lowpass_line_complex_sse2(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, @@ -62,6 +68,9 @@ av_cold void ff_interlace_init_x86(InterlaceContext *s, int depth) if (EXTERNAL_AVX(cpu_flags)) if (s->lowpass == VLPF_LIN) s->lowpass_line = ff_lowpass_line_16_avx; + if (EXTERNAL_AVX2_FAST(cpu_flags)) + if (s->lowpass == VLPF_LIN) + s->lowpass_line = ff_lowpass_line_16_avx2; } else { if (EXTERNAL_SSE2(cpu_flags)) { if (s->lowpass == VLPF_LIN) @@ -72,5 +81,8 @@ av_cold void ff_interlace_init_x86(InterlaceContext *s, int depth) if (EXTERNAL_AVX(cpu_flags)) if (s->lowpass == VLPF_LIN) s->lowpass_line = ff_lowpass_line_avx; + if (EXTERNAL_AVX2_FAST(cpu_flags)) + if (s->lowpass == VLPF_LIN) + s->lowpass_line = ff_lowpass_line_avx2; } } diff --git a/libavfilter/x86/vf_tinterlace_init.c b/libavfilter/x86/vf_tinterlace_init.c index 209812964d0ed..2c9b1de581f37 100644 --- a/libavfilter/x86/vf_tinterlace_init.c +++ b/libavfilter/x86/vf_tinterlace_init.c @@ -33,6 +33,9 @@ void ff_lowpass_line_sse2(uint8_t *dstp, ptrdiff_t linesize, void ff_lowpass_line_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); +void ff_lowpass_line_avx2 (uint8_t *dstp, ptrdiff_t linesize, + const uint8_t *srcp, ptrdiff_t mref, + ptrdiff_t pref, int clip_max); void ff_lowpass_line_16_sse2(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, @@ -40,6 +43,9 @@ void ff_lowpass_line_16_sse2(uint8_t *dstp, ptrdiff_t linesize, void ff_lowpass_line_16_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref, int clip_max); +void ff_lowpass_line_16_avx2 (uint8_t *dstp, ptrdiff_t linesize, + const uint8_t *srcp, ptrdiff_t mref, + ptrdiff_t pref, int clip_max); void ff_lowpass_line_complex_sse2(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, @@ -63,6 +69,11 @@ av_cold void ff_tinterlace_init_x86(TInterlaceContext *s) if (EXTERNAL_AVX(cpu_flags)) if (!(s->flags & TINTERLACE_FLAG_CVLPF)) s->lowpass_line = ff_lowpass_line_16_avx; + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + if (!(s->flags & TINTERLACE_FLAG_CVLPF)) { + s->lowpass_line = ff_lowpass_line_16_avx2; + } + } } else { if (EXTERNAL_SSE2(cpu_flags)) { if (!(s->flags & TINTERLACE_FLAG_CVLPF)) @@ -73,5 +84,10 @@ av_cold void ff_tinterlace_init_x86(TInterlaceContext *s) if (EXTERNAL_AVX(cpu_flags)) if (!(s->flags & TINTERLACE_FLAG_CVLPF)) s->lowpass_line = ff_lowpass_line_avx; + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + if (!(s->flags & TINTERLACE_FLAG_CVLPF)) { + s->lowpass_line = ff_lowpass_line_avx2; + } + } } } From 6e80079a2840ee407c5d126030eb1066bcbfdfc5 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 7 Jan 2018 00:45:37 -0300 Subject: [PATCH 1627/2557] avcodec: increase AV_INPUT_BUFFER_PADDING_SIZE to 64 AVX-512 support has been introduced, and even if no functions currently use zmm registers (able to load as much as 64 bytes of consecutive data per instruction), they will be added eventually. Reviewed-by: Rostislav Pehlivanov Tested-by: Michael Niedermayer Signed-off-by: James Almer --- libavcodec/avcodec.h | 2 +- libavcodec/x86/hevc_sao.asm | 2 +- libavcodec/x86/hevc_sao_10bit.asm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index c13deb599fc21..8fbbc798a2e65 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -767,7 +767,7 @@ typedef struct AVCodecDescriptor { * Note: If the first 23 bits of the additional bytes are not 0, then damaged * MPEG bitstreams could cause overread and segfault. */ -#define AV_INPUT_BUFFER_PADDING_SIZE 32 +#define AV_INPUT_BUFFER_PADDING_SIZE 64 /** * @ingroup lavc_encoding diff --git a/libavcodec/x86/hevc_sao.asm b/libavcodec/x86/hevc_sao.asm index 888a28afa7c48..756adfee5784c 100644 --- a/libavcodec/x86/hevc_sao.asm +++ b/libavcodec/x86/hevc_sao.asm @@ -198,7 +198,7 @@ HEVC_SAO_BAND_FILTER 64, 2 ;****************************************************************************** %define MAX_PB_SIZE 64 -%define PADDING_SIZE 32 ; AV_INPUT_BUFFER_PADDING_SIZE +%define PADDING_SIZE 64 ; AV_INPUT_BUFFER_PADDING_SIZE %define EDGE_SRCSTRIDE 2 * MAX_PB_SIZE + PADDING_SIZE %macro HEVC_SAO_EDGE_FILTER_INIT 0 diff --git a/libavcodec/x86/hevc_sao_10bit.asm b/libavcodec/x86/hevc_sao_10bit.asm index f81e2d503391d..b30583dd2f878 100644 --- a/libavcodec/x86/hevc_sao_10bit.asm +++ b/libavcodec/x86/hevc_sao_10bit.asm @@ -190,7 +190,7 @@ HEVC_SAO_BAND_FILTER 12, 64, 4 ;****************************************************************************** %define MAX_PB_SIZE 64 -%define PADDING_SIZE 32 ; AV_INPUT_BUFFER_PADDING_SIZE +%define PADDING_SIZE 64 ; AV_INPUT_BUFFER_PADDING_SIZE %define EDGE_SRCSTRIDE 2 * MAX_PB_SIZE + PADDING_SIZE %macro PMINUW 4 From 9b955eece610f7f8b4aa2096b4e0ca738e21edc4 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Thu, 11 Jan 2018 13:21:58 +0800 Subject: [PATCH 1628/2557] examples/vaapi_encode: Remove redundancy check when free context. avcodec_free_context have handle NULL pointer case, so caller doesn't need to check the NULL before call this function. Signe-off-by: Jun Zhao Signed-off-by: Michael Niedermayer --- doc/examples/vaapi_encode.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/examples/vaapi_encode.c b/doc/examples/vaapi_encode.c index f66a4a7c488dc..6425b1c98c354 100644 --- a/doc/examples/vaapi_encode.c +++ b/doc/examples/vaapi_encode.c @@ -217,8 +217,7 @@ int main(int argc, char *argv[]) fclose(fout); av_frame_free(&sw_frame); av_frame_free(&hw_frame); - if (avctx) - avcodec_free_context(&avctx); + avcodec_free_context(&avctx); av_buffer_unref(&hw_device_ctx); return err; From a571a2a65abea24adb3a9fff4b05bc562ce93ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Heusipp?= Date: Thu, 11 Jan 2018 09:11:29 +0100 Subject: [PATCH 1629/2557] avformat/libopenmpt: Fix mixed code and declarations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Heusipp Signed-off-by: Michael Niedermayer --- libavformat/libopenmpt.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libavformat/libopenmpt.c b/libavformat/libopenmpt.c index af6eb1ac4a028..2e22290003895 100644 --- a/libavformat/libopenmpt.c +++ b/libavformat/libopenmpt.c @@ -72,13 +72,14 @@ static int read_header_openmpt(AVFormatContext *s) { AVStream *st; OpenMPTContext *openmpt = s->priv_data; - int64_t size = avio_size(s->pb); - if (size <= 0) - return AVERROR_INVALIDDATA; - char *buf = av_malloc(size); + int64_t size; + char *buf; int ret; - + size = avio_size(s->pb); + if (size <= 0) + return AVERROR_INVALIDDATA; + buf = av_malloc(size); if (!buf) return AVERROR(ENOMEM); size = avio_read(s->pb, buf, size); From 8b1b25a86f1b3c61f1c9742c9b7fff5baa5f1bc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Heusipp?= Date: Thu, 11 Jan 2018 09:11:30 +0100 Subject: [PATCH 1630/2557] avformat/libopenmpt: Update to libopenmpt 0.3 API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit libopenmpt 0.3 deprecates openmpt_module_create_from_memory() and provides a replacement function openmpt_module_create_from_memory2(). Detecting libopenmpt 0.3 can be done at build time via the API version macros provided by libopenmpt. libopenmpt 0.2 did not provide all required macros, however libopenmpt documents the required #define shims that can be safely added for libopenmpt 0.2. Using openmpt_module_create_from_memory2() instead of openmpt_module_create_from_memory() avoids the deprecation warning when building ffmpeg with libopenmpt 0.3. openmpt_module_create_from_memory2() provides more fine-grained error reporting and in particular allows distinguishing out-of-memory from input file parsing errors. Return appropriate ffmpeg errors accordingly. libopenmpt 0.3 is ABI and API compatible with applications built against libopenmpt 0.2. Building ffmpeg with libopenmpt 0.2 is still supported. Signed-off-by: Jörn Heusipp Signed-off-by: Michael Niedermayer --- libavformat/libopenmpt.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/libavformat/libopenmpt.c b/libavformat/libopenmpt.c index 2e22290003895..30c3d6e646f01 100644 --- a/libavformat/libopenmpt.c +++ b/libavformat/libopenmpt.c @@ -21,6 +21,14 @@ #include #include +#include +/* Shims to support libopenmpt < 0.3.0 (as documented by libopenmpt) */ +#if !defined(OPENMPT_API_VERSION_MAKE) +#define OPENMPT_API_VERSION_MAKE(major, minor, patch) (((major)<<24)|((minor)<<16)|((patch)<<0)) +#endif +#if !defined(OPENMPT_API_VERSION_AT_LEAST) +#define OPENMPT_API_VERSION_AT_LEAST(major, minor, patch) (OPENMPT_API_VERSION >= OPENMPT_API_VERSION_MAKE((major), (minor), (patch))) +#endif #include "libavutil/avstring.h" #include "libavutil/opt.h" @@ -74,6 +82,9 @@ static int read_header_openmpt(AVFormatContext *s) OpenMPTContext *openmpt = s->priv_data; int64_t size; char *buf; +#if OPENMPT_API_VERSION_AT_LEAST(0,3,0) + int error; +#endif int ret; size = avio_size(s->pb); @@ -89,10 +100,24 @@ static int read_header_openmpt(AVFormatContext *s) return size; } +#if OPENMPT_API_VERSION_AT_LEAST(0,3,0) + error = OPENMPT_ERROR_OK; + openmpt->module = openmpt_module_create_from_memory2(buf, size, openmpt_logfunc, s, NULL, NULL, &error, NULL, NULL); + av_freep(&buf); + if (!openmpt->module) { + if (error == OPENMPT_ERROR_OUT_OF_MEMORY) + return AVERROR(ENOMEM); + else if (error >= OPENMPT_ERROR_GENERAL) + return AVERROR_INVALIDDATA; + else + return AVERROR_UNKNOWN; + } +#else openmpt->module = openmpt_module_create_from_memory(buf, size, openmpt_logfunc, s, NULL); av_freep(&buf); if (!openmpt->module) return AVERROR_INVALIDDATA; +#endif openmpt->channels = av_get_channel_layout_nb_channels(openmpt->layout); From 43e510d66887fe665b2c736be6ff842418f411c6 Mon Sep 17 00:00:00 2001 From: Harald Gaechter Date: Tue, 28 Nov 2017 09:59:02 +0100 Subject: [PATCH 1631/2557] avdevice/gdigrab: Fix screen size and mouse position calculations on hi-DPI screens Signed-off-by: Harald Gaechter Signed-off-by: Michael Niedermayer --- libavdevice/gdigrab.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libavdevice/gdigrab.c b/libavdevice/gdigrab.c index 87f5012034ce9..ff2ef3b1629f3 100644 --- a/libavdevice/gdigrab.c +++ b/libavdevice/gdigrab.c @@ -235,7 +235,9 @@ gdigrab_read_header(AVFormatContext *s1) AVStream *st = NULL; int bpp; + int horzres; int vertres; + int desktophorzres; int desktopvertres; RECT virtual_rect; RECT clip_rect; @@ -279,11 +281,13 @@ gdigrab_read_header(AVFormatContext *s1) GetClientRect(hwnd, &virtual_rect); } else { /* desktop -- get the right height and width for scaling DPI */ + horzres = GetDeviceCaps(source_hdc, HORZRES); vertres = GetDeviceCaps(source_hdc, VERTRES); + desktophorzres = GetDeviceCaps(source_hdc, DESKTOPHORZRES); desktopvertres = GetDeviceCaps(source_hdc, DESKTOPVERTRES); virtual_rect.left = GetSystemMetrics(SM_XVIRTUALSCREEN); virtual_rect.top = GetSystemMetrics(SM_YVIRTUALSCREEN); - virtual_rect.right = (virtual_rect.left + GetSystemMetrics(SM_CXVIRTUALSCREEN)) * desktopvertres / vertres; + virtual_rect.right = (virtual_rect.left + GetSystemMetrics(SM_CXVIRTUALSCREEN)) * desktophorzres / horzres; virtual_rect.bottom = (virtual_rect.top + GetSystemMetrics(SM_CYVIRTUALSCREEN)) * desktopvertres / vertres; } @@ -447,7 +451,9 @@ static void paint_mouse_pointer(AVFormatContext *s1, struct gdigrab *gdigrab) POINT pos; RECT clip_rect = gdigrab->clip_rect; HWND hwnd = gdigrab->hwnd; + int horzres = GetDeviceCaps(gdigrab->source_hdc, HORZRES); int vertres = GetDeviceCaps(gdigrab->source_hdc, VERTRES); + int desktophorzres = GetDeviceCaps(gdigrab->source_hdc, DESKTOPHORZRES); int desktopvertres = GetDeviceCaps(gdigrab->source_hdc, DESKTOPVERTRES); info.hbmMask = NULL; info.hbmColor = NULL; @@ -483,7 +489,7 @@ static void paint_mouse_pointer(AVFormatContext *s1, struct gdigrab *gdigrab) } //that would keep the correct location of mouse with hidpi screens - pos.x = pos.x * desktopvertres / vertres; + pos.x = pos.x * desktophorzres / horzres; pos.y = pos.y * desktopvertres / vertres; av_log(s1, AV_LOG_DEBUG, "Cursor pos (%li,%li) -> (%li,%li)\n", From 58e16a4f4b70b00e1ae14c8a52aea49000fa34a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Martinez?= Date: Fri, 5 Jan 2018 11:09:01 +0100 Subject: [PATCH 1632/2557] avcodec/ffv1enc: mark RGB48 support as non-experimental Resulting bitstream was tested with a conformance checker using the last draft of FFV1 specifications. Signed-off-by: Michael Niedermayer Also the files are already in the wild, and decoder support is thus needed. And with decoders widely supporting it, there is no advantage in not allowing it in the encoder. The exact bitstream format may change in future versions of the spec, if improvments are found. --- libavcodec/ffv1enc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index 09df4c0c57f07..c0c1558ffe634 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -630,10 +630,6 @@ FF_ENABLE_DEPRECATION_WARNINGS s->bits_per_raw_sample = 16; s->use32bit = 1; s->version = FFMAX(s->version, 1); - if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { - av_log(avctx, AV_LOG_ERROR, "16bit RGB is experimental and under development, only use it for experiments\n"); - return AVERROR_INVALIDDATA; - } break; case AV_PIX_FMT_0RGB32: s->colorspace = 1; From 9147c0975533c83564b1ba47f22952b291b80282 Mon Sep 17 00:00:00 2001 From: Richard Shaffer Date: Thu, 11 Jan 2018 14:28:52 -0800 Subject: [PATCH 1633/2557] avformat/http: fix memory leak in parse_cookie. Signed-off-by: Michael Niedermayer --- libavformat/http.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/http.c b/libavformat/http.c index 4806b1e59b38f..510b23375a301 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -824,6 +824,7 @@ static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies) } } } + av_dict_free(&new_params); // duplicate the cookie name (dict will dupe the value) if (!(eql = strchr(p, '='))) return AVERROR(EINVAL); From 7dbbb75ee32f87108ca9e15f5551dbbe69fe2641 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 11 Jan 2018 22:47:10 +0100 Subject: [PATCH 1634/2557] avcodec/arm/sbrdsp_neon: Use a free register instead of putting 2 things in one Fixes high pitched shriek Fixes: 25420848_1478428308873746_4255813235963330560_n.mp4 Reported-by: Dale Curtis Reviewed-by: Dale Curtis Signed-off-by: Michael Niedermayer --- libavcodec/arm/sbrdsp_neon.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/arm/sbrdsp_neon.S b/libavcodec/arm/sbrdsp_neon.S index e66abd682a8fe..003b04ea05653 100644 --- a/libavcodec/arm/sbrdsp_neon.S +++ b/libavcodec/arm/sbrdsp_neon.S @@ -336,11 +336,11 @@ function ff_sbr_hf_apply_noise_0_neon, export=1 vld1.32 {d0}, [r0,:64] vld1.32 {d6}, [lr,:64] vld1.32 {d2[]}, [r1,:32]! - vld1.32 {d3[]}, [r2,:32]! + vld1.32 {d18[]}, [r2,:32]! vceq.f32 d4, d2, #0 veor d2, d2, d3 vmov d1, d0 - vmla.f32 d0, d6, d3 + vmla.f32 d0, d6, d18 vadd.f32 s2, s2, s4 vbif d0, d1, d4 vst1.32 {d0}, [r0,:64]! From 2cd718a4c52f3225d36d35055f16ef923c03aeac Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 31 Dec 2017 22:47:38 +0100 Subject: [PATCH 1635/2557] avcodec/opus: Add {} over multiline if() body Signed-off-by: Michael Niedermayer --- libavcodec/opus.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/opus.c b/libavcodec/opus.c index 9cbf4aed92868..aa827b604c533 100644 --- a/libavcodec/opus.c +++ b/libavcodec/opus.c @@ -566,13 +566,14 @@ void ff_celt_bitalloc(CeltFrame *f, OpusRangeCoder *rc, int encode) int bits2[CELT_MAX_BANDS]; /* Spread */ - if (opus_rc_tell(rc) + 4 <= f->framebits) + if (opus_rc_tell(rc) + 4 <= f->framebits) { if (encode) ff_opus_rc_enc_cdf(rc, f->spread, ff_celt_model_spread); else f->spread = ff_opus_rc_dec_cdf(rc, ff_celt_model_spread); - else + } else { f->spread = CELT_SPREAD_NORMAL; + } /* Initialize static allocation caps */ for (i = 0; i < CELT_MAX_BANDS; i++) From 860d991fcd715233b5b9eb1f6c7bf0aadefb6061 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 4 Jun 2017 01:53:58 +0200 Subject: [PATCH 1636/2557] avcodec/utils: Avoid hardcoding duplicated types in sizeof() Signed-off-by: Michael Niedermayer --- libavcodec/utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 4d736d2e7d2fd..4c718432ad06c 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -608,7 +608,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code ff_lock_avcodec(avctx, codec); - avctx->internal = av_mallocz(sizeof(AVCodecInternal)); + avctx->internal = av_mallocz(sizeof(*avctx->internal)); if (!avctx->internal) { ret = AVERROR(ENOMEM); goto end; @@ -1099,7 +1099,7 @@ void avsubtitle_free(AVSubtitle *sub) av_freep(&sub->rects); - memset(sub, 0, sizeof(AVSubtitle)); + memset(sub, 0, sizeof(*sub)); } av_cold int avcodec_close(AVCodecContext *avctx) From 0c31a3876d9a522add43ab62a9bcd3d857b28436 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 19 Dec 2017 23:49:41 +0100 Subject: [PATCH 1637/2557] avfilter/vf_framerate: simplify filter The framerate filter was quite convoluted with some filter_frame / request_frame logic bugs. It seemed easier to rewrite the whole filter_frame / request_frame part and also the frame interpolation ratio calculation part in one step. Notable changes: - The filter now only stores 2 frames instead of 3 - filter_frame outputs all the frames it can to be able to handle consecutive filter_frame calls which previously caused early drops of buffered frames. - because of this, request_frame is largely simplified and it only outputs frames on flush. Previously consecuitve request_frame calls could cause the filter to think it is in flush mode filling its buffer with the same frames causing a "ghost" effect on the output. - PTS discontinuities are handled better - frames with unknown PTS values are now dropped Fixes ticket #4870. Probably fixes ticket #5493. Signed-off-by: Marton Balint --- libavfilter/vf_framerate.c | 361 ++++++----------------- tests/ref/fate/filter-framerate-12bit-up | 1 + 2 files changed, 95 insertions(+), 267 deletions(-) diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index 38f45a8033c13..a5ae6ddb7135c 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -39,8 +39,6 @@ #include "internal.h" #include "video.h" -#define N_SRCE 3 - typedef struct FrameRateContext { const AVClass *class; // parameters @@ -55,30 +53,25 @@ typedef struct FrameRateContext { int line_size[4]; ///< bytes of pixel data per line for each plane int vsub; - int frst, next, prev, crnt, last; - int pending_srce_frames; ///< how many input frames are still waiting to be processed - int flush; ///< are we flushing final frames - int pending_end_frame; ///< flag indicating we are waiting to call filter_frame() - AVRational srce_time_base; ///< timebase of source - AVRational dest_time_base; ///< timebase of destination - int32_t dest_frame_num; - int64_t last_dest_frame_pts; ///< pts of the last frame output - int64_t average_srce_pts_dest_delta;///< average input pts delta converted from input rate to output rate - int64_t average_dest_pts_delta; ///< calculated average output pts delta av_pixelutils_sad_fn sad; ///< Sum of the absolute difference function (scene detect only) double prev_mafd; ///< previous MAFD (scene detect only) - AVFrame *srce[N_SRCE]; ///< buffered source frames - int64_t srce_pts_dest[N_SRCE]; ///< pts for source frames scaled to output timebase - double srce_score[N_SRCE]; ///< scene change score compared to the next srce frame - int64_t pts; ///< pts of frame we are working on - int max; int bitdepth; AVFrame *work; + + AVFrame *f0; ///< last frame + AVFrame *f1; ///< current frame + int64_t pts0; ///< last frame pts in dest_time_base + int64_t pts1; ///< current frame pts in dest_time_base + int64_t delta; ///< pts1 to pts0 delta + double score; ///< scene change score (f0 to f1) + int flush; ///< 1 if the filter is being flushed + int64_t start_pts; ///< pts of the first output frame + int64_t n; ///< output frame counter } FrameRateContext; #define OFFSET(x) offsetof(FrameRateContext, x) @@ -102,27 +95,6 @@ static const AVOption framerate_options[] = { AVFILTER_DEFINE_CLASS(framerate); -static void next_source(AVFilterContext *ctx) -{ - FrameRateContext *s = ctx->priv; - int i; - - ff_dlog(ctx, "next_source()\n"); - - if (s->srce[s->last] && s->srce[s->last] != s->srce[s->last-1]) { - ff_dlog(ctx, "next_source() unlink %d\n", s->last); - av_frame_free(&s->srce[s->last]); - } - for (i = s->last; i > s->frst; i--) { - ff_dlog(ctx, "next_source() copy %d to %d\n", i - 1, i); - s->srce[i] = s->srce[i - 1]; - s->srce_score[i] = s->srce_score[i - 1]; - } - ff_dlog(ctx, "next_source() make %d null\n", s->frst); - s->srce[s->frst] = NULL; - s->srce_score[s->frst] = -1.0; -} - static av_always_inline int64_t sad_8x8_16(const uint16_t *src1, ptrdiff_t stride1, const uint16_t *src2, ptrdiff_t stride2) { @@ -307,28 +279,25 @@ static int filter_slice16(AVFilterContext *ctx, void *arg, int job, int nb_jobs) return 0; } -static int blend_frames(AVFilterContext *ctx, int interpolate, - int src1, int src2) +static int blend_frames(AVFilterContext *ctx, int interpolate) { FrameRateContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; double interpolate_scene_score = 0; - if ((s->flags & FRAMERATE_FLAG_SCD) && s->srce[src1] && s->srce[src2]) { - int i1 = src1 < src2 ? src1 : src2; - int i2 = src1 < src2 ? src2 : src1; - if (i2 == i1 + 1 && s->srce_score[i1] >= 0.0) - interpolate_scene_score = s->srce_score[i1]; + if ((s->flags & FRAMERATE_FLAG_SCD)) { + if (s->score >= 0.0) + interpolate_scene_score = s->score; else - interpolate_scene_score = s->srce_score[i1] = get_scene_score(ctx, s->srce[i1], s->srce[i2]); + interpolate_scene_score = s->score = get_scene_score(ctx, s->f0, s->f1); ff_dlog(ctx, "blend_frames() interpolate scene score:%f\n", interpolate_scene_score); } // decide if the shot-change detection allows us to blend two frames - if (interpolate_scene_score < s->scene_score && s->srce[src2]) { + if (interpolate_scene_score < s->scene_score) { ThreadData td; - td.copy_src1 = s->srce[src1]; - td.copy_src2 = s->srce[src2]; - td.src2_factor = FFABS(interpolate); + td.copy_src1 = s->f0; + td.copy_src2 = s->f1; + td.src2_factor = interpolate; td.src1_factor = s->max - td.src2_factor; // get work-space for output frame @@ -336,7 +305,7 @@ static int blend_frames(AVFilterContext *ctx, int interpolate, if (!s->work) return AVERROR(ENOMEM); - av_frame_copy_props(s->work, s->srce[s->crnt]); + av_frame_copy_props(s->work, s->f0); ff_dlog(ctx, "blend_frames() INTERPOLATE to create work frame\n"); ctx->internal->execute(ctx, s->bitdepth == 8 ? filter_slice8 : filter_slice16, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); @@ -345,198 +314,65 @@ static int blend_frames(AVFilterContext *ctx, int interpolate, return 0; } -static int process_work_frame(AVFilterContext *ctx, int stop) +static int process_work_frame(AVFilterContext *ctx) { FrameRateContext *s = ctx->priv; - int64_t work_next_pts; + int64_t work_pts; int interpolate; - int src1, src2; - - ff_dlog(ctx, "process_work_frame()\n"); - - ff_dlog(ctx, "process_work_frame() pending_input_frames %d\n", s->pending_srce_frames); - - if (s->srce[s->prev]) ff_dlog(ctx, "process_work_frame() srce prev pts:%"PRId64"\n", s->srce[s->prev]->pts); - if (s->srce[s->crnt]) ff_dlog(ctx, "process_work_frame() srce crnt pts:%"PRId64"\n", s->srce[s->crnt]->pts); - if (s->srce[s->next]) ff_dlog(ctx, "process_work_frame() srce next pts:%"PRId64"\n", s->srce[s->next]->pts); + int ret; - if (!s->srce[s->crnt]) { - // the filter cannot do anything - ff_dlog(ctx, "process_work_frame() no current frame cached: move on to next frame, do not output a frame\n"); - next_source(ctx); + if (!s->f1) return 0; - } - - work_next_pts = s->pts + s->average_dest_pts_delta; - - ff_dlog(ctx, "process_work_frame() work crnt pts:%"PRId64"\n", s->pts); - ff_dlog(ctx, "process_work_frame() work next pts:%"PRId64"\n", work_next_pts); - if (s->srce[s->prev]) - ff_dlog(ctx, "process_work_frame() srce prev pts:%"PRId64" at dest time base:%u/%u\n", - s->srce_pts_dest[s->prev], s->dest_time_base.num, s->dest_time_base.den); - if (s->srce[s->crnt]) - ff_dlog(ctx, "process_work_frame() srce crnt pts:%"PRId64" at dest time base:%u/%u\n", - s->srce_pts_dest[s->crnt], s->dest_time_base.num, s->dest_time_base.den); - if (s->srce[s->next]) - ff_dlog(ctx, "process_work_frame() srce next pts:%"PRId64" at dest time base:%u/%u\n", - s->srce_pts_dest[s->next], s->dest_time_base.num, s->dest_time_base.den); - - av_assert0(s->srce[s->next]); - - // should filter be skipping input frame (output frame rate is lower than input frame rate) - if (!s->flush && s->pts >= s->srce_pts_dest[s->next]) { - ff_dlog(ctx, "process_work_frame() work crnt pts >= srce next pts: SKIP FRAME, move on to next frame, do not output a frame\n"); - next_source(ctx); - s->pending_srce_frames--; + if (!s->f0 && !s->flush) return 0; - } - // calculate interpolation - interpolate = av_rescale(s->pts - s->srce_pts_dest[s->crnt], s->max, s->average_srce_pts_dest_delta); - ff_dlog(ctx, "process_work_frame() interpolate:%d/%d\n", interpolate, s->max); - src1 = s->crnt; - if (interpolate > s->interp_end) { - ff_dlog(ctx, "process_work_frame() source is:NEXT\n"); - src1 = s->next; - } - if (s->srce[s->prev] && interpolate < -s->interp_end) { - ff_dlog(ctx, "process_work_frame() source is:PREV\n"); - src1 = s->prev; - } + work_pts = s->start_pts + av_rescale_q(s->n, av_inv_q(s->dest_frame_rate), s->dest_time_base); + + if (work_pts >= s->pts1 && !s->flush) + return 0; - // decide whether to blend two frames - if ((interpolate >= s->interp_start && interpolate <= s->interp_end) || (interpolate <= -s->interp_start && interpolate >= -s->interp_end)) { - if (interpolate > 0) { - ff_dlog(ctx, "process_work_frame() interpolate source is:NEXT\n"); - src2 = s->next; + if (!s->f0) { + s->work = av_frame_clone(s->f1); + } else { + if (work_pts >= s->pts1 + s->delta && s->flush) + return 0; + + interpolate = av_rescale(work_pts - s->pts0, s->max, s->delta); + ff_dlog(ctx, "process_work_frame() interpolate:%d/%d\n", interpolate, s->max); + if (interpolate > s->interp_end) { + s->work = av_frame_clone(s->f1); + } else if (interpolate < s->interp_start) { + s->work = av_frame_clone(s->f0); } else { - ff_dlog(ctx, "process_work_frame() interpolate source is:PREV\n"); - src2 = s->prev; + ret = blend_frames(ctx, interpolate); + if (ret < 0) + return ret; + if (ret == 0) + s->work = av_frame_clone(interpolate > (s->max >> 1) ? s->f1 : s->f0); } - if (blend_frames(ctx, interpolate, src1, src2)) - goto copy_done; - else - ff_dlog(ctx, "process_work_frame() CUT - DON'T INTERPOLATE\n"); } - ff_dlog(ctx, "process_work_frame() COPY to the work frame\n"); - // copy the frame we decided is our base source - s->work = av_frame_clone(s->srce[src1]); if (!s->work) return AVERROR(ENOMEM); -copy_done: - s->work->pts = s->pts; - - // should filter be re-using input frame (output frame rate is higher than input frame rate) - if (!s->flush && (work_next_pts + s->average_dest_pts_delta) < (s->srce_pts_dest[s->crnt] + s->average_srce_pts_dest_delta)) { - ff_dlog(ctx, "process_work_frame() REPEAT FRAME\n"); - } else { - ff_dlog(ctx, "process_work_frame() CONSUME FRAME, move to next frame\n"); - s->pending_srce_frames--; - next_source(ctx); - } - ff_dlog(ctx, "process_work_frame() output a frame\n"); - s->dest_frame_num++; - if (stop) - s->pending_end_frame = 0; - s->last_dest_frame_pts = s->work->pts; + s->work->pts = work_pts; + s->n++; return 1; } -static void set_srce_frame_dest_pts(AVFilterContext *ctx) -{ - FrameRateContext *s = ctx->priv; - - ff_dlog(ctx, "set_srce_frame_output_pts()\n"); - - // scale the input pts from the timebase difference between input and output - if (s->srce[s->prev]) - s->srce_pts_dest[s->prev] = av_rescale_q(s->srce[s->prev]->pts, s->srce_time_base, s->dest_time_base); - if (s->srce[s->crnt]) - s->srce_pts_dest[s->crnt] = av_rescale_q(s->srce[s->crnt]->pts, s->srce_time_base, s->dest_time_base); - if (s->srce[s->next]) - s->srce_pts_dest[s->next] = av_rescale_q(s->srce[s->next]->pts, s->srce_time_base, s->dest_time_base); -} - -static void set_work_frame_pts(AVFilterContext *ctx) -{ - FrameRateContext *s = ctx->priv; - int64_t pts, average_srce_pts_delta = 0; - - ff_dlog(ctx, "set_work_frame_pts()\n"); - - av_assert0(s->srce[s->next]); - av_assert0(s->srce[s->crnt]); - - ff_dlog(ctx, "set_work_frame_pts() srce crnt pts:%"PRId64"\n", s->srce[s->crnt]->pts); - ff_dlog(ctx, "set_work_frame_pts() srce next pts:%"PRId64"\n", s->srce[s->next]->pts); - if (s->srce[s->prev]) - ff_dlog(ctx, "set_work_frame_pts() srce prev pts:%"PRId64"\n", s->srce[s->prev]->pts); - - average_srce_pts_delta = s->average_srce_pts_dest_delta; - ff_dlog(ctx, "set_work_frame_pts() initial average srce pts:%"PRId64"\n", average_srce_pts_delta); - - set_srce_frame_dest_pts(ctx); - - // calculate the PTS delta - if ((pts = (s->srce_pts_dest[s->next] - s->srce_pts_dest[s->crnt]))) { - average_srce_pts_delta = average_srce_pts_delta?((average_srce_pts_delta+pts)>>1):pts; - } else if (s->srce[s->prev] && (pts = (s->srce_pts_dest[s->crnt] - s->srce_pts_dest[s->prev]))) { - average_srce_pts_delta = average_srce_pts_delta?((average_srce_pts_delta+pts)>>1):pts; - } - - s->average_srce_pts_dest_delta = average_srce_pts_delta; - ff_dlog(ctx, "set_work_frame_pts() average srce pts:%"PRId64"\n", average_srce_pts_delta); - ff_dlog(ctx, "set_work_frame_pts() average srce pts:%"PRId64" at dest time base:%u/%u\n", - s->average_srce_pts_dest_delta, s->dest_time_base.num, s->dest_time_base.den); - - if (ctx->inputs[0] && !s->average_dest_pts_delta) { - int64_t d = av_q2d(av_inv_q(av_mul_q(s->dest_time_base, s->dest_frame_rate))); - s->average_dest_pts_delta = d; - ff_dlog(ctx, "set_work_frame_pts() average dest pts delta:%"PRId64"\n", s->average_dest_pts_delta); - } - - if (!s->dest_frame_num) { - s->pts = s->last_dest_frame_pts = s->srce_pts_dest[s->crnt]; - } else { - s->pts = s->last_dest_frame_pts + s->average_dest_pts_delta; - } - - ff_dlog(ctx, "set_work_frame_pts() calculated pts:%"PRId64" at dest time base:%u/%u\n", - s->pts, s->dest_time_base.num, s->dest_time_base.den); -} - static av_cold int init(AVFilterContext *ctx) { FrameRateContext *s = ctx->priv; - int i; - - s->dest_frame_num = 0; - - s->crnt = (N_SRCE)>>1; - s->last = N_SRCE - 1; - - s->next = s->crnt - 1; - s->prev = s->crnt + 1; - - for (i = 0; i < N_SRCE; i++) - s->srce_score[i] = -1.0; - + s->start_pts = AV_NOPTS_VALUE; return 0; } static av_cold void uninit(AVFilterContext *ctx) { FrameRateContext *s = ctx->priv; - int i; - - for (i = s->frst; i < s->last; i++) { - if (s->srce[i] && (s->srce[i] != s->srce[i + 1])) - av_frame_free(&s->srce[i]); - } - av_frame_free(&s->srce[s->last]); + av_frame_free(&s->f0); + av_frame_free(&s->f1); } static int query_formats(AVFilterContext *ctx) @@ -593,28 +429,48 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) int ret; AVFilterContext *ctx = inlink->dst; FrameRateContext *s = ctx->priv; - - // we have one new frame - s->pending_srce_frames++; + int64_t pts; if (inpicref->interlaced_frame) av_log(ctx, AV_LOG_WARNING, "Interlaced frame found - the output will not be correct.\n"); - // store the pointer to the new frame - av_frame_free(&s->srce[s->frst]); - s->srce[s->frst] = inpicref; + if (inpicref->pts == AV_NOPTS_VALUE) { + av_log(ctx, AV_LOG_WARNING, "Ignoring frame without PTS.\n"); + return 0; + } - if (!s->pending_end_frame && s->srce[s->crnt]) { - set_work_frame_pts(ctx); - s->pending_end_frame = 1; - } else { - set_srce_frame_dest_pts(ctx); + pts = av_rescale_q(inpicref->pts, s->srce_time_base, s->dest_time_base); + if (s->f1 && pts == s->pts1) { + av_log(ctx, AV_LOG_WARNING, "Ignoring frame with same PTS.\n"); + return 0; } - ret = process_work_frame(ctx, 1); - if (ret < 0) - return ret; - return ret ? ff_filter_frame(ctx->outputs[0], s->work) : 0; + av_frame_free(&s->f0); + s->f0 = s->f1; + s->pts0 = s->pts1; + s->f1 = inpicref; + s->pts1 = pts; + s->delta = s->pts1 - s->pts0; + s->score = -1.0; + + if (s->delta < 0) { + av_log(ctx, AV_LOG_WARNING, "PTS discontinuity.\n"); + s->start_pts = s->pts1; + s->n = 0; + av_frame_free(&s->f0); + } + + if (s->start_pts == AV_NOPTS_VALUE) + s->start_pts = s->pts1; + + do { + ret = process_work_frame(ctx); + if (ret <= 0) + return ret; + ret = ff_filter_frame(ctx->outputs[0], s->work); + } while (ret >= 0); + + return ret; } static int config_output(AVFilterLink *outlink) @@ -666,50 +522,21 @@ static int request_frame(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; FrameRateContext *s = ctx->priv; - int ret, i; + int ret; ff_dlog(ctx, "request_frame()\n"); - // if there is no "next" frame AND we are not in flush then get one from our input filter - if (!s->srce[s->frst] && !s->flush) - goto request; - - ff_dlog(ctx, "request_frame() REPEAT or FLUSH\n"); - - if (s->pending_srce_frames <= 0) { - ff_dlog(ctx, "request_frame() nothing else to do, return:EOF\n"); - return AVERROR_EOF; - } - - // otherwise, make brand-new frame and pass to our output filter - ff_dlog(ctx, "request_frame() FLUSH\n"); - - // back fill at end of file when source has no more frames - for (i = s->last; i > s->frst; i--) { - if (!s->srce[i - 1] && s->srce[i]) { - ff_dlog(ctx, "request_frame() copy:%d to:%d\n", i, i - 1); - s->srce[i - 1] = s->srce[i]; - } - } - - set_work_frame_pts(ctx); - ret = process_work_frame(ctx, 0); - if (ret < 0) - return ret; - if (ret) - return ff_filter_frame(ctx->outputs[0], s->work); - -request: - ff_dlog(ctx, "request_frame() call source's request_frame()\n"); ret = ff_request_frame(ctx->inputs[0]); - if (ret < 0 && (ret != AVERROR_EOF)) { - ff_dlog(ctx, "request_frame() source's request_frame() returned error:%d\n", ret); - return ret; - } else if (ret == AVERROR_EOF) { + if (ret == AVERROR_EOF && s->f1 && !s->flush) { s->flush = 1; + ret = process_work_frame(ctx); + if (ret < 0) + return ret; + ret = ret ? ff_filter_frame(ctx->outputs[0], s->work) : AVERROR_EOF; } + ff_dlog(ctx, "request_frame() source's request_frame() returned:%d\n", ret); - return 0; + return ret; } static const AVFilterPad framerate_inputs[] = { diff --git a/tests/ref/fate/filter-framerate-12bit-up b/tests/ref/fate/filter-framerate-12bit-up index 686fe8e82bd71..ef709a8fc8052 100644 --- a/tests/ref/fate/filter-framerate-12bit-up +++ b/tests/ref/fate/filter-framerate-12bit-up @@ -62,3 +62,4 @@ 0, 56, 56, 1, 307200, 0x8cf55128 0, 57, 57, 1, 307200, 0x4e740b42 0, 58, 58, 1, 307200, 0x8e7e705c +0, 59, 59, 1, 307200, 0xe73f29ef From 1eb7c1d49d67fe0f21c71fb87d6c1fa8542f8cef Mon Sep 17 00:00:00 2001 From: Rodger Combs Date: Mon, 18 Dec 2017 06:18:57 -0600 Subject: [PATCH 1638/2557] lavc/libx265: support all color parameters that x265 does --- libavcodec/libx265.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 52ad2312a3d76..3c97800ccb5a7 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -115,11 +115,11 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) ctx->params->sourceHeight = avctx->height; ctx->params->bEnablePsnr = !!(avctx->flags & AV_CODEC_FLAG_PSNR); - if ((avctx->color_primaries <= AVCOL_PRI_BT2020 && + if ((avctx->color_primaries <= AVCOL_PRI_SMPTE432 && avctx->color_primaries != AVCOL_PRI_UNSPECIFIED) || - (avctx->color_trc <= AVCOL_TRC_BT2020_12 && + (avctx->color_trc <= AVCOL_TRC_ARIB_STD_B67 && avctx->color_trc != AVCOL_TRC_UNSPECIFIED) || - (avctx->colorspace <= AVCOL_SPC_BT2020_CL && + (avctx->colorspace <= AVCOL_SPC_ICTCP && avctx->colorspace != AVCOL_SPC_UNSPECIFIED)) { ctx->params->vui.bEnableVideoSignalTypePresentFlag = 1; From fcb681ac3edd708f26c3b5014c06e32fd2723887 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 13 Jan 2018 11:46:29 +0000 Subject: [PATCH 1639/2557] aacenc: use the fast coder as the default The twoloop coder sounds decent at low bitrates, however at higher bitrates it sounds worse than the fast coder (which used to be the old twoloop coder before October 2015) and needs quite a lot more CPU. Change the default to fast. It has been well tested and has had little changes over the years so its been confirmed to be quite stable. Also change its description (not valid for more than a year) and the documentation. Signed-off-by: Rostislav Pehlivanov --- doc/encoders.texi | 9 ++++----- libavcodec/aacenc.c | 4 ++-- tests/fate/aac.mak | 20 ++++++++++---------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index 88ef8f9b230b4..6a410a8cb643a 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -64,7 +64,6 @@ to find an optimal combination by adding or subtracting a specific value from all quantizers and adjusting some individual quantizer a little. Will tune itself based on whether @option{aac_is}, @option{aac_ms} and @option{aac_pns} are enabled. -This is the default choice for a coder. @item anmr Average noise to mask ratio (ANMR) trellis-based solution. @@ -77,10 +76,10 @@ Not currently recommended. @item fast Constant quantizer method. -This method sets a constant quantizer for all bands. This is the fastest of all -the methods and has no rate control or support for @option{aac_is} or -@option{aac_pns}. -Not recommended. +Uses a cheaper version of twoloop algorithm that doesn't try to do as many +clever adjustments. Worse with low bitrates (less than 64kbps), but is better +and much faster at higher bitrates. +This is the default choice for a coder @end table diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index fa7932d42d71c..6d94c76905994 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -1118,10 +1118,10 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) #define AACENC_FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM static const AVOption aacenc_options[] = { - {"aac_coder", "Coding algorithm", offsetof(AACEncContext, options.coder), AV_OPT_TYPE_INT, {.i64 = AAC_CODER_TWOLOOP}, 0, AAC_CODER_NB-1, AACENC_FLAGS, "coder"}, + {"aac_coder", "Coding algorithm", offsetof(AACEncContext, options.coder), AV_OPT_TYPE_INT, {.i64 = AAC_CODER_FAST}, 0, AAC_CODER_NB-1, AACENC_FLAGS, "coder"}, {"anmr", "ANMR method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_ANMR}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"}, {"twoloop", "Two loop searching method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_TWOLOOP}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"}, - {"fast", "Constant quantizer", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAST}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"}, + {"fast", "Default fast search", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAST}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"}, {"aac_ms", "Force M/S stereo coding", offsetof(AACEncContext, options.mid_side), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AACENC_FLAGS}, {"aac_is", "Intensity stereo coding", offsetof(AACEncContext, options.intensity_stereo), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS}, {"aac_pns", "Perceptual noise substitution", offsetof(AACEncContext, options.pns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS}, diff --git a/tests/fate/aac.mak b/tests/fate/aac.mak index e8cbcef54d7a9..5bc6779c39db9 100644 --- a/tests/fate/aac.mak +++ b/tests/fate/aac.mak @@ -154,7 +154,7 @@ fate-aac-aref-encode: CMD = enc_dec_pcm adts wav s16le $(REF) -c:a aac -aac_is 0 fate-aac-aref-encode: CMP = stddev fate-aac-aref-encode: REF = ./tests/data/asynth-44100-2.wav fate-aac-aref-encode: CMP_SHIFT = -4096 -fate-aac-aref-encode: CMP_TARGET = 669 +fate-aac-aref-encode: CMP_TARGET = 596 fate-aac-aref-encode: SIZE_TOLERANCE = 2464 fate-aac-aref-encode: FUZZ = 89 @@ -163,7 +163,7 @@ fate-aac-ln-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-ref fate-aac-ln-encode: CMP = stddev fate-aac-ln-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-ln-encode: CMP_SHIFT = -4096 -fate-aac-ln-encode: CMP_TARGET = 61 +fate-aac-ln-encode: CMP_TARGET = 72 fate-aac-ln-encode: SIZE_TOLERANCE = 3560 fate-aac-ln-encode: FUZZ = 30 @@ -172,7 +172,7 @@ fate-aac-ln-encode-128k: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audi fate-aac-ln-encode-128k: CMP = stddev fate-aac-ln-encode-128k: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-ln-encode-128k: CMP_SHIFT = -4096 -fate-aac-ln-encode-128k: CMP_TARGET = 800 +fate-aac-ln-encode-128k: CMP_TARGET = 622 fate-aac-ln-encode-128k: SIZE_TOLERANCE = 3560 fate-aac-ln-encode-128k: FUZZ = 5 @@ -181,7 +181,7 @@ fate-aac-pns-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-re fate-aac-pns-encode: CMP = stddev fate-aac-pns-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-pns-encode: CMP_SHIFT = -4096 -fate-aac-pns-encode: CMP_TARGET = 616 +fate-aac-pns-encode: CMP_TARGET = 655 fate-aac-pns-encode: SIZE_TOLERANCE = 3560 fate-aac-pns-encode: FUZZ = 74 @@ -190,7 +190,7 @@ fate-aac-tns-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-re fate-aac-tns-encode: CMP = stddev fate-aac-tns-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-tns-encode: CMP_SHIFT = -4096 -fate-aac-tns-encode: CMP_TARGET = 817 +fate-aac-tns-encode: CMP_TARGET = 637 fate-aac-tns-encode: FUZZ = 7 fate-aac-tns-encode: SIZE_TOLERANCE = 3560 @@ -199,7 +199,7 @@ fate-aac-is-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-ref fate-aac-is-encode: CMP = stddev fate-aac-is-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-is-encode: CMP_SHIFT = -4096 -fate-aac-is-encode: CMP_TARGET = 615 +fate-aac-is-encode: CMP_TARGET = 514 fate-aac-is-encode: SIZE_TOLERANCE = 3560 fate-aac-is-encode: FUZZ = 10 @@ -208,7 +208,7 @@ fate-aac-ms-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-ref fate-aac-ms-encode: CMP = stddev fate-aac-ms-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-ms-encode: CMP_SHIFT = -4096 -fate-aac-ms-encode: CMP_TARGET = 675 +fate-aac-ms-encode: CMP_TARGET = 558 fate-aac-ms-encode: SIZE_TOLERANCE = 3560 fate-aac-ms-encode: FUZZ = 15 @@ -217,7 +217,7 @@ fate-aac-ltp-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-re fate-aac-ltp-encode: CMP = stddev fate-aac-ltp-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-ltp-encode: CMP_SHIFT = -4096 -fate-aac-ltp-encode: CMP_TARGET = 1270 +fate-aac-ltp-encode: CMP_TARGET = 1207 fate-aac-ltp-encode: SIZE_TOLERANCE = 3560 fate-aac-ltp-encode: FUZZ = 17 @@ -227,7 +227,7 @@ fate-aac-yoraw-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio- fate-aac-yoraw-encode: CMP = stddev fate-aac-yoraw-encode: REF = $(SAMPLES)/audio-reference/yo.raw-short.wav fate-aac-yoraw-encode: CMP_SHIFT = -12288 -fate-aac-yoraw-encode: CMP_TARGET = 259 +fate-aac-yoraw-encode: CMP_TARGET = 226 fate-aac-yoraw-encode: SIZE_TOLERANCE = 3560 fate-aac-yoraw-encode: FUZZ = 17 @@ -237,7 +237,7 @@ fate-aac-pred-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-r fate-aac-pred-encode: CMP = stddev fate-aac-pred-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-pred-encode: CMP_SHIFT = -4096 -fate-aac-pred-encode: CMP_TARGET = 841 +fate-aac-pred-encode: CMP_TARGET = 662 fate-aac-pred-encode: FUZZ = 12 fate-aac-pred-encode: SIZE_TOLERANCE = 3560 From 6c4b9eb935b677e6f562660caf145b73ea49cf30 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 13 Jan 2018 12:03:49 +0000 Subject: [PATCH 1640/2557] fate: remove the fate-aac-ltp-encode test It tests a useless profile which sounds no better than regular aac and which takes extremely long to encoder something. Also it has been behind experimental flag for as long as it has been supported. Should be removed altogether sometime in the future. --- tests/fate/aac.mak | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/fate/aac.mak b/tests/fate/aac.mak index 5bc6779c39db9..bd283225c1f91 100644 --- a/tests/fate/aac.mak +++ b/tests/fate/aac.mak @@ -212,15 +212,6 @@ fate-aac-ms-encode: CMP_TARGET = 558 fate-aac-ms-encode: SIZE_TOLERANCE = 3560 fate-aac-ms-encode: FUZZ = 15 -FATE_AAC_ENCODE += fate-aac-ltp-encode -fate-aac-ltp-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -strict -2 -c:a aac -profile:a aac_ltp -aac_pns 0 -aac_is 0 -aac_ms 0 -aac_tns 0 -b:a 36k -fflags +bitexact -flags +bitexact -fate-aac-ltp-encode: CMP = stddev -fate-aac-ltp-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -fate-aac-ltp-encode: CMP_SHIFT = -4096 -fate-aac-ltp-encode: CMP_TARGET = 1207 -fate-aac-ltp-encode: SIZE_TOLERANCE = 3560 -fate-aac-ltp-encode: FUZZ = 17 - #Ticket1784 FATE_AAC_ENCODE += fate-aac-yoraw-encode fate-aac-yoraw-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/yo.raw-short.wav -c:a aac -fflags +bitexact -flags +bitexact From c7d726f7f466f69af8321a5e01133e64b4885f53 Mon Sep 17 00:00:00 2001 From: Daniil Cherednik Date: Tue, 9 Jan 2018 21:15:20 +0300 Subject: [PATCH 1641/2557] opusenc_psy: Typo, use all coeffs in range for band tonality calculation --- libavcodec/opusenc_psy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/opusenc_psy.c b/libavcodec/opusenc_psy.c index b7126033441e3..8aded2140de15 100644 --- a/libavcodec/opusenc_psy.c +++ b/libavcodec/opusenc_psy.c @@ -119,7 +119,7 @@ static void step_collect_psy_metrics(OpusPsyContext *s, int index) for (j = 0; j < range; j++) { const float c_s = coeffs[j]*coeffs[j]; - dist_dev = (avg_c_s - c_s)*(avg_c_s - c_s); + dist_dev += (avg_c_s - c_s)*(avg_c_s - c_s); } st->tone[ch][i] += sqrtf(dist_dev); From 56e11ebf55a5e51a8a7131d382c2020e35d34f42 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 13 Jan 2018 18:03:42 +0000 Subject: [PATCH 1642/2557] dcaenc: cleanup on init failure and add a threadsafe init codec cap The encoder didn't clean up if a malloc failed during init. It also doesn't need any external tables to be initialized on init. Finally, it didn't need to check for whether avctx->priv_data exists during uninit. Signed-off-by: Rostislav Pehlivanov --- libavcodec/dcaenc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/dcaenc.c b/libavcodec/dcaenc.c index dd601ffae0077..7ba2346ef1fa6 100644 --- a/libavcodec/dcaenc.c +++ b/libavcodec/dcaenc.c @@ -295,11 +295,10 @@ static int encode_init(AVCodecContext *avctx) static av_cold int encode_close(AVCodecContext *avctx) { - if (avctx->priv_data) { - DCAEncContext *c = avctx->priv_data; - subband_bufer_free(c); - ff_dcaadpcm_free(&c->adpcm_ctx); - } + DCAEncContext *c = avctx->priv_data; + subband_bufer_free(c); + ff_dcaadpcm_free(&c->adpcm_ctx); + return 0; } @@ -1287,6 +1286,7 @@ AVCodec ff_dca_encoder = { .close = encode_close, .encode2 = encode_frame, .capabilities = AV_CODEC_CAP_EXPERIMENTAL, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, .supported_samplerates = sample_rates, From ec6e389c753ba7de0303e8094a494a981b927b77 Mon Sep 17 00:00:00 2001 From: Daniil Cherednik Date: Sun, 7 Jan 2018 22:39:22 +0000 Subject: [PATCH 1643/2557] avcodec/dcaenc: Use ffmpeg mdct instead of own implementation Signed-off-by: Daniil Cherednik --- libavcodec/dcaenc.c | 118 +++++++++++------------------------------- tests/fate/acodec.mak | 4 +- 2 files changed, 33 insertions(+), 89 deletions(-) diff --git a/libavcodec/dcaenc.c b/libavcodec/dcaenc.c index 7ba2346ef1fa6..0967c5639658c 100644 --- a/libavcodec/dcaenc.c +++ b/libavcodec/dcaenc.c @@ -21,6 +21,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define FFT_FLOAT 0 +#define FFT_FIXED_32 1 + #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" @@ -33,6 +36,7 @@ #include "dca_core.h" #include "dcadata.h" #include "dcaenc.h" +#include "fft.h" #include "internal.h" #include "mathops.h" #include "put_bits.h" @@ -56,6 +60,7 @@ typedef struct DCAEncContext { AVClass *class; PutBitContext pb; DCAADPCMEncContext adpcm_ctx; + FFTContext mdct; CompressionOptions options; int frame_size; int frame_bits; @@ -154,6 +159,7 @@ static int encode_init(AVCodecContext *avctx) DCAEncContext *c = avctx->priv_data; uint64_t layout = avctx->channel_layout; int i, j, min_frame_bits; + int ret; if (subband_bufer_alloc(c)) return AVERROR(ENOMEM); @@ -231,6 +237,9 @@ static int encode_init(AVCodecContext *avctx) avctx->frame_size = 32 * SUBBAND_SAMPLES; + if ((ret = ff_mdct_init(&c->mdct, 9, 0, 1.0)) < 0) + return ret; + if (!cos_table[0]) { int j, k; @@ -296,6 +305,7 @@ static int encode_init(AVCodecContext *avctx) static av_cold int encode_close(AVCodecContext *avctx) { DCAEncContext *c = avctx->priv_data; + ff_mdct_end(&c->mdct); subband_bufer_free(c); ff_dcaadpcm_free(&c->adpcm_ctx); @@ -307,16 +317,6 @@ static inline int32_t cos_t(int x) return cos_table[x & 2047]; } -static inline int32_t sin_t(int x) -{ - return cos_t(x - 512); -} - -static inline int32_t half32(int32_t a) -{ - return (a + 1) >> 1; -} - static void subband_transform(DCAEncContext *c, const int32_t *input) { int ch, subs, i, k, j; @@ -397,78 +397,6 @@ static void lfe_downsample(DCAEncContext *c, const int32_t *input) } } -typedef struct { - int32_t re; - int32_t im; -} cplx32; - -static void fft(const int32_t in[2 * 256], cplx32 out[256]) -{ - cplx32 buf[256], rin[256], rout[256]; - int i, j, k, l; - - /* do two transforms in parallel */ - for (i = 0; i < 256; i++) { - /* Apply the Hann window */ - rin[i].re = mul32(in[2 * i], 0x3fffffff - (cos_t(8 * i + 2) >> 1)); - rin[i].im = mul32(in[2 * i + 1], 0x3fffffff - (cos_t(8 * i + 6) >> 1)); - } - /* pre-rotation */ - for (i = 0; i < 256; i++) { - buf[i].re = mul32(cos_t(4 * i + 2), rin[i].re) - - mul32(sin_t(4 * i + 2), rin[i].im); - buf[i].im = mul32(cos_t(4 * i + 2), rin[i].im) - + mul32(sin_t(4 * i + 2), rin[i].re); - } - - for (j = 256, l = 1; j != 1; j >>= 1, l <<= 1) { - for (k = 0; k < 256; k += j) { - for (i = k; i < k + j / 2; i++) { - cplx32 sum, diff; - int t = 8 * l * i; - - sum.re = buf[i].re + buf[i + j / 2].re; - sum.im = buf[i].im + buf[i + j / 2].im; - - diff.re = buf[i].re - buf[i + j / 2].re; - diff.im = buf[i].im - buf[i + j / 2].im; - - buf[i].re = half32(sum.re); - buf[i].im = half32(sum.im); - - buf[i + j / 2].re = mul32(diff.re, cos_t(t)) - - mul32(diff.im, sin_t(t)); - buf[i + j / 2].im = mul32(diff.im, cos_t(t)) - + mul32(diff.re, sin_t(t)); - } - } - } - /* post-rotation */ - for (i = 0; i < 256; i++) { - int b = ff_reverse[i]; - rout[i].re = mul32(buf[b].re, cos_t(4 * i)) - - mul32(buf[b].im, sin_t(4 * i)); - rout[i].im = mul32(buf[b].im, cos_t(4 * i)) - + mul32(buf[b].re, sin_t(4 * i)); - } - for (i = 0; i < 256; i++) { - /* separate the results of the two transforms */ - cplx32 o1, o2; - - o1.re = rout[i].re - rout[255 - i].re; - o1.im = rout[i].im + rout[255 - i].im; - - o2.re = rout[i].im - rout[255 - i].im; - o2.im = -rout[i].re - rout[255 - i].re; - - /* combine them into one long transform */ - out[i].re = mul32( o1.re + o2.re, cos_t(2 * i + 1)) - + mul32( o1.im - o2.im, sin_t(2 * i + 1)); - out[i].im = mul32( o1.im + o2.im, cos_t(2 * i + 1)) - + mul32(-o1.re + o2.re, sin_t(2 * i + 1)); - } -} - static int32_t get_cb(int32_t in) { int i, res; @@ -493,21 +421,37 @@ static int32_t add_cb(int32_t a, int32_t b) return a + cb_to_add[a - b]; } -static void adjust_jnd(int samplerate_index, +static void calc_power(DCAEncContext *c, + const int32_t in[2 * 256], int32_t power[256]) +{ + int i; + LOCAL_ALIGNED_32(int32_t, data, [512]); + LOCAL_ALIGNED_32(int32_t, coeff, [256]); + + for (i = 0; i < 512; i++) { + data[i] = norm__(mul32(in[i], 0x3fffffff - (cos_t(4 * i + 2) >> 1)), 4); + } + c->mdct.mdct_calc(&c->mdct, coeff, data); + for (i = 0; i < 256; i++) { + const int32_t cb = get_cb(coeff[i]); + power[i] = add_cb(cb, cb); + } +} + +static void adjust_jnd(DCAEncContext *c, const int32_t in[512], int32_t out_cb[256]) { int32_t power[256]; - cplx32 out[256]; int32_t out_cb_unnorm[256]; int32_t denom; const int32_t ca_cb = -1114; const int32_t cs_cb = 928; + const int samplerate_index = c->samplerate_index; int i, j; - fft(in, out); + calc_power(c, in, power); for (j = 0; j < 256; j++) { - power[j] = add_cb(get_cb(out[j].re), get_cb(out[j].im)); out_cb_unnorm[j] = -2047; /* and can only grow */ } @@ -585,7 +529,7 @@ static void calc_masking(DCAEncContext *c, const int32_t *input) data[i] = c->history[ch][k]; for (k -= 512; i < 512; i++, k++) data[i] = input[k * c->channels + chi]; - adjust_jnd(c->samplerate_index, data, c->masking_curve_cb[ssf]); + adjust_jnd(c, data, c->masking_curve_cb[ssf]); } for (i = 0; i < 256; i++) { int32_t m = 2048; diff --git a/tests/fate/acodec.mak b/tests/fate/acodec.mak index 5c3fea90c5822..80d26de0f9c91 100644 --- a/tests/fate/acodec.mak +++ b/tests/fate/acodec.mak @@ -104,14 +104,14 @@ fate-acodec-dca: tests/data/asynth-44100-2.wav fate-acodec-dca: SRC = tests/data/asynth-44100-2.wav fate-acodec-dca: CMD = md5 -i $(TARGET_PATH)/$(SRC) -c:a dca -strict -2 -f dts -flags +bitexact fate-acodec-dca: CMP = oneline -fate-acodec-dca: REF = 7cd79a3717943a06b217f1130223a86f +fate-acodec-dca: REF = 2aa580ac67820fce4f581b96ebb34acc FATE_ACODEC-$(call ENCDEC, DCA, WAV) += fate-acodec-dca2 fate-acodec-dca2: CMD = enc_dec_pcm dts wav s16le $(SRC) -c:a dca -strict -2 -flags +bitexact fate-acodec-dca2: REF = $(SRC) fate-acodec-dca2: CMP = stddev fate-acodec-dca2: CMP_SHIFT = -2048 -fate-acodec-dca2: CMP_TARGET = 527 +fate-acodec-dca2: CMP_TARGET = 535 fate-acodec-dca2: SIZE_TOLERANCE = 1632 FATE_ACODEC-$(call ENCDEC, FLAC, FLAC) += fate-acodec-flac fate-acodec-flac-exact-rice From c51301db14fe08bf9f5c3b4f9e588e04095f9ac1 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 13 Jan 2018 18:27:36 +0000 Subject: [PATCH 1644/2557] dcaenc: move all tables inside context and fix incorrect coding style Functionally identical to the old code, with less lines wasted. Partially fixes the complete disregard for the 80 col/line guide. Signed-off-by: Rostislav Pehlivanov --- libavcodec/dcaenc.c | 258 +++++++++++++++++++++++--------------------- 1 file changed, 136 insertions(+), 122 deletions(-) diff --git a/libavcodec/dcaenc.c b/libavcodec/dcaenc.c index 0967c5639658c..186997c6311d2 100644 --- a/libavcodec/dcaenc.c +++ b/libavcodec/dcaenc.c @@ -52,6 +52,8 @@ #define SUBBAND_SAMPLES (SUBFRAMES * SUBSUBFRAMES * 8) #define AUBANDS 25 +#define COS_T(x) (c->cos_table[(x) & 2047]) + typedef struct CompressionOptions { int adpcm_mode; } CompressionOptions; @@ -97,15 +99,15 @@ typedef struct DCAEncContext { int32_t worst_noise_ever; int consumed_bits; int consumed_adpcm_bits; ///< Number of bits to transmit ADPCM related info -} DCAEncContext; -static int32_t cos_table[2048]; -static int32_t band_interpolation[2][512]; -static int32_t band_spectrum[2][8]; -static int32_t auf[9][AUBANDS][256]; -static int32_t cb_to_add[256]; -static int32_t cb_to_level[2048]; -static int32_t lfe_fir_64i[512]; + int32_t cos_table[2048]; + int32_t band_interpolation_tab[2][512]; + int32_t band_spectrum_tab[2][8]; + int32_t auf[9][AUBANDS][256]; + int32_t cb_to_add[256]; + int32_t cb_to_level[2048]; + int32_t lfe_fir_64i[512]; +} DCAEncContext; /* Transfer function of outer and middle ear, Hz -> dB */ static double hom(double f) @@ -158,7 +160,7 @@ static int encode_init(AVCodecContext *avctx) { DCAEncContext *c = avctx->priv_data; uint64_t layout = avctx->channel_layout; - int i, j, min_frame_bits; + int i, j, k, min_frame_bits; int ret; if (subband_bufer_alloc(c)) @@ -166,8 +168,8 @@ static int encode_init(AVCodecContext *avctx) c->fullband_channels = c->channels = avctx->channels; c->lfe_channel = (avctx->channels == 3 || avctx->channels == 6); - c->band_interpolation = band_interpolation[1]; - c->band_spectrum = band_spectrum[1]; + c->band_interpolation = c->band_interpolation_tab[1]; + c->band_spectrum = c->band_spectrum_tab[1]; c->worst_quantization_noise = -2047; c->worst_noise_ever = -2047; c->consumed_adpcm_bits = 0; @@ -240,65 +242,63 @@ static int encode_init(AVCodecContext *avctx) if ((ret = ff_mdct_init(&c->mdct, 9, 0, 1.0)) < 0) return ret; - if (!cos_table[0]) { - int j, k; - - cos_table[0] = 0x7fffffff; - cos_table[512] = 0; - cos_table[1024] = -cos_table[0]; - for (i = 1; i < 512; i++) { - cos_table[i] = (int32_t)(0x7fffffff * cos(M_PI * i / 1024)); - cos_table[1024-i] = -cos_table[i]; - cos_table[1024+i] = -cos_table[i]; - cos_table[2048-i] = cos_table[i]; - } - for (i = 0; i < 2048; i++) { - cb_to_level[i] = (int32_t)(0x7fffffff * ff_exp10(-0.005 * i)); - } + /* Init all tables */ + c->cos_table[0] = 0x7fffffff; + c->cos_table[512] = 0; + c->cos_table[1024] = -c->cos_table[0]; + for (i = 1; i < 512; i++) { + c->cos_table[i] = (int32_t)(0x7fffffff * cos(M_PI * i / 1024)); + c->cos_table[1024-i] = -c->cos_table[i]; + c->cos_table[1024+i] = -c->cos_table[i]; + c->cos_table[2048-i] = +c->cos_table[i]; + } - for (k = 0; k < 32; k++) { - for (j = 0; j < 8; j++) { - lfe_fir_64i[64 * j + k] = (int32_t)(0xffffff800000ULL * ff_dca_lfe_fir_64[8 * k + j]); - lfe_fir_64i[64 * (7-j) + (63 - k)] = (int32_t)(0xffffff800000ULL * ff_dca_lfe_fir_64[8 * k + j]); - } - } + for (i = 0; i < 2048; i++) + c->cb_to_level[i] = (int32_t)(0x7fffffff * ff_exp10(-0.005 * i)); - for (i = 0; i < 512; i++) { - band_interpolation[0][i] = (int32_t)(0x1000000000ULL * ff_dca_fir_32bands_perfect[i]); - band_interpolation[1][i] = (int32_t)(0x1000000000ULL * ff_dca_fir_32bands_nonperfect[i]); + for (k = 0; k < 32; k++) { + for (j = 0; j < 8; j++) { + c->lfe_fir_64i[64 * j + k] = (int32_t)(0xffffff800000ULL * ff_dca_lfe_fir_64[8 * k + j]); + c->lfe_fir_64i[64 * (7-j) + (63 - k)] = (int32_t)(0xffffff800000ULL * ff_dca_lfe_fir_64[8 * k + j]); } + } - for (i = 0; i < 9; i++) { - for (j = 0; j < AUBANDS; j++) { - for (k = 0; k < 256; k++) { - double freq = sample_rates[i] * (k + 0.5) / 512; + for (i = 0; i < 512; i++) { + c->band_interpolation_tab[0][i] = (int32_t)(0x1000000000ULL * ff_dca_fir_32bands_perfect[i]); + c->band_interpolation_tab[1][i] = (int32_t)(0x1000000000ULL * ff_dca_fir_32bands_nonperfect[i]); + } - auf[i][j][k] = (int32_t)(10 * (hom(freq) + gammafilter(j, freq))); - } + for (i = 0; i < 9; i++) { + for (j = 0; j < AUBANDS; j++) { + for (k = 0; k < 256; k++) { + double freq = sample_rates[i] * (k + 0.5) / 512; + + c->auf[i][j][k] = (int32_t)(10 * (hom(freq) + gammafilter(j, freq))); } } + } - for (i = 0; i < 256; i++) { - double add = 1 + ff_exp10(-0.01 * i); - cb_to_add[i] = (int32_t)(100 * log10(add)); - } - for (j = 0; j < 8; j++) { - double accum = 0; - for (i = 0; i < 512; i++) { - double reconst = ff_dca_fir_32bands_perfect[i] * ((i & 64) ? (-1) : 1); - accum += reconst * cos(2 * M_PI * (i + 0.5 - 256) * (j + 0.5) / 512); - } - band_spectrum[0][j] = (int32_t)(200 * log10(accum)); + for (i = 0; i < 256; i++) { + double add = 1 + ff_exp10(-0.01 * i); + c->cb_to_add[i] = (int32_t)(100 * log10(add)); + } + for (j = 0; j < 8; j++) { + double accum = 0; + for (i = 0; i < 512; i++) { + double reconst = ff_dca_fir_32bands_perfect[i] * ((i & 64) ? (-1) : 1); + accum += reconst * cos(2 * M_PI * (i + 0.5 - 256) * (j + 0.5) / 512); } - for (j = 0; j < 8; j++) { - double accum = 0; - for (i = 0; i < 512; i++) { - double reconst = ff_dca_fir_32bands_nonperfect[i] * ((i & 64) ? (-1) : 1); - accum += reconst * cos(2 * M_PI * (i + 0.5 - 256) * (j + 0.5) / 512); - } - band_spectrum[1][j] = (int32_t)(200 * log10(accum)); + c->band_spectrum_tab[0][j] = (int32_t)(200 * log10(accum)); + } + for (j = 0; j < 8; j++) { + double accum = 0; + for (i = 0; i < 512; i++) { + double reconst = ff_dca_fir_32bands_nonperfect[i] * ((i & 64) ? (-1) : 1); + accum += reconst * cos(2 * M_PI * (i + 0.5 - 256) * (j + 0.5) / 512); } + c->band_spectrum_tab[1][j] = (int32_t)(200 * log10(accum)); } + return 0; } @@ -312,11 +312,6 @@ static av_cold int encode_close(AVCodecContext *avctx) return 0; } -static inline int32_t cos_t(int x) -{ - return cos_table[x & 2047]; -} - static void subband_transform(DCAEncContext *c, const int32_t *input) { int ch, subs, i, k, j; @@ -352,7 +347,7 @@ static void subband_transform(DCAEncContext *c, const int32_t *input) resp = 0; for (i = 16; i < 48; i++) { int s = (2 * band + 1) * (2 * (i + 16) + 1); - resp += mul32(accum[i], cos_t(s << 3)) >> 3; + resp += mul32(accum[i], COS_T(s << 3)) >> 3; } c->subband[ch][band][subs] = ((band + 1) & 2) ? -resp : resp; @@ -383,9 +378,9 @@ static void lfe_downsample(DCAEncContext *c, const int32_t *input) accum = 0; for (i = hist_start, j = 0; i < 512; i++, j++) - accum += mul32(hist[i], lfe_fir_64i[j]); + accum += mul32(hist[i], c->lfe_fir_64i[j]); for (i = 0; i < hist_start; i++, j++) - accum += mul32(hist[i], lfe_fir_64i[j]); + accum += mul32(hist[i], c->lfe_fir_64i[j]); c->downsampled_lfe[lfes] = accum; @@ -397,28 +392,26 @@ static void lfe_downsample(DCAEncContext *c, const int32_t *input) } } -static int32_t get_cb(int32_t in) +static int32_t get_cb(DCAEncContext *c, int32_t in) { - int i, res; + int i, res = 0; + in = FFABS(in); - res = 0; - if (in < 0) - in = -in; for (i = 1024; i > 0; i >>= 1) { - if (cb_to_level[i + res] >= in) + if (c->cb_to_level[i + res] >= in) res += i; } return -res; } -static int32_t add_cb(int32_t a, int32_t b) +static int32_t add_cb(DCAEncContext *c, int32_t a, int32_t b) { if (a < b) FFSWAP(int32_t, a, b); if (a - b >= 256) return a; - return a + cb_to_add[a - b]; + return a + c->cb_to_add[a - b]; } static void calc_power(DCAEncContext *c, @@ -428,13 +421,13 @@ static void calc_power(DCAEncContext *c, LOCAL_ALIGNED_32(int32_t, data, [512]); LOCAL_ALIGNED_32(int32_t, coeff, [256]); - for (i = 0; i < 512; i++) { - data[i] = norm__(mul32(in[i], 0x3fffffff - (cos_t(4 * i + 2) >> 1)), 4); - } + for (i = 0; i < 512; i++) + data[i] = norm__(mul32(in[i], 0x3fffffff - (COS_T(4 * i + 2) >> 1)), 4); + c->mdct.mdct_calc(&c->mdct, coeff, data); for (i = 0; i < 256; i++) { - const int32_t cb = get_cb(coeff[i]); - power[i] = add_cb(cb, cb); + const int32_t cb = get_cb(c, coeff[i]); + power[i] = add_cb(c, cb, cb); } } @@ -451,21 +444,20 @@ static void adjust_jnd(DCAEncContext *c, calc_power(c, in, power); - for (j = 0; j < 256; j++) { + for (j = 0; j < 256; j++) out_cb_unnorm[j] = -2047; /* and can only grow */ - } for (i = 0; i < AUBANDS; i++) { denom = ca_cb; /* and can only grow */ for (j = 0; j < 256; j++) - denom = add_cb(denom, power[j] + auf[samplerate_index][i][j]); + denom = add_cb(c, denom, power[j] + c->auf[samplerate_index][i][j]); for (j = 0; j < 256; j++) - out_cb_unnorm[j] = add_cb(out_cb_unnorm[j], - -denom + auf[samplerate_index][i][j]); + out_cb_unnorm[j] = add_cb(c, out_cb_unnorm[j], + -denom + c->auf[samplerate_index][i][j]); } for (j = 0; j < 256; j++) - out_cb[j] = add_cb(out_cb[j], -out_cb_unnorm[j] - ca_cb - cs_cb); + out_cb[j] = add_cb(c, out_cb[j], -out_cb_unnorm[j] - ca_cb - cs_cb); } typedef void (*walk_band_t)(DCAEncContext *c, int band1, int band2, int f, @@ -547,16 +539,16 @@ static void calc_masking(DCAEncContext *c, const int32_t *input) } } -static inline int32_t find_peak(const int32_t *in, int len) { +static inline int32_t find_peak(DCAEncContext *c, const int32_t *in, int len) +{ int sample; int32_t m = 0; for (sample = 0; sample < len; sample++) { int32_t s = abs(in[sample]); - if (m < s) { + if (m < s) m = s; - } } - return get_cb(m); + return get_cb(c, m); } static void find_peaks(DCAEncContext *c) @@ -564,14 +556,13 @@ static void find_peaks(DCAEncContext *c) int band, ch; for (ch = 0; ch < c->fullband_channels; ch++) { - for (band = 0; band < 32; band++) { - c->peak_cb[ch][band] = find_peak(c->subband[ch][band], SUBBAND_SAMPLES); - } + for (band = 0; band < 32; band++) + c->peak_cb[ch][band] = find_peak(c, c->subband[ch][band], + SUBBAND_SAMPLES); } - if (c->lfe_channel) { - c->lfe_peak_cb = find_peak(c->downsampled_lfe, DCA_LFE_SAMPLES); - } + if (c->lfe_channel) + c->lfe_peak_cb = find_peak(c, c->downsampled_lfe, DCA_LFE_SAMPLES); } static void adpcm_analysis(DCAEncContext *c) @@ -585,11 +576,12 @@ static void adpcm_analysis(DCAEncContext *c) for (ch = 0; ch < c->fullband_channels; ch++) { for (band = 0; band < 32; band++) { samples = c->subband[ch][band] - DCA_ADPCM_COEFFS; - pred_vq_id = ff_dcaadpcm_subband_analysis(&c->adpcm_ctx, samples, SUBBAND_SAMPLES, estimated_diff); + pred_vq_id = ff_dcaadpcm_subband_analysis(&c->adpcm_ctx, samples, + SUBBAND_SAMPLES, estimated_diff); if (pred_vq_id >= 0) { c->prediction_mode[ch][band] = pred_vq_id; c->consumed_adpcm_bits += 12; //12 bits to transmit prediction vq index - c->diff_peak_cb[ch][band] = find_peak(estimated_diff, 16); + c->diff_peak_cb[ch][band] = find_peak(c, estimated_diff, 16); } else { c->prediction_mode[ch][band] = -1; } @@ -601,7 +593,7 @@ static const int snr_fudge = 128; #define USED_1ABITS 1 #define USED_26ABITS 4 -static inline int32_t get_step_size(const DCAEncContext *c, int ch, int band) +static inline int32_t get_step_size(DCAEncContext *c, int ch, int band) { int32_t step_size; @@ -613,7 +605,8 @@ static inline int32_t get_step_size(const DCAEncContext *c, int ch, int band) return step_size; } -static int calc_one_scale(int32_t peak_cb, int abits, softfloat *quant) +static int calc_one_scale(DCAEncContext *c, int32_t peak_cb, int abits, + softfloat *quant) { int32_t peak; int our_nscale, try_remove; @@ -623,7 +616,7 @@ static int calc_one_scale(int32_t peak_cb, int abits, softfloat *quant) av_assert0(peak_cb >= -2047); our_nscale = 127; - peak = cb_to_level[-peak_cb]; + peak = c->cb_to_level[-peak_cb]; for (try_remove = 64; try_remove > 0; try_remove >>= 1) { if (scalefactor_inv[our_nscale - try_remove].e + stepsize_inv[abits].e <= 17) @@ -649,15 +642,17 @@ static inline void quantize_adpcm_subband(DCAEncContext *c, int ch, int band) { int32_t step_size; int32_t diff_peak_cb = c->diff_peak_cb[ch][band]; - c->scale_factor[ch][band] = calc_one_scale(diff_peak_cb, + c->scale_factor[ch][band] = calc_one_scale(c, diff_peak_cb, c->abits[ch][band], &c->quant[ch][band]); step_size = get_step_size(c, ch, band); ff_dcaadpcm_do_real(c->prediction_mode[ch][band], - c->quant[ch][band], ff_dca_scale_factor_quant7[c->scale_factor[ch][band]], step_size, - c->adpcm_history[ch][band], c->subband[ch][band], c->adpcm_history[ch][band]+4, c->quantized[ch][band], - SUBBAND_SAMPLES, cb_to_level[-diff_peak_cb]); + c->quant[ch][band], + ff_dca_scale_factor_quant7[c->scale_factor[ch][band]], + step_size, c->adpcm_history[ch][band], c->subband[ch][band], + c->adpcm_history[ch][band] + 4, c->quantized[ch][band], + SUBBAND_SAMPLES, c->cb_to_level[-diff_peak_cb]); } static void quantize_adpcm(DCAEncContext *c) @@ -674,21 +669,31 @@ static void quantize_pcm(DCAEncContext *c) { int sample, band, ch; - for (ch = 0; ch < c->fullband_channels; ch++) - for (band = 0; band < 32; band++) - if (c->prediction_mode[ch][band] == -1) - for (sample = 0; sample < SUBBAND_SAMPLES; sample++) - c->quantized[ch][band][sample] = quantize_value(c->subband[ch][band][sample], c->quant[ch][band]); + for (ch = 0; ch < c->fullband_channels; ch++) { + for (band = 0; band < 32; band++) { + if (c->prediction_mode[ch][band] == -1) { + for (sample = 0; sample < SUBBAND_SAMPLES; sample++) { + int32_t val = quantize_value(c->subband[ch][band][sample], + c->quant[ch][band]); + c->quantized[ch][band][sample] = val; + } + } + } + } } -static void accumulate_huff_bit_consumption(int abits, int32_t *quantized, uint32_t *result) +static void accumulate_huff_bit_consumption(int abits, int32_t *quantized, + uint32_t *result) { uint8_t sel, id = abits - 1; for (sel = 0; sel < ff_dca_quant_index_group_size[id]; sel++) - result[sel] += ff_dca_vlc_calc_quant_bits(quantized, SUBBAND_SAMPLES, sel, id); + result[sel] += ff_dca_vlc_calc_quant_bits(quantized, SUBBAND_SAMPLES, + sel, id); } -static uint32_t set_best_code(uint32_t vlc_bits[DCA_CODE_BOOKS][7], uint32_t clc_bits[DCA_CODE_BOOKS], int32_t res[DCA_CODE_BOOKS]) +static uint32_t set_best_code(uint32_t vlc_bits[DCA_CODE_BOOKS][7], + uint32_t clc_bits[DCA_CODE_BOOKS], + int32_t res[DCA_CODE_BOOKS]) { uint8_t i, sel; uint32_t best_sel_bits[DCA_CODE_BOOKS]; @@ -727,7 +732,8 @@ static uint32_t set_best_code(uint32_t vlc_bits[DCA_CODE_BOOKS][7], uint32_t clc return bits; } -static uint32_t set_best_abits_code(int abits[DCAENC_SUBBANDS], int bands, int32_t *res) +static uint32_t set_best_abits_code(int abits[DCAENC_SUBBANDS], int bands, + int32_t *res) { uint8_t i; uint32_t t; @@ -788,7 +794,8 @@ static int init_quantization_noise(DCAEncContext *c, int noise, int forbid_zero) ret &= ~(USED_26ABITS | USED_1ABITS); } } - c->consumed_bits += set_best_abits_code(c->abits[ch], 32, &c->bit_allocation_sel[ch]); + c->consumed_bits += set_best_abits_code(c->abits[ch], 32, + &c->bit_allocation_sel[ch]); } /* Recalc scale_factor each time to get bits consumption in case of Huffman coding. @@ -797,7 +804,7 @@ static int init_quantization_noise(DCAEncContext *c, int noise, int forbid_zero) for (ch = 0; ch < c->fullband_channels; ch++) { for (band = 0; band < 32; band++) { if (c->prediction_mode[ch][band] == -1) { - c->scale_factor[ch][band] = calc_one_scale(c->peak_cb[ch][band], + c->scale_factor[ch][band] = calc_one_scale(c, c->peak_cb[ch][band], c->abits[ch][band], &c->quant[ch][band]); } @@ -811,7 +818,9 @@ static int init_quantization_noise(DCAEncContext *c, int noise, int forbid_zero) for (ch = 0; ch < c->fullband_channels; ch++) { for (band = 0; band < 32; band++) { if (c->abits[ch][band] && c->abits[ch][band] <= DCA_CODE_BOOKS) { - accumulate_huff_bit_consumption(c->abits[ch][band], c->quantized[ch][band], huff_bit_count_accum[ch][c->abits[ch][band] - 1]); + accumulate_huff_bit_consumption(c->abits[ch][band], + c->quantized[ch][band], + huff_bit_count_accum[ch][c->abits[ch][band] - 1]); clc_bit_count_accum[ch][c->abits[ch][band] - 1] += bit_consumption[c->abits[ch][band]]; } else { bits_counter += bit_consumption[c->abits[ch][band]]; @@ -820,7 +829,9 @@ static int init_quantization_noise(DCAEncContext *c, int noise, int forbid_zero) } for (ch = 0; ch < c->fullband_channels; ch++) { - bits_counter += set_best_code(huff_bit_count_accum[ch], clc_bit_count_accum[ch], c->quant_index_sel[ch]); + bits_counter += set_best_code(huff_bit_count_accum[ch], + clc_bit_count_accum[ch], + c->quant_index_sel[ch]); } c->consumed_bits += bits_counter; @@ -897,7 +908,8 @@ static void fill_in_adpcm_bufer(DCAEncContext *c) step_size = get_step_size(c, ch, band); ff_dca_core_dequantize(c->adpcm_history[ch][band], - c->quantized[ch][band]+12, step_size, ff_dca_scale_factor_quant7[c->scale_factor[ch][band]], 0, 4); + c->quantized[ch][band]+12, step_size, + ff_dca_scale_factor_quant7[c->scale_factor[ch][band]], 0, 4); } else { AV_COPY128U(c->adpcm_history[ch][band], c->adpcm_history[ch][band]+4); } @@ -920,7 +932,7 @@ static void fill_in_adpcm_bufer(DCAEncContext *c) static void calc_lfe_scales(DCAEncContext *c) { if (c->lfe_channel) - c->lfe_scale_factor = calc_one_scale(c->lfe_peak_cb, 11, &c->lfe_quant); + c->lfe_scale_factor = calc_one_scale(c, c->lfe_peak_cb, 11, &c->lfe_quant); } static void put_frame_header(DCAEncContext *c) @@ -1061,7 +1073,8 @@ static void put_subframe_samples(DCAEncContext *c, int ss, int band, int ch) sel = c->quant_index_sel[ch][c->abits[ch][band] - 1]; // Huffman codes if (sel < ff_dca_quant_index_group_size[c->abits[ch][band] - 1]) { - ff_dca_vlc_enc_quant(&c->pb, &c->quantized[ch][band][ss * 8], 8, sel, c->abits[ch][band] - 1); + ff_dca_vlc_enc_quant(&c->pb, &c->quantized[ch][band][ss * 8], 8, + sel, c->abits[ch][band] - 1); return; } @@ -1114,7 +1127,8 @@ static void put_subframe(DCAEncContext *c, int subframe) put_bits(&c->pb, 5, c->abits[ch][band]); } } else { - ff_dca_vlc_enc_alloc(&c->pb, c->abits[ch], DCAENC_SUBBANDS, c->bit_allocation_sel[ch]); + ff_dca_vlc_enc_alloc(&c->pb, c->abits[ch], DCAENC_SUBBANDS, + c->bit_allocation_sel[ch]); } } From 02dba49dd3f02c0b2d4f4740597a3062d6c4981c Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 29 May 2017 18:12:51 -0300 Subject: [PATCH 1645/2557] avformat/adtsenc: add adts_init() Signed-off-by: James Almer --- libavformat/adtsenc.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libavformat/adtsenc.c b/libavformat/adtsenc.c index a24f99c4479ea..c24572f160acd 100644 --- a/libavformat/adtsenc.c +++ b/libavformat/adtsenc.c @@ -94,13 +94,11 @@ static int adts_decode_extradata(AVFormatContext *s, ADTSContext *adts, const ui return 0; } -static int adts_write_header(AVFormatContext *s) +static int adts_init(AVFormatContext *s) { ADTSContext *adts = s->priv_data; AVCodecParameters *par = s->streams[0]->codecpar; - if (adts->id3v2tag) - ff_id3v2_write_simple(s, 4, ID3v2_DEFAULT_MAGIC); if (par->extradata_size > 0) return adts_decode_extradata(s, adts, par->extradata, par->extradata_size); @@ -108,6 +106,16 @@ static int adts_write_header(AVFormatContext *s) return 0; } +static int adts_write_header(AVFormatContext *s) +{ + ADTSContext *adts = s->priv_data; + + if (adts->id3v2tag) + ff_id3v2_write_simple(s, 4, ID3v2_DEFAULT_MAGIC); + + return 0; +} + static int adts_write_frame_header(ADTSContext *ctx, uint8_t *buf, int size, int pce_size) { @@ -220,6 +228,7 @@ AVOutputFormat ff_adts_muxer = { .priv_data_size = sizeof(ADTSContext), .audio_codec = AV_CODEC_ID_AAC, .video_codec = AV_CODEC_ID_NONE, + .init = adts_init, .write_header = adts_write_header, .write_packet = adts_write_packet, .write_trailer = adts_write_trailer, From 96f94624e0a1a91134bd8e1e3127080b81716f6f Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Sun, 14 Jan 2018 17:30:23 +0530 Subject: [PATCH 1646/2557] avformat/adtsenc: allow only AAC streams The ADTS muxer will silently (attempt to) mux any audio stream passed to it. Patch adds a codec check. Signed-off-by: James Almer --- libavformat/adtsenc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/adtsenc.c b/libavformat/adtsenc.c index c24572f160acd..3c2840c6abefb 100644 --- a/libavformat/adtsenc.c +++ b/libavformat/adtsenc.c @@ -99,6 +99,10 @@ static int adts_init(AVFormatContext *s) ADTSContext *adts = s->priv_data; AVCodecParameters *par = s->streams[0]->codecpar; + if (par->codec_id != AV_CODEC_ID_AAC) { + av_log(s, AV_LOG_ERROR, "Only AAC streams can be muxed by the ADTS muxer\n"); + return AVERROR(EINVAL); + } if (par->extradata_size > 0) return adts_decode_extradata(s, adts, par->extradata, par->extradata_size); From 66e551eafb8d202f37ba5a2bbe03741966a9e241 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 14 Jan 2018 22:33:57 +0800 Subject: [PATCH 1647/2557] dashdec: Expose bandwidth and representation ID as metadata The primary goal was making it viable to play YouTube/Vimeo/... videos using the native demuxer, since mpv currently uses a workaround in form of Edit Decision Lists (EDL). Implemented features: 1 Exposing id / bitrate as stream metadata (similar to the HLS demuxer) 2 Support for multiple video and audio streams 3 A few minor parts of the specification that are in use at YouTube Signed-off-by: Steven Liu --- libavformat/dashdec.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 0e3afd2a3b913..1a18ab021441d 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -84,6 +84,8 @@ struct representation { int stream_index; enum AVMediaType type; + char id[20]; + int bandwidth; int n_fragments; struct fragment **fragments; /* VOD list of fragment for profile */ @@ -801,6 +803,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, if (rep) { if (rep->fragment_duration > 0 && !rep->fragment_timescale) rep->fragment_timescale = 1; + rep->bandwidth = rep_bandwidth_val ? atoi(rep_bandwidth_val) : 0; + strncpy(rep->id, rep_id_val ? rep_id_val : "", sizeof(rep->id)); if (type == AVMEDIA_TYPE_VIDEO) { rep->rep_idx = video_rep_idx; c->cur_video = rep; @@ -1650,10 +1654,20 @@ static int dash_read_header(AVFormatContext *s) } if (c->cur_video) { - av_program_add_stream_index(s, 0, c->cur_video->stream_index); + int stream_index = c->cur_video->stream_index; + av_program_add_stream_index(s, 0, stream_index); + if (c->cur_video->bandwidth > 0) + av_dict_set_int(&s->streams[stream_index]->metadata, "variant_bitrate", c->cur_video->bandwidth, 0); + if (c->cur_video->id[0]) + av_dict_set(&s->streams[stream_index]->metadata, "id", c->cur_video->id, 0); } if (c->cur_audio) { - av_program_add_stream_index(s, 0, c->cur_audio->stream_index); + int stream_index = c->cur_audio->stream_index; + av_program_add_stream_index(s, 0, stream_index); + if (c->cur_audio->bandwidth > 0) + av_dict_set_int(&s->streams[stream_index]->metadata, "variant_bitrate", c->cur_audio->bandwidth, 0); + if (c->cur_audio->id[0]) + av_dict_set(&s->streams[stream_index]->metadata, "id", c->cur_audio->id, 0); } } From 94cc16499ff1309386ca1d77aac0627e16ffa917 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 14 Jan 2018 22:34:43 +0800 Subject: [PATCH 1648/2557] dashdec: Support for multiple video/audio streams Signed-off-by: Steven Liu --- doc/demuxers.texi | 10 ++ libavformat/dashdec.c | 342 ++++++++++++++++++++++++++---------------- 2 files changed, 223 insertions(+), 129 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 6080167233d97..e7c2abce57d7b 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -244,6 +244,16 @@ file subdir/file-2.wav @end example @end itemize +@section dash + +Dynamic Adaptive Streaming over HTTP demuxer. + +This demuxer presents all AVStreams found in the manifest. +By setting the discard flags on AVStreams the caller can decide +which streams to actually receive. +Each stream mirrors the @code{id} and @code{bandwidth} properties from the +@code{} as metadata keys named "id" and "variant_bitrate" respectively. + @section flv, live_flv Adobe Flash Video Format demuxer. diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 1a18ab021441d..0ac3c67785918 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -86,6 +86,7 @@ struct representation { enum AVMediaType type; char id[20]; int bandwidth; + AVStream *assoc_stream; /* demuxer stream associated with this representation */ int n_fragments; struct fragment **fragments; /* VOD list of fragment for profile */ @@ -120,8 +121,11 @@ struct representation { typedef struct DASHContext { const AVClass *class; char *base_url; - struct representation *cur_video; - struct representation *cur_audio; + + int n_videos; + struct representation **videos; + int n_audios; + struct representation **audios; /* MediaPresentationDescription Attribute */ uint64_t media_presentation_duration; @@ -333,6 +337,28 @@ static void free_representation(struct representation *pls) av_freep(&pls); } +static void free_video_list(DASHContext *c) +{ + int i; + for (i = 0; i < c->n_videos; i++) { + struct representation *pls = c->videos[i]; + free_representation(pls); + } + av_freep(&c->videos); + c->n_videos = 0; +} + +static void free_audio_list(DASHContext *c) +{ + int i; + for (i = 0; i < c->n_audios; i++) { + struct representation *pls = c->audios[i]; + free_representation(pls); + } + av_freep(&c->audios); + c->n_audios = 0; +} + static void set_httpheader_options(DASHContext *c, AVDictionary **opts) { // broker prior HTTP options that should be consistent across requests @@ -658,7 +684,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, type = get_content_type(adaptionset_node); if (type == AVMEDIA_TYPE_UNKNOWN) { av_log(s, AV_LOG_VERBOSE, "Parsing '%s' - skipp not supported representation type\n", url); - } else if ((type == AVMEDIA_TYPE_VIDEO && !c->cur_video) || (type == AVMEDIA_TYPE_AUDIO && !c->cur_audio)) { + } else if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO) { // convert selected representation to our internal struct rep = av_mallocz(sizeof(struct representation)); if (!rep) { @@ -807,10 +833,10 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, strncpy(rep->id, rep_id_val ? rep_id_val : "", sizeof(rep->id)); if (type == AVMEDIA_TYPE_VIDEO) { rep->rep_idx = video_rep_idx; - c->cur_video = rep; + dynarray_add(&c->videos, &c->n_videos, rep); } else { rep->rep_idx = audio_rep_idx; - c->cur_audio = rep; + dynarray_add(&c->audios, &c->n_audios, rep); } } } @@ -883,8 +909,6 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) char *val = NULL; uint32_t perdiod_duration_sec = 0; uint32_t perdiod_start_sec = 0; - int32_t audio_rep_idx = 0; - int32_t video_rep_idx = 0; if (!in) { close_in = 1; @@ -1014,14 +1038,6 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) } adaptionset_node = xmlNextElementSibling(adaptionset_node); } - if (c->cur_video) { - c->cur_video->rep_count = video_rep_idx; - av_log(s, AV_LOG_VERBOSE, "rep_idx[%d]\n", (int)c->cur_video->rep_idx); - av_log(s, AV_LOG_VERBOSE, "rep_count[%d]\n", (int)video_rep_idx); - } - if (c->cur_audio) { - c->cur_audio->rep_count = audio_rep_idx; - } cleanup: /*free the document */ xmlFreeDoc(doc); @@ -1139,48 +1155,69 @@ static void move_segments(struct representation *rep_src, struct representation static int refresh_manifest(AVFormatContext *s) { - int ret = 0; + int ret = 0, i; DASHContext *c = s->priv_data; // save current context - struct representation *cur_video = c->cur_video; - struct representation *cur_audio = c->cur_audio; + int n_videos = c->n_videos; + struct representation **videos = c->videos; + int n_audios = c->n_audios; + struct representation **audios = c->audios; char *base_url = c->base_url; c->base_url = NULL; - c->cur_video = NULL; - c->cur_audio = NULL; + c->n_videos = 0; + c->videos = NULL; + c->n_audios = 0; + c->audios = NULL; ret = parse_manifest(s, s->filename, NULL); if (ret) goto finish; - if (cur_video && cur_video->timelines || cur_audio && cur_audio->timelines) { - // calc current time - int64_t currentVideoTime = 0; - int64_t currentAudioTime = 0; - if (cur_video && cur_video->timelines) - currentVideoTime = get_segment_start_time_based_on_timeline(cur_video, cur_video->cur_seq_no) / cur_video->fragment_timescale; - if (cur_audio && cur_audio->timelines) - currentAudioTime = get_segment_start_time_based_on_timeline(cur_audio, cur_audio->cur_seq_no) / cur_audio->fragment_timescale; - // update segments - if (cur_video && cur_video->timelines) { - c->cur_video->cur_seq_no = calc_next_seg_no_from_timelines(c->cur_video, currentVideoTime * cur_video->fragment_timescale - 1); - if (c->cur_video->cur_seq_no >= 0) { - move_timelines(c->cur_video, cur_video, c); + if (c->n_videos != n_videos) { + av_log(c, AV_LOG_ERROR, + "new manifest has mismatched no. of video representations, %d -> %d\n", + n_videos, c->n_videos); + return AVERROR_INVALIDDATA; + } + if (c->n_audios != n_audios) { + av_log(c, AV_LOG_ERROR, + "new manifest has mismatched no. of audio representations, %d -> %d\n", + n_audios, c->n_audios); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < n_videos; i++) { + struct representation *cur_video = videos[i]; + struct representation *ccur_video = c->videos[i]; + if (cur_video->timelines) { + // calc current time + int64_t currentTime = get_segment_start_time_based_on_timeline(cur_video, cur_video->cur_seq_no) / cur_video->fragment_timescale; + // update segments + ccur_video->cur_seq_no = calc_next_seg_no_from_timelines(ccur_video, currentTime * cur_video->fragment_timescale - 1); + if (ccur_video->cur_seq_no >= 0) { + move_timelines(ccur_video, cur_video, c); } } - if (cur_audio && cur_audio->timelines) { - c->cur_audio->cur_seq_no = calc_next_seg_no_from_timelines(c->cur_audio, currentAudioTime * cur_audio->fragment_timescale - 1); - if (c->cur_audio->cur_seq_no >= 0) { - move_timelines(c->cur_audio, cur_audio, c); - } + if (cur_video->fragments) { + move_segments(ccur_video, cur_video, c); } } - if (cur_video && cur_video->fragments) { - move_segments(c->cur_video, cur_video, c); - } - if (cur_audio && cur_audio->fragments) { - move_segments(c->cur_audio, cur_audio, c); + for (i = 0; i < n_audios; i++) { + struct representation *cur_audio = audios[i]; + struct representation *ccur_audio = c->audios[i]; + if (cur_audio->timelines) { + // calc current time + int64_t currentTime = get_segment_start_time_based_on_timeline(cur_audio, cur_audio->cur_seq_no) / cur_audio->fragment_timescale; + // update segments + ccur_audio->cur_seq_no = calc_next_seg_no_from_timelines(ccur_audio, currentTime * cur_audio->fragment_timescale - 1); + if (ccur_audio->cur_seq_no >= 0) { + move_timelines(ccur_audio, cur_audio, c); + } + } + if (cur_audio->fragments) { + move_segments(ccur_audio, cur_audio, c); + } } finish: @@ -1189,12 +1226,14 @@ static int refresh_manifest(AVFormatContext *s) av_free(base_url); else c->base_url = base_url; - if (c->cur_audio) - free_representation(c->cur_audio); - if (c->cur_video) - free_representation(c->cur_video); - c->cur_audio = cur_audio; - c->cur_video = cur_video; + if (c->audios) + free_audio_list(c); + if (c->videos) + free_video_list(c); + c->n_audios = n_audios; + c->audios = audios; + c->n_videos = n_videos; + c->videos = videos; return ret; } @@ -1493,6 +1532,16 @@ static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url, return AVERROR(EPERM); } +static void close_demux_for_component(struct representation *pls) +{ + /* note: the internal buffer could have changed */ + av_freep(&pls->pb.buffer); + memset(&pls->pb, 0x00, sizeof(AVIOContext)); + pls->ctx->pb = NULL; + avformat_close_input(&pls->ctx); + pls->ctx = NULL; +} + static int reopen_demux_for_component(AVFormatContext *s, struct representation *pls) { DASHContext *c = s->priv_data; @@ -1502,12 +1551,7 @@ static int reopen_demux_for_component(AVFormatContext *s, struct representation int ret = 0; if (pls->ctx) { - /* note: the internal buffer could have changed, and be != avio_ctx_buffer */ - av_freep(&pls->pb.buffer); - memset(&pls->pb, 0x00, sizeof(AVIOContext)); - pls->ctx->pb = NULL; - avformat_close_input(&pls->ctx); - pls->ctx = NULL; + close_demux_for_component(pls); } if (!(pls->ctx = avformat_alloc_context())) { ret = AVERROR(ENOMEM); @@ -1596,6 +1640,7 @@ static int dash_read_header(AVFormatContext *s) DASHContext *c = s->priv_data; int ret = 0; int stream_index = 0; + int i; c->interrupt_callback = &s->interrupt_callback; // if the URL context is good, read important options we must broker later @@ -1617,27 +1662,23 @@ static int dash_read_header(AVFormatContext *s) s->duration = (int64_t) c->media_presentation_duration * AV_TIME_BASE; } - /* Open the demuxer for curent video and current audio components if available */ - if (!ret && c->cur_video) { - ret = open_demux_for_component(s, c->cur_video); - if (!ret) { - c->cur_video->stream_index = stream_index; - ++stream_index; - } else { - free_representation(c->cur_video); - c->cur_video = NULL; - } + /* Open the demuxer for video and audio components if available */ + for (i = 0; i < c->n_videos; i++) { + struct representation *cur_video = c->videos[i]; + ret = open_demux_for_component(s, cur_video); + if (ret) + goto fail; + cur_video->stream_index = stream_index; + ++stream_index; } - if (!ret && c->cur_audio) { - ret = open_demux_for_component(s, c->cur_audio); - if (!ret) { - c->cur_audio->stream_index = stream_index; - ++stream_index; - } else { - free_representation(c->cur_audio); - c->cur_audio = NULL; - } + for (i = 0; i < c->n_audios; i++) { + struct representation *cur_audio = c->audios[i]; + ret = open_demux_for_component(s, cur_audio); + if (ret) + goto fail; + cur_audio->stream_index = stream_index; + ++stream_index; } if (!stream_index) { @@ -1653,21 +1694,25 @@ static int dash_read_header(AVFormatContext *s) goto fail; } - if (c->cur_video) { - int stream_index = c->cur_video->stream_index; - av_program_add_stream_index(s, 0, stream_index); - if (c->cur_video->bandwidth > 0) - av_dict_set_int(&s->streams[stream_index]->metadata, "variant_bitrate", c->cur_video->bandwidth, 0); - if (c->cur_video->id[0]) - av_dict_set(&s->streams[stream_index]->metadata, "id", c->cur_video->id, 0); - } - if (c->cur_audio) { - int stream_index = c->cur_audio->stream_index; - av_program_add_stream_index(s, 0, stream_index); - if (c->cur_audio->bandwidth > 0) - av_dict_set_int(&s->streams[stream_index]->metadata, "variant_bitrate", c->cur_audio->bandwidth, 0); - if (c->cur_audio->id[0]) - av_dict_set(&s->streams[stream_index]->metadata, "id", c->cur_audio->id, 0); + for (i = 0; i < c->n_videos; i++) { + struct representation *pls = c->videos[i]; + + av_program_add_stream_index(s, 0, pls->stream_index); + pls->assoc_stream = s->streams[pls->stream_index]; + if (pls->bandwidth > 0) + av_dict_set_int(&pls->assoc_stream->metadata, "variant_bitrate", pls->bandwidth, 0); + if (pls->id[0]) + av_dict_set(&pls->assoc_stream->metadata, "id", pls->id, 0); + } + for (i = 0; i < c->n_audios; i++) { + struct representation *pls = c->audios[i]; + + av_program_add_stream_index(s, 0, pls->stream_index); + pls->assoc_stream = s->streams[pls->stream_index]; + if (pls->bandwidth > 0) + av_dict_set_int(&pls->assoc_stream->metadata, "variant_bitrate", pls->bandwidth, 0); + if (pls->id[0]) + av_dict_set(&pls->assoc_stream->metadata, "id", pls->id, 0); } } @@ -1676,43 +1721,79 @@ static int dash_read_header(AVFormatContext *s) return ret; } +static void recheck_discard_flags(AVFormatContext *s, struct representation **p, int n) +{ + int i, j; + + for (i = 0; i < n; i++) { + struct representation *pls = p[i]; + + int needed = !pls->assoc_stream || pls->assoc_stream->discard < AVDISCARD_ALL; + if (needed && !pls->ctx) { + pls->cur_seg_offset = 0; + pls->init_sec_buf_read_offset = 0; + /* Catch up */ + for (j = 0; j < n; j++) { + pls->cur_seq_no = FFMAX(pls->cur_seq_no, p[j]->cur_seq_no); + } + reopen_demux_for_component(s, pls); + av_log(s, AV_LOG_INFO, "Now receiving stream_index %d\n", pls->stream_index); + } else if (!needed && pls->ctx) { + close_demux_for_component(pls); + if (pls->input) + ff_format_io_close(pls->parent, &pls->input); + av_log(s, AV_LOG_INFO, "No longer receiving stream_index %d\n", pls->stream_index); + } + } +} + static int dash_read_packet(AVFormatContext *s, AVPacket *pkt) { DASHContext *c = s->priv_data; - int ret = 0; + int ret = 0, i; + int64_t mints = 0; struct representation *cur = NULL; - if (!c->cur_audio && !c->cur_video ) { - return AVERROR_INVALIDDATA; + recheck_discard_flags(s, c->videos, c->n_videos); + recheck_discard_flags(s, c->audios, c->n_audios); + + for (i = 0; i < c->n_videos; i++) { + struct representation *pls = c->videos[i]; + if (!pls->ctx) + continue; + if (!cur || pls->cur_timestamp < mints) { + cur = pls; + mints = pls->cur_timestamp; + } } - if (c->cur_audio && !c->cur_video) { - cur = c->cur_audio; - } else if (!c->cur_audio && c->cur_video) { - cur = c->cur_video; - } else if (c->cur_video->cur_timestamp < c->cur_audio->cur_timestamp) { - cur = c->cur_video; - } else { - cur = c->cur_audio; + for (i = 0; i < c->n_audios; i++) { + struct representation *pls = c->audios[i]; + if (!pls->ctx) + continue; + if (!cur || pls->cur_timestamp < mints) { + cur = pls; + mints = pls->cur_timestamp; + } } - if (cur->ctx) { - while (!ff_check_interrupt(c->interrupt_callback) && !ret) { - ret = av_read_frame(cur->ctx, pkt); - if (ret >= 0) { - /* If we got a packet, return it */ - cur->cur_timestamp = av_rescale(pkt->pts, (int64_t)cur->ctx->streams[0]->time_base.num * 90000, cur->ctx->streams[0]->time_base.den); - pkt->stream_index = cur->stream_index; - return 0; - } - if (cur->is_restart_needed) { - cur->cur_seg_offset = 0; - cur->init_sec_buf_read_offset = 0; - if (cur->input) - ff_format_io_close(cur->parent, &cur->input); - ret = reopen_demux_for_component(s, cur); - cur->is_restart_needed = 0; - } - + if (!cur) { + return AVERROR_INVALIDDATA; + } + while (!ff_check_interrupt(c->interrupt_callback) && !ret) { + ret = av_read_frame(cur->ctx, pkt); + if (ret >= 0) { + /* If we got a packet, return it */ + cur->cur_timestamp = av_rescale(pkt->pts, (int64_t)cur->ctx->streams[0]->time_base.num * 90000, cur->ctx->streams[0]->time_base.den); + pkt->stream_index = cur->stream_index; + return 0; + } + if (cur->is_restart_needed) { + cur->cur_seg_offset = 0; + cur->init_sec_buf_read_offset = 0; + if (cur->input) + ff_format_io_close(cur->parent, &cur->input); + ret = reopen_demux_for_component(s, cur); + cur->is_restart_needed = 0; } } return AVERROR_EOF; @@ -1721,12 +1802,8 @@ static int dash_read_packet(AVFormatContext *s, AVPacket *pkt) static int dash_close(AVFormatContext *s) { DASHContext *c = s->priv_data; - if (c->cur_audio) { - free_representation(c->cur_audio); - } - if (c->cur_video) { - free_representation(c->cur_video); - } + free_audio_list(c); + free_video_list(c); av_freep(&c->cookies); av_freep(&c->user_agent); @@ -1799,7 +1876,7 @@ static int dash_seek(AVFormatContext *s, struct representation *pls, int64_t see static int dash_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { - int ret = 0; + int ret, i; DASHContext *c = s->priv_data; int64_t seek_pos_msec = av_rescale_rnd(timestamp, 1000, s->streams[stream_index]->time_base.den, @@ -1807,12 +1884,19 @@ static int dash_read_seek(AVFormatContext *s, int stream_index, int64_t timestam AV_ROUND_DOWN : AV_ROUND_UP); if ((flags & AVSEEK_FLAG_BYTE) || c->is_live) return AVERROR(ENOSYS); - if (c->cur_audio) { - ret = dash_seek(s, c->cur_audio, seek_pos_msec, flags); + + ret = AVERROR_EOF; + for (i = 0; i < c->n_videos; i++) { + if (c->videos[i]->stream_index == stream_index) { + ret = dash_seek(s, c->videos[i], seek_pos_msec, flags); + } } - if (!ret && c->cur_video) { - ret = dash_seek(s, c->cur_video, seek_pos_msec, flags); + for (i = 0; i < c->n_audios; i++) { + if (c->audios[i]->stream_index == stream_index) { + ret = dash_seek(s, c->audios[i], seek_pos_msec, flags); + } } + return ret; } From bb0cc2e7bd6d6cc79413ed898e405c1b11c47759 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 14 Jan 2018 22:35:31 +0800 Subject: [PATCH 1649/2557] dashdec: Search for segment timeline inside AdaptionSets too --- libavformat/dashdec.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 0ac3c67785918..f1012d51b5b54 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -648,7 +648,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr period_baseurl_node, xmlNodePtr fragment_template_node, xmlNodePtr content_component_node, - xmlNodePtr adaptionset_baseurl_node) + xmlNodePtr adaptionset_baseurl_node, + xmlNodePtr adaptionset_segmentlist_node) { int32_t ret = 0; int32_t audio_rep_idx = 0; @@ -659,8 +660,9 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr representation_segmenttemplate_node = NULL; xmlNodePtr representation_baseurl_node = NULL; xmlNodePtr representation_segmentlist_node = NULL; + xmlNodePtr segmentlists_tab[2]; xmlNodePtr fragment_timeline_node = NULL; - xmlNodePtr fragment_templates_tab[2]; + xmlNodePtr fragment_templates_tab[3]; char *duration_val = NULL; char *presentation_timeoffset_val = NULL; char *startnumber_val = NULL; @@ -703,14 +705,15 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, if (representation_segmenttemplate_node || fragment_template_node) { fragment_timeline_node = NULL; fragment_templates_tab[0] = representation_segmenttemplate_node; - fragment_templates_tab[1] = fragment_template_node; + fragment_templates_tab[1] = adaptionset_segmentlist_node; + fragment_templates_tab[2] = fragment_template_node; - presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "presentationTimeOffset"); - duration_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "duration"); - startnumber_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "startNumber"); - timescale_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "timescale"); - initialization_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "initialization"); - media_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "media"); + presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "presentationTimeOffset"); + duration_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "duration"); + startnumber_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "startNumber"); + timescale_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "timescale"); + initialization_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "initialization"); + media_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "media"); if (initialization_val) { rep->init_section = av_mallocz(sizeof(struct fragment)); @@ -756,6 +759,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, if (!fragment_timeline_node) fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline"); + if (!fragment_timeline_node) + fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline"); if (fragment_timeline_node) { fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); while (fragment_timeline_node) { @@ -784,8 +789,11 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, // TODO: https://www.brendanlong.com/the-structure-of-an-mpeg-dash-mpd.html // http://www-itec.uni-klu.ac.at/dash/ddash/mpdGenerator.php?fragmentlength=15&type=full xmlNodePtr fragmenturl_node = NULL; - duration_val = xmlGetProp(representation_segmentlist_node, "duration"); - timescale_val = xmlGetProp(representation_segmentlist_node, "timescale"); + segmentlists_tab[0] = representation_segmentlist_node; + segmentlists_tab[1] = adaptionset_segmentlist_node; + + duration_val = get_val_from_nodes_tab(segmentlists_tab, 2, "duration"); + timescale_val = get_val_from_nodes_tab(segmentlists_tab, 2, "timescale"); if (duration_val) { rep->fragment_duration = (int64_t) strtoll(duration_val, NULL, 10); xmlFree(duration_val); @@ -810,6 +818,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, if (!fragment_timeline_node) fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline"); + if (!fragment_timeline_node) + fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline"); if (fragment_timeline_node) { fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); while (fragment_timeline_node) { @@ -862,6 +872,7 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, xmlNodePtr fragment_template_node = NULL; xmlNodePtr content_component_node = NULL; xmlNodePtr adaptionset_baseurl_node = NULL; + xmlNodePtr adaptionset_segmentlist_node = NULL; xmlNodePtr node = NULL; node = xmlFirstElementChild(adaptionset_node); @@ -872,6 +883,8 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, content_component_node = node; } else if (!av_strcasecmp(node->name, (const char *)"BaseURL")) { adaptionset_baseurl_node = node; + } else if (!av_strcasecmp(node->name, (const char *)"SegmentList")) { + adaptionset_segmentlist_node = node; } else if (!av_strcasecmp(node->name, (const char *)"Representation")) { ret = parse_manifest_representation(s, url, node, adaptionset_node, @@ -879,7 +892,8 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, period_baseurl_node, fragment_template_node, content_component_node, - adaptionset_baseurl_node); + adaptionset_baseurl_node, + adaptionset_segmentlist_node); if (ret < 0) { return ret; } @@ -1863,7 +1877,7 @@ static int dash_seek(AVFormatContext *s, struct representation *pls, int64_t see } else if (pls->fragment_duration > 0) { pls->cur_seq_no = pls->first_seq_no + ((seek_pos_msec * pls->fragment_timescale) / pls->fragment_duration) / 1000; } else { - av_log(pls->parent, AV_LOG_ERROR, "dash_seek missing fragment_duration\n"); + av_log(pls->parent, AV_LOG_ERROR, "dash_seek missing timeline or fragment_duration\n"); pls->cur_seq_no = pls->first_seq_no; } pls->cur_timestamp = 0; From 74b143d81fa38cd4f05a0db889a19a2cb7ff226c Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 14 Jan 2018 22:36:02 +0800 Subject: [PATCH 1650/2557] dashdec: Correct seeking behaviour dash_read_seek() is called only once to issue a seek of *all* streams to the specified timestamp. But to avoid reopening each stream, do a "dry run" for streams that are in a discarded state. Signed-off-by: Steven Liu --- libavformat/dashdec.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index f1012d51b5b54..05b60214744b2 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -1826,19 +1826,22 @@ static int dash_close(AVFormatContext *s) return 0; } -static int dash_seek(AVFormatContext *s, struct representation *pls, int64_t seek_pos_msec, int flags) +static int dash_seek(AVFormatContext *s, struct representation *pls, int64_t seek_pos_msec, int flags, int dry_run) { int ret = 0; int i = 0; int j = 0; int64_t duration = 0; - av_log(pls->parent, AV_LOG_VERBOSE, "DASH seek pos[%"PRId64"ms], playlist %d\n", seek_pos_msec, pls->rep_idx); + av_log(pls->parent, AV_LOG_VERBOSE, "DASH seek pos[%"PRId64"ms], playlist %d%s\n", + seek_pos_msec, pls->rep_idx, dry_run ? " (dry)" : ""); // single fragment mode if (pls->n_fragments == 1) { pls->cur_timestamp = 0; pls->cur_seg_offset = 0; + if (dry_run) + return 0; ff_read_frame_flush(pls->ctx); return av_seek_frame(pls->ctx, -1, seek_pos_msec * 1000, flags); } @@ -1883,14 +1886,14 @@ static int dash_seek(AVFormatContext *s, struct representation *pls, int64_t see pls->cur_timestamp = 0; pls->cur_seg_offset = 0; pls->init_sec_buf_read_offset = 0; - ret = reopen_demux_for_component(s, pls); + ret = dry_run ? 0 : reopen_demux_for_component(s, pls); return ret; } static int dash_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { - int ret, i; + int ret = 0, i; DASHContext *c = s->priv_data; int64_t seek_pos_msec = av_rescale_rnd(timestamp, 1000, s->streams[stream_index]->time_base.den, @@ -1899,16 +1902,14 @@ static int dash_read_seek(AVFormatContext *s, int stream_index, int64_t timestam if ((flags & AVSEEK_FLAG_BYTE) || c->is_live) return AVERROR(ENOSYS); - ret = AVERROR_EOF; + /* Seek in discarded streams with dry_run=1 to avoid reopening them */ for (i = 0; i < c->n_videos; i++) { - if (c->videos[i]->stream_index == stream_index) { - ret = dash_seek(s, c->videos[i], seek_pos_msec, flags); - } + if (!ret) + ret = dash_seek(s, c->videos[i], seek_pos_msec, flags, !c->videos[i]->ctx); } for (i = 0; i < c->n_audios; i++) { - if (c->audios[i]->stream_index == stream_index) { - ret = dash_seek(s, c->audios[i], seek_pos_msec, flags); - } + if (!ret) + ret = dash_seek(s, c->audios[i], seek_pos_msec, flags, !c->audios[i]->ctx); } return ret; From 01d74c405564bb4846bf894bb928ae542273cfe8 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 14 Jan 2018 23:01:45 +0800 Subject: [PATCH 1651/2557] dashdec: Avoid trying to read any segments beyond the last Signed-off-by: Steven Liu --- libavformat/dashdec.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 05b60214744b2..2427ad059eb74 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -1503,9 +1503,11 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) if (ret > 0) goto end; - if (!v->is_restart_needed) - v->cur_seq_no++; - v->is_restart_needed = 1; + if (c->is_live || v->cur_seq_no < v->last_seq_no) { + if (!v->is_restart_needed) + v->cur_seq_no++; + v->is_restart_needed = 1; + } end: return ret; From 57dbabd9c13b9770d2447a2168a1acccd7296827 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 14 Jan 2018 23:02:26 +0800 Subject: [PATCH 1652/2557] dashdec: Support SegmentTemplate inside Period Signed-off-by: Steven Liu --- libavformat/dashdec.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 2427ad059eb74..2492f1d2660ed 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -646,6 +646,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr adaptionset_node, xmlNodePtr mpd_baseurl_node, xmlNodePtr period_baseurl_node, + xmlNodePtr period_segmenttemplate_node, xmlNodePtr fragment_template_node, xmlNodePtr content_component_node, xmlNodePtr adaptionset_baseurl_node, @@ -662,7 +663,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr representation_segmentlist_node = NULL; xmlNodePtr segmentlists_tab[2]; xmlNodePtr fragment_timeline_node = NULL; - xmlNodePtr fragment_templates_tab[3]; + xmlNodePtr fragment_templates_tab[4]; char *duration_val = NULL; char *presentation_timeoffset_val = NULL; char *startnumber_val = NULL; @@ -702,18 +703,19 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, baseurl_nodes[2] = adaptionset_baseurl_node; baseurl_nodes[3] = representation_baseurl_node; - if (representation_segmenttemplate_node || fragment_template_node) { + if (representation_segmenttemplate_node || fragment_template_node || period_segmenttemplate_node) { fragment_timeline_node = NULL; fragment_templates_tab[0] = representation_segmenttemplate_node; fragment_templates_tab[1] = adaptionset_segmentlist_node; fragment_templates_tab[2] = fragment_template_node; + fragment_templates_tab[3] = period_segmenttemplate_node; - presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "presentationTimeOffset"); - duration_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "duration"); - startnumber_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "startNumber"); - timescale_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "timescale"); - initialization_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "initialization"); - media_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "media"); + presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "presentationTimeOffset"); + duration_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "duration"); + startnumber_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "startNumber"); + timescale_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "timescale"); + initialization_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "initialization"); + media_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "media"); if (initialization_val) { rep->init_section = av_mallocz(sizeof(struct fragment)); @@ -866,7 +868,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, xmlNodePtr adaptionset_node, xmlNodePtr mpd_baseurl_node, - xmlNodePtr period_baseurl_node) + xmlNodePtr period_baseurl_node, + xmlNodePtr period_segmenttemplate_node) { int ret = 0; xmlNodePtr fragment_template_node = NULL; @@ -890,6 +893,7 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, adaptionset_node, mpd_baseurl_node, period_baseurl_node, + period_segmenttemplate_node, fragment_template_node, content_component_node, adaptionset_baseurl_node, @@ -918,6 +922,7 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) xmlNodePtr period_node = NULL; xmlNodePtr mpd_baseurl_node = NULL; xmlNodePtr period_baseurl_node = NULL; + xmlNodePtr period_segmenttemplate_node = NULL; xmlNodePtr adaptionset_node = NULL; xmlAttrPtr attr = NULL; char *val = NULL; @@ -1047,8 +1052,10 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) while (adaptionset_node) { if (!av_strcasecmp(adaptionset_node->name, (const char *)"BaseURL")) { period_baseurl_node = adaptionset_node; + } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"SegmentTemplate")) { + period_segmenttemplate_node = adaptionset_node; } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"AdaptationSet")) { - parse_manifest_adaptationset(s, url, adaptionset_node, mpd_baseurl_node, period_baseurl_node); + parse_manifest_adaptationset(s, url, adaptionset_node, mpd_baseurl_node, period_baseurl_node, period_segmenttemplate_node); } adaptionset_node = xmlNextElementSibling(adaptionset_node); } From 856b7cae9f40c094be6a1dfa73eb57295838496c Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Sat, 13 Jan 2018 16:51:43 +0100 Subject: [PATCH 1653/2557] avfilter/vf_idet: added more YUVA formats to idet query_formats Signed-off-by: Michael Niedermayer --- libavfilter/vf_idet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavfilter/vf_idet.c b/libavfilter/vf_idet.c index 14f031aaa9570..02ae2edcb99ec 100644 --- a/libavfilter/vf_idet.c +++ b/libavfilter/vf_idet.c @@ -392,6 +392,8 @@ static int query_formats(AVFilterContext *ctx) AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P, + AV_PIX_FMT_YUVA422P, + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE }; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); From 43e1ccfea186080b1c4cb4cd1e59ac1a3c3dc446 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jan 2018 02:27:20 +0100 Subject: [PATCH 1654/2557] http: cosmetics: reformat reconnect check for better readability The condition was a bit too long, and most editors will break the line and turn it into an unreadable mess. Move out some of the conditions. This should not change the behavior. --- libavformat/http.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libavformat/http.c b/libavformat/http.c index 510b23375a301..aa80e314dff5b 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -1449,12 +1449,18 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) return http_buf_read_compressed(h, buf, size); #endif /* CONFIG_ZLIB */ read_ret = http_buf_read(h, buf, size); - while ((read_ret < 0 && s->reconnect && (!h->is_streamed || s->reconnect_streamed) && s->filesize > 0 && s->off < s->filesize) - || (read_ret == AVERROR_EOF && s->reconnect_at_eof && (!h->is_streamed || s->reconnect_streamed))) { + while (read_ret < 0) { uint64_t target = h->is_streamed ? 0 : s->off; if (read_ret == AVERROR_EXIT) - return read_ret; + break; + + if (h->is_streamed && !s->reconnect_streamed) + break; + + if (!(s->reconnect && s->filesize > 0 && s->off < s->filesize) && + !(s->reconnect_at_eof && read_ret == AVERROR_EOF)) + break; if (reconnect_delay > s->reconnect_delay_max) return AVERROR(EIO); From cbbb2067341d7c2d98f560f81c6fb103af33a490 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 13 Jan 2018 07:05:09 +0100 Subject: [PATCH 1655/2557] hwcontext_vdpau: implement av_hwdevice_get_hwframe_constraints() In addition, this does not allow creating frames contexts with sw_format for which no known transfer formats exist. In theory, we should check whether the chroma format (i.e. the sw_format) is supported at all by the vdpau driver, but checking for transfer formats has the same effect. Note that the pre-existing code adds 1 to priv->nb_pix_fmts[i] for unknown reason, and some checks need to account for that to check for empty lists. They are not off-by-one errors. --- libavutil/hwcontext_vdpau.c | 55 ++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/libavutil/hwcontext_vdpau.c b/libavutil/hwcontext_vdpau.c index 9b8f83964740e..c11c3cfdab25e 100644 --- a/libavutil/hwcontext_vdpau.c +++ b/libavutil/hwcontext_vdpau.c @@ -79,11 +79,12 @@ static const VDPAUPixFmtMap pix_fmts_444[] = { static const struct { VdpChromaType chroma_type; + enum AVPixelFormat frames_sw_format; const VDPAUPixFmtMap *map; } vdpau_pix_fmts[] = { - { VDP_CHROMA_TYPE_420, pix_fmts_420 }, - { VDP_CHROMA_TYPE_422, pix_fmts_422 }, - { VDP_CHROMA_TYPE_444, pix_fmts_444 }, + { VDP_CHROMA_TYPE_420, AV_PIX_FMT_YUV420P, pix_fmts_420 }, + { VDP_CHROMA_TYPE_422, AV_PIX_FMT_YUV422P, pix_fmts_422 }, + { VDP_CHROMA_TYPE_444, AV_PIX_FMT_YUV444P, pix_fmts_444 }, }; static int count_pixfmts(const VDPAUPixFmtMap *map) @@ -170,6 +171,35 @@ static void vdpau_device_uninit(AVHWDeviceContext *ctx) av_freep(&priv->pix_fmts[i]); } +static int vdpau_frames_get_constraints(AVHWDeviceContext *ctx, + const void *hwconfig, + AVHWFramesConstraints *constraints) +{ + VDPAUDeviceContext *priv = ctx->internal->priv; + int nb_sw_formats = 0; + int i; + + constraints->valid_sw_formats = av_malloc_array(FF_ARRAY_ELEMS(vdpau_pix_fmts) + 1, + sizeof(*constraints->valid_sw_formats)); + if (!constraints->valid_sw_formats) + return AVERROR(ENOMEM); + + for (i = 0; i < FF_ARRAY_ELEMS(vdpau_pix_fmts); i++) { + if (priv->nb_pix_fmts[i] > 1) + constraints->valid_sw_formats[nb_sw_formats++] = vdpau_pix_fmts[i].frames_sw_format; + } + constraints->valid_sw_formats[nb_sw_formats] = AV_PIX_FMT_NONE; + + constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats)); + if (!constraints->valid_hw_formats) + return AVERROR(ENOMEM); + + constraints->valid_hw_formats[0] = AV_PIX_FMT_VDPAU; + constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE; + + return 0; +} + static void vdpau_buffer_free(void *opaque, uint8_t *data) { AVHWFramesContext *ctx = opaque; @@ -214,26 +244,18 @@ static int vdpau_frames_init(AVHWFramesContext *ctx) int i; - switch (ctx->sw_format) { - case AV_PIX_FMT_YUV420P: priv->chroma_type = VDP_CHROMA_TYPE_420; break; - case AV_PIX_FMT_YUV422P: priv->chroma_type = VDP_CHROMA_TYPE_422; break; - case AV_PIX_FMT_YUV444P: priv->chroma_type = VDP_CHROMA_TYPE_444; break; - default: - av_log(ctx, AV_LOG_ERROR, "Unsupported data layout: %s\n", - av_get_pix_fmt_name(ctx->sw_format)); - return AVERROR(ENOSYS); - } - for (i = 0; i < FF_ARRAY_ELEMS(vdpau_pix_fmts); i++) { - if (vdpau_pix_fmts[i].chroma_type == priv->chroma_type) { + if (vdpau_pix_fmts[i].frames_sw_format == ctx->sw_format) { + priv->chroma_type = vdpau_pix_fmts[i].chroma_type; priv->chroma_idx = i; priv->pix_fmts = device_priv->pix_fmts[i]; priv->nb_pix_fmts = device_priv->nb_pix_fmts[i]; break; } } - if (!priv->pix_fmts) { - av_log(ctx, AV_LOG_ERROR, "Unsupported chroma type: %d\n", priv->chroma_type); + if (priv->nb_pix_fmts < 2) { + av_log(ctx, AV_LOG_ERROR, "Unsupported sw format: %s\n", + av_get_pix_fmt_name(ctx->sw_format)); return AVERROR(ENOSYS); } @@ -468,6 +490,7 @@ const HWContextType ff_hwcontext_type_vdpau = { #endif .device_init = vdpau_device_init, .device_uninit = vdpau_device_uninit, + .frames_get_constraints = vdpau_frames_get_constraints, .frames_init = vdpau_frames_init, .frames_get_buffer = vdpau_get_buffer, .transfer_get_formats = vdpau_transfer_get_formats, From a1f38c75893c852cf19dcf3e4553549ba1e70950 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 14 Jan 2018 00:39:39 +0100 Subject: [PATCH 1656/2557] avcodec/ac3dec_fixed: Fix integer overflow in scale_coefs() Fixes: runtime error: signed integer overflow: 2147483520 + 128 cannot be represented in type 'int' Fixes: 4800/clusterfuzz-testcase-minimized-6110372403609600 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/ac3dec_fixed.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/ac3dec_fixed.c b/libavcodec/ac3dec_fixed.c index 9a6d7a08b1c0a..bd66175d50f93 100644 --- a/libavcodec/ac3dec_fixed.c +++ b/libavcodec/ac3dec_fixed.c @@ -64,8 +64,8 @@ static void scale_coefs ( int dynrng, int len) { - int i, shift, round; - unsigned mul; + int i, shift; + unsigned mul, round; int temp, temp1, temp2, temp3, temp4, temp5, temp6, temp7; mul = (dynrng & 0x1f) + 0x20; From 6887e412434776eb260ad3904f565be491dd5726 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 14 Jan 2018 00:39:40 +0100 Subject: [PATCH 1657/2557] avcodec/jpeg2000: Check sum of sizes of band->prec before allocating Fixes: OOM Fixes: 4810/clusterfuzz-testcase-minimized-6034253235093504 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/jpeg2000.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c index e7f03bd0df53d..8e90980976e52 100644 --- a/libavcodec/jpeg2000.c +++ b/libavcodec/jpeg2000.c @@ -541,6 +541,9 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp, if (!reslevel->band) return AVERROR(ENOMEM); + if (reslevel->num_precincts_x * (uint64_t)reslevel->num_precincts_y * reslevel->nbands > avctx->max_pixels / sizeof(*reslevel->band->prec)) + return AVERROR(ENOMEM); + for (bandno = 0; bandno < reslevel->nbands; bandno++, gbandno++) { ret = init_band(avctx, reslevel, comp, codsty, qntsty, From 83e34ae3c2b36e7b20169a8866e3f49294db1f5a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 14 Jan 2018 00:39:41 +0100 Subject: [PATCH 1658/2557] avcodec/wavpack: Fix integer overflows in wv_unpack_stereo / mono Fixes: runtime error: signed integer overflow: 2146276249 + 1487583 cannot be represented in type 'int' Fixes: 4823/clusterfuzz-testcase-minimized-4551896611160064 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/wavpack.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c index a117e8aa81ba2..d5e1e07b743be 100644 --- a/libavcodec/wavpack.c +++ b/libavcodec/wavpack.c @@ -433,8 +433,8 @@ static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb, L2 = L + ((s->decorr[i].weightA * (int64_t)A + 512) >> 10); R2 = R + ((s->decorr[i].weightB * (int64_t)B + 512) >> 10); } else { - L2 = L + ((int)(s->decorr[i].weightA * (unsigned)A + 512) >> 10); - R2 = R + ((int)(s->decorr[i].weightB * (unsigned)B + 512) >> 10); + L2 = L + (unsigned)((int)(s->decorr[i].weightA * (unsigned)A + 512) >> 10); + R2 = R + (unsigned)((int)(s->decorr[i].weightB * (unsigned)B + 512) >> 10); } if (A && L) s->decorr[i].weightA -= ((((L ^ A) >> 30) & 2) - 1) * s->decorr[i].delta; @@ -446,7 +446,7 @@ static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb, if (type != AV_SAMPLE_FMT_S16P) L2 = L + ((s->decorr[i].weightA * (int64_t)s->decorr[i].samplesA[0] + 512) >> 10); else - L2 = L + ((int)(s->decorr[i].weightA * (unsigned)s->decorr[i].samplesA[0] + 512) >> 10); + L2 = L + (unsigned)((int)(s->decorr[i].weightA * (unsigned)s->decorr[i].samplesA[0] + 512) >> 10); UPDATE_WEIGHT_CLIP(s->decorr[i].weightA, s->decorr[i].delta, s->decorr[i].samplesA[0], L); L = L2; if (type != AV_SAMPLE_FMT_S16P) @@ -460,7 +460,7 @@ static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb, if (type != AV_SAMPLE_FMT_S16P) R2 = R + ((s->decorr[i].weightB * (int64_t)s->decorr[i].samplesB[0] + 512) >> 10); else - R2 = R + ((int)(s->decorr[i].weightB * (unsigned)s->decorr[i].samplesB[0] + 512) >> 10); + R2 = R + (unsigned)((int)(s->decorr[i].weightB * (unsigned)s->decorr[i].samplesB[0] + 512) >> 10); UPDATE_WEIGHT_CLIP(s->decorr[i].weightB, s->decorr[i].delta, s->decorr[i].samplesB[0], R); R = R2; @@ -472,7 +472,7 @@ static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb, if (type != AV_SAMPLE_FMT_S16P) L2 = L + ((s->decorr[i].weightA * (int64_t)R2 + 512) >> 10); else - L2 = L + ((int)(s->decorr[i].weightA * (unsigned)R2 + 512) >> 10); + L2 = L + (unsigned)((int)(s->decorr[i].weightA * (unsigned)R2 + 512) >> 10); UPDATE_WEIGHT_CLIP(s->decorr[i].weightA, s->decorr[i].delta, R2, L); L = L2; s->decorr[i].samplesB[0] = L; @@ -554,7 +554,7 @@ static inline int wv_unpack_mono(WavpackFrameContext *s, GetBitContext *gb, if (type != AV_SAMPLE_FMT_S16P) S = T + ((s->decorr[i].weightA * (int64_t)A + 512) >> 10); else - S = T + ((int)(s->decorr[i].weightA * (unsigned)A + 512) >> 10); + S = T + (unsigned)((int)(s->decorr[i].weightA * (unsigned)A + 512) >> 10); if (A && T) s->decorr[i].weightA -= ((((T ^ A) >> 30) & 2) - 1) * s->decorr[i].delta; s->decorr[i].samplesA[j] = T = S; From 6512ff72f9cc058e27646604caeacc4ef0dbd93e Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 15 Jan 2018 13:09:31 +0100 Subject: [PATCH 1659/2557] avformat: deprecate another ffserver API leftover --- doc/APIchanges | 4 ++++ libavformat/avformat.h | 5 +++++ libavformat/utils.c | 12 ++++++++++++ libavformat/version.h | 5 ++++- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index d66c842521d56..018481522496a 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-01-xx - xxxxxxx - lavf 58.4.100 - avformat.h + Deprecate AVStream.recommended_encoder_configuration. It was useful only for + FFserver, which has been removed. + 2018-01-xx - xxxxxxx - lavfi 7.11.101 - avfilter.h Deprecate avfilter_link_get_channels(). Use av_buffersink_get_channels(). diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 4f2798a871683..8556f80372af7 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -986,12 +986,15 @@ typedef struct AVStream { */ AVRational r_frame_rate; +#if FF_API_LAVF_FFSERVER /** * String containing pairs of key and values describing recommended encoder configuration. * Pairs are separated by ','. * Keys are separated from values by '='. */ + attribute_deprecated char *recommended_encoder_configuration; +#endif /** * Codec parameters associated with this stream. Allocated and freed by @@ -1218,10 +1221,12 @@ AVRational av_stream_get_r_frame_rate(const AVStream *s); attribute_deprecated void av_stream_set_r_frame_rate(AVStream *s, AVRational r); attribute_deprecated +#if FF_API_LAVF_FFSERVER char* av_stream_get_recommended_encoder_configuration(const AVStream *s); attribute_deprecated void av_stream_set_recommended_encoder_configuration(AVStream *s, char *configuration); #endif +#endif struct AVCodecParserContext *av_stream_get_parser(const AVStream *s); diff --git a/libavformat/utils.c b/libavformat/utils.c index 2185a6f05b089..00226395738ad 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -119,7 +119,11 @@ static int64_t wrap_timestamp(const AVStream *st, int64_t timestamp) #if FF_API_FORMAT_GET_SET MAKE_ACCESSORS(AVStream, stream, AVRational, r_frame_rate) +#if FF_API_LAVF_FFSERVER +FF_DISABLE_DEPRECATION_WARNINGS MAKE_ACCESSORS(AVStream, stream, char *, recommended_encoder_configuration) +FF_ENABLE_DEPRECATION_WARNINGS +#endif MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, video_codec) MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, audio_codec) MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, subtitle_codec) @@ -4256,6 +4260,8 @@ int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src) } } +#if FF_API_LAVF_FFSERVER +FF_DISABLE_DEPRECATION_WARNINGS av_freep(&dst->recommended_encoder_configuration); if (src->recommended_encoder_configuration) { const char *conf_str = src->recommended_encoder_configuration; @@ -4263,6 +4269,8 @@ int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src) if (!dst->recommended_encoder_configuration) return AVERROR(ENOMEM); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } @@ -4310,7 +4318,11 @@ FF_ENABLE_DEPRECATION_WARNINGS if (st->info) av_freep(&st->info->duration_error); av_freep(&st->info); +#if FF_API_LAVF_FFSERVER +FF_DISABLE_DEPRECATION_WARNINGS av_freep(&st->recommended_encoder_configuration); +FF_ENABLE_DEPRECATION_WARNINGS +#endif av_freep(pst); } diff --git a/libavformat/version.h b/libavformat/version.h index 5ced041f0a433..d566e255e53d3 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 3 +#define LIBAVFORMAT_VERSION_MINOR 4 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ @@ -82,6 +82,9 @@ #ifndef FF_API_OLD_AVIO_EOF_0 #define FF_API_OLD_AVIO_EOF_0 (LIBAVFORMAT_VERSION_MAJOR < 59) #endif +#ifndef FF_API_LAVF_FFSERVER +#define FF_API_LAVF_FFSERVER (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif #ifndef FF_API_R_FRAME_RATE From 631c56a8e46dea41585f3e7b3ef9c52b49faa385 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 16 Jan 2018 12:57:04 +0100 Subject: [PATCH 1660/2557] avformat: make avformat_network_init() explicitly optional It was sort of optional before - if you didn't call it, networking was initialized on demand, and an ugly warning was logged. Also, the doxygen comments threatened that it would be made strictly required one day. Make it explicitly optional. I would prefer to deprecate it fully, but there might still be legitimate reasons to use this. But the average user won't need it. This is needed only for two reasons: to initialize TLS libraries like OpenSSL and GnuTLS, and winsock. OpenSSL and GnuTLS were already silently initialized on demand if the global network init function was not called. They also have various thread-safety acrobatics, which make concurrent initialization within libavformat safe. In addition, the libraries are moving towards making their global init functions safe, which removes all need for central global init. In particular, GnuTLS 3.5.16 and OpenSSL 1.1.0g have been found to have safe init functions. In all cases, they use internal reference counters to avoid that the global uninit functions interfere with concurrent uses of the library by other API users who called global init. winsock should be thread-safe as well, and maintains an internal reference counter as well. Since we still support ancient TLS libraries, which do not have this fixed, and since it's unknown whether winsock and GnuTLS reinitialization is costly in any way, don't deprecate the libavformat functions yet. --- doc/APIchanges | 6 ++++++ libavformat/avformat.h | 19 +++++++++++++------ libavformat/network.c | 9 --------- libavformat/network.h | 1 - libavformat/utils.c | 2 -- libavformat/version.h | 2 +- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 018481522496a..76993658794e5 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,12 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-01-xx - xxxxxxx - lavf 58.5.100 - avformat.h + Explicitly make avformat_network_init() and avformat_network_deinit() optional. + If these are not called, network initialization and deinitialization is + automatic, and unlike in older versions, fully supported, unless libavformat + is linked to ancient GnuTLS and OpenSSL. + 2018-01-xx - xxxxxxx - lavf 58.4.100 - avformat.h Deprecate AVStream.recommended_encoder_configuration. It was useful only for FFserver, which has been removed. diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 8556f80372af7..b0387214c53f7 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1998,17 +1998,24 @@ void av_register_input_format(AVInputFormat *format); void av_register_output_format(AVOutputFormat *format); /** - * Do global initialization of network components. This is optional, - * but recommended, since it avoids the overhead of implicitly - * doing the setup for each session. + * Do global initialization of network libraries. This is optional, + * and not recommended anymore. * - * Calling this function will become mandatory if using network - * protocols at some major version bump. + * This functions only exists to work around thread-safety issues + * with older GnuTLS or OpenSSL libraries. If libavformat is linked + * to newer versions of those libraries, or if you do not use them, + * calling this function is unnecessary. Otherwise, you need to call + * this function before any other threads using them are started. + * + * This function will be deprecated once support for older GnuTLS and + * OpenSSL libraries is removed, and this function has no purpose + * anymore. */ int avformat_network_init(void); /** - * Undo the initialization done by avformat_network_init. + * Undo the initialization done by avformat_network_init. Call it only + * once for each time you called avformat_network_init. */ int avformat_network_deinit(void); diff --git a/libavformat/network.c b/libavformat/network.c index e9eb4b443a0e6..d5c82e9ab9ba8 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -54,20 +54,11 @@ void ff_tls_deinit(void) #endif } -int ff_network_inited_globally; - int ff_network_init(void) { #if HAVE_WINSOCK2_H WSADATA wsaData; -#endif - if (!ff_network_inited_globally) - av_log(NULL, AV_LOG_WARNING, "Using network protocols without global " - "network initialization. Please use " - "avformat_network_init(), this will " - "become mandatory later.\n"); -#if HAVE_WINSOCK2_H if (WSAStartup(MAKEWORD(1,1), &wsaData)) return 0; #endif diff --git a/libavformat/network.h b/libavformat/network.h index 3c0f8732799fe..e3fda4d5e2da1 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -75,7 +75,6 @@ int ff_neterrno(void); int ff_socket_nonblock(int socket, int enable); -extern int ff_network_inited_globally; int ff_network_init(void); void ff_network_close(void); diff --git a/libavformat/utils.c b/libavformat/utils.c index 00226395738ad..3d733417e19df 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -4885,7 +4885,6 @@ int avformat_network_init(void) { #if CONFIG_NETWORK int ret; - ff_network_inited_globally = 1; if ((ret = ff_network_init()) < 0) return ret; if ((ret = ff_tls_init()) < 0) @@ -4899,7 +4898,6 @@ int avformat_network_deinit(void) #if CONFIG_NETWORK ff_network_close(); ff_tls_deinit(); - ff_network_inited_globally = 0; #endif return 0; } diff --git a/libavformat/version.h b/libavformat/version.h index d566e255e53d3..87758b027ce87 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 4 +#define LIBAVFORMAT_VERSION_MINOR 5 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From 27b9f82e2c5dca3ad642ed13c2360032a17687ec Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 16 Jan 2018 13:23:55 +0100 Subject: [PATCH 1661/2557] hwcontext_d3d11va: implement av_hwdevice_get_hwframe_constraints() D3D11 has rather fine grained per format capabilities for different uses that can be queried at runtime. Since we don't know what the user wants to do with the formats when av_hwdevice_get_hwframe_constraints() is called, we simply return all formats that have the most basic support. --- libavutil/hwcontext_d3d11va.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 2f97156a54ce1..960883c9d8a81 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -120,6 +120,38 @@ static void d3d11va_frames_uninit(AVHWFramesContext *ctx) s->staging_texture = NULL; } +static int d3d11va_frames_get_constraints(AVHWDeviceContext *ctx, + const void *hwconfig, + AVHWFramesConstraints *constraints) +{ + AVD3D11VADeviceContext *device_hwctx = ctx->hwctx; + int nb_sw_formats = 0; + HRESULT hr; + int i; + + constraints->valid_sw_formats = av_malloc_array(FF_ARRAY_ELEMS(supported_formats) + 1, + sizeof(*constraints->valid_sw_formats)); + if (!constraints->valid_sw_formats) + return AVERROR(ENOMEM); + + for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) { + UINT format_support = 0; + hr = ID3D11Device_CheckFormatSupport(device_hwctx->device, supported_formats[i].d3d_format, &format_support); + if (SUCCEEDED(hr) && (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D)) + constraints->valid_sw_formats[nb_sw_formats++] = supported_formats[i].pix_fmt; + } + constraints->valid_sw_formats[nb_sw_formats] = AV_PIX_FMT_NONE; + + constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats)); + if (!constraints->valid_hw_formats) + return AVERROR(ENOMEM); + + constraints->valid_hw_formats[0] = AV_PIX_FMT_D3D11; + constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE; + + return 0; +} + static void free_texture(void *opaque, uint8_t *data) { ID3D11Texture2D_Release((ID3D11Texture2D *)opaque); @@ -576,6 +608,7 @@ const HWContextType ff_hwcontext_type_d3d11va = { .device_create = d3d11va_device_create, .device_init = d3d11va_device_init, .device_uninit = d3d11va_device_uninit, + .frames_get_constraints = d3d11va_frames_get_constraints, .frames_init = d3d11va_frames_init, .frames_uninit = d3d11va_frames_uninit, .frames_get_buffer = d3d11va_get_buffer, From 85e10c0a9321bfe0d2afe0f3983ab6a8df6e3fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 16 Jan 2018 15:40:24 +0200 Subject: [PATCH 1662/2557] intreadwrite: Use __unaligned in MSVC for ARM64 as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This attribute is supported for this architecture in MSVC as well (but produces errors if used for 32 bit x86). Signed-off-by: Martin Storsjö --- libavutil/intreadwrite.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/intreadwrite.h b/libavutil/intreadwrite.h index 84685f02ebb61..94abb6cd1131a 100644 --- a/libavutil/intreadwrite.h +++ b/libavutil/intreadwrite.h @@ -192,7 +192,7 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; # define AV_RN(s, p) (((const union unaligned_##s *) (p))->l) # define AV_WN(s, p, v) ((((union unaligned_##s *) (p))->l) = (v)) -#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_X64)) && AV_HAVE_FAST_UNALIGNED +#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_X64) || defined(_M_ARM64)) && AV_HAVE_FAST_UNALIGNED # define AV_RN(s, p) (*((const __unaligned uint##s##_t*)(p))) # define AV_WN(s, p, v) (*((__unaligned uint##s##_t*)(p)) = (v)) From a919ab853efcecf89516e703df8018d0649e1143 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 15 Jan 2018 18:57:33 +0800 Subject: [PATCH 1663/2557] lavc/snow_dwt: add struct MpegEncContext to fix headers check. add missing struct MpegEncContext, use make checkheaders found this warning. Signed-off-by: Jun Zhao Signed-off-by: Michael Niedermayer --- libavcodec/snow_dwt.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/snow_dwt.h b/libavcodec/snow_dwt.h index e2d7528056f40..ee699de35ed45 100644 --- a/libavcodec/snow_dwt.h +++ b/libavcodec/snow_dwt.h @@ -24,6 +24,8 @@ #include #include +struct MpegEncContext; + typedef int DWTELEM; typedef short IDWTELEM; From 383804edd812410219a097e2bf3efac8a8b4562a Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Tue, 16 Jan 2018 22:44:02 +0800 Subject: [PATCH 1664/2557] lavfi/deinterlace_vaapi: fix can't show full option information. use ffmpeg -h filter=deinterlace_vaapi can't get full help information, the root cause is not setting the flags fileld in options. Signed-off-by: Jun Zhao Signed-off-by: Michael Niedermayer --- libavfilter/vf_deinterlace_vaapi.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c index 44c5ae7642cbd..a38da5d57b707 100644 --- a/libavfilter/vf_deinterlace_vaapi.c +++ b/libavfilter/vf_deinterlace_vaapi.c @@ -615,22 +615,22 @@ static const AVOption deint_vaapi_options[] = { OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = VAProcDeinterlacingNone }, VAProcDeinterlacingNone, VAProcDeinterlacingCount - 1, FLAGS, "mode" }, { "default", "Use the highest-numbered (and therefore possibly most advanced) deinterlacing algorithm", - 0, AV_OPT_TYPE_CONST, { .i64 = VAProcDeinterlacingNone }, .unit = "mode" }, + 0, AV_OPT_TYPE_CONST, { .i64 = VAProcDeinterlacingNone }, 0, 0, FLAGS, "mode" }, { "bob", "Use the bob deinterlacing algorithm", - 0, AV_OPT_TYPE_CONST, { .i64 = VAProcDeinterlacingBob }, .unit = "mode" }, + 0, AV_OPT_TYPE_CONST, { .i64 = VAProcDeinterlacingBob }, 0, 0, FLAGS, "mode" }, { "weave", "Use the weave deinterlacing algorithm", - 0, AV_OPT_TYPE_CONST, { .i64 = VAProcDeinterlacingWeave }, .unit = "mode" }, + 0, AV_OPT_TYPE_CONST, { .i64 = VAProcDeinterlacingWeave }, 0, 0, FLAGS, "mode" }, { "motion_adaptive", "Use the motion adaptive deinterlacing algorithm", - 0, AV_OPT_TYPE_CONST, { .i64 = VAProcDeinterlacingMotionAdaptive }, .unit = "mode" }, + 0, AV_OPT_TYPE_CONST, { .i64 = VAProcDeinterlacingMotionAdaptive }, 0, 0, FLAGS, "mode" }, { "motion_compensated", "Use the motion compensated deinterlacing algorithm", - 0, AV_OPT_TYPE_CONST, { .i64 = VAProcDeinterlacingMotionCompensated }, .unit = "mode" }, + 0, AV_OPT_TYPE_CONST, { .i64 = VAProcDeinterlacingMotionCompensated }, 0, 0, FLAGS, "mode" }, { "rate", "Generate output at frame rate or field rate", OFFSET(field_rate), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 2, FLAGS, "rate" }, { "frame", "Output at frame rate (one frame of output for each field-pair)", - 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .unit = "rate" }, + 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "rate" }, { "field", "Output at field rate (one frame of output for each field)", - 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, .unit = "rate" }, + 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, FLAGS, "rate" }, { "auto", "Only deinterlace fields, passing frames through unchanged", OFFSET(auto_enable), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, From e1e89c0695b430ca1f0f869ac8a2b6b46be9e2fa Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Sat, 23 Dec 2017 16:14:25 +0530 Subject: [PATCH 1665/2557] avfilter/vidstab: check bytesPerPixel only for packed formats. libvidstab introduced this variable only for packed formats but in vf_vidstab*.c, it's checked for all inputs. So the filter errors out for YUV422/444P streams. Fixes #6736. Signed-off-by: Michael Niedermayer --- libavfilter/vf_vidstabdetect.c | 3 ++- libavfilter/vf_vidstabtransform.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_vidstabdetect.c b/libavfilter/vf_vidstabdetect.c index 63a178a0c2b5c..fd7ff3be24b0e 100644 --- a/libavfilter/vf_vidstabdetect.c +++ b/libavfilter/vf_vidstabdetect.c @@ -107,10 +107,11 @@ static int config_input(AVFilterLink *inlink) VSMotionDetect* md = &(s->md); VSFrameInfo fi; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int is_planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR; vsFrameInfoInit(&fi, inlink->w, inlink->h, ff_av2vs_pixfmt(ctx, inlink->format)); - if (fi.bytesPerPixel != av_get_bits_per_pixel(desc)/8) { + if (!is_planar && fi.bytesPerPixel != av_get_bits_per_pixel(desc)/8) { av_log(ctx, AV_LOG_ERROR, "pixel-format error: wrong bits/per/pixel, please report a BUG"); return AVERROR(EINVAL); } diff --git a/libavfilter/vf_vidstabtransform.c b/libavfilter/vf_vidstabtransform.c index 11a0e3d512520..d1ec1391cbb87 100644 --- a/libavfilter/vf_vidstabtransform.c +++ b/libavfilter/vf_vidstabtransform.c @@ -146,6 +146,7 @@ static int config_input(AVFilterLink *inlink) FILE *f; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int is_planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR; VSTransformData *td = &(tc->td); @@ -161,7 +162,7 @@ static int config_input(AVFilterLink *inlink) return AVERROR(EINVAL); } - if (fi_src.bytesPerPixel != av_get_bits_per_pixel(desc)/8 || + if ((!is_planar && fi_src.bytesPerPixel != av_get_bits_per_pixel(desc)/8) || fi_src.log2ChromaW != desc->log2_chroma_w || fi_src.log2ChromaH != desc->log2_chroma_h) { av_log(ctx, AV_LOG_ERROR, "pixel-format error: bpp %i<>%i ", From 1b5d3c08e3fbaa1fb6ba43532ce79904b0d5650b Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 17 Jan 2018 19:39:24 -0300 Subject: [PATCH 1666/2557] avformat: small cosmetics after 6512ff72f9 Signed-off-by: James Almer --- libavformat/avformat.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index b0387214c53f7..bfb57d7757fe5 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -991,6 +991,8 @@ typedef struct AVStream { * String containing pairs of key and values describing recommended encoder configuration. * Pairs are separated by ','. * Keys are separated from values by '='. + * + * @deprecated unused */ attribute_deprecated char *recommended_encoder_configuration; @@ -1220,8 +1222,8 @@ attribute_deprecated AVRational av_stream_get_r_frame_rate(const AVStream *s); attribute_deprecated void av_stream_set_r_frame_rate(AVStream *s, AVRational r); -attribute_deprecated #if FF_API_LAVF_FFSERVER +attribute_deprecated char* av_stream_get_recommended_encoder_configuration(const AVStream *s); attribute_deprecated void av_stream_set_recommended_encoder_configuration(AVStream *s, char *configuration); From 8088b5d69c51b9329ccbc6d1125cf55c54ff6374 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 18 Jan 2018 11:17:03 +0100 Subject: [PATCH 1667/2557] avfilter/af_afade: acrossfade: switch to activate Signed-off-by: Paul B Mahol --- libavfilter/af_afade.c | 207 +++++++++++++++++------------------------ 1 file changed, 83 insertions(+), 124 deletions(-) diff --git a/libavfilter/af_afade.c b/libavfilter/af_afade.c index 4d0b31eac7536..285b5b6557ec0 100644 --- a/libavfilter/af_afade.c +++ b/libavfilter/af_afade.c @@ -23,10 +23,14 @@ * fade audio filter */ +#define FF_INTERNAL_FIELDS 1 +#include "framequeue.h" + #include "libavutil/audio_fifo.h" #include "libavutil/opt.h" #include "audio.h" #include "avfilter.h" +#include "filters.h" #include "internal.h" typedef struct AudioFadeContext { @@ -39,6 +43,7 @@ typedef struct AudioFadeContext { int64_t start_time; int overlap; int cf0_eof; + int prev_size; int crossfade_is_over; AVAudioFifo *fifo[2]; int64_t pts; @@ -428,157 +433,127 @@ CROSSFADE(flt, float) CROSSFADE(s16, int16_t) CROSSFADE(s32, int32_t) -static int acrossfade_filter_frame(AVFilterLink *inlink, AVFrame *in) +static int activate(AVFilterContext *ctx) { - AVFilterContext *ctx = inlink->dst; AudioFadeContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - AVFrame *out, *cf[2] = { NULL }; - int ret = 0, nb_samples; + AVFrame *in = NULL, *out, *cf[2] = { NULL }; + int ret = 0, nb_samples, status; + int64_t pts; if (s->crossfade_is_over) { + ret = ff_inlink_consume_frame(ctx->inputs[1], &in); + if (ret < 0) { + return ret; + } else if (ff_inlink_acknowledge_status(ctx->inputs[1], &status, &pts)) { + ff_outlink_set_status(ctx->outputs[0], status, pts); + return 0; + } else { + if (ff_outlink_frame_wanted(ctx->outputs[0]) && !in) { + ff_inlink_request_frame(ctx->inputs[1]); + return 0; + } + } in->pts = s->pts; s->pts += av_rescale_q(in->nb_samples, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); return ff_filter_frame(outlink, in); - } else if (inlink == ctx->inputs[0]) { - av_audio_fifo_write(s->fifo[0], (void **)in->extended_data, in->nb_samples); + } - nb_samples = av_audio_fifo_size(s->fifo[0]) - s->nb_samples; + if (ff_framequeue_queued_samples(&ctx->inputs[0]->fifo) > s->nb_samples) { + nb_samples = ff_framequeue_queued_samples(&ctx->inputs[0]->fifo) - s->nb_samples; if (nb_samples > 0) { - out = ff_get_audio_buffer(outlink, nb_samples); - if (!out) { - ret = AVERROR(ENOMEM); - goto fail; - } - av_audio_fifo_read(s->fifo[0], (void **)out->extended_data, nb_samples); - out->pts = s->pts; - s->pts += av_rescale_q(nb_samples, - (AVRational){ 1, outlink->sample_rate }, outlink->time_base); - ret = ff_filter_frame(outlink, out); - } - } else if (av_audio_fifo_size(s->fifo[1]) < s->nb_samples) { - if (!s->overlap && av_audio_fifo_size(s->fifo[0]) > 0) { - nb_samples = av_audio_fifo_size(s->fifo[0]); - - cf[0] = ff_get_audio_buffer(outlink, nb_samples); - out = ff_get_audio_buffer(outlink, nb_samples); - if (!out || !cf[0]) { - ret = AVERROR(ENOMEM); - goto fail; + ret = ff_inlink_consume_samples(ctx->inputs[0], nb_samples, nb_samples, &in); + if (ret < 0) { + return ret; } - av_audio_fifo_read(s->fifo[0], (void **)cf[0]->extended_data, nb_samples); - - s->fade_samples(out->extended_data, cf[0]->extended_data, nb_samples, - outlink->channels, -1, nb_samples - 1, nb_samples, s->curve); - out->pts = s->pts; - s->pts += av_rescale_q(nb_samples, - (AVRational){ 1, outlink->sample_rate }, outlink->time_base); - ret = ff_filter_frame(outlink, out); - if (ret < 0) - goto fail; } - - av_audio_fifo_write(s->fifo[1], (void **)in->extended_data, in->nb_samples); - } else if (av_audio_fifo_size(s->fifo[1]) >= s->nb_samples) { - av_audio_fifo_write(s->fifo[1], (void **)in->extended_data, in->nb_samples); - + in->pts = s->pts; + s->pts += av_rescale_q(in->nb_samples, + (AVRational){ 1, outlink->sample_rate }, outlink->time_base); + return ff_filter_frame(outlink, in); + } else if (ff_framequeue_queued_samples(&ctx->inputs[1]->fifo) >= s->nb_samples) { if (s->overlap) { - cf[0] = ff_get_audio_buffer(outlink, s->nb_samples); - cf[1] = ff_get_audio_buffer(outlink, s->nb_samples); out = ff_get_audio_buffer(outlink, s->nb_samples); - if (!out || !cf[0] || !cf[1]) { + if (!out) + return AVERROR(ENOMEM); + + ret = ff_inlink_consume_samples(ctx->inputs[0], s->nb_samples, s->nb_samples, &cf[0]); + if (ret < 0) { av_frame_free(&out); - ret = AVERROR(ENOMEM); - goto fail; + return ret; } - av_audio_fifo_read(s->fifo[0], (void **)cf[0]->extended_data, s->nb_samples); - av_audio_fifo_read(s->fifo[1], (void **)cf[1]->extended_data, s->nb_samples); + ret = ff_inlink_consume_samples(ctx->inputs[1], s->nb_samples, s->nb_samples, &cf[1]); + if (ret < 0) { + av_frame_free(&out); + return ret; + } s->crossfade_samples(out->extended_data, cf[0]->extended_data, cf[1]->extended_data, - s->nb_samples, in->channels, + s->nb_samples, out->channels, s->curve, s->curve2); out->pts = s->pts; s->pts += av_rescale_q(s->nb_samples, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); - ret = ff_filter_frame(outlink, out); - if (ret < 0) - goto fail; + s->crossfade_is_over = 1; + av_frame_free(&cf[0]); + av_frame_free(&cf[1]); + return ff_filter_frame(outlink, out); } else { out = ff_get_audio_buffer(outlink, s->nb_samples); - cf[1] = ff_get_audio_buffer(outlink, s->nb_samples); - if (!out || !cf[1]) { - ret = AVERROR(ENOMEM); + if (!out) + return AVERROR(ENOMEM); + + ret = ff_inlink_consume_samples(ctx->inputs[0], s->nb_samples, s->nb_samples, &cf[0]); + if (ret < 0) { av_frame_free(&out); - goto fail; + return ret; } - av_audio_fifo_read(s->fifo[1], (void **)cf[1]->extended_data, s->nb_samples); - - s->fade_samples(out->extended_data, cf[1]->extended_data, s->nb_samples, - outlink->channels, 1, 0, s->nb_samples, s->curve2); + s->fade_samples(out->extended_data, cf[0]->extended_data, s->nb_samples, + outlink->channels, -1, s->nb_samples - 1, s->nb_samples, s->curve); out->pts = s->pts; s->pts += av_rescale_q(s->nb_samples, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); + av_frame_free(&cf[0]); ret = ff_filter_frame(outlink, out); if (ret < 0) - goto fail; - } + return ret; - nb_samples = av_audio_fifo_size(s->fifo[1]); - if (nb_samples > 0) { - out = ff_get_audio_buffer(outlink, nb_samples); - if (!out) { - ret = AVERROR(ENOMEM); - goto fail; + out = ff_get_audio_buffer(outlink, s->nb_samples); + if (!out) + return AVERROR(ENOMEM); + + ret = ff_inlink_consume_samples(ctx->inputs[1], s->nb_samples, s->nb_samples, &cf[1]); + if (ret < 0) { + av_frame_free(&out); + return ret; } - av_audio_fifo_read(s->fifo[1], (void **)out->extended_data, nb_samples); + s->fade_samples(out->extended_data, cf[1]->extended_data, s->nb_samples, + outlink->channels, 1, 0, s->nb_samples, s->curve2); out->pts = s->pts; - s->pts += av_rescale_q(nb_samples, + s->pts += av_rescale_q(s->nb_samples, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); - ret = ff_filter_frame(outlink, out); + s->crossfade_is_over = 1; + av_frame_free(&cf[1]); + return ff_filter_frame(outlink, out); } - s->crossfade_is_over = 1; - } - -fail: - av_frame_free(&in); - av_frame_free(&cf[0]); - av_frame_free(&cf[1]); - return ret; -} - -static int acrossfade_request_frame(AVFilterLink *outlink) -{ - AVFilterContext *ctx = outlink->src; - AudioFadeContext *s = ctx->priv; - int ret = 0; - - if (!s->cf0_eof) { - AVFilterLink *cf0 = ctx->inputs[0]; - ret = ff_request_frame(cf0); - if (ret < 0 && ret != AVERROR_EOF) - return ret; - if (ret == AVERROR_EOF) { + } else if (ff_outlink_frame_wanted(ctx->outputs[0])) { + if (!s->cf0_eof && ctx->inputs[0]->status_in) { s->cf0_eof = 1; - ret = 0; } - } else { - AVFilterLink *cf1 = ctx->inputs[1]; - int nb_samples = av_audio_fifo_size(s->fifo[1]); - - ret = ff_request_frame(cf1); - if (ret == AVERROR_EOF && nb_samples > 0) { - AVFrame *out = ff_get_audio_buffer(outlink, nb_samples); - if (!out) - return AVERROR(ENOMEM); - - av_audio_fifo_read(s->fifo[1], (void **)out->extended_data, nb_samples); - ret = ff_filter_frame(outlink, out); + if (ctx->inputs[1]->status_in) { + ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, AV_NOPTS_VALUE); + return 0; } + if (!s->cf0_eof) + ff_inlink_request_frame(ctx->inputs[0]); + else + ff_inlink_request_frame(ctx->inputs[1]); + return 0; } return ret; @@ -615,32 +590,17 @@ static int acrossfade_config_output(AVFilterLink *outlink) config_output(outlink); - s->fifo[0] = av_audio_fifo_alloc(outlink->format, outlink->channels, s->nb_samples); - s->fifo[1] = av_audio_fifo_alloc(outlink->format, outlink->channels, s->nb_samples); - if (!s->fifo[0] || !s->fifo[1]) - return AVERROR(ENOMEM); - return 0; } -static av_cold void uninit(AVFilterContext *ctx) -{ - AudioFadeContext *s = ctx->priv; - - av_audio_fifo_free(s->fifo[0]); - av_audio_fifo_free(s->fifo[1]); -} - static const AVFilterPad avfilter_af_acrossfade_inputs[] = { { .name = "crossfade0", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = acrossfade_filter_frame, }, { .name = "crossfade1", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = acrossfade_filter_frame, }, { NULL } }; @@ -649,7 +609,6 @@ static const AVFilterPad avfilter_af_acrossfade_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .request_frame = acrossfade_request_frame, .config_props = acrossfade_config_output, }, { NULL } @@ -660,7 +619,7 @@ AVFilter ff_af_acrossfade = { .description = NULL_IF_CONFIG_SMALL("Cross fade two input audio streams."), .query_formats = query_formats, .priv_size = sizeof(AudioFadeContext), - .uninit = uninit, + .activate = activate, .priv_class = &acrossfade_class, .inputs = avfilter_af_acrossfade_inputs, .outputs = avfilter_af_acrossfade_outputs, From 4f6b34f1f803a103f321330bc5f9e4a01f788925 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 18 Jan 2018 13:00:25 -0300 Subject: [PATCH 1668/2557] avformat: small AVFormatContext doxy cosmetics Signed-off-by: James Almer --- libavformat/avformat.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index bfb57d7757fe5..e5740be2b4dfb 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1019,10 +1019,10 @@ typedef struct AVStream { ***************************************************************** */ +#define MAX_STD_TIMEBASES (30*12+30+3+6) /** * Stream information used internally by avformat_find_stream_info() */ -#define MAX_STD_TIMEBASES (30*12+30+3+6) struct { int64_t last_dts; int64_t duration_gcd; @@ -1859,7 +1859,7 @@ typedef struct AVFormatContext { */ char *protocol_whitelist; - /* + /** * A callback for opening new IO streams. * * Whenever a muxer or a demuxer needs to open an IO stream (typically from From fb3fd4d506238c7ef731a2c031c744abb1c54813 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 18 Jan 2018 19:12:30 -0300 Subject: [PATCH 1669/2557] fate: update filter-acrossfade test reference file durandal_1707: 8088b5d69c broke the acrossfade test <@durandal_1707> jamrial: there was test? durandal_1707: fate-filter-acrossfade <@durandal_1707> what broke? what used to be one frame is now two <@durandal_1707> ahh, just update test Signed-off-by: James Almer --- tests/ref/fate/filter-acrossfade | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ref/fate/filter-acrossfade b/tests/ref/fate/filter-acrossfade index 0567b022e873c..8d524c4d2e8e4 100644 --- a/tests/ref/fate/filter-acrossfade +++ b/tests/ref/fate/filter-acrossfade @@ -178,7 +178,8 @@ 0, 174968, 174968, 1024, 4096, 0x74ffeeae 0, 175992, 175992, 408, 1632, 0x28353dae 0, 176400, 176400, 88200, 352800, 0x4fb492af -0, 264600, 264600, 1912, 7648, 0xf0c93a5a +0, 264600, 264600, 888, 3552, 0xa5a41b07 +0, 265488, 265488, 1024, 4096, 0xc1c61f53 0, 266512, 266512, 1024, 4096, 0x35b6d595 0, 267536, 267536, 1024, 4096, 0xc4481118 0, 268560, 268560, 1024, 4096, 0x5dc0b58d From 381a4820c64ba2d1b3ddc3a50147961f1d8c5848 Mon Sep 17 00:00:00 2001 From: Rodger Combs Date: Fri, 12 Jan 2018 19:08:27 -0600 Subject: [PATCH 1670/2557] lavfi/vf_scale_vaapi: set output SAR --- libavfilter/vf_scale_vaapi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c index 22e928c098871..4bead5aaf4b88 100644 --- a/libavfilter/vf_scale_vaapi.c +++ b/libavfilter/vf_scale_vaapi.c @@ -240,6 +240,11 @@ static int scale_vaapi_config_output(AVFilterLink *outlink) goto fail; } + if (inlink->sample_aspect_ratio.num) + outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink->w, outlink->w * inlink->h}, inlink->sample_aspect_ratio); + else + outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; + av_freep(&hwconfig); av_hwframe_constraints_free(&constraints); return 0; From 0afa171f25bc9b613a77328182e54d6e781269d3 Mon Sep 17 00:00:00 2001 From: Karthick Jeyapal Date: Fri, 19 Jan 2018 17:03:09 +0800 Subject: [PATCH 1671/2557] avformat/hlsenc: Add CODECS attribute to master playlist --- libavformat/dashenc.c | 2 +- libavformat/hlsenc.c | 67 ++++++++++++++++++++++++++++++++++++++- libavformat/hlsplaylist.c | 5 ++- libavformat/hlsplaylist.h | 3 +- 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 3345b89118d77..39d0afe350a80 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -820,7 +820,7 @@ static int write_manifest(AVFormatContext *s, int final) stream_bitrate += max_audio_bitrate; } get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i); - ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, agroup); + ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, agroup, NULL); } avio_close(out); if (use_rename) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index e36120c320631..8ad906a480cd4 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -58,6 +58,11 @@ typedef enum { HLS_START_SEQUENCE_AS_FORMATTED_DATETIME = 2, // YYYYMMDDhhmmss } StartSequenceSourceType; +typedef enum { + CODEC_ATTRIBUTE_WRITTEN = 0, + CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN, +} CodecAttributeStatus; + #define KEYSIZE 16 #define LINE_BUFFER_SIZE 1024 #define HLS_MICROSECOND_UNIT 1000000 @@ -142,6 +147,8 @@ typedef struct VariantStream { int fmp4_init_mode; AVStream **streams; + char codec_attr[128]; + CodecAttributeStatus attr_status; unsigned int nb_streams; int m3u8_created; /* status of media play-list creation */ char *agroup; /* audio group name */ @@ -290,6 +297,51 @@ static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSCont } +static void write_codec_attr(AVStream *st, VariantStream *vs) { + int codec_strlen = strlen(vs->codec_attr); + char attr[32]; + + if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) + return; + if (vs->attr_status == CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN) + return; + + if (st->codecpar->codec_id == AV_CODEC_ID_H264) { + uint8_t *data = st->codecpar->extradata; + if ((data[0] | data[1] | data[2]) == 0 && data[3] == 1 && (data[4] & 0x1F) == 7) { + snprintf(attr, sizeof(attr), + "avc1.%02x%02x%02x", data[5], data[6], data[7]); + } else { + goto fail; + } + } else if (st->codecpar->codec_id == AV_CODEC_ID_MP2) { + snprintf(attr, sizeof(attr), "mp4a.40.33"); + } else if (st->codecpar->codec_id == AV_CODEC_ID_MP3) { + snprintf(attr, sizeof(attr), "mp4a.40.34"); + } else if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { + /* TODO : For HE-AAC, HE-AACv2, the last digit needs to be set to 5 and 29 respectively */ + snprintf(attr, sizeof(attr), "mp4a.40.2"); + } else if (st->codecpar->codec_id == AV_CODEC_ID_AC3) { + snprintf(attr, sizeof(attr), "ac-3"); + } else if (st->codecpar->codec_id == AV_CODEC_ID_EAC3) { + snprintf(attr, sizeof(attr), "ec-3"); + } else { + goto fail; + } + // Don't write the same attribute multiple times + if (!av_stristr(vs->codec_attr, attr)) { + snprintf(vs->codec_attr + codec_strlen, + sizeof(vs->codec_attr) - codec_strlen, + "%s%s", codec_strlen ? "," : "", attr); + } + return; + +fail: + vs->codec_attr[0] = '\0'; + vs->attr_status = CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN; + return; +} + static int replace_int_data_in_filename(char *buf, int buf_size, const char *filename, char placeholder, int64_t number) { const char *p; @@ -1227,7 +1279,7 @@ static int create_master_playlist(AVFormatContext *s, bandwidth += bandwidth / 10; ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name, - aud_st ? vs->agroup : NULL); + aud_st ? vs->agroup : NULL, vs->codec_attr); av_freep(&m3u8_rel_name); } @@ -1857,6 +1909,19 @@ static int hls_write_header(AVFormatContext *s) continue; } avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den); + write_codec_attr(outer_st, vs); + + } + /* Update the Codec Attr string for the mapped audio groups */ + if (vs->has_video && vs->agroup) { + for (j = 0; j < hls->nb_varstreams; j++) { + VariantStream *vs_agroup = &(hls->var_streams[j]); + if (!vs_agroup->has_video && !vs_agroup->has_subtitle && + vs_agroup->agroup && + !av_strcasecmp(vs_agroup->agroup, vs->agroup)) { + write_codec_attr(vs_agroup->streams[0], vs); + } + } } } fail: diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c index 098dc8917032d..b8a3a1409034a 100644 --- a/libavformat/hlsplaylist.c +++ b/libavformat/hlsplaylist.c @@ -46,7 +46,8 @@ void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, } void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, - int bandwidth, char *filename, char *agroup) { + int bandwidth, char *filename, char *agroup, + char *codecs) { if (!out || !filename) return; @@ -60,6 +61,8 @@ void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, if (st && st->codecpar->width > 0 && st->codecpar->height > 0) avio_printf(out, ",RESOLUTION=%dx%d", st->codecpar->width, st->codecpar->height); + if (codecs && strlen(codecs) > 0) + avio_printf(out, ",CODECS=\"%s\"", codecs); if (agroup && strlen(agroup) > 0) avio_printf(out, ",AUDIO=\"group_%s\"", agroup); avio_printf(out, "\n%s\n\n", filename); diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index 9969315e00501..7532e3752f88f 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -40,7 +40,8 @@ void ff_hls_write_playlist_version(AVIOContext *out, int version); void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, char *filename, int name_id, int is_default); void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, - int bandwidth, char *filename, char *agroup); + int bandwidth, char *filename, char *agroup, + char *codecs); void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, int target_duration, int64_t sequence, uint32_t playlist_type); From e07649e618caedc07eaf2f4d09253de7f77d14f0 Mon Sep 17 00:00:00 2001 From: Nikolas Bowe Date: Thu, 18 Jan 2018 15:21:56 -0800 Subject: [PATCH 1672/2557] avformat/matroskadec: Fix float-cast-overflow undefined behavior in matroska_parse_tracks() Signed-off-by: Michael Niedermayer --- libavformat/matroskadec.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 496499b553273..158ce7ae1fa39 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -2096,8 +2096,16 @@ static int matroska_parse_tracks(AVFormatContext *s) } if (track->type == MATROSKA_TRACK_TYPE_VIDEO) { - if (!track->default_duration && track->video.frame_rate > 0) - track->default_duration = 1000000000 / track->video.frame_rate; + if (!track->default_duration && track->video.frame_rate > 0) { + double default_duration = 1000000000 / track->video.frame_rate; + if (default_duration > UINT64_MAX || default_duration < 0) { + av_log(matroska->ctx, AV_LOG_WARNING, + "Invalid frame rate %e. Cannot calculate default duration.\n", + track->video.frame_rate); + } else { + track->default_duration = default_duration; + } + } if (track->video.display_width == -1) track->video.display_width = track->video.pixel_width; if (track->video.display_height == -1) From 07a96b6251f0d55d370e14d661301ced0cd03c24 Mon Sep 17 00:00:00 2001 From: Yogender Gupta Date: Thu, 18 Jan 2018 12:16:19 +0530 Subject: [PATCH 1673/2557] avcodec/cuviddec: set key frame for decoded frames Signed-off-by: Timo Rothenpieler --- libavcodec/cuviddec.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index c23033c7e3182..122c28f6e87ef 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -74,6 +74,8 @@ typedef struct CuvidContext int internal_error; int decoder_flushing; + int *key_frame; + cudaVideoCodec codec_type; cudaVideoChromaFormat chroma_format; @@ -340,6 +342,8 @@ static int CUDAAPI cuvid_handle_picture_decode(void *opaque, CUVIDPICPARAMS* pic av_log(avctx, AV_LOG_TRACE, "pfnDecodePicture\n"); + ctx->key_frame[picparams->CurrPicIdx] = picparams->intra_pic_flag; + ctx->internal_error = CHECK_CU(ctx->cvdl->cuvidDecodePicture(ctx->cudecoder, picparams)); if (ctx->internal_error < 0) return 0; @@ -590,6 +594,7 @@ static int cuvid_output_frame(AVCodecContext *avctx, AVFrame *frame) goto error; } + frame->key_frame = ctx->key_frame[parsed_frame.dispinfo.picture_index]; frame->width = avctx->width; frame->height = avctx->height; if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) @@ -693,6 +698,8 @@ static av_cold int cuvid_decode_end(AVCodecContext *avctx) av_buffer_unref(&ctx->hwframe); av_buffer_unref(&ctx->hwdevice); + av_freep(&ctx->key_frame); + cuvid_free_functions(&ctx->cvdl); return 0; @@ -977,6 +984,12 @@ static av_cold int cuvid_decode_init(AVCodecContext *avctx) FFMIN(sizeof(ctx->cuparse_ext.raw_seqhdr_data), avctx->extradata_size)); } + ctx->key_frame = av_mallocz(ctx->nb_surfaces * sizeof(int)); + if (!ctx->key_frame) { + ret = AVERROR(ENOMEM); + goto error; + } + ctx->cuparseinfo.ulMaxNumDecodeSurfaces = ctx->nb_surfaces; ctx->cuparseinfo.ulMaxDisplayDelay = 4; ctx->cuparseinfo.pUserData = avctx; From 7652af9df06ddcdb6f6fdf52919c2d6260b51ca1 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Thu, 18 Jan 2018 21:25:49 +0100 Subject: [PATCH 1674/2557] lavf/swfdec: Reduce score when auto-detecting swf files. Not more than 32bit are tested. --- libavformat/swfdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/swfdec.c b/libavformat/swfdec.c index 57b619fb203d0..212157f54aeb9 100644 --- a/libavformat/swfdec.c +++ b/libavformat/swfdec.c @@ -95,7 +95,7 @@ static int swf_probe(AVProbeData *p) if (p->buf[3] >= 20 || xmax < 16 || ymax < 16) return AVPROBE_SCORE_MAX / 4; - return AVPROBE_SCORE_MAX; + return AVPROBE_SCORE_EXTENSION + 1; } #if CONFIG_ZLIB From e3acba0d5d7b5b35b779b25ec3a76a4d80a405ea Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 6 Jan 2018 22:04:21 +0100 Subject: [PATCH 1675/2557] avfilter/formats: remove support for deprecated channel count specification Signed-off-by: Marton Balint --- libavfilter/formats.c | 12 ++---------- tests/ref/fate/filter-formats | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/libavfilter/formats.c b/libavfilter/formats.c index 20a2c89719983..31ee445c494ee 100644 --- a/libavfilter/formats.c +++ b/libavfilter/formats.c @@ -662,20 +662,12 @@ int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx) int ff_parse_channel_layout(int64_t *ret, int *nret, const char *arg, void *log_ctx) { - char *tail; int64_t chlayout; int nb_channels; if (av_get_extended_channel_layout(arg, &chlayout, &nb_channels) < 0) { - /* [TEMPORARY 2016-12 -> 2017-12]*/ - nb_channels = strtol(arg, &tail, 10); - if (!errno && *tail == 'c' && *(tail + 1) == '\0' && nb_channels > 0 && nb_channels < 64) { - chlayout = 0; - av_log(log_ctx, AV_LOG_WARNING, "Deprecated channel count specification '%s'. This will stop working in releases made in 2018 and after.\n", arg); - } else { - av_log(log_ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n", arg); - return AVERROR(EINVAL); - } + av_log(log_ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n", arg); + return AVERROR(EINVAL); } if (!chlayout && !nret) { av_log(log_ctx, AV_LOG_ERROR, "Unknown channel layout '%s' is not supported.\n", arg); diff --git a/tests/ref/fate/filter-formats b/tests/ref/fate/filter-formats index ea85eed23d3f9..17ff5b222f12f 100644 --- a/tests/ref/fate/filter-formats +++ b/tests/ref/fate/filter-formats @@ -75,7 +75,7 @@ quad(side) 0 = ff_parse_channel_layout(0000000000000004, 1, 1c); 0 = ff_parse_channel_layout(0000000000000003, 2, 2c); -1 = ff_parse_channel_layout(FFFFFFFFFFFFFFFF, -1, -1c); -0 = ff_parse_channel_layout(0000000000000000, 60, 60c); +-1 = ff_parse_channel_layout(FFFFFFFFFFFFFFFF, -1, 60c); -1 = ff_parse_channel_layout(FFFFFFFFFFFFFFFF, -1, 65c); 0 = ff_parse_channel_layout(0000000000000000, 2, 2C); 0 = ff_parse_channel_layout(0000000000000000, 60, 60C); From 7c27bbd590e6d9da5b7b33163e7dce7876ef2b58 Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Mon, 15 Jan 2018 13:51:46 +0530 Subject: [PATCH 1676/2557] avdevice/decklink: addition of copyts option Signed-off-by: Marton Balint --- doc/indevs.texi | 5 +++++ libavdevice/decklink_common_c.h | 1 + libavdevice/decklink_dec.cpp | 18 +++++++++++------- libavdevice/decklink_dec_c.c | 1 + 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index 56066bf23adf6..36aef49108590 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -317,6 +317,11 @@ Defaults to @samp{1073741824}. Sets the audio sample bit depth. Must be @samp{16} or @samp{32}. Defaults to @samp{16}. +@item decklink_copyts +If set to @option{true}, timestamps are forwarded as they are without removing +the initial offset. +Defaults to @option{false}. + @end table @subsection Examples diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h index 368ac259e4a4c..ac6563a317eb4 100644 --- a/libavdevice/decklink_common_c.h +++ b/libavdevice/decklink_common_c.h @@ -52,6 +52,7 @@ struct decklink_cctx { char *format_code; int raw_format; int64_t queue_size; + int copyts; }; #endif /* AVDEVICE_DECKLINK_COMMON_C_H */ diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 94dae2600328b..1fd40caaf5b32 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -586,7 +586,8 @@ static int64_t get_pkt_pts(IDeckLinkVideoInputFrame *videoFrame, IDeckLinkAudioInputPacket *audioFrame, int64_t wallclock, DecklinkPtsSource pts_src, - AVRational time_base, int64_t *initial_pts) + AVRational time_base, int64_t *initial_pts, + int copyts) { int64_t pts = AV_NOPTS_VALUE; BMDTimeValue bmd_pts; @@ -619,10 +620,12 @@ static int64_t get_pkt_pts(IDeckLinkVideoInputFrame *videoFrame, if (res == S_OK) pts = bmd_pts / time_base.num; - if (pts != AV_NOPTS_VALUE && *initial_pts == AV_NOPTS_VALUE) - *initial_pts = pts; - if (*initial_pts != AV_NOPTS_VALUE) - pts -= *initial_pts; + if (!copyts) { + if (pts != AV_NOPTS_VALUE && *initial_pts == AV_NOPTS_VALUE) + *initial_pts = pts; + if (*initial_pts != AV_NOPTS_VALUE) + pts -= *initial_pts; + } return pts; } @@ -635,6 +638,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( BMDTimeValue frameTime; BMDTimeValue frameDuration; int64_t wallclock = 0; + struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data; if (ctx->autodetect) { if (videoFrame && !(videoFrame->GetFlags() & bmdFrameHasNoInputSource) && @@ -694,7 +698,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( no_video = 0; } - pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, ctx->video_pts_source, ctx->video_st->time_base, &initial_video_pts); + pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, ctx->video_pts_source, ctx->video_st->time_base, &initial_video_pts, cctx->copyts); pkt.dts = pkt.pts; pkt.duration = frameDuration; @@ -785,7 +789,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( pkt.size = audioFrame->GetSampleFrameCount() * ctx->audio_st->codecpar->channels * (ctx->audio_depth / 8); audioFrame->GetBytes(&audioFrameBytes); audioFrame->GetPacketTime(&audio_pts, ctx->audio_st->time_base.den); - pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, ctx->audio_pts_source, ctx->audio_st->time_base, &initial_audio_pts); + pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, ctx->audio_pts_source, ctx->audio_st->time_base, &initial_audio_pts, cctx->copyts); pkt.dts = pkt.pts; //fprintf(stderr,"Audio Frame size %d ts %d\n", pkt.size, pkt.pts); diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c index 1c6d826945442..f65b17727636a 100644 --- a/libavdevice/decklink_dec_c.c +++ b/libavdevice/decklink_dec_c.c @@ -73,6 +73,7 @@ static const AVOption options[] = { { "draw_bars", "draw bars on signal loss" , OFFSET(draw_bars), AV_OPT_TYPE_BOOL, { .i64 = 1}, 0, 1, DEC }, { "queue_size", "input queue buffer size", OFFSET(queue_size), AV_OPT_TYPE_INT64, { .i64 = (1024 * 1024 * 1024)}, 0, INT64_MAX, DEC }, { "audio_depth", "audio bitdepth (16 or 32)", OFFSET(audio_depth), AV_OPT_TYPE_INT, { .i64 = 16}, 16, 32, DEC }, + { "decklink_copyts", "copy timestamps, do not remove the initial offset", OFFSET(copyts), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC }, { NULL }, }; From dfa2523bdd820348634325edaf6e3ae2afb8c218 Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Mon, 15 Jan 2018 13:52:11 +0530 Subject: [PATCH 1677/2557] avdevice/decklink: addition of PTS_SRC_NB in enum DecklinkPtsSource Signed-off-by: Marton Balint --- libavdevice/decklink_common_c.h | 1 + libavdevice/decklink_dec_c.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h index ac6563a317eb4..18097e2d5f632 100644 --- a/libavdevice/decklink_common_c.h +++ b/libavdevice/decklink_common_c.h @@ -28,6 +28,7 @@ typedef enum DecklinkPtsSource { PTS_SRC_VIDEO = 2, PTS_SRC_REFERENCE = 3, PTS_SRC_WALLCLOCK = 4, + PTS_SRC_NB } DecklinkPtsSource; struct decklink_cctx { diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c index f65b17727636a..accae530503dd 100644 --- a/libavdevice/decklink_dec_c.c +++ b/libavdevice/decklink_dec_c.c @@ -64,8 +64,8 @@ static const AVOption options[] = { { "analog_xlr", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 4}, 0, 0, DEC, "audio_input"}, { "analog_rca", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 5}, 0, 0, DEC, "audio_input"}, { "microphone", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 6}, 0, 0, DEC, "audio_input"}, - { "audio_pts", "audio pts source", OFFSET(audio_pts_source), AV_OPT_TYPE_INT, { .i64 = PTS_SRC_AUDIO }, 1, 4, DEC, "pts_source"}, - { "video_pts", "video pts source", OFFSET(video_pts_source), AV_OPT_TYPE_INT, { .i64 = PTS_SRC_VIDEO }, 1, 4, DEC, "pts_source"}, + { "audio_pts", "audio pts source", OFFSET(audio_pts_source), AV_OPT_TYPE_INT, { .i64 = PTS_SRC_AUDIO }, 1, PTS_SRC_NB-1, DEC, "pts_source"}, + { "video_pts", "video pts source", OFFSET(video_pts_source), AV_OPT_TYPE_INT, { .i64 = PTS_SRC_VIDEO }, 1, PTS_SRC_NB-1, DEC, "pts_source"}, { "audio", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PTS_SRC_AUDIO }, 0, 0, DEC, "pts_source"}, { "video", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PTS_SRC_VIDEO }, 0, 0, DEC, "pts_source"}, { "reference", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PTS_SRC_REFERENCE}, 0, 0, DEC, "pts_source"}, From fc93eca126aa4d68dd37c3e1b9d15bf05565ef04 Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Mon, 15 Jan 2018 13:52:26 +0530 Subject: [PATCH 1678/2557] avdevice/decklink: addition of absolute wallclock option for pts source Signed-off-by: Marton Balint --- doc/indevs.texi | 6 ++++-- libavdevice/decklink_common_c.h | 1 + libavdevice/decklink_dec.cpp | 16 ++++++++++++---- libavdevice/decklink_dec_c.c | 1 + libavdevice/version.h | 2 +- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index 36aef49108590..0bc8e6a9b1bea 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -298,11 +298,13 @@ Sets the audio input source. Must be @samp{unset}, @samp{embedded}, @item video_pts Sets the video packet timestamp source. Must be @samp{video}, @samp{audio}, -@samp{reference} or @samp{wallclock}. Defaults to @samp{video}. +@samp{reference}, @samp{wallclock} or @samp{abs_wallclock}. +Defaults to @samp{video}. @item audio_pts Sets the audio packet timestamp source. Must be @samp{video}, @samp{audio}, -@samp{reference} or @samp{wallclock}. Defaults to @samp{audio}. +@samp{reference}, @samp{wallclock} or @samp{abs_wallclock}. +Defaults to @samp{audio}. @item draw_bars If set to @samp{true}, color bars are drawn in the event of a signal loss. diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h index 18097e2d5f632..08e9f9bbd5e12 100644 --- a/libavdevice/decklink_common_c.h +++ b/libavdevice/decklink_common_c.h @@ -28,6 +28,7 @@ typedef enum DecklinkPtsSource { PTS_SRC_VIDEO = 2, PTS_SRC_REFERENCE = 3, PTS_SRC_WALLCLOCK = 4, + PTS_SRC_ABS_WALLCLOCK = 5, PTS_SRC_NB } DecklinkPtsSource; diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 1fd40caaf5b32..a69e28680be3a 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -585,6 +585,7 @@ ULONG decklink_input_callback::Release(void) static int64_t get_pkt_pts(IDeckLinkVideoInputFrame *videoFrame, IDeckLinkAudioInputPacket *audioFrame, int64_t wallclock, + int64_t abs_wallclock, DecklinkPtsSource pts_src, AVRational time_base, int64_t *initial_pts, int copyts) @@ -607,13 +608,18 @@ static int64_t get_pkt_pts(IDeckLinkVideoInputFrame *videoFrame, res = videoFrame->GetHardwareReferenceTimestamp(time_base.den, &bmd_pts, &bmd_duration); break; case PTS_SRC_WALLCLOCK: + /* fall through */ + case PTS_SRC_ABS_WALLCLOCK: { /* MSVC does not support compound literals like AV_TIME_BASE_Q * in C++ code (compiler error C4576) */ AVRational timebase; timebase.num = 1; timebase.den = AV_TIME_BASE; - pts = av_rescale_q(wallclock, timebase, time_base); + if (pts_src == PTS_SRC_WALLCLOCK) + pts = av_rescale_q(wallclock, timebase, time_base); + else + pts = av_rescale_q(abs_wallclock, timebase, time_base); break; } } @@ -637,7 +643,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( void *audioFrameBytes; BMDTimeValue frameTime; BMDTimeValue frameDuration; - int64_t wallclock = 0; + int64_t wallclock = 0, abs_wallclock = 0; struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data; if (ctx->autodetect) { @@ -652,6 +658,8 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( ctx->frameCount++; if (ctx->audio_pts_source == PTS_SRC_WALLCLOCK || ctx->video_pts_source == PTS_SRC_WALLCLOCK) wallclock = av_gettime_relative(); + if (ctx->audio_pts_source == PTS_SRC_ABS_WALLCLOCK || ctx->video_pts_source == PTS_SRC_ABS_WALLCLOCK) + abs_wallclock = av_gettime(); // Handle Video Frame if (videoFrame) { @@ -698,7 +706,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( no_video = 0; } - pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, ctx->video_pts_source, ctx->video_st->time_base, &initial_video_pts, cctx->copyts); + pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, abs_wallclock, ctx->video_pts_source, ctx->video_st->time_base, &initial_video_pts, cctx->copyts); pkt.dts = pkt.pts; pkt.duration = frameDuration; @@ -789,7 +797,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( pkt.size = audioFrame->GetSampleFrameCount() * ctx->audio_st->codecpar->channels * (ctx->audio_depth / 8); audioFrame->GetBytes(&audioFrameBytes); audioFrame->GetPacketTime(&audio_pts, ctx->audio_st->time_base.den); - pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, ctx->audio_pts_source, ctx->audio_st->time_base, &initial_audio_pts, cctx->copyts); + pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, abs_wallclock, ctx->audio_pts_source, ctx->audio_st->time_base, &initial_audio_pts, cctx->copyts); pkt.dts = pkt.pts; //fprintf(stderr,"Audio Frame size %d ts %d\n", pkt.size, pkt.pts); diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c index accae530503dd..47018dc681a96 100644 --- a/libavdevice/decklink_dec_c.c +++ b/libavdevice/decklink_dec_c.c @@ -70,6 +70,7 @@ static const AVOption options[] = { { "video", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PTS_SRC_VIDEO }, 0, 0, DEC, "pts_source"}, { "reference", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PTS_SRC_REFERENCE}, 0, 0, DEC, "pts_source"}, { "wallclock", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PTS_SRC_WALLCLOCK}, 0, 0, DEC, "pts_source"}, + { "abs_wallclock", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PTS_SRC_ABS_WALLCLOCK}, 0, 0, DEC, "pts_source"}, { "draw_bars", "draw bars on signal loss" , OFFSET(draw_bars), AV_OPT_TYPE_BOOL, { .i64 = 1}, 0, 1, DEC }, { "queue_size", "input queue buffer size", OFFSET(queue_size), AV_OPT_TYPE_INT64, { .i64 = (1024 * 1024 * 1024)}, 0, INT64_MAX, DEC }, { "audio_depth", "audio bitdepth (16 or 32)", OFFSET(audio_depth), AV_OPT_TYPE_INT, { .i64 = 16}, 16, 32, DEC }, diff --git a/libavdevice/version.h b/libavdevice/version.h index 364404d65ecb0..0d4477f82e2a1 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -29,7 +29,7 @@ #define LIBAVDEVICE_VERSION_MAJOR 58 #define LIBAVDEVICE_VERSION_MINOR 0 -#define LIBAVDEVICE_VERSION_MICRO 100 +#define LIBAVDEVICE_VERSION_MICRO 101 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ LIBAVDEVICE_VERSION_MINOR, \ From 5409f065f2c48ad9c4baf787d08384176cbc62a4 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 8 Jan 2018 20:16:56 -0500 Subject: [PATCH 1679/2557] avdevice/decklink: Suppress warning about misuse of struct instead of class When building with Clang, the following warning is shown: warning: struct 'IDeckLinkVideoFrame' was previously declared as a class [-Wmismatched-tags] The function incorrectly casts IDeckLinkVideoFrame as a struct instead of a class pointer. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- libavdevice/decklink_enc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index c06ca4668f025..89b03f2bd5648 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -321,7 +321,7 @@ static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt) pthread_mutex_unlock(&ctx->mutex); /* Schedule frame for playback. */ - hr = ctx->dlo->ScheduleVideoFrame((struct IDeckLinkVideoFrame *) frame, + hr = ctx->dlo->ScheduleVideoFrame((class IDeckLinkVideoFrame *) frame, pkt->pts * ctx->bmd_tb_num, ctx->bmd_tb_num, ctx->bmd_tb_den); /* Pass ownership to DeckLink, or release on failure */ From b5b48685043e4761335c4ab7086eba3b24a9c03d Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 8 Jan 2018 20:16:58 -0500 Subject: [PATCH 1680/2557] avdevice/decklink: Fix compilation of module on OSX Clang applies the missing-prototypes warning on C++ files, whereas gcc only applies it to C. As a result, the decklink_common.cpp file fails to build because of missing prototypes in DecklinkDispatch.cpp (which is #included by decklink_common.cpp). We don't want to change the actual Blackmagic SDK sources, so suppress the warning just for that one #include. Signed-off-by: Devin Heitmueller Signed-off-by: Marton Balint --- libavdevice/decklink_common.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp index 6ef2c529f446e..d1576b85535dc 100644 --- a/libavdevice/decklink_common.cpp +++ b/libavdevice/decklink_common.cpp @@ -29,7 +29,18 @@ extern "C" { #ifdef _WIN32 #include #else +/* The file provided by the SDK is known to be missing prototypes, which doesn't + cause issues with GCC since the warning doesn't apply to C++ files. However + Clang does complain (and warnings are treated as errors), so suppress the + warning just for this one file */ +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmissing-prototypes" +#endif #include +#ifdef __clang__ +#pragma clang diagnostic pop +#endif #endif extern "C" { From 3a02cbe3faccad9e346d63cf40c009e664657304 Mon Sep 17 00:00:00 2001 From: Henrik Gramner Date: Sat, 5 Aug 2017 00:09:52 +0200 Subject: [PATCH 1681/2557] x86inc: Enable AVX emulation for floating-point pseudo-instructions There are 32 pseudo-instructions for each floating-point comparison instruction, but only 8 of them are actually valid in legacy-encoded mode. The remaining 24 requires the use of VEX-encoded (v-prefixed) instructions and can therefore be disregarded for this purpose. --- libavutil/x86/x86inc.asm | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/libavutil/x86/x86inc.asm b/libavutil/x86/x86inc.asm index 196374c34827a..3b43dbc2e02f2 100644 --- a/libavutil/x86/x86inc.asm +++ b/libavutil/x86/x86inc.asm @@ -1297,10 +1297,42 @@ AVX_INSTR blendpd, sse4, 1, 1, 0 AVX_INSTR blendps, sse4, 1, 1, 0 AVX_INSTR blendvpd, sse4 ; can't be emulated AVX_INSTR blendvps, sse4 ; can't be emulated +AVX_INSTR cmpeqpd, sse2, 1, 0, 1 +AVX_INSTR cmpeqps, sse, 1, 0, 1 +AVX_INSTR cmpeqsd, sse2, 1, 0, 0 +AVX_INSTR cmpeqss, sse, 1, 0, 0 +AVX_INSTR cmplepd, sse2, 1, 0, 0 +AVX_INSTR cmpleps, sse, 1, 0, 0 +AVX_INSTR cmplesd, sse2, 1, 0, 0 +AVX_INSTR cmpless, sse, 1, 0, 0 +AVX_INSTR cmpltpd, sse2, 1, 0, 0 +AVX_INSTR cmpltps, sse, 1, 0, 0 +AVX_INSTR cmpltsd, sse2, 1, 0, 0 +AVX_INSTR cmpltss, sse, 1, 0, 0 +AVX_INSTR cmpneqpd, sse2, 1, 0, 1 +AVX_INSTR cmpneqps, sse, 1, 0, 1 +AVX_INSTR cmpneqsd, sse2, 1, 0, 0 +AVX_INSTR cmpneqss, sse, 1, 0, 0 +AVX_INSTR cmpnlepd, sse2, 1, 0, 0 +AVX_INSTR cmpnleps, sse, 1, 0, 0 +AVX_INSTR cmpnlesd, sse2, 1, 0, 0 +AVX_INSTR cmpnless, sse, 1, 0, 0 +AVX_INSTR cmpnltpd, sse2, 1, 0, 0 +AVX_INSTR cmpnltps, sse, 1, 0, 0 +AVX_INSTR cmpnltsd, sse2, 1, 0, 0 +AVX_INSTR cmpnltss, sse, 1, 0, 0 +AVX_INSTR cmpordpd, sse2 1, 0, 1 +AVX_INSTR cmpordps, sse 1, 0, 1 +AVX_INSTR cmpordsd, sse2 1, 0, 0 +AVX_INSTR cmpordss, sse 1, 0, 0 AVX_INSTR cmppd, sse2, 1, 1, 0 AVX_INSTR cmpps, sse, 1, 1, 0 AVX_INSTR cmpsd, sse2, 1, 1, 0 AVX_INSTR cmpss, sse, 1, 1, 0 +AVX_INSTR cmpunordpd, sse2, 1, 0, 1 +AVX_INSTR cmpunordps, sse, 1, 0, 1 +AVX_INSTR cmpunordsd, sse2, 1, 0, 0 +AVX_INSTR cmpunordss, sse, 1, 0, 0 AVX_INSTR comisd, sse2 AVX_INSTR comiss, sse AVX_INSTR cvtdq2pd, sse2 From 9e4b3675f226238ae132cada2bb82bcb00110aa6 Mon Sep 17 00:00:00 2001 From: Henrik Gramner Date: Tue, 15 Aug 2017 16:11:32 +0200 Subject: [PATCH 1682/2557] x86inc: Use .rdata instead of .rodata on Windows The standard section for read-only data on Windows is .rdata. Nasm will flag non-standard sections as executable by default which isn't ideal. --- libavutil/x86/x86inc.asm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavutil/x86/x86inc.asm b/libavutil/x86/x86inc.asm index 3b43dbc2e02f2..57cd4d80de545 100644 --- a/libavutil/x86/x86inc.asm +++ b/libavutil/x86/x86inc.asm @@ -90,6 +90,10 @@ SECTION .text %elifidn __OUTPUT_FORMAT__,coff SECTION .text + %elifidn __OUTPUT_FORMAT__,win32 + SECTION .rdata align=%1 + %elif WIN64 + SECTION .rdata align=%1 %else SECTION .rodata align=%1 %endif From 6b6edd121699a87c17bd5eca9e94cdd125088c0e Mon Sep 17 00:00:00 2001 From: Henrik Gramner Date: Wed, 16 Aug 2017 15:59:16 +0200 Subject: [PATCH 1683/2557] x86inc: Support creating global symbols from local labels On ELF platforms such symbols needs to be flagged as functions with the correct visibility to please certain linkers in some scenarios. --- libavutil/x86/x86inc.asm | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libavutil/x86/x86inc.asm b/libavutil/x86/x86inc.asm index 57cd4d80de545..de048f863d202 100644 --- a/libavutil/x86/x86inc.asm +++ b/libavutil/x86/x86inc.asm @@ -4,9 +4,9 @@ ;* Copyright (C) 2005-2017 x264 project ;* ;* Authors: Loren Merritt +;* Henrik Gramner ;* Anton Mitrofanov ;* Fiona Glaser -;* Henrik Gramner ;* ;* Permission to use, copy, modify, and/or distribute this software for any ;* purpose with or without fee is hereby granted, provided that the above @@ -743,6 +743,16 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %endif %endmacro +; Create a global symbol from a local label with the correct name mangling and type +%macro cglobal_label 1 + %if FORMAT_ELF + global current_function %+ %1:function hidden + %else + global current_function %+ %1 + %endif + %1: +%endmacro + %macro cextern 1 %xdefine %1 mangle(private_prefix %+ _ %+ %1) CAT_XDEFINE cglobaled_, %1, 1 From eb5f063e7ccc93062a70faac2402a533bb9669fd Mon Sep 17 00:00:00 2001 From: Henrik Gramner Date: Sat, 6 Jan 2018 17:47:42 +0100 Subject: [PATCH 1684/2557] x86inc: Correctly set mmreg variables --- libavutil/x86/x86inc.asm | 87 +++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 51 deletions(-) diff --git a/libavutil/x86/x86inc.asm b/libavutil/x86/x86inc.asm index de048f863d202..438863042f509 100644 --- a/libavutil/x86/x86inc.asm +++ b/libavutil/x86/x86inc.asm @@ -1,7 +1,7 @@ ;***************************************************************************** ;* x86inc.asm: x264asm abstraction layer ;***************************************************************************** -;* Copyright (C) 2005-2017 x264 project +;* Copyright (C) 2005-2018 x264 project ;* ;* Authors: Loren Merritt ;* Henrik Gramner @@ -892,6 +892,36 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %undef %1%2 %endmacro +%macro DEFINE_MMREGS 1 ; mmtype + %assign %%prev_mmregs 0 + %ifdef num_mmregs + %assign %%prev_mmregs num_mmregs + %endif + + %assign num_mmregs 8 + %if ARCH_X86_64 && mmsize >= 16 + %assign num_mmregs 16 + %if cpuflag(avx512) || mmsize == 64 + %assign num_mmregs 32 + %endif + %endif + + %assign %%i 0 + %rep num_mmregs + CAT_XDEFINE m, %%i, %1 %+ %%i + CAT_XDEFINE nn%1, %%i, %%i + %assign %%i %%i+1 + %endrep + %if %%prev_mmregs > num_mmregs + %rep %%prev_mmregs - num_mmregs + CAT_UNDEF m, %%i + CAT_UNDEF nn %+ mmtype, %%i + %assign %%i %%i+1 + %endrep + %endif + %xdefine mmtype %1 +%endmacro + ; Prefer registers 16-31 over 0-15 to avoid having to use vzeroupper %macro AVX512_MM_PERMUTATION 0-1 0 ; start_reg %if ARCH_X86_64 && cpuflag(avx512) @@ -908,23 +938,12 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %assign avx_enabled 0 %define RESET_MM_PERMUTATION INIT_MMX %1 %define mmsize 8 - %define num_mmregs 8 %define mova movq %define movu movq %define movh movd %define movnta movntq - %assign %%i 0 - %rep 8 - CAT_XDEFINE m, %%i, mm %+ %%i - CAT_XDEFINE nnmm, %%i, %%i - %assign %%i %%i+1 - %endrep - %rep 24 - CAT_UNDEF m, %%i - CAT_UNDEF nnmm, %%i - %assign %%i %%i+1 - %endrep INIT_CPUFLAGS %1 + DEFINE_MMREGS mm %endmacro %macro INIT_XMM 0-1+ @@ -936,22 +955,9 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %define movh movq %define movnta movntdq INIT_CPUFLAGS %1 - %define num_mmregs 8 - %if ARCH_X86_64 - %define num_mmregs 16 - %if cpuflag(avx512) - %define num_mmregs 32 - %endif - %endif - %assign %%i 0 - %rep num_mmregs - CAT_XDEFINE m, %%i, xmm %+ %%i - CAT_XDEFINE nnxmm, %%i, %%i - %assign %%i %%i+1 - %endrep + DEFINE_MMREGS xmm %if WIN64 - ; Swap callee-saved registers with volatile registers - AVX512_MM_PERMUTATION 6 + AVX512_MM_PERMUTATION 6 ; Swap callee-saved registers with volatile registers %endif %endmacro @@ -964,19 +970,7 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %undef movh %define movnta movntdq INIT_CPUFLAGS %1 - %define num_mmregs 8 - %if ARCH_X86_64 - %define num_mmregs 16 - %if cpuflag(avx512) - %define num_mmregs 32 - %endif - %endif - %assign %%i 0 - %rep num_mmregs - CAT_XDEFINE m, %%i, ymm %+ %%i - CAT_XDEFINE nnymm, %%i, %%i - %assign %%i %%i+1 - %endrep + DEFINE_MMREGS ymm AVX512_MM_PERMUTATION %endmacro @@ -984,21 +978,12 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %assign avx_enabled 1 %define RESET_MM_PERMUTATION INIT_ZMM %1 %define mmsize 64 - %define num_mmregs 8 - %if ARCH_X86_64 - %define num_mmregs 32 - %endif %define mova movdqa %define movu movdqu %undef movh %define movnta movntdq - %assign %%i 0 - %rep num_mmregs - CAT_XDEFINE m, %%i, zmm %+ %%i - CAT_XDEFINE nnzmm, %%i, %%i - %assign %%i %%i+1 - %endrep INIT_CPUFLAGS %1 + DEFINE_MMREGS zmm AVX512_MM_PERMUTATION %endmacro From 6f62b0bd4ff2bd4333d899b697f82643d14ff560 Mon Sep 17 00:00:00 2001 From: Henrik Gramner Date: Thu, 18 Jan 2018 23:20:33 +0100 Subject: [PATCH 1685/2557] x86inc: Drop cpuflags_slowctz --- libavutil/x86/x86inc.asm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavutil/x86/x86inc.asm b/libavutil/x86/x86inc.asm index 438863042f509..5044ee86f0d99 100644 --- a/libavutil/x86/x86inc.asm +++ b/libavutil/x86/x86inc.asm @@ -827,9 +827,8 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, %assign cpuflags_cache32 (1<<21) %assign cpuflags_cache64 (1<<22) -%assign cpuflags_slowctz (1<<23) -%assign cpuflags_aligned (1<<24) ; not a cpu feature, but a function variant -%assign cpuflags_atom (1<<25) +%assign cpuflags_aligned (1<<23) ; not a cpu feature, but a function variant +%assign cpuflags_atom (1<<24) ; Returns a boolean value expressing whether or not the specified cpuflag is enabled. %define cpuflag(x) (((((cpuflags & (cpuflags_ %+ x)) ^ (cpuflags_ %+ x)) - 1) >> 31) & 1) From ef5994e09d07ace62a672fcdc84761231288edad Mon Sep 17 00:00:00 2001 From: Nikolas Bowe Date: Fri, 19 Jan 2018 13:17:07 -0800 Subject: [PATCH 1686/2557] avformat/lrcdec: Fix memory leak in lrc_read_header() Signed-off-by: Michael Niedermayer --- libavformat/lrcdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/lrcdec.c b/libavformat/lrcdec.c index 12f74b22a08ef..f4e9a4efa9118 100644 --- a/libavformat/lrcdec.c +++ b/libavformat/lrcdec.c @@ -212,6 +212,7 @@ static int lrc_read_header(AVFormatContext *s) } ff_subtitles_queue_finalize(s, &lrc->q); ff_metadata_conv_ctx(s, NULL, ff_lrc_metadata_conv); + av_bprint_finalize(&line, NULL); return 0; } From 725353525e73bbe5b6b4d01528252675f2417a02 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 15 Jan 2018 19:03:48 +0100 Subject: [PATCH 1687/2557] avcodec/ulti: Check number of blocks at init Fixes: Timeout Fixes: 4832/clusterfuzz-testcase-4699096590843904 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/ulti.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/ulti.c b/libavcodec/ulti.c index e6f43749811cc..9e4c088b101c7 100644 --- a/libavcodec/ulti.c +++ b/libavcodec/ulti.c @@ -50,6 +50,8 @@ static av_cold int ulti_decode_init(AVCodecContext *avctx) s->width = avctx->width; s->height = avctx->height; s->blocks = (s->width / 8) * (s->height / 8); + if (s->blocks == 0) + return AVERROR_INVALIDDATA; avctx->pix_fmt = AV_PIX_FMT_YUV410P; s->ulti_codebook = ulti_codebook; From 2eecf3cf8eeae67697934df326e98df2149881e5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 15 Jan 2018 03:03:36 +0100 Subject: [PATCH 1688/2557] avcodec/snowdec: Fix integer overflow before htaps check Fixes: runtime error: signed integer overflow: -1094995529 * 2 cannot be represented in type 'int' Fixes: 4828/clusterfuzz-testcase-minimized-5100849937252352 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/snowdec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/snowdec.c b/libavcodec/snowdec.c index a9bdb8da5ef0f..0146a2a4c9ba0 100644 --- a/libavcodec/snowdec.c +++ b/libavcodec/snowdec.c @@ -363,9 +363,10 @@ static int decode_header(SnowContext *s){ int htaps, i, sum=0; Plane *p= &s->plane[plane_index]; p->diag_mc= get_rac(&s->c, s->header_state); - htaps= get_symbol(&s->c, s->header_state, 0)*2 + 2; - if((unsigned)htaps >= HTAPS_MAX || htaps==0) + htaps= get_symbol(&s->c, s->header_state, 0); + if((unsigned)htaps >= HTAPS_MAX/2 - 1) return AVERROR_INVALIDDATA; + htaps = htaps*2 + 2; p->htaps= htaps; for(i= htaps/2; i; i--){ p->hcoeff[i]= get_symbol(&s->c, s->header_state, 0) * (1-2*(i&1)); From 6c1c6c6c71fc776c6dd25d13861b036dad2cdc1b Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Thu, 11 Jan 2018 18:30:16 +0530 Subject: [PATCH 1689/2557] avfilter/drawtext - implement fix_bounds When enabled, text, including effects like shadow or box, will be completely bound within the video frame. Default value changed to false to keep continuity of behaviour. Fixes #6960. Signed-off-by: Kyle Swanson --- libavfilter/vf_drawtext.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index f6151443bbb5c..f97a741b5085d 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -238,7 +238,7 @@ static const AVOption drawtext_options[]= { {"rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS}, {"reload", "reload text file for each frame", OFFSET(reload), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, { "alpha", "apply alpha while rendering", OFFSET(a_expr), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS }, - {"fix_bounds", "check and fix text coords to avoid clipping", OFFSET(fix_bounds), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS}, + {"fix_bounds", "check and fix text coords to avoid clipping", OFFSET(fix_bounds), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, {"start_number", "start frame number for n/frame_num variable", OFFSET(start_number), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS}, #if CONFIG_LIBFRIBIDI @@ -1401,6 +1401,32 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame, box_w = FFMIN(width - 1 , max_text_line_w); box_h = FFMIN(height - 1, y + s->max_glyph_h); + if (s->fix_bounds) { + + /* calculate footprint of text effects */ + int boxoffset = s->draw_box ? FFMAX(s->boxborderw, 0) : 0; + int borderoffset = s->borderw ? FFMAX(s->borderw, 0) : 0; + + int offsetleft = FFMAX3(boxoffset, borderoffset, + (s->shadowx < 0 ? FFABS(s->shadowx) : 0)); + int offsettop = FFMAX3(boxoffset, borderoffset, + (s->shadowy < 0 ? FFABS(s->shadowy) : 0)); + + int offsetright = FFMAX3(boxoffset, borderoffset, + (s->shadowx > 0 ? s->shadowx : 0)); + int offsetbottom = FFMAX3(boxoffset, borderoffset, + (s->shadowy > 0 ? s->shadowy : 0)); + + + if (s->x - offsetleft < 0) s->x = offsetleft; + if (s->y - offsettop < 0) s->y = offsettop; + + if (s->x + box_w + offsetright > width) + s->x = FFMAX(width - box_w - offsetright, 0); + if (s->y + box_h + offsetbottom > height) + s->y = FFMAX(height - box_h - offsetbottom, 0); + } + /* draw box */ if (s->draw_box) ff_blend_rectangle(&s->dc, &boxcolor, From a0c624e299730c8c5800375c2f5f3c6c200053ff Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 9 Jan 2018 23:56:41 +0100 Subject: [PATCH 1690/2557] avcodec: v4l2_m2m: fix races around freeing data on close Refcount all of the context information. This also fixes a potential segmentation fault when accessing freed memory (buffer returned after the codec has been closed). Tested-by: Jorge Ramirez-Ortiz --- libavcodec/v4l2_buffers.c | 32 +++++++++----- libavcodec/v4l2_buffers.h | 6 +++ libavcodec/v4l2_m2m.c | 93 ++++++++++++++++++++++++--------------- libavcodec/v4l2_m2m.h | 35 ++++++++++++--- libavcodec/v4l2_m2m_dec.c | 22 +++++---- libavcodec/v4l2_m2m_enc.c | 22 +++++---- 6 files changed, 140 insertions(+), 70 deletions(-) diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index ba70c5d14bcc2..4e68f901b3869 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -207,20 +207,17 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused) V4L2Buffer* avbuf = opaque; V4L2m2mContext *s = buf_to_m2mctx(avbuf); - atomic_fetch_sub_explicit(&s->refcount, 1, memory_order_acq_rel); - if (s->reinit) { - if (!atomic_load(&s->refcount)) - sem_post(&s->refsync); - return; - } + if (atomic_fetch_sub(&avbuf->context_refcount, 1) == 1) { + atomic_fetch_sub_explicit(&s->refcount, 1, memory_order_acq_rel); - if (avbuf->context->streamon) { - ff_v4l2_buffer_enqueue(avbuf); - return; - } + if (s->reinit) { + if (!atomic_load(&s->refcount)) + sem_post(&s->refsync); + } else if (avbuf->context->streamon) + ff_v4l2_buffer_enqueue(avbuf); - if (!atomic_load(&s->refcount)) - ff_v4l2_m2m_codec_end(s->avctx); + av_buffer_unref(&avbuf->context_ref); + } } static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf) @@ -236,6 +233,17 @@ static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf) if (!*buf) return AVERROR(ENOMEM); + if (in->context_ref) + atomic_fetch_add(&in->context_refcount, 1); + else { + in->context_ref = av_buffer_ref(s->self_ref); + if (!in->context_ref) { + av_buffer_unref(buf); + return AVERROR(ENOMEM); + } + in->context_refcount = 1; + } + in->status = V4L2BUF_RET_USER; atomic_fetch_add_explicit(&s->refcount, 1, memory_order_relaxed); diff --git a/libavcodec/v4l2_buffers.h b/libavcodec/v4l2_buffers.h index e28a4a650d763..dc5cc9e26717b 100644 --- a/libavcodec/v4l2_buffers.h +++ b/libavcodec/v4l2_buffers.h @@ -24,6 +24,7 @@ #ifndef AVCODEC_V4L2_BUFFERS_H #define AVCODEC_V4L2_BUFFERS_H +#include #include #include "avcodec.h" @@ -41,6 +42,11 @@ typedef struct V4L2Buffer { /* each buffer needs to have a reference to its context */ struct V4L2Context *context; + /* This object is refcounted per-plane, so we need to keep track + * of how many context-refs we are holding. */ + AVBufferRef *context_ref; + atomic_uint context_refcount; + /* keep track of the mmap address and mmap length */ struct V4L2Plane_info { int bytesperline; diff --git a/libavcodec/v4l2_m2m.c b/libavcodec/v4l2_m2m.c index 1d7a8521d80fd..fd989ce60156b 100644 --- a/libavcodec/v4l2_m2m.c +++ b/libavcodec/v4l2_m2m.c @@ -222,8 +222,6 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mContext* s) } /* 5. complete reinit */ - sem_destroy(&s->refsync); - sem_init(&s->refsync, 0, 0); s->draining = 0; s->reinit = 0; @@ -241,24 +239,26 @@ int ff_v4l2_m2m_codec_full_reinit(V4L2m2mContext *s) if (atomic_load(&s->refcount)) while(sem_wait(&s->refsync) == -1 && errno == EINTR); - /* close the driver */ - ff_v4l2_m2m_codec_end(s->avctx); + ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); + if (ret) { + av_log(s->avctx, AV_LOG_ERROR, "output VIDIOC_STREAMOFF\n"); + goto error; + } + + ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); + if (ret) { + av_log(s->avctx, AV_LOG_ERROR, "capture VIDIOC_STREAMOFF\n"); + goto error; + } + + /* release and unmmap the buffers */ + ff_v4l2_context_release(&s->output); + ff_v4l2_context_release(&s->capture); /* start again now that we know the stream dimensions */ s->draining = 0; s->reinit = 0; - s->fd = open(s->devname, O_RDWR | O_NONBLOCK, 0); - if (s->fd < 0) - return AVERROR(errno); - - ret = v4l2_prepare_contexts(s); - if (ret < 0) - goto error; - - /* if a full re-init was requested - probe didn't run - we need to populate - * the format for each context - */ ret = ff_v4l2_context_get_format(&s->output); if (ret) { av_log(log_ctx, AV_LOG_DEBUG, "v4l2 output format not supported\n"); @@ -301,19 +301,25 @@ int ff_v4l2_m2m_codec_full_reinit(V4L2m2mContext *s) return 0; error: - if (close(s->fd) < 0) { - ret = AVERROR(errno); - av_log(log_ctx, AV_LOG_ERROR, "error closing %s (%s)\n", - s->devname, av_err2str(AVERROR(errno))); - } - s->fd = -1; - return ret; } +static void v4l2_m2m_destroy_context(void *opaque, uint8_t *context) +{ + V4L2m2mContext *s = (V4L2m2mContext*)context; + + ff_v4l2_context_release(&s->capture); + sem_destroy(&s->refsync); + + close(s->fd); + + av_free(s); +} + int ff_v4l2_m2m_codec_end(AVCodecContext *avctx) { - V4L2m2mContext* s = avctx->priv_data; + V4L2m2mPriv *priv = avctx->priv_data; + V4L2m2mContext* s = priv->context; int ret; ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); @@ -326,17 +332,8 @@ int ff_v4l2_m2m_codec_end(AVCodecContext *avctx) ff_v4l2_context_release(&s->output); - if (atomic_load(&s->refcount)) - av_log(avctx, AV_LOG_ERROR, "ff_v4l2m2m_codec_end leaving pending buffers\n"); - - ff_v4l2_context_release(&s->capture); - sem_destroy(&s->refsync); - - /* release the hardware */ - if (close(s->fd) < 0 ) - av_log(avctx, AV_LOG_ERROR, "failure closing %s (%s)\n", s->devname, av_err2str(AVERROR(errno))); - - s->fd = -1; + s->self_ref = NULL; + av_buffer_unref(&priv->context_ref); return 0; } @@ -348,7 +345,7 @@ int ff_v4l2_m2m_codec_init(AVCodecContext *avctx) char node[PATH_MAX]; DIR *dirp; - V4L2m2mContext *s = avctx->priv_data; + V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; s->avctx = avctx; dirp = opendir("/dev"); @@ -381,3 +378,29 @@ int ff_v4l2_m2m_codec_init(AVCodecContext *avctx) return v4l2_configure_contexts(s); } + +int ff_v4l2_m2m_create_context(AVCodecContext *avctx, V4L2m2mContext **s) +{ + V4L2m2mPriv *priv = avctx->priv_data; + + *s = av_mallocz(sizeof(V4L2m2mContext)); + if (!*s) + return AVERROR(ENOMEM); + + priv->context_ref = av_buffer_create((uint8_t *) *s, sizeof(V4L2m2mContext), + &v4l2_m2m_destroy_context, NULL, 0); + if (!priv->context_ref) { + av_free(s); + return AVERROR(ENOMEM); + } + + /* assign the context */ + priv->context = *s; + + /* populate it */ + priv->context->capture.num_buffers = priv->num_capture_buffers; + priv->context->output.num_buffers = priv->num_output_buffers; + priv->context->self_ref = priv->context_ref; + + return 0; +} diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h index afa3987c46635..452bf0d9bc258 100644 --- a/libavcodec/v4l2_m2m.h +++ b/libavcodec/v4l2_m2m.h @@ -38,11 +38,9 @@ #define V4L_M2M_DEFAULT_OPTS \ { "num_output_buffers", "Number of buffers in the output context",\ - OFFSET(output.num_buffers), AV_OPT_TYPE_INT, { .i64 = 16 }, 6, INT_MAX, FLAGS } + OFFSET(num_output_buffers), AV_OPT_TYPE_INT, { .i64 = 16 }, 6, INT_MAX, FLAGS } -typedef struct V4L2m2mContext -{ - AVClass *class; +typedef struct V4L2m2mContext { char devname[PATH_MAX]; int fd; @@ -50,18 +48,41 @@ typedef struct V4L2m2mContext V4L2Context capture; V4L2Context output; - /* refcount of buffers held by the user */ - atomic_uint refcount; - /* dynamic stream reconfig */ AVCodecContext *avctx; sem_t refsync; + atomic_uint refcount; int reinit; /* null frame/packet received */ int draining; + + /* Reference to self; only valid while codec is active. */ + AVBufferRef *self_ref; } V4L2m2mContext; +typedef struct V4L2m2mPriv +{ + AVClass *class; + + V4L2m2mContext *context; + AVBufferRef *context_ref; + + int num_output_buffers; + int num_capture_buffers; +} V4L2m2mPriv; + +/** + * Allocate a new context and references for a V4L2 M2M instance. + * + * @param[in] ctx The AVCodecContext instantiated by the encoder/decoder. + * @param[out] ctx The V4L2m2mContext. + * + * @returns 0 in success, a negative error code otherwise. + */ +int ff_v4l2_m2m_create_context(AVCodecContext *avctx, V4L2m2mContext **s); + + /** * Probes the video nodes looking for the required codec capabilities. * diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index 8308613978ded..bca45be148461 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -35,7 +35,7 @@ static int v4l2_try_start(AVCodecContext *avctx) { - V4L2m2mContext *s = avctx->priv_data; + V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; V4L2Context *const capture = &s->capture; V4L2Context *const output = &s->output; struct v4l2_selection selection; @@ -127,7 +127,7 @@ static int v4l2_prepare_decoder(V4L2m2mContext *s) static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) { - V4L2m2mContext *s = avctx->priv_data; + V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; V4L2Context *const capture = &s->capture; V4L2Context *const output = &s->output; AVPacket avpkt = {0}; @@ -159,11 +159,17 @@ static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) static av_cold int v4l2_decode_init(AVCodecContext *avctx) { - V4L2m2mContext *s = avctx->priv_data; - V4L2Context *capture = &s->capture; - V4L2Context *output = &s->output; + V4L2Context *capture, *output; + V4L2m2mContext *s; int ret; + ret = ff_v4l2_m2m_create_context(avctx, &s); + if (ret < 0) + return ret; + + capture = &s->capture; + output = &s->output; + /* if these dimensions are invalid (ie, 0 or too small) an event will be raised * by the v4l2 driver; this event will trigger a full pipeline reconfig and * the proper values will be retrieved from the kernel driver. @@ -186,13 +192,13 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) return v4l2_prepare_decoder(s); } -#define OFFSET(x) offsetof(V4L2m2mContext, x) +#define OFFSET(x) offsetof(V4L2m2mPriv, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { V4L_M2M_DEFAULT_OPTS, { "num_capture_buffers", "Number of buffers in the capture context", - OFFSET(capture.num_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 20, INT_MAX, FLAGS }, + OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 20, INT_MAX, FLAGS }, { NULL}, }; @@ -209,7 +215,7 @@ AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \ .long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " decoder wrapper"),\ .type = AVMEDIA_TYPE_VIDEO,\ .id = CODEC ,\ - .priv_data_size = sizeof(V4L2m2mContext),\ + .priv_data_size = sizeof(V4L2m2mPriv),\ .priv_class = &v4l2_m2m_ ## NAME ## _dec_class,\ .init = v4l2_decode_init,\ .receive_frame = v4l2_receive_frame,\ diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c index 7e88f4d2e6f67..4c9ea1fd92b72 100644 --- a/libavcodec/v4l2_m2m_enc.c +++ b/libavcodec/v4l2_m2m_enc.c @@ -242,7 +242,7 @@ static int v4l2_prepare_encoder(V4L2m2mContext *s) static int v4l2_send_frame(AVCodecContext *avctx, const AVFrame *frame) { - V4L2m2mContext *s = avctx->priv_data; + V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; V4L2Context *const output = &s->output; return ff_v4l2_context_enqueue_frame(output, frame); @@ -250,7 +250,7 @@ static int v4l2_send_frame(AVCodecContext *avctx, const AVFrame *frame) static int v4l2_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) { - V4L2m2mContext *s = avctx->priv_data; + V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; V4L2Context *const capture = &s->capture; V4L2Context *const output = &s->output; int ret; @@ -280,11 +280,17 @@ static int v4l2_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) static av_cold int v4l2_encode_init(AVCodecContext *avctx) { - V4L2m2mContext *s = avctx->priv_data; - V4L2Context *capture = &s->capture; - V4L2Context *output = &s->output; + V4L2Context *capture, *output; + V4L2m2mContext *s; int ret; + ret = ff_v4l2_m2m_create_context(avctx, &s); + if (ret < 0) + return ret; + + capture = &s->capture; + output = &s->output; + /* common settings output/capture */ output->height = capture->height = avctx->height; output->width = capture->width = avctx->width; @@ -306,13 +312,13 @@ static av_cold int v4l2_encode_init(AVCodecContext *avctx) return v4l2_prepare_encoder(s); } -#define OFFSET(x) offsetof(V4L2m2mContext, x) +#define OFFSET(x) offsetof(V4L2m2mPriv, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { V4L_M2M_DEFAULT_OPTS, { "num_capture_buffers", "Number of buffers in the capture context", - OFFSET(capture.num_buffers), AV_OPT_TYPE_INT, {.i64 = 4 }, 4, INT_MAX, FLAGS }, + OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 4 }, 4, INT_MAX, FLAGS }, { NULL }, }; @@ -329,7 +335,7 @@ AVCodec ff_ ## NAME ## _v4l2m2m_encoder = { \ .long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " encoder wrapper"),\ .type = AVMEDIA_TYPE_VIDEO,\ .id = CODEC ,\ - .priv_data_size = sizeof(V4L2m2mContext),\ + .priv_data_size = sizeof(V4L2m2mPriv),\ .priv_class = &v4l2_m2m_ ## NAME ##_enc_class,\ .init = v4l2_encode_init,\ .send_frame = v4l2_send_frame,\ From 5d5de3eba4c7890c2e8077f5b4ae569671d11cf8 Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Tue, 9 Jan 2018 23:56:42 +0100 Subject: [PATCH 1691/2557] avcodec: v4l2_m2m: remove unnecessary timeout. Qualcomm's db410c/db820 Venus driver currently present in mainline kernel has a bug which mishandles the CMD_STOP requests causing the decoder to block while draining [1]. This patch removes the workaround that was used to prevent that situation. Encoding/Decoding tested on db820c. [1] on CMD_STOP, the driver is flushing all buffers and never raising IPIPE which ends up in blocking on poll. --- libavcodec/v4l2_buffers.c | 10 +++++-- libavcodec/v4l2_context.c | 61 +++++++++++++++++++++++---------------- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index 4e68f901b3869..8e4d4d1c9fa72 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -213,8 +213,14 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused) if (s->reinit) { if (!atomic_load(&s->refcount)) sem_post(&s->refsync); - } else if (avbuf->context->streamon) - ff_v4l2_buffer_enqueue(avbuf); + } else { + if (s->draining) { + /* no need to queue more buffers to the driver */ + avbuf->status = V4L2BUF_AVAILABLE; + } + else if (avbuf->context->streamon) + ff_v4l2_buffer_enqueue(avbuf); + } av_buffer_unref(&avbuf->context_ref); } diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index 4c169928fab9e..dde97d0d1fd5e 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -217,6 +217,7 @@ static int v4l2_stop_decode(V4L2Context *ctx) { struct v4l2_decoder_cmd cmd = { .cmd = V4L2_DEC_CMD_STOP, + .flags = 0, }; int ret; @@ -234,6 +235,7 @@ static int v4l2_stop_encode(V4L2Context *ctx) { struct v4l2_encoder_cmd cmd = { .cmd = V4L2_ENC_CMD_STOP, + .flags = 0, }; int ret; @@ -256,10 +258,26 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout) .events = POLLIN | POLLRDNORM | POLLPRI | POLLOUT | POLLWRNORM, /* default blocking capture */ .fd = ctx_to_m2mctx(ctx)->fd, }; - int ret; + int i, ret; + + /* if we are draining and there are no more capture buffers queued in the driver we are done */ + if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) { + for (i = 0; i < ctx->num_buffers; i++) { + if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER) + goto start; + } + ctx->done = 1; + return NULL; + } +start: if (V4L2_TYPE_IS_OUTPUT(ctx->type)) pfd.events = POLLOUT | POLLWRNORM; + else { + /* no need to listen to requests for more input while draining */ + if (ctx_to_m2mctx(ctx)->draining) + pfd.events = POLLIN | POLLRDNORM | POLLPRI; + } for (;;) { ret = poll(&pfd, 1, timeout); @@ -267,11 +285,6 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout) break; if (errno == EINTR) continue; - - /* timeout is being used to indicate last valid bufer when draining */ - if (ctx_to_m2mctx(ctx)->draining) - ctx->done = 1; - return NULL; } @@ -286,7 +299,7 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout) ret = v4l2_handle_event(ctx); if (ret < 0) { /* if re-init failed, abort */ - ctx->done = EINVAL; + ctx->done = 1; return NULL; } if (ret) { @@ -325,23 +338,25 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout) ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DQBUF, &buf); if (ret) { if (errno != EAGAIN) { - ctx->done = errno; + ctx->done = 1; if (errno != EPIPE) av_log(logger(ctx), AV_LOG_DEBUG, "%s VIDIOC_DQBUF, errno (%s)\n", ctx->name, av_err2str(AVERROR(errno))); } - } else { - avbuf = &ctx->buffers[buf.index]; - avbuf->status = V4L2BUF_AVAILABLE; - avbuf->buf = buf; - if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { - memcpy(avbuf->planes, planes, sizeof(planes)); - avbuf->buf.m.planes = avbuf->planes; - } + return NULL; } + + avbuf = &ctx->buffers[buf.index]; + avbuf->status = V4L2BUF_AVAILABLE; + avbuf->buf = buf; + if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { + memcpy(avbuf->planes, planes, sizeof(planes)); + avbuf->buf.m.planes = avbuf->planes; + } + return avbuf; } - return avbuf; + return NULL; } static V4L2Buffer* v4l2_getfree_v4l2buf(V4L2Context *ctx) @@ -552,14 +567,12 @@ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame) { V4L2Buffer* avbuf = NULL; - /* if we are draining, we are no longer inputing data, therefore enable a - * timeout so we can dequeue and flag the last valid buffer. - * + /* * blocks until: * 1. decoded frame available * 2. an input buffer is ready to be dequeued */ - avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? 200 : -1); + avbuf = v4l2_dequeue_v4l2buf(ctx, -1); if (!avbuf) { if (ctx->done) return AVERROR_EOF; @@ -574,14 +587,12 @@ int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt) { V4L2Buffer* avbuf = NULL; - /* if we are draining, we are no longer inputing data, therefore enable a - * timeout so we can dequeue and flag the last valid buffer. - * + /* * blocks until: * 1. encoded packet available * 2. an input buffer ready to be dequeued */ - avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? 200 : -1); + avbuf = v4l2_dequeue_v4l2buf(ctx, -1); if (!avbuf) { if (ctx->done) return AVERROR_EOF; From 0b9b7f0b46a80b848b19ebbb624cc7dc06bd33b7 Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Tue, 9 Jan 2018 23:56:43 +0100 Subject: [PATCH 1692/2557] avcodec: v4l2_m2m: context: fix raising warning on POLLERR During the initialization stage, the codec attempts to get free buffers from the driver before any have been queued (this is to keep the code simple and generic) When the kernel driver detects this situation, it returns POLLERR in revents and ffmpeg therefore raises a warning. This commit disables the warning since no buffers were queued to the driver yet. Signed-off-by: Jorge Ramirez-Ortiz --- libavcodec/v4l2_context.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index dde97d0d1fd5e..e0431b1b3e359 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -290,7 +290,17 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout) /* 0. handle errors */ if (pfd.revents & POLLERR) { - av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name); + /* if we are trying to get free buffers but none have been queued yet + no need to raise a warning */ + if (timeout == 0) { + for (i = 0; i < ctx->num_buffers; i++) { + if (ctx->buffers[i].status != V4L2BUF_AVAILABLE) + av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name); + } + } + else + av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name); + return NULL; } From 251f0bcb7be9e42af91c1beb346d752185bbcbb9 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sat, 20 Jan 2018 16:07:25 +0100 Subject: [PATCH 1693/2557] lavf/rawdec: Also probe the last byte of mjpeg streams. Fixes ticket #6957. --- libavformat/rawdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/rawdec.c b/libavformat/rawdec.c index e926549a60332..b38a4b5e5d4ba 100644 --- a/libavformat/rawdec.c +++ b/libavformat/rawdec.c @@ -130,7 +130,7 @@ static int mjpeg_probe(AVProbeData *p) int nb_invalid = 0; int nb_frames = 0; - for (i=0; ibuf_size-2; i++) { + for (i = 0; i < p->buf_size - 1; i++) { int c; if (p->buf[i] != 0xFF) continue; From 9462b2b8205397ea5972b2365c2e8db6872ef3e9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 20 Jan 2018 16:54:15 -0300 Subject: [PATCH 1694/2557] avcodec/hevc_ps: add a function to uninitialize parameter set buffers Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavcodec/hevc_ps.c | 16 ++++++++++++++++ libavcodec/hevc_ps.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index a4f7ed60f7ec5..4787312cfaa0e 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1704,6 +1704,22 @@ int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, return ret; } +void ff_hevc_ps_uninit(HEVCParamSets *ps) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(ps->vps_list); i++) + av_buffer_unref(&ps->vps_list[i]); + for (i = 0; i < FF_ARRAY_ELEMS(ps->sps_list); i++) + av_buffer_unref(&ps->sps_list[i]); + for (i = 0; i < FF_ARRAY_ELEMS(ps->pps_list); i++) + av_buffer_unref(&ps->pps_list[i]); + + ps->sps = NULL; + ps->pps = NULL; + ps->vps = NULL; +} + int ff_hevc_compute_poc(const HEVCSPS *sps, int pocTid0, int poc_lsb, int nal_unit_type) { int max_poc_lsb = 1 << sps->log2_max_poc_lsb; diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 477ee4299a6db..9873754389cc5 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -421,6 +421,8 @@ int ff_hevc_decode_nal_sps(GetBitContext *gb, AVCodecContext *avctx, int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, HEVCParamSets *ps); +void ff_hevc_ps_uninit(HEVCParamSets *ps); + int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx, ShortTermRPS *rps, const HEVCSPS *sps, int is_slice_header); From 1f0cf1b2f4ef6304c343d53508193ac4b5d9c1d2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 20 Jan 2018 16:54:51 -0300 Subject: [PATCH 1695/2557] avcodec/hevcdec: use ff_hevc_uninit_parameter_sets() Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavcodec/hevcdec.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 4bfae8c12b190..8f1c1f19534cd 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -3277,15 +3277,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) av_frame_free(&s->DPB[i].frame); } - for (i = 0; i < FF_ARRAY_ELEMS(s->ps.vps_list); i++) - av_buffer_unref(&s->ps.vps_list[i]); - for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) - av_buffer_unref(&s->ps.sps_list[i]); - for (i = 0; i < FF_ARRAY_ELEMS(s->ps.pps_list); i++) - av_buffer_unref(&s->ps.pps_list[i]); - s->ps.sps = NULL; - s->ps.pps = NULL; - s->ps.vps = NULL; + ff_hevc_ps_uninit(&s->ps); av_freep(&s->sh.entry_point_offset); av_freep(&s->sh.offset); From 2159d4bbc3e69d04242e87bac13ebea8b942d94d Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 20 Jan 2018 16:55:00 -0300 Subject: [PATCH 1696/2557] avcodec/hevc_parser: use ff_hevc_uninit_parameter_sets() Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavcodec/hevc_parser.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c index ff7e8a49d66d0..88d3d9a22f30f 100644 --- a/libavcodec/hevc_parser.c +++ b/libavcodec/hevc_parser.c @@ -359,17 +359,8 @@ static int hevc_split(AVCodecContext *avctx, const uint8_t *buf, int buf_size) static void hevc_parser_close(AVCodecParserContext *s) { HEVCParserContext *ctx = s->priv_data; - int i; - - for (i = 0; i < FF_ARRAY_ELEMS(ctx->ps.vps_list); i++) - av_buffer_unref(&ctx->ps.vps_list[i]); - for (i = 0; i < FF_ARRAY_ELEMS(ctx->ps.sps_list); i++) - av_buffer_unref(&ctx->ps.sps_list[i]); - for (i = 0; i < FF_ARRAY_ELEMS(ctx->ps.pps_list); i++) - av_buffer_unref(&ctx->ps.pps_list[i]); - - ctx->ps.sps = NULL; + ff_hevc_ps_uninit(&ctx->ps); ff_h2645_packet_uninit(&ctx->pkt); ff_hevc_reset_sei(&ctx->sei); From 777d6c677b1d70e9267c5e31c2c2473fa064076b Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 21 Jan 2018 13:14:51 +0800 Subject: [PATCH 1697/2557] dashdec: Make use of frame rate specified in Representation If the manifest provides this, setting r_frame_rate avoids warnings regarding frame rate estimation. --- libavformat/dashdec.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 2492f1d2660ed..a080bf35847b7 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -86,6 +86,7 @@ struct representation { enum AVMediaType type; char id[20]; int bandwidth; + AVRational framerate; AVStream *assoc_stream; /* demuxer stream associated with this representation */ int n_fragments; @@ -674,6 +675,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr representation_node = node; char *rep_id_val = xmlGetProp(representation_node, "id"); char *rep_bandwidth_val = xmlGetProp(representation_node, "bandwidth"); + char *rep_framerate_val = xmlGetProp(representation_node, "frameRate"); enum AVMediaType type = AVMEDIA_TYPE_UNKNOWN; // try get information from representation @@ -843,6 +845,13 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, rep->fragment_timescale = 1; rep->bandwidth = rep_bandwidth_val ? atoi(rep_bandwidth_val) : 0; strncpy(rep->id, rep_id_val ? rep_id_val : "", sizeof(rep->id)); + rep->framerate = av_make_q(0, 0); + if (type == AVMEDIA_TYPE_VIDEO && rep_framerate_val) { + ret = av_parse_video_rate(&rep->framerate, rep_framerate_val); + if (ret < 0) + av_log(s, AV_LOG_VERBOSE, "Ignoring invalid frame rate '%s'\n", rep_framerate_val); + } + if (type == AVMEDIA_TYPE_VIDEO) { rep->rep_idx = video_rep_idx; dynarray_add(&c->videos, &c->n_videos, rep); @@ -861,6 +870,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlFree(rep_id_val); if (rep_bandwidth_val) xmlFree(rep_bandwidth_val); + if (rep_framerate_val) + xmlFree(rep_framerate_val); return ret; } @@ -1571,7 +1582,7 @@ static int reopen_demux_for_component(AVFormatContext *s, struct representation AVInputFormat *in_fmt = NULL; AVDictionary *in_fmt_opts = NULL; uint8_t *avio_ctx_buffer = NULL; - int ret = 0; + int ret = 0, i; if (pls->ctx) { close_demux_for_component(pls); @@ -1618,6 +1629,13 @@ static int reopen_demux_for_component(AVFormatContext *s, struct representation if (ret < 0) goto fail; if (pls->n_fragments) { +#if FF_API_R_FRAME_RATE + if (pls->framerate.den) { + for (i = 0; i < pls->ctx->nb_streams; i++) + pls->ctx->streams[i]->r_frame_rate = pls->framerate; + } +#endif + ret = avformat_find_stream_info(pls->ctx, NULL); if (ret < 0) goto fail; From 2472dbc7a770a908a2f511ec337ec392ca3e3afa Mon Sep 17 00:00:00 2001 From: Brendan McGrath Date: Sun, 21 Jan 2018 13:16:42 +0800 Subject: [PATCH 1698/2557] avformat/hlsenc: Check that data is set If codecpar->extradata is not set (for example, when the stream goes through the 'tee' muxer), then a segfault occurs. This patch ensures the data variable is not null before attempting to access it Before the var_stream_map option was available - I was using the tee muxer to create each resolution as an individual stream. When running this configuration after the most recent hlsenc change I hit a segfault The most simple command which recreates the segfault is: ffmpeg -i in.ts -map 0:a -map 0:v -c:a aac -c:v h264 -f tee [select=\'a,v\':f=hls]tv_hls_hd.m3u8 Signed-off-by: Brendan McGrath --- libavformat/hlsenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 8ad906a480cd4..42e437f5d1978 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -308,7 +308,7 @@ static void write_codec_attr(AVStream *st, VariantStream *vs) { if (st->codecpar->codec_id == AV_CODEC_ID_H264) { uint8_t *data = st->codecpar->extradata; - if ((data[0] | data[1] | data[2]) == 0 && data[3] == 1 && (data[4] & 0x1F) == 7) { + if (data && (data[0] | data[1] | data[2]) == 0 && data[3] == 1 && (data[4] & 0x1F) == 7) { snprintf(attr, sizeof(attr), "avc1.%02x%02x%02x", data[5], data[6], data[7]); } else { From 1f48c5c0671bb4f39c9dc3ec44c727f1680547b3 Mon Sep 17 00:00:00 2001 From: Brendan McGrath Date: Sun, 21 Jan 2018 13:20:02 +0800 Subject: [PATCH 1699/2557] dashdec: Only free url string if being reused If no representation bandwidth value is set, the url value returned by get_content_url is corrupt (as it has been freed). This change ensures the url string is not freed unless it is about to be reused Changes since v1: 1 removed the unneeded 'if' statement (as pointed out by Michael Niedermayer 2 added comment to make it clear why the av_free was required Signed-off-by: Brendan McGrath --- libavformat/dashdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index a080bf35847b7..7d960670b96fb 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -483,9 +483,10 @@ static char *get_content_url(xmlNodePtr *baseurl_nodes, return NULL; } av_strlcpy(tmp_str, url, sizeof(tmp_str)); - av_free(url); } if (rep_bandwidth_val && tmp_str[0] != '\0') { + // free any previously assigned url before reassigning + av_free(url); url = av_strireplace(tmp_str, "$Bandwidth$", (const char*)rep_bandwidth_val); if (!url) { return NULL; From 8db4ef3e6d9377d131e7051dcebf41fa6cc9ac81 Mon Sep 17 00:00:00 2001 From: Colin NG Date: Sun, 21 Jan 2018 13:27:48 +0800 Subject: [PATCH 1700/2557] avformat/dashdec.c: Download dash content with byte range info --- libavformat/dashdec.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 7d960670b96fb..6bf0fcfaff5e0 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -552,6 +552,23 @@ static enum AVMediaType get_content_type(xmlNodePtr node) return type; } +static struct fragment * get_Fragment(char *range) +{ + struct fragment * seg = av_mallocz(sizeof(struct fragment)); + + if (!seg) + return NULL; + + seg->size = -1; + if (range) { + char *str_end_offset; + char *str_offset = av_strtok(range, "-", &str_end_offset); + seg->url_offset = strtoll(str_offset, NULL, 10); + seg->size = strtoll(str_end_offset, NULL, 10) - seg->url_offset; + } + return seg; +} + static int parse_manifest_segmenturlnode(AVFormatContext *s, struct representation *rep, xmlNodePtr fragmenturl_node, xmlNodePtr *baseurl_nodes, @@ -560,13 +577,16 @@ static int parse_manifest_segmenturlnode(AVFormatContext *s, struct representati { char *initialization_val = NULL; char *media_val = NULL; + char *range_val = NULL; if (!av_strcasecmp(fragmenturl_node->name, (const char *)"Initialization")) { initialization_val = xmlGetProp(fragmenturl_node, "sourceURL"); - if (initialization_val) { - rep->init_section = av_mallocz(sizeof(struct fragment)); + range_val = xmlGetProp(fragmenturl_node, "range"); + if (initialization_val || range_val) { + rep->init_section = get_Fragment(range_val); if (!rep->init_section) { xmlFree(initialization_val); + xmlFree(range_val); return AVERROR(ENOMEM); } rep->init_section->url = get_content_url(baseurl_nodes, 4, @@ -576,17 +596,20 @@ static int parse_manifest_segmenturlnode(AVFormatContext *s, struct representati if (!rep->init_section->url) { av_free(rep->init_section); xmlFree(initialization_val); + xmlFree(range_val); return AVERROR(ENOMEM); } - rep->init_section->size = -1; xmlFree(initialization_val); + xmlFree(range_val); } } else if (!av_strcasecmp(fragmenturl_node->name, (const char *)"SegmentURL")) { media_val = xmlGetProp(fragmenturl_node, "media"); - if (media_val) { - struct fragment *seg = av_mallocz(sizeof(struct fragment)); + range_val = xmlGetProp(fragmenturl_node, "mediaRange"); + if (media_val || range_val) { + struct fragment *seg = get_Fragment(range_val); if (!seg) { xmlFree(media_val); + xmlFree(range_val); return AVERROR(ENOMEM); } seg->url = get_content_url(baseurl_nodes, 4, @@ -596,11 +619,12 @@ static int parse_manifest_segmenturlnode(AVFormatContext *s, struct representati if (!seg->url) { av_free(seg); xmlFree(media_val); + xmlFree(range_val); return AVERROR(ENOMEM); } - seg->size = -1; dynarray_add(&rep->fragments, &rep->n_fragments, seg); xmlFree(media_val); + xmlFree(range_val); } } From 7a63da891023767824af75ff1c9fe681c156ac19 Mon Sep 17 00:00:00 2001 From: Colin NG Date: Sun, 21 Jan 2018 13:35:30 +0800 Subject: [PATCH 1701/2557] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) 1 Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is available, the path of mpd file will be set as the baseURL. 2 Remove checking for newly established connection. 3 Establish the communication protocol in each connection rather than applying one protocol to all connection. --- libavformat/dashdec.c | 128 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 115 insertions(+), 13 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 6bf0fcfaff5e0..3aac89c4ab951 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -150,6 +150,11 @@ typedef struct DASHContext { AVDictionary *avio_opts; } DASHContext; +static int ishttp(char *url) { + const char *proto_name = avio_find_protocol_name(url); + return av_strstart(proto_name, "http", NULL); +} + static uint64_t get_current_time_in_sec(void) { return av_gettime() / 1000000; @@ -421,7 +426,8 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) return AVERROR_INVALIDDATA; - ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); + av_freep(pb); + ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); if (ret >= 0) { // update cookies on http response with setcookies. char *new_cookies = NULL; @@ -566,6 +572,7 @@ static struct fragment * get_Fragment(char *range) seg->url_offset = strtoll(str_offset, NULL, 10); seg->size = strtoll(str_end_offset, NULL, 10) - seg->url_offset; } + return seg; } @@ -593,6 +600,7 @@ static int parse_manifest_segmenturlnode(AVFormatContext *s, struct representati rep_id_val, rep_bandwidth_val, initialization_val); + if (!rep->init_section->url) { av_free(rep->init_section); xmlFree(initialization_val); @@ -667,6 +675,105 @@ static int parse_manifest_segmenttimeline(AVFormatContext *s, struct representat return 0; } +static int resolve_content_path(AVFormatContext *s, const char *url, xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { + + char *tmp_str = NULL; + char *path = NULL; + char *mpdName = NULL; + xmlNodePtr node = NULL; + char *baseurl = NULL; + char *root_url = NULL; + char *text = NULL; + + int isRootHttp = 0; + char token ='/'; + int start = 0; + int rootId = 0; + int updated = 0; + int size = 0; + int i; + int max_url_size = strlen(url); + + for (i = n_baseurl_nodes-1; i >= 0 ; i--) { + text = xmlNodeGetContent(baseurl_nodes[i]); + if (!text) + continue; + max_url_size += strlen(text); + if (ishttp(text)) { + xmlFree(text); + break; + } + xmlFree(text); + } + + text = av_mallocz(max_url_size); + if (!text) { + updated = AVERROR(ENOMEM); + goto end; + } + av_strlcpy(text, url, strlen(url)+1); + while (mpdName = av_strtok(text, "/", &text)) { + size = strlen(mpdName); + } + + path = av_mallocz(max_url_size); + tmp_str = av_mallocz(max_url_size); + if (!tmp_str || !path) { + updated = AVERROR(ENOMEM); + goto end; + } + + av_strlcpy (path, url, strlen(url) - size + 1); + for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId --) { + if (!(node = baseurl_nodes[rootId])) { + continue; + } + if (ishttp(xmlNodeGetContent(node))) { + break; + } + } + + node = baseurl_nodes[rootId]; + baseurl = xmlNodeGetContent(node); + root_url = (av_strcasecmp(baseurl, "")) ? baseurl : path; + if (node) { + xmlNodeSetContent(node, root_url); + updated = 1; + } + + size = strlen(root_url); + isRootHttp = ishttp(root_url); + + if (root_url[size - 1] != token) { + av_strlcat(root_url, "/", size + 2); + size += 2; + } + + for (i = 0; i < n_baseurl_nodes; ++i) { + if (i == rootId) { + continue; + } + text = xmlNodeGetContent(baseurl_nodes[i]); + if (text) { + memset(tmp_str, 0, strlen(tmp_str)); + if (!ishttp(text) && isRootHttp) { + av_strlcpy(tmp_str, root_url, size + 1); + } + start = (text[0] == token); + av_strlcat(tmp_str, text + start, max_url_size); + xmlNodeSetContent(baseurl_nodes[i], tmp_str); + updated = 1; + xmlFree(text); + } + } + +end: + av_free(path); + av_free(tmp_str); + return updated; + +} + static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr node, xmlNodePtr adaptionset_node, @@ -730,6 +837,10 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, baseurl_nodes[2] = adaptionset_baseurl_node; baseurl_nodes[3] = representation_baseurl_node; + ret = resolve_content_path(s, url, baseurl_nodes, 4); + if (ret == AVERROR(ENOMEM) || (ret == 0)) { + goto end; + } if (representation_segmenttemplate_node || fragment_template_node || period_segmenttemplate_node) { fragment_timeline_node = NULL; fragment_templates_tab[0] = representation_segmenttemplate_node; @@ -1050,6 +1161,9 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) } mpd_baseurl_node = find_child_node_by_name(node, "BaseURL"); + if (!mpd_baseurl_node) { + mpd_baseurl_node = xmlNewNode(NULL, "BaseURL"); + } // at now we can handle only one period, with the longest duration node = xmlFirstElementChild(node); @@ -1417,18 +1531,6 @@ static int open_input(DASHContext *c, struct representation *pls, struct fragmen goto cleanup; } - /* Seek to the requested position. If this was a HTTP request, the offset - * should already be where want it to, but this allows e.g. local testing - * without a HTTP server. */ - if (!ret && seg->url_offset) { - int64_t seekret = avio_seek(pls->input, seg->url_offset, SEEK_SET); - if (seekret < 0) { - av_log(pls->parent, AV_LOG_ERROR, "Unable to seek to offset %"PRId64" of DASH fragment '%s'\n", seg->url_offset, seg->url); - ret = (int) seekret; - ff_format_io_close(pls->parent, &pls->input); - } - } - cleanup: av_dict_free(&opts); pls->cur_seg_offset = 0; From 78e884f3fb1d0471dbe2c89fec0d0f274f7c8350 Mon Sep 17 00:00:00 2001 From: Colin NG Date: Sun, 21 Jan 2018 13:56:57 +0800 Subject: [PATCH 1702/2557] libavformat/dashdec: Fix for ticket 6856 (filename limited to 1024) --- libavformat/dashdec.c | 94 +++++++++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 31 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 3aac89c4ab951..f4cbb065e919f 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -148,13 +148,20 @@ typedef struct DASHContext { char *headers; ///< holds HTTP headers set as an AVOption to the HTTP protocol context char *allowed_extensions; AVDictionary *avio_opts; + int max_url_size; } DASHContext; -static int ishttp(char *url) { +static int ishttp(char *url) +{ const char *proto_name = avio_find_protocol_name(url); return av_strstart(proto_name, "http", NULL); } +static int aligned(int val) +{ + return ((val + 0x3F) >> 6) << 6; +} + static uint64_t get_current_time_in_sec(void) { return av_gettime() / 1000000; @@ -453,6 +460,7 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, static char *get_content_url(xmlNodePtr *baseurl_nodes, int n_baseurl_nodes, + int max_url_size, char *rep_id_val, char *rep_bandwidth_val, char *val) @@ -460,10 +468,12 @@ static char *get_content_url(xmlNodePtr *baseurl_nodes, int i; char *text; char *url = NULL; - char tmp_str[MAX_URL_SIZE]; - char tmp_str_2[MAX_URL_SIZE]; + char *tmp_str = av_mallocz(max_url_size); + char *tmp_str_2 = av_mallocz(max_url_size); - memset(tmp_str, 0, sizeof(tmp_str)); + if (!tmp_str || !tmp_str_2) { + return NULL; + } for (i = 0; i < n_baseurl_nodes; ++i) { if (baseurl_nodes[i] && @@ -471,33 +481,36 @@ static char *get_content_url(xmlNodePtr *baseurl_nodes, baseurl_nodes[i]->children->type == XML_TEXT_NODE) { text = xmlNodeGetContent(baseurl_nodes[i]->children); if (text) { - memset(tmp_str, 0, sizeof(tmp_str)); - memset(tmp_str_2, 0, sizeof(tmp_str_2)); - ff_make_absolute_url(tmp_str_2, MAX_URL_SIZE, tmp_str, text); - av_strlcpy(tmp_str, tmp_str_2, sizeof(tmp_str)); + memset(tmp_str, 0, max_url_size); + memset(tmp_str_2, 0, max_url_size); + ff_make_absolute_url(tmp_str_2, max_url_size, tmp_str, text); + av_strlcpy(tmp_str, tmp_str_2, max_url_size); xmlFree(text); } } } if (val) - av_strlcat(tmp_str, (const char*)val, sizeof(tmp_str)); + av_strlcat(tmp_str, (const char*)val, max_url_size); if (rep_id_val) { url = av_strireplace(tmp_str, "$RepresentationID$", (const char*)rep_id_val); if (!url) { - return NULL; + goto end; } - av_strlcpy(tmp_str, url, sizeof(tmp_str)); + av_strlcpy(tmp_str, url, max_url_size); } if (rep_bandwidth_val && tmp_str[0] != '\0') { // free any previously assigned url before reassigning av_free(url); url = av_strireplace(tmp_str, "$Bandwidth$", (const char*)rep_bandwidth_val); if (!url) { - return NULL; + goto end; } } +end: + av_free(tmp_str); + av_free(tmp_str_2); return url; } @@ -582,9 +595,11 @@ static int parse_manifest_segmenturlnode(AVFormatContext *s, struct representati char *rep_id_val, char *rep_bandwidth_val) { + DASHContext *c = s->priv_data; char *initialization_val = NULL; char *media_val = NULL; char *range_val = NULL; + int max_url_size = c ? c->max_url_size: MAX_URL_SIZE; if (!av_strcasecmp(fragmenturl_node->name, (const char *)"Initialization")) { initialization_val = xmlGetProp(fragmenturl_node, "sourceURL"); @@ -597,6 +612,7 @@ static int parse_manifest_segmenturlnode(AVFormatContext *s, struct representati return AVERROR(ENOMEM); } rep->init_section->url = get_content_url(baseurl_nodes, 4, + max_url_size, rep_id_val, rep_bandwidth_val, initialization_val); @@ -621,6 +637,7 @@ static int parse_manifest_segmenturlnode(AVFormatContext *s, struct representati return AVERROR(ENOMEM); } seg->url = get_content_url(baseurl_nodes, 4, + max_url_size, rep_id_val, rep_bandwidth_val, media_val); @@ -675,7 +692,7 @@ static int parse_manifest_segmenttimeline(AVFormatContext *s, struct representat return 0; } -static int resolve_content_path(AVFormatContext *s, const char *url, xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { +static int resolve_content_path(AVFormatContext *s, const char *url, int *max_url_size, xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { char *tmp_str = NULL; char *path = NULL; @@ -692,13 +709,13 @@ static int resolve_content_path(AVFormatContext *s, const char *url, xmlNodePtr int updated = 0; int size = 0; int i; - int max_url_size = strlen(url); + int tmp_max_url_size = strlen(url); for (i = n_baseurl_nodes-1; i >= 0 ; i--) { text = xmlNodeGetContent(baseurl_nodes[i]); if (!text) continue; - max_url_size += strlen(text); + tmp_max_url_size += strlen(text); if (ishttp(text)) { xmlFree(text); break; @@ -706,7 +723,8 @@ static int resolve_content_path(AVFormatContext *s, const char *url, xmlNodePtr xmlFree(text); } - text = av_mallocz(max_url_size); + tmp_max_url_size = aligned(tmp_max_url_size); + text = av_mallocz(tmp_max_url_size); if (!text) { updated = AVERROR(ENOMEM); goto end; @@ -716,8 +734,8 @@ static int resolve_content_path(AVFormatContext *s, const char *url, xmlNodePtr size = strlen(mpdName); } - path = av_mallocz(max_url_size); - tmp_str = av_mallocz(max_url_size); + path = av_mallocz(tmp_max_url_size); + tmp_str = av_mallocz(tmp_max_url_size); if (!tmp_str || !path) { updated = AVERROR(ENOMEM); goto end; @@ -760,7 +778,7 @@ static int resolve_content_path(AVFormatContext *s, const char *url, xmlNodePtr av_strlcpy(tmp_str, root_url, size + 1); } start = (text[0] == token); - av_strlcat(tmp_str, text + start, max_url_size); + av_strlcat(tmp_str, text + start, tmp_max_url_size); xmlNodeSetContent(baseurl_nodes[i], tmp_str); updated = 1; xmlFree(text); @@ -768,6 +786,9 @@ static int resolve_content_path(AVFormatContext *s, const char *url, xmlNodePtr } end: + if (tmp_max_url_size > *max_url_size) { + *max_url_size = tmp_max_url_size; + } av_free(path); av_free(tmp_str); return updated; @@ -837,8 +858,9 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, baseurl_nodes[2] = adaptionset_baseurl_node; baseurl_nodes[3] = representation_baseurl_node; - ret = resolve_content_path(s, url, baseurl_nodes, 4); - if (ret == AVERROR(ENOMEM) || (ret == 0)) { + ret = resolve_content_path(s, url, &c->max_url_size, baseurl_nodes, 4); + c->max_url_size = aligned(c->max_url_size + strlen(rep_id_val) + strlen(rep_bandwidth_val)); + if (ret == AVERROR(ENOMEM) || ret == 0) { goto end; } if (representation_segmenttemplate_node || fragment_template_node || period_segmenttemplate_node) { @@ -862,7 +884,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, ret = AVERROR(ENOMEM); goto end; } - rep->init_section->url = get_content_url(baseurl_nodes, 4, rep_id_val, rep_bandwidth_val, initialization_val); + c->max_url_size = aligned(c->max_url_size + strlen(initialization_val)); + rep->init_section->url = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, initialization_val); if (!rep->init_section->url) { av_free(rep->init_section); av_free(rep); @@ -874,7 +897,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, } if (media_val) { - rep->url_template = get_content_url(baseurl_nodes, 4, rep_id_val, rep_bandwidth_val, media_val); + c->max_url_size = aligned(c->max_url_size + strlen(media_val)); + rep->url_template = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, media_val); xmlFree(media_val); } @@ -917,7 +941,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, ret = AVERROR(ENOMEM); goto end; } - seg->url = get_content_url(baseurl_nodes, 4, rep_id_val, rep_bandwidth_val, NULL); + seg->url = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, NULL); if (!seg->url) { av_free(seg); ret = AVERROR(ENOMEM); @@ -1461,19 +1485,22 @@ static struct fragment *get_current_fragment(struct representation *pls) } } if (seg) { - char tmpfilename[MAX_URL_SIZE]; - - ff_dash_fill_tmpl_params(tmpfilename, sizeof(tmpfilename), pls->url_template, 0, pls->cur_seq_no, 0, get_segment_start_time_based_on_timeline(pls, pls->cur_seq_no)); + char *tmpfilename= av_mallocz(c->max_url_size); + if (!tmpfilename) { + return NULL; + } + ff_dash_fill_tmpl_params(tmpfilename, c->max_url_size, pls->url_template, 0, pls->cur_seq_no, 0, get_segment_start_time_based_on_timeline(pls, pls->cur_seq_no)); seg->url = av_strireplace(pls->url_template, pls->url_template, tmpfilename); if (!seg->url) { av_log(pls->parent, AV_LOG_WARNING, "Unable to resolve template url '%s', try to use origin template\n", pls->url_template); seg->url = av_strdup(pls->url_template); if (!seg->url) { av_log(pls->parent, AV_LOG_ERROR, "Cannot resolve template url '%s'\n", pls->url_template); + av_free(tmpfilename); return NULL; } } - + av_free(tmpfilename); seg->size = -1; } @@ -1512,9 +1539,13 @@ static int read_from_url(struct representation *pls, struct fragment *seg, static int open_input(DASHContext *c, struct representation *pls, struct fragment *seg) { AVDictionary *opts = NULL; - char url[MAX_URL_SIZE]; - int ret; + char *url = NULL; + int ret = 0; + url = av_mallocz(c->max_url_size); + if (!url) { + goto cleanup; + } set_httpheader_options(c, &opts); if (seg->size >= 0) { /* try to restrict the HTTP request to the part we want @@ -1523,7 +1554,7 @@ static int open_input(DASHContext *c, struct representation *pls, struct fragmen av_dict_set_int(&opts, "end_offset", seg->url_offset + seg->size, 0); } - ff_make_absolute_url(url, MAX_URL_SIZE, c->base_url, seg->url); + ff_make_absolute_url(url, c->max_url_size, c->base_url, seg->url); av_log(pls->parent, AV_LOG_VERBOSE, "DASH request for url '%s', offset %"PRId64", playlist %d\n", url, seg->url_offset, pls->rep_idx); ret = open_url(pls->parent, &pls->input, url, c->avio_opts, opts, NULL); @@ -1532,6 +1563,7 @@ static int open_input(DASHContext *c, struct representation *pls, struct fragmen } cleanup: + av_free(url); av_dict_free(&opts); pls->cur_seg_offset = 0; pls->cur_seg_size = seg->size; From 55bdee7b07262a07d7c63475b1952b4ec17503d0 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Thu, 18 Jan 2018 23:31:48 +0100 Subject: [PATCH 1703/2557] lavc/svq3: Do not write into memory defined as const. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes a warning on ppc: libavcodec/svq3.c:1055:21: warning: passing argument 1 of ‘av_write_bswap32’ discards 'const' qualifier from pointer target type --- libavcodec/svq3.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index a937b2f951349..fc17081ecf412 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -1048,12 +1048,12 @@ static int svq3_decode_slice_header(AVCodecContext *avctx) } memcpy(s->slice_buf, s->gb.buffer + s->gb.index / 8, slice_bytes); - init_get_bits(&s->gb_slice, s->slice_buf, slice_bits); - if (s->watermark_key) { - uint32_t header = AV_RL32(&s->gb_slice.buffer[1]); - AV_WL32(&s->gb_slice.buffer[1], header ^ s->watermark_key); + uint32_t header = AV_RL32(&s->slice_buf[1]); + AV_WL32(&s->slice_buf[1], header ^ s->watermark_key); } + init_get_bits(&s->gb_slice, s->slice_buf, slice_bits); + if (length > 0) { memmove(s->slice_buf, &s->slice_buf[slice_length], length - 1); } From 15a05d2b73c6e5ae530b7e2cafeabe2a383ef72b Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Fri, 19 Jan 2018 17:52:32 +0100 Subject: [PATCH 1704/2557] MAINTAINERS: add myself for avcodec/v4l2_ Signed-off-by: Michael Niedermayer --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index e5839261af714..d0de26c4f70d3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -240,6 +240,7 @@ Codecs: tta.c Alex Beregszaszi, Jaikrishnan Menon ttaenc.c Paul B Mahol txd.c Ivo van Poorten + v4l2_* Jorge Ramirez-Ortiz vc2* Rostislav Pehlivanov vcr1.c Michael Niedermayer videotoolboxenc.c Rick Kern, Aman Gupta From 56a53340ed4cc55898e49c07081311ebb2816630 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 20 Jan 2018 04:10:50 +0100 Subject: [PATCH 1705/2557] avcodec/truemotion2: Fix integer overflow in TM2_RECALC_BLOCK() Fixes: signed integer overflow: 1477974040 - -1877995504 cannot be represented in type 'int' Fixes: 4861/clusterfuzz-testcase-minimized-4570316383715328 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/truemotion2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/truemotion2.c b/libavcodec/truemotion2.c index f077f0e4bd990..97c38f7f088d2 100644 --- a/libavcodec/truemotion2.c +++ b/libavcodec/truemotion2.c @@ -441,8 +441,8 @@ static inline int GET_TOK(TM2Context *ctx,int type) /* recalculate last and delta values for next blocks */ #define TM2_RECALC_BLOCK(CHR, stride, last, CD) {\ - CD[0] = CHR[1] - last[1];\ - CD[1] = (int)CHR[stride + 1] - (int)CHR[1];\ + CD[0] = (unsigned)CHR[ 1] - (unsigned)last[1];\ + CD[1] = (unsigned)CHR[stride + 1] - (unsigned) CHR[1];\ last[0] = (int)CHR[stride + 0];\ last[1] = (int)CHR[stride + 1];} From dfdeed5a2c8f432d6c5eda1a3a6a1f333f3d4604 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 8 Jan 2018 15:56:43 +0800 Subject: [PATCH 1706/2557] lavfi: VAAPI VPP common infrastructure. Re-work the VAAPI common infrastructure to avoid code duplication between filters. Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- libavfilter/vaapi_vpp.c | 379 ++++++++++++++++++++++++++++++++++++++++ libavfilter/vaapi_vpp.h | 82 +++++++++ 2 files changed, 461 insertions(+) create mode 100644 libavfilter/vaapi_vpp.c create mode 100644 libavfilter/vaapi_vpp.h diff --git a/libavfilter/vaapi_vpp.c b/libavfilter/vaapi_vpp.c new file mode 100644 index 0000000000000..9d917722a0235 --- /dev/null +++ b/libavfilter/vaapi_vpp.c @@ -0,0 +1,379 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/avassert.h" +#include "libavutil/pixdesc.h" +#include "formats.h" + +#include "vaapi_vpp.h" + +int ff_vaapi_vpp_query_formats(AVFilterContext *avctx) +{ + enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, + }; + int err; + + if ((err = ff_formats_ref(ff_make_format_list(pix_fmts), + &avctx->inputs[0]->out_formats)) < 0) + return err; + if ((err = ff_formats_ref(ff_make_format_list(pix_fmts), + &avctx->outputs[0]->in_formats)) < 0) + return err; + + return 0; +} + +void ff_vaapi_vpp_pipeline_uninit(AVFilterContext *avctx) +{ + VAAPIVPPContext *ctx = avctx->priv; + int i; + for (i = 0; i < ctx->nb_filter_buffers; i++) { + if (ctx->filter_buffers[i] != VA_INVALID_ID) { + vaDestroyBuffer(ctx->hwctx->display, ctx->filter_buffers[i]); + ctx->filter_buffers[i] = VA_INVALID_ID; + } + } + ctx->nb_filter_buffers = 0; + + if (ctx->va_context != VA_INVALID_ID) { + vaDestroyContext(ctx->hwctx->display, ctx->va_context); + ctx->va_context = VA_INVALID_ID; + } + + if (ctx->va_config != VA_INVALID_ID) { + vaDestroyConfig(ctx->hwctx->display, ctx->va_config); + ctx->va_config = VA_INVALID_ID; + } + + av_buffer_unref(&ctx->output_frames_ref); + av_buffer_unref(&ctx->device_ref); + ctx->hwctx = NULL; +} + +int ff_vaapi_vpp_config_input(AVFilterLink *inlink) +{ + AVFilterContext *avctx = inlink->dst; + VAAPIVPPContext *ctx = avctx->priv; + + if (ctx->pipeline_uninit) + ctx->pipeline_uninit(avctx); + + if (!inlink->hw_frames_ctx) { + av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is " + "required to associate the processing device.\n"); + return AVERROR(EINVAL); + } + + ctx->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx); + if (!ctx->input_frames_ref) { + av_log(avctx, AV_LOG_ERROR, "A input frames reference create " + "failed.\n"); + return AVERROR(ENOMEM); + } + ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data; + + return 0; +} + +int ff_vaapi_vpp_config_output(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + VAAPIVPPContext *ctx = avctx->priv; + AVVAAPIHWConfig *hwconfig = NULL; + AVHWFramesConstraints *constraints = NULL; + AVVAAPIFramesContext *va_frames; + VAStatus vas; + int err, i; + + if (ctx->pipeline_uninit) + ctx->pipeline_uninit(avctx); + + if (!ctx->output_width) + ctx->output_width = avctx->inputs[0]->w; + if (!ctx->output_height) + ctx->output_height = avctx->inputs[0]->h; + + av_assert0(ctx->input_frames); + ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref); + if (!ctx->device_ref) { + av_log(avctx, AV_LOG_ERROR, "A device reference create " + "failed.\n"); + return AVERROR(ENOMEM); + } + ctx->hwctx = ((AVHWDeviceContext*)ctx->device_ref->data)->hwctx; + + av_assert0(ctx->va_config == VA_INVALID_ID); + vas = vaCreateConfig(ctx->hwctx->display, VAProfileNone, + VAEntrypointVideoProc, NULL, 0, &ctx->va_config); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to create processing pipeline " + "config: %d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref); + if (!hwconfig) { + err = AVERROR(ENOMEM); + goto fail; + } + hwconfig->config_id = ctx->va_config; + + constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref, + hwconfig); + if (!constraints) { + err = AVERROR(ENOMEM); + goto fail; + } + + if (ctx->output_format == AV_PIX_FMT_NONE) + ctx->output_format = ctx->input_frames->sw_format; + if (constraints->valid_sw_formats) { + for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { + if (ctx->output_format == constraints->valid_sw_formats[i]) + break; + } + if (constraints->valid_sw_formats[i] == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Hardware does not support output " + "format %s.\n", av_get_pix_fmt_name(ctx->output_format)); + err = AVERROR(EINVAL); + goto fail; + } + } + + if (ctx->output_width < constraints->min_width || + ctx->output_height < constraints->min_height || + ctx->output_width > constraints->max_width || + ctx->output_height > constraints->max_height) { + av_log(avctx, AV_LOG_ERROR, "Hardware does not support scaling to " + "size %dx%d (constraints: width %d-%d height %d-%d).\n", + ctx->output_width, ctx->output_height, + constraints->min_width, constraints->max_width, + constraints->min_height, constraints->max_height); + err = AVERROR(EINVAL); + goto fail; + } + + ctx->output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref); + if (!ctx->output_frames_ref) { + av_log(avctx, AV_LOG_ERROR, "Failed to create HW frame context " + "for output.\n"); + err = AVERROR(ENOMEM); + goto fail; + } + + ctx->output_frames = (AVHWFramesContext*)ctx->output_frames_ref->data; + + ctx->output_frames->format = AV_PIX_FMT_VAAPI; + ctx->output_frames->sw_format = ctx->output_format; + ctx->output_frames->width = ctx->output_width; + ctx->output_frames->height = ctx->output_height; + + // The number of output frames we need is determined by what follows + // the filter. If it's an encoder with complex frame reference + // structures then this could be very high. + ctx->output_frames->initial_pool_size = 10; + + err = av_hwframe_ctx_init(ctx->output_frames_ref); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to initialise VAAPI frame " + "context for output: %d\n", err); + goto fail; + } + + va_frames = ctx->output_frames->hwctx; + + av_assert0(ctx->va_context == VA_INVALID_ID); + vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, + ctx->output_width, ctx->output_height, + VA_PROGRESSIVE, + va_frames->surface_ids, va_frames->nb_surfaces, + &ctx->va_context); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to create processing pipeline " + "context: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + + outlink->w = ctx->output_width; + outlink->h = ctx->output_height; + + if (ctx->build_filter_params) { + err = ctx->build_filter_params(avctx); + if (err < 0) + goto fail; + } + + outlink->hw_frames_ctx = av_buffer_ref(ctx->output_frames_ref); + if (!outlink->hw_frames_ctx) { + err = AVERROR(ENOMEM); + goto fail; + } + + av_freep(&hwconfig); + av_hwframe_constraints_free(&constraints); + return 0; + +fail: + av_buffer_unref(&ctx->output_frames_ref); + av_freep(&hwconfig); + av_hwframe_constraints_free(&constraints); + return err; +} + +int ff_vaapi_vpp_colour_standard(enum AVColorSpace av_cs) +{ + switch(av_cs) { +#define CS(av, va) case AVCOL_SPC_ ## av: return VAProcColorStandard ## va; + CS(BT709, BT709); + CS(BT470BG, BT601); + CS(SMPTE170M, SMPTE170M); + CS(SMPTE240M, SMPTE240M); +#undef CS + default: + return VAProcColorStandardNone; + } +} + +int ff_vaapi_vpp_make_param_buffers(AVFilterContext *avctx, + int type, + const void *data, + size_t size, + int count) +{ + VAStatus vas; + VABufferID buffer; + VAAPIVPPContext *ctx = avctx->priv; + + av_assert0(ctx->nb_filter_buffers + 1 <= VAProcFilterCount); + + vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, + type, size, count, (void*)data, &buffer); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to create parameter " + "buffer (type %d): %d (%s).\n", + type, vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + + ctx->filter_buffers[ctx->nb_filter_buffers++] = buffer; + + av_log(avctx, AV_LOG_DEBUG, "Param buffer (type %d, %zu bytes, count %d) " + "is %#x.\n", type, size, count, buffer); + return 0; +} + + +int ff_vaapi_vpp_render_picture(AVFilterContext *avctx, + VAProcPipelineParameterBuffer *params, + VASurfaceID output_surface) +{ + VABufferID params_id; + VAStatus vas; + int err = 0; + VAAPIVPPContext *ctx = avctx->priv; + + vas = vaBeginPicture(ctx->hwctx->display, + ctx->va_context, output_surface); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to attach new picture: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, + VAProcPipelineParameterBufferType, + sizeof(*params), 1, params, ¶ms_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail_after_begin; + } + av_log(avctx, AV_LOG_DEBUG, "Pipeline parameter buffer is %#x.\n", + params_id); + + vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, + ¶ms_id, 1); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to render parameter buffer: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail_after_begin; + } + + vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to start picture processing: " + "%d (%s).\n", vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail_after_render; + } + + if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks & + AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) { + vas = vaDestroyBuffer(ctx->hwctx->display, params_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to free parameter buffer: " + "%d (%s).\n", vas, vaErrorStr(vas)); + // And ignore. + } + } + + return 0; + + // We want to make sure that if vaBeginPicture has been called, we also + // call vaRenderPicture and vaEndPicture. These calls may well fail or + // do something else nasty, but once we're in this failure case there + // isn't much else we can do. +fail_after_begin: + vaRenderPicture(ctx->hwctx->display, ctx->va_context, ¶ms_id, 1); +fail_after_render: + vaEndPicture(ctx->hwctx->display, ctx->va_context); +fail: + return err; +} + +void ff_vaapi_vpp_ctx_init(AVFilterContext *avctx) +{ + int i; + VAAPIVPPContext *ctx = avctx->priv; + + ctx->va_config = VA_INVALID_ID; + ctx->va_context = VA_INVALID_ID; + ctx->valid_ids = 1; + + for (i = 0; i < VAProcFilterCount; i++) + ctx->filter_buffers[i] = VA_INVALID_ID; + ctx->nb_filter_buffers = 0; +} + +void ff_vaapi_vpp_ctx_uninit(AVFilterContext *avctx) +{ + VAAPIVPPContext *ctx = avctx->priv; + if (ctx->valid_ids && ctx->pipeline_uninit) + ctx->pipeline_uninit(avctx); + + av_buffer_unref(&ctx->input_frames_ref); + av_buffer_unref(&ctx->output_frames_ref); + av_buffer_unref(&ctx->device_ref); +} diff --git a/libavfilter/vaapi_vpp.h b/libavfilter/vaapi_vpp.h new file mode 100644 index 0000000000000..83e0ec1cc2fdb --- /dev/null +++ b/libavfilter/vaapi_vpp.h @@ -0,0 +1,82 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_VAAPI_VPP_H +#define AVFILTER_VAAPI_VPP_H + +#include +#include + +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_vaapi.h" + +#include "avfilter.h" + +typedef struct VAAPIVPPContext { + const AVClass *class; + + AVVAAPIDeviceContext *hwctx; + AVBufferRef *device_ref; + + int valid_ids; + VAConfigID va_config; + VAContextID va_context; + + AVBufferRef *input_frames_ref; + AVHWFramesContext *input_frames; + + AVBufferRef *output_frames_ref; + AVHWFramesContext *output_frames; + + enum AVPixelFormat output_format; + int output_width; // computed width + int output_height; // computed height + + VABufferID filter_buffers[VAProcFilterCount]; + int nb_filter_buffers; + + int (*build_filter_params)(AVFilterContext *avctx); + + void (*pipeline_uninit)(AVFilterContext *avctx); +} VAAPIVPPContext; + +void ff_vaapi_vpp_ctx_init(AVFilterContext *avctx); + +void ff_vaapi_vpp_ctx_uninit(AVFilterContext *avctx); + +int ff_vaapi_vpp_query_formats(AVFilterContext *avctx); + +void ff_vaapi_vpp_pipeline_uninit(AVFilterContext *avctx); + +int ff_vaapi_vpp_config_input(AVFilterLink *inlink); + +int ff_vaapi_vpp_config_output(AVFilterLink *outlink); + +int ff_vaapi_vpp_colour_standard(enum AVColorSpace av_cs); + +int ff_vaapi_vpp_make_param_buffers(AVFilterContext *avctx, + int type, + const void *data, + size_t size, + int count); + +int ff_vaapi_vpp_render_picture(AVFilterContext *avctx, + VAProcPipelineParameterBuffer *params, + VASurfaceID output_surface); + +#endif /* AVFILTER_VAAPI_VPP_H */ From 19214f005140b0ee7f706509bd3fab47f4af9b90 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 8 Jan 2018 16:02:35 +0800 Subject: [PATCH 1707/2557] lavfi: use common VAAPI VPP infrastructure for vf_scale_vaapi. Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- libavfilter/Makefile | 2 +- libavfilter/vf_scale_vaapi.c | 356 ++++------------------------------- 2 files changed, 42 insertions(+), 316 deletions(-) diff --git a/libavfilter/Makefile b/libavfilter/Makefile index ef4729dd3ffaf..3d8dd2c890b00 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -296,7 +296,7 @@ OBJS-$(CONFIG_SCALE_FILTER) += vf_scale.o scale.o OBJS-$(CONFIG_SCALE_CUDA_FILTER) += vf_scale_cuda.o vf_scale_cuda.ptx.o OBJS-$(CONFIG_SCALE_NPP_FILTER) += vf_scale_npp.o scale.o OBJS-$(CONFIG_SCALE_QSV_FILTER) += vf_scale_qsv.o -OBJS-$(CONFIG_SCALE_VAAPI_FILTER) += vf_scale_vaapi.o scale.o +OBJS-$(CONFIG_SCALE_VAAPI_FILTER) += vf_scale_vaapi.o scale.o vaapi_vpp.o OBJS-$(CONFIG_SCALE2REF_FILTER) += vf_scale.o scale.o OBJS-$(CONFIG_SELECT_FILTER) += f_select.o OBJS-$(CONFIG_SELECTIVECOLOR_FILTER) += vf_selectivecolor.o diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c index 4bead5aaf4b88..d349ff0f900cd 100644 --- a/libavfilter/vf_scale_vaapi.c +++ b/libavfilter/vf_scale_vaapi.c @@ -18,12 +18,7 @@ #include -#include -#include - #include "libavutil/avassert.h" -#include "libavutil/hwcontext.h" -#include "libavutil/hwcontext_vaapi.h" #include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -33,276 +28,74 @@ #include "internal.h" #include "scale.h" #include "video.h" +#include "vaapi_vpp.h" typedef struct ScaleVAAPIContext { - const AVClass *class; - - AVVAAPIDeviceContext *hwctx; - AVBufferRef *device_ref; - - int valid_ids; - VAConfigID va_config; - VAContextID va_context; - - AVBufferRef *input_frames_ref; - AVHWFramesContext *input_frames; - - AVBufferRef *output_frames_ref; - AVHWFramesContext *output_frames; + VAAPIVPPContext vpp_ctx; // must be the first fileld char *output_format_string; - enum AVPixelFormat output_format; char *w_expr; // width expression string char *h_expr; // height expression string - - int output_width; // computed width - int output_height; // computed height } ScaleVAAPIContext; - -static int scale_vaapi_query_formats(AVFilterContext *avctx) -{ - enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, - }; - int err; - - if ((err = ff_formats_ref(ff_make_format_list(pix_fmts), - &avctx->inputs[0]->out_formats)) < 0) - return err; - if ((err = ff_formats_ref(ff_make_format_list(pix_fmts), - &avctx->outputs[0]->in_formats)) < 0) - return err; - - return 0; -} - -static int scale_vaapi_pipeline_uninit(ScaleVAAPIContext *ctx) -{ - if (ctx->va_context != VA_INVALID_ID) { - vaDestroyContext(ctx->hwctx->display, ctx->va_context); - ctx->va_context = VA_INVALID_ID; - } - - if (ctx->va_config != VA_INVALID_ID) { - vaDestroyConfig(ctx->hwctx->display, ctx->va_config); - ctx->va_config = VA_INVALID_ID; - } - - av_buffer_unref(&ctx->output_frames_ref); - av_buffer_unref(&ctx->device_ref); - ctx->hwctx = 0; - - return 0; -} - -static int scale_vaapi_config_input(AVFilterLink *inlink) -{ - AVFilterContext *avctx = inlink->dst; - ScaleVAAPIContext *ctx = avctx->priv; - - scale_vaapi_pipeline_uninit(ctx); - - if (!inlink->hw_frames_ctx) { - av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is " - "required to associate the processing device.\n"); - return AVERROR(EINVAL); - } - - ctx->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx); - ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data; - - return 0; -} - static int scale_vaapi_config_output(AVFilterLink *outlink) { - AVFilterLink *inlink = outlink->src->inputs[0]; - AVFilterContext *avctx = outlink->src; - ScaleVAAPIContext *ctx = avctx->priv; - AVVAAPIHWConfig *hwconfig = NULL; - AVHWFramesConstraints *constraints = NULL; - AVVAAPIFramesContext *va_frames; - VAStatus vas; - int err, i; - - scale_vaapi_pipeline_uninit(ctx); - - ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref); - ctx->hwctx = ((AVHWDeviceContext*)ctx->device_ref->data)->hwctx; - - av_assert0(ctx->va_config == VA_INVALID_ID); - vas = vaCreateConfig(ctx->hwctx->display, VAProfileNone, - VAEntrypointVideoProc, 0, 0, &ctx->va_config); - if (vas != VA_STATUS_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "Failed to create processing pipeline " - "config: %d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail; - } - - hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref); - if (!hwconfig) { - err = AVERROR(ENOMEM); - goto fail; - } - hwconfig->config_id = ctx->va_config; - - constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref, - hwconfig); - if (!constraints) { - err = AVERROR(ENOMEM); - goto fail; - } - - if (ctx->output_format == AV_PIX_FMT_NONE) - ctx->output_format = ctx->input_frames->sw_format; - if (constraints->valid_sw_formats) { - for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { - if (ctx->output_format == constraints->valid_sw_formats[i]) - break; - } - if (constraints->valid_sw_formats[i] == AV_PIX_FMT_NONE) { - av_log(ctx, AV_LOG_ERROR, "Hardware does not support output " - "format %s.\n", av_get_pix_fmt_name(ctx->output_format)); - err = AVERROR(EINVAL); - goto fail; - } - } + AVFilterLink *inlink = outlink->src->inputs[0]; + AVFilterContext *avctx = outlink->src; + VAAPIVPPContext *vpp_ctx = avctx->priv; + ScaleVAAPIContext *ctx = avctx->priv; + int err; if ((err = ff_scale_eval_dimensions(ctx, ctx->w_expr, ctx->h_expr, inlink, outlink, - &ctx->output_width, &ctx->output_height)) < 0) - goto fail; - - if (ctx->output_width < constraints->min_width || - ctx->output_height < constraints->min_height || - ctx->output_width > constraints->max_width || - ctx->output_height > constraints->max_height) { - av_log(ctx, AV_LOG_ERROR, "Hardware does not support scaling to " - "size %dx%d (constraints: width %d-%d height %d-%d).\n", - ctx->output_width, ctx->output_height, - constraints->min_width, constraints->max_width, - constraints->min_height, constraints->max_height); - err = AVERROR(EINVAL); - goto fail; - } - - ctx->output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref); - if (!ctx->output_frames_ref) { - av_log(ctx, AV_LOG_ERROR, "Failed to create HW frame context " - "for output.\n"); - err = AVERROR(ENOMEM); - goto fail; - } - - ctx->output_frames = (AVHWFramesContext*)ctx->output_frames_ref->data; - - ctx->output_frames->format = AV_PIX_FMT_VAAPI; - ctx->output_frames->sw_format = ctx->output_format; - ctx->output_frames->width = ctx->output_width; - ctx->output_frames->height = ctx->output_height; - - // The number of output frames we need is determined by what follows - // the filter. If it's an encoder with complex frame reference - // structures then this could be very high. - ctx->output_frames->initial_pool_size = 10; - - err = av_hwframe_ctx_init(ctx->output_frames_ref); - if (err < 0) { - av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI frame " - "context for output: %d\n", err); - goto fail; - } - - va_frames = ctx->output_frames->hwctx; - - av_assert0(ctx->va_context == VA_INVALID_ID); - vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, - ctx->output_width, ctx->output_height, - VA_PROGRESSIVE, - va_frames->surface_ids, va_frames->nb_surfaces, - &ctx->va_context); - if (vas != VA_STATUS_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "Failed to create processing pipeline " - "context: %d (%s).\n", vas, vaErrorStr(vas)); - return AVERROR(EIO); - } - - outlink->w = ctx->output_width; - outlink->h = ctx->output_height; + &vpp_ctx->output_width, &vpp_ctx->output_height)) < 0) + return err; - outlink->hw_frames_ctx = av_buffer_ref(ctx->output_frames_ref); - if (!outlink->hw_frames_ctx) { - err = AVERROR(ENOMEM); - goto fail; - } + err = ff_vaapi_vpp_config_output(outlink); + if (err < 0) + return err; if (inlink->sample_aspect_ratio.num) outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink->w, outlink->w * inlink->h}, inlink->sample_aspect_ratio); else outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; - av_freep(&hwconfig); - av_hwframe_constraints_free(&constraints); return 0; - -fail: - av_buffer_unref(&ctx->output_frames_ref); - av_freep(&hwconfig); - av_hwframe_constraints_free(&constraints); - return err; -} - -static int vaapi_proc_colour_standard(enum AVColorSpace av_cs) -{ - switch(av_cs) { -#define CS(av, va) case AVCOL_SPC_ ## av: return VAProcColorStandard ## va; - CS(BT709, BT709); - CS(BT470BG, BT601); - CS(SMPTE170M, SMPTE170M); - CS(SMPTE240M, SMPTE240M); -#undef CS - default: - return VAProcColorStandardNone; - } } static int scale_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) { - AVFilterContext *avctx = inlink->dst; - AVFilterLink *outlink = avctx->outputs[0]; - ScaleVAAPIContext *ctx = avctx->priv; - AVFrame *output_frame = NULL; + AVFilterContext *avctx = inlink->dst; + AVFilterLink *outlink = avctx->outputs[0]; + VAAPIVPPContext *vpp_ctx = avctx->priv; + AVFrame *output_frame = NULL; VASurfaceID input_surface, output_surface; VAProcPipelineParameterBuffer params; - VABufferID params_id; VARectangle input_region; - VAStatus vas; int err; - av_log(ctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", + av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", av_get_pix_fmt_name(input_frame->format), input_frame->width, input_frame->height, input_frame->pts); - if (ctx->va_context == VA_INVALID_ID) + if (vpp_ctx->va_context == VA_INVALID_ID) return AVERROR(EINVAL); input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3]; - av_log(ctx, AV_LOG_DEBUG, "Using surface %#x for scale input.\n", + av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for scale input.\n", input_surface); - output_frame = ff_get_video_buffer(outlink, ctx->output_width, - ctx->output_height); + output_frame = ff_get_video_buffer(outlink, vpp_ctx->output_width, + vpp_ctx->output_height); if (!output_frame) { err = AVERROR(ENOMEM); goto fail; } output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3]; - av_log(ctx, AV_LOG_DEBUG, "Using surface %#x for scale output.\n", + av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for scale output.\n", output_surface); memset(¶ms, 0, sizeof(params)); @@ -319,7 +112,7 @@ static int scale_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) params.surface = input_surface; params.surface_region = &input_region; params.surface_color_standard = - vaapi_proc_colour_standard(input_frame->colorspace); + ff_vaapi_vpp_colour_standard(input_frame->colorspace); params.output_region = 0; params.output_background_color = 0xff000000; @@ -328,71 +121,22 @@ static int scale_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) params.pipeline_flags = 0; params.filter_flags = VA_FILTER_SCALING_HQ; - vas = vaBeginPicture(ctx->hwctx->display, - ctx->va_context, output_surface); - if (vas != VA_STATUS_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "Failed to attach new picture: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); + err = ff_vaapi_vpp_render_picture(avctx, ¶ms, output_surface); + if (err < 0) goto fail; - } - - vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, - VAProcPipelineParameterBufferType, - sizeof(params), 1, ¶ms, ¶ms_id); - if (vas != VA_STATUS_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "Failed to create parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_begin; - } - av_log(ctx, AV_LOG_DEBUG, "Pipeline parameter buffer is %#x.\n", - params_id); - - vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, - ¶ms_id, 1); - if (vas != VA_STATUS_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "Failed to render parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_begin; - } - vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); - if (vas != VA_STATUS_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "Failed to start picture processing: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_render; - } - - if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks & - AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) { - vas = vaDestroyBuffer(ctx->hwctx->display, params_id); - if (vas != VA_STATUS_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "Failed to free parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - // And ignore. - } - } + err = av_frame_copy_props(output_frame, input_frame); + if (err < 0) + goto fail; - av_frame_copy_props(output_frame, input_frame); av_frame_free(&input_frame); - av_log(ctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", + av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", av_get_pix_fmt_name(output_frame->format), output_frame->width, output_frame->height, output_frame->pts); return ff_filter_frame(outlink, output_frame); - // We want to make sure that if vaBeginPicture has been called, we also - // call vaRenderPicture and vaEndPicture. These calls may well fail or - // do something else nasty, but once we're in this failure case there - // isn't much else we can do. -fail_after_begin: - vaRenderPicture(ctx->hwctx->display, ctx->va_context, ¶ms_id, 1); -fail_after_render: - vaEndPicture(ctx->hwctx->display, ctx->va_context); fail: av_frame_free(&input_frame); av_frame_free(&output_frame); @@ -401,39 +145,26 @@ static int scale_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) static av_cold int scale_vaapi_init(AVFilterContext *avctx) { - ScaleVAAPIContext *ctx = avctx->priv; + VAAPIVPPContext *vpp_ctx = avctx->priv; + ScaleVAAPIContext *ctx = avctx->priv; - ctx->va_config = VA_INVALID_ID; - ctx->va_context = VA_INVALID_ID; - ctx->valid_ids = 1; + ff_vaapi_vpp_ctx_init(avctx); + vpp_ctx->pipeline_uninit = ff_vaapi_vpp_pipeline_uninit; if (ctx->output_format_string) { - ctx->output_format = av_get_pix_fmt(ctx->output_format_string); - if (ctx->output_format == AV_PIX_FMT_NONE) { - av_log(ctx, AV_LOG_ERROR, "Invalid output format.\n"); + vpp_ctx->output_format = av_get_pix_fmt(ctx->output_format_string); + if (vpp_ctx->output_format == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Invalid output format.\n"); return AVERROR(EINVAL); } } else { // Use the input format once that is configured. - ctx->output_format = AV_PIX_FMT_NONE; + vpp_ctx->output_format = AV_PIX_FMT_NONE; } return 0; } -static av_cold void scale_vaapi_uninit(AVFilterContext *avctx) -{ - ScaleVAAPIContext *ctx = avctx->priv; - - if (ctx->valid_ids) - scale_vaapi_pipeline_uninit(ctx); - - av_buffer_unref(&ctx->input_frames_ref); - av_buffer_unref(&ctx->output_frames_ref); - av_buffer_unref(&ctx->device_ref); -} - - #define OFFSET(x) offsetof(ScaleVAAPIContext, x) #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM) static const AVOption scale_vaapi_options[] = { @@ -446,19 +177,14 @@ static const AVOption scale_vaapi_options[] = { { NULL }, }; -static const AVClass scale_vaapi_class = { - .class_name = "scale_vaapi", - .item_name = av_default_item_name, - .option = scale_vaapi_options, - .version = LIBAVUTIL_VERSION_INT, -}; +AVFILTER_DEFINE_CLASS(scale_vaapi); static const AVFilterPad scale_vaapi_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .filter_frame = &scale_vaapi_filter_frame, - .config_props = &scale_vaapi_config_input, + .config_props = &ff_vaapi_vpp_config_input, }, { NULL } }; @@ -477,8 +203,8 @@ AVFilter ff_vf_scale_vaapi = { .description = NULL_IF_CONFIG_SMALL("Scale to/from VAAPI surfaces."), .priv_size = sizeof(ScaleVAAPIContext), .init = &scale_vaapi_init, - .uninit = &scale_vaapi_uninit, - .query_formats = &scale_vaapi_query_formats, + .uninit = &ff_vaapi_vpp_ctx_uninit, + .query_formats = &ff_vaapi_vpp_query_formats, .inputs = scale_vaapi_inputs, .outputs = scale_vaapi_outputs, .priv_class = &scale_vaapi_class, From 92704c480e811e0bd2a605173559d2baa974119f Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 8 Jan 2018 16:07:38 +0800 Subject: [PATCH 1708/2557] lavfi: use common VAAPI VPP infrastructure for vf_deinterlace_vaapi. Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- libavfilter/Makefile | 2 +- libavfilter/vf_deinterlace_vaapi.c | 351 ++++------------------------- 2 files changed, 46 insertions(+), 307 deletions(-) diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 3d8dd2c890b00..bbc97a0831270 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -171,7 +171,7 @@ OBJS-$(CONFIG_DECONVOLVE_FILTER) += vf_convolve.o framesync.o OBJS-$(CONFIG_DEFLATE_FILTER) += vf_neighbor.o OBJS-$(CONFIG_DEFLICKER_FILTER) += vf_deflicker.o OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER) += vf_deinterlace_qsv.o -OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER) += vf_deinterlace_vaapi.o +OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER) += vf_deinterlace_vaapi.o vaapi_vpp.o OBJS-$(CONFIG_DEJUDDER_FILTER) += vf_dejudder.o OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o OBJS-$(CONFIG_DESHAKE_FILTER) += vf_deshake.o diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c index a38da5d57b707..9700f85817d48 100644 --- a/libavfilter/vf_deinterlace_vaapi.c +++ b/libavfilter/vf_deinterlace_vaapi.c @@ -18,13 +18,8 @@ #include -#include -#include - #include "libavutil/avassert.h" #include "libavutil/common.h" -#include "libavutil/hwcontext.h" -#include "libavutil/hwcontext_vaapi.h" #include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -33,31 +28,17 @@ #include "formats.h" #include "internal.h" #include "video.h" +#include "vaapi_vpp.h" #define MAX_REFERENCES 8 typedef struct DeintVAAPIContext { - const AVClass *class; - - AVVAAPIDeviceContext *hwctx; - AVBufferRef *device_ref; + VAAPIVPPContext vpp_ctx; // must be the first fileld int mode; int field_rate; int auto_enable; - int valid_ids; - VAConfigID va_config; - VAContextID va_context; - - AVBufferRef *input_frames_ref; - AVHWFramesContext *input_frames; - - AVBufferRef *output_frames_ref; - AVHWFramesContext *output_frames; - int output_height; - int output_width; - VAProcFilterCapDeinterlacing deint_caps[VAProcDeinterlacingCount]; int nb_deint_caps; @@ -67,8 +48,6 @@ typedef struct DeintVAAPIContext { int queue_count; AVFrame *frame_queue[MAX_REFERENCES]; int extra_delay_for_timestamps; - - VABufferID filter_buffer; } DeintVAAPIContext; static const char *deint_vaapi_mode_name(int mode) @@ -85,82 +64,29 @@ static const char *deint_vaapi_mode_name(int mode) } } -static int deint_vaapi_query_formats(AVFilterContext *avctx) +static void deint_vaapi_pipeline_uninit(AVFilterContext *avctx) { - enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, - }; - int err; - - if ((err = ff_formats_ref(ff_make_format_list(pix_fmts), - &avctx->inputs[0]->out_formats)) < 0) - return err; - if ((err = ff_formats_ref(ff_make_format_list(pix_fmts), - &avctx->outputs[0]->in_formats)) < 0) - return err; - - return 0; -} - -static int deint_vaapi_pipeline_uninit(AVFilterContext *avctx) -{ - DeintVAAPIContext *ctx = avctx->priv; + DeintVAAPIContext *ctx = avctx->priv; int i; for (i = 0; i < ctx->queue_count; i++) av_frame_free(&ctx->frame_queue[i]); ctx->queue_count = 0; - if (ctx->filter_buffer != VA_INVALID_ID) { - vaDestroyBuffer(ctx->hwctx->display, ctx->filter_buffer); - ctx->filter_buffer = VA_INVALID_ID; - } - - if (ctx->va_context != VA_INVALID_ID) { - vaDestroyContext(ctx->hwctx->display, ctx->va_context); - ctx->va_context = VA_INVALID_ID; - } - - if (ctx->va_config != VA_INVALID_ID) { - vaDestroyConfig(ctx->hwctx->display, ctx->va_config); - ctx->va_config = VA_INVALID_ID; - } - - av_buffer_unref(&ctx->device_ref); - ctx->hwctx = NULL; - - return 0; -} - -static int deint_vaapi_config_input(AVFilterLink *inlink) -{ - AVFilterContext *avctx = inlink->dst; - DeintVAAPIContext *ctx = avctx->priv; - - deint_vaapi_pipeline_uninit(avctx); - - if (!inlink->hw_frames_ctx) { - av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is " - "required to associate the processing device.\n"); - return AVERROR(EINVAL); - } - - ctx->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx); - ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data; - - return 0; + ff_vaapi_vpp_pipeline_uninit(avctx); } static int deint_vaapi_build_filter_params(AVFilterContext *avctx) { - DeintVAAPIContext *ctx = avctx->priv; + VAAPIVPPContext *vpp_ctx = avctx->priv; + DeintVAAPIContext *ctx = avctx->priv; VAStatus vas; VAProcFilterParameterBufferDeinterlacing params; int i; ctx->nb_deint_caps = VAProcDeinterlacingCount; - vas = vaQueryVideoProcFilterCaps(ctx->hwctx->display, - ctx->va_context, + vas = vaQueryVideoProcFilterCaps(vpp_ctx->hwctx->display, + vpp_ctx->va_context, VAProcFilterDeinterlacing, &ctx->deint_caps, &ctx->nb_deint_caps); @@ -194,20 +120,17 @@ static int deint_vaapi_build_filter_params(AVFilterContext *avctx) params.algorithm = ctx->mode; params.flags = 0; - av_assert0(ctx->filter_buffer == VA_INVALID_ID); - vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, - VAProcFilterParameterBufferType, - sizeof(params), 1, ¶ms, - &ctx->filter_buffer); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to create deinterlace " - "parameter buffer: %d (%s).\n", vas, vaErrorStr(vas)); - return AVERROR(EIO); - } - - vas = vaQueryVideoProcPipelineCaps(ctx->hwctx->display, - ctx->va_context, - &ctx->filter_buffer, 1, + vas = ff_vaapi_vpp_make_param_buffers(avctx, + VAProcFilterParameterBufferType, + ¶ms, + sizeof(params), + 1); + if (vas) + return vas; + + vas = vaQueryVideoProcPipelineCaps(vpp_ctx->hwctx->display, + vpp_ctx->va_context, + &vpp_ctx->filter_buffers[0], 1, &ctx->pipeline_caps); if (vas != VA_STATUS_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to query pipeline " @@ -234,159 +157,35 @@ static int deint_vaapi_build_filter_params(AVFilterContext *avctx) static int deint_vaapi_config_output(AVFilterLink *outlink) { - AVFilterContext *avctx = outlink->src; - AVFilterLink *inlink = avctx->inputs[0]; - DeintVAAPIContext *ctx = avctx->priv; - AVVAAPIHWConfig *hwconfig = NULL; - AVHWFramesConstraints *constraints = NULL; - AVVAAPIFramesContext *va_frames; - VAStatus vas; + AVFilterLink *inlink = outlink->src->inputs[0]; + AVFilterContext *avctx = outlink->src; + DeintVAAPIContext *ctx = avctx->priv; int err; - deint_vaapi_pipeline_uninit(avctx); - - av_assert0(ctx->input_frames); - ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref); - ctx->hwctx = ((AVHWDeviceContext*)ctx->device_ref->data)->hwctx; - - ctx->output_width = ctx->input_frames->width; - ctx->output_height = ctx->input_frames->height; - - av_assert0(ctx->va_config == VA_INVALID_ID); - vas = vaCreateConfig(ctx->hwctx->display, VAProfileNone, - VAEntrypointVideoProc, 0, 0, &ctx->va_config); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to create processing pipeline " - "config: %d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail; - } - - hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref); - if (!hwconfig) { - err = AVERROR(ENOMEM); - goto fail; - } - hwconfig->config_id = ctx->va_config; - - constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref, - hwconfig); - if (!constraints) { - err = AVERROR(ENOMEM); - goto fail; - } - - if (ctx->output_width < constraints->min_width || - ctx->output_height < constraints->min_height || - ctx->output_width > constraints->max_width || - ctx->output_height > constraints->max_height) { - av_log(avctx, AV_LOG_ERROR, "Hardware does not support " - "deinterlacing to size %dx%d " - "(constraints: width %d-%d height %d-%d).\n", - ctx->output_width, ctx->output_height, - constraints->min_width, constraints->max_width, - constraints->min_height, constraints->max_height); - err = AVERROR(EINVAL); - goto fail; - } - - ctx->output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref); - if (!ctx->output_frames_ref) { - av_log(avctx, AV_LOG_ERROR, "Failed to create HW frame context " - "for output.\n"); - err = AVERROR(ENOMEM); - goto fail; - } - - ctx->output_frames = (AVHWFramesContext*)ctx->output_frames_ref->data; - - ctx->output_frames->format = AV_PIX_FMT_VAAPI; - ctx->output_frames->sw_format = ctx->input_frames->sw_format; - ctx->output_frames->width = ctx->output_width; - ctx->output_frames->height = ctx->output_height; - - // The number of output frames we need is determined by what follows - // the filter. If it's an encoder with complex frame reference - // structures then this could be very high. - ctx->output_frames->initial_pool_size = 10; - - err = av_hwframe_ctx_init(ctx->output_frames_ref); - if (err < 0) { - av_log(avctx, AV_LOG_ERROR, "Failed to initialise VAAPI frame " - "context for output: %d\n", err); - goto fail; - } - - va_frames = ctx->output_frames->hwctx; - - av_assert0(ctx->va_context == VA_INVALID_ID); - vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, - ctx->output_width, ctx->output_height, 0, - va_frames->surface_ids, va_frames->nb_surfaces, - &ctx->va_context); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to create processing pipeline " - "context: %d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail; - } - - err = deint_vaapi_build_filter_params(avctx); + err = ff_vaapi_vpp_config_output(outlink); if (err < 0) - goto fail; - - outlink->w = inlink->w; - outlink->h = inlink->h; - + return err; outlink->time_base = av_mul_q(inlink->time_base, (AVRational) { 1, ctx->field_rate }); outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational) { ctx->field_rate, 1 }); - outlink->hw_frames_ctx = av_buffer_ref(ctx->output_frames_ref); - if (!outlink->hw_frames_ctx) { - err = AVERROR(ENOMEM); - goto fail; - } - - av_freep(&hwconfig); - av_hwframe_constraints_free(&constraints); return 0; - -fail: - av_buffer_unref(&ctx->output_frames_ref); - av_freep(&hwconfig); - av_hwframe_constraints_free(&constraints); - return err; -} - -static int vaapi_proc_colour_standard(enum AVColorSpace av_cs) -{ - switch(av_cs) { -#define CS(av, va) case AVCOL_SPC_ ## av: return VAProcColorStandard ## va; - CS(BT709, BT709); - CS(BT470BG, BT470BG); - CS(SMPTE170M, SMPTE170M); - CS(SMPTE240M, SMPTE240M); -#undef CS - default: - return VAProcColorStandardNone; - } } static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) { AVFilterContext *avctx = inlink->dst; AVFilterLink *outlink = avctx->outputs[0]; - DeintVAAPIContext *ctx = avctx->priv; - AVFrame *output_frame = NULL; + VAAPIVPPContext *vpp_ctx = avctx->priv; + DeintVAAPIContext *ctx = avctx->priv; + AVFrame *output_frame = NULL; VASurfaceID input_surface, output_surface; VASurfaceID backward_references[MAX_REFERENCES]; VASurfaceID forward_references[MAX_REFERENCES]; VAProcPipelineParameterBuffer params; VAProcFilterParameterBufferDeinterlacing *filter_params; VARectangle input_region; - VABufferID params_id; VAStatus vas; void *filter_params_addr = NULL; int err, i, field, current_frame_index; @@ -431,8 +230,8 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) av_log(avctx, AV_LOG_DEBUG, "\n"); for (field = 0; field < ctx->field_rate; field++) { - output_frame = ff_get_video_buffer(outlink, ctx->output_width, - ctx->output_height); + output_frame = ff_get_video_buffer(outlink, vpp_ctx->output_width, + vpp_ctx->output_height); if (!output_frame) { err = AVERROR(ENOMEM); goto fail; @@ -454,7 +253,7 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) params.surface = input_surface; params.surface_region = &input_region; params.surface_color_standard = - vaapi_proc_colour_standard(input_frame->colorspace); + ff_vaapi_vpp_colour_standard(input_frame->colorspace); params.output_region = NULL; params.output_background_color = 0xff000000; @@ -464,7 +263,7 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) params.filter_flags = VA_FRAME_PICTURE; if (!ctx->auto_enable || input_frame->interlaced_frame) { - vas = vaMapBuffer(ctx->hwctx->display, ctx->filter_buffer, + vas = vaMapBuffer(vpp_ctx->hwctx->display, vpp_ctx->filter_buffers[0], &filter_params_addr); if (vas != VA_STATUS_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to map filter parameter " @@ -481,12 +280,12 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) filter_params->flags |= field ? 0 : VA_DEINTERLACING_BOTTOM_FIELD; } filter_params_addr = NULL; - vas = vaUnmapBuffer(ctx->hwctx->display, ctx->filter_buffer); + vas = vaUnmapBuffer(vpp_ctx->hwctx->display, vpp_ctx->filter_buffers[0]); if (vas != VA_STATUS_SUCCESS) av_log(avctx, AV_LOG_ERROR, "Failed to unmap filter parameter " "buffer: %d (%s).\n", vas, vaErrorStr(vas)); - params.filters = &ctx->filter_buffer; + params.filters = &vpp_ctx->filter_buffers[0]; params.num_filters = 1; params.forward_references = forward_references; @@ -501,53 +300,9 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) params.num_filters = 0; } - vas = vaBeginPicture(ctx->hwctx->display, - ctx->va_context, output_surface); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to attach new picture: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); + err = ff_vaapi_vpp_render_picture(avctx, ¶ms, output_surface); + if (err < 0) goto fail; - } - - vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, - VAProcPipelineParameterBufferType, - sizeof(params), 1, ¶ms, ¶ms_id); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_begin; - } - av_log(avctx, AV_LOG_DEBUG, "Pipeline parameter buffer is %#x.\n", - params_id); - - vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, - ¶ms_id, 1); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to render parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_begin; - } - - vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to start picture processing: " - "%d (%s).\n", vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail_after_render; - } - - if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks & - AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) { - vas = vaDestroyBuffer(ctx->hwctx->display, params_id); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to free parameter buffer: " - "%d (%s).\n", vas, vaErrorStr(vas)); - // And ignore. - } - } err = av_frame_copy_props(output_frame, input_frame); if (err < 0) @@ -573,41 +328,25 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) return err; -fail_after_begin: - vaRenderPicture(ctx->hwctx->display, ctx->va_context, ¶ms_id, 1); -fail_after_render: - vaEndPicture(ctx->hwctx->display, ctx->va_context); fail: if (filter_params_addr) - vaUnmapBuffer(ctx->hwctx->display, ctx->filter_buffer); + vaUnmapBuffer(vpp_ctx->hwctx->display, vpp_ctx->filter_buffers[0]); av_frame_free(&output_frame); return err; } static av_cold int deint_vaapi_init(AVFilterContext *avctx) { - DeintVAAPIContext *ctx = avctx->priv; + VAAPIVPPContext *vpp_ctx = avctx->priv; - ctx->va_config = VA_INVALID_ID; - ctx->va_context = VA_INVALID_ID; - ctx->filter_buffer = VA_INVALID_ID; - ctx->valid_ids = 1; + ff_vaapi_vpp_ctx_init(avctx); + vpp_ctx->pipeline_uninit = deint_vaapi_pipeline_uninit; + vpp_ctx->build_filter_params = deint_vaapi_build_filter_params; + vpp_ctx->output_format = AV_PIX_FMT_NONE; return 0; } -static av_cold void deint_vaapi_uninit(AVFilterContext *avctx) -{ - DeintVAAPIContext *ctx = avctx->priv; - - if (ctx->valid_ids) - deint_vaapi_pipeline_uninit(avctx); - - av_buffer_unref(&ctx->input_frames_ref); - av_buffer_unref(&ctx->output_frames_ref); - av_buffer_unref(&ctx->device_ref); -} - #define OFFSET(x) offsetof(DeintVAAPIContext, x) #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM) static const AVOption deint_vaapi_options[] = { @@ -650,7 +389,7 @@ static const AVFilterPad deint_vaapi_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .filter_frame = &deint_vaapi_filter_frame, - .config_props = &deint_vaapi_config_input, + .config_props = &ff_vaapi_vpp_config_input, }, { NULL } }; @@ -669,8 +408,8 @@ AVFilter ff_vf_deinterlace_vaapi = { .description = NULL_IF_CONFIG_SMALL("Deinterlacing of VAAPI surfaces"), .priv_size = sizeof(DeintVAAPIContext), .init = &deint_vaapi_init, - .uninit = &deint_vaapi_uninit, - .query_formats = &deint_vaapi_query_formats, + .uninit = &ff_vaapi_vpp_ctx_uninit, + .query_formats = &ff_vaapi_vpp_query_formats, .inputs = deint_vaapi_inputs, .outputs = deint_vaapi_outputs, .priv_class = &deint_vaapi_class, From fcf5eae4bf24dac897da34b95cfe23634b9ac5fa Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 8 Jan 2018 16:12:41 +0800 Subject: [PATCH 1709/2557] lavfi: add ProcAmp (color balance) VAAPI video filter. Add ProcAmp(color balance) vaapi video filter, use the option like -vf "procamp_vaapi=b=10:h=120:c=2.8:s=3.7" to set brightness/hue/contrast/saturation. Signed-off-by: Yun Zhou Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- Changelog | 1 + configure | 1 + libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_procamp_vaapi.c | 281 +++++++++++++++++++++++++++++++++ 5 files changed, 285 insertions(+) create mode 100644 libavfilter/vf_procamp_vaapi.c diff --git a/Changelog b/Changelog index 61075b3392297..c7ecfffbb37db 100644 --- a/Changelog +++ b/Changelog @@ -38,6 +38,7 @@ version : - Removed the ffserver program - Removed the ffmenc and ffmdec muxer and demuxer - VideoToolbox HEVC encoder and hwaccel +- VAAPI-accelerated ProcAmp (color balance) filter version 3.4: diff --git a/configure b/configure index 5d533621ae114..12fb34a2026fb 100755 --- a/configure +++ b/configure @@ -3245,6 +3245,7 @@ perspective_filter_deps="gpl" phase_filter_deps="gpl" pp7_filter_deps="gpl" pp_filter_deps="gpl postproc" +procamp_vaapi_filter_deps="vaapi VAProcPipelineParameterBuffer" program_opencl_filter_deps="opencl" pullup_filter_deps="gpl" removelogo_filter_deps="avcodec avformat swscale" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index bbc97a0831270..43d0dd36e6d76 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -275,6 +275,7 @@ OBJS-$(CONFIG_PP_FILTER) += vf_pp.o OBJS-$(CONFIG_PP7_FILTER) += vf_pp7.o OBJS-$(CONFIG_PREMULTIPLY_FILTER) += vf_premultiply.o framesync.o OBJS-$(CONFIG_PREWITT_FILTER) += vf_convolution.o +OBJS-$(CONFIG_PROCAMP_VAAPI_FILTER) += vf_procamp_vaapi.o vaapi_vpp.o OBJS-$(CONFIG_PROGRAM_OPENCL_FILTER) += vf_program_opencl.o opencl.o framesync.o OBJS-$(CONFIG_PSEUDOCOLOR_FILTER) += vf_pseudocolor.o OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o framesync.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 42516bbdf9fc9..63550628e59e5 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -284,6 +284,7 @@ static void register_all(void) REGISTER_FILTER(PP7, pp7, vf); REGISTER_FILTER(PREMULTIPLY, premultiply, vf); REGISTER_FILTER(PREWITT, prewitt, vf); + REGISTER_FILTER(PROCAMP_VAAPI, procamp_vaapi, vf); REGISTER_FILTER(PROGRAM_OPENCL, program_opencl, vf); REGISTER_FILTER(PSEUDOCOLOR, pseudocolor, vf); REGISTER_FILTER(PSNR, psnr, vf); diff --git a/libavfilter/vf_procamp_vaapi.c b/libavfilter/vf_procamp_vaapi.c new file mode 100644 index 0000000000000..10f9a6ba0c6e0 --- /dev/null +++ b/libavfilter/vf_procamp_vaapi.c @@ -0,0 +1,281 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include + +#include "libavutil/avassert.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "vaapi_vpp.h" + +// ProcAmp Min/Max/Default Values +#define BRIGHTNESS_MIN -100.0F +#define BRIGHTNESS_MAX 100.0F +#define BRIGHTNESS_DEFAULT 0.0F + +#define CONTRAST_MIN 0.0F +#define CONTRAST_MAX 10.0F +#define CONTRAST_DEFAULT 1.0F + +#define HUE_MIN -180.0F +#define HUE_MAX 180.0F +#define HUE_DEFAULT 0.0F + +#define SATURATION_MIN 0.0F +#define SATURATION_MAX 10.0F +#define SATURATION_DEFAULT 1.0F + +#define EPSILON 0.00001F + +typedef struct ProcampVAAPIContext { + VAAPIVPPContext vpp_ctx; // must be the first fileld + + float bright; + float hue; + float saturation; + float contrast; +} ProcampVAAPIContext; + +static float map(float x, float in_min, float in_max, float out_min, float out_max) +{ + double slope, output; + + slope = 1.0 * (out_max - out_min) / (in_max - in_min); + output = out_min + slope * (x - in_min); + + return (float)output; +} + +static int fequal(float a, float b) +{ + return fabs(a-b) < EPSILON; +} + +static int procamp_vaapi_build_filter_params(AVFilterContext *avctx) +{ + VAAPIVPPContext *vpp_ctx = avctx->priv; + ProcampVAAPIContext *ctx = avctx->priv; + VAStatus vas; + VAProcFilterParameterBufferColorBalance procamp_params[4]; + VAProcFilterCapColorBalance procamp_caps[VAProcColorBalanceCount]; + int num_caps; + int i = 0; + + memset(&procamp_params, 0, sizeof(procamp_params)); + memset(&procamp_caps, 0, sizeof(procamp_caps)); + + num_caps = VAProcColorBalanceCount; + vas = vaQueryVideoProcFilterCaps(vpp_ctx->hwctx->display, vpp_ctx->va_context, + VAProcFilterColorBalance, &procamp_caps, &num_caps); + + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query procamp " + "filter caps: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + + if (!fequal(ctx->bright, BRIGHTNESS_DEFAULT)) { + procamp_params[i].type = VAProcFilterColorBalance; + procamp_params[i].attrib = VAProcColorBalanceBrightness; + procamp_params[i].value = map(ctx->bright, BRIGHTNESS_MIN, BRIGHTNESS_MAX, + procamp_caps[VAProcColorBalanceBrightness-1].range.min_value, + procamp_caps[VAProcColorBalanceBrightness-1].range.max_value); + i++; + } + + if (!fequal(ctx->contrast, CONTRAST_DEFAULT)) { + procamp_params[i].type = VAProcFilterColorBalance; + procamp_params[i].attrib = VAProcColorBalanceContrast; + procamp_params[i].value = map(ctx->contrast, CONTRAST_MIN, CONTRAST_MAX, + procamp_caps[VAProcColorBalanceContrast-1].range.min_value, + procamp_caps[VAProcColorBalanceContrast-1].range.max_value); + i++; + } + + if (!fequal(ctx->hue, HUE_DEFAULT)) { + procamp_params[i].type = VAProcFilterColorBalance; + procamp_params[i].attrib = VAProcColorBalanceHue; + procamp_params[i].value = map(ctx->hue, HUE_MIN, HUE_MAX, + procamp_caps[VAProcColorBalanceHue-1].range.min_value, + procamp_caps[VAProcColorBalanceHue-1].range.max_value); + i++; + } + + if (!fequal(ctx->saturation, SATURATION_DEFAULT)) { + procamp_params[i].type = VAProcFilterColorBalance; + procamp_params[i].attrib = VAProcColorBalanceSaturation; + procamp_params[i].value = map(ctx->saturation, SATURATION_MIN, SATURATION_MAX, + procamp_caps[VAProcColorBalanceSaturation-1].range.min_value, + procamp_caps[VAProcColorBalanceSaturation-1].range.max_value); + i++; + } + + return ff_vaapi_vpp_make_param_buffers(avctx, + VAProcFilterParameterBufferType, + &procamp_params, + sizeof(procamp_params[0]), + i); +} + +static int procamp_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) +{ + AVFilterContext *avctx = inlink->dst; + AVFilterLink *outlink = avctx->outputs[0]; + VAAPIVPPContext *vpp_ctx = avctx->priv; + AVFrame *output_frame = NULL; + VASurfaceID input_surface, output_surface; + VAProcPipelineParameterBuffer params; + VARectangle input_region; + int err; + + av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(input_frame->format), + input_frame->width, input_frame->height, input_frame->pts); + + if (vpp_ctx->va_context == VA_INVALID_ID) + return AVERROR(EINVAL); + + input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3]; + av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for procamp input.\n", + input_surface); + + output_frame = ff_get_video_buffer(outlink, vpp_ctx->output_width, + vpp_ctx->output_height); + if (!output_frame) { + err = AVERROR(ENOMEM); + goto fail; + } + + output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3]; + av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for procamp output.\n", + output_surface); + memset(¶ms, 0, sizeof(params)); + input_region = (VARectangle) { + .x = 0, + .y = 0, + .width = input_frame->width, + .height = input_frame->height, + }; + + params.surface = input_surface; + params.surface_region = &input_region; + params.surface_color_standard = + ff_vaapi_vpp_colour_standard(input_frame->colorspace); + + params.output_region = NULL; + params.output_background_color = 0xff000000; + params.output_color_standard = params.surface_color_standard; + + params.pipeline_flags = 0; + params.filter_flags = VA_FRAME_PICTURE; + + params.filters = &vpp_ctx->filter_buffers[0]; + params.num_filters = 1; + + err = ff_vaapi_vpp_render_picture(avctx, ¶ms, output_surface); + if (err < 0) + goto fail; + + err = av_frame_copy_props(output_frame, input_frame); + if (err < 0) + goto fail; + av_frame_free(&input_frame); + + av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(output_frame->format), + output_frame->width, output_frame->height, output_frame->pts); + + return ff_filter_frame(outlink, output_frame); + +fail: + av_frame_free(&input_frame); + av_frame_free(&output_frame); + return err; +} + +static av_cold int procamp_vaapi_init(AVFilterContext *avctx) +{ + VAAPIVPPContext *vpp_ctx = avctx->priv; + + ff_vaapi_vpp_ctx_init(avctx); + vpp_ctx->pipeline_uninit = ff_vaapi_vpp_pipeline_uninit; + vpp_ctx->build_filter_params = procamp_vaapi_build_filter_params; + vpp_ctx->output_format = AV_PIX_FMT_NONE; + + return 0; +} + +#define OFFSET(x) offsetof(ProcampVAAPIContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption procamp_vaapi_options[] = { + { "b", "Output video brightness", + OFFSET(bright), AV_OPT_TYPE_FLOAT, { .dbl = BRIGHTNESS_DEFAULT }, BRIGHTNESS_MIN, BRIGHTNESS_MAX, .flags = FLAGS }, + { "brightness", "Output video brightness", + OFFSET(bright), AV_OPT_TYPE_FLOAT, { .dbl = BRIGHTNESS_DEFAULT }, BRIGHTNESS_MIN, BRIGHTNESS_MAX, .flags = FLAGS }, + { "s", "Output video saturation", + OFFSET(saturation), AV_OPT_TYPE_FLOAT, { .dbl = SATURATION_DEFAULT }, SATURATION_MIN, SATURATION_MAX, .flags = FLAGS }, + { "saturatio", "Output video saturation", + OFFSET(saturation), AV_OPT_TYPE_FLOAT, { .dbl = SATURATION_DEFAULT }, SATURATION_MIN, SATURATION_MAX, .flags = FLAGS }, + { "c", "Output video contrast", + OFFSET(contrast), AV_OPT_TYPE_FLOAT, { .dbl = CONTRAST_DEFAULT }, CONTRAST_MIN, CONTRAST_MAX, .flags = FLAGS }, + { "contrast", "Output video contrast", + OFFSET(contrast), AV_OPT_TYPE_FLOAT, { .dbl = CONTRAST_DEFAULT }, CONTRAST_MIN, CONTRAST_MAX, .flags = FLAGS }, + { "h", "Output video hue", + OFFSET(hue), AV_OPT_TYPE_FLOAT, { .dbl = HUE_DEFAULT }, HUE_MIN, HUE_MAX, .flags = FLAGS }, + { "hue", "Output video hue", + OFFSET(hue), AV_OPT_TYPE_FLOAT, { .dbl = HUE_DEFAULT }, HUE_MIN, HUE_MAX, .flags = FLAGS }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(procamp_vaapi); + +static const AVFilterPad procamp_vaapi_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &procamp_vaapi_filter_frame, + .config_props = &ff_vaapi_vpp_config_input, + }, + { NULL } +}; + +static const AVFilterPad procamp_vaapi_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vaapi_vpp_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_procamp_vaapi = { + .name = "procamp_vaapi", + .description = NULL_IF_CONFIG_SMALL("ProcAmp (color balance) adjustments for hue, saturation, brightness, contrast"), + .priv_size = sizeof(ProcampVAAPIContext), + .init = &procamp_vaapi_init, + .uninit = &ff_vaapi_vpp_ctx_uninit, + .query_formats = &ff_vaapi_vpp_query_formats, + .inputs = procamp_vaapi_inputs, + .outputs = procamp_vaapi_outputs, + .priv_class = &procamp_vaapi_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From 9bba10c174c893b08b036898a522ed6dad1d3660 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 8 Jan 2018 16:19:17 +0800 Subject: [PATCH 1710/2557] lavfi: add denoise and sharpness VAAPI video filters. Most code between them is common, so put them in a new file for miscellaneous VAAPI filters. Signed-off-by: Yun Zhou Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- Changelog | 2 +- configure | 2 + libavfilter/Makefile | 2 + libavfilter/allfilters.c | 2 + libavfilter/vf_misc_vaapi.c | 293 ++++++++++++++++++++++++++++++++++++ 5 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_misc_vaapi.c diff --git a/Changelog b/Changelog index c7ecfffbb37db..7a73447a6b5fd 100644 --- a/Changelog +++ b/Changelog @@ -38,7 +38,7 @@ version : - Removed the ffserver program - Removed the ffmenc and ffmdec muxer and demuxer - VideoToolbox HEVC encoder and hwaccel -- VAAPI-accelerated ProcAmp (color balance) filter +- VAAPI-accelerated ProcAmp (color balance), denoise and sharpness filters version 3.4: diff --git a/configure b/configure index 12fb34a2026fb..24c4f672a3493 100755 --- a/configure +++ b/configure @@ -3204,6 +3204,7 @@ deconvolve_filter_select="fft" deinterlace_qsv_filter_deps="libmfx" deinterlace_vaapi_filter_deps="vaapi" delogo_filter_deps="gpl" +denoise_vaapi_filter_deps="vaapi VAProcPipelineParameterBuffer" deshake_filter_select="pixelutils" drawtext_filter_deps="libfreetype" drawtext_filter_suggest="libfontconfig libfribidi" @@ -3257,6 +3258,7 @@ scale2ref_filter_deps="swscale" scale_filter_deps="swscale" scale_qsv_filter_deps="libmfx" select_filter_select="pixelutils" +sharpness_vaapi_filter_deps="vaapi VAProcPipelineParameterBuffer" showcqt_filter_deps="avcodec avformat swscale" showcqt_filter_suggest="libfontconfig libfreetype" showcqt_filter_select="fft" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 43d0dd36e6d76..34971ce6c1f04 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -174,6 +174,7 @@ OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER) += vf_deinterlace_qsv.o OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER) += vf_deinterlace_vaapi.o vaapi_vpp.o OBJS-$(CONFIG_DEJUDDER_FILTER) += vf_dejudder.o OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o +OBJS-$(CONFIG_DENOISE_VAAPI_FILTER) += vf_misc_vaapi.o vaapi_vpp.o OBJS-$(CONFIG_DESHAKE_FILTER) += vf_deshake.o OBJS-$(CONFIG_DESPILL_FILTER) += vf_despill.o OBJS-$(CONFIG_DETELECINE_FILTER) += vf_detelecine.o @@ -309,6 +310,7 @@ OBJS-$(CONFIG_SETPTS_FILTER) += setpts.o OBJS-$(CONFIG_SETRANGE_FILTER) += vf_setparams.o OBJS-$(CONFIG_SETSAR_FILTER) += vf_aspect.o OBJS-$(CONFIG_SETTB_FILTER) += settb.o +OBJS-$(CONFIG_SHARPNESS_VAAPI_FILTER) += vf_misc_vaapi.o vaapi_vpp.o OBJS-$(CONFIG_SHOWINFO_FILTER) += vf_showinfo.o OBJS-$(CONFIG_SHOWPALETTE_FILTER) += vf_showpalette.o OBJS-$(CONFIG_SHUFFLEFRAMES_FILTER) += vf_shuffleframes.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 63550628e59e5..9adb1090b7c35 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -184,6 +184,7 @@ static void register_all(void) REGISTER_FILTER(DEINTERLACE_VAAPI, deinterlace_vaapi, vf); REGISTER_FILTER(DEJUDDER, dejudder, vf); REGISTER_FILTER(DELOGO, delogo, vf); + REGISTER_FILTER(DENOISE_VAAPI, denoise_vaapi, vf); REGISTER_FILTER(DESHAKE, deshake, vf); REGISTER_FILTER(DESPILL, despill, vf); REGISTER_FILTER(DETELECINE, detelecine, vf); @@ -318,6 +319,7 @@ static void register_all(void) REGISTER_FILTER(SETRANGE, setrange, vf); REGISTER_FILTER(SETSAR, setsar, vf); REGISTER_FILTER(SETTB, settb, vf); + REGISTER_FILTER(SHARPNESS_VAAPI, sharpness_vaapi, vf); REGISTER_FILTER(SHOWINFO, showinfo, vf); REGISTER_FILTER(SHOWPALETTE, showpalette, vf); REGISTER_FILTER(SHUFFLEFRAMES, shuffleframes, vf); diff --git a/libavfilter/vf_misc_vaapi.c b/libavfilter/vf_misc_vaapi.c new file mode 100644 index 0000000000000..316f15e38b545 --- /dev/null +++ b/libavfilter/vf_misc_vaapi.c @@ -0,0 +1,293 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include + +#include "libavutil/avassert.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "vaapi_vpp.h" + +// Denoise min/max/default Values +#define DENOISE_MIN 0 +#define DENOISE_MAX 64 +#define DENOISE_DEFAULT 0 + +// Sharpness min/max/default values +#define SHARPNESS_MIN 0 +#define SHARPNESS_MAX 64 +#define SHARPNESS_DEFAULT 44 + +typedef struct DenoiseVAAPIContext { + VAAPIVPPContext vpp_ctx; // must be the first fileld + + int denoise; // enable denoise algo. +} DenoiseVAAPIContext; + +typedef struct SharpnessVAAPIContext { + VAAPIVPPContext vpp_ctx; // must be the first fileld + + int sharpness; // enable sharpness. +} SharpnessVAAPIContext; + +static float map(int x, int in_min, int in_max, float out_min, float out_max) +{ + double slope, output; + + slope = 1.0 * (out_max - out_min) / (in_max - in_min); + output = out_min + slope * (x - in_min); + + return (float)output; +} + +static int denoise_vaapi_build_filter_params(AVFilterContext *avctx) +{ + VAAPIVPPContext *vpp_ctx = avctx->priv; + DenoiseVAAPIContext *ctx = avctx->priv; + + VAProcFilterCap caps; + + VAStatus vas; + uint32_t num_caps = 1; + + VAProcFilterParameterBuffer denoise; + + if (ctx->denoise != DENOISE_DEFAULT) { + vas = vaQueryVideoProcFilterCaps(vpp_ctx->hwctx->display, vpp_ctx->va_context, + VAProcFilterNoiseReduction, + &caps, &num_caps); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query denoise caps " + "context: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + + denoise.type = VAProcFilterNoiseReduction; + denoise.value = map(ctx->denoise, DENOISE_MIN, DENOISE_MAX, + caps.range.min_value, + caps.range.max_value); + ff_vaapi_vpp_make_param_buffers(avctx, VAProcFilterParameterBufferType, + &denoise, sizeof(denoise), 1); + } + + return 0; +} + +static int sharpness_vaapi_build_filter_params(AVFilterContext *avctx) +{ + VAAPIVPPContext *vpp_ctx = avctx->priv; + SharpnessVAAPIContext *ctx = avctx->priv; + + VAProcFilterCap caps; + + VAStatus vas; + uint32_t num_caps = 1; + + VAProcFilterParameterBuffer sharpness; + + if (ctx->sharpness != SHARPNESS_DEFAULT) { + vas = vaQueryVideoProcFilterCaps(vpp_ctx->hwctx->display, vpp_ctx->va_context, + VAProcFilterSharpening, + &caps, &num_caps); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query sharpness caps " + "context: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + + sharpness.type = VAProcFilterSharpening; + sharpness.value = map(ctx->sharpness, + SHARPNESS_MIN, SHARPNESS_MAX, + caps.range.min_value, + caps.range.max_value); + ff_vaapi_vpp_make_param_buffers(avctx, + VAProcFilterParameterBufferType, + &sharpness, sizeof(sharpness), 1); + } + + return 0; +} + +static int misc_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) +{ + AVFilterContext *avctx = inlink->dst; + AVFilterLink *outlink = avctx->outputs[0]; + VAAPIVPPContext *vpp_ctx = avctx->priv; + AVFrame *output_frame = NULL; + VASurfaceID input_surface, output_surface; + VARectangle input_region; + + VAProcPipelineParameterBuffer params; + int err; + + av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(input_frame->format), + input_frame->width, input_frame->height, input_frame->pts); + + if (vpp_ctx->va_context == VA_INVALID_ID) + return AVERROR(EINVAL); + + input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3]; + av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp input.\n", + input_surface); + + output_frame = ff_get_video_buffer(outlink, vpp_ctx->output_width, + vpp_ctx->output_height); + if (!output_frame) { + err = AVERROR(ENOMEM); + goto fail; + } + + output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3]; + av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp output.\n", + output_surface); + memset(¶ms, 0, sizeof(params)); + input_region = (VARectangle) { + .x = 0, + .y = 0, + .width = input_frame->width, + .height = input_frame->height, + }; + + if (vpp_ctx->nb_filter_buffers) { + params.filters = &vpp_ctx->filter_buffers[0]; + params.num_filters = vpp_ctx->nb_filter_buffers; + } + params.surface = input_surface; + params.surface_region = &input_region; + params.surface_color_standard = + ff_vaapi_vpp_colour_standard(input_frame->colorspace); + + params.output_region = NULL; + params.output_background_color = 0xff000000; + params.output_color_standard = params.surface_color_standard; + + params.pipeline_flags = 0; + params.filter_flags = VA_FRAME_PICTURE; + + err = ff_vaapi_vpp_render_picture(avctx, ¶ms, output_surface); + if (err < 0) + goto fail; + + err = av_frame_copy_props(output_frame, input_frame); + if (err < 0) + goto fail; + av_frame_free(&input_frame); + + av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(output_frame->format), + output_frame->width, output_frame->height, output_frame->pts); + + return ff_filter_frame(outlink, output_frame); + +fail: + av_frame_free(&input_frame); + av_frame_free(&output_frame); + return err; +} + +static av_cold int denoise_vaapi_init(AVFilterContext *avctx) +{ + VAAPIVPPContext *vpp_ctx = avctx->priv; + + ff_vaapi_vpp_ctx_init(avctx); + vpp_ctx->pipeline_uninit = ff_vaapi_vpp_pipeline_uninit; + vpp_ctx->build_filter_params = denoise_vaapi_build_filter_params; + vpp_ctx->output_format = AV_PIX_FMT_NONE; + + return 0; +} + +static av_cold int sharpness_vaapi_init(AVFilterContext *avctx) +{ + VAAPIVPPContext *vpp_ctx = avctx->priv; + + ff_vaapi_vpp_ctx_init(avctx); + vpp_ctx->pipeline_uninit = ff_vaapi_vpp_pipeline_uninit; + vpp_ctx->build_filter_params = sharpness_vaapi_build_filter_params; + vpp_ctx->output_format = AV_PIX_FMT_NONE; + + return 0; +} + +#define DOFFSET(x) offsetof(DenoiseVAAPIContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption denoise_vaapi_options[] = { + { "denoise", "denoise level", + DOFFSET(denoise), AV_OPT_TYPE_INT, { .i64 = DENOISE_DEFAULT }, DENOISE_MIN, DENOISE_MAX, .flags = FLAGS }, + { NULL }, +}; + +#define SOFFSET(x) offsetof(SharpnessVAAPIContext, x) +static const AVOption sharpness_vaapi_options[] = { + { "sharpness", "sharpness level", + SOFFSET(sharpness), AV_OPT_TYPE_INT, { .i64 = SHARPNESS_DEFAULT }, SHARPNESS_MIN, SHARPNESS_MAX, .flags = FLAGS }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(denoise_vaapi); +AVFILTER_DEFINE_CLASS(sharpness_vaapi); + +static const AVFilterPad misc_vaapi_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &misc_vaapi_filter_frame, + .config_props = &ff_vaapi_vpp_config_input, + }, + { NULL } +}; + +static const AVFilterPad misc_vaapi_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vaapi_vpp_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_denoise_vaapi = { + .name = "denoise_vaapi", + .description = NULL_IF_CONFIG_SMALL("VAAPI VPP for de-noise"), + .priv_size = sizeof(DenoiseVAAPIContext), + .init = &denoise_vaapi_init, + .uninit = &ff_vaapi_vpp_ctx_uninit, + .query_formats = &ff_vaapi_vpp_query_formats, + .inputs = misc_vaapi_inputs, + .outputs = misc_vaapi_outputs, + .priv_class = &denoise_vaapi_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; + +AVFilter ff_vf_sharpness_vaapi = { + .name = "sharpness_vaapi", + .description = NULL_IF_CONFIG_SMALL("VAAPI VPP for sharpness"), + .priv_size = sizeof(SharpnessVAAPIContext), + .init = &sharpness_vaapi_init, + .uninit = &ff_vaapi_vpp_ctx_uninit, + .query_formats = &ff_vaapi_vpp_query_formats, + .inputs = misc_vaapi_inputs, + .outputs = misc_vaapi_outputs, + .priv_class = &sharpness_vaapi_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From bda5ad305e907d6e5eaa6abbb1b3bc1590ec20d8 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 21 Jan 2018 22:59:29 +0000 Subject: [PATCH 1711/2557] v4l2_m2m: Fix free of the wrong pointer in an error path Fixes CIDs #1427821 and #1427822. --- libavcodec/v4l2_m2m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/v4l2_m2m.c b/libavcodec/v4l2_m2m.c index fd989ce60156b..427e165f586f9 100644 --- a/libavcodec/v4l2_m2m.c +++ b/libavcodec/v4l2_m2m.c @@ -390,7 +390,7 @@ int ff_v4l2_m2m_create_context(AVCodecContext *avctx, V4L2m2mContext **s) priv->context_ref = av_buffer_create((uint8_t *) *s, sizeof(V4L2m2mContext), &v4l2_m2m_destroy_context, NULL, 0); if (!priv->context_ref) { - av_free(s); + av_freep(s); return AVERROR(ENOMEM); } From 388a0f7869a852dec51482dc1802239f792775db Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 21 Jan 2018 22:57:41 -0300 Subject: [PATCH 1712/2557] avcodec/mpeg12dec: fix preprocessor check for mpeg1_nvdec hwaccel Signed-off-by: James Almer --- libavcodec/mpeg12dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index ac5ac4bca4d0d..f5f2c696c05c5 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -2893,7 +2893,7 @@ AVCodec ff_mpeg1video_decoder = { .max_lowres = 3, .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg_decode_update_thread_context), .hw_configs = (const AVCodecHWConfigInternal*[]) { -#if CONFIG_MPEG2_NVDEC_HWACCEL +#if CONFIG_MPEG1_NVDEC_HWACCEL HWACCEL_NVDEC(mpeg1), #endif #if CONFIG_MPEG1_VDPAU_HWACCEL From 2e96f5278095d44f090a4d89507e62d27cccf3b9 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 21 Jan 2018 00:52:18 +0000 Subject: [PATCH 1713/2557] v4l2_m2m: Fix integer overflow in timestamp handling --- libavcodec/v4l2_buffers.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index 8e4d4d1c9fa72..aef911f3bbcff 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -69,7 +69,8 @@ static inline uint64_t v4l2_get_pts(V4L2Buffer *avbuf) int64_t v4l2_pts; /* convert pts back to encoder timebase */ - v4l2_pts = avbuf->buf.timestamp.tv_sec * USEC_PER_SEC + avbuf->buf.timestamp.tv_usec; + v4l2_pts = (int64_t)avbuf->buf.timestamp.tv_sec * USEC_PER_SEC + + avbuf->buf.timestamp.tv_usec; return av_rescale_q(v4l2_pts, v4l2_timebase, s->avctx->time_base); } From 9b1ec248350405e1da64eecad620a8d7a4ee6caa Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Tue, 23 Jan 2018 09:41:29 +0100 Subject: [PATCH 1714/2557] avcodec: v4l2_context: remove unnecessary code Fixes CID 1418358 Signed-off-by: Jorge Ramirez-Ortiz --- libavcodec/v4l2_context.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index e0431b1b3e359..efcb0426e4906 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -446,9 +446,7 @@ static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p) if (pixfmt != AV_PIX_FMT_NONE) { ret = v4l2_try_raw_format(ctx, pixfmt); - if (ret) - pixfmt = AV_PIX_FMT_NONE; - else + if (!ret) return 0; } From 9f07cf7c00f3a87669c27aec947daf0f3d33b01f Mon Sep 17 00:00:00 2001 From: Jacob Trimble Date: Mon, 8 Jan 2018 14:12:43 -0800 Subject: [PATCH 1715/2557] avutil/aes_ctr: Add method to set 16-byte IV. Signed-off-by: Jacob Trimble Signed-off-by: Michael Niedermayer --- doc/APIchanges | 3 +++ libavutil/aes_ctr.c | 6 ++++++ libavutil/aes_ctr.h | 7 ++++++- libavutil/tests/aes_ctr.c | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 76993658794e5..c27f104c951c0 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-xx-xx - xxxxxxx - lavu 56.9.100 - aes_ctr.h + Add method to set the 16-byte IV. + 2018-01-xx - xxxxxxx - lavf 58.5.100 - avformat.h Explicitly make avformat_network_init() and avformat_network_deinit() optional. If these are not called, network initialization and deinitialization is diff --git a/libavutil/aes_ctr.c b/libavutil/aes_ctr.c index e9c568fe0d13d..0c2e86785f1bb 100644 --- a/libavutil/aes_ctr.c +++ b/libavutil/aes_ctr.c @@ -45,6 +45,12 @@ void av_aes_ctr_set_iv(struct AVAESCTR *a, const uint8_t* iv) a->block_offset = 0; } +void av_aes_ctr_set_full_iv(struct AVAESCTR *a, const uint8_t* iv) +{ + memcpy(a->counter, iv, sizeof(a->counter)); + a->block_offset = 0; +} + const uint8_t* av_aes_ctr_get_iv(struct AVAESCTR *a) { return a->counter; diff --git a/libavutil/aes_ctr.h b/libavutil/aes_ctr.h index f596fa6a46bac..e4aae126a764b 100644 --- a/libavutil/aes_ctr.h +++ b/libavutil/aes_ctr.h @@ -67,10 +67,15 @@ const uint8_t* av_aes_ctr_get_iv(struct AVAESCTR *a); void av_aes_ctr_set_random_iv(struct AVAESCTR *a); /** - * Forcefully change the iv + * Forcefully change the 8-byte iv */ void av_aes_ctr_set_iv(struct AVAESCTR *a, const uint8_t* iv); +/** + * Forcefully change the "full" 16-byte iv, including the counter + */ +void av_aes_ctr_set_full_iv(struct AVAESCTR *a, const uint8_t* iv); + /** * Increment the top 64 bit of the iv (performed after each frame) */ diff --git a/libavutil/tests/aes_ctr.c b/libavutil/tests/aes_ctr.c index c5ebeda7ac209..00fdb05d13a01 100644 --- a/libavutil/tests/aes_ctr.c +++ b/libavutil/tests/aes_ctr.c @@ -45,7 +45,7 @@ int main (void) av_aes_ctr_set_random_iv(ae); iv = av_aes_ctr_get_iv(ae); - av_aes_ctr_set_iv(ad, iv); + av_aes_ctr_set_full_iv(ad, iv); av_aes_ctr_crypt(ae, tmp, plain, sizeof(tmp)); av_aes_ctr_crypt(ad, tmp, tmp, sizeof(tmp)); From 94d4237a7a294ce80e1e577b38e9c93e8882aff9 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 15 Jan 2018 23:42:57 +0100 Subject: [PATCH 1716/2557] avcodec/hevc_cabac: Move prefix check in coeff_abs_level_remaining_decode() down Signed-off-by: Michael Niedermayer --- libavcodec/hevc_cabac.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c index 5b5da1165a786..743168500c7b8 100644 --- a/libavcodec/hevc_cabac.c +++ b/libavcodec/hevc_cabac.c @@ -990,16 +990,19 @@ static av_always_inline int coeff_abs_level_remaining_decode(HEVCContext *s, int while (prefix < CABAC_MAX_BIN && get_cabac_bypass(&s->HEVClc->cc)) prefix++; - if (prefix == CABAC_MAX_BIN) { - av_log(s->avctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", prefix); - return 0; - } + if (prefix < 3) { for (i = 0; i < rc_rice_param; i++) suffix = (suffix << 1) | get_cabac_bypass(&s->HEVClc->cc); last_coeff_abs_level_remaining = (prefix << rc_rice_param) + suffix; } else { int prefix_minus3 = prefix - 3; + + if (prefix == CABAC_MAX_BIN) { + av_log(s->avctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", prefix); + return 0; + } + for (i = 0; i < prefix_minus3 + rc_rice_param; i++) suffix = (suffix << 1) | get_cabac_bypass(&s->HEVClc->cc); last_coeff_abs_level_remaining = (((1 << prefix_minus3) + 3 - 1) From 6e1a167c5564085385488b4f579e9efb987d4bfa Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 22 Jan 2018 14:02:59 +0100 Subject: [PATCH 1717/2557] avcodec/dxtory: Fix bits left checks Fixes: Timeout Fixes: 4863/clusterfuzz-testcase-6347354178322432 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/dxtory.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/dxtory.c b/libavcodec/dxtory.c index 6f8652ad499db..e736cec8dbb43 100644 --- a/libavcodec/dxtory.c +++ b/libavcodec/dxtory.c @@ -326,7 +326,7 @@ static int dx2_decode_slice_5x5(GetBitContext *gb, AVFrame *frame, int stride = frame->linesize[0]; uint8_t *dst = frame->data[0] + stride * line; - for (y = 0; y < left && get_bits_left(gb) > 16; y++) { + for (y = 0; y < left && get_bits_left(gb) > 6 * width; y++) { for (x = 0; x < width; x++) { b = decode_sym_565(gb, lru[0], 5); g = decode_sym_565(gb, lru[1], is_565 ? 6 : 5); @@ -392,7 +392,7 @@ static int dx2_decode_slice_rgb(GetBitContext *gb, AVFrame *frame, int stride = frame->linesize[0]; uint8_t *dst = frame->data[0] + stride * line; - for (y = 0; y < left && get_bits_left(gb) > 16; y++) { + for (y = 0; y < left && get_bits_left(gb) > 6 * width; y++) { for (x = 0; x < width; x++) { dst[x * 3 + 0] = decode_sym(gb, lru[0]); dst[x * 3 + 1] = decode_sym(gb, lru[1]); @@ -437,7 +437,7 @@ static int dx2_decode_slice_410(GetBitContext *gb, AVFrame *frame, uint8_t *U = frame->data[1] + (ustride >> 2) * line; uint8_t *V = frame->data[2] + (vstride >> 2) * line; - for (y = 0; y < left - 3 && get_bits_left(gb) > 16; y += 4) { + for (y = 0; y < left - 3 && get_bits_left(gb) > 9 * width; y += 4) { for (x = 0; x < width; x += 4) { for (j = 0; j < 4; j++) for (i = 0; i < 4; i++) @@ -481,7 +481,7 @@ static int dx2_decode_slice_420(GetBitContext *gb, AVFrame *frame, uint8_t *V = frame->data[2] + (vstride >> 1) * line; - for (y = 0; y < left - 1 && get_bits_left(gb) > 16; y += 2) { + for (y = 0; y < left - 1 && get_bits_left(gb) > 6 * width; y += 2) { for (x = 0; x < width; x += 2) { Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]); Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]); @@ -524,7 +524,7 @@ static int dx2_decode_slice_444(GetBitContext *gb, AVFrame *frame, uint8_t *U = frame->data[1] + ustride * line; uint8_t *V = frame->data[2] + vstride * line; - for (y = 0; y < left && get_bits_left(gb) > 16; y++) { + for (y = 0; y < left && get_bits_left(gb) > 6 * width; y++) { for (x = 0; x < width; x++) { Y[x] = decode_sym(gb, lru[0]); U[x] = decode_sym(gb, lru[1]) ^ 0x80; From 046a9468688a74cf107bfd425ad9e1d7b9d3890b Mon Sep 17 00:00:00 2001 From: Karthick Jeyapal Date: Tue, 23 Jan 2018 23:24:35 +0100 Subject: [PATCH 1718/2557] MAINTAINERS: Add dashenc maintainer If somebody else wants to maintain dashenc either now or in future, I am absolutely fine with giving up this responsibility anytime. But till then we need a maintainer for dashenc, and I am volunteering for that task. Signed-off-by: Michael Niedermayer --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index d0de26c4f70d3..ba7a7284eb826 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -395,6 +395,7 @@ Muxers/Demuxers: cdxl.c Paul B Mahol crc.c Michael Niedermayer dashdec.c Steven Liu + dashenc.c Karthick Jeyapal daud.c Reimar Doeffinger dss.c Oleksij Rempel dtsdec.c foo86 From 172564ace9c535e2848edb8d17df926578a458b9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 23 Jan 2018 23:37:33 -0300 Subject: [PATCH 1719/2557] configure: fix vaapi_encode_example dependencies Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 24c4f672a3493..fcfa7aa4422ef 100755 --- a/configure +++ b/configure @@ -3319,7 +3319,7 @@ resampling_audio_example_deps="avutil swresample" scaling_video_example_deps="avutil swscale" transcode_aac_example_deps="avcodec avformat swresample" transcoding_example_deps="avfilter avcodec avformat avutil" -vaapi_encode_example_deps="avcodec avutil" +vaapi_encode_example_deps="avcodec avutil h264_vaapi_encoder" # EXTRALIBS_LIST cpu_init_extralibs="pthreads_extralibs" From f0320afab977edc7b73317c8ef36ff1d60296401 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 23 Jan 2018 23:38:03 -0300 Subject: [PATCH 1720/2557] avfilter/Makefile: skip compiling vaapi_vpp.h when vaapi is not enabled Fixes make checkheaders Signed-off-by: James Almer --- libavfilter/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 34971ce6c1f04..6a6083618d3fb 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -413,6 +413,7 @@ OBJS-$(CONFIG_SHARED) += log2_tab.o SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h +SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h TOOLS = graph2dot TESTPROGS = drawutils filtfmts formats integral From 8a4cc0a2567fa8418709f75af5539cdf76fefb99 Mon Sep 17 00:00:00 2001 From: Richard Shaffer Date: Tue, 23 Jan 2018 09:39:53 -0800 Subject: [PATCH 1721/2557] avformat: add option to parse/store ID3 PRIV tags in metadata. Enables getting access to ID3 PRIV tags from the command-line or metadata API when demuxing. The PRIV owner is stored as the metadata key prepended with "id3v2_priv.", and the data is stored as the metadata value. As PRIV tags may contain arbitrary data, non-printable characters, including NULL bytes, are escaped as \xXX. Similarly, any metadata tags that begin with "id3v2_priv." are inserted as ID3 PRIV tags into the output (assuming the format supports ID3). \xXX sequences in the value are un-escaped to their byte value. Signed-off-by: wm4 --- libavformat/id3v2.c | 48 +++++++++++++++++++++++++++++++++ libavformat/id3v2.h | 15 +++++++++++ libavformat/id3v2enc.c | 60 ++++++++++++++++++++++++++++++++++++++++++ libavformat/utils.c | 2 ++ libavformat/version.h | 2 +- 5 files changed, 126 insertions(+), 1 deletion(-) diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index 6c216ba7a251a..b80178d67a093 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -33,6 +33,7 @@ #endif #include "libavutil/avstring.h" +#include "libavutil/bprint.h" #include "libavutil/dict.h" #include "libavutil/intreadwrite.h" #include "avio_internal.h" @@ -1224,3 +1225,50 @@ int ff_id3v2_parse_chapters(AVFormatContext *s, ID3v2ExtraMeta **extra_meta) av_freep(&chapters); return ret; } + +int ff_id3v2_parse_priv_dict(AVDictionary **metadata, ID3v2ExtraMeta **extra_meta) +{ + ID3v2ExtraMeta *cur; + int dict_flags = AV_DICT_DONT_OVERWRITE | AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL; + + for (cur = *extra_meta; cur; cur = cur->next) { + if (!strcmp(cur->tag, "PRIV")) { + ID3v2ExtraMetaPRIV *priv = cur->data; + AVBPrint bprint; + char *escaped, *key; + int i, ret; + + if ((key = av_asprintf(ID3v2_PRIV_METADATA_PREFIX "%s", priv->owner)) == NULL) { + return AVERROR(ENOMEM); + } + + av_bprint_init(&bprint, priv->datasize + 1, AV_BPRINT_SIZE_UNLIMITED); + + for (i = 0; i < priv->datasize; i++) { + if (priv->data[i] < 32 || priv->data[i] > 126 || priv->data[i] == '\\') { + av_bprintf(&bprint, "\\x%02x", priv->data[i]); + } else { + av_bprint_chars(&bprint, priv->data[i], 1); + } + } + + if ((ret = av_bprint_finalize(&bprint, &escaped)) < 0) { + av_free(key); + return ret; + } + + if ((ret = av_dict_set(metadata, key, escaped, dict_flags)) < 0) { + av_free(key); + av_free(escaped); + return ret; + } + } + } + + return 0; +} + +int ff_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta **extra_meta) +{ + return ff_id3v2_parse_priv_dict(&s->metadata, extra_meta); +} diff --git a/libavformat/id3v2.h b/libavformat/id3v2.h index 5e64ead096a82..9de0bee374380 100644 --- a/libavformat/id3v2.h +++ b/libavformat/id3v2.h @@ -39,6 +39,8 @@ #define ID3v2_FLAG_ENCRYPTION 0x0004 #define ID3v2_FLAG_COMPRESSION 0x0008 +#define ID3v2_PRIV_METADATA_PREFIX "id3v2_priv." + enum ID3v2Encoding { ID3v2_ENCODING_ISO8859 = 0, ID3v2_ENCODING_UTF16BOM = 1, @@ -167,6 +169,19 @@ int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta); */ int ff_id3v2_parse_chapters(AVFormatContext *s, ID3v2ExtraMeta **extra_meta); +/** + * Parse PRIV tags into a dictionary. The PRIV owner is the metadata key. The + * PRIV data is the value, with non-printable characters escaped. + */ +int ff_id3v2_parse_priv_dict(AVDictionary **d, ID3v2ExtraMeta **extra_meta); + +/** + * Add metadata for all PRIV tags in the ID3v2 header. The PRIV owner is the + * metadata key. The PRIV data is the value, with non-printable characters + * escaped. + */ +int ff_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta **extra_meta); + extern const AVMetadataConv ff_id3v2_34_metadata_conv[]; extern const AVMetadataConv ff_id3v2_4_metadata_conv[]; diff --git a/libavformat/id3v2enc.c b/libavformat/id3v2enc.c index 14de76ac06d4b..ffe358f019865 100644 --- a/libavformat/id3v2enc.c +++ b/libavformat/id3v2enc.c @@ -96,6 +96,59 @@ static int id3v2_put_ttag(ID3v2EncContext *id3, AVIOContext *avioc, const char * return len + ID3v2_HEADER_SIZE; } +/** + * Write a priv frame with owner and data. 'key' is the owner prepended with + * ID3v2_PRIV_METADATA_PREFIX. 'data' is provided as a string. Any \xXX + * (where 'X' is a valid hex digit) will be unescaped to the byte value. + */ +static int id3v2_put_priv(ID3v2EncContext *id3, AVIOContext *avioc, const char *key, const char *data) +{ + int len; + uint8_t *pb; + AVIOContext *dyn_buf; + + if (!av_strstart(key, ID3v2_PRIV_METADATA_PREFIX, &key)) { + return 0; + } + + if (avio_open_dyn_buf(&dyn_buf) < 0) + return AVERROR(ENOMEM); + + // owner + null byte. + avio_write(dyn_buf, key, strlen(key) + 1); + + while (*data) { + if (av_strstart(data, "\\x", &data)) { + if (data[0] && data[1] && av_isxdigit(data[0]) && av_isxdigit(data[1])) { + char digits[] = {data[0], data[1], 0}; + avio_w8(dyn_buf, strtol(digits, NULL, 16)); + data += 2; + } else { + ffio_free_dyn_buf(&dyn_buf); + av_log(avioc, AV_LOG_ERROR, "Invalid escape '\\x%.2s' in metadata tag '" + ID3v2_PRIV_METADATA_PREFIX "%s'.\n", data, key); + return AVERROR(EINVAL); + } + } else { + avio_write(dyn_buf, data++, 1); + } + } + + len = avio_close_dyn_buf(dyn_buf, &pb); + + avio_wb32(avioc, MKBETAG('P', 'R', 'I', 'V')); + if (id3->version == 3) + avio_wb32(avioc, len); + else + id3v2_put_size(avioc, len); + avio_wb16(avioc, 0); + avio_write(avioc, pb, len); + + av_free(pb); + + return len + ID3v2_HEADER_SIZE; +} + static int id3v2_check_write_tag(ID3v2EncContext *id3, AVIOContext *pb, AVDictionaryEntry *t, const char table[][4], enum ID3v2Encoding enc) { @@ -186,6 +239,13 @@ static int write_metadata(AVIOContext *pb, AVDictionary **metadata, continue; } + if ((ret = id3v2_put_priv(id3, pb, t->key, t->value)) > 0) { + id3->len += ret; + continue; + } else if (ret < 0) { + return ret; + } + /* unknown tag, write as TXXX frame */ if ((ret = id3v2_put_ttag(id3, pb, t->key, t->value, MKBETAG('T', 'X', 'X', 'X'), enc)) < 0) return ret; diff --git a/libavformat/utils.c b/libavformat/utils.c index 3d733417e19df..c15b8cc8181e0 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -637,6 +637,8 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, goto fail; if ((ret = ff_id3v2_parse_chapters(s, &id3v2_extra_meta)) < 0) goto fail; + if ((ret = ff_id3v2_parse_priv(s, &id3v2_extra_meta)) < 0) + goto fail; } else av_log(s, AV_LOG_DEBUG, "demuxer does not support additional id3 data, skipping\n"); } diff --git a/libavformat/version.h b/libavformat/version.h index 87758b027ce87..148fc75faa091 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -33,7 +33,7 @@ // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 #define LIBAVFORMAT_VERSION_MINOR 5 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From 1948b76a1beabbcf36480c4b2c2af891886ead88 Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Wed, 24 Jan 2018 11:42:57 +0800 Subject: [PATCH 1722/2557] avformat/hlsenc: closed caption tags in the master playlist --- doc/muxers.texi | 37 +++++++++ libavformat/dashenc.c | 2 +- libavformat/hlsenc.c | 155 +++++++++++++++++++++++++++++++++++++- libavformat/hlsplaylist.c | 5 +- libavformat/hlsplaylist.h | 2 +- 5 files changed, 196 insertions(+), 5 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index b060c4f36014f..d9a5cc03dcb4e 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -901,6 +901,43 @@ and they are mapped to the two video only variant streams with audio group names By default, a single hls variant containing all the encoded streams is created. +@item cc_stream_map +Map string which specifies different closed captions groups and their +attributes. The closed captions stream groups are separated by space. +Expected string format is like this +"ccgroup:,instreamid:,language: ....". +'ccgroup' and 'instreamid' are mandatory attributes. 'language' is an optional +attribute. +The closed captions groups configured using this option are mapped to different +variant streams by providing the same 'ccgroup' name in the +@code{var_stream_map} string. If @code{var_stream_map} is not set, then the +first available ccgroup in @code{cc_stream_map} is mapped to the output variant +stream. The examples for these two use cases are given below. + +@example +ffmpeg -re -i in.ts -b:v 1000k -b:a 64k -a53cc 1 -f hls \ + -cc_stream_map "ccgroup:cc,instreamid:CC1,language:en" \ + -master_pl_name master.m3u8 \ + http://example.com/live/out.m3u8 +@end example +This example adds @code{#EXT-X-MEDIA} tag with @code{TYPE=CLOSED-CAPTIONS} in +the master playlist with group name 'cc', langauge 'en' (english) and +INSTREAM-ID 'CC1'. Also, it adds @code{CLOSED-CAPTIONS} attribute with group +name 'cc' for the output variant stream. +@example +ffmpeg -re -i in.ts -b:v:0 1000k -b:v:1 256k -b:a:0 64k -b:a:1 32k \ + -a53cc:0 1 -a53cc:1 1\ + -map 0:v -map 0:a -map 0:v -map 0:a -f hls \ + -cc_stream_map "ccgroup:cc,instreamid:CC1,language:en ccgroup:cc,instreamid:CC2,language:sp" \ + -var_stream_map "v:0,a:0,ccgroup:cc v:1,a:1,ccgroup:cc" \ + -master_pl_name master.m3u8 \ + http://example.com/live/out_%v.m3u8 +@end example +This example adds two @code{#EXT-X-MEDIA} tags with @code{TYPE=CLOSED-CAPTIONS} in +the master playlist for the INSTREAM-IDs 'CC1' and 'CC2'. Also, it adds +@code{CLOSED-CAPTIONS} attribute with group name 'cc' for the two output variant +streams. + @item master_pl_name Create HLS master playlist with the given name. diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 39d0afe350a80..5ece1002fe1b9 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -820,7 +820,7 @@ static int write_manifest(AVFormatContext *s, int final) stream_bitrate += max_audio_bitrate; } get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i); - ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, agroup, NULL); + ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, agroup, NULL, NULL); } avio_close(out); if (use_rename) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 42e437f5d1978..aab21f2f5eb8b 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -152,9 +152,16 @@ typedef struct VariantStream { unsigned int nb_streams; int m3u8_created; /* status of media play-list creation */ char *agroup; /* audio group name */ + char *ccgroup; /* closed caption group name */ char *baseurl; } VariantStream; +typedef struct ClosedCaptionsStream { + char *ccgroup; /* closed caption group name */ + char *instreamid; /* closed captions INSTREAM-ID */ + char *language; /* closed captions langauge */ +} ClosedCaptionsStream; + typedef struct HLSContext { const AVClass *class; // Class for private options. int64_t start_sequence; @@ -203,11 +210,14 @@ typedef struct HLSContext { VariantStream *var_streams; unsigned int nb_varstreams; + ClosedCaptionsStream *cc_streams; + unsigned int nb_ccstreams; int master_m3u8_created; /* status of master play-list creation */ char *master_m3u8_url; /* URL of the master m3u8 file */ int version; /* HLS version */ char *var_stream_map; /* user specified variant stream map string */ + char *cc_stream_map; /* user specified closed caption streams map string */ char *master_pl_name; unsigned int master_publish_rate; int http_persistent; @@ -1167,7 +1177,8 @@ static int create_master_playlist(AVFormatContext *s, AVDictionary *options = NULL; unsigned int i, j; int m3u8_name_size, ret, bandwidth; - char *m3u8_rel_name; + char *m3u8_rel_name, *ccgroup; + ClosedCaptionsStream *ccs; input_vs->m3u8_created = 1; if (!hls->master_m3u8_created) { @@ -1194,6 +1205,16 @@ static int create_master_playlist(AVFormatContext *s, ff_hls_write_playlist_version(hls->m3u8_out, hls->version); + for (i = 0; i < hls->nb_ccstreams; i++) { + ccs = &(hls->cc_streams[i]); + avio_printf(hls->m3u8_out, "#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS"); + avio_printf(hls->m3u8_out, ",GROUP-ID=\"%s\"", ccs->ccgroup); + avio_printf(hls->m3u8_out, ",NAME=\"%s\"", ccs->instreamid); + if (ccs->language) + avio_printf(hls->m3u8_out, ",LANGUAGE=\"%s\"", ccs->language); + avio_printf(hls->m3u8_out, ",INSTREAM-ID=\"%s\"\n", ccs->instreamid); + } + /* For audio only variant streams add #EXT-X-MEDIA tag with attributes*/ for (i = 0; i < hls->nb_varstreams; i++) { vs = &(hls->var_streams[i]); @@ -1278,8 +1299,23 @@ static int create_master_playlist(AVFormatContext *s, bandwidth += aud_st->codecpar->bit_rate; bandwidth += bandwidth / 10; + ccgroup = NULL; + if (vid_st && vs->ccgroup) { + /* check if this group name is available in the cc map string */ + for (j = 0; j < hls->nb_ccstreams; j++) { + ccs = &(hls->cc_streams[j]); + if (!av_strcasecmp(ccs->ccgroup, vs->ccgroup)) { + ccgroup = vs->ccgroup; + break; + } + } + if (j == hls->nb_ccstreams) + av_log(NULL, AV_LOG_WARNING, "mapping ccgroup %s not found\n", + vs->ccgroup); + } + ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name, - aud_st ? vs->agroup : NULL, vs->codec_attr); + aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup); av_freep(&m3u8_rel_name); } @@ -1766,6 +1802,11 @@ static int parse_variant_stream_mapstring(AVFormatContext *s) if (!vs->agroup) return AVERROR(ENOMEM); continue; + } else if (av_strstart(keyval, "ccgroup:", &val)) { + vs->ccgroup = av_strdup(val); + if (!vs->ccgroup) + return AVERROR(ENOMEM); + continue; } else if (av_strstart(keyval, "v:", &val)) { codec_type = AVMEDIA_TYPE_VIDEO; } else if (av_strstart(keyval, "a:", &val)) { @@ -1796,9 +1837,94 @@ static int parse_variant_stream_mapstring(AVFormatContext *s) return 0; } +static int parse_cc_stream_mapstring(AVFormatContext *s) +{ + HLSContext *hls = s->priv_data; + int nb_ccstreams; + char *p, *q, *saveptr1, *saveptr2, *ccstr, *keyval; + const char *val; + ClosedCaptionsStream *ccs; + + p = av_strdup(hls->cc_stream_map); + q = p; + while(av_strtok(q, " \t", &saveptr1)) { + q = NULL; + hls->nb_ccstreams++; + } + av_freep(&p); + + hls->cc_streams = av_mallocz(sizeof(*hls->cc_streams) * hls->nb_ccstreams); + if (!hls->cc_streams) + return AVERROR(ENOMEM); + + p = hls->cc_stream_map; + nb_ccstreams = 0; + while (ccstr = av_strtok(p, " \t", &saveptr1)) { + p = NULL; + + if (nb_ccstreams < hls->nb_ccstreams) + ccs = &(hls->cc_streams[nb_ccstreams++]); + else + return AVERROR(EINVAL); + + while (keyval = av_strtok(ccstr, ",", &saveptr2)) { + ccstr = NULL; + + if (av_strstart(keyval, "ccgroup:", &val)) { + ccs->ccgroup = av_strdup(val); + if (!ccs->ccgroup) + return AVERROR(ENOMEM); + } else if (av_strstart(keyval, "instreamid:", &val)) { + ccs->instreamid = av_strdup(val); + if (!ccs->instreamid) + return AVERROR(ENOMEM); + } else if (av_strstart(keyval, "language:", &val)) { + ccs->language = av_strdup(val); + if (!ccs->language) + return AVERROR(ENOMEM); + } else { + av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval); + return AVERROR(EINVAL); + } + } + + if (!ccs->ccgroup || !ccs->instreamid) { + av_log(s, AV_LOG_ERROR, "Insufficient parameters in cc stream map string\n"); + return AVERROR(EINVAL); + } + + if (av_strstart(ccs->instreamid, "CC", &val)) { + if(atoi(val) < 1 || atoi(val) > 4) { + av_log(s, AV_LOG_ERROR, "Invalid instream ID CC index %d in %s, range 1-4\n", + atoi(val), ccs->instreamid); + return AVERROR(EINVAL); + } + } else if (av_strstart(ccs->instreamid, "SERVICE", &val)) { + if(atoi(val) < 1 || atoi(val) > 63) { + av_log(s, AV_LOG_ERROR, "Invalid instream ID SERVICE index %d in %s, range 1-63 \n", + atoi(val), ccs->instreamid); + return AVERROR(EINVAL); + } + } else { + av_log(s, AV_LOG_ERROR, "Invalid instream ID %s, supported are CCn or SERIVICEn\n", + ccs->instreamid); + return AVERROR(EINVAL); + } + } + + return 0; +} + static int update_variant_stream_info(AVFormatContext *s) { HLSContext *hls = s->priv_data; unsigned int i; + int ret = 0; + + if (hls->cc_stream_map) { + ret = parse_cc_stream_mapstring(s); + if (ret < 0) + return ret; + } if (hls->var_stream_map) { return parse_variant_stream_mapstring(s); @@ -1816,6 +1942,13 @@ static int update_variant_stream_info(AVFormatContext *s) { if (!hls->var_streams[0].streams) return AVERROR(ENOMEM); + //by default, the first available ccgroup is mapped to the variant stream + if (hls->nb_ccstreams) { + hls->var_streams[0].ccgroup = av_strdup(hls->cc_streams[0].ccgroup); + if (!hls->var_streams[0].ccgroup) + return AVERROR(ENOMEM); + } + for (i = 0; i < s->nb_streams; i++) hls->var_streams[0].streams[i] = s->streams[i]; } @@ -2192,13 +2325,22 @@ static int hls_write_trailer(struct AVFormatContext *s) av_freep(&vs->m3u8_name); av_freep(&vs->streams); av_freep(&vs->agroup); + av_freep(&vs->ccgroup); av_freep(&vs->baseurl); } + for (i = 0; i < hls->nb_ccstreams; i++) { + ClosedCaptionsStream *ccs = &hls->cc_streams[i]; + av_freep(&ccs->ccgroup); + av_freep(&ccs->instreamid); + av_freep(&ccs->language); + } + ff_format_io_close(s, &hls->m3u8_out); ff_format_io_close(s, &hls->sub_m3u8_out); av_freep(&hls->key_basename); av_freep(&hls->var_streams); + av_freep(&hls->cc_streams); av_freep(&hls->master_m3u8_url); return 0; } @@ -2535,13 +2677,21 @@ static int hls_init(AVFormatContext *s) av_freep(&vs->vtt_m3u8_name); av_freep(&vs->streams); av_freep(&vs->agroup); + av_freep(&vs->ccgroup); av_freep(&vs->baseurl); if (vs->avf) avformat_free_context(vs->avf); if (vs->vtt_avf) avformat_free_context(vs->vtt_avf); } + for (i = 0; i < hls->nb_ccstreams; i++) { + ClosedCaptionsStream *ccs = &hls->cc_streams[i]; + av_freep(&ccs->ccgroup); + av_freep(&ccs->instreamid); + av_freep(&ccs->language); + } av_freep(&hls->var_streams); + av_freep(&hls->cc_streams); av_freep(&hls->master_m3u8_url); } @@ -2601,6 +2751,7 @@ static const AVOption options[] = { {"datetime", "current datetime as YYYYMMDDhhmmss", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME }, INT_MIN, INT_MAX, E, "start_sequence_source_type" }, {"http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"var_stream_map", "Variant stream map string", OFFSET(var_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, + {"cc_stream_map", "Closed captions stream map string", OFFSET(cc_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"master_pl_name", "Create HLS master playlist with this name", OFFSET(master_pl_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"master_pl_publish_rate", "Publish master play list every after this many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E}, {"http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c index b8a3a1409034a..efcbff0009db7 100644 --- a/libavformat/hlsplaylist.c +++ b/libavformat/hlsplaylist.c @@ -47,7 +47,8 @@ void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, char *filename, char *agroup, - char *codecs) { + char *codecs, char *ccgroup) { + if (!out || !filename) return; @@ -65,6 +66,8 @@ void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, avio_printf(out, ",CODECS=\"%s\"", codecs); if (agroup && strlen(agroup) > 0) avio_printf(out, ",AUDIO=\"group_%s\"", agroup); + if (ccgroup && strlen(ccgroup) > 0) + avio_printf(out, ",CLOSED-CAPTIONS=\"%s\"", ccgroup); avio_printf(out, "\n%s\n\n", filename); } diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index 7532e3752f88f..5054b01c8fc53 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -41,7 +41,7 @@ void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, char *filename, int name_id, int is_default); void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, char *filename, char *agroup, - char *codecs); + char *codecs, char *ccgroup); void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, int target_duration, int64_t sequence, uint32_t playlist_type); From a2a9e4eea0e4fde2ed8d3405b4f33f655b600c2d Mon Sep 17 00:00:00 2001 From: Josh Allmann Date: Tue, 23 Jan 2018 16:47:12 -0800 Subject: [PATCH 1723/2557] rtmp: Plug leak if sending bytes read report fails. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/rtmpproto.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 115c335974615..48c5ead74701b 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -2396,8 +2396,10 @@ static int get_packet(URLContext *s, int for_header) rt->bytes_read += ret; if (rt->bytes_read - rt->last_bytes_read > rt->receive_report_size) { av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n"); - if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0) + if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0) { + ff_rtmp_packet_destroy(&rpkt); return ret; + } rt->last_bytes_read = rt->bytes_read; } From 4dbae00bac7af0b35622feb5ac78d29ac16889fd Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Wed, 24 Jan 2018 08:40:59 +0800 Subject: [PATCH 1724/2557] lavfi/vf_xxx_vaapi: fix typo. Signed-off-by: Jun Zhao --- libavfilter/vf_deinterlace_vaapi.c | 2 +- libavfilter/vf_misc_vaapi.c | 4 ++-- libavfilter/vf_procamp_vaapi.c | 2 +- libavfilter/vf_scale_vaapi.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c index 9700f85817d48..f7a262d0c6be1 100644 --- a/libavfilter/vf_deinterlace_vaapi.c +++ b/libavfilter/vf_deinterlace_vaapi.c @@ -33,7 +33,7 @@ #define MAX_REFERENCES 8 typedef struct DeintVAAPIContext { - VAAPIVPPContext vpp_ctx; // must be the first fileld + VAAPIVPPContext vpp_ctx; // must be the first field int mode; int field_rate; diff --git a/libavfilter/vf_misc_vaapi.c b/libavfilter/vf_misc_vaapi.c index 316f15e38b545..c60b7b0c48553 100644 --- a/libavfilter/vf_misc_vaapi.c +++ b/libavfilter/vf_misc_vaapi.c @@ -38,13 +38,13 @@ #define SHARPNESS_DEFAULT 44 typedef struct DenoiseVAAPIContext { - VAAPIVPPContext vpp_ctx; // must be the first fileld + VAAPIVPPContext vpp_ctx; // must be the first field int denoise; // enable denoise algo. } DenoiseVAAPIContext; typedef struct SharpnessVAAPIContext { - VAAPIVPPContext vpp_ctx; // must be the first fileld + VAAPIVPPContext vpp_ctx; // must be the first field int sharpness; // enable sharpness. } SharpnessVAAPIContext; diff --git a/libavfilter/vf_procamp_vaapi.c b/libavfilter/vf_procamp_vaapi.c index 10f9a6ba0c6e0..aad76aa37106f 100644 --- a/libavfilter/vf_procamp_vaapi.c +++ b/libavfilter/vf_procamp_vaapi.c @@ -47,7 +47,7 @@ #define EPSILON 0.00001F typedef struct ProcampVAAPIContext { - VAAPIVPPContext vpp_ctx; // must be the first fileld + VAAPIVPPContext vpp_ctx; // must be the first field float bright; float hue; diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c index d349ff0f900cd..c19e23ccd0201 100644 --- a/libavfilter/vf_scale_vaapi.c +++ b/libavfilter/vf_scale_vaapi.c @@ -31,7 +31,7 @@ #include "vaapi_vpp.h" typedef struct ScaleVAAPIContext { - VAAPIVPPContext vpp_ctx; // must be the first fileld + VAAPIVPPContext vpp_ctx; // must be the first field char *output_format_string; From 559370f2c45110afd8308eec7194437736c323d4 Mon Sep 17 00:00:00 2001 From: "Ruiling, Song" Date: Wed, 24 Jan 2018 10:14:51 +0800 Subject: [PATCH 1725/2557] qsv: Skip the packet if decoding failure MediaSDK may fail to decode some frame, just skip it. Otherwise, it will keep decoding the failure packet repeatedly without processing any packet afterwards. Signed-off-by: Ruiling Song Signed-off-by: Luca Barbato --- libavcodec/qsvdec_h2645.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c index 83880dc085e2c..78a7b613f9ae1 100644 --- a/libavcodec/qsvdec_h2645.c +++ b/libavcodec/qsvdec_h2645.c @@ -153,8 +153,12 @@ static int qsv_decode_frame(AVCodecContext *avctx, void *data, } ret = ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->buffer_pkt); - if (ret < 0) + if (ret < 0){ + /* Drop buffer_pkt when failed to decode the packet. Otherwise, + the decoder will keep decoding the failure packet. */ + av_packet_unref(&s->buffer_pkt); return ret; + } s->buffer_pkt.size -= ret; s->buffer_pkt.data += ret; From ee88f31d34c848fd95daf12bdf054b7228efdf14 Mon Sep 17 00:00:00 2001 From: Josh Allmann Date: Tue, 23 Jan 2018 16:49:16 -0800 Subject: [PATCH 1726/2557] libavformat/rtmpproto: Plug leak if sending bytes read report fails. Signed-off-by: Michael Niedermayer --- libavformat/rtmpproto.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index faf2a6f24409c..b741e421af972 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -2431,8 +2431,10 @@ static int get_packet(URLContext *s, int for_header) rt->bytes_read += ret; if (rt->bytes_read - rt->last_bytes_read > rt->receive_report_size) { av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n"); - if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0) + if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0) { + ff_rtmp_packet_destroy(&rpkt); return ret; + } rt->last_bytes_read = rt->bytes_read; } From 74cf4a75f74ee3d80d021fc50b05e38bff5940e3 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 18 Jan 2018 23:24:05 +0000 Subject: [PATCH 1727/2557] ffmpeg: Ignore SIGPIPE On systems which deliver SIGPIPE (Unices), a broken pipe will currently result in the immediate termination of the ffmpeg process (the default disposition as required by POSIX). This is undesirable, because while the broken pipe is likely fatal to useful cleanup of whatever component is writing to it, there might be other components which can do useful cleanup - for example, a muxer on another stream may still need to write indexes to complete a file. Therefore, set the signal disposition for SIGPIPE to ignore the signal - the call which caused the signal will fail with EPIPE and the error will be propagated upwards like any other I/O failure on a single stream. --- fftools/ffmpeg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 528849a2c6636..918eb353aac9e 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -406,6 +406,9 @@ void term_init(void) #ifdef SIGXCPU signal(SIGXCPU, sigterm_handler); #endif +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); /* Broken pipe (POSIX). */ +#endif #if HAVE_SETCONSOLECTRLHANDLER SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE); #endif From 658ac0672f46cef483e68440061da763e908b68a Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Wed, 24 Jan 2018 09:28:24 +0800 Subject: [PATCH 1728/2557] lavfi/procamp_vaapi: fix the green video issue if without arguments. Fix the green output issue when use procamp_vaapi without any arguments, now if use procamp_vaapi without any arguments, will use the default value to setting procamp_vaapi. Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- libavfilter/vf_procamp_vaapi.c | 73 +++++++++++++++------------------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/libavfilter/vf_procamp_vaapi.c b/libavfilter/vf_procamp_vaapi.c index aad76aa37106f..45a3120b23716 100644 --- a/libavfilter/vf_procamp_vaapi.c +++ b/libavfilter/vf_procamp_vaapi.c @@ -44,8 +44,6 @@ #define SATURATION_MAX 10.0F #define SATURATION_DEFAULT 1.0F -#define EPSILON 0.00001F - typedef struct ProcampVAAPIContext { VAAPIVPPContext vpp_ctx; // must be the first field @@ -65,11 +63,6 @@ static float map(float x, float in_min, float in_max, float out_min, float out_m return (float)output; } -static int fequal(float a, float b) -{ - return fabs(a-b) < EPSILON; -} - static int procamp_vaapi_build_filter_params(AVFilterContext *avctx) { VAAPIVPPContext *vpp_ctx = avctx->priv; @@ -93,41 +86,37 @@ static int procamp_vaapi_build_filter_params(AVFilterContext *avctx) return AVERROR(EIO); } - if (!fequal(ctx->bright, BRIGHTNESS_DEFAULT)) { - procamp_params[i].type = VAProcFilterColorBalance; - procamp_params[i].attrib = VAProcColorBalanceBrightness; - procamp_params[i].value = map(ctx->bright, BRIGHTNESS_MIN, BRIGHTNESS_MAX, - procamp_caps[VAProcColorBalanceBrightness-1].range.min_value, - procamp_caps[VAProcColorBalanceBrightness-1].range.max_value); - i++; - } - - if (!fequal(ctx->contrast, CONTRAST_DEFAULT)) { - procamp_params[i].type = VAProcFilterColorBalance; - procamp_params[i].attrib = VAProcColorBalanceContrast; - procamp_params[i].value = map(ctx->contrast, CONTRAST_MIN, CONTRAST_MAX, - procamp_caps[VAProcColorBalanceContrast-1].range.min_value, - procamp_caps[VAProcColorBalanceContrast-1].range.max_value); - i++; - } - - if (!fequal(ctx->hue, HUE_DEFAULT)) { - procamp_params[i].type = VAProcFilterColorBalance; - procamp_params[i].attrib = VAProcColorBalanceHue; - procamp_params[i].value = map(ctx->hue, HUE_MIN, HUE_MAX, - procamp_caps[VAProcColorBalanceHue-1].range.min_value, - procamp_caps[VAProcColorBalanceHue-1].range.max_value); - i++; - } - - if (!fequal(ctx->saturation, SATURATION_DEFAULT)) { - procamp_params[i].type = VAProcFilterColorBalance; - procamp_params[i].attrib = VAProcColorBalanceSaturation; - procamp_params[i].value = map(ctx->saturation, SATURATION_MIN, SATURATION_MAX, - procamp_caps[VAProcColorBalanceSaturation-1].range.min_value, - procamp_caps[VAProcColorBalanceSaturation-1].range.max_value); - i++; - } + /* brightness */ + procamp_params[i].type = VAProcFilterColorBalance; + procamp_params[i].attrib = VAProcColorBalanceBrightness; + procamp_params[i].value = map(ctx->bright, BRIGHTNESS_MIN, BRIGHTNESS_MAX, + procamp_caps[VAProcColorBalanceBrightness-1].range.min_value, + procamp_caps[VAProcColorBalanceBrightness-1].range.max_value); + i++; + + /* contrast */ + procamp_params[i].type = VAProcFilterColorBalance; + procamp_params[i].attrib = VAProcColorBalanceContrast; + procamp_params[i].value = map(ctx->contrast, CONTRAST_MIN, CONTRAST_MAX, + procamp_caps[VAProcColorBalanceContrast-1].range.min_value, + procamp_caps[VAProcColorBalanceContrast-1].range.max_value); + i++; + + /* hue */ + procamp_params[i].type = VAProcFilterColorBalance; + procamp_params[i].attrib = VAProcColorBalanceHue; + procamp_params[i].value = map(ctx->hue, HUE_MIN, HUE_MAX, + procamp_caps[VAProcColorBalanceHue-1].range.min_value, + procamp_caps[VAProcColorBalanceHue-1].range.max_value); + i++; + + /* saturation */ + procamp_params[i].type = VAProcFilterColorBalance; + procamp_params[i].attrib = VAProcColorBalanceSaturation; + procamp_params[i].value = map(ctx->saturation, SATURATION_MIN, SATURATION_MAX, + procamp_caps[VAProcColorBalanceSaturation-1].range.min_value, + procamp_caps[VAProcColorBalanceSaturation-1].range.max_value); + i++; return ff_vaapi_vpp_make_param_buffers(avctx, VAProcFilterParameterBufferType, From 4e6e1e5350b73bee3122ad4044195bb14d69c229 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Wed, 24 Jan 2018 09:32:50 +0800 Subject: [PATCH 1729/2557] lavfi/misc_vaapi: use default value setting if without arguments. Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- libavfilter/vf_misc_vaapi.c | 64 +++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/libavfilter/vf_misc_vaapi.c b/libavfilter/vf_misc_vaapi.c index c60b7b0c48553..8b179fe21553b 100644 --- a/libavfilter/vf_misc_vaapi.c +++ b/libavfilter/vf_misc_vaapi.c @@ -71,24 +71,22 @@ static int denoise_vaapi_build_filter_params(AVFilterContext *avctx) VAProcFilterParameterBuffer denoise; - if (ctx->denoise != DENOISE_DEFAULT) { - vas = vaQueryVideoProcFilterCaps(vpp_ctx->hwctx->display, vpp_ctx->va_context, - VAProcFilterNoiseReduction, - &caps, &num_caps); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to query denoise caps " - "context: %d (%s).\n", vas, vaErrorStr(vas)); - return AVERROR(EIO); - } - - denoise.type = VAProcFilterNoiseReduction; - denoise.value = map(ctx->denoise, DENOISE_MIN, DENOISE_MAX, - caps.range.min_value, - caps.range.max_value); - ff_vaapi_vpp_make_param_buffers(avctx, VAProcFilterParameterBufferType, - &denoise, sizeof(denoise), 1); + vas = vaQueryVideoProcFilterCaps(vpp_ctx->hwctx->display, vpp_ctx->va_context, + VAProcFilterNoiseReduction, + &caps, &num_caps); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query denoise caps " + "context: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); } + denoise.type = VAProcFilterNoiseReduction; + denoise.value = map(ctx->denoise, DENOISE_MIN, DENOISE_MAX, + caps.range.min_value, + caps.range.max_value); + ff_vaapi_vpp_make_param_buffers(avctx, VAProcFilterParameterBufferType, + &denoise, sizeof(denoise), 1); + return 0; } @@ -104,26 +102,24 @@ static int sharpness_vaapi_build_filter_params(AVFilterContext *avctx) VAProcFilterParameterBuffer sharpness; - if (ctx->sharpness != SHARPNESS_DEFAULT) { - vas = vaQueryVideoProcFilterCaps(vpp_ctx->hwctx->display, vpp_ctx->va_context, - VAProcFilterSharpening, - &caps, &num_caps); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to query sharpness caps " - "context: %d (%s).\n", vas, vaErrorStr(vas)); - return AVERROR(EIO); - } - - sharpness.type = VAProcFilterSharpening; - sharpness.value = map(ctx->sharpness, - SHARPNESS_MIN, SHARPNESS_MAX, - caps.range.min_value, - caps.range.max_value); - ff_vaapi_vpp_make_param_buffers(avctx, - VAProcFilterParameterBufferType, - &sharpness, sizeof(sharpness), 1); + vas = vaQueryVideoProcFilterCaps(vpp_ctx->hwctx->display, vpp_ctx->va_context, + VAProcFilterSharpening, + &caps, &num_caps); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query sharpness caps " + "context: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); } + sharpness.type = VAProcFilterSharpening; + sharpness.value = map(ctx->sharpness, + SHARPNESS_MIN, SHARPNESS_MAX, + caps.range.min_value, + caps.range.max_value); + ff_vaapi_vpp_make_param_buffers(avctx, + VAProcFilterParameterBufferType, + &sharpness, sizeof(sharpness), 1); + return 0; } From 0df9d0f4cbcb18006f9fde0502671f9ef293e2f2 Mon Sep 17 00:00:00 2001 From: Karthick Jeyapal Date: Tue, 2 Jan 2018 13:49:56 +0530 Subject: [PATCH 1730/2557] avformat/dashenc: Fix a resource leak when http persistent in enabled --- libavformat/dashenc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 5ece1002fe1b9..38cc592cde227 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1,6 +1,7 @@ /* * MPEG-DASH ISO BMFF segmenter * Copyright (c) 2014 Martin Storsjo + * Copyright (c) 2018 Akamai Technologies, Inc. * * This file is part of FFmpeg. * @@ -309,6 +310,9 @@ static void dash_free(AVFormatContext *s) av_free(os->segments); } av_freep(&c->streams); + + ff_format_io_close(s, &c->mpd_out); + ff_format_io_close(s, &c->m3u8_out); } static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatContext *s, From 18e2ac032e9d7258e57ec033962fca665f2a0be5 Mon Sep 17 00:00:00 2001 From: Karthick Jeyapal Date: Tue, 2 Jan 2018 13:49:57 +0530 Subject: [PATCH 1731/2557] avformat/dashenc: Signal http end of chunk(http_shutdown) explicitly Currently http end of chunk is signalled implicitly in dashenc_io_open(). This mean playlists http writes would have to wait upto a segment duration to signal end of chunk causing delays. This patch will fix that problem and improve performance. --- libavformat/dashenc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 38cc592cde227..d1e4d7466a419 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -149,7 +149,10 @@ static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filenam ff_format_io_close(s, pb); #if CONFIG_HTTP_PROTOCOL } else { + URLContext *http_url_context = ffio_geturlcontext(*pb); + av_assert0(http_url_context); avio_flush(*pb); + ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE); #endif } } From 77237504757b97c068796a4e9ef81b9653618616 Mon Sep 17 00:00:00 2001 From: Rodger Combs Date: Thu, 25 Jan 2018 20:53:59 -0600 Subject: [PATCH 1732/2557] lavc/aarch64/sbrdsp_neon: fix build on old binutils --- libavcodec/aarch64/sbrdsp_neon.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/aarch64/sbrdsp_neon.S b/libavcodec/aarch64/sbrdsp_neon.S index d1d79b749c2fe..d23717e76055f 100644 --- a/libavcodec/aarch64/sbrdsp_neon.S +++ b/libavcodec/aarch64/sbrdsp_neon.S @@ -287,7 +287,7 @@ endfunc zip1 v4.4S, v4.4S, v4.4S fmla v6.4S, v1.4S, v3.4S fmla v2.4S, v5.4S, v4.4S - fcmeq v7.4S, v3.4S, #0.0 + fcmeq v7.4S, v3.4S, #0 bif v2.16B, v6.16B, v7.16B st1 {v2.4S}, [x0], #16 subs x5, x5, #2 From 6829a079444e10818a847e153121fb458cc5c0a8 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Thu, 25 Jan 2018 18:19:12 +0800 Subject: [PATCH 1733/2557] qsvdec: Relax the surface vs coded dimension check Fix a common vp8 decoding failure. Many vp8 clips cannot decode if hw_frames_ctx is enabled, reporting "Error during QSV decoding.: incompatible video parameters (-14)". It is due to mfx.FrameInfo.Width/Height not matching coded_w/coded_h. See: avconv -hwaccel qsv -init_hw_device qsv -c:v vp8_qsv -i vp8-test-vectors-r1/vp80-00-comprehensive-001.ivf -vf "hwdownload,format=nv12" -pix_fmt yuv420p -f md5 - Signed-off-by: Zhong Li Signed-off-by: Luca Barbato --- libavcodec/qsv.c | 2 +- libavcodec/qsvdec.c | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index 96dca14e9ae24..e78633d62abe6 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -389,7 +389,7 @@ static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, mfxFrameInfo *i = &req->Info; mfxFrameInfo *i1 = &frames_hwctx->surfaces[0].Info; - if (i->Width != i1->Width || i->Height != i1->Height || + if (i->Width > i1->Width || i->Height > i1->Height || i->FourCC != i1->FourCC || i->ChromaFormat != i1->ChromaFormat) { av_log(ctx->logctx, AV_LOG_ERROR, "Mismatching surface properties in an " "allocation request: %dx%d %d %d vs %dx%d %d %d\n", diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 9741f33109434..f31172de29a3a 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -149,9 +149,6 @@ static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q) else if (frames_hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET) iopattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY; } - - frame_width = frames_hwctx->surfaces[0].Info.Width; - frame_height = frames_hwctx->surfaces[0].Info.Height; } if (!iopattern) From 637dfa39421c2806616d1aa454c9182db1aac3d9 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 24 Jan 2018 07:58:52 +0100 Subject: [PATCH 1734/2557] hls: do not allow fallback to generic seeking This makes little sense due to how HLS works, and only causes some additional annoyances if the HLS read_seek function fails (for example if it's a live stream). It was most likely unintended. --- libavformat/hls.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/hls.c b/libavformat/hls.c index 950cc4c3bd1af..ff7bdecc9338e 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -2333,6 +2333,7 @@ AVInputFormat ff_hls_demuxer = { .long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"), .priv_class = &hls_class, .priv_data_size = sizeof(HLSContext), + .flags = AVFMT_NOGENSEARCH, .read_probe = hls_probe, .read_header = hls_read_header, .read_packet = hls_read_packet, From 6194d7e56454897b9c5d9d52e82376b2a6e6b85c Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 24 Jan 2018 08:02:25 +0100 Subject: [PATCH 1735/2557] avformat, hls: add a flag to signal unavailability of seeking The seek function can just return an error if seeking is unavailable, but often this is too late. Add a flag that signals that the stream is unseekable, and use it in HLS. --- doc/APIchanges | 3 +++ libavformat/avformat.h | 5 +++++ libavformat/hls.c | 8 ++++++-- libavformat/version.h | 4 ++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index c27f104c951c0..59e3b20c08b88 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-01-xx - xxxxxxx - lavf 58.6.100 - avformat.h + Add AVFMTCTX_UNSEEKABLE (for HLS demuxer). + 2018-xx-xx - xxxxxxx - lavu 56.9.100 - aes_ctr.h Add method to set the 16-byte IV. diff --git a/libavformat/avformat.h b/libavformat/avformat.h index e5740be2b4dfb..60ab9fbc804e1 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1275,6 +1275,11 @@ typedef struct AVProgram { #define AVFMTCTX_NOHEADER 0x0001 /**< signal that no header is present (streams are added dynamically) */ +#define AVFMTCTX_UNSEEKABLE 0x0002 /**< signal that the stream is definitely + not seekable, and attempts to call the + seek function will fail. For some + network protocols (e.g. HLS), this can + change dynamically at runtime. */ typedef struct AVChapter { int id; ///< unique ID to identify the chapter diff --git a/libavformat/hls.c b/libavformat/hls.c index ff7bdecc9338e..6e1a2e3f1eda8 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -930,6 +930,11 @@ static int parse_playlist(HLSContext *c, const char *url, av_free(new_url); if (close_in) ff_format_io_close(c->ctx, &in); + c->ctx->ctx_flags = c->ctx->ctx_flags & ~(unsigned)AVFMTCTX_UNSEEKABLE; + if (!c->n_variants || !c->variants[0]->n_playlists || + !(c->variants[0]->playlists[0]->finished || + c->variants[0]->playlists[0]->type == PLS_TYPE_EVENT)) + c->ctx->ctx_flags |= AVFMTCTX_UNSEEKABLE; return ret; } @@ -2213,8 +2218,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, int stream_subdemuxer_index; int64_t first_timestamp, seek_timestamp, duration; - if ((flags & AVSEEK_FLAG_BYTE) || - !(c->variants[0]->playlists[0]->finished || c->variants[0]->playlists[0]->type == PLS_TYPE_EVENT)) + if ((flags & AVSEEK_FLAG_BYTE) || (c->ctx->ctx_flags & AVFMTCTX_UNSEEKABLE)) return AVERROR(ENOSYS); first_timestamp = c->first_timestamp == AV_NOPTS_VALUE ? diff --git a/libavformat/version.h b/libavformat/version.h index 148fc75faa091..5ff8a89ae0864 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,8 +32,8 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 5 -#define LIBAVFORMAT_VERSION_MICRO 101 +#define LIBAVFORMAT_VERSION_MINOR 6 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From 23ffeb91fe46f6f95348731396ccfdb7fbff0337 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 24 Jan 2018 08:04:38 +0100 Subject: [PATCH 1736/2557] hls: don't print a certain warning if playlist loading is aborted AVERROR_EXIT happens when the user's interrupt callback signals that playback should be aborted. In this case, the demuxer shouldn't print a warning, as it's expected that all network accesses are stopped. --- libavformat/hls.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 6e1a2e3f1eda8..02e764f932827 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1422,8 +1422,9 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) if (!v->finished && av_gettime_relative() - v->last_load_time >= reload_interval) { if ((ret = parse_playlist(c, v->url, v, NULL)) < 0) { - av_log(v->parent, AV_LOG_WARNING, "Failed to reload playlist %d\n", - v->index); + if (ret != AVERROR_EXIT) + av_log(v->parent, AV_LOG_WARNING, "Failed to reload playlist %d\n", + v->index); return ret; } /* If we need to reload the playlist again below (if From c6939f65a116b1ffed345d29d8621ee4ffb32235 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 24 Jan 2018 19:38:05 +0100 Subject: [PATCH 1737/2557] avfilter/vf_transpose: Fix used plane count. Fixes out of array access Fixes: poc.mp4 Found-by: GwanYeong Kim Signed-off-by: Michael Niedermayer --- libavfilter/vf_transpose.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c index 982fb0c8ca496..1e1a5c4b893d5 100644 --- a/libavfilter/vf_transpose.c +++ b/libavfilter/vf_transpose.c @@ -27,6 +27,7 @@ #include +#include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" @@ -54,6 +55,7 @@ enum TransposeDir { typedef struct TransContext { const AVClass *class; int hsub, vsub; + int planes; int pixsteps[4]; int passthrough; ///< PassthroughType, landscape passthrough mode enabled @@ -215,6 +217,10 @@ static int config_props_output(AVFilterLink *outlink) s->hsub = desc_in->log2_chroma_w; s->vsub = desc_in->log2_chroma_h; + s->planes = desc_in->nb_components; + + av_assert0(desc_in->nb_components == desc_out->nb_components); + av_image_fill_max_pixsteps(s->pixsteps, NULL, desc_out); @@ -272,7 +278,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, AVFrame *in = td->in; int plane; - for (plane = 0; out->data[plane]; plane++) { + for (plane = 0; plane < s->planes; plane++) { int hsub = plane == 1 || plane == 2 ? s->hsub : 0; int vsub = plane == 1 || plane == 2 ? s->vsub : 0; int pixstep = s->pixsteps[plane]; From 1bfc1aa004950c5ad527d823a08b8a19eef34eb0 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 24 Jan 2018 03:28:49 +0100 Subject: [PATCH 1738/2557] avcodec/mjpegdec: Fix integer overflow in DC dequantization Fixes: runtime error: signed integer overflow: -65535 * 65312 cannot be represented in type 'int' Fixes: 4900/clusterfuzz-testcase-minimized-5769019744321536 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/mjpegdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index e005dd0cd3bf2..5055ee28267bc 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -715,7 +715,7 @@ static int decode_block(MJpegDecodeContext *s, int16_t *block, int component, av_log(s->avctx, AV_LOG_ERROR, "error dc\n"); return AVERROR_INVALIDDATA; } - val = val * quant_matrix[0] + s->last_dc[component]; + val = val * (unsigned)quant_matrix[0] + s->last_dc[component]; val = av_clip_int16(val); s->last_dc[component] = val; block[0] = val; From a026a3efaeb9c2026668dccbbda339a21ab3206b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 15 Jan 2018 23:46:44 +0100 Subject: [PATCH 1739/2557] avcodec/hevc_cabac: Check prefix so as to avoid invalid shifts in coeff_abs_level_remaining_decode() I suspect that this can be limited tighter, but i failed to find anything in the spec that would confirm that. Fixes: 4833/clusterfuzz-testcase-minimized-5302840101699584 Fixes: runtime error: left shift of 134217730 by 4 places cannot be represented in type 'int' Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevc_cabac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c index 743168500c7b8..faa36d545935f 100644 --- a/libavcodec/hevc_cabac.c +++ b/libavcodec/hevc_cabac.c @@ -998,7 +998,7 @@ static av_always_inline int coeff_abs_level_remaining_decode(HEVCContext *s, int } else { int prefix_minus3 = prefix - 3; - if (prefix == CABAC_MAX_BIN) { + if (prefix == CABAC_MAX_BIN || prefix_minus3 + rc_rice_param >= 31) { av_log(s->avctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", prefix); return 0; } From bbe1b21022e4872bc64066d46a4567dc1b655f7a Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Fri, 26 Jan 2018 20:16:53 +0100 Subject: [PATCH 1740/2557] avcodec/nvenc: refcount input frame mappings If some logic like vsync in ffmpeg.c duplicates frames, it might pass the same frame twice, which will result in a crash due it being effectively mapped and unmapped twice. Signed-off-by: Timo Rothenpieler --- libavcodec/nvenc.c | 39 +++++++++++++++++++++++---------------- libavcodec/nvenc.h | 2 +- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 4a91d9972014f..0ecaa15162469 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -1389,12 +1389,9 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) av_fifo_freep(&ctx->unused_surface_queue); if (ctx->surfaces && (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11)) { - for (i = 0; i < ctx->nb_surfaces; ++i) { - if (ctx->surfaces[i].input_surface) { - p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->surfaces[i].in_map.mappedResource); - } - } for (i = 0; i < ctx->nb_registered_frames; i++) { + if (ctx->registered_frames[i].mapped) + p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->registered_frames[i].in_map.mappedResource); if (ctx->registered_frames[i].regptr) p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[i].regptr); } @@ -1629,19 +1626,23 @@ static int nvenc_upload_frame(AVCodecContext *avctx, const AVFrame *frame, if (res < 0) return res; - nvenc_frame->in_map.version = NV_ENC_MAP_INPUT_RESOURCE_VER; - nvenc_frame->in_map.registeredResource = ctx->registered_frames[reg_idx].regptr; - nv_status = p_nvenc->nvEncMapInputResource(ctx->nvencoder, &nvenc_frame->in_map); - if (nv_status != NV_ENC_SUCCESS) { - av_frame_unref(nvenc_frame->in_ref); - return nvenc_print_error(avctx, nv_status, "Error mapping an input resource"); + if (!ctx->registered_frames[reg_idx].mapped) { + ctx->registered_frames[reg_idx].in_map.version = NV_ENC_MAP_INPUT_RESOURCE_VER; + ctx->registered_frames[reg_idx].in_map.registeredResource = ctx->registered_frames[reg_idx].regptr; + nv_status = p_nvenc->nvEncMapInputResource(ctx->nvencoder, &ctx->registered_frames[reg_idx].in_map); + if (nv_status != NV_ENC_SUCCESS) { + av_frame_unref(nvenc_frame->in_ref); + return nvenc_print_error(avctx, nv_status, "Error mapping an input resource"); + } } - ctx->registered_frames[reg_idx].mapped = 1; + ctx->registered_frames[reg_idx].mapped += 1; + nvenc_frame->reg_idx = reg_idx; - nvenc_frame->input_surface = nvenc_frame->in_map.mappedResource; - nvenc_frame->format = nvenc_frame->in_map.mappedBufferFmt; + nvenc_frame->input_surface = ctx->registered_frames[reg_idx].in_map.mappedResource; + nvenc_frame->format = ctx->registered_frames[reg_idx].in_map.mappedBufferFmt; nvenc_frame->pitch = frame->linesize[0]; + return 0; } else { NV_ENC_LOCK_INPUT_BUFFER lockBufferParams = { 0 }; @@ -1793,9 +1794,15 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) { - p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, tmpoutsurf->in_map.mappedResource); + ctx->registered_frames[tmpoutsurf->reg_idx].mapped -= 1; + if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped == 0) { + p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->registered_frames[tmpoutsurf->reg_idx].in_map.mappedResource); + } else if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped < 0) { + res = AVERROR_BUG; + goto error; + } + av_frame_unref(tmpoutsurf->in_ref); - ctx->registered_frames[tmpoutsurf->reg_idx].mapped = 0; tmpoutsurf->input_surface = NULL; } diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 2e51f1e946f4b..ab6825f633a31 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -44,7 +44,6 @@ typedef struct NvencSurface { NV_ENC_INPUT_PTR input_surface; AVFrame *in_ref; - NV_ENC_MAP_INPUT_RESOURCE in_map; int reg_idx; int width; int height; @@ -131,6 +130,7 @@ typedef struct NvencContext int ptr_index; NV_ENC_REGISTERED_PTR regptr; int mapped; + NV_ENC_MAP_INPUT_RESOURCE in_map; } registered_frames[MAX_REGISTERED_FRAMES]; int nb_registered_frames; From 32bc4e77f61a5483c83a360b9ccbfc2840daba1e Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sun, 28 Jan 2018 12:39:03 +0100 Subject: [PATCH 1741/2557] avcodec/nvenc: unregister input resource when unmapping Currently the resource is only ever unregistered when the registered_frames array is fully in use and an unmapped entry is re-used and cleaned up. I'm pretty sure the frame will have been cleaned up before that happens, so I'm kinda surprised this never blew up. Signed-off-by: Timo Rothenpieler --- libavcodec/nvenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 0ecaa15162469..a8194231ae687 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -1797,6 +1797,8 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur ctx->registered_frames[tmpoutsurf->reg_idx].mapped -= 1; if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped == 0) { p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->registered_frames[tmpoutsurf->reg_idx].in_map.mappedResource); + p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[tmpoutsurf->reg_idx].regptr); + ctx->registered_frames[tmpoutsurf->reg_idx].regptr = NULL; } else if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped < 0) { res = AVERROR_BUG; goto error; From 48e52e4edd12adbc36eee0eebe1b97ffe0255be3 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sun, 28 Jan 2018 12:51:20 +0100 Subject: [PATCH 1742/2557] avcodec/nvenc: add some more error case checks Signed-off-by: Timo Rothenpieler --- libavcodec/nvenc.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index a8194231ae687..7038a49d9022e 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -1529,6 +1529,7 @@ static int nvenc_find_free_reg_resource(AVCodecContext *avctx) NvencContext *ctx = avctx->priv_data; NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; + NVENCSTATUS nv_status; int i; @@ -1536,8 +1537,9 @@ static int nvenc_find_free_reg_resource(AVCodecContext *avctx) for (i = 0; i < ctx->nb_registered_frames; i++) { if (!ctx->registered_frames[i].mapped) { if (ctx->registered_frames[i].regptr) { - p_nvenc->nvEncUnregisterResource(ctx->nvencoder, - ctx->registered_frames[i].regptr); + nv_status = p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[i].regptr); + if (nv_status != NV_ENC_SUCCESS) + return nvenc_print_error(avctx, nv_status, "Failed unregistering unused input resource"); ctx->registered_frames[i].regptr = NULL; } return i; @@ -1789,15 +1791,25 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur memcpy(pkt->data, lock_params.bitstreamBufferPtr, lock_params.bitstreamSizeInBytes); nv_status = p_nvenc->nvEncUnlockBitstream(ctx->nvencoder, tmpoutsurf->output_surface); - if (nv_status != NV_ENC_SUCCESS) - nvenc_print_error(avctx, nv_status, "Failed unlocking bitstream buffer, expect the gates of mordor to open"); + if (nv_status != NV_ENC_SUCCESS) { + res = nvenc_print_error(avctx, nv_status, "Failed unlocking bitstream buffer, expect the gates of mordor to open"); + goto error; + } if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) { ctx->registered_frames[tmpoutsurf->reg_idx].mapped -= 1; if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped == 0) { - p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->registered_frames[tmpoutsurf->reg_idx].in_map.mappedResource); - p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[tmpoutsurf->reg_idx].regptr); + nv_status = p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->registered_frames[tmpoutsurf->reg_idx].in_map.mappedResource); + if (nv_status != NV_ENC_SUCCESS) { + res = nvenc_print_error(avctx, nv_status, "Failed unmapping input resource"); + goto error; + } + nv_status = p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[tmpoutsurf->reg_idx].regptr); + if (nv_status != NV_ENC_SUCCESS) { + res = nvenc_print_error(avctx, nv_status, "Failed unregistering input resource"); + goto error; + } ctx->registered_frames[tmpoutsurf->reg_idx].regptr = NULL; } else if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped < 0) { res = AVERROR_BUG; From 932037c6bb6b41a24e75b031426844a2e6472a74 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sun, 28 Jan 2018 13:05:09 +0100 Subject: [PATCH 1743/2557] avcodec/nvenc: also clear data pointer after unregistering a resource Signed-off-by: Timo Rothenpieler --- libavcodec/nvenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 7038a49d9022e..39c3aa1fbb2a5 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -1540,6 +1540,7 @@ static int nvenc_find_free_reg_resource(AVCodecContext *avctx) nv_status = p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[i].regptr); if (nv_status != NV_ENC_SUCCESS) return nvenc_print_error(avctx, nv_status, "Failed unregistering unused input resource"); + ctx->registered_frames[i].ptr = NULL; ctx->registered_frames[i].regptr = NULL; } return i; @@ -1810,6 +1811,7 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur res = nvenc_print_error(avctx, nv_status, "Failed unregistering input resource"); goto error; } + ctx->registered_frames[tmpoutsurf->reg_idx].ptr = NULL; ctx->registered_frames[tmpoutsurf->reg_idx].regptr = NULL; } else if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped < 0) { res = AVERROR_BUG; From 3f621455d62e46745453568d915badd5b1e5bcd5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 28 Jan 2018 02:46:56 +0100 Subject: [PATCH 1744/2557] avfilter/vf_transpose: Fix regression with packed pixel formats Regression since: c6939f65a116b1ffed345d29d8621ee4ffb32235 Found-by: Paul B Mahol Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer --- libavfilter/vf_transpose.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c index 1e1a5c4b893d5..3ff4cb424961b 100644 --- a/libavfilter/vf_transpose.c +++ b/libavfilter/vf_transpose.c @@ -217,7 +217,7 @@ static int config_props_output(AVFilterLink *outlink) s->hsub = desc_in->log2_chroma_w; s->vsub = desc_in->log2_chroma_h; - s->planes = desc_in->nb_components; + s->planes = av_pix_fmt_count_planes(outlink->format); av_assert0(desc_in->nb_components == desc_out->nb_components); From 293f24b42c5d116172510768802d85de3d7d0d62 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 28 Jan 2018 13:34:07 +0100 Subject: [PATCH 1745/2557] fate: test the transpose filter more fully Signed-off-by: Michael Niedermayer --- tests/fate/filter-video.mak | 3 + tests/ref/fate/filter-pixfmts-transpose | 108 ++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 tests/ref/fate/filter-pixfmts-transpose diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index bf6e2c6f84cdb..221ae81fdc8c7 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -684,6 +684,9 @@ fate-filter-pixfmts-tinterlace_pad: CMD = pixfmts "pad" FATE_FILTER_PIXFMTS-$(CONFIG_TINTERLACE_FILTER) += fate-filter-pixfmts-tinterlace_vlpf fate-filter-pixfmts-tinterlace_vlpf: CMD = pixfmts "interleave_top:vlpf" +FATE_FILTER_PIXFMTS-$(CONFIG_TRANSPOSE_FILTER) += fate-filter-pixfmts-transpose +fate-filter-pixfmts-transpose: CMD = pixfmts "dir=cclock_flip" + FATE_FILTER_PIXFMTS-$(CONFIG_VFLIP_FILTER) += fate-filter-pixfmts-vflip fate-filter-pixfmts-vflip: CMD = pixfmts diff --git a/tests/ref/fate/filter-pixfmts-transpose b/tests/ref/fate/filter-pixfmts-transpose new file mode 100644 index 0000000000000..6f25f3dd2752d --- /dev/null +++ b/tests/ref/fate/filter-pixfmts-transpose @@ -0,0 +1,108 @@ +0bgr 6929c1e308d2f4f941d002627047d262 +0rgb cf1bedd0784a3efd3ab00c4e44005c37 +abgr 6d6f896f853a6c6f93ee70dba9af3d17 +argb 87bbd23debb94d486ac3a6b6c0b005f9 +ayuv64le e4c07e0d5b333b3bc9eb4f3ce6af3a2c +bgr0 df3a6eedd4939ce09a357b655ac2962a +bgr24 f9a08135e5d58c0b2a5509c369a88414 +bgr444be dd9e990a327649ec0b2b81a8ee4d8f49 +bgr444le bee1d9fae8733d0c0669bca2ac4dfaf6 +bgr48be 39f48f6353dfc772af36cbb41e6126a4 +bgr48le 9a61d9531b1f6de44b27f6bb9b4dfc79 +bgr4_byte ddff9da461afce90e3122a41d79b287d +bgr555be 24e5c6502a6d927f8ba88f3320ebf619 +bgr555le 5201d098979ea86a66d8df1ef41c79ad +bgr565be 59afe17b455e921daf428ba05a40bab9 +bgr565le b2709790684abbd2133906b637f2b4b8 +bgr8 b6ee15f70989d2f52f184e32b3af2c18 +bgra f2fe61e08446900ad209f2c586997e15 +bgra64be 8d01994c8c32e628fcf9749851f1ffe8 +bgra64le faaef6d280f92e7e8abdd9fa4a61f7b5 +gbrap 0899b3af50d35a63bfecb419a5b29968 +gbrap10be 3e3be2d8f9aa5f449a1df404e27d0054 +gbrap10le db4e4861010cbbf726492fad282d5813 +gbrap12be 1518c9a565d1ba1a45dd369acc1aa75e +gbrap12le 714fe318af81a46f83655c6e7e13351e +gbrap16be 39d488528aacff466aac7539c9b948a8 +gbrap16le 5426ac9457289927bfe2ec03038a8780 +gbrp 7b4b6a2f1cdc51455b25515c3ecea944 +gbrp10be d7401725699b2ddf954caa16a0878a1e +gbrp10le 6036711969eae1979be6358f688bd9c8 +gbrp12be ec7d6e69fc579619b53d57a76c20480d +gbrp12le bf7478185274486c3f7dd4db1da8f7d0 +gbrp14be 9b66f22e4315aaa878a430ae3f44ab57 +gbrp14le 16f30349b42dca007b37b8522d3018df +gbrp16be 0d003b88d4f446ae9ba12cab1cbb359a +gbrp16le a1c09038fa4636c9843ab8dd2b7601ea +gbrp9be df381b4b27be25d172fa556434478807 +gbrp9le a5301e978f68b29bfc613b2462ec4888 +gray c5f8bc6636fd15dbc57deb4bba1e7379 +gray10be 48b421da79c195fd91dffb8fca79a8a2 +gray10le 7774e3296916b896afa46f626334a280 +gray12be 89f1c4b7821b771f6d967f9db871f8ef +gray12le 43d392c3dcbd79b47cce31f2006c5050 +gray16be 4aef307021a91b1de67f1d4381a39132 +gray16le 76f2afe156edca7ae05cfa4e5867126e +gray9be 2c425fa532c940d226822da8b3592310 +gray9le bcc575942910b3c72eaa72e8794f3acd +nv12 aca847644e5dc0e942419183014981a4 +nv21 098884e968d27286c8cf0d2fb1557dcd +p010be 5ff62dffa5dfdf823978c4f563f69c94 +p010le 20131abe34e084b04f1d169c66447825 +rgb0 31ea5da7fe779c6ea0a33f1d28aad918 +rgb24 47654cabaaad79170b90afd5a02161dd +rgb444be 3cac1f0c43a74d2a95eb02e187070845 +rgb444le 46d602468bd9e5a430622e3d4b7c8f40 +rgb48be 400932419bbb780614254253ef5591c3 +rgb48le 6a99c40f21629cb0655e8772d7190374 +rgb4_byte d3990da196266305a3f2e5b1d72401a5 +rgb555be 79e4503ff0d5cf52d3a7901397499a28 +rgb555le c65f2594c0b3107a322f7aeb81aa8a16 +rgb565be 0c746b5063d02d6cb98e9e9a59ad3b99 +rgb565le 63b02db11c3d20be54d218c7c44f8ddb +rgb8 c90feb30c3c9391ef5f470209d7b7a15 +rgba 4d76a9542143752a4ac30f82f88f68f1 +rgba64be a60041217f4c0cd796d19d3940a12a41 +rgba64le ad47197774858858ae7b0c177dffa459 +xyz12be 68e5cba640f6e4ef72dff950e88b5342 +xyz12le 8b6b6a6db4d7561e80db88ccaecce7a9 +ya8 d4b7a62f80681fa44c977ff3a64f4ce4 +yuv410p 4c0143429edd30aa01493447c90132ea +yuv420p 2fa5b2201c75034206cc20e2c6134aed +yuv420p10be 0931660f930d9be8aea9d0c76b406055 +yuv420p10le 9ce12b168c49db871836c979b526c1f1 +yuv420p12be 73d6be4230b6f4e4e269977afab56323 +yuv420p12le 6938815c8acd690138506cbb5f005fb8 +yuv420p14be bf76a805b9c2f9808c73492d3b8da268 +yuv420p14le 5df47483b89ffe6ef4bbf14058d7d3b3 +yuv420p16be 3a64132681656be6db635f4e6a282dc9 +yuv420p16le c77a81e47d1690a338693ec6f323ef1e +yuv420p9be 2307cb7f324df299c4829b11cb0e6bc7 +yuv420p9le c735c3c8424c70d822ab4a1fe1f504e2 +yuv444p eb755977ca464baac5f03771858080ae +yuv444p10be 866b59a23dff3dc1cb6bf7bd7da26da4 +yuv444p10le 417d62f15abf4777c4ec5e0d00796a9e +yuv444p12be c1da110f0ee898fbcd4b45afb5aed58b +yuv444p12le dc18bddd7b6bb9fdb2e0c7e7476375fa +yuv444p14be 2f181fa3403e7911b233d3d976abea73 +yuv444p14le ac718343878786a25b9a50924f9aabca +yuv444p16be 128214efef6fffe3293db513ae700d4a +yuv444p16le a8b6613094b8d2b275e2e4bc4512c9e4 +yuv444p9be eae529dd1cdb7f512ae2674334c1ef08 +yuv444p9le 06ffcacdd03f6457614c352a4ccb7642 +yuva420p 058d00d9564be827e5db6ce2b8b2dbb5 +yuva420p10be 333209d11916161a65c6453d2bf435c2 +yuva420p10le 4b7ea5b59a712f1f59cd394b3b40ff69 +yuva420p16be 5984c7f4d14e4cf0e511cb0aa6c53089 +yuva420p16le 34e29fc4a22a0ab1ea01641d0df2ac86 +yuva420p9be 45ea80889575b31cccc83a4d16555497 +yuva420p9le 6e5cb3e761a9c45e26370307c49f8831 +yuva444p 4f9e649fbc2c0c91178d1576e462bb31 +yuva444p10be 9450fbac30b5f9da7414c895695591a9 +yuva444p10le 84a93637bf2c7e498380beff9b1fc503 +yuva444p16be 9fd2f00ea9bef8e488228bc0b47b28cb +yuva444p16le ae9fd8d1baea0f8626b963816d667d2d +yuva444p9be 4ce11ae57780f74c78cdd5c06be4bded +yuva444p9le 1b9cc85fd6ab0c7e240915a99e98d1c1 +yuvj420p 9603b8dd64daec41f0514197989c2b19 +yuvj444p 66ec9b3219df9eb2c1315d293602ab42 From 5bf774a4a448418c6977c744fbf1ec74659eb0d3 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 8 Jan 2018 21:01:09 +0100 Subject: [PATCH 1746/2557] avfilter/vf_framerate: unify luma and chroma blending The expressions were mathematically equvivalent... Signed-off-by: Marton Balint --- libavfilter/vf_framerate.c | 60 ++++++++++---------------------------- 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index a5ae6ddb7135c..583c96e02c538 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -196,32 +196,16 @@ static int filter_slice8(AVFilterContext *ctx, void *arg, int job, int nb_jobs) cpy_src2_data += start * cpy_src2_line_size; cpy_dst_data += start * cpy_dst_line_size; - if (plane <1 || plane >2) { - // luma or alpha - for (line = start; line < end; line++) { - for (pixel = 0; pixel < cpy_line_width; pixel++) { - // integer version of (src1 * src1_factor) + (src2 + src2_factor) + 0.5 - // 0.5 is for rounding - // 128 is the integer representation of 0.5 << 8 - cpy_dst_data[pixel] = ((cpy_src1_data[pixel] * src1_factor) + (cpy_src2_data[pixel] * src2_factor) + 128) >> 8; - } - cpy_src1_data += cpy_src1_line_size; - cpy_src2_data += cpy_src2_line_size; - cpy_dst_data += cpy_dst_line_size; - } - } else { - // chroma - for (line = start; line < end; line++) { - for (pixel = 0; pixel < cpy_line_width; pixel++) { - // as above - // because U and V are based around 128 we have to subtract 128 from the components. - // 32896 is the integer representation of 128.5 << 8 - cpy_dst_data[pixel] = (((cpy_src1_data[pixel] - 128) * src1_factor) + ((cpy_src2_data[pixel] - 128) * src2_factor) + 32896) >> 8; - } - cpy_src1_data += cpy_src1_line_size; - cpy_src2_data += cpy_src2_line_size; - cpy_dst_data += cpy_dst_line_size; + for (line = start; line < end; line++) { + for (pixel = 0; pixel < cpy_line_width; pixel++) { + // integer version of (src1 * src1_factor) + (src2 + src2_factor) + 0.5 + // 0.5 is for rounding + // 128 is the integer representation of 0.5 << 8 + cpy_dst_data[pixel] = ((cpy_src1_data[pixel] * src1_factor) + (cpy_src2_data[pixel] * src2_factor) + 128) >> 8; } + cpy_src1_data += cpy_src1_line_size; + cpy_src2_data += cpy_src2_line_size; + cpy_dst_data += cpy_dst_line_size; } } @@ -235,7 +219,6 @@ static int filter_slice16(AVFilterContext *ctx, void *arg, int job, int nb_jobs) uint16_t src1_factor = td->src1_factor; uint16_t src2_factor = td->src2_factor; const int half = s->max / 2; - const int uv = (s->max + 1) * half; const int shift = s->bitdepth; int plane, line, pixel; @@ -254,25 +237,12 @@ static int filter_slice16(AVFilterContext *ctx, void *arg, int job, int nb_jobs) cpy_src2_data += start * cpy_src2_line_size; cpy_dst_data += start * cpy_dst_line_size; - if (plane <1 || plane >2) { - // luma or alpha - for (line = start; line < end; line++) { - for (pixel = 0; pixel < cpy_line_width; pixel++) - cpy_dst_data[pixel] = ((cpy_src1_data[pixel] * src1_factor) + (cpy_src2_data[pixel] * src2_factor) + half) >> shift; - cpy_src1_data += cpy_src1_line_size; - cpy_src2_data += cpy_src2_line_size; - cpy_dst_data += cpy_dst_line_size; - } - } else { - // chroma - for (line = start; line < end; line++) { - for (pixel = 0; pixel < cpy_line_width; pixel++) { - cpy_dst_data[pixel] = (((cpy_src1_data[pixel] - half) * src1_factor) + ((cpy_src2_data[pixel] - half) * src2_factor) + uv) >> shift; - } - cpy_src1_data += cpy_src1_line_size; - cpy_src2_data += cpy_src2_line_size; - cpy_dst_data += cpy_dst_line_size; - } + for (line = start; line < end; line++) { + for (pixel = 0; pixel < cpy_line_width; pixel++) + cpy_dst_data[pixel] = ((cpy_src1_data[pixel] * src1_factor) + (cpy_src2_data[pixel] * src2_factor) + half) >> shift; + cpy_src1_data += cpy_src1_line_size; + cpy_src2_data += cpy_src2_line_size; + cpy_dst_data += cpy_dst_line_size; } } From 1b6ffe9aca1bdcc0bf2249c8c1314faa1ab0dae6 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 8 Jan 2018 21:44:42 +0100 Subject: [PATCH 1747/2557] avfilter/vf_framerate: factorize blend functions and unify filter_slice Signed-off-by: Marton Balint --- libavfilter/vf_framerate.c | 108 +++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 51 deletions(-) diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index 583c96e02c538..2a6d692eb0d14 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -39,6 +39,14 @@ #include "internal.h" #include "video.h" +#define BLEND_FUNC_PARAMS const uint8_t *src1, ptrdiff_t src1_linesize, \ + const uint8_t *src2, ptrdiff_t src2_linesize, \ + uint8_t *dst, ptrdiff_t dst_linesize, \ + ptrdiff_t width, ptrdiff_t height, \ + int factor1, int factor2, int half, int shift + +typedef void (*blend_func)(BLEND_FUNC_PARAMS); + typedef struct FrameRateContext { const AVClass *class; // parameters @@ -72,6 +80,8 @@ typedef struct FrameRateContext { int flush; ///< 1 if the filter is being flushed int64_t start_pts; ///< pts of the first output frame int64_t n; ///< output frame counter + + blend_func blend; } FrameRateContext; #define OFFSET(x) offsetof(FrameRateContext, x) @@ -173,13 +183,13 @@ typedef struct ThreadData { uint16_t src1_factor, src2_factor; } ThreadData; -static int filter_slice8(AVFilterContext *ctx, void *arg, int job, int nb_jobs) +static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) { FrameRateContext *s = ctx->priv; ThreadData *td = arg; uint16_t src1_factor = td->src1_factor; uint16_t src2_factor = td->src2_factor; - int plane, line, pixel; + int plane; for (plane = 0; plane < 4 && td->copy_src1->data[plane] && td->copy_src2->data[plane]; plane++) { int cpy_line_width = s->line_size[plane]; @@ -196,54 +206,11 @@ static int filter_slice8(AVFilterContext *ctx, void *arg, int job, int nb_jobs) cpy_src2_data += start * cpy_src2_line_size; cpy_dst_data += start * cpy_dst_line_size; - for (line = start; line < end; line++) { - for (pixel = 0; pixel < cpy_line_width; pixel++) { - // integer version of (src1 * src1_factor) + (src2 + src2_factor) + 0.5 - // 0.5 is for rounding - // 128 is the integer representation of 0.5 << 8 - cpy_dst_data[pixel] = ((cpy_src1_data[pixel] * src1_factor) + (cpy_src2_data[pixel] * src2_factor) + 128) >> 8; - } - cpy_src1_data += cpy_src1_line_size; - cpy_src2_data += cpy_src2_line_size; - cpy_dst_data += cpy_dst_line_size; - } - } - - return 0; -} - -static int filter_slice16(AVFilterContext *ctx, void *arg, int job, int nb_jobs) -{ - FrameRateContext *s = ctx->priv; - ThreadData *td = arg; - uint16_t src1_factor = td->src1_factor; - uint16_t src2_factor = td->src2_factor; - const int half = s->max / 2; - const int shift = s->bitdepth; - int plane, line, pixel; - - for (plane = 0; plane < 4 && td->copy_src1->data[plane] && td->copy_src2->data[plane]; plane++) { - int cpy_line_width = s->line_size[plane]; - const uint16_t *cpy_src1_data = (const uint16_t *)td->copy_src1->data[plane]; - int cpy_src1_line_size = td->copy_src1->linesize[plane] / 2; - const uint16_t *cpy_src2_data = (const uint16_t *)td->copy_src2->data[plane]; - int cpy_src2_line_size = td->copy_src2->linesize[plane] / 2; - int cpy_src_h = (plane > 0 && plane < 3) ? (td->copy_src1->height >> s->vsub) : (td->copy_src1->height); - uint16_t *cpy_dst_data = (uint16_t *)s->work->data[plane]; - int cpy_dst_line_size = s->work->linesize[plane] / 2; - const int start = (cpy_src_h * job ) / nb_jobs; - const int end = (cpy_src_h * (job+1)) / nb_jobs; - cpy_src1_data += start * cpy_src1_line_size; - cpy_src2_data += start * cpy_src2_line_size; - cpy_dst_data += start * cpy_dst_line_size; - - for (line = start; line < end; line++) { - for (pixel = 0; pixel < cpy_line_width; pixel++) - cpy_dst_data[pixel] = ((cpy_src1_data[pixel] * src1_factor) + (cpy_src2_data[pixel] * src2_factor) + half) >> shift; - cpy_src1_data += cpy_src1_line_size; - cpy_src2_data += cpy_src2_line_size; - cpy_dst_data += cpy_dst_line_size; - } + s->blend(cpy_src1_data, cpy_src1_line_size, + cpy_src2_data, cpy_src2_line_size, + cpy_dst_data, cpy_dst_line_size, + cpy_line_width, end - start, + src1_factor, src2_factor, s->max / 2, s->bitdepth); } return 0; @@ -278,7 +245,7 @@ static int blend_frames(AVFilterContext *ctx, int interpolate) av_frame_copy_props(s->work, s->f0); ff_dlog(ctx, "blend_frames() INTERPOLATE to create work frame\n"); - ctx->internal->execute(ctx, s->bitdepth == 8 ? filter_slice8 : filter_slice16, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); + ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); return 1; } return 0; @@ -366,6 +333,41 @@ static int query_formats(AVFilterContext *ctx) return ff_set_common_formats(ctx, fmts_list); } +static void blend_frames_c(BLEND_FUNC_PARAMS) +{ + int line, pixel; + for (line = 0; line < height; line++) { + for (pixel = 0; pixel < width; pixel++) { + // integer version of (src1 * factor1) + (src2 * factor2) + 0.5 + // 0.5 is for rounding + // 128 is the integer representation of 0.5 << 8 + dst[pixel] = ((src1[pixel] * factor1) + (src2[pixel] * factor2) + 128) >> 8; + } + src1 += src1_linesize; + src2 += src2_linesize; + dst += dst_linesize; + } +} + +static void blend_frames16_c(BLEND_FUNC_PARAMS) +{ + int line, pixel; + uint16_t *dstw = (uint16_t *)dst; + uint16_t *src1w = (uint16_t *)src1; + uint16_t *src2w = (uint16_t *)src2; + width /= 2; + src1_linesize /= 2; + src2_linesize /= 2; + dst_linesize /= 2; + for (line = 0; line < height; line++) { + for (pixel = 0; pixel < width; pixel++) + dstw[pixel] = ((src1w[pixel] * factor1) + (src2w[pixel] * factor2) + half) >> shift; + src1w += src1_linesize; + src2w += src2_linesize; + dstw += dst_linesize; + } +} + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -390,6 +392,10 @@ static int config_input(AVFilterLink *inlink) s->srce_time_base = inlink->time_base; s->max = 1 << (s->bitdepth); + if (s->bitdepth == 8) + s->blend = blend_frames_c; + else + s->blend = blend_frames16_c; return 0; } From 2cbe6bac0337939f023bd1c37a9c455e6d535f3a Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 15 Jan 2018 22:19:46 +0100 Subject: [PATCH 1748/2557] avfilter/vf_framerate: change blend factor precision This is done mainly in preparation for the SIMD patches. - for the 8-bit input, decrease the blend factor precision to 7-bit. - for the 16-bit input, increase the blend factor precision to 15-bit. - make sure the blend functions are not called with 0 or maximum blending factors, because we don't want the signed factor integers to overflow. Fate test changes are due to different rounding. Signed-off-by: Marton Balint --- libavfilter/vf_framerate.c | 54 +++++++-------- tests/ref/fate/filter-framerate-12bit-down | 80 +++++++++++----------- tests/ref/fate/filter-framerate-12bit-up | 78 ++++++++++----------- tests/ref/fate/filter-framerate-up | 8 +-- 4 files changed, 109 insertions(+), 111 deletions(-) diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index 2a6d692eb0d14..8119fe2bfd237 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -43,7 +43,10 @@ const uint8_t *src2, ptrdiff_t src2_linesize, \ uint8_t *dst, ptrdiff_t dst_linesize, \ ptrdiff_t width, ptrdiff_t height, \ - int factor1, int factor2, int half, int shift + int factor1, int factor2, int half + +#define BLEND_FACTOR_DEPTH8 7 +#define BLEND_FACTOR_DEPTH16 15 typedef void (*blend_func)(BLEND_FUNC_PARAMS); @@ -53,10 +56,8 @@ typedef struct FrameRateContext { AVRational dest_frame_rate; ///< output frames per second int flags; ///< flags affecting frame rate conversion algorithm double scene_score; ///< score that denotes a scene change has happened - int interp_start; ///< start of range to apply linear interpolation (same bitdepth as input) - int interp_end; ///< end of range to apply linear interpolation (same bitdepth as input) - int interp_start_param; ///< start of range to apply linear interpolation - int interp_end_param; ///< end of range to apply linear interpolation + int interp_start; ///< start of range to apply linear interpolation + int interp_end; ///< end of range to apply linear interpolation int line_size[4]; ///< bytes of pixel data per line for each plane int vsub; @@ -67,7 +68,7 @@ typedef struct FrameRateContext { av_pixelutils_sad_fn sad; ///< Sum of the absolute difference function (scene detect only) double prev_mafd; ///< previous MAFD (scene detect only) - int max; + int blend_factor_max; int bitdepth; AVFrame *work; @@ -92,8 +93,8 @@ typedef struct FrameRateContext { static const AVOption framerate_options[] = { {"fps", "required output frames per second rate", OFFSET(dest_frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="50"}, 0, INT_MAX, V|F }, - {"interp_start", "point to start linear interpolation", OFFSET(interp_start_param),AV_OPT_TYPE_INT, {.i64=15}, 0, 255, V|F }, - {"interp_end", "point to end linear interpolation", OFFSET(interp_end_param), AV_OPT_TYPE_INT, {.i64=240}, 0, 255, V|F }, + {"interp_start", "point to start linear interpolation", OFFSET(interp_start), AV_OPT_TYPE_INT, {.i64=15}, 0, 255, V|F }, + {"interp_end", "point to end linear interpolation", OFFSET(interp_end), AV_OPT_TYPE_INT, {.i64=240}, 0, 255, V|F }, {"scene", "scene change level", OFFSET(scene_score), AV_OPT_TYPE_DOUBLE, {.dbl=8.2}, 0, INT_MAX, V|F }, {"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, INT_MAX, V|F, "flags" }, @@ -210,7 +211,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) cpy_src2_data, cpy_src2_line_size, cpy_dst_data, cpy_dst_line_size, cpy_line_width, end - start, - src1_factor, src2_factor, s->max / 2, s->bitdepth); + src1_factor, src2_factor, s->blend_factor_max >> 1); } return 0; @@ -235,7 +236,7 @@ static int blend_frames(AVFilterContext *ctx, int interpolate) td.copy_src1 = s->f0; td.copy_src2 = s->f1; td.src2_factor = interpolate; - td.src1_factor = s->max - td.src2_factor; + td.src1_factor = s->blend_factor_max - td.src2_factor; // get work-space for output frame s->work = ff_get_video_buffer(outlink, outlink->w, outlink->h); @@ -255,7 +256,7 @@ static int process_work_frame(AVFilterContext *ctx) { FrameRateContext *s = ctx->priv; int64_t work_pts; - int interpolate; + int64_t interpolate, interpolate8; int ret; if (!s->f1) @@ -274,18 +275,19 @@ static int process_work_frame(AVFilterContext *ctx) if (work_pts >= s->pts1 + s->delta && s->flush) return 0; - interpolate = av_rescale(work_pts - s->pts0, s->max, s->delta); - ff_dlog(ctx, "process_work_frame() interpolate:%d/%d\n", interpolate, s->max); - if (interpolate > s->interp_end) { + interpolate = av_rescale(work_pts - s->pts0, s->blend_factor_max, s->delta); + interpolate8 = av_rescale(work_pts - s->pts0, 256, s->delta); + ff_dlog(ctx, "process_work_frame() interpolate: %"PRId64"/256\n", interpolate8); + if (interpolate >= s->blend_factor_max || interpolate8 > s->interp_end) { s->work = av_frame_clone(s->f1); - } else if (interpolate < s->interp_start) { + } else if (interpolate <= 0 || interpolate8 < s->interp_start) { s->work = av_frame_clone(s->f0); } else { ret = blend_frames(ctx, interpolate); if (ret < 0) return ret; if (ret == 0) - s->work = av_frame_clone(interpolate > (s->max >> 1) ? s->f1 : s->f0); + s->work = av_frame_clone(interpolate > (s->blend_factor_max >> 1) ? s->f1 : s->f0); } } @@ -337,12 +339,8 @@ static void blend_frames_c(BLEND_FUNC_PARAMS) { int line, pixel; for (line = 0; line < height; line++) { - for (pixel = 0; pixel < width; pixel++) { - // integer version of (src1 * factor1) + (src2 * factor2) + 0.5 - // 0.5 is for rounding - // 128 is the integer representation of 0.5 << 8 - dst[pixel] = ((src1[pixel] * factor1) + (src2[pixel] * factor2) + 128) >> 8; - } + for (pixel = 0; pixel < width; pixel++) + dst[pixel] = ((src1[pixel] * factor1) + (src2[pixel] * factor2) + half) >> BLEND_FACTOR_DEPTH8; src1 += src1_linesize; src2 += src2_linesize; dst += dst_linesize; @@ -361,7 +359,7 @@ static void blend_frames16_c(BLEND_FUNC_PARAMS) dst_linesize /= 2; for (line = 0; line < height; line++) { for (pixel = 0; pixel < width; pixel++) - dstw[pixel] = ((src1w[pixel] * factor1) + (src2w[pixel] * factor2) + half) >> shift; + dstw[pixel] = ((src1w[pixel] * factor1) + (src2w[pixel] * factor2) + half) >> BLEND_FACTOR_DEPTH16; src1w += src1_linesize; src2w += src2_linesize; dstw += dst_linesize; @@ -382,8 +380,6 @@ static int config_input(AVFilterLink *inlink) s->bitdepth = pix_desc->comp[0].depth; s->vsub = pix_desc->log2_chroma_h; - s->interp_start = s->interp_start_param << (s->bitdepth - 8); - s->interp_end = s->interp_end_param << (s->bitdepth - 8); s->sad = av_pixelutils_get_sad_fn(3, 3, 2, s); // 8x8 both sources aligned if (!s->sad) @@ -391,11 +387,13 @@ static int config_input(AVFilterLink *inlink) s->srce_time_base = inlink->time_base; - s->max = 1 << (s->bitdepth); - if (s->bitdepth == 8) + if (s->bitdepth == 8) { + s->blend_factor_max = 1 << BLEND_FACTOR_DEPTH8; s->blend = blend_frames_c; - else + } else { + s->blend_factor_max = 1 << BLEND_FACTOR_DEPTH16; s->blend = blend_frames16_c; + } return 0; } diff --git a/tests/ref/fate/filter-framerate-12bit-down b/tests/ref/fate/filter-framerate-12bit-down index 49dcb1e5fa492..25a3c0a53a7af 100644 --- a/tests/ref/fate/filter-framerate-12bit-down +++ b/tests/ref/fate/filter-framerate-12bit-down @@ -4,52 +4,52 @@ #dimensions 0: 320x240 #sar 0: 1/1 0, 0, 0, 1, 307200, 0xb49cf016 -0, 1, 1, 1, 307200, 0xc3be6971 -0, 2, 2, 1, 307200, 0x4d458da1 -0, 3, 3, 1, 307200, 0xb49ed940 -0, 4, 4, 1, 307200, 0x1577849f +0, 1, 1, 1, 307200, 0xbccf696d +0, 2, 2, 1, 307200, 0x709c8dd1 +0, 3, 3, 1, 307200, 0xb948d907 +0, 4, 4, 1, 307200, 0x850f849a 0, 5, 5, 1, 307200, 0xaf71e7fc -0, 6, 6, 1, 307200, 0x1290a487 -0, 7, 7, 1, 307200, 0xaf0cf5ee -0, 8, 8, 1, 307200, 0x6ffb3abb -0, 9, 9, 1, 307200, 0x9e65597e +0, 6, 6, 1, 307200, 0x0a1ba486 +0, 7, 7, 1, 307200, 0x0601f62a +0, 8, 8, 1, 307200, 0x2c6d3a59 +0, 9, 9, 1, 307200, 0xed03597b 0, 10, 10, 1, 307200, 0x9f84df5d -0, 11, 11, 1, 307200, 0xf60b8c87 -0, 12, 12, 1, 307200, 0xe2eac3a7 -0, 13, 13, 1, 307200, 0x2c4ac771 -0, 14, 14, 1, 307200, 0xf4d9003d +0, 11, 11, 1, 307200, 0x9fbe8c84 +0, 12, 12, 1, 307200, 0x8f7bc394 +0, 13, 13, 1, 307200, 0x5113c787 +0, 14, 14, 1, 307200, 0x41e8002f 0, 15, 15, 1, 307200, 0xab2162fc -0, 16, 16, 1, 307200, 0xdc90848a -0, 17, 17, 1, 307200, 0x29f79f4b -0, 18, 18, 1, 307200, 0x45b1e01b -0, 19, 19, 1, 307200, 0x43baddc2 +0, 16, 16, 1, 307200, 0xbf8f847c +0, 17, 17, 1, 307200, 0x832d9ef7 +0, 18, 18, 1, 307200, 0xd2f5e043 +0, 19, 19, 1, 307200, 0xceeaddb8 0, 20, 20, 1, 307200, 0xf2b12fe5 -0, 21, 21, 1, 307200, 0x1de67e13 -0, 22, 22, 1, 307200, 0xfc1f7774 -0, 23, 23, 1, 307200, 0x5552e7f2 -0, 24, 24, 1, 307200, 0xb1d60366 +0, 21, 21, 1, 307200, 0xf3477e11 +0, 22, 22, 1, 307200, 0xdf387773 +0, 23, 23, 1, 307200, 0x273be7e2 +0, 24, 24, 1, 307200, 0x68cd0360 0, 25, 25, 1, 307200, 0x4693ab03 -0, 26, 26, 1, 307200, 0x7295ef7a -0, 27, 27, 1, 307200, 0xf442a5df -0, 28, 28, 1, 307200, 0x01e0dbb8 -0, 29, 29, 1, 307200, 0xf10c3549 +0, 26, 26, 1, 307200, 0xe2baef73 +0, 27, 27, 1, 307200, 0x0c9fa60a +0, 28, 28, 1, 307200, 0x6e4ddbc5 +0, 29, 29, 1, 307200, 0xd1b2353c 0, 30, 30, 1, 307200, 0x8a512668 -0, 31, 31, 1, 307200, 0x69e7b43e -0, 32, 32, 1, 307200, 0x6c5343ca -0, 33, 33, 1, 307200, 0xf323456c -0, 34, 34, 1, 307200, 0xeead5632 +0, 31, 31, 1, 307200, 0x7224b439 +0, 32, 32, 1, 307200, 0x7a9243e2 +0, 33, 33, 1, 307200, 0x9a7e4553 +0, 34, 34, 1, 307200, 0x4d795626 0, 35, 35, 1, 307200, 0x4e24d659 -0, 36, 36, 1, 307200, 0x7a25b546 -0, 37, 37, 1, 307200, 0x9b7e8e8f -0, 38, 38, 1, 307200, 0x9d059d4c -0, 39, 39, 1, 307200, 0x21c4a16f +0, 36, 36, 1, 307200, 0xa230b54b +0, 37, 37, 1, 307200, 0x14598ea5 +0, 38, 38, 1, 307200, 0x21619cf3 +0, 39, 39, 1, 307200, 0x5220a167 0, 40, 40, 1, 307200, 0xb6505ff0 -0, 41, 41, 1, 307200, 0x12562a42 -0, 42, 42, 1, 307200, 0x3335e451 -0, 43, 43, 1, 307200, 0x6f1274cf -0, 44, 44, 1, 307200, 0xa52e71d2 +0, 41, 41, 1, 307200, 0x0a482a3d +0, 42, 42, 1, 307200, 0x6bdce40c +0, 43, 43, 1, 307200, 0x3c6074f3 +0, 44, 44, 1, 307200, 0x369c71c8 0, 45, 45, 1, 307200, 0x4fda2634 -0, 46, 46, 1, 307200, 0x5b48d624 -0, 47, 47, 1, 307200, 0xa9505af8 -0, 48, 48, 1, 307200, 0xc2624880 -0, 49, 49, 1, 307200, 0x4eb317a5 +0, 46, 46, 1, 307200, 0x4df2d619 +0, 47, 47, 1, 307200, 0x21205aab +0, 48, 48, 1, 307200, 0xe00f48c2 +0, 49, 49, 1, 307200, 0xe3b11798 diff --git a/tests/ref/fate/filter-framerate-12bit-up b/tests/ref/fate/filter-framerate-12bit-up index ef709a8fc8052..15bf9be6f6403 100644 --- a/tests/ref/fate/filter-framerate-12bit-up +++ b/tests/ref/fate/filter-framerate-12bit-up @@ -4,62 +4,62 @@ #dimensions 0: 320x240 #sar 0: 1/1 0, 0, 0, 1, 307200, 0xb49cf016 -0, 1, 1, 1, 307200, 0xbe4390ed -0, 2, 2, 1, 307200, 0xe4ca172c +0, 1, 1, 1, 307200, 0x95d191b2 +0, 2, 2, 1, 307200, 0x20e5173b 0, 3, 3, 1, 307200, 0x5378b13c -0, 4, 4, 1, 307200, 0xe742454c -0, 5, 5, 1, 307200, 0x68f620cd +0, 4, 4, 1, 307200, 0x3e304543 +0, 5, 5, 1, 307200, 0x2f131cdb 0, 6, 6, 1, 307200, 0x83dbe321 -0, 7, 7, 1, 307200, 0x7135c77d -0, 8, 8, 1, 307200, 0xc69a864a +0, 7, 7, 1, 307200, 0xb81fc682 +0, 8, 8, 1, 307200, 0xb32a8644 0, 9, 9, 1, 307200, 0xc5c8b0f8 -0, 10, 10, 1, 307200, 0xf6ee5d1c -0, 11, 11, 1, 307200, 0xab36763c +0, 10, 10, 1, 307200, 0x27945d0a +0, 11, 11, 1, 307200, 0x444c7640 0, 12, 12, 1, 307200, 0xcba4c6bb -0, 13, 13, 1, 307200, 0xb379c679 -0, 14, 14, 1, 307200, 0x63339757 +0, 13, 13, 1, 307200, 0xf923c7a3 +0, 14, 14, 1, 307200, 0x88149757 0, 15, 15, 1, 307200, 0x4bdfd3ca -0, 16, 16, 1, 307200, 0x14e09691 -0, 17, 17, 1, 307200, 0x5dc7c711 +0, 16, 16, 1, 307200, 0x1c279695 +0, 17, 17, 1, 307200, 0x634cc809 0, 18, 18, 1, 307200, 0xda8c6c41 -0, 19, 19, 1, 307200, 0xe187c6b6 -0, 20, 20, 1, 307200, 0x5d8b76ab +0, 19, 19, 1, 307200, 0x2136c986 +0, 20, 20, 1, 307200, 0x457576a8 0, 21, 21, 1, 307200, 0xe2337c57 -0, 22, 22, 1, 307200, 0x492117d7 -0, 23, 23, 1, 307200, 0xf0df5ea3 +0, 22, 22, 1, 307200, 0x8ed517c9 +0, 23, 23, 1, 307200, 0x4fd35f99 0, 24, 24, 1, 307200, 0x4237e892 -0, 25, 25, 1, 307200, 0x4f61a7d7 -0, 26, 26, 1, 307200, 0x2ba55745 +0, 25, 25, 1, 307200, 0x1383a9d8 +0, 26, 26, 1, 307200, 0xc7195735 0, 27, 27, 1, 307200, 0x0e058165 -0, 28, 28, 1, 307200, 0xe371f352 -0, 29, 29, 1, 307200, 0xab562bfe +0, 28, 28, 1, 307200, 0x0b81f345 +0, 29, 29, 1, 307200, 0x2ddf2f0a 0, 30, 30, 1, 307200, 0x0b58bcf7 -0, 31, 31, 1, 307200, 0xf1a04a1e -0, 32, 32, 1, 307200, 0xb466f1d6 +0, 31, 31, 1, 307200, 0x1b684a1d +0, 32, 32, 1, 307200, 0x1e44f1cf 0, 33, 33, 1, 307200, 0x3ed6b5d8 -0, 34, 34, 1, 307200, 0x05091a43 -0, 35, 35, 1, 307200, 0xbfb20efc +0, 34, 34, 1, 307200, 0x00881a40 +0, 35, 35, 1, 307200, 0x2c3d1406 0, 36, 36, 1, 307200, 0xbd67248a -0, 37, 37, 1, 307200, 0x58001b29 -0, 38, 38, 1, 307200, 0x6ec5bbb1 +0, 37, 37, 1, 307200, 0x46261913 +0, 38, 38, 1, 307200, 0xe5b2bbaa 0, 39, 39, 1, 307200, 0x0e4455cd -0, 40, 40, 1, 307200, 0x5c2c3213 -0, 41, 41, 1, 307200, 0x976f6900 +0, 40, 40, 1, 307200, 0xb4943212 +0, 41, 41, 1, 307200, 0xf96b6808 0, 42, 42, 1, 307200, 0x58adad3f -0, 43, 43, 1, 307200, 0x8dbb14f0 -0, 44, 44, 1, 307200, 0x49163226 +0, 43, 43, 1, 307200, 0x978413f0 +0, 44, 44, 1, 307200, 0x0037320a 0, 45, 45, 1, 307200, 0xaac8e1ca -0, 46, 46, 1, 307200, 0x07cc8404 -0, 47, 47, 1, 307200, 0xbf85c994 +0, 46, 46, 1, 307200, 0xc3578407 +0, 47, 47, 1, 307200, 0xfc29c675 0, 48, 48, 1, 307200, 0x22ed5b5a -0, 49, 49, 1, 307200, 0x1bf7df1e -0, 50, 50, 1, 307200, 0x3a21b4d2 +0, 49, 49, 1, 307200, 0x6d58e21e +0, 50, 50, 1, 307200, 0xbf62b4c3 0, 51, 51, 1, 307200, 0xbd5edb2d -0, 52, 52, 1, 307200, 0x336a8437 -0, 53, 53, 1, 307200, 0x02c7e528 +0, 52, 52, 1, 307200, 0x55528432 +0, 53, 53, 1, 307200, 0xa3f1e514 0, 54, 54, 1, 307200, 0xba073e6f -0, 55, 55, 1, 307200, 0x9e25ddfe -0, 56, 56, 1, 307200, 0x8cf55128 +0, 55, 55, 1, 307200, 0x29b8df00 +0, 56, 56, 1, 307200, 0x1517512b 0, 57, 57, 1, 307200, 0x4e740b42 -0, 58, 58, 1, 307200, 0x8e7e705c +0, 58, 58, 1, 307200, 0xbd6b7053 0, 59, 59, 1, 307200, 0xe73f29ef diff --git a/tests/ref/fate/filter-framerate-up b/tests/ref/fate/filter-framerate-up index 15bf6d815ba09..a276bf660dce6 100644 --- a/tests/ref/fate/filter-framerate-up +++ b/tests/ref/fate/filter-framerate-up @@ -4,12 +4,12 @@ #dimensions 0: 320x240 #sar 0: 1/1 0, 0, 0, 1, 115200, 0x3744b3ed -0, 1, 1, 1, 115200, 0xc44bdc65 +0, 1, 1, 1, 115200, 0xec1fdfa0 0, 2, 2, 1, 115200, 0xa17f0d74 0, 3, 3, 1, 115200, 0xd72532a9 -0, 4, 4, 1, 115200, 0x232d6368 +0, 4, 4, 1, 115200, 0x032e60f8 0, 5, 5, 1, 115200, 0x6e318ba0 -0, 6, 6, 1, 115200, 0x247e846e +0, 6, 6, 1, 115200, 0x76018292 0, 7, 7, 1, 115200, 0x89e27599 0, 8, 8, 1, 115200, 0x68536eac -0, 9, 9, 1, 115200, 0x97e45fec +0, 9, 9, 1, 115200, 0xc3ac62a8 From 4d95c6d5d7d8d79b5acafcf526a1b7c1797a1060 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 8 Jan 2018 01:05:45 +0100 Subject: [PATCH 1749/2557] avfilter/vf_framerate: add SIMD functions for frame blending Blend function speedups on x86_64 Core i5 4460: ffmpeg -f lavfi -i allyuv -vf framerate=60:threads=1 -f null none C: 447548411 decicycles in Blend, 2048 runs, 0 skips SSSE3: 130020087 decicycles in Blend, 2048 runs, 0 skips AVX2: 128508221 decicycles in Blend, 2048 runs, 0 skips ffmpeg -f lavfi -i allyuv -vf format=yuv420p12,framerate=60:threads=1 -f null none C: 228932745 decicycles in Blend, 2048 runs, 0 skips SSE4: 123357781 decicycles in Blend, 2048 runs, 0 skips AVX2: 121215353 decicycles in Blend, 2048 runs, 0 skips Signed-off-by: Marton Balint --- libavfilter/framerate.h | 74 +++++++++++++++ libavfilter/vf_framerate.c | 70 ++++----------- libavfilter/x86/Makefile | 2 + libavfilter/x86/vf_framerate.asm | 134 ++++++++++++++++++++++++++++ libavfilter/x86/vf_framerate_init.c | 42 +++++++++ 5 files changed, 268 insertions(+), 54 deletions(-) create mode 100644 libavfilter/framerate.h create mode 100644 libavfilter/x86/vf_framerate.asm create mode 100644 libavfilter/x86/vf_framerate_init.c diff --git a/libavfilter/framerate.h b/libavfilter/framerate.h new file mode 100644 index 0000000000000..a42d5af68a293 --- /dev/null +++ b/libavfilter/framerate.h @@ -0,0 +1,74 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_FRAMERATE_H +#define AVFILTER_FRAMERATE_H + +#include "libavutil/pixelutils.h" +#include "avfilter.h" + +#define BLEND_FUNC_PARAMS const uint8_t *src1, ptrdiff_t src1_linesize, \ + const uint8_t *src2, ptrdiff_t src2_linesize, \ + uint8_t *dst, ptrdiff_t dst_linesize, \ + ptrdiff_t width, ptrdiff_t height, \ + int factor1, int factor2, int half + +#define BLEND_FACTOR_DEPTH8 7 +#define BLEND_FACTOR_DEPTH16 15 + +typedef void (*blend_func)(BLEND_FUNC_PARAMS); + +typedef struct FrameRateContext { + const AVClass *class; + // parameters + AVRational dest_frame_rate; ///< output frames per second + int flags; ///< flags affecting frame rate conversion algorithm + double scene_score; ///< score that denotes a scene change has happened + int interp_start; ///< start of range to apply linear interpolation + int interp_end; ///< end of range to apply linear interpolation + + int line_size[4]; ///< bytes of pixel data per line for each plane + int vsub; + + AVRational srce_time_base; ///< timebase of source + AVRational dest_time_base; ///< timebase of destination + + av_pixelutils_sad_fn sad; ///< Sum of the absolute difference function (scene detect only) + double prev_mafd; ///< previous MAFD (scene detect only) + + int blend_factor_max; + int bitdepth; + AVFrame *work; + + AVFrame *f0; ///< last frame + AVFrame *f1; ///< current frame + int64_t pts0; ///< last frame pts in dest_time_base + int64_t pts1; ///< current frame pts in dest_time_base + int64_t delta; ///< pts1 to pts0 delta + double score; ///< scene change score (f0 to f1) + int flush; ///< 1 if the filter is being flushed + int64_t start_pts; ///< pts of the first output frame + int64_t n; ///< output frame counter + + blend_func blend; +} FrameRateContext; + +void ff_framerate_init(FrameRateContext *s); +void ff_framerate_init_x86(FrameRateContext *s); + +#endif /* AVFILTER_FRAMERATE_H */ diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index 8119fe2bfd237..3e2615be5e695 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -38,52 +38,7 @@ #include "avfilter.h" #include "internal.h" #include "video.h" - -#define BLEND_FUNC_PARAMS const uint8_t *src1, ptrdiff_t src1_linesize, \ - const uint8_t *src2, ptrdiff_t src2_linesize, \ - uint8_t *dst, ptrdiff_t dst_linesize, \ - ptrdiff_t width, ptrdiff_t height, \ - int factor1, int factor2, int half - -#define BLEND_FACTOR_DEPTH8 7 -#define BLEND_FACTOR_DEPTH16 15 - -typedef void (*blend_func)(BLEND_FUNC_PARAMS); - -typedef struct FrameRateContext { - const AVClass *class; - // parameters - AVRational dest_frame_rate; ///< output frames per second - int flags; ///< flags affecting frame rate conversion algorithm - double scene_score; ///< score that denotes a scene change has happened - int interp_start; ///< start of range to apply linear interpolation - int interp_end; ///< end of range to apply linear interpolation - - int line_size[4]; ///< bytes of pixel data per line for each plane - int vsub; - - AVRational srce_time_base; ///< timebase of source - AVRational dest_time_base; ///< timebase of destination - - av_pixelutils_sad_fn sad; ///< Sum of the absolute difference function (scene detect only) - double prev_mafd; ///< previous MAFD (scene detect only) - - int blend_factor_max; - int bitdepth; - AVFrame *work; - - AVFrame *f0; ///< last frame - AVFrame *f1; ///< current frame - int64_t pts0; ///< last frame pts in dest_time_base - int64_t pts1; ///< current frame pts in dest_time_base - int64_t delta; ///< pts1 to pts0 delta - double score; ///< scene change score (f0 to f1) - int flush; ///< 1 if the filter is being flushed - int64_t start_pts; ///< pts of the first output frame - int64_t n; ///< output frame counter - - blend_func blend; -} FrameRateContext; +#include "framerate.h" #define OFFSET(x) offsetof(FrameRateContext, x) #define V AV_OPT_FLAG_VIDEO_PARAM @@ -246,7 +201,7 @@ static int blend_frames(AVFilterContext *ctx, int interpolate) av_frame_copy_props(s->work, s->f0); ff_dlog(ctx, "blend_frames() INTERPOLATE to create work frame\n"); - ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); + ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(FFMAX(1, outlink->h >> 2), ff_filter_get_nb_threads(ctx))); return 1; } return 0; @@ -366,6 +321,19 @@ static void blend_frames16_c(BLEND_FUNC_PARAMS) } } +void ff_framerate_init(FrameRateContext *s) +{ + if (s->bitdepth == 8) { + s->blend_factor_max = 1 << BLEND_FACTOR_DEPTH8; + s->blend = blend_frames_c; + } else { + s->blend_factor_max = 1 << BLEND_FACTOR_DEPTH16; + s->blend = blend_frames16_c; + } + if (ARCH_X86) + ff_framerate_init_x86(s); +} + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -387,13 +355,7 @@ static int config_input(AVFilterLink *inlink) s->srce_time_base = inlink->time_base; - if (s->bitdepth == 8) { - s->blend_factor_max = 1 << BLEND_FACTOR_DEPTH8; - s->blend = blend_frames_c; - } else { - s->blend_factor_max = 1 << BLEND_FACTOR_DEPTH16; - s->blend = blend_frames16_c; - } + ff_framerate_init(s); return 0; } diff --git a/libavfilter/x86/Makefile b/libavfilter/x86/Makefile index 2fc5c62644dd6..4d4c5e503a98b 100644 --- a/libavfilter/x86/Makefile +++ b/libavfilter/x86/Makefile @@ -5,6 +5,7 @@ OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp_init.o OBJS-$(CONFIG_EQ_FILTER) += x86/vf_eq.o OBJS-$(CONFIG_FSPP_FILTER) += x86/vf_fspp_init.o OBJS-$(CONFIG_GRADFUN_FILTER) += x86/vf_gradfun_init.o +OBJS-$(CONFIG_FRAMERATE_FILTER) += x86/vf_framerate_init.o OBJS-$(CONFIG_HFLIP_FILTER) += x86/vf_hflip_init.o OBJS-$(CONFIG_HQDN3D_FILTER) += x86/vf_hqdn3d_init.o OBJS-$(CONFIG_IDET_FILTER) += x86/vf_idet_init.o @@ -31,6 +32,7 @@ X86ASM-OBJS-$(CONFIG_AFIR_FILTER) += x86/af_afir.o X86ASM-OBJS-$(CONFIG_BLEND_FILTER) += x86/vf_blend.o X86ASM-OBJS-$(CONFIG_BWDIF_FILTER) += x86/vf_bwdif.o X86ASM-OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp.o +X86ASM-OBJS-$(CONFIG_FRAMERATE_FILTER) += x86/vf_framerate.o X86ASM-OBJS-$(CONFIG_FSPP_FILTER) += x86/vf_fspp.o X86ASM-OBJS-$(CONFIG_GRADFUN_FILTER) += x86/vf_gradfun.o X86ASM-OBJS-$(CONFIG_HFLIP_FILTER) += x86/vf_hflip.o diff --git a/libavfilter/x86/vf_framerate.asm b/libavfilter/x86/vf_framerate.asm new file mode 100644 index 0000000000000..7a30c870bd5ae --- /dev/null +++ b/libavfilter/x86/vf_framerate.asm @@ -0,0 +1,134 @@ +;***************************************************************************** +;* x86-optimized functions for framerate filter +;* +;* Copyright (C) 2018 Marton Balint +;* +;* Based on vf_blend.asm, Copyright (C) 2015 Paul B Mahol +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION .text + + +%macro XSPLAT 3 +%if cpuflag(avx2) + vpbroadcast%3 %1, %2 +%else + movd %1, %2 +%ifidn %3, d + SPLATD %1 +%else + SPLATW %1, %1 +%endif +%endif +%endmacro + + +%macro BLEND_INIT 0-1 +%if ARCH_X86_64 +cglobal blend_frames%1, 6, 9, 5, src1, src1_linesize, src2, src2_linesize, dst, dst_linesize, width, end, x + mov widthd, dword widthm +%else +cglobal blend_frames%1, 5, 7, 5, src1, src1_linesize, src2, src2_linesize, dst, end, x +%define dst_linesizeq r5mp +%define widthq r6mp +%endif + mov endd, dword r7m + add src1q, widthq + add src2q, widthq + add dstq, widthq + neg widthq +%endmacro + + +%macro BLEND_LOOP 4 +.nextrow: + mov xq, widthq + + .loop: + movu m0, [src1q + xq] + movu m1, [src2q + xq] + SBUTTERFLY %1%2, 0, 1, 4 ; aAbBcCdD + ; eEfFgGhH + pmadd%3 m0, m2 + pmadd%3 m1, m2 + + padd%2 m0, m3 + padd%2 m1, m3 + psrl%2 m0, %4 ; 0A0B0C0D + psrl%2 m1, %4 ; 0E0F0G0H + + packus%2%1 m0, m1 ; ABCDEFGH + movu [dstq + xq], m0 + add xq, mmsize + jl .loop + add src1q, src1_linesizeq + add src2q, src2_linesizeq + add dstq, dst_linesizeq + sub endd, 1 + jg .nextrow +REP_RET +%endmacro + + +%macro BLEND_FRAMES 0 + BLEND_INIT + + XSPLAT m2, r8m, w ; factor1 + XSPLAT m3, r9m, w ; factor2 + + psllw m3, 8 + por m2, m3 ; interleaved factors + + XSPLAT m3, r10m, w ; half + + BLEND_LOOP b, w, ubsw, 7 +%endmacro + + +%macro BLEND_FRAMES16 0 + BLEND_INIT 16 + + XSPLAT m2, r8m, d ; factor1 + XSPLAT m3, r9m, d ; factor2 + + pslld m3, 16 + por m2, m3 ; interleaved factors + + XSPLAT m3, r10m, d ; half + + BLEND_LOOP w, d, wd, 15 +%endmacro + + +INIT_XMM ssse3 +BLEND_FRAMES + +INIT_XMM sse4 +BLEND_FRAMES16 + + +%if HAVE_AVX2_EXTERNAL + +INIT_YMM avx2 +BLEND_FRAMES +BLEND_FRAMES16 + +%endif diff --git a/libavfilter/x86/vf_framerate_init.c b/libavfilter/x86/vf_framerate_init.c new file mode 100644 index 0000000000000..9d40faf0a4f25 --- /dev/null +++ b/libavfilter/x86/vf_framerate_init.c @@ -0,0 +1,42 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavfilter/framerate.h" + +void ff_blend_frames_ssse3(BLEND_FUNC_PARAMS); +void ff_blend_frames_avx2(BLEND_FUNC_PARAMS); +void ff_blend_frames16_sse4(BLEND_FUNC_PARAMS); +void ff_blend_frames16_avx2(BLEND_FUNC_PARAMS); + +void ff_framerate_init_x86(FrameRateContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + if (s->bitdepth == 8) { + if (EXTERNAL_AVX2_FAST(cpu_flags)) + s->blend = ff_blend_frames_avx2; + else if (EXTERNAL_SSSE3(cpu_flags)) + s->blend = ff_blend_frames_ssse3; + } else { + if (EXTERNAL_AVX2_FAST(cpu_flags)) + s->blend = ff_blend_frames16_avx2; + else if (EXTERNAL_SSE4(cpu_flags)) + s->blend = ff_blend_frames16_sse4; + } +} From 3a230ce5fa10b21312236b362df9eeddd99e7ac2 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Wed, 17 Jan 2018 20:59:58 +0100 Subject: [PATCH 1750/2557] avfilter/x86/vf_blend : avfilter/x86/vf_blend : add AVX2 version for each func except divide and optimize average, grainextract, multiply, screen, grain merge --- libavfilter/x86/vf_blend.asm | 229 ++++++++++++++++++++------------ libavfilter/x86/vf_blend_init.c | 39 ++++++ 2 files changed, 184 insertions(+), 84 deletions(-) diff --git a/libavfilter/x86/vf_blend.asm b/libavfilter/x86/vf_blend.asm index 4916aaf251e01..680e266348a90 100644 --- a/libavfilter/x86/vf_blend.asm +++ b/libavfilter/x86/vf_blend.asm @@ -2,6 +2,8 @@ ;* x86-optimized functions for blend filter ;* ;* Copyright (C) 2015 Paul B Mahol +;* Copyright (C) 2018 Henrik Gramner +;* Copyright (C) 2018 Jokyo Images ;* ;* This file is part of FFmpeg. ;* @@ -74,39 +76,36 @@ BLEND_INIT %1, 2 BLEND_END %endmacro -INIT_XMM sse2 -BLEND_SIMPLE xor, xor -BLEND_SIMPLE or, or -BLEND_SIMPLE and, and -BLEND_SIMPLE addition, addusb -BLEND_SIMPLE subtract, subusb -BLEND_SIMPLE darken, minub -BLEND_SIMPLE lighten, maxub - -BLEND_INIT grainextract, 4 - pxor m2, m2 - mova m3, [pw_128] +%macro GRAINEXTRACT 0 +BLEND_INIT grainextract, 6 + pxor m4, m4 + VBROADCASTI128 m5, [pw_128] .nextrow: mov xq, widthq - .loop: - movh m0, [topq + xq] - movh m1, [bottomq + xq] - punpcklbw m0, m2 - punpcklbw m1, m2 - paddw m0, m3 - psubw m0, m1 - packuswb m0, m0 - movh [dstq + xq], m0 - add xq, mmsize / 2 + movu m1, [topq + xq] + movu m3, [bottomq + xq] + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + + paddw m0, m5 + paddw m1, m5 + psubw m0, m2 + psubw m1, m3 + + packuswb m0, m1 + mova [dstq + xq], m0 + add xq, mmsize jl .loop BLEND_END +%endmacro %macro MULTIPLY 3 ; a, b, pw_1 pmullw %1, %2 ; xxxxxxxx a * b paddw %1, %3 - mova %2, %1 - psrlw %2, 8 + psrlw %2, %1, 8 paddw %1, %2 psrlw %1, 8 ; 00xx00xx a * b / 255 %endmacro @@ -118,92 +117,112 @@ BLEND_END pxor %1, %4 ; 00xx00xx 255 - x / 255 %endmacro -BLEND_INIT multiply, 4 - pxor m2, m2 - mova m3, [pw_1] +%macro BLEND_MULTIPLY 0 +BLEND_INIT multiply, 6 + pxor m4, m4 + VBROADCASTI128 m5, [pw_1] .nextrow: mov xq, widthq .loop: - ; word - ; |--| - movh m0, [topq + xq] ; 0000xxxx - movh m1, [bottomq + xq] - punpcklbw m0, m2 ; 00xx00xx - punpcklbw m1, m2 - - MULTIPLY m0, m1, m3 - - packuswb m0, m0 ; 0000xxxx - movh [dstq + xq], m0 - add xq, mmsize / 2 - + movu m1, [topq + xq] + movu m3, [bottomq + xq] + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + + MULTIPLY m0, m2, m5 + MULTIPLY m1, m3, m5 + + packuswb m0, m1 + mova [dstq + xq], m0 + add xq, mmsize jl .loop BLEND_END +%endmacro -BLEND_INIT screen, 5 - pxor m2, m2 - mova m3, [pw_1] - mova m4, [pw_255] +%macro BLEND_SCREEN 0 +BLEND_INIT screen, 7 + pxor m4, m4 + + VBROADCASTI128 m5, [pw_1] + VBROADCASTI128 m6, [pw_255] .nextrow: mov xq, widthq .loop: - movh m0, [topq + xq] ; 0000xxxx - movh m1, [bottomq + xq] - punpcklbw m0, m2 ; 00xx00xx - punpcklbw m1, m2 - - SCREEN m0, m1, m3, m4 - - packuswb m0, m0 ; 0000xxxx - movh [dstq + xq], m0 - add xq, mmsize / 2 - + movu m1, [topq + xq] + movu m3, [bottomq + xq] + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + + SCREEN m0, m2, m5, m6 + SCREEN m1, m3, m5, m6 + + packuswb m0, m1 + mova [dstq + xq], m0 + add xq, mmsize jl .loop BLEND_END +%endmacro +%macro AVERAGE 0 BLEND_INIT average, 3 - pxor m2, m2 + pcmpeqb m2, m2 + .nextrow: mov xq, widthq - .loop: - movh m0, [topq + xq] - movh m1, [bottomq + xq] - punpcklbw m0, m2 - punpcklbw m1, m2 - paddw m0, m1 - psrlw m0, 1 - packuswb m0, m0 - movh [dstq + xq], m0 - add xq, mmsize / 2 +.loop: + movu m0, [topq + xq] + movu m1, [bottomq + xq] + pxor m0, m2 + pxor m1, m2 + pavgb m0, m1 + pxor m0, m2 + mova [dstq + xq], m0 + add xq, mmsize jl .loop BLEND_END +%endmacro -BLEND_INIT grainmerge, 4 - pxor m2, m2 - mova m3, [pw_128] + +%macro GRAINMERGE 0 +BLEND_INIT grainmerge, 6 + pxor m4, m4 + + VBROADCASTI128 m5, [pw_128] .nextrow: mov xq, widthq .loop: - movh m0, [topq + xq] - movh m1, [bottomq + xq] - punpcklbw m0, m2 - punpcklbw m1, m2 - paddw m0, m1 - psubw m0, m3 - packuswb m0, m0 - movh [dstq + xq], m0 - add xq, mmsize / 2 + movu m1, [topq + xq] + movu m3, [bottomq + xq] + punpcklbw m0, m1, m4 + punpckhbw m1, m4 + punpcklbw m2, m3, m4 + punpckhbw m3, m4 + + paddw m0, m2 + paddw m1, m3 + psubw m0, m5 + psubw m1, m5 + + packuswb m0, m1 + mova [dstq + xq], m0 + add xq, mmsize jl .loop BLEND_END +%endmacro +%macro HARDMIX 0 BLEND_INIT hardmix, 5 - mova m2, [pb_255] - mova m3, [pb_128] - mova m4, [pb_127] + VBROADCASTI128 m2, [pb_255] + VBROADCASTI128 m3, [pb_128] + VBROADCASTI128 m4, [pb_127] .nextrow: mov xq, widthq @@ -218,7 +237,9 @@ BLEND_INIT hardmix, 5 add xq, mmsize jl .loop BLEND_END +%endmacro +%macro DIVIDE 0 BLEND_INIT divide, 4 pxor m2, m2 mova m3, [ps_255] @@ -247,9 +268,11 @@ BLEND_INIT divide, 4 jl .loop BLEND_END +%endmacro +%macro PHOENIX 0 BLEND_INIT phoenix, 4 - mova m3, [pb_255] + VBROADCASTI128 m3, [pb_255] .nextrow: mov xq, widthq @@ -266,6 +289,7 @@ BLEND_INIT phoenix, 4 add xq, mmsize jl .loop BLEND_END +%endmacro %macro BLEND_ABS 0 BLEND_INIT difference, 5 @@ -291,7 +315,7 @@ BLEND_END BLEND_INIT extremity, 8 pxor m2, m2 - mova m4, [pw_255] + VBROADCASTI128 m4, [pw_255] .nextrow: mov xq, widthq @@ -315,7 +339,7 @@ BLEND_END BLEND_INIT negation, 8 pxor m2, m2 - mova m4, [pw_255] + VBROADCASTI128 m4, [pw_255] .nextrow: mov xq, widthq @@ -341,6 +365,43 @@ BLEND_END %endmacro INIT_XMM sse2 +BLEND_SIMPLE xor, xor +BLEND_SIMPLE or, or +BLEND_SIMPLE and, and +BLEND_SIMPLE addition, addusb +BLEND_SIMPLE subtract, subusb +BLEND_SIMPLE darken, minub +BLEND_SIMPLE lighten, maxub +GRAINEXTRACT +BLEND_MULTIPLY +BLEND_SCREEN +AVERAGE +GRAINMERGE +HARDMIX +PHOENIX +DIVIDE + BLEND_ABS + INIT_XMM ssse3 BLEND_ABS + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +BLEND_SIMPLE xor, xor +BLEND_SIMPLE or, or +BLEND_SIMPLE and, and +BLEND_SIMPLE addition, addusb +BLEND_SIMPLE subtract, subusb +BLEND_SIMPLE darken, minub +BLEND_SIMPLE lighten, maxub +GRAINEXTRACT +BLEND_MULTIPLY +BLEND_SCREEN +AVERAGE +GRAINMERGE +HARDMIX +PHOENIX + +BLEND_ABS +%endif diff --git a/libavfilter/x86/vf_blend_init.c b/libavfilter/x86/vf_blend_init.c index a4fc9af2469de..6e782e4edbcfe 100644 --- a/libavfilter/x86/vf_blend_init.c +++ b/libavfilter/x86/vf_blend_init.c @@ -31,26 +31,43 @@ void ff_blend_##name##_##opt(const uint8_t *top, ptrdiff_t top_linesize, \ struct FilterParams *param, double *values, int starty); BLEND_FUNC(addition, sse2) +BLEND_FUNC(addition, avx2) BLEND_FUNC(grainmerge, sse2) +BLEND_FUNC(grainmerge, avx2) BLEND_FUNC(average, sse2) +BLEND_FUNC(average, avx2) BLEND_FUNC(and, sse2) +BLEND_FUNC(and, avx2) BLEND_FUNC(darken, sse2) +BLEND_FUNC(darken, avx2) BLEND_FUNC(grainextract, sse2) +BLEND_FUNC(grainextract, avx2) BLEND_FUNC(multiply, sse2) +BLEND_FUNC(multiply, avx2) BLEND_FUNC(screen, sse2) +BLEND_FUNC(screen, avx2) BLEND_FUNC(hardmix, sse2) +BLEND_FUNC(hardmix, avx2) BLEND_FUNC(divide, sse2) BLEND_FUNC(lighten, sse2) +BLEND_FUNC(lighten, avx2) BLEND_FUNC(or, sse2) +BLEND_FUNC(or, avx2) BLEND_FUNC(phoenix, sse2) +BLEND_FUNC(phoenix, avx2) BLEND_FUNC(subtract, sse2) +BLEND_FUNC(subtract, avx2) BLEND_FUNC(xor, sse2) +BLEND_FUNC(xor, avx2) BLEND_FUNC(difference, sse2) BLEND_FUNC(difference, ssse3) +BLEND_FUNC(difference, avx2) BLEND_FUNC(extremity, sse2) BLEND_FUNC(extremity, ssse3) +BLEND_FUNC(extremity, avx2) BLEND_FUNC(negation, sse2) BLEND_FUNC(negation, ssse3) +BLEND_FUNC(negation, avx2) av_cold void ff_blend_init_x86(FilterParams *param, int is_16bit) { @@ -85,4 +102,26 @@ av_cold void ff_blend_init_x86(FilterParams *param, int is_16bit) case BLEND_NEGATION: param->blend = ff_blend_negation_ssse3; break; } } + + if (EXTERNAL_AVX2_FAST(cpu_flags) && param->opacity == 1 && !is_16bit) { + switch (param->mode) { + case BLEND_ADDITION: param->blend = ff_blend_addition_avx2; break; + case BLEND_GRAINMERGE: param->blend = ff_blend_grainmerge_avx2; break; + case BLEND_AND: param->blend = ff_blend_and_avx2; break; + case BLEND_AVERAGE: param->blend = ff_blend_average_avx2; break; + case BLEND_DARKEN: param->blend = ff_blend_darken_avx2; break; + case BLEND_GRAINEXTRACT: param->blend = ff_blend_grainextract_avx2; break; + case BLEND_HARDMIX: param->blend = ff_blend_hardmix_avx2; break; + case BLEND_LIGHTEN: param->blend = ff_blend_lighten_avx2; break; + case BLEND_MULTIPLY: param->blend = ff_blend_multiply_avx2; break; + case BLEND_OR: param->blend = ff_blend_or_avx2; break; + case BLEND_PHOENIX: param->blend = ff_blend_phoenix_avx2; break; + case BLEND_SCREEN: param->blend = ff_blend_screen_avx2; break; + case BLEND_SUBTRACT: param->blend = ff_blend_subtract_avx2; break; + case BLEND_XOR: param->blend = ff_blend_xor_avx2; break; + case BLEND_DIFFERENCE: param->blend = ff_blend_difference_avx2; break; + case BLEND_EXTREMITY: param->blend = ff_blend_extremity_avx2; break; + case BLEND_NEGATION: param->blend = ff_blend_negation_avx2; break; + } + } } From 8f9c38b19629838066def1207703cfcdc19fcbc9 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 14 Jan 2018 14:23:05 +0100 Subject: [PATCH 1751/2557] avcodec/utvideoenc : add SIMD (avx) for sub_left_prediction asm code by Henrik Gramner --- libavcodec/lossless_videoencdsp.c | 15 ++++++++ libavcodec/lossless_videoencdsp.h | 5 +++ libavcodec/utvideoenc.c | 20 +--------- libavcodec/x86/lossless_videoencdsp.asm | 43 ++++++++++++++++++++++ libavcodec/x86/lossless_videoencdsp_init.c | 7 ++++ 5 files changed, 71 insertions(+), 19 deletions(-) diff --git a/libavcodec/lossless_videoencdsp.c b/libavcodec/lossless_videoencdsp.c index 5cc4934c0ef6a..ed70329628aec 100644 --- a/libavcodec/lossless_videoencdsp.c +++ b/libavcodec/lossless_videoencdsp.c @@ -74,10 +74,25 @@ static void sub_median_pred_c(uint8_t *dst, const uint8_t *src1, *left_top = lt; } +static void sub_left_predict_c(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, ptrdiff_t width, int height) +{ + int i, j; + uint8_t prev = 0x80; /* Set the initial value */ + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + *dst++ = src[i] - prev; + prev = src[i]; + } + src += stride; + } +} + av_cold void ff_llvidencdsp_init(LLVidEncDSPContext *c) { c->diff_bytes = diff_bytes_c; c->sub_median_pred = sub_median_pred_c; + c->sub_left_predict = sub_left_predict_c; if (ARCH_X86) ff_llvidencdsp_init_x86(c); diff --git a/libavcodec/lossless_videoencdsp.h b/libavcodec/lossless_videoencdsp.h index 3d645b159adfc..faa6c325512c0 100644 --- a/libavcodec/lossless_videoencdsp.h +++ b/libavcodec/lossless_videoencdsp.h @@ -21,6 +21,8 @@ #include +#include "avcodec.h" + typedef struct LLVidEncDSPContext { void (*diff_bytes)(uint8_t *dst /* align 16 */, const uint8_t *src1 /* align 16 */, @@ -33,6 +35,9 @@ typedef struct LLVidEncDSPContext { void (*sub_median_pred)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, intptr_t w, int *left, int *left_top); + + void (*sub_left_predict)(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, ptrdiff_t width, int height); } LLVidEncDSPContext; void ff_llvidencdsp_init(LLVidEncDSPContext *c); diff --git a/libavcodec/utvideoenc.c b/libavcodec/utvideoenc.c index a829b7aaac59e..db00e1eff5f29 100644 --- a/libavcodec/utvideoenc.c +++ b/libavcodec/utvideoenc.c @@ -283,23 +283,6 @@ static void mangle_rgb_planes(uint8_t *dst[4], ptrdiff_t dst_stride, } } -/* Write data to a plane with left prediction */ -static void left_predict(uint8_t *src, uint8_t *dst, ptrdiff_t stride, - int width, int height) -{ - int i, j; - uint8_t prev; - - prev = 0x80; /* Set the initial value */ - for (j = 0; j < height; j++) { - for (i = 0; i < width; i++) { - *dst++ = src[i] - prev; - prev = src[i]; - } - src += stride; - } -} - #undef A #undef B @@ -436,8 +419,7 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src, for (i = 0; i < c->slices; i++) { sstart = send; send = height * (i + 1) / c->slices & cmask; - left_predict(src + sstart * stride, dst + sstart * width, - stride, width, send - sstart); + c->llvidencdsp.sub_left_predict(dst + sstart * width, src + sstart * stride, stride, width, send - sstart); } break; case PRED_MEDIAN: diff --git a/libavcodec/x86/lossless_videoencdsp.asm b/libavcodec/x86/lossless_videoencdsp.asm index 4d79eee36ba1a..fb1204f0f1f61 100644 --- a/libavcodec/x86/lossless_videoencdsp.asm +++ b/libavcodec/x86/lossless_videoencdsp.asm @@ -25,6 +25,8 @@ %include "libavutil/x86/x86util.asm" +cextern pb_80 + SECTION .text ; void ff_diff_bytes(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, @@ -149,3 +151,44 @@ DIFF_BYTES_PROLOGUE DIFF_BYTES_BODY u, u %undef i %endif + + +;-------------------------------------------------------------------------------------------------- +;void sub_left_predict(uint8_t *dst, uint8_t *src, ptrdiff_t stride, ptrdiff_t width, int height) +;-------------------------------------------------------------------------------------------------- + +INIT_XMM avx +cglobal sub_left_predict, 5,6,5, dst, src, stride, width, height, x + mova m1, [pb_80] ; prev initial + add dstq, widthq + add srcq, widthq + lea xd, [widthq-1] + neg widthq + and xd, 15 + pinsrb m4, m1, xd, 15 + mov xq, widthq + + .loop: + movu m0, [srcq + widthq] + palignr m2, m0, m1, 15 + movu m1, [srcq + widthq + 16] + palignr m3, m1, m0, 15 + psubb m2, m0, m2 + psubb m3, m1, m3 + movu [dstq + widthq], m2 + movu [dstq + widthq + 16], m3 + add widthq, 2 * 16 + jl .loop + + add srcq, strideq + sub dstq, xq ; dst + width + test xd, 16 + jz .mod32 + mova m1, m0 + +.mod32: + pshufb m1, m4 + mov widthq, xq + dec heightd + jg .loop + RET diff --git a/libavcodec/x86/lossless_videoencdsp_init.c b/libavcodec/x86/lossless_videoencdsp_init.c index fc728c9fd1ef7..40407add52526 100644 --- a/libavcodec/x86/lossless_videoencdsp_init.c +++ b/libavcodec/x86/lossless_videoencdsp_init.c @@ -36,6 +36,9 @@ void ff_diff_bytes_sse2(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, void ff_diff_bytes_avx2(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, intptr_t w); +void ff_sub_left_predict_avx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, ptrdiff_t width, int height); + #if HAVE_INLINE_ASM static void sub_median_pred_mmxext(uint8_t *dst, const uint8_t *src1, @@ -98,6 +101,10 @@ av_cold void ff_llvidencdsp_init_x86(LLVidEncDSPContext *c) c->diff_bytes = ff_diff_bytes_sse2; } + if (EXTERNAL_AVX(cpu_flags)) { + c->sub_left_predict = ff_sub_left_predict_avx; + } + if (EXTERNAL_AVX2_FAST(cpu_flags)) { c->diff_bytes = ff_diff_bytes_avx2; } From 78b982d3b9f11877a5e4408146cc3cb82908862c Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 14 Jan 2018 14:23:42 +0100 Subject: [PATCH 1752/2557] checkasm : add test for losslessvideoencdsp for diff bytes and sub_left_pred --- tests/checkasm/Makefile | 1 + tests/checkasm/checkasm.c | 3 + tests/checkasm/checkasm.h | 1 + tests/checkasm/llviddspenc.c | 114 +++++++++++++++++++++++++++++++++++ tests/fate/checkasm.mak | 1 + 5 files changed, 120 insertions(+) create mode 100644 tests/checkasm/llviddspenc.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 35250945451fc..afbd09b940aac 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -10,6 +10,7 @@ AVCODECOBJS-$(CONFIG_H264DSP) += h264dsp.o AVCODECOBJS-$(CONFIG_H264PRED) += h264pred.o AVCODECOBJS-$(CONFIG_H264QPEL) += h264qpel.o AVCODECOBJS-$(CONFIG_LLVIDDSP) += llviddsp.o +AVCODECOBJS-$(CONFIG_LLVIDENCDSP) += llviddspenc.o AVCODECOBJS-$(CONFIG_VP8DSP) += vp8dsp.o AVCODECOBJS-$(CONFIG_VIDEODSP) += videodsp.o diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index ff0ca5b68d374..a4b8aff9848a1 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -126,6 +126,9 @@ static const struct { #if CONFIG_HUFFYUVDSP { "llviddsp", checkasm_check_llviddsp }, #endif + #if CONFIG_LLVIDENCDSP + { "llviddspenc", checkasm_check_llviddspenc }, + #endif #if CONFIG_PIXBLOCKDSP { "pixblockdsp", checkasm_check_pixblockdsp }, #endif diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index cfe9bfb35500f..3de38e67172cc 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -60,6 +60,7 @@ void checkasm_check_hevc_idct(void); void checkasm_check_huffyuvdsp(void); void checkasm_check_jpeg2000dsp(void); void checkasm_check_llviddsp(void); +void checkasm_check_llviddspenc(void); void checkasm_check_pixblockdsp(void); void checkasm_check_sbrdsp(void); void checkasm_check_synth_filter(void); diff --git a/tests/checkasm/llviddspenc.c b/tests/checkasm/llviddspenc.c new file mode 100644 index 0000000000000..31eafd5526d1a --- /dev/null +++ b/tests/checkasm/llviddspenc.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016 Alexandra Hájková + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" + +#include "libavcodec/lossless_videoencdsp.h" + +#include "checkasm.h" + +#define randomize_buffers(buf, size) \ + do { \ + int j; \ + for (j = 0; j < size; j+=4) \ + AV_WN32(buf + j, rnd()); \ + } while (0) + +static const struct {uint8_t w, h, s;} planes[] = { + {16,16,16}, {21,23,25}, {32,17,48}, {15,128,16}, {128,127,128} +}; + +#define MAX_STRIDE 128 +#define MAX_HEIGHT 127 + +static void check_diff_bytes(LLVidEncDSPContext *c) +{ + int i; + LOCAL_ALIGNED_32(uint8_t, dst0, [MAX_STRIDE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [MAX_STRIDE]); + LOCAL_ALIGNED_32(uint8_t, src0, [MAX_STRIDE]); + LOCAL_ALIGNED_32(uint8_t, src1, [MAX_STRIDE]); + LOCAL_ALIGNED_32(uint8_t, src2, [MAX_STRIDE]); + LOCAL_ALIGNED_32(uint8_t, src3, [MAX_STRIDE]); + + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, const uint8_t *src1, + const uint8_t *src2, intptr_t w); + + memset(dst0, 0, MAX_STRIDE); + memset(dst1, 0, MAX_STRIDE); + randomize_buffers(src0, MAX_STRIDE); + memcpy(src1, src0, MAX_STRIDE); + randomize_buffers(src2, MAX_STRIDE); + memcpy(src3, src2, MAX_STRIDE); + + if (check_func(c->diff_bytes, "diff_bytes")) { + for (i = 0; i < 5; i ++) { + call_ref(dst0, src0, src2, planes[i].w); + call_new(dst1, src1, src3, planes[i].w); + if (memcmp(dst0, dst1, planes[i].w)) + fail(); + } + bench_new(dst1, src0, src2, planes[4].w); + } +} + +static void check_sub_left_pred(LLVidEncDSPContext *c) +{ + int i; + LOCAL_ALIGNED_32(uint8_t, dst0, [MAX_STRIDE * MAX_HEIGHT]); + LOCAL_ALIGNED_32(uint8_t, dst1, [MAX_STRIDE * MAX_HEIGHT]); + LOCAL_ALIGNED_32(uint8_t, src0, [MAX_STRIDE * MAX_HEIGHT]); + LOCAL_ALIGNED_32(uint8_t, src1, [MAX_STRIDE * MAX_HEIGHT]); + + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, ptrdiff_t width, int height); + + memset(dst0, 0, MAX_STRIDE * MAX_HEIGHT); + memset(dst1, 0, MAX_STRIDE * MAX_HEIGHT); + randomize_buffers(src0, MAX_STRIDE * MAX_HEIGHT); + memcpy(src1, src0, MAX_STRIDE * MAX_HEIGHT); + + if (check_func(c->sub_left_predict, "sub_left_predict")) { + for (i = 0; i < 5; i ++) { + call_ref(dst0, src0, planes[i].s, planes[i].w, planes[i].h); + call_new(dst1, src1, planes[i].s, planes[i].w, planes[i].h); + if (memcmp(dst0, dst1, planes[i].w * planes[i].h)) + fail(); + break; + } + bench_new(dst1, src0, planes[4].s, planes[4].w, planes[4].h); + } +} + +void checkasm_check_llviddspenc(void) +{ + LLVidEncDSPContext c; + ff_llvidencdsp_init(&c); + + check_diff_bytes(&c); + report("diff_bytes"); + + check_sub_left_pred(&c); + report("sub_left_predict"); +} diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index 9216c71cb8ede..826ac16789689 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -16,6 +16,7 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp \ fate-checkasm-hevc_idct \ fate-checkasm-jpeg2000dsp \ fate-checkasm-llviddsp \ + fate-checkasm-llviddspenc \ fate-checkasm-pixblockdsp \ fate-checkasm-sbrdsp \ fate-checkasm-synth_filter \ From dc5d1515681b57a257443ba72bb81fb3e6e6621b Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 6 Jan 2018 18:41:27 +0100 Subject: [PATCH 1753/2557] avformat/hlsenc: use av_bprintf without buffer limit in replace_int_data_in_filename In preparation for the deprecation of AVFormatContext->filename. Signed-off-by: Marton Balint --- libavformat/hlsenc.c | 113 ++++++++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 55 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index aab21f2f5eb8b..d7f8ab50379a6 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -352,14 +352,17 @@ static void write_codec_attr(AVStream *st, VariantStream *vs) { return; } -static int replace_int_data_in_filename(char *buf, int buf_size, const char *filename, char placeholder, int64_t number) +static int replace_int_data_in_filename(char **s, const char *filename, char placeholder, int64_t number) { const char *p; - char *q, buf1[20], c; - int nd, len, addchar_count; + char *new_filename; + char c; + int nd, addchar_count; int found_count = 0; + AVBPrint buf; + + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); - q = buf; p = filename; for (;;) { c = *p; @@ -376,13 +379,7 @@ static int replace_int_data_in_filename(char *buf, int buf_size, const char *fil } if (*(p + addchar_count) == placeholder) { - len = snprintf(buf1, sizeof(buf1), "%0*"PRId64, (number < 0) ? nd : nd++, number); - if (len < 1) // returned error or empty buf1 - goto fail; - if ((q - buf + len) > buf_size - 1) - goto fail; - memcpy(q, buf1, len); - q += len; + av_bprintf(&buf, "%0*"PRId64, (number < 0) ? nd : nd++, number); p += (addchar_count + 1); addchar_count = 0; found_count++; @@ -391,17 +388,17 @@ static int replace_int_data_in_filename(char *buf, int buf_size, const char *fil } else addchar_count = 1; - while (addchar_count--) - if ((q - buf) < buf_size - 1) - *q++ = *p++; - else - goto fail; + av_bprint_append_data(&buf, p, addchar_count); + p += addchar_count; } - *q = '\0'; + if (!av_bprint_is_complete(&buf)) { + av_bprint_finalize(&buf, NULL); + return -1; + } + if (av_bprint_finalize(&buf, &new_filename) < 0 || !new_filename) + return -1; + *s = new_filename; return found_count; -fail: - *q = '\0'; - return -1; } static void write_styp(AVIOContext *pb) @@ -813,13 +810,8 @@ static int sls_flags_filename_process(struct AVFormatContext *s, HLSContext *hls strlen(vs->current_segment_final_filename_fmt)) { av_strlcpy(vs->avf->filename, vs->current_segment_final_filename_fmt, sizeof(vs->avf->filename)); if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) { - char * filename = av_strdup(vs->avf->filename); // %%s will be %s after strftime - if (!filename) { - av_free(en); - return AVERROR(ENOMEM); - } - if (replace_int_data_in_filename(vs->avf->filename, sizeof(vs->avf->filename), - filename, 's', pos + size) < 1) { + char *filename = NULL; + if (replace_int_data_in_filename(&filename, vs->avf->filename, 's', pos + size) < 1) { av_log(hls, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_size flag\n", @@ -828,16 +820,13 @@ static int sls_flags_filename_process(struct AVFormatContext *s, HLSContext *hls av_free(en); return AVERROR(EINVAL); } + av_strlcpy(vs->avf->filename, filename, sizeof(vs->avf->filename)); av_free(filename); } if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) { - char * filename = av_strdup(vs->avf->filename); // %%t will be %t after strftime - if (!filename) { - av_free(en); - return AVERROR(ENOMEM); - } - if (replace_int_data_in_filename(vs->avf->filename, sizeof(vs->avf->filename), - filename, 't', (int64_t)round(duration * HLS_MICROSECOND_UNIT)) < 1) { + char *filename = NULL; + if (replace_int_data_in_filename(&filename, vs->avf->filename, + 't', (int64_t)round(duration * HLS_MICROSECOND_UNIT)) < 1) { av_log(hls, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_time flag\n", @@ -846,6 +835,7 @@ static int sls_flags_filename_process(struct AVFormatContext *s, HLSContext *hls av_free(en); return AVERROR(EINVAL); } + av_strlcpy(vs->avf->filename, filename, sizeof(vs->avf->filename)); av_free(filename); } } @@ -905,14 +895,12 @@ static void sls_flag_file_rename(HLSContext *hls, VariantStream *vs, char *old_f static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c, VariantStream *vs) { if (c->flags & HLS_SECOND_LEVEL_SEGMENT_INDEX) { - char * filename = av_strdup(oc->filename); // %%d will be %d after strftime - if (!filename) - return AVERROR(ENOMEM); - if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename), + char *filename = NULL; + if (replace_int_data_in_filename(&filename, #if FF_API_HLS_WRAP - filename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) { + oc->filename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) { #else - filename, 'd', vs->sequence) < 1) { + oc->filename, 'd', vs->sequence) < 1) { #endif av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_index flag\n", @@ -920,35 +908,34 @@ static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c, V av_free(filename); return AVERROR(EINVAL); } + av_strlcpy(oc->filename, filename, sizeof(oc->filename)); av_free(filename); } if (c->flags & (HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION)) { av_strlcpy(vs->current_segment_final_filename_fmt, oc->filename, sizeof(vs->current_segment_final_filename_fmt)); if (c->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) { - char * filename = av_strdup(oc->filename); // %%s will be %s after strftime - if (!filename) - return AVERROR(ENOMEM); - if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename), filename, 's', 0) < 1) { + char *filename = NULL; + if (replace_int_data_in_filename(&filename, oc->filename, 's', 0) < 1) { av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_size flag\n", filename); av_free(filename); return AVERROR(EINVAL); } + av_strlcpy(oc->filename, filename, sizeof(oc->filename)); av_free(filename); } if (c->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) { - char * filename = av_strdup(oc->filename); // %%t will be %t after strftime - if (!filename) - return AVERROR(ENOMEM); - if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename), filename, 't', 0) < 1) { + char *filename = NULL; + if (replace_int_data_in_filename(&filename, oc->filename, 't', 0) < 1) { av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_time flag\n", filename); av_free(filename); return AVERROR(EINVAL); } + av_strlcpy(oc->filename, filename, sizeof(oc->filename)); av_free(filename); } } @@ -1460,15 +1447,19 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) av_strlcpy(vtt_oc->filename, vs->vtt_basename, sizeof(vtt_oc->filename)); } else if (c->max_seg_size > 0) { - if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename), + char *filename = NULL; + if (replace_int_data_in_filename(&filename, #if FF_API_HLS_WRAP vs->basename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) { #else vs->basename, 'd', vs->sequence) < 1) { #endif + av_free(filename); av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -use_localtime 1 with it\n", vs->basename); return AVERROR(EINVAL); } + av_strlcpy(oc->filename, filename, sizeof(oc->filename)); + av_free(filename); } else { if (c->use_localtime) { time_t now0; @@ -1499,25 +1490,35 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) } av_free(fn_copy); } - } else if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename), + } else { + char *filename = NULL; + if (replace_int_data_in_filename(&filename, #if FF_API_HLS_WRAP vs->basename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) { #else vs->basename, 'd', vs->sequence) < 1) { #endif - av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -use_localtime 1 with it\n", vs->basename); - return AVERROR(EINVAL); + av_free(filename); + av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -use_localtime 1 with it\n", vs->basename); + return AVERROR(EINVAL); + } + av_strlcpy(oc->filename, filename, sizeof(oc->filename)); + av_free(filename); } if( vs->vtt_basename) { - if (replace_int_data_in_filename(vtt_oc->filename, sizeof(vtt_oc->filename), + char *filename = NULL; + if (replace_int_data_in_filename(&filename, #if FF_API_HLS_WRAP vs->vtt_basename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) { #else vs->vtt_basename, 'd', vs->sequence) < 1) { #endif + av_free(filename); av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", vs->vtt_basename); return AVERROR(EINVAL); } + av_strlcpy(vtt_oc->filename, filename, sizeof(vtt_oc->filename)); + av_free(filename); } } vs->number++; @@ -1677,7 +1678,7 @@ static int validate_name(int nb_vs, const char *fn) static int format_name(char *buf, int buf_len, int index) { const char *proto, *dir; - char *orig_buf_dup = NULL, *mod_buf_dup = NULL; + char *orig_buf_dup = NULL, *mod_buf = NULL, *mod_buf_dup = NULL; int ret = 0; if (!av_stristr(buf, "%v")) @@ -1689,10 +1690,11 @@ static int format_name(char *buf, int buf_len, int index) goto fail; } - if (replace_int_data_in_filename(buf, buf_len, orig_buf_dup, 'v', index) < 1) { + if (replace_int_data_in_filename(&mod_buf, orig_buf_dup, 'v', index) < 1) { ret = AVERROR(EINVAL); goto fail; } + av_strlcpy(buf, mod_buf, buf_len); proto = avio_find_protocol_name(orig_buf_dup); dir = av_dirname(orig_buf_dup); @@ -1715,6 +1717,7 @@ static int format_name(char *buf, int buf_len, int index) fail: av_freep(&orig_buf_dup); av_freep(&mod_buf_dup); + av_freep(&mod_buf); return ret; } From ea3672b7d67c432724bdbc8de0221f869b6a04c6 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Fri, 29 Dec 2017 01:01:37 +0100 Subject: [PATCH 1754/2557] avformat: add url field to AVFormatContext This will replace the 1024 character limited filename field. Compatiblity for output contexts are provided by copying filename field to URL if URL is unset and by providing an internal function for muxers to set both url and filename at once. Signed-off-by: Marton Balint --- doc/APIchanges | 3 +++ libavformat/avformat.h | 15 +++++++++++++++ libavformat/internal.h | 7 +++++++ libavformat/mux.c | 11 ++++++++++- libavformat/utils.c | 14 ++++++++++++++ libavformat/version.h | 2 +- 6 files changed, 50 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 59e3b20c08b88..878429848d050 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-01-xx - xxxxxxx - lavf 58.7.100 - avformat.h + Add url field to AVFormatContext and add ff_format_set_url helper function. + 2018-01-xx - xxxxxxx - lavf 58.6.100 - avformat.h Add AVFMTCTX_UNSEEKABLE (for HLS demuxer). diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 60ab9fbc804e1..d1bd4902d0a2e 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1402,6 +1402,21 @@ typedef struct AVFormatContext { */ char filename[1024]; + /** + * input or output URL. Unlike the old filename field, this field has no + * length restriction. + * + * - demuxing: set by avformat_open_input(), initialized to an empty + * string if url parameter was NULL in avformat_open_input(). + * - muxing: may be set by the caller before calling avformat_write_header() + * (or avformat_init_output() if that is called first) to a string + * which is freeable by av_free(). Set to an empty string if it + * was NULL in avformat_init_output(). + * + * Freed by libavformat in avformat_free_context(). + */ + char *url; + /** * Position of the first frame of the component, in * AV_TIME_BASE fractional seconds. NEVER set this value directly: diff --git a/libavformat/internal.h b/libavformat/internal.h index 0cd0556dc799e..1e2a3e05a11b1 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -696,4 +696,11 @@ int ff_interleaved_peek(AVFormatContext *s, int stream, int ff_lock_avformat(void); int ff_unlock_avformat(void); +/** + * Set AVFormatContext url field to the provided pointer. The pointer must + * point to a valid string. The existing url field is freed if necessary. Also + * set the legacy filename field to the same string which was provided in url. + */ +void ff_format_set_url(AVFormatContext *s, char *url); + #endif /* AVFORMAT_INTERNAL_H */ diff --git a/libavformat/mux.c b/libavformat/mux.c index ea9f13fdf5a90..de63f2ca25326 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -186,8 +186,12 @@ int avformat_alloc_output_context2(AVFormatContext **avctx, AVOutputFormat *ofor } else s->priv_data = NULL; - if (filename) + if (filename) { av_strlcpy(s->filename, filename, sizeof(s->filename)); + if (!(s->url = av_strdup(filename))) + goto nomem; + + } *avctx = s; return 0; nomem: @@ -251,6 +255,11 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) (ret = av_opt_set_dict2(s->priv_data, &tmp, AV_OPT_SEARCH_CHILDREN)) < 0) goto fail; + if (!s->url && !(s->url = av_strdup(s->filename))) { + ret = AVERROR(ENOMEM); + goto fail; + } + #if FF_API_LAVF_AVCTX FF_DISABLE_DEPRECATION_WARNINGS if (s->nb_streams && s->streams[0]->codec->flags & AV_CODEC_FLAG_BITEXACT) { diff --git a/libavformat/utils.c b/libavformat/utils.c index c15b8cc8181e0..74e615f86ec80 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -555,6 +555,11 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, if ((ret = av_opt_set_dict(s, &tmp)) < 0) goto fail; + if (!(s->url = av_strdup(filename ? filename : ""))) { + ret = AVERROR(ENOMEM); + goto fail; + } + av_strlcpy(s->filename, filename ? filename : "", sizeof(s->filename)); if ((ret = init_input(s, filename, &tmp)) < 0) goto fail; @@ -4371,6 +4376,7 @@ void avformat_free_context(AVFormatContext *s) av_freep(&s->streams); flush_packet_queue(s); av_freep(&s->internal); + av_freep(&s->url); av_free(s); } @@ -5636,3 +5642,11 @@ FF_ENABLE_DEPRECATION_WARNINGS return st->internal->avctx->time_base; #endif } + +void ff_format_set_url(AVFormatContext *s, char *url) +{ + av_assert0(url); + av_freep(&s->url); + s->url = url; + av_strlcpy(s->filename, url, sizeof(s->filename)); +} diff --git a/libavformat/version.h b/libavformat/version.h index 5ff8a89ae0864..c375b0da15729 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 6 +#define LIBAVFORMAT_VERSION_MINOR 7 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From 25a2d269bdd919e633e202b67927c3c72f9f0dd5 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Fri, 29 Dec 2017 23:29:27 +0100 Subject: [PATCH 1755/2557] fftools, tools, examples: migrate to AVFormatContext->url Signed-off-by: Marton Balint --- doc/examples/transcode_aac.c | 7 +++++-- fftools/ffmpeg.c | 16 ++++++++-------- fftools/ffmpeg_opt.c | 8 ++++---- fftools/ffplay.c | 6 +++--- fftools/ffprobe.c | 2 +- tools/uncoded_frame.c | 2 +- 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/doc/examples/transcode_aac.c b/doc/examples/transcode_aac.c index 9fd5c00d6059e..3c7688cd3383f 100644 --- a/doc/examples/transcode_aac.c +++ b/doc/examples/transcode_aac.c @@ -171,8 +171,11 @@ static int open_output_file(const char *filename, goto cleanup; } - av_strlcpy((*output_format_context)->filename, filename, - sizeof((*output_format_context)->filename)); + if (!((*output_format_context)->url = av_strdup(filename))) { + fprintf(stderr, "Could not allocate url.\n"); + error = AVERROR(ENOMEM); + goto cleanup; + } /* Find the encoder to be used by its name. */ if (!(output_codec = avcodec_find_encoder(AV_CODEC_ID_AAC))) { diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 918eb353aac9e..a37de2ff98419 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1563,7 +1563,7 @@ static void print_final_stats(int64_t total_size) uint64_t total_packets = 0, total_size = 0; av_log(NULL, AV_LOG_VERBOSE, "Input file #%d (%s):\n", - i, f->ctx->filename); + i, f->ctx->url); for (j = 0; j < f->nb_streams; j++) { InputStream *ist = input_streams[f->ist_index + j]; @@ -1597,7 +1597,7 @@ static void print_final_stats(int64_t total_size) uint64_t total_packets = 0, total_size = 0; av_log(NULL, AV_LOG_VERBOSE, "Output file #%d (%s):\n", - i, of->ctx->filename); + i, of->ctx->url); for (j = 0; j < of->ctx->nb_streams; j++) { OutputStream *ost = output_streams[of->ost_index + j]; @@ -2105,7 +2105,7 @@ static void check_decode_result(InputStream *ist, int *got_output, int ret) if (exit_on_error && *got_output && ist) { if (ist->decoded_frame->decode_error_flags || (ist->decoded_frame->flags & AV_FRAME_FLAG_CORRUPT)) { - av_log(NULL, AV_LOG_FATAL, "%s: corrupt decoded frame in stream %d\n", input_files[ist->file_index]->ctx->filename, ist->st->index); + av_log(NULL, AV_LOG_FATAL, "%s: corrupt decoded frame in stream %d\n", input_files[ist->file_index]->ctx->url, ist->st->index); exit_program(1); } } @@ -2989,7 +2989,7 @@ static int check_init_output_file(OutputFile *of, int file_index) //assert_avoptions(of->opts); of->header_written = 1; - av_dump_format(of->ctx, file_index, of->ctx->filename, 1); + av_dump_format(of->ctx, file_index, of->ctx->url, 1); if (sdp_filename || want_sdp) print_sdp(); @@ -4252,7 +4252,7 @@ static int process_input(int file_index) } if (ret < 0) { if (ret != AVERROR_EOF) { - print_error(is->filename, ret); + print_error(is->url, ret); if (exit_on_error) exit_program(1); } @@ -4301,7 +4301,7 @@ static int process_input(int file_index) goto discard_packet; if (exit_on_error && (pkt.flags & AV_PKT_FLAG_CORRUPT)) { - av_log(NULL, AV_LOG_FATAL, "%s: corrupt input packet in stream %d\n", is->filename, pkt.stream_index); + av_log(NULL, AV_LOG_FATAL, "%s: corrupt input packet in stream %d\n", is->url, pkt.stream_index); exit_program(1); } @@ -4668,11 +4668,11 @@ static int transcode(void) av_log(NULL, AV_LOG_ERROR, "Nothing was written into output file %d (%s), because " "at least one of its streams received no packets.\n", - i, os->filename); + i, os->url); continue; } if ((ret = av_write_trailer(os)) < 0) { - av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s\n", os->filename, av_err2str(ret)); + av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s\n", os->url, av_err2str(ret)); if (exit_on_error) exit_program(1); } diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 92199b3ac28f2..997d53838108c 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1271,7 +1271,7 @@ static int choose_encoder(OptionsContext *o, AVFormatContext *s, OutputStream *o if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_SUBTITLE) { MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st); if (!codec_name) { - ost->st->codecpar->codec_id = av_guess_codec(s->oformat, NULL, s->filename, + ost->st->codecpar->codec_id = av_guess_codec(s->oformat, NULL, s->url, NULL, ost->st->codecpar->codec_type); ost->enc = avcodec_find_encoder(ost->st->codecpar->codec_id); if (!ost->enc) { @@ -2334,7 +2334,7 @@ static int open_output_file(OptionsContext *o, const char *filename) #endif if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) { - av_dump_format(oc, nb_output_files - 1, oc->filename, 1); + av_dump_format(oc, nb_output_files - 1, oc->url, 1); av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", nb_output_files - 1); exit_program(1); } @@ -2466,8 +2466,8 @@ static int open_output_file(OptionsContext *o, const char *filename) /* check filename in case of an image number is expected */ if (oc->oformat->flags & AVFMT_NEEDNUMBER) { - if (!av_filename_number_test(oc->filename)) { - print_error(oc->filename, AVERROR(EINVAL)); + if (!av_filename_number_test(oc->url)) { + print_error(oc->url, AVERROR(EINVAL)); exit_program(1); } } diff --git a/fftools/ffplay.c b/fftools/ffplay.c index 9bfa3e6ceabd3..f2028d4b13df9 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -2712,8 +2712,8 @@ static int is_realtime(AVFormatContext *s) ) return 1; - if(s->pb && ( !strncmp(s->filename, "rtp:", 4) - || !strncmp(s->filename, "udp:", 4) + if(s->pb && ( !strncmp(s->url, "rtp:", 4) + || !strncmp(s->url, "udp:", 4) ) ) return 1; @@ -2928,7 +2928,7 @@ static int read_thread(void *arg) ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, - "%s: error while seeking\n", is->ic->filename); + "%s: error while seeking\n", is->ic->url); } else { if (is->audio_stream >= 0) { packet_queue_flush(&is->audioq); diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 0e7a771517d43..acb403e3b12ac 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2778,7 +2778,7 @@ static int show_format(WriterContext *w, InputFile *ifile) int ret = 0; writer_print_section_header(w, SECTION_ID_FORMAT); - print_str_validate("filename", fmt_ctx->filename); + print_str_validate("filename", fmt_ctx->url); print_int("nb_streams", fmt_ctx->nb_streams); print_int("nb_programs", fmt_ctx->nb_programs); print_str("format_name", fmt_ctx->iformat->name); diff --git a/tools/uncoded_frame.c b/tools/uncoded_frame.c index 606bdb746ae3a..3aaa4b6897544 100644 --- a/tools/uncoded_frame.c +++ b/tools/uncoded_frame.c @@ -141,7 +141,7 @@ int main(int argc, char **argv) goto fail; } if (!(st->mux->oformat->flags & AVFMT_NOFILE)) { - ret = avio_open2(&st->mux->pb, st->mux->filename, AVIO_FLAG_WRITE, + ret = avio_open2(&st->mux->pb, st->mux->url, AVIO_FLAG_WRITE, NULL, NULL); if (ret < 0) { av_log(st->mux, AV_LOG_ERROR, "Failed to init output: %s\n", From 4bb04098204afadc8604af0113294f8ecc63a2de Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Fri, 29 Dec 2017 23:29:52 +0100 Subject: [PATCH 1756/2557] avdevice: migrate to AVFormatContext->url Signed-off-by: Marton Balint --- libavdevice/alsa.c | 4 ++-- libavdevice/avfoundation.m | 2 +- libavdevice/bktr.c | 2 +- libavdevice/caca.c | 2 +- libavdevice/decklink_common.cpp | 2 +- libavdevice/decklink_dec.cpp | 4 ++-- libavdevice/decklink_enc.cpp | 4 ++-- libavdevice/dshow.c | 2 +- libavdevice/fbdev_dec.c | 4 ++-- libavdevice/fbdev_enc.c | 4 ++-- libavdevice/gdigrab.c | 2 +- libavdevice/iec61883.c | 8 ++++---- libavdevice/jack.c | 6 +++--- libavdevice/lavfi.c | 2 +- libavdevice/libcdio.c | 6 +++--- libavdevice/libndi_newtek_dec.c | 2 +- libavdevice/libndi_newtek_enc.c | 4 ++-- libavdevice/openal-dec.c | 2 +- libavdevice/opengl_enc.c | 2 +- libavdevice/oss_dec.c | 2 +- libavdevice/oss_enc.c | 2 +- libavdevice/pulse_audio_dec.c | 4 ++-- libavdevice/pulse_audio_enc.c | 4 ++-- libavdevice/sdl2.c | 2 +- libavdevice/sndio_dec.c | 2 +- libavdevice/sndio_enc.c | 2 +- libavdevice/v4l2.c | 16 +++++++++------- libavdevice/v4l2enc.c | 4 ++-- libavdevice/vfwcap.c | 4 ++-- libavdevice/xcbgrab.c | 8 ++++---- libavdevice/xv.c | 2 +- 31 files changed, 59 insertions(+), 57 deletions(-) diff --git a/libavdevice/alsa.c b/libavdevice/alsa.c index 1bbff30d5cc43..1b21beb6d51e7 100644 --- a/libavdevice/alsa.c +++ b/libavdevice/alsa.c @@ -177,8 +177,8 @@ av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode, snd_pcm_uframes_t buffer_size, period_size; uint64_t layout = ctx->streams[0]->codecpar->channel_layout; - if (ctx->filename[0] == 0) audio_device = "default"; - else audio_device = ctx->filename; + if (ctx->url[0] == 0) audio_device = "default"; + else audio_device = ctx->url; if (*codec_id == AV_CODEC_ID_NONE) *codec_id = DEFAULT_CODEC_ID; diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m index e2ddf47dbe8dc..a540f6a079246 100644 --- a/libavdevice/avfoundation.m +++ b/libavdevice/avfoundation.m @@ -259,7 +259,7 @@ static void destroy_context(AVFContext* ctx) static void parse_device_name(AVFormatContext *s) { AVFContext *ctx = (AVFContext*)s->priv_data; - char *tmp = av_strdup(s->filename); + char *tmp = av_strdup(s->url); char *save; if (tmp[0] != ':') { diff --git a/libavdevice/bktr.c b/libavdevice/bktr.c index 418247dc4eb5e..993cc19ac7c79 100644 --- a/libavdevice/bktr.c +++ b/libavdevice/bktr.c @@ -294,7 +294,7 @@ static int grab_read_header(AVFormatContext *s1) st->codecpar->height = s->height; st->avg_frame_rate = framerate; - if (bktr_init(s1->filename, s->width, s->height, s->standard, + if (bktr_init(s1->url, s->width, s->height, s->standard, &s->video_fd, &s->tuner_fd, -1, 0.0) < 0) { ret = AVERROR(EIO); goto out; diff --git a/libavdevice/caca.c b/libavdevice/caca.c index 93cc0ffd252e9..47de8247dcf11 100644 --- a/libavdevice/caca.c +++ b/libavdevice/caca.c @@ -178,7 +178,7 @@ static int caca_write_header(AVFormatContext *s) } if (!c->window_title) - c->window_title = av_strdup(s->filename); + c->window_title = av_strdup(s->url); caca_set_display_title(c->display, c->window_title); caca_set_display_time(c->display, av_rescale_q(1, st->codec->time_base, AV_TIME_BASE_Q)); diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp index d1576b85535dc..da414ed5f8b81 100644 --- a/libavdevice/decklink_common.cpp +++ b/libavdevice/decklink_common.cpp @@ -404,7 +404,7 @@ int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direct } av_log(avctx, AV_LOG_INFO, "Supported formats for '%s':\n\tformat_code\tdescription", - avctx->filename); + avctx->url); while (itermode->Next(&mode) == S_OK) { BMDTimeValue tb_num, tb_den; mode->GetFrameRate(&tb_num, &tb_den); diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index a69e28680be3a..5c116f2d1371d 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -951,7 +951,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) cctx->raw_format = MKBETAG('v','2','1','0'); } - strcpy (fname, avctx->filename); + av_strlcpy(fname, avctx->url, sizeof(fname)); tmp=strchr (fname, '@'); if (tmp != NULL) { av_log(avctx, AV_LOG_WARNING, "The @mode syntax is deprecated and will be removed. Please use the -format_code option.\n"); @@ -966,7 +966,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) /* Get input device. */ if (ctx->dl->QueryInterface(IID_IDeckLinkInput, (void **) &ctx->dli) != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not open input device from '%s'\n", - avctx->filename); + avctx->url); ret = AVERROR(EIO); goto error; } diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index 89b03f2bd5648..28ab928cd50cd 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -400,14 +400,14 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx) return AVERROR_EXIT; } - ret = ff_decklink_init_device(avctx, avctx->filename); + ret = ff_decklink_init_device(avctx, avctx->url); if (ret < 0) return ret; /* Get output device. */ if (ctx->dl->QueryInterface(IID_IDeckLinkOutput, (void **) &ctx->dlo) != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not open output device from '%s'\n", - avctx->filename); + avctx->url); ret = AVERROR(EIO); goto error; } diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index f2453e6114477..de910c0994344 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -1033,7 +1033,7 @@ static int parse_device_name(AVFormatContext *avctx) { struct dshow_ctx *ctx = avctx->priv_data; char **device_name = ctx->device_name; - char *name = av_strdup(avctx->filename); + char *name = av_strdup(avctx->url); char *tmp = name; int ret = 1; char *type; diff --git a/libavdevice/fbdev_dec.c b/libavdevice/fbdev_dec.c index d9c75df2029b6..6a5181686812c 100644 --- a/libavdevice/fbdev_dec.c +++ b/libavdevice/fbdev_dec.c @@ -78,8 +78,8 @@ static av_cold int fbdev_read_header(AVFormatContext *avctx) if (avctx->flags & AVFMT_FLAG_NONBLOCK) flags |= O_NONBLOCK; - if (avctx->filename[0]) - device = avctx->filename; + if (avctx->url[0]) + device = avctx->url; else device = ff_fbdev_default_device(); diff --git a/libavdevice/fbdev_enc.c b/libavdevice/fbdev_enc.c index b4e5f849759ff..4191596825069 100644 --- a/libavdevice/fbdev_enc.c +++ b/libavdevice/fbdev_enc.c @@ -53,8 +53,8 @@ static av_cold int fbdev_write_header(AVFormatContext *h) return AVERROR(EINVAL); } - if (h->filename[0]) - device = h->filename; + if (h->url[0]) + device = h->url; else device = ff_fbdev_default_device(); diff --git a/libavdevice/gdigrab.c b/libavdevice/gdigrab.c index ff2ef3b1629f3..ab08c11788481 100644 --- a/libavdevice/gdigrab.c +++ b/libavdevice/gdigrab.c @@ -230,7 +230,7 @@ gdigrab_read_header(AVFormatContext *s1) HBITMAP hbmp = NULL; void *buffer = NULL; - const char *filename = s1->filename; + const char *filename = s1->url; const char *name = NULL; AVStream *st = NULL; diff --git a/libavdevice/iec61883.c b/libavdevice/iec61883.c index 721dca38eef99..7d4d37847cba7 100644 --- a/libavdevice/iec61883.c +++ b/libavdevice/iec61883.c @@ -259,14 +259,14 @@ static int iec61883_read_header(AVFormatContext *context) goto fail; } - inport = strtol(context->filename, &endptr, 10); - if (endptr != context->filename && *endptr == '\0') { + inport = strtol(context->url, &endptr, 10); + if (endptr != context->url && *endptr == '\0') { av_log(context, AV_LOG_INFO, "Selecting IEEE1394 port: %d\n", inport); j = inport; nb_ports = inport + 1; - } else if (strcmp(context->filename, "auto")) { + } else if (strcmp(context->url, "auto")) { av_log(context, AV_LOG_ERROR, "Invalid input \"%s\", you should specify " - "\"auto\" for auto-detection, or the port number.\n", context->filename); + "\"auto\" for auto-detection, or the port number.\n", context->url); goto fail; } diff --git a/libavdevice/jack.c b/libavdevice/jack.c index e35a4a815aea7..34f1c6de97350 100644 --- a/libavdevice/jack.c +++ b/libavdevice/jack.c @@ -150,8 +150,8 @@ static int start_jack(AVFormatContext *context) jack_status_t status; int i, test; - /* Register as a JACK client, using the context filename as client name. */ - self->client = jack_client_open(context->filename, JackNullOption, &status); + /* Register as a JACK client, using the context url as client name. */ + self->client = jack_client_open(context->url, JackNullOption, &status); if (!self->client) { av_log(context, AV_LOG_ERROR, "Unable to register as a JACK client\n"); return AVERROR(EIO); @@ -174,7 +174,7 @@ static int start_jack(AVFormatContext *context) JackPortIsInput, 0); if (!self->ports[i]) { av_log(context, AV_LOG_ERROR, "Unable to register port %s:%s\n", - context->filename, str); + context->url, str); jack_client_close(self->client); return AVERROR(EIO); } diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index 5273717e6b234..6f2ae958dcbf7 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -166,7 +166,7 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) } if (!lavfi->graph_str) - lavfi->graph_str = av_strdup(avctx->filename); + lavfi->graph_str = av_strdup(avctx->url); /* parse the graph, create a stream for each open output */ if (!(lavfi->graph = avfilter_graph_alloc())) diff --git a/libavdevice/libcdio.c b/libavdevice/libcdio.c index f6d4fce25629f..a4c9f52337373 100644 --- a/libavdevice/libcdio.c +++ b/libavdevice/libcdio.c @@ -60,9 +60,9 @@ static av_cold int read_header(AVFormatContext *ctx) if (!(st = avformat_new_stream(ctx, NULL))) return AVERROR(ENOMEM); - s->drive = cdio_cddap_identify(ctx->filename, CDDA_MESSAGE_LOGIT, &err); + s->drive = cdio_cddap_identify(ctx->url, CDDA_MESSAGE_LOGIT, &err); if (!s->drive) { - av_log(ctx, AV_LOG_ERROR, "Could not open drive %s.\n", ctx->filename); + av_log(ctx, AV_LOG_ERROR, "Could not open drive %s.\n", ctx->url); return AVERROR(EINVAL); } if (err) { @@ -70,7 +70,7 @@ static av_cold int read_header(AVFormatContext *ctx) free(err); } if ((ret = cdio_cddap_open(s->drive)) < 0 || !s->drive->opened) { - av_log(ctx, AV_LOG_ERROR, "Could not open disk in drive %s.\n", ctx->filename); + av_log(ctx, AV_LOG_ERROR, "Could not open disk in drive %s.\n", ctx->url); return AVERROR(EINVAL); } diff --git a/libavdevice/libndi_newtek_dec.c b/libavdevice/libndi_newtek_dec.c index 2f14f4b03fd77..4fb719770e57c 100644 --- a/libavdevice/libndi_newtek_dec.c +++ b/libavdevice/libndi_newtek_dec.c @@ -149,7 +149,7 @@ static int ndi_read_header(AVFormatContext *avctx) } /* Find available sources. */ - ret = ndi_find_sources(avctx, avctx->filename, &recv_create_desc.source_to_connect_to); + ret = ndi_find_sources(avctx, avctx->url, &recv_create_desc.source_to_connect_to); if (ctx->find_sources) { return AVERROR_EXIT; } diff --git a/libavdevice/libndi_newtek_enc.c b/libavdevice/libndi_newtek_enc.c index 6ca6f41b734ed..f3603f5a3ad6e 100644 --- a/libavdevice/libndi_newtek_enc.c +++ b/libavdevice/libndi_newtek_enc.c @@ -233,7 +233,7 @@ static int ndi_write_header(AVFormatContext *avctx) int ret = 0; unsigned int n; struct NDIContext *ctx = avctx->priv_data; - const NDIlib_send_create_t ndi_send_desc = { .p_ndi_name = avctx->filename, + const NDIlib_send_create_t ndi_send_desc = { .p_ndi_name = avctx->url, .p_groups = NULL, .clock_video = ctx->clock_video, .clock_audio = ctx->clock_audio }; if (!NDIlib_initialize()) { @@ -260,7 +260,7 @@ static int ndi_write_header(AVFormatContext *avctx) ctx->ndi_send = NDIlib_send_create(&ndi_send_desc); if (!ctx->ndi_send) { - av_log(avctx, AV_LOG_ERROR, "Failed to create NDI output %s\n", avctx->filename); + av_log(avctx, AV_LOG_ERROR, "Failed to create NDI output %s\n", avctx->url); ret = AVERROR_EXTERNAL; } diff --git a/libavdevice/openal-dec.c b/libavdevice/openal-dec.c index 6eb0efe38f1e3..c19048e15d34a 100644 --- a/libavdevice/openal-dec.c +++ b/libavdevice/openal-dec.c @@ -139,7 +139,7 @@ static int read_header(AVFormatContext *ctx) /* Open device for capture */ ad->device = - alcCaptureOpenDevice(ctx->filename[0] ? ctx->filename : NULL, + alcCaptureOpenDevice(ctx->url[0] ? ctx->url : NULL, ad->sample_rate, ad->sample_format, ad->sample_rate); /* Maximum 1 second of sample data to be read at once */ diff --git a/libavdevice/opengl_enc.c b/libavdevice/opengl_enc.c index bb6787c6f13ba..54c7e610bd52b 100644 --- a/libavdevice/opengl_enc.c +++ b/libavdevice/opengl_enc.c @@ -1070,7 +1070,7 @@ static av_cold int opengl_write_header(AVFormatContext *h) opengl->window_height = opengl->height; if (!opengl->window_title && !opengl->no_window) - opengl->window_title = av_strdup(h->filename); + opengl->window_title = av_strdup(h->url); if ((ret = opengl_create_window(h))) goto fail; diff --git a/libavdevice/oss_dec.c b/libavdevice/oss_dec.c index 6fef96a450711..d0dc327dc6273 100644 --- a/libavdevice/oss_dec.c +++ b/libavdevice/oss_dec.c @@ -52,7 +52,7 @@ static int audio_read_header(AVFormatContext *s1) return AVERROR(ENOMEM); } - ret = ff_oss_audio_open(s1, 0, s1->filename); + ret = ff_oss_audio_open(s1, 0, s1->url); if (ret < 0) { return AVERROR(EIO); } diff --git a/libavdevice/oss_enc.c b/libavdevice/oss_enc.c index e7a7b6d403550..e3172afaa47b9 100644 --- a/libavdevice/oss_enc.c +++ b/libavdevice/oss_enc.c @@ -46,7 +46,7 @@ static int audio_write_header(AVFormatContext *s1) st = s1->streams[0]; s->sample_rate = st->codecpar->sample_rate; s->channels = st->codecpar->channels; - ret = ff_oss_audio_open(s1, 1, s1->filename); + ret = ff_oss_audio_open(s1, 1, s1->url); if (ret < 0) { return AVERROR(EIO); } else { diff --git a/libavdevice/pulse_audio_dec.c b/libavdevice/pulse_audio_dec.c index 95a1d6ecfa620..5977fb7e9e5f6 100644 --- a/libavdevice/pulse_audio_dec.c +++ b/libavdevice/pulse_audio_dec.c @@ -158,8 +158,8 @@ static av_cold int pulse_read_header(AVFormatContext *s) attr.fragsize = pd->fragment_size; - if (s->filename[0] != '\0' && strcmp(s->filename, "default")) - device = s->filename; + if (s->url[0] != '\0' && strcmp(s->url, "default")) + device = s->url; if (!(pd->mainloop = pa_threaded_mainloop_new())) { pulse_close(s); diff --git a/libavdevice/pulse_audio_enc.c b/libavdevice/pulse_audio_enc.c index 0efcf0fe7e5c6..d430b77272647 100644 --- a/libavdevice/pulse_audio_enc.c +++ b/libavdevice/pulse_audio_enc.c @@ -459,8 +459,8 @@ static av_cold int pulse_write_header(AVFormatContext *h) st = h->streams[0]; if (!stream_name) { - if (h->filename[0]) - stream_name = h->filename; + if (h->url[0]) + stream_name = h->url; else stream_name = "Playback"; } diff --git a/libavdevice/sdl2.c b/libavdevice/sdl2.c index 5d9e91ec2139a..48ed977bebd35 100644 --- a/libavdevice/sdl2.c +++ b/libavdevice/sdl2.c @@ -165,7 +165,7 @@ static int sdl2_write_header(AVFormatContext *s) int flags = 0; if (!sdl->window_title) - sdl->window_title = av_strdup(s->filename); + sdl->window_title = av_strdup(s->url); if (SDL_WasInit(SDL_INIT_VIDEO)) { av_log(s, AV_LOG_WARNING, diff --git a/libavdevice/sndio_dec.c b/libavdevice/sndio_dec.c index 2d13232bf17a6..ebb485a2c7b78 100644 --- a/libavdevice/sndio_dec.c +++ b/libavdevice/sndio_dec.c @@ -41,7 +41,7 @@ static av_cold int audio_read_header(AVFormatContext *s1) if (!st) return AVERROR(ENOMEM); - ret = ff_sndio_open(s1, 0, s1->filename); + ret = ff_sndio_open(s1, 0, s1->url); if (ret < 0) return ret; diff --git a/libavdevice/sndio_enc.c b/libavdevice/sndio_enc.c index 47f500d71e515..f6dd2901089c2 100644 --- a/libavdevice/sndio_enc.c +++ b/libavdevice/sndio_enc.c @@ -38,7 +38,7 @@ static av_cold int audio_write_header(AVFormatContext *s1) s->sample_rate = st->codecpar->sample_rate; s->channels = st->codecpar->channels; - ret = ff_sndio_open(s1, 1, s1->filename); + ret = ff_sndio_open(s1, 1, s1->url); return ret; } diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index f087badf5ca74..10a0ff0dd611c 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -106,7 +106,7 @@ struct buff_data { int index; }; -static int device_open(AVFormatContext *ctx) +static int device_open(AVFormatContext *ctx, const char* device_path) { struct video_data *s = ctx->priv_data; struct v4l2_capability cap; @@ -147,11 +147,11 @@ static int device_open(AVFormatContext *ctx) flags |= O_NONBLOCK; } - fd = v4l2_open(ctx->filename, flags, 0); + fd = v4l2_open(device_path, flags, 0); if (fd < 0) { err = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s: %s\n", - ctx->filename, av_err2str(err)); + device_path, av_err2str(err)); return err; } @@ -840,7 +840,7 @@ static int v4l2_read_header(AVFormatContext *ctx) v4l2_log_file = fopen("/dev/null", "w"); #endif - s->fd = device_open(ctx); + s->fd = device_open(ctx, ctx->url); if (s->fd < 0) return s->fd; @@ -1042,11 +1042,13 @@ static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_l return ret; } while ((entry = readdir(dir))) { + char device_name[256]; + if (!v4l2_is_v4l_dev(entry->d_name)) continue; - snprintf(ctx->filename, sizeof(ctx->filename), "/dev/%s", entry->d_name); - if ((s->fd = device_open(ctx)) < 0) + snprintf(device_name, sizeof(device_name), "/dev/%s", entry->d_name); + if ((s->fd = device_open(ctx, device_name)) < 0) continue; if (v4l2_ioctl(s->fd, VIDIOC_QUERYCAP, &cap) < 0) { @@ -1060,7 +1062,7 @@ static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_l ret = AVERROR(ENOMEM); goto fail; } - device->device_name = av_strdup(ctx->filename); + device->device_name = av_strdup(device_name); device->device_description = av_strdup(cap.card); if (!device->device_name || !device->device_description) { ret = AVERROR(ENOMEM); diff --git a/libavdevice/v4l2enc.c b/libavdevice/v4l2enc.c index faf6e07f86796..85200d0a36314 100644 --- a/libavdevice/v4l2enc.c +++ b/libavdevice/v4l2enc.c @@ -39,10 +39,10 @@ static av_cold int write_header(AVFormatContext *s1) if (s1->flags & AVFMT_FLAG_NONBLOCK) flags |= O_NONBLOCK; - s->fd = open(s1->filename, flags); + s->fd = open(s1->url, flags); if (s->fd < 0) { res = AVERROR(errno); - av_log(s1, AV_LOG_ERROR, "Unable to open V4L2 device '%s'\n", s1->filename); + av_log(s1, AV_LOG_ERROR, "Unable to open V4L2 device '%s'\n", s1->url); return res; } diff --git a/libavdevice/vfwcap.c b/libavdevice/vfwcap.c index f03d38ac2629c..6a923d9957802 100644 --- a/libavdevice/vfwcap.c +++ b/libavdevice/vfwcap.c @@ -256,7 +256,7 @@ static int vfw_read_header(AVFormatContext *s) int ret; AVRational framerate_q; - if (!strcmp(s->filename, "list")) { + if (!strcmp(s->url, "list")) { for (devnum = 0; devnum <= 9; devnum++) { char driver_name[256]; char driver_ver[256]; @@ -279,7 +279,7 @@ static int vfw_read_header(AVFormatContext *s) } /* If atoi fails, devnum==0 and the default device is used */ - devnum = atoi(s->filename); + devnum = atoi(s->url); ret = SendMessage(ctx->hwnd, WM_CAP_DRIVER_CONNECT, devnum, 0); if(!ret) { diff --git a/libavdevice/xcbgrab.c b/libavdevice/xcbgrab.c index 1968fe02d4f45..6d142abd4fd3a 100644 --- a/libavdevice/xcbgrab.c +++ b/libavdevice/xcbgrab.c @@ -629,14 +629,14 @@ static av_cold int xcbgrab_read_header(AVFormatContext *s) XCBGrabContext *c = s->priv_data; int screen_num, ret; const xcb_setup_t *setup; - char *display_name = av_strdup(s->filename); + char *display_name = av_strdup(s->url); if (!display_name) return AVERROR(ENOMEM); - if (!sscanf(s->filename, "%[^+]+%d,%d", display_name, &c->x, &c->y)) { + if (!sscanf(s->url, "%[^+]+%d,%d", display_name, &c->x, &c->y)) { *display_name = 0; - sscanf(s->filename, "+%d,%d", &c->x, &c->y); + sscanf(s->url, "+%d,%d", &c->x, &c->y); } c->conn = xcb_connect(display_name[0] ? display_name : NULL, &screen_num); @@ -644,7 +644,7 @@ static av_cold int xcbgrab_read_header(AVFormatContext *s) if ((ret = xcb_connection_has_error(c->conn))) { av_log(s, AV_LOG_ERROR, "Cannot open display %s, error %d.\n", - s->filename[0] ? s->filename : "default", ret); + s->url[0] ? s->url : "default", ret); return AVERROR(EIO); } diff --git a/libavdevice/xv.c b/libavdevice/xv.c index 185de7569e10a..c3ed2e48bd25c 100644 --- a/libavdevice/xv.c +++ b/libavdevice/xv.c @@ -151,7 +151,7 @@ static int xv_write_header(AVFormatContext *s) xv->window_width, xv->window_height, 0, 0, 0); if (!xv->window_title) { - if (!(xv->window_title = av_strdup(s->filename))) { + if (!(xv->window_title = av_strdup(s->url))) { ret = AVERROR(ENOMEM); goto fail; } From 45ec2e44be911da073b02ae3a14e3cb08ce0a1f5 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Fri, 29 Dec 2017 22:00:04 +0100 Subject: [PATCH 1757/2557] avformat/hls: migrate to AVFormatContext->url Signed-off-by: Marton Balint --- libavformat/hls.c | 4 +- libavformat/hlsenc.c | 166 ++++++++++++++++++++++++------------------- 2 files changed, 96 insertions(+), 74 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 02e764f932827..ba7eb941215b8 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1682,7 +1682,7 @@ static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url, av_log(s, AV_LOG_ERROR, "A HLS playlist item '%s' referred to an external file '%s'. " "Opening this file was forbidden for security reasons\n", - s->filename, url); + s->url, url); return AVERROR(EPERM); } @@ -1820,7 +1820,7 @@ static int hls_read_header(AVFormatContext *s) update_options(&c->http_proxy, "http_proxy", u); } - if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0) + if ((ret = parse_playlist(c, s->url, NULL, s->pb)) < 0) goto fail; if ((ret = save_avio_options(s)) < 0) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index d7f8ab50379a6..cc13c94e9741a 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -292,7 +292,7 @@ static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSContext *c) { - int http_base_proto = ff_is_http_proto(s->filename); + int http_base_proto = ff_is_http_proto(s->url); if (c->method) { av_dict_set(options, "method", c->method, 0); @@ -467,7 +467,7 @@ static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, if (hls->segment_filename) { dirname = av_strdup(hls->segment_filename); } else { - dirname = av_strdup(vs->avf->filename); + dirname = av_strdup(vs->avf->url); } if (!dirname) { ret = AVERROR(ENOMEM); @@ -494,7 +494,7 @@ static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, av_strlcat(path, segment->filename, path_size); } - proto = avio_find_protocol_name(s->filename); + proto = avio_find_protocol_name(s->url); if (hls->method || (proto && !av_strcasecmp(proto, "http"))) { av_dict_set(&options, "method", "DELETE", 0); if ((ret = vs->avf->io_open(vs->avf, &out, path, AVIO_FLAG_WRITE, &options)) < 0) @@ -564,12 +564,12 @@ static int do_encrypt(AVFormatContext *s, VariantStream *vs) AVIOContext *pb; uint8_t key[KEYSIZE]; - len = strlen(s->filename) + 4 + 1; + len = strlen(s->url) + 4 + 1; hls->key_basename = av_mallocz(len); if (!hls->key_basename) return AVERROR(ENOMEM); - av_strlcpy(hls->key_basename, s->filename, len); + av_strlcpy(hls->key_basename, s->url, len); av_strlcat(hls->key_basename, ".key", len); if (hls->key_url) { @@ -699,7 +699,10 @@ static int hls_mux_init(AVFormatContext *s, VariantStream *vs) return ret; oc = vs->avf; - oc->filename[0] = '\0'; + oc->url = av_strdup(""); + if (!oc->url) + return AVERROR(ENOMEM); + oc->oformat = vs->oformat; oc->interrupt_callback = s->interrupt_callback; oc->max_delay = s->max_delay; @@ -808,35 +811,38 @@ static int sls_flags_filename_process(struct AVFormatContext *s, HLSContext *hls { if ((hls->flags & (HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION)) && strlen(vs->current_segment_final_filename_fmt)) { - av_strlcpy(vs->avf->filename, vs->current_segment_final_filename_fmt, sizeof(vs->avf->filename)); + char * new_url = av_strdup(vs->current_segment_final_filename_fmt); + if (!new_url) { + av_free(en); + return AVERROR(ENOMEM); + } + ff_format_set_url(vs->avf, new_url); if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) { char *filename = NULL; - if (replace_int_data_in_filename(&filename, vs->avf->filename, 's', pos + size) < 1) { + if (replace_int_data_in_filename(&filename, vs->avf->url, 's', pos + size) < 1) { av_log(hls, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_size flag\n", - filename); + vs->avf->url); av_free(filename); av_free(en); return AVERROR(EINVAL); } - av_strlcpy(vs->avf->filename, filename, sizeof(vs->avf->filename)); - av_free(filename); + ff_format_set_url(vs->avf, filename); } if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) { char *filename = NULL; - if (replace_int_data_in_filename(&filename, vs->avf->filename, + if (replace_int_data_in_filename(&filename, vs->avf->url, 't', (int64_t)round(duration * HLS_MICROSECOND_UNIT)) < 1) { av_log(hls, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_time flag\n", - filename); + vs->avf->url); av_free(filename); av_free(en); return AVERROR(EINVAL); } - av_strlcpy(vs->avf->filename, filename, sizeof(vs->avf->filename)); - av_free(filename); + ff_format_set_url(vs->avf, filename); } } return 0; @@ -888,7 +894,7 @@ static int sls_flag_check_duration_size(HLSContext *hls, VariantStream *vs) static void sls_flag_file_rename(HLSContext *hls, VariantStream *vs, char *old_filename) { if ((hls->flags & (HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION)) && strlen(vs->current_segment_final_filename_fmt)) { - ff_rename(old_filename, vs->avf->filename, hls); + ff_rename(old_filename, vs->avf->url, hls); } } @@ -898,45 +904,42 @@ static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c, V char *filename = NULL; if (replace_int_data_in_filename(&filename, #if FF_API_HLS_WRAP - oc->filename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) { + oc->url, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) { #else - oc->filename, 'd', vs->sequence) < 1) { + oc->url, 'd', vs->sequence) < 1) { #endif av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_index flag\n", - filename); + oc->url); av_free(filename); return AVERROR(EINVAL); } - av_strlcpy(oc->filename, filename, sizeof(oc->filename)); - av_free(filename); + ff_format_set_url(oc, filename); } if (c->flags & (HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION)) { - av_strlcpy(vs->current_segment_final_filename_fmt, oc->filename, + av_strlcpy(vs->current_segment_final_filename_fmt, oc->url, sizeof(vs->current_segment_final_filename_fmt)); if (c->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) { char *filename = NULL; - if (replace_int_data_in_filename(&filename, oc->filename, 's', 0) < 1) { + if (replace_int_data_in_filename(&filename, oc->url, 's', 0) < 1) { av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_size flag\n", - filename); + oc->url); av_free(filename); return AVERROR(EINVAL); } - av_strlcpy(oc->filename, filename, sizeof(oc->filename)); - av_free(filename); + ff_format_set_url(oc, filename); } if (c->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) { char *filename = NULL; - if (replace_int_data_in_filename(&filename, oc->filename, 't', 0) < 1) { + if (replace_int_data_in_filename(&filename, oc->url, 't', 0) < 1) { av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_time flag\n", - filename); + oc->url); av_free(filename); return AVERROR(EINVAL); } - av_strlcpy(oc->filename, filename, sizeof(oc->filename)); - av_free(filename); + ff_format_set_url(oc, filename); } } return 0; @@ -960,10 +963,10 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, return ret; } - filename = av_basename(vs->avf->filename); + filename = av_basename(vs->avf->url); if (hls->use_localtime_mkdir) { - filename = vs->avf->filename; + filename = vs->avf->url; } if ((find_segment_by_filename(vs->segments, filename) || find_segment_by_filename(vs->old_segments, filename)) && !byterange_mode) { @@ -972,7 +975,7 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, av_strlcpy(en->filename, filename, sizeof(en->filename)); if(vs->has_subtitle) - av_strlcpy(en->sub_filename, av_basename(vs->vtt_avf->filename), sizeof(en->sub_filename)); + av_strlcpy(en->sub_filename, av_basename(vs->vtt_avf->url), sizeof(en->sub_filename)); else en->sub_filename[0] = '\0'; @@ -1098,10 +1101,15 @@ static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs continue; } else if (line[0]) { if (is_segment) { + char *new_file = av_strdup(line); + if (!new_file) { + ret = AVERROR(ENOMEM); + goto fail; + } + ff_format_set_url(vs->avf, new_file); is_segment = 0; new_start_pos = avio_tell(vs->avf->pb); vs->size = new_start_pos - vs->start_pos; - av_strlcpy(vs->avf->filename, line, sizeof(line)); ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size); if (ret < 0) goto fail; @@ -1126,15 +1134,19 @@ static void hls_free_segments(HLSSegment *p) } } -static void hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc) +static int hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc) { - size_t len = strlen(oc->filename); - char final_filename[sizeof(oc->filename)]; + size_t len = strlen(oc->url); + char *final_filename = av_strdup(oc->url); + int ret; - av_strlcpy(final_filename, oc->filename, len); + if (!final_filename) + return AVERROR(ENOMEM); final_filename[len-4] = '\0'; - ff_rename(oc->filename, final_filename, s); - oc->filename[len-4] = '\0'; + ret = ff_rename(oc->url, final_filename, s); + oc->url[len-4] = '\0'; + av_freep(&final_filename); + return ret; } static int get_relative_url(const char *master_url, const char *media_url, @@ -1322,7 +1334,7 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) int ret = 0; char temp_filename[1024]; int64_t sequence = FFMAX(hls->start_sequence, vs->sequence - vs->nb_entries); - const char *proto = avio_find_protocol_name(s->filename); + const char *proto = avio_find_protocol_name(s->url); int use_rename = proto && !strcmp(proto, "file"); static unsigned warned_non_file; char *key_uri = NULL; @@ -1441,11 +1453,16 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) int err = 0; if (c->flags & HLS_SINGLE_FILE) { - av_strlcpy(oc->filename, vs->basename, - sizeof(oc->filename)); - if (vs->vtt_basename) - av_strlcpy(vtt_oc->filename, vs->vtt_basename, - sizeof(vtt_oc->filename)); + char *new_name = av_strdup(vs->basename); + if (!new_name) + return AVERROR(ENOMEM); + ff_format_set_url(oc, new_name); + if (vs->vtt_basename) { + new_name = av_strdup(vs->vtt_basename); + if (!new_name) + return AVERROR(ENOMEM); + ff_format_set_url(vtt_oc, new_name); + } } else if (c->max_seg_size > 0) { char *filename = NULL; if (replace_int_data_in_filename(&filename, @@ -1458,15 +1475,19 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -use_localtime 1 with it\n", vs->basename); return AVERROR(EINVAL); } - av_strlcpy(oc->filename, filename, sizeof(oc->filename)); - av_free(filename); + ff_format_set_url(oc, filename); } else { if (c->use_localtime) { time_t now0; struct tm *tm, tmpbuf; + int bufsize = strlen(vs->basename) + 1024; + char *buf = av_mallocz(bufsize); + if (!buf) + return AVERROR(ENOMEM); time(&now0); tm = localtime_r(&now0, &tmpbuf); - if (!strftime(oc->filename, sizeof(oc->filename), vs->basename, tm)) { + ff_format_set_url(oc, buf); + if (!strftime(oc->url, bufsize, vs->basename, tm)) { av_log(oc, AV_LOG_ERROR, "Could not get segment filename with use_localtime\n"); return AVERROR(EINVAL); } @@ -1478,7 +1499,7 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) if (c->use_localtime_mkdir) { const char *dir; - char *fn_copy = av_strdup(oc->filename); + char *fn_copy = av_strdup(oc->url); if (!fn_copy) { return AVERROR(ENOMEM); } @@ -1502,8 +1523,7 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -use_localtime 1 with it\n", vs->basename); return AVERROR(EINVAL); } - av_strlcpy(oc->filename, filename, sizeof(oc->filename)); - av_free(filename); + ff_format_set_url(oc, filename); } if( vs->vtt_basename) { char *filename = NULL; @@ -1517,8 +1537,7 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", vs->vtt_basename); return AVERROR(EINVAL); } - av_strlcpy(vtt_oc->filename, filename, sizeof(vtt_oc->filename)); - av_free(filename); + ff_format_set_url(vtt_oc, filename); } } vs->number++; @@ -1526,7 +1545,10 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) set_http_options(s, &options, c); if (c->flags & HLS_TEMP_FILE) { - av_strlcat(oc->filename, ".tmp", sizeof(oc->filename)); + char *new_name = av_asprintf("%s.tmp", oc->url); + if (!new_name) + return AVERROR(ENOMEM); + ff_format_set_url(oc, new_name); } if (c->key_info_file || c->encrypt) { @@ -1554,7 +1576,7 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) if ((err = av_dict_set(&options, "encryption_iv", iv_string, 0)) < 0) goto fail; - filename = av_asprintf("crypto:%s", oc->filename); + filename = av_asprintf("crypto:%s", oc->url); if (!filename) { err = AVERROR(ENOMEM); goto fail; @@ -1565,12 +1587,12 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) if (err < 0) return err; } else if (c->segment_type != SEGMENT_TYPE_FMP4) { - if ((err = hlsenc_io_open(s, &oc->pb, oc->filename, &options)) < 0) + if ((err = hlsenc_io_open(s, &oc->pb, oc->url, &options)) < 0) goto fail; } if (vs->vtt_basename) { set_http_options(s, &options, c); - if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->filename, &options)) < 0) + if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->url, &options)) < 0) goto fail; } av_dict_free(&options); @@ -1964,7 +1986,7 @@ static int update_master_pl_info(AVFormatContext *s) { char *fn1= NULL, *fn2 = NULL; int ret = 0; - fn1 = av_strdup(s->filename); + fn1 = av_strdup(s->url); if (!fn1) { ret = AVERROR(ENOMEM); goto fail; @@ -2146,7 +2168,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) if (vs->packets_written && can_split && av_compare_ts(pkt->pts - vs->start_pts, st->time_base, end_pts, AV_TIME_BASE_Q) >= 0) { int64_t new_start_pos; - char *old_filename = av_strdup(vs->avf->filename); + char *old_filename = av_strdup(vs->avf->url); int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); if (!old_filename) { @@ -2171,13 +2193,13 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) hlsenc_io_close(s, &vs->out, vs->base_output_dirname); } } else { - hlsenc_io_close(s, &oc->pb, oc->filename); + hlsenc_io_close(s, &oc->pb, oc->url); } if (vs->vtt_avf) { - hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->filename); + hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->url); } } - if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) { + if ((hls->flags & HLS_TEMP_FILE) && oc->url[0]) { if (!(hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size <= 0)) if ((vs->avf->oformat->priv_class && vs->avf->priv_data) && hls->segment_type != SEGMENT_TYPE_FMP4) av_opt_set(vs->avf->priv_data, "mpegts_flags", "resend_headers", 0); @@ -2189,10 +2211,10 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) } if (hls->segment_type == SEGMENT_TYPE_FMP4) { - ret = hlsenc_io_open(s, &vs->out, vs->avf->filename, NULL); + ret = hlsenc_io_open(s, &vs->out, vs->avf->url, NULL); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", - vs->avf->filename); + vs->avf->url); av_free(old_filename); return ret; } @@ -2265,16 +2287,16 @@ static int hls_write_trailer(struct AVFormatContext *s) oc = vs->avf; vtt_oc = vs->vtt_avf; - old_filename = av_strdup(vs->avf->filename); + old_filename = av_strdup(vs->avf->url); if (!old_filename) { return AVERROR(ENOMEM); } if ( hls->segment_type == SEGMENT_TYPE_FMP4) { int range_length = 0; - ret = hlsenc_io_open(s, &vs->out, vs->avf->filename, NULL); + ret = hlsenc_io_open(s, &vs->out, vs->avf->url, NULL); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", vs->avf->filename); + av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", vs->avf->url); goto failed; } write_styp(vs->out); @@ -2292,7 +2314,7 @@ static int hls_write_trailer(struct AVFormatContext *s) if (hls->segment_type != SEGMENT_TYPE_FMP4) ff_format_io_close(s, &oc->pb); - if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) { + if ((hls->flags & HLS_TEMP_FILE) && oc->url[0]) { hls_rename_temp_file(s, oc); } @@ -2377,7 +2399,7 @@ static int hls_init(AVFormatContext *s) goto fail; } - ret = validate_name(hls->nb_varstreams, s->filename); + ret = validate_name(hls->nb_varstreams, s->url); if (ret < 0) goto fail; @@ -2432,12 +2454,12 @@ static int hls_init(AVFormatContext *s) for (i = 0; i < hls->nb_varstreams; i++) { vs = &hls->var_streams[i]; - vs->m3u8_name = av_strdup(s->filename); + vs->m3u8_name = av_strdup(s->url); if (!vs->m3u8_name ) { ret = AVERROR(ENOMEM); goto fail; } - ret = format_name(vs->m3u8_name, strlen(s->filename) + 1, i); + ret = format_name(vs->m3u8_name, strlen(s->url) + 1, i); if (ret < 0) goto fail; From 18ac64235939c4c5c7656546a9545f68339affbe Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Fri, 29 Dec 2017 23:30:14 +0100 Subject: [PATCH 1758/2557] avformat: migrate to AVFormatContext->url Signed-off-by: Marton Balint --- libavformat/concatdec.c | 4 ++-- libavformat/dashenc.c | 16 +++++++------- libavformat/fifo.c | 8 +++---- libavformat/flvenc.c | 4 ++-- libavformat/gxfenc.c | 4 ++-- libavformat/hdsenc.c | 24 ++++++++++----------- libavformat/img2dec.c | 4 ++-- libavformat/img2enc.c | 4 ++-- libavformat/matroskadec.c | 4 ++-- libavformat/mlvdec.c | 4 ++-- libavformat/mov.c | 2 +- libavformat/movenc.c | 10 ++++----- libavformat/mpeg.c | 4 ++-- libavformat/mpegtsenc.c | 2 +- libavformat/options.c | 2 +- libavformat/rtsp.c | 18 ++++++++++------ libavformat/rtspdec.c | 4 ++-- libavformat/rtspenc.c | 4 +++- libavformat/sapdec.c | 2 +- libavformat/sapenc.c | 10 +++++++-- libavformat/sdp.c | 4 ++-- libavformat/segment.c | 36 +++++++++++++++++++------------- libavformat/smoothstreamingenc.c | 12 +++++------ libavformat/tee.c | 4 ++-- libavformat/utils.c | 2 +- libavformat/webm_chunk.c | 10 ++++----- 26 files changed, 111 insertions(+), 91 deletions(-) diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index bd5174ada2540..178fac86cbff1 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -126,10 +126,10 @@ static int add_file(AVFormatContext *avf, char *filename, ConcatFile **rfile, url = filename; filename = NULL; } else { - url_len = strlen(avf->filename) + strlen(filename) + 16; + url_len = strlen(avf->url) + strlen(filename) + 16; if (!(url = av_malloc(url_len))) FAIL(AVERROR(ENOMEM)); - ff_make_absolute_url(url, url_len, avf->filename, filename); + ff_make_absolute_url(url, url_len, avf->url, filename); av_freep(&filename); } diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index d1e4d7466a419..0f6f4f22faf81 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -692,7 +692,7 @@ static int write_manifest(AVFormatContext *s, int final) AVIOContext *out; char temp_filename[1024]; int ret, i; - const char *proto = avio_find_protocol_name(s->filename); + const char *proto = avio_find_protocol_name(s->url); int use_rename = proto && !strcmp(proto, "file"); static unsigned int warned_non_file = 0; AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0); @@ -701,7 +701,7 @@ static int write_manifest(AVFormatContext *s, int final) if (!use_rename && !warned_non_file++) av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n"); - snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->filename); + snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->url); set_http_options(&opts, c); ret = dashenc_io_open(s, &c->mpd_out, temp_filename, &opts); if (ret < 0) { @@ -778,7 +778,7 @@ static int write_manifest(AVFormatContext *s, int final) dashenc_io_close(s, &c->mpd_out, temp_filename); if (use_rename) { - if ((ret = avpriv_io_move(temp_filename, s->filename)) < 0) + if ((ret = avpriv_io_move(temp_filename, s->url)) < 0) return ret; } @@ -859,14 +859,14 @@ static int dash_init(AVFormatContext *s) if (c->single_file) c->use_template = 0; - av_strlcpy(c->dirname, s->filename, sizeof(c->dirname)); + av_strlcpy(c->dirname, s->url, sizeof(c->dirname)); ptr = strrchr(c->dirname, '/'); if (ptr) { av_strlcpy(basename, &ptr[1], sizeof(basename)); ptr[1] = '\0'; } else { c->dirname[0] = '\0'; - av_strlcpy(basename, s->filename, sizeof(basename)); + av_strlcpy(basename, s->url, sizeof(basename)); } ptr = strrchr(basename, '.'); @@ -1025,7 +1025,7 @@ static int dash_write_header(AVFormatContext *s) } ret = write_manifest(s, 0); if (!ret) - av_log(s, AV_LOG_VERBOSE, "Manifest written to: %s\n", s->filename); + av_log(s, AV_LOG_VERBOSE, "Manifest written to: %s\n", s->url); return ret; } @@ -1124,7 +1124,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) DASHContext *c = s->priv_data; int i, ret = 0; - const char *proto = avio_find_protocol_name(s->filename); + const char *proto = avio_find_protocol_name(s->url); int use_rename = proto && !strcmp(proto, "file"); int cur_flush_segment_index = 0; @@ -1332,7 +1332,7 @@ static int dash_write_trailer(AVFormatContext *s) snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile); unlink(filename); } - unlink(s->filename); + unlink(s->url); } return 0; diff --git a/libavformat/fifo.c b/libavformat/fifo.c index c881f31e94f24..145e2e266047e 100644 --- a/libavformat/fifo.c +++ b/libavformat/fifo.c @@ -124,9 +124,9 @@ static int fifo_thread_write_header(FifoThreadContext *ctx) if (ret < 0) return ret; - ret = ff_format_output_open(avf2, avf->filename, &format_options); + ret = ff_format_output_open(avf2, avf->url, &format_options); if (ret < 0) { - av_log(avf, AV_LOG_ERROR, "Error opening %s: %s\n", avf->filename, + av_log(avf, AV_LOG_ERROR, "Error opening %s: %s\n", avf->url, av_err2str(ret)); goto end; } @@ -500,13 +500,13 @@ static int fifo_init(AVFormatContext *avf) } } - oformat = av_guess_format(fifo->format, avf->filename, NULL); + oformat = av_guess_format(fifo->format, avf->url, NULL); if (!oformat) { ret = AVERROR_MUXER_NOT_FOUND; return ret; } - ret = fifo_mux_init(avf, oformat, avf->filename); + ret = fifo_mux_init(avf, oformat, avf->url); if (ret < 0) return ret; diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 899b07ea7bef8..e8af48cb6415a 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -610,10 +610,10 @@ static int shift_data(AVFormatContext *s) * writing, so we re-open the same output, but for reading. It also avoids * a read/seek/write/seek back and forth. */ avio_flush(s->pb); - ret = s->io_open(s, &read_pb, s->filename, AVIO_FLAG_READ, NULL); + ret = s->io_open(s, &read_pb, s->url, AVIO_FLAG_READ, NULL); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for " - "the second pass (add_keyframe_index)\n", s->filename); + "the second pass (add_keyframe_index)\n", s->url); goto end; } diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c index 0e0772b744157..3507c00b40122 100644 --- a/libavformat/gxfenc.c +++ b/libavformat/gxfenc.c @@ -311,7 +311,7 @@ static int gxf_write_material_data_section(AVFormatContext *s) AVIOContext *pb = s->pb; int64_t pos; int len; - const char *filename = strrchr(s->filename, '/'); + const char *filename = strrchr(s->url, '/'); pos = avio_tell(pb); avio_wb16(pb, 0); /* size */ @@ -320,7 +320,7 @@ static int gxf_write_material_data_section(AVFormatContext *s) if (filename) filename++; else - filename = s->filename; + filename = s->url; len = strlen(filename); avio_w8(pb, MAT_NAME); diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c index 72829f7257a28..d82aee17b98e2 100644 --- a/libavformat/hdsenc.c +++ b/libavformat/hdsenc.c @@ -169,8 +169,8 @@ static int write_manifest(AVFormatContext *s, int final) if (c->nb_streams > 0) duration = c->streams[0].last_ts * av_q2d(s->streams[0]->time_base); - snprintf(filename, sizeof(filename), "%s/index.f4m", s->filename); - snprintf(temp_filename, sizeof(temp_filename), "%s/index.f4m.tmp", s->filename); + snprintf(filename, sizeof(filename), "%s/index.f4m", s->url); + snprintf(temp_filename, sizeof(temp_filename), "%s/index.f4m.tmp", s->url); ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename); @@ -178,7 +178,7 @@ static int write_manifest(AVFormatContext *s, int final) } avio_printf(out, "\n"); avio_printf(out, "\n"); - avio_printf(out, "\t%s\n", av_basename(s->filename)); + avio_printf(out, "\t%s\n", av_basename(s->url)); avio_printf(out, "\t%s\n", final ? "recorded" : "live"); avio_printf(out, "\tstreaming\n"); @@ -236,9 +236,9 @@ static int write_abst(AVFormatContext *s, OutputStream *os, int final) cur_media_time = os->fragments[os->nb_fragments - 1]->start_time; snprintf(filename, sizeof(filename), - "%s/stream%d.abst", s->filename, index); + "%s/stream%d.abst", s->url, index); snprintf(temp_filename, sizeof(temp_filename), - "%s/stream%d.abst.tmp", s->filename, index); + "%s/stream%d.abst.tmp", s->url, index); ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename); @@ -317,9 +317,9 @@ static int hds_write_header(AVFormatContext *s) int ret = 0, i; AVOutputFormat *oformat; - if (mkdir(s->filename, 0777) == -1 && errno != EEXIST) { + if (mkdir(s->url, 0777) == -1 && errno != EEXIST) { ret = AVERROR(errno); - av_log(s, AV_LOG_ERROR , "Failed to create directory %s\n", s->filename); + av_log(s, AV_LOG_ERROR , "Failed to create directory %s\n", s->url); goto fail; } @@ -412,7 +412,7 @@ static int hds_write_header(AVFormatContext *s) s->streams[os->first_stream + j]->time_base = os->ctx->streams[j]->time_base; snprintf(os->temp_filename, sizeof(os->temp_filename), - "%s/stream%d_temp", s->filename, i); + "%s/stream%d_temp", s->url, i); ret = init_file(s, os, 0); if (ret < 0) goto fail; @@ -476,7 +476,7 @@ static int hds_flush(AVFormatContext *s, OutputStream *os, int final, close_file(s, os); snprintf(target_filename, sizeof(target_filename), - "%s/stream%dSeg1-Frag%d", s->filename, index, os->fragment_index); + "%s/stream%dSeg1-Frag%d", s->url, index, os->fragment_index); ret = ff_rename(os->temp_filename, target_filename, s); if (ret < 0) return ret; @@ -549,13 +549,13 @@ static int hds_write_trailer(AVFormatContext *s) if (c->remove_at_exit) { char filename[1024]; - snprintf(filename, sizeof(filename), "%s/index.f4m", s->filename); + snprintf(filename, sizeof(filename), "%s/index.f4m", s->url); unlink(filename); for (i = 0; i < c->nb_streams; i++) { - snprintf(filename, sizeof(filename), "%s/stream%d.abst", s->filename, i); + snprintf(filename, sizeof(filename), "%s/stream%d.abst", s->url, i); unlink(filename); } - rmdir(s->filename); + rmdir(s->url); } hds_free(s); diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c index ecf64eaffaed2..62db0d92cf3e2 100644 --- a/libavformat/img2dec.c +++ b/libavformat/img2dec.c @@ -198,7 +198,7 @@ int ff_img_read_header(AVFormatContext *s1) return AVERROR(EINVAL); } - av_strlcpy(s->path, s1->filename, sizeof(s->path)); + av_strlcpy(s->path, s1->url, sizeof(s->path)); s->img_number = 0; s->img_count = 0; @@ -338,7 +338,7 @@ int ff_img_read_header(AVFormatContext *s1) pd.buf = probe_buffer; pd.buf_size = probe_buffer_size; - pd.filename = s1->filename; + pd.filename = s1->url; while ((fmt = av_iformat_next(fmt))) { if (fmt->read_header != ff_img_read_header || diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index b680676bff7b4..a09cc8ec501e5 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -53,7 +53,7 @@ static int write_header(AVFormatContext *s) AVStream *st = s->streams[0]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(st->codecpar->format); - av_strlcpy(img->path, s->filename, sizeof(img->path)); + av_strlcpy(img->path, s->url, sizeof(img->path)); /* find format */ if (s->oformat->flags & AVFMT_NOFILE) @@ -156,7 +156,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) av_assert0(!img->split_planes); - ret = avformat_alloc_output_context2(&fmt, NULL, img->muxer, s->filename); + ret = avformat_alloc_output_context2(&fmt, NULL, img->muxer, s->url); if (ret < 0) return ret; st = avformat_new_stream(fmt, NULL); diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 158ce7ae1fa39..a45fe0974361f 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -3953,8 +3953,8 @@ static int webm_dash_manifest_read_header(AVFormatContext *s) } // basename of the file - buf = strrchr(s->filename, '/'); - av_dict_set(&s->streams[0]->metadata, FILENAME, buf ? ++buf : s->filename, 0); + buf = strrchr(s->url, '/'); + av_dict_set(&s->streams[0]->metadata, FILENAME, buf ? ++buf : s->url, 0); // track number tracks = matroska->tracks.elem; diff --git a/libavformat/mlvdec.c b/libavformat/mlvdec.c index 319cd26de4f00..d387c871ee953 100644 --- a/libavformat/mlvdec.c +++ b/libavformat/mlvdec.c @@ -342,9 +342,9 @@ static int read_header(AVFormatContext *avctx) return ret; /* scan secondary files */ - if (strlen(avctx->filename) > 2) { + if (strlen(avctx->url) > 2) { int i; - char *filename = av_strdup(avctx->filename); + char *filename = av_strdup(avctx->url); if (!filename) return AVERROR(ENOMEM); diff --git a/libavformat/mov.c b/libavformat/mov.c index 22faecfc1774d..d16b431e039cc 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4115,7 +4115,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) { MOVDref *dref = &sc->drefs[sc->dref_id - 1]; if (c->enable_drefs) { - if (mov_open_dref(c, &sc->pb, c->fc->filename, dref) < 0) + if (mov_open_dref(c, &sc->pb, c->fc->url, dref) < 0) av_log(c->fc, AV_LOG_ERROR, "stream %d, error opening alias: path='%s', dir='%s', " "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n", diff --git a/libavformat/movenc.c b/libavformat/movenc.c index a597b0853d86c..f7079f3df7456 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1556,9 +1556,9 @@ static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track) else if (track->mode == MODE_ISM) tag = track->par->codec_tag; else if (track->mode == MODE_IPOD) { - if (!av_match_ext(s->filename, "m4a") && - !av_match_ext(s->filename, "m4v") && - !av_match_ext(s->filename, "m4b")) + if (!av_match_ext(s->url, "m4a") && + !av_match_ext(s->url, "m4v") && + !av_match_ext(s->url, "m4b")) av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v " "Quicktime/Ipod might not play the file\n"); tag = track->par->codec_tag; @@ -6400,10 +6400,10 @@ static int shift_data(AVFormatContext *s) * writing, so we re-open the same output, but for reading. It also avoids * a read/seek/write/seek back and forth. */ avio_flush(s->pb); - ret = s->io_open(s, &read_pb, s->filename, AVIO_FLAG_READ, NULL); + ret = s->io_open(s, &read_pb, s->url, AVIO_FLAG_READ, NULL); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for " - "the second pass (faststart)\n", s->filename); + "the second pass (faststart)\n", s->url); goto end; } diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index 50fe7a1a76873..abdc6a937cb9e 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -703,7 +703,7 @@ static int vobsub_read_header(AVFormatContext *s) if (!vobsub->sub_name) { char *ext; - vobsub->sub_name = av_strdup(s->filename); + vobsub->sub_name = av_strdup(s->url); if (!vobsub->sub_name) { ret = AVERROR(ENOMEM); goto end; @@ -718,7 +718,7 @@ static int vobsub_read_header(AVFormatContext *s) goto end; } memcpy(ext, !strncmp(ext, "IDX", 3) ? "SUB" : "sub", 3); - av_log(s, AV_LOG_VERBOSE, "IDX/SUB: %s -> %s\n", s->filename, vobsub->sub_name); + av_log(s, AV_LOG_VERBOSE, "IDX/SUB: %s -> %s\n", s->url, vobsub->sub_name); } if (!(iformat = av_find_input_format("mpeg"))) { diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index fdfa544ee26f4..8b0736ac4e36f 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -1012,7 +1012,7 @@ static int mpegts_init(AVFormatContext *s) ts->sdt_packet_period, ts->pat_packet_period); if (ts->m2ts_mode == -1) { - if (av_match_ext(s->filename, "m2ts")) { + if (av_match_ext(s->url, "m2ts")) { ts->m2ts_mode = 1; } else { ts->m2ts_mode = 0; diff --git a/libavformat/options.c b/libavformat/options.c index 9371c72667479..c188c23506a20 100644 --- a/libavformat/options.c +++ b/libavformat/options.c @@ -104,7 +104,7 @@ static int io_open_default(AVFormatContext *s, AVIOContext **pb, { int loglevel; - if (!strcmp(url, s->filename) || + if (!strcmp(url, s->url) || s->iformat && !strcmp(s->iformat->name, "image2") || s->oformat && !strcmp(s->oformat->name, "image2") ) { diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index cf7cdb2f2b6e3..89fc1e293c810 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1686,7 +1686,7 @@ int ff_rtsp_connect(AVFormatContext *s) redirect: /* extract hostname and port */ av_url_split(proto, sizeof(proto), auth, sizeof(auth), - host, sizeof(host), &port, path, sizeof(path), s->filename); + host, sizeof(host), &port, path, sizeof(path), s->url); if (!strcmp(proto, "rtsps")) { lower_rtsp_proto = "tls"; @@ -1717,7 +1717,7 @@ int ff_rtsp_connect(AVFormatContext *s) } } - /* Construct the URI used in request; this is similar to s->filename, + /* Construct the URI used in request; this is similar to s->url, * but with authentication credentials removed and RTSP specific options * stripped out. */ ff_url_join(rt->control_uri, sizeof(rt->control_uri), proto, NULL, @@ -1905,13 +1905,19 @@ int ff_rtsp_connect(AVFormatContext *s) ff_rtsp_close_streams(s); ff_rtsp_close_connections(s); if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) { - av_strlcpy(s->filename, reply->location, sizeof(s->filename)); + char *new_url = av_strdup(reply->location); + if (!new_url) { + err = AVERROR(ENOMEM); + goto fail2; + } + ff_format_set_url(s, new_url); rt->session_id[0] = '\0'; av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n", reply->status_code, - s->filename); + s->url); goto redirect; } + fail2: ff_network_close(); return err; } @@ -2425,7 +2431,7 @@ static int rtp_read_header(AVFormatContext *s) if (!ff_network_init()) return AVERROR(EIO); - ret = ffurl_open_whitelist(&in, s->filename, AVIO_FLAG_READ, + ret = ffurl_open_whitelist(&in, s->url, AVIO_FLAG_READ, &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist, NULL); if (ret) goto fail; @@ -2476,7 +2482,7 @@ static int rtp_read_header(AVFormatContext *s) } av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, - NULL, 0, s->filename); + NULL, 0, s->url); snprintf(sdp, sizeof(sdp), "v=0\r\nc=IN IP%d %s\r\nm=%s %d RTP/AVP %d\r\n", diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index fdf75a0979f15..32dff2319c51f 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -644,7 +644,7 @@ static int rtsp_listen(AVFormatContext *s) /* extract hostname and port */ av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host), - &port, path, sizeof(path), s->filename); + &port, path, sizeof(path), s->url); /* ff_url_join. No authorization by now (NULL) */ ff_url_join(rt->control_uri, sizeof(rt->control_uri), proto, NULL, host, @@ -804,7 +804,7 @@ static int resetup_tcp(AVFormatContext *s) int port; av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0, - s->filename); + s->url); ff_rtsp_undo_setup(s, 0); return ff_rtsp_make_setup_request(s, host, port, RTSP_LOWER_TRANSPORT_TCP, rt->real_challenge); diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c index e7707bb5fb4ac..97e3ef6da3c1f 100644 --- a/libavformat/rtspenc.c +++ b/libavformat/rtspenc.c @@ -50,6 +50,7 @@ int ff_rtsp_setup_output_streams(AVFormatContext *s, const char *addr) int i; char *sdp; AVFormatContext sdp_ctx, *ctx_array[1]; + char url[1024]; if (s->start_time_realtime == 0 || s->start_time_realtime == AV_NOPTS_VALUE) s->start_time_realtime = av_gettime(); @@ -71,7 +72,8 @@ int ff_rtsp_setup_output_streams(AVFormatContext *s, const char *addr) * flexible SDP creation interface. */ sdp_ctx = *s; - ff_url_join(sdp_ctx.filename, sizeof(sdp_ctx.filename), + sdp_ctx.url = url; + ff_url_join(url, sizeof(url), "rtsp", NULL, addr, -1, NULL); ctx_array[0] = &sdp_ctx; if (av_sdp_create(ctx_array, 1, sdp, SDP_MAX_SIZE)) { diff --git a/libavformat/sapdec.c b/libavformat/sapdec.c index 522b38d10a215..7a6c8bf1761e5 100644 --- a/libavformat/sapdec.c +++ b/libavformat/sapdec.c @@ -74,7 +74,7 @@ static int sap_read_header(AVFormatContext *s) return AVERROR(EIO); av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, - path, sizeof(path), s->filename); + path, sizeof(path), s->url); if (port < 0) port = 9875; diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c index 3098e340ca94a..f9afab0c33eb4 100644 --- a/libavformat/sapenc.c +++ b/libavformat/sapenc.c @@ -84,7 +84,7 @@ static int sap_write_header(AVFormatContext *s) /* extract hostname and port */ av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &base_port, - path, sizeof(path), s->filename); + path, sizeof(path), s->url); if (base_port < 0) base_port = 5004; @@ -144,6 +144,7 @@ static int sap_write_header(AVFormatContext *s) s->start_time_realtime = av_gettime(); for (i = 0; i < s->nb_streams; i++) { URLContext *fd; + char *new_url; ff_url_join(url, sizeof(url), "rtp", NULL, host, base_port, "?ttl=%d", ttl); @@ -161,7 +162,12 @@ static int sap_write_header(AVFormatContext *s) goto fail; s->streams[i]->priv_data = contexts[i]; s->streams[i]->time_base = contexts[i]->streams[0]->time_base; - av_strlcpy(contexts[i]->filename, url, sizeof(contexts[i]->filename)); + new_url = av_strdup(url); + if (!new_url) { + ret = AVERROR(ENOMEM); + goto fail; + } + ff_format_set_url(contexts[i], new_url); } if (s->nb_streams > 0 && title) diff --git a/libavformat/sdp.c b/libavformat/sdp.c index e7149167a1404..a5d202e99cb28 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -784,7 +784,7 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) port = 0; ttl = 0; if (n_files == 1) { - port = sdp_get_address(dst, sizeof(dst), &ttl, ac[0]->filename); + port = sdp_get_address(dst, sizeof(dst), &ttl, ac[0]->url ? ac[0]->url : ""); is_multicast = resolve_destination(dst, sizeof(dst), dst_type, sizeof(dst_type)); if (!is_multicast) @@ -804,7 +804,7 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) dst[0] = 0; for (i = 0; i < n_files; i++) { if (n_files != 1) { - port = sdp_get_address(dst, sizeof(dst), &ttl, ac[i]->filename); + port = sdp_get_address(dst, sizeof(dst), &ttl, ac[i]->url ? ac[i]->url : ""); is_multicast = resolve_destination(dst, sizeof(dst), dst_type, sizeof(dst_type)); if (!is_multicast) diff --git a/libavformat/segment.c b/libavformat/segment.c index 81d3f1d9408bc..8da4fca512d1a 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -192,6 +192,8 @@ static int set_segment_filename(AVFormatContext *s) AVFormatContext *oc = seg->avf; size_t size; int ret; + char buf[1024]; + char *new_name; if (seg->segment_idx_wrap) seg->segment_idx %= seg->segment_idx_wrap; @@ -200,18 +202,22 @@ static int set_segment_filename(AVFormatContext *s) struct tm *tm, tmpbuf; time(&now0); tm = localtime_r(&now0, &tmpbuf); - if (!strftime(oc->filename, sizeof(oc->filename), s->filename, tm)) { + if (!strftime(buf, sizeof(buf), s->url, tm)) { av_log(oc, AV_LOG_ERROR, "Could not get segment filename with strftime\n"); return AVERROR(EINVAL); } - } else if (av_get_frame_filename(oc->filename, sizeof(oc->filename), - s->filename, seg->segment_idx) < 0) { - av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", s->filename); + } else if (av_get_frame_filename(buf, sizeof(buf), + s->url, seg->segment_idx) < 0) { + av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", s->url); return AVERROR(EINVAL); } + new_name = av_strdup(buf); + if (!new_name) + return AVERROR(ENOMEM); + ff_format_set_url(oc, new_name); /* copy modified name in list entry */ - size = strlen(av_basename(oc->filename)) + 1; + size = strlen(av_basename(oc->url)) + 1; if (seg->entry_prefix) size += strlen(seg->entry_prefix); @@ -219,7 +225,7 @@ static int set_segment_filename(AVFormatContext *s) return ret; snprintf(seg->cur_entry.filename, size, "%s%s", seg->entry_prefix ? seg->entry_prefix : "", - av_basename(oc->filename)); + av_basename(oc->url)); return 0; } @@ -245,8 +251,8 @@ static int segment_start(AVFormatContext *s, int write_header) if ((err = set_segment_filename(s)) < 0) return err; - if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0) { - av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename); + if ((err = s->io_open(s, &oc->pb, oc->url, AVIO_FLAG_WRITE, NULL)) < 0) { + av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->url); return err; } if (!seg->individual_header_trailer) @@ -360,7 +366,7 @@ static int segment_end(AVFormatContext *s, int write_trailer, int is_last) if (ret < 0) av_log(s, AV_LOG_ERROR, "Failure occurred when ending segment '%s'\n", - oc->filename); + oc->url); if (seg->list) { if (seg->list_size || seg->list_type == LIST_TYPE_M3U8) { @@ -403,7 +409,7 @@ static int segment_end(AVFormatContext *s, int write_trailer, int is_last) } av_log(s, AV_LOG_VERBOSE, "segment:'%s' count:%d ended\n", - seg->avf->filename, seg->segment_count); + seg->avf->url, seg->segment_count); seg->segment_count++; if (seg->increment_tc) { @@ -726,7 +732,7 @@ static int seg_init(AVFormatContext *s) seg->reference_stream_index, av_get_media_type_string(s->streams[seg->reference_stream_index]->codecpar->codec_type)); - seg->oformat = av_guess_format(seg->format, s->filename, NULL); + seg->oformat = av_guess_format(seg->format, s->url, NULL); if (!seg->oformat) return AVERROR_MUXER_NOT_FOUND; @@ -745,9 +751,9 @@ static int seg_init(AVFormatContext *s) if (seg->write_header_trailer) { if ((ret = s->io_open(s, &oc->pb, - seg->header_filename ? seg->header_filename : oc->filename, + seg->header_filename ? seg->header_filename : oc->url, AVIO_FLAG_WRITE, NULL)) < 0) { - av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename); + av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->url); return ret; } if (!seg->individual_header_trailer) @@ -830,7 +836,7 @@ static int seg_write_header(AVFormatContext *s) } else { close_null_ctxp(&oc->pb); } - if ((ret = oc->io_open(oc, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0) + if ((ret = oc->io_open(oc, &oc->pb, oc->url, AVIO_FLAG_WRITE, NULL)) < 0) return ret; if (!seg->individual_header_trailer) oc->pb->seekable = 0; @@ -917,7 +923,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) if (seg->segment_frame_count == 0) { av_log(s, AV_LOG_VERBOSE, "segment:'%s' starts with packet stream:%d pts:%s pts_time:%s frame:%d\n", - seg->avf->filename, pkt->stream_index, + seg->avf->url, pkt->stream_index, av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), seg->frame_count); } diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c index 54a1c49caae69..094712af27dd6 100644 --- a/libavformat/smoothstreamingenc.c +++ b/libavformat/smoothstreamingenc.c @@ -221,8 +221,8 @@ static int write_manifest(AVFormatContext *s, int final) int ret, i, video_chunks = 0, audio_chunks = 0, video_streams = 0, audio_streams = 0; int64_t duration = 0; - snprintf(filename, sizeof(filename), "%s/Manifest", s->filename); - snprintf(temp_filename, sizeof(temp_filename), "%s/Manifest.tmp", s->filename); + snprintf(filename, sizeof(filename), "%s/Manifest", s->url); + snprintf(temp_filename, sizeof(temp_filename), "%s/Manifest.tmp", s->url); ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename); @@ -295,7 +295,7 @@ static int ism_write_header(AVFormatContext *s) int ret = 0, i; AVOutputFormat *oformat; - if (mkdir(s->filename, 0777) == -1 && errno != EEXIST) { + if (mkdir(s->url, 0777) == -1 && errno != EEXIST) { ret = AVERROR(errno); av_log(s, AV_LOG_ERROR, "mkdir failed\n"); goto fail; @@ -324,7 +324,7 @@ static int ism_write_header(AVFormatContext *s) ret = AVERROR(EINVAL); goto fail; } - snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%"PRId64")", s->filename, s->streams[i]->codecpar->bit_rate); + snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%"PRId64")", s->url, s->streams[i]->codecpar->bit_rate); if (mkdir(os->dirname, 0777) == -1 && errno != EEXIST) { ret = AVERROR(errno); av_log(s, AV_LOG_ERROR, "mkdir failed\n"); @@ -609,9 +609,9 @@ static int ism_write_trailer(AVFormatContext *s) if (c->remove_at_exit) { char filename[1024]; - snprintf(filename, sizeof(filename), "%s/Manifest", s->filename); + snprintf(filename, sizeof(filename), "%s/Manifest", s->url); unlink(filename); - rmdir(s->filename); + rmdir(s->url); } ism_free(s); diff --git a/libavformat/tee.c b/libavformat/tee.c index dd1844ac0e162..ef3b113a47180 100644 --- a/libavformat/tee.c +++ b/libavformat/tee.c @@ -406,7 +406,7 @@ static void log_slave(TeeSlave *slave, void *log_ctx, int log_level) { int i; av_log(log_ctx, log_level, "filename:'%s' format:%s\n", - slave->avf->filename, slave->avf->oformat->name); + slave->avf->url, slave->avf->oformat->name); for (i = 0; i < slave->avf->nb_streams; i++) { AVStream *st = slave->avf->streams[i]; AVBSFContext *bsf = slave->bsfs[i]; @@ -448,7 +448,7 @@ static int tee_write_header(AVFormatContext *avf) { TeeContext *tee = avf->priv_data; unsigned nb_slaves = 0, i; - const char *filename = avf->filename; + const char *filename = avf->url; char **slaves = NULL; int ret; diff --git a/libavformat/utils.c b/libavformat/utils.c index 74e615f86ec80..0d722c69c82d2 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2061,7 +2061,7 @@ void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance) int64_t pos_delta = 0; int64_t skip = 0; //We could use URLProtocol flags here but as many user applications do not use URLProtocols this would be unreliable - const char *proto = avio_find_protocol_name(s->filename); + const char *proto = avio_find_protocol_name(s->url); if (!proto) { av_log(s, AV_LOG_INFO, diff --git a/libavformat/webm_chunk.c b/libavformat/webm_chunk.c index f8dbaa3339506..549ec2879a5ef 100644 --- a/libavformat/webm_chunk.c +++ b/libavformat/webm_chunk.c @@ -99,8 +99,8 @@ static int get_chunk_filename(AVFormatContext *s, int is_header, char *filename) av_strlcpy(filename, wc->header_filename, strlen(wc->header_filename) + 1); } else { if (av_get_frame_filename(filename, MAX_FILENAME_SIZE, - s->filename, wc->chunk_index - 1) < 0) { - av_log(oc, AV_LOG_ERROR, "Invalid chunk filename template '%s'\n", s->filename); + s->url, wc->chunk_index - 1) < 0) { + av_log(oc, AV_LOG_ERROR, "Invalid chunk filename template '%s'\n", s->url); return AVERROR(EINVAL); } } @@ -119,7 +119,7 @@ static int webm_chunk_write_header(AVFormatContext *s) if (s->nb_streams != 1) { return AVERROR_INVALIDDATA; } wc->chunk_index = wc->chunk_start_index; - wc->oformat = av_guess_format("webm", s->filename, "video/webm"); + wc->oformat = av_guess_format("webm", s->url, "video/webm"); if (!wc->oformat) return AVERROR_MUXER_NOT_FOUND; @@ -127,12 +127,12 @@ static int webm_chunk_write_header(AVFormatContext *s) if (ret < 0) return ret; oc = wc->avf; - ret = get_chunk_filename(s, 1, oc->filename); + ret = get_chunk_filename(s, 1, oc->url); if (ret < 0) return ret; if (wc->http_method) av_dict_set(&options, "method", wc->http_method, 0); - ret = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, &options); + ret = s->io_open(s, &oc->pb, oc->url, AVIO_FLAG_WRITE, &options); av_dict_free(&options); if (ret < 0) return ret; From fa8308d3d4f27d6fb38ac2069887a7b259f1c6ab Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Fri, 29 Dec 2017 01:19:37 +0100 Subject: [PATCH 1759/2557] avformat: deprecate AVFormatContext filename field Signed-off-by: Marton Balint --- doc/APIchanges | 4 ++++ libavformat/avformat.h | 5 +++++ libavformat/mux.c | 10 ++++++++++ libavformat/utils.c | 8 ++++++++ libavformat/version.h | 3 +++ 5 files changed, 30 insertions(+) diff --git a/doc/APIchanges b/doc/APIchanges index 878429848d050..6185545d56c3b 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-01-xx - xxxxxxx - lavf 58.7.100 - avformat.h + Deprecate AVFormatContext filename field which had limited length, use the + new dynamically allocated url field instead. + 2018-01-xx - xxxxxxx - lavf 58.7.100 - avformat.h Add url field to AVFormatContext and add ff_format_set_url helper function. diff --git a/libavformat/avformat.h b/libavformat/avformat.h index d1bd4902d0a2e..82f98453375ed 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1394,13 +1394,18 @@ typedef struct AVFormatContext { */ AVStream **streams; +#if FF_API_FORMAT_FILENAME /** * input or output filename * * - demuxing: set by avformat_open_input() * - muxing: may be set by the caller before avformat_write_header() + * + * @deprecated Use url instead. */ + attribute_deprecated char filename[1024]; +#endif /** * input or output URL. Unlike the old filename field, this field has no diff --git a/libavformat/mux.c b/libavformat/mux.c index de63f2ca25326..a13f0e3a1b8a7 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -187,7 +187,11 @@ int avformat_alloc_output_context2(AVFormatContext **avctx, AVOutputFormat *ofor s->priv_data = NULL; if (filename) { +#if FF_API_FORMAT_FILENAME +FF_DISABLE_DEPRECATION_WARNINGS av_strlcpy(s->filename, filename, sizeof(s->filename)); +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (!(s->url = av_strdup(filename))) goto nomem; @@ -255,7 +259,13 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) (ret = av_opt_set_dict2(s->priv_data, &tmp, AV_OPT_SEARCH_CHILDREN)) < 0) goto fail; +#if FF_API_FORMAT_FILENAME +FF_DISABLE_DEPRECATION_WARNINGS if (!s->url && !(s->url = av_strdup(s->filename))) { +FF_ENABLE_DEPRECATION_WARNINGS +#else + if (!s->url && !(s->url = av_strdup(""))) { +#endif ret = AVERROR(ENOMEM); goto fail; } diff --git a/libavformat/utils.c b/libavformat/utils.c index 0d722c69c82d2..28ea0714091c6 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -560,7 +560,11 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, goto fail; } +#if FF_API_FORMAT_FILENAME +FF_DISABLE_DEPRECATION_WARNINGS av_strlcpy(s->filename, filename ? filename : "", sizeof(s->filename)); +FF_ENABLE_DEPRECATION_WARNINGS +#endif if ((ret = init_input(s, filename, &tmp)) < 0) goto fail; s->probe_score = ret; @@ -5648,5 +5652,9 @@ void ff_format_set_url(AVFormatContext *s, char *url) av_assert0(url); av_freep(&s->url); s->url = url; +#if FF_API_FORMAT_FILENAME +FF_DISABLE_DEPRECATION_WARNINGS av_strlcpy(s->filename, url, sizeof(s->filename)); +FF_ENABLE_DEPRECATION_WARNINGS +#endif } diff --git a/libavformat/version.h b/libavformat/version.h index c375b0da15729..897be0c2fe9e2 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -85,6 +85,9 @@ #ifndef FF_API_LAVF_FFSERVER #define FF_API_LAVF_FFSERVER (LIBAVFORMAT_VERSION_MAJOR < 59) #endif +#ifndef FF_API_FORMAT_FILENAME +#define FF_API_FORMAT_FILENAME (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif #ifndef FF_API_R_FRAME_RATE From 4e3e8980b58fc22eb41c0e3cd3392bb4e6ca0184 Mon Sep 17 00:00:00 2001 From: Brendan McGrath Date: Mon, 29 Jan 2018 10:46:50 +0800 Subject: [PATCH 1760/2557] dashdec: Fix segfault on decoding segment timeline If first_seq_no is not within the bounds of timelines then a segfault will occur. This patch removes the use of first_seq_no within the timelines array It also adds first_seq_no to the value returned by calc_next_seg_no_from_timelines (which allows for different values of 'startNumber') Signed-off-by: Brendan McGrath --- libavformat/dashdec.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index f4cbb065e919f..f9dc03309798b 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -1257,15 +1257,12 @@ static int64_t calc_cur_seg_no(AVFormatContext *s, struct representation *pls) if (pls->n_fragments) { num = pls->first_seq_no; } else if (pls->n_timelines) { - start_time_offset = get_segment_start_time_based_on_timeline(pls, 0xFFFFFFFF) - pls->timelines[pls->first_seq_no]->starttime; // total duration of playlist - if (start_time_offset < 60 * pls->fragment_timescale) - start_time_offset = 0; - else - start_time_offset = start_time_offset - 60 * pls->fragment_timescale; - - num = calc_next_seg_no_from_timelines(pls, pls->timelines[pls->first_seq_no]->starttime + start_time_offset); + start_time_offset = get_segment_start_time_based_on_timeline(pls, 0xFFFFFFFF) - 60 * pls->fragment_timescale; // 60 seconds before end + num = calc_next_seg_no_from_timelines(pls, start_time_offset); if (num == -1) num = pls->first_seq_no; + else + num += pls->first_seq_no; } else if (pls->fragment_duration){ if (pls->presentation_timeoffset) { num = pls->presentation_timeoffset * pls->fragment_timescale / pls->fragment_duration; From 05f4703a168a336363750e32bcfdd6f303fbdbc3 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 28 Jan 2018 02:29:00 +0100 Subject: [PATCH 1761/2557] avcodec/mpeg4videodec: Check mb_num also against 0 The spec implies that 0 is invalid in addition to the existing checks Found-by: Reviewed-by: Kieran Kunhya Signed-off-by: Michael Niedermayer --- libavcodec/mpeg4videodec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 12755b5e8a40f..ba332de5311d3 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -465,7 +465,7 @@ int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx) } mb_num = get_bits(&s->gb, mb_num_bits); - if (mb_num >= s->mb_num) { + if (mb_num >= s->mb_num || !mb_num) { av_log(s->avctx, AV_LOG_ERROR, "illegal mb_num in video packet (%d %d) \n", mb_num, s->mb_num); return -1; From 4a94ff4ccd4f2329c599e37cabe4152dae60359e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 28 Jan 2018 02:29:01 +0100 Subject: [PATCH 1762/2557] avcodec/get_bits: Document the return code of get_vlc2() Found-by: kierank Reviewed-by: Kieran Kunhya Signed-off-by: Michael Niedermayer --- libavcodec/get_bits.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index c530015169e1c..0c7f5ff0c6011 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -550,6 +550,7 @@ static inline const uint8_t *align_get_bits(GetBitContext *s) * @param max_depth is the number of times bits bits must be read to completely * read the longest vlc code * = (max_vlc_length + bits - 1) / bits + * @returns the code parsed or -1 if no vlc matches */ static av_always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2], int bits, int max_depth) From d4967c04e040b3b2f937cad88599af825147ec94 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 28 Jan 2018 02:29:02 +0100 Subject: [PATCH 1763/2557] avcodec/mpeg4videodec: Avoid possibly aliasing violating casts Found-by: kierank Reviewed-by: Kieran Kunhya Signed-off-by: Michael Niedermayer --- libavcodec/mpeg4videodec.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index ba332de5311d3..756753e2fc1f2 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -1256,10 +1256,12 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, */ static int mpeg4_decode_partitioned_mb(MpegEncContext *s, int16_t block[6][64]) { - Mpeg4DecContext *ctx = (Mpeg4DecContext *)s; + Mpeg4DecContext *ctx = s->avctx->priv_data; int cbp, mb_type; const int xy = s->mb_x + s->mb_y * s->mb_stride; + av_assert2(s == (void*)ctx); + mb_type = s->current_picture.mb_type[xy]; cbp = s->cbp_table[xy]; @@ -1341,12 +1343,13 @@ static int mpeg4_decode_partitioned_mb(MpegEncContext *s, int16_t block[6][64]) static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) { - Mpeg4DecContext *ctx = (Mpeg4DecContext *)s; + Mpeg4DecContext *ctx = s->avctx->priv_data; int cbpc, cbpy, i, cbp, pred_x, pred_y, mx, my, dquant; int16_t *mot_val; static const int8_t quant_tab[4] = { -1, -2, 1, 2 }; const int xy = s->mb_x + s->mb_y * s->mb_stride; + av_assert2(s == (void*)ctx); av_assert2(s->h263_pred); if (s->pict_type == AV_PICTURE_TYPE_P || From 63b5d04e331c2580726e8a6936fecc04b815c516 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 29 Jan 2018 22:59:52 -0300 Subject: [PATCH 1764/2557] avformat/matroskadec: force full frame parsing of MLP/TrueHD streams There's at least one known file with a TrueHD stream that hasn't been correctly muxed, and requires full frame parsing and repack. Signed-off-by: James Almer --- libavformat/matroskadec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index a45fe0974361f..cda8df221344b 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -2521,7 +2521,9 @@ static int matroska_parse_tracks(AVFormatContext *s) st->codecpar->channels = track->audio.channels; if (!st->codecpar->bits_per_coded_sample) st->codecpar->bits_per_coded_sample = track->audio.bitdepth; - if (st->codecpar->codec_id == AV_CODEC_ID_MP3) + if (st->codecpar->codec_id == AV_CODEC_ID_MP3 || + st->codecpar->codec_id == AV_CODEC_ID_MLP || + st->codecpar->codec_id == AV_CODEC_ID_TRUEHD) st->need_parsing = AVSTREAM_PARSE_FULL; else if (st->codecpar->codec_id != AV_CODEC_ID_AAC) st->need_parsing = AVSTREAM_PARSE_HEADERS; From 55ebf707d0abf720a2b02fc5ebc47eb742bfbe99 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 19 Jan 2018 15:52:21 -0300 Subject: [PATCH 1765/2557] avcodec/mlp_parser: don't try to combine frames when full frames are provided Attempting full frame reconstruction is unnecessary for non raw containers, so just skip it altogether. Signed-off-by: James Almer --- libavcodec/mlp_parser.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index 3c0330f777c2c..4827354f18942 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -256,6 +256,9 @@ static int mlp_parse(AVCodecParserContext *s, if (buf_size == 0) return 0; + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { if (!mp->in_sync) { // Not in sync - find a major sync header @@ -315,6 +318,7 @@ static int mlp_parse(AVCodecParserContext *s, } mp->bytes_left = 0; + } sync_present = (AV_RB32(buf + 4) & 0xfffffffe) == 0xf8726fba; From ede6e7494f61927d20216cdbc6f85cfba2341654 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 19 Jan 2018 15:53:32 -0300 Subject: [PATCH 1766/2557] avcodec/mlp_parser: reindent after last commit Signed-off-by: James Almer --- libavcodec/mlp_parser.c | 92 ++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index 4827354f18942..185bd4d667f66 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -259,65 +259,65 @@ static int mlp_parse(AVCodecParserContext *s, if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { next = buf_size; } else { - if (!mp->in_sync) { - // Not in sync - find a major sync header - - for (i = 0; i < buf_size; i++) { - mp->pc.state = (mp->pc.state << 8) | buf[i]; - if ((mp->pc.state & 0xfffffffe) == 0xf8726fba && - // ignore if we do not have the data for the start of header - mp->pc.index + i >= 7) { - mp->in_sync = 1; - mp->bytes_left = 0; - break; + if (!mp->in_sync) { + // Not in sync - find a major sync header + + for (i = 0; i < buf_size; i++) { + mp->pc.state = (mp->pc.state << 8) | buf[i]; + if ((mp->pc.state & 0xfffffffe) == 0xf8726fba && + // ignore if we do not have the data for the start of header + mp->pc.index + i >= 7) { + mp->in_sync = 1; + mp->bytes_left = 0; + break; + } } - } - if (!mp->in_sync) { - if (ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size) != -1) + if (!mp->in_sync) { + if (ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size) != -1) + av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n"); + return buf_size; + } + + if ((ret = ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size)) < 0) { av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n"); - return buf_size; - } + return ret; + } - if ((ret = ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size)) < 0) { - av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n"); - return ret; + return i - 7; } - return i - 7; - } + if (mp->bytes_left == 0) { + // Find length of this packet - if (mp->bytes_left == 0) { - // Find length of this packet - - /* Copy overread bytes from last frame into buffer. */ - for(; mp->pc.overread>0; mp->pc.overread--) { - mp->pc.buffer[mp->pc.index++]= mp->pc.buffer[mp->pc.overread_index++]; - } + /* Copy overread bytes from last frame into buffer. */ + for(; mp->pc.overread>0; mp->pc.overread--) { + mp->pc.buffer[mp->pc.index++]= mp->pc.buffer[mp->pc.overread_index++]; + } - if (mp->pc.index + buf_size < 2) { - if (ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size) != -1) - av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n"); - return buf_size; - } + if (mp->pc.index + buf_size < 2) { + if (ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size) != -1) + av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n"); + return buf_size; + } - mp->bytes_left = ((mp->pc.index > 0 ? mp->pc.buffer[0] : buf[0]) << 8) - | (mp->pc.index > 1 ? mp->pc.buffer[1] : buf[1-mp->pc.index]); - mp->bytes_left = (mp->bytes_left & 0xfff) * 2; - if (mp->bytes_left <= 0) { // prevent infinite loop - goto lost_sync; + mp->bytes_left = ((mp->pc.index > 0 ? mp->pc.buffer[0] : buf[0]) << 8) + | (mp->pc.index > 1 ? mp->pc.buffer[1] : buf[1-mp->pc.index]); + mp->bytes_left = (mp->bytes_left & 0xfff) * 2; + if (mp->bytes_left <= 0) { // prevent infinite loop + goto lost_sync; + } + mp->bytes_left -= mp->pc.index; } - mp->bytes_left -= mp->pc.index; - } - next = (mp->bytes_left > buf_size) ? END_NOT_FOUND : mp->bytes_left; + next = (mp->bytes_left > buf_size) ? END_NOT_FOUND : mp->bytes_left; - if (ff_combine_frame(&mp->pc, next, &buf, &buf_size) < 0) { - mp->bytes_left -= buf_size; - return buf_size; - } + if (ff_combine_frame(&mp->pc, next, &buf, &buf_size) < 0) { + mp->bytes_left -= buf_size; + return buf_size; + } - mp->bytes_left = 0; + mp->bytes_left = 0; } sync_present = (AV_RB32(buf + 4) & 0xfffffffe) == 0xf8726fba; From 0cc3d830d1597c9c7cf98cc26126ff7a18e51640 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 30 Jan 2018 00:32:27 -0300 Subject: [PATCH 1767/2557] avcodec/Makefile: add missing opus.c dependency to opus encoder Needed for ff_celt_quant_bands and ff_celt_bitalloc. Signed-off-by: James Almer --- libavcodec/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index cfacd6b70ce48..68777d91f23c6 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -479,7 +479,7 @@ OBJS-$(CONFIG_NUV_DECODER) += nuv.o rtjpeg.o OBJS-$(CONFIG_ON2AVC_DECODER) += on2avc.o on2avcdata.o OBJS-$(CONFIG_OPUS_DECODER) += opusdec.o opus.o opus_celt.o opus_rc.o \ opus_pvq.o opus_silk.o opustab.o vorbis_data.o -OBJS-$(CONFIG_OPUS_ENCODER) += opusenc.o opus_rc.o opustab.o opus_pvq.o \ +OBJS-$(CONFIG_OPUS_ENCODER) += opusenc.o opus.o opus_rc.o opustab.o opus_pvq.o \ opusenc_psy.o OBJS-$(CONFIG_PAF_AUDIO_DECODER) += pafaudio.o OBJS-$(CONFIG_PAF_VIDEO_DECODER) += pafvideo.o From b99e77b9f7b9df53aa59f9cc4b41572453a55513 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Mon, 29 Jan 2018 11:53:36 +0530 Subject: [PATCH 1768/2557] avformat/mpegenc - fix typo in VBV warning Default VBV buffer size is 230KB, not 130KB. Signed-off-by: Michael Niedermayer --- libavformat/mpegenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c index c77c3dfe41459..695de3f081d93 100644 --- a/libavformat/mpegenc.c +++ b/libavformat/mpegenc.c @@ -397,7 +397,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) stream->max_buffer_size = 6 * 1024 + props->buffer_size / 8; else { av_log(ctx, AV_LOG_WARNING, - "VBV buffer size not set, using default size of 130KB\n" + "VBV buffer size not set, using default size of 230KB\n" "If you want the mpeg file to be compliant to some specification\n" "Like DVD, VCD or others, make sure you set the correct buffer size\n"); // FIXME: this is probably too small as default From 42323c3e3a600288e4bf1cefe952486ffc29d280 Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Mon, 29 Jan 2018 15:10:26 -0800 Subject: [PATCH 1769/2557] avcodec/mpegaudio_parser: Skip APE tags when parsing mp3 packets. Otherwise the decoder will throw "Missing header" errors when the packets are sent for decoding. This is similar to 89a420b71b5. Signed-off-by: Michael Niedermayer --- libavcodec/mpegaudio_parser.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/mpegaudio_parser.c b/libavcodec/mpegaudio_parser.c index 8c39825792282..244281b56fa2b 100644 --- a/libavcodec/mpegaudio_parser.c +++ b/libavcodec/mpegaudio_parser.c @@ -23,6 +23,7 @@ #include "parser.h" #include "mpegaudiodecheader.h" #include "libavutil/common.h" +#include "libavformat/apetag.h" // for APE tag. #include "libavformat/id3v1.h" // for ID3v1_TAG_SIZE typedef struct MpegAudioParseContext { @@ -120,6 +121,12 @@ static int mpegaudio_parse(AVCodecParserContext *s1, return next; } + if (flush && buf_size >= APE_TAG_FOOTER_BYTES && memcmp(buf, APE_TAG_PREAMBLE, 8) == 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return next; + } + *poutbuf = buf; *poutbuf_size = buf_size; return next; From 222d7055e2dd20eb1381c257d34a50ec4c8dadb0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 20 Jan 2018 00:57:18 -0300 Subject: [PATCH 1770/2557] avcodec/hevc_parser: use ff_hevc_decode_extradata() to parse extradata Signed-off-by: James Almer --- libavcodec/hevc_parser.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c index 88d3d9a22f30f..a468682ed335b 100644 --- a/libavcodec/hevc_parser.c +++ b/libavcodec/hevc_parser.c @@ -24,6 +24,7 @@ #include "golomb.h" #include "hevc.h" +#include "hevc_parse.h" #include "hevc_ps.h" #include "hevc_sei.h" #include "h2645_parse.h" @@ -43,6 +44,8 @@ typedef struct HEVCParserContext { HEVCSEI sei; SliceHeader sh; + int is_avc; + int nal_length_size; int parsed_extradata; int poc; @@ -181,7 +184,6 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, HEVCParserContext *ctx = s->priv_data; HEVCParamSets *ps = &ctx->ps; HEVCSEI *sei = &ctx->sei; - int is_global = buf == avctx->extradata; int ret, i; /* set some sane default values */ @@ -191,8 +193,8 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, ff_hevc_reset_sei(sei); - ret = ff_h2645_packet_split(&ctx->pkt, buf, buf_size, avctx, 0, 0, - AV_CODEC_ID_HEVC, 1); + ret = ff_h2645_packet_split(&ctx->pkt, buf, buf_size, avctx, ctx->is_avc, + ctx->nal_length_size, AV_CODEC_ID_HEVC, 1); if (ret < 0) return ret; @@ -230,12 +232,6 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, case HEVC_NAL_RADL_R: case HEVC_NAL_RASL_N: case HEVC_NAL_RASL_R: - - if (is_global) { - av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit: %d\n", nal->type); - return AVERROR_INVALIDDATA; - } - ret = hevc_parse_slice_header(s, nal, avctx); if (ret) return ret; @@ -243,8 +239,7 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, } } /* didn't find a picture! */ - if (!is_global) - av_log(avctx, AV_LOG_ERROR, "missing picture in access unit\n"); + av_log(avctx, AV_LOG_ERROR, "missing picture in access unit\n"); return -1; } @@ -301,7 +296,9 @@ static int hevc_parse(AVCodecParserContext *s, AVCodecContext *avctx, ParseContext *pc = &ctx->pc; if (avctx->extradata && !ctx->parsed_extradata) { - parse_nal_units(s, avctx->extradata, avctx->extradata_size, avctx); + ff_hevc_decode_extradata(avctx->extradata, avctx->extradata_size, &ctx->ps, &ctx->sei, + &ctx->is_avc, &ctx->nal_length_size, avctx->err_recognition, + 1, avctx); ctx->parsed_extradata = 1; } From 782e066e3e3d8015d6d64c47cda0925c10aebe08 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 20 Jan 2018 16:55:17 -0300 Subject: [PATCH 1771/2557] avcodec/mediacodecdec: use ff_hevc_ps_uninit() Fixes memleaks. Signed-off-by: James Almer --- libavcodec/mediacodecdec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 6c5d3ddd799a4..cb1151a19527b 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -258,6 +258,8 @@ static int hevc_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format) } done: + ff_hevc_ps_uninit(&ps); + av_freep(&vps_data); av_freep(&sps_data); av_freep(&pps_data); From 4a75a75c62efc645ec28444e4675c325b8f2bb1a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 24 Jan 2018 03:15:23 +0100 Subject: [PATCH 1772/2557] avcodec/hevc_ps: Check log2_sao_offset_scale_* Fixes: 4868/clusterfuzz-testcase-minimized-6236542906400768 Fixes: runtime error: shift exponent 126 is too large for 32-bit type 'int' Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevc_ps.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 4787312cfaa0e..1f18d0335b9f5 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1324,6 +1324,11 @@ static int pps_range_extensions(GetBitContext *gb, AVCodecContext *avctx, pps->log2_sao_offset_scale_luma = get_ue_golomb_long(gb); pps->log2_sao_offset_scale_chroma = get_ue_golomb_long(gb); + if ( pps->log2_sao_offset_scale_luma > FFMAX(sps->bit_depth - 10, 0) + || pps->log2_sao_offset_scale_chroma > FFMAX(sps->bit_depth_chroma - 10, 0) + ) + return AVERROR_INVALIDDATA; + return(0); } From 2ff9f178519b68d4d1d606eb5451ad81da948efc Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 26 Jan 2018 00:24:49 +0100 Subject: [PATCH 1773/2557] avcodec/indeo5: Do not leave frame_type set to an invalid value Fixes: null pointer dereference Fixes: 5264/clusterfuzz-testcase-minimized-4621956621008896 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/indeo5.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/indeo5.c b/libavcodec/indeo5.c index 81b4514038ae4..b39cffd9a91be 100644 --- a/libavcodec/indeo5.c +++ b/libavcodec/indeo5.c @@ -324,6 +324,7 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx) ctx->frame_type = get_bits(&ctx->gb, 3); if (ctx->frame_type >= 5) { av_log(avctx, AV_LOG_ERROR, "Invalid frame type: %d \n", ctx->frame_type); + ctx->frame_type = FRAMETYPE_INTRA; return AVERROR_INVALIDDATA; } From fe1e6c06d03432c3e9208f019533c1d701f485d0 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 25 Jan 2018 23:14:37 +0100 Subject: [PATCH 1774/2557] avcodec/dirac_dwt: Fix several integer overflows Fixes: runtime error: signed integer overflow: -2146071175 + -268479557 cannot be represented in type 'int' Fixes: 5237/clusterfuzz-testcase-minimized-4569895275593728 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/dirac_dwt.h | 4 ++-- libavcodec/dirac_dwt_template.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/dirac_dwt.h b/libavcodec/dirac_dwt.h index 1af41e07025fe..68ebd195603a1 100644 --- a/libavcodec/dirac_dwt.h +++ b/libavcodec/dirac_dwt.h @@ -93,10 +93,10 @@ void ff_spatial_idwt_slice2(DWTContext *d, int y); // shared stuff for simd optimizations #define COMPOSE_53iL0(b0, b1, b2)\ - (b1 - ((int)(b0 + (unsigned)(b2) + 2) >> 2)) + (b1 - (unsigned)((int)(b0 + (unsigned)(b2) + 2) >> 2)) #define COMPOSE_DIRAC53iH0(b0, b1, b2)\ - (b1 + ((int)(b0 + (unsigned)(b2) + 1) >> 1)) + (b1 + (unsigned)((int)(b0 + (unsigned)(b2) + 1) >> 1)) #define COMPOSE_DD97iH0(b0, b1, b2, b3, b4)\ (int)(((unsigned)(b2) + ((int)(-b0 + 9U*b1 + 9U*b3 - b4 + 8) >> 4))) diff --git a/libavcodec/dirac_dwt_template.c b/libavcodec/dirac_dwt_template.c index e436c247a1fd6..e68cc4d5300a7 100644 --- a/libavcodec/dirac_dwt_template.c +++ b/libavcodec/dirac_dwt_template.c @@ -49,7 +49,7 @@ static void RENAME(vertical_compose53iL0)(uint8_t *_b0, uint8_t *_b1, uint8_t *_ TYPE *b1 = (TYPE *)_b1; TYPE *b2 = (TYPE *)_b2; for (i = 0; i < width; i++) - b1[i] -= (int)(b0[i] + (unsigned)b2[i] + 2) >> 2; + b1[i] -= (unsigned)((int)(b0[i] + (unsigned)b2[i] + 2) >> 2); } static av_always_inline void RENAME(interleave)(TYPE *dst, TYPE *src0, TYPE *src1, int w2, From 5085f25ace1e74846a0de3369bedd0e22d1a1bdc Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Sat, 27 Jan 2018 21:19:30 -0500 Subject: [PATCH 1775/2557] vc1: skip motion compensation when data for last picture is invalid Bug-Id: 1101 Cc: libav-stable@libav.org --- libavcodec/vc1_mc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/vc1_mc.c b/libavcodec/vc1_mc.c index f4632d6247600..18ac47a0378f0 100644 --- a/libavcodec/vc1_mc.c +++ b/libavcodec/vc1_mc.c @@ -689,6 +689,11 @@ void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg) if (s->avctx->flags & AV_CODEC_FLAG_GRAY) return; + if (!s->last_picture.f->data[1]) { + av_log(s->avctx, AV_LOG_ERROR, "Bad data in last picture frame.\n"); + return; + } + for (i = 0; i < 4; i++) { int d = i < 2 ? dir: dir2; tx = s->mv[d][i][0]; From 61a4ee8ab482925cb419133cab42e4c4ef6a3f07 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Wed, 6 Apr 2016 11:51:24 +0100 Subject: [PATCH 1776/2557] avcodec/vc2enc: prevent bitrate overshoots The rounding caused by the size scaler wasn't compensated for and the slice sizes grew beyond what is allowed per frame. Signed-off-by: Rostislav Pehlivanov --- libavcodec/vc2enc.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c index 2f08441d55645..b7adcd3d36d4c 100644 --- a/libavcodec/vc2enc.c +++ b/libavcodec/vc2enc.c @@ -164,6 +164,7 @@ typedef struct VC2EncContext { int chroma_y_shift; /* Rate control stuff */ + int frame_max_bytes; int slice_max_bytes; int slice_min_bytes; int q_ceil; @@ -715,7 +716,7 @@ static int calc_slice_sizes(VC2EncContext *s) for (i = 0; i < s->num_x*s->num_y; i++) { SliceArgs *args = &enc_args[i]; - bytes_left += s->slice_max_bytes - args->bytes; + bytes_left += args->bytes; for (j = 0; j < slice_redist_range; j++) { if (args->bytes > bytes_top[j]) { bytes_top[j] = args->bytes; @@ -725,8 +726,10 @@ static int calc_slice_sizes(VC2EncContext *s) } } + bytes_left = s->frame_max_bytes - bytes_left; + /* Second pass - distribute leftover bytes */ - while (1) { + while (bytes_left > 0) { int distributed = 0; for (i = 0; i < slice_redist_range; i++) { SliceArgs *args; @@ -994,13 +997,13 @@ static av_cold int vc2_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet) { int ret = 0; - int sig_size = 256; + int slice_ceil, sig_size = 256; VC2EncContext *s = avctx->priv_data; const int bitexact = avctx->flags & AV_CODEC_FLAG_BITEXACT; const char *aux_data = bitexact ? "Lavc" : LIBAVCODEC_IDENT; const int aux_data_size = bitexact ? sizeof("Lavc") : sizeof(LIBAVCODEC_IDENT); const int header_size = 100 + aux_data_size; - int64_t max_frame_bytes, r_bitrate = avctx->bit_rate >> (s->interlaced); + int64_t r_bitrate = avctx->bit_rate >> (s->interlaced); s->avctx = avctx; s->size_scaler = 2; @@ -1009,18 +1012,21 @@ static av_cold int vc2_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, s->next_parse_offset = 0; /* Rate control */ - max_frame_bytes = (av_rescale(r_bitrate, s->avctx->time_base.num, - s->avctx->time_base.den) >> 3) - header_size; - s->slice_max_bytes = av_rescale(max_frame_bytes, 1, s->num_x*s->num_y); + s->frame_max_bytes = (av_rescale(r_bitrate, s->avctx->time_base.num, + s->avctx->time_base.den) >> 3) - header_size; + s->slice_max_bytes = slice_ceil = av_rescale(s->frame_max_bytes, 1, s->num_x*s->num_y); /* Find an appropriate size scaler */ while (sig_size > 255) { int r_size = SSIZE_ROUND(s->slice_max_bytes); + if (r_size > slice_ceil) { + s->slice_max_bytes -= r_size - slice_ceil; + r_size = SSIZE_ROUND(s->slice_max_bytes); + } sig_size = r_size/s->size_scaler; /* Signalled slize size */ s->size_scaler <<= 1; } - s->slice_max_bytes = SSIZE_ROUND(s->slice_max_bytes); s->slice_min_bytes = s->slice_max_bytes - s->slice_max_bytes*(s->tolerance/100.0f); ret = encode_frame(s, avpkt, frame, aux_data, header_size, s->interlaced); From 27fe8930e0b9e7881e61eb9ed0b8b526f718abfe Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 1 Feb 2018 10:55:19 +0800 Subject: [PATCH 1777/2557] avfilter: add comments for duplicate line comment about the looks like a duplicate line. but that is used to reason x is expressed from y Suggested-by: Paul B Mahol Suggested-by: Michael Niedermayer Signed-off-by: Steven Liu --- libavfilter/vf_crop.c | 1 + libavfilter/vf_drawtext.c | 1 + libavfilter/vf_overlay.c | 1 + 3 files changed, 3 insertions(+) diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c index 7c31c1665d91c..0fdc4949e3bd4 100644 --- a/libavfilter/vf_crop.c +++ b/libavfilter/vf_crop.c @@ -262,6 +262,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame) NAN : frame->pkt_pos; s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL); s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, NULL); + /* It is necessary if x is expressed from y */ s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL); normalize_double(&s->x, s->var_values[VAR_X]); diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index f97a741b5085d..e8905a40d3ead 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -1390,6 +1390,7 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame, s->x = s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, &s->prng); s->y = s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, &s->prng); + /* It is necessary if x is expressed from y */ s->x = s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, &s->prng); update_alpha(s); diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index aa5835ae3abf4..c6a6ac82f397a 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -149,6 +149,7 @@ static void eval_expr(AVFilterContext *ctx) s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL); s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, NULL); + /* It is necessary if x is expressed from y */ s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL); s->x = normalize_xy(s->var_values[VAR_X], s->hsub); s->y = normalize_xy(s->var_values[VAR_Y], s->vsub); From 44f343067455e09ce4da16b2169e89d9c062dbca Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 1 Feb 2018 10:56:51 +0800 Subject: [PATCH 1778/2557] avformat/http: add referer option into http add Referer message if referer have been set. Signed-off-by: Steven Liu --- doc/protocols.texi | 3 +++ libavformat/http.c | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/doc/protocols.texi b/doc/protocols.texi index 98deb73005bc2..c24dc74505239 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -296,6 +296,9 @@ Use persistent connections if set to 1, default is 0. @item post_data Set custom HTTP post data. +@item referer +Set the Referer header. Include 'Referer: URL' header in HTTP request. + @item user_agent Override the User-Agent header. If not specified the protocol will use a string describing the libavformat build. ("Lavf/") diff --git a/libavformat/http.c b/libavformat/http.c index aa80e314dff5b..344fd603cb9b0 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -76,6 +76,7 @@ typedef struct HTTPContext { char *mime_type; char *http_version; char *user_agent; + char *referer; #if FF_API_HTTP_USER_AGENT char *user_agent_deprecated; #endif @@ -138,6 +139,7 @@ static const AVOption options[] = { { "headers", "set custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E }, { "content_type", "set a specific content type for the POST messages", OFFSET(content_type), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E }, { "user_agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, { .str = DEFAULT_USER_AGENT }, 0, 0, D }, + { "referer", "override referer header", OFFSET(referer), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, #if FF_API_HTTP_USER_AGENT { "user-agent", "override User-Agent header", OFFSET(user_agent_deprecated), AV_OPT_TYPE_STRING, { .str = DEFAULT_USER_AGENT }, 0, 0, D }, #endif @@ -1198,6 +1200,12 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, if (!has_header(s->headers, "\r\nUser-Agent: ")) len += av_strlcatf(headers + len, sizeof(headers) - len, "User-Agent: %s\r\n", s->user_agent); + if (s->referer) { + /* set default headers if needed */ + if (!has_header(s->headers, "\r\nReferer: ")) + len += av_strlcatf(headers + len, sizeof(headers) - len, + "Referer: %s\r\n", s->referer); + } if (!has_header(s->headers, "\r\nAccept: ")) len += av_strlcpy(headers + len, "Accept: */*\r\n", sizeof(headers) - len); From b1af0e23a3b685b3e626158f63e5f958f5f75420 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Thu, 1 Feb 2018 10:57:29 +0800 Subject: [PATCH 1779/2557] avformat/hls: store referer message in HLS http request Signed-off-by: Steven Liu --- libavformat/hls.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index ba7eb941215b8..9bd54c84ccf6b 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -202,6 +202,7 @@ typedef struct HLSContext { int64_t first_timestamp; int64_t cur_timestamp; AVIOInterruptCB *interrupt_callback; + char *referer; ///< holds HTTP referer set as an AVOption to the HTTP protocol context char *user_agent; ///< holds HTTP user agent set as an AVOption to the HTTP protocol context char *cookies; ///< holds HTTP cookie values set in either the initial response or as an AVOption to the HTTP protocol context char *headers; ///< holds HTTP headers set as an AVOption to the HTTP protocol context @@ -1184,6 +1185,7 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg, // broker prior HTTP options that should be consistent across requests av_dict_set(&opts, "user_agent", c->user_agent, 0); + av_dict_set(&opts, "referer", c->referer, 0); av_dict_set(&opts, "cookies", c->cookies, 0); av_dict_set(&opts, "headers", c->headers, 0); av_dict_set(&opts, "http_proxy", c->http_proxy, 0); @@ -1658,7 +1660,7 @@ static int save_avio_options(AVFormatContext *s) { HLSContext *c = s->priv_data; static const char * const opts[] = { - "headers", "http_proxy", "user_agent", "user-agent", "cookies", NULL }; + "headers", "http_proxy", "user_agent", "user-agent", "cookies", "referer", NULL }; const char * const * opt = opts; uint8_t *buf; int ret = 0; From 8965e2af921ec5926b26d5ae466ee4104bb5262b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 1 Feb 2018 14:56:49 +0200 Subject: [PATCH 1780/2557] avpacket: Initialize the allocated padding area in side data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes sure that consumers of the side data actually can rely on the padding as intended, without having the callers of av_packet_new_side_data to explicitly zero initialize it. Signed-off-by: Martin Storsjö --- libavcodec/avpacket.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index 93e9eb6ae7d69..c705df3d5933c 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -271,6 +271,7 @@ uint8_t *av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, data = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!data) return NULL; + memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); ret = av_packet_add_side_data(pkt, type, data, size); if (ret < 0) { From 0a2560a9775be7c5df09c85c9908b05e711a54a3 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 31 Jan 2018 17:50:21 +0100 Subject: [PATCH 1781/2557] avcodec/exr: Fix memleaks in decode_header() Fixes: 4793/clusterfuzz-testcase-minimized-5707366629638144 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/exr.c | 82 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 26 deletions(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 454dc74cfb14c..f08576af22c61 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -1306,6 +1306,7 @@ static int decode_header(EXRContext *s, AVFrame *frame) AVDictionary *metadata = NULL; int magic_number, version, i, flags, sar = 0; int layer_match = 0; + int ret; s->current_channel_offset = 0; s->xmin = ~0; @@ -1364,8 +1365,10 @@ static int decode_header(EXRContext *s, AVFrame *frame) if ((var_size = check_header_variable(s, "channels", "chlist", 38)) >= 0) { GetByteContext ch_gb; - if (!var_size) - return AVERROR_INVALIDDATA; + if (!var_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } bytestream2_init(&ch_gb, s->gb.buffer, var_size); @@ -1424,14 +1427,16 @@ static int decode_header(EXRContext *s, AVFrame *frame) if (bytestream2_get_bytes_left(&ch_gb) < 4) { av_log(s->avctx, AV_LOG_ERROR, "Incomplete header.\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } current_pixel_type = bytestream2_get_le32(&ch_gb); if (current_pixel_type >= EXR_UNKNOWN) { avpriv_report_missing_feature(s->avctx, "Pixel type %d", current_pixel_type); - return AVERROR_PATCHWELCOME; + ret = AVERROR_PATCHWELCOME; + goto fail; } bytestream2_skip(&ch_gb, 4); @@ -1442,7 +1447,8 @@ static int decode_header(EXRContext *s, AVFrame *frame) avpriv_report_missing_feature(s->avctx, "Subsampling %dx%d", xsub, ysub); - return AVERROR_PATCHWELCOME; + ret = AVERROR_PATCHWELCOME; + goto fail; } if (channel_index >= 0 && s->channel_offsets[channel_index] == -1) { /* channel has not been previously assigned */ @@ -1450,7 +1456,8 @@ static int decode_header(EXRContext *s, AVFrame *frame) s->pixel_type != current_pixel_type) { av_log(s->avctx, AV_LOG_ERROR, "RGB channels not of the same depth.\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } s->pixel_type = current_pixel_type; s->channel_offsets[channel_index] = s->current_channel_offset; @@ -1458,8 +1465,10 @@ static int decode_header(EXRContext *s, AVFrame *frame) s->channels = av_realloc(s->channels, ++s->nb_channels * sizeof(EXRChannel)); - if (!s->channels) - return AVERROR(ENOMEM); + if (!s->channels) { + ret = AVERROR(ENOMEM); + goto fail; + } channel = &s->channels[s->nb_channels - 1]; channel->pixel_type = current_pixel_type; channel->xsub = xsub; @@ -1484,7 +1493,8 @@ static int decode_header(EXRContext *s, AVFrame *frame) av_log(s->avctx, AV_LOG_ERROR, "Missing green channel.\n"); if (s->channel_offsets[2] < 0) av_log(s->avctx, AV_LOG_ERROR, "Missing blue channel.\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } } @@ -1493,8 +1503,10 @@ static int decode_header(EXRContext *s, AVFrame *frame) continue; } else if ((var_size = check_header_variable(s, "dataWindow", "box2i", 31)) >= 0) { - if (!var_size) - return AVERROR_INVALIDDATA; + if (!var_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } s->xmin = bytestream2_get_le32(&s->gb); s->ymin = bytestream2_get_le32(&s->gb); @@ -1506,8 +1518,10 @@ static int decode_header(EXRContext *s, AVFrame *frame) continue; } else if ((var_size = check_header_variable(s, "displayWindow", "box2i", 34)) >= 0) { - if (!var_size) - return AVERROR_INVALIDDATA; + if (!var_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } bytestream2_skip(&s->gb, 8); s->w = bytestream2_get_le32(&s->gb) + 1; @@ -1517,29 +1531,36 @@ static int decode_header(EXRContext *s, AVFrame *frame) } else if ((var_size = check_header_variable(s, "lineOrder", "lineOrder", 25)) >= 0) { int line_order; - if (!var_size) - return AVERROR_INVALIDDATA; + if (!var_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } line_order = bytestream2_get_byte(&s->gb); av_log(s->avctx, AV_LOG_DEBUG, "line order: %d.\n", line_order); if (line_order > 2) { av_log(s->avctx, AV_LOG_ERROR, "Unknown line order.\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } continue; } else if ((var_size = check_header_variable(s, "pixelAspectRatio", "float", 31)) >= 0) { - if (!var_size) - return AVERROR_INVALIDDATA; + if (!var_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } sar = bytestream2_get_le32(&s->gb); continue; } else if ((var_size = check_header_variable(s, "compression", "compression", 29)) >= 0) { - if (!var_size) - return AVERROR_INVALIDDATA; + if (!var_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } if (s->compression == EXR_UNKN) s->compression = bytestream2_get_byte(&s->gb); @@ -1566,13 +1587,15 @@ static int decode_header(EXRContext *s, AVFrame *frame) if (s->tile_attr.level_mode >= EXR_TILE_LEVEL_UNKNOWN){ avpriv_report_missing_feature(s->avctx, "Tile level mode %d", s->tile_attr.level_mode); - return AVERROR_PATCHWELCOME; + ret = AVERROR_PATCHWELCOME; + goto fail; } if (s->tile_attr.level_round >= EXR_TILE_ROUND_UNKNOWN) { avpriv_report_missing_feature(s->avctx, "Tile level round %d", s->tile_attr.level_round); - return AVERROR_PATCHWELCOME; + ret = AVERROR_PATCHWELCOME; + goto fail; } continue; @@ -1589,7 +1612,8 @@ static int decode_header(EXRContext *s, AVFrame *frame) // Check if there are enough bytes for a header if (bytestream2_get_bytes_left(&s->gb) <= 9) { av_log(s->avctx, AV_LOG_ERROR, "Incomplete header\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } // Process unknown variables @@ -1604,19 +1628,22 @@ static int decode_header(EXRContext *s, AVFrame *frame) if (s->compression == EXR_UNKN) { av_log(s->avctx, AV_LOG_ERROR, "Missing compression attribute.\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } if (s->is_tile) { if (s->tile_attr.xSize < 1 || s->tile_attr.ySize < 1) { av_log(s->avctx, AV_LOG_ERROR, "Invalid tile attribute.\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } } if (bytestream2_get_bytes_left(&s->gb) <= 0) { av_log(s->avctx, AV_LOG_ERROR, "Incomplete frame.\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } frame->metadata = metadata; @@ -1624,6 +1651,9 @@ static int decode_header(EXRContext *s, AVFrame *frame) // aaand we are done bytestream2_skip(&s->gb, 1); return 0; +fail: + av_dict_free(&metadata); + return ret; } static int decode_frame(AVCodecContext *avctx, void *data, From b1bef755f617af9685b592d866b3eb7f3c4b02b1 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 31 Jan 2018 18:13:07 +0100 Subject: [PATCH 1782/2557] avcodec/aacsbr_fixed: Fix overflows in rounding in sbr_hf_assemble() Fixes: runtime error: signed integer overflow: 2052929346 + 204817098 cannot be represented in type 'int' Fixes: 5275/clusterfuzz-testcase-minimized-5367635958038528 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/aacsbr_fixed.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavcodec/aacsbr_fixed.c b/libavcodec/aacsbr_fixed.c index 3d5875a4690d2..eeada0b9f2b7e 100644 --- a/libavcodec/aacsbr_fixed.c +++ b/libavcodec/aacsbr_fixed.c @@ -568,7 +568,8 @@ static void sbr_hf_assemble(int Y1[38][64][2], int A = (1-((indexsine+(kx & 1))&2)); int B = (A^(-idx)) + idx; int *out = &Y1[i][kx][idx]; - int shift, round; + int shift; + unsigned round; SoftFloat *in = sbr->s_m[e]; for (m = 0; m+1 < m_max; m+=2) { @@ -581,12 +582,12 @@ static void sbr_hf_assemble(int Y1[38][64][2], } if (shift < 32) { round = 1 << (shift-1); - out[2*m ] += (in[m ].mant * A + round) >> shift; + out[2*m ] += (int)(in[m ].mant * A + round) >> shift; } if (shift2 < 32) { round = 1 << (shift2-1); - out[2*m+2] += (in[m+1].mant * B + round) >> shift2; + out[2*m+2] += (int)(in[m+1].mant * B + round) >> shift2; } } if(m_max&1) @@ -597,7 +598,7 @@ static void sbr_hf_assemble(int Y1[38][64][2], return; } else if (shift < 32) { round = 1 << (shift-1); - out[2*m ] += (in[m ].mant * A + round) >> shift; + out[2*m ] += (int)(in[m ].mant * A + round) >> shift; } } } From caaa40d2c67b1f4ebde368c859647af6f42f394a Mon Sep 17 00:00:00 2001 From: Xiaohan Wang Date: Wed, 31 Jan 2018 14:20:02 -0800 Subject: [PATCH 1783/2557] configure: Remove carriage return ('\r') in Windows CC_IDENT Currently the Windows CC_IDENT is ended with '\r\n'. "head -n1" will not remove the '\r' and this is causing building error in Chromium. This CL adds "tr -d '\r'" to remove '\r' in the CC_IDENT string. Since in most cases '\r' only appears at the end of a string/line, this should work in most cases. See example: printf "hello\r\nworld\r\n" | head -n1 | hd 00000000 68 65 6c 6c 6f 0d 0a |hello..| printf "hello\r\nworld\r\n" | head -n1 | tr -d '\r' | hd 00000000 68 65 6c 6c 6f 0a |hello.| Also note a similar previous change at: https://lists.ffmpeg.org/pipermail/ffmpeg-cvslog/2013-October/069950.html Signed-off-by: Michael Niedermayer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index fcfa7aa4422ef..0b01a221c798e 100755 --- a/configure +++ b/configure @@ -4289,7 +4289,7 @@ probe_cc(){ _ld_path='-libpath:' elif $_cc -nologo- 2>&1 | grep -q Microsoft; then _type=msvc - _ident=$($_cc 2>&1 | head -n1) + _ident=$($_cc 2>&1 | head -n1 | tr -d '\r') _DEPCMD='$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< 2>&1 | awk '\''/including/ { sub(/^.*file: */, ""); gsub(/\\/, "/"); if (!match($$0, / /)) print "$@:", $$0 }'\'' > $(@:.o=.d)' _DEPFLAGS='$(CPPFLAGS) $(CFLAGS) -showIncludes -Zs' _cflags_speed="-O2" From 4be6307cbf819eeaac850b3f0e7e088b147107d3 Mon Sep 17 00:00:00 2001 From: Richard Shaffer Date: Sat, 27 Jan 2018 18:21:28 -0800 Subject: [PATCH 1784/2557] fate: add id3v2 test Adds basic unit test for parsing ID3v2 tags. Signed-off-by: James Almer --- tests/Makefile | 1 + tests/fate-run.sh | 4 ++++ tests/fate/id3v2.mak | 5 +++++ tests/ref/fate/id3v2-priv | 5 +++++ 4 files changed, 15 insertions(+) create mode 100644 tests/fate/id3v2.mak create mode 100644 tests/ref/fate/id3v2-priv diff --git a/tests/Makefile b/tests/Makefile index 14b9601378c2d..327e3f44201f9 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -130,6 +130,7 @@ include $(SRC_PATH)/tests/fate/gapless.mak include $(SRC_PATH)/tests/fate/gif.mak include $(SRC_PATH)/tests/fate/h264.mak include $(SRC_PATH)/tests/fate/hevc.mak +include $(SRC_PATH)/tests/fate/id3v2.mak include $(SRC_PATH)/tests/fate/image.mak include $(SRC_PATH)/tests/fate/indeo.mak include $(SRC_PATH)/tests/fate/libavcodec.mak diff --git a/tests/fate-run.sh b/tests/fate-run.sh index 05f4ca5e20bcf..82862b7ef40a3 100755 --- a/tests/fate-run.sh +++ b/tests/fate-run.sh @@ -88,6 +88,10 @@ probefmt(){ run ffprobe${PROGSUF} -show_entries format=format_name -print_format default=nw=1:nk=1 -v 0 "$@" } +probetags(){ + run ffprobe${PROGSUF} -show_entries format_tags -v 0 "$@" +} + runlocal(){ test "${V:-0}" -gt 0 && echo ${base}/"$@" ${base} >&3 ${base}/"$@" ${base} diff --git a/tests/fate/id3v2.mak b/tests/fate/id3v2.mak new file mode 100644 index 0000000000000..873f593d8cb39 --- /dev/null +++ b/tests/fate/id3v2.mak @@ -0,0 +1,5 @@ +FATE_SAMPLES_ID3V2-$(CONFIG_MP3_DEMUXER) += fate-id3v2-priv +fate-id3v2-priv: CMD = probetags $(TARGET_SAMPLES)/id3v2/id3v2_priv.mp3 + +FATE_SAMPLES_FFPROBE += $(FATE_SAMPLES_ID3V2-yes) +fate-id3v2: $(FATE_SAMPLES_ID3V2-yes) diff --git a/tests/ref/fate/id3v2-priv b/tests/ref/fate/id3v2-priv new file mode 100644 index 0000000000000..965c8695e8852 --- /dev/null +++ b/tests/ref/fate/id3v2-priv @@ -0,0 +1,5 @@ +[FORMAT] +TAG:title=id3v2-test +TAG:id3v2_priv.testowner=testdata +TAG:id3v2_priv.testowner2=\x00\x01\x02 +[/FORMAT] From 108958e43df075967217d4c81cb4cea5164b2b5f Mon Sep 17 00:00:00 2001 From: Calvin Walton Date: Thu, 1 Feb 2018 13:28:25 -0500 Subject: [PATCH 1785/2557] librsvgdec: Fix frame clearing code The existing code attempts to clear the frame by painting in OVER mode with transparent black - which is a no-op. As a result if you have many input frames (e.g. you're using a sequence of svg files), you'll start to see new frames drawn over old frames as memory gets re-used. Switch the code to paint using the CLEAR compositing operator, which fills every channel with 0 values (setting a source colour is not required). --- libavcodec/librsvgdec.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/librsvgdec.c b/libavcodec/librsvgdec.c index e57070f8e44ec..66977850261f9 100644 --- a/libavcodec/librsvgdec.c +++ b/libavcodec/librsvgdec.c @@ -82,8 +82,10 @@ static int librsvg_decode_frame(AVCodecContext *avctx, void *data, int *got_fram crender = cairo_create(image); - cairo_set_source_rgba(crender, 0.0, 0.0, 0.0, 1.0f); - cairo_paint_with_alpha(crender, 0.0f); + cairo_save(crender); + cairo_set_operator(crender, CAIRO_OPERATOR_CLEAR); + cairo_paint(crender); + cairo_restore(crender); cairo_scale(crender, dimensions.width / (double)unscaled_dimensions.width, dimensions.height / (double)unscaled_dimensions.height); From 19b1d905b88d32a86511219585eae6afda23dfbd Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Fri, 19 Jan 2018 13:05:55 +0800 Subject: [PATCH 1786/2557] ffprobe: Initialize coded_width/height coded_width/height are unnitialized and will be overwritten by dec_ctx->width/height in avcodec_open2() This fixes tiket #6958. Signed-off-by: Zhong Li Signed-off-by: James Almer --- fftools/ffprobe.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index acb403e3b12ac..fc3a14a807ced 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2512,10 +2512,12 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id case AVMEDIA_TYPE_VIDEO: print_int("width", par->width); print_int("height", par->height); +#if FF_API_LAVF_AVCTX if (dec_ctx) { print_int("coded_width", dec_ctx->coded_width); print_int("coded_height", dec_ctx->coded_height); } +#endif print_int("has_b_frames", par->video_delay); sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL); if (sar.den) { @@ -2912,6 +2914,12 @@ static int open_input_file(InputFile *ifile, const char *filename) ist->dec_ctx->pkt_timebase = stream->time_base; ist->dec_ctx->framerate = stream->avg_frame_rate; +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + ist->dec_ctx->coded_width = stream->codec->coded_width; + ist->dec_ctx->coded_height = stream->codec->coded_height; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (avcodec_open2(ist->dec_ctx, codec, &opts) < 0) { av_log(NULL, AV_LOG_WARNING, "Could not open codec for input stream %d\n", From 94eb5505ad7b061e17e1c338f04bec0d05e10ca0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 2 Feb 2018 17:51:24 -0300 Subject: [PATCH 1787/2557] ffprobe: remove usage of deprecation warning removal pragmas Fixes compilation in non Windows targets. Signed-off-by: James Almer --- fftools/ffprobe.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index fc3a14a807ced..967adbe30cd8f 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2915,10 +2915,8 @@ static int open_input_file(InputFile *ifile, const char *filename) ist->dec_ctx->pkt_timebase = stream->time_base; ist->dec_ctx->framerate = stream->avg_frame_rate; #if FF_API_LAVF_AVCTX -FF_DISABLE_DEPRECATION_WARNINGS ist->dec_ctx->coded_width = stream->codec->coded_width; ist->dec_ctx->coded_height = stream->codec->coded_height; -FF_ENABLE_DEPRECATION_WARNINGS #endif if (avcodec_open2(ist->dec_ctx, codec, &opts) < 0) { From e3d946b3f48fa000e2ba917ecb1bf21e5fe947fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Martinez?= Date: Thu, 1 Feb 2018 13:15:54 +0100 Subject: [PATCH 1788/2557] avcodec/ffv1enc: mark RGB48 support as non-experimental Remove the 2nd mark, 1st mark was removed in 58e16a4 Signed-off-by: Michael Niedermayer --- libavcodec/ffv1enc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index c0c1558ffe634..0778f84c9bbaa 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -657,10 +657,6 @@ FF_ENABLE_DEPRECATION_WARNINGS s->chroma_planes = 1; if (s->bits_per_raw_sample >= 16) { s->use32bit = 1; - if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { - av_log(avctx, AV_LOG_ERROR, "16bit RGB is experimental and under development, only use it for experiments\n"); - return AVERROR_INVALIDDATA; - } } s->version = FFMAX(s->version, 1); break; From c86490c49a3d0683b2f63338430a369c174e2bd5 Mon Sep 17 00:00:00 2001 From: Nikolas Bowe Date: Fri, 2 Feb 2018 15:11:04 -0800 Subject: [PATCH 1789/2557] avfilter/af_join: Fix crash in join filter Previously if ff_outlink_frame_wanted() returned 0 it could dereference a null pointer when trying to read nb_samples. Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer --- libavfilter/af_join.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavfilter/af_join.c b/libavfilter/af_join.c index cf5131e8dcaf0..4f86e13558417 100644 --- a/libavfilter/af_join.c +++ b/libavfilter/af_join.c @@ -485,6 +485,9 @@ static int activate(AVFilterContext *ctx) return 0; } } + if (!s->input_frames[0]) { + return 0; + } } nb_samples = s->input_frames[0]->nb_samples; From 8e50bd61e4ff97bd7fc6cbd7ec4ca514e17a70c4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 31 Jan 2018 02:50:18 +0100 Subject: [PATCH 1790/2557] avcodec/wavpack: Fix integer overflow in FFABS Fixes: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself Fixes: 5396/clusterfuzz-testcase-minimized-6558555529281536 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/wavpack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c index d5e1e07b743be..0e40b29879959 100644 --- a/libavcodec/wavpack.c +++ b/libavcodec/wavpack.c @@ -480,7 +480,7 @@ static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb, } if (type == AV_SAMPLE_FMT_S16P) { - if (FFABS(L) + (unsigned)FFABS(R) > (1<<19)) { + if (FFABS((int64_t)L) + FFABS((int64_t)R) > (1<<19)) { av_log(s->avctx, AV_LOG_ERROR, "sample %d %d too large\n", L, R); return AVERROR_INVALIDDATA; } From 3caecf7ce8e9642cd17942e61f12803bbab52ad2 Mon Sep 17 00:00:00 2001 From: Muhammad Faiz Date: Sat, 3 Feb 2018 01:18:27 +0700 Subject: [PATCH 1791/2557] avcodec: do not use init_static_data on some codecs They don't modify AVCodec, no needs to call it at register. They will be wasteful if these codecs are unused. Instead, call static data initialization at codecs' init. Benchmark: old: 51281340 decicycles in avcodec_register_all, 1 runs, 0 skips new: 6738960 decicycles in avcodec_register_all, 1 runs, 0 skips Reviewed-by: wm4 Reviewed-by: Michael Niedermayer Signed-off-by: Muhammad Faiz --- libavcodec/jpeg2000dec.c | 16 +++++++++------- libavcodec/qdmc.c | 7 +++++-- libavcodec/wmavoice.c | 7 +++++-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 01fe4b3949330..4cf8a2880cab7 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -34,6 +34,7 @@ #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "bytestream.h" #include "internal.h" @@ -2142,10 +2143,18 @@ static int jp2_find_codestream(Jpeg2000DecoderContext *s) return 0; } +static av_cold void jpeg2000_init_static_data(void) +{ + ff_jpeg2000_init_tier1_luts(); + ff_mqc_init_context_tables(); +} + static av_cold int jpeg2000_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; Jpeg2000DecoderContext *s = avctx->priv_data; + ff_thread_once(&init_static_once, jpeg2000_init_static_data); ff_jpeg2000dsp_init(&s->dsp); return 0; @@ -2223,12 +2232,6 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data, return ret; } -static av_cold void jpeg2000_init_static_data(AVCodec *codec) -{ - ff_jpeg2000_init_tier1_luts(); - ff_mqc_init_context_tables(); -} - #define OFFSET(x) offsetof(Jpeg2000DecoderContext, x) #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM @@ -2252,7 +2255,6 @@ AVCodec ff_jpeg2000_decoder = { .id = AV_CODEC_ID_JPEG2000, .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_DR1, .priv_data_size = sizeof(Jpeg2000DecoderContext), - .init_static_data = jpeg2000_init_static_data, .init = jpeg2000_decode_init, .decode = jpeg2000_decode_frame, .priv_class = &jpeg2000_class, diff --git a/libavcodec/qdmc.c b/libavcodec/qdmc.c index 1c8952b97be40..f1f86accd831b 100644 --- a/libavcodec/qdmc.c +++ b/libavcodec/qdmc.c @@ -26,6 +26,7 @@ #define BITSTREAM_READER_LE #include "libavutil/channel_layout.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "bytestream.h" @@ -204,7 +205,7 @@ static const uint8_t phase_diff_codes[] = { INIT_VLC_LE | INIT_VLC_USE_NEW_STATIC); \ } while (0) -static av_cold void qdmc_init_static_data(AVCodec *codec) +static av_cold void qdmc_init_static_data(void) { int i; @@ -250,10 +251,13 @@ static void make_noises(QDMCContext *s) static av_cold int qdmc_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; QDMCContext *s = avctx->priv_data; int fft_size, fft_order, size, g, j, x; GetByteContext b; + ff_thread_once(&init_static_once, qdmc_init_static_data); + if (!avctx->extradata || (avctx->extradata_size < 48)) { av_log(avctx, AV_LOG_ERROR, "extradata missing or truncated\n"); return AVERROR_INVALIDDATA; @@ -775,7 +779,6 @@ AVCodec ff_qdmc_decoder = { .id = AV_CODEC_ID_QDMC, .priv_data_size = sizeof(QDMCContext), .init = qdmc_decode_init, - .init_static_data = qdmc_init_static_data, .close = qdmc_decode_close, .decode = qdmc_decode_frame, .flush = qdmc_flush, diff --git a/libavcodec/wmavoice.c b/libavcodec/wmavoice.c index 3f86d0da3578b..444e303b0df16 100644 --- a/libavcodec/wmavoice.c +++ b/libavcodec/wmavoice.c @@ -30,6 +30,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/float_dsp.h" #include "libavutil/mem.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "internal.h" #include "get_bits.h" @@ -310,7 +311,7 @@ static av_cold int decode_vbmtree(GetBitContext *gb, int8_t vbm_tree[25]) return 0; } -static av_cold void wmavoice_init_static_data(AVCodec *codec) +static av_cold void wmavoice_init_static_data(void) { static const uint8_t bits[] = { 2, 2, 2, 4, 4, 4, @@ -365,9 +366,12 @@ static av_cold void wmavoice_flush(AVCodecContext *ctx) */ static av_cold int wmavoice_decode_init(AVCodecContext *ctx) { + static AVOnce init_static_once = AV_ONCE_INIT; int n, flags, pitch_range, lsp16_flag; WMAVoiceContext *s = ctx->priv_data; + ff_thread_once(&init_static_once, wmavoice_init_static_data); + /** * Extradata layout: * - byte 0-18: WMAPro-in-WMAVoice extradata (see wmaprodec.c), @@ -1991,7 +1995,6 @@ AVCodec ff_wmavoice_decoder = { .id = AV_CODEC_ID_WMAVOICE, .priv_data_size = sizeof(WMAVoiceContext), .init = wmavoice_decode_init, - .init_static_data = wmavoice_init_static_data, .close = wmavoice_decode_end, .decode = wmavoice_decode_packet, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, From 0519e66a90f076591fb35dab1a3ed14204de08c0 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Thu, 11 Jan 2018 15:00:30 +0800 Subject: [PATCH 1792/2557] examples: Add a VA-API transcode example. Usage is: ./vaapi_transcode input_stream codec output_stream For example: - ./vaapi_transcode input.mp4 h264_vaapi output_h264.mp4 - ./vaapi_transcode input.mp4 vp8_vaapi output_vp8.ivf Does not handle resolution changes on the input stream. Signed-off-by: Jun Zhao Signed-off-by: Liu, Kaixuan Signed-off-by: Mark Thompson --- configure | 2 + doc/examples/Makefile | 1 + doc/examples/vaapi_transcode.c | 306 +++++++++++++++++++++++++++++++++ 3 files changed, 309 insertions(+) create mode 100644 doc/examples/vaapi_transcode.c diff --git a/configure b/configure index 0b01a221c798e..27113828c6a6f 100755 --- a/configure +++ b/configure @@ -1526,6 +1526,7 @@ EXAMPLE_LIST=" transcode_aac_example transcoding_example vaapi_encode_example + vaapi_transcode_example " EXTERNAL_AUTODETECT_LIBRARY_LIST=" @@ -3320,6 +3321,7 @@ scaling_video_example_deps="avutil swscale" transcode_aac_example_deps="avcodec avformat swresample" transcoding_example_deps="avfilter avcodec avformat avutil" vaapi_encode_example_deps="avcodec avutil h264_vaapi_encoder" +vaapi_transcode_example_deps="avcodec avformat avutil h264_vaapi_encoder" # EXTRALIBS_LIST cpu_init_extralibs="pthreads_extralibs" diff --git a/doc/examples/Makefile b/doc/examples/Makefile index da5af36532ba6..928ff306b356e 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -20,6 +20,7 @@ EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE) += scaling_video EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac EXAMPLES-$(CONFIG_TRANSCODING_EXAMPLE) += transcoding EXAMPLES-$(CONFIG_VAAPI_ENCODE_EXAMPLE) += vaapi_encode +EXAMPLES-$(CONFIG_VAAPI_TRANSCODE_EXAMPLE) += vaapi_transcode EXAMPLES := $(EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)$(EXESUF)) EXAMPLES_G := $(EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)_g$(EXESUF)) diff --git a/doc/examples/vaapi_transcode.c b/doc/examples/vaapi_transcode.c new file mode 100644 index 0000000000000..6318895af3307 --- /dev/null +++ b/doc/examples/vaapi_transcode.c @@ -0,0 +1,306 @@ +/* + * Video Acceleration API (video transcoding) transcode sample + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Intel VAAPI-accelerated transcoding example. + * + * @example vaapi_transcode.c + * This example shows how to do VAAPI-accelerated transcoding. + * Usage: vaapi_transcode input_stream codec output_stream + * e.g: - vaapi_transcode input.mp4 h264_vaapi output_h264.mp4 + * - vaapi_transcode input.mp4 vp9_vaapi output_vp9.ivf + */ + +#include +#include + +#include +#include +#include + +static AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL; +static AVBufferRef *hw_device_ctx = NULL; +static AVCodecContext *decoder_ctx = NULL, *encoder_ctx = NULL; +static int video_stream = -1; +static AVStream *ost; +static int initialized = 0; + +static enum AVPixelFormat get_vaapi_format(AVCodecContext *ctx, + const enum AVPixelFormat *pix_fmts) +{ + const enum AVPixelFormat *p; + + for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) { + if (*p == AV_PIX_FMT_VAAPI) + return *p; + } + + fprintf(stderr, "Unable to decode this file using VA-API.\n"); + return AV_PIX_FMT_NONE; +} + +static int open_input_file(const char *filename) +{ + int ret; + AVCodec *decoder = NULL; + AVStream *video = NULL; + + if ((ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL)) < 0) { + fprintf(stderr, "Cannot open input file '%s', Error code: %s\n", + filename, av_err2str(ret)); + return ret; + } + + if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) { + fprintf(stderr, "Cannot find input stream information. Error code: %s\n", + av_err2str(ret)); + return ret; + } + + ret = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0); + if (ret < 0) { + fprintf(stderr, "Cannot find a video stream in the input file. " + "Error code: %s\n", av_err2str(ret)); + return ret; + } + video_stream = ret; + + if (!(decoder_ctx = avcodec_alloc_context3(decoder))) + return AVERROR(ENOMEM); + + video = ifmt_ctx->streams[video_stream]; + if ((ret = avcodec_parameters_to_context(decoder_ctx, video->codecpar)) < 0) { + fprintf(stderr, "avcodec_parameters_to_context error. Error code: %s\n", + av_err2str(ret)); + return ret; + } + + decoder_ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx); + if (!decoder_ctx->hw_device_ctx) { + fprintf(stderr, "A hardware device reference create failed.\n"); + return AVERROR(ENOMEM); + } + decoder_ctx->get_format = get_vaapi_format; + + if ((ret = avcodec_open2(decoder_ctx, decoder, NULL)) < 0) + fprintf(stderr, "Failed to open codec for decoding. Error code: %s\n", + av_err2str(ret)); + + return ret; +} + +static int encode_write(AVFrame *frame) +{ + int ret = 0; + AVPacket enc_pkt; + + av_init_packet(&enc_pkt); + enc_pkt.data = NULL; + enc_pkt.size = 0; + + if ((ret = avcodec_send_frame(encoder_ctx, frame)) < 0) { + fprintf(stderr, "Error during encoding. Error code: %s\n", av_err2str(ret)); + goto end; + } + while (1) { + ret = avcodec_receive_packet(encoder_ctx, &enc_pkt); + if (ret) + break; + + enc_pkt.stream_index = 0; + av_packet_rescale_ts(&enc_pkt, ifmt_ctx->streams[video_stream]->time_base, + ofmt_ctx->streams[0]->time_base); + ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt); + if (ret < 0) { + fprintf(stderr, "Error during writing data to output file. " + "Error code: %s\n", av_err2str(ret)); + return -1; + } + } + +end: + if (ret == AVERROR_EOF) + return 0; + ret = ((ret == AVERROR(EAGAIN)) ? 0:-1); + return ret; +} + +static int dec_enc(AVPacket *pkt, AVCodec *enc_codec) +{ + AVFrame *frame; + int ret = 0; + + ret = avcodec_send_packet(decoder_ctx, pkt); + if (ret < 0) { + fprintf(stderr, "Error during decoding. Error code: %s\n", av_err2str(ret)); + return ret; + } + + while (ret >= 0) { + if (!(frame = av_frame_alloc())) + return AVERROR(ENOMEM); + + ret = avcodec_receive_frame(decoder_ctx, frame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + av_frame_free(&frame); + return 0; + } else if (ret < 0) { + fprintf(stderr, "Error while decoding. Error code: %s\n", av_err2str(ret)); + goto fail; + } + + if (!initialized) { + /* we need to ref hw_frames_ctx of decoder to initialize encoder's codec. + Only after we get a decoded frame, can we obtain its hw_frames_ctx */ + encoder_ctx->hw_frames_ctx = av_buffer_ref(decoder_ctx->hw_frames_ctx); + if (!encoder_ctx->hw_frames_ctx) { + ret = AVERROR(ENOMEM); + goto fail; + } + /* set AVCodecContext Parameters for encoder, here we keep them stay + * the same as decoder. + * xxx: now the the sample can't handle resolution change case. + */ + encoder_ctx->time_base = av_inv_q(decoder_ctx->framerate); + encoder_ctx->pix_fmt = AV_PIX_FMT_VAAPI; + encoder_ctx->width = decoder_ctx->width; + encoder_ctx->height = decoder_ctx->height; + + if ((ret = avcodec_open2(encoder_ctx, enc_codec, NULL)) < 0) { + fprintf(stderr, "Failed to open encode codec. Error code: %s\n", + av_err2str(ret)); + goto fail; + } + + if (!(ost = avformat_new_stream(ofmt_ctx, enc_codec))) { + fprintf(stderr, "Failed to allocate stream for output format.\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + + ost->time_base = encoder_ctx->time_base; + ret = avcodec_parameters_from_context(ost->codecpar, encoder_ctx); + if (ret < 0) { + fprintf(stderr, "Failed to copy the stream parameters. " + "Error code: %s\n", av_err2str(ret)); + goto fail; + } + + /* write the stream header */ + if ((ret = avformat_write_header(ofmt_ctx, NULL)) < 0) { + fprintf(stderr, "Error while writing stream header. " + "Error code: %s\n", av_err2str(ret)); + goto fail; + } + + initialized = 1; + } + + if ((ret = encode_write(frame)) < 0) + fprintf(stderr, "Error during encoding and writing.\n"); + +fail: + av_frame_free(&frame); + if (ret < 0) + return ret; + } + return 0; +} + +int main(int argc, char **argv) +{ + int ret = 0; + AVPacket dec_pkt; + AVCodec *enc_codec; + + if (argc != 4) { + fprintf(stderr, "Usage: %s \n" + "The output format is guessed according to the file extension.\n" + "\n", argv[0]); + return -1; + } + + av_register_all(); + + ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI, NULL, NULL, 0); + if (ret < 0) { + fprintf(stderr, "Failed to create a VAAPI device. Error code: %s\n", av_err2str(ret)); + return -1; + } + + if ((ret = open_input_file(argv[1])) < 0) + goto end; + + if (!(enc_codec = avcodec_find_encoder_by_name(argv[2]))) { + fprintf(stderr, "Could not find encoder '%s'\n", argv[2]); + ret = -1; + goto end; + } + + if ((ret = (avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, argv[3]))) < 0) { + fprintf(stderr, "Failed to deduce output format from file extension. Error code: " + "%s\n", av_err2str(ret)); + goto end; + } + + if (!(encoder_ctx = avcodec_alloc_context3(enc_codec))) { + ret = AVERROR(ENOMEM); + goto end; + } + + ret = avio_open(&ofmt_ctx->pb, argv[3], AVIO_FLAG_WRITE); + if (ret < 0) { + fprintf(stderr, "Cannot open output file. " + "Error code: %s\n", av_err2str(ret)); + goto end; + } + + /* read all packets and only transcoding video */ + while (ret >= 0) { + if ((ret = av_read_frame(ifmt_ctx, &dec_pkt)) < 0) + break; + + if (video_stream == dec_pkt.stream_index) + ret = dec_enc(&dec_pkt, enc_codec); + + av_packet_unref(&dec_pkt); + } + + /* flush decoder */ + dec_pkt.data = NULL; + dec_pkt.size = 0; + ret = dec_enc(&dec_pkt, enc_codec); + av_packet_unref(&dec_pkt); + + /* flush encoder */ + ret = encode_write(NULL); + + /* write the trailer for output stream */ + av_write_trailer(ofmt_ctx); + +end: + avformat_close_input(&ifmt_ctx); + avformat_close_input(&ofmt_ctx); + avcodec_free_context(&decoder_ctx); + avcodec_free_context(&encoder_ctx); + av_buffer_unref(&hw_device_ctx); + return ret; +} From 96e476cc9d414e248692c773d9dce736662572b8 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Sun, 19 Mar 2017 15:44:46 +0800 Subject: [PATCH 1793/2557] hwcontext: Fix documentation for av_hwdevice_ctx_alloc() From ffmpeg commit 9365dfcbf665b83b2e60c5ec5e2abf1f0a49e2c3. Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- libavutil/hwcontext.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h index 203ea510ec629..ba293d72e5816 100644 --- a/libavutil/hwcontext.h +++ b/libavutil/hwcontext.h @@ -252,8 +252,9 @@ const char *av_hwdevice_get_type_name(enum AVHWDeviceType type); enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev); /** - * Allocate an AVHWDeviceContext for a given pixel format. + * Allocate an AVHWDeviceContext for a given hardware type. * + * @param type the type of the hardware device to allocate. * @return a reference to the newly created AVHWDeviceContext on success or NULL * on failure. */ From 2eb396b175e55e515aa6a13c5b1789a2a18d3935 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Fri, 26 Jan 2018 23:12:18 +0000 Subject: [PATCH 1794/2557] hwcontext: Fix memory leak on derived frame allocation failure --- libavutil/hwcontext.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index 6dc95bba15988..2630087b5d4bb 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -470,8 +470,10 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags) ret = av_hwframe_get_buffer(ctx->internal->source_frames, src_frame, 0); - if (ret < 0) + if (ret < 0) { + av_frame_free(&src_frame); return ret; + } ret = av_hwframe_map(frame, src_frame, ctx->internal->source_allocation_map_flags); From ff46124b0df17a1d35249e09ae8eae9a61f16e04 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 25 Jan 2018 18:57:26 +0100 Subject: [PATCH 1795/2557] rtsp: rename certain options after a deprecation period The "timeout" option name inherently clashes with the meaning of the HTTP libavformat protocol option with the same name. Rename it after a deprecation period to make it compatible with the HTTP one. --- doc/APIchanges | 7 +++++++ libavformat/rtsp.c | 12 ++++++++++-- libavformat/version.h | 3 +++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 6185545d56c3b..b802f62d4da85 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,13 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-02-xx - xxxxxxx - lavf 58.8.100 - avformat.h + Deprecate the current names of the RTSP "timeout", "stimeout", "user-agent" + options. Introduce "listen_timeout" as replacement for the current "timeout" + option, and "user_agent" as replacement for "user-agent". Once the deprecation + is over, the old "timeout" option will be removed, and "stimeout" will be + renamed to "stimeout" (the "timeout" option will essentially change semantics). + 2018-01-xx - xxxxxxx - lavf 58.7.100 - avformat.h Deprecate AVFormatContext filename field which had limited length, use the new dynamically allocated url field instead. diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 89fc1e293c810..b3cfbb874f65e 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -93,10 +93,18 @@ const AVOption ff_rtsp_options[] = { RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"), { "min_port", "set minimum local UDP port", OFFSET(rtp_port_min), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MIN}, 0, 65535, DEC|ENC }, { "max_port", "set maximum local UDP port", OFFSET(rtp_port_max), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MAX}, 0, 65535, DEC|ENC }, - { "timeout", "set maximum timeout (in seconds) to wait for incoming connections (-1 is infinite, imply flag listen)", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC }, + { "listen_timeout", "set maximum timeout (in seconds) to wait for incoming connections (-1 is infinite, imply flag listen)", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC }, +#if FF_API_OLD_RTSP_OPTIONS + { "timeout", "set maximum timeout (in seconds) to wait for incoming connections (-1 is infinite, imply flag listen) (deprecated, use listen_timeout)", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC }, { "stimeout", "set timeout (in microseconds) of socket TCP I/O operations", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC }, +#else + { "timeout", "set timeout (in microseconds) of socket TCP I/O operations", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC }, +#endif COMMON_OPTS(), - { "user-agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC }, + { "user_agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC }, +#if FF_API_OLD_RTSP_OPTIONS + { "user-agent", "override User-Agent header (deprecated, use user_agent)", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC }, +#endif { NULL }, }; diff --git a/libavformat/version.h b/libavformat/version.h index 897be0c2fe9e2..a42ab7056dd63 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -88,6 +88,9 @@ #ifndef FF_API_FORMAT_FILENAME #define FF_API_FORMAT_FILENAME (LIBAVFORMAT_VERSION_MAJOR < 59) #endif +#ifndef FF_API_OLD_RTSP_OPTIONS +#define FF_API_OLD_RTSP_OPTIONS (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif #ifndef FF_API_R_FRAME_RATE From 48bc9fffd11c05e75b9125d8cd90e9263108bd83 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 30 Jan 2018 13:22:53 +0100 Subject: [PATCH 1796/2557] id3v2: fix unsynchronization The ID3v2 "unsynchronization scheme" requires replacing any 0xFF 0x00 sequences with 0xFF. This has to be done on every byte of the source data, while the current code skipped a byte after a replacement. This meant 0xFF 0x00 0xFF 00 was translated to 0xFF 0xFF 0x00 instead of 0xFF 0xFF. It feels a bit messy to do this correctly with the avio use. But fortunately, this translation can be done in-place, so we can just do it in memory. Inspired by what taglib does. Also see 9ae80e6a9cefcab61e867256ba19ef78a4bfe0cb. (The sample file for that commit is gone, so it could not be retested.) --- libavformat/id3v2.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index b80178d67a093..f7de26a1d8e54 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -976,19 +976,21 @@ static void id3v2_parse(AVIOContext *pb, AVDictionary **metadata, } } if (unsync || tunsync) { - int64_t end = avio_tell(pb) + tlen; - uint8_t *b; - - b = buffer; - while (avio_tell(pb) < end && b - buffer < tlen && !pb->eof_reached) { - *b++ = avio_r8(pb); - if (*(b - 1) == 0xff && avio_tell(pb) < end - 1 && - b - buffer < tlen && - !pb->eof_reached ) { - uint8_t val = avio_r8(pb); - *b++ = val ? val : avio_r8(pb); - } + uint8_t *b = buffer; + uint8_t *t = buffer; + uint8_t *end = t + tlen; + + if (avio_read(pb, buffer, tlen) != tlen) { + av_log(s, AV_LOG_ERROR, "Failed to read tag data\n"); + goto seek; } + + while (t != end) { + *b++ = *t++; + if (t != end && t[-1] == 0xff && !t[0]) + t++; + } + ffio_init_context(&pb_local, buffer, b - buffer, 0, NULL, NULL, NULL, NULL); tlen = b - buffer; From 118e1b0b3370dd1c0da442901b486689efd1654b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 2 Feb 2018 21:44:57 +0100 Subject: [PATCH 1797/2557] avcodec/utvideodec: Fix bytes left check in decode_frame() Fixes: out of array read Fixes: poc-2017.avi Found-by: GwanYeong Kim Signed-off-by: Michael Niedermayer --- libavcodec/utvideodec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 608c8c4998a15..1bcd14e74c69f 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -676,7 +676,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, for (j = 0; j < c->slices; j++) { slice_end = bytestream2_get_le32u(&gb); if (slice_end < 0 || slice_end < slice_start || - bytestream2_get_bytes_left(&gb) < slice_end) { + bytestream2_get_bytes_left(&gb) < slice_end + 1024LL) { av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n"); return AVERROR_INVALIDDATA; } From caa4bd7a9fe9186a56fdcb8194263b066978cbbe Mon Sep 17 00:00:00 2001 From: Muhammad Faiz Date: Sun, 4 Feb 2018 05:44:23 +0700 Subject: [PATCH 1798/2557] avcodec/me_cmp: remove ff_me_cmp_init_static() Precalculate and constify ff_square_tab. Reviewed-by: James Almer Signed-off-by: Muhammad Faiz --- libavcodec/me_cmp.c | 50 +++++++++++++++++++++++++++--------- libavcodec/me_cmp.h | 4 +-- libavcodec/mpegvideo_enc.c | 2 +- libavcodec/mpegvideoencdsp.c | 2 +- libavcodec/snowenc.c | 2 +- libavcodec/utils.c | 13 ---------- 6 files changed, 42 insertions(+), 31 deletions(-) diff --git a/libavcodec/me_cmp.c b/libavcodec/me_cmp.c index 5e34a11593da3..465d3ccb2af16 100644 --- a/libavcodec/me_cmp.c +++ b/libavcodec/me_cmp.c @@ -29,13 +29,47 @@ #include "mpegvideo.h" #include "config.h" -uint32_t ff_square_tab[512] = { 0, }; +/* (i - 256) * (i - 256) */ +const uint32_t ff_square_tab[512] = { + 65536, 65025, 64516, 64009, 63504, 63001, 62500, 62001, 61504, 61009, 60516, 60025, 59536, 59049, 58564, 58081, + 57600, 57121, 56644, 56169, 55696, 55225, 54756, 54289, 53824, 53361, 52900, 52441, 51984, 51529, 51076, 50625, + 50176, 49729, 49284, 48841, 48400, 47961, 47524, 47089, 46656, 46225, 45796, 45369, 44944, 44521, 44100, 43681, + 43264, 42849, 42436, 42025, 41616, 41209, 40804, 40401, 40000, 39601, 39204, 38809, 38416, 38025, 37636, 37249, + 36864, 36481, 36100, 35721, 35344, 34969, 34596, 34225, 33856, 33489, 33124, 32761, 32400, 32041, 31684, 31329, + 30976, 30625, 30276, 29929, 29584, 29241, 28900, 28561, 28224, 27889, 27556, 27225, 26896, 26569, 26244, 25921, + 25600, 25281, 24964, 24649, 24336, 24025, 23716, 23409, 23104, 22801, 22500, 22201, 21904, 21609, 21316, 21025, + 20736, 20449, 20164, 19881, 19600, 19321, 19044, 18769, 18496, 18225, 17956, 17689, 17424, 17161, 16900, 16641, + 16384, 16129, 15876, 15625, 15376, 15129, 14884, 14641, 14400, 14161, 13924, 13689, 13456, 13225, 12996, 12769, + 12544, 12321, 12100, 11881, 11664, 11449, 11236, 11025, 10816, 10609, 10404, 10201, 10000, 9801, 9604, 9409, + 9216, 9025, 8836, 8649, 8464, 8281, 8100, 7921, 7744, 7569, 7396, 7225, 7056, 6889, 6724, 6561, + 6400, 6241, 6084, 5929, 5776, 5625, 5476, 5329, 5184, 5041, 4900, 4761, 4624, 4489, 4356, 4225, + 4096, 3969, 3844, 3721, 3600, 3481, 3364, 3249, 3136, 3025, 2916, 2809, 2704, 2601, 2500, 2401, + 2304, 2209, 2116, 2025, 1936, 1849, 1764, 1681, 1600, 1521, 1444, 1369, 1296, 1225, 1156, 1089, + 1024, 961, 900, 841, 784, 729, 676, 625, 576, 529, 484, 441, 400, 361, 324, 289, + 256, 225, 196, 169, 144, 121, 100, 81, 64, 49, 36, 25, 16, 9, 4, 1, + 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, + 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, + 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, + 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969, + 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, + 6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281, 8464, 8649, 8836, 9025, + 9216, 9409, 9604, 9801, 10000, 10201, 10404, 10609, 10816, 11025, 11236, 11449, 11664, 11881, 12100, 12321, + 12544, 12769, 12996, 13225, 13456, 13689, 13924, 14161, 14400, 14641, 14884, 15129, 15376, 15625, 15876, 16129, + 16384, 16641, 16900, 17161, 17424, 17689, 17956, 18225, 18496, 18769, 19044, 19321, 19600, 19881, 20164, 20449, + 20736, 21025, 21316, 21609, 21904, 22201, 22500, 22801, 23104, 23409, 23716, 24025, 24336, 24649, 24964, 25281, + 25600, 25921, 26244, 26569, 26896, 27225, 27556, 27889, 28224, 28561, 28900, 29241, 29584, 29929, 30276, 30625, + 30976, 31329, 31684, 32041, 32400, 32761, 33124, 33489, 33856, 34225, 34596, 34969, 35344, 35721, 36100, 36481, + 36864, 37249, 37636, 38025, 38416, 38809, 39204, 39601, 40000, 40401, 40804, 41209, 41616, 42025, 42436, 42849, + 43264, 43681, 44100, 44521, 44944, 45369, 45796, 46225, 46656, 47089, 47524, 47961, 48400, 48841, 49284, 49729, + 50176, 50625, 51076, 51529, 51984, 52441, 52900, 53361, 53824, 54289, 54756, 55225, 55696, 56169, 56644, 57121, + 57600, 58081, 58564, 59049, 59536, 60025, 60516, 61009, 61504, 62001, 62500, 63001, 63504, 64009, 64516, 65025, +}; static int sse4_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t stride, int h) { int s = 0, i; - uint32_t *sq = ff_square_tab + 256; + const uint32_t *sq = ff_square_tab + 256; for (i = 0; i < h; i++) { s += sq[pix1[0] - pix2[0]]; @@ -52,7 +86,7 @@ static int sse8_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t stride, int h) { int s = 0, i; - uint32_t *sq = ff_square_tab + 256; + const uint32_t *sq = ff_square_tab + 256; for (i = 0; i < h; i++) { s += sq[pix1[0] - pix2[0]]; @@ -73,7 +107,7 @@ static int sse16_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t stride, int h) { int s = 0, i; - uint32_t *sq = ff_square_tab + 256; + const uint32_t *sq = ff_square_tab + 256; for (i = 0; i < h; i++) { s += sq[pix1[0] - pix2[0]]; @@ -977,14 +1011,6 @@ WRAPPER8_16_SQ(quant_psnr8x8_c, quant_psnr16_c) WRAPPER8_16_SQ(rd8x8_c, rd16_c) WRAPPER8_16_SQ(bit8x8_c, bit16_c) -av_cold void ff_me_cmp_init_static(void) -{ - int i; - - for (i = 0; i < 512; i++) - ff_square_tab[i] = (i - 256) * (i - 256); -} - int ff_check_alignment(void) { static int did_fail = 0; diff --git a/libavcodec/me_cmp.h b/libavcodec/me_cmp.h index 0dbbcbb1d9a58..0a589e3c3da1d 100644 --- a/libavcodec/me_cmp.h +++ b/libavcodec/me_cmp.h @@ -23,7 +23,7 @@ #include "avcodec.h" -extern uint32_t ff_square_tab[512]; +extern const uint32_t ff_square_tab[512]; /* minimum alignment rules ;) @@ -79,8 +79,6 @@ typedef struct MECmpContext { me_cmp_func median_sad[6]; } MECmpContext; -void ff_me_cmp_init_static(void); - int ff_check_alignment(void); void ff_me_cmp_init(MECmpContext *c, AVCodecContext *avctx); diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index f1f4989231d4a..979e138b8895c 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -2713,7 +2713,7 @@ static inline void encode_mb_hq(MpegEncContext *s, MpegEncContext *backup, MpegE } static int sse(MpegEncContext *s, uint8_t *src1, uint8_t *src2, int w, int h, int stride){ - uint32_t *sq = ff_square_tab + 256; + const uint32_t *sq = ff_square_tab + 256; int acc=0; int x,y; diff --git a/libavcodec/mpegvideoencdsp.c b/libavcodec/mpegvideoencdsp.c index 0af3d8bef8b8a..a34ab3553e37a 100644 --- a/libavcodec/mpegvideoencdsp.c +++ b/libavcodec/mpegvideoencdsp.c @@ -81,7 +81,7 @@ static int pix_sum_c(uint8_t *pix, int line_size) static int pix_norm1_c(uint8_t *pix, int line_size) { int s = 0, i, j; - uint32_t *sq = ff_square_tab + 256; + const uint32_t *sq = ff_square_tab + 256; for (i = 0; i < 16; i++) { for (j = 0; j < 16; j += 8) { diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 4fec377591136..61a658fa4401a 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -179,7 +179,7 @@ static int pix_sum(uint8_t * pix, int line_size, int w, int h) static int pix_norm1(uint8_t * pix, int line_size, int w) { int s, i, j; - uint32_t *sq = ff_square_tab + 256; + const uint32_t *sq = ff_square_tab + 256; s = 0; for (i = 0; i < w; i++) { diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 4c718432ad06c..aefe6315902d6 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -104,18 +104,6 @@ AVCodec *av_codec_next(const AVCodec *c) return first_avcodec; } -static av_cold void avcodec_init(void) -{ - static int initialized = 0; - - if (initialized != 0) - return; - initialized = 1; - - if (CONFIG_ME_CMP) - ff_me_cmp_init_static(); -} - int av_codec_is_encoder(const AVCodec *codec) { return codec && (codec->encode_sub || codec->encode2 ||codec->send_frame); @@ -131,7 +119,6 @@ static AVMutex codec_register_mutex = AV_MUTEX_INITIALIZER; av_cold void avcodec_register(AVCodec *codec) { AVCodec **p; - avcodec_init(); ff_mutex_lock(&codec_register_mutex); p = last_avcodec; From bca41545b371efc34e38d1fa8bb12dba8b614da0 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 5 Feb 2018 13:53:49 +0100 Subject: [PATCH 1799/2557] configure: Group code that sets the license string with licensing checks This also moves the setting of the licensing string out of a block that is skipped when quiet operation is requested. --- configure | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 593064f8788df..9f84f880140c7 100755 --- a/configure +++ b/configure @@ -2881,6 +2881,18 @@ map "die_license_disabled version3" $EXTERNAL_LIBRARY_VERSION3_LIST enabled version3 && { enabled gpl && enable gplv3 || enable lgplv3; } +if enabled nonfree; then + license="nonfree and unredistributable" +elif enabled gplv3; then + license="GPL version 3 or later" +elif enabled lgplv3; then + license="LGPL version 3 or later" +elif enabled gpl; then + license="GPL version 2 or later" +else + license="LGPL version 2.1 or later" +fi + enabled_all gnutls openssl && die "GnuTLS and OpenSSL must not be enabled at the same time." @@ -5170,17 +5182,6 @@ if test -n "$ignore_tests"; then echo fi -license="LGPL version 2.1 or later" -if enabled nonfree; then - license="nonfree and unredistributable" -elif enabled gplv3; then - license="GPL version 3 or later" -elif enabled lgplv3; then - license="LGPL version 3 or later" -elif enabled gpl; then - license="GPL version 2 or later" -fi - echo "License: $license" fi # test "$quiet" != "yes" From 4cf84e254ae75b524e1cacae499a97d7cc9e5906 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 3 Nov 2017 17:20:49 +0100 Subject: [PATCH 1800/2557] Drop some unnecessary config.h #includes --- libavcodec/thread.h | 1 - libavformat/tls.h | 4 ++-- libavutil/aarch64/cpu.h | 1 - libavutil/arm/cpu.h | 1 - libavutil/cpu_internal.h | 2 ++ libavutil/ppc/cpu.h | 1 - libavutil/x86/cpu.h | 1 - 7 files changed, 4 insertions(+), 7 deletions(-) diff --git a/libavcodec/thread.h b/libavcodec/thread.h index 864e67eb98b45..b06958de804f2 100644 --- a/libavcodec/thread.h +++ b/libavcodec/thread.h @@ -29,7 +29,6 @@ #include "libavutil/buffer.h" -#include "config.h" #include "avcodec.h" typedef struct ThreadFrame { diff --git a/libavformat/tls.h b/libavformat/tls.h index 94f30ab854bc1..846aa8333e66c 100644 --- a/libavformat/tls.h +++ b/libavformat/tls.h @@ -22,10 +22,10 @@ #ifndef AVFORMAT_TLS_H #define AVFORMAT_TLS_H -#include "config.h" -#include "url.h" #include "libavutil/opt.h" +#include "url.h" + typedef struct TLSShared { char *ca_file; int verify; diff --git a/libavutil/aarch64/cpu.h b/libavutil/aarch64/cpu.h index f5b1d8913260d..0f2531b0dcd35 100644 --- a/libavutil/aarch64/cpu.h +++ b/libavutil/aarch64/cpu.h @@ -19,7 +19,6 @@ #ifndef AVUTIL_AARCH64_CPU_H #define AVUTIL_AARCH64_CPU_H -#include "config.h" #include "libavutil/cpu.h" #include "libavutil/cpu_internal.h" diff --git a/libavutil/arm/cpu.h b/libavutil/arm/cpu.h index 127993e5ddb5f..99986d908bd17 100644 --- a/libavutil/arm/cpu.h +++ b/libavutil/arm/cpu.h @@ -19,7 +19,6 @@ #ifndef AVUTIL_ARM_CPU_H #define AVUTIL_ARM_CPU_H -#include "config.h" #include "libavutil/cpu.h" #include "libavutil/cpu_internal.h" diff --git a/libavutil/cpu_internal.h b/libavutil/cpu_internal.h index 18c744a9837b4..4c5e1308aa521 100644 --- a/libavutil/cpu_internal.h +++ b/libavutil/cpu_internal.h @@ -19,6 +19,8 @@ #ifndef AVUTIL_CPU_INTERNAL_H #define AVUTIL_CPU_INTERNAL_H +#include "config.h" + #include "cpu.h" #define CPUEXT_SUFFIX(flags, suffix, cpuext) \ diff --git a/libavutil/ppc/cpu.h b/libavutil/ppc/cpu.h index a8b823f534b1c..bed687125edc0 100644 --- a/libavutil/ppc/cpu.h +++ b/libavutil/ppc/cpu.h @@ -19,7 +19,6 @@ #ifndef AVUTIL_PPC_CPU_H #define AVUTIL_PPC_CPU_H -#include "config.h" #include "libavutil/cpu.h" #include "libavutil/cpu_internal.h" diff --git a/libavutil/x86/cpu.h b/libavutil/x86/cpu.h index c0a525dd4e137..6373e57db2013 100644 --- a/libavutil/x86/cpu.h +++ b/libavutil/x86/cpu.h @@ -19,7 +19,6 @@ #ifndef AVUTIL_X86_CPU_H #define AVUTIL_X86_CPU_H -#include "config.h" #include "libavutil/cpu.h" #include "libavutil/cpu_internal.h" From 38434a9ff5b9a1a048f32c1c7e2a9519cf12f8ba Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 10 Nov 2017 15:40:30 +0100 Subject: [PATCH 1801/2557] configure: Simplify restrict keyword handling Skip a variable indirection and only redefine restrict if necessary. --- configure | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/configure b/configure index 9f84f880140c7..b4c6320f7a328 100755 --- a/configure +++ b/configure @@ -4144,9 +4144,8 @@ extern_prefix=${sym%%ff_extern*} ! disabled inline_asm && check_inline_asm inline_asm '"" ::' -_restrict= -for restrict_keyword in restrict __restrict__ __restrict; do - check_cc < $TMPH <> $TMPH + test -n "$malloc_prefix" && echo "#define MALLOC_PREFIX $malloc_prefix" >>$TMPH From fd36cf6bf6524247a8ff6788c028836fe7d9fd20 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 20 Oct 2017 04:42:13 +0200 Subject: [PATCH 1802/2557] configure: Factorize check_64_bit() --- configure | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/configure b/configure index b4c6320f7a328..ed930e6cd461c 100755 --- a/configure +++ b/configure @@ -3773,7 +3773,7 @@ check_host_cflags $host_cflags_speed check_64bit(){ arch32=$1 arch64=$2 - expr=$3 + expr=${3:-'sizeof(void *) > 4'} check_code cc "" "int test[2*($expr) - 1]" && subarch=$arch64 || subarch=$arch32 enable $subarch @@ -3788,23 +3788,23 @@ case "$arch" in enabled shared && enable_weak pic ;; parisc) - check_64bit parisc parisc64 'sizeof(void *) > 4' + check_64bit parisc parisc64 enabled shared && enable_weak pic ;; ppc) - check_64bit ppc ppc64 'sizeof(void *) > 4' + check_64bit ppc ppc64 enabled shared && enable_weak pic ;; s390) - check_64bit s390 s390x 'sizeof(void *) > 4' + check_64bit s390 s390x enabled shared && enable_weak pic ;; sparc) - check_64bit sparc sparc64 'sizeof(void *) > 4' + check_64bit sparc sparc64 enabled shared && enable_weak pic ;; x86) - check_64bit x86_32 x86_64 'sizeof(void *) > 4' + check_64bit x86_32 x86_64 if enabled x86_64; then enabled shared && enable_weak pic objformat=elf64 From 7e8eba2d8755962d9dca5eade57bf8f591a73c0c Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Fri, 22 Dec 2017 22:17:00 +0000 Subject: [PATCH 1803/2557] lavc: add new API for iterating codecs and codec parsers Based on an unfinished patch by atomnuker. --- Makefile | 3 +- configure | 12 +- doc/APIchanges | 4 + libavcodec/.gitignore | 2 + libavcodec/allcodecs.c | 1466 +++++++++++++++++++++++----------------- libavcodec/avcodec.h | 31 + libavcodec/parser.c | 84 ++- libavcodec/utils.c | 99 --- libavcodec/version.h | 3 + 9 files changed, 966 insertions(+), 738 deletions(-) diff --git a/Makefile b/Makefile index 9defddebfdaed..1d1c8865bc635 100644 --- a/Makefile +++ b/Makefile @@ -142,7 +142,8 @@ distclean:: clean $(RM) .version avversion.h config.asm config.h mapfile \ ffbuild/.config ffbuild/config.* libavutil/avconfig.h \ version.h libavutil/ffversion.h libavcodec/codec_names.h \ - libavcodec/bsf_list.c libavformat/protocol_list.c + libavcodec/bsf_list.c libavformat/protocol_list.c \ + libavcodec/codec_list.c libavcodec/parser_list.c ifeq ($(SRC_LINK),src) $(RM) src endif diff --git a/configure b/configure index 27113828c6a6f..86c74d7c2c151 100755 --- a/configure +++ b/configure @@ -3525,9 +3525,6 @@ find_things(){ sed -n "s/^[^#]*$pattern.*([^,]*, *\([^,]*\)\(,.*\)*).*/\1_$thing/p" "$file" } -ENCODER_LIST=$(find_things encoder ENC libavcodec/allcodecs.c) -DECODER_LIST=$(find_things decoder DEC libavcodec/allcodecs.c) -PARSER_LIST=$(find_things parser PARSER libavcodec/allcodecs.c) MUXER_LIST=$(find_things muxer _MUX libavformat/allformats.c) DEMUXER_LIST=$(find_things demuxer DEMUX libavformat/allformats.c) OUTDEV_LIST=$(find_things outdev OUTDEV libavdevice/alldevices.c) @@ -3541,6 +3538,13 @@ find_things_extern(){ sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" "$file" } +ENCODER_LIST=$(find_things_extern encoder AVCodec libavcodec/allcodecs.c) +DECODER_LIST=$(find_things_extern decoder AVCodec libavcodec/allcodecs.c) +CODEC_LIST=" + $ENCODER_LIST + $DECODER_LIST +" +PARSER_LIST=$(find_things_extern parser AVCodecParser libavcodec/parser.c) BSF_LIST=$(find_things_extern bsf AVBitStreamFilter libavcodec/bitstream_filters.c) HWACCEL_LIST=$(find_things_extern hwaccel AVHWAccel libavcodec/hwaccels.h) PROTOCOL_LIST=$(find_things_extern protocol URLProtocol libavformat/protocols.c) @@ -7029,6 +7033,8 @@ print_enabled_components(){ cp_if_changed $TMPH $file } +print_enabled_components libavcodec/codec_list.c AVCodec codec_list $CODEC_LIST +print_enabled_components libavcodec/parser_list.c AVCodecParser parser_list $PARSER_LIST print_enabled_components libavcodec/bsf_list.c AVBitStreamFilter bitstream_filters $BSF_LIST print_enabled_components libavformat/protocol_list.c URLProtocol url_protocols $PROTOCOL_LIST diff --git a/doc/APIchanges b/doc/APIchanges index b802f62d4da85..bb49fd5f2479f 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-01-xx - xxxxxxx - lavc 58.9.100 - avcodec.h + Deprecate use of avcodec_register(), avcodec_register_all(), and + av_codec_next(). Add av_codec_iterate(). + 2018-02-xx - xxxxxxx - lavf 58.8.100 - avformat.h Deprecate the current names of the RTSP "timeout", "stimeout", "user-agent" options. Introduce "listen_timeout" as replacement for the current "timeout" diff --git a/libavcodec/.gitignore b/libavcodec/.gitignore index 77a2ab1bd8075..28814f72331a6 100644 --- a/libavcodec/.gitignore +++ b/libavcodec/.gitignore @@ -2,3 +2,5 @@ /*_tables.c /*_tables.h /bsf_list.c +/codec_list.c +/parser_list.c diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index ed1e7ab06e5ce..268df243f7a4a 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -29,641 +29,857 @@ #include "avcodec.h" #include "version.h" -#define REGISTER_ENCODER(X, x) \ - { \ - extern AVCodec ff_##x##_encoder; \ - if (CONFIG_##X##_ENCODER) \ - avcodec_register(&ff_##x##_encoder); \ - } +extern AVCodec ff_a64multi_encoder; +extern AVCodec ff_a64multi5_encoder; +extern AVCodec ff_aasc_decoder; +extern AVCodec ff_aic_decoder; +extern AVCodec ff_alias_pix_encoder; +extern AVCodec ff_alias_pix_decoder; +extern AVCodec ff_amv_encoder; +extern AVCodec ff_amv_decoder; +extern AVCodec ff_anm_decoder; +extern AVCodec ff_ansi_decoder; +extern AVCodec ff_apng_encoder; +extern AVCodec ff_apng_decoder; +extern AVCodec ff_asv1_encoder; +extern AVCodec ff_asv1_decoder; +extern AVCodec ff_asv2_encoder; +extern AVCodec ff_asv2_decoder; +extern AVCodec ff_aura_decoder; +extern AVCodec ff_aura2_decoder; +extern AVCodec ff_avrp_encoder; +extern AVCodec ff_avrp_decoder; +extern AVCodec ff_avrn_decoder; +extern AVCodec ff_avs_decoder; +extern AVCodec ff_avui_encoder; +extern AVCodec ff_avui_decoder; +extern AVCodec ff_ayuv_encoder; +extern AVCodec ff_ayuv_decoder; +extern AVCodec ff_bethsoftvid_decoder; +extern AVCodec ff_bfi_decoder; +extern AVCodec ff_bink_decoder; +extern AVCodec ff_bmp_encoder; +extern AVCodec ff_bmp_decoder; +extern AVCodec ff_bmv_video_decoder; +extern AVCodec ff_brender_pix_decoder; +extern AVCodec ff_c93_decoder; +extern AVCodec ff_cavs_decoder; +extern AVCodec ff_cdgraphics_decoder; +extern AVCodec ff_cdxl_decoder; +extern AVCodec ff_cfhd_decoder; +extern AVCodec ff_cinepak_encoder; +extern AVCodec ff_cinepak_decoder; +extern AVCodec ff_clearvideo_decoder; +extern AVCodec ff_cljr_encoder; +extern AVCodec ff_cljr_decoder; +extern AVCodec ff_cllc_decoder; +extern AVCodec ff_comfortnoise_encoder; +extern AVCodec ff_comfortnoise_decoder; +extern AVCodec ff_cpia_decoder; +extern AVCodec ff_cscd_decoder; +extern AVCodec ff_cyuv_decoder; +extern AVCodec ff_dds_decoder; +extern AVCodec ff_dfa_decoder; +extern AVCodec ff_dirac_decoder; +extern AVCodec ff_dnxhd_encoder; +extern AVCodec ff_dnxhd_decoder; +extern AVCodec ff_dpx_encoder; +extern AVCodec ff_dpx_decoder; +extern AVCodec ff_dsicinvideo_decoder; +extern AVCodec ff_dvaudio_decoder; +extern AVCodec ff_dvvideo_encoder; +extern AVCodec ff_dvvideo_decoder; +extern AVCodec ff_dxa_decoder; +extern AVCodec ff_dxtory_decoder; +extern AVCodec ff_dxv_decoder; +extern AVCodec ff_eacmv_decoder; +extern AVCodec ff_eamad_decoder; +extern AVCodec ff_eatgq_decoder; +extern AVCodec ff_eatgv_decoder; +extern AVCodec ff_eatqi_decoder; +extern AVCodec ff_eightbps_decoder; +extern AVCodec ff_eightsvx_exp_decoder; +extern AVCodec ff_eightsvx_fib_decoder; +extern AVCodec ff_escape124_decoder; +extern AVCodec ff_escape130_decoder; +extern AVCodec ff_exr_decoder; +extern AVCodec ff_ffv1_encoder; +extern AVCodec ff_ffv1_decoder; +extern AVCodec ff_ffvhuff_encoder; +extern AVCodec ff_ffvhuff_decoder; +extern AVCodec ff_fic_decoder; +extern AVCodec ff_fits_encoder; +extern AVCodec ff_fits_decoder; +extern AVCodec ff_flashsv_encoder; +extern AVCodec ff_flashsv_decoder; +extern AVCodec ff_flashsv2_encoder; +extern AVCodec ff_flashsv2_decoder; +extern AVCodec ff_flic_decoder; +extern AVCodec ff_flv_encoder; +extern AVCodec ff_flv_decoder; +extern AVCodec ff_fmvc_decoder; +extern AVCodec ff_fourxm_decoder; +extern AVCodec ff_fraps_decoder; +extern AVCodec ff_frwu_decoder; +extern AVCodec ff_g2m_decoder; +extern AVCodec ff_gdv_decoder; +extern AVCodec ff_gif_encoder; +extern AVCodec ff_gif_decoder; +extern AVCodec ff_h261_encoder; +extern AVCodec ff_h261_decoder; +extern AVCodec ff_h263_encoder; +extern AVCodec ff_h263_decoder; +extern AVCodec ff_h263i_decoder; +extern AVCodec ff_h263p_encoder; +extern AVCodec ff_h263p_decoder; +extern AVCodec ff_h263_v4l2m2m_decoder; +extern AVCodec ff_h264_decoder; +extern AVCodec ff_h264_crystalhd_decoder; +extern AVCodec ff_h264_v4l2m2m_decoder; +extern AVCodec ff_h264_mediacodec_decoder; +extern AVCodec ff_h264_mmal_decoder; +extern AVCodec ff_h264_qsv_decoder; +extern AVCodec ff_h264_rkmpp_decoder; +extern AVCodec ff_hap_encoder; +extern AVCodec ff_hap_decoder; +extern AVCodec ff_hevc_decoder; +extern AVCodec ff_hevc_qsv_decoder; +extern AVCodec ff_hevc_rkmpp_decoder; +extern AVCodec ff_hevc_v4l2m2m_decoder; +extern AVCodec ff_hnm4_video_decoder; +extern AVCodec ff_hq_hqa_decoder; +extern AVCodec ff_hqx_decoder; +extern AVCodec ff_huffyuv_encoder; +extern AVCodec ff_huffyuv_decoder; +extern AVCodec ff_idcin_decoder; +extern AVCodec ff_iff_ilbm_decoder; +extern AVCodec ff_indeo2_decoder; +extern AVCodec ff_indeo3_decoder; +extern AVCodec ff_indeo4_decoder; +extern AVCodec ff_indeo5_decoder; +extern AVCodec ff_interplay_video_decoder; +extern AVCodec ff_jpeg2000_encoder; +extern AVCodec ff_jpeg2000_decoder; +extern AVCodec ff_jpegls_encoder; +extern AVCodec ff_jpegls_decoder; +extern AVCodec ff_jv_decoder; +extern AVCodec ff_kgv1_decoder; +extern AVCodec ff_kmvc_decoder; +extern AVCodec ff_lagarith_decoder; +extern AVCodec ff_ljpeg_encoder; +extern AVCodec ff_loco_decoder; +extern AVCodec ff_m101_decoder; +extern AVCodec ff_magicyuv_encoder; +extern AVCodec ff_magicyuv_decoder; +extern AVCodec ff_mdec_decoder; +extern AVCodec ff_mimic_decoder; +extern AVCodec ff_mjpeg_encoder; +extern AVCodec ff_mjpeg_decoder; +extern AVCodec ff_mjpegb_decoder; +extern AVCodec ff_mmvideo_decoder; +extern AVCodec ff_motionpixels_decoder; +extern AVCodec ff_mpeg1video_encoder; +extern AVCodec ff_mpeg1video_decoder; +extern AVCodec ff_mpeg2video_encoder; +extern AVCodec ff_mpeg2video_decoder; +extern AVCodec ff_mpeg4_encoder; +extern AVCodec ff_mpeg4_decoder; +extern AVCodec ff_mpeg4_crystalhd_decoder; +extern AVCodec ff_mpeg4_v4l2m2m_decoder; +extern AVCodec ff_mpeg4_mmal_decoder; +extern AVCodec ff_mpegvideo_decoder; +extern AVCodec ff_mpeg1_v4l2m2m_decoder; +extern AVCodec ff_mpeg2_mmal_decoder; +extern AVCodec ff_mpeg2_crystalhd_decoder; +extern AVCodec ff_mpeg2_v4l2m2m_decoder; +extern AVCodec ff_mpeg2_qsv_decoder; +extern AVCodec ff_mpeg2_mediacodec_decoder; +extern AVCodec ff_msa1_decoder; +extern AVCodec ff_mscc_decoder; +extern AVCodec ff_msmpeg4v1_decoder; +extern AVCodec ff_msmpeg4v2_encoder; +extern AVCodec ff_msmpeg4v2_decoder; +extern AVCodec ff_msmpeg4v3_encoder; +extern AVCodec ff_msmpeg4v3_decoder; +extern AVCodec ff_msmpeg4_crystalhd_decoder; +extern AVCodec ff_msrle_decoder; +extern AVCodec ff_mss1_decoder; +extern AVCodec ff_mss2_decoder; +extern AVCodec ff_msvideo1_encoder; +extern AVCodec ff_msvideo1_decoder; +extern AVCodec ff_mszh_decoder; +extern AVCodec ff_mts2_decoder; +extern AVCodec ff_mvc1_decoder; +extern AVCodec ff_mvc2_decoder; +extern AVCodec ff_mxpeg_decoder; +extern AVCodec ff_nuv_decoder; +extern AVCodec ff_paf_video_decoder; +extern AVCodec ff_pam_encoder; +extern AVCodec ff_pam_decoder; +extern AVCodec ff_pbm_encoder; +extern AVCodec ff_pbm_decoder; +extern AVCodec ff_pcx_encoder; +extern AVCodec ff_pcx_decoder; +extern AVCodec ff_pgm_encoder; +extern AVCodec ff_pgm_decoder; +extern AVCodec ff_pgmyuv_encoder; +extern AVCodec ff_pgmyuv_decoder; +extern AVCodec ff_pictor_decoder; +extern AVCodec ff_pixlet_decoder; +extern AVCodec ff_png_encoder; +extern AVCodec ff_png_decoder; +extern AVCodec ff_ppm_encoder; +extern AVCodec ff_ppm_decoder; +extern AVCodec ff_prores_encoder; +extern AVCodec ff_prores_decoder; +extern AVCodec ff_prores_aw_encoder; +extern AVCodec ff_prores_ks_encoder; +extern AVCodec ff_prores_lgpl_decoder; +extern AVCodec ff_psd_decoder; +extern AVCodec ff_ptx_decoder; +extern AVCodec ff_qdraw_decoder; +extern AVCodec ff_qpeg_decoder; +extern AVCodec ff_qtrle_encoder; +extern AVCodec ff_qtrle_decoder; +extern AVCodec ff_r10k_encoder; +extern AVCodec ff_r10k_decoder; +extern AVCodec ff_r210_encoder; +extern AVCodec ff_r210_decoder; +extern AVCodec ff_rawvideo_encoder; +extern AVCodec ff_rawvideo_decoder; +extern AVCodec ff_rl2_decoder; +extern AVCodec ff_roq_encoder; +extern AVCodec ff_roq_decoder; +extern AVCodec ff_rpza_decoder; +extern AVCodec ff_rscc_decoder; +extern AVCodec ff_rv10_encoder; +extern AVCodec ff_rv10_decoder; +extern AVCodec ff_rv20_encoder; +extern AVCodec ff_rv20_decoder; +extern AVCodec ff_rv30_decoder; +extern AVCodec ff_rv40_decoder; +extern AVCodec ff_s302m_encoder; +extern AVCodec ff_s302m_decoder; +extern AVCodec ff_sanm_decoder; +extern AVCodec ff_scpr_decoder; +extern AVCodec ff_screenpresso_decoder; +extern AVCodec ff_sdx2_dpcm_decoder; +extern AVCodec ff_sgi_encoder; +extern AVCodec ff_sgi_decoder; +extern AVCodec ff_sgirle_decoder; +extern AVCodec ff_sheervideo_decoder; +extern AVCodec ff_smacker_decoder; +extern AVCodec ff_smc_decoder; +extern AVCodec ff_smvjpeg_decoder; +extern AVCodec ff_snow_encoder; +extern AVCodec ff_snow_decoder; +extern AVCodec ff_sp5x_decoder; +extern AVCodec ff_speedhq_decoder; +extern AVCodec ff_srgc_decoder; +extern AVCodec ff_sunrast_encoder; +extern AVCodec ff_sunrast_decoder; +extern AVCodec ff_svq1_encoder; +extern AVCodec ff_svq1_decoder; +extern AVCodec ff_svq3_decoder; +extern AVCodec ff_targa_encoder; +extern AVCodec ff_targa_decoder; +extern AVCodec ff_targa_y216_decoder; +extern AVCodec ff_tdsc_decoder; +extern AVCodec ff_theora_decoder; +extern AVCodec ff_thp_decoder; +extern AVCodec ff_tiertexseqvideo_decoder; +extern AVCodec ff_tiff_encoder; +extern AVCodec ff_tiff_decoder; +extern AVCodec ff_tmv_decoder; +extern AVCodec ff_truemotion1_decoder; +extern AVCodec ff_truemotion2_decoder; +extern AVCodec ff_truemotion2rt_decoder; +extern AVCodec ff_tscc_decoder; +extern AVCodec ff_tscc2_decoder; +extern AVCodec ff_txd_decoder; +extern AVCodec ff_ulti_decoder; +extern AVCodec ff_utvideo_encoder; +extern AVCodec ff_utvideo_decoder; +extern AVCodec ff_v210_encoder; +extern AVCodec ff_v210_decoder; +extern AVCodec ff_v210x_decoder; +extern AVCodec ff_v308_encoder; +extern AVCodec ff_v308_decoder; +extern AVCodec ff_v408_encoder; +extern AVCodec ff_v408_decoder; +extern AVCodec ff_v410_encoder; +extern AVCodec ff_v410_decoder; +extern AVCodec ff_vb_decoder; +extern AVCodec ff_vble_decoder; +extern AVCodec ff_vc1_decoder; +extern AVCodec ff_vc1_crystalhd_decoder; +extern AVCodec ff_vc1image_decoder; +extern AVCodec ff_vc1_mmal_decoder; +extern AVCodec ff_vc1_qsv_decoder; +extern AVCodec ff_vc1_v4l2m2m_decoder; +extern AVCodec ff_vc2_encoder; +extern AVCodec ff_vcr1_decoder; +extern AVCodec ff_vmdvideo_decoder; +extern AVCodec ff_vmnc_decoder; +extern AVCodec ff_vp3_decoder; +extern AVCodec ff_vp5_decoder; +extern AVCodec ff_vp6_decoder; +extern AVCodec ff_vp6a_decoder; +extern AVCodec ff_vp6f_decoder; +extern AVCodec ff_vp7_decoder; +extern AVCodec ff_vp8_decoder; +extern AVCodec ff_vp8_rkmpp_decoder; +extern AVCodec ff_vp8_v4l2m2m_decoder; +extern AVCodec ff_vp9_decoder; +extern AVCodec ff_vp9_rkmpp_decoder; +extern AVCodec ff_vp9_v4l2m2m_decoder; +extern AVCodec ff_vqa_decoder; +extern AVCodec ff_bitpacked_decoder; +extern AVCodec ff_webp_decoder; +extern AVCodec ff_wrapped_avframe_encoder; +extern AVCodec ff_wrapped_avframe_decoder; +extern AVCodec ff_wmv1_encoder; +extern AVCodec ff_wmv1_decoder; +extern AVCodec ff_wmv2_encoder; +extern AVCodec ff_wmv2_decoder; +extern AVCodec ff_wmv3_decoder; +extern AVCodec ff_wmv3_crystalhd_decoder; +extern AVCodec ff_wmv3image_decoder; +extern AVCodec ff_wnv1_decoder; +extern AVCodec ff_xan_wc3_decoder; +extern AVCodec ff_xan_wc4_decoder; +extern AVCodec ff_xbm_encoder; +extern AVCodec ff_xbm_decoder; +extern AVCodec ff_xface_encoder; +extern AVCodec ff_xface_decoder; +extern AVCodec ff_xl_decoder; +extern AVCodec ff_xpm_decoder; +extern AVCodec ff_xwd_encoder; +extern AVCodec ff_xwd_decoder; +extern AVCodec ff_y41p_encoder; +extern AVCodec ff_y41p_decoder; +extern AVCodec ff_ylc_decoder; +extern AVCodec ff_yop_decoder; +extern AVCodec ff_yuv4_encoder; +extern AVCodec ff_yuv4_decoder; +extern AVCodec ff_zero12v_decoder; +extern AVCodec ff_zerocodec_decoder; +extern AVCodec ff_zlib_encoder; +extern AVCodec ff_zlib_decoder; +extern AVCodec ff_zmbv_encoder; +extern AVCodec ff_zmbv_decoder; + +/* audio codecs */ +extern AVCodec ff_aac_encoder; +extern AVCodec ff_aac_decoder; +extern AVCodec ff_aac_fixed_decoder; +extern AVCodec ff_aac_latm_decoder; +extern AVCodec ff_ac3_encoder; +extern AVCodec ff_ac3_decoder; +extern AVCodec ff_ac3_fixed_encoder; +extern AVCodec ff_ac3_fixed_decoder; +extern AVCodec ff_alac_encoder; +extern AVCodec ff_alac_decoder; +extern AVCodec ff_als_decoder; +extern AVCodec ff_amrnb_decoder; +extern AVCodec ff_amrwb_decoder; +extern AVCodec ff_ape_decoder; +extern AVCodec ff_aptx_encoder; +extern AVCodec ff_aptx_decoder; +extern AVCodec ff_atrac1_decoder; +extern AVCodec ff_atrac3_decoder; +extern AVCodec ff_atrac3al_decoder; +extern AVCodec ff_atrac3p_decoder; +extern AVCodec ff_atrac3pal_decoder; +extern AVCodec ff_binkaudio_dct_decoder; +extern AVCodec ff_binkaudio_rdft_decoder; +extern AVCodec ff_bmv_audio_decoder; +extern AVCodec ff_cook_decoder; +extern AVCodec ff_dca_encoder; +extern AVCodec ff_dca_decoder; +extern AVCodec ff_dolby_e_decoder; +extern AVCodec ff_dsd_lsbf_decoder; +extern AVCodec ff_dsd_msbf_decoder; +extern AVCodec ff_dsd_lsbf_planar_decoder; +extern AVCodec ff_dsd_msbf_planar_decoder; +extern AVCodec ff_dsicinaudio_decoder; +extern AVCodec ff_dss_sp_decoder; +extern AVCodec ff_dst_decoder; +extern AVCodec ff_eac3_encoder; +extern AVCodec ff_eac3_decoder; +extern AVCodec ff_evrc_decoder; +extern AVCodec ff_ffwavesynth_decoder; +extern AVCodec ff_flac_encoder; +extern AVCodec ff_flac_decoder; +extern AVCodec ff_g723_1_encoder; +extern AVCodec ff_g723_1_decoder; +extern AVCodec ff_g729_decoder; +extern AVCodec ff_gsm_decoder; +extern AVCodec ff_gsm_ms_decoder; +extern AVCodec ff_iac_decoder; +extern AVCodec ff_imc_decoder; +extern AVCodec ff_interplay_acm_decoder; +extern AVCodec ff_mace3_decoder; +extern AVCodec ff_mace6_decoder; +extern AVCodec ff_metasound_decoder; +extern AVCodec ff_mlp_encoder; +extern AVCodec ff_mlp_decoder; +extern AVCodec ff_mp1_decoder; +extern AVCodec ff_mp1float_decoder; +extern AVCodec ff_mp2_encoder; +extern AVCodec ff_mp2_decoder; +extern AVCodec ff_mp2float_decoder; +extern AVCodec ff_mp2fixed_encoder; +extern AVCodec ff_mp3_decoder; +extern AVCodec ff_mp3float_decoder; +extern AVCodec ff_mp3adu_decoder; +extern AVCodec ff_mp3adufloat_decoder; +extern AVCodec ff_mp3on4_decoder; +extern AVCodec ff_mp3on4float_decoder; +extern AVCodec ff_mpc7_decoder; +extern AVCodec ff_mpc8_decoder; +extern AVCodec ff_nellymoser_encoder; +extern AVCodec ff_nellymoser_decoder; +extern AVCodec ff_on2avc_decoder; +extern AVCodec ff_opus_encoder; +extern AVCodec ff_opus_decoder; +extern AVCodec ff_paf_audio_decoder; +extern AVCodec ff_qcelp_decoder; +extern AVCodec ff_qdm2_decoder; +extern AVCodec ff_qdmc_decoder; +extern AVCodec ff_ra_144_encoder; +extern AVCodec ff_ra_144_decoder; +extern AVCodec ff_ra_288_decoder; +extern AVCodec ff_ralf_decoder; +extern AVCodec ff_shorten_decoder; +extern AVCodec ff_sipr_decoder; +extern AVCodec ff_smackaud_decoder; +extern AVCodec ff_sonic_encoder; +extern AVCodec ff_sonic_decoder; +extern AVCodec ff_sonic_ls_encoder; +extern AVCodec ff_tak_decoder; +extern AVCodec ff_truehd_encoder; +extern AVCodec ff_truehd_decoder; +extern AVCodec ff_truespeech_decoder; +extern AVCodec ff_tta_encoder; +extern AVCodec ff_tta_decoder; +extern AVCodec ff_twinvq_decoder; +extern AVCodec ff_vmdaudio_decoder; +extern AVCodec ff_vorbis_encoder; +extern AVCodec ff_vorbis_decoder; +extern AVCodec ff_wavpack_encoder; +extern AVCodec ff_wavpack_decoder; +extern AVCodec ff_wmalossless_decoder; +extern AVCodec ff_wmapro_decoder; +extern AVCodec ff_wmav1_encoder; +extern AVCodec ff_wmav1_decoder; +extern AVCodec ff_wmav2_encoder; +extern AVCodec ff_wmav2_decoder; +extern AVCodec ff_wmavoice_decoder; +extern AVCodec ff_ws_snd1_decoder; +extern AVCodec ff_xma1_decoder; +extern AVCodec ff_xma2_decoder; + +/* PCM codecs */ +extern AVCodec ff_pcm_alaw_encoder; +extern AVCodec ff_pcm_alaw_decoder; +extern AVCodec ff_pcm_bluray_decoder; +extern AVCodec ff_pcm_dvd_decoder; +extern AVCodec ff_pcm_f16le_decoder; +extern AVCodec ff_pcm_f24le_decoder; +extern AVCodec ff_pcm_f32be_encoder; +extern AVCodec ff_pcm_f32be_decoder; +extern AVCodec ff_pcm_f32le_encoder; +extern AVCodec ff_pcm_f32le_decoder; +extern AVCodec ff_pcm_f64be_encoder; +extern AVCodec ff_pcm_f64be_decoder; +extern AVCodec ff_pcm_f64le_encoder; +extern AVCodec ff_pcm_f64le_decoder; +extern AVCodec ff_pcm_lxf_decoder; +extern AVCodec ff_pcm_mulaw_encoder; +extern AVCodec ff_pcm_mulaw_decoder; +extern AVCodec ff_pcm_s8_encoder; +extern AVCodec ff_pcm_s8_decoder; +extern AVCodec ff_pcm_s8_planar_encoder; +extern AVCodec ff_pcm_s8_planar_decoder; +extern AVCodec ff_pcm_s16be_encoder; +extern AVCodec ff_pcm_s16be_decoder; +extern AVCodec ff_pcm_s16be_planar_encoder; +extern AVCodec ff_pcm_s16be_planar_decoder; +extern AVCodec ff_pcm_s16le_encoder; +extern AVCodec ff_pcm_s16le_decoder; +extern AVCodec ff_pcm_s16le_planar_encoder; +extern AVCodec ff_pcm_s16le_planar_decoder; +extern AVCodec ff_pcm_s24be_encoder; +extern AVCodec ff_pcm_s24be_decoder; +extern AVCodec ff_pcm_s24daud_encoder; +extern AVCodec ff_pcm_s24daud_decoder; +extern AVCodec ff_pcm_s24le_encoder; +extern AVCodec ff_pcm_s24le_decoder; +extern AVCodec ff_pcm_s24le_planar_encoder; +extern AVCodec ff_pcm_s24le_planar_decoder; +extern AVCodec ff_pcm_s32be_encoder; +extern AVCodec ff_pcm_s32be_decoder; +extern AVCodec ff_pcm_s32le_encoder; +extern AVCodec ff_pcm_s32le_decoder; +extern AVCodec ff_pcm_s32le_planar_encoder; +extern AVCodec ff_pcm_s32le_planar_decoder; +extern AVCodec ff_pcm_s64be_encoder; +extern AVCodec ff_pcm_s64be_decoder; +extern AVCodec ff_pcm_s64le_encoder; +extern AVCodec ff_pcm_s64le_decoder; +extern AVCodec ff_pcm_u8_encoder; +extern AVCodec ff_pcm_u8_decoder; +extern AVCodec ff_pcm_u16be_encoder; +extern AVCodec ff_pcm_u16be_decoder; +extern AVCodec ff_pcm_u16le_encoder; +extern AVCodec ff_pcm_u16le_decoder; +extern AVCodec ff_pcm_u24be_encoder; +extern AVCodec ff_pcm_u24be_decoder; +extern AVCodec ff_pcm_u24le_encoder; +extern AVCodec ff_pcm_u24le_decoder; +extern AVCodec ff_pcm_u32be_encoder; +extern AVCodec ff_pcm_u32be_decoder; +extern AVCodec ff_pcm_u32le_encoder; +extern AVCodec ff_pcm_u32le_decoder; +extern AVCodec ff_pcm_zork_decoder; + +/* DPCM codecs */ +extern AVCodec ff_gremlin_dpcm_decoder; +extern AVCodec ff_interplay_dpcm_decoder; +extern AVCodec ff_roq_dpcm_encoder; +extern AVCodec ff_roq_dpcm_decoder; +extern AVCodec ff_sol_dpcm_decoder; +extern AVCodec ff_xan_dpcm_decoder; + +/* ADPCM codecs */ +extern AVCodec ff_adpcm_4xm_decoder; +extern AVCodec ff_adpcm_adx_encoder; +extern AVCodec ff_adpcm_adx_decoder; +extern AVCodec ff_adpcm_afc_decoder; +extern AVCodec ff_adpcm_aica_decoder; +extern AVCodec ff_adpcm_ct_decoder; +extern AVCodec ff_adpcm_dtk_decoder; +extern AVCodec ff_adpcm_ea_decoder; +extern AVCodec ff_adpcm_ea_maxis_xa_decoder; +extern AVCodec ff_adpcm_ea_r1_decoder; +extern AVCodec ff_adpcm_ea_r2_decoder; +extern AVCodec ff_adpcm_ea_r3_decoder; +extern AVCodec ff_adpcm_ea_xas_decoder; +extern AVCodec ff_adpcm_g722_encoder; +extern AVCodec ff_adpcm_g722_decoder; +extern AVCodec ff_adpcm_g726_encoder; +extern AVCodec ff_adpcm_g726_decoder; +extern AVCodec ff_adpcm_g726le_encoder; +extern AVCodec ff_adpcm_g726le_decoder; +extern AVCodec ff_adpcm_ima_amv_decoder; +extern AVCodec ff_adpcm_ima_apc_decoder; +extern AVCodec ff_adpcm_ima_dat4_decoder; +extern AVCodec ff_adpcm_ima_dk3_decoder; +extern AVCodec ff_adpcm_ima_dk4_decoder; +extern AVCodec ff_adpcm_ima_ea_eacs_decoder; +extern AVCodec ff_adpcm_ima_ea_sead_decoder; +extern AVCodec ff_adpcm_ima_iss_decoder; +extern AVCodec ff_adpcm_ima_oki_decoder; +extern AVCodec ff_adpcm_ima_qt_encoder; +extern AVCodec ff_adpcm_ima_qt_decoder; +extern AVCodec ff_adpcm_ima_rad_decoder; +extern AVCodec ff_adpcm_ima_smjpeg_decoder; +extern AVCodec ff_adpcm_ima_wav_encoder; +extern AVCodec ff_adpcm_ima_wav_decoder; +extern AVCodec ff_adpcm_ima_ws_decoder; +extern AVCodec ff_adpcm_ms_encoder; +extern AVCodec ff_adpcm_ms_decoder; +extern AVCodec ff_adpcm_mtaf_decoder; +extern AVCodec ff_adpcm_psx_decoder; +extern AVCodec ff_adpcm_sbpro_2_decoder; +extern AVCodec ff_adpcm_sbpro_3_decoder; +extern AVCodec ff_adpcm_sbpro_4_decoder; +extern AVCodec ff_adpcm_swf_encoder; +extern AVCodec ff_adpcm_swf_decoder; +extern AVCodec ff_adpcm_thp_decoder; +extern AVCodec ff_adpcm_thp_le_decoder; +extern AVCodec ff_adpcm_vima_decoder; +extern AVCodec ff_adpcm_xa_decoder; +extern AVCodec ff_adpcm_yamaha_encoder; +extern AVCodec ff_adpcm_yamaha_decoder; + +/* subtitles */ +extern AVCodec ff_ssa_encoder; +extern AVCodec ff_ssa_decoder; +extern AVCodec ff_ass_encoder; +extern AVCodec ff_ass_decoder; +extern AVCodec ff_ccaption_decoder; +extern AVCodec ff_dvbsub_encoder; +extern AVCodec ff_dvbsub_decoder; +extern AVCodec ff_dvdsub_encoder; +extern AVCodec ff_dvdsub_decoder; +extern AVCodec ff_jacosub_decoder; +extern AVCodec ff_microdvd_decoder; +extern AVCodec ff_movtext_encoder; +extern AVCodec ff_movtext_decoder; +extern AVCodec ff_mpl2_decoder; +extern AVCodec ff_pgssub_decoder; +extern AVCodec ff_pjs_decoder; +extern AVCodec ff_realtext_decoder; +extern AVCodec ff_sami_decoder; +extern AVCodec ff_srt_encoder; +extern AVCodec ff_srt_decoder; +extern AVCodec ff_stl_decoder; +extern AVCodec ff_subrip_encoder; +extern AVCodec ff_subrip_decoder; +extern AVCodec ff_subviewer_decoder; +extern AVCodec ff_subviewer1_decoder; +extern AVCodec ff_text_encoder; +extern AVCodec ff_text_decoder; +extern AVCodec ff_vplayer_decoder; +extern AVCodec ff_webvtt_encoder; +extern AVCodec ff_webvtt_decoder; +extern AVCodec ff_xsub_encoder; +extern AVCodec ff_xsub_decoder; + +/* external libraries */ +extern AVCodec ff_aac_at_encoder; +extern AVCodec ff_aac_at_decoder; +extern AVCodec ff_ac3_at_decoder; +extern AVCodec ff_adpcm_ima_qt_at_decoder; +extern AVCodec ff_alac_at_encoder; +extern AVCodec ff_alac_at_decoder; +extern AVCodec ff_amr_nb_at_decoder; +extern AVCodec ff_eac3_at_decoder; +extern AVCodec ff_gsm_ms_at_decoder; +extern AVCodec ff_ilbc_at_encoder; +extern AVCodec ff_ilbc_at_decoder; +extern AVCodec ff_mp1_at_decoder; +extern AVCodec ff_mp2_at_decoder; +extern AVCodec ff_mp3_at_decoder; +extern AVCodec ff_pcm_alaw_at_encoder; +extern AVCodec ff_pcm_alaw_at_decoder; +extern AVCodec ff_pcm_mulaw_at_encoder; +extern AVCodec ff_pcm_mulaw_at_decoder; +extern AVCodec ff_qdmc_at_decoder; +extern AVCodec ff_qdm2_at_decoder; +extern AVCodec ff_libcelt_decoder; +extern AVCodec ff_libfdk_aac_encoder; +extern AVCodec ff_libfdk_aac_decoder; +extern AVCodec ff_libgsm_encoder; +extern AVCodec ff_libgsm_decoder; +extern AVCodec ff_libgsm_ms_encoder; +extern AVCodec ff_libgsm_ms_decoder; +extern AVCodec ff_libilbc_encoder; +extern AVCodec ff_libilbc_decoder; +extern AVCodec ff_libmp3lame_encoder; +extern AVCodec ff_libopencore_amrnb_encoder; +extern AVCodec ff_libopencore_amrnb_decoder; +extern AVCodec ff_libopencore_amrwb_decoder; +extern AVCodec ff_libopenjpeg_encoder; +extern AVCodec ff_libopenjpeg_decoder; +extern AVCodec ff_libopus_encoder; +extern AVCodec ff_libopus_decoder; +extern AVCodec ff_librsvg_decoder; +extern AVCodec ff_libshine_encoder; +extern AVCodec ff_libspeex_encoder; +extern AVCodec ff_libspeex_decoder; +extern AVCodec ff_libtheora_encoder; +extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libvo_amrwbenc_encoder; +extern AVCodec ff_libvorbis_encoder; +extern AVCodec ff_libvorbis_decoder; +extern AVCodec ff_libvpx_vp8_encoder; +extern AVCodec ff_libvpx_vp8_decoder; +extern AVCodec ff_libvpx_vp9_encoder; +extern AVCodec ff_libvpx_vp9_decoder; +extern AVCodec ff_libwavpack_encoder; +/* preferred over libwebp */ +extern AVCodec ff_libwebp_anim_encoder; +extern AVCodec ff_libwebp_encoder; +extern AVCodec ff_libx262_encoder; +extern AVCodec ff_libx264_encoder; +extern AVCodec ff_libx264rgb_encoder; +extern AVCodec ff_libx265_encoder; +extern AVCodec ff_libxavs_encoder; +extern AVCodec ff_libxvid_encoder; +extern AVCodec ff_libzvbi_teletext_decoder; + +/* text */ +extern AVCodec ff_bintext_decoder; +extern AVCodec ff_xbin_decoder; +extern AVCodec ff_idf_decoder; -#define REGISTER_DECODER(X, x) \ - { \ - extern AVCodec ff_##x##_decoder; \ - if (CONFIG_##X##_DECODER) \ - avcodec_register(&ff_##x##_decoder); \ +/* external libraries, that shouldn't be used by default if one of the + * above is available */ +extern AVCodec ff_h263_v4l2m2m_encoder; +extern AVCodec ff_libopenh264_encoder; +extern AVCodec ff_libopenh264_decoder; +extern AVCodec ff_h264_amf_encoder; +extern AVCodec ff_h264_cuvid_decoder; +extern AVCodec ff_h264_nvenc_encoder; +extern AVCodec ff_h264_omx_encoder; +extern AVCodec ff_h264_qsv_encoder; +extern AVCodec ff_h264_v4l2m2m_encoder; +extern AVCodec ff_h264_vaapi_encoder; +extern AVCodec ff_h264_videotoolbox_encoder; +#if FF_API_NVENC_OLD_NAME +extern AVCodec ff_nvenc_encoder; +extern AVCodec ff_nvenc_h264_encoder; +extern AVCodec ff_nvenc_hevc_encoder; +#endif +extern AVCodec ff_hevc_amf_encoder; +extern AVCodec ff_hevc_cuvid_decoder; +extern AVCodec ff_hevc_mediacodec_decoder; +extern AVCodec ff_hevc_nvenc_encoder; +extern AVCodec ff_hevc_qsv_encoder; +extern AVCodec ff_hevc_v4l2m2m_encoder; +extern AVCodec ff_hevc_vaapi_encoder; +extern AVCodec ff_hevc_videotoolbox_encoder; +extern AVCodec ff_libkvazaar_encoder; +extern AVCodec ff_mjpeg_cuvid_decoder; +extern AVCodec ff_mjpeg_qsv_encoder; +extern AVCodec ff_mjpeg_vaapi_encoder; +extern AVCodec ff_mpeg1_cuvid_decoder; +extern AVCodec ff_mpeg2_cuvid_decoder; +extern AVCodec ff_mpeg2_qsv_encoder; +extern AVCodec ff_mpeg2_vaapi_encoder; +extern AVCodec ff_mpeg4_cuvid_decoder; +extern AVCodec ff_mpeg4_mediacodec_decoder; +extern AVCodec ff_mpeg4_v4l2m2m_encoder; +extern AVCodec ff_vc1_cuvid_decoder; +extern AVCodec ff_vp8_cuvid_decoder; +extern AVCodec ff_vp8_mediacodec_decoder; +extern AVCodec ff_vp8_qsv_decoder; +extern AVCodec ff_vp8_v4l2m2m_encoder; +extern AVCodec ff_vp8_vaapi_encoder; +extern AVCodec ff_vp9_cuvid_decoder; +extern AVCodec ff_vp9_mediacodec_decoder; +extern AVCodec ff_vp9_vaapi_encoder; + +#include "libavcodec/codec_list.c" + +static AVOnce av_codec_static_init = AV_ONCE_INIT; +static void av_codec_init_static(void) +{ + for (int i = 0; codec_list[i]; i++) { + if (codec_list[i]->init_static_data) + codec_list[i]->init_static_data((AVCodec*)codec_list[i]); } +} + +const AVCodec *av_codec_iterate(void **opaque) +{ + uintptr_t i = (uintptr_t)*opaque; + const AVCodec *c = codec_list[i]; + + ff_thread_once(&av_codec_static_init, av_codec_init_static); + + if (c) + *opaque = (void*)(i + 1); + + return c; +} -#define REGISTER_ENCDEC(X, x) REGISTER_ENCODER(X, x); REGISTER_DECODER(X, x) +#if FF_API_NEXT +FF_DISABLE_DEPRECATION_WARNINGS +static AVOnce av_codec_next_init = AV_ONCE_INIT; -#define REGISTER_PARSER(X, x) \ - { \ - extern AVCodecParser ff_##x##_parser; \ - if (CONFIG_##X##_PARSER) \ - av_register_codec_parser(&ff_##x##_parser); \ +static void av_codec_init_next(void) +{ + AVCodec *prev = NULL, *p; + void *i = 0; + while ((p = (AVCodec*)av_codec_iterate(&i))) { + if (prev) + prev->next = p; + prev = p; } +} + -static void register_all(void) + +av_cold void avcodec_register(AVCodec *codec) { - /* video codecs */ - REGISTER_ENCODER(A64MULTI, a64multi); - REGISTER_ENCODER(A64MULTI5, a64multi5); - REGISTER_DECODER(AASC, aasc); - REGISTER_DECODER(AIC, aic); - REGISTER_ENCDEC (ALIAS_PIX, alias_pix); - REGISTER_ENCDEC (AMV, amv); - REGISTER_DECODER(ANM, anm); - REGISTER_DECODER(ANSI, ansi); - REGISTER_ENCDEC (APNG, apng); - REGISTER_ENCDEC (ASV1, asv1); - REGISTER_ENCDEC (ASV2, asv2); - REGISTER_DECODER(AURA, aura); - REGISTER_DECODER(AURA2, aura2); - REGISTER_ENCDEC (AVRP, avrp); - REGISTER_DECODER(AVRN, avrn); - REGISTER_DECODER(AVS, avs); - REGISTER_ENCDEC (AVUI, avui); - REGISTER_ENCDEC (AYUV, ayuv); - REGISTER_DECODER(BETHSOFTVID, bethsoftvid); - REGISTER_DECODER(BFI, bfi); - REGISTER_DECODER(BINK, bink); - REGISTER_ENCDEC (BMP, bmp); - REGISTER_DECODER(BMV_VIDEO, bmv_video); - REGISTER_DECODER(BRENDER_PIX, brender_pix); - REGISTER_DECODER(C93, c93); - REGISTER_DECODER(CAVS, cavs); - REGISTER_DECODER(CDGRAPHICS, cdgraphics); - REGISTER_DECODER(CDXL, cdxl); - REGISTER_DECODER(CFHD, cfhd); - REGISTER_ENCDEC (CINEPAK, cinepak); - REGISTER_DECODER(CLEARVIDEO, clearvideo); - REGISTER_ENCDEC (CLJR, cljr); - REGISTER_DECODER(CLLC, cllc); - REGISTER_ENCDEC (COMFORTNOISE, comfortnoise); - REGISTER_DECODER(CPIA, cpia); - REGISTER_DECODER(CSCD, cscd); - REGISTER_DECODER(CYUV, cyuv); - REGISTER_DECODER(DDS, dds); - REGISTER_DECODER(DFA, dfa); - REGISTER_DECODER(DIRAC, dirac); - REGISTER_ENCDEC (DNXHD, dnxhd); - REGISTER_ENCDEC (DPX, dpx); - REGISTER_DECODER(DSICINVIDEO, dsicinvideo); - REGISTER_DECODER(DVAUDIO, dvaudio); - REGISTER_ENCDEC (DVVIDEO, dvvideo); - REGISTER_DECODER(DXA, dxa); - REGISTER_DECODER(DXTORY, dxtory); - REGISTER_DECODER(DXV, dxv); - REGISTER_DECODER(EACMV, eacmv); - REGISTER_DECODER(EAMAD, eamad); - REGISTER_DECODER(EATGQ, eatgq); - REGISTER_DECODER(EATGV, eatgv); - REGISTER_DECODER(EATQI, eatqi); - REGISTER_DECODER(EIGHTBPS, eightbps); - REGISTER_DECODER(EIGHTSVX_EXP, eightsvx_exp); - REGISTER_DECODER(EIGHTSVX_FIB, eightsvx_fib); - REGISTER_DECODER(ESCAPE124, escape124); - REGISTER_DECODER(ESCAPE130, escape130); - REGISTER_DECODER(EXR, exr); - REGISTER_ENCDEC (FFV1, ffv1); - REGISTER_ENCDEC (FFVHUFF, ffvhuff); - REGISTER_DECODER(FIC, fic); - REGISTER_ENCDEC (FITS, fits); - REGISTER_ENCDEC (FLASHSV, flashsv); - REGISTER_ENCDEC (FLASHSV2, flashsv2); - REGISTER_DECODER(FLIC, flic); - REGISTER_ENCDEC (FLV, flv); - REGISTER_DECODER(FMVC, fmvc); - REGISTER_DECODER(FOURXM, fourxm); - REGISTER_DECODER(FRAPS, fraps); - REGISTER_DECODER(FRWU, frwu); - REGISTER_DECODER(G2M, g2m); - REGISTER_DECODER(GDV, gdv); - REGISTER_ENCDEC (GIF, gif); - REGISTER_ENCDEC (H261, h261); - REGISTER_ENCDEC (H263, h263); - REGISTER_DECODER(H263I, h263i); - REGISTER_ENCDEC (H263P, h263p); - REGISTER_DECODER(H263_V4L2M2M, h263_v4l2m2m); - REGISTER_DECODER(H264, h264); - REGISTER_DECODER(H264_CRYSTALHD, h264_crystalhd); - REGISTER_DECODER(H264_V4L2M2M, h264_v4l2m2m); - REGISTER_DECODER(H264_MEDIACODEC, h264_mediacodec); - REGISTER_DECODER(H264_MMAL, h264_mmal); - REGISTER_DECODER(H264_QSV, h264_qsv); - REGISTER_DECODER(H264_RKMPP, h264_rkmpp); - REGISTER_ENCDEC (HAP, hap); - REGISTER_DECODER(HEVC, hevc); - REGISTER_DECODER(HEVC_QSV, hevc_qsv); - REGISTER_DECODER(HEVC_RKMPP, hevc_rkmpp); - REGISTER_DECODER(HEVC_V4L2M2M, hevc_v4l2m2m); - REGISTER_DECODER(HNM4_VIDEO, hnm4_video); - REGISTER_DECODER(HQ_HQA, hq_hqa); - REGISTER_DECODER(HQX, hqx); - REGISTER_ENCDEC (HUFFYUV, huffyuv); - REGISTER_DECODER(IDCIN, idcin); - REGISTER_DECODER(IFF_ILBM, iff_ilbm); - REGISTER_DECODER(INDEO2, indeo2); - REGISTER_DECODER(INDEO3, indeo3); - REGISTER_DECODER(INDEO4, indeo4); - REGISTER_DECODER(INDEO5, indeo5); - REGISTER_DECODER(INTERPLAY_VIDEO, interplay_video); - REGISTER_ENCDEC (JPEG2000, jpeg2000); - REGISTER_ENCDEC (JPEGLS, jpegls); - REGISTER_DECODER(JV, jv); - REGISTER_DECODER(KGV1, kgv1); - REGISTER_DECODER(KMVC, kmvc); - REGISTER_DECODER(LAGARITH, lagarith); - REGISTER_ENCODER(LJPEG, ljpeg); - REGISTER_DECODER(LOCO, loco); - REGISTER_DECODER(M101, m101); - REGISTER_ENCDEC (MAGICYUV, magicyuv); - REGISTER_DECODER(MDEC, mdec); - REGISTER_DECODER(MIMIC, mimic); - REGISTER_ENCDEC (MJPEG, mjpeg); - REGISTER_DECODER(MJPEGB, mjpegb); - REGISTER_DECODER(MMVIDEO, mmvideo); - REGISTER_DECODER(MOTIONPIXELS, motionpixels); - REGISTER_ENCDEC (MPEG1VIDEO, mpeg1video); - REGISTER_ENCDEC (MPEG2VIDEO, mpeg2video); - REGISTER_ENCDEC (MPEG4, mpeg4); - REGISTER_DECODER(MPEG4_CRYSTALHD, mpeg4_crystalhd); - REGISTER_DECODER(MPEG4_V4L2M2M, mpeg4_v4l2m2m); - REGISTER_DECODER(MPEG4_MMAL, mpeg4_mmal); - REGISTER_DECODER(MPEGVIDEO, mpegvideo); - REGISTER_DECODER(MPEG1_V4L2M2M, mpeg1_v4l2m2m); - REGISTER_DECODER(MPEG2_MMAL, mpeg2_mmal); - REGISTER_DECODER(MPEG2_CRYSTALHD, mpeg2_crystalhd); - REGISTER_DECODER(MPEG2_V4L2M2M, mpeg2_v4l2m2m); - REGISTER_DECODER(MPEG2_QSV, mpeg2_qsv); - REGISTER_DECODER(MPEG2_MEDIACODEC, mpeg2_mediacodec); - REGISTER_DECODER(MSA1, msa1); - REGISTER_DECODER(MSCC, mscc); - REGISTER_DECODER(MSMPEG4V1, msmpeg4v1); - REGISTER_ENCDEC (MSMPEG4V2, msmpeg4v2); - REGISTER_ENCDEC (MSMPEG4V3, msmpeg4v3); - REGISTER_DECODER(MSMPEG4_CRYSTALHD, msmpeg4_crystalhd); - REGISTER_DECODER(MSRLE, msrle); - REGISTER_DECODER(MSS1, mss1); - REGISTER_DECODER(MSS2, mss2); - REGISTER_ENCDEC (MSVIDEO1, msvideo1); - REGISTER_DECODER(MSZH, mszh); - REGISTER_DECODER(MTS2, mts2); - REGISTER_DECODER(MVC1, mvc1); - REGISTER_DECODER(MVC2, mvc2); - REGISTER_DECODER(MXPEG, mxpeg); - REGISTER_DECODER(NUV, nuv); - REGISTER_DECODER(PAF_VIDEO, paf_video); - REGISTER_ENCDEC (PAM, pam); - REGISTER_ENCDEC (PBM, pbm); - REGISTER_ENCDEC (PCX, pcx); - REGISTER_ENCDEC (PGM, pgm); - REGISTER_ENCDEC (PGMYUV, pgmyuv); - REGISTER_DECODER(PICTOR, pictor); - REGISTER_DECODER(PIXLET, pixlet); - REGISTER_ENCDEC (PNG, png); - REGISTER_ENCDEC (PPM, ppm); - REGISTER_ENCDEC (PRORES, prores); - REGISTER_ENCODER(PRORES_AW, prores_aw); - REGISTER_ENCODER(PRORES_KS, prores_ks); - REGISTER_DECODER(PRORES_LGPL, prores_lgpl); - REGISTER_DECODER(PSD, psd); - REGISTER_DECODER(PTX, ptx); - REGISTER_DECODER(QDRAW, qdraw); - REGISTER_DECODER(QPEG, qpeg); - REGISTER_ENCDEC (QTRLE, qtrle); - REGISTER_ENCDEC (R10K, r10k); - REGISTER_ENCDEC (R210, r210); - REGISTER_ENCDEC (RAWVIDEO, rawvideo); - REGISTER_DECODER(RL2, rl2); - REGISTER_ENCDEC (ROQ, roq); - REGISTER_DECODER(RPZA, rpza); - REGISTER_DECODER(RSCC, rscc); - REGISTER_ENCDEC (RV10, rv10); - REGISTER_ENCDEC (RV20, rv20); - REGISTER_DECODER(RV30, rv30); - REGISTER_DECODER(RV40, rv40); - REGISTER_ENCDEC (S302M, s302m); - REGISTER_DECODER(SANM, sanm); - REGISTER_DECODER(SCPR, scpr); - REGISTER_DECODER(SCREENPRESSO, screenpresso); - REGISTER_DECODER(SDX2_DPCM, sdx2_dpcm); - REGISTER_ENCDEC (SGI, sgi); - REGISTER_DECODER(SGIRLE, sgirle); - REGISTER_DECODER(SHEERVIDEO, sheervideo); - REGISTER_DECODER(SMACKER, smacker); - REGISTER_DECODER(SMC, smc); - REGISTER_DECODER(SMVJPEG, smvjpeg); - REGISTER_ENCDEC (SNOW, snow); - REGISTER_DECODER(SP5X, sp5x); - REGISTER_DECODER(SPEEDHQ, speedhq); - REGISTER_DECODER(SRGC, srgc); - REGISTER_ENCDEC (SUNRAST, sunrast); - REGISTER_ENCDEC (SVQ1, svq1); - REGISTER_DECODER(SVQ3, svq3); - REGISTER_ENCDEC (TARGA, targa); - REGISTER_DECODER(TARGA_Y216, targa_y216); - REGISTER_DECODER(TDSC, tdsc); - REGISTER_DECODER(THEORA, theora); - REGISTER_DECODER(THP, thp); - REGISTER_DECODER(TIERTEXSEQVIDEO, tiertexseqvideo); - REGISTER_ENCDEC (TIFF, tiff); - REGISTER_DECODER(TMV, tmv); - REGISTER_DECODER(TRUEMOTION1, truemotion1); - REGISTER_DECODER(TRUEMOTION2, truemotion2); - REGISTER_DECODER(TRUEMOTION2RT, truemotion2rt); - REGISTER_DECODER(TSCC, tscc); - REGISTER_DECODER(TSCC2, tscc2); - REGISTER_DECODER(TXD, txd); - REGISTER_DECODER(ULTI, ulti); - REGISTER_ENCDEC (UTVIDEO, utvideo); - REGISTER_ENCDEC (V210, v210); - REGISTER_DECODER(V210X, v210x); - REGISTER_ENCDEC (V308, v308); - REGISTER_ENCDEC (V408, v408); - REGISTER_ENCDEC (V410, v410); - REGISTER_DECODER(VB, vb); - REGISTER_DECODER(VBLE, vble); - REGISTER_DECODER(VC1, vc1); - REGISTER_DECODER(VC1_CRYSTALHD, vc1_crystalhd); - REGISTER_DECODER(VC1IMAGE, vc1image); - REGISTER_DECODER(VC1_MMAL, vc1_mmal); - REGISTER_DECODER(VC1_QSV, vc1_qsv); - REGISTER_DECODER(VC1_V4L2M2M, vc1_v4l2m2m); - REGISTER_ENCODER(VC2, vc2); - REGISTER_DECODER(VCR1, vcr1); - REGISTER_DECODER(VMDVIDEO, vmdvideo); - REGISTER_DECODER(VMNC, vmnc); - REGISTER_DECODER(VP3, vp3); - REGISTER_DECODER(VP5, vp5); - REGISTER_DECODER(VP6, vp6); - REGISTER_DECODER(VP6A, vp6a); - REGISTER_DECODER(VP6F, vp6f); - REGISTER_DECODER(VP7, vp7); - REGISTER_DECODER(VP8, vp8); - REGISTER_DECODER(VP8_RKMPP, vp8_rkmpp); - REGISTER_DECODER(VP8_V4L2M2M, vp8_v4l2m2m); - REGISTER_DECODER(VP9, vp9); - REGISTER_DECODER(VP9_RKMPP, vp9_rkmpp); - REGISTER_DECODER(VP9_V4L2M2M, vp9_v4l2m2m); - REGISTER_DECODER(VQA, vqa); - REGISTER_DECODER(BITPACKED, bitpacked); - REGISTER_DECODER(WEBP, webp); - REGISTER_ENCDEC (WRAPPED_AVFRAME, wrapped_avframe); - REGISTER_ENCDEC (WMV1, wmv1); - REGISTER_ENCDEC (WMV2, wmv2); - REGISTER_DECODER(WMV3, wmv3); - REGISTER_DECODER(WMV3_CRYSTALHD, wmv3_crystalhd); - REGISTER_DECODER(WMV3IMAGE, wmv3image); - REGISTER_DECODER(WNV1, wnv1); - REGISTER_DECODER(XAN_WC3, xan_wc3); - REGISTER_DECODER(XAN_WC4, xan_wc4); - REGISTER_ENCDEC (XBM, xbm); - REGISTER_ENCDEC (XFACE, xface); - REGISTER_DECODER(XL, xl); - REGISTER_DECODER(XPM, xpm); - REGISTER_ENCDEC (XWD, xwd); - REGISTER_ENCDEC (Y41P, y41p); - REGISTER_DECODER(YLC, ylc); - REGISTER_DECODER(YOP, yop); - REGISTER_ENCDEC (YUV4, yuv4); - REGISTER_DECODER(ZERO12V, zero12v); - REGISTER_DECODER(ZEROCODEC, zerocodec); - REGISTER_ENCDEC (ZLIB, zlib); - REGISTER_ENCDEC (ZMBV, zmbv); - - /* audio codecs */ - REGISTER_ENCDEC (AAC, aac); - REGISTER_DECODER(AAC_FIXED, aac_fixed); - REGISTER_DECODER(AAC_LATM, aac_latm); - REGISTER_ENCDEC (AC3, ac3); - REGISTER_ENCDEC (AC3_FIXED, ac3_fixed); - REGISTER_ENCDEC (ALAC, alac); - REGISTER_DECODER(ALS, als); - REGISTER_DECODER(AMRNB, amrnb); - REGISTER_DECODER(AMRWB, amrwb); - REGISTER_DECODER(APE, ape); - REGISTER_ENCDEC (APTX, aptx); - REGISTER_DECODER(ATRAC1, atrac1); - REGISTER_DECODER(ATRAC3, atrac3); - REGISTER_DECODER(ATRAC3AL, atrac3al); - REGISTER_DECODER(ATRAC3P, atrac3p); - REGISTER_DECODER(ATRAC3PAL, atrac3pal); - REGISTER_DECODER(BINKAUDIO_DCT, binkaudio_dct); - REGISTER_DECODER(BINKAUDIO_RDFT, binkaudio_rdft); - REGISTER_DECODER(BMV_AUDIO, bmv_audio); - REGISTER_DECODER(COOK, cook); - REGISTER_ENCDEC (DCA, dca); - REGISTER_DECODER(DOLBY_E, dolby_e); - REGISTER_DECODER(DSD_LSBF, dsd_lsbf); - REGISTER_DECODER(DSD_MSBF, dsd_msbf); - REGISTER_DECODER(DSD_LSBF_PLANAR, dsd_lsbf_planar); - REGISTER_DECODER(DSD_MSBF_PLANAR, dsd_msbf_planar); - REGISTER_DECODER(DSICINAUDIO, dsicinaudio); - REGISTER_DECODER(DSS_SP, dss_sp); - REGISTER_DECODER(DST, dst); - REGISTER_ENCDEC (EAC3, eac3); - REGISTER_DECODER(EVRC, evrc); - REGISTER_DECODER(FFWAVESYNTH, ffwavesynth); - REGISTER_ENCDEC (FLAC, flac); - REGISTER_ENCDEC (G723_1, g723_1); - REGISTER_DECODER(G729, g729); - REGISTER_DECODER(GSM, gsm); - REGISTER_DECODER(GSM_MS, gsm_ms); - REGISTER_DECODER(IAC, iac); - REGISTER_DECODER(IMC, imc); - REGISTER_DECODER(INTERPLAY_ACM, interplay_acm); - REGISTER_DECODER(MACE3, mace3); - REGISTER_DECODER(MACE6, mace6); - REGISTER_DECODER(METASOUND, metasound); - REGISTER_ENCDEC (MLP, mlp); - REGISTER_DECODER(MP1, mp1); - REGISTER_DECODER(MP1FLOAT, mp1float); - REGISTER_ENCDEC (MP2, mp2); - REGISTER_DECODER(MP2FLOAT, mp2float); - REGISTER_ENCODER(MP2FIXED, mp2fixed); - REGISTER_DECODER(MP3, mp3); - REGISTER_DECODER(MP3FLOAT, mp3float); - REGISTER_DECODER(MP3ADU, mp3adu); - REGISTER_DECODER(MP3ADUFLOAT, mp3adufloat); - REGISTER_DECODER(MP3ON4, mp3on4); - REGISTER_DECODER(MP3ON4FLOAT, mp3on4float); - REGISTER_DECODER(MPC7, mpc7); - REGISTER_DECODER(MPC8, mpc8); - REGISTER_ENCDEC (NELLYMOSER, nellymoser); - REGISTER_DECODER(ON2AVC, on2avc); - REGISTER_ENCDEC (OPUS, opus); - REGISTER_DECODER(PAF_AUDIO, paf_audio); - REGISTER_DECODER(QCELP, qcelp); - REGISTER_DECODER(QDM2, qdm2); - REGISTER_DECODER(QDMC, qdmc); - REGISTER_ENCDEC (RA_144, ra_144); - REGISTER_DECODER(RA_288, ra_288); - REGISTER_DECODER(RALF, ralf); - REGISTER_DECODER(SHORTEN, shorten); - REGISTER_DECODER(SIPR, sipr); - REGISTER_DECODER(SMACKAUD, smackaud); - REGISTER_ENCDEC (SONIC, sonic); - REGISTER_ENCODER(SONIC_LS, sonic_ls); - REGISTER_DECODER(TAK, tak); - REGISTER_ENCDEC (TRUEHD, truehd); - REGISTER_DECODER(TRUESPEECH, truespeech); - REGISTER_ENCDEC (TTA, tta); - REGISTER_DECODER(TWINVQ, twinvq); - REGISTER_DECODER(VMDAUDIO, vmdaudio); - REGISTER_ENCDEC (VORBIS, vorbis); - REGISTER_ENCDEC (WAVPACK, wavpack); - REGISTER_DECODER(WMALOSSLESS, wmalossless); - REGISTER_DECODER(WMAPRO, wmapro); - REGISTER_ENCDEC (WMAV1, wmav1); - REGISTER_ENCDEC (WMAV2, wmav2); - REGISTER_DECODER(WMAVOICE, wmavoice); - REGISTER_DECODER(WS_SND1, ws_snd1); - REGISTER_DECODER(XMA1, xma1); - REGISTER_DECODER(XMA2, xma2); - - /* PCM codecs */ - REGISTER_ENCDEC (PCM_ALAW, pcm_alaw); - REGISTER_DECODER(PCM_BLURAY, pcm_bluray); - REGISTER_DECODER(PCM_DVD, pcm_dvd); - REGISTER_DECODER(PCM_F16LE, pcm_f16le); - REGISTER_DECODER(PCM_F24LE, pcm_f24le); - REGISTER_ENCDEC (PCM_F32BE, pcm_f32be); - REGISTER_ENCDEC (PCM_F32LE, pcm_f32le); - REGISTER_ENCDEC (PCM_F64BE, pcm_f64be); - REGISTER_ENCDEC (PCM_F64LE, pcm_f64le); - REGISTER_DECODER(PCM_LXF, pcm_lxf); - REGISTER_ENCDEC (PCM_MULAW, pcm_mulaw); - REGISTER_ENCDEC (PCM_S8, pcm_s8); - REGISTER_ENCDEC (PCM_S8_PLANAR, pcm_s8_planar); - REGISTER_ENCDEC (PCM_S16BE, pcm_s16be); - REGISTER_ENCDEC (PCM_S16BE_PLANAR, pcm_s16be_planar); - REGISTER_ENCDEC (PCM_S16LE, pcm_s16le); - REGISTER_ENCDEC (PCM_S16LE_PLANAR, pcm_s16le_planar); - REGISTER_ENCDEC (PCM_S24BE, pcm_s24be); - REGISTER_ENCDEC (PCM_S24DAUD, pcm_s24daud); - REGISTER_ENCDEC (PCM_S24LE, pcm_s24le); - REGISTER_ENCDEC (PCM_S24LE_PLANAR, pcm_s24le_planar); - REGISTER_ENCDEC (PCM_S32BE, pcm_s32be); - REGISTER_ENCDEC (PCM_S32LE, pcm_s32le); - REGISTER_ENCDEC (PCM_S32LE_PLANAR, pcm_s32le_planar); - REGISTER_ENCDEC (PCM_S64BE, pcm_s64be); - REGISTER_ENCDEC (PCM_S64LE, pcm_s64le); - REGISTER_ENCDEC (PCM_U8, pcm_u8); - REGISTER_ENCDEC (PCM_U16BE, pcm_u16be); - REGISTER_ENCDEC (PCM_U16LE, pcm_u16le); - REGISTER_ENCDEC (PCM_U24BE, pcm_u24be); - REGISTER_ENCDEC (PCM_U24LE, pcm_u24le); - REGISTER_ENCDEC (PCM_U32BE, pcm_u32be); - REGISTER_ENCDEC (PCM_U32LE, pcm_u32le); - REGISTER_DECODER(PCM_ZORK, pcm_zork); - - /* DPCM codecs */ - REGISTER_DECODER(GREMLIN_DPCM, gremlin_dpcm); - REGISTER_DECODER(INTERPLAY_DPCM, interplay_dpcm); - REGISTER_ENCDEC (ROQ_DPCM, roq_dpcm); - REGISTER_DECODER(SOL_DPCM, sol_dpcm); - REGISTER_DECODER(XAN_DPCM, xan_dpcm); - - /* ADPCM codecs */ - REGISTER_DECODER(ADPCM_4XM, adpcm_4xm); - REGISTER_ENCDEC (ADPCM_ADX, adpcm_adx); - REGISTER_DECODER(ADPCM_AFC, adpcm_afc); - REGISTER_DECODER(ADPCM_AICA, adpcm_aica); - REGISTER_DECODER(ADPCM_CT, adpcm_ct); - REGISTER_DECODER(ADPCM_DTK, adpcm_dtk); - REGISTER_DECODER(ADPCM_EA, adpcm_ea); - REGISTER_DECODER(ADPCM_EA_MAXIS_XA, adpcm_ea_maxis_xa); - REGISTER_DECODER(ADPCM_EA_R1, adpcm_ea_r1); - REGISTER_DECODER(ADPCM_EA_R2, adpcm_ea_r2); - REGISTER_DECODER(ADPCM_EA_R3, adpcm_ea_r3); - REGISTER_DECODER(ADPCM_EA_XAS, adpcm_ea_xas); - REGISTER_ENCDEC (ADPCM_G722, adpcm_g722); - REGISTER_ENCDEC (ADPCM_G726, adpcm_g726); - REGISTER_ENCDEC (ADPCM_G726LE, adpcm_g726le); - REGISTER_DECODER(ADPCM_IMA_AMV, adpcm_ima_amv); - REGISTER_DECODER(ADPCM_IMA_APC, adpcm_ima_apc); - REGISTER_DECODER(ADPCM_IMA_DAT4, adpcm_ima_dat4); - REGISTER_DECODER(ADPCM_IMA_DK3, adpcm_ima_dk3); - REGISTER_DECODER(ADPCM_IMA_DK4, adpcm_ima_dk4); - REGISTER_DECODER(ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs); - REGISTER_DECODER(ADPCM_IMA_EA_SEAD, adpcm_ima_ea_sead); - REGISTER_DECODER(ADPCM_IMA_ISS, adpcm_ima_iss); - REGISTER_DECODER(ADPCM_IMA_OKI, adpcm_ima_oki); - REGISTER_ENCDEC (ADPCM_IMA_QT, adpcm_ima_qt); - REGISTER_DECODER(ADPCM_IMA_RAD, adpcm_ima_rad); - REGISTER_DECODER(ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg); - REGISTER_ENCDEC (ADPCM_IMA_WAV, adpcm_ima_wav); - REGISTER_DECODER(ADPCM_IMA_WS, adpcm_ima_ws); - REGISTER_ENCDEC (ADPCM_MS, adpcm_ms); - REGISTER_DECODER(ADPCM_MTAF, adpcm_mtaf); - REGISTER_DECODER(ADPCM_PSX, adpcm_psx); - REGISTER_DECODER(ADPCM_SBPRO_2, adpcm_sbpro_2); - REGISTER_DECODER(ADPCM_SBPRO_3, adpcm_sbpro_3); - REGISTER_DECODER(ADPCM_SBPRO_4, adpcm_sbpro_4); - REGISTER_ENCDEC (ADPCM_SWF, adpcm_swf); - REGISTER_DECODER(ADPCM_THP, adpcm_thp); - REGISTER_DECODER(ADPCM_THP_LE, adpcm_thp_le); - REGISTER_DECODER(ADPCM_VIMA, adpcm_vima); - REGISTER_DECODER(ADPCM_XA, adpcm_xa); - REGISTER_ENCDEC (ADPCM_YAMAHA, adpcm_yamaha); - - /* subtitles */ - REGISTER_ENCDEC (SSA, ssa); - REGISTER_ENCDEC (ASS, ass); - REGISTER_DECODER(CCAPTION, ccaption); - REGISTER_ENCDEC (DVBSUB, dvbsub); - REGISTER_ENCDEC (DVDSUB, dvdsub); - REGISTER_DECODER(JACOSUB, jacosub); - REGISTER_DECODER(MICRODVD, microdvd); - REGISTER_ENCDEC (MOVTEXT, movtext); - REGISTER_DECODER(MPL2, mpl2); - REGISTER_DECODER(PGSSUB, pgssub); - REGISTER_DECODER(PJS, pjs); - REGISTER_DECODER(REALTEXT, realtext); - REGISTER_DECODER(SAMI, sami); - REGISTER_ENCDEC (SRT, srt); - REGISTER_DECODER(STL, stl); - REGISTER_ENCDEC (SUBRIP, subrip); - REGISTER_DECODER(SUBVIEWER, subviewer); - REGISTER_DECODER(SUBVIEWER1, subviewer1); - REGISTER_ENCDEC (TEXT, text); - REGISTER_DECODER(VPLAYER, vplayer); - REGISTER_ENCDEC (WEBVTT, webvtt); - REGISTER_ENCDEC (XSUB, xsub); - - /* external libraries */ - REGISTER_ENCDEC (AAC_AT, aac_at); - REGISTER_DECODER(AC3_AT, ac3_at); - REGISTER_DECODER(ADPCM_IMA_QT_AT, adpcm_ima_qt_at); - REGISTER_ENCDEC (ALAC_AT, alac_at); - REGISTER_DECODER(AMR_NB_AT, amr_nb_at); - REGISTER_DECODER(EAC3_AT, eac3_at); - REGISTER_DECODER(GSM_MS_AT, gsm_ms_at); - REGISTER_ENCDEC (ILBC_AT, ilbc_at); - REGISTER_DECODER(MP1_AT, mp1_at); - REGISTER_DECODER(MP2_AT, mp2_at); - REGISTER_DECODER(MP3_AT, mp3_at); - REGISTER_ENCDEC (PCM_ALAW_AT, pcm_alaw_at); - REGISTER_ENCDEC (PCM_MULAW_AT, pcm_mulaw_at); - REGISTER_DECODER(QDMC_AT, qdmc_at); - REGISTER_DECODER(QDM2_AT, qdm2_at); - REGISTER_DECODER(LIBCELT, libcelt); - REGISTER_ENCDEC (LIBFDK_AAC, libfdk_aac); - REGISTER_ENCDEC (LIBGSM, libgsm); - REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms); - REGISTER_ENCDEC (LIBILBC, libilbc); - REGISTER_ENCODER(LIBMP3LAME, libmp3lame); - REGISTER_ENCDEC (LIBOPENCORE_AMRNB, libopencore_amrnb); - REGISTER_DECODER(LIBOPENCORE_AMRWB, libopencore_amrwb); - REGISTER_ENCDEC (LIBOPENJPEG, libopenjpeg); - REGISTER_ENCDEC (LIBOPUS, libopus); - REGISTER_DECODER(LIBRSVG, librsvg); - REGISTER_ENCODER(LIBSHINE, libshine); - REGISTER_ENCDEC (LIBSPEEX, libspeex); - REGISTER_ENCODER(LIBTHEORA, libtheora); - REGISTER_ENCODER(LIBTWOLAME, libtwolame); - REGISTER_ENCODER(LIBVO_AMRWBENC, libvo_amrwbenc); - REGISTER_ENCDEC (LIBVORBIS, libvorbis); - REGISTER_ENCDEC (LIBVPX_VP8, libvpx_vp8); - REGISTER_ENCDEC (LIBVPX_VP9, libvpx_vp9); - REGISTER_ENCODER(LIBWAVPACK, libwavpack); - REGISTER_ENCODER(LIBWEBP_ANIM, libwebp_anim); /* preferred over libwebp */ - REGISTER_ENCODER(LIBWEBP, libwebp); - REGISTER_ENCODER(LIBX262, libx262); - REGISTER_ENCODER(LIBX264, libx264); - REGISTER_ENCODER(LIBX264RGB, libx264rgb); - REGISTER_ENCODER(LIBX265, libx265); - REGISTER_ENCODER(LIBXAVS, libxavs); - REGISTER_ENCODER(LIBXVID, libxvid); - REGISTER_DECODER(LIBZVBI_TELETEXT, libzvbi_teletext); - - /* text */ - REGISTER_DECODER(BINTEXT, bintext); - REGISTER_DECODER(XBIN, xbin); - REGISTER_DECODER(IDF, idf); - - /* external libraries, that shouldn't be used by default if one of the - * above is available */ - REGISTER_ENCODER(H263_V4L2M2M, h263_v4l2m2m); - REGISTER_ENCDEC (LIBOPENH264, libopenh264); - REGISTER_ENCODER(H264_AMF, h264_amf); - REGISTER_DECODER(H264_CUVID, h264_cuvid); - REGISTER_ENCODER(H264_NVENC, h264_nvenc); - REGISTER_ENCODER(H264_OMX, h264_omx); - REGISTER_ENCODER(H264_QSV, h264_qsv); - REGISTER_ENCODER(H264_V4L2M2M, h264_v4l2m2m); - REGISTER_ENCODER(H264_VAAPI, h264_vaapi); - REGISTER_ENCODER(H264_VIDEOTOOLBOX, h264_videotoolbox); -#if FF_API_NVENC_OLD_NAME - REGISTER_ENCODER(NVENC, nvenc); - REGISTER_ENCODER(NVENC_H264, nvenc_h264); - REGISTER_ENCODER(NVENC_HEVC, nvenc_hevc); -#endif - REGISTER_ENCODER(HEVC_AMF, hevc_amf); - REGISTER_DECODER(HEVC_CUVID, hevc_cuvid); - REGISTER_DECODER(HEVC_MEDIACODEC, hevc_mediacodec); - REGISTER_ENCODER(HEVC_NVENC, hevc_nvenc); - REGISTER_ENCODER(HEVC_QSV, hevc_qsv); - REGISTER_ENCODER(HEVC_V4L2M2M, hevc_v4l2m2m); - REGISTER_ENCODER(HEVC_VAAPI, hevc_vaapi); - REGISTER_ENCODER(HEVC_VIDEOTOOLBOX, hevc_videotoolbox); - REGISTER_ENCODER(LIBKVAZAAR, libkvazaar); - REGISTER_DECODER(MJPEG_CUVID, mjpeg_cuvid); - REGISTER_ENCODER(MJPEG_QSV, mjpeg_qsv); - REGISTER_ENCODER(MJPEG_VAAPI, mjpeg_vaapi); - REGISTER_DECODER(MPEG1_CUVID, mpeg1_cuvid); - REGISTER_DECODER(MPEG2_CUVID, mpeg2_cuvid); - REGISTER_ENCODER(MPEG2_QSV, mpeg2_qsv); - REGISTER_ENCODER(MPEG2_VAAPI, mpeg2_vaapi); - REGISTER_DECODER(MPEG4_CUVID, mpeg4_cuvid); - REGISTER_DECODER(MPEG4_MEDIACODEC, mpeg4_mediacodec); - REGISTER_ENCODER(MPEG4_V4L2M2M, mpeg4_v4l2m2m); - REGISTER_DECODER(VC1_CUVID, vc1_cuvid); - REGISTER_DECODER(VP8_CUVID, vp8_cuvid); - REGISTER_DECODER(VP8_MEDIACODEC, vp8_mediacodec); - REGISTER_DECODER(VP8_QSV, vp8_qsv); - REGISTER_ENCODER(VP8_V4L2M2M, vp8_v4l2m2m); - REGISTER_ENCODER(VP8_VAAPI, vp8_vaapi); - REGISTER_DECODER(VP9_CUVID, vp9_cuvid); - REGISTER_DECODER(VP9_MEDIACODEC, vp9_mediacodec); - REGISTER_ENCODER(VP9_VAAPI, vp9_vaapi); - - /* parsers */ - REGISTER_PARSER(AAC, aac); - REGISTER_PARSER(AAC_LATM, aac_latm); - REGISTER_PARSER(AC3, ac3); - REGISTER_PARSER(ADX, adx); - REGISTER_PARSER(BMP, bmp); - REGISTER_PARSER(CAVSVIDEO, cavsvideo); - REGISTER_PARSER(COOK, cook); - REGISTER_PARSER(DCA, dca); - REGISTER_PARSER(DIRAC, dirac); - REGISTER_PARSER(DNXHD, dnxhd); - REGISTER_PARSER(DPX, dpx); - REGISTER_PARSER(DVAUDIO, dvaudio); - REGISTER_PARSER(DVBSUB, dvbsub); - REGISTER_PARSER(DVDSUB, dvdsub); - REGISTER_PARSER(DVD_NAV, dvd_nav); - REGISTER_PARSER(FLAC, flac); - REGISTER_PARSER(G729, g729); - REGISTER_PARSER(GSM, gsm); - REGISTER_PARSER(H261, h261); - REGISTER_PARSER(H263, h263); - REGISTER_PARSER(H264, h264); - REGISTER_PARSER(HEVC, hevc); - REGISTER_PARSER(MJPEG, mjpeg); - REGISTER_PARSER(MLP, mlp); - REGISTER_PARSER(MPEG4VIDEO, mpeg4video); - REGISTER_PARSER(MPEGAUDIO, mpegaudio); - REGISTER_PARSER(MPEGVIDEO, mpegvideo); - REGISTER_PARSER(OPUS, opus); - REGISTER_PARSER(PNG, png); - REGISTER_PARSER(PNM, pnm); - REGISTER_PARSER(RV30, rv30); - REGISTER_PARSER(RV40, rv40); - REGISTER_PARSER(SIPR, sipr); - REGISTER_PARSER(TAK, tak); - REGISTER_PARSER(VC1, vc1); - REGISTER_PARSER(VORBIS, vorbis); - REGISTER_PARSER(VP3, vp3); - REGISTER_PARSER(VP8, vp8); - REGISTER_PARSER(VP9, vp9); - REGISTER_PARSER(XMA, xma); + ff_thread_once(&av_codec_next_init, av_codec_init_next); +} + +AVCodec *av_codec_next(const AVCodec *c) +{ + ff_thread_once(&av_codec_next_init, av_codec_init_next); + + if (c) + return c->next; + else + return (AVCodec*)codec_list[0]; } void avcodec_register_all(void) { - static AVOnce control = AV_ONCE_INIT; + ff_thread_once(&av_codec_next_init, av_codec_init_next); +} +FF_ENABLE_DEPRECATION_WARNINGS +#endif + +static enum AVCodecID remap_deprecated_codec_id(enum AVCodecID id) +{ + switch(id){ + //This is for future deprecatec codec ids, its empty since + //last major bump but will fill up again over time, please don't remove it + default : return id; + } +} + +static AVCodec *find_codec(enum AVCodecID id, int (*x)(const AVCodec *)) +{ + const AVCodec *p, *experimental = NULL; + void *i = 0; + + id = remap_deprecated_codec_id(id); + + while ((p = av_codec_iterate(&i))) { + if (!x(p)) + continue; + if (p->id == id) { + if (p->capabilities & AV_CODEC_CAP_EXPERIMENTAL && !experimental) { + experimental = p; + } else + return (AVCodec*)p; + } + } + + return (AVCodec*)experimental; +} + +AVCodec *avcodec_find_encoder(enum AVCodecID id) +{ + return find_codec(id, av_codec_is_encoder); +} + +AVCodec *avcodec_find_decoder(enum AVCodecID id) +{ + return find_codec(id, av_codec_is_decoder); +} - ff_thread_once(&control, register_all); +static AVCodec *find_codec_by_name(const char *name, int (*x)(const AVCodec *)) +{ + void *i = 0; + const AVCodec *p; + + if (!name) + return NULL; + + while ((p = av_codec_iterate(&i))) { + if (!x(p)) + continue; + if (strcmp(name, p->name) == 0) + return (AVCodec*)p; + } + + return NULL; +} + +AVCodec *avcodec_find_encoder_by_name(const char *name) +{ + return find_codec_by_name(name, av_codec_is_encoder); +} + +AVCodec *avcodec_find_decoder_by_name(const char *name) +{ + return find_codec_by_name(name, av_codec_is_decoder); } diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 8fbbc798a2e65..99f5fb9da0999 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3978,12 +3978,26 @@ typedef struct AVCodecParameters { int seek_preroll; } AVCodecParameters; +/** + * Iterate over all registered codecs. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec or NULL when the iteration is + * finished + */ +const AVCodec *av_codec_iterate(void **opaque); + +#if FF_API_NEXT /** * If c is NULL, returns the first registered codec, * if c is non-NULL, returns the next registered codec after c, * or NULL if c is the last one. */ +attribute_deprecated AVCodec *av_codec_next(const AVCodec *c); +#endif /** * Return the LIBAVCODEC_VERSION_INT constant. @@ -4000,6 +4014,7 @@ const char *avcodec_configuration(void); */ const char *avcodec_license(void); +#if FF_API_NEXT /** * Register the codec codec and initialize libavcodec. * @@ -4008,6 +4023,7 @@ const char *avcodec_license(void); * * @see avcodec_register_all() */ +attribute_deprecated void avcodec_register(AVCodec *codec); /** @@ -4020,7 +4036,9 @@ void avcodec_register(AVCodec *codec); * @see av_register_codec_parser * @see av_register_bitstream_filter */ +attribute_deprecated void avcodec_register_all(void); +#endif /** * Allocate an AVCodecContext and set its fields to default values. The @@ -5120,8 +5138,21 @@ typedef struct AVCodecParser { struct AVCodecParser *next; } AVCodecParser; +/** + * Iterate over all registered codec parsers. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec parser or NULL when the iteration is + * finished + */ +const AVCodecParser *av_parser_iterate(void **opaque); + +attribute_deprecated AVCodecParser *av_parser_next(const AVCodecParser *c); +attribute_deprecated void av_register_codec_parser(AVCodecParser *parser); AVCodecParserContext *av_parser_init(int codec_id); diff --git a/libavcodec/parser.c b/libavcodec/parser.c index 747ea2ee8aaca..0c66e80b96ac6 100644 --- a/libavcodec/parser.c +++ b/libavcodec/parser.c @@ -32,36 +32,100 @@ #include "internal.h" #include "parser.h" -static AVCodecParser *av_first_parser = NULL; +/* Parsers */ +extern AVCodecParser ff_aac_parser; +extern AVCodecParser ff_aac_latm_parser; +extern AVCodecParser ff_ac3_parser; +extern AVCodecParser ff_adx_parser; +extern AVCodecParser ff_bmp_parser; +extern AVCodecParser ff_cavsvideo_parser; +extern AVCodecParser ff_cook_parser; +extern AVCodecParser ff_dca_parser; +extern AVCodecParser ff_dirac_parser; +extern AVCodecParser ff_dnxhd_parser; +extern AVCodecParser ff_dpx_parser; +extern AVCodecParser ff_dvaudio_parser; +extern AVCodecParser ff_dvbsub_parser; +extern AVCodecParser ff_dvdsub_parser; +extern AVCodecParser ff_dvd_nav_parser; +extern AVCodecParser ff_flac_parser; +extern AVCodecParser ff_g729_parser; +extern AVCodecParser ff_gsm_parser; +extern AVCodecParser ff_h261_parser; +extern AVCodecParser ff_h263_parser; +extern AVCodecParser ff_h264_parser; +extern AVCodecParser ff_hevc_parser; +extern AVCodecParser ff_mjpeg_parser; +extern AVCodecParser ff_mlp_parser; +extern AVCodecParser ff_mpeg4video_parser; +extern AVCodecParser ff_mpegaudio_parser; +extern AVCodecParser ff_mpegvideo_parser; +extern AVCodecParser ff_opus_parser; +extern AVCodecParser ff_png_parser; +extern AVCodecParser ff_pnm_parser; +extern AVCodecParser ff_rv30_parser; +extern AVCodecParser ff_rv40_parser; +extern AVCodecParser ff_sipr_parser; +extern AVCodecParser ff_tak_parser; +extern AVCodecParser ff_vc1_parser; +extern AVCodecParser ff_vorbis_parser; +extern AVCodecParser ff_vp3_parser; +extern AVCodecParser ff_vp8_parser; +extern AVCodecParser ff_vp9_parser; +extern AVCodecParser ff_xma_parser; + +#include "libavcodec/parser_list.c" + +static AVOnce av_parser_next_init = AV_ONCE_INIT; + +static void av_parser_init_next(void) +{ + AVCodecParser *prev = NULL, *p; + int i = 0; + while ((p = (AVCodecParser*)parser_list[i++])) { + if (prev) + prev->next = p; + prev = p; + } +} AVCodecParser *av_parser_next(const AVCodecParser *p) { + ff_thread_once(&av_parser_next_init, av_parser_init_next); + if (p) return p->next; else - return av_first_parser; + return (AVCodecParser*)parser_list[0]; } -static AVMutex parser_register_mutex = AV_MUTEX_INITIALIZER; +const AVCodecParser *av_parser_iterate(void **opaque) +{ + uintptr_t i = (uintptr_t)*opaque; + const AVCodecParser *p = parser_list[i]; + + if (p) + *opaque = (void*)(i + 1); + + return p; +} void av_register_codec_parser(AVCodecParser *parser) { - ff_mutex_lock(&parser_register_mutex); - parser->next = av_first_parser; - av_first_parser = parser; - ff_mutex_unlock(&parser_register_mutex); + ff_thread_once(&av_parser_next_init, av_parser_init_next); } AVCodecParserContext *av_parser_init(int codec_id) { AVCodecParserContext *s = NULL; - AVCodecParser *parser; + const AVCodecParser *parser; + void *i = 0; int ret; if (codec_id == AV_CODEC_ID_NONE) return NULL; - for (parser = av_first_parser; parser; parser = parser->next) { + while ((parser = av_parser_iterate(&i))) { if (parser->codec_ids[0] == codec_id || parser->codec_ids[1] == codec_id || parser->codec_ids[2] == codec_id || @@ -75,7 +139,7 @@ AVCodecParserContext *av_parser_init(int codec_id) s = av_mallocz(sizeof(AVCodecParserContext)); if (!s) goto err_out; - s->parser = parser; + s->parser = (AVCodecParser*)parser; s->priv_data = av_mallocz(parser->priv_data_size); if (!s->priv_data) goto err_out; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index aefe6315902d6..8c7d056da6454 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -46,7 +46,6 @@ #include "decode.h" #include "hwaccel.h" #include "libavutil/opt.h" -#include "me_cmp.h" #include "mpegvideo.h" #include "thread.h" #include "frame_thread_encoder.h" @@ -92,18 +91,6 @@ void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size) memset(*p, 0, min_size + AV_INPUT_BUFFER_PADDING_SIZE); } -/* encoder management */ -static AVCodec *first_avcodec = NULL; -static AVCodec **last_avcodec = &first_avcodec; - -AVCodec *av_codec_next(const AVCodec *c) -{ - if (c) - return c->next; - else - return first_avcodec; -} - int av_codec_is_encoder(const AVCodec *codec) { return codec && (codec->encode_sub || codec->encode2 ||codec->send_frame); @@ -114,27 +101,6 @@ int av_codec_is_decoder(const AVCodec *codec) return codec && (codec->decode || codec->receive_frame); } -static AVMutex codec_register_mutex = AV_MUTEX_INITIALIZER; - -av_cold void avcodec_register(AVCodec *codec) -{ - AVCodec **p; - - ff_mutex_lock(&codec_register_mutex); - p = last_avcodec; - - while (*p) - p = &(*p)->next; - *p = codec; - codec->next = NULL; - last_avcodec = &codec->next; - - ff_mutex_unlock(&codec_register_mutex); - - if (codec->init_static_data) - codec->init_static_data(codec); -} - int ff_set_dimensions(AVCodecContext *s, int width, int height) { int ret = av_image_check_size2(width, height, s->max_pixels, AV_PIX_FMT_NONE, 0, s); @@ -1155,71 +1121,6 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; } -static enum AVCodecID remap_deprecated_codec_id(enum AVCodecID id) -{ - switch(id){ - //This is for future deprecatec codec ids, its empty since - //last major bump but will fill up again over time, please don't remove it - default : return id; - } -} - -static AVCodec *find_encdec(enum AVCodecID id, int encoder) -{ - AVCodec *p, *experimental = NULL; - p = first_avcodec; - id= remap_deprecated_codec_id(id); - while (p) { - if ((encoder ? av_codec_is_encoder(p) : av_codec_is_decoder(p)) && - p->id == id) { - if (p->capabilities & AV_CODEC_CAP_EXPERIMENTAL && !experimental) { - experimental = p; - } else - return p; - } - p = p->next; - } - return experimental; -} - -AVCodec *avcodec_find_encoder(enum AVCodecID id) -{ - return find_encdec(id, 1); -} - -AVCodec *avcodec_find_encoder_by_name(const char *name) -{ - AVCodec *p; - if (!name) - return NULL; - p = first_avcodec; - while (p) { - if (av_codec_is_encoder(p) && strcmp(name, p->name) == 0) - return p; - p = p->next; - } - return NULL; -} - -AVCodec *avcodec_find_decoder(enum AVCodecID id) -{ - return find_encdec(id, 0); -} - -AVCodec *avcodec_find_decoder_by_name(const char *name) -{ - AVCodec *p; - if (!name) - return NULL; - p = first_avcodec; - while (p) { - if (av_codec_is_decoder(p) && strcmp(name, p->name) == 0) - return p; - p = p->next; - } - return NULL; -} - const char *avcodec_get_name(enum AVCodecID id) { const AVCodecDescriptor *cd; diff --git a/libavcodec/version.h b/libavcodec/version.h index 47a15d52b8f09..8cc0f9bf9c3fe 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -129,6 +129,9 @@ #ifndef FF_API_LOCKMGR #define FF_API_LOCKMGR (LIBAVCODEC_VERSION_MAJOR < 59) #endif +#ifndef FF_API_NEXT +#define FF_API_NEXT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif #endif /* AVCODEC_VERSION_H */ From 61974537610d82bd35b6e3ac91ccd270c6bdc711 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Mon, 1 Jan 2018 23:31:26 +0000 Subject: [PATCH 1804/2557] lavf/rtp: replace linked list with array --- libavformat/allformats.c | 4 -- libavformat/rdt.c | 9 +-- libavformat/rdt.h | 5 -- libavformat/rtpdec.c | 138 ++++++++++++++++++++++----------------- libavformat/rtpdec.h | 25 ++++++- 5 files changed, 100 insertions(+), 81 deletions(-) diff --git a/libavformat/allformats.c b/libavformat/allformats.c index ec8409630e592..83ed766559c2b 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -282,10 +282,6 @@ static void register_all(void) REGISTER_DEMUXER (SDR2, sdr2); REGISTER_DEMUXER (SDS, sds); REGISTER_DEMUXER (SDX, sdx); -#if CONFIG_RTPDEC - ff_register_rtp_dynamic_payload_handlers(); - ff_register_rdt_dynamic_payload_handlers(); -#endif REGISTER_DEMUXER (SEGAFILM, segafilm); REGISTER_MUXER (SEGMENT, segment); REGISTER_MUXER (SEGMENT, stream_segment); diff --git a/libavformat/rdt.c b/libavformat/rdt.c index b69827fcbfcd6..31a32ffec3dca 100644 --- a/libavformat/rdt.c +++ b/libavformat/rdt.c @@ -554,7 +554,7 @@ rdt_close_context (PayloadContext *rdt) } #define RDT_HANDLER(n, s, t) \ -static RTPDynamicProtocolHandler rdt_ ## n ## _handler = { \ +RTPDynamicProtocolHandler ff_rdt_ ## n ## _handler = { \ .enc_name = s, \ .codec_type = t, \ .codec_id = AV_CODEC_ID_NONE, \ @@ -570,10 +570,3 @@ RDT_HANDLER(live_audio, "x-pn-multirate-realaudio-live", AVMEDIA_TYPE_AUDIO); RDT_HANDLER(video, "x-pn-realvideo", AVMEDIA_TYPE_VIDEO); RDT_HANDLER(audio, "x-pn-realaudio", AVMEDIA_TYPE_AUDIO); -void ff_register_rdt_dynamic_payload_handlers(void) -{ - ff_register_dynamic_payload_handler(&rdt_video_handler); - ff_register_dynamic_payload_handler(&rdt_audio_handler); - ff_register_dynamic_payload_handler(&rdt_live_video_handler); - ff_register_dynamic_payload_handler(&rdt_live_audio_handler); -} diff --git a/libavformat/rdt.h b/libavformat/rdt.h index ce6026f49c251..248056568833c 100644 --- a/libavformat/rdt.h +++ b/libavformat/rdt.h @@ -59,11 +59,6 @@ void ff_rdt_parse_close(RDTDemuxContext *s); void ff_rdt_calc_response_and_checksum(char response[41], char chksum[9], const char *challenge); -/** - * Register RDT-related dynamic payload handlers with our cache. - */ -void ff_register_rdt_dynamic_payload_handlers(void); - /** * Add subscription information to Subscribe parameter string. * diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index 4acb1ca629d4b..6499e275ffb00 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -69,88 +69,104 @@ static RTPDynamicProtocolHandler t140_dynamic_handler = { /* RFC 4103 */ .codec_id = AV_CODEC_ID_TEXT, }; -static RTPDynamicProtocolHandler *rtp_first_dynamic_payload_handler = NULL; +extern RTPDynamicProtocolHandler ff_rdt_video_handler; +extern RTPDynamicProtocolHandler ff_rdt_audio_handler; +extern RTPDynamicProtocolHandler ff_rdt_live_video_handler; +extern RTPDynamicProtocolHandler ff_rdt_live_audio_handler; + +static const RTPDynamicProtocolHandler *rtp_dynamic_protocol_handler_list[] = { + /* rtp */ + &ff_ac3_dynamic_handler, + &ff_amr_nb_dynamic_handler, + &ff_amr_wb_dynamic_handler, + &ff_dv_dynamic_handler, + &ff_g726_16_dynamic_handler, + &ff_g726_24_dynamic_handler, + &ff_g726_32_dynamic_handler, + &ff_g726_40_dynamic_handler, + &ff_g726le_16_dynamic_handler, + &ff_g726le_24_dynamic_handler, + &ff_g726le_32_dynamic_handler, + &ff_g726le_40_dynamic_handler, + &ff_h261_dynamic_handler, + &ff_h263_1998_dynamic_handler, + &ff_h263_2000_dynamic_handler, + &ff_h263_rfc2190_dynamic_handler, + &ff_h264_dynamic_handler, + &ff_hevc_dynamic_handler, + &ff_ilbc_dynamic_handler, + &ff_jpeg_dynamic_handler, + &ff_mp4a_latm_dynamic_handler, + &ff_mp4v_es_dynamic_handler, + &ff_mpeg_audio_dynamic_handler, + &ff_mpeg_audio_robust_dynamic_handler, + &ff_mpeg_video_dynamic_handler, + &ff_mpeg4_generic_dynamic_handler, + &ff_mpegts_dynamic_handler, + &ff_ms_rtp_asf_pfa_handler, + &ff_ms_rtp_asf_pfv_handler, + &ff_qcelp_dynamic_handler, + &ff_qdm2_dynamic_handler, + &ff_qt_rtp_aud_handler, + &ff_qt_rtp_vid_handler, + &ff_quicktime_rtp_aud_handler, + &ff_quicktime_rtp_vid_handler, + &ff_rfc4175_rtp_handler, + &ff_svq3_dynamic_handler, + &ff_theora_dynamic_handler, + &ff_vc2hq_dynamic_handler, + &ff_vorbis_dynamic_handler, + &ff_vp8_dynamic_handler, + &ff_vp9_dynamic_handler, + &gsm_dynamic_handler, + &l24_dynamic_handler, + &opus_dynamic_handler, + &realmedia_mp3_dynamic_handler, + &speex_dynamic_handler, + &t140_dynamic_handler, + /* rdt */ + &ff_rdt_video_handler, + &ff_rdt_audio_handler, + &ff_rdt_live_video_handler, + &ff_rdt_live_audio_handler, + NULL, +}; -void ff_register_dynamic_payload_handler(RTPDynamicProtocolHandler *handler) +const RTPDynamicProtocolHandler *ff_rtp_handler_iterate(void **opaque) { - handler->next = rtp_first_dynamic_payload_handler; - rtp_first_dynamic_payload_handler = handler; -} + uintptr_t i = (uintptr_t)*opaque; + const RTPDynamicProtocolHandler *r = rtp_dynamic_protocol_handler_list[i]; -void ff_register_rtp_dynamic_payload_handlers(void) -{ - ff_register_dynamic_payload_handler(&ff_ac3_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_amr_nb_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_amr_wb_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_dv_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_g726_16_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_g726_24_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_g726_32_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_g726_40_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_g726le_16_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_g726le_24_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_g726le_32_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_g726le_40_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_h261_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_h263_1998_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_h263_2000_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_h263_rfc2190_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_h264_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_hevc_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_ilbc_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_jpeg_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_mp4a_latm_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_mp4v_es_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_mpeg_audio_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_mpeg_audio_robust_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_mpeg_video_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_mpeg4_generic_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_mpegts_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfa_handler); - ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfv_handler); - ff_register_dynamic_payload_handler(&ff_qcelp_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_qdm2_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_qt_rtp_aud_handler); - ff_register_dynamic_payload_handler(&ff_qt_rtp_vid_handler); - ff_register_dynamic_payload_handler(&ff_quicktime_rtp_aud_handler); - ff_register_dynamic_payload_handler(&ff_quicktime_rtp_vid_handler); - ff_register_dynamic_payload_handler(&ff_rfc4175_rtp_handler); - ff_register_dynamic_payload_handler(&ff_svq3_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_theora_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_vc2hq_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_vorbis_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_vp8_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_vp9_dynamic_handler); - ff_register_dynamic_payload_handler(&gsm_dynamic_handler); - ff_register_dynamic_payload_handler(&l24_dynamic_handler); - ff_register_dynamic_payload_handler(&opus_dynamic_handler); - ff_register_dynamic_payload_handler(&realmedia_mp3_dynamic_handler); - ff_register_dynamic_payload_handler(&speex_dynamic_handler); - ff_register_dynamic_payload_handler(&t140_dynamic_handler); + if (r) + *opaque = (void*)(i + 1); + + return r; } RTPDynamicProtocolHandler *ff_rtp_handler_find_by_name(const char *name, enum AVMediaType codec_type) { - RTPDynamicProtocolHandler *handler; - for (handler = rtp_first_dynamic_payload_handler; - handler; handler = handler->next) + void *i = 0; + const RTPDynamicProtocolHandler *handler; + while (handler = ff_rtp_handler_iterate(&i)) { if (handler->enc_name && !av_strcasecmp(name, handler->enc_name) && codec_type == handler->codec_type) return handler; + } return NULL; } RTPDynamicProtocolHandler *ff_rtp_handler_find_by_id(int id, enum AVMediaType codec_type) { - RTPDynamicProtocolHandler *handler; - for (handler = rtp_first_dynamic_payload_handler; - handler; handler = handler->next) + void *i = 0; + const RTPDynamicProtocolHandler *handler; + while (handler = ff_rtp_handler_iterate(&i)) { if (handler->static_payload_id && handler->static_payload_id == id && codec_type == handler->codec_type) return handler; + } return NULL; } diff --git a/libavformat/rtpdec.h b/libavformat/rtpdec.h index 77596b6707444..fe726a6886579 100644 --- a/libavformat/rtpdec.h +++ b/libavformat/rtpdec.h @@ -192,9 +192,30 @@ struct RTPDemuxContext { PayloadContext *dynamic_protocol_context; }; -void ff_register_dynamic_payload_handler(RTPDynamicProtocolHandler *handler); +/** + * Iterate over all registered rtp dynamic protocol handlers. + * + * @param opaque a pointer where libavformat will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered rtp dynamic protocol handler or NULL when the iteration is + * finished + */ +const RTPDynamicProtocolHandler *ff_rtp_handler_iterate(void **opaque); +/** + * Find a registered rtp dynamic protocol handler with the specified name. + * + * @param name name of the requested rtp dynamic protocol handler + * @return A rtp dynamic protocol handler if one was found, NULL otherwise. + */ RTPDynamicProtocolHandler *ff_rtp_handler_find_by_name(const char *name, enum AVMediaType codec_type); +/** + * Find a registered rtp dynamic protocol handler with a matching codec ID. + * + * @param id AVCodecID of the requested rtp dynamic protocol handler. + * @return A rtp dynamic protocol handler if one was found, NULL otherwise. + */ RTPDynamicProtocolHandler *ff_rtp_handler_find_by_id(int id, enum AVMediaType codec_type); @@ -209,8 +230,6 @@ int ff_parse_fmtp(AVFormatContext *s, PayloadContext *data, const char *attr, const char *value)); -void ff_register_rtp_dynamic_payload_handlers(void); - /** * Close the dynamic buffer and make a packet from it. */ From 598d5f8579b3a048a643486a5f20fc4d479a2017 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Tue, 2 Jan 2018 13:36:05 +0000 Subject: [PATCH 1805/2557] lavf: move fifo test muxer into separate file This fixes the fate-fifo-muxer test with the clarified removal of registering external formats. --- libavformat/Makefile | 2 +- libavformat/allformats.c | 1 + libavformat/fifo_test.c | 151 +++++++++++++++++++++++++++++++++ libavformat/tests/fifo_muxer.c | 115 +------------------------ 4 files changed, 155 insertions(+), 114 deletions(-) create mode 100644 libavformat/fifo_test.c diff --git a/libavformat/Makefile b/libavformat/Makefile index de0de921c2d3b..e0bb8aef86eff 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -163,7 +163,7 @@ OBJS-$(CONFIG_EAC3_MUXER) += rawenc.o OBJS-$(CONFIG_EPAF_DEMUXER) += epafdec.o pcm.o OBJS-$(CONFIG_FFMETADATA_DEMUXER) += ffmetadec.o OBJS-$(CONFIG_FFMETADATA_MUXER) += ffmetaenc.o -OBJS-$(CONFIG_FIFO_MUXER) += fifo.o +OBJS-$(CONFIG_FIFO_MUXER) += fifo.o fifo_test.o OBJS-$(CONFIG_FILMSTRIP_DEMUXER) += filmstripdec.o OBJS-$(CONFIG_FILMSTRIP_MUXER) += filmstripenc.o OBJS-$(CONFIG_FITS_DEMUXER) += fitsdec.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 83ed766559c2b..ce4f0d8c76e78 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -122,6 +122,7 @@ static void register_all(void) REGISTER_MUXER (F4V, f4v); REGISTER_MUXDEMUX(FFMETADATA, ffmetadata); REGISTER_MUXER (FIFO, fifo); + REGISTER_MUXER (FIFO, fifo_test); REGISTER_MUXDEMUX(FILMSTRIP, filmstrip); REGISTER_MUXDEMUX(FITS, fits); REGISTER_MUXDEMUX(FLAC, flac); diff --git a/libavformat/fifo_test.c b/libavformat/fifo_test.c new file mode 100644 index 0000000000000..188e607855944 --- /dev/null +++ b/libavformat/fifo_test.c @@ -0,0 +1,151 @@ +/* + * FIFO test pseudo-muxer + * Copyright (c) 2016 Jan Sebechlebsky + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with FFmpeg; if not, write to the Free Software * Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "libavutil/opt.h" +#include "libavutil/time.h" +#include "libavutil/avassert.h" +#include "libavformat/avformat.h" +#include "libavformat/url.h" +#include "libavformat/network.h" + +/* Implementation of mock muxer to simulate real muxer failures */ + +#define MAX_TST_PACKETS 128 +#define SLEEPTIME_50_MS 50000 +#define SLEEPTIME_10_MS 10000 + +/* Implementation of mock muxer to simulate real muxer failures */ + +/* This is structure of data sent in packets to + * failing muxer */ +typedef struct FailingMuxerPacketData { + int ret; /* return value of write_packet call*/ + int recover_after; /* set ret to zero after this number of recovery attempts */ + unsigned sleep_time; /* sleep for this long in write_packet to simulate long I/O operation */ +} FailingMuxerPacketData; + + +typedef struct FailingMuxerContext { + AVClass *class; + int write_header_ret; + int write_trailer_ret; + /* If non-zero, summary of processed packets will be printed in deinit */ + int print_deinit_summary; + + int flush_count; + int pts_written[MAX_TST_PACKETS]; + int pts_written_nr; +} FailingMuxerContext; + +static int failing_write_header(AVFormatContext *avf) +{ + FailingMuxerContext *ctx = avf->priv_data; + return ctx->write_header_ret; +} + +static int failing_write_packet(AVFormatContext *avf, AVPacket *pkt) +{ + FailingMuxerContext *ctx = avf->priv_data; + int ret = 0; + if (!pkt) { + ctx->flush_count++; + } else { + FailingMuxerPacketData *data = (FailingMuxerPacketData*) pkt->data; + + if (!data->recover_after) { + data->ret = 0; + } else { + data->recover_after--; + } + + ret = data->ret; + + if (data->sleep_time) { + int64_t slept = 0; + while (slept < data->sleep_time) { + if (ff_check_interrupt(&avf->interrupt_callback)) + return AVERROR_EXIT; + av_usleep(SLEEPTIME_10_MS); + slept += SLEEPTIME_10_MS; + } + } + + if (!ret) { + ctx->pts_written[ctx->pts_written_nr++] = pkt->pts; + av_packet_unref(pkt); + } + } + return ret; +} + +static int failing_write_trailer(AVFormatContext *avf) +{ + FailingMuxerContext *ctx = avf->priv_data; + return ctx->write_trailer_ret; +} + +static void failing_deinit(AVFormatContext *avf) +{ + int i; + FailingMuxerContext *ctx = avf->priv_data; + + if (!ctx->print_deinit_summary) + return; + + printf("flush count: %d\n", ctx->flush_count); + printf("pts seen nr: %d\n", ctx->pts_written_nr); + printf("pts seen: "); + for (i = 0; i < ctx->pts_written_nr; ++i ) { + printf(i ? ",%d" : "%d", ctx->pts_written[i]); + } + printf("\n"); +} +#define OFFSET(x) offsetof(FailingMuxerContext, x) +static const AVOption options[] = { + {"write_header_ret", "write_header() return value", OFFSET(write_header_ret), + AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, + {"write_trailer_ret", "write_trailer() return value", OFFSET(write_trailer_ret), + AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, + {"print_deinit_summary", "print summary when deinitializing muxer", OFFSET(print_deinit_summary), + AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, + {NULL} + }; + +static const AVClass failing_muxer_class = { + .class_name = "Fifo test muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVOutputFormat ff_fifo_test_muxer = { + .name = "fifo_test", + .long_name = NULL_IF_CONFIG_SMALL("Fifo test muxer"), + .priv_data_size = sizeof(FailingMuxerContext), + .write_header = failing_write_header, + .write_packet = failing_write_packet, + .write_trailer = failing_write_trailer, + .deinit = failing_deinit, + .priv_class = &failing_muxer_class, + .flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH, +}; + diff --git a/libavformat/tests/fifo_muxer.c b/libavformat/tests/fifo_muxer.c index 4b63df085e2b3..5127a8aadb926 100644 --- a/libavformat/tests/fifo_muxer.c +++ b/libavformat/tests/fifo_muxer.c @@ -31,8 +31,6 @@ #define SLEEPTIME_50_MS 50000 #define SLEEPTIME_10_MS 10000 -/* Implementation of mock muxer to simulate real muxer failures */ - /* This is structure of data sent in packets to * failing muxer */ typedef struct FailingMuxerPacketData { @@ -41,113 +39,7 @@ typedef struct FailingMuxerPacketData { unsigned sleep_time; /* sleep for this long in write_packet to simulate long I/O operation */ } FailingMuxerPacketData; - -typedef struct FailingMuxerContext { - AVClass *class; - int write_header_ret; - int write_trailer_ret; - /* If non-zero, summary of processed packets will be printed in deinit */ - int print_deinit_summary; - - int flush_count; - int pts_written[MAX_TST_PACKETS]; - int pts_written_nr; -} FailingMuxerContext; - -static int failing_write_header(AVFormatContext *avf) -{ - FailingMuxerContext *ctx = avf->priv_data; - return ctx->write_header_ret; -} - -static int failing_write_packet(AVFormatContext *avf, AVPacket *pkt) -{ - FailingMuxerContext *ctx = avf->priv_data; - int ret = 0; - if (!pkt) { - ctx->flush_count++; - } else { - FailingMuxerPacketData *data = (FailingMuxerPacketData*) pkt->data; - - if (!data->recover_after) { - data->ret = 0; - } else { - data->recover_after--; - } - - ret = data->ret; - - if (data->sleep_time) { - int64_t slept = 0; - while (slept < data->sleep_time) { - if (ff_check_interrupt(&avf->interrupt_callback)) - return AVERROR_EXIT; - av_usleep(SLEEPTIME_10_MS); - slept += SLEEPTIME_10_MS; - } - } - - if (!ret) { - ctx->pts_written[ctx->pts_written_nr++] = pkt->pts; - av_packet_unref(pkt); - } - } - return ret; -} - -static int failing_write_trailer(AVFormatContext *avf) -{ - FailingMuxerContext *ctx = avf->priv_data; - return ctx->write_trailer_ret; -} - -static void failing_deinit(AVFormatContext *avf) -{ - int i; - FailingMuxerContext *ctx = avf->priv_data; - - if (!ctx->print_deinit_summary) - return; - - printf("flush count: %d\n", ctx->flush_count); - printf("pts seen nr: %d\n", ctx->pts_written_nr); - printf("pts seen: "); - for (i = 0; i < ctx->pts_written_nr; ++i ) { - printf(i ? ",%d" : "%d", ctx->pts_written[i]); - } - printf("\n"); -} -#define OFFSET(x) offsetof(FailingMuxerContext, x) -static const AVOption options[] = { - {"write_header_ret", "write_header() return value", OFFSET(write_header_ret), - AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, - {"write_trailer_ret", "write_trailer() return value", OFFSET(write_trailer_ret), - AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, - {"print_deinit_summary", "print summary when deinitializing muxer", OFFSET(print_deinit_summary), - AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, - {NULL} - }; - -static const AVClass failing_muxer_class = { - .class_name = "Failing test muxer", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVOutputFormat tst_failing_muxer = { - .name = "fail", - .long_name = NULL_IF_CONFIG_SMALL("Failing test muxer"), - .priv_data_size = sizeof(FailingMuxerContext), - .write_header = failing_write_header, - .write_packet = failing_write_packet, - .write_trailer = failing_write_trailer, - .deinit = failing_deinit, - .priv_class = &failing_muxer_class, - .flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH, -}; - -static int prepare_packet(AVPacket *pkt,const FailingMuxerPacketData *pkt_data, int64_t pts) +static int prepare_packet(AVPacket *pkt, const FailingMuxerPacketData *pkt_data, int64_t pts) { int ret; FailingMuxerPacketData *data = av_malloc(sizeof(*data)); @@ -333,7 +225,7 @@ static int run_test(const TestCase *test) (int)test->print_summary_on_deinit, test->write_header_ret, test->write_trailer_ret); ret = av_dict_set(&opts, "format_opts", buffer, 0); - ret1 = av_dict_set(&opts, "fifo_format", "fail", 0); + ret1 = av_dict_set(&opts, "fifo_format", "fifo_test", 0); if (ret < 0 || ret1 < 0) { fprintf(stderr, "Failed to set options for test muxer: %s\n", av_err2str(ret)); @@ -382,9 +274,6 @@ int main(int argc, char *argv[]) { int i, ret, ret_all = 0; - av_register_all(); - av_register_output_format(&tst_failing_muxer); - for (i = 0; tests[i].test_func; i++) { ret = run_test(&tests[i]); if (!ret_all && ret < 0) From 0694d8702421e7aff1340038559c438b61bb30dd Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Sun, 21 Jan 2018 16:06:54 +0000 Subject: [PATCH 1806/2557] lavf: add new API for iterating muxers and demuxers --- Makefile | 3 +- configure | 6 +- doc/APIchanges | 7 +- libavformat/.gitignore | 2 + libavformat/allformats.c | 868 +++++++++++++++++++++++---------------- libavformat/avformat.h | 31 ++ libavformat/format.c | 68 +-- libavformat/version.h | 3 + 8 files changed, 567 insertions(+), 421 deletions(-) diff --git a/Makefile b/Makefile index 1d1c8865bc635..0cd0a1d6f2d55 100644 --- a/Makefile +++ b/Makefile @@ -143,7 +143,8 @@ distclean:: clean ffbuild/.config ffbuild/config.* libavutil/avconfig.h \ version.h libavutil/ffversion.h libavcodec/codec_names.h \ libavcodec/bsf_list.c libavformat/protocol_list.c \ - libavcodec/codec_list.c libavcodec/parser_list.c + libavcodec/codec_list.c libavcodec/parser_list.c \ + libavformat/muxer_list.c libavformat/demuxer_list.c ifeq ($(SRC_LINK),src) $(RM) src endif diff --git a/configure b/configure index 86c74d7c2c151..7c654575a6297 100755 --- a/configure +++ b/configure @@ -3525,8 +3525,6 @@ find_things(){ sed -n "s/^[^#]*$pattern.*([^,]*, *\([^,]*\)\(,.*\)*).*/\1_$thing/p" "$file" } -MUXER_LIST=$(find_things muxer _MUX libavformat/allformats.c) -DEMUXER_LIST=$(find_things demuxer DEMUX libavformat/allformats.c) OUTDEV_LIST=$(find_things outdev OUTDEV libavdevice/alldevices.c) INDEV_LIST=$(find_things indev _IN libavdevice/alldevices.c) FILTER_LIST=$(find_things filter FILTER libavfilter/allfilters.c) @@ -3538,6 +3536,8 @@ find_things_extern(){ sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" "$file" } +MUXER_LIST=$(find_things_extern muxer AVOutputFormat libavformat/allformats.c) +DEMUXER_LIST=$(find_things_extern demuxer AVInputFormat libavformat/allformats.c) ENCODER_LIST=$(find_things_extern encoder AVCodec libavcodec/allcodecs.c) DECODER_LIST=$(find_things_extern decoder AVCodec libavcodec/allcodecs.c) CODEC_LIST=" @@ -7036,6 +7036,8 @@ print_enabled_components(){ print_enabled_components libavcodec/codec_list.c AVCodec codec_list $CODEC_LIST print_enabled_components libavcodec/parser_list.c AVCodecParser parser_list $PARSER_LIST print_enabled_components libavcodec/bsf_list.c AVBitStreamFilter bitstream_filters $BSF_LIST +print_enabled_components libavformat/demuxer_list.c AVInputFormat demuxer_list $DEMUXER_LIST +print_enabled_components libavformat/muxer_list.c AVOutputFormat muxer_list $MUXER_LIST print_enabled_components libavformat/protocol_list.c URLProtocol url_protocols $PROTOCOL_LIST # Settings for pkg-config files diff --git a/doc/APIchanges b/doc/APIchanges index bb49fd5f2479f..69fb58eaded08 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,7 +15,12 @@ libavutil: 2017-10-21 API changes, most recent first: -2018-01-xx - xxxxxxx - lavc 58.9.100 - avcodec.h +2018-xx-xx - xxxxxxx - lavf 58.9.100 - avformat.h + Deprecate use of av_register_input_format(), av_register_output_format(), + avformat_register_all(), av_iformat_next(), av_oformat_next(). + Add av_demuxer_iterate(), and av_muxer_iterate(). + +2018-xx-xx - xxxxxxx - lavc 58.9.100 - avcodec.h Deprecate use of avcodec_register(), avcodec_register_all(), and av_codec_next(). Add av_codec_iterate(). diff --git a/libavformat/.gitignore b/libavformat/.gitignore index cdc24b717fe35..fb70c122c43dc 100644 --- a/libavformat/.gitignore +++ b/libavformat/.gitignore @@ -1 +1,3 @@ /protocol_list.c +/muxer_list.c +/demuxer_list.c diff --git a/libavformat/allformats.c b/libavformat/allformats.c index ce4f0d8c76e78..09c42136ccdec 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -26,371 +26,529 @@ #include "url.h" #include "version.h" -#define REGISTER_MUXER(X, x) \ - { \ - extern AVOutputFormat ff_##x##_muxer; \ - if (CONFIG_##X##_MUXER) \ - av_register_output_format(&ff_##x##_muxer); \ - } +/* (de)muxers */ +extern AVOutputFormat ff_a64_muxer; +extern AVInputFormat ff_aa_demuxer; +extern AVInputFormat ff_aac_demuxer; +extern AVInputFormat ff_ac3_demuxer; +extern AVOutputFormat ff_ac3_muxer; +extern AVInputFormat ff_acm_demuxer; +extern AVInputFormat ff_act_demuxer; +extern AVInputFormat ff_adf_demuxer; +extern AVInputFormat ff_adp_demuxer; +extern AVInputFormat ff_ads_demuxer; +extern AVOutputFormat ff_adts_muxer; +extern AVInputFormat ff_adx_demuxer; +extern AVOutputFormat ff_adx_muxer; +extern AVInputFormat ff_aea_demuxer; +extern AVInputFormat ff_afc_demuxer; +extern AVInputFormat ff_aiff_demuxer; +extern AVOutputFormat ff_aiff_muxer; +extern AVInputFormat ff_aix_demuxer; +extern AVInputFormat ff_amr_demuxer; +extern AVOutputFormat ff_amr_muxer; +extern AVInputFormat ff_amrnb_demuxer; +extern AVInputFormat ff_amrwb_demuxer; +extern AVInputFormat ff_anm_demuxer; +extern AVInputFormat ff_apc_demuxer; +extern AVInputFormat ff_ape_demuxer; +extern AVInputFormat ff_apng_demuxer; +extern AVOutputFormat ff_apng_muxer; +extern AVInputFormat ff_aptx_demuxer; +extern AVOutputFormat ff_aptx_muxer; +extern AVInputFormat ff_aqtitle_demuxer; +extern AVInputFormat ff_asf_demuxer; +extern AVOutputFormat ff_asf_muxer; +extern AVInputFormat ff_asf_o_demuxer; +extern AVInputFormat ff_ass_demuxer; +extern AVOutputFormat ff_ass_muxer; +extern AVInputFormat ff_ast_demuxer; +extern AVOutputFormat ff_ast_muxer; +extern AVOutputFormat ff_asf_stream_muxer; +extern AVInputFormat ff_au_demuxer; +extern AVOutputFormat ff_au_muxer; +extern AVInputFormat ff_avi_demuxer; +extern AVOutputFormat ff_avi_muxer; +extern AVInputFormat ff_avisynth_demuxer; +extern AVOutputFormat ff_avm2_muxer; +extern AVInputFormat ff_avr_demuxer; +extern AVInputFormat ff_avs_demuxer; +extern AVInputFormat ff_bethsoftvid_demuxer; +extern AVInputFormat ff_bfi_demuxer; +extern AVInputFormat ff_bintext_demuxer; +extern AVInputFormat ff_bink_demuxer; +extern AVInputFormat ff_bit_demuxer; +extern AVOutputFormat ff_bit_muxer; +extern AVInputFormat ff_bmv_demuxer; +extern AVInputFormat ff_bfstm_demuxer; +extern AVInputFormat ff_brstm_demuxer; +extern AVInputFormat ff_boa_demuxer; +extern AVInputFormat ff_c93_demuxer; +extern AVInputFormat ff_caf_demuxer; +extern AVOutputFormat ff_caf_muxer; +extern AVInputFormat ff_cavsvideo_demuxer; +extern AVOutputFormat ff_cavsvideo_muxer; +extern AVInputFormat ff_cdg_demuxer; +extern AVInputFormat ff_cdxl_demuxer; +extern AVInputFormat ff_cine_demuxer; +extern AVInputFormat ff_concat_demuxer; +extern AVOutputFormat ff_crc_muxer; +extern AVInputFormat ff_dash_demuxer; +extern AVOutputFormat ff_dash_muxer; +extern AVInputFormat ff_data_demuxer; +extern AVOutputFormat ff_data_muxer; +extern AVInputFormat ff_daud_demuxer; +extern AVOutputFormat ff_daud_muxer; +extern AVInputFormat ff_dcstr_demuxer; +extern AVInputFormat ff_dfa_demuxer; +extern AVInputFormat ff_dirac_demuxer; +extern AVOutputFormat ff_dirac_muxer; +extern AVInputFormat ff_dnxhd_demuxer; +extern AVOutputFormat ff_dnxhd_muxer; +extern AVInputFormat ff_dsf_demuxer; +extern AVInputFormat ff_dsicin_demuxer; +extern AVInputFormat ff_dss_demuxer; +extern AVInputFormat ff_dts_demuxer; +extern AVOutputFormat ff_dts_muxer; +extern AVInputFormat ff_dtshd_demuxer; +extern AVInputFormat ff_dv_demuxer; +extern AVOutputFormat ff_dv_muxer; +extern AVInputFormat ff_dvbsub_demuxer; +extern AVInputFormat ff_dvbtxt_demuxer; +extern AVInputFormat ff_dxa_demuxer; +extern AVInputFormat ff_ea_demuxer; +extern AVInputFormat ff_ea_cdata_demuxer; +extern AVInputFormat ff_eac3_demuxer; +extern AVOutputFormat ff_eac3_muxer; +extern AVInputFormat ff_epaf_demuxer; +extern AVOutputFormat ff_f4v_muxer; +extern AVInputFormat ff_ffmetadata_demuxer; +extern AVOutputFormat ff_ffmetadata_muxer; +extern AVOutputFormat ff_fifo_muxer; +extern AVOutputFormat ff_fifo_test_muxer; +extern AVInputFormat ff_filmstrip_demuxer; +extern AVOutputFormat ff_filmstrip_muxer; +extern AVInputFormat ff_fits_demuxer; +extern AVOutputFormat ff_fits_muxer; +extern AVInputFormat ff_flac_demuxer; +extern AVOutputFormat ff_flac_muxer; +extern AVInputFormat ff_flic_demuxer; +extern AVInputFormat ff_flv_demuxer; +extern AVOutputFormat ff_flv_muxer; +extern AVInputFormat ff_live_flv_demuxer; +extern AVInputFormat ff_fourxm_demuxer; +extern AVOutputFormat ff_framecrc_muxer; +extern AVOutputFormat ff_framehash_muxer; +extern AVOutputFormat ff_framemd5_muxer; +extern AVInputFormat ff_frm_demuxer; +extern AVInputFormat ff_fsb_demuxer; +extern AVInputFormat ff_g722_demuxer; +extern AVOutputFormat ff_g722_muxer; +extern AVInputFormat ff_g723_1_demuxer; +extern AVOutputFormat ff_g723_1_muxer; +extern AVInputFormat ff_g726_demuxer; +extern AVOutputFormat ff_g726_muxer; +extern AVInputFormat ff_g726le_demuxer; +extern AVOutputFormat ff_g726le_muxer; +extern AVInputFormat ff_g729_demuxer; +extern AVInputFormat ff_gdv_demuxer; +extern AVInputFormat ff_genh_demuxer; +extern AVInputFormat ff_gif_demuxer; +extern AVOutputFormat ff_gif_muxer; +extern AVInputFormat ff_gsm_demuxer; +extern AVOutputFormat ff_gsm_muxer; +extern AVInputFormat ff_gxf_demuxer; +extern AVOutputFormat ff_gxf_muxer; +extern AVInputFormat ff_h261_demuxer; +extern AVOutputFormat ff_h261_muxer; +extern AVInputFormat ff_h263_demuxer; +extern AVOutputFormat ff_h263_muxer; +extern AVInputFormat ff_h264_demuxer; +extern AVOutputFormat ff_h264_muxer; +extern AVOutputFormat ff_hash_muxer; +extern AVOutputFormat ff_hds_muxer; +extern AVInputFormat ff_hevc_demuxer; +extern AVOutputFormat ff_hevc_muxer; +extern AVInputFormat ff_hls_demuxer; +extern AVOutputFormat ff_hls_muxer; +extern AVInputFormat ff_hnm_demuxer; +extern AVInputFormat ff_ico_demuxer; +extern AVOutputFormat ff_ico_muxer; +extern AVInputFormat ff_idcin_demuxer; +extern AVInputFormat ff_idf_demuxer; +extern AVInputFormat ff_iff_demuxer; +extern AVInputFormat ff_ilbc_demuxer; +extern AVOutputFormat ff_ilbc_muxer; +extern AVInputFormat ff_image2_demuxer; +extern AVOutputFormat ff_image2_muxer; +extern AVInputFormat ff_image2pipe_demuxer; +extern AVOutputFormat ff_image2pipe_muxer; +extern AVInputFormat ff_image2_alias_pix_demuxer; +extern AVInputFormat ff_image2_brender_pix_demuxer; +extern AVInputFormat ff_ingenient_demuxer; +extern AVInputFormat ff_ipmovie_demuxer; +extern AVOutputFormat ff_ipod_muxer; +extern AVInputFormat ff_ircam_demuxer; +extern AVOutputFormat ff_ircam_muxer; +extern AVOutputFormat ff_ismv_muxer; +extern AVInputFormat ff_iss_demuxer; +extern AVInputFormat ff_iv8_demuxer; +extern AVInputFormat ff_ivf_demuxer; +extern AVOutputFormat ff_ivf_muxer; +extern AVInputFormat ff_ivr_demuxer; +extern AVInputFormat ff_jacosub_demuxer; +extern AVOutputFormat ff_jacosub_muxer; +extern AVInputFormat ff_jv_demuxer; +extern AVOutputFormat ff_latm_muxer; +extern AVInputFormat ff_lmlm4_demuxer; +extern AVInputFormat ff_loas_demuxer; +extern AVInputFormat ff_lrc_demuxer; +extern AVOutputFormat ff_lrc_muxer; +extern AVInputFormat ff_lvf_demuxer; +extern AVInputFormat ff_lxf_demuxer; +extern AVInputFormat ff_m4v_demuxer; +extern AVOutputFormat ff_m4v_muxer; +extern AVOutputFormat ff_md5_muxer; +extern AVInputFormat ff_matroska_demuxer; +extern AVOutputFormat ff_matroska_muxer; +extern AVOutputFormat ff_matroska_audio_muxer; +extern AVInputFormat ff_mgsts_demuxer; +extern AVInputFormat ff_microdvd_demuxer; +extern AVOutputFormat ff_microdvd_muxer; +extern AVInputFormat ff_mjpeg_demuxer; +extern AVOutputFormat ff_mjpeg_muxer; +extern AVInputFormat ff_mjpeg_2000_demuxer; +extern AVInputFormat ff_mlp_demuxer; +extern AVOutputFormat ff_mlp_muxer; +extern AVInputFormat ff_mlv_demuxer; +extern AVInputFormat ff_mm_demuxer; +extern AVInputFormat ff_mmf_demuxer; +extern AVOutputFormat ff_mmf_muxer; +extern AVInputFormat ff_mov_demuxer; +extern AVOutputFormat ff_mov_muxer; +extern AVOutputFormat ff_mp2_muxer; +extern AVInputFormat ff_mp3_demuxer; +extern AVOutputFormat ff_mp3_muxer; +extern AVOutputFormat ff_mp4_muxer; +extern AVInputFormat ff_mpc_demuxer; +extern AVInputFormat ff_mpc8_demuxer; +extern AVOutputFormat ff_mpeg1system_muxer; +extern AVOutputFormat ff_mpeg1vcd_muxer; +extern AVOutputFormat ff_mpeg1video_muxer; +extern AVOutputFormat ff_mpeg2dvd_muxer; +extern AVOutputFormat ff_mpeg2svcd_muxer; +extern AVOutputFormat ff_mpeg2video_muxer; +extern AVOutputFormat ff_mpeg2vob_muxer; +extern AVInputFormat ff_mpegps_demuxer; +extern AVInputFormat ff_mpegts_demuxer; +extern AVOutputFormat ff_mpegts_muxer; +extern AVInputFormat ff_mpegtsraw_demuxer; +extern AVInputFormat ff_mpegvideo_demuxer; +extern AVInputFormat ff_mpjpeg_demuxer; +extern AVOutputFormat ff_mpjpeg_muxer; +extern AVInputFormat ff_mpl2_demuxer; +extern AVInputFormat ff_mpsub_demuxer; +extern AVInputFormat ff_msf_demuxer; +extern AVInputFormat ff_msnwc_tcp_demuxer; +extern AVInputFormat ff_mtaf_demuxer; +extern AVInputFormat ff_mtv_demuxer; +extern AVInputFormat ff_musx_demuxer; +extern AVInputFormat ff_mv_demuxer; +extern AVInputFormat ff_mvi_demuxer; +extern AVInputFormat ff_mxf_demuxer; +extern AVOutputFormat ff_mxf_muxer; +extern AVOutputFormat ff_mxf_d10_muxer; +extern AVOutputFormat ff_mxf_opatom_muxer; +extern AVInputFormat ff_mxg_demuxer; +extern AVInputFormat ff_nc_demuxer; +extern AVInputFormat ff_nistsphere_demuxer; +extern AVInputFormat ff_nsp_demuxer; +extern AVInputFormat ff_nsv_demuxer; +extern AVOutputFormat ff_null_muxer; +extern AVInputFormat ff_nut_demuxer; +extern AVOutputFormat ff_nut_muxer; +extern AVInputFormat ff_nuv_demuxer; +extern AVOutputFormat ff_oga_muxer; +extern AVInputFormat ff_ogg_demuxer; +extern AVOutputFormat ff_ogg_muxer; +extern AVOutputFormat ff_ogv_muxer; +extern AVInputFormat ff_oma_demuxer; +extern AVOutputFormat ff_oma_muxer; +extern AVOutputFormat ff_opus_muxer; +extern AVInputFormat ff_paf_demuxer; +extern AVInputFormat ff_pcm_alaw_demuxer; +extern AVOutputFormat ff_pcm_alaw_muxer; +extern AVInputFormat ff_pcm_mulaw_demuxer; +extern AVOutputFormat ff_pcm_mulaw_muxer; +extern AVInputFormat ff_pcm_f64be_demuxer; +extern AVOutputFormat ff_pcm_f64be_muxer; +extern AVInputFormat ff_pcm_f64le_demuxer; +extern AVOutputFormat ff_pcm_f64le_muxer; +extern AVInputFormat ff_pcm_f32be_demuxer; +extern AVOutputFormat ff_pcm_f32be_muxer; +extern AVInputFormat ff_pcm_f32le_demuxer; +extern AVOutputFormat ff_pcm_f32le_muxer; +extern AVInputFormat ff_pcm_s32be_demuxer; +extern AVOutputFormat ff_pcm_s32be_muxer; +extern AVInputFormat ff_pcm_s32le_demuxer; +extern AVOutputFormat ff_pcm_s32le_muxer; +extern AVInputFormat ff_pcm_s24be_demuxer; +extern AVOutputFormat ff_pcm_s24be_muxer; +extern AVInputFormat ff_pcm_s24le_demuxer; +extern AVOutputFormat ff_pcm_s24le_muxer; +extern AVInputFormat ff_pcm_s16be_demuxer; +extern AVOutputFormat ff_pcm_s16be_muxer; +extern AVInputFormat ff_pcm_s16le_demuxer; +extern AVOutputFormat ff_pcm_s16le_muxer; +extern AVInputFormat ff_pcm_s8_demuxer; +extern AVOutputFormat ff_pcm_s8_muxer; +extern AVInputFormat ff_pcm_u32be_demuxer; +extern AVOutputFormat ff_pcm_u32be_muxer; +extern AVInputFormat ff_pcm_u32le_demuxer; +extern AVOutputFormat ff_pcm_u32le_muxer; +extern AVInputFormat ff_pcm_u24be_demuxer; +extern AVOutputFormat ff_pcm_u24be_muxer; +extern AVInputFormat ff_pcm_u24le_demuxer; +extern AVOutputFormat ff_pcm_u24le_muxer; +extern AVInputFormat ff_pcm_u16be_demuxer; +extern AVOutputFormat ff_pcm_u16be_muxer; +extern AVInputFormat ff_pcm_u16le_demuxer; +extern AVOutputFormat ff_pcm_u16le_muxer; +extern AVInputFormat ff_pcm_u8_demuxer; +extern AVOutputFormat ff_pcm_u8_muxer; +extern AVInputFormat ff_pjs_demuxer; +extern AVInputFormat ff_pmp_demuxer; +extern AVOutputFormat ff_psp_muxer; +extern AVInputFormat ff_pva_demuxer; +extern AVInputFormat ff_pvf_demuxer; +extern AVInputFormat ff_qcp_demuxer; +extern AVInputFormat ff_r3d_demuxer; +extern AVInputFormat ff_rawvideo_demuxer; +extern AVOutputFormat ff_rawvideo_muxer; +extern AVInputFormat ff_realtext_demuxer; +extern AVInputFormat ff_redspark_demuxer; +extern AVInputFormat ff_rl2_demuxer; +extern AVInputFormat ff_rm_demuxer; +extern AVOutputFormat ff_rm_muxer; +extern AVInputFormat ff_roq_demuxer; +extern AVOutputFormat ff_roq_muxer; +extern AVInputFormat ff_rpl_demuxer; +extern AVInputFormat ff_rsd_demuxer; +extern AVInputFormat ff_rso_demuxer; +extern AVOutputFormat ff_rso_muxer; +extern AVInputFormat ff_rtp_demuxer; +extern AVOutputFormat ff_rtp_muxer; +extern AVOutputFormat ff_rtp_mpegts_muxer; +extern AVInputFormat ff_rtsp_demuxer; +extern AVOutputFormat ff_rtsp_muxer; +extern AVInputFormat ff_s337m_demuxer; +extern AVInputFormat ff_sami_demuxer; +extern AVInputFormat ff_sap_demuxer; +extern AVOutputFormat ff_sap_muxer; +extern AVInputFormat ff_sbg_demuxer; +extern AVInputFormat ff_scc_demuxer; +extern AVOutputFormat ff_scc_muxer; +extern AVInputFormat ff_sdp_demuxer; +extern AVInputFormat ff_sdr2_demuxer; +extern AVInputFormat ff_sds_demuxer; +extern AVInputFormat ff_sdx_demuxer; +extern AVInputFormat ff_segafilm_demuxer; +extern AVOutputFormat ff_segment_muxer; +extern AVOutputFormat ff_stream_segment_muxer; +extern AVInputFormat ff_shorten_demuxer; +extern AVInputFormat ff_siff_demuxer; +extern AVOutputFormat ff_singlejpeg_muxer; +extern AVInputFormat ff_sln_demuxer; +extern AVInputFormat ff_smacker_demuxer; +extern AVInputFormat ff_smjpeg_demuxer; +extern AVOutputFormat ff_smjpeg_muxer; +extern AVOutputFormat ff_smoothstreaming_muxer; +extern AVInputFormat ff_smush_demuxer; +extern AVInputFormat ff_sol_demuxer; +extern AVInputFormat ff_sox_demuxer; +extern AVOutputFormat ff_sox_muxer; +extern AVOutputFormat ff_spx_muxer; +extern AVInputFormat ff_spdif_demuxer; +extern AVOutputFormat ff_spdif_muxer; +extern AVInputFormat ff_srt_demuxer; +extern AVOutputFormat ff_srt_muxer; +extern AVInputFormat ff_str_demuxer; +extern AVInputFormat ff_stl_demuxer; +extern AVInputFormat ff_subviewer1_demuxer; +extern AVInputFormat ff_subviewer_demuxer; +extern AVInputFormat ff_sup_demuxer; +extern AVOutputFormat ff_sup_muxer; +extern AVInputFormat ff_svag_demuxer; +extern AVInputFormat ff_swf_demuxer; +extern AVOutputFormat ff_swf_muxer; +extern AVInputFormat ff_tak_demuxer; +extern AVOutputFormat ff_tee_muxer; +extern AVInputFormat ff_tedcaptions_demuxer; +extern AVOutputFormat ff_tg2_muxer; +extern AVOutputFormat ff_tgp_muxer; +extern AVInputFormat ff_thp_demuxer; +extern AVInputFormat ff_threedostr_demuxer; +extern AVInputFormat ff_tiertexseq_demuxer; +extern AVOutputFormat ff_mkvtimestamp_v2_muxer; +extern AVInputFormat ff_tmv_demuxer; +extern AVInputFormat ff_truehd_demuxer; +extern AVOutputFormat ff_truehd_muxer; +extern AVInputFormat ff_tta_demuxer; +extern AVOutputFormat ff_tta_muxer; +extern AVInputFormat ff_txd_demuxer; +extern AVInputFormat ff_tty_demuxer; +extern AVInputFormat ff_ty_demuxer; +extern AVOutputFormat ff_uncodedframecrc_muxer; +extern AVInputFormat ff_v210_demuxer; +extern AVInputFormat ff_v210x_demuxer; +extern AVInputFormat ff_vag_demuxer; +extern AVInputFormat ff_vc1_demuxer; +extern AVOutputFormat ff_vc1_muxer; +extern AVInputFormat ff_vc1t_demuxer; +extern AVOutputFormat ff_vc1t_muxer; +extern AVInputFormat ff_vivo_demuxer; +extern AVInputFormat ff_vmd_demuxer; +extern AVInputFormat ff_vobsub_demuxer; +extern AVInputFormat ff_voc_demuxer; +extern AVOutputFormat ff_voc_muxer; +extern AVInputFormat ff_vpk_demuxer; +extern AVInputFormat ff_vplayer_demuxer; +extern AVInputFormat ff_vqf_demuxer; +extern AVInputFormat ff_w64_demuxer; +extern AVOutputFormat ff_w64_muxer; +extern AVInputFormat ff_wav_demuxer; +extern AVOutputFormat ff_wav_muxer; +extern AVInputFormat ff_wc3_demuxer; +extern AVOutputFormat ff_webm_muxer; +extern AVInputFormat ff_webm_dash_manifest_demuxer; +extern AVOutputFormat ff_webm_dash_manifest_muxer; +extern AVOutputFormat ff_webm_chunk_muxer; +extern AVOutputFormat ff_webp_muxer; +extern AVInputFormat ff_webvtt_demuxer; +extern AVOutputFormat ff_webvtt_muxer; +extern AVInputFormat ff_wsaud_demuxer; +extern AVInputFormat ff_wsd_demuxer; +extern AVInputFormat ff_wsvqa_demuxer; +extern AVInputFormat ff_wtv_demuxer; +extern AVOutputFormat ff_wtv_muxer; +extern AVInputFormat ff_wve_demuxer; +extern AVInputFormat ff_wv_demuxer; +extern AVOutputFormat ff_wv_muxer; +extern AVInputFormat ff_xa_demuxer; +extern AVInputFormat ff_xbin_demuxer; +extern AVInputFormat ff_xmv_demuxer; +extern AVInputFormat ff_xvag_demuxer; +extern AVInputFormat ff_xwma_demuxer; +extern AVInputFormat ff_yop_demuxer; +extern AVInputFormat ff_yuv4mpegpipe_demuxer; +extern AVOutputFormat ff_yuv4mpegpipe_muxer; +/* image demuxers */ +extern AVInputFormat ff_image_bmp_pipe_demuxer; +extern AVInputFormat ff_image_dds_pipe_demuxer; +extern AVInputFormat ff_image_dpx_pipe_demuxer; +extern AVInputFormat ff_image_exr_pipe_demuxer; +extern AVInputFormat ff_image_j2k_pipe_demuxer; +extern AVInputFormat ff_image_jpeg_pipe_demuxer; +extern AVInputFormat ff_image_jpegls_pipe_demuxer; +extern AVInputFormat ff_image_pam_pipe_demuxer; +extern AVInputFormat ff_image_pbm_pipe_demuxer; +extern AVInputFormat ff_image_pcx_pipe_demuxer; +extern AVInputFormat ff_image_pgmyuv_pipe_demuxer; +extern AVInputFormat ff_image_pgm_pipe_demuxer; +extern AVInputFormat ff_image_pictor_pipe_demuxer; +extern AVInputFormat ff_image_png_pipe_demuxer; +extern AVInputFormat ff_image_ppm_pipe_demuxer; +extern AVInputFormat ff_image_psd_pipe_demuxer; +extern AVInputFormat ff_image_qdraw_pipe_demuxer; +extern AVInputFormat ff_image_sgi_pipe_demuxer; +extern AVInputFormat ff_image_svg_pipe_demuxer; +extern AVInputFormat ff_image_sunrast_pipe_demuxer; +extern AVInputFormat ff_image_tiff_pipe_demuxer; +extern AVInputFormat ff_image_webp_pipe_demuxer; +extern AVInputFormat ff_image_xpm_pipe_demuxer; -#define REGISTER_DEMUXER(X, x) \ - { \ - extern AVInputFormat ff_##x##_demuxer; \ - if (CONFIG_##X##_DEMUXER) \ - av_register_input_format(&ff_##x##_demuxer); \ - } +/* external libraries */ +extern AVOutputFormat ff_chromaprint_muxer; +extern AVInputFormat ff_libgme_demuxer; +extern AVInputFormat ff_libmodplug_demuxer; +extern AVInputFormat ff_libopenmpt_demuxer; -#define REGISTER_MUXDEMUX(X, x) REGISTER_MUXER(X, x); REGISTER_DEMUXER(X, x) +#include "libavformat/muxer_list.c" +#include "libavformat/demuxer_list.c" -static void register_all(void) +const AVOutputFormat *av_muxer_iterate(void **opaque) { - avcodec_register_all(); + uintptr_t i = (uintptr_t)*opaque; + const AVOutputFormat *f = muxer_list[i]; + if (f) + *opaque = (void*)(i + 1); + return f; +} - /* (de)muxers */ - REGISTER_MUXER (A64, a64); - REGISTER_DEMUXER (AA, aa); - REGISTER_DEMUXER (AAC, aac); - REGISTER_MUXDEMUX(AC3, ac3); - REGISTER_DEMUXER (ACM, acm); - REGISTER_DEMUXER (ACT, act); - REGISTER_DEMUXER (ADF, adf); - REGISTER_DEMUXER (ADP, adp); - REGISTER_DEMUXER (ADS, ads); - REGISTER_MUXER (ADTS, adts); - REGISTER_MUXDEMUX(ADX, adx); - REGISTER_DEMUXER (AEA, aea); - REGISTER_DEMUXER (AFC, afc); - REGISTER_MUXDEMUX(AIFF, aiff); - REGISTER_DEMUXER (AIX, aix); - REGISTER_MUXDEMUX(AMR, amr); - REGISTER_DEMUXER (AMRNB, amrnb); - REGISTER_DEMUXER (AMRWB, amrwb); - REGISTER_DEMUXER (ANM, anm); - REGISTER_DEMUXER (APC, apc); - REGISTER_DEMUXER (APE, ape); - REGISTER_MUXDEMUX(APNG, apng); - REGISTER_MUXDEMUX(APTX, aptx); - REGISTER_DEMUXER (AQTITLE, aqtitle); - REGISTER_MUXDEMUX(ASF, asf); - REGISTER_DEMUXER (ASF_O, asf_o); - REGISTER_MUXDEMUX(ASS, ass); - REGISTER_MUXDEMUX(AST, ast); - REGISTER_MUXER (ASF_STREAM, asf_stream); - REGISTER_MUXDEMUX(AU, au); - REGISTER_MUXDEMUX(AVI, avi); - REGISTER_DEMUXER (AVISYNTH, avisynth); - REGISTER_MUXER (AVM2, avm2); - REGISTER_DEMUXER (AVR, avr); - REGISTER_DEMUXER (AVS, avs); - REGISTER_DEMUXER (BETHSOFTVID, bethsoftvid); - REGISTER_DEMUXER (BFI, bfi); - REGISTER_DEMUXER (BINTEXT, bintext); - REGISTER_DEMUXER (BINK, bink); - REGISTER_MUXDEMUX(BIT, bit); - REGISTER_DEMUXER (BMV, bmv); - REGISTER_DEMUXER (BFSTM, bfstm); - REGISTER_DEMUXER (BRSTM, brstm); - REGISTER_DEMUXER (BOA, boa); - REGISTER_DEMUXER (C93, c93); - REGISTER_MUXDEMUX(CAF, caf); - REGISTER_MUXDEMUX(CAVSVIDEO, cavsvideo); - REGISTER_DEMUXER (CDG, cdg); - REGISTER_DEMUXER (CDXL, cdxl); - REGISTER_DEMUXER (CINE, cine); - REGISTER_DEMUXER (CONCAT, concat); - REGISTER_MUXER (CRC, crc); - REGISTER_MUXDEMUX(DASH, dash); - REGISTER_MUXDEMUX(DATA, data); - REGISTER_MUXDEMUX(DAUD, daud); - REGISTER_DEMUXER (DCSTR, dcstr); - REGISTER_DEMUXER (DFA, dfa); - REGISTER_MUXDEMUX(DIRAC, dirac); - REGISTER_MUXDEMUX(DNXHD, dnxhd); - REGISTER_DEMUXER (DSF, dsf); - REGISTER_DEMUXER (DSICIN, dsicin); - REGISTER_DEMUXER (DSS, dss); - REGISTER_MUXDEMUX(DTS, dts); - REGISTER_DEMUXER (DTSHD, dtshd); - REGISTER_MUXDEMUX(DV, dv); - REGISTER_DEMUXER (DVBSUB, dvbsub); - REGISTER_DEMUXER (DVBTXT, dvbtxt); - REGISTER_DEMUXER (DXA, dxa); - REGISTER_DEMUXER (EA, ea); - REGISTER_DEMUXER (EA_CDATA, ea_cdata); - REGISTER_MUXDEMUX(EAC3, eac3); - REGISTER_DEMUXER (EPAF, epaf); - REGISTER_MUXER (F4V, f4v); - REGISTER_MUXDEMUX(FFMETADATA, ffmetadata); - REGISTER_MUXER (FIFO, fifo); - REGISTER_MUXER (FIFO, fifo_test); - REGISTER_MUXDEMUX(FILMSTRIP, filmstrip); - REGISTER_MUXDEMUX(FITS, fits); - REGISTER_MUXDEMUX(FLAC, flac); - REGISTER_DEMUXER (FLIC, flic); - REGISTER_MUXDEMUX(FLV, flv); - REGISTER_DEMUXER (LIVE_FLV, live_flv); - REGISTER_DEMUXER (FOURXM, fourxm); - REGISTER_MUXER (FRAMECRC, framecrc); - REGISTER_MUXER (FRAMEHASH, framehash); - REGISTER_MUXER (FRAMEMD5, framemd5); - REGISTER_DEMUXER (FRM, frm); - REGISTER_DEMUXER (FSB, fsb); - REGISTER_MUXDEMUX(G722, g722); - REGISTER_MUXDEMUX(G723_1, g723_1); - REGISTER_MUXDEMUX(G726, g726); - REGISTER_MUXDEMUX(G726LE, g726le); - REGISTER_DEMUXER (G729, g729); - REGISTER_DEMUXER (GDV, gdv); - REGISTER_DEMUXER (GENH, genh); - REGISTER_MUXDEMUX(GIF, gif); - REGISTER_MUXDEMUX(GSM, gsm); - REGISTER_MUXDEMUX(GXF, gxf); - REGISTER_MUXDEMUX(H261, h261); - REGISTER_MUXDEMUX(H263, h263); - REGISTER_MUXDEMUX(H264, h264); - REGISTER_MUXER (HASH, hash); - REGISTER_MUXER (HDS, hds); - REGISTER_MUXDEMUX(HEVC, hevc); - REGISTER_MUXDEMUX(HLS, hls); - REGISTER_DEMUXER (HNM, hnm); - REGISTER_MUXDEMUX(ICO, ico); - REGISTER_DEMUXER (IDCIN, idcin); - REGISTER_DEMUXER (IDF, idf); - REGISTER_DEMUXER (IFF, iff); - REGISTER_MUXDEMUX(ILBC, ilbc); - REGISTER_MUXDEMUX(IMAGE2, image2); - REGISTER_MUXDEMUX(IMAGE2PIPE, image2pipe); - REGISTER_DEMUXER (IMAGE2_ALIAS_PIX, image2_alias_pix); - REGISTER_DEMUXER (IMAGE2_BRENDER_PIX, image2_brender_pix); - REGISTER_DEMUXER (INGENIENT, ingenient); - REGISTER_DEMUXER (IPMOVIE, ipmovie); - REGISTER_MUXER (IPOD, ipod); - REGISTER_MUXDEMUX(IRCAM, ircam); - REGISTER_MUXER (ISMV, ismv); - REGISTER_DEMUXER (ISS, iss); - REGISTER_DEMUXER (IV8, iv8); - REGISTER_MUXDEMUX(IVF, ivf); - REGISTER_DEMUXER (IVR, ivr); - REGISTER_MUXDEMUX(JACOSUB, jacosub); - REGISTER_DEMUXER (JV, jv); - REGISTER_MUXER (LATM, latm); - REGISTER_DEMUXER (LMLM4, lmlm4); - REGISTER_DEMUXER (LOAS, loas); - REGISTER_MUXDEMUX(LRC, lrc); - REGISTER_DEMUXER (LVF, lvf); - REGISTER_DEMUXER (LXF, lxf); - REGISTER_MUXDEMUX(M4V, m4v); - REGISTER_MUXER (MD5, md5); - REGISTER_MUXDEMUX(MATROSKA, matroska); - REGISTER_MUXER (MATROSKA_AUDIO, matroska_audio); - REGISTER_DEMUXER (MGSTS, mgsts); - REGISTER_MUXDEMUX(MICRODVD, microdvd); - REGISTER_MUXDEMUX(MJPEG, mjpeg); - REGISTER_DEMUXER (MJPEG_2000, mjpeg_2000); - REGISTER_MUXDEMUX(MLP, mlp); - REGISTER_DEMUXER (MLV, mlv); - REGISTER_DEMUXER (MM, mm); - REGISTER_MUXDEMUX(MMF, mmf); - REGISTER_MUXDEMUX(MOV, mov); - REGISTER_MUXER (MP2, mp2); - REGISTER_MUXDEMUX(MP3, mp3); - REGISTER_MUXER (MP4, mp4); - REGISTER_DEMUXER (MPC, mpc); - REGISTER_DEMUXER (MPC8, mpc8); - REGISTER_MUXER (MPEG1SYSTEM, mpeg1system); - REGISTER_MUXER (MPEG1VCD, mpeg1vcd); - REGISTER_MUXER (MPEG1VIDEO, mpeg1video); - REGISTER_MUXER (MPEG2DVD, mpeg2dvd); - REGISTER_MUXER (MPEG2SVCD, mpeg2svcd); - REGISTER_MUXER (MPEG2VIDEO, mpeg2video); - REGISTER_MUXER (MPEG2VOB, mpeg2vob); - REGISTER_DEMUXER (MPEGPS, mpegps); - REGISTER_MUXDEMUX(MPEGTS, mpegts); - REGISTER_DEMUXER (MPEGTSRAW, mpegtsraw); - REGISTER_DEMUXER (MPEGVIDEO, mpegvideo); - REGISTER_MUXDEMUX(MPJPEG, mpjpeg); - REGISTER_DEMUXER (MPL2, mpl2); - REGISTER_DEMUXER (MPSUB, mpsub); - REGISTER_DEMUXER (MSF, msf); - REGISTER_DEMUXER (MSNWC_TCP, msnwc_tcp); - REGISTER_DEMUXER (MTAF, mtaf); - REGISTER_DEMUXER (MTV, mtv); - REGISTER_DEMUXER (MUSX, musx); - REGISTER_DEMUXER (MV, mv); - REGISTER_DEMUXER (MVI, mvi); - REGISTER_MUXDEMUX(MXF, mxf); - REGISTER_MUXER (MXF_D10, mxf_d10); - REGISTER_MUXER (MXF_OPATOM, mxf_opatom); - REGISTER_DEMUXER (MXG, mxg); - REGISTER_DEMUXER (NC, nc); - REGISTER_DEMUXER (NISTSPHERE, nistsphere); - REGISTER_DEMUXER (NSP, nsp); - REGISTER_DEMUXER (NSV, nsv); - REGISTER_MUXER (NULL, null); - REGISTER_MUXDEMUX(NUT, nut); - REGISTER_DEMUXER (NUV, nuv); - REGISTER_MUXER (OGA, oga); - REGISTER_MUXDEMUX(OGG, ogg); - REGISTER_MUXER (OGV, ogv); - REGISTER_MUXDEMUX(OMA, oma); - REGISTER_MUXER (OPUS, opus); - REGISTER_DEMUXER (PAF, paf); - REGISTER_MUXDEMUX(PCM_ALAW, pcm_alaw); - REGISTER_MUXDEMUX(PCM_MULAW, pcm_mulaw); - REGISTER_MUXDEMUX(PCM_F64BE, pcm_f64be); - REGISTER_MUXDEMUX(PCM_F64LE, pcm_f64le); - REGISTER_MUXDEMUX(PCM_F32BE, pcm_f32be); - REGISTER_MUXDEMUX(PCM_F32LE, pcm_f32le); - REGISTER_MUXDEMUX(PCM_S32BE, pcm_s32be); - REGISTER_MUXDEMUX(PCM_S32LE, pcm_s32le); - REGISTER_MUXDEMUX(PCM_S24BE, pcm_s24be); - REGISTER_MUXDEMUX(PCM_S24LE, pcm_s24le); - REGISTER_MUXDEMUX(PCM_S16BE, pcm_s16be); - REGISTER_MUXDEMUX(PCM_S16LE, pcm_s16le); - REGISTER_MUXDEMUX(PCM_S8, pcm_s8); - REGISTER_MUXDEMUX(PCM_U32BE, pcm_u32be); - REGISTER_MUXDEMUX(PCM_U32LE, pcm_u32le); - REGISTER_MUXDEMUX(PCM_U24BE, pcm_u24be); - REGISTER_MUXDEMUX(PCM_U24LE, pcm_u24le); - REGISTER_MUXDEMUX(PCM_U16BE, pcm_u16be); - REGISTER_MUXDEMUX(PCM_U16LE, pcm_u16le); - REGISTER_MUXDEMUX(PCM_U8, pcm_u8); - REGISTER_DEMUXER (PJS, pjs); - REGISTER_DEMUXER (PMP, pmp); - REGISTER_MUXER (PSP, psp); - REGISTER_DEMUXER (PVA, pva); - REGISTER_DEMUXER (PVF, pvf); - REGISTER_DEMUXER (QCP, qcp); - REGISTER_DEMUXER (R3D, r3d); - REGISTER_MUXDEMUX(RAWVIDEO, rawvideo); - REGISTER_DEMUXER (REALTEXT, realtext); - REGISTER_DEMUXER (REDSPARK, redspark); - REGISTER_DEMUXER (RL2, rl2); - REGISTER_MUXDEMUX(RM, rm); - REGISTER_MUXDEMUX(ROQ, roq); - REGISTER_DEMUXER (RPL, rpl); - REGISTER_DEMUXER (RSD, rsd); - REGISTER_MUXDEMUX(RSO, rso); - REGISTER_MUXDEMUX(RTP, rtp); - REGISTER_MUXER (RTP_MPEGTS, rtp_mpegts); - REGISTER_MUXDEMUX(RTSP, rtsp); - REGISTER_DEMUXER (S337M, s337m); - REGISTER_DEMUXER (SAMI, sami); - REGISTER_MUXDEMUX(SAP, sap); - REGISTER_DEMUXER (SBG, sbg); - REGISTER_MUXDEMUX(SCC, scc); - REGISTER_DEMUXER (SDP, sdp); - REGISTER_DEMUXER (SDR2, sdr2); - REGISTER_DEMUXER (SDS, sds); - REGISTER_DEMUXER (SDX, sdx); - REGISTER_DEMUXER (SEGAFILM, segafilm); - REGISTER_MUXER (SEGMENT, segment); - REGISTER_MUXER (SEGMENT, stream_segment); - REGISTER_DEMUXER (SHORTEN, shorten); - REGISTER_DEMUXER (SIFF, siff); - REGISTER_MUXER (SINGLEJPEG, singlejpeg); - REGISTER_DEMUXER (SLN, sln); - REGISTER_DEMUXER (SMACKER, smacker); - REGISTER_MUXDEMUX(SMJPEG, smjpeg); - REGISTER_MUXER (SMOOTHSTREAMING, smoothstreaming); - REGISTER_DEMUXER (SMUSH, smush); - REGISTER_DEMUXER (SOL, sol); - REGISTER_MUXDEMUX(SOX, sox); - REGISTER_MUXER (SPX, spx); - REGISTER_MUXDEMUX(SPDIF, spdif); - REGISTER_MUXDEMUX(SRT, srt); - REGISTER_DEMUXER (STR, str); - REGISTER_DEMUXER (STL, stl); - REGISTER_DEMUXER (SUBVIEWER1, subviewer1); - REGISTER_DEMUXER (SUBVIEWER, subviewer); - REGISTER_MUXDEMUX(SUP, sup); - REGISTER_DEMUXER (SVAG, svag); - REGISTER_MUXDEMUX(SWF, swf); - REGISTER_DEMUXER (TAK, tak); - REGISTER_MUXER (TEE, tee); - REGISTER_DEMUXER (TEDCAPTIONS, tedcaptions); - REGISTER_MUXER (TG2, tg2); - REGISTER_MUXER (TGP, tgp); - REGISTER_DEMUXER (THP, thp); - REGISTER_DEMUXER (THREEDOSTR, threedostr); - REGISTER_DEMUXER (TIERTEXSEQ, tiertexseq); - REGISTER_MUXER (MKVTIMESTAMP_V2, mkvtimestamp_v2); - REGISTER_DEMUXER (TMV, tmv); - REGISTER_MUXDEMUX(TRUEHD, truehd); - REGISTER_MUXDEMUX(TTA, tta); - REGISTER_DEMUXER (TXD, txd); - REGISTER_DEMUXER (TTY, tty); - REGISTER_DEMUXER (TY, ty); - REGISTER_MUXER (UNCODEDFRAMECRC, uncodedframecrc); - REGISTER_DEMUXER (V210, v210); - REGISTER_DEMUXER (V210X, v210x); - REGISTER_DEMUXER (VAG, vag); - REGISTER_MUXDEMUX(VC1, vc1); - REGISTER_MUXDEMUX(VC1T, vc1t); - REGISTER_DEMUXER (VIVO, vivo); - REGISTER_DEMUXER (VMD, vmd); - REGISTER_DEMUXER (VOBSUB, vobsub); - REGISTER_MUXDEMUX(VOC, voc); - REGISTER_DEMUXER (VPK, vpk); - REGISTER_DEMUXER (VPLAYER, vplayer); - REGISTER_DEMUXER (VQF, vqf); - REGISTER_MUXDEMUX(W64, w64); - REGISTER_MUXDEMUX(WAV, wav); - REGISTER_DEMUXER (WC3, wc3); - REGISTER_MUXER (WEBM, webm); - REGISTER_MUXDEMUX(WEBM_DASH_MANIFEST, webm_dash_manifest); - REGISTER_MUXER (WEBM_CHUNK, webm_chunk); - REGISTER_MUXER (WEBP, webp); - REGISTER_MUXDEMUX(WEBVTT, webvtt); - REGISTER_DEMUXER (WSAUD, wsaud); - REGISTER_DEMUXER (WSD, wsd); - REGISTER_DEMUXER (WSVQA, wsvqa); - REGISTER_MUXDEMUX(WTV, wtv); - REGISTER_DEMUXER (WVE, wve); - REGISTER_MUXDEMUX(WV, wv); - REGISTER_DEMUXER (XA, xa); - REGISTER_DEMUXER (XBIN, xbin); - REGISTER_DEMUXER (XMV, xmv); - REGISTER_DEMUXER (XVAG, xvag); - REGISTER_DEMUXER (XWMA, xwma); - REGISTER_DEMUXER (YOP, yop); - REGISTER_MUXDEMUX(YUV4MPEGPIPE, yuv4mpegpipe); +const AVInputFormat *av_demuxer_iterate(void **opaque){ + uintptr_t i = (uintptr_t)*opaque; + const AVInputFormat *f = demuxer_list[i]; - /* image demuxers */ - REGISTER_DEMUXER (IMAGE_BMP_PIPE, image_bmp_pipe); - REGISTER_DEMUXER (IMAGE_DDS_PIPE, image_dds_pipe); - REGISTER_DEMUXER (IMAGE_DPX_PIPE, image_dpx_pipe); - REGISTER_DEMUXER (IMAGE_EXR_PIPE, image_exr_pipe); - REGISTER_DEMUXER (IMAGE_J2K_PIPE, image_j2k_pipe); - REGISTER_DEMUXER (IMAGE_JPEG_PIPE, image_jpeg_pipe); - REGISTER_DEMUXER (IMAGE_JPEGLS_PIPE, image_jpegls_pipe); - REGISTER_DEMUXER (IMAGE_PAM_PIPE, image_pam_pipe); - REGISTER_DEMUXER (IMAGE_PBM_PIPE, image_pbm_pipe); - REGISTER_DEMUXER (IMAGE_PCX_PIPE, image_pcx_pipe); - REGISTER_DEMUXER (IMAGE_PGMYUV_PIPE, image_pgmyuv_pipe); - REGISTER_DEMUXER (IMAGE_PGM_PIPE, image_pgm_pipe); - REGISTER_DEMUXER (IMAGE_PICTOR_PIPE, image_pictor_pipe); - REGISTER_DEMUXER (IMAGE_PNG_PIPE, image_png_pipe); - REGISTER_DEMUXER (IMAGE_PPM_PIPE, image_ppm_pipe); - REGISTER_DEMUXER (IMAGE_PSD_PIPE, image_psd_pipe); - REGISTER_DEMUXER (IMAGE_QDRAW_PIPE, image_qdraw_pipe); - REGISTER_DEMUXER (IMAGE_SGI_PIPE, image_sgi_pipe); - REGISTER_DEMUXER (IMAGE_SVG_PIPE, image_svg_pipe); - REGISTER_DEMUXER (IMAGE_SUNRAST_PIPE, image_sunrast_pipe); - REGISTER_DEMUXER (IMAGE_TIFF_PIPE, image_tiff_pipe); - REGISTER_DEMUXER (IMAGE_WEBP_PIPE, image_webp_pipe); - REGISTER_DEMUXER (IMAGE_XPM_PIPE, image_xpm_pipe); + if (f) + *opaque = (void*)(i + 1); + return f; +} + +#if FF_API_NEXT +FF_DISABLE_DEPRECATION_WARNINGS +static AVOnce av_format_next_init = AV_ONCE_INIT; - /* external libraries */ - REGISTER_MUXER (CHROMAPRINT, chromaprint); - REGISTER_DEMUXER (LIBGME, libgme); - REGISTER_DEMUXER (LIBMODPLUG, libmodplug); - REGISTER_DEMUXER (LIBOPENMPT, libopenmpt); +static void av_format_init_next(void) +{ + AVOutputFormat *prevout = NULL, *out; + AVInputFormat *previn = NULL, *in; + void *i = 0; + + while ((out = (AVOutputFormat*)av_muxer_iterate(&i))) { + if (prevout) + prevout->next = out; + prevout = out; + } + + i = 0; + while ((in = (AVInputFormat*)av_demuxer_iterate(&i))) { + if (previn) + previn->next = in; + previn = in; + } +} + +AVInputFormat *av_iformat_next(const AVInputFormat *f) +{ + ff_thread_once(&av_format_next_init, av_format_init_next); + if (f) + return f->next; + else + return demuxer_list[0]; +} + +AVOutputFormat *av_oformat_next(const AVOutputFormat *f) +{ + ff_thread_once(&av_format_next_init, av_format_init_next); + if (f) + return f->next; + else + return muxer_list[0]; } void av_register_all(void) { - static AVOnce control = AV_ONCE_INIT; + ff_thread_once(&av_format_next_init, av_format_init_next); +} - ff_thread_once(&control, register_all); +void av_register_input_format(AVInputFormat *format) +{ + ff_thread_once(&av_format_next_init, av_format_init_next); +} + +void av_register_output_format(AVOutputFormat *format) +{ + ff_thread_once(&av_format_next_init, av_format_init_next); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 82f98453375ed..4ea1b5ab727b3 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2011,6 +2011,7 @@ const char *avformat_configuration(void); */ const char *avformat_license(void); +#if FF_API_NEXT /** * Initialize libavformat and register all the muxers, demuxers and * protocols. If you do not call this function, then you can select @@ -2019,10 +2020,14 @@ const char *avformat_license(void); * @see av_register_input_format() * @see av_register_output_format() */ +attribute_deprecated void av_register_all(void); +attribute_deprecated void av_register_input_format(AVInputFormat *format); +attribute_deprecated void av_register_output_format(AVOutputFormat *format); +#endif /** * Do global initialization of network libraries. This is optional, @@ -2046,11 +2051,13 @@ int avformat_network_init(void); */ int avformat_network_deinit(void); +#if FF_API_NEXT /** * If f is NULL, returns the first registered input format, * if f is non-NULL, returns the next registered input format after f * or NULL if f is the last one. */ +attribute_deprecated AVInputFormat *av_iformat_next(const AVInputFormat *f); /** @@ -2058,7 +2065,31 @@ AVInputFormat *av_iformat_next(const AVInputFormat *f); * if f is non-NULL, returns the next registered output format after f * or NULL if f is the last one. */ +attribute_deprecated AVOutputFormat *av_oformat_next(const AVOutputFormat *f); +#endif + +/** + * Iterate over all registered muxers. + * + * @param opaque a pointer where libavformat will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered muxer or NULL when the iteration is + * finished + */ +const AVOutputFormat *av_muxer_iterate(void **opaque); + +/** + * Iterate over all registered demuxers. + * + * @param opaque a pointer where libavformat will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered demuxer or NULL when the iteration is + * finished + */ +const AVInputFormat *av_demuxer_iterate(void **opaque); /** * Allocate an AVFormatContext. diff --git a/libavformat/format.c b/libavformat/format.c index 759b5b1ab498c..608af1b692773 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -34,65 +34,6 @@ * @file * Format register and lookup */ -/** head of registered input format linked list */ -static AVInputFormat *first_iformat = NULL; -/** head of registered output format linked list */ -static AVOutputFormat *first_oformat = NULL; - -static AVInputFormat **last_iformat = &first_iformat; -static AVOutputFormat **last_oformat = &first_oformat; - -AVInputFormat *av_iformat_next(const AVInputFormat *f) -{ - if (f) - return f->next; - else - return first_iformat; -} - -AVOutputFormat *av_oformat_next(const AVOutputFormat *f) -{ - if (f) - return f->next; - else - return first_oformat; -} - -static AVMutex iformat_register_mutex = AV_MUTEX_INITIALIZER; - -void av_register_input_format(AVInputFormat *format) -{ - AVInputFormat **p; - - ff_mutex_lock(&iformat_register_mutex); - p = last_iformat; - - while (*p) - p = &(*p)->next; - *p = format; - format->next = NULL; - last_iformat = &format->next; - - ff_mutex_unlock(&iformat_register_mutex); -} - -static AVMutex oformat_register_mutex = AV_MUTEX_INITIALIZER; - -void av_register_output_format(AVOutputFormat *format) -{ - AVOutputFormat **p; - - ff_mutex_lock(&oformat_register_mutex); - p = last_oformat; - - while (*p) - p = &(*p)->next; - *p = format; - format->next = NULL; - last_oformat = &format->next; - - ff_mutex_unlock(&oformat_register_mutex); -} int av_match_ext(const char *filename, const char *extensions) { @@ -111,6 +52,7 @@ AVOutputFormat *av_guess_format(const char *short_name, const char *filename, const char *mime_type) { AVOutputFormat *fmt = NULL, *fmt_found; + void *i = 0; int score_max, score; /* specific test for image sequences */ @@ -124,7 +66,7 @@ AVOutputFormat *av_guess_format(const char *short_name, const char *filename, /* Find the proper file type. */ fmt_found = NULL; score_max = 0; - while ((fmt = av_oformat_next(fmt))) { + while ((fmt = av_muxer_iterate(&i))) { score = 0; if (fmt->name && short_name && av_match_name(short_name, fmt->name)) score += 100; @@ -176,7 +118,8 @@ enum AVCodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name, AVInputFormat *av_find_input_format(const char *short_name) { AVInputFormat *fmt = NULL; - while ((fmt = av_iformat_next(fmt))) + void *i = 0; + while ((fmt = av_demuxer_iterate(&i))) if (av_match_name(short_name, fmt->name)) return fmt; return NULL; @@ -188,6 +131,7 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, AVProbeData lpd = *pd; AVInputFormat *fmt1 = NULL, *fmt; int score, score_max = 0; + void *i = 0; const static uint8_t zerobuffer[AVPROBE_PADDING_SIZE]; enum nodat { NO_ID3, @@ -213,7 +157,7 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, } fmt = NULL; - while ((fmt1 = av_iformat_next(fmt1))) { + while ((fmt1 = av_demuxer_iterate(&i))) { if (!is_opened == !(fmt1->flags & AVFMT_NOFILE) && strcmp(fmt1->name, "image2")) continue; score = 0; diff --git a/libavformat/version.h b/libavformat/version.h index a42ab7056dd63..7669c226237ba 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -91,6 +91,9 @@ #ifndef FF_API_OLD_RTSP_OPTIONS #define FF_API_OLD_RTSP_OPTIONS (LIBAVFORMAT_VERSION_MAJOR < 59) #endif +#ifndef FF_API_NEXT +#define FF_API_NEXT (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif #ifndef FF_API_R_FRAME_RATE From 0fd475704e871ef3a535947596a012894bae3cbd Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Tue, 2 Jan 2018 14:34:18 +0000 Subject: [PATCH 1807/2557] lavd: add new API for iterating input and output devices This also adds an avpriv function to register devices in libavformat --- Makefile | 3 +- configure | 27 +++++- libavdevice/.gitignore | 2 + libavdevice/alldevices.c | 181 +++++++++++++++++++++++++++++---------- libavdevice/avdevice.c | 46 ---------- libavdevice/avdevice.h | 28 ++++++ libavdevice/version.h | 4 + libavformat/allformats.c | 42 ++++++++- libavformat/format.c | 8 ++ libavformat/internal.h | 7 ++ 10 files changed, 252 insertions(+), 96 deletions(-) create mode 100644 libavdevice/.gitignore diff --git a/Makefile b/Makefile index 0cd0a1d6f2d55..bb93b69f8910d 100644 --- a/Makefile +++ b/Makefile @@ -144,7 +144,8 @@ distclean:: clean version.h libavutil/ffversion.h libavcodec/codec_names.h \ libavcodec/bsf_list.c libavformat/protocol_list.c \ libavcodec/codec_list.c libavcodec/parser_list.c \ - libavformat/muxer_list.c libavformat/demuxer_list.c + libavformat/muxer_list.c libavformat/demuxer_list.c \ + libavdevice/indev_list.c libavdevice/outdev_list.c ifeq ($(SRC_LINK),src) $(RM) src endif diff --git a/configure b/configure index 7c654575a6297..8d713f1bc0035 100755 --- a/configure +++ b/configure @@ -568,6 +568,12 @@ add_suffix(){ for v; do echo ${v}${suffix}; done } +remove_suffix(){ + suffix=$1 + shift + for v; do echo ${v%$suffix}; done +} + set_all(){ value=$1 shift @@ -3525,17 +3531,18 @@ find_things(){ sed -n "s/^[^#]*$pattern.*([^,]*, *\([^,]*\)\(,.*\)*).*/\1_$thing/p" "$file" } -OUTDEV_LIST=$(find_things outdev OUTDEV libavdevice/alldevices.c) -INDEV_LIST=$(find_things indev _IN libavdevice/alldevices.c) FILTER_LIST=$(find_things filter FILTER libavfilter/allfilters.c) find_things_extern(){ thing=$1 pattern=$2 file=$source_path/$3 - sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" "$file" + out=${4:-$thing} + sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$out/p" "$file" } +OUTDEV_LIST=$(find_things_extern muxer AVOutputFormat libavdevice/alldevices.c outdev) +INDEV_LIST=$(find_things_extern demuxer AVInputFormat libavdevice/alldevices.c indev) MUXER_LIST=$(find_things_extern muxer AVOutputFormat libavformat/allformats.c) DEMUXER_LIST=$(find_things_extern demuxer AVInputFormat libavformat/allformats.c) ENCODER_LIST=$(find_things_extern encoder AVCodec libavcodec/allcodecs.c) @@ -7027,7 +7034,17 @@ print_enabled_components(){ shift 3 echo "static const $struct_name * const $name[] = {" > $TMPH for c in $*; do - enabled $c && printf " &ff_%s,\n" $c >> $TMPH + if enabled $c; then + case $name in + indev_list) + c=$(add_suffix _demuxer $(remove_suffix _indev $c)) + ;; + outdev_list) + c=$(add_suffix _muxer $(remove_suffix _outdev $c)) + ;; + esac + printf " &ff_%s,\n" $c >> $TMPH + fi done echo " NULL };" >> $TMPH cp_if_changed $TMPH $file @@ -7036,6 +7053,8 @@ print_enabled_components(){ print_enabled_components libavcodec/codec_list.c AVCodec codec_list $CODEC_LIST print_enabled_components libavcodec/parser_list.c AVCodecParser parser_list $PARSER_LIST print_enabled_components libavcodec/bsf_list.c AVBitStreamFilter bitstream_filters $BSF_LIST +print_enabled_components libavdevice/indev_list.c AVInputFormat indev_list $INDEV_LIST +print_enabled_components libavdevice/outdev_list.c AVOutputFormat outdev_list $OUTDEV_LIST print_enabled_components libavformat/demuxer_list.c AVInputFormat demuxer_list $DEMUXER_LIST print_enabled_components libavformat/muxer_list.c AVOutputFormat muxer_list $MUXER_LIST print_enabled_components libavformat/protocol_list.c URLProtocol url_protocols $PROTOCOL_LIST diff --git a/libavdevice/.gitignore b/libavdevice/.gitignore new file mode 100644 index 0000000000000..08ac3eb86a81f --- /dev/null +++ b/libavdevice/.gitignore @@ -0,0 +1,2 @@ +/indev_list.c +/outdev_list.c diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index b767b6a718821..8b58aa19e5d6b 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -22,57 +22,152 @@ #include "libavutil/thread.h" #include "avdevice.h" -#define REGISTER_OUTDEV(X, x) \ - { \ - extern AVOutputFormat ff_##x##_muxer; \ - if (CONFIG_##X##_OUTDEV) \ - av_register_output_format(&ff_##x##_muxer); \ +#if FF_API_NEXT +#include "libavformat/internal.h" +#endif + +/* devices */ +extern AVInputFormat ff_alsa_demuxer; +extern AVOutputFormat ff_alsa_muxer; +extern AVInputFormat ff_avfoundation_demuxer; +extern AVInputFormat ff_bktr_demuxer; +extern AVOutputFormat ff_caca_muxer; +extern AVInputFormat ff_decklink_demuxer; +extern AVOutputFormat ff_decklink_muxer; +extern AVInputFormat ff_libndi_newtek_demuxer; +extern AVOutputFormat ff_libndi_newtek_muxer; +extern AVInputFormat ff_dshow_demuxer; +extern AVInputFormat ff_fbdev_demuxer; +extern AVOutputFormat ff_fbdev_muxer; +extern AVInputFormat ff_gdigrab_demuxer; +extern AVInputFormat ff_iec61883_demuxer; +extern AVInputFormat ff_jack_demuxer; +extern AVInputFormat ff_kmsgrab_demuxer; +extern AVInputFormat ff_lavfi_demuxer; +extern AVInputFormat ff_openal_demuxer; +extern AVOutputFormat ff_opengl_muxer; +extern AVInputFormat ff_oss_demuxer; +extern AVOutputFormat ff_oss_muxer; +extern AVInputFormat ff_pulse_demuxer; +extern AVOutputFormat ff_pulse_muxer; +extern AVOutputFormat ff_sdl2_muxer; +extern AVInputFormat ff_sndio_demuxer; +extern AVOutputFormat ff_sndio_muxer; +extern AVInputFormat ff_v4l2_demuxer; +extern AVOutputFormat ff_v4l2_muxer; +extern AVInputFormat ff_vfwcap_demuxer; +extern AVInputFormat ff_xcbgrab_demuxer; +extern AVOutputFormat ff_xv_muxer; + +/* external libraries */ +extern AVInputFormat ff_libcdio_demuxer; +extern AVInputFormat ff_libdc1394_demuxer; + +#include "libavdevice/outdev_list.c" +#include "libavdevice/indev_list.c" + +const AVOutputFormat *av_outdev_iterate(void **opaque) +{ + uintptr_t i = (uintptr_t)*opaque; + const AVOutputFormat *f = outdev_list[i]; + + if (f) + *opaque = (void*)(i + 1); + return f; +} + +const AVInputFormat *av_indev_iterate(void **opaque) +{ + uintptr_t i = (uintptr_t)*opaque; + const AVInputFormat *f = indev_list[i]; + + if (f) + *opaque = (void*)(i + 1); + return f; +} + +#if FF_API_NEXT +FF_DISABLE_DEPRECATION_WARNINGS +static AVOnce av_device_next_init = AV_ONCE_INIT; + +static void av_device_init_next(void) +{ + AVOutputFormat *prevout = NULL, *out; + AVInputFormat *previn = NULL, *in; + void *i = 0; + + while ((out = (AVOutputFormat*)av_outdev_iterate(&i))) { + if (prevout) + prevout->next = out; + prevout = out; } -#define REGISTER_INDEV(X, x) \ - { \ - extern AVInputFormat ff_##x##_demuxer; \ - if (CONFIG_##X##_INDEV) \ - av_register_input_format(&ff_##x##_demuxer); \ + i = 0; + while ((in = (AVInputFormat*)av_indev_iterate(&i))) { + if (previn) + previn->next = in; + previn = in; } -#define REGISTER_INOUTDEV(X, x) REGISTER_OUTDEV(X, x); REGISTER_INDEV(X, x) + avpriv_register_devices(outdev_list, indev_list); +} -static void register_all(void) +void avdevice_register_all(void) { - /* devices */ - REGISTER_INOUTDEV(ALSA, alsa); - REGISTER_INDEV (AVFOUNDATION, avfoundation); - REGISTER_INDEV (BKTR, bktr); - REGISTER_OUTDEV (CACA, caca); - REGISTER_INOUTDEV(DECKLINK, decklink); - REGISTER_INOUTDEV(LIBNDI_NEWTEK, libndi_newtek); - REGISTER_INDEV (DSHOW, dshow); - REGISTER_INOUTDEV(FBDEV, fbdev); - REGISTER_INDEV (GDIGRAB, gdigrab); - REGISTER_INDEV (IEC61883, iec61883); - REGISTER_INDEV (JACK, jack); - REGISTER_INDEV (KMSGRAB, kmsgrab); - REGISTER_INDEV (LAVFI, lavfi); - REGISTER_INDEV (OPENAL, openal); - REGISTER_OUTDEV (OPENGL, opengl); - REGISTER_INOUTDEV(OSS, oss); - REGISTER_INOUTDEV(PULSE, pulse); - REGISTER_OUTDEV (SDL2, sdl2); - REGISTER_INOUTDEV(SNDIO, sndio); - REGISTER_INOUTDEV(V4L2, v4l2); - REGISTER_INDEV (VFWCAP, vfwcap); - REGISTER_INDEV (XCBGRAB, xcbgrab); - REGISTER_OUTDEV (XV, xv); - - /* external libraries */ - REGISTER_INDEV (LIBCDIO, libcdio); - REGISTER_INDEV (LIBDC1394, libdc1394); + ff_thread_once(&av_device_next_init, av_device_init_next); } -void avdevice_register_all(void) +static void *device_next(void *prev, int output, + AVClassCategory c1, AVClassCategory c2) +{ + const AVClass *pc; + AVClassCategory category = AV_CLASS_CATEGORY_NA; + + ff_thread_once(&av_device_next_init, av_device_init_next); + + if (!prev && !(prev = (output ? (void*)outdev_list[0] : (void*)indev_list[0]))) + return NULL; + + do { + if (output) { + if (!(prev = ((AVOutputFormat *)prev)->next)) + break; + pc = ((AVOutputFormat *)prev)->priv_class; + } else { + if (!(prev = ((AVInputFormat *)prev)->next)) + break; + pc = ((AVInputFormat *)prev)->priv_class; + } + if (!pc) + continue; + category = pc->category; + } while (category != c1 && category != c2); + return prev; +} + +AVInputFormat *av_input_audio_device_next(AVInputFormat *d) +{ + return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT); +} + +AVInputFormat *av_input_video_device_next(AVInputFormat *d) +{ + return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT); +} + +AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d) { - static AVOnce control = AV_ONCE_INIT; + return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT); +} - ff_thread_once(&control, register_all); +AVOutputFormat *av_output_video_device_next(AVOutputFormat *d) +{ + return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT); } +FF_DISABLE_DEPRECATION_WARNINGS +#endif + diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c index 72e1b67887f9b..a42d3498b56d5 100644 --- a/libavdevice/avdevice.c +++ b/libavdevice/avdevice.c @@ -78,52 +78,6 @@ const char * avdevice_license(void) return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; } -static void *device_next(void *prev, int output, - AVClassCategory c1, AVClassCategory c2) -{ - const AVClass *pc; - AVClassCategory category = AV_CLASS_CATEGORY_NA; - do { - if (output) { - if (!(prev = av_oformat_next(prev))) - break; - pc = ((AVOutputFormat *)prev)->priv_class; - } else { - if (!(prev = av_iformat_next(prev))) - break; - pc = ((AVInputFormat *)prev)->priv_class; - } - if (!pc) - continue; - category = pc->category; - } while (category != c1 && category != c2); - return prev; -} - -AVInputFormat *av_input_audio_device_next(AVInputFormat *d) -{ - return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, - AV_CLASS_CATEGORY_DEVICE_INPUT); -} - -AVInputFormat *av_input_video_device_next(AVInputFormat *d) -{ - return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, - AV_CLASS_CATEGORY_DEVICE_INPUT); -} - -AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d) -{ - return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, - AV_CLASS_CATEGORY_DEVICE_OUTPUT); -} - -AVOutputFormat *av_output_video_device_next(AVOutputFormat *d) -{ - return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, - AV_CLASS_CATEGORY_DEVICE_OUTPUT); -} - int avdevice_app_to_dev_control_message(struct AVFormatContext *s, enum AVAppToDevMessageType type, void *data, size_t data_size) { diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h index ee9462480e2cd..dd6ad9365e231 100644 --- a/libavdevice/avdevice.h +++ b/libavdevice/avdevice.h @@ -65,6 +65,29 @@ const char *avdevice_configuration(void); */ const char *avdevice_license(void); +/** + * Iterate over all registered output devices. + * + * @param opaque a pointer where libavdevice will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered output device or NULL when the iteration is + * finished + */ +const AVOutputFormat *av_outdev_iterate(void **opaque); + +/** + * Iterate over all registered input devices. + * + * @param opaque a pointer where libavdevice will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered input device or NULL when the iteration is + * finished + */ +const AVInputFormat *av_indev_iterate(void **opaque); + +#if FF_API_NEXT /** * Initialize libavdevice and register all the input and output devices. */ @@ -77,6 +100,7 @@ void avdevice_register_all(void); * if d is non-NULL, returns the next registered input audio/video device after d * or NULL if d is the last one. */ +attribute_deprecated AVInputFormat *av_input_audio_device_next(AVInputFormat *d); /** @@ -86,6 +110,7 @@ AVInputFormat *av_input_audio_device_next(AVInputFormat *d); * if d is non-NULL, returns the next registered input audio/video device after d * or NULL if d is the last one. */ +attribute_deprecated AVInputFormat *av_input_video_device_next(AVInputFormat *d); /** @@ -95,6 +120,7 @@ AVInputFormat *av_input_video_device_next(AVInputFormat *d); * if d is non-NULL, returns the next registered output audio/video device after d * or NULL if d is the last one. */ +attribute_deprecated AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d); /** @@ -104,7 +130,9 @@ AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d); * if d is non-NULL, returns the next registered output audio/video device after d * or NULL if d is the last one. */ +attribute_deprecated AVOutputFormat *av_output_video_device_next(AVOutputFormat *d); +#endif typedef struct AVDeviceRect { int x; /**< x coordinate of top left corner */ diff --git a/libavdevice/version.h b/libavdevice/version.h index 0d4477f82e2a1..892c4f374edb2 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -47,4 +47,8 @@ * the public API and may change, break or disappear at any time. */ +#ifndef FF_API_NEXT +#define FF_API_NEXT (LIBAVDEVICE_VERSION_MAJOR < 59) +#endif + #endif /* AVDEVICE_VERSION_H */ diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 09c42136ccdec..9fd649bb4cee4 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -25,6 +25,9 @@ #include "rdt.h" #include "url.h" #include "version.h" +#if FF_API_NEXT +#include "internal.h" +#endif /* (de)muxers */ extern AVOutputFormat ff_a64_muxer; @@ -480,6 +483,7 @@ const AVOutputFormat *av_muxer_iterate(void **opaque) { uintptr_t i = (uintptr_t)*opaque; const AVOutputFormat *f = muxer_list[i]; + if (f) *opaque = (void*)(i + 1); return f; @@ -498,6 +502,9 @@ const AVInputFormat *av_demuxer_iterate(void **opaque){ FF_DISABLE_DEPRECATION_WARNINGS static AVOnce av_format_next_init = AV_ONCE_INIT; +static const AVInputFormat * const *indev_list = NULL; +static const AVOutputFormat * const *outdev_list = NULL; + static void av_format_init_next(void) { AVOutputFormat *prevout = NULL, *out; @@ -510,30 +517,61 @@ static void av_format_init_next(void) prevout = out; } + if (outdev_list) { + for (int j = 0; (out = (AVOutputFormat*)outdev_list[j]); j++) { + if (prevout) + prevout->next = out; + prevout = out; + } + } + i = 0; while ((in = (AVInputFormat*)av_demuxer_iterate(&i))) { if (previn) previn->next = in; previn = in; } + + if (indev_list) { + for (int j = 0; (in = (AVInputFormat*)indev_list[j]); j++) { + if (previn) + previn->next = in; + previn = in; + } + } + +} + +void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]) +{ + static AVMutex avpriv_register_devices_mutex = AV_MUTEX_INITIALIZER; + ff_mutex_lock(&avpriv_register_devices_mutex); + outdev_list = o; + indev_list = i; + av_format_init_next(); + ff_mutex_unlock(&avpriv_register_devices_mutex); } AVInputFormat *av_iformat_next(const AVInputFormat *f) { ff_thread_once(&av_format_next_init, av_format_init_next); + if (f) return f->next; else - return demuxer_list[0]; + /* If there are no demuxers but input devices, then return the first input device. + * This will still return null if both there are both no demuxers or input devices. */ + return demuxer_list[0] ? (AVInputFormat*)demuxer_list[0] : (indev_list ? (AVInputFormat*)indev_list[0] : NULL); } AVOutputFormat *av_oformat_next(const AVOutputFormat *f) { ff_thread_once(&av_format_next_init, av_format_init_next); + if (f) return f->next; else - return muxer_list[0]; + return muxer_list[0] ? (AVOutputFormat*)muxer_list[0] : (outdev_list ? (AVOutputFormat*)outdev_list[0] : NULL); } void av_register_all(void) diff --git a/libavformat/format.c b/libavformat/format.c index 608af1b692773..b8c5a90a92d44 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -118,10 +118,18 @@ enum AVCodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name, AVInputFormat *av_find_input_format(const char *short_name) { AVInputFormat *fmt = NULL; +#if FF_API_NEXT +FF_DISABLE_DEPRECATION_WARNINGS + while ((fmt = av_iformat_next(fmt))) + if (av_match_name(short_name, fmt->name)) + return fmt; +FF_ENABLE_DEPRECATION_WARNINGS +#else void *i = 0; while ((fmt = av_demuxer_iterate(&i))) if (av_match_name(short_name, fmt->name)) return fmt; +#endif return NULL; } diff --git a/libavformat/internal.h b/libavformat/internal.h index 1e2a3e05a11b1..0d08576c299ae 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -703,4 +703,11 @@ int ff_unlock_avformat(void); */ void ff_format_set_url(AVFormatContext *s, char *url); +#if FF_API_NEXT +/** + * Register devices in deprecated format linked list. + */ +void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]); +#endif + #endif /* AVFORMAT_INTERNAL_H */ From cdc78058c78dfa4966758a342acd2c1f3b282c46 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Tue, 30 Jan 2018 21:28:28 +0000 Subject: [PATCH 1808/2557] cmdutils: make use of new iteration APIs --- fftools/cmdutils.c | 122 ++++++++++++++++----------------------------- 1 file changed, 43 insertions(+), 79 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 6920ca07641a5..9ecc51b8ac995 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1250,19 +1250,11 @@ int show_license(void *optctx, const char *opt, const char *arg) return 0; } -static int is_device(const AVClass *avclass) -{ - if (!avclass) - return 0; - return AV_IS_INPUT_DEVICE(avclass->category) || AV_IS_OUTPUT_DEVICE(avclass->category); -} - static int show_formats_devices(void *optctx, const char *opt, const char *arg, int device_only, int muxdemuxers) { - AVInputFormat *ifmt = NULL; - AVOutputFormat *ofmt = NULL; + const AVInputFormat *ifmt = NULL; + const AVOutputFormat *ofmt = NULL; const char *last_name; - int is_dev; printf("%s\n" " D. = Demuxing supported\n" @@ -1275,34 +1267,24 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg, const char *name = NULL; const char *long_name = NULL; - if (muxdemuxers !=SHOW_DEMUXERS) { - while ((ofmt = av_oformat_next(ofmt))) { - is_dev = is_device(ofmt->priv_class); - if (!is_dev && device_only) - continue; - if ((!name || strcmp(ofmt->name, name) < 0) && - strcmp(ofmt->name, last_name) > 0) { - name = ofmt->name; - long_name = ofmt->long_name; - encode = 1; - } - } - } - if (muxdemuxers != SHOW_MUXERS) { - while ((ifmt = av_iformat_next(ifmt))) { - is_dev = is_device(ifmt->priv_class); - if (!is_dev && device_only) - continue; - if ((!name || strcmp(ifmt->name, name) < 0) && - strcmp(ifmt->name, last_name) > 0) { - name = ifmt->name; - long_name = ifmt->long_name; - encode = 0; - } - if (name && strcmp(ifmt->name, name) == 0) - decode = 1; - } - } +#define x(func, type, condition) do { \ + void *i = 0; \ + if (condition) { \ + while ((type = func(&i))) { \ + if ((!name || strcmp(type->name, name) < 0) && \ + strcmp(type->name, last_name) > 0) { \ + name = type->name; \ + long_name = type->long_name; \ + encode = 1; \ + } \ + } \ + } } while(0) + + x(av_muxer_iterate, ofmt, muxdemuxers != SHOW_DEMUXERS && !device_only); + x(av_outdev_iterate, ofmt, muxdemuxers != SHOW_DEMUXERS); + x(av_demuxer_iterate, ifmt, muxdemuxers != SHOW_MUXERS && !device_only); + x(av_indev_iterate, ifmt, muxdemuxers != SHOW_MUXERS); +#undef x if (!name) break; last_name = name; @@ -1442,7 +1424,8 @@ static char get_media_type_char(enum AVMediaType type) static const AVCodec *next_codec_for_id(enum AVCodecID id, const AVCodec *prev, int encoder) { - while ((prev = av_codec_next(prev))) { + void *i = 0; + while ((prev = av_codec_iterate(&i))) { if (prev->id == id && (encoder ? av_codec_is_encoder(prev) : av_codec_is_decoder(prev))) return prev; @@ -2116,7 +2099,7 @@ double get_rotation(AVStream *st) } #if CONFIG_AVDEVICE -static int print_device_sources(AVInputFormat *fmt, AVDictionary *opts) +static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) { int ret, i; AVDeviceInfoList *device_list = NULL; @@ -2131,7 +2114,7 @@ static int print_device_sources(AVInputFormat *fmt, AVDictionary *opts) goto fail; } - if ((ret = avdevice_list_input_sources(fmt, NULL, opts, &device_list)) < 0) { + if ((ret = avdevice_list_input_sources((AVInputFormat*)fmt, NULL, opts, &device_list)) < 0) { printf("Cannot list sources.\n"); goto fail; } @@ -2146,7 +2129,7 @@ static int print_device_sources(AVInputFormat *fmt, AVDictionary *opts) return ret; } -static int print_device_sinks(AVOutputFormat *fmt, AVDictionary *opts) +static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *opts) { int ret, i; AVDeviceInfoList *device_list = NULL; @@ -2161,7 +2144,7 @@ static int print_device_sinks(AVOutputFormat *fmt, AVDictionary *opts) goto fail; } - if ((ret = avdevice_list_output_sinks(fmt, NULL, opts, &device_list)) < 0) { + if ((ret = avdevice_list_output_sinks((AVOutputFormat*)fmt, NULL, opts, &device_list)) < 0) { printf("Cannot list sinks.\n"); goto fail; } @@ -2200,7 +2183,8 @@ static int show_sinks_sources_parse_arg(const char *arg, char **dev, AVDictionar int show_sources(void *optctx, const char *opt, const char *arg) { - AVInputFormat *fmt = NULL; + const AVInputFormat *fmt = NULL; + void *i = 0; char *dev = NULL; AVDictionary *opts = NULL; int ret = 0; @@ -2211,24 +2195,14 @@ int show_sources(void *optctx, const char *opt, const char *arg) if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0) goto fail; - do { - fmt = av_input_audio_device_next(fmt); - if (fmt) { - if (!strcmp(fmt->name, "lavfi")) - continue; //it's pointless to probe lavfi - if (dev && !av_match_name(dev, fmt->name)) - continue; - print_device_sources(fmt, opts); - } - } while (fmt); - do { - fmt = av_input_video_device_next(fmt); - if (fmt) { - if (dev && !av_match_name(dev, fmt->name)) - continue; - print_device_sources(fmt, opts); - } - } while (fmt); + while ((fmt = av_indev_iterate(&i))) { + if (!strcmp(fmt->name, "lavfi")) + continue; //it's pointless to probe lavfi + if (dev && !av_match_name(dev, fmt->name)) + continue; + print_device_sources(fmt, opts); + } + fail: av_dict_free(&opts); av_free(dev); @@ -2238,7 +2212,8 @@ int show_sources(void *optctx, const char *opt, const char *arg) int show_sinks(void *optctx, const char *opt, const char *arg) { - AVOutputFormat *fmt = NULL; + const AVOutputFormat *fmt = NULL; + void *i = 0; char *dev = NULL; AVDictionary *opts = NULL; int ret = 0; @@ -2249,22 +2224,11 @@ int show_sinks(void *optctx, const char *opt, const char *arg) if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0) goto fail; - do { - fmt = av_output_audio_device_next(fmt); - if (fmt) { - if (dev && !av_match_name(dev, fmt->name)) - continue; - print_device_sinks(fmt, opts); - } - } while (fmt); - do { - fmt = av_output_video_device_next(fmt); - if (fmt) { - if (dev && !av_match_name(dev, fmt->name)) - continue; - print_device_sinks(fmt, opts); - } - } while (fmt); + while ((fmt = av_outdev_iterate(&i))) { + if (dev && !av_match_name(dev, fmt->name)) + continue; + print_device_sinks(fmt, opts); + } fail: av_dict_free(&opts); av_free(dev); From 26d879c1cea176d4f0e0a47d4b641c86495aa0e8 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Fri, 2 Feb 2018 19:25:36 +0000 Subject: [PATCH 1809/2557] lavc/bsf: make BSF iteration the same as other iterators --- fftools/cmdutils.c | 2 +- libavcodec/avcodec.h | 6 +++++- libavcodec/bitstream_filter.c | 4 ++-- libavcodec/bitstream_filters.c | 29 ++++++++++++++++++----------- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 9ecc51b8ac995..0b06ccc71a083 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1586,7 +1586,7 @@ int show_bsfs(void *optctx, const char *opt, const char *arg) void *opaque = NULL; printf("Bitstream filters:\n"); - while ((bsf = av_bsf_next(&opaque))) + while ((bsf = av_bsf_iterate(&opaque))) printf("%s\n", bsf->name); printf("\n"); return 0; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 99f5fb9da0999..c41779ad40c27 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -5728,7 +5728,7 @@ attribute_deprecated void av_bitstream_filter_close(AVBitStreamFilterContext *bsf); /** * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) - * is deprecated. Use av_bsf_next() from the new bitstream filtering API (using + * is deprecated. Use av_bsf_iterate() from the new bitstream filtering API (using * AVBSFContext). */ attribute_deprecated @@ -5750,7 +5750,11 @@ const AVBitStreamFilter *av_bsf_get_by_name(const char *name); * @return the next registered bitstream filter or NULL when the iteration is * finished */ +const AVBitStreamFilter *av_bsf_iterate(void **opaque); +#if FF_API_NEXT +attribute_deprecated const AVBitStreamFilter *av_bsf_next(void **opaque); +#endif /** * Allocate a context for a given bitstream filter. The caller must fill in the diff --git a/libavcodec/bitstream_filter.c b/libavcodec/bitstream_filter.c index ed1cf3335ba54..ca11ed371e37c 100644 --- a/libavcodec/bitstream_filter.c +++ b/libavcodec/bitstream_filter.c @@ -34,9 +34,9 @@ const AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f) void *opaque = NULL; while (filter != f) - filter = av_bsf_next(&opaque); + filter = av_bsf_iterate(&opaque); - return av_bsf_next(&opaque); + return av_bsf_iterate(&opaque); } void av_register_bitstream_filter(AVBitStreamFilter *bsf) diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 7b0cb5032a3ce..338ef8251bf81 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -52,7 +52,7 @@ extern const AVBitStreamFilter ff_vp9_superframe_split_bsf; #include "libavcodec/bsf_list.c" -const AVBitStreamFilter *av_bsf_next(void **opaque) +const AVBitStreamFilter *av_bsf_iterate(void **opaque) { uintptr_t i = (uintptr_t)*opaque; const AVBitStreamFilter *f = bitstream_filters[i]; @@ -63,12 +63,18 @@ const AVBitStreamFilter *av_bsf_next(void **opaque) return f; } +#if FF_API_NEXT +const AVBitStreamFilter *av_bsf_next(void **opaque) { + return av_bsf_iterate(opaque); +} +#endif + const AVBitStreamFilter *av_bsf_get_by_name(const char *name) { - int i; + const AVBitStreamFilter *f = NULL; + void *i = 0; - for (i = 0; bitstream_filters[i]; i++) { - const AVBitStreamFilter *f = bitstream_filters[i]; + while ((f = av_bsf_iterate(&i))) { if (!strcmp(f->name, name)) return f; } @@ -78,19 +84,20 @@ const AVBitStreamFilter *av_bsf_get_by_name(const char *name) const AVClass *ff_bsf_child_class_next(const AVClass *prev) { - int i; + const AVBitStreamFilter *f = NULL; + void *i = 0; /* find the filter that corresponds to prev */ - for (i = 0; prev && bitstream_filters[i]; i++) { - if (bitstream_filters[i]->priv_class == prev) { - i++; + while (prev && (f = av_bsf_iterate(&i))) { + if (f->priv_class == prev) { break; } } /* find next filter with priv options */ - for (; bitstream_filters[i]; i++) - if (bitstream_filters[i]->priv_class) - return bitstream_filters[i]->priv_class; + while ((f = av_bsf_iterate(&i))) { + if (f->priv_class) + return f->priv_class; + } return NULL; } From 204c7caf0d77bdfd73196ffee00695222d0ff2cb Mon Sep 17 00:00:00 2001 From: Menno Date: Mon, 5 Feb 2018 10:54:53 +0100 Subject: [PATCH 1810/2557] avcodec/libopus: support disabling phase inversion. Signed-off-by: Menno Signed-off-by: Michael Niedermayer --- doc/encoders.texi | 5 +++++ libavcodec/libopusdec.c | 33 +++++++++++++++++++++++++++++++++ libavcodec/libopusenc.c | 14 ++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index 6a410a8cb643a..c5dfc646d962a 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -981,6 +981,11 @@ Other values include 0 for mono and stereo, 1 for surround sound with masking and LFE bandwidth optimizations, and 255 for independent streams with an unspecified channel layout. +@item apply_phase_inv (N.A.) (requires libopus >= 1.2) +If set to 0, disables the use of phase inversion for intensity stereo, +improving the quality of mono downmixes, but slightly reducing normal stereo +quality. The default is 1 (phase inversion enabled). + @end table @anchor{libshine} diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c index 4f7f4755c242a..3d2ee5b61b21b 100644 --- a/libavcodec/libopusdec.c +++ b/libavcodec/libopusdec.c @@ -25,6 +25,7 @@ #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/ffmath.h" +#include "libavutil/opt.h" #include "avcodec.h" #include "internal.h" @@ -33,11 +34,15 @@ #include "libopus.h" struct libopus_context { + AVClass *class; OpusMSDecoder *dec; int pre_skip; #ifndef OPUS_SET_GAIN union { int i; double d; } gain; #endif +#ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST + int apply_phase_inv; +#endif }; #define OPUS_HEAD_SIZE 19 @@ -136,6 +141,15 @@ static av_cold int libopus_decode_init(AVCodecContext *avc) } #endif +#ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST + ret = opus_multistream_decoder_ctl(opus->dec, + OPUS_SET_PHASE_INVERSION_DISABLED(!opus->apply_phase_inv)); + if (ret != OPUS_OK) + av_log(avc, AV_LOG_WARNING, + "Unable to set phase inversion: %s\n", + opus_strerror(ret)); +#endif + /* Decoder delay (in samples) at 48kHz */ avc->delay = avc->internal->skip_samples = opus->pre_skip; @@ -209,6 +223,24 @@ static void libopus_flush(AVCodecContext *avc) avc->internal->skip_samples = opus->pre_skip; } + +#define OFFSET(x) offsetof(struct libopus_context, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption libopusdec_options[] = { +#ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST + { "apply_phase_inv", "Apply intensity stereo phase inversion", OFFSET(apply_phase_inv), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS }, +#endif + { NULL }, +}; + +static const AVClass libopusdec_class = { + .class_name = "libopusdec", + .item_name = av_default_item_name, + .option = libopusdec_options, + .version = LIBAVUTIL_VERSION_INT, +}; + + AVCodec ff_libopus_decoder = { .name = "libopus", .long_name = NULL_IF_CONFIG_SMALL("libopus Opus"), @@ -223,5 +255,6 @@ AVCodec ff_libopus_decoder = { .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .priv_class = &libopusdec_class, .wrapper_name = "libopus", }; diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c index b449497d15fbe..4ae81b0bb2e23 100644 --- a/libavcodec/libopusenc.c +++ b/libavcodec/libopusenc.c @@ -39,6 +39,9 @@ typedef struct LibopusEncOpts { int packet_size; int max_bandwidth; int mapping_family; +#ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST + int apply_phase_inv; +#endif } LibopusEncOpts; typedef struct LibopusEncContext { @@ -154,6 +157,14 @@ static int libopus_configure_encoder(AVCodecContext *avctx, OpusMSEncoder *enc, "Unable to set maximum bandwidth: %s\n", opus_strerror(ret)); } +#ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST + ret = opus_multistream_encoder_ctl(enc, + OPUS_SET_PHASE_INVERSION_DISABLED(!opts->apply_phase_inv)); + if (ret != OPUS_OK) + av_log(avctx, AV_LOG_WARNING, + "Unable to set phase inversion: %s\n", + opus_strerror(ret)); +#endif return OPUS_OK; } @@ -530,6 +541,9 @@ static const AVOption libopus_options[] = { { "on", "Use variable bit rate", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "vbr" }, { "constrained", "Use constrained VBR", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, FLAGS, "vbr" }, { "mapping_family", "Channel Mapping Family", OFFSET(mapping_family), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, FLAGS, "mapping_family" }, +#ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST + { "apply_phase_inv", "Apply intensity stereo phase inversion", OFFSET(apply_phase_inv), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS }, +#endif { NULL }, }; From 698d5eb5bf83d1afbff3e74bb25a6d486b6bf7e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Martinez?= Date: Thu, 1 Feb 2018 13:11:53 +0100 Subject: [PATCH 1811/2557] avcodec/ffv1: Support for RGBA64 and GBRAP16 Signed-off-by: Michael Niedermayer --- libavcodec/ffv1dec.c | 14 ++++++++++---- libavcodec/ffv1dec_template.c | 9 +++++++-- libavcodec/ffv1enc.c | 16 ++++++++++++++-- libavcodec/ffv1enc_template.c | 14 ++++++++++---- 4 files changed, 41 insertions(+), 12 deletions(-) diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index 5eadb6b158648..923b79f3ab6e3 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -336,14 +336,16 @@ static int decode_slice(AVCodecContext *c, void *arg) decode_plane(fs, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2); decode_plane(fs, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2); } else if (f->use32bit) { - uint8_t *planes[3] = { p->data[0] + ps * x + y * p->linesize[0], + uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0], p->data[1] + ps * x + y * p->linesize[1], - p->data[2] + ps * x + y * p->linesize[2] }; + p->data[2] + ps * x + y * p->linesize[2], + p->data[3] + ps * x + y * p->linesize[3] }; decode_rgb_frame32(fs, planes, width, height, p->linesize); } else { - uint8_t *planes[3] = { p->data[0] + ps * x + y * p->linesize[0], + uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0], p->data[1] + ps * x + y * p->linesize[1], - p->data[2] + ps * x + y * p->linesize[2] }; + p->data[2] + ps * x + y * p->linesize[2], + p->data[3] + ps * x + y * p->linesize[3] }; decode_rgb_frame(fs, planes, width, height, p->linesize); } if (fs->ac != AC_GOLOMB_RICE && f->version > 2) { @@ -694,6 +696,10 @@ static int read_header(FFV1Context *f) f->avctx->pix_fmt = AV_PIX_FMT_GBRP16; f->use32bit = 1; } + else if (f->avctx->bits_per_raw_sample == 16 && f->transparency) { + f->avctx->pix_fmt = AV_PIX_FMT_GBRAP16; + f->use32bit = 1; + } } else { av_log(f->avctx, AV_LOG_ERROR, "colorspace not supported\n"); return AVERROR(ENOSYS); diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c index 37df7667737d3..a25b3384f1373 100644 --- a/libavcodec/ffv1dec_template.c +++ b/libavcodec/ffv1dec_template.c @@ -107,13 +107,14 @@ static av_always_inline int RENAME(decode_line)(FFV1Context *s, int w, return 0; } -static void RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[3], int w, int h, int stride[3]) +static void RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[4], int w, int h, int stride[4]) { int x, y, p; TYPE *sample[4][2]; int lbd = s->avctx->bits_per_raw_sample <= 8; int bits = s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8; int offset = 1 << bits; + int transparency = s->transparency; for (x = 0; x < 4; x++) { sample[x][0] = RENAME(s->sample_buffer) + x * 2 * (w + 6) + 3; @@ -125,7 +126,7 @@ static void RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[3], int w, int memset(RENAME(s->sample_buffer), 0, 8 * (w + 6) * sizeof(*RENAME(s->sample_buffer))); for (y = 0; y < h; y++) { - for (p = 0; p < 3 + s->transparency; p++) { + for (p = 0; p < 3 + transparency; p++) { TYPE *temp = sample[p][0]; // FIXME: try a normal buffer sample[p][0] = sample[p][1]; @@ -158,10 +159,14 @@ static void RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[3], int w, int *((uint16_t*)(src[0] + x*2 + stride[0]*y)) = g; *((uint16_t*)(src[1] + x*2 + stride[1]*y)) = b; *((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r; + if (transparency) + *((uint16_t*)(src[3] + x*2 + stride[3]*y)) = a; } else { *((uint16_t*)(src[0] + x*2 + stride[0]*y)) = b; *((uint16_t*)(src[1] + x*2 + stride[1]*y)) = g; *((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r; + if (transparency) + *((uint16_t*)(src[3] + x*2 + stride[3]*y)) = a; } } } diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index 0778f84c9bbaa..49b8d590a389b 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -624,6 +624,14 @@ FF_ENABLE_DEPRECATION_WARNINGS s->chroma_planes = 1; s->bits_per_raw_sample = 8; break; + case AV_PIX_FMT_RGBA64: + s->colorspace = 1; + s->transparency = 1; + s->chroma_planes = 1; + s->bits_per_raw_sample = 16; + s->use32bit = 1; + s->version = FFMAX(s->version, 1); + break; case AV_PIX_FMT_RGB48: s->colorspace = 1; s->chroma_planes = 1; @@ -649,10 +657,12 @@ FF_ENABLE_DEPRECATION_WARNINGS if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample) s->bits_per_raw_sample = 14; case AV_PIX_FMT_GBRP16: + case AV_PIX_FMT_GBRAP16: if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample) s->bits_per_raw_sample = 16; else if (!s->bits_per_raw_sample) s->bits_per_raw_sample = avctx->bits_per_raw_sample; + s->transparency = desc->nb_components == 4 || desc->nb_components == 2; s->colorspace = 1; s->chroma_planes = 1; if (s->bits_per_raw_sample >= 16) { @@ -1024,9 +1034,10 @@ static int encode_slice(AVCodecContext *c, void *arg) const int ps = av_pix_fmt_desc_get(c->pix_fmt)->comp[0].step; int ret; RangeCoder c_bak = fs->c; - const uint8_t *planes[3] = {p->data[0] + ps*x + y*p->linesize[0], + const uint8_t *planes[4] = {p->data[0] + ps*x + y*p->linesize[0], p->data[1] ? p->data[1] + ps*x + y*p->linesize[1] : NULL, - p->data[2] ? p->data[2] + ps*x + y*p->linesize[2] : NULL}; + p->data[2] ? p->data[2] + ps*x + y*p->linesize[2] : NULL, + p->data[3] ? p->data[3] + ps*x + y*p->linesize[3] : NULL}; fs->slice_coding_mode = 0; if (f->version > 3) { @@ -1318,6 +1329,7 @@ AVCodec ff_ffv1_encoder = { AV_PIX_FMT_YA8, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GBRP16, AV_PIX_FMT_RGB48, + AV_PIX_FMT_GBRAP16, AV_PIX_FMT_RGBA64, AV_PIX_FMT_NONE }, diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c index b7eea0dd700dc..b93336538b276 100644 --- a/libavcodec/ffv1enc_template.c +++ b/libavcodec/ffv1enc_template.c @@ -122,8 +122,8 @@ static av_always_inline int RENAME(encode_line)(FFV1Context *s, int w, return 0; } -static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[3], - int w, int h, const int stride[3]) +static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[4], + int w, int h, const int stride[4]) { int x, y, p, i; const int ring_size = s->context_model ? 3 : 2; @@ -132,6 +132,8 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[3], int packed = !src[1]; int bits = s->bits_per_raw_sample > 0 ? s->bits_per_raw_sample : 8; int offset = 1 << bits; + int transparency = s->transparency; + int packed_size = (3 + transparency)*2; s->run_index = 0; @@ -152,14 +154,18 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[3], r = (v >> 16) & 0xFF; a = v >> 24; } else if (packed) { - const uint16_t *p = ((const uint16_t*)(src[0] + x*6 + stride[0]*y)); + const uint16_t *p = ((const uint16_t*)(src[0] + x*packed_size + stride[0]*y)); r = p[0]; g = p[1]; b = p[2]; + if (transparency) + a = p[3]; } else if (sizeof(TYPE) == 4) { g = *((const uint16_t *)(src[0] + x*2 + stride[0]*y)); b = *((const uint16_t *)(src[1] + x*2 + stride[1]*y)); r = *((const uint16_t *)(src[2] + x*2 + stride[2]*y)); + if (transparency) + a = *((const uint16_t *)(src[3] + x*2 + stride[3]*y)); } else { b = *((const uint16_t *)(src[0] + x*2 + stride[0]*y)); g = *((const uint16_t *)(src[1] + x*2 + stride[1]*y)); @@ -179,7 +185,7 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[3], sample[2][0][x] = r; sample[3][0][x] = a; } - for (p = 0; p < 3 + s->transparency; p++) { + for (p = 0; p < 3 + transparency; p++) { int ret; sample[p][0][-1] = sample[p][1][0 ]; sample[p][1][ w] = sample[p][1][w-1]; From 8f6a71f7f13d21614f5140e672976e96dca04af8 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 31 Jan 2018 15:22:29 +0100 Subject: [PATCH 1812/2557] avformat/bintext: Implement bin_probe() Fixes misdetection of sbQ9.bin Signed-off-by: Michael Niedermayer --- libavformat/bintext.c | 49 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/libavformat/bintext.c b/libavformat/bintext.c index 12e3bfde4deb5..f1c0b3e8925b7 100644 --- a/libavformat/bintext.c +++ b/libavformat/bintext.c @@ -126,6 +126,53 @@ static void predict_width(AVCodecParameters *par, uint64_t fsize, int got_width) par->width = fsize > 4000 ? (160<<3) : (80<<3); } +static int bin_probe(AVProbeData *p) +{ + const uint8_t *d = p->buf; + int magic = 0, sauce = 0; + int invisible = 0; + int i; + + if (p->buf_size > 256) + magic = !memcmp(d + p->buf_size - 256, next_magic, sizeof(next_magic)); + if (p->buf_size > 128) + sauce = !memcmp(d + p->buf_size - 128, "SAUCE00", 7); + + if (magic) + return AVPROBE_SCORE_EXTENSION + 1; + + if (av_match_ext(p->filename, "bin")) { + AVCodecParameters par; + int got_width = 0; + par.width = par.height = 0; + if (sauce) + return AVPROBE_SCORE_EXTENSION + 1; + + predict_width(&par, p->buf_size, got_width); + if (par.width <= 0) + return 0; + calculate_height(&par, p->buf_size); + if (par.height <= 0) + return 0; + + for (i = 0; i < p->buf_size - 256; i+=2) { + if ((d[i+1] & 15) == (d[i+1] >> 4) && d[i] && d[i] != 0xFF && d[i] != ' ') { + invisible ++; + } + } + + if (par.width * par.height * 2 / (8*16) == p->buf_size) + return AVPROBE_SCORE_MAX / 2; + return 1; + } + + if (sauce) + return 1; + + return 0; +} + + static int bintext_read_header(AVFormatContext *s) { BinDemuxContext *bin = s->priv_data; @@ -343,9 +390,9 @@ AVInputFormat ff_bintext_demuxer = { .name = "bin", .long_name = NULL_IF_CONFIG_SMALL("Binary text"), .priv_data_size = sizeof(BinDemuxContext), + .read_probe = bin_probe, .read_header = bintext_read_header, .read_packet = read_packet, - .extensions = "bin", .priv_class = CLASS("Binary text demuxer"), }; #endif From 8885a29e5dc832622c6a4c07f51e93a082811b09 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 6 Feb 2018 20:02:23 -0300 Subject: [PATCH 1813/2557] avformat/Makefile: fix fifo and fifo_test muxer build objects Signed-off-by: James Almer --- libavformat/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index e0bb8aef86eff..1b3547971511a 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -163,7 +163,8 @@ OBJS-$(CONFIG_EAC3_MUXER) += rawenc.o OBJS-$(CONFIG_EPAF_DEMUXER) += epafdec.o pcm.o OBJS-$(CONFIG_FFMETADATA_DEMUXER) += ffmetadec.o OBJS-$(CONFIG_FFMETADATA_MUXER) += ffmetaenc.o -OBJS-$(CONFIG_FIFO_MUXER) += fifo.o fifo_test.o +OBJS-$(CONFIG_FIFO_MUXER) += fifo.o +OBJS-$(CONFIG_FIFO_TEST_MUXER) += fifo_test.o OBJS-$(CONFIG_FILMSTRIP_DEMUXER) += filmstripdec.o OBJS-$(CONFIG_FILMSTRIP_MUXER) += filmstripenc.o OBJS-$(CONFIG_FITS_DEMUXER) += fitsdec.o From f7aacf4ab7654a57408d5c0f871fd3b39930c6d7 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 5 Feb 2018 22:26:26 -0300 Subject: [PATCH 1814/2557] avformat/mov: add VP8 codec support Demuxing only. Muxing is disabled as altref frame handling is not defined in the spec, and there's no way to know the presence of such frames during stream initialization. Based on a patch by Steven Liu. Fixes ticket #7000 Reviewed-by: Carl Eugen Hoyos Signed-off-by: James Almer --- libavformat/isom.c | 1 + libavformat/mov.c | 1 + libavformat/movenc.c | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/libavformat/isom.c b/libavformat/isom.c index 9d9f85885b0b4..59502a8b3f2be 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -186,6 +186,7 @@ const AVCodecTag ff_codec_movvideo_tags[] = { { AV_CODEC_ID_H264, MKTAG('x', 'a', 'l', 'g') }, /* XAVC-L HD422 produced by FCP */ { AV_CODEC_ID_H264, MKTAG('a', 'v', 'l', 'g') }, /* Panasonic P2 AVC-LongG */ + { AV_CODEC_ID_VP8, MKTAG('v', 'p', '0', '8') }, /* VP8 */ { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') }, /* VP9 */ { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', ' ') }, diff --git a/libavformat/mov.c b/libavformat/mov.c index d16b431e039cc..acfbfc5324d13 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2397,6 +2397,7 @@ static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb, case AV_CODEC_ID_EAC3: case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_VC1: + case AV_CODEC_ID_VP8: case AV_CODEC_ID_VP9: st->need_parsing = AVSTREAM_PARSE_FULL; break; diff --git a/libavformat/movenc.c b/libavformat/movenc.c index f7079f3df7456..f43349932b216 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -6079,6 +6079,11 @@ static int mov_init(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "VP9 only supported in MP4.\n"); return AVERROR(EINVAL); } + } else if (track->par->codec_id == AV_CODEC_ID_VP8) { + /* altref frames handling is not defined in the spec as of version v1.0, + * so just forbid muxing VP8 streams altogether until a new version does */ + av_log(s, AV_LOG_ERROR, "VP8 muxing is currently not supported.\n"); + return AVERROR_PATCHWELCOME; } } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { track->timescale = st->codecpar->sample_rate; From 36c85d6e773d51af1d084fb15ad89d9acc5dd893 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 6 Feb 2018 23:38:38 -0300 Subject: [PATCH 1815/2557] api: add missing version bumps and APIChanges entries avcodec bump missed in 7e8eba2d8755962d9dca5eade57bf8f591a73c0c avformat bump missed in ff46124b0df17a1d35249e09ae8eae9a61f16e04 and 0694d8702421e7aff1340038559c438b61bb30dd avdevice bump missed in 0fd475704e871ef3a535947596a012894bae3cbd Signed-off-by: James Almer --- doc/APIchanges | 7 ++++++- libavcodec/version.h | 2 +- libavdevice/version.h | 4 ++-- libavformat/version.h | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 69fb58eaded08..3523d3b7bda12 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,12 +15,17 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-02-06 - 0fd475704e - lavd 58.1.100 - avdevice.h + Deprecate use of av_input_audio_device_next(), av_input_video_device_next(), + av_output_audio_device_next(), av_output_video_device_next(). + Add av_indev_iterate(), and av_outdev_iterate(). + 2018-xx-xx - xxxxxxx - lavf 58.9.100 - avformat.h Deprecate use of av_register_input_format(), av_register_output_format(), avformat_register_all(), av_iformat_next(), av_oformat_next(). Add av_demuxer_iterate(), and av_muxer_iterate(). -2018-xx-xx - xxxxxxx - lavc 58.9.100 - avcodec.h +2018-xx-xx - xxxxxxx - lavc 58.10.100 - avcodec.h Deprecate use of avcodec_register(), avcodec_register_all(), and av_codec_next(). Add av_codec_iterate(). diff --git a/libavcodec/version.h b/libavcodec/version.h index 8cc0f9bf9c3fe..e36cea30b5586 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 9 +#define LIBAVCODEC_VERSION_MINOR 10 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavdevice/version.h b/libavdevice/version.h index 892c4f374edb2..e5f60032f7c1e 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVDEVICE_VERSION_MAJOR 58 -#define LIBAVDEVICE_VERSION_MINOR 0 -#define LIBAVDEVICE_VERSION_MICRO 101 +#define LIBAVDEVICE_VERSION_MINOR 1 +#define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ LIBAVDEVICE_VERSION_MINOR, \ diff --git a/libavformat/version.h b/libavformat/version.h index 7669c226237ba..009f981095377 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 7 +#define LIBAVFORMAT_VERSION_MINOR 9 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From e8323c42c19f58b84c5742cc3c734a4a2f3737af Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 6 Feb 2018 23:49:13 -0300 Subject: [PATCH 1816/2557] doc/APIChanges: fix lavu version numbers in a few recent entries Signed-off-by: James Almer --- doc/APIchanges | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 3523d3b7bda12..c67be2b05c527 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -103,14 +103,14 @@ API changes, most recent first: 2017-11-xx - xxxxxxx - lavc 58.4.100 - avcodec.h Add AVCodecHWConfig and avcodec_get_hw_config(). -2017-11-22 - 3650cb2dfa - lavu 55.3.100 - opencl.h +2017-11-22 - 3650cb2dfa - lavu 56.3.100 - opencl.h Remove experimental OpenCL API (av_opencl_*). -2017-11-22 - b25d8ef0a7 - lavu 55.2.100 - hwcontext.h hwcontext_opencl.h +2017-11-22 - b25d8ef0a7 - lavu 56.2.100 - hwcontext.h hwcontext_opencl.h Add AV_HWDEVICE_TYPE_OPENCL and a new installed header with OpenCL-specific hwcontext definitions. -2017-11-22 - a050f56c09 - lavu 55.1.100 - pixfmt.h +2017-11-22 - a050f56c09 - lavu 56.1.100 - pixfmt.h Add AV_PIX_FMT_OPENCL. 2017-11-11 - 48e4eda11d - lavc 58.3.100 - avcodec.h From 8318bf17513529c86545dfaeec489636d77df78d Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 7 Feb 2018 00:29:55 -0300 Subject: [PATCH 1817/2557] avformat/fifo_test: remove network.h include It's not needed, and fixes compilation with network disabled. Signed-off-by: James Almer --- libavformat/fifo_test.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavformat/fifo_test.c b/libavformat/fifo_test.c index 188e607855944..02ec215cbbb8b 100644 --- a/libavformat/fifo_test.c +++ b/libavformat/fifo_test.c @@ -20,12 +20,13 @@ */ #include + #include "libavutil/opt.h" #include "libavutil/time.h" #include "libavutil/avassert.h" -#include "libavformat/avformat.h" -#include "libavformat/url.h" -#include "libavformat/network.h" + +#include "avformat.h" +#include "url.h" /* Implementation of mock muxer to simulate real muxer failures */ From 33d632d40e147f99aaacafd9621f696a27dbf239 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Mon, 5 Feb 2018 11:04:45 +0000 Subject: [PATCH 1818/2557] lavfi: add a gitignore file for OpenCL compiled kernels Signed-off-by: Rostislav Pehlivanov --- libavfilter/opencl/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 libavfilter/opencl/.gitignore diff --git a/libavfilter/opencl/.gitignore b/libavfilter/opencl/.gitignore new file mode 100644 index 0000000000000..064a8d8ef55dc --- /dev/null +++ b/libavfilter/opencl/.gitignore @@ -0,0 +1 @@ +*.c From 651d5f963921bbd547373380e1581df9bbc83199 Mon Sep 17 00:00:00 2001 From: Richard Shaffer Date: Fri, 2 Feb 2018 12:59:45 -0800 Subject: [PATCH 1819/2557] avformat/hls: Support metadata updates from subdemuxers If a subdemuxer has the updated metadata event flag set, the metadata is copied to the corresponding stream. The flag is cleared on the subdemuxer and the appropriate event flag is set on the stream. Signed-off-by: wm4 --- libavformat/hls.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/libavformat/hls.c b/libavformat/hls.c index 9bd54c84ccf6b..c578bf86e3b8d 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1062,6 +1062,7 @@ static void handle_id3(AVIOContext *pb, struct playlist *pls) /* demuxer not yet opened, defer picture attachment */ pls->id3_deferred_extra = extra_meta; + ff_id3v2_parse_priv_dict(&metadata, &extra_meta); av_dict_copy(&pls->ctx->metadata, metadata, 0); pls->id3_initial = metadata; @@ -1960,6 +1961,7 @@ static int hls_read_header(AVFormatContext *s) if (pls->id3_deferred_extra && pls->ctx->nb_streams == 1) { ff_id3v2_parse_apic(pls->ctx, &pls->id3_deferred_extra); avformat_queue_attached_pictures(pls->ctx); + ff_id3v2_parse_priv(pls->ctx, &pls->id3_deferred_extra); ff_id3v2_free_extra_meta(&pls->id3_deferred_extra); pls->id3_deferred_extra = NULL; } @@ -1986,6 +1988,13 @@ static int hls_read_header(AVFormatContext *s) if (ret < 0) goto fail; + /* + * Copy any metadata from playlist to main streams, but do not set + * event flags. + */ + if (pls->n_main_streams) + av_dict_copy(&pls->main_streams[0]->metadata, pls->ctx->metadata, 0); + add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_AUDIO); add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_VIDEO); add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_SUBTITLE); @@ -2170,6 +2179,17 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) return ret; } + // If sub-demuxer reports updated metadata, copy it to the first stream + // and set its AVSTREAM_EVENT_FLAG_METADATA_UPDATED flag. + if (pls->ctx->event_flags & AVFMT_EVENT_FLAG_METADATA_UPDATED) { + if (pls->n_main_streams) { + st = pls->main_streams[0]; + av_dict_copy(&st->metadata, pls->ctx->metadata, 0); + st->event_flags |= AVSTREAM_EVENT_FLAG_METADATA_UPDATED; + } + pls->ctx->event_flags &= ~AVFMT_EVENT_FLAG_METADATA_UPDATED; + } + /* check if noheader flag has been cleared by the subdemuxer */ if (pls->has_noheader_flag && !(pls->ctx->ctx_flags & AVFMTCTX_NOHEADER)) { pls->has_noheader_flag = 0; From cf666651b4992d41a8e6df47cc636116c07f78a1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 7 Feb 2018 16:42:11 -0300 Subject: [PATCH 1820/2557] avformat: fix stream_segment muxer build dependencies Signed-off-by: James Almer --- libavformat/Makefile | 1 + libavformat/segment.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/libavformat/Makefile b/libavformat/Makefile index 1b3547971511a..f9a45338ece7a 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -474,6 +474,7 @@ OBJS-$(CONFIG_SRT_DEMUXER) += srtdec.o subtitles.o OBJS-$(CONFIG_SRT_MUXER) += srtenc.o OBJS-$(CONFIG_STL_DEMUXER) += stldec.o subtitles.o OBJS-$(CONFIG_STR_DEMUXER) += psxstr.o +OBJS-$(CONFIG_STREAM_SEGMENT_MUXER) += segment.o OBJS-$(CONFIG_SUBVIEWER1_DEMUXER) += subviewer1dec.o subtitles.o OBJS-$(CONFIG_SUBVIEWER_DEMUXER) += subviewerdec.o subtitles.o OBJS-$(CONFIG_SUP_DEMUXER) += supdec.o diff --git a/libavformat/segment.c b/libavformat/segment.c index 8da4fca512d1a..7fb4dc7d2124c 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -1064,6 +1064,7 @@ static const AVOption options[] = { { NULL }, }; +#if CONFIG_SEGMENT_MUXER static const AVClass seg_class = { .class_name = "segment muxer", .item_name = av_default_item_name, @@ -1084,7 +1085,9 @@ AVOutputFormat ff_segment_muxer = { .check_bitstream = seg_check_bitstream, .priv_class = &seg_class, }; +#endif +#if CONFIG_STREAM_SEGMENT_MUXER static const AVClass sseg_class = { .class_name = "stream_segment muxer", .item_name = av_default_item_name, @@ -1105,3 +1108,4 @@ AVOutputFormat ff_stream_segment_muxer = { .check_bitstream = seg_check_bitstream, .priv_class = &sseg_class, }; +#endif From 9d8fb095e6f886cf0fd377cfb416b00ff1e24bd1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 7 Feb 2018 16:56:47 -0300 Subject: [PATCH 1821/2557] doc/APIchanges: fix a recent depreacted function name Signed-off-by: James Almer --- doc/APIchanges | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index c67be2b05c527..21a2cca709f62 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -22,7 +22,7 @@ API changes, most recent first: 2018-xx-xx - xxxxxxx - lavf 58.9.100 - avformat.h Deprecate use of av_register_input_format(), av_register_output_format(), - avformat_register_all(), av_iformat_next(), av_oformat_next(). + av_register_all(), av_iformat_next(), av_oformat_next(). Add av_demuxer_iterate(), and av_muxer_iterate(). 2018-xx-xx - xxxxxxx - lavc 58.10.100 - avcodec.h From 3f0a41367eb9180ab6d22d43ad42b9bd85a26df0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 7 Feb 2018 17:05:01 -0300 Subject: [PATCH 1822/2557] doc/APIchanges: mention a few more recently introduced and deprecated functions Signed-off-by: James Almer --- doc/APIchanges | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 21a2cca709f62..91f41a5020ad3 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -26,8 +26,9 @@ API changes, most recent first: Add av_demuxer_iterate(), and av_muxer_iterate(). 2018-xx-xx - xxxxxxx - lavc 58.10.100 - avcodec.h - Deprecate use of avcodec_register(), avcodec_register_all(), and - av_codec_next(). Add av_codec_iterate(). + Deprecate use of avcodec_register(), avcodec_register_all(), + av_codec_next(), av_register_codec_parser(), and av_parser_next(). + Add av_codec_iterate() and av_parser_iterate(). 2018-02-xx - xxxxxxx - lavf 58.8.100 - avformat.h Deprecate the current names of the RTSP "timeout", "stimeout", "user-agent" From ddd851f7cbcb9181445b81bb3ff526f11f69c295 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 6 Feb 2018 01:21:08 +0100 Subject: [PATCH 1823/2557] avcodec: Document that init_static_data() is not intended for time consuming operations. Reviewed-by: Muhammad Faiz Signed-off-by: Michael Niedermayer --- libavcodec/avcodec.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index c41779ad40c27..1c32339754459 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3439,6 +3439,9 @@ typedef struct AVCodec { /** * Initialize codec static data, called from avcodec_register(). + * + * This is not intended for time consuming operations as it is + * run for every codec regardless of that codec being used. */ void (*init_static_data)(struct AVCodec *codec); From cb97400f93ba925485ef0af976cd656b90a9ba86 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 8 Feb 2018 13:20:36 -0300 Subject: [PATCH 1824/2557] Revert "cmdutils: make use of new iteration APIs" This reverts commit cdc78058c78dfa4966758a342acd2c1f3b282c46. It introduced several issues in the command line tools, and it's implementing a new API that may still see some changes. Revert for the time being until the state of the API is defined. Signed-off-by: James Almer --- fftools/cmdutils.c | 122 +++++++++++++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 43 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 0b06ccc71a083..0c7d13c27a780 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1250,11 +1250,19 @@ int show_license(void *optctx, const char *opt, const char *arg) return 0; } +static int is_device(const AVClass *avclass) +{ + if (!avclass) + return 0; + return AV_IS_INPUT_DEVICE(avclass->category) || AV_IS_OUTPUT_DEVICE(avclass->category); +} + static int show_formats_devices(void *optctx, const char *opt, const char *arg, int device_only, int muxdemuxers) { - const AVInputFormat *ifmt = NULL; - const AVOutputFormat *ofmt = NULL; + AVInputFormat *ifmt = NULL; + AVOutputFormat *ofmt = NULL; const char *last_name; + int is_dev; printf("%s\n" " D. = Demuxing supported\n" @@ -1267,24 +1275,34 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg, const char *name = NULL; const char *long_name = NULL; -#define x(func, type, condition) do { \ - void *i = 0; \ - if (condition) { \ - while ((type = func(&i))) { \ - if ((!name || strcmp(type->name, name) < 0) && \ - strcmp(type->name, last_name) > 0) { \ - name = type->name; \ - long_name = type->long_name; \ - encode = 1; \ - } \ - } \ - } } while(0) - - x(av_muxer_iterate, ofmt, muxdemuxers != SHOW_DEMUXERS && !device_only); - x(av_outdev_iterate, ofmt, muxdemuxers != SHOW_DEMUXERS); - x(av_demuxer_iterate, ifmt, muxdemuxers != SHOW_MUXERS && !device_only); - x(av_indev_iterate, ifmt, muxdemuxers != SHOW_MUXERS); -#undef x + if (muxdemuxers !=SHOW_DEMUXERS) { + while ((ofmt = av_oformat_next(ofmt))) { + is_dev = is_device(ofmt->priv_class); + if (!is_dev && device_only) + continue; + if ((!name || strcmp(ofmt->name, name) < 0) && + strcmp(ofmt->name, last_name) > 0) { + name = ofmt->name; + long_name = ofmt->long_name; + encode = 1; + } + } + } + if (muxdemuxers != SHOW_MUXERS) { + while ((ifmt = av_iformat_next(ifmt))) { + is_dev = is_device(ifmt->priv_class); + if (!is_dev && device_only) + continue; + if ((!name || strcmp(ifmt->name, name) < 0) && + strcmp(ifmt->name, last_name) > 0) { + name = ifmt->name; + long_name = ifmt->long_name; + encode = 0; + } + if (name && strcmp(ifmt->name, name) == 0) + decode = 1; + } + } if (!name) break; last_name = name; @@ -1424,8 +1442,7 @@ static char get_media_type_char(enum AVMediaType type) static const AVCodec *next_codec_for_id(enum AVCodecID id, const AVCodec *prev, int encoder) { - void *i = 0; - while ((prev = av_codec_iterate(&i))) { + while ((prev = av_codec_next(prev))) { if (prev->id == id && (encoder ? av_codec_is_encoder(prev) : av_codec_is_decoder(prev))) return prev; @@ -2099,7 +2116,7 @@ double get_rotation(AVStream *st) } #if CONFIG_AVDEVICE -static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) +static int print_device_sources(AVInputFormat *fmt, AVDictionary *opts) { int ret, i; AVDeviceInfoList *device_list = NULL; @@ -2114,7 +2131,7 @@ static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) goto fail; } - if ((ret = avdevice_list_input_sources((AVInputFormat*)fmt, NULL, opts, &device_list)) < 0) { + if ((ret = avdevice_list_input_sources(fmt, NULL, opts, &device_list)) < 0) { printf("Cannot list sources.\n"); goto fail; } @@ -2129,7 +2146,7 @@ static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) return ret; } -static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *opts) +static int print_device_sinks(AVOutputFormat *fmt, AVDictionary *opts) { int ret, i; AVDeviceInfoList *device_list = NULL; @@ -2144,7 +2161,7 @@ static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *opts) goto fail; } - if ((ret = avdevice_list_output_sinks((AVOutputFormat*)fmt, NULL, opts, &device_list)) < 0) { + if ((ret = avdevice_list_output_sinks(fmt, NULL, opts, &device_list)) < 0) { printf("Cannot list sinks.\n"); goto fail; } @@ -2183,8 +2200,7 @@ static int show_sinks_sources_parse_arg(const char *arg, char **dev, AVDictionar int show_sources(void *optctx, const char *opt, const char *arg) { - const AVInputFormat *fmt = NULL; - void *i = 0; + AVInputFormat *fmt = NULL; char *dev = NULL; AVDictionary *opts = NULL; int ret = 0; @@ -2195,14 +2211,24 @@ int show_sources(void *optctx, const char *opt, const char *arg) if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0) goto fail; - while ((fmt = av_indev_iterate(&i))) { - if (!strcmp(fmt->name, "lavfi")) - continue; //it's pointless to probe lavfi - if (dev && !av_match_name(dev, fmt->name)) - continue; - print_device_sources(fmt, opts); - } - + do { + fmt = av_input_audio_device_next(fmt); + if (fmt) { + if (!strcmp(fmt->name, "lavfi")) + continue; //it's pointless to probe lavfi + if (dev && !av_match_name(dev, fmt->name)) + continue; + print_device_sources(fmt, opts); + } + } while (fmt); + do { + fmt = av_input_video_device_next(fmt); + if (fmt) { + if (dev && !av_match_name(dev, fmt->name)) + continue; + print_device_sources(fmt, opts); + } + } while (fmt); fail: av_dict_free(&opts); av_free(dev); @@ -2212,8 +2238,7 @@ int show_sources(void *optctx, const char *opt, const char *arg) int show_sinks(void *optctx, const char *opt, const char *arg) { - const AVOutputFormat *fmt = NULL; - void *i = 0; + AVOutputFormat *fmt = NULL; char *dev = NULL; AVDictionary *opts = NULL; int ret = 0; @@ -2224,11 +2249,22 @@ int show_sinks(void *optctx, const char *opt, const char *arg) if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0) goto fail; - while ((fmt = av_outdev_iterate(&i))) { - if (dev && !av_match_name(dev, fmt->name)) - continue; - print_device_sinks(fmt, opts); - } + do { + fmt = av_output_audio_device_next(fmt); + if (fmt) { + if (dev && !av_match_name(dev, fmt->name)) + continue; + print_device_sinks(fmt, opts); + } + } while (fmt); + do { + fmt = av_output_video_device_next(fmt); + if (fmt) { + if (dev && !av_match_name(dev, fmt->name)) + continue; + print_device_sinks(fmt, opts); + } + } while (fmt); fail: av_dict_free(&opts); av_free(dev); From 08c220d26cff51ca2f6896b65aebfa3accc67290 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 31 Jan 2018 19:20:10 +0100 Subject: [PATCH 1825/2557] avcodec/huffyuvdec: Check input buffer size Fixes: Timeout Fixes: 5487/clusterfuzz-testcase-4696837035393024 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer --- libavcodec/huffyuvdec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/huffyuvdec.c b/libavcodec/huffyuvdec.c index 979c4b9d5c11a..66357bfb40353 100644 --- a/libavcodec/huffyuvdec.c +++ b/libavcodec/huffyuvdec.c @@ -919,6 +919,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVFrame *const p = data; int table_size = 0, ret; + if (buf_size < (width * height + 7)/8) + return AVERROR_INVALIDDATA; + av_fast_padded_malloc(&s->bitstream_buffer, &s->bitstream_buffer_size, buf_size); From e752da546463e693865d92a837fc0e8d2b28db2e Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 9 Feb 2018 10:54:24 +0800 Subject: [PATCH 1826/2557] dashdec: Support SegmentTimeline inside Period Reviewed-by: Steven Liu --- libavformat/dashdec.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index f9dc03309798b..2b396a01b7171 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -801,6 +801,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr mpd_baseurl_node, xmlNodePtr period_baseurl_node, xmlNodePtr period_segmenttemplate_node, + xmlNodePtr period_segmentlist_node, xmlNodePtr fragment_template_node, xmlNodePtr content_component_node, xmlNodePtr adaptionset_baseurl_node, @@ -817,7 +818,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr representation_segmentlist_node = NULL; xmlNodePtr segmentlists_tab[2]; xmlNodePtr fragment_timeline_node = NULL; - xmlNodePtr fragment_templates_tab[4]; + xmlNodePtr fragment_templates_tab[5]; char *duration_val = NULL; char *presentation_timeoffset_val = NULL; char *startnumber_val = NULL; @@ -869,6 +870,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, fragment_templates_tab[1] = adaptionset_segmentlist_node; fragment_templates_tab[2] = fragment_template_node; fragment_templates_tab[3] = period_segmenttemplate_node; + fragment_templates_tab[4] = period_segmentlist_node; presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "presentationTimeOffset"); duration_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "duration"); @@ -925,6 +927,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline"); if (!fragment_timeline_node) fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline"); + if (!fragment_timeline_node) + fragment_timeline_node = find_child_node_by_name(period_segmentlist_node, "SegmentTimeline"); if (fragment_timeline_node) { fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); while (fragment_timeline_node) { @@ -984,6 +988,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline"); if (!fragment_timeline_node) fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline"); + if (!fragment_timeline_node) + fragment_timeline_node = find_child_node_by_name(period_segmentlist_node, "SegmentTimeline"); if (fragment_timeline_node) { fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); while (fragment_timeline_node) { @@ -1040,7 +1046,8 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, xmlNodePtr adaptionset_node, xmlNodePtr mpd_baseurl_node, xmlNodePtr period_baseurl_node, - xmlNodePtr period_segmenttemplate_node) + xmlNodePtr period_segmenttemplate_node, + xmlNodePtr period_segmentlist_node) { int ret = 0; xmlNodePtr fragment_template_node = NULL; @@ -1065,6 +1072,7 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, mpd_baseurl_node, period_baseurl_node, period_segmenttemplate_node, + period_segmentlist_node, fragment_template_node, content_component_node, adaptionset_baseurl_node, @@ -1094,6 +1102,7 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) xmlNodePtr mpd_baseurl_node = NULL; xmlNodePtr period_baseurl_node = NULL; xmlNodePtr period_segmenttemplate_node = NULL; + xmlNodePtr period_segmentlist_node = NULL; xmlNodePtr adaptionset_node = NULL; xmlAttrPtr attr = NULL; char *val = NULL; @@ -1228,8 +1237,10 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) period_baseurl_node = adaptionset_node; } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"SegmentTemplate")) { period_segmenttemplate_node = adaptionset_node; + } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"SegmentList")) { + period_segmentlist_node = adaptionset_node; } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"AdaptationSet")) { - parse_manifest_adaptationset(s, url, adaptionset_node, mpd_baseurl_node, period_baseurl_node, period_segmenttemplate_node); + parse_manifest_adaptationset(s, url, adaptionset_node, mpd_baseurl_node, period_baseurl_node, period_segmenttemplate_node, period_segmentlist_node); } adaptionset_node = xmlNextElementSibling(adaptionset_node); } From 5a2abf00f1949fa3dd64e55ae1963b1fd566e9ab Mon Sep 17 00:00:00 2001 From: Muhammad Faiz Date: Sat, 3 Feb 2018 01:07:44 +0700 Subject: [PATCH 1827/2557] avcodec/codec_desc: sort codec_descriptors Use bsearch on avcodec_descriptor_get(). Reviewed-by: Michael Niedermayer Signed-off-by: Muhammad Faiz --- libavcodec/codec_desc.c | 1103 ++++++++++++++++++++------------------- 1 file changed, 563 insertions(+), 540 deletions(-) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index c3688de1d6df4..1e5d715416494 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -21,8 +21,10 @@ #include +#include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/internal.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "profiles.h" #include "version.h" @@ -89,6 +91,28 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Apple MJPEG-B"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_LJPEG, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ljpeg", + .long_name = NULL_IF_CONFIG_SMALL("Lossless JPEG"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_SP5X, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sp5x", + .long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_JPEGLS, + .type = AVMEDIA_TYPE_VIDEO, + .name = "jpegls", + .long_name = NULL_IF_CONFIG_SMALL("JPEG-LS"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + }, { .id = AV_CODEC_ID_MPEG4, .type = AVMEDIA_TYPE_VIDEO, @@ -160,14 +184,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("FLV / Sorenson Spark / Sorenson H.263 (Flash Video)"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_SVG, - .type = AVMEDIA_TYPE_VIDEO, - .name = "svg", - .long_name = NULL_IF_CONFIG_SMALL("Scalable Vector Graphics"), - .props = AV_CODEC_PROP_LOSSLESS, - .mime_types= MT("image/svg+xml"), - }, { .id = AV_CODEC_ID_SVQ1, .type = AVMEDIA_TYPE_VIDEO, @@ -407,13 +423,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"), .props = AV_CODEC_PROP_LOSSLESS, }, - { - .id = AV_CODEC_ID_SNOW, - .type = AVMEDIA_TYPE_VIDEO, - .name = "snow", - .long_name = NULL_IF_CONFIG_SMALL("Snow"), - .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_TSCC, .type = AVMEDIA_TYPE_VIDEO, @@ -449,6 +458,50 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Q-team QPEG"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_PNG, + .type = AVMEDIA_TYPE_VIDEO, + .name = "png", + .long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), + .props = AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/png"), + }, + { + .id = AV_CODEC_ID_PPM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ppm", + .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PBM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pbm", + .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PGM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pgm", + .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PGMYUV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pgmyuv", + .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PAM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pam", + .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/x-portable-pixmap"), + }, { .id = AV_CODEC_ID_FFVHUFF, .type = AVMEDIA_TYPE_VIDEO, @@ -637,6 +690,14 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("On2 VP6 (Flash version)"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_TARGA, + .type = AVMEDIA_TYPE_VIDEO, + .name = "targa", + .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/x-targa", "image/x-tga"), + }, { .id = AV_CODEC_ID_DSICINVIDEO, .type = AVMEDIA_TYPE_VIDEO, @@ -651,6 +712,22 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_TIFF, + .type = AVMEDIA_TYPE_VIDEO, + .name = "tiff", + .long_name = NULL_IF_CONFIG_SMALL("TIFF image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/tiff"), + }, + { + .id = AV_CODEC_ID_GIF, + .type = AVMEDIA_TYPE_VIDEO, + .name = "gif", + .long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), + .props = AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/gif"), + }, { .id = AV_CODEC_ID_DXA, .type = AVMEDIA_TYPE_VIDEO, @@ -673,6 +750,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Nintendo Gamecube THP video"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_SGI, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sgi", + .long_name = NULL_IF_CONFIG_SMALL("SGI image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, { .id = AV_CODEC_ID_C93, .type = AVMEDIA_TYPE_VIDEO, @@ -687,6 +771,20 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Bethesda VID video"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_PTX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ptx", + .long_name = NULL_IF_CONFIG_SMALL("V.Flash PTX image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TXD, + .type = AVMEDIA_TYPE_VIDEO, + .name = "txd", + .long_name = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_VP6A, .type = AVMEDIA_TYPE_VIDEO, @@ -708,6 +806,21 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Beam Software VB"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_PCX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pcx", + .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/x-pcx"), + }, + { + .id = AV_CODEC_ID_SUNRAST, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sunrast", + .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, { .id = AV_CODEC_ID_INDEO4, .type = AVMEDIA_TYPE_VIDEO, @@ -743,13 +856,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Escape 124"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_DAALA, - .type = AVMEDIA_TYPE_VIDEO, - .name = "daala", - .long_name = NULL_IF_CONFIG_SMALL("Daala"), - .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_DIRAC, .type = AVMEDIA_TYPE_VIDEO, @@ -834,6 +940,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_DPX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "dpx", + .long_name = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, { .id = AV_CODEC_ID_MAD, .type = AVMEDIA_TYPE_VIDEO, @@ -911,14 +1024,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("On2 VP8"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_VP9, - .type = AVMEDIA_TYPE_VIDEO, - .name = "vp9", - .long_name = NULL_IF_CONFIG_SMALL("Google VP9"), - .props = AV_CODEC_PROP_LOSSY, - .profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), - }, { .id = AV_CODEC_ID_PICTOR, .type = AVMEDIA_TYPE_VIDEO, @@ -926,6 +1031,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Pictor/PC Paint"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_ANSI, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ansi", + .long_name = NULL_IF_CONFIG_SMALL("ASCII/ANSI art"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_A64_MULTI, .type = AVMEDIA_TYPE_VIDEO, @@ -947,27 +1059,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("AJA Kona 10-bit RGB Codec"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, - { - .id = AV_CODEC_ID_M101, - .type = AVMEDIA_TYPE_VIDEO, - .name = "m101", - .long_name = NULL_IF_CONFIG_SMALL("Matrox Uncompressed SD"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_MVC1, - .type = AVMEDIA_TYPE_VIDEO, - .name = "mvc1", - .long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 1"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_MVC2, - .type = AVMEDIA_TYPE_VIDEO, - .name = "mvc2", - .long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 2"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, - }, { .id = AV_CODEC_ID_MXPEG, .type = AVMEDIA_TYPE_VIDEO, @@ -1003,6 +1094,20 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Chronomaster DFA"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_WMV3IMAGE, + .type = AVMEDIA_TYPE_VIDEO, + .name = "wmv3image", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VC1IMAGE, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vc1image", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image v2"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_UTVIDEO, .type = AVMEDIA_TYPE_VIDEO, @@ -1038,6 +1143,14 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:4:4 10-bit"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_XWD, + .type = AVMEDIA_TYPE_VIDEO, + .name = "xwd", + .long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/x-xwindowdump"), + }, { .id = AV_CODEC_ID_CDXL, .type = AVMEDIA_TYPE_VIDEO, @@ -1045,6 +1158,14 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_XBM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "xbm", + .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/x-xbitmap"), + }, { .id = AV_CODEC_ID_ZEROCODEC, .type = AVMEDIA_TYPE_VIDEO, @@ -1094,6 +1215,14 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("MS Windows Media Video V9 Screen"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_VP9, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vp9", + .long_name = NULL_IF_CONFIG_SMALL("Google VP9"), + .props = AV_CODEC_PROP_LOSSY, + .profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), + }, { .id = AV_CODEC_ID_AIC, .type = AVMEDIA_TYPE_VIDEO, @@ -1101,13 +1230,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Apple Intermediate Codec"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_Y41P, - .type = AVMEDIA_TYPE_VIDEO, - .name = "y41p", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed YUV 4:1:1 12-bit"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_ESCAPE130, .type = AVMEDIA_TYPE_VIDEO, @@ -1116,96 +1238,23 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_LOSSY, }, { - .id = AV_CODEC_ID_AVRP, + .id = AV_CODEC_ID_G2M, .type = AVMEDIA_TYPE_VIDEO, - .name = "avrp", - .long_name = NULL_IF_CONFIG_SMALL("Avid 1:1 10-bit RGB Packer"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .name = "g2m", + .long_name = NULL_IF_CONFIG_SMALL("Go2Meeting"), + .props = AV_CODEC_PROP_LOSSY, }, { - .id = AV_CODEC_ID_012V, + .id = AV_CODEC_ID_WEBP, .type = AVMEDIA_TYPE_VIDEO, - .name = "012v", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .name = "webp", + .long_name = NULL_IF_CONFIG_SMALL("WebP"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/webp"), }, { - .id = AV_CODEC_ID_AVUI, - .type = AVMEDIA_TYPE_VIDEO, - .name = "avui", - .long_name = NULL_IF_CONFIG_SMALL("Avid Meridien Uncompressed"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_AYUV, - .type = AVMEDIA_TYPE_VIDEO, - .name = "ayuv", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed MS 4:4:4:4"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_TARGA_Y216, - .type = AVMEDIA_TYPE_VIDEO, - .name = "targa_y216", - .long_name = NULL_IF_CONFIG_SMALL("Pinnacle TARGA CineWave YUV16"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_V308, - .type = AVMEDIA_TYPE_VIDEO, - .name = "v308", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:4:4"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_V408, - .type = AVMEDIA_TYPE_VIDEO, - .name = "v408", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed QT 4:4:4:4"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_YUV4, - .type = AVMEDIA_TYPE_VIDEO, - .name = "yuv4", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:2:0"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_AVRN, - .type = AVMEDIA_TYPE_VIDEO, - .name = "avrn", - .long_name = NULL_IF_CONFIG_SMALL("Avid AVI Codec"), - }, - { - .id = AV_CODEC_ID_CPIA, - .type = AVMEDIA_TYPE_VIDEO, - .name = "cpia", - .long_name = NULL_IF_CONFIG_SMALL("CPiA video format"), - }, - { - .id = AV_CODEC_ID_XFACE, - .type = AVMEDIA_TYPE_VIDEO, - .name = "xface", - .long_name = NULL_IF_CONFIG_SMALL("X-face image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_SMVJPEG, - .type = AVMEDIA_TYPE_VIDEO, - .name = "smvjpeg", - .long_name = NULL_IF_CONFIG_SMALL("Sigmatel Motion Video"), - }, - - { - .id = AV_CODEC_ID_G2M, - .type = AVMEDIA_TYPE_VIDEO, - .name = "g2m", - .long_name = NULL_IF_CONFIG_SMALL("Go2Meeting"), - .props = AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_HNM4_VIDEO, + .id = AV_CODEC_ID_HNM4_VIDEO, .type = AVMEDIA_TYPE_VIDEO, .name = "hnm4video", .long_name = NULL_IF_CONFIG_SMALL("HNM 4 video"), @@ -1226,6 +1275,20 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Mirillis FIC"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_ALIAS_PIX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "alias_pix", + .long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_BRENDER_PIX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "brender_pix", + .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, { .id = AV_CODEC_ID_PAF_VIDEO, .type = AVMEDIA_TYPE_VIDEO, @@ -1233,6 +1296,14 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_EXR, + .type = AVMEDIA_TYPE_VIDEO, + .name = "exr", + .long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + }, { .id = AV_CODEC_ID_VP7, .type = AVMEDIA_TYPE_VIDEO, @@ -1254,6 +1325,20 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("SGI RLE 8-bit"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, + { + .id = AV_CODEC_ID_MVC1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mvc1", + .long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 1"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MVC2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mvc2", + .long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 2"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_HQX, .type = AVMEDIA_TYPE_VIDEO, @@ -1261,6 +1346,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Canopus HQX"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_TDSC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "tdsc", + .long_name = NULL_IF_CONFIG_SMALL("TDSC"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_HQ_HQA, .type = AVMEDIA_TYPE_VIDEO, @@ -1275,6 +1367,14 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Vidvox Hap"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_DDS, + .type = AVMEDIA_TYPE_VIDEO, + .name = "dds", + .long_name = NULL_IF_CONFIG_SMALL("DirectDraw Surface image decoder"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + }, { .id = AV_CODEC_ID_DXV, .type = AVMEDIA_TYPE_VIDEO, @@ -1289,20 +1389,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Screenpresso"), .props = AV_CODEC_PROP_LOSSLESS, }, - { - .id = AV_CODEC_ID_SPEEDHQ, - .type = AVMEDIA_TYPE_VIDEO, - .name = "speedhq", - .long_name = NULL_IF_CONFIG_SMALL("NewTek SpeedHQ"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_WRAPPED_AVFRAME, - .type = AVMEDIA_TYPE_VIDEO, - .name = "wrapped_avframe", - .long_name = NULL_IF_CONFIG_SMALL("AVFrame to AVPacket passthrough"), - .props = AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_RSCC, .type = AVMEDIA_TYPE_VIDEO, @@ -1311,229 +1397,155 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_MAGICYUV, + .id = AV_CODEC_ID_Y41P, .type = AVMEDIA_TYPE_VIDEO, - .name = "magicyuv", - .long_name = NULL_IF_CONFIG_SMALL("MagicYUV video"), + .name = "y41p", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed YUV 4:1:1 12-bit"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_TRUEMOTION2RT, - .type = AVMEDIA_TYPE_VIDEO, - .name = "truemotion2rt", - .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0 Real Time"), - .props = AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_CFHD, - .type = AVMEDIA_TYPE_VIDEO, - .name = "cfhd", - .long_name = NULL_IF_CONFIG_SMALL("Cineform HD"), - .props = AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_SHEERVIDEO, + .id = AV_CODEC_ID_AVRP, .type = AVMEDIA_TYPE_VIDEO, - .name = "sheervideo", - .long_name = NULL_IF_CONFIG_SMALL("BitJazz SheerVideo"), + .name = "avrp", + .long_name = NULL_IF_CONFIG_SMALL("Avid 1:1 10-bit RGB Packer"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_YLC, + .id = AV_CODEC_ID_012V, .type = AVMEDIA_TYPE_VIDEO, - .name = "ylc", - .long_name = NULL_IF_CONFIG_SMALL("YUY2 Lossless Codec"), + .name = "012v", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PIXLET, - .type = AVMEDIA_TYPE_VIDEO, - .name = "pixlet", - .long_name = NULL_IF_CONFIG_SMALL("Apple Pixlet"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_FMVC, - .type = AVMEDIA_TYPE_VIDEO, - .name = "fmvc", - .long_name = NULL_IF_CONFIG_SMALL("FM Screen Capture Codec"), - .props = AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_SCPR, - .type = AVMEDIA_TYPE_VIDEO, - .name = "scpr", - .long_name = NULL_IF_CONFIG_SMALL("ScreenPressor"), - .props = AV_CODEC_PROP_LOSSLESS | AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_CLEARVIDEO, - .type = AVMEDIA_TYPE_VIDEO, - .name = "clearvideo", - .long_name = NULL_IF_CONFIG_SMALL("Iterated Systems ClearVideo"), - .props = AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_AV1, - .type = AVMEDIA_TYPE_VIDEO, - .name = "av1", - .long_name = NULL_IF_CONFIG_SMALL("Alliance for Open Media AV1"), - .props = AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_BITPACKED, + .id = AV_CODEC_ID_AVUI, .type = AVMEDIA_TYPE_VIDEO, - .name = "bitpacked", - .long_name = NULL_IF_CONFIG_SMALL("Bitpacked"), + .name = "avui", + .long_name = NULL_IF_CONFIG_SMALL("Avid Meridien Uncompressed"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_MSCC, + .id = AV_CODEC_ID_AYUV, .type = AVMEDIA_TYPE_VIDEO, - .name = "mscc", - .long_name = NULL_IF_CONFIG_SMALL("Mandsoft Screen Capture Codec"), + .name = "ayuv", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed MS 4:4:4:4"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_SRGC, + .id = AV_CODEC_ID_TARGA_Y216, .type = AVMEDIA_TYPE_VIDEO, - .name = "srgc", - .long_name = NULL_IF_CONFIG_SMALL("Screen Recorder Gold Codec"), + .name = "targa_y216", + .long_name = NULL_IF_CONFIG_SMALL("Pinnacle TARGA CineWave YUV16"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_GDV, - .type = AVMEDIA_TYPE_VIDEO, - .name = "gdv", - .long_name = NULL_IF_CONFIG_SMALL("Gremlin Digital Video"), - .props = AV_CODEC_PROP_LOSSY, - }, - - /* image codecs */ - { - .id = AV_CODEC_ID_ALIAS_PIX, + .id = AV_CODEC_ID_V308, .type = AVMEDIA_TYPE_VIDEO, - .name = "alias_pix", - .long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"), + .name = "v308", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:4:4"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_ANSI, - .type = AVMEDIA_TYPE_VIDEO, - .name = "ansi", - .long_name = NULL_IF_CONFIG_SMALL("ASCII/ANSI art"), - .props = AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_BRENDER_PIX, + .id = AV_CODEC_ID_V408, .type = AVMEDIA_TYPE_VIDEO, - .name = "brender_pix", - .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"), + .name = "v408", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed QT 4:4:4:4"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_DDS, + .id = AV_CODEC_ID_YUV4, .type = AVMEDIA_TYPE_VIDEO, - .name = "dds", - .long_name = NULL_IF_CONFIG_SMALL("DirectDraw Surface image decoder"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | - AV_CODEC_PROP_LOSSLESS, + .name = "yuv4", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:2:0"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_DPX, + .id = AV_CODEC_ID_AVRN, .type = AVMEDIA_TYPE_VIDEO, - .name = "dpx", - .long_name = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .name = "avrn", + .long_name = NULL_IF_CONFIG_SMALL("Avid AVI Codec"), }, { - .id = AV_CODEC_ID_EXR, + .id = AV_CODEC_ID_CPIA, .type = AVMEDIA_TYPE_VIDEO, - .name = "exr", - .long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | - AV_CODEC_PROP_LOSSLESS, + .name = "cpia", + .long_name = NULL_IF_CONFIG_SMALL("CPiA video format"), }, { - .id = AV_CODEC_ID_FITS, + .id = AV_CODEC_ID_XFACE, .type = AVMEDIA_TYPE_VIDEO, - .name = "fits", - .long_name = NULL_IF_CONFIG_SMALL("FITS (Flexible Image Transport System)"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .name = "xface", + .long_name = NULL_IF_CONFIG_SMALL("X-face image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { - .id = AV_CODEC_ID_GIF, + .id = AV_CODEC_ID_SNOW, .type = AVMEDIA_TYPE_VIDEO, - .name = "gif", - .long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), - .props = AV_CODEC_PROP_LOSSLESS, - .mime_types= MT("image/gif"), + .name = "snow", + .long_name = NULL_IF_CONFIG_SMALL("Snow"), + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_JPEGLS, + .id = AV_CODEC_ID_SMVJPEG, .type = AVMEDIA_TYPE_VIDEO, - .name = "jpegls", - .long_name = NULL_IF_CONFIG_SMALL("JPEG-LS"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | - AV_CODEC_PROP_LOSSLESS, + .name = "smvjpeg", + .long_name = NULL_IF_CONFIG_SMALL("Sigmatel Motion Video"), }, { - .id = AV_CODEC_ID_LJPEG, + .id = AV_CODEC_ID_APNG, .type = AVMEDIA_TYPE_VIDEO, - .name = "ljpeg", - .long_name = NULL_IF_CONFIG_SMALL("Lossless JPEG"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .name = "apng", + .long_name = NULL_IF_CONFIG_SMALL("APNG (Animated Portable Network Graphics) image"), + .props = AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/png"), }, { - .id = AV_CODEC_ID_PAM, + .id = AV_CODEC_ID_DAALA, .type = AVMEDIA_TYPE_VIDEO, - .name = "pam", - .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - .mime_types= MT("image/x-portable-pixmap"), + .name = "daala", + .long_name = NULL_IF_CONFIG_SMALL("Daala"), + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PBM, + .id = AV_CODEC_ID_CFHD, .type = AVMEDIA_TYPE_VIDEO, - .name = "pbm", - .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .name = "cfhd", + .long_name = NULL_IF_CONFIG_SMALL("Cineform HD"), + .props = AV_CODEC_PROP_LOSSY, }, { - .id = AV_CODEC_ID_PCX, + .id = AV_CODEC_ID_TRUEMOTION2RT, .type = AVMEDIA_TYPE_VIDEO, - .name = "pcx", - .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - .mime_types= MT("image/x-pcx"), + .name = "truemotion2rt", + .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0 Real Time"), + .props = AV_CODEC_PROP_LOSSY, }, { - .id = AV_CODEC_ID_PGM, + .id = AV_CODEC_ID_M101, .type = AVMEDIA_TYPE_VIDEO, - .name = "pgm", - .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), + .name = "m101", + .long_name = NULL_IF_CONFIG_SMALL("Matrox Uncompressed SD"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PGMYUV, + .id = AV_CODEC_ID_MAGICYUV, .type = AVMEDIA_TYPE_VIDEO, - .name = "pgmyuv", - .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), + .name = "magicyuv", + .long_name = NULL_IF_CONFIG_SMALL("MagicYUV video"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PNG, + .id = AV_CODEC_ID_SHEERVIDEO, .type = AVMEDIA_TYPE_VIDEO, - .name = "png", - .long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), - .props = AV_CODEC_PROP_LOSSLESS, - .mime_types= MT("image/png"), + .name = "sheervideo", + .long_name = NULL_IF_CONFIG_SMALL("BitJazz SheerVideo"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PPM, + .id = AV_CODEC_ID_YLC, .type = AVMEDIA_TYPE_VIDEO, - .name = "ppm", - .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), + .name = "ylc", + .long_name = NULL_IF_CONFIG_SMALL("YUY2 Lossless Codec"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { @@ -1544,117 +1556,97 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PTX, + .id = AV_CODEC_ID_PIXLET, .type = AVMEDIA_TYPE_VIDEO, - .name = "ptx", - .long_name = NULL_IF_CONFIG_SMALL("V.Flash PTX image"), + .name = "pixlet", + .long_name = NULL_IF_CONFIG_SMALL("Apple Pixlet"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { - .id = AV_CODEC_ID_SGI, - .type = AVMEDIA_TYPE_VIDEO, - .name = "sgi", - .long_name = NULL_IF_CONFIG_SMALL("SGI image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_SP5X, + .id = AV_CODEC_ID_SPEEDHQ, .type = AVMEDIA_TYPE_VIDEO, - .name = "sp5x", - .long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), + .name = "speedhq", + .long_name = NULL_IF_CONFIG_SMALL("NewTek SpeedHQ"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { - .id = AV_CODEC_ID_SUNRAST, + .id = AV_CODEC_ID_FMVC, .type = AVMEDIA_TYPE_VIDEO, - .name = "sunrast", - .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .name = "fmvc", + .long_name = NULL_IF_CONFIG_SMALL("FM Screen Capture Codec"), + .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_TARGA, + .id = AV_CODEC_ID_SCPR, .type = AVMEDIA_TYPE_VIDEO, - .name = "targa", - .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - .mime_types= MT("image/x-targa", "image/x-tga"), + .name = "scpr", + .long_name = NULL_IF_CONFIG_SMALL("ScreenPressor"), + .props = AV_CODEC_PROP_LOSSLESS | AV_CODEC_PROP_LOSSY, }, { - .id = AV_CODEC_ID_TDSC, + .id = AV_CODEC_ID_CLEARVIDEO, .type = AVMEDIA_TYPE_VIDEO, - .name = "tdsc", - .long_name = NULL_IF_CONFIG_SMALL("TDSC"), + .name = "clearvideo", + .long_name = NULL_IF_CONFIG_SMALL("Iterated Systems ClearVideo"), .props = AV_CODEC_PROP_LOSSY, }, { - .id = AV_CODEC_ID_TIFF, + .id = AV_CODEC_ID_XPM, .type = AVMEDIA_TYPE_VIDEO, - .name = "tiff", - .long_name = NULL_IF_CONFIG_SMALL("TIFF image"), + .name = "xpm", + .long_name = NULL_IF_CONFIG_SMALL("XPM (X PixMap) image"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - .mime_types= MT("image/tiff"), - }, - { - .id = AV_CODEC_ID_TXD, - .type = AVMEDIA_TYPE_VIDEO, - .name = "txd", - .long_name = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + .mime_types= MT("image/x-xpixmap"), }, { - .id = AV_CODEC_ID_VC1IMAGE, + .id = AV_CODEC_ID_AV1, .type = AVMEDIA_TYPE_VIDEO, - .name = "vc1image", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image v2"), + .name = "av1", + .long_name = NULL_IF_CONFIG_SMALL("Alliance for Open Media AV1"), .props = AV_CODEC_PROP_LOSSY, }, { - .id = AV_CODEC_ID_WEBP, + .id = AV_CODEC_ID_BITPACKED, .type = AVMEDIA_TYPE_VIDEO, - .name = "webp", - .long_name = NULL_IF_CONFIG_SMALL("WebP"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | - AV_CODEC_PROP_LOSSLESS, - .mime_types= MT("image/webp"), + .name = "bitpacked", + .long_name = NULL_IF_CONFIG_SMALL("Bitpacked"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_WMV3IMAGE, + .id = AV_CODEC_ID_MSCC, .type = AVMEDIA_TYPE_VIDEO, - .name = "wmv3image", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image"), - .props = AV_CODEC_PROP_LOSSY, + .name = "mscc", + .long_name = NULL_IF_CONFIG_SMALL("Mandsoft Screen Capture Codec"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_XBM, + .id = AV_CODEC_ID_SRGC, .type = AVMEDIA_TYPE_VIDEO, - .name = "xbm", - .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"), + .name = "srgc", + .long_name = NULL_IF_CONFIG_SMALL("Screen Recorder Gold Codec"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - .mime_types= MT("image/x-xbitmap"), }, { - .id = AV_CODEC_ID_XPM, + .id = AV_CODEC_ID_SVG, .type = AVMEDIA_TYPE_VIDEO, - .name = "xpm", - .long_name = NULL_IF_CONFIG_SMALL("XPM (X PixMap) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - .mime_types= MT("image/x-xpixmap"), + .name = "svg", + .long_name = NULL_IF_CONFIG_SMALL("Scalable Vector Graphics"), + .props = AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/svg+xml"), }, { - .id = AV_CODEC_ID_XWD, + .id = AV_CODEC_ID_GDV, .type = AVMEDIA_TYPE_VIDEO, - .name = "xwd", - .long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, - .mime_types= MT("image/x-xwindowdump"), + .name = "gdv", + .long_name = NULL_IF_CONFIG_SMALL("Gremlin Digital Video"), + .props = AV_CODEC_PROP_LOSSY, }, { - .id = AV_CODEC_ID_APNG, + .id = AV_CODEC_ID_FITS, .type = AVMEDIA_TYPE_VIDEO, - .name = "apng", - .long_name = NULL_IF_CONFIG_SMALL("APNG (Animated Portable Network Graphics) image"), - .props = AV_CODEC_PROP_LOSSLESS, - .mime_types= MT("image/png"), + .name = "fits", + .long_name = NULL_IF_CONFIG_SMALL("FITS (Flexible Image Transport System)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, /* various PCM "codecs" */ @@ -1728,20 +1720,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("PCM signed 32-bit big-endian"), .props = AV_CODEC_PROP_LOSSLESS, }, - { - .id = AV_CODEC_ID_PCM_S64LE, - .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_s64le", - .long_name = NULL_IF_CONFIG_SMALL("PCM signed 64-bit little-endian"), - .props = AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_PCM_S64BE, - .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_s64be", - .long_name = NULL_IF_CONFIG_SMALL("PCM signed 64-bit big-endian"), - .props = AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_PCM_U32LE, .type = AVMEDIA_TYPE_AUDIO, @@ -1799,108 +1777,122 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_LOSSY, }, { - .id = AV_CODEC_ID_PCM_S16BE_PLANAR, + .id = AV_CODEC_ID_PCM_S16LE_PLANAR, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_s16be_planar", - .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit big-endian planar"), + .name = "pcm_s16le_planar", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit little-endian planar"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PCM_S16LE_PLANAR, + .id = AV_CODEC_ID_PCM_DVD, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_s16le_planar", - .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit little-endian planar"), + .name = "pcm_dvd", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 20|24-bit big-endian"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PCM_S24LE_PLANAR, + .id = AV_CODEC_ID_PCM_F32BE, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_s24le_planar", - .long_name = NULL_IF_CONFIG_SMALL("PCM signed 24-bit little-endian planar"), + .name = "pcm_f32be", + .long_name = NULL_IF_CONFIG_SMALL("PCM 32-bit floating point big-endian"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PCM_S32LE_PLANAR, + .id = AV_CODEC_ID_PCM_F32LE, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_s32le_planar", - .long_name = NULL_IF_CONFIG_SMALL("PCM signed 32-bit little-endian planar"), + .name = "pcm_f32le", + .long_name = NULL_IF_CONFIG_SMALL("PCM 32-bit floating point little-endian"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PCM_DVD, + .id = AV_CODEC_ID_PCM_F64BE, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_dvd", - .long_name = NULL_IF_CONFIG_SMALL("PCM signed 20|24-bit big-endian"), + .name = "pcm_f64be", + .long_name = NULL_IF_CONFIG_SMALL("PCM 64-bit floating point big-endian"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PCM_F16LE, + .id = AV_CODEC_ID_PCM_F64LE, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_f16le", - .long_name = NULL_IF_CONFIG_SMALL("PCM 16.8 floating point little-endian"), + .name = "pcm_f64le", + .long_name = NULL_IF_CONFIG_SMALL("PCM 64-bit floating point little-endian"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PCM_F24LE, + .id = AV_CODEC_ID_PCM_BLURAY, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_f24le", - .long_name = NULL_IF_CONFIG_SMALL("PCM 24.0 floating point little-endian"), + .name = "pcm_bluray", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PCM_F32BE, + .id = AV_CODEC_ID_PCM_LXF, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_f32be", - .long_name = NULL_IF_CONFIG_SMALL("PCM 32-bit floating point big-endian"), + .name = "pcm_lxf", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 20-bit little-endian planar"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PCM_F32LE, + .id = AV_CODEC_ID_S302M, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_f32le", - .long_name = NULL_IF_CONFIG_SMALL("PCM 32-bit floating point little-endian"), + .name = "s302m", + .long_name = NULL_IF_CONFIG_SMALL("SMPTE 302M"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PCM_F64BE, + .id = AV_CODEC_ID_PCM_S8_PLANAR, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s8_planar", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 8-bit planar"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_S24LE_PLANAR, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s24le_planar", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 24-bit little-endian planar"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_S32LE_PLANAR, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_f64be", - .long_name = NULL_IF_CONFIG_SMALL("PCM 64-bit floating point big-endian"), + .name = "pcm_s32le_planar", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 32-bit little-endian planar"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PCM_F64LE, + .id = AV_CODEC_ID_PCM_S16BE_PLANAR, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_f64le", - .long_name = NULL_IF_CONFIG_SMALL("PCM 64-bit floating point little-endian"), + .name = "pcm_s16be_planar", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit big-endian planar"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PCM_BLURAY, + .id = AV_CODEC_ID_PCM_S64LE, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_bluray", - .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"), + .name = "pcm_s64le", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 64-bit little-endian"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PCM_LXF, + .id = AV_CODEC_ID_PCM_S64BE, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_lxf", - .long_name = NULL_IF_CONFIG_SMALL("PCM signed 20-bit little-endian planar"), + .name = "pcm_s64be", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 64-bit big-endian"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_S302M, + .id = AV_CODEC_ID_PCM_F16LE, .type = AVMEDIA_TYPE_AUDIO, - .name = "s302m", - .long_name = NULL_IF_CONFIG_SMALL("SMPTE 302M"), + .name = "pcm_f16le", + .long_name = NULL_IF_CONFIG_SMALL("PCM 16.8 floating point little-endian"), .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_PCM_S8_PLANAR, + .id = AV_CODEC_ID_PCM_F24LE, .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_s8_planar", - .long_name = NULL_IF_CONFIG_SMALL("PCM signed 8-bit planar"), + .name = "pcm_f24le", + .long_name = NULL_IF_CONFIG_SMALL("PCM 24.0 floating point little-endian"), .props = AV_CODEC_PROP_LOSSLESS, }, @@ -2038,13 +2030,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("ADPCM Nintendo THP"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_ADPCM_THP_LE, - .type = AVMEDIA_TYPE_AUDIO, - .name = "adpcm_thp_le", - .long_name = NULL_IF_CONFIG_SMALL("ADPCM Nintendo THP (Little-Endian)"), - .props = AV_CODEC_PROP_LOSSY, - }, { .id = AV_CODEC_ID_ADPCM_IMA_AMV, .type = AVMEDIA_TYPE_AUDIO, @@ -2122,6 +2107,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA CRYO APC"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_ADPCM_VIMA, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_vima", + .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_ADPCM_AFC, .type = AVMEDIA_TYPE_AUDIO, @@ -2158,10 +2150,10 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_LOSSY, }, { - .id = AV_CODEC_ID_ADPCM_VIMA, + .id = AV_CODEC_ID_ADPCM_THP_LE, .type = AVMEDIA_TYPE_AUDIO, - .name = "adpcm_vima", - .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"), + .name = "adpcm_thp_le", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Nintendo THP (Little-Endian)"), .props = AV_CODEC_PROP_LOSSY, }, { @@ -2185,6 +2177,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Eurocom DAT4"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_ADPCM_MTAF, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_mtaf", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM MTAF"), + .props = AV_CODEC_PROP_LOSSY, + }, /* AMR */ { @@ -2546,20 +2545,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ (Adaptive TRansform Acoustic Coding 3+)"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_ATRAC3PAL, - .type = AVMEDIA_TYPE_AUDIO, - .name = "atrac3pal", - .long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ AL (Adaptive TRansform Acoustic Coding 3+ Advanced Lossless)"), - .props = AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_ATRAC3AL, - .type = AVMEDIA_TYPE_AUDIO, - .name = "atrac3al", - .long_name = NULL_IF_CONFIG_SMALL("ATRAC3 AL (Adaptive TRansform Acoustic Coding 3 Advanced Lossless)"), - .props = AV_CODEC_PROP_LOSSLESS, - }, { .id = AV_CODEC_ID_EAC3, .type = AVMEDIA_TYPE_AUDIO, @@ -2652,20 +2637,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("G.723.1"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_DSS_SP, - .type = AVMEDIA_TYPE_AUDIO, - .name = "dss_sp", - .long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard - Standard Play mode (DSS SP)"), - .props = AV_CODEC_PROP_LOSSY, - }, - { - .id = AV_CODEC_ID_DOLBY_E, - .type = AVMEDIA_TYPE_AUDIO, - .name = "dolby_e", - .long_name = NULL_IF_CONFIG_SMALL("Dolby E"), - .props = AV_CODEC_PROP_LOSSY, - }, { .id = AV_CODEC_ID_G729, .type = AVMEDIA_TYPE_AUDIO, @@ -2715,24 +2686,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_FFWAVESYNTH, - .type = AVMEDIA_TYPE_AUDIO, - .name = "wavesynth", - .long_name = NULL_IF_CONFIG_SMALL("Wave synthesis pseudo-codec"), - }, - { - .id = AV_CODEC_ID_SONIC, - .type = AVMEDIA_TYPE_AUDIO, - .name = "sonic", - .long_name = NULL_IF_CONFIG_SMALL("Sonic"), - }, - { - .id = AV_CODEC_ID_SONIC_LS, - .type = AVMEDIA_TYPE_AUDIO, - .name = "sonicls", - .long_name = NULL_IF_CONFIG_SMALL("Sonic lossless"), - }, { .id = AV_CODEC_ID_OPUS, .type = AVMEDIA_TYPE_AUDIO, @@ -2775,6 +2728,31 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("On2 Audio for Video Codec"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_DSS_SP, + .type = AVMEDIA_TYPE_AUDIO, + .name = "dss_sp", + .long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard - Standard Play mode (DSS SP)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_FFWAVESYNTH, + .type = AVMEDIA_TYPE_AUDIO, + .name = "wavesynth", + .long_name = NULL_IF_CONFIG_SMALL("Wave synthesis pseudo-codec"), + }, + { + .id = AV_CODEC_ID_SONIC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "sonic", + .long_name = NULL_IF_CONFIG_SMALL("Sonic"), + }, + { + .id = AV_CODEC_ID_SONIC_LS, + .type = AVMEDIA_TYPE_AUDIO, + .name = "sonicls", + .long_name = NULL_IF_CONFIG_SMALL("Sonic lossless"), + }, { .id = AV_CODEC_ID_EVRC, .type = AVMEDIA_TYPE_AUDIO, @@ -2789,13 +2767,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("SMV (Selectable Mode Vocoder)"), .props = AV_CODEC_PROP_LOSSY, }, - { - .id = AV_CODEC_ID_4GV, - .type = AVMEDIA_TYPE_AUDIO, - .name = "4gv", - .long_name = NULL_IF_CONFIG_SMALL("4GV (Fourth Generation Vocoder)"), - .props = AV_CODEC_PROP_LOSSY, - }, { .id = AV_CODEC_ID_DSD_LSBF, .type = AVMEDIA_TYPE_AUDIO, @@ -2824,6 +2795,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("DSD (Direct Stream Digital), most significant bit first, planar"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_4GV, + .type = AVMEDIA_TYPE_AUDIO, + .name = "4gv", + .long_name = NULL_IF_CONFIG_SMALL("4GV (Fourth Generation Vocoder)"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_INTERPLAY_ACM, .type = AVMEDIA_TYPE_AUDIO, @@ -2853,10 +2831,24 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_LOSSLESS, }, { - .id = AV_CODEC_ID_ADPCM_MTAF, + .id = AV_CODEC_ID_ATRAC3AL, .type = AVMEDIA_TYPE_AUDIO, - .name = "adpcm_mtaf", - .long_name = NULL_IF_CONFIG_SMALL("ADPCM MTAF"), + .name = "atrac3al", + .long_name = NULL_IF_CONFIG_SMALL("ATRAC3 AL (Adaptive TRansform Acoustic Coding 3 Advanced Lossless)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_ATRAC3PAL, + .type = AVMEDIA_TYPE_AUDIO, + .name = "atrac3pal", + .long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ AL (Adaptive TRansform Acoustic Coding 3+ Advanced Lossless)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_DOLBY_E, + .type = AVMEDIA_TYPE_AUDIO, + .name = "dolby_e", + .long_name = NULL_IF_CONFIG_SMALL("Dolby E"), .props = AV_CODEC_PROP_LOSSY, }, { @@ -2896,13 +2888,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("XSUB"), .props = AV_CODEC_PROP_BITMAP_SUB, }, - { - .id = AV_CODEC_ID_ASS, - .type = AVMEDIA_TYPE_SUBTITLE, - .name = "ass", - .long_name = NULL_IF_CONFIG_SMALL("ASS (Advanced SSA) subtitle"), - .props = AV_CODEC_PROP_TEXT_SUB, - }, { .id = AV_CODEC_ID_SSA, .type = AVMEDIA_TYPE_SUBTITLE, @@ -2937,13 +2922,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle with embedded timing"), .props = AV_CODEC_PROP_TEXT_SUB, }, - { - .id = AV_CODEC_ID_SUBRIP, - .type = AVMEDIA_TYPE_SUBTITLE, - .name = "subrip", - .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), - .props = AV_CODEC_PROP_TEXT_SUB, - }, { .id = AV_CODEC_ID_MICRODVD, .type = AVMEDIA_TYPE_SUBTITLE, @@ -2951,13 +2929,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("MicroDVD subtitle"), .props = AV_CODEC_PROP_TEXT_SUB, }, - { - .id = AV_CODEC_ID_MPL2, - .type = AVMEDIA_TYPE_SUBTITLE, - .name = "mpl2", - .long_name = NULL_IF_CONFIG_SMALL("MPL2 subtitle"), - .props = AV_CODEC_PROP_TEXT_SUB, - }, { .id = AV_CODEC_ID_EIA_608, .type = AVMEDIA_TYPE_SUBTITLE, @@ -2972,13 +2943,6 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("JACOsub subtitle"), .props = AV_CODEC_PROP_TEXT_SUB, }, - { - .id = AV_CODEC_ID_PJS, - .type = AVMEDIA_TYPE_SUBTITLE, - .name = "pjs", - .long_name = NULL_IF_CONFIG_SMALL("PJS (Phoenix Japanimation Society) subtitle"), - .props = AV_CODEC_PROP_TEXT_SUB, - }, { .id = AV_CODEC_ID_SAMI, .type = AVMEDIA_TYPE_SUBTITLE, @@ -3015,10 +2979,10 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_TEXT_SUB, }, { - .id = AV_CODEC_ID_VPLAYER, + .id = AV_CODEC_ID_SUBRIP, .type = AVMEDIA_TYPE_SUBTITLE, - .name = "vplayer", - .long_name = NULL_IF_CONFIG_SMALL("VPlayer subtitle"), + .name = "subrip", + .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), .props = AV_CODEC_PROP_TEXT_SUB, }, { @@ -3028,6 +2992,34 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), .props = AV_CODEC_PROP_TEXT_SUB, }, + { + .id = AV_CODEC_ID_MPL2, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "mpl2", + .long_name = NULL_IF_CONFIG_SMALL("MPL2 subtitle"), + .props = AV_CODEC_PROP_TEXT_SUB, + }, + { + .id = AV_CODEC_ID_VPLAYER, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "vplayer", + .long_name = NULL_IF_CONFIG_SMALL("VPlayer subtitle"), + .props = AV_CODEC_PROP_TEXT_SUB, + }, + { + .id = AV_CODEC_ID_PJS, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "pjs", + .long_name = NULL_IF_CONFIG_SMALL("PJS (Phoenix Japanimation Society) subtitle"), + .props = AV_CODEC_PROP_TEXT_SUB, + }, + { + .id = AV_CODEC_ID_ASS, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "ass", + .long_name = NULL_IF_CONFIG_SMALL("ASS (Advanced SSA) subtitle"), + .props = AV_CODEC_PROP_TEXT_SUB, + }, { .id = AV_CODEC_ID_HDMV_TEXT_SUBTITLE, .type = AVMEDIA_TYPE_SUBTITLE, @@ -3044,6 +3036,12 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("TrueType font"), .mime_types= MT("application/x-truetype-font", "application/x-font"), }, + { + .id = AV_CODEC_ID_SCTE_35, + .type = AVMEDIA_TYPE_DATA, + .name = "scte_35", + .long_name = NULL_IF_CONFIG_SMALL("SCTE 35 Message Queue"), + }, { .id = AV_CODEC_ID_BINTEXT, .type = AVMEDIA_TYPE_VIDEO, @@ -3098,23 +3096,48 @@ static const AVCodecDescriptor codec_descriptors[] = { .mime_types= MT("application/octet-stream"), }, { - .id = AV_CODEC_ID_SCTE_35, - .type = AVMEDIA_TYPE_DATA, - .name = "scte_35", - .long_name = NULL_IF_CONFIG_SMALL("SCTE 35 Message Queue"), + .id = AV_CODEC_ID_WRAPPED_AVFRAME, + .type = AVMEDIA_TYPE_VIDEO, + .name = "wrapped_avframe", + .long_name = NULL_IF_CONFIG_SMALL("AVFrame to AVPacket passthrough"), + .props = AV_CODEC_PROP_LOSSLESS, }, - - /* deprecated codec ids */ }; -const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id) +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 +static void check_validity(void) { int i; - for (i = 0; i < FF_ARRAY_ELEMS(codec_descriptors); i++) - if (codec_descriptors[i].id == id) - return &codec_descriptors[i]; - return NULL; + for (i = 0; i < FF_ARRAY_ELEMS(codec_descriptors) - 1; i++) { + if (codec_descriptors[i].id >= codec_descriptors[i+1].id) { + av_log(NULL, AV_LOG_FATAL, "unsorted codec_id '%s' and '%s'.\n", + codec_descriptors[i].name, codec_descriptors[i+1].name); + av_assert0(0); + } + } +} + +static AVOnce check_validity_once = AV_ONCE_INIT; +#define CHECK_VALIDITY() ff_thread_once(&check_validity_once, check_validity); +#else +#define CHECK_VALIDITY() ((void)0) +#endif + +static int descriptor_compare(const void *key, const void *member) +{ + enum AVCodecID id = *(const enum AVCodecID *) key; + const AVCodecDescriptor *desc = member; + + return id - desc->id; +} + +const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id) +{ + CHECK_VALIDITY(); + + return bsearch(&id, codec_descriptors, FF_ARRAY_ELEMS(codec_descriptors), + sizeof(codec_descriptors[0]), descriptor_compare); } const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev) From 81d6501be77b273053a66eeced94d78e2021f1d1 Mon Sep 17 00:00:00 2001 From: Muhammad Faiz Date: Fri, 9 Feb 2018 17:50:44 +0700 Subject: [PATCH 1828/2557] checkasm/Makefile: add EXTRALIBS-swresample Should fix https://ffmpeg.org/pipermail/ffmpeg-devel/2018-February/225058.html Signed-off-by: Muhammad Faiz --- tests/checkasm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index afbd09b940aac..77bdcf6e65602 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -61,7 +61,7 @@ tests/checkasm/checkasm.o: CFLAGS += -Umain CHECKASM := tests/checkasm/checkasm$(EXESUF) $(CHECKASM): $(CHECKASMOBJS) $(FF_STATIC_DEP_LIBS) - $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(CHECKASMOBJS) $(FF_STATIC_DEP_LIBS) $(EXTRALIBS-avcodec) $(EXTRALIBS-avfilter) $(EXTRALIBS-avutil) $(EXTRALIBS) + $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(CHECKASMOBJS) $(FF_STATIC_DEP_LIBS) $(EXTRALIBS-avcodec) $(EXTRALIBS-avfilter) $(EXTRALIBS-avutil) $(EXTRALIBS-swresample) $(EXTRALIBS) checkasm: $(CHECKASM) From b7915f8a149aaa3cdd72a5f126a30bf2e0bf1738 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sat, 6 Jan 2018 00:23:43 +0100 Subject: [PATCH 1829/2557] aptx: simplify by pre-calculating factor_max --- libavcodec/aptx.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libavcodec/aptx.c b/libavcodec/aptx.c index a35d2861c175d..7b9556ce42f16 100644 --- a/libavcodec/aptx.c +++ b/libavcodec/aptx.c @@ -188,7 +188,7 @@ typedef const struct { const int32_t *quantize_dither_factors; const int16_t *quantize_factor_select_offset; int tables_size; - int32_t quantized_bits; + int32_t factor_max; int32_t prediction_order; } ConstTables; @@ -198,25 +198,25 @@ static ConstTables tables[NB_SUBBANDS] = { quantize_dither_factors_LF, quantize_factor_select_offset_LF, FF_ARRAY_ELEMS(quantize_intervals_LF), - 7, 24 }, + 0x11FF, 24 }, [MLF] = { quantize_intervals_MLF, invert_quantize_dither_factors_MLF, quantize_dither_factors_MLF, quantize_factor_select_offset_MLF, FF_ARRAY_ELEMS(quantize_intervals_MLF), - 4, 12 }, + 0x14FF, 12 }, [MHF] = { quantize_intervals_MHF, invert_quantize_dither_factors_MHF, quantize_dither_factors_MHF, quantize_factor_select_offset_MHF, FF_ARRAY_ELEMS(quantize_intervals_MHF), - 2, 6 }, + 0x16FF, 6 }, [HF] = { quantize_intervals_HF, invert_quantize_dither_factors_HF, quantize_dither_factors_HF, quantize_factor_select_offset_HF, FF_ARRAY_ELEMS(quantize_intervals_HF), - 3, 12 }, + 0x15FF, 12 }, }; static const int16_t quantization_factors[32] = { @@ -530,16 +530,14 @@ static void aptx_invert_quantization(InvertQuantize *invert_quantize, qr = rshift64_clip24(((int64_t)qr<<32) + MUL64(dither, tables->invert_quantize_dither_factors[idx]), 32); invert_quantize->reconstructed_difference = MUL64(invert_quantize->quantization_factor, qr) >> 19; - shift = 24 - tables->quantized_bits; - /* update factor_select */ factor_select = 32620 * invert_quantize->factor_select; factor_select = rshift32(factor_select + (tables->quantize_factor_select_offset[idx] << 15), 15); - invert_quantize->factor_select = av_clip(factor_select, 0, (shift << 8) | 0xFF); + invert_quantize->factor_select = av_clip(factor_select, 0, tables->factor_max); /* update quantization factor */ idx = (invert_quantize->factor_select & 0xFF) >> 3; - shift -= invert_quantize->factor_select >> 8; + shift = (tables->factor_max - invert_quantize->factor_select) >> 8; invert_quantize->quantization_factor = (quantization_factors[idx] << 11) >> shift; } From fea8e119a2bc103b64faba6b5e1f3defe0c344c2 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sat, 6 Jan 2018 01:22:31 +0100 Subject: [PATCH 1830/2557] aptx: factorize FFABS calculation --- libavcodec/aptx.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavcodec/aptx.c b/libavcodec/aptx.c index 7b9556ce42f16..64a63a7d5b668 100644 --- a/libavcodec/aptx.c +++ b/libavcodec/aptx.c @@ -462,10 +462,12 @@ static void aptx_quantize_difference(Quantize *quantize, { const int32_t *intervals = tables->quantize_intervals; int32_t quantized_sample, dithered_sample, parity_change; - int32_t d, mean, interval, inv; + int32_t d, mean, interval, inv, sample_difference_abs; int64_t error; - quantized_sample = aptx_bin_search(FFABS(sample_difference) >> 4, + sample_difference_abs = FFABS(sample_difference); + + quantized_sample = aptx_bin_search(sample_difference_abs >> 4, quantization_factor, intervals, tables->tables_size); @@ -477,7 +479,7 @@ static void aptx_quantize_difference(Quantize *quantize, interval = (intervals[1] - intervals[0]) * (-(sample_difference < 0) | 1); dithered_sample = rshift64_clip24(MUL64(dither, interval) + ((int64_t)(mean + d) << 32), 32); - error = ((int64_t)FFABS(sample_difference) << 20) - MUL64(dithered_sample, quantization_factor); + error = ((int64_t)sample_difference_abs << 20) - MUL64(dithered_sample, quantization_factor); quantize->error = FFABS(rshift64(error, 23)); parity_change = quantized_sample; From 96b217f5e878fabc142fc198b1e297b624f5c17e Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sat, 6 Jan 2018 01:31:02 +0100 Subject: [PATCH 1831/2557] aptx: do some clipping to match original codec in extreme cases --- libavcodec/aptx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/aptx.c b/libavcodec/aptx.c index 64a63a7d5b668..4173402d0312b 100644 --- a/libavcodec/aptx.c +++ b/libavcodec/aptx.c @@ -466,6 +466,7 @@ static void aptx_quantize_difference(Quantize *quantize, int64_t error; sample_difference_abs = FFABS(sample_difference); + sample_difference_abs = FFMIN(sample_difference_abs, (1 << 23) - 1); quantized_sample = aptx_bin_search(sample_difference_abs >> 4, quantization_factor, @@ -478,7 +479,7 @@ static void aptx_quantize_difference(Quantize *quantize, mean = (intervals[1] + intervals[0]) / 2; interval = (intervals[1] - intervals[0]) * (-(sample_difference < 0) | 1); - dithered_sample = rshift64_clip24(MUL64(dither, interval) + ((int64_t)(mean + d) << 32), 32); + dithered_sample = rshift64_clip24(MUL64(dither, interval) + ((int64_t)av_clip_intp2(mean + d, 23) << 32), 32); error = ((int64_t)sample_difference_abs << 20) - MUL64(dithered_sample, quantization_factor); quantize->error = FFABS(rshift64(error, 23)); From 6fd110a0940f9177d33db4e98b2a66742cc29988 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sat, 6 Jan 2018 17:11:48 +0100 Subject: [PATCH 1832/2557] aptx: implement the aptX HD bluetooth codec --- Changelog | 2 +- configure | 2 + doc/general.texi | 2 + libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 2 + libavcodec/aptx.c | 352 +++++++++++++++++++++++++++++++++++++--- libavcodec/avcodec.h | 1 + libavcodec/codec_desc.c | 7 + 8 files changed, 342 insertions(+), 28 deletions(-) diff --git a/Changelog b/Changelog index 7a73447a6b5fd..e23fdd6ff8054 100644 --- a/Changelog +++ b/Changelog @@ -11,7 +11,7 @@ version : - TiVo ty/ty+ demuxer - Intel QSV-accelerated MJPEG encoding - PCE support for extended channel layouts in the AAC encoder -- native aptX encoder and decoder +- native aptX and aptX HD encoder and decoder - Raw aptX muxer and demuxer - NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-1/2/4, VC1, VP8/9 hwaccel decoding - Intel QSV-accelerated overlay filter diff --git a/configure b/configure index 8d713f1bc0035..fee7d97cc358c 100755 --- a/configure +++ b/configure @@ -2461,6 +2461,8 @@ apng_encoder_deps="zlib" apng_encoder_select="llvidencdsp" aptx_decoder_select="audio_frame_queue" aptx_encoder_select="audio_frame_queue" +aptx_hd_decoder_select="audio_frame_queue" +aptx_hd_encoder_select="audio_frame_queue" asv1_decoder_select="blockdsp bswapdsp idctdsp" asv1_encoder_select="bswapdsp fdctdsp pixblockdsp" asv2_decoder_select="blockdsp bswapdsp idctdsp" diff --git a/doc/general.texi b/doc/general.texi index 3b73e31310d1a..352110f42c5ce 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -1009,6 +1009,8 @@ following image formats are supported: @tab QuickTime fourcc 'alac' @item aptX @tab X @tab X @tab Used in Bluetooth A2DP +@item aptX HD @tab X @tab X + @tab Used in Bluetooth A2DP @item ATRAC1 @tab @tab X @item ATRAC3 @tab @tab X @item ATRAC3+ @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 68777d91f23c6..beaca9ee51b08 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -190,6 +190,8 @@ OBJS-$(CONFIG_ANSI_DECODER) += ansi.o cga_data.o OBJS-$(CONFIG_APE_DECODER) += apedec.o OBJS-$(CONFIG_APTX_DECODER) += aptx.o OBJS-$(CONFIG_APTX_ENCODER) += aptx.o +OBJS-$(CONFIG_APTX_HD_DECODER) += aptx.o +OBJS-$(CONFIG_APTX_HD_ENCODER) += aptx.o OBJS-$(CONFIG_APNG_DECODER) += png.o pngdec.o pngdsp.o OBJS-$(CONFIG_APNG_ENCODER) += png.o pngenc.o OBJS-$(CONFIG_SSA_DECODER) += assdec.o ass.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 268df243f7a4a..774b78ef097d6 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -386,6 +386,8 @@ extern AVCodec ff_amrwb_decoder; extern AVCodec ff_ape_decoder; extern AVCodec ff_aptx_encoder; extern AVCodec ff_aptx_decoder; +extern AVCodec ff_aptx_hd_encoder; +extern AVCodec ff_aptx_hd_decoder; extern AVCodec ff_atrac1_decoder; extern AVCodec ff_atrac3_decoder; extern AVCodec ff_atrac3al_decoder; diff --git a/libavcodec/aptx.c b/libavcodec/aptx.c index 4173402d0312b..6c0f3d35a9c89 100644 --- a/libavcodec/aptx.c +++ b/libavcodec/aptx.c @@ -89,6 +89,8 @@ typedef struct { } Channel; typedef struct { + int hd; + int block_size; int32_t sync_idx; Channel channels[NB_CHANNELS]; AudioFrameQueue afq; @@ -182,6 +184,205 @@ static const int16_t quantize_factor_select_offset_HF[5] = { 0, -8, 33, 95, 262, }; + +static const int32_t hd_quantize_intervals_LF[257] = { + -2436, 2436, 7308, 12180, 17054, 21930, 26806, 31686, + 36566, 41450, 46338, 51230, 56124, 61024, 65928, 70836, + 75750, 80670, 85598, 90530, 95470, 100418, 105372, 110336, + 115308, 120288, 125278, 130276, 135286, 140304, 145334, 150374, + 155426, 160490, 165566, 170654, 175756, 180870, 185998, 191138, + 196294, 201466, 206650, 211850, 217068, 222300, 227548, 232814, + 238096, 243396, 248714, 254050, 259406, 264778, 270172, 275584, + 281018, 286470, 291944, 297440, 302956, 308496, 314056, 319640, + 325248, 330878, 336532, 342212, 347916, 353644, 359398, 365178, + 370986, 376820, 382680, 388568, 394486, 400430, 406404, 412408, + 418442, 424506, 430600, 436726, 442884, 449074, 455298, 461554, + 467844, 474168, 480528, 486922, 493354, 499820, 506324, 512866, + 519446, 526064, 532722, 539420, 546160, 552940, 559760, 566624, + 573532, 580482, 587478, 594520, 601606, 608740, 615920, 623148, + 630426, 637754, 645132, 652560, 660042, 667576, 675164, 682808, + 690506, 698262, 706074, 713946, 721876, 729868, 737920, 746036, + 754216, 762460, 770770, 779148, 787594, 796108, 804694, 813354, + 822086, 830892, 839774, 848736, 857776, 866896, 876100, 885386, + 894758, 904218, 913766, 923406, 933138, 942964, 952886, 962908, + 973030, 983254, 993582, 1004020, 1014566, 1025224, 1035996, 1046886, + 1057894, 1069026, 1080284, 1091670, 1103186, 1114838, 1126628, 1138558, + 1150634, 1162858, 1175236, 1187768, 1200462, 1213320, 1226346, 1239548, + 1252928, 1266490, 1280242, 1294188, 1308334, 1322688, 1337252, 1352034, + 1367044, 1382284, 1397766, 1413494, 1429478, 1445728, 1462252, 1479058, + 1496158, 1513562, 1531280, 1549326, 1567710, 1586446, 1605550, 1625034, + 1644914, 1665208, 1685932, 1707108, 1728754, 1750890, 1773542, 1796732, + 1820488, 1844840, 1869816, 1895452, 1921780, 1948842, 1976680, 2005338, + 2034868, 2065322, 2096766, 2129260, 2162880, 2197708, 2233832, 2271352, + 2310384, 2351050, 2393498, 2437886, 2484404, 2533262, 2584710, 2639036, + 2696578, 2757738, 2822998, 2892940, 2968278, 3049896, 3138912, 3236760, + 3345312, 3467068, 3605434, 3765154, 3952904, 4177962, 4452178, 4787134, + 5187290, 5647128, 6159120, 6720518, 7332904, 8000032, 8726664, 9518152, + 10380372, +}; +static const int32_t hd_invert_quantize_dither_factors_LF[257] = { + 2436, 2436, 2436, 2436, 2438, 2438, 2438, 2440, + 2442, 2442, 2444, 2446, 2448, 2450, 2454, 2456, + 2458, 2462, 2464, 2468, 2472, 2476, 2480, 2484, + 2488, 2492, 2498, 2502, 2506, 2512, 2518, 2524, + 2528, 2534, 2540, 2548, 2554, 2560, 2568, 2574, + 2582, 2588, 2596, 2604, 2612, 2620, 2628, 2636, + 2646, 2654, 2664, 2672, 2682, 2692, 2702, 2712, + 2722, 2732, 2742, 2752, 2764, 2774, 2786, 2798, + 2810, 2822, 2834, 2846, 2858, 2870, 2884, 2896, + 2910, 2924, 2938, 2952, 2966, 2980, 2994, 3010, + 3024, 3040, 3056, 3070, 3086, 3104, 3120, 3136, + 3154, 3170, 3188, 3206, 3224, 3242, 3262, 3280, + 3300, 3320, 3338, 3360, 3380, 3400, 3422, 3442, + 3464, 3486, 3508, 3532, 3554, 3578, 3602, 3626, + 3652, 3676, 3702, 3728, 3754, 3780, 3808, 3836, + 3864, 3892, 3920, 3950, 3980, 4010, 4042, 4074, + 4106, 4138, 4172, 4206, 4240, 4276, 4312, 4348, + 4384, 4422, 4460, 4500, 4540, 4580, 4622, 4664, + 4708, 4752, 4796, 4842, 4890, 4938, 4986, 5036, + 5086, 5138, 5192, 5246, 5300, 5358, 5416, 5474, + 5534, 5596, 5660, 5726, 5792, 5860, 5930, 6002, + 6074, 6150, 6226, 6306, 6388, 6470, 6556, 6644, + 6736, 6828, 6924, 7022, 7124, 7228, 7336, 7448, + 7562, 7680, 7802, 7928, 8058, 8192, 8332, 8476, + 8624, 8780, 8940, 9106, 9278, 9458, 9644, 9840, + 10042, 10252, 10472, 10702, 10942, 11194, 11458, 11734, + 12024, 12328, 12648, 12986, 13342, 13720, 14118, 14540, + 14990, 15466, 15976, 16520, 17102, 17726, 18398, 19124, + 19908, 20760, 21688, 22702, 23816, 25044, 26404, 27922, + 29622, 31540, 33720, 36222, 39116, 42502, 46514, 51334, + 57218, 64536, 73830, 85890, 101860, 123198, 151020, 183936, + 216220, 243618, 268374, 293022, 319362, 347768, 378864, 412626, 449596, +}; +static const int32_t hd_quantize_dither_factors_LF[256] = { + 0, 0, 0, 1, 0, 0, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 2, 2, 2, 1, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 3, + 2, 3, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 4, 3, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 5, 4, 4, 5, + 4, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 6, 5, 5, 6, 5, 6, + 6, 6, 6, 6, 6, 6, 6, 7, + 6, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 8, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 11, 11, 11, + 11, 11, 12, 12, 12, 12, 13, 13, + 13, 14, 14, 14, 15, 15, 15, 15, + 16, 16, 17, 17, 17, 18, 18, 18, + 19, 19, 20, 21, 21, 22, 22, 23, + 23, 24, 25, 26, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, + 39, 40, 42, 43, 45, 47, 49, 51, + 53, 55, 58, 60, 63, 66, 69, 73, + 76, 80, 85, 89, 95, 100, 106, 113, + 119, 128, 136, 146, 156, 168, 182, 196, + 213, 232, 254, 279, 307, 340, 380, 425, + 480, 545, 626, 724, 847, 1003, 1205, 1471, + 1830, 2324, 3015, 3993, 5335, 6956, 8229, 8071, + 6850, 6189, 6162, 6585, 7102, 7774, 8441, 9243, +}; +static const int16_t hd_quantize_factor_select_offset_LF[257] = { + 0, -22, -21, -21, -20, -20, -19, -19, + -18, -18, -17, -17, -16, -16, -15, -14, + -14, -13, -13, -12, -12, -11, -11, -10, + -10, -9, -9, -8, -7, -7, -6, -6, + -5, -5, -4, -4, -3, -3, -2, -1, + -1, 0, 0, 1, 1, 2, 2, 3, + 4, 4, 5, 5, 6, 6, 7, 8, + 8, 9, 9, 10, 11, 11, 12, 12, + 13, 14, 14, 15, 15, 16, 17, 17, + 18, 19, 19, 20, 20, 21, 22, 22, + 23, 24, 24, 25, 26, 26, 27, 28, + 28, 29, 30, 30, 31, 32, 33, 33, + 34, 35, 35, 36, 37, 38, 38, 39, + 40, 41, 41, 42, 43, 44, 44, 45, + 46, 47, 48, 48, 49, 50, 51, 52, + 52, 53, 54, 55, 56, 57, 58, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 69, 70, 71, 72, 73, + 74, 75, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 89, 90, 91, + 92, 93, 94, 96, 97, 98, 99, 101, + 102, 103, 105, 106, 107, 109, 110, 112, + 113, 115, 116, 118, 119, 121, 122, 124, + 125, 127, 129, 130, 132, 134, 136, 137, + 139, 141, 143, 145, 147, 149, 151, 153, + 155, 158, 160, 162, 164, 167, 169, 172, + 174, 177, 180, 182, 185, 188, 191, 194, + 197, 201, 204, 208, 211, 215, 219, 223, + 227, 232, 236, 241, 246, 251, 257, 263, + 269, 275, 283, 290, 298, 307, 317, 327, + 339, 352, 367, 384, 404, 429, 458, 494, + 522, 522, 522, 522, 522, 522, 522, 522, 522, +}; + + +static const int32_t hd_quantize_intervals_MLF[33] = { + -21236, 21236, 63830, 106798, 150386, 194832, 240376, 287258, + 335726, 386034, 438460, 493308, 550924, 611696, 676082, 744626, + 817986, 896968, 982580, 1076118, 1179278, 1294344, 1424504, 1574386, + 1751090, 1966260, 2240868, 2617662, 3196432, 4176450, 5658260, 7671068, + 10380372, +}; +static const int32_t hd_invert_quantize_dither_factors_MLF[33] = { + 21236, 21236, 21360, 21608, 21978, 22468, 23076, 23806, + 24660, 25648, 26778, 28070, 29544, 31228, 33158, 35386, + 37974, 41008, 44606, 48934, 54226, 60840, 69320, 80564, + 96140, 119032, 155576, 221218, 357552, 622468, 859344, 1153464, 1555840, +}; +static const int32_t hd_quantize_dither_factors_MLF[32] = { + 0, 31, 62, 93, 123, 152, 183, 214, + 247, 283, 323, 369, 421, 483, 557, 647, + 759, 900, 1082, 1323, 1654, 2120, 2811, 3894, + 5723, 9136, 16411, 34084, 66229, 59219, 73530, 100594, +}; +static const int16_t hd_quantize_factor_select_offset_MLF[33] = { + 0, -21, -16, -12, -7, -2, 3, 8, + 13, 19, 24, 30, 36, 43, 50, 57, + 65, 74, 83, 93, 104, 117, 131, 147, + 166, 189, 219, 259, 322, 427, 521, 521, 521, +}; + + +static const int32_t hd_quantize_intervals_MHF[9] = { + -95044, 95044, 295844, 528780, 821332, 1226438, 1890540, 3344850, 6450664, +}; +static const int32_t hd_invert_quantize_dither_factors_MHF[9] = { + 95044, 95044, 105754, 127180, 165372, 39736, 424366, 1029946, 2075866, +}; +static const int32_t hd_quantize_dither_factors_MHF[8] = { + 0, 2678, 5357, 9548, -31409, 96158, 151395, 261480, +}; +static const int16_t hd_quantize_factor_select_offset_MHF[9] = { + 0, -17, 5, 30, 62, 105, 177, 334, 518, +}; + + +static const int32_t hd_quantize_intervals_HF[17] = { + -45754, 45754, 138496, 234896, 337336, 448310, 570738, 708380, + 866534, 1053262, 1281958, 1577438, 1993050, 2665984, 3900982, 5902844, + 8897462, +}; +static const int32_t hd_invert_quantize_dither_factors_HF[17] = { + 45754, 45754, 46988, 49412, 53026, 57950, 64478, 73164, + 84988, 101740, 126958, 168522, 247092, 425842, 809154, 1192708, 1801910, +}; +static const int32_t hd_quantize_dither_factors_HF[16] = { + 0, 309, 606, 904, 1231, 1632, 2172, 2956, + 4188, 6305, 10391, 19643, 44688, 95828, 95889, 152301, +}; +static const int16_t hd_quantize_factor_select_offset_HF[17] = { + 0, -18, -8, 2, 13, 25, 38, 53, + 70, 90, 115, 147, 192, 264, 398, 521, 521, +}; + typedef const struct { const int32_t *quantize_intervals; const int32_t *invert_quantize_dither_factors; @@ -192,7 +393,8 @@ typedef const struct { int32_t prediction_order; } ConstTables; -static ConstTables tables[NB_SUBBANDS] = { +static ConstTables tables[2][NB_SUBBANDS] = { +{ [LF] = { quantize_intervals_LF, invert_quantize_dither_factors_LF, quantize_dither_factors_LF, @@ -217,6 +419,33 @@ static ConstTables tables[NB_SUBBANDS] = { quantize_factor_select_offset_HF, FF_ARRAY_ELEMS(quantize_intervals_HF), 0x15FF, 12 }, +}, +{ + [LF] = { hd_quantize_intervals_LF, + hd_invert_quantize_dither_factors_LF, + hd_quantize_dither_factors_LF, + hd_quantize_factor_select_offset_LF, + FF_ARRAY_ELEMS(hd_quantize_intervals_LF), + 0x11FF, 24 }, + [MLF] = { hd_quantize_intervals_MLF, + hd_invert_quantize_dither_factors_MLF, + hd_quantize_dither_factors_MLF, + hd_quantize_factor_select_offset_MLF, + FF_ARRAY_ELEMS(hd_quantize_intervals_MLF), + 0x14FF, 12 }, + [MHF] = { hd_quantize_intervals_MHF, + hd_invert_quantize_dither_factors_MHF, + hd_quantize_dither_factors_MHF, + hd_quantize_factor_select_offset_MHF, + FF_ARRAY_ELEMS(hd_quantize_intervals_MHF), + 0x16FF, 6 }, + [HF] = { hd_quantize_intervals_HF, + hd_invert_quantize_dither_factors_HF, + hd_quantize_dither_factors_HF, + hd_quantize_factor_select_offset_HF, + FF_ARRAY_ELEMS(hd_quantize_intervals_HF), + 0x15FF, 12 }, +} }; static const int16_t quantization_factors[32] = { @@ -494,7 +723,7 @@ static void aptx_quantize_difference(Quantize *quantize, quantize->quantized_sample_parity_change = parity_change ^ inv; } -static void aptx_encode_channel(Channel *channel, int32_t samples[4]) +static void aptx_encode_channel(Channel *channel, int32_t samples[4], int hd) { int32_t subband_samples[4]; int subband; @@ -505,7 +734,7 @@ static void aptx_encode_channel(Channel *channel, int32_t samples[4]) aptx_quantize_difference(&channel->quantize[subband], diff, channel->dither[subband], channel->invert_quantize[subband].quantization_factor, - &tables[subband]); + &tables[hd][subband]); } } @@ -616,7 +845,7 @@ static void aptx_process_subband(InvertQuantize *invert_quantize, tables->prediction_order); } -static void aptx_invert_quantize_and_prediction(Channel *channel) +static void aptx_invert_quantize_and_prediction(Channel *channel, int hd) { int subband; for (subband = 0; subband < NB_SUBBANDS; subband++) @@ -624,7 +853,7 @@ static void aptx_invert_quantize_and_prediction(Channel *channel) &channel->prediction[subband], channel->quantize[subband].quantized_sample, channel->dither[subband], - &tables[subband]); + &tables[hd][subband]); } static int32_t aptx_quantized_parity(Channel *channel) @@ -678,6 +907,15 @@ static uint16_t aptx_pack_codeword(Channel *channel) | (((channel->quantize[0].quantized_sample & 0x7F) ) << 0); } +static uint32_t aptxhd_pack_codeword(Channel *channel) +{ + int32_t parity = aptx_quantized_parity(channel); + return (((channel->quantize[3].quantized_sample & 0x01E) | parity) << 19) + | (((channel->quantize[2].quantized_sample & 0x00F) ) << 15) + | (((channel->quantize[1].quantized_sample & 0x03F) ) << 9) + | (((channel->quantize[0].quantized_sample & 0x1FF) ) << 0); +} + static void aptx_unpack_codeword(Channel *channel, uint16_t codeword) { channel->quantize[0].quantized_sample = sign_extend(codeword >> 0, 7); @@ -688,35 +926,53 @@ static void aptx_unpack_codeword(Channel *channel, uint16_t codeword) | aptx_quantized_parity(channel); } +static void aptxhd_unpack_codeword(Channel *channel, uint32_t codeword) +{ + channel->quantize[0].quantized_sample = sign_extend(codeword >> 0, 9); + channel->quantize[1].quantized_sample = sign_extend(codeword >> 9, 6); + channel->quantize[2].quantized_sample = sign_extend(codeword >> 15, 4); + channel->quantize[3].quantized_sample = sign_extend(codeword >> 19, 5); + channel->quantize[3].quantized_sample = (channel->quantize[3].quantized_sample & ~1) + | aptx_quantized_parity(channel); +} + static void aptx_encode_samples(AptXContext *ctx, int32_t samples[NB_CHANNELS][4], - uint8_t output[2*NB_CHANNELS]) + uint8_t *output) { int channel; for (channel = 0; channel < NB_CHANNELS; channel++) - aptx_encode_channel(&ctx->channels[channel], samples[channel]); + aptx_encode_channel(&ctx->channels[channel], samples[channel], ctx->hd); aptx_insert_sync(ctx->channels, &ctx->sync_idx); for (channel = 0; channel < NB_CHANNELS; channel++) { - aptx_invert_quantize_and_prediction(&ctx->channels[channel]); - AV_WB16(output + 2*channel, aptx_pack_codeword(&ctx->channels[channel])); + aptx_invert_quantize_and_prediction(&ctx->channels[channel], ctx->hd); + if (ctx->hd) + AV_WB24(output + 3*channel, + aptxhd_pack_codeword(&ctx->channels[channel])); + else + AV_WB16(output + 2*channel, + aptx_pack_codeword(&ctx->channels[channel])); } } static int aptx_decode_samples(AptXContext *ctx, - const uint8_t input[2*NB_CHANNELS], + const uint8_t *input, int32_t samples[NB_CHANNELS][4]) { int channel, ret; for (channel = 0; channel < NB_CHANNELS; channel++) { - uint16_t codeword; aptx_generate_dither(&ctx->channels[channel]); - codeword = AV_RB16(input + 2*channel); - aptx_unpack_codeword(&ctx->channels[channel], codeword); - aptx_invert_quantize_and_prediction(&ctx->channels[channel]); + if (ctx->hd) + aptxhd_unpack_codeword(&ctx->channels[channel], + AV_RB24(input + 3*channel)); + else + aptx_unpack_codeword(&ctx->channels[channel], + AV_RB16(input + 2*channel)); + aptx_invert_quantize_and_prediction(&ctx->channels[channel], ctx->hd); } ret = aptx_check_parity(ctx->channels, &ctx->sync_idx); @@ -733,11 +989,15 @@ static av_cold int aptx_init(AVCodecContext *avctx) AptXContext *s = avctx->priv_data; int chan, subband; + s->hd = avctx->codec->id == AV_CODEC_ID_APTX_HD; + s->block_size = s->hd ? 6 : 4; + if (avctx->frame_size == 0) - avctx->frame_size = 1024; + avctx->frame_size = 256 * s->block_size; - if (avctx->frame_size & 3) { - av_log(avctx, AV_LOG_ERROR, "Frame size must be a multiple of 4 samples\n"); + if (avctx->frame_size % s->block_size) { + av_log(avctx, AV_LOG_ERROR, + "Frame size must be a multiple of %d samples\n", s->block_size); return AVERROR(EINVAL); } @@ -759,9 +1019,9 @@ static int aptx_decode_frame(AVCodecContext *avctx, void *data, { AptXContext *s = avctx->priv_data; AVFrame *frame = data; - int pos, channel, sample, ret; + int pos, opos, channel, sample, ret; - if (avpkt->size < 4) { + if (avpkt->size < s->block_size) { av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); return AVERROR_INVALIDDATA; } @@ -769,11 +1029,11 @@ static int aptx_decode_frame(AVCodecContext *avctx, void *data, /* get output buffer */ frame->channels = NB_CHANNELS; frame->format = AV_SAMPLE_FMT_S32P; - frame->nb_samples = avpkt->size & ~3; + frame->nb_samples = 4 * avpkt->size / s->block_size; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - for (pos = 0; pos < frame->nb_samples; pos += 4) { + for (pos = 0, opos = 0; opos < frame->nb_samples; pos += s->block_size, opos += 4) { int32_t samples[NB_CHANNELS][4]; if (aptx_decode_samples(s, &avpkt->data[pos], samples)) { @@ -783,32 +1043,33 @@ static int aptx_decode_frame(AVCodecContext *avctx, void *data, for (channel = 0; channel < NB_CHANNELS; channel++) for (sample = 0; sample < 4; sample++) - AV_WN32A(&frame->data[channel][4*(sample+pos)], + AV_WN32A(&frame->data[channel][4*(opos+sample)], samples[channel][sample] << 8); } *got_frame_ptr = 1; - return frame->nb_samples; + return s->block_size * frame->nb_samples / 4; } static int aptx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { AptXContext *s = avctx->priv_data; - int pos, channel, sample, ret; + int pos, ipos, channel, sample, output_size, ret; if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) return ret; - if ((ret = ff_alloc_packet2(avctx, avpkt, frame->nb_samples, 0)) < 0) + output_size = s->block_size * frame->nb_samples/4; + if ((ret = ff_alloc_packet2(avctx, avpkt, output_size, 0)) < 0) return ret; - for (pos = 0; pos < frame->nb_samples; pos += 4) { + for (pos = 0, ipos = 0; pos < output_size; pos += s->block_size, ipos += 4) { int32_t samples[NB_CHANNELS][4]; for (channel = 0; channel < NB_CHANNELS; channel++) for (sample = 0; sample < 4; sample++) - samples[channel][sample] = (int32_t)AV_RN32A(&frame->data[channel][4*(sample+pos)]) >> 8; + samples[channel][sample] = (int32_t)AV_RN32A(&frame->data[channel][4*(ipos+sample)]) >> 8; aptx_encode_samples(s, samples, avpkt->data + pos); } @@ -844,6 +1105,24 @@ AVCodec ff_aptx_decoder = { }; #endif +#if CONFIG_APTX_HD_DECODER +AVCodec ff_aptx_hd_decoder = { + .name = "aptx_hd", + .long_name = NULL_IF_CONFIG_SMALL("aptX HD (Audio Processing Technology for Bluetooth)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_APTX_HD, + .priv_data_size = sizeof(AptXContext), + .init = aptx_init, + .decode = aptx_decode_frame, + .close = aptx_close, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_NONE }, +}; +#endif + #if CONFIG_APTX_ENCODER AVCodec ff_aptx_encoder = { .name = "aptx", @@ -862,3 +1141,22 @@ AVCodec ff_aptx_encoder = { .supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0}, }; #endif + +#if CONFIG_APTX_HD_ENCODER +AVCodec ff_aptx_hd_encoder = { + .name = "aptx_hd", + .long_name = NULL_IF_CONFIG_SMALL("aptX HD (Audio Processing Technology for Bluetooth)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_APTX_HD, + .priv_data_size = sizeof(AptXContext), + .init = aptx_init, + .encode2 = aptx_encode_frame, + .close = aptx_close, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_NONE }, + .supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0}, +}; +#endif diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 1c32339754459..ad0b48a83996c 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -634,6 +634,7 @@ enum AVCodecID { AV_CODEC_ID_ATRAC3PAL, AV_CODEC_ID_DOLBY_E, AV_CODEC_ID_APTX, + AV_CODEC_ID_APTX_HD, /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 1e5d715416494..15f6489278660 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2858,6 +2858,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_APTX_HD, + .type = AVMEDIA_TYPE_AUDIO, + .name = "aptx_hd", + .long_name = NULL_IF_CONFIG_SMALL("aptX HD (Audio Processing Technology for Bluetooth)"), + .props = AV_CODEC_PROP_LOSSY, + }, /* subtitle codecs */ { From d8258489c87e5571337056be6ce1c2aa739e6873 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sat, 6 Jan 2018 17:33:01 +0100 Subject: [PATCH 1833/2557] aptx: add raw muxer and demuxer for aptX HD --- Changelog | 2 +- doc/general.texi | 1 + libavformat/Makefile | 2 ++ libavformat/allformats.c | 2 ++ libavformat/aptxdec.c | 58 +++++++++++++++++++++++++++++++++++++--- libavformat/rawenc.c | 13 +++++++++ 6 files changed, 73 insertions(+), 5 deletions(-) diff --git a/Changelog b/Changelog index e23fdd6ff8054..2acdbbea300b0 100644 --- a/Changelog +++ b/Changelog @@ -12,7 +12,7 @@ version : - Intel QSV-accelerated MJPEG encoding - PCE support for extended channel layouts in the AAC encoder - native aptX and aptX HD encoder and decoder -- Raw aptX muxer and demuxer +- Raw aptX and aptX HD muxer and demuxer - NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-1/2/4, VC1, VP8/9 hwaccel decoding - Intel QSV-accelerated overlay filter - mcompand audio filter diff --git a/doc/general.texi b/doc/general.texi index 352110f42c5ce..9ddcccf041ea9 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -455,6 +455,7 @@ library: @item raw AMR-NB @tab @tab X @item raw AMR-WB @tab @tab X @item raw aptX @tab X @tab X +@item raw aptX HD @tab X @tab X @item raw Chinese AVS video @tab X @tab X @item raw CRI ADX @tab X @tab X @item raw Dirac @tab X @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index f9a45338ece7a..404873624d684 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -96,6 +96,8 @@ OBJS-$(CONFIG_APNG_DEMUXER) += apngdec.o OBJS-$(CONFIG_APNG_MUXER) += apngenc.o OBJS-$(CONFIG_APTX_DEMUXER) += aptxdec.o rawdec.o OBJS-$(CONFIG_APTX_MUXER) += rawenc.o +OBJS-$(CONFIG_APTX_HD_DEMUXER) += aptxdec.o rawdec.o +OBJS-$(CONFIG_APTX_HD_MUXER) += rawenc.o OBJS-$(CONFIG_AQTITLE_DEMUXER) += aqtitledec.o subtitles.o OBJS-$(CONFIG_ASF_DEMUXER) += asfdec_f.o asf.o asfcrypt.o \ avlanguage.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 9fd649bb4cee4..e75cd917e44a9 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -59,6 +59,8 @@ extern AVInputFormat ff_apng_demuxer; extern AVOutputFormat ff_apng_muxer; extern AVInputFormat ff_aptx_demuxer; extern AVOutputFormat ff_aptx_muxer; +extern AVInputFormat ff_aptx_hd_demuxer; +extern AVOutputFormat ff_aptx_hd_muxer; extern AVInputFormat ff_aqtitle_demuxer; extern AVInputFormat ff_asf_demuxer; extern AVOutputFormat ff_asf_muxer; diff --git a/libavformat/aptxdec.c b/libavformat/aptxdec.c index 3b8fae1b55e39..467bc3fd5a834 100644 --- a/libavformat/aptxdec.c +++ b/libavformat/aptxdec.c @@ -26,26 +26,49 @@ #define APTX_BLOCK_SIZE 4 #define APTX_PACKET_SIZE (256*APTX_BLOCK_SIZE) +#define APTX_HD_BLOCK_SIZE 6 +#define APTX_HD_PACKET_SIZE (256*APTX_HD_BLOCK_SIZE) + typedef struct AptXDemuxerContext { AVClass *class; int sample_rate; } AptXDemuxerContext; -static int aptx_read_header(AVFormatContext *s) +static AVStream *aptx_read_header_common(AVFormatContext *s) { AptXDemuxerContext *s1 = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); if (!st) - return AVERROR(ENOMEM); + return NULL; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->codec_id = AV_CODEC_ID_APTX; st->codecpar->format = AV_SAMPLE_FMT_S32P; st->codecpar->channels = 2; st->codecpar->sample_rate = s1->sample_rate; + st->start_time = 0; + return st; +} + +static int aptx_read_header(AVFormatContext *s) +{ + AVStream *st = aptx_read_header_common(s); + if (!st) + return AVERROR(ENOMEM); + st->codecpar->codec_id = AV_CODEC_ID_APTX; st->codecpar->bits_per_coded_sample = 4; st->codecpar->block_align = APTX_BLOCK_SIZE; st->codecpar->frame_size = APTX_PACKET_SIZE; - st->start_time = 0; + return 0; +} + +static int aptx_hd_read_header(AVFormatContext *s) +{ + AVStream *st = aptx_read_header_common(s); + if (!st) + return AVERROR(ENOMEM); + st->codecpar->codec_id = AV_CODEC_ID_APTX_HD; + st->codecpar->bits_per_coded_sample = 6; + st->codecpar->block_align = APTX_HD_BLOCK_SIZE; + st->codecpar->frame_size = APTX_HD_PACKET_SIZE; return 0; } @@ -54,11 +77,17 @@ static int aptx_read_packet(AVFormatContext *s, AVPacket *pkt) return av_get_packet(s->pb, pkt, APTX_PACKET_SIZE); } +static int aptx_hd_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + return av_get_packet(s->pb, pkt, APTX_HD_PACKET_SIZE); +} + static const AVOption aptx_options[] = { { "sample_rate", "", offsetof(AptXDemuxerContext, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, { NULL }, }; +#if CONFIG_APTX_MUXER static const AVClass aptx_demuxer_class = { .class_name = "aptx demuxer", .item_name = av_default_item_name, @@ -76,3 +105,24 @@ AVInputFormat ff_aptx_demuxer = { .flags = AVFMT_GENERIC_INDEX, .priv_class = &aptx_demuxer_class, }; +#endif + +#if CONFIG_APTX_HD_DEMUXER +static const AVClass aptx_hd_demuxer_class = { + .class_name = "aptx hd demuxer", + .item_name = av_default_item_name, + .option = aptx_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_aptx_hd_demuxer = { + .name = "aptx_hd", + .long_name = NULL_IF_CONFIG_SMALL("raw aptX HD"), + .extensions = "aptxhd", + .priv_data_size = sizeof(AptXDemuxerContext), + .read_header = aptx_hd_read_header, + .read_packet = aptx_hd_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .priv_class = &aptx_hd_demuxer_class, +}; +#endif diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index aa3ef76fbf41c..dcf880d17e0e7 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -104,6 +104,19 @@ AVOutputFormat ff_aptx_muxer = { }; #endif +#if CONFIG_APTX_HD_MUXER +AVOutputFormat ff_aptx_hd_muxer = { + .name = "aptx_hd", + .long_name = NULL_IF_CONFIG_SMALL("raw aptX HD (Audio Processing Technology for Bluetooth)"), + .extensions = "aptxhd", + .audio_codec = AV_CODEC_ID_APTX_HD, + .video_codec = AV_CODEC_ID_NONE, + .write_header = force_one_stream, + .write_packet = ff_raw_write_packet, + .flags = AVFMT_NOTIMESTAMPS, +}; +#endif + #if CONFIG_CAVSVIDEO_MUXER AVOutputFormat ff_cavsvideo_muxer = { .name = "cavsvideo", From c69054fa24f5125eea3c817e8a76fe6422ea165d Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sat, 6 Jan 2018 17:56:21 +0100 Subject: [PATCH 1834/2557] aptx: indentation (cosmetics only) --- libavcodec/aptx.c | 104 +++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/libavcodec/aptx.c b/libavcodec/aptx.c index 6c0f3d35a9c89..8750d8421fb4e 100644 --- a/libavcodec/aptx.c +++ b/libavcodec/aptx.c @@ -394,58 +394,58 @@ typedef const struct { } ConstTables; static ConstTables tables[2][NB_SUBBANDS] = { -{ - [LF] = { quantize_intervals_LF, - invert_quantize_dither_factors_LF, - quantize_dither_factors_LF, - quantize_factor_select_offset_LF, - FF_ARRAY_ELEMS(quantize_intervals_LF), - 0x11FF, 24 }, - [MLF] = { quantize_intervals_MLF, - invert_quantize_dither_factors_MLF, - quantize_dither_factors_MLF, - quantize_factor_select_offset_MLF, - FF_ARRAY_ELEMS(quantize_intervals_MLF), - 0x14FF, 12 }, - [MHF] = { quantize_intervals_MHF, - invert_quantize_dither_factors_MHF, - quantize_dither_factors_MHF, - quantize_factor_select_offset_MHF, - FF_ARRAY_ELEMS(quantize_intervals_MHF), - 0x16FF, 6 }, - [HF] = { quantize_intervals_HF, - invert_quantize_dither_factors_HF, - quantize_dither_factors_HF, - quantize_factor_select_offset_HF, - FF_ARRAY_ELEMS(quantize_intervals_HF), - 0x15FF, 12 }, -}, -{ - [LF] = { hd_quantize_intervals_LF, - hd_invert_quantize_dither_factors_LF, - hd_quantize_dither_factors_LF, - hd_quantize_factor_select_offset_LF, - FF_ARRAY_ELEMS(hd_quantize_intervals_LF), - 0x11FF, 24 }, - [MLF] = { hd_quantize_intervals_MLF, - hd_invert_quantize_dither_factors_MLF, - hd_quantize_dither_factors_MLF, - hd_quantize_factor_select_offset_MLF, - FF_ARRAY_ELEMS(hd_quantize_intervals_MLF), - 0x14FF, 12 }, - [MHF] = { hd_quantize_intervals_MHF, - hd_invert_quantize_dither_factors_MHF, - hd_quantize_dither_factors_MHF, - hd_quantize_factor_select_offset_MHF, - FF_ARRAY_ELEMS(hd_quantize_intervals_MHF), - 0x16FF, 6 }, - [HF] = { hd_quantize_intervals_HF, - hd_invert_quantize_dither_factors_HF, - hd_quantize_dither_factors_HF, - hd_quantize_factor_select_offset_HF, - FF_ARRAY_ELEMS(hd_quantize_intervals_HF), - 0x15FF, 12 }, -} + { + [LF] = { quantize_intervals_LF, + invert_quantize_dither_factors_LF, + quantize_dither_factors_LF, + quantize_factor_select_offset_LF, + FF_ARRAY_ELEMS(quantize_intervals_LF), + 0x11FF, 24 }, + [MLF] = { quantize_intervals_MLF, + invert_quantize_dither_factors_MLF, + quantize_dither_factors_MLF, + quantize_factor_select_offset_MLF, + FF_ARRAY_ELEMS(quantize_intervals_MLF), + 0x14FF, 12 }, + [MHF] = { quantize_intervals_MHF, + invert_quantize_dither_factors_MHF, + quantize_dither_factors_MHF, + quantize_factor_select_offset_MHF, + FF_ARRAY_ELEMS(quantize_intervals_MHF), + 0x16FF, 6 }, + [HF] = { quantize_intervals_HF, + invert_quantize_dither_factors_HF, + quantize_dither_factors_HF, + quantize_factor_select_offset_HF, + FF_ARRAY_ELEMS(quantize_intervals_HF), + 0x15FF, 12 }, + }, + { + [LF] = { hd_quantize_intervals_LF, + hd_invert_quantize_dither_factors_LF, + hd_quantize_dither_factors_LF, + hd_quantize_factor_select_offset_LF, + FF_ARRAY_ELEMS(hd_quantize_intervals_LF), + 0x11FF, 24 }, + [MLF] = { hd_quantize_intervals_MLF, + hd_invert_quantize_dither_factors_MLF, + hd_quantize_dither_factors_MLF, + hd_quantize_factor_select_offset_MLF, + FF_ARRAY_ELEMS(hd_quantize_intervals_MLF), + 0x14FF, 12 }, + [MHF] = { hd_quantize_intervals_MHF, + hd_invert_quantize_dither_factors_MHF, + hd_quantize_dither_factors_MHF, + hd_quantize_factor_select_offset_MHF, + FF_ARRAY_ELEMS(hd_quantize_intervals_MHF), + 0x16FF, 6 }, + [HF] = { hd_quantize_intervals_HF, + hd_invert_quantize_dither_factors_HF, + hd_quantize_dither_factors_HF, + hd_quantize_factor_select_offset_HF, + FF_ARRAY_ELEMS(hd_quantize_intervals_HF), + 0x15FF, 12 }, + } }; static const int16_t quantization_factors[32] = { From 10bcc41bb40ba479bfc5ad29b1650a6b335437a8 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 7 Feb 2018 19:36:57 +0000 Subject: [PATCH 1835/2557] examples: Don't call deprecated functions which don't do anything --- doc/examples/avio_dir_cmd.c | 2 -- doc/examples/avio_reading.c | 3 --- doc/examples/decode_audio.c | 3 --- doc/examples/decode_video.c | 2 -- doc/examples/demuxing_decoding.c | 3 --- doc/examples/encode_audio.c | 3 --- doc/examples/encode_video.c | 2 -- doc/examples/extract_mvs.c | 2 -- doc/examples/filtering_audio.c | 1 - doc/examples/filtering_video.c | 1 - doc/examples/http_multiclient.c | 1 - doc/examples/hw_decode.c | 2 -- doc/examples/metadata.c | 1 - doc/examples/muxing.c | 3 --- doc/examples/qsvdec.c | 2 -- doc/examples/remuxing.c | 2 -- doc/examples/transcode_aac.c | 2 -- doc/examples/transcoding.c | 1 - doc/examples/vaapi_encode.c | 2 -- doc/examples/vaapi_transcode.c | 2 -- 20 files changed, 40 deletions(-) diff --git a/doc/examples/avio_dir_cmd.c b/doc/examples/avio_dir_cmd.c index 50c435cf8f89b..0722bd9ab154c 100644 --- a/doc/examples/avio_dir_cmd.c +++ b/doc/examples/avio_dir_cmd.c @@ -143,8 +143,6 @@ int main(int argc, char *argv[]) return 1; } - /* register codecs and formats and other lavf/lavc components*/ - av_register_all(); avformat_network_init(); op = argv[1]; diff --git a/doc/examples/avio_reading.c b/doc/examples/avio_reading.c index 7860fd5e2fd7b..cbfeb174b8ce4 100644 --- a/doc/examples/avio_reading.c +++ b/doc/examples/avio_reading.c @@ -74,9 +74,6 @@ int main(int argc, char *argv[]) } input_filename = argv[1]; - /* register codecs and formats and other lavf/lavc components*/ - av_register_all(); - /* slurp file content into buffer */ ret = av_file_map(input_filename, &buffer, &buffer_size, 0, NULL); if (ret < 0) diff --git a/doc/examples/decode_audio.c b/doc/examples/decode_audio.c index fb9a9af2f60b0..19dcafd2c82c3 100644 --- a/doc/examples/decode_audio.c +++ b/doc/examples/decode_audio.c @@ -94,9 +94,6 @@ int main(int argc, char **argv) filename = argv[1]; outfilename = argv[2]; - /* register all the codecs */ - avcodec_register_all(); - pkt = av_packet_alloc(); /* find the MPEG audio decoder */ diff --git a/doc/examples/decode_video.c b/doc/examples/decode_video.c index 4377fd49e0dc6..5a9d43f689733 100644 --- a/doc/examples/decode_video.c +++ b/doc/examples/decode_video.c @@ -101,8 +101,6 @@ int main(int argc, char **argv) filename = argv[1]; outfilename = argv[2]; - avcodec_register_all(); - pkt = av_packet_alloc(); if (!pkt) exit(1); diff --git a/doc/examples/demuxing_decoding.c b/doc/examples/demuxing_decoding.c index b1a216abb4cb7..69a31a893519c 100644 --- a/doc/examples/demuxing_decoding.c +++ b/doc/examples/demuxing_decoding.c @@ -252,9 +252,6 @@ int main (int argc, char **argv) video_dst_filename = argv[2]; audio_dst_filename = argv[3]; - /* register all formats and codecs */ - av_register_all(); - /* open input file, and allocate format context */ if (avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) < 0) { fprintf(stderr, "Could not open source file %s\n", src_filename); diff --git a/doc/examples/encode_audio.c b/doc/examples/encode_audio.c index d1ef105d9dabd..ab3586be7fd6e 100644 --- a/doc/examples/encode_audio.c +++ b/doc/examples/encode_audio.c @@ -138,9 +138,6 @@ int main(int argc, char **argv) } filename = argv[1]; - /* register all the codecs */ - avcodec_register_all(); - /* find the MP2 encoder */ codec = avcodec_find_encoder(AV_CODEC_ID_MP2); if (!codec) { diff --git a/doc/examples/encode_video.c b/doc/examples/encode_video.c index 8cd13219bb560..6731b2ad19bf1 100644 --- a/doc/examples/encode_video.c +++ b/doc/examples/encode_video.c @@ -84,8 +84,6 @@ int main(int argc, char **argv) filename = argv[1]; codec_name = argv[2]; - avcodec_register_all(); - /* find the mpeg1video encoder */ codec = avcodec_find_encoder_by_name(codec_name); if (!codec) { diff --git a/doc/examples/extract_mvs.c b/doc/examples/extract_mvs.c index 7ae934ead3d51..de31ccd2b9877 100644 --- a/doc/examples/extract_mvs.c +++ b/doc/examples/extract_mvs.c @@ -129,8 +129,6 @@ int main(int argc, char **argv) } src_filename = argv[1]; - av_register_all(); - if (avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) < 0) { fprintf(stderr, "Could not open source file %s\n", src_filename); exit(1); diff --git a/doc/examples/filtering_audio.c b/doc/examples/filtering_audio.c index 18d6ca275c50d..73a00e814c1ab 100644 --- a/doc/examples/filtering_audio.c +++ b/doc/examples/filtering_audio.c @@ -228,7 +228,6 @@ int main(int argc, char **argv) exit(1); } - av_register_all(); avfilter_register_all(); if ((ret = open_input_file(argv[1])) < 0) diff --git a/doc/examples/filtering_video.c b/doc/examples/filtering_video.c index 9b607ba016f73..01d6644620be6 100644 --- a/doc/examples/filtering_video.c +++ b/doc/examples/filtering_video.c @@ -222,7 +222,6 @@ int main(int argc, char **argv) exit(1); } - av_register_all(); avfilter_register_all(); if ((ret = open_input_file(argv[1])) < 0) diff --git a/doc/examples/http_multiclient.c b/doc/examples/http_multiclient.c index e2c2201a08f36..831e89c60a496 100644 --- a/doc/examples/http_multiclient.c +++ b/doc/examples/http_multiclient.c @@ -114,7 +114,6 @@ int main(int argc, char **argv) in_uri = argv[1]; out_uri = argv[2]; - av_register_all(); avformat_network_init(); if ((ret = av_dict_set(&options, "listen", "2", 0)) < 0) { diff --git a/doc/examples/hw_decode.c b/doc/examples/hw_decode.c index 83a5808bf7f90..14fe08b374f9e 100644 --- a/doc/examples/hw_decode.c +++ b/doc/examples/hw_decode.c @@ -163,8 +163,6 @@ int main(int argc, char *argv[]) return -1; } - av_register_all(); - type = av_hwdevice_find_type_by_name(argv[1]); if (type == AV_HWDEVICE_TYPE_NONE) { fprintf(stderr, "Device type %s is not supported.\n", argv[1]); diff --git a/doc/examples/metadata.c b/doc/examples/metadata.c index f73c2673692c1..e330d077a9393 100644 --- a/doc/examples/metadata.c +++ b/doc/examples/metadata.c @@ -44,7 +44,6 @@ int main (int argc, char **argv) return 1; } - av_register_all(); if ((ret = avformat_open_input(&fmt_ctx, argv[1], NULL, NULL))) return ret; diff --git a/doc/examples/muxing.c b/doc/examples/muxing.c index 6b98a3b2a0ac1..08da98e574a91 100644 --- a/doc/examples/muxing.c +++ b/doc/examples/muxing.c @@ -564,9 +564,6 @@ int main(int argc, char **argv) AVDictionary *opt = NULL; int i; - /* Initialize libavcodec, and register all codecs and formats. */ - av_register_all(); - if (argc < 2) { printf("usage: %s output_file\n" "API example program to output a media file with libavformat.\n" diff --git a/doc/examples/qsvdec.c b/doc/examples/qsvdec.c index cede6153bed3b..7415eefca5b82 100644 --- a/doc/examples/qsvdec.c +++ b/doc/examples/qsvdec.c @@ -150,8 +150,6 @@ int main(int argc, char **argv) int ret, i; - av_register_all(); - if (argc < 3) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; diff --git a/doc/examples/remuxing.c b/doc/examples/remuxing.c index 59594181a7090..9e4d1031b4a59 100644 --- a/doc/examples/remuxing.c +++ b/doc/examples/remuxing.c @@ -65,8 +65,6 @@ int main(int argc, char **argv) in_filename = argv[1]; out_filename = argv[2]; - av_register_all(); - if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) { fprintf(stderr, "Could not open input file '%s'", in_filename); goto end; diff --git a/doc/examples/transcode_aac.c b/doc/examples/transcode_aac.c index 3c7688cd3383f..b19349573ac59 100644 --- a/doc/examples/transcode_aac.c +++ b/doc/examples/transcode_aac.c @@ -753,8 +753,6 @@ int main(int argc, char **argv) exit(1); } - /* Register all codecs and formats so that they can be used. */ - av_register_all(); /* Open the input file for reading. */ if (open_input_file(argv[1], &input_format_context, &input_codec_context)) diff --git a/doc/examples/transcoding.c b/doc/examples/transcoding.c index e32ab202453da..ed1fd6411bfd1 100644 --- a/doc/examples/transcoding.c +++ b/doc/examples/transcoding.c @@ -517,7 +517,6 @@ int main(int argc, char **argv) return 1; } - av_register_all(); avfilter_register_all(); if ((ret = open_input_file(argv[1])) < 0) diff --git a/doc/examples/vaapi_encode.c b/doc/examples/vaapi_encode.c index 6425b1c98c354..3bdc62bef37da 100644 --- a/doc/examples/vaapi_encode.c +++ b/doc/examples/vaapi_encode.c @@ -125,8 +125,6 @@ int main(int argc, char *argv[]) goto close; } - avcodec_register_all(); - err = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI, NULL, NULL, 0); if (err < 0) { diff --git a/doc/examples/vaapi_transcode.c b/doc/examples/vaapi_transcode.c index 6318895af3307..649f48b97c308 100644 --- a/doc/examples/vaapi_transcode.c +++ b/doc/examples/vaapi_transcode.c @@ -238,8 +238,6 @@ int main(int argc, char **argv) return -1; } - av_register_all(); - ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI, NULL, NULL, 0); if (ret < 0) { fprintf(stderr, "Failed to create a VAAPI device. Error code: %s\n", av_err2str(ret)); From 909e00ae816df9b6a05b1c4d0cafb794d4d0ca28 Mon Sep 17 00:00:00 2001 From: Muhammad Faiz Date: Fri, 9 Feb 2018 17:03:42 +0700 Subject: [PATCH 1836/2557] avformat/format: temporarily use old next api Should fix https://ffmpeg.org/pipermail/ffmpeg-devel/2018-February/225066.html Signed-off-by: Muhammad Faiz --- libavformat/format.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/libavformat/format.c b/libavformat/format.c index b8c5a90a92d44..75951938cf054 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -52,7 +52,9 @@ AVOutputFormat *av_guess_format(const char *short_name, const char *filename, const char *mime_type) { AVOutputFormat *fmt = NULL, *fmt_found; +#if !FF_API_NEXT void *i = 0; +#endif int score_max, score; /* specific test for image sequences */ @@ -66,7 +68,13 @@ AVOutputFormat *av_guess_format(const char *short_name, const char *filename, /* Find the proper file type. */ fmt_found = NULL; score_max = 0; - while ((fmt = av_muxer_iterate(&i))) { +#if FF_API_NEXT +FF_DISABLE_DEPRECATION_WARNINGS + while ((fmt = av_oformat_next(fmt))) +#else + while ((fmt = av_muxer_iterate(&i))) +#endif + { score = 0; if (fmt->name && short_name && av_match_name(short_name, fmt->name)) score += 100; @@ -81,6 +89,9 @@ AVOutputFormat *av_guess_format(const char *short_name, const char *filename, fmt_found = fmt; } } +#if FF_API_NEXT +FF_ENABLE_DEPRECATION_WARNINGS +#endif return fmt_found; } From dd5208aaf5bf229915a4c0e4d58cb063dfcb3b9a Mon Sep 17 00:00:00 2001 From: Xiaohan Wang Date: Fri, 2 Feb 2018 17:33:56 -0800 Subject: [PATCH 1837/2557] avformat/mov: Fix ctts_index calculation An index should never be equal to the count. Hence we must make sure *ctts_index < ctts_count. Reviewed-by: Sasi Inguva Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index acfbfc5324d13..04567fc475cb1 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3132,7 +3132,7 @@ static int find_prev_closest_index(AVStream *st, } } - while (*index >= 0 && (*ctts_index) >= 0) { + while (*index >= 0 && (*ctts_index) >= 0 && (*ctts_index) < ctts_count) { // Find a "key frame" with PTS <= timestamp_pts (So that we can decode B-frames correctly). // No need to add dts_shift to the timestamp here becase timestamp_pts has already been // compensated by dts_shift above. From 3e21f285ccdeb2bb64385a8019ac6635af7316bb Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Fri, 9 Feb 2018 22:22:09 +0100 Subject: [PATCH 1838/2557] MAINTAINERS: add myself for aptx.c --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index ba7a7284eb826..b691bd56ec68c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -139,6 +139,7 @@ Codecs: aacenc*, aaccoder.c Rostislav Pehlivanov alacenc.c Jaikrishnan Menon alsdec.c Thilo Borgmann, Umair Khan + aptx.c Aurelien Jacobs ass* Aurelien Jacobs asv* Michael Niedermayer atrac3plus* Maxim Poliakovski From 063be4fe2cc631315fac028b5e5642e451304807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Sat, 10 Feb 2018 16:59:54 +0200 Subject: [PATCH 1839/2557] lavf/aptxdec: fix the limit on the APTX demuxer definition Fixes breakage with --disable-muxers as it was originally limited to the muxer, and not the demuxer. --- libavformat/aptxdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/aptxdec.c b/libavformat/aptxdec.c index 467bc3fd5a834..a262cd9ebea40 100644 --- a/libavformat/aptxdec.c +++ b/libavformat/aptxdec.c @@ -87,7 +87,7 @@ static const AVOption aptx_options[] = { { NULL }, }; -#if CONFIG_APTX_MUXER +#if CONFIG_APTX_DEMUXER static const AVClass aptx_demuxer_class = { .class_name = "aptx demuxer", .item_name = av_default_item_name, From 8b154cb3e90a3e599cadf477d815a9854b7bb4e1 Mon Sep 17 00:00:00 2001 From: Nekopanda Date: Sat, 10 Feb 2018 18:36:32 +0900 Subject: [PATCH 1840/2557] avcodec/mpeg2dec: Fix field selection for skipped macroblocks For B field pictures, the spec says, > The prediction shall be made from the field of the same parity as the field being predicted. I did it. Signed-off-by: Michael Niedermayer --- libavcodec/mpeg12dec.c | 2 + tests/ref/fate/mpeg2-ticket186 | 328 ++++++++++++++++----------------- 2 files changed, 166 insertions(+), 164 deletions(-) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index f5f2c696c05c5..9e076e89daa73 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -1969,6 +1969,8 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y, s->mv[0][0][1] = s->last_mv[0][0][1]; s->mv[1][0][0] = s->last_mv[1][0][0]; s->mv[1][0][1] = s->last_mv[1][0][1]; + s->field_select[0][0] = (s->picture_structure - 1) & 1; + s->field_select[1][0] = (s->picture_structure - 1) & 1; } } } diff --git a/tests/ref/fate/mpeg2-ticket186 b/tests/ref/fate/mpeg2-ticket186 index b716ca56110c1..31afda15e8c47 100644 --- a/tests/ref/fate/mpeg2-ticket186 +++ b/tests/ref/fate/mpeg2-ticket186 @@ -3,354 +3,354 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 12/11 -0, 0, 0, 1, 152064, 0xd23ffc59 +0, 0, 0, 1, 152064, 0x8f9d00c1 0, 1, 1, 1, 152064, 0x899fb8b1 -0, 2, 2, 1, 152064, 0x5958d070 +0, 2, 2, 1, 152064, 0x7225cb39 0, 3, 3, 1, 152064, 0xf2becd8f -0, 4, 4, 1, 152064, 0xb47bbed7 +0, 4, 4, 1, 152064, 0xd56bc556 0, 5, 5, 1, 152064, 0x7ca54f36 -0, 6, 6, 1, 152064, 0x02389610 +0, 6, 6, 1, 152064, 0x06d7805c 0, 7, 7, 1, 152064, 0x469f3f87 -0, 8, 8, 1, 152064, 0x935a780e +0, 8, 8, 1, 152064, 0xdb2f57d5 0, 9, 9, 1, 152064, 0x3876c20c -0, 10, 10, 1, 152064, 0x49df265f +0, 10, 10, 1, 152064, 0x5b670e79 0, 11, 11, 1, 152064, 0xdfe420e0 -0, 12, 12, 1, 152064, 0x6e34a0c4 +0, 12, 12, 1, 152064, 0x17578222 0, 13, 13, 1, 152064, 0x47e1cb26 -0, 14, 14, 1, 152064, 0x68e74188 +0, 14, 14, 1, 152064, 0x168e35d6 0, 15, 15, 1, 152064, 0xe9d34b4e -0, 16, 16, 1, 152064, 0xa8665e1a +0, 16, 16, 1, 152064, 0x5e395308 0, 17, 17, 1, 152064, 0x88e3b39f -0, 18, 18, 1, 152064, 0x1c1ab2c3 +0, 18, 18, 1, 152064, 0x6b099c51 0, 19, 19, 1, 152064, 0xb1a24ddf -0, 20, 20, 1, 152064, 0x030d5afc +0, 20, 20, 1, 152064, 0xcea840fc 0, 21, 21, 1, 152064, 0x98306d64 -0, 22, 22, 1, 152064, 0x5ce0548d +0, 22, 22, 1, 152064, 0xb05354d3 0, 23, 23, 1, 152064, 0xacac26f3 -0, 24, 24, 1, 152064, 0xf167f698 +0, 24, 24, 1, 152064, 0xbccdf14b 0, 25, 25, 1, 152064, 0xd9398539 -0, 26, 26, 1, 152064, 0xd7aec2c4 +0, 26, 26, 1, 152064, 0x07aec13a 0, 27, 27, 1, 152064, 0xa6ef9440 -0, 28, 28, 1, 152064, 0xc289b278 +0, 28, 28, 1, 152064, 0x0e7ab64e 0, 29, 29, 1, 152064, 0x3796939d -0, 30, 30, 1, 152064, 0x48c09366 +0, 30, 30, 1, 152064, 0xcc219365 0, 31, 31, 1, 152064, 0xf4cc815a -0, 32, 32, 1, 152064, 0x1c63cdc2 +0, 32, 32, 1, 152064, 0x8b91c622 0, 33, 33, 1, 152064, 0xd3a8ad8e -0, 34, 34, 1, 152064, 0x70f94bc0 +0, 34, 34, 1, 152064, 0x658e498f 0, 35, 35, 1, 152064, 0xf9c115ea -0, 36, 36, 1, 152064, 0x44a2f607 +0, 36, 36, 1, 152064, 0xb639f8d2 0, 37, 37, 1, 152064, 0x7e9eaa64 -0, 38, 38, 1, 152064, 0x37b86b68 +0, 38, 38, 1, 152064, 0x8a546bcf 0, 39, 39, 1, 152064, 0x59d22dd4 -0, 40, 40, 1, 152064, 0x5d0d0e8d +0, 40, 40, 1, 152064, 0x80a10edc 0, 41, 41, 1, 152064, 0x5c97d4a1 -0, 42, 42, 1, 152064, 0xd44ef54d +0, 42, 42, 1, 152064, 0x4f1bf025 0, 43, 43, 1, 152064, 0x42721789 -0, 44, 44, 1, 152064, 0x27597277 +0, 44, 44, 1, 152064, 0x39e6700d 0, 45, 45, 1, 152064, 0xdf4af8b4 -0, 46, 46, 1, 152064, 0x5df7390c +0, 46, 46, 1, 152064, 0xacf839bb 0, 47, 47, 1, 152064, 0xbebfbf7c -0, 48, 48, 1, 152064, 0x753959bb +0, 48, 48, 1, 152064, 0x09c7630d 0, 49, 49, 1, 152064, 0x3331ab18 -0, 50, 50, 1, 152064, 0xec4a0f33 +0, 50, 50, 1, 152064, 0xae0f0f28 0, 51, 51, 1, 152064, 0xbb085737 -0, 52, 52, 1, 152064, 0x3938abf4 +0, 52, 52, 1, 152064, 0x1e23ad39 0, 53, 53, 1, 152064, 0x18d46683 -0, 54, 54, 1, 152064, 0xb12ace0c +0, 54, 54, 1, 152064, 0x4eadd0a0 0, 55, 55, 1, 152064, 0x09b13430 -0, 56, 56, 1, 152064, 0x85bd5e88 +0, 56, 56, 1, 152064, 0x240a607b 0, 57, 57, 1, 152064, 0xec0f8a67 -0, 58, 58, 1, 152064, 0x51a4fc74 +0, 58, 58, 1, 152064, 0x6c37fc08 0, 59, 59, 1, 152064, 0xded4cda7 -0, 60, 60, 1, 152064, 0xb69412a9 +0, 60, 60, 1, 152064, 0xc5df1477 0, 61, 61, 1, 152064, 0x3c9de6f9 -0, 62, 62, 1, 152064, 0x223fcc41 +0, 62, 62, 1, 152064, 0xefd1cdbd 0, 63, 63, 1, 152064, 0x5df7b89c -0, 64, 64, 1, 152064, 0x1e58b37a +0, 64, 64, 1, 152064, 0x1b04af5f 0, 65, 65, 1, 152064, 0xbbff2c09 -0, 66, 66, 1, 152064, 0x4e0f4d4a +0, 66, 66, 1, 152064, 0x23b04553 0, 67, 67, 1, 152064, 0x3d99caa3 -0, 68, 68, 1, 152064, 0xcc329c2f +0, 68, 68, 1, 152064, 0x35139bf8 0, 69, 69, 1, 152064, 0x49207c0a -0, 70, 70, 1, 152064, 0x489f2d50 +0, 70, 70, 1, 152064, 0xa78e2efa 0, 71, 71, 1, 152064, 0x5a50b0df -0, 72, 72, 1, 152064, 0x509eb79e +0, 72, 72, 1, 152064, 0x3255b306 0, 73, 73, 1, 152064, 0x60622c61 0, 74, 74, 1, 152064, 0x8c8cde9f 0, 75, 75, 1, 152064, 0xe8c0bb6c -0, 76, 76, 1, 152064, 0xb03581b6 +0, 76, 76, 1, 152064, 0xbc698473 0, 77, 77, 1, 152064, 0x398525c2 0, 78, 78, 1, 152064, 0x87983ab0 0, 79, 79, 1, 152064, 0x032af6b5 -0, 80, 80, 1, 152064, 0x7434baa4 +0, 80, 80, 1, 152064, 0x4878bb11 0, 81, 81, 1, 152064, 0xff5dd044 -0, 82, 82, 1, 152064, 0x45b2bb36 +0, 82, 82, 1, 152064, 0xe675bfe0 0, 83, 83, 1, 152064, 0x1af29008 0, 84, 84, 1, 152064, 0x07aa8975 0, 85, 85, 1, 152064, 0x17957756 0, 86, 86, 1, 152064, 0x48b5825e 0, 87, 87, 1, 152064, 0x169d70bc -0, 88, 88, 1, 152064, 0x803b30c6 +0, 88, 88, 1, 152064, 0x326730c8 0, 89, 89, 1, 152064, 0x6158c971 -0, 90, 90, 1, 152064, 0xb126e53e +0, 90, 90, 1, 152064, 0x1035e3ee 0, 91, 91, 1, 152064, 0xef49ba53 -0, 92, 92, 1, 152064, 0xfcfd7f17 +0, 92, 92, 1, 152064, 0x261081fa 0, 93, 93, 1, 152064, 0x5280779e -0, 94, 94, 1, 152064, 0x638d6f48 +0, 94, 94, 1, 152064, 0x8a6d6df3 0, 95, 95, 1, 152064, 0xdb0f1ed5 -0, 96, 96, 1, 152064, 0x2cb959b0 +0, 96, 96, 1, 152064, 0x5162570a 0, 97, 97, 1, 152064, 0x0841547c -0, 98, 98, 1, 152064, 0x412a555b +0, 98, 98, 1, 152064, 0xf0694fcd 0, 99, 99, 1, 152064, 0xfe525057 -0, 100, 100, 1, 152064, 0xa8cf0cbc +0, 100, 100, 1, 152064, 0xb4ec0c96 0, 101, 101, 1, 152064, 0xbf2dcaee -0, 102, 102, 1, 152064, 0x636cc494 +0, 102, 102, 1, 152064, 0x7860c418 0, 103, 103, 1, 152064, 0xc9e288bc -0, 104, 104, 1, 152064, 0xe77f4d03 +0, 104, 104, 1, 152064, 0xb0514dc3 0, 105, 105, 1, 152064, 0x722a4bd0 -0, 106, 106, 1, 152064, 0x5271f5ef +0, 106, 106, 1, 152064, 0x5277f52d 0, 107, 107, 1, 152064, 0x05208e75 -0, 108, 108, 1, 152064, 0xb8845f88 +0, 108, 108, 1, 152064, 0x0b596089 0, 109, 109, 1, 152064, 0x47aa117c -0, 110, 110, 1, 152064, 0xe695fe27 +0, 110, 110, 1, 152064, 0x12edfe8b 0, 111, 111, 1, 152064, 0x2e50f864 -0, 112, 112, 1, 152064, 0x52d2b719 +0, 112, 112, 1, 152064, 0x4cedb882 0, 113, 113, 1, 152064, 0xdbf48285 -0, 114, 114, 1, 152064, 0xe0b2ba93 +0, 114, 114, 1, 152064, 0x9071b0e6 0, 115, 115, 1, 152064, 0x1c85a5ce 0, 116, 116, 1, 152064, 0x8ef9a8e8 0, 117, 117, 1, 152064, 0x41e8ae26 0, 118, 118, 1, 152064, 0x3328d571 0, 119, 119, 1, 152064, 0xce7d4da2 -0, 120, 120, 1, 152064, 0x7a6f7416 +0, 120, 120, 1, 152064, 0x032d7575 0, 121, 121, 1, 152064, 0xb3fc65a6 -0, 122, 122, 1, 152064, 0xc5a261e9 +0, 122, 122, 1, 152064, 0xe5a266b4 0, 123, 123, 1, 152064, 0x943c5925 -0, 124, 124, 1, 152064, 0x259180b2 +0, 124, 124, 1, 152064, 0xe6138024 0, 125, 125, 1, 152064, 0x3acd4e1b -0, 126, 126, 1, 152064, 0x692090b4 +0, 126, 126, 1, 152064, 0x9de7903e 0, 127, 127, 1, 152064, 0xea1184d0 -0, 128, 128, 1, 152064, 0x3e0038d5 +0, 128, 128, 1, 152064, 0x9e323818 0, 129, 129, 1, 152064, 0xf77872a2 -0, 130, 130, 1, 152064, 0xe4cb7bb5 +0, 130, 130, 1, 152064, 0x8f7c75c7 0, 131, 131, 1, 152064, 0x9d6d2623 -0, 132, 132, 1, 152064, 0xb9056247 +0, 132, 132, 1, 152064, 0x3d8e62ab 0, 133, 133, 1, 152064, 0xcd8b3dc5 -0, 134, 134, 1, 152064, 0x13ea1b6d +0, 134, 134, 1, 152064, 0x57681ebc 0, 135, 135, 1, 152064, 0x764f3233 -0, 136, 136, 1, 152064, 0x54c00ba8 +0, 136, 136, 1, 152064, 0x8c8b0a4b 0, 137, 137, 1, 152064, 0x2d9aedac -0, 138, 138, 1, 152064, 0x1af00532 +0, 138, 138, 1, 152064, 0x0afe03ae 0, 139, 139, 1, 152064, 0xcecae31b 0, 140, 140, 1, 152064, 0x0e6ea17f 0, 141, 141, 1, 152064, 0x66b0b8c4 -0, 142, 142, 1, 152064, 0x0ee879bb +0, 142, 142, 1, 152064, 0xd44f7976 0, 143, 143, 1, 152064, 0xf7f029cc -0, 144, 144, 1, 152064, 0xdd5d08d6 +0, 144, 144, 1, 152064, 0xada307a9 0, 145, 145, 1, 152064, 0x936ae367 -0, 146, 146, 1, 152064, 0xf0f4aba0 +0, 146, 146, 1, 152064, 0xa019ad8a 0, 147, 147, 1, 152064, 0x5233a9e7 -0, 148, 148, 1, 152064, 0x02af732b +0, 148, 148, 1, 152064, 0x6fd5737f 0, 149, 149, 1, 152064, 0xb2eb2476 -0, 150, 150, 1, 152064, 0x998732b4 +0, 150, 150, 1, 152064, 0x36a53280 0, 151, 151, 1, 152064, 0xf025230f -0, 152, 152, 1, 152064, 0x474f3b12 +0, 152, 152, 1, 152064, 0x48373a3e 0, 153, 153, 1, 152064, 0xe4e950e2 -0, 154, 154, 1, 152064, 0xa3f87fb3 +0, 154, 154, 1, 152064, 0x63d37fc4 0, 155, 155, 1, 152064, 0x1e465fda -0, 156, 156, 1, 152064, 0x9e8caab2 +0, 156, 156, 1, 152064, 0xc47ea97e 0, 157, 157, 1, 152064, 0x0224aca7 -0, 158, 158, 1, 152064, 0x24fcec49 +0, 158, 158, 1, 152064, 0x909dedcc 0, 159, 159, 1, 152064, 0x1c1df7ea -0, 160, 160, 1, 152064, 0xc466f68f +0, 160, 160, 1, 152064, 0x5e43f7f1 0, 161, 161, 1, 152064, 0xdb11d8fa -0, 162, 162, 1, 152064, 0xa0f61157 +0, 162, 162, 1, 152064, 0xa66710f5 0, 163, 163, 1, 152064, 0x352013b0 -0, 164, 164, 1, 152064, 0xc14243c7 +0, 164, 164, 1, 152064, 0xc8e745f1 0, 165, 165, 1, 152064, 0xb18b6810 -0, 166, 166, 1, 152064, 0x040942e6 +0, 166, 166, 1, 152064, 0xb1c243e2 0, 167, 167, 1, 152064, 0x6fe129f9 -0, 168, 168, 1, 152064, 0xc3d64c5f +0, 168, 168, 1, 152064, 0x92814bde 0, 169, 169, 1, 152064, 0x50954752 -0, 170, 170, 1, 152064, 0xa4d24c64 +0, 170, 170, 1, 152064, 0x48634df3 0, 171, 171, 1, 152064, 0x3af254c0 0, 172, 172, 1, 152064, 0x6fde4801 0, 173, 173, 1, 152064, 0xf8fe19b4 -0, 174, 174, 1, 152064, 0x97b34958 +0, 174, 174, 1, 152064, 0x57004906 0, 175, 175, 1, 152064, 0x916e2ff4 -0, 176, 176, 1, 152064, 0x60c528e2 +0, 176, 176, 1, 152064, 0xbc0d28f0 0, 177, 177, 1, 152064, 0x4522435e 0, 178, 178, 1, 152064, 0x861f5d1b 0, 179, 179, 1, 152064, 0x42c3bf28 -0, 180, 180, 1, 152064, 0x9772db11 +0, 180, 180, 1, 152064, 0xbd6adb19 0, 181, 181, 1, 152064, 0x0692f5b8 -0, 182, 182, 1, 152064, 0xb06b4aed +0, 182, 182, 1, 152064, 0x1e1e4bfb 0, 183, 183, 1, 152064, 0xdc852986 -0, 184, 184, 1, 152064, 0xa7a025fb +0, 184, 184, 1, 152064, 0x61c5259e 0, 185, 185, 1, 152064, 0xe28f365a -0, 186, 186, 1, 152064, 0xcbf3830e +0, 186, 186, 1, 152064, 0x19388308 0, 187, 187, 1, 152064, 0x043bace9 -0, 188, 188, 1, 152064, 0x5dd0b5df +0, 188, 188, 1, 152064, 0x4bebb678 0, 189, 189, 1, 152064, 0x6bd6d112 -0, 190, 190, 1, 152064, 0xa585ceb6 +0, 190, 190, 1, 152064, 0x3c9dc401 0, 191, 191, 1, 152064, 0x91e7556a -0, 192, 192, 1, 152064, 0x8f2a0404 +0, 192, 192, 1, 152064, 0xae60f7e7 0, 193, 193, 1, 152064, 0x14066893 -0, 194, 194, 1, 152064, 0x8f715862 +0, 194, 194, 1, 152064, 0x7f5a5f0a 0, 195, 195, 1, 152064, 0xb1063958 -0, 196, 196, 1, 152064, 0x014c40f0 +0, 196, 196, 1, 152064, 0xadf13b9f 0, 197, 197, 1, 152064, 0x7ddcf94d -0, 198, 198, 1, 152064, 0x25473a22 +0, 198, 198, 1, 152064, 0x91393730 0, 199, 199, 1, 152064, 0xcd150536 -0, 200, 200, 1, 152064, 0x2d24d974 +0, 200, 200, 1, 152064, 0x52e0d7bd 0, 201, 201, 1, 152064, 0x9130b2ce -0, 202, 202, 1, 152064, 0x9450a62a +0, 202, 202, 1, 152064, 0xa07fa62a 0, 203, 203, 1, 152064, 0x7da258cd -0, 204, 204, 1, 152064, 0x6c2770de +0, 204, 204, 1, 152064, 0x984071a6 0, 205, 205, 1, 152064, 0xd5fa731a -0, 206, 206, 1, 152064, 0x93757c14 +0, 206, 206, 1, 152064, 0x593d7910 0, 207, 207, 1, 152064, 0x4b754c71 0, 208, 208, 1, 152064, 0x51544841 0, 209, 209, 1, 152064, 0xf466910e -0, 210, 210, 1, 152064, 0xe818c675 +0, 210, 210, 1, 152064, 0x6535c9c4 0, 211, 211, 1, 152064, 0x6d45b6d8 -0, 212, 212, 1, 152064, 0xa3de9aec +0, 212, 212, 1, 152064, 0xe77998a2 0, 213, 213, 1, 152064, 0x56023275 -0, 214, 214, 1, 152064, 0xa1af21cb +0, 214, 214, 1, 152064, 0x779b20cc 0, 215, 215, 1, 152064, 0x1ff1b05e -0, 216, 216, 1, 152064, 0x142ecbdb +0, 216, 216, 1, 152064, 0xb9e2c3f0 0, 217, 217, 1, 152064, 0xdfc6d541 -0, 218, 218, 1, 152064, 0x8d8f7a4c +0, 218, 218, 1, 152064, 0x301a7948 0, 219, 219, 1, 152064, 0x03d611ca -0, 220, 220, 1, 152064, 0x999e6d3f +0, 220, 220, 1, 152064, 0xe9426f2a 0, 221, 221, 1, 152064, 0x304c95df -0, 222, 222, 1, 152064, 0xbdcff306 +0, 222, 222, 1, 152064, 0x60e7f924 0, 223, 223, 1, 152064, 0x6408670c -0, 224, 224, 1, 152064, 0xa6d4d038 +0, 224, 224, 1, 152064, 0xbf09ca74 0, 225, 225, 1, 152064, 0xf2d13572 -0, 226, 226, 1, 152064, 0x2fa8b357 +0, 226, 226, 1, 152064, 0x90ccb47d 0, 227, 227, 1, 152064, 0x24bbd269 -0, 228, 228, 1, 152064, 0x23dd31f2 +0, 228, 228, 1, 152064, 0x7ae333dd 0, 229, 229, 1, 152064, 0x90913fe2 -0, 230, 230, 1, 152064, 0x855efbca +0, 230, 230, 1, 152064, 0xc994007c 0, 231, 231, 1, 152064, 0x45a123c0 -0, 232, 232, 1, 152064, 0xec465cb2 +0, 232, 232, 1, 152064, 0xa0335bbf 0, 233, 233, 1, 152064, 0x3e79c4e9 -0, 234, 234, 1, 152064, 0xaeac4476 +0, 234, 234, 1, 152064, 0x05cf4479 0, 235, 235, 1, 152064, 0x2146392c -0, 236, 236, 1, 152064, 0x7a186239 +0, 236, 236, 1, 152064, 0x68ac5d0a 0, 237, 237, 1, 152064, 0x9d26fed8 -0, 238, 238, 1, 152064, 0x88f090ba +0, 238, 238, 1, 152064, 0x047c9082 0, 239, 239, 1, 152064, 0x518bd9f8 -0, 240, 240, 1, 152064, 0x70013bdd +0, 240, 240, 1, 152064, 0xfbd03b16 0, 241, 241, 1, 152064, 0x5317601a -0, 242, 242, 1, 152064, 0x97e91795 +0, 242, 242, 1, 152064, 0x450118c5 0, 243, 243, 1, 152064, 0x1058915b -0, 244, 244, 1, 152064, 0x3549ffeb +0, 244, 244, 1, 152064, 0x0a4a000a 0, 245, 245, 1, 152064, 0xa277707d -0, 246, 246, 1, 152064, 0xdcb6287d +0, 246, 246, 1, 152064, 0xc7cb29b2 0, 247, 247, 1, 152064, 0x371344fc -0, 248, 248, 1, 152064, 0xb7ea75c7 +0, 248, 248, 1, 152064, 0xbc9375a9 0, 249, 249, 1, 152064, 0x70c2fa2f -0, 250, 250, 1, 152064, 0x8dbec050 +0, 250, 250, 1, 152064, 0x41fbc057 0, 251, 251, 1, 152064, 0xc21a77fe -0, 252, 252, 1, 152064, 0xf7c7678e +0, 252, 252, 1, 152064, 0x51e06384 0, 253, 253, 1, 152064, 0xbee83fcb -0, 254, 254, 1, 152064, 0x6627efd7 +0, 254, 254, 1, 152064, 0xce2befdf 0, 255, 255, 1, 152064, 0x4f139865 -0, 256, 256, 1, 152064, 0x76fa5435 +0, 256, 256, 1, 152064, 0x4e0f5372 0, 257, 257, 1, 152064, 0xf0701fd6 -0, 258, 258, 1, 152064, 0x153e3763 +0, 258, 258, 1, 152064, 0x746c35f4 0, 259, 259, 1, 152064, 0xf5211469 -0, 260, 260, 1, 152064, 0xc19d24b8 +0, 260, 260, 1, 152064, 0xae8f1c2f 0, 261, 261, 1, 152064, 0xc2483a75 -0, 262, 262, 1, 152064, 0x67a149ee +0, 262, 262, 1, 152064, 0x2da24ae6 0, 263, 263, 1, 152064, 0x86f70e3a -0, 264, 264, 1, 152064, 0x281b166b +0, 264, 264, 1, 152064, 0x52b8172a 0, 265, 265, 1, 152064, 0xca810f3b -0, 266, 266, 1, 152064, 0x91c90741 +0, 266, 266, 1, 152064, 0x6d9504c4 0, 267, 267, 1, 152064, 0x4edcfbfa -0, 268, 268, 1, 152064, 0x0ca40c66 +0, 268, 268, 1, 152064, 0x292c0bfd 0, 269, 269, 1, 152064, 0xee998e3d 0, 270, 270, 1, 152064, 0xe4b6c1b2 0, 271, 271, 1, 152064, 0xbbe0a4cc -0, 272, 272, 1, 152064, 0xd080bcfd +0, 272, 272, 1, 152064, 0xcd88bcf2 0, 273, 273, 1, 152064, 0x365df7c5 -0, 274, 274, 1, 152064, 0x934f071f +0, 274, 274, 1, 152064, 0x01cd06a4 0, 275, 275, 1, 152064, 0xcfaefeef -0, 276, 276, 1, 152064, 0xedd8263e +0, 276, 276, 1, 152064, 0xe615289d 0, 277, 277, 1, 152064, 0x1d5243de -0, 278, 278, 1, 152064, 0xc0d87e50 +0, 278, 278, 1, 152064, 0x7c397dfe 0, 279, 279, 1, 152064, 0xe25845b1 -0, 280, 280, 1, 152064, 0x47006123 +0, 280, 280, 1, 152064, 0x2d6a60a8 0, 281, 281, 1, 152064, 0xf1926203 -0, 282, 282, 1, 152064, 0x494b8b9c +0, 282, 282, 1, 152064, 0x634a88c9 0, 283, 283, 1, 152064, 0xc50aa1b7 -0, 284, 284, 1, 152064, 0xb82da5e2 +0, 284, 284, 1, 152064, 0x972fa713 0, 285, 285, 1, 152064, 0xa11cd0f6 -0, 286, 286, 1, 152064, 0x7ebff98d +0, 286, 286, 1, 152064, 0xbff8f90e 0, 287, 287, 1, 152064, 0x00902e76 -0, 288, 288, 1, 152064, 0xdee41ea2 +0, 288, 288, 1, 152064, 0x5cf31cb1 0, 289, 289, 1, 152064, 0x2b026058 -0, 290, 290, 1, 152064, 0xce81051f +0, 290, 290, 1, 152064, 0x258002cc 0, 291, 291, 1, 152064, 0x0d708815 -0, 292, 292, 1, 152064, 0xd7719e35 +0, 292, 292, 1, 152064, 0xe3809ce0 0, 293, 293, 1, 152064, 0xf0239467 -0, 294, 294, 1, 152064, 0x466d98b4 +0, 294, 294, 1, 152064, 0x6e71916a 0, 295, 295, 1, 152064, 0xc1fb36e1 -0, 296, 296, 1, 152064, 0x26bc139e +0, 296, 296, 1, 152064, 0xd47f07c9 0, 297, 297, 1, 152064, 0x7fd111ea -0, 298, 298, 1, 152064, 0xa39737cb +0, 298, 298, 1, 152064, 0xc4023a80 0, 299, 299, 1, 152064, 0x8f5851ba -0, 300, 300, 1, 152064, 0xa971f6e2 +0, 300, 300, 1, 152064, 0x9982f47b 0, 301, 301, 1, 152064, 0x0e5f6f80 -0, 302, 302, 1, 152064, 0xdb8b5e06 +0, 302, 302, 1, 152064, 0x49925e53 0, 303, 303, 1, 152064, 0xf6006bcc -0, 304, 304, 1, 152064, 0x060cd1a6 +0, 304, 304, 1, 152064, 0xd4b5d0f7 0, 305, 305, 1, 152064, 0x419ef0a4 -0, 306, 306, 1, 152064, 0xe79f0b93 +0, 306, 306, 1, 152064, 0x4e610934 0, 307, 307, 1, 152064, 0x1919e999 -0, 308, 308, 1, 152064, 0xacb715bc +0, 308, 308, 1, 152064, 0x3a750d80 0, 309, 309, 1, 152064, 0x16616075 -0, 310, 310, 1, 152064, 0x09aa4f10 +0, 310, 310, 1, 152064, 0x3284519f 0, 311, 311, 1, 152064, 0x976cdd70 -0, 312, 312, 1, 152064, 0x4811dc21 +0, 312, 312, 1, 152064, 0x4ec5d1e3 0, 313, 313, 1, 152064, 0x30d31172 -0, 314, 314, 1, 152064, 0x2db60b70 +0, 314, 314, 1, 152064, 0xe33609b5 0, 315, 315, 1, 152064, 0x5377bb89 -0, 316, 316, 1, 152064, 0x6c20cab3 +0, 316, 316, 1, 152064, 0x5479cd3d 0, 317, 317, 1, 152064, 0x964dad60 -0, 318, 318, 1, 152064, 0x514df2c3 +0, 318, 318, 1, 152064, 0x3a7deaf4 0, 319, 319, 1, 152064, 0xced22332 -0, 320, 320, 1, 152064, 0x1c64bc82 +0, 320, 320, 1, 152064, 0x3b36b53f 0, 321, 321, 1, 152064, 0x10c38662 -0, 322, 322, 1, 152064, 0xe6c7ff46 +0, 322, 322, 1, 152064, 0x45d4fceb 0, 323, 323, 1, 152064, 0x359da948 -0, 324, 324, 1, 152064, 0x5a9458ee +0, 324, 324, 1, 152064, 0x60625190 0, 325, 325, 1, 152064, 0x1cda9888 -0, 326, 326, 1, 152064, 0xbd081682 +0, 326, 326, 1, 152064, 0x77ad1d8c 0, 327, 327, 1, 152064, 0x20f1510f -0, 328, 328, 1, 152064, 0x6bc261a9 +0, 328, 328, 1, 152064, 0xd11d52c6 0, 329, 329, 1, 152064, 0x9f0e5797 -0, 330, 330, 1, 152064, 0xd14ca712 +0, 330, 330, 1, 152064, 0x174ca55b 0, 331, 331, 1, 152064, 0x8df79054 -0, 332, 332, 1, 152064, 0x34efa950 +0, 332, 332, 1, 152064, 0x3844a495 0, 333, 333, 1, 152064, 0x268d9d12 -0, 334, 334, 1, 152064, 0xad91b2ed +0, 334, 334, 1, 152064, 0xf672b44f 0, 335, 335, 1, 152064, 0xe0ac87cf -0, 336, 336, 1, 152064, 0xba4cfd8e +0, 336, 336, 1, 152064, 0xbc99fd7d 0, 337, 337, 1, 152064, 0x876ef9e3 -0, 338, 338, 1, 152064, 0x45ab6684 +0, 338, 338, 1, 152064, 0xef8066f7 0, 339, 339, 1, 152064, 0x72a99564 -0, 340, 340, 1, 152064, 0xdfc8be01 +0, 340, 340, 1, 152064, 0x5921c088 0, 341, 341, 1, 152064, 0x3a6b9e74 -0, 342, 342, 1, 152064, 0xca1be9c6 +0, 342, 342, 1, 152064, 0xfb03e9b5 0, 343, 343, 1, 152064, 0xc351bfc6 -0, 344, 344, 1, 152064, 0xef30c978 +0, 344, 344, 1, 152064, 0x2faec717 0, 345, 345, 1, 152064, 0x062fc6f3 -0, 346, 346, 1, 152064, 0x8731a9ec +0, 346, 346, 1, 152064, 0xede7a97f 0, 347, 347, 1, 152064, 0x19874144 0, 348, 348, 1, 152064, 0x929650eb 0, 349, 349, 1, 152064, 0x082557a1 -0, 350, 350, 1, 152064, 0xb80510ae +0, 350, 350, 1, 152064, 0x2b25104b From 0fb33a82890753233225c61863fff1fcc9d970d4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 3 Feb 2018 18:49:07 +0100 Subject: [PATCH 1841/2557] avcodec/scpr: Fix reading a pixel before the first Fixes: 5540/clusterfuzz-testcase-minimized-6122458273808384 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/scpr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/scpr.c b/libavcodec/scpr.c index cbe1bc40d9c81..ad6073dbf0118 100644 --- a/libavcodec/scpr.c +++ b/libavcodec/scpr.c @@ -681,6 +681,8 @@ static int decompress_p(AVCodecContext *avctx, return AVERROR_INVALIDDATA; if (bx == 0) { + if (by < 2) + return AVERROR_INVALIDDATA; z = backstep; } else { z = 0; @@ -710,6 +712,8 @@ static int decompress_p(AVCodecContext *avctx, return AVERROR_INVALIDDATA; if (bx == 0) { + if (by < 2) + return AVERROR_INVALIDDATA; z = backstep; } else { z = 0; From 66acb630286cf1bf03bfbdab6c7c784ff20bde61 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 4 Feb 2018 02:14:49 +0100 Subject: [PATCH 1842/2557] avcodec/pafvideo: Check allocated frame size Fixes: OOM Fixes: 5549/clusterfuzz-testcase-minimized-5390553567985664 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/pafvideo.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/pafvideo.c b/libavcodec/pafvideo.c index 6980ae1b352be..7c5861dfaf6c6 100644 --- a/libavcodec/pafvideo.c +++ b/libavcodec/pafvideo.c @@ -78,6 +78,7 @@ static av_cold int paf_video_init(AVCodecContext *avctx) { PAFVideoDecContext *c = avctx->priv_data; int i; + int ret; c->width = avctx->width; c->height = avctx->height; @@ -90,6 +91,9 @@ static av_cold int paf_video_init(AVCodecContext *avctx) } avctx->pix_fmt = AV_PIX_FMT_PAL8; + ret = av_image_check_size2(avctx->width, FFALIGN(avctx->height, 256), avctx->max_pixels, avctx->pix_fmt, 0, avctx); + if (ret < 0) + return ret; c->pic = av_frame_alloc(); if (!c->pic) From 76cc0f0f673353cd4746cd3b83838ae335e5d9ed Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 9 Feb 2018 15:27:41 +0100 Subject: [PATCH 1843/2557] avcodec/utvideodec: Add several out of array read related checks Fixes: OV_decode_plane.avi Found-by: GwanYeong Kim Signed-off-by: Michael Niedermayer --- libavcodec/utvideodec.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 1bcd14e74c69f..c5f553496430d 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -268,6 +268,9 @@ static int decode_plane(UtvideoContext *c, int plane_no, send = (height * (slice + 1) / c->slices) & cmask; dest = dst + sstart * stride; + if (3 * ((dst + send * stride - dest + 7)/8) > get_bits_left(&cbit)) + return AVERROR_INVALIDDATA; + for (p = dest; p < dst + send * stride; p += 8) { int bits = get_bits_le(&cbit, 3); @@ -277,6 +280,9 @@ static int decode_plane(UtvideoContext *c, int plane_no, uint32_t sub = 0x80 >> (8 - (bits + 1)), add; int k; + if ((bits + 1) * 8 > get_bits_left(&pbit)) + return AVERROR_INVALIDDATA; + for (k = 0; k < 8; k++) { p[k] = get_bits_le(&pbit, bits + 1); @@ -639,9 +645,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, for (j = 0; j < c->slices; j++) { c->packed_stream[i][j] = packed_stream; c->packed_stream_size[i][j] = bytestream2_get_le32(&pb); - left -= c->packed_stream_size[i][j]; - if (left < 0) + if (c->packed_stream_size[i][j] > left) return AVERROR_INVALIDDATA; + left -= c->packed_stream_size[i][j]; packed_stream += c->packed_stream_size[i][j]; } } @@ -652,9 +658,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, for (j = 0; j < c->slices; j++) { c->control_stream[i][j] = control_stream; c->control_stream_size[i][j] = bytestream2_get_le32(&pb); - left -= c->control_stream_size[i][j]; - if (left < 0) + if (c->control_stream_size[i][j] > left) return AVERROR_INVALIDDATA; + left -= c->control_stream_size[i][j]; control_stream += c->control_stream_size[i][j]; } } From 570023eab3e2962b4ad8345a157c1e18ca1a6eca Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 9 Feb 2018 04:17:16 +0100 Subject: [PATCH 1844/2557] avcodec/vp3: Check eob_run Fixes: out of array access Fixes: 5919/clusterfuzz-testcase-minimized-5859311382167552 Fixes: special case for theora (untested due to lack of sample) Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/vp3.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index cf9c57f5faa62..33be345c144bd 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -978,6 +978,9 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb, if (eob_run_get_bits[token]) eob_run += get_bits(gb, eob_run_get_bits[token]); + if (!eob_run) + eob_run = INT_MAX; + // record only the number of blocks ended in this plane, // any spill will be recorded in the next plane. if (eob_run > num_coeffs - coeff_i) { From f4d5d7e8de189ab448a5e662245b57ceb8f20df6 Mon Sep 17 00:00:00 2001 From: Nekopanda Date: Sun, 11 Feb 2018 17:15:54 +0900 Subject: [PATCH 1845/2557] avcodec/mpeg2dec: Fix motion vector rounding for chroma components In 16x8 motion compensation, for lower 16x8 region, the input to mpeg_motion() for motion_y was "motion_y + 16", which causes wrong rounding. For 4:2:0, chroma scaling for y is dividing by two and rounding toward zero. When motion_y < 0 and motion_y + 16 > 0, the rounding direction of "motion_y" and "motion_y + 16" is different and rounding "motion_y + 16" would be incorrect. We should input "motion_y" as is to round correctly. I add "is_16x8" flag to do that. Signed-off-by: Michael Niedermayer --- libavcodec/mpegvideo_motion.c | 30 +++---- tests/ref/fate/filter-mcdeint-fast | 60 +++++++------- tests/ref/fate/filter-mcdeint-medium | 60 +++++++------- tests/ref/fate/filter-w3fdif-complex | 60 +++++++------- tests/ref/fate/filter-w3fdif-simple | 60 +++++++------- tests/ref/fate/filter-yadif-mode0 | 60 +++++++------- tests/ref/fate/filter-yadif-mode1 | 118 +++++++++++++-------------- tests/ref/fate/filter-yadif10 | 60 +++++++------- tests/ref/fate/filter-yadif16 | 60 +++++++------- tests/ref/fate/mpeg2-field-enc | 60 +++++++------- tests/ref/fate/mpeg2-ticket6677 | 12 +-- 11 files changed, 321 insertions(+), 319 deletions(-) diff --git a/libavcodec/mpegvideo_motion.c b/libavcodec/mpegvideo_motion.c index c913504a657f2..5624c1062974c 100644 --- a/libavcodec/mpegvideo_motion.c +++ b/libavcodec/mpegvideo_motion.c @@ -239,20 +239,22 @@ void mpeg_motion_internal(MpegEncContext *s, int motion_y, int h, int is_mpeg12, + int is_16x8, int mb_y) { uint8_t *ptr_y, *ptr_cb, *ptr_cr; int dxy, uvdxy, mx, my, src_x, src_y, - uvsrc_x, uvsrc_y, v_edge_pos; + uvsrc_x, uvsrc_y, v_edge_pos, block_y_half; ptrdiff_t uvlinesize, linesize; v_edge_pos = s->v_edge_pos >> field_based; linesize = s->current_picture.f->linesize[0] << field_based; uvlinesize = s->current_picture.f->linesize[1] << field_based; + block_y_half = (field_based | is_16x8); dxy = ((motion_y & 1) << 1) | (motion_x & 1); src_x = s->mb_x * 16 + (motion_x >> 1); - src_y = (mb_y << (4 - field_based)) + (motion_y >> 1); + src_y = (mb_y << (4 - block_y_half)) + (motion_y >> 1); if (!is_mpeg12 && s->out_format == FMT_H263) { if ((s->workaround_bugs & FF_BUG_HPEL_CHROMA) && field_based) { @@ -260,7 +262,7 @@ void mpeg_motion_internal(MpegEncContext *s, my = motion_y >> 1; uvdxy = ((my & 1) << 1) | (mx & 1); uvsrc_x = s->mb_x * 8 + (mx >> 1); - uvsrc_y = (mb_y << (3 - field_based)) + (my >> 1); + uvsrc_y = (mb_y << (3 - block_y_half)) + (my >> 1); } else { uvdxy = dxy | (motion_y & 2) | ((motion_x & 2) >> 1); uvsrc_x = src_x >> 1; @@ -279,7 +281,7 @@ void mpeg_motion_internal(MpegEncContext *s, my = motion_y / 2; uvdxy = ((my & 1) << 1) | (mx & 1); uvsrc_x = s->mb_x * 8 + (mx >> 1); - uvsrc_y = (mb_y << (3 - field_based)) + (my >> 1); + uvsrc_y = (mb_y << (3 - block_y_half)) + (my >> 1); } else { if (s->chroma_x_shift) { // Chroma422 @@ -370,18 +372,18 @@ static void mpeg_motion(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int field_select, uint8_t **ref_picture, op_pixels_func (*pix_op)[4], - int motion_x, int motion_y, int h, int mb_y) + int motion_x, int motion_y, int h, int is_16x8, int mb_y) { #if !CONFIG_SMALL if (s->out_format == FMT_MPEG1) mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 0, 0, field_select, ref_picture, pix_op, - motion_x, motion_y, h, 1, mb_y); + motion_x, motion_y, h, 1, is_16x8, mb_y); else #endif mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 0, 0, field_select, ref_picture, pix_op, - motion_x, motion_y, h, 0, mb_y); + motion_x, motion_y, h, 0, is_16x8, mb_y); } static void mpeg_motion_field(MpegEncContext *s, uint8_t *dest_y, @@ -395,12 +397,12 @@ static void mpeg_motion_field(MpegEncContext *s, uint8_t *dest_y, if (s->out_format == FMT_MPEG1) mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 1, bottom_field, field_select, ref_picture, pix_op, - motion_x, motion_y, h, 1, mb_y); + motion_x, motion_y, h, 1, 0, mb_y); else #endif mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 1, bottom_field, field_select, ref_picture, pix_op, - motion_x, motion_y, h, 0, mb_y); + motion_x, motion_y, h, 0, 0, mb_y); } // FIXME: SIMDify, avg variant, 16x16 version @@ -870,7 +872,7 @@ static av_always_inline void mpv_motion_internal(MpegEncContext *s, } else { mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, ref_picture, pix_op, - s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y); + s->mv[dir][0][0], s->mv[dir][0][1], 16, 0, mb_y); } break; case MV_TYPE_8X8: @@ -907,7 +909,7 @@ static av_always_inline void mpv_motion_internal(MpegEncContext *s, mpeg_motion(s, dest_y, dest_cb, dest_cr, s->field_select[dir][0], ref_picture, pix_op, - s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y >> 1); + s->mv[dir][0][0], s->mv[dir][0][1], 16, 0, mb_y >> 1); } break; case MV_TYPE_16X8: @@ -924,8 +926,8 @@ static av_always_inline void mpv_motion_internal(MpegEncContext *s, mpeg_motion(s, dest_y, dest_cb, dest_cr, s->field_select[dir][i], ref2picture, pix_op, - s->mv[dir][i][0], s->mv[dir][i][1] + 16 * i, - 8, mb_y >> 1); + s->mv[dir][i][0], s->mv[dir][i][1], + 8, 1, (mb_y & ~1) + i); dest_y += 16 * s->linesize; dest_cb += (16 >> s->chroma_y_shift) * s->uvlinesize; @@ -952,7 +954,7 @@ static av_always_inline void mpv_motion_internal(MpegEncContext *s, s->picture_structure != i + 1, ref_picture, pix_op, s->mv[dir][2 * i][0], s->mv[dir][2 * i][1], - 16, mb_y >> 1); + 16, 0, mb_y >> 1); // after put we make avg of the same block pix_op = s->hdsp.avg_pixels_tab; diff --git a/tests/ref/fate/filter-mcdeint-fast b/tests/ref/fate/filter-mcdeint-fast index 228be5e17d23e..e4c2f8a337895 100644 --- a/tests/ref/fate/filter-mcdeint-fast +++ b/tests/ref/fate/filter-mcdeint-fast @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x576 #sar 0: 16/15 -0, 9, 9, 1, 622080, 0xb3b66c5c -0, 10, 10, 1, 622080, 0xc6568bd7 -0, 11, 11, 1, 622080, 0xa5b543c3 -0, 12, 12, 1, 622080, 0x4095ac51 -0, 13, 13, 1, 622080, 0xccd8c1d9 -0, 14, 14, 1, 622080, 0x84a88f22 -0, 15, 15, 1, 622080, 0x7273c26b -0, 16, 16, 1, 622080, 0xac188c41 -0, 17, 17, 1, 622080, 0xf32f6fb4 -0, 18, 18, 1, 622080, 0xd696ccce -0, 19, 19, 1, 622080, 0x9778a418 -0, 20, 20, 1, 622080, 0xf2b5be2e -0, 21, 21, 1, 622080, 0x653ee12a -0, 22, 22, 1, 622080, 0xe7fce188 -0, 23, 23, 1, 622080, 0x6e9f1deb -0, 24, 24, 1, 622080, 0x33090aac -0, 25, 25, 1, 622080, 0x840a57f1 -0, 26, 26, 1, 622080, 0x635e430a -0, 27, 27, 1, 622080, 0x52f98809 -0, 28, 28, 1, 622080, 0xc567b6a5 -0, 29, 29, 1, 622080, 0x4134f583 -0, 30, 30, 1, 622080, 0xd02a73bc -0, 31, 31, 1, 622080, 0x763085d6 -0, 32, 32, 1, 622080, 0x77fdc7a6 -0, 33, 33, 1, 622080, 0x77f71b9f -0, 34, 34, 1, 622080, 0x71c91244 -0, 35, 35, 1, 622080, 0xc7b86da5 -0, 36, 36, 1, 622080, 0x1edf8890 -0, 37, 37, 1, 622080, 0x03c82bec -0, 38, 38, 1, 622080, 0x148b6a04 +0, 9, 9, 1, 622080, 0xff496bf5 +0, 10, 10, 1, 622080, 0x513c8bd9 +0, 11, 11, 1, 622080, 0x4e474368 +0, 12, 12, 1, 622080, 0x1248abe9 +0, 13, 13, 1, 622080, 0xa705c158 +0, 14, 14, 1, 622080, 0xf9048e95 +0, 15, 15, 1, 622080, 0x78b5c1a2 +0, 16, 16, 1, 622080, 0x0efa8be8 +0, 17, 17, 1, 622080, 0xd3396eac +0, 18, 18, 1, 622080, 0x5870cbdd +0, 19, 19, 1, 622080, 0x086fa311 +0, 20, 20, 1, 622080, 0x7ce9bced +0, 21, 21, 1, 622080, 0xe7e0e0e1 +0, 22, 22, 1, 622080, 0x5af3e14b +0, 23, 23, 1, 622080, 0xbf221d96 +0, 24, 24, 1, 622080, 0x43d90a62 +0, 25, 25, 1, 622080, 0x267a57b6 +0, 26, 26, 1, 622080, 0x88d942eb +0, 27, 27, 1, 622080, 0x34ff87bf +0, 28, 28, 1, 622080, 0xa849b5ec +0, 29, 29, 1, 622080, 0x8302f51f +0, 30, 30, 1, 622080, 0xac9e7315 +0, 31, 31, 1, 622080, 0x38b284fc +0, 32, 32, 1, 622080, 0x1ff0c6c4 +0, 33, 33, 1, 622080, 0x50bf1ba5 +0, 34, 34, 1, 622080, 0xe9bd1240 +0, 35, 35, 1, 622080, 0x22116da3 +0, 36, 36, 1, 622080, 0x6f3e887a +0, 37, 37, 1, 622080, 0x46b82bc5 +0, 38, 38, 1, 622080, 0xeaaf69ee diff --git a/tests/ref/fate/filter-mcdeint-medium b/tests/ref/fate/filter-mcdeint-medium index 05d1d722f8778..1b0261960e466 100644 --- a/tests/ref/fate/filter-mcdeint-medium +++ b/tests/ref/fate/filter-mcdeint-medium @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x576 #sar 0: 16/15 -0, 9, 9, 1, 622080, 0xb3b66c5c -0, 10, 10, 1, 622080, 0x26a29152 -0, 11, 11, 1, 622080, 0x787adddc -0, 12, 12, 1, 622080, 0xcc52df08 -0, 13, 13, 1, 622080, 0x53dad126 -0, 14, 14, 1, 622080, 0xe1448652 -0, 15, 15, 1, 622080, 0x159fd353 -0, 16, 16, 1, 622080, 0xcbe893a0 -0, 17, 17, 1, 622080, 0x43a67c6b -0, 18, 18, 1, 622080, 0xef30caf9 -0, 19, 19, 1, 622080, 0xa9cea62b -0, 20, 20, 1, 622080, 0x4c4cada1 -0, 21, 21, 1, 622080, 0x8e91f6de -0, 22, 22, 1, 622080, 0xb03ef044 -0, 23, 23, 1, 622080, 0x6b54262b -0, 24, 24, 1, 622080, 0x911e0cea -0, 25, 25, 1, 622080, 0x8320632c -0, 26, 26, 1, 622080, 0x2bde42b2 -0, 27, 27, 1, 622080, 0xe9d988c3 -0, 28, 28, 1, 622080, 0xa9f0b1db -0, 29, 29, 1, 622080, 0xb5bcf186 -0, 30, 30, 1, 622080, 0x469c6717 -0, 31, 31, 1, 622080, 0x2ca883e6 -0, 32, 32, 1, 622080, 0x4f5fba72 -0, 33, 33, 1, 622080, 0xa2e423ca -0, 34, 34, 1, 622080, 0xc1fb0aaf -0, 35, 35, 1, 622080, 0x96a879b8 -0, 36, 36, 1, 622080, 0x212e92e6 -0, 37, 37, 1, 622080, 0x9f26378a -0, 38, 38, 1, 622080, 0xdeaf77ab +0, 9, 9, 1, 622080, 0xff496bf5 +0, 10, 10, 1, 622080, 0xc0e4912c +0, 11, 11, 1, 622080, 0xa8aedd7e +0, 12, 12, 1, 622080, 0x2054deb9 +0, 13, 13, 1, 622080, 0x1005d0ca +0, 14, 14, 1, 622080, 0x60f085dc +0, 15, 15, 1, 622080, 0x4da0d261 +0, 16, 16, 1, 622080, 0x968e940e +0, 17, 17, 1, 622080, 0x86687b04 +0, 18, 18, 1, 622080, 0xd63bc93d +0, 19, 19, 1, 622080, 0x7ab0a6e6 +0, 20, 20, 1, 622080, 0x883dab85 +0, 21, 21, 1, 622080, 0x9f6ef6b5 +0, 22, 22, 1, 622080, 0xceccee25 +0, 23, 23, 1, 622080, 0x2aa823a5 +0, 24, 24, 1, 622080, 0xb20d0f48 +0, 25, 25, 1, 622080, 0x571560b9 +0, 26, 26, 1, 622080, 0xc0904764 +0, 27, 27, 1, 622080, 0xdb5b89c3 +0, 28, 28, 1, 622080, 0x707aadc5 +0, 29, 29, 1, 622080, 0x6383ef1b +0, 30, 30, 1, 622080, 0xf9e56040 +0, 31, 31, 1, 622080, 0x86ce7ff0 +0, 32, 32, 1, 622080, 0x0c76bd84 +0, 33, 33, 1, 622080, 0xd7192781 +0, 34, 34, 1, 622080, 0x83b70cdc +0, 35, 35, 1, 622080, 0xaae87453 +0, 36, 36, 1, 622080, 0xfafa92e2 +0, 37, 37, 1, 622080, 0x28323354 +0, 38, 38, 1, 622080, 0x34d47484 diff --git a/tests/ref/fate/filter-w3fdif-complex b/tests/ref/fate/filter-w3fdif-complex index 4b334daec16d5..cbd8f06faee92 100644 --- a/tests/ref/fate/filter-w3fdif-complex +++ b/tests/ref/fate/filter-w3fdif-complex @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x576 #sar 0: 16/15 -0, 18, 18, 1, 622080, 0x21d21485 -0, 19, 19, 1, 622080, 0x600a5468 -0, 20, 20, 1, 622080, 0x9526f7b8 -0, 21, 21, 1, 622080, 0x8b3e661f -0, 22, 22, 1, 622080, 0xff5cb5a9 -0, 23, 23, 1, 622080, 0x7e5e730c -0, 24, 24, 1, 622080, 0x85219ac6 -0, 25, 25, 1, 622080, 0x2f3465a0 -0, 26, 26, 1, 622080, 0xddbf4da0 -0, 27, 27, 1, 622080, 0xc115d4ee -0, 28, 28, 1, 622080, 0x7a8a8d72 -0, 29, 29, 1, 622080, 0xbafcd973 -0, 30, 30, 1, 622080, 0xd2c15603 -0, 31, 31, 1, 622080, 0xd7217855 -0, 32, 32, 1, 622080, 0x9a584eca -0, 33, 33, 1, 622080, 0x9f3e1c40 -0, 34, 34, 1, 622080, 0x6d01efb7 -0, 35, 35, 1, 622080, 0x9ecfcce0 -0, 36, 36, 1, 622080, 0xb355fd7e -0, 37, 37, 1, 622080, 0xc7784021 -0, 38, 38, 1, 622080, 0x13fe4187 -0, 39, 39, 1, 622080, 0xfa03b613 -0, 40, 40, 1, 622080, 0x2c9ccfcd -0, 41, 41, 1, 622080, 0xcae6e6c6 -0, 42, 42, 1, 622080, 0x177968f9 -0, 43, 43, 1, 622080, 0xf708de36 -0, 44, 44, 1, 622080, 0x4491870a -0, 45, 45, 1, 622080, 0x37709f98 -0, 46, 46, 1, 622080, 0x23e8d22f -0, 47, 47, 1, 622080, 0x25cba876 +0, 18, 18, 1, 622080, 0xe1b21462 +0, 19, 19, 1, 622080, 0x1362538d +0, 20, 20, 1, 622080, 0x0f55f79b +0, 21, 21, 1, 622080, 0xfdb265f6 +0, 22, 22, 1, 622080, 0x2f8eb534 +0, 23, 23, 1, 622080, 0x0de472b1 +0, 24, 24, 1, 622080, 0x3e699a78 +0, 25, 25, 1, 622080, 0x66396524 +0, 26, 26, 1, 622080, 0x17244d40 +0, 27, 27, 1, 622080, 0x04a5d554 +0, 28, 28, 1, 622080, 0x0e278cd9 +0, 29, 29, 1, 622080, 0x7b53d8de +0, 30, 30, 1, 622080, 0xe51a558e +0, 31, 31, 1, 622080, 0xd58177e4 +0, 32, 32, 1, 622080, 0x270b4e1f +0, 33, 33, 1, 622080, 0x3fbf1bdf +0, 34, 34, 1, 622080, 0xbfebee9d +0, 35, 35, 1, 622080, 0x2c6fcccf +0, 36, 36, 1, 622080, 0x4a57fcc2 +0, 37, 37, 1, 622080, 0x33b53f5d +0, 38, 38, 1, 622080, 0x93ba405d +0, 39, 39, 1, 622080, 0xf4dbb54b +0, 40, 40, 1, 622080, 0xf205ce68 +0, 41, 41, 1, 622080, 0x383fe5bc +0, 42, 42, 1, 622080, 0x4dd06905 +0, 43, 43, 1, 622080, 0xc925de57 +0, 44, 44, 1, 622080, 0x7c8786e8 +0, 45, 45, 1, 622080, 0x550b9f60 +0, 46, 46, 1, 622080, 0x4162d1e9 +0, 47, 47, 1, 622080, 0xf609a847 diff --git a/tests/ref/fate/filter-w3fdif-simple b/tests/ref/fate/filter-w3fdif-simple index 62efaae929e68..09c0d7ce55f88 100644 --- a/tests/ref/fate/filter-w3fdif-simple +++ b/tests/ref/fate/filter-w3fdif-simple @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x576 #sar 0: 16/15 -0, 18, 18, 1, 622080, 0xc73774f5 -0, 19, 19, 1, 622080, 0x4ea3a400 -0, 20, 20, 1, 622080, 0x95153cda -0, 21, 21, 1, 622080, 0xec39bf0b -0, 22, 22, 1, 622080, 0x94b6f836 -0, 23, 23, 1, 622080, 0xc145c3ee -0, 24, 24, 1, 622080, 0x4d4cdee2 -0, 25, 25, 1, 622080, 0x193ebc7c -0, 26, 26, 1, 622080, 0xbd728fd8 -0, 27, 27, 1, 622080, 0xf0f3252f -0, 28, 28, 1, 622080, 0xc012d20a -0, 29, 29, 1, 622080, 0x7b5831b2 -0, 30, 30, 1, 622080, 0x464e9622 -0, 31, 31, 1, 622080, 0x46e3c6c0 -0, 32, 32, 1, 622080, 0xa6ec908b -0, 33, 33, 1, 622080, 0x6a257595 -0, 34, 34, 1, 622080, 0xa6552ecc -0, 35, 35, 1, 622080, 0xdecd1a91 -0, 36, 36, 1, 622080, 0xfaa53e71 -0, 37, 37, 1, 622080, 0xc94a9707 -0, 38, 38, 1, 622080, 0xb5727fd4 -0, 39, 39, 1, 622080, 0x143c018c -0, 40, 40, 1, 622080, 0x92d110c9 -0, 41, 41, 1, 622080, 0x4f762fc0 -0, 42, 42, 1, 622080, 0x3dd2a7d2 -0, 43, 43, 1, 622080, 0xa5d02dc0 -0, 44, 44, 1, 622080, 0x2223ce3d -0, 45, 45, 1, 622080, 0xe4a5fc36 -0, 46, 46, 1, 622080, 0x8384159e -0, 47, 47, 1, 622080, 0x995efa57 +0, 18, 18, 1, 622080, 0x338874e8 +0, 19, 19, 1, 622080, 0x1a9da32b +0, 20, 20, 1, 622080, 0x2ecc3cd9 +0, 21, 21, 1, 622080, 0x0441beec +0, 22, 22, 1, 622080, 0x4de3f7ba +0, 23, 23, 1, 622080, 0x59a4c388 +0, 24, 24, 1, 622080, 0x833ade92 +0, 25, 25, 1, 622080, 0x4c79bbf3 +0, 26, 26, 1, 622080, 0xe1998f77 +0, 27, 27, 1, 622080, 0xd00e2586 +0, 28, 28, 1, 622080, 0xe716d185 +0, 29, 29, 1, 622080, 0x24763136 +0, 30, 30, 1, 622080, 0xaeaa95a2 +0, 31, 31, 1, 622080, 0x92eec65a +0, 32, 32, 1, 622080, 0x7cde9000 +0, 33, 33, 1, 622080, 0x98e2752c +0, 34, 34, 1, 622080, 0x5ffe2db6 +0, 35, 35, 1, 622080, 0x1e911a65 +0, 36, 36, 1, 622080, 0x302d3dc2 +0, 37, 37, 1, 622080, 0xc1399647 +0, 38, 38, 1, 622080, 0xc4477ebf +0, 39, 39, 1, 622080, 0x50e900ca +0, 40, 40, 1, 622080, 0x867e0f7a +0, 41, 41, 1, 622080, 0xa2412ebe +0, 42, 42, 1, 622080, 0xc7a5a7e6 +0, 43, 43, 1, 622080, 0xaa5d2de7 +0, 44, 44, 1, 622080, 0x9bf0ce31 +0, 45, 45, 1, 622080, 0xfb88fbf9 +0, 46, 46, 1, 622080, 0xe6321572 +0, 47, 47, 1, 622080, 0x5541fa37 diff --git a/tests/ref/fate/filter-yadif-mode0 b/tests/ref/fate/filter-yadif-mode0 index 2c6346bd4349d..be807f9de5432 100644 --- a/tests/ref/fate/filter-yadif-mode0 +++ b/tests/ref/fate/filter-yadif-mode0 @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x576 #sar 0: 16/15 -0, 9, 9, 1, 622080, 0x6331caee -0, 10, 10, 1, 622080, 0xa459e690 -0, 11, 11, 1, 622080, 0x6429c648 -0, 12, 12, 1, 622080, 0xa49891ca -0, 13, 13, 1, 622080, 0x2a887404 -0, 14, 14, 1, 622080, 0xe8d49705 -0, 15, 15, 1, 622080, 0x1b627835 -0, 16, 16, 1, 622080, 0x686858fd -0, 17, 17, 1, 622080, 0x2675174f -0, 18, 18, 1, 622080, 0x78470e7f -0, 19, 19, 1, 622080, 0xffb366ec -0, 20, 20, 1, 622080, 0xd575da72 -0, 21, 21, 1, 622080, 0x5fb297f7 -0, 22, 22, 1, 622080, 0xbac77ca0 -0, 23, 23, 1, 622080, 0x3276ed72 -0, 24, 24, 1, 622080, 0x264092b2 -0, 25, 25, 1, 622080, 0x20ba1094 -0, 26, 26, 1, 622080, 0x76cc3139 -0, 27, 27, 1, 622080, 0x469a4902 -0, 28, 28, 1, 622080, 0x0ed7b8f5 -0, 29, 29, 1, 622080, 0xdc51aeac -0, 30, 30, 1, 622080, 0xee06aa36 -0, 31, 31, 1, 622080, 0x7372405f -0, 32, 32, 1, 622080, 0x9e0ee776 -0, 33, 33, 1, 622080, 0x39e6d8c9 -0, 34, 34, 1, 622080, 0x51d9ac9a -0, 35, 35, 1, 622080, 0x2b63441d -0, 36, 36, 1, 622080, 0x58afbd5e -0, 37, 37, 1, 622080, 0xb972f716 -0, 38, 38, 1, 622080, 0x6a6df129 +0, 9, 9, 1, 622080, 0x77c0ca92 +0, 10, 10, 1, 622080, 0xbe7fe646 +0, 11, 11, 1, 622080, 0x4384c5da +0, 12, 12, 1, 622080, 0x296b9168 +0, 13, 13, 1, 622080, 0x96d5738e +0, 14, 14, 1, 622080, 0x769b9681 +0, 15, 15, 1, 622080, 0x461d778d +0, 16, 16, 1, 622080, 0xb88c584b +0, 17, 17, 1, 622080, 0x7d7b1635 +0, 18, 18, 1, 622080, 0x49c60dc0 +0, 19, 19, 1, 622080, 0x498765a4 +0, 20, 20, 1, 622080, 0x0caed8f9 +0, 21, 21, 1, 622080, 0x41d897d3 +0, 22, 22, 1, 622080, 0x7aeb7c93 +0, 23, 23, 1, 622080, 0xa8bced40 +0, 24, 24, 1, 622080, 0x11de928c +0, 25, 25, 1, 622080, 0x64741075 +0, 26, 26, 1, 622080, 0x160f310e +0, 27, 27, 1, 622080, 0x702d489c +0, 28, 28, 1, 622080, 0xaf2fb8aa +0, 29, 29, 1, 622080, 0x575bae0f +0, 30, 30, 1, 622080, 0xfd68a990 +0, 31, 31, 1, 622080, 0x8b513f66 +0, 32, 32, 1, 622080, 0x0e6ae6c3 +0, 33, 33, 1, 622080, 0x3d12d8ab +0, 34, 34, 1, 622080, 0x45d0ac80 +0, 35, 35, 1, 622080, 0xb18d4421 +0, 36, 36, 1, 622080, 0x2e81bd32 +0, 37, 37, 1, 622080, 0x852cf6cf +0, 38, 38, 1, 622080, 0xb055f0e5 diff --git a/tests/ref/fate/filter-yadif-mode1 b/tests/ref/fate/filter-yadif-mode1 index e2d14d5605131..53741b0ae7f5a 100644 --- a/tests/ref/fate/filter-yadif-mode1 +++ b/tests/ref/fate/filter-yadif-mode1 @@ -3,62 +3,62 @@ #codec_id 0: rawvideo #dimensions 0: 720x576 #sar 0: 16/15 -0, 18, 18, 1, 622080, 0x6331caee -0, 19, 19, 1, 622080, 0x625da883 -0, 20, 20, 1, 622080, 0xa459e690 -0, 21, 21, 1, 622080, 0xce5d891e -0, 22, 22, 1, 622080, 0x6429c648 -0, 23, 23, 1, 622080, 0x608cc0ba -0, 24, 24, 1, 622080, 0xa49891ca -0, 25, 25, 1, 622080, 0x9721987f -0, 26, 26, 1, 622080, 0x2a887404 -0, 27, 27, 1, 622080, 0x60d71d47 -0, 28, 28, 1, 622080, 0xe8d49705 -0, 29, 29, 1, 622080, 0x821e13cb -0, 30, 30, 1, 622080, 0x1b627835 -0, 31, 31, 1, 622080, 0x1806c5f4 -0, 32, 32, 1, 622080, 0x686858fd -0, 33, 33, 1, 622080, 0xab865773 -0, 34, 34, 1, 622080, 0x2675174f -0, 35, 35, 1, 622080, 0x43a61a14 -0, 36, 36, 1, 622080, 0x78470e7f -0, 37, 37, 1, 622080, 0xeb877bc6 -0, 38, 38, 1, 622080, 0xffb366ec -0, 39, 39, 1, 622080, 0xda0906e7 -0, 40, 40, 1, 622080, 0xd575da72 -0, 41, 41, 1, 622080, 0x23ae25a4 -0, 42, 42, 1, 622080, 0x5fb297f7 -0, 43, 43, 1, 622080, 0x99b32978 -0, 44, 44, 1, 622080, 0xbac77ca0 -0, 45, 45, 1, 622080, 0xc1cdcbf9 -0, 46, 46, 1, 622080, 0x3276ed72 -0, 47, 47, 1, 622080, 0x4061f5ab -0, 48, 48, 1, 622080, 0x264092b2 -0, 49, 49, 1, 622080, 0xa4e2039e -0, 50, 50, 1, 622080, 0x20ba1094 -0, 51, 51, 1, 622080, 0x984e906e -0, 52, 52, 1, 622080, 0x76cc3139 -0, 53, 53, 1, 622080, 0xf70e2cf6 -0, 54, 54, 1, 622080, 0x469a4902 -0, 55, 55, 1, 622080, 0x235312e6 -0, 56, 56, 1, 622080, 0x0ed7b8f5 -0, 57, 57, 1, 622080, 0xd0269cc3 -0, 58, 58, 1, 622080, 0xdc51aeac -0, 59, 59, 1, 622080, 0x1aa5f76e -0, 60, 60, 1, 622080, 0xee06aa36 -0, 61, 61, 1, 622080, 0xa7103230 -0, 62, 62, 1, 622080, 0x7372405f -0, 63, 63, 1, 622080, 0x8d7a44b5 -0, 64, 64, 1, 622080, 0x9e0ee776 -0, 65, 65, 1, 622080, 0xd41e8560 -0, 66, 66, 1, 622080, 0x39e6d8c9 -0, 67, 67, 1, 622080, 0x7a23d70c -0, 68, 68, 1, 622080, 0x51d9ac9a -0, 69, 69, 1, 622080, 0x8eacf7f2 -0, 70, 70, 1, 622080, 0x2b63441d -0, 71, 71, 1, 622080, 0x9f71b742 -0, 72, 72, 1, 622080, 0x58afbd5e -0, 73, 73, 1, 622080, 0x4d645292 -0, 74, 74, 1, 622080, 0xb972f716 -0, 75, 75, 1, 622080, 0xbb5d01a2 -0, 76, 76, 1, 622080, 0x6a6df129 +0, 18, 18, 1, 622080, 0x77c0ca92 +0, 19, 19, 1, 622080, 0x06d3a822 +0, 20, 20, 1, 622080, 0xbe7fe646 +0, 21, 21, 1, 622080, 0x542e891a +0, 22, 22, 1, 622080, 0x4384c5da +0, 23, 23, 1, 622080, 0xddd4c056 +0, 24, 24, 1, 622080, 0x296b9168 +0, 25, 25, 1, 622080, 0xf8e09812 +0, 26, 26, 1, 622080, 0x96d5738e +0, 27, 27, 1, 622080, 0xac341d9b +0, 28, 28, 1, 622080, 0x769b9681 +0, 29, 29, 1, 622080, 0xb5da1354 +0, 30, 30, 1, 622080, 0x461d778d +0, 31, 31, 1, 622080, 0xd9dcc5a8 +0, 32, 32, 1, 622080, 0xb88c584b +0, 33, 33, 1, 622080, 0x581b5727 +0, 34, 34, 1, 622080, 0x7d7b1635 +0, 35, 35, 1, 622080, 0xfc1b1a12 +0, 36, 36, 1, 622080, 0x49c60dc0 +0, 37, 37, 1, 622080, 0x1d537b22 +0, 38, 38, 1, 622080, 0x498765a4 +0, 39, 39, 1, 622080, 0xdd2e063a +0, 40, 40, 1, 622080, 0x0caed8f9 +0, 41, 41, 1, 622080, 0xfb4a24aa +0, 42, 42, 1, 622080, 0x41d897d3 +0, 43, 43, 1, 622080, 0xdd3f29ae +0, 44, 44, 1, 622080, 0x7aeb7c93 +0, 45, 45, 1, 622080, 0x2410cbe2 +0, 46, 46, 1, 622080, 0xa8bced40 +0, 47, 47, 1, 622080, 0x5534f5ca +0, 48, 48, 1, 622080, 0x11de928c +0, 49, 49, 1, 622080, 0x82180322 +0, 50, 50, 1, 622080, 0x64741075 +0, 51, 51, 1, 622080, 0x5e048fc8 +0, 52, 52, 1, 622080, 0x160f310e +0, 53, 53, 1, 622080, 0x4f6d2ce7 +0, 54, 54, 1, 622080, 0x702d489c +0, 55, 55, 1, 622080, 0xa4b41315 +0, 56, 56, 1, 622080, 0xaf2fb8aa +0, 57, 57, 1, 622080, 0x5ec09c25 +0, 58, 58, 1, 622080, 0x575bae0f +0, 59, 59, 1, 622080, 0x94ecf775 +0, 60, 60, 1, 622080, 0xfd68a990 +0, 61, 61, 1, 622080, 0x15a7315c +0, 62, 62, 1, 622080, 0x8b513f66 +0, 63, 63, 1, 622080, 0xeba9440a +0, 64, 64, 1, 622080, 0x0e6ae6c3 +0, 65, 65, 1, 622080, 0x751484a6 +0, 66, 66, 1, 622080, 0x3d12d8ab +0, 67, 67, 1, 622080, 0xdff3d681 +0, 68, 68, 1, 622080, 0x45d0ac80 +0, 69, 69, 1, 622080, 0xbe2df7f7 +0, 70, 70, 1, 622080, 0xb18d4421 +0, 71, 71, 1, 622080, 0xa49cb6de +0, 72, 72, 1, 622080, 0x2e81bd32 +0, 73, 73, 1, 622080, 0xa47a5272 +0, 74, 74, 1, 622080, 0x852cf6cf +0, 75, 75, 1, 622080, 0x892a014e +0, 76, 76, 1, 622080, 0xb055f0e5 diff --git a/tests/ref/fate/filter-yadif10 b/tests/ref/fate/filter-yadif10 index 09ab7458bb15c..28e799fc1f01a 100644 --- a/tests/ref/fate/filter-yadif10 +++ b/tests/ref/fate/filter-yadif10 @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x576 #sar 0: 16/15 -0, 9, 9, 1, 1244160, 0x5b49e0c0 -0, 10, 10, 1, 1244160, 0x76ba6bab -0, 11, 11, 1, 1244160, 0x0298cb8d -0, 12, 12, 1, 1244160, 0x9c81759a -0, 13, 13, 1, 1244160, 0xa239d1ae -0, 14, 14, 1, 1244160, 0x3e95ada9 -0, 15, 15, 1, 1244160, 0x8b87e8f8 -0, 16, 16, 1, 1244160, 0x64f89653 -0, 17, 17, 1, 1244160, 0x58e5d12e -0, 18, 18, 1, 1244160, 0x38b4003a -0, 19, 19, 1, 1244160, 0xc005c29c -0, 20, 20, 1, 1244160, 0x10c0c60d -0, 21, 21, 1, 1244160, 0x1b550998 -0, 22, 22, 1, 1244160, 0x7aacf6ab -0, 23, 23, 1, 1244160, 0xeb205d98 -0, 24, 24, 1, 1244160, 0x6ad2134c -0, 25, 25, 1, 1244160, 0x8aea4e56 -0, 26, 26, 1, 1244160, 0x0d910a6b -0, 27, 27, 1, 1244160, 0x749ae307 -0, 28, 28, 1, 1244160, 0x8ff7af3c -0, 29, 29, 1, 1244160, 0x9ba51b91 -0, 30, 30, 1, 1244160, 0xad476514 -0, 31, 31, 1, 1244160, 0x674481d6 -0, 32, 32, 1, 1244160, 0x0937e677 -0, 33, 33, 1, 1244160, 0x6c2c53ee -0, 34, 34, 1, 1244160, 0x524a164e -0, 35, 35, 1, 1244160, 0x77a405ab -0, 36, 36, 1, 1244160, 0xaa6b47c4 -0, 37, 37, 1, 1244160, 0x0b5ab556 -0, 38, 38, 1, 1244160, 0xbe1edab9 +0, 9, 9, 1, 1244160, 0xe0c2231b +0, 10, 10, 1, 1244160, 0xdc7caa43 +0, 11, 11, 1, 1244160, 0x52c4dfbf +0, 12, 12, 1, 1244160, 0x7c577f07 +0, 13, 13, 1, 1244160, 0x5b6ad7ce +0, 14, 14, 1, 1244160, 0x6f15ce76 +0, 15, 15, 1, 1244160, 0xf120034a +0, 16, 16, 1, 1244160, 0x9c65ba64 +0, 17, 17, 1, 1244160, 0x883b237e +0, 18, 18, 1, 1244160, 0xb8292e0d +0, 19, 19, 1, 1244160, 0xbc392721 +0, 20, 20, 1, 1244160, 0x7cd82ec9 +0, 21, 21, 1, 1244160, 0x167325eb +0, 22, 22, 1, 1244160, 0x49bafa73 +0, 23, 23, 1, 1244160, 0xe1ff6dbf +0, 24, 24, 1, 1244160, 0x85f710b6 +0, 25, 25, 1, 1244160, 0xd1fd4cdb +0, 26, 26, 1, 1244160, 0xafee03c5 +0, 27, 27, 1, 1244160, 0x566be070 +0, 28, 28, 1, 1244160, 0xb6abbd01 +0, 29, 29, 1, 1244160, 0xa98f38fd +0, 30, 30, 1, 1244160, 0x00f4736b +0, 31, 31, 1, 1244160, 0x6b0f9dd2 +0, 32, 32, 1, 1244160, 0x15810b92 +0, 33, 33, 1, 1244160, 0x0b516465 +0, 34, 34, 1, 1244160, 0x927d15e6 +0, 35, 35, 1, 1244160, 0xd102f2bf +0, 36, 36, 1, 1244160, 0xdd8b3b20 +0, 37, 37, 1, 1244160, 0x229ac529 +0, 38, 38, 1, 1244160, 0xf844e0a2 diff --git a/tests/ref/fate/filter-yadif16 b/tests/ref/fate/filter-yadif16 index 3386b026c9a48..0c856ab37a8d2 100644 --- a/tests/ref/fate/filter-yadif16 +++ b/tests/ref/fate/filter-yadif16 @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x576 #sar 0: 16/15 -0, 9, 9, 1, 1244160, 0xfb65caee -0, 10, 10, 1, 1244160, 0x6222e690 -0, 11, 11, 1, 1244160, 0x020ac648 -0, 12, 12, 1, 1244160, 0xb76691ca -0, 13, 13, 1, 1244160, 0xe0fd7404 -0, 14, 14, 1, 1244160, 0x3ab29705 -0, 15, 15, 1, 1244160, 0xbe807835 -0, 16, 16, 1, 1244160, 0x77d358fd -0, 17, 17, 1, 1244160, 0x359b174f -0, 18, 18, 1, 1244160, 0xe20f0e7f -0, 19, 19, 1, 1244160, 0x988966ec -0, 20, 20, 1, 1244160, 0xd078da72 -0, 21, 21, 1, 1244160, 0x276d97f7 -0, 22, 22, 1, 1244160, 0xf8ee7ca0 -0, 23, 23, 1, 1244160, 0x776bed72 -0, 24, 24, 1, 1244160, 0xb9bf92b2 -0, 25, 25, 1, 1244160, 0x30e01094 -0, 26, 26, 1, 1244160, 0xbc5f3139 -0, 27, 27, 1, 1244160, 0x44324902 -0, 28, 28, 1, 1244160, 0x64aab8f5 -0, 29, 29, 1, 1244160, 0x0a05aeac -0, 30, 30, 1, 1244160, 0x31e5aa36 -0, 31, 31, 1, 1244160, 0xa685405f -0, 32, 32, 1, 1244160, 0x54a6e776 -0, 33, 33, 1, 1244160, 0x9af4d8c9 -0, 34, 34, 1, 1244160, 0xf709ac9a -0, 35, 35, 1, 1244160, 0x12a9441d -0, 36, 36, 1, 1244160, 0xf3f1bd5e -0, 37, 37, 1, 1244160, 0x7bcef716 -0, 38, 38, 1, 1244160, 0xe3a2f129 +0, 9, 9, 1, 1244160, 0x24eeca92 +0, 10, 10, 1, 1244160, 0x96b8e646 +0, 11, 11, 1, 1244160, 0xc11fc5da +0, 12, 12, 1, 1244160, 0xc15f9168 +0, 13, 13, 1, 1244160, 0xba1c738e +0, 14, 14, 1, 1244160, 0x56b59681 +0, 15, 15, 1, 1244160, 0x14ad778d +0, 16, 16, 1, 1244160, 0x18dc584b +0, 17, 17, 1, 1244160, 0xe4c11635 +0, 18, 18, 1, 1244160, 0x85cc0dc0 +0, 19, 19, 1, 1244160, 0x2d6a65a4 +0, 20, 20, 1, 1244160, 0x4054d8f9 +0, 21, 21, 1, 1244160, 0xebce97d3 +0, 22, 22, 1, 1244160, 0x79437c93 +0, 23, 23, 1, 1244160, 0x6438ed40 +0, 24, 24, 1, 1244160, 0x9121928c +0, 25, 25, 1, 1244160, 0xb8731075 +0, 26, 26, 1, 1244160, 0xfb01310e +0, 27, 27, 1, 1244160, 0x97be489c +0, 28, 28, 1, 1244160, 0xa5b4b8aa +0, 29, 29, 1, 1244160, 0x00a7ae0f +0, 30, 30, 1, 1244160, 0x514fa990 +0, 31, 31, 1, 1244160, 0xd73c3f66 +0, 32, 32, 1, 1244160, 0x3602e6c3 +0, 33, 33, 1, 1244160, 0xa16ad8ab +0, 34, 34, 1, 1244160, 0xdf11ac80 +0, 35, 35, 1, 1244160, 0x1f084421 +0, 36, 36, 1, 1244160, 0x9fc1bd32 +0, 37, 37, 1, 1244160, 0x1389f6cf +0, 38, 38, 1, 1244160, 0x6fc5f0e5 diff --git a/tests/ref/fate/mpeg2-field-enc b/tests/ref/fate/mpeg2-field-enc index 4c288a83efc01..8062b824832e7 100644 --- a/tests/ref/fate/mpeg2-field-enc +++ b/tests/ref/fate/mpeg2-field-enc @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x576 #sar 0: 16/15 -0, 9, 9, 1, 622080, 0xb3b66c5c -0, 10, 10, 1, 622080, 0x088ec02b -0, 11, 11, 1, 622080, 0x7a36db21 -0, 12, 12, 1, 622080, 0x541b286f -0, 13, 13, 1, 622080, 0xb6c3e590 -0, 14, 14, 1, 622080, 0x39dbed51 -0, 15, 15, 1, 622080, 0x973dc728 -0, 16, 16, 1, 622080, 0xd7a4f804 -0, 17, 17, 1, 622080, 0xa2484762 -0, 18, 18, 1, 622080, 0x0cd268d1 -0, 19, 19, 1, 622080, 0x72eb663d -0, 20, 20, 1, 622080, 0x8fdbac59 -0, 21, 21, 1, 622080, 0xa6f4feb9 -0, 22, 22, 1, 622080, 0xadb828c6 -0, 23, 23, 1, 622080, 0xea630a63 -0, 24, 24, 1, 622080, 0xa901d925 -0, 25, 25, 1, 622080, 0xac5e7087 -0, 26, 26, 1, 622080, 0x10274a2b -0, 27, 27, 1, 622080, 0x143d541c -0, 28, 28, 1, 622080, 0xee94c93a -0, 29, 29, 1, 622080, 0xca030208 -0, 30, 30, 1, 622080, 0x26f30ead -0, 31, 31, 1, 622080, 0xfc22f32c -0, 32, 32, 1, 622080, 0x940a5ff8 -0, 33, 33, 1, 622080, 0x2164f805 -0, 34, 34, 1, 622080, 0xa76f5aba -0, 35, 35, 1, 622080, 0x8c311471 -0, 36, 36, 1, 622080, 0xa45e1d95 -0, 37, 37, 1, 622080, 0x6cc61d6c -0, 38, 38, 1, 622080, 0x6983b417 +0, 9, 9, 1, 622080, 0xff496bf5 +0, 10, 10, 1, 622080, 0x9bf6c014 +0, 11, 11, 1, 622080, 0x870edac7 +0, 12, 12, 1, 622080, 0x9dec280c +0, 13, 13, 1, 622080, 0x0f02e57a +0, 14, 14, 1, 622080, 0x161beccb +0, 15, 15, 1, 622080, 0x2234c6b0 +0, 16, 16, 1, 622080, 0x143ef78a +0, 17, 17, 1, 622080, 0x0d6e46cf +0, 18, 18, 1, 622080, 0xb41667fd +0, 19, 19, 1, 622080, 0xcc476539 +0, 20, 20, 1, 622080, 0x85d8ab16 +0, 21, 21, 1, 622080, 0xcd6afec1 +0, 22, 22, 1, 622080, 0x187a28ac +0, 23, 23, 1, 622080, 0x06100a4b +0, 24, 24, 1, 622080, 0x1b4ed8e9 +0, 25, 25, 1, 622080, 0xde33702c +0, 26, 26, 1, 622080, 0x11974a0c +0, 27, 27, 1, 622080, 0x1a0553e8 +0, 28, 28, 1, 622080, 0x98e1c8da +0, 29, 29, 1, 622080, 0x003801ce +0, 30, 30, 1, 622080, 0x6f300e00 +0, 31, 31, 1, 622080, 0xb232f27d +0, 32, 32, 1, 622080, 0x07c65f57 +0, 33, 33, 1, 622080, 0x6363f7ce +0, 34, 34, 1, 622080, 0x69ba5ac3 +0, 35, 35, 1, 622080, 0x8561143e +0, 36, 36, 1, 622080, 0xf45e1d76 +0, 37, 37, 1, 622080, 0x69f81d2f +0, 38, 38, 1, 622080, 0x8653b3ed diff --git a/tests/ref/fate/mpeg2-ticket6677 b/tests/ref/fate/mpeg2-ticket6677 index 5fc7cb2a26ac8..e963e32f2dfbc 100644 --- a/tests/ref/fate/mpeg2-ticket6677 +++ b/tests/ref/fate/mpeg2-ticket6677 @@ -3,10 +3,10 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 8/9 -0, 0, 0, 1, 518400, 0x354b6fc3 -0, 1, 1, 1, 518400, 0xd86f281b -0, 2, 2, 1, 518400, 0xdd2e2b38 -0, 3, 3, 1, 518400, 0x589535d4 -0, 4, 4, 1, 518400, 0x3f8f02b6 -0, 5, 5, 1, 518400, 0xa81b246a +0, 0, 0, 1, 518400, 0xc1866f5f +0, 1, 1, 1, 518400, 0x9ba32764 +0, 2, 2, 1, 518400, 0xa9031bb8 +0, 3, 3, 1, 518400, 0x5e2c3502 +0, 4, 4, 1, 518400, 0xe860027a +0, 5, 5, 1, 518400, 0xa9152430 0, 6, 6, 1, 518400, 0xb98dd9f7 From 63a4bdbf3b732504e54cc2b9ec0886e6242a90bc Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 9 Feb 2018 22:24:58 +0100 Subject: [PATCH 1846/2557] avcodec/mpeg4videodec: Ignore multiple VOL headers Fixes: Ticket7005 Signed-off-by: Michael Niedermayer --- libavcodec/mpeg4videodec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 756753e2fc1f2..19210d97fe665 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -2707,8 +2707,8 @@ int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb) if (startcode >= 0x120 && startcode <= 0x12F) { if (vol) { - av_log(s->avctx, AV_LOG_ERROR, "Multiple VOL headers"); - return AVERROR_INVALIDDATA; + av_log(s->avctx, AV_LOG_WARNING, "Ignoring multiple VOL headers\n"); + continue; } vol++; if ((ret = decode_vol_header(ctx, gb)) < 0) From f2318aee8ca8df1c84092f7d6691a2d0df02c474 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 11 Feb 2018 03:38:54 +0100 Subject: [PATCH 1847/2557] avcodec/vp3: Error out on invalid num_coeffs in unpack_vlcs() This fixes a hypothetical integer overflow Signed-off-by: Michael Niedermayer --- libavcodec/vp3.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index 33be345c144bd..1d8375331493f 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -951,9 +951,11 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb, Vp3Fragment *all_fragments = s->all_fragments; VLC_TYPE(*vlc_table)[2] = table->table; - if (num_coeffs < 0) + if (num_coeffs < 0) { av_log(s->avctx, AV_LOG_ERROR, "Invalid number of coefficients at level %d\n", coeff_index); + return AVERROR_INVALIDDATA; + } if (eob_run > num_coeffs) { coeff_i = From dced1f6cdfe479965898bed3cb5219d2ddbb0ad9 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sat, 10 Feb 2018 02:54:42 +0100 Subject: [PATCH 1848/2557] lavf/rtpdec: Constify several pointers. Fixes two warnings: libavformat/rtpdec.c:155:20: warning: return discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers] libavformat/rtpdec.c:168:20: warning: return discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers] --- libavformat/rdt.c | 2 +- libavformat/rdt.h | 2 +- libavformat/rtpdec.c | 6 +++--- libavformat/rtpdec.h | 6 +++--- libavformat/rtsp.c | 8 ++++---- libavformat/rtsp.h | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/libavformat/rdt.c b/libavformat/rdt.c index 31a32ffec3dca..60c36f09e636e 100644 --- a/libavformat/rdt.c +++ b/libavformat/rdt.c @@ -53,7 +53,7 @@ struct RDTDemuxContext { RDTDemuxContext * ff_rdt_parse_open(AVFormatContext *ic, int first_stream_of_set_idx, - void *priv_data, RTPDynamicProtocolHandler *handler) + void *priv_data, const RTPDynamicProtocolHandler *handler) { RDTDemuxContext *s = av_mallocz(sizeof(RDTDemuxContext)); if (!s) diff --git a/libavformat/rdt.h b/libavformat/rdt.h index 248056568833c..67fb308421df8 100644 --- a/libavformat/rdt.h +++ b/libavformat/rdt.h @@ -41,7 +41,7 @@ typedef struct RDTDemuxContext RDTDemuxContext; RDTDemuxContext *ff_rdt_parse_open(AVFormatContext *ic, int first_stream_of_set_idx, void *priv_data, - RTPDynamicProtocolHandler *handler); + const RTPDynamicProtocolHandler *handler); void ff_rdt_parse_close(RDTDemuxContext *s); /** diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index 6499e275ffb00..e75a34cb93330 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -143,7 +143,7 @@ const RTPDynamicProtocolHandler *ff_rtp_handler_iterate(void **opaque) return r; } -RTPDynamicProtocolHandler *ff_rtp_handler_find_by_name(const char *name, +const RTPDynamicProtocolHandler *ff_rtp_handler_find_by_name(const char *name, enum AVMediaType codec_type) { void *i = 0; @@ -157,7 +157,7 @@ RTPDynamicProtocolHandler *ff_rtp_handler_find_by_name(const char *name, return NULL; } -RTPDynamicProtocolHandler *ff_rtp_handler_find_by_id(int id, +const RTPDynamicProtocolHandler *ff_rtp_handler_find_by_id(int id, enum AVMediaType codec_type) { void *i = 0; @@ -572,7 +572,7 @@ RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st, } void ff_rtp_parse_set_dynamic_protocol(RTPDemuxContext *s, PayloadContext *ctx, - RTPDynamicProtocolHandler *handler) + const RTPDynamicProtocolHandler *handler) { s->dynamic_protocol_context = ctx; s->handler = handler; diff --git a/libavformat/rtpdec.h b/libavformat/rtpdec.h index fe726a6886579..5a47d6f79d5fb 100644 --- a/libavformat/rtpdec.h +++ b/libavformat/rtpdec.h @@ -43,7 +43,7 @@ typedef struct RTPDemuxContext RTPDemuxContext; RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st, int payload_type, int queue_size); void ff_rtp_parse_set_dynamic_protocol(RTPDemuxContext *s, PayloadContext *ctx, - RTPDynamicProtocolHandler *handler); + const RTPDynamicProtocolHandler *handler); void ff_rtp_parse_set_crypto(RTPDemuxContext *s, const char *suite, const char *params); int ff_rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt, @@ -208,7 +208,7 @@ const RTPDynamicProtocolHandler *ff_rtp_handler_iterate(void **opaque); * @param name name of the requested rtp dynamic protocol handler * @return A rtp dynamic protocol handler if one was found, NULL otherwise. */ -RTPDynamicProtocolHandler *ff_rtp_handler_find_by_name(const char *name, +const RTPDynamicProtocolHandler *ff_rtp_handler_find_by_name(const char *name, enum AVMediaType codec_type); /** * Find a registered rtp dynamic protocol handler with a matching codec ID. @@ -216,7 +216,7 @@ RTPDynamicProtocolHandler *ff_rtp_handler_find_by_name(const char *name, * @param id AVCodecID of the requested rtp dynamic protocol handler. * @return A rtp dynamic protocol handler if one was found, NULL otherwise. */ -RTPDynamicProtocolHandler *ff_rtp_handler_find_by_id(int id, +const RTPDynamicProtocolHandler *ff_rtp_handler_find_by_id(int id, enum AVMediaType codec_type); /* from rtsp.c, but used by rtp dynamic protocol handlers. */ diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index b3cfbb874f65e..ceb770a3a4901 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -211,7 +211,7 @@ static int get_sockaddr(AVFormatContext *s, } #if CONFIG_RTPDEC -static void init_rtp_handler(RTPDynamicProtocolHandler *handler, +static void init_rtp_handler(const RTPDynamicProtocolHandler *handler, RTSPStream *rtsp_st, AVStream *st) { AVCodecParameters *par = st ? st->codecpar : NULL; @@ -271,7 +271,7 @@ static int sdp_parse_rtpmap(AVFormatContext *s, } if (par->codec_id == AV_CODEC_ID_NONE) { - RTPDynamicProtocolHandler *handler = + const RTPDynamicProtocolHandler *handler = ff_rtp_handler_find_by_name(buf, par->codec_type); init_rtp_handler(handler, rtsp_st, st); /* If no dynamic handler was found, check with the list of standard @@ -495,7 +495,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, if (CONFIG_RTPDEC && !rt->ts) rt->ts = avpriv_mpegts_parse_open(s); } else { - RTPDynamicProtocolHandler *handler; + const RTPDynamicProtocolHandler *handler; handler = ff_rtp_handler_find_by_id( rtsp_st->sdp_payload_type, AVMEDIA_TYPE_DATA); init_rtp_handler(handler, rtsp_st, NULL); @@ -513,7 +513,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, rtsp_st->stream_index = st->index; st->codecpar->codec_type = codec_type; if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) { - RTPDynamicProtocolHandler *handler; + const RTPDynamicProtocolHandler *handler; /* if standard payload type, we can find the codec right now */ ff_rtp_get_codec_info(st->codecpar, rtsp_st->sdp_payload_type); if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index 36fdae492b4de..9a7f366b39290 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -458,7 +458,7 @@ typedef struct RTSPStream { /** The following are used for dynamic protocols (rtpdec_*.c/rdt.c) */ //@{ /** handler structure */ - RTPDynamicProtocolHandler *dynamic_handler; + const RTPDynamicProtocolHandler *dynamic_handler; /** private data associated with the dynamic protocol */ PayloadContext *dynamic_protocol_context; From 5b145290df2998a9836a93eb925289c6c8b63af0 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 29 Jan 2018 22:18:00 +0000 Subject: [PATCH 1849/2557] lavc: Add support for increasing hardware frame pool sizes AVCodecContext.extra_hw_frames is added to the size of hardware frame pools created by libavcodec for APIs which require fixed-size pools. This allows the user to keep references to a greater number of frames after decode, which may be necessary for some use-cases. It is also added to the initial_pool_size value returned by avcodec_get_hw_frames_parameters() if a fixed-size pool is required. --- doc/APIchanges | 3 +++ libavcodec/avcodec.h | 14 ++++++++++++++ libavcodec/decode.c | 9 +++++++++ libavcodec/options_table.h | 1 + libavcodec/version.h | 2 +- 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 0bde3a052d43c..d62f7674f33fe 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2017-03-23 API changes, most recent first: +2018-02-xx - xxxxxxx - lavc 58.9.0 - avcodec.h + Add AVCodecContext.extra_hw_frames. + 2017-xx-xx - xxxxxxx - lavc 58.8.0 - avcodec.h Add const to AVCodecContext.hwaccel. diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 7eaa0c9277318..03a3d5bd6d0c4 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2739,6 +2739,20 @@ typedef struct AVCodecContext { * AVCodecContext.get_format callback) */ int hwaccel_flags; + + /** + * Video decoding only. Sets the number of extra hardware frames which + * the decoder will allocate for use by the caller. This must be set + * before avcodec_open2() is called. + * + * Some hardware decoders require all frames that they will use for + * output to be defined in advance before decoding starts. For such + * decoders, the hardware frame pool must therefore be of a fixed size. + * The extra frames set here are on top of any number that the decoder + * needs internally in order to operate normally (for example, frames + * used as reference pictures). + */ + int extra_hw_frames; } AVCodecContext; /** diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 12a95d4221b8b..e024a32321120 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -791,6 +791,15 @@ int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, ret = hwa->frame_params(avctx, frames_ref); if (ret >= 0) { + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)frames_ref->data; + + if (frames_ctx->initial_pool_size) { + // If the user has requested that extra output surfaces be + // available then add them here. + if (avctx->extra_hw_frames > 0) + frames_ctx->initial_pool_size += avctx->extra_hw_frames; + } + *out_frames_ref = frames_ref; } else { av_buffer_unref(&frames_ref); diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 925ef376f3953..4b0a8344d0ade 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -419,6 +419,7 @@ static const AVOption avcodec_options[] = { {"side_data_only_packets", NULL, OFFSET(side_data_only_packets), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, A|V|E }, #endif {"apply_cropping", NULL, OFFSET(apply_cropping), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, V | D }, +{"extra_hw_frames", "Number of extra hardware frames to allocate for the user", OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, V|D }, {NULL}, }; diff --git a/libavcodec/version.h b/libavcodec/version.h index 9b47110301a9b..36a014959e2f1 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 8 +#define LIBAVCODEC_VERSION_MINOR 9 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From cad739dace55e3446ef7180de688173cd19fb000 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 29 Jan 2018 22:55:11 +0000 Subject: [PATCH 1850/2557] lavc: Add per-thread surfaces in get_hw_frame_parameters() This number is definitely required when frame threading is enabled, so add it here rather than forcing all users to handle it themselves. DXVA2 contained this addition in specific code as well (therefore being added twice in the internal case) - just remove it from there. --- libavcodec/decode.c | 9 +++++---- libavcodec/dxva2.c | 4 ---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index e024a32321120..8635aec949b22 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -748,10 +748,6 @@ int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx, // We guarantee 4 base work surfaces. The function above guarantees 1 // (the absolute minimum), so add the missing count. frames_ctx->initial_pool_size += 3; - - // Add an additional surface per thread is frame threading is enabled. - if (avctx->active_thread_type & FF_THREAD_FRAME) - frames_ctx->initial_pool_size += avctx->thread_count; } ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); @@ -798,6 +794,11 @@ int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, // available then add them here. if (avctx->extra_hw_frames > 0) frames_ctx->initial_pool_size += avctx->extra_hw_frames; + + // If frame threading is enabled then an extra surface per thread + // is also required. + if (avctx->active_thread_type & FF_THREAD_FRAME) + frames_ctx->initial_pool_size += avctx->thread_count; } *out_frames_ref = frames_ref; diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index e34409d44a3b7..939b45a65b9d7 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -608,10 +608,6 @@ int ff_dxva2_common_frame_params(AVCodecContext *avctx, else num_surfaces += 2; - /* add extra surfaces for frame threading */ - if (avctx->active_thread_type & FF_THREAD_FRAME) - num_surfaces += avctx->thread_count; - frames_ctx->sw_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; frames_ctx->width = FFALIGN(avctx->coded_width, surface_alignment); From 6d86cef06ba36c0ed591e14a2382e9630059fc5d Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 27 Mar 2017 21:10:53 +0100 Subject: [PATCH 1851/2557] lavfi: Add support for increasing hardware frame pool sizes AVFilterContext.extra_hw_frames functions identically to the field of the same name in AVCodecContext. --- doc/APIchanges | 3 +++ libavfilter/avfilter.c | 23 +++++++++++++++++++++++ libavfilter/avfilter.h | 16 ++++++++++++++++ libavfilter/internal.h | 17 +++++++++++++++++ libavfilter/version.h | 2 +- 5 files changed, 60 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index d62f7674f33fe..d385d73b0c12d 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2017-03-23 API changes, most recent first: +2018-02-xx - xxxxxxx - lavfi 7.1.0 - avfilter.h + Add AVFilterContext.extra_hw_frames. + 2018-02-xx - xxxxxxx - lavc 58.9.0 - avcodec.h Add AVCodecContext.extra_hw_frames. diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 83c1a7c20d5ff..2c4a385ea907f 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -368,6 +368,8 @@ static const AVOption avfilter_options[] = { { "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, "thread_type" }, { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .unit = "thread_type" }, + { "extra_hw_frames", "Number of extra hardware frames to allocate for the user", + OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, { NULL }, }; @@ -707,3 +709,24 @@ const AVClass *avfilter_get_class(void) { return &avfilter_class; } + +int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link, + int default_pool_size) +{ + AVHWFramesContext *frames; + + // Must already be set by caller. + av_assert0(link->hw_frames_ctx); + + frames = (AVHWFramesContext*)link->hw_frames_ctx->data; + + if (frames->initial_pool_size == 0) { + // Dynamic allocation is necessarily supported. + } else if (avctx->extra_hw_frames >= 0) { + frames->initial_pool_size += avctx->extra_hw_frames; + } else { + frames->initial_pool_size = default_pool_size; + } + + return 0; +} diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 6df69dbbbf1bc..46dbadfcdc20a 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -311,6 +311,22 @@ struct AVFilterContext { * hardware context information. */ AVBufferRef *hw_device_ctx; + + /** + * Sets the number of extra hardware frames which the filter will + * allocate on its output links for use in following filters or by + * the caller. + * + * Some hardware filters require all frames that they will use for + * output to be defined in advance before filtering starts. For such + * filters, any hardware frame pools used for output must therefore be + * of fixed size. The extra frames set here are on top of any number + * that the filter needs internally in order to operate normally. + * + * This field must be set before the graph containing this filter is + * configured. + */ + int extra_hw_frames; }; /** diff --git a/libavfilter/internal.h b/libavfilter/internal.h index a377f9b2bab7e..dd021e00a124d 100644 --- a/libavfilter/internal.h +++ b/libavfilter/internal.h @@ -226,4 +226,21 @@ void ff_filter_graph_remove_filter(AVFilterGraph *graph, AVFilterContext *filter */ #define FF_FILTER_FLAG_HWFRAME_AWARE (1 << 0) +/** + * Perform any additional setup required for hardware frames. + * + * link->hw_frames_ctx must be set before calling this function. + * Inside link->hw_frames_ctx, the fields format, sw_format, width and + * height must be set. If dynamically allocated pools are not supported, + * then initial_pool_size must also be set, to the minimum hardware frame + * pool size necessary for the filter to work (taking into account any + * frames which need to stored for use in operations as appropriate). If + * default_pool_size is nonzero, then it will be used as the pool size if + * no other modification takes place (this can be used to preserve + * compatibility). + */ +int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link, + int default_pool_size); + + #endif /* AVFILTER_INTERNAL_H */ diff --git a/libavfilter/version.h b/libavfilter/version.h index 62fc97dd27897..00e9bf7a99d5f 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 0 +#define LIBAVFILTER_VERSION_MINOR 1 #define LIBAVFILTER_VERSION_MICRO 0 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ From b128be1748f3920a14a98307265df5f2d3433e1d Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 27 Mar 2017 21:10:10 +0100 Subject: [PATCH 1852/2557] vf_*_vaapi: Support increasing hardware frame pool size Defaults to 10 frames to preserve compatibility, but can allocate fewer if extra_hw_frames is set explicitly. --- libavfilter/vf_deinterlace_vaapi.c | 39 ++++++++++++--------------- libavfilter/vf_scale_vaapi.c | 42 ++++++++++++------------------ 2 files changed, 33 insertions(+), 48 deletions(-) diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c index 95a0f40419c0d..082df89147312 100644 --- a/libavfilter/vf_deinterlace_vaapi.c +++ b/libavfilter/vf_deinterlace_vaapi.c @@ -53,8 +53,6 @@ typedef struct DeintVAAPIContext { AVBufferRef *input_frames_ref; AVHWFramesContext *input_frames; - AVBufferRef *output_frames_ref; - AVHWFramesContext *output_frames; int output_height; int output_width; @@ -236,6 +234,7 @@ static int deint_vaapi_config_output(AVFilterLink *outlink) DeintVAAPIContext *ctx = avctx->priv; AVVAAPIHWConfig *hwconfig = NULL; AVHWFramesConstraints *constraints = NULL; + AVHWFramesContext *output_frames; AVVAAPIFramesContext *va_frames; VAStatus vas; int err; @@ -287,34 +286,35 @@ static int deint_vaapi_config_output(AVFilterLink *outlink) goto fail; } - ctx->output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref); - if (!ctx->output_frames_ref) { + outlink->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->device_ref); + if (!outlink->hw_frames_ctx) { av_log(avctx, AV_LOG_ERROR, "Failed to create HW frame context " "for output.\n"); err = AVERROR(ENOMEM); goto fail; } - ctx->output_frames = (AVHWFramesContext*)ctx->output_frames_ref->data; + output_frames = (AVHWFramesContext*)outlink->hw_frames_ctx->data; - ctx->output_frames->format = AV_PIX_FMT_VAAPI; - ctx->output_frames->sw_format = ctx->input_frames->sw_format; - ctx->output_frames->width = ctx->output_width; - ctx->output_frames->height = ctx->output_height; + output_frames->format = AV_PIX_FMT_VAAPI; + output_frames->sw_format = ctx->input_frames->sw_format; + output_frames->width = ctx->output_width; + output_frames->height = ctx->output_height; - // The number of output frames we need is determined by what follows - // the filter. If it's an encoder with complex frame reference - // structures then this could be very high. - ctx->output_frames->initial_pool_size = 10; + output_frames->initial_pool_size = 4; + + err = ff_filter_init_hw_frames(avctx, outlink, 10); + if (err < 0) + goto fail; - err = av_hwframe_ctx_init(ctx->output_frames_ref); + err = av_hwframe_ctx_init(outlink->hw_frames_ctx); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to initialise VAAPI frame " "context for output: %d\n", err); goto fail; } - va_frames = ctx->output_frames->hwctx; + va_frames = output_frames->hwctx; av_assert0(ctx->va_context == VA_INVALID_ID); vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, @@ -340,18 +340,12 @@ static int deint_vaapi_config_output(AVFilterLink *outlink) outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational) { ctx->field_rate, 1 }); - outlink->hw_frames_ctx = av_buffer_ref(ctx->output_frames_ref); - if (!outlink->hw_frames_ctx) { - err = AVERROR(ENOMEM); - goto fail; - } - av_freep(&hwconfig); av_hwframe_constraints_free(&constraints); return 0; fail: - av_buffer_unref(&ctx->output_frames_ref); + av_buffer_unref(&outlink->hw_frames_ctx); av_freep(&hwconfig); av_hwframe_constraints_free(&constraints); return err; @@ -601,7 +595,6 @@ static av_cold void deint_vaapi_uninit(AVFilterContext *avctx) deint_vaapi_pipeline_uninit(avctx); av_buffer_unref(&ctx->input_frames_ref); - av_buffer_unref(&ctx->output_frames_ref); av_buffer_unref(&ctx->device_ref); } diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c index 4c8f2cf4efd91..0ab5518b5fb21 100644 --- a/libavfilter/vf_scale_vaapi.c +++ b/libavfilter/vf_scale_vaapi.c @@ -22,6 +22,7 @@ #include #include "libavutil/avassert.h" +#include "libavutil/common.h" #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_vaapi.h" #include "libavutil/mem.h" @@ -46,9 +47,6 @@ typedef struct ScaleVAAPIContext { AVBufferRef *input_frames_ref; AVHWFramesContext *input_frames; - AVBufferRef *output_frames_ref; - AVHWFramesContext *output_frames; - char *output_format_string; enum AVPixelFormat output_format; int output_width; @@ -83,7 +81,6 @@ static int scale_vaapi_pipeline_uninit(ScaleVAAPIContext *ctx) ctx->va_config = VA_INVALID_ID; } - av_buffer_unref(&ctx->output_frames_ref); av_buffer_unref(&ctx->device_ref); ctx->hwctx = 0; @@ -115,6 +112,7 @@ static int scale_vaapi_config_output(AVFilterLink *outlink) ScaleVAAPIContext *ctx = avctx->priv; AVVAAPIHWConfig *hwconfig = NULL; AVHWFramesConstraints *constraints = NULL; + AVHWFramesContext *output_frames; AVVAAPIFramesContext *va_frames; VAStatus vas; int err, i; @@ -176,34 +174,35 @@ static int scale_vaapi_config_output(AVFilterLink *outlink) goto fail; } - ctx->output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref); - if (!ctx->output_frames_ref) { + outlink->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->device_ref); + if (!outlink->hw_frames_ctx) { av_log(ctx, AV_LOG_ERROR, "Failed to create HW frame context " "for output.\n"); err = AVERROR(ENOMEM); goto fail; } - ctx->output_frames = (AVHWFramesContext*)ctx->output_frames_ref->data; + output_frames = (AVHWFramesContext*)outlink->hw_frames_ctx->data; + + output_frames->format = AV_PIX_FMT_VAAPI; + output_frames->sw_format = ctx->output_format; + output_frames->width = ctx->output_width; + output_frames->height = ctx->output_height; - ctx->output_frames->format = AV_PIX_FMT_VAAPI; - ctx->output_frames->sw_format = ctx->output_format; - ctx->output_frames->width = ctx->output_width; - ctx->output_frames->height = ctx->output_height; + output_frames->initial_pool_size = 4; - // The number of output frames we need is determined by what follows - // the filter. If it's an encoder with complex frame reference - // structures then this could be very high. - ctx->output_frames->initial_pool_size = 10; + err = ff_filter_init_hw_frames(avctx, outlink, 10); + if (err < 0) + goto fail; - err = av_hwframe_ctx_init(ctx->output_frames_ref); + err = av_hwframe_ctx_init(outlink->hw_frames_ctx); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI frame " "context for output: %d\n", err); goto fail; } - va_frames = ctx->output_frames->hwctx; + va_frames = output_frames->hwctx; av_assert0(ctx->va_context == VA_INVALID_ID); vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, @@ -220,18 +219,12 @@ static int scale_vaapi_config_output(AVFilterLink *outlink) outlink->w = ctx->output_width; outlink->h = ctx->output_height; - outlink->hw_frames_ctx = av_buffer_ref(ctx->output_frames_ref); - if (!outlink->hw_frames_ctx) { - err = AVERROR(ENOMEM); - goto fail; - } - av_freep(&hwconfig); av_hwframe_constraints_free(&constraints); return 0; fail: - av_buffer_unref(&ctx->output_frames_ref); + av_buffer_unref(&outlink->hw_frames_ctx); av_freep(&hwconfig); av_hwframe_constraints_free(&constraints); return err; @@ -410,7 +403,6 @@ static av_cold void scale_vaapi_uninit(AVFilterContext *avctx) scale_vaapi_pipeline_uninit(ctx); av_buffer_unref(&ctx->input_frames_ref); - av_buffer_unref(&ctx->output_frames_ref); av_buffer_unref(&ctx->device_ref); } From e4cdef00263dc8b3c8de9d34ceacd00dc68979c0 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 27 Mar 2017 21:10:23 +0100 Subject: [PATCH 1853/2557] vf_scale_qsv: Support increasing hardware frame pool size The deinterlacer does not change, because it does not allocate any new frames (for output it uses the same pool as the input). --- libavfilter/vf_scale_qsv.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c index 8ef77835dca00..c568e962599d1 100644 --- a/libavfilter/vf_scale_qsv.c +++ b/libavfilter/vf_scale_qsv.c @@ -71,7 +71,6 @@ enum var_name { typedef struct QSVScaleContext { const AVClass *class; - AVBufferRef *out_frames_ref; /* a clone of the main session, used internally for scaling */ mfxSession session; @@ -134,7 +133,6 @@ static void qsvscale_uninit(AVFilterContext *ctx) MFXClose(s->session); s->session = NULL; } - av_buffer_unref(&s->out_frames_ref); av_freep(&s->mem_ids_in); av_freep(&s->mem_ids_out); @@ -163,6 +161,7 @@ static int init_out_pool(AVFilterContext *ctx, int out_width, int out_height) { QSVScaleContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; AVHWFramesContext *in_frames_ctx; AVHWFramesContext *out_frames_ctx; @@ -183,21 +182,25 @@ static int init_out_pool(AVFilterContext *ctx, in_format = in_frames_ctx->sw_format; out_format = (s->format == AV_PIX_FMT_NONE) ? in_format : s->format; - s->out_frames_ref = av_hwframe_ctx_alloc(in_frames_ctx->device_ref); - if (!s->out_frames_ref) + outlink->hw_frames_ctx = av_hwframe_ctx_alloc(in_frames_ctx->device_ref); + if (!outlink->hw_frames_ctx) return AVERROR(ENOMEM); - out_frames_ctx = (AVHWFramesContext*)s->out_frames_ref->data; + out_frames_ctx = (AVHWFramesContext*)outlink->hw_frames_ctx->data; out_frames_hwctx = out_frames_ctx->hwctx; out_frames_ctx->format = AV_PIX_FMT_QSV; out_frames_ctx->width = FFALIGN(out_width, 32); out_frames_ctx->height = FFALIGN(out_height, 32); out_frames_ctx->sw_format = out_format; - out_frames_ctx->initial_pool_size = 32; + out_frames_ctx->initial_pool_size = 4; out_frames_hwctx->frame_type = in_frames_hwctx->frame_type; - ret = av_hwframe_ctx_init(s->out_frames_ref); + ret = ff_filter_init_hw_frames(ctx, outlink, 32); + if (ret < 0) + return ret; + + ret = av_hwframe_ctx_init(outlink->hw_frames_ctx); if (ret < 0) return ret; @@ -264,7 +267,7 @@ static int init_out_session(AVFilterContext *ctx) QSVScaleContext *s = ctx->priv; AVHWFramesContext *in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data; - AVHWFramesContext *out_frames_ctx = (AVHWFramesContext*)s->out_frames_ref->data; + AVHWFramesContext *out_frames_ctx = (AVHWFramesContext*)ctx->outputs[0]->hw_frames_ctx->data; AVQSVFramesContext *in_frames_hwctx = in_frames_ctx->hwctx; AVQSVFramesContext *out_frames_hwctx = out_frames_ctx->hwctx; AVQSVDeviceContext *device_hwctx = in_frames_ctx->device_ctx->hwctx; @@ -405,8 +408,6 @@ static int init_out_session(AVFilterContext *ctx) static int init_scale_session(AVFilterContext *ctx, int in_width, int in_height, int out_width, int out_height) { - QSVScaleContext *s = ctx->priv; - int ret; qsvscale_uninit(ctx); @@ -419,11 +420,6 @@ static int init_scale_session(AVFilterContext *ctx, int in_width, int in_height, if (ret < 0) return ret; - av_buffer_unref(&ctx->outputs[0]->hw_frames_ctx); - ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->out_frames_ref); - if (!ctx->outputs[0]->hw_frames_ctx) - return AVERROR(ENOMEM); - return 0; } From c6bc18bc121ea66df715123c59f7ef9542c0914a Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 5 Aug 2017 22:10:46 +0100 Subject: [PATCH 1854/2557] vf_hwupload/hwmap: Support setting a fixed pool size These filters do not directly know whether the API they are using will support dynamic frame pools, so this is somewhat tricky. If the user sets extra_hw_frames, we assume that they are aware of the problem and set a fixed size based on that. If not, most cases use dynamic sizing just like they did previously. The hardware-reverse-mapping case for hwmap previously had a large fixed size (64) here, primarily as a hack for QSV use - this is removed and extra_hw_frames will need to be set for QSV to work since it requires fixed-size pools (as the other cases do, and which didn't work before). --- libavfilter/vf_hwmap.c | 7 ++++++- libavfilter/vf_hwupload.c | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c index b28cb214565cd..d5ad2768f26ee 100644 --- a/libavfilter/vf_hwmap.c +++ b/libavfilter/vf_hwmap.c @@ -138,7 +138,9 @@ static int hwmap_config_output(AVFilterLink *outlink) frames->sw_format = hwfc->sw_format; frames->width = hwfc->width; frames->height = hwfc->height; - frames->initial_pool_size = 64; + + if (avctx->extra_hw_frames >= 0) + frames->initial_pool_size = 2 + avctx->extra_hw_frames; err = av_hwframe_ctx_init(ctx->hwframes_ref); if (err < 0) { @@ -218,6 +220,9 @@ static int hwmap_config_output(AVFilterLink *outlink) hwfc->width = inlink->w; hwfc->height = inlink->h; + if (avctx->extra_hw_frames >= 0) + hwfc->initial_pool_size = 2 + avctx->extra_hw_frames; + err = av_hwframe_ctx_init(ctx->hwframes_ref); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to create frame " diff --git a/libavfilter/vf_hwupload.c b/libavfilter/vf_hwupload.c index 8cca9f42e2f7b..af4ff9b81fabf 100644 --- a/libavfilter/vf_hwupload.c +++ b/libavfilter/vf_hwupload.c @@ -133,6 +133,9 @@ static int hwupload_config_output(AVFilterLink *outlink) ctx->hwframes->width = inlink->w; ctx->hwframes->height = inlink->h; + if (avctx->extra_hw_frames >= 0) + ctx->hwframes->initial_pool_size = 2 + avctx->extra_hw_frames; + err = av_hwframe_ctx_init(ctx->hwframes_ref); if (err < 0) goto fail; From caecb85014fc81f8734560a150073627eedab78c Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 8 Oct 2017 15:19:17 +0100 Subject: [PATCH 1855/2557] hwcontext: Perform usual initialisation on derived device contexts The initialisation should be common. For libmfx, it was previously happening in the derivation function and this moves it out. --- libavutil/hwcontext.c | 4 ++++ libavutil/hwcontext_qsv.c | 11 ----------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index 2630087b5d4bb..cccbd6234e143 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -645,6 +645,10 @@ int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, goto fail; done: + ret = av_hwdevice_ctx_init(dst_ref); + if (ret < 0) + goto fail; + *dst_ref_ptr = dst_ref; return 0; diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 9270b2258f591..9fa603c3502a0 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -989,7 +989,6 @@ static int qsv_device_derive_from_child(AVHWDeviceContext *ctx, int flags) { AVQSVDeviceContext *hwctx = ctx->hwctx; - QSVDeviceContext *s = ctx->internal->priv; mfxVersion ver = { { 3, 1 } }; mfxHDL handle; @@ -1058,16 +1057,6 @@ static int qsv_device_derive_from_child(AVHWDeviceContext *ctx, goto fail; } - ret = qsv_device_init(ctx); - if (ret < 0) - goto fail; - if (s->handle_type != handle_type) { - av_log(ctx, AV_LOG_ERROR, "Error in child device handle setup: " - "type mismatch (%d != %d).\n", s->handle_type, handle_type); - err = AVERROR_UNKNOWN; - goto fail; - } - return 0; fail: From e412d683fe0349bb8450645813a23158bb4ebd66 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 26 Jun 2017 20:28:07 +0100 Subject: [PATCH 1856/2557] hwcontext: Perform usual uninitialisation on derived frames contexts --- libavutil/hwcontext.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index cccbd6234e143..34fb720a7545b 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -205,19 +205,16 @@ static void hwframe_ctx_free(void *opaque, uint8_t *data) { AVHWFramesContext *ctx = (AVHWFramesContext*)data; - if (ctx->internal->source_frames) { - av_buffer_unref(&ctx->internal->source_frames); + if (ctx->internal->pool_internal) + av_buffer_pool_uninit(&ctx->internal->pool_internal); - } else { - if (ctx->internal->pool_internal) - av_buffer_pool_uninit(&ctx->internal->pool_internal); + if (ctx->internal->hw_type->frames_uninit) + ctx->internal->hw_type->frames_uninit(ctx); - if (ctx->internal->hw_type->frames_uninit) - ctx->internal->hw_type->frames_uninit(ctx); + if (ctx->free) + ctx->free(ctx); - if (ctx->free) - ctx->free(ctx); - } + av_buffer_unref(&ctx->internal->source_frames); av_buffer_unref(&ctx->device_ref); From b7d476b1384fe0e4a2c4d424d880d9c4f0b6f7ca Mon Sep 17 00:00:00 2001 From: Muhammad Faiz Date: Sat, 10 Feb 2018 16:30:14 +0700 Subject: [PATCH 1857/2557] fate/libavcodec: add codec_desc test Remove runtime check at codec_desc.c Reviewed-by: wm4 Reviewed-by: Michael Niedermayer Signed-off-by: Muhammad Faiz --- libavcodec/Makefile | 1 + libavcodec/codec_desc.c | 24 ------------------- libavcodec/tests/codec_desc.c | 45 +++++++++++++++++++++++++++++++++++ tests/fate/libavcodec.mak | 5 ++++ 4 files changed, 51 insertions(+), 24 deletions(-) create mode 100644 libavcodec/tests/codec_desc.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index beaca9ee51b08..3d4b738e0be12 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1090,6 +1090,7 @@ SKIPHEADERS-$(CONFIG_V4L2_M2M) += v4l2_buffers.h v4l2_context.h v4l2_m2m TESTPROGS = avpacket \ celp_math \ + codec_desc \ htmlsubtitles \ imgconvert \ jpeg2000dwt \ diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 15f6489278660..44a54a31c94bf 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -21,10 +21,8 @@ #include -#include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/internal.h" -#include "libavutil/thread.h" #include "avcodec.h" #include "profiles.h" #include "version.h" @@ -3111,26 +3109,6 @@ static const AVCodecDescriptor codec_descriptors[] = { }, }; -#if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 -static void check_validity(void) -{ - int i; - - for (i = 0; i < FF_ARRAY_ELEMS(codec_descriptors) - 1; i++) { - if (codec_descriptors[i].id >= codec_descriptors[i+1].id) { - av_log(NULL, AV_LOG_FATAL, "unsorted codec_id '%s' and '%s'.\n", - codec_descriptors[i].name, codec_descriptors[i+1].name); - av_assert0(0); - } - } -} - -static AVOnce check_validity_once = AV_ONCE_INIT; -#define CHECK_VALIDITY() ff_thread_once(&check_validity_once, check_validity); -#else -#define CHECK_VALIDITY() ((void)0) -#endif - static int descriptor_compare(const void *key, const void *member) { enum AVCodecID id = *(const enum AVCodecID *) key; @@ -3141,8 +3119,6 @@ static int descriptor_compare(const void *key, const void *member) const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id) { - CHECK_VALIDITY(); - return bsearch(&id, codec_descriptors, FF_ARRAY_ELEMS(codec_descriptors), sizeof(codec_descriptors[0]), descriptor_compare); } diff --git a/libavcodec/tests/codec_desc.c b/libavcodec/tests/codec_desc.c new file mode 100644 index 0000000000000..c9b3497343af0 --- /dev/null +++ b/libavcodec/tests/codec_desc.c @@ -0,0 +1,45 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/avcodec.h" + +int main(int argc, char **argv) +{ + const AVCodecDescriptor *old_desc = NULL, *desc; + + while (desc = avcodec_descriptor_next(old_desc)) { + if (old_desc && old_desc->id >= desc->id) { + av_log(NULL, AV_LOG_FATAL, "Unsorted codec_descriptors '%s' and '%s'.\n", old_desc->name, desc->name); + return 1; + } + + if (avcodec_descriptor_get(desc->id) != desc) { + av_log(NULL, AV_LOG_FATAL, "avcodec_descriptor_get() failed with '%s'.\n", desc->name); + return 1; + } + + if (avcodec_descriptor_get_by_name(desc->name) != desc) { + av_log(NULL, AV_LOG_FATAL, "avcodec_descriptor_get_by_name() failed with '%s'.\n", desc->name); + return 1; + } + + old_desc = desc; + } + + return 0; +} diff --git a/tests/fate/libavcodec.mak b/tests/fate/libavcodec.mak index a2d5d9fe33372..d3b2dd874e96e 100644 --- a/tests/fate/libavcodec.mak +++ b/tests/fate/libavcodec.mak @@ -13,6 +13,11 @@ fate-celp_math: libavcodec/tests/celp_math$(EXESUF) fate-celp_math: CMD = run libavcodec/tests/celp_math fate-celp_math: CMP = null +FATE_LIBAVCODEC-yes += fate-codec_desc +fate-codec_desc: libavcodec/tests/codec_desc$(EXESUF) +fate-codec_desc: CMD = run libavcodec/tests/codec_desc +fate-codec_desc: CMP = null + FATE_LIBAVCODEC-$(CONFIG_GOLOMB) += fate-golomb fate-golomb: libavcodec/tests/golomb$(EXESUF) fate-golomb: CMD = run libavcodec/tests/golomb From 8bb9824fcbc5a6ebf68391d70a2c4f03447990d2 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Tue, 30 Jan 2018 18:07:23 +0800 Subject: [PATCH 1858/2557] qsvenc: AVBR is not supported on non-windows OS AVBR is supported from API 1.3 but only available for Windows Signed-off-by: Zhong Li Signed-off-by: Maxym Dmytrychenko --- libavcodec/qsvenc.c | 17 ++++++++++++++--- libavcodec/qsvenc.h | 2 ++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 24d9ec4d714be..16d942f00aa3c 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -84,7 +84,9 @@ static const struct { { MFX_RATECONTROL_CBR, "CBR" }, { MFX_RATECONTROL_VBR, "VBR" }, { MFX_RATECONTROL_CQP, "CQP" }, +#if QSV_HAVE_AVBR { MFX_RATECONTROL_AVBR, "AVBR" }, +#endif #if QSV_HAVE_LA { MFX_RATECONTROL_LA, "LA" }, #endif @@ -163,11 +165,14 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, } else if (info->RateControlMethod == MFX_RATECONTROL_CQP) { av_log(avctx, AV_LOG_VERBOSE, "QPI: %"PRIu16"; QPP: %"PRIu16"; QPB: %"PRIu16"\n", info->QPI, info->QPP, info->QPB); - } else if (info->RateControlMethod == MFX_RATECONTROL_AVBR) { + } +#if QSV_HAVE_AVBR + else if (info->RateControlMethod == MFX_RATECONTROL_AVBR) { av_log(avctx, AV_LOG_VERBOSE, "TargetKbps: %"PRIu16"; Accuracy: %"PRIu16"; Convergence: %"PRIu16"\n", info->TargetKbps, info->Accuracy, info->Convergence); } +#endif #if QSV_HAVE_LA else if (info->RateControlMethod == MFX_RATECONTROL_LA #if QSV_HAVE_LA_HRD @@ -333,10 +338,14 @@ static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) else if (avctx->rc_max_rate == avctx->bit_rate) { rc_mode = MFX_RATECONTROL_CBR; rc_desc = "constant bitrate (CBR)"; - } else if (!avctx->rc_max_rate) { + } +#if QSV_HAVE_AVBR + else if (!avctx->rc_max_rate) { rc_mode = MFX_RATECONTROL_AVBR; rc_desc = "average variable bitrate (AVBR)"; - } else { + } +#endif + else { rc_mode = MFX_RATECONTROL_VBR; rc_desc = "variable bitrate (VBR)"; } @@ -522,11 +531,13 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->param.mfx.QPB = av_clip(quant * fabs(avctx->b_quant_factor) + avctx->b_quant_offset, 0, 51); break; +#if QSV_HAVE_AVBR case MFX_RATECONTROL_AVBR: q->param.mfx.TargetKbps = avctx->bit_rate / 1000; q->param.mfx.Convergence = q->avbr_convergence; q->param.mfx.Accuracy = q->avbr_accuracy; break; +#endif #if QSV_HAVE_LA case MFX_RATECONTROL_LA: q->param.mfx.TargetKbps = avctx->bit_rate / 1000; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 088a61de548bb..725651e2e1fe9 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -46,10 +46,12 @@ #define QSV_HAVE_LA_HRD QSV_VERSION_ATLEAST(1, 11) #if defined(_WIN32) +#define QSV_HAVE_AVBR QSV_VERSION_ATLEAST(1, 3) #define QSV_HAVE_ICQ QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_VCM QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_QVBR QSV_VERSION_ATLEAST(1, 11) #else +#define QSV_HAVE_AVBR 0 #define QSV_HAVE_ICQ 0 #define QSV_HAVE_VCM 0 #define QSV_HAVE_QVBR 0 From 9b09792c90b580842157ca8ce534be434725a841 Mon Sep 17 00:00:00 2001 From: Ruiling Song Date: Sun, 11 Feb 2018 15:43:45 +0800 Subject: [PATCH 1859/2557] lavc/qsv: default la_ds to MFX_LOOKAHEAD_DS_UNKNOWN MFX_LOOKAHEAD_DS_UNKNOWN means auto. -1 is not a valid value. Signed-off-by: Ruiling Song Signed-off-by: Maxym Dmytrychenko --- libavcodec/qsvenc.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 725651e2e1fe9..31537b2663cf7 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -73,8 +73,9 @@ { "slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_QUALITY }, INT_MIN, INT_MAX, VE, "preset" }, \ { "la_depth", "Number of frames to analyze before encoding.", OFFSET(qsv.la_depth), AV_OPT_TYPE_INT, { .i64 = 9 }, 9, 100, VE, "la_depth" }, \ { "unset", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 9 }, INT_MIN, INT_MAX, VE, "la_depth" }, \ -{ "la_ds", "Downscaling factor for the frames saved for the lookahead analysis", OFFSET(qsv.la_ds), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, MFX_LOOKAHEAD_DS_4x, VE, "la_ds" }, \ -{ "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, VE, "la_ds" }, \ +{ "la_ds", "Downscaling factor for the frames saved for the lookahead analysis", OFFSET(qsv.la_ds), AV_OPT_TYPE_INT, \ + { .i64 = MFX_LOOKAHEAD_DS_UNKNOWN }, MFX_LOOKAHEAD_DS_UNKNOWN, MFX_LOOKAHEAD_DS_4x, VE, "la_ds" }, \ +{ "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_UNKNOWN }, INT_MIN, INT_MAX, VE, "la_ds" }, \ { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_OFF }, INT_MIN, INT_MAX, VE, "la_ds" }, \ { "2x", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_2x }, INT_MIN, INT_MAX, VE, "la_ds" }, \ { "4x", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_4x }, INT_MIN, INT_MAX, VE, "la_ds" }, \ From 5b6213ef6bf5e0781c83e86926eb0b33a98dc185 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 14 Dec 2013 17:11:21 +0100 Subject: [PATCH 1860/2557] avcodec/vc1dec: fix mby_start for interlaced content Bug-Id: 1100 Bug-Id: ffmpeg/Ticket2531 Cc: libav-stable@libav.org --- libavcodec/vc1dec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 890211019a1c8..5005a2148be4d 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -652,7 +652,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, buf_size3 << 3); /* assuming that the field marker is at the exact middle, hope it's correct */ - slices[n_slices].mby_start = s->mb_height >> 1; + slices[n_slices].mby_start = s->mb_height + 1 >> 1; n_slices1 = n_slices - 1; // index of the last slice of the first field n_slices++; break; @@ -700,7 +700,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, buf_size3 = vc1_unescape_buffer(divider + 4, buf + buf_size - divider - 4, slices[n_slices].buf); init_get_bits(&slices[n_slices].gb, slices[n_slices].buf, buf_size3 << 3); - slices[n_slices].mby_start = s->mb_height >> 1; + slices[n_slices].mby_start = s->mb_height + 1 >> 1; n_slices1 = n_slices - 1; n_slices++; } From a674b31240e99a369059385b03582b35629d190f Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 9 Feb 2018 17:48:27 +0000 Subject: [PATCH 1861/2557] build: Ignore generated mpeg12framerate test binary --- libavcodec/tests/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/tests/.gitignore b/libavcodec/tests/.gitignore index 31fa59b01802b..488a3be24021c 100644 --- a/libavcodec/tests/.gitignore +++ b/libavcodec/tests/.gitignore @@ -3,4 +3,5 @@ /fft-fixed /golomb /iirfilter +/mpeg12framerate /rangecoder From 50945482a75c009ad932ccda5c7d406e8319e54f Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 10 Feb 2018 13:16:36 +0000 Subject: [PATCH 1862/2557] h264_idct: enable unmacro on newer NASM versions Signed-off-by: Rostislav Pehlivanov --- libavcodec/x86/h264_idct.asm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/x86/h264_idct.asm b/libavcodec/x86/h264_idct.asm index 88046380913d4..c54f9f1a6832a 100644 --- a/libavcodec/x86/h264_idct.asm +++ b/libavcodec/x86/h264_idct.asm @@ -1144,7 +1144,11 @@ IDCT_DC_DEQUANT 0 INIT_MMX sse2 IDCT_DC_DEQUANT 7 -; %unmacro STORE_DIFFx2 8 ; remove macro from x86util.asm but yasm doesn't have this yet +%ifdef __NASM_VER__ +%if __NASM_MAJOR__ >= 2 && __NASM_MINOR__ >= 4 +%unmacro STORE_DIFFx2 8 ; remove macro from x86util.asm but yasm doesn't have this yet +%endif +%endif %macro STORE_DIFFx2 8 ; add1, add2, reg1, reg2, zero, shift, source, stride movd %3, [%7] movd %4, [%7+%8] From 192ea5bb77a7ca0b28c41f21ae6dc779dedca9da Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 12 Feb 2018 11:29:07 -0300 Subject: [PATCH 1863/2557] avformat/Makefile: use individual dependencies for librtmp protocols Fixes compilation of libavformat when librtmp is enabled but all the relevant protocols are disabled. Signed-off-by: James Almer --- libavformat/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index 404873624d684..7ac1ba95ad47f 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -555,7 +555,11 @@ OBJS-$(CONFIG_CHROMAPRINT_MUXER) += chromaprint.o OBJS-$(CONFIG_LIBGME_DEMUXER) += libgme.o OBJS-$(CONFIG_LIBMODPLUG_DEMUXER) += libmodplug.o OBJS-$(CONFIG_LIBOPENMPT_DEMUXER) += libopenmpt.o -OBJS-$(CONFIG_LIBRTMP) += librtmp.o +OBJS-$(CONFIG_LIBRTMP_PROTOCOL) += librtmp.o +OBJS-$(CONFIG_LIBRTMPE_PROTOCOL) += librtmp.o +OBJS-$(CONFIG_LIBRTMPS_PROTOCOL) += librtmp.o +OBJS-$(CONFIG_LIBRTMPT_PROTOCOL) += librtmp.o +OBJS-$(CONFIG_LIBRTMPTE_PROTOCOL) += librtmp.o OBJS-$(CONFIG_LIBSSH_PROTOCOL) += libssh.o OBJS-$(CONFIG_LIBSMBCLIENT_PROTOCOL) += libsmbclient.o From e023334661e6eafcf638ffc2a780fd495fc25ec9 Mon Sep 17 00:00:00 2001 From: Richard Shaffer Date: Thu, 1 Feb 2018 18:37:45 -0800 Subject: [PATCH 1864/2557] libavformat/aac: Parse ID3 tags between ADTS frames. While rare, ID3 tags may be inserted between ADTS frames. This change enables parsing them and setting the appropriate metadata updated event flag. --- libavformat/aacdec.c | 45 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/libavformat/aacdec.c b/libavformat/aacdec.c index 36d558ff54cd2..5ec706bdc7a9e 100644 --- a/libavformat/aacdec.c +++ b/libavformat/aacdec.c @@ -22,8 +22,10 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "avio_internal.h" #include "internal.h" #include "id3v1.h" +#include "id3v2.h" #include "apetag.h" #define ADTS_HEADER_SIZE 7 @@ -116,13 +118,52 @@ static int adts_aac_read_header(AVFormatContext *s) return 0; } +static int handle_id3(AVFormatContext *s, AVPacket *pkt) +{ + AVDictionary *metadata = NULL; + AVIOContext ioctx; + ID3v2ExtraMeta *id3v2_extra_meta = NULL; + int ret; + + ret = av_append_packet(s->pb, pkt, ff_id3v2_tag_len(pkt->data) - pkt->size); + if (ret < 0) { + av_packet_unref(pkt); + return ret; + } + + ffio_init_context(&ioctx, pkt->data, pkt->size, 0, NULL, NULL, NULL, NULL); + ff_id3v2_read_dict(&ioctx, &metadata, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); + if ((ret = ff_id3v2_parse_priv_dict(&metadata, &id3v2_extra_meta)) < 0) + goto error; + + if (metadata) { + if ((ret = av_dict_copy(&s->metadata, metadata, 0)) < 0) + goto error; + s->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED; + } + +error: + av_packet_unref(pkt); + ff_id3v2_free_extra_meta(&id3v2_extra_meta); + av_dict_free(&metadata); + + return ret; +} + static int adts_aac_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret, fsize; - ret = av_get_packet(s->pb, pkt, ADTS_HEADER_SIZE); + ret = av_get_packet(s->pb, pkt, FFMAX(ID3v2_HEADER_SIZE, ADTS_HEADER_SIZE)); + + if (ret >= ID3v2_HEADER_SIZE && ff_id3v2_match(pkt->data, ID3v2_DEFAULT_MAGIC)) { + if ((ret = handle_id3(s, pkt)) >= 0) + ret = av_get_packet(s->pb, pkt, ADTS_HEADER_SIZE); + } + if (ret < 0) return ret; + if (ret < ADTS_HEADER_SIZE) { av_packet_unref(pkt); return AVERROR(EIO); @@ -139,7 +180,7 @@ static int adts_aac_read_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR_INVALIDDATA; } - ret = av_append_packet(s->pb, pkt, fsize - ADTS_HEADER_SIZE); + ret = av_append_packet(s->pb, pkt, fsize - pkt->size); if (ret < 0) av_packet_unref(pkt); From 81d1e1e5094bfb85464f87f51f22b0b5ca4d84bb Mon Sep 17 00:00:00 2001 From: Richard Shaffer Date: Sat, 3 Feb 2018 23:24:45 -0800 Subject: [PATCH 1865/2557] fate: add aac id3v2 demux test A basic test for demuxing raw AAC (ADTS) with ID3v2 tags. --- tests/fate/demux.mak | 3 +- tests/ref/fate/adts-id3v2-demux | 240 ++++++++++++++++++++++++++++++++ 2 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 tests/ref/fate/adts-id3v2-demux diff --git a/tests/fate/demux.mak b/tests/fate/demux.mak index 9427ac30c8ccf..306904b9dec57 100644 --- a/tests/fate/demux.mak +++ b/tests/fate/demux.mak @@ -1,9 +1,10 @@ FATE_SAMPLES_DEMUX-$(call DEMDEC, AVI, FRAPS) += fate-avio-direct fate-avio-direct: CMD = framecrc -avioflags direct -i $(TARGET_SAMPLES)/fraps/fraps-v5-bouncing-balls-partial.avi -avioflags direct -FATE_SAMPLES_DEMUX-$(call DEMDEC, AAC, AAC) += fate-adts-demux fate-adts-id3v1-demux +FATE_SAMPLES_DEMUX-$(call DEMDEC, AAC, AAC) += fate-adts-demux fate-adts-id3v1-demux fate-adts-id3v2-demux fate-adts-demux: CMD = crc -i $(TARGET_SAMPLES)/aac/ct_faac-adts.aac -c:a copy fate-adts-id3v1-demux: CMD = framecrc -f aac -i $(TARGET_SAMPLES)/aac/id3v1.aac -c:a copy +fate-adts-id3v2-demux: CMD = framecrc -f aac -i $(TARGET_SAMPLES)/aac/id3v2.aac -c:a copy FATE_SAMPLES_DEMUX-$(CONFIG_AEA_DEMUXER) += fate-aea-demux fate-aea-demux: CMD = crc -i $(TARGET_SAMPLES)/aea/chirp.aea -c:a copy diff --git a/tests/ref/fate/adts-id3v2-demux b/tests/ref/fate/adts-id3v2-demux new file mode 100644 index 0000000000000..db00e3b81eb9b --- /dev/null +++ b/tests/ref/fate/adts-id3v2-demux @@ -0,0 +1,240 @@ +#tb 0: 1/28224000 +#media_type 0: audio +#codec_id 0: aac +#sample_rate 0: 48000 +#channel_layout 0: 4 +#channel_layout_name 0: mono +0, 0, 0, 602112, 126, 0x639a3a5b +0, 602112, 602112, 602112, 135, 0x5b1f3ced +0, 1204224, 1204224, 602112, 123, 0xfcb73863 +0, 1806336, 1806336, 602112, 126, 0x639a3a5b +0, 2408448, 2408448, 602112, 135, 0x5b1f3ced +0, 3010560, 3010560, 602112, 123, 0xfcb73863 +0, 3612672, 3612672, 602112, 144, 0xa0434540 +0, 4214784, 4214784, 602112, 119, 0x45053cc1 +0, 4816896, 4816896, 602112, 111, 0x23043aaf +0, 5419008, 5419008, 602112, 126, 0x693a3a67 +0, 6021120, 6021120, 602112, 149, 0x31304a34 +0, 6623232, 6623232, 602112, 111, 0x21603aab +0, 7225344, 7225344, 602112, 132, 0xe42d43b3 +0, 7827456, 7827456, 602112, 135, 0x5b1f3ced +0, 8429568, 8429568, 602112, 123, 0xfe8b3867 +0, 9031680, 9031680, 602112, 144, 0xa26b4544 +0, 9633792, 9633792, 602112, 129, 0xf7de3bc7 +0, 10235904, 10235904, 602112, 111, 0x1fbc3aa7 +0, 10838016, 10838016, 602112, 126, 0x657a3a5f +0, 11440128, 11440128, 602112, 140, 0xdb6542ec +0, 12042240, 12042240, 602112, 123, 0xfcb73863 +0, 12644352, 12644352, 602112, 138, 0xad7e44b6 +0, 13246464, 13246464, 602112, 119, 0x46c93cc5 +0, 13848576, 13848576, 602112, 123, 0xfe8b3867 +0, 14450688, 14450688, 602112, 144, 0xa26b4544 +0, 15052800, 15052800, 602112, 129, 0xf7de3bc7 +0, 15654912, 15654912, 602112, 111, 0x1fbc3aa7 +0, 16257024, 16257024, 602112, 126, 0x657a3a5f +0, 16859136, 16859136, 602112, 140, 0xdb6542ec +0, 17461248, 17461248, 602112, 123, 0xfcb73863 +0, 18063360, 18063360, 602112, 138, 0xad7e44b6 +0, 18665472, 18665472, 602112, 119, 0x46c93cc5 +0, 19267584, 19267584, 602112, 123, 0xfe8b3867 +0, 19869696, 19869696, 602112, 144, 0xa26b4544 +0, 20471808, 20471808, 602112, 129, 0xf7de3bc7 +0, 21073920, 21073920, 602112, 111, 0x1fbc3aa7 +0, 21676032, 21676032, 602112, 126, 0x657a3a5f +0, 22278144, 22278144, 602112, 140, 0xdb6542ec +0, 22880256, 22880256, 602112, 123, 0xfcb73863 +0, 23482368, 23482368, 602112, 138, 0xad7e44b6 +0, 24084480, 24084480, 602112, 119, 0x488d3cc9 +0, 24686592, 24686592, 602112, 123, 0xfe8b3867 +0, 25288704, 25288704, 602112, 144, 0xa26b4544 +0, 25890816, 25890816, 602112, 129, 0xf7de3bc7 +0, 26492928, 26492928, 602112, 111, 0x1fbc3aa7 +0, 27095040, 27095040, 602112, 126, 0x657a3a5f +0, 27697152, 27697152, 602112, 140, 0xdb6542ec +0, 28299264, 28299264, 602112, 123, 0xfcb73863 +0, 28901376, 28901376, 602112, 126, 0x639a3a5b +0, 29503488, 29503488, 602112, 135, 0x5b1f3ced +0, 30105600, 30105600, 602112, 123, 0xfcb73863 +0, 30707712, 30707712, 602112, 126, 0x639a3a5b +0, 31309824, 31309824, 602112, 135, 0x5b1f3ced +0, 31911936, 31911936, 602112, 123, 0xfcb73863 +0, 32514048, 32514048, 602112, 144, 0xa0434540 +0, 33116160, 33116160, 602112, 119, 0x45053cc1 +0, 33718272, 33718272, 602112, 111, 0x23043aaf +0, 34320384, 34320384, 602112, 126, 0x693a3a67 +0, 34922496, 34922496, 602112, 149, 0x31304a34 +0, 35524608, 35524608, 602112, 111, 0x21603aab +0, 36126720, 36126720, 602112, 132, 0xe42d43b3 +0, 36728832, 36728832, 602112, 135, 0x5b1f3ced +0, 37330944, 37330944, 602112, 123, 0xfe8b3867 +0, 37933056, 37933056, 602112, 144, 0xa26b4544 +0, 38535168, 38535168, 602112, 129, 0xf7de3bc7 +0, 39137280, 39137280, 602112, 111, 0x1fbc3aa7 +0, 39739392, 39739392, 602112, 126, 0x657a3a5f +0, 40341504, 40341504, 602112, 140, 0xdb6542ec +0, 40943616, 40943616, 602112, 123, 0xfcb73863 +0, 41545728, 41545728, 602112, 138, 0xad7e44b6 +0, 42147840, 42147840, 602112, 119, 0x46c93cc5 +0, 42749952, 42749952, 602112, 123, 0xfe8b3867 +0, 43352064, 43352064, 602112, 144, 0xa26b4544 +0, 43954176, 43954176, 602112, 129, 0xf7de3bc7 +0, 44556288, 44556288, 602112, 111, 0x1fbc3aa7 +0, 45158400, 45158400, 602112, 126, 0x657a3a5f +0, 45760512, 45760512, 602112, 140, 0xdb6542ec +0, 46362624, 46362624, 602112, 123, 0xfcb73863 +0, 46964736, 46964736, 602112, 138, 0xad7e44b6 +0, 47566848, 47566848, 602112, 119, 0x46c93cc5 +0, 48168960, 48168960, 602112, 123, 0xfe8b3867 +0, 48771072, 48771072, 602112, 144, 0xa26b4544 +0, 49373184, 49373184, 602112, 129, 0xf7de3bc7 +0, 49975296, 49975296, 602112, 111, 0x1fbc3aa7 +0, 50577408, 50577408, 602112, 126, 0x657a3a5f +0, 51179520, 51179520, 602112, 140, 0xdb6542ec +0, 51781632, 51781632, 602112, 123, 0xfcb73863 +0, 52383744, 52383744, 602112, 138, 0xad7e44b6 +0, 52985856, 52985856, 602112, 119, 0x488d3cc9 +0, 53587968, 53587968, 602112, 123, 0xfe8b3867 +0, 54190080, 54190080, 602112, 144, 0xa26b4544 +0, 54792192, 54792192, 602112, 129, 0xf7de3bc7 +0, 55394304, 55394304, 602112, 111, 0x1fbc3aa7 +0, 55996416, 55996416, 602112, 126, 0x657a3a5f +0, 56598528, 56598528, 602112, 140, 0xdb6542ec +0, 57200640, 57200640, 602112, 123, 0xfcb73863 +0, 57802752, 57802752, 602112, 126, 0x639a3a5b +0, 58404864, 58404864, 602112, 135, 0x5b1f3ced +0, 59006976, 59006976, 602112, 123, 0xfcb73863 +0, 59609088, 59609088, 602112, 126, 0x639a3a5b +0, 60211200, 60211200, 602112, 135, 0x5b1f3ced +0, 60813312, 60813312, 602112, 123, 0xfcb73863 +0, 61415424, 61415424, 602112, 144, 0xa0434540 +0, 62017536, 62017536, 602112, 119, 0x45053cc1 +0, 62619648, 62619648, 602112, 111, 0x23043aaf +0, 63221760, 63221760, 602112, 126, 0x693a3a67 +0, 63823872, 63823872, 602112, 149, 0x31304a34 +0, 64425984, 64425984, 602112, 111, 0x21603aab +0, 65028096, 65028096, 602112, 132, 0xe42d43b3 +0, 65630208, 65630208, 602112, 135, 0x5b1f3ced +0, 66232320, 66232320, 602112, 123, 0xfe8b3867 +0, 66834432, 66834432, 602112, 144, 0xa26b4544 +0, 67436544, 67436544, 602112, 129, 0xf7de3bc7 +0, 68038656, 68038656, 602112, 111, 0x1fbc3aa7 +0, 68640768, 68640768, 602112, 126, 0x657a3a5f +0, 69242880, 69242880, 602112, 140, 0xdb6542ec +0, 69844992, 69844992, 602112, 123, 0xfcb73863 +0, 70447104, 70447104, 602112, 138, 0xad7e44b6 +0, 71049216, 71049216, 602112, 119, 0x46c93cc5 +0, 71651328, 71651328, 602112, 123, 0xfe8b3867 +0, 72253440, 72253440, 602112, 144, 0xa26b4544 +0, 72855552, 72855552, 602112, 129, 0xf7de3bc7 +0, 73457664, 73457664, 602112, 111, 0x1fbc3aa7 +0, 74059776, 74059776, 602112, 126, 0x657a3a5f +0, 74661888, 74661888, 602112, 140, 0xdb6542ec +0, 75264000, 75264000, 602112, 123, 0xfcb73863 +0, 75866112, 75866112, 602112, 138, 0xad7e44b6 +0, 76468224, 76468224, 602112, 119, 0x46c93cc5 +0, 77070336, 77070336, 602112, 123, 0xfe8b3867 +0, 77672448, 77672448, 602112, 144, 0xa26b4544 +0, 78274560, 78274560, 602112, 129, 0xf7de3bc7 +0, 78876672, 78876672, 602112, 111, 0x1fbc3aa7 +0, 79478784, 79478784, 602112, 126, 0x657a3a5f +0, 80080896, 80080896, 602112, 140, 0xdb6542ec +0, 80683008, 80683008, 602112, 123, 0xfcb73863 +0, 81285120, 81285120, 602112, 138, 0xad7e44b6 +0, 81887232, 81887232, 602112, 119, 0x488d3cc9 +0, 82489344, 82489344, 602112, 123, 0xfe8b3867 +0, 83091456, 83091456, 602112, 144, 0xa26b4544 +0, 83693568, 83693568, 602112, 129, 0xf7de3bc7 +0, 84295680, 84295680, 602112, 111, 0x1fbc3aa7 +0, 84897792, 84897792, 602112, 126, 0x657a3a5f +0, 85499904, 85499904, 602112, 140, 0xdb6542ec +0, 86102016, 86102016, 602112, 123, 0xfcb73863 +0, 86704128, 86704128, 602112, 126, 0x639a3a5b +0, 87306240, 87306240, 602112, 135, 0x5b1f3ced +0, 87908352, 87908352, 602112, 123, 0xfcb73863 +0, 88510464, 88510464, 602112, 126, 0x639a3a5b +0, 89112576, 89112576, 602112, 135, 0x5b1f3ced +0, 89714688, 89714688, 602112, 123, 0xfcb73863 +0, 90316800, 90316800, 602112, 144, 0xa0434540 +0, 90918912, 90918912, 602112, 119, 0x45053cc1 +0, 91521024, 91521024, 602112, 111, 0x23043aaf +0, 92123136, 92123136, 602112, 126, 0x693a3a67 +0, 92725248, 92725248, 602112, 149, 0x31304a34 +0, 93327360, 93327360, 602112, 111, 0x21603aab +0, 93929472, 93929472, 602112, 132, 0xe42d43b3 +0, 94531584, 94531584, 602112, 135, 0x5b1f3ced +0, 95133696, 95133696, 602112, 123, 0xfe8b3867 +0, 95735808, 95735808, 602112, 144, 0xa26b4544 +0, 96337920, 96337920, 602112, 129, 0xf7de3bc7 +0, 96940032, 96940032, 602112, 111, 0x1fbc3aa7 +0, 97542144, 97542144, 602112, 126, 0x657a3a5f +0, 98144256, 98144256, 602112, 140, 0xdb6542ec +0, 98746368, 98746368, 602112, 123, 0xfcb73863 +0, 99348480, 99348480, 602112, 138, 0xad7e44b6 +0, 99950592, 99950592, 602112, 119, 0x46c93cc5 +0, 100552704, 100552704, 602112, 123, 0xfe8b3867 +0, 101154816, 101154816, 602112, 144, 0xa26b4544 +0, 101756928, 101756928, 602112, 129, 0xf7de3bc7 +0, 102359040, 102359040, 602112, 111, 0x1fbc3aa7 +0, 102961152, 102961152, 602112, 126, 0x657a3a5f +0, 103563264, 103563264, 602112, 140, 0xdb6542ec +0, 104165376, 104165376, 602112, 123, 0xfcb73863 +0, 104767488, 104767488, 602112, 138, 0xad7e44b6 +0, 105369600, 105369600, 602112, 119, 0x46c93cc5 +0, 105971712, 105971712, 602112, 123, 0xfe8b3867 +0, 106573824, 106573824, 602112, 144, 0xa26b4544 +0, 107175936, 107175936, 602112, 129, 0xf7de3bc7 +0, 107778048, 107778048, 602112, 111, 0x1fbc3aa7 +0, 108380160, 108380160, 602112, 126, 0x657a3a5f +0, 108982272, 108982272, 602112, 140, 0xdb6542ec +0, 109584384, 109584384, 602112, 123, 0xfcb73863 +0, 110186496, 110186496, 602112, 138, 0xad7e44b6 +0, 110788608, 110788608, 602112, 119, 0x488d3cc9 +0, 111390720, 111390720, 602112, 123, 0xfe8b3867 +0, 111992832, 111992832, 602112, 144, 0xa26b4544 +0, 112594944, 112594944, 602112, 129, 0xf7de3bc7 +0, 113197056, 113197056, 602112, 111, 0x1fbc3aa7 +0, 113799168, 113799168, 602112, 126, 0x657a3a5f +0, 114401280, 114401280, 602112, 140, 0xdb6542ec +0, 115003392, 115003392, 602112, 123, 0xfcb73863 +0, 115605504, 115605504, 602112, 126, 0x639a3a5b +0, 116207616, 116207616, 602112, 135, 0x5b1f3ced +0, 116809728, 116809728, 602112, 123, 0xfcb73863 +0, 117411840, 117411840, 602112, 126, 0x639a3a5b +0, 118013952, 118013952, 602112, 135, 0x5b1f3ced +0, 118616064, 118616064, 602112, 123, 0xfcb73863 +0, 119218176, 119218176, 602112, 144, 0xa0434540 +0, 119820288, 119820288, 602112, 119, 0x45053cc1 +0, 120422400, 120422400, 602112, 111, 0x23043aaf +0, 121024512, 121024512, 602112, 126, 0x693a3a67 +0, 121626624, 121626624, 602112, 149, 0x31304a34 +0, 122228736, 122228736, 602112, 111, 0x21603aab +0, 122830848, 122830848, 602112, 132, 0xe42d43b3 +0, 123432960, 123432960, 602112, 135, 0x5b1f3ced +0, 124035072, 124035072, 602112, 123, 0xfe8b3867 +0, 124637184, 124637184, 602112, 144, 0xa26b4544 +0, 125239296, 125239296, 602112, 129, 0xf7de3bc7 +0, 125841408, 125841408, 602112, 111, 0x1fbc3aa7 +0, 126443520, 126443520, 602112, 126, 0x657a3a5f +0, 127045632, 127045632, 602112, 140, 0xdb6542ec +0, 127647744, 127647744, 602112, 123, 0xfcb73863 +0, 128249856, 128249856, 602112, 138, 0xad7e44b6 +0, 128851968, 128851968, 602112, 119, 0x46c93cc5 +0, 129454080, 129454080, 602112, 123, 0xfe8b3867 +0, 130056192, 130056192, 602112, 144, 0xa26b4544 +0, 130658304, 130658304, 602112, 129, 0xf7de3bc7 +0, 131260416, 131260416, 602112, 111, 0x1fbc3aa7 +0, 131862528, 131862528, 602112, 126, 0x657a3a5f +0, 132464640, 132464640, 602112, 140, 0xdb6542ec +0, 133066752, 133066752, 602112, 123, 0xfcb73863 +0, 133668864, 133668864, 602112, 138, 0xad7e44b6 +0, 134270976, 134270976, 602112, 119, 0x46c93cc5 +0, 134873088, 134873088, 602112, 123, 0xfe8b3867 +0, 135475200, 135475200, 602112, 144, 0xa26b4544 +0, 136077312, 136077312, 602112, 129, 0xf7de3bc7 +0, 136679424, 136679424, 602112, 111, 0x1fbc3aa7 +0, 137281536, 137281536, 602112, 126, 0x657a3a5f +0, 137883648, 137883648, 602112, 140, 0xdb6542ec +0, 138485760, 138485760, 602112, 123, 0xfcb73863 +0, 139087872, 139087872, 602112, 138, 0xad7e44b6 +0, 139689984, 139689984, 602112, 119, 0x488d3cc9 +0, 140292096, 140292096, 602112, 123, 0xfe8b3867 From d401ba6b3d86091dff2fae326c610f0120ee8853 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sun, 11 Feb 2018 20:41:32 +0100 Subject: [PATCH 1866/2557] lavf/matroskaenc: Force the minimum value for -reserve_index_space to 2. Fixes an assertion failure: Assertion size >= 2 failed at libavformat/matroskaenc.c:298 --- libavformat/matroskaenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index f22c2ab70cced..5950b4de4436f 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -2001,6 +2001,8 @@ static int mkv_write_header(AVFormatContext *s) } if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && mkv->reserve_cues_space) { mkv->cues_pos = avio_tell(pb); + if (mkv->reserve_cues_space == 1) + mkv->reserve_cues_space++; put_ebml_void(pb, mkv->reserve_cues_space); } From a5ed07940c6929cadc44073f355cd15cfba7161e Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 12 Feb 2018 22:53:05 +0000 Subject: [PATCH 1867/2557] fate: Fix fate-api reference files after AVCodecContext change Broken by d23fff0d8a0e7df170c67a9dd5c1f7c1fc0da489. --- tests/ref/fate/api-mjpeg-codec-param | 2 ++ tests/ref/fate/api-png-codec-param | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/ref/fate/api-mjpeg-codec-param b/tests/ref/fate/api-mjpeg-codec-param index 178b7c73cb076..e5ad2b76566f7 100644 --- a/tests/ref/fate/api-mjpeg-codec-param +++ b/tests/ref/fate/api-mjpeg-codec-param @@ -137,6 +137,7 @@ stream=0, decode=0 video_size=400x225 max_pixels=2147483647 hwaccel_flags=0x00000001 + extra_hw_frames=-1 stream=0, decode=1 b=0 ab=0 @@ -276,3 +277,4 @@ stream=0, decode=1 video_size=400x225 max_pixels=2147483647 hwaccel_flags=0x00000001 + extra_hw_frames=-1 diff --git a/tests/ref/fate/api-png-codec-param b/tests/ref/fate/api-png-codec-param index c6ea7c62967f2..f04ffa757dc2d 100644 --- a/tests/ref/fate/api-png-codec-param +++ b/tests/ref/fate/api-png-codec-param @@ -137,6 +137,7 @@ stream=0, decode=0 video_size=128x128 max_pixels=2147483647 hwaccel_flags=0x00000001 + extra_hw_frames=-1 stream=0, decode=1 b=0 ab=0 @@ -276,3 +277,4 @@ stream=0, decode=1 video_size=128x128 max_pixels=2147483647 hwaccel_flags=0x00000001 + extra_hw_frames=-1 From ce6ce595cf10778f77ae586b606203ecb2914ed8 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 10 Feb 2018 19:03:36 +0100 Subject: [PATCH 1868/2557] avcodec/mpeg12enc: add support for specifying video_format in the sequence_display_extension In a recent commit the default was changed from 0 (component) to 5 (unspecified), however some standards require using 0. With this option, the user will be able to do so. Reviewed-by: Michael Niedermayer Signed-off-by: Marton Balint --- doc/encoders.texi | 5 +++++ libavcodec/mpeg12enc.c | 12 ++++++++++-- libavcodec/mpegvideo.h | 7 +++++++ libavcodec/version.h | 2 +- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index c5dfc646d962a..f25d47e272015 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -2359,6 +2359,11 @@ Never write it. @itemx always Always write it. @end table +@item video_format @var{integer} +Specifies the video_format written into the sequence display extension +indicating the source of the video pictures. The default is @samp{unspecified}, +can be @samp{component}, @samp{pal}, @samp{ntsc}, @samp{secam} or @samp{mac}. +For maximum compatibility, use @samp{component}. @end table @section png diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 0084f544f2716..d0b458e34bdb4 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -348,12 +348,13 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) height != s->height || s->avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || s->avctx->color_trc != AVCOL_TRC_UNSPECIFIED || - s->avctx->colorspace != AVCOL_SPC_UNSPECIFIED); + s->avctx->colorspace != AVCOL_SPC_UNSPECIFIED || + s->video_format != VIDEO_FORMAT_UNSPECIFIED); if (s->seq_disp_ext == 1 || (s->seq_disp_ext == -1 && use_seq_disp_ext)) { put_header(s, EXT_START_CODE); put_bits(&s->pb, 4, 2); // sequence display extension - put_bits(&s->pb, 3, 5); // video_format: 5 is unspecified + put_bits(&s->pb, 3, s->video_format); // video_format put_bits(&s->pb, 1, 1); // colour_description put_bits(&s->pb, 8, s->avctx->color_primaries); // colour_primaries put_bits(&s->pb, 8, s->avctx->color_trc); // transfer_characteristics @@ -1125,6 +1126,13 @@ static const AVOption mpeg2_options[] = { { "auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, VE, "seq_disp_ext" }, { "never", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, VE, "seq_disp_ext" }, { "always", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, VE, "seq_disp_ext" }, + { "video_format", "Video_format in the sequence_display_extension indicating the source of the video.", OFFSET(video_format), AV_OPT_TYPE_INT, { .i64 = VIDEO_FORMAT_UNSPECIFIED }, 0, 7, VE, "video_format" }, + { "component", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_COMPONENT }, 0, 0, VE, "video_format" }, + { "pal", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_PAL }, 0, 0, VE, "video_format" }, + { "ntsc", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_NTSC }, 0, 0, VE, "video_format" }, + { "secam", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_SECAM }, 0, 0, VE, "video_format" }, + { "mac", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_MAC }, 0, 0, VE, "video_format" }, + { "unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_UNSPECIFIED}, 0, 0, VE, "video_format" }, FF_MPV_COMMON_OPTS { NULL }, }; diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index c5e3359458df7..e800e4a3b8d08 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -464,6 +464,13 @@ typedef struct MpegEncContext { int intra_vlc_format; int alternate_scan; int seq_disp_ext; + int video_format; +#define VIDEO_FORMAT_COMPONENT 0 +#define VIDEO_FORMAT_PAL 1 +#define VIDEO_FORMAT_NTSC 2 +#define VIDEO_FORMAT_SECAM 3 +#define VIDEO_FORMAT_MAC 4 +#define VIDEO_FORMAT_UNSPECIFIED 5 int repeat_first_field; int chroma_420_type; int chroma_format; diff --git a/libavcodec/version.h b/libavcodec/version.h index 3597a1a380ef3..d13dd41fa3e60 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 11 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From c837cd3d4d11b7d304ff83a448831c81a53c8c25 Mon Sep 17 00:00:00 2001 From: Ray Tiley Date: Sun, 11 Feb 2018 16:16:45 -0800 Subject: [PATCH 1869/2557] avdevice/decklink_dec: extract NTSC VANC This changes how NTSC VANC is extracted from the buffer. In NTSC the vanc data is interleaved between luma and chroma, and not just the luma as in high definition resolutions. In my testing this allows a decklink card encoding valid NTSC closed captions to pass the caption data to the x264 encoder. Updated with reviews from Devin Heitmueller and Marton Balint. Signed-off-by: Ray Tiley Signed-off-by: Marton Balint --- libavdevice/decklink_dec.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 5c116f2d1371d..c3bb46e18f9bf 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -149,6 +149,17 @@ static void extract_luma_from_v210(uint16_t *dst, const uint8_t *src, int width) } } +static void unpack_v210(uint16_t *dst, const uint8_t *src, int width) +{ + int i; + for (i = 0; i < width * 2 / 3; i++) { + *dst++ = src[0] + ((src[1] & 3) << 8); + *dst++ = (src[1] >> 2) + ((src[2] & 15) << 6); + *dst++ = (src[2] >> 4) + ((src[3] & 63) << 4); + src += 4; + } +} + static uint8_t calc_parity_and_line_offset(int line) { uint8_t ret = (line < 313) << 5; @@ -752,9 +763,15 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( for (i = vanc_line_numbers[idx].vanc_start; i <= vanc_line_numbers[idx].vanc_end; i++) { uint8_t *buf; if (vanc->GetBufferForVerticalBlankingLine(i, (void**)&buf) == S_OK) { - uint16_t luma_vanc[MAX_WIDTH_VANC]; - extract_luma_from_v210(luma_vanc, buf, videoFrame->GetWidth()); - txt_buf = get_metadata(avctx, luma_vanc, videoFrame->GetWidth(), + uint16_t vanc[MAX_WIDTH_VANC]; + size_t vanc_size = videoFrame->GetWidth(); + if (ctx->bmd_mode == bmdModeNTSC && videoFrame->GetWidth() * 2 <= MAX_WIDTH_VANC) { + vanc_size = vanc_size * 2; + unpack_v210(vanc, buf, videoFrame->GetWidth()); + } else { + extract_luma_from_v210(vanc, buf, videoFrame->GetWidth()); + } + txt_buf = get_metadata(avctx, vanc, vanc_size, txt_buf, sizeof(txt_buf0) - (txt_buf - txt_buf0), &pkt); } if (i == vanc_line_numbers[idx].field0_vanc_end) From 474194a8d0f2812802c275f6ed4f0fd5cd58ae0e Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 13 Feb 2018 04:11:27 +0100 Subject: [PATCH 1870/2557] avutil/opt: remove ABI hacks These were needed for ABI compatibility with Libav. We don't need them anymore. --- libavutil/opt.h | 18 +++++++++--------- libavutil/version.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libavutil/opt.h b/libavutil/opt.h index 555929dd6b130..391720f2e25ac 100644 --- a/libavutil/opt.h +++ b/libavutil/opt.h @@ -229,15 +229,15 @@ enum AVOptionType{ AV_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length AV_OPT_TYPE_DICT, AV_OPT_TYPE_UINT64, - AV_OPT_TYPE_CONST = 128, - AV_OPT_TYPE_IMAGE_SIZE = MKBETAG('S','I','Z','E'), ///< offset must point to two consecutive integers - AV_OPT_TYPE_PIXEL_FMT = MKBETAG('P','F','M','T'), - AV_OPT_TYPE_SAMPLE_FMT = MKBETAG('S','F','M','T'), - AV_OPT_TYPE_VIDEO_RATE = MKBETAG('V','R','A','T'), ///< offset must point to AVRational - AV_OPT_TYPE_DURATION = MKBETAG('D','U','R',' '), - AV_OPT_TYPE_COLOR = MKBETAG('C','O','L','R'), - AV_OPT_TYPE_CHANNEL_LAYOUT = MKBETAG('C','H','L','A'), - AV_OPT_TYPE_BOOL = MKBETAG('B','O','O','L'), + AV_OPT_TYPE_CONST, + AV_OPT_TYPE_IMAGE_SIZE, ///< offset must point to two consecutive integers + AV_OPT_TYPE_PIXEL_FMT, + AV_OPT_TYPE_SAMPLE_FMT, + AV_OPT_TYPE_VIDEO_RATE, ///< offset must point to AVRational + AV_OPT_TYPE_DURATION, + AV_OPT_TYPE_COLOR, + AV_OPT_TYPE_CHANNEL_LAYOUT, + AV_OPT_TYPE_BOOL, }; /** diff --git a/libavutil/version.h b/libavutil/version.h index d81ec6fa7bf9e..a2a820aebf03d 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -80,7 +80,7 @@ #define LIBAVUTIL_VERSION_MAJOR 56 #define LIBAVUTIL_VERSION_MINOR 7 -#define LIBAVUTIL_VERSION_MICRO 100 +#define LIBAVUTIL_VERSION_MICRO 101 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ From 71f39de2a57efc8db1d607b09c162c3b806cd45d Mon Sep 17 00:00:00 2001 From: Xiaohan Wang Date: Sat, 3 Feb 2018 01:43:35 -0800 Subject: [PATCH 1871/2557] avcodec/h264_cavlc: Set valid qscale value in ff_h264_decode_mb_cavlc() When ff_h264_decode_mb_cavlc() failed due to wrong sl->qscale values, e.g. dquant out of range, set the qscale to be a valid value before returning -1 and exiting the function. The qscale value can be used later e.g. in loop filter. BUG=806122 Signed-off-by: Michael Niedermayer --- libavcodec/h264_cavlc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/h264_cavlc.c b/libavcodec/h264_cavlc.c index 187b1c64e26aa..5e6a20304a564 100644 --- a/libavcodec/h264_cavlc.c +++ b/libavcodec/h264_cavlc.c @@ -1111,6 +1111,7 @@ int ff_h264_decode_mb_cavlc(const H264Context *h, H264SliceContext *sl) else sl->qscale -= max_qp+1; if (((unsigned)sl->qscale) > max_qp){ av_log(h->avctx, AV_LOG_ERROR, "dquant out of range (%d) at %d %d\n", dquant, sl->mb_x, sl->mb_y); + sl->qscale = max_qp; return -1; } } From dc77e64f2d41a9a778b11afbfa8709e1ce483ef1 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Mon, 12 Feb 2018 22:21:06 +0100 Subject: [PATCH 1872/2557] lavf/rtpdec*: Constify all RTPDynamicProtocolHandler. Reviewed-by: Muhammad Faiz --- libavformat/rtpdec_ac3.c | 2 +- libavformat/rtpdec_amr.c | 4 +- libavformat/rtpdec_asf.c | 2 +- libavformat/rtpdec_dv.c | 2 +- libavformat/rtpdec_formats.h | 84 +++++++++++++++---------------- libavformat/rtpdec_g726.c | 4 +- libavformat/rtpdec_h261.c | 2 +- libavformat/rtpdec_h263.c | 4 +- libavformat/rtpdec_h263_rfc2190.c | 2 +- libavformat/rtpdec_h264.c | 2 +- libavformat/rtpdec_hevc.c | 2 +- libavformat/rtpdec_ilbc.c | 2 +- libavformat/rtpdec_jpeg.c | 2 +- libavformat/rtpdec_latm.c | 2 +- libavformat/rtpdec_mpa_robust.c | 2 +- libavformat/rtpdec_mpeg12.c | 4 +- libavformat/rtpdec_mpeg4.c | 4 +- libavformat/rtpdec_mpegts.c | 2 +- libavformat/rtpdec_qcelp.c | 2 +- libavformat/rtpdec_qdm2.c | 2 +- libavformat/rtpdec_rfc4175.c | 2 +- libavformat/rtpdec_svq3.c | 2 +- libavformat/rtpdec_vc2hq.c | 2 +- libavformat/rtpdec_vp8.c | 2 +- libavformat/rtpdec_vp9.c | 2 +- libavformat/rtpdec_xiph.c | 4 +- 26 files changed, 73 insertions(+), 73 deletions(-) diff --git a/libavformat/rtpdec_ac3.c b/libavformat/rtpdec_ac3.c index 48b2d9cf98b4b..56a379f86ccc2 100644 --- a/libavformat/rtpdec_ac3.c +++ b/libavformat/rtpdec_ac3.c @@ -122,7 +122,7 @@ static int ac3_handle_packet(AVFormatContext *ctx, PayloadContext *data, return 0; } -RTPDynamicProtocolHandler ff_ac3_dynamic_handler = { +const RTPDynamicProtocolHandler ff_ac3_dynamic_handler = { .enc_name = "ac3", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_AC3, diff --git a/libavformat/rtpdec_amr.c b/libavformat/rtpdec_amr.c index 8687e654a3c52..35d322281102e 100644 --- a/libavformat/rtpdec_amr.c +++ b/libavformat/rtpdec_amr.c @@ -182,7 +182,7 @@ static int amr_parse_sdp_line(AVFormatContext *s, int st_index, return 0; } -RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler = { +const RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler = { .enc_name = "AMR", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_AMR_NB, @@ -192,7 +192,7 @@ RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler = { .parse_packet = amr_handle_packet, }; -RTPDynamicProtocolHandler ff_amr_wb_dynamic_handler = { +const RTPDynamicProtocolHandler ff_amr_wb_dynamic_handler = { .enc_name = "AMR-WB", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_AMR_WB, diff --git a/libavformat/rtpdec_asf.c b/libavformat/rtpdec_asf.c index 09f214a71c9c9..54ffef68767ef 100644 --- a/libavformat/rtpdec_asf.c +++ b/libavformat/rtpdec_asf.c @@ -300,7 +300,7 @@ static void asfrtp_close_context(PayloadContext *asf) } #define RTP_ASF_HANDLER(n, s, t) \ -RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \ +const RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \ .enc_name = s, \ .codec_type = t, \ .codec_id = AV_CODEC_ID_NONE, \ diff --git a/libavformat/rtpdec_dv.c b/libavformat/rtpdec_dv.c index de99d277950c8..53a5855ad360c 100644 --- a/libavformat/rtpdec_dv.c +++ b/libavformat/rtpdec_dv.c @@ -131,7 +131,7 @@ static int dv_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_dv_ctx, return 0; } -RTPDynamicProtocolHandler ff_dv_dynamic_handler = { +const RTPDynamicProtocolHandler ff_dv_dynamic_handler = { .enc_name = "DV", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_DVVIDEO, diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h index a436c9d62c60d..dad2b8ac1bb05 100644 --- a/libavformat/rtpdec_formats.h +++ b/libavformat/rtpdec_formats.h @@ -47,47 +47,47 @@ int ff_h264_handle_frag_packet(AVPacket *pkt, const uint8_t *buf, int len, int nal_header_len); void ff_h264_parse_framesize(AVCodecParameters *par, const char *p); -extern RTPDynamicProtocolHandler ff_ac3_dynamic_handler; -extern RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler; -extern RTPDynamicProtocolHandler ff_amr_wb_dynamic_handler; -extern RTPDynamicProtocolHandler ff_dv_dynamic_handler; -extern RTPDynamicProtocolHandler ff_g726_16_dynamic_handler; -extern RTPDynamicProtocolHandler ff_g726_24_dynamic_handler; -extern RTPDynamicProtocolHandler ff_g726_32_dynamic_handler; -extern RTPDynamicProtocolHandler ff_g726_40_dynamic_handler; -extern RTPDynamicProtocolHandler ff_g726le_16_dynamic_handler; -extern RTPDynamicProtocolHandler ff_g726le_24_dynamic_handler; -extern RTPDynamicProtocolHandler ff_g726le_32_dynamic_handler; -extern RTPDynamicProtocolHandler ff_g726le_40_dynamic_handler; -extern RTPDynamicProtocolHandler ff_h261_dynamic_handler; -extern RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler; -extern RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler; -extern RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler; -extern RTPDynamicProtocolHandler ff_h264_dynamic_handler; -extern RTPDynamicProtocolHandler ff_hevc_dynamic_handler; -extern RTPDynamicProtocolHandler ff_ilbc_dynamic_handler; -extern RTPDynamicProtocolHandler ff_jpeg_dynamic_handler; -extern RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler; -extern RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler; -extern RTPDynamicProtocolHandler ff_mpeg_audio_dynamic_handler; -extern RTPDynamicProtocolHandler ff_mpeg_audio_robust_dynamic_handler; -extern RTPDynamicProtocolHandler ff_mpeg_video_dynamic_handler; -extern RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler; -extern RTPDynamicProtocolHandler ff_mpegts_dynamic_handler; -extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfa_handler; -extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfv_handler; -extern RTPDynamicProtocolHandler ff_qcelp_dynamic_handler; -extern RTPDynamicProtocolHandler ff_qdm2_dynamic_handler; -extern RTPDynamicProtocolHandler ff_qt_rtp_aud_handler; -extern RTPDynamicProtocolHandler ff_qt_rtp_vid_handler; -extern RTPDynamicProtocolHandler ff_quicktime_rtp_aud_handler; -extern RTPDynamicProtocolHandler ff_quicktime_rtp_vid_handler; -extern RTPDynamicProtocolHandler ff_rfc4175_rtp_handler; -extern RTPDynamicProtocolHandler ff_svq3_dynamic_handler; -extern RTPDynamicProtocolHandler ff_theora_dynamic_handler; -extern RTPDynamicProtocolHandler ff_vc2hq_dynamic_handler; -extern RTPDynamicProtocolHandler ff_vorbis_dynamic_handler; -extern RTPDynamicProtocolHandler ff_vp8_dynamic_handler; -extern RTPDynamicProtocolHandler ff_vp9_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_ac3_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_amr_wb_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_dv_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_g726_16_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_g726_24_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_g726_32_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_g726_40_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_g726le_16_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_g726le_24_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_g726le_32_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_g726le_40_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_h261_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_h264_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_hevc_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_ilbc_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_jpeg_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_mpeg_audio_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_mpeg_audio_robust_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_mpeg_video_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_mpegts_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_ms_rtp_asf_pfa_handler; +extern const RTPDynamicProtocolHandler ff_ms_rtp_asf_pfv_handler; +extern const RTPDynamicProtocolHandler ff_qcelp_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_qdm2_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_qt_rtp_aud_handler; +extern const RTPDynamicProtocolHandler ff_qt_rtp_vid_handler; +extern const RTPDynamicProtocolHandler ff_quicktime_rtp_aud_handler; +extern const RTPDynamicProtocolHandler ff_quicktime_rtp_vid_handler; +extern const RTPDynamicProtocolHandler ff_rfc4175_rtp_handler; +extern const RTPDynamicProtocolHandler ff_svq3_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_theora_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_vc2hq_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_vorbis_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_vp8_dynamic_handler; +extern const RTPDynamicProtocolHandler ff_vp9_dynamic_handler; #endif /* AVFORMAT_RTPDEC_FORMATS_H */ diff --git a/libavformat/rtpdec_g726.c b/libavformat/rtpdec_g726.c index 2de09ac233450..89afd586c2aec 100644 --- a/libavformat/rtpdec_g726.c +++ b/libavformat/rtpdec_g726.c @@ -35,13 +35,13 @@ static av_cold int g726_ ## bitrate ##_init(AVFormatContext *s, int st_index, \ return 0; \ } \ \ -RTPDynamicProtocolHandler ff_g726_ ## bitrate ## _dynamic_handler = { \ +const RTPDynamicProtocolHandler ff_g726_ ## bitrate ## _dynamic_handler = { \ .enc_name = "AAL2-G726-" #bitrate, \ .codec_type = AVMEDIA_TYPE_AUDIO, \ .codec_id = AV_CODEC_ID_ADPCM_G726, \ .init = g726_ ## bitrate ## _init, \ }; \ -RTPDynamicProtocolHandler ff_g726le_ ## bitrate ## _dynamic_handler = { \ +const RTPDynamicProtocolHandler ff_g726le_ ## bitrate ## _dynamic_handler = { \ .enc_name = "G726-" #bitrate, \ .codec_type = AVMEDIA_TYPE_AUDIO, \ .codec_id = AV_CODEC_ID_ADPCM_G726LE, \ diff --git a/libavformat/rtpdec_h261.c b/libavformat/rtpdec_h261.c index 9729f21d15757..a102909c60dbe 100644 --- a/libavformat/rtpdec_h261.c +++ b/libavformat/rtpdec_h261.c @@ -162,7 +162,7 @@ static int h261_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_h261_ctx return 0; } -RTPDynamicProtocolHandler ff_h261_dynamic_handler = { +const RTPDynamicProtocolHandler ff_h261_dynamic_handler = { .enc_name = "H261", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_H261, diff --git a/libavformat/rtpdec_h263.c b/libavformat/rtpdec_h263.c index 97aa4add3685c..9b71ed7efe9d7 100644 --- a/libavformat/rtpdec_h263.c +++ b/libavformat/rtpdec_h263.c @@ -89,7 +89,7 @@ int ff_h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, return 0; } -RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler = { +const RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler = { .enc_name = "H263-1998", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_H263, @@ -97,7 +97,7 @@ RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler = { .parse_packet = ff_h263_handle_packet, }; -RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler = { +const RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler = { .enc_name = "H263-2000", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_H263, diff --git a/libavformat/rtpdec_h263_rfc2190.c b/libavformat/rtpdec_h263_rfc2190.c index 6ba2814be2268..a0f587f5c34bf 100644 --- a/libavformat/rtpdec_h263_rfc2190.c +++ b/libavformat/rtpdec_h263_rfc2190.c @@ -183,7 +183,7 @@ static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, return 0; } -RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler = { +const RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler = { .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_H263, .need_parsing = AVSTREAM_PARSE_FULL, diff --git a/libavformat/rtpdec_h264.c b/libavformat/rtpdec_h264.c index 6f8148ab6d5db..a785120c23097 100644 --- a/libavformat/rtpdec_h264.c +++ b/libavformat/rtpdec_h264.c @@ -408,7 +408,7 @@ static int parse_h264_sdp_line(AVFormatContext *s, int st_index, return 0; } -RTPDynamicProtocolHandler ff_h264_dynamic_handler = { +const RTPDynamicProtocolHandler ff_h264_dynamic_handler = { .enc_name = "H264", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_H264, diff --git a/libavformat/rtpdec_hevc.c b/libavformat/rtpdec_hevc.c index a0e3a7c2f49cf..5a06b2362cc87 100644 --- a/libavformat/rtpdec_hevc.c +++ b/libavformat/rtpdec_hevc.c @@ -347,7 +347,7 @@ static int hevc_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_hevc_ctx return res; } -RTPDynamicProtocolHandler ff_hevc_dynamic_handler = { +const RTPDynamicProtocolHandler ff_hevc_dynamic_handler = { .enc_name = "H265", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_HEVC, diff --git a/libavformat/rtpdec_ilbc.c b/libavformat/rtpdec_ilbc.c index cb48f7661da18..9094f2c786fff 100644 --- a/libavformat/rtpdec_ilbc.c +++ b/libavformat/rtpdec_ilbc.c @@ -66,7 +66,7 @@ static int ilbc_parse_sdp_line(AVFormatContext *s, int st_index, return 0; } -RTPDynamicProtocolHandler ff_ilbc_dynamic_handler = { +const RTPDynamicProtocolHandler ff_ilbc_dynamic_handler = { .enc_name = "iLBC", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_ILBC, diff --git a/libavformat/rtpdec_jpeg.c b/libavformat/rtpdec_jpeg.c index 465d9bc292119..931463cec4090 100644 --- a/libavformat/rtpdec_jpeg.c +++ b/libavformat/rtpdec_jpeg.c @@ -379,7 +379,7 @@ static int jpeg_parse_packet(AVFormatContext *ctx, PayloadContext *jpeg, return AVERROR(EAGAIN); } -RTPDynamicProtocolHandler ff_jpeg_dynamic_handler = { +const RTPDynamicProtocolHandler ff_jpeg_dynamic_handler = { .enc_name = "JPEG", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_MJPEG, diff --git a/libavformat/rtpdec_latm.c b/libavformat/rtpdec_latm.c index a25c07fe52f4d..9087d6bec540b 100644 --- a/libavformat/rtpdec_latm.c +++ b/libavformat/rtpdec_latm.c @@ -162,7 +162,7 @@ static int latm_parse_sdp_line(AVFormatContext *s, int st_index, return 0; } -RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler = { +const RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler = { .enc_name = "MP4A-LATM", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_AAC, diff --git a/libavformat/rtpdec_mpa_robust.c b/libavformat/rtpdec_mpa_robust.c index 86c8958d5cef8..f4716edf747b3 100644 --- a/libavformat/rtpdec_mpa_robust.c +++ b/libavformat/rtpdec_mpa_robust.c @@ -189,7 +189,7 @@ static int mpa_robust_parse_packet(AVFormatContext *ctx, PayloadContext *data, return 0; } -RTPDynamicProtocolHandler ff_mpeg_audio_robust_dynamic_handler = { +const RTPDynamicProtocolHandler ff_mpeg_audio_robust_dynamic_handler = { .enc_name = "mpa-robust", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_MP3ADU, diff --git a/libavformat/rtpdec_mpeg12.c b/libavformat/rtpdec_mpeg12.c index b93de3d9e4da6..43d9d5854c4a9 100644 --- a/libavformat/rtpdec_mpeg12.c +++ b/libavformat/rtpdec_mpeg12.c @@ -48,7 +48,7 @@ static int mpeg_parse_packet(AVFormatContext *ctx, PayloadContext *data, return 0; } -RTPDynamicProtocolHandler ff_mpeg_audio_dynamic_handler = { +const RTPDynamicProtocolHandler ff_mpeg_audio_dynamic_handler = { .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_MP3, .need_parsing = AVSTREAM_PARSE_FULL, @@ -56,7 +56,7 @@ RTPDynamicProtocolHandler ff_mpeg_audio_dynamic_handler = { .static_payload_id = 14, }; -RTPDynamicProtocolHandler ff_mpeg_video_dynamic_handler = { +const RTPDynamicProtocolHandler ff_mpeg_video_dynamic_handler = { .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_MPEG2VIDEO, .need_parsing = AVSTREAM_PARSE_FULL, diff --git a/libavformat/rtpdec_mpeg4.c b/libavformat/rtpdec_mpeg4.c index 994ab49251769..4f705990845e3 100644 --- a/libavformat/rtpdec_mpeg4.c +++ b/libavformat/rtpdec_mpeg4.c @@ -325,7 +325,7 @@ static int parse_sdp_line(AVFormatContext *s, int st_index, return 0; } -RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler = { +const RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler = { .enc_name = "MP4V-ES", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_MPEG4, @@ -334,7 +334,7 @@ RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler = { .parse_sdp_a_line = parse_sdp_line, }; -RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler = { +const RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler = { .enc_name = "mpeg4-generic", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_AAC, diff --git a/libavformat/rtpdec_mpegts.c b/libavformat/rtpdec_mpegts.c index 5bf0f186dbd07..405271f744aa7 100644 --- a/libavformat/rtpdec_mpegts.c +++ b/libavformat/rtpdec_mpegts.c @@ -89,7 +89,7 @@ static int mpegts_handle_packet(AVFormatContext *ctx, PayloadContext *data, return 0; } -RTPDynamicProtocolHandler ff_mpegts_dynamic_handler = { +const RTPDynamicProtocolHandler ff_mpegts_dynamic_handler = { .codec_type = AVMEDIA_TYPE_DATA, .priv_data_size = sizeof(PayloadContext), .parse_packet = mpegts_handle_packet, diff --git a/libavformat/rtpdec_qcelp.c b/libavformat/rtpdec_qcelp.c index 41cc8263dfc90..3485c27b6858d 100644 --- a/libavformat/rtpdec_qcelp.c +++ b/libavformat/rtpdec_qcelp.c @@ -209,7 +209,7 @@ static int qcelp_parse_packet(AVFormatContext *ctx, PayloadContext *data, return return_stored_frame(ctx, data, st, pkt, timestamp, buf, len); } -RTPDynamicProtocolHandler ff_qcelp_dynamic_handler = { +const RTPDynamicProtocolHandler ff_qcelp_dynamic_handler = { .enc_name = "x-Purevoice", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_QCELP, diff --git a/libavformat/rtpdec_qdm2.c b/libavformat/rtpdec_qdm2.c index 1f4fd5aace5e6..fa2b1b9302fbd 100644 --- a/libavformat/rtpdec_qdm2.c +++ b/libavformat/rtpdec_qdm2.c @@ -298,7 +298,7 @@ static int qdm2_parse_packet(AVFormatContext *s, PayloadContext *qdm, return (qdm->cache > 0) ? 1 : 0; } -RTPDynamicProtocolHandler ff_qdm2_dynamic_handler = { +const RTPDynamicProtocolHandler ff_qdm2_dynamic_handler = { .enc_name = "X-QDM", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_NONE, diff --git a/libavformat/rtpdec_rfc4175.c b/libavformat/rtpdec_rfc4175.c index 498381dfd3fb1..e9c62c1389751 100644 --- a/libavformat/rtpdec_rfc4175.c +++ b/libavformat/rtpdec_rfc4175.c @@ -226,7 +226,7 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data, return AVERROR(EAGAIN); } -RTPDynamicProtocolHandler ff_rfc4175_rtp_handler = { +const RTPDynamicProtocolHandler ff_rfc4175_rtp_handler = { .enc_name = "raw", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_BITPACKED, diff --git a/libavformat/rtpdec_svq3.c b/libavformat/rtpdec_svq3.c index 18d79d2e22dad..77164dd6f917e 100644 --- a/libavformat/rtpdec_svq3.c +++ b/libavformat/rtpdec_svq3.c @@ -110,7 +110,7 @@ static void svq3_close_context(PayloadContext *sv) ffio_free_dyn_buf(&sv->pktbuf); } -RTPDynamicProtocolHandler ff_svq3_dynamic_handler = { +const RTPDynamicProtocolHandler ff_svq3_dynamic_handler = { .enc_name = "X-SV3V-ES", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_NONE, // see if (config_packet) above diff --git a/libavformat/rtpdec_vc2hq.c b/libavformat/rtpdec_vc2hq.c index 8a3996a035aeb..1a11ace9a2836 100644 --- a/libavformat/rtpdec_vc2hq.c +++ b/libavformat/rtpdec_vc2hq.c @@ -216,7 +216,7 @@ static int vc2hq_handle_packet(AVFormatContext *ctx, PayloadContext *pl_ctx, return res; } -RTPDynamicProtocolHandler ff_vc2hq_dynamic_handler = { +const RTPDynamicProtocolHandler ff_vc2hq_dynamic_handler = { .enc_name = "VC2", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_DIRAC, diff --git a/libavformat/rtpdec_vp8.c b/libavformat/rtpdec_vp8.c index f0e457b70fbb2..360dd5c782a3e 100644 --- a/libavformat/rtpdec_vp8.c +++ b/libavformat/rtpdec_vp8.c @@ -276,7 +276,7 @@ static int vp8_need_keyframe(PayloadContext *vp8) return vp8->sequence_dirty || !vp8->sequence_ok; } -RTPDynamicProtocolHandler ff_vp8_dynamic_handler = { +const RTPDynamicProtocolHandler ff_vp8_dynamic_handler = { .enc_name = "VP8", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_VP8, diff --git a/libavformat/rtpdec_vp9.c b/libavformat/rtpdec_vp9.c index 4a7f934d6a605..6bbdf4847ad6d 100644 --- a/libavformat/rtpdec_vp9.c +++ b/libavformat/rtpdec_vp9.c @@ -330,7 +330,7 @@ static void vp9_close_context(PayloadContext *vp9) ffio_free_dyn_buf(&vp9->buf); } -RTPDynamicProtocolHandler ff_vp9_dynamic_handler = { +const RTPDynamicProtocolHandler ff_vp9_dynamic_handler = { .enc_name = "VP9", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_VP9, diff --git a/libavformat/rtpdec_xiph.c b/libavformat/rtpdec_xiph.c index 43de6ce343195..574508affb6ec 100644 --- a/libavformat/rtpdec_xiph.c +++ b/libavformat/rtpdec_xiph.c @@ -365,7 +365,7 @@ static int xiph_parse_sdp_line(AVFormatContext *s, int st_index, return 0; } -RTPDynamicProtocolHandler ff_theora_dynamic_handler = { +const RTPDynamicProtocolHandler ff_theora_dynamic_handler = { .enc_name = "theora", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_THEORA, @@ -375,7 +375,7 @@ RTPDynamicProtocolHandler ff_theora_dynamic_handler = { .parse_packet = xiph_handle_packet, }; -RTPDynamicProtocolHandler ff_vorbis_dynamic_handler = { +const RTPDynamicProtocolHandler ff_vorbis_dynamic_handler = { .enc_name = "vorbis", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_VORBIS, From 7c82e0f61e365296b094684fd92aea0fe05ceb93 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sat, 3 Feb 2018 15:22:05 +0100 Subject: [PATCH 1873/2557] avfilter/af_loudnorm: correctly initialize PTS Right now, the PTS always starts out as 0, which causes problems on a seek or when inserting this filter mid-stream. Initialize it instead to AV_NOPTS_VALUE and copy the PTS from the first frame instead if this is the case. --- libavfilter/af_loudnorm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavfilter/af_loudnorm.c b/libavfilter/af_loudnorm.c index a7f11cbe6e22b..314b25fa39f5f 100644 --- a/libavfilter/af_loudnorm.c +++ b/libavfilter/af_loudnorm.c @@ -431,6 +431,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); } + if (s->pts == AV_NOPTS_VALUE) + s->pts = in->pts; + out->pts = s->pts; src = (const double *)in->data[0]; dst = (double *)out->data[0]; @@ -763,7 +766,7 @@ static int config_input(AVFilterLink *inlink) inlink->partial_buf_size = frame_size(inlink->sample_rate, 3000); } - s->pts = + s->pts = AV_NOPTS_VALUE; s->buf_index = s->prev_buf_index = s->limiter_buf_index = 0; From 3b4026e15110547892d5d770b6b43c9e34df458f Mon Sep 17 00:00:00 2001 From: Yusuke Nakamura Date: Wed, 14 Feb 2018 11:43:24 +0900 Subject: [PATCH 1874/2557] avpacket: reset dst side_data fields in av_packet_copy_props This effectively copies the side data elements from src instead of potentially merging them with those already existing in dst. This by extension also removes the only dependency on existing values in the dst packet. Reviewed-by: wm4 Signed-off-by: James Almer --- libavcodec/avpacket.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index 90b821592835e..fe8113ab76455 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -571,6 +571,8 @@ FF_ENABLE_DEPRECATION_WARNINGS dst->flags = src->flags; dst->stream_index = src->stream_index; + dst->side_data = NULL; + dst->side_data_elems = 0; for (i = 0; i < src->side_data_elems; i++) { enum AVPacketSideDataType type = src->side_data[i].type; int size = src->side_data[i].size; From 23e1bf6e51106f54ab75551ccc98361b83ba55fe Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 13 Feb 2018 18:42:04 -0300 Subject: [PATCH 1875/2557] avcodec: remove unnecessary calls to ff_init_buffer_info() And remove the function altogether while at it. It's a duplicate of another. Reviewed-by: wm4 Signed-off-by: James Almer --- libavcodec/decode.c | 11 ++--------- libavcodec/internal.h | 6 ------ libavcodec/pthread_frame.c | 2 -- libavcodec/smvjpegdec.c | 1 - 4 files changed, 2 insertions(+), 18 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 522720c07a955..ea2168ad0cc70 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -130,7 +130,7 @@ static int extract_packet_props(AVCodecInternal *avci, const AVPacket *pkt) if (pkt) { ret = av_packet_copy_props(avci->last_pkt_props, pkt); if (!ret) - avci->last_pkt_props->size = pkt->size; // HACK: Needed for ff_init_buffer_info(). + avci->last_pkt_props->size = pkt->size; // HACK: Needed for ff_decode_frame_props(). } return ret; } @@ -1661,7 +1661,7 @@ static int add_metadata_from_side_data(const AVPacket *avpkt, AVFrame *frame) return av_packet_unpack_dictionary(side_metadata, size, frame_md); } -int ff_init_buffer_info(AVCodecContext *avctx, AVFrame *frame) +int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) { const AVPacket *pkt = avctx->internal->last_pkt_props; int i; @@ -1769,11 +1769,6 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; } -int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) -{ - return ff_init_buffer_info(avctx, frame); -} - static void validate_avframe_allocation(AVCodecContext *avctx, AVFrame *frame) { if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { @@ -1916,8 +1911,6 @@ static int reget_buffer_internal(AVCodecContext *avctx, AVFrame *frame) av_frame_unref(frame); } - ff_init_buffer_info(avctx, frame); - if (!frame->data[0]) return ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF); diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 16bd10128495b..bb92873d7b85c 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -235,12 +235,6 @@ int ff_match_2uint16(const uint16_t (*tab)[2], int size, int a, int b); unsigned int avpriv_toupper4(unsigned int x); -/** - * does needed setup of pkt_pts/pos and such for (re)get_buffer(); - */ -int ff_init_buffer_info(AVCodecContext *s, AVFrame *frame); - - void ff_color_frame(AVFrame *frame, const int color[4]); /** diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 25aa3e2cd22c9..5104b1beba4b2 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -886,8 +886,6 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int f->owner[0] = f->owner[1] = avctx; - ff_init_buffer_info(avctx, f->f); - if (!(avctx->active_thread_type & FF_THREAD_FRAME)) return ff_get_buffer(avctx, f->f, flags); diff --git a/libavcodec/smvjpegdec.c b/libavcodec/smvjpegdec.c index 018e135b30010..0b05d19f7b026 100644 --- a/libavcodec/smvjpegdec.c +++ b/libavcodec/smvjpegdec.c @@ -193,7 +193,6 @@ static int smvjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_siz s->picture[1]->width = avctx->width; s->picture[1]->height = avctx->height; s->picture[1]->format = avctx->pix_fmt; - /* ff_init_buffer_info(avctx, &s->picture[1]); */ smv_img_pnt(s->picture[1]->data, mjpeg_data->data, mjpeg_data->linesize, avctx->pix_fmt, avctx->width, avctx->height, cur_frame); for (i = 0; i < AV_NUM_DATA_POINTERS; i++) From aa6280805e21e1e2c3fb7bb1efb47a27ceeb3fed Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 14 Feb 2018 20:56:21 -0300 Subject: [PATCH 1876/2557] avformat/aviobuf: zero initialize the AVIOContext in ffio_init_context() This makes sure no field is ever used uninitialized. Reviewed-by: Carl Eugen Hoyos Reviewed-by: wm4 Signed-off-by: James Almer --- libavformat/aviobuf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 86eb6579f43e4..d63db3897f4c8 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -87,6 +87,8 @@ int ffio_init_context(AVIOContext *s, int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t (*seek)(void *opaque, int64_t offset, int whence)) { + memset(s, 0, sizeof(AVIOContext)); + s->buffer = buffer; s->orig_buffer_size = s->buffer_size = buffer_size; @@ -135,7 +137,7 @@ AVIOContext *avio_alloc_context( int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t (*seek)(void *opaque, int64_t offset, int whence)) { - AVIOContext *s = av_mallocz(sizeof(AVIOContext)); + AVIOContext *s = av_malloc(sizeof(AVIOContext)); if (!s) return NULL; ffio_init_context(s, buffer, buffer_size, write_flag, opaque, From fb580731c1febec44e0f1ec1433f6b3ee89cfe65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Martinez?= Date: Wed, 14 Feb 2018 08:39:15 +0100 Subject: [PATCH 1877/2557] avcodec/ffv1: Support for GBRAP10 and GBRAP12 Signed-off-by: Michael Niedermayer --- libavcodec/ffv1dec.c | 4 ++++ libavcodec/ffv1dec_template.c | 4 +--- libavcodec/ffv1enc.c | 3 +++ libavcodec/ffv1enc_template.c | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index 923b79f3ab6e3..3d2ee2569faa4 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -688,8 +688,12 @@ static int read_header(FFV1Context *f) f->avctx->pix_fmt = AV_PIX_FMT_GBRP9; else if (f->avctx->bits_per_raw_sample == 10 && !f->transparency) f->avctx->pix_fmt = AV_PIX_FMT_GBRP10; + else if (f->avctx->bits_per_raw_sample == 10 && f->transparency) + f->avctx->pix_fmt = AV_PIX_FMT_GBRAP10; else if (f->avctx->bits_per_raw_sample == 12 && !f->transparency) f->avctx->pix_fmt = AV_PIX_FMT_GBRP12; + else if (f->avctx->bits_per_raw_sample == 12 && f->transparency) + f->avctx->pix_fmt = AV_PIX_FMT_GBRAP12; else if (f->avctx->bits_per_raw_sample == 14 && !f->transparency) f->avctx->pix_fmt = AV_PIX_FMT_GBRP14; else if (f->avctx->bits_per_raw_sample == 16 && !f->transparency) { diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c index a25b3384f1373..f8a42a6d44cac 100644 --- a/libavcodec/ffv1dec_template.c +++ b/libavcodec/ffv1dec_template.c @@ -155,7 +155,7 @@ static void RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[4], int w, int if (lbd) *((uint32_t*)(src[0] + x*4 + stride[0]*y)) = b + ((unsigned)g<<8) + ((unsigned)r<<16) + ((unsigned)a<<24); - else if (sizeof(TYPE) == 4) { + else if (sizeof(TYPE) == 4 || transparency) { *((uint16_t*)(src[0] + x*2 + stride[0]*y)) = g; *((uint16_t*)(src[1] + x*2 + stride[1]*y)) = b; *((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r; @@ -165,8 +165,6 @@ static void RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[4], int w, int *((uint16_t*)(src[0] + x*2 + stride[0]*y)) = b; *((uint16_t*)(src[1] + x*2 + stride[1]*y)) = g; *((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r; - if (transparency) - *((uint16_t*)(src[3] + x*2 + stride[3]*y)) = a; } } } diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index 49b8d590a389b..d71d952c6dbc1 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -648,9 +648,11 @@ FF_ENABLE_DEPRECATION_WARNINGS if (!avctx->bits_per_raw_sample) s->bits_per_raw_sample = 9; case AV_PIX_FMT_GBRP10: + case AV_PIX_FMT_GBRAP10: if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample) s->bits_per_raw_sample = 10; case AV_PIX_FMT_GBRP12: + case AV_PIX_FMT_GBRAP12: if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample) s->bits_per_raw_sample = 12; case AV_PIX_FMT_GBRP14: @@ -1326,6 +1328,7 @@ AVCodec ff_ffv1_encoder = { AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_GRAY16, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, + AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_YA8, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GBRP16, AV_PIX_FMT_RGB48, diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c index b93336538b276..bc0add5ed7c23 100644 --- a/libavcodec/ffv1enc_template.c +++ b/libavcodec/ffv1enc_template.c @@ -160,7 +160,7 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[4], b = p[2]; if (transparency) a = p[3]; - } else if (sizeof(TYPE) == 4) { + } else if (sizeof(TYPE) == 4 || transparency) { g = *((const uint16_t *)(src[0] + x*2 + stride[0]*y)); b = *((const uint16_t *)(src[1] + x*2 + stride[1]*y)); r = *((const uint16_t *)(src[2] + x*2 + stride[2]*y)); From f26a63c4ee1bdbe21d7ab462cd66f8ba20b14244 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 14 Feb 2018 00:32:30 +0100 Subject: [PATCH 1878/2557] avcodec/h264_cabac: Tighten allowed coeff_abs range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: integer overflows Reported-by: "Xiaohan Wang (王消寒)" Based on limits in "8.5 Transform coefficient decoding process and picture construction process prior to deblocking filter process" Signed-off-by: Michael Niedermayer --- libavcodec/h264_cabac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c index ec5fc74b9b1d4..815149a501acb 100644 --- a/libavcodec/h264_cabac.c +++ b/libavcodec/h264_cabac.c @@ -1735,7 +1735,7 @@ decode_cabac_residual_internal(const H264Context *h, H264SliceContext *sl, \ if( coeff_abs >= 15 ) { \ int j = 0; \ - while (get_cabac_bypass(CC) && j < 30) { \ + while (get_cabac_bypass(CC) && j < 16+7) { \ j++; \ } \ \ From 173939259aaefbf622be125ba6871b11d302b974 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 15 Feb 2018 13:48:25 +0100 Subject: [PATCH 1879/2557] avfilter/avf_avectorscope: Fix ;; Signed-off-by: Michael Niedermayer --- libavfilter/avf_avectorscope.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/avf_avectorscope.c b/libavfilter/avf_avectorscope.c index 725ac8bbda1b8..75e0ee5e2a41f 100644 --- a/libavfilter/avf_avectorscope.c +++ b/libavfilter/avf_avectorscope.c @@ -331,7 +331,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) src[1] = -src[1]; if (s->swap) - FFSWAP(float, src[0], src[1]);; + FFSWAP(float, src[0], src[1]); if (s->mode == LISSAJOUS) { x = ((src[1] - src[0]) * zoom / 2 + 1) * hw; From 75027066d8e85ccf42b83f6cf1c3085221148f42 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 15 Feb 2018 13:48:52 +0100 Subject: [PATCH 1880/2557] avdevice/decklink_dec: Fix ;; Signed-off-by: Michael Niedermayer --- libavdevice/decklink_dec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index c3bb46e18f9bf..28a748a28f8ff 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -1070,7 +1070,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) break; case bmdFormat8BitARGB: st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; - st->codecpar->codec_tag = avcodec_pix_fmt_to_codec_tag((enum AVPixelFormat)st->codecpar->format);; + st->codecpar->codec_tag = avcodec_pix_fmt_to_codec_tag((enum AVPixelFormat)st->codecpar->format); st->codecpar->format = AV_PIX_FMT_0RGB; st->codecpar->bit_rate = av_rescale(ctx->bmd_width * ctx->bmd_height * 32, st->time_base.den, st->time_base.num); break; From 8a8d0b319a9f941e1fcfda65f3a77c607cb05af2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Feb 2018 11:12:54 -0300 Subject: [PATCH 1881/2557] avutil/crypto: change length parameter to size_t on the remaining modules See 651ee9346105b9d492e01172ab447c04d03fa32e fcc4ed1efa1a7575dc45fe57ce552af331941469 Signed-off-by: James Almer --- doc/APIchanges | 4 ++++ libavutil/hash.c | 4 ++++ libavutil/hash.h | 6 ++++++ libavutil/murmur3.c | 4 ++++ libavutil/murmur3.h | 6 ++++++ libavutil/ripemd.c | 4 ++++ libavutil/ripemd.h | 4 ++++ 7 files changed, 32 insertions(+) diff --git a/doc/APIchanges b/doc/APIchanges index 8565cbeb094e1..a98475366d100 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-02-xx - xxxxxxx + Change av_ripemd_update(), av_murmur3_update() and av_hash_update() length + parameter type to size_t at next major bump. + 2018-02-xx - xxxxxxx - lavfi 7.12.100 - avfilter.h Add AVFilterContext.extra_hw_frames. diff --git a/libavutil/hash.c b/libavutil/hash.c index 7037b0d6ff7e3..75edb6db78865 100644 --- a/libavutil/hash.c +++ b/libavutil/hash.c @@ -155,7 +155,11 @@ void av_hash_init(AVHashContext *ctx) } } +#if FF_API_CRYPTO_SIZE_T void av_hash_update(AVHashContext *ctx, const uint8_t *src, int len) +#else +void av_hash_update(AVHashContext *ctx, const uint8_t *src, size_t len) +#endif { switch (ctx->type) { case MD5: av_md5_update(ctx->ctx, src, len); break; diff --git a/libavutil/hash.h b/libavutil/hash.h index a20b8934f196f..7693e6bf0dbca 100644 --- a/libavutil/hash.h +++ b/libavutil/hash.h @@ -29,6 +29,8 @@ #include +#include "version.h" + /** * @defgroup lavu_hash Hash Functions * @ingroup lavu_crypto @@ -179,7 +181,11 @@ void av_hash_init(struct AVHashContext *ctx); * @param[in] src Data to be added to the hash context * @param[in] len Size of the additional data */ +#if FF_API_CRYPTO_SIZE_T void av_hash_update(struct AVHashContext *ctx, const uint8_t *src, int len); +#else +void av_hash_update(struct AVHashContext *ctx, const uint8_t *src, size_t len); +#endif /** * Finalize a hash context and compute the actual hash value. diff --git a/libavutil/murmur3.c b/libavutil/murmur3.c index ef853f404abeb..7961752515692 100644 --- a/libavutil/murmur3.c +++ b/libavutil/murmur3.c @@ -89,7 +89,11 @@ static inline uint64_t update_h2(uint64_t k, uint64_t h1, uint64_t h2) return k; } +#if FF_API_CRYPTO_SIZE_T void av_murmur3_update(AVMurMur3 *c, const uint8_t *src, int len) +#else +void av_murmur3_update(AVMurMur3 *c, const uint8_t *src, size_t len) +#endif { const uint8_t *end; uint64_t h1 = c->h1, h2 = c->h2; diff --git a/libavutil/murmur3.h b/libavutil/murmur3.h index 6a1694c08df29..1b09175c1ec21 100644 --- a/libavutil/murmur3.h +++ b/libavutil/murmur3.h @@ -29,6 +29,8 @@ #include +#include "version.h" + /** * @defgroup lavu_murmur3 Murmur3 * @ingroup lavu_hash @@ -97,7 +99,11 @@ void av_murmur3_init(struct AVMurMur3 *c); * @param[in] src Input data to update hash with * @param[in] len Number of bytes to read from `src` */ +#if FF_API_CRYPTO_SIZE_T void av_murmur3_update(struct AVMurMur3 *c, const uint8_t *src, int len); +#else +void av_murmur3_update(struct AVMurMur3 *c, const uint8_t *src, size_t len); +#endif /** * Finish hashing and output digest value. diff --git a/libavutil/ripemd.c b/libavutil/ripemd.c index b0db2970db8a8..4f1c4ea899fbe 100644 --- a/libavutil/ripemd.c +++ b/libavutil/ripemd.c @@ -510,7 +510,11 @@ av_cold int av_ripemd_init(AVRIPEMD *ctx, int bits) return 0; } +#if FF_API_CRYPTO_SIZE_T void av_ripemd_update(AVRIPEMD* ctx, const uint8_t* data, unsigned int len) +#else +void av_ripemd_update(AVRIPEMD* ctx, const uint8_t* data, size_t len) +#endif { unsigned int i, j; diff --git a/libavutil/ripemd.h b/libavutil/ripemd.h index 6d6bb3208f1fb..0db6858ff3321 100644 --- a/libavutil/ripemd.h +++ b/libavutil/ripemd.h @@ -66,7 +66,11 @@ int av_ripemd_init(struct AVRIPEMD* context, int bits); * @param data input data to update hash with * @param len input data length */ +#if FF_API_CRYPTO_SIZE_T void av_ripemd_update(struct AVRIPEMD* context, const uint8_t* data, unsigned int len); +#else +void av_ripemd_update(struct AVRIPEMD* context, const uint8_t* data, size_t len); +#endif /** * Finish hashing and output digest value. From f0809bc0fa634afe8b7c3f2682b8e51e87d0861e Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Wed, 7 Feb 2018 18:05:08 +0530 Subject: [PATCH 1882/2557] avformat/mpegenc - accept PCM_DVD streams PCM_S16BE stream packets in MPEG-PS have a 3-byte header and are recognized as PCM_DVD by the demuxer which prevents their correct remuxing in MPEG-1/2 PS. Signed-off-by: Michael Niedermayer --- libavformat/mpegenc.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c index 695de3f081d93..c84dc52eb9549 100644 --- a/libavformat/mpegenc.c +++ b/libavformat/mpegenc.c @@ -353,7 +353,8 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) if (!s->is_mpeg2 && (st->codecpar->codec_id == AV_CODEC_ID_AC3 || st->codecpar->codec_id == AV_CODEC_ID_DTS || - st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE)) + st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE || + st->codecpar->codec_id == AV_CODEC_ID_PCM_DVD)) av_log(ctx, AV_LOG_WARNING, "%s in MPEG-1 system streams is not widely supported, " "consider using the vob or the dvd muxer " @@ -363,7 +364,12 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) stream->id = ac3_id++; } else if (st->codecpar->codec_id == AV_CODEC_ID_DTS) { stream->id = dts_id++; - } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE) { + } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE || + st->codecpar->codec_id == AV_CODEC_ID_PCM_DVD) { + if (st->codecpar->bits_per_coded_sample != 16) { + av_log(ctx, AV_LOG_ERROR, "Only 16 bit LPCM streams can be muxed.\n"); + goto fail; + } stream->id = lpcm_id++; for (j = 0; j < 4; j++) { if (lpcm_freq_tab[j] == st->codecpar->sample_rate) @@ -1150,6 +1156,19 @@ static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt) return AVERROR(ENOMEM); pkt_desc->pts = pts; pkt_desc->dts = dts; + + if (st->codecpar->codec_id == AV_CODEC_ID_PCM_DVD) { + if (size < 3) { + av_log(ctx, AV_LOG_ERROR, "Invalid packet size %d\n", size); + return AVERROR(EINVAL); + } + + /* Skip first 3 bytes of packet data, which comprise PCM header + and will be written fresh by this muxer. */ + buf += 3; + size -= 3; + } + pkt_desc->unwritten_size = pkt_desc->size = size; if (!stream->predecode_packet) From 310d56e86f494273e2859cf25dd4ae2433f9a2be Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Thu, 15 Feb 2018 17:48:47 +0530 Subject: [PATCH 1883/2557] fate/mpegps: add tests for PCM_DVD stream remux Signed-off-by: Michael Niedermayer --- tests/Makefile | 1 + tests/fate-run.sh | 16 ++++++++ tests/fate/mpegps.mak | 7 ++++ tests/ref/fate/mpegps-remuxed-pcm-demux | 50 +++++++++++++++++++++++++ 4 files changed, 74 insertions(+) create mode 100644 tests/fate/mpegps.mak create mode 100644 tests/ref/fate/mpegps-remuxed-pcm-demux diff --git a/tests/Makefile b/tests/Makefile index 327e3f44201f9..f1ac610454480 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -149,6 +149,7 @@ include $(SRC_PATH)/tests/fate/mov.mak include $(SRC_PATH)/tests/fate/mp3.mak include $(SRC_PATH)/tests/fate/mpc.mak include $(SRC_PATH)/tests/fate/mpeg4.mak +include $(SRC_PATH)/tests/fate/mpegps.mak include $(SRC_PATH)/tests/fate/mpegts.mak include $(SRC_PATH)/tests/fate/mxf.mak include $(SRC_PATH)/tests/fate/opus.mak diff --git a/tests/fate-run.sh b/tests/fate-run.sh index 82862b7ef40a3..457761c152913 100755 --- a/tests/fate-run.sh +++ b/tests/fate-run.sh @@ -226,6 +226,22 @@ transcode(){ -f framecrc - || return } +stream_remux(){ + src_fmt=$1 + srcfile=$2 + enc_fmt=$3 + stream_maps=$4 + final_decode=$5 + encfile="${outdir}/${test}.${enc_fmt}" + test "$7" = -keep || cleanfiles="$cleanfiles $encfile" + tsrcfile=$(target_path $srcfile) + tencfile=$(target_path $encfile) + ffmpeg -f $src_fmt -i $tsrcfile $stream_maps -codec copy $FLAGS \ + -f $enc_fmt -y $tencfile || return + ffmpeg $DEC_OPTS -i $encfile $ENC_OPTS $FLAGS $final_decode \ + -f framecrc - || return +} + lavffatetest(){ t="${test#lavf-fate-}" ref=${base}/ref/lavf-fate/$t diff --git a/tests/fate/mpegps.mak b/tests/fate/mpegps.mak new file mode 100644 index 0000000000000..cec1ea77fa126 --- /dev/null +++ b/tests/fate/mpegps.mak @@ -0,0 +1,7 @@ +# This tests that a 16-bit pcm_dvd stream is correctly remuxed in mpegps +FATE_MPEGPS-$(call DEMMUX, MPEGPS, MPEG1SYSTEM) += fate-mpegps-remuxed-pcm-demux +fate-mpegps-remuxed-pcm-demux: $(TARGET_SAMPLES)/mpegps/pcm_aud.mpg +fate-mpegps-remuxed-pcm-demux: CMD = stream_remux "mpeg" "$(TARGET_SAMPLES)/mpegps/pcm_aud.mpg" "mpeg" "-map 0:a:0" "-codec copy" + +FATE_SAMPLES_FFMPEG += $(FATE_MPEGPS-yes) +fate-mpegps: $(FATE_MPEGPS-yes) diff --git a/tests/ref/fate/mpegps-remuxed-pcm-demux b/tests/ref/fate/mpegps-remuxed-pcm-demux new file mode 100644 index 0000000000000..b5b277868ff50 --- /dev/null +++ b/tests/ref/fate/mpegps-remuxed-pcm-demux @@ -0,0 +1,50 @@ +#tb 0: 1/90000 +#media_type 0: audio +#codec_id 0: pcm_dvd +#sample_rate 0: 44100 +#channel_layout 0: 4 +#channel_layout_name 0: mono +0, 0, 0, 2040, 2005, 0x8e98e563 +0, 2090, 2090, 2069, 2033, 0xd6f2f455 +0, 4180, 4180, 2057, 2021, 0x77a6e6c9 +0, 6269, 6269, 2057, 2021, 0x8dbcf6be +0, 8359, 8359, 2057, 2021, 0xc629eaa0 +0, 10449, 10449, 2057, 2021, 0xa951ebe5 +0, 12539, 12539, 2057, 2021, 0x1324f29b +0, 14629, 14629, 2057, 2021, 0x55f1e968 +0, 16718, 16718, 2057, 2021, 0x98a7f994 +0, 18808, 18808, 2057, 2021, 0xba42f42f +0, 20898, 20898, 2057, 2021, 0xcf5cefe6 +0, 22988, 22988, 2057, 2021, 0xeef8f2b5 +0, 25078, 25078, 2057, 2021, 0x71faf42f +0, 27167, 27167, 2057, 2021, 0x0346f019 +0, 29257, 29257, 2057, 2021, 0xbca0f4a3 +0, 31347, 31347, 2057, 2021, 0x3b6ced4f +0, 33437, 33437, 2057, 2021, 0xc8b9ea0a +0, 35527, 35527, 2057, 2021, 0x18e5f385 +0, 37616, 37616, 2057, 2021, 0x74f6e9d6 +0, 39706, 39706, 2057, 2021, 0x35d8f2b5 +0, 41796, 41796, 2057, 2021, 0x9d2aec53 +0, 43886, 43886, 2057, 2021, 0xf0acf1a0 +0, 45976, 45976, 2057, 2021, 0xa724ebe9 +0, 48065, 48065, 2057, 2021, 0xd4f8f534 +0, 50155, 50155, 2057, 2021, 0xdf62efc6 +0, 52245, 52245, 2057, 2021, 0x9865f504 +0, 54335, 54335, 2057, 2021, 0x8670efb7 +0, 56424, 56424, 2057, 2021, 0xe51af219 +0, 58514, 58514, 2057, 2021, 0x0210f27f +0, 60604, 60604, 2057, 2021, 0x4b08f406 +0, 62694, 62694, 2057, 2021, 0x2b02eed4 +0, 64784, 64784, 2057, 2021, 0x0445ed00 +0, 66873, 66873, 2057, 2021, 0xfae9f21f +0, 68963, 68963, 2057, 2021, 0x3d6beabc +0, 71053, 71053, 2057, 2021, 0xc50af39c +0, 73143, 73143, 2057, 2021, 0xf9eceb82 +0, 75233, 75233, 2057, 2021, 0x7b89eb9b +0, 77322, 77322, 2057, 2021, 0x7c07ef4b +0, 79412, 79412, 2057, 2021, 0xbfacf1eb +0, 81502, 81502, 2057, 2021, 0xccb2f27b +0, 83592, 83592, 2057, 2021, 0xc035f557 +0, 85682, 85682, 2057, 2021, 0xbdf1edea +0, 87771, 87771, 2057, 2021, 0x3644f424 +0, 89861, 89861, 1457, 1433, 0xdd17d51f From ab6f571ef71967da7c7c1cfba483d3597c7357d5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 14 Feb 2018 03:54:13 +0100 Subject: [PATCH 1884/2557] avutil/common: Fix integer overflow in av_clip_uint8_c() and av_clip_uint16_c() Fixes: 5567/clusterfuzz-testcase-minimized-5769966247739392 Fixes: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavutil/common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavutil/common.h b/libavutil/common.h index 5e0382827b083..0fffa67714e81 100644 --- a/libavutil/common.h +++ b/libavutil/common.h @@ -158,7 +158,7 @@ static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, in */ static av_always_inline av_const uint8_t av_clip_uint8_c(int a) { - if (a&(~0xFF)) return (-a)>>31; + if (a&(~0xFF)) return (~a)>>31; else return a; } @@ -180,7 +180,7 @@ static av_always_inline av_const int8_t av_clip_int8_c(int a) */ static av_always_inline av_const uint16_t av_clip_uint16_c(int a) { - if (a&(~0xFFFF)) return (-a)>>31; + if (a&(~0xFFFF)) return (~a)>>31; else return a; } From dd8351b1184b8054925c28ecc5fcb6dbbc177fad Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 14 Feb 2018 13:01:46 +0100 Subject: [PATCH 1885/2557] avcodec/exr: Check remaining bits in last get code loop Fixes: runtime error: shift exponent -7 is negative Fixes: 3902/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_EXR_fuzzer-6081926122176512 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/exr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index f08576af22c61..47f59bd638d7a 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -558,7 +558,7 @@ static int huf_decode(const uint64_t *hcode, const HufDec *hdecod, while (lc > 0) { const HufDec pl = hdecod[(c << (HUF_DECBITS - lc)) & HUF_DECMASK]; - if (pl.len) { + if (pl.len && lc >= pl.len) { lc -= pl.len; get_code(pl.lit, rlc, c, lc, gb, out, oe, outb); } else { From de675648cef7e451ca82fabaee0d8ec1fe653311 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 17 Feb 2018 04:20:52 +0100 Subject: [PATCH 1886/2557] avcodec/vp8: Check for bitstream end before vp7_fade_frame() Fixes: Timeout Fixes: 5653/clusterfuzz-testcase-5497680018014208 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/vp8.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index 7f71a75e4ba06..62b9f8bc2dae2 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -656,6 +656,8 @@ static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si s->fade_present = vp8_rac_get(c); } + if (c->end <= c->buffer && c->bits >= 0) + return AVERROR_INVALIDDATA; /* E. Fading information for previous frame */ if (s->fade_present && vp8_rac_get(c)) { if ((ret = vp7_fade_frame(s ,c)) < 0) From 01370b31aced784593f2bc0836f4ba6fd8e7f6b3 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 17 Feb 2018 04:20:53 +0100 Subject: [PATCH 1887/2557] avcodec/jpeg2000dec: Use av_image_check_size2() Fixes: OOM Fixes: 5733/clusterfuzz-testcase-minimized-4906757966004224 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/jpeg2000dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 4cf8a2880cab7..5414ce565547c 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -285,7 +285,7 @@ static int get_siz(Jpeg2000DecoderContext *s) avpriv_request_sample(s->avctx, "Support for image offsets"); return AVERROR_PATCHWELCOME; } - if (av_image_check_size(s->width, s->height, 0, s->avctx)) { + if (av_image_check_size2(s->width, s->height, s->avctx->max_pixels, AV_PIX_FMT_NONE, 0, s->avctx)) { avpriv_request_sample(s->avctx, "Large Dimensions"); return AVERROR_PATCHWELCOME; } From 1be49cee34eb588d70c2bf4c46dc23539fd71b53 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 17 Feb 2018 04:20:54 +0100 Subject: [PATCH 1888/2557] avcodec/h264: Increase field_poc to 64bit in ff_h264_init_poc() to detect overflows Fixes: Integer overflow Fixes: 5746/clusterfuzz-testcase-minimized-6270097623613440 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/h264_parse.c | 6 +++++- libavcodec/h264_parser.c | 4 +++- libavcodec/h264_slice.c | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c index fee28d90d990a..6cbef5a13dd76 100644 --- a/libavcodec/h264_parse.c +++ b/libavcodec/h264_parse.c @@ -271,7 +271,7 @@ int ff_h264_init_poc(int pic_field_poc[2], int *pic_poc, int picture_structure, int nal_ref_idc) { const int max_frame_num = 1 << sps->log2_max_frame_num; - int field_poc[2]; + int64_t field_poc[2]; pc->frame_num_offset = pc->prev_frame_num_offset; if (pc->frame_num < pc->prev_frame_num) @@ -337,6 +337,10 @@ int ff_h264_init_poc(int pic_field_poc[2], int *pic_poc, field_poc[1] = poc; } + if ( field_poc[0] != (int)field_poc[0] + || field_poc[1] != (int)field_poc[1]) + return AVERROR_INVALIDDATA; + if (picture_structure != PICT_BOTTOM_FIELD) pic_field_poc[0] = field_poc[0]; if (picture_structure != PICT_TOP_FIELD) diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index 65d9d44b50a6f..1a9840a62c542 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -449,8 +449,10 @@ static inline int parse_nal_units(AVCodecParserContext *s, /* Decode POC of this picture. * The prev_ values needed for decoding POC of the next picture are not set here. */ field_poc[0] = field_poc[1] = INT_MAX; - ff_h264_init_poc(field_poc, &s->output_picture_number, sps, + ret = ff_h264_init_poc(field_poc, &s->output_picture_number, sps, &p->poc, p->picture_structure, nal.ref_idc); + if (ret < 0) + goto fail; /* Continue parsing to check if MMCO_RESET is present. * FIXME: MMCO_RESET could appear in non-first slice. diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index e6b7998834c9a..90e05ed8f1021 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1607,8 +1607,10 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl, (h->mb_height * h->mb_stride - 1) * sizeof(*h->slice_table)); } - ff_h264_init_poc(h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc, + ret = ff_h264_init_poc(h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc, h->ps.sps, &h->poc, h->picture_structure, nal->ref_idc); + if (ret < 0) + return ret; memcpy(h->mmco, sl->mmco, sl->nb_mmco * sizeof(*h->mmco)); h->nb_mmco = sl->nb_mmco; From d2fc244293b531cf1ce175155f74202b697a7a23 Mon Sep 17 00:00:00 2001 From: Calvin Walton Date: Fri, 16 Feb 2018 15:02:02 -0500 Subject: [PATCH 1889/2557] libavfilter/vf_fps: Add more fate tests These tests cover specific rounding behaviour, to ensure that I don't introduce any regressions with the rewritten "activate" callback based fps filter. Signed-off-by: Michael Niedermayer --- tests/fate/filter-video.mak | 10 +++++++++- tests/ref/fate/filter-fps-down | 15 +++++++++++++++ tests/ref/fate/filter-fps-down-eof-pass | 16 ++++++++++++++++ tests/ref/fate/filter-fps-down-round-down | 15 +++++++++++++++ tests/ref/fate/filter-fps-down-round-up | 16 ++++++++++++++++ tests/ref/fate/filter-fps-up | 17 +++++++++++++++++ tests/ref/fate/filter-fps-up-round-down | 16 ++++++++++++++++ tests/ref/fate/filter-fps-up-round-up | 17 +++++++++++++++++ 8 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 tests/ref/fate/filter-fps-down create mode 100644 tests/ref/fate/filter-fps-down-eof-pass create mode 100644 tests/ref/fate/filter-fps-down-round-down create mode 100644 tests/ref/fate/filter-fps-down-round-up create mode 100644 tests/ref/fate/filter-fps-up create mode 100644 tests/ref/fate/filter-fps-up-round-down create mode 100644 tests/ref/fate/filter-fps-up-round-up diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 221ae81fdc8c7..e3e128cf67d15 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -108,7 +108,6 @@ FATE_FILTER-$(call ALLYES, AVDEVICE TESTSRC_FILTER FORMAT_FILTER CONCAT_FILTER S fate-filter-lavd-scalenorm: tests/data/filtergraphs/scalenorm fate-filter-lavd-scalenorm: CMD = framecrc -f lavfi -graph_file $(TARGET_PATH)/tests/data/filtergraphs/scalenorm -i dummy - FATE_FILTER-$(call ALLYES, FRAMERATE_FILTER TESTSRC2_FILTER) += fate-filter-framerate-up fate-filter-framerate-down fate-filter-framerate-up: CMD = framecrc -lavfi testsrc2=r=2:d=10,framerate=fps=10 -t 1 fate-filter-framerate-down: CMD = framecrc -lavfi testsrc2=r=2:d=10,framerate=fps=1 -t 1 @@ -426,6 +425,15 @@ fate-filter-concat: CMD = framecrc -filter_complex_script $(TARGET_PATH)/tests/d FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER FPS_FILTER MPDECIMATE_FILTER) += fate-filter-mpdecimate fate-filter-mpdecimate: CMD = framecrc -lavfi testsrc2=r=2:d=10,fps=3,mpdecimate -r 3 -pix_fmt yuv420p +FATE_FILTER-$(call ALLYES, FPS_FILTER TESTSRC2_FILTER) += fate-filter-fps-up fate-filter-fps-up-round-down fate-filter-fps-up-round-up fate-filter-fps-down fate-filter-fps-down-round-down fate-filter-fps-down-round-up fate-filter-fps-down-eof-pass +fate-filter-fps-up: CMD = framecrc -lavfi testsrc2=r=3:d=2,fps=7 +fate-filter-fps-up-round-down: CMD = framecrc -lavfi testsrc2=r=3:d=2,fps=7:round=down +fate-filter-fps-up-round-up: CMD = framecrc -lavfi testsrc2=r=3:d=2,fps=7:round=up +fate-filter-fps-down: CMD = framecrc -lavfi testsrc2=r=7:d=3.5,fps=3 +fate-filter-fps-down-round-down: CMD = framecrc -lavfi testsrc2=r=7:d=3.5,fps=3:round=down +fate-filter-fps-down-round-up: CMD = framecrc -lavfi testsrc2=r=7:d=3.5,fps=3:round=up +fate-filter-fps-down-eof-pass: CMD = framecrc -lavfi testsrc2=r=7:d=3.5,fps=3:eof_action=pass + FATE_FILTER_SAMPLES-$(call ALLYES, MOV_DEMUXER FPS_FILTER QTRLE_DECODER) += fate-filter-fps-cfr fate-filter-fps fate-filter-fps-r fate-filter-fps-cfr: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vsync cfr -pix_fmt yuv420p fate-filter-fps-r: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vf fps -pix_fmt yuv420p diff --git a/tests/ref/fate/filter-fps-down b/tests/ref/fate/filter-fps-down new file mode 100644 index 0000000000000..eb8b36898548b --- /dev/null +++ b/tests/ref/fate/filter-fps-down @@ -0,0 +1,15 @@ +#tb 0: 1/3 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0x0c1062d6 +0, 1, 1, 1, 115200, 0x278d887e +0, 2, 2, 1, 115200, 0x75e1a17b +0, 3, 3, 1, 115200, 0x686b77e7 +0, 4, 4, 1, 115200, 0x1fc2d693 +0, 5, 5, 1, 115200, 0x2d0ba5a4 +0, 6, 6, 1, 115200, 0x40426f99 +0, 7, 7, 1, 115200, 0xc705ccd9 +0, 8, 8, 1, 115200, 0x5635daa5 +0, 9, 9, 1, 115200, 0x7161ef8f diff --git a/tests/ref/fate/filter-fps-down-eof-pass b/tests/ref/fate/filter-fps-down-eof-pass new file mode 100644 index 0000000000000..0b6725f0376e4 --- /dev/null +++ b/tests/ref/fate/filter-fps-down-eof-pass @@ -0,0 +1,16 @@ +#tb 0: 1/3 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0x0c1062d6 +0, 1, 1, 1, 115200, 0x278d887e +0, 2, 2, 1, 115200, 0x75e1a17b +0, 3, 3, 1, 115200, 0x686b77e7 +0, 4, 4, 1, 115200, 0x1fc2d693 +0, 5, 5, 1, 115200, 0x2d0ba5a4 +0, 6, 6, 1, 115200, 0x40426f99 +0, 7, 7, 1, 115200, 0xc705ccd9 +0, 8, 8, 1, 115200, 0x5635daa5 +0, 9, 9, 1, 115200, 0x7161ef8f +0, 10, 10, 1, 115200, 0xccf02fed diff --git a/tests/ref/fate/filter-fps-down-round-down b/tests/ref/fate/filter-fps-down-round-down new file mode 100644 index 0000000000000..4440539b6fddb --- /dev/null +++ b/tests/ref/fate/filter-fps-down-round-down @@ -0,0 +1,15 @@ +#tb 0: 1/3 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0x201b9db1 +0, 1, 1, 1, 115200, 0x309b9c06 +0, 2, 2, 1, 115200, 0xa14e9aca +0, 3, 3, 1, 115200, 0x02b6ab21 +0, 4, 4, 1, 115200, 0x296dd4a5 +0, 5, 5, 1, 115200, 0x59e85f83 +0, 6, 6, 1, 115200, 0xf040bf35 +0, 7, 7, 1, 115200, 0xa76dcd9d +0, 8, 8, 1, 115200, 0x3af5d306 +0, 9, 9, 1, 115200, 0xc8ce7fb1 diff --git a/tests/ref/fate/filter-fps-down-round-up b/tests/ref/fate/filter-fps-down-round-up new file mode 100644 index 0000000000000..c3cf02fd24fae --- /dev/null +++ b/tests/ref/fate/filter-fps-down-round-up @@ -0,0 +1,16 @@ +#tb 0: 1/3 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0x3744b3ed +0, 1, 1, 1, 115200, 0x201b9db1 +0, 2, 2, 1, 115200, 0x309b9c06 +0, 3, 3, 1, 115200, 0xb73857e2 +0, 4, 4, 1, 115200, 0x02b6ab21 +0, 5, 5, 1, 115200, 0x296dd4a5 +0, 6, 6, 1, 115200, 0xc95a675e +0, 7, 7, 1, 115200, 0xf040bf35 +0, 8, 8, 1, 115200, 0xa76dcd9d +0, 9, 9, 1, 115200, 0x0caf7172 +0, 10, 10, 1, 115200, 0xc8ce7fb1 diff --git a/tests/ref/fate/filter-fps-up b/tests/ref/fate/filter-fps-up new file mode 100644 index 0000000000000..f1a847864fab3 --- /dev/null +++ b/tests/ref/fate/filter-fps-up @@ -0,0 +1,17 @@ +#tb 0: 1/7 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0x3744b3ed +0, 1, 1, 1, 115200, 0x3744b3ed +0, 2, 2, 1, 115200, 0x60a58f35 +0, 3, 3, 1, 115200, 0x60a58f35 +0, 4, 4, 1, 115200, 0x60a58f35 +0, 5, 5, 1, 115200, 0x09ffa4e1 +0, 6, 6, 1, 115200, 0x09ffa4e1 +0, 7, 7, 1, 115200, 0x33f15918 +0, 8, 8, 1, 115200, 0x33f15918 +0, 9, 9, 1, 115200, 0xb0dfacf8 +0, 10, 10, 1, 115200, 0xb0dfacf8 +0, 11, 11, 1, 115200, 0xb0dfacf8 diff --git a/tests/ref/fate/filter-fps-up-round-down b/tests/ref/fate/filter-fps-up-round-down new file mode 100644 index 0000000000000..daecb125e3d00 --- /dev/null +++ b/tests/ref/fate/filter-fps-up-round-down @@ -0,0 +1,16 @@ +#tb 0: 1/7 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0x3744b3ed +0, 1, 1, 1, 115200, 0x3744b3ed +0, 2, 2, 1, 115200, 0x60a58f35 +0, 3, 3, 1, 115200, 0x60a58f35 +0, 4, 4, 1, 115200, 0x09ffa4e1 +0, 5, 5, 1, 115200, 0x09ffa4e1 +0, 6, 6, 1, 115200, 0x09ffa4e1 +0, 7, 7, 1, 115200, 0x33f15918 +0, 8, 8, 1, 115200, 0x33f15918 +0, 9, 9, 1, 115200, 0xb0dfacf8 +0, 10, 10, 1, 115200, 0xb0dfacf8 diff --git a/tests/ref/fate/filter-fps-up-round-up b/tests/ref/fate/filter-fps-up-round-up new file mode 100644 index 0000000000000..d69dbf67ffd04 --- /dev/null +++ b/tests/ref/fate/filter-fps-up-round-up @@ -0,0 +1,17 @@ +#tb 0: 1/7 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0x3744b3ed +0, 1, 1, 1, 115200, 0x3744b3ed +0, 2, 2, 1, 115200, 0x3744b3ed +0, 3, 3, 1, 115200, 0x60a58f35 +0, 4, 4, 1, 115200, 0x60a58f35 +0, 5, 5, 1, 115200, 0x09ffa4e1 +0, 6, 6, 1, 115200, 0x09ffa4e1 +0, 7, 7, 1, 115200, 0x33f15918 +0, 8, 8, 1, 115200, 0x33f15918 +0, 9, 9, 1, 115200, 0x33f15918 +0, 10, 10, 1, 115200, 0xb0dfacf8 +0, 11, 11, 1, 115200, 0xb0dfacf8 From f82dd4c09b2decb033f1e339d4be81efd38554f1 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 17 Feb 2018 21:42:34 +0100 Subject: [PATCH 1890/2557] avcodec/hevcdec: Check luma/chroma_log2_weight_denom Fixes: signed integer overflow: 3 + 2147483647 cannot be represented in type 'int' Fixes: 5888/clusterfuzz-testcase-minimized-5634701067812864 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/hevcdec.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 8f1c1f19534cd..fc4eb781dc013 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -151,12 +151,18 @@ static int pred_weight_table(HEVCContext *s, GetBitContext *gb) int luma_log2_weight_denom; luma_log2_weight_denom = get_ue_golomb_long(gb); - if (luma_log2_weight_denom < 0 || luma_log2_weight_denom > 7) + if (luma_log2_weight_denom < 0 || luma_log2_weight_denom > 7) { av_log(s->avctx, AV_LOG_ERROR, "luma_log2_weight_denom %d is invalid\n", luma_log2_weight_denom); + return AVERROR_INVALIDDATA; + } s->sh.luma_log2_weight_denom = av_clip_uintp2(luma_log2_weight_denom, 3); if (s->ps.sps->chroma_format_idc != 0) { - int delta = get_se_golomb(gb); - s->sh.chroma_log2_weight_denom = av_clip_uintp2(s->sh.luma_log2_weight_denom + delta, 3); + int64_t chroma_log2_weight_denom = luma_log2_weight_denom + (int64_t)get_se_golomb(gb); + if (chroma_log2_weight_denom < 0 || chroma_log2_weight_denom > 7) { + av_log(s->avctx, AV_LOG_ERROR, "chroma_log2_weight_denom %"PRId64" is invalid\n", chroma_log2_weight_denom); + return AVERROR_INVALIDDATA; + } + s->sh.chroma_log2_weight_denom = chroma_log2_weight_denom; } for (i = 0; i < s->sh.nb_refs[L0]; i++) { From 647fa49495c39a48b7ccb92acd8fb975b1575456 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 17 Feb 2018 21:47:09 +0100 Subject: [PATCH 1891/2557] avcodec/dirac_dwt_template: Fix Integer overflow in horizontal_compose_dd137i() Fixes: 5894/clusterfuzz-testcase-minimized-5315325420634112 Fixes: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/dirac_dwt_template.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/dirac_dwt_template.c b/libavcodec/dirac_dwt_template.c index e68cc4d5300a7..8c25c1f8228cd 100644 --- a/libavcodec/dirac_dwt_template.c +++ b/libavcodec/dirac_dwt_template.c @@ -95,8 +95,8 @@ static void RENAME(horizontal_compose_dd97i)(uint8_t *_b, uint8_t *_tmp, int w) tmp[w2+1] = tmp[w2] = tmp[w2-1]; for (x = 0; x < w2; x++) { - b[2*x ] = (tmp[x] + 1)>>1; - b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1; + b[2*x ] = ((int)(tmp[x] + 1U))>>1; + b[2*x+1] = ((int)(COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1U))>>1; } } @@ -118,8 +118,8 @@ static void RENAME(horizontal_compose_dd137i)(uint8_t *_b, uint8_t *_tmp, int w) tmp[w2+1] = tmp[w2] = tmp[w2-1]; for (x = 0; x < w2; x++) { - b[2*x ] = (tmp[x] + 1)>>1; - b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1; + b[2*x ] = ((int)(tmp[x] + 1U))>>1; + b[2*x+1] = ((int)(COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1U))>>1; } } From 6325bd3717348615adafb52e4da2fd01a3007d0a Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Wed, 14 Feb 2018 17:01:08 +0100 Subject: [PATCH 1892/2557] swresample/rematrix: fix update of channel matrix if input or output layout is undefined Prefer direct in/out channel count values over channel layout, when available. Fixes a pan filter bug (ticket #6790). Signed-off-by: Tobias Rapp --- libswresample/rematrix.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c index 9fcfff1318c56..82277300564d6 100644 --- a/libswresample/rematrix.c +++ b/libswresample/rematrix.c @@ -69,8 +69,10 @@ int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride) return AVERROR(EINVAL); memset(s->matrix, 0, sizeof(s->matrix)); memset(s->matrix_flt, 0, sizeof(s->matrix_flt)); - nb_in = av_get_channel_layout_nb_channels(s->user_in_ch_layout); - nb_out = av_get_channel_layout_nb_channels(s->user_out_ch_layout); + nb_in = (s->user_in_ch_count > 0) ? s->user_in_ch_count : + av_get_channel_layout_nb_channels(s->user_in_ch_layout); + nb_out = (s->user_out_ch_count > 0) ? s->user_out_ch_count : + av_get_channel_layout_nb_channels(s->user_out_ch_layout); for (out = 0; out < nb_out; out++) { for (in = 0; in < nb_in; in++) s->matrix_flt[out][in] = s->matrix[out][in] = matrix[in]; From 56f77b0f678de74404ae3a64f6ba664ea4449348 Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Thu, 15 Feb 2018 08:21:24 +0100 Subject: [PATCH 1893/2557] fate: add tests for pan audio filter Signed-off-by: Tobias Rapp --- tests/fate/filter-audio.mak | 30 ++++++++++++++++++++++++++++++ tests/ref/fate/filter-pan-mono1 | 26 ++++++++++++++++++++++++++ tests/ref/fate/filter-pan-mono2 | 26 ++++++++++++++++++++++++++ tests/ref/fate/filter-pan-stereo1 | 26 ++++++++++++++++++++++++++ tests/ref/fate/filter-pan-stereo2 | 26 ++++++++++++++++++++++++++ tests/ref/fate/filter-pan-stereo3 | 26 ++++++++++++++++++++++++++ tests/ref/fate/filter-pan-stereo4 | 26 ++++++++++++++++++++++++++ 7 files changed, 186 insertions(+) create mode 100644 tests/ref/fate/filter-pan-mono1 create mode 100644 tests/ref/fate/filter-pan-mono2 create mode 100644 tests/ref/fate/filter-pan-stereo1 create mode 100644 tests/ref/fate/filter-pan-stereo2 create mode 100644 tests/ref/fate/filter-pan-stereo3 create mode 100644 tests/ref/fate/filter-pan-stereo4 diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak index bd8b3d3c351c2..2a3ba1992fc79 100644 --- a/tests/fate/filter-audio.mak +++ b/tests/fate/filter-audio.mak @@ -128,6 +128,36 @@ fate-filter-firequalizer: CMP = oneoff fate-filter-firequalizer: CMP_UNIT = s16 fate-filter-firequalizer: SIZE_TOLERANCE = 1058400 - 1097208 +FATE_AFILTER-$(call FILTERDEMDECENCMUX, PAN, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-pan-mono1 +fate-filter-pan-mono1: tests/data/asynth-44100-2.wav +fate-filter-pan-mono1: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav +fate-filter-pan-mono1: CMD = framecrc -ss 3.14 -i $(SRC) -frames:a 20 -filter:a "pan=mono|FC=FL" + +FATE_AFILTER-$(call FILTERDEMDECENCMUX, PAN, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-pan-mono2 +fate-filter-pan-mono2: tests/data/asynth-44100-2.wav +fate-filter-pan-mono2: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav +fate-filter-pan-mono2: CMD = framecrc -ss 3.14 -i $(SRC) -frames:a 20 -filter:a "pan=1C|c0=c0+c1" + +FATE_AFILTER-$(call FILTERDEMDECENCMUX, PAN, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-pan-stereo1 +fate-filter-pan-stereo1: tests/data/asynth-44100-3.wav +fate-filter-pan-stereo1: SRC = $(TARGET_PATH)/tests/data/asynth-44100-3.wav +fate-filter-pan-stereo1: CMD = framecrc -ss 3.14 -i $(SRC) -frames:a 20 -filter:a "pan=2c|FL=FR|FR=FL" + +FATE_AFILTER-$(call FILTERDEMDECENCMUX, PAN, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-pan-stereo2 +fate-filter-pan-stereo2: tests/data/asynth-44100-3.wav +fate-filter-pan-stereo2: SRC = $(TARGET_PATH)/tests/data/asynth-44100-3.wav +fate-filter-pan-stereo2: CMD = framecrc -ss 3.14 -i $(SRC) -frames:a 20 -filter:a "pan=stereo|c0=c0-c2|c1=c1-c2" + +FATE_AFILTER-$(call FILTERDEMDECENCMUX, PAN, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-pan-stereo3 +fate-filter-pan-stereo3: tests/data/asynth-44100-2.wav +fate-filter-pan-stereo3: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav +fate-filter-pan-stereo3: CMD = framecrc -ss 3.14 -i $(SRC) -frames:a 20 -filter:a "pan=FL+FR|FL<3*c0+2*c1|FR<2*c0+3*c1" + +FATE_AFILTER-$(call FILTERDEMDECENCMUX, PAN, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-pan-stereo4 +fate-filter-pan-stereo4: tests/data/asynth-44100-2.wav +fate-filter-pan-stereo4: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav +fate-filter-pan-stereo4: CMD = framecrc -ss 3.14 -guess_layout_max 0 -i $(SRC) -frames:a 20 -filter:a "pan=4C|c0=c0-0.5*c1|c1=c1+0.5*c0|c2=0*c0|c3=0*c0" + FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, SILENCEREMOVE, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-silenceremove fate-filter-silenceremove: SRC = $(TARGET_SAMPLES)/audio-reference/divertimenti_2ch_96kHz_s24.wav fate-filter-silenceremove: CMD = framecrc -i $(SRC) -frames:a 30 -af silenceremove=0:0:0:-1:0:-90dB diff --git a/tests/ref/fate/filter-pan-mono1 b/tests/ref/fate/filter-pan-mono1 new file mode 100644 index 0000000000000..3bd7c25bc1f3c --- /dev/null +++ b/tests/ref/fate/filter-pan-mono1 @@ -0,0 +1,26 @@ +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 44100 +#channel_layout 0: 4 +#channel_layout_name 0: mono +0, 0, 0, 1024, 2048, 0x750f0a66 +0, 1024, 1024, 1024, 2048, 0x155cf063 +0, 2048, 2048, 1024, 2048, 0x1e43fc32 +0, 3072, 3072, 1024, 2048, 0x282ffc28 +0, 4096, 4096, 1024, 2048, 0x6d7bf000 +0, 5120, 5120, 1024, 2048, 0xc0b2f411 +0, 6144, 6144, 1024, 2048, 0xd711fb03 +0, 7168, 7168, 1024, 2048, 0x3164189c +0, 8192, 8192, 1024, 2048, 0x8c69e827 +0, 9216, 9216, 1024, 2048, 0x562d0518 +0, 10240, 10240, 1024, 2048, 0x380aee27 +0, 11264, 11264, 1024, 2048, 0x990a03e4 +0, 12288, 12288, 1024, 2048, 0x68d7ef60 +0, 13312, 13312, 1024, 2048, 0xd13fef9e +0, 14336, 14336, 1024, 2048, 0x009306e4 +0, 15360, 15360, 1024, 2048, 0x51850390 +0, 16384, 16384, 1024, 2048, 0xcd3ceeae +0, 17408, 17408, 1024, 2048, 0x189ff277 +0, 18432, 18432, 1024, 2048, 0x4b98f68c +0, 19456, 19456, 1024, 2048, 0x34eaf544 diff --git a/tests/ref/fate/filter-pan-mono2 b/tests/ref/fate/filter-pan-mono2 new file mode 100644 index 0000000000000..0867ca9a1342f --- /dev/null +++ b/tests/ref/fate/filter-pan-mono2 @@ -0,0 +1,26 @@ +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 44100 +#channel_layout 0: 0 +#channel_layout_name 0: 1 channels +0, 0, 0, 1024, 2048, 0x6130fb80 +0, 1024, 1024, 1024, 2048, 0xd5ef0930 +0, 2048, 2048, 1024, 2048, 0x40bce3f6 +0, 3072, 3072, 1024, 2048, 0x72e5d193 +0, 4096, 4096, 1024, 2048, 0xb005073f +0, 5120, 5120, 1024, 2048, 0xa323fdbe +0, 6144, 6144, 1024, 2048, 0xe5cbfe1e +0, 7168, 7168, 1024, 2048, 0x4b42fe79 +0, 8192, 8192, 1024, 2048, 0x384eedea +0, 9216, 9216, 1024, 2048, 0xe5cdf825 +0, 10240, 10240, 1024, 2048, 0xc2970ec0 +0, 11264, 11264, 1024, 2048, 0xa85fe5e0 +0, 12288, 12288, 1024, 2048, 0xfd51f2de +0, 13312, 13312, 1024, 2048, 0xa1aafe30 +0, 14336, 14336, 1024, 2048, 0x8770fea2 +0, 15360, 15360, 1024, 2048, 0x67c50d76 +0, 16384, 16384, 1024, 2048, 0x7772fbc8 +0, 17408, 17408, 1024, 2048, 0xc48eff54 +0, 18432, 18432, 1024, 2048, 0x2e14f359 +0, 19456, 19456, 1024, 2048, 0x2df70a60 diff --git a/tests/ref/fate/filter-pan-stereo1 b/tests/ref/fate/filter-pan-stereo1 new file mode 100644 index 0000000000000..3125d4e570a57 --- /dev/null +++ b/tests/ref/fate/filter-pan-stereo1 @@ -0,0 +1,26 @@ +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 44100 +#channel_layout 0: 3 +#channel_layout_name 0: stereo +0, 0, 0, 682, 2728, 0xaf365458 +0, 682, 682, 682, 2728, 0xcd684898 +0, 1364, 1364, 682, 2728, 0x5d514ae5 +0, 2046, 2046, 682, 2728, 0x48cb4605 +0, 2728, 2728, 682, 2728, 0x76ac43ee +0, 3410, 3410, 682, 2728, 0x088355fa +0, 4092, 4092, 682, 2728, 0xf66f4efa +0, 4774, 4774, 682, 2728, 0x7efc3b1a +0, 5456, 5456, 682, 2728, 0x1c1745f3 +0, 6138, 6138, 682, 2728, 0x824d50fe +0, 6820, 6820, 682, 2728, 0xb26c5b94 +0, 7502, 7502, 682, 2728, 0x02d5636d +0, 8184, 8184, 682, 2728, 0x65e647de +0, 8866, 8866, 682, 2728, 0x93374812 +0, 9548, 9548, 682, 2728, 0xa0d55153 +0, 10230, 10230, 682, 2728, 0x56cf392c +0, 10912, 10912, 682, 2728, 0x554051c3 +0, 11594, 11594, 682, 2728, 0xbc3655ce +0, 12276, 12276, 682, 2728, 0xb432529f +0, 12958, 12958, 682, 2728, 0x64df52a7 diff --git a/tests/ref/fate/filter-pan-stereo2 b/tests/ref/fate/filter-pan-stereo2 new file mode 100644 index 0000000000000..7f96799e2c1a5 --- /dev/null +++ b/tests/ref/fate/filter-pan-stereo2 @@ -0,0 +1,26 @@ +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 44100 +#channel_layout 0: 3 +#channel_layout_name 0: stereo +0, 0, 0, 682, 2728, 0x35c15e81 +0, 682, 682, 682, 2728, 0x770f2e2d +0, 1364, 1364, 682, 2728, 0x6f8d6d9f +0, 2046, 2046, 682, 2728, 0x5b9e46f3 +0, 2728, 2728, 682, 2728, 0xda7e5fdc +0, 3410, 3410, 682, 2728, 0x55e446f8 +0, 4092, 4092, 682, 2728, 0x4fcf4f8e +0, 4774, 4774, 682, 2728, 0x86e757b2 +0, 5456, 5456, 682, 2728, 0x8d4256e9 +0, 6138, 6138, 682, 2728, 0xa28d4e58 +0, 6820, 6820, 682, 2728, 0xacaa5738 +0, 7502, 7502, 682, 2728, 0xd1fe580f +0, 8184, 8184, 682, 2728, 0x09a05c0a +0, 8866, 8866, 682, 2728, 0xcaf2555d +0, 9548, 9548, 682, 2728, 0xcee159fc +0, 10230, 10230, 682, 2728, 0xaa3444a5 +0, 10912, 10912, 682, 2728, 0x23b76512 +0, 11594, 11594, 682, 2728, 0xef2243dd +0, 12276, 12276, 682, 2728, 0x36486118 +0, 12958, 12958, 682, 2728, 0xfd59626c diff --git a/tests/ref/fate/filter-pan-stereo3 b/tests/ref/fate/filter-pan-stereo3 new file mode 100644 index 0000000000000..effe11c785d49 --- /dev/null +++ b/tests/ref/fate/filter-pan-stereo3 @@ -0,0 +1,26 @@ +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 44100 +#channel_layout 0: 3 +#channel_layout_name 0: stereo +0, 0, 0, 1024, 4096, 0xa0d1fbb3 +0, 1024, 1024, 1024, 4096, 0x598a056c +0, 2048, 2048, 1024, 4096, 0x741ded28 +0, 3072, 3072, 1024, 4096, 0xc651b0ec +0, 4096, 4096, 1024, 4096, 0x1082057c +0, 5120, 5120, 1024, 4096, 0x70f7f00d +0, 6144, 6144, 1024, 4096, 0xaed7fc53 +0, 7168, 7168, 1024, 4096, 0x4250faae +0, 8192, 8192, 1024, 4096, 0xf7fcf61a +0, 9216, 9216, 1024, 4096, 0xb1350562 +0, 10240, 10240, 1024, 4096, 0x16adea0b +0, 11264, 11264, 1024, 4096, 0x706fd834 +0, 12288, 12288, 1024, 4096, 0x5431dd24 +0, 13312, 13312, 1024, 4096, 0xfaedfb73 +0, 14336, 14336, 1024, 4096, 0xee3d07e2 +0, 15360, 15360, 1024, 4096, 0x2561eeb8 +0, 16384, 16384, 1024, 4096, 0x8f76fc05 +0, 17408, 17408, 1024, 4096, 0xef05f0a1 +0, 18432, 18432, 1024, 4096, 0x4e92f19a +0, 19456, 19456, 1024, 4096, 0x81b6e0bc diff --git a/tests/ref/fate/filter-pan-stereo4 b/tests/ref/fate/filter-pan-stereo4 new file mode 100644 index 0000000000000..87c70a7f1fccf --- /dev/null +++ b/tests/ref/fate/filter-pan-stereo4 @@ -0,0 +1,26 @@ +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 44100 +#channel_layout 0: 0 +#channel_layout_name 0: 4 channels +0, 0, 0, 1024, 8192, 0xdaadfc44 +0, 1024, 1024, 1024, 8192, 0xe6d9ec37 +0, 2048, 2048, 1024, 8192, 0x5edfea64 +0, 3072, 3072, 1024, 8192, 0x7f7be38c +0, 4096, 4096, 1024, 8192, 0x3f60f5c9 +0, 5120, 5120, 1024, 8192, 0xcee4fe06 +0, 6144, 6144, 1024, 8192, 0xdb98fa3e +0, 7168, 7168, 1024, 8192, 0x4cb30687 +0, 8192, 8192, 1024, 8192, 0x00f6ecab +0, 9216, 9216, 1024, 8192, 0xa7b0e0db +0, 10240, 10240, 1024, 8192, 0xc2dcf89c +0, 11264, 11264, 1024, 8192, 0x30d6f2fe +0, 12288, 12288, 1024, 8192, 0xf83ae182 +0, 13312, 13312, 1024, 8192, 0xeecd05d1 +0, 14336, 14336, 1024, 8192, 0xfd3b0559 +0, 15360, 15360, 1024, 8192, 0xcd69e3e6 +0, 16384, 16384, 1024, 8192, 0xdf80fc29 +0, 17408, 17408, 1024, 8192, 0x7e8bf52b +0, 18432, 18432, 1024, 8192, 0xee07e5f7 +0, 19456, 19456, 1024, 8192, 0xc874f294 From 97eee953e639bd4d17a9f9398293775277d00505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 17 Feb 2018 00:08:45 +0200 Subject: [PATCH 1894/2557] Revert "configure: Stop using dlltool to create an import library" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 67c72f08a4707c18a67a4734660e3a23cc9488b6. While the linker produced import libraries might work with MSVC in simple test cases, they don't if e.g. linking to multiple GNU ld produced import libraries at the same time. (They end up importing functions from the wrong libraries.) The ones produced by dlltool work fine though. This issue was pointed out by Hendrik Leppkes. Signed-off-by: Martin Storsjö --- configure | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/configure b/configure index ed930e6cd461c..06fb839a181bc 100755 --- a/configure +++ b/configure @@ -3891,6 +3891,10 @@ case $target_os in ;; mingw32*|mingw64*) target_os=mingw32 + LIBTARGET=i386 + if enabled x86_64; then + LIBTARGET="i386:x86-64" + fi if enabled shared; then # Cannot build both shared and static libs when using dllimport. disable static @@ -3902,7 +3906,7 @@ case $target_os in SLIBSUF=".dll" SLIBNAME_WITH_VERSION='$(SLIBPREF)$(NAME)-$(LIBVERSION)$(SLIBSUF)' SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(NAME)-$(LIBMAJOR)$(SLIBSUF)' - SLIB_EXTRA_CMD='cp $(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a) $(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib)' + SLIB_EXTRA_CMD=-'$(DLLTOOL) -m $(LIBTARGET) -d $$(@:$(SLIBSUF)=.def) -l $(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib) -D $(SLIBNAME_WITH_MAJOR)' SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)' SLIB_INSTALL_LINKS= SLIB_INSTALL_EXTRA_SHLIB='$(SLIBNAME:$(SLIBSUF)=.lib)' @@ -3910,6 +3914,7 @@ case $target_os in SLIB_CREATE_DEF_CMD='EXTERN_PREFIX="$(EXTERN_PREFIX)" AR="$(AR_CMD)" NM="$(NM_CMD)" $(SRC_PATH)/compat/windows/makedef $(SUBDIR)lib$(NAME).ver $(OBJS) > $$(@:$(SLIBSUF)=.def)' SHFLAGS='-shared -Wl,--out-implib,$(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a) -Wl,--enable-auto-image-base $$(@:$(SLIBSUF)=.def)' enabled x86_64 && objformat="win64" || objformat="win32" + dlltool="${cross_prefix}dlltool" ranlib=: enable dos_paths ;; @@ -5248,6 +5253,7 @@ X86ASM_O=$X86ASM_O LD_O=$LD_O LD_LIB=$LD_LIB LD_PATH=$LD_PATH +DLLTOOL=$dlltool LDFLAGS=$LDFLAGS LDEXEFLAGS=$LDEXEFLAGS LDSOFLAGS=$LDSOFLAGS @@ -5294,6 +5300,7 @@ LIB_INSTALL_EXTRA_CMD=$LIB_INSTALL_EXTRA_CMD EXTRALIBS=$extralibs COMPAT_OBJS=$compat_objs INSTALL=install +LIBTARGET=${LIBTARGET} SLIBNAME=${SLIBNAME} SLIBNAME_WITH_VERSION=${SLIBNAME_WITH_VERSION} SLIBNAME_WITH_MAJOR=${SLIBNAME_WITH_MAJOR} From cc1c94dacd0642ac1a6cad45deb65071f127d91a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 17 Feb 2018 00:17:21 +0200 Subject: [PATCH 1895/2557] configure: Pass the right machine types to dlltool for arm and arm64 mingw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are supported by llvm-dlltool. Signed-off-by: Martin Storsjö --- configure | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure b/configure index 06fb839a181bc..1c35f9dc641e5 100755 --- a/configure +++ b/configure @@ -3894,6 +3894,10 @@ case $target_os in LIBTARGET=i386 if enabled x86_64; then LIBTARGET="i386:x86-64" + elif enabled arm; then + LIBTARGET="arm" + elif enabled aarch64; then + LIBTARGET="arm64" fi if enabled shared; then # Cannot build both shared and static libs when using dllimport. From f611fef37cca44b89d0d7e6dfd1ac257736b5f7a Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Thu, 15 Feb 2018 19:52:14 -0800 Subject: [PATCH 1896/2557] avcodec/mediacodecdec: refactor to take advantage of new decoding api This refactor splits up the main mediacodec decode loop into two send/receive helpers, which are then used to rewrite the receive_frame callback and take full advantage of the new decoding api. Since we can now request packets on demand with ff_decode_get_packet(), the fifo buffer is no longer necessary and has been removed. This change was motivated by behavior observed on certain Android TV devices, featuring hardware mpeg2/h264 decoders which also deinterlace content (to produce multiple frames per field). Previously, this code caused buffering issues because queueInputBuffer() was always invoked before each dequeueOutputBuffer(), even though twice as many output buffers were being generated. With this patch, the decoder will always attempt to drain new frames first before sending more data into the underlying codec. Signed-off-by: Matthieu Bouron --- libavcodec/mediacodecdec.c | 107 +++++++++++------------------- libavcodec/mediacodecdec_common.c | 50 +++++++++----- libavcodec/mediacodecdec_common.h | 14 ++-- 3 files changed, 80 insertions(+), 91 deletions(-) diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index cb1151a19527b..363e12427e54a 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -25,7 +25,6 @@ #include "libavutil/avassert.h" #include "libavutil/common.h" -#include "libavutil/fifo.h" #include "libavutil/opt.h" #include "libavutil/intreadwrite.h" #include "libavutil/pixfmt.h" @@ -43,8 +42,6 @@ typedef struct MediaCodecH264DecContext { MediaCodecDecContext *ctx; - AVFifoBuffer *fifo; - AVPacket buffered_pkt; } MediaCodecH264DecContext; @@ -56,8 +53,6 @@ static av_cold int mediacodec_decode_close(AVCodecContext *avctx) ff_mediacodec_dec_close(avctx, s->ctx); s->ctx = NULL; - av_fifo_free(s->fifo); - av_packet_unref(&s->buffered_pkt); return 0; @@ -400,12 +395,6 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_INFO, "MediaCodec started successfully, ret = %d\n", ret); - s->fifo = av_fifo_alloc(sizeof(AVPacket)); - if (!s->fifo) { - ret = AVERROR(ENOMEM); - goto done; - } - done: if (format) { ff_AMediaFormat_delete(format); @@ -418,13 +407,33 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx) return ret; } +static int mediacodec_send_receive(AVCodecContext *avctx, + MediaCodecH264DecContext *s, + AVFrame *frame, bool wait) +{ + int ret; + + /* send any pending data from buffered packet */ + while (s->buffered_pkt.size) { + ret = ff_mediacodec_dec_send(avctx, s->ctx, &s->buffered_pkt); + if (ret == AVERROR(EAGAIN)) + break; + else if (ret < 0) + return ret; + s->buffered_pkt.size -= ret; + s->buffered_pkt.data += ret; + if (s->buffered_pkt.size <= 0) + av_packet_unref(&s->buffered_pkt); + } + + /* check for new frame */ + return ff_mediacodec_dec_receive(avctx, s->ctx, frame, wait); +} + static int mediacodec_receive_frame(AVCodecContext *avctx, AVFrame *frame) { MediaCodecH264DecContext *s = avctx->priv_data; int ret; - int got_frame = 0; - int is_eof = 0; - AVPacket pkt = { 0 }; /* * MediaCodec.flush() discards both input and output buffers, thus we @@ -452,74 +461,34 @@ static int mediacodec_receive_frame(AVCodecContext *avctx, AVFrame *frame) } } - ret = ff_decode_get_packet(avctx, &pkt); - if (ret == AVERROR_EOF) - is_eof = 1; - else if (ret == AVERROR(EAGAIN)) - ; /* no input packet, but fallthrough to check for pending frames */ - else if (ret < 0) + /* flush buffered packet and check for new frame */ + ret = mediacodec_send_receive(avctx, s, frame, false); + if (ret != AVERROR(EAGAIN)) return ret; - /* buffer the input packet */ - if (pkt.size) { - if (av_fifo_space(s->fifo) < sizeof(pkt)) { - ret = av_fifo_realloc2(s->fifo, - av_fifo_size(s->fifo) + sizeof(pkt)); - if (ret < 0) { - av_packet_unref(&pkt); - return ret; - } - } - av_fifo_generic_write(s->fifo, &pkt, sizeof(pkt), NULL); - } - - /* process buffered data */ - while (!got_frame) { - /* prepare the input data */ - if (s->buffered_pkt.size <= 0) { - av_packet_unref(&s->buffered_pkt); - - /* no more data */ - if (av_fifo_size(s->fifo) < sizeof(AVPacket)) { - AVPacket null_pkt = { 0 }; - if (is_eof) { - ret = ff_mediacodec_dec_decode(avctx, s->ctx, frame, - &got_frame, &null_pkt); - if (ret < 0) - return ret; - else if (got_frame) - return 0; - else - return AVERROR_EOF; - } - return AVERROR(EAGAIN); - } - - av_fifo_generic_read(s->fifo, &s->buffered_pkt, sizeof(s->buffered_pkt), NULL); - } + /* skip fetching new packet if we still have one buffered */ + if (s->buffered_pkt.size > 0) + return AVERROR(EAGAIN); - ret = ff_mediacodec_dec_decode(avctx, s->ctx, frame, &got_frame, &s->buffered_pkt); + /* fetch new packet or eof */ + ret = ff_decode_get_packet(avctx, &s->buffered_pkt); + if (ret == AVERROR_EOF) { + AVPacket null_pkt = { 0 }; + ret = ff_mediacodec_dec_send(avctx, s->ctx, &null_pkt); if (ret < 0) return ret; - - s->buffered_pkt.size -= ret; - s->buffered_pkt.data += ret; } + else if (ret < 0) + return ret; - return 0; + /* crank decoder with new packet */ + return mediacodec_send_receive(avctx, s, frame, true); } static void mediacodec_decode_flush(AVCodecContext *avctx) { MediaCodecH264DecContext *s = avctx->priv_data; - while (av_fifo_size(s->fifo)) { - AVPacket pkt; - av_fifo_generic_read(s->fifo, &pkt, sizeof(pkt), NULL); - av_packet_unref(&pkt); - } - av_fifo_reset(s->fifo); - av_packet_unref(&s->buffered_pkt); ff_mediacodec_dec_flush(avctx, s->ctx); diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index a9147f3a086cb..b44abaef7fe67 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -555,23 +555,17 @@ int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s, return ret; } -int ff_mediacodec_dec_decode(AVCodecContext *avctx, MediaCodecDecContext *s, - AVFrame *frame, int *got_frame, - AVPacket *pkt) +int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s, + AVPacket *pkt) { - int ret; int offset = 0; int need_draining = 0; uint8_t *data; ssize_t index; size_t size; FFAMediaCodec *codec = s->codec; - FFAMediaCodecBufferInfo info = { 0 }; - int status; - int64_t input_dequeue_timeout_us = INPUT_DEQUEUE_TIMEOUT_US; - int64_t output_dequeue_timeout_us = OUTPUT_DEQUEUE_TIMEOUT_US; if (s->flushing) { av_log(avctx, AV_LOG_ERROR, "Decoder is flushing and cannot accept new buffer " @@ -584,13 +578,14 @@ int ff_mediacodec_dec_decode(AVCodecContext *avctx, MediaCodecDecContext *s, } if (s->draining && s->eos) { - return 0; + return AVERROR_EOF; } while (offset < pkt->size || (need_draining && !s->draining)) { index = ff_AMediaCodec_dequeueInputBuffer(codec, input_dequeue_timeout_us); if (ff_AMediaCodec_infoTryAgainLater(codec, index)) { + av_log(avctx, AV_LOG_TRACE, "Failed to dequeue input buffer, try again later..\n"); break; } @@ -621,13 +616,15 @@ int ff_mediacodec_dec_decode(AVCodecContext *avctx, MediaCodecDecContext *s, return AVERROR_EXTERNAL; } + av_log(avctx, AV_LOG_TRACE, "Queued input buffer %zd" + " size=%zd ts=%" PRIi64 "\n", index, size, pts); + s->draining = 1; break; } else { int64_t pts = pkt->pts; size = FFMIN(pkt->size - offset, size); - memcpy(data, pkt->data + offset, size); offset += size; @@ -643,11 +640,32 @@ int ff_mediacodec_dec_decode(AVCodecContext *avctx, MediaCodecDecContext *s, } } - if (need_draining || s->draining) { + if (offset == 0) + return AVERROR(EAGAIN); + return offset; +} + +int ff_mediacodec_dec_receive(AVCodecContext *avctx, MediaCodecDecContext *s, + AVFrame *frame, bool wait) +{ + int ret; + uint8_t *data; + ssize_t index; + size_t size; + FFAMediaCodec *codec = s->codec; + FFAMediaCodecBufferInfo info = { 0 }; + int status; + int64_t output_dequeue_timeout_us = OUTPUT_DEQUEUE_TIMEOUT_US; + + if (s->draining && s->eos) { + return AVERROR_EOF; + } + + if (s->draining) { /* If the codec is flushing or need to be flushed, block for a fair * amount of time to ensure we got a frame */ output_dequeue_timeout_us = OUTPUT_DEQUEUE_BLOCK_TIMEOUT_US; - } else if (s->output_buffer_count == 0) { + } else if (s->output_buffer_count == 0 || !wait) { /* If the codec hasn't produced any frames, do not block so we * can push data to it as fast as possible, and get the first * frame */ @@ -656,9 +674,7 @@ int ff_mediacodec_dec_decode(AVCodecContext *avctx, MediaCodecDecContext *s, index = ff_AMediaCodec_dequeueOutputBuffer(codec, &info, output_dequeue_timeout_us); if (index >= 0) { - int ret; - - av_log(avctx, AV_LOG_DEBUG, "Got output buffer %zd" + av_log(avctx, AV_LOG_TRACE, "Got output buffer %zd" " offset=%" PRIi32 " size=%" PRIi32 " ts=%" PRIi64 " flags=%" PRIu32 "\n", index, info.offset, info.size, info.presentationTimeUs, info.flags); @@ -686,8 +702,8 @@ int ff_mediacodec_dec_decode(AVCodecContext *avctx, MediaCodecDecContext *s, } } - *got_frame = 1; s->output_buffer_count++; + return 0; } else { status = ff_AMediaCodec_releaseOutputBuffer(codec, index, 0); if (status < 0) { @@ -737,7 +753,7 @@ int ff_mediacodec_dec_decode(AVCodecContext *avctx, MediaCodecDecContext *s, return AVERROR_EXTERNAL; } - return offset; + return AVERROR(EAGAIN); } int ff_mediacodec_dec_flush(AVCodecContext *avctx, MediaCodecDecContext *s) diff --git a/libavcodec/mediacodecdec_common.h b/libavcodec/mediacodecdec_common.h index 10f38277b54db..32d16d3e3a72c 100644 --- a/libavcodec/mediacodecdec_common.h +++ b/libavcodec/mediacodecdec_common.h @@ -25,6 +25,7 @@ #include #include +#include #include #include "libavutil/frame.h" @@ -69,11 +70,14 @@ int ff_mediacodec_dec_init(AVCodecContext *avctx, const char *mime, FFAMediaFormat *format); -int ff_mediacodec_dec_decode(AVCodecContext *avctx, - MediaCodecDecContext *s, - AVFrame *frame, - int *got_frame, - AVPacket *pkt); +int ff_mediacodec_dec_send(AVCodecContext *avctx, + MediaCodecDecContext *s, + AVPacket *pkt); + +int ff_mediacodec_dec_receive(AVCodecContext *avctx, + MediaCodecDecContext *s, + AVFrame *frame, + bool wait); int ff_mediacodec_dec_flush(AVCodecContext *avctx, MediaCodecDecContext *s); From 6d8bef8c05ea5dcb95f5930954cd6bd28868c2c9 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Fri, 16 Feb 2018 21:24:59 +0100 Subject: [PATCH 1897/2557] build: restore using dlltool/lib.exe for creating Win32 .lib files The GCC generated import libraries don't work properly when being imported by MSVC, resulting in missing symbols at runtime. This reverts 5b5365fe9 and partially reverts changes from 98a9b1f0d --- configure | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 99c53d482ae6b..3b06b86a6eab8 100755 --- a/configure +++ b/configure @@ -4994,6 +4994,10 @@ case $target_os in ;; mingw32*|mingw64*) target_os=mingw32 + LIBTARGET=i386 + if enabled x86_64; then + LIBTARGET="i386:x86-64" + fi if enabled shared; then # Cannot build both shared and static libs when using dllimport. disable static @@ -5005,7 +5009,14 @@ case $target_os in SLIBSUF=".dll" SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)' SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)' - SLIB_EXTRA_CMD='cp $(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a) $(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib)' + if check_cmd lib.exe -list; then + SLIB_EXTRA_CMD=-'lib.exe -nologo -machine:$(LIBTARGET) -def:$$(@:$(SLIBSUF)=.def) -out:$(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib)' + if enabled x86_64; then + LIBTARGET=x64 + fi + else + SLIB_EXTRA_CMD=-'$(DLLTOOL) -m $(LIBTARGET) -d $$(@:$(SLIBSUF)=.def) -l $(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib) -D $(SLIBNAME_WITH_MAJOR)' + fi SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)' SLIB_INSTALL_LINKS= SLIB_INSTALL_EXTRA_SHLIB='$(SLIBNAME:$(SLIBSUF)=.lib)' @@ -5013,6 +5024,7 @@ case $target_os in SLIB_CREATE_DEF_CMD='EXTERN_PREFIX="$(EXTERN_PREFIX)" AR="$(AR_CMD)" NM="$(NM_CMD)" $(SRC_PATH)/compat/windows/makedef $(SUBDIR)lib$(NAME).ver $(OBJS) > $$(@:$(SLIBSUF)=.def)' SHFLAGS='-shared -Wl,--out-implib,$(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a) -Wl,--disable-auto-image-base $$(@:$(SLIBSUF)=.def)' enabled x86_64 && objformat="win64" || objformat="win32" + dlltool="${cross_prefix}dlltool" ranlib=: enable dos_paths check_ldflags -Wl,--nxcompat,--dynamicbase @@ -6886,6 +6898,7 @@ LD_O=$LD_O X86ASM_O=$X86ASM_O LD_LIB=$LD_LIB LD_PATH=$LD_PATH +DLLTOOL=$dlltool WINDRES=$windres DEPWINDRES=$dep_cc DOXYGEN=$doxygen @@ -6939,6 +6952,7 @@ LIB_INSTALL_EXTRA_CMD=$LIB_INSTALL_EXTRA_CMD EXTRALIBS=$extralibs COMPAT_OBJS=$compat_objs INSTALL=$install +LIBTARGET=${LIBTARGET} SLIBNAME=${SLIBNAME} SLIBNAME_WITH_VERSION=${SLIBNAME_WITH_VERSION} SLIBNAME_WITH_MAJOR=${SLIBNAME_WITH_MAJOR} From b50f68bb1ecc6dcfe7aaed04c12dd94bdc222428 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Mon, 15 Jan 2018 20:20:33 +0530 Subject: [PATCH 1898/2557] docs/codecs: remove dead codec debug options FF_API_DEBUG_MV has been disabled. Related options removed from docs. Mention of non-existent debug option value 'pts' also removed. --- doc/codecs.texi | 8 -------- 1 file changed, 8 deletions(-) diff --git a/doc/codecs.texi b/doc/codecs.texi index 7e20374334093..c9b9a1136dceb 100644 --- a/doc/codecs.texi +++ b/doc/codecs.texi @@ -467,8 +467,6 @@ rate control macroblock (MB) type @item qp per-block quantization parameter (QP) -@item mv -motion vector @item dct_coeff @item green_metadata @@ -478,18 +476,12 @@ display complexity metadata for the upcoming frame, GoP or for a given duration. @item startcode -@item pts - @item er error recognition @item mmco memory management control operations (H.264) @item bugs -@item vis_qp -visualize quantization parameter (QP), lower QP are tinted greener -@item vis_mb_type -visualize block types @item buffers picture buffer allocations @item thread_ops From acdea9e7c56b74b05c56b4733acc855b959ba073 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 13 Jan 2018 16:04:21 -0300 Subject: [PATCH 1899/2557] avformat/matroskadec: ignore CodecPrivate if the stream is VP9 Defined in a recent revision of https://www.webmproject.org/docs/container/ This prevents storing the contents of CodecPrivate into extradata for a codec that doesn't need nor expect any. It will among other things prevent matroska specific binary data from being dumped onto other formats during remuxing. Signed-off-by: James Almer --- libavformat/matroskadec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index cda8df221344b..edc4f5d476480 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -2397,6 +2397,10 @@ static int matroska_parse_tracks(AVFormatContext *s) return ret; } else if (codec_id == AV_CODEC_ID_PRORES && track->codec_priv.size == 4) { fourcc = AV_RL32(track->codec_priv.data); + } else if (codec_id == AV_CODEC_ID_VP9 && track->codec_priv.size) { + /* we don't need any value stored in CodecPrivate. + make sure that it's not exported as extradata. */ + track->codec_priv.size = 0; } track->codec_priv.size -= extradata_offset; From 88eb368f4210fc2975666f9cb89504b3374094ab Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Feb 2018 10:25:54 -0300 Subject: [PATCH 1900/2557] avformat/matroskadec: free the packet on webvtt side data allocation failure Fixes potential memory leaks Signed-off-by: James Almer --- libavformat/matroskadec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index edc4f5d476480..bf0e47ce3a38e 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -3121,6 +3121,7 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, AV_PKT_DATA_WEBVTT_IDENTIFIER, id_len); if (!buf) { + av_packet_unref(pkt); av_free(pkt); return AVERROR(ENOMEM); } @@ -3132,6 +3133,7 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, AV_PKT_DATA_WEBVTT_SETTINGS, settings_len); if (!buf) { + av_packet_unref(pkt); av_free(pkt); return AVERROR(ENOMEM); } From f4f39582e786cdd6cedc3a6abf9a2057dcd8dd7a Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Feb 2018 10:26:21 -0300 Subject: [PATCH 1901/2557] avformat/matroskadec: fix return value err is already an AVERROR. Signed-off-by: James Almer --- libavformat/matroskadec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index bf0e47ce3a38e..2faaf9dfb8b1b 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -3111,7 +3111,7 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, err = av_new_packet(pkt, text_len); if (err < 0) { av_free(pkt); - return AVERROR(err); + return err; } memcpy(pkt->data, text, text_len); From 3748746a4d6988484d34516f7a3c6febf7bdf488 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 17 Feb 2018 21:27:16 +0100 Subject: [PATCH 1902/2557] avcodec/dxtory: Remove code that corrupts dimensions Fixes: Timeout Fixes: 5796/clusterfuzz-testcase-minimized-5206729085157376 Does someone have a valid sample that triggers this path ? Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/dxtory.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libavcodec/dxtory.c b/libavcodec/dxtory.c index e736cec8dbb43..285ca38efb8b4 100644 --- a/libavcodec/dxtory.c +++ b/libavcodec/dxtory.c @@ -305,11 +305,7 @@ static int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic, } if (avctx->height - line) { - av_log(avctx, AV_LOG_VERBOSE, - "Not enough slice data available, " - "cropping the frame by %d pixels\n", - avctx->height - line); - avctx->height = line; + avpriv_request_sample(avctx, "Not enough slice data available"); } return 0; From cbcbefdc3b4cbc917d2f8b2dd216fb12121a838b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 17 Feb 2018 23:54:44 +0100 Subject: [PATCH 1903/2557] avcodec/diracdec: Use int64 in global mv to prevent overflow Fixes: runtime error: signed integer overflow: 361 * -6295541 cannot be represented in type 'int' Fixes: 5911/clusterfuzz-testcase-minimized-6450382197751808 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/diracdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/diracdec.c b/libavcodec/diracdec.c index 530e1c6ffd269..e3afbf14be184 100644 --- a/libavcodec/diracdec.c +++ b/libavcodec/diracdec.c @@ -1399,8 +1399,8 @@ static void global_mv(DiracContext *s, DiracBlock *block, int x, int y, int ref) int *c = s->globalmc[ref].perspective; int m = (1<u.mv[ref][0] = (mx + (1<<(ez+ep))) >> (ez+ep); block->u.mv[ref][1] = (my + (1<<(ez+ep))) >> (ez+ep); From 793347a54579ee954b58d336b82eed4a1786de21 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 18 Feb 2018 00:11:33 +0100 Subject: [PATCH 1904/2557] avcodec/jpeg2000dwt: Fix integer overflows in sr_1d53() Fixes: 5918/clusterfuzz-testcase-minimized-5120505435652096 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/jpeg2000dwt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/jpeg2000dwt.c b/libavcodec/jpeg2000dwt.c index 55dd5e89b524a..ce1678a3d74ed 100644 --- a/libavcodec/jpeg2000dwt.c +++ b/libavcodec/jpeg2000dwt.c @@ -305,22 +305,22 @@ static void dwt_encode97_int(DWTContext *s, int *t) t[i] = (t[i] + ((1<>1)) >> I_PRESHIFT; } -static void sr_1d53(int *p, int i0, int i1) +static void sr_1d53(unsigned *p, int i0, int i1) { int i; if (i1 <= i0 + 1) { if (i0 == 1) - p[1] >>= 1; + p[1] = (int)p[1] >> 1; return; } extend53(p, i0, i1); for (i = (i0 >> 1); i < (i1 >> 1) + 1; i++) - p[2 * i] -= (p[2 * i - 1] + p[2 * i + 1] + 2) >> 2; + p[2 * i] -= (int)(p[2 * i - 1] + p[2 * i + 1] + 2) >> 2; for (i = (i0 >> 1); i < (i1 >> 1); i++) - p[2 * i + 1] += (p[2 * i] + p[2 * i + 2]) >> 1; + p[2 * i + 1] += (int)(p[2 * i] + p[2 * i + 2]) >> 1; } static void dwt_decode53(DWTContext *s, int *t) From 33fe17bdc88d51a8e0c87aa1e8011aaaf38a7a90 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 18 Feb 2018 16:55:52 +0100 Subject: [PATCH 1905/2557] avcodec/aacdec_templat: Fix integer overflow in apply_ltp() Fixes: signed integer overflow: -1625276744 + -1041893960 cannot be represented in type 'int' Fixes: 5948/clusterfuzz-testcase-minimized-5791479856365568 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/aacdec_template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c index 6c6cdd84aff54..c2d9802023aea 100644 --- a/libavcodec/aacdec_template.c +++ b/libavcodec/aacdec_template.c @@ -2561,7 +2561,7 @@ static void apply_ltp(AACContext *ac, SingleChannelElement *sce) for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++) if (ltp->used[sfb]) for (i = offsets[sfb]; i < offsets[sfb + 1]; i++) - sce->coeffs[i] += predFreq[i]; + sce->coeffs[i] += (UINTFLOAT)predFreq[i]; } } From 85c85fffff3f9c75301db3eba1bd5f2fb1e6285d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 18 Feb 2018 17:12:28 +0100 Subject: [PATCH 1906/2557] avcodec/h264_parse: Clear invalid chroma weights in ff_h264_pred_weight_table() Fixes: 6037/clusterfuzz-testcase-minimized-5030249784934400 Fixes: signed integer overflow: 256 * 16992036 cannot be represented in type 'int' Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/h264_parse.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c index 6cbef5a13dd76..87e5b3cdc5323 100644 --- a/libavcodec/h264_parse.c +++ b/libavcodec/h264_parse.c @@ -82,8 +82,11 @@ int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps, pwt->chroma_weight[i][list][j][0] = get_se_golomb(gb); pwt->chroma_weight[i][list][j][1] = get_se_golomb(gb); if ((int8_t)pwt->chroma_weight[i][list][j][0] != pwt->chroma_weight[i][list][j][0] || - (int8_t)pwt->chroma_weight[i][list][j][1] != pwt->chroma_weight[i][list][j][1]) + (int8_t)pwt->chroma_weight[i][list][j][1] != pwt->chroma_weight[i][list][j][1]) { + pwt->chroma_weight[i][list][j][0] = chroma_def; + pwt->chroma_weight[i][list][j][1] = 0; goto out_range_weight; + } if (pwt->chroma_weight[i][list][j][0] != chroma_def || pwt->chroma_weight[i][list][j][1] != 0) { pwt->use_weight_chroma = 1; From 47e65ad63b3d067445c4de41a7718b83fc07767c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 18 Feb 2018 21:51:38 +0100 Subject: [PATCH 1907/2557] avcodec/diracdec: Fix integer overflow in mv computation Fixes: signed integer overflow: -2072 + -2147483646 cannot be represented in type 'int' Fixes: 6097/clusterfuzz-testcase-minimized-5034145253163008 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/diracdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/diracdec.c b/libavcodec/diracdec.c index e3afbf14be184..753adeff61ce8 100644 --- a/libavcodec/diracdec.c +++ b/libavcodec/diracdec.c @@ -1437,8 +1437,8 @@ static void decode_block_params(DiracContext *s, DiracArith arith[8], DiracBlock global_mv(s, block, x, y, i); } else { pred_mv(block, stride, x, y, i); - block->u.mv[i][0] += dirac_get_arith_int(arith + 4 + 2 * i, CTX_MV_F1, CTX_MV_DATA); - block->u.mv[i][1] += dirac_get_arith_int(arith + 5 + 2 * i, CTX_MV_F1, CTX_MV_DATA); + block->u.mv[i][0] += (unsigned)dirac_get_arith_int(arith + 4 + 2 * i, CTX_MV_F1, CTX_MV_DATA); + block->u.mv[i][1] += (unsigned)dirac_get_arith_int(arith + 5 + 2 * i, CTX_MV_F1, CTX_MV_DATA); } } } From a877d22d9a8af3cd9a7da500fe2db99bebd38dd5 Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Mon, 19 Feb 2018 11:25:09 +0530 Subject: [PATCH 1908/2557] avformat/movenc: addition of flag to fragment at every frame Signed-off-by: Michael Niedermayer --- libavformat/movenc.c | 10 +++++++--- libavformat/movenc.h | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index f43349932b216..5b1e66c89736a 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -62,6 +62,7 @@ static const AVOption options[] = { { "moov_size", "maximum moov size so it can be placed at the begin", offsetof(MOVMuxContext, reserved_moov_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 0 }, { "empty_moov", "Make the initial moov atom empty", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_EMPTY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "frag_keyframe", "Fragment at video keyframes", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_KEYFRAME}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "frag_every_frame", "Fragment at every frame", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_EVERY_FRAME}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "separate_moof", "Write separate moof/mdat atoms for each track", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SEPARATE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_CUSTOM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "isml", "Create a live smooth streaming feed (for pushing to a publishing point)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_ISML}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, @@ -5432,7 +5433,8 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) || (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME && par->codec_type == AVMEDIA_TYPE_VIDEO && - trk->entry && pkt->flags & AV_PKT_FLAG_KEY)) { + trk->entry && pkt->flags & AV_PKT_FLAG_KEY) || + (mov->flags & FF_MOV_FLAG_FRAG_EVERY_FRAME)) { if (frag_duration >= mov->min_fragment_duration) { // Set the duration of this track to line up with the next // sample in this track. This avoids relying on AVPacket @@ -5874,7 +5876,8 @@ static int mov_init(AVFormatContext *s) if (mov->max_fragment_duration || mov->max_fragment_size || mov->flags & (FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_FRAG_KEYFRAME | - FF_MOV_FLAG_FRAG_CUSTOM)) + FF_MOV_FLAG_FRAG_CUSTOM | + FF_MOV_FLAG_FRAG_EVERY_FRAME)) mov->flags |= FF_MOV_FLAG_FRAGMENT; /* Set other implicit flags immediately */ @@ -6238,7 +6241,8 @@ static int mov_write_header(AVFormatContext *s) if (mov->flags & FF_MOV_FLAG_FRAGMENT) { /* If no fragmentation options have been set, set a default. */ if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME | - FF_MOV_FLAG_FRAG_CUSTOM)) && + FF_MOV_FLAG_FRAG_CUSTOM | + FF_MOV_FLAG_FRAG_EVERY_FRAME)) && !mov->max_fragment_duration && !mov->max_fragment_size) mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME; } else { diff --git a/libavformat/movenc.h b/libavformat/movenc.h index c4e966b7fb75f..ca2a9c97226b8 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -245,6 +245,7 @@ typedef struct MOVMuxContext { #define FF_MOV_FLAG_USE_MDTA (1 << 17) #define FF_MOV_FLAG_SKIP_TRAILER (1 << 18) #define FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS (1 << 19) +#define FF_MOV_FLAG_FRAG_EVERY_FRAME (1 << 20) int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt); From 2651352988212531038326c44754ece1728c4a3b Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 9 Nov 2017 01:03:57 +0000 Subject: [PATCH 1909/2557] cbs: Allocate the context inside the init function ... instead of making callers allocate it themselves. This is more consistent with other APIs in libav. --- libavcodec/cbs.c | 20 +++++++++++++++++--- libavcodec/cbs.h | 6 +++--- libavcodec/h264_metadata_bsf.c | 20 ++++++++++---------- libavcodec/h264_redundant_pps_bsf.c | 18 +++++++++--------- libavcodec/h265_metadata_bsf.c | 18 +++++++++--------- libavcodec/mpeg2_metadata_bsf.c | 16 ++++++++-------- libavcodec/trace_headers_bsf.c | 14 +++++++------- libavcodec/vaapi_encode_h264.c | 14 +++++++------- libavcodec/vaapi_encode_h265.c | 10 +++++----- libavcodec/vaapi_encode_mpeg2.c | 10 +++++----- 10 files changed, 80 insertions(+), 66 deletions(-) diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index 3baa31a4ddd64..fd9baa2997c9d 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -39,9 +39,10 @@ static const CodedBitstreamType *cbs_type_table[] = { #endif }; -int ff_cbs_init(CodedBitstreamContext *ctx, +int ff_cbs_init(CodedBitstreamContext **ctx_ptr, enum AVCodecID codec_id, void *log_ctx) { + CodedBitstreamContext *ctx; const CodedBitstreamType *type; int i; @@ -55,27 +56,40 @@ int ff_cbs_init(CodedBitstreamContext *ctx, if (!type) return AVERROR(EINVAL); + ctx = av_mallocz(sizeof(*ctx)); + if (!ctx) + return AVERROR(ENOMEM); + ctx->log_ctx = log_ctx; ctx->codec = type; ctx->priv_data = av_mallocz(ctx->codec->priv_data_size); - if (!ctx->priv_data) + if (!ctx->priv_data) { + av_freep(&ctx); return AVERROR(ENOMEM); + } ctx->decompose_unit_types = NULL; ctx->trace_enable = 0; ctx->trace_level = AV_LOG_TRACE; + *ctx_ptr = ctx; return 0; } -void ff_cbs_close(CodedBitstreamContext *ctx) +void ff_cbs_close(CodedBitstreamContext **ctx_ptr) { + CodedBitstreamContext *ctx = *ctx_ptr; + + if (!ctx) + return; + if (ctx->codec && ctx->codec->close) ctx->codec->close(ctx); av_freep(&ctx->priv_data); + av_freep(ctx_ptr); } static void cbs_unit_uninit(CodedBitstreamContext *ctx, diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h index 01b2239b7b1b0..34ee78be32fb6 100644 --- a/libavcodec/cbs.h +++ b/libavcodec/cbs.h @@ -169,15 +169,15 @@ typedef struct CodedBitstreamContext { /** - * Initialise a new context for the given codec. + * Create and initialise a new context for the given codec. */ -int ff_cbs_init(CodedBitstreamContext *ctx, +int ff_cbs_init(CodedBitstreamContext **ctx, enum AVCodecID codec_id, void *log_ctx); /** * Close a context and free all internal state. */ -void ff_cbs_close(CodedBitstreamContext *ctx); +void ff_cbs_close(CodedBitstreamContext **ctx); /** diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index ac0b9823b919b..2b579e9d3d9f4 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -35,7 +35,7 @@ enum { typedef struct H264MetadataContext { const AVClass *class; - CodedBitstreamContext cbc; + CodedBitstreamContext *cbc; CodedBitstreamFragment access_unit; H264RawAUD aud_nal; @@ -214,7 +214,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) if (err < 0) goto fail; - err = ff_cbs_read_packet(&ctx->cbc, au, in); + err = ff_cbs_read_packet(ctx->cbc, au, in); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); goto fail; @@ -229,7 +229,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) // If an AUD is present, it must be the first NAL unit. if (au->units[0].type == H264_NAL_AUD) { if (ctx->aud == REMOVE) - ff_cbs_delete_unit(&ctx->cbc, au, 0); + ff_cbs_delete_unit(ctx->cbc, au, 0); } else { if (ctx->aud == INSERT) { static const int primary_pic_type_table[] = { @@ -269,7 +269,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) aud->nal_unit_header.nal_unit_type = H264_NAL_AUD; aud->primary_pic_type = j; - err = ff_cbs_insert_unit_content(&ctx->cbc, au, + err = ff_cbs_insert_unit_content(ctx->cbc, au, 0, H264_NAL_AUD, aud); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n"); @@ -314,7 +314,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) sei->nal_unit_header.nal_unit_type = H264_NAL_SEI; - err = ff_cbs_insert_unit_content(&ctx->cbc, au, + err = ff_cbs_insert_unit_content(ctx->cbc, au, sei_pos, H264_NAL_SEI, sei); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to insert SEI.\n"); @@ -375,7 +375,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) ++sei->payload_count; } - err = ff_cbs_write_packet(&ctx->cbc, out, au); + err = ff_cbs_write_packet(ctx->cbc, out, au); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); goto fail; @@ -387,7 +387,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) err = 0; fail: - ff_cbs_fragment_uninit(&ctx->cbc, au); + ff_cbs_fragment_uninit(ctx->cbc, au); av_freep(&sei_udu_string); av_packet_free(&in); @@ -406,7 +406,7 @@ static int h264_metadata_init(AVBSFContext *bsf) return err; if (bsf->par_in->extradata) { - err = ff_cbs_read_extradata(&ctx->cbc, au, bsf->par_in); + err = ff_cbs_read_extradata(ctx->cbc, au, bsf->par_in); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); goto fail; @@ -420,7 +420,7 @@ static int h264_metadata_init(AVBSFContext *bsf) } } - err = ff_cbs_write_extradata(&ctx->cbc, bsf->par_out, au); + err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, au); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); goto fail; @@ -429,7 +429,7 @@ static int h264_metadata_init(AVBSFContext *bsf) err = 0; fail: - ff_cbs_fragment_uninit(&ctx->cbc, au); + ff_cbs_fragment_uninit(ctx->cbc, au); return err; } diff --git a/libavcodec/h264_redundant_pps_bsf.c b/libavcodec/h264_redundant_pps_bsf.c index abc7af788a449..24b7b67300417 100644 --- a/libavcodec/h264_redundant_pps_bsf.c +++ b/libavcodec/h264_redundant_pps_bsf.c @@ -28,8 +28,8 @@ typedef struct H264RedundantPPSContext { - CodedBitstreamContext input; - CodedBitstreamContext output; + CodedBitstreamContext *input; + CodedBitstreamContext *output; CodedBitstreamFragment access_unit; @@ -77,7 +77,7 @@ static int h264_redundant_pps_filter(AVBSFContext *bsf, AVPacket *out) if (err < 0) return err; - err = ff_cbs_read_packet(&ctx->input, au, in); + err = ff_cbs_read_packet(ctx->input, au, in); if (err < 0) return err; @@ -92,7 +92,7 @@ static int h264_redundant_pps_filter(AVBSFContext *bsf, AVPacket *out) if (!au_has_sps) { av_log(ctx, AV_LOG_VERBOSE, "Deleting redundant PPS " "at %"PRId64".\n", in->pts); - ff_cbs_delete_unit(&ctx->input, au, i); + ff_cbs_delete_unit(ctx->input, au, i); } } if (nal->type == H264_NAL_SLICE || @@ -102,11 +102,11 @@ static int h264_redundant_pps_filter(AVBSFContext *bsf, AVPacket *out) } } - err = ff_cbs_write_packet(&ctx->output, out, au); + err = ff_cbs_write_packet(ctx->output, out, au); if (err < 0) return err; - ff_cbs_fragment_uninit(&ctx->output, au); + ff_cbs_fragment_uninit(ctx->output, au); err = av_packet_copy_props(out, in); if (err < 0) @@ -134,7 +134,7 @@ static int h264_redundant_pps_init(AVBSFContext *bsf) ctx->global_pic_init_qp = 26; if (bsf->par_in->extradata) { - err = ff_cbs_read_extradata(&ctx->input, au, bsf->par_in); + err = ff_cbs_read_extradata(ctx->input, au, bsf->par_in); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); return err; @@ -145,13 +145,13 @@ static int h264_redundant_pps_init(AVBSFContext *bsf) h264_redundant_pps_fixup_pps(ctx, au->units[i].content); } - err = ff_cbs_write_extradata(&ctx->output, bsf->par_out, au); + err = ff_cbs_write_extradata(ctx->output, bsf->par_out, au); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); return err; } - ff_cbs_fragment_uninit(&ctx->output, au); + ff_cbs_fragment_uninit(ctx->output, au); } return 0; diff --git a/libavcodec/h265_metadata_bsf.c b/libavcodec/h265_metadata_bsf.c index aef4a55fb7e54..ffaf7f2873f26 100644 --- a/libavcodec/h265_metadata_bsf.c +++ b/libavcodec/h265_metadata_bsf.c @@ -33,7 +33,7 @@ enum { typedef struct H265MetadataContext { const AVClass *class; - CodedBitstreamContext cbc; + CodedBitstreamContext *cbc; CodedBitstreamFragment access_unit; H265RawAUD aud_nal; @@ -241,7 +241,7 @@ static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *out) if (err < 0) goto fail; - err = ff_cbs_read_packet(&ctx->cbc, au, in); + err = ff_cbs_read_packet(ctx->cbc, au, in); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); goto fail; @@ -256,7 +256,7 @@ static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *out) // If an AUD is present, it must be the first NAL unit. if (au->units[0].type == HEVC_NAL_AUD) { if (ctx->aud == REMOVE) - ff_cbs_delete_unit(&ctx->cbc, au, 0); + ff_cbs_delete_unit(ctx->cbc, au, 0); } else { if (ctx->aud == INSERT) { H265RawAUD *aud = &ctx->aud_nal; @@ -288,7 +288,7 @@ static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *out) }; aud->pic_type = pic_type; - err = ff_cbs_insert_unit_content(&ctx->cbc, au, + err = ff_cbs_insert_unit_content(ctx->cbc, au, 0, HEVC_NAL_AUD, aud); if (err) { av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n"); @@ -310,7 +310,7 @@ static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *out) } } - err = ff_cbs_write_packet(&ctx->cbc, out, au); + err = ff_cbs_write_packet(ctx->cbc, out, au); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); goto fail; @@ -322,7 +322,7 @@ static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *out) err = 0; fail: - ff_cbs_fragment_uninit(&ctx->cbc, au); + ff_cbs_fragment_uninit(ctx->cbc, au); av_packet_free(&in); @@ -340,7 +340,7 @@ static int h265_metadata_init(AVBSFContext *bsf) return err; if (bsf->par_in->extradata) { - err = ff_cbs_read_extradata(&ctx->cbc, au, bsf->par_in); + err = ff_cbs_read_extradata(ctx->cbc, au, bsf->par_in); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); goto fail; @@ -359,7 +359,7 @@ static int h265_metadata_init(AVBSFContext *bsf) } } - err = ff_cbs_write_extradata(&ctx->cbc, bsf->par_out, au); + err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, au); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); goto fail; @@ -368,7 +368,7 @@ static int h265_metadata_init(AVBSFContext *bsf) err = 0; fail: - ff_cbs_fragment_uninit(&ctx->cbc, au); + ff_cbs_fragment_uninit(ctx->cbc, au); return err; } diff --git a/libavcodec/mpeg2_metadata_bsf.c b/libavcodec/mpeg2_metadata_bsf.c index 5dae481d3da3f..4923932864579 100644 --- a/libavcodec/mpeg2_metadata_bsf.c +++ b/libavcodec/mpeg2_metadata_bsf.c @@ -28,7 +28,7 @@ typedef struct MPEG2MetadataContext { const AVClass *class; - CodedBitstreamContext cbc; + CodedBitstreamContext *cbc; CodedBitstreamFragment fragment; MPEG2RawExtensionData sequence_display_extension; @@ -165,7 +165,7 @@ static int mpeg2_metadata_update_fragment(AVBSFContext *bsf, if (add_sde) { int err; - err = ff_cbs_insert_unit_content(&ctx->cbc, frag, se_pos + 1, + err = ff_cbs_insert_unit_content(ctx->cbc, frag, se_pos + 1, MPEG2_START_EXTENSION, &ctx->sequence_display_extension); if (err < 0) { @@ -189,7 +189,7 @@ static int mpeg2_metadata_filter(AVBSFContext *bsf, AVPacket *out) if (err < 0) goto fail; - err = ff_cbs_read_packet(&ctx->cbc, frag, in); + err = ff_cbs_read_packet(ctx->cbc, frag, in); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); goto fail; @@ -201,7 +201,7 @@ static int mpeg2_metadata_filter(AVBSFContext *bsf, AVPacket *out) goto fail; } - err = ff_cbs_write_packet(&ctx->cbc, out, frag); + err = ff_cbs_write_packet(ctx->cbc, out, frag); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); goto fail; @@ -215,7 +215,7 @@ static int mpeg2_metadata_filter(AVBSFContext *bsf, AVPacket *out) err = 0; fail: - ff_cbs_fragment_uninit(&ctx->cbc, frag); + ff_cbs_fragment_uninit(ctx->cbc, frag); av_packet_free(&in); @@ -233,7 +233,7 @@ static int mpeg2_metadata_init(AVBSFContext *bsf) return err; if (bsf->par_in->extradata) { - err = ff_cbs_read_extradata(&ctx->cbc, frag, bsf->par_in); + err = ff_cbs_read_extradata(ctx->cbc, frag, bsf->par_in); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); goto fail; @@ -245,7 +245,7 @@ static int mpeg2_metadata_init(AVBSFContext *bsf) goto fail; } - err = ff_cbs_write_extradata(&ctx->cbc, bsf->par_out, frag); + err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, frag); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); goto fail; @@ -254,7 +254,7 @@ static int mpeg2_metadata_init(AVBSFContext *bsf) err = 0; fail: - ff_cbs_fragment_uninit(&ctx->cbc, frag); + ff_cbs_fragment_uninit(ctx->cbc, frag); return err; } diff --git a/libavcodec/trace_headers_bsf.c b/libavcodec/trace_headers_bsf.c index 2f1369e4dcce3..9c97dd4cea691 100644 --- a/libavcodec/trace_headers_bsf.c +++ b/libavcodec/trace_headers_bsf.c @@ -27,7 +27,7 @@ typedef struct TraceHeadersContext { - CodedBitstreamContext cbc; + CodedBitstreamContext *cbc; } TraceHeadersContext; @@ -40,21 +40,21 @@ static int trace_headers_init(AVBSFContext *bsf) if (err < 0) return err; - ctx->cbc.trace_enable = 1; - ctx->cbc.trace_level = AV_LOG_INFO; + ctx->cbc->trace_enable = 1; + ctx->cbc->trace_level = AV_LOG_INFO; if (bsf->par_in->extradata) { CodedBitstreamFragment ps; av_log(bsf, AV_LOG_INFO, "Extradata\n"); - err = ff_cbs_read_extradata(&ctx->cbc, &ps, bsf->par_in); + err = ff_cbs_read_extradata(ctx->cbc, &ps, bsf->par_in); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); return err; } - ff_cbs_fragment_uninit(&ctx->cbc, &ps); + ff_cbs_fragment_uninit(ctx->cbc, &ps); } return 0; @@ -97,11 +97,11 @@ static int trace_headers(AVBSFContext *bsf, AVPacket *out) av_log(bsf, AV_LOG_INFO, "Packet: %d bytes%s.\n", in->size, tmp); - err = ff_cbs_read_packet(&ctx->cbc, &au, in); + err = ff_cbs_read_packet(ctx->cbc, &au, in); if (err < 0) return err; - ff_cbs_fragment_uninit(&ctx->cbc, &au); + ff_cbs_fragment_uninit(ctx->cbc, &au); av_packet_move_ref(out, in); av_packet_free(&in); diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index b7eee756e129e..a9f8832e20f44 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -78,7 +78,7 @@ typedef struct VAAPIEncodeH264Context { int cpb_delay; int dpb_delay; - CodedBitstreamContext cbc; + CodedBitstreamContext *cbc; CodedBitstreamFragment current_access_unit; int aud_needed; int sei_needed; @@ -104,7 +104,7 @@ static int vaapi_encode_h264_write_access_unit(AVCodecContext *avctx, VAAPIEncodeH264Context *priv = ctx->priv_data; int err; - err = ff_cbs_write_fragment_data(&priv->cbc, au); + err = ff_cbs_write_fragment_data(priv->cbc, au); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); return err; @@ -132,7 +132,7 @@ static int vaapi_encode_h264_add_nal(AVCodecContext *avctx, H264RawNALUnitHeader *header = nal_unit; int err; - err = ff_cbs_insert_unit_content(&priv->cbc, au, -1, + err = ff_cbs_insert_unit_content(priv->cbc, au, -1, header->nal_unit_type, nal_unit); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " @@ -168,7 +168,7 @@ static int vaapi_encode_h264_write_sequence_header(AVCodecContext *avctx, err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au); fail: - ff_cbs_fragment_uninit(&priv->cbc, au); + ff_cbs_fragment_uninit(priv->cbc, au); return err; } @@ -195,7 +195,7 @@ static int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx, err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au); fail: - ff_cbs_fragment_uninit(&priv->cbc, au); + ff_cbs_fragment_uninit(priv->cbc, au); return err; } @@ -255,7 +255,7 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, if (err < 0) goto fail; - ff_cbs_fragment_uninit(&priv->cbc, au); + ff_cbs_fragment_uninit(priv->cbc, au); *type = VAEncPackedHeaderRawData; return 0; @@ -277,7 +277,7 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx, } fail: - ff_cbs_fragment_uninit(&priv->cbc, au); + ff_cbs_fragment_uninit(priv->cbc, au); return err; } diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index a9853a3aa0a6a..38c9e2521230b 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -55,7 +55,7 @@ typedef struct VAAPIEncodeH265Context { int slice_type; int pic_type; - CodedBitstreamContext cbc; + CodedBitstreamContext *cbc; CodedBitstreamFragment current_access_unit; int aud_needed; } VAAPIEncodeH265Context; @@ -76,7 +76,7 @@ static int vaapi_encode_h265_write_access_unit(AVCodecContext *avctx, VAAPIEncodeH265Context *priv = ctx->priv_data; int err; - err = ff_cbs_write_fragment_data(&priv->cbc, au); + err = ff_cbs_write_fragment_data(priv->cbc, au); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); return err; @@ -104,7 +104,7 @@ static int vaapi_encode_h265_add_nal(AVCodecContext *avctx, H265RawNALUnitHeader *header = nal_unit; int err; - err = ff_cbs_insert_unit_content(&priv->cbc, au, -1, + err = ff_cbs_insert_unit_content(priv->cbc, au, -1, header->nal_unit_type, nal_unit); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " @@ -144,7 +144,7 @@ static int vaapi_encode_h265_write_sequence_header(AVCodecContext *avctx, err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); fail: - ff_cbs_fragment_uninit(&priv->cbc, au); + ff_cbs_fragment_uninit(priv->cbc, au); return err; } @@ -171,7 +171,7 @@ static int vaapi_encode_h265_write_slice_header(AVCodecContext *avctx, err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); fail: - ff_cbs_fragment_uninit(&priv->cbc, au); + ff_cbs_fragment_uninit(priv->cbc, au); return err; } diff --git a/libavcodec/vaapi_encode_mpeg2.c b/libavcodec/vaapi_encode_mpeg2.c index 954b60733c1fa..39f1e4b5f2967 100644 --- a/libavcodec/vaapi_encode_mpeg2.c +++ b/libavcodec/vaapi_encode_mpeg2.c @@ -52,7 +52,7 @@ typedef struct VAAPIEncodeMPEG2Context { unsigned int f_code_horizontal; unsigned int f_code_vertical; - CodedBitstreamContext cbc; + CodedBitstreamContext *cbc; CodedBitstreamFragment current_fragment; } VAAPIEncodeMPEG2Context; @@ -65,7 +65,7 @@ static int vaapi_encode_mpeg2_write_fragment(AVCodecContext *avctx, VAAPIEncodeMPEG2Context *priv = ctx->priv_data; int err; - err = ff_cbs_write_fragment_data(&priv->cbc, frag); + err = ff_cbs_write_fragment_data(priv->cbc, frag); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); return err; @@ -92,7 +92,7 @@ static int vaapi_encode_mpeg2_add_header(AVCodecContext *avctx, VAAPIEncodeMPEG2Context *priv = ctx->priv_data; int err; - err = ff_cbs_insert_unit_content(&priv->cbc, frag, -1, type, header); + err = ff_cbs_insert_unit_content(priv->cbc, frag, -1, type, header); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to add header: " "type = %d.\n", type); @@ -132,7 +132,7 @@ static int vaapi_encode_mpeg2_write_sequence_header(AVCodecContext *avctx, err = vaapi_encode_mpeg2_write_fragment(avctx, data, data_len, frag); fail: - ff_cbs_fragment_uninit(&priv->cbc, frag); + ff_cbs_fragment_uninit(priv->cbc, frag); return 0; } @@ -157,7 +157,7 @@ static int vaapi_encode_mpeg2_write_picture_header(AVCodecContext *avctx, err = vaapi_encode_mpeg2_write_fragment(avctx, data, data_len, frag); fail: - ff_cbs_fragment_uninit(&priv->cbc, frag); + ff_cbs_fragment_uninit(priv->cbc, frag); return 0; } From 1d12a545ce828eaf4fb37295400008ea37635ab8 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 9 Nov 2017 01:04:02 +0000 Subject: [PATCH 1910/2557] cbs: Add an explicit type for coded bitstream unit types Also fix conversion specifiers used for the unit type. --- libavcodec/cbs.c | 12 +++++++----- libavcodec/cbs.h | 19 +++++++++++++++---- libavcodec/cbs_h2645.c | 2 +- libavcodec/cbs_mpeg2.c | 4 ++-- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index fd9baa2997c9d..e5819afce3c37 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -137,10 +137,10 @@ static int cbs_read_fragment_content(CodedBitstreamContext *ctx, if (err == AVERROR(ENOSYS)) { av_log(ctx->log_ctx, AV_LOG_WARNING, "Decomposition unimplemented for unit %d " - "(type %d).\n", i, frag->units[i].type); + "(type %"PRIu32").\n", i, frag->units[i].type); } else if (err < 0) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d " - "(type %d).\n", i, frag->units[i].type); + "(type %"PRIu32").\n", i, frag->units[i].type); return err; } } @@ -225,7 +225,7 @@ int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx, err = ctx->codec->write_unit(ctx, &frag->units[i]); if (err < 0) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d " - "(type %d).\n", i, frag->units[i].type); + "(type %"PRIu32").\n", i, frag->units[i].type); return err; } } @@ -421,7 +421,8 @@ static int cbs_insert_unit(CodedBitstreamContext *ctx, int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, - int position, uint32_t type, + int position, + CodedBitstreamUnitType type, void *content) { int err; @@ -443,7 +444,8 @@ int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx, int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, - int position, uint32_t type, + int position, + CodedBitstreamUnitType type, uint8_t *data, size_t data_size) { int err; diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h index 34ee78be32fb6..85c7b55577293 100644 --- a/libavcodec/cbs.h +++ b/libavcodec/cbs.h @@ -27,6 +27,15 @@ struct CodedBitstreamType; +/** + * The codec-specific type of a bitstream unit. + * + * H.264 / AVC: nal_unit_type + * H.265 / HEVC: nal_unit_type + * MPEG-2: start code value (without prefix) + */ +typedef uint32_t CodedBitstreamUnitType; + /** * Coded bitstream unit structure. * @@ -40,7 +49,7 @@ typedef struct CodedBitstreamUnit { /** * Codec-specific type of this unit. */ - uint32_t type; + CodedBitstreamUnitType type; /** * Pointer to the bitstream form of this unit. @@ -149,7 +158,7 @@ typedef struct CodedBitstreamContext { * Types not in this list will be available in bitstream form only. * If NULL, all supported types will be decomposed. */ - uint32_t *decompose_unit_types; + CodedBitstreamUnitType *decompose_unit_types; /** * Length of the decompose_unit_types array. */ @@ -250,7 +259,8 @@ void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx, */ int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, - int position, uint32_t type, + int position, + CodedBitstreamUnitType type, void *content); /** @@ -260,7 +270,8 @@ int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx, */ int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, - int position, uint32_t type, + int position, + CodedBitstreamUnitType type, uint8_t *data, size_t data_size); /** diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 00eed0f283609..e3b5bf618a570 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -1213,7 +1213,7 @@ static int cbs_h265_write_nal_unit(CodedBitstreamContext *ctx, default: av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for " - "NAL unit type %d.\n", unit->type); + "NAL unit type %"PRIu32".\n", unit->type); return AVERROR_PATCHWELCOME; } diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index 54875c2e1c379..5956f393355a0 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -220,7 +220,7 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header); #undef START default: - av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown start code %02x.\n", + av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown start code %02"PRIx32".\n", unit->type); return AVERROR_INVALIDDATA; } @@ -248,7 +248,7 @@ static int cbs_mpeg2_write_header(CodedBitstreamContext *ctx, #undef START default: av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for start " - "code %02x.\n", unit->type); + "code %02"PRIx32".\n", unit->type); return AVERROR_PATCHWELCOME; } From 254e728d207c173a3714e6a01c9d68fcb3af8b73 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 9 Nov 2017 01:04:15 +0000 Subject: [PATCH 1911/2557] cbs: Minor comment fixes / cosmetics --- libavcodec/cbs.h | 35 +++++++++++++++++++++++++++++++---- libavcodec/cbs_internal.h | 3 +++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h index 85c7b55577293..ffeca057abb89 100644 --- a/libavcodec/cbs.h +++ b/libavcodec/cbs.h @@ -25,6 +25,19 @@ #include "avcodec.h" +/* + * This defines a framework for converting between a coded bitstream + * and structures defining all individual syntax elements found in + * such a stream. + * + * Conversion in both directions is possible. Given a coded bitstream + * (any meaningful fragment), it can be parsed and decomposed into + * syntax elements stored in a set of codec-specific structures. + * Similarly, given a set of those same codec-specific structures the + * syntax elements can be serialised and combined to create a coded + * bitstream. + */ + struct CodedBitstreamType; /** @@ -39,7 +52,7 @@ typedef uint32_t CodedBitstreamUnitType; /** * Coded bitstream unit structure. * - * A bitstream unit the the smallest element of a bitstream which + * A bitstream unit the smallest element of a bitstream which * is meaningful on its own. For example, an H.264 NAL unit. * * See the codec-specific header for the meaning of this for any @@ -52,7 +65,7 @@ typedef struct CodedBitstreamUnit { CodedBitstreamUnitType type; /** - * Pointer to the bitstream form of this unit. + * Pointer to the directly-parsable bitstream form of this unit. * * May be NULL if the unit currently only exists in decomposed form. */ @@ -114,7 +127,7 @@ typedef struct CodedBitstreamFragment { /** * Number of units in this fragment. * - * This may be zero if the fragment only exists in bistream form + * This may be zero if the fragment only exists in bitstream form * and has not been decomposed. */ int nb_units; @@ -162,7 +175,7 @@ typedef struct CodedBitstreamContext { /** * Length of the decompose_unit_types array. */ - int nb_decompose_unit_types; + int nb_decompose_unit_types; /** * Enable trace output during read/write operations. @@ -204,6 +217,10 @@ int ff_cbs_read_extradata(CodedBitstreamContext *ctx, /** * Read the data bitstream from a packet into a fragment, then * split into units and decompose. + * + * This also updates the internal state of the coded bitstream context + * with any persistent data from the fragment which may be required to + * read following fragments (e.g. parameter sets). */ int ff_cbs_read_packet(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, @@ -212,6 +229,10 @@ int ff_cbs_read_packet(CodedBitstreamContext *ctx, /** * Read a bitstream from a memory region into a fragment, then * split into units and decompose. + * + * This also updates the internal state of the coded bitstream context + * with any persistent data from the fragment which may be required to + * read following fragments (e.g. parameter sets). */ int ff_cbs_read(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, @@ -225,12 +246,18 @@ int ff_cbs_read(CodedBitstreamContext *ctx, * data buffer. When modifying the content of decomposed units, this * can be used to regenerate the bitstream form of units or the whole * fragment so that it can be extracted for other use. + * + * This also updates the internal state of the coded bitstream context + * with any persistent data from the fragment which may be required to + * write following fragments (e.g. parameter sets). */ int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag); /** * Write the bitstream of a fragment to the extradata in codec parameters. + * + * This replaces any existing extradata in the structure. */ int ff_cbs_write_extradata(CodedBitstreamContext *ctx, AVCodecParameters *par, diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index dddeae9d5bd46..1a1c22f0680c8 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -32,6 +32,9 @@ typedef struct CodedBitstreamType { // Split frag->data into coded bitstream units, creating the // frag->units array. Fill data but not content on each unit. + // The header argument should be set if the fragment came from + // a header block, which may require different parsing for some + // codecs (e.g. the AVCC header in H.264). int (*split_fragment)(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, int header); From c8e135ea9225137050a6315fd9ba9c0f242c90b6 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Thu, 24 Aug 2017 09:13:01 +0800 Subject: [PATCH 1912/2557] vaapi_encode: Allocate slice structures and parameter buffers dynamically This removes the arbitrary limit on the allowed number of slices and parameter buffers. From ffmpeg commit e4a6eb70f471eda36592078e8fa1bad87fc9df73. Signed-off-by: Mark Thompson --- libavcodec/vaapi_encode.c | 40 +++++++++++++++++++++++++++++---------- libavcodec/vaapi_encode.h | 6 ++---- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 47795ba735546..c6113b1de5fbc 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -36,13 +36,17 @@ static int vaapi_encode_make_packed_header(AVCodecContext *avctx, VAAPIEncodeContext *ctx = avctx->priv_data; VAStatus vas; VABufferID param_buffer, data_buffer; + VABufferID *tmp; VAEncPackedHeaderParameterBuffer params = { .type = type, .bit_length = bit_len, .has_emulation_bytes = 1, }; - av_assert0(pic->nb_param_buffers + 2 <= MAX_PARAM_BUFFERS); + tmp = av_realloc_array(pic->param_buffers, sizeof(*tmp), pic->nb_param_buffers + 2); + if (!tmp) + return AVERROR(ENOMEM); + pic->param_buffers = tmp; vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, VAEncPackedHeaderParameterBufferType, @@ -77,9 +81,13 @@ static int vaapi_encode_make_param_buffer(AVCodecContext *avctx, { VAAPIEncodeContext *ctx = avctx->priv_data; VAStatus vas; + VABufferID *tmp; VABufferID buffer; - av_assert0(pic->nb_param_buffers + 1 <= MAX_PARAM_BUFFERS); + tmp = av_realloc_array(pic->param_buffers, sizeof(*tmp), pic->nb_param_buffers + 1); + if (!tmp) + return AVERROR(ENOMEM); + pic->param_buffers = tmp; vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, type, len, 1, data, &buffer); @@ -313,15 +321,16 @@ static int vaapi_encode_issue(AVCodecContext *avctx, } } - av_assert0(pic->nb_slices <= MAX_PICTURE_SLICES); - for (i = 0; i < pic->nb_slices; i++) { - slice = av_mallocz(sizeof(*slice)); - if (!slice) { + if (pic->nb_slices > 0) { + pic->slices = av_mallocz_array(pic->nb_slices, sizeof(*pic->slices)); + if (!pic->slices) { err = AVERROR(ENOMEM); goto fail; } + } + for (i = 0; i < pic->nb_slices; i++) { + slice = &pic->slices[i]; slice->index = i; - pic->slices[i] = slice; if (ctx->codec->slice_params_size > 0) { slice->codec_slice_params = av_mallocz(ctx->codec->slice_params_size); @@ -425,8 +434,16 @@ static int vaapi_encode_issue(AVCodecContext *avctx, fail: for(i = 0; i < pic->nb_param_buffers; i++) vaDestroyBuffer(ctx->hwctx->display, pic->param_buffers[i]); + for (i = 0; i < pic->nb_slices; i++) { + if (pic->slices) { + av_freep(&pic->slices[i].priv_data); + av_freep(&pic->slices[i].codec_slice_params); + } + } fail_at_end: av_freep(&pic->codec_picture_params); + av_freep(&pic->param_buffers); + av_freep(&pic->slices); av_frame_free(&pic->recon_image); av_buffer_unref(&pic->output_buffer_ref); pic->output_buffer = VA_INVALID_ID; @@ -535,15 +552,18 @@ static int vaapi_encode_free(AVCodecContext *avctx, vaapi_encode_discard(avctx, pic); for (i = 0; i < pic->nb_slices; i++) { - av_freep(&pic->slices[i]->priv_data); - av_freep(&pic->slices[i]->codec_slice_params); - av_freep(&pic->slices[i]); + if (pic->slices) { + av_freep(&pic->slices[i].priv_data); + av_freep(&pic->slices[i].codec_slice_params); + } } av_freep(&pic->codec_picture_params); av_frame_free(&pic->input_image); av_frame_free(&pic->recon_image); + av_freep(&pic->param_buffers); + av_freep(&pic->slices); // Output buffer should already be destroyed. av_assert0(pic->output_buffer == VA_INVALID_ID); diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 1b0fed80e449a..31c3790531072 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -35,8 +35,6 @@ enum { MAX_CONFIG_ATTRIBUTES = 4, MAX_GLOBAL_PARAMS = 4, MAX_PICTURE_REFERENCES = 2, - MAX_PICTURE_SLICES = 112, - MAX_PARAM_BUFFERS = 128, MAX_REORDER_DELAY = 16, MAX_PARAM_BUFFER_SIZE = 1024, }; @@ -73,7 +71,7 @@ typedef struct VAAPIEncodePicture { VASurfaceID recon_surface; int nb_param_buffers; - VABufferID param_buffers[MAX_PARAM_BUFFERS]; + VABufferID *param_buffers; AVBufferRef *output_buffer_ref; VABufferID output_buffer; @@ -85,7 +83,7 @@ typedef struct VAAPIEncodePicture { struct VAAPIEncodePicture *refs[MAX_PICTURE_REFERENCES]; int nb_slices; - VAAPIEncodeSlice *slices[MAX_PICTURE_SLICES]; + VAAPIEncodeSlice *slices; } VAAPIEncodePicture; typedef struct VAAPIEncodeContext { From 216c44dfc17252ec0681dcb0bbeeb45a9d14eca7 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 17 Dec 2017 19:48:35 +0000 Subject: [PATCH 1913/2557] vaapi_encode: Destroy output buffer pool before VA context The buffers are created associated with the context, so they should be destroyed before the context is. This is enforced by the iHD driver. --- libavcodec/vaapi_encode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index c6113b1de5fbc..398b8e11f2f4c 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1556,6 +1556,8 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx) vaapi_encode_free(avctx, pic); } + av_buffer_pool_uninit(&ctx->output_buffer_pool); + if (ctx->va_context != VA_INVALID_ID) { vaDestroyContext(ctx->hwctx->display, ctx->va_context); ctx->va_context = VA_INVALID_ID; @@ -1566,8 +1568,6 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx) ctx->va_config = VA_INVALID_ID; } - av_buffer_pool_uninit(&ctx->output_buffer_pool); - av_freep(&ctx->codec_sequence_params); av_freep(&ctx->codec_picture_params); From 67eb2b16daa77f6ba3e04a28ca18e53193723b7f Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 17 Dec 2017 19:50:29 +0000 Subject: [PATCH 1914/2557] vaapi_h265: Mark unused entries in RefPicList[01] as explicitly invalid The iHD driver looks at entries beyond num_ref_idx_l[01]_active_minus1 for unknown reasons. --- libavcodec/vaapi_encode_h265.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 38c9e2521230b..52ac4a68753b2 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -767,8 +767,6 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, .num_ref_idx_l0_active_minus1 = sh->num_ref_idx_l0_active_minus1, .num_ref_idx_l1_active_minus1 = sh->num_ref_idx_l1_active_minus1, - .ref_pic_list0[0] = vpic->reference_frames[0], - .ref_pic_list1[0] = vpic->reference_frames[1], .luma_log2_weight_denom = sh->luma_log2_weight_denom, .delta_chroma_log2_weight_denom = sh->delta_chroma_log2_weight_denom, @@ -802,6 +800,25 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, }, }; + for (i = 0; i < FF_ARRAY_ELEMS(vslice->ref_pic_list0); i++) { + vslice->ref_pic_list0[i].picture_id = VA_INVALID_ID; + vslice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID; + vslice->ref_pic_list1[i].picture_id = VA_INVALID_ID; + vslice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID; + } + + av_assert0(pic->nb_refs <= 2); + if (pic->nb_refs >= 1) { + // Backward reference for P- or B-frame. + av_assert0(pic->type == PICTURE_TYPE_P || + pic->type == PICTURE_TYPE_B); + vslice->ref_pic_list0[0] = vpic->reference_frames[0]; + } + if (pic->nb_refs >= 2) { + // Forward reference for B-frame. + av_assert0(pic->type == PICTURE_TYPE_B); + vslice->ref_pic_list1[0] = vpic->reference_frames[1]; + } return 0; } From a3daecd6375279d9fdb863ac9db3545a33e97651 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 11 Dec 2017 00:28:40 +0000 Subject: [PATCH 1915/2557] cbs: Demote the "decomposition unimplemented" warning This is harmless and should not be a warning - unknown units are passed through to the write functions unchanged, and no other code will interact with them. --- libavcodec/cbs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index e5819afce3c37..a8d252f6c20f6 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -135,7 +135,7 @@ static int cbs_read_fragment_content(CodedBitstreamContext *ctx, err = ctx->codec->read_unit(ctx, &frag->units[i]); if (err == AVERROR(ENOSYS)) { - av_log(ctx->log_ctx, AV_LOG_WARNING, + av_log(ctx->log_ctx, AV_LOG_VERBOSE, "Decomposition unimplemented for unit %d " "(type %"PRIu32").\n", i, frag->units[i].type); } else if (err < 0) { From 0e4c166cdd6446522a085dd9731967d09ac71f72 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 11 Dec 2017 00:38:57 +0000 Subject: [PATCH 1916/2557] cbs_h2645: Remove active ps references when it is replaced --- libavcodec/cbs_h2645.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index e3b5bf618a570..9d05d59156f64 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -674,6 +674,8 @@ static int cbs_h26 ## h26n ## _replace_ ## ps_var(CodedBitstreamContext *ctx, \ " id : %d.\n", id); \ return AVERROR_INVALIDDATA; \ } \ + if (priv->ps_var[id] == priv->active_ ## ps_var) \ + priv->active_ ## ps_var = NULL ; \ av_freep(&priv->ps_var[id]); \ priv->ps_var[id] = av_malloc(sizeof(*ps_var)); \ if (!priv->ps_var[id]) \ From 13ca5d34ba5c473211daaae0a101123bcaada3e6 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 11 Dec 2017 00:22:42 +0000 Subject: [PATCH 1917/2557] cbs_h264: Add hack for pic_timing with no active SPS If there is exactly one possible SPS but it is not yet active then just assume that it should be the active one. --- libavcodec/cbs_h264_syntax_template.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libavcodec/cbs_h264_syntax_template.c b/libavcodec/cbs_h264_syntax_template.c index 0fe18441c03ac..c2fd546822f1e 100644 --- a/libavcodec/cbs_h264_syntax_template.c +++ b/libavcodec/cbs_h264_syntax_template.c @@ -560,6 +560,22 @@ static int FUNC(sei_pic_timing)(CodedBitstreamContext *ctx, RWContext *rw, int err; sps = h264->active_sps; + if (!sps) { + // If there is exactly one possible SPS but it is not yet active + // then just assume that it should be the active one. + int i, k = -1; + for (i = 0; i < H264_MAX_SPS_COUNT; i++) { + if (h264->sps[i]) { + if (k >= 0) { + k = -1; + break; + } + k = i; + } + } + if (k >= 0) + sps = h264->sps[k]; + } if (!sps) { av_log(ctx->log_ctx, AV_LOG_ERROR, "No active SPS for pic_timing.\n"); From ce5870a3a8f2b10668ee4f04c2ae0287f66f31b2 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Feb 2018 00:51:33 +0000 Subject: [PATCH 1918/2557] cbs: Refcount all the things! This makes it easier for users of the CBS API to get alloc/free right - all subelements use the buffer API so that it's clear how to free them. It also allows eliding some redundant copies: the packet -> fragment copy disappears after this change if the input packet is refcounted, and more codec-specific cases are now possible (but not included in this patch). --- libavcodec/cbs.c | 165 +++++++++--- libavcodec/cbs.h | 51 +++- libavcodec/cbs_h264.h | 4 + libavcodec/cbs_h2645.c | 340 ++++++++++++------------- libavcodec/cbs_h265.h | 2 + libavcodec/cbs_internal.h | 3 - libavcodec/cbs_mpeg2.c | 91 +++---- libavcodec/cbs_mpeg2.h | 5 + libavcodec/cbs_mpeg2_syntax_template.c | 5 +- libavcodec/h264_metadata_bsf.c | 6 +- libavcodec/h265_metadata_bsf.c | 2 +- libavcodec/mpeg2_metadata_bsf.c | 3 +- libavcodec/vaapi_encode_h264.c | 2 +- libavcodec/vaapi_encode_h265.c | 2 +- libavcodec/vaapi_encode_mpeg2.c | 2 +- 15 files changed, 404 insertions(+), 279 deletions(-) diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index a8d252f6c20f6..04ad2dfc41af2 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -21,6 +21,7 @@ #include "config.h" #include "libavutil/avassert.h" +#include "libavutil/buffer.h" #include "libavutil/common.h" #include "cbs.h" @@ -95,11 +96,12 @@ void ff_cbs_close(CodedBitstreamContext **ctx_ptr) static void cbs_unit_uninit(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit) { - if (ctx->codec->free_unit && unit->content && !unit->content_external) - ctx->codec->free_unit(unit); + av_buffer_unref(&unit->content_ref); + unit->content = NULL; - av_freep(&unit->data); - unit->data_size = 0; + av_buffer_unref(&unit->data_ref); + unit->data = NULL; + unit->data_size = 0; unit->data_bit_padding = 0; } @@ -113,7 +115,8 @@ void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx, av_freep(&frag->units); frag->nb_units = 0; - av_freep(&frag->data); + av_buffer_unref(&frag->data_ref); + frag->data = NULL; frag->data_size = 0; frag->data_bit_padding = 0; } @@ -133,6 +136,9 @@ static int cbs_read_fragment_content(CodedBitstreamContext *ctx, continue; } + av_buffer_unref(&frag->units[i].content_ref); + frag->units[i].content = NULL; + err = ctx->codec->read_unit(ctx, &frag->units[i]); if (err == AVERROR(ENOSYS)) { av_log(ctx->log_ctx, AV_LOG_VERBOSE, @@ -169,6 +175,27 @@ int ff_cbs_read_extradata(CodedBitstreamContext *ctx, return cbs_read_fragment_content(ctx, frag); } +static int cbs_fill_fragment_data(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const uint8_t *data, size_t size) +{ + av_assert0(!frag->data && !frag->data_ref); + + frag->data_ref = + av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!frag->data_ref) + return AVERROR(ENOMEM); + + frag->data = frag->data_ref->data; + frag->data_size = size; + + memcpy(frag->data, data, size); + memset(frag->data + size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); + + return 0; +} + int ff_cbs_read_packet(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, const AVPacket *pkt) @@ -177,16 +204,24 @@ int ff_cbs_read_packet(CodedBitstreamContext *ctx, memset(frag, 0, sizeof(*frag)); - frag->data = pkt->data; - frag->data_size = pkt->size; + if (pkt->buf) { + frag->data_ref = av_buffer_ref(pkt->buf); + if (!frag->data_ref) + return AVERROR(ENOMEM); + + frag->data = pkt->data; + frag->data_size = pkt->size; + + } else { + err = cbs_fill_fragment_data(ctx, frag, pkt->data, pkt->size); + if (err < 0) + return err; + } err = ctx->codec->split_fragment(ctx, frag, 0); if (err < 0) return err; - frag->data = NULL; - frag->data_size = 0; - return cbs_read_fragment_content(ctx, frag); } @@ -198,17 +233,14 @@ int ff_cbs_read(CodedBitstreamContext *ctx, memset(frag, 0, sizeof(*frag)); - // (We won't write to this during split.) - frag->data = (uint8_t*)data; - frag->data_size = size; + err = cbs_fill_fragment_data(ctx, frag, data, size); + if (err < 0) + return err; err = ctx->codec->split_fragment(ctx, frag, 0); if (err < 0) return err; - frag->data = NULL; - frag->data_size = 0; - return cbs_read_fragment_content(ctx, frag); } @@ -219,17 +251,25 @@ int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx, int err, i; for (i = 0; i < frag->nb_units; i++) { - if (!frag->units[i].content) + CodedBitstreamUnit *unit = &frag->units[i]; + + if (!unit->content) continue; - err = ctx->codec->write_unit(ctx, &frag->units[i]); + av_buffer_unref(&unit->data_ref); + unit->data = NULL; + + err = ctx->codec->write_unit(ctx, unit); if (err < 0) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d " - "(type %"PRIu32").\n", i, frag->units[i].type); + "(type %"PRIu32").\n", i, unit->type); return err; } } + av_buffer_unref(&frag->data_ref); + frag->data = NULL; + err = ctx->codec->assemble_fragment(ctx, frag); if (err < 0) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n"); @@ -394,6 +434,45 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc, } +int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + size_t size, + void (*free)(void *opaque, uint8_t *data)) +{ + av_assert0(!unit->content && !unit->content_ref); + + unit->content = av_mallocz(size); + if (!unit->content) + return AVERROR(ENOMEM); + + unit->content_ref = av_buffer_create(unit->content, size, + free, ctx, 0); + if (!unit->content_ref) { + av_freep(&unit->content); + return AVERROR(ENOMEM); + } + + return 0; +} + +int ff_cbs_alloc_unit_data(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + size_t size) +{ + av_assert0(!unit->data && !unit->data_ref); + + unit->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!unit->data_ref) + return AVERROR(ENOMEM); + + unit->data = unit->data_ref->data; + unit->data_size = size; + + memset(unit->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + return 0; +} + static int cbs_insert_unit(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, int position) @@ -423,21 +502,35 @@ int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, int position, CodedBitstreamUnitType type, - void *content) + void *content, + AVBufferRef *content_buf) { + CodedBitstreamUnit *unit; + AVBufferRef *content_ref; int err; if (position == -1) position = frag->nb_units; av_assert0(position >= 0 && position <= frag->nb_units); + if (content_buf) { + content_ref = av_buffer_ref(content_buf); + if (!content_ref) + return AVERROR(ENOMEM); + } else { + content_ref = NULL; + } + err = cbs_insert_unit(ctx, frag, position); - if (err < 0) + if (err < 0) { + av_buffer_unref(&content_ref); return err; + } - frag->units[position].type = type; - frag->units[position].content = content; - frag->units[position].content_external = 1; + unit = &frag->units[position]; + unit->type = type; + unit->content = content; + unit->content_ref = content_ref; return 0; } @@ -446,21 +539,35 @@ int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, int position, CodedBitstreamUnitType type, - uint8_t *data, size_t data_size) + uint8_t *data, size_t data_size, + AVBufferRef *data_buf) { + CodedBitstreamUnit *unit; + AVBufferRef *data_ref; int err; if (position == -1) position = frag->nb_units; av_assert0(position >= 0 && position <= frag->nb_units); + if (data_buf) + data_ref = av_buffer_ref(data_buf); + else + data_ref = av_buffer_create(data, data_size, NULL, NULL, 0); + if (!data_ref) + return AVERROR(ENOMEM); + err = cbs_insert_unit(ctx, frag, position); - if (err < 0) + if (err < 0) { + av_buffer_unref(&data_ref); return err; + } - frag->units[position].type = type; - frag->units[position].data = data; - frag->units[position].data_size = data_size; + unit = &frag->units[position]; + unit->type = type; + unit->data = data; + unit->data_size = data_size; + unit->data_ref = data_ref; return 0; } diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h index ffeca057abb89..65053867083c8 100644 --- a/libavcodec/cbs.h +++ b/libavcodec/cbs.h @@ -22,6 +22,8 @@ #include #include +#include "libavutil/buffer.h" + #include "avcodec.h" @@ -81,6 +83,11 @@ typedef struct CodedBitstreamUnit { * This supports non-byte-aligned bitstreams. */ size_t data_bit_padding; + /** + * If data is reference counted, a reference to the buffer containing + * data. Null if data is not reference counted. + */ + AVBufferRef *data_ref; /** * Pointer to the decomposed form of this unit. @@ -91,11 +98,10 @@ typedef struct CodedBitstreamUnit { */ void *content; /** - * Whether the content was supplied externally. - * - * If so, it should not be freed when freeing the unit. + * If content is reference counted, a reference to the buffer containing + * content. Null if content is not reference counted. */ - int content_external; + AVBufferRef *content_ref; } CodedBitstreamUnit; /** @@ -123,6 +129,11 @@ typedef struct CodedBitstreamFragment { * The number of bits which should be ignored in the final byte. */ size_t data_bit_padding; + /** + * If data is reference counted, a reference to the buffer containing + * data. Null if data is not reference counted. + */ + AVBufferRef *data_ref; /** * Number of units in this fragment. @@ -278,28 +289,50 @@ void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag); +/** + * Allocate a new internal content buffer of the given size in the unit. + * + * The content will be zeroed. + */ +int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + size_t size, + void (*free)(void *unit, uint8_t *content)); + +/** + * Allocate a new internal data buffer of the given size in the unit. + * + * The data buffer will have input padding. + */ +int ff_cbs_alloc_unit_data(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + size_t size); + /** * Insert a new unit into a fragment with the given content. * - * The content structure continues to be owned by the caller, and - * will not be freed when the unit is. + * The content structure continues to be owned by the caller if + * content_buf is not supplied. */ int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, int position, CodedBitstreamUnitType type, - void *content); + void *content, + AVBufferRef *content_buf); /** * Insert a new unit into a fragment with the given data bitstream. * - * The data buffer will be owned by the unit after this operation. + * If data_buf is not supplied then data must have been allocated with + * av_malloc() and will become owned by the unit after this call. */ int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, int position, CodedBitstreamUnitType type, - uint8_t *data, size_t data_size); + uint8_t *data, size_t data_size, + AVBufferRef *data_buf); /** * Delete a unit from a fragment and free all memory it uses. diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h index b58f19f17ea52..14ea69ae286df 100644 --- a/libavcodec/cbs_h264.h +++ b/libavcodec/cbs_h264.h @@ -266,12 +266,14 @@ typedef struct H264RawSEIUserDataRegistered { uint8_t itu_t_t35_country_code_extension_byte; uint8_t *data; size_t data_length; + AVBufferRef *data_ref; } H264RawSEIUserDataRegistered; typedef struct H264RawSEIUserDataUnregistered { uint8_t uuid_iso_iec_11578[16]; uint8_t *data; size_t data_length; + AVBufferRef *data_ref; } H264RawSEIUserDataUnregistered; typedef struct H264RawSEIRecoveryPoint { @@ -304,6 +306,7 @@ typedef struct H264RawSEIPayload { struct { uint8_t *data; size_t data_length; + AVBufferRef *data_ref; } other; } payload; } H264RawSEIPayload; @@ -399,6 +402,7 @@ typedef struct H264RawSlice { uint8_t *data; size_t data_size; int data_bit_start; + AVBufferRef *data_ref; } H264RawSlice; diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 9d05d59156f64..5b23d6104be05 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -291,9 +291,10 @@ static int cbs_h2645_read_more_rbsp_data(BitstreamContext *bc) #define byte_alignment(rw) (bitstream_tell(rw) % 8) #define allocate(name, size) do { \ - name = av_mallocz(size); \ - if (!name) \ + name ## _ref = av_buffer_allocz(size); \ + if (!name ## _ref) \ return AVERROR(ENOMEM); \ + name = name ## _ref->data; \ } while (0) #define FUNC(name) FUNC_H264(READWRITE, name) @@ -393,82 +394,68 @@ static int cbs_h2645_read_more_rbsp_data(BitstreamContext *bc) #undef allocate -static void cbs_h264_free_sei(H264RawSEI *sei) +static void cbs_h264_free_sei_payload(H264RawSEIPayload *payload) { - int i; - for (i = 0; i < sei->payload_count; i++) { - H264RawSEIPayload *payload = &sei->payload[i]; - - switch (payload->payload_type) { - case H264_SEI_TYPE_BUFFERING_PERIOD: - case H264_SEI_TYPE_PIC_TIMING: - case H264_SEI_TYPE_RECOVERY_POINT: - case H264_SEI_TYPE_DISPLAY_ORIENTATION: - break; - case H264_SEI_TYPE_USER_DATA_REGISTERED: - av_freep(&payload->payload.user_data_registered.data); - break; - case H264_SEI_TYPE_USER_DATA_UNREGISTERED: - av_freep(&payload->payload.user_data_unregistered.data); - break; - default: - av_freep(&payload->payload.other.data); - break; - } + switch (payload->payload_type) { + case H264_SEI_TYPE_BUFFERING_PERIOD: + case H264_SEI_TYPE_PIC_TIMING: + case H264_SEI_TYPE_RECOVERY_POINT: + case H264_SEI_TYPE_DISPLAY_ORIENTATION: + break; + case H264_SEI_TYPE_USER_DATA_REGISTERED: + av_buffer_unref(&payload->payload.user_data_registered.data_ref); + break; + case H264_SEI_TYPE_USER_DATA_UNREGISTERED: + av_buffer_unref(&payload->payload.user_data_unregistered.data_ref); + break; + default: + av_buffer_unref(&payload->payload.other.data_ref); + break; } } -static void cbs_h264_free_slice(H264RawSlice *slice) +static void cbs_h264_free_sei(void *unit, uint8_t *content) { - av_freep(&slice->data); + H264RawSEI *sei = (H264RawSEI*)content; + int i; + for (i = 0; i < sei->payload_count; i++) + cbs_h264_free_sei_payload(&sei->payload[i]); + av_freep(&content); } -static void cbs_h264_free_nal_unit(CodedBitstreamUnit *unit) +static void cbs_h264_free_slice(void *unit, uint8_t *content) { - switch (unit->type) { - case H264_NAL_SEI: - cbs_h264_free_sei(unit->content); - break; - case H264_NAL_IDR_SLICE: - case H264_NAL_SLICE: - cbs_h264_free_slice(unit->content); - break; - } - av_freep(&unit->content); + H264RawSlice *slice = (H264RawSlice*)content; + av_buffer_unref(&slice->data_ref); + av_freep(&content); } -static void cbs_h265_free_nal_unit(CodedBitstreamUnit *unit) +static void cbs_h265_free_vps(void *unit, uint8_t *content) { - switch (unit->type) { - case HEVC_NAL_VPS: - av_freep(&((H265RawVPS*)unit->content)->extension_data.data); - break; - case HEVC_NAL_SPS: - av_freep(&((H265RawSPS*)unit->content)->extension_data.data); - break; - case HEVC_NAL_PPS: - av_freep(&((H265RawPPS*)unit->content)->extension_data.data); - break; - case HEVC_NAL_TRAIL_N: - case HEVC_NAL_TRAIL_R: - case HEVC_NAL_TSA_N: - case HEVC_NAL_TSA_R: - case HEVC_NAL_STSA_N: - case HEVC_NAL_STSA_R: - case HEVC_NAL_RADL_N: - case HEVC_NAL_RADL_R: - case HEVC_NAL_RASL_N: - case HEVC_NAL_RASL_R: - case HEVC_NAL_BLA_W_LP: - case HEVC_NAL_BLA_W_RADL: - case HEVC_NAL_BLA_N_LP: - case HEVC_NAL_IDR_W_RADL: - case HEVC_NAL_IDR_N_LP: - case HEVC_NAL_CRA_NUT: - av_freep(&((H265RawSlice*)unit->content)->data); - break; - } - av_freep(&unit->content); + H265RawVPS *vps = (H265RawVPS*)content; + av_buffer_unref(&vps->extension_data.data_ref); + av_freep(&content); +} + +static void cbs_h265_free_sps(void *unit, uint8_t *content) +{ + H265RawSPS *sps = (H265RawSPS*)content; + av_buffer_unref(&sps->extension_data.data_ref); + av_freep(&content); +} + +static void cbs_h265_free_pps(void *unit, uint8_t *content) +{ + H265RawPPS *pps = (H265RawPPS*)content; + av_buffer_unref(&pps->extension_data.data_ref); + av_freep(&content); +} + +static void cbs_h265_free_slice(void *unit, uint8_t *content) +{ + H265RawSlice *slice = (H265RawSlice*)content; + av_buffer_unref(&slice->data_ref); + av_freep(&content); } static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx, @@ -494,7 +481,7 @@ static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx, memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); err = ff_cbs_insert_unit_data(ctx, frag, -1, nal->type, - data, nal->size); + data, nal->size, NULL); if (err < 0) { av_freep(&data); return err; @@ -705,35 +692,32 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, { H264RawSPS *sps; - sps = av_mallocz(sizeof(*sps)); - if (!sps) - return AVERROR(ENOMEM); + err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*sps), NULL); + if (err < 0) + return err; + sps = unit->content; + err = cbs_h264_read_sps(ctx, &bc, sps); - if (err >= 0) - err = cbs_h264_replace_sps(ctx, sps); - if (err < 0) { - av_free(sps); + if (err < 0) return err; - } - unit->content = sps; + err = cbs_h264_replace_sps(ctx, sps); + if (err < 0) + return err; } break; case H264_NAL_SPS_EXT: { - H264RawSPSExtension *sps_ext; - - sps_ext = av_mallocz(sizeof(*sps_ext)); - if (!sps_ext) - return AVERROR(ENOMEM); - err = cbs_h264_read_sps_extension(ctx, &bc, sps_ext); - if (err < 0) { - av_free(sps_ext); + err = ff_cbs_alloc_unit_content(ctx, unit, + sizeof(H264RawSPSExtension), + NULL); + if (err < 0) return err; - } - unit->content = sps_ext; + err = cbs_h264_read_sps_extension(ctx, &bc, unit->content); + if (err < 0) + return err; } break; @@ -741,18 +725,18 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, { H264RawPPS *pps; - pps = av_mallocz(sizeof(*pps)); - if (!pps) - return AVERROR(ENOMEM); + err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*pps), NULL); + if (err < 0) + return err; + pps = unit->content; + err = cbs_h264_read_pps(ctx, &bc, pps); - if (err >= 0) - err = cbs_h264_replace_pps(ctx, pps); - if (err < 0) { - av_free(pps); + if (err < 0) return err; - } - unit->content = pps; + err = cbs_h264_replace_pps(ctx, pps); + if (err < 0) + return err; } break; @@ -763,14 +747,15 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, H264RawSlice *slice; int pos, len; - slice = av_mallocz(sizeof(*slice)); - if (!slice) - return AVERROR(ENOMEM); + err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*slice), + &cbs_h264_free_slice); + if (err < 0) + return err; + slice = unit->content; + err = cbs_h264_read_slice_header(ctx, &bc, &slice->header); - if (err < 0) { - av_free(slice); + if (err < 0) return err; - } pos = bitstream_tell(&bc); len = unit->data_size; @@ -783,54 +768,42 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, } slice->data_size = len - pos / 8; - slice->data = av_malloc(slice->data_size + - AV_INPUT_BUFFER_PADDING_SIZE); - if (!slice->data) { - av_free(slice); + slice->data_ref = av_buffer_alloc(slice->data_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!slice->data_ref) return AVERROR(ENOMEM); - } + slice->data = slice->data_ref->data; memcpy(slice->data, unit->data + pos / 8, slice->data_size); memset(slice->data + slice->data_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); slice->data_bit_start = pos % 8; - - unit->content = slice; } break; case H264_NAL_AUD: { - H264RawAUD *aud; - - aud = av_mallocz(sizeof(*aud)); - if (!aud) - return AVERROR(ENOMEM); - err = cbs_h264_read_aud(ctx, &bc, aud); - if (err < 0) { - av_free(aud); + err = ff_cbs_alloc_unit_content(ctx, unit, + sizeof(H264RawAUD), NULL); + if (err < 0) return err; - } - unit->content = aud; + err = cbs_h264_read_aud(ctx, &bc, unit->content); + if (err < 0) + return err; } break; case H264_NAL_SEI: { - H264RawSEI *sei; - - sei = av_mallocz(sizeof(*sei)); - if (!sei) - return AVERROR(ENOMEM); - err = cbs_h264_read_sei(ctx, &bc, sei); - if (err < 0) { - cbs_h264_free_sei(sei); - av_free(sei); + err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(H264RawSEI), + &cbs_h264_free_sei); + if (err < 0) return err; - } - unit->content = sei; + err = cbs_h264_read_sei(ctx, &bc, unit->content); + if (err < 0) + return err; } break; @@ -856,36 +829,38 @@ static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx, { H265RawVPS *vps; - vps = av_mallocz(sizeof(*vps)); - if (!vps) - return AVERROR(ENOMEM); + err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*vps), + &cbs_h265_free_vps); + if (err < 0) + return err; + vps = unit->content; + err = cbs_h265_read_vps(ctx, &bc, vps); - if (err >= 0) - err = cbs_h265_replace_vps(ctx, vps); - if (err < 0) { - av_free(vps); + if (err < 0) return err; - } - unit->content = vps; + err = cbs_h265_replace_vps(ctx, vps); + if (err < 0) + return err; } break; case HEVC_NAL_SPS: { H265RawSPS *sps; - sps = av_mallocz(sizeof(*sps)); - if (!sps) - return AVERROR(ENOMEM); + err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*sps), + &cbs_h265_free_sps); + if (err < 0) + return err; + sps = unit->content; + err = cbs_h265_read_sps(ctx, &bc, sps); - if (err >= 0) - err = cbs_h265_replace_sps(ctx, sps); - if (err < 0) { - av_free(sps); + if (err < 0) return err; - } - unit->content = sps; + err = cbs_h265_replace_sps(ctx, sps); + if (err < 0) + return err; } break; @@ -893,18 +868,19 @@ static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx, { H265RawPPS *pps; - pps = av_mallocz(sizeof(*pps)); - if (!pps) - return AVERROR(ENOMEM); + err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*pps), + &cbs_h265_free_pps); + if (err < 0) + return err; + pps = unit->content; + err = cbs_h265_read_pps(ctx, &bc, pps); - if (err >= 0) - err = cbs_h265_replace_pps(ctx, pps); - if (err < 0) { - av_free(pps); + if (err < 0) return err; - } - unit->content = pps; + err = cbs_h265_replace_pps(ctx, pps); + if (err < 0) + return err; } break; @@ -928,14 +904,15 @@ static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx, H265RawSlice *slice; int pos, len; - slice = av_mallocz(sizeof(*slice)); - if (!slice) - return AVERROR(ENOMEM); + err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*slice), + &cbs_h265_free_slice); + if (err < 0) + return err; + slice = unit->content; + err = cbs_h265_read_slice_segment_header(ctx, &bc, &slice->header); - if (err < 0) { - av_free(slice); + if (err < 0) return err; - } pos = bitstream_tell(&bc); len = unit->data_size; @@ -948,36 +925,29 @@ static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx, } slice->data_size = len - pos / 8; - slice->data = av_malloc(slice->data_size + - AV_INPUT_BUFFER_PADDING_SIZE); - if (!slice->data) { - av_free(slice); + slice->data_ref = av_buffer_alloc(slice->data_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!slice->data_ref) return AVERROR(ENOMEM); - } + slice->data = slice->data_ref->data; memcpy(slice->data, unit->data + pos / 8, slice->data_size); memset(slice->data + slice->data_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); slice->data_bit_start = pos % 8; - - unit->content = slice; } break; case HEVC_NAL_AUD: { - H265RawAUD *aud; - - aud = av_mallocz(sizeof(*aud)); - if (!aud) - return AVERROR(ENOMEM); - err = cbs_h265_read_aud(ctx, &bc, aud); - if (err < 0) { - av_free(aud); + err = ff_cbs_alloc_unit_content(ctx, unit, + sizeof(H265RawAUD), NULL); + if (err < 0) return err; - } - unit->content = aud; + err = cbs_h265_read_aud(ctx, &bc, unit->content); + if (err < 0) + return err; } break; @@ -1272,7 +1242,7 @@ static int cbs_h2645_write_nal_unit(CodedBitstreamContext *ctx, unit->data_size = (put_bits_count(&pbc) + 7) / 8; flush_put_bits(&pbc); - err = av_reallocp(&unit->data, unit->data_size); + err = ff_cbs_alloc_unit_data(ctx, unit, unit->data_size); if (err < 0) return err; @@ -1354,6 +1324,12 @@ static int cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx, if (err) return err; + frag->data_ref = av_buffer_create(data, dp, NULL, NULL, 0); + if (!frag->data_ref) { + av_freep(&data); + return AVERROR(ENOMEM); + } + frag->data = data; frag->data_size = dp; @@ -1402,7 +1378,6 @@ const CodedBitstreamType ff_cbs_type_h264 = { .write_unit = &cbs_h2645_write_nal_unit, .assemble_fragment = &cbs_h2645_assemble_fragment, - .free_unit = &cbs_h264_free_nal_unit, .close = &cbs_h264_close, }; @@ -1416,6 +1391,5 @@ const CodedBitstreamType ff_cbs_type_h265 = { .write_unit = &cbs_h2645_write_nal_unit, .assemble_fragment = &cbs_h2645_assemble_fragment, - .free_unit = &cbs_h265_free_nal_unit, .close = &cbs_h265_close, }; diff --git a/libavcodec/cbs_h265.h b/libavcodec/cbs_h265.h index 6ee07259333d4..0628748f18ff4 100644 --- a/libavcodec/cbs_h265.h +++ b/libavcodec/cbs_h265.h @@ -154,6 +154,7 @@ typedef struct H265RawVUI { typedef struct H265RawPSExtensionData { uint8_t *data; size_t bit_length; + AVBufferRef *data_ref; } H265RawPSExtensionData; typedef struct H265RawVPS { @@ -512,6 +513,7 @@ typedef struct H265RawSlice { uint8_t *data; size_t data_size; int data_bit_start; + AVBufferRef *data_ref; } H265RawSlice; diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index 1a1c22f0680c8..4c6f421d196d4 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -53,9 +53,6 @@ typedef struct CodedBitstreamType { int (*assemble_fragment)(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag); - // Free the content and data of a single unit. - void (*free_unit)(CodedBitstreamUnit *unit); - // Free the codec internal state. void (*close)(CodedBitstreamContext *ctx); } CodedBitstreamType; diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index 5956f393355a0..3db10c515297b 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -102,6 +102,21 @@ #undef nextbits +static void cbs_mpeg2_free_user_data(void *unit, uint8_t *content) +{ + MPEG2RawUserData *user = (MPEG2RawUserData*)content; + av_buffer_unref(&user->user_data_ref); + av_freep(&content); +} + +static void cbs_mpeg2_free_slice(void *unit, uint8_t *content) +{ + MPEG2RawSlice *slice = (MPEG2RawSlice*)content; + av_buffer_unref(&slice->header.extra_information_ref); + av_buffer_unref(&slice->data_ref); + av_freep(&content); +} + static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, int header) @@ -138,7 +153,7 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, memset(unit_data + unit_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); err = ff_cbs_insert_unit_data(ctx, frag, i, unit_type, - unit_data, unit_size); + unit_data, unit_size, NULL); if (err < 0) { av_freep(&unit_data); return err; @@ -168,25 +183,25 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, MPEG2RawSlice *slice; int pos, len; - slice = av_mallocz(sizeof(*slice)); - if (!slice) - return AVERROR(ENOMEM); + err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*slice), + &cbs_mpeg2_free_slice); + if (err < 0) + return err; + slice = unit->content; + err = cbs_mpeg2_read_slice_header(ctx, &bc, &slice->header); - if (err < 0) { - av_free(slice); + if (err < 0) return err; - } pos = bitstream_tell(&bc); len = unit->data_size; slice->data_size = len - pos / 8; - slice->data = av_malloc(slice->data_size + - AV_INPUT_BUFFER_PADDING_SIZE); - if (!slice->data) { - av_free(slice); + slice->data_ref = av_buffer_alloc(slice->data_size + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!slice->data_ref) return AVERROR(ENOMEM); - } + slice->data = slice->data_ref->data; memcpy(slice->data, unit->data + pos / 8, slice->data_size); @@ -194,30 +209,29 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, AV_INPUT_BUFFER_PADDING_SIZE); slice->data_bit_start = pos % 8; - unit->content = slice; - } else { switch (unit->type) { -#define START(start_code, type, func) \ +#define START(start_code, type, read_func, free_func) \ case start_code: \ { \ type *header; \ - header = av_mallocz(sizeof(*header)); \ - if (!header) \ - return AVERROR(ENOMEM); \ - err = cbs_mpeg2_read_ ## func(ctx, &bc, header); \ - if (err < 0) { \ - av_free(header); \ + err = ff_cbs_alloc_unit_content(ctx, unit, \ + sizeof(*header), free_func); \ + if (err < 0) \ + return err; \ + header = unit->content; \ + err = cbs_mpeg2_read_ ## read_func(ctx, &bc, header); \ + if (err < 0) \ return err; \ - } \ - unit->content = header; \ } \ break; - START(0x00, MPEG2RawPictureHeader, picture_header); - START(0xb2, MPEG2RawUserData, user_data); - START(0xb3, MPEG2RawSequenceHeader, sequence_header); - START(0xb5, MPEG2RawExtensionData, extension_data); - START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header); + START(0x00, MPEG2RawPictureHeader, picture_header, NULL); + START(0xb2, MPEG2RawUserData, user_data, + &cbs_mpeg2_free_user_data); + START(0xb3, MPEG2RawSequenceHeader, sequence_header, NULL); + START(0xb5, MPEG2RawExtensionData, extension_data, NULL); + START(0xb8, MPEG2RawGroupOfPicturesHeader, + group_of_pictures_header, NULL); #undef START default: av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown start code %02"PRIx32".\n", @@ -335,7 +349,7 @@ static int cbs_mpeg2_write_unit(CodedBitstreamContext *ctx, unit->data_size = (put_bits_count(&pbc) + 7) / 8; flush_put_bits(&pbc); - err = av_reallocp(&unit->data, unit->data_size); + err = ff_cbs_alloc_unit_data(ctx, unit, unit->data_size); if (err < 0) return err; @@ -355,9 +369,10 @@ static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx, for (i = 0; i < frag->nb_units; i++) size += 3 + frag->units[i].data_size; - data = av_malloc(size); - if (!data) + frag->data_ref = av_buffer_alloc(size); + if (!frag->data_ref) return AVERROR(ENOMEM); + data = frag->data_ref->data; dp = 0; for (i = 0; i < frag->nb_units; i++) { @@ -379,19 +394,6 @@ static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx, return 0; } -static void cbs_mpeg2_free_unit(CodedBitstreamUnit *unit) -{ - if (MPEG2_START_IS_SLICE(unit->type)) { - MPEG2RawSlice *slice = unit->content; - av_freep(&slice->data); - av_freep(&slice->header.extra_information); - } else if (unit->type == MPEG2_START_USER_DATA) { - MPEG2RawUserData *user = unit->content; - av_freep(&user->user_data); - } - av_freep(&unit->content); -} - static void cbs_mpeg2_close(CodedBitstreamContext *ctx) { CodedBitstreamMPEG2Context *priv = ctx->priv_data; @@ -409,6 +411,5 @@ const CodedBitstreamType ff_cbs_type_mpeg2 = { .write_unit = &cbs_mpeg2_write_unit, .assemble_fragment = &cbs_mpeg2_assemble_fragment, - .free_unit = &cbs_mpeg2_free_unit, .close = &cbs_mpeg2_close, }; diff --git a/libavcodec/cbs_mpeg2.h b/libavcodec/cbs_mpeg2.h index 0b6cb998dcd01..31e57ce36b816 100644 --- a/libavcodec/cbs_mpeg2.h +++ b/libavcodec/cbs_mpeg2.h @@ -22,6 +22,8 @@ #include #include +#include "libavutil/buffer.h" + enum { MPEG2_START_PICTURE = 0x00, @@ -76,6 +78,7 @@ typedef struct MPEG2RawUserData { uint8_t *user_data; size_t user_data_length; + AVBufferRef *user_data_ref; } MPEG2RawUserData; typedef struct MPEG2RawSequenceExtension { @@ -195,6 +198,7 @@ typedef struct MPEG2RawSliceHeader { size_t extra_information_length; uint8_t *extra_information; + AVBufferRef *extra_information_ref; } MPEG2RawSliceHeader; typedef struct MPEG2RawSlice { @@ -203,6 +207,7 @@ typedef struct MPEG2RawSlice { uint8_t *data; size_t data_size; int data_bit_start; + AVBufferRef *data_ref; } MPEG2RawSlice; diff --git a/libavcodec/cbs_mpeg2_syntax_template.c b/libavcodec/cbs_mpeg2_syntax_template.c index 4aa1eb3c062c2..b61fc8bc24e65 100644 --- a/libavcodec/cbs_mpeg2_syntax_template.c +++ b/libavcodec/cbs_mpeg2_syntax_template.c @@ -71,9 +71,10 @@ static int FUNC(user_data)(CodedBitstreamContext *ctx, RWContext *rw, av_assert0(k % 8 == 0); current->user_data_length = k /= 8; if (k > 0) { - current->user_data = av_malloc(k); - if (!current->user_data) + current->user_data_ref = av_buffer_alloc(k); + if (!current->user_data_ref) return AVERROR(ENOMEM); + current->user_data = current->user_data_ref->data; } #endif diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 2b579e9d3d9f4..6a1904e3150ed 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -270,7 +270,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) aud->primary_pic_type = j; err = ff_cbs_insert_unit_content(ctx->cbc, au, - 0, H264_NAL_AUD, aud); + 0, H264_NAL_AUD, aud, NULL); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n"); goto fail; @@ -314,8 +314,8 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) sei->nal_unit_header.nal_unit_type = H264_NAL_SEI; - err = ff_cbs_insert_unit_content(ctx->cbc, au, - sei_pos, H264_NAL_SEI, sei); + err = ff_cbs_insert_unit_content(ctx->cbc, au, sei_pos, + H264_NAL_SEI, sei, NULL); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to insert SEI.\n"); goto fail; diff --git a/libavcodec/h265_metadata_bsf.c b/libavcodec/h265_metadata_bsf.c index ffaf7f2873f26..cb73210c0d0e7 100644 --- a/libavcodec/h265_metadata_bsf.c +++ b/libavcodec/h265_metadata_bsf.c @@ -289,7 +289,7 @@ static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *out) aud->pic_type = pic_type; err = ff_cbs_insert_unit_content(ctx->cbc, au, - 0, HEVC_NAL_AUD, aud); + 0, HEVC_NAL_AUD, aud, NULL); if (err) { av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n"); goto fail; diff --git a/libavcodec/mpeg2_metadata_bsf.c b/libavcodec/mpeg2_metadata_bsf.c index 4923932864579..668d70ea2f8bd 100644 --- a/libavcodec/mpeg2_metadata_bsf.c +++ b/libavcodec/mpeg2_metadata_bsf.c @@ -167,7 +167,8 @@ static int mpeg2_metadata_update_fragment(AVBSFContext *bsf, err = ff_cbs_insert_unit_content(ctx->cbc, frag, se_pos + 1, MPEG2_START_EXTENSION, - &ctx->sequence_display_extension); + &ctx->sequence_display_extension, + NULL); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to insert new sequence " "display extension.\n"); diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index a9f8832e20f44..74a6417e0d9e3 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -133,7 +133,7 @@ static int vaapi_encode_h264_add_nal(AVCodecContext *avctx, int err; err = ff_cbs_insert_unit_content(priv->cbc, au, -1, - header->nal_unit_type, nal_unit); + header->nal_unit_type, nal_unit, NULL); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " "type = %d.\n", header->nal_unit_type); diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 52ac4a68753b2..9080aa82daf80 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -105,7 +105,7 @@ static int vaapi_encode_h265_add_nal(AVCodecContext *avctx, int err; err = ff_cbs_insert_unit_content(priv->cbc, au, -1, - header->nal_unit_type, nal_unit); + header->nal_unit_type, nal_unit, NULL); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " "type = %d.\n", header->nal_unit_type); diff --git a/libavcodec/vaapi_encode_mpeg2.c b/libavcodec/vaapi_encode_mpeg2.c index 39f1e4b5f2967..df26ed4c89f96 100644 --- a/libavcodec/vaapi_encode_mpeg2.c +++ b/libavcodec/vaapi_encode_mpeg2.c @@ -92,7 +92,7 @@ static int vaapi_encode_mpeg2_add_header(AVCodecContext *avctx, VAAPIEncodeMPEG2Context *priv = ctx->priv_data; int err; - err = ff_cbs_insert_unit_content(priv->cbc, frag, -1, type, header); + err = ff_cbs_insert_unit_content(priv->cbc, frag, -1, type, header, NULL); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to add header: " "type = %d.\n", type); From a2ca8ed903b435446031a8a0792ca535e6ee2913 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Feb 2018 15:37:34 +0000 Subject: [PATCH 1919/2557] cbs_h264: Add utility functions to insert/delete SEI messages --- libavcodec/cbs_h264.h | 19 +++++++++ libavcodec/cbs_h2645.c | 95 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h index 14ea69ae286df..8c17680bb549c 100644 --- a/libavcodec/cbs_h264.h +++ b/libavcodec/cbs_h264.h @@ -22,6 +22,7 @@ #include #include +#include "cbs.h" #include "cbs_h2645.h" #include "h264.h" @@ -428,4 +429,22 @@ typedef struct CodedBitstreamH264Context { } CodedBitstreamH264Context; +/** + * Add an SEI message to an access unit. + */ +int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx, + CodedBitstreamFragment *access_unit, + const H264RawSEIPayload *payload); + +/** + * Delete an SEI message from an access unit. + * + * Deletes from nal_unit, which must be an SEI NAL unit. If this is the + * last message in nal_unit, also deletes it from access_unit. + */ +int ff_cbs_h264_delete_sei_message(CodedBitstreamContext *ctx, + CodedBitstreamFragment *access_unit, + CodedBitstreamUnit *nal_unit, + int position); + #endif /* AVCODEC_CBS_H264_H */ diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 5b23d6104be05..25bd33f162618 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -1393,3 +1393,98 @@ const CodedBitstreamType ff_cbs_type_h265 = { .close = &cbs_h265_close, }; + +int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx, + CodedBitstreamFragment *au, + const H264RawSEIPayload *payload) +{ + H264RawSEI *sei; + CodedBitstreamUnit *nal = NULL; + int err, i; + + // Find an existing SEI NAL unit to add to. + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_SEI) { + nal = &au->units[i]; + break; + } + } + if (nal) { + sei = nal->content; + + } else { + // Need to make a new SEI NAL unit. Insert it before the first + // slice data NAL unit; if no slice data, add at the end. + AVBufferRef *sei_ref; + + sei = av_mallocz(sizeof(*sei)); + if (!sei) + return AVERROR(ENOMEM); + + sei->nal_unit_header.nal_unit_type = H264_NAL_SEI; + sei->nal_unit_header.nal_ref_idc = 0; + + sei_ref = av_buffer_create((uint8_t*)sei, sizeof(*sei), + &cbs_h264_free_sei, ctx, 0); + if (!sei_ref) { + av_freep(&sei); + return AVERROR(ENOMEM); + } + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_SLICE || + au->units[i].type == H264_NAL_IDR_SLICE) + break; + } + + err = ff_cbs_insert_unit_content(ctx, au, i, H264_NAL_SEI, + sei, sei_ref); + av_buffer_unref(&sei_ref); + if (err < 0) + return err; + } + + if (sei->payload_count >= H264_MAX_SEI_PAYLOADS) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many payloads in " + "SEI NAL unit.\n"); + return AVERROR(EINVAL); + } + + memcpy(&sei->payload[sei->payload_count], payload, sizeof(*payload)); + ++sei->payload_count; + + return 0; +} + +int ff_cbs_h264_delete_sei_message(CodedBitstreamContext *ctx, + CodedBitstreamFragment *au, + CodedBitstreamUnit *nal, + int position) +{ + H264RawSEI *sei = nal->content; + + av_assert0(nal->type == H264_NAL_SEI); + av_assert0(position >= 0 && position < sei->payload_count); + + if (position == 0 && sei->payload_count == 1) { + // Deleting NAL unit entirely. + int i; + + for (i = 0; i < au->nb_units; i++) { + if (&au->units[i] == nal) + break; + } + av_assert0(i < au->nb_units && "NAL unit not in access unit."); + + return ff_cbs_delete_unit(ctx, au, i); + } else { + cbs_h264_free_sei_payload(&sei->payload[position]); + + --sei->payload_count; + memmove(sei->payload + position, + sei->payload + position + 1, + (sei->payload_count - position) * sizeof(*sei->payload)); + + return 0; + } +} From 69062d0f9b6aef5d9d9b8c9c9b5cfb23037caddb Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Feb 2018 15:38:02 +0000 Subject: [PATCH 1920/2557] h264_metadata: Use common SEI addition function --- libavcodec/h264_metadata_bsf.c | 72 +++++++++------------------------- 1 file changed, 19 insertions(+), 53 deletions(-) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 6a1904e3150ed..356daef3ec6a2 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -208,7 +208,6 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) AVPacket *in = NULL; CodedBitstreamFragment *au = &ctx->access_unit; int err, i, j, has_sps; - char *sei_udu_string = NULL; err = ff_bsf_get_packet(bsf, &in); if (err < 0) @@ -290,42 +289,11 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) // Only insert the SEI in access units containing SPSs. if (has_sps && ctx->sei_user_data) { - H264RawSEI *sei; - H264RawSEIPayload *payload; - H264RawSEIUserDataUnregistered *udu; - int sei_pos, sei_new; - - for (i = 0; i < au->nb_units; i++) { - if (au->units[i].type == H264_NAL_SEI || - au->units[i].type == H264_NAL_SLICE || - au->units[i].type == H264_NAL_IDR_SLICE) - break; - } - sei_pos = i; - - if (sei_pos < au->nb_units && - au->units[sei_pos].type == H264_NAL_SEI) { - sei_new = 0; - sei = au->units[sei_pos].content; - } else { - sei_new = 1; - sei = &ctx->sei_nal; - memset(sei, 0, sizeof(*sei)); - - sei->nal_unit_header.nal_unit_type = H264_NAL_SEI; - - err = ff_cbs_insert_unit_content(ctx->cbc, au, sei_pos, - H264_NAL_SEI, sei, NULL); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to insert SEI.\n"); - goto fail; - } - } - - payload = &sei->payload[sei->payload_count]; - - payload->payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED; - udu = &payload->payload.user_data_unregistered; + H264RawSEIPayload payload = { + .payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED, + }; + H264RawSEIUserDataUnregistered *udu = + &payload.payload.user_data_unregistered; for (i = j = 0; j < 32 && ctx->sei_user_data[i]; i++) { int c, v; @@ -345,21 +313,25 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) ++j; } if (j == 32 && ctx->sei_user_data[i] == '+') { - sei_udu_string = av_strdup(ctx->sei_user_data + i + 1); - if (!sei_udu_string) { + size_t len = strlen(ctx->sei_user_data + i + 1); + + udu->data_ref = av_buffer_alloc(len + 1); + if (!udu->data_ref) { err = AVERROR(ENOMEM); - goto sei_fail; + goto fail; } - udu->data = sei_udu_string; - udu->data_length = strlen(sei_udu_string); + udu->data = udu->data_ref->data; + udu->data_length = len + 1; + memcpy(udu->data, ctx->sei_user_data + i + 1, len + 1); - payload->payload_size = 16 + udu->data_length; + payload.payload_size = 16 + udu->data_length; - if (!sei_new) { - // This will be freed by the existing internal - // reference in fragment_uninit(). - sei_udu_string = NULL; + err = ff_cbs_h264_add_sei_message(ctx->cbc, au, &payload); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI " + "message to access unit.\n"); + goto fail; } } else { @@ -367,12 +339,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) av_log(bsf, AV_LOG_ERROR, "Invalid user data: " "must be \"UUID+string\".\n"); err = AVERROR(EINVAL); - sei_fail: - memset(payload, 0, sizeof(*payload)); - goto fail; } - - ++sei->payload_count; } err = ff_cbs_write_packet(ctx->cbc, out, au); @@ -388,7 +355,6 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) err = 0; fail: ff_cbs_fragment_uninit(ctx->cbc, au); - av_freep(&sei_udu_string); av_packet_free(&in); From 78fa0b9033c0834c049e2aedf71a8c613fed87ab Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Feb 2018 15:41:07 +0000 Subject: [PATCH 1921/2557] h264_metadata: Always add the SEI user data to the first access unit This should be added even if the first access unit does not contain parameter sets. --- libavcodec/h264_metadata_bsf.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 356daef3ec6a2..d8d5487c99de3 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -62,6 +62,7 @@ typedef struct H264MetadataContext { int crop_bottom; const char *sei_user_data; + int sei_first_au; } H264MetadataContext; @@ -287,14 +288,17 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) } } - // Only insert the SEI in access units containing SPSs. - if (has_sps && ctx->sei_user_data) { + // Only insert the SEI in access units containing SPSs, and also + // unconditionally in the first access unit we ever see. + if (ctx->sei_user_data && (has_sps || !ctx->sei_first_au)) { H264RawSEIPayload payload = { .payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED, }; H264RawSEIUserDataUnregistered *udu = &payload.payload.user_data_unregistered; + ctx->sei_first_au = 1; + for (i = j = 0; j < 32 && ctx->sei_user_data[i]; i++) { int c, v; c = ctx->sei_user_data[i]; From 7157d959264f3729da463725c6faa580d9394d19 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Feb 2018 00:57:46 +0000 Subject: [PATCH 1922/2557] cbs_h264: Move slice_group_id array out of PPS structure It's very large, and is only used in some FMO streams. --- libavcodec/cbs_h264.h | 4 +++- libavcodec/cbs_h2645.c | 10 +++++++++- libavcodec/cbs_h264_syntax_template.c | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h index 8c17680bb549c..a59b7be1beb43 100644 --- a/libavcodec/cbs_h264.h +++ b/libavcodec/cbs_h264.h @@ -195,7 +195,9 @@ typedef struct H264RawPPS { uint8_t slice_group_change_direction_flag; uint16_t slice_group_change_rate_minus1; uint16_t pic_size_in_map_units_minus1; - uint8_t slice_group_id[H264_MAX_MB_PIC_SIZE]; + + uint8_t *slice_group_id; + AVBufferRef *slice_group_id_ref; uint8_t num_ref_idx_l0_default_active_minus1; uint8_t num_ref_idx_l1_default_active_minus1; diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 25bd33f162618..ebc02361d02d6 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -394,6 +394,13 @@ static int cbs_h2645_read_more_rbsp_data(BitstreamContext *bc) #undef allocate +static void cbs_h264_free_pps(void *unit, uint8_t *content) +{ + H264RawPPS *pps = (H264RawPPS*)content; + av_buffer_unref(&pps->slice_group_id_ref); + av_freep(&content); +} + static void cbs_h264_free_sei_payload(H264RawSEIPayload *payload) { switch (payload->payload_type) { @@ -725,7 +732,8 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, { H264RawPPS *pps; - err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*pps), NULL); + err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*pps), + &cbs_h264_free_pps); if (err < 0) return err; pps = unit->content; diff --git a/libavcodec/cbs_h264_syntax_template.c b/libavcodec/cbs_h264_syntax_template.c index c2fd546822f1e..29e9735987402 100644 --- a/libavcodec/cbs_h264_syntax_template.c +++ b/libavcodec/cbs_h264_syntax_template.c @@ -404,6 +404,9 @@ static int FUNC(pps)(CodedBitstreamContext *ctx, RWContext *rw, ue(slice_group_change_rate_minus1, 0, pic_size - 1); } else if (current->slice_group_map_type == 6) { ue(pic_size_in_map_units_minus1, pic_size - 1, pic_size - 1); + + allocate(current->slice_group_id, + current->pic_size_in_map_units_minus1 + 1); for (i = 0; i <= current->pic_size_in_map_units_minus1; i++) u(av_log2(2 * current->num_slice_groups_minus1 + 1), slice_group_id[i], 0, current->num_slice_groups_minus1); From eccc03c8fbc603a0a3257df66f0705f74fe2581a Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Feb 2018 17:33:15 +0000 Subject: [PATCH 1923/2557] cbs_h264: Add support for filler NAL units --- libavcodec/cbs_h264.h | 6 ++++++ libavcodec/cbs_h2645.c | 21 +++++++++++++++++++ libavcodec/cbs_h264_syntax_template.c | 29 +++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h index a59b7be1beb43..5a7dc27698c70 100644 --- a/libavcodec/cbs_h264.h +++ b/libavcodec/cbs_h264.h @@ -408,6 +408,12 @@ typedef struct H264RawSlice { AVBufferRef *data_ref; } H264RawSlice; +typedef struct H264RawFiller { + H264RawNALUnitHeader nal_unit_header; + + uint32_t filler_size; +} H264RawFiller; + typedef struct CodedBitstreamH264Context { // Reader/writer context in common with the H.265 implementation. diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index ebc02361d02d6..d6131a13e5ea8 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -815,6 +815,19 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx, } break; + case H264_NAL_FILLER_DATA: + { + err = ff_cbs_alloc_unit_content(ctx, unit, + sizeof(H264RawFiller), NULL); + if (err < 0) + return err; + + err = cbs_h264_read_filler(ctx, &bc, unit->content); + if (err < 0) + return err; + } + break; + default: return AVERROR(ENOSYS); } @@ -1070,6 +1083,14 @@ static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx, } break; + case H264_NAL_FILLER_DATA: + { + err = cbs_h264_write_filler(ctx, pbc, unit->content); + if (err < 0) + return err; + } + break; + default: av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for " "NAL unit type %"PRIu32".\n", unit->type); diff --git a/libavcodec/cbs_h264_syntax_template.c b/libavcodec/cbs_h264_syntax_template.c index 29e9735987402..1aa7888584eb3 100644 --- a/libavcodec/cbs_h264_syntax_template.c +++ b/libavcodec/cbs_h264_syntax_template.c @@ -1247,3 +1247,32 @@ static int FUNC(slice_header)(CodedBitstreamContext *ctx, RWContext *rw, return 0; } + +static int FUNC(filler)(CodedBitstreamContext *ctx, RWContext *rw, + H264RawFiller *current) +{ + av_unused int ff_byte = 0xff; + int err; + + HEADER("Filler Data"); + + CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, + 1 << H264_NAL_FILLER_DATA)); + +#ifdef READ + while (bitstream_peek(rw, 8) == 0xff) { + xu(8, ff_byte, ff_byte, 0xff, 0xff); + ++current->filler_size; + } +#else + { + uint32_t i; + for (i = 0; i < current->filler_size; i++) + xu(8, ff_byte, ff_byte, 0xff, 0xff); + } +#endif + + CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); + + return 0; +} From 6d5a6dde5301c81e221a37b3f39bb03149492b98 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 11 Dec 2017 00:30:54 +0000 Subject: [PATCH 1924/2557] h264_metadata: Add option to delete filler data Deletes both filler NAL units and filler SEI messages. (Annex B zero_bytes between NAL units are already discarded by the read/write process.) --- libavcodec/h264_metadata_bsf.c | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index d8d5487c99de3..7b51e8ee8bb66 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -63,6 +63,8 @@ typedef struct H264MetadataContext { const char *sei_user_data; int sei_first_au; + + int delete_filler; } H264MetadataContext; @@ -346,6 +348,44 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) } } + if (ctx->delete_filler) { + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_FILLER_DATA) { + // Filler NAL units. + err = ff_cbs_delete_unit(ctx->cbc, au, i); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to delete " + "filler NAL.\n"); + goto fail; + } + --i; + continue; + } + + if (au->units[i].type == H264_NAL_SEI) { + // Filler SEI messages. + H264RawSEI *sei = au->units[i].content; + + for (j = 0; j < sei->payload_count; j++) { + if (sei->payload[j].payload_type == + H264_SEI_TYPE_FILLER_PAYLOAD) { + err = ff_cbs_h264_delete_sei_message(ctx->cbc, au, + &au->units[i], j); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to delete " + "filler SEI message.\n"); + goto fail; + } + // Renumbering might have happened, start again at + // the same NAL unit position. + --i; + break; + } + } + } + } + } + err = ff_cbs_write_packet(ctx->cbc, out, au); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); @@ -465,6 +505,9 @@ static const AVOption h264_metadata_options[] = { { "sei_user_data", "Insert SEI user data (UUID+string)", OFFSET(sei_user_data), AV_OPT_TYPE_STRING, { .str = NULL } }, + { "delete_filler", "Delete all filler (both NAL and SEI)", + OFFSET(delete_filler), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1 }, + { NULL } }; From d09368a40844e62d952c77cc0fa4f6992afb924e Mon Sep 17 00:00:00 2001 From: Lou Logan Date: Wed, 21 Feb 2018 12:32:23 -0900 Subject: [PATCH 1925/2557] doc/ffmpeg: document -dn option Also mention -map in the -vn, -an, and -sn options. Fixes #7036. Signed-off-by: Lou Logan --- doc/ffmpeg.texi | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 25a0707dc1b18..86c6fd864cd76 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -413,6 +413,10 @@ they do not conflict with the standard, as in: ffmpeg -i myfile.avi -target vcd -bf 2 /tmp/vcd.mpg @end example +@item -dn (@emph{output}) +Disable data recording. For full manual control see the @code{-map} +option. + @item -dframes @var{number} (@emph{output}) Set the number of data frames to output. This is an obsolete alias for @code{-frames:d}, which you should use instead. @@ -571,7 +575,8 @@ stored at container level, but not the aspect ratio stored in encoded frames, if it exists. @item -vn (@emph{output}) -Disable video recording. +Disable video recording. For full manual control see the @code{-map} +option. @item -vcodec @var{codec} (@emph{output}) Set the video codec. This is an alias for @code{-codec:v}. @@ -886,7 +891,8 @@ default to the number of input audio channels. For input streams this option only makes sense for audio grabbing devices and raw demuxers and is mapped to the corresponding demuxer options. @item -an (@emph{output}) -Disable audio recording. +Disable audio recording. For full manual control see the @code{-map} +option. @item -acodec @var{codec} (@emph{input/output}) Set the audio codec. This is an alias for @code{-codec:a}. @item -sample_fmt[:@var{stream_specifier}] @var{sample_fmt} (@emph{output,per-stream}) @@ -921,7 +927,8 @@ stereo but not 6 channels as 5.1. The default is to always try to guess. Use @item -scodec @var{codec} (@emph{input/output}) Set the subtitle codec. This is an alias for @code{-codec:s}. @item -sn (@emph{output}) -Disable subtitle recording. +Disable subtitle recording. For full manual control see the @code{-map} +option. @item -sbsf @var{bitstream_filter} Deprecated, see -bsf @end table From 41317da325921d39834b65d8552a2ebb2f3e802b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Mon, 19 Feb 2018 18:42:25 +0100 Subject: [PATCH 1926/2557] Add -vf scale example for making pixels square This is a common use case. --- doc/filters.texi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index bd93e0ab84f39..8a9b78d778b98 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -13721,6 +13721,19 @@ keeping the same aspect ratio as the input: @example scale=w='min(500\, iw*3/2):h=-1' @end example + +@item +Make pixels square by combining scale and setsar: +@example +scale='trunc(ih*dar):ih',setsar=1/1 +@end example + +@item +Make pixels square by combining scale and setsar, +making sure the resulting resolution is even (required by some codecs): +@example +scale='trunc(ih*dar/2)*2:trunc(ih/2)*2',setsar=1/1 +@end example @end itemize @subsection Commands From 5ac3a309fddde79db1f70269fbcbd0ba4d94d30e Mon Sep 17 00:00:00 2001 From: Felix Matouschek Date: Tue, 20 Feb 2018 09:41:46 +0100 Subject: [PATCH 1927/2557] avdevice: add android_camera indev This commit adds an indev for Android devices on API level 24+ which uses the Android NDK Camera2 API to capture video from builtin cameras Signed-off-by: Felix Matouschek Signed-off-by: Michael Niedermayer --- Changelog | 1 + MAINTAINERS | 1 + configure | 6 + doc/indevs.texi | 40 ++ libavdevice/Makefile | 1 + libavdevice/alldevices.c | 1 + libavdevice/android_camera.c | 871 +++++++++++++++++++++++++++++++++++ libavdevice/version.h | 2 +- 8 files changed, 922 insertions(+), 1 deletion(-) create mode 100644 libavdevice/android_camera.c diff --git a/Changelog b/Changelog index 2acdbbea300b0..56dedd1aea0a7 100644 --- a/Changelog +++ b/Changelog @@ -39,6 +39,7 @@ version : - Removed the ffmenc and ffmdec muxer and demuxer - VideoToolbox HEVC encoder and hwaccel - VAAPI-accelerated ProcAmp (color balance), denoise and sharpness filters +- Add android_camera indev version 3.4: diff --git a/MAINTAINERS b/MAINTAINERS index b691bd56ec68c..bf1299bdbfa82 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -281,6 +281,7 @@ libavdevice avfoundation.m Thilo Borgmann + android_camera.c Felix Matouschek decklink* Marton Balint dshow.c Roger Pack (CC rogerdpack@gmail.com) fbdev_enc.c Lukasz Marek diff --git a/configure b/configure index 013308cfa4315..fa5c530abe742 100755 --- a/configure +++ b/configure @@ -3081,6 +3081,8 @@ xmv_demuxer_select="riffdec" xwma_demuxer_select="riffdec" # indevs / outdevs +android_camera_indev_deps="android camera2ndk mediandk pthreads" +android_camera_indev_extralibs="-landroid -lcamera2ndk -lmediandk" alsa_indev_deps="alsa" alsa_outdev_deps="alsa" avfoundation_indev_deps="avfoundation corevideo coremedia pthreads" @@ -5756,6 +5758,10 @@ check_lib shell32 "windows.h shellapi.h" CommandLineToArgvW -lshell32 check_lib wincrypt "windows.h wincrypt.h" CryptGenRandom -ladvapi32 check_lib psapi "windows.h psapi.h" GetProcessMemoryInfo -lpsapi +check_lib android android/native_window.h ANativeWindow_acquire -landroid +check_lib mediandk "stdint.h media/NdkImage.h" AImage_delete -lmediandk +check_lib camera2ndk "stdbool.h stdint.h camera/NdkCameraManager.h" ACameraManager_create -lcamera2ndk + enabled appkit && check_apple_framework AppKit enabled audiotoolbox && check_apple_framework AudioToolbox enabled avfoundation && check_apple_framework AVFoundation diff --git a/doc/indevs.texi b/doc/indevs.texi index 0bc8e6a9b1bea..6951940a93a44 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -63,6 +63,46 @@ Set the number of channels. Default is 2. @end table +@section android_camera + +Android camera input device. + +This input devices uses the Android Camera2 NDK API which is +available on devices with API level 24+. The availability of +android_camera is autodetected during configuration. + +This device allows capturing from all cameras on an Android device, +which are integrated into the Camera2 NDK API. + +The available cameras are enumerated internally and can be selected +with the @var{camera_index} parameter. The input file string is +discarded. + +Generally the back facing camera has index 0 while the front facing +camera has index 1. + +@subsection Options + +@table @option + +@item video_size +Set the video size given as a string such as 640x480 or hd720. +Falls back to the first available configuration reported by +Android if requested video size is not available or by default. + +@item framerate +Set the video framerate. +Falls back to the first available configuration reported by +Android if requested framerate is not available or by default (-1). + +@item camera_index +Set the index of the camera to use. Default is 0. + +@item input_queue_size +Set the maximum number of frames to buffer. Default is 5. + +@end table + @section avfoundation AVFoundation input device. diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 8228d6214793f..f11a6f2a860b1 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -14,6 +14,7 @@ OBJS-$(CONFIG_SHARED) += reverse.o # input/output devices OBJS-$(CONFIG_ALSA_INDEV) += alsa_dec.o alsa.o timefilter.o OBJS-$(CONFIG_ALSA_OUTDEV) += alsa_enc.o alsa.o +OBJS-$(CONFIG_ANDROID_CAMERA_INDEV) += android_camera.o OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation.o OBJS-$(CONFIG_BKTR_INDEV) += bktr.o OBJS-$(CONFIG_CACA_OUTDEV) += caca.o diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index 8b58aa19e5d6b..4c89649b97268 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -29,6 +29,7 @@ /* devices */ extern AVInputFormat ff_alsa_demuxer; extern AVOutputFormat ff_alsa_muxer; +extern AVInputFormat ff_android_camera_demuxer; extern AVInputFormat ff_avfoundation_demuxer; extern AVInputFormat ff_bktr_demuxer; extern AVOutputFormat ff_caca_muxer; diff --git a/libavdevice/android_camera.c b/libavdevice/android_camera.c new file mode 100644 index 0000000000000..ff6caaa55e3d9 --- /dev/null +++ b/libavdevice/android_camera.c @@ -0,0 +1,871 @@ +/* + * Android camera input device + * + * Copyright (C) 2017 Felix Matouschek + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "libavformat/avformat.h" +#include "libavformat/internal.h" +#include "libavutil/avstring.h" +#include "libavutil/display.h" +#include "libavutil/imgutils.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "libavutil/pixfmt.h" +#include "libavutil/threadmessage.h" +#include "libavutil/time.h" + +#include "version.h" + +/* This image format is available on all Android devices + * supporting the Camera2 API */ +#define IMAGE_FORMAT_ANDROID AIMAGE_FORMAT_YUV_420_888 + +#define MAX_BUF_COUNT 2 +#define VIDEO_STREAM_INDEX 0 +#define VIDEO_TIMEBASE_ANDROID 1000000000 + +#define RETURN_CASE(x) case x: return AV_STRINGIFY(x); +#define RETURN_DEFAULT(x) default: return AV_STRINGIFY(x); + +typedef struct AndroidCameraCtx { + const AVClass *class; + + int requested_width; + int requested_height; + AVRational framerate; + int camera_index; + int input_queue_size; + + uint8_t lens_facing; + int32_t sensor_orientation; + int width; + int height; + int32_t framerate_range[2]; + int image_format; + + ACameraManager *camera_mgr; + char *camera_id; + ACameraMetadata *camera_metadata; + ACameraDevice *camera_dev; + ACameraDevice_StateCallbacks camera_state_callbacks; + AImageReader *image_reader; + AImageReader_ImageListener image_listener; + ANativeWindow *image_reader_window; + ACaptureSessionOutputContainer *capture_session_output_container; + ACaptureSessionOutput *capture_session_output; + ACameraOutputTarget *camera_output_target; + ACaptureRequest *capture_request; + ACameraCaptureSession_stateCallbacks capture_session_state_callbacks; + ACameraCaptureSession *capture_session; + + AVThreadMessageQueue *input_queue; + atomic_int exit; + atomic_int got_image_format; +} AndroidCameraCtx; + +static const char *camera_status_string(camera_status_t val) +{ + switch(val) { + RETURN_CASE(ACAMERA_OK) + RETURN_CASE(ACAMERA_ERROR_UNKNOWN) + RETURN_CASE(ACAMERA_ERROR_INVALID_PARAMETER) + RETURN_CASE(ACAMERA_ERROR_CAMERA_DISCONNECTED) + RETURN_CASE(ACAMERA_ERROR_NOT_ENOUGH_MEMORY) + RETURN_CASE(ACAMERA_ERROR_METADATA_NOT_FOUND) + RETURN_CASE(ACAMERA_ERROR_CAMERA_DEVICE) + RETURN_CASE(ACAMERA_ERROR_CAMERA_SERVICE) + RETURN_CASE(ACAMERA_ERROR_SESSION_CLOSED) + RETURN_CASE(ACAMERA_ERROR_INVALID_OPERATION) + RETURN_CASE(ACAMERA_ERROR_STREAM_CONFIGURE_FAIL) + RETURN_CASE(ACAMERA_ERROR_CAMERA_IN_USE) + RETURN_CASE(ACAMERA_ERROR_MAX_CAMERA_IN_USE) + RETURN_CASE(ACAMERA_ERROR_CAMERA_DISABLED) + RETURN_CASE(ACAMERA_ERROR_PERMISSION_DENIED) + RETURN_DEFAULT(ACAMERA_ERROR_UNKNOWN) + } +} + +static const char *media_status_string(media_status_t val) +{ + switch(val) { + RETURN_CASE(AMEDIA_OK) + RETURN_CASE(AMEDIA_ERROR_UNKNOWN) + RETURN_CASE(AMEDIA_ERROR_MALFORMED) + RETURN_CASE(AMEDIA_ERROR_UNSUPPORTED) + RETURN_CASE(AMEDIA_ERROR_INVALID_OBJECT) + RETURN_CASE(AMEDIA_ERROR_INVALID_PARAMETER) + RETURN_CASE(AMEDIA_ERROR_INVALID_OPERATION) + RETURN_CASE(AMEDIA_DRM_NOT_PROVISIONED) + RETURN_CASE(AMEDIA_DRM_RESOURCE_BUSY) + RETURN_CASE(AMEDIA_DRM_DEVICE_REVOKED) + RETURN_CASE(AMEDIA_DRM_SHORT_BUFFER) + RETURN_CASE(AMEDIA_DRM_SESSION_NOT_OPENED) + RETURN_CASE(AMEDIA_DRM_TAMPER_DETECTED) + RETURN_CASE(AMEDIA_DRM_VERIFY_FAILED) + RETURN_CASE(AMEDIA_DRM_NEED_KEY) + RETURN_CASE(AMEDIA_DRM_LICENSE_EXPIRED) + RETURN_CASE(AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE) + RETURN_CASE(AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED) + RETURN_CASE(AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE) + RETURN_CASE(AMEDIA_IMGREADER_CANNOT_UNLOCK_IMAGE) + RETURN_CASE(AMEDIA_IMGREADER_IMAGE_NOT_LOCKED) + RETURN_DEFAULT(AMEDIA_ERROR_UNKNOWN) + } +} + +static const char *error_state_callback_string(int val) +{ + switch(val) { + RETURN_CASE(ERROR_CAMERA_IN_USE) + RETURN_CASE(ERROR_MAX_CAMERAS_IN_USE) + RETURN_CASE(ERROR_CAMERA_DISABLED) + RETURN_CASE(ERROR_CAMERA_DEVICE) + RETURN_CASE(ERROR_CAMERA_SERVICE) + default: + return "ERROR_CAMERA_UNKNOWN"; + } +} + +static void camera_dev_disconnected(void *context, ACameraDevice *device) +{ + AVFormatContext *avctx = context; + AndroidCameraCtx *ctx = avctx->priv_data; + atomic_store(&ctx->exit, 1); + av_log(avctx, AV_LOG_ERROR, "Camera with id %s disconnected.\n", + ACameraDevice_getId(device)); +} + +static void camera_dev_error(void *context, ACameraDevice *device, int error) +{ + AVFormatContext *avctx = context; + AndroidCameraCtx *ctx = avctx->priv_data; + atomic_store(&ctx->exit, 1); + av_log(avctx, AV_LOG_ERROR, "Error %s on camera with id %s.\n", + error_state_callback_string(error), ACameraDevice_getId(device)); +} + +static int open_camera(AVFormatContext *avctx) +{ + AndroidCameraCtx *ctx = avctx->priv_data; + camera_status_t ret; + ACameraIdList *camera_ids; + + ret = ACameraManager_getCameraIdList(ctx->camera_mgr, &camera_ids); + if (ret != ACAMERA_OK) { + av_log(avctx, AV_LOG_ERROR, "Failed to get camera id list, error: %s.\n", + camera_status_string(ret)); + return AVERROR_EXTERNAL; + } + + if (ctx->camera_index < camera_ids->numCameras) { + ctx->camera_id = av_strdup(camera_ids->cameraIds[ctx->camera_index]); + if (!ctx->camera_id) { + av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory for camera_id.\n"); + return AVERROR(ENOMEM); + } + } else { + av_log(avctx, AV_LOG_ERROR, "No camera with index %d available.\n", + ctx->camera_index); + return AVERROR(ENXIO); + } + + ACameraManager_deleteCameraIdList(camera_ids); + + ret = ACameraManager_getCameraCharacteristics(ctx->camera_mgr, + ctx->camera_id, &ctx->camera_metadata); + if (ret != ACAMERA_OK) { + av_log(avctx, AV_LOG_ERROR, "Failed to get metadata for camera with id %s, error: %s.\n", + ctx->camera_id, camera_status_string(ret)); + return AVERROR_EXTERNAL; + } + + ctx->camera_state_callbacks.context = avctx; + ctx->camera_state_callbacks.onDisconnected = camera_dev_disconnected; + ctx->camera_state_callbacks.onError = camera_dev_error; + + ret = ACameraManager_openCamera(ctx->camera_mgr, ctx->camera_id, + &ctx->camera_state_callbacks, &ctx->camera_dev); + if (ret != ACAMERA_OK) { + av_log(avctx, AV_LOG_ERROR, "Failed to open camera with id %s, error: %s.\n", + ctx->camera_id, camera_status_string(ret)); + return AVERROR_EXTERNAL; + } + + return 0; +} + +static void get_sensor_orientation(AVFormatContext *avctx) +{ + AndroidCameraCtx *ctx = avctx->priv_data; + ACameraMetadata_const_entry lens_facing; + ACameraMetadata_const_entry sensor_orientation; + + ACameraMetadata_getConstEntry(ctx->camera_metadata, + ACAMERA_LENS_FACING, &lens_facing); + ACameraMetadata_getConstEntry(ctx->camera_metadata, + ACAMERA_SENSOR_ORIENTATION, &sensor_orientation); + + ctx->lens_facing = lens_facing.data.u8[0]; + ctx->sensor_orientation = sensor_orientation.data.i32[0]; +} + +static void match_video_size(AVFormatContext *avctx) +{ + AndroidCameraCtx *ctx = avctx->priv_data; + ACameraMetadata_const_entry available_configs; + int found = 0; + + ACameraMetadata_getConstEntry(ctx->camera_metadata, + ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, + &available_configs); + + for (int i = 0; i < available_configs.count; i++) { + int32_t input = available_configs.data.i32[i * 4 + 3]; + int32_t format = available_configs.data.i32[i * 4 + 0]; + + if (input) { + continue; + } + + if (format == IMAGE_FORMAT_ANDROID) { + int32_t width = available_configs.data.i32[i * 4 + 1]; + int32_t height = available_configs.data.i32[i * 4 + 2]; + + //Same ratio + if ((ctx->requested_width == width && ctx->requested_height == height) || + (ctx->requested_width == height && ctx->requested_height == width)) { + ctx->width = width; + ctx->height = height; + found = 1; + break; + } + } + } + + if (!found || ctx->width == 0 || ctx->height == 0) { + ctx->width = available_configs.data.i32[1]; + ctx->height = available_configs.data.i32[2]; + + av_log(avctx, AV_LOG_WARNING, + "Requested video_size %dx%d not available, falling back to %dx%d\n", + ctx->requested_width, ctx->requested_height, ctx->width, ctx->height); + } + + return; +} + +static void match_framerate(AVFormatContext *avctx) +{ + AndroidCameraCtx *ctx = avctx->priv_data; + ACameraMetadata_const_entry available_framerates; + int found = 0; + int current_best_match = -1; + int requested_framerate = av_q2d(ctx->framerate); + + ACameraMetadata_getConstEntry(ctx->camera_metadata, + ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, + &available_framerates); + + for (int i = 0; i < available_framerates.count; i++) { + int32_t min = available_framerates.data.i32[i * 2 + 0]; + int32_t max = available_framerates.data.i32[i * 2 + 1]; + + if (requested_framerate == max) { + if (min == max) { + ctx->framerate_range[0] = min; + ctx->framerate_range[1] = max; + found = 1; + break; + } else if (current_best_match >= 0) { + int32_t current_best_match_min = available_framerates.data.i32[current_best_match * 2 + 0]; + if (min > current_best_match_min) { + current_best_match = i; + } + } else { + current_best_match = i; + } + } + } + + if (!found) { + if (current_best_match >= 0) { + ctx->framerate_range[0] = available_framerates.data.i32[current_best_match * 2 + 0]; + ctx->framerate_range[1] = available_framerates.data.i32[current_best_match * 2 + 1]; + + } else { + ctx->framerate_range[0] = available_framerates.data.i32[0]; + ctx->framerate_range[1] = available_framerates.data.i32[1]; + } + + av_log(avctx, AV_LOG_WARNING, + "Requested framerate %d not available, falling back to min: %d and max: %d fps\n", + requested_framerate, ctx->framerate_range[0], ctx->framerate_range[1]); + } + + return; +} + +static int get_image_format(AVFormatContext *avctx, AImage *image) +{ + AndroidCameraCtx *ctx = avctx->priv_data; + int32_t image_pixelstrides[2]; + uint8_t *image_plane_data[2]; + int plane_data_length[2]; + + for (int i = 0; i < 2; i++) { + AImage_getPlanePixelStride(image, i + 1, &image_pixelstrides[i]); + AImage_getPlaneData(image, i + 1, &image_plane_data[i], &plane_data_length[i]); + } + + if (image_pixelstrides[0] != image_pixelstrides[1]) { + av_log(avctx, AV_LOG_ERROR, + "Pixel strides of U and V plane should have been the same.\n"); + return AVERROR_EXTERNAL; + } + + switch (image_pixelstrides[0]) { + case 1: + ctx->image_format = AV_PIX_FMT_YUV420P; + break; + case 2: + if (image_plane_data[0] < image_plane_data[1]) { + ctx->image_format = AV_PIX_FMT_NV12; + } else { + ctx->image_format = AV_PIX_FMT_NV21; + } + break; + default: + av_log(avctx, AV_LOG_ERROR, + "Unknown pixel stride %d of U and V plane, cannot determine camera image format.\n", + image_pixelstrides[0]); + return AVERROR(ENOSYS); + } + + return 0; +} + +static void image_available(void *context, AImageReader *reader) +{ + AVFormatContext *avctx = context; + AndroidCameraCtx *ctx = avctx->priv_data; + media_status_t media_status; + int ret = 0; + + AImage *image; + int64_t image_timestamp; + int32_t image_linestrides[4]; + uint8_t *image_plane_data[4]; + int plane_data_length[4]; + + AVPacket pkt; + int pkt_buffer_size = 0; + + media_status = AImageReader_acquireLatestImage(reader, &image); + if (media_status != AMEDIA_OK) { + if (media_status == AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE) { + av_log(avctx, AV_LOG_WARNING, + "An image reader frame was discarded"); + } else { + av_log(avctx, AV_LOG_ERROR, + "Failed to acquire latest image from image reader, error: %s.\n", + media_status_string(media_status)); + ret = AVERROR_EXTERNAL; + } + goto error; + } + + // Silently drop frames when exit is set + if (atomic_load(&ctx->exit)) { + goto error; + } + + // Determine actual image format + if (!atomic_load(&ctx->got_image_format)) { + ret = get_image_format(avctx, image); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "Could not get image format of camera.\n"); + goto error; + } else { + atomic_store(&ctx->got_image_format, 1); + } + } + + pkt_buffer_size = av_image_get_buffer_size(ctx->image_format, ctx->width, ctx->height, 32); + AImage_getTimestamp(image, &image_timestamp); + + AImage_getPlaneRowStride(image, 0, &image_linestrides[0]); + AImage_getPlaneData(image, 0, &image_plane_data[0], &plane_data_length[0]); + + switch (ctx->image_format) { + case AV_PIX_FMT_YUV420P: + AImage_getPlaneRowStride(image, 1, &image_linestrides[1]); + AImage_getPlaneData(image, 1, &image_plane_data[1], &plane_data_length[1]); + AImage_getPlaneRowStride(image, 2, &image_linestrides[2]); + AImage_getPlaneData(image, 2, &image_plane_data[2], &plane_data_length[2]); + break; + case AV_PIX_FMT_NV12: + AImage_getPlaneRowStride(image, 1, &image_linestrides[1]); + AImage_getPlaneData(image, 1, &image_plane_data[1], &plane_data_length[1]); + break; + case AV_PIX_FMT_NV21: + AImage_getPlaneRowStride(image, 2, &image_linestrides[1]); + AImage_getPlaneData(image, 2, &image_plane_data[1], &plane_data_length[1]); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported camera image format.\n"); + ret = AVERROR(ENOSYS); + goto error; + } + + ret = av_new_packet(&pkt, pkt_buffer_size); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "Failed to create new av packet, error: %s.\n", av_err2str(ret)); + goto error; + } + + pkt.stream_index = VIDEO_STREAM_INDEX; + pkt.pts = image_timestamp; + av_image_copy_to_buffer(pkt.data, pkt_buffer_size, + (const uint8_t * const *) image_plane_data, + image_linestrides, ctx->image_format, + ctx->width, ctx->height, 32); + + ret = av_thread_message_queue_send(ctx->input_queue, &pkt, AV_THREAD_MESSAGE_NONBLOCK); + +error: + if (ret < 0) { + if (ret != AVERROR(EAGAIN)) { + av_log(avctx, AV_LOG_ERROR, + "Error while processing new image, error: %s.\n", av_err2str(ret)); + av_thread_message_queue_set_err_recv(ctx->input_queue, ret); + atomic_store(&ctx->exit, 1); + } else { + av_log(avctx, AV_LOG_WARNING, + "Input queue was full, dropping frame, consider raising the input_queue_size option (current value: %d)\n", + ctx->input_queue_size); + } + if (pkt_buffer_size) { + av_packet_unref(&pkt); + } + } + + AImage_delete(image); + + return; +} + +static int create_image_reader(AVFormatContext *avctx) +{ + AndroidCameraCtx *ctx = avctx->priv_data; + media_status_t ret; + + ret = AImageReader_new(ctx->width, ctx->height, IMAGE_FORMAT_ANDROID, + MAX_BUF_COUNT, &ctx->image_reader); + if (ret != AMEDIA_OK) { + av_log(avctx, AV_LOG_ERROR, + "Failed to create image reader, error: %s.\n", media_status_string(ret)); + return AVERROR_EXTERNAL; + } + + ctx->image_listener.context = avctx; + ctx->image_listener.onImageAvailable = image_available; + + ret = AImageReader_setImageListener(ctx->image_reader, &ctx->image_listener); + if (ret != AMEDIA_OK) { + av_log(avctx, AV_LOG_ERROR, + "Failed to set image listener on image reader, error: %s.\n", + media_status_string(ret)); + return AVERROR_EXTERNAL; + } + + ret = AImageReader_getWindow(ctx->image_reader, &ctx->image_reader_window); + if (ret != AMEDIA_OK) { + av_log(avctx, AV_LOG_ERROR, + "Could not get image reader window, error: %s.\n", + media_status_string(ret)); + return AVERROR_EXTERNAL; + } + + return 0; +} + +static void capture_session_closed(void *context, ACameraCaptureSession *session) +{ + av_log(context, AV_LOG_INFO, "Android camera capture session was closed.\n"); +} + +static void capture_session_ready(void *context, ACameraCaptureSession *session) +{ + av_log(context, AV_LOG_INFO, "Android camera capture session is ready.\n"); +} + +static void capture_session_active(void *context, ACameraCaptureSession *session) +{ + av_log(context, AV_LOG_INFO, "Android camera capture session is active.\n"); +} + +static int create_capture_session(AVFormatContext *avctx) +{ + AndroidCameraCtx *ctx = avctx->priv_data; + camera_status_t ret; + + ret = ACaptureSessionOutputContainer_create(&ctx->capture_session_output_container); + if (ret != ACAMERA_OK) { + av_log(avctx, AV_LOG_ERROR, + "Failed to create capture session output container, error: %s.\n", + camera_status_string(ret)); + return AVERROR_EXTERNAL; + } + + ANativeWindow_acquire(ctx->image_reader_window); + + ret = ACaptureSessionOutput_create(ctx->image_reader_window, &ctx->capture_session_output); + if (ret != ACAMERA_OK) { + av_log(avctx, AV_LOG_ERROR, + "Failed to create capture session container, error: %s.\n", + camera_status_string(ret)); + return AVERROR_EXTERNAL; + } + + ret = ACaptureSessionOutputContainer_add(ctx->capture_session_output_container, + ctx->capture_session_output); + if (ret != ACAMERA_OK) { + av_log(avctx, AV_LOG_ERROR, + "Failed to add output to output container, error: %s.\n", + camera_status_string(ret)); + return AVERROR_EXTERNAL; + } + + ret = ACameraOutputTarget_create(ctx->image_reader_window, &ctx->camera_output_target); + if (ret != ACAMERA_OK) { + av_log(avctx, AV_LOG_ERROR, + "Failed to create camera output target, error: %s.\n", + camera_status_string(ret)); + return AVERROR_EXTERNAL; + } + + ret = ACameraDevice_createCaptureRequest(ctx->camera_dev, TEMPLATE_RECORD, &ctx->capture_request); + if (ret != ACAMERA_OK) { + av_log(avctx, AV_LOG_ERROR, + "Failed to create capture request, error: %s.\n", + camera_status_string(ret)); + return AVERROR_EXTERNAL; + } + + ret = ACaptureRequest_setEntry_i32(ctx->capture_request, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE, + 2, ctx->framerate_range); + if (ret != ACAMERA_OK) { + av_log(avctx, AV_LOG_ERROR, + "Failed to set target fps range in capture request, error: %s.\n", + camera_status_string(ret)); + return AVERROR_EXTERNAL; + } + + ret = ACaptureRequest_addTarget(ctx->capture_request, ctx->camera_output_target); + if (ret != ACAMERA_OK) { + av_log(avctx, AV_LOG_ERROR, + "Failed to add capture request capture request, error: %s.\n", + camera_status_string(ret)); + return AVERROR_EXTERNAL; + } + + ctx->capture_session_state_callbacks.context = avctx; + ctx->capture_session_state_callbacks.onClosed = capture_session_closed; + ctx->capture_session_state_callbacks.onReady = capture_session_ready; + ctx->capture_session_state_callbacks.onActive = capture_session_active; + + ret = ACameraDevice_createCaptureSession(ctx->camera_dev, ctx->capture_session_output_container, + &ctx->capture_session_state_callbacks, &ctx->capture_session); + if (ret != ACAMERA_OK) { + av_log(avctx, AV_LOG_ERROR, + "Failed to create capture session, error: %s.\n", + camera_status_string(ret)); + return AVERROR_EXTERNAL; + } + + ret = ACameraCaptureSession_setRepeatingRequest(ctx->capture_session, NULL, 1, &ctx->capture_request, NULL); + if (ret != ACAMERA_OK) { + av_log(avctx, AV_LOG_ERROR, + "Failed to set repeating request on capture session, error: %s.\n", + camera_status_string(ret)); + return AVERROR_EXTERNAL; + } + + return 0; +} + +static int wait_for_image_format(AVFormatContext *avctx) +{ + AndroidCameraCtx *ctx = avctx->priv_data; + + while (!atomic_load(&ctx->got_image_format) && !atomic_load(&ctx->exit)) { + //Wait until first frame arrived and actual image format was determined + usleep(1000); + } + + return atomic_load(&ctx->got_image_format); +} + +static int add_display_matrix(AVFormatContext *avctx, AVStream *st) +{ + AndroidCameraCtx *ctx = avctx->priv_data; + uint8_t *side_data; + int32_t display_matrix[9]; + + av_display_rotation_set(display_matrix, ctx->sensor_orientation); + + if (ctx->lens_facing == ACAMERA_LENS_FACING_FRONT) { + av_display_matrix_flip(display_matrix, 1, 0); + } + + side_data = av_stream_new_side_data(st, + AV_PKT_DATA_DISPLAYMATRIX, sizeof(display_matrix)); + + if (!side_data) { + return AVERROR(ENOMEM); + } + + memcpy(side_data, display_matrix, sizeof(display_matrix)); + + return 0; +} + +static int add_video_stream(AVFormatContext *avctx) +{ + AndroidCameraCtx *ctx = avctx->priv_data; + AVStream *st; + AVCodecParameters *codecpar; + + st = avformat_new_stream(avctx, NULL); + if (!st) { + return AVERROR(ENOMEM); + } + + st->id = VIDEO_STREAM_INDEX; + st->avg_frame_rate = (AVRational) { ctx->framerate_range[1], 1 }; + st->r_frame_rate = (AVRational) { ctx->framerate_range[1], 1 }; + + if (!wait_for_image_format(avctx)) { + return AVERROR_EXTERNAL; + } + + codecpar = st->codecpar; + codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + codecpar->format = ctx->image_format; + codecpar->width = ctx->width; + codecpar->height = ctx->height; + + avpriv_set_pts_info(st, 64, 1, VIDEO_TIMEBASE_ANDROID); + + return add_display_matrix(avctx, st); +} + +static int android_camera_read_close(AVFormatContext *avctx) +{ + AndroidCameraCtx *ctx = avctx->priv_data; + + atomic_store(&ctx->exit, 1); + + if (ctx->capture_session) { + ACameraCaptureSession_stopRepeating(ctx->capture_session); + // Following warning is emitted, after capture session closed callback is received: + // ACameraCaptureSession: Device is closed but session 0 is not notified + // Seems to be a bug in Android, we can ignore this + ACameraCaptureSession_close(ctx->capture_session); + ctx->capture_session = NULL; + } + + if (ctx->capture_request) { + ACaptureRequest_removeTarget(ctx->capture_request, ctx->camera_output_target); + ACaptureRequest_free(ctx->capture_request); + ctx->capture_request = NULL; + } + + if (ctx->camera_output_target) { + ACameraOutputTarget_free(ctx->camera_output_target); + ctx->camera_output_target = NULL; + } + + if (ctx->capture_session_output) { + ACaptureSessionOutputContainer_remove(ctx->capture_session_output_container, + ctx->capture_session_output); + ACaptureSessionOutput_free(ctx->capture_session_output); + ctx->capture_session_output = NULL; + } + + if (ctx->image_reader_window) { + ANativeWindow_release(ctx->image_reader_window); + ctx->image_reader_window = NULL; + } + + if (ctx->capture_session_output_container) { + ACaptureSessionOutputContainer_free(ctx->capture_session_output_container); + ctx->capture_session_output_container = NULL; + } + + if (ctx->camera_dev) { + ACameraDevice_close(ctx->camera_dev); + ctx->camera_dev = NULL; + } + + if (ctx->image_reader) { + AImageReader_delete(ctx->image_reader); + ctx->image_reader = NULL; + } + + if (ctx->camera_metadata) { + ACameraMetadata_free(ctx->camera_metadata); + ctx->camera_metadata = NULL; + } + + av_freep(&ctx->camera_id); + + if (ctx->camera_mgr) { + ACameraManager_delete(ctx->camera_mgr); + ctx->camera_mgr = NULL; + } + + if (ctx->input_queue) { + AVPacket pkt; + av_thread_message_queue_set_err_send(ctx->input_queue, AVERROR_EOF); + while (av_thread_message_queue_recv(ctx->input_queue, &pkt, AV_THREAD_MESSAGE_NONBLOCK) >= 0) { + av_packet_unref(&pkt); + } + av_thread_message_queue_free(&ctx->input_queue); + } + + return 0; +} + +static int android_camera_read_header(AVFormatContext *avctx) +{ + AndroidCameraCtx *ctx = avctx->priv_data; + int ret; + + atomic_init(&ctx->got_image_format, 0); + atomic_init(&ctx->exit, 0); + + ret = av_thread_message_queue_alloc(&ctx->input_queue, ctx->input_queue_size, sizeof(AVPacket)); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "Failed to allocate input queue, error: %s.\n", av_err2str(ret)); + goto error; + } + + ctx->camera_mgr = ACameraManager_create(); + if (!ctx->camera_mgr) { + av_log(avctx, AV_LOG_ERROR, "Failed to create Android camera manager.\n"); + ret = AVERROR_EXTERNAL; + goto error; + } + + ret = open_camera(avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to open camera.\n"); + goto error; + } + + get_sensor_orientation(avctx); + match_video_size(avctx); + match_framerate(avctx); + + ret = create_image_reader(avctx); + if (ret < 0) { + goto error; + } + + ret = create_capture_session(avctx); + if (ret < 0) { + goto error; + } + + ret = add_video_stream(avctx); + +error: + if (ret < 0) { + android_camera_read_close(avctx); + av_log(avctx, AV_LOG_ERROR, "Failed to open android_camera.\n"); + } + + return ret; +} + +static int android_camera_read_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + AndroidCameraCtx *ctx = avctx->priv_data; + int ret; + + if (!atomic_load(&ctx->exit)) { + ret = av_thread_message_queue_recv(ctx->input_queue, pkt, + avctx->flags & AVFMT_FLAG_NONBLOCK ? AV_THREAD_MESSAGE_NONBLOCK : 0); + } else { + ret = AVERROR_EOF; + } + + if (ret < 0) { + return ret; + } else { + return pkt->size; + } +} + +#define OFFSET(x) offsetof(AndroidCameraCtx, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "video_size", "set video size given as a string such as 640x480 or hd720", OFFSET(requested_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC }, + { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "30"}, 0, INT_MAX, DEC }, + { "camera_index", "set index of camera to use", OFFSET(camera_index), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC }, + { "input_queue_size", "set maximum number of frames to buffer", OFFSET(input_queue_size), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, DEC }, + { NULL }, +}; + +static const AVClass android_camera_class = { + .class_name = "android_camera indev", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVDEVICE_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, +}; + +AVInputFormat ff_android_camera_demuxer = { + .name = "android_camera", + .long_name = NULL_IF_CONFIG_SMALL("Android camera input device"), + .priv_data_size = sizeof(AndroidCameraCtx), + .read_header = android_camera_read_header, + .read_packet = android_camera_read_packet, + .read_close = android_camera_read_close, + .flags = AVFMT_NOFILE, + .priv_class = &android_camera_class, +}; diff --git a/libavdevice/version.h b/libavdevice/version.h index e5f60032f7c1e..80285a2611dc4 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVDEVICE_VERSION_MAJOR 58 -#define LIBAVDEVICE_VERSION_MINOR 1 +#define LIBAVDEVICE_VERSION_MINOR 2 #define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ From ff0de964e7abba6df0d8923f70f93cbd6c242ec8 Mon Sep 17 00:00:00 2001 From: Calvin Walton Date: Mon, 19 Feb 2018 19:54:35 -0500 Subject: [PATCH 1928/2557] libavfilter/vf_fps: Add tests for start_time option Signed-off-by: Michael Niedermayer --- tests/fate/filter-video.mak | 4 +++- tests/ref/fate/filter-fps-start-drop | 11 +++++++++++ tests/ref/fate/filter-fps-start-fill | 11 +++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/ref/fate/filter-fps-start-drop create mode 100644 tests/ref/fate/filter-fps-start-fill diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index e3e128cf67d15..07572143a8257 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -425,7 +425,7 @@ fate-filter-concat: CMD = framecrc -filter_complex_script $(TARGET_PATH)/tests/d FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER FPS_FILTER MPDECIMATE_FILTER) += fate-filter-mpdecimate fate-filter-mpdecimate: CMD = framecrc -lavfi testsrc2=r=2:d=10,fps=3,mpdecimate -r 3 -pix_fmt yuv420p -FATE_FILTER-$(call ALLYES, FPS_FILTER TESTSRC2_FILTER) += fate-filter-fps-up fate-filter-fps-up-round-down fate-filter-fps-up-round-up fate-filter-fps-down fate-filter-fps-down-round-down fate-filter-fps-down-round-up fate-filter-fps-down-eof-pass +FATE_FILTER-$(call ALLYES, FPS_FILTER TESTSRC2_FILTER) += fate-filter-fps-up fate-filter-fps-up-round-down fate-filter-fps-up-round-up fate-filter-fps-down fate-filter-fps-down-round-down fate-filter-fps-down-round-up fate-filter-fps-down-eof-pass fate-filter-fps-start-drop fate-filter-fps-start-fill fate-filter-fps-up: CMD = framecrc -lavfi testsrc2=r=3:d=2,fps=7 fate-filter-fps-up-round-down: CMD = framecrc -lavfi testsrc2=r=3:d=2,fps=7:round=down fate-filter-fps-up-round-up: CMD = framecrc -lavfi testsrc2=r=3:d=2,fps=7:round=up @@ -433,6 +433,8 @@ fate-filter-fps-down: CMD = framecrc -lavfi testsrc2=r=7:d=3.5,fps=3 fate-filter-fps-down-round-down: CMD = framecrc -lavfi testsrc2=r=7:d=3.5,fps=3:round=down fate-filter-fps-down-round-up: CMD = framecrc -lavfi testsrc2=r=7:d=3.5,fps=3:round=up fate-filter-fps-down-eof-pass: CMD = framecrc -lavfi testsrc2=r=7:d=3.5,fps=3:eof_action=pass +fate-filter-fps-start-drop: CMD = framecrc -lavfi testsrc2=r=7:d=3.5,fps=3:start_time=1.5 +fate-filter-fps-start-fill: CMD = framecrc -lavfi testsrc2=r=7:d=1.5,setpts=PTS+14,fps=3:start_time=1.5 FATE_FILTER_SAMPLES-$(call ALLYES, MOV_DEMUXER FPS_FILTER QTRLE_DECODER) += fate-filter-fps-cfr fate-filter-fps fate-filter-fps-r fate-filter-fps-cfr: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vsync cfr -pix_fmt yuv420p diff --git a/tests/ref/fate/filter-fps-start-drop b/tests/ref/fate/filter-fps-start-drop new file mode 100644 index 0000000000000..cfa1c40997bbc --- /dev/null +++ b/tests/ref/fate/filter-fps-start-drop @@ -0,0 +1,11 @@ +#tb 0: 1/3 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 5, 5, 1, 115200, 0x2d0ba5a4 +0, 6, 6, 1, 115200, 0xc95a675e +0, 7, 7, 1, 115200, 0xf040bf35 +0, 8, 8, 1, 115200, 0x5635daa5 +0, 9, 9, 1, 115200, 0x0caf7172 +0, 10, 10, 1, 115200, 0xc8ce7fb1 diff --git a/tests/ref/fate/filter-fps-start-fill b/tests/ref/fate/filter-fps-start-fill new file mode 100644 index 0000000000000..c5efb42a8f7b3 --- /dev/null +++ b/tests/ref/fate/filter-fps-start-fill @@ -0,0 +1,11 @@ +#tb 0: 1/3 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 5, 5, 1, 115200, 0x3744b3ed +0, 6, 6, 1, 115200, 0x3744b3ed +0, 7, 7, 1, 115200, 0x201b9db1 +0, 8, 8, 1, 115200, 0x75e1a17b +0, 9, 9, 1, 115200, 0xb73857e2 +0, 10, 10, 1, 115200, 0x02b6ab21 From 4f8c691040b026d001ff33d38c0e1516a35b946e Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Tue, 20 Feb 2018 20:31:28 +0530 Subject: [PATCH 1929/2557] avformat/mpegenc - log error msgs for unsupported LPCM streams The MPEG-PS muxer only accepts PCM streams having up to 8 channels and the following sampling rates: 32/44.1/48/96 kHz. Signed-off-by: Michael Niedermayer --- libavformat/mpegenc.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c index c84dc52eb9549..4c6fa67fb83c1 100644 --- a/libavformat/mpegenc.c +++ b/libavformat/mpegenc.c @@ -375,10 +375,19 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) if (lpcm_freq_tab[j] == st->codecpar->sample_rate) break; } - if (j == 4) + if (j == 4) { + int sr; + av_log(ctx, AV_LOG_ERROR, "Invalid sampling rate for PCM stream.\n"); + av_log(ctx, AV_LOG_INFO, "Allowed sampling rates:"); + for (sr = 0; sr < 4; sr++) + av_log(ctx, AV_LOG_INFO, " %d", lpcm_freq_tab[sr]); + av_log(ctx, AV_LOG_INFO, "\n"); goto fail; - if (st->codecpar->channels > 8) - return -1; + } + if (st->codecpar->channels > 8) { + av_log(ctx, AV_LOG_ERROR, "At most 8 channels allowed for LPCM streams.\n"); + goto fail; + } stream->lpcm_header[0] = 0x0c; stream->lpcm_header[1] = (st->codecpar->channels - 1) | (j << 4); stream->lpcm_header[2] = 0x80; From ae2eb04648839bfc6c61c32cb0f124e91bb7ff8e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 20 Feb 2018 23:11:01 +0100 Subject: [PATCH 1930/2557] avcodec/cavsdec: Check alpha/beta offset Fixes: Integer overflow Fixes: 6183/clusterfuzz-testcase-minimized-6269224436629504 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/cavsdec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c index 06c752735ecef..c7fff67c06c66 100644 --- a/libavcodec/cavsdec.c +++ b/libavcodec/cavsdec.c @@ -1067,6 +1067,11 @@ static int decode_pic(AVSContext *h) if (!h->loop_filter_disable && get_bits1(&h->gb)) { h->alpha_offset = get_se_golomb(&h->gb); h->beta_offset = get_se_golomb(&h->gb); + if ( h->alpha_offset < -64 || h->alpha_offset > 64 + || h-> beta_offset < -64 || h-> beta_offset > 64) { + h->alpha_offset = h->beta_offset = 0; + return AVERROR_INVALIDDATA; + } } else { h->alpha_offset = h->beta_offset = 0; } From 9ca79784e9e640829645b0b28201cf9cdfbfc0f4 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 23 Nov 2017 22:44:27 +0000 Subject: [PATCH 1931/2557] lavc/mjpeg: Add profiles for MJPEG using SOF marker codes This is needed by later hwaccel code to tell which encoding process was used for a particular frame, because hardware decoders may only support a subset of possible methods. --- libavcodec/avcodec.h | 6 ++++++ libavcodec/mjpegdec.c | 7 +++++++ libavcodec/version.h | 4 ++-- tests/ref/fate/api-mjpeg-codec-param | 4 ++-- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index bc0eacd66b09a..74c7b9dadd939 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2918,6 +2918,12 @@ typedef struct AVCodecContext { #define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3 #define FF_PROFILE_HEVC_REXT 4 +#define FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT 0xc0 +#define FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1 +#define FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT 0xc2 +#define FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS 0xc3 +#define FF_PROFILE_MJPEG_JPEG_LS 0xf7 + /** * level * - encoding: Set by user. diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 5055ee28267bc..29f99373ccb9a 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -2288,6 +2288,10 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, break; case SOF0: case SOF1: + if (start_code == SOF0) + s->avctx->profile = FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT; + else + s->avctx->profile = FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT; s->lossless = 0; s->ls = 0; s->progressive = 0; @@ -2295,6 +2299,7 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, goto fail; break; case SOF2: + s->avctx->profile = FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT; s->lossless = 0; s->ls = 0; s->progressive = 1; @@ -2302,6 +2307,7 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, goto fail; break; case SOF3: + s->avctx->profile = FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS; s->avctx->properties |= FF_CODEC_PROPERTY_LOSSLESS; s->lossless = 1; s->ls = 0; @@ -2310,6 +2316,7 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, goto fail; break; case SOF48: + s->avctx->profile = FF_PROFILE_MJPEG_JPEG_LS; s->avctx->properties |= FF_CODEC_PROPERTY_LOSSLESS; s->lossless = 1; s->ls = 1; diff --git a/libavcodec/version.h b/libavcodec/version.h index d13dd41fa3e60..d772f3e48e75f 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 11 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MINOR 12 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/tests/ref/fate/api-mjpeg-codec-param b/tests/ref/fate/api-mjpeg-codec-param index e5ad2b76566f7..290f941ff3c0d 100644 --- a/tests/ref/fate/api-mjpeg-codec-param +++ b/tests/ref/fate/api-mjpeg-codec-param @@ -81,7 +81,7 @@ stream=0, decode=0 nssew=8 skip_top=0 skip_bottom=0 - profile=-99 + profile=192 level=-99 lowres=0 skip_threshold=0 @@ -221,7 +221,7 @@ stream=0, decode=1 nssew=8 skip_top=0 skip_bottom=0 - profile=-99 + profile=192 level=-99 lowres=0 skip_threshold=0 From 6c0bfa30c00d062737b10f22c2532f60d94afdf2 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 23 Nov 2017 23:45:32 +0000 Subject: [PATCH 1932/2557] mjpegdec: Add hwaccel hooks Also adds some extra fields to the main context structure that may be needed by a hwaccel decoder. --- libavcodec/mjpegdec.c | 74 ++++++++++++++++++++++++++++++++++++++++--- libavcodec/mjpegdec.h | 13 ++++++++ 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 29f99373ccb9a..6141f06367c76 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -36,6 +36,7 @@ #include "avcodec.h" #include "blockdsp.h" #include "copy_block.h" +#include "hwaccel.h" #include "idctdsp.h" #include "internal.h" #include "jpegtables.h" @@ -147,6 +148,7 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) s->org_height = avctx->coded_height; avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; avctx->colorspace = AVCOL_SPC_BT470BG; + s->hwaccel_pix_fmt = s->hwaccel_sw_pix_fmt = AV_PIX_FMT_NONE; if ((ret = build_basic_mjpeg_vlc(s)) < 0) return ret; @@ -279,13 +281,18 @@ int ff_mjpeg_decode_dht(MJpegDecodeContext *s) code_max + 1, 0, 0)) < 0) return ret; } + + for (i = 0; i < 16; i++) + s->raw_huffman_lengths[class][index][i] = bits_table[i + 1]; + for (i = 0; i < 256; i++) + s->raw_huffman_values[class][index][i] = val_table[i]; } return 0; } int ff_mjpeg_decode_sof(MJpegDecodeContext *s) { - int len, nb_components, i, width, height, bits, ret; + int len, nb_components, i, width, height, bits, ret, size_change; unsigned pix_fmt_id; int h_count[MAX_COMPONENTS] = { 0 }; int v_count[MAX_COMPONENTS] = { 0 }; @@ -392,6 +399,7 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) if (width != s->width || height != s->height || bits != s->bits || memcmp(s->h_count, h_count, sizeof(h_count)) || memcmp(s->v_count, v_count, sizeof(v_count))) { + size_change = 1; s->width = width; s->height = height; @@ -418,6 +426,8 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) return ret; s->first_picture = 0; + } else { + size_change = 0; } if (s->got_picture && s->interlaced && (s->bottom_field == !s->interlace_polarity)) { @@ -636,6 +646,21 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) return AVERROR_BUG; } + if (s->avctx->pix_fmt == s->hwaccel_sw_pix_fmt && !size_change) { + s->avctx->pix_fmt = s->hwaccel_pix_fmt; + } else { + enum AVPixelFormat pix_fmts[] = { + s->avctx->pix_fmt, + AV_PIX_FMT_NONE, + }; + s->hwaccel_pix_fmt = ff_get_format(s->avctx, pix_fmts); + if (s->hwaccel_pix_fmt < 0) + return AVERROR(EINVAL); + + s->hwaccel_sw_pix_fmt = s->avctx->pix_fmt; + s->avctx->pix_fmt = s->hwaccel_pix_fmt; + } + if (s->avctx->skip_frame == AVDISCARD_ALL) { s->picture_ptr->pict_type = AV_PICTURE_TYPE_I; s->picture_ptr->key_frame = 1; @@ -683,6 +708,19 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) } memset(s->coefs_finished, 0, sizeof(s->coefs_finished)); } + + if (s->avctx->hwaccel) { + s->hwaccel_picture_private = + av_mallocz(s->avctx->hwaccel->frame_priv_data_size); + if (!s->hwaccel_picture_private) + return AVERROR(ENOMEM); + + ret = s->avctx->hwaccel->start_frame(s->avctx, s->raw_image_buffer, + s->raw_image_buffer_size); + if (ret < 0) + return ret; + } + return 0; } @@ -1510,7 +1548,6 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, } } - av_assert0(s->picture_ptr->data[0]); /* XXX: verify len field validity */ len = get_bits(&s->gb, 16); nb_components = get_bits(&s->gb, 8); @@ -1600,7 +1637,18 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, for (i = 0; i < nb_components; i++) s->last_dc[i] = (4 << s->bits); - if (s->lossless) { + if (s->avctx->hwaccel) { + int bytes_to_start = get_bits_count(&s->gb) / 8; + av_assert0(bytes_to_start >= 0 && + s->raw_scan_buffer_size >= bytes_to_start); + + ret = s->avctx->hwaccel->decode_slice(s->avctx, + s->raw_scan_buffer + bytes_to_start, + s->raw_scan_buffer_size - bytes_to_start); + if (ret < 0) + return ret; + + } else if (s->lossless) { av_assert0(s->picture_ptr == s->picture); if (CONFIG_JPEGLS_DECODER && s->ls) { // for () { @@ -2278,6 +2326,8 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, case SOI: s->restart_interval = 0; s->restart_count = 0; + s->raw_image_buffer = buf_ptr; + s->raw_image_buffer_size = buf_end - buf_ptr; /* nothing to do on SOI */ break; case DHT: @@ -2331,7 +2381,8 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, break; case EOI: eoi_parser: - if (avctx->skip_frame != AVDISCARD_ALL && s->progressive && s->cur_scan && s->got_picture) + if (!avctx->hwaccel && avctx->skip_frame != AVDISCARD_ALL && + s->progressive && s->cur_scan && s->got_picture) mjpeg_idct_scan_progressive_ac(s); s->cur_scan = 0; if (!s->got_picture) { @@ -2349,6 +2400,13 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, s->got_picture = 0; goto the_end_no_picture; } + if (s->avctx->hwaccel) { + ret = s->avctx->hwaccel->end_frame(s->avctx); + if (ret < 0) + return ret; + + av_freep(&s->hwaccel_picture_private); + } if ((ret = av_frame_ref(frame, s->picture_ptr)) < 0) return ret; *got_frame = 1; @@ -2371,6 +2429,9 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, goto the_end; case SOS: + s->raw_scan_buffer = buf_ptr; + s->raw_scan_buffer_size = buf_end - buf_ptr; + s->cur_scan++; if (avctx->skip_frame == AVDISCARD_ALL) { skip_bits(&s->gb, get_bits_left(&s->gb)); @@ -2673,6 +2734,8 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx) reset_icc_profile(s); + av_freep(&s->hwaccel_picture_private); + return 0; } @@ -2713,6 +2776,9 @@ AVCodec ff_mjpeg_decoder = { .priv_class = &mjpegdec_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .hw_configs = (const AVCodecHWConfigInternal*[]) { + NULL + }, }; #endif #if CONFIG_THP_DECODER diff --git a/libavcodec/mjpegdec.h b/libavcodec/mjpegdec.h index c36fba5f2281a..ff301bcb93799 100644 --- a/libavcodec/mjpegdec.h +++ b/libavcodec/mjpegdec.h @@ -137,6 +137,19 @@ typedef struct MJpegDecodeContext { int *iccdatalens; int iccnum; int iccread; + + // Raw stream data for hwaccel use. + const uint8_t *raw_image_buffer; + size_t raw_image_buffer_size; + const uint8_t *raw_scan_buffer; + size_t raw_scan_buffer_size; + + uint8_t raw_huffman_lengths[2][4][16]; + uint8_t raw_huffman_values[2][4][256]; + + enum AVPixelFormat hwaccel_sw_pix_fmt; + enum AVPixelFormat hwaccel_pix_fmt; + void *hwaccel_picture_private; } MJpegDecodeContext; int ff_mjpeg_decode_init(AVCodecContext *avctx); From fabcbfba3846667869e14a562bd84c7b4dd0c6a4 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 19 Feb 2018 20:03:08 +0000 Subject: [PATCH 1933/2557] hwcontext_vaapi: Add more surface formats Adds YUV 4:1:1, 4:4:0 and 4:4:4 - these will be needed for JPEG decoding. --- libavutil/hwcontext_vaapi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 29698d1b27816..68f88ecd6b2ba 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -110,6 +110,9 @@ static const struct { MAP(422H, YUV422, YUV422P), MAP(UYVY, YUV422, UYVY422), MAP(YUY2, YUV422, YUYV422), + MAP(411P, YUV411, YUV411P), + MAP(422V, YUV422, YUV440P), + MAP(444P, YUV444, YUV444P), MAP(Y800, YUV400, GRAY8), #ifdef VA_FOURCC_P010 MAP(P010, YUV420_10BPP, P010), From 193e43e6195eba669015098b4245a7287b7506b0 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 19 Feb 2018 20:04:25 +0000 Subject: [PATCH 1934/2557] hwcontext_vaapi: Fix frames context creation with external attributes --- libavutil/hwcontext_vaapi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 68f88ecd6b2ba..af9a136ef0531 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -475,9 +475,9 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc) int need_memory_type = !(hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE); int need_pixel_format = 1; for (i = 0; i < avfc->nb_attributes; i++) { - if (ctx->attributes[i].type == VASurfaceAttribMemoryType) + if (avfc->attributes[i].type == VASurfaceAttribMemoryType) need_memory_type = 0; - if (ctx->attributes[i].type == VASurfaceAttribPixelFormat) + if (avfc->attributes[i].type == VASurfaceAttribPixelFormat) need_pixel_format = 0; } ctx->nb_attributes = From 99ab0a13dc231b92dcd207f58a1101fe5f11d663 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 19 Feb 2018 20:04:31 +0000 Subject: [PATCH 1935/2557] vaapi_decode: Make the frames context format selection more general Examine the supported fourcc list manually and make the best choice, then use the external attribute on the frames context to force that fourcc. --- libavcodec/vaapi_decode.c | 152 ++++++++++++++++++++++++++++++++------ libavcodec/vaapi_decode.h | 2 + 2 files changed, 132 insertions(+), 22 deletions(-) diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index 572b3a40ac054..28c6eeb80120d 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -232,6 +232,132 @@ int ff_vaapi_decode_cancel(AVCodecContext *avctx, return 0; } +static const struct { + uint32_t fourcc; + enum AVPixelFormat pix_fmt; +} vaapi_format_map[] = { +#define MAP(va, av) { VA_FOURCC_ ## va, AV_PIX_FMT_ ## av } + // 4:0:0 + MAP(Y800, GRAY8), + // 4:2:0 + MAP(NV12, NV12), + MAP(YV12, YUV420P), + MAP(IYUV, YUV420P), +#ifdef VA_FOURCC_I420 + MAP(I420, YUV420P), +#endif + MAP(IMC3, YUV420P), + // 4:1:1 + MAP(411P, YUV411P), + // 4:2:2 + MAP(422H, YUV422P), +#ifdef VA_FOURCC_YV16 + MAP(YV16, YUV422P), +#endif + // 4:4:0 + MAP(422V, YUV440P), + // 4:4:4 + MAP(444P, YUV444P), + // 4:2:0 10-bit +#ifdef VA_FOURCC_P010 + MAP(P010, P010), +#endif +#ifdef VA_FOURCC_I010 + MAP(I010, YUV420P10), +#endif +#undef MAP +}; + +static int vaapi_decode_find_best_format(AVCodecContext *avctx, + AVHWDeviceContext *device, + VAConfigID config_id, + AVHWFramesContext *frames) +{ + AVVAAPIDeviceContext *hwctx = device->hwctx; + VAStatus vas; + VASurfaceAttrib *attr; + enum AVPixelFormat source_format, best_format, format; + uint32_t best_fourcc, fourcc; + int i, j, nb_attr; + + source_format = avctx->sw_pix_fmt; + av_assert0(source_format != AV_PIX_FMT_NONE); + + vas = vaQuerySurfaceAttributes(hwctx->display, config_id, + NULL, &nb_attr); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: " + "%d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(ENOSYS); + } + + attr = av_malloc_array(nb_attr, sizeof(*attr)); + if (!attr) + return AVERROR(ENOMEM); + + vas = vaQuerySurfaceAttributes(hwctx->display, config_id, + attr, &nb_attr); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: " + "%d (%s).\n", vas, vaErrorStr(vas)); + av_freep(&attr); + return AVERROR(ENOSYS); + } + + best_format = AV_PIX_FMT_NONE; + + for (i = 0; i < nb_attr; i++) { + if (attr[i].type != VASurfaceAttribPixelFormat) + continue; + + fourcc = attr[i].value.value.i; + for (j = 0; j < FF_ARRAY_ELEMS(vaapi_format_map); j++) { + if (fourcc == vaapi_format_map[j].fourcc) + break; + } + if (j >= FF_ARRAY_ELEMS(vaapi_format_map)) { + av_log(avctx, AV_LOG_DEBUG, "Ignoring unknown format %#x.\n", + fourcc); + continue; + } + format = vaapi_format_map[j].pix_fmt; + av_log(avctx, AV_LOG_DEBUG, "Considering format %#x -> %s.\n", + fourcc, av_get_pix_fmt_name(format)); + + best_format = av_find_best_pix_fmt_of_2(format, best_format, + source_format, 0, NULL); + if (format == best_format) + best_fourcc = fourcc; + } + + av_freep(&attr); + + if (best_format == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "No usable formats for decoding!\n"); + return AVERROR(EINVAL); + } + + av_log(avctx, AV_LOG_DEBUG, "Picked %s (%#x) as best match for %s.\n", + av_get_pix_fmt_name(best_format), best_fourcc, + av_get_pix_fmt_name(source_format)); + + frames->sw_format = best_format; + if (avctx->internal->hwaccel_priv_data) { + VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; + AVVAAPIFramesContext *avfc = frames->hwctx; + + ctx->pixel_format_attribute = (VASurfaceAttrib) { + .type = VASurfaceAttribPixelFormat, + .value.value.i = best_fourcc, + }; + + avfc->attributes = &ctx->pixel_format_attribute; + avfc->nb_attributes = 1; + } + + return 0; +} + static const struct { enum AVCodecID codec_id; int codec_profile; @@ -289,7 +415,6 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, const AVCodecDescriptor *codec_desc; VAProfile *profile_list = NULL, matched_va_profile; int profile_count, exact_match, matched_ff_profile; - const AVPixFmtDescriptor *sw_desc, *desc; AVHWDeviceContext *device = (AVHWDeviceContext*)device_ref->data; AVVAAPIDeviceContext *hwctx = device->hwctx; @@ -417,27 +542,10 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, frames->width = avctx->coded_width; frames->height = avctx->coded_height; - // Find the first format in the list which matches the expected - // bit depth and subsampling. If none are found (this can happen - // when 10-bit streams are decoded to 8-bit surfaces, for example) - // then just take the first format on the list. - frames->sw_format = constraints->valid_sw_formats[0]; - sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); - for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { - desc = av_pix_fmt_desc_get(constraints->valid_sw_formats[i]); - if (desc->nb_components != sw_desc->nb_components || - desc->log2_chroma_w != sw_desc->log2_chroma_w || - desc->log2_chroma_h != sw_desc->log2_chroma_h) - continue; - for (j = 0; j < desc->nb_components; j++) { - if (desc->comp[j].depth != sw_desc->comp[j].depth) - break; - } - if (j < desc->nb_components) - continue; - frames->sw_format = constraints->valid_sw_formats[i]; - break; - } + err = vaapi_decode_find_best_format(avctx, device, + *va_config, frames); + if (err < 0) + goto fail; frames->initial_pool_size = 1; // Add per-codec number of surfaces used for storing reference frames. diff --git a/libavcodec/vaapi_decode.h b/libavcodec/vaapi_decode.h index 1fcecac4682fb..6b415dd1d36d0 100644 --- a/libavcodec/vaapi_decode.h +++ b/libavcodec/vaapi_decode.h @@ -72,6 +72,8 @@ FF_ENABLE_DEPRECATION_WARNINGS enum AVPixelFormat surface_format; int surface_count; + + VASurfaceAttrib pixel_format_attribute; } VAAPIDecodeContext; From 63c690ad154509dcda78d3d3537bd1af9c406241 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Thu, 23 Nov 2017 23:47:52 +0000 Subject: [PATCH 1936/2557] vaapi: Add MJPEG decode hwaccel --- Changelog | 2 +- configure | 2 + libavcodec/Makefile | 1 + libavcodec/hwaccels.h | 1 + libavcodec/mjpegdec.c | 6 ++ libavcodec/vaapi_decode.c | 2 + libavcodec/vaapi_mjpeg.c | 159 ++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 8 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 libavcodec/vaapi_mjpeg.c diff --git a/Changelog b/Changelog index 56dedd1aea0a7..441ee1cd29e72 100644 --- a/Changelog +++ b/Changelog @@ -21,7 +21,7 @@ version : - video mix filter - video normalize filter - audio lv2 wrapper filter -- VAAPI VP8 decoding +- VAAPI MJPEG and VP8 decoding - AMD AMF H.264 and HEVC encoders - video fillborders filter - video setrange filter diff --git a/configure b/configure index fa5c530abe742..9b2468516a840 100755 --- a/configure +++ b/configure @@ -2714,6 +2714,8 @@ hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC" hevc_vdpau_hwaccel_select="hevc_decoder" hevc_videotoolbox_hwaccel_deps="videotoolbox" hevc_videotoolbox_hwaccel_select="hevc_decoder" +mjpeg_vaapi_hwaccel_deps="vaapi" +mjpeg_vaapi_hwaccel_select="mjpeg_decoder" mpeg_xvmc_hwaccel_deps="xvmc" mpeg_xvmc_hwaccel_select="mpeg2video_decoder" mpeg1_nvdec_hwaccel_deps="nvdec" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3d4b738e0be12..de52bc2094361 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -854,6 +854,7 @@ OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec_h2645.o OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o +OBJS-$(CONFIG_MJPEG_VAAPI_HWACCEL) += vaapi_mjpeg.o OBJS-$(CONFIG_MPEG1_NVDEC_HWACCEL) += nvdec_mpeg12.o OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL) += vdpau_mpeg12.o OBJS-$(CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h index fcfe4e088ec7b..420e2feeea117 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -37,6 +37,7 @@ extern const AVHWAccel ff_hevc_nvdec_hwaccel; extern const AVHWAccel ff_hevc_vaapi_hwaccel; extern const AVHWAccel ff_hevc_vdpau_hwaccel; extern const AVHWAccel ff_hevc_videotoolbox_hwaccel; +extern const AVHWAccel ff_mjpeg_vaapi_hwaccel; extern const AVHWAccel ff_mpeg1_nvdec_hwaccel; extern const AVHWAccel ff_mpeg1_vdpau_hwaccel; extern const AVHWAccel ff_mpeg1_videotoolbox_hwaccel; diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 6141f06367c76..939f2849d0e3e 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -650,6 +650,9 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) s->avctx->pix_fmt = s->hwaccel_pix_fmt; } else { enum AVPixelFormat pix_fmts[] = { +#if CONFIG_MJPEG_VAAPI_HWACCEL + AV_PIX_FMT_VAAPI, +#endif s->avctx->pix_fmt, AV_PIX_FMT_NONE, }; @@ -2777,6 +2780,9 @@ AVCodec ff_mjpeg_decoder = { .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_MJPEG_VAAPI_HWACCEL + HWACCEL_VAAPI(mjpeg), +#endif NULL }, }; diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index 28c6eeb80120d..d0a6b5817d794 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -379,6 +379,8 @@ static const struct { MAP(HEVC, HEVC_MAIN, HEVCMain ), MAP(HEVC, HEVC_MAIN_10, HEVCMain10 ), #endif + MAP(MJPEG, MJPEG_HUFFMAN_BASELINE_DCT, + JPEGBaseline), MAP(WMV3, VC1_SIMPLE, VC1Simple ), MAP(WMV3, VC1_MAIN, VC1Main ), MAP(WMV3, VC1_COMPLEX, VC1Advanced ), diff --git a/libavcodec/vaapi_mjpeg.c b/libavcodec/vaapi_mjpeg.c new file mode 100644 index 0000000000000..14e0206ae1fa3 --- /dev/null +++ b/libavcodec/vaapi_mjpeg.c @@ -0,0 +1,159 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "hwaccel.h" +#include "vaapi_decode.h" +#include "mjpegdec.h" + +static int vaapi_mjpeg_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + const MJpegDecodeContext *s = avctx->priv_data; + VAAPIDecodePicture *pic = s->hwaccel_picture_private; + VAPictureParameterBufferJPEGBaseline pp; + int err, i; + + pic->output_surface = ff_vaapi_get_surface_id(s->picture_ptr); + + pp = (VAPictureParameterBufferJPEGBaseline) { + .picture_width = avctx->width, + .picture_height = avctx->height, + + .num_components = s->nb_components, + }; + + for (i = 0; i < s->nb_components; i++) { + pp.components[i].component_id = s->component_id[i]; + pp.components[i].h_sampling_factor = s->h_count[i]; + pp.components[i].v_sampling_factor = s->v_count[i]; + pp.components[i].quantiser_table_selector = s->quant_index[i]; + } + + err = ff_vaapi_decode_make_param_buffer(avctx, pic, + VAPictureParameterBufferType, + &pp, sizeof(pp)); + if (err < 0) + goto fail; + + return 0; + +fail: + ff_vaapi_decode_cancel(avctx, pic); + return err; +} + +static int vaapi_mjpeg_end_frame(AVCodecContext *avctx) +{ + const MJpegDecodeContext *s = avctx->priv_data; + VAAPIDecodePicture *pic = s->hwaccel_picture_private; + + return ff_vaapi_decode_issue(avctx, pic); +} + +static int vaapi_mjpeg_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + const MJpegDecodeContext *s = avctx->priv_data; + VAAPIDecodePicture *pic = s->hwaccel_picture_private; + VAHuffmanTableBufferJPEGBaseline huff; + VAIQMatrixBufferJPEGBaseline quant; + VASliceParameterBufferJPEGBaseline sp; + int err, i, j; + + memset(&huff, 0, sizeof(huff)); + for (i = 0; i < 2; i++) { + huff.load_huffman_table[i] = 1; + for (j = 0; j < 16; j++) + huff.huffman_table[i].num_dc_codes[j] = s->raw_huffman_lengths[0][i][j]; + for (j = 0; j < 12; j++) + huff.huffman_table[i].dc_values[j] = s->raw_huffman_values[0][i][j]; + for (j = 0; j < 16; j++) + huff.huffman_table[i].num_ac_codes[j] = s->raw_huffman_lengths[1][i][j]; + for (j = 0; j < 162; j++) + huff.huffman_table[i].ac_values[j] = s->raw_huffman_values[1][i][j]; + } + + err = ff_vaapi_decode_make_param_buffer(avctx, pic, + VAHuffmanTableBufferType, + &huff, sizeof(huff)); + if (err < 0) + goto fail; + + memset(&quant, 0, sizeof(quant)); + for (i = 0; i < 4; i++) { + quant.load_quantiser_table[i] = 1; + for (j = 0; j < 64; j++) + quant.quantiser_table[i][j] = s->quant_matrixes[i][j]; + } + + err = ff_vaapi_decode_make_param_buffer(avctx, pic, + VAIQMatrixBufferType, + &quant, sizeof(quant)); + if (err < 0) + goto fail; + + sp = (VASliceParameterBufferJPEGBaseline) { + .slice_data_size = size, + .slice_data_offset = 0, + .slice_data_flag = VA_SLICE_DATA_FLAG_ALL, + + .slice_horizontal_position = 0, + .slice_vertical_position = 0, + + .restart_interval = s->restart_interval, + .num_mcus = s->mb_width * s->mb_height, + }; + + sp.num_components = s->nb_components; + for (i = 0; i < s->nb_components; i++) { + sp.components[i].component_selector = s->component_id[s->comp_index[i]]; + sp.components[i].dc_table_selector = s->dc_index[i]; + sp.components[i].ac_table_selector = s->ac_index[i]; + } + + err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &sp, sizeof(sp), buffer, size); + if (err) + goto fail; + + return 0; + +fail: + ff_vaapi_decode_cancel(avctx, pic); + return err; +} + +const AVHWAccel ff_mjpeg_vaapi_hwaccel = { + .name = "mjpeg_vaapi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MJPEG, + .pix_fmt = AV_PIX_FMT_VAAPI, + .start_frame = &vaapi_mjpeg_start_frame, + .end_frame = &vaapi_mjpeg_end_frame, + .decode_slice = &vaapi_mjpeg_decode_slice, + .frame_priv_data_size = sizeof(VAAPIDecodePicture), + .init = &ff_vaapi_decode_init, + .uninit = &ff_vaapi_decode_uninit, + .frame_params = &ff_vaapi_common_frame_params, + .priv_data_size = sizeof(VAAPIDecodeContext), + .caps_internal = HWACCEL_CAP_ASYNC_SAFE, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index d772f3e48e75f..3939c4f67aa94 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 12 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From cd98f20b4abac8241ef7f922eb85ba6fe3fe230b Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Sun, 18 Feb 2018 15:53:33 -0800 Subject: [PATCH 1937/2557] avcodec/nvdec: Implement mjpeg nvdec hwaccel --- Changelog | 2 +- configure | 2 + libavcodec/Makefile | 1 + libavcodec/hwaccels.h | 1 + libavcodec/mjpegdec.c | 6 +++ libavcodec/nvdec.c | 1 + libavcodec/nvdec_mjpeg.c | 86 ++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 8 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 libavcodec/nvdec_mjpeg.c diff --git a/Changelog b/Changelog index 441ee1cd29e72..f7afd2f9ed2c4 100644 --- a/Changelog +++ b/Changelog @@ -13,7 +13,7 @@ version : - PCE support for extended channel layouts in the AAC encoder - native aptX and aptX HD encoder and decoder - Raw aptX and aptX HD muxer and demuxer -- NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-1/2/4, VC1, VP8/9 hwaccel decoding +- NVIDIA NVDEC-accelerated H.264, HEVC, MJPEG, MPEG-1/2/4, VC1, VP8/9 hwaccel decoding - Intel QSV-accelerated overlay filter - mcompand audio filter - acontrast audio filter diff --git a/configure b/configure index 9b2468516a840..d40718f8427a2 100755 --- a/configure +++ b/configure @@ -2714,6 +2714,8 @@ hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC" hevc_vdpau_hwaccel_select="hevc_decoder" hevc_videotoolbox_hwaccel_deps="videotoolbox" hevc_videotoolbox_hwaccel_select="hevc_decoder" +mjpeg_nvdec_hwaccel_deps="nvdec" +mjpeg_nvdec_hwaccel_select="mjpeg_decoder" mjpeg_vaapi_hwaccel_deps="vaapi" mjpeg_vaapi_hwaccel_select="mjpeg_decoder" mpeg_xvmc_hwaccel_deps="xvmc" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index de52bc2094361..c7a5692421904 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -854,6 +854,7 @@ OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec_h2645.o OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o +OBJS-$(CONFIG_MJPEG_NVDEC_HWACCEL) += nvdec_mjpeg.o OBJS-$(CONFIG_MJPEG_VAAPI_HWACCEL) += vaapi_mjpeg.o OBJS-$(CONFIG_MPEG1_NVDEC_HWACCEL) += nvdec_mpeg12.o OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL) += vdpau_mpeg12.o diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h index 420e2feeea117..7d73da86767cf 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -37,6 +37,7 @@ extern const AVHWAccel ff_hevc_nvdec_hwaccel; extern const AVHWAccel ff_hevc_vaapi_hwaccel; extern const AVHWAccel ff_hevc_vdpau_hwaccel; extern const AVHWAccel ff_hevc_videotoolbox_hwaccel; +extern const AVHWAccel ff_mjpeg_nvdec_hwaccel; extern const AVHWAccel ff_mjpeg_vaapi_hwaccel; extern const AVHWAccel ff_mpeg1_nvdec_hwaccel; extern const AVHWAccel ff_mpeg1_vdpau_hwaccel; diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 939f2849d0e3e..beef174618fbf 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -650,6 +650,9 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) s->avctx->pix_fmt = s->hwaccel_pix_fmt; } else { enum AVPixelFormat pix_fmts[] = { +#if CONFIG_MJPEG_NVDEC_HWACCEL + AV_PIX_FMT_CUDA, +#endif #if CONFIG_MJPEG_VAAPI_HWACCEL AV_PIX_FMT_VAAPI, #endif @@ -2780,6 +2783,9 @@ AVCodec ff_mjpeg_decoder = { .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .hw_configs = (const AVCodecHWConfigInternal*[]) { +#if CONFIG_MJPEG_NVDEC_HWACCEL + HWACCEL_NVDEC(mjpeg), +#endif #if CONFIG_MJPEG_VAAPI_HWACCEL HWACCEL_VAAPI(mjpeg), #endif diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index e9e6ea0f8b9d0..ab3cb88b27589 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -54,6 +54,7 @@ static int map_avcodec_id(enum AVCodecID id) switch (id) { case AV_CODEC_ID_H264: return cudaVideoCodec_H264; case AV_CODEC_ID_HEVC: return cudaVideoCodec_HEVC; + case AV_CODEC_ID_MJPEG: return cudaVideoCodec_JPEG; case AV_CODEC_ID_MPEG1VIDEO: return cudaVideoCodec_MPEG1; case AV_CODEC_ID_MPEG2VIDEO: return cudaVideoCodec_MPEG2; case AV_CODEC_ID_MPEG4: return cudaVideoCodec_MPEG4; diff --git a/libavcodec/nvdec_mjpeg.c b/libavcodec/nvdec_mjpeg.c new file mode 100644 index 0000000000000..7e404246cec73 --- /dev/null +++ b/libavcodec/nvdec_mjpeg.c @@ -0,0 +1,86 @@ +/* + * MJPEG HW decode acceleration through NVDEC + * + * Copyright (c) 2017 Philip Langdale + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "internal.h" +#include "mjpegdec.h" +#include "nvdec.h" +#include "decode.h" + +static int nvdec_mjpeg_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + MJpegDecodeContext *s = avctx->priv_data; + + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + CUVIDPICPARAMS *pp = &ctx->pic_params; + FrameDecodeData *fdd; + NVDECFrame *cf; + AVFrame *cur_frame = s->picture; + + int ret; + + ret = ff_nvdec_start_frame(avctx, cur_frame); + if (ret < 0) + return ret; + + fdd = (FrameDecodeData*)cur_frame->private_ref->data; + cf = (NVDECFrame*)fdd->hwaccel_priv; + + *pp = (CUVIDPICPARAMS) { + .PicWidthInMbs = (cur_frame->width + 15) / 16, + .FrameHeightInMbs = (cur_frame->height + 15) / 16, + .CurrPicIdx = cf->idx, + + .intra_pic_flag = 1, + .ref_pic_flag = 0, + }; + + return ff_nvdec_simple_decode_slice(avctx, buffer, size); +} + +static int nvdec_mjpeg_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + return 0; +} + +static int nvdec_mjpeg_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) +{ + // Only need storage for the current frame + return ff_nvdec_frame_params(avctx, hw_frames_ctx, 1); +} + +#if CONFIG_MJPEG_NVDEC_HWACCEL +AVHWAccel ff_mjpeg_nvdec_hwaccel = { + .name = "mjpeg_nvdec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MJPEG, + .pix_fmt = AV_PIX_FMT_CUDA, + .start_frame = nvdec_mjpeg_start_frame, + .end_frame = ff_nvdec_simple_end_frame, + .decode_slice = nvdec_mjpeg_decode_slice, + .frame_params = nvdec_mjpeg_frame_params, + .init = ff_nvdec_decode_init, + .uninit = ff_nvdec_decode_uninit, + .priv_data_size = sizeof(NVDECContext), +}; +#endif diff --git a/libavcodec/version.h b/libavcodec/version.h index 3939c4f67aa94..97e475f9ce05a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 12 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MICRO 102 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From a246701e9abe8ef7cb9b0dd9fb5fa877e78334ef Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Thu, 15 Feb 2018 16:22:55 -0800 Subject: [PATCH 1938/2557] Parse and drop gain control data, so that SSR packets decode. This will result in poor quality audio for SSR streams, but they will at least demux and decode without error; partially fixing ticket #1693. This pulls in the decode_gain_control() function from the ffmpeg summer-of-code repo (original author Maxim Gavrilov) at svn://svn.mplayerhq.hu/soc/aac/aac.c with some minor modifications and adds AOT_AAC_SSR to decode_audio_specific_config_gb(). Signed-off-by: Dale Curtis Co-authored-by: Maxim Gavrilov --- libavcodec/aac.h | 2 ++ libavcodec/aacdec_template.c | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/libavcodec/aac.h b/libavcodec/aac.h index 4910c661d6197..05bc95385f231 100644 --- a/libavcodec/aac.h +++ b/libavcodec/aac.h @@ -357,6 +357,8 @@ struct AACContext { int warned_num_aac_frames; int warned_960_sbr; + int warned_gain_control; + /* aacdec functions pointers */ void (*imdct_and_windowing)(AACContext *ac, SingleChannelElement *sce); void (*apply_ltp)(AACContext *ac, SingleChannelElement *sce); diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c index c2d9802023aea..cf971810926ed 100644 --- a/libavcodec/aacdec_template.c +++ b/libavcodec/aacdec_template.c @@ -997,6 +997,7 @@ static int decode_audio_specific_config_gb(AACContext *ac, switch (m4ac->object_type) { case AOT_AAC_MAIN: case AOT_AAC_LC: + case AOT_AAC_SSR: case AOT_AAC_LTP: case AOT_ER_AAC_LC: case AOT_ER_AAC_LD: @@ -1967,6 +1968,33 @@ static void apply_prediction(AACContext *ac, SingleChannelElement *sce) reset_all_predictors(sce->predictor_state); } +static void decode_gain_control(SingleChannelElement * sce, GetBitContext * gb) +{ + // wd_num, wd_test, aloc_size + static const uint8_t gain_mode[4][3] = { + {1, 0, 5}, // ONLY_LONG_SEQUENCE = 0, + {2, 1, 2}, // LONG_START_SEQUENCE, + {8, 0, 2}, // EIGHT_SHORT_SEQUENCE, + {2, 1, 5}, // LONG_STOP_SEQUENCE + }; + + const int mode = sce->ics.window_sequence[0]; + uint8_t bd, wd, ad; + + // FIXME: Store the gain control data on |sce| and do something with it. + uint8_t max_band = get_bits(gb, 2); + for (bd = 0; bd < max_band; bd++) { + for (wd = 0; wd < gain_mode[mode][0]; wd++) { + uint8_t adjust_num = get_bits(gb, 3); + for (ad = 0; ad < adjust_num; ad++) { + skip_bits(gb, 4 + ((wd == 0 && gain_mode[mode][1]) + ? 4 + : gain_mode[mode][2])); + } + } + } +} + /** * Decode an individual_channel_stream payload; reference: table 4.44. * @@ -2034,9 +2062,11 @@ static int decode_ics(AACContext *ac, SingleChannelElement *sce, goto fail; } if (!eld_syntax && get_bits1(gb)) { - avpriv_request_sample(ac->avctx, "SSR"); - ret = AVERROR_PATCHWELCOME; - goto fail; + decode_gain_control(sce, gb); + if (!ac->warned_gain_control) { + avpriv_report_missing_feature(ac->avctx, "Gain control"); + ac->warned_gain_control = 1; + } } // I see no textual basis in the spec for this occurring after SSR gain // control, but this is what both reference and real implmentations do From aedbb3c72c97099a633c151b68d29b63c2a89339 Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Thu, 22 Feb 2018 08:53:03 +0100 Subject: [PATCH 1939/2557] doc/filters: add links to ffmpeg-utils and ffmpeg documentation Signed-off-by: Tobias Rapp --- doc/filters.texi | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 8a9b78d778b98..7908c51d48232 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1611,7 +1611,7 @@ The filter accepts the syntax [@var{sample_rate}:]@var{resampler_options}, where @var{sample_rate} expresses a sample rate and @var{resampler_options} is a list of @var{key}=@var{value} pairs, separated by ":". See the -@ref{Resampler Options,,the "Resampler Options" section in the +@ref{Resampler Options,,"Resampler Options" section in the ffmpeg-resampler(1) manual,ffmpeg-resampler} for the complete list of supported options. @@ -7449,7 +7449,7 @@ the input width and height. It defaults to 0. @item color, c Specify the color of the box to write. For the general syntax of this option, -check the "Color" section in the ffmpeg-utils manual. If the special +check the @ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. If the special value @code{invert} is used, the box edge color is the same as the video with inverted luma. @@ -7552,7 +7552,7 @@ framed. Default to 0. @item color, c Specify the color of the grid. For the general syntax of this option, -check the "Color" section in the ffmpeg-utils manual. If the special +check the @ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. If the special value @code{invert} is used, the grid color is the same as the video with inverted luma. @@ -7648,7 +7648,7 @@ The default value of @var{boxborderw} is 0. @item boxcolor The color to be used for drawing box around text. For the syntax of this -option, check the "Color" section in the ffmpeg-utils manual. +option, check the @ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. The default value of @var{boxcolor} is "white". @@ -7662,7 +7662,7 @@ The default value of @var{borderw} is 0. @item bordercolor Set the color to be used for drawing border around text. For the syntax of this -option, check the "Color" section in the ffmpeg-utils manual. +option, check the @ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. The default value of @var{bordercolor} is "black". @@ -7683,7 +7683,7 @@ If true, check and fix text coords to avoid clipping. @item fontcolor The color to be used for drawing fonts. For the syntax of this option, check -the "Color" section in the ffmpeg-utils manual. +the @ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. The default value of @var{fontcolor} is "black". @@ -7746,7 +7746,8 @@ libfreetype flags. @item shadowcolor The color to be used for drawing a shadow behind the drawn text. For the -syntax of this option, check the "Color" section in the ffmpeg-utils manual. +syntax of this option, check the @ref{color syntax,,"Color" section in the +ffmpeg-utils manual,ffmpeg-utils}. The default value of @var{shadowcolor} is "black". @@ -9322,8 +9323,9 @@ A '|'-separated list of parameters to pass to the frei0r effect. A frei0r effect parameter can be a boolean (its value is either "y" or "n"), a double, a color (specified as @var{R}/@var{G}/@var{B}, where @var{R}, @var{G}, and @var{B} are floating point -numbers between 0.0 and 1.0, inclusive) or by a color description specified in the "Color" -section in the ffmpeg-utils manual), a position (specified as @var{X}/@var{Y}, where +numbers between 0.0 and 1.0, inclusive) or a color description as specified in the +@ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}, +a position (specified as @var{X}/@var{Y}, where @var{X} and @var{Y} are floating point numbers) and/or a string. The number and types of parameters depend on the loaded effect. If an @@ -11881,7 +11883,8 @@ so the input image is centered on the padded area. @item color Specify the color of the padded area. For the syntax of this option, -check the "Color" section in the ffmpeg-utils manual. +check the @ref{color syntax,,"Color" section in the ffmpeg-utils +manual,ffmpeg-utils}. The default value of @var{color} is "black". @@ -13273,8 +13276,9 @@ it. Default value is 1. @item fillcolor, c Set the color used to fill the output area not covered by the rotated -image. For the general syntax of this option, check the "Color" section in the -ffmpeg-utils manual. If the special value "none" is selected then no +image. For the general syntax of this option, check the +@ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. +If the special value "none" is selected then no background is printed (useful for example if the background is never shown). Default value is "black". @@ -15156,8 +15160,8 @@ refer to the pad video filter. @item color Specify the color of the unused area. For the syntax of this option, check the -"Color" section in the ffmpeg-utils manual. The default value of @var{color} -is "black". +@ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. +The default value of @var{color} is "black". @item overlap Set the number of frames to overlap when tiling several successive frames together. @@ -17298,8 +17302,8 @@ Set frame rate, expressed as number of frames per second. Default value is "25". @item size, s -Set frame size. For the syntax of this option, check the "Video -size" section in the ffmpeg-utils manual. Default value is "640x480". +Set frame size. For the syntax of this option, check the @ref{video size syntax,,"Video +size" section in the ffmpeg-utils manual,ffmpeg-utils}. Default value is "640x480". @item start_scale Set the initial scale value. Default value is 3.0. @@ -17498,8 +17502,8 @@ used to represent a dead cell. @item mold_color Set mold color, for definitely dead and moldy cells. -For the syntax of these 3 color options, check the "Color" section in the -ffmpeg-utils manual. +For the syntax of these 3 color options, check the @ref{color syntax,,"Color" section in the +ffmpeg-utils manual,ffmpeg-utils}. @end table @subsection Examples @@ -17590,8 +17594,8 @@ coded on a @code{1/(N*N)} scale. @item color, c Specify the color of the source, only available in the @code{color} -source. For the syntax of this option, check the "Color" section in the -ffmpeg-utils manual. +source. For the syntax of this option, check the +@ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. @item size, s Specify the size of the sourced video. For the syntax of this option, check the @@ -20288,8 +20292,8 @@ postfix. The default value is "0". @item streams, s Specifies the streams to read. Several streams can be specified, separated by "+". The source will then have as many outputs, in the -same order. The syntax is explained in the ``Stream specifiers'' -section in the ffmpeg manual. Two special names, "dv" and "da" specify +same order. The syntax is explained in the @ref{Stream specifiers,,"Stream specifiers" +section in the ffmpeg manual,ffmpeg}. Two special names, "dv" and "da" specify respectively the default (best suited) video and audio stream. Default is "dv", or "da" if the filter is called as "amovie". From 8ca39b855a7b0e4d9f726fa9d285bc8edcb953e6 Mon Sep 17 00:00:00 2001 From: Ruiling Song Date: Mon, 12 Feb 2018 16:37:16 +0800 Subject: [PATCH 1940/2557] qsv: Default PicStruct to progressive The PicStruct is required by MediaSDK, so give a default value. hwupload does not work without this. Signed-off-by: Ruiling Song Signed-off-by: Luca Barbato --- libavutil/hwcontext_qsv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 9fa603c3502a0..73b5f2467c8e2 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -313,6 +313,7 @@ static int qsv_init_surface(AVHWFramesContext *ctx, mfxFrameSurface1 *surf) surf->Info.CropH = ctx->height; surf->Info.FrameRateExtN = 25; surf->Info.FrameRateExtD = 1; + surf->Info.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; return 0; } From ce8a12fb72271a6e4f50ffcb360e7fdac6eccdcb Mon Sep 17 00:00:00 2001 From: Nikolas Bowe Date: Fri, 16 Feb 2018 15:25:17 -0800 Subject: [PATCH 1941/2557] avformat/flvdec: Set broken_sizes for FlixEngine. we found some very old videos which suffered from corruption after 9e6a2427558a718be0c1fffacffd935f630a7a8d, but were fine before. These had "End of AC stream reached in vp6_parse_coeff" warnings in logs. These also had flv Packet mismatch warnings. Adding FlixEngine to the list of flv muxers which produce broken packet sizes fixes this corruption. FlixEngine is very old and not maintained or available anymore (since 2010), so we won't need to worry about newer versions fixing the issue. Signed-off-by: Michael Niedermayer --- libavformat/flvdec.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 0217cef8424eb..34c3e08bad23d 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -598,8 +598,10 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, if (version > 0 && version <= 655) flv->broken_sizes = 1; } - } else if (!strcmp(key, "metadatacreator") && !strcmp(str_val, "MEGA")) { - flv->broken_sizes = 1; + } else if (!strcmp(key, "metadatacreator")) { + if ( !strcmp (str_val, "MEGA") + || !strncmp(str_val, "FlixEngine", 10)) + flv->broken_sizes = 1; } } } From b6652f5100af48141dadcc45b087cf75eadc145e Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Thu, 22 Feb 2018 18:04:42 +0530 Subject: [PATCH 1942/2557] avutil/timecode: fix starting frame number for 59.94 fps The existing code for adjusting starting frame number assumes 29.97 as stream fps. Signed-off-by: Michael Niedermayer --- libavutil/timecode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/timecode.c b/libavutil/timecode.c index e9d8504ee7a68..60077ba0c0440 100644 --- a/libavutil/timecode.c +++ b/libavutil/timecode.c @@ -214,7 +214,7 @@ int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *st tc->start = (hh*3600 + mm*60 + ss) * tc->fps + ff; if (tc->flags & AV_TIMECODE_FLAG_DROPFRAME) { /* adjust frame number */ int tmins = 60*hh + mm; - tc->start -= 2 * (tmins - tmins/10); + tc->start -= (tc->fps == 30 ? 2 : 4) * (tmins - tmins/10); } return 0; } From dc40e64adb1712b1209c018914a44f809bc32664 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 23 Feb 2018 00:09:38 -0300 Subject: [PATCH 1943/2557] hvcc: zero initialize the nal buffers past the last written byte Bug-Id: 1116 Cc: libav-stable@libav.org Signed-off-by: James Almer --- libavformat/hevc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/hevc.c b/libavformat/hevc.c index f8bfeebd31130..1f8a7bb3c6d05 100644 --- a/libavformat/hevc.c +++ b/libavformat/hevc.c @@ -657,6 +657,8 @@ static uint8_t *nal_unit_extract_rbsp(const uint8_t *src, uint32_t src_len, while (i < src_len) dst[len++] = src[i++]; + memset(dst + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); + *dst_len = len; return dst; } From 85e6a33bdfddfc9532dc10079368649a23c2b6c4 Mon Sep 17 00:00:00 2001 From: Bela Bodecs Date: Mon, 19 Feb 2018 21:36:25 +0100 Subject: [PATCH 1944/2557] hlsenc: Fixing HLS_TEMP_FILE usage with HLS_SECOND_LEVEL_SEGMENT_... Currently using HLS_TEMP together with HLS_SECOND_LEVEL_SEGMENT_DURATION or HLS_SECOND_LEVEL_SEGMENT_SIZE gives error at end of each segment writing and the final segment file names do not contain the desired data. This patch fixes this bug by delaying the initilization of original segment filename after actual temp file renaming will skip the interfering. Signed-off-by: Bela Bodecs --- libavformat/hlsenc.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index cc13c94e9741a..ff064732a1d33 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -2168,13 +2168,9 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) if (vs->packets_written && can_split && av_compare_ts(pkt->pts - vs->start_pts, st->time_base, end_pts, AV_TIME_BASE_Q) >= 0) { int64_t new_start_pos; - char *old_filename = av_strdup(vs->avf->url); + char *old_filename = NULL; int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); - if (!old_filename) { - return AVERROR(ENOMEM); - } - av_write_frame(vs->avf, NULL); /* Flush any buffered data */ new_start_pos = avio_tell(vs->avf->pb); @@ -2215,17 +2211,21 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", vs->avf->url); - av_free(old_filename); return ret; } write_styp(vs->out); ret = flush_dynbuf(vs, &range_length); if (ret < 0) { - av_free(old_filename); return ret; } ff_format_io_close(s, &vs->out); } + + old_filename = av_strdup(vs->avf->url); + if (!old_filename) { + return AVERROR(ENOMEM); + } + ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size); vs->start_pos = new_start_pos; if (ret < 0) { @@ -2316,6 +2316,12 @@ static int hls_write_trailer(struct AVFormatContext *s) if ((hls->flags & HLS_TEMP_FILE) && oc->url[0]) { hls_rename_temp_file(s, oc); + av_free(old_filename); + old_filename = av_strdup(vs->avf->url); + + if (!old_filename) { + return AVERROR(ENOMEM); + } } /* after av_write_trailer, then duration + 1 duration per packet */ From 8720d3ffddbb3e03a72123322d67e12083c56c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20P=C3=B6schel?= Date: Tue, 20 Feb 2018 18:15:00 +0100 Subject: [PATCH 1945/2557] lavf/mpegts: add supplementary audio descriptor The supplementary audio descriptor is defined in ETSI EN 300 468 and provides more details regarding accessibility audio tracks, especially the normative annex J contains a detailed description of its use. Its language code (if present) overrides the language code of an also present ISO 639 language descriptor. Note that this also changes the priority of multiple descriptors with language from "the last descriptor with language within the ES loop" to "specific descriptor over general ISO 639 descriptor". Signed-off-by: Aman Gupta --- libavformat/mpegts.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 0a3ad05726447..bca7a7af4e80e 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -1840,7 +1840,9 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type } if (i && language[0]) { language[i - 1] = 0; - av_dict_set(&st->metadata, "language", language, 0); + /* don't overwrite language, as it may already have been set by + * another, more specific descriptor (e.g. supplementary audio) */ + av_dict_set(&st->metadata, "language", language, AV_DICT_DONT_OVERWRITE); } break; case 0x05: /* registration descriptor */ @@ -1895,6 +1897,39 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type st->internal->need_context_update = 1; } } + if (ext_desc_tag == 0x06) { /* supplementary audio descriptor */ + int flags; + + if (desc_len < 1) + return AVERROR_INVALIDDATA; + flags = get8(pp, desc_end); + + switch ((flags >> 2) & 0x1F) { /* editorial_classification */ + case 0x01: + st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; + break; + case 0x02: + st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; + break; + case 0x03: + st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; + break; + } + + if (flags & 0x01) { /* language_code_present */ + if (desc_len < 4) + return AVERROR_INVALIDDATA; + language[0] = get8(pp, desc_end); + language[1] = get8(pp, desc_end); + language[2] = get8(pp, desc_end); + language[3] = 0; + + /* This language always has to override a possible + * ISO 639 language descriptor language */ + if (language[0]) + av_dict_set(&st->metadata, "language", language, 0); + } + } break; default: break; From 61ecfbc32aa2a5d02bd90a298496bf1b6ecb0762 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 23 Feb 2018 13:38:20 -0800 Subject: [PATCH 1946/2557] avformat/dump: tag AV_DISPOSITION_DESCRIPTIONS streams Signed-off-by: Aman Gupta --- libavformat/dump.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/dump.c b/libavformat/dump.c index ef143fd4e2208..e20902ce8577e 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -547,6 +547,8 @@ static void dump_stream_format(AVFormatContext *ic, int i, av_log(NULL, AV_LOG_INFO, " (visual impaired)"); if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS) av_log(NULL, AV_LOG_INFO, " (clean effects)"); + if (st->disposition & AV_DISPOSITION_DESCRIPTIONS) + av_log(NULL, AV_LOG_INFO, " (descriptions)"); av_log(NULL, AV_LOG_INFO, "\n"); dump_metadata(NULL, st->metadata, " "); From 4f40d64e009869441ee63dad00b41e0a5bf7634d Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 23 Feb 2018 13:38:33 -0800 Subject: [PATCH 1947/2557] avformat/mpegts: set AV_DISPOSITION_DEPENDENT for mix_type=0 supplementary audio Signed-off-by: Aman Gupta --- fftools/ffmpeg.c | 1 + libavformat/avformat.h | 1 + libavformat/dump.c | 2 ++ libavformat/mpegts.c | 3 +++ 4 files changed, 7 insertions(+) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index a37de2ff98419..bea922b0aa580 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3592,6 +3592,7 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len) { "clean_effects" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS }, .unit = "flags" }, { "captions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS }, .unit = "flags" }, { "descriptions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, .unit = "flags" }, + { "dependent" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEPENDENT }, .unit = "flags" }, { "metadata" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA }, .unit = "flags" }, { NULL }, }; diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 4ea1b5ab727b3..a2fe7c6bb2caf 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -845,6 +845,7 @@ typedef struct AVStreamInternal AVStreamInternal; #define AV_DISPOSITION_CAPTIONS 0x10000 #define AV_DISPOSITION_DESCRIPTIONS 0x20000 #define AV_DISPOSITION_METADATA 0x40000 +#define AV_DISPOSITION_DEPENDENT 0x80000 ///< dependent audio stream (mix_type=0 in mpegts) /** * Options for behavior on timestamp wrap detection. diff --git a/libavformat/dump.c b/libavformat/dump.c index e20902ce8577e..942e62a581946 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -549,6 +549,8 @@ static void dump_stream_format(AVFormatContext *ic, int i, av_log(NULL, AV_LOG_INFO, " (clean effects)"); if (st->disposition & AV_DISPOSITION_DESCRIPTIONS) av_log(NULL, AV_LOG_INFO, " (descriptions)"); + if (st->disposition & AV_DISPOSITION_DEPENDENT) + av_log(NULL, AV_LOG_INFO, " (dependent)"); av_log(NULL, AV_LOG_INFO, "\n"); dump_metadata(NULL, st->metadata, " "); diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index bca7a7af4e80e..37a6aa8bffee7 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -1904,6 +1904,9 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type return AVERROR_INVALIDDATA; flags = get8(pp, desc_end); + if ((flags & 0x80) == 0) /* mix_type */ + st->disposition |= AV_DISPOSITION_DEPENDENT; + switch ((flags >> 2) & 0x1F) { /* editorial_classification */ case 0x01: st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; From 0419623cdca948cdd1fa3f9269e14881385a6796 Mon Sep 17 00:00:00 2001 From: Rodger Combs Date: Wed, 21 Feb 2018 22:01:51 -0600 Subject: [PATCH 1948/2557] lavfi/vf_transpose: fix regression with semiplanar formats (e.g. nv12) Regression since 7b19e76aeb0ace57b99aaef156bbfe592e43e65e --- libavfilter/vf_transpose.c | 50 ++++++++++++++----------- tests/ref/fate/filter-pixfmts-transpose | 8 ++-- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c index 3ff4cb424961b..74a4bbcf58b47 100644 --- a/libavfilter/vf_transpose.c +++ b/libavfilter/vf_transpose.c @@ -52,6 +52,14 @@ enum TransposeDir { TRANSPOSE_CLOCK_FLIP, }; +typedef struct TransVtable { + void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize, + uint8_t *dst, ptrdiff_t dst_linesize); + void (*transpose_block)(uint8_t *src, ptrdiff_t src_linesize, + uint8_t *dst, ptrdiff_t dst_linesize, + int w, int h); +} TransVtable; + typedef struct TransContext { const AVClass *class; int hsub, vsub; @@ -61,11 +69,7 @@ typedef struct TransContext { int passthrough; ///< PassthroughType, landscape passthrough mode enabled int dir; ///< TransposeDir - void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize, - uint8_t *dst, ptrdiff_t dst_linesize); - void (*transpose_block)(uint8_t *src, ptrdiff_t src_linesize, - uint8_t *dst, ptrdiff_t dst_linesize, - int w, int h); + TransVtable vtables[4]; } TransContext; static int query_formats(AVFilterContext *ctx) @@ -233,19 +237,22 @@ static int config_props_output(AVFilterLink *outlink) else outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; - switch (s->pixsteps[0]) { - case 1: s->transpose_block = transpose_block_8_c; - s->transpose_8x8 = transpose_8x8_8_c; break; - case 2: s->transpose_block = transpose_block_16_c; - s->transpose_8x8 = transpose_8x8_16_c; break; - case 3: s->transpose_block = transpose_block_24_c; - s->transpose_8x8 = transpose_8x8_24_c; break; - case 4: s->transpose_block = transpose_block_32_c; - s->transpose_8x8 = transpose_8x8_32_c; break; - case 6: s->transpose_block = transpose_block_48_c; - s->transpose_8x8 = transpose_8x8_48_c; break; - case 8: s->transpose_block = transpose_block_64_c; - s->transpose_8x8 = transpose_8x8_64_c; break; + for (int i = 0; i < 4; i++) { + TransVtable *v = &s->vtables[i]; + switch (s->pixsteps[i]) { + case 1: v->transpose_block = transpose_block_8_c; + v->transpose_8x8 = transpose_8x8_8_c; break; + case 2: v->transpose_block = transpose_block_16_c; + v->transpose_8x8 = transpose_8x8_16_c; break; + case 3: v->transpose_block = transpose_block_24_c; + v->transpose_8x8 = transpose_8x8_24_c; break; + case 4: v->transpose_block = transpose_block_32_c; + v->transpose_8x8 = transpose_8x8_32_c; break; + case 6: v->transpose_block = transpose_block_48_c; + v->transpose_8x8 = transpose_8x8_48_c; break; + case 8: v->transpose_block = transpose_block_64_c; + v->transpose_8x8 = transpose_8x8_64_c; break; + } } av_log(ctx, AV_LOG_VERBOSE, @@ -290,6 +297,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, uint8_t *dst, *src; int dstlinesize, srclinesize; int x, y; + TransVtable *v = &s->vtables[plane]; dstlinesize = out->linesize[plane]; dst = out->data[plane] + start * dstlinesize; @@ -308,20 +316,20 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, for (y = start; y < end - 7; y += 8) { for (x = 0; x < outw - 7; x += 8) { - s->transpose_8x8(src + x * srclinesize + y * pixstep, + v->transpose_8x8(src + x * srclinesize + y * pixstep, srclinesize, dst + (y - start) * dstlinesize + x * pixstep, dstlinesize); } if (outw - x > 0 && end - y > 0) - s->transpose_block(src + x * srclinesize + y * pixstep, + v->transpose_block(src + x * srclinesize + y * pixstep, srclinesize, dst + (y - start) * dstlinesize + x * pixstep, dstlinesize, outw - x, end - y); } if (end - y > 0) - s->transpose_block(src + 0 * srclinesize + y * pixstep, + v->transpose_block(src + 0 * srclinesize + y * pixstep, srclinesize, dst + (y - start) * dstlinesize + 0 * pixstep, dstlinesize, outw, end - y); diff --git a/tests/ref/fate/filter-pixfmts-transpose b/tests/ref/fate/filter-pixfmts-transpose index 6f25f3dd2752d..fcad28b9ff135 100644 --- a/tests/ref/fate/filter-pixfmts-transpose +++ b/tests/ref/fate/filter-pixfmts-transpose @@ -45,10 +45,10 @@ gray16be 4aef307021a91b1de67f1d4381a39132 gray16le 76f2afe156edca7ae05cfa4e5867126e gray9be 2c425fa532c940d226822da8b3592310 gray9le bcc575942910b3c72eaa72e8794f3acd -nv12 aca847644e5dc0e942419183014981a4 -nv21 098884e968d27286c8cf0d2fb1557dcd -p010be 5ff62dffa5dfdf823978c4f563f69c94 -p010le 20131abe34e084b04f1d169c66447825 +nv12 1965e3826144686748f2f6b516fca5ba +nv21 292adaf5271c5c8516b71640458c01f4 +p010be ad0de2cc9bff81688b182a870fcf7000 +p010le e7ff5143595021246733ce6bd0a769e8 rgb0 31ea5da7fe779c6ea0a33f1d28aad918 rgb24 47654cabaaad79170b90afd5a02161dd rgb444be 3cac1f0c43a74d2a95eb02e187070845 From 4f273b97b046762e9cf1f2f950448e7874c08e64 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 23 Feb 2018 21:52:42 -0300 Subject: [PATCH 1949/2557] avcodec/Makefile: add missing dependencies for some cuvid decoders Signed-off-by: James Almer --- libavcodec/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index c7a5692421904..4a815e1ef3042 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -416,6 +416,7 @@ OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpegenc_common.o \ mjpegenc_huffman.o OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o +OBJS-$(CONFIG_MJPEG_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MJPEG_QSV_ENCODER) += qsvenc_jpeg.o OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER) += vaapi_encode_mjpeg.o OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o @@ -443,16 +444,19 @@ OBJS-$(CONFIG_MPC8_DECODER) += mpc8.o mpc.o OBJS-$(CONFIG_MPEGVIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_MPEG1VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpeg12.o +OBJS-$(CONFIG_MPEG1_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MPEG1_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_MPEG2_MMAL_DECODER) += mmaldec.o OBJS-$(CONFIG_MPEG2_QSV_DECODER) += qsvdec_other.o OBJS-$(CONFIG_MPEG2_QSV_ENCODER) += qsvenc_mpeg2.o OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpeg12.o +OBJS-$(CONFIG_MPEG2_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MPEG2_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_MPEG2_VAAPI_ENCODER) += vaapi_encode_mpeg2.o OBJS-$(CONFIG_MPEG2_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_MPEG4_DECODER) += xvididct.o +OBJS-$(CONFIG_MPEG4_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MPEG4_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_MPEG4_OMX_ENCODER) += omx.o OBJS-$(CONFIG_MPEG4_V4L2M2M_DECODER) += v4l2_m2m_dec.o From 9482ec1b203e4cf51d7f60c85d261cc13f9a9d2f Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 23 Feb 2018 00:03:15 -0300 Subject: [PATCH 1950/2557] avformat/hvcc: zero initialize the nal buffers past the last written byte Prevents use of uninitialized values. Fixes ticket #7038. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/hevc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/hevc.c b/libavformat/hevc.c index e45d2c08d2ddb..3628d5a0282b7 100644 --- a/libavformat/hevc.c +++ b/libavformat/hevc.c @@ -669,6 +669,8 @@ static uint8_t *nal_unit_extract_rbsp(const uint8_t *src, uint32_t src_len, while (i < src_len) dst[len++] = src[i++]; + memset(dst + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); + *dst_len = len; return dst; } From b141902872bbe5d9389ee9f4fddbb87698c86689 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Fri, 23 Feb 2018 15:02:29 +0800 Subject: [PATCH 1951/2557] doc/bitstream_filters: documents delete_filler option. documents delete_filler option for bsf h264_metadata. Signed-off-by: Jun Zhao Signed-off-by: Michael Niedermayer --- doc/bitstream_filters.texi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 5efb8e0ee886c..cfd81fa12deca 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -153,6 +153,9 @@ possibly separated by hyphens, and the string can be anything. For example, @samp{086f3693-b7b3-4f2c-9653-21492feee5b8+hello} will insert the string ``hello'' associated with the given UUID. +@item delete_filler +Deletes both filler NAL units and filler SEI messages. + @end table @section h264_mp4toannexb From 0293663483ab5dbfff23602a62800d84e021b33c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 23 Feb 2018 03:40:02 +0100 Subject: [PATCH 1952/2557] avcodec/smc: Check input packet size Fixes: Timeout Fixes: 6261/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SMC_fuzzer-5811309653262336 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/smc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/smc.c b/libavcodec/smc.c index 79f9a757a0502..3cb48347378da 100644 --- a/libavcodec/smc.c +++ b/libavcodec/smc.c @@ -438,6 +438,10 @@ static int smc_decode_frame(AVCodecContext *avctx, int pal_size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size); int ret; + int total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4); + + if (total_blocks / 1024 > avpkt->size) + return AVERROR_INVALIDDATA; bytestream2_init(&s->gb, buf, buf_size); From 74afa545286bdb4b6fb1137209338cab00280f78 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Fri, 23 Feb 2018 15:58:10 +0800 Subject: [PATCH 1953/2557] ffmpeg_opt: fix max_error_rate help info display issue. ffmpeg -h display "max_error_rate" option help information have been cut off, the root cause is used a wrong initial order. Signed-off-by: Jun Zhao Signed-off-by: Michael Niedermayer --- fftools/ffmpeg_opt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 997d53838108c..1b591d9695ea5 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -3457,7 +3457,7 @@ const OptionDef options[] = { { "debug_ts", OPT_BOOL | OPT_EXPERT, { &debug_ts }, "print timestamp debugging info" }, { "max_error_rate", HAS_ARG | OPT_FLOAT, { &max_error_rate }, - "maximum error rate", "ratio of errors (0.0: no errors, 1.0: 100% errors) above which ffmpeg returns an error instead of success." }, + "ratio of errors (0.0: no errors, 1.0: 100% errors) above which ffmpeg returns an error instead of success.", "maximum error rate" }, { "discard", OPT_STRING | HAS_ARG | OPT_SPEC | OPT_INPUT, { .off = OFFSET(discard) }, "discard", "" }, From ffe7cc89d0ce352fd9e67283d6a949eaa98f46a4 Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Mon, 19 Feb 2018 11:25:25 +0530 Subject: [PATCH 1954/2557] avformat/dashenc: opening a segment file when its first frame is ready --- libavformat/dashenc.c | 57 +++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 0f6f4f22faf81..0eb4b25da1345 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -81,6 +81,9 @@ typedef struct OutputStream { char bandwidth_str[64]; char codec_str[100]; + char filename[1024]; + char full_path[1024]; + char temp_path[1024]; } OutputStream; typedef struct DASHContext { @@ -1134,7 +1137,6 @@ static int dash_flush(AVFormatContext *s, int final, int stream) for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; AVStream *st = s->streams[i]; - char filename[1024] = "", full_path[1024], temp_path[1024]; int range_length, index_length = 0; if (!os->packets_written) @@ -1152,24 +1154,11 @@ static int dash_flush(AVFormatContext *s, int final, int stream) continue; } - if (!os->init_range_length) { - flush_init_segment(s, os); - } - if (!c->single_file) { - AVDictionary *opts = NULL; - ff_dash_fill_tmpl_params(filename, sizeof(filename), c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts); - snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename); - snprintf(temp_path, sizeof(temp_path), use_rename ? "%s.tmp" : "%s", full_path); - set_http_options(&opts, c); - ret = dashenc_io_open(s, &os->out, temp_path, &opts); - if (ret < 0) - break; - av_dict_free(&opts); if (!strcmp(os->format_name, "mp4")) write_styp(os->ctx->pb); } else { - snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, os->initfile); + snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, os->initfile); } ret = flush_dynbuf(os, &range_length); @@ -1178,12 +1167,12 @@ static int dash_flush(AVFormatContext *s, int final, int stream) os->packets_written = 0; if (c->single_file) { - find_index_range(s, full_path, os->pos, &index_length); + find_index_range(s, os->full_path, os->pos, &index_length); } else { - dashenc_io_close(s, &os->out, temp_path); + dashenc_io_close(s, &os->out, os->temp_path); if (use_rename) { - ret = avpriv_io_move(temp_path, full_path); + ret = avpriv_io_move(os->temp_path, os->full_path); if (ret < 0) break; } @@ -1200,8 +1189,8 @@ static int dash_flush(AVFormatContext *s, int final, int stream) " bandwidth=\"%d\"", os->bit_rate); } } - add_segment(os, filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length); - av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, full_path); + add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length); + av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, os->full_path); os->pos += range_length; } @@ -1303,7 +1292,33 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) else os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration); os->packets_written++; - return ff_write_chained(os->ctx, 0, pkt, s, 0); + if ((ret = ff_write_chained(os->ctx, 0, pkt, s, 0)) < 0) + return ret; + + if (!os->init_range_length) + flush_init_segment(s, os); + + //open the output context when the first frame of a segment is ready + if (!c->single_file && !os->out) { + AVDictionary *opts = NULL; + const char *proto = avio_find_protocol_name(s->filename); + int use_rename = proto && !strcmp(proto, "file"); + os->filename[0] = os->full_path[0] = os->temp_path[0] = '\0'; + ff_dash_fill_tmpl_params(os->filename, sizeof(os->filename), + c->media_seg_name, pkt->stream_index, + os->segment_index, os->bit_rate, os->start_pts); + snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, + os->filename); + snprintf(os->temp_path, sizeof(os->temp_path), + use_rename ? "%s.tmp" : "%s", os->full_path); + set_http_options(&opts, c); + ret = dashenc_io_open(s, &os->out, os->temp_path, &opts); + if (ret < 0) + return ret; + av_dict_free(&opts); + } + + return ret; } static int dash_write_trailer(AVFormatContext *s) From 28924f4b488a2a22c2a1e41706fd97b6e484325c Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Mon, 19 Feb 2018 11:25:36 +0530 Subject: [PATCH 1955/2557] avformat/dashenc: chunk streaming support for low latency use cases --- doc/muxers.texi | 3 +++ libavformat/dashenc.c | 26 +++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index d9a5cc03dcb4e..c156ec0c87ba4 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -254,6 +254,9 @@ Use persistent HTTP connections. Applicable only for HTTP output. @item -hls_playlist @var{hls_playlist} Generate HLS playlist files as well. The master playlist is generated with the filename master.m3u8. One media playlist file is generated for each stream with filenames media_0.m3u8, media_1.m3u8, etc. +@item -streaming @var{streaming} +Enable (1) or disable (0) chunk streaming mode of output. In chunk streaming +mode, each frame will be a moof fragment which forms a chunk. @item -adaptation_sets @var{adaptation_sets} Assign streams to AdaptationSets. Syntax is "id=x,streams=a,b,c id=y,streams=d,e" with x and y being the IDs of the adaptation sets and a,b,c,d and e are the indices of the mapped streams. diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 0eb4b25da1345..d6474f3549fbd 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -81,6 +81,7 @@ typedef struct OutputStream { char bandwidth_str[64]; char codec_str[100]; + int written_len; char filename[1024]; char full_path[1024]; char temp_path[1024]; @@ -114,6 +115,7 @@ typedef struct DASHContext { int master_playlist_created; AVIOContext *mpd_out; AVIOContext *m3u8_out; + int streaming; } DASHContext; static struct codec_string { @@ -250,7 +252,8 @@ static int flush_dynbuf(OutputStream *os, int *range_length) // write out to file *range_length = avio_close_dyn_buf(os->ctx->pb, &buffer); os->ctx->pb = NULL; - avio_write(os->out, buffer, *range_length); + avio_write(os->out, buffer + os->written_len, *range_length - os->written_len); + os->written_len = 0; av_free(buffer); // re-open buffer @@ -960,7 +963,10 @@ static int dash_init(AVFormatContext *s) os->init_start_pos = 0; if (!strcmp(os->format_name, "mp4")) { - av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0); + if (c->streaming) + av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov", 0); + else + av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0); } else { av_dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000, 0); av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit @@ -1155,7 +1161,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) } if (!c->single_file) { - if (!strcmp(os->format_name, "mp4")) + if (!strcmp(os->format_name, "mp4") && !os->written_len) write_styp(os->ctx->pb); } else { snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, os->initfile); @@ -1318,6 +1324,19 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) av_dict_free(&opts); } + //write out the data immediately in streaming mode + if (c->streaming && !strcmp(os->format_name, "mp4")) { + int len = 0; + uint8_t *buf = NULL; + if (!os->written_len) + write_styp(os->ctx->pb); + avio_flush(os->ctx->pb); + len = avio_get_dyn_buf (os->ctx->pb, &buf); + avio_write(os->out, buf + os->written_len, len - os->written_len); + os->written_len = len; + avio_flush(os->out); + } + return ret; } @@ -1394,6 +1413,7 @@ static const AVOption options[] = { { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, + { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { NULL }, }; From f958f431eced497f42220d8f9890506215742512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Tue, 8 Aug 2017 15:27:27 +0200 Subject: [PATCH 1956/2557] Add libcodec2 en/decoder --- Changelog | 1 + configure | 5 + doc/general.texi | 20 ++++ libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 2 + libavcodec/avcodec.h | 1 + libavcodec/codec2utils.c | 80 +++++++++++++++ libavcodec/codec2utils.h | 82 +++++++++++++++ libavcodec/codec_desc.c | 7 ++ libavcodec/libcodec2.c | 213 +++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 4 +- 11 files changed, 415 insertions(+), 2 deletions(-) create mode 100644 libavcodec/codec2utils.c create mode 100644 libavcodec/codec2utils.h create mode 100644 libavcodec/libcodec2.c diff --git a/Changelog b/Changelog index f7afd2f9ed2c4..d726d119ea5d2 100644 --- a/Changelog +++ b/Changelog @@ -40,6 +40,7 @@ version : - VideoToolbox HEVC encoder and hwaccel - VAAPI-accelerated ProcAmp (color balance), denoise and sharpness filters - Add android_camera indev +- codec2 en/decoding via libcodec2 version 3.4: diff --git a/configure b/configure index d40718f8427a2..1bdb7c1c2def0 100755 --- a/configure +++ b/configure @@ -224,6 +224,7 @@ External library support: --enable-libcaca enable textual display using libcaca [no] --enable-libcelt enable CELT decoding via libcelt [no] --enable-libcdio enable audio CD grabbing with libcdio [no] + --enable-libcodec2 enable codec2 en/decoding using libcodec2 [no] --enable-libdc1394 enable IIDC-1394 grabbing using libdc1394 and libraw1394 [no] --enable-libfdk-aac enable AAC de/encoding via libfdk-aac [no] @@ -1603,6 +1604,7 @@ EXTERNAL_LIBRARY_LIST=" libbs2b libcaca libcelt + libcodec2 libdc1394 libdrm libflite @@ -2944,6 +2946,8 @@ h264_videotoolbox_encoder_select="videotoolbox_encoder" hevc_videotoolbox_encoder_deps="pthreads" hevc_videotoolbox_encoder_select="videotoolbox_encoder" libcelt_decoder_deps="libcelt" +libcodec2_decoder_deps="libcodec2" +libcodec2_encoder_deps="libcodec2" libfdk_aac_decoder_deps="libfdk_aac" libfdk_aac_encoder_deps="libfdk_aac" libfdk_aac_encoder_select="audio_frame_queue" @@ -5891,6 +5895,7 @@ enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && { check_lib libcelt celt/celt.h celt_decoder_create_custom -lcelt0 || die "ERROR: libcelt must be installed and version must be >= 0.11.0."; } enabled libcaca && require_pkg_config libcaca caca caca.h caca_create_canvas +enabled libcodec2 && require libcodec2 codec2/codec2.h codec2_create -lcodec2 enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new enabled libdrm && require_pkg_config libdrm libdrm xf86drm.h drmGetVersion enabled libfdk_aac && { check_pkg_config libfdk_aac fdk-aac "fdk-aac/aacenc_lib.h" aacEncOpen || diff --git a/doc/general.texi b/doc/general.texi index 9ddcccf041ea9..63722f272d622 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -85,6 +85,24 @@ Go to @url{http://www.twolame.org/} and follow the instructions for installing the library. Then pass @code{--enable-libtwolame} to configure to enable it. +@section libcodec2 / codec2 general + +FFmpeg can make use of libcodec2 for codec2 encoding and decoding. +There is currently no native decoder, so libcodec2 must be used for decoding. + +Go to @url{http://freedv.org/}, download "Codec 2 source archive". +Build and install using CMake. Debian users can install the libcodec2-dev package instead. +Once libcodec2 is installed you can pass @code{--enable-libcodec2} to configure to enable it. + +The easiest way to use codec2 is with .c2 files, since they contain the mode information required for decoding. +To encode such a file, use a .c2 file extension and give the libcodec2 encoder the -mode option: +@code{ffmpeg -i input.wav -mode 700C output.c2}. +Playback is as simple as @code{ffplay output.c2}. +For a list of supported modes, run @code{ffmpeg -h encoder=libcodec2}. +Raw codec2 files are also supported. +To make sense of them the mode in use needs to be specified as a format option: +@code{ffmpeg -f codec2raw -mode 1300 -i input.raw output.wav}. + @section libvpx FFmpeg can make use of the libvpx library for VP8/VP9 encoding. @@ -1019,6 +1037,8 @@ following image formats are supported: @tab Used in Bink and Smacker files in many games. @item CELT @tab @tab E @tab decoding supported through external library libcelt +@item codec2 @tab E @tab E + @tab en/decoding supported through external library libcodec2 @item Delphine Software International CIN audio @tab @tab X @tab Codec used in Delphine Software International games. @item Digital Speech Standard - Standard Play mode (DSS SP) @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 4a815e1ef3042..f09518b1977bc 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -935,6 +935,8 @@ OBJS-$(CONFIG_ILBC_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_PCM_ALAW_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o +OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o codec2utils.o +OBJS-$(CONFIG_LIBCODEC2_ENCODER) += libcodec2.o codec2utils.o OBJS-$(CONFIG_LIBFDK_AAC_DECODER) += libfdk-aacdec.o OBJS-$(CONFIG_LIBFDK_AAC_ENCODER) += libfdk-aacenc.o OBJS-$(CONFIG_LIBGSM_DECODER) += libgsmdec.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 774b78ef097d6..70cbb7da0c86f 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -662,6 +662,8 @@ extern AVCodec ff_pcm_mulaw_at_decoder; extern AVCodec ff_qdmc_at_decoder; extern AVCodec ff_qdm2_at_decoder; extern AVCodec ff_libcelt_decoder; +extern AVCodec ff_libcodec2_encoder; +extern AVCodec ff_libcodec2_decoder; extern AVCodec ff_libfdk_aac_encoder; extern AVCodec ff_libfdk_aac_decoder; extern AVCodec ff_libgsm_encoder; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 74c7b9dadd939..1060ac453b474 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -615,6 +615,7 @@ enum AVCodecID { AV_CODEC_ID_PAF_AUDIO, AV_CODEC_ID_ON2AVC, AV_CODEC_ID_DSS_SP, + AV_CODEC_ID_CODEC2, AV_CODEC_ID_FFWAVESYNTH = 0x15800, AV_CODEC_ID_SONIC, diff --git a/libavcodec/codec2utils.c b/libavcodec/codec2utils.c new file mode 100644 index 0000000000000..931478f22a3e1 --- /dev/null +++ b/libavcodec/codec2utils.c @@ -0,0 +1,80 @@ +/* + * codec2 utility functions + * Copyright (c) 2017 Tomas Härdin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "internal.h" +#include "libavcodec/codec2utils.h" + +int avpriv_codec2_mode_bit_rate(void *logctx, int mode) +{ + int frame_size = avpriv_codec2_mode_frame_size(logctx, mode); + int block_align = avpriv_codec2_mode_block_align(logctx, mode); + + if (frame_size <= 0 || block_align <= 0) { + return 0; + } + + return 8 * 8000 * block_align / frame_size; +} + +int avpriv_codec2_mode_frame_size(void *logctx, int mode) +{ + int frame_size_table[AVPRIV_CODEC2_MODE_MAX+1] = { + 160, // 3200 + 160, // 2400 + 320, // 1600 + 320, // 1400 + 320, // 1300 + 320, // 1200 + 320, // 700 + 320, // 700B + 320, // 700C + }; + + if (mode < 0 || mode > AVPRIV_CODEC2_MODE_MAX) { + av_log(logctx, AV_LOG_ERROR, "unknown codec2 mode %i, can't find frame_size\n", mode); + return 0; + } else { + return frame_size_table[mode]; + } +} + +int avpriv_codec2_mode_block_align(void *logctx, int mode) +{ + int block_align_table[AVPRIV_CODEC2_MODE_MAX+1] = { + 8, // 3200 + 6, // 2400 + 8, // 1600 + 7, // 1400 + 7, // 1300 + 6, // 1200 + 4, // 700 + 4, // 700B + 4, // 700C + }; + + if (mode < 0 || mode > AVPRIV_CODEC2_MODE_MAX) { + av_log(logctx, AV_LOG_ERROR, "unknown codec2 mode %i, can't find block_align\n", mode); + return 0; + } else { + return block_align_table[mode]; + } +} diff --git a/libavcodec/codec2utils.h b/libavcodec/codec2utils.h new file mode 100644 index 0000000000000..6def4d4aa3958 --- /dev/null +++ b/libavcodec/codec2utils.h @@ -0,0 +1,82 @@ +/* + * codec2 utility functions + * Copyright (c) 2017 Tomas Härdin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC2UTILS_H +#define AVCODEC_CODEC2UTILS_H + +#include + +//Highest mode we're willing to use. +//Don't want to let users accidentally produce files that can't be decoded in the future. +//CODEC2_MODE_WB (9) is experimental/unstable as of 2017-11-23. +#define AVPRIV_CODEC2_MODE_MAX 8 //CODEC2_MODE_700C + +//Used by both codec2raw demuxer and libcodec2 encoder. +//The integers match the values in codec2.h, so "3200" -> CODEC2_MODE_3000 = 0 and so on. +//It is possible that we're linked to a version of libcodec2 that lacks some of these modes. +//For example Debian stretch ships with libcodec2.so.0.4 which lacks CODEC2_MODE_700C. +#define AVPRIV_CODEC2_AVOPTIONS(desc, classname, min_val, default_val, option_flags) \ + { "mode", desc, offsetof(classname, mode), AV_OPT_TYPE_INT, {.i64 = default_val}, min_val, AVPRIV_CODEC2_MODE_MAX, .flags=option_flags, .unit="codec2_mode"},\ + { "3200", "3200", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, .flags=option_flags, .unit="codec2_mode"},\ + { "2400", "2400", 0, AV_OPT_TYPE_CONST, {.i64 = 1}, .flags=option_flags, .unit="codec2_mode"},\ + { "1600", "1600", 0, AV_OPT_TYPE_CONST, {.i64 = 2}, .flags=option_flags, .unit="codec2_mode"},\ + { "1400", "1400", 0, AV_OPT_TYPE_CONST, {.i64 = 3}, .flags=option_flags, .unit="codec2_mode"},\ + { "1300", "1300", 0, AV_OPT_TYPE_CONST, {.i64 = 4}, .flags=option_flags, .unit="codec2_mode"},\ + { "1200", "1200", 0, AV_OPT_TYPE_CONST, {.i64 = 5}, .flags=option_flags, .unit="codec2_mode"},\ + { "700", "700", 0, AV_OPT_TYPE_CONST, {.i64 = 6}, .flags=option_flags, .unit="codec2_mode"},\ + { "700B", "700B", 0, AV_OPT_TYPE_CONST, {.i64 = 7}, .flags=option_flags, .unit="codec2_mode"},\ + { "700C", "700C", 0, AV_OPT_TYPE_CONST, {.i64 = 8}, .flags=option_flags, .unit="codec2_mode"} + +//The three following functions are here to avoid needing libavformat/codec2.c to depend on libcodec2 + +//Computes bitrate from mode, with frames rounded up to the nearest octet. +//So 700 bit/s (28 bits/frame) becomes 800 bits/s (32 bits/frame). +//logctx is used for av_log() +//Returns <0 if mode is invalid +int avpriv_codec2_mode_bit_rate(void *logctx, int mode); + +//Mimics codec2_samples_per_frame() +int avpriv_codec2_mode_frame_size(void *logctx, int mode); + +//Mimics (codec2_bits_per_frame()+7)/8 +int avpriv_codec2_mode_block_align(void *logctx, int mode); + +#define AVPRIV_CODEC2_EXTRADATA_SIZE 4 + +//Used in codec2raw demuxer and libcodec2 encoder +static inline void avpriv_codec2_make_extradata(uint8_t *ptr, int mode) { + //version 0.8 as of 2017-12-23 (r3386) + ptr[0] = 0; //major + ptr[1] = 8; //minor + ptr[2] = mode; //mode + ptr[3] = 0; //flags +} + +//Returns version as a 16-bit value. 0.8 -> 0x0008 +static inline uint16_t avpriv_codec2_version_from_extradata(uint8_t *ptr) { + return (ptr[0] << 8) + ptr[1]; +} + +static inline uint8_t avpriv_codec2_mode_from_extradata(uint8_t *ptr) { + return ptr[2]; +} + +#endif /* AVCODEC_CODEC2UTILS_H */ diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 44a54a31c94bf..f1ba6b13ac4a9 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2733,6 +2733,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard - Standard Play mode (DSS SP)"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_CODEC2, + .type = AVMEDIA_TYPE_AUDIO, + .name = "codec2", + .long_name = NULL_IF_CONFIG_SMALL("codec2 (very low bitrate speech codec)"), + .props = AV_CODEC_PROP_LOSSY, + }, { .id = AV_CODEC_ID_FFWAVESYNTH, .type = AVMEDIA_TYPE_AUDIO, diff --git a/libavcodec/libcodec2.c b/libavcodec/libcodec2.c new file mode 100644 index 0000000000000..1d6bed03833ea --- /dev/null +++ b/libavcodec/libcodec2.c @@ -0,0 +1,213 @@ +/* + * codec2 encoder/decoder using libcodec2 + * Copyright (c) 2017 Tomas Härdin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "avcodec.h" +#include "libavutil/opt.h" +#include "internal.h" +#include "codec2utils.h" + +typedef struct { + const AVClass *class; + struct CODEC2 *codec; + int mode; +} LibCodec2Context; + +static const AVOption options[] = { + //not AV_OPT_FLAG_DECODING_PARAM since mode should come from the demuxer + //1300 (aka FreeDV 1600) is the most common mode on-the-air, default to it here as well + AVPRIV_CODEC2_AVOPTIONS("codec2 mode", LibCodec2Context, 0, 4 /*CODEC2_MODE_1300*/, AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_ENCODING_PARAM), + { NULL }, +}; + +static const AVClass libcodec2_enc_class = { + .class_name = "libcodec2 encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVClass libcodec2_dec_class = { + .class_name = "libcodec2 decoder", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, +}; + +static av_cold int libcodec2_init_common(AVCodecContext *avctx, int mode) +{ + LibCodec2Context *c2 = avctx->priv_data; + //Grab mode name from options, unless it's some weird number. + const char *modename = mode >= 0 && mode <= AVPRIV_CODEC2_MODE_MAX ? options[mode+1].name : "?"; + + c2->codec = codec2_create(mode); + if (!c2->codec) { + //Out of memory or unsupported mode. The latter seems most likely, + //but we can't tell for sure with the current API. + goto libcodec2_init_common_error; + } + + avctx->frame_size = codec2_samples_per_frame(c2->codec); + avctx->block_align = (codec2_bits_per_frame(c2->codec) + 7) / 8; + + if (avctx->frame_size <= 0 || avctx->block_align <= 0) { + //codec2_create() may succeed for some modes but still fail at codec2_samples_per_frame() + //example is -mode 700C on libcodec2 0.4 + codec2_destroy(c2->codec); + c2->codec = NULL; + goto libcodec2_init_common_error; + } + + codec2_set_natural_or_gray(c2->codec, 1); + + return 0; + +libcodec2_init_common_error: + av_log(avctx, AV_LOG_ERROR, + "Mode %i (%s) not supported with the linked version of libcodec2\n", + mode, modename); + return AVERROR(EINVAL); +} + +static av_cold int libcodec2_init_decoder(AVCodecContext *avctx) +{ + avctx->sample_rate = 8000; + avctx->channels = 1; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + + if (avctx->extradata_size != AVPRIV_CODEC2_EXTRADATA_SIZE) { + av_log(avctx, AV_LOG_ERROR, "must have exactly %i bytes of extradata (got %i)\n", + AVPRIV_CODEC2_EXTRADATA_SIZE, avctx->extradata_size); + return AVERROR_INVALIDDATA; + } + + return libcodec2_init_common(avctx, avpriv_codec2_mode_from_extradata(avctx->extradata)); +} + +static av_cold int libcodec2_init_encoder(AVCodecContext *avctx) +{ + LibCodec2Context *c2 = avctx->priv_data; + + //will need to be smarter once we get wideband support + if (avctx->sample_rate != 8000 || + avctx->channels != 1 || + avctx->sample_fmt != AV_SAMPLE_FMT_S16) { + av_log(avctx, AV_LOG_ERROR, "only 8 kHz 16-bit mono allowed\n"); + return AVERROR(EINVAL); + } + + avctx->extradata = av_mallocz(AVPRIV_CODEC2_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + return AVERROR(ENOMEM); + } + + avctx->extradata_size = AVPRIV_CODEC2_EXTRADATA_SIZE; + avpriv_codec2_make_extradata(avctx->extradata, c2->mode); + + return libcodec2_init_common(avctx, c2->mode); +} + +static av_cold int libcodec2_close(AVCodecContext *avctx) +{ + LibCodec2Context *c2 = avctx->priv_data; + + codec2_destroy(c2->codec); + return 0; +} + +static int libcodec2_decode(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *pkt) +{ + LibCodec2Context *c2 = avctx->priv_data; + AVFrame *frame = data; + int ret, nframes, i; + uint8_t *input; + int16_t *output; + + nframes = pkt->size / avctx->block_align; + frame->nb_samples = avctx->frame_size * nframes; + + ret = ff_get_buffer(avctx, frame, 0); + if (ret < 0) { + return ret; + } + + input = pkt->data; + output = (int16_t *)frame->data[0]; + + for (i = 0; i < nframes; i++) { + codec2_decode(c2->codec, output, input); + input += avctx->block_align; + output += avctx->frame_size; + } + + *got_frame_ptr = nframes > 0; + return nframes * avctx->block_align; +} + +static int libcodec2_encode(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + LibCodec2Context *c2 = avctx->priv_data; + int16_t *samples = (int16_t *)frame->data[0]; + + int ret = ff_alloc_packet2(avctx, avpkt, avctx->block_align, 0); + if (ret < 0) { + return ret; + } + + codec2_encode(c2->codec, avpkt->data, samples); + *got_packet_ptr = 1; + + return 0; +} + +AVCodec ff_libcodec2_decoder = { + .name = "libcodec2", + .long_name = NULL_IF_CONFIG_SMALL("codec2 decoder using libcodec2"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_CODEC2, + .priv_data_size = sizeof(LibCodec2Context), + .init = libcodec2_init_decoder, + .close = libcodec2_close, + .decode = libcodec2_decode, + .capabilities = 0, + .supported_samplerates = (const int[]){ 8000, 0 }, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 }, + .priv_class = &libcodec2_dec_class, +}; + +AVCodec ff_libcodec2_encoder = { + .name = "libcodec2", + .long_name = NULL_IF_CONFIG_SMALL("codec2 encoder using libcodec2"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_CODEC2, + .priv_data_size = sizeof(LibCodec2Context), + .init = libcodec2_init_encoder, + .close = libcodec2_close, + .encode2 = libcodec2_encode, + .capabilities = 0, + .supported_samplerates = (const int[]){ 8000, 0 }, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 }, + .priv_class = &libcodec2_enc_class, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 97e475f9ce05a..ca18ce6e8bf73 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 12 -#define LIBAVCODEC_VERSION_MICRO 102 +#define LIBAVCODEC_VERSION_MINOR 13 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 5655048c73f7c737f44f63e0c0d2b60abe4b9d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Tue, 8 Aug 2017 15:28:06 +0200 Subject: [PATCH 1957/2557] Add muxer/demuxer for raw codec2 and .c2 files --- Changelog | 1 + doc/general.texi | 4 + libavformat/Makefile | 4 + libavformat/allformats.c | 4 + libavformat/codec2.c | 285 +++++++++++++++++++++++++++++++++++++++ libavformat/rawenc.c | 13 ++ libavformat/utils.c | 1 + libavformat/version.h | 2 +- 8 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 libavformat/codec2.c diff --git a/Changelog b/Changelog index d726d119ea5d2..499413f30673d 100644 --- a/Changelog +++ b/Changelog @@ -41,6 +41,7 @@ version : - VAAPI-accelerated ProcAmp (color balance), denoise and sharpness filters - Add android_camera indev - codec2 en/decoding via libcodec2 +- muxer/demuxer for raw codec2 files and .c2 files version 3.4: diff --git a/doc/general.texi b/doc/general.texi index 63722f272d622..63aed348082db 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -320,6 +320,10 @@ library: @item BRSTM @tab @tab X @tab Audio format used on the Nintendo Wii. @item BWF @tab X @tab X +@item codec2 (raw) @tab X @tab X + @tab Must be given -mode format option to decode correctly. +@item codec2 (.c2 files) @tab X @tab X + @tab Contains header with version and mode info, simplifying playback. @item CRI ADX @tab X @tab X @tab Audio-only format used in console video games. @item Discworld II BMV @tab @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index 7ac1ba95ad47f..d90766e201971 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -133,6 +133,10 @@ OBJS-$(CONFIG_CAVSVIDEO_MUXER) += rawenc.o OBJS-$(CONFIG_CDG_DEMUXER) += cdg.o OBJS-$(CONFIG_CDXL_DEMUXER) += cdxl.o OBJS-$(CONFIG_CINE_DEMUXER) += cinedec.o +OBJS-$(CONFIG_CODEC2_DEMUXER) += ../libavcodec/codec2utils.o codec2.o rawdec.o pcm.o +OBJS-$(CONFIG_CODEC2_MUXER) += ../libavcodec/codec2utils.o codec2.o rawenc.o +OBJS-$(CONFIG_CODEC2RAW_DEMUXER) += ../libavcodec/codec2utils.o codec2.o rawdec.o pcm.o +OBJS-$(CONFIG_CODEC2RAW_MUXER) += rawenc.o OBJS-$(CONFIG_CONCAT_DEMUXER) += concatdec.o OBJS-$(CONFIG_CRC_MUXER) += crcenc.o OBJS-$(CONFIG_DATA_DEMUXER) += rawdec.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index e75cd917e44a9..662e5054160a3 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -96,6 +96,10 @@ extern AVOutputFormat ff_cavsvideo_muxer; extern AVInputFormat ff_cdg_demuxer; extern AVInputFormat ff_cdxl_demuxer; extern AVInputFormat ff_cine_demuxer; +extern AVInputFormat ff_codec2_demuxer; +extern AVOutputFormat ff_codec2_muxer; +extern AVInputFormat ff_codec2raw_demuxer; +extern AVOutputFormat ff_codec2raw_muxer; extern AVInputFormat ff_concat_demuxer; extern AVOutputFormat ff_crc_muxer; extern AVInputFormat ff_dash_demuxer; diff --git a/libavformat/codec2.c b/libavformat/codec2.c new file mode 100644 index 0000000000000..28dbbd8176f44 --- /dev/null +++ b/libavformat/codec2.c @@ -0,0 +1,285 @@ +/* + * codec2 muxer and demuxers + * Copyright (c) 2017 Tomas Härdin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "libavcodec/codec2utils.h" +#include "libavutil/intreadwrite.h" +#include "avio_internal.h" +#include "avformat.h" +#include "internal.h" +#include "rawdec.h" +#include "rawenc.h" +#include "pcm.h" + +#define AVPRIV_CODEC2_HEADER_SIZE 7 +#define AVPRIV_CODEC2_MAGIC 0xC0DEC2 + +//the lowest version we should ever run across is 0.8 +//we may run across later versions as the format evolves +#define EXPECTED_CODEC2_MAJOR_VERSION 0 +#define EXPECTED_CODEC2_MINOR_VERSION 8 + +typedef struct { + const AVClass *class; + int mode; + int frames_per_packet; +} Codec2Context; + +static int codec2_probe(AVProbeData *p) +{ + //must start wih C0 DE C2 + if (AV_RB24(p->buf) != AVPRIV_CODEC2_MAGIC) { + return 0; + } + + //no .c2 files prior to 0.8 + //be strict about major version while we're at it + if (p->buf[3] != EXPECTED_CODEC2_MAJOR_VERSION || + p->buf[4] < EXPECTED_CODEC2_MINOR_VERSION) { + return 0; + } + + //32 bits of identification -> low score + return AVPROBE_SCORE_EXTENSION + 1; +} + +static int codec2_read_header_common(AVFormatContext *s, AVStream *st) +{ + int mode = avpriv_codec2_mode_from_extradata(st->codecpar->extradata); + + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_CODEC2; + st->codecpar->sample_rate = 8000; + st->codecpar->channels = 1; + st->codecpar->format = AV_SAMPLE_FMT_S16; + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->bit_rate = avpriv_codec2_mode_bit_rate(s, mode); + st->codecpar->frame_size = avpriv_codec2_mode_frame_size(s, mode); + st->codecpar->block_align = avpriv_codec2_mode_block_align(s, mode); + + if (st->codecpar->bit_rate <= 0 || + st->codecpar->frame_size <= 0 || + st->codecpar->block_align <= 0) { + return AVERROR_INVALIDDATA; + } + + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); + + return 0; +} + +static int codec2_read_header(AVFormatContext *s) +{ + AVStream *st = avformat_new_stream(s, NULL); + int ret, version; + + if (!st) { + return AVERROR(ENOMEM); + } + + if (avio_rb24(s->pb) != AVPRIV_CODEC2_MAGIC) { + av_log(s, AV_LOG_ERROR, "not a .c2 file\n"); + return AVERROR_INVALIDDATA; + } + + ret = ff_alloc_extradata(st->codecpar, AVPRIV_CODEC2_EXTRADATA_SIZE); + if (ret) { + return ret; + } + + ret = ffio_read_size(s->pb, st->codecpar->extradata, AVPRIV_CODEC2_EXTRADATA_SIZE); + if (ret < 0) { + return ret; + } + + version = avpriv_codec2_version_from_extradata(st->codecpar->extradata); + if ((version >> 8) != EXPECTED_CODEC2_MAJOR_VERSION) { + avpriv_report_missing_feature(s, "Major version %i", version >> 8); + return AVERROR_PATCHWELCOME; + } + + s->internal->data_offset = AVPRIV_CODEC2_HEADER_SIZE; + + return codec2_read_header_common(s, st); +} + +static int codec2_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + Codec2Context *c2 = s->priv_data; + AVStream *st = s->streams[0]; + int ret, size, n, block_align, frame_size; + + block_align = st->codecpar->block_align; + frame_size = st->codecpar->frame_size; + + if (block_align <= 0 || frame_size <= 0 || c2->frames_per_packet <= 0) { + return AVERROR(EINVAL); + } + + //try to read desired number of frames, compute n from to actual number of bytes read + size = c2->frames_per_packet * block_align; + ret = av_get_packet(s->pb, pkt, size); + if (ret < 0) { + return ret; + } + + //only set duration - compute_pkt_fields() and ff_pcm_read_seek() takes care of everything else + //tested by spamming the seek functionality in ffplay + n = ret / block_align; + pkt->duration = n * frame_size; + + return ret; +} + +static int codec2_write_header(AVFormatContext *s) +{ + AVStream *st; + + if (s->nb_streams != 1 || s->streams[0]->codecpar->codec_id != AV_CODEC_ID_CODEC2) { + av_log(s, AV_LOG_ERROR, ".c2 files must have exactly one codec2 stream\n"); + return AVERROR(EINVAL); + } + + st = s->streams[0]; + + if (st->codecpar->extradata_size != AVPRIV_CODEC2_EXTRADATA_SIZE) { + av_log(s, AV_LOG_ERROR, ".c2 files require exactly %i bytes of extradata (got %i)\n", + AVPRIV_CODEC2_EXTRADATA_SIZE, st->codecpar->extradata_size); + return AVERROR(EINVAL); + } + + avio_wb24(s->pb, AVPRIV_CODEC2_MAGIC); + avio_write(s->pb, st->codecpar->extradata, AVPRIV_CODEC2_EXTRADATA_SIZE); + + return 0; +} + +static int codec2raw_read_header(AVFormatContext *s) +{ + Codec2Context *c2 = s->priv_data; + AVStream *st; + int ret; + + if (c2->mode < 0) { + //FIXME: using a default value of -1 for mandatory options is an incredibly ugly hack + av_log(s, AV_LOG_ERROR, "-mode must be set in order to make sense of raw codec2 files\n"); + return AVERROR(EINVAL); + } + + st = avformat_new_stream(s, NULL); + if (!st) { + return AVERROR(ENOMEM); + } + + ret = ff_alloc_extradata(st->codecpar, AVPRIV_CODEC2_EXTRADATA_SIZE); + if (ret) { + return ret; + } + + s->internal->data_offset = 0; + avpriv_codec2_make_extradata(st->codecpar->extradata, c2->mode); + + return codec2_read_header_common(s, st); +} + +//transcoding report2074.c2 to wav went from 7.391s to 5.322s with -frames_per_packet 1000 compared to default, same sha1sum +#define FRAMES_PER_PACKET \ + { "frames_per_packet", "Number of frames to read at a time. Higher = faster decoding, lower granularity", \ + offsetof(Codec2Context, frames_per_packet), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM} + +static const AVOption codec2_options[] = { + FRAMES_PER_PACKET, + { NULL }, +}; + +static const AVOption codec2raw_options[] = { + AVPRIV_CODEC2_AVOPTIONS("codec2 mode [mandatory]", Codec2Context, -1, -1, AV_OPT_FLAG_DECODING_PARAM), + FRAMES_PER_PACKET, + { NULL }, +}; + +static const AVClass codec2_mux_class = { + .class_name = "codec2 muxer", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEMUXER, +}; + +static const AVClass codec2_demux_class = { + .class_name = "codec2 demuxer", + .item_name = av_default_item_name, + .option = codec2_options, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEMUXER, +}; + +static const AVClass codec2raw_demux_class = { + .class_name = "codec2raw demuxer", + .item_name = av_default_item_name, + .option = codec2raw_options, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEMUXER, +}; + +#if CONFIG_CODEC2_DEMUXER +AVInputFormat ff_codec2_demuxer = { + .name = "codec2", + .long_name = NULL_IF_CONFIG_SMALL("codec2 .c2 demuxer"), + .priv_data_size = sizeof(Codec2Context), + .extensions = "c2", + .read_probe = codec2_probe, + .read_header = codec2_read_header, + .read_packet = codec2_read_packet, + .read_seek = ff_pcm_read_seek, + .flags = AVFMT_GENERIC_INDEX, + .raw_codec_id = AV_CODEC_ID_CODEC2, + .priv_class = &codec2_demux_class, +}; +#endif + +#if CONFIG_CODEC2_MUXER +AVOutputFormat ff_codec2_muxer = { + .name = "codec2", + .long_name = NULL_IF_CONFIG_SMALL("codec2 .c2 muxer"), + .priv_data_size = sizeof(Codec2Context), + .extensions = "c2", + .audio_codec = AV_CODEC_ID_CODEC2, + .video_codec = AV_CODEC_ID_NONE, + .write_header = codec2_write_header, + .write_packet = ff_raw_write_packet, + .flags = AVFMT_NOTIMESTAMPS, + .priv_class = &codec2_mux_class, +}; +#endif + +#if CONFIG_CODEC2RAW_DEMUXER +AVInputFormat ff_codec2raw_demuxer = { + .name = "codec2raw", + .long_name = NULL_IF_CONFIG_SMALL("raw codec2 demuxer"), + .priv_data_size = sizeof(Codec2Context), + .read_header = codec2raw_read_header, + .read_packet = codec2_read_packet, + .read_seek = ff_pcm_read_seek, + .flags = AVFMT_GENERIC_INDEX, + .raw_codec_id = AV_CODEC_ID_CODEC2, + .priv_class = &codec2raw_demux_class, +}; +#endif diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index dcf880d17e0e7..fcfbfbce8ea2e 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -130,6 +130,19 @@ AVOutputFormat ff_cavsvideo_muxer = { }; #endif +#if CONFIG_CODEC2RAW_MUXER +AVOutputFormat ff_codec2raw_muxer = { + .name = "codec2raw", + .long_name = NULL_IF_CONFIG_SMALL("raw codec2 muxer"), + .audio_codec = AV_CODEC_ID_CODEC2, + .video_codec = AV_CODEC_ID_NONE, + .write_header = force_one_stream, + .write_packet = ff_raw_write_packet, + .flags = AVFMT_NOTIMESTAMPS, +}; +#endif + + #if CONFIG_DATA_MUXER AVOutputFormat ff_data_muxer = { .name = "data", diff --git a/libavformat/utils.c b/libavformat/utils.c index 28ea0714091c6..2c2ea876b6133 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -933,6 +933,7 @@ static int determinable_frame_size(AVCodecContext *avctx) case AV_CODEC_ID_MP1: case AV_CODEC_ID_MP2: case AV_CODEC_ID_MP3: + case AV_CODEC_ID_CODEC2: return 1; } diff --git a/libavformat/version.h b/libavformat/version.h index 009f981095377..e28a9e7dfec52 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 9 +#define LIBAVFORMAT_VERSION_MINOR 10 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From 5caae279799893e9ecd7646433262a07e0dfca75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Thu, 3 Aug 2017 17:33:04 +0200 Subject: [PATCH 1958/2557] Don't complain about codec2's 700 bit/s modes in ffmpeg.c --- fftools/ffmpeg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index bea922b0aa580..32caa4bfb29ed 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3502,7 +3502,8 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len) av_buffersink_set_frame_size(ost->filter->filter, ost->enc_ctx->frame_size); assert_avoptions(ost->encoder_opts); - if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000) + if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 && + ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */) av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low." " It takes bits/s as argument, not kbits/s\n"); From 5f36c546ec4ef279027da6e0f0ef1276bea4207a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Tue, 13 Feb 2018 11:46:44 +0100 Subject: [PATCH 1959/2557] Add myself as codec2 maintainer --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index bf1299bdbfa82..cc4c23df6f75a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -188,6 +188,7 @@ Codecs: jvdec.c Peter Ross lcl*.c Roberto Togni, Reimar Doeffinger libcelt_dec.c Nicolas George + libcodec2.c Tomas Härdin libdirac* David Conrad libgsm.c Michel Bardiaux libkvazaar.c Arttu Ylä-Outinen @@ -395,6 +396,7 @@ Muxers/Demuxers: brstm.c Paul B Mahol caf* Peter Ross cdxl.c Paul B Mahol + codec2.c Tomas Härdin crc.c Michael Niedermayer dashdec.c Steven Liu dashenc.c Karthick Jeyapal From dcb2ef2211fd472b4fa235e9f1c4a48582e44049 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 3 Feb 2018 22:03:58 +0100 Subject: [PATCH 1960/2557] avformat/aviobuf: add ff_read_line_to_bprint and ff_read_line_to_bprint_overwrite functions To be able to read lines longer than a static buffer size. Signed-off-by: Marton Balint --- libavformat/aviobuf.c | 46 ++++++++++++++++++++++++++++++++++++++++++ libavformat/internal.h | 26 ++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index d63db3897f4c8..95b33644784c0 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -823,6 +823,52 @@ int ff_get_line(AVIOContext *s, char *buf, int maxlen) return i; } +int64_t ff_read_line_to_bprint(AVIOContext *s, AVBPrint *bp) +{ + int len, end; + int64_t read = 0; + char tmp[1024]; + char c; + + do { + len = 0; + do { + c = avio_r8(s); + end = (c == '\r' || c == '\n' || c == '\0'); + if (!end) + tmp[len++] = c; + } while (!end && len < sizeof(tmp)); + av_bprint_append_data(bp, tmp, len); + read += len; + } while (!end); + + if (c == '\r' && avio_r8(s) != '\n' && !avio_feof(s)) + avio_skip(s, -1); + + if (!c && s->error) + return s->error; + + if (!c && !read && avio_feof(s)) + return AVERROR_EOF; + + return read; +} + +int64_t ff_read_line_to_bprint_overwrite(AVIOContext *s, AVBPrint *bp) +{ + int64_t ret; + + av_bprint_clear(bp); + ret = ff_read_line_to_bprint(s, bp); + if (ret < 0) + return ret; + + if (!av_bprint_is_complete(bp)) + return AVERROR(ENOMEM); + + return bp->len; +} + int avio_get_str(AVIOContext *s, int maxlen, char *buf, int buflen) { int i; diff --git a/libavformat/internal.h b/libavformat/internal.h index 0d08576c299ae..2ac7e2e1a0b0a 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -299,6 +299,32 @@ void ff_put_v(AVIOContext *bc, uint64_t val); */ int ff_get_line(AVIOContext *s, char *buf, int maxlen); +/** + * Read a whole line of text from AVIOContext to an AVBPrint buffer. Stop + * reading after reaching a \\r, a \\n, a \\r\\n, a \\0 or EOF. The line + * ending characters are NOT included in the buffer, but they are skipped on + * the input. + * + * @param s the read-only AVIOContext + * @param bp the AVBPrint buffer + * @return the length of the read line, not including the line endings, + * negative on error. + */ +int64_t ff_read_line_to_bprint(AVIOContext *s, AVBPrint *bp); + +/** + * Read a whole line of text from AVIOContext to an AVBPrint buffer overwriting + * its contents. Stop reading after reaching a \\r, a \\n, a \\r\\n, a \\0 or + * EOF. The line ending characters are NOT included in the buffer, but they + * are skipped on the input. + * + * @param s the read-only AVIOContext + * @param bp the AVBPrint buffer + * @return the length of the read line not including the line endings, + * negative on error, or if the buffer becomes truncated. + */ +int64_t ff_read_line_to_bprint_overwrite(AVIOContext *s, AVBPrint *bp); + #define SPACE_CHARS " \t\r\n" /** From ffabff1baa0873a2aa9c0c09ec93b2f4191493b5 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 3 Feb 2018 22:05:21 +0100 Subject: [PATCH 1961/2557] avformat/concatdec: add support for very long line sizes Fixes ticket #6761. Signed-off-by: Marton Balint --- libavformat/concatdec.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 178fac86cbff1..8fff9cc2cbca8 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -20,6 +20,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/bprint.h" #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" @@ -386,18 +387,18 @@ static int concat_read_close(AVFormatContext *avf) static int concat_read_header(AVFormatContext *avf) { ConcatContext *cat = avf->priv_data; - uint8_t buf[4096]; + AVBPrint bp; uint8_t *cursor, *keyword; - int ret, line = 0, i; + int line = 0, i; unsigned nb_files_alloc = 0; ConcatFile *file = NULL; - int64_t time = 0; + int64_t ret, time = 0; - while (1) { - if ((ret = ff_get_line(avf->pb, buf, sizeof(buf))) <= 0) - break; + av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); + + while ((ret = ff_read_line_to_bprint_overwrite(avf->pb, &bp)) >= 0) { line++; - cursor = buf; + cursor = bp.str; keyword = get_keyword(&cursor); if (!*keyword || *keyword == '#') continue; @@ -473,7 +474,7 @@ static int concat_read_header(AVFormatContext *avf) FAIL(AVERROR_INVALIDDATA); } } - if (ret < 0) + if (ret != AVERROR_EOF && ret < 0) goto fail; if (!cat->nb_files) FAIL(AVERROR_INVALIDDATA); @@ -499,9 +500,11 @@ static int concat_read_header(AVFormatContext *avf) MATCH_ONE_TO_ONE; if ((ret = open_file(avf, 0)) < 0) goto fail; + av_bprint_finalize(&bp, NULL); return 0; fail: + av_bprint_finalize(&bp, NULL); concat_read_close(avf); return ret; } From ea03f295ec79ee72d3c7a6af4e4abcda70b9a423 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 17 Feb 2018 20:44:12 +0100 Subject: [PATCH 1962/2557] avcodec/exr : add support for long name flag and be more explicit about unsupported flag based-on patch by Carl Eugen Hoyos Fix ticket 6994 --- libavcodec/exr.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 47f59bd638d7a..444af17778e99 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -1350,12 +1350,14 @@ static int decode_header(EXRContext *s, AVFrame *frame) flags = bytestream2_get_le24(&s->gb); - if (flags == 0x00) - s->is_tile = 0; - else if (flags & 0x02) + if (flags & 0x02) s->is_tile = 1; - else{ - avpriv_report_missing_feature(s->avctx, "flags %d", flags); + if (flags & 0x08) { + avpriv_report_missing_feature(s->avctx, "deep data"); + return AVERROR_PATCHWELCOME; + } + if (flags & 0x10) { + avpriv_report_missing_feature(s->avctx, "multipart"); return AVERROR_PATCHWELCOME; } From c8552b78584a13cea3eaf7401027a5e29acdec05 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Fri, 9 Feb 2018 09:16:04 +0100 Subject: [PATCH 1963/2557] fate/exr : add test for long name flag ticket 6994 --- tests/fate/image.mak | 3 +++ tests/ref/fate/exr-rgba-zip16-16x32-flag4 | 6 ++++++ 2 files changed, 9 insertions(+) create mode 100644 tests/ref/fate/exr-rgba-zip16-16x32-flag4 diff --git a/tests/fate/image.mak b/tests/fate/image.mak index 7e7be3f119e55..121405aab9cc6 100644 --- a/tests/fate/image.mak +++ b/tests/fate/image.mak @@ -284,6 +284,9 @@ fate-exr-y-scanline-zip-half-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/y_sca FATE_EXR += fate-exr-rgb-scanline-half-piz-dw-t08 fate-exr-rgb-scanline-half-piz-dw-t08: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_piz_dw_t08.exr -pix_fmt rgb48le +FATE_EXR += fate-exr-rgba-zip16-16x32-flag4 +fate-exr-rgba-zip16-16x32-flag4: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_zip16_16x32_flag4.exr -pix_fmt rgba64le + FATE_EXR-$(call DEMDEC, IMAGE2, EXR) += $(FATE_EXR) FATE_IMAGE += $(FATE_EXR-yes) diff --git a/tests/ref/fate/exr-rgba-zip16-16x32-flag4 b/tests/ref/fate/exr-rgba-zip16-16x32-flag4 new file mode 100644 index 0000000000000..e34aa711eab7f --- /dev/null +++ b/tests/ref/fate/exr-rgba-zip16-16x32-flag4 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 16x32 +#sar 0: 1/1 +0, 0, 0, 1, 4096, 0xf90ab1e9 From e3fc36a84c4335fcb347ed82911f98339279ec39 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 17 Feb 2018 20:48:42 +0100 Subject: [PATCH 1964/2557] checkasm/vf_blend : add depth param in order to add test for 16 bit version --- tests/checkasm/vf_blend.c | 57 ++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/tests/checkasm/vf_blend.c b/tests/checkasm/vf_blend.c index be6573045288c..9933f0426ece8 100644 --- a/tests/checkasm/vf_blend.c +++ b/tests/checkasm/vf_blend.c @@ -60,28 +60,29 @@ } \ } while (0) -#define check_blend_func() \ +#define check_blend_func(depth) \ do { \ - int i; \ + int i, w; \ declare_func(void, const uint8_t *top, ptrdiff_t top_linesize, \ const uint8_t *bottom, ptrdiff_t bottom_linesize, \ uint8_t *dst, ptrdiff_t dst_linesize, \ ptrdiff_t width, ptrdiff_t height, \ struct FilterParams *param, double *values); \ + w = WIDTH / depth; \ \ for (i = 0; i < BUF_UNITS - 1; i++) { \ int src_offset = i * SIZE_PER_UNIT + i; /* Test various alignments */ \ int dst_offset = i * SIZE_PER_UNIT; /* dst must be aligned */ \ randomize_buffers(); \ - call_ref(top1 + src_offset, WIDTH, bot1 + src_offset, WIDTH, \ - dst1 + dst_offset, WIDTH, WIDTH, HEIGHT, ¶m, NULL); \ - call_new(top2 + src_offset, WIDTH, bot2 + src_offset, WIDTH, \ - dst2 + dst_offset, WIDTH, WIDTH, HEIGHT, ¶m, NULL); \ + call_ref(top1 + src_offset, w, bot1 + src_offset, w, \ + dst1 + dst_offset, w, w, HEIGHT, ¶m, NULL); \ + call_new(top2 + src_offset, w, bot2 + src_offset, w, \ + dst2 + dst_offset, w, w, HEIGHT, ¶m, NULL); \ if (memcmp(top1, top2, BUF_SIZE) || memcmp(bot1, bot2, BUF_SIZE) || memcmp(dst1, dst2, BUF_SIZE)) \ fail(); \ } \ - bench_new(top2, WIDTH / 4, bot2, WIDTH / 4, dst2, WIDTH / 4, \ - WIDTH / 4, HEIGHT / 4, ¶m, NULL); \ + bench_new(top2, w / 4, bot2, w / 4, dst2, w / 4, \ + w / 4, HEIGHT / 4, ¶m, NULL); \ } while (0) void checkasm_check_blend(void) @@ -96,29 +97,29 @@ void checkasm_check_blend(void) .opacity = 1.0, }; -#define check_and_report(name, val) \ +#define check_and_report(name, val, depth) \ param.mode = val; \ - ff_blend_init(¶m, 0); \ + ff_blend_init(¶m, depth - 1); \ if (check_func(param.blend, #name)) \ - check_blend_func(); + check_blend_func(depth); - check_and_report(addition, BLEND_ADDITION) - check_and_report(grainmerge, BLEND_GRAINMERGE) - check_and_report(and, BLEND_AND) - check_and_report(average, BLEND_AVERAGE) - check_and_report(darken, BLEND_DARKEN) - check_and_report(grainextract, BLEND_GRAINEXTRACT) - check_and_report(hardmix, BLEND_HARDMIX) - check_and_report(lighten, BLEND_LIGHTEN) - check_and_report(multiply, BLEND_MULTIPLY) - check_and_report(or, BLEND_OR) - check_and_report(phoenix, BLEND_PHOENIX) - check_and_report(screen, BLEND_SCREEN) - check_and_report(subtract, BLEND_SUBTRACT) - check_and_report(xor, BLEND_XOR) - check_and_report(difference, BLEND_DIFFERENCE) - check_and_report(extremity, BLEND_EXTREMITY) - check_and_report(negation, BLEND_NEGATION) + check_and_report(addition, BLEND_ADDITION, 1) + check_and_report(grainmerge, BLEND_GRAINMERGE, 1) + check_and_report(and, BLEND_AND, 1) + check_and_report(average, BLEND_AVERAGE, 1) + check_and_report(darken, BLEND_DARKEN, 1) + check_and_report(grainextract, BLEND_GRAINEXTRACT, 1) + check_and_report(hardmix, BLEND_HARDMIX, 1) + check_and_report(lighten, BLEND_LIGHTEN, 1) + check_and_report(multiply, BLEND_MULTIPLY, 1) + check_and_report(or, BLEND_OR, 1) + check_and_report(phoenix, BLEND_PHOENIX, 1) + check_and_report(screen, BLEND_SCREEN, 1) + check_and_report(subtract, BLEND_SUBTRACT, 1) + check_and_report(xor, BLEND_XOR, 1) + check_and_report(difference, BLEND_DIFFERENCE, 1) + check_and_report(extremity, BLEND_EXTREMITY, 1) + check_and_report(negation, BLEND_NEGATION, 1) report("8bit"); From 7590d58b61462ef1f802fc75a092662758d4039a Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 17 Feb 2018 20:49:12 +0100 Subject: [PATCH 1965/2557] avfilter/x86/vf_blend : reorganize init in order to add 16 bit version --- libavfilter/x86/vf_blend_init.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavfilter/x86/vf_blend_init.c b/libavfilter/x86/vf_blend_init.c index 6e782e4edbcfe..b88ea7a7d25a9 100644 --- a/libavfilter/x86/vf_blend_init.c +++ b/libavfilter/x86/vf_blend_init.c @@ -73,7 +73,8 @@ av_cold void ff_blend_init_x86(FilterParams *param, int is_16bit) { int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_SSE2(cpu_flags) && param->opacity == 1 && !is_16bit) { + if (!is_16bit) { + if (EXTERNAL_SSE2(cpu_flags) && param->opacity == 1) { switch (param->mode) { case BLEND_ADDITION: param->blend = ff_blend_addition_sse2; break; case BLEND_GRAINMERGE: param->blend = ff_blend_grainmerge_sse2; break; @@ -95,7 +96,7 @@ av_cold void ff_blend_init_x86(FilterParams *param, int is_16bit) case BLEND_NEGATION: param->blend = ff_blend_negation_sse2; break; } } - if (EXTERNAL_SSSE3(cpu_flags) && param->opacity == 1 && !is_16bit) { + if (EXTERNAL_SSSE3(cpu_flags) && param->opacity == 1) { switch (param->mode) { case BLEND_DIFFERENCE: param->blend = ff_blend_difference_ssse3; break; case BLEND_EXTREMITY: param->blend = ff_blend_extremity_ssse3; break; @@ -103,7 +104,7 @@ av_cold void ff_blend_init_x86(FilterParams *param, int is_16bit) } } - if (EXTERNAL_AVX2_FAST(cpu_flags) && param->opacity == 1 && !is_16bit) { + if (EXTERNAL_AVX2_FAST(cpu_flags) && param->opacity == 1) { switch (param->mode) { case BLEND_ADDITION: param->blend = ff_blend_addition_avx2; break; case BLEND_GRAINMERGE: param->blend = ff_blend_grainmerge_avx2; break; @@ -124,4 +125,5 @@ av_cold void ff_blend_init_x86(FilterParams *param, int is_16bit) case BLEND_NEGATION: param->blend = ff_blend_negation_avx2; break; } } + } } From 6c6c9d14a841543166189dec79e33471c44dc863 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 17 Feb 2018 20:49:32 +0100 Subject: [PATCH 1966/2557] avfilter/x86/vf_blend : indent --- libavfilter/x86/vf_blend_init.c | 94 ++++++++++++++++----------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/libavfilter/x86/vf_blend_init.c b/libavfilter/x86/vf_blend_init.c index b88ea7a7d25a9..c9c7a52ef9477 100644 --- a/libavfilter/x86/vf_blend_init.c +++ b/libavfilter/x86/vf_blend_init.c @@ -74,56 +74,56 @@ av_cold void ff_blend_init_x86(FilterParams *param, int is_16bit) int cpu_flags = av_get_cpu_flags(); if (!is_16bit) { - if (EXTERNAL_SSE2(cpu_flags) && param->opacity == 1) { - switch (param->mode) { - case BLEND_ADDITION: param->blend = ff_blend_addition_sse2; break; - case BLEND_GRAINMERGE: param->blend = ff_blend_grainmerge_sse2; break; - case BLEND_AND: param->blend = ff_blend_and_sse2; break; - case BLEND_AVERAGE: param->blend = ff_blend_average_sse2; break; - case BLEND_DARKEN: param->blend = ff_blend_darken_sse2; break; - case BLEND_GRAINEXTRACT: param->blend = ff_blend_grainextract_sse2; break; - case BLEND_DIVIDE: param->blend = ff_blend_divide_sse2; break; - case BLEND_HARDMIX: param->blend = ff_blend_hardmix_sse2; break; - case BLEND_LIGHTEN: param->blend = ff_blend_lighten_sse2; break; - case BLEND_MULTIPLY: param->blend = ff_blend_multiply_sse2; break; - case BLEND_OR: param->blend = ff_blend_or_sse2; break; - case BLEND_PHOENIX: param->blend = ff_blend_phoenix_sse2; break; - case BLEND_SCREEN: param->blend = ff_blend_screen_sse2; break; - case BLEND_SUBTRACT: param->blend = ff_blend_subtract_sse2; break; - case BLEND_XOR: param->blend = ff_blend_xor_sse2; break; - case BLEND_DIFFERENCE: param->blend = ff_blend_difference_sse2; break; - case BLEND_EXTREMITY: param->blend = ff_blend_extremity_sse2; break; - case BLEND_NEGATION: param->blend = ff_blend_negation_sse2; break; + if (EXTERNAL_SSE2(cpu_flags) && param->opacity == 1) { + switch (param->mode) { + case BLEND_ADDITION: param->blend = ff_blend_addition_sse2; break; + case BLEND_GRAINMERGE: param->blend = ff_blend_grainmerge_sse2; break; + case BLEND_AND: param->blend = ff_blend_and_sse2; break; + case BLEND_AVERAGE: param->blend = ff_blend_average_sse2; break; + case BLEND_DARKEN: param->blend = ff_blend_darken_sse2; break; + case BLEND_GRAINEXTRACT: param->blend = ff_blend_grainextract_sse2; break; + case BLEND_DIVIDE: param->blend = ff_blend_divide_sse2; break; + case BLEND_HARDMIX: param->blend = ff_blend_hardmix_sse2; break; + case BLEND_LIGHTEN: param->blend = ff_blend_lighten_sse2; break; + case BLEND_MULTIPLY: param->blend = ff_blend_multiply_sse2; break; + case BLEND_OR: param->blend = ff_blend_or_sse2; break; + case BLEND_PHOENIX: param->blend = ff_blend_phoenix_sse2; break; + case BLEND_SCREEN: param->blend = ff_blend_screen_sse2; break; + case BLEND_SUBTRACT: param->blend = ff_blend_subtract_sse2; break; + case BLEND_XOR: param->blend = ff_blend_xor_sse2; break; + case BLEND_DIFFERENCE: param->blend = ff_blend_difference_sse2; break; + case BLEND_EXTREMITY: param->blend = ff_blend_extremity_sse2; break; + case BLEND_NEGATION: param->blend = ff_blend_negation_sse2; break; + } } - } - if (EXTERNAL_SSSE3(cpu_flags) && param->opacity == 1) { - switch (param->mode) { - case BLEND_DIFFERENCE: param->blend = ff_blend_difference_ssse3; break; - case BLEND_EXTREMITY: param->blend = ff_blend_extremity_ssse3; break; - case BLEND_NEGATION: param->blend = ff_blend_negation_ssse3; break; + if (EXTERNAL_SSSE3(cpu_flags) && param->opacity == 1) { + switch (param->mode) { + case BLEND_DIFFERENCE: param->blend = ff_blend_difference_ssse3; break; + case BLEND_EXTREMITY: param->blend = ff_blend_extremity_ssse3; break; + case BLEND_NEGATION: param->blend = ff_blend_negation_ssse3; break; + } } - } - if (EXTERNAL_AVX2_FAST(cpu_flags) && param->opacity == 1) { - switch (param->mode) { - case BLEND_ADDITION: param->blend = ff_blend_addition_avx2; break; - case BLEND_GRAINMERGE: param->blend = ff_blend_grainmerge_avx2; break; - case BLEND_AND: param->blend = ff_blend_and_avx2; break; - case BLEND_AVERAGE: param->blend = ff_blend_average_avx2; break; - case BLEND_DARKEN: param->blend = ff_blend_darken_avx2; break; - case BLEND_GRAINEXTRACT: param->blend = ff_blend_grainextract_avx2; break; - case BLEND_HARDMIX: param->blend = ff_blend_hardmix_avx2; break; - case BLEND_LIGHTEN: param->blend = ff_blend_lighten_avx2; break; - case BLEND_MULTIPLY: param->blend = ff_blend_multiply_avx2; break; - case BLEND_OR: param->blend = ff_blend_or_avx2; break; - case BLEND_PHOENIX: param->blend = ff_blend_phoenix_avx2; break; - case BLEND_SCREEN: param->blend = ff_blend_screen_avx2; break; - case BLEND_SUBTRACT: param->blend = ff_blend_subtract_avx2; break; - case BLEND_XOR: param->blend = ff_blend_xor_avx2; break; - case BLEND_DIFFERENCE: param->blend = ff_blend_difference_avx2; break; - case BLEND_EXTREMITY: param->blend = ff_blend_extremity_avx2; break; - case BLEND_NEGATION: param->blend = ff_blend_negation_avx2; break; + if (EXTERNAL_AVX2_FAST(cpu_flags) && param->opacity == 1) { + switch (param->mode) { + case BLEND_ADDITION: param->blend = ff_blend_addition_avx2; break; + case BLEND_GRAINMERGE: param->blend = ff_blend_grainmerge_avx2; break; + case BLEND_AND: param->blend = ff_blend_and_avx2; break; + case BLEND_AVERAGE: param->blend = ff_blend_average_avx2; break; + case BLEND_DARKEN: param->blend = ff_blend_darken_avx2; break; + case BLEND_GRAINEXTRACT: param->blend = ff_blend_grainextract_avx2; break; + case BLEND_HARDMIX: param->blend = ff_blend_hardmix_avx2; break; + case BLEND_LIGHTEN: param->blend = ff_blend_lighten_avx2; break; + case BLEND_MULTIPLY: param->blend = ff_blend_multiply_avx2; break; + case BLEND_OR: param->blend = ff_blend_or_avx2; break; + case BLEND_PHOENIX: param->blend = ff_blend_phoenix_avx2; break; + case BLEND_SCREEN: param->blend = ff_blend_screen_avx2; break; + case BLEND_SUBTRACT: param->blend = ff_blend_subtract_avx2; break; + case BLEND_XOR: param->blend = ff_blend_xor_avx2; break; + case BLEND_DIFFERENCE: param->blend = ff_blend_difference_avx2; break; + case BLEND_EXTREMITY: param->blend = ff_blend_extremity_avx2; break; + case BLEND_NEGATION: param->blend = ff_blend_negation_avx2; break; + } } } - } } From 53a03b5c8c7d355bd353727115efc9977aa76f28 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 17 Feb 2018 21:01:34 +0100 Subject: [PATCH 1967/2557] avfilter/x86/vf_blend : add 16 bit version for BLEND_SIMPLE, phoenix, difference for SSE and AVX2 (x86_64) --- libavfilter/x86/vf_blend.asm | 75 +++++++++++++++++++++++++++------ libavfilter/x86/vf_blend_init.c | 54 ++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 13 deletions(-) diff --git a/libavfilter/x86/vf_blend.asm b/libavfilter/x86/vf_blend.asm index 680e266348a90..5d9a90919295e 100644 --- a/libavfilter/x86/vf_blend.asm +++ b/libavfilter/x86/vf_blend.asm @@ -36,10 +36,13 @@ pb_255: times 16 db 255 SECTION .text -%macro BLEND_INIT 2 +%macro BLEND_INIT 2-3 %if ARCH_X86_64 cglobal blend_%1, 6, 9, %2, top, top_linesize, bottom, bottom_linesize, dst, dst_linesize, width, end, x mov widthd, dword widthm + %if %0 == 3; is 16 bit + add widthq, widthq ; doesn't compile on x86_32 + %endif %else cglobal blend_%1, 5, 7, %2, top, top_linesize, bottom, bottom_linesize, dst, end, x %define dst_linesizeq r5mp @@ -61,8 +64,8 @@ cglobal blend_%1, 5, 7, %2, top, top_linesize, bottom, bottom_linesize, dst, end REP_RET %endmacro -%macro BLEND_SIMPLE 2 -BLEND_INIT %1, 2 +%macro BLEND_SIMPLE 2-3 +BLEND_INIT %1, 2, %3 .nextrow: mov xq, widthq @@ -270,8 +273,9 @@ BLEND_INIT divide, 4 BLEND_END %endmacro -%macro PHOENIX 0 -BLEND_INIT phoenix, 4 +%macro PHOENIX 2-3 +; %1 name, %2 b or w, %3 (opt) 1 if 16 bit +BLEND_INIT %1, 4, %3 VBROADCASTI128 m3, [pb_255] .nextrow: mov xq, widthq @@ -280,19 +284,19 @@ BLEND_INIT phoenix, 4 movu m0, [topq + xq] movu m1, [bottomq + xq] mova m2, m0 - pminub m0, m1 - pmaxub m1, m2 + pminu%2 m0, m1 + pmaxu%2 m1, m2 mova m2, m3 - psubusb m2, m1 - paddusb m2, m0 + psubus%2 m2, m1 + paddus%2 m2, m0 mova [dstq + xq], m2 add xq, mmsize jl .loop BLEND_END %endmacro -%macro BLEND_ABS 0 -BLEND_INIT difference, 5 +%macro DIFFERENCE 1-2 +BLEND_INIT %1, 5, %2 pxor m2, m2 .nextrow: mov xq, widthq @@ -300,6 +304,17 @@ BLEND_INIT difference, 5 .loop: movu m0, [topq + xq] movu m1, [bottomq + xq] +%if %0 == 2 ; 16 bit + punpckhwd m3, m0, m2 + punpcklwd m0, m2 + punpckhwd m4, m1, m2 + punpcklwd m1, m2 + psubd m0, m1 + psubd m3, m4 + pabsd m0, m0 + pabsd m3, m3 + packusdw m0, m3 +%else punpckhbw m3, m0, m2 punpcklbw m0, m2 punpckhbw m4, m1, m2 @@ -308,11 +323,14 @@ BLEND_INIT difference, 5 psubw m3, m4 ABS2 m0, m3, m1, m4 packuswb m0, m3 +%endif mova [dstq + xq], m0 add xq, mmsize jl .loop BLEND_END +%endmacro +%macro BLEND_ABS 0 BLEND_INIT extremity, 8 pxor m2, m2 VBROADCASTI128 m4, [pw_255] @@ -378,14 +396,32 @@ BLEND_SCREEN AVERAGE GRAINMERGE HARDMIX -PHOENIX +PHOENIX phoenix, b +DIFFERENCE difference DIVIDE BLEND_ABS +%if ARCH_X86_64 +BLEND_SIMPLE addition_16, addusw, 1 +BLEND_SIMPLE and_16, and, 1 +BLEND_SIMPLE or_16, or, 1 +BLEND_SIMPLE subtract_16, subusw, 1 +BLEND_SIMPLE xor_16, xor, 1 +%endif + INIT_XMM ssse3 +DIFFERENCE difference BLEND_ABS +INIT_XMM sse4 +%if ARCH_X86_64 +BLEND_SIMPLE darken_16, minuw, 1 +BLEND_SIMPLE lighten_16, maxuw, 1 +PHOENIX phoenix_16, w, 1 +DIFFERENCE difference_16, 1 +%endif + %if HAVE_AVX2_EXTERNAL INIT_YMM avx2 BLEND_SIMPLE xor, xor @@ -401,7 +437,20 @@ BLEND_SCREEN AVERAGE GRAINMERGE HARDMIX -PHOENIX +PHOENIX phoenix, b +DIFFERENCE difference BLEND_ABS + +%if ARCH_X86_64 +BLEND_SIMPLE addition_16, addusw, 1 +BLEND_SIMPLE and_16, and, 1 +BLEND_SIMPLE darken_16, minuw, 1 +BLEND_SIMPLE lighten_16, maxuw, 1 +BLEND_SIMPLE or_16, or, 1 +BLEND_SIMPLE subtract_16, subusw, 1 +BLEND_SIMPLE xor_16, xor, 1 +PHOENIX phoenix_16, w, 1 +DIFFERENCE difference_16, 1 +%endif %endif diff --git a/libavfilter/x86/vf_blend_init.c b/libavfilter/x86/vf_blend_init.c index c9c7a52ef9477..0962f6d7fdc4a 100644 --- a/libavfilter/x86/vf_blend_init.c +++ b/libavfilter/x86/vf_blend_init.c @@ -69,6 +69,27 @@ BLEND_FUNC(negation, sse2) BLEND_FUNC(negation, ssse3) BLEND_FUNC(negation, avx2) +#if ARCH_X86_64 +BLEND_FUNC(addition_16, sse2) +BLEND_FUNC(addition_16, avx2) +BLEND_FUNC(and_16, sse2) +BLEND_FUNC(and_16, avx2) +BLEND_FUNC(darken_16, sse4) +BLEND_FUNC(darken_16, avx2) +BLEND_FUNC(difference_16, sse4) +BLEND_FUNC(difference_16, avx2) +BLEND_FUNC(lighten_16, sse4) +BLEND_FUNC(lighten_16, avx2) +BLEND_FUNC(or_16, sse2) +BLEND_FUNC(or_16, avx2) +BLEND_FUNC(phoenix_16, sse4) +BLEND_FUNC(phoenix_16, avx2) +BLEND_FUNC(subtract_16, sse2) +BLEND_FUNC(subtract_16, avx2) +BLEND_FUNC(xor_16, sse2) +BLEND_FUNC(xor_16, avx2) +#endif /* ARCH_X86_64 */ + av_cold void ff_blend_init_x86(FilterParams *param, int is_16bit) { int cpu_flags = av_get_cpu_flags(); @@ -125,5 +146,38 @@ av_cold void ff_blend_init_x86(FilterParams *param, int is_16bit) case BLEND_NEGATION: param->blend = ff_blend_negation_avx2; break; } } + } else { /* is_16_bit */ +#if ARCH_X86_64 + if (EXTERNAL_SSE2(cpu_flags) && param->opacity == 1) { + switch (param->mode) { + case BLEND_ADDITION: param->blend = ff_blend_addition_16_sse2; break; + case BLEND_AND: param->blend = ff_blend_and_16_sse2; break; + case BLEND_OR: param->blend = ff_blend_or_16_sse2; break; + case BLEND_SUBTRACT: param->blend = ff_blend_subtract_16_sse2; break; + case BLEND_XOR: param->blend = ff_blend_xor_16_sse2; break; + } + } + if (EXTERNAL_SSE4(cpu_flags) && param->opacity == 1) { + switch (param->mode) { + case BLEND_DARKEN: param->blend = ff_blend_darken_16_sse4; break; + case BLEND_DIFFERENCE: param->blend = ff_blend_difference_16_sse4; break; + case BLEND_LIGHTEN: param->blend = ff_blend_lighten_16_sse4; break; + case BLEND_PHOENIX: param->blend = ff_blend_phoenix_16_sse4; break; + } + } + if (EXTERNAL_AVX2_FAST(cpu_flags) && param->opacity == 1) { + switch (param->mode) { + case BLEND_ADDITION: param->blend = ff_blend_addition_16_avx2; break; + case BLEND_AND: param->blend = ff_blend_and_16_avx2; break; + case BLEND_DARKEN: param->blend = ff_blend_darken_16_avx2; break; + case BLEND_DIFFERENCE: param->blend = ff_blend_difference_16_avx2; break; + case BLEND_LIGHTEN: param->blend = ff_blend_lighten_16_avx2; break; + case BLEND_OR: param->blend = ff_blend_or_16_avx2; break; + case BLEND_PHOENIX: param->blend = ff_blend_phoenix_16_avx2; break; + case BLEND_SUBTRACT: param->blend = ff_blend_subtract_16_avx2; break; + case BLEND_XOR: param->blend = ff_blend_xor_16_avx2; break; + } + } +#endif /* ARCH_X86_64 */ } } From c0919c49855b4b7f6a476d2daf2b160d9c50407b Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 17 Feb 2018 21:02:12 +0100 Subject: [PATCH 1968/2557] checkasm/vf_blend : add test for blend_simple_16, phoenix_16 and difference_16 --- tests/checkasm/vf_blend.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/checkasm/vf_blend.c b/tests/checkasm/vf_blend.c index 9933f0426ece8..79bdf9f163d65 100644 --- a/tests/checkasm/vf_blend.c +++ b/tests/checkasm/vf_blend.c @@ -123,6 +123,18 @@ void checkasm_check_blend(void) report("8bit"); + check_and_report(addition_16, BLEND_ADDITION, 2) + check_and_report(and_16, BLEND_AND, 2) + check_and_report(darken_16, BLEND_DARKEN, 2) + check_and_report(difference_16, BLEND_DIFFERENCE, 2) + check_and_report(lighten_16, BLEND_LIGHTEN, 2) + check_and_report(or_16, BLEND_OR, 2) + check_and_report(phoenix_16, BLEND_PHOENIX, 2) + check_and_report(subtract_16, BLEND_SUBTRACT, 2) + check_and_report(xor_16, BLEND_SUBTRACT, 2) + + report("16bit"); + av_freep(&top1); av_freep(&top2); av_freep(&bot1); From f4709f1b7b9008380a74dd0415323fd3e0085c93 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 26 Feb 2018 01:43:54 -0300 Subject: [PATCH 1969/2557] configure: add missing audio_frame_queue dependency to vorbis encoder Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 1bdb7c1c2def0..6916b4549ae9a 100755 --- a/configure +++ b/configure @@ -2642,7 +2642,7 @@ vble_decoder_select="llviddsp" vc1_decoder_select="blockdsp h263_decoder h264qpel intrax8 mpegvideo vc1dsp" vc1image_decoder_select="vc1_decoder" vorbis_decoder_select="mdct" -vorbis_encoder_select="mdct" +vorbis_encoder_select="audio_frame_queue mdct" vp3_decoder_select="hpeldsp vp3dsp videodsp" vp5_decoder_select="h264chroma hpeldsp videodsp vp3dsp vp56dsp" vp6_decoder_select="h264chroma hpeldsp huffman videodsp vp3dsp vp56dsp" From e2399e0c1aeb110456405d23e211066fab6cb041 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Thu, 15 Feb 2018 13:26:20 +0100 Subject: [PATCH 1970/2557] fate: Error out more gracefully on configure failure If configure fails before config.fate is generated, the report file misses some values and gets discarded by the FATE server. In these cases, print those values as "failed" along with the failing configure command line. --- tests/fate.sh | 60 +++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/tests/fate.sh b/tests/fate.sh index c93e20a4642a9..033e7bf5e92e9 100755 --- a/tests/fate.sh +++ b/tests/fate.sh @@ -21,6 +21,33 @@ test -d "$samples" || die "samples location not specified" : ${branch:=master} +src=${workdir}/src +: ${build:=${workdir}/build} +: ${inst:=${workdir}/install} + +configuration=' + --enable-gpl + --prefix="${inst}" + --samples="${samples}" + ${ignore_tests:+--ignore-tests="$ignore_tests"} + ${arch:+--arch="$arch"} + ${cpu:+--cpu="$cpu"} + ${toolchain:+--toolchain="$toolchain"} + ${cross_prefix:+--cross-prefix="$cross_prefix"} + ${as:+--as="$as"} + ${cc:+--cc="$cc"} + ${ld:+--ld="$ld"} + ${target_os:+--target-os="$target_os"} + ${sysroot:+--sysroot="$sysroot"} + ${target_exec:+--target-exec="$target_exec"} + ${target_path:+--target-path="$target_path"} + ${target_samples:+--target-samples="$target_samples"} + ${extra_cflags:+--extra-cflags="$extra_cflags"} + ${extra_ldflags:+--extra-ldflags="$extra_ldflags"} + ${extra_libs:+--extra-libs="$extra_libs"} + ${extra_conf} +' + lock(){ lock=$1/fate.lock (set -C; exec >$lock) 2>/dev/null || return @@ -43,27 +70,7 @@ update()( configure()( cd ${build} || return - ${src}/configure \ - --prefix="${inst}" \ - --samples="${samples}" \ - --enable-gpl \ - ${ignore_tests:+--ignore-tests="$ignore_tests"} \ - ${arch:+--arch=$arch} \ - ${cpu:+--cpu="$cpu"} \ - ${toolchain:+--toolchain="$toolchain"} \ - ${cross_prefix:+--cross-prefix="$cross_prefix"} \ - ${as:+--as="$as"} \ - ${cc:+--cc="$cc"} \ - ${ld:+--ld="$ld"} \ - ${target_os:+--target-os="$target_os"} \ - ${sysroot:+--sysroot="$sysroot"} \ - ${target_exec:+--target-exec="$target_exec"} \ - ${target_path:+--target-path="$target_path"} \ - ${target_samples:+--target-samples="$target_samples"} \ - ${extra_cflags:+--extra-cflags="$extra_cflags"} \ - ${extra_ldflags:+--extra-ldflags="$extra_ldflags"} \ - ${extra_libs:+--extra-libs="$extra_libs"} \ - ${extra_conf} + eval ${src}/configure ${configuration} ) compile()( @@ -84,7 +91,12 @@ clean(){ report(){ date=$(date -u +%Y%m%d%H%M%S) echo "fate:1:${date}:${slot}:${version}:$1:$2:${branch}:${comment}" >report - cat ${build}/avbuild/config.fate ${build}/tests/data/fate/*.rep >> report 2> /dev/null + if test -e ${build}/avbuild/config.fate; then + cat ${build}/avbuild/config.fate >> report 2> /dev/null + else + eval echo config:failed:failed:failed:failed:failed:${configuration} >> report 2> /dev/null + fi + cat ${build}/tests/data/fate/*.rep >> report 2> /dev/null test -n "$fate_recv" && $tar report *.log | gzip | $fate_recv } @@ -98,10 +110,6 @@ mkdir -p ${workdir} || die "Error creating ${workdir}" lock ${workdir} || die "${workdir} locked" cd ${workdir} || die "cd ${workdir} failed" -src=${workdir}/src -: ${build:=${workdir}/build} -: ${inst:=${workdir}/install} - test -d "$src" && update || checkout || die "Error fetching source" cd ${workdir} From f235359b2b1175585df757e6b60fabac29b8aa22 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 26 Feb 2018 00:18:53 -0300 Subject: [PATCH 1971/2557] avformat/utils: don't overwrite the return value of read_packet() This only affected demuxers that didn't return reference counted packets. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/utils.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index 2c2ea876b6133..72531d4185f50 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -869,9 +869,9 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) if (!pkt->buf) { AVPacket tmp = { 0 }; - ret = av_packet_ref(&tmp, pkt); - if (ret < 0) - return ret; + err = av_packet_ref(&tmp, pkt); + if (err < 0) + return err; *pkt = tmp; } From 6d763ab58811e856517926353ee2920369cf20b4 Mon Sep 17 00:00:00 2001 From: Serhii Marchuk Date: Fri, 23 Feb 2018 11:35:40 +0200 Subject: [PATCH 1972/2557] avformat/dashenc: add option to change HTTP method --- libavformat/dashenc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index d6474f3549fbd..febe46869183c 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -109,6 +109,7 @@ typedef struct DASHContext { const char *init_seg_name; const char *media_seg_name; const char *utc_timing_url; + const char *method; const char *user_agent; int hls_playlist; int http_persistent; @@ -262,6 +263,8 @@ static int flush_dynbuf(OutputStream *os, int *range_length) static void set_http_options(AVDictionary **options, DASHContext *c) { + if (c->method) + av_dict_set(options, "method", c->method, 0); if (c->user_agent) av_dict_set(options, "user_agent", c->user_agent, 0); if (c->http_persistent) @@ -1410,6 +1413,7 @@ static const AVOption options[] = { { "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.m4s"}, 0, 0, E }, { "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.m4s"}, 0, 0, E }, { "utc_timing_url", "URL of the page that will return the UTC timestamp in ISO format", OFFSET(utc_timing_url), AV_OPT_TYPE_STRING, { 0 }, 0, 0, E }, + { "method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, From e3851f6a3739e84094051d8b9c85732ab12c9fd9 Mon Sep 17 00:00:00 2001 From: Karthick Jeyapal Date: Sat, 24 Feb 2018 12:47:18 +0530 Subject: [PATCH 1973/2557] avformat/dashenc: Removed usage of deprecated 'filename' variable --- libavformat/dashenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index febe46869183c..83e0cff728f2a 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1310,7 +1310,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) //open the output context when the first frame of a segment is ready if (!c->single_file && !os->out) { AVDictionary *opts = NULL; - const char *proto = avio_find_protocol_name(s->filename); + const char *proto = avio_find_protocol_name(s->url); int use_rename = proto && !strcmp(proto, "file"); os->filename[0] = os->full_path[0] = os->temp_path[0] = '\0'; ff_dash_fill_tmpl_params(os->filename, sizeof(os->filename), From fa0c9d69d3d70ab81400c54a7a7d1446c678ef7a Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Mon, 26 Feb 2018 08:38:53 +0100 Subject: [PATCH 1974/2557] fftools/ffmpeg: replace call to av_strerror with av_err2str Signed-off-by: Tobias Rapp --- fftools/ffmpeg.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 32caa4bfb29ed..3a45f43c1db6a 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2175,10 +2175,7 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) ret = reap_filters(1); if (ret < 0 && ret != AVERROR_EOF) { - char errbuf[128]; - av_strerror(ret, errbuf, sizeof(errbuf)); - - av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", errbuf); + av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); return ret; } @@ -4638,10 +4635,7 @@ static int transcode(void) ret = transcode_step(); if (ret < 0 && ret != AVERROR_EOF) { - char errbuf[128]; - av_strerror(ret, errbuf, sizeof(errbuf)); - - av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", errbuf); + av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); break; } From bbed942dfd64c43d8f943532d8e12f10e7613938 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 26 Feb 2018 02:15:34 +0100 Subject: [PATCH 1975/2557] avcodec/rscc: Skip empty frames (nb_tiles == 0) Fixes: Timeout Fixes: 6266/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RSCC_fuzzer-5692431816196096 Its not known if nb_tiles is allowed so it is not treated as an error Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/rscc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/rscc.c b/libavcodec/rscc.c index f270cd535113c..dae5e84634520 100644 --- a/libavcodec/rscc.c +++ b/libavcodec/rscc.c @@ -157,6 +157,12 @@ static int rscc_decode_frame(AVCodecContext *avctx, void *data, /* Read number of tiles, and allocate the array */ tiles_nb = bytestream2_get_le16(gbc); + + if (tiles_nb == 0) { + av_log(avctx, AV_LOG_DEBUG, "no tiles\n"); + return avpkt->size; + } + av_fast_malloc(&ctx->tiles, &ctx->tiles_size, tiles_nb * sizeof(*ctx->tiles)); if (!ctx->tiles) { From 7414d0bda7763f9bd69c26c068e482ab297c1c96 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 26 Feb 2018 03:02:48 +0100 Subject: [PATCH 1976/2557] avcodec/utvideodec: Check subsample factors Fixes: Out of array read Fixes: heap_poc Found-by: GwanYeong Kim Signed-off-by: Michael Niedermayer --- libavcodec/utvideodec.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index c5f553496430d..086129d094755 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -30,6 +30,7 @@ #define UNCHECKED_BITSTREAM_READER 1 #include "libavutil/intreadwrite.h" +#include "libavutil/pixdesc.h" #include "avcodec.h" #include "bswapdsp.h" #include "bytestream.h" @@ -912,6 +913,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, static av_cold int decode_init(AVCodecContext *avctx) { UtvideoContext * const c = avctx->priv_data; + int h_shift, v_shift; c->avctx = avctx; @@ -1012,6 +1014,13 @@ static av_cold int decode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } + av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &h_shift, &v_shift); + if ((avctx->width & ((1<height & ((1<pack && avctx->extradata_size >= 16) { av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", avctx->extradata[3], avctx->extradata[2], From 27cbbbb33f259de7c795d2b75edf7b240f0f82e6 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Mon, 26 Feb 2018 01:20:51 +0100 Subject: [PATCH 1977/2557] compat: remove in-tree NVidia headers External headers are no longer welcome in the ffmpeg codebase because they increase the maintenance burden. However, in the NVidia case the vanilla headers need some modifications to be usable in ffmpeg therefore we still provide them, but in a separate repository. The external headers can be found at https://git.videolan.org/?p=ffmpeg/nv-codec-headers.git Fate-source is updated because of the deleted files, and dynlink_loader.h license headers were updated with the standard FFmpeg headers. Signed-off-by: Marton Balint Signed-off-by: Timo Rothenpieler --- Changelog | 2 + compat/cuda/dynlink_cuda.h | 98 - compat/cuda/dynlink_cuviddec.h | 886 --------- compat/cuda/dynlink_loader.h | 273 +-- compat/cuda/dynlink_nvcuvid.h | 356 ---- compat/nvenc/nvEncodeAPI.h | 3324 -------------------------------- configure | 5 +- libavcodec/nvenc.h | 2 +- tests/ref/fate/source | 4 - 9 files changed, 26 insertions(+), 4924 deletions(-) delete mode 100644 compat/cuda/dynlink_cuda.h delete mode 100644 compat/cuda/dynlink_cuviddec.h delete mode 100644 compat/cuda/dynlink_nvcuvid.h delete mode 100644 compat/nvenc/nvEncodeAPI.h diff --git a/Changelog b/Changelog index 499413f30673d..e2a4224c91f00 100644 --- a/Changelog +++ b/Changelog @@ -42,6 +42,8 @@ version : - Add android_camera indev - codec2 en/decoding via libcodec2 - muxer/demuxer for raw codec2 files and .c2 files +- Moved nvidia codec headers into an external repository. + They can be found at http://git.videolan.org/?p=ffmpeg/nv-codec-headers.git version 3.4: diff --git a/compat/cuda/dynlink_cuda.h b/compat/cuda/dynlink_cuda.h deleted file mode 100644 index 3a13611ce6458..0000000000000 --- a/compat/cuda/dynlink_cuda.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * This copyright notice applies to this header file only: - * - * Copyright (c) 2016 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the software, and to permit persons to whom the - * software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#if !defined(AV_COMPAT_DYNLINK_CUDA_H) && !defined(CUDA_VERSION) -#define AV_COMPAT_DYNLINK_CUDA_H - -#include - -#define CUDA_VERSION 7050 - -#if defined(_WIN32) || defined(__CYGWIN__) -#define CUDAAPI __stdcall -#else -#define CUDAAPI -#endif - -#define CU_CTX_SCHED_BLOCKING_SYNC 4 - -typedef int CUdevice; -typedef void* CUarray; -typedef void* CUcontext; -typedef void* CUstream; -#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) -typedef unsigned long long CUdeviceptr; -#else -typedef unsigned int CUdeviceptr; -#endif - -typedef enum cudaError_enum { - CUDA_SUCCESS = 0 -} CUresult; - -typedef enum CUmemorytype_enum { - CU_MEMORYTYPE_HOST = 1, - CU_MEMORYTYPE_DEVICE = 2 -} CUmemorytype; - -typedef struct CUDA_MEMCPY2D_st { - size_t srcXInBytes; - size_t srcY; - CUmemorytype srcMemoryType; - const void *srcHost; - CUdeviceptr srcDevice; - CUarray srcArray; - size_t srcPitch; - - size_t dstXInBytes; - size_t dstY; - CUmemorytype dstMemoryType; - void *dstHost; - CUdeviceptr dstDevice; - CUarray dstArray; - size_t dstPitch; - - size_t WidthInBytes; - size_t Height; -} CUDA_MEMCPY2D; - -typedef CUresult CUDAAPI tcuInit(unsigned int Flags); -typedef CUresult CUDAAPI tcuDeviceGetCount(int *count); -typedef CUresult CUDAAPI tcuDeviceGet(CUdevice *device, int ordinal); -typedef CUresult CUDAAPI tcuDeviceGetName(char *name, int len, CUdevice dev); -typedef CUresult CUDAAPI tcuDeviceComputeCapability(int *major, int *minor, CUdevice dev); -typedef CUresult CUDAAPI tcuCtxCreate_v2(CUcontext *pctx, unsigned int flags, CUdevice dev); -typedef CUresult CUDAAPI tcuCtxPushCurrent_v2(CUcontext *pctx); -typedef CUresult CUDAAPI tcuCtxPopCurrent_v2(CUcontext *pctx); -typedef CUresult CUDAAPI tcuCtxDestroy_v2(CUcontext ctx); -typedef CUresult CUDAAPI tcuMemAlloc_v2(CUdeviceptr *dptr, size_t bytesize); -typedef CUresult CUDAAPI tcuMemFree_v2(CUdeviceptr dptr); -typedef CUresult CUDAAPI tcuMemcpy2D_v2(const CUDA_MEMCPY2D *pcopy); -typedef CUresult CUDAAPI tcuGetErrorName(CUresult error, const char** pstr); -typedef CUresult CUDAAPI tcuGetErrorString(CUresult error, const char** pstr); - -#endif diff --git a/compat/cuda/dynlink_cuviddec.h b/compat/cuda/dynlink_cuviddec.h deleted file mode 100644 index 4af78a186baa8..0000000000000 --- a/compat/cuda/dynlink_cuviddec.h +++ /dev/null @@ -1,886 +0,0 @@ -/* - * This copyright notice applies to this header file only: - * - * Copyright (c) 2010-2017 NVIDIA Corporation - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the software, and to permit persons to whom the - * software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/*****************************************************************************************************/ -//! \file cuviddec.h -//! NVDECODE API provides video decoding interface to NVIDIA GPU devices. -//! \date 2015-2017 -//! This file contains constants, structure definitions and function prototypes used for decoding. -/*****************************************************************************************************/ - -#if !defined(__CUDA_VIDEO_H__) -#define __CUDA_VIDEO_H__ - -#if defined(_WIN64) || defined(__LP64__) || defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) -#if (CUDA_VERSION >= 3020) && (!defined(CUDA_FORCE_API_VERSION) || (CUDA_FORCE_API_VERSION >= 3020)) -#define __CUVID_DEVPTR64 -#endif -#endif - -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus */ - -#if defined(__CYGWIN__) -typedef unsigned int tcu_ulong; -#else -typedef unsigned long tcu_ulong; -#endif - -typedef void *CUvideodecoder; -typedef struct _CUcontextlock_st *CUvideoctxlock; - -/*********************************************************************************/ -//! \enum cudaVideoCodec -//! Video codec enums -//! These enums are used in CUVIDDECODECREATEINFO and CUVIDDECODECAPS structures -/*********************************************************************************/ -typedef enum cudaVideoCodec_enum { - cudaVideoCodec_MPEG1=0, /**< MPEG1 */ - cudaVideoCodec_MPEG2, /**< MPEG2 */ - cudaVideoCodec_MPEG4, /**< MPEG4 */ - cudaVideoCodec_VC1, /**< VC1 */ - cudaVideoCodec_H264, /**< H264 */ - cudaVideoCodec_JPEG, /**< JPEG */ - cudaVideoCodec_H264_SVC, /**< H264-SVC */ - cudaVideoCodec_H264_MVC, /**< H264-MVC */ - cudaVideoCodec_HEVC, /**< HEVC */ - cudaVideoCodec_VP8, /**< VP8 */ - cudaVideoCodec_VP9, /**< VP9 */ - cudaVideoCodec_NumCodecs, /**< Max codecs */ - // Uncompressed YUV - cudaVideoCodec_YUV420 = (('I'<<24)|('Y'<<16)|('U'<<8)|('V')), /**< Y,U,V (4:2:0) */ - cudaVideoCodec_YV12 = (('Y'<<24)|('V'<<16)|('1'<<8)|('2')), /**< Y,V,U (4:2:0) */ - cudaVideoCodec_NV12 = (('N'<<24)|('V'<<16)|('1'<<8)|('2')), /**< Y,UV (4:2:0) */ - cudaVideoCodec_YUYV = (('Y'<<24)|('U'<<16)|('Y'<<8)|('V')), /**< YUYV/YUY2 (4:2:2) */ - cudaVideoCodec_UYVY = (('U'<<24)|('Y'<<16)|('V'<<8)|('Y')) /**< UYVY (4:2:2) */ -} cudaVideoCodec; - -/*********************************************************************************/ -//! \enum cudaVideoSurfaceFormat -//! Video surface format enums used for output format of decoded output -//! These enums are used in CUVIDDECODECREATEINFO structure -/*********************************************************************************/ -typedef enum cudaVideoSurfaceFormat_enum { - cudaVideoSurfaceFormat_NV12=0, /**< NV12 format */ - cudaVideoSurfaceFormat_P016=1 /**< 16 bit semiplaner format. Can be used for 10 bit(6LSB bits 0), - 12 bit (4LSB bits 0) */ -} cudaVideoSurfaceFormat; - -/******************************************************************************************************************/ -//! \enum cudaVideoDeinterlaceMode -//! Deinterlacing mode enums -//! These enums are used in CUVIDDECODECREATEINFO structure -//! Use cudaVideoDeinterlaceMode_Weave for progressive content and for content that doesn't need deinterlacing -//! cudaVideoDeinterlaceMode_Adaptive needs more video memory than other DImodes -/******************************************************************************************************************/ -typedef enum cudaVideoDeinterlaceMode_enum { - cudaVideoDeinterlaceMode_Weave=0, /**< Weave both fields (no deinterlacing) */ - cudaVideoDeinterlaceMode_Bob, /**< Drop one field */ - cudaVideoDeinterlaceMode_Adaptive /**< Adaptive deinterlacing */ -} cudaVideoDeinterlaceMode; - -/**************************************************************************************************************/ -//! \enum cudaVideoChromaFormat -//! Chroma format enums -//! These enums are used in CUVIDDECODECREATEINFO and CUVIDDECODECAPS structures -//! JPEG supports Monochrome, YUV 4:2:0, YUV 4:2:2 and YUV 4:4:4 chroma formats. -//! H264, HEVC, VP9, VP8, VC1, MPEG1, MPEG2 and MPEG4 support YUV 4:2:0 chroma format only. -/**************************************************************************************************************/ -typedef enum cudaVideoChromaFormat_enum { - cudaVideoChromaFormat_Monochrome=0, /**< MonoChrome */ - cudaVideoChromaFormat_420, /**< YUV 4:2:0 */ - cudaVideoChromaFormat_422, /**< YUV 4:2:2 */ - cudaVideoChromaFormat_444 /**< YUV 4:4:4 */ -} cudaVideoChromaFormat; - -/*************************************************************************************************************/ -//! \enum cudaVideoCreateFlags -//! Decoder flag enums to select preferred decode path -//! cudaVideoCreate_Default and cudaVideoCreate_PreferCUVID are most optimized, use these whenever possible -/*************************************************************************************************************/ -typedef enum cudaVideoCreateFlags_enum { - cudaVideoCreate_Default = 0x00, /**< Default operation mode: use dedicated video engines */ - cudaVideoCreate_PreferCUDA = 0x01, /**< Use CUDA-based decoder (requires valid vidLock object for multi-threading) */ - cudaVideoCreate_PreferDXVA = 0x02, /**< Go through DXVA internally if possible (requires D3D9 interop) */ - cudaVideoCreate_PreferCUVID = 0x04 /**< Use dedicated video engines directly */ -} cudaVideoCreateFlags; - - -/**************************************************************************************************************/ -//! \struct CUVIDDECODECAPS; -//! This structure is used in cuvidGetDecoderCaps API -/**************************************************************************************************************/ -typedef struct _CUVIDDECODECAPS -{ - cudaVideoCodec eCodecType; /**< IN: cudaVideoCodec_XXX */ - cudaVideoChromaFormat eChromaFormat; /**< IN: cudaVideoChromaFormat_XXX */ - unsigned int nBitDepthMinus8; /**< IN: The Value "BitDepth minus 8" */ - unsigned int reserved1[3]; /**< Reserved for future use - set to zero */ - - unsigned char bIsSupported; /**< OUT: 1 if codec supported, 0 if not supported */ - unsigned char reserved2[3]; /**< Reserved for future use - set to zero */ - unsigned int nMaxWidth; /**< OUT: Max supported coded width in pixels */ - unsigned int nMaxHeight; /**< OUT: Max supported coded height in pixels */ - unsigned int nMaxMBCount; /**< OUT: Max supported macroblock count - CodedWidth*CodedHeight/256 must be <= nMaxMBCount */ - unsigned short nMinWidth; /**< OUT: Min supported coded width in pixels */ - unsigned short nMinHeight; /**< OUT: Min supported coded height in pixels */ - unsigned int reserved3[11]; /**< Reserved for future use - set to zero */ -} CUVIDDECODECAPS; - -/**************************************************************************************************************/ -//! \struct CUVIDDECODECREATEINFO -//! This structure is used in cuvidCreateDecoder API -/**************************************************************************************************************/ -typedef struct _CUVIDDECODECREATEINFO -{ - tcu_ulong ulWidth; /**< IN: Coded sequence width in pixels */ - tcu_ulong ulHeight; /**< IN: Coded sequence height in pixels */ - tcu_ulong ulNumDecodeSurfaces; /**< IN: Maximum number of internal decode surfaces */ - cudaVideoCodec CodecType; /**< IN: cudaVideoCodec_XXX */ - cudaVideoChromaFormat ChromaFormat; /**< IN: cudaVideoChromaFormat_XXX */ - tcu_ulong ulCreationFlags; /**< IN: Decoder creation flags (cudaVideoCreateFlags_XXX) */ - tcu_ulong bitDepthMinus8; /**< IN: The value "BitDepth minus 8" */ - tcu_ulong ulIntraDecodeOnly; /**< IN: Set 1 only if video has all intra frames (default value is 0). This will - optimize video memory for Intra frames only decoding. The support is limited - to specific codecs(H264 rightnow), the flag will be ignored for codecs which - are not supported. However decoding might fail if the flag is enabled in case - of supported codecs for regular bit streams having P and/or B frames. */ - tcu_ulong Reserved1[3]; /**< Reserved for future use - set to zero */ - /** - * IN: area of the frame that should be displayed - */ - struct { - short left; - short top; - short right; - short bottom; - } display_area; - - cudaVideoSurfaceFormat OutputFormat; /**< IN: cudaVideoSurfaceFormat_XXX */ - cudaVideoDeinterlaceMode DeinterlaceMode; /**< IN: cudaVideoDeinterlaceMode_XXX */ - tcu_ulong ulTargetWidth; /**< IN: Post-processed output width (Should be aligned to 2) */ - tcu_ulong ulTargetHeight; /**< IN: Post-processed output height (Should be aligbed to 2) */ - tcu_ulong ulNumOutputSurfaces; /**< IN: Maximum number of output surfaces simultaneously mapped */ - CUvideoctxlock vidLock; /**< IN: If non-NULL, context lock used for synchronizing ownership of - the cuda context. Needed for cudaVideoCreate_PreferCUDA decode */ - /** - * IN: target rectangle in the output frame (for aspect ratio conversion) - * if a null rectangle is specified, {0,0,ulTargetWidth,ulTargetHeight} will be used - */ - struct { - short left; - short top; - short right; - short bottom; - } target_rect; - tcu_ulong Reserved2[5]; /**< Reserved for future use - set to zero */ -} CUVIDDECODECREATEINFO; - -/*********************************************************/ -//! \struct CUVIDH264DPBENTRY -//! H.264 DPB entry -//! This structure is used in CUVIDH264PICPARAMS structure -/*********************************************************/ -typedef struct _CUVIDH264DPBENTRY -{ - int PicIdx; /**< picture index of reference frame */ - int FrameIdx; /**< frame_num(short-term) or LongTermFrameIdx(long-term) */ - int is_long_term; /**< 0=short term reference, 1=long term reference */ - int not_existing; /**< non-existing reference frame (corresponding PicIdx should be set to -1) */ - int used_for_reference; /**< 0=unused, 1=top_field, 2=bottom_field, 3=both_fields */ - int FieldOrderCnt[2]; /**< field order count of top and bottom fields */ -} CUVIDH264DPBENTRY; - -/************************************************************/ -//! \struct CUVIDH264MVCEXT -//! H.264 MVC picture parameters ext -//! This structure is used in CUVIDH264PICPARAMS structure -/************************************************************/ -typedef struct _CUVIDH264MVCEXT -{ - int num_views_minus1; /**< Max number of coded views minus 1 in video : Range - 0 to 1023 */ - int view_id; /**< view identifier */ - unsigned char inter_view_flag; /**< 1 if used for inter-view prediction, 0 if not */ - unsigned char num_inter_view_refs_l0; /**< number of inter-view ref pics in RefPicList0 */ - unsigned char num_inter_view_refs_l1; /**< number of inter-view ref pics in RefPicList1 */ - unsigned char MVCReserved8Bits; /**< Reserved bits */ - int InterViewRefsL0[16]; /**< view id of the i-th view component for inter-view prediction in RefPicList0 */ - int InterViewRefsL1[16]; /**< view id of the i-th view component for inter-view prediction in RefPicList1 */ -} CUVIDH264MVCEXT; - -/*********************************************************/ -//! \struct CUVIDH264SVCEXT -//! H.264 SVC picture parameters ext -//! This structure is used in CUVIDH264PICPARAMS structure -/*********************************************************/ -typedef struct _CUVIDH264SVCEXT -{ - unsigned char profile_idc; - unsigned char level_idc; - unsigned char DQId; - unsigned char DQIdMax; - unsigned char disable_inter_layer_deblocking_filter_idc; - unsigned char ref_layer_chroma_phase_y_plus1; - signed char inter_layer_slice_alpha_c0_offset_div2; - signed char inter_layer_slice_beta_offset_div2; - - unsigned short DPBEntryValidFlag; - unsigned char inter_layer_deblocking_filter_control_present_flag; - unsigned char extended_spatial_scalability_idc; - unsigned char adaptive_tcoeff_level_prediction_flag; - unsigned char slice_header_restriction_flag; - unsigned char chroma_phase_x_plus1_flag; - unsigned char chroma_phase_y_plus1; - - unsigned char tcoeff_level_prediction_flag; - unsigned char constrained_intra_resampling_flag; - unsigned char ref_layer_chroma_phase_x_plus1_flag; - unsigned char store_ref_base_pic_flag; - unsigned char Reserved8BitsA; - unsigned char Reserved8BitsB; - - short scaled_ref_layer_left_offset; - short scaled_ref_layer_top_offset; - short scaled_ref_layer_right_offset; - short scaled_ref_layer_bottom_offset; - unsigned short Reserved16Bits; - struct _CUVIDPICPARAMS *pNextLayer; /**< Points to the picparams for the next layer to be decoded. - Linked list ends at the target layer. */ - int bRefBaseLayer; /**< whether to store ref base pic */ -} CUVIDH264SVCEXT; - -/******************************************************/ -//! \struct CUVIDH264PICPARAMS -//! H.264 picture parameters -//! This structure is used in CUVIDPICPARAMS structure -/******************************************************/ -typedef struct _CUVIDH264PICPARAMS -{ - // SPS - int log2_max_frame_num_minus4; - int pic_order_cnt_type; - int log2_max_pic_order_cnt_lsb_minus4; - int delta_pic_order_always_zero_flag; - int frame_mbs_only_flag; - int direct_8x8_inference_flag; - int num_ref_frames; // NOTE: shall meet level 4.1 restrictions - unsigned char residual_colour_transform_flag; - unsigned char bit_depth_luma_minus8; // Must be 0 (only 8-bit supported) - unsigned char bit_depth_chroma_minus8; // Must be 0 (only 8-bit supported) - unsigned char qpprime_y_zero_transform_bypass_flag; - // PPS - int entropy_coding_mode_flag; - int pic_order_present_flag; - int num_ref_idx_l0_active_minus1; - int num_ref_idx_l1_active_minus1; - int weighted_pred_flag; - int weighted_bipred_idc; - int pic_init_qp_minus26; - int deblocking_filter_control_present_flag; - int redundant_pic_cnt_present_flag; - int transform_8x8_mode_flag; - int MbaffFrameFlag; - int constrained_intra_pred_flag; - int chroma_qp_index_offset; - int second_chroma_qp_index_offset; - int ref_pic_flag; - int frame_num; - int CurrFieldOrderCnt[2]; - // DPB - CUVIDH264DPBENTRY dpb[16]; // List of reference frames within the DPB - // Quantization Matrices (raster-order) - unsigned char WeightScale4x4[6][16]; - unsigned char WeightScale8x8[2][64]; - // FMO/ASO - unsigned char fmo_aso_enable; - unsigned char num_slice_groups_minus1; - unsigned char slice_group_map_type; - signed char pic_init_qs_minus26; - unsigned int slice_group_change_rate_minus1; - union - { - unsigned long long slice_group_map_addr; - const unsigned char *pMb2SliceGroupMap; - } fmo; - unsigned int Reserved[12]; - // SVC/MVC - union - { - CUVIDH264MVCEXT mvcext; - CUVIDH264SVCEXT svcext; - }; -} CUVIDH264PICPARAMS; - - -/********************************************************/ -//! \struct CUVIDMPEG2PICPARAMS -//! MPEG-2 picture parameters -//! This structure is used in CUVIDPICPARAMS structure -/********************************************************/ -typedef struct _CUVIDMPEG2PICPARAMS -{ - int ForwardRefIdx; // Picture index of forward reference (P/B-frames) - int BackwardRefIdx; // Picture index of backward reference (B-frames) - int picture_coding_type; - int full_pel_forward_vector; - int full_pel_backward_vector; - int f_code[2][2]; - int intra_dc_precision; - int frame_pred_frame_dct; - int concealment_motion_vectors; - int q_scale_type; - int intra_vlc_format; - int alternate_scan; - int top_field_first; - // Quantization matrices (raster order) - unsigned char QuantMatrixIntra[64]; - unsigned char QuantMatrixInter[64]; -} CUVIDMPEG2PICPARAMS; - -// MPEG-4 has VOP types instead of Picture types -#define I_VOP 0 -#define P_VOP 1 -#define B_VOP 2 -#define S_VOP 3 - -/*******************************************************/ -//! \struct CUVIDMPEG4PICPARAMS -//! MPEG-4 picture parameters -//! This structure is used in CUVIDPICPARAMS structure -/*******************************************************/ -typedef struct _CUVIDMPEG4PICPARAMS -{ - int ForwardRefIdx; // Picture index of forward reference (P/B-frames) - int BackwardRefIdx; // Picture index of backward reference (B-frames) - // VOL - int video_object_layer_width; - int video_object_layer_height; - int vop_time_increment_bitcount; - int top_field_first; - int resync_marker_disable; - int quant_type; - int quarter_sample; - int short_video_header; - int divx_flags; - // VOP - int vop_coding_type; - int vop_coded; - int vop_rounding_type; - int alternate_vertical_scan_flag; - int interlaced; - int vop_fcode_forward; - int vop_fcode_backward; - int trd[2]; - int trb[2]; - // Quantization matrices (raster order) - unsigned char QuantMatrixIntra[64]; - unsigned char QuantMatrixInter[64]; - int gmc_enabled; -} CUVIDMPEG4PICPARAMS; - -/********************************************************/ -//! \struct CUVIDVC1PICPARAMS -//! VC1 picture parameters -//! This structure is used in CUVIDPICPARAMS structure -/********************************************************/ -typedef struct _CUVIDVC1PICPARAMS -{ - int ForwardRefIdx; /**< Picture index of forward reference (P/B-frames) */ - int BackwardRefIdx; /**< Picture index of backward reference (B-frames) */ - int FrameWidth; /**< Actual frame width */ - int FrameHeight; /**< Actual frame height */ - // PICTURE - int intra_pic_flag; /**< Set to 1 for I,BI frames */ - int ref_pic_flag; /**< Set to 1 for I,P frames */ - int progressive_fcm; /**< Progressive frame */ - // SEQUENCE - int profile; - int postprocflag; - int pulldown; - int interlace; - int tfcntrflag; - int finterpflag; - int psf; - int multires; - int syncmarker; - int rangered; - int maxbframes; - // ENTRYPOINT - int panscan_flag; - int refdist_flag; - int extended_mv; - int dquant; - int vstransform; - int loopfilter; - int fastuvmc; - int overlap; - int quantizer; - int extended_dmv; - int range_mapy_flag; - int range_mapy; - int range_mapuv_flag; - int range_mapuv; - int rangeredfrm; // range reduction state -} CUVIDVC1PICPARAMS; - -/***********************************************************/ -//! \struct CUVIDJPEGPICPARAMS -//! JPEG picture parameters -//! This structure is used in CUVIDPICPARAMS structure -/***********************************************************/ -typedef struct _CUVIDJPEGPICPARAMS -{ - int Reserved; -} CUVIDJPEGPICPARAMS; - - -/*******************************************************/ -//! \struct CUVIDHEVCPICPARAMS -//! HEVC picture parameters -//! This structure is used in CUVIDPICPARAMS structure -/*******************************************************/ -typedef struct _CUVIDHEVCPICPARAMS -{ - // sps - int pic_width_in_luma_samples; - int pic_height_in_luma_samples; - unsigned char log2_min_luma_coding_block_size_minus3; - unsigned char log2_diff_max_min_luma_coding_block_size; - unsigned char log2_min_transform_block_size_minus2; - unsigned char log2_diff_max_min_transform_block_size; - unsigned char pcm_enabled_flag; - unsigned char log2_min_pcm_luma_coding_block_size_minus3; - unsigned char log2_diff_max_min_pcm_luma_coding_block_size; - unsigned char pcm_sample_bit_depth_luma_minus1; - - unsigned char pcm_sample_bit_depth_chroma_minus1; - unsigned char pcm_loop_filter_disabled_flag; - unsigned char strong_intra_smoothing_enabled_flag; - unsigned char max_transform_hierarchy_depth_intra; - unsigned char max_transform_hierarchy_depth_inter; - unsigned char amp_enabled_flag; - unsigned char separate_colour_plane_flag; - unsigned char log2_max_pic_order_cnt_lsb_minus4; - - unsigned char num_short_term_ref_pic_sets; - unsigned char long_term_ref_pics_present_flag; - unsigned char num_long_term_ref_pics_sps; - unsigned char sps_temporal_mvp_enabled_flag; - unsigned char sample_adaptive_offset_enabled_flag; - unsigned char scaling_list_enable_flag; - unsigned char IrapPicFlag; - unsigned char IdrPicFlag; - - unsigned char bit_depth_luma_minus8; - unsigned char bit_depth_chroma_minus8; - unsigned char reserved1[14]; - - // pps - unsigned char dependent_slice_segments_enabled_flag; - unsigned char slice_segment_header_extension_present_flag; - unsigned char sign_data_hiding_enabled_flag; - unsigned char cu_qp_delta_enabled_flag; - unsigned char diff_cu_qp_delta_depth; - signed char init_qp_minus26; - signed char pps_cb_qp_offset; - signed char pps_cr_qp_offset; - - unsigned char constrained_intra_pred_flag; - unsigned char weighted_pred_flag; - unsigned char weighted_bipred_flag; - unsigned char transform_skip_enabled_flag; - unsigned char transquant_bypass_enabled_flag; - unsigned char entropy_coding_sync_enabled_flag; - unsigned char log2_parallel_merge_level_minus2; - unsigned char num_extra_slice_header_bits; - - unsigned char loop_filter_across_tiles_enabled_flag; - unsigned char loop_filter_across_slices_enabled_flag; - unsigned char output_flag_present_flag; - unsigned char num_ref_idx_l0_default_active_minus1; - unsigned char num_ref_idx_l1_default_active_minus1; - unsigned char lists_modification_present_flag; - unsigned char cabac_init_present_flag; - unsigned char pps_slice_chroma_qp_offsets_present_flag; - - unsigned char deblocking_filter_override_enabled_flag; - unsigned char pps_deblocking_filter_disabled_flag; - signed char pps_beta_offset_div2; - signed char pps_tc_offset_div2; - unsigned char tiles_enabled_flag; - unsigned char uniform_spacing_flag; - unsigned char num_tile_columns_minus1; - unsigned char num_tile_rows_minus1; - - unsigned short column_width_minus1[21]; - unsigned short row_height_minus1[21]; - unsigned int reserved3[15]; - - // RefPicSets - int NumBitsForShortTermRPSInSlice; - int NumDeltaPocsOfRefRpsIdx; - int NumPocTotalCurr; - int NumPocStCurrBefore; - int NumPocStCurrAfter; - int NumPocLtCurr; - int CurrPicOrderCntVal; - int RefPicIdx[16]; // [refpic] Indices of valid reference pictures (-1 if unused for reference) - int PicOrderCntVal[16]; // [refpic] - unsigned char IsLongTerm[16]; // [refpic] 0=not a long-term reference, 1=long-term reference - unsigned char RefPicSetStCurrBefore[8]; // [0..NumPocStCurrBefore-1] -> refpic (0..15) - unsigned char RefPicSetStCurrAfter[8]; // [0..NumPocStCurrAfter-1] -> refpic (0..15) - unsigned char RefPicSetLtCurr[8]; // [0..NumPocLtCurr-1] -> refpic (0..15) - unsigned char RefPicSetInterLayer0[8]; - unsigned char RefPicSetInterLayer1[8]; - unsigned int reserved4[12]; - - // scaling lists (diag order) - unsigned char ScalingList4x4[6][16]; // [matrixId][i] - unsigned char ScalingList8x8[6][64]; // [matrixId][i] - unsigned char ScalingList16x16[6][64]; // [matrixId][i] - unsigned char ScalingList32x32[2][64]; // [matrixId][i] - unsigned char ScalingListDCCoeff16x16[6]; // [matrixId] - unsigned char ScalingListDCCoeff32x32[2]; // [matrixId] -} CUVIDHEVCPICPARAMS; - - -/***********************************************************/ -//! \struct CUVIDVP8PICPARAMS -//! VP8 picture parameters -//! This structure is used in CUVIDPICPARAMS structure -/***********************************************************/ -typedef struct _CUVIDVP8PICPARAMS -{ - int width; - int height; - unsigned int first_partition_size; - //Frame Indexes - unsigned char LastRefIdx; - unsigned char GoldenRefIdx; - unsigned char AltRefIdx; - union { - struct { - unsigned char frame_type : 1; /**< 0 = KEYFRAME, 1 = INTERFRAME */ - unsigned char version : 3; - unsigned char show_frame : 1; - unsigned char update_mb_segmentation_data : 1; /**< Must be 0 if segmentation is not enabled */ - unsigned char Reserved2Bits : 2; - }; - unsigned char wFrameTagFlags; - }; - unsigned char Reserved1[4]; - unsigned int Reserved2[3]; -} CUVIDVP8PICPARAMS; - -/***********************************************************/ -//! \struct CUVIDVP9PICPARAMS -//! VP9 picture parameters -//! This structure is used in CUVIDPICPARAMS structure -/***********************************************************/ -typedef struct _CUVIDVP9PICPARAMS -{ - unsigned int width; - unsigned int height; - - //Frame Indices - unsigned char LastRefIdx; - unsigned char GoldenRefIdx; - unsigned char AltRefIdx; - unsigned char colorSpace; - - unsigned short profile : 3; - unsigned short frameContextIdx : 2; - unsigned short frameType : 1; - unsigned short showFrame : 1; - unsigned short errorResilient : 1; - unsigned short frameParallelDecoding : 1; - unsigned short subSamplingX : 1; - unsigned short subSamplingY : 1; - unsigned short intraOnly : 1; - unsigned short allow_high_precision_mv : 1; - unsigned short refreshEntropyProbs : 1; - unsigned short reserved2Bits : 2; - - unsigned short reserved16Bits; - - unsigned char refFrameSignBias[4]; - - unsigned char bitDepthMinus8Luma; - unsigned char bitDepthMinus8Chroma; - unsigned char loopFilterLevel; - unsigned char loopFilterSharpness; - - unsigned char modeRefLfEnabled; - unsigned char log2_tile_columns; - unsigned char log2_tile_rows; - - unsigned char segmentEnabled : 1; - unsigned char segmentMapUpdate : 1; - unsigned char segmentMapTemporalUpdate : 1; - unsigned char segmentFeatureMode : 1; - unsigned char reserved4Bits : 4; - - - unsigned char segmentFeatureEnable[8][4]; - short segmentFeatureData[8][4]; - unsigned char mb_segment_tree_probs[7]; - unsigned char segment_pred_probs[3]; - unsigned char reservedSegment16Bits[2]; - - int qpYAc; - int qpYDc; - int qpChDc; - int qpChAc; - - unsigned int activeRefIdx[3]; - unsigned int resetFrameContext; - unsigned int mcomp_filter_type; - unsigned int mbRefLfDelta[4]; - unsigned int mbModeLfDelta[2]; - unsigned int frameTagSize; - unsigned int offsetToDctParts; - unsigned int reserved128Bits[4]; - -} CUVIDVP9PICPARAMS; - - -/******************************************************************************************/ -//! \struct CUVIDPICPARAMS -//! Picture parameters for decoding -//! This structure is used in cuvidDecodePicture API -//! IN for cuvidDecodePicture -/******************************************************************************************/ -typedef struct _CUVIDPICPARAMS -{ - int PicWidthInMbs; /**< IN: Coded frame size in macroblocks */ - int FrameHeightInMbs; /**< IN: Coded frame height in macroblocks */ - int CurrPicIdx; /**< IN: Output index of the current picture */ - int field_pic_flag; /**< IN: 0=frame picture, 1=field picture */ - int bottom_field_flag; /**< IN: 0=top field, 1=bottom field (ignored if field_pic_flag=0) */ - int second_field; /**< IN: Second field of a complementary field pair */ - // Bitstream data - unsigned int nBitstreamDataLen; /**< IN: Number of bytes in bitstream data buffer */ - const unsigned char *pBitstreamData; /**< IN: Ptr to bitstream data for this picture (slice-layer) */ - unsigned int nNumSlices; /**< IN: Number of slices in this picture */ - const unsigned int *pSliceDataOffsets; /**< IN: nNumSlices entries, contains offset of each slice within - the bitstream data buffer */ - int ref_pic_flag; /**< IN: This picture is a reference picture */ - int intra_pic_flag; /**< IN: This picture is entirely intra coded */ - unsigned int Reserved[30]; /**< Reserved for future use */ - // IN: Codec-specific data - union { - CUVIDMPEG2PICPARAMS mpeg2; /**< Also used for MPEG-1 */ - CUVIDH264PICPARAMS h264; - CUVIDVC1PICPARAMS vc1; - CUVIDMPEG4PICPARAMS mpeg4; - CUVIDJPEGPICPARAMS jpeg; - CUVIDHEVCPICPARAMS hevc; - CUVIDVP8PICPARAMS vp8; - CUVIDVP9PICPARAMS vp9; - unsigned int CodecReserved[1024]; - } CodecSpecific; -} CUVIDPICPARAMS; - - -/******************************************************/ -//! \struct CUVIDPROCPARAMS -//! Picture parameters for postprocessing -//! This structure is used in cuvidMapVideoFrame API -/******************************************************/ -typedef struct _CUVIDPROCPARAMS -{ - int progressive_frame; /**< IN: Input is progressive (deinterlace_mode will be ignored) */ - int second_field; /**< IN: Output the second field (ignored if deinterlace mode is Weave) */ - int top_field_first; /**< IN: Input frame is top field first (1st field is top, 2nd field is bottom) */ - int unpaired_field; /**< IN: Input only contains one field (2nd field is invalid) */ - // The fields below are used for raw YUV input - unsigned int reserved_flags; /**< Reserved for future use (set to zero) */ - unsigned int reserved_zero; /**< Reserved (set to zero) */ - unsigned long long raw_input_dptr; /**< IN: Input CUdeviceptr for raw YUV extensions */ - unsigned int raw_input_pitch; /**< IN: pitch in bytes of raw YUV input (should be aligned appropriately) */ - unsigned int raw_input_format; /**< IN: Input YUV format (cudaVideoCodec_enum) */ - unsigned long long raw_output_dptr; /**< IN: Output CUdeviceptr for raw YUV extensions */ - unsigned int raw_output_pitch; /**< IN: pitch in bytes of raw YUV output (should be aligned appropriately) */ - unsigned int Reserved1; /**< Reserved for future use (set to zero) */ - CUstream output_stream; /**< IN: stream object used by cuvidMapVideoFrame */ - unsigned int Reserved[46]; /**< Reserved for future use (set to zero) */ - void *Reserved2[2]; /**< Reserved for future use (set to zero) */ -} CUVIDPROCPARAMS; - - -/***********************************************************************************************************/ -//! VIDEO_DECODER -//! -//! In order to minimize decode latencies, there should be always at least 2 pictures in the decode -//! queue at any time, in order to make sure that all decode engines are always busy. -//! -//! Overall data flow: -//! - cuvidGetDecoderCaps(...) -//! - cuvidCreateDecoder(...) -//! - For each picture: -//! + cuvidDecodePicture(N) -//! + cuvidMapVideoFrame(N-4) -//! + do some processing in cuda -//! + cuvidUnmapVideoFrame(N-4) -//! + cuvidDecodePicture(N+1) -//! + cuvidMapVideoFrame(N-3) -//! + ... -//! - cuvidDestroyDecoder(...) -//! -//! NOTE: -//! - When the cuda context is created from a D3D device, the D3D device must also be created -//! with the D3DCREATE_MULTITHREADED flag. -//! - There is a limit to how many pictures can be mapped simultaneously (ulNumOutputSurfaces) -//! - cuvidDecodePicture may block the calling thread if there are too many pictures pending -//! in the decode queue -/***********************************************************************************************************/ - - -/**********************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidGetDecoderCaps(CUVIDDECODECAPS *pdc) -//! Queries decode capabilities of NVDEC-HW based on CodecType, ChromaFormat and BitDepthMinus8 parameters. -//! 1. Application fills IN parameters CodecType, ChromaFormat and BitDepthMinus8 of CUVIDDECODECAPS structure -//! 2. On calling cuvidGetDecoderCaps, driver fills OUT parameters if the IN parameters are supported -//! If IN parameters passed to the driver are not supported by NVDEC-HW, then all OUT params are set to 0. -//! E.g. on Geforce GTX 960: -//! App fills - eCodecType = cudaVideoCodec_H264; eChromaFormat = cudaVideoChromaFormat_420; nBitDepthMinus8 = 0; -//! Given IN parameters are supported, hence driver fills: bIsSupported = 1; nMinWidth = 48; nMinHeight = 16; -//! nMaxWidth = 4096; nMaxHeight = 4096; nMaxMBCount = 65536; -//! CodedWidth*CodedHeight/256 must be less than or equal to nMaxMBCount -/**********************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidGetDecoderCaps(CUVIDDECODECAPS *pdc); - -/********************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidCreateDecoder(CUvideodecoder *phDecoder, CUVIDDECODECREATEINFO *pdci) -//! Create the decoder object based on pdci. A handle to the created decoder is returned -/********************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidCreateDecoder(CUvideodecoder *phDecoder, CUVIDDECODECREATEINFO *pdci); -/********************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidDestroyDecoder(CUvideodecoder hDecoder) -//! Destroy the decoder object. -/********************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidDestroyDecoder(CUvideodecoder hDecoder); - -/********************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidDecodePicture(CUvideodecoder hDecoder, CUVIDPICPARAMS *pPicParams) -//! Decode a single picture (field or frame) -//! Kicks off HW decoding -/********************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidDecodePicture(CUvideodecoder hDecoder, CUVIDPICPARAMS *pPicParams); - - -#if !defined(__CUVID_DEVPTR64) || defined(__CUVID_INTERNAL) -/************************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidMapVideoFrame(CUvideodecoder hDecoder, int nPicIdx, unsigned int *pDevPtr, -//! unsigned int *pPitch, CUVIDPROCPARAMS *pVPP); -//! Post-process and map video frame corresponding to nPicIdx for use in cuda. Returns cuda device pointer and associated -//! pitch of the video frame -/************************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidMapVideoFrame(CUvideodecoder hDecoder, int nPicIdx, - unsigned int *pDevPtr, unsigned int *pPitch, - CUVIDPROCPARAMS *pVPP); - -/********************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidUnmapVideoFrame(CUvideodecoder hDecoder, unsigned int DevPtr) -//! Unmap a previously mapped video frame -/********************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidUnmapVideoFrame(CUvideodecoder hDecoder, unsigned int DevPtr); -#endif - -#if defined(_WIN64) || defined(__LP64__) || defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) -/************************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidMapVideoFrame64(CUvideodecoder hDecoder, int nPicIdx, unsigned long long *pDevPtr, -//! unsigned int *pPitch, CUVIDPROCPARAMS *pVPP); -//! Post-process and map video frame corresponding to nPicIdx for use in cuda. Returns cuda device pointer and associated -//! pitch of the video frame -/************************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidMapVideoFrame64(CUvideodecoder hDecoder, int nPicIdx, unsigned long long *pDevPtr, - unsigned int *pPitch, CUVIDPROCPARAMS *pVPP); - -/********************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidUnmapVideoFrame64(CUvideodecoder hDecoder, unsigned long long DevPtr); -//! Unmap a previously mapped video frame -/********************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidUnmapVideoFrame64(CUvideodecoder hDecoder, unsigned long long DevPtr); - -#if defined(__CUVID_DEVPTR64) && !defined(__CUVID_INTERNAL) -#define tcuvidMapVideoFrame tcuvidMapVideoFrame64 -#define tcuvidUnmapVideoFrame tcuvidUnmapVideoFrame64 -#endif -#endif - - - -/********************************************************************************************************************/ -//! -//! Context-locking: to facilitate multi-threaded implementations, the following 4 functions -//! provide a simple mutex-style host synchronization. If a non-NULL context is specified -//! in CUVIDDECODECREATEINFO, the codec library will acquire the mutex associated with the given -//! context before making any cuda calls. -//! A multi-threaded application could create a lock associated with a context handle so that -//! multiple threads can safely share the same cuda context: -//! - use cuCtxPopCurrent immediately after context creation in order to create a 'floating' context -//! that can be passed to cuvidCtxLockCreate. -//! - When using a floating context, all cuda calls should only be made within a cuvidCtxLock/cuvidCtxUnlock section. -//! -//! NOTE: This is a safer alternative to cuCtxPushCurrent and cuCtxPopCurrent, and is not related to video -//! decoder in any way (implemented as a critical section associated with cuCtx{Push|Pop}Current calls). -/********************************************************************************************************************/ - -/********************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidCtxLockCreate(CUvideoctxlock *pLock, CUcontext ctx) -//! This API is used to create CtxLock object -/********************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidCtxLockCreate(CUvideoctxlock *pLock, CUcontext ctx); - -/********************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidCtxLockDestroy(CUvideoctxlock lck) -//! This API is used to free CtxLock object -/********************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidCtxLockDestroy(CUvideoctxlock lck); - -/********************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidCtxLock(CUvideoctxlock lck, unsigned int reserved_flags) -//! This API is used to acquire ctxlock -/********************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidCtxLock(CUvideoctxlock lck, unsigned int reserved_flags); - -/********************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidCtxUnlock(CUvideoctxlock lck, unsigned int reserved_flags) -//! This API is used to release ctxlock -/********************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidCtxUnlock(CUvideoctxlock lck, unsigned int reserved_flags); - -/**********************************************************************************************/ - -#if defined(__cplusplus) -} -#endif /* __cplusplus */ - -#endif // __CUDA_VIDEO_H__ diff --git a/compat/cuda/dynlink_loader.h b/compat/cuda/dynlink_loader.h index fa43782c9ac48..9f93465088ed1 100644 --- a/compat/cuda/dynlink_loader.h +++ b/compat/cuda/dynlink_loader.h @@ -1,268 +1,33 @@ /* - * This copyright notice applies to this header file only: + * This file is part of FFmpeg. * - * Copyright (c) 2016 + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the software, and to permit persons to whom the - * software is furnished to do so, subject to the following - * conditions: + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef AV_COMPAT_CUDA_DYNLINK_LOADER_H #define AV_COMPAT_CUDA_DYNLINK_LOADER_H -#include "compat/cuda/dynlink_cuda.h" -#include "compat/cuda/dynlink_nvcuvid.h" -#include "compat/nvenc/nvEncodeAPI.h" -#include "compat/w32dlfcn.h" - #include "libavutil/log.h" -#include "libavutil/error.h" - -#if defined(_WIN32) -# define LIB_HANDLE HMODULE -#else -# define LIB_HANDLE void* -#endif - -#if defined(_WIN32) || defined(__CYGWIN__) -# define CUDA_LIBNAME "nvcuda.dll" -# define NVCUVID_LIBNAME "nvcuvid.dll" -# if ARCH_X86_64 -# define NVENC_LIBNAME "nvEncodeAPI64.dll" -# else -# define NVENC_LIBNAME "nvEncodeAPI.dll" -# endif -#else -# define CUDA_LIBNAME "libcuda.so.1" -# define NVCUVID_LIBNAME "libnvcuvid.so.1" -# define NVENC_LIBNAME "libnvidia-encode.so.1" -#endif - -#define LOAD_LIBRARY(l, path) \ - do { \ - if (!((l) = dlopen(path, RTLD_LAZY))) { \ - av_log(logctx, AV_LOG_ERROR, "Cannot load %s\n", path); \ - ret = AVERROR_UNKNOWN; \ - goto error; \ - } \ - av_log(logctx, AV_LOG_TRACE, "Loaded lib: %s\n", path); \ - } while (0) - -#define LOAD_SYMBOL(fun, tp, symbol) \ - do { \ - if (!((f->fun) = (tp*)dlsym(f->lib, symbol))) { \ - av_log(logctx, AV_LOG_ERROR, "Cannot load %s\n", symbol); \ - ret = AVERROR_UNKNOWN; \ - goto error; \ - } \ - av_log(logctx, AV_LOG_TRACE, "Loaded sym: %s\n", symbol); \ - } while (0) - -#define LOAD_SYMBOL_OPT(fun, tp, symbol) \ - do { \ - if (!((f->fun) = (tp*)dlsym(f->lib, symbol))) { \ - av_log(logctx, AV_LOG_DEBUG, "Cannot load optional %s\n", symbol); \ - } else { \ - av_log(logctx, AV_LOG_TRACE, "Loaded sym: %s\n", symbol); \ - } \ - } while (0) - -#define GENERIC_LOAD_FUNC_PREAMBLE(T, n, N) \ - T *f; \ - int ret; \ - \ - n##_free_functions(functions); \ - \ - f = *functions = av_mallocz(sizeof(*f)); \ - if (!f) \ - return AVERROR(ENOMEM); \ - \ - LOAD_LIBRARY(f->lib, N); - -#define GENERIC_LOAD_FUNC_FINALE(n) \ - return 0; \ -error: \ - n##_free_functions(functions); \ - return ret; - -#define GENERIC_FREE_FUNC() \ - if (!functions) \ - return; \ - if (*functions && (*functions)->lib) \ - dlclose((*functions)->lib); \ - av_freep(functions); - -#ifdef AV_COMPAT_DYNLINK_CUDA_H -typedef struct CudaFunctions { - tcuInit *cuInit; - tcuDeviceGetCount *cuDeviceGetCount; - tcuDeviceGet *cuDeviceGet; - tcuDeviceGetName *cuDeviceGetName; - tcuDeviceComputeCapability *cuDeviceComputeCapability; - tcuCtxCreate_v2 *cuCtxCreate; - tcuCtxPushCurrent_v2 *cuCtxPushCurrent; - tcuCtxPopCurrent_v2 *cuCtxPopCurrent; - tcuCtxDestroy_v2 *cuCtxDestroy; - tcuMemAlloc_v2 *cuMemAlloc; - tcuMemFree_v2 *cuMemFree; - tcuMemcpy2D_v2 *cuMemcpy2D; - tcuGetErrorName *cuGetErrorName; - tcuGetErrorString *cuGetErrorString; - - LIB_HANDLE lib; -} CudaFunctions; -#else -typedef struct CudaFunctions CudaFunctions; -#endif - -typedef struct CuvidFunctions { - tcuvidGetDecoderCaps *cuvidGetDecoderCaps; - tcuvidCreateDecoder *cuvidCreateDecoder; - tcuvidDestroyDecoder *cuvidDestroyDecoder; - tcuvidDecodePicture *cuvidDecodePicture; - tcuvidMapVideoFrame *cuvidMapVideoFrame; - tcuvidUnmapVideoFrame *cuvidUnmapVideoFrame; - tcuvidCtxLockCreate *cuvidCtxLockCreate; - tcuvidCtxLockDestroy *cuvidCtxLockDestroy; - tcuvidCtxLock *cuvidCtxLock; - tcuvidCtxUnlock *cuvidCtxUnlock; - - tcuvidCreateVideoSource *cuvidCreateVideoSource; - tcuvidCreateVideoSourceW *cuvidCreateVideoSourceW; - tcuvidDestroyVideoSource *cuvidDestroyVideoSource; - tcuvidSetVideoSourceState *cuvidSetVideoSourceState; - tcuvidGetVideoSourceState *cuvidGetVideoSourceState; - tcuvidGetSourceVideoFormat *cuvidGetSourceVideoFormat; - tcuvidGetSourceAudioFormat *cuvidGetSourceAudioFormat; - tcuvidCreateVideoParser *cuvidCreateVideoParser; - tcuvidParseVideoData *cuvidParseVideoData; - tcuvidDestroyVideoParser *cuvidDestroyVideoParser; - - LIB_HANDLE lib; -} CuvidFunctions; - -typedef NVENCSTATUS NVENCAPI tNvEncodeAPICreateInstance(NV_ENCODE_API_FUNCTION_LIST *functionList); -typedef NVENCSTATUS NVENCAPI tNvEncodeAPIGetMaxSupportedVersion(uint32_t* version); - -typedef struct NvencFunctions { - tNvEncodeAPICreateInstance *NvEncodeAPICreateInstance; - tNvEncodeAPIGetMaxSupportedVersion *NvEncodeAPIGetMaxSupportedVersion; - - LIB_HANDLE lib; -} NvencFunctions; - -#ifdef AV_COMPAT_DYNLINK_CUDA_H -static inline void cuda_free_functions(CudaFunctions **functions) -{ - GENERIC_FREE_FUNC(); -} -#endif - -static inline void cuvid_free_functions(CuvidFunctions **functions) -{ - GENERIC_FREE_FUNC(); -} - -static inline void nvenc_free_functions(NvencFunctions **functions) -{ - GENERIC_FREE_FUNC(); -} - -#ifdef AV_COMPAT_DYNLINK_CUDA_H -static inline int cuda_load_functions(CudaFunctions **functions, void *logctx) -{ - GENERIC_LOAD_FUNC_PREAMBLE(CudaFunctions, cuda, CUDA_LIBNAME); - - LOAD_SYMBOL(cuInit, tcuInit, "cuInit"); - LOAD_SYMBOL(cuDeviceGetCount, tcuDeviceGetCount, "cuDeviceGetCount"); - LOAD_SYMBOL(cuDeviceGet, tcuDeviceGet, "cuDeviceGet"); - LOAD_SYMBOL(cuDeviceGetName, tcuDeviceGetName, "cuDeviceGetName"); - LOAD_SYMBOL(cuDeviceComputeCapability, tcuDeviceComputeCapability, "cuDeviceComputeCapability"); - LOAD_SYMBOL(cuCtxCreate, tcuCtxCreate_v2, "cuCtxCreate_v2"); - LOAD_SYMBOL(cuCtxPushCurrent, tcuCtxPushCurrent_v2, "cuCtxPushCurrent_v2"); - LOAD_SYMBOL(cuCtxPopCurrent, tcuCtxPopCurrent_v2, "cuCtxPopCurrent_v2"); - LOAD_SYMBOL(cuCtxDestroy, tcuCtxDestroy_v2, "cuCtxDestroy_v2"); - LOAD_SYMBOL(cuMemAlloc, tcuMemAlloc_v2, "cuMemAlloc_v2"); - LOAD_SYMBOL(cuMemFree, tcuMemFree_v2, "cuMemFree_v2"); - LOAD_SYMBOL(cuMemcpy2D, tcuMemcpy2D_v2, "cuMemcpy2D_v2"); - LOAD_SYMBOL(cuGetErrorName, tcuGetErrorName, "cuGetErrorName"); - LOAD_SYMBOL(cuGetErrorString, tcuGetErrorString, "cuGetErrorString"); - - GENERIC_LOAD_FUNC_FINALE(cuda); -} -#endif - -static inline int cuvid_load_functions(CuvidFunctions **functions, void *logctx) -{ - GENERIC_LOAD_FUNC_PREAMBLE(CuvidFunctions, cuvid, NVCUVID_LIBNAME); - - LOAD_SYMBOL_OPT(cuvidGetDecoderCaps, tcuvidGetDecoderCaps, "cuvidGetDecoderCaps"); - LOAD_SYMBOL(cuvidCreateDecoder, tcuvidCreateDecoder, "cuvidCreateDecoder"); - LOAD_SYMBOL(cuvidDestroyDecoder, tcuvidDestroyDecoder, "cuvidDestroyDecoder"); - LOAD_SYMBOL(cuvidDecodePicture, tcuvidDecodePicture, "cuvidDecodePicture"); -#ifdef __CUVID_DEVPTR64 - LOAD_SYMBOL(cuvidMapVideoFrame, tcuvidMapVideoFrame, "cuvidMapVideoFrame64"); - LOAD_SYMBOL(cuvidUnmapVideoFrame, tcuvidUnmapVideoFrame, "cuvidUnmapVideoFrame64"); -#else - LOAD_SYMBOL(cuvidMapVideoFrame, tcuvidMapVideoFrame, "cuvidMapVideoFrame"); - LOAD_SYMBOL(cuvidUnmapVideoFrame, tcuvidUnmapVideoFrame, "cuvidUnmapVideoFrame"); -#endif - LOAD_SYMBOL(cuvidCtxLockCreate, tcuvidCtxLockCreate, "cuvidCtxLockCreate"); - LOAD_SYMBOL(cuvidCtxLockDestroy, tcuvidCtxLockDestroy, "cuvidCtxLockDestroy"); - LOAD_SYMBOL(cuvidCtxLock, tcuvidCtxLock, "cuvidCtxLock"); - LOAD_SYMBOL(cuvidCtxUnlock, tcuvidCtxUnlock, "cuvidCtxUnlock"); - - LOAD_SYMBOL(cuvidCreateVideoSource, tcuvidCreateVideoSource, "cuvidCreateVideoSource"); - LOAD_SYMBOL(cuvidCreateVideoSourceW, tcuvidCreateVideoSourceW, "cuvidCreateVideoSourceW"); - LOAD_SYMBOL(cuvidDestroyVideoSource, tcuvidDestroyVideoSource, "cuvidDestroyVideoSource"); - LOAD_SYMBOL(cuvidSetVideoSourceState, tcuvidSetVideoSourceState, "cuvidSetVideoSourceState"); - LOAD_SYMBOL(cuvidGetVideoSourceState, tcuvidGetVideoSourceState, "cuvidGetVideoSourceState"); - LOAD_SYMBOL(cuvidGetSourceVideoFormat, tcuvidGetSourceVideoFormat, "cuvidGetSourceVideoFormat"); - LOAD_SYMBOL(cuvidGetSourceAudioFormat, tcuvidGetSourceAudioFormat, "cuvidGetSourceAudioFormat"); - LOAD_SYMBOL(cuvidCreateVideoParser, tcuvidCreateVideoParser, "cuvidCreateVideoParser"); - LOAD_SYMBOL(cuvidParseVideoData, tcuvidParseVideoData, "cuvidParseVideoData"); - LOAD_SYMBOL(cuvidDestroyVideoParser, tcuvidDestroyVideoParser, "cuvidDestroyVideoParser"); - - GENERIC_LOAD_FUNC_FINALE(cuvid); -} - -static inline int nvenc_load_functions(NvencFunctions **functions, void *logctx) -{ - GENERIC_LOAD_FUNC_PREAMBLE(NvencFunctions, nvenc, NVENC_LIBNAME); - - LOAD_SYMBOL(NvEncodeAPICreateInstance, tNvEncodeAPICreateInstance, "NvEncodeAPICreateInstance"); - LOAD_SYMBOL(NvEncodeAPIGetMaxSupportedVersion, tNvEncodeAPIGetMaxSupportedVersion, "NvEncodeAPIGetMaxSupportedVersion"); +#include "compat/w32dlfcn.h" - GENERIC_LOAD_FUNC_FINALE(nvenc); -} +#define FFNV_LOAD_FUNC(path) dlopen((path), RTLD_LAZY) +#define FFNV_SYM_FUNC(lib, sym) dlsym((lib), (sym)) +#define FFNV_FREE_FUNC(lib) dlclose(lib) +#define FFNV_LOG_FUNC(logctx, msg, ...) av_log(logctx, AV_LOG_ERROR, msg, __VA_ARGS__) +#define FFNV_DEBUG_LOG_FUNC(logctx, msg, ...) av_log(logctx, AV_LOG_DEBUG, msg, __VA_ARGS__) -#undef GENERIC_LOAD_FUNC_PREAMBLE -#undef LOAD_LIBRARY -#undef LOAD_SYMBOL -#undef GENERIC_LOAD_FUNC_FINALE -#undef GENERIC_FREE_FUNC -#undef CUDA_LIBNAME -#undef NVCUVID_LIBNAME -#undef NVENC_LIBNAME -#undef LIB_HANDLE +#include #endif - diff --git a/compat/cuda/dynlink_nvcuvid.h b/compat/cuda/dynlink_nvcuvid.h deleted file mode 100644 index 87294248e5a72..0000000000000 --- a/compat/cuda/dynlink_nvcuvid.h +++ /dev/null @@ -1,356 +0,0 @@ -/* - * This copyright notice applies to this header file only: - * - * Copyright (c) 2010-2017 NVIDIA Corporation - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the software, and to permit persons to whom the - * software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/********************************************************************************************************************/ -//! \file nvcuvid.h -//! NVDECODE API provides video decoding interface to NVIDIA GPU devices. -//! \date 2015-2017 -//! This file contains the interface constants, structure definitions and function prototypes. -/********************************************************************************************************************/ - -#if !defined(__NVCUVID_H__) -#define __NVCUVID_H__ - -#include "compat/cuda/dynlink_cuviddec.h" - -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus */ - -/********************************* -** Initialization -*********************************/ -CUresult CUDAAPI cuvidInit(unsigned int Flags); - -/***********************************************/ -//! -//! High-level helper APIs for video sources -//! -/***********************************************/ - -typedef void *CUvideosource; -typedef void *CUvideoparser; -typedef long long CUvideotimestamp; - - -/************************************************************************/ -//! \enum cudaVideoState -//! Video source state enums -//! Used in cuvidSetVideoSourceState and cuvidGetVideoSourceState APIs -/************************************************************************/ -typedef enum { - cudaVideoState_Error = -1, /**< Error state (invalid source) */ - cudaVideoState_Stopped = 0, /**< Source is stopped (or reached end-of-stream) */ - cudaVideoState_Started = 1 /**< Source is running and delivering data */ -} cudaVideoState; - -/************************************************************************/ -//! \enum cudaAudioCodec -//! Audio compression enums -//! Used in CUAUDIOFORMAT structure -/************************************************************************/ -typedef enum { - cudaAudioCodec_MPEG1=0, /**< MPEG-1 Audio */ - cudaAudioCodec_MPEG2, /**< MPEG-2 Audio */ - cudaAudioCodec_MP3, /**< MPEG-1 Layer III Audio */ - cudaAudioCodec_AC3, /**< Dolby Digital (AC3) Audio */ - cudaAudioCodec_LPCM, /**< PCM Audio */ - cudaAudioCodec_AAC, /**< AAC Audio */ -} cudaAudioCodec; - -/************************************************************************************************/ -//! \ingroup STRUCTS -//! \struct CUVIDEOFORMAT -//! Video format -//! Used in cuvidGetSourceVideoFormat API -/************************************************************************************************/ -typedef struct -{ - cudaVideoCodec codec; /**< OUT: Compression format */ - /** - * OUT: frame rate = numerator / denominator (for example: 30000/1001) - */ - struct { - /**< OUT: frame rate numerator (0 = unspecified or variable frame rate) */ - unsigned int numerator; - /**< OUT: frame rate denominator (0 = unspecified or variable frame rate) */ - unsigned int denominator; - } frame_rate; - unsigned char progressive_sequence; /**< OUT: 0=interlaced, 1=progressive */ - unsigned char bit_depth_luma_minus8; /**< OUT: high bit depth luma. E.g, 2 for 10-bitdepth, 4 for 12-bitdepth */ - unsigned char bit_depth_chroma_minus8; /**< OUT: high bit depth chroma. E.g, 2 for 10-bitdepth, 4 for 12-bitdepth */ - unsigned char reserved1; /**< Reserved for future use */ - unsigned int coded_width; /**< OUT: coded frame width in pixels */ - unsigned int coded_height; /**< OUT: coded frame height in pixels */ - /** - * area of the frame that should be displayed - * typical example: - * coded_width = 1920, coded_height = 1088 - * display_area = { 0,0,1920,1080 } - */ - struct { - int left; /**< OUT: left position of display rect */ - int top; /**< OUT: top position of display rect */ - int right; /**< OUT: right position of display rect */ - int bottom; /**< OUT: bottom position of display rect */ - } display_area; - cudaVideoChromaFormat chroma_format; /**< OUT: Chroma format */ - unsigned int bitrate; /**< OUT: video bitrate (bps, 0=unknown) */ - /** - * OUT: Display Aspect Ratio = x:y (4:3, 16:9, etc) - */ - struct { - int x; - int y; - } display_aspect_ratio; - /** - * Video Signal Description - * Refer section E.2.1 (VUI parameters semantics) of H264 spec file - */ - struct { - unsigned char video_format : 3; /**< OUT: 0-Component, 1-PAL, 2-NTSC, 3-SECAM, 4-MAC, 5-Unspecified */ - unsigned char video_full_range_flag : 1; /**< OUT: indicates the black level and luma and chroma range */ - unsigned char reserved_zero_bits : 4; /**< Reserved bits */ - unsigned char color_primaries; /**< OUT: chromaticity coordinates of source primaries */ - unsigned char transfer_characteristics; /**< OUT: opto-electronic transfer characteristic of the source picture */ - unsigned char matrix_coefficients; /**< OUT: used in deriving luma and chroma signals from RGB primaries */ - } video_signal_description; - unsigned int seqhdr_data_length; /**< OUT: Additional bytes following (CUVIDEOFORMATEX) */ -} CUVIDEOFORMAT; - -/****************************************************************/ -//! \ingroup STRUCTS -//! \struct CUVIDEOFORMATEX -//! Video format including raw sequence header information -//! Used in cuvidGetSourceVideoFormat API -/****************************************************************/ -typedef struct -{ - CUVIDEOFORMAT format; /**< OUT: CUVIDEOFORMAT structure */ - unsigned char raw_seqhdr_data[1024]; /**< OUT: Sequence header data */ -} CUVIDEOFORMATEX; - -/****************************************************************/ -//! \ingroup STRUCTS -//! \struct CUAUDIOFORMAT -//! Audio formats -//! Used in cuvidGetSourceAudioFormat API -/****************************************************************/ -typedef struct -{ - cudaAudioCodec codec; /**< OUT: Compression format */ - unsigned int channels; /**< OUT: number of audio channels */ - unsigned int samplespersec; /**< OUT: sampling frequency */ - unsigned int bitrate; /**< OUT: For uncompressed, can also be used to determine bits per sample */ - unsigned int reserved1; /**< Reserved for future use */ - unsigned int reserved2; /**< Reserved for future use */ -} CUAUDIOFORMAT; - - -/***************************************************************/ -//! \enum CUvideopacketflags -//! Data packet flags -//! Used in CUVIDSOURCEDATAPACKET structure -/***************************************************************/ -typedef enum { - CUVID_PKT_ENDOFSTREAM = 0x01, /**< Set when this is the last packet for this stream */ - CUVID_PKT_TIMESTAMP = 0x02, /**< Timestamp is valid */ - CUVID_PKT_DISCONTINUITY = 0x04, /**< Set when a discontinuity has to be signalled */ - CUVID_PKT_ENDOFPICTURE = 0x08, /**< Set when the packet contains exactly one frame */ -} CUvideopacketflags; - -/*****************************************************************************/ -//! \ingroup STRUCTS -//! \struct CUVIDSOURCEDATAPACKET -//! Data Packet -//! Used in cuvidParseVideoData API -//! IN for cuvidParseVideoData -/*****************************************************************************/ -typedef struct _CUVIDSOURCEDATAPACKET -{ - tcu_ulong flags; /**< IN: Combination of CUVID_PKT_XXX flags */ - tcu_ulong payload_size; /**< IN: number of bytes in the payload (may be zero if EOS flag is set) */ - const unsigned char *payload; /**< IN: Pointer to packet payload data (may be NULL if EOS flag is set) */ - CUvideotimestamp timestamp; /**< IN: Presentation time stamp (10MHz clock), only valid if - CUVID_PKT_TIMESTAMP flag is set */ -} CUVIDSOURCEDATAPACKET; - -// Callback for packet delivery -typedef int (CUDAAPI *PFNVIDSOURCECALLBACK)(void *, CUVIDSOURCEDATAPACKET *); - -/**************************************************************************************************************************/ -//! \ingroup STRUCTS -//! \struct CUVIDSOURCEPARAMS -//! Describes parameters needed in cuvidCreateVideoSource API -//! NVDECODE API is intended for HW accelerated video decoding so CUvideosource doesn't have audio demuxer for all supported -//! containers. It's recommended to clients to use their own or third party demuxer if audio support is needed. -/**************************************************************************************************************************/ -typedef struct _CUVIDSOURCEPARAMS -{ - unsigned int ulClockRate; /**< IN: Time stamp units in Hz (0=default=10000000Hz) */ - unsigned int uReserved1[7]; /**< Reserved for future use - set to zero */ - void *pUserData; /**< IN: User private data passed in to the data handlers */ - PFNVIDSOURCECALLBACK pfnVideoDataHandler; /**< IN: Called to deliver video packets */ - PFNVIDSOURCECALLBACK pfnAudioDataHandler; /**< IN: Called to deliver audio packets. */ - void *pvReserved2[8]; /**< Reserved for future use - set to NULL */ -} CUVIDSOURCEPARAMS; - - -/**********************************************/ -//! \ingroup ENUMS -//! \enum CUvideosourceformat_flags -//! CUvideosourceformat_flags -//! Used in cuvidGetSourceVideoFormat API -/**********************************************/ -typedef enum { - CUVID_FMT_EXTFORMATINFO = 0x100 /**< Return extended format structure (CUVIDEOFORMATEX) */ -} CUvideosourceformat_flags; - -#if !defined(__APPLE__) -/**************************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidCreateVideoSource(CUvideosource *pObj, const char *pszFileName, CUVIDSOURCEPARAMS *pParams) -//! Create CUvideosource object. CUvideosource spawns demultiplexer thread that provides two callbacks: -//! pfnVideoDataHandler() and pfnAudioDataHandler() -//! NVDECODE API is intended for HW accelerated video decoding so CUvideosource doesn't have audio demuxer for all supported -//! containers. It's recommended to clients to use their own or third party demuxer if audio support is needed. -/**************************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidCreateVideoSource(CUvideosource *pObj, const char *pszFileName, CUVIDSOURCEPARAMS *pParams); - -/****************************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidCreateVideoSourceW(CUvideosource *pObj, const wchar_t *pwszFileName, CUVIDSOURCEPARAMS *pParams) -//! Create video source object and initialize -/****************************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidCreateVideoSourceW(CUvideosource *pObj, const wchar_t *pwszFileName, CUVIDSOURCEPARAMS *pParams); - -/*********************************************************************/ -//! \fn CUresult CUDAAPI cuvidDestroyVideoSource(CUvideosource obj) -//! Destroy video source -/*********************************************************************/ -typedef CUresult CUDAAPI tcuvidDestroyVideoSource(CUvideosource obj); - -/******************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidSetVideoSourceState(CUvideosource obj, cudaVideoState state) -//! Set video source state -/******************************************************************************************/ -typedef CUresult CUDAAPI tcuvidSetVideoSourceState(CUvideosource obj, cudaVideoState state); - -/******************************************************************************************/ -//! \fn cudaVideoState CUDAAPI cuvidGetVideoSourceState(CUvideosource obj) -//! Get video source state -/******************************************************************************************/ -typedef cudaVideoState CUDAAPI tcuvidGetVideoSourceState(CUvideosource obj); - -/****************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidGetSourceVideoFormat(CUvideosource obj, CUVIDEOFORMAT *pvidfmt, unsigned int flags) -//! Gets details of video stream in pvidfmt -/****************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidGetSourceVideoFormat(CUvideosource obj, CUVIDEOFORMAT *pvidfmt, unsigned int flags); - -/****************************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidGetSourceAudioFormat(CUvideosource obj, CUAUDIOFORMAT *paudfmt, unsigned int flags) -//! Get audio source format -//! NVDECODE API is intended for HW accelarated video decoding so CUvideosource doesn't have audio demuxer for all suppported -//! containers. It's recommended to clients to use their own or third party demuxer if audio support is needed. -/****************************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidGetSourceAudioFormat(CUvideosource obj, CUAUDIOFORMAT *paudfmt, unsigned int flags); - -#endif -/**********************************************************************************/ -//! \ingroup STRUCTS -//! \struct CUVIDPARSERDISPINFO -//! Used in cuvidParseVideoData API with PFNVIDDISPLAYCALLBACK pfnDisplayPicture -/**********************************************************************************/ -typedef struct _CUVIDPARSERDISPINFO -{ - int picture_index; /**< OUT: Index of the current picture */ - int progressive_frame; /**< OUT: 1 if progressive frame; 0 otherwise */ - int top_field_first; /**< OUT: 1 if top field is displayed first; 0 otherwise */ - int repeat_first_field; /**< OUT: Number of additional fields (1=ivtc, 2=frame doubling, 4=frame tripling, - -1=unpaired field) */ - CUvideotimestamp timestamp; /**< OUT: Presentation time stamp */ -} CUVIDPARSERDISPINFO; - -/***********************************************************************************************************************/ -//! Parser callbacks -//! The parser will call these synchronously from within cuvidParseVideoData(), whenever a picture is ready to -//! be decoded and/or displayed. First argument in functions is "void *pUserData" member of structure CUVIDSOURCEPARAMS -/***********************************************************************************************************************/ -typedef int (CUDAAPI *PFNVIDSEQUENCECALLBACK)(void *, CUVIDEOFORMAT *); -typedef int (CUDAAPI *PFNVIDDECODECALLBACK)(void *, CUVIDPICPARAMS *); -typedef int (CUDAAPI *PFNVIDDISPLAYCALLBACK)(void *, CUVIDPARSERDISPINFO *); - -/**************************************/ -//! \ingroup STRUCTS -//! \struct CUVIDPARSERPARAMS -//! Used in cuvidCreateVideoParser API -/**************************************/ -typedef struct _CUVIDPARSERPARAMS -{ - cudaVideoCodec CodecType; /**< IN: cudaVideoCodec_XXX */ - unsigned int ulMaxNumDecodeSurfaces; /**< IN: Max # of decode surfaces (parser will cycle through these) */ - unsigned int ulClockRate; /**< IN: Timestamp units in Hz (0=default=10000000Hz) */ - unsigned int ulErrorThreshold; /**< IN: % Error threshold (0-100) for calling pfnDecodePicture (100=always - IN: call pfnDecodePicture even if picture bitstream is fully corrupted) */ - unsigned int ulMaxDisplayDelay; /**< IN: Max display queue delay (improves pipelining of decode with display) - 0=no delay (recommended values: 2..4) */ - unsigned int uReserved1[5]; /**< IN: Reserved for future use - set to 0 */ - void *pUserData; /**< IN: User data for callbacks */ - PFNVIDSEQUENCECALLBACK pfnSequenceCallback; /**< IN: Called before decoding frames and/or whenever there is a fmt change */ - PFNVIDDECODECALLBACK pfnDecodePicture; /**< IN: Called when a picture is ready to be decoded (decode order) */ - PFNVIDDISPLAYCALLBACK pfnDisplayPicture; /**< IN: Called whenever a picture is ready to be displayed (display order) */ - void *pvReserved2[7]; /**< Reserved for future use - set to NULL */ - CUVIDEOFORMATEX *pExtVideoInfo; /**< IN: [Optional] sequence header data from system layer */ -} CUVIDPARSERPARAMS; - -/************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidCreateVideoParser(CUvideoparser *pObj, CUVIDPARSERPARAMS *pParams) -//! Create video parser object and initialize -/************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidCreateVideoParser(CUvideoparser *pObj, CUVIDPARSERPARAMS *pParams); - -/************************************************************************************************/ -//! \fn CUresult CUDAAPI cuvidParseVideoData(CUvideoparser obj, CUVIDSOURCEDATAPACKET *pPacket) -//! Parse the video data from source data packet in pPacket -//! Extracts parameter sets like SPS, PPS, bitstream etc. from pPacket and -//! calls back pfnDecodePicture with CUVIDPICPARAMS data for kicking of HW decoding -/************************************************************************************************/ -typedef CUresult CUDAAPI tcuvidParseVideoData(CUvideoparser obj, CUVIDSOURCEDATAPACKET *pPacket); - -/*******************************************************************/ -//! \fn CUresult CUDAAPI cuvidDestroyVideoParser(CUvideoparser obj) -/*******************************************************************/ -typedef CUresult CUDAAPI tcuvidDestroyVideoParser(CUvideoparser obj); - -/**********************************************************************************************/ - -#if defined(__cplusplus) -} -#endif /* __cplusplus */ - -#endif // __NVCUVID_H__ - - diff --git a/compat/nvenc/nvEncodeAPI.h b/compat/nvenc/nvEncodeAPI.h deleted file mode 100644 index e662880f4d94e..0000000000000 --- a/compat/nvenc/nvEncodeAPI.h +++ /dev/null @@ -1,3324 +0,0 @@ -/* - * This copyright notice applies to this header file only: - * - * Copyright (c) 2010-2017 NVIDIA Corporation - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the software, and to permit persons to whom the - * software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * \file nvEncodeAPI.h - * NVIDIA GPUs - beginning with the Kepler generation - contain a hardware-based encoder - * (referred to as NVENC) which provides fully-accelerated hardware-based video encoding. - * NvEncodeAPI provides the interface for NVIDIA video encoder (NVENC). - * \date 2011-2017 - * This file contains the interface constants, structure definitions and function prototypes. - */ - -#ifndef _NV_ENCODEAPI_H_ -#define _NV_ENCODEAPI_H_ - -#include - -#ifdef _WIN32 -#include -#endif - -#ifdef _MSC_VER -#ifndef _STDINT -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; -typedef unsigned short uint16_t; -#endif -#else -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \addtogroup ENCODER_STRUCTURE NvEncodeAPI Data structures - * @{ - */ - -#if defined(_WIN32) || defined(__CYGWIN__) -#define NVENCAPI __stdcall -#else -#define NVENCAPI -#endif - -#ifdef _WIN32 -typedef RECT NVENC_RECT; -#else -// ========================================================================================= -#if !defined(GUID) && !defined(GUID_DEFINED) -/*! - * \struct GUID - * Abstracts the GUID structure for non-windows platforms. - */ -// ========================================================================================= -typedef struct -{ - uint32_t Data1; /**< [in]: Specifies the first 8 hexadecimal digits of the GUID. */ - uint16_t Data2; /**< [in]: Specifies the first group of 4 hexadecimal digits. */ - uint16_t Data3; /**< [in]: Specifies the second group of 4 hexadecimal digits. */ - uint8_t Data4[8]; /**< [in]: Array of 8 bytes. The first 2 bytes contain the third group of 4 hexadecimal digits. - The remaining 6 bytes contain the final 12 hexadecimal digits. */ -} GUID; -#endif // GUID - -/** - * \struct _NVENC_RECT - * Defines a Rectangle. Used in ::NV_ENC_PREPROCESS_FRAME. - */ -typedef struct _NVENC_RECT -{ - uint32_t left; /**< [in]: X coordinate of the upper left corner of rectangular area to be specified. */ - uint32_t top; /**< [in]: Y coordinate of the upper left corner of the rectangular area to be specified. */ - uint32_t right; /**< [in]: X coordinate of the bottom right corner of the rectangular area to be specified. */ - uint32_t bottom; /**< [in]: Y coordinate of the bottom right corner of the rectangular area to be specified. */ -} NVENC_RECT; - -#endif // _WIN32 - -/** @} */ /* End of GUID and NVENC_RECT structure grouping*/ - -typedef void* NV_ENC_INPUT_PTR; /**< NVENCODE API input buffer */ -typedef void* NV_ENC_OUTPUT_PTR; /**< NVENCODE API output buffer*/ -typedef void* NV_ENC_REGISTERED_PTR; /**< A Resource that has been registered with NVENCODE API*/ - -#define NVENCAPI_MAJOR_VERSION 8 -#define NVENCAPI_MINOR_VERSION 0 - -#define NVENCAPI_VERSION (NVENCAPI_MAJOR_VERSION | (NVENCAPI_MINOR_VERSION << 24)) - -/** - * Macro to generate per-structure version for use with API. - */ -#define NVENCAPI_STRUCT_VERSION(ver) ((uint32_t)NVENCAPI_VERSION | ((ver)<<16) | (0x7 << 28)) - - -#define NVENC_INFINITE_GOPLENGTH 0xffffffff - -#define NV_MAX_SEQ_HDR_LEN (512) - -// ========================================================================================= -// Encode Codec GUIDS supported by the NvEncodeAPI interface. -// ========================================================================================= - -// {6BC82762-4E63-4ca4-AA85-1E50F321F6BF} -static const GUID NV_ENC_CODEC_H264_GUID = -{ 0x6bc82762, 0x4e63, 0x4ca4, { 0xaa, 0x85, 0x1e, 0x50, 0xf3, 0x21, 0xf6, 0xbf } }; - -// {790CDC88-4522-4d7b-9425-BDA9975F7603} -static const GUID NV_ENC_CODEC_HEVC_GUID = -{ 0x790cdc88, 0x4522, 0x4d7b, { 0x94, 0x25, 0xbd, 0xa9, 0x97, 0x5f, 0x76, 0x3 } }; - - - -// ========================================================================================= -// * Encode Profile GUIDS supported by the NvEncodeAPI interface. -// ========================================================================================= - -// {BFD6F8E7-233C-4341-8B3E-4818523803F4} -static const GUID NV_ENC_CODEC_PROFILE_AUTOSELECT_GUID = -{ 0xbfd6f8e7, 0x233c, 0x4341, { 0x8b, 0x3e, 0x48, 0x18, 0x52, 0x38, 0x3, 0xf4 } }; - -// {0727BCAA-78C4-4c83-8C2F-EF3DFF267C6A} -static const GUID NV_ENC_H264_PROFILE_BASELINE_GUID = -{ 0x727bcaa, 0x78c4, 0x4c83, { 0x8c, 0x2f, 0xef, 0x3d, 0xff, 0x26, 0x7c, 0x6a } }; - -// {60B5C1D4-67FE-4790-94D5-C4726D7B6E6D} -static const GUID NV_ENC_H264_PROFILE_MAIN_GUID = -{ 0x60b5c1d4, 0x67fe, 0x4790, { 0x94, 0xd5, 0xc4, 0x72, 0x6d, 0x7b, 0x6e, 0x6d } }; - -// {E7CBC309-4F7A-4b89-AF2A-D537C92BE310} -static const GUID NV_ENC_H264_PROFILE_HIGH_GUID = -{ 0xe7cbc309, 0x4f7a, 0x4b89, { 0xaf, 0x2a, 0xd5, 0x37, 0xc9, 0x2b, 0xe3, 0x10 } }; - -// {7AC663CB-A598-4960-B844-339B261A7D52} -static const GUID NV_ENC_H264_PROFILE_HIGH_444_GUID = -{ 0x7ac663cb, 0xa598, 0x4960, { 0xb8, 0x44, 0x33, 0x9b, 0x26, 0x1a, 0x7d, 0x52 } }; - -// {40847BF5-33F7-4601-9084-E8FE3C1DB8B7} -static const GUID NV_ENC_H264_PROFILE_STEREO_GUID = -{ 0x40847bf5, 0x33f7, 0x4601, { 0x90, 0x84, 0xe8, 0xfe, 0x3c, 0x1d, 0xb8, 0xb7 } }; - -// {CE788D20-AAA9-4318-92BB-AC7E858C8D36} -static const GUID NV_ENC_H264_PROFILE_SVC_TEMPORAL_SCALABILTY = -{ 0xce788d20, 0xaaa9, 0x4318, { 0x92, 0xbb, 0xac, 0x7e, 0x85, 0x8c, 0x8d, 0x36 } }; - -// {B405AFAC-F32B-417B-89C4-9ABEED3E5978} -static const GUID NV_ENC_H264_PROFILE_PROGRESSIVE_HIGH_GUID = -{ 0xb405afac, 0xf32b, 0x417b, { 0x89, 0xc4, 0x9a, 0xbe, 0xed, 0x3e, 0x59, 0x78 } }; - -// {AEC1BD87-E85B-48f2-84C3-98BCA6285072} -static const GUID NV_ENC_H264_PROFILE_CONSTRAINED_HIGH_GUID = -{ 0xaec1bd87, 0xe85b, 0x48f2, { 0x84, 0xc3, 0x98, 0xbc, 0xa6, 0x28, 0x50, 0x72 } }; - -// {B514C39A-B55B-40fa-878F-F1253B4DFDEC} -static const GUID NV_ENC_HEVC_PROFILE_MAIN_GUID = -{ 0xb514c39a, 0xb55b, 0x40fa, { 0x87, 0x8f, 0xf1, 0x25, 0x3b, 0x4d, 0xfd, 0xec } }; - -// {fa4d2b6c-3a5b-411a-8018-0a3f5e3c9be5} -static const GUID NV_ENC_HEVC_PROFILE_MAIN10_GUID = -{ 0xfa4d2b6c, 0x3a5b, 0x411a, { 0x80, 0x18, 0x0a, 0x3f, 0x5e, 0x3c, 0x9b, 0xe5 } }; - -// For HEVC Main 444 8 bit and HEVC Main 444 10 bit profiles only -// {51ec32b5-1b4c-453c-9cbd-b616bd621341} -static const GUID NV_ENC_HEVC_PROFILE_FREXT_GUID = -{ 0x51ec32b5, 0x1b4c, 0x453c, { 0x9c, 0xbd, 0xb6, 0x16, 0xbd, 0x62, 0x13, 0x41 } }; - -// ========================================================================================= -// * Preset GUIDS supported by the NvEncodeAPI interface. -// ========================================================================================= -// {B2DFB705-4EBD-4C49-9B5F-24A777D3E587} -static const GUID NV_ENC_PRESET_DEFAULT_GUID = -{ 0xb2dfb705, 0x4ebd, 0x4c49, { 0x9b, 0x5f, 0x24, 0xa7, 0x77, 0xd3, 0xe5, 0x87 } }; - -// {60E4C59F-E846-4484-A56D-CD45BE9FDDF6} -static const GUID NV_ENC_PRESET_HP_GUID = -{ 0x60e4c59f, 0xe846, 0x4484, { 0xa5, 0x6d, 0xcd, 0x45, 0xbe, 0x9f, 0xdd, 0xf6 } }; - -// {34DBA71D-A77B-4B8F-9C3E-B6D5DA24C012} -static const GUID NV_ENC_PRESET_HQ_GUID = -{ 0x34dba71d, 0xa77b, 0x4b8f, { 0x9c, 0x3e, 0xb6, 0xd5, 0xda, 0x24, 0xc0, 0x12 } }; - -// {82E3E450-BDBB-4e40-989C-82A90DF9EF32} -static const GUID NV_ENC_PRESET_BD_GUID = -{ 0x82e3e450, 0xbdbb, 0x4e40, { 0x98, 0x9c, 0x82, 0xa9, 0xd, 0xf9, 0xef, 0x32 } }; - -// {49DF21C5-6DFA-4feb-9787-6ACC9EFFB726} -static const GUID NV_ENC_PRESET_LOW_LATENCY_DEFAULT_GUID = -{ 0x49df21c5, 0x6dfa, 0x4feb, { 0x97, 0x87, 0x6a, 0xcc, 0x9e, 0xff, 0xb7, 0x26 } }; - -// {C5F733B9-EA97-4cf9-BEC2-BF78A74FD105} -static const GUID NV_ENC_PRESET_LOW_LATENCY_HQ_GUID = -{ 0xc5f733b9, 0xea97, 0x4cf9, { 0xbe, 0xc2, 0xbf, 0x78, 0xa7, 0x4f, 0xd1, 0x5 } }; - -// {67082A44-4BAD-48FA-98EA-93056D150A58} -static const GUID NV_ENC_PRESET_LOW_LATENCY_HP_GUID = -{ 0x67082a44, 0x4bad, 0x48fa, { 0x98, 0xea, 0x93, 0x5, 0x6d, 0x15, 0xa, 0x58 } }; - -// {D5BFB716-C604-44e7-9BB8-DEA5510FC3AC} -static const GUID NV_ENC_PRESET_LOSSLESS_DEFAULT_GUID = -{ 0xd5bfb716, 0xc604, 0x44e7, { 0x9b, 0xb8, 0xde, 0xa5, 0x51, 0xf, 0xc3, 0xac } }; - -// {149998E7-2364-411d-82EF-179888093409} -static const GUID NV_ENC_PRESET_LOSSLESS_HP_GUID = -{ 0x149998e7, 0x2364, 0x411d, { 0x82, 0xef, 0x17, 0x98, 0x88, 0x9, 0x34, 0x9 } }; - -/** - * \addtogroup ENCODER_STRUCTURE NvEncodeAPI Data structures - * @{ - */ - -/** - * Input frame encode modes - */ -typedef enum _NV_ENC_PARAMS_FRAME_FIELD_MODE -{ - NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME = 0x01, /**< Frame mode */ - NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD = 0x02, /**< Field mode */ - NV_ENC_PARAMS_FRAME_FIELD_MODE_MBAFF = 0x03 /**< MB adaptive frame/field */ -} NV_ENC_PARAMS_FRAME_FIELD_MODE; - -/** - * Rate Control Modes - */ -typedef enum _NV_ENC_PARAMS_RC_MODE -{ - NV_ENC_PARAMS_RC_CONSTQP = 0x0, /**< Constant QP mode */ - NV_ENC_PARAMS_RC_VBR = 0x1, /**< Variable bitrate mode */ - NV_ENC_PARAMS_RC_CBR = 0x2, /**< Constant bitrate mode */ - NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ = 0x8, /**< low-delay CBR, high quality */ - NV_ENC_PARAMS_RC_CBR_HQ = 0x10, /**< CBR, high quality (slower) */ - NV_ENC_PARAMS_RC_VBR_HQ = 0x20 /**< VBR, high quality (slower) */ -} NV_ENC_PARAMS_RC_MODE; - -#define NV_ENC_PARAMS_RC_VBR_MINQP (NV_ENC_PARAMS_RC_MODE)0x4 /**< Deprecated */ -#define NV_ENC_PARAMS_RC_2_PASS_QUALITY NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ /**< Deprecated */ -#define NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP NV_ENC_PARAMS_RC_CBR_HQ /**< Deprecated */ -#define NV_ENC_PARAMS_RC_2_PASS_VBR NV_ENC_PARAMS_RC_VBR_HQ /**< Deprecated */ -#define NV_ENC_PARAMS_RC_CBR2 NV_ENC_PARAMS_RC_CBR /**< Deprecated */ - -/** - * Input picture structure - */ -typedef enum _NV_ENC_PIC_STRUCT -{ - NV_ENC_PIC_STRUCT_FRAME = 0x01, /**< Progressive frame */ - NV_ENC_PIC_STRUCT_FIELD_TOP_BOTTOM = 0x02, /**< Field encoding top field first */ - NV_ENC_PIC_STRUCT_FIELD_BOTTOM_TOP = 0x03 /**< Field encoding bottom field first */ -} NV_ENC_PIC_STRUCT; - -/** - * Input picture type - */ -typedef enum _NV_ENC_PIC_TYPE -{ - NV_ENC_PIC_TYPE_P = 0x0, /**< Forward predicted */ - NV_ENC_PIC_TYPE_B = 0x01, /**< Bi-directionally predicted picture */ - NV_ENC_PIC_TYPE_I = 0x02, /**< Intra predicted picture */ - NV_ENC_PIC_TYPE_IDR = 0x03, /**< IDR picture */ - NV_ENC_PIC_TYPE_BI = 0x04, /**< Bi-directionally predicted with only Intra MBs */ - NV_ENC_PIC_TYPE_SKIPPED = 0x05, /**< Picture is skipped */ - NV_ENC_PIC_TYPE_INTRA_REFRESH = 0x06, /**< First picture in intra refresh cycle */ - NV_ENC_PIC_TYPE_UNKNOWN = 0xFF /**< Picture type unknown */ -} NV_ENC_PIC_TYPE; - -/** - * Motion vector precisions - */ -typedef enum _NV_ENC_MV_PRECISION -{ - NV_ENC_MV_PRECISION_DEFAULT = 0x0, /** (if lookahead is enabled, input frames must remain available to the encoder until encode completion) */ - uint32_t disableIadapt :1; /**< [in]: Set this to 1 to disable adaptive I-frame insertion at scene cuts (only has an effect when lookahead is enabled) */ - uint32_t disableBadapt :1; /**< [in]: Set this to 1 to disable adaptive B-frame decision (only has an effect when lookahead is enabled) */ - uint32_t enableTemporalAQ :1; /**< [in]: Set this to 1 to enable temporal AQ for H.264 */ - uint32_t zeroReorderDelay :1; /**< [in]: Set this to 1 to indicate zero latency operation (no reordering delay, num_reorder_frames=0) */ - uint32_t enableNonRefP :1; /**< [in]: Set this to 1 to enable automatic insertion of non-reference P-frames (no effect if enablePTD=0) */ - uint32_t strictGOPTarget :1; /**< [in]: Set this to 1 to minimize GOP-to-GOP rate fluctuations */ - uint32_t aqStrength :4; /**< [in]: When AQ (Spatial) is enabled (i.e. NV_ENC_RC_PARAMS::enableAQ is set), this field is used to specify AQ strength. AQ strength scale is from 1 (low) - 15 (aggressive). If not set, strength is autoselected by driver. */ - uint32_t reservedBitFields :16; /**< [in]: Reserved bitfields and must be set to 0 */ - NV_ENC_QP minQP; /**< [in]: Specifies the minimum QP used for rate control. Client must set NV_ENC_CONFIG::enableMinQP to 1. */ - NV_ENC_QP maxQP; /**< [in]: Specifies the maximum QP used for rate control. Client must set NV_ENC_CONFIG::enableMaxQP to 1. */ - NV_ENC_QP initialRCQP; /**< [in]: Specifies the initial QP used for rate control. Client must set NV_ENC_CONFIG::enableInitialRCQP to 1. */ - uint32_t temporallayerIdxMask; /**< [in]: Specifies the temporal layers (as a bitmask) whose QPs have changed. Valid max bitmask is [2^NV_ENC_CAPS_NUM_MAX_TEMPORAL_LAYERS - 1] */ - uint8_t temporalLayerQP[8]; /**< [in]: Specifies the temporal layer QPs used for rate control. Temporal layer index is used as as the array index */ - uint8_t targetQuality; /**< [in]: Target CQ (Constant Quality) level for VBR mode (range 0-51 with 0-automatic) */ - uint8_t targetQualityLSB; /**< [in]: Fractional part of target quality (as 8.8 fixed point format) */ - uint16_t lookaheadDepth; /**< [in]: Maximum depth of lookahead with range 0-32 (only used if enableLookahead=1) */ - uint32_t reserved[9]; - } NV_ENC_RC_PARAMS; - -/** macro for constructing the version field of ::_NV_ENC_RC_PARAMS */ -#define NV_ENC_RC_PARAMS_VER NVENCAPI_STRUCT_VERSION(1) - - - -/** - * \struct _NV_ENC_CONFIG_H264_VUI_PARAMETERS - * H264 Video Usability Info parameters - */ -typedef struct _NV_ENC_CONFIG_H264_VUI_PARAMETERS -{ - uint32_t overscanInfoPresentFlag; /**< [in]: if set to 1 , it specifies that the overscanInfo is present */ - uint32_t overscanInfo; /**< [in]: Specifies the overscan info(as defined in Annex E of the ITU-T Specification). */ - uint32_t videoSignalTypePresentFlag; /**< [in]: If set to 1, it specifies that the videoFormat, videoFullRangeFlag and colourDescriptionPresentFlag are present. */ - uint32_t videoFormat; /**< [in]: Specifies the source video format(as defined in Annex E of the ITU-T Specification).*/ - uint32_t videoFullRangeFlag; /**< [in]: Specifies the output range of the luma and chroma samples(as defined in Annex E of the ITU-T Specification). */ - uint32_t colourDescriptionPresentFlag; /**< [in]: If set to 1, it specifies that the colourPrimaries, transferCharacteristics and colourMatrix are present. */ - uint32_t colourPrimaries; /**< [in]: Specifies color primaries for converting to RGB(as defined in Annex E of the ITU-T Specification) */ - uint32_t transferCharacteristics; /**< [in]: Specifies the opto-electronic transfer characteristics to use (as defined in Annex E of the ITU-T Specification) */ - uint32_t colourMatrix; /**< [in]: Specifies the matrix coefficients used in deriving the luma and chroma from the RGB primaries (as defined in Annex E of the ITU-T Specification). */ - uint32_t chromaSampleLocationFlag; /**< [in]: if set to 1 , it specifies that the chromaSampleLocationTop and chromaSampleLocationBot are present.*/ - uint32_t chromaSampleLocationTop; /**< [in]: Specifies the chroma sample location for top field(as defined in Annex E of the ITU-T Specification) */ - uint32_t chromaSampleLocationBot; /**< [in]: Specifies the chroma sample location for bottom field(as defined in Annex E of the ITU-T Specification) */ - uint32_t bitstreamRestrictionFlag; /**< [in]: if set to 1, it specifies the bitstream restriction parameters are present in the bitstream.*/ - uint32_t reserved[15]; -}NV_ENC_CONFIG_H264_VUI_PARAMETERS; - -typedef NV_ENC_CONFIG_H264_VUI_PARAMETERS NV_ENC_CONFIG_HEVC_VUI_PARAMETERS; - -/** - * \struct _NVENC_EXTERNAL_ME_HINT_COUNTS_PER_BLOCKTYPE - * External motion vector hint counts per block type. - * H264 supports multiple hint while HEVC supports one hint for each valid candidate. - */ -typedef struct _NVENC_EXTERNAL_ME_HINT_COUNTS_PER_BLOCKTYPE -{ - uint32_t numCandsPerBlk16x16 : 4; /**< [in]: Supported for H264,HEVC.It Specifies the number of candidates per 16x16 block. */ - uint32_t numCandsPerBlk16x8 : 4; /**< [in]: Supported for H264 only.Specifies the number of candidates per 16x8 block. */ - uint32_t numCandsPerBlk8x16 : 4; /**< [in]: Supported for H264 only.Specifies the number of candidates per 8x16 block. */ - uint32_t numCandsPerBlk8x8 : 4; /**< [in]: Supported for H264,HEVC.Specifies the number of candidates per 8x8 block. */ - uint32_t reserved : 16; /**< [in]: Reserved for padding. */ - uint32_t reserved1[3]; /**< [in]: Reserved for future use. */ -} NVENC_EXTERNAL_ME_HINT_COUNTS_PER_BLOCKTYPE; - - -/** - * \struct _NVENC_EXTERNAL_ME_HINT - * External Motion Vector hint structure. - */ -typedef struct _NVENC_EXTERNAL_ME_HINT -{ - int32_t mvx : 12; /**< [in]: Specifies the x component of integer pixel MV (relative to current MB) S12.0. */ - int32_t mvy : 10; /**< [in]: Specifies the y component of integer pixel MV (relative to current MB) S10.0 .*/ - int32_t refidx : 5; /**< [in]: Specifies the reference index (31=invalid). Current we support only 1 reference frame per direction for external hints, so \p refidx must be 0. */ - int32_t dir : 1; /**< [in]: Specifies the direction of motion estimation . 0=L0 1=L1.*/ - int32_t partType : 2; /**< [in]: Specifies the block partition type.0=16x16 1=16x8 2=8x16 3=8x8 (blocks in partition must be consecutive).*/ - int32_t lastofPart : 1; /**< [in]: Set to 1 for the last MV of (sub) partition */ - int32_t lastOfMB : 1; /**< [in]: Set to 1 for the last MV of macroblock. */ -} NVENC_EXTERNAL_ME_HINT; - - -/** - * \struct _NV_ENC_CONFIG_H264 - * H264 encoder configuration parameters - */ -typedef struct _NV_ENC_CONFIG_H264 -{ - uint32_t enableTemporalSVC :1; /**< [in]: Set to 1 to enable SVC temporal*/ - uint32_t enableStereoMVC :1; /**< [in]: Set to 1 to enable stereo MVC*/ - uint32_t hierarchicalPFrames :1; /**< [in]: Set to 1 to enable hierarchical PFrames */ - uint32_t hierarchicalBFrames :1; /**< [in]: Set to 1 to enable hierarchical BFrames */ - uint32_t outputBufferingPeriodSEI :1; /**< [in]: Set to 1 to write SEI buffering period syntax in the bitstream */ - uint32_t outputPictureTimingSEI :1; /**< [in]: Set to 1 to write SEI picture timing syntax in the bitstream. When set for following rateControlMode : NV_ENC_PARAMS_RC_CBR, NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ, - NV_ENC_PARAMS_RC_CBR_HQ, filler data is inserted if needed to achieve hrd bitrate */ - uint32_t outputAUD :1; /**< [in]: Set to 1 to write access unit delimiter syntax in bitstream */ - uint32_t disableSPSPPS :1; /**< [in]: Set to 1 to disable writing of Sequence and Picture parameter info in bitstream */ - uint32_t outputFramePackingSEI :1; /**< [in]: Set to 1 to enable writing of frame packing arrangement SEI messages to bitstream */ - uint32_t outputRecoveryPointSEI :1; /**< [in]: Set to 1 to enable writing of recovery point SEI message */ - uint32_t enableIntraRefresh :1; /**< [in]: Set to 1 to enable gradual decoder refresh or intra refresh. If the GOP structure uses B frames this will be ignored */ - uint32_t enableConstrainedEncoding :1; /**< [in]: Set this to 1 to enable constrainedFrame encoding where each slice in the constarined picture is independent of other slices - Check support for constrained encoding using ::NV_ENC_CAPS_SUPPORT_CONSTRAINED_ENCODING caps. */ - uint32_t repeatSPSPPS :1; /**< [in]: Set to 1 to enable writing of Sequence and Picture parameter for every IDR frame */ - uint32_t enableVFR :1; /**< [in]: Set to 1 to enable variable frame rate. */ - uint32_t enableLTR :1; /**< [in]: Set to 1 to enable LTR (Long Term Reference) frame support. LTR can be used in two modes: "LTR Trust" mode and "LTR Per Picture" mode. - LTR Trust mode: In this mode, ltrNumFrames pictures after IDR are automatically marked as LTR. This mode is enabled by setting ltrTrustMode = 1. - Use of LTR Trust mode is strongly discouraged as this mode may be deprecated in future. - LTR Per Picture mode: In this mode, client can control whether the current picture should be marked as LTR. Enable this mode by setting - ltrTrustMode = 0 and ltrMarkFrame = 1 for the picture to be marked as LTR. This is the preferred mode - for using LTR. - Note that LTRs are not supported if encoding session is configured with B-frames */ - uint32_t qpPrimeYZeroTransformBypassFlag :1; /**< [in]: To enable lossless encode set this to 1, set QP to 0 and RC_mode to NV_ENC_PARAMS_RC_CONSTQP and profile to HIGH_444_PREDICTIVE_PROFILE. - Check support for lossless encoding using ::NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE caps. */ - uint32_t useConstrainedIntraPred :1; /**< [in]: Set 1 to enable constrained intra prediction. */ - uint32_t reservedBitFields :15; /**< [in]: Reserved bitfields and must be set to 0 */ - uint32_t level; /**< [in]: Specifies the encoding level. Client is recommended to set this to NV_ENC_LEVEL_AUTOSELECT in order to enable the NvEncodeAPI interface to select the correct level. */ - uint32_t idrPeriod; /**< [in]: Specifies the IDR interval. If not set, this is made equal to gopLength in NV_ENC_CONFIG.Low latency application client can set IDR interval to NVENC_INFINITE_GOPLENGTH so that IDR frames are not inserted automatically. */ - uint32_t separateColourPlaneFlag; /**< [in]: Set to 1 to enable 4:4:4 separate colour planes */ - uint32_t disableDeblockingFilterIDC; /**< [in]: Specifies the deblocking filter mode. Permissible value range: [0,2] */ - uint32_t numTemporalLayers; /**< [in]: Specifies max temporal layers to be used for hierarchical coding. Valid value range is [1,::NV_ENC_CAPS_NUM_MAX_TEMPORAL_LAYERS] */ - uint32_t spsId; /**< [in]: Specifies the SPS id of the sequence header */ - uint32_t ppsId; /**< [in]: Specifies the PPS id of the picture header */ - NV_ENC_H264_ADAPTIVE_TRANSFORM_MODE adaptiveTransformMode; /**< [in]: Specifies the AdaptiveTransform Mode. Check support for AdaptiveTransform mode using ::NV_ENC_CAPS_SUPPORT_ADAPTIVE_TRANSFORM caps. */ - NV_ENC_H264_FMO_MODE fmoMode; /**< [in]: Specified the FMO Mode. Check support for FMO using ::NV_ENC_CAPS_SUPPORT_FMO caps. */ - NV_ENC_H264_BDIRECT_MODE bdirectMode; /**< [in]: Specifies the BDirect mode. Check support for BDirect mode using ::NV_ENC_CAPS_SUPPORT_BDIRECT_MODE caps.*/ - NV_ENC_H264_ENTROPY_CODING_MODE entropyCodingMode; /**< [in]: Specifies the entropy coding mode. Check support for CABAC mode using ::NV_ENC_CAPS_SUPPORT_CABAC caps. */ - NV_ENC_STEREO_PACKING_MODE stereoMode; /**< [in]: Specifies the stereo frame packing mode which is to be signalled in frame packing arrangement SEI */ - uint32_t intraRefreshPeriod; /**< [in]: Specifies the interval between successive intra refresh if enableIntrarefresh is set. Requires enableIntraRefresh to be set. - Will be disabled if NV_ENC_CONFIG::gopLength is not set to NVENC_INFINITE_GOPLENGTH. */ - uint32_t intraRefreshCnt; /**< [in]: Specifies the length of intra refresh in number of frames for periodic intra refresh. This value should be smaller than intraRefreshPeriod */ - uint32_t maxNumRefFrames; /**< [in]: Specifies the DPB size used for encoding. Setting it to 0 will let driver use the default dpb size. - The low latency application which wants to invalidate reference frame as an error resilience tool - is recommended to use a large DPB size so that the encoder can keep old reference frames which can be used if recent - frames are invalidated. */ - uint32_t sliceMode; /**< [in]: This parameter in conjunction with sliceModeData specifies the way in which the picture is divided into slices - sliceMode = 0 MB based slices, sliceMode = 1 Byte based slices, sliceMode = 2 MB row based slices, sliceMode = 3, numSlices in Picture - When forceIntraRefreshWithFrameCnt is set it will have priority over sliceMode setting - When sliceMode == 0 and sliceModeData == 0 whole picture will be coded with one slice */ - uint32_t sliceModeData; /**< [in]: Specifies the parameter needed for sliceMode. For: - sliceMode = 0, sliceModeData specifies # of MBs in each slice (except last slice) - sliceMode = 1, sliceModeData specifies maximum # of bytes in each slice (except last slice) - sliceMode = 2, sliceModeData specifies # of MB rows in each slice (except last slice) - sliceMode = 3, sliceModeData specifies number of slices in the picture. Driver will divide picture into slices optimally */ - NV_ENC_CONFIG_H264_VUI_PARAMETERS h264VUIParameters; /**< [in]: Specifies the H264 video usability info pamameters */ - uint32_t ltrNumFrames; /**< [in]: Specifies the number of LTR frames. This parameter has different meaning in two LTR modes. - In "LTR Trust" mode (ltrTrustMode = 1), encoder will mark the first ltrNumFrames base layer reference frames within each IDR interval as LTR. - In "LTR Per Picture" mode (ltrTrustMode = 0 and ltrMarkFrame = 1), ltrNumFrames specifies maximum number of LTR frames in DPB. */ - uint32_t ltrTrustMode; /**< [in]: Specifies the LTR operating mode. See comments near NV_ENC_CONFIG_H264::enableLTR for description of the two modes. - Set to 1 to use "LTR Trust" mode of LTR operation. Clients are discouraged to use "LTR Trust" mode as this mode may - be deprecated in future releases. - Set to 0 when using "LTR Per Picture" mode of LTR operation. */ - uint32_t chromaFormatIDC; /**< [in]: Specifies the chroma format. Should be set to 1 for yuv420 input, 3 for yuv444 input. - Check support for YUV444 encoding using ::NV_ENC_CAPS_SUPPORT_YUV444_ENCODE caps.*/ - uint32_t maxTemporalLayers; /**< [in]: Specifies the max temporal layer used for hierarchical coding. */ - uint32_t reserved1[270]; /**< [in]: Reserved and must be set to 0 */ - void* reserved2[64]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_CONFIG_H264; - - -/** - * \struct _NV_ENC_CONFIG_HEVC - * HEVC encoder configuration parameters to be set during initialization. - */ -typedef struct _NV_ENC_CONFIG_HEVC -{ - uint32_t level; /**< [in]: Specifies the level of the encoded bitstream.*/ - uint32_t tier; /**< [in]: Specifies the level tier of the encoded bitstream.*/ - NV_ENC_HEVC_CUSIZE minCUSize; /**< [in]: Specifies the minimum size of luma coding unit.*/ - NV_ENC_HEVC_CUSIZE maxCUSize; /**< [in]: Specifies the maximum size of luma coding unit. Currently NVENC SDK only supports maxCUSize equal to NV_ENC_HEVC_CUSIZE_32x32.*/ - uint32_t useConstrainedIntraPred :1; /**< [in]: Set 1 to enable constrained intra prediction. */ - uint32_t disableDeblockAcrossSliceBoundary :1; /**< [in]: Set 1 to disable in loop filtering across slice boundary.*/ - uint32_t outputBufferingPeriodSEI :1; /**< [in]: Set 1 to write SEI buffering period syntax in the bitstream */ - uint32_t outputPictureTimingSEI :1; /**< [in]: Set 1 to write SEI picture timing syntax in the bitstream */ - uint32_t outputAUD :1; /**< [in]: Set 1 to write Access Unit Delimiter syntax. */ - uint32_t enableLTR :1; /**< [in]: Set to 1 to enable LTR (Long Term Reference) frame support. LTR can be used in two modes: "LTR Trust" mode and "LTR Per Picture" mode. - LTR Trust mode: In this mode, ltrNumFrames pictures after IDR are automatically marked as LTR. This mode is enabled by setting ltrTrustMode = 1. - Use of LTR Trust mode is strongly discouraged as this mode may be deprecated in future releases. - LTR Per Picture mode: In this mode, client can control whether the current picture should be marked as LTR. Enable this mode by setting - ltrTrustMode = 0 and ltrMarkFrame = 1 for the picture to be marked as LTR. This is the preferred mode - for using LTR. - Note that LTRs are not supported if encoding session is configured with B-frames */ - uint32_t disableSPSPPS :1; /**< [in]: Set 1 to disable VPS,SPS and PPS signalling in the bitstream. */ - uint32_t repeatSPSPPS :1; /**< [in]: Set 1 to output VPS,SPS and PPS for every IDR frame.*/ - uint32_t enableIntraRefresh :1; /**< [in]: Set 1 to enable gradual decoder refresh or intra refresh. If the GOP structure uses B frames this will be ignored */ - uint32_t chromaFormatIDC :2; /**< [in]: Specifies the chroma format. Should be set to 1 for yuv420 input, 3 for yuv444 input.*/ - uint32_t pixelBitDepthMinus8 :3; /**< [in]: Specifies pixel bit depth minus 8. Should be set to 0 for 8 bit input, 2 for 10 bit input.*/ - uint32_t reserved :18; /**< [in]: Reserved bitfields.*/ - uint32_t idrPeriod; /**< [in]: Specifies the IDR interval. If not set, this is made equal to gopLength in NV_ENC_CONFIG.Low latency application client can set IDR interval to NVENC_INFINITE_GOPLENGTH so that IDR frames are not inserted automatically. */ - uint32_t intraRefreshPeriod; /**< [in]: Specifies the interval between successive intra refresh if enableIntrarefresh is set. Requires enableIntraRefresh to be set. - Will be disabled if NV_ENC_CONFIG::gopLength is not set to NVENC_INFINITE_GOPLENGTH. */ - uint32_t intraRefreshCnt; /**< [in]: Specifies the length of intra refresh in number of frames for periodic intra refresh. This value should be smaller than intraRefreshPeriod */ - uint32_t maxNumRefFramesInDPB; /**< [in]: Specifies the maximum number of references frames in the DPB.*/ - uint32_t ltrNumFrames; /**< [in]: This parameter has different meaning in two LTR modes. - In "LTR Trust" mode (ltrTrustMode = 1), encoder will mark the first ltrNumFrames base layer reference frames within each IDR interval as LTR. - In "LTR Per Picture" mode (ltrTrustMode = 0 and ltrMarkFrame = 1), ltrNumFrames specifies maximum number of LTR frames in DPB. */ - uint32_t vpsId; /**< [in]: Specifies the VPS id of the video parameter set */ - uint32_t spsId; /**< [in]: Specifies the SPS id of the sequence header */ - uint32_t ppsId; /**< [in]: Specifies the PPS id of the picture header */ - uint32_t sliceMode; /**< [in]: This parameter in conjunction with sliceModeData specifies the way in which the picture is divided into slices - sliceMode = 0 CTU based slices, sliceMode = 1 Byte based slices, sliceMode = 2 CTU row based slices, sliceMode = 3, numSlices in Picture - When sliceMode == 0 and sliceModeData == 0 whole picture will be coded with one slice */ - uint32_t sliceModeData; /**< [in]: Specifies the parameter needed for sliceMode. For: - sliceMode = 0, sliceModeData specifies # of CTUs in each slice (except last slice) - sliceMode = 1, sliceModeData specifies maximum # of bytes in each slice (except last slice) - sliceMode = 2, sliceModeData specifies # of CTU rows in each slice (except last slice) - sliceMode = 3, sliceModeData specifies number of slices in the picture. Driver will divide picture into slices optimally */ - uint32_t maxTemporalLayersMinus1; /**< [in]: Specifies the max temporal layer used for hierarchical coding. */ - NV_ENC_CONFIG_HEVC_VUI_PARAMETERS hevcVUIParameters; /**< [in]: Specifies the HEVC video usability info pamameters */ - uint32_t ltrTrustMode; /**< [in]: Specifies the LTR operating mode. See comments near NV_ENC_CONFIG_HEVC::enableLTR for description of the two modes. - Set to 1 to use "LTR Trust" mode of LTR operation. Clients are discouraged to use "LTR Trust" mode as this mode may - be deprecated in future releases. - Set to 0 when using "LTR Per Picture" mode of LTR operation. */ - uint32_t reserved1[217]; /**< [in]: Reserved and must be set to 0.*/ - void* reserved2[64]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_CONFIG_HEVC; - -/** - * \struct _NV_ENC_CONFIG_H264_MEONLY - * H264 encoder configuration parameters for ME only Mode - * - */ -typedef struct _NV_ENC_CONFIG_H264_MEONLY -{ - uint32_t disablePartition16x16 :1; /**< [in]: Disable MotionEstimation on 16x16 blocks*/ - uint32_t disablePartition8x16 :1; /**< [in]: Disable MotionEstimation on 8x16 blocks*/ - uint32_t disablePartition16x8 :1; /**< [in]: Disable MotionEstimation on 16x8 blocks*/ - uint32_t disablePartition8x8 :1; /**< [in]: Disable MotionEstimation on 8x8 blocks*/ - uint32_t disableIntraSearch :1; /**< [in]: Disable Intra search during MotionEstimation*/ - uint32_t bStereoEnable :1; /**< [in]: Enable Stereo Mode for Motion Estimation where each view is independently executed*/ - uint32_t reserved :26; /**< [in]: Reserved and must be set to 0 */ - uint32_t reserved1 [255]; /**< [in]: Reserved and must be set to 0 */ - void* reserved2[64]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_CONFIG_H264_MEONLY; - - -/** - * \struct _NV_ENC_CONFIG_HEVC_MEONLY - * HEVC encoder configuration parameters for ME only Mode - * - */ -typedef struct _NV_ENC_CONFIG_HEVC_MEONLY -{ - uint32_t reserved [256]; /**< [in]: Reserved and must be set to 0 */ - void* reserved1[64]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_CONFIG_HEVC_MEONLY; - -/** - * \struct _NV_ENC_CODEC_CONFIG - * Codec-specific encoder configuration parameters to be set during initialization. - */ -typedef union _NV_ENC_CODEC_CONFIG -{ - NV_ENC_CONFIG_H264 h264Config; /**< [in]: Specifies the H.264-specific encoder configuration. */ - NV_ENC_CONFIG_HEVC hevcConfig; /**< [in]: Specifies the HEVC-specific encoder configuration. */ - NV_ENC_CONFIG_H264_MEONLY h264MeOnlyConfig; /**< [in]: Specifies the H.264-specific ME only encoder configuration. */ - NV_ENC_CONFIG_HEVC_MEONLY hevcMeOnlyConfig; /**< [in]: Specifies the HEVC-specific ME only encoder configuration. */ - uint32_t reserved[320]; /**< [in]: Reserved and must be set to 0 */ -} NV_ENC_CODEC_CONFIG; - - -/** - * \struct _NV_ENC_CONFIG - * Encoder configuration parameters to be set during initialization. - */ -typedef struct _NV_ENC_CONFIG -{ - uint32_t version; /**< [in]: Struct version. Must be set to ::NV_ENC_CONFIG_VER. */ - GUID profileGUID; /**< [in]: Specifies the codec profile guid. If client specifies \p NV_ENC_CODEC_PROFILE_AUTOSELECT_GUID the NvEncodeAPI interface will select the appropriate codec profile. */ - uint32_t gopLength; /**< [in]: Specifies the number of pictures in one GOP. Low latency application client can set goplength to NVENC_INFINITE_GOPLENGTH so that keyframes are not inserted automatically. */ - int32_t frameIntervalP; /**< [in]: Specifies the GOP pattern as follows: \p frameIntervalP = 0: I, 1: IPP, 2: IBP, 3: IBBP If goplength is set to NVENC_INFINITE_GOPLENGTH \p frameIntervalP should be set to 1. */ - uint32_t monoChromeEncoding; /**< [in]: Set this to 1 to enable monochrome encoding for this session. */ - NV_ENC_PARAMS_FRAME_FIELD_MODE frameFieldMode; /**< [in]: Specifies the frame/field mode. - Check support for field encoding using ::NV_ENC_CAPS_SUPPORT_FIELD_ENCODING caps. - Using a frameFieldMode other than NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME for RGB input is not supported. */ - NV_ENC_MV_PRECISION mvPrecision; /**< [in]: Specifies the desired motion vector prediction precision. */ - NV_ENC_RC_PARAMS rcParams; /**< [in]: Specifies the rate control parameters for the current encoding session. */ - NV_ENC_CODEC_CONFIG encodeCodecConfig; /**< [in]: Specifies the codec specific config parameters through this union. */ - uint32_t reserved [278]; /**< [in]: Reserved and must be set to 0 */ - void* reserved2[64]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_CONFIG; - -/** macro for constructing the version field of ::_NV_ENC_CONFIG */ -#define NV_ENC_CONFIG_VER (NVENCAPI_STRUCT_VERSION(6) | ( 1<<31 )) - - -/** - * \struct _NV_ENC_INITIALIZE_PARAMS - * Encode Session Initialization parameters. - */ -typedef struct _NV_ENC_INITIALIZE_PARAMS -{ - uint32_t version; /**< [in]: Struct version. Must be set to ::NV_ENC_INITIALIZE_PARAMS_VER. */ - GUID encodeGUID; /**< [in]: Specifies the Encode GUID for which the encoder is being created. ::NvEncInitializeEncoder() API will fail if this is not set, or set to unsupported value. */ - GUID presetGUID; /**< [in]: Specifies the preset for encoding. If the preset GUID is set then , the preset configuration will be applied before any other parameter. */ - uint32_t encodeWidth; /**< [in]: Specifies the encode width. If not set ::NvEncInitializeEncoder() API will fail. */ - uint32_t encodeHeight; /**< [in]: Specifies the encode height. If not set ::NvEncInitializeEncoder() API will fail. */ - uint32_t darWidth; /**< [in]: Specifies the display aspect ratio Width. */ - uint32_t darHeight; /**< [in]: Specifies the display aspect ratio height. */ - uint32_t frameRateNum; /**< [in]: Specifies the numerator for frame rate used for encoding in frames per second ( Frame rate = frameRateNum / frameRateDen ). */ - uint32_t frameRateDen; /**< [in]: Specifies the denominator for frame rate used for encoding in frames per second ( Frame rate = frameRateNum / frameRateDen ). */ - uint32_t enableEncodeAsync; /**< [in]: Set this to 1 to enable asynchronous mode and is expected to use events to get picture completion notification. */ - uint32_t enablePTD; /**< [in]: Set this to 1 to enable the Picture Type Decision is be taken by the NvEncodeAPI interface. */ - uint32_t reportSliceOffsets :1; /**< [in]: Set this to 1 to enable reporting slice offsets in ::_NV_ENC_LOCK_BITSTREAM. NV_ENC_INITIALIZE_PARAMS::enableEncodeAsync must be set to 0 to use this feature. Client must set this to 0 if NV_ENC_CONFIG_H264::sliceMode is 1 on Kepler GPUs */ - uint32_t enableSubFrameWrite :1; /**< [in]: Set this to 1 to write out available bitstream to memory at subframe intervals */ - uint32_t enableExternalMEHints :1; /**< [in]: Set to 1 to enable external ME hints for the current frame. For NV_ENC_INITIALIZE_PARAMS::enablePTD=1 with B frames, programming L1 hints is optional for B frames since Client doesn't know internal GOP structure. - NV_ENC_PIC_PARAMS::meHintRefPicDist should preferably be set with enablePTD=1. */ - uint32_t enableMEOnlyMode :1; /**< [in]: Set to 1 to enable ME Only Mode .*/ - uint32_t enableWeightedPrediction :1; /**< [in]: Set this to 1 to enable weighted prediction. Not supported if encode session is configured for B-Frames( 'frameIntervalP' in NV_ENC_CONFIG is greater than 1).*/ - uint32_t reservedBitFields :27; /**< [in]: Reserved bitfields and must be set to 0 */ - uint32_t privDataSize; /**< [in]: Reserved private data buffer size and must be set to 0 */ - void* privData; /**< [in]: Reserved private data buffer and must be set to NULL */ - NV_ENC_CONFIG* encodeConfig; /**< [in]: Specifies the advanced codec specific structure. If client has sent a valid codec config structure, it will override parameters set by the NV_ENC_INITIALIZE_PARAMS::presetGUID parameter. If set to NULL the NvEncodeAPI interface will use the NV_ENC_INITIALIZE_PARAMS::presetGUID to set the codec specific parameters. - Client can also optionally query the NvEncodeAPI interface to get codec specific parameters for a presetGUID using ::NvEncGetEncodePresetConfig() API. It can then modify (if required) some of the codec config parameters and send down a custom config structure as part of ::_NV_ENC_INITIALIZE_PARAMS. - Even in this case client is recommended to pass the same preset guid it has used in ::NvEncGetEncodePresetConfig() API to query the config structure; as NV_ENC_INITIALIZE_PARAMS::presetGUID. This will not override the custom config structure but will be used to determine other Encoder HW specific parameters not exposed in the API. */ - uint32_t maxEncodeWidth; /**< [in]: Maximum encode width to be used for current Encode session. - Client should allocate output buffers according to this dimension for dynamic resolution change. If set to 0, Encoder will not allow dynamic resolution change. */ - uint32_t maxEncodeHeight; /**< [in]: Maximum encode height to be allowed for current Encode session. - Client should allocate output buffers according to this dimension for dynamic resolution change. If set to 0, Encode will not allow dynamic resolution change. */ - NVENC_EXTERNAL_ME_HINT_COUNTS_PER_BLOCKTYPE maxMEHintCountsPerBlock[2]; /**< [in]: If Client wants to pass external motion vectors in NV_ENC_PIC_PARAMS::meExternalHints buffer it must specify the maximum number of hint candidates per block per direction for the encode session. - The NV_ENC_INITIALIZE_PARAMS::maxMEHintCountsPerBlock[0] is for L0 predictors and NV_ENC_INITIALIZE_PARAMS::maxMEHintCountsPerBlock[1] is for L1 predictors. - This client must also set NV_ENC_INITIALIZE_PARAMS::enableExternalMEHints to 1. */ - uint32_t reserved [289]; /**< [in]: Reserved and must be set to 0 */ - void* reserved2[64]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_INITIALIZE_PARAMS; - -/** macro for constructing the version field of ::_NV_ENC_INITIALIZE_PARAMS */ -#define NV_ENC_INITIALIZE_PARAMS_VER (NVENCAPI_STRUCT_VERSION(5) | ( 1<<31 )) - - -/** - * \struct _NV_ENC_RECONFIGURE_PARAMS - * Encode Session Reconfigured parameters. - */ -typedef struct _NV_ENC_RECONFIGURE_PARAMS -{ - uint32_t version; /**< [in]: Struct version. Must be set to ::NV_ENC_RECONFIGURE_PARAMS_VER. */ - NV_ENC_INITIALIZE_PARAMS reInitEncodeParams; /**< [in]: Encoder session re-initialization parameters. */ - uint32_t resetEncoder :1; /**< [in]: This resets the rate control states and other internal encoder states. This should be used only with an IDR frame. - If NV_ENC_INITIALIZE_PARAMS::enablePTD is set to 1, encoder will force the frame type to IDR */ - uint32_t forceIDR :1; /**< [in]: Encode the current picture as an IDR picture. This flag is only valid when Picture type decision is taken by the Encoder - [_NV_ENC_INITIALIZE_PARAMS::enablePTD == 1]. */ - uint32_t reserved :30; - -}NV_ENC_RECONFIGURE_PARAMS; - -/** macro for constructing the version field of ::_NV_ENC_RECONFIGURE_PARAMS */ -#define NV_ENC_RECONFIGURE_PARAMS_VER (NVENCAPI_STRUCT_VERSION(1) | ( 1<<31 )) - -/** - * \struct _NV_ENC_PRESET_CONFIG - * Encoder preset config - */ -typedef struct _NV_ENC_PRESET_CONFIG -{ - uint32_t version; /**< [in]: Struct version. Must be set to ::NV_ENC_PRESET_CONFIG_VER. */ - NV_ENC_CONFIG presetCfg; /**< [out]: preset config returned by the Nvidia Video Encoder interface. */ - uint32_t reserved1[255]; /**< [in]: Reserved and must be set to 0 */ - void* reserved2[64]; /**< [in]: Reserved and must be set to NULL */ -}NV_ENC_PRESET_CONFIG; - -/** macro for constructing the version field of ::_NV_ENC_PRESET_CONFIG */ -#define NV_ENC_PRESET_CONFIG_VER (NVENCAPI_STRUCT_VERSION(4) | ( 1<<31 )) - - -/** - * \struct _NV_ENC_SEI_PAYLOAD - * User SEI message - */ -typedef struct _NV_ENC_SEI_PAYLOAD -{ - uint32_t payloadSize; /**< [in] SEI payload size in bytes. SEI payload must be byte aligned, as described in Annex D */ - uint32_t payloadType; /**< [in] SEI payload types and syntax can be found in Annex D of the H.264 Specification. */ - uint8_t *payload; /**< [in] pointer to user data */ -} NV_ENC_SEI_PAYLOAD; - -#define NV_ENC_H264_SEI_PAYLOAD NV_ENC_SEI_PAYLOAD - -/** - * \struct _NV_ENC_PIC_PARAMS_H264 - * H264 specific enc pic params. sent on a per frame basis. - */ -typedef struct _NV_ENC_PIC_PARAMS_H264 -{ - uint32_t displayPOCSyntax; /**< [in]: Specifies the display POC syntax This is required to be set if client is handling the picture type decision. */ - uint32_t reserved3; /**< [in]: Reserved and must be set to 0 */ - uint32_t refPicFlag; /**< [in]: Set to 1 for a reference picture. This is ignored if NV_ENC_INITIALIZE_PARAMS::enablePTD is set to 1. */ - uint32_t colourPlaneId; /**< [in]: Specifies the colour plane ID associated with the current input. */ - uint32_t forceIntraRefreshWithFrameCnt; /**< [in]: Forces an intra refresh with duration equal to intraRefreshFrameCnt. - When outputRecoveryPointSEI is set this is value is used for recovery_frame_cnt in recovery point SEI message - forceIntraRefreshWithFrameCnt cannot be used if B frames are used in the GOP structure specified */ - uint32_t constrainedFrame :1; /**< [in]: Set to 1 if client wants to encode this frame with each slice completely independent of other slices in the frame. - NV_ENC_INITIALIZE_PARAMS::enableConstrainedEncoding should be set to 1 */ - uint32_t sliceModeDataUpdate :1; /**< [in]: Set to 1 if client wants to change the sliceModeData field to specify new sliceSize Parameter - When forceIntraRefreshWithFrameCnt is set it will have priority over sliceMode setting */ - uint32_t ltrMarkFrame :1; /**< [in]: Set to 1 if client wants to mark this frame as LTR */ - uint32_t ltrUseFrames :1; /**< [in]: Set to 1 if client allows encoding this frame using the LTR frames specified in ltrFrameBitmap */ - uint32_t reservedBitFields :28; /**< [in]: Reserved bit fields and must be set to 0 */ - uint8_t* sliceTypeData; /**< [in]: Deprecated. */ - uint32_t sliceTypeArrayCnt; /**< [in]: Deprecated. */ - uint32_t seiPayloadArrayCnt; /**< [in]: Specifies the number of elements allocated in seiPayloadArray array. */ - NV_ENC_SEI_PAYLOAD* seiPayloadArray; /**< [in]: Array of SEI payloads which will be inserted for this frame. */ - uint32_t sliceMode; /**< [in]: This parameter in conjunction with sliceModeData specifies the way in which the picture is divided into slices - sliceMode = 0 MB based slices, sliceMode = 1 Byte based slices, sliceMode = 2 MB row based slices, sliceMode = 3, numSlices in Picture - When forceIntraRefreshWithFrameCnt is set it will have priority over sliceMode setting - When sliceMode == 0 and sliceModeData == 0 whole picture will be coded with one slice */ - uint32_t sliceModeData; /**< [in]: Specifies the parameter needed for sliceMode. For: - sliceMode = 0, sliceModeData specifies # of MBs in each slice (except last slice) - sliceMode = 1, sliceModeData specifies maximum # of bytes in each slice (except last slice) - sliceMode = 2, sliceModeData specifies # of MB rows in each slice (except last slice) - sliceMode = 3, sliceModeData specifies number of slices in the picture. Driver will divide picture into slices optimally */ - uint32_t ltrMarkFrameIdx; /**< [in]: Specifies the long term referenceframe index to use for marking this frame as LTR.*/ - uint32_t ltrUseFrameBitmap; /**< [in]: Specifies the the associated bitmap of LTR frame indices to use when encoding this frame. */ - uint32_t ltrUsageMode; /**< [in]: Not supported. Reserved for future use and must be set to 0. */ - uint32_t reserved [243]; /**< [in]: Reserved and must be set to 0. */ - void* reserved2[62]; /**< [in]: Reserved and must be set to NULL. */ -} NV_ENC_PIC_PARAMS_H264; - -/** - * \struct _NV_ENC_PIC_PARAMS_HEVC - * HEVC specific enc pic params. sent on a per frame basis. - */ -typedef struct _NV_ENC_PIC_PARAMS_HEVC -{ - uint32_t displayPOCSyntax; /**< [in]: Specifies the display POC syntax This is required to be set if client is handling the picture type decision. */ - uint32_t refPicFlag; /**< [in]: Set to 1 for a reference picture. This is ignored if NV_ENC_INITIALIZE_PARAMS::enablePTD is set to 1. */ - uint32_t temporalId; /**< [in]: Specifies the temporal id of the picture */ - uint32_t forceIntraRefreshWithFrameCnt; /**< [in]: Forces an intra refresh with duration equal to intraRefreshFrameCnt. - When outputRecoveryPointSEI is set this is value is used for recovery_frame_cnt in recovery point SEI message - forceIntraRefreshWithFrameCnt cannot be used if B frames are used in the GOP structure specified */ - uint32_t constrainedFrame :1; /**< [in]: Set to 1 if client wants to encode this frame with each slice completely independent of other slices in the frame. - NV_ENC_INITIALIZE_PARAMS::enableConstrainedEncoding should be set to 1 */ - uint32_t sliceModeDataUpdate :1; /**< [in]: Set to 1 if client wants to change the sliceModeData field to specify new sliceSize Parameter - When forceIntraRefreshWithFrameCnt is set it will have priority over sliceMode setting */ - uint32_t ltrMarkFrame :1; /**< [in]: Set to 1 if client wants to mark this frame as LTR */ - uint32_t ltrUseFrames :1; /**< [in]: Set to 1 if client allows encoding this frame using the LTR frames specified in ltrFrameBitmap */ - uint32_t reservedBitFields :28; /**< [in]: Reserved bit fields and must be set to 0 */ - uint8_t* sliceTypeData; /**< [in]: Array which specifies the slice type used to force intra slice for a particular slice. Currently supported only for NV_ENC_CONFIG_H264::sliceMode == 3. - Client should allocate array of size sliceModeData where sliceModeData is specified in field of ::_NV_ENC_CONFIG_H264 - Array element with index n corresponds to nth slice. To force a particular slice to intra client should set corresponding array element to NV_ENC_SLICE_TYPE_I - all other array elements should be set to NV_ENC_SLICE_TYPE_DEFAULT */ - uint32_t sliceTypeArrayCnt; /**< [in]: Client should set this to the number of elements allocated in sliceTypeData array. If sliceTypeData is NULL then this should be set to 0 */ - uint32_t sliceMode; /**< [in]: This parameter in conjunction with sliceModeData specifies the way in which the picture is divided into slices - sliceMode = 0 CTU based slices, sliceMode = 1 Byte based slices, sliceMode = 2 CTU row based slices, sliceMode = 3, numSlices in Picture - When forceIntraRefreshWithFrameCnt is set it will have priority over sliceMode setting - When sliceMode == 0 and sliceModeData == 0 whole picture will be coded with one slice */ - uint32_t sliceModeData; /**< [in]: Specifies the parameter needed for sliceMode. For: - sliceMode = 0, sliceModeData specifies # of CTUs in each slice (except last slice) - sliceMode = 1, sliceModeData specifies maximum # of bytes in each slice (except last slice) - sliceMode = 2, sliceModeData specifies # of CTU rows in each slice (except last slice) - sliceMode = 3, sliceModeData specifies number of slices in the picture. Driver will divide picture into slices optimally */ - uint32_t ltrMarkFrameIdx; /**< [in]: Specifies the long term reference frame index to use for marking this frame as LTR.*/ - uint32_t ltrUseFrameBitmap; /**< [in]: Specifies the associated bitmap of LTR frame indices to use when encoding this frame. */ - uint32_t ltrUsageMode; /**< [in]: Not supported. Reserved for future use and must be set to 0. */ - uint32_t seiPayloadArrayCnt; /**< [in]: Specifies the number of elements allocated in seiPayloadArray array. */ - uint32_t reserved; /**< [in]: Reserved and must be set to 0. */ - NV_ENC_SEI_PAYLOAD* seiPayloadArray; /**< [in]: Array of SEI payloads which will be inserted for this frame. */ - uint32_t reserved2 [244]; /**< [in]: Reserved and must be set to 0. */ - void* reserved3[61]; /**< [in]: Reserved and must be set to NULL. */ -} NV_ENC_PIC_PARAMS_HEVC; - - -/** - * Codec specific per-picture encoding parameters. - */ -typedef union _NV_ENC_CODEC_PIC_PARAMS -{ - NV_ENC_PIC_PARAMS_H264 h264PicParams; /**< [in]: H264 encode picture params. */ - NV_ENC_PIC_PARAMS_HEVC hevcPicParams; /**< [in]: HEVC encode picture params. */ - uint32_t reserved[256]; /**< [in]: Reserved and must be set to 0. */ -} NV_ENC_CODEC_PIC_PARAMS; - -/** - * \struct _NV_ENC_PIC_PARAMS - * Encoding parameters that need to be sent on a per frame basis. - */ -typedef struct _NV_ENC_PIC_PARAMS -{ - uint32_t version; /**< [in]: Struct version. Must be set to ::NV_ENC_PIC_PARAMS_VER. */ - uint32_t inputWidth; /**< [in]: Specifies the input buffer width */ - uint32_t inputHeight; /**< [in]: Specifies the input buffer height */ - uint32_t inputPitch; /**< [in]: Specifies the input buffer pitch. If pitch value is not known, set this to inputWidth. */ - uint32_t encodePicFlags; /**< [in]: Specifies bit-wise OR`ed encode pic flags. See ::NV_ENC_PIC_FLAGS enum. */ - uint32_t frameIdx; /**< [in]: Specifies the frame index associated with the input frame [optional]. */ - uint64_t inputTimeStamp; /**< [in]: Specifies presentation timestamp associated with the input picture. */ - uint64_t inputDuration; /**< [in]: Specifies duration of the input picture */ - NV_ENC_INPUT_PTR inputBuffer; /**< [in]: Specifies the input buffer pointer. Client must use a pointer obtained from ::NvEncCreateInputBuffer() or ::NvEncMapInputResource() APIs.*/ - NV_ENC_OUTPUT_PTR outputBitstream; /**< [in]: Specifies the pointer to output buffer. Client should use a pointer obtained from ::NvEncCreateBitstreamBuffer() API. */ - void* completionEvent; /**< [in]: Specifies an event to be signalled on completion of encoding of this Frame [only if operating in Asynchronous mode]. Each output buffer should be associated with a distinct event pointer. */ - NV_ENC_BUFFER_FORMAT bufferFmt; /**< [in]: Specifies the input buffer format. */ - NV_ENC_PIC_STRUCT pictureStruct; /**< [in]: Specifies structure of the input picture. */ - NV_ENC_PIC_TYPE pictureType; /**< [in]: Specifies input picture type. Client required to be set explicitly by the client if the client has not set NV_ENC_INITALIZE_PARAMS::enablePTD to 1 while calling NvInitializeEncoder. */ - NV_ENC_CODEC_PIC_PARAMS codecPicParams; /**< [in]: Specifies the codec specific per-picture encoding parameters. */ - NVENC_EXTERNAL_ME_HINT_COUNTS_PER_BLOCKTYPE meHintCountsPerBlock[2]; /**< [in]: Specifies the number of hint candidates per block per direction for the current frame. meHintCountsPerBlock[0] is for L0 predictors and meHintCountsPerBlock[1] is for L1 predictors. - The candidate count in NV_ENC_PIC_PARAMS::meHintCountsPerBlock[lx] must never exceed NV_ENC_INITIALIZE_PARAMS::maxMEHintCountsPerBlock[lx] provided during encoder intialization. */ - NVENC_EXTERNAL_ME_HINT *meExternalHints; /**< [in]: Specifies the pointer to ME external hints for the current frame. The size of ME hint buffer should be equal to number of macroblocks * the total number of candidates per macroblock. - The total number of candidates per MB per direction = 1*meHintCountsPerBlock[Lx].numCandsPerBlk16x16 + 2*meHintCountsPerBlock[Lx].numCandsPerBlk16x8 + 2*meHintCountsPerBlock[Lx].numCandsPerBlk8x8 - + 4*meHintCountsPerBlock[Lx].numCandsPerBlk8x8. For frames using bidirectional ME , the total number of candidates for single macroblock is sum of total number of candidates per MB for each direction (L0 and L1) */ - uint32_t reserved1[6]; /**< [in]: Reserved and must be set to 0 */ - void* reserved2[2]; /**< [in]: Reserved and must be set to NULL */ - int8_t *qpDeltaMap; /**< [in]: Specifies the pointer to signed byte array containing QP delta value per MB in raster scan order in the current picture. This QP modifier is applied on top of the QP chosen by rate control. */ - uint32_t qpDeltaMapSize; /**< [in]: Specifies the size in bytes of qpDeltaMap surface allocated by client and pointed to by NV_ENC_PIC_PARAMS::qpDeltaMap. Surface (array) should be picWidthInMbs * picHeightInMbs */ - uint32_t reservedBitFields; /**< [in]: Reserved bitfields and must be set to 0 */ - uint16_t meHintRefPicDist[2]; /**< [in]: Specifies temporal distance for reference picture (NVENC_EXTERNAL_ME_HINT::refidx = 0) used during external ME with NV_ENC_INITALIZE_PARAMS::enablePTD = 1 . meHintRefPicDist[0] is for L0 hints and meHintRefPicDist[1] is for L1 hints. - If not set, will internally infer distance of 1. Ignored for NV_ENC_INITALIZE_PARAMS::enablePTD = 0 */ - uint32_t reserved3[286]; /**< [in]: Reserved and must be set to 0 */ - void* reserved4[60]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_PIC_PARAMS; - -/** Macro for constructing the version field of ::_NV_ENC_PIC_PARAMS */ -#define NV_ENC_PIC_PARAMS_VER (NVENCAPI_STRUCT_VERSION(4) | ( 1<<31 )) - - -/** - * \struct _NV_ENC_MEONLY_PARAMS - * MEOnly parameters that need to be sent on a per motion estimation basis. - * NV_ENC_MEONLY_PARAMS::meExternalHints is supported for H264 only. - */ -typedef struct _NV_ENC_MEONLY_PARAMS -{ - uint32_t version; /**< [in]: Struct version. Must be set to NV_ENC_MEONLY_PARAMS_VER.*/ - uint32_t inputWidth; /**< [in]: Specifies the input buffer width */ - uint32_t inputHeight; /**< [in]: Specifies the input buffer height */ - NV_ENC_INPUT_PTR inputBuffer; /**< [in]: Specifies the input buffer pointer. Client must use a pointer obtained from NvEncCreateInputBuffer() or NvEncMapInputResource() APIs. */ - NV_ENC_INPUT_PTR referenceFrame; /**< [in]: Specifies the reference frame pointer */ - NV_ENC_OUTPUT_PTR mvBuffer; /**< [in]: Specifies the pointer to motion vector data buffer allocated by NvEncCreateMVBuffer. Client must lock mvBuffer using ::NvEncLockBitstream() API to get the motion vector data. */ - NV_ENC_BUFFER_FORMAT bufferFmt; /**< [in]: Specifies the input buffer format. */ - void* completionEvent; /**< [in]: Specifies an event to be signalled on completion of motion estimation - of this Frame [only if operating in Asynchronous mode]. - Each output buffer should be associated with a distinct event pointer. */ - uint32_t viewID; /**< [in]: Specifies left,right viewID if NV_ENC_CONFIG_H264_MEONLY::bStereoEnable is set. - viewID can be 0,1 if bStereoEnable is set, 0 otherwise. */ - NVENC_EXTERNAL_ME_HINT_COUNTS_PER_BLOCKTYPE - meHintCountsPerBlock[2]; /**< [in]: Specifies the number of hint candidates per block for the current frame. meHintCountsPerBlock[0] is for L0 predictors. - The candidate count in NV_ENC_PIC_PARAMS::meHintCountsPerBlock[lx] must never exceed NV_ENC_INITIALIZE_PARAMS::maxMEHintCountsPerBlock[lx] provided during encoder intialization. */ - NVENC_EXTERNAL_ME_HINT *meExternalHints; /**< [in]: Specifies the pointer to ME external hints for the current frame. The size of ME hint buffer should be equal to number of macroblocks * the total number of candidates per macroblock. - The total number of candidates per MB per direction = 1*meHintCountsPerBlock[Lx].numCandsPerBlk16x16 + 2*meHintCountsPerBlock[Lx].numCandsPerBlk16x8 + 2*meHintCountsPerBlock[Lx].numCandsPerBlk8x8 - + 4*meHintCountsPerBlock[Lx].numCandsPerBlk8x8. For frames using bidirectional ME , the total number of candidates for single macroblock is sum of total number of candidates per MB for each direction (L0 and L1) */ - uint32_t reserved1[243]; /**< [in]: Reserved and must be set to 0 */ - void* reserved2[59]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_MEONLY_PARAMS; - -/** NV_ENC_MEONLY_PARAMS struct version*/ -#define NV_ENC_MEONLY_PARAMS_VER NVENCAPI_STRUCT_VERSION(3) - - -/** - * \struct _NV_ENC_LOCK_BITSTREAM - * Bitstream buffer lock parameters. - */ -typedef struct _NV_ENC_LOCK_BITSTREAM -{ - uint32_t version; /**< [in]: Struct version. Must be set to ::NV_ENC_LOCK_BITSTREAM_VER. */ - uint32_t doNotWait :1; /**< [in]: If this flag is set, the NvEncodeAPI interface will return buffer pointer even if operation is not completed. If not set, the call will block until operation completes. */ - uint32_t ltrFrame :1; /**< [out]: Flag indicating this frame is marked as LTR frame */ - uint32_t reservedBitFields :30; /**< [in]: Reserved bit fields and must be set to 0 */ - void* outputBitstream; /**< [in]: Pointer to the bitstream buffer being locked. */ - uint32_t* sliceOffsets; /**< [in,out]: Array which receives the slice offsets. This is not supported if NV_ENC_CONFIG_H264::sliceMode is 1 on Kepler GPUs. Array size must be equal to size of frame in MBs. */ - uint32_t frameIdx; /**< [out]: Frame no. for which the bitstream is being retrieved. */ - uint32_t hwEncodeStatus; /**< [out]: The NvEncodeAPI interface status for the locked picture. */ - uint32_t numSlices; /**< [out]: Number of slices in the encoded picture. Will be reported only if NV_ENC_INITIALIZE_PARAMS::reportSliceOffsets set to 1. */ - uint32_t bitstreamSizeInBytes; /**< [out]: Actual number of bytes generated and copied to the memory pointed by bitstreamBufferPtr. */ - uint64_t outputTimeStamp; /**< [out]: Presentation timestamp associated with the encoded output. */ - uint64_t outputDuration; /**< [out]: Presentation duration associates with the encoded output. */ - void* bitstreamBufferPtr; /**< [out]: Pointer to the generated output bitstream. - For MEOnly mode _NV_ENC_LOCK_BITSTREAM::bitstreamBufferPtr should be typecast to - NV_ENC_H264_MV_DATA/NV_ENC_HEVC_MV_DATA pointer respectively for H264/HEVC */ - NV_ENC_PIC_TYPE pictureType; /**< [out]: Picture type of the encoded picture. */ - NV_ENC_PIC_STRUCT pictureStruct; /**< [out]: Structure of the generated output picture. */ - uint32_t frameAvgQP; /**< [out]: Average QP of the frame. */ - uint32_t frameSatd; /**< [out]: Total SATD cost for whole frame. */ - uint32_t ltrFrameIdx; /**< [out]: Frame index associated with this LTR frame. */ - uint32_t ltrFrameBitmap; /**< [out]: Bitmap of LTR frames indices which were used for encoding this frame. Value of 0 if no LTR frames were used. */ - uint32_t reserved [236]; /**< [in]: Reserved and must be set to 0 */ - void* reserved2[64]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_LOCK_BITSTREAM; - -/** Macro for constructing the version field of ::_NV_ENC_LOCK_BITSTREAM */ -#define NV_ENC_LOCK_BITSTREAM_VER NVENCAPI_STRUCT_VERSION(1) - - -/** - * \struct _NV_ENC_LOCK_INPUT_BUFFER - * Uncompressed Input Buffer lock parameters. - */ -typedef struct _NV_ENC_LOCK_INPUT_BUFFER -{ - uint32_t version; /**< [in]: Struct version. Must be set to ::NV_ENC_LOCK_INPUT_BUFFER_VER. */ - uint32_t doNotWait :1; /**< [in]: Set to 1 to make ::NvEncLockInputBuffer() a unblocking call. If the encoding is not completed, driver will return ::NV_ENC_ERR_ENCODER_BUSY error code. */ - uint32_t reservedBitFields :31; /**< [in]: Reserved bitfields and must be set to 0 */ - NV_ENC_INPUT_PTR inputBuffer; /**< [in]: Pointer to the input buffer to be locked, client should pass the pointer obtained from ::NvEncCreateInputBuffer() or ::NvEncMapInputResource API. */ - void* bufferDataPtr; /**< [out]: Pointed to the locked input buffer data. Client can only access input buffer using the \p bufferDataPtr. */ - uint32_t pitch; /**< [out]: Pitch of the locked input buffer. */ - uint32_t reserved1[251]; /**< [in]: Reserved and must be set to 0 */ - void* reserved2[64]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_LOCK_INPUT_BUFFER; - -/** Macro for constructing the version field of ::_NV_ENC_LOCK_INPUT_BUFFER */ -#define NV_ENC_LOCK_INPUT_BUFFER_VER NVENCAPI_STRUCT_VERSION(1) - - -/** - * \struct _NV_ENC_MAP_INPUT_RESOURCE - * Map an input resource to a Nvidia Encoder Input Buffer - */ -typedef struct _NV_ENC_MAP_INPUT_RESOURCE -{ - uint32_t version; /**< [in]: Struct version. Must be set to ::NV_ENC_MAP_INPUT_RESOURCE_VER. */ - uint32_t subResourceIndex; /**< [in]: Deprecated. Do not use. */ - void* inputResource; /**< [in]: Deprecated. Do not use. */ - NV_ENC_REGISTERED_PTR registeredResource; /**< [in]: The Registered resource handle obtained by calling NvEncRegisterInputResource. */ - NV_ENC_INPUT_PTR mappedResource; /**< [out]: Mapped pointer corresponding to the registeredResource. This pointer must be used in NV_ENC_PIC_PARAMS::inputBuffer parameter in ::NvEncEncodePicture() API. */ - NV_ENC_BUFFER_FORMAT mappedBufferFmt; /**< [out]: Buffer format of the outputResource. This buffer format must be used in NV_ENC_PIC_PARAMS::bufferFmt if client using the above mapped resource pointer. */ - uint32_t reserved1[251]; /**< [in]: Reserved and must be set to 0. */ - void* reserved2[63]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_MAP_INPUT_RESOURCE; - -/** Macro for constructing the version field of ::_NV_ENC_MAP_INPUT_RESOURCE */ -#define NV_ENC_MAP_INPUT_RESOURCE_VER NVENCAPI_STRUCT_VERSION(4) - -/** - * \struct _NV_ENC_INPUT_RESOURCE_OPENGL_TEX - * NV_ENC_REGISTER_RESOURCE::resourceToRegister must be a pointer to a variable of this type, - * when NV_ENC_REGISTER_RESOURCE::resourceType is NV_ENC_INPUT_RESOURCE_TYPE_OPENGL_TEX - */ -typedef struct _NV_ENC_INPUT_RESOURCE_OPENGL_TEX -{ - uint32_t texture; /**< [in]: The name of the texture to be used. */ - uint32_t target; /**< [in]: Accepted values are GL_TEXTURE_RECTANGLE and GL_TEXTURE_2D. */ -} NV_ENC_INPUT_RESOURCE_OPENGL_TEX; - -/** - * \struct _NV_ENC_REGISTER_RESOURCE - * Register a resource for future use with the Nvidia Video Encoder Interface. - */ -typedef struct _NV_ENC_REGISTER_RESOURCE -{ - uint32_t version; /**< [in]: Struct version. Must be set to ::NV_ENC_REGISTER_RESOURCE_VER. */ - NV_ENC_INPUT_RESOURCE_TYPE resourceType; /**< [in]: Specifies the type of resource to be registered. - Supported values are - ::NV_ENC_INPUT_RESOURCE_TYPE_DIRECTX, - ::NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR, - ::NV_ENC_INPUT_RESOURCE_TYPE_OPENGL_TEX */ - uint32_t width; /**< [in]: Input buffer Width. */ - uint32_t height; /**< [in]: Input buffer Height. */ - uint32_t pitch; /**< [in]: Input buffer Pitch. */ - uint32_t subResourceIndex; /**< [in]: Subresource Index of the DirectX resource to be registered. Should be set to 0 for other interfaces. */ - void* resourceToRegister; /**< [in]: Handle to the resource that is being registered. */ - NV_ENC_REGISTERED_PTR registeredResource; /**< [out]: Registered resource handle. This should be used in future interactions with the Nvidia Video Encoder Interface. */ - NV_ENC_BUFFER_FORMAT bufferFormat; /**< [in]: Buffer format of resource to be registered. */ - uint32_t reserved1[248]; /**< [in]: Reserved and must be set to 0. */ - void* reserved2[62]; /**< [in]: Reserved and must be set to NULL. */ -} NV_ENC_REGISTER_RESOURCE; - -/** Macro for constructing the version field of ::_NV_ENC_REGISTER_RESOURCE */ -#define NV_ENC_REGISTER_RESOURCE_VER NVENCAPI_STRUCT_VERSION(3) - -/** - * \struct _NV_ENC_STAT - * Encode Stats structure. - */ -typedef struct _NV_ENC_STAT -{ - uint32_t version; /**< [in]: Struct version. Must be set to ::NV_ENC_STAT_VER. */ - uint32_t reserved; /**< [in]: Reserved and must be set to 0 */ - NV_ENC_OUTPUT_PTR outputBitStream; /**< [out]: Specifies the pointer to output bitstream. */ - uint32_t bitStreamSize; /**< [out]: Size of generated bitstream in bytes. */ - uint32_t picType; /**< [out]: Picture type of encoded picture. See ::NV_ENC_PIC_TYPE. */ - uint32_t lastValidByteOffset; /**< [out]: Offset of last valid bytes of completed bitstream */ - uint32_t sliceOffsets[16]; /**< [out]: Offsets of each slice */ - uint32_t picIdx; /**< [out]: Picture number */ - uint32_t reserved1[233]; /**< [in]: Reserved and must be set to 0 */ - void* reserved2[64]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_STAT; - -/** Macro for constructing the version field of ::_NV_ENC_STAT */ -#define NV_ENC_STAT_VER NVENCAPI_STRUCT_VERSION(1) - - -/** - * \struct _NV_ENC_SEQUENCE_PARAM_PAYLOAD - * Sequence and picture paramaters payload. - */ -typedef struct _NV_ENC_SEQUENCE_PARAM_PAYLOAD -{ - uint32_t version; /**< [in]: Struct version. Must be set to ::NV_ENC_INITIALIZE_PARAMS_VER. */ - uint32_t inBufferSize; /**< [in]: Specifies the size of the spsppsBuffer provied by the client */ - uint32_t spsId; /**< [in]: Specifies the SPS id to be used in sequence header. Default value is 0. */ - uint32_t ppsId; /**< [in]: Specifies the PPS id to be used in picture header. Default value is 0. */ - void* spsppsBuffer; /**< [in]: Specifies bitstream header pointer of size NV_ENC_SEQUENCE_PARAM_PAYLOAD::inBufferSize. It is the client's responsibility to manage this memory. */ - uint32_t* outSPSPPSPayloadSize; /**< [out]: Size of the sequence and picture header in bytes written by the NvEncodeAPI interface to the SPSPPSBuffer. */ - uint32_t reserved [250]; /**< [in]: Reserved and must be set to 0 */ - void* reserved2[64]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_SEQUENCE_PARAM_PAYLOAD; - -/** Macro for constructing the version field of ::_NV_ENC_SEQUENCE_PARAM_PAYLOAD */ -#define NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER NVENCAPI_STRUCT_VERSION(1) - - -/** - * Event registration/unregistration parameters. - */ -typedef struct _NV_ENC_EVENT_PARAMS -{ - uint32_t version; /**< [in]: Struct version. Must be set to ::NV_ENC_EVENT_PARAMS_VER. */ - uint32_t reserved; /**< [in]: Reserved and must be set to 0 */ - void* completionEvent; /**< [in]: Handle to event to be registered/unregistered with the NvEncodeAPI interface. */ - uint32_t reserved1[253]; /**< [in]: Reserved and must be set to 0 */ - void* reserved2[64]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_EVENT_PARAMS; - -/** Macro for constructing the version field of ::_NV_ENC_EVENT_PARAMS */ -#define NV_ENC_EVENT_PARAMS_VER NVENCAPI_STRUCT_VERSION(1) - -/** - * Encoder Session Creation parameters - */ -typedef struct _NV_ENC_OPEN_ENCODE_SESSIONEX_PARAMS -{ - uint32_t version; /**< [in]: Struct version. Must be set to ::NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER. */ - NV_ENC_DEVICE_TYPE deviceType; /**< [in]: Specified the device Type */ - void* device; /**< [in]: Pointer to client device. */ - void* reserved; /**< [in]: Reserved and must be set to 0. */ - uint32_t apiVersion; /**< [in]: API version. Should be set to NVENCAPI_VERSION. */ - uint32_t reserved1[253]; /**< [in]: Reserved and must be set to 0 */ - void* reserved2[64]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS; -/** Macro for constructing the version field of ::_NV_ENC_OPEN_ENCODE_SESSIONEX_PARAMS */ -#define NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER NVENCAPI_STRUCT_VERSION(1) - -/** @} */ /* END ENCODER_STRUCTURE */ - - -/** - * \addtogroup ENCODE_FUNC NvEncodeAPI Functions - * @{ - */ - -// NvEncOpenEncodeSession -/** - * \brief Opens an encoding session. - * - * Deprecated. - * - * \return - * ::NV_ENC_ERR_INVALID_CALL\n - * - */ -NVENCSTATUS NVENCAPI NvEncOpenEncodeSession (void* device, uint32_t deviceType, void** encoder); - -// NvEncGetEncodeGuidCount -/** - * \brief Retrieves the number of supported encode GUIDs. - * - * The function returns the number of codec guids supported by the NvEncodeAPI - * interface. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [out] encodeGUIDCount - * Number of supported encode GUIDs. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncGetEncodeGUIDCount (void* encoder, uint32_t* encodeGUIDCount); - - -// NvEncGetEncodeGUIDs -/** - * \brief Retrieves an array of supported encoder codec GUIDs. - * - * The function returns an array of codec guids supported by the NvEncodeAPI interface. - * The client must allocate an array where the NvEncodeAPI interface can - * fill the supported guids and pass the pointer in \p *GUIDs parameter. - * The size of the array can be determined by using ::NvEncGetEncodeGUIDCount() API. - * The Nvidia Encoding interface returns the number of codec guids it has actually - * filled in the guid array in the \p GUIDCount parameter. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] guidArraySize - * Number of GUIDs to retrieved. Should be set to the number retrieved using - * ::NvEncGetEncodeGUIDCount. - * \param [out] GUIDs - * Array of supported Encode GUIDs. - * \param [out] GUIDCount - * Number of supported Encode GUIDs. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncGetEncodeGUIDs (void* encoder, GUID* GUIDs, uint32_t guidArraySize, uint32_t* GUIDCount); - - -// NvEncGetEncodeProfileGuidCount -/** - * \brief Retrieves the number of supported profile GUIDs. - * - * The function returns the number of profile GUIDs supported for a given codec. - * The client must first enumerate the codec guids supported by the NvEncodeAPI - * interface. After determining the codec guid, it can query the NvEncodeAPI - * interface to determine the number of profile guids supported for a particular - * codec guid. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] encodeGUID - * The codec guid for which the profile guids are being enumerated. - * \param [out] encodeProfileGUIDCount - * Number of encode profiles supported for the given encodeGUID. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncGetEncodeProfileGUIDCount (void* encoder, GUID encodeGUID, uint32_t* encodeProfileGUIDCount); - - -// NvEncGetEncodeProfileGUIDs -/** - * \brief Retrieves an array of supported encode profile GUIDs. - * - * The function returns an array of supported profile guids for a particular - * codec guid. The client must allocate an array where the NvEncodeAPI interface - * can populate the profile guids. The client can determine the array size using - * ::NvEncGetEncodeProfileGUIDCount() API. The client must also validiate that the - * NvEncodeAPI interface supports the GUID the client wants to pass as \p encodeGUID - * parameter. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] encodeGUID - * The encode guid whose profile guids are being enumerated. - * \param [in] guidArraySize - * Number of GUIDs to be retrieved. Should be set to the number retrieved using - * ::NvEncGetEncodeProfileGUIDCount. - * \param [out] profileGUIDs - * Array of supported Encode Profile GUIDs - * \param [out] GUIDCount - * Number of valid encode profile GUIDs in \p profileGUIDs array. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncGetEncodeProfileGUIDs (void* encoder, GUID encodeGUID, GUID* profileGUIDs, uint32_t guidArraySize, uint32_t* GUIDCount); - -// NvEncGetInputFormatCount -/** - * \brief Retrieve the number of supported Input formats. - * - * The function returns the number of supported input formats. The client must - * query the NvEncodeAPI interface to determine the supported input formats - * before creating the input surfaces. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] encodeGUID - * Encode GUID, corresponding to which the number of supported input formats - * is to be retrieved. - * \param [out] inputFmtCount - * Number of input formats supported for specified Encode GUID. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_GENERIC \n - */ -NVENCSTATUS NVENCAPI NvEncGetInputFormatCount (void* encoder, GUID encodeGUID, uint32_t* inputFmtCount); - - -// NvEncGetInputFormats -/** - * \brief Retrieves an array of supported Input formats - * - * Returns an array of supported input formats The client must use the input - * format to create input surface using ::NvEncCreateInputBuffer() API. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] encodeGUID - * Encode GUID, corresponding to which the number of supported input formats - * is to be retrieved. - *\param [in] inputFmtArraySize - * Size input format count array passed in \p inputFmts. - *\param [out] inputFmts - * Array of input formats supported for this Encode GUID. - *\param [out] inputFmtCount - * The number of valid input format types returned by the NvEncodeAPI - * interface in \p inputFmts array. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncGetInputFormats (void* encoder, GUID encodeGUID, NV_ENC_BUFFER_FORMAT* inputFmts, uint32_t inputFmtArraySize, uint32_t* inputFmtCount); - - -// NvEncGetEncodeCaps -/** - * \brief Retrieves the capability value for a specified encoder attribute. - * - * The function returns the capability value for a given encoder attribute. The - * client must validate the encodeGUID using ::NvEncGetEncodeGUIDs() API before - * calling this function. The encoder attribute being queried are enumerated in - * ::NV_ENC_CAPS_PARAM enum. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] encodeGUID - * Encode GUID, corresponding to which the capability attribute is to be retrieved. - * \param [in] capsParam - * Used to specify attribute being queried. Refer ::NV_ENC_CAPS_PARAM for more - * details. - * \param [out] capsVal - * The value corresponding to the capability attribute being queried. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_GENERIC \n - */ -NVENCSTATUS NVENCAPI NvEncGetEncodeCaps (void* encoder, GUID encodeGUID, NV_ENC_CAPS_PARAM* capsParam, int* capsVal); - - -// NvEncGetEncodePresetCount -/** - * \brief Retrieves the number of supported preset GUIDs. - * - * The function returns the number of preset GUIDs available for a given codec. - * The client must validate the codec guid using ::NvEncGetEncodeGUIDs() API - * before calling this function. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] encodeGUID - * Encode GUID, corresponding to which the number of supported presets is to - * be retrieved. - * \param [out] encodePresetGUIDCount - * Receives the number of supported preset GUIDs. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncGetEncodePresetCount (void* encoder, GUID encodeGUID, uint32_t* encodePresetGUIDCount); - - -// NvEncGetEncodePresetGUIDs -/** - * \brief Receives an array of supported encoder preset GUIDs. - * - * The function returns an array of encode preset guids available for a given codec. - * The client can directly use one of the preset guids based upon the use case - * or target device. The preset guid chosen can be directly used in - * NV_ENC_INITIALIZE_PARAMS::presetGUID parameter to ::NvEncEncodePicture() API. - * Alternately client can also use the preset guid to retrieve the encoding config - * parameters being used by NvEncodeAPI interface for that given preset, using - * ::NvEncGetEncodePresetConfig() API. It can then modify preset config parameters - * as per its use case and send it to NvEncodeAPI interface as part of - * NV_ENC_INITIALIZE_PARAMS::encodeConfig parameter for NvEncInitializeEncoder() - * API. - * - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] encodeGUID - * Encode GUID, corresponding to which the list of supported presets is to be - * retrieved. - * \param [in] guidArraySize - * Size of array of preset guids passed in \p preset GUIDs - * \param [out] presetGUIDs - * Array of supported Encode preset GUIDs from the NvEncodeAPI interface - * to client. - * \param [out] encodePresetGUIDCount - * Receives the number of preset GUIDs returned by the NvEncodeAPI - * interface. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncGetEncodePresetGUIDs (void* encoder, GUID encodeGUID, GUID* presetGUIDs, uint32_t guidArraySize, uint32_t* encodePresetGUIDCount); - - -// NvEncGetEncodePresetConfig -/** - * \brief Returns a preset config structure supported for given preset GUID. - * - * The function returns a preset config structure for a given preset guid. Before - * using this function the client must enumerate the preset guids available for - * a given codec. The preset config structure can be modified by the client depending - * upon its use case and can be then used to initialize the encoder using - * ::NvEncInitializeEncoder() API. The client can use this function only if it - * wants to modify the NvEncodeAPI preset configuration, otherwise it can - * directly use the preset guid. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] encodeGUID - * Encode GUID, corresponding to which the list of supported presets is to be - * retrieved. - * \param [in] presetGUID - * Preset GUID, corresponding to which the Encoding configurations is to be - * retrieved. - * \param [out] presetConfig - * The requested Preset Encoder Attribute set. Refer ::_NV_ENC_CONFIG for -* more details. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncGetEncodePresetConfig (void* encoder, GUID encodeGUID, GUID presetGUID, NV_ENC_PRESET_CONFIG* presetConfig); - -// NvEncInitializeEncoder -/** - * \brief Initialize the encoder. - * - * This API must be used to initialize the encoder. The initialization parameter - * is passed using \p *createEncodeParams The client must send the following - * fields of the _NV_ENC_INITIALIZE_PARAMS structure with a valid value. - * - NV_ENC_INITIALIZE_PARAMS::encodeGUID - * - NV_ENC_INITIALIZE_PARAMS::encodeWidth - * - NV_ENC_INITIALIZE_PARAMS::encodeHeight - * - * The client can pass a preset guid directly to the NvEncodeAPI interface using - * NV_ENC_INITIALIZE_PARAMS::presetGUID field. If the client doesn't pass - * NV_ENC_INITIALIZE_PARAMS::encodeConfig structure, the codec specific parameters - * will be selected based on the preset guid. The preset guid must have been - * validated by the client using ::NvEncGetEncodePresetGUIDs() API. - * If the client passes a custom ::_NV_ENC_CONFIG structure through - * NV_ENC_INITIALIZE_PARAMS::encodeConfig , it will override the codec specific parameters - * based on the preset guid. It is recommended that even if the client passes a custom config, - * it should also send a preset guid. In this case, the preset guid passed by the client - * will not override any of the custom config parameters programmed by the client, - * it is only used as a hint by the NvEncodeAPI interface to determine certain encoder parameters - * which are not exposed to the client. - * - * There are two modes of operation for the encoder namely: - * - Asynchronous mode - * - Synchronous mode - * - * The client can select asynchronous or synchronous mode by setting the \p - * enableEncodeAsync field in ::_NV_ENC_INITIALIZE_PARAMS to 1 or 0 respectively. - *\par Asynchronous mode of operation: - * The Asynchronous mode can be enabled by setting NV_ENC_INITIALIZE_PARAMS::enableEncodeAsync to 1. - * The client operating in asynchronous mode must allocate completion event object - * for each output buffer and pass the completion event object in the - * ::NvEncEncodePicture() API. The client can create another thread and wait on - * the event object to be signalled by NvEncodeAPI interface on completion of the - * encoding process for the output frame. This should unblock the main thread from - * submitting work to the encoder. When the event is signalled the client can call - * NvEncodeAPI interfaces to copy the bitstream data using ::NvEncLockBitstream() - * API. This is the preferred mode of operation. - * - * NOTE: Asynchronous mode is not supported on Linux. - * - *\par Synchronous mode of operation: - * The client can select synchronous mode by setting NV_ENC_INITIALIZE_PARAMS::enableEncodeAsync to 0. - * The client working in synchronous mode can work in a single threaded or multi - * threaded mode. The client need not allocate any event objects. The client can - * only lock the bitstream data after NvEncodeAPI interface has returned - * ::NV_ENC_SUCCESS from encode picture. The NvEncodeAPI interface can return - * ::NV_ENC_ERR_NEED_MORE_INPUT error code from ::NvEncEncodePicture() API. The - * client must not lock the output buffer in such case but should send the next - * frame for encoding. The client must keep on calling ::NvEncEncodePicture() API - * until it returns ::NV_ENC_SUCCESS. \n - * The client must always lock the bitstream data in order in which it has submitted. - * This is true for both asynchronous and synchronous mode. - * - *\par Picture type decision: - * If the client is taking the picture type decision and it must disable the picture - * type decision module in NvEncodeAPI by setting NV_ENC_INITIALIZE_PARAMS::enablePTD - * to 0. In this case the client is required to send the picture in encoding - * order to NvEncodeAPI by doing the re-ordering for B frames. \n - * If the client doesn't want to take the picture type decision it can enable - * picture type decision module in the NvEncodeAPI interface by setting - * NV_ENC_INITIALIZE_PARAMS::enablePTD to 1 and send the input pictures in display - * order. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] createEncodeParams - * Refer ::_NV_ENC_INITIALIZE_PARAMS for details. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncInitializeEncoder (void* encoder, NV_ENC_INITIALIZE_PARAMS* createEncodeParams); - - -// NvEncCreateInputBuffer -/** - * \brief Allocates Input buffer. - * - * This function is used to allocate an input buffer. The client must enumerate - * the input buffer format before allocating the input buffer resources. The - * NV_ENC_INPUT_PTR returned by the NvEncodeAPI interface in the - * NV_ENC_CREATE_INPUT_BUFFER::inputBuffer field can be directly used in - * ::NvEncEncodePicture() API. The number of input buffers to be allocated by the - * client must be at least 4 more than the number of B frames being used for encoding. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in,out] createInputBufferParams - * Pointer to the ::NV_ENC_CREATE_INPUT_BUFFER structure. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncCreateInputBuffer (void* encoder, NV_ENC_CREATE_INPUT_BUFFER* createInputBufferParams); - - -// NvEncDestroyInputBuffer -/** - * \brief Release an input buffers. - * - * This function is used to free an input buffer. If the client has allocated - * any input buffer using ::NvEncCreateInputBuffer() API, it must free those - * input buffers by calling this function. The client must release the input - * buffers before destroying the encoder using ::NvEncDestroyEncoder() API. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] inputBuffer - * Pointer to the input buffer to be released. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncDestroyInputBuffer (void* encoder, NV_ENC_INPUT_PTR inputBuffer); - - -// NvEncCreateBitstreamBuffer -/** - * \brief Allocates an output bitstream buffer - * - * This function is used to allocate an output bitstream buffer and returns a - * NV_ENC_OUTPUT_PTR to bitstream buffer to the client in the - * NV_ENC_CREATE_BITSTREAM_BUFFER::bitstreamBuffer field. - * The client can only call this function after the encoder session has been - * initialized using ::NvEncInitializeEncoder() API. The minimum number of output - * buffers allocated by the client must be at least 4 more than the number of B - * B frames being used for encoding. The client can only access the output - * bitsteam data by locking the \p bitstreamBuffer using the ::NvEncLockBitstream() - * function. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in,out] createBitstreamBufferParams - * Pointer ::NV_ENC_CREATE_BITSTREAM_BUFFER for details. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncCreateBitstreamBuffer (void* encoder, NV_ENC_CREATE_BITSTREAM_BUFFER* createBitstreamBufferParams); - - -// NvEncDestroyBitstreamBuffer -/** - * \brief Release a bitstream buffer. - * - * This function is used to release the output bitstream buffer allocated using - * the ::NvEncCreateBitstreamBuffer() function. The client must release the output - * bitstreamBuffer using this function before destroying the encoder session. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] bitstreamBuffer - * Pointer to the bitstream buffer being released. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncDestroyBitstreamBuffer (void* encoder, NV_ENC_OUTPUT_PTR bitstreamBuffer); - -// NvEncEncodePicture -/** - * \brief Submit an input picture for encoding. - * - * This function is used to submit an input picture buffer for encoding. The - * encoding parameters are passed using \p *encodePicParams which is a pointer - * to the ::_NV_ENC_PIC_PARAMS structure. - * - * If the client has set NV_ENC_INITIALIZE_PARAMS::enablePTD to 0, then it must - * send a valid value for the following fields. - * - NV_ENC_PIC_PARAMS::pictureType - * - NV_ENC_PIC_PARAMS_H264::displayPOCSyntax (H264 only) - * - NV_ENC_PIC_PARAMS_H264::frameNumSyntax(H264 only) - * - NV_ENC_PIC_PARAMS_H264::refPicFlag(H264 only) - * - * - *\par Asynchronous Encoding - * If the client has enabled asynchronous mode of encoding by setting - * NV_ENC_INITIALIZE_PARAMS::enableEncodeAsync to 1 in the ::NvEncInitializeEncoder() - * API ,then the client must send a valid NV_ENC_PIC_PARAMS::completionEvent. - * Incase of asynchronous mode of operation, client can queue the ::NvEncEncodePicture() - * API commands from the main thread and then queue output buffers to be processed - * to a secondary worker thread. Before the locking the output buffers in the - * secondary thread , the client must wait on NV_ENC_PIC_PARAMS::completionEvent - * it has queued in ::NvEncEncodePicture() API call. The client must always process - * completion event and the output buffer in the same order in which they have been - * submitted for encoding. The NvEncodeAPI interface is responsible for any - * re-ordering required for B frames and will always ensure that encoded bitstream - * data is written in the same order in which output buffer is submitted. - *\code - The below example shows how asynchronous encoding in case of 1 B frames - ------------------------------------------------------------------------ - Suppose the client allocated 4 input buffers(I1,I2..), 4 output buffers(O1,O2..) - and 4 completion events(E1, E2, ...). The NvEncodeAPI interface will need to - keep a copy of the input buffers for re-ordering and it allocates following - internal buffers (NvI1, NvI2...). These internal buffers are managed by NvEncodeAPI - and the client is not responsible for the allocating or freeing the memory of - the internal buffers. - - a) The client main thread will queue the following encode frame calls. - Note the picture type is unknown to the client, the decision is being taken by - NvEncodeAPI interface. The client should pass ::_NV_ENC_PIC_PARAMS parameter - consisting of allocated input buffer, output buffer and output events in successive - ::NvEncEncodePicture() API calls along with other required encode picture params. - For example: - 1st EncodePicture parameters - (I1, O1, E1) - 2nd EncodePicture parameters - (I2, O2, E2) - 3rd EncodePicture parameters - (I3, O3, E3) - - b) NvEncodeAPI SW will receive the following encode Commands from the client. - The left side shows input from client in the form (Input buffer, Output Buffer, - Output Event). The right hand side shows a possible picture type decision take by - the NvEncodeAPI interface. - (I1, O1, E1) ---P1 Frame - (I2, O2, E2) ---B2 Frame - (I3, O3, E3) ---P3 Frame - - c) NvEncodeAPI interface will make a copy of the input buffers to its internal - buffersfor re-ordering. These copies are done as part of nvEncEncodePicture - function call from the client and NvEncodeAPI interface is responsible for - synchronization of copy operation with the actual encoding operation. - I1 --> NvI1 - I2 --> NvI2 - I3 --> NvI3 - - d) After returning from ::NvEncEncodePicture() call , the client must queue the output - bitstream processing work to the secondary thread. The output bitstream processing - for asynchronous mode consist of first waiting on completion event(E1, E2..) - and then locking the output bitstream buffer(O1, O2..) for reading the encoded - data. The work queued to the secondary thread by the client is in the following order - (I1, O1, E1) - (I2, O2, E2) - (I3, O3, E3) - Note they are in the same order in which client calls ::NvEncEncodePicture() API - in \p step a). - - e) NvEncodeAPI interface will do the re-ordering such that Encoder HW will receive - the following encode commands: - (NvI1, O1, E1) ---P1 Frame - (NvI3, O2, E2) ---P3 Frame - (NvI2, O3, E3) ---B2 frame - - f) After the encoding operations are completed, the events will be signalled - by NvEncodeAPI interface in the following order : - (O1, E1) ---P1 Frame ,output bitstream copied to O1 and event E1 signalled. - (O2, E2) ---P3 Frame ,output bitstream copied to O2 and event E2 signalled. - (O3, E3) ---B2 Frame ,output bitstream copied to O3 and event E3 signalled. - - g) The client must lock the bitstream data using ::NvEncLockBitstream() API in - the order O1,O2,O3 to read the encoded data, after waiting for the events - to be signalled in the same order i.e E1, E2 and E3.The output processing is - done in the secondary thread in the following order: - Waits on E1, copies encoded bitstream from O1 - Waits on E2, copies encoded bitstream from O2 - Waits on E3, copies encoded bitstream from O3 - - -Note the client will receive the events signalling and output buffer in the - same order in which they have submitted for encoding. - -Note the LockBitstream will have picture type field which will notify the - output picture type to the clients. - -Note the input, output buffer and the output completion event are free to be - reused once NvEncodeAPI interfaced has signalled the event and the client has - copied the data from the output buffer. - - * \endcode - * - *\par Synchronous Encoding - * The client can enable synchronous mode of encoding by setting - * NV_ENC_INITIALIZE_PARAMS::enableEncodeAsync to 0 in ::NvEncInitializeEncoder() API. - * The NvEncodeAPI interface may return ::NV_ENC_ERR_NEED_MORE_INPUT error code for - * some ::NvEncEncodePicture() API calls when NV_ENC_INITIALIZE_PARAMS::enablePTD - * is set to 1, but the client must not treat it as a fatal error. The NvEncodeAPI - * interface might not be able to submit an input picture buffer for encoding - * immediately due to re-ordering for B frames. The NvEncodeAPI interface cannot - * submit the input picture which is decided to be encoded as B frame as it waits - * for backward reference from temporally subsequent frames. This input picture - * is buffered internally and waits for more input picture to arrive. The client - * must not call ::NvEncLockBitstream() API on the output buffers whose - * ::NvEncEncodePicture() API returns ::NV_ENC_ERR_NEED_MORE_INPUT. The client must - * wait for the NvEncodeAPI interface to return ::NV_ENC_SUCCESS before locking the - * output bitstreams to read the encoded bitstream data. The following example - * explains the scenario with synchronous encoding with 2 B frames. - *\code - The below example shows how synchronous encoding works in case of 1 B frames - ----------------------------------------------------------------------------- - Suppose the client allocated 4 input buffers(I1,I2..), 4 output buffers(O1,O2..) - and 4 completion events(E1, E2, ...). The NvEncodeAPI interface will need to - keep a copy of the input buffers for re-ordering and it allocates following - internal buffers (NvI1, NvI2...). These internal buffers are managed by NvEncodeAPI - and the client is not responsible for the allocating or freeing the memory of - the internal buffers. - - The client calls ::NvEncEncodePicture() API with input buffer I1 and output buffer O1. - The NvEncodeAPI decides to encode I1 as P frame and submits it to encoder - HW and returns ::NV_ENC_SUCCESS. - The client can now read the encoded data by locking the output O1 by calling - NvEncLockBitstream API. - - The client calls ::NvEncEncodePicture() API with input buffer I2 and output buffer O2. - The NvEncodeAPI decides to encode I2 as B frame and buffers I2 by copying it - to internal buffer and returns ::NV_ENC_ERR_NEED_MORE_INPUT. - The error is not fatal and it notifies client that it cannot read the encoded - data by locking the output O2 by calling ::NvEncLockBitstream() API without submitting - more work to the NvEncodeAPI interface. - - The client calls ::NvEncEncodePicture() with input buffer I3 and output buffer O3. - The NvEncodeAPI decides to encode I3 as P frame and it first submits I3 for - encoding which will be used as backward reference frame for I2. - The NvEncodeAPI then submits I2 for encoding and returns ::NV_ENC_SUCESS. Both - the submission are part of the same ::NvEncEncodePicture() function call. - The client can now read the encoded data for both the frames by locking the output - O2 followed by O3 ,by calling ::NvEncLockBitstream() API. - - The client must always lock the output in the same order in which it has submitted - to receive the encoded bitstream in correct encoding order. - - * \endcode - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in,out] encodePicParams - * Pointer to the ::_NV_ENC_PIC_PARAMS structure. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_ENCODER_BUSY \n - * ::NV_ENC_ERR_NEED_MORE_INPUT \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncEncodePicture (void* encoder, NV_ENC_PIC_PARAMS* encodePicParams); - - -// NvEncLockBitstream -/** - * \brief Lock output bitstream buffer - * - * This function is used to lock the bitstream buffer to read the encoded data. - * The client can only access the encoded data by calling this function. - * The pointer to client accessible encoded data is returned in the - * NV_ENC_LOCK_BITSTREAM::bitstreamBufferPtr field. The size of the encoded data - * in the output buffer is returned in the NV_ENC_LOCK_BITSTREAM::bitstreamSizeInBytes - * The NvEncodeAPI interface also returns the output picture type and picture structure - * of the encoded frame in NV_ENC_LOCK_BITSTREAM::pictureType and - * NV_ENC_LOCK_BITSTREAM::pictureStruct fields respectively. If the client has - * set NV_ENC_LOCK_BITSTREAM::doNotWait to 1, the function might return - * ::NV_ENC_ERR_LOCK_BUSY if client is operating in synchronous mode. This is not - * a fatal failure if NV_ENC_LOCK_BITSTREAM::doNotWait is set to 1. In the above case the client can - * retry the function after few milliseconds. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in,out] lockBitstreamBufferParams - * Pointer to the ::_NV_ENC_LOCK_BITSTREAM structure. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_LOCK_BUSY \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncLockBitstream (void* encoder, NV_ENC_LOCK_BITSTREAM* lockBitstreamBufferParams); - - -// NvEncUnlockBitstream -/** - * \brief Unlock the output bitstream buffer - * - * This function is used to unlock the output bitstream buffer after the client - * has read the encoded data from output buffer. The client must call this function - * to unlock the output buffer which it has previously locked using ::NvEncLockBitstream() - * function. Using a locked bitstream buffer in ::NvEncEncodePicture() API will cause - * the function to fail. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in,out] bitstreamBuffer - * bitstream buffer pointer being unlocked - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncUnlockBitstream (void* encoder, NV_ENC_OUTPUT_PTR bitstreamBuffer); - - -// NvLockInputBuffer -/** - * \brief Locks an input buffer - * - * This function is used to lock the input buffer to load the uncompressed YUV - * pixel data into input buffer memory. The client must pass the NV_ENC_INPUT_PTR - * it had previously allocated using ::NvEncCreateInputBuffer()in the - * NV_ENC_LOCK_INPUT_BUFFER::inputBuffer field. - * The NvEncodeAPI interface returns pointer to client accessible input buffer - * memory in NV_ENC_LOCK_INPUT_BUFFER::bufferDataPtr field. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in,out] lockInputBufferParams - * Pointer to the ::_NV_ENC_LOCK_INPUT_BUFFER structure - * - * \return - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_LOCK_BUSY \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncLockInputBuffer (void* encoder, NV_ENC_LOCK_INPUT_BUFFER* lockInputBufferParams); - - -// NvUnlockInputBuffer -/** - * \brief Unlocks the input buffer - * - * This function is used to unlock the input buffer memory previously locked for - * uploading YUV pixel data. The input buffer must be unlocked before being used - * again for encoding, otherwise NvEncodeAPI will fail the ::NvEncEncodePicture() - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] inputBuffer - * Pointer to the input buffer that is being unlocked. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_GENERIC \n - * - * - */ -NVENCSTATUS NVENCAPI NvEncUnlockInputBuffer (void* encoder, NV_ENC_INPUT_PTR inputBuffer); - - -// NvEncGetEncodeStats -/** - * \brief Get encoding statistics. - * - * This function is used to retrieve the encoding statistics. - * This API is not supported when encode device type is CUDA. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in,out] encodeStats - * Pointer to the ::_NV_ENC_STAT structure. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncGetEncodeStats (void* encoder, NV_ENC_STAT* encodeStats); - - -// NvEncGetSequenceParams -/** - * \brief Get encoded sequence and picture header. - * - * This function can be used to retrieve the sequence and picture header out of - * band. The client must call this function only after the encoder has been - * initialized using ::NvEncInitializeEncoder() function. The client must - * allocate the memory where the NvEncodeAPI interface can copy the bitstream - * header and pass the pointer to the memory in NV_ENC_SEQUENCE_PARAM_PAYLOAD::spsppsBuffer. - * The size of buffer is passed in the field NV_ENC_SEQUENCE_PARAM_PAYLOAD::inBufferSize. - * The NvEncodeAPI interface will copy the bitstream header payload and returns - * the actual size of the bitstream header in the field - * NV_ENC_SEQUENCE_PARAM_PAYLOAD::outSPSPPSPayloadSize. - * The client must call ::NvEncGetSequenceParams() function from the same thread which is - * being used to call ::NvEncEncodePicture() function. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in,out] sequenceParamPayload - * Pointer to the ::_NV_ENC_SEQUENCE_PARAM_PAYLOAD structure. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncGetSequenceParams (void* encoder, NV_ENC_SEQUENCE_PARAM_PAYLOAD* sequenceParamPayload); - - -// NvEncRegisterAsyncEvent -/** - * \brief Register event for notification to encoding completion. - * - * This function is used to register the completion event with NvEncodeAPI - * interface. The event is required when the client has configured the encoder to - * work in asynchronous mode. In this mode the client needs to send a completion - * event with every output buffer. The NvEncodeAPI interface will signal the - * completion of the encoding process using this event. Only after the event is - * signalled the client can get the encoded data using ::NvEncLockBitstream() function. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] eventParams - * Pointer to the ::_NV_ENC_EVENT_PARAMS structure. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncRegisterAsyncEvent (void* encoder, NV_ENC_EVENT_PARAMS* eventParams); - - -// NvEncUnregisterAsyncEvent -/** - * \brief Unregister completion event. - * - * This function is used to unregister completion event which has been previously - * registered using ::NvEncRegisterAsyncEvent() function. The client must unregister - * all events before destroying the encoder using ::NvEncDestroyEncoder() function. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] eventParams - * Pointer to the ::_NV_ENC_EVENT_PARAMS structure. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncUnregisterAsyncEvent (void* encoder, NV_ENC_EVENT_PARAMS* eventParams); - - -// NvEncMapInputResource -/** - * \brief Map an externally created input resource pointer for encoding. - * - * Maps an externally allocated input resource [using and returns a NV_ENC_INPUT_PTR - * which can be used for encoding in the ::NvEncEncodePicture() function. The - * mapped resource is returned in the field NV_ENC_MAP_INPUT_RESOURCE::outputResourcePtr. - * The NvEncodeAPI interface also returns the buffer format of the mapped resource - * in the field NV_ENC_MAP_INPUT_RESOURCE::outbufferFmt. - * This function provides synchronization guarantee that any graphics or compute - * work submitted on the input buffer is completed before the buffer is used for encoding. - * The client should not access any input buffer while they are mapped by the encoder. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in,out] mapInputResParams - * Pointer to the ::_NV_ENC_MAP_INPUT_RESOURCE structure. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_RESOURCE_NOT_REGISTERED \n - * ::NV_ENC_ERR_MAP_FAILED \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncMapInputResource (void* encoder, NV_ENC_MAP_INPUT_RESOURCE* mapInputResParams); - - -// NvEncUnmapInputResource -/** - * \brief UnMaps a NV_ENC_INPUT_PTR which was mapped for encoding - * - * - * UnMaps an input buffer which was previously mapped using ::NvEncMapInputResource() - * API. The mapping created using ::NvEncMapInputResource() should be invalidated - * using this API before the external resource is destroyed by the client. The client - * must unmap the buffer after ::NvEncLockBitstream() API returns succuessfully for encode - * work submitted using the mapped input buffer. - * - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] mappedInputBuffer - * Pointer to the NV_ENC_INPUT_PTR - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_RESOURCE_NOT_REGISTERED \n - * ::NV_ENC_ERR_RESOURCE_NOT_MAPPED \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncUnmapInputResource (void* encoder, NV_ENC_INPUT_PTR mappedInputBuffer); - -// NvEncDestroyEncoder -/** - * \brief Destroy Encoding Session - * - * Destroys the encoder session previously created using ::NvEncOpenEncodeSession() - * function. The client must flush the encoder before freeing any resources. In order - * to flush the encoder the client must pass a NULL encode picture packet and either - * wait for the ::NvEncEncodePicture() function to return in synchronous mode or wait - * for the flush event to be signaled by the encoder in asynchronous mode. - * The client must free all the input and output resources created using the - * NvEncodeAPI interface before destroying the encoder. If the client is operating - * in asynchronous mode, it must also unregister the completion events previously - * registered. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncDestroyEncoder (void* encoder); - -// NvEncInvalidateRefFrames -/** - * \brief Invalidate reference frames - * - * Invalidates reference frame based on the time stamp provided by the client. - * The encoder marks any reference frames or any frames which have been reconstructed - * using the corrupt frame as invalid for motion estimation and uses older reference - * frames for motion estimation. The encoded forces the current frame to be encoded - * as an intra frame if no reference frames are left after invalidation process. - * This is useful for low latency application for error resiliency. The client - * is recommended to set NV_ENC_CONFIG_H264::maxNumRefFrames to a large value so - * that encoder can keep a backup of older reference frames in the DPB and can use them - * for motion estimation when the newer reference frames have been invalidated. - * This API can be called multiple times. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] invalidRefFrameTimeStamp - * Timestamp of the invalid reference frames which needs to be invalidated. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncInvalidateRefFrames(void* encoder, uint64_t invalidRefFrameTimeStamp); - -// NvEncOpenEncodeSessionEx -/** - * \brief Opens an encoding session. - * - * Opens an encoding session and returns a pointer to the encoder interface in - * the \p **encoder parameter. The client should start encoding process by calling - * this API first. - * The client must pass a pointer to IDirect3DDevice9 device or CUDA context in the \p *device parameter. - * For the OpenGL interface, \p device must be NULL. An OpenGL context must be current when - * calling all NvEncodeAPI functions. - * If the creation of encoder session fails, the client must call ::NvEncDestroyEncoder API - * before exiting. - * - * \param [in] openSessionExParams - * Pointer to a ::NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS structure. - * \param [out] encoder - * Encode Session pointer to the NvEncodeAPI interface. - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_NO_ENCODE_DEVICE \n - * ::NV_ENC_ERR_UNSUPPORTED_DEVICE \n - * ::NV_ENC_ERR_INVALID_DEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncOpenEncodeSessionEx (NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS *openSessionExParams, void** encoder); - -// NvEncRegisterResource -/** - * \brief Registers a resource with the Nvidia Video Encoder Interface. - * - * Registers a resource with the Nvidia Video Encoder Interface for book keeping. - * The client is expected to pass the registered resource handle as well, while calling ::NvEncMapInputResource API. - * - * \param [in] encoder - * Pointer to the NVEncodeAPI interface. - * - * \param [in] registerResParams - * Pointer to a ::_NV_ENC_REGISTER_RESOURCE structure - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_RESOURCE_REGISTER_FAILED \n - * ::NV_ENC_ERR_GENERIC \n - * ::NV_ENC_ERR_UNIMPLEMENTED \n - * - */ -NVENCSTATUS NVENCAPI NvEncRegisterResource (void* encoder, NV_ENC_REGISTER_RESOURCE* registerResParams); - -// NvEncUnregisterResource -/** - * \brief Unregisters a resource previously registered with the Nvidia Video Encoder Interface. - * - * Unregisters a resource previously registered with the Nvidia Video Encoder Interface. - * The client is expected to unregister any resource that it has registered with the - * Nvidia Video Encoder Interface before destroying the resource. - * - * \param [in] encoder - * Pointer to the NVEncodeAPI interface. - * - * \param [in] registeredResource - * The registered resource pointer that was returned in ::NvEncRegisterResource. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_RESOURCE_NOT_REGISTERED \n - * ::NV_ENC_ERR_GENERIC \n - * ::NV_ENC_ERR_UNIMPLEMENTED \n - * - */ -NVENCSTATUS NVENCAPI NvEncUnregisterResource (void* encoder, NV_ENC_REGISTERED_PTR registeredResource); - -// NvEncReconfigureEncoder -/** - * \brief Reconfigure an existing encoding session. - * - * Reconfigure an existing encoding session. - * The client should call this API to change/reconfigure the parameter passed during - * NvEncInitializeEncoder API call. - * Currently Reconfiguration of following are not supported. - * Change in GOP structure. - * Change in sync-Async mode. - * Change in MaxWidth & MaxHeight. - * Change in PTDmode. - * - * Resolution change is possible only if maxEncodeWidth & maxEncodeHeight of NV_ENC_INITIALIZE_PARAMS - * is set while creating encoder session. - * - * \param [in] encoder - * Pointer to the NVEncodeAPI interface. - * - * \param [in] reInitEncodeParams - * Pointer to a ::NV_ENC_RECONFIGURE_PARAMS structure. - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_NO_ENCODE_DEVICE \n - * ::NV_ENC_ERR_UNSUPPORTED_DEVICE \n - * ::NV_ENC_ERR_INVALID_DEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_GENERIC \n - * - */ -NVENCSTATUS NVENCAPI NvEncReconfigureEncoder (void *encoder, NV_ENC_RECONFIGURE_PARAMS* reInitEncodeParams); - - - -// NvEncCreateMVBuffer -/** - * \brief Allocates output MV buffer for ME only mode. - * - * This function is used to allocate an output MV buffer. The size of the mvBuffer is - * dependent on the frame height and width of the last ::NvEncCreateInputBuffer() call. - * The NV_ENC_OUTPUT_PTR returned by the NvEncodeAPI interface in the - * ::NV_ENC_CREATE_MV_BUFFER::mvBuffer field should be used in - * ::NvEncRunMotionEstimationOnly() API. - * Client must lock ::NV_ENC_CREATE_MV_BUFFER::mvBuffer using ::NvEncLockBitstream() API to get the motion vector data. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in,out] createMVBufferParams - * Pointer to the ::NV_ENC_CREATE_MV_BUFFER structure. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_GENERIC \n - */ -NVENCSTATUS NVENCAPI NvEncCreateMVBuffer (void* encoder, NV_ENC_CREATE_MV_BUFFER* createMVBufferParams); - - -// NvEncDestroyMVBuffer -/** - * \brief Release an output MV buffer for ME only mode. - * - * This function is used to release the output MV buffer allocated using - * the ::NvEncCreateMVBuffer() function. The client must release the output - * mvBuffer using this function before destroying the encoder session. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] mvBuffer - * Pointer to the mvBuffer being released. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_GENERIC \n - */ -NVENCSTATUS NVENCAPI NvEncDestroyMVBuffer (void* encoder, NV_ENC_OUTPUT_PTR mvBuffer); - - -// NvEncRunMotionEstimationOnly -/** - * \brief Submit an input picture and reference frame for motion estimation in ME only mode. - * - * This function is used to submit the input frame and reference frame for motion - * estimation. The ME parameters are passed using *meOnlyParams which is a pointer - * to ::_NV_ENC_MEONLY_PARAMS structure. - * Client must lock ::NV_ENC_CREATE_MV_BUFFER::mvBuffer using ::NvEncLockBitstream() API to get the motion vector data. - * to get motion vector data. - * - * \param [in] encoder - * Pointer to the NvEncodeAPI interface. - * \param [in] meOnlyParams - * Pointer to the ::_NV_ENC_MEONLY_PARAMS structure. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - * ::NV_ENC_ERR_INVALID_ENCODERDEVICE \n - * ::NV_ENC_ERR_DEVICE_NOT_EXIST \n - * ::NV_ENC_ERR_UNSUPPORTED_PARAM \n - * ::NV_ENC_ERR_OUT_OF_MEMORY \n - * ::NV_ENC_ERR_INVALID_PARAM \n - * ::NV_ENC_ERR_INVALID_VERSION \n - * ::NV_ENC_ERR_NEED_MORE_INPUT \n - * ::NV_ENC_ERR_ENCODER_NOT_INITIALIZED \n - * ::NV_ENC_ERR_GENERIC \n - */ -NVENCSTATUS NVENCAPI NvEncRunMotionEstimationOnly (void* encoder, NV_ENC_MEONLY_PARAMS* meOnlyParams); - -// NvEncodeAPIGetMaxSupportedVersion -/** - * \brief Get the largest NvEncodeAPI version supported by the driver. - * - * This function can be used by clients to determine if the driver supports - * the NvEncodeAPI header the application was compiled with. - * - * \param [out] version - * Pointer to the requested value. The 4 least significant bits in the returned - * indicate the minor version and the rest of the bits indicate the major - * version of the largest supported version. - * - * \return - * ::NV_ENC_SUCCESS \n - * ::NV_ENC_ERR_INVALID_PTR \n - */ -NVENCSTATUS NVENCAPI NvEncodeAPIGetMaxSupportedVersion (uint32_t* version); - - -/// \cond API PFN -/* - * Defines API function pointers - */ -typedef NVENCSTATUS (NVENCAPI* PNVENCOPENENCODESESSION) (void* device, uint32_t deviceType, void** encoder); -typedef NVENCSTATUS (NVENCAPI* PNVENCGETENCODEGUIDCOUNT) (void* encoder, uint32_t* encodeGUIDCount); -typedef NVENCSTATUS (NVENCAPI* PNVENCGETENCODEGUIDS) (void* encoder, GUID* GUIDs, uint32_t guidArraySize, uint32_t* GUIDCount); -typedef NVENCSTATUS (NVENCAPI* PNVENCGETENCODEPROFILEGUIDCOUNT) (void* encoder, GUID encodeGUID, uint32_t* encodeProfileGUIDCount); -typedef NVENCSTATUS (NVENCAPI* PNVENCGETENCODEPROFILEGUIDS) (void* encoder, GUID encodeGUID, GUID* profileGUIDs, uint32_t guidArraySize, uint32_t* GUIDCount); -typedef NVENCSTATUS (NVENCAPI* PNVENCGETINPUTFORMATCOUNT) (void* encoder, GUID encodeGUID, uint32_t* inputFmtCount); -typedef NVENCSTATUS (NVENCAPI* PNVENCGETINPUTFORMATS) (void* encoder, GUID encodeGUID, NV_ENC_BUFFER_FORMAT* inputFmts, uint32_t inputFmtArraySize, uint32_t* inputFmtCount); -typedef NVENCSTATUS (NVENCAPI* PNVENCGETENCODECAPS) (void* encoder, GUID encodeGUID, NV_ENC_CAPS_PARAM* capsParam, int* capsVal); -typedef NVENCSTATUS (NVENCAPI* PNVENCGETENCODEPRESETCOUNT) (void* encoder, GUID encodeGUID, uint32_t* encodePresetGUIDCount); -typedef NVENCSTATUS (NVENCAPI* PNVENCGETENCODEPRESETGUIDS) (void* encoder, GUID encodeGUID, GUID* presetGUIDs, uint32_t guidArraySize, uint32_t* encodePresetGUIDCount); -typedef NVENCSTATUS (NVENCAPI* PNVENCGETENCODEPRESETCONFIG) (void* encoder, GUID encodeGUID, GUID presetGUID, NV_ENC_PRESET_CONFIG* presetConfig); -typedef NVENCSTATUS (NVENCAPI* PNVENCINITIALIZEENCODER) (void* encoder, NV_ENC_INITIALIZE_PARAMS* createEncodeParams); -typedef NVENCSTATUS (NVENCAPI* PNVENCCREATEINPUTBUFFER) (void* encoder, NV_ENC_CREATE_INPUT_BUFFER* createInputBufferParams); -typedef NVENCSTATUS (NVENCAPI* PNVENCDESTROYINPUTBUFFER) (void* encoder, NV_ENC_INPUT_PTR inputBuffer); -typedef NVENCSTATUS (NVENCAPI* PNVENCCREATEBITSTREAMBUFFER) (void* encoder, NV_ENC_CREATE_BITSTREAM_BUFFER* createBitstreamBufferParams); -typedef NVENCSTATUS (NVENCAPI* PNVENCDESTROYBITSTREAMBUFFER) (void* encoder, NV_ENC_OUTPUT_PTR bitstreamBuffer); -typedef NVENCSTATUS (NVENCAPI* PNVENCENCODEPICTURE) (void* encoder, NV_ENC_PIC_PARAMS* encodePicParams); -typedef NVENCSTATUS (NVENCAPI* PNVENCLOCKBITSTREAM) (void* encoder, NV_ENC_LOCK_BITSTREAM* lockBitstreamBufferParams); -typedef NVENCSTATUS (NVENCAPI* PNVENCUNLOCKBITSTREAM) (void* encoder, NV_ENC_OUTPUT_PTR bitstreamBuffer); -typedef NVENCSTATUS (NVENCAPI* PNVENCLOCKINPUTBUFFER) (void* encoder, NV_ENC_LOCK_INPUT_BUFFER* lockInputBufferParams); -typedef NVENCSTATUS (NVENCAPI* PNVENCUNLOCKINPUTBUFFER) (void* encoder, NV_ENC_INPUT_PTR inputBuffer); -typedef NVENCSTATUS (NVENCAPI* PNVENCGETENCODESTATS) (void* encoder, NV_ENC_STAT* encodeStats); -typedef NVENCSTATUS (NVENCAPI* PNVENCGETSEQUENCEPARAMS) (void* encoder, NV_ENC_SEQUENCE_PARAM_PAYLOAD* sequenceParamPayload); -typedef NVENCSTATUS (NVENCAPI* PNVENCREGISTERASYNCEVENT) (void* encoder, NV_ENC_EVENT_PARAMS* eventParams); -typedef NVENCSTATUS (NVENCAPI* PNVENCUNREGISTERASYNCEVENT) (void* encoder, NV_ENC_EVENT_PARAMS* eventParams); -typedef NVENCSTATUS (NVENCAPI* PNVENCMAPINPUTRESOURCE) (void* encoder, NV_ENC_MAP_INPUT_RESOURCE* mapInputResParams); -typedef NVENCSTATUS (NVENCAPI* PNVENCUNMAPINPUTRESOURCE) (void* encoder, NV_ENC_INPUT_PTR mappedInputBuffer); -typedef NVENCSTATUS (NVENCAPI* PNVENCDESTROYENCODER) (void* encoder); -typedef NVENCSTATUS (NVENCAPI* PNVENCINVALIDATEREFFRAMES) (void* encoder, uint64_t invalidRefFrameTimeStamp); -typedef NVENCSTATUS (NVENCAPI* PNVENCOPENENCODESESSIONEX) (NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS *openSessionExParams, void** encoder); -typedef NVENCSTATUS (NVENCAPI* PNVENCREGISTERRESOURCE) (void* encoder, NV_ENC_REGISTER_RESOURCE* registerResParams); -typedef NVENCSTATUS (NVENCAPI* PNVENCUNREGISTERRESOURCE) (void* encoder, NV_ENC_REGISTERED_PTR registeredRes); -typedef NVENCSTATUS (NVENCAPI* PNVENCRECONFIGUREENCODER) (void* encoder, NV_ENC_RECONFIGURE_PARAMS* reInitEncodeParams); - -typedef NVENCSTATUS (NVENCAPI* PNVENCCREATEMVBUFFER) (void* encoder, NV_ENC_CREATE_MV_BUFFER* createMVBufferParams); -typedef NVENCSTATUS (NVENCAPI* PNVENCDESTROYMVBUFFER) (void* encoder, NV_ENC_OUTPUT_PTR mvBuffer); -typedef NVENCSTATUS (NVENCAPI* PNVENCRUNMOTIONESTIMATIONONLY) (void* encoder, NV_ENC_MEONLY_PARAMS* meOnlyParams); - - -/// \endcond - - -/** @} */ /* END ENCODE_FUNC */ - -/** - * \ingroup ENCODER_STRUCTURE - * NV_ENCODE_API_FUNCTION_LIST - */ -typedef struct _NV_ENCODE_API_FUNCTION_LIST -{ - uint32_t version; /**< [in]: Client should pass NV_ENCODE_API_FUNCTION_LIST_VER. */ - uint32_t reserved; /**< [in]: Reserved and should be set to 0. */ - PNVENCOPENENCODESESSION nvEncOpenEncodeSession; /**< [out]: Client should access ::NvEncOpenEncodeSession() API through this pointer. */ - PNVENCGETENCODEGUIDCOUNT nvEncGetEncodeGUIDCount; /**< [out]: Client should access ::NvEncGetEncodeGUIDCount() API through this pointer. */ - PNVENCGETENCODEPRESETCOUNT nvEncGetEncodeProfileGUIDCount; /**< [out]: Client should access ::NvEncGetEncodeProfileGUIDCount() API through this pointer.*/ - PNVENCGETENCODEPRESETGUIDS nvEncGetEncodeProfileGUIDs; /**< [out]: Client should access ::NvEncGetEncodeProfileGUIDs() API through this pointer. */ - PNVENCGETENCODEGUIDS nvEncGetEncodeGUIDs; /**< [out]: Client should access ::NvEncGetEncodeGUIDs() API through this pointer. */ - PNVENCGETINPUTFORMATCOUNT nvEncGetInputFormatCount; /**< [out]: Client should access ::NvEncGetInputFormatCount() API through this pointer. */ - PNVENCGETINPUTFORMATS nvEncGetInputFormats; /**< [out]: Client should access ::NvEncGetInputFormats() API through this pointer. */ - PNVENCGETENCODECAPS nvEncGetEncodeCaps; /**< [out]: Client should access ::NvEncGetEncodeCaps() API through this pointer. */ - PNVENCGETENCODEPRESETCOUNT nvEncGetEncodePresetCount; /**< [out]: Client should access ::NvEncGetEncodePresetCount() API through this pointer. */ - PNVENCGETENCODEPRESETGUIDS nvEncGetEncodePresetGUIDs; /**< [out]: Client should access ::NvEncGetEncodePresetGUIDs() API through this pointer. */ - PNVENCGETENCODEPRESETCONFIG nvEncGetEncodePresetConfig; /**< [out]: Client should access ::NvEncGetEncodePresetConfig() API through this pointer. */ - PNVENCINITIALIZEENCODER nvEncInitializeEncoder; /**< [out]: Client should access ::NvEncInitializeEncoder() API through this pointer. */ - PNVENCCREATEINPUTBUFFER nvEncCreateInputBuffer; /**< [out]: Client should access ::NvEncCreateInputBuffer() API through this pointer. */ - PNVENCDESTROYINPUTBUFFER nvEncDestroyInputBuffer; /**< [out]: Client should access ::NvEncDestroyInputBuffer() API through this pointer. */ - PNVENCCREATEBITSTREAMBUFFER nvEncCreateBitstreamBuffer; /**< [out]: Client should access ::NvEncCreateBitstreamBuffer() API through this pointer. */ - PNVENCDESTROYBITSTREAMBUFFER nvEncDestroyBitstreamBuffer; /**< [out]: Client should access ::NvEncDestroyBitstreamBuffer() API through this pointer. */ - PNVENCENCODEPICTURE nvEncEncodePicture; /**< [out]: Client should access ::NvEncEncodePicture() API through this pointer. */ - PNVENCLOCKBITSTREAM nvEncLockBitstream; /**< [out]: Client should access ::NvEncLockBitstream() API through this pointer. */ - PNVENCUNLOCKBITSTREAM nvEncUnlockBitstream; /**< [out]: Client should access ::NvEncUnlockBitstream() API through this pointer. */ - PNVENCLOCKINPUTBUFFER nvEncLockInputBuffer; /**< [out]: Client should access ::NvEncLockInputBuffer() API through this pointer. */ - PNVENCUNLOCKINPUTBUFFER nvEncUnlockInputBuffer; /**< [out]: Client should access ::NvEncUnlockInputBuffer() API through this pointer. */ - PNVENCGETENCODESTATS nvEncGetEncodeStats; /**< [out]: Client should access ::NvEncGetEncodeStats() API through this pointer. */ - PNVENCGETSEQUENCEPARAMS nvEncGetSequenceParams; /**< [out]: Client should access ::NvEncGetSequenceParams() API through this pointer. */ - PNVENCREGISTERASYNCEVENT nvEncRegisterAsyncEvent; /**< [out]: Client should access ::NvEncRegisterAsyncEvent() API through this pointer. */ - PNVENCUNREGISTERASYNCEVENT nvEncUnregisterAsyncEvent; /**< [out]: Client should access ::NvEncUnregisterAsyncEvent() API through this pointer. */ - PNVENCMAPINPUTRESOURCE nvEncMapInputResource; /**< [out]: Client should access ::NvEncMapInputResource() API through this pointer. */ - PNVENCUNMAPINPUTRESOURCE nvEncUnmapInputResource; /**< [out]: Client should access ::NvEncUnmapInputResource() API through this pointer. */ - PNVENCDESTROYENCODER nvEncDestroyEncoder; /**< [out]: Client should access ::NvEncDestroyEncoder() API through this pointer. */ - PNVENCINVALIDATEREFFRAMES nvEncInvalidateRefFrames; /**< [out]: Client should access ::NvEncInvalidateRefFrames() API through this pointer. */ - PNVENCOPENENCODESESSIONEX nvEncOpenEncodeSessionEx; /**< [out]: Client should access ::NvEncOpenEncodeSession() API through this pointer. */ - PNVENCREGISTERRESOURCE nvEncRegisterResource; /**< [out]: Client should access ::NvEncRegisterResource() API through this pointer. */ - PNVENCUNREGISTERRESOURCE nvEncUnregisterResource; /**< [out]: Client should access ::NvEncUnregisterResource() API through this pointer. */ - PNVENCRECONFIGUREENCODER nvEncReconfigureEncoder; /**< [out]: Client should access ::NvEncReconfigureEncoder() API through this pointer. */ - void* reserved1; - PNVENCCREATEMVBUFFER nvEncCreateMVBuffer; /**< [out]: Client should access ::NvEncCreateMVBuffer API through this pointer. */ - PNVENCDESTROYMVBUFFER nvEncDestroyMVBuffer; /**< [out]: Client should access ::NvEncDestroyMVBuffer API through this pointer. */ - PNVENCRUNMOTIONESTIMATIONONLY nvEncRunMotionEstimationOnly; /**< [out]: Client should access ::NvEncRunMotionEstimationOnly API through this pointer. */ - void* reserved2[281]; /**< [in]: Reserved and must be set to NULL */ -} NV_ENCODE_API_FUNCTION_LIST; - -/** Macro for constructing the version field of ::_NV_ENCODEAPI_FUNCTION_LIST. */ -#define NV_ENCODE_API_FUNCTION_LIST_VER NVENCAPI_STRUCT_VERSION(2) - -// NvEncodeAPICreateInstance -/** - * \ingroup ENCODE_FUNC - * Entry Point to the NvEncodeAPI interface. - * - * Creates an instance of the NvEncodeAPI interface, and populates the - * pFunctionList with function pointers to the API routines implemented by the - * NvEncodeAPI interface. - * - * \param [out] functionList - * - * \return - * ::NV_ENC_SUCCESS - * ::NV_ENC_ERR_INVALID_PTR - */ -NVENCSTATUS NVENCAPI NvEncodeAPICreateInstance(NV_ENCODE_API_FUNCTION_LIST *functionList); - -#ifdef __cplusplus -} -#endif - - -#endif - diff --git a/configure b/configure index 6916b4549ae9a..fe81ba31b5ed7 100755 --- a/configure +++ b/configure @@ -5811,6 +5811,9 @@ check_type "va/va.h va/va_enc_vp9.h" "VAEncPictureParameterBufferVP9" check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC" +check_pkg_config cuda "ffnvcodec >= 8.0.14.1" \ + "ffnvcodec/nvEncodeAPI.h ffnvcodec/dynlink_cuda.h ffnvcodec/dynlink_cuviddec.h ffnvcodec/dynlink_nvcuvid.h" "" + check_cpp_condition windows.h "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)" && enable winrt || disable winrt if ! disabled w32threads && ! enabled pthreads; then @@ -6263,7 +6266,7 @@ fi enabled nvenc && check_cc -I$source_path < NV_ENCODE_API_FUNCTION_LIST flist; void f(void) { struct { const GUID guid; } s[] = { { NV_ENC_PRESET_HQ_GUID } }; } int main(void) { return 0; } diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index ab6825f633a31..bff25dfc3ca12 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -28,7 +28,7 @@ typedef void ID3D11Device; #endif -#include "compat/nvenc/nvEncodeAPI.h" +#include #include "compat/cuda/dynlink_loader.h" #include "libavutil/fifo.h" diff --git a/tests/ref/fate/source b/tests/ref/fate/source index 2def03495beec..809c4632d4ffd 100644 --- a/tests/ref/fate/source +++ b/tests/ref/fate/source @@ -23,12 +23,8 @@ compat/avisynth/avs/types.h compat/avisynth/avxsynth_c.h compat/avisynth/windowsPorts/basicDataTypeConversions.h compat/avisynth/windowsPorts/windows2linux.h -compat/cuda/dynlink_cuda.h -compat/cuda/dynlink_cuviddec.h compat/cuda/dynlink_loader.h -compat/cuda/dynlink_nvcuvid.h compat/float/float.h compat/float/limits.h -compat/nvenc/nvEncodeAPI.h Use of av_clip() where av_clip_uintp2() could be used: Use of av_clip() where av_clip_intp2() could be used: From 090c0abff9c8b27304614f15d9464dbf4ea59833 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 26 Feb 2018 21:17:08 +0100 Subject: [PATCH 1978/2557] avcodec/bintext: sanity check dimensions Fixes: Timeout Fixes: 6277/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_XBIN_fuzzer-6047202288861184 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/bintext.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/bintext.c b/libavcodec/bintext.c index 90bbe67b59b69..d967317671b89 100644 --- a/libavcodec/bintext.c +++ b/libavcodec/bintext.c @@ -35,6 +35,8 @@ #include "bintext.h" #include "internal.h" +#define FONT_WIDTH 8 + typedef struct XbinContext { AVFrame *frame; int palette[16]; @@ -91,6 +93,9 @@ static av_cold int decode_init(AVCodecContext *avctx) break; } } + if (avctx->width < FONT_WIDTH || avctx->height < s->font_height) + return AVERROR_INVALIDDATA; + s->frame = av_frame_alloc(); if (!s->frame) @@ -113,8 +118,6 @@ av_unused static void hscroll(AVCodecContext *avctx) } } -#define FONT_WIDTH 8 - /** * Draw character to screen */ From 49062a90174b6e4104876c0257dc673a0da854ca Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 21 Feb 2018 04:29:44 +0100 Subject: [PATCH 1979/2557] avcodec/exr: fix invalid shift in unpack_14() Fixes: 6154/clusterfuzz-testcase-minimized-5762231061970944 Fixes: runtime error: shift exponent 63 is too large for 32-bit type 'int' Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/exr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 444af17778e99..5253cc3f136c7 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -899,7 +899,7 @@ static int pxr24_uncompress(EXRContext *s, const uint8_t *src, static void unpack_14(const uint8_t b[14], uint16_t s[16]) { - unsigned short shift = (b[ 2] >> 2); + unsigned short shift = (b[ 2] >> 2) & 15; unsigned short bias = (0x20 << shift); int i; From 3981fb8d2a03cdb3399590da8621a7bcc22e2964 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 22 Feb 2018 02:34:05 +0100 Subject: [PATCH 1980/2557] avcodec/g2meet: Check tile dimensions with av_image_check_size2() Fixes: OOM Fixes: 6216/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_G2M_fuzzer-4983807968018432 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/g2meet.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index 842095ba3b40d..a46157218f23b 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -28,6 +28,7 @@ #include #include +#include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" @@ -1451,7 +1452,8 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, c->tile_height = bytestream2_get_be32(&bc); if (c->tile_width <= 0 || c->tile_height <= 0 || ((c->tile_width | c->tile_height) & 0xF) || - c->tile_width * (uint64_t)c->tile_height >= INT_MAX / 4 + c->tile_width * (uint64_t)c->tile_height >= INT_MAX / 4 || + av_image_check_size2(c->tile_width, c->tile_height, avctx->max_pixels, avctx->pix_fmt, 0, avctx) < 0 ) { av_log(avctx, AV_LOG_ERROR, "Invalid tile dimensions %dx%d\n", From 8b5c29b6c2ab00f8fb545475238a99f575b5d81d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 22 Feb 2018 03:04:40 +0100 Subject: [PATCH 1981/2557] avcodec/truemotion2rt: Check input buffer size Fixes: Timeout Fixes: 6250/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TRUEMOTION2RT_fuzzer-5479814011027456 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/truemotion2rt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/truemotion2rt.c b/libavcodec/truemotion2rt.c index d63918742dbe1..9df0b527bbdfb 100644 --- a/libavcodec/truemotion2rt.c +++ b/libavcodec/truemotion2rt.c @@ -116,6 +116,9 @@ static int truemotion2rt_decode_frame(AVCodecContext *avctx, void *data, if (ret < 0) return ret; + if (avctx->width / s->hscale * avctx->height * s->delta_size > avpkt->size * 8LL * 4) + return AVERROR_INVALIDDATA; + ret = init_get_bits8(gb, avpkt->data + ret, avpkt->size - ret); if (ret < 0) return ret; From f9cb17f988cc72048f2051ce120ccbd6d05ce1c2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 26 Feb 2018 16:44:50 +0100 Subject: [PATCH 1982/2557] avcodec/msmpeg4dec: Check for input end in msmpeg4v34_decode_mb() Fixes: Timeout Fixes: 6276/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WMV1_fuzzer-5881196690014208 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/msmpeg4dec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c index 4105d4ba7d061..457a37e745806 100644 --- a/libavcodec/msmpeg4dec.c +++ b/libavcodec/msmpeg4dec.c @@ -208,6 +208,9 @@ static int msmpeg4v34_decode_mb(MpegEncContext *s, int16_t block[6][64]) uint8_t *coded_val; uint32_t * const mb_type_ptr = &s->current_picture.mb_type[s->mb_x + s->mb_y*s->mb_stride]; + if (get_bits_left(&s->gb) <= 0) + return AVERROR_INVALIDDATA; + if (s->pict_type == AV_PICTURE_TYPE_P) { if (s->use_skip_mb_code) { if (get_bits1(&s->gb)) { From 40102a21374096ce0ba05c67c6e7474f176af2d0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 27 Feb 2018 17:51:02 -0300 Subject: [PATCH 1983/2557] avcodec/Makefile: skip nvdec.h header when nvdec is not enabled Fixes make checkheaders now that the cuda headers are no longer in-tree Signed-off-by: James Almer --- libavcodec/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index f09518b1977bc..b496f0dfb0c4d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1086,6 +1086,7 @@ SKIPHEADERS-$(CONFIG_JNI) += ffjni.h SKIPHEADERS-$(CONFIG_LIBVPX) += libvpx.h SKIPHEADERS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.h SKIPHEADERS-$(CONFIG_MEDIACODEC) += mediacodecdec_common.h mediacodec_surface.h mediacodec_wrapper.h mediacodec_sw_buffer.h +SKIPHEADERS-$(CONFIG_NVDEC) += nvdec.h SKIPHEADERS-$(CONFIG_NVENC) += nvenc.h SKIPHEADERS-$(CONFIG_QSV) += qsv.h qsv_internal.h SKIPHEADERS-$(CONFIG_QSVDEC) += qsvdec.h From d7239944499687b4329ac3484d0b00bd92617847 Mon Sep 17 00:00:00 2001 From: Bodecs Bela Date: Sun, 25 Feb 2018 17:07:40 +0100 Subject: [PATCH 1984/2557] avfilter/avf_concat: add next command This patch makes it possible to dinamically close the current segment and step to the next one by introducing command handling capabilities into the filter. This new feature is very usefull when working with real-time sources or live streams as source. Combinig usage with zmqsend tool you can interactively end the current segment and step to next one. Signed-off-by: Bela Bodecs --- doc/filters.texi | 8 ++++++++ libavfilter/avf_concat.c | 14 ++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 7908c51d48232..7151d4c7485b0 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -18153,6 +18153,14 @@ do not have exactly the same duration in the first file. @end itemize +@subsection Commands + +This filter supports the following commands: +@table @option +@item next +Close the current segment and step to the next one +@end table + @section drawgraph, adrawgraph Draw a graph using input video or audio metadata. diff --git a/libavfilter/avf_concat.c b/libavfilter/avf_concat.c index 6198a33d53560..46bd42359b301 100644 --- a/libavfilter/avf_concat.c +++ b/libavfilter/avf_concat.c @@ -418,6 +418,19 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&cat->in); } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret = AVERROR(ENOSYS); + + if (!strcmp(cmd, "next")) { + av_log(ctx, AV_LOG_VERBOSE, "Command received: next\n"); + return flush_segment(ctx); + } + + return ret; +} + AVFilter ff_avf_concat = { .name = "concat", .description = NULL_IF_CONFIG_SMALL("Concatenate audio and video streams."), @@ -429,4 +442,5 @@ AVFilter ff_avf_concat = { .outputs = NULL, .priv_class = &concat_class, .flags = AVFILTER_FLAG_DYNAMIC_INPUTS | AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .process_command = process_command, }; From 1be4c8579024bd44265ce2f63c6a090aa1b21bc4 Mon Sep 17 00:00:00 2001 From: Maxton Date: Tue, 27 Feb 2018 04:43:52 -0500 Subject: [PATCH 1985/2557] avcodec/wmaprodec: support decoding up to 16 channels of xma Signed-off by: Maxton --- libavcodec/wmaprodec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c index 77a49c9db8c99..9439bfa771c0f 100644 --- a/libavcodec/wmaprodec.c +++ b/libavcodec/wmaprodec.c @@ -107,8 +107,8 @@ #define MAX_BANDS 29 ///< max number of scale factor bands #define MAX_FRAMESIZE 32768 ///< maximum compressed frame size #define XMA_MAX_STREAMS 8 -#define XMA_MAX_CHANNELS 8 #define XMA_MAX_CHANNELS_STREAM 2 +#define XMA_MAX_CHANNELS (XMA_MAX_STREAMS * XMA_MAX_CHANNELS_STREAM) #define WMAPRO_BLOCK_MIN_BITS 6 ///< log2 of min block size #define WMAPRO_BLOCK_MAX_BITS 13 ///< log2 of max block size From 6731f60598963da357ff77dafe9e5e903629bde9 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Tue, 17 Oct 2017 23:57:28 +0100 Subject: [PATCH 1986/2557] frame: add an av_frame_new_side_data_from_buf function Signed-off-by: Rostislav Pehlivanov --- doc/APIchanges | 3 +++ libavutil/frame.c | 32 +++++++++++++++----------------- libavutil/frame.h | 16 ++++++++++++++++ libavutil/version.h | 4 ++-- 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index a98475366d100..d1957e2e191c6 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-03-xx - xxxxxxx - lavu 56.8.100 - frame.h + Add av_frame_new_side_data_from_buf(). + 2018-02-xx - xxxxxxx Change av_ripemd_update(), av_murmur3_update() and av_hash_update() length parameter type to size_t at next major bump. diff --git a/libavutil/frame.c b/libavutil/frame.c index 662a7e5ab5cc9..61c45f0f53247 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -26,11 +26,6 @@ #include "mem.h" #include "samplefmt.h" - -static AVFrameSideData *frame_new_side_data(AVFrame *frame, - enum AVFrameSideDataType type, - AVBufferRef *buf); - #if FF_API_FRAME_GET_SET MAKE_ACCESSORS(AVFrame, frame, int64_t, best_effort_timestamp) MAKE_ACCESSORS(AVFrame, frame, int64_t, pkt_duration) @@ -356,8 +351,10 @@ FF_ENABLE_DEPRECATION_WARNINGS } memcpy(sd_dst->data, sd_src->data, sd_src->size); } else { - sd_dst = frame_new_side_data(dst, sd_src->type, av_buffer_ref(sd_src->buf)); + AVBufferRef *ref = av_buffer_ref(sd_src->buf); + sd_dst = av_frame_new_side_data_from_buf(dst, sd_src->type, ref); if (!sd_dst) { + av_buffer_unref(&ref); wipe_side_data(dst); return AVERROR(ENOMEM); } @@ -642,9 +639,9 @@ AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane) return NULL; } -static AVFrameSideData *frame_new_side_data(AVFrame *frame, - enum AVFrameSideDataType type, - AVBufferRef *buf) +AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame, + enum AVFrameSideDataType type, + AVBufferRef *buf) { AVFrameSideData *ret, **tmp; @@ -652,17 +649,17 @@ static AVFrameSideData *frame_new_side_data(AVFrame *frame, return NULL; if (frame->nb_side_data > INT_MAX / sizeof(*frame->side_data) - 1) - goto fail; + return NULL; tmp = av_realloc(frame->side_data, (frame->nb_side_data + 1) * sizeof(*frame->side_data)); if (!tmp) - goto fail; + return NULL; frame->side_data = tmp; ret = av_mallocz(sizeof(*ret)); if (!ret) - goto fail; + return NULL; ret->buf = buf; ret->data = ret->buf->data; @@ -672,17 +669,18 @@ static AVFrameSideData *frame_new_side_data(AVFrame *frame, frame->side_data[frame->nb_side_data++] = ret; return ret; -fail: - av_buffer_unref(&buf); - return NULL; } AVFrameSideData *av_frame_new_side_data(AVFrame *frame, enum AVFrameSideDataType type, int size) { - - return frame_new_side_data(frame, type, av_buffer_alloc(size)); + AVFrameSideData *ret; + AVBufferRef *buf = av_buffer_alloc(size); + ret = av_frame_new_side_data_from_buf(frame, type, buf); + if (!ret) + av_buffer_unref(&buf); + return ret; } AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, diff --git a/libavutil/frame.h b/libavutil/frame.h index d54bd9a35436d..59cee8ceabc68 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -800,6 +800,22 @@ AVFrameSideData *av_frame_new_side_data(AVFrame *frame, enum AVFrameSideDataType type, int size); +/** + * Add a new side data to a frame from an existing AVBufferRef + * + * @param frame a frame to which the side data should be added + * @param type the type of the added side data + * @param buf an AVBufferRef to add as side data. The ownership of + * the reference is transferred to the frame. + * + * @return newly added side data on success, NULL on error. On failure + * the frame is unchanged and the AVBufferRef remains owned by + * the caller. + */ +AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame, + enum AVFrameSideDataType type, + AVBufferRef *buf); + /** * @return a pointer to the side data of a given type on success, NULL if there * is no side data with such type in this frame. diff --git a/libavutil/version.h b/libavutil/version.h index a2a820aebf03d..d7398c41c592c 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,8 +79,8 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 7 -#define LIBAVUTIL_VERSION_MICRO 101 +#define LIBAVUTIL_VERSION_MINOR 8 +#define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ From d54a04b69b8d31f3286738cfc68f25a24dfda4af Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 12 Feb 2018 23:34:23 +0100 Subject: [PATCH 1987/2557] avformat/mxfdec: fix indentation Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 3b8d4239066f7..fcae863ef4b82 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -3303,18 +3303,18 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti av_inv_q(source_track->edit_rate)); if (mxf->nb_index_tables <= 0) { - if (!s->bit_rate) - return AVERROR_INVALIDDATA; - if (sample_time < 0) - sample_time = 0; - seconds = av_rescale(sample_time, st->time_base.num, st->time_base.den); + if (!s->bit_rate) + return AVERROR_INVALIDDATA; + if (sample_time < 0) + sample_time = 0; + seconds = av_rescale(sample_time, st->time_base.num, st->time_base.den); - seekpos = avio_seek(s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET); - if (seekpos < 0) - return seekpos; + seekpos = avio_seek(s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET); + if (seekpos < 0) + return seekpos; - ff_update_cur_dts(s, st, sample_time); - mxf->current_edit_unit = sample_time; + ff_update_cur_dts(s, st, sample_time); + mxf->current_edit_unit = sample_time; } else { t = &mxf->index_tables[0]; From e9b0e42e773d4a1c9575c75e95688faca7ce4e06 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 17 Feb 2018 11:47:57 +0100 Subject: [PATCH 1988/2557] avformat/mxfdec: fix essence_offset calculation The reference point for a KAG is the first byte of the key of a Partition Pack. Fixes ticket #2817. Fixes ticket #5317. Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index fcae863ef4b82..95767ccba4e56 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -2875,8 +2875,8 @@ static int mxf_read_header(AVFormatContext *s) * for OPAtom we still need the actual essence_offset though (the KL's length can vary) */ int64_t op1a_essence_offset = - round_to_kag(mxf->current_partition->this_partition + - mxf->current_partition->pack_length, mxf->current_partition->kag_size) + + mxf->current_partition->this_partition + + round_to_kag(mxf->current_partition->pack_length, mxf->current_partition->kag_size) + round_to_kag(mxf->current_partition->header_byte_count, mxf->current_partition->kag_size) + round_to_kag(mxf->current_partition->index_byte_count, mxf->current_partition->kag_size); From 5c2fd59700c4050f81e902bfde914fe9684aa4ad Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 17 Feb 2018 15:02:19 +0100 Subject: [PATCH 1989/2557] avformat/mxfdec: use the first system item if available for calculating essence_offset Also add an additional system item key. Fixes parsing of ffmpeg-bugs/trac/ticket2817/warehouse.mxf Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 95767ccba4e56..43a0220c87d86 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -289,7 +289,8 @@ static const uint8_t mxf_header_partition_pack_key[] = { 0x06,0x0e,0x2b,0x static const uint8_t mxf_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01 }; static const uint8_t mxf_avid_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0e,0x04,0x03,0x01 }; static const uint8_t mxf_canopus_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x0a,0x0e,0x0f,0x03,0x01 }; -static const uint8_t mxf_system_item_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x03,0x01,0x04 }; +static const uint8_t mxf_system_item_key_cp[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x03,0x01,0x04 }; +static const uint8_t mxf_system_item_key_gc[] = { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x03,0x01,0x14 }; static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x34 }; /* complete keys to match */ static const uint8_t mxf_crypto_source_container_ul[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x02,0x02,0x00,0x00,0x00 }; @@ -2861,7 +2862,8 @@ static int mxf_read_header(AVFormatContext *s) if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key) || IS_KLV_KEY(klv.key, mxf_essence_element_key) || IS_KLV_KEY(klv.key, mxf_avid_essence_element_key) || - IS_KLV_KEY(klv.key, mxf_system_item_key)) { + IS_KLV_KEY(klv.key, mxf_system_item_key_cp) || + IS_KLV_KEY(klv.key, mxf_system_item_key_gc)) { if (!mxf->current_partition) { av_log(mxf->fc, AV_LOG_ERROR, "found essence prior to first PartitionPack\n"); @@ -2888,7 +2890,10 @@ static int mxf_read_header(AVFormatContext *s) mxf->current_partition->essence_length = klv.length; } else { /* NOTE: op1a_essence_offset may be less than to klv.offset (C0023S01.mxf) */ - mxf->current_partition->essence_offset = op1a_essence_offset; + if (IS_KLV_KEY(klv.key, mxf_system_item_key_cp) || IS_KLV_KEY(klv.key, mxf_system_item_key_gc)) + mxf->current_partition->essence_offset = klv.offset; + else + mxf->current_partition->essence_offset = op1a_essence_offset; } } From 9ec3e61fc37ae0cdd4bae2ba609b34424251e367 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 5 Feb 2018 23:27:20 +0100 Subject: [PATCH 1990/2557] avformat/mxfdec: use full UMID to resolve source package Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 43a0220c87d86..4c3f2a64cb335 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1681,7 +1681,7 @@ static MXFTimecodeComponent* mxf_resolve_timecode_component(MXFContext *mxf, UID return NULL; } -static MXFPackage* mxf_resolve_source_package(MXFContext *mxf, UID package_uid) +static MXFPackage* mxf_resolve_source_package(MXFContext *mxf, UID package_ul, UID package_uid) { MXFPackage *package = NULL; int i; @@ -1691,7 +1691,7 @@ static MXFPackage* mxf_resolve_source_package(MXFContext *mxf, UID package_uid) if (!package) continue; - if (!memcmp(package->package_uid, package_uid, 16)) + if (!memcmp(package->package_ul, package_ul, 16) && !memcmp(package->package_uid, package_uid, 16)) return package; } return NULL; @@ -1740,7 +1740,7 @@ static MXFStructuralComponent* mxf_resolve_essence_group_choice(MXFContext *mxf, if (!component) continue; - if (!(package = mxf_resolve_source_package(mxf, component->source_package_uid))) + if (!(package = mxf_resolve_source_package(mxf, component->source_package_ul, component->source_package_uid))) continue; descriptor = mxf_resolve_strong_ref(mxf, &package->descriptor_ref, Descriptor); @@ -1806,7 +1806,7 @@ static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_t if (!sourceclip) continue; - if (!(physical_package = mxf_resolve_source_package(mxf, sourceclip->source_package_uid))) + if (!(physical_package = mxf_resolve_source_package(mxf, sourceclip->source_package_ul, sourceclip->source_package_uid))) break; mxf_add_umid_metadata(&st->metadata, "reel_umid", physical_package); @@ -1976,7 +1976,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) if (!component) continue; - source_package = mxf_resolve_source_package(mxf, component->source_package_uid); + source_package = mxf_resolve_source_package(mxf, component->source_package_ul, component->source_package_uid); if (!source_package) { av_log(mxf->fc, AV_LOG_TRACE, "material track %d: no corresponding source package found\n", material_track->track_id); continue; From 9492bb58eeea474158f9c523fd77395629117b57 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 6 Feb 2018 22:41:16 +0100 Subject: [PATCH 1991/2557] avformat/mxfdec: use both body_sid and track_number to find the track of a packet In order to do that we have to parse the EssenceContainerData and assign the proper body_sid and index_sid to the tracks from the corresponding source packages. This fixes packets returned in the wrong stream for some OP1-b files. Based on a patch by Alex Mogurenko from https://github.com/da8eat/FFmpeg Reference: http://mogurenko.com/2018/01/02/mxf-op1b-ffmpeg-part1/ Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 87 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 4 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 4c3f2a64cb335..4f30877f6d659 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -162,6 +162,8 @@ typedef struct { int intra_only; uint64_t sample_count; int64_t original_duration; /* st->duration in SampleRate/EditRate units */ + int index_sid; + int body_sid; } MXFTrack; typedef struct MXFDescriptor { @@ -223,6 +225,15 @@ typedef struct MXFPackage { int comment_count; } MXFPackage; +typedef struct MXFEssenceContainerData { + UID uid; + enum MXFMetadataSetType type; + UID package_uid; + UID package_ul; + int index_sid; + int body_sid; +} MXFEssenceContainerData; + typedef struct MXFMetadataSet { UID uid; enum MXFMetadataSetType type; @@ -247,6 +258,8 @@ typedef struct MXFContext { MXFOP op; UID *packages_refs; int packages_count; + UID *essence_container_data_refs; + int essence_container_data_count; MXFMetadataSet **metadata_sets; int metadata_sets_count; AVFormatContext *fc; @@ -385,20 +398,43 @@ static int klv_read_packet(KLVPacket *klv, AVIOContext *pb) return klv->length == -1 ? -1 : 0; } -static int mxf_get_stream_index(AVFormatContext *s, KLVPacket *klv) +static int mxf_get_stream_index(AVFormatContext *s, KLVPacket *klv, int body_sid) { int i; for (i = 0; i < s->nb_streams; i++) { MXFTrack *track = s->streams[i]->priv_data; /* SMPTE 379M 7.3 */ - if (track && !memcmp(klv->key + sizeof(mxf_essence_element_key), track->track_number, sizeof(track->track_number))) + if (track && (!body_sid || !track->body_sid || track->body_sid == body_sid) && !memcmp(klv->key + sizeof(mxf_essence_element_key), track->track_number, sizeof(track->track_number))) return i; } /* return 0 if only one stream, for OP Atom files with 0 as track number */ return s->nb_streams == 1 ? 0 : -1; } +static int find_body_sid_by_offset(MXFContext *mxf, int64_t offset) +{ + // we look for partition where the offset is placed + int a, b, m; + int64_t this_partition; + + a = -1; + b = mxf->partitions_count; + + while (b - a > 1) { + m = (a + b) >> 1; + this_partition = mxf->partitions[m].this_partition; + if (this_partition <= offset) + a = m; + else + b = m; + } + + if (a == -1) + return 0; + return mxf->partitions[a].body_sid; +} + /* XXX: use AVBitStreamFilter */ static int mxf_get_d10_aes3_packet(AVIOContext *pb, AVStream *st, AVPacket *pkt, int64_t length) { @@ -440,6 +476,7 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv uint8_t ivec[16]; uint8_t tmpbuf[16]; int index; + int body_sid; if (!mxf->aesc && s->key && s->keylen == 16) { mxf->aesc = av_aes_alloc(); @@ -457,7 +494,9 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv avio_read(pb, klv->key, 16); if (!IS_KLV_KEY(klv, mxf_essence_element_key)) return AVERROR_INVALIDDATA; - index = mxf_get_stream_index(s, klv); + + body_sid = find_body_sid_by_offset(mxf, klv->offset); + index = mxf_get_stream_index(s, klv, body_sid); if (index < 0) return AVERROR_INVALIDDATA; // source size @@ -757,6 +796,9 @@ static int mxf_read_content_storage(void *arg, AVIOContext *pb, int tag, int siz av_log(mxf->fc, AV_LOG_VERBOSE, "Multiple packages_refs\n"); av_free(mxf->packages_refs); return mxf_read_strong_ref_array(pb, &mxf->packages_refs, &mxf->packages_count); + case 0x1902: + av_free(mxf->essence_container_data_refs); + return mxf_read_strong_ref_array(pb, &mxf->essence_container_data_refs, &mxf->essence_container_data_count); } return 0; } @@ -893,6 +935,25 @@ static int mxf_read_package(void *arg, AVIOContext *pb, int tag, int size, UID u return 0; } +static int mxf_read_essence_container_data(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) +{ + MXFEssenceContainerData *essence_data = arg; + switch(tag) { + case 0x2701: + /* linked package umid UMID */ + avio_read(pb, essence_data->package_ul, 16); + avio_read(pb, essence_data->package_uid, 16); + break; + case 0x3f06: + essence_data->index_sid = avio_rb32(pb); + break; + case 0x3f07: + essence_data->body_sid = avio_rb32(pb); + break; + } + return 0; +} + static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *segment) { int i, length; @@ -1996,6 +2057,21 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) av_log(mxf->fc, AV_LOG_ERROR, "material track %d: no corresponding source track found\n", material_track->track_id); break; } + + for (k = 0; k < mxf->essence_container_data_count; k++) { + MXFEssenceContainerData *essence_data; + + if (!(essence_data = mxf_resolve_strong_ref(mxf, &mxf->essence_container_data_refs[k], EssenceContainerData))) { + av_log(mxf, AV_LOG_TRACE, "could not resolve essence container data strong ref\n"); + continue; + } + if (!memcmp(component->source_package_ul, essence_data->package_ul, sizeof(UID)) && !memcmp(component->source_package_uid, essence_data->package_uid, sizeof(UID))) { + source_track->body_sid = essence_data->body_sid; + source_track->index_sid = essence_data->index_sid; + break; + } + } + if(source_track && component) break; } @@ -2402,6 +2478,7 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = { { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0c,0x00 }, mxf_read_pulldown_component, sizeof(MXFPulldownComponent), PulldownComponent }, { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x04,0x01,0x02,0x02,0x00,0x00 }, mxf_read_cryptographic_context, sizeof(MXFCryptoContext), CryptoContext }, { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 }, mxf_read_index_table_segment, sizeof(MXFIndexTableSegment), IndexTableSegment }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x23,0x00 }, mxf_read_essence_container_data, sizeof(MXFEssenceContainerData), EssenceContainerData }, { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL, 0, AnyType }, }; @@ -3111,7 +3188,8 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) if (IS_KLV_KEY(klv.key, mxf_essence_element_key) || IS_KLV_KEY(klv.key, mxf_canopus_essence_element_key) || IS_KLV_KEY(klv.key, mxf_avid_essence_element_key)) { - int index = mxf_get_stream_index(s, &klv); + int body_sid = find_body_sid_by_offset(mxf, klv.offset); + int index = mxf_get_stream_index(s, &klv, body_sid); int64_t next_ofs, next_klv; AVStream *st; @@ -3237,6 +3315,7 @@ static int mxf_read_close(AVFormatContext *s) int i; av_freep(&mxf->packages_refs); + av_freep(&mxf->essence_container_data_refs); for (i = 0; i < s->nb_streams; i++) s->streams[i]->priv_data = NULL; From c46e430c5bc790cd1b96f92a95a56b3da97f3f66 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Wed, 7 Feb 2018 00:20:01 +0100 Subject: [PATCH 1992/2557] avformat/mxfdec: fix sorting of index segments Fixes ticket #5320. Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 4f30877f6d659..7abb0471176df 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1309,9 +1309,15 @@ static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segment * We want the smallest values for the keys than what we currently have, unless this is the first such entry this time around. * If we come across an entry with the same IndexStartPosition but larger IndexDuration, then we'll prefer it over the one we currently have. */ - if ((i == 0 || s->body_sid > last_body_sid || s->index_sid > last_index_sid || s->index_start_position > last_index_start) && - (best == -1 || s->body_sid < best_body_sid || s->index_sid < best_index_sid || s->index_start_position < best_index_start || - (s->index_start_position == best_index_start && s->index_duration > best_index_duration))) { + if ((i == 0 || + s->body_sid > last_body_sid || + s->body_sid == last_body_sid && s->index_sid > last_index_sid || + s->body_sid == last_body_sid && s->index_sid == last_index_sid && s->index_start_position > last_index_start) && + (best == -1 || + s->body_sid < best_body_sid || + s->body_sid == best_body_sid && s->index_sid < best_index_sid || + s->body_sid == best_body_sid && s->index_sid == best_index_sid && s->index_start_position < best_index_start || + s->body_sid == best_body_sid && s->index_sid == best_index_sid && s->index_start_position == best_index_start && s->index_duration > best_index_duration)) { best = j; best_body_sid = s->body_sid; best_index_sid = s->index_sid; From 5b36379eb6eb0dfbc7e0b68a278eea2ce65f9147 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 17 Feb 2018 16:46:41 +0100 Subject: [PATCH 1993/2557] avformat/mxfdec: set index_duration from the track using the index Also use original_duration as index_duration is in edit units. Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 7abb0471176df..64f607a491a04 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1564,14 +1564,6 @@ static int mxf_compute_index_tables(MXFContext *mxf) { int i, j, k, ret, nb_sorted_segments; MXFIndexTableSegment **sorted_segments = NULL; - AVStream *st = NULL; - - for (i = 0; i < mxf->fc->nb_streams; i++) { - if (mxf->fc->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_DATA) - continue; - st = mxf->fc->streams[i]; - break; - } if ((ret = mxf_get_sorted_table_segments(mxf, &nb_sorted_segments, &sorted_segments)) || nb_sorted_segments <= 0) { @@ -1610,6 +1602,7 @@ static int mxf_compute_index_tables(MXFContext *mxf) for (i = j = 0; j < mxf->nb_index_tables; i += mxf->index_tables[j++].nb_segments) { MXFIndexTable *t = &mxf->index_tables[j]; + MXFTrack *mxf_track = NULL; t->segments = av_mallocz_array(t->nb_segments, sizeof(*t->segments)); @@ -1632,6 +1625,14 @@ static int mxf_compute_index_tables(MXFContext *mxf) if ((ret = mxf_compute_ptses_fake_index(mxf, t)) < 0) goto finish_decoding_index; + for (k = 0; k < mxf->fc->nb_streams; k++) { + MXFTrack *track = mxf->fc->streams[k]->priv_data; + if (track && track->index_sid == t->index_sid) { + mxf_track = track; + break; + } + } + /* fix zero IndexDurations */ for (k = 0; k < t->nb_segments; k++) { if (t->segments[k]->index_duration) @@ -1641,7 +1642,7 @@ static int mxf_compute_index_tables(MXFContext *mxf) av_log(mxf->fc, AV_LOG_WARNING, "IndexSID %i segment %i has zero IndexDuration and there's more than one segment\n", t->index_sid, k); - if (!st) { + if (!mxf_track) { av_log(mxf->fc, AV_LOG_WARNING, "no streams?\n"); break; } @@ -1649,7 +1650,7 @@ static int mxf_compute_index_tables(MXFContext *mxf) /* assume the first stream's duration is reasonable * leave index_duration = 0 on further segments in case we have any (unlikely) */ - t->segments[k]->index_duration = st->duration; + t->segments[k]->index_duration = mxf_track->original_duration; break; } } From 0827c78e98da808b750966af8ff3cbe0361cfcee Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Thu, 8 Feb 2018 02:38:56 +0100 Subject: [PATCH 1994/2557] avformat/mxfdec: use body_offset of the partitions in mxf_absolute_bodysid_offset Use body_offset of the partitions to search for the partition with the given offset in the essence. This makes the function find the correct partition for non frame-wrapped essences as well, where only the essence data is part of the the edit unit byte count, not the KLV-s. Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 64f607a491a04..497a97d3efddb 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -91,6 +91,7 @@ typedef struct MXFPartition { int64_t index_byte_count; int pack_length; int64_t pack_ofs; ///< absolute offset of pack in file, including run-in + int64_t body_offset; } MXFPartition; typedef struct MXFCryptoContext { @@ -612,7 +613,7 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size partition->header_byte_count = avio_rb64(pb); partition->index_byte_count = avio_rb64(pb); partition->index_sid = avio_rb32(pb); - avio_skip(pb, 8); + partition->body_offset = avio_rb64(pb); partition->body_sid = avio_rb32(pb); if (avio_read(pb, op, sizeof(UID)) != sizeof(UID)) { av_log(mxf->fc, AV_LOG_ERROR, "Failed reading UID\n"); @@ -1347,7 +1348,10 @@ static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segment static int mxf_absolute_bodysid_offset(MXFContext *mxf, int body_sid, int64_t offset, int64_t *offset_out) { int x; - int64_t offset_in = offset; /* for logging */ + MXFPartition *last_p = NULL; + + if (offset < 0) + return AVERROR(EINVAL); for (x = 0; x < mxf->partitions_count; x++) { MXFPartition *p = &mxf->partitions[x]; @@ -1355,17 +1359,20 @@ static int mxf_absolute_bodysid_offset(MXFContext *mxf, int body_sid, int64_t of if (p->body_sid != body_sid) continue; - if (offset < p->essence_length || !p->essence_length) { - *offset_out = p->essence_offset + offset; - return 0; - } + if (p->body_offset > offset) + break; + + last_p = p; + } - offset -= p->essence_length; + if (last_p && (!last_p->essence_length || last_p->essence_length > (offset - last_p->body_offset))) { + *offset_out = last_p->essence_offset + (offset - last_p->body_offset); + return 0; } av_log(mxf->fc, AV_LOG_ERROR, "failed to find absolute offset of %"PRIX64" in BodySID %i - partial file?\n", - offset_in, body_sid); + offset, body_sid); return AVERROR_INVALIDDATA; } From e8e1c22f21eecca9269f6bb18c615acaf29d974f Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 13 Feb 2018 23:44:05 +0100 Subject: [PATCH 1995/2557] avformat/mxfdec: compute sample_count after seek from index for audio streams This fixes audio timestamps if the audio streams are not frame wrapped with the video. Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 54 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 497a97d3efddb..21fd2a876befd 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -3055,6 +3055,42 @@ static int mxf_read_header(AVFormatContext *s) return ret; } +static MXFIndexTable *mxf_find_index_table(MXFContext *mxf, int index_sid) +{ + int i; + for (i = 0; i < mxf->nb_index_tables; i++) + if (mxf->index_tables[i].index_sid == index_sid) + return &mxf->index_tables[i]; + return NULL; +} + +/* Get the edit unit of the next packet from current_offset in a track. The returned edit unit can be original_duration as well! */ +static int mxf_get_next_track_edit_unit(MXFContext *mxf, MXFTrack *track, int64_t current_offset, int64_t *edit_unit_out) +{ + int64_t a, b, m, offset; + MXFIndexTable *t = mxf_find_index_table(mxf, track->index_sid); + + if (!t || track->original_duration <= 0) + return -1; + + a = -1; + b = track->original_duration; + + while (b - a > 1) { + m = (a + b) >> 1; + if (mxf_edit_unit_absolute_offset(mxf, t, m, NULL, &offset, 0) < 0) + return -1; + if (offset < current_offset) + a = m; + else + b = m; + } + + *edit_unit_out = b; + + return 0; +} + /** * Sets mxf->current_edit_unit based on what offset we're currently at. * @return next_ofs if OK, <0 on error @@ -3454,13 +3490,19 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti for (i = 0; i < s->nb_streams; i++) { AVStream *cur_st = s->streams[i]; MXFTrack *cur_track = cur_st->priv_data; - uint64_t current_sample_count = 0; if (cur_st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - ret = mxf_compute_sample_count(mxf, i, ¤t_sample_count); - if (ret < 0) - return ret; - - cur_track->sample_count = current_sample_count; + int64_t track_edit_unit; + if (st != cur_st && mxf_get_next_track_edit_unit(mxf, cur_track, seekpos, &track_edit_unit) >= 0) { + cur_track->sample_count = av_rescale_q(track_edit_unit, + av_inv_q(cur_track->edit_rate), + cur_st->time_base); + } else { + uint64_t current_sample_count = 0; + ret = mxf_compute_sample_count(mxf, i, ¤t_sample_count); + if (ret < 0) + return ret; + cur_track->sample_count = current_sample_count; + } } } return 0; From f50741147ccac999a8a3e8a15244cbe525537622 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 17 Feb 2018 19:31:33 +0100 Subject: [PATCH 1996/2557] avformat/mxfdec: always use a stream which matches the first index table when seeking Obviously this is still not perfect, but better then it was. Using the first index table and mxf->current_edit_unit is still hardcoded in many places, so this change has hopefully the less chance of breaking anything that works now. Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 21fd2a876befd..e0a4b5bd11e6a 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -3451,6 +3451,20 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti mxf->current_edit_unit = sample_time; } else { t = &mxf->index_tables[0]; + if (t->index_sid != source_track->index_sid) { + /* If the first index table does not belong to the stream, then find a stream which does belong to the index table */ + for (i = 0; i < s->nb_streams; i++) { + MXFTrack *new_source_track = s->streams[i]->priv_data; + if (new_source_track && new_source_track->index_sid == t->index_sid) { + sample_time = av_rescale_q(sample_time, new_source_track->edit_rate, source_track->edit_rate); + source_track = new_source_track; + st = s->streams[i]; + break; + } + } + if (i == s->nb_streams) + return AVERROR_INVALIDDATA; + } /* clamp above zero, else ff_index_search_timestamp() returns negative * this also means we allow seeking before the start */ From f5f2209d689cd17f4bce7ce5c4f0b1634befc785 Mon Sep 17 00:00:00 2001 From: Xiaohan Wang Date: Fri, 23 Feb 2018 17:04:41 -0800 Subject: [PATCH 1997/2557] ffmpeg: Fix memset size on ctts_data in mov_read_trun() (round 2) The allocated size of sc->ctts_data is (st->nb_index_entries + entries) * sizeof(*sc->ctts_data). The size to memset at offset sc->ctts_data + sc->ctts_count should be (st->nb_index_entries + entries - sc->ctts_count) * sizeof(*sc->ctts_data)) The current code missed |entries| I believe, which was introduced in https://patchwork.ffmpeg.org/patch/5541/. However, after offline discussion, it seems the original code is much more clear to read (before https://patchwork.ffmpeg.org/patch/5541/). Hence this CL revert the memset logic to it's previous state by remembering the |old_ctts_allocated_size|, and only memset the newly allocated entries. BUG=812567 Change-Id: Ibe94c7138e5818bfaae76866bfa6619a9b8a2b6b Reviewed-on: https://chromium-review.googlesource.com/934925 Reviewed-by: Dale Curtis Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 04567fc475cb1..f01116874c6a2 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4596,6 +4596,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) int64_t prev_dts = AV_NOPTS_VALUE; int next_frag_index = -1, index_entry_pos; size_t requested_size; + size_t old_ctts_allocated_size; AVIndexEntry *new_entries; MOVFragmentStreamInfo * frag_stream_info; @@ -4688,6 +4689,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) st->index_entries= new_entries; requested_size = (st->nb_index_entries + entries) * sizeof(*sc->ctts_data); + old_ctts_allocated_size = sc->ctts_allocated_size; ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, requested_size); if (!ctts_data) @@ -4697,8 +4699,8 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) // In case there were samples without ctts entries, ensure they get // zero valued entries. This ensures clips which mix boxes with and // without ctts entries don't pickup uninitialized data. - memset(sc->ctts_data + sc->ctts_count, 0, - (st->nb_index_entries - sc->ctts_count) * sizeof(*sc->ctts_data)); + memset((uint8_t*)(sc->ctts_data) + old_ctts_allocated_size, 0, + sc->ctts_allocated_size - old_ctts_allocated_size); if (index_entry_pos < st->nb_index_entries) { // Make hole in index_entries and ctts_data for new samples From aa294ad00a497d07931914027267cd4964425ca3 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 2 Mar 2018 10:56:36 +0800 Subject: [PATCH 1998/2557] avformat/hlsenc: add reference stream index for split segment fix ticket: #7044 Get the first video stream to reference for split segment when there have more than one video stream Signed-off-by: Steven Liu Reviewed-by: Karthick Jeyapal --- libavformat/hlsenc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index ff064732a1d33..08fe0aa7a04c3 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -129,6 +129,7 @@ typedef struct VariantStream { int nb_entries; int discontinuity_set; int discontinuity; + int reference_stream_index; HLSSegment *segments; HLSSegment *last_segment; @@ -2141,7 +2142,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) if (vs->has_video) { can_split = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ((pkt->flags & AV_PKT_FLAG_KEY) || (hls->flags & HLS_SPLIT_BY_TIME)); - is_ref_pkt = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO; + is_ref_pkt = (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && (pkt->stream_index == vs->reference_stream_index); } if (pkt->pts == AV_NOPTS_VALUE) is_ref_pkt = can_split = 0; @@ -2497,6 +2498,11 @@ static int hls_init(AVFormatContext *s) for (j = 0; j < vs->nb_streams; j++) { vs->has_video += vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO; + /* Get one video stream to reference for split segments + * so use the first video stream index. */ + if ((vs->has_video == 1) && (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) { + vs->reference_stream_index = j; + } vs->has_subtitle += vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE; } From 6ce5dd228c40159c774543425dd1f94a5d670542 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 27 Feb 2018 00:09:47 -0300 Subject: [PATCH 1999/2557] avformat/mxg: return reference counted packets Reviewed-by: wm4 Signed-off-by: James Almer --- libavformat/mxg.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/libavformat/mxg.c b/libavformat/mxg.c index 6fbf99cfa31ed..fe5879ecf04f6 100644 --- a/libavformat/mxg.c +++ b/libavformat/mxg.c @@ -169,11 +169,14 @@ static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt) continue; } + size = mxg->buffer_ptr - mxg->soi_ptr; + ret = av_new_packet(pkt, size); + if (ret < 0) + return ret; + memcpy(pkt->data, mxg->soi_ptr, size); + pkt->pts = pkt->dts = mxg->dts; pkt->stream_index = 0; - pkt->buf = NULL; - pkt->size = mxg->buffer_ptr - mxg->soi_ptr; - pkt->data = mxg->soi_ptr; if (mxg->soi_ptr - mxg->buffer > mxg->cache_size) { if (mxg->cache_size > 0) { @@ -206,12 +209,14 @@ static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt) mxg->buffer_ptr += size; if (marker == APP13 && size >= 16) { /* audio data */ + ret = av_new_packet(pkt, size - 14); + if (ret < 0) + return ret; + memcpy(pkt->data, startmarker_ptr + 16, size - 14); + /* time (GMT) of first sample in usec since 1970, little-endian */ pkt->pts = pkt->dts = AV_RL64(startmarker_ptr + 8); pkt->stream_index = 1; - pkt->buf = NULL; - pkt->size = size - 14; - pkt->data = startmarker_ptr + 16; if (startmarker_ptr - mxg->buffer > mxg->cache_size) { if (mxg->cache_size > 0) { From 61c972384d311508d07f9360d196909e27195655 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Thu, 1 Mar 2018 19:30:42 +0100 Subject: [PATCH 2000/2557] parseutils: add support for ms and us suffix for AV_OPT_TYPE_DURATION supported suffixes are: - s: seconds (default when no suffix specified) - m or ms: milliseconds - u or us: microseconds --- libavutil/parseutils.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c index 7ca07b37a19ad..44c845577a9a0 100644 --- a/libavutil/parseutils.c +++ b/libavutil/parseutils.c @@ -590,7 +590,7 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) int64_t t, now64; time_t now; struct tm dt = { 0 }, tmbuf; - int today = 0, negative = 0, microseconds = 0; + int today = 0, negative = 0, microseconds = 0, suffix = 1000000; int i; static const char * const date_fmt[] = { "%Y - %m - %d", @@ -689,6 +689,17 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) if (duration) { t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec; + if (*q == 'm') { + suffix = 1000; + microseconds /= 1000; + q++; + } else if (*q == 'u') { + suffix = 1; + microseconds = 0; + q++; + } + if (*q == 's') + q++; } else { int is_utc = *q == 'Z' || *q == 'z'; int tzoffset = 0; @@ -724,7 +735,7 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) if (*q) return AVERROR(EINVAL); - t *= 1000000; + t *= suffix; t += microseconds; *timeval = negative ? -t : t; return 0; From e990713ff9e39418318b2ca8dd8ab432e5e55c7c Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Sun, 25 Feb 2018 09:44:23 -0800 Subject: [PATCH 2001/2557] avcodec/hevcdec: Declare that nvdec supports 12bit decoding --- libavcodec/hevcdec.c | 5 +++++ libavcodec/version.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index fc4eb781dc013..c8877626d2e43 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -404,6 +404,11 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif +#if CONFIG_HEVC_NVDEC_HWACCEL + *fmt++ = AV_PIX_FMT_CUDA; +#endif + break; + case AV_PIX_FMT_YUV420P12: #if CONFIG_HEVC_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; #endif diff --git a/libavcodec/version.h b/libavcodec/version.h index ca18ce6e8bf73..1e84410d68a71 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 13 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 9d5aff09a7163b17ec98f8c712ddde7727372dbc Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Thu, 1 Mar 2018 20:16:48 -0800 Subject: [PATCH 2002/2557] swscale: Add p016 output support and generalise yuv420p1x to p010 To make the best use of existing code, I generalised the wrapper that currently does yuv420p10 to p010 to support any mixture of input and output sizes between 10 and 16 bits. This had the side effect of yielding a working code path for all yuv420p1x formats to p01x. --- libswscale/output.c | 31 ++++++++++++++++++++++ libswscale/swscale_unscaled.c | 35 ++++++++++++++++++------- libswscale/utils.c | 4 +-- libswscale/version.h | 2 +- tests/ref/fate/filter-pixdesc-p016be | 1 + tests/ref/fate/filter-pixdesc-p016le | 1 + tests/ref/fate/filter-pixfmts-copy | 2 ++ tests/ref/fate/filter-pixfmts-crop | 2 ++ tests/ref/fate/filter-pixfmts-field | 2 ++ tests/ref/fate/filter-pixfmts-hflip | 2 ++ tests/ref/fate/filter-pixfmts-il | 2 ++ tests/ref/fate/filter-pixfmts-null | 2 ++ tests/ref/fate/filter-pixfmts-pad | 1 + tests/ref/fate/filter-pixfmts-scale | 2 ++ tests/ref/fate/filter-pixfmts-transpose | 2 ++ tests/ref/fate/filter-pixfmts-vflip | 2 ++ 16 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 tests/ref/fate/filter-pixdesc-p016be create mode 100644 tests/ref/fate/filter-pixdesc-p016le diff --git a/libswscale/output.c b/libswscale/output.c index f30bce8dd3c1e..0af2fffea4e83 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -180,6 +180,34 @@ yuv2planeX_16_c_template(const int16_t *filter, int filterSize, } } +static void yuv2p016cX_c(SwsContext *c, const int16_t *chrFilter, int chrFilterSize, + const int16_t **chrUSrc, const int16_t **chrVSrc, + uint8_t *dest8, int chrDstW) +{ + uint16_t *dest = (uint16_t*)dest8; + const int32_t **uSrc = (const int32_t **)chrUSrc; + const int32_t **vSrc = (const int32_t **)chrVSrc; + int shift = 15; + int big_endian = c->dstFormat == AV_PIX_FMT_P016BE; + int i, j; + + for (i = 0; i < chrDstW; i++) { + int u = 1 << (shift - 1); + int v = 1 << (shift - 1); + + /* See yuv2planeX_16_c_template for details. */ + u -= 0x40000000; + v -= 0x40000000; + for (j = 0; j < chrFilterSize; j++) { + u += uSrc[j][i] * (unsigned)chrFilter[j]; + v += vSrc[j][i] * (unsigned)chrFilter[j]; + } + + output_pixel(&dest[2*i] , u, 0x8000, int); + output_pixel(&dest[2*i+1], v, 0x8000, int); + } +} + #undef output_pixel #define output_pixel(pos, val) \ @@ -2257,6 +2285,9 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, } else if (is16BPS(dstFormat)) { *yuv2planeX = isBE(dstFormat) ? yuv2planeX_16BE_c : yuv2planeX_16LE_c; *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_16BE_c : yuv2plane1_16LE_c; + if (dstFormat == AV_PIX_FMT_P016LE || dstFormat == AV_PIX_FMT_P016BE) { + *yuv2nv12cX = yuv2p016cX_c; + } } else if (isNBPS(dstFormat)) { if (desc->comp[0].depth == 9) { *yuv2planeX = isBE(dstFormat) ? yuv2planeX_9BE_c : yuv2planeX_9LE_c; diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 5ec2116bcfa8d..766c9b4872774 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -180,16 +180,28 @@ static int nv12ToPlanarWrapper(SwsContext *c, const uint8_t *src[], return srcSliceH; } -static int planarToP010Wrapper(SwsContext *c, const uint8_t *src8[], +static int planarToP01xWrapper(SwsContext *c, const uint8_t *src8[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dstParam8[], int dstStride[]) { + const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat); const uint16_t **src = (const uint16_t**)src8; uint16_t *dstY = (uint16_t*)(dstParam8[0] + dstStride[0] * srcSliceY); uint16_t *dstUV = (uint16_t*)(dstParam8[1] + dstStride[1] * srcSliceY / 2); int x, y; + /* Calculate net shift required for values. */ + const int shift[3] = { + dst_format->comp[0].depth + dst_format->comp[0].shift - + src_format->comp[0].depth - src_format->comp[0].shift, + dst_format->comp[1].depth + dst_format->comp[1].shift - + src_format->comp[1].depth - src_format->comp[1].shift, + dst_format->comp[2].depth + dst_format->comp[2].shift - + src_format->comp[2].depth - src_format->comp[2].shift, + }; + av_assert0(!(srcStride[0] % 2 || srcStride[1] % 2 || srcStride[2] % 2 || dstStride[0] % 2 || dstStride[1] % 2)); @@ -197,7 +209,7 @@ static int planarToP010Wrapper(SwsContext *c, const uint8_t *src8[], uint16_t *tdstY = dstY; const uint16_t *tsrc0 = src[0]; for (x = c->srcW; x > 0; x--) { - *tdstY++ = *tsrc0++ << 6; + *tdstY++ = *tsrc0++ << shift[0]; } src[0] += srcStride[0] / 2; dstY += dstStride[0] / 2; @@ -207,8 +219,8 @@ static int planarToP010Wrapper(SwsContext *c, const uint8_t *src8[], const uint16_t *tsrc1 = src[1]; const uint16_t *tsrc2 = src[2]; for (x = c->srcW / 2; x > 0; x--) { - *tdstUV++ = *tsrc1++ << 6; - *tdstUV++ = *tsrc2++ << 6; + *tdstUV++ = *tsrc1++ << shift[1]; + *tdstUV++ = *tsrc2++ << shift[2]; } src[1] += srcStride[1] / 2; src[2] += srcStride[2] / 2; @@ -1738,14 +1750,17 @@ void ff_get_unscaled_swscale(SwsContext *c) !(flags & SWS_ACCURATE_RND) && (c->dither == SWS_DITHER_BAYER || c->dither == SWS_DITHER_AUTO) && !(dstH & 1)) { c->swscale = ff_yuv2rgb_get_func_ptr(c); } - /* yuv420p10_to_p010 */ - if ((srcFormat == AV_PIX_FMT_YUV420P10 || srcFormat == AV_PIX_FMT_YUVA420P10) && - dstFormat == AV_PIX_FMT_P010) { - c->swscale = planarToP010Wrapper; + /* yuv420p1x_to_p01x */ + if ((srcFormat == AV_PIX_FMT_YUV420P10 || srcFormat == AV_PIX_FMT_YUVA420P10 || + srcFormat == AV_PIX_FMT_YUV420P12 || + srcFormat == AV_PIX_FMT_YUV420P14 || + srcFormat == AV_PIX_FMT_YUV420P16 || srcFormat == AV_PIX_FMT_YUVA420P16) && + (dstFormat == AV_PIX_FMT_P010 || dstFormat == AV_PIX_FMT_P016)) { + c->swscale = planarToP01xWrapper; } - /* yuv420p_to_p010le */ + /* yuv420p_to_p01xle */ if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) && - dstFormat == AV_PIX_FMT_P010LE) { + (dstFormat == AV_PIX_FMT_P010LE || dstFormat == AV_PIX_FMT_P016LE)) { c->swscale = planar8ToP01xleWrapper; } diff --git a/libswscale/utils.c b/libswscale/utils.c index 4df09306d36d1..98a6b994760fb 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -254,8 +254,8 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = { [AV_PIX_FMT_AYUV64LE] = { 1, 1}, [AV_PIX_FMT_P010LE] = { 1, 1 }, [AV_PIX_FMT_P010BE] = { 1, 1 }, - [AV_PIX_FMT_P016LE] = { 1, 0 }, - [AV_PIX_FMT_P016BE] = { 1, 0 }, + [AV_PIX_FMT_P016LE] = { 1, 1 }, + [AV_PIX_FMT_P016BE] = { 1, 1 }, }; int sws_isSupportedInput(enum AVPixelFormat pix_fmt) diff --git a/libswscale/version.h b/libswscale/version.h index 0393a6fe4aff6..edc133b2339e5 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -28,7 +28,7 @@ #define LIBSWSCALE_VERSION_MAJOR 5 #define LIBSWSCALE_VERSION_MINOR 0 -#define LIBSWSCALE_VERSION_MICRO 101 +#define LIBSWSCALE_VERSION_MICRO 102 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ LIBSWSCALE_VERSION_MINOR, \ diff --git a/tests/ref/fate/filter-pixdesc-p016be b/tests/ref/fate/filter-pixdesc-p016be new file mode 100644 index 0000000000000..7c934079c8b36 --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p016be @@ -0,0 +1 @@ +pixdesc-p016be 784a49bf554861da9d0809a615bcf813 diff --git a/tests/ref/fate/filter-pixdesc-p016le b/tests/ref/fate/filter-pixdesc-p016le new file mode 100644 index 0000000000000..c723a0f1fd021 --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p016le @@ -0,0 +1 @@ +pixdesc-p016le ed04897de0a6788bb3458e7365f10d36 diff --git a/tests/ref/fate/filter-pixfmts-copy b/tests/ref/fate/filter-pixfmts-copy index 124dddeacbe6e..c45ce937b3777 100644 --- a/tests/ref/fate/filter-pixfmts-copy +++ b/tests/ref/fate/filter-pixfmts-copy @@ -51,6 +51,8 @@ nv12 8e24feb2c544dc26a20047a71e4c27aa nv21 335d85c9af6110f26ae9e187a82ed2cf p010be 7f9842d6015026136bad60d03c035cc3 p010le c453421b9f726bdaf2bacf59a492c43b +p016be 7f9842d6015026136bad60d03c035cc3 +p016le c453421b9f726bdaf2bacf59a492c43b pal8 ff5929f5b42075793b2c34cb441bede5 rgb0 0de71e5a1f97f81fb51397a0435bfa72 rgb24 f4438057d046e6d98ade4e45294b21be diff --git a/tests/ref/fate/filter-pixfmts-crop b/tests/ref/fate/filter-pixfmts-crop index e21479ceb0086..c5bb8a4135599 100644 --- a/tests/ref/fate/filter-pixfmts-crop +++ b/tests/ref/fate/filter-pixfmts-crop @@ -49,6 +49,8 @@ nv12 92cda427f794374731ec0321ee00caac nv21 1bcfc197f4fb95de85ba58182d8d2f69 p010be 8b2de2eb6b099bbf355bfc55a0694ddc p010le 373b50c766dfd0a8e79c9a73246d803a +p016be 8b2de2eb6b099bbf355bfc55a0694ddc +p016le 373b50c766dfd0a8e79c9a73246d803a pal8 1f2cdc8e718f95c875dbc1034a688bfb rgb0 736646b70dd9a0be22b8da8041e35035 rgb24 c5fbbf816bb2000f4d2914e335698ef5 diff --git a/tests/ref/fate/filter-pixfmts-field b/tests/ref/fate/filter-pixfmts-field index ba2af6e76fc44..df43ce693127b 100644 --- a/tests/ref/fate/filter-pixfmts-field +++ b/tests/ref/fate/filter-pixfmts-field @@ -51,6 +51,8 @@ nv12 16f7a46708ef25ebd0b72e47920cc11e nv21 7294574037cc7f9373ef5695d8ebe809 p010be a0311a09bba7383553267d2b3b9c075e p010le ee09a18aefa3ebe97715b3a7312cb8ff +p016be a0311a09bba7383553267d2b3b9c075e +p016le ee09a18aefa3ebe97715b3a7312cb8ff pal8 0658c18dcd8d052d59dfbe23f5b368d9 rgb0 ca3fa6e865b91b3511c7f2bf62830059 rgb24 25ab271e26a5785be169578d99da5dd0 diff --git a/tests/ref/fate/filter-pixfmts-hflip b/tests/ref/fate/filter-pixfmts-hflip index 875980d8928dd..a98314b0b3568 100644 --- a/tests/ref/fate/filter-pixfmts-hflip +++ b/tests/ref/fate/filter-pixfmts-hflip @@ -49,6 +49,8 @@ nv12 801e58f1be5fd0b5bc4bf007c604b0b4 nv21 9f10dfff8963dc327d3395af21f0554f p010be 744b13e44d39e1ff7588983fa03e0101 p010le a50b160346ab94f55a425065b57006f0 +p016be 744b13e44d39e1ff7588983fa03e0101 +p016le a50b160346ab94f55a425065b57006f0 pal8 5b7c77d99817b4f52339742a47de7797 rgb0 0092452f37d73da20193265ace0b7d57 rgb24 21571104e6091a689feabb7867e513dd diff --git a/tests/ref/fate/filter-pixfmts-il b/tests/ref/fate/filter-pixfmts-il index c6885b970ef42..3ed6c462266d9 100644 --- a/tests/ref/fate/filter-pixfmts-il +++ b/tests/ref/fate/filter-pixfmts-il @@ -51,6 +51,8 @@ nv12 3c3ba9b1b4c4dfff09c26f71b51dd146 nv21 ab586d8781246b5a32d8760a61db9797 p010be 3df51286ef66b53e3e283dbbab582263 p010le eadcd8241e97e35b2b47d5eb2eaea6cd +p016be 3df51286ef66b53e3e283dbbab582263 +p016le eadcd8241e97e35b2b47d5eb2eaea6cd rgb0 cfaf68671e43248267d8cd50cae8c13f rgb24 88894f608cf33ba310f21996748d77a7 rgb444be 99d36d814988fb388aacdef575dacfcf diff --git a/tests/ref/fate/filter-pixfmts-null b/tests/ref/fate/filter-pixfmts-null index 124dddeacbe6e..c45ce937b3777 100644 --- a/tests/ref/fate/filter-pixfmts-null +++ b/tests/ref/fate/filter-pixfmts-null @@ -51,6 +51,8 @@ nv12 8e24feb2c544dc26a20047a71e4c27aa nv21 335d85c9af6110f26ae9e187a82ed2cf p010be 7f9842d6015026136bad60d03c035cc3 p010le c453421b9f726bdaf2bacf59a492c43b +p016be 7f9842d6015026136bad60d03c035cc3 +p016le c453421b9f726bdaf2bacf59a492c43b pal8 ff5929f5b42075793b2c34cb441bede5 rgb0 0de71e5a1f97f81fb51397a0435bfa72 rgb24 f4438057d046e6d98ade4e45294b21be diff --git a/tests/ref/fate/filter-pixfmts-pad b/tests/ref/fate/filter-pixfmts-pad index e777211cd9a0b..097bd58c86cca 100644 --- a/tests/ref/fate/filter-pixfmts-pad +++ b/tests/ref/fate/filter-pixfmts-pad @@ -22,6 +22,7 @@ gray16le 468bda6155bdc7a7a20c34d6e599fd16 gray9le f8f3dfe31ca5fcba828285bceefdab9a nv12 381574979cb04be10c9168540310afad nv21 0fdeb2cdd56cf5a7147dc273456fa217 +p016le 536a3b4c3b47d005f9ab033370cc1c3b rgb0 78d500c8361ab6423a4826a00268c908 rgb24 17f9e2e0c609009acaf2175c42d4a2a5 rgba b157c90191463d34fb3ce77b36c96386 diff --git a/tests/ref/fate/filter-pixfmts-scale b/tests/ref/fate/filter-pixfmts-scale index f43c5194286b0..1611c60ea7cbb 100644 --- a/tests/ref/fate/filter-pixfmts-scale +++ b/tests/ref/fate/filter-pixfmts-scale @@ -51,6 +51,8 @@ nv12 b118d24a3653fe66e5d9e079033aef79 nv21 c74bb1c10dbbdee8a1f682b194486c4d p010be 1d6726d94bf1385996a9a9840dd0e878 p010le 4b316f2b9e18972299beb73511278fa8 +p016be 31e204018cbb53f8988c4e1174ea8ce9 +p016le d5afe557f492a09317e525d7cb782f5b pal8 29e10892009b2cfe431815ec3052ed3b rgb0 fbd27e98154efb7535826afed41e9bb0 rgb24 e022e741451e81f2ecce1c7240b93e87 diff --git a/tests/ref/fate/filter-pixfmts-transpose b/tests/ref/fate/filter-pixfmts-transpose index fcad28b9ff135..49069d6e06df8 100644 --- a/tests/ref/fate/filter-pixfmts-transpose +++ b/tests/ref/fate/filter-pixfmts-transpose @@ -49,6 +49,8 @@ nv12 1965e3826144686748f2f6b516fca5ba nv21 292adaf5271c5c8516b71640458c01f4 p010be ad0de2cc9bff81688b182a870fcf7000 p010le e7ff5143595021246733ce6bd0a769e8 +p016be ad0de2cc9bff81688b182a870fcf7000 +p016le e7ff5143595021246733ce6bd0a769e8 rgb0 31ea5da7fe779c6ea0a33f1d28aad918 rgb24 47654cabaaad79170b90afd5a02161dd rgb444be 3cac1f0c43a74d2a95eb02e187070845 diff --git a/tests/ref/fate/filter-pixfmts-vflip b/tests/ref/fate/filter-pixfmts-vflip index 84b9d56858ab5..d49e50196e33e 100644 --- a/tests/ref/fate/filter-pixfmts-vflip +++ b/tests/ref/fate/filter-pixfmts-vflip @@ -51,6 +51,8 @@ nv12 261ebe585ae2aa4e70d39a10c1679294 nv21 2909feacd27bebb080c8e0fa41795269 p010be 06e9354b6e0e38ba41736352cedc0bd5 p010le fd18d322bffbf5816902c13102872e22 +p016be 06e9354b6e0e38ba41736352cedc0bd5 +p016le fd18d322bffbf5816902c13102872e22 pal8 450b0155d0f2d5628bf95a442db5f817 rgb0 56a7ea69541bcd27bef6a5615784722b rgb24 195e6dae1c3a488b9d3ceb7560d25d85 From 6a89cdc474bc1a2a276dff63629784d68b9cab6e Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Sun, 25 Feb 2018 09:08:06 -0800 Subject: [PATCH 2003/2557] avcodec/nvenc: Declare support for P016 nvenc doesn't support P016, but we have two problems today: 1) We declare support for YUV444P16 which nvenc also doesn't support. We do this because it's the only pix_fmt we have that can approximate nvenc's internal format that is YUV444P10 with data in MSBs instead of LSBs. Because the declared format is a 16bit one, it will be preferrentially chosen when encoding >10bit content, but that content will normally be YUV420P12 or P016 which should get mapped to P010 and not YUV444P10. 2) Transcoding P016 content with nvenc should be possible in a pure hardware pipeline, and that can't be done if nvenc doesn't say it accepts P016. By mapping it to P010, we can use it, albeit with truncation. I have established that swscale doesn't know how to dither to 10bits so we'd get truncation anyway, even if we tried to do this 'properly'. --- libavcodec/nvenc.c | 5 ++++- libavcodec/version.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 39c3aa1fbb2a5..1f601a63bda17 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -41,7 +41,8 @@ const enum AVPixelFormat ff_nvenc_pix_fmts[] = { AV_PIX_FMT_NV12, AV_PIX_FMT_P010, AV_PIX_FMT_YUV444P, - AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_P016, // Truncated to 10bits + AV_PIX_FMT_YUV444P16, // Truncated to 10bits AV_PIX_FMT_0RGB32, AV_PIX_FMT_0BGR32, AV_PIX_FMT_CUDA, @@ -52,6 +53,7 @@ const enum AVPixelFormat ff_nvenc_pix_fmts[] = { }; #define IS_10BIT(pix_fmt) (pix_fmt == AV_PIX_FMT_P010 || \ + pix_fmt == AV_PIX_FMT_P016 || \ pix_fmt == AV_PIX_FMT_YUV444P16) #define IS_YUV444(pix_fmt) (pix_fmt == AV_PIX_FMT_YUV444P || \ @@ -1219,6 +1221,7 @@ static NV_ENC_BUFFER_FORMAT nvenc_map_buffer_format(enum AVPixelFormat pix_fmt) case AV_PIX_FMT_NV12: return NV_ENC_BUFFER_FORMAT_NV12_PL; case AV_PIX_FMT_P010: + case AV_PIX_FMT_P016: return NV_ENC_BUFFER_FORMAT_YUV420_10BIT; case AV_PIX_FMT_YUV444P: return NV_ENC_BUFFER_FORMAT_YUV444_PL; diff --git a/libavcodec/version.h b/libavcodec/version.h index 1e84410d68a71..d8256bff21e4d 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MINOR 13 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MICRO 102 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 0dd1fff1c97d6d4e4f9c485028652aa791e4a91f Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Fri, 2 Mar 2018 11:52:37 +0530 Subject: [PATCH 2004/2557] avformat/dashenc: fix for segment open issue when persistent connection is enabled --- libavformat/dashenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 83e0cff728f2a..489e4581475bb 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1308,7 +1308,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) flush_init_segment(s, os); //open the output context when the first frame of a segment is ready - if (!c->single_file && !os->out) { + if (!c->single_file && os->packets_written == 1) { AVDictionary *opts = NULL; const char *proto = avio_find_protocol_name(s->url); int use_rename = proto && !strcmp(proto, "file"); From e45d55756188186f065fa23fcab7b7d9026ddf41 Mon Sep 17 00:00:00 2001 From: Serhii Marchuk Date: Tue, 27 Feb 2018 11:18:10 +0200 Subject: [PATCH 2005/2557] avformat/dashenc: Use HTTP DELETE for HTTP base proto --- libavformat/dashenc.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 489e4581475bb..79d63e52d439b 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1131,6 +1131,28 @@ static int update_stream_extradata(AVFormatContext *s, OutputStream *os, return 0; } +static void dashenc_delete_file(AVFormatContext *s, char *filename) { + DASHContext *c = s->priv_data; + int http_base_proto = ff_is_http_proto(filename); + + if (http_base_proto) { + AVIOContext *out = NULL; + AVDictionary *http_opts = NULL; + + set_http_options(&http_opts, c); + av_dict_set(&http_opts, "method", "DELETE", 0); + + if (dashenc_io_open(s, &out, filename, &http_opts) < 0) { + av_log(s, AV_LOG_ERROR, "failed to delete %s\n", filename); + } + + av_dict_free(&http_opts); + dashenc_io_close(s, &out, filename); + } else if (unlink(filename) < 0) { + av_log(s, AV_LOG_ERROR, "failed to delete %s: %s\n", filename, strerror(errno)); + } +} + static int dash_flush(AVFormatContext *s, int final, int stream) { DASHContext *c = s->priv_data; @@ -1215,7 +1237,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) for (j = 0; j < remove; j++) { char filename[1024]; snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->segments[j]->file); - unlink(filename); + dashenc_delete_file(s, filename); av_free(os->segments[j]); } os->nb_segments -= remove; @@ -1367,9 +1389,9 @@ static int dash_write_trailer(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile); - unlink(filename); + dashenc_delete_file(s, filename); } - unlink(s->url); + dashenc_delete_file(s, s->url); } return 0; From a079eaba8ee20bc3869852df658f2f6cc11875e3 Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Mon, 19 Feb 2018 16:13:00 +0100 Subject: [PATCH 2006/2557] avcodec/mediacodecdec_common: refactor mediacodec_dec_parse_format() --- libavcodec/mediacodecdec_common.c | 82 +++++++++++-------------------- 1 file changed, 30 insertions(+), 52 deletions(-) diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index b44abaef7fe67..ab26df04bda03 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -339,11 +339,22 @@ FF_ENABLE_DEPRECATION_WARNINGS return ret; } +#define AMEDIAFORMAT_GET_INT32(name, key, mandatory) do { \ + int32_t value = 0; \ + if (ff_AMediaFormat_getInt32(s->format, key, &value)) { \ + (name) = value; \ + } else if (mandatory) { \ + av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", key, format); \ + ret = AVERROR_EXTERNAL; \ + goto fail; \ + } \ +} while (0) \ + static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecContext *s) { + int ret = 0; int width = 0; int height = 0; - int32_t value = 0; char *format = NULL; if (!s->format) { @@ -356,40 +367,16 @@ static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecConte return AVERROR_EXTERNAL; } av_log(avctx, AV_LOG_DEBUG, "Parsing MediaFormat %s\n", format); - av_freep(&format); /* Mandatory fields */ - if (!ff_AMediaFormat_getInt32(s->format, "width", &value)) { - format = ff_AMediaFormat_toString(s->format); - av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "width", format); - av_freep(&format); - return AVERROR_EXTERNAL; - } - s->width = value; + AMEDIAFORMAT_GET_INT32(s->width, "width", 1); + AMEDIAFORMAT_GET_INT32(s->height, "height", 1); - if (!ff_AMediaFormat_getInt32(s->format, "height", &value)) { - format = ff_AMediaFormat_toString(s->format); - av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "height", format); - av_freep(&format); - return AVERROR_EXTERNAL; - } - s->height = value; + AMEDIAFORMAT_GET_INT32(s->stride, "stride", 1); + s->stride = s->stride > 0 ? s->stride : s->width; - if (!ff_AMediaFormat_getInt32(s->format, "stride", &value)) { - format = ff_AMediaFormat_toString(s->format); - av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "stride", format); - av_freep(&format); - return AVERROR_EXTERNAL; - } - s->stride = value > 0 ? value : s->width; - - if (!ff_AMediaFormat_getInt32(s->format, "slice-height", &value)) { - format = ff_AMediaFormat_toString(s->format); - av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "slice-height", format); - av_freep(&format); - return AVERROR_EXTERNAL; - } - s->slice_height = value > 0 ? value : s->height; + AMEDIAFORMAT_GET_INT32(s->slice_height, "slice-height", 1); + s->slice_height = s->slice_height > 0 ? s->slice_height : s->height; if (strstr(s->codec_name, "OMX.Nvidia.")) { s->slice_height = FFALIGN(s->height, 16); @@ -398,32 +385,19 @@ static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecConte s->stride = avctx->width; } - if (!ff_AMediaFormat_getInt32(s->format, "color-format", &value)) { - format = ff_AMediaFormat_toString(s->format); - av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "color-format", format); - av_freep(&format); - return AVERROR_EXTERNAL; - } - s->color_format = value; - - s->pix_fmt = avctx->pix_fmt = mcdec_map_color_format(avctx, s, value); + AMEDIAFORMAT_GET_INT32(s->color_format, "color-format", 1); + s->pix_fmt = avctx->pix_fmt = mcdec_map_color_format(avctx, s, s->color_format); if (avctx->pix_fmt == AV_PIX_FMT_NONE) { av_log(avctx, AV_LOG_ERROR, "Output color format is not supported\n"); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } /* Optional fields */ - if (ff_AMediaFormat_getInt32(s->format, "crop-top", &value)) - s->crop_top = value; - - if (ff_AMediaFormat_getInt32(s->format, "crop-bottom", &value)) - s->crop_bottom = value; - - if (ff_AMediaFormat_getInt32(s->format, "crop-left", &value)) - s->crop_left = value; - - if (ff_AMediaFormat_getInt32(s->format, "crop-right", &value)) - s->crop_right = value; + AMEDIAFORMAT_GET_INT32(s->crop_top, "crop-top", 0); + AMEDIAFORMAT_GET_INT32(s->crop_bottom, "crop-bottom", 0); + AMEDIAFORMAT_GET_INT32(s->crop_left, "crop-left", 0); + AMEDIAFORMAT_GET_INT32(s->crop_right, "crop-right", 0); width = s->crop_right + 1 - s->crop_left; height = s->crop_bottom + 1 - s->crop_top; @@ -434,7 +408,11 @@ static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecConte s->crop_top, s->crop_bottom, s->crop_left, s->crop_right, width, height); + av_freep(&format); return ff_set_dimensions(avctx, width, height); +fail: + av_freep(&format); + return ret; } From 5d69e249c81ec71630b4cb536907cc831fadef6b Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Mon, 19 Feb 2018 16:13:51 +0100 Subject: [PATCH 2007/2557] avcodec/mediacodecdec_common: remove spurious space --- libavcodec/mediacodecdec_common.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index ab26df04bda03..195cc70ba7c6d 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -415,7 +415,6 @@ static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecConte return ret; } - static int mediacodec_dec_flush_codec(AVCodecContext *avctx, MediaCodecDecContext *s) { FFAMediaCodec *codec = s->codec; From cc9875dc29383dd2c82dee3736e0cf53008a865e Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Tue, 20 Feb 2018 11:08:01 +0100 Subject: [PATCH 2008/2557] avcodec/mediacodecdec_common: remove unused field from MediaCodecDecContext --- libavcodec/mediacodecdec_common.c | 2 +- libavcodec/mediacodecdec_common.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index 195cc70ba7c6d..929db78361805 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -386,7 +386,7 @@ static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecConte } AMEDIAFORMAT_GET_INT32(s->color_format, "color-format", 1); - s->pix_fmt = avctx->pix_fmt = mcdec_map_color_format(avctx, s, s->color_format); + avctx->pix_fmt = mcdec_map_color_format(avctx, s, s->color_format); if (avctx->pix_fmt == AV_PIX_FMT_NONE) { av_log(avctx, AV_LOG_ERROR, "Output color format is not supported\n"); ret = AVERROR(EINVAL); diff --git a/libavcodec/mediacodecdec_common.h b/libavcodec/mediacodecdec_common.h index 32d16d3e3a72c..85df507ffb287 100644 --- a/libavcodec/mediacodecdec_common.h +++ b/libavcodec/mediacodecdec_common.h @@ -55,7 +55,6 @@ typedef struct MediaCodecDecContext { int stride; int slice_height; int color_format; - enum AVPixelFormat pix_fmt; int crop_top; int crop_bottom; int crop_left; From c55ba52a6a0698e0d6a9f7698f7dcc384764505a Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Wed, 21 Feb 2018 14:15:42 +0100 Subject: [PATCH 2009/2557] avcodec/mediacodec_wrapper: load and use MediaFormat.constainsKey() Avoids triggering an exception in MediaFormat getter functions if the key does not exist. --- libavcodec/mediacodec_wrapper.c | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c index dbc37bf4639bf..9436b3c9941f8 100644 --- a/libavcodec/mediacodec_wrapper.c +++ b/libavcodec/mediacodec_wrapper.c @@ -111,6 +111,8 @@ struct JNIAMediaFormatFields { jmethodID init_id; + jmethodID contains_key_id; + jmethodID get_integer_id; jmethodID get_long_id; jmethodID get_float_id; @@ -132,6 +134,8 @@ static const struct FFJniField jni_amediaformat_mapping[] = { { "android/media/MediaFormat", "", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, init_id), 1 }, + { "android/media/MediaFormat", "containsKey", "(Ljava/lang/String;)Z", FF_JNI_METHOD,offsetof(struct JNIAMediaFormatFields, contains_key_id), 1 }, + { "android/media/MediaFormat", "getInteger", "(Ljava/lang/String;)I", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_integer_id), 1 }, { "android/media/MediaFormat", "getLong", "(Ljava/lang/String;)J", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_long_id), 1 }, { "android/media/MediaFormat", "getFloat", "(Ljava/lang/String;)F", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_float_id), 1 }, @@ -738,6 +742,7 @@ int ff_AMediaFormat_getInt32(FFAMediaFormat* format, const char *name, int32_t * JNIEnv *env = NULL; jstring key = NULL; + jboolean contains_key; av_assert0(format != NULL); @@ -749,6 +754,12 @@ int ff_AMediaFormat_getInt32(FFAMediaFormat* format, const char *name, int32_t * goto fail; } + contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key); + if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) { + ret = 0; + goto fail; + } + *out = (*env)->CallIntMethod(env, format->object, format->jfields.get_integer_id, key); if ((ret = ff_jni_exception_check(env, 1, format)) < 0) { ret = 0; @@ -770,6 +781,7 @@ int ff_AMediaFormat_getInt64(FFAMediaFormat* format, const char *name, int64_t * JNIEnv *env = NULL; jstring key = NULL; + jboolean contains_key; av_assert0(format != NULL); @@ -781,6 +793,12 @@ int ff_AMediaFormat_getInt64(FFAMediaFormat* format, const char *name, int64_t * goto fail; } + contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key); + if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) { + ret = 0; + goto fail; + } + *out = (*env)->CallLongMethod(env, format->object, format->jfields.get_long_id, key); if ((ret = ff_jni_exception_check(env, 1, format)) < 0) { ret = 0; @@ -802,6 +820,7 @@ int ff_AMediaFormat_getFloat(FFAMediaFormat* format, const char *name, float *ou JNIEnv *env = NULL; jstring key = NULL; + jboolean contains_key; av_assert0(format != NULL); @@ -813,6 +832,12 @@ int ff_AMediaFormat_getFloat(FFAMediaFormat* format, const char *name, float *ou goto fail; } + contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key); + if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) { + ret = 0; + goto fail; + } + *out = (*env)->CallFloatMethod(env, format->object, format->jfields.get_float_id, key); if ((ret = ff_jni_exception_check(env, 1, format)) < 0) { ret = 0; @@ -834,6 +859,7 @@ int ff_AMediaFormat_getBuffer(FFAMediaFormat* format, const char *name, void** d JNIEnv *env = NULL; jstring key = NULL; + jboolean contains_key; jobject result = NULL; av_assert0(format != NULL); @@ -846,6 +872,12 @@ int ff_AMediaFormat_getBuffer(FFAMediaFormat* format, const char *name, void** d goto fail; } + contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key); + if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) { + ret = 0; + goto fail; + } + result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_bytebuffer_id, key); if ((ret = ff_jni_exception_check(env, 1, format)) < 0) { ret = 0; @@ -885,6 +917,7 @@ int ff_AMediaFormat_getString(FFAMediaFormat* format, const char *name, const ch JNIEnv *env = NULL; jstring key = NULL; + jboolean contains_key; jstring result = NULL; av_assert0(format != NULL); @@ -897,6 +930,12 @@ int ff_AMediaFormat_getString(FFAMediaFormat* format, const char *name, const ch goto fail; } + contains_key = (*env)->CallBooleanMethod(env, format->object, format->jfields.contains_key_id, key); + if (!contains_key || (ret = ff_jni_exception_check(env, 1, format)) < 0) { + ret = 0; + goto fail; + } + result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_string_id, key); if ((ret = ff_jni_exception_check(env, 1, format)) < 0) { ret = 0; From 535e020225486514dd3cd2f4e3b59f0cc42c54f7 Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Fri, 2 Mar 2018 12:04:30 +0100 Subject: [PATCH 2010/2557] avcodec/mediacodecdec: add missing "libavutil/internal.h" include libavutil/internal.h defines NULL_IF_CONFIG_SMALL. --- libavcodec/mediacodecdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 363e12427e54a..ad09d16398c7d 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -28,6 +28,7 @@ #include "libavutil/opt.h" #include "libavutil/intreadwrite.h" #include "libavutil/pixfmt.h" +#include "libavutil/internal.h" #include "avcodec.h" #include "decode.h" From af167d970bbf86c5741e4ba8d524be77085c30ae Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Fri, 2 Mar 2018 10:36:08 +0100 Subject: [PATCH 2011/2557] avcodec/mediacodecdec: factorize common extradata functions --- libavcodec/mediacodecdec.c | 41 +++++++++----------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index ad09d16398c7d..4579da1fa56b2 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -264,34 +264,11 @@ static int hevc_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format) } #endif -#if CONFIG_MPEG2_MEDIACODEC_DECODER -static int mpeg2_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format) -{ - int ret = 0; - - if (avctx->extradata) { - ff_AMediaFormat_setBuffer(format, "csd-0", avctx->extradata, avctx->extradata_size); - } - - return ret; -} -#endif - -#if CONFIG_MPEG4_MEDIACODEC_DECODER -static int mpeg4_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format) -{ - int ret = 0; - - if (avctx->extradata) { - ff_AMediaFormat_setBuffer(format, "csd-0", avctx->extradata, avctx->extradata_size); - } - - return ret; -} -#endif - -#if CONFIG_VP8_MEDIACODEC_DECODER || CONFIG_VP9_MEDIACODEC_DECODER -static int vpx_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format) +#if CONFIG_MPEG2_MEDIACODEC_DECODER || \ + CONFIG_MPEG4_MEDIACODEC_DECODER || \ + CONFIG_VP8_MEDIACODEC_DECODER || \ + CONFIG_VP9_MEDIACODEC_DECODER +static int common_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format) { int ret = 0; @@ -342,7 +319,7 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx) case AV_CODEC_ID_MPEG2VIDEO: codec_mime = "video/mpeg2"; - ret = mpeg2_set_extradata(avctx, format); + ret = common_set_extradata(avctx, format); if (ret < 0) goto done; break; @@ -351,7 +328,7 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx) case AV_CODEC_ID_MPEG4: codec_mime = "video/mp4v-es", - ret = mpeg4_set_extradata(avctx, format); + ret = common_set_extradata(avctx, format); if (ret < 0) goto done; break; @@ -360,7 +337,7 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx) case AV_CODEC_ID_VP8: codec_mime = "video/x-vnd.on2.vp8"; - ret = vpx_set_extradata(avctx, format); + ret = common_set_extradata(avctx, format); if (ret < 0) goto done; break; @@ -369,7 +346,7 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx) case AV_CODEC_ID_VP9: codec_mime = "video/x-vnd.on2.vp9"; - ret = vpx_set_extradata(avctx, format); + ret = common_set_extradata(avctx, format); if (ret < 0) goto done; break; From 2238e54ef02b7a7ce3ddf614280d7d883ed2a9e6 Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Fri, 2 Mar 2018 12:06:19 +0100 Subject: [PATCH 2012/2557] avcodec/mediacodecdec: factorize codec declarations --- libavcodec/mediacodecdec.c | 116 ++++++++----------------------------- 1 file changed, 24 insertions(+), 92 deletions(-) diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 4579da1fa56b2..0fe14846c3373 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -485,112 +485,44 @@ static const AVCodecHWConfigInternal *mediacodec_hw_configs[] = { NULL }; +#define DECLARE_MEDIACODEC_VDEC(short_name, full_name, codec_id, bsf) \ +AVCodec ff_##short_name##_mediacodec_decoder = { \ + .name = #short_name "_mediacodec", \ + .long_name = NULL_IF_CONFIG_SMALL(full_name " Android MediaCodec decoder"), \ + .type = AVMEDIA_TYPE_VIDEO, \ + .id = codec_id, \ + .priv_data_size = sizeof(MediaCodecH264DecContext), \ + .init = mediacodec_decode_init, \ + .receive_frame = mediacodec_receive_frame, \ + .flush = mediacodec_decode_flush, \ + .close = mediacodec_decode_close, \ + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ + .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, \ + .bsfs = bsf, \ + .hw_configs = mediacodec_hw_configs, \ + .wrapper_name = "mediacodec", \ +}; \ + #if CONFIG_H264_MEDIACODEC_DECODER -AVCodec ff_h264_mediacodec_decoder = { - .name = "h264_mediacodec", - .long_name = NULL_IF_CONFIG_SMALL("H.264 Android MediaCodec decoder"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .priv_data_size = sizeof(MediaCodecH264DecContext), - .init = mediacodec_decode_init, - .receive_frame = mediacodec_receive_frame, - .flush = mediacodec_decode_flush, - .close = mediacodec_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, - .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, - .bsfs = "h264_mp4toannexb", - .hw_configs = mediacodec_hw_configs, - .wrapper_name = "mediacodec", -}; +DECLARE_MEDIACODEC_VDEC(h264, "H.264", AV_CODEC_ID_H264, "h264_mp4toannexb") #endif #if CONFIG_HEVC_MEDIACODEC_DECODER -AVCodec ff_hevc_mediacodec_decoder = { - .name = "hevc_mediacodec", - .long_name = NULL_IF_CONFIG_SMALL("H.265 Android MediaCodec decoder"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HEVC, - .priv_data_size = sizeof(MediaCodecH264DecContext), - .init = mediacodec_decode_init, - .receive_frame = mediacodec_receive_frame, - .flush = mediacodec_decode_flush, - .close = mediacodec_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, - .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, - .bsfs = "hevc_mp4toannexb", - .hw_configs = mediacodec_hw_configs, - .wrapper_name = "mediacodec", -}; +DECLARE_MEDIACODEC_VDEC(hevc, "H.265", AV_CODEC_ID_HEVC, "hevc_mp4toannexb") #endif #if CONFIG_MPEG2_MEDIACODEC_DECODER -AVCodec ff_mpeg2_mediacodec_decoder = { - .name = "mpeg2_mediacodec", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 Android MediaCodec decoder"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO, - .priv_data_size = sizeof(MediaCodecH264DecContext), - .init = mediacodec_decode_init, - .receive_frame = mediacodec_receive_frame, - .flush = mediacodec_decode_flush, - .close = mediacodec_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, - .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, - .hw_configs = mediacodec_hw_configs, - .wrapper_name = "mediacodec", -}; +DECLARE_MEDIACODEC_VDEC(mpeg2, "MPEG-2", AV_CODEC_ID_MPEG2VIDEO, NULL) #endif #if CONFIG_MPEG4_MEDIACODEC_DECODER -AVCodec ff_mpeg4_mediacodec_decoder = { - .name = "mpeg4_mediacodec", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Android MediaCodec decoder"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG4, - .priv_data_size = sizeof(MediaCodecH264DecContext), - .init = mediacodec_decode_init, - .receive_frame = mediacodec_receive_frame, - .flush = mediacodec_decode_flush, - .close = mediacodec_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, - .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, - .hw_configs = mediacodec_hw_configs, - .wrapper_name = "mediacodec", -}; +DECLARE_MEDIACODEC_VDEC(mpeg4, "MPEG-4", AV_CODEC_ID_MPEG4, NULL) #endif #if CONFIG_VP8_MEDIACODEC_DECODER -AVCodec ff_vp8_mediacodec_decoder = { - .name = "vp8_mediacodec", - .long_name = NULL_IF_CONFIG_SMALL("VP8 Android MediaCodec decoder"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP8, - .priv_data_size = sizeof(MediaCodecH264DecContext), - .init = mediacodec_decode_init, - .receive_frame = mediacodec_receive_frame, - .flush = mediacodec_decode_flush, - .close = mediacodec_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, - .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, - .hw_configs = mediacodec_hw_configs, - .wrapper_name = "mediacodec", -}; +DECLARE_MEDIACODEC_VDEC(vp8, "VP8", AV_CODEC_ID_VP8, NULL) #endif #if CONFIG_VP9_MEDIACODEC_DECODER -AVCodec ff_vp9_mediacodec_decoder = { - .name = "vp9_mediacodec", - .long_name = NULL_IF_CONFIG_SMALL("VP9 Android MediaCodec decoder"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP9, - .priv_data_size = sizeof(MediaCodecH264DecContext), - .init = mediacodec_decode_init, - .receive_frame = mediacodec_receive_frame, - .flush = mediacodec_decode_flush, - .close = mediacodec_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, - .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, - .hw_configs = mediacodec_hw_configs, - .wrapper_name = "mediacodec", -}; +DECLARE_MEDIACODEC_VDEC(vp9, "VP9", AV_CODEC_ID_VP9, NULL) #endif From 5df9d75b4417e8ca16a4ca48caa2902315723dd2 Mon Sep 17 00:00:00 2001 From: Tianqiang Liu Date: Fri, 2 Mar 2018 09:17:11 -0800 Subject: [PATCH 2013/2557] avformat/mov: Add manu/modl to mov_read_udta_string. Documentation: http://mp4ra.org/atoms.html Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index f01116874c6a2..00b3b2594459c 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -336,6 +336,8 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) case MKTAG( 'l','d','e','s'): key = "synopsis"; break; case MKTAG( 'l','o','c','i'): return mov_metadata_loci(c, pb, atom.size); + case MKTAG( 'm','a','n','u'): key = "make"; break; + case MKTAG( 'm','o','d','l'): key = "model"; break; case MKTAG( 'p','c','s','t'): key = "podcast"; parse = mov_metadata_int8_no_padding; break; case MKTAG( 'p','g','a','p'): key = "gapless_playback"; From 1c7f1f38c533382710361ef7e765f1de4f7dfa78 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Fri, 23 Feb 2018 13:53:05 +0800 Subject: [PATCH 2014/2557] doc/bitstream_filters: correct dump_extra bsfs docs. Update dump_extra bit stream filter docs to follow current code implement. Signed-off-by: Jun Zhao Reviewed-by: Steven Liu Signed-off-by: Michael Niedermayer --- doc/bitstream_filters.texi | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index cfd81fa12deca..b7ea54932227b 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -50,21 +50,22 @@ DTS-HD. Add extradata to the beginning of the filtered packets. +@table @option +@item freq The additional argument specifies which packets should be filtered. It accepts the values: @table @samp -@item a -add extradata to all key packets, but only if @var{local_header} is -set in the @option{flags2} codec context field - @item k +@item keyframe add extradata to all key packets @item e +@item all add extradata to all packets @end table +@end table -If not specified it is assumed @samp{k}. +If not specified it is assumed @samp{e}. For example the following @command{ffmpeg} command forces a global header (thus disabling individual packet headers) in the H.264 packets From dd3f1e3a1186ac2cd3d4ce71944626a2c3f200f1 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Fri, 2 Mar 2018 09:09:05 -0800 Subject: [PATCH 2015/2557] swscale: Introduce a helper to identify semi-planar formats This cleans up the ever-more-unreadable list of semi-planar exclusions for selecting the planar copy wrapper. --- libswscale/swscale_internal.h | 11 +++++++++++ libswscale/swscale_unscaled.c | 7 +------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 0f51df95d7520..c9120d8f5f158 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -676,6 +676,17 @@ static av_always_inline int isPlanarYUV(enum AVPixelFormat pix_fmt) return ((desc->flags & AV_PIX_FMT_FLAG_PLANAR) && isYUV(pix_fmt)); } +/* + * Identity semi-planar YUV formats. Specifically, those are YUV formats + * where the second and third components (U & V) are on the same plane. + */ +static av_always_inline int isSemiPlanarYUV(enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + av_assert0(desc); + return (isPlanarYUV(pix_fmt) && desc->comp[1].plane == desc->comp[2].plane); +} + static av_always_inline int isRGB(enum AVPixelFormat pix_fmt) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 766c9b4872774..13f9cd83e36bf 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -1930,12 +1930,7 @@ void ff_get_unscaled_swscale(SwsContext *c) (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) && c->chrDstHSubSample == c->chrSrcHSubSample && c->chrDstVSubSample == c->chrSrcVSubSample && - dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 && - dstFormat != AV_PIX_FMT_P010LE && dstFormat != AV_PIX_FMT_P010BE && - dstFormat != AV_PIX_FMT_P016LE && dstFormat != AV_PIX_FMT_P016BE && - srcFormat != AV_PIX_FMT_NV12 && srcFormat != AV_PIX_FMT_NV21 && - srcFormat != AV_PIX_FMT_P010LE && srcFormat != AV_PIX_FMT_P010BE && - srcFormat != AV_PIX_FMT_P016LE && srcFormat != AV_PIX_FMT_P016BE)) + !isSemiPlanarYUV(srcFormat) && !isSemiPlanarYUV(dstFormat))) { if (isPacked(c->srcFormat)) c->swscale = packedCopyWrapper; From 1160d1d47887353c5afa4f5e8a18b56bd775501e Mon Sep 17 00:00:00 2001 From: Jerome Borsboom Date: Sun, 25 Feb 2018 20:09:46 +0100 Subject: [PATCH 2016/2557] avcodec/vc1: add bitstream elements for VAAPI VC-1 interlaced decoding We need to pass more bitstream elements to the VAAPI VC-1 decoder in order to start doing interlaced decoding in hardware. Signed-off-by: Jerome Borsboom --- libavcodec/vc1.c | 95 +++++++++++++++++++++++++----------------------- libavcodec/vc1.h | 6 +++ 2 files changed, 55 insertions(+), 46 deletions(-) diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c index 48a2cc1e48949..2b9f8db3ee977 100644 --- a/libavcodec/vc1.c +++ b/libavcodec/vc1.c @@ -629,7 +629,7 @@ int ff_vc1_parse_frame_header(VC1Context *v, GetBitContext* gb) int pqindex, lowquant, status; v->field_mode = 0; - v->fcm = 0; + v->fcm = PROGRESSIVE; if (v->finterpflag) v->interpfrm = get_bits1(gb); if (!v->s.avctx->codec) @@ -766,7 +766,8 @@ int ff_vc1_parse_frame_header(VC1Context *v, GetBitContext* gb) /* Hopefully this is correct for P-frames */ v->s.mv_table_index = get_bits(gb, 2); //but using ff_vc1_ tables - v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[get_bits(gb, 2)]; + v->cbptab = get_bits(gb, 2); + v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[v->cbptab]; if (v->dquant) { av_log(v->s.avctx, AV_LOG_DEBUG, "VOP DQuant info\n"); @@ -804,7 +805,8 @@ int ff_vc1_parse_frame_header(VC1Context *v, GetBitContext* gb) "Imode: %i, Invert: %i\n", status>>1, status&1); v->s.mv_table_index = get_bits(gb, 2); - v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[get_bits(gb, 2)]; + v->cbptab = get_bits(gb, 2); + v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[v->cbptab]; if (v->dquant) { av_log(v->s.avctx, AV_LOG_DEBUG, "VOP DQuant info\n"); @@ -845,7 +847,6 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) { int pqindex, lowquant; int status; - int mbmodetab, imvtab, icbptab, twomvbptab, fourmvbptab; /* useful only for debugging */ int field_mode, fcm; v->numref = 0; @@ -1056,21 +1057,21 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) status = bitplane_decoding(v->s.mbskip_table, &v->skip_is_raw, v); av_log(v->s.avctx, AV_LOG_DEBUG, "SKIPMB plane encoding: " "Imode: %i, Invert: %i\n", status>>1, status&1); - mbmodetab = get_bits(gb, 2); + v->mbmodetab = get_bits(gb, 2); if (v->fourmvswitch) - v->mbmode_vlc = &ff_vc1_intfr_4mv_mbmode_vlc[mbmodetab]; + v->mbmode_vlc = &ff_vc1_intfr_4mv_mbmode_vlc[v->mbmodetab]; else - v->mbmode_vlc = &ff_vc1_intfr_non4mv_mbmode_vlc[mbmodetab]; - imvtab = get_bits(gb, 2); - v->imv_vlc = &ff_vc1_1ref_mvdata_vlc[imvtab]; + v->mbmode_vlc = &ff_vc1_intfr_non4mv_mbmode_vlc[v->mbmodetab]; + v->imvtab = get_bits(gb, 2); + v->imv_vlc = &ff_vc1_1ref_mvdata_vlc[v->imvtab]; // interlaced p-picture cbpcy range is [1, 63] - icbptab = get_bits(gb, 3); - v->cbpcy_vlc = &ff_vc1_icbpcy_vlc[icbptab]; - twomvbptab = get_bits(gb, 2); - v->twomvbp_vlc = &ff_vc1_2mv_block_pattern_vlc[twomvbptab]; + v->icbptab = get_bits(gb, 3); + v->cbpcy_vlc = &ff_vc1_icbpcy_vlc[v->icbptab]; + v->twomvbptab = get_bits(gb, 2); + v->twomvbp_vlc = &ff_vc1_2mv_block_pattern_vlc[v->twomvbptab]; if (v->fourmvswitch) { - fourmvbptab = get_bits(gb, 2); - v->fourmvbp_vlc = &ff_vc1_4mv_block_pattern_vlc[fourmvbptab]; + v->fourmvbptab = get_bits(gb, 2); + v->fourmvbp_vlc = &ff_vc1_4mv_block_pattern_vlc[v->fourmvbptab]; } } } @@ -1154,27 +1155,28 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) /* Hopefully this is correct for P-frames */ v->s.mv_table_index = get_bits(gb, 2); //but using ff_vc1_ tables - v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[get_bits(gb, 2)]; + v->cbptab = get_bits(gb, 2); + v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[v->cbptab]; } else if (v->fcm == ILACE_FRAME) { // frame interlaced v->qs_last = v->s.quarter_sample; v->s.quarter_sample = 1; v->s.mspel = 1; } else { // field interlaced - mbmodetab = get_bits(gb, 3); - imvtab = get_bits(gb, 2 + v->numref); + v->mbmodetab = get_bits(gb, 3); + v->imvtab = get_bits(gb, 2 + v->numref); if (!v->numref) - v->imv_vlc = &ff_vc1_1ref_mvdata_vlc[imvtab]; + v->imv_vlc = &ff_vc1_1ref_mvdata_vlc[v->imvtab]; else - v->imv_vlc = &ff_vc1_2ref_mvdata_vlc[imvtab]; - icbptab = get_bits(gb, 3); - v->cbpcy_vlc = &ff_vc1_icbpcy_vlc[icbptab]; + v->imv_vlc = &ff_vc1_2ref_mvdata_vlc[v->imvtab]; + v->icbptab = get_bits(gb, 3); + v->cbpcy_vlc = &ff_vc1_icbpcy_vlc[v->icbptab]; if ((v->mv_mode == MV_PMODE_INTENSITY_COMP && v->mv_mode2 == MV_PMODE_MIXED_MV) || v->mv_mode == MV_PMODE_MIXED_MV) { - fourmvbptab = get_bits(gb, 2); - v->fourmvbp_vlc = &ff_vc1_4mv_block_pattern_vlc[fourmvbptab]; - v->mbmode_vlc = &ff_vc1_if_mmv_mbmode_vlc[mbmodetab]; + v->fourmvbptab = get_bits(gb, 2); + v->fourmvbp_vlc = &ff_vc1_4mv_block_pattern_vlc[v->fourmvbptab]; + v->mbmode_vlc = &ff_vc1_if_mmv_mbmode_vlc[v->mbmodetab]; } else { - v->mbmode_vlc = &ff_vc1_if_1mv_mbmode_vlc[mbmodetab]; + v->mbmode_vlc = &ff_vc1_if_1mv_mbmode_vlc[v->mbmodetab]; } } if (v->dquant) { @@ -1228,18 +1230,18 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) return -1; av_log(v->s.avctx, AV_LOG_DEBUG, "MB Forward Type plane encoding: " "Imode: %i, Invert: %i\n", status>>1, status&1); - mbmodetab = get_bits(gb, 3); + v->mbmodetab = get_bits(gb, 3); if (v->mv_mode == MV_PMODE_MIXED_MV) - v->mbmode_vlc = &ff_vc1_if_mmv_mbmode_vlc[mbmodetab]; + v->mbmode_vlc = &ff_vc1_if_mmv_mbmode_vlc[v->mbmodetab]; else - v->mbmode_vlc = &ff_vc1_if_1mv_mbmode_vlc[mbmodetab]; - imvtab = get_bits(gb, 3); - v->imv_vlc = &ff_vc1_2ref_mvdata_vlc[imvtab]; - icbptab = get_bits(gb, 3); - v->cbpcy_vlc = &ff_vc1_icbpcy_vlc[icbptab]; + v->mbmode_vlc = &ff_vc1_if_1mv_mbmode_vlc[v->mbmodetab]; + v->imvtab = get_bits(gb, 3); + v->imv_vlc = &ff_vc1_2ref_mvdata_vlc[v->imvtab]; + v->icbptab = get_bits(gb, 3); + v->cbpcy_vlc = &ff_vc1_icbpcy_vlc[v->icbptab]; if (v->mv_mode == MV_PMODE_MIXED_MV) { - fourmvbptab = get_bits(gb, 2); - v->fourmvbp_vlc = &ff_vc1_4mv_block_pattern_vlc[fourmvbptab]; + v->fourmvbptab = get_bits(gb, 2); + v->fourmvbp_vlc = &ff_vc1_4mv_block_pattern_vlc[v->fourmvbptab]; } v->numref = 1; // interlaced field B pictures are always 2-ref } else if (v->fcm == ILACE_FRAME) { @@ -1263,17 +1265,17 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) return -1; av_log(v->s.avctx, AV_LOG_DEBUG, "MB Skip plane encoding: " "Imode: %i, Invert: %i\n", status>>1, status&1); - mbmodetab = get_bits(gb, 2); - v->mbmode_vlc = &ff_vc1_intfr_non4mv_mbmode_vlc[mbmodetab]; - imvtab = get_bits(gb, 2); - v->imv_vlc = &ff_vc1_1ref_mvdata_vlc[imvtab]; + v->mbmodetab = get_bits(gb, 2); + v->mbmode_vlc = &ff_vc1_intfr_non4mv_mbmode_vlc[v->mbmodetab]; + v->imvtab = get_bits(gb, 2); + v->imv_vlc = &ff_vc1_1ref_mvdata_vlc[v->imvtab]; // interlaced p/b-picture cbpcy range is [1, 63] - icbptab = get_bits(gb, 3); - v->cbpcy_vlc = &ff_vc1_icbpcy_vlc[icbptab]; - twomvbptab = get_bits(gb, 2); - v->twomvbp_vlc = &ff_vc1_2mv_block_pattern_vlc[twomvbptab]; - fourmvbptab = get_bits(gb, 2); - v->fourmvbp_vlc = &ff_vc1_4mv_block_pattern_vlc[fourmvbptab]; + v->icbptab = get_bits(gb, 3); + v->cbpcy_vlc = &ff_vc1_icbpcy_vlc[v->icbptab]; + v->twomvbptab = get_bits(gb, 2); + v->twomvbp_vlc = &ff_vc1_2mv_block_pattern_vlc[v->twomvbptab]; + v->fourmvbptab = get_bits(gb, 2); + v->fourmvbp_vlc = &ff_vc1_4mv_block_pattern_vlc[v->fourmvbptab]; } else { v->mv_mode = get_bits1(gb) ? MV_PMODE_1MV : MV_PMODE_1MV_HPEL_BILIN; v->qs_last = v->s.quarter_sample; @@ -1290,7 +1292,8 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) av_log(v->s.avctx, AV_LOG_DEBUG, "MB Skip plane encoding: " "Imode: %i, Invert: %i\n", status>>1, status&1); v->s.mv_table_index = get_bits(gb, 2); - v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[get_bits(gb, 2)]; + v->cbptab = get_bits(gb, 2); + v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[v->cbptab]; } if (v->dquant) { diff --git a/libavcodec/vc1.h b/libavcodec/vc1.h index 556906d496189..8fc0729cb8bb9 100644 --- a/libavcodec/vc1.h +++ b/libavcodec/vc1.h @@ -296,6 +296,7 @@ typedef struct VC1Context{ uint8_t (*curr_luty)[256] ,(*curr_lutuv)[256]; int last_use_ic, *curr_use_ic, next_use_ic, aux_use_ic; int rnd; ///< rounding control + int cbptab; /** Frame decoding info for S/M profiles only */ //@{ @@ -367,6 +368,11 @@ typedef struct VC1Context{ int frfd, brfd; ///< reference frame distance (forward or backward) int first_pic_header_flag; int pic_header_flag; + int mbmodetab; + int icbptab; + int imvtab; + int twomvbptab; + int fourmvbptab; /** Frame decoding info for sprite modes */ //@{ From 883bdc5fb7c4f579eba1c10e01487b08601ec0be Mon Sep 17 00:00:00 2001 From: Jerome Borsboom Date: Thu, 1 Mar 2018 09:07:17 +0100 Subject: [PATCH 2017/2557] avcodec/vaapi: add fields for VAAPI VC-1 interlaced decoding Pass necessary bitstream elements to the VAAPI VC-1 decoder in order to start doing interlaced decoding in hardware. Signed-off-by: Jerome Borsboom --- libavcodec/vaapi_vc1.c | 163 +++++++++++++++++++++++++++++++++-------- 1 file changed, 134 insertions(+), 29 deletions(-) diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c index 525376790ec3a..97b23917f6f4b 100644 --- a/libavcodec/vaapi_vc1.c +++ b/libavcodec/vaapi_vc1.c @@ -44,7 +44,8 @@ static inline int vc1_has_MVTYPEMB_bitplane(const VC1Context *v) { if (v->mv_type_is_raw) return 0; - return v->s.pict_type == AV_PICTURE_TYPE_P && + return v->fcm == PROGRESSIVE && + (v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) && (v->mv_mode == MV_PMODE_MIXED_MV || (v->mv_mode == MV_PMODE_INTENSITY_COMP && v->mv_mode2 == MV_PMODE_MIXED_MV)); @@ -55,8 +56,9 @@ static inline int vc1_has_SKIPMB_bitplane(const VC1Context *v) { if (v->skip_is_raw) return 0; - return v->s.pict_type == AV_PICTURE_TYPE_P || - (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type); + return (v->fcm == PROGRESSIVE || v->fcm == ILACE_FRAME) && + ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) || + (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type)); } /** Check whether the DIRECTMB bitplane is present */ @@ -64,7 +66,8 @@ static inline int vc1_has_DIRECTMB_bitplane(const VC1Context *v) { if (v->dmb_is_raw) return 0; - return v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type; + return (v->fcm == PROGRESSIVE || v->fcm == ILACE_FRAME) && + (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type); } /** Check whether the ACPRED bitplane is present */ @@ -89,6 +92,25 @@ static inline int vc1_has_OVERFLAGS_bitplane(const VC1Context *v) v->condover == CONDOVER_SELECT; } +/** Check whether the FIELDTX bitplane is present */ +static inline int vc1_has_FIELDTX_bitplane(const VC1Context *v) +{ + if (v->fieldtx_is_raw) + return 0; + return v->fcm == ILACE_FRAME && + (v->s.pict_type == AV_PICTURE_TYPE_I || + (v->s.pict_type == AV_PICTURE_TYPE_B && v->bi_type)); +} + +/** Check whether the FORWARDMB bitplane is present */ +static inline int vc1_has_FORWARDMB_bitplane(const VC1Context *v) +{ + if (v->fmb_is_raw) + return 0; + return v->fcm == ILACE_FIELD && + (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type); +} + /** Reconstruct bitstream PTYPE (7.1.1.4, index into Table-35) */ static int vc1_get_PTYPE(const VC1Context *v) { @@ -101,10 +123,22 @@ static int vc1_get_PTYPE(const VC1Context *v) return 0; } +/** Reconstruct bitstream FPTYPE (9.1.1.42, index into Table-105) */ +static int vc1_get_FPTYPE(const VC1Context *v) +{ + const MpegEncContext *s = &v->s; + switch (s->pict_type) { + case AV_PICTURE_TYPE_I: return 0; + case AV_PICTURE_TYPE_P: return 3; + case AV_PICTURE_TYPE_B: return v->bi_type ? 7 : 4; + } + return 0; +} + /** Reconstruct bitstream MVMODE (7.1.1.32) */ static inline VAMvModeVC1 vc1_get_MVMODE(const VC1Context *v) { - if (v->s.pict_type == AV_PICTURE_TYPE_P || + if ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) || (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type)) return get_VAMvModeVC1(v->mv_mode); return 0; @@ -113,11 +147,77 @@ static inline VAMvModeVC1 vc1_get_MVMODE(const VC1Context *v) /** Reconstruct bitstream MVMODE2 (7.1.1.33) */ static inline VAMvModeVC1 vc1_get_MVMODE2(const VC1Context *v) { - if (v->s.pict_type == AV_PICTURE_TYPE_P && v->mv_mode == MV_PMODE_INTENSITY_COMP) + if ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) && + v->mv_mode == MV_PMODE_INTENSITY_COMP) return get_VAMvModeVC1(v->mv_mode2); return 0; } +av_unused static inline int vc1_get_INTCOMPFIELD(const VC1Context *v) +{ + if ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) && + v->fcm == ILACE_FIELD && + v->mv_mode == MV_PMODE_INTENSITY_COMP) + switch (v->intcompfield) { + case 1: return 1; + case 2: return 2; + case 3: return 0; + } + return 0; +} + +static inline int vc1_get_LUMSCALE(const VC1Context *v) +{ + if (v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) { + if ((v->fcm == PROGRESSIVE && v->mv_mode == MV_PMODE_INTENSITY_COMP) || + (v->fcm == ILACE_FRAME && v->intcomp)) + return v->lumscale; + else if (v->fcm == ILACE_FIELD && v->mv_mode == MV_PMODE_INTENSITY_COMP) + switch (v->intcompfield) { + case 1: return v->lumscale; + case 2: return v->lumscale2; + case 3: return v->lumscale; + } + } + return 0; +} + +static inline int vc1_get_LUMSHIFT(const VC1Context *v) +{ + if (v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) { + if ((v->fcm == PROGRESSIVE && v->mv_mode == MV_PMODE_INTENSITY_COMP) || + (v->fcm == ILACE_FRAME && v->intcomp)) + return v->lumshift; + else if (v->fcm == ILACE_FIELD && v->mv_mode == MV_PMODE_INTENSITY_COMP) + switch (v->intcompfield) { + case 1: return v->lumshift; + case 2: return v->lumshift2; + case 3: return v->lumshift; + } + } + return 0; +} + +av_unused static inline int vc1_get_LUMSCALE2(const VC1Context *v) +{ + if ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) && + v->fcm == ILACE_FIELD && + v->mv_mode == MV_PMODE_INTENSITY_COMP && + v->intcompfield == 3) + return v->lumscale2; + return 0; +} + +av_unused static inline int vc1_get_LUMSHIFT2(const VC1Context *v) +{ + if ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) && + v->fcm == ILACE_FIELD && + v->mv_mode == MV_PMODE_INTENSITY_COMP && + v->intcompfield == 3) + return v->lumshift2; + return 0; +} + /** Reconstruct bitstream TTFRM (7.1.1.41, Table-53) */ static inline int vc1_get_TTFRM(const VC1Context *v) { @@ -189,27 +289,32 @@ static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t .chroma = v->range_mapuv, }, .b_picture_fraction = v->bfraction_lut_index, - .cbp_table = v->cbpcy_vlc ? v->cbpcy_vlc - ff_vc1_cbpcy_p_vlc : 0, - .mb_mode_table = 0, /* XXX: interlaced frame */ + .cbp_table = (v->fcm == PROGRESSIVE ? v->cbptab : v->icbptab), + .mb_mode_table = v->mbmodetab, .range_reduction_frame = v->rangeredfrm, .rounding_control = v->rnd, .post_processing = v->postproc, .picture_resolution_index = v->respic, - .luma_scale = v->lumscale, - .luma_shift = v->lumshift, .picture_fields.bits = { - .picture_type = vc1_get_PTYPE(v), + .picture_type = (v->fcm == ILACE_FIELD ? vc1_get_FPTYPE(v) : vc1_get_PTYPE(v)), .frame_coding_mode = v->fcm, .top_field_first = v->tff, - .is_first_field = v->fcm == 0, /* XXX: interlaced frame */ - .intensity_compensation = v->mv_mode == MV_PMODE_INTENSITY_COMP, + .is_first_field = !v->second_field, + .intensity_compensation = v->intcomp, }, + .luma_scale = vc1_get_LUMSCALE(v), + .luma_shift = vc1_get_LUMSHIFT(v), +#if VA_CHECK_VERSION(1, 1, 0) + .luma_scale2 = vc1_get_LUMSCALE2(v), + .luma_shift2 = vc1_get_LUMSHIFT2(v), + .intensity_compensation_field = vc1_get_INTCOMPFIELD(v), +#endif .raw_coding.flags = { .mv_type_mb = v->mv_type_is_raw, .direct_mb = v->dmb_is_raw, .skip_mb = v->skip_is_raw, - .field_tx = 0, /* XXX: interlaced frame */ - .forward_mb = 0, /* XXX: interlaced frame */ + .field_tx = v->fieldtx_is_raw, + .forward_mb = v->fmb_is_raw, .ac_pred = v->acpred_is_raw, .overflags = v->overflg_is_raw, }, @@ -217,28 +322,28 @@ static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t .bp_mv_type_mb = vc1_has_MVTYPEMB_bitplane(v), .bp_direct_mb = vc1_has_DIRECTMB_bitplane(v), .bp_skip_mb = vc1_has_SKIPMB_bitplane(v), - .bp_field_tx = 0, /* XXX: interlaced frame */ - .bp_forward_mb = 0, /* XXX: interlaced frame */ + .bp_field_tx = vc1_has_FIELDTX_bitplane(v), + .bp_forward_mb = vc1_has_FORWARDMB_bitplane(v), .bp_ac_pred = vc1_has_ACPRED_bitplane(v), .bp_overflags = vc1_has_OVERFLAGS_bitplane(v), }, .reference_fields.bits = { .reference_distance_flag = v->refdist_flag, - .reference_distance = 0, /* XXX: interlaced frame */ - .num_reference_pictures = 0, /* XXX: interlaced frame */ - .reference_field_pic_indicator = 0, /* XXX: interlaced frame */ + .reference_distance = v->refdist, + .num_reference_pictures = v->numref, + .reference_field_pic_indicator = v->reffield, }, .mv_fields.bits = { .mv_mode = vc1_get_MVMODE(v), .mv_mode2 = vc1_get_MVMODE2(v), - .mv_table = s->mv_table_index, - .two_mv_block_pattern_table = 0, /* XXX: interlaced frame */ - .four_mv_switch = 0, /* XXX: interlaced frame */ - .four_mv_block_pattern_table = 0, /* XXX: interlaced frame */ + .mv_table = (v->fcm == PROGRESSIVE ? s->mv_table_index : v->imvtab), + .two_mv_block_pattern_table = v->twomvbptab, + .four_mv_switch = v->fourmvswitch, + .four_mv_block_pattern_table = v->fourmvbptab, .extended_mv_flag = v->extended_mv, .extended_mv_range = v->mvrange, .extended_dmv_flag = v->extended_dmv, - .extended_dmv_range = 0, /* XXX: interlaced frame */ + .extended_dmv_range = v->dmvrange, }, .pic_quantizer_fields.bits = { .dquant = v->dquant, @@ -298,14 +403,14 @@ static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t break; case AV_PICTURE_TYPE_B: if (!v->bi_type) { - ff_bp[0] = pic_param.bitplane_present.flags.bp_direct_mb ? v->direct_mb_plane : NULL; - ff_bp[1] = pic_param.bitplane_present.flags.bp_skip_mb ? s->mbskip_table : NULL; - ff_bp[2] = NULL; /* XXX: interlaced frame (FORWARD plane) */ + ff_bp[0] = pic_param.bitplane_present.flags.bp_direct_mb ? v->direct_mb_plane : NULL; + ff_bp[1] = pic_param.bitplane_present.flags.bp_skip_mb ? s->mbskip_table : NULL; + ff_bp[2] = pic_param.bitplane_present.flags.bp_forward_mb ? v->forward_mb_plane : NULL; break; } /* fall-through (BI-type) */ case AV_PICTURE_TYPE_I: - ff_bp[0] = NULL; /* XXX: interlaced frame (FIELDTX plane) */ + ff_bp[0] = pic_param.bitplane_present.flags.bp_field_tx ? v->fieldtx_plane : NULL; ff_bp[1] = pic_param.bitplane_present.flags.bp_ac_pred ? v->acpred_plane : NULL; ff_bp[2] = pic_param.bitplane_present.flags.bp_overflags ? v->over_flags_plane : NULL; break; From 0ec7eb930520b21b9cda34809378b0a8ca3a46e2 Mon Sep 17 00:00:00 2001 From: Jerome Borsboom Date: Sun, 25 Feb 2018 20:13:46 +0100 Subject: [PATCH 2018/2557] avcodec/vaapi: mask unused bits in bitplane_present.value Due to the union construct, unused bits in bitplane_present.value might be uninitialized even when the used bits are all set to a value. Masking the unused bits prevents spurious true values when all used bits are unset, e.g. skipped pictures. Signed-off-by: Jerome Borsboom --- libavcodec/vaapi_vc1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c index 97b23917f6f4b..74ba7831416de 100644 --- a/libavcodec/vaapi_vc1.c +++ b/libavcodec/vaapi_vc1.c @@ -383,7 +383,7 @@ static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t if (err) goto fail; - if (pic_param.bitplane_present.value) { + if (pic_param.bitplane_present.value & 0x7f) { uint8_t *bitplane; const uint8_t *ff_bp[3]; int x, y, n; From 133ddd38750acc01d0a9599d5b31375d33798d67 Mon Sep 17 00:00:00 2001 From: Matt Wolenetz Date: Fri, 2 Mar 2018 15:12:41 -0800 Subject: [PATCH 2019/2557] avformat/mov: Initialize a potential gap in ctts_data in mov_build_index mov_read_ctts ignores ctts entries having count <= 0. Generally, the aggregate of all ctts entries' count fields resulting from mov_read_ctts can be less than the corresponding sample_count. mov_build_index attempts to normalize any existing ctts_data counts to be 1, to make a 1-1 mapping of a ctts_data entry to a sample. That 1-1 mapping left a tail of uninitialized ctts_data entries when the aggregate, normalized ctts_count < sample_count. Even more generally, later usage of ctts_data may depend on the entire ctts_allocated_size having been initialized. This change memsets the entire allocation of the normalized ctts_data in mov_build_index, to prevent use of uninitialized data later. BUG=816787 Change-Id: I7fd7db255e3aeed076ee32c90cb2df211741c052 Reviewed-on: https://chromium-review.googlesource.com/947110 Reviewed-by: Xiaohan Wang Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index 00b3b2594459c..95b9cd3f8bafa 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3747,6 +3747,9 @@ static void mov_build_index(MOVContext *mov, AVStream *st) av_free(ctts_data_old); return; } + + memset((uint8_t*)(sc->ctts_data), 0, sc->ctts_allocated_size); + for (i = 0; i < ctts_count_old && sc->ctts_count < sc->sample_count; i++) for (j = 0; j < ctts_data_old[i].count && From a194e9c4159845fc5f3410272e7cd6c4356bb2e7 Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Mon, 12 Feb 2018 11:11:23 +0100 Subject: [PATCH 2020/2557] fftools/ffmpeg: fix progress log message in case pts is not available Also fixes sign prefix for progress report. Signed-off-by: Tobias Rapp --- fftools/ffmpeg.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 3a45f43c1db6a..fa2f48f551e04 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1650,6 +1650,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti static int64_t last_time = -1; static int qp_histogram[52]; int hours, mins, secs, us; + const char *hours_sign; int ret; float t; @@ -1757,6 +1758,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti secs %= 60; hours = mins / 60; mins %= 60; + hours_sign = (pts < 0) ? "-" : ""; bitrate = pts && total_size >= 0 ? total_size * 8 / (pts / 1000.0) : -1; speed = t != 0.0 ? (double)pts / AV_TIME_BASE / t : -1; @@ -1765,11 +1767,13 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti "size=N/A time="); else snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "size=%8.0fkB time=", total_size / 1024.0); - if (pts < 0) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "-"); - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "%02d:%02d:%02d.%02d ", hours, mins, secs, - (100 * us) / AV_TIME_BASE); + if (pts == AV_NOPTS_VALUE) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "N/A "); + } else { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + "%s%02d:%02d:%02d.%02d ", hours_sign, hours, mins, secs, + (100 * us) / AV_TIME_BASE); + } if (bitrate < 0) { snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),"bitrate=N/A"); @@ -1781,9 +1785,14 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti if (total_size < 0) av_bprintf(&buf_script, "total_size=N/A\n"); else av_bprintf(&buf_script, "total_size=%"PRId64"\n", total_size); - av_bprintf(&buf_script, "out_time_ms=%"PRId64"\n", pts); - av_bprintf(&buf_script, "out_time=%02d:%02d:%02d.%06d\n", - hours, mins, secs, us); + if (pts == AV_NOPTS_VALUE) { + av_bprintf(&buf_script, "out_time_ms=N/A\n"); + av_bprintf(&buf_script, "out_time=N/A\n"); + } else { + av_bprintf(&buf_script, "out_time_ms=%"PRId64"\n", pts); + av_bprintf(&buf_script, "out_time=%s%02d:%02d:%02d.%06d\n", + hours_sign, hours, mins, secs, us); + } if (nb_frames_dup || nb_frames_drop) snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d", From 69995a94d8409a704361dce9bc16ede7f88bdf1a Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Mon, 26 Feb 2018 15:13:29 +0100 Subject: [PATCH 2021/2557] fftools/ffmpeg: update print_report to use AVBPrint API Signed-off-by: Tobias Rapp --- fftools/ffmpeg.c | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index fa2f48f551e04..ee7258fcd1f65 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1637,8 +1637,7 @@ static void print_final_stats(int64_t total_size) static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time) { - char buf[1024]; - AVBPrint buf_script; + AVBPrint buf, buf_script; OutputStream *ost; AVFormatContext *oc; int64_t total_size; @@ -1676,8 +1675,8 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti if (total_size <= 0) // FIXME improve avio_size() so it works with non seekable output too total_size = avio_tell(oc->pb); - buf[0] = '\0'; vid = 0; + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC); av_bprint_init(&buf_script, 0, 1); for (i = 0; i < nb_output_streams; i++) { float q = -1; @@ -1687,7 +1686,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti q = ost->quality / (float) FF_QP2LAMBDA; if (vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", q); + av_bprintf(&buf, "q=%2.1f ", q); av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n", ost->file_index, ost->index, q); } @@ -1696,21 +1695,21 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti frame_number = ost->frame_number; fps = t > 1 ? frame_number / t : 0; - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3.*f q=%3.1f ", + av_bprintf(&buf, "frame=%5d fps=%3.*f q=%3.1f ", frame_number, fps < 9.95, fps, q); av_bprintf(&buf_script, "frame=%d\n", frame_number); av_bprintf(&buf_script, "fps=%.1f\n", fps); av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n", ost->file_index, ost->index, q); if (is_last_report) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L"); + av_bprintf(&buf, "L"); if (qp_hist) { int j; int qp = lrintf(q); if (qp >= 0 && qp < FF_ARRAY_ELEMS(qp_histogram)) qp_histogram[qp]++; for (j = 0; j < 32; j++) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%X", av_log2(qp_histogram[j] + 1)); + av_bprintf(&buf, "%X", av_log2(qp_histogram[j] + 1)); } if ((enc->flags & AV_CODEC_FLAG_PSNR) && (ost->pict_type != AV_PICTURE_TYPE_NONE || is_last_report)) { @@ -1719,7 +1718,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti double scale, scale_sum = 0; double p; char type[3] = { 'Y','U','V' }; - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "PSNR="); + av_bprintf(&buf, "PSNR="); for (j = 0; j < 3; j++) { if (is_last_report) { error = enc->error[j]; @@ -1733,12 +1732,12 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti error_sum += error; scale_sum += scale; p = psnr(error / scale); - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%c:%2.2f ", type[j], p); + av_bprintf(&buf, "%c:%2.2f ", type[j], p); av_bprintf(&buf_script, "stream_%d_%d_psnr_%c=%2.2f\n", ost->file_index, ost->index, type[j] | 32, p); } p = psnr(error_sum / scale_sum); - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "*:%2.2f ", psnr(error_sum / scale_sum)); + av_bprintf(&buf, "*:%2.2f ", psnr(error_sum / scale_sum)); av_bprintf(&buf_script, "stream_%d_%d_psnr_all=%2.2f\n", ost->file_index, ost->index, p); } @@ -1763,23 +1762,20 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti bitrate = pts && total_size >= 0 ? total_size * 8 / (pts / 1000.0) : -1; speed = t != 0.0 ? (double)pts / AV_TIME_BASE / t : -1; - if (total_size < 0) snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "size=N/A time="); - else snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "size=%8.0fkB time=", total_size / 1024.0); + if (total_size < 0) av_bprintf(&buf, "size=N/A time="); + else av_bprintf(&buf, "size=%8.0fkB time=", total_size / 1024.0); if (pts == AV_NOPTS_VALUE) { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "N/A "); + av_bprintf(&buf, "N/A "); } else { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "%s%02d:%02d:%02d.%02d ", hours_sign, hours, mins, secs, - (100 * us) / AV_TIME_BASE); + av_bprintf(&buf, "%s%02d:%02d:%02d.%02d ", + hours_sign, hours, mins, secs, (100 * us) / AV_TIME_BASE); } if (bitrate < 0) { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),"bitrate=N/A"); + av_bprintf(&buf, "bitrate=N/A"); av_bprintf(&buf_script, "bitrate=N/A\n"); }else{ - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),"bitrate=%6.1fkbits/s", bitrate); + av_bprintf(&buf, "bitrate=%6.1fkbits/s", bitrate); av_bprintf(&buf_script, "bitrate=%6.1fkbits/s\n", bitrate); } @@ -1795,28 +1791,28 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti } if (nb_frames_dup || nb_frames_drop) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d", - nb_frames_dup, nb_frames_drop); + av_bprintf(&buf, " dup=%d drop=%d", nb_frames_dup, nb_frames_drop); av_bprintf(&buf_script, "dup_frames=%d\n", nb_frames_dup); av_bprintf(&buf_script, "drop_frames=%d\n", nb_frames_drop); if (speed < 0) { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf)," speed=N/A"); + av_bprintf(&buf, " speed=N/A"); av_bprintf(&buf_script, "speed=N/A\n"); } else { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf)," speed=%4.3gx", speed); + av_bprintf(&buf, " speed=%4.3gx", speed); av_bprintf(&buf_script, "speed=%4.3gx\n", speed); } if (print_stats || is_last_report) { const char end = is_last_report ? '\n' : '\r'; if (print_stats==1 && AV_LOG_INFO > av_log_get_level()) { - fprintf(stderr, "%s %c", buf, end); + fprintf(stderr, "%s %c", buf.str, end); } else - av_log(NULL, AV_LOG_INFO, "%s %c", buf, end); + av_log(NULL, AV_LOG_INFO, "%s %c", buf.str, end); fflush(stderr); } + av_bprint_finalize(&buf, NULL); if (progress_avio) { av_bprintf(&buf_script, "progress=%s\n", From 2d6b3f3a9dce409ca51d70ef4b85c0593bb4b109 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Fri, 2 Mar 2018 11:26:27 +0800 Subject: [PATCH 2022/2557] qsvenc: Provide a detailed error message if the parameters are invalid Currently it always shows "Selected ratecontrol mode is not supported by the QSV runtime. Choose a different mode", but sometimes it is not accurate. Signed-off-by: Zhong Li Signed-off-by: Luca Barbato --- libavcodec/qsvenc.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 16d942f00aa3c..d4dd4a3b94aa3 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -356,15 +356,34 @@ static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) return 0; } -static int rc_supported(QSVEncContext *q) +static int check_enc_param(AVCodecContext *avctx, QSVEncContext *q) { mfxVideoParam param_out = { .mfx.CodecId = q->param.mfx.CodecId }; mfxStatus ret; +#define UNMATCH(x) (param_out.mfx.x != q->param.mfx.x) + ret = MFXVideoENCODE_Query(q->session, &q->param, ¶m_out); - if (ret < 0 || - param_out.mfx.RateControlMethod != q->param.mfx.RateControlMethod) + + if (ret < 0) { + if (UNMATCH(CodecId)) + av_log(avctx, AV_LOG_ERROR, "Current codec type is unsupported\n"); + if (UNMATCH(CodecProfile)) + av_log(avctx, AV_LOG_ERROR, "Current profile is unsupported\n"); + if (UNMATCH(RateControlMethod)) + av_log(avctx, AV_LOG_ERROR, "Selected ratecontrol mode is unsupported\n"); + if (UNMATCH(LowPower)) + av_log(avctx, AV_LOG_ERROR, "Low power mode is unsupported\n"); + if (UNMATCH(FrameInfo.FrameRateExtN) || UNMATCH(FrameInfo.FrameRateExtN)) + av_log(avctx, AV_LOG_ERROR, "Current frame rate is unsupported\n"); + if (UNMATCH(FrameInfo.PicStruct)) + av_log(avctx, AV_LOG_ERROR, "Current picture structure is unsupported\n"); + if (UNMATCH(FrameInfo.Width) || UNMATCH(FrameInfo.Height)) + av_log(avctx, AV_LOG_ERROR, "Current resolution is unsupported\n"); + if (UNMATCH(FrameInfo.FourCC)) + av_log(avctx, AV_LOG_ERROR, "Current pixel format is unsupported\n"); return 0; + } return 1; } @@ -639,10 +658,10 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif } - if (!rc_supported(q)) { + if (!check_enc_param(avctx,q)) { av_log(avctx, AV_LOG_ERROR, - "Selected ratecontrol mode is not supported by the QSV " - "runtime. Choose a different mode.\n"); + "some encoding parameters are not supported by the QSV " + "runtime. Please double check the input parameters.\n"); return AVERROR(ENOSYS); } From df3a2ff7670a76c808fa015559b867aecbbdcd54 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 5 Mar 2018 11:04:59 -0300 Subject: [PATCH 2023/2557] avcodec/cbs: use a reference to the assembled CodedBitstreamFragment buffer when writing packets This saves one malloc + memcpy per packet The CodedBitstreamFragment buffer is padded to follow the requirements of AVPacket. Reviewed-by: jkqxz Signed-off-by: James Almer --- libavcodec/cbs.c | 12 ++++++++---- libavcodec/cbs_h2645.c | 8 +++++--- libavcodec/cbs_mpeg2.c | 3 ++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index dcca6430c48c7..62f60be437bcd 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -308,17 +308,21 @@ int ff_cbs_write_packet(CodedBitstreamContext *ctx, AVPacket *pkt, CodedBitstreamFragment *frag) { + AVBufferRef *buf; int err; err = ff_cbs_write_fragment_data(ctx, frag); if (err < 0) return err; - err = av_new_packet(pkt, frag->data_size); - if (err < 0) - return err; + av_assert0(frag->data_ref); + buf = av_buffer_ref(frag->data_ref); + if (!buf) + return AVERROR(ENOMEM); - memcpy(pkt->data, frag->data, frag->data_size); + av_init_packet(pkt); + pkt->buf = buf; + pkt->data = frag->data; pkt->size = frag->data_size; return 0; diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 5ad0f2b500d05..5585831cf61b1 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -1298,7 +1298,7 @@ static int cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx, max_size += 3 + frag->units[i].data_size * 3 / 2; } - data = av_malloc(max_size); + data = av_malloc(max_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!data) return AVERROR(ENOMEM); @@ -1349,11 +1349,13 @@ static int cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx, } av_assert0(dp <= max_size); - err = av_reallocp(&data, dp); + err = av_reallocp(&data, dp + AV_INPUT_BUFFER_PADDING_SIZE); if (err) return err; + memset(data + dp, 0, AV_INPUT_BUFFER_PADDING_SIZE); - frag->data_ref = av_buffer_create(data, dp, NULL, NULL, 0); + frag->data_ref = av_buffer_create(data, dp + AV_INPUT_BUFFER_PADDING_SIZE, + NULL, NULL, 0); if (!frag->data_ref) { av_freep(&data); return AVERROR(ENOMEM); diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index 5bb2e1e107c7e..bfb64a0851192 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -369,7 +369,7 @@ static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx, for (i = 0; i < frag->nb_units; i++) size += 3 + frag->units[i].data_size; - frag->data_ref = av_buffer_alloc(size); + frag->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!frag->data_ref) return AVERROR(ENOMEM); data = frag->data_ref->data; @@ -388,6 +388,7 @@ static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx, av_assert0(dp == size); + memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); frag->data = data; frag->data_size = size; From 5787908e8c63bcb9206a59961031bdb54682ab0a Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sat, 3 Mar 2018 21:28:26 +0100 Subject: [PATCH 2024/2557] configure: rename cuda to ffnvcodec Right now, if someone configures ffmpeg with for example --enable-nvenc they will get an error message complaining about missing cuda. This is very confusing and already has lead people into installing the CUDA SDK, even though it's not what they need. This will make it complain about ffnvcodec instead. Signed-off-by: Timo Rothenpieler --- configure | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/configure b/configure index fe81ba31b5ed7..5e38bdab17cfb 100755 --- a/configure +++ b/configure @@ -307,11 +307,11 @@ External library support: The following libraries provide various hardware acceleration features: --disable-amf disable AMF video encoding code [autodetect] --disable-audiotoolbox disable Apple AudioToolbox code [autodetect] - --disable-cuda disable dynamically linked Nvidia CUDA code [autodetect] --enable-cuda-sdk enable CUDA features that require the CUDA SDK [no] --disable-cuvid disable Nvidia CUVID support [autodetect] --disable-d3d11va disable Microsoft Direct3D 11 video acceleration code [autodetect] --disable-dxva2 disable Microsoft DirectX 9 video acceleration code [autodetect] + --disable-ffnvcodec disable dynamically linked Nvidia code [autodetect] --enable-libdrm enable DRM code (Linux) [no] --enable-libmfx enable Intel MediaSDK (AKA Quick Sync Video) code via libmfx [no] --enable-libnpp enable Nvidia Performance Primitives-based code [no] @@ -1660,6 +1660,7 @@ HWACCEL_AUTODETECT_LIBRARY_LIST=" cuvid d3d11va dxva2 + ffnvcodec nvdec nvenc vaapi @@ -2675,11 +2676,12 @@ zmbv_encoder_deps="zlib" # hardware accelerators crystalhd_deps="libcrystalhd_libcrystalhd_if_h" -cuda_deps_any="libdl LoadLibrary" -cuvid_deps="cuda" +cuda_deps="ffnvcodec" +cuvid_deps="ffnvcodec" d3d11va_deps="dxva_h ID3D11VideoDecoder ID3D11VideoContext" dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" -nvdec_deps="cuda" +ffnvcodec_deps_any="libdl LoadLibrary" +nvdec_deps="ffnvcodec" videotoolbox_hwaccel_deps="videotoolbox pthreads" videotoolbox_hwaccel_extralibs="-framework QuartzCore" xvmc_deps="X11_extensions_XvMClib_h" @@ -2797,13 +2799,13 @@ qsvvpp_select="qsv" vaapi_encode_deps="vaapi" v4l2_m2m_deps_any="linux_videodev2_h" -hwupload_cuda_filter_deps="cuda" -scale_npp_filter_deps="cuda libnpp" +hwupload_cuda_filter_deps="ffnvcodec" +scale_npp_filter_deps="ffnvcodec libnpp" scale_cuda_filter_deps="cuda_sdk" thumbnail_cuda_filter_deps="cuda_sdk" amf_deps_any="libdl LoadLibrary" -nvenc_deps="cuda" +nvenc_deps="ffnvcodec" nvenc_deps_any="libdl LoadLibrary" nvenc_encoder_deps="nvenc" @@ -3357,7 +3359,7 @@ avformat_deps="avcodec avutil" avformat_suggest="libm network zlib" avresample_deps="avutil" avresample_suggest="libm" -avutil_suggest="clock_gettime cuda libm libdrm libmfx opencl user32 vaapi videotoolbox corefoundation corevideo coremedia wincrypt" +avutil_suggest="clock_gettime ffnvcodec libm libdrm libmfx opencl user32 vaapi videotoolbox corefoundation corevideo coremedia wincrypt" postproc_deps="avutil gpl" postproc_suggest="libm" swresample_deps="avutil" @@ -5811,8 +5813,10 @@ check_type "va/va.h va/va_enc_vp9.h" "VAEncPictureParameterBufferVP9" check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC" -check_pkg_config cuda "ffnvcodec >= 8.0.14.1" \ - "ffnvcodec/nvEncodeAPI.h ffnvcodec/dynlink_cuda.h ffnvcodec/dynlink_cuviddec.h ffnvcodec/dynlink_nvcuvid.h" "" +if ! disabled ffnvcodec; then + check_pkg_config ffnvcodec "ffnvcodec >= 8.0.14.1" \ + "ffnvcodec/nvEncodeAPI.h ffnvcodec/dynlink_cuda.h ffnvcodec/dynlink_cuviddec.h ffnvcodec/dynlink_nvcuvid.h" "" +fi check_cpp_condition windows.h "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)" && enable winrt || disable winrt @@ -6257,13 +6261,15 @@ if enabled x86; then mingw32*|mingw64*|win32|win64|linux|cygwin*) ;; *) - disable cuda cuvid nvdec nvenc + disable ffnvcodec cuvid nvdec nvenc ;; esac else - disable cuda cuvid nvdec nvenc + disable ffnvcodec cuvid nvdec nvenc fi +enabled ffnvcodec && enable cuda + enabled nvenc && check_cc -I$source_path < From 8218249f1f04de65904f58519bde21948e5a0783 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 3 Mar 2018 20:17:46 +0000 Subject: [PATCH 2025/2557] parseutils: accept only full "ms" suffix The commit which added those was pushed prematurely before anyone could object to illogical suffixes like just m for milliseconds. Without this, we'd be locked into never being able to implement the "m" suffix for minutes. Signed-off-by: Rostislav Pehlivanov --- libavutil/parseutils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c index 44c845577a9a0..95274f564f2ca 100644 --- a/libavutil/parseutils.c +++ b/libavutil/parseutils.c @@ -689,10 +689,10 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) if (duration) { t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec; - if (*q == 'm') { + if (q[0] == 'm' && q[1] == 's') { suffix = 1000; microseconds /= 1000; - q++; + q += 2; } else if (*q == 'u') { suffix = 1; microseconds = 0; From 0645698ecc2021ec422b625a6c1d235d2f252563 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Thu, 1 Mar 2018 13:20:19 +0800 Subject: [PATCH 2026/2557] lavc/qsvenc: disable h264 look_ahead by default Look_ahead can provide quality improvements, but would better disable it by default due to some reasons: 1. It is only available for some codecs (e.g. HEVC is not supported) on Intel Haswell and plus platforms. Thus means it will be failed on some platforms. 2. It significantly increases encoding latency and memory consumption. 3. It may overwrite some other options such as CBR and CAVLC. Signed-off-by: Zhong Li Signed-off-by: Mark Thompson --- libavcodec/qsvenc_h264.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index 09e4c0e599dd9..e01a2a3369305 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -109,7 +109,7 @@ static const AVOption options[] = { { "max_dec_frame_buffering", "Maximum number of frames buffered in the DPB", OFFSET(qsv.max_dec_frame_buffering), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE }, #if QSV_HAVE_LA - { "look_ahead", "Use VBR algorithm with look ahead", OFFSET(qsv.look_ahead), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, + { "look_ahead", "Use VBR algorithm with look ahead", OFFSET(qsv.look_ahead), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, { "look_ahead_depth", "Depth of look ahead in number frames", OFFSET(qsv.look_ahead_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, VE }, #endif #if QSV_HAVE_LA_DS From aeaa108bafa11db290f1ada0e22dbfbd655cf2ba Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 16 Feb 2018 16:09:25 +0100 Subject: [PATCH 2027/2557] hls: Add a discontinuity marker on recover It seems to improve the compatibility with the js demuxers. Signed-off-by: Luca Barbato --- libavformat/hlsenc.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index c84dd82e7da53..2fd3f19fcb2d0 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -42,6 +42,7 @@ typedef struct ListEntry { char name[1024]; int64_t duration; // segment duration in AV_TIME_BASE units + int discont; struct ListEntry *next; } ListEntry; @@ -76,6 +77,8 @@ typedef struct HLSContext { char *iv; // Set by a private option. int iv_len; + int recovered; + char *key_basename; AVDictionary *enc_opts; @@ -214,7 +217,8 @@ static int hls_mux_init(AVFormatContext *s) return 0; } -static int append_entry(HLSContext *hls, int64_t duration, const char *name) +static int append_entry(HLSContext *hls, int64_t duration, const char *name, + int discont) { ListEntry *en = av_malloc(sizeof(*en)); @@ -223,6 +227,7 @@ static int append_entry(HLSContext *hls, int64_t duration, const char *name) av_strlcpy(en->name, name, sizeof(en->name)); + en->discont = discont; en->duration = duration; en->next = NULL; @@ -289,6 +294,10 @@ static int hls_window(AVFormatContext *s, int last) sequence); for (en = hls->list; en; en = en->next) { + if (en->discont) { + avio_printf(out, "#EXT-X-DISCONTINUITY\n"); + } + if (hls->encrypt) { char *key_url; @@ -383,7 +392,7 @@ static int hls_recover(AVFormatContext *s) char line[1024]; AVIOContext *io; const char *ptr; - int ret, is_segment = 0; + int ret, is_segment = 0, is_discont = 0; int64_t duration = 0; ret = s->io_open(s, &io, s->filename, AVIO_FLAG_READ, NULL); @@ -410,16 +419,21 @@ static int hls_recover(AVFormatContext *s) } else if (av_strstart(line, "#EXTINF:", &ptr)) { is_segment = 1; duration = atof(ptr) * AV_TIME_BASE; + } else if (av_strstart(line, "#EXT-X-DISCONTINUITY", NULL)) { + is_discont = 1; } else if (av_strstart(line, "#", NULL)) { continue; } else if (line[0]) { if (is_segment) { - append_entry(hls, duration, av_basename(line)); + append_entry(hls, duration, av_basename(line), is_discont); is_segment = 0; + is_discont = 0; } } } + hls->recovered = 1; + return 0; } @@ -539,7 +553,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) hls->duration = pts - hls->end_pts; if (can_split && pts - hls->start_pts >= end_pts) { - ret = append_entry(hls, hls->duration, av_basename(hls->avf->filename)); + ret = append_entry(hls, hls->duration, av_basename(hls->avf->filename), hls->recovered); + hls->recovered = 0; if (ret) return ret; @@ -574,7 +589,7 @@ static int hls_write_trailer(struct AVFormatContext *s) ff_format_io_close(s, &oc->pb); avformat_free_context(oc); av_free(hls->basename); - append_entry(hls, hls->duration, av_basename(hls->avf->filename)); + append_entry(hls, hls->duration, av_basename(hls->avf->filename), 0); hls_window(s, 1); free_entries(hls); From 313b6057fbf1ccb18be3165f41f5a49e26d2bdd2 Mon Sep 17 00:00:00 2001 From: Stefan _ Date: Tue, 6 Mar 2018 18:00:27 +0000 Subject: [PATCH 2028/2557] avcodec/mediacodec_wrapper: blacklist more software decoders Additionally blacklist ffmpeg, Samsung and Qualcomm software implementations offered through MediaCodec. Signed-off-by: Aman Gupta Signed-off-by: Matthieu Bouron --- libavcodec/mediacodec_wrapper.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c index 9436b3c9941f8..83811281a5dbc 100644 --- a/libavcodec/mediacodec_wrapper.c +++ b/libavcodec/mediacodec_wrapper.c @@ -469,7 +469,12 @@ char *ff_AMediaCodecList_getCodecNameByType(const char *mime, int profile, int e goto done; } - if (strstr(name, "OMX.google")) { + /* Skip software decoders */ + if ( + strstr(name, "OMX.google") || + strstr(name, "OMX.ffmpeg") || + strstr(name, "OMX.SEC") || + !strcmp(name, "OMX.qcom.video.decoder.hevcswvdec")) { av_freep(&name); goto done_with_type; } From c22e7b00e4b9359a5cfe27495d9c4b6e6f53fda2 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 6 Mar 2018 13:33:19 -0800 Subject: [PATCH 2029/2557] avcodec/mediacodec: reduce loglevel for per-frame logging Signed-off-by: Aman Gupta Signed-off-by: Matthieu Bouron --- libavcodec/mediacodecdec_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index 929db78361805..0bd660f7c9ea8 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -297,7 +297,7 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif frame->pkt_dts = AV_NOPTS_VALUE; - av_log(avctx, AV_LOG_DEBUG, + av_log(avctx, AV_LOG_TRACE, "Frame: width=%d stride=%d height=%d slice-height=%d " "crop-top=%d crop-bottom=%d crop-left=%d crop-right=%d encoder=%s\n" "destination linesizes=%d,%d,%d\n" , From b19e11a4dc836f4fe87d3e3c25eb5cc4f6f4b447 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 6 Mar 2018 13:33:20 -0800 Subject: [PATCH 2030/2557] MAINTAINERS: add myself to mediacodec Signed-off-by: Matthieu Bouron --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index cc4c23df6f75a..3c54ad6781f70 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -268,7 +268,7 @@ Hardware acceleration: crystalhd.c Philip Langdale dxva2* Hendrik Leppkes, Laurent Aimar, Steve Lhomme d3d11va* Steve Lhomme - mediacodec* Matthieu Bouron + mediacodec* Matthieu Bouron, Aman Gupta vaapi* Gwenole Beauchesne vaapi_encode* Mark Thompson vdpau* Philip Langdale, Carl Eugen Hoyos From 0ca33b1d4eb2a2a2e78ff3a37f1647917635b0d2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 6 Mar 2018 01:19:13 -0300 Subject: [PATCH 2031/2557] avformat/utils: free existing extradata before trying to allocate a new one This prevents leaks in the rare cases the function is called when extradata already exists. Reviewed-by: Paul B Mahol Signed-off-by: James Almer --- libavformat/utils.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/utils.c b/libavformat/utils.c index 72531d4185f50..31340a484bd39 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -3245,6 +3245,7 @@ int ff_alloc_extradata(AVCodecParameters *par, int size) { int ret; + av_freep(&par->extradata); if (size < 0 || size >= INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { par->extradata = NULL; par->extradata_size = 0; From 2aa42fac77ac1d29d858327fc72c972672ff3729 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 6 Mar 2018 01:37:21 -0300 Subject: [PATCH 2032/2557] avformat/utils: simplify ff_alloc_extradata() Cosmetic refactor Reviewed-by: 74a2fa708af88d225ed708af758f236f869b1a57 Signed-off-by: James Almer --- libavformat/utils.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index 31340a484bd39..3ca1ca24412ee 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -3243,24 +3243,20 @@ static int tb_unreliable(AVCodecContext *c) int ff_alloc_extradata(AVCodecParameters *par, int size) { - int ret; - av_freep(&par->extradata); - if (size < 0 || size >= INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { - par->extradata = NULL; - par->extradata_size = 0; + par->extradata_size = 0; + + if (size < 0 || size >= INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE) return AVERROR(EINVAL); - } + par->extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); - if (par->extradata) { - memset(par->extradata + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); - par->extradata_size = size; - ret = 0; - } else { - par->extradata_size = 0; - ret = AVERROR(ENOMEM); - } - return ret; + if (!par->extradata) + return AVERROR(ENOMEM); + + memset(par->extradata + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + par->extradata_size = size; + + return 0; } int ff_get_extradata(AVFormatContext *s, AVCodecParameters *par, AVIOContext *pb, int size) From 56912555bc1921420f5271159b0c20034ab4209e Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 6 Mar 2018 23:39:00 +0000 Subject: [PATCH 2033/2557] h264_metadata: Actually fail when sei_user_data option is invalid --- libavcodec/h264_metadata_bsf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 89bdedfc69d42..466823cda69e1 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -345,6 +345,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) av_log(bsf, AV_LOG_ERROR, "Invalid user data: " "must be \"UUID+string\".\n"); err = AVERROR(EINVAL); + goto fail; } } From 7c39305a174899cbf924ed013c89715b8bddc442 Mon Sep 17 00:00:00 2001 From: Stefan _ Date: Wed, 21 Feb 2018 17:57:00 +0000 Subject: [PATCH 2034/2557] libavformat/tls_libtls: pass numeric hostnames to tls_connect_cbs() Numeric hosts in certificates are not very common, but supported by LibreSSL. Forward the IP address to make verification work in this case. Fixes ticket #7029 --- libavformat/tls_libtls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/tls_libtls.c b/libavformat/tls_libtls.c index 1321f79229f8f..ba83b56ffe2a3 100644 --- a/libavformat/tls_libtls.c +++ b/libavformat/tls_libtls.c @@ -119,7 +119,7 @@ static int ff_tls_open(URLContext *h, const char *uri, int flags, AVDictionary * if (!c->listen) { ret = tls_connect_cbs(p->ctx, tls_read_callback, tls_write_callback, - c->tcp, !c->numerichost ? c->host : NULL); + c->tcp, c->host); } else { struct tls *ctx_new; ret = tls_accept_cbs(p->ctx, &ctx_new, tls_read_callback, From 8b0a9f79c8973283e7dc21609bb3848a21427906 Mon Sep 17 00:00:00 2001 From: Masaki Tanaka Date: Sun, 11 Feb 2018 15:40:55 +0200 Subject: [PATCH 2035/2557] mpegvideo_parser: fix indentation of an if statement --- libavcodec/mpegvideo_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c index be240b68908ea..7a3c7abdb24e5 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -61,7 +61,7 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, if (bytes_left >= 2) { s->pict_type = (buf[1] >> 3) & 7; if (bytes_left >= 4) - vbv_delay = ((buf[1] & 0x07) << 13) | (buf[2] << 5) | (buf[3] >> 3); + vbv_delay = ((buf[1] & 0x07) << 13) | (buf[2] << 5) | (buf[3] >> 3); } break; case SEQ_START_CODE: From a43e9cdd442b3ccf50faa32a15b03bdaff278017 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 6 Mar 2018 23:26:22 -0300 Subject: [PATCH 2036/2557] avformat/isom: don't free extradata before calling ff_get_extradata() ff_get_extradata() frees any existing extradata before allocating now, and using av_free() here leaves a dangling pointer that will result in a double free. Fixes a regression since 0ca33b1d4eb2a2a2e78ff3a37f1647917635b0d2. Tested-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/isom.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavformat/isom.c b/libavformat/isom.c index 59502a8b3f2be..2792371c2503a 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -526,7 +526,6 @@ FF_ENABLE_DEPRECATION_WARNINGS av_log(fc, AV_LOG_TRACE, "Specific MPEG-4 header len=%d\n", len); if (!len || (uint64_t)len > (1<<30)) return AVERROR_INVALIDDATA; - av_free(st->codecpar->extradata); if ((ret = ff_get_extradata(fc, st->codecpar, pb, len)) < 0) return ret; if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { From 0711d142997b2662ba9198e607015b06c6eed0d8 Mon Sep 17 00:00:00 2001 From: Andreas Unterweger Date: Tue, 27 Feb 2018 17:48:03 +0100 Subject: [PATCH 2037/2557] examples: Use new API for transcoding example Signed-off-by: Diego Biurrun --- doc/examples/transcode_aac.c | 101 ++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 32 deletions(-) diff --git a/doc/examples/transcode_aac.c b/doc/examples/transcode_aac.c index 44d5af6b0481d..ec557768578b1 100644 --- a/doc/examples/transcode_aac.c +++ b/doc/examples/transcode_aac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 Andreas Unterweger + * Copyright (c) 2013-2018 Andreas Unterweger * * This file is part of Libav. * @@ -398,24 +398,39 @@ static int decode_audio_frame(AVFrame *frame, } } - /* Decode the audio frame stored in the temporary packet. - * The input audio stream decoder is used to do this. - * If we are at the end of the file, pass an empty packet to the decoder - * to flush it. */ - if ((error = avcodec_decode_audio4(input_codec_context, frame, - data_present, &input_packet)) < 0) { - fprintf(stderr, "Could not decode frame (error '%s')\n", + /* Send the audio frame stored in the temporary packet to the decoder. + * The input audio stream decoder is used to do this. */ + if ((error = avcodec_send_packet(input_codec_context, &input_packet)) < 0) { + fprintf(stderr, "Could not send packet for decoding (error '%s')\n", get_error_text(error)); - av_packet_unref(&input_packet); return error; } - /* If the decoder has not been flushed completely, we are not finished, - * so that this function has to be called again. */ - if (*finished && *data_present) - *finished = 0; + /* Receive one frame from the decoder. */ + error = avcodec_receive_frame(input_codec_context, frame); + /* If the decoder asks for more data to be able to decode a frame, + * return indicating that no data is present. */ + if (error == AVERROR(EAGAIN)) { + error = 0; + goto cleanup; + /* If the end of the input file is reached, stop decoding. */ + } else if (error == AVERROR_EOF) { + *finished = 1; + error = 0; + goto cleanup; + } else if (error < 0) { + fprintf(stderr, "Could not decode frame (error '%s')\n", + get_error_text(error)); + goto cleanup; + /* Default case: Return decoded data. */ + } else { + *data_present = 1; + goto cleanup; + } + +cleanup: av_packet_unref(&input_packet); - return 0; + return error; } /** @@ -556,7 +571,7 @@ static int read_decode_convert_and_store(AVAudioFifo *fifo, AVFrame *input_frame = NULL; /* Temporary storage for the converted input samples. */ uint8_t **converted_input_samples = NULL; - int data_present; + int data_present = 0; int ret = AVERROR_EXIT; /* Initialize temporary storage for one input frame. */ @@ -569,7 +584,7 @@ static int read_decode_convert_and_store(AVAudioFifo *fifo, /* If we are at the end of the file and there are no more samples * in the decoder which are delayed, we are actually finished. * This must not be treated as an error. */ - if (*finished && !data_present) { + if (*finished) { ret = 0; goto cleanup; } @@ -655,7 +670,7 @@ static int64_t pts = 0; * @param output_format_context Format context of the output file * @param output_codec_context Codec context of the output file * @param[out] data_present Indicates whether data has been - * decoded + * encoded * @return Error code (0 if successful) */ static int encode_audio_frame(AVFrame *frame, @@ -674,29 +689,50 @@ static int encode_audio_frame(AVFrame *frame, pts += frame->nb_samples; } - /* Encode the audio frame and store it in the temporary packet. + /* Send the audio frame stored in the temporary packet to the encoder. * The output audio stream encoder is used to do this. */ - if ((error = avcodec_encode_audio2(output_codec_context, &output_packet, - frame, data_present)) < 0) { - fprintf(stderr, "Could not encode frame (error '%s')\n", + error = avcodec_send_frame(output_codec_context, frame); + /* The encoder signals that it has nothing more to encode. */ + if (error == AVERROR_EOF) { + error = 0; + goto cleanup; + } else if (error < 0) { + fprintf(stderr, "Could not send packet for encoding (error '%s')\n", get_error_text(error)); - av_packet_unref(&output_packet); return error; } - /* Write one audio frame from the temporary packet to the output file. */ - if (*data_present) { - if ((error = av_write_frame(output_format_context, &output_packet)) < 0) { - fprintf(stderr, "Could not write frame (error '%s')\n", - get_error_text(error)); - av_packet_unref(&output_packet); - return error; - } + /* Receive one encoded frame from the encoder. */ + error = avcodec_receive_packet(output_codec_context, &output_packet); + /* If the encoder asks for more data to be able to provide an + * encoded frame, return indicating that no data is present. */ + if (error == AVERROR(EAGAIN)) { + error = 0; + goto cleanup; + /* If the last frame has been encoded, stop encoding. */ + } else if (error == AVERROR_EOF) { + error = 0; + goto cleanup; + } else if (error < 0) { + fprintf(stderr, "Could not encode frame (error '%s')\n", + get_error_text(error)); + goto cleanup; + /* Default case: Return encoded data. */ + } else { + *data_present = 1; + } - av_packet_unref(&output_packet); + /* Write one audio frame from the temporary packet to the output file. */ + if (*data_present && + (error = av_write_frame(output_format_context, &output_packet)) < 0) { + fprintf(stderr, "Could not write frame (error '%s')\n", + get_error_text(error)); + goto cleanup; } - return 0; +cleanup: + av_packet_unref(&output_packet); + return error; } /** @@ -836,6 +872,7 @@ int main(int argc, char **argv) int data_written; /* Flush the encoder as it may have delayed frames. */ do { + data_written = 0; if (encode_audio_frame(NULL, output_format_context, output_codec_context, &data_written)) goto cleanup; From 5ab0ecf2830fd7a864bb21f7fe247594872932fa Mon Sep 17 00:00:00 2001 From: Stefan _ Date: Tue, 6 Mar 2018 22:19:36 +0000 Subject: [PATCH 2038/2557] avcodec/mediacodec_wrapper: fix false positives in swdec blacklist 'OMX.SEC.avc.dec' is a valid hardware decoder, while the decoders we seek to blacklist all match 'OMX.SEC.*.sw.dec'. --- libavcodec/mediacodec_wrapper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c index 83811281a5dbc..11d7f665c77c4 100644 --- a/libavcodec/mediacodec_wrapper.c +++ b/libavcodec/mediacodec_wrapper.c @@ -473,7 +473,7 @@ char *ff_AMediaCodecList_getCodecNameByType(const char *mime, int profile, int e if ( strstr(name, "OMX.google") || strstr(name, "OMX.ffmpeg") || - strstr(name, "OMX.SEC") || + (strstr(name, "OMX.SEC") && strstr(name, ".sw.")) || !strcmp(name, "OMX.qcom.video.decoder.hevcswvdec")) { av_freep(&name); goto done_with_type; From 121314895f6360852b2807d5dfafea576b2e6fed Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 7 Mar 2018 13:27:39 +0100 Subject: [PATCH 2039/2557] configure: Fix logic of AMF external library check Fail if AMF is requested but unavailable, as we do for all other external libraries that need to be explicitly enabled. --- configure | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/configure b/configure index 1c35f9dc641e5..d882d4c73f896 100755 --- a/configure +++ b/configure @@ -4598,11 +4598,7 @@ for func in $MATH_FUNCS; do done # these are off by default, so fail if requested and not available - -enabled amf && - check_cpp_condition "AMF/core/Version.h" \ - "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400040001" || - disable amf +enabled amf && require_cpp_condition AMF/core/Version.h "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400040001" enabled avisynth && require_header avisynth/avisynth_c.h enabled avxsynth && require_header avxsynth/avxsynth_c.h enabled cuda && require cuda cuda.h cuInit -lcuda From 8c893aa3cd5f2d73896c72af330dcbfe299fbc5a Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 21 Oct 2017 01:27:23 +0200 Subject: [PATCH 2040/2557] configure: Drop unnecessary variables, shifts, and quotes in helper functions --- configure | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/configure b/configure index d882d4c73f896..f373698b6c945 100755 --- a/configure +++ b/configure @@ -816,7 +816,7 @@ EOF check_insn(){ log check_insn "$@" - check_inline_asm ${1}_inline "\"$2\"" + check_inline_asm ${1}_inline "$2" echo "$2" | check_as && enable ${1}_external || disable ${1}_external } @@ -1097,11 +1097,9 @@ check_struct(){ check_builtin(){ log check_builtin "$@" name=$1 - headers=$2 - builtin=$3 - shift 3 + shift disable "$name" - check_code ld "$headers" "$builtin" "$@" && enable "$name" + check_code ld "$@" && enable "$name" } check_compile_assert(){ @@ -1118,25 +1116,20 @@ require(){ log require "$@" name_version="$1" name="${1%% *}" - headers="$2" - func="$3" - shift 3 - check_lib $name "$headers" $func "$@" || die "ERROR: $name_version not found" + shift + check_lib $name "$@" || die "ERROR: $name_version not found" } require_header(){ log require_header "$@" headers="$1" - shift - check_header "$headers" "$@" || die "ERROR: $headers not found" + check_header "$@" || die "ERROR: $headers not found" } require_cpp_condition(){ log require_cpp_condition "$@" - header="$1" condition="$2" - shift 2 - check_cpp_condition "$header" "$condition" "$@" || die "ERROR: $condition not satisfied" + check_cpp_condition "$@" || die "ERROR: $condition not satisfied" } require_pkg_config(){ From 49804dc2baec009577e6b4ee827ae562188fbc2f Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sun, 4 Feb 2018 20:21:57 +0100 Subject: [PATCH 2041/2557] configure: Use test_ prefix for helper functions that do not set variables --- configure | 263 +++++++++++++++++++++++++++--------------------------- 1 file changed, 132 insertions(+), 131 deletions(-) diff --git a/configure b/configure index f373698b6c945..b900682d0e152 100755 --- a/configure +++ b/configure @@ -758,7 +758,7 @@ add_compat(){ map 'add_cppflags -D$v' "$@" } -check_cmd(){ +test_cmd(){ log "$@" "$@" >> $logfile 2>&1 } @@ -771,36 +771,36 @@ cc_e(){ eval printf '%s\\n' $CC_E } -check_cc(){ - log check_cc "$@" +test_cc(){ + log test_cc "$@" cat > $TMPC log_file $TMPC - check_cmd $cc $CPPFLAGS $CFLAGS "$@" $CC_C $(cc_o $TMPO) $TMPC + test_cmd $cc $CPPFLAGS $CFLAGS "$@" $CC_C $(cc_o $TMPO) $TMPC } -check_objcc(){ - log check_objcc "$@" +test_objcc(){ + log test_objcc "$@" cat > $TMPC log_file $TMPC - check_cmd $objcc $CPPFLAGS $CFLAGS $OBJCFLAGS "$@" $OBJCC_C $(cc_o $TMPO) $TMPC + test_cmd $objcc $CPPFLAGS $CFLAGS $OBJCFLAGS "$@" $OBJCC_C $(cc_o $TMPO) $TMPC } -check_cpp(){ - log check_cpp "$@" +test_cpp(){ + log test_cpp "$@" cat > $TMPC log_file $TMPC - check_cmd $cc $CPPFLAGS $CFLAGS "$@" $(cc_e $TMPO) $TMPC + test_cmd $cc $CPPFLAGS $CFLAGS "$@" $(cc_e $TMPO) $TMPC } as_o(){ eval printf '%s\\n' $AS_O } -check_as(){ - log check_as "$@" +test_as(){ + log test_as "$@" cat > $TMPS log_file $TMPS - check_cmd $as $CPPFLAGS $ASFLAGS "$@" $AS_C $(as_o $TMPO) $TMPS + test_cmd $as $CPPFLAGS $ASFLAGS "$@" $AS_C $(as_o $TMPO) $TMPS } check_inline_asm(){ @@ -809,7 +809,7 @@ check_inline_asm(){ code="$2" shift 2 disable $name - check_cc "$@" < $TMPS log_file $TMPS shift 1 - check_cmd $x86asmexe $X86ASMFLAGS "$@" -o $TMPO $TMPS + test_cmd $x86asmexe $X86ASMFLAGS "$@" -o $TMPO $TMPS } ld_o(){ eval printf '%s\\n' $LD_O } -check_ld(){ - log check_ld "$@" +test_ld(){ + log test_ld "$@" flags=$(filter_out '-l*' "$@") libs=$(filter '-l*' "$@") - check_cc $($cflags_filter $flags) || return + test_cc $($cflags_filter $flags) || return flags=$($ldflags_filter $flags) libs=$($ldflags_filter $libs) - check_cmd $ld $LDFLAGS $flags $(ld_o $TMPE) $TMPO $libs $extralibs + test_cmd $ld $LDFLAGS $flags $(ld_o $TMPE) $TMPO $libs $extralibs } print_include(){ @@ -849,8 +849,8 @@ print_include(){ echo "#include <$hdr>" } -check_code(){ - log check_code "$@" +test_code(){ + log test_code "$@" check=$1 headers=$2 code=$3 @@ -860,12 +860,12 @@ check_code(){ print_include $hdr done echo "int main(void) { $code; return 0; }" - } | check_$check "$@" + } | test_$check "$@" } check_cppflags(){ log check_cppflags "$@" - check_cpp "$@" <; EOF } @@ -873,7 +873,7 @@ EOF test_cflags(){ log test_cflags "$@" set -- $($cflags_filter "$@") - check_cc "$@" < float foo(float f, float g) { return $func($args); } int main(void){ return 0; } @@ -974,15 +974,15 @@ check_func_headers(){ echo "long check_$func(void) { return (long) $func; }" done echo "int main(void) { return 0; }" - } | check_ld "$@" && enable $funcs && enable_sanitized $headers + } | test_ld "$@" && enable $funcs && enable_sanitized $headers } -check_cpp_condition(){ - log check_cpp_condition "$@" +test_cpp_condition(){ + log test_cpp_condition "$@" header=$1 condition=$2 shift 2 - check_cpp "$@" < #if !($condition) #error "unsatisfied condition: $condition" @@ -996,7 +996,7 @@ test_cflags_cpp(){ condition=$2 shift 2 set -- $($cflags_filter "$flags") - check_cpp "$@" <> $logfile 2>&1; } +test_exec(){ + log test_exec "$@" + test_ld "$@" && { enabled cross_compile || $TMPE >> $logfile 2>&1; } } check_exec_crash(){ @@ -1053,7 +1054,7 @@ check_exec_crash(){ # can redirect the "Terminated" message from the shell. SIGBUS # is not defined by standard C so it is used conditionally. - (check_exec "$@") >> $logfile 2>&1 <> $logfile 2>&1 < static void sighandler(int sig){ raise(SIGTERM); @@ -1080,7 +1081,7 @@ check_type(){ type=$2 shift 2 disable_sanitized "$type" - check_code cc "$headers" "$type v" "$@" && enable_sanitized "$type" + test_code cc "$headers" "$type v" "$@" && enable_sanitized "$type" } check_struct(){ @@ -1090,7 +1091,7 @@ check_struct(){ member=$3 shift 3 disable_sanitized "${struct}_${member}" - check_code cc "$headers" "const void *p = &(($struct *)0)->$member" "$@" && + test_code cc "$headers" "const void *p = &(($struct *)0)->$member" "$@" && enable_sanitized "${struct}_${member}" } @@ -1099,7 +1100,7 @@ check_builtin(){ name=$1 shift disable "$name" - check_code ld "$@" && enable "$name" + test_code ld "$@" && enable "$name" } check_compile_assert(){ @@ -1109,7 +1110,7 @@ check_compile_assert(){ condition=$3 shift 3 disable "$name" - check_code cc "$headers" "char c[2 * !!($condition) - 1]" "$@" && enable "$name" + test_code cc "$headers" "char c[2 * !!($condition) - 1]" "$@" && enable "$name" } require(){ @@ -1129,7 +1130,7 @@ require_header(){ require_cpp_condition(){ log require_cpp_condition "$@" condition="$2" - check_cpp_condition "$@" || die "ERROR: $condition not satisfied" + test_cpp_condition "$@" || die "ERROR: $condition not satisfied" } require_pkg_config(){ @@ -1146,23 +1147,23 @@ hostcc_o(){ eval printf '%s\\n' $HOSTCC_O } -check_host_cc(){ - log check_host_cc "$@" +test_host_cc(){ + log test_host_cc "$@" cat > $TMPC log_file $TMPC - check_cmd $host_cc $host_cflags "$@" $HOSTCC_C $(hostcc_o $TMPO) $TMPC + test_cmd $host_cc $host_cflags "$@" $HOSTCC_C $(hostcc_o $TMPO) $TMPC } -check_host_cpp(){ - log check_host_cpp "$@" +test_host_cpp(){ + log test_host_cpp "$@" cat > $TMPC log_file $TMPC - check_cmd $host_cc $host_cppflags $host_cflags "$@" $(hostcc_e $TMPO) $TMPC + test_cmd $host_cc $host_cppflags $host_cflags "$@" $(hostcc_e $TMPO) $TMPC } check_host_cppflags(){ log check_host_cppflags "$@" - check_host_cpp "$@" <; EOF } @@ -1170,17 +1171,17 @@ EOF check_host_cflags(){ log check_host_cflags "$@" set -- $($host_cflags_filter "$@") - check_host_cc "$@" < #if !($condition) #error "unsatisfied condition: $condition" @@ -3044,7 +3045,7 @@ HOSTEXESUF=$(exesuf $host_os) : ${TMPDIR:=$TMP} : ${TMPDIR:=/tmp} -if ! check_cmd mktemp -u XXXXXX; then +if ! test_cmd mktemp -u XXXXXX; then # simple replacement for missing mktemp # NOT SAFE FOR GENERAL USE mktemp(){ @@ -3542,7 +3543,7 @@ elif enabled alpha; then elif enabled arm; then check_arm_arch() { - check_cpp_condition stddef.h \ + test_cpp_condition stddef.h \ "defined __ARM_ARCH_${1}__ || defined __TARGET_ARCH_${2:-$1}" \ $cpuflags } @@ -3735,7 +3736,7 @@ if [ "$cpu" != generic ]; then fi # compiler sanity check -check_exec <= 201112L" -std=c11 && +test_cpp_condition stdlib.h "__STDC_VERSION__ >= 201112L" -std=c11 && add_cflags -std=c11 || check_cflags -std=c99 @@ -3767,7 +3768,7 @@ check_64bit(){ arch32=$1 arch64=$2 expr=${3:-'sizeof(void *) > 4'} - check_code cc "" "int test[2*($expr) - 1]" && + test_code cc "" "int test[2*($expr) - 1]" && subarch=$arch64 || subarch=$arch32 enable $subarch } @@ -4023,38 +4024,38 @@ probe_libc(){ pfx=$1 pfx_no_=${pfx%_} # uclibc defines __GLIBC__, so it needs to be checked before glibc. - if check_${pfx}cpp_condition features.h "defined __UCLIBC__"; then + if test_${pfx}cpp_condition features.h "defined __UCLIBC__"; then eval ${pfx}libc_type=uclibc add_${pfx}cppflags -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 - elif check_${pfx}cpp_condition features.h "defined __GLIBC__"; then + elif test_${pfx}cpp_condition features.h "defined __GLIBC__"; then eval ${pfx}libc_type=glibc add_${pfx}cppflags -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 # MinGW headers can be installed on Cygwin, so check for newlib first. - elif check_${pfx}cpp_condition newlib.h "defined _NEWLIB_VERSION"; then + elif test_${pfx}cpp_condition newlib.h "defined _NEWLIB_VERSION"; then eval ${pfx}libc_type=newlib add_${pfx}cppflags -U__STRICT_ANSI__ -D_XOPEN_SOURCE=600 # MinGW64 is backwards compatible with MinGW32, so check for it first. - elif check_${pfx}cpp_condition _mingw.h "defined __MINGW64_VERSION_MAJOR"; then + elif test_${pfx}cpp_condition _mingw.h "defined __MINGW64_VERSION_MAJOR"; then eval ${pfx}libc_type=mingw64 add_${pfx}cppflags -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO=1 eval test \$${pfx_no_}cc_type = "gcc" && add_${pfx}cppflags -D__printf__=__gnu_printf__ - elif check_${pfx}cpp_condition _mingw.h "defined __MINGW_VERSION" || - check_${pfx}cpp_condition _mingw.h "defined __MINGW32_VERSION"; then + elif test_${pfx}cpp_condition _mingw.h "defined __MINGW_VERSION" || + test_${pfx}cpp_condition _mingw.h "defined __MINGW32_VERSION"; then eval ${pfx}libc_type=mingw32 - check_${pfx}cpp_condition _mingw.h "__MINGW32_MAJOR_VERSION > 3 || \ + test_${pfx}cpp_condition _mingw.h "__MINGW32_MAJOR_VERSION > 3 || \ (__MINGW32_MAJOR_VERSION == 3 && __MINGW32_MINOR_VERSION >= 15)" || die "ERROR: MinGW32 runtime version must be >= 3.15." add_${pfx}cppflags -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO=1 - check_${pfx}cpp_condition _mingw.h "__MSVCRT_VERSION__ < 0x0700" && + test_${pfx}cpp_condition _mingw.h "__MSVCRT_VERSION__ < 0x0700" && add_${pfx}cppflags -D__MSVCRT_VERSION__=0x0700 - check_${pfx}cpp_condition windows.h "defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0502" && + test_${pfx}cpp_condition windows.h "defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0502" && add_${pfx}cppflags -D_WIN32_WINNT=0x0502 eval test \$${pfx_no_}cc_type = "gcc" && add_${pfx}cppflags -D__printf__=__gnu_printf__ - elif check_${pfx}cpp_condition crtversion.h "defined _VC_CRT_MAJOR_VERSION"; then + elif test_${pfx}cpp_condition crtversion.h "defined _VC_CRT_MAJOR_VERSION"; then eval ${pfx}libc_type=msvcrt - if check_${pfx}cpp_condition crtversion.h "_VC_CRT_MAJOR_VERSION < 14"; then + if test_${pfx}cpp_condition crtversion.h "_VC_CRT_MAJOR_VERSION < 14"; then if [ "$pfx" = host_ ]; then add_host_cppflags -Dsnprintf=_snprintf else @@ -4075,8 +4076,8 @@ probe_libc(){ # family. For these cases, configure is free to use any functions # found in the SDK headers by default. (Alternatively, we could force # _WIN32_WINNT to 0x0602 in that case.) - check_${pfx}cpp_condition stdlib.h "defined(_WIN32_WINNT)" || - { check_${pfx}cpp < #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) @@ -4087,11 +4088,11 @@ EOF if [ "$pfx" = "" ]; then check_func strtoll || add_cflags -Dstrtoll=_strtoi64 fi - elif check_${pfx}cpp_condition stddef.h "defined __KLIBC__"; then + elif test_${pfx}cpp_condition stddef.h "defined __KLIBC__"; then eval ${pfx}libc_type=klibc - elif check_${pfx}cpp_condition sys/cdefs.h "defined __BIONIC__"; then + elif test_${pfx}cpp_condition sys/cdefs.h "defined __BIONIC__"; then eval ${pfx}libc_type=bionic - elif check_${pfx}cpp_condition sys/brand.h "defined LABELED_BRAND_NAME"; then + elif test_${pfx}cpp_condition sys/brand.h "defined LABELED_BRAND_NAME"; then eval ${pfx}libc_type=solaris add_${pfx}cppflags -D__EXTENSIONS__ -D_XOPEN_SOURCE=600 else @@ -4115,7 +4116,7 @@ esac check_compile_assert flt_lim "float.h limits.h" "DBL_MAX == (double)DBL_MAX" || add_cppflags '-I\$(SRC_PATH)/compat/float' -check_cpp_condition stdlib.h "defined(__PIC__) || defined(__pic__) || defined(PIC)" && enable_weak pic +test_cpp_condition stdlib.h "defined(__PIC__) || defined(__pic__) || defined(PIC)" && enable_weak pic set_default $PATHS_LIST set_default nm @@ -4138,7 +4139,7 @@ enable_weak_pic() { enabled pic && enable_weak_pic -check_cc <= 30"; then + elif test_cpp_condition stddef.h "defined _M_ARM_FP && _M_ARM_FP >= 30"; then enable vfp_args - elif ! check_cpp_condition stddef.h "defined __ARM_PCS || defined __SOFTFP__" && [ $target_os != darwin ]; then + elif ! test_cpp_condition stddef.h "defined __ARM_PCS || defined __SOFTFP__" && [ $target_os != darwin ]; then case "${cross_prefix:-$cc}" in *hardfloat*) enable vfp_args; fpabi=vfp ;; - *) check_ld <= 118" && - { check_cpp_condition x264.h "X264_MPEG2" && + { test_cpp_condition x264.h "X264_MPEG2" && enable libx262; } enabled libx265 && require_pkg_config libx265 x265 x265.h x265_api_get && require_cpp_condition x265.h "X265_BUILD >= 57" @@ -4675,8 +4676,8 @@ enabled openssl && { { check_pkg_config openssl openssl openssl/ssl.h enabled avplay && test_pkg_config sdl "sdl >= 1.2.1 sdl < 1.3.0" SDL_events.h SDL_PollEvent -! disabled pod2man && check_cmd pod2man --help && enable pod2man || disable pod2man -! disabled texi2html && check_cmd texi2html -version && enable texi2html || disable texi2html +! disabled pod2man && test_cmd pod2man --help && enable pod2man || disable pod2man +! disabled texi2html && test_cmd texi2html -version && enable texi2html || disable texi2html check_header linux/fb.h check_header linux/videodev2.h @@ -4690,7 +4691,7 @@ check_lib user32 "windows.h winuser.h" GetShellWindow -luser32 check_lib vfw32 "windows.h vfw.h" capCreateCaptureWindow -lvfw32 # check that WM_CAP_DRIVER_CONNECT is defined to the proper value # w32api 3.12 had it defined wrong -check_cpp_condition vfw.h "WM_CAP_DRIVER_CONNECT > WM_USER" && enable vfwcap_defines +test_cpp_condition vfw.h "WM_CAP_DRIVER_CONNECT > WM_USER" && enable vfwcap_defines # check for ioctl_meteor.h, ioctl_bt848.h and alternatives check_header "dev/bktr/ioctl_meteor.h dev/bktr/ioctl_bt848.h" || @@ -4725,7 +4726,7 @@ fi # d3d11va requires linking directly to dxgi and d3d11 if not building for # the desktop api partition -check_cpp < #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) @@ -4741,7 +4742,7 @@ EOF enabled vaapi && require vaapi va/va.h vaInitialize -lva enabled vaapi && - check_code cc "va/va.h" "vaCreateSurfaces(0, 0, 0, 0, 0, 0, 0, 0)" || + test_code cc "va/va.h" "vaCreateSurfaces(0, 0, 0, 0, 0, 0, 0, 0)" || disable vaapi enabled vaapi && @@ -4751,11 +4752,11 @@ enabled vaapi && check_lib vaapi_x11 "va/va.h va/va_x11.h" vaGetDisplay -lva -lva-x11 -lX11 enabled vaapi && - check_cpp_condition "va/va.h" "VA_CHECK_VERSION(1, 0, 0)" && + test_cpp_condition "va/va.h" "VA_CHECK_VERSION(1, 0, 0)" && enable vaapi_1 enabled vdpau && - check_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || + test_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || disable vdpau enabled vdpau && @@ -4801,7 +4802,7 @@ check_disable_warning_headers -Wno-unused-variable check_objcflags -fobjc-arc && enable objc_arc -check_cc <= 1400" && + test_cpp_condition "windows.h" "__ICL < 1300 || __ICL >= 1400" && add_cflags -Qansi-alias # icl will pass the inline asm tests but inline asm is currently # not supported (build will fail) disable inline_asm fi # msvcrt10 x64 incorrectly enables log2, only msvcrt12 (MSVC 2013) onwards actually has log2. - check_cpp_condition crtversion.h "_VC_CRT_MAJOR_VERSION >= 12" || disable log2 + test_cpp_condition crtversion.h "_VC_CRT_MAJOR_VERSION >= 12" || disable log2 # The CRT headers contain __declspec(restrict) in a few places, but if redefining # restrict, this might break. MSVC 2010 and 2012 fail with __declspec(__restrict) # (as it ends up if the restrict redefine is done before including stdlib.h), while @@ -4972,7 +4973,7 @@ elif enabled_any msvc icl; then # If this declspec fails, force including stdlib.h before the restrict redefinition # happens in config.h. if [ $restrict_keyword != restrict ]; then - check_cc < Date: Sun, 24 Sep 2017 18:55:28 +0200 Subject: [PATCH 2042/2557] configure: Add check_cmd() helper function to simplify some expressions --- configure | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/configure b/configure index b900682d0e152..784caf85dfd99 100755 --- a/configure +++ b/configure @@ -803,6 +803,14 @@ test_as(){ test_cmd $as $CPPFLAGS $ASFLAGS "$@" $AS_C $(as_o $TMPO) $TMPS } +check_cmd(){ + log check_cmd "$@" + cmd=$1 + disabled $cmd && return + disable $cmd + test_cmd $@ && enable $cmd +} + check_inline_asm(){ log check_inline_asm "$@" name="$1" @@ -4676,9 +4684,6 @@ enabled openssl && { { check_pkg_config openssl openssl openssl/ssl.h enabled avplay && test_pkg_config sdl "sdl >= 1.2.1 sdl < 1.3.0" SDL_events.h SDL_PollEvent -! disabled pod2man && test_cmd pod2man --help && enable pod2man || disable pod2man -! disabled texi2html && test_cmd texi2html -version && enable texi2html || disable texi2html - check_header linux/fb.h check_header linux/videodev2.h check_struct linux/videodev2.h "struct v4l2_frmivalenum" discrete @@ -5003,6 +5008,9 @@ esac enabled asm || { arch=c; disable $ARCH_LIST $ARCH_EXT_LIST; } +check_cmd pod2man --help +check_cmd texi2html -version + check_deps $CONFIG_LIST \ $CONFIG_EXTRA \ $HAVE_LIST \ From 83fef16b6a8dbbcbd80d159ba3ebe818dbbb2776 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 7 Oct 2017 21:20:36 +0200 Subject: [PATCH 2043/2557] configure: Add check_cpp_condition() helper function to simplify some expressions --- configure | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/configure b/configure index 784caf85dfd99..9e90ab22c9c63 100755 --- a/configure +++ b/configure @@ -998,6 +998,14 @@ test_cpp_condition(){ EOF } +check_cpp_condition(){ + log check_cpp_condition "$@" + name=$1 + shift 1 + disable $name + test_cpp_condition "$@" && enable $name +} + test_cflags_cpp(){ log test_cflags_cpp "$@" flags=$1 @@ -1197,6 +1205,14 @@ test_host_cpp_condition(){ EOF } +check_host_cpp_condition(){ + log check_host_cpp_condition "$@" + name=$1 + shift 1 + disable $name + test_host_cpp_condition "$@" && enable $name +} + cp_if_changed(){ cmp -s "$1" "$2" && { test "$quiet" != "yes" && echo "$2 is unchanged"; } && return mkdir -p "$(dirname $2)" @@ -4232,14 +4248,14 @@ elif enabled alpha; then elif enabled arm; then - enabled msvc && test_cpp_condition stddef.h "defined _M_ARMT" && enable thumb + enabled msvc && check_cpp_condition thumb stddef.h "defined _M_ARMT" test_cpp_condition stddef.h "defined __thumb__" && enable_weak thumb enabled thumb && check_cflags -mthumb || check_cflags -marm - if test_cpp_condition stddef.h "defined __ARM_PCS_VFP"; then - enable vfp_args - elif test_cpp_condition stddef.h "defined _M_ARM_FP && _M_ARM_FP >= 30"; then - enable vfp_args + if check_cpp_condition vfp_args stddef.h "defined __ARM_PCS_VFP"; then + : + elif check_cpp_condition vfp_args stddef.h "defined _M_ARM_FP && _M_ARM_FP >= 30"; then + : elif ! test_cpp_condition stddef.h "defined __ARM_PCS || defined __SOFTFP__" && [ $target_os != darwin ]; then case "${cross_prefix:-$cc}" in *hardfloat*) enable vfp_args; fpabi=vfp ;; @@ -4334,7 +4350,7 @@ elif enabled ppc; then fi if enabled power8; then - test_cpp_condition "altivec.h" "defined(_ARCH_PWR8)" || disable power8 + check_cpp_condition power8 altivec.h "defined(_ARCH_PWR8)" fi elif enabled x86; then @@ -4655,8 +4671,7 @@ enabled libwavpack && require libwavpack wavpack/wavpack.h WavpackOpenFil enabled libwebp && require_pkg_config libwebp libwebp webp/encode.h WebPGetEncoderVersion enabled libx264 && require_pkg_config libx264 x264 "stdint.h x264.h" x264_encoder_encode && require_cpp_condition x264.h "X264_BUILD >= 118" && - { test_cpp_condition x264.h "X264_MPEG2" && - enable libx262; } + check_cpp_condition libx262 x264.h "X264_MPEG2" enabled libx265 && require_pkg_config libx265 x265 x265.h x265_api_get && require_cpp_condition x265.h "X265_BUILD >= 57" enabled libxavs && require libxavs "stdint.h xavs.h" xavs_encoder_encode -lxavs @@ -4696,7 +4711,7 @@ check_lib user32 "windows.h winuser.h" GetShellWindow -luser32 check_lib vfw32 "windows.h vfw.h" capCreateCaptureWindow -lvfw32 # check that WM_CAP_DRIVER_CONNECT is defined to the proper value # w32api 3.12 had it defined wrong -test_cpp_condition vfw.h "WM_CAP_DRIVER_CONNECT > WM_USER" && enable vfwcap_defines +check_cpp_condition vfwcap_defines vfw.h "WM_CAP_DRIVER_CONNECT > WM_USER" # check for ioctl_meteor.h, ioctl_bt848.h and alternatives check_header "dev/bktr/ioctl_meteor.h dev/bktr/ioctl_bt848.h" || @@ -4761,8 +4776,7 @@ enabled vaapi && enable vaapi_1 enabled vdpau && - test_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || - disable vdpau + check_cpp_condition vdpau vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" enabled vdpau && check_lib vdpau_x11 "vdpau/vdpau.h vdpau/vdpau_x11.h" vdp_device_create_x11 -lvdpau -lX11 @@ -4970,7 +4984,7 @@ elif enabled_any msvc icl; then disable inline_asm fi # msvcrt10 x64 incorrectly enables log2, only msvcrt12 (MSVC 2013) onwards actually has log2. - test_cpp_condition crtversion.h "_VC_CRT_MAJOR_VERSION >= 12" || disable log2 + check_cpp_condition log2 crtversion.h "_VC_CRT_MAJOR_VERSION >= 12" # The CRT headers contain __declspec(restrict) in a few places, but if redefining # restrict, this might break. MSVC 2010 and 2012 fail with __declspec(__restrict) # (as it ends up if the restrict redefine is done before including stdlib.h), while From 9c37d765ef28b027414f86b0088b0c282a3c46d8 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 17 Oct 2017 03:00:50 +0200 Subject: [PATCH 2044/2557] configure: Add check_cc/require_cc helper functions to simplify some expressions --- configure | 71 ++++++++++++++++++++++++++----------------------------- 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/configure b/configure index 9e90ab22c9c63..499d98f1bad61 100755 --- a/configure +++ b/configure @@ -1129,6 +1129,14 @@ check_compile_assert(){ test_code cc "$headers" "char c[2 * !!($condition) - 1]" "$@" && enable "$name" } +check_cc(){ + log check_cc "$@" + name=$1 + shift + disable "$name" + test_code cc "$@" && enable "$name" +} + require(){ log require "$@" name_version="$1" @@ -1137,6 +1145,13 @@ require(){ check_lib $name "$@" || die "ERROR: $name_version not found" } +require_cc(){ + log require_cc "$@" + name="$1" + shift + test_code cc "$@" || die "ERROR: $name failed" +} + require_header(){ log require_header "$@" headers="$1" @@ -4172,18 +4187,12 @@ extern_prefix=${sym%%ff_extern*} ! disabled inline_asm && check_inline_asm inline_asm '"" ::' for restrict_keyword in restrict __restrict__ __restrict ""; do - test_cc < Date: Fri, 20 Oct 2017 03:43:58 +0200 Subject: [PATCH 2045/2557] configure: Add check_ld() helper function to simplify some expressions --- configure | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 499d98f1bad61..5e350983dd814 100755 --- a/configure +++ b/configure @@ -850,6 +850,14 @@ test_ld(){ test_cmd $ld $LDFLAGS $flags $(ld_o $TMPE) $TMPO $libs $extralibs } +check_ld(){ + log check_ld "$@" + name=$1 + shift + disable $name + test_ld $@ && enable $name +} + print_include(){ hdr=$1 test "${hdr%.h}" = "${hdr}" && @@ -4267,8 +4275,8 @@ elif enabled arm; then : elif ! test_cpp_condition stddef.h "defined __ARM_PCS || defined __SOFTFP__" && [ $target_os != darwin ]; then case "${cross_prefix:-$cc}" in - *hardfloat*) enable vfp_args; fpabi=vfp ;; - *) test_ld < Date: Fri, 20 Oct 2017 04:43:13 +0200 Subject: [PATCH 2046/2557] configure: Add check_as() helper function to simplify some expressions --- configure | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/configure b/configure index 5e350983dd814..d59fc6fd1ae29 100755 --- a/configure +++ b/configure @@ -811,6 +811,17 @@ check_cmd(){ test_cmd $@ && enable $cmd } +check_as(){ + log check_as "$@" + name=$1 + code=$2 + shift 2 + disable $name + test_as $@ < Date: Wed, 28 Feb 2018 06:33:05 +0000 Subject: [PATCH 2047/2557] amf: Replace writer_id option with LIBAV_AMF_WRITER_ID constant AMFTraceWriter is an abstraction to configure how AMF outputs its logs for the current process and can be configured to output different levels of trace output. If multiple LibavWriter objects are used in one process, there will be duplication of output in av_log. Use a constant writer_id to prevent this scenario. Signed-off-by: Diego Biurrun --- libavcodec/amfenc.c | 8 +++++--- libavcodec/amfenc.h | 4 +--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index f305a48bf7d11..74b020b4d8a93 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -46,6 +46,8 @@ #include #endif +#define LIBAV_AMF_WRITER_ID L"libav_log" + #define PTS_PROP L"PtsProp" const enum AVPixelFormat ff_amf_pix_fmts[] = { @@ -171,8 +173,8 @@ static int amf_init_context(AVCodecContext *avctx) // connect AMF logger to av_log ctx->tracer.vtbl = &tracer_vtbl; ctx->tracer.avctx = avctx; - ctx->trace->pVtbl->RegisterWriter(ctx->trace, ctx->writer_id, (AMFTraceWriter*)&ctx->tracer, 1); - ctx->trace->pVtbl->SetWriterLevel(ctx->trace, ctx->writer_id, AMF_TRACE_TRACE); + ctx->trace->pVtbl->RegisterWriter(ctx->trace, LIBAV_AMF_WRITER_ID,(AMFTraceWriter *)&ctx->tracer, 1); + ctx->trace->pVtbl->SetWriterLevel(ctx->trace, LIBAV_AMF_WRITER_ID, AMF_TRACE_TRACE); res = ctx->factory->pVtbl->CreateContext(ctx->factory, &ctx->context); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext() failed with error %d\n", res); @@ -283,7 +285,7 @@ int av_cold ff_amf_encode_close(AVCodecContext *avctx) av_buffer_unref(&ctx->hw_frames_ctx); if (ctx->trace) { - ctx->trace->pVtbl->UnregisterWriter(ctx->trace, ctx->writer_id); + ctx->trace->pVtbl->UnregisterWriter(ctx->trace, LIBAV_AMF_WRITER_ID); } if (ctx->library) { dlclose(ctx->library); diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h index f3b82be7704fe..a8153ef12e8fd 100644 --- a/libavcodec/amfenc.h +++ b/libavcodec/amfenc.h @@ -80,7 +80,6 @@ typedef struct AmfContext { // common encoder options int log_to_dbg; - char *writer_id; // Static options, have to be set before Init() call int usage; @@ -152,7 +151,6 @@ extern const enum AVPixelFormat ff_amf_pix_fmts[]; } #define AMF_COMMON_OPTIONS \ - { "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, \ - { "writer_id", "Enable AMF logging to writer id", OFFSET(writer_id), AV_OPT_TYPE_STRING, { .str = "libavcodec" }, 0, 1, VE } \ + { "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE } \ #endif //AVCODEC_AMFENC_H From 23c91abe4f6a76d0a5066adf2abbf8cd66f1b1ec Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 6 Mar 2018 12:44:59 -0800 Subject: [PATCH 2048/2557] avcodec/aacdec: log configuration change details Signed-off-by: Aman Gupta Signed-off-by: Michael Niedermayer --- libavcodec/aacdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c index 44352764a7ae1..d394700cdc857 100644 --- a/libavcodec/aacdec.c +++ b/libavcodec/aacdec.c @@ -318,8 +318,8 @@ static int latm_decode_audio_specific_config(struct LATMContext *latmctx, ac->oc[1].m4ac.sample_rate != m4ac.sample_rate || ac->oc[1].m4ac.chan_config != m4ac.chan_config) { - if(latmctx->initialized) { - av_log(avctx, AV_LOG_INFO, "audio config changed\n"); + if (latmctx->initialized) { + av_log(avctx, AV_LOG_INFO, "audio config changed (sample_rate=%d, chan_config=%d)\n", m4ac.sample_rate, m4ac.chan_config); } else { av_log(avctx, AV_LOG_DEBUG, "initializing latmctx\n"); } From b59b59944693e645cdcf5e61b60f288820fe48c3 Mon Sep 17 00:00:00 2001 From: Matt Wolenetz Date: Mon, 5 Mar 2018 15:59:18 -0800 Subject: [PATCH 2049/2557] lavc/vorbisdec: Allow avcodec_open2 to call .close If there is a decoder initialization failure detected in avcodec_open2 after .init is called, allow graceful decoder .close to prevent leaking vorbis decoder allocations such as those from vorbis_parse_setup_*. BUG=772699 Signed-off-by: Michael Niedermayer --- libavcodec/vorbisdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/vorbisdec.c b/libavcodec/vorbisdec.c index 2a4f482031ef3..00e9cd8a1317b 100644 --- a/libavcodec/vorbisdec.c +++ b/libavcodec/vorbisdec.c @@ -1862,6 +1862,7 @@ AVCodec ff_vorbis_decoder = { .decode = vorbis_decode_frame, .flush = vorbis_decode_flush, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .channel_layouts = ff_vorbis_channel_layouts, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, From 5735a390a69df29b426d7626d63cd06baa30bc38 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 7 Mar 2018 10:03:46 +0100 Subject: [PATCH 2050/2557] avformat/internal: Document the freeing behavior of ff_alloc_extradata() Signed-off-by: Michael Niedermayer --- libavformat/internal.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/internal.h b/libavformat/internal.h index 2ac7e2e1a0b0a..a020b1b417d5c 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -580,6 +580,8 @@ static inline int ff_rename(const char *oldpath, const char *newpath, void *logc * Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end * which is always set to 0. * + * Previously allocated extradata in par will be freed. + * * @param size size of extradata * @return 0 if OK, AVERROR_xxx on error */ From c87bf5b6d0cd662c8d68672262ea5f056640206a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 5 Mar 2018 18:59:27 +0100 Subject: [PATCH 2051/2557] avfilter/vf_*_vaapi: Add missing AV_OPT_FLAG_FILTERING_PARAM Reviewed-by: Jun Zhao Signed-off-by: Michael Niedermayer --- libavfilter/vf_misc_vaapi.c | 2 +- libavfilter/vf_procamp_vaapi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_misc_vaapi.c b/libavfilter/vf_misc_vaapi.c index 8b179fe21553b..30b808a993460 100644 --- a/libavfilter/vf_misc_vaapi.c +++ b/libavfilter/vf_misc_vaapi.c @@ -226,7 +226,7 @@ static av_cold int sharpness_vaapi_init(AVFilterContext *avctx) } #define DOFFSET(x) offsetof(DenoiseVAAPIContext, x) -#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) static const AVOption denoise_vaapi_options[] = { { "denoise", "denoise level", DOFFSET(denoise), AV_OPT_TYPE_INT, { .i64 = DENOISE_DEFAULT }, DENOISE_MIN, DENOISE_MAX, .flags = FLAGS }, diff --git a/libavfilter/vf_procamp_vaapi.c b/libavfilter/vf_procamp_vaapi.c index 45a3120b23716..10eccbe97d783 100644 --- a/libavfilter/vf_procamp_vaapi.c +++ b/libavfilter/vf_procamp_vaapi.c @@ -214,7 +214,7 @@ static av_cold int procamp_vaapi_init(AVFilterContext *avctx) } #define OFFSET(x) offsetof(ProcampVAAPIContext, x) -#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) static const AVOption procamp_vaapi_options[] = { { "b", "Output video brightness", OFFSET(bright), AV_OPT_TYPE_FLOAT, { .dbl = BRIGHTNESS_DEFAULT }, BRIGHTNESS_MIN, BRIGHTNESS_MAX, .flags = FLAGS }, From 367929bed9def1ccdd9a0f4ac5b7b98d1993782d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 5 Mar 2018 23:12:57 +0100 Subject: [PATCH 2052/2557] avformat/mov: Fix integer overflow in mov_get_stsc_samples() Fixes: runtime error: signed integer overflow: 5 * -2147483647 cannot be represented in type 'int' Fixes: Chromium bug 817338 Reviewed-by: Matt Wolenetz Reported-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 95b9cd3f8bafa..7002a82787984 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2645,7 +2645,7 @@ static inline int mov_stsc_index_valid(unsigned int index, unsigned int count) } /* Compute the samples value for the stsc entry at the given index. */ -static inline int mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index) +static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index) { int chunk_count; @@ -2654,7 +2654,7 @@ static inline int mov_get_stsc_samples(MOVStreamContext *sc, unsigned int index) else chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1); - return sc->stsc_data[index].count * chunk_count; + return sc->stsc_data[index].count * (int64_t)chunk_count; } static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom) @@ -7189,12 +7189,13 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, /* adjust stsd index */ time_sample = 0; for (i = 0; i < sc->stsc_count; i++) { - int next = time_sample + mov_get_stsc_samples(sc, i); + int64_t next = time_sample + mov_get_stsc_samples(sc, i); if (next > sc->current_sample) { sc->stsc_index = i; sc->stsc_sample = sc->current_sample - time_sample; break; } + av_assert0(next == (int)next); time_sample = next; } From 3934aa495d786845d9f541c84ee405c096938f76 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 6 Mar 2018 18:14:12 +0100 Subject: [PATCH 2053/2557] libavformat/oggparsevorbis: Fix memleak on multiple headers Fixes: Chromium bug 800123 Reported-by: Matt Wolenetz Reviewed-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavformat/oggparsevorbis.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c index 29b1ab514e642..bcfd246b8dcf3 100644 --- a/libavformat/oggparsevorbis.c +++ b/libavformat/oggparsevorbis.c @@ -230,6 +230,10 @@ static int fixup_vorbis_headers(AVFormatContext *as, len = priv->len[0] + priv->len[1] + priv->len[2]; buf_len = len + len / 255 + 64; + + if (*buf) + return AVERROR_INVALIDDATA; + ptr = *buf = av_realloc(NULL, buf_len); if (!ptr) return AVERROR(ENOMEM); From da069e9c68ec1a54e618940dcb9ebae9bf179a32 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 6 Mar 2018 18:14:12 +0100 Subject: [PATCH 2054/2557] avformat/oggdec: Fix metadata memleak on multiple headers Fixes: Chromium bug 800123 Reported-by: Matt Wolenetz Reviewed-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavformat/oggdec.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 38f60653f98fa..27d16a3e4e5c0 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -128,7 +128,10 @@ static int ogg_restore(AVFormatContext *s) ogg->state = ost->next; for (i = 0; i < ogg->nstreams; i++) { - av_freep(&ogg->streams[i].buf); + struct ogg_stream *stream = &ogg->streams[i]; + av_freep(&stream->buf); + av_freep(&stream->new_metadata); + if (i >= ost->nstreams || !ost->streams[i].private) { free_stream(s, i); } From 1b1362e408cd6acb63fef126b814b0d16562aa8e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 7 Mar 2018 00:10:11 +0100 Subject: [PATCH 2055/2557] avformat/utils: Fix integer overflow of fps_first/last_dts Fixes: runtime error: signed integer overflow: 7738135736989908991 - -7898362169240453118 cannot be represented in type 'long' Fixes: Chromium bug 796778 Reported-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavformat/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index 3ca1ca24412ee..4d0b56c2a82af 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -3778,7 +3778,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if (st->info->fps_last_dts != AV_NOPTS_VALUE && st->info->fps_last_dts_idx > st->info->fps_first_dts_idx && (pkt->dts - st->info->fps_last_dts) / 1000 > - (st->info->fps_last_dts - st->info->fps_first_dts) / + (st->info->fps_last_dts - (uint64_t)st->info->fps_first_dts) / (st->info->fps_last_dts_idx - st->info->fps_first_dts_idx)) { av_log(ic, AV_LOG_WARNING, "DTS discontinuity in stream %d: packet %d with DTS " From ea0963181a2cc8e42a0c58da96fb7fed5e857e5b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 7 Mar 2018 21:36:12 +0100 Subject: [PATCH 2056/2557] avfilter/af_alimiter: check if buffer_size is valid Fixes #7050. Signed-off-by: Paul B Mahol --- libavfilter/af_alimiter.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavfilter/af_alimiter.c b/libavfilter/af_alimiter.c index 0fc8e6baa3fb7..c41e95576f760 100644 --- a/libavfilter/af_alimiter.c +++ b/libavfilter/af_alimiter.c @@ -327,6 +327,11 @@ static int config_input(AVFilterLink *inlink) s->buffer_size = inlink->sample_rate * s->attack * inlink->channels; s->buffer_size -= s->buffer_size % inlink->channels; + if (s->buffer_size <= 0) { + av_log(ctx, AV_LOG_ERROR, "Attack is too small.\n"); + return AVERROR(EINVAL); + } + return 0; } From 0b4ad86959cdd5c53474faf2c0b46e0f8a057fe1 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Wed, 20 Dec 2017 01:29:05 +0100 Subject: [PATCH 2057/2557] crc: add AV_CRC_8_SBC as a 8 bits CRC with polynomial 0x1D --- libavutil/crc.c | 26 ++++++++++++++++++++++++++ libavutil/crc.h | 1 + libavutil/tests/crc.c | 7 ++++--- tests/ref/fate/crc | 1 + 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/libavutil/crc.c b/libavutil/crc.c index d44550c9c007b..c45ea63a62217 100644 --- a/libavutil/crc.c +++ b/libavutil/crc.c @@ -52,6 +52,30 @@ static const AVCRC av_crc_table[AV_CRC_MAX][257] = { 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3, 0x01 }, + [AV_CRC_8_EBU] = { + 0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53, 0xE8, 0xF5, 0xD2, 0xCF, + 0x9C, 0x81, 0xA6, 0xBB, 0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E, + 0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76, 0x87, 0x9A, 0xBD, 0xA0, + 0xF3, 0xEE, 0xC9, 0xD4, 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C, + 0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19, 0xA2, 0xBF, 0x98, 0x85, + 0xD6, 0xCB, 0xEC, 0xF1, 0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40, + 0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8, 0xDE, 0xC3, 0xE4, 0xF9, + 0xAA, 0xB7, 0x90, 0x8D, 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65, + 0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7, 0x7C, 0x61, 0x46, 0x5B, + 0x08, 0x15, 0x32, 0x2F, 0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A, + 0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2, 0x26, 0x3B, 0x1C, 0x01, + 0x52, 0x4F, 0x68, 0x75, 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D, + 0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8, 0x03, 0x1E, 0x39, 0x24, + 0x77, 0x6A, 0x4D, 0x50, 0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2, + 0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A, 0x6C, 0x71, 0x56, 0x4B, + 0x18, 0x05, 0x22, 0x3F, 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7, + 0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66, 0xDD, 0xC0, 0xE7, 0xFA, + 0xA9, 0xB4, 0x93, 0x8E, 0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB, + 0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43, 0xB2, 0xAF, 0x88, 0x95, + 0xC6, 0xDB, 0xFC, 0xE1, 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09, + 0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C, 0x97, 0x8A, 0xAD, 0xB0, + 0xE3, 0xFE, 0xD9, 0xC4, 0x01 + }, [AV_CRC_16_ANSI] = { 0x0000, 0x0580, 0x0F80, 0x0A00, 0x1B80, 0x1E00, 0x1400, 0x1180, 0x3380, 0x3600, 0x3C00, 0x3980, 0x2800, 0x2D80, 0x2780, 0x2200, @@ -305,6 +329,7 @@ static void id ## _init_table_once(void) #define CRC_INIT_TABLE_ONCE(id) ff_thread_once(&id ## _once_control, id ## _init_table_once) DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_8_ATM, 0, 8, 0x07) +DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_8_EBU, 0, 8, 0x1D) DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_16_ANSI, 0, 16, 0x8005) DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_16_CCITT, 0, 16, 0x1021) DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_24_IEEE, 0, 24, 0x864CFB) @@ -351,6 +376,7 @@ const AVCRC *av_crc_get_table(AVCRCId crc_id) #if !CONFIG_HARDCODED_TABLES switch (crc_id) { case AV_CRC_8_ATM: CRC_INIT_TABLE_ONCE(AV_CRC_8_ATM); break; + case AV_CRC_8_EBU: CRC_INIT_TABLE_ONCE(AV_CRC_8_EBU); break; case AV_CRC_16_ANSI: CRC_INIT_TABLE_ONCE(AV_CRC_16_ANSI); break; case AV_CRC_16_CCITT: CRC_INIT_TABLE_ONCE(AV_CRC_16_CCITT); break; case AV_CRC_24_IEEE: CRC_INIT_TABLE_ONCE(AV_CRC_24_IEEE); break; diff --git a/libavutil/crc.h b/libavutil/crc.h index fe9a7c8fcbfee..47e22b4c7872b 100644 --- a/libavutil/crc.h +++ b/libavutil/crc.h @@ -54,6 +54,7 @@ typedef enum { AV_CRC_32_IEEE_LE, /*< reversed bitorder version of AV_CRC_32_IEEE */ AV_CRC_16_ANSI_LE, /*< reversed bitorder version of AV_CRC_16_ANSI */ AV_CRC_24_IEEE, + AV_CRC_8_EBU, AV_CRC_MAX, /*< Not part of public API! Do not use outside libavutil. */ }AVCRCId; diff --git a/libavutil/tests/crc.c b/libavutil/tests/crc.c index 9825d6bec9014..413aada8a2eb2 100644 --- a/libavutil/tests/crc.c +++ b/libavutil/tests/crc.c @@ -25,20 +25,21 @@ int main(void) { uint8_t buf[1999]; int i; - static const unsigned p[6][3] = { + static const unsigned p[7][3] = { { AV_CRC_32_IEEE_LE, 0xEDB88320, 0x3D5CDD04 }, { AV_CRC_32_IEEE , 0x04C11DB7, 0xC0F5BAE0 }, { AV_CRC_24_IEEE , 0x864CFB , 0xB704CE }, { AV_CRC_16_ANSI_LE, 0xA001 , 0xBFD8 }, { AV_CRC_16_ANSI , 0x8005 , 0x1FBB }, - { AV_CRC_8_ATM , 0x07 , 0xE3 } + { AV_CRC_8_ATM , 0x07 , 0xE3 }, + { AV_CRC_8_EBU , 0x1D , 0xD6 }, }; const AVCRC *ctx; for (i = 0; i < sizeof(buf); i++) buf[i] = i + i * i; - for (i = 0; i < 6; i++) { + for (i = 0; i < 7; i++) { ctx = av_crc_get_table(p[i][0]); printf("crc %08X = %X\n", p[i][1], av_crc(ctx, 0, buf, sizeof(buf))); } diff --git a/tests/ref/fate/crc b/tests/ref/fate/crc index 8aa0dd24481d3..7b59a3cc07ae3 100644 --- a/tests/ref/fate/crc +++ b/tests/ref/fate/crc @@ -4,3 +4,4 @@ crc 00864CFB = 326039 crc 0000A001 = BFD8 crc 00008005 = BB1F crc 00000007 = E3 +crc 0000001D = D6 From 4439887198025a9782f2ed52f8fda995269aad07 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sun, 17 Dec 2017 19:53:35 +0100 Subject: [PATCH 2058/2557] sbc: implement SBC decoder (low-complexity subband codec) This was originally based on libsbc, and was fully integrated into ffmpeg. --- doc/general.texi | 2 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/codec_desc.c | 7 + libavcodec/sbc.c | 271 ++++++++++++++++++++++++++++ libavcodec/sbc.h | 118 ++++++++++++ libavcodec/sbcdec.c | 379 +++++++++++++++++++++++++++++++++++++++ libavcodec/sbcdec_data.c | 127 +++++++++++++ libavcodec/sbcdec_data.h | 44 +++++ 10 files changed, 951 insertions(+) create mode 100644 libavcodec/sbc.c create mode 100644 libavcodec/sbc.h create mode 100644 libavcodec/sbcdec.c create mode 100644 libavcodec/sbcdec_data.c create mode 100644 libavcodec/sbcdec_data.h diff --git a/doc/general.texi b/doc/general.texi index 63aed348082db..91aad1c22d15a 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -1141,6 +1141,8 @@ following image formats are supported: @tab Real low bitrate AC-3 codec @item RealAudio Lossless @tab @tab X @item RealAudio SIPR / ACELP.NET @tab @tab X +@item SBC (low-complexity subband codec) @tab @tab X + @tab Used in Bluetooth A2DP @item Shorten @tab @tab X @item Sierra VMD audio @tab @tab X @tab Used in Sierra VMD files. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index b496f0dfb0c4d..7a9b248540691 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -587,6 +587,7 @@ OBJS-$(CONFIG_SUBVIEWER_DECODER) += subviewerdec.o ass.o OBJS-$(CONFIG_SUNRAST_DECODER) += sunrast.o OBJS-$(CONFIG_SUNRAST_ENCODER) += sunrastenc.o OBJS-$(CONFIG_LIBRSVG_DECODER) += librsvgdec.o +OBJS-$(CONFIG_SBC_DECODER) += sbcdec.o sbcdec_data.o sbc.o OBJS-$(CONFIG_SVQ1_DECODER) += svq1dec.o svq1.o svq13.o h263data.o OBJS-$(CONFIG_SVQ1_ENCODER) += svq1enc.o svq1.o h263data.o \ h263.o ituh263enc.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 70cbb7da0c86f..4ddf92f00687b 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -453,6 +453,7 @@ extern AVCodec ff_ra_144_encoder; extern AVCodec ff_ra_144_decoder; extern AVCodec ff_ra_288_decoder; extern AVCodec ff_ralf_decoder; +extern AVCodec ff_sbc_decoder; extern AVCodec ff_shorten_decoder; extern AVCodec ff_sipr_decoder; extern AVCodec ff_smackaud_decoder; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 1060ac453b474..769f210c077b5 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -636,6 +636,7 @@ enum AVCodecID { AV_CODEC_ID_DOLBY_E, AV_CODEC_ID_APTX, AV_CODEC_ID_APTX_HD, + AV_CODEC_ID_SBC, /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index f1ba6b13ac4a9..da7c0871a279e 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2870,6 +2870,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("aptX HD (Audio Processing Technology for Bluetooth)"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_SBC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "sbc", + .long_name = NULL_IF_CONFIG_SMALL("SBC (low-complexity subband codec)"), + .props = AV_CODEC_PROP_LOSSY, + }, /* subtitle codecs */ { diff --git a/libavcodec/sbc.c b/libavcodec/sbc.c new file mode 100644 index 0000000000000..f7dba79f4fe90 --- /dev/null +++ b/libavcodec/sbc.c @@ -0,0 +1,271 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2012-2013 Intel Corporation + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2008 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * SBC common functions for the encoder and decoder + */ + +#include "avcodec.h" +#include "sbc.h" + +/* A2DP specification: Appendix B, page 69 */ +static const int sbc_offset4[4][4] = { + { -1, 0, 0, 0 }, + { -2, 0, 0, 1 }, + { -2, 0, 0, 1 }, + { -2, 0, 0, 1 } +}; + +/* A2DP specification: Appendix B, page 69 */ +static const int sbc_offset8[4][8] = { + { -2, 0, 0, 0, 0, 0, 0, 1 }, + { -3, 0, 0, 0, 0, 0, 1, 2 }, + { -4, 0, 0, 0, 0, 0, 1, 2 }, + { -4, 0, 0, 0, 0, 0, 1, 2 } +}; + +/* + * Calculates the CRC-8 of the first len bits in data + */ +uint8_t sbc_crc8(const AVCRC *ctx, const uint8_t *data, size_t len) +{ + size_t byte_length = len >> 3; + int bit_length = len & 7; + uint8_t crc; + + crc = av_crc(ctx, 0x0F, data, byte_length); + + if (bit_length) { + uint8_t bits = data[byte_length]; + while (bit_length--) { + int8_t mask = bits ^ crc; + crc = (crc << 1) ^ ((mask >> 7) & 0x1D); + bits <<= 1; + } + } + + return crc; +} + +/* + * Code straight from the spec to calculate the bits array + * Takes a pointer to the frame in question and a pointer to the bits array + */ +void ff_sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8]) +{ + int subbands = frame->subbands; + uint8_t sf = frame->frequency; + + if (frame->mode == MONO || frame->mode == DUAL_CHANNEL) { + int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice; + int ch, sb; + + for (ch = 0; ch < frame->channels; ch++) { + max_bitneed = 0; + if (frame->allocation == SNR) { + for (sb = 0; sb < subbands; sb++) { + bitneed[ch][sb] = frame->scale_factor[ch][sb]; + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } + } else { + for (sb = 0; sb < subbands; sb++) { + if (frame->scale_factor[ch][sb] == 0) + bitneed[ch][sb] = -5; + else { + if (subbands == 4) + loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb]; + else + loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb]; + if (loudness > 0) + bitneed[ch][sb] = loudness / 2; + else + bitneed[ch][sb] = loudness; + } + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } + } + + bitcount = 0; + slicecount = 0; + bitslice = max_bitneed + 1; + do { + bitslice--; + bitcount += slicecount; + slicecount = 0; + for (sb = 0; sb < subbands; sb++) { + if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16)) + slicecount++; + else if (bitneed[ch][sb] == bitslice + 1) + slicecount += 2; + } + } while (bitcount + slicecount < frame->bitpool); + + if (bitcount + slicecount == frame->bitpool) { + bitcount += slicecount; + bitslice--; + } + + for (sb = 0; sb < subbands; sb++) { + if (bitneed[ch][sb] < bitslice + 2) + bits[ch][sb] = 0; + else { + bits[ch][sb] = bitneed[ch][sb] - bitslice; + if (bits[ch][sb] > 16) + bits[ch][sb] = 16; + } + } + + for (sb = 0; bitcount < frame->bitpool && + sb < subbands; sb++) { + if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) { + bits[ch][sb]++; + bitcount++; + } else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) { + bits[ch][sb] = 2; + bitcount += 2; + } + } + + for (sb = 0; bitcount < frame->bitpool && + sb < subbands; sb++) { + if (bits[ch][sb] < 16) { + bits[ch][sb]++; + bitcount++; + } + } + + } + + } else if (frame->mode == STEREO || frame->mode == JOINT_STEREO) { + int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice; + int ch, sb; + + max_bitneed = 0; + if (frame->allocation == SNR) { + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < subbands; sb++) { + bitneed[ch][sb] = frame->scale_factor[ch][sb]; + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } + } + } else { + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < subbands; sb++) { + if (frame->scale_factor[ch][sb] == 0) + bitneed[ch][sb] = -5; + else { + if (subbands == 4) + loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb]; + else + loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb]; + if (loudness > 0) + bitneed[ch][sb] = loudness / 2; + else + bitneed[ch][sb] = loudness; + } + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } + } + } + + bitcount = 0; + slicecount = 0; + bitslice = max_bitneed + 1; + do { + bitslice--; + bitcount += slicecount; + slicecount = 0; + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < subbands; sb++) { + if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16)) + slicecount++; + else if (bitneed[ch][sb] == bitslice + 1) + slicecount += 2; + } + } + } while (bitcount + slicecount < frame->bitpool); + + if (bitcount + slicecount == frame->bitpool) { + bitcount += slicecount; + bitslice--; + } + + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < subbands; sb++) { + if (bitneed[ch][sb] < bitslice + 2) { + bits[ch][sb] = 0; + } else { + bits[ch][sb] = bitneed[ch][sb] - bitslice; + if (bits[ch][sb] > 16) + bits[ch][sb] = 16; + } + } + } + + ch = 0; + sb = 0; + while (bitcount < frame->bitpool) { + if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) { + bits[ch][sb]++; + bitcount++; + } else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) { + bits[ch][sb] = 2; + bitcount += 2; + } + if (ch == 1) { + ch = 0; + sb++; + if (sb >= subbands) + break; + } else + ch = 1; + } + + ch = 0; + sb = 0; + while (bitcount < frame->bitpool) { + if (bits[ch][sb] < 16) { + bits[ch][sb]++; + bitcount++; + } + if (ch == 1) { + ch = 0; + sb++; + if (sb >= subbands) + break; + } else + ch = 1; + } + + } + +} diff --git a/libavcodec/sbc.h b/libavcodec/sbc.h new file mode 100644 index 0000000000000..405fadc3a6205 --- /dev/null +++ b/libavcodec/sbc.h @@ -0,0 +1,118 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2012-2014 Intel Corporation + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * SBC common definitions for the encoder and decoder + */ + +#ifndef AVCODEC_SBC_H +#define AVCODEC_SBC_H + +#include "avcodec.h" +#include "libavutil/crc.h" + +#define MSBC_BLOCKS 15 + +/* sampling frequency */ +#define SBC_FREQ_16000 0x00 +#define SBC_FREQ_32000 0x01 +#define SBC_FREQ_44100 0x02 +#define SBC_FREQ_48000 0x03 + +/* blocks */ +#define SBC_BLK_4 0x00 +#define SBC_BLK_8 0x01 +#define SBC_BLK_12 0x02 +#define SBC_BLK_16 0x03 + +/* channel mode */ +#define SBC_MODE_MONO 0x00 +#define SBC_MODE_DUAL_CHANNEL 0x01 +#define SBC_MODE_STEREO 0x02 +#define SBC_MODE_JOINT_STEREO 0x03 + +/* allocation method */ +#define SBC_AM_LOUDNESS 0x00 +#define SBC_AM_SNR 0x01 + +/* subbands */ +#define SBC_SB_4 0x00 +#define SBC_SB_8 0x01 + +/* synchronisation words */ +#define SBC_SYNCWORD 0x9C +#define MSBC_SYNCWORD 0xAD + +/* extra bits of precision for the synthesis filter input data */ +#define SBCDEC_FIXED_EXTRA_BITS 2 + +/* + * Enforce 16 byte alignment for the data, which is supposed to be used + * with SIMD optimized code. + */ +#define SBC_ALIGN 16 + +/* This structure contains an unpacked SBC frame. + Yes, there is probably quite some unused space herein */ +struct sbc_frame { + uint8_t frequency; + uint8_t blocks; + enum { + MONO = SBC_MODE_MONO, + DUAL_CHANNEL = SBC_MODE_DUAL_CHANNEL, + STEREO = SBC_MODE_STEREO, + JOINT_STEREO = SBC_MODE_JOINT_STEREO + } mode; + uint8_t channels; + enum { + LOUDNESS = SBC_AM_LOUDNESS, + SNR = SBC_AM_SNR + } allocation; + uint8_t subbands; + uint8_t bitpool; + uint16_t codesize; + + /* bit number x set means joint stereo has been used in subband x */ + uint8_t joint; + + /* only the lower 4 bits of every element are to be used */ + DECLARE_ALIGNED(SBC_ALIGN, uint32_t, scale_factor)[2][8]; + + /* raw integer subband samples in the frame */ + DECLARE_ALIGNED(SBC_ALIGN, int32_t, sb_sample_f)[16][2][8]; + + /* modified subband samples */ + DECLARE_ALIGNED(SBC_ALIGN, int32_t, sb_sample)[16][2][8]; + + const AVCRC *crc_ctx; +}; + +uint8_t sbc_crc8(const AVCRC *crc_ctx, const uint8_t *data, size_t len); +void ff_sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8]); + +#endif /* AVCODEC_SBC_H */ diff --git a/libavcodec/sbcdec.c b/libavcodec/sbcdec.c new file mode 100644 index 0000000000000..be703382ff5d3 --- /dev/null +++ b/libavcodec/sbcdec.c @@ -0,0 +1,379 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2012-2013 Intel Corporation + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2008 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * SBC decoder implementation + */ + +#include +#include "avcodec.h" +#include "internal.h" +#include "libavutil/intreadwrite.h" +#include "sbc.h" +#include "sbcdec_data.h" + +struct sbc_decoder_state { + int32_t V[2][170]; + int offset[2][16]; +}; + +typedef struct SBCDecContext { + AVClass *class; + DECLARE_ALIGNED(SBC_ALIGN, struct sbc_frame, frame); + DECLARE_ALIGNED(SBC_ALIGN, struct sbc_decoder_state, dsp); +} SBCDecContext; + +/* + * Unpacks a SBC frame at the beginning of the stream in data, + * which has at most len bytes into frame. + * Returns the length in bytes of the packed frame, or a negative + * value on error. The error codes are: + * + * -1 Data stream too short + * -2 Sync byte incorrect + * -3 CRC8 incorrect + * -4 Bitpool value out of bounds + */ +static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, + size_t len) +{ + unsigned int consumed; + /* Will copy the parts of the header that are relevant to crc + * calculation here */ + uint8_t crc_header[11] = { 0 }; + int crc_pos; + int32_t temp; + + uint32_t audio_sample; + int ch, sb, blk, bit; /* channel, subband, block and bit standard + counters */ + int bits[2][8]; /* bits distribution */ + uint32_t levels[2][8]; /* levels derived from that */ + + if (len < 4) + return -1; + + if (data[0] == MSBC_SYNCWORD) { + if (data[1] != 0) + return -2; + if (data[2] != 0) + return -2; + + frame->frequency = SBC_FREQ_16000; + frame->blocks = MSBC_BLOCKS; + frame->allocation = LOUDNESS; + frame->mode = MONO; + frame->channels = 1; + frame->subbands = 8; + frame->bitpool = 26; + } else if (data[0] == SBC_SYNCWORD) { + frame->frequency = (data[1] >> 6) & 0x03; + frame->blocks = 4 * ((data[1] >> 4) & 0x03) + 4; + frame->mode = (data[1] >> 2) & 0x03; + frame->channels = frame->mode == MONO ? 1 : 2; + frame->allocation = (data[1] >> 1) & 0x01; + frame->subbands = data[1] & 0x01 ? 8 : 4; + frame->bitpool = data[2]; + + if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) && + frame->bitpool > 16 * frame->subbands) + return -4; + + if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) && + frame->bitpool > 32 * frame->subbands) + return -4; + } else + return -2; + + consumed = 32; + crc_header[0] = data[1]; + crc_header[1] = data[2]; + crc_pos = 16; + + if (frame->mode == JOINT_STEREO) { + if (len * 8 < consumed + frame->subbands) + return -1; + + frame->joint = 0x00; + for (sb = 0; sb < frame->subbands - 1; sb++) + frame->joint |= ((data[4] >> (7 - sb)) & 0x01) << sb; + if (frame->subbands == 4) + crc_header[crc_pos / 8] = data[4] & 0xf0; + else + crc_header[crc_pos / 8] = data[4]; + + consumed += frame->subbands; + crc_pos += frame->subbands; + } + + if (len * 8 < consumed + (4 * frame->subbands * frame->channels)) + return -1; + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + /* FIXME assert(consumed % 4 == 0); */ + frame->scale_factor[ch][sb] = + (data[consumed >> 3] >> (4 - (consumed & 0x7))) & 0x0F; + crc_header[crc_pos >> 3] |= + frame->scale_factor[ch][sb] << (4 - (crc_pos & 0x7)); + + consumed += 4; + crc_pos += 4; + } + } + + if (data[3] != sbc_crc8(frame->crc_ctx, crc_header, crc_pos)) + return -3; + + ff_sbc_calculate_bits(frame, bits); + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) + levels[ch][sb] = (1 << bits[ch][sb]) - 1; + } + + for (blk = 0; blk < frame->blocks; blk++) { + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + uint32_t shift; + + if (levels[ch][sb] == 0) { + frame->sb_sample[blk][ch][sb] = 0; + continue; + } + + shift = frame->scale_factor[ch][sb] + + 1 + SBCDEC_FIXED_EXTRA_BITS; + + audio_sample = 0; + for (bit = 0; bit < bits[ch][sb]; bit++) { + if (consumed > len * 8) + return -1; + + if ((data[consumed >> 3] >> (7 - (consumed & 0x7))) & 0x01) + audio_sample |= 1 << (bits[ch][sb] - bit - 1); + + consumed++; + } + + frame->sb_sample[blk][ch][sb] = (int32_t) + (((((uint64_t) audio_sample << 1) | 1) << shift) / + levels[ch][sb]) - (1 << shift); + } + } + } + + if (frame->mode == JOINT_STEREO) { + for (blk = 0; blk < frame->blocks; blk++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (frame->joint & (0x01 << sb)) { + temp = frame->sb_sample[blk][0][sb] + + frame->sb_sample[blk][1][sb]; + frame->sb_sample[blk][1][sb] = + frame->sb_sample[blk][0][sb] - + frame->sb_sample[blk][1][sb]; + frame->sb_sample[blk][0][sb] = temp; + } + } + } + } + + if ((consumed & 0x7) != 0) + consumed += 8 - (consumed & 0x7); + + return consumed >> 3; +} + +static inline void sbc_synthesize_four(struct sbc_decoder_state *state, + struct sbc_frame *frame, + int ch, int blk, AVFrame *output_frame) +{ + int i, k, idx; + int32_t *v = state->V[ch]; + int *offset = state->offset[ch]; + + for (i = 0; i < 8; i++) { + /* Shifting */ + offset[i]--; + if (offset[i] < 0) { + offset[i] = 79; + memcpy(v + 80, v, 9 * sizeof(*v)); + } + + /* Distribute the new matrix value to the shifted position */ + v[offset[i]] = + ( ff_synmatrix4[i][0] * frame->sb_sample[blk][ch][0] + + ff_synmatrix4[i][1] * frame->sb_sample[blk][ch][1] + + ff_synmatrix4[i][2] * frame->sb_sample[blk][ch][2] + + ff_synmatrix4[i][3] * frame->sb_sample[blk][ch][3] ) >> 15; + } + + /* Compute the samples */ + for (idx = 0, i = 0; i < 4; i++, idx += 5) { + k = (i + 4) & 0xf; + + /* Store in output, Q0 */ + AV_WN16A(&output_frame->data[ch][blk * 8 + i * 2], av_clip_int16( + ( v[offset[i] + 0] * ff_sbc_proto_4_40m0[idx + 0] + + v[offset[k] + 1] * ff_sbc_proto_4_40m1[idx + 0] + + v[offset[i] + 2] * ff_sbc_proto_4_40m0[idx + 1] + + v[offset[k] + 3] * ff_sbc_proto_4_40m1[idx + 1] + + v[offset[i] + 4] * ff_sbc_proto_4_40m0[idx + 2] + + v[offset[k] + 5] * ff_sbc_proto_4_40m1[idx + 2] + + v[offset[i] + 6] * ff_sbc_proto_4_40m0[idx + 3] + + v[offset[k] + 7] * ff_sbc_proto_4_40m1[idx + 3] + + v[offset[i] + 8] * ff_sbc_proto_4_40m0[idx + 4] + + v[offset[k] + 9] * ff_sbc_proto_4_40m1[idx + 4] ) >> 15)); + } +} + +static inline void sbc_synthesize_eight(struct sbc_decoder_state *state, + struct sbc_frame *frame, + int ch, int blk, AVFrame *output_frame) +{ + int i, k, idx; + int32_t *v = state->V[ch]; + int *offset = state->offset[ch]; + + for (i = 0; i < 16; i++) { + /* Shifting */ + offset[i]--; + if (offset[i] < 0) { + offset[i] = 159; + memcpy(v + 160, v, 9 * sizeof(*v)); + } + + /* Distribute the new matrix value to the shifted position */ + v[offset[i]] = + ( ff_synmatrix8[i][0] * frame->sb_sample[blk][ch][0] + + ff_synmatrix8[i][1] * frame->sb_sample[blk][ch][1] + + ff_synmatrix8[i][2] * frame->sb_sample[blk][ch][2] + + ff_synmatrix8[i][3] * frame->sb_sample[blk][ch][3] + + ff_synmatrix8[i][4] * frame->sb_sample[blk][ch][4] + + ff_synmatrix8[i][5] * frame->sb_sample[blk][ch][5] + + ff_synmatrix8[i][6] * frame->sb_sample[blk][ch][6] + + ff_synmatrix8[i][7] * frame->sb_sample[blk][ch][7] ) >> 15; + } + + /* Compute the samples */ + for (idx = 0, i = 0; i < 8; i++, idx += 5) { + k = (i + 8) & 0xf; + + /* Store in output, Q0 */ + AV_WN16A(&output_frame->data[ch][blk * 16 + i * 2], av_clip_int16( + ( v[offset[i] + 0] * ff_sbc_proto_8_80m0[idx + 0] + + v[offset[k] + 1] * ff_sbc_proto_8_80m1[idx + 0] + + v[offset[i] + 2] * ff_sbc_proto_8_80m0[idx + 1] + + v[offset[k] + 3] * ff_sbc_proto_8_80m1[idx + 1] + + v[offset[i] + 4] * ff_sbc_proto_8_80m0[idx + 2] + + v[offset[k] + 5] * ff_sbc_proto_8_80m1[idx + 2] + + v[offset[i] + 6] * ff_sbc_proto_8_80m0[idx + 3] + + v[offset[k] + 7] * ff_sbc_proto_8_80m1[idx + 3] + + v[offset[i] + 8] * ff_sbc_proto_8_80m0[idx + 4] + + v[offset[k] + 9] * ff_sbc_proto_8_80m1[idx + 4] ) >> 15)); + } +} + +static void sbc_synthesize_audio(struct sbc_decoder_state *state, + struct sbc_frame *frame, AVFrame *output_frame) +{ + int ch, blk; + + switch (frame->subbands) { + case 4: + for (ch = 0; ch < frame->channels; ch++) + for (blk = 0; blk < frame->blocks; blk++) + sbc_synthesize_four(state, frame, ch, blk, output_frame); + break; + + case 8: + for (ch = 0; ch < frame->channels; ch++) + for (blk = 0; blk < frame->blocks; blk++) + sbc_synthesize_eight(state, frame, ch, blk, output_frame); + break; + } +} + +static int sbc_decode_init(AVCodecContext *avctx) +{ + SBCDecContext *sbc = avctx->priv_data; + int i, ch; + + sbc->frame.crc_ctx = av_crc_get_table(AV_CRC_8_EBU); + + memset(sbc->dsp.V, 0, sizeof(sbc->dsp.V)); + for (ch = 0; ch < 2; ch++) + for (i = 0; i < FF_ARRAY_ELEMS(sbc->dsp.offset[0]); i++) + sbc->dsp.offset[ch][i] = (10 * i + 10); + return 0; +} + +static int sbc_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame_ptr, + AVPacket *avpkt) +{ + SBCDecContext *sbc = avctx->priv_data; + AVFrame *frame = data; + int ret, frame_length; + + if (!sbc) + return AVERROR(EIO); + + frame_length = sbc_unpack_frame(avpkt->data, &sbc->frame, avpkt->size); + if (frame_length <= 0) + return frame_length; + + frame->channels = sbc->frame.channels; + frame->format = AV_SAMPLE_FMT_S16P; + frame->nb_samples = sbc->frame.blocks * sbc->frame.subbands; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + sbc_synthesize_audio(&sbc->dsp, &sbc->frame, frame); + + *got_frame_ptr = 1; + + return frame_length; +} + +AVCodec ff_sbc_decoder = { + .name = "sbc", + .long_name = NULL_IF_CONFIG_SMALL("SBC (low-complexity subband codec)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_SBC, + .priv_data_size = sizeof(SBCDecContext), + .init = sbc_decode_init, + .decode = sbc_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, 0}, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, + .supported_samplerates = (const int[]) { 16000, 32000, 44100, 48000, 0 }, +}; diff --git a/libavcodec/sbcdec_data.c b/libavcodec/sbcdec_data.c new file mode 100644 index 0000000000000..21521622075f3 --- /dev/null +++ b/libavcodec/sbcdec_data.c @@ -0,0 +1,127 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * SBC decoder tables + */ + +#include +#include "sbcdec_data.h" +#include "sbc.h" + +#define SS4(val) ((int32_t)val >> 12) +#define SS8(val) ((int32_t)val >> 14) +#define SN4(val) ((int32_t)val >> 11 + 1 + SBCDEC_FIXED_EXTRA_BITS) +#define SN8(val) ((int32_t)val >> 11 + 1 + SBCDEC_FIXED_EXTRA_BITS) + +const int32_t ff_sbc_proto_4_40m0[] = { + SS4(0x00000000), SS4(0xffa6982f), SS4(0xfba93848), SS4(0x0456c7b8), + SS4(0x005967d1), SS4(0xfffb9ac7), SS4(0xff589157), SS4(0xf9c2a8d8), + SS4(0x027c1434), SS4(0x0019118b), SS4(0xfff3c74c), SS4(0xff137330), + SS4(0xf81b8d70), SS4(0x00ec1b8b), SS4(0xfff0b71a), SS4(0xffe99b00), + SS4(0xfef84470), SS4(0xf6fb4370), SS4(0xffcdc351), SS4(0xffe01dc7) +}; + +const int32_t ff_sbc_proto_4_40m1[] = { + SS4(0xffe090ce), SS4(0xff2c0475), SS4(0xf694f800), SS4(0xff2c0475), + SS4(0xffe090ce), SS4(0xffe01dc7), SS4(0xffcdc351), SS4(0xf6fb4370), + SS4(0xfef84470), SS4(0xffe99b00), SS4(0xfff0b71a), SS4(0x00ec1b8b), + SS4(0xf81b8d70), SS4(0xff137330), SS4(0xfff3c74c), SS4(0x0019118b), + SS4(0x027c1434), SS4(0xf9c2a8d8), SS4(0xff589157), SS4(0xfffb9ac7) +}; + +const int32_t ff_sbc_proto_8_80m0[] = { + SS8(0x00000000), SS8(0xfe8d1970), SS8(0xee979f00), SS8(0x11686100), + SS8(0x0172e690), SS8(0xfff5bd1a), SS8(0xfdf1c8d4), SS8(0xeac182c0), + SS8(0x0d9daee0), SS8(0x00e530da), SS8(0xffe9811d), SS8(0xfd52986c), + SS8(0xe7054ca0), SS8(0x0a00d410), SS8(0x006c1de4), SS8(0xffdba705), + SS8(0xfcbc98e8), SS8(0xe3889d20), SS8(0x06af2308), SS8(0x000bb7db), + SS8(0xffca00ed), SS8(0xfc3fbb68), SS8(0xe071bc00), SS8(0x03bf7948), + SS8(0xffc4e05c), SS8(0xffb54b3b), SS8(0xfbedadc0), SS8(0xdde26200), + SS8(0x0142291c), SS8(0xff960e94), SS8(0xff9f3e17), SS8(0xfbd8f358), + SS8(0xdbf79400), SS8(0xff405e01), SS8(0xff7d4914), SS8(0xff8b1a31), + SS8(0xfc1417b8), SS8(0xdac7bb40), SS8(0xfdbb828c), SS8(0xff762170) +}; + +const int32_t ff_sbc_proto_8_80m1[] = { + SS8(0xff7c272c), SS8(0xfcb02620), SS8(0xda612700), SS8(0xfcb02620), + SS8(0xff7c272c), SS8(0xff762170), SS8(0xfdbb828c), SS8(0xdac7bb40), + SS8(0xfc1417b8), SS8(0xff8b1a31), SS8(0xff7d4914), SS8(0xff405e01), + SS8(0xdbf79400), SS8(0xfbd8f358), SS8(0xff9f3e17), SS8(0xff960e94), + SS8(0x0142291c), SS8(0xdde26200), SS8(0xfbedadc0), SS8(0xffb54b3b), + SS8(0xffc4e05c), SS8(0x03bf7948), SS8(0xe071bc00), SS8(0xfc3fbb68), + SS8(0xffca00ed), SS8(0x000bb7db), SS8(0x06af2308), SS8(0xe3889d20), + SS8(0xfcbc98e8), SS8(0xffdba705), SS8(0x006c1de4), SS8(0x0a00d410), + SS8(0xe7054ca0), SS8(0xfd52986c), SS8(0xffe9811d), SS8(0x00e530da), + SS8(0x0d9daee0), SS8(0xeac182c0), SS8(0xfdf1c8d4), SS8(0xfff5bd1a) +}; + +const int32_t ff_synmatrix4[8][4] = { + { SN4(0x05a82798), SN4(0xfa57d868), SN4(0xfa57d868), SN4(0x05a82798) }, + { SN4(0x030fbc54), SN4(0xf89be510), SN4(0x07641af0), SN4(0xfcf043ac) }, + { SN4(0x00000000), SN4(0x00000000), SN4(0x00000000), SN4(0x00000000) }, + { SN4(0xfcf043ac), SN4(0x07641af0), SN4(0xf89be510), SN4(0x030fbc54) }, + { SN4(0xfa57d868), SN4(0x05a82798), SN4(0x05a82798), SN4(0xfa57d868) }, + { SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) }, + { SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000) }, + { SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) } +}; + +const int32_t ff_synmatrix8[16][8] = { + { SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798), + SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798) }, + { SN8(0x0471ced0), SN8(0xf8275a10), SN8(0x018f8b84), SN8(0x06a6d988), + SN8(0xf9592678), SN8(0xfe70747c), SN8(0x07d8a5f0), SN8(0xfb8e3130) }, + { SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac), + SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54) }, + { SN8(0x018f8b84), SN8(0xfb8e3130), SN8(0x06a6d988), SN8(0xf8275a10), + SN8(0x07d8a5f0), SN8(0xf9592678), SN8(0x0471ced0), SN8(0xfe70747c) }, + { SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), + SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000) }, + { SN8(0xfe70747c), SN8(0x0471ced0), SN8(0xf9592678), SN8(0x07d8a5f0), + SN8(0xf8275a10), SN8(0x06a6d988), SN8(0xfb8e3130), SN8(0x018f8b84) }, + { SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54), + SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac) }, + { SN8(0xfb8e3130), SN8(0x07d8a5f0), SN8(0xfe70747c), SN8(0xf9592678), + SN8(0x06a6d988), SN8(0x018f8b84), SN8(0xf8275a10), SN8(0x0471ced0) }, + { SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868), + SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868) }, + { SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0), + SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) }, + { SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0), + SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) }, + { SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c), + SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) }, + { SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), + SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000) }, + { SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c), + SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) }, + { SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0), + SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) }, + { SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0), + SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) } +}; diff --git a/libavcodec/sbcdec_data.h b/libavcodec/sbcdec_data.h new file mode 100644 index 0000000000000..1b79d1de237f7 --- /dev/null +++ b/libavcodec/sbcdec_data.h @@ -0,0 +1,44 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * SBC decoder tables + */ + +#ifndef AVCODEC_SBCDEC_DATA_H +#define AVCODEC_SBCDEC_DATA_H + +#include + +extern const int32_t ff_sbc_proto_4_40m0[]; +extern const int32_t ff_sbc_proto_4_40m1[]; +extern const int32_t ff_sbc_proto_8_80m0[]; +extern const int32_t ff_sbc_proto_8_80m1[]; +extern const int32_t ff_synmatrix4[8][4]; +extern const int32_t ff_synmatrix8[16][8]; + +#endif /* AVCODEC_SBCDEC_DATA_H */ From 2505ebc632d4f3650d6082c58a8809faeb1ee832 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sat, 12 Aug 2017 02:35:06 +0200 Subject: [PATCH 2059/2557] sbc: add parser for SBC --- libavcodec/Makefile | 1 + libavcodec/parser.c | 1 + libavcodec/sbc_parser.c | 122 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 libavcodec/sbc_parser.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 7a9b248540691..01bc15d9b7475 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1022,6 +1022,7 @@ OBJS-$(CONFIG_PNG_PARSER) += png_parser.o OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o OBJS-$(CONFIG_RV40_PARSER) += rv34_parser.o +OBJS-$(CONFIG_SBC_PARSER) += sbc_parser.o OBJS-$(CONFIG_SIPR_PARSER) += sipr_parser.o OBJS-$(CONFIG_TAK_PARSER) += tak_parser.o tak.o OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o \ diff --git a/libavcodec/parser.c b/libavcodec/parser.c index 0c66e80b96ac6..f43b197d5eaca 100644 --- a/libavcodec/parser.c +++ b/libavcodec/parser.c @@ -65,6 +65,7 @@ extern AVCodecParser ff_png_parser; extern AVCodecParser ff_pnm_parser; extern AVCodecParser ff_rv30_parser; extern AVCodecParser ff_rv40_parser; +extern AVCodecParser ff_sbc_parser; extern AVCodecParser ff_sipr_parser; extern AVCodecParser ff_tak_parser; extern AVCodecParser ff_vc1_parser; diff --git a/libavcodec/sbc_parser.c b/libavcodec/sbc_parser.c new file mode 100644 index 0000000000000..f56564147a43e --- /dev/null +++ b/libavcodec/sbc_parser.c @@ -0,0 +1,122 @@ +/* + * SBC parser + * + * Copyright (C) 2017 Aurelien Jacobs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sbc.h" +#include "parser.h" + +typedef struct SBCParseContext { + ParseContext pc; + uint8_t header[3]; + int header_size; + int buffered_size; +} SBCParseContext; + +static int sbc_parse_header(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t *data, size_t len) +{ + static const int sample_rates[4] = { 16000, 32000, 44100, 48000 }; + int sr, blocks, mode, subbands, bitpool, channels, joint; + int length; + + if (len < 3) + return -1; + + if (data[0] == MSBC_SYNCWORD && data[1] == 0 && data[2] == 0) { + avctx->channels = 1; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + avctx->sample_rate = 16000; + avctx->frame_size = 120; + s->duration = avctx->frame_size; + return 57; + } + + if (data[0] != SBC_SYNCWORD) + return -2; + + sr = (data[1] >> 6) & 0x03; + blocks = (((data[1] >> 4) & 0x03) + 1) << 2; + mode = (data[1] >> 2) & 0x03; + subbands = (((data[1] >> 0) & 0x01) + 1) << 2; + bitpool = data[2]; + + channels = mode == SBC_MODE_MONO ? 1 : 2; + joint = mode == SBC_MODE_JOINT_STEREO; + + length = 4 + (subbands * channels) / 2 + + ((((mode == SBC_MODE_DUAL_CHANNEL) + 1) * blocks * bitpool + + (joint * subbands)) + 7) / 8; + + avctx->channels = channels; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + avctx->sample_rate = sample_rates[sr]; + avctx->frame_size = subbands * blocks; + s->duration = avctx->frame_size; + return length; +} + +static int sbc_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + SBCParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + if (pc->header_size) { + memcpy(pc->header + pc->header_size, buf, + sizeof(pc->header) - pc->header_size); + next = sbc_parse_header(s, avctx, pc->header, sizeof(pc->header)) + - pc->buffered_size; + pc->header_size = 0; + } else { + next = sbc_parse_header(s, avctx, buf, buf_size); + if (next >= buf_size) + next = -1; + } + + if (next < 0) { + pc->header_size = FFMIN(sizeof(pc->header), buf_size); + memcpy(pc->header, buf, pc->header_size); + pc->buffered_size = buf_size; + next = END_NOT_FOUND; + } + + if (ff_combine_frame(&pc->pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_sbc_parser = { + .codec_ids = { AV_CODEC_ID_SBC }, + .priv_data_size = sizeof(SBCParseContext), + .parser_parse = sbc_parse, + .parser_close = ff_parse_close, +}; From 2e08de08159df2079f1db2a7d8fe66e2ad2238d5 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sun, 17 Dec 2017 20:23:25 +0100 Subject: [PATCH 2060/2557] sbc: add raw demuxer for SBC --- doc/general.texi | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/sbcdec.c | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+) create mode 100644 libavformat/sbcdec.c diff --git a/doc/general.texi b/doc/general.texi index 91aad1c22d15a..5827af38418c8 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -501,6 +501,7 @@ library: @item raw NULL @tab X @tab @item raw video @tab X @tab X @item raw id RoQ @tab X @tab +@item raw SBC @tab @tab X @item raw Shorten @tab @tab X @item raw TAK @tab @tab X @item raw TrueHD @tab X @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index d90766e201971..3fad2cb0430eb 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -452,6 +452,7 @@ OBJS-$(CONFIG_S337M_DEMUXER) += s337m.o spdif.o OBJS-$(CONFIG_SAMI_DEMUXER) += samidec.o subtitles.o OBJS-$(CONFIG_SAP_DEMUXER) += sapdec.o OBJS-$(CONFIG_SAP_MUXER) += sapenc.o +OBJS-$(CONFIG_SBC_DEMUXER) += sbcdec.o rawdec.o OBJS-$(CONFIG_SBG_DEMUXER) += sbgdec.o OBJS-$(CONFIG_SCC_DEMUXER) += sccdec.o subtitles.o OBJS-$(CONFIG_SCC_MUXER) += sccenc.o subtitles.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 662e5054160a3..9c7f687a8e3da 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -354,6 +354,7 @@ extern AVInputFormat ff_s337m_demuxer; extern AVInputFormat ff_sami_demuxer; extern AVInputFormat ff_sap_demuxer; extern AVOutputFormat ff_sap_muxer; +extern AVInputFormat ff_sbc_demuxer; extern AVInputFormat ff_sbg_demuxer; extern AVInputFormat ff_scc_demuxer; extern AVOutputFormat ff_scc_muxer; diff --git a/libavformat/sbcdec.c b/libavformat/sbcdec.c new file mode 100644 index 0000000000000..ae74a220dc81a --- /dev/null +++ b/libavformat/sbcdec.c @@ -0,0 +1,33 @@ +/* + * RAW SBC demuxer + * Copyright (C) 2017 Aurelien Jacobs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" +#include "rawdec.h" + +AVInputFormat ff_sbc_demuxer = { + .name = "sbc", + .long_name = NULL_IF_CONFIG_SMALL("raw SBC (low-complexity subband codec)"), + .extensions = "sbc,msbc", + .raw_codec_id = AV_CODEC_ID_SBC, + .read_header = ff_raw_audio_read_header, + .read_packet = ff_raw_read_partial_packet, + .flags = AVFMT_GENERIC_INDEX, +}; From ff4600d95471a653073a961ec77f32e2f946684a Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sun, 17 Dec 2017 19:59:30 +0100 Subject: [PATCH 2061/2557] sbc: implement SBC encoder (low-complexity subband codec) This was originally based on libsbc, and was fully integrated into ffmpeg. --- doc/general.texi | 2 +- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 2 + libavcodec/options_table.h | 1 + libavcodec/profiles.c | 5 + libavcodec/profiles.h | 1 + libavcodec/sbcdsp.c | 382 +++++++++++++++++++++++++++++++++++++ libavcodec/sbcdsp.h | 83 ++++++++ libavcodec/sbcdsp_data.c | 329 ++++++++++++++++++++++++++++++++ libavcodec/sbcdsp_data.h | 55 ++++++ libavcodec/sbcenc.c | 361 +++++++++++++++++++++++++++++++++++ 12 files changed, 1222 insertions(+), 1 deletion(-) create mode 100644 libavcodec/sbcdsp.c create mode 100644 libavcodec/sbcdsp.h create mode 100644 libavcodec/sbcdsp_data.c create mode 100644 libavcodec/sbcdsp_data.h create mode 100644 libavcodec/sbcenc.c diff --git a/doc/general.texi b/doc/general.texi index 5827af38418c8..de13a7695e667 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -1142,7 +1142,7 @@ following image formats are supported: @tab Real low bitrate AC-3 codec @item RealAudio Lossless @tab @tab X @item RealAudio SIPR / ACELP.NET @tab @tab X -@item SBC (low-complexity subband codec) @tab @tab X +@item SBC (low-complexity subband codec) @tab X @tab X @tab Used in Bluetooth A2DP @item Shorten @tab @tab X @item Sierra VMD audio @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 01bc15d9b7475..ff6c9f8b2cf76 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -588,6 +588,7 @@ OBJS-$(CONFIG_SUNRAST_DECODER) += sunrast.o OBJS-$(CONFIG_SUNRAST_ENCODER) += sunrastenc.o OBJS-$(CONFIG_LIBRSVG_DECODER) += librsvgdec.o OBJS-$(CONFIG_SBC_DECODER) += sbcdec.o sbcdec_data.o sbc.o +OBJS-$(CONFIG_SBC_ENCODER) += sbcenc.o sbc.o sbcdsp.o sbcdsp_data.o OBJS-$(CONFIG_SVQ1_DECODER) += svq1dec.o svq1.o svq13.o h263data.o OBJS-$(CONFIG_SVQ1_ENCODER) += svq1enc.o svq1.o h263data.o \ h263.o ituh263enc.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4ddf92f00687b..71719595c63ec 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -453,6 +453,7 @@ extern AVCodec ff_ra_144_encoder; extern AVCodec ff_ra_144_decoder; extern AVCodec ff_ra_288_decoder; extern AVCodec ff_ralf_decoder; +extern AVCodec ff_sbc_encoder; extern AVCodec ff_sbc_decoder; extern AVCodec ff_shorten_decoder; extern AVCodec ff_sipr_decoder; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 769f210c077b5..a8322fb62a2f2 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2926,6 +2926,8 @@ typedef struct AVCodecContext { #define FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS 0xc3 #define FF_PROFILE_MJPEG_JPEG_LS 0xf7 +#define FF_PROFILE_SBC_MSBC 1 + /** * level * - encoding: Set by user. diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index ac9ce4b30196e..5a5eae65fba41 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -300,6 +300,7 @@ static const AVOption avcodec_options[] = { {"mpeg4_main", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG4_MAIN }, INT_MIN, INT_MAX, V|E, "profile"}, {"mpeg4_asp", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG4_ADVANCED_SIMPLE }, INT_MIN, INT_MAX, V|E, "profile"}, {"main10", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_HEVC_MAIN_10 }, INT_MIN, INT_MAX, V|E, "profile"}, +{"msbc", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_SBC_MSBC }, INT_MIN, INT_MAX, A|E, "profile"}, {"level", NULL, OFFSET(level), AV_OPT_TYPE_INT, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"}, {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"}, {"lowres", "decode at 1= 1/2, 2=1/4, 3=1/8 resolutions", OFFSET(lowres), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|A|D}, diff --git a/libavcodec/profiles.c b/libavcodec/profiles.c index 30498efedfc29..721587b3a6a00 100644 --- a/libavcodec/profiles.c +++ b/libavcodec/profiles.c @@ -140,4 +140,9 @@ const AVProfile ff_vp9_profiles[] = { { FF_PROFILE_UNKNOWN }, }; +const AVProfile ff_sbc_profiles[] = { + { FF_PROFILE_SBC_MSBC, "mSBC" }, + { FF_PROFILE_UNKNOWN }, +}; + #endif /* !CONFIG_SMALL */ diff --git a/libavcodec/profiles.h b/libavcodec/profiles.h index eb18b406af4c7..3783c10c397f7 100644 --- a/libavcodec/profiles.h +++ b/libavcodec/profiles.h @@ -31,5 +31,6 @@ extern const AVProfile ff_mpeg2_video_profiles[]; extern const AVProfile ff_mpeg4_video_profiles[]; extern const AVProfile ff_vc1_profiles[]; extern const AVProfile ff_vp9_profiles[]; +extern const AVProfile ff_sbc_profiles[]; #endif /* AVCODEC_PROFILES_H */ diff --git a/libavcodec/sbcdsp.c b/libavcodec/sbcdsp.c new file mode 100644 index 0000000000000..e155387f0d359 --- /dev/null +++ b/libavcodec/sbcdsp.c @@ -0,0 +1,382 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2012-2013 Intel Corporation + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * SBC basic "building bricks" + */ + +#include +#include +#include +#include "libavutil/common.h" +#include "libavutil/intmath.h" +#include "libavutil/intreadwrite.h" +#include "sbc.h" +#include "sbcdsp.h" +#include "sbcdsp_data.h" + +/* + * A reference C code of analysis filter with SIMD-friendly tables + * reordering and code layout. This code can be used to develop platform + * specific SIMD optimizations. Also it may be used as some kind of test + * for compiler autovectorization capabilities (who knows, if the compiler + * is very good at this stuff, hand optimized assembly may be not strictly + * needed for some platform). + * + * Note: It is also possible to make a simple variant of analysis filter, + * which needs only a single constants table without taking care about + * even/odd cases. This simple variant of filter can be implemented without + * input data permutation. The only thing that would be lost is the + * possibility to use pairwise SIMD multiplications. But for some simple + * CPU cores without SIMD extensions it can be useful. If anybody is + * interested in implementing such variant of a filter, sourcecode from + * bluez versions 4.26/4.27 can be used as a reference and the history of + * the changes in git repository done around that time may be worth checking. + */ + +static av_always_inline void sbc_analyze_simd(const int16_t *in, int32_t *out, + const int16_t *consts, + unsigned subbands) +{ + int32_t t1[8]; + int16_t t2[8]; + int i, j, hop = 0; + + /* rounding coefficient */ + for (i = 0; i < subbands; i++) + t1[i] = 1 << (SBC_PROTO_FIXED_SCALE - 1); + + /* low pass polyphase filter */ + for (hop = 0; hop < 10*subbands; hop += 2*subbands) + for (i = 0; i < 2*subbands; i++) + t1[i >> 1] += in[hop + i] * consts[hop + i]; + + /* scaling */ + for (i = 0; i < subbands; i++) + t2[i] = t1[i] >> SBC_PROTO_FIXED_SCALE; + + memset(t1, 0, sizeof(t1)); + + /* do the cos transform */ + for (i = 0; i < subbands/2; i++) + for (j = 0; j < 2*subbands; j++) + t1[j>>1] += t2[i * 2 + (j&1)] * consts[10*subbands + i*2*subbands + j]; + + for (i = 0; i < subbands; i++) + out[i] = t1[i] >> (SBC_COS_TABLE_FIXED_SCALE - SCALE_OUT_BITS); +} + +static void sbc_analyze_4_simd(const int16_t *in, int32_t *out, + const int16_t *consts) +{ + sbc_analyze_simd(in, out, consts, 4); +} + +static void sbc_analyze_8_simd(const int16_t *in, int32_t *out, + const int16_t *consts) +{ + sbc_analyze_simd(in, out, consts, 8); +} + +static inline void sbc_analyze_4b_4s_simd(SBCDSPContext *s, + int16_t *x, int32_t *out, int out_stride) +{ + /* Analyze blocks */ + s->sbc_analyze_4(x + 12, out, ff_sbcdsp_analysis_consts_fixed4_simd_odd); + out += out_stride; + s->sbc_analyze_4(x + 8, out, ff_sbcdsp_analysis_consts_fixed4_simd_even); + out += out_stride; + s->sbc_analyze_4(x + 4, out, ff_sbcdsp_analysis_consts_fixed4_simd_odd); + out += out_stride; + s->sbc_analyze_4(x + 0, out, ff_sbcdsp_analysis_consts_fixed4_simd_even); +} + +static inline void sbc_analyze_4b_8s_simd(SBCDSPContext *s, + int16_t *x, int32_t *out, int out_stride) +{ + /* Analyze blocks */ + s->sbc_analyze_8(x + 24, out, ff_sbcdsp_analysis_consts_fixed8_simd_odd); + out += out_stride; + s->sbc_analyze_8(x + 16, out, ff_sbcdsp_analysis_consts_fixed8_simd_even); + out += out_stride; + s->sbc_analyze_8(x + 8, out, ff_sbcdsp_analysis_consts_fixed8_simd_odd); + out += out_stride; + s->sbc_analyze_8(x + 0, out, ff_sbcdsp_analysis_consts_fixed8_simd_even); +} + +static inline void sbc_analyze_1b_8s_simd_even(SBCDSPContext *s, + int16_t *x, int32_t *out, + int out_stride); + +static inline void sbc_analyze_1b_8s_simd_odd(SBCDSPContext *s, + int16_t *x, int32_t *out, + int out_stride) +{ + s->sbc_analyze_8(x, out, ff_sbcdsp_analysis_consts_fixed8_simd_odd); + s->sbc_analyze_8s = sbc_analyze_1b_8s_simd_even; +} + +static inline void sbc_analyze_1b_8s_simd_even(SBCDSPContext *s, + int16_t *x, int32_t *out, + int out_stride) +{ + s->sbc_analyze_8(x, out, ff_sbcdsp_analysis_consts_fixed8_simd_even); + s->sbc_analyze_8s = sbc_analyze_1b_8s_simd_odd; +} + +/* + * Input data processing functions. The data is endian converted if needed, + * channels are deintrleaved and audio samples are reordered for use in + * SIMD-friendly analysis filter function. The results are put into "X" + * array, getting appended to the previous data (or it is better to say + * prepended, as the buffer is filled from top to bottom). Old data is + * discarded when neededed, but availability of (10 * nrof_subbands) + * contiguous samples is always guaranteed for the input to the analysis + * filter. This is achieved by copying a sufficient part of old data + * to the top of the buffer on buffer wraparound. + */ + +static int sbc_enc_process_input_4s(int position, const uint8_t *pcm, + int16_t X[2][SBC_X_BUFFER_SIZE], + int nsamples, int nchannels) +{ + int c; + + /* handle X buffer wraparound */ + if (position < nsamples) { + for (c = 0; c < nchannels; c++) + memcpy(&X[c][SBC_X_BUFFER_SIZE - 40], &X[c][position], + 36 * sizeof(int16_t)); + position = SBC_X_BUFFER_SIZE - 40; + } + + /* copy/permutate audio samples */ + for (; nsamples >= 8; nsamples -= 8, pcm += 16 * nchannels) { + position -= 8; + for (c = 0; c < nchannels; c++) { + int16_t *x = &X[c][position]; + x[0] = AV_RN16(pcm + 14*nchannels + 2*c); + x[1] = AV_RN16(pcm + 6*nchannels + 2*c); + x[2] = AV_RN16(pcm + 12*nchannels + 2*c); + x[3] = AV_RN16(pcm + 8*nchannels + 2*c); + x[4] = AV_RN16(pcm + 0*nchannels + 2*c); + x[5] = AV_RN16(pcm + 4*nchannels + 2*c); + x[6] = AV_RN16(pcm + 2*nchannels + 2*c); + x[7] = AV_RN16(pcm + 10*nchannels + 2*c); + } + } + + return position; +} + +static int sbc_enc_process_input_8s(int position, const uint8_t *pcm, + int16_t X[2][SBC_X_BUFFER_SIZE], + int nsamples, int nchannels) +{ + int c; + + /* handle X buffer wraparound */ + if (position < nsamples) { + for (c = 0; c < nchannels; c++) + memcpy(&X[c][SBC_X_BUFFER_SIZE - 72], &X[c][position], + 72 * sizeof(int16_t)); + position = SBC_X_BUFFER_SIZE - 72; + } + + if (position % 16 == 8) { + position -= 8; + nsamples -= 8; + for (c = 0; c < nchannels; c++) { + int16_t *x = &X[c][position]; + x[0] = AV_RN16(pcm + 14*nchannels + 2*c); + x[2] = AV_RN16(pcm + 12*nchannels + 2*c); + x[3] = AV_RN16(pcm + 0*nchannels + 2*c); + x[4] = AV_RN16(pcm + 10*nchannels + 2*c); + x[5] = AV_RN16(pcm + 2*nchannels + 2*c); + x[6] = AV_RN16(pcm + 8*nchannels + 2*c); + x[7] = AV_RN16(pcm + 4*nchannels + 2*c); + x[8] = AV_RN16(pcm + 6*nchannels + 2*c); + } + pcm += 16 * nchannels; + } + + /* copy/permutate audio samples */ + for (; nsamples >= 16; nsamples -= 16, pcm += 32 * nchannels) { + position -= 16; + for (c = 0; c < nchannels; c++) { + int16_t *x = &X[c][position]; + x[0] = AV_RN16(pcm + 30*nchannels + 2*c); + x[1] = AV_RN16(pcm + 14*nchannels + 2*c); + x[2] = AV_RN16(pcm + 28*nchannels + 2*c); + x[3] = AV_RN16(pcm + 16*nchannels + 2*c); + x[4] = AV_RN16(pcm + 26*nchannels + 2*c); + x[5] = AV_RN16(pcm + 18*nchannels + 2*c); + x[6] = AV_RN16(pcm + 24*nchannels + 2*c); + x[7] = AV_RN16(pcm + 20*nchannels + 2*c); + x[8] = AV_RN16(pcm + 22*nchannels + 2*c); + x[9] = AV_RN16(pcm + 6*nchannels + 2*c); + x[10] = AV_RN16(pcm + 12*nchannels + 2*c); + x[11] = AV_RN16(pcm + 0*nchannels + 2*c); + x[12] = AV_RN16(pcm + 10*nchannels + 2*c); + x[13] = AV_RN16(pcm + 2*nchannels + 2*c); + x[14] = AV_RN16(pcm + 8*nchannels + 2*c); + x[15] = AV_RN16(pcm + 4*nchannels + 2*c); + } + } + + if (nsamples == 8) { + position -= 8; + for (c = 0; c < nchannels; c++) { + int16_t *x = &X[c][position]; + x[-7] = AV_RN16(pcm + 14*nchannels + 2*c); + x[1] = AV_RN16(pcm + 6*nchannels + 2*c); + x[2] = AV_RN16(pcm + 12*nchannels + 2*c); + x[3] = AV_RN16(pcm + 0*nchannels + 2*c); + x[4] = AV_RN16(pcm + 10*nchannels + 2*c); + x[5] = AV_RN16(pcm + 2*nchannels + 2*c); + x[6] = AV_RN16(pcm + 8*nchannels + 2*c); + x[7] = AV_RN16(pcm + 4*nchannels + 2*c); + } + } + + return position; +} + +static void sbc_calc_scalefactors(int32_t sb_sample_f[16][2][8], + uint32_t scale_factor[2][8], + int blocks, int channels, int subbands) +{ + int ch, sb, blk; + for (ch = 0; ch < channels; ch++) { + for (sb = 0; sb < subbands; sb++) { + uint32_t x = 1 << SCALE_OUT_BITS; + for (blk = 0; blk < blocks; blk++) { + int32_t tmp = FFABS(sb_sample_f[blk][ch][sb]); + if (tmp != 0) + x |= tmp - 1; + } + scale_factor[ch][sb] = (31 - SCALE_OUT_BITS) - ff_clz(x); + } + } +} + +static int sbc_calc_scalefactors_j(int32_t sb_sample_f[16][2][8], + uint32_t scale_factor[2][8], + int blocks, int subbands) +{ + int blk, joint = 0; + int32_t tmp0, tmp1; + uint32_t x, y; + + /* last subband does not use joint stereo */ + int sb = subbands - 1; + x = 1 << SCALE_OUT_BITS; + y = 1 << SCALE_OUT_BITS; + for (blk = 0; blk < blocks; blk++) { + tmp0 = FFABS(sb_sample_f[blk][0][sb]); + tmp1 = FFABS(sb_sample_f[blk][1][sb]); + if (tmp0 != 0) + x |= tmp0 - 1; + if (tmp1 != 0) + y |= tmp1 - 1; + } + scale_factor[0][sb] = (31 - SCALE_OUT_BITS) - ff_clz(x); + scale_factor[1][sb] = (31 - SCALE_OUT_BITS) - ff_clz(y); + + /* the rest of subbands can use joint stereo */ + while (--sb >= 0) { + int32_t sb_sample_j[16][2]; + x = 1 << SCALE_OUT_BITS; + y = 1 << SCALE_OUT_BITS; + for (blk = 0; blk < blocks; blk++) { + tmp0 = sb_sample_f[blk][0][sb]; + tmp1 = sb_sample_f[blk][1][sb]; + sb_sample_j[blk][0] = (tmp0 >> 1) + (tmp1 >> 1); + sb_sample_j[blk][1] = (tmp0 >> 1) - (tmp1 >> 1); + tmp0 = FFABS(tmp0); + tmp1 = FFABS(tmp1); + if (tmp0 != 0) + x |= tmp0 - 1; + if (tmp1 != 0) + y |= tmp1 - 1; + } + scale_factor[0][sb] = (31 - SCALE_OUT_BITS) - + ff_clz(x); + scale_factor[1][sb] = (31 - SCALE_OUT_BITS) - + ff_clz(y); + x = 1 << SCALE_OUT_BITS; + y = 1 << SCALE_OUT_BITS; + for (blk = 0; blk < blocks; blk++) { + tmp0 = FFABS(sb_sample_j[blk][0]); + tmp1 = FFABS(sb_sample_j[blk][1]); + if (tmp0 != 0) + x |= tmp0 - 1; + if (tmp1 != 0) + y |= tmp1 - 1; + } + x = (31 - SCALE_OUT_BITS) - ff_clz(x); + y = (31 - SCALE_OUT_BITS) - ff_clz(y); + + /* decide whether to use joint stereo for this subband */ + if ((scale_factor[0][sb] + scale_factor[1][sb]) > x + y) { + joint |= 1 << (subbands - 1 - sb); + scale_factor[0][sb] = x; + scale_factor[1][sb] = y; + for (blk = 0; blk < blocks; blk++) { + sb_sample_f[blk][0][sb] = sb_sample_j[blk][0]; + sb_sample_f[blk][1][sb] = sb_sample_j[blk][1]; + } + } + } + + /* bitmask with the information about subbands using joint stereo */ + return joint; +} + +/* + * Detect CPU features and setup function pointers + */ +av_cold void ff_sbcdsp_init(SBCDSPContext *s) +{ + /* Default implementation for analyze functions */ + s->sbc_analyze_4 = sbc_analyze_4_simd; + s->sbc_analyze_8 = sbc_analyze_8_simd; + s->sbc_analyze_4s = sbc_analyze_4b_4s_simd; + if (s->increment == 1) + s->sbc_analyze_8s = sbc_analyze_1b_8s_simd_odd; + else + s->sbc_analyze_8s = sbc_analyze_4b_8s_simd; + + /* Default implementation for input reordering / deinterleaving */ + s->sbc_enc_process_input_4s = sbc_enc_process_input_4s; + s->sbc_enc_process_input_8s = sbc_enc_process_input_8s; + + /* Default implementation for scale factors calculation */ + s->sbc_calc_scalefactors = sbc_calc_scalefactors; + s->sbc_calc_scalefactors_j = sbc_calc_scalefactors_j; +} diff --git a/libavcodec/sbcdsp.h b/libavcodec/sbcdsp.h new file mode 100644 index 0000000000000..66ed7d324eb0e --- /dev/null +++ b/libavcodec/sbcdsp.h @@ -0,0 +1,83 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * SBC basic "building bricks" + */ + +#ifndef AVCODEC_SBCDSP_H +#define AVCODEC_SBCDSP_H + +#include "sbc.h" +#include "sbcdsp_data.h" + +#define SCALE_OUT_BITS 15 +#define SBC_X_BUFFER_SIZE 328 + +typedef struct sbc_dsp_context SBCDSPContext; + +struct sbc_dsp_context { + int position; + /* Number of consecutive blocks handled by the encoder */ + uint8_t increment; + DECLARE_ALIGNED(SBC_ALIGN, int16_t, X)[2][SBC_X_BUFFER_SIZE]; + void (*sbc_analyze_4)(const int16_t *in, int32_t *out, const int16_t *consts); + void (*sbc_analyze_8)(const int16_t *in, int32_t *out, const int16_t *consts); + /* Polyphase analysis filter for 4 subbands configuration, + * it handles "increment" blocks at once */ + void (*sbc_analyze_4s)(SBCDSPContext *s, + int16_t *x, int32_t *out, int out_stride); + /* Polyphase analysis filter for 8 subbands configuration, + * it handles "increment" blocks at once */ + void (*sbc_analyze_8s)(SBCDSPContext *s, + int16_t *x, int32_t *out, int out_stride); + /* Process input data (deinterleave, endian conversion, reordering), + * depending on the number of subbands and input data byte order */ + int (*sbc_enc_process_input_4s)(int position, const uint8_t *pcm, + int16_t X[2][SBC_X_BUFFER_SIZE], + int nsamples, int nchannels); + int (*sbc_enc_process_input_8s)(int position, const uint8_t *pcm, + int16_t X[2][SBC_X_BUFFER_SIZE], + int nsamples, int nchannels); + /* Scale factors calculation */ + void (*sbc_calc_scalefactors)(int32_t sb_sample_f[16][2][8], + uint32_t scale_factor[2][8], + int blocks, int channels, int subbands); + /* Scale factors calculation with joint stereo support */ + int (*sbc_calc_scalefactors_j)(int32_t sb_sample_f[16][2][8], + uint32_t scale_factor[2][8], + int blocks, int subbands); +}; + +/* + * Initialize pointers to the functions which are the basic "building bricks" + * of SBC codec. Best implementation is selected based on target CPU + * capabilities. + */ +void ff_sbcdsp_init(SBCDSPContext *s); + +#endif /* AVCODEC_SBCDSP_H */ diff --git a/libavcodec/sbcdsp_data.c b/libavcodec/sbcdsp_data.c new file mode 100644 index 0000000000000..78c07c0077181 --- /dev/null +++ b/libavcodec/sbcdsp_data.c @@ -0,0 +1,329 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * miscellaneous SBC tables + */ + +#include "sbcdsp_data.h" + +#define F_PROTO(x) ((int32_t) (((x) * 2) * ((int32_t) 1 << 15) + 0.5)) +#define F_COS(x) ((int32_t) (((x) ) * ((int32_t) 1 << 15) + 0.5)) + +/* + * Constant tables for the use in SIMD optimized analysis filters + * Each table consists of two parts: + * 1. reordered "proto" table + * 2. reordered "cos" table + * + * Due to non-symmetrical reordering, separate tables for "even" + * and "odd" cases are needed + */ + +DECLARE_ALIGNED(SBC_ALIGN, const int16_t, ff_sbcdsp_analysis_consts_fixed4_simd_even)[40 + 16] = { +#define C0 1.0932568993 +#define C1 1.3056875580 +#define C2 1.3056875580 +#define C3 1.6772280856 + +#define F(x) F_PROTO(x) + F(0.00000000E+00 * C0), F(3.83720193E-03 * C0), + F(5.36548976E-04 * C1), F(2.73370904E-03 * C1), + F(3.06012286E-03 * C2), F(3.89205149E-03 * C2), + F(0.00000000E+00 * C3), -F(1.49188357E-03 * C3), + F(1.09137620E-02 * C0), F(2.58767811E-02 * C0), + F(2.04385087E-02 * C1), F(3.21939290E-02 * C1), + F(7.76463494E-02 * C2), F(6.13245186E-03 * C2), + F(0.00000000E+00 * C3), -F(2.88757392E-02 * C3), + F(1.35593274E-01 * C0), F(2.94315332E-01 * C0), + F(1.94987841E-01 * C1), F(2.81828203E-01 * C1), + -F(1.94987841E-01 * C2), F(2.81828203E-01 * C2), + F(0.00000000E+00 * C3), -F(2.46636662E-01 * C3), + -F(1.35593274E-01 * C0), F(2.58767811E-02 * C0), + -F(7.76463494E-02 * C1), F(6.13245186E-03 * C1), + -F(2.04385087E-02 * C2), F(3.21939290E-02 * C2), + F(0.00000000E+00 * C3), F(2.88217274E-02 * C3), + -F(1.09137620E-02 * C0), F(3.83720193E-03 * C0), + -F(3.06012286E-03 * C1), F(3.89205149E-03 * C1), + -F(5.36548976E-04 * C2), F(2.73370904E-03 * C2), + F(0.00000000E+00 * C3), -F(1.86581691E-03 * C3), +#undef F +#define F(x) F_COS(x) + F(0.7071067812 / C0), F(0.9238795325 / C1), + -F(0.7071067812 / C0), F(0.3826834324 / C1), + -F(0.7071067812 / C0), -F(0.3826834324 / C1), + F(0.7071067812 / C0), -F(0.9238795325 / C1), + F(0.3826834324 / C2), -F(1.0000000000 / C3), + -F(0.9238795325 / C2), -F(1.0000000000 / C3), + F(0.9238795325 / C2), -F(1.0000000000 / C3), + -F(0.3826834324 / C2), -F(1.0000000000 / C3), +#undef F + +#undef C0 +#undef C1 +#undef C2 +#undef C3 +}; + +DECLARE_ALIGNED(SBC_ALIGN, const int16_t, ff_sbcdsp_analysis_consts_fixed4_simd_odd)[40 + 16] = { +#define C0 1.3056875580 +#define C1 1.6772280856 +#define C2 1.0932568993 +#define C3 1.3056875580 + +#define F(x) F_PROTO(x) + F(2.73370904E-03 * C0), F(5.36548976E-04 * C0), + -F(1.49188357E-03 * C1), F(0.00000000E+00 * C1), + F(3.83720193E-03 * C2), F(1.09137620E-02 * C2), + F(3.89205149E-03 * C3), F(3.06012286E-03 * C3), + F(3.21939290E-02 * C0), F(2.04385087E-02 * C0), + -F(2.88757392E-02 * C1), F(0.00000000E+00 * C1), + F(2.58767811E-02 * C2), F(1.35593274E-01 * C2), + F(6.13245186E-03 * C3), F(7.76463494E-02 * C3), + F(2.81828203E-01 * C0), F(1.94987841E-01 * C0), + -F(2.46636662E-01 * C1), F(0.00000000E+00 * C1), + F(2.94315332E-01 * C2), -F(1.35593274E-01 * C2), + F(2.81828203E-01 * C3), -F(1.94987841E-01 * C3), + F(6.13245186E-03 * C0), -F(7.76463494E-02 * C0), + F(2.88217274E-02 * C1), F(0.00000000E+00 * C1), + F(2.58767811E-02 * C2), -F(1.09137620E-02 * C2), + F(3.21939290E-02 * C3), -F(2.04385087E-02 * C3), + F(3.89205149E-03 * C0), -F(3.06012286E-03 * C0), + -F(1.86581691E-03 * C1), F(0.00000000E+00 * C1), + F(3.83720193E-03 * C2), F(0.00000000E+00 * C2), + F(2.73370904E-03 * C3), -F(5.36548976E-04 * C3), +#undef F +#define F(x) F_COS(x) + F(0.9238795325 / C0), -F(1.0000000000 / C1), + F(0.3826834324 / C0), -F(1.0000000000 / C1), + -F(0.3826834324 / C0), -F(1.0000000000 / C1), + -F(0.9238795325 / C0), -F(1.0000000000 / C1), + F(0.7071067812 / C2), F(0.3826834324 / C3), + -F(0.7071067812 / C2), -F(0.9238795325 / C3), + -F(0.7071067812 / C2), F(0.9238795325 / C3), + F(0.7071067812 / C2), -F(0.3826834324 / C3), +#undef F + +#undef C0 +#undef C1 +#undef C2 +#undef C3 +}; + +DECLARE_ALIGNED(SBC_ALIGN, const int16_t, ff_sbcdsp_analysis_consts_fixed8_simd_even)[80 + 64] = { +#define C0 2.7906148894 +#define C1 2.4270044280 +#define C2 2.8015616024 +#define C3 3.1710363741 +#define C4 2.5377944043 +#define C5 2.4270044280 +#define C6 2.8015616024 +#define C7 3.1710363741 + +#define F(x) F_PROTO(x) + F(0.00000000E+00 * C0), F(2.01182542E-03 * C0), + F(1.56575398E-04 * C1), F(1.78371725E-03 * C1), + F(3.43256425E-04 * C2), F(1.47640169E-03 * C2), + F(5.54620202E-04 * C3), F(1.13992507E-03 * C3), + -F(8.23919506E-04 * C4), F(0.00000000E+00 * C4), + F(2.10371989E-03 * C5), F(3.49717454E-03 * C5), + F(1.99454554E-03 * C6), F(1.64973098E-03 * C6), + F(1.61656283E-03 * C7), F(1.78805361E-04 * C7), + F(5.65949473E-03 * C0), F(1.29371806E-02 * C0), + F(8.02941163E-03 * C1), F(1.53184106E-02 * C1), + F(1.04584443E-02 * C2), F(1.62208471E-02 * C2), + F(1.27472335E-02 * C3), F(1.59045603E-02 * C3), + -F(1.46525263E-02 * C4), F(0.00000000E+00 * C4), + F(8.85757540E-03 * C5), F(5.31873032E-02 * C5), + F(2.92408442E-03 * C6), F(3.90751381E-02 * C6), + -F(4.91578024E-03 * C7), F(2.61098752E-02 * C7), + F(6.79989431E-02 * C0), F(1.46955068E-01 * C0), + F(8.29847578E-02 * C1), F(1.45389847E-01 * C1), + F(9.75753918E-02 * C2), F(1.40753505E-01 * C2), + F(1.11196689E-01 * C3), F(1.33264415E-01 * C3), + -F(1.23264548E-01 * C4), F(0.00000000E+00 * C4), + F(1.45389847E-01 * C5), -F(8.29847578E-02 * C5), + F(1.40753505E-01 * C6), -F(9.75753918E-02 * C6), + F(1.33264415E-01 * C7), -F(1.11196689E-01 * C7), + -F(6.79989431E-02 * C0), F(1.29371806E-02 * C0), + -F(5.31873032E-02 * C1), F(8.85757540E-03 * C1), + -F(3.90751381E-02 * C2), F(2.92408442E-03 * C2), + -F(2.61098752E-02 * C3), -F(4.91578024E-03 * C3), + F(1.46404076E-02 * C4), F(0.00000000E+00 * C4), + F(1.53184106E-02 * C5), -F(8.02941163E-03 * C5), + F(1.62208471E-02 * C6), -F(1.04584443E-02 * C6), + F(1.59045603E-02 * C7), -F(1.27472335E-02 * C7), + -F(5.65949473E-03 * C0), F(2.01182542E-03 * C0), + -F(3.49717454E-03 * C1), F(2.10371989E-03 * C1), + -F(1.64973098E-03 * C2), F(1.99454554E-03 * C2), + -F(1.78805361E-04 * C3), F(1.61656283E-03 * C3), + -F(9.02154502E-04 * C4), F(0.00000000E+00 * C4), + F(1.78371725E-03 * C5), -F(1.56575398E-04 * C5), + F(1.47640169E-03 * C6), -F(3.43256425E-04 * C6), + F(1.13992507E-03 * C7), -F(5.54620202E-04 * C7), +#undef F +#define F(x) F_COS(x) + F(0.7071067812 / C0), F(0.8314696123 / C1), + -F(0.7071067812 / C0), -F(0.1950903220 / C1), + -F(0.7071067812 / C0), -F(0.9807852804 / C1), + F(0.7071067812 / C0), -F(0.5555702330 / C1), + F(0.7071067812 / C0), F(0.5555702330 / C1), + -F(0.7071067812 / C0), F(0.9807852804 / C1), + -F(0.7071067812 / C0), F(0.1950903220 / C1), + F(0.7071067812 / C0), -F(0.8314696123 / C1), + F(0.9238795325 / C2), F(0.9807852804 / C3), + F(0.3826834324 / C2), F(0.8314696123 / C3), + -F(0.3826834324 / C2), F(0.5555702330 / C3), + -F(0.9238795325 / C2), F(0.1950903220 / C3), + -F(0.9238795325 / C2), -F(0.1950903220 / C3), + -F(0.3826834324 / C2), -F(0.5555702330 / C3), + F(0.3826834324 / C2), -F(0.8314696123 / C3), + F(0.9238795325 / C2), -F(0.9807852804 / C3), + -F(1.0000000000 / C4), F(0.5555702330 / C5), + -F(1.0000000000 / C4), -F(0.9807852804 / C5), + -F(1.0000000000 / C4), F(0.1950903220 / C5), + -F(1.0000000000 / C4), F(0.8314696123 / C5), + -F(1.0000000000 / C4), -F(0.8314696123 / C5), + -F(1.0000000000 / C4), -F(0.1950903220 / C5), + -F(1.0000000000 / C4), F(0.9807852804 / C5), + -F(1.0000000000 / C4), -F(0.5555702330 / C5), + F(0.3826834324 / C6), F(0.1950903220 / C7), + -F(0.9238795325 / C6), -F(0.5555702330 / C7), + F(0.9238795325 / C6), F(0.8314696123 / C7), + -F(0.3826834324 / C6), -F(0.9807852804 / C7), + -F(0.3826834324 / C6), F(0.9807852804 / C7), + F(0.9238795325 / C6), -F(0.8314696123 / C7), + -F(0.9238795325 / C6), F(0.5555702330 / C7), + F(0.3826834324 / C6), -F(0.1950903220 / C7), +#undef F + +#undef C0 +#undef C1 +#undef C2 +#undef C3 +#undef C4 +#undef C5 +#undef C6 +#undef C7 +}; + +DECLARE_ALIGNED(SBC_ALIGN, const int16_t, ff_sbcdsp_analysis_consts_fixed8_simd_odd)[80 + 64] = { +#define C0 2.5377944043 +#define C1 2.4270044280 +#define C2 2.8015616024 +#define C3 3.1710363741 +#define C4 2.7906148894 +#define C5 2.4270044280 +#define C6 2.8015616024 +#define C7 3.1710363741 + +#define F(x) F_PROTO(x) + F(0.00000000E+00 * C0), -F(8.23919506E-04 * C0), + F(1.56575398E-04 * C1), F(1.78371725E-03 * C1), + F(3.43256425E-04 * C2), F(1.47640169E-03 * C2), + F(5.54620202E-04 * C3), F(1.13992507E-03 * C3), + F(2.01182542E-03 * C4), F(5.65949473E-03 * C4), + F(2.10371989E-03 * C5), F(3.49717454E-03 * C5), + F(1.99454554E-03 * C6), F(1.64973098E-03 * C6), + F(1.61656283E-03 * C7), F(1.78805361E-04 * C7), + F(0.00000000E+00 * C0), -F(1.46525263E-02 * C0), + F(8.02941163E-03 * C1), F(1.53184106E-02 * C1), + F(1.04584443E-02 * C2), F(1.62208471E-02 * C2), + F(1.27472335E-02 * C3), F(1.59045603E-02 * C3), + F(1.29371806E-02 * C4), F(6.79989431E-02 * C4), + F(8.85757540E-03 * C5), F(5.31873032E-02 * C5), + F(2.92408442E-03 * C6), F(3.90751381E-02 * C6), + -F(4.91578024E-03 * C7), F(2.61098752E-02 * C7), + F(0.00000000E+00 * C0), -F(1.23264548E-01 * C0), + F(8.29847578E-02 * C1), F(1.45389847E-01 * C1), + F(9.75753918E-02 * C2), F(1.40753505E-01 * C2), + F(1.11196689E-01 * C3), F(1.33264415E-01 * C3), + F(1.46955068E-01 * C4), -F(6.79989431E-02 * C4), + F(1.45389847E-01 * C5), -F(8.29847578E-02 * C5), + F(1.40753505E-01 * C6), -F(9.75753918E-02 * C6), + F(1.33264415E-01 * C7), -F(1.11196689E-01 * C7), + F(0.00000000E+00 * C0), F(1.46404076E-02 * C0), + -F(5.31873032E-02 * C1), F(8.85757540E-03 * C1), + -F(3.90751381E-02 * C2), F(2.92408442E-03 * C2), + -F(2.61098752E-02 * C3), -F(4.91578024E-03 * C3), + F(1.29371806E-02 * C4), -F(5.65949473E-03 * C4), + F(1.53184106E-02 * C5), -F(8.02941163E-03 * C5), + F(1.62208471E-02 * C6), -F(1.04584443E-02 * C6), + F(1.59045603E-02 * C7), -F(1.27472335E-02 * C7), + F(0.00000000E+00 * C0), -F(9.02154502E-04 * C0), + -F(3.49717454E-03 * C1), F(2.10371989E-03 * C1), + -F(1.64973098E-03 * C2), F(1.99454554E-03 * C2), + -F(1.78805361E-04 * C3), F(1.61656283E-03 * C3), + F(2.01182542E-03 * C4), F(0.00000000E+00 * C4), + F(1.78371725E-03 * C5), -F(1.56575398E-04 * C5), + F(1.47640169E-03 * C6), -F(3.43256425E-04 * C6), + F(1.13992507E-03 * C7), -F(5.54620202E-04 * C7), +#undef F +#define F(x) F_COS(x) + -F(1.0000000000 / C0), F(0.8314696123 / C1), + -F(1.0000000000 / C0), -F(0.1950903220 / C1), + -F(1.0000000000 / C0), -F(0.9807852804 / C1), + -F(1.0000000000 / C0), -F(0.5555702330 / C1), + -F(1.0000000000 / C0), F(0.5555702330 / C1), + -F(1.0000000000 / C0), F(0.9807852804 / C1), + -F(1.0000000000 / C0), F(0.1950903220 / C1), + -F(1.0000000000 / C0), -F(0.8314696123 / C1), + F(0.9238795325 / C2), F(0.9807852804 / C3), + F(0.3826834324 / C2), F(0.8314696123 / C3), + -F(0.3826834324 / C2), F(0.5555702330 / C3), + -F(0.9238795325 / C2), F(0.1950903220 / C3), + -F(0.9238795325 / C2), -F(0.1950903220 / C3), + -F(0.3826834324 / C2), -F(0.5555702330 / C3), + F(0.3826834324 / C2), -F(0.8314696123 / C3), + F(0.9238795325 / C2), -F(0.9807852804 / C3), + F(0.7071067812 / C4), F(0.5555702330 / C5), + -F(0.7071067812 / C4), -F(0.9807852804 / C5), + -F(0.7071067812 / C4), F(0.1950903220 / C5), + F(0.7071067812 / C4), F(0.8314696123 / C5), + F(0.7071067812 / C4), -F(0.8314696123 / C5), + -F(0.7071067812 / C4), -F(0.1950903220 / C5), + -F(0.7071067812 / C4), F(0.9807852804 / C5), + F(0.7071067812 / C4), -F(0.5555702330 / C5), + F(0.3826834324 / C6), F(0.1950903220 / C7), + -F(0.9238795325 / C6), -F(0.5555702330 / C7), + F(0.9238795325 / C6), F(0.8314696123 / C7), + -F(0.3826834324 / C6), -F(0.9807852804 / C7), + -F(0.3826834324 / C6), F(0.9807852804 / C7), + F(0.9238795325 / C6), -F(0.8314696123 / C7), + -F(0.9238795325 / C6), F(0.5555702330 / C7), + F(0.3826834324 / C6), -F(0.1950903220 / C7), +#undef F + +#undef C0 +#undef C1 +#undef C2 +#undef C3 +#undef C4 +#undef C5 +#undef C6 +#undef C7 +}; diff --git a/libavcodec/sbcdsp_data.h b/libavcodec/sbcdsp_data.h new file mode 100644 index 0000000000000..10fad5caa5e0e --- /dev/null +++ b/libavcodec/sbcdsp_data.h @@ -0,0 +1,55 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * miscellaneous SBC tables + */ + +#ifndef AVCODEC_SBCDSP_DATA_H +#define AVCODEC_SBCDSP_DATA_H + +#include "sbc.h" + +#define SBC_PROTO_FIXED_SCALE 16 +#define SBC_COS_TABLE_FIXED_SCALE 15 + +/* + * Constant tables for the use in SIMD optimized analysis filters + * Each table consists of two parts: + * 1. reordered "proto" table + * 2. reordered "cos" table + * + * Due to non-symmetrical reordering, separate tables for "even" + * and "odd" cases are needed + */ + +extern const int16_t ff_sbcdsp_analysis_consts_fixed4_simd_even[]; +extern const int16_t ff_sbcdsp_analysis_consts_fixed4_simd_odd[]; +extern const int16_t ff_sbcdsp_analysis_consts_fixed8_simd_even[]; +extern const int16_t ff_sbcdsp_analysis_consts_fixed8_simd_odd[]; + +#endif /* AVCODEC_SBCDSP_DATA_H */ diff --git a/libavcodec/sbcenc.c b/libavcodec/sbcenc.c new file mode 100644 index 0000000000000..a0064c0e8c722 --- /dev/null +++ b/libavcodec/sbcenc.c @@ -0,0 +1,361 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2012-2013 Intel Corporation + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2008 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * SBC encoder implementation + */ + +#include +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" +#include "profiles.h" +#include "put_bits.h" +#include "sbc.h" +#include "sbcdsp.h" + +typedef struct SBCEncContext { + AVClass *class; + int64_t max_delay; + int msbc; + DECLARE_ALIGNED(SBC_ALIGN, struct sbc_frame, frame); + DECLARE_ALIGNED(SBC_ALIGN, SBCDSPContext, dsp); +} SBCEncContext; + +static int sbc_analyze_audio(SBCDSPContext *s, struct sbc_frame *frame) +{ + int ch, blk; + int16_t *x; + + switch (frame->subbands) { + case 4: + for (ch = 0; ch < frame->channels; ch++) { + x = &s->X[ch][s->position - 4 * + s->increment + frame->blocks * 4]; + for (blk = 0; blk < frame->blocks; + blk += s->increment) { + s->sbc_analyze_4s( + s, x, + frame->sb_sample_f[blk][ch], + frame->sb_sample_f[blk + 1][ch] - + frame->sb_sample_f[blk][ch]); + x -= 4 * s->increment; + } + } + return frame->blocks * 4; + + case 8: + for (ch = 0; ch < frame->channels; ch++) { + x = &s->X[ch][s->position - 8 * + s->increment + frame->blocks * 8]; + for (blk = 0; blk < frame->blocks; + blk += s->increment) { + s->sbc_analyze_8s( + s, x, + frame->sb_sample_f[blk][ch], + frame->sb_sample_f[blk + 1][ch] - + frame->sb_sample_f[blk][ch]); + x -= 8 * s->increment; + } + } + return frame->blocks * 8; + + default: + return AVERROR(EIO); + } +} + +/* + * Packs the SBC frame from frame into the memory in avpkt. + * Returns the length of the packed frame. + */ +static size_t sbc_pack_frame(AVPacket *avpkt, struct sbc_frame *frame, + int joint, bool msbc) +{ + PutBitContext pb; + + /* Will copy the header parts for CRC-8 calculation here */ + uint8_t crc_header[11] = { 0 }; + int crc_pos; + + uint32_t audio_sample; + + int ch, sb, blk; /* channel, subband, block and bit counters */ + int bits[2][8]; /* bits distribution */ + uint32_t levels[2][8]; /* levels are derived from that */ + uint32_t sb_sample_delta[2][8]; + + if (msbc) { + avpkt->data[0] = MSBC_SYNCWORD; + avpkt->data[1] = 0; + avpkt->data[2] = 0; + } else { + avpkt->data[0] = SBC_SYNCWORD; + + avpkt->data[1] = (frame->frequency & 0x03) << 6; + avpkt->data[1] |= (((frame->blocks >> 2) - 1) & 0x03) << 4; + avpkt->data[1] |= (frame->mode & 0x03) << 2; + avpkt->data[1] |= (frame->allocation & 0x01) << 1; + avpkt->data[1] |= ((frame->subbands == 8) & 0x01) << 0; + + avpkt->data[2] = frame->bitpool; + + if (frame->bitpool > frame->subbands << (4 + (frame->mode == STEREO + || frame->mode == JOINT_STEREO))) + return -5; + } + + /* Can't fill in crc yet */ + crc_header[0] = avpkt->data[1]; + crc_header[1] = avpkt->data[2]; + crc_pos = 16; + + init_put_bits(&pb, avpkt->data + 4, avpkt->size); + + if (frame->mode == JOINT_STEREO) { + put_bits(&pb, frame->subbands, joint); + crc_header[crc_pos >> 3] = joint; + crc_pos += frame->subbands; + } + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + put_bits(&pb, 4, frame->scale_factor[ch][sb] & 0x0F); + crc_header[crc_pos >> 3] <<= 4; + crc_header[crc_pos >> 3] |= frame->scale_factor[ch][sb] & 0x0F; + crc_pos += 4; + } + } + + /* align the last crc byte */ + if (crc_pos % 8) + crc_header[crc_pos >> 3] <<= 8 - (crc_pos % 8); + + avpkt->data[3] = sbc_crc8(frame->crc_ctx, crc_header, crc_pos); + + ff_sbc_calculate_bits(frame, bits); + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + levels[ch][sb] = ((1 << bits[ch][sb]) - 1) << + (32 - (frame->scale_factor[ch][sb] + + SCALE_OUT_BITS + 2)); + sb_sample_delta[ch][sb] = (uint32_t) 1 << + (frame->scale_factor[ch][sb] + + SCALE_OUT_BITS + 1); + } + } + + for (blk = 0; blk < frame->blocks; blk++) { + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + + if (bits[ch][sb] == 0) + continue; + + audio_sample = ((uint64_t) levels[ch][sb] * + (sb_sample_delta[ch][sb] + + frame->sb_sample_f[blk][ch][sb])) >> 32; + + put_bits(&pb, bits[ch][sb], audio_sample); + } + } + } + + flush_put_bits(&pb); + + return (put_bits_count(&pb) + 7) / 8; +} + +static int sbc_encode_init(AVCodecContext *avctx) +{ + SBCEncContext *sbc = avctx->priv_data; + struct sbc_frame *frame = &sbc->frame; + + if (avctx->profile == FF_PROFILE_SBC_MSBC) + sbc->msbc = 1; + + if (sbc->msbc) { + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "mSBC require mono channel.\n"); + return AVERROR(EINVAL); + } + + if (avctx->sample_rate != 16000) { + av_log(avctx, AV_LOG_ERROR, "mSBC require 16 kHz samplerate.\n"); + return AVERROR(EINVAL); + } + + frame->mode = SBC_MODE_MONO; + frame->subbands = 8; + frame->blocks = MSBC_BLOCKS; + frame->allocation = SBC_AM_LOUDNESS; + frame->bitpool = 26; + + avctx->frame_size = 8 * MSBC_BLOCKS; + } else { + int d; + + if (avctx->global_quality > 255*FF_QP2LAMBDA) { + av_log(avctx, AV_LOG_ERROR, "bitpool > 255 is not allowed.\n"); + return AVERROR(EINVAL); + } + + if (avctx->channels == 1) { + frame->mode = SBC_MODE_MONO; + if (sbc->max_delay <= 3000 || avctx->bit_rate > 270000) + frame->subbands = 4; + else + frame->subbands = 8; + } else { + if (avctx->bit_rate < 180000 || avctx->bit_rate > 420000) + frame->mode = SBC_MODE_JOINT_STEREO; + else + frame->mode = SBC_MODE_STEREO; + if (sbc->max_delay <= 4000 || avctx->bit_rate > 420000) + frame->subbands = 4; + else + frame->subbands = 8; + } + /* sbc algorithmic delay is ((blocks + 10) * subbands - 2) / sample_rate */ + frame->blocks = av_clip(((sbc->max_delay * avctx->sample_rate + 2) + / (1000000 * frame->subbands)) - 10, 4, 16) & ~3; + + frame->allocation = SBC_AM_LOUDNESS; + + d = frame->blocks * ((frame->mode == SBC_MODE_DUAL_CHANNEL) + 1); + frame->bitpool = (((avctx->bit_rate * frame->subbands * frame->blocks) / avctx->sample_rate) + - 4 * frame->subbands * avctx->channels + - (frame->mode == SBC_MODE_JOINT_STEREO)*frame->subbands - 32 + d/2) / d; + if (avctx->global_quality > 0) + frame->bitpool = avctx->global_quality / FF_QP2LAMBDA; + + avctx->frame_size = 4*((frame->subbands >> 3) + 1) * 4*(frame->blocks >> 2); + } + + for (int i = 0; avctx->codec->supported_samplerates[i]; i++) + if (avctx->sample_rate == avctx->codec->supported_samplerates[i]) + frame->frequency = i; + + frame->channels = avctx->channels; + frame->codesize = frame->subbands * frame->blocks * avctx->channels * 2; + frame->crc_ctx = av_crc_get_table(AV_CRC_8_EBU); + + memset(&sbc->dsp.X, 0, sizeof(sbc->dsp.X)); + sbc->dsp.position = (SBC_X_BUFFER_SIZE - frame->subbands * 9) & ~7; + sbc->dsp.increment = sbc->msbc ? 1 : 4; + ff_sbcdsp_init(&sbc->dsp); + + return 0; +} + +static int sbc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *av_frame, int *got_packet_ptr) +{ + SBCEncContext *sbc = avctx->priv_data; + struct sbc_frame *frame = &sbc->frame; + uint8_t joint = frame->mode == SBC_MODE_JOINT_STEREO; + uint8_t dual = frame->mode == SBC_MODE_DUAL_CHANNEL; + int ret, j = 0; + + int frame_length = 4 + (4 * frame->subbands * frame->channels) / 8 + + ((frame->blocks * frame->bitpool * (1 + dual) + + joint * frame->subbands) + 7) / 8; + + /* input must be large enough to encode a complete frame */ + if (av_frame->nb_samples * frame->channels * 2 < frame->codesize) + return 0; + + if ((ret = ff_alloc_packet2(avctx, avpkt, frame_length, 0)) < 0) + return ret; + + /* Select the needed input data processing function and call it */ + if (frame->subbands == 8) + sbc->dsp.position = sbc->dsp.sbc_enc_process_input_8s( + sbc->dsp.position, av_frame->data[0], sbc->dsp.X, + frame->subbands * frame->blocks, frame->channels); + else + sbc->dsp.position = sbc->dsp.sbc_enc_process_input_4s( + sbc->dsp.position, av_frame->data[0], sbc->dsp.X, + frame->subbands * frame->blocks, frame->channels); + + sbc_analyze_audio(&sbc->dsp, &sbc->frame); + + if (frame->mode == JOINT_STEREO) + j = sbc->dsp.sbc_calc_scalefactors_j(frame->sb_sample_f, + frame->scale_factor, + frame->blocks, + frame->subbands); + else + sbc->dsp.sbc_calc_scalefactors(frame->sb_sample_f, + frame->scale_factor, + frame->blocks, + frame->channels, + frame->subbands); + emms_c(); + sbc_pack_frame(avpkt, frame, j, sbc->msbc); + + *got_packet_ptr = 1; + return 0; +} + +#define OFFSET(x) offsetof(SBCEncContext, x) +#define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "sbc_delay", "set maximum algorithmic latency", + OFFSET(max_delay), AV_OPT_TYPE_DURATION, {.i64 = 13000}, 1000,13000, AE }, + { "msbc", "use mSBC mode (wideband speech mono SBC)", + OFFSET(msbc), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AE }, + { NULL }, +}; + +static const AVClass sbc_class = { + .class_name = "sbc encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_sbc_encoder = { + .name = "sbc", + .long_name = NULL_IF_CONFIG_SMALL("SBC (low-complexity subband codec)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_SBC, + .priv_data_size = sizeof(SBCEncContext), + .init = sbc_encode_init, + .encode2 = sbc_encode_frame, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, 0}, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .supported_samplerates = (const int[]) { 16000, 32000, 44100, 48000, 0 }, + .priv_class = &sbc_class, + .profiles = NULL_IF_CONFIG_SMALL(ff_sbc_profiles), +}; From 88508a87a55789672ce0eb66ccd23fda38eab5af Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sun, 17 Dec 2017 20:24:21 +0100 Subject: [PATCH 2062/2557] sbc: add raw muxer for SBC --- doc/general.texi | 2 +- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/rawenc.c | 13 +++++++++++++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/general.texi b/doc/general.texi index de13a7695e667..c5d46d3404714 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -501,7 +501,7 @@ library: @item raw NULL @tab X @tab @item raw video @tab X @tab X @item raw id RoQ @tab X @tab -@item raw SBC @tab @tab X +@item raw SBC @tab X @tab X @item raw Shorten @tab @tab X @item raw TAK @tab @tab X @item raw TrueHD @tab X @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index 3fad2cb0430eb..e64c5b30a1e15 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -453,6 +453,7 @@ OBJS-$(CONFIG_SAMI_DEMUXER) += samidec.o subtitles.o OBJS-$(CONFIG_SAP_DEMUXER) += sapdec.o OBJS-$(CONFIG_SAP_MUXER) += sapenc.o OBJS-$(CONFIG_SBC_DEMUXER) += sbcdec.o rawdec.o +OBJS-$(CONFIG_SBC_MUXER) += rawenc.o OBJS-$(CONFIG_SBG_DEMUXER) += sbgdec.o OBJS-$(CONFIG_SCC_DEMUXER) += sccdec.o subtitles.o OBJS-$(CONFIG_SCC_MUXER) += sccenc.o subtitles.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 9c7f687a8e3da..9dc5ce8a767b2 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -355,6 +355,7 @@ extern AVInputFormat ff_sami_demuxer; extern AVInputFormat ff_sap_demuxer; extern AVOutputFormat ff_sap_muxer; extern AVInputFormat ff_sbc_demuxer; +extern AVOutputFormat ff_sbc_muxer; extern AVInputFormat ff_sbg_demuxer; extern AVInputFormat ff_scc_demuxer; extern AVOutputFormat ff_scc_muxer; diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index fcfbfbce8ea2e..809ca23b1a5d2 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -452,6 +452,19 @@ AVOutputFormat ff_rawvideo_muxer = { }; #endif +#if CONFIG_SBC_MUXER +AVOutputFormat ff_sbc_muxer = { + .name = "sbc", + .long_name = NULL_IF_CONFIG_SMALL("raw SBC"), + .mime_type = "audio/x-sbc", + .extensions = "sbc,msbc", + .audio_codec = AV_CODEC_ID_SBC, + .write_header = force_one_stream, + .write_packet = ff_raw_write_packet, + .flags = AVFMT_NOTIMESTAMPS, +}; +#endif + #if CONFIG_TRUEHD_MUXER AVOutputFormat ff_truehd_muxer = { .name = "truehd", From f1e490b1adedd90ce35db894520ccc61cacb991d Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sun, 17 Dec 2017 20:07:33 +0100 Subject: [PATCH 2063/2557] sbcenc: add MMX optimizations This was originally based on libsbc, and was fully integrated into ffmpeg. Rough speed test: C version: speed= 592x MMX version: speed= 785x --- libavcodec/sbcdsp.c | 3 + libavcodec/sbcdsp.h | 2 + libavcodec/x86/Makefile | 2 + libavcodec/x86/sbcdsp.asm | 168 +++++++++++++++++++++++++++++++++++ libavcodec/x86/sbcdsp_init.c | 51 +++++++++++ 5 files changed, 226 insertions(+) create mode 100644 libavcodec/x86/sbcdsp.asm create mode 100644 libavcodec/x86/sbcdsp_init.c diff --git a/libavcodec/sbcdsp.c b/libavcodec/sbcdsp.c index e155387f0d359..2d0addcf28930 100644 --- a/libavcodec/sbcdsp.c +++ b/libavcodec/sbcdsp.c @@ -379,4 +379,7 @@ av_cold void ff_sbcdsp_init(SBCDSPContext *s) /* Default implementation for scale factors calculation */ s->sbc_calc_scalefactors = sbc_calc_scalefactors; s->sbc_calc_scalefactors_j = sbc_calc_scalefactors_j; + + if (ARCH_X86) + ff_sbcdsp_init_x86(s); } diff --git a/libavcodec/sbcdsp.h b/libavcodec/sbcdsp.h index 66ed7d324eb0e..127e6a8a11eb3 100644 --- a/libavcodec/sbcdsp.h +++ b/libavcodec/sbcdsp.h @@ -80,4 +80,6 @@ struct sbc_dsp_context { */ void ff_sbcdsp_init(SBCDSPContext *s); +void ff_sbcdsp_init_x86(SBCDSPContext *s); + #endif /* AVCODEC_SBCDSP_H */ diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile index a805cd37b484f..2350c8bbee688 100644 --- a/libavcodec/x86/Makefile +++ b/libavcodec/x86/Makefile @@ -63,6 +63,7 @@ OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp_init.o OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp_init.o OBJS-$(CONFIG_PRORES_LGPL_DECODER) += x86/proresdsp_init.o OBJS-$(CONFIG_RV40_DECODER) += x86/rv40dsp_init.o +OBJS-$(CONFIG_SBC_ENCODER) += x86/sbcdsp_init.o OBJS-$(CONFIG_SVQ1_ENCODER) += x86/svq1enc_init.o OBJS-$(CONFIG_TAK_DECODER) += x86/takdsp_init.o OBJS-$(CONFIG_TRUEHD_DECODER) += x86/mlpdsp_init.o @@ -172,6 +173,7 @@ X86ASM-OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp.o X86ASM-OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp.o X86ASM-OBJS-$(CONFIG_PRORES_LGPL_DECODER) += x86/proresdsp.o X86ASM-OBJS-$(CONFIG_RV40_DECODER) += x86/rv40dsp.o +X86ASM-OBJS-$(CONFIG_SBC_ENCODER) += x86/sbcdsp.o X86ASM-OBJS-$(CONFIG_SVQ1_ENCODER) += x86/svq1enc.o X86ASM-OBJS-$(CONFIG_TAK_DECODER) += x86/takdsp.o X86ASM-OBJS-$(CONFIG_TRUEHD_DECODER) += x86/mlpdsp.o diff --git a/libavcodec/x86/sbcdsp.asm b/libavcodec/x86/sbcdsp.asm new file mode 100644 index 0000000000000..d68d3a9ae8c02 --- /dev/null +++ b/libavcodec/x86/sbcdsp.asm @@ -0,0 +1,168 @@ +;****************************************************************************** +;* SIMD optimized SBC encoder DSP functions +;* +;* Copyright (C) 2017 Aurelien Jacobs +;* Copyright (C) 2008-2010 Nokia Corporation +;* Copyright (C) 2004-2010 Marcel Holtmann +;* Copyright (C) 2004-2005 Henryk Ploetz +;* Copyright (C) 2005-2006 Brad Midgley +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +scale_mask: times 2 dd 0x8000 ; 1 << (SBC_PROTO_FIXED_SCALE - 1) + +SECTION .text + +%macro NIDN 3 +%ifnidn %2, %3 + %1 %2, %3 +%endif +%endmacro + +%macro ANALYZE_MAC 9 ; out1, out2, in1, in2, tmp1, tmp2, add1, add2, offset + NIDN movq, %5, %3 + NIDN movq, %6, %4 + pmaddwd %5, [constsq+%9] + pmaddwd %6, [constsq+%9+8] + NIDN paddd, %1, %7 + NIDN paddd, %2, %8 +%endmacro + +%macro ANALYZE_MAC_IN 7 ; out1, out2, tmp1, tmp2, add1, add2, offset + ANALYZE_MAC %1, %2, [inq+%7], [inq+%7+8], %3, %4, %5, %6, %7 +%endmacro + +%macro ANALYZE_MAC_REG 7 ; out1, out2, in, tmp1, tmp2, offset, pack +%ifidn %7, pack + psrad %3, 16 ; SBC_PROTO_FIXED_SCALE + packssdw %3, %3 +%endif + ANALYZE_MAC %1, %2, %3, %3, %4, %5, %4, %5, %6 +%endmacro + +;******************************************************************* +;void ff_sbc_analyze_4(const int16_t *in, int32_t *out, const int16_t *consts); +;******************************************************************* +INIT_MMX mmx +cglobal sbc_analyze_4, 3, 3, 4, in, out, consts + ANALYZE_MAC_IN m0, m1, m0, m1, [scale_mask], [scale_mask], 0 + ANALYZE_MAC_IN m0, m1, m2, m3, m2, m3, 16 + ANALYZE_MAC_IN m0, m1, m2, m3, m2, m3, 32 + ANALYZE_MAC_IN m0, m1, m2, m3, m2, m3, 48 + ANALYZE_MAC_IN m0, m1, m2, m3, m2, m3, 64 + + ANALYZE_MAC_REG m0, m2, m0, m0, m2, 80, pack + ANALYZE_MAC_REG m0, m2, m1, m1, m3, 96, pack + + movq [outq ], m0 + movq [outq+8], m2 + + RET + + +;******************************************************************* +;void ff_sbc_analyze_8(const int16_t *in, int32_t *out, const int16_t *consts); +;******************************************************************* +INIT_MMX mmx +cglobal sbc_analyze_8, 3, 3, 4, in, out, consts + ANALYZE_MAC_IN m0, m1, m0, m1, [scale_mask], [scale_mask], 0 + ANALYZE_MAC_IN m2, m3, m2, m3, [scale_mask], [scale_mask], 16 + ANALYZE_MAC_IN m0, m1, m4, m5, m4, m5, 32 + ANALYZE_MAC_IN m2, m3, m6, m7, m6, m7, 48 + ANALYZE_MAC_IN m0, m1, m4, m5, m4, m5, 64 + ANALYZE_MAC_IN m2, m3, m6, m7, m6, m7, 80 + ANALYZE_MAC_IN m0, m1, m4, m5, m4, m5, 96 + ANALYZE_MAC_IN m2, m3, m6, m7, m6, m7, 112 + ANALYZE_MAC_IN m0, m1, m4, m5, m4, m5, 128 + ANALYZE_MAC_IN m2, m3, m6, m7, m6, m7, 144 + + ANALYZE_MAC_REG m4, m5, m0, m4, m5, 160, pack + ANALYZE_MAC_REG m4, m5, m1, m6, m7, 192, pack + ANALYZE_MAC_REG m4, m5, m2, m6, m7, 224, pack + ANALYZE_MAC_REG m4, m5, m3, m6, m7, 256, pack + + movq [outq ], m4 + movq [outq+8], m5 + + ANALYZE_MAC_REG m0, m5, m0, m0, m5, 176, no + ANALYZE_MAC_REG m0, m5, m1, m1, m7, 208, no + ANALYZE_MAC_REG m0, m5, m2, m2, m7, 240, no + ANALYZE_MAC_REG m0, m5, m3, m3, m7, 272, no + + movq [outq+16], m0 + movq [outq+24], m5 + + RET + + +;******************************************************************* +;void ff_sbc_calc_scalefactors(int32_t sb_sample_f[16][2][8], +; uint32_t scale_factor[2][8], +; int blocks, int channels, int subbands) +;******************************************************************* +INIT_MMX mmx +cglobal sbc_calc_scalefactors, 5, 7, 4, sb_sample_f, scale_factor, blocks, channels, subbands, ptr, blk + ; subbands = 4 * subbands * channels + movq m3, [scale_mask] + shl subbandsd, 2 + cmp channelsd, 2 + jl .loop_1 + shl subbandsd, 1 + +.loop_1: + sub subbandsq, 8 + lea ptrq, [sb_sample_fq + subbandsq] + + ; blk = (blocks - 1) * 64; + lea blkq, [blocksq - 1] + shl blkd, 6 + + movq m0, m3 +.loop_2: + movq m1, [ptrq+blkq] + pxor m2, m2 + pcmpgtd m1, m2 + paddd m1, [ptrq+blkq] + pcmpgtd m2, m1 + pxor m1, m2 + + por m0, m1 + + sub blkq, 64 + jns .loop_2 + + movd blkd, m0 + psrlq m0, 32 + bsr blkd, blkd + sub blkd, 15 ; SCALE_OUT_BITS + mov [scale_factorq + subbandsq], blkd + + movd blkd, m0 + bsr blkd, blkd + sub blkd, 15 ; SCALE_OUT_BITS + mov [scale_factorq + subbandsq + 4], blkd + + cmp subbandsq, 0 + jg .loop_1 + + emms + RET diff --git a/libavcodec/x86/sbcdsp_init.c b/libavcodec/x86/sbcdsp_init.c new file mode 100644 index 0000000000000..86effecfdf565 --- /dev/null +++ b/libavcodec/x86/sbcdsp_init.c @@ -0,0 +1,51 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * SBC MMX optimization for some basic "building bricks" + */ + +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/sbcdsp.h" + +void ff_sbc_analyze_4_mmx(const int16_t *in, int32_t *out, const int16_t *consts); +void ff_sbc_analyze_8_mmx(const int16_t *in, int32_t *out, const int16_t *consts); +void ff_sbc_calc_scalefactors_mmx(int32_t sb_sample_f[16][2][8], + uint32_t scale_factor[2][8], + int blocks, int channels, int subbands); + +av_cold void ff_sbcdsp_init_x86(SBCDSPContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_MMX(cpu_flags)) { + s->sbc_analyze_4 = ff_sbc_analyze_4_mmx; + s->sbc_analyze_8 = ff_sbc_analyze_8_mmx; + s->sbc_calc_scalefactors = ff_sbc_calc_scalefactors_mmx; + } +} From f677718bc87a96c05edda25be7e8c9b9dc357f5d Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sun, 17 Dec 2017 20:10:32 +0100 Subject: [PATCH 2064/2557] sbcenc: add armv6 and neon asm optimizations This was originally based on libsbc, and was fully integrated into ffmpeg. --- libavcodec/arm/Makefile | 3 + libavcodec/arm/sbcdsp_armv6.S | 245 +++++++++++ libavcodec/arm/sbcdsp_init_arm.c | 105 +++++ libavcodec/arm/sbcdsp_neon.S | 714 +++++++++++++++++++++++++++++++ libavcodec/sbcdsp.c | 2 + libavcodec/sbcdsp.h | 1 + 6 files changed, 1070 insertions(+) create mode 100644 libavcodec/arm/sbcdsp_armv6.S create mode 100644 libavcodec/arm/sbcdsp_init_arm.c create mode 100644 libavcodec/arm/sbcdsp_neon.S diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile index 1eeac5449eeac..fd2401f4e5c9e 100644 --- a/libavcodec/arm/Makefile +++ b/libavcodec/arm/Makefile @@ -42,6 +42,7 @@ OBJS-$(CONFIG_DCA_DECODER) += arm/synth_filter_init_arm.o OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_arm.o OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_init_arm.o OBJS-$(CONFIG_RV40_DECODER) += arm/rv40dsp_init_arm.o +OBJS-$(CONFIG_SBC_ENCODER) += arm/sbcdsp_init_arm.o OBJS-$(CONFIG_VORBIS_DECODER) += arm/vorbisdsp_init_arm.o OBJS-$(CONFIG_VP6_DECODER) += arm/vp6dsp_init_arm.o OBJS-$(CONFIG_VP9_DECODER) += arm/vp9dsp_init_10bpp_arm.o \ @@ -81,6 +82,7 @@ ARMV6-OBJS-$(CONFIG_VP8DSP) += arm/vp8_armv6.o \ # decoders/encoders ARMV6-OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_armv6.o +ARMV6-OBJS-$(CONFIG_SBC_ENCODER) += arm/sbcdsp_armv6.o # VFP optimizations @@ -140,6 +142,7 @@ NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_neon.o \ NEON-OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_neon.o NEON-OBJS-$(CONFIG_RV40_DECODER) += arm/rv34dsp_neon.o \ arm/rv40dsp_neon.o +NEON-OBJS-$(CONFIG_SBC_ENCODER) += arm/sbcdsp_neon.o NEON-OBJS-$(CONFIG_VORBIS_DECODER) += arm/vorbisdsp_neon.o NEON-OBJS-$(CONFIG_VP6_DECODER) += arm/vp6dsp_neon.o NEON-OBJS-$(CONFIG_VP9_DECODER) += arm/vp9itxfm_16bpp_neon.o \ diff --git a/libavcodec/arm/sbcdsp_armv6.S b/libavcodec/arm/sbcdsp_armv6.S new file mode 100644 index 0000000000000..f1ff845798843 --- /dev/null +++ b/libavcodec/arm/sbcdsp_armv6.S @@ -0,0 +1,245 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * SBC ARMv6 optimizations. The instructions are scheduled for ARM11 pipeline. + */ + +#include "libavutil/arm/asm.S" + +function ff_sbc_analyze_4_armv6, export=1 + @ r0 = in, r1 = out, r2 = consts + push {r1, r3-r7, lr} + push {r8-r12, r14} + ldrd r4, r5, [r0, #0] + ldrd r6, r7, [r2, #0] + ldrd r8, r9, [r0, #16] + ldrd r10, r11, [r2, #16] + mov r14, #0x8000 + smlad r3, r4, r6, r14 + smlad r12, r5, r7, r14 + ldrd r4, r5, [r0, #32] + ldrd r6, r7, [r2, #32] + smlad r3, r8, r10, r3 + smlad r12, r9, r11, r12 + ldrd r8, r9, [r0, #48] + ldrd r10, r11, [r2, #48] + smlad r3, r4, r6, r3 + smlad r12, r5, r7, r12 + ldrd r4, r5, [r0, #64] + ldrd r6, r7, [r2, #64] + smlad r3, r8, r10, r3 + smlad r12, r9, r11, r12 + ldrd r8, r9, [r0, #8] + ldrd r10, r11, [r2, #8] + smlad r3, r4, r6, r3 @ t1[0] is done + smlad r12, r5, r7, r12 @ t1[1] is done + ldrd r4, r5, [r0, #24] + ldrd r6, r7, [r2, #24] + pkhtb r3, r12, r3, asr #16 @ combine t1[0] and t1[1] + smlad r12, r8, r10, r14 + smlad r14, r9, r11, r14 + ldrd r8, r9, [r0, #40] + ldrd r10, r11, [r2, #40] + smlad r12, r4, r6, r12 + smlad r14, r5, r7, r14 + ldrd r4, r5, [r0, #56] + ldrd r6, r7, [r2, #56] + smlad r12, r8, r10, r12 + smlad r14, r9, r11, r14 + ldrd r8, r9, [r0, #72] + ldrd r10, r11, [r2, #72] + smlad r12, r4, r6, r12 + smlad r14, r5, r7, r14 + ldrd r4, r5, [r2, #80] @ start loading cos table + smlad r12, r8, r10, r12 @ t1[2] is done + smlad r14, r9, r11, r14 @ t1[3] is done + ldrd r6, r7, [r2, #88] + ldrd r8, r9, [r2, #96] + ldrd r10, r11, [r2, #104] @ cos table fully loaded + pkhtb r12, r14, r12, asr #16 @ combine t1[2] and t1[3] + smuad r4, r3, r4 + smuad r5, r3, r5 + smlad r4, r12, r8, r4 + smlad r5, r12, r9, r5 + smuad r6, r3, r6 + smuad r7, r3, r7 + smlad r6, r12, r10, r6 + smlad r7, r12, r11, r7 + pop {r8-r12, r14} + stmia r1, {r4, r5, r6, r7} + pop {r1, r3-r7, pc} +endfunc + +function ff_sbc_analyze_8_armv6, export=1 + @ r0 = in, r1 = out, r2 = consts + push {r1, r3-r7, lr} + push {r8-r12, r14} + ldrd r4, r5, [r0, #24] + ldrd r6, r7, [r2, #24] + ldrd r8, r9, [r0, #56] + ldrd r10, r11, [r2, #56] + mov r14, #0x8000 + smlad r3, r4, r6, r14 + smlad r12, r5, r7, r14 + ldrd r4, r5, [r0, #88] + ldrd r6, r7, [r2, #88] + smlad r3, r8, r10, r3 + smlad r12, r9, r11, r12 + ldrd r8, r9, [r0, #120] + ldrd r10, r11, [r2, #120] + smlad r3, r4, r6, r3 + smlad r12, r5, r7, r12 + ldrd r4, r5, [r0, #152] + ldrd r6, r7, [r2, #152] + smlad r3, r8, r10, r3 + smlad r12, r9, r11, r12 + ldrd r8, r9, [r0, #16] + ldrd r10, r11, [r2, #16] + smlad r3, r4, r6, r3 @ t1[6] is done + smlad r12, r5, r7, r12 @ t1[7] is done + ldrd r4, r5, [r0, #48] + ldrd r6, r7, [r2, #48] + pkhtb r3, r12, r3, asr #16 @ combine t1[6] and t1[7] + str r3, [sp, #-4]! @ save to stack + smlad r3, r8, r10, r14 + smlad r12, r9, r11, r14 + ldrd r8, r9, [r0, #80] + ldrd r10, r11, [r2, #80] + smlad r3, r4, r6, r3 + smlad r12, r5, r7, r12 + ldrd r4, r5, [r0, #112] + ldrd r6, r7, [r2, #112] + smlad r3, r8, r10, r3 + smlad r12, r9, r11, r12 + ldrd r8, r9, [r0, #144] + ldrd r10, r11, [r2, #144] + smlad r3, r4, r6, r3 + smlad r12, r5, r7, r12 + ldrd r4, r5, [r0, #0] + ldrd r6, r7, [r2, #0] + smlad r3, r8, r10, r3 @ t1[4] is done + smlad r12, r9, r11, r12 @ t1[5] is done + ldrd r8, r9, [r0, #32] + ldrd r10, r11, [r2, #32] + pkhtb r3, r12, r3, asr #16 @ combine t1[4] and t1[5] + str r3, [sp, #-4]! @ save to stack + smlad r3, r4, r6, r14 + smlad r12, r5, r7, r14 + ldrd r4, r5, [r0, #64] + ldrd r6, r7, [r2, #64] + smlad r3, r8, r10, r3 + smlad r12, r9, r11, r12 + ldrd r8, r9, [r0, #96] + ldrd r10, r11, [r2, #96] + smlad r3, r4, r6, r3 + smlad r12, r5, r7, r12 + ldrd r4, r5, [r0, #128] + ldrd r6, r7, [r2, #128] + smlad r3, r8, r10, r3 + smlad r12, r9, r11, r12 + ldrd r8, r9, [r0, #8] + ldrd r10, r11, [r2, #8] + smlad r3, r4, r6, r3 @ t1[0] is done + smlad r12, r5, r7, r12 @ t1[1] is done + ldrd r4, r5, [r0, #40] + ldrd r6, r7, [r2, #40] + pkhtb r3, r12, r3, asr #16 @ combine t1[0] and t1[1] + smlad r12, r8, r10, r14 + smlad r14, r9, r11, r14 + ldrd r8, r9, [r0, #72] + ldrd r10, r11, [r2, #72] + smlad r12, r4, r6, r12 + smlad r14, r5, r7, r14 + ldrd r4, r5, [r0, #104] + ldrd r6, r7, [r2, #104] + smlad r12, r8, r10, r12 + smlad r14, r9, r11, r14 + ldrd r8, r9, [r0, #136] + ldrd r10, r11, [r2, #136]! + smlad r12, r4, r6, r12 + smlad r14, r5, r7, r14 + ldrd r4, r5, [r2, #(160 - 136 + 0)] + smlad r12, r8, r10, r12 @ t1[2] is done + smlad r14, r9, r11, r14 @ t1[3] is done + ldrd r6, r7, [r2, #(160 - 136 + 8)] + smuad r4, r3, r4 + smuad r5, r3, r5 + pkhtb r12, r14, r12, asr #16 @ combine t1[2] and t1[3] + @ r3 = t2[0:1] + @ r12 = t2[2:3] + pop {r0, r14} @ t2[4:5], t2[6:7] + ldrd r8, r9, [r2, #(160 - 136 + 32)] + smuad r6, r3, r6 + smuad r7, r3, r7 + ldrd r10, r11, [r2, #(160 - 136 + 40)] + smlad r4, r12, r8, r4 + smlad r5, r12, r9, r5 + ldrd r8, r9, [r2, #(160 - 136 + 64)] + smlad r6, r12, r10, r6 + smlad r7, r12, r11, r7 + ldrd r10, r11, [r2, #(160 - 136 + 72)] + smlad r4, r0, r8, r4 + smlad r5, r0, r9, r5 + ldrd r8, r9, [r2, #(160 - 136 + 96)] + smlad r6, r0, r10, r6 + smlad r7, r0, r11, r7 + ldrd r10, r11, [r2, #(160 - 136 + 104)] + smlad r4, r14, r8, r4 + smlad r5, r14, r9, r5 + ldrd r8, r9, [r2, #(160 - 136 + 16 + 0)] + smlad r6, r14, r10, r6 + smlad r7, r14, r11, r7 + ldrd r10, r11, [r2, #(160 - 136 + 16 + 8)] + stmia r1!, {r4, r5} + smuad r4, r3, r8 + smuad r5, r3, r9 + ldrd r8, r9, [r2, #(160 - 136 + 16 + 32)] + stmia r1!, {r6, r7} + smuad r6, r3, r10 + smuad r7, r3, r11 + ldrd r10, r11, [r2, #(160 - 136 + 16 + 40)] + smlad r4, r12, r8, r4 + smlad r5, r12, r9, r5 + ldrd r8, r9, [r2, #(160 - 136 + 16 + 64)] + smlad r6, r12, r10, r6 + smlad r7, r12, r11, r7 + ldrd r10, r11, [r2, #(160 - 136 + 16 + 72)] + smlad r4, r0, r8, r4 + smlad r5, r0, r9, r5 + ldrd r8, r9, [r2, #(160 - 136 + 16 + 96)] + smlad r6, r0, r10, r6 + smlad r7, r0, r11, r7 + ldrd r10, r11, [r2, #(160 - 136 + 16 + 104)] + smlad r4, r14, r8, r4 + smlad r5, r14, r9, r5 + smlad r6, r14, r10, r6 + smlad r7, r14, r11, r7 + pop {r8-r12, r14} + stmia r1!, {r4, r5, r6, r7} + pop {r1, r3-r7, pc} +endfunc diff --git a/libavcodec/arm/sbcdsp_init_arm.c b/libavcodec/arm/sbcdsp_init_arm.c new file mode 100644 index 0000000000000..6bf7e729ef118 --- /dev/null +++ b/libavcodec/arm/sbcdsp_init_arm.c @@ -0,0 +1,105 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * SBC ARMv6 optimization for some basic "building bricks" + */ + +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/sbcdsp.h" + +void ff_sbc_analyze_4_armv6(const int16_t *in, int32_t *out, const int16_t *consts); +void ff_sbc_analyze_8_armv6(const int16_t *in, int32_t *out, const int16_t *consts); + +void ff_sbc_analyze_4_neon(const int16_t *in, int32_t *out, const int16_t *consts); +void ff_sbc_analyze_8_neon(const int16_t *in, int32_t *out, const int16_t *consts); +void ff_sbc_calc_scalefactors_neon(int32_t sb_sample_f[16][2][8], + uint32_t scale_factor[2][8], + int blocks, int channels, int subbands); +int ff_sbc_calc_scalefactors_j_neon(int32_t sb_sample_f[16][2][8], + uint32_t scale_factor[2][8], + int blocks, int subbands); +int ff_sbc_enc_process_input_4s_neon(int position, const uint8_t *pcm, + int16_t X[2][SBC_X_BUFFER_SIZE], + int nsamples, int nchannels); +int ff_sbc_enc_process_input_8s_neon(int position, const uint8_t *pcm, + int16_t X[2][SBC_X_BUFFER_SIZE], + int nsamples, int nchannels); + +DECLARE_ALIGNED(SBC_ALIGN, int32_t, ff_sbcdsp_joint_bits_mask)[8] = { + 8, 4, 2, 1, 128, 64, 32, 16 +}; + +#if HAVE_BIGENDIAN +#define PERM(a, b, c, d) { \ + (a * 2) + 1, (a * 2) + 0, \ + (b * 2) + 1, (b * 2) + 0, \ + (c * 2) + 1, (c * 2) + 0, \ + (d * 2) + 1, (d * 2) + 0 \ + } +#else +#define PERM(a, b, c, d) { \ + (a * 2) + 0, (a * 2) + 1, \ + (b * 2) + 0, (b * 2) + 1, \ + (c * 2) + 0, (c * 2) + 1, \ + (d * 2) + 0, (d * 2) + 1 \ + } +#endif + +DECLARE_ALIGNED(SBC_ALIGN, uint8_t, ff_sbc_input_perm_4)[2][8] = { + PERM(7, 3, 6, 4), + PERM(0, 2, 1, 5) +}; + +DECLARE_ALIGNED(SBC_ALIGN, uint8_t, ff_sbc_input_perm_8)[4][8] = { + PERM(15, 7, 14, 8), + PERM(13, 9, 12, 10), + PERM(11, 3, 6, 0), + PERM( 5, 1, 4, 2) +}; + +av_cold void ff_sbcdsp_init_arm(SBCDSPContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_armv6(cpu_flags)) { + s->sbc_analyze_4 = ff_sbc_analyze_4_armv6; + s->sbc_analyze_8 = ff_sbc_analyze_8_armv6; + } + + if (have_neon(cpu_flags)) { + s->sbc_analyze_4 = ff_sbc_analyze_4_neon; + s->sbc_analyze_8 = ff_sbc_analyze_8_neon; + s->sbc_calc_scalefactors = ff_sbc_calc_scalefactors_neon; + s->sbc_calc_scalefactors_j = ff_sbc_calc_scalefactors_j_neon; + if (s->increment != 1) { + s->sbc_enc_process_input_4s = ff_sbc_enc_process_input_4s_neon; + s->sbc_enc_process_input_8s = ff_sbc_enc_process_input_8s_neon; + } + } +} diff --git a/libavcodec/arm/sbcdsp_neon.S b/libavcodec/arm/sbcdsp_neon.S new file mode 100644 index 0000000000000..d83d21d20202d --- /dev/null +++ b/libavcodec/arm/sbcdsp_neon.S @@ -0,0 +1,714 @@ +/* + * Bluetooth low-complexity, subband codec (SBC) + * + * Copyright (C) 2017 Aurelien Jacobs + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * SBC ARM NEON optimizations + */ + +#include "libavutil/arm/asm.S" +#include "neon.S" + +#define SBC_PROTO_FIXED_SCALE 16 + +function ff_sbc_analyze_4_neon, export=1 + /* TODO: merge even and odd cases (or even merge all four calls to this + * function) in order to have only aligned reads from 'in' array + * and reduce number of load instructions */ + vld1.16 {d4, d5}, [r0, :64]! + vld1.16 {d8, d9}, [r2, :128]! + + vmull.s16 q0, d4, d8 + vld1.16 {d6, d7}, [r0, :64]! + vmull.s16 q1, d5, d9 + vld1.16 {d10, d11}, [r2, :128]! + + vmlal.s16 q0, d6, d10 + vld1.16 {d4, d5}, [r0, :64]! + vmlal.s16 q1, d7, d11 + vld1.16 {d8, d9}, [r2, :128]! + + vmlal.s16 q0, d4, d8 + vld1.16 {d6, d7}, [r0, :64]! + vmlal.s16 q1, d5, d9 + vld1.16 {d10, d11}, [r2, :128]! + + vmlal.s16 q0, d6, d10 + vld1.16 {d4, d5}, [r0, :64]! + vmlal.s16 q1, d7, d11 + vld1.16 {d8, d9}, [r2, :128]! + + vmlal.s16 q0, d4, d8 + vmlal.s16 q1, d5, d9 + + vpadd.s32 d0, d0, d1 + vpadd.s32 d1, d2, d3 + + vrshrn.s32 d0, q0, SBC_PROTO_FIXED_SCALE + + vld1.16 {d2, d3, d4, d5}, [r2, :128]! + + vdup.i32 d1, d0[1] /* TODO: can be eliminated */ + vdup.i32 d0, d0[0] /* TODO: can be eliminated */ + + vmull.s16 q3, d2, d0 + vmull.s16 q4, d3, d0 + vmlal.s16 q3, d4, d1 + vmlal.s16 q4, d5, d1 + + vpadd.s32 d0, d6, d7 /* TODO: can be eliminated */ + vpadd.s32 d1, d8, d9 /* TODO: can be eliminated */ + + vst1.32 {d0, d1}, [r1, :128] + + bx lr +endfunc + +function ff_sbc_analyze_8_neon, export=1 + /* TODO: merge even and odd cases (or even merge all four calls to this + * function) in order to have only aligned reads from 'in' array + * and reduce number of load instructions */ + vld1.16 {d4, d5}, [r0, :64]! + vld1.16 {d8, d9}, [r2, :128]! + + vmull.s16 q6, d4, d8 + vld1.16 {d6, d7}, [r0, :64]! + vmull.s16 q7, d5, d9 + vld1.16 {d10, d11}, [r2, :128]! + vmull.s16 q8, d6, d10 + vld1.16 {d4, d5}, [r0, :64]! + vmull.s16 q9, d7, d11 + vld1.16 {d8, d9}, [r2, :128]! + + vmlal.s16 q6, d4, d8 + vld1.16 {d6, d7}, [r0, :64]! + vmlal.s16 q7, d5, d9 + vld1.16 {d10, d11}, [r2, :128]! + vmlal.s16 q8, d6, d10 + vld1.16 {d4, d5}, [r0, :64]! + vmlal.s16 q9, d7, d11 + vld1.16 {d8, d9}, [r2, :128]! + + vmlal.s16 q6, d4, d8 + vld1.16 {d6, d7}, [r0, :64]! + vmlal.s16 q7, d5, d9 + vld1.16 {d10, d11}, [r2, :128]! + vmlal.s16 q8, d6, d10 + vld1.16 {d4, d5}, [r0, :64]! + vmlal.s16 q9, d7, d11 + vld1.16 {d8, d9}, [r2, :128]! + + vmlal.s16 q6, d4, d8 + vld1.16 {d6, d7}, [r0, :64]! + vmlal.s16 q7, d5, d9 + vld1.16 {d10, d11}, [r2, :128]! + vmlal.s16 q8, d6, d10 + vld1.16 {d4, d5}, [r0, :64]! + vmlal.s16 q9, d7, d11 + vld1.16 {d8, d9}, [r2, :128]! + + vmlal.s16 q6, d4, d8 + vld1.16 {d6, d7}, [r0, :64]! + vmlal.s16 q7, d5, d9 + vld1.16 {d10, d11}, [r2, :128]! + + vmlal.s16 q8, d6, d10 + vmlal.s16 q9, d7, d11 + + vpadd.s32 d0, d12, d13 + vpadd.s32 d1, d14, d15 + vpadd.s32 d2, d16, d17 + vpadd.s32 d3, d18, d19 + + vrshr.s32 q0, q0, SBC_PROTO_FIXED_SCALE + vrshr.s32 q1, q1, SBC_PROTO_FIXED_SCALE + vmovn.s32 d0, q0 + vmovn.s32 d1, q1 + + vdup.i32 d3, d1[1] /* TODO: can be eliminated */ + vdup.i32 d2, d1[0] /* TODO: can be eliminated */ + vdup.i32 d1, d0[1] /* TODO: can be eliminated */ + vdup.i32 d0, d0[0] /* TODO: can be eliminated */ + + vld1.16 {d4, d5}, [r2, :128]! + vmull.s16 q6, d4, d0 + vld1.16 {d6, d7}, [r2, :128]! + vmull.s16 q7, d5, d0 + vmull.s16 q8, d6, d0 + vmull.s16 q9, d7, d0 + + vld1.16 {d4, d5}, [r2, :128]! + vmlal.s16 q6, d4, d1 + vld1.16 {d6, d7}, [r2, :128]! + vmlal.s16 q7, d5, d1 + vmlal.s16 q8, d6, d1 + vmlal.s16 q9, d7, d1 + + vld1.16 {d4, d5}, [r2, :128]! + vmlal.s16 q6, d4, d2 + vld1.16 {d6, d7}, [r2, :128]! + vmlal.s16 q7, d5, d2 + vmlal.s16 q8, d6, d2 + vmlal.s16 q9, d7, d2 + + vld1.16 {d4, d5}, [r2, :128]! + vmlal.s16 q6, d4, d3 + vld1.16 {d6, d7}, [r2, :128]! + vmlal.s16 q7, d5, d3 + vmlal.s16 q8, d6, d3 + vmlal.s16 q9, d7, d3 + + vpadd.s32 d0, d12, d13 /* TODO: can be eliminated */ + vpadd.s32 d1, d14, d15 /* TODO: can be eliminated */ + vpadd.s32 d2, d16, d17 /* TODO: can be eliminated */ + vpadd.s32 d3, d18, d19 /* TODO: can be eliminated */ + + vst1.32 {d0, d1, d2, d3}, [r1, :128] + + bx lr +endfunc + +function ff_sbc_calc_scalefactors_neon, export=1 + @ parameters + @ r0 = sb_sample_f + @ r1 = scale_factor + @ r2 = blocks + @ r3 = channels + @ r4 = subbands + @ local variables + @ r5 = in_loop_1 + @ r6 = in + @ r7 = out_loop_1 + @ r8 = out + @ r9 = ch + @ r10 = sb + @ r11 = inc + @ r12 = blk + + push {r1-r2, r4-r12} + ldr r4, [sp, #44] + mov r11, #64 + + mov r9, #0 +1: + add r5, r0, r9, lsl#5 + add r7, r1, r9, lsl#5 + + mov r10, #0 +2: + add r6, r5, r10, lsl#2 + add r8, r7, r10, lsl#2 + mov r12, r2 + + vmov.s32 q0, #0 + vmov.s32 q1, #0x8000 @ 1 << SCALE_OUT_BITS + vmov.s32 q14, #1 + vmov.s32 q15, #16 @ 31 - SCALE_OUT_BITS + vadd.s32 q1, q1, q14 +3: + vld1.32 {d16, d17}, [r6, :128], r11 + vabs.s32 q8, q8 + vld1.32 {d18, d19}, [r6, :128], r11 + vabs.s32 q9, q9 + vld1.32 {d20, d21}, [r6, :128], r11 + vabs.s32 q10, q10 + vld1.32 {d22, d23}, [r6, :128], r11 + vabs.s32 q11, q11 + vmax.s32 q0, q0, q8 + vmax.s32 q1, q1, q9 + vmax.s32 q0, q0, q10 + vmax.s32 q1, q1, q11 + subs r12, r12, #4 + bgt 3b + vmax.s32 q0, q0, q1 + vsub.s32 q0, q0, q14 + vclz.s32 q0, q0 + vsub.s32 q0, q15, q0 + vst1.32 {d0, d1}, [r8, :128] + + add r10, r10, #4 + cmp r10, r4 + blt 2b + + add r9, r9, #1 + cmp r9, r3 + blt 1b + + pop {r1-r2, r4-r12} + bx lr +endfunc + +/* + * constants: q13 = (31 - SCALE_OUT_BITS) + * q14 = 1 + * input: q0 - ((1 << SCALE_OUT_BITS) + 1) + * r5 - samples for channel 0 + * r6 - samples for shannel 1 + * output: q0, q1 - scale factors without joint stereo + * q2, q3 - scale factors with joint stereo + * q15 - joint stereo selection mask + */ +.macro calc_scalefactors + vmov.s32 q1, q0 + vmov.s32 q2, q0 + vmov.s32 q3, q0 + mov r3, r2 +1: + vld1.32 {d18, d19}, [r6, :128], r11 + vbic.s32 q11, q9, q14 + vld1.32 {d16, d17}, [r5, :128], r11 + vhadd.s32 q10, q8, q11 + vhsub.s32 q11, q8, q11 + vabs.s32 q8, q8 + vabs.s32 q9, q9 + vabs.s32 q10, q10 + vabs.s32 q11, q11 + vmax.s32 q0, q0, q8 + vmax.s32 q1, q1, q9 + vmax.s32 q2, q2, q10 + vmax.s32 q3, q3, q11 + subs r3, r3, #1 + bgt 1b + vsub.s32 q0, q0, q14 + vsub.s32 q1, q1, q14 + vsub.s32 q2, q2, q14 + vsub.s32 q3, q3, q14 + vclz.s32 q0, q0 + vclz.s32 q1, q1 + vclz.s32 q2, q2 + vclz.s32 q3, q3 + vsub.s32 q0, q13, q0 + vsub.s32 q1, q13, q1 + vsub.s32 q2, q13, q2 + vsub.s32 q3, q13, q3 +.endm + +/* + * constants: q14 = 1 + * input: q15 - joint stereo selection mask + * r5 - value set by calc_scalefactors macro + * r6 - value set by calc_scalefactors macro + */ +.macro update_joint_stereo_samples + sub r8, r6, r11 + sub r7, r5, r11 + sub r6, r6, r11, asl #1 + sub r5, r5, r11, asl #1 + vld1.32 {d18, d19}, [r6, :128] + vbic.s32 q11, q9, q14 + vld1.32 {d16, d17}, [r5, :128] + vld1.32 {d2, d3}, [r8, :128] + vbic.s32 q3, q1, q14 + vld1.32 {d0, d1}, [r7, :128] + vhsub.s32 q10, q8, q11 + vhadd.s32 q11, q8, q11 + vhsub.s32 q2, q0, q3 + vhadd.s32 q3, q0, q3 + vbif.s32 q10, q9, q15 + vbif.s32 d22, d16, d30 + sub r11, r10, r11, asl #1 + sub r3, r2, #2 +2: + vbif.s32 d23, d17, d31 + vst1.32 {d20, d21}, [r6, :128], r11 + vbif.s32 d4, d2, d30 + vld1.32 {d18, d19}, [r6, :128] + vbif.s32 d5, d3, d31 + vst1.32 {d22, d23}, [r5, :128], r11 + vbif.s32 d6, d0, d30 + vld1.32 {d16, d17}, [r5, :128] + vbif.s32 d7, d1, d31 + vst1.32 {d4, d5}, [r8, :128], r11 + vbic.s32 q11, q9, q14 + vld1.32 {d2, d3}, [r8, :128] + vst1.32 {d6, d7}, [r7, :128], r11 + vbic.s32 q3, q1, q14 + vld1.32 {d0, d1}, [r7, :128] + vhsub.s32 q10, q8, q11 + vhadd.s32 q11, q8, q11 + vhsub.s32 q2, q0, q3 + vhadd.s32 q3, q0, q3 + vbif.s32 q10, q9, q15 + vbif.s32 d22, d16, d30 + subs r3, r3, #2 + bgt 2b + sub r11, r10, r11, asr #1 + vbif.s32 d23, d17, d31 + vst1.32 {d20, d21}, [r6, :128] + vbif.s32 q2, q1, q15 + vst1.32 {d22, d23}, [r5, :128] + vbif.s32 q3, q0, q15 + vst1.32 {d4, d5}, [r8, :128] + vst1.32 {d6, d7}, [r7, :128] +.endm + +function ff_sbc_calc_scalefactors_j_neon, export=1 + @ parameters + @ r0 = in = sb_sample_f + @ r1 = out = scale_factor + @ r2 = blocks + @ r3 = subbands + @ local variables + @ r4 = consts = ff_sbcdsp_joint_bits_mask + @ r5 = in0 + @ r6 = in1 + @ r7 = out0 + @ r8 = out1 + @ r10 = zero + @ r11 = inc + @ return r0 = joint + + push {r3-r11} + movrelx r4, X(ff_sbcdsp_joint_bits_mask) + mov r10, #0 + mov r11, #64 + + vmov.s32 q14, #1 + vmov.s32 q13, #16 @ 31 - SCALE_OUT_BITS + + cmp r3, #4 + bne 8f + +4: @ 4 subbands + add r5, r0, #0 + add r6, r0, #32 + add r7, r1, #0 + add r8, r1, #32 + vmov.s32 q0, #0x8000 @ 1 << SCALE_OUT_BITS + vadd.s32 q0, q0, q14 + + calc_scalefactors + + @ check whether to use joint stereo for subbands 0, 1, 2 + vadd.s32 q15, q0, q1 + vadd.s32 q9, q2, q3 + vmov.s32 d31[1], r10 @ last subband -> no joint + vld1.32 {d16, d17}, [r4, :128]! + vcgt.s32 q15, q15, q9 + + @ calculate and save to memory 'joint' variable + @ update and save scale factors to memory + vand.s32 q8, q8, q15 + vbit.s32 q0, q2, q15 + vpadd.s32 d16, d16, d17 + vbit.s32 q1, q3, q15 + vpadd.s32 d16, d16, d16 + vst1.32 {d0, d1}, [r7, :128] + vst1.32 {d2, d3}, [r8, :128] + vmov.32 r0, d16[0] + + update_joint_stereo_samples + b 9f + +8: @ 8 subbands + add r5, r0, #16 + add r6, r0, #48 + add r7, r1, #16 + add r8, r1, #48 + vmov.s32 q0, #0x8000 @ 1 << SCALE_OUT_BITS + vadd.s32 q0, q0, q14 + + calc_scalefactors + + @ check whether to use joint stereo for subbands 4, 5, 6 + vadd.s32 q15, q0, q1 + vadd.s32 q9, q2, q3 + vmov.s32 d31[1], r10 @ last subband -> no joint + vld1.32 {d16, d17}, [r4, :128]! + vcgt.s32 q15, q15, q9 + + @ calculate part of 'joint' variable and save it to d24 + @ update and save scale factors to memory + vand.s32 q8, q8, q15 + vbit.s32 q0, q2, q15 + vpadd.s32 d16, d16, d17 + vbit.s32 q1, q3, q15 + vst1.32 {d0, d1}, [r7, :128] + vst1.32 {d2, d3}, [r8, :128] + vpadd.s32 d24, d16, d16 + + update_joint_stereo_samples + + add r5, r0, #0 + add r6, r0, #32 + add r7, r1, #0 + add r8, r1, #32 + vmov.s32 q0, #0x8000 @ 1 << SCALE_OUT_BITS + vadd.s32 q0, q0, q14 + + calc_scalefactors + + @ check whether to use joint stereo for subbands 0, 1, 2, 3 + vadd.s32 q15, q0, q1 + vadd.s32 q9, q2, q3 + vld1.32 {d16, d17}, [r4, :128]! + vcgt.s32 q15, q15, q9 + + @ combine last part of 'joint' with d24 and save to memory + @ update and save scale factors to memory + vand.s32 q8, q8, q15 + vbit.s32 q0, q2, q15 + vpadd.s32 d16, d16, d17 + vbit.s32 q1, q3, q15 + vpadd.s32 d16, d16, d16 + vst1.32 {d0, d1}, [r7, :128] + vadd.s32 d16, d16, d24 + vst1.32 {d2, d3}, [r8, :128] + vmov.32 r0, d16[0] + + update_joint_stereo_samples +9: + pop {r3-r11} + bx lr +endfunc + +function ff_sbc_enc_process_input_4s_neon, export=1 + @ parameters + @ r0 = positioin + @ r1 = pcm + @ r2 = X + @ r3 = nsamples + @ r4 = nchannels + @ local variables + @ r5 = ff_sbc_input_perm_4 + @ r6 = src / x + @ r7 = dst / y + + push {r1, r3-r7} + ldr r4, [sp, #24] + movrelx r5, X(ff_sbc_input_perm_4) + + @ handle X buffer wraparound + cmp r0, r3 + bge 1f @ if (position < nsamples) + add r7, r2, #576 @ &X[0][SBC_X_BUFFER_SIZE - 40] + add r6, r2, r0, lsl#1 @ &X[0][position] + vld1.16 {d0, d1, d2, d3}, [r6, :128]! + vst1.16 {d0, d1, d2, d3}, [r7, :128]! + vld1.16 {d0, d1, d2, d3}, [r6, :128]! + vst1.16 {d0, d1, d2, d3}, [r7, :128]! + vld1.16 {d0}, [r6, :64]! + vst1.16 {d0}, [r7, :64]! + cmp r4, #1 + ble 2f @ if (nchannels > 1) + add r7, r2, #1232 @ &X[1][SBC_X_BUFFER_SIZE - 40] + add r6, r2, #656 + add r6, r6, r0, lsl#1 @ &X[1][position] + vld1.16 {d0, d1, d2, d3}, [r6, :128]! + vst1.16 {d0, d1, d2, d3}, [r7, :128]! + vld1.16 {d0, d1, d2, d3}, [r6, :128]! + vst1.16 {d0, d1, d2, d3}, [r7, :128]! + vld1.16 {d0}, [r6, :64]! + vst1.16 {d0}, [r7, :64]! +2: + mov r0, #288 @ SBC_X_BUFFER_SIZE - 40 +1: + + add r6, r2, r0, lsl#1 @ &X[0][position] + add r7, r6, #656 @ &X[1][position] + + cmp r4, #1 + ble 8f @ if (nchannels > 1) + tst r1, #1 + beq 7f @ if (pcm & 1) + @ poor 'pcm' alignment + vld1.8 {d0, d1}, [r5, :128] +1: + sub r6, r6, #16 + sub r7, r7, #16 + sub r0, r0, #8 + vld1.8 {d4, d5}, [r1]! + vuzp.16 d4, d5 + vld1.8 {d20, d21}, [r1]! + vuzp.16 d20, d21 + vswp d5, d20 + vtbl.8 d16, {d4, d5}, d0 + vtbl.8 d17, {d4, d5}, d1 + vtbl.8 d18, {d20, d21}, d0 + vtbl.8 d19, {d20, d21}, d1 + vst1.16 {d16, d17}, [r6, :128] + vst1.16 {d18, d19}, [r7, :128] + subs r3, r3, #8 + bgt 1b + b 9f +7: + @ proper 'pcm' alignment + vld1.8 {d0, d1}, [r5, :128] +1: + sub r6, r6, #16 + sub r7, r7, #16 + sub r0, r0, #8 + vld2.16 {d4, d5}, [r1]! + vld2.16 {d20, d21}, [r1]! + vswp d5, d20 + vtbl.8 d16, {d4, d5}, d0 + vtbl.8 d17, {d4, d5}, d1 + vtbl.8 d18, {d20, d21}, d0 + vtbl.8 d19, {d20, d21}, d1 + vst1.16 {d16, d17}, [r6, :128] + vst1.16 {d18, d19}, [r7, :128] + subs r3, r3, #8 + bgt 1b + b 9f +8: + @ mono + vld1.8 {d0, d1}, [r5, :128] +1: + sub r6, r6, #16 + sub r0, r0, #8 + vld1.8 {d4, d5}, [r1]! + vtbl.8 d16, {d4, d5}, d0 + vtbl.8 d17, {d4, d5}, d1 + vst1.16 {d16, d17}, [r6, :128] + subs r3, r3, #8 + bgt 1b +9: + pop {r1, r3-r7} + bx lr +endfunc + +function ff_sbc_enc_process_input_8s_neon, export=1 + @ parameters + @ r0 = positioin + @ r1 = pcm + @ r2 = X + @ r3 = nsamples + @ r4 = nchannels + @ local variables + @ r5 = ff_sbc_input_perm_8 + @ r6 = src + @ r7 = dst + + push {r1, r3-r7} + ldr r4, [sp, #24] + movrelx r5, X(ff_sbc_input_perm_8) + + @ handle X buffer wraparound + cmp r0, r3 + bge 1f @ if (position < nsamples) + add r7, r2, #512 @ &X[0][SBC_X_BUFFER_SIZE - 72] + add r6, r2, r0, lsl#1 @ &X[0][position] + vld1.16 {d0, d1, d2, d3}, [r6, :128]! + vst1.16 {d0, d1, d2, d3}, [r7, :128]! + vld1.16 {d0, d1, d2, d3}, [r6, :128]! + vst1.16 {d0, d1, d2, d3}, [r7, :128]! + vld1.16 {d0, d1, d2, d3}, [r6, :128]! + vst1.16 {d0, d1, d2, d3}, [r7, :128]! + vld1.16 {d0, d1, d2, d3}, [r6, :128]! + vst1.16 {d0, d1, d2, d3}, [r7, :128]! + vld1.16 {d0, d1}, [r6, :128]! + vst1.16 {d0, d1}, [r7, :128]! + cmp r4, #1 + ble 2f @ if (nchannels > 1) + add r7, r2, #1168 @ &X[1][SBC_X_BUFFER_SIZE - 72] + add r6, r2, #656 + add r6, r6, r0, lsl#1 @ &X[1][position] + vld1.16 {d0, d1, d2, d3}, [r6, :128]! + vst1.16 {d0, d1, d2, d3}, [r7, :128]! + vld1.16 {d0, d1, d2, d3}, [r6, :128]! + vst1.16 {d0, d1, d2, d3}, [r7, :128]! + vld1.16 {d0, d1, d2, d3}, [r6, :128]! + vst1.16 {d0, d1, d2, d3}, [r7, :128]! + vld1.16 {d0, d1, d2, d3}, [r6, :128]! + vst1.16 {d0, d1, d2, d3}, [r7, :128]! + vld1.16 {d0, d1}, [r6, :128]! + vst1.16 {d0, d1}, [r7, :128]! +2: + mov r0, #256 @ SBC_X_BUFFER_SIZE - 72 +1: + + add r6, r2, r0, lsl#1 @ &X[0][position] + add r7, r6, #656 @ &X[1][position] + + cmp r4, #1 + ble 8f @ if (nchannels > 1) + tst r1, #1 + beq 7f @ if (pcm & 1) + @ poor 'pcm' alignment + vld1.8 {d0, d1, d2, d3}, [r5, :128] +1: + sub r6, r6, #32 + sub r7, r7, #32 + sub r0, r0, #16 + vld1.8 {d4, d5, d6, d7}, [r1]! + vuzp.16 q2, q3 + vld1.8 {d20, d21, d22, d23}, [r1]! + vuzp.16 q10, q11 + vswp q3, q10 + vtbl.8 d16, {d4, d5, d6, d7}, d0 + vtbl.8 d17, {d4, d5, d6, d7}, d1 + vtbl.8 d18, {d4, d5, d6, d7}, d2 + vtbl.8 d19, {d4, d5, d6, d7}, d3 + vst1.16 {d16, d17, d18, d19}, [r6, :128] + vtbl.8 d16, {d20, d21, d22, d23}, d0 + vtbl.8 d17, {d20, d21, d22, d23}, d1 + vtbl.8 d18, {d20, d21, d22, d23}, d2 + vtbl.8 d19, {d20, d21, d22, d23}, d3 + vst1.16 {d16, d17, d18, d19}, [r7, :128] + subs r3, r3, #16 + bgt 1b + b 9f +7: + @ proper 'pcm' alignment + vld1.8 {d0, d1, d2, d3}, [r5, :128] +1: + sub r6, r6, #32 + sub r7, r7, #32 + sub r0, r0, #16 + vld2.16 {d4, d5, d6, d7}, [r1]! + vld2.16 {d20, d21, d22, d23}, [r1]! + vswp q3, q10 + vtbl.8 d16, {d4, d5, d6, d7}, d0 + vtbl.8 d17, {d4, d5, d6, d7}, d1 + vtbl.8 d18, {d4, d5, d6, d7}, d2 + vtbl.8 d19, {d4, d5, d6, d7}, d3 + vst1.16 {d16, d17, d18, d19}, [r6, :128] + vtbl.8 d16, {d20, d21, d22, d23}, d0 + vtbl.8 d17, {d20, d21, d22, d23}, d1 + vtbl.8 d18, {d20, d21, d22, d23}, d2 + vtbl.8 d19, {d20, d21, d22, d23}, d3 + vst1.16 {d16, d17, d18, d19}, [r7, :128] + subs r3, r3, #16 + bgt 1b + b 9f +8: + @ mono + vld1.8 {d0, d1, d2, d3}, [r5, :128] +1: + sub r6, r6, #32 + sub r0, r0, #16 + vld1.8 {d4, d5, d6, d7}, [r1]! + vtbl.8 d16, {d4, d5, d6, d7}, d0 + vtbl.8 d17, {d4, d5, d6, d7}, d1 + vtbl.8 d18, {d4, d5, d6, d7}, d2 + vtbl.8 d19, {d4, d5, d6, d7}, d3 + vst1.16 {d16, d17, d18, d19}, [r6, :128] + subs r3, r3, #16 + bgt 1b +9: + pop {r1, r3-r7} + bx lr +endfunc diff --git a/libavcodec/sbcdsp.c b/libavcodec/sbcdsp.c index 2d0addcf28930..e745595da012c 100644 --- a/libavcodec/sbcdsp.c +++ b/libavcodec/sbcdsp.c @@ -380,6 +380,8 @@ av_cold void ff_sbcdsp_init(SBCDSPContext *s) s->sbc_calc_scalefactors = sbc_calc_scalefactors; s->sbc_calc_scalefactors_j = sbc_calc_scalefactors_j; + if (ARCH_ARM) + ff_sbcdsp_init_arm(s); if (ARCH_X86) ff_sbcdsp_init_x86(s); } diff --git a/libavcodec/sbcdsp.h b/libavcodec/sbcdsp.h index 127e6a8a11eb3..334c058e6de02 100644 --- a/libavcodec/sbcdsp.h +++ b/libavcodec/sbcdsp.h @@ -80,6 +80,7 @@ struct sbc_dsp_context { */ void ff_sbcdsp_init(SBCDSPContext *s); +void ff_sbcdsp_init_arm(SBCDSPContext *s); void ff_sbcdsp_init_x86(SBCDSPContext *s); #endif /* AVCODEC_SBCDSP_H */ From 840f6eb77aed6c9dc2eff1a89add3611ec305262 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Sun, 17 Dec 2017 20:27:04 +0100 Subject: [PATCH 2065/2557] Changelog: list the new SBC codec --- Changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog b/Changelog index e2a4224c91f00..d8630731fa1d6 100644 --- a/Changelog +++ b/Changelog @@ -44,6 +44,7 @@ version : - muxer/demuxer for raw codec2 files and .c2 files - Moved nvidia codec headers into an external repository. They can be found at http://git.videolan.org/?p=ffmpeg/nv-codec-headers.git +- native SBC encoder and decoder version 3.4: From 2a0eb8685728ccb260e42f60e1dbefe47ababbc3 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 6 Mar 2018 13:07:32 -0800 Subject: [PATCH 2066/2557] avcodec/mediacodecdec: add delay_flush option The default behavior of the mediacodec decoder before this commit was to delay flushes until all pending hardware frames were returned to the decoder. This was useful for certain types of applications, but was unexpected behavior for others. The new default behavior with this commit is now to execute flushes immediately to invalidate all pending frames. The old behavior can be enabled by setting delay_flush=1. With the new behavior, video players implementing seek can simply call flush on the decoder without having to worry about whether they have one or more mediacodec frames still buffered in their rendering pipeline. Previously, all these frames had to be explictly freed (or rendered) before the seek/flush would execute. The new behavior matches the behavior of all other lavc decoders, reducing the amount of special casing required when using the mediacodec decoder. Signed-off-by: Aman Gupta Signed-off-by: Matthieu Bouron --- doc/APIchanges | 5 +++++ libavcodec/mediacodec.c | 2 +- libavcodec/mediacodecdec.c | 24 ++++++++++++++++++++++++ libavcodec/mediacodecdec_common.c | 11 ++++++++--- libavcodec/mediacodecdec_common.h | 4 ++++ libavcodec/version.h | 4 ++-- 6 files changed, 44 insertions(+), 6 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index d1957e2e191c6..297a5a20618ba 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,11 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-03-xx - xxxxxxx - lavc 58.14.100 - mediacodec.h + Change the default behavior of avcodec_flush() on mediacodec + video decoders. To restore the previous behavior, use the new + delay_flush=1 option. + 2018-03-xx - xxxxxxx - lavu 56.8.100 - frame.h Add av_frame_new_side_data_from_buf(). diff --git a/libavcodec/mediacodec.c b/libavcodec/mediacodec.c index d492eefe0b5ce..bf1b7477f15ba 100644 --- a/libavcodec/mediacodec.c +++ b/libavcodec/mediacodec.c @@ -91,7 +91,7 @@ int av_mediacodec_release_buffer(AVMediaCodecBuffer *buffer, int render) MediaCodecDecContext *ctx = buffer->ctx; int released = atomic_fetch_add(&buffer->released, 1); - if (!released) { + if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) { return ff_AMediaCodec_releaseOutputBuffer(ctx->codec, buffer->index, render); } diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 0fe14846c3373..89d2421ae907f 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -41,10 +41,14 @@ typedef struct MediaCodecH264DecContext { + AVClass *avclass; + MediaCodecDecContext *ctx; AVPacket buffered_pkt; + int delay_flush; + } MediaCodecH264DecContext; static av_cold int mediacodec_decode_close(AVCodecContext *avctx) @@ -366,6 +370,8 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx) goto done; } + s->ctx->delay_flush = s->delay_flush; + if ((ret = ff_mediacodec_dec_init(avctx, s->ctx, codec_mime, format)) < 0) { s->ctx = NULL; goto done; @@ -485,12 +491,30 @@ static const AVCodecHWConfigInternal *mediacodec_hw_configs[] = { NULL }; +#define OFFSET(x) offsetof(MediaCodecH264DecContext, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption ff_mediacodec_vdec_options[] = { + { "delay_flush", "Delay flush until hw output buffers are returned to the decoder", + OFFSET(delay_flush), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, VD }, + { NULL } +}; + +#define DECLARE_MEDIACODEC_VCLASS(short_name) \ +static const AVClass ff_##short_name##_mediacodec_dec_class = { \ + .class_name = #short_name "_mediacodec", \ + .item_name = av_default_item_name, \ + .option = ff_mediacodec_vdec_options, \ + .version = LIBAVUTIL_VERSION_INT, \ +}; + #define DECLARE_MEDIACODEC_VDEC(short_name, full_name, codec_id, bsf) \ +DECLARE_MEDIACODEC_VCLASS(short_name) \ AVCodec ff_##short_name##_mediacodec_decoder = { \ .name = #short_name "_mediacodec", \ .long_name = NULL_IF_CONFIG_SMALL(full_name " Android MediaCodec decoder"), \ .type = AVMEDIA_TYPE_VIDEO, \ .id = codec_id, \ + .priv_class = &ff_##short_name##_mediacodec_dec_class, \ .priv_data_size = sizeof(MediaCodecH264DecContext), \ .init = mediacodec_decode_init, \ .receive_frame = mediacodec_receive_frame, \ diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index 0bd660f7c9ea8..693524abd6599 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -178,11 +178,12 @@ static void mediacodec_buffer_release(void *opaque, uint8_t *data) MediaCodecDecContext *ctx = buffer->ctx; int released = atomic_load(&buffer->released); - if (!released) { + if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) { ff_AMediaCodec_releaseOutputBuffer(ctx->codec, buffer->index, 0); } - ff_mediacodec_dec_unref(ctx); + if (ctx->delay_flush) + ff_mediacodec_dec_unref(ctx); av_freep(&buffer); } @@ -236,7 +237,9 @@ FF_ENABLE_DEPRECATION_WARNINGS } buffer->ctx = s; - ff_mediacodec_dec_ref(s); + buffer->serial = atomic_load(&s->serial); + if (s->delay_flush) + ff_mediacodec_dec_ref(s); buffer->index = index; buffer->pts = info->presentationTimeUs; @@ -425,6 +428,7 @@ static int mediacodec_dec_flush_codec(AVCodecContext *avctx, MediaCodecDecContex s->draining = 0; s->flushing = 0; s->eos = 0; + atomic_fetch_add(&s->serial, 1); status = ff_AMediaCodec_flush(codec); if (status < 0) { @@ -449,6 +453,7 @@ int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s, }; atomic_init(&s->refcount, 1); + atomic_init(&s->serial, 1); pix_fmt = ff_get_format(avctx, pix_fmts); if (pix_fmt == AV_PIX_FMT_MEDIACODEC) { diff --git a/libavcodec/mediacodecdec_common.h b/libavcodec/mediacodecdec_common.h index 85df507ffb287..afb98ffed9b2f 100644 --- a/libavcodec/mediacodecdec_common.h +++ b/libavcodec/mediacodecdec_common.h @@ -62,6 +62,9 @@ typedef struct MediaCodecDecContext { uint64_t output_buffer_count; + bool delay_flush; + atomic_int serial; + } MediaCodecDecContext; int ff_mediacodec_dec_init(AVCodecContext *avctx, @@ -93,6 +96,7 @@ typedef struct MediaCodecBuffer { ssize_t index; int64_t pts; atomic_int released; + int serial; } MediaCodecBuffer; diff --git a/libavcodec/version.h b/libavcodec/version.h index d8256bff21e4d..ed34095c77675 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 13 -#define LIBAVCODEC_VERSION_MICRO 102 +#define LIBAVCODEC_VERSION_MINOR 14 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From 823a758543e2b1052cdcff22d02d396f4e0792f9 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 6 Mar 2018 13:14:51 -0800 Subject: [PATCH 2067/2557] avcodec/mediacodecdec: add more trace logging of input/output buffers Signed-off-by: Aman Gupta Signed-off-by: Matthieu Bouron --- libavcodec/mediacodec.c | 3 +++ libavcodec/mediacodecdec_common.c | 8 ++++++-- libavcodec/mediacodecdec_common.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libavcodec/mediacodec.c b/libavcodec/mediacodec.c index bf1b7477f15ba..3ddd303c975f3 100644 --- a/libavcodec/mediacodec.c +++ b/libavcodec/mediacodec.c @@ -92,6 +92,9 @@ int av_mediacodec_release_buffer(AVMediaCodecBuffer *buffer, int render) int released = atomic_fetch_add(&buffer->released, 1); if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) { + av_log(ctx->avctx, AV_LOG_TRACE, + "Releasing output buffer %zd ts=%"PRId64" render=%d\n", + buffer->index, buffer->pts, render); return ff_AMediaCodec_releaseOutputBuffer(ctx->codec, buffer->index, render); } diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index 693524abd6599..5064809cf6f52 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -452,6 +452,7 @@ int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s, AV_PIX_FMT_NONE, }; + s->avctx = avctx; atomic_init(&s->refcount, 1); atomic_init(&s->serial, 1); @@ -598,8 +599,8 @@ int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s, return AVERROR_EXTERNAL; } - av_log(avctx, AV_LOG_TRACE, "Queued input buffer %zd" - " size=%zd ts=%" PRIi64 "\n", index, size, pts); + av_log(avctx, AV_LOG_TRACE, + "Queued input buffer %zd size=%zd ts=%"PRIi64"\n", index, size, pts); s->draining = 1; break; @@ -619,6 +620,9 @@ int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s, av_log(avctx, AV_LOG_ERROR, "Failed to queue input buffer (status = %d)\n", status); return AVERROR_EXTERNAL; } + + av_log(avctx, AV_LOG_TRACE, + "Queued input buffer %zd size=%zd ts=%"PRIi64"\n", index, size, pts); } } diff --git a/libavcodec/mediacodecdec_common.h b/libavcodec/mediacodecdec_common.h index afb98ffed9b2f..3fd2412a650eb 100644 --- a/libavcodec/mediacodecdec_common.h +++ b/libavcodec/mediacodecdec_common.h @@ -36,6 +36,7 @@ typedef struct MediaCodecDecContext { + AVCodecContext *avctx; atomic_int refcount; char *codec_name; From 00ae5c1d3d87efc7f13b86cce80e139c805db179 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Tue, 6 Feb 2018 16:17:17 +0800 Subject: [PATCH 2068/2557] lavc/vaapi_encode: Don't return error if the underlying driver doesn't support B frames The underlying driver need not support B frames - since they are enabled by default for some codecs, it is better to disable them rather than returning an error in this case. This makes the default settings usable for low-power encoding on Intel platforms. Signed-off-by: Haihao Xiang Signed-off-by: Mark Thompson --- libavcodec/vaapi_encode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index f5785ce4c532c..36c85a381547a 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1096,10 +1096,10 @@ static av_cold int vaapi_encode_config_attributes(AVCodecContext *avctx) goto fail; } if (avctx->max_b_frames > 0 && ref_l1 < 1) { - av_log(avctx, AV_LOG_ERROR, "B frames are not " - "supported (%#x).\n", attr[i].value); - err = AVERROR(EINVAL); - goto fail; + av_log(avctx, AV_LOG_WARNING, "B frames are not " + "supported (%#x) by the underlying driver.\n", + attr[i].value); + avctx->max_b_frames = 0; } } break; From 80798e385780b5f20ab08d1338f36dc31f11a7f6 Mon Sep 17 00:00:00 2001 From: Yingming Fan Date: Wed, 7 Mar 2018 12:42:30 +0800 Subject: [PATCH 2069/2557] checkasm/hevc_sao : add hevc_sao for checkasm Signed-off-by: James Almer --- tests/checkasm/Makefile | 2 +- tests/checkasm/checkasm.c | 1 + tests/checkasm/checkasm.h | 1 + tests/checkasm/hevc_sao.c | 150 ++++++++++++++++++++++++++++++++++++++ tests/fate/checkasm.mak | 1 + 5 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 tests/checkasm/hevc_sao.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 77bdcf6e65602..0520e264e2a80 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -23,7 +23,7 @@ AVCODECOBJS-$(CONFIG_EXR_DECODER) += exrdsp.o AVCODECOBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuvdsp.o AVCODECOBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dsp.o AVCODECOBJS-$(CONFIG_PIXBLOCKDSP) += pixblockdsp.o -AVCODECOBJS-$(CONFIG_HEVC_DECODER) += hevc_add_res.o hevc_idct.o +AVCODECOBJS-$(CONFIG_HEVC_DECODER) += hevc_add_res.o hevc_idct.o hevc_sao.o AVCODECOBJS-$(CONFIG_UTVIDEO_DECODER) += utvideodsp.o AVCODECOBJS-$(CONFIG_V210_ENCODER) += v210enc.o AVCODECOBJS-$(CONFIG_VP9_DECODER) += vp9dsp.o diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index a4b8aff9848a1..fe81d139c6250 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -116,6 +116,7 @@ static const struct { #if CONFIG_HEVC_DECODER { "hevc_add_res", checkasm_check_hevc_add_res }, { "hevc_idct", checkasm_check_hevc_idct }, + { "hevc_sao", checkasm_check_hevc_sao }, #endif #if CONFIG_HUFFYUV_DECODER { "huffyuvdsp", checkasm_check_huffyuvdsp }, diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 3de38e67172cc..8b9d96bc1525b 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -57,6 +57,7 @@ void checkasm_check_h264pred(void); void checkasm_check_h264qpel(void); void checkasm_check_hevc_add_res(void); void checkasm_check_hevc_idct(void); +void checkasm_check_hevc_sao(void); void checkasm_check_huffyuvdsp(void); void checkasm_check_jpeg2000dsp(void); void checkasm_check_llviddsp(void); diff --git a/tests/checkasm/hevc_sao.c b/tests/checkasm/hevc_sao.c new file mode 100644 index 0000000000000..8d0cf807746dc --- /dev/null +++ b/tests/checkasm/hevc_sao.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2018 Yingming Fan + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "libavutil/intreadwrite.h" + +#include "libavcodec/avcodec.h" + +#include "libavcodec/hevcdsp.h" + +#include "checkasm.h" + +static const uint32_t pixel_mask[3] = { 0xffffffff, 0x03ff03ff, 0x0fff0fff }; +static const uint32_t sao_size[5] = {8, 16, 32, 48, 64}; + +#define SIZEOF_PIXEL ((bit_depth + 7) / 8) +#define PIXEL_STRIDE (2*MAX_PB_SIZE + AV_INPUT_BUFFER_PADDING_SIZE) //same with sao_edge src_stride +#define BUF_SIZE (PIXEL_STRIDE * (64+2) * 2) //+2 for top and bottom row, *2 for high bit depth +#define OFFSET_THRESH (1 << (bit_depth - 5)) +#define OFFSET_LENGTH 5 + +#define randomize_buffers(buf0, buf1, size) \ + do { \ + uint32_t mask = pixel_mask[(bit_depth - 8) >> 1]; \ + int k; \ + for (k = 0; k < size; k += 4) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(buf0 + k, r); \ + AV_WN32A(buf1 + k, r); \ + } \ + } while (0) + +#define randomize_buffers2(buf, size) \ + do { \ + uint32_t max_offset = OFFSET_THRESH; \ + int k; \ + if (bit_depth == 8) { \ + for (k = 0; k < size; k++) { \ + uint8_t r = rnd() % max_offset; \ + buf[k] = r; \ + } \ + } else { \ + for (k = 0; k < size; k++) { \ + uint16_t r = rnd() % max_offset; \ + buf[k] = r; \ + } \ + } \ + } while (0) + +static void check_sao_band(HEVCDSPContext h, int bit_depth) +{ + int i; + LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, src0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, src1, [BUF_SIZE]); + int16_t offset_val[OFFSET_LENGTH]; + int left_class = rnd()%32; + + for (i = 0; i <= 4; i++) { + int block_size = sao_size[i]; + ptrdiff_t stride = PIXEL_STRIDE*SIZEOF_PIXEL; + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, uint8_t *src, ptrdiff_t dst_stride, ptrdiff_t src_stride, + int16_t *sao_offset_val, int sao_left_class, int width, int height); + + randomize_buffers(src0, src1, BUF_SIZE); + randomize_buffers2(offset_val, OFFSET_LENGTH); + memset(dst0, 0, BUF_SIZE); + memset(dst1, 0, BUF_SIZE); + + if (check_func(h.sao_band_filter[i], "hevc_sao_band_%dx%d_%d", block_size, block_size, bit_depth)) { + call_ref(dst0, src0, stride, stride, offset_val, left_class, block_size, block_size); + call_new(dst1, src1, stride, stride, offset_val, left_class, block_size, block_size); + if (memcmp(dst0, dst1, BUF_SIZE)) + fail(); + bench_new(dst1, src1, stride, stride, offset_val, left_class, block_size, block_size); + } + } +} + +static void check_sao_edge(HEVCDSPContext h, int bit_depth) +{ + int i; + LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, src0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, src1, [BUF_SIZE]); + int16_t offset_val[OFFSET_LENGTH]; + int eo = rnd()%4; + + for (i = 0; i <= 4; i++) { + int block_size = sao_size[i]; + ptrdiff_t stride = PIXEL_STRIDE*SIZEOF_PIXEL; + int offset = (AV_INPUT_BUFFER_PADDING_SIZE + PIXEL_STRIDE)*SIZEOF_PIXEL; + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, uint8_t *src, ptrdiff_t stride_dst, + int16_t *sao_offset_val, int eo, int width, int height); + + randomize_buffers(src0, src1, BUF_SIZE); + randomize_buffers2(offset_val, OFFSET_LENGTH); + memset(dst0, 0, BUF_SIZE); + memset(dst1, 0, BUF_SIZE); + + if (check_func(h.sao_edge_filter[i], "hevc_sao_edge_%dx%d_%d", block_size, block_size, bit_depth)) { + call_ref(dst0, src0 + offset, stride, offset_val, eo, block_size, block_size); + call_new(dst1, src1 + offset, stride, offset_val, eo, block_size, block_size); + if (memcmp(dst0, dst1, BUF_SIZE)) + fail(); + bench_new(dst1, src1 + offset, stride, offset_val, eo, block_size, block_size); + } + } +} + +void checkasm_check_hevc_sao(void) +{ + int bit_depth; + + for (bit_depth = 8; bit_depth <= 12; bit_depth += 2) { + HEVCDSPContext h; + + ff_hevc_dsp_init(&h, bit_depth); + check_sao_band(h, bit_depth); + } + report("sao_band"); + + for (bit_depth = 8; bit_depth <= 12; bit_depth += 2) { + HEVCDSPContext h; + + ff_hevc_dsp_init(&h, bit_depth); + check_sao_edge(h, bit_depth); + } + report("sao_edge"); +} diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index 826ac16789689..cf62f9b1190f5 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -14,6 +14,7 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp \ fate-checkasm-h264qpel \ fate-checkasm-hevc_add_res \ fate-checkasm-hevc_idct \ + fate-checkasm-hevc_sao \ fate-checkasm-jpeg2000dsp \ fate-checkasm-llviddsp \ fate-checkasm-llviddspenc \ From 2f147588f7beac9c85df81f331ce38626def20d7 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 8 Mar 2018 11:04:12 +0100 Subject: [PATCH 2070/2557] avfilter/vf_vaguedenoiser: fix plane copy for >8 bit depth formats Fixes #7072. Signed-off-by: Paul B Mahol --- libavfilter/vf_vaguedenoiser.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_vaguedenoiser.c b/libavfilter/vf_vaguedenoiser.c index 2b93e70e57d28..b323ce54796a2 100644 --- a/libavfilter/vf_vaguedenoiser.c +++ b/libavfilter/vf_vaguedenoiser.c @@ -42,6 +42,7 @@ typedef struct VagueDenoiserContext { int planes; int depth; + int bpc; int peak; int nb_planes; int planeheight[4]; @@ -135,6 +136,7 @@ static int config_input(AVFilterLink *inlink) int p, i, nsteps_width, nsteps_height, nsteps_max; s->depth = desc->comp[0].depth; + s->bpc = (s->depth + 7) / 8; s->nb_planes = desc->nb_components; s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); @@ -410,7 +412,7 @@ static void filter(VagueDenoiserContext *s, AVFrame *in, AVFrame *out) if (!((1 << p) & s->planes)) { av_image_copy_plane(out->data[p], out->linesize[p], in->data[p], in->linesize[p], - s->planewidth[p], s->planeheight[p]); + s->planewidth[p] * s->bpc, s->planeheight[p]); continue; } From e4edc567a077d34f579d31ef0bfe164c7abfac4c Mon Sep 17 00:00:00 2001 From: Calvin Walton Date: Thu, 22 Feb 2018 14:10:03 -0500 Subject: [PATCH 2071/2557] libavfilter/vf_fps: Rewrite using activate callback The old version of the filter had a problem where it would queue up all of the duplicate frames required to fill a timestamp gap in a single call to filter_frame. In problematic files - I've hit this in webcam streams with large gaps due to network issues - this will queue up a potentially huge number of frames. (I've seen it trigger the Linux OOM-killer on particularly large pts gaps.) This revised version of the filter using the activate callback will generate at most 1 frame each time it is called. --- libavfilter/vf_fps.c | 352 ++++++++++++++++++++++--------------------- 1 file changed, 183 insertions(+), 169 deletions(-) diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c index dbafd2c35a66e..cc350243a9bd1 100644 --- a/libavfilter/vf_fps.c +++ b/libavfilter/vf_fps.c @@ -2,6 +2,7 @@ * Copyright 2007 Bobby Bingham * Copyright 2012 Robert Nagy * Copyright 2012 Anton Khirnov + * Copyright 2018 Calvin Walton * * This file is part of FFmpeg. * @@ -28,17 +29,12 @@ #include #include -#include "libavutil/common.h" -#include "libavutil/fifo.h" +#include "libavutil/avassert.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" -#include "libavutil/parseutils.h" - -#define FF_INTERNAL_FIELDS 1 -#include "framequeue.h" #include "avfilter.h" +#include "filters.h" #include "internal.h" -#include "video.h" enum EOFAction { EOF_ACTION_ROUND, @@ -49,18 +45,27 @@ enum EOFAction { typedef struct FPSContext { const AVClass *class; - AVFifoBuffer *fifo; ///< store frames until we get two successive timestamps - - /* timestamps in input timebase */ - int64_t first_pts; ///< pts of the first frame that arrived on this filter - double start_time; ///< pts, in seconds, of the expected first frame AVRational framerate; ///< target framerate int rounding; ///< AVRounding method for timestamps int eof_action; ///< action performed for last frame in FIFO + /* Set during outlink configuration */ + int64_t in_pts_off; ///< input frame pts offset for start_time handling + int64_t out_pts_off; ///< output frame pts offset for start_time handling + + /* Runtime state */ + int status; ///< buffered input status + int64_t status_pts; ///< buffered input status timestamp + + AVFrame *frames[2]; ///< buffered frames + int frames_count; ///< number of buffered frames + + int64_t next_pts; ///< pts of the next frame to output + /* statistics */ + int cur_frame_out; ///< number of times current frame has been output int frames_in; ///< number of frames on input int frames_out; ///< number of frames on output int dup; ///< number of frames duplicated @@ -91,31 +96,51 @@ static av_cold int init(AVFilterContext *ctx) { FPSContext *s = ctx->priv; - if (!(s->fifo = av_fifo_alloc_array(2, sizeof(AVFrame*)))) - return AVERROR(ENOMEM); - - s->first_pts = AV_NOPTS_VALUE; + s->status_pts = AV_NOPTS_VALUE; + s->next_pts = AV_NOPTS_VALUE; av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", s->framerate.num, s->framerate.den); return 0; } -static void flush_fifo(AVFifoBuffer *fifo) +/* Remove the first frame from the buffer, returning it */ +static AVFrame *shift_frame(AVFilterContext *ctx, FPSContext *s) { - while (av_fifo_size(fifo)) { - AVFrame *tmp; - av_fifo_generic_read(fifo, &tmp, sizeof(tmp), NULL); - av_frame_free(&tmp); + AVFrame *frame; + + /* Must only be called when there are frames in the buffer */ + av_assert1(s->frames_count > 0); + + frame = s->frames[0]; + s->frames[0] = s->frames[1]; + s->frames[1] = NULL; + s->frames_count--; + + /* Update statistics counters */ + s->frames_out += s->cur_frame_out; + if (s->cur_frame_out > 1) { + av_log(ctx, AV_LOG_DEBUG, "Duplicated frame with pts %"PRId64" %d times\n", + frame->pts, s->cur_frame_out - 1); + s->dup += s->cur_frame_out - 1; + } else if (s->cur_frame_out == 0) { + av_log(ctx, AV_LOG_DEBUG, "Dropping frame with pts %"PRId64"\n", + frame->pts); + s->drop++; } + s->cur_frame_out = 0; + + return frame; } static av_cold void uninit(AVFilterContext *ctx) { FPSContext *s = ctx->priv; - if (s->fifo) { - s->drop += av_fifo_size(s->fifo) / sizeof(AVFrame*); - flush_fifo(s->fifo); - av_fifo_freep(&s->fifo); + + AVFrame *frame; + + while (s->frames_count > 0) { + frame = shift_frame(ctx, s); + av_frame_free(&frame); } av_log(ctx, AV_LOG_VERBOSE, "%d frames in, %d frames out; %d frames dropped, " @@ -124,198 +149,187 @@ static av_cold void uninit(AVFilterContext *ctx) static int config_props(AVFilterLink* link) { - FPSContext *s = link->src->priv; + AVFilterContext *ctx = link->src; + AVFilterLink *inlink = ctx->inputs[0]; + FPSContext *s = ctx->priv; link->time_base = av_inv_q(s->framerate); link->frame_rate= s->framerate; link->w = link->src->inputs[0]->w; link->h = link->src->inputs[0]->h; - return 0; -} - -static int request_frame(AVFilterLink *outlink) -{ - AVFilterContext *ctx = outlink->src; - FPSContext *s = ctx->priv; - int ret; - - ret = ff_request_frame(ctx->inputs[0]); - - /* flush the fifo */ - if (ret == AVERROR_EOF && av_fifo_size(s->fifo)) { - int i; - for (i = 0; av_fifo_size(s->fifo); i++) { - AVFrame *buf; - - av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL); - if (av_fifo_size(s->fifo)) { - buf->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base, - outlink->time_base) + s->frames_out; - - if ((ret = ff_filter_frame(outlink, buf)) < 0) - return ret; - - s->frames_out++; - } else { - /* This is the last frame, we may have to duplicate it to match - * the last frame duration */ - int j; - int eof_rounding = (s->eof_action == EOF_ACTION_PASS) ? AV_ROUND_UP : s->rounding; - int delta = av_rescale_q_rnd(ctx->inputs[0]->current_pts - s->first_pts, - ctx->inputs[0]->time_base, - outlink->time_base, eof_rounding) - s->frames_out; - av_log(ctx, AV_LOG_DEBUG, "EOF frames_out:%d delta:%d\n", s->frames_out, delta); - /* if the delta is equal to 1, it means we just need to output - * the last frame. Greater than 1 means we will need duplicate - * delta-1 frames */ - if (delta > 0 ) { - for (j = 0; j < delta; j++) { - AVFrame *dup = av_frame_clone(buf); - - av_log(ctx, AV_LOG_DEBUG, "Duplicating frame.\n"); - dup->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base, - outlink->time_base) + s->frames_out; - - if ((ret = ff_filter_frame(outlink, dup)) < 0) - return ret; - - s->frames_out++; - if (j > 0) s->dup++; - } - av_frame_free(&buf); - } else { - /* for delta less or equal to 0, we should drop the frame, - * otherwise, we will have one or more extra frames */ - av_frame_free(&buf); - s->drop++; - } - } + /* Calculate the input and output pts offsets for start_time */ + if (s->start_time != DBL_MAX && s->start_time != AV_NOPTS_VALUE) { + double first_pts = s->start_time * AV_TIME_BASE; + if (first_pts < INT64_MIN || first_pts > INT64_MAX) { + av_log(ctx, AV_LOG_ERROR, "Start time %f cannot be represented in internal time base\n", + s->start_time); + return AVERROR(EINVAL); } - return 0; + s->in_pts_off = av_rescale_q_rnd(first_pts, AV_TIME_BASE_Q, inlink->time_base, + s->rounding | AV_ROUND_PASS_MINMAX); + s->out_pts_off = av_rescale_q_rnd(first_pts, AV_TIME_BASE_Q, link->time_base, + s->rounding | AV_ROUND_PASS_MINMAX); + s->next_pts = s->out_pts_off; + av_log(ctx, AV_LOG_VERBOSE, "Set first pts to (in:%"PRId64" out:%"PRId64") from start time %f\n", + s->in_pts_off, s->out_pts_off, s->start_time); } - return ret; + return 0; } -static int write_to_fifo(AVFifoBuffer *fifo, AVFrame *buf) +/* Read a frame from the input and save it in the buffer */ +static int read_frame(AVFilterContext *ctx, FPSContext *s, AVFilterLink *inlink, AVFilterLink *outlink) { + AVFrame *frame; int ret; + int64_t in_pts; - if (!av_fifo_space(fifo) && - (ret = av_fifo_realloc2(fifo, 2*av_fifo_size(fifo)))) { - av_frame_free(&buf); + /* Must only be called when we have buffer room available */ + av_assert1(s->frames_count < 2); + + ret = ff_inlink_consume_frame(inlink, &frame); + /* Caller must have run ff_inlink_check_available_frame first */ + av_assert1(ret); + if (ret < 0) return ret; - } - av_fifo_generic_write(fifo, &buf, sizeof(buf), NULL); - return 0; + /* Convert frame pts to output timebase. + * The dance with offsets is required to match the rounding behaviour of the + * previous version of the fps filter when using the start_time option. */ + in_pts = frame->pts; + frame->pts = s->out_pts_off + av_rescale_q_rnd(in_pts - s->in_pts_off, + inlink->time_base, outlink->time_base, + s->rounding | AV_ROUND_PASS_MINMAX); + + av_log(ctx, AV_LOG_DEBUG, "Read frame with in pts %"PRId64", out pts %"PRId64"\n", + in_pts, frame->pts); + + s->frames[s->frames_count++] = frame; + s->frames_in++; + + return 1; } -static int filter_frame(AVFilterLink *inlink, AVFrame *buf) +/* Write a frame to the output */ +static int write_frame(AVFilterContext *ctx, FPSContext *s, AVFilterLink *outlink, int *again) { - AVFilterContext *ctx = inlink->dst; - FPSContext *s = ctx->priv; - AVFilterLink *outlink = ctx->outputs[0]; - int64_t delta; - int i, ret; + AVFrame *frame; - s->frames_in++; - /* discard frames until we get the first timestamp */ - if (s->first_pts == AV_NOPTS_VALUE) { - if (buf->pts != AV_NOPTS_VALUE) { - ret = write_to_fifo(s->fifo, buf); - if (ret < 0) - return ret; + av_assert1(s->frames_count == 2 || (s->status && s->frames_count == 1)); - if (s->start_time != DBL_MAX && s->start_time != AV_NOPTS_VALUE) { - double first_pts = s->start_time * AV_TIME_BASE; - first_pts = FFMIN(FFMAX(first_pts, INT64_MIN), INT64_MAX); - s->first_pts = av_rescale_q(first_pts, AV_TIME_BASE_Q, - inlink->time_base); - av_log(ctx, AV_LOG_VERBOSE, "Set first pts to (in:%"PRId64" out:%"PRId64")\n", - s->first_pts, av_rescale_q(first_pts, AV_TIME_BASE_Q, - outlink->time_base)); - } else { - s->first_pts = buf->pts; - } + /* We haven't yet determined the pts of the first frame */ + if (s->next_pts == AV_NOPTS_VALUE) { + if (s->frames[0]->pts != AV_NOPTS_VALUE) { + s->next_pts = s->frames[0]->pts; + av_log(ctx, AV_LOG_VERBOSE, "Set first pts to %"PRId64"\n", s->next_pts); } else { av_log(ctx, AV_LOG_WARNING, "Discarding initial frame(s) with no " "timestamp.\n"); - av_frame_free(&buf); - s->drop++; + frame = shift_frame(ctx, s); + av_frame_free(&frame); + *again = 1; + return 0; } - return 0; } - /* now wait for the next timestamp */ - if (buf->pts == AV_NOPTS_VALUE || av_fifo_size(s->fifo) <= 0) { - return write_to_fifo(s->fifo, buf); - } + /* There are two conditions where we want to drop a frame: + * - If we have two buffered frames and the second frame is acceptable + * as the next output frame, then drop the first buffered frame. + * - If we have status (EOF) set, drop frames when we hit the + * status timestamp. */ + if ((s->frames_count == 2 && s->frames[1]->pts <= s->next_pts) || + (s->status && s->status_pts <= s->next_pts)) { + + frame = shift_frame(ctx, s); + av_frame_free(&frame); + *again = 1; + return 0; - /* number of output frames */ - delta = av_rescale_q_rnd(buf->pts - s->first_pts, inlink->time_base, - outlink->time_base, s->rounding) - s->frames_out ; + /* Output a copy of the first buffered frame */ + } else { + frame = av_frame_clone(s->frames[0]); + if (!frame) + return AVERROR(ENOMEM); + frame->pts = s->next_pts++; - if (delta < 1) { - /* drop everything buffered except the last */ - int drop = av_fifo_size(s->fifo)/sizeof(AVFrame*); + av_log(ctx, AV_LOG_DEBUG, "Writing frame with pts %"PRId64" to pts %"PRId64"\n", + s->frames[0]->pts, frame->pts); + s->cur_frame_out++; - av_log(ctx, AV_LOG_DEBUG, "Dropping %d frame(s).\n", drop); - s->drop += drop; + return ff_filter_frame(outlink, frame); + } +} - flush_fifo(s->fifo); - ret = write_to_fifo(s->fifo, buf); +/* Convert status_pts to outlink timebase */ +static void update_eof_pts(AVFilterContext *ctx, FPSContext *s, AVFilterLink *inlink, AVFilterLink *outlink, int64_t status_pts) +{ + int eof_rounding = (s->eof_action == EOF_ACTION_PASS) ? AV_ROUND_UP : s->rounding; + s->status_pts = av_rescale_q_rnd(status_pts, inlink->time_base, outlink->time_base, + eof_rounding | AV_ROUND_PASS_MINMAX); - return ret; - } + av_log(ctx, AV_LOG_DEBUG, "EOF is at pts %"PRId64"\n", s->status_pts); +} - /* can output >= 1 frames */ - for (i = 0; i < delta; i++) { - AVFrame *buf_out; - av_fifo_generic_read(s->fifo, &buf_out, sizeof(buf_out), NULL); +static int activate(AVFilterContext *ctx) +{ + FPSContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; - /* duplicate the frame if needed */ - if (!av_fifo_size(s->fifo) && i < delta - 1) { - AVFrame *dup = av_frame_clone(buf_out); + int ret; + int again = 0; + int64_t status_pts; - av_log(ctx, AV_LOG_DEBUG, "Duplicating frame.\n"); - if (dup) - ret = write_to_fifo(s->fifo, dup); - else - ret = AVERROR(ENOMEM); + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - if (ret < 0) { - av_frame_free(&buf_out); - av_frame_free(&buf); - return ret; - } + /* No buffered status: normal operation */ + if (!s->status) { - s->dup++; + /* Read available input frames if we have room */ + while (s->frames_count < 2 && ff_inlink_check_available_frame(inlink)) { + ret = read_frame(ctx, s, inlink, outlink); + if (ret < 0) + return ret; } - buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base, - outlink->time_base) + s->frames_out; - - if ((ret = ff_filter_frame(outlink, buf_out)) < 0) { - av_frame_free(&buf); - return ret; + /* We do not yet have enough frames to produce output */ + if (s->frames_count < 2) { + /* Check if we've hit EOF (or otherwise that an error status is set) */ + ret = ff_inlink_acknowledge_status(inlink, &s->status, &status_pts); + if (ret > 0) + update_eof_pts(ctx, s, inlink, outlink, status_pts); + + if (!ret) { + /* If someone wants us to output, we'd better ask for more input */ + FF_FILTER_FORWARD_WANTED(outlink, inlink); + return 0; + } } + } - s->frames_out++; + /* Buffered frames are available, so generate an output frame */ + if (s->frames_count > 0) { + ret = write_frame(ctx, s, outlink, &again); + /* Couldn't generate a frame, so schedule us to perform another step */ + if (again) + ff_filter_set_ready(ctx, 100); + return ret; } - flush_fifo(s->fifo); - ret = write_to_fifo(s->fifo, buf); + /* No frames left, so forward the status */ + if (s->status && s->frames_count == 0) { + ff_outlink_set_status(outlink, s->status, s->next_pts); + return 0; + } - return ret; + return FFERROR_NOT_READY; } static const AVFilterPad avfilter_vf_fps_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = filter_frame, }, { NULL } }; @@ -324,8 +338,7 @@ static const AVFilterPad avfilter_vf_fps_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, - .config_props = config_props + .config_props = config_props, }, { NULL } }; @@ -337,6 +350,7 @@ AVFilter ff_vf_fps = { .uninit = uninit, .priv_size = sizeof(FPSContext), .priv_class = &fps_class, + .activate = activate, .inputs = avfilter_vf_fps_inputs, .outputs = avfilter_vf_fps_outputs, }; From 2b2c8b22da9f9f0005b619a539023afbad1a1edd Mon Sep 17 00:00:00 2001 From: Calvin Walton Date: Thu, 22 Feb 2018 14:10:04 -0500 Subject: [PATCH 2072/2557] libavfilter/vf_fps: Minor cleanups Since the config_props function now references both the input and output links, rename the 'link' variable to 'outlink'. Fix up some mismatching indentation. Don't bother setting the width and height on the outlink; the filter framework does that for us. --- libavfilter/vf_fps.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c index cc350243a9bd1..9167a00a13ccb 100644 --- a/libavfilter/vf_fps.c +++ b/libavfilter/vf_fps.c @@ -147,16 +147,14 @@ static av_cold void uninit(AVFilterContext *ctx) "%d frames duplicated.\n", s->frames_in, s->frames_out, s->drop, s->dup); } -static int config_props(AVFilterLink* link) +static int config_props(AVFilterLink* outlink) { - AVFilterContext *ctx = link->src; - AVFilterLink *inlink = ctx->inputs[0]; - FPSContext *s = ctx->priv; + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; + FPSContext *s = ctx->priv; - link->time_base = av_inv_q(s->framerate); - link->frame_rate= s->framerate; - link->w = link->src->inputs[0]->w; - link->h = link->src->inputs[0]->h; + outlink->time_base = av_inv_q(s->framerate); + outlink->frame_rate = s->framerate; /* Calculate the input and output pts offsets for start_time */ if (s->start_time != DBL_MAX && s->start_time != AV_NOPTS_VALUE) { @@ -168,7 +166,7 @@ static int config_props(AVFilterLink* link) } s->in_pts_off = av_rescale_q_rnd(first_pts, AV_TIME_BASE_Q, inlink->time_base, s->rounding | AV_ROUND_PASS_MINMAX); - s->out_pts_off = av_rescale_q_rnd(first_pts, AV_TIME_BASE_Q, link->time_base, + s->out_pts_off = av_rescale_q_rnd(first_pts, AV_TIME_BASE_Q, outlink->time_base, s->rounding | AV_ROUND_PASS_MINMAX); s->next_pts = s->out_pts_off; av_log(ctx, AV_LOG_VERBOSE, "Set first pts to (in:%"PRId64" out:%"PRId64") from start time %f\n", From 9fe61b61074b013bc0a9289a207efce2107bfbcf Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Wed, 7 Mar 2018 00:36:21 +0100 Subject: [PATCH 2073/2557] lavfi/drawutils: Do not claim to support P016. Fixes fate on big-endian. --- libavfilter/drawutils.c | 2 +- tests/ref/fate/filter-pixfmts-pad | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index 77ab86b775454..17e26c764acc8 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -186,7 +186,7 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) return AVERROR(EINVAL); if (desc->flags & ~(AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PSEUDOPAL | AV_PIX_FMT_FLAG_ALPHA)) return AVERROR(ENOSYS); - if (format == AV_PIX_FMT_P010LE || format == AV_PIX_FMT_P010BE) + if (format == AV_PIX_FMT_P010LE || format == AV_PIX_FMT_P010BE || format == AV_PIX_FMT_P016LE || format == AV_PIX_FMT_P016BE) return AVERROR(ENOSYS); for (i = 0; i < desc->nb_components; i++) { c = &desc->comp[i]; diff --git a/tests/ref/fate/filter-pixfmts-pad b/tests/ref/fate/filter-pixfmts-pad index 097bd58c86cca..e777211cd9a0b 100644 --- a/tests/ref/fate/filter-pixfmts-pad +++ b/tests/ref/fate/filter-pixfmts-pad @@ -22,7 +22,6 @@ gray16le 468bda6155bdc7a7a20c34d6e599fd16 gray9le f8f3dfe31ca5fcba828285bceefdab9a nv12 381574979cb04be10c9168540310afad nv21 0fdeb2cdd56cf5a7147dc273456fa217 -p016le 536a3b4c3b47d005f9ab033370cc1c3b rgb0 78d500c8361ab6423a4826a00268c908 rgb24 17f9e2e0c609009acaf2175c42d4a2a5 rgba b157c90191463d34fb3ce77b36c96386 From dd7e63af93b2430b5d42b87a966160c66736342c Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Thu, 8 Mar 2018 11:47:04 +0100 Subject: [PATCH 2074/2557] configure: Restore original endianness test Previously the bit pattern for the endianness test was declared as a global, instead of a local, variable. This ensures that the pattern appears unchanged in the object file and is not optimized out. --- configure | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/configure b/configure index d59fc6fd1ae29..b91be3210284b 100755 --- a/configure +++ b/configure @@ -4211,7 +4211,10 @@ done check_cc pragma_deprecated "" '_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")' -require_cc "endian test" "" "unsigned int endian = 'B' << 24 | 'I' << 16 | 'G' << 8 | 'E'" +# The global variable ensures the bits appear unchanged in the object file. +test_cc < Date: Fri, 2 Feb 2018 20:50:13 -0600 Subject: [PATCH 2075/2557] lavc/videotoolbox: fix threaded decoding AVHWAccel.end_frame can run on a worker thread. The assumption of the frame threading code is that the worker thread will change the AVFrame image data, not the AVFrame fields. So the AVFrame fields are not synced back to the main thread. But this breaks videotoolbox due to its special requirements (everything else is fine). It actually wants to update AVFrame fields. The actual videotoolbox frame is now stored in the dummy AVBufferRef, so it mimics what happens in non-videotoolbox cases. (Changing the AVBufferRef contents is a bit like changing the image data.) The post_process callback copies that reference to the proper AVFrame field. Based on a patch by wm4. Signed-off-by: Aman Gupta --- libavcodec/h264dec.c | 3 -- libavcodec/videotoolbox.c | 68 +++++++++++++++++++++++++++++---------- libavcodec/vt_internal.h | 1 - 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 8c9c6d9f3bfb2..7494c7a8f2ced 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -838,9 +838,6 @@ static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp) AVFrame *src = srcp->f; int ret; - if (src->format == AV_PIX_FMT_VIDEOTOOLBOX && src->buf[0]->size == 1) - return AVERROR_INVALIDDATA; - ret = av_frame_ref(dst, src); if (ret < 0) return ret; diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index afec1edf3f6a7..f82c31c5df653 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -45,8 +45,10 @@ enum { kCMVideoCodecType_HEVC = 'hvc1' }; static void videotoolbox_buffer_release(void *opaque, uint8_t *data) { - CVPixelBufferRef cv_buffer = (CVImageBufferRef)data; + CVPixelBufferRef cv_buffer = *(CVPixelBufferRef *)data; CVPixelBufferRelease(cv_buffer); + + av_free(data); } static int videotoolbox_buffer_copy(VTContext *vtctx, @@ -69,19 +71,47 @@ static int videotoolbox_buffer_copy(VTContext *vtctx, return 0; } +static int videotoolbox_postproc_frame(void *avctx, AVFrame *frame) +{ + CVPixelBufferRef ref = *(CVPixelBufferRef *)frame->buf[0]->data; + + if (!ref) { + av_log(avctx, AV_LOG_ERROR, "No frame decoded?\n"); + av_frame_unref(frame); + return AVERROR_EXTERNAL; + } + + frame->data[3] = (uint8_t*)ref; + + return 0; +} + int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame) { + size_t size = sizeof(CVPixelBufferRef); + uint8_t *data = NULL; + AVBufferRef *buf = NULL; int ret = ff_attach_decode_data(frame); + FrameDecodeData *fdd; if (ret < 0) return ret; + data = av_mallocz(size); + if (!data) + return AVERROR(ENOMEM); + buf = av_buffer_create(data, size, videotoolbox_buffer_release, NULL, 0); + if (!buf) { + av_freep(&data); + return AVERROR(ENOMEM); + } + frame->buf[0] = buf; + + fdd = (FrameDecodeData*)frame->private_ref->data; + fdd->post_process = videotoolbox_postproc_frame; + frame->width = avctx->width; frame->height = avctx->height; frame->format = avctx->pix_fmt; - frame->buf[0] = av_buffer_alloc(1); - - if (!frame->buf[0]) - return AVERROR(ENOMEM); return 0; } @@ -285,20 +315,24 @@ CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx) return data; } -int ff_videotoolbox_buffer_create(VTContext *vtctx, AVFrame *frame) +static int videotoolbox_set_frame(AVCodecContext *avctx, AVFrame *frame) { - av_buffer_unref(&frame->buf[0]); - - frame->buf[0] = av_buffer_create((uint8_t*)vtctx->frame, - sizeof(vtctx->frame), - videotoolbox_buffer_release, - NULL, - AV_BUFFER_FLAG_READONLY); - if (!frame->buf[0]) { - return AVERROR(ENOMEM); + VTContext *vtctx = avctx->internal->hwaccel_priv_data; + if (!frame->buf[0] || frame->data[3]) { + av_log(avctx, AV_LOG_ERROR, "videotoolbox: invalid state\n"); + av_frame_unref(frame); + return AVERROR_EXTERNAL; + } + + CVPixelBufferRef *ref = (CVPixelBufferRef *)frame->buf[0]->data; + + if (*ref) { + av_log(avctx, AV_LOG_ERROR, "videotoolbox: frame already set?\n"); + av_frame_unref(frame); + return AVERROR_EXTERNAL; } - frame->data[3] = (uint8_t*)vtctx->frame; + *ref = vtctx->frame; vtctx->frame = NULL; return 0; @@ -406,7 +440,7 @@ static int videotoolbox_buffer_create(AVCodecContext *avctx, AVFrame *frame) AVHWFramesContext *cached_frames; int ret; - ret = ff_videotoolbox_buffer_create(vtctx, frame); + ret = videotoolbox_set_frame(avctx, frame); if (ret < 0) return ret; diff --git a/libavcodec/vt_internal.h b/libavcodec/vt_internal.h index 929fe423fcde5..fb64735b8cd35 100644 --- a/libavcodec/vt_internal.h +++ b/libavcodec/vt_internal.h @@ -46,7 +46,6 @@ typedef struct VTContext { int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame); int ff_videotoolbox_uninit(AVCodecContext *avctx); -int ff_videotoolbox_buffer_create(VTContext *vtctx, AVFrame *frame); int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size); From 00035a6b4a9fcb4a9756fd4a3a01a196575e0d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Martinez?= Date: Wed, 7 Mar 2018 13:26:36 +0100 Subject: [PATCH 2076/2557] avcodec/ffv1enc: remove warning about transparency Signed-off-by: Michael Niedermayer --- libavcodec/ffv1enc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index d71d952c6dbc1..2e999b0986b1f 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -685,9 +685,6 @@ FF_ENABLE_DEPRECATION_WARNINGS s->ac = AC_RANGE_CUSTOM_TAB; } } - if (s->transparency) { - av_log(avctx, AV_LOG_WARNING, "Storing alpha plane, this will require a recent FFV1 decoder to playback!\n"); - } #if FF_API_PRIVATE_OPT FF_DISABLE_DEPRECATION_WARNINGS if (avctx->context_model) From 3386be16d5131961f73c4227e9ddde4e3a5e39e3 Mon Sep 17 00:00:00 2001 From: Xiaohan Wang Date: Tue, 13 Feb 2018 14:45:14 -0800 Subject: [PATCH 2077/2557] ffmpeg: Fix stts_data memory allocation In this loop, |i| is the "index". And the memory allocated should be at least the current "count", which is |i + 1|. BUG=801821 Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 7002a82787984..ab03a99dc3771 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2859,7 +2859,7 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) for (i = 0; i < entries && !pb->eof_reached; i++) { int sample_duration; unsigned int sample_count; - unsigned min_entries = FFMIN(FFMAX(i, 1024 * 1024), entries); + unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries); MOVStts *stts_data = av_fast_realloc(sc->stts_data, &alloc_size, min_entries * sizeof(*sc->stts_data)); if (!stts_data) { From c4cee261296c917c605ead5edbfb452f2aa86d92 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 9 Mar 2018 11:23:23 -0300 Subject: [PATCH 2078/2557] avformat/mov: print the projection type when reporting it as unsupported Reviewed-by: Derek Buitenhuis Signed-off-by: James Almer --- libavformat/mov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index ab03a99dc3771..39c2179dcd569 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -5454,7 +5454,7 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) projection = AV_SPHERICAL_EQUIRECTANGULAR; break; default: - av_log(c->fc, AV_LOG_ERROR, "Unknown projection type\n"); + av_log(c->fc, AV_LOG_ERROR, "Unknown projection type: %s\n", av_fourcc2str(tag)); return 0; } From d168e78effd170377ec57f67bca05c9f0de91bca Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 9 Mar 2018 13:00:55 -0300 Subject: [PATCH 2079/2557] avcodec/extract_extradata: zero initalize the padding bytes in all allocated buffers Reviewed-by: Derek Buitenhuis Signed-off-by: James Almer --- libavcodec/extract_extradata_bsf.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c index d40907a675c55..fbfd12aeef51c 100644 --- a/libavcodec/extract_extradata_bsf.c +++ b/libavcodec/extract_extradata_bsf.c @@ -114,6 +114,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, ret = AVERROR(ENOMEM); goto fail; } + memset(extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); *data = extradata; *size = extradata_size; @@ -137,6 +138,8 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, pkt->buf = filtered_buf; pkt->data = filtered_buf->data; pkt->size = filtered_data - filtered_buf->data; + + memset(pkt->data + pkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE); } } @@ -169,6 +172,7 @@ static int extract_extradata_vc1(AVBSFContext *ctx, AVPacket *pkt, return AVERROR(ENOMEM); memcpy(*data, pkt->data, extradata_size); + memset(*data + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); *size = extradata_size; if (s->remove) { @@ -199,6 +203,7 @@ static int extract_extradata_mpeg12(AVBSFContext *ctx, AVPacket *pkt, return AVERROR(ENOMEM); memcpy(*data, pkt->data, *size); + memset(*data + *size, 0, AV_INPUT_BUFFER_PADDING_SIZE); if (s->remove) { pkt->data += *size; @@ -228,6 +233,7 @@ static int extract_extradata_mpeg4(AVBSFContext *ctx, AVPacket *pkt, return AVERROR(ENOMEM); memcpy(*data, pkt->data, *size); + memset(*data + *size, 0, AV_INPUT_BUFFER_PADDING_SIZE); if (s->remove) { pkt->data += *size; From 3aaf97e7737cab5d5476f70fd8405d5d330cb215 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 18 Feb 2018 01:12:01 +0100 Subject: [PATCH 2080/2557] avformat/mxfdec: fix opAtom audio demuxing Consider edit rate when determining edit_units_per_packet and also make sure that checks are done in edit rate time base and not in stream time base. Fixes some errors reported with the sample in ticket #5863. Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index e0a4b5bd11e6a..d4291f5dc79b3 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -275,7 +275,7 @@ typedef struct MXFContext { int parsing_backward; int64_t last_forward_tell; int last_forward_partition; - int current_edit_unit; + int64_t current_edit_unit; int nb_index_tables; MXFIndexTable *index_tables; int edit_units_per_packet; ///< how many edit units to read at a time (PCM, OPAtom) @@ -2786,6 +2786,7 @@ static AVStream* mxf_get_opatom_stream(MXFContext *mxf) static void mxf_handle_small_eubc(AVFormatContext *s) { MXFContext *mxf = s->priv_data; + MXFTrack *track; /* assuming non-OPAtom == frame wrapped * no sane writer would wrap 2 byte PCM packets with 20 byte headers.. */ @@ -2805,7 +2806,8 @@ static void mxf_handle_small_eubc(AVFormatContext *s) /* TODO: We could compute this from the ratio between the audio * and video edit rates for 48 kHz NTSC we could use the * 1802-1802-1802-1802-1801 pattern. */ - mxf->edit_units_per_packet = 1920; + track = st->priv_data; + mxf->edit_units_per_packet = FFMAX(1, track->edit_rate.num / track->edit_rate.den / 25); } /** @@ -3263,7 +3265,7 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) * truncate the packet since it's probably very large (>2 GiB is common) */ avpriv_request_sample(s, "OPAtom misinterpreted as OP1a? " - "KLV for edit unit %i extending into " + "KLV for edit unit %"PRId64" extending into " "next edit unit", mxf->current_edit_unit); klv.length = next_ofs - avio_tell(s->pb); @@ -3307,6 +3309,7 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) int64_t ret64, pos, next_pos; AVStream *st; MXFIndexTable *t; + MXFTrack *track; int edit_units; if (mxf->op != OPAtom) @@ -3317,14 +3320,16 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) if (!st) return AVERROR_EOF; + track = st->priv_data; + /* OPAtom - clip wrapped demuxing */ /* NOTE: mxf_read_header() makes sure nb_index_tables > 0 for OPAtom */ t = &mxf->index_tables[0]; - if (mxf->current_edit_unit >= st->duration) + if (mxf->current_edit_unit >= track->original_duration) return AVERROR_EOF; - edit_units = FFMIN(mxf->edit_units_per_packet, st->duration - mxf->current_edit_unit); + edit_units = FFMIN(mxf->edit_units_per_packet, track->original_duration - mxf->current_edit_unit); if ((ret = mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit, NULL, &pos, 1)) < 0) return ret; From 90756e67a0a1de762d27c2fe01a30ac8434a3631 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 19 Feb 2018 00:43:05 +0100 Subject: [PATCH 2081/2557] avformat/mxfdec: use binary search in mxf_absolute_bodysid_offset Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index d4291f5dc79b3..70091e0dc9f21 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1347,24 +1347,30 @@ static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segment */ static int mxf_absolute_bodysid_offset(MXFContext *mxf, int body_sid, int64_t offset, int64_t *offset_out) { - int x; MXFPartition *last_p = NULL; + int a, b, m, m0; if (offset < 0) return AVERROR(EINVAL); - for (x = 0; x < mxf->partitions_count; x++) { - MXFPartition *p = &mxf->partitions[x]; + a = -1; + b = mxf->partitions_count; - if (p->body_sid != body_sid) - continue; + while (b - a > 1) { + m0 = m = (a + b) >> 1; - if (p->body_offset > offset) - break; + while (m < b && mxf->partitions[m].body_sid != body_sid) + m++; - last_p = p; + if (m < b && mxf->partitions[m].body_offset <= offset) + a = m; + else + b = m0; } + if (a >= 0) + last_p = &mxf->partitions[a]; + if (last_p && (!last_p->essence_length || last_p->essence_length > (offset - last_p->body_offset))) { *offset_out = last_p->essence_offset + (offset - last_p->body_offset); return 0; From cf5ffe0183947112ac50be81942d8be610aa987c Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Fri, 9 Mar 2018 00:46:06 +0100 Subject: [PATCH 2082/2557] avformat/mxfdec: do not allow more partitions than INT_MAX/2 Some math (e.g: partition binary search) overflows if we have that many parititions. Signed-off-by: Marton Balint --- libavformat/mxfdec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 70091e0dc9f21..7a42555562190 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -565,6 +565,9 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size uint64_t footer_partition; uint32_t nb_essence_containers; + if (mxf->partitions_count >= INT_MAX / 2) + return AVERROR_INVALIDDATA; + tmp_part = av_realloc_array(mxf->partitions, mxf->partitions_count + 1, sizeof(*mxf->partitions)); if (!tmp_part) return AVERROR(ENOMEM); From 8d37dd6ed3bc3de6b6aa2bdc46f87e842ee19054 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 6 Mar 2018 00:45:09 +0100 Subject: [PATCH 2083/2557] avutil/parseutils: only accept full us duration, do not accept mss duration Accepting 'u' suffix for a time specification is neither intuitive nor consistent (now that we don't accept m). Also there was a bug in the code accepting an extra 's' even after 'ms'. Signed-off-by: Marton Balint --- libavutil/parseutils.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c index 95274f564f2ca..924c49d52cf65 100644 --- a/libavutil/parseutils.c +++ b/libavutil/parseutils.c @@ -693,12 +693,11 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) suffix = 1000; microseconds /= 1000; q += 2; - } else if (*q == 'u') { + } else if (q[0] == 'u' && q[1] == 's') { suffix = 1; microseconds = 0; - q++; - } - if (*q == 's') + q += 2; + } else if (*q == 's') q++; } else { int is_utc = *q == 'Z' || *q == 'z'; From 02ecda4aba69670ca744ccc640391b7621f01fb0 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 8 Mar 2018 17:28:36 +0100 Subject: [PATCH 2084/2557] avformat/oggparsetheora: Do not adjust AV_NOPTS_VALUE Fixes: Chromium bug 795653 Fixes: signed integer overflow: 9223372036854775807 + 1 cannot be represented in type 'long' Reported-by: Matt Wolenetz Reviewed-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavformat/oggparsetheora.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/oggparsetheora.c b/libavformat/oggparsetheora.c index b14f9f0669c1a..b0c0edc7a545f 100644 --- a/libavformat/oggparsetheora.c +++ b/libavformat/oggparsetheora.c @@ -181,6 +181,7 @@ static int theora_packet(AVFormatContext *s, int idx) if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) { int seg; + int64_t pts; duration = 1; for (seg = os->segp; seg < os->nsegs; seg++) { @@ -188,7 +189,10 @@ static int theora_packet(AVFormatContext *s, int idx) duration ++; } - os->lastpts = os->lastdts = theora_gptopts(s, idx, os->granule, NULL) - duration; + pts = theora_gptopts(s, idx, os->granule, NULL); + if (pts != AV_NOPTS_VALUE) + pts -= duration; + os->lastpts = os->lastdts = pts; if(s->streams[idx]->start_time == AV_NOPTS_VALUE) { s->streams[idx]->start_time = os->lastpts; if (s->streams[idx]->duration > 0) From 06e092e7819b9437da32925200e7c369f93d82e7 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 8 Mar 2018 22:40:50 +0100 Subject: [PATCH 2085/2557] avformat/avidec: Fix integer overflow in cum_len check Fixes: signed integer overflow: 3775922176 * 4278190080 cannot be represented in type 'long' Fixes: Chromium bug 791237 Reported-by: Matt Wolenetz Reviewed-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavformat/avidec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/avidec.c b/libavformat/avidec.c index 3ff515d492f96..bafe1dc8da0c4 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -670,7 +670,7 @@ FF_ENABLE_DEPRECATION_WARNINGS st->start_time = 0; avio_rl32(pb); /* buffer size */ avio_rl32(pb); /* quality */ - if (ast->cum_len*ast->scale/ast->rate > 3600) { + if (ast->cum_len > 3600LL * ast->rate / ast->scale) { av_log(s, AV_LOG_ERROR, "crazy start time, iam scared, giving up\n"); ast->cum_len = 0; } From 010b7b30b721b90993e05e9ee6338e88bb8debb3 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 8 Mar 2018 23:14:04 +0100 Subject: [PATCH 2086/2557] avformat/oggparseogm: Fix undefined shift in ogm_packet() Fixes: shift exponent 48 is too large for 32-bit type 'int' Fixes: Chromium bug 786793 Reported-by: Matt Wolenetz Reviewed-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavformat/oggparseogm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/oggparseogm.c b/libavformat/oggparseogm.c index ca6b62669d5a5..4b4edf26ca36f 100644 --- a/libavformat/oggparseogm.c +++ b/libavformat/oggparseogm.c @@ -180,7 +180,7 @@ ogm_packet(AVFormatContext *s, int idx) os->psize -= lb + 1; while (lb--) - os->pduration += p[lb+1] << (lb*8); + os->pduration += (uint64_t)p[lb+1] << (lb*8); return 0; } From 3e7c847aaf5a298b62afae12b4ecfb8e12385998 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 9 Mar 2018 01:05:20 +0100 Subject: [PATCH 2087/2557] avformat/oggparseogm: Check lb against psize No testcase, this was found during code review Found-by: Matt Wolenetz Reviewed-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavformat/oggparseogm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/oggparseogm.c b/libavformat/oggparseogm.c index 4b4edf26ca36f..a07453760b710 100644 --- a/libavformat/oggparseogm.c +++ b/libavformat/oggparseogm.c @@ -176,6 +176,9 @@ ogm_packet(AVFormatContext *s, int idx) os->pflags |= AV_PKT_FLAG_KEY; lb = ((*p & 2) << 1) | ((*p >> 6) & 3); + if (os->psize < lb + 1) + return AVERROR_INVALIDDATA; + os->pstart += lb + 1; os->psize -= lb + 1; From f655ddfb47e8484b205b14c7f871c643ad24d701 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 8 Mar 2018 17:28:36 +0100 Subject: [PATCH 2088/2557] avformat/oggparsedaala: Do not adjust AV_NOPTS_VALUE Fixes: potential signed integer overflow Signed-off-by: Michael Niedermayer --- libavformat/oggparsedaala.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/oggparsedaala.c b/libavformat/oggparsedaala.c index a373b41b4cac4..e944470aca38c 100644 --- a/libavformat/oggparsedaala.c +++ b/libavformat/oggparsedaala.c @@ -218,6 +218,7 @@ static int daala_packet(AVFormatContext *s, int idx) int seg, duration = 1; struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; + int64_t pts; /* * first packet handling: here we parse the duration of each packet in the @@ -230,7 +231,10 @@ static int daala_packet(AVFormatContext *s, int idx) if (os->segments[seg] < 255) duration++; - os->lastpts = os->lastdts = daala_gptopts(s, idx, os->granule, NULL) - duration; + pts = daala_gptopts(s, idx, os->granule, NULL); + if (pts != AV_NOPTS_VALUE) + pts -= duration; + os->lastpts = os->lastdts = pts; if(s->streams[idx]->start_time == AV_NOPTS_VALUE) { s->streams[idx]->start_time = os->lastpts; if (s->streams[idx]->duration != AV_NOPTS_VALUE) From a6cba062051f345e8ebfdff34aba071ed73d923f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 10 Mar 2018 01:40:36 +0100 Subject: [PATCH 2089/2557] avformat/img2dec: fix infinite loop Fixes: kira-poc Found-by: Kira Change suggested by Kira Signed-off-by: Michael Niedermayer --- libavformat/img2dec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c index 62db0d92cf3e2..f3f52c83b355a 100644 --- a/libavformat/img2dec.c +++ b/libavformat/img2dec.c @@ -878,10 +878,14 @@ static int svg_probe(AVProbeData *p) { const uint8_t *b = p->buf; const uint8_t *end = p->buf + p->buf_size; + if (memcmp(p->buf, "= end - 4) return 0; if (!memcmp(b, " Date: Sat, 10 Mar 2018 01:15:05 -0300 Subject: [PATCH 2090/2557] avutil: add missing version bump for AV_CRC_8_EBU Signed-off-by: James Almer --- doc/APIchanges | 3 +++ libavutil/version.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 297a5a20618ba..395ac902dd6cc 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-03-07 - xxxxxxx - lavu 56.9.100 - crc.h + Add AV_CRC_8_EBU crc variant. + 2018-03-xx - xxxxxxx - lavc 58.14.100 - mediacodec.h Change the default behavior of avcodec_flush() on mediacodec video decoders. To restore the previous behavior, use the new diff --git a/libavutil/version.h b/libavutil/version.h index d7398c41c592c..0c032c8553204 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 8 +#define LIBAVUTIL_VERSION_MINOR 9 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From ea6973a5733ce1a6b6359357fd5c1722c2774dce Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Tue, 27 Feb 2018 23:12:33 +0000 Subject: [PATCH 2091/2557] vc2enc: replace quantization LUT with a smaller division LUT This commit replaces the huge and impractical LUT which converted coeffs and a quantizer to bits to encode and instead uses a standard multiplication and a shift to replace the division and then codes the values using the regular golomb coding functions. Signed-off-by: Rostislav Pehlivanov --- libavcodec/vc2enc.c | 118 ++++++++++++-------------------------------- 1 file changed, 31 insertions(+), 87 deletions(-) diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c index b7adcd3d36d4c..2e480ba8d0feb 100644 --- a/libavcodec/vc2enc.c +++ b/libavcodec/vc2enc.c @@ -29,10 +29,6 @@ #include "vc2enc_dwt.h" #include "diractab.h" -/* Total range is -COEF_LUT_TAB to +COEFF_LUT_TAB, but total tab size is half - * (COEF_LUT_TAB*DIRAC_MAX_QUANT_INDEX), as the sign is appended during encoding */ -#define COEF_LUT_TAB 2048 - /* The limited size resolution of each slice forces us to do this */ #define SSIZE_ROUND(b) (FFALIGN((b), s->size_scaler) + 4 + s->prefix_bytes) @@ -152,9 +148,8 @@ typedef struct VC2EncContext { uint8_t quant[MAX_DWT_LEVELS][4]; int custom_quant_matrix; - /* Coefficient LUT */ - uint32_t *coef_lut_val; - uint8_t *coef_lut_len; + /* Division LUT */ + uint32_t qmagic_lut[116][2]; int num_x; /* #slices horizontally */ int num_y; /* #slices vertically */ @@ -229,37 +224,6 @@ static av_always_inline int count_vc2_ue_uint(uint32_t val) return ff_log2(topbit)*2 + 1; } -static av_always_inline void get_vc2_ue_uint(int val, uint8_t *nbits, - uint32_t *eval) -{ - int i; - int pbits = 0, bits = 0, topbit = 1, maxval = 1; - - if (!val++) { - *nbits = 1; - *eval = 1; - return; - } - - while (val > maxval) { - topbit <<= 1; - maxval <<= 1; - maxval |= 1; - } - - bits = ff_log2(topbit); - - for (i = 0; i < bits; i++) { - topbit >>= 1; - pbits <<= 2; - if (val & topbit) - pbits |= 0x1; - } - - *nbits = bits*2 + 1; - *eval = (pbits << 1) | 1; -} - /* VC-2 10.4 - parse_info() */ static void encode_parse_info(VC2EncContext *s, enum DiracParseCodes pcode) { @@ -557,7 +521,7 @@ static void encode_picture_start(VC2EncContext *s) encode_wavelet_transform(s); } -#define QUANT(c, qf) (((c) << 2)/(qf)) +#define QUANT(c, mul, add, shift) (((mul) * (c) + (add)) >> (shift)) /* VC-2 13.5.5.2 - slice_band() */ static void encode_subband(VC2EncContext *s, PutBitContext *pb, int sx, int sy, @@ -570,24 +534,17 @@ static void encode_subband(VC2EncContext *s, PutBitContext *pb, int sx, int sy, const int top = b->height * (sy+0) / s->num_y; const int bottom = b->height * (sy+1) / s->num_y; - const int qfactor = ff_dirac_qscale_tab[quant]; - const uint8_t *len_lut = &s->coef_lut_len[quant*COEF_LUT_TAB]; - const uint32_t *val_lut = &s->coef_lut_val[quant*COEF_LUT_TAB]; - dwtcoef *coeff = b->buf + top * b->stride; + const uint64_t q_m = ((uint64_t)(s->qmagic_lut[quant][0])) << 2; + const uint64_t q_a = s->qmagic_lut[quant][1]; + const int q_s = av_log2(ff_dirac_qscale_tab[quant]) + 32; for (y = top; y < bottom; y++) { for (x = left; x < right; x++) { - const int neg = coeff[x] < 0; - uint32_t c_abs = FFABS(coeff[x]); - if (c_abs < COEF_LUT_TAB) { - put_bits(pb, len_lut[c_abs], val_lut[c_abs] | neg); - } else { - c_abs = QUANT(c_abs, qfactor); - put_vc2_ue_uint(pb, c_abs); - if (c_abs) - put_bits(pb, 1, neg); - } + uint32_t c_abs = QUANT(FFABS(coeff[x]), q_m, q_a, q_s); + put_vc2_ue_uint(pb, c_abs); + if (c_abs) + put_bits(pb, 1, coeff[x] < 0); } coeff += b->stride; } @@ -619,8 +576,9 @@ static int count_hq_slice(SliceArgs *slice, int quant_idx) SubBand *b = &s->plane[p].band[level][orientation]; const int q_idx = quants[level][orientation]; - const uint8_t *len_lut = &s->coef_lut_len[q_idx*COEF_LUT_TAB]; - const int qfactor = ff_dirac_qscale_tab[q_idx]; + const uint64_t q_m = ((uint64_t)s->qmagic_lut[q_idx][0]) << 2; + const uint64_t q_a = s->qmagic_lut[q_idx][1]; + const int q_s = av_log2(ff_dirac_qscale_tab[q_idx]) + 32; const int left = b->width * slice->x / s->num_x; const int right = b->width *(slice->x+1) / s->num_x; @@ -631,14 +589,9 @@ static int count_hq_slice(SliceArgs *slice, int quant_idx) for (y = top; y < bottom; y++) { for (x = left; x < right; x++) { - uint32_t c_abs = FFABS(buf[x]); - if (c_abs < COEF_LUT_TAB) { - bits += len_lut[c_abs]; - } else { - c_abs = QUANT(c_abs, qfactor); - bits += count_vc2_ue_uint(c_abs); - bits += !!c_abs; - } + uint32_t c_abs = QUANT(FFABS(buf[x]), q_m, q_a, q_s); + bits += count_vc2_ue_uint(c_abs); + bits += !!c_abs; } buf += b->stride; } @@ -1059,8 +1012,6 @@ static av_cold int vc2_encode_end(AVCodecContext *avctx) } av_freep(&s->slice_args); - av_freep(&s->coef_lut_len); - av_freep(&s->coef_lut_val); return 0; } @@ -1069,7 +1020,7 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx) { Plane *p; SubBand *b; - int i, j, level, o, shift, ret; + int i, level, o, shift, ret; const AVPixFmtDescriptor *fmt = av_pix_fmt_desc_get(avctx->pix_fmt); const int depth = fmt->comp[0].depth; VC2EncContext *s = avctx->priv_data; @@ -1211,27 +1162,20 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx) if (!s->slice_args) goto alloc_fail; - /* Lookup tables */ - s->coef_lut_len = av_malloc(COEF_LUT_TAB*(s->q_ceil+1)*sizeof(*s->coef_lut_len)); - if (!s->coef_lut_len) - goto alloc_fail; - - s->coef_lut_val = av_malloc(COEF_LUT_TAB*(s->q_ceil+1)*sizeof(*s->coef_lut_val)); - if (!s->coef_lut_val) - goto alloc_fail; - - for (i = 0; i < s->q_ceil; i++) { - uint8_t *len_lut = &s->coef_lut_len[i*COEF_LUT_TAB]; - uint32_t *val_lut = &s->coef_lut_val[i*COEF_LUT_TAB]; - for (j = 0; j < COEF_LUT_TAB; j++) { - get_vc2_ue_uint(QUANT(j, ff_dirac_qscale_tab[i]), - &len_lut[j], &val_lut[j]); - if (len_lut[j] != 1) { - len_lut[j] += 1; - val_lut[j] <<= 1; - } else { - val_lut[j] = 1; - } + for (i = 0; i < 116; i++) { + const uint32_t qf = ff_dirac_qscale_tab[i]; + const int m = av_log2(qf); + const uint32_t t = (1UL << (m + 32)) / qf; + const uint32_t r = (t*qf + qf) & ((1UL << 32) - 1); + if (!(qf & (qf - 1))) { + s->qmagic_lut[i][0] = 0xFFFFFFFF; + s->qmagic_lut[i][1] = 0xFFFFFFFF; + } else if (r <= 1UL << m) { + s->qmagic_lut[i][0] = t + 1; + s->qmagic_lut[i][1] = 0; + } else { + s->qmagic_lut[i][0] = t; + s->qmagic_lut[i][1] = t; } } From b6fc09cdb4c4e5e4974ca35159f459174b9a9be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Martinez?= Date: Wed, 7 Mar 2018 11:19:03 +0100 Subject: [PATCH 2092/2557] avcodec/ffv1: support of more pix_fmt Without direct support of such pix_fmt, content is padded to 16-bit and it is not possible to know that the source file was with a smaller bit depth so framemd5 is different Signed-off-by: Michael Niedermayer --- libavcodec/ffv1dec.c | 14 +++++++++++++- libavcodec/ffv1enc.c | 13 ++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index 3d2ee2569faa4..b4a183c5b7a9d 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -591,7 +591,10 @@ static int read_header(FFV1Context *f) if (!f->transparency && !f->chroma_planes) { if (f->avctx->bits_per_raw_sample <= 8) f->avctx->pix_fmt = AV_PIX_FMT_GRAY8; - else if (f->avctx->bits_per_raw_sample == 10) { + else if (f->avctx->bits_per_raw_sample == 9) { + f->packed_at_lsb = 1; + f->avctx->pix_fmt = AV_PIX_FMT_GRAY9; + } else if (f->avctx->bits_per_raw_sample == 10) { f->packed_at_lsb = 1; f->avctx->pix_fmt = AV_PIX_FMT_GRAY10; } else if (f->avctx->bits_per_raw_sample == 12) { @@ -642,6 +645,7 @@ static int read_header(FFV1Context *f) f->packed_at_lsb = 1; switch(16 * f->chroma_h_shift + f->chroma_v_shift) { case 0x00: f->avctx->pix_fmt = AV_PIX_FMT_YUV444P10; break; + case 0x01: f->avctx->pix_fmt = AV_PIX_FMT_YUV440P10; break; case 0x10: f->avctx->pix_fmt = AV_PIX_FMT_YUV422P10; break; case 0x11: f->avctx->pix_fmt = AV_PIX_FMT_YUV420P10; break; } @@ -656,9 +660,17 @@ static int read_header(FFV1Context *f) f->packed_at_lsb = 1; switch(16 * f->chroma_h_shift + f->chroma_v_shift) { case 0x00: f->avctx->pix_fmt = AV_PIX_FMT_YUV444P12; break; + case 0x01: f->avctx->pix_fmt = AV_PIX_FMT_YUV440P12; break; case 0x10: f->avctx->pix_fmt = AV_PIX_FMT_YUV422P12; break; case 0x11: f->avctx->pix_fmt = AV_PIX_FMT_YUV420P12; break; } + } else if (f->avctx->bits_per_raw_sample == 14 && !f->transparency) { + f->packed_at_lsb = 1; + switch(16 * f->chroma_h_shift + f->chroma_v_shift) { + case 0x00: f->avctx->pix_fmt = AV_PIX_FMT_YUV444P14; break; + case 0x10: f->avctx->pix_fmt = AV_PIX_FMT_YUV422P14; break; + case 0x11: f->avctx->pix_fmt = AV_PIX_FMT_YUV420P14; break; + } } else if (f->avctx->bits_per_raw_sample == 16 && !f->transparency){ f->packed_at_lsb = 1; switch(16 * f->chroma_h_shift + f->chroma_v_shift) { diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index 2e999b0986b1f..dd4d7429f5484 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -558,6 +558,7 @@ FF_ENABLE_DEPRECATION_WARNINGS s->plane_count = 3; switch(avctx->pix_fmt) { + case AV_PIX_FMT_GRAY9: case AV_PIX_FMT_YUV444P9: case AV_PIX_FMT_YUV422P9: case AV_PIX_FMT_YUV420P9: @@ -568,6 +569,7 @@ FF_ENABLE_DEPRECATION_WARNINGS s->bits_per_raw_sample = 9; case AV_PIX_FMT_GRAY10: case AV_PIX_FMT_YUV444P10: + case AV_PIX_FMT_YUV440P10: case AV_PIX_FMT_YUV420P10: case AV_PIX_FMT_YUV422P10: case AV_PIX_FMT_YUVA444P10: @@ -577,11 +579,17 @@ FF_ENABLE_DEPRECATION_WARNINGS s->bits_per_raw_sample = 10; case AV_PIX_FMT_GRAY12: case AV_PIX_FMT_YUV444P12: + case AV_PIX_FMT_YUV440P12: case AV_PIX_FMT_YUV420P12: case AV_PIX_FMT_YUV422P12: - s->packed_at_lsb = 1; if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample) s->bits_per_raw_sample = 12; + case AV_PIX_FMT_YUV444P14: + case AV_PIX_FMT_YUV420P14: + case AV_PIX_FMT_YUV422P14: + if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample) + s->bits_per_raw_sample = 14; + s->packed_at_lsb = 1; case AV_PIX_FMT_GRAY16: case AV_PIX_FMT_YUV444P16: case AV_PIX_FMT_YUV422P16: @@ -1330,6 +1338,9 @@ AVCodec ff_ffv1_encoder = { AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GBRP16, AV_PIX_FMT_RGB48, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_RGBA64, + AV_PIX_FMT_GRAY9, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV440P12, AV_PIX_FMT_NONE }, From 43205df645bc10bc780c646ca0d652b574535f06 Mon Sep 17 00:00:00 2001 From: Sasi Inguva Date: Fri, 9 Mar 2018 13:30:21 -0800 Subject: [PATCH 2093/2557] lavf/mov.c: Use the correct offset to shift timestamp when seeking. Fixes seek for files with empty edits and files with negative ctts (dts_shift > 0). Added fate samples and tests. Signed-off-by: Sasi Inguva Signed-off-by: Michael Niedermayer --- libavformat/isom.h | 1 + libavformat/mov.c | 27 +++-- tests/fate/seek.mak | 6 + tests/ref/seek/empty-edit-mp4 | 134 +++++++++++++++++++++++ tests/ref/seek/test-iibbibb-mp4 | 122 +++++++++++++++++++++ tests/ref/seek/test-iibbibb-neg-ctts-mp4 | 122 +++++++++++++++++++++ 6 files changed, 401 insertions(+), 11 deletions(-) create mode 100644 tests/ref/seek/empty-edit-mp4 create mode 100644 tests/ref/seek/test-iibbibb-mp4 create mode 100644 tests/ref/seek/test-iibbibb-neg-ctts-mp4 diff --git a/libavformat/isom.h b/libavformat/isom.h index 65676fb0f55f7..4da34142f0669 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -168,6 +168,7 @@ typedef struct MOVStreamContext { int *keyframes; int time_scale; int64_t time_offset; ///< time offset of the edit list entries + int64_t min_corrected_pts; ///< minimum Composition time shown by the edits excluding empty edits. int current_sample; int64_t current_index; MOVIndexRange* index_ranges; diff --git a/libavformat/mov.c b/libavformat/mov.c index 39c2179dcd569..51228f5df2095 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3378,7 +3378,6 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) int64_t edit_list_start_ctts_sample = 0; int64_t curr_cts; int64_t curr_ctts = 0; - int64_t min_corrected_pts = -1; int64_t empty_edits_sum_duration = 0; int64_t edit_list_index = 0; int64_t index; @@ -3419,6 +3418,9 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) msc->ctts_sample = 0; msc->ctts_allocated_size = 0; + // Reinitialize min_corrected_pts so that it can be computed again. + msc->min_corrected_pts = -1; + // If the dts_shift is positive (in case of negative ctts values in mov), // then negate the DTS by dts_shift if (msc->dts_shift > 0) { @@ -3563,10 +3565,10 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) } } } else { - if (min_corrected_pts < 0) { - min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift; + if (msc->min_corrected_pts < 0) { + msc->min_corrected_pts = edit_list_dts_counter + curr_ctts + msc->dts_shift; } else { - min_corrected_pts = FFMIN(min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift); + msc->min_corrected_pts = FFMIN(msc->min_corrected_pts, edit_list_dts_counter + curr_ctts + msc->dts_shift); } if (edit_list_start_encountered == 0) { edit_list_start_encountered = 1; @@ -3625,16 +3627,16 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) } } } - // If there are empty edits, then min_corrected_pts might be positive intentionally. So we subtract the - // sum duration of emtpy edits here. - min_corrected_pts -= empty_edits_sum_duration; + // If there are empty edits, then msc->min_corrected_pts might be positive + // intentionally. So we subtract the sum duration of emtpy edits here. + msc->min_corrected_pts -= empty_edits_sum_duration; // If the minimum pts turns out to be greater than zero after fixing the index, then we subtract the // dts by that amount to make the first pts zero. - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && min_corrected_pts > 0) { - av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", min_corrected_pts); + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && msc->min_corrected_pts > 0) { + av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts); for (i = 0; i < st->nb_index_entries; ++i) { - st->index_entries[i].timestamp -= min_corrected_pts; + st->index_entries[i].timestamp -= msc->min_corrected_pts; } } @@ -3697,6 +3699,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st) if (empty_duration) empty_duration = av_rescale(empty_duration, sc->time_scale, mov->time_scale); sc->time_offset = start_time - empty_duration; + sc->min_corrected_pts = start_time; if (!mov->advanced_editlist) current_dts = -sc->time_offset; } @@ -7158,7 +7161,9 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int sample, time_sample, ret; unsigned int i; - timestamp -= sc->time_offset; + // Here we consider timestamp to be PTS, hence try to offset it so that we + // can search over the DTS timeline. + timestamp -= (sc->min_corrected_pts + sc->dts_shift); ret = mov_seek_fragment(s, st, timestamp); if (ret < 0) diff --git a/tests/fate/seek.mak b/tests/fate/seek.mak index 751873baa4ede..6a9f843d828db 100644 --- a/tests/fate/seek.mak +++ b/tests/fate/seek.mak @@ -251,9 +251,15 @@ FATE_SEEK_EXTRA-$(CONFIG_MP3_DEMUXER) += fate-seek-extra-mp3 FATE_SEEK_EXTRA-$(call ALLYES, CACHE_PROTOCOL PIPE_PROTOCOL MP3_DEMUXER) += fate-seek-cache-pipe FATE_SEEK_EXTRA-$(CONFIG_MATROSKA_DEMUXER) += fate-seek-mkv-codec-delay FATE_SEEK_EXTRA-$(CONFIG_MOV_DEMUXER) += fate-seek-extra-mp4 +FATE_SEEK_EXTRA-$(CONFIG_MOV_DEMUXER) += fate-seek-empty-edit-mp4 +FATE_SEEK_EXTRA-$(CONFIG_MOV_DEMUXER) += fate-seek-test-iibbibb-mp4 +FATE_SEEK_EXTRA-$(CONFIG_MOV_DEMUXER) += fate-seek-test-iibbibb-neg-ctts-mp4 fate-seek-extra-mp3: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/gapless/gapless.mp3 -fastseek 1 fate-seek-extra-mp4: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/mov/buck480p30_na.mp4 -duration 180 -frames 4 +fate-seek-empty-edit-mp4: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/mov/empty_edit_5s.mp4 -duration 15 -frames 4 +fate-seek-test-iibbibb-mp4: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/mov/test_iibbibb.mp4 -duration 13 -frames 4 +fate-seek-test-iibbibb-neg-ctts-mp4: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/mov/test_iibbibb_neg_ctts.mp4 -duration 13 -frames 4 fate-seek-cache-pipe: CMD = cat $(TARGET_SAMPLES)/gapless/gapless.mp3 | run libavformat/tests/seek$(EXESUF) cache:pipe:0 -read_ahead_limit -1 fate-seek-mkv-codec-delay: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/mkv/codec_delay_opus.mkv diff --git a/tests/ref/seek/empty-edit-mp4 b/tests/ref/seek/empty-edit-mp4 new file mode 100644 index 0000000000000..f0a4ad30b000e --- /dev/null +++ b/tests/ref/seek/empty-edit-mp4 @@ -0,0 +1,134 @@ +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 5.000000 pos: 48 size: 2917 +ret: 0 st: 0 flags:0 dts: 5.100000 pts: 5.100000 pos: 2965 size: 672 +ret: 0 st: 0 flags:0 dts: 5.200000 pts: 5.200000 pos: 3637 size: 464 +ret: 0 st: 0 flags:0 dts: 5.300000 pts: 5.300000 pos: 4101 size: 454 +ret: 0 st:-1 flags:0 ts:-1.000000 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 5.000000 pos: 48 size: 2917 +ret: 0 st: 0 flags:0 dts: 5.100000 pts: 5.100000 pos: 2965 size: 672 +ret: 0 st: 0 flags:0 dts: 5.200000 pts: 5.200000 pos: 3637 size: 464 +ret: 0 st: 0 flags:0 dts: 5.300000 pts: 5.300000 pos: 4101 size: 454 +ret: 0 st:-1 flags:1 ts: 11.894167 +ret: 0 st: 0 flags:1 dts: 11.000000 pts: 11.000000 pos: 40515 size: 3214 +ret: 0 st: 0 flags:0 dts: 11.100000 pts: 11.100000 pos: 43729 size: 581 +ret: 0 st: 0 flags:0 dts: 11.200000 pts: 11.200000 pos: 44310 size: 432 +ret: 0 st: 0 flags:0 dts: 11.300000 pts: 11.300000 pos: 44742 size: 380 +ret: 0 st: 0 flags:0 ts: 9.788379 +ret: 0 st: 0 flags:1 dts: 10.000000 pts: 10.000000 pos: 33523 size: 3221 +ret: 0 st: 0 flags:0 dts: 10.100000 pts: 10.100000 pos: 36744 size: 575 +ret: 0 st: 0 flags:0 dts: 10.200000 pts: 10.200000 pos: 37319 size: 438 +ret: 0 st: 0 flags:0 dts: 10.300000 pts: 10.300000 pos: 37757 size: 449 +ret: 0 st: 0 flags:1 ts: 7.682520 +ret: 0 st: 0 flags:1 dts: 7.000000 pts: 7.000000 pos: 13643 size: 3234 +ret: 0 st: 0 flags:0 dts: 7.100000 pts: 7.100000 pos: 16877 size: 585 +ret: 0 st: 0 flags:0 dts: 7.200000 pts: 7.200000 pos: 17462 size: 442 +ret: 0 st: 0 flags:0 dts: 7.300000 pts: 7.300000 pos: 17904 size: 371 +ret: 0 st:-1 flags:0 ts: 5.576668 +ret: 0 st: 0 flags:1 dts: 6.000000 pts: 6.000000 pos: 6953 size: 3166 +ret: 0 st: 0 flags:0 dts: 6.100000 pts: 6.100000 pos: 10119 size: 599 +ret: 0 st: 0 flags:0 dts: 6.200000 pts: 6.200000 pos: 10718 size: 418 +ret: 0 st: 0 flags:0 dts: 6.300000 pts: 6.300000 pos: 11136 size: 354 +ret: 0 st:-1 flags:1 ts: 3.470835 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 5.000000 pos: 48 size: 2917 +ret: 0 st: 0 flags:0 dts: 5.100000 pts: 5.100000 pos: 2965 size: 672 +ret: 0 st: 0 flags:0 dts: 5.200000 pts: 5.200000 pos: 3637 size: 464 +ret: 0 st: 0 flags:0 dts: 5.300000 pts: 5.300000 pos: 4101 size: 454 +ret: 0 st: 0 flags:0 ts: 1.365039 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 5.000000 pos: 48 size: 2917 +ret: 0 st: 0 flags:0 dts: 5.100000 pts: 5.100000 pos: 2965 size: 672 +ret: 0 st: 0 flags:0 dts: 5.200000 pts: 5.200000 pos: 3637 size: 464 +ret: 0 st: 0 flags:0 dts: 5.300000 pts: 5.300000 pos: 4101 size: 454 +ret: 0 st: 0 flags:1 ts:-0.740820 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 5.000000 pos: 48 size: 2917 +ret: 0 st: 0 flags:0 dts: 5.100000 pts: 5.100000 pos: 2965 size: 672 +ret: 0 st: 0 flags:0 dts: 5.200000 pts: 5.200000 pos: 3637 size: 464 +ret: 0 st: 0 flags:0 dts: 5.300000 pts: 5.300000 pos: 4101 size: 454 +ret: 0 st:-1 flags:0 ts: 12.153336 +ret: 0 st: 0 flags:1 dts: 13.000000 pts: 13.000000 pos: 54444 size: 3310 +ret: 0 st: 0 flags:0 dts: 13.100000 pts: 13.100000 pos: 57754 size: 540 +ret: 0 st: 0 flags:0 dts: 13.200000 pts: 13.200000 pos: 58294 size: 419 +ret: 0 st: 0 flags:0 dts: 13.300000 pts: 13.300000 pos: 58713 size: 338 +ret: 0 st:-1 flags:1 ts: 10.047503 +ret: 0 st: 0 flags:1 dts: 10.000000 pts: 10.000000 pos: 33523 size: 3221 +ret: 0 st: 0 flags:0 dts: 10.100000 pts: 10.100000 pos: 36744 size: 575 +ret: 0 st: 0 flags:0 dts: 10.200000 pts: 10.200000 pos: 37319 size: 438 +ret: 0 st: 0 flags:0 dts: 10.300000 pts: 10.300000 pos: 37757 size: 449 +ret: 0 st: 0 flags:0 ts: 7.941699 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 8.000000 pos: 20396 size: 3281 +ret: 0 st: 0 flags:0 dts: 8.100000 pts: 8.100000 pos: 23677 size: 631 +ret: 0 st: 0 flags:0 dts: 8.200000 pts: 8.200000 pos: 24308 size: 349 +ret: 0 st: 0 flags:0 dts: 8.300000 pts: 8.300000 pos: 24657 size: 319 +ret: 0 st: 0 flags:1 ts: 5.835840 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 5.000000 pos: 48 size: 2917 +ret: 0 st: 0 flags:0 dts: 5.100000 pts: 5.100000 pos: 2965 size: 672 +ret: 0 st: 0 flags:0 dts: 5.200000 pts: 5.200000 pos: 3637 size: 464 +ret: 0 st: 0 flags:0 dts: 5.300000 pts: 5.300000 pos: 4101 size: 454 +ret: 0 st:-1 flags:0 ts: 3.730004 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 5.000000 pos: 48 size: 2917 +ret: 0 st: 0 flags:0 dts: 5.100000 pts: 5.100000 pos: 2965 size: 672 +ret: 0 st: 0 flags:0 dts: 5.200000 pts: 5.200000 pos: 3637 size: 464 +ret: 0 st: 0 flags:0 dts: 5.300000 pts: 5.300000 pos: 4101 size: 454 +ret: 0 st:-1 flags:1 ts: 1.624171 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 5.000000 pos: 48 size: 2917 +ret: 0 st: 0 flags:0 dts: 5.100000 pts: 5.100000 pos: 2965 size: 672 +ret: 0 st: 0 flags:0 dts: 5.200000 pts: 5.200000 pos: 3637 size: 464 +ret: 0 st: 0 flags:0 dts: 5.300000 pts: 5.300000 pos: 4101 size: 454 +ret: 0 st: 0 flags:0 ts:-0.481641 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 5.000000 pos: 48 size: 2917 +ret: 0 st: 0 flags:0 dts: 5.100000 pts: 5.100000 pos: 2965 size: 672 +ret: 0 st: 0 flags:0 dts: 5.200000 pts: 5.200000 pos: 3637 size: 464 +ret: 0 st: 0 flags:0 dts: 5.300000 pts: 5.300000 pos: 4101 size: 454 +ret: 0 st: 0 flags:1 ts: 12.412500 +ret: 0 st: 0 flags:1 dts: 12.000000 pts: 12.000000 pos: 47419 size: 3229 +ret: 0 st: 0 flags:0 dts: 12.100000 pts: 12.100000 pos: 50648 size: 588 +ret: 0 st: 0 flags:0 dts: 12.200000 pts: 12.200000 pos: 51236 size: 404 +ret: 0 st: 0 flags:0 dts: 12.300000 pts: 12.300000 pos: 51640 size: 415 +ret: 0 st:-1 flags:0 ts: 10.306672 +ret: 0 st: 0 flags:1 dts: 11.000000 pts: 11.000000 pos: 40515 size: 3214 +ret: 0 st: 0 flags:0 dts: 11.100000 pts: 11.100000 pos: 43729 size: 581 +ret: 0 st: 0 flags:0 dts: 11.200000 pts: 11.200000 pos: 44310 size: 432 +ret: 0 st: 0 flags:0 dts: 11.300000 pts: 11.300000 pos: 44742 size: 380 +ret: 0 st:-1 flags:1 ts: 8.200839 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 8.000000 pos: 20396 size: 3281 +ret: 0 st: 0 flags:0 dts: 8.100000 pts: 8.100000 pos: 23677 size: 631 +ret: 0 st: 0 flags:0 dts: 8.200000 pts: 8.200000 pos: 24308 size: 349 +ret: 0 st: 0 flags:0 dts: 8.300000 pts: 8.300000 pos: 24657 size: 319 +ret: 0 st: 0 flags:0 ts: 6.095020 +ret: 0 st: 0 flags:1 dts: 7.000000 pts: 7.000000 pos: 13643 size: 3234 +ret: 0 st: 0 flags:0 dts: 7.100000 pts: 7.100000 pos: 16877 size: 585 +ret: 0 st: 0 flags:0 dts: 7.200000 pts: 7.200000 pos: 17462 size: 442 +ret: 0 st: 0 flags:0 dts: 7.300000 pts: 7.300000 pos: 17904 size: 371 +ret: 0 st: 0 flags:1 ts: 3.989160 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 5.000000 pos: 48 size: 2917 +ret: 0 st: 0 flags:0 dts: 5.100000 pts: 5.100000 pos: 2965 size: 672 +ret: 0 st: 0 flags:0 dts: 5.200000 pts: 5.200000 pos: 3637 size: 464 +ret: 0 st: 0 flags:0 dts: 5.300000 pts: 5.300000 pos: 4101 size: 454 +ret: 0 st:-1 flags:0 ts: 1.883340 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 5.000000 pos: 48 size: 2917 +ret: 0 st: 0 flags:0 dts: 5.100000 pts: 5.100000 pos: 2965 size: 672 +ret: 0 st: 0 flags:0 dts: 5.200000 pts: 5.200000 pos: 3637 size: 464 +ret: 0 st: 0 flags:0 dts: 5.300000 pts: 5.300000 pos: 4101 size: 454 +ret: 0 st:-1 flags:1 ts:-0.222493 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 5.000000 pos: 48 size: 2917 +ret: 0 st: 0 flags:0 dts: 5.100000 pts: 5.100000 pos: 2965 size: 672 +ret: 0 st: 0 flags:0 dts: 5.200000 pts: 5.200000 pos: 3637 size: 464 +ret: 0 st: 0 flags:0 dts: 5.300000 pts: 5.300000 pos: 4101 size: 454 +ret: 0 st: 0 flags:0 ts: 12.671680 +ret: 0 st: 0 flags:1 dts: 13.000000 pts: 13.000000 pos: 54444 size: 3310 +ret: 0 st: 0 flags:0 dts: 13.100000 pts: 13.100000 pos: 57754 size: 540 +ret: 0 st: 0 flags:0 dts: 13.200000 pts: 13.200000 pos: 58294 size: 419 +ret: 0 st: 0 flags:0 dts: 13.300000 pts: 13.300000 pos: 58713 size: 338 +ret: 0 st: 0 flags:1 ts: 10.565820 +ret: 0 st: 0 flags:1 dts: 10.000000 pts: 10.000000 pos: 33523 size: 3221 +ret: 0 st: 0 flags:0 dts: 10.100000 pts: 10.100000 pos: 36744 size: 575 +ret: 0 st: 0 flags:0 dts: 10.200000 pts: 10.200000 pos: 37319 size: 438 +ret: 0 st: 0 flags:0 dts: 10.300000 pts: 10.300000 pos: 37757 size: 449 +ret: 0 st:-1 flags:0 ts: 8.460008 +ret: 0 st: 0 flags:1 dts: 9.000000 pts: 9.000000 pos: 27090 size: 3182 +ret: 0 st: 0 flags:0 dts: 9.100000 pts: 9.100000 pos: 30272 size: 481 +ret: 0 st: 0 flags:0 dts: 9.200000 pts: 9.200000 pos: 30753 size: 334 +ret: 0 st: 0 flags:0 dts: 9.300000 pts: 9.300000 pos: 31087 size: 328 +ret: 0 st:-1 flags:1 ts: 6.354175 +ret: 0 st: 0 flags:1 dts: 6.000000 pts: 6.000000 pos: 6953 size: 3166 +ret: 0 st: 0 flags:0 dts: 6.100000 pts: 6.100000 pos: 10119 size: 599 +ret: 0 st: 0 flags:0 dts: 6.200000 pts: 6.200000 pos: 10718 size: 418 +ret: 0 st: 0 flags:0 dts: 6.300000 pts: 6.300000 pos: 11136 size: 354 diff --git a/tests/ref/seek/test-iibbibb-mp4 b/tests/ref/seek/test-iibbibb-mp4 new file mode 100644 index 0000000000000..5a8960021882f --- /dev/null +++ b/tests/ref/seek/test-iibbibb-mp4 @@ -0,0 +1,122 @@ +ret: 0 st: 0 flags:1 dts:-2.000000 pts: 0.000000 pos: 48 size: 7804 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st:-1 flags:0 ts:-1.000000 +ret: 0 st: 0 flags:1 dts:-2.000000 pts: 0.000000 pos: 48 size: 7804 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st:-1 flags:1 ts: 4.894167 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret:-1 st: 0 flags:0 ts: 10.788330 +ret: 0 st: 0 flags:1 ts: 3.682495 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st:-1 flags:0 ts: 9.576668 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:0 dts: 9.000000 pts: 11.000000 pos: 44894 size: 1437 +ret: 0 st: 0 flags:0 dts: 10.000000 pts: 10.000000 pos: 46331 size: 1186 +ret:-EOF +ret: 0 st:-1 flags:1 ts: 2.470835 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 ts: 8.364990 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:0 dts: 9.000000 pts: 11.000000 pos: 44894 size: 1437 +ret: 0 st: 0 flags:0 dts: 10.000000 pts: 10.000000 pos: 46331 size: 1186 +ret:-EOF +ret: 0 st: 0 flags:1 ts: 1.259155 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st:-1 flags:0 ts: 7.153336 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:0 dts: 9.000000 pts: 11.000000 pos: 44894 size: 1437 +ret: 0 st: 0 flags:0 dts: 10.000000 pts: 10.000000 pos: 46331 size: 1186 +ret:-EOF +ret: 0 st:-1 flags:1 ts: 0.047503 +ret: 0 st: 0 flags:1 dts:-2.000000 pts: 0.000000 pos: 48 size: 7804 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st: 0 flags:0 ts: 5.941650 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st: 0 flags:0 dts: 6.000000 pts: 8.000000 pos: 35757 size: 1273 +ret: 0 st: 0 flags:0 dts: 7.000000 pts: 7.000000 pos: 37030 size: 1130 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:1 ts: 11.835815 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:0 dts: 9.000000 pts: 11.000000 pos: 44894 size: 1437 +ret: 0 st: 0 flags:0 dts: 10.000000 pts: 10.000000 pos: 46331 size: 1186 +ret:-EOF +ret: 0 st:-1 flags:0 ts: 4.730004 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st: 0 flags:0 dts: 6.000000 pts: 8.000000 pos: 35757 size: 1273 +ret: 0 st: 0 flags:0 dts: 7.000000 pts: 7.000000 pos: 37030 size: 1130 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st:-1 flags:1 ts: 10.624171 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:0 dts: 9.000000 pts: 11.000000 pos: 44894 size: 1437 +ret: 0 st: 0 flags:0 dts: 10.000000 pts: 10.000000 pos: 46331 size: 1186 +ret:-EOF +ret: 0 st: 0 flags:0 ts: 3.518311 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st: 0 flags:1 ts: 9.412476 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st: 0 flags:0 dts: 6.000000 pts: 8.000000 pos: 35757 size: 1273 +ret: 0 st: 0 flags:0 dts: 7.000000 pts: 7.000000 pos: 37030 size: 1130 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st:-1 flags:0 ts: 2.306672 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st:-1 flags:1 ts: 8.200839 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st: 0 flags:0 dts: 6.000000 pts: 8.000000 pos: 35757 size: 1273 +ret: 0 st: 0 flags:0 dts: 7.000000 pts: 7.000000 pos: 37030 size: 1130 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:0 ts: 1.095032 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st: 0 flags:1 ts: 6.989197 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st:-1 flags:0 ts:-0.116660 +ret: 0 st: 0 flags:1 dts:-2.000000 pts: 0.000000 pos: 48 size: 7804 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st:-1 flags:1 ts: 5.777507 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret:-1 st: 0 flags:0 ts: 11.671692 +ret: 0 st: 0 flags:1 ts: 4.565857 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret:-1 st:-1 flags:0 ts: 10.460008 +ret: 0 st:-1 flags:1 ts: 3.354175 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 diff --git a/tests/ref/seek/test-iibbibb-neg-ctts-mp4 b/tests/ref/seek/test-iibbibb-neg-ctts-mp4 new file mode 100644 index 0000000000000..5a8960021882f --- /dev/null +++ b/tests/ref/seek/test-iibbibb-neg-ctts-mp4 @@ -0,0 +1,122 @@ +ret: 0 st: 0 flags:1 dts:-2.000000 pts: 0.000000 pos: 48 size: 7804 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st:-1 flags:0 ts:-1.000000 +ret: 0 st: 0 flags:1 dts:-2.000000 pts: 0.000000 pos: 48 size: 7804 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st:-1 flags:1 ts: 4.894167 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret:-1 st: 0 flags:0 ts: 10.788330 +ret: 0 st: 0 flags:1 ts: 3.682495 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st:-1 flags:0 ts: 9.576668 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:0 dts: 9.000000 pts: 11.000000 pos: 44894 size: 1437 +ret: 0 st: 0 flags:0 dts: 10.000000 pts: 10.000000 pos: 46331 size: 1186 +ret:-EOF +ret: 0 st:-1 flags:1 ts: 2.470835 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 ts: 8.364990 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:0 dts: 9.000000 pts: 11.000000 pos: 44894 size: 1437 +ret: 0 st: 0 flags:0 dts: 10.000000 pts: 10.000000 pos: 46331 size: 1186 +ret:-EOF +ret: 0 st: 0 flags:1 ts: 1.259155 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st:-1 flags:0 ts: 7.153336 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:0 dts: 9.000000 pts: 11.000000 pos: 44894 size: 1437 +ret: 0 st: 0 flags:0 dts: 10.000000 pts: 10.000000 pos: 46331 size: 1186 +ret:-EOF +ret: 0 st:-1 flags:1 ts: 0.047503 +ret: 0 st: 0 flags:1 dts:-2.000000 pts: 0.000000 pos: 48 size: 7804 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st: 0 flags:0 ts: 5.941650 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st: 0 flags:0 dts: 6.000000 pts: 8.000000 pos: 35757 size: 1273 +ret: 0 st: 0 flags:0 dts: 7.000000 pts: 7.000000 pos: 37030 size: 1130 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:1 ts: 11.835815 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:0 dts: 9.000000 pts: 11.000000 pos: 44894 size: 1437 +ret: 0 st: 0 flags:0 dts: 10.000000 pts: 10.000000 pos: 46331 size: 1186 +ret:-EOF +ret: 0 st:-1 flags:0 ts: 4.730004 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st: 0 flags:0 dts: 6.000000 pts: 8.000000 pos: 35757 size: 1273 +ret: 0 st: 0 flags:0 dts: 7.000000 pts: 7.000000 pos: 37030 size: 1130 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st:-1 flags:1 ts: 10.624171 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:0 dts: 9.000000 pts: 11.000000 pos: 44894 size: 1437 +ret: 0 st: 0 flags:0 dts: 10.000000 pts: 10.000000 pos: 46331 size: 1186 +ret:-EOF +ret: 0 st: 0 flags:0 ts: 3.518311 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st: 0 flags:1 ts: 9.412476 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st: 0 flags:0 dts: 6.000000 pts: 8.000000 pos: 35757 size: 1273 +ret: 0 st: 0 flags:0 dts: 7.000000 pts: 7.000000 pos: 37030 size: 1130 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st:-1 flags:0 ts: 2.306672 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st:-1 flags:1 ts: 8.200839 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st: 0 flags:0 dts: 6.000000 pts: 8.000000 pos: 35757 size: 1273 +ret: 0 st: 0 flags:0 dts: 7.000000 pts: 7.000000 pos: 37030 size: 1130 +ret: 0 st: 0 flags:1 dts: 8.000000 pts: 12.000000 pos: 38160 size: 6734 +ret: 0 st: 0 flags:0 ts: 1.095032 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st: 0 flags:1 ts: 6.989197 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret: 0 st:-1 flags:0 ts:-0.116660 +ret: 0 st: 0 flags:1 dts:-2.000000 pts: 0.000000 pos: 48 size: 7804 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st:-1 flags:1 ts: 5.777507 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret:-1 st: 0 flags:0 ts: 11.671692 +ret: 0 st: 0 flags:1 ts: 4.565857 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 +ret: 0 st: 0 flags:0 dts: 3.000000 pts: 5.000000 pos: 25805 size: 1247 +ret: 0 st: 0 flags:0 dts: 4.000000 pts: 4.000000 pos: 27052 size: 1110 +ret: 0 st: 0 flags:1 dts: 5.000000 pts: 9.000000 pos: 28162 size: 7595 +ret:-1 st:-1 flags:0 ts: 10.460008 +ret: 0 st:-1 flags:1 ts: 3.354175 +ret: 0 st: 0 flags:1 dts:-1.000000 pts: 3.000000 pos: 7852 size: 7808 +ret: 0 st: 0 flags:0 dts: 0.000000 pts: 2.000000 pos: 15660 size: 1301 +ret: 0 st: 0 flags:0 dts: 1.000000 pts: 1.000000 pos: 16961 size: 1114 +ret: 0 st: 0 flags:1 dts: 2.000000 pts: 6.000000 pos: 18075 size: 7730 From 2536bd863246218631ab27144d8a3be45036445a Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 9 Mar 2018 14:31:30 -0300 Subject: [PATCH 2094/2557] avcodec/extract_extradata: don't allocate more space than needed when removing NALUs in h264/hevc Signed-off-by: James Almer --- libavcodec/extract_extradata_bsf.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c index fbfd12aeef51c..4e2d6017429cf 100644 --- a/libavcodec/extract_extradata_bsf.c +++ b/libavcodec/extract_extradata_bsf.c @@ -62,7 +62,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, ExtractExtradataContext *s = ctx->priv_data; H2645Packet h2645_pkt = { 0 }; - int extradata_size = 0; + int extradata_size = 0, filtered_size = 0; const int *extradata_nal_types; int nb_extradata_nal_types; int i, has_sps = 0, has_vps = 0, ret = 0; @@ -90,6 +90,8 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, } else { if (nal->type == H264_NAL_SPS) has_sps = 1; } + } else if (s->remove) { + filtered_size += nal->raw_size + 3; } } @@ -100,11 +102,13 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, uint8_t *extradata, *filtered_data; if (s->remove) { - filtered_buf = av_buffer_alloc(pkt->size + AV_INPUT_BUFFER_PADDING_SIZE); + filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!filtered_buf) { ret = AVERROR(ENOMEM); goto fail; } + memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + filtered_data = filtered_buf->data; } @@ -137,9 +141,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, av_buffer_unref(&pkt->buf); pkt->buf = filtered_buf; pkt->data = filtered_buf->data; - pkt->size = filtered_data - filtered_buf->data; - - memset(pkt->data + pkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + pkt->size = filtered_size; } } From 8fb0e51bd198c996b8932735e8002f0952ef1d06 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 6 Mar 2018 19:47:29 +0100 Subject: [PATCH 2095/2557] avfilter: add drmeter audio filter Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/filters.texi | 15 +++ libavfilter/Makefile | 1 + libavfilter/af_drmeter.c | 233 +++++++++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- 6 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 libavfilter/af_drmeter.c diff --git a/Changelog b/Changelog index d8630731fa1d6..c1b9df46bc715 100644 --- a/Changelog +++ b/Changelog @@ -45,6 +45,7 @@ version : - Moved nvidia codec headers into an external repository. They can be found at http://git.videolan.org/?p=ffmpeg/nv-codec-headers.git - native SBC encoder and decoder +- drmeter audio filter version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index 7151d4c7485b0..bd43a7ac6e16f 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2538,6 +2538,21 @@ Optional. It should have a value much less than 1 (e.g. 0.05 or 0.02) and is used to prevent clipping. @end table +@section drmeter +Measure audio dynamic range. + +DR values of 14 and higher is found in very dynamic material. DR of 8 to 13 +is found in transition material. And anything less that 8 have very poor dynamics +and is very compressed. + +The filter accepts the following options: + +@table @option +@item length +Set window length in seconds used to split audio into segments of equal length. +Default is 3 seconds. +@end table + @section dynaudnorm Dynamic Audio Normalizer. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 6a6083618d3fb..fc16512e2c3eb 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -87,6 +87,7 @@ OBJS-$(CONFIG_COMPENSATIONDELAY_FILTER) += af_compensationdelay.o OBJS-$(CONFIG_CROSSFEED_FILTER) += af_crossfeed.o OBJS-$(CONFIG_CRYSTALIZER_FILTER) += af_crystalizer.o OBJS-$(CONFIG_DCSHIFT_FILTER) += af_dcshift.o +OBJS-$(CONFIG_DRMETER_FILTER) += af_drmeter.o OBJS-$(CONFIG_DYNAUDNORM_FILTER) += af_dynaudnorm.o OBJS-$(CONFIG_EARWAX_FILTER) += af_earwax.o OBJS-$(CONFIG_EBUR128_FILTER) += f_ebur128.o diff --git a/libavfilter/af_drmeter.c b/libavfilter/af_drmeter.c new file mode 100644 index 0000000000000..ecccb6518639d --- /dev/null +++ b/libavfilter/af_drmeter.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2018 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/ffmath.h" +#include "libavutil/opt.h" +#include "audio.h" +#include "avfilter.h" +#include "internal.h" + +typedef struct ChannelStats { + uint64_t nb_samples; + uint64_t blknum; + float peak; + float sum; + uint32_t peaks[10001]; + uint32_t rms[10001]; +} ChannelStats; + +typedef struct DRMeterContext { + const AVClass *class; + ChannelStats *chstats; + int nb_channels; + uint64_t tc_samples; + double time_constant; +} DRMeterContext; + +#define OFFSET(x) offsetof(DRMeterContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption drmeter_options[] = { + { "length", "set the window length", OFFSET(time_constant), AV_OPT_TYPE_DOUBLE, {.dbl=3}, .01, 10, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(drmeter); + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats; + AVFilterChannelLayouts *layouts; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_NONE + }; + int ret; + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + formats = ff_all_samplerates(); + if (!formats) + return AVERROR(ENOMEM); + return ff_set_common_samplerates(ctx, formats); +} + +static int config_output(AVFilterLink *outlink) +{ + DRMeterContext *s = outlink->src->priv; + + s->chstats = av_calloc(sizeof(*s->chstats), outlink->channels); + if (!s->chstats) + return AVERROR(ENOMEM); + s->nb_channels = outlink->channels; + s->tc_samples = s->time_constant * outlink->sample_rate + .5; + + return 0; +} + +static void finish_block(ChannelStats *p) +{ + int peak_bin, rms_bin; + float peak, rms; + + rms = sqrt(2 * p->sum / p->nb_samples); + peak = p->peak; + rms_bin = av_clip(rms * 10000, 0, 10000); + peak_bin = av_clip(peak * 10000, 0, 10000); + p->rms[rms_bin]++; + p->peaks[peak_bin]++; + + p->peak = 0; + p->sum = 0; + p->nb_samples = 0; + p->blknum++; +} + +static void update_stat(DRMeterContext *s, ChannelStats *p, float sample) +{ + if (p->nb_samples >= s->tc_samples) { + finish_block(p); + } + + p->peak = FFMAX(FFABS(sample), p->peak); + p->sum += sample * sample; + p->nb_samples++; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *buf) +{ + DRMeterContext *s = inlink->dst->priv; + const int channels = s->nb_channels; + int i, c; + + switch (inlink->format) { + case AV_SAMPLE_FMT_FLTP: + for (c = 0; c < channels; c++) { + ChannelStats *p = &s->chstats[c]; + const float *src = (const float *)buf->extended_data[c]; + + for (i = 0; i < buf->nb_samples; i++, src++) + update_stat(s, p, *src); + } + break; + case AV_SAMPLE_FMT_FLT: { + const float *src = (const float *)buf->extended_data[0]; + + for (i = 0; i < buf->nb_samples; i++) { + for (c = 0; c < channels; c++, src++) + update_stat(s, &s->chstats[c], *src); + }} + break; + } + + return ff_filter_frame(inlink->dst->outputs[0], buf); +} + +#define SQR(a) ((a)*(a)) + +static void print_stats(AVFilterContext *ctx) +{ + DRMeterContext *s = ctx->priv; + float dr = 0; + int ch; + + for (ch = 0; ch < s->nb_channels; ch++) { + ChannelStats *p = &s->chstats[ch]; + float chdr, secondpeak, rmssum = 0; + int i, j, first = 0; + + finish_block(p); + + for (i = 0; i <= 10000; i++) { + if (p->peaks[10000 - i]) { + if (first) + break; + first = 1; + } + } + + secondpeak = (10000 - i) / 10000.; + + for (i = 10000, j = 0; i >= 0 && j < 0.2 * p->blknum; i--) { + if (p->rms[i]) { + rmssum += SQR(i / 10000.) * p->rms[i]; + j += p->rms[i]; + } + } + + chdr = 20 * log10(secondpeak / sqrt(rmssum / (0.2 * p->blknum))); + dr += chdr; + av_log(ctx, AV_LOG_INFO, "Channel %d: DR: %.1f\n", ch + 1, chdr); + } + + av_log(ctx, AV_LOG_INFO, "Overall DR: %.1f\n", dr / s->nb_channels); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + DRMeterContext *s = ctx->priv; + + if (s->nb_channels) + print_stats(ctx); + av_freep(&s->chstats); +} + +static const AVFilterPad drmeter_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad drmeter_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_af_drmeter = { + .name = "drmeter", + .description = NULL_IF_CONFIG_SMALL("Measure audio dynamic range."), + .query_formats = query_formats, + .priv_size = sizeof(DRMeterContext), + .priv_class = &drmeter_class, + .uninit = uninit, + .inputs = drmeter_inputs, + .outputs = drmeter_outputs, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 9adb1090b7c35..cc423af7381a5 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -98,6 +98,7 @@ static void register_all(void) REGISTER_FILTER(CROSSFEED, crossfeed, af); REGISTER_FILTER(CRYSTALIZER, crystalizer, af); REGISTER_FILTER(DCSHIFT, dcshift, af); + REGISTER_FILTER(DRMETER, drmeter, af); REGISTER_FILTER(DYNAUDNORM, dynaudnorm, af); REGISTER_FILTER(EARWAX, earwax, af); REGISTER_FILTER(EBUR128, ebur128, af); diff --git a/libavfilter/version.h b/libavfilter/version.h index ca096962bb5d3..babb4187b4199 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 12 +#define LIBAVFILTER_VERSION_MINOR 13 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ From 27d4249fadbada099ece60fc6d7ddc3603c10df6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 11 Mar 2018 13:53:04 -0300 Subject: [PATCH 2096/2557] avcodec/chomp: move the reference in the bsf internal buffer There's no need to allocate a new packet for it. Reviewed-by: Mark Thompson Signed-off-by: James Almer --- libavcodec/chomp_bsf.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libavcodec/chomp_bsf.c b/libavcodec/chomp_bsf.c index cc94380535a46..3ba45f3e06dff 100644 --- a/libavcodec/chomp_bsf.c +++ b/libavcodec/chomp_bsf.c @@ -23,20 +23,16 @@ #include "bsf.h" #include "internal.h" -static int chomp_filter(AVBSFContext *ctx, AVPacket *out) +static int chomp_filter(AVBSFContext *ctx, AVPacket *pkt) { - AVPacket *in; int ret; - ret = ff_bsf_get_packet(ctx, &in); + ret = ff_bsf_get_packet_ref(ctx, pkt); if (ret < 0) return ret; - while (in->size > 0 && !in->data[in->size - 1]) - in->size--; - - av_packet_move_ref(out, in); - av_packet_free(&in); + while (pkt->size > 0 && !pkt->data[pkt->size - 1]) + pkt->size--; return 0; } From aba437a6d0a7e0d9bafc6a2170ddd31d19d6c4d5 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 11 Mar 2018 13:29:19 -0300 Subject: [PATCH 2097/2557] avcodec/dca_core: move the reference in the bsf internal buffer There's no need to allocate a new packet for it. Reviewed-by: Mark Thompson Signed-off-by: James Almer --- libavcodec/dca_core_bsf.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/libavcodec/dca_core_bsf.c b/libavcodec/dca_core_bsf.c index 9edc0cfd61867..8565796951e16 100644 --- a/libavcodec/dca_core_bsf.c +++ b/libavcodec/dca_core_bsf.c @@ -24,18 +24,17 @@ #include "dca_syncwords.h" #include "libavutil/mem.h" -static int dca_core_filter(AVBSFContext *ctx, AVPacket *out) +static int dca_core_filter(AVBSFContext *ctx, AVPacket *pkt) { - AVPacket *in; GetByteContext gb; uint32_t syncword; int core_size = 0, ret; - ret = ff_bsf_get_packet(ctx, &in); + ret = ff_bsf_get_packet_ref(ctx, pkt); if (ret < 0) return ret; - bytestream2_init(&gb, in->data, in->size); + bytestream2_init(&gb, pkt->data, pkt->size); syncword = bytestream2_get_be32(&gb); bytestream2_skip(&gb, 1); @@ -45,11 +44,8 @@ static int dca_core_filter(AVBSFContext *ctx, AVPacket *out) break; } - av_packet_move_ref(out, in); - av_packet_free(&in); - - if (core_size > 0 && core_size <= out->size) { - out->size = core_size; + if (core_size > 0 && core_size <= pkt->size) { + pkt->size = core_size; } return 0; From 9c6dd9d6248897a2d8dd4ede948c166e5a579a4b Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 11 Mar 2018 13:45:05 -0300 Subject: [PATCH 2098/2557] avcodec/extract_extradata: move the reference in the bsf internal buffer There's no need to allocate a new packet for it. Reviewed-by: Mark Thompson Signed-off-by: James Almer --- libavcodec/extract_extradata_bsf.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c index 4e2d6017429cf..1c386becd7e80 100644 --- a/libavcodec/extract_extradata_bsf.c +++ b/libavcodec/extract_extradata_bsf.c @@ -279,24 +279,23 @@ static int extract_extradata_init(AVBSFContext *ctx) return 0; } -static int extract_extradata_filter(AVBSFContext *ctx, AVPacket *out) +static int extract_extradata_filter(AVBSFContext *ctx, AVPacket *pkt) { ExtractExtradataContext *s = ctx->priv_data; - AVPacket *in; uint8_t *extradata = NULL; int extradata_size; int ret = 0; - ret = ff_bsf_get_packet(ctx, &in); + ret = ff_bsf_get_packet_ref(ctx, pkt); if (ret < 0) return ret; - ret = s->extract(ctx, in, &extradata, &extradata_size); + ret = s->extract(ctx, pkt, &extradata, &extradata_size); if (ret < 0) goto fail; if (extradata) { - ret = av_packet_add_side_data(in, AV_PKT_DATA_NEW_EXTRADATA, + ret = av_packet_add_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, extradata, extradata_size); if (ret < 0) { av_freep(&extradata); @@ -304,10 +303,10 @@ static int extract_extradata_filter(AVBSFContext *ctx, AVPacket *out) } } - av_packet_move_ref(out, in); + return 0; fail: - av_packet_free(&in); + av_packet_unref(pkt); return ret; } From 11bef2fe7232d290541a112efb2d360600c7b917 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 11 Mar 2018 14:02:10 -0300 Subject: [PATCH 2099/2557] avcodec/mov2textsub: move the reference in the bsf internal buffer There's no need to allocate a new packet for it. Reviewed-by: Mark Thompson Signed-off-by: James Almer --- libavcodec/movsub_bsf.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/libavcodec/movsub_bsf.c b/libavcodec/movsub_bsf.c index 3cb1183cd89e3..5878607061eab 100644 --- a/libavcodec/movsub_bsf.c +++ b/libavcodec/movsub_bsf.c @@ -62,35 +62,23 @@ const AVBitStreamFilter ff_text2movsub_bsf = { .filter = text2movsub, }; -static int mov2textsub(AVBSFContext *ctx, AVPacket *out) +static int mov2textsub(AVBSFContext *ctx, AVPacket *pkt) { - AVPacket *in; int ret = 0; - ret = ff_bsf_get_packet(ctx, &in); + ret = ff_bsf_get_packet_ref(ctx, pkt); if (ret < 0) return ret; - if (in->size < 2) { - ret = AVERROR_INVALIDDATA; - goto fail; + if (pkt->size < 2) { + av_packet_unref(pkt); + return AVERROR_INVALIDDATA; } - ret = av_new_packet(out, FFMIN(in->size - 2, AV_RB16(in->data))); - if (ret < 0) - goto fail; - - ret = av_packet_copy_props(out, in); - if (ret < 0) - goto fail; - - memcpy(out->data, in->data + 2, out->size); + pkt->data += 2; + pkt->size = FFMIN(pkt->size - 2, AV_RB16(pkt->data)); -fail: - if (ret < 0) - av_packet_unref(out); - av_packet_free(&in); - return ret; + return 0; } const AVBitStreamFilter ff_mov2textsub_bsf = { From a1a0859ad52e8f5161b1ba15cc951783e52b5ff8 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 11 Mar 2018 13:45:19 -0300 Subject: [PATCH 2100/2557] avcodec/remove_extradata: move the reference in the bsf internal buffer There's no need to allocate a new packet for it. Reviewed-by: Mark Thompson Signed-off-by: James Almer --- libavcodec/remove_extradata_bsf.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/libavcodec/remove_extradata_bsf.c b/libavcodec/remove_extradata_bsf.c index a54bbdbacfcee..d74391e547ab9 100644 --- a/libavcodec/remove_extradata_bsf.c +++ b/libavcodec/remove_extradata_bsf.c @@ -38,30 +38,26 @@ typedef struct RemoveExtradataContext { AVCodecContext *avctx; } RemoveExtradataContext; -static int remove_extradata(AVBSFContext *ctx, AVPacket *out) +static int remove_extradata(AVBSFContext *ctx, AVPacket *pkt) { RemoveExtradataContext *s = ctx->priv_data; - AVPacket *in; int ret; - ret = ff_bsf_get_packet(ctx, &in); + ret = ff_bsf_get_packet_ref(ctx, pkt); if (ret < 0) return ret; if (s->parser && s->parser->parser->split) { if (s->freq == REMOVE_FREQ_ALL || - (s->freq == REMOVE_FREQ_NONKEYFRAME && !(in->flags & AV_PKT_FLAG_KEY)) || - (s->freq == REMOVE_FREQ_KEYFRAME && in->flags & AV_PKT_FLAG_KEY)) { - int i = s->parser->parser->split(s->avctx, in->data, in->size); - in->data += i; - in->size -= i; + (s->freq == REMOVE_FREQ_NONKEYFRAME && !(pkt->flags & AV_PKT_FLAG_KEY)) || + (s->freq == REMOVE_FREQ_KEYFRAME && pkt->flags & AV_PKT_FLAG_KEY)) { + int i = s->parser->parser->split(s->avctx, pkt->data, pkt->size); + pkt->data += i; + pkt->size -= i; } } - av_packet_move_ref(out, in); - av_packet_free(&in); - return 0; } From c266049191e5230e36e610874a57673e7af0515d Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 11 Mar 2018 13:50:28 -0300 Subject: [PATCH 2101/2557] avcodec/trace_headers: move the reference in the bsf internal buffer There's no need to allocate a new packet for it. Reviewed-by: Mark Thompson Signed-off-by: James Almer --- libavcodec/trace_headers_bsf.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/libavcodec/trace_headers_bsf.c b/libavcodec/trace_headers_bsf.c index 93d04cb5097ca..0697e98943d59 100644 --- a/libavcodec/trace_headers_bsf.c +++ b/libavcodec/trace_headers_bsf.c @@ -67,45 +67,43 @@ static void trace_headers_close(AVBSFContext *bsf) ff_cbs_close(&ctx->cbc); } -static int trace_headers(AVBSFContext *bsf, AVPacket *out) +static int trace_headers(AVBSFContext *bsf, AVPacket *pkt) { TraceHeadersContext *ctx = bsf->priv_data; CodedBitstreamFragment au; - AVPacket *in; char tmp[256] = { 0 }; int err; - err = ff_bsf_get_packet(bsf, &in); + err = ff_bsf_get_packet_ref(bsf, pkt); if (err < 0) return err; - if (in->flags & AV_PKT_FLAG_KEY) + if (pkt->flags & AV_PKT_FLAG_KEY) av_strlcat(tmp, ", key frame", sizeof(tmp)); - if (in->flags & AV_PKT_FLAG_CORRUPT) + if (pkt->flags & AV_PKT_FLAG_CORRUPT) av_strlcat(tmp, ", corrupt", sizeof(tmp)); - if (in->pts != AV_NOPTS_VALUE) - av_strlcatf(tmp, sizeof(tmp), ", pts %"PRId64, in->pts); + if (pkt->pts != AV_NOPTS_VALUE) + av_strlcatf(tmp, sizeof(tmp), ", pts %"PRId64, pkt->pts); else av_strlcat(tmp, ", no pts", sizeof(tmp)); - if (in->dts != AV_NOPTS_VALUE) - av_strlcatf(tmp, sizeof(tmp), ", dts %"PRId64, in->dts); + if (pkt->dts != AV_NOPTS_VALUE) + av_strlcatf(tmp, sizeof(tmp), ", dts %"PRId64, pkt->dts); else av_strlcat(tmp, ", no dts", sizeof(tmp)); - if (in->duration > 0) - av_strlcatf(tmp, sizeof(tmp), ", duration %"PRId64, in->duration); + if (pkt->duration > 0) + av_strlcatf(tmp, sizeof(tmp), ", duration %"PRId64, pkt->duration); - av_log(bsf, AV_LOG_INFO, "Packet: %d bytes%s.\n", in->size, tmp); + av_log(bsf, AV_LOG_INFO, "Packet: %d bytes%s.\n", pkt->size, tmp); - err = ff_cbs_read_packet(ctx->cbc, &au, in); - if (err < 0) + err = ff_cbs_read_packet(ctx->cbc, &au, pkt); + if (err < 0) { + av_packet_unref(pkt); return err; + } ff_cbs_fragment_uninit(ctx->cbc, &au); - av_packet_move_ref(out, in); - av_packet_free(&in); - return 0; } From 2f37082827a405430c40408ee2db19ea2866ce64 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 9 Mar 2018 16:43:29 +0100 Subject: [PATCH 2102/2557] avformat/mov: Fix integer overflows related to sample_duration Fixes: runtime error: signed integer overflow: -9166684017437101870 + -2495066639299164439 cannot be represented in type Fixes: Chromium bug 791349 Reported-by: Matt Wolenetz Reviewed-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 51228f5df2095..b7f9c0cdd1827 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2885,14 +2885,19 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) && total_sample_count > 100 && sample_duration/10 > duration / total_sample_count) sample_duration = duration / total_sample_count; - duration+=(int64_t)sample_duration*sample_count; + duration+=(int64_t)sample_duration*(uint64_t)sample_count; total_sample_count+=sample_count; } sc->stts_count = i; - sc->duration_for_fps += duration; - sc->nb_frames_for_fps += total_sample_count; + if (duration > 0 && + duration <= INT64_MAX - sc->duration_for_fps && + total_sample_count <= INT64_MAX - sc->nb_frames_for_fps + ) { + sc->duration_for_fps += duration; + sc->nb_frames_for_fps += total_sample_count; + } if (pb->eof_reached) { av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STTS atom\n"); @@ -4798,8 +4803,13 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) dts += sample_duration; offset += sample_size; sc->data_size += sample_size; - sc->duration_for_fps += sample_duration; - sc->nb_frames_for_fps ++; + + if (sample_duration <= INT64_MAX - sc->duration_for_fps && + 1 <= INT64_MAX - sc->nb_frames_for_fps + ) { + sc->duration_for_fps += sample_duration; + sc->nb_frames_for_fps ++; + } } if (i < entries) { // EOF found before reading all entries. Fix the hole this would From 64c9ce0abc0fd8774b523afda3ddb17c86caa86a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 11 Mar 2018 00:13:57 +0100 Subject: [PATCH 2103/2557] avcodec/wmalosslessdec: Reset num_saved_bits on error path Fixes: NULL pointer dereference Fixes: poc-201803.wav Found-by: GwanYeong Kim Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer --- libavcodec/wmalosslessdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index 133a3e92d1ad4..59e89295867e2 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -1148,6 +1148,7 @@ static void save_bits(WmallDecodeCtx *s, GetBitContext* gb, int len, if (len <= 0 || buflen > s->max_frame_size) { avpriv_request_sample(s->avctx, "Too small input buffer"); s->packet_loss = 1; + s->num_saved_bits = 0; return; } From 8ee3265dbe2e85537affe3b3055b00ba8646aa70 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 27 Feb 2018 15:17:12 +0100 Subject: [PATCH 2104/2557] avcodec/nuv: Check for minimum input size for uncomprssed and rtjpeg Fixes: Timeout Fixes: 6297/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_NUV_fuzzer-4882404863901696 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/nuv.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libavcodec/nuv.c b/libavcodec/nuv.c index ad6c029e5005f..8d806dbbff30a 100644 --- a/libavcodec/nuv.c +++ b/libavcodec/nuv.c @@ -161,6 +161,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, int orig_size = buf_size; int keyframe, ret; int size_change = 0; + int minsize = 0; int result, init_frame = !avctx->frame_number; enum { NUV_UNCOMPRESSED = '0', @@ -206,6 +207,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, keyframe = 1; break; } + switch (comptype) { + case NUV_UNCOMPRESSED: + minsize = c->width * c->height * 3 / 2; + break; + case NUV_RTJPEG: + minsize = c->width/16 * (c->height/16) * 6; + break; + } + if (buf_size < minsize / 4) + return AVERROR_INVALIDDATA; retry: // Skip the rest of the frame header. buf = &buf[12]; From 939440ad1aa820bed51f54d273b4fa6c5016d9f9 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 27 Feb 2018 15:17:12 +0100 Subject: [PATCH 2105/2557] avcodec/nuv: rtjpeg with dimensions less than 16 would result in no decoded pixels thus reject it Fixes: Timeout Fixes: 6297/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_NUV_fuzzer-4882404863901696 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/nuv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/nuv.c b/libavcodec/nuv.c index 8d806dbbff30a..32ed65899b13d 100644 --- a/libavcodec/nuv.c +++ b/libavcodec/nuv.c @@ -199,6 +199,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, case NUV_RTJPEG_IN_LZO: case NUV_RTJPEG: keyframe = !buf[2]; + if (c->width < 16 || c->height < 16) { + return AVERROR_INVALIDDATA; + } break; case NUV_COPY_LAST: keyframe = 0; From 44a1731011e87fbf4180d026aefb8bfe85d8c7dc Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sun, 11 Feb 2018 21:32:04 +0100 Subject: [PATCH 2106/2557] ivf: Support VP9 and AV1 as well --- libavformat/ivfenc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c index 1e57106993639..48186a890786c 100644 --- a/libavformat/ivfenc.c +++ b/libavformat/ivfenc.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "avformat.h" +#include "riff.h" #include "libavutil/intreadwrite.h" static int ivf_write_header(AVFormatContext *s) @@ -30,14 +31,17 @@ static int ivf_write_header(AVFormatContext *s) return AVERROR(EINVAL); } par = s->streams[0]->codecpar; - if (par->codec_type != AVMEDIA_TYPE_VIDEO || par->codec_id != AV_CODEC_ID_VP8) { - av_log(s, AV_LOG_ERROR, "Currently only VP8 is supported!\n"); + if (par->codec_type != AVMEDIA_TYPE_VIDEO || + !(par->codec_id == AV_CODEC_ID_AV1 || + par->codec_id == AV_CODEC_ID_VP8 || + par->codec_id == AV_CODEC_ID_VP9)) { + av_log(s, AV_LOG_ERROR, "Currently only AV1, VP8 and VP9 are supported!\n"); return AVERROR(EINVAL); } avio_write(pb, "DKIF", 4); avio_wl16(pb, 0); // version avio_wl16(pb, 32); // header length - avio_wl32(pb, par->codec_tag ? par->codec_tag : AV_RL32("VP80")); + avio_wl32(pb, par->codec_tag ? par->codec_tag : ff_codec_get_tag(ff_codec_bmp_tags, par->codec_id)); avio_wl16(pb, par->width); avio_wl16(pb, par->height); avio_wl32(pb, s->streams[0]->time_base.den); From c438899a706422b8362a13714580e988be4d638b Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Thu, 25 Aug 2016 17:28:17 +0200 Subject: [PATCH 2107/2557] Add AV1 video decoding support through libaom Signed-off-by: Diego Biurrun Signed-off-by: Luca Barbato --- Changelog | 1 + configure | 4 ++ doc/general.texi | 10 +++ libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 1 + libavcodec/libaom.c | 133 ++++++++++++++++++++++++++++++++++ libavcodec/libaom.h | 31 ++++++++ libavcodec/libaomdec.c | 160 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 342 insertions(+) create mode 100644 libavcodec/libaom.c create mode 100644 libavcodec/libaom.h create mode 100644 libavcodec/libaomdec.c diff --git a/Changelog b/Changelog index 51c3f85a28f96..0d20cd47df849 100644 --- a/Changelog +++ b/Changelog @@ -20,6 +20,7 @@ version : - Intel QSV-accelerated MJPEG encoding - NVIDIA CUVID-accelerated H.264 and HEVC decoding - Intel QSV-accelerated overlay filter +- AV1 Support through libaom version 12: diff --git a/configure b/configure index b91be3210284b..a43fb93cdf2ff 100755 --- a/configure +++ b/configure @@ -187,6 +187,7 @@ External library support: --enable-bzlib bzip2 compression [autodetect] --enable-frei0r video filtering plugins --enable-gnutls crypto + --enable-libaom AV1 video encoding/decoding --enable-libbs2b Bauer stereophonic-to-binaural DSP --enable-libcdio audio CD input --enable-libdc1394 IEEE 1394/Firewire camera input @@ -1349,6 +1350,7 @@ EXTERNAL_LIBRARY_LIST=" avxsynth frei0r gnutls + libaom libbs2b libdc1394 libdcadec @@ -2363,6 +2365,7 @@ avisynth_deps="LoadLibrary" avxsynth_deps="libdl" avisynth_demuxer_deps_any="avisynth avxsynth" avisynth_demuxer_select="riffdec" +libaom_av1_decoder_deps="libaom" libdcadec_decoder_deps="libdcadec" libfaac_encoder_deps="libfaac" libfaac_encoder_select="audio_frame_queue" @@ -4641,6 +4644,7 @@ enabled cuvid && require cuvid cuviddec.h cuvidCreateDecoder -lnvcuv enabled frei0r && require_header frei0r.h enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init && check_lib gmp gmp.h mpz_export -lgmp +enabled libaom && require_pkg_config libaom "aom >= 0.1.0" aom/aom_codec.h aom_codec_version enabled libbs2b && require_pkg_config libbs2b libbs2b bs2b.h bs2b_open enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new enabled libdcadec && require libdcadec libdcadec/dca_context.h dcadec_context_create -ldcadec diff --git a/doc/general.texi b/doc/general.texi index 0c92761a49cf8..e066b42187231 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -16,6 +16,14 @@ for more formats. None of them are used by default, their use has to be explicitly requested by passing the appropriate flags to @command{./configure}. +@section Alliance for Open Media libaom + +Libav can make use of the libaom library for AV1 decoding. + +Go to @url{http://aomedia.org/} and follow the instructions for +installing the library. Then pass @code{--enable-libaom} to configure to +enable it. + @section OpenCORE and VisualOn libraries Spun off Google Android sources, OpenCore, VisualOn and Fraunhofer @@ -617,6 +625,8 @@ following image formats are supported: @item Autodesk Animator Flic video @tab @tab X @item Autodesk RLE @tab @tab X @tab fourcc: AASC +@item AV1 @tab @tab E + @tab Supported through external library libaom @item AVS (Audio Video Standard) video @tab @tab X @tab Video encoding used by the Creature Shock game. @item Beam Software VB @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 99969ac779720..0b50a839bc878 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -687,6 +687,7 @@ OBJS-$(CONFIG_TAK_DEMUXER) += tak.o OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o # external codec libraries +OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o OBJS-$(CONFIG_LIBDCADEC_DECODER) += libdcadec.o dca.o OBJS-$(CONFIG_LIBFAAC_ENCODER) += libfaac.o OBJS-$(CONFIG_LIBFDK_AAC_DECODER) += libfdk-aacdec.o @@ -814,6 +815,7 @@ SKIPHEADERS-$(CONFIG_CUVID) += cuvid.h SKIPHEADERS-$(CONFIG_AMF) += amfenc.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h +SKIPHEADERS-$(CONFIG_LIBAOM) += libaom.h SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h SKIPHEADERS-$(CONFIG_LIBVPX) += libvpx.h SKIPHEADERS-$(CONFIG_NVENC) += nvenc.h diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index efde5a2b0e6b7..ec923cd5117af 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -421,6 +421,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (XSUB, xsub); /* external libraries */ + REGISTER_DECODER(LIBAOM_AV1, libaom_av1); REGISTER_DECODER(LIBDCADEC, libdcadec) REGISTER_ENCODER(LIBFAAC, libfaac); REGISTER_ENCDEC (LIBFDK_AAC, libfdk_aac); diff --git a/libavcodec/libaom.c b/libavcodec/libaom.c new file mode 100644 index 0000000000000..220b1bd245b6b --- /dev/null +++ b/libavcodec/libaom.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2013 Guillaume Martres + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libaom.h" + +#define HIGH_DEPTH(fmt) \ +case AOM_IMG_FMT_I ## fmt ## 16: \ + switch (depth) { \ + case 8: \ + return AV_PIX_FMT_YUV ## fmt ## P; \ + case 10: \ + return AV_PIX_FMT_YUV ## fmt ## P10; \ + case 12: \ + return AV_PIX_FMT_YUV ## fmt ## P12; \ + default: \ + return AV_PIX_FMT_NONE; \ + } + +enum AVPixelFormat ff_aom_imgfmt_to_pixfmt(aom_img_fmt_t img, int depth) +{ + switch (img) { + case AOM_IMG_FMT_RGB24: + return AV_PIX_FMT_RGB24; + case AOM_IMG_FMT_RGB565: + return AV_PIX_FMT_RGB565BE; + case AOM_IMG_FMT_RGB555: + return AV_PIX_FMT_RGB555BE; + case AOM_IMG_FMT_UYVY: + return AV_PIX_FMT_UYVY422; + case AOM_IMG_FMT_YUY2: + return AV_PIX_FMT_YUYV422; + case AOM_IMG_FMT_YVYU: + return AV_PIX_FMT_YVYU422; + case AOM_IMG_FMT_BGR24: + return AV_PIX_FMT_BGR24; + case AOM_IMG_FMT_ARGB: + return AV_PIX_FMT_ARGB; + case AOM_IMG_FMT_ARGB_LE: + return AV_PIX_FMT_BGRA; + case AOM_IMG_FMT_RGB565_LE: + return AV_PIX_FMT_RGB565LE; + case AOM_IMG_FMT_RGB555_LE: + return AV_PIX_FMT_RGB555LE; + case AOM_IMG_FMT_I420: + return AV_PIX_FMT_YUV420P; + case AOM_IMG_FMT_I422: + return AV_PIX_FMT_YUV422P; + case AOM_IMG_FMT_I444: + return AV_PIX_FMT_YUV444P; + case AOM_IMG_FMT_444A: + return AV_PIX_FMT_YUVA444P; + case AOM_IMG_FMT_I440: + return AV_PIX_FMT_YUV440P; + HIGH_DEPTH(420) + HIGH_DEPTH(422) + HIGH_DEPTH(444) + default: + return AV_PIX_FMT_NONE; + } +} + +#undef HIGH_DEPTH + +aom_img_fmt_t ff_aom_pixfmt_to_imgfmt(enum AVPixelFormat pix) +{ + switch (pix) { + case AV_PIX_FMT_RGB24: + return AOM_IMG_FMT_RGB24; + case AV_PIX_FMT_RGB565BE: + return AOM_IMG_FMT_RGB565; + case AV_PIX_FMT_RGB555BE: + return AOM_IMG_FMT_RGB555; + case AV_PIX_FMT_UYVY422: + return AOM_IMG_FMT_UYVY; + case AV_PIX_FMT_YUYV422: + return AOM_IMG_FMT_YUY2; + case AV_PIX_FMT_YVYU422: + return AOM_IMG_FMT_YVYU; + case AV_PIX_FMT_BGR24: + return AOM_IMG_FMT_BGR24; + case AV_PIX_FMT_ARGB: + return AOM_IMG_FMT_ARGB; + case AV_PIX_FMT_BGRA: + return AOM_IMG_FMT_ARGB_LE; + case AV_PIX_FMT_RGB565LE: + return AOM_IMG_FMT_RGB565_LE; + case AV_PIX_FMT_RGB555LE: + return AOM_IMG_FMT_RGB555_LE; + case AV_PIX_FMT_YUV420P: + return AOM_IMG_FMT_I420; + case AV_PIX_FMT_YUV422P: + return AOM_IMG_FMT_I422; + case AV_PIX_FMT_YUV444P: + return AOM_IMG_FMT_I444; + case AV_PIX_FMT_YUVA444P: + return AOM_IMG_FMT_444A; + case AV_PIX_FMT_YUV440P: + return AOM_IMG_FMT_I440; + case AV_PIX_FMT_YUV420P10: + return AOM_IMG_FMT_I42016; + case AV_PIX_FMT_YUV422P10: + return AOM_IMG_FMT_I42216; + case AV_PIX_FMT_YUV444P10: + return AOM_IMG_FMT_I44416; + case AV_PIX_FMT_YUV420P12: + return AOM_IMG_FMT_I42016; + case AV_PIX_FMT_YUV422P12: + return AOM_IMG_FMT_I42216; + case AV_PIX_FMT_YUV444P12: + return AOM_IMG_FMT_I44416; + default: + return AOM_IMG_FMT_NONE; + } +} diff --git a/libavcodec/libaom.h b/libavcodec/libaom.h new file mode 100644 index 0000000000000..d3d52f704ec62 --- /dev/null +++ b/libavcodec/libaom.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Guillaume Martres + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_LIBAOM_H +#define AVCODEC_LIBAOM_H + +#include + +#include "libavutil/pixfmt.h" + +enum AVPixelFormat ff_aom_imgfmt_to_pixfmt(aom_img_fmt_t img, int depth); +aom_img_fmt_t ff_aom_pixfmt_to_imgfmt(enum AVPixelFormat pix); + +#endif /* AVCODEC_LIBAOM_H */ diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c new file mode 100644 index 0000000000000..859c7729b62b8 --- /dev/null +++ b/libavcodec/libaomdec.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2010, Google, Inc. + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * AV1 decoder support via libaom + */ + +#include +#include + +#include "libavutil/common.h" +#include "libavutil/imgutils.h" + +#include "avcodec.h" +#include "internal.h" +#include "libaom.h" + +typedef struct AV1DecodeContext { + struct aom_codec_ctx decoder; +} AV1DecodeContext; + +static av_cold int aom_init(AVCodecContext *avctx) +{ + AV1DecodeContext *ctx = avctx->priv_data; + struct aom_codec_dec_cfg deccfg = { + /* token partitions+1 would be a decent choice */ + .threads = FFMIN(avctx->thread_count, 16) + }; + const struct aom_codec_iface *iface = &aom_codec_av1_dx_algo; + + av_log(avctx, AV_LOG_INFO, "%s\n", aom_codec_version_str()); + av_log(avctx, AV_LOG_VERBOSE, "%s\n", aom_codec_build_config()); + + if (aom_codec_dec_init(&ctx->decoder, iface, &deccfg, 0) != AOM_CODEC_OK) { + const char *error = aom_codec_error(&ctx->decoder); + av_log(avctx, AV_LOG_ERROR, "Failed to initialize decoder: %s\n", + error); + return AVERROR(EINVAL); + } + + return 0; +} + +static void image_copy_16_to_8(AVFrame *pic, struct aom_image *img) +{ + int i; + + for (i = 0; i < 3; i++) { + int w = img->d_w; + int h = img->d_h; + int x, y; + + if (i) { + w = (w + img->x_chroma_shift) >> img->x_chroma_shift; + h = (h + img->y_chroma_shift) >> img->y_chroma_shift; + } + + for (y = 0; y < h; y++) { + uint16_t *src = (uint16_t *)(img->planes[i] + y * img->stride[i]); + uint8_t *dst = pic->data[i] + y * pic->linesize[i]; + for (x = 0; x < w; x++) + *dst++ = *src++; + } + } +} + + +static int aom_decode(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + AV1DecodeContext *ctx = avctx->priv_data; + AVFrame *picture = data; + const void *iter = NULL; + struct aom_image *img; + int ret; + + if (aom_codec_decode(&ctx->decoder, avpkt->data, avpkt->size, NULL) != + AOM_CODEC_OK) { + const char *error = aom_codec_error(&ctx->decoder); + const char *detail = aom_codec_error_detail(&ctx->decoder); + + av_log(avctx, AV_LOG_ERROR, "Failed to decode frame: %s\n", error); + if (detail) + av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n", + detail); + return AVERROR_INVALIDDATA; + } + + if ((img = aom_codec_get_frame(&ctx->decoder, &iter))) { + avctx->pix_fmt = ff_aom_imgfmt_to_pixfmt(img->fmt, img->bit_depth); + if (avctx->pix_fmt == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (0x%02x %dbits)\n", + img->fmt, img->bit_depth); + return AVERROR_INVALIDDATA; + } + + if ((int)img->d_w != avctx->width || (int)img->d_h != avctx->height) { + av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d -> %dx%d\n", + avctx->width, avctx->height, img->d_w, img->d_h); + ret = ff_set_dimensions(avctx, img->d_w, img->d_h); + if (ret < 0) + return ret; + } + if ((ret = ff_get_buffer(avctx, picture, 0)) < 0) + return ret; + if ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) && img->bit_depth == 8) + image_copy_16_to_8(picture, img); + else + av_image_copy(picture->data, picture->linesize, (const uint8_t **)img->planes, + img->stride, avctx->pix_fmt, img->d_w, img->d_h); + switch (img->range) { + case AOM_CR_STUDIO_RANGE: + picture->color_range = AVCOL_RANGE_MPEG; + break; + case AOM_CR_FULL_RANGE: + picture->color_range = AVCOL_RANGE_JPEG; + break; + } + *got_frame = 1; + } + return avpkt->size; +} + +static av_cold int aom_free(AVCodecContext *avctx) +{ + AV1DecodeContext *ctx = avctx->priv_data; + aom_codec_destroy(&ctx->decoder); + return 0; +} + +AVCodec ff_libaom_av1_decoder = { + .name = "libaom-av1", + .long_name = NULL_IF_CONFIG_SMALL("libaom AV1"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AV1, + .priv_data_size = sizeof(AV1DecodeContext), + .init = aom_init, + .close = aom_free, + .decode = aom_decode, + .capabilities = AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_DR1, + .wrapper_name = "libaom", +}; From 936312d18c985335d8e90b04bb15b4227bce7b31 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Sat, 10 Mar 2018 23:43:42 -0800 Subject: [PATCH 2108/2557] avcodec/mediacodecdec: add debug logging around hw buffer lifecycle Some Android devices are very finicky about how quicky output buffers are returned back to the decoder, especially when they are associated with a Surface. This commit adds a new counter that keeps track of exactly how many hw output buffers are being retained by the user, along with DEBUG level logging that makes it easy to track the lifecycle of these buffers. Signed-off-by: Aman Gupta Signed-off-by: Matthieu Bouron --- libavcodec/mediacodec.c | 7 ++++--- libavcodec/mediacodecdec_common.c | 11 +++++++++++ libavcodec/mediacodecdec_common.h | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/libavcodec/mediacodec.c b/libavcodec/mediacodec.c index 3ddd303c975f3..b0aae43a879d0 100644 --- a/libavcodec/mediacodec.c +++ b/libavcodec/mediacodec.c @@ -92,9 +92,10 @@ int av_mediacodec_release_buffer(AVMediaCodecBuffer *buffer, int render) int released = atomic_fetch_add(&buffer->released, 1); if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) { - av_log(ctx->avctx, AV_LOG_TRACE, - "Releasing output buffer %zd ts=%"PRId64" render=%d\n", - buffer->index, buffer->pts, render); + atomic_fetch_sub(&ctx->hw_buffer_count, 1); + av_log(ctx->avctx, AV_LOG_DEBUG, + "Releasing output buffer %zd (%p) ts=%"PRId64" with render=%d [%d pending]\n", + buffer->index, buffer, buffer->pts, render, atomic_load(&ctx->hw_buffer_count)); return ff_AMediaCodec_releaseOutputBuffer(ctx->codec, buffer->index, render); } diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index 5064809cf6f52..2697af3d08851 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -179,6 +179,10 @@ static void mediacodec_buffer_release(void *opaque, uint8_t *data) int released = atomic_load(&buffer->released); if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) { + atomic_fetch_sub(&ctx->hw_buffer_count, 1); + av_log(ctx->avctx, AV_LOG_DEBUG, + "Releasing output buffer %zd (%p) ts=%"PRId64" on free() [%d pending]\n", + buffer->index, buffer, buffer->pts, atomic_load(&ctx->hw_buffer_count)); ff_AMediaCodec_releaseOutputBuffer(ctx->codec, buffer->index, 0); } @@ -246,6 +250,11 @@ FF_ENABLE_DEPRECATION_WARNINGS frame->data[3] = (uint8_t *)buffer; + atomic_fetch_add(&s->hw_buffer_count, 1); + av_log(avctx, AV_LOG_DEBUG, + "Wrapping output buffer %zd (%p) ts=%"PRId64" [%d pending]\n", + buffer->index, buffer, buffer->pts, atomic_load(&s->hw_buffer_count)); + return 0; fail: av_freep(buffer); @@ -429,6 +438,7 @@ static int mediacodec_dec_flush_codec(AVCodecContext *avctx, MediaCodecDecContex s->flushing = 0; s->eos = 0; atomic_fetch_add(&s->serial, 1); + atomic_init(&s->hw_buffer_count, 0); status = ff_AMediaCodec_flush(codec); if (status < 0) { @@ -454,6 +464,7 @@ int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s, s->avctx = avctx; atomic_init(&s->refcount, 1); + atomic_init(&s->hw_buffer_count, 0); atomic_init(&s->serial, 1); pix_fmt = ff_get_format(avctx, pix_fmts); diff --git a/libavcodec/mediacodecdec_common.h b/libavcodec/mediacodecdec_common.h index 3fd2412a650eb..4f3b4f9fa58b7 100644 --- a/libavcodec/mediacodecdec_common.h +++ b/libavcodec/mediacodecdec_common.h @@ -38,6 +38,7 @@ typedef struct MediaCodecDecContext { AVCodecContext *avctx; atomic_int refcount; + atomic_int hw_buffer_count; char *codec_name; From 41d7c4d3813b71d0feefb19c69f6a246ea2bdcee Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Mon, 12 Mar 2018 09:10:57 +0100 Subject: [PATCH 2109/2557] avcodec/mediacodecdec_common: make INFO_TRY_AGAIN trace messages more consistent Signed-off-by: Aman Gupta Signed-off-by: Matthieu Bouron --- libavcodec/mediacodecdec_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index 2697af3d08851..635ee73486d15 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -579,7 +579,7 @@ int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s, index = ff_AMediaCodec_dequeueInputBuffer(codec, input_dequeue_timeout_us); if (ff_AMediaCodec_infoTryAgainLater(codec, index)) { - av_log(avctx, AV_LOG_TRACE, "Failed to dequeue input buffer, try again later..\n"); + av_log(avctx, AV_LOG_TRACE, "No input buffer available, try again later\n"); break; } @@ -743,7 +743,7 @@ int ff_mediacodec_dec_receive(AVCodecContext *avctx, MediaCodecDecContext *s, "while draining remaining frames, output will probably lack frames\n", output_dequeue_timeout_us / 1000); } else { - av_log(avctx, AV_LOG_DEBUG, "No output buffer available, try again later\n"); + av_log(avctx, AV_LOG_TRACE, "No output buffer available, try again later\n"); } } else { av_log(avctx, AV_LOG_ERROR, "Failed to dequeue output buffer (status=%zd)\n", index); From 43778a501f1bfbceeddc8eaeea2ea2b3506beeda Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sun, 11 Feb 2018 21:33:25 +0100 Subject: [PATCH 2110/2557] Support AV1 encoding using libaom --- configure | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 2 +- libavcodec/avcodec.h | 4 + libavcodec/libaomenc.c | 583 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 590 insertions(+), 1 deletion(-) create mode 100644 libavcodec/libaomenc.c diff --git a/configure b/configure index a43fb93cdf2ff..42465edf94756 100755 --- a/configure +++ b/configure @@ -2366,6 +2366,7 @@ avxsynth_deps="libdl" avisynth_demuxer_deps_any="avisynth avxsynth" avisynth_demuxer_select="riffdec" libaom_av1_decoder_deps="libaom" +libaom_av1_encoder_deps="libaom" libdcadec_decoder_deps="libdcadec" libfaac_encoder_deps="libfaac" libfaac_encoder_select="audio_frame_queue" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 0b50a839bc878..ea0c9dceae07f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -688,6 +688,7 @@ OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o # external codec libraries OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o +OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o libaom.o OBJS-$(CONFIG_LIBDCADEC_DECODER) += libdcadec.o dca.o OBJS-$(CONFIG_LIBFAAC_ENCODER) += libfaac.o OBJS-$(CONFIG_LIBFDK_AAC_DECODER) += libfdk-aacdec.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index ec923cd5117af..4aee65762ea91 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -421,7 +421,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (XSUB, xsub); /* external libraries */ - REGISTER_DECODER(LIBAOM_AV1, libaom_av1); + REGISTER_ENCDEC (LIBAOM_AV1, libaom_av1); REGISTER_DECODER(LIBDCADEC, libdcadec) REGISTER_ENCODER(LIBFAAC, libfaac); REGISTER_ENCDEC (LIBFDK_AAC, libfdk_aac); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 03a3d5bd6d0c4..ac0915328ca9c 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2551,6 +2551,10 @@ typedef struct AVCodecContext { #define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3 #define FF_PROFILE_HEVC_REXT 4 +#define FF_PROFILE_AV1_0 0 +#define FF_PROFILE_AV1_1 1 +#define FF_PROFILE_AV1_2 2 + /** * level * - encoding: Set by user. diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c new file mode 100644 index 0000000000000..94b3ddd326551 --- /dev/null +++ b/libavcodec/libaomenc.c @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2010, Google, Inc. + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define AOM_DISABLE_CTRL_TYPECHECKS 1 +#include +#include + +#include "libavutil/base64.h" +#include "libavutil/common.h" +#include "libavutil/mathematics.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avcodec.h" +#include "internal.h" +#include "libaom.h" + +/* + * Portion of struct aom_codec_cx_pkt from aom_encoder.h. + * One encoded frame returned from the library. + */ +struct FrameListData { + void *buf; /* compressed data buffer */ + size_t sz; /* length of compressed data */ + int64_t pts; /* time stamp to show frame + * (in timebase units) */ + unsigned long duration; /* duration to show frame + * (in timebase units) */ + uint32_t flags; /* flags for this frame */ + struct FrameListData *next; +}; + +typedef struct AOMEncoderContext { + AVClass *class; + struct aom_codec_ctx encoder; + struct aom_image rawimg; + struct aom_fixed_buf twopass_stats; + struct FrameListData *coded_frame_list; + int cpu_used; + int auto_alt_ref; + int lag_in_frames; + int error_resilient; + int crf; + int static_thresh; + int drop_threshold; + int noise_sensitivity; +} AOMContext; + +static const char *const ctlidstr[] = { + [AOME_SET_CPUUSED] = "AOME_SET_CPUUSED", + [AOME_SET_CQ_LEVEL] = "AOME_SET_CQ_LEVEL", + [AOME_SET_ENABLEAUTOALTREF] = "AOME_SET_ENABLEAUTOALTREF", + [AOME_SET_STATIC_THRESHOLD] = "AOME_SET_STATIC_THRESHOLD", +}; + +static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc) +{ + AOMContext *ctx = avctx->priv_data; + const char *error = aom_codec_error(&ctx->encoder); + const char *detail = aom_codec_error_detail(&ctx->encoder); + + av_log(avctx, AV_LOG_ERROR, "%s: %s\n", desc, error); + if (detail) + av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n", detail); +} + +static av_cold void dump_enc_cfg(AVCodecContext *avctx, + const struct aom_codec_enc_cfg *cfg) +{ + int width = -30; + int level = AV_LOG_DEBUG; + + av_log(avctx, level, "aom_codec_enc_cfg\n"); + av_log(avctx, level, "generic settings\n" + " %*s%u\n %*s%u\n %*s%u\n %*s%u\n %*s%u\n" + " %*s{%u/%u}\n %*s%u\n %*s%d\n %*s%u\n", + width, "g_usage:", cfg->g_usage, + width, "g_threads:", cfg->g_threads, + width, "g_profile:", cfg->g_profile, + width, "g_w:", cfg->g_w, + width, "g_h:", cfg->g_h, + width, "g_timebase:", cfg->g_timebase.num, cfg->g_timebase.den, + width, "g_error_resilient:", cfg->g_error_resilient, + width, "g_pass:", cfg->g_pass, + width, "g_lag_in_frames:", cfg->g_lag_in_frames); + av_log(avctx, level, "rate control settings\n" + " %*s%u\n %*s%d\n %*s%p(%zu)\n %*s%u\n", + width, "rc_dropframe_thresh:", cfg->rc_dropframe_thresh, + width, "rc_end_usage:", cfg->rc_end_usage, + width, "rc_twopass_stats_in:", cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz, + width, "rc_target_bitrate:", cfg->rc_target_bitrate); + av_log(avctx, level, "quantizer settings\n" + " %*s%u\n %*s%u\n", + width, "rc_min_quantizer:", cfg->rc_min_quantizer, + width, "rc_max_quantizer:", cfg->rc_max_quantizer); + av_log(avctx, level, "bitrate tolerance\n" + " %*s%u\n %*s%u\n", + width, "rc_undershoot_pct:", cfg->rc_undershoot_pct, + width, "rc_overshoot_pct:", cfg->rc_overshoot_pct); + av_log(avctx, level, "decoder buffer model\n" + " %*s%u\n %*s%u\n %*s%u\n", + width, "rc_buf_sz:", cfg->rc_buf_sz, + width, "rc_buf_initial_sz:", cfg->rc_buf_initial_sz, + width, "rc_buf_optimal_sz:", cfg->rc_buf_optimal_sz); + av_log(avctx, level, "2 pass rate control settings\n" + " %*s%u\n %*s%u\n %*s%u\n", + width, "rc_2pass_vbr_bias_pct:", cfg->rc_2pass_vbr_bias_pct, + width, "rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct, + width, "rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct); + av_log(avctx, level, "keyframing settings\n" + " %*s%d\n %*s%u\n %*s%u\n", + width, "kf_mode:", cfg->kf_mode, + width, "kf_min_dist:", cfg->kf_min_dist, + width, "kf_max_dist:", cfg->kf_max_dist); + av_log(avctx, level, "\n"); +} + +static void coded_frame_add(void *list, struct FrameListData *cx_frame) +{ + struct FrameListData **p = list; + + while (*p) + p = &(*p)->next; + *p = cx_frame; + cx_frame->next = NULL; +} + +static av_cold void free_coded_frame(struct FrameListData *cx_frame) +{ + av_freep(&cx_frame->buf); + av_freep(&cx_frame); +} + +static av_cold void free_frame_list(struct FrameListData *list) +{ + struct FrameListData *p = list; + + while (p) { + list = list->next; + free_coded_frame(p); + p = list; + } +} + +static av_cold int codecctl_int(AVCodecContext *avctx, + enum aome_enc_control_id id, int val) +{ + AOMContext *ctx = avctx->priv_data; + char buf[80]; + int width = -30; + int res; + + snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]); + av_log(avctx, AV_LOG_DEBUG, " %*s%d\n", width, buf, val); + + res = aom_codec_control(&ctx->encoder, id, val); + if (res != AOM_CODEC_OK) { + snprintf(buf, sizeof(buf), "Failed to set %s codec control", + ctlidstr[id]); + log_encoder_error(avctx, buf); + return AVERROR(EINVAL); + } + + return 0; +} + +static av_cold int aom_free(AVCodecContext *avctx) +{ + AOMContext *ctx = avctx->priv_data; + + aom_codec_destroy(&ctx->encoder); + av_freep(&ctx->twopass_stats.buf); + av_freep(&avctx->stats_out); + free_frame_list(ctx->coded_frame_list); + return 0; +} + +static av_cold int aom_init(AVCodecContext *avctx) +{ + AOMContext *ctx = avctx->priv_data; + struct aom_codec_enc_cfg enccfg = { 0 }; + AVCPBProperties *cpb_props; + int res; + const struct aom_codec_iface *iface = &aom_codec_av1_cx_algo; + + av_log(avctx, AV_LOG_INFO, "%s\n", aom_codec_version_str()); + av_log(avctx, AV_LOG_VERBOSE, "%s\n", aom_codec_build_config()); + + if ((res = aom_codec_enc_config_default(iface, &enccfg, 0)) != AOM_CODEC_OK) { + av_log(avctx, AV_LOG_ERROR, "Failed to get config: %s\n", + aom_codec_err_to_string(res)); + return AVERROR(EINVAL); + } + dump_enc_cfg(avctx, &enccfg); + + enccfg.g_w = avctx->width; + enccfg.g_h = avctx->height; + enccfg.g_timebase.num = avctx->time_base.num; + enccfg.g_timebase.den = avctx->time_base.den; + enccfg.g_threads = avctx->thread_count; + + if (ctx->lag_in_frames >= 0) + enccfg.g_lag_in_frames = ctx->lag_in_frames; + + if (avctx->flags & AV_CODEC_FLAG_PASS1) + enccfg.g_pass = AOM_RC_FIRST_PASS; + else if (avctx->flags & AV_CODEC_FLAG_PASS2) + enccfg.g_pass = AOM_RC_LAST_PASS; + else + enccfg.g_pass = AOM_RC_ONE_PASS; + + if (!avctx->bit_rate) + avctx->bit_rate = enccfg.rc_target_bitrate * 1000; + else + enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000, + AV_ROUND_NEAR_INF); + + if (ctx->crf) + enccfg.rc_end_usage = AOM_CQ; + else if (avctx->rc_min_rate == avctx->rc_max_rate && + avctx->rc_min_rate == avctx->bit_rate) + enccfg.rc_end_usage = AOM_CBR; + + if (avctx->qmin > 0) + enccfg.rc_min_quantizer = avctx->qmin; + if (avctx->qmax > 0) + enccfg.rc_max_quantizer = avctx->qmax; + + enccfg.rc_dropframe_thresh = ctx->drop_threshold; + + // 0-100 (0 => CBR, 100 => VBR) + enccfg.rc_2pass_vbr_bias_pct = round(avctx->qcompress * 100); + enccfg.rc_2pass_vbr_minsection_pct = + avctx->rc_min_rate * 100LL / avctx->bit_rate; + if (avctx->rc_max_rate) + enccfg.rc_2pass_vbr_maxsection_pct = + avctx->rc_max_rate * 100LL / avctx->bit_rate; + + if (avctx->rc_buffer_size) + enccfg.rc_buf_sz = + avctx->rc_buffer_size * 1000LL / avctx->bit_rate; + if (avctx->rc_initial_buffer_occupancy) + enccfg.rc_buf_initial_sz = + avctx->rc_initial_buffer_occupancy * 1000LL / avctx->bit_rate; + enccfg.rc_buf_optimal_sz = enccfg.rc_buf_sz * 5 / 6; + + // _enc_init() will balk if kf_min_dist differs from max w/AOM_KF_AUTO + if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size) + enccfg.kf_min_dist = avctx->keyint_min; + if (avctx->gop_size >= 0) + enccfg.kf_max_dist = avctx->gop_size; + + if (enccfg.g_pass == AOM_RC_FIRST_PASS) + enccfg.g_lag_in_frames = 0; + else if (enccfg.g_pass == AOM_RC_LAST_PASS) { + int decode_size, ret; + + if (!avctx->stats_in) { + av_log(avctx, AV_LOG_ERROR, "No stats file for second pass\n"); + return AVERROR_INVALIDDATA; + } + + ctx->twopass_stats.sz = strlen(avctx->stats_in) * 3 / 4; + ret = av_reallocp(&ctx->twopass_stats.buf, ctx->twopass_stats.sz); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "Stat buffer alloc (%zu bytes) failed\n", + ctx->twopass_stats.sz); + return ret; + } + decode_size = av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in, + ctx->twopass_stats.sz); + if (decode_size < 0) { + av_log(avctx, AV_LOG_ERROR, "Stat buffer decode failed\n"); + return AVERROR_INVALIDDATA; + } + + ctx->twopass_stats.sz = decode_size; + enccfg.rc_twopass_stats_in = ctx->twopass_stats; + } + + /* 0-3: For non-zero values the encoder increasingly optimizes for reduced + * complexity playback on low powered devices at the expense of encode + * quality. */ + if (avctx->profile != FF_PROFILE_UNKNOWN) + enccfg.g_profile = avctx->profile; + else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) + avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_0; + else { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + if (desc->comp[0].depth < 12) + avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_1; + else + avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_2; + } + + + enccfg.g_error_resilient = ctx->error_resilient; + + dump_enc_cfg(avctx, &enccfg); + /* Construct Encoder Context */ + res = aom_codec_enc_init(&ctx->encoder, iface, &enccfg, 0); + if (res != AOM_CODEC_OK) { + log_encoder_error(avctx, "Failed to initialize encoder"); + return AVERROR(EINVAL); + } + + // codec control failures are currently treated only as warnings + av_log(avctx, AV_LOG_DEBUG, "aom_codec_control\n"); + if (ctx->cpu_used != INT_MIN) + codecctl_int(avctx, AOME_SET_CPUUSED, ctx->cpu_used); + if (ctx->auto_alt_ref >= 0) + codecctl_int(avctx, AOME_SET_ENABLEAUTOALTREF, ctx->auto_alt_ref); + + codecctl_int(avctx, AOME_SET_STATIC_THRESHOLD, ctx->static_thresh); + codecctl_int(avctx, AOME_SET_CQ_LEVEL, ctx->crf); + + // provide dummy value to initialize wrapper, values will be updated each _encode() + aom_img_wrap(&ctx->rawimg, ff_aom_pixfmt_to_imgfmt(avctx->pix_fmt), + avctx->width, avctx->height, 1, (unsigned char *)1); + + cpb_props = ff_add_cpb_side_data(avctx); + if (!cpb_props) + return AVERROR(ENOMEM); + + if (enccfg.rc_end_usage == AOM_CBR || + enccfg.g_pass != AOM_RC_ONE_PASS) { + cpb_props->max_bitrate = avctx->rc_max_rate; + cpb_props->min_bitrate = avctx->rc_min_rate; + cpb_props->avg_bitrate = avctx->bit_rate; + } + cpb_props->buffer_size = avctx->rc_buffer_size; + + return 0; +} + +static inline void cx_pktcpy(struct FrameListData *dst, + const struct aom_codec_cx_pkt *src) +{ + dst->pts = src->data.frame.pts; + dst->duration = src->data.frame.duration; + dst->flags = src->data.frame.flags; + dst->sz = src->data.frame.sz; + dst->buf = src->data.frame.buf; +} + +/** + * Store coded frame information in format suitable for return from encode2(). + * + * Write information from @a cx_frame to @a pkt + * @return packet data size on success + * @return a negative AVERROR on error + */ +static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, + AVPacket *pkt) +{ + int ret = ff_alloc_packet(pkt, cx_frame->sz); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "Error getting output packet of size %zu.\n", cx_frame->sz); + return ret; + } + memcpy(pkt->data, cx_frame->buf, pkt->size); + pkt->pts = pkt->dts = cx_frame->pts; + + if (!!(cx_frame->flags & AOM_FRAME_IS_KEY)) + pkt->flags |= AV_PKT_FLAG_KEY; + return pkt->size; +} + +/** + * Queue multiple output frames from the encoder, returning the front-most. + * In cases where aom_codec_get_cx_data() returns more than 1 frame append + * the frame queue. Return the head frame if available. + * @return Stored frame size + * @return AVERROR(EINVAL) on output size error + * @return AVERROR(ENOMEM) on coded frame queue data allocation error + */ +static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out) +{ + AOMContext *ctx = avctx->priv_data; + const struct aom_codec_cx_pkt *pkt; + const void *iter = NULL; + int size = 0; + + if (ctx->coded_frame_list) { + struct FrameListData *cx_frame = ctx->coded_frame_list; + /* return the leading frame if we've already begun queueing */ + size = storeframe(avctx, cx_frame, pkt_out); + if (size < 0) + return size; + ctx->coded_frame_list = cx_frame->next; + free_coded_frame(cx_frame); + } + + /* consume all available output from the encoder before returning. buffers + * are only good through the next aom_codec call */ + while ((pkt = aom_codec_get_cx_data(&ctx->encoder, &iter))) { + switch (pkt->kind) { + case AOM_CODEC_CX_FRAME_PKT: + if (!size) { + struct FrameListData cx_frame; + + /* avoid storing the frame when the list is empty and we haven't yet + * provided a frame for output */ + assert(!ctx->coded_frame_list); + cx_pktcpy(&cx_frame, pkt); + size = storeframe(avctx, &cx_frame, pkt_out); + if (size < 0) + return size; + } else { + struct FrameListData *cx_frame = + av_malloc(sizeof(struct FrameListData)); + + if (!cx_frame) { + av_log(avctx, AV_LOG_ERROR, + "Frame queue element alloc failed\n"); + return AVERROR(ENOMEM); + } + cx_pktcpy(cx_frame, pkt); + cx_frame->buf = av_malloc(cx_frame->sz); + + if (!cx_frame->buf) { + av_log(avctx, AV_LOG_ERROR, + "Data buffer alloc (%zu bytes) failed\n", + cx_frame->sz); + av_freep(&cx_frame); + return AVERROR(ENOMEM); + } + memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz); + coded_frame_add(&ctx->coded_frame_list, cx_frame); + } + break; + case AOM_CODEC_STATS_PKT: + { + struct aom_fixed_buf *stats = &ctx->twopass_stats; + int err; + if ((err = av_reallocp(&stats->buf, + stats->sz + + pkt->data.twopass_stats.sz)) < 0) { + stats->sz = 0; + av_log(avctx, AV_LOG_ERROR, "Stat buffer realloc failed\n"); + return err; + } + memcpy((uint8_t *)stats->buf + stats->sz, + pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz); + stats->sz += pkt->data.twopass_stats.sz; + break; + } + case AOM_CODEC_PSNR_PKT: // FIXME add support for AV_CODEC_FLAG_PSNR + case AOM_CODEC_CUSTOM_PKT: + // ignore unsupported/unrecognized packet types + break; + } + } + + return size; +} + +static int aom_encode(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + AOMContext *ctx = avctx->priv_data; + struct aom_image *rawimg = NULL; + int64_t timestamp = 0; + int res, coded_size; + aom_enc_frame_flags_t flags = 0; + + if (frame) { + rawimg = &ctx->rawimg; + rawimg->planes[AOM_PLANE_Y] = frame->data[0]; + rawimg->planes[AOM_PLANE_U] = frame->data[1]; + rawimg->planes[AOM_PLANE_V] = frame->data[2]; + rawimg->stride[AOM_PLANE_Y] = frame->linesize[0]; + rawimg->stride[AOM_PLANE_U] = frame->linesize[1]; + rawimg->stride[AOM_PLANE_V] = frame->linesize[2]; + timestamp = frame->pts; + switch (frame->color_range) { + case AVCOL_RANGE_MPEG: + rawimg->range = AOM_CR_STUDIO_RANGE; + break; + case AVCOL_RANGE_JPEG: + rawimg->range = AOM_CR_FULL_RANGE; + break; + } + + if (frame->pict_type == AV_PICTURE_TYPE_I) + flags |= AOM_EFLAG_FORCE_KF; + } + + res = aom_codec_encode(&ctx->encoder, rawimg, timestamp, + avctx->ticks_per_frame, flags); + if (res != AOM_CODEC_OK) { + log_encoder_error(avctx, "Error encoding frame"); + return AVERROR_INVALIDDATA; + } + coded_size = queue_frames(avctx, pkt); + + if (!frame && avctx->flags & AV_CODEC_FLAG_PASS1) { + size_t b64_size = AV_BASE64_SIZE(ctx->twopass_stats.sz); + + avctx->stats_out = av_malloc(b64_size); + if (!avctx->stats_out) { + av_log(avctx, AV_LOG_ERROR, "Stat buffer alloc (%zu bytes) failed\n", + b64_size); + return AVERROR(ENOMEM); + } + av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf, + ctx->twopass_stats.sz); + } + + *got_packet = !!coded_size; + return 0; +} + +#define OFFSET(x) offsetof(AOMContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, INT_MIN, INT_MAX, VE}, + { "auto-alt-ref", "Enable use of alternate reference " + "frames (2-pass only)", OFFSET(auto_alt_ref), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE}, + { "lag-in-frames", "Number of frames to look ahead at for " + "alternate reference frame selection", OFFSET(lag_in_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE}, + { "error-resilience", "Error resilience configuration", OFFSET(error_resilient), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, VE, "er"}, + { "default", "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {.i64 = AOM_ERROR_RESILIENT_DEFAULT}, 0, 0, VE, "er"}, + { "partitions", "The frame partitions are independently decodable " + "by the bool decoder, meaning that partitions can be decoded even " + "though earlier partitions have been lost. Note that intra predicition" + " is still done over the partition boundary.", 0, AV_OPT_TYPE_CONST, {.i64 = AOM_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"}, + { "crf", "Select the quality for constant quality mode", offsetof(AOMContext, crf), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 63, VE }, + { "static-thresh", "A change threshold on blocks below which they will be skipped by the encoder", OFFSET(static_thresh), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, + { "drop-threshold", "Frame drop threshold", offsetof(AOMContext, drop_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, VE }, + { "noise-sensitivity", "Noise sensitivity", OFFSET(noise_sensitivity), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 4, VE}, + { NULL } +}; + +static const AVCodecDefault defaults[] = { + { "qmin", "-1" }, + { "qmax", "-1" }, + { "g", "-1" }, + { "keyint_min", "-1" }, + { NULL }, +}; + +static const AVClass class_aom = { + .class_name = "libaom encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libaom_av1_encoder = { + .name = "libaom-av1", + .long_name = NULL_IF_CONFIG_SMALL("libaom AV1"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AV1, + .priv_data_size = sizeof(AOMContext), + .init = aom_init, + .encode2 = aom_encode, + .close = aom_free, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_EXPERIMENTAL, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .priv_class = &class_aom, + .defaults = defaults, + .wrapper_name = "libaom", +}; From 9c249110ea974ce213840fde5ee5a3d842fa088d Mon Sep 17 00:00:00 2001 From: Vishwanath Dixit Date: Mon, 12 Mar 2018 23:17:58 +0800 Subject: [PATCH 2111/2557] avformat/hlsenc: fix for zero EXTINF tag duration This is the fix for bug https://trac.ffmpeg.org/ticket/7073 Tested-by: Brainiarc7 Reviewed-by: Steven Liu --- libavformat/hlsenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 08fe0aa7a04c3..7d9512b6648f3 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -2501,7 +2501,7 @@ static int hls_init(AVFormatContext *s) /* Get one video stream to reference for split segments * so use the first video stream index. */ if ((vs->has_video == 1) && (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) { - vs->reference_stream_index = j; + vs->reference_stream_index = vs->streams[j]->index; } vs->has_subtitle += vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE; } From 68f5384804fa86af2737f7b08799c9ca2c306db4 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 11 Mar 2018 18:02:12 +0100 Subject: [PATCH 2112/2557] ffprobe: fix infinite loop in subtitle decoding Fixes a regression since 2a88ebd096f3c748a2d99ed1b60b22879b3c567c which caused an infinite loop in the subtitle decoding. Fixes ticket #6796. Signed-off-by: Marton Balint --- fftools/ffprobe.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 967adbe30cd8f..a4ac6972a215a 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2275,7 +2275,8 @@ static av_always_inline int process_frame(WriterContext *w, break; case AVMEDIA_TYPE_SUBTITLE: - ret = avcodec_decode_subtitle2(dec_ctx, &sub, &got_frame, pkt); + if (*packet_new) + ret = avcodec_decode_subtitle2(dec_ctx, &sub, &got_frame, pkt); *packet_new = 0; break; default: From af7e953a595690caf4127957f42d639641035411 Mon Sep 17 00:00:00 2001 From: Yusuke Nakamura Date: Tue, 13 Feb 2018 01:45:05 +0900 Subject: [PATCH 2113/2557] h264_mp4toannexb_bsf: Fix start code size of parameter sets. Any parameter set shall have start code of at least 4 byte size. Signed-off-by: Michael Niedermayer --- libavcodec/h264_mp4toannexb_bsf.c | 22 ++++++++++---------- tests/ref/fate/h264-bsf-mp4toannexb | 2 +- tests/ref/fate/h264_mp4toannexb_ticket2991 | 22 ++++++++++---------- tests/ref/fate/h264_mp4toannexb_ticket5927 | 10 ++++----- tests/ref/fate/h264_mp4toannexb_ticket5927_2 | 10 ++++----- tests/ref/fate/segment-mp4-to-ts | 4 ++-- 6 files changed, 35 insertions(+), 35 deletions(-) diff --git a/libavcodec/h264_mp4toannexb_bsf.c b/libavcodec/h264_mp4toannexb_bsf.c index 163d0f59ceb5c..292d10643307b 100644 --- a/libavcodec/h264_mp4toannexb_bsf.c +++ b/libavcodec/h264_mp4toannexb_bsf.c @@ -39,21 +39,21 @@ typedef struct H264BSFContext { static int alloc_and_copy(AVPacket *out, const uint8_t *sps_pps, uint32_t sps_pps_size, - const uint8_t *in, uint32_t in_size) + const uint8_t *in, uint32_t in_size, int ps) { uint32_t offset = out->size; - uint8_t nal_header_size = offset ? 3 : 4; + uint8_t start_code_size = offset == 0 || ps ? 4 : 3; int err; - err = av_grow_packet(out, sps_pps_size + in_size + nal_header_size); + err = av_grow_packet(out, sps_pps_size + in_size + start_code_size); if (err < 0) return err; if (sps_pps) memcpy(out->data + offset, sps_pps, sps_pps_size); - memcpy(out->data + sps_pps_size + nal_header_size + offset, in, in_size); - if (!offset) { - AV_WB32(out->data + sps_pps_size, 1); + memcpy(out->data + sps_pps_size + start_code_size + offset, in, in_size); + if (start_code_size == 4) { + AV_WB32(out->data + offset + sps_pps_size, 1); } else { (out->data + offset + sps_pps_size)[0] = (out->data + offset + sps_pps_size)[1] = 0; @@ -221,7 +221,7 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) if ((ret = alloc_and_copy(out, ctx->par_out->extradata + s->sps_offset, s->pps_offset != -1 ? s->pps_offset : ctx->par_out->extradata_size - s->sps_offset, - buf, nal_size)) < 0) + buf, nal_size, 1)) < 0) goto fail; s->idr_sps_seen = 1; goto next_nal; @@ -239,21 +239,21 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) if (s->new_idr && unit_type == 5 && !s->idr_sps_seen && !s->idr_pps_seen) { if ((ret=alloc_and_copy(out, ctx->par_out->extradata, ctx->par_out->extradata_size, - buf, nal_size)) < 0) + buf, nal_size, 1)) < 0) goto fail; s->new_idr = 0; /* if only SPS has been seen, also insert PPS */ } else if (s->new_idr && unit_type == 5 && s->idr_sps_seen && !s->idr_pps_seen) { if (s->pps_offset == -1) { av_log(ctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n"); - if ((ret = alloc_and_copy(out, NULL, 0, buf, nal_size)) < 0) + if ((ret = alloc_and_copy(out, NULL, 0, buf, nal_size, 0)) < 0) goto fail; } else if ((ret = alloc_and_copy(out, ctx->par_out->extradata + s->pps_offset, ctx->par_out->extradata_size - s->pps_offset, - buf, nal_size)) < 0) + buf, nal_size, 1)) < 0) goto fail; } else { - if ((ret=alloc_and_copy(out, NULL, 0, buf, nal_size)) < 0) + if ((ret=alloc_and_copy(out, NULL, 0, buf, nal_size, unit_type == 7 || unit_type == 8)) < 0) goto fail; if (!s->new_idr && unit_type == 1) { s->new_idr = 1; diff --git a/tests/ref/fate/h264-bsf-mp4toannexb b/tests/ref/fate/h264-bsf-mp4toannexb index 2049f39701e32..7cd086a268cd1 100644 --- a/tests/ref/fate/h264-bsf-mp4toannexb +++ b/tests/ref/fate/h264-bsf-mp4toannexb @@ -1 +1 @@ -5f04c27cc6ee8625fe2405fb0f7da9a3 +f340e7ca9a46d437af4e96f6c8de221c diff --git a/tests/ref/fate/h264_mp4toannexb_ticket2991 b/tests/ref/fate/h264_mp4toannexb_ticket2991 index 76bdf3cae79c7..3245ef442c62e 100644 --- a/tests/ref/fate/h264_mp4toannexb_ticket2991 +++ b/tests/ref/fate/h264_mp4toannexb_ticket2991 @@ -1,12 +1,12 @@ -05d66e60ab22ee004720e0051af0fe74 *tests/data/fate/h264_mp4toannexb_ticket2991.h264 -1985815 tests/data/fate/h264_mp4toannexb_ticket2991.h264 -#extradata 0: 47, 0x3a590d55 +dba672c154b41414cf26aae967c27eef *tests/data/fate/h264_mp4toannexb_ticket2991.h264 +1985823 tests/data/fate/h264_mp4toannexb_ticket2991.h264 +#extradata 0: 48, 0x47ae0d55 #tb 0: 1/1200000 #media_type 0: video #codec_id 0: h264 #dimensions 0: 1280x720 #sar 0: 3/4 -0, 0, 0, 48000, 37126, 0xb020184c +0, 0, 0, 48000, 37127, 0xc125184c 0, 48000, 48000, 40040, 6920, 0x8512361a, F=0x0 0, 88040, 88040, 40040, 7550, 0x1bc56ed4, F=0x0 0, 128081, 128081, 40040, 8752, 0xb8c6f0a1, F=0x0 @@ -21,7 +21,7 @@ 0, 488444, 488444, 40040, 11234, 0x83cbd9fd, F=0x0 0, 528485, 528485, 40040, 17616, 0xfdf95104, F=0x0 0, 568525, 568525, 40040, 10689, 0x9633d32b, F=0x0 -0, 608566, 608566, 40040, 45291, 0x543c2cf6 +0, 608566, 608566, 40040, 45292, 0x66dd2cf6 0, 648606, 648606, 40040, 20837, 0x051abfab, F=0x0 0, 688646, 688646, 40040, 21418, 0xe2a59d70, F=0x0 0, 728687, 728687, 40040, 15643, 0x15cf2cec, F=0x0 @@ -36,7 +36,7 @@ 0, 1089050, 1089050, 40040, 13130, 0xcbb6bb8e, F=0x0 0, 1129091, 1129091, 40040, 16180, 0x5d188a7a, F=0x0 0, 1169131, 1169131, 40040, 14961, 0x9ff2f463, F=0x0 -0, 1209172, 1209172, 40040, 54296, 0xe6ec30ed +0, 1209172, 1209172, 40040, 54297, 0xf98d30ed 0, 1249212, 1249212, 40040, 11500, 0x8c4852c9, F=0x0 0, 1289252, 1289252, 40040, 12065, 0xfb7954c3, F=0x0 0, 1329293, 1329293, 40040, 12532, 0xf0a935d3, F=0x0 @@ -51,7 +51,7 @@ 0, 1689656, 1689656, 40040, 13250, 0xfed0deb8, F=0x0 0, 1729697, 1729697, 40040, 13360, 0xbf92d476, F=0x0 0, 1769737, 1769737, 40040, 11749, 0x3041eaf1, F=0x0 -0, 1809778, 1809778, 40040, 23997, 0xdbe6d5c4 +0, 1809778, 1809778, 40040, 23998, 0xee87d5c4 0, 1849818, 1849818, 40040, 16065, 0xe8f715b7, F=0x0 0, 1889858, 1889858, 40040, 16441, 0x0a4e060f, F=0x0 0, 1929899, 1929899, 40040, 17395, 0xa8edecc2, F=0x0 @@ -66,7 +66,7 @@ 0, 2290262, 2290262, 40040, 13748, 0xed26aeb4, F=0x0 0, 2330303, 2330303, 40040, 15092, 0x3c983538, F=0x0 0, 2370343, 2370343, 40040, 14636, 0x9b278a6c, F=0x0 -0, 2410384, 2410384, 40040, 29134, 0xf784be18 +0, 2410384, 2410384, 40040, 29135, 0x0a34be18 0, 2450424, 2450424, 40040, 10232, 0x5408e15b, F=0x0 0, 2490464, 2490464, 40040, 9769, 0xc93cb7f9, F=0x0 0, 2530505, 2530505, 40040, 14454, 0x45230dbe, F=0x0 @@ -81,7 +81,7 @@ 0, 2890868, 2890868, 40040, 14801, 0x40bae016, F=0x0 0, 2930909, 2930909, 40040, 17303, 0x9ce1fd31, F=0x0 0, 2970949, 2970949, 40040, 17678, 0x9bd66141, F=0x0 -0, 3010990, 3010990, 40040, 48672, 0x3215ce46 +0, 3010990, 3010990, 40040, 48673, 0x44b6ce46 0, 3051030, 3051030, 40040, 11894, 0x12e1fece, F=0x0 0, 3091070, 3091070, 40040, 16514, 0xc57aed05, F=0x0 0, 3131111, 3131111, 40040, 13044, 0x61914fa0, F=0x0 @@ -96,7 +96,7 @@ 0, 3491474, 3491474, 40040, 12208, 0x81a587c0, F=0x0 0, 3531515, 3531515, 40040, 14709, 0x5dffbe04, F=0x0 0, 3571555, 3571555, 40040, 14390, 0xbfd1e041, F=0x0 -0, 3611596, 3611596, 40040, 37236, 0xe7f924b1 +0, 3611596, 3611596, 40040, 37237, 0xfa9a24b1 0, 3651636, 3651636, 40040, 14056, 0x24714c7c, F=0x0 0, 3691676, 3691676, 40040, 19438, 0x0c50dcd5, F=0x0 0, 3731717, 3731717, 40040, 21728, 0x7eea4a11, F=0x0 @@ -111,7 +111,7 @@ 0, 4092080, 4092080, 40040, 16878, 0x98efbae2, F=0x0 0, 4132121, 4132121, 40040, 14685, 0x1bf78d65, F=0x0 0, 4172161, 4172161, 40040, 13127, 0x0b91881d, F=0x0 -0, 4212202, 4212202, 40040, 29390, 0xf6a5ed6b +0, 4212202, 4212202, 40040, 29391, 0x0955ed6b 0, 4252242, 4252242, 40040, 12576, 0xe9845ded, F=0x0 0, 4292282, 4292282, 40040, 12599, 0x96a79ab8, F=0x0 0, 4332323, 4332323, 40040, 16134, 0xb4c36d3f, F=0x0 diff --git a/tests/ref/fate/h264_mp4toannexb_ticket5927 b/tests/ref/fate/h264_mp4toannexb_ticket5927 index 95e35c4d802f2..006ea398fd6e0 100644 --- a/tests/ref/fate/h264_mp4toannexb_ticket5927 +++ b/tests/ref/fate/h264_mp4toannexb_ticket5927 @@ -1,12 +1,12 @@ -a3b02fd09392e01619cebc959d4d9ff2 *tests/data/fate/h264_mp4toannexb_ticket5927.h264 -595583 tests/data/fate/h264_mp4toannexb_ticket5927.h264 -#extradata 0: 33, 0x84fe08f8 +562487bfea635cdadbc23d390322b589 *tests/data/fate/h264_mp4toannexb_ticket5927.h264 +595585 tests/data/fate/h264_mp4toannexb_ticket5927.h264 +#extradata 0: 34, 0x8df608f8 #tb 0: 1/1200000 #media_type 0: video #codec_id 0: h264 #dimensions 0: 1920x1080 #sar 0: 0/1 -0, -48000, -9223372036854775808, 48000, 247993, 0x1ce821ea +0, -48000, -9223372036854775808, 48000, 247994, 0x2e1e21ea 0, 0, -9223372036854775808, 48000, 43354, 0xa05dca6f, F=0x0 0, 48000, -9223372036854775808, 48000, 11423, 0x5e8086dd, F=0x0 0, 96000, -9223372036854775808, 48000, 50798, 0x145fbe4f, F=0x0 @@ -18,4 +18,4 @@ a3b02fd09392e01619cebc959d4d9ff2 *tests/data/fate/h264_mp4toannexb_ticket5927.h2 0, 384000, -9223372036854775808, 48000, 54483, 0xefead99f, F=0x0 0, 432000, -9223372036854775808, 48000, 13705, 0x23cd27e8, F=0x0 0, 480000, -9223372036854775808, 48000, 22308, 0x4093b5af, F=0x0 -0, 528000, -9223372036854775808, 48000, 6369, 0x858b2aa1 +0, 528000, -9223372036854775808, 48000, 6370, 0x96c12aa1 diff --git a/tests/ref/fate/h264_mp4toannexb_ticket5927_2 b/tests/ref/fate/h264_mp4toannexb_ticket5927_2 index 8db6a7e54a7d7..51432b153533f 100644 --- a/tests/ref/fate/h264_mp4toannexb_ticket5927_2 +++ b/tests/ref/fate/h264_mp4toannexb_ticket5927_2 @@ -1,12 +1,12 @@ -a3b02fd09392e01619cebc959d4d9ff2 *tests/data/fate/h264_mp4toannexb_ticket5927_2.h264 -595583 tests/data/fate/h264_mp4toannexb_ticket5927_2.h264 -#extradata 0: 33, 0x84fe08f8 +562487bfea635cdadbc23d390322b589 *tests/data/fate/h264_mp4toannexb_ticket5927_2.h264 +595585 tests/data/fate/h264_mp4toannexb_ticket5927_2.h264 +#extradata 0: 34, 0x8df608f8 #tb 0: 1/1200000 #media_type 0: video #codec_id 0: h264 #dimensions 0: 1920x1080 #sar 0: 0/1 -0, -48000, -9223372036854775808, 48000, 247993, 0x1ce821ea +0, -48000, -9223372036854775808, 48000, 247994, 0x2e1e21ea 0, 0, -9223372036854775808, 48000, 43354, 0xa05dca6f, F=0x0 0, 48000, -9223372036854775808, 48000, 11423, 0x5e8086dd, F=0x0 0, 96000, -9223372036854775808, 48000, 50798, 0x145fbe4f, F=0x0 @@ -18,4 +18,4 @@ a3b02fd09392e01619cebc959d4d9ff2 *tests/data/fate/h264_mp4toannexb_ticket5927_2. 0, 384000, -9223372036854775808, 48000, 54483, 0xefead99f, F=0x0 0, 432000, -9223372036854775808, 48000, 13705, 0x23cd27e8, F=0x0 0, 480000, -9223372036854775808, 48000, 22308, 0x4093b5af, F=0x0 -0, 528000, -9223372036854775808, 48000, 6369, 0x858b2aa1 +0, 528000, -9223372036854775808, 48000, 6370, 0x96c12aa1 diff --git a/tests/ref/fate/segment-mp4-to-ts b/tests/ref/fate/segment-mp4-to-ts index 847c1a297db90..b5accb60f7268 100644 --- a/tests/ref/fate/segment-mp4-to-ts +++ b/tests/ref/fate/segment-mp4-to-ts @@ -1,10 +1,10 @@ -#extradata 0: 50, 0x4f1b0df9 +#extradata 0: 51, 0x5d140df9 #tb 0: 1/90000 #media_type 0: video #codec_id 0: h264 #dimensions 0: 640x360 #sar 0: 1/1 -0, -7200, 0, 0, 22630, 0x9b109541, S=1, 1, 0x00e000e0 +0, -7200, 0, 0, 22631, 0x9cec9541, S=1, 1, 0x00e000e0 0, -3600, 14400, 0, 4021, 0xbf7cdb02, F=0x0, S=1, 1, 0x00e000e0 0, 0, 7200, 0, 1096, 0x4f162690, F=0x0, S=1, 1, 0x00e000e0 0, 3600, 3600, 0, 687, 0x00394b95, F=0x0, S=1, 1, 0x00e000e0 From 040b28aeccce8bc3c2e109f8e0ea7f0ed4d3af08 Mon Sep 17 00:00:00 2001 From: "Philipp M. Scholl" Date: Sat, 10 Mar 2018 15:50:06 +0100 Subject: [PATCH 2114/2557] avformat/pcm: decrease delay when reading PCM streams. Thanks for the discussion. Here's the next version, now with /25 and removed ff_log2(). The blocksize of the PCM decoder is hard-coded. This creates unnecessary delay when reading low-rate (<100Hz) streams. This creates issues when multiplexing multiple streams, since other inputs are only opened/read after a low-rate input block was completely read. This patch decreases the blocksize for low-rate inputs, so approximately a block is read every 40ms. This decreases the startup delay when multiplexing inputs with different rates. Signed-off-by: Philipp M. Scholl Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer --- libavformat/pcm.c | 13 +++++++++--- tests/ref/seek/lavf-alaw | 42 +++++++++++++++++++-------------------- tests/ref/seek/lavf-mulaw | 42 +++++++++++++++++++-------------------- 3 files changed, 52 insertions(+), 45 deletions(-) diff --git a/libavformat/pcm.c b/libavformat/pcm.c index 806f91b6b135e..767bbd045a994 100644 --- a/libavformat/pcm.c +++ b/libavformat/pcm.c @@ -28,13 +28,20 @@ int ff_pcm_read_packet(AVFormatContext *s, AVPacket *pkt) { + AVCodecParameters *par = s->streams[0]->codecpar; int ret, size; - size= RAW_SAMPLES*s->streams[0]->codecpar->block_align; - if (size <= 0) + if (par->block_align <= 0) return AVERROR(EINVAL); - ret= av_get_packet(s->pb, pkt, size); + /* + * Compute read size to complete a read every 62ms. + * Clamp to RAW_SAMPLES if larger. + */ + size = FFMAX(par->sample_rate/25, 1); + size = FFMIN(size, RAW_SAMPLES) * par->block_align; + + ret = av_get_packet(s->pb, pkt, size); pkt->flags &= ~AV_PKT_FLAG_CORRUPT; pkt->stream_index = 0; diff --git a/tests/ref/seek/lavf-alaw b/tests/ref/seek/lavf-alaw index 4b1f8fbc02e11..8d517fa2bbdcb 100644 --- a/tests/ref/seek/lavf-alaw +++ b/tests/ref/seek/lavf-alaw @@ -1,53 +1,53 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 1.894150 pts: 1.894150 pos: 41766 size: 1024 +ret: 0 st: 0 flags:1 dts: 1.894150 pts: 1.894150 pos: 41766 size: 882 ret: 0 st: 0 flags:0 ts: 0.788345 -ret: 0 st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos: 17383 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos: 17383 size: 882 ret: 0 st: 0 flags:1 ts:-0.317506 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st:-1 flags:0 ts: 2.576668 ret:-EOF ret: 0 st:-1 flags:1 ts: 1.470835 -ret: 0 st: 0 flags:1 dts: 1.470839 pts: 1.470839 pos: 32432 size: 1024 +ret: 0 st: 0 flags:1 dts: 1.470839 pts: 1.470839 pos: 32432 size: 882 ret: 0 st: 0 flags:0 ts: 0.364989 -ret: 0 st: 0 flags:1 dts: 0.364989 pts: 0.364989 pos: 8048 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.364989 pts: 0.364989 pos: 8048 size: 882 ret: 0 st: 0 flags:1 ts:-0.740816 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st:-1 flags:0 ts: 2.153336 ret:-EOF ret: 0 st:-1 flags:1 ts: 1.047503 -ret: 0 st: 0 flags:1 dts: 1.047483 pts: 1.047483 pos: 23097 size: 1024 +ret: 0 st: 0 flags:1 dts: 1.047483 pts: 1.047483 pos: 23097 size: 882 ret: 0 st: 0 flags:0 ts:-0.058322 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st: 0 flags:1 ts: 2.835828 ret:-EOF ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 0 flags:1 dts: 1.730023 pts: 1.730023 pos: 38147 size: 1024 +ret: 0 st: 0 flags:1 dts: 1.730023 pts: 1.730023 pos: 38147 size: 882 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.624172 pts: 0.624172 pos: 13763 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.624172 pts: 0.624172 pos: 13763 size: 882 ret: 0 st: 0 flags:0 ts:-0.481678 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st: 0 flags:1 ts: 2.412517 ret:-EOF ret: 0 st:-1 flags:0 ts: 1.306672 -ret: 0 st: 0 flags:1 dts: 1.306667 pts: 1.306667 pos: 28812 size: 1024 +ret: 0 st: 0 flags:1 dts: 1.306667 pts: 1.306667 pos: 28812 size: 882 ret: 0 st:-1 flags:1 ts: 0.200839 -ret: 0 st: 0 flags:1 dts: 0.200816 pts: 0.200816 pos: 4428 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.200816 pts: 0.200816 pos: 4428 size: 882 ret: 0 st: 0 flags:0 ts:-0.904989 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st: 0 flags:1 ts: 1.989161 ret: 0 st: 0 flags:1 dts: 1.989161 pts: 1.989161 pos: 43861 size: 239 ret: 0 st:-1 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 0.883356 pts: 0.883356 pos: 19478 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.883356 pts: 0.883356 pos: 19478 size: 882 ret: 0 st:-1 flags:1 ts:-0.222493 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st: 0 flags:0 ts: 2.671655 ret:-EOF ret: 0 st: 0 flags:1 ts: 1.565850 -ret: 0 st: 0 flags:1 dts: 1.565850 pts: 1.565850 pos: 34527 size: 1024 +ret: 0 st: 0 flags:1 dts: 1.565850 pts: 1.565850 pos: 34527 size: 882 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.460000 pts: 0.460000 pos: 10143 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.460000 pts: 0.460000 pos: 10143 size: 882 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 diff --git a/tests/ref/seek/lavf-mulaw b/tests/ref/seek/lavf-mulaw index 4b1f8fbc02e11..8d517fa2bbdcb 100644 --- a/tests/ref/seek/lavf-mulaw +++ b/tests/ref/seek/lavf-mulaw @@ -1,53 +1,53 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 1.894150 pts: 1.894150 pos: 41766 size: 1024 +ret: 0 st: 0 flags:1 dts: 1.894150 pts: 1.894150 pos: 41766 size: 882 ret: 0 st: 0 flags:0 ts: 0.788345 -ret: 0 st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos: 17383 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos: 17383 size: 882 ret: 0 st: 0 flags:1 ts:-0.317506 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st:-1 flags:0 ts: 2.576668 ret:-EOF ret: 0 st:-1 flags:1 ts: 1.470835 -ret: 0 st: 0 flags:1 dts: 1.470839 pts: 1.470839 pos: 32432 size: 1024 +ret: 0 st: 0 flags:1 dts: 1.470839 pts: 1.470839 pos: 32432 size: 882 ret: 0 st: 0 flags:0 ts: 0.364989 -ret: 0 st: 0 flags:1 dts: 0.364989 pts: 0.364989 pos: 8048 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.364989 pts: 0.364989 pos: 8048 size: 882 ret: 0 st: 0 flags:1 ts:-0.740816 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st:-1 flags:0 ts: 2.153336 ret:-EOF ret: 0 st:-1 flags:1 ts: 1.047503 -ret: 0 st: 0 flags:1 dts: 1.047483 pts: 1.047483 pos: 23097 size: 1024 +ret: 0 st: 0 flags:1 dts: 1.047483 pts: 1.047483 pos: 23097 size: 882 ret: 0 st: 0 flags:0 ts:-0.058322 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st: 0 flags:1 ts: 2.835828 ret:-EOF ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 0 flags:1 dts: 1.730023 pts: 1.730023 pos: 38147 size: 1024 +ret: 0 st: 0 flags:1 dts: 1.730023 pts: 1.730023 pos: 38147 size: 882 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.624172 pts: 0.624172 pos: 13763 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.624172 pts: 0.624172 pos: 13763 size: 882 ret: 0 st: 0 flags:0 ts:-0.481678 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st: 0 flags:1 ts: 2.412517 ret:-EOF ret: 0 st:-1 flags:0 ts: 1.306672 -ret: 0 st: 0 flags:1 dts: 1.306667 pts: 1.306667 pos: 28812 size: 1024 +ret: 0 st: 0 flags:1 dts: 1.306667 pts: 1.306667 pos: 28812 size: 882 ret: 0 st:-1 flags:1 ts: 0.200839 -ret: 0 st: 0 flags:1 dts: 0.200816 pts: 0.200816 pos: 4428 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.200816 pts: 0.200816 pos: 4428 size: 882 ret: 0 st: 0 flags:0 ts:-0.904989 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st: 0 flags:1 ts: 1.989161 ret: 0 st: 0 flags:1 dts: 1.989161 pts: 1.989161 pos: 43861 size: 239 ret: 0 st:-1 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 0.883356 pts: 0.883356 pos: 19478 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.883356 pts: 0.883356 pos: 19478 size: 882 ret: 0 st:-1 flags:1 ts:-0.222493 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st: 0 flags:0 ts: 2.671655 ret:-EOF ret: 0 st: 0 flags:1 ts: 1.565850 -ret: 0 st: 0 flags:1 dts: 1.565850 pts: 1.565850 pos: 34527 size: 1024 +ret: 0 st: 0 flags:1 dts: 1.565850 pts: 1.565850 pos: 34527 size: 882 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.460000 pts: 0.460000 pos: 10143 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.460000 pts: 0.460000 pos: 10143 size: 882 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 1024 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 From 688060fbb7233d9212a92ce171e3b94784f95ca1 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Mon, 12 Mar 2018 23:31:22 +0000 Subject: [PATCH 2115/2557] vc2enc: properly promote operations to 64 bits On Windows machines, the UL suffix still means 32 bits. The only parts that need 64 bits are (1ULL << (m + 32)) and (t*qf + qf). Hence, use the proper ULL suffix for the former and just increase the type of the qf constant for the latter. No overflows can happen as long as these are done in 64 bits and the quantization table doesn't change. Signed-off-by: Rostislav Pehlivanov --- libavcodec/vc2enc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c index 2e480ba8d0feb..d0101e01e4309 100644 --- a/libavcodec/vc2enc.c +++ b/libavcodec/vc2enc.c @@ -1163,14 +1163,14 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx) goto alloc_fail; for (i = 0; i < 116; i++) { - const uint32_t qf = ff_dirac_qscale_tab[i]; - const int m = av_log2(qf); - const uint32_t t = (1UL << (m + 32)) / qf; - const uint32_t r = (t*qf + qf) & ((1UL << 32) - 1); + const uint64_t qf = ff_dirac_qscale_tab[i]; + const uint32_t m = av_log2(qf); + const uint32_t t = (1ULL << (m + 32)) / qf; + const uint32_t r = (t*qf + qf) & UINT32_MAX; if (!(qf & (qf - 1))) { s->qmagic_lut[i][0] = 0xFFFFFFFF; s->qmagic_lut[i][1] = 0xFFFFFFFF; - } else if (r <= 1UL << m) { + } else if (r <= 1 << m) { s->qmagic_lut[i][0] = t + 1; s->qmagic_lut[i][1] = 0; } else { From 847190ebd99ffd57dc89bd568a33bf2d5c424129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 13 Mar 2018 00:13:55 +0200 Subject: [PATCH 2116/2557] configure: Don't assume an aligned stack on clang on windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we'd enable a 16 byte aligned stack, clang/llvm would also assume that alignment everywhere and produce code that strictly requires it. That would require adding realignment (via attribute_align_arg) on every single public library function or enable -mstackrealign (which does the same on every single function). Also relatedly; the parameter currently tested (-mllvm -stack-alignment=16) hasn't actually been supported for quite some time; current clang versions use -mstack-alignment=16 for the same. Actually testing for that parameter would be a different change though, since it has a real risk of changing behaviour on any other platform where clang is used. Signed-off-by: Martin Storsjö --- configure | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 42465edf94756..95e60064401e1 100755 --- a/configure +++ b/configure @@ -4960,7 +4960,16 @@ elif enabled gcc; then elif enabled llvm_gcc; then check_cflags -mllvm -stack-alignment=16 elif enabled clang; then - check_cflags -mllvm -stack-alignment=16 + if [ "$target_os" = "mingw32" -o "$target_os" = "win32" ] && enabled x86_32; then + # Clang doesn't support maintaining alignment without assuming the + # same alignment in every function. If 16 byte alignment would be + # enabled, one would also have to either add attribute_align_arg on + # every single entry point into the libraries or enable -mstackrealign + # (doing stack realignment in every single function). + disable aligned_stack + else + check_cflags -mllvm -stack-alignment=16 + fi check_cflags -Qunused-arguments check_cflags -Werror=implicit-function-declaration check_cflags -Werror=missing-prototypes From f869e54d228d43adb3b1e0026a48273befe443eb Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 11 Mar 2018 19:15:56 +0100 Subject: [PATCH 2117/2557] avcodec/hap : move parse_section_header to hap.c in order to be use by new bsf filter --- libavcodec/hap.c | 22 ++++++++++++++++++++++ libavcodec/hap.h | 6 ++++++ libavcodec/hapdec.c | 33 ++++----------------------------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/libavcodec/hap.c b/libavcodec/hap.c index 5b3af5e1d0f49..1a330c9c9b3cc 100644 --- a/libavcodec/hap.c +++ b/libavcodec/hap.c @@ -53,3 +53,25 @@ av_cold void ff_hap_free_context(HapContext *ctx) av_freep(&ctx->chunks); av_freep(&ctx->chunk_results); } + +int ff_hap_parse_section_header(GetByteContext *gbc, int *section_size, + enum HapSectionType *section_type) +{ + if (bytestream2_get_bytes_left(gbc) < 4) + return AVERROR_INVALIDDATA; + + *section_size = bytestream2_get_le24(gbc); + *section_type = bytestream2_get_byte(gbc); + + if (*section_size == 0) { + if (bytestream2_get_bytes_left(gbc) < 4) + return AVERROR_INVALIDDATA; + + *section_size = bytestream2_get_le32(gbc); + } + + if (*section_size > bytestream2_get_bytes_left(gbc) || *section_size < 0) + return AVERROR_INVALIDDATA; + else + return 0; +} diff --git a/libavcodec/hap.h b/libavcodec/hap.h index 74455f3dd9d6d..bbeed11e32984 100644 --- a/libavcodec/hap.h +++ b/libavcodec/hap.h @@ -103,4 +103,10 @@ int ff_hap_set_chunk_count(HapContext *ctx, int count, int first_in_frame); */ av_cold void ff_hap_free_context(HapContext *ctx); +/* The first three bytes are the size of the section past the header, or zero + * if the length is stored in the next long word. The fourth byte in the first + * long word indicates the type of the current section. */ +int ff_hap_parse_section_header(GetByteContext *gbc, int *section_size, + enum HapSectionType *section_type); + #endif /* AVCODEC_HAP_H */ diff --git a/libavcodec/hapdec.c b/libavcodec/hapdec.c index 8fd4aa962c6cf..8c845770cf3d5 100644 --- a/libavcodec/hapdec.c +++ b/libavcodec/hapdec.c @@ -43,31 +43,6 @@ #include "texturedsp.h" #include "thread.h" -/* The first three bytes are the size of the section past the header, or zero - * if the length is stored in the next long word. The fourth byte in the first - * long word indicates the type of the current section. */ -static int parse_section_header(GetByteContext *gbc, int *section_size, - enum HapSectionType *section_type) -{ - if (bytestream2_get_bytes_left(gbc) < 4) - return AVERROR_INVALIDDATA; - - *section_size = bytestream2_get_le24(gbc); - *section_type = bytestream2_get_byte(gbc); - - if (*section_size == 0) { - if (bytestream2_get_bytes_left(gbc) < 4) - return AVERROR_INVALIDDATA; - - *section_size = bytestream2_get_le32(gbc); - } - - if (*section_size > bytestream2_get_bytes_left(gbc) || *section_size < 0) - return AVERROR_INVALIDDATA; - else - return 0; -} - static int hap_parse_decode_instructions(HapContext *ctx, int size) { GetByteContext *gbc = &ctx->gbc; @@ -78,7 +53,7 @@ static int hap_parse_decode_instructions(HapContext *ctx, int size) while (size > 0) { int stream_remaining = bytestream2_get_bytes_left(gbc); - ret = parse_section_header(gbc, §ion_size, §ion_type); + ret = ff_hap_parse_section_header(gbc, §ion_size, §ion_type); if (ret != 0) return ret; @@ -159,7 +134,7 @@ static int hap_parse_frame_header(AVCodecContext *avctx) const char *compressorstr; int i, ret; - ret = parse_section_header(gbc, &ctx->texture_section_size, §ion_type); + ret = ff_hap_parse_section_header(gbc, &ctx->texture_section_size, §ion_type); if (ret != 0) return ret; @@ -190,7 +165,7 @@ static int hap_parse_frame_header(AVCodecContext *avctx) } break; case HAP_COMP_COMPLEX: - ret = parse_section_header(gbc, §ion_size, §ion_type); + ret = ff_hap_parse_section_header(gbc, §ion_size, §ion_type); if (ret == 0 && section_type != HAP_ST_DECODE_INSTRUCTIONS) ret = AVERROR_INVALIDDATA; if (ret == 0) @@ -342,7 +317,7 @@ static int hap_decode(AVCodecContext *avctx, void *data, /* check for multi texture header */ if (ctx->texture_count == 2) { - ret = parse_section_header(&ctx->gbc, §ion_size, §ion_type); + ret = ff_hap_parse_section_header(&ctx->gbc, §ion_size, §ion_type); if (ret != 0) return ret; if ((section_type & 0x0F) != 0x0D) { From 7b0cb2e032d38b914a98dedc82c5262c14eeccb7 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 11 Mar 2018 19:16:09 +0100 Subject: [PATCH 2118/2557] avcodec/hapqa_extract_bsf : add new bsf filter convert HapQA data to HAPQ or HAPAlphaOnly by copying the corresponding texture --- Changelog | 1 + doc/bitstream_filters.texi | 25 ++++++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/hapqa_extract_bsf.c | 135 +++++++++++++++++++++++++++++++++ 5 files changed, 163 insertions(+) create mode 100644 libavcodec/hapqa_extract_bsf.c diff --git a/Changelog b/Changelog index c1b9df46bc715..7969b414c4777 100644 --- a/Changelog +++ b/Changelog @@ -46,6 +46,7 @@ version : They can be found at http://git.videolan.org/?p=ffmpeg/nv-codec-headers.git - native SBC encoder and decoder - drmeter audio filter +- hapqa_extract bitstream filter version 3.4: diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index b7ea54932227b..aac4705be47c9 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -93,6 +93,31 @@ When this option is enabled, the long-term headers are removed from the bitstream after extraction. @end table +@section hapqa_extract + +Extract Rgb or Alpha part of an HAPQA file, without recompression, in order to create an HAPQ or an HAPAlphaOnly file. + +@table @option +@item texture +Specifies the texture to keep. + +@table @option +@item color +@item alpha +@end table + +@end table + +Convert HAPQA to HAPQ +@example +ffmpeg -i hapqa_inputfile.mov -c copy -bsf:v hapqa_extract=texture=color -tag:v HapY -metadata:s:v:0 encoder="HAPQ" hapq_file.mov +@end example + +Convert HAPQA to HAPAlphaOnly +@example +ffmpeg -i hapqa_inputfile.mov -c copy -bsf:v hapqa_extract=texture=alpha -tag:v HapA -metadata:s:v:0 encoder="HAPAlpha Only" hapalphaonly_file.mov +@end example + @section h264_metadata Modify metadata embedded in an H.264 stream. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index ff6c9f8b2cf76..0984455ec4221 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1043,6 +1043,7 @@ OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \ OBJS-$(CONFIG_H264_METADATA_BSF) += h264_metadata_bsf.o OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o OBJS-$(CONFIG_H264_REDUNDANT_PPS_BSF) += h264_redundant_pps_bsf.o +OBJS-$(CONFIG_HAPQA_EXTRACT_BSF) += hapqa_extract_bsf.o hap.o OBJS-$(CONFIG_HEVC_METADATA_BSF) += h265_metadata_bsf.o OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 338ef8251bf81..68e652286d920 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -32,6 +32,7 @@ extern const AVBitStreamFilter ff_extract_extradata_bsf; extern const AVBitStreamFilter ff_h264_metadata_bsf; extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf; extern const AVBitStreamFilter ff_h264_redundant_pps_bsf; +extern const AVBitStreamFilter ff_hapqa_extract_bsf; extern const AVBitStreamFilter ff_hevc_metadata_bsf; extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf; extern const AVBitStreamFilter ff_imx_dump_header_bsf; diff --git a/libavcodec/hapqa_extract_bsf.c b/libavcodec/hapqa_extract_bsf.c new file mode 100644 index 0000000000000..45fe9fbe8f483 --- /dev/null +++ b/libavcodec/hapqa_extract_bsf.c @@ -0,0 +1,135 @@ +/* + * HAPQA extract bitstream filter + * Copyright (c) 2017 Jokyo Images + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * HAPQA extract bitstream filter + * extract one of the two textures of the HAQA + */ + +#include "avcodec.h" +#include "bsf.h" +#include "bytestream.h" +#include "hap.h" + +typedef struct HapqaExtractContext { + const AVClass *class; + int texture;/* index of the texture to keep (0 for rgb or 1 for alpha) */ +} HapqaExtractContext; + +static int check_texture(HapqaExtractContext *ctx, int section_type) { + if (((ctx->texture == 0)&&((section_type & 0x0F) == 0x0F)) || /* HapQ texture and rgb extract */ + ((ctx->texture == 1)&&((section_type & 0x0F) == 0x01))) /* HapAlphaOnly texture and alpha extract */ + { + return 1; /* the texture is the one to keep */ + } else { + return 0; + } +} + +static int hapqa_extract(AVBSFContext *bsf, AVPacket *out) +{ + HapqaExtractContext *ctx = bsf->priv_data; + GetByteContext gbc; + int section_size; + enum HapSectionType section_type; + int start_section_size; + int target_packet_size = 0; + AVPacket *in; + int ret = 0; + + ret = ff_bsf_get_packet(bsf, &in); + if (ret < 0) + return ret; + + bytestream2_init(&gbc, in->data, in->size); + ret = ff_hap_parse_section_header(&gbc, §ion_size, §ion_type); + if (ret != 0) + goto fail; + + if ((section_type & 0x0F) != 0x0D) { + av_log(bsf, AV_LOG_ERROR, "Invalid section type for HAPQA %#04x.\n", section_type & 0x0F); + goto fail; + } + + start_section_size = 4; + + bytestream2_seek(&gbc, start_section_size, SEEK_SET);/* go to start of the first texture */ + + ret = ff_hap_parse_section_header(&gbc, §ion_size, §ion_type); + if (ret != 0) + goto fail; + + target_packet_size = section_size + 4; + + if (check_texture(ctx, section_type) == 0) { /* the texture is not the one to keep */ + start_section_size += 4 + section_size; + bytestream2_seek(&gbc, start_section_size, SEEK_SET);/* go to start of the second texture */ + ret = ff_hap_parse_section_header(&gbc, §ion_size, §ion_type); + if (ret != 0) + goto fail; + + target_packet_size = section_size + 4; + + if (check_texture(ctx, section_type) == 0){ /* the second texture is not the one to keep */ + av_log(bsf, AV_LOG_ERROR, "No valid texture found.\n"); + goto fail; + } + } + + av_packet_move_ref(out, in); + out->data += start_section_size; + out->size = target_packet_size; + +fail: + if (ret < 0) + av_packet_unref(out); + av_packet_free(&in); + return ret; +} + +static const enum AVCodecID codec_ids[] = { + AV_CODEC_ID_HAP, AV_CODEC_ID_NONE, +}; + +#define OFFSET(x) offsetof(HapqaExtractContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "texture", "texture to keep", OFFSET(texture), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "texture" }, + { "color", "keep HapQ texture", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "texture" }, + { "alpha", "keep HapAlphaOnly texture", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "texture" }, + { NULL }, +}; + +static const AVClass hapqa_extract_class = { + .class_name = "hapqa_extract_bsf", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_MAJOR, +}; + +const AVBitStreamFilter ff_hapqa_extract_bsf = { + .name = "hapqa_extract", + .filter = hapqa_extract, + .priv_data_size = sizeof(HapqaExtractContext), + .priv_class = &hapqa_extract_class, + .codec_ids = codec_ids, +}; From 414c0e27a981f0fdcb91cc4856fc0ce81d2da877 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 11 Mar 2018 19:22:54 +0100 Subject: [PATCH 2119/2557] fate/hap : move decoding test to a separate file --- tests/Makefile | 1 + tests/fate/hap.mak | 29 +++++++++++++++++++++++++++++ tests/fate/video.mak | 30 ------------------------------ 3 files changed, 30 insertions(+), 30 deletions(-) create mode 100644 tests/fate/hap.mak diff --git a/tests/Makefile b/tests/Makefile index f1ac610454480..6074ac748e07c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -129,6 +129,7 @@ include $(SRC_PATH)/tests/fate/flvenc.mak include $(SRC_PATH)/tests/fate/gapless.mak include $(SRC_PATH)/tests/fate/gif.mak include $(SRC_PATH)/tests/fate/h264.mak +include $(SRC_PATH)/tests/fate/hap.mak include $(SRC_PATH)/tests/fate/hevc.mak include $(SRC_PATH)/tests/fate/id3v2.mak include $(SRC_PATH)/tests/fate/image.mak diff --git a/tests/fate/hap.mak b/tests/fate/hap.mak new file mode 100644 index 0000000000000..b48123a3cd353 --- /dev/null +++ b/tests/fate/hap.mak @@ -0,0 +1,29 @@ +FATE_HAP += fate-hap1 +fate-hap1: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hap1.mov + +FATE_HAP += fate-hap5 +fate-hap5: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hap5.mov + +FATE_HAP += fate-hapy +fate-hapy: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hapy.mov + +FATE_HAP += fate-hap-chunk +fate-hap-chunk: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hapy-12-chunks.mov + +FATE_HAP += fate-hapqa-nosnappy-127x71 +fate-hapqa-nosnappy-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_NoSnappy_127x1.mov + +FATE_HAP += fate-hapqa-snappy1-127x71 +fate-hapqa-snappy1-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_Snappy_1chunk_127x1.mov + +FATE_HAP += fate-hapqa-snappy16-127x71 +fate-hapqa-snappy16-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_Snappy_16chunk_127x1.mov + +FATE_HAP += fate-hap-alpha-only-nosnappy-128x72 +fate-hap-alpha-only-nosnappy-128x72: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HapAlphaOnly_NoSnappy_128x72.mov -pix_fmt gray8 + +FATE_HAP += fate-hap-alpha-only-snappy-127x71 +fate-hap-alpha-only-snappy-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HapAlphaOnly_snappy1chunk_127x71.mov -pix_fmt gray8 + +FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, HAP) += $(FATE_HAP) +fate-hap: $(FATE_HAP) diff --git a/tests/fate/video.mak b/tests/fate/video.mak index e7817d3d13afe..43c3432c95498 100644 --- a/tests/fate/video.mak +++ b/tests/fate/video.mak @@ -171,36 +171,6 @@ fate-id-cin-video: CMD = framecrc -i $(TARGET_SAMPLES)/idcin/idlog-2MB.cin -pix_ FATE_VIDEO-$(call ENCDEC, ROQ PGMYUV, ROQ IMAGE2) += fate-idroq-video-encode fate-idroq-video-encode: CMD = md5 -f image2 -c:v pgmyuv -i $(TARGET_SAMPLES)/ffmpeg-synthetic/vsynth1/%02d.pgm -r 30 -sws_flags +bitexact -vf pad=512:512:80:112 -f roq -t 0.2 -FATE_HAP += fate-hap1 -fate-hap1: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hap1.mov - -FATE_HAP += fate-hap5 -fate-hap5: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hap5.mov - -FATE_HAP += fate-hapy -fate-hapy: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hapy.mov - -FATE_HAP += fate-hap-chunk -fate-hap-chunk: CMD = framecrc -i $(TARGET_SAMPLES)/hap/hapy-12-chunks.mov - -FATE_HAP += fate-hapqa-nosnappy-127x71 -fate-hapqa-nosnappy-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_NoSnappy_127x1.mov - -FATE_HAP += fate-hapqa-snappy1-127x71 -fate-hapqa-snappy1-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_Snappy_1chunk_127x1.mov - -FATE_HAP += fate-hapqa-snappy16-127x71 -fate-hapqa-snappy16-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_Snappy_16chunk_127x1.mov - -FATE_HAP += fate-hap-alpha-only-nosnappy-128x72 -fate-hap-alpha-only-nosnappy-128x72: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HapAlphaOnly_NoSnappy_128x72.mov -pix_fmt gray8 - -FATE_HAP += fate-hap-alpha-only-snappy-127x71 -fate-hap-alpha-only-snappy-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HapAlphaOnly_snappy1chunk_127x71.mov -pix_fmt gray8 - -FATE_VIDEO-$(call DEMDEC, MOV, HAP) += $(FATE_HAP) -fate-hap: $(FATE_HAP) - FATE_IFF-$(CONFIG_IFF_ILBM_DECODER) += fate-iff-byterun1 fate-iff-byterun1: CMD = framecrc -i $(TARGET_SAMPLES)/iff/ASH.LBM -pix_fmt rgb24 From f56ee7403384a7aae0f5ee5aa76da0dedfdd7c35 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sun, 11 Mar 2018 19:34:54 +0100 Subject: [PATCH 2120/2557] fate/hap : add test for hap encoding with and without snappy compression with chunk 1 or chunk 16 for hap, hapa, and hapq --- tests/fate/hap.mak | 38 +++++++++++++++++++++++++++++ tests/ref/fate/hapenc-hap-none | 14 +++++++++++ tests/ref/fate/hapenc-hap-snappy1 | 14 +++++++++++ tests/ref/fate/hapenc-hap-snappy16 | 14 +++++++++++ tests/ref/fate/hapenc-hapa-none | 14 +++++++++++ tests/ref/fate/hapenc-hapa-snappy1 | 14 +++++++++++ tests/ref/fate/hapenc-hapa-snappy16 | 14 +++++++++++ tests/ref/fate/hapenc-hapq-none | 14 +++++++++++ tests/ref/fate/hapenc-hapq-snappy1 | 14 +++++++++++ tests/ref/fate/hapenc-hapq-snappy16 | 14 +++++++++++ 10 files changed, 164 insertions(+) create mode 100644 tests/ref/fate/hapenc-hap-none create mode 100644 tests/ref/fate/hapenc-hap-snappy1 create mode 100644 tests/ref/fate/hapenc-hap-snappy16 create mode 100644 tests/ref/fate/hapenc-hapa-none create mode 100644 tests/ref/fate/hapenc-hapa-snappy1 create mode 100644 tests/ref/fate/hapenc-hapa-snappy16 create mode 100644 tests/ref/fate/hapenc-hapq-none create mode 100644 tests/ref/fate/hapenc-hapq-snappy1 create mode 100644 tests/ref/fate/hapenc-hapq-snappy16 diff --git a/tests/fate/hap.mak b/tests/fate/hap.mak index b48123a3cd353..98a85806d76b7 100644 --- a/tests/fate/hap.mak +++ b/tests/fate/hap.mak @@ -27,3 +27,41 @@ fate-hap-alpha-only-snappy-127x71: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HapAl FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, HAP) += $(FATE_HAP) fate-hap: $(FATE_HAP) + + +fate-hapenc%: CMD = framemd5 -f image2 -c:v pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -sws_flags +accurate_rnd+bitexact -vframes 5 -c:v hap ${OPTS} + +FATE_HAPENC += fate-hapenc-hap-none +fate-hapenc-hap-none: OPTS = -pix_fmt rgba -format hap -compressor none + +FATE_HAPENC += fate-hapenc-hap-snappy1 +fate-hapenc-hap-snappy1: OPTS = -pix_fmt rgba -format hap -compressor snappy -chunks 1 + +FATE_HAPENC += fate-hapenc-hap-snappy16 +fate-hapenc-hap-snappy16: OPTS = -pix_fmt rgba -format hap -compressor snappy -chunks 16 + + +FATE_HAPENC += fate-hapenc-hapa-none +fate-hapenc-hapa-none: OPTS = -pix_fmt rgba -format hap_alpha -compressor none + +FATE_HAPENC += fate-hapenc-hapa-snappy1 +fate-hapenc-hapa-snappy1: OPTS = -pix_fmt rgba -format hap_alpha -compressor snappy -chunks 1 + +FATE_HAPENC += fate-hapenc-hapa-snappy16 +fate-hapenc-hapa-snappy16: OPTS = -pix_fmt rgba -format hap_alpha -compressor snappy -chunks 16 + + +FATE_HAPENC += fate-hapenc-hapq-none +fate-hapenc-hapq-none: OPTS = -pix_fmt rgba -format hap_q -compressor none + +FATE_HAPENC += fate-hapenc-hapq-snappy1 +fate-hapenc-hapq-snappy1: OPTS = -pix_fmt rgba -format hap_q -compressor snappy -chunks 1 + +FATE_HAPENC += fate-hapenc-hapq-snappy16 +fate-hapenc-hapq-snappy16: OPTS = -pix_fmt rgba -format hap_q -compressor snappy -chunks 16 + + +$(FATE_HAPENC): $(VREF) + +FATE_AVCONV-$(call ENCMUX, HAP, MOV) += $(FATE_HAPENC) +fate-hapenc: $(FATE_HAPENC) diff --git a/tests/ref/fate/hapenc-hap-none b/tests/ref/fate/hapenc-hap-none new file mode 100644 index 0000000000000..22c8b2c75163e --- /dev/null +++ b/tests/ref/fate/hapenc-hap-none @@ -0,0 +1,14 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: hap +#dimensions 0: 352x288 +#sar 0: 0/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 50696, 7fd5bc08f7b96326953ba6926cb06109 +0, 1, 1, 1, 50696, 24d172f2ea03994add2596a48151fca8 +0, 2, 2, 1, 50696, e5f2bac02ad850eb769007694a2f7acc +0, 3, 3, 1, 50696, 26042fbce3868ad012b0b4557fd95d8a +0, 4, 4, 1, 50696, 80902dd47d1211f1cd388652d5e0a797 diff --git a/tests/ref/fate/hapenc-hap-snappy1 b/tests/ref/fate/hapenc-hap-snappy1 new file mode 100644 index 0000000000000..53b5c7d6267d9 --- /dev/null +++ b/tests/ref/fate/hapenc-hap-snappy1 @@ -0,0 +1,14 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: hap +#dimensions 0: 352x288 +#sar 0: 0/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 38199, e9a458a776d7f32d5d01ba9d2a1e9242 +0, 1, 1, 1, 38475, 0f134741aaf9532629c6163c90e5d779 +0, 2, 2, 1, 39157, 39c2b6b8c308af8e5d6a9eef92e8e8dc +0, 3, 3, 1, 38674, 7cc1dfb3cb636181237a7ecd67d17614 +0, 4, 4, 1, 38360, 05d0bcfa66349e41db6e42134cc47121 diff --git a/tests/ref/fate/hapenc-hap-snappy16 b/tests/ref/fate/hapenc-hap-snappy16 new file mode 100644 index 0000000000000..ab0771bf61ac5 --- /dev/null +++ b/tests/ref/fate/hapenc-hap-snappy16 @@ -0,0 +1,14 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: hap +#dimensions 0: 352x288 +#sar 0: 0/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 42239, ad3bdee68ffa054fa2bdd3fbc083e39c +0, 1, 1, 1, 42268, 5b96644be5f424bc04e5695f58f6c238 +0, 2, 2, 1, 42703, 6d6ea64b8808625638bb5e3e065042c1 +0, 3, 3, 1, 42170, 307615782d52350c1379caefc79123ab +0, 4, 4, 1, 42005, 5dfcc935564600944eb7b8a3a82fb569 diff --git a/tests/ref/fate/hapenc-hapa-none b/tests/ref/fate/hapenc-hapa-none new file mode 100644 index 0000000000000..9aa80ae83d05f --- /dev/null +++ b/tests/ref/fate/hapenc-hapa-none @@ -0,0 +1,14 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: hap +#dimensions 0: 352x288 +#sar 0: 0/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 101384, 7bd1e603a54fb468242c9e00b0a90359 +0, 1, 1, 1, 101384, 09bf0e48db9bf465f3d89a192ddfda2d +0, 2, 2, 1, 101384, 4993a96ed5f5d2bc0f0ff2080622eed2 +0, 3, 3, 1, 101384, 5cdbd0f763ba40366816588160ec73c2 +0, 4, 4, 1, 101384, 9202fe8358efde2c92c75210ed93c118 diff --git a/tests/ref/fate/hapenc-hapa-snappy1 b/tests/ref/fate/hapenc-hapa-snappy1 new file mode 100644 index 0000000000000..add69139fa9cc --- /dev/null +++ b/tests/ref/fate/hapenc-hapa-snappy1 @@ -0,0 +1,14 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: hap +#dimensions 0: 352x288 +#sar 0: 0/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 47912, ac94f44194b154b15b7008ef38ae2343 +0, 1, 1, 1, 48244, 21bff8df4137fdde2c836ea4c5aa10e0 +0, 2, 2, 1, 49175, 4a6053f4f81259ad201d10ac83e47524 +0, 3, 3, 1, 48159, 90df8d03d9d7bc99a22e439e4d79e9fc +0, 4, 4, 1, 47932, 8e719e872130057df3d3580f62693733 diff --git a/tests/ref/fate/hapenc-hapa-snappy16 b/tests/ref/fate/hapenc-hapa-snappy16 new file mode 100644 index 0000000000000..08613c011a766 --- /dev/null +++ b/tests/ref/fate/hapenc-hapa-snappy16 @@ -0,0 +1,14 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: hap +#dimensions 0: 352x288 +#sar 0: 0/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 50172, d6100c76b42d6926497ff8c38d4ad5fb +0, 1, 1, 1, 50342, 62902c55f89169cb4dd46943e21f6f4a +0, 2, 2, 1, 51244, 64f44a60052dfbdd315e485f2ced97eb +0, 3, 3, 1, 50266, 05cd86de81a7e4e44ce9d1489d839ffa +0, 4, 4, 1, 50056, 2ee4234d16f3f13bec7ace5c8c2a94f5 diff --git a/tests/ref/fate/hapenc-hapq-none b/tests/ref/fate/hapenc-hapq-none new file mode 100644 index 0000000000000..ee467b6753f65 --- /dev/null +++ b/tests/ref/fate/hapenc-hapq-none @@ -0,0 +1,14 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: hap +#dimensions 0: 352x288 +#sar 0: 0/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 101384, cb6ef787ae7adff965ba4904a57c2188 +0, 1, 1, 1, 101384, 7cd50676c256354c06f728a265556efd +0, 2, 2, 1, 101384, 454b14f7770a1f57830a678ea6e24b86 +0, 3, 3, 1, 101384, 6e6c088ed068d05870976fe78a75bb30 +0, 4, 4, 1, 101384, ba79bd8e7fc5d8919b174f0c8ea82753 diff --git a/tests/ref/fate/hapenc-hapq-snappy1 b/tests/ref/fate/hapenc-hapq-snappy1 new file mode 100644 index 0000000000000..f22815057f599 --- /dev/null +++ b/tests/ref/fate/hapenc-hapq-snappy1 @@ -0,0 +1,14 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: hap +#dimensions 0: 352x288 +#sar 0: 0/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 78214, a84391a7ca12ae34b7fea3e65c75a576 +0, 1, 1, 1, 79137, 2a75402a0e5a5e009cd16b341939fefd +0, 2, 2, 1, 80273, 67a555ea3e38cdcd76c03761a426c424 +0, 3, 3, 1, 78672, c3f883869d6cda0bb96e7c629faaefd2 +0, 4, 4, 1, 78941, 219761cabd005f8e7904a248ffbbcf8f diff --git a/tests/ref/fate/hapenc-hapq-snappy16 b/tests/ref/fate/hapenc-hapq-snappy16 new file mode 100644 index 0000000000000..eac1799611d1c --- /dev/null +++ b/tests/ref/fate/hapenc-hapq-snappy16 @@ -0,0 +1,14 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: hap +#dimensions 0: 352x288 +#sar 0: 0/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 81934, ad9ee8c455704cad6c641479085d81dd +0, 1, 1, 1, 82165, dde5dfcfa5507c3f943d4186490e9fa6 +0, 2, 2, 1, 83238, b1c9f8ce21d75e61dcd9d69726fd32cf +0, 3, 3, 1, 81773, 0ccaca5d91a1e41b0cb132826352be6f +0, 4, 4, 1, 82174, a629612d432620e61b82ac2f7c9a3619 From 3172b31223e1f0a64233fa5b355e11d7a00e477b Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 13 Mar 2018 02:40:09 -0700 Subject: [PATCH 2121/2557] avcodec/mediacodecdec: fix immediate EAGAIN with buffered packet In cases where the mediacodec decoder consumed a partial packet, receive_frame() would start returning EAGAIN if the rest of the packet couldn't be flushed and no frames were immediately available. This fixes receive_frame() to perform its normal blocking wait for new frames before returning EAGAIN. Fixes an issue I could reproduce fairly often on a FireOS 6 device, and reported to be happening intermittently by two mpv users. Signed-off-by: Aman Gupta Signed-off-by: Matthieu Bouron --- libavcodec/mediacodecdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 89d2421ae907f..0d4a853f078c0 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -452,7 +452,7 @@ static int mediacodec_receive_frame(AVCodecContext *avctx, AVFrame *frame) /* skip fetching new packet if we still have one buffered */ if (s->buffered_pkt.size > 0) - return AVERROR(EAGAIN); + return mediacodec_send_receive(avctx, s, frame, true); /* fetch new packet or eof */ ret = ff_decode_get_packet(avctx, &s->buffered_pkt); From 2b6699f024ae9968244d02d3c81e57737d603b62 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 13 Mar 2018 18:55:49 -0300 Subject: [PATCH 2122/2557] avcodec/hapqa_extract: move the reference in the bsf internal buffer There's no need to allocate a new packet for it. Signed-off-by: James Almer --- libavcodec/hapqa_extract_bsf.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/libavcodec/hapqa_extract_bsf.c b/libavcodec/hapqa_extract_bsf.c index 45fe9fbe8f483..333efb2e3a41c 100644 --- a/libavcodec/hapqa_extract_bsf.c +++ b/libavcodec/hapqa_extract_bsf.c @@ -45,7 +45,7 @@ static int check_texture(HapqaExtractContext *ctx, int section_type) { } } -static int hapqa_extract(AVBSFContext *bsf, AVPacket *out) +static int hapqa_extract(AVBSFContext *bsf, AVPacket *pkt) { HapqaExtractContext *ctx = bsf->priv_data; GetByteContext gbc; @@ -53,14 +53,13 @@ static int hapqa_extract(AVBSFContext *bsf, AVPacket *out) enum HapSectionType section_type; int start_section_size; int target_packet_size = 0; - AVPacket *in; int ret = 0; - ret = ff_bsf_get_packet(bsf, &in); + ret = ff_bsf_get_packet_ref(bsf, pkt); if (ret < 0) return ret; - bytestream2_init(&gbc, in->data, in->size); + bytestream2_init(&gbc, pkt->data, pkt->size); ret = ff_hap_parse_section_header(&gbc, §ion_size, §ion_type); if (ret != 0) goto fail; @@ -95,14 +94,12 @@ static int hapqa_extract(AVBSFContext *bsf, AVPacket *out) } } - av_packet_move_ref(out, in); - out->data += start_section_size; - out->size = target_packet_size; + pkt->data += start_section_size; + pkt->size = target_packet_size; fail: if (ret < 0) - av_packet_unref(out); - av_packet_free(&in); + av_packet_unref(pkt); return ret; } From b173e035362b103e17cc7b394c231c60a4915c59 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 13 Mar 2018 19:06:45 -0300 Subject: [PATCH 2123/2557] avcodec/hapqa_extract: fix two error return values ret is 0 by default. Reviewed-by: Martin Vignali Signed-off-by: James Almer --- libavcodec/hapqa_extract_bsf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/hapqa_extract_bsf.c b/libavcodec/hapqa_extract_bsf.c index 333efb2e3a41c..ee5dc191f79d7 100644 --- a/libavcodec/hapqa_extract_bsf.c +++ b/libavcodec/hapqa_extract_bsf.c @@ -66,6 +66,7 @@ static int hapqa_extract(AVBSFContext *bsf, AVPacket *pkt) if ((section_type & 0x0F) != 0x0D) { av_log(bsf, AV_LOG_ERROR, "Invalid section type for HAPQA %#04x.\n", section_type & 0x0F); + ret = AVERROR_INVALIDDATA; goto fail; } @@ -90,6 +91,7 @@ static int hapqa_extract(AVBSFContext *bsf, AVPacket *pkt) if (check_texture(ctx, section_type) == 0){ /* the second texture is not the one to keep */ av_log(bsf, AV_LOG_ERROR, "No valid texture found.\n"); + ret = AVERROR_INVALIDDATA; goto fail; } } From 6010537956d5a7260f2dd52184779fe01a085a2b Mon Sep 17 00:00:00 2001 From: Ravindra Date: Wed, 14 Mar 2018 19:59:34 +0800 Subject: [PATCH 2124/2557] avformat/hlsenc: Option to set timeout for socket I/O operation Reviewed-by: Steven Liu --- doc/muxers.texi | 3 +++ libavformat/hlsenc.c | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index c156ec0c87ba4..3a63da7fe72d0 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -964,6 +964,9 @@ publishing it repeatedly every after 30 segments i.e. every after 60s. @item http_persistent Use persistent HTTP connections. Applicable only for HTTP output. +@item timeout +Set timeout for socket I/O operations. Applicable only for HTTP output. + @end table @anchor{ico} diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 7d9512b6648f3..58d403d3fa4dd 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -224,6 +224,7 @@ typedef struct HLSContext { int http_persistent; AVIOContext *m3u8_out; AVIOContext *sub_m3u8_out; + int64_t timeout; } HLSContext; static int mkdir_p(const char *path) { @@ -305,7 +306,8 @@ static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSCont av_dict_set(options, "user_agent", c->user_agent, 0); if (c->http_persistent) av_dict_set_int(options, "multiple_requests", 1, 0); - + if (c->timeout >= 0) + av_dict_set_int(options, "timeout", c->timeout, 0); } static void write_codec_attr(AVStream *st, VariantStream *vs) { @@ -2792,6 +2794,7 @@ static const AVOption options[] = { {"master_pl_name", "Create HLS master playlist with this name", OFFSET(master_pl_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"master_pl_publish_rate", "Publish master play list every after this many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E}, {"http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, + {"timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E }, { NULL }, }; From f706cdda5694d2fce24bfb2ee81a4382327fa760 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 13 Mar 2018 22:08:29 -0300 Subject: [PATCH 2125/2557] avcodec/hapqa_extract: remove the AVOption flags These two are not used for bitstream filters. Reviewed-by: Martin Vignali Signed-off-by: James Almer --- libavcodec/hapqa_extract_bsf.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libavcodec/hapqa_extract_bsf.c b/libavcodec/hapqa_extract_bsf.c index ee5dc191f79d7..652f79a7fe762 100644 --- a/libavcodec/hapqa_extract_bsf.c +++ b/libavcodec/hapqa_extract_bsf.c @@ -110,11 +110,10 @@ static const enum AVCodecID codec_ids[] = { }; #define OFFSET(x) offsetof(HapqaExtractContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "texture", "texture to keep", OFFSET(texture), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "texture" }, - { "color", "keep HapQ texture", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "texture" }, - { "alpha", "keep HapAlphaOnly texture", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "texture" }, + { "texture", "texture to keep", OFFSET(texture), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, 0, "texture" }, + { "color", "keep HapQ texture", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .unit = "texture" }, + { "alpha", "keep HapAlphaOnly texture", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .unit = "texture" }, { NULL }, }; From 1dd7bb978436e9064e92411693252ad4ad183435 Mon Sep 17 00:00:00 2001 From: sanilraut Date: Thu, 15 Mar 2018 04:00:04 -0700 Subject: [PATCH 2126/2557] avformat/dashdec: Correct spelling mistakes Signed-off-by: Steven Liu --- libavformat/dashdec.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 2b396a01b7171..7b79b93c2412c 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -1106,8 +1106,8 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) xmlNodePtr adaptionset_node = NULL; xmlAttrPtr attr = NULL; char *val = NULL; - uint32_t perdiod_duration_sec = 0; - uint32_t perdiod_start_sec = 0; + uint32_t period_duration_sec = 0; + uint32_t period_start_sec = 0; if (!in) { close_in = 1; @@ -1202,23 +1202,23 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) node = xmlFirstElementChild(node); while (node) { if (!av_strcasecmp(node->name, (const char *)"Period")) { - perdiod_duration_sec = 0; - perdiod_start_sec = 0; + period_duration_sec = 0; + period_start_sec = 0; attr = node->properties; while (attr) { val = xmlGetProp(node, attr->name); if (!av_strcasecmp(attr->name, (const char *)"duration")) { - perdiod_duration_sec = get_duration_insec(s, (const char *)val); + period_duration_sec = get_duration_insec(s, (const char *)val); } else if (!av_strcasecmp(attr->name, (const char *)"start")) { - perdiod_start_sec = get_duration_insec(s, (const char *)val); + period_start_sec = get_duration_insec(s, (const char *)val); } attr = attr->next; xmlFree(val); } - if ((perdiod_duration_sec) >= (c->period_duration)) { + if ((period_duration_sec) >= (c->period_duration)) { period_node = node; - c->period_duration = perdiod_duration_sec; - c->period_start = perdiod_start_sec; + c->period_duration = period_duration_sec; + c->period_start = period_start_sec; if (c->period_start > 0) c->media_presentation_duration = c->period_duration; } From eeca8921e265f565e687eea414cef5790f2b2bbc Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 15 Mar 2018 20:33:20 -0300 Subject: [PATCH 2127/2557] configure: add missing adts_header to aac_fixed decoder Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 76b3ba68d31b0..0c5ed07a072c7 100755 --- a/configure +++ b/configure @@ -2437,7 +2437,7 @@ rdft_select="fft" # decoders / encoders aac_decoder_select="adts_header mdct15 mdct sinewin" -aac_fixed_decoder_select="mdct sinewin" +aac_fixed_decoder_select="adts_header mdct sinewin" aac_encoder_select="audio_frame_queue iirfilter lpc mdct sinewin" aac_latm_decoder_select="aac_decoder aac_latm_parser" ac3_decoder_select="ac3_parser ac3dsp bswapdsp fmtconvert mdct" From 935a9986fc2ef4ab4a752632be258811ec7f695f Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 13 Mar 2018 23:35:12 -0300 Subject: [PATCH 2128/2557] avformat/movenc: move the concatenated eac3 packet reference Simplifies code. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/movenc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 5b1e66c89736a..d681d519e6b4d 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -491,10 +491,7 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track) if (info->num_blocks != 6) goto end; av_packet_unref(pkt); - ret = av_packet_ref(pkt, &info->pkt); - if (ret < 0) - goto end; - av_packet_unref(&info->pkt); + av_packet_move_ref(pkt, &info->pkt); info->num_blocks = 0; } ret = pkt->size; From e0e72539cf5cb9d83cd13434f3be7b80e7ca84e4 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Thu, 8 Mar 2018 13:47:23 +0800 Subject: [PATCH 2129/2557] lavu/opt: add AV_OPT_FLAG_BSF_PARAM add AV_OPT_FLAG_BSF_PARAM for bit stream filter options. Signed-off-by: Jun Zhao Signed-off-by: Michael Niedermayer --- libavutil/opt.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/opt.h b/libavutil/opt.h index 391720f2e25ac..07da68ea23d37 100644 --- a/libavutil/opt.h +++ b/libavutil/opt.h @@ -287,6 +287,7 @@ typedef struct AVOption { * This flag only makes sense when AV_OPT_FLAG_EXPORT is also set. */ #define AV_OPT_FLAG_READONLY 128 +#define AV_OPT_FLAG_BSF_PARAM (1<<8) ///< a generic parameter which can be set by the user for bit stream filtering #define AV_OPT_FLAG_FILTERING_PARAM (1<<16) ///< a generic parameter which can be set by the user for filtering //FIXME think about enc-audio, ... style flags From 7b5cf0a410760bbd516d5c72cbb867c45017f9a7 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Wed, 14 Mar 2018 10:05:05 +0800 Subject: [PATCH 2130/2557] lavu/opt: add bit stream filter option dump support. enable dump bit stream filter and update opt fate test ref. Signed-off-by: Jun Zhao Signed-off-by: Michael Niedermayer --- libavutil/opt.c | 1 + tests/ref/fate/opt | 50 +++++++++++++++++++++++----------------------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/libavutil/opt.c b/libavutil/opt.c index df88663e3f09b..3b0aab4ee82ea 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -1181,6 +1181,7 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit, av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.'); av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_EXPORT) ? 'X' : '.'); av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_READONLY) ? 'R' : '.'); + av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_BSF_PARAM) ? 'B' : '.'); if (opt->help) av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help); diff --git a/tests/ref/fate/opt b/tests/ref/fate/opt index 7b47d429c55e7..6a7dbfa797026 100644 --- a/tests/ref/fate/opt +++ b/tests/ref/fate/opt @@ -18,31 +18,31 @@ num64=1 flt=0.333333 dbl=0.333333 TestContext AVOptions: - -num E....... set num (from 0 to 100) (default 0) - -toggle E....... set toggle (from 0 to 1) (default 1) - -rational E....... set rational (from 0 to 10) (default 1/1) - -string E....... set string (default "default") - -escape E....... set escape str (default "\=,") - -flags E....... set flags (default cool) - cool E....... set cool flag - lame E....... set lame flag - mu E....... set mu flag - -size E....... set size (default "200x300") - -pix_fmt E....... set pixfmt (default 0bgr) - -sample_fmt E....... set samplefmt (default s16) - -video_rate E....... set videorate (default "25") - -duration E....... set duration (default 0.001) - -color E....... set color (default "pink") - -cl E....... set channel layout (default 0x137) - -bin E....... set binary value - -bin1 E....... set binary value - -bin2 E....... set binary value - -num64 E....... set num 64bit (from 0 to 100) (default 1) - -flt E....... set float (from 0 to 100) (default 0.333333) - -dbl E....... set double (from 0 to 100) (default 0.333333) - -bool1 E....... set boolean value (default auto) - -bool2 E....... set boolean value (default true) - -bool3 E....... set boolean value (default false) + -num E........ set num (from 0 to 100) (default 0) + -toggle E........ set toggle (from 0 to 1) (default 1) + -rational E........ set rational (from 0 to 10) (default 1/1) + -string E........ set string (default "default") + -escape E........ set escape str (default "\=,") + -flags E........ set flags (default cool) + cool E........ set cool flag + lame E........ set lame flag + mu E........ set mu flag + -size E........ set size (default "200x300") + -pix_fmt E........ set pixfmt (default 0bgr) + -sample_fmt E........ set samplefmt (default s16) + -video_rate E........ set videorate (default "25") + -duration E........ set duration (default 0.001) + -color E........ set color (default "pink") + -cl E........ set channel layout (default 0x137) + -bin E........ set binary value + -bin1 E........ set binary value + -bin2 E........ set binary value + -num64 E........ set num 64bit (from 0 to 100) (default 1) + -flt E........ set float (from 0 to 100) (default 0.333333) + -dbl E........ set double (from 0 to 100) (default 0.333333) + -bool1 E........ set boolean value (default auto) + -bool2 E........ set boolean value (default true) + -bool3 E........ set boolean value (default false) Testing av_opt_is_set_to_default() name: num default:1 error: From a675eed17538708a4efb90946b83161ec788b36a Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Thu, 8 Mar 2018 13:50:31 +0800 Subject: [PATCH 2131/2557] ffmpeg: support dump bit stream filter options. Support dump bit stream filter option in ffmpeg -h full and ffmpeg -h bsf=FooBar. Signed-off-by: Jun Zhao Signed-off-by: Michael Niedermayer --- fftools/cmdutils.c | 17 +++++++++++++++++ fftools/ffmpeg_opt.c | 3 ++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 0c7d13c27a780..f9d87f67246d6 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1897,6 +1897,21 @@ static void show_help_filter(const char *name) } #endif +static void show_help_bsf(const char *name) +{ + const AVBitStreamFilter *bsf = av_bsf_get_by_name(name); + + if (!bsf) { + av_log(NULL, AV_LOG_ERROR, "Unknown bit stream filter '%s'.\n", name); + return; + } + + printf("Bit stream filter %s\n", bsf->name); + if (bsf->priv_class) + show_help_children(bsf->priv_class, AV_OPT_FLAG_BSF_PARAM); + printf("\n"); +} + int show_help(void *optctx, const char *opt, const char *arg) { char *topic, *par; @@ -1923,6 +1938,8 @@ int show_help(void *optctx, const char *opt, const char *arg) } else if (!strcmp(topic, "filter")) { show_help_filter(par); #endif + } else if (!strcmp(topic, "bsf")) { + show_help_bsf(par); } else { show_help_default(topic, par); } diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 1b591d9695ea5..d7a7eb0662806 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -3114,7 +3114,7 @@ void show_help_default(const char *opt, const char *arg) " -h -- print basic options\n" " -h long -- print more options\n" " -h full -- print all options (including all format and codec specific options, very long)\n" - " -h type=name -- print all options for the named decoder/encoder/demuxer/muxer/filter\n" + " -h type=name -- print all options for the named decoder/encoder/demuxer/muxer/filter/bsf\n" " See man %s for detailed description of the options.\n" "\n", program_name); @@ -3159,6 +3159,7 @@ void show_help_default(const char *opt, const char *arg) #endif show_help_children(swr_get_class(), AV_OPT_FLAG_AUDIO_PARAM); show_help_children(avfilter_get_class(), AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM); + show_help_children(av_bsf_get_class(), AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_BSF_PARAM); } } From 7af2336598e99433a273fd0346fd456940f46f96 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 16 Mar 2018 00:19:45 -0300 Subject: [PATCH 2132/2557] avutil: bump version after the latest AVOption flag addition Signed-off-by: James Almer --- doc/APIchanges | 3 +++ libavutil/version.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 395ac902dd6cc..f757f5063ed4e 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-03-15 - e0e72539cf - lavu 56.10.100 - opt.h + Add AV_OPT_FLAG_BSF_PARAM + 2018-03-07 - xxxxxxx - lavu 56.9.100 - crc.h Add AV_CRC_8_EBU crc variant. diff --git a/libavutil/version.h b/libavutil/version.h index 0c032c8553204..9ca556ddc9d1c 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 9 +#define LIBAVUTIL_VERSION_MINOR 10 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 1296a718dc62728b6601f694539a1c5ad8ad260c Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Wed, 14 Mar 2018 09:34:32 +0100 Subject: [PATCH 2133/2557] avutil/log: print level prefix also when no AVClass context is available Adds the level prefix to all log messages, except those with level <= AV_LOG_QUIET as they seem to be used for flushing the log buffer. Reviewed-by: Michael Niedermayer Signed-off-by: Tobias Rapp --- libavutil/log.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavutil/log.c b/libavutil/log.c index bd47f2a25f3f6..9b7d48487f6ff 100644 --- a/libavutil/log.c +++ b/libavutil/log.c @@ -266,11 +266,11 @@ static void format_line(void *avcl, int level, const char *fmt, va_list vl, av_bprintf(part+1, "[%s @ %p] ", avc->item_name(avcl), avcl); if(type) type[1] = get_category(avcl); - - if (flags & AV_LOG_PRINT_LEVEL) - av_bprintf(part+2, "[%s] ", get_level_str(level)); } + if (*print_prefix && (level > AV_LOG_QUIET) && (flags & AV_LOG_PRINT_LEVEL)) + av_bprintf(part+2, "[%s] ", get_level_str(level)); + av_vbprintf(part+3, fmt, vl); if(*part[0].str || *part[1].str || *part[2].str || *part[3].str) { From 5941179e28b996b9ddfc18bf4981af14d621dc83 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 16 Mar 2018 12:30:17 +0100 Subject: [PATCH 2134/2557] avfilter/af_surround: drain input at EOF Signed-off-by: Paul B Mahol --- libavfilter/af_surround.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/libavfilter/af_surround.c b/libavfilter/af_surround.c index 460e18cd5ada0..f29afecbfb640 100644 --- a/libavfilter/af_surround.c +++ b/libavfilter/af_surround.c @@ -1390,6 +1390,27 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return 0; } +static int request_frame(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AudioSurroundContext *s = ctx->priv; + int ret = 0; + + ret = ff_request_frame(ctx->inputs[0]); + + if (ret == AVERROR_EOF && av_audio_fifo_size(s->fifo) > 0 && av_audio_fifo_size(s->fifo) < s->buf_size) { + AVFrame *in; + + in = ff_get_audio_buffer(outlink, s->buf_size - av_audio_fifo_size(s->fifo)); + if (!in) + return AVERROR(ENOMEM); + ret = filter_frame(ctx->inputs[0], in); + av_audio_fifo_drain(s->fifo, s->buf_size); + } + + return ret; +} + static av_cold void uninit(AVFilterContext *ctx) { AudioSurroundContext *s = ctx->priv; @@ -1445,9 +1466,10 @@ static const AVFilterPad inputs[] = { static const AVFilterPad outputs[] = { { - .name = "default", - .type = AVMEDIA_TYPE_AUDIO, - .config_props = config_output, + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .request_frame = request_frame, + .config_props = config_output, }, { NULL } }; From 3d6e76b953afd36e23ef8532b81aea58a6338931 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Thu, 15 Mar 2018 18:02:11 +0800 Subject: [PATCH 2135/2557] qsvenc: Fix a typo of FrameRateExtD/FrameRateExtN Signed-off-by: Zhong Li Signed-off-by: Luca Barbato --- libavcodec/qsvenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index d4dd4a3b94aa3..baa2c6307f959 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -374,7 +374,7 @@ static int check_enc_param(AVCodecContext *avctx, QSVEncContext *q) av_log(avctx, AV_LOG_ERROR, "Selected ratecontrol mode is unsupported\n"); if (UNMATCH(LowPower)) av_log(avctx, AV_LOG_ERROR, "Low power mode is unsupported\n"); - if (UNMATCH(FrameInfo.FrameRateExtN) || UNMATCH(FrameInfo.FrameRateExtN)) + if (UNMATCH(FrameInfo.FrameRateExtN) || UNMATCH(FrameInfo.FrameRateExtD)) av_log(avctx, AV_LOG_ERROR, "Current frame rate is unsupported\n"); if (UNMATCH(FrameInfo.PicStruct)) av_log(avctx, AV_LOG_ERROR, "Current picture structure is unsupported\n"); From deefca02c275ce4bc5ccbee690463ffef81a18b8 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Thu, 15 Mar 2018 18:02:12 +0800 Subject: [PATCH 2136/2557] qsvenc: add the Access Unit Delimiter NAL Unit support Signed-off-by: Zhong Li Signed-off-by: Luca Barbato --- libavcodec/qsvenc.c | 1 + libavcodec/qsvenc.h | 2 ++ libavcodec/qsvenc_h264.c | 2 ++ 3 files changed, 5 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index baa2c6307f959..f6b1a0d6760d6 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -600,6 +600,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if (q->recovery_point_sei >= 0) q->extco.RecoveryPointSEI = q->recovery_point_sei ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; q->extco.MaxDecFrameBuffering = q->max_dec_frame_buffering; + q->extco.AUDelimiter = q->aud ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; } q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 31537b2663cf7..ab55795950c80 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -137,6 +137,8 @@ typedef struct QSVEncContext { int max_frame_size; int max_slice_size; + int aud; + int single_sei_nal_unit; int max_dec_frame_buffering; int trellis; diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index 1552d7691dff7..634a7d3f9199b 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -91,6 +91,8 @@ static const AVOption options[] = { { "main" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, { "high" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_HIGH }, INT_MIN, INT_MAX, VE, "profile" }, + { "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, + { NULL }, }; From a7a8320c4f17f889d8d5bf8715eba4ff74d613e7 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 16 Mar 2018 19:51:08 -0300 Subject: [PATCH 2137/2557] avcodec/null_bsf: move the reference in the bsf internal buffer There's no need to allocate a new packet for it. Signed-off-by: James Almer --- libavcodec/null_bsf.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/libavcodec/null_bsf.c b/libavcodec/null_bsf.c index feb71248a970d..24d26dfb1aad9 100644 --- a/libavcodec/null_bsf.c +++ b/libavcodec/null_bsf.c @@ -24,17 +24,9 @@ #include "avcodec.h" #include "bsf.h" -static int null_filter(AVBSFContext *ctx, AVPacket *out) +static int null_filter(AVBSFContext *ctx, AVPacket *pkt) { - AVPacket *in; - int ret; - - ret = ff_bsf_get_packet(ctx, &in); - if (ret < 0) - return ret; - av_packet_move_ref(out, in); - av_packet_free(&in); - return 0; + return ff_bsf_get_packet_ref(ctx, pkt); } const AVBitStreamFilter ff_null_bsf = { From 055f60e874673188357854db3c2456f10fe41162 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Mar 2018 11:53:56 -0300 Subject: [PATCH 2138/2557] cmdutils: remove a superfluous line break Signed-off-by: James Almer --- fftools/cmdutils.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index f9d87f67246d6..708a849f5189b 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1909,7 +1909,6 @@ static void show_help_bsf(const char *name) printf("Bit stream filter %s\n", bsf->name); if (bsf->priv_class) show_help_children(bsf->priv_class, AV_OPT_FLAG_BSF_PARAM); - printf("\n"); } int show_help(void *optctx, const char *opt, const char *arg) From edce64c9e98f32579dddb5dccf590034686decc2 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Thu, 8 Mar 2018 14:05:53 +0800 Subject: [PATCH 2139/2557] lavc/extract_extradata_bsf: support dump options. support dump bit stream filter options Signed-off-by: Jun Zhao Signed-off-by: James Almer --- libavcodec/extract_extradata_bsf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c index 1c386becd7e80..82632c5b57769 100644 --- a/libavcodec/extract_extradata_bsf.c +++ b/libavcodec/extract_extradata_bsf.c @@ -322,9 +322,10 @@ static const enum AVCodecID codec_ids[] = { }; #define OFFSET(x) offsetof(ExtractExtradataContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) static const AVOption options[] = { { "remove", "remove the extradata from the bitstream", OFFSET(remove), AV_OPT_TYPE_INT, - { .i64 = 0 }, 0, 1 }, + { .i64 = 0 }, 0, 1, FLAGS }, { NULL }, }; From 1410454c8b0b35ccc5292ab5e639b29b326a80da Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Mar 2018 12:03:32 -0300 Subject: [PATCH 2140/2557] Partially revert "avcodec/hapqa_extract: remove the AVOption flags Re add AVOptions flags, using the new one meant for bsfs. This partially reverts commit f706cdda56. Signed-off-by: James Almer --- libavcodec/hapqa_extract_bsf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavcodec/hapqa_extract_bsf.c b/libavcodec/hapqa_extract_bsf.c index 652f79a7fe762..167d22d06ea21 100644 --- a/libavcodec/hapqa_extract_bsf.c +++ b/libavcodec/hapqa_extract_bsf.c @@ -110,10 +110,11 @@ static const enum AVCodecID codec_ids[] = { }; #define OFFSET(x) offsetof(HapqaExtractContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_BSF_PARAM) static const AVOption options[] = { - { "texture", "texture to keep", OFFSET(texture), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, 0, "texture" }, - { "color", "keep HapQ texture", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .unit = "texture" }, - { "alpha", "keep HapAlphaOnly texture", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .unit = "texture" }, + { "texture", "texture to keep", OFFSET(texture), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "texture" }, + { "color", "keep HapQ texture", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "texture" }, + { "alpha", "keep HapAlphaOnly texture", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "texture" }, { NULL }, }; From ed1a750fd18f2293cad92ae63f1d6d53a99eeaff Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Mar 2018 02:08:37 -0300 Subject: [PATCH 2141/2557] fate: add a dca_core bitstream filter test Reviwed-by: Paul B Mahol Signed-off-by: James Almer --- tests/fate/dca.mak | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/fate/dca.mak b/tests/fate/dca.mak index b1681c6b59313..fad3a7529ecd1 100644 --- a/tests/fate/dca.mak +++ b/tests/fate/dca.mak @@ -75,5 +75,10 @@ fate-dts_es: CMD = pcm -i $(TARGET_SAMPLES)/dts/dts_es.dts fate-dts_es: CMP = oneoff fate-dts_es: REF = $(SAMPLES)/dts/dts_es_2.pcm +FATE_DCA-$(call ALLYES, DTS_DEMUXER DTS_MUXER DCA_CORE_BSF) += fate-dca-core-bsf +fate-dca-core-bsf: CMD = md5pipe -i $(TARGET_SAMPLES)/dts/master_audio_7.1_24bit.dts -c:a copy -bsf:a dca_core -fflags +bitexact -f dts +fate-dca-core-bsf: CMP = oneline +fate-dca-core-bsf: REF = ca22b00d8c641cd168e2f7ca8d2f340e + FATE_SAMPLES_AUDIO += $(FATE_DCA-yes) fate-dca: $(FATE_DCA-yes) From 32dbee4462a06a7c82fd1719d044dde2e9b013e7 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Wed, 14 Mar 2018 07:26:43 +0100 Subject: [PATCH 2142/2557] fate/hapenc : remove test which use libsnappy the test in none mode can be let (they don't use libsnappy) --- tests/fate/hap.mak | 21 --------------------- tests/ref/fate/hapenc-hap-snappy1 | 14 -------------- tests/ref/fate/hapenc-hap-snappy16 | 14 -------------- tests/ref/fate/hapenc-hapa-snappy1 | 14 -------------- tests/ref/fate/hapenc-hapa-snappy16 | 14 -------------- tests/ref/fate/hapenc-hapq-snappy1 | 14 -------------- tests/ref/fate/hapenc-hapq-snappy16 | 14 -------------- 7 files changed, 105 deletions(-) delete mode 100644 tests/ref/fate/hapenc-hap-snappy1 delete mode 100644 tests/ref/fate/hapenc-hap-snappy16 delete mode 100644 tests/ref/fate/hapenc-hapa-snappy1 delete mode 100644 tests/ref/fate/hapenc-hapa-snappy16 delete mode 100644 tests/ref/fate/hapenc-hapq-snappy1 delete mode 100644 tests/ref/fate/hapenc-hapq-snappy16 diff --git a/tests/fate/hap.mak b/tests/fate/hap.mak index 98a85806d76b7..51673366f2157 100644 --- a/tests/fate/hap.mak +++ b/tests/fate/hap.mak @@ -34,33 +34,12 @@ fate-hapenc%: CMD = framemd5 -f image2 -c:v pgmyuv -i $(TARGET_PATH)/tests/vsynt FATE_HAPENC += fate-hapenc-hap-none fate-hapenc-hap-none: OPTS = -pix_fmt rgba -format hap -compressor none -FATE_HAPENC += fate-hapenc-hap-snappy1 -fate-hapenc-hap-snappy1: OPTS = -pix_fmt rgba -format hap -compressor snappy -chunks 1 - -FATE_HAPENC += fate-hapenc-hap-snappy16 -fate-hapenc-hap-snappy16: OPTS = -pix_fmt rgba -format hap -compressor snappy -chunks 16 - - FATE_HAPENC += fate-hapenc-hapa-none fate-hapenc-hapa-none: OPTS = -pix_fmt rgba -format hap_alpha -compressor none -FATE_HAPENC += fate-hapenc-hapa-snappy1 -fate-hapenc-hapa-snappy1: OPTS = -pix_fmt rgba -format hap_alpha -compressor snappy -chunks 1 - -FATE_HAPENC += fate-hapenc-hapa-snappy16 -fate-hapenc-hapa-snappy16: OPTS = -pix_fmt rgba -format hap_alpha -compressor snappy -chunks 16 - - FATE_HAPENC += fate-hapenc-hapq-none fate-hapenc-hapq-none: OPTS = -pix_fmt rgba -format hap_q -compressor none -FATE_HAPENC += fate-hapenc-hapq-snappy1 -fate-hapenc-hapq-snappy1: OPTS = -pix_fmt rgba -format hap_q -compressor snappy -chunks 1 - -FATE_HAPENC += fate-hapenc-hapq-snappy16 -fate-hapenc-hapq-snappy16: OPTS = -pix_fmt rgba -format hap_q -compressor snappy -chunks 16 - - $(FATE_HAPENC): $(VREF) FATE_AVCONV-$(call ENCMUX, HAP, MOV) += $(FATE_HAPENC) diff --git a/tests/ref/fate/hapenc-hap-snappy1 b/tests/ref/fate/hapenc-hap-snappy1 deleted file mode 100644 index 53b5c7d6267d9..0000000000000 --- a/tests/ref/fate/hapenc-hap-snappy1 +++ /dev/null @@ -1,14 +0,0 @@ -#format: frame checksums -#version: 2 -#hash: MD5 -#tb 0: 1/25 -#media_type 0: video -#codec_id 0: hap -#dimensions 0: 352x288 -#sar 0: 0/1 -#stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 38199, e9a458a776d7f32d5d01ba9d2a1e9242 -0, 1, 1, 1, 38475, 0f134741aaf9532629c6163c90e5d779 -0, 2, 2, 1, 39157, 39c2b6b8c308af8e5d6a9eef92e8e8dc -0, 3, 3, 1, 38674, 7cc1dfb3cb636181237a7ecd67d17614 -0, 4, 4, 1, 38360, 05d0bcfa66349e41db6e42134cc47121 diff --git a/tests/ref/fate/hapenc-hap-snappy16 b/tests/ref/fate/hapenc-hap-snappy16 deleted file mode 100644 index ab0771bf61ac5..0000000000000 --- a/tests/ref/fate/hapenc-hap-snappy16 +++ /dev/null @@ -1,14 +0,0 @@ -#format: frame checksums -#version: 2 -#hash: MD5 -#tb 0: 1/25 -#media_type 0: video -#codec_id 0: hap -#dimensions 0: 352x288 -#sar 0: 0/1 -#stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 42239, ad3bdee68ffa054fa2bdd3fbc083e39c -0, 1, 1, 1, 42268, 5b96644be5f424bc04e5695f58f6c238 -0, 2, 2, 1, 42703, 6d6ea64b8808625638bb5e3e065042c1 -0, 3, 3, 1, 42170, 307615782d52350c1379caefc79123ab -0, 4, 4, 1, 42005, 5dfcc935564600944eb7b8a3a82fb569 diff --git a/tests/ref/fate/hapenc-hapa-snappy1 b/tests/ref/fate/hapenc-hapa-snappy1 deleted file mode 100644 index add69139fa9cc..0000000000000 --- a/tests/ref/fate/hapenc-hapa-snappy1 +++ /dev/null @@ -1,14 +0,0 @@ -#format: frame checksums -#version: 2 -#hash: MD5 -#tb 0: 1/25 -#media_type 0: video -#codec_id 0: hap -#dimensions 0: 352x288 -#sar 0: 0/1 -#stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 47912, ac94f44194b154b15b7008ef38ae2343 -0, 1, 1, 1, 48244, 21bff8df4137fdde2c836ea4c5aa10e0 -0, 2, 2, 1, 49175, 4a6053f4f81259ad201d10ac83e47524 -0, 3, 3, 1, 48159, 90df8d03d9d7bc99a22e439e4d79e9fc -0, 4, 4, 1, 47932, 8e719e872130057df3d3580f62693733 diff --git a/tests/ref/fate/hapenc-hapa-snappy16 b/tests/ref/fate/hapenc-hapa-snappy16 deleted file mode 100644 index 08613c011a766..0000000000000 --- a/tests/ref/fate/hapenc-hapa-snappy16 +++ /dev/null @@ -1,14 +0,0 @@ -#format: frame checksums -#version: 2 -#hash: MD5 -#tb 0: 1/25 -#media_type 0: video -#codec_id 0: hap -#dimensions 0: 352x288 -#sar 0: 0/1 -#stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 50172, d6100c76b42d6926497ff8c38d4ad5fb -0, 1, 1, 1, 50342, 62902c55f89169cb4dd46943e21f6f4a -0, 2, 2, 1, 51244, 64f44a60052dfbdd315e485f2ced97eb -0, 3, 3, 1, 50266, 05cd86de81a7e4e44ce9d1489d839ffa -0, 4, 4, 1, 50056, 2ee4234d16f3f13bec7ace5c8c2a94f5 diff --git a/tests/ref/fate/hapenc-hapq-snappy1 b/tests/ref/fate/hapenc-hapq-snappy1 deleted file mode 100644 index f22815057f599..0000000000000 --- a/tests/ref/fate/hapenc-hapq-snappy1 +++ /dev/null @@ -1,14 +0,0 @@ -#format: frame checksums -#version: 2 -#hash: MD5 -#tb 0: 1/25 -#media_type 0: video -#codec_id 0: hap -#dimensions 0: 352x288 -#sar 0: 0/1 -#stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 78214, a84391a7ca12ae34b7fea3e65c75a576 -0, 1, 1, 1, 79137, 2a75402a0e5a5e009cd16b341939fefd -0, 2, 2, 1, 80273, 67a555ea3e38cdcd76c03761a426c424 -0, 3, 3, 1, 78672, c3f883869d6cda0bb96e7c629faaefd2 -0, 4, 4, 1, 78941, 219761cabd005f8e7904a248ffbbcf8f diff --git a/tests/ref/fate/hapenc-hapq-snappy16 b/tests/ref/fate/hapenc-hapq-snappy16 deleted file mode 100644 index eac1799611d1c..0000000000000 --- a/tests/ref/fate/hapenc-hapq-snappy16 +++ /dev/null @@ -1,14 +0,0 @@ -#format: frame checksums -#version: 2 -#hash: MD5 -#tb 0: 1/25 -#media_type 0: video -#codec_id 0: hap -#dimensions 0: 352x288 -#sar 0: 0/1 -#stream#, dts, pts, duration, size, hash -0, 0, 0, 1, 81934, ad9ee8c455704cad6c641479085d81dd -0, 1, 1, 1, 82165, dde5dfcfa5507c3f943d4186490e9fa6 -0, 2, 2, 1, 83238, b1c9f8ce21d75e61dcd9d69726fd32cf -0, 3, 3, 1, 81773, 0ccaca5d91a1e41b0cb132826352be6f -0, 4, 4, 1, 82174, a629612d432620e61b82ac2f7c9a3619 From c51dbc2717203e60788fcb0f711a78b15c76a057 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Mar 2018 16:49:15 -0300 Subject: [PATCH 2143/2557] configure: revert changes to the schannel check check_cpp_condition was not being called on some targets, which made schannel remain enabled even when it was not available Signed-off-by: James Almer --- configure | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 97767f47dbc8f..f09f48c54baad 100755 --- a/configure +++ b/configure @@ -6126,7 +6126,9 @@ enabled securetransport && enabled schannel && check_func_headers "windows.h security.h" InitializeSecurityContext -DSECURITY_WIN32 -lsecur32 && - check_cpp_condition schannel winerror.h "defined(SEC_I_CONTEXT_EXPIRED)" && schannel_extralibs="-lsecur32" + test_cpp_condition winerror.h "defined(SEC_I_CONTEXT_EXPIRED)" && + schannel_extralibs="-lsecur32" || + disable schannel makeinfo --version > /dev/null 2>&1 && enable makeinfo || disable makeinfo enabled makeinfo \ From 86c7d8df95c15625ee582254e92f0d494e7d2d9f Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 17 Mar 2018 17:17:25 -0300 Subject: [PATCH 2144/2557] avformat/codec2: don't include avcodec objects They belong in avcodec. Signed-off-by: James Almer --- libavcodec/Makefile | 3 +++ libavformat/Makefile | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 0984455ec4221..b15f677bdd494 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -897,6 +897,9 @@ OBJS-$(CONFIG_ISO_MEDIA) += mpeg4audio.o mpegaudiodata.o OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o OBJS-$(CONFIG_CAF_DEMUXER) += ac3tab.o +OBJS-$(CONFIG_CODEC2_DEMUXER) += codec2utils.o +OBJS-$(CONFIG_CODEC2_MUXER) += codec2utils.o +OBJS-$(CONFIG_CODEC2RAW_DEMUXER) += codec2utils.o OBJS-$(CONFIG_DNXHD_DEMUXER) += dnxhddata.o OBJS-$(CONFIG_FITS_DEMUXER) += fits.o OBJS-$(CONFIG_FLV_DEMUXER) += mpeg4audio.o diff --git a/libavformat/Makefile b/libavformat/Makefile index e64c5b30a1e15..39ec68c28b893 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -133,9 +133,9 @@ OBJS-$(CONFIG_CAVSVIDEO_MUXER) += rawenc.o OBJS-$(CONFIG_CDG_DEMUXER) += cdg.o OBJS-$(CONFIG_CDXL_DEMUXER) += cdxl.o OBJS-$(CONFIG_CINE_DEMUXER) += cinedec.o -OBJS-$(CONFIG_CODEC2_DEMUXER) += ../libavcodec/codec2utils.o codec2.o rawdec.o pcm.o -OBJS-$(CONFIG_CODEC2_MUXER) += ../libavcodec/codec2utils.o codec2.o rawenc.o -OBJS-$(CONFIG_CODEC2RAW_DEMUXER) += ../libavcodec/codec2utils.o codec2.o rawdec.o pcm.o +OBJS-$(CONFIG_CODEC2_DEMUXER) += codec2.o rawdec.o pcm.o +OBJS-$(CONFIG_CODEC2_MUXER) += codec2.o rawenc.o +OBJS-$(CONFIG_CODEC2RAW_DEMUXER) += codec2.o rawdec.o pcm.o OBJS-$(CONFIG_CODEC2RAW_MUXER) += rawenc.o OBJS-$(CONFIG_CONCAT_DEMUXER) += concatdec.o OBJS-$(CONFIG_CRC_MUXER) += crcenc.o From ea2f72a2c14c67a3b35dac6426d1e3c0fae33fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 15 Mar 2018 23:47:22 +0200 Subject: [PATCH 2145/2557] configure: Don't assume a 16 byte aligned stack on BSDs on i386 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With GCC, request it to maintain 16 byte alignment, and the existing entry points already align it via attribute_align_arg. With clang, do the same as for mingw; disable the aligned stack and let the assembly functions that require it do the alignment instead. Signed-off-by: Martin Storsjö --- configure | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 95e60064401e1..78a2065208de9 100755 --- a/configure +++ b/configure @@ -4957,16 +4957,34 @@ elif enabled gcc; then check_cflags -Werror=format-security check_cflags -fdiagnostics-color=auto enabled extra_warnings || check_disable_warning -Wno-maybe-uninitialized + if enabled x86_32; then + case $target_os in + *bsd*) + # BSDs don't guarantee a 16 byte aligned stack, but we can + # request GCC to try to maintain 16 byte alignment throughout + # function calls. Library entry points that might call assembly + # functions align the stack. (The parameter means 2^4 bytes.) + check_cflags -mpreferred-stack-boundary=4 + ;; + esac + fi elif enabled llvm_gcc; then check_cflags -mllvm -stack-alignment=16 elif enabled clang; then - if [ "$target_os" = "mingw32" -o "$target_os" = "win32" ] && enabled x86_32; then + if enabled x86_32; then # Clang doesn't support maintaining alignment without assuming the # same alignment in every function. If 16 byte alignment would be # enabled, one would also have to either add attribute_align_arg on # every single entry point into the libraries or enable -mstackrealign # (doing stack realignment in every single function). - disable aligned_stack + case $target_os in + mingw32|win32|*bsd*) + disable aligned_stack + ;; + *) + check_cflags -mllvm -stack-alignment=16 + ;; + esac else check_cflags -mllvm -stack-alignment=16 fi From 99230b7ef874129ffd3ccca0e799c66970258203 Mon Sep 17 00:00:00 2001 From: Ravindra Date: Mon, 5 Mar 2018 15:07:26 +0530 Subject: [PATCH 2146/2557] libavformat/dashenc: Option to set timeout for socket I/O operation --- doc/muxers.texi | 2 ++ libavformat/dashenc.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/doc/muxers.texi b/doc/muxers.texi index 3a63da7fe72d0..cb75c261c5582 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -264,6 +264,8 @@ of the adaptation sets and a,b,c,d and e are the indices of the mapped streams. To map all video (or audio) streams to an AdaptationSet, "v" (or "a") can be used as stream identifier instead of IDs. When no assignment is defined, this defaults to an AdaptationSet for each stream. +@item -timeout @var{timeout} +Set timeout for socket I/O operations. Applicable only for HTTP output. @end table @anchor{framecrc} diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 79d63e52d439b..9feb4f1afb815 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -117,6 +117,7 @@ typedef struct DASHContext { AVIOContext *mpd_out; AVIOContext *m3u8_out; int streaming; + int64_t timeout; } DASHContext; static struct codec_string { @@ -269,6 +270,8 @@ static void set_http_options(AVDictionary **options, DASHContext *c) av_dict_set(options, "user_agent", c->user_agent, 0); if (c->http_persistent) av_dict_set_int(options, "multiple_requests", 1, 0); + if (c->timeout >= 0) + av_dict_set_int(options, "timeout", c->timeout, 0); } static void get_hls_playlist_name(char *playlist_name, int string_size, @@ -1440,6 +1443,7 @@ static const AVOption options[] = { { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, + { "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E }, { NULL }, }; From 08e0f45cc88903967da5a76e18be45d7406397f7 Mon Sep 17 00:00:00 2001 From: Rodger Combs Date: Wed, 14 Mar 2018 01:24:39 -0500 Subject: [PATCH 2147/2557] lavf/dashenc: remove unneeded call to dash_free --- libavformat/dashenc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 9feb4f1afb815..bdf8c8d5601e8 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1033,10 +1033,8 @@ static int dash_write_header(AVFormatContext *s) int i, ret; for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; - if ((ret = avformat_write_header(os->ctx, NULL)) < 0) { - dash_free(s); + if ((ret = avformat_write_header(os->ctx, NULL)) < 0) return ret; - } } ret = write_manifest(s, 0); if (!ret) From a92ca3c07c89855d46c801ef05428b5d86a1b30c Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Sun, 18 Mar 2018 14:07:00 +0800 Subject: [PATCH 2148/2557] avformat/hlsenc: fix write wrong init file URI string problem fmp4_init_filename should append after base_output_dirname Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 58d403d3fa4dd..3df0784146e99 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -2583,21 +2583,6 @@ static int hls_init(AVFormatContext *s) } av_strlcpy(vs->fmp4_init_filename, hls->fmp4_init_filename, fmp4_init_filename_len); - - if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) { - ret = format_name(vs->fmp4_init_filename, fmp4_init_filename_len, i); - if (ret < 0) - goto fail; - - fmp4_init_filename_len = strlen(vs->fmp4_init_filename) + 1; - vs->base_output_dirname = av_malloc(fmp4_init_filename_len); - if (!vs->base_output_dirname) { - ret = AVERROR(ENOMEM); - goto fail; - } - av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, - fmp4_init_filename_len); - } else { if (hls->nb_varstreams > 1) { ret = append_postfix(vs->fmp4_init_filename, fmp4_init_filename_len, i); if (ret < 0) @@ -2624,7 +2609,6 @@ static int hls_init(AVFormatContext *s) av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, fmp4_init_filename_len); } - } } if (!hls->use_localtime) { From 10a0436dcab3dd51d70c391ba299f9a7e8521018 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Sun, 18 Mar 2018 14:07:40 +0800 Subject: [PATCH 2149/2557] avformat/hlsenc: reindent after previous commits Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 3df0784146e99..2271cedbfcc2b 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -2583,32 +2583,32 @@ static int hls_init(AVFormatContext *s) } av_strlcpy(vs->fmp4_init_filename, hls->fmp4_init_filename, fmp4_init_filename_len); - if (hls->nb_varstreams > 1) { - ret = append_postfix(vs->fmp4_init_filename, fmp4_init_filename_len, i); - if (ret < 0) - goto fail; - } + if (hls->nb_varstreams > 1) { + ret = append_postfix(vs->fmp4_init_filename, fmp4_init_filename_len, i); + if (ret < 0) + goto fail; + } - fmp4_init_filename_len = strlen(vs->m3u8_name) + - strlen(vs->fmp4_init_filename) + 1; + fmp4_init_filename_len = strlen(vs->m3u8_name) + + strlen(vs->fmp4_init_filename) + 1; - vs->base_output_dirname = av_malloc(fmp4_init_filename_len); - if (!vs->base_output_dirname) { - ret = AVERROR(ENOMEM); - goto fail; - } + vs->base_output_dirname = av_malloc(fmp4_init_filename_len); + if (!vs->base_output_dirname) { + ret = AVERROR(ENOMEM); + goto fail; + } - av_strlcpy(vs->base_output_dirname, vs->m3u8_name, + av_strlcpy(vs->base_output_dirname, vs->m3u8_name, + fmp4_init_filename_len); + p = strrchr(vs->base_output_dirname, '/'); + if (p) { + *(p + 1) = '\0'; + av_strlcat(vs->base_output_dirname, vs->fmp4_init_filename, fmp4_init_filename_len); - p = strrchr(vs->base_output_dirname, '/'); - if (p) { - *(p + 1) = '\0'; - av_strlcat(vs->base_output_dirname, vs->fmp4_init_filename, - fmp4_init_filename_len); - } else { - av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, - fmp4_init_filename_len); - } + } else { + av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, + fmp4_init_filename_len); + } } if (!hls->use_localtime) { From c6086692645951264a4f98a3568f80b7c827a129 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Sun, 18 Mar 2018 14:08:14 +0800 Subject: [PATCH 2150/2557] avformat/hlsenc: fix memleak problem about fmp4_init_filename move fmp4_init_filename init in if else for first fmp4_init_filename set value operation. Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 2271cedbfcc2b..d64755436ed2a 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -2576,6 +2576,13 @@ static int hls_init(AVFormatContext *s) if (hls->segment_type == SEGMENT_TYPE_FMP4) { if (hls->nb_varstreams > 1) fmp4_init_filename_len += strlen(POSTFIX_PATTERN); + if (hls->flags & HLS_SINGLE_FILE) { + vs->fmp4_init_filename = av_strdup(vs->basename); + if (!vs->fmp4_init_filename) { + ret = AVERROR(ENOMEM); + goto fail; + } + } else { vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len); if (!vs->fmp4_init_filename ) { ret = AVERROR(ENOMEM); @@ -2609,6 +2616,7 @@ static int hls_init(AVFormatContext *s) av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, fmp4_init_filename_len); } + } } if (!hls->use_localtime) { @@ -2663,13 +2671,6 @@ static int hls_init(AVFormatContext *s) } } - if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) { - vs->fmp4_init_filename = av_strdup(vs->basename); - if (!vs->fmp4_init_filename) { - ret = AVERROR(ENOMEM); - goto fail; - } - } if ((ret = hls_mux_init(s, vs)) < 0) goto fail; From c8f625f52998faa9bf0fe22701f1684e51edfc07 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Sun, 18 Mar 2018 14:08:57 +0800 Subject: [PATCH 2151/2557] avformat/hlsenc: fix fmp4 single init file problem fix ticket: #7021 Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 66 +++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index d64755436ed2a..afd3cfe02abae 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -765,7 +765,11 @@ static int hls_mux_init(AVFormatContext *s, VariantStream *vs) if ((ret = avio_open_dyn_buf(&oc->pb)) < 0) return ret; - ret = hlsenc_io_open(s, &vs->out, vs->base_output_dirname, &options); + if (byterange_mode) { + ret = hlsenc_io_open(s, &vs->out, vs->basename, &options); + } else { + ret = hlsenc_io_open(s, &vs->out, vs->base_output_dirname, &options); + } av_dict_free(&options); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", vs->fmp4_init_filename); @@ -1397,8 +1401,8 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) } if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == vs->segments)) { - ff_hls_write_init_file(hls->m3u8_out, vs->fmp4_init_filename, - hls->flags & HLS_SINGLE_FILE, en->size, en->pos); + ff_hls_write_init_file(hls->m3u8_out, (hls->flags & HLS_SINGLE_FILE) ? en->filename : vs->fmp4_init_filename, + hls->flags & HLS_SINGLE_FILE, vs->init_range_length, 0); } ret = ff_hls_write_file_entry(hls->m3u8_out, en->discont, byterange_mode, @@ -2177,9 +2181,12 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) av_write_frame(vs->avf, NULL); /* Flush any buffered data */ new_start_pos = avio_tell(vs->avf->pb); - vs->size = new_start_pos - vs->start_pos; + if (hls->segment_type != SEGMENT_TYPE_FMP4) { + vs->size = new_start_pos - vs->start_pos; + } else { + vs->size = new_start_pos; + } - if (!byterange_mode) { if (hls->segment_type == SEGMENT_TYPE_FMP4) { if (!vs->init_range_length) { avio_flush(oc->pb); @@ -2188,16 +2195,22 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) vs->init_range_length = range_length; avio_open_dyn_buf(&oc->pb); vs->packets_written = 0; - ff_format_io_close(s, &vs->out); - hlsenc_io_close(s, &vs->out, vs->base_output_dirname); + vs->start_pos = range_length; + if (!byterange_mode) { + ff_format_io_close(s, &vs->out); + hlsenc_io_close(s, &vs->out, vs->base_output_dirname); + } } } else { + if (!byterange_mode) { hlsenc_io_close(s, &oc->pb, oc->url); + } } + if (!byterange_mode) { if (vs->vtt_avf) { hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->url); } - } + } if ((hls->flags & HLS_TEMP_FILE) && oc->url[0]) { if (!(hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size <= 0)) if ((vs->avf->oformat->priv_class && vs->avf->priv_data) && hls->segment_type != SEGMENT_TYPE_FMP4) @@ -2210,6 +2223,14 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) } if (hls->segment_type == SEGMENT_TYPE_FMP4) { + if (hls->flags & HLS_SINGLE_FILE) { + ret = flush_dynbuf(vs, &range_length); + if (ret < 0) { + av_free(old_filename); + return ret; + } + vs->size = range_length; + } else { ret = hlsenc_io_open(s, &vs->out, vs->avf->url, NULL); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", @@ -2222,6 +2243,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) return ret; } ff_format_io_close(s, &vs->out); + } } old_filename = av_strdup(vs->avf->url); @@ -2229,15 +2251,21 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(ENOMEM); } - ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size); - vs->start_pos = new_start_pos; - if (ret < 0) { - av_free(old_filename); - return ret; + if (vs->start_pos || hls->segment_type != SEGMENT_TYPE_FMP4) { + ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size); + vs->end_pts = pkt->pts; + vs->duration = 0; + if (ret < 0) { + av_free(old_filename); + return ret; + } } - vs->end_pts = pkt->pts; - vs->duration = 0; + if (hls->segment_type != SEGMENT_TYPE_FMP4) { + vs->start_pos = new_start_pos; + } else { + vs->start_pos += vs->size; + } vs->fmp4_init_mode = 0; if (hls->flags & HLS_SINGLE_FILE) { @@ -2297,12 +2325,14 @@ static int hls_write_trailer(struct AVFormatContext *s) } if ( hls->segment_type == SEGMENT_TYPE_FMP4) { int range_length = 0; + if (!(hls->flags & HLS_SINGLE_FILE)) { ret = hlsenc_io_open(s, &vs->out, vs->avf->url, NULL); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", vs->avf->url); goto failed; } write_styp(vs->out); + } ret = flush_dynbuf(vs, &range_length); if (ret < 0) { goto failed; @@ -2313,7 +2343,11 @@ static int hls_write_trailer(struct AVFormatContext *s) failed: av_write_trailer(oc); if (oc->pb) { - vs->size = avio_tell(vs->avf->pb) - vs->start_pos; + if (hls->segment_type != SEGMENT_TYPE_FMP4) { + vs->size = avio_tell(vs->avf->pb) - vs->start_pos; + } else { + vs->size = avio_tell(vs->avf->pb); + } if (hls->segment_type != SEGMENT_TYPE_FMP4) ff_format_io_close(s, &oc->pb); From f19b0c6aeea212a3c2e05d4cebb856d1d774def7 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Sun, 18 Mar 2018 14:09:44 +0800 Subject: [PATCH 2152/2557] avformat/hlsenc: reindent after previous commits Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 250 +++++++++++++++++++++---------------------- 1 file changed, 125 insertions(+), 125 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index afd3cfe02abae..b7c6fbde6ae76 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -2173,7 +2173,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) } if (vs->packets_written && can_split && av_compare_ts(pkt->pts - vs->start_pts, st->time_base, - end_pts, AV_TIME_BASE_Q) >= 0) { + end_pts, AV_TIME_BASE_Q) >= 0) { int64_t new_start_pos; char *old_filename = NULL; int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); @@ -2187,30 +2187,30 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) vs->size = new_start_pos; } - if (hls->segment_type == SEGMENT_TYPE_FMP4) { - if (!vs->init_range_length) { - avio_flush(oc->pb); - range_length = avio_close_dyn_buf(oc->pb, &buffer); - avio_write(vs->out, buffer, range_length); - vs->init_range_length = range_length; - avio_open_dyn_buf(&oc->pb); - vs->packets_written = 0; - vs->start_pos = range_length; - if (!byterange_mode) { - ff_format_io_close(s, &vs->out); - hlsenc_io_close(s, &vs->out, vs->base_output_dirname); - } - } - } else { + if (hls->segment_type == SEGMENT_TYPE_FMP4) { + if (!vs->init_range_length) { + avio_flush(oc->pb); + range_length = avio_close_dyn_buf(oc->pb, &buffer); + avio_write(vs->out, buffer, range_length); + vs->init_range_length = range_length; + avio_open_dyn_buf(&oc->pb); + vs->packets_written = 0; + vs->start_pos = range_length; if (!byterange_mode) { - hlsenc_io_close(s, &oc->pb, oc->url); + ff_format_io_close(s, &vs->out); + hlsenc_io_close(s, &vs->out, vs->base_output_dirname); } } + } else { if (!byterange_mode) { + hlsenc_io_close(s, &oc->pb, oc->url); + } + } + if (!byterange_mode) { if (vs->vtt_avf) { hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->url); } - } + } if ((hls->flags & HLS_TEMP_FILE) && oc->url[0]) { if (!(hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size <= 0)) if ((vs->avf->oformat->priv_class && vs->avf->priv_data) && hls->segment_type != SEGMENT_TYPE_FMP4) @@ -2231,18 +2231,18 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) } vs->size = range_length; } else { - ret = hlsenc_io_open(s, &vs->out, vs->avf->url, NULL); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", - vs->avf->url); - return ret; - } - write_styp(vs->out); - ret = flush_dynbuf(vs, &range_length); - if (ret < 0) { - return ret; - } - ff_format_io_close(s, &vs->out); + ret = hlsenc_io_open(s, &vs->out, vs->avf->url, NULL); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", + vs->avf->url); + return ret; + } + write_styp(vs->out); + ret = flush_dynbuf(vs, &range_length); + if (ret < 0) { + return ret; + } + ff_format_io_close(s, &vs->out); } } @@ -2316,85 +2316,85 @@ static int hls_write_trailer(struct AVFormatContext *s) for (i = 0; i < hls->nb_varstreams; i++) { vs = &hls->var_streams[i]; - oc = vs->avf; - vtt_oc = vs->vtt_avf; - old_filename = av_strdup(vs->avf->url); + oc = vs->avf; + vtt_oc = vs->vtt_avf; + old_filename = av_strdup(vs->avf->url); - if (!old_filename) { - return AVERROR(ENOMEM); - } - if ( hls->segment_type == SEGMENT_TYPE_FMP4) { - int range_length = 0; - if (!(hls->flags & HLS_SINGLE_FILE)) { - ret = hlsenc_io_open(s, &vs->out, vs->avf->url, NULL); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Failed to open file '%s'\n", vs->avf->url); - goto failed; - } - write_styp(vs->out); + if (!old_filename) { + return AVERROR(ENOMEM); } - ret = flush_dynbuf(vs, &range_length); - if (ret < 0) { - goto failed; + if ( hls->segment_type == SEGMENT_TYPE_FMP4) { + int range_length = 0; + if (!(hls->flags & HLS_SINGLE_FILE)) { + ret = hlsenc_io_open(s, &vs->out, vs->avf->url, NULL); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", vs->avf->url); + goto failed; + } + write_styp(vs->out); + } + ret = flush_dynbuf(vs, &range_length); + if (ret < 0) { + goto failed; + } + ff_format_io_close(s, &vs->out); } - ff_format_io_close(s, &vs->out); - } failed: - av_write_trailer(oc); - if (oc->pb) { - if (hls->segment_type != SEGMENT_TYPE_FMP4) { - vs->size = avio_tell(vs->avf->pb) - vs->start_pos; - } else { - vs->size = avio_tell(vs->avf->pb); - } - if (hls->segment_type != SEGMENT_TYPE_FMP4) - ff_format_io_close(s, &oc->pb); + av_write_trailer(oc); + if (oc->pb) { + if (hls->segment_type != SEGMENT_TYPE_FMP4) { + vs->size = avio_tell(vs->avf->pb) - vs->start_pos; + } else { + vs->size = avio_tell(vs->avf->pb); + } + if (hls->segment_type != SEGMENT_TYPE_FMP4) + ff_format_io_close(s, &oc->pb); - if ((hls->flags & HLS_TEMP_FILE) && oc->url[0]) { - hls_rename_temp_file(s, oc); - av_free(old_filename); - old_filename = av_strdup(vs->avf->url); + if ((hls->flags & HLS_TEMP_FILE) && oc->url[0]) { + hls_rename_temp_file(s, oc); + av_free(old_filename); + old_filename = av_strdup(vs->avf->url); - if (!old_filename) { - return AVERROR(ENOMEM); + if (!old_filename) { + return AVERROR(ENOMEM); + } } - } - /* after av_write_trailer, then duration + 1 duration per packet */ - hls_append_segment(s, hls, vs, vs->duration + vs->dpp, vs->start_pos, vs->size); - } + /* after av_write_trailer, then duration + 1 duration per packet */ + hls_append_segment(s, hls, vs, vs->duration + vs->dpp, vs->start_pos, vs->size); + } - sls_flag_file_rename(hls, vs, old_filename); + sls_flag_file_rename(hls, vs, old_filename); - if (vtt_oc) { - if (vtt_oc->pb) - av_write_trailer(vtt_oc); - vs->size = avio_tell(vs->vtt_avf->pb) - vs->start_pos; - ff_format_io_close(s, &vtt_oc->pb); - } - av_freep(&vs->basename); - av_freep(&vs->base_output_dirname); - avformat_free_context(oc); + if (vtt_oc) { + if (vtt_oc->pb) + av_write_trailer(vtt_oc); + vs->size = avio_tell(vs->vtt_avf->pb) - vs->start_pos; + ff_format_io_close(s, &vtt_oc->pb); + } + av_freep(&vs->basename); + av_freep(&vs->base_output_dirname); + avformat_free_context(oc); - vs->avf = NULL; - hls_window(s, 1, vs); + vs->avf = NULL; + hls_window(s, 1, vs); - av_freep(&vs->fmp4_init_filename); - if (vtt_oc) { - av_freep(&vs->vtt_basename); - av_freep(&vs->vtt_m3u8_name); - avformat_free_context(vtt_oc); - } + av_freep(&vs->fmp4_init_filename); + if (vtt_oc) { + av_freep(&vs->vtt_basename); + av_freep(&vs->vtt_m3u8_name); + avformat_free_context(vtt_oc); + } - hls_free_segments(vs->segments); - hls_free_segments(vs->old_segments); - av_free(old_filename); - av_freep(&vs->m3u8_name); - av_freep(&vs->streams); - av_freep(&vs->agroup); - av_freep(&vs->ccgroup); - av_freep(&vs->baseurl); + hls_free_segments(vs->segments); + hls_free_segments(vs->old_segments); + av_free(old_filename); + av_freep(&vs->m3u8_name); + av_freep(&vs->streams); + av_freep(&vs->agroup); + av_freep(&vs->ccgroup); + av_freep(&vs->baseurl); } for (i = 0; i < hls->nb_ccstreams; i++) { @@ -2432,7 +2432,7 @@ static int hls_init(AVFormatContext *s) ret = update_variant_stream_info(s); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n", - ret); + ret); goto fail; } //TODO: Updates needed to encryption functionality with periodic re-key when more than one variant streams are present @@ -2468,7 +2468,7 @@ static int hls_init(AVFormatContext *s) ret = update_master_pl_info(s); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n", - ret); + ret); goto fail; } } @@ -2617,39 +2617,39 @@ static int hls_init(AVFormatContext *s) goto fail; } } else { - vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len); - if (!vs->fmp4_init_filename ) { - ret = AVERROR(ENOMEM); - goto fail; - } - av_strlcpy(vs->fmp4_init_filename, hls->fmp4_init_filename, - fmp4_init_filename_len); - if (hls->nb_varstreams > 1) { - ret = append_postfix(vs->fmp4_init_filename, fmp4_init_filename_len, i); - if (ret < 0) + vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len); + if (!vs->fmp4_init_filename ) { + ret = AVERROR(ENOMEM); goto fail; - } + } + av_strlcpy(vs->fmp4_init_filename, hls->fmp4_init_filename, + fmp4_init_filename_len); + if (hls->nb_varstreams > 1) { + ret = append_postfix(vs->fmp4_init_filename, fmp4_init_filename_len, i); + if (ret < 0) + goto fail; + } - fmp4_init_filename_len = strlen(vs->m3u8_name) + - strlen(vs->fmp4_init_filename) + 1; + fmp4_init_filename_len = strlen(vs->m3u8_name) + + strlen(vs->fmp4_init_filename) + 1; - vs->base_output_dirname = av_malloc(fmp4_init_filename_len); - if (!vs->base_output_dirname) { - ret = AVERROR(ENOMEM); - goto fail; - } + vs->base_output_dirname = av_malloc(fmp4_init_filename_len); + if (!vs->base_output_dirname) { + ret = AVERROR(ENOMEM); + goto fail; + } - av_strlcpy(vs->base_output_dirname, vs->m3u8_name, - fmp4_init_filename_len); - p = strrchr(vs->base_output_dirname, '/'); - if (p) { - *(p + 1) = '\0'; - av_strlcat(vs->base_output_dirname, vs->fmp4_init_filename, + av_strlcpy(vs->base_output_dirname, vs->m3u8_name, fmp4_init_filename_len); - } else { - av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, - fmp4_init_filename_len); - } + p = strrchr(vs->base_output_dirname, '/'); + if (p) { + *(p + 1) = '\0'; + av_strlcat(vs->base_output_dirname, vs->fmp4_init_filename, + fmp4_init_filename_len); + } else { + av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, + fmp4_init_filename_len); + } } } From 36855abc0eb96d5caa992304f3417a0f8a62960c Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 1 Mar 2018 15:50:56 +0100 Subject: [PATCH 2153/2557] lavu/frame: fix inconsistent qp_table_buf deprecation Everything related to the QP data is deprecated, with qp_table_buf being an inconsistent exception. Some parts were under the deprecation guards, some not. It probably didn't even compile. --- libavutil/frame.c | 7 ++++--- libavutil/frame.h | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libavutil/frame.c b/libavutil/frame.c index 61c45f0f53247..0db2a2d57b69d 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -48,11 +48,10 @@ MAKE_ACCESSORS(AVFrame, frame, enum AVColorRange, color_range) #if FF_API_FRAME_QP int av_frame_set_qp_table(AVFrame *f, AVBufferRef *buf, int stride, int qp_type) { +FF_DISABLE_DEPRECATION_WARNINGS av_buffer_unref(&f->qp_table_buf); f->qp_table_buf = buf; - -FF_DISABLE_DEPRECATION_WARNINGS f->qscale_table = buf->data; f->qstride = stride; f->qscale_type = qp_type; @@ -66,12 +65,12 @@ int8_t *av_frame_get_qp_table(AVFrame *f, int *stride, int *type) FF_DISABLE_DEPRECATION_WARNINGS *stride = f->qstride; *type = f->qscale_type; -FF_ENABLE_DEPRECATION_WARNINGS if (!f->qp_table_buf) return NULL; return f->qp_table_buf->data; +FF_ENABLE_DEPRECATION_WARNINGS } #endif @@ -520,7 +519,9 @@ void av_frame_unref(AVFrame *frame) av_freep(&frame->extended_buf); av_dict_free(&frame->metadata); #if FF_API_FRAME_QP +FF_DISABLE_DEPRECATION_WARNINGS av_buffer_unref(&frame->qp_table_buf); +FF_ENABLE_DEPRECATION_WARNINGS #endif av_buffer_unref(&frame->hw_frames_ctx); diff --git a/libavutil/frame.h b/libavutil/frame.h index 59cee8ceabc68..ddbac3156dcf7 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -529,6 +529,7 @@ typedef struct AVFrame { attribute_deprecated int qscale_type; + attribute_deprecated AVBufferRef *qp_table_buf; #endif /** From 4b86ac27a017ccd1d166f0bdd38c08720c561f7d Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 1 Mar 2018 15:57:01 +0100 Subject: [PATCH 2154/2557] lavu/frame: add QP side data This adds a way for an API user to transfer QP data and metadata without having to keep the reference to AVFrame, and without having to explicitly care about QP APIs. It might also provide a way to finally remove the deprecated QP related fields. In the end, the QP table should be handled in a very similar way to e.g. AV_FRAME_DATA_MOTION_VECTORS. There are two side data types, because I didn't care about having to repack the QP data so the table and the metadata are in a single AVBufferRef. Otherwise it would have either required a copy on decoding (extra slowdown for something as obscure as the QP data), or would have required making intrusive changes to the codecs which support export of this data. The new side data types are added under deprecation guards, because I don't intend to change the status of the QP export as being deprecated (as it was before this patch too). --- doc/APIchanges | 3 ++ libavutil/frame.c | 59 +++++++++++++++++++++++++++--- libavutil/frame.h | 17 +++++++++ libavutil/version.h | 2 +- tests/ref/fate/exif-image-embedded | 6 +++ tests/ref/fate/exif-image-jpg | 6 +++ 6 files changed, 86 insertions(+), 7 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index f757f5063ed4e..4c0ee7147a15a 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-03-18 - xxxxxxx - lavu 56.11.100 - frame.h + Add AV_FRAME_DATA_QP_TABLE_PROPERTIES and AV_FRAME_DATA_QP_TABLE_DATA. + 2018-03-15 - e0e72539cf - lavu 56.10.100 - opt.h Add AV_OPT_FLAG_BSF_PARAM diff --git a/libavutil/frame.c b/libavutil/frame.c index 0db2a2d57b69d..ea13cd3ed61a9 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -46,8 +46,17 @@ MAKE_ACCESSORS(AVFrame, frame, enum AVColorRange, color_range) av_get_channel_layout_nb_channels((frame)->channel_layout)) #if FF_API_FRAME_QP +struct qp_properties { + int stride; + int type; +}; + int av_frame_set_qp_table(AVFrame *f, AVBufferRef *buf, int stride, int qp_type) { + struct qp_properties *p; + AVFrameSideData *sd; + AVBufferRef *ref; + FF_DISABLE_DEPRECATION_WARNINGS av_buffer_unref(&f->qp_table_buf); @@ -57,20 +66,56 @@ FF_DISABLE_DEPRECATION_WARNINGS f->qscale_type = qp_type; FF_ENABLE_DEPRECATION_WARNINGS + av_frame_remove_side_data(f, AV_FRAME_DATA_QP_TABLE_PROPERTIES); + av_frame_remove_side_data(f, AV_FRAME_DATA_QP_TABLE_DATA); + + ref = av_buffer_ref(buf); + if (!av_frame_new_side_data_from_buf(f, AV_FRAME_DATA_QP_TABLE_DATA, ref)) { + av_buffer_unref(&ref); + return AVERROR(ENOMEM); + } + + sd = av_frame_new_side_data(f, AV_FRAME_DATA_QP_TABLE_PROPERTIES, + sizeof(struct qp_properties)); + if (!sd) + return AVERROR(ENOMEM); + + p = (struct qp_properties *)sd->data; + p->stride = stride; + p->type = qp_type; + return 0; } int8_t *av_frame_get_qp_table(AVFrame *f, int *stride, int *type) { -FF_DISABLE_DEPRECATION_WARNINGS - *stride = f->qstride; - *type = f->qscale_type; + AVBufferRef *buf = NULL; - if (!f->qp_table_buf) - return NULL; + *stride = 0; + *type = 0; - return f->qp_table_buf->data; +FF_DISABLE_DEPRECATION_WARNINGS + if (f->qp_table_buf) { + *stride = f->qstride; + *type = f->qscale_type; + buf = f->qp_table_buf; FF_ENABLE_DEPRECATION_WARNINGS + } else { + AVFrameSideData *sd; + struct qp_properties *p; + sd = av_frame_get_side_data(f, AV_FRAME_DATA_QP_TABLE_PROPERTIES); + if (!sd) + return NULL; + p = (struct qp_properties *)sd->data; + sd = av_frame_get_side_data(f, AV_FRAME_DATA_QP_TABLE_DATA); + if (!sd) + return NULL; + *stride = p->stride; + *type = p->type; + buf = sd->buf; + } + + return buf ? buf->data : NULL; } #endif @@ -787,6 +832,8 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type) case AV_FRAME_DATA_CONTENT_LIGHT_LEVEL: return "Content light level metadata"; case AV_FRAME_DATA_GOP_TIMECODE: return "GOP timecode"; case AV_FRAME_DATA_ICC_PROFILE: return "ICC profile"; + case AV_FRAME_DATA_QP_TABLE_PROPERTIES: return "QP table properties"; + case AV_FRAME_DATA_QP_TABLE_DATA: return "QP table data"; } return NULL; } diff --git a/libavutil/frame.h b/libavutil/frame.h index ddbac3156dcf7..9d57d6ce66ff9 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -141,6 +141,23 @@ enum AVFrameSideDataType { * metadata key entry "name". */ AV_FRAME_DATA_ICC_PROFILE, + +#if FF_API_FRAME_QP + /** + * Implementation-specific description of the format of AV_FRAME_QP_TABLE_DATA. + * The contents of this side data are undocumented and internal; use + * av_frame_set_qp_table() and av_frame_get_qp_table() to access this in a + * meaningful way instead. + */ + AV_FRAME_DATA_QP_TABLE_PROPERTIES, + + /** + * Raw QP table data. Its format is described by + * AV_FRAME_DATA_QP_TABLE_PROPERTIES. Use av_frame_set_qp_table() and + * av_frame_get_qp_table() to access this instead. + */ + AV_FRAME_DATA_QP_TABLE_DATA, +#endif }; enum AVActiveFormatDescription { diff --git a/libavutil/version.h b/libavutil/version.h index 9ca556ddc9d1c..d166bb30e7c53 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 10 +#define LIBAVUTIL_VERSION_MINOR 11 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/tests/ref/fate/exif-image-embedded b/tests/ref/fate/exif-image-embedded index 306ae0854b1a8..0b640767a88e3 100644 --- a/tests/ref/fate/exif-image-embedded +++ b/tests/ref/fate/exif-image-embedded @@ -29,6 +29,12 @@ color_transfer=unknown chroma_location=center TAG:UserComment=AppleMark +[SIDE_DATA] +side_data_type=QP table data +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=QP table properties +[/SIDE_DATA] [/FRAME] [FRAME] media_type=audio diff --git a/tests/ref/fate/exif-image-jpg b/tests/ref/fate/exif-image-jpg index b266501191bed..eb18dede21925 100644 --- a/tests/ref/fate/exif-image-jpg +++ b/tests/ref/fate/exif-image-jpg @@ -229,4 +229,10 @@ TAG:ExposureMode= 0 TAG:WhiteBalance= 0 TAG:DigitalZoomRatio= 4000:4000 TAG:SceneCaptureType= 0 +[SIDE_DATA] +side_data_type=QP table data +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=QP table properties +[/SIDE_DATA] [/FRAME] From 39c1d170a3474a06f4805589d642f605f7ef1436 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 8 Mar 2018 04:30:35 +0100 Subject: [PATCH 2155/2557] http: do not print a warning message for expired cookies libavformat prints a warning that the cookie couldn't be parsed (see callers of parse_cookie()). This is obviously not true - it could be parsed, but was simply ignored. Don't return an error to avoid the warning. --- libavformat/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/http.c b/libavformat/http.c index 344fd603cb9b0..d7a72e7129728 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -802,7 +802,7 @@ static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies) // if the cookie has already expired ignore it if (av_timegm(&new_tm) < av_gettime() / 1000000) { av_dict_free(&new_params); - return -1; + return 0; } // only replace an older cookie with the same name From c0687acbf6094053834af6a20e9d71b455842c8c Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 8 Mar 2018 04:47:40 +0100 Subject: [PATCH 2156/2557] http: avoid out of bound accesses on broken Set-Cookie headers It's trivial to craft a HTTP response that will make the code for skipping trailing whitespace access and possibly overwrite bytes outside of the memory allocation. Why this can happen is blindingly obvious: it accesses cstr[strlen(cstr)-1] without checking whether the string is empty. --- libavformat/http.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index d7a72e7129728..59f90ac603469 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -750,6 +750,9 @@ static int parse_set_cookie(const char *set_cookie, AVDictionary **dict) { char *param, *next_param, *cstr, *back; + if (!set_cookie[0]) + return 0; + if (!(cstr = av_strdup(set_cookie))) return AVERROR(EINVAL); From b7d842c554b1fec051ca906f446f7311139c5725 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 8 Mar 2018 04:52:36 +0100 Subject: [PATCH 2157/2557] http: fix potentially dangerous whitespace skipping code If the string consists entirely of whitespace, this could in theory continue to write '\0' before the start of the memory allocation. In practice, it didn't really happen: the generic HTTP header parsing code already skips leading whitespaces, so the string is either empty, or consists a non-whitespace. (The generic code and the cookie code actually have different ideas about what bytes are whitespace: the former uses av_isspace(), the latter uses WHITESPACES. Fortunately, av_isspace() is a super set of the http.c specific WHITESPACES, so there's probably no case where the above assumption could have been broken.) --- libavformat/http.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index 59f90ac603469..983034f0830f9 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -760,6 +760,8 @@ static int parse_set_cookie(const char *set_cookie, AVDictionary **dict) back = &cstr[strlen(cstr)-1]; while (strchr(WHITESPACES, *back)) { *back='\0'; + if (back == cstr) + break; back--; } From b2bb1cb68be2627f4873ae1203197e1fca768650 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 17 Mar 2018 21:07:17 +0100 Subject: [PATCH 2158/2557] fate/hapqa_extract : add test for hapqa_extract bsf test extract color and alpha with the three main kind of hap frame : - no snappy compression - snappy compression and one chunk - snappy compression and several chunks (16 here) like the bsf filter need to be used with vtag and encoder edition also test the information of the target mov for color and alpha --- tests/fate/hap.mak | 43 +++++++++++ ...hapqa-extract-nosnappy-to-hapalphaonly-mov | 73 +++++++++++++++++++ .../fate/hapqa-extract-nosnappy-to-hapq-mov | 73 +++++++++++++++++++ .../hapqa-extract-snappy1-to-hapalphaonly | 6 ++ tests/ref/fate/hapqa-extract-snappy1-to-hapq | 6 ++ .../hapqa-extract-snappy16-to-hapalphaonly | 6 ++ tests/ref/fate/hapqa-extract-snappy16-to-hapq | 6 ++ 7 files changed, 213 insertions(+) create mode 100644 tests/ref/fate/hapqa-extract-nosnappy-to-hapalphaonly-mov create mode 100644 tests/ref/fate/hapqa-extract-nosnappy-to-hapq-mov create mode 100644 tests/ref/fate/hapqa-extract-snappy1-to-hapalphaonly create mode 100644 tests/ref/fate/hapqa-extract-snappy1-to-hapq create mode 100644 tests/ref/fate/hapqa-extract-snappy16-to-hapalphaonly create mode 100644 tests/ref/fate/hapqa-extract-snappy16-to-hapq diff --git a/tests/fate/hap.mak b/tests/fate/hap.mak index 51673366f2157..075a602e458ea 100644 --- a/tests/fate/hap.mak +++ b/tests/fate/hap.mak @@ -29,6 +29,49 @@ FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, HAP) += $(FATE_HAP) fate-hap: $(FATE_HAP) +#Test bsf conversion +FATE_HAPQA_EXTRACT_BSF += fate-hapqa-extract-snappy1-to-hapq +fate-hapqa-extract-snappy1-to-hapq: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_Snappy_1chunk_127x1.mov -c:v copy -bsf:v hapqa_extract=texture=color -tag:v HapY -metadata:s:v:0 encoder="HAPQ" + +FATE_HAPQA_EXTRACT_BSF += fate-hapqa-extract-snappy16-to-hapq +fate-hapqa-extract-snappy16-to-hapq: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_Snappy_16chunk_127x1.mov -c:v copy -bsf:v hapqa_extract=texture=color -tag:v HapY -metadata:s:v:0 encoder="HAPQ" + +FATE_HAPQA_EXTRACT_BSF += fate-hapqa-extract-snappy1-to-hapalphaonly +fate-hapqa-extract-snappy1-to-hapalphaonly: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_Snappy_1chunk_127x1.mov -c:v copy -bsf:v hapqa_extract=texture=alpha -tag:v HapA -metadata:s:v:0 encoder="HAPAlphaOnly" + +FATE_HAPQA_EXTRACT_BSF += fate-hapqa-extract-snappy16-to-hapalphaonly +fate-hapqa-extract-snappy16-to-hapalphaonly: CMD = framecrc -i $(TARGET_SAMPLES)/hap/HAPQA_Snappy_16chunk_127x1.mov -c:v copy -bsf:v hapqa_extract=texture=alpha -tag:v HapA -metadata:s:v:0 encoder="HAPAlphaOnly" + + +#Test bsf conversion and mov +tests/data/hapq_nosnappy.mov: TAG = GEN +tests/data/hapq_nosnappy.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + -i $(TARGET_SAMPLES)/hap/HAPQA_NoSnappy_127x1.mov -nostdin -c:v copy -bsf:v hapqa_extract=texture=color \ + -tag:v HapY -metadata:s:v:0 encoder="HAPQ" $(TARGET_PATH)/$@ -y 2>/dev/null + +tests/data/hapalphaonly_nosnappy.mov: TAG = GEN +tests/data/hapalphaonly_nosnappy.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + -i $(TARGET_SAMPLES)/hap/HAPQA_NoSnappy_127x1.mov -nostdin -c:v copy -bsf:v hapqa_extract=texture=alpha \ + -tag:v HapA -metadata:s:v:0 encoder="HAPAlpha Only" $(TARGET_PATH)/$@ -y 2>/dev/null + + +FATE_HAPQA_EXTRACT_BSF_FFPROBE += fate-hapqa-extract-nosnappy-to-hapq-mov +fate-hapqa-extract-nosnappy-to-hapq-mov: tests/data/hapq_nosnappy.mov +fate-hapqa-extract-nosnappy-to-hapq-mov: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_packets -show_data_hash adler32 -show_streams -select_streams v -v 0 $(TARGET_PATH)/tests/data/hapq_nosnappy.mov + +FATE_HAPQA_EXTRACT_BSF_FFPROBE += fate-hapqa-extract-nosnappy-to-hapalphaonly-mov +fate-hapqa-extract-nosnappy-to-hapalphaonly-mov: tests/data/hapalphaonly_nosnappy.mov +fate-hapqa-extract-nosnappy-to-hapalphaonly-mov: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_packets -show_data_hash adler32 -show_streams -select_streams v -v 0 $(TARGET_PATH)/tests/data/hapalphaonly_nosnappy.mov + + +FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER HAPQA_EXTRACT_BSF MOV_MUXER) += $(FATE_HAPQA_EXTRACT_BSF) +FATE_SAMPLES_FFPROBE += $(FATE_HAPQA_EXTRACT_BSF_FFPROBE) + +fate-hapqa-extract-bsf: $(FATE_HAPQA_EXTRACT_BSF) $(FATE_HAPQA_EXTRACT_BSF_FFPROBE) + + fate-hapenc%: CMD = framemd5 -f image2 -c:v pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -sws_flags +accurate_rnd+bitexact -vframes 5 -c:v hap ${OPTS} FATE_HAPENC += fate-hapenc-hap-none diff --git a/tests/ref/fate/hapqa-extract-nosnappy-to-hapalphaonly-mov b/tests/ref/fate/hapqa-extract-nosnappy-to-hapalphaonly-mov new file mode 100644 index 0000000000000..f5ecdd4311411 --- /dev/null +++ b/tests/ref/fate/hapqa-extract-nosnappy-to-hapalphaonly-mov @@ -0,0 +1,73 @@ +[PACKET] +codec_type=video +stream_index=0 +pts=0 +pts_time=0.000000 +dts=0 +dts_time=0.000000 +duration=512 +duration_time=0.040000 +convergence_duration=N/A +convergence_duration_time=N/A +size=4612 +pos=36 +flags=K_ +data_hash=adler32:ed83c166 +[/PACKET] +[STREAM] +index=0 +codec_name=hap +codec_long_name=Vidvox Hap +profile=unknown +codec_type=video +codec_time_base=1/25 +codec_tag_string=HapA +codec_tag=0x41706148 +width=127 +height=71 +coded_width=128 +coded_height=72 +has_b_frames=0 +sample_aspect_ratio=1:1 +display_aspect_ratio=127:71 +pix_fmt=gray +level=-99 +color_range=unknown +color_space=unknown +color_transfer=unknown +color_primaries=unknown +chroma_location=unspecified +field_order=unknown +timecode=N/A +refs=1 +id=N/A +r_frame_rate=25/1 +avg_frame_rate=25/1 +time_base=1/12800 +start_pts=0 +start_time=0.000000 +duration_ts=512 +duration=0.040000 +bit_rate=922400 +max_bit_rate=N/A +bits_per_raw_sample=N/A +nb_frames=1 +nb_read_frames=N/A +nb_read_packets=1 +extradata_hash=adler32:00000001 +DISPOSITION:default=1 +DISPOSITION:dub=0 +DISPOSITION:original=0 +DISPOSITION:comment=0 +DISPOSITION:lyrics=0 +DISPOSITION:karaoke=0 +DISPOSITION:forced=0 +DISPOSITION:hearing_impaired=0 +DISPOSITION:visual_impaired=0 +DISPOSITION:clean_effects=0 +DISPOSITION:attached_pic=0 +DISPOSITION:timed_thumbnails=0 +TAG:language=eng +TAG:handler_name=DataHandler +TAG:encoder=HAPAlpha Only +[/STREAM] diff --git a/tests/ref/fate/hapqa-extract-nosnappy-to-hapq-mov b/tests/ref/fate/hapqa-extract-nosnappy-to-hapq-mov new file mode 100644 index 0000000000000..c3a0a599fd401 --- /dev/null +++ b/tests/ref/fate/hapqa-extract-nosnappy-to-hapq-mov @@ -0,0 +1,73 @@ +[PACKET] +codec_type=video +stream_index=0 +pts=0 +pts_time=0.000000 +dts=0 +dts_time=0.000000 +duration=512 +duration_time=0.040000 +convergence_duration=N/A +convergence_duration_time=N/A +size=9220 +pos=36 +flags=K_ +data_hash=adler32:b3ccc147 +[/PACKET] +[STREAM] +index=0 +codec_name=hap +codec_long_name=Vidvox Hap +profile=unknown +codec_type=video +codec_time_base=1/25 +codec_tag_string=HapY +codec_tag=0x59706148 +width=127 +height=71 +coded_width=128 +coded_height=72 +has_b_frames=0 +sample_aspect_ratio=1:1 +display_aspect_ratio=127:71 +pix_fmt=rgb0 +level=-99 +color_range=unknown +color_space=unknown +color_transfer=unknown +color_primaries=unknown +chroma_location=unspecified +field_order=unknown +timecode=N/A +refs=1 +id=N/A +r_frame_rate=25/1 +avg_frame_rate=25/1 +time_base=1/12800 +start_pts=0 +start_time=0.000000 +duration_ts=512 +duration=0.040000 +bit_rate=1844000 +max_bit_rate=N/A +bits_per_raw_sample=N/A +nb_frames=1 +nb_read_frames=N/A +nb_read_packets=1 +extradata_hash=adler32:00000001 +DISPOSITION:default=1 +DISPOSITION:dub=0 +DISPOSITION:original=0 +DISPOSITION:comment=0 +DISPOSITION:lyrics=0 +DISPOSITION:karaoke=0 +DISPOSITION:forced=0 +DISPOSITION:hearing_impaired=0 +DISPOSITION:visual_impaired=0 +DISPOSITION:clean_effects=0 +DISPOSITION:attached_pic=0 +DISPOSITION:timed_thumbnails=0 +TAG:language=eng +TAG:handler_name=DataHandler +TAG:encoder=HAPQ +[/STREAM] diff --git a/tests/ref/fate/hapqa-extract-snappy1-to-hapalphaonly b/tests/ref/fate/hapqa-extract-snappy1-to-hapalphaonly new file mode 100644 index 0000000000000..9ab123f09d1d8 --- /dev/null +++ b/tests/ref/fate/hapqa-extract-snappy1-to-hapalphaonly @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: hap +#dimensions 0: 127x71 +#sar 0: 1/1 +0, 0, 0, 1, 3044, 0xcaf6ddd0 diff --git a/tests/ref/fate/hapqa-extract-snappy1-to-hapq b/tests/ref/fate/hapqa-extract-snappy1-to-hapq new file mode 100644 index 0000000000000..f658b1c0b4908 --- /dev/null +++ b/tests/ref/fate/hapqa-extract-snappy1-to-hapq @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: hap +#dimensions 0: 127x71 +#sar 0: 1/1 +0, 0, 0, 1, 8217, 0x04271f0f diff --git a/tests/ref/fate/hapqa-extract-snappy16-to-hapalphaonly b/tests/ref/fate/hapqa-extract-snappy16-to-hapalphaonly new file mode 100644 index 0000000000000..1bd920699ae2f --- /dev/null +++ b/tests/ref/fate/hapqa-extract-snappy16-to-hapalphaonly @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: hap +#dimensions 0: 127x71 +#sar 0: 1/1 +0, 0, 0, 1, 3513, 0x69c7014f diff --git a/tests/ref/fate/hapqa-extract-snappy16-to-hapq b/tests/ref/fate/hapqa-extract-snappy16-to-hapq new file mode 100644 index 0000000000000..8334d53d616ec --- /dev/null +++ b/tests/ref/fate/hapqa-extract-snappy16-to-hapq @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: hap +#dimensions 0: 127x71 +#sar 0: 1/1 +0, 0, 0, 1, 8726, 0xf889691c From 3e7fa34d3b688b9b4b5b22344e8fc27c4b53286d Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 17 Mar 2018 22:20:34 +0100 Subject: [PATCH 2159/2557] avfilter/vf_premultiply : fix unpremultiply_offset for rgb input --- libavfilter/vf_premultiply.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_premultiply.c b/libavfilter/vf_premultiply.c index df4f26578d114..4f250df3f4e4f 100644 --- a/libavfilter/vf_premultiply.c +++ b/libavfilter/vf_premultiply.c @@ -272,7 +272,7 @@ static void unpremultiply8offset(const uint8_t *msrc, const uint8_t *asrc, for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { if (asrc[x] > 0 && asrc[x] < 255) - dst[x] = FFMIN((msrc[x] - offset) * 255 / asrc[x] + offset, 255); + dst[x] = FFMIN(FFMAX(msrc[x] - offset, 0) * 255 / asrc[x] + offset, 255); else dst[x] = msrc[x]; } @@ -350,7 +350,7 @@ static void unpremultiply16offset(const uint8_t *mmsrc, const uint8_t *aasrc, for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { if (asrc[x] > 0 && asrc[x] < max) - dst[x] = FFMAX(FFMIN((msrc[x] - offset) * (unsigned)max / asrc[x] + offset, max), 0); + dst[x] = FFMAX(FFMIN(FFMAX(msrc[x] - offset, 0) * (unsigned)max / asrc[x] + offset, max), 0); else dst[x] = msrc[x]; } From ce1d77a5e7cebce11074bf6f9e38ad6da37338ff Mon Sep 17 00:00:00 2001 From: Felix Matouschek Date: Wed, 14 Mar 2018 13:14:07 +0100 Subject: [PATCH 2160/2557] lavd: fix iterating of input and output devices In the previous implementation the first input or output device was skipped when device_next was called with prev = NULL Signed-off-by: Felix Matouschek Signed-off-by: Timo Rothenpieler --- libavdevice/alldevices.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index 4c89649b97268..39993354bc428 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -126,16 +126,13 @@ static void *device_next(void *prev, int output, ff_thread_once(&av_device_next_init, av_device_init_next); - if (!prev && !(prev = (output ? (void*)outdev_list[0] : (void*)indev_list[0]))) - return NULL; - do { if (output) { - if (!(prev = ((AVOutputFormat *)prev)->next)) + if (!(prev = prev ? ((AVOutputFormat *)prev)->next : (void*)outdev_list[0])) break; pc = ((AVOutputFormat *)prev)->priv_class; } else { - if (!(prev = ((AVInputFormat *)prev)->next)) + if (!(prev = prev ? ((AVInputFormat *)prev)->next : (void*)indev_list[0])) break; pc = ((AVInputFormat *)prev)->priv_class; } From 0e782661d63b39d729b2167e75a690b4e2934740 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Mar 2018 14:40:23 +0000 Subject: [PATCH 2161/2557] cbs_h264: Fix overflow in shifts The type of the result of a shift operation is unaffected by the type of the right operand, so some existing code overflows with undefined behaviour when the element length is 32. Add a helper macro to calculate the maximum value correctly and then use it everywhere this pattern appears. Found-by: Andreas Rheinhardt --- libavcodec/cbs_h264_syntax_template.c | 22 +++++++++++----------- libavcodec/cbs_internal.h | 4 ++++ 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/libavcodec/cbs_h264_syntax_template.c b/libavcodec/cbs_h264_syntax_template.c index f58dee8a25877..b5cd0b2310b48 100644 --- a/libavcodec/cbs_h264_syntax_template.c +++ b/libavcodec/cbs_h264_syntax_template.c @@ -342,8 +342,8 @@ static int FUNC(sps_extension)(CodedBitstreamContext *ctx, RWContext *rw, flag(alpha_incr_flag); bits = current->bit_depth_aux_minus8 + 9; - u(bits, alpha_opaque_value, 0, (1 << bits) - 1); - u(bits, alpha_transparent_value, 0, (1 << bits) - 1); + u(bits, alpha_opaque_value, 0, MAX_UINT_BITS(bits)); + u(bits, alpha_transparent_value, 0, MAX_UINT_BITS(bits)); } flag(additional_extension_flag); @@ -483,10 +483,10 @@ static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw, length = sps->vui.nal_hrd_parameters.initial_cpb_removal_delay_length_minus1 + 1; xu(length, initial_cpb_removal_delay[SchedSelIdx], current->nal.initial_cpb_removal_delay[i], - 0, (1 << (uint64_t)length) - 1); + 1, MAX_UINT_BITS(length)); xu(length, initial_cpb_removal_delay_offset[SchedSelIdx], current->nal.initial_cpb_removal_delay_offset[i], - 0, (1 << (uint64_t)length) - 1); + 0, MAX_UINT_BITS(length)); } } @@ -495,10 +495,10 @@ static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw, length = sps->vui.vcl_hrd_parameters.initial_cpb_removal_delay_length_minus1 + 1; xu(length, initial_cpb_removal_delay[SchedSelIdx], current->vcl.initial_cpb_removal_delay[i], - 0, (1 << (uint64_t)length) - 1); + 1, MAX_UINT_BITS(length)); xu(length, initial_cpb_removal_delay_offset[SchedSelIdx], current->vcl.initial_cpb_removal_delay_offset[i], - 0, (1 << (uint64_t)length) - 1); + 0, MAX_UINT_BITS(length)); } } @@ -548,7 +548,7 @@ static int FUNC(sei_pic_timestamp)(CodedBitstreamContext *ctx, RWContext *rw, if (time_offset_length > 0) u(time_offset_length, time_offset, - 0, (1 << (uint64_t)time_offset_length) - 1); + 0, MAX_UINT_BITS(time_offset_length)); else infer(time_offset, 0); @@ -600,9 +600,9 @@ static int FUNC(sei_pic_timing)(CodedBitstreamContext *ctx, RWContext *rw, } u(hrd->cpb_removal_delay_length_minus1 + 1, cpb_removal_delay, - 0, (1 << (uint64_t)hrd->cpb_removal_delay_length_minus1) + 1); + 0, MAX_UINT_BITS(hrd->cpb_removal_delay_length_minus1 + 1)); u(hrd->dpb_output_delay_length_minus1 + 1, dpb_output_delay, - 0, (1 << (uint64_t)hrd->dpb_output_delay_length_minus1) + 1); + 0, MAX_UINT_BITS(hrd->dpb_output_delay_length_minus1 + 1)); } if (sps->vui.pic_struct_present_flag) { @@ -1123,7 +1123,7 @@ static int FUNC(slice_header)(CodedBitstreamContext *ctx, RWContext *rw, u(2, colour_plane_id, 0, 2); u(sps->log2_max_frame_num_minus4 + 4, frame_num, - 0, (1 << (sps->log2_max_frame_num_minus4 + 4)) - 1); + 0, MAX_UINT_BITS(sps->log2_max_frame_num_minus4 + 4)); if (!sps->frame_mbs_only_flag) { flag(field_pic_flag); @@ -1141,7 +1141,7 @@ static int FUNC(slice_header)(CodedBitstreamContext *ctx, RWContext *rw, if (sps->pic_order_cnt_type == 0) { u(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, pic_order_cnt_lsb, - 0, (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1); + 0, MAX_UINT_BITS(sps->log2_max_pic_order_cnt_lsb_minus4 + 4)); if (pps->bottom_field_pic_order_in_frame_present_flag && !current->field_pic_flag) se(delta_pic_order_cnt_bottom, INT32_MIN + 1, INT32_MAX); diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index 56748034727e7..be540e2a44d3d 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -79,6 +79,10 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc, int width, const char *name, uint32_t value, uint32_t range_min, uint32_t range_max); +// The largest value representable in N bits, suitable for use as +// range_max in the above functions. +#define MAX_UINT_BITS(length) ((UINT64_C(1) << (length)) - 1) + extern const CodedBitstreamType ff_cbs_type_h264; extern const CodedBitstreamType ff_cbs_type_h265; From c4eeea76335d6b3ec08a27ed5468cfd127feb1b1 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Mar 2018 14:42:09 +0000 Subject: [PATCH 2162/2557] cbs_h265: Use helper macro for maximum values of fixed-width elements Apply the same logic as the previous patch to H.265. There are no cases which currently overflow here, but this is still more consistent. --- libavcodec/cbs_h265_syntax_template.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/cbs_h265_syntax_template.c b/libavcodec/cbs_h265_syntax_template.c index dae7f2dd46325..140c827c9dd2f 100644 --- a/libavcodec/cbs_h265_syntax_template.c +++ b/libavcodec/cbs_h265_syntax_template.c @@ -665,7 +665,7 @@ static int FUNC(sps_scc_extension)(CodedBitstreamContext *ctx, RWContext *rw, : current->bit_depth_chroma_minus8 + 8; for (i = 0; i <= current->sps_num_palette_predictor_initializer_minus1; i++) u(bit_depth, sps_palette_predictor_initializers[comp][i], - 0, (1 << bit_depth) - 1); + 0, MAX_UINT_BITS(bit_depth)); } } } @@ -827,7 +827,7 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, for (i = 0; i < current->num_long_term_ref_pics_sps; i++) { u(current->log2_max_pic_order_cnt_lsb_minus4 + 4, lt_ref_pic_poc_lsb_sps[i], - 0, (1 << (current->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1); + 0, MAX_UINT_BITS(current->log2_max_pic_order_cnt_lsb_minus4 + 4)); flag(used_by_curr_pic_lt_sps_flag[i]); } } @@ -845,7 +845,7 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, flag(sps_multilayer_extension_flag); flag(sps_3d_extension_flag); flag(sps_scc_extension_flag); - u(4, sps_extension_4bits, 0, (1 << 4) - 1); + u(4, sps_extension_4bits, 0, MAX_UINT_BITS(4)); } if (current->sps_range_extension_flag) @@ -925,7 +925,7 @@ static int FUNC(pps_scc_extension)(CodedBitstreamContext *ctx, RWContext *rw, : current->chroma_bit_depth_entry_minus8 + 8; for (i = 0; i < current->pps_num_palette_predictor_initializer; i++) u(bit_depth, pps_palette_predictor_initializers[comp][i], - 0, (1 << bit_depth) - 1); + 0, MAX_UINT_BITS(bit_depth)); } } } @@ -1038,7 +1038,7 @@ static int FUNC(pps)(CodedBitstreamContext *ctx, RWContext *rw, flag(pps_multilayer_extension_flag); flag(pps_3d_extension_flag); flag(pps_scc_extension_flag); - u(4, pps_extension_4bits, 0, (1 << 4) - 1); + u(4, pps_extension_4bits, 0, MAX_UINT_BITS(4)); } if (current->pps_range_extension_flag) CHECK(FUNC(pps_range_extension)(ctx, rw, current)); @@ -1274,7 +1274,7 @@ static int FUNC(slice_segment_header)(CodedBitstreamContext *ctx, RWContext *rw, const H265RawSTRefPicSet *rps; u(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, slice_pic_order_cnt_lsb, - 0, (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1); + 0, MAX_UINT_BITS(sps->log2_max_pic_order_cnt_lsb_minus4 + 4)); flag(short_term_ref_pic_set_sps_flag); if (!current->short_term_ref_pic_set_sps_flag) { @@ -1321,7 +1321,7 @@ static int FUNC(slice_segment_header)(CodedBitstreamContext *ctx, RWContext *rw, ++num_pic_total_curr; } else { u(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, poc_lsb_lt[i], - 0, (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1); + 0, MAX_UINT_BITS(sps->log2_max_pic_order_cnt_lsb_minus4 + 4)); flag(used_by_curr_pic_lt_flag[i]); if (current->used_by_curr_pic_lt_flag[i]) ++num_pic_total_curr; @@ -1487,7 +1487,7 @@ static int FUNC(slice_segment_header)(CodedBitstreamContext *ctx, RWContext *rw, ue(offset_len_minus1, 0, 31); for (i = 0; i < current->num_entry_point_offsets; i++) u(current->offset_len_minus1 + 1, entry_point_offset_minus1[i], - 0, (1 << (current->offset_len_minus1 + 1)) - 1); + 0, MAX_UINT_BITS(current->offset_len_minus1 + 1)); } } From 84c3c766d86d1e064b77f9c56e4930e936bc84ec Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Mar 2018 16:39:03 +0000 Subject: [PATCH 2163/2557] h264_metadata: Add support for display orientation SEI messages --- libavcodec/h264_metadata_bsf.c | 169 ++++++++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 4 deletions(-) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 466823cda69e1..36047887ca990 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -17,6 +17,7 @@ */ #include "libavutil/avstring.h" +#include "libavutil/display.h" #include "libavutil/common.h" #include "libavutil/opt.h" @@ -30,6 +31,12 @@ enum { PASS, INSERT, REMOVE, + EXTRACT, +}; + +enum { + FLIP_HORIZONTAL = 1, + FLIP_VERTICAL = 2, }; typedef struct H264MetadataContext { @@ -38,6 +45,8 @@ typedef struct H264MetadataContext { CodedBitstreamContext *cbc; CodedBitstreamFragment access_unit; + int done_first_au; + H264RawAUD aud_nal; H264RawSEI sei_nal; @@ -62,9 +71,12 @@ typedef struct H264MetadataContext { int crop_bottom; const char *sei_user_data; - int sei_first_au; int delete_filler; + + int display_orientation; + double rotate; + int flip; } H264MetadataContext; @@ -211,6 +223,8 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) AVPacket *in = NULL; CodedBitstreamFragment *au = &ctx->access_unit; int err, i, j, has_sps; + uint8_t *displaymatrix_side_data = NULL; + size_t displaymatrix_side_data_size = 0; err = ff_bsf_get_packet(bsf, &in); if (err < 0) @@ -292,15 +306,13 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) // Only insert the SEI in access units containing SPSs, and also // unconditionally in the first access unit we ever see. - if (ctx->sei_user_data && (has_sps || !ctx->sei_first_au)) { + if (ctx->sei_user_data && (has_sps || !ctx->done_first_au)) { H264RawSEIPayload payload = { .payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED, }; H264RawSEIUserDataUnregistered *udu = &payload.payload.user_data_unregistered; - ctx->sei_first_au = 1; - for (i = j = 0; j < 32 && ctx->sei_user_data[i]; i++) { int c, v; c = ctx->sei_user_data[i]; @@ -387,6 +399,121 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) } } + if (ctx->display_orientation != PASS) { + for (i = 0; i < au->nb_units; i++) { + H264RawSEI *sei; + if (au->units[i].type != H264_NAL_SEI) + continue; + sei = au->units[i].content; + + for (j = 0; j < sei->payload_count; j++) { + H264RawSEIDisplayOrientation *disp; + int32_t *matrix; + + if (sei->payload[j].payload_type != + H264_SEI_TYPE_DISPLAY_ORIENTATION) + continue; + disp = &sei->payload[j].payload.display_orientation; + + if (ctx->display_orientation == REMOVE || + ctx->display_orientation == INSERT) { + err = ff_cbs_h264_delete_sei_message(ctx->cbc, au, + &au->units[i], j); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to delete " + "display orientation SEI message.\n"); + goto fail; + } + --i; + break; + } + + matrix = av_mallocz(9 * sizeof(int32_t)); + if (!matrix) { + err = AVERROR(ENOMEM); + goto fail; + } + + av_display_rotation_set(matrix, + disp->anticlockwise_rotation * + 180.0 / 65536.0); + av_display_matrix_flip(matrix, disp->hor_flip, disp->ver_flip); + + displaymatrix_side_data = (uint8_t*)matrix; + displaymatrix_side_data_size = 9 * sizeof(int32_t); + } + } + } + if (ctx->display_orientation == INSERT) { + H264RawSEIPayload payload = { + .payload_type = H264_SEI_TYPE_DISPLAY_ORIENTATION, + }; + H264RawSEIDisplayOrientation *disp = + &payload.payload.display_orientation; + uint8_t *data; + int size; + int write = 0; + + data = av_packet_get_side_data(in, AV_PKT_DATA_DISPLAYMATRIX, &size); + if (data && size >= 9 * sizeof(int32_t)) { + int32_t matrix[9]; + int hflip, vflip; + double angle; + + memcpy(matrix, data, sizeof(matrix)); + + hflip = vflip = 0; + if (matrix[0] < 0 && matrix[4] > 0) + hflip = 1; + else if (matrix[0] > 0 && matrix[4] < 0) + vflip = 1; + av_display_matrix_flip(matrix, hflip, vflip); + + angle = av_display_rotation_get(matrix); + + if (!(angle >= -180.0 && angle <= 180.0 /* also excludes NaN */) || + matrix[2] != 0 || matrix[5] != 0 || + matrix[6] != 0 || matrix[7] != 0) { + av_log(bsf, AV_LOG_WARNING, "Input display matrix is not " + "representable in H.264 parameters.\n"); + } else { + disp->hor_flip = hflip; + disp->ver_flip = vflip; + disp->anticlockwise_rotation = + (uint16_t)rint((angle >= 0.0 ? angle + : angle + 360.0) * + 65536.0 / 360.0); + write = 1; + } + } + + if (has_sps || !ctx->done_first_au) { + if (!isnan(ctx->rotate)) { + disp->anticlockwise_rotation = + (uint16_t)rint((ctx->rotate >= 0.0 ? ctx->rotate + : ctx->rotate + 360.0) * + 65536.0 / 360.0); + write = 1; + } + if (ctx->flip) { + disp->hor_flip = !!(ctx->flip & FLIP_HORIZONTAL); + disp->ver_flip = !!(ctx->flip & FLIP_VERTICAL); + write = 1; + } + } + + if (write) { + disp->display_orientation_repetition_period = 1; + + err = ff_cbs_h264_add_sei_message(ctx->cbc, au, &payload); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to add display orientation " + "SEI message to access unit.\n"); + goto fail; + } + } + } + err = ff_cbs_write_packet(ctx->cbc, out, au); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); @@ -397,9 +524,24 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) if (err < 0) goto fail; + if (displaymatrix_side_data) { + err = av_packet_add_side_data(out, AV_PKT_DATA_DISPLAYMATRIX, + displaymatrix_side_data, + displaymatrix_side_data_size); + if (err) { + av_log(bsf, AV_LOG_ERROR, "Failed to attach extracted " + "displaymatrix side data to packet.\n"); + goto fail; + } + displaymatrix_side_data = NULL; + } + + ctx->done_first_au = 1; + err = 0; fail: ff_cbs_fragment_uninit(ctx->cbc, au); + av_freep(&displaymatrix_side_data); av_packet_free(&in); @@ -509,6 +651,25 @@ static const AVOption h264_metadata_options[] = { { "delete_filler", "Delete all filler (both NAL and SEI)", OFFSET(delete_filler), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1 }, + { "display_orientation", "Display orientation SEI", + OFFSET(display_orientation), AV_OPT_TYPE_INT, + { .i64 = PASS }, PASS, EXTRACT, 0, "disp_or" }, + { "pass", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PASS }, .unit = "disp_or" }, + { "insert", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = INSERT }, .unit = "disp_or" }, + { "remove", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE }, .unit = "disp_or" }, + { "extract", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = EXTRACT }, .unit = "disp_or" }, + + { "rotate", "Set rotation in display orientation SEI (anticlockwise angle in degrees)", + OFFSET(rotate), AV_OPT_TYPE_DOUBLE, + { .dbl = NAN }, -360.0, +360.0 }, + { "flip", "Set flip in display orientation SEI", + OFFSET(flip), AV_OPT_TYPE_FLAGS, + { .i64 = 0 }, 0, FLIP_HORIZONTAL | FLIP_VERTICAL, .unit ="flip" }, + { "horizontal", "Set hor_flip", + 0, AV_OPT_TYPE_CONST, { .i64 = FLIP_HORIZONTAL }, .unit ="flip" }, + { "vertical", "Set ver_flip", + 0, AV_OPT_TYPE_CONST, { .i64 = FLIP_VERTICAL }, .unit ="flip" }, + { NULL } }; From 94d42cb4cc6e420c80abbf54148be1578f7c3244 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Mar 2018 17:04:01 +0000 Subject: [PATCH 2164/2557] h264_metadata: Remove unused fields The SEI NAL is unused since 69062d0f9b6aef5d9d9b8c9c9b5cfb23037caddb, while the AUD NAL is small and would more sensibly be on the stack. --- libavcodec/h264_metadata_bsf.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 36047887ca990..da37115b5d098 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -47,9 +47,6 @@ typedef struct H264MetadataContext { int done_first_au; - H264RawAUD aud_nal; - H264RawSEI sei_nal; - int aud; AVRational sample_aspect_ratio; @@ -259,7 +256,9 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) 0x3ff, // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int primary_pic_type_mask = 0xff; - H264RawAUD *aud = &ctx->aud_nal; + H264RawAUD aud = { + .nal_unit_header.nal_unit_type = H264_NAL_AUD, + }; for (i = 0; i < au->nb_units; i++) { if (au->units[i].type == H264_NAL_SLICE || @@ -282,11 +281,10 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) goto fail; } - aud->nal_unit_header.nal_unit_type = H264_NAL_AUD; - aud->primary_pic_type = j; + aud.primary_pic_type = j; err = ff_cbs_insert_unit_content(ctx->cbc, au, - 0, H264_NAL_AUD, aud, NULL); + 0, H264_NAL_AUD, &aud, NULL); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n"); goto fail; From 84bb8327f571c4924789413efafde47d96b8b72b Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Mar 2018 17:27:15 +0000 Subject: [PATCH 2165/2557] cbs: Add a table of all supported codec IDs Use it as the set of codec IDs supported by the trace_headers BSF. --- configure | 2 +- libavcodec/cbs.c | 13 +++++++++++++ libavcodec/cbs.h | 8 ++++++++ libavcodec/trace_headers_bsf.c | 9 +-------- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/configure b/configure index f09f48c54baad..87430f460f920 100755 --- a/configure +++ b/configure @@ -2924,7 +2924,7 @@ h264_redundant_pps_bsf_select="cbs_h264" hevc_metadata_bsf_select="cbs_h265" mjpeg2jpeg_bsf_select="jpegtables" mpeg2_metadata_bsf_select="cbs_mpeg2" -trace_headers_bsf_select="cbs_h264 cbs_h265 cbs_mpeg2" +trace_headers_bsf_select="cbs" # external libraries aac_at_decoder_deps="audiotoolbox" diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index 62f60be437bcd..897e0bb28e34c 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -40,6 +40,19 @@ static const CodedBitstreamType *cbs_type_table[] = { #endif }; +const enum AVCodecID ff_cbs_all_codec_ids[] = { +#if CONFIG_CBS_H264 + AV_CODEC_ID_H264, +#endif +#if CONFIG_CBS_H265 + AV_CODEC_ID_H265, +#endif +#if CONFIG_CBS_MPEG2 + AV_CODEC_ID_MPEG2VIDEO, +#endif + AV_CODEC_ID_NONE +}; + int ff_cbs_init(CodedBitstreamContext **ctx_ptr, enum AVCodecID codec_id, void *log_ctx) { diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h index 396ff0faec7fb..402eb39e00aef 100644 --- a/libavcodec/cbs.h +++ b/libavcodec/cbs.h @@ -201,6 +201,14 @@ typedef struct CodedBitstreamContext { } CodedBitstreamContext; +/** + * Table of all supported codec IDs. + * + * Terminated by AV_CODEC_ID_NONE. + */ +extern const enum AVCodecID ff_cbs_all_codec_ids[]; + + /** * Create and initialise a new context for the given codec. */ diff --git a/libavcodec/trace_headers_bsf.c b/libavcodec/trace_headers_bsf.c index 0697e98943d59..94a3ef72a2224 100644 --- a/libavcodec/trace_headers_bsf.c +++ b/libavcodec/trace_headers_bsf.c @@ -107,18 +107,11 @@ static int trace_headers(AVBSFContext *bsf, AVPacket *pkt) return 0; } -static const enum AVCodecID trace_headers_codec_ids[] = { - AV_CODEC_ID_H264, - AV_CODEC_ID_HEVC, - AV_CODEC_ID_MPEG2VIDEO, - AV_CODEC_ID_NONE, -}; - const AVBitStreamFilter ff_trace_headers_bsf = { .name = "trace_headers", .priv_data_size = sizeof(TraceHeadersContext), .init = &trace_headers_init, .close = &trace_headers_close, .filter = &trace_headers, - .codec_ids = trace_headers_codec_ids, + .codec_ids = ff_cbs_all_codec_ids, }; From 389f4c3e0d0a26a7d3d2696017384874cf5e93fa Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Mar 2018 21:16:25 +0000 Subject: [PATCH 2166/2557] hwcontext_vaapi: Fix condition for DRM device derivation vaGetDisplayDRM() is required for this code to work, libdrm is not. --- libavutil/hwcontext_vaapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index af9a136ef0531..99f76b9169a02 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -1324,7 +1324,7 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, static int vaapi_device_derive(AVHWDeviceContext *ctx, AVHWDeviceContext *src_ctx, int flags) { -#if CONFIG_LIBDRM +#if HAVE_VAAPI_DRM if (src_ctx->type == AV_HWDEVICE_TYPE_DRM) { AVDRMDeviceContext *src_hwctx = src_ctx->hwctx; VADisplay *display; From c99f837ddecad977018fd4d737c6070d167521c4 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 6 Mar 2018 18:49:27 +0000 Subject: [PATCH 2167/2557] lavc: Add filter_units bitstream filter This can remove units with types in or not in a given set from a stream. For example, it can be used to remove all non-VCL NAL units from an H.264 or H.265 stream. --- configure | 1 + doc/bitstream_filters.texi | 29 ++++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/filter_units_bsf.c | 256 +++++++++++++++++++++++++++++++++ 5 files changed, 288 insertions(+) create mode 100644 libavcodec/filter_units_bsf.c diff --git a/configure b/configure index 87430f460f920..d5ed95b7690d4 100755 --- a/configure +++ b/configure @@ -2919,6 +2919,7 @@ vc1_parser_select="vc1dsp" # bitstream_filters aac_adtstoasc_bsf_select="adts_header" +filter_units_bsf_select="cbs" h264_metadata_bsf_select="cbs_h264" h264_redundant_pps_bsf_select="cbs_h264" hevc_metadata_bsf_select="cbs_h265" diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index aac4705be47c9..982e3edac8f10 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -93,6 +93,35 @@ When this option is enabled, the long-term headers are removed from the bitstream after extraction. @end table +@section filter_units + +Remove units with types in or not in a given set from the stream. + +@table @option +@item pass_types +List of unit types or ranges of unit types to pass through while removing +all others. This is specified as a '|'-separated list of unit type values +or ranges of values with '-'. + +@item remove_types +Identical to @option{pass_types}, except the units in the given set +removed and all others passed through. +@end table + +Extradata is unchanged by this transformation, but note that if the stream +contains inline parameter sets then the output may be unusable if they are +removed. + +For example, to remove all non-VCL NAL units from an H.264 stream: +@example +ffmpeg -i INPUT -c:v copy -bsf:v 'filter_units=pass_types=1-5' OUTPUT +@end example + +To remove all AUDs, SEI and filler from an H.265 stream: +@example +ffmpeg -i INPUT -c:v copy -bsf:v 'filter_units=remove_types=35|38-40' OUTPUT +@end example + @section hapqa_extract Extract Rgb or Alpha part of an HAPQA file, without recompression, in order to create an HAPQ or an HAPAlphaOnly file. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index b15f677bdd494..aaef6c3ab84ce 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1043,6 +1043,7 @@ OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o OBJS-$(CONFIG_DCA_CORE_BSF) += dca_core_bsf.o OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \ h2645_parse.o +OBJS-$(CONFIG_FILTER_UNITS_BSF) += filter_units_bsf.o OBJS-$(CONFIG_H264_METADATA_BSF) += h264_metadata_bsf.o OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o OBJS-$(CONFIG_H264_REDUNDANT_PPS_BSF) += h264_redundant_pps_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 68e652286d920..12211225bb52f 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -29,6 +29,7 @@ extern const AVBitStreamFilter ff_chomp_bsf; extern const AVBitStreamFilter ff_dump_extradata_bsf; extern const AVBitStreamFilter ff_dca_core_bsf; extern const AVBitStreamFilter ff_extract_extradata_bsf; +extern const AVBitStreamFilter ff_filter_units_bsf; extern const AVBitStreamFilter ff_h264_metadata_bsf; extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf; extern const AVBitStreamFilter ff_h264_redundant_pps_bsf; diff --git a/libavcodec/filter_units_bsf.c b/libavcodec/filter_units_bsf.c new file mode 100644 index 0000000000000..1ee0afdf2b636 --- /dev/null +++ b/libavcodec/filter_units_bsf.c @@ -0,0 +1,256 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "bsf.h" +#include "cbs.h" + + +typedef struct FilterUnitsContext { + const AVClass *class; + + CodedBitstreamContext *cbc; + CodedBitstreamFragment fragment; + + const char *pass_types; + const char *remove_types; + + enum { + NOOP, + PASS, + REMOVE, + } mode; + CodedBitstreamUnitType *type_list; + int nb_types; +} FilterUnitsContext; + + +static int filter_units_make_type_list(const char *list_string, + CodedBitstreamUnitType **type_list, + int *nb_types) +{ + CodedBitstreamUnitType *list = NULL; + int pass, count; + + for (pass = 1; pass <= 2; pass++) { + long value, range_start, range_end; + const char *str; + char *value_end; + + count = 0; + for (str = list_string; *str;) { + value = strtol(str, &value_end, 0); + if (str == value_end) + goto invalid; + str = (const char *)value_end; + if (*str == '-') { + ++str; + range_start = value; + range_end = strtol(str, &value_end, 0); + if (str == value_end) + goto invalid; + + for (value = range_start; value < range_end; value++) { + if (pass == 2) + list[count] = value; + ++count; + } + } else { + if (pass == 2) + list[count] = value; + ++count; + } + if (*str == '|') + ++str; + } + if (pass == 1) { + list = av_malloc_array(count, sizeof(*list)); + if (!list) + return AVERROR(ENOMEM); + } + } + + *type_list = list; + *nb_types = count; + return 0; + +invalid: + av_freep(&list); + return AVERROR(EINVAL); +} + +static int filter_units_filter(AVBSFContext *bsf, AVPacket *out) +{ + FilterUnitsContext *ctx = bsf->priv_data; + CodedBitstreamFragment *frag = &ctx->fragment; + AVPacket *in = NULL; + int err, i, j; + + while (1) { + err = ff_bsf_get_packet(bsf, &in); + if (err < 0) + return err; + + if (ctx->mode == NOOP) { + av_packet_move_ref(out, in); + av_packet_free(&in); + return 0; + } + + err = ff_cbs_read_packet(ctx->cbc, frag, in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); + goto fail; + } + + for (i = 0; i < frag->nb_units; i++) { + for (j = 0; j < ctx->nb_types; j++) { + if (frag->units[i].type == ctx->type_list[j]) + break; + } + if (ctx->mode == REMOVE ? j < ctx->nb_types + : j >= ctx->nb_types) { + ff_cbs_delete_unit(ctx->cbc, frag, i); + --i; + } + } + + if (frag->nb_units > 0) + break; + + // Don't return packets with nothing in them. + av_packet_free(&in); + ff_cbs_fragment_uninit(ctx->cbc, frag); + } + + err = ff_cbs_write_packet(ctx->cbc, out, frag); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); + goto fail; + } + + err = av_packet_copy_props(out, in); + if (err < 0) + goto fail; + +fail: + ff_cbs_fragment_uninit(ctx->cbc, frag); + av_packet_free(&in); + + return err; +} + +static int filter_units_init(AVBSFContext *bsf) +{ + FilterUnitsContext *ctx = bsf->priv_data; + int err; + + if (ctx->pass_types && ctx->remove_types) { + av_log(bsf, AV_LOG_ERROR, "Exactly one of pass_types or " + "remove_types is required.\n"); + return AVERROR(EINVAL); + } + + if (ctx->pass_types) { + ctx->mode = PASS; + err = filter_units_make_type_list(ctx->pass_types, + &ctx->type_list, &ctx->nb_types); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to parse pass_types.\n"); + return err; + } + } else if (ctx->remove_types) { + ctx->mode = REMOVE; + err = filter_units_make_type_list(ctx->remove_types, + &ctx->type_list, &ctx->nb_types); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to parse remove_types.\n"); + return err; + } + } else { + return 0; + } + + err = ff_cbs_init(&ctx->cbc, bsf->par_in->codec_id, bsf); + if (err < 0) + return err; + + // Don't actually decompose anything, we only want the unit data. + ctx->cbc->decompose_unit_types = ctx->type_list; + ctx->cbc->nb_decompose_unit_types = 0; + + if (bsf->par_in->extradata) { + CodedBitstreamFragment ps; + + err = ff_cbs_read_extradata(ctx->cbc, &ps, bsf->par_in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); + } else { + err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, &ps); + if (err < 0) + av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); + } + + ff_cbs_fragment_uninit(ctx->cbc, &ps); + } + + return err; +} + +static void filter_units_close(AVBSFContext *bsf) +{ + FilterUnitsContext *ctx = bsf->priv_data; + + av_freep(&ctx->type_list); + + ff_cbs_close(&ctx->cbc); +} + +#define OFFSET(x) offsetof(FilterUnitsContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) +static const AVOption filter_units_options[] = { + { "pass_types", "List of unit types to pass through the filter.", + OFFSET(pass_types), AV_OPT_TYPE_STRING, + { .str = NULL }, .flags = FLAGS }, + { "remove_types", "List of unit types to remove in the filter.", + OFFSET(remove_types), AV_OPT_TYPE_STRING, + { .str = NULL }, .flags = FLAGS }, + + { NULL } +}; + +static const AVClass filter_units_class = { + .class_name = "filter_units", + .item_name = av_default_item_name, + .option = filter_units_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const AVBitStreamFilter ff_filter_units_bsf = { + .name = "filter_units", + .priv_data_size = sizeof(FilterUnitsContext), + .priv_class = &filter_units_class, + .init = &filter_units_init, + .close = &filter_units_close, + .filter = &filter_units_filter, + .codec_ids = ff_cbs_all_codec_ids, +}; From 0f3d1c69b5ed2206e061261503b0c34b3bfda617 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 18 Mar 2018 18:34:38 +0000 Subject: [PATCH 2168/2557] hwcontext_vaapi: Always include DRM hwcontext header Fixes building with VAAPI but not libdrm, which was broken by 389f4c3e0d0a26a7d3d2696017384874cf5e93fa. Just unconditionally include the header, since it doesn't depend on libdrm being present. --- libavutil/hwcontext_vaapi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 99f76b9169a02..3797005433a62 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -40,15 +40,13 @@ #include "buffer.h" #include "common.h" #include "hwcontext.h" +#include "hwcontext_drm.h" #include "hwcontext_internal.h" #include "hwcontext_vaapi.h" #include "mem.h" #include "pixdesc.h" #include "pixfmt.h" -#if CONFIG_LIBDRM -# include "hwcontext_drm.h" -#endif typedef struct VAAPIDevicePriv { #if HAVE_VAAPI_X11 From a094e7f16abffd2b0ed7bb4ce2edfeaf0d066691 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 16 Mar 2018 20:06:40 -0300 Subject: [PATCH 2169/2557] avcodec/aac_adtstoasc: move the reference in the bsf internal buffer There's no need to allocate a new packet for it. Signed-off-by: James Almer --- libavcodec/aac_adtstoasc_bsf.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/libavcodec/aac_adtstoasc_bsf.c b/libavcodec/aac_adtstoasc_bsf.c index 49f1f095e61be..6541b1189c21c 100644 --- a/libavcodec/aac_adtstoasc_bsf.c +++ b/libavcodec/aac_adtstoasc_bsf.c @@ -36,27 +36,26 @@ typedef struct AACBSFContext { * This filter creates an MPEG-4 AudioSpecificConfig from an MPEG-2/4 * ADTS header and removes the ADTS header. */ -static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out) +static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *pkt) { AACBSFContext *ctx = bsfc->priv_data; GetBitContext gb; PutBitContext pb; AACADTSHeaderInfo hdr; - AVPacket *in; int ret; - ret = ff_bsf_get_packet(bsfc, &in); + ret = ff_bsf_get_packet_ref(bsfc, pkt); if (ret < 0) return ret; - if (bsfc->par_in->extradata && in->size >= 2 && (AV_RB16(in->data) >> 4) != 0xfff) - goto finish; + if (bsfc->par_in->extradata && pkt->size >= 2 && (AV_RB16(pkt->data) >> 4) != 0xfff) + return 0; - if (in->size < AV_AAC_ADTS_HEADER_SIZE) + if (pkt->size < AV_AAC_ADTS_HEADER_SIZE) goto packet_too_small; - init_get_bits(&gb, in->data, AV_AAC_ADTS_HEADER_SIZE * 8); + init_get_bits(&gb, pkt->data, AV_AAC_ADTS_HEADER_SIZE * 8); if (ff_adts_header_parse(&gb, &hdr) < 0) { av_log(bsfc, AV_LOG_ERROR, "Error parsing ADTS frame header!\n"); @@ -71,10 +70,10 @@ static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out) goto fail; } - in->size -= AV_AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent; - if (in->size <= 0) + pkt->size -= AV_AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent; + if (pkt->size <= 0) goto packet_too_small; - in->data += AV_AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent; + pkt->data += AV_AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent; if (!ctx->first_frame_done) { int pce_size = 0; @@ -82,7 +81,7 @@ static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out) uint8_t *extradata; if (!hdr.chan_config) { - init_get_bits(&gb, in->data, in->size * 8); + init_get_bits(&gb, pkt->data, pkt->size * 8); if (get_bits(&gb, 3) != 5) { avpriv_report_missing_feature(bsfc, "PCE-based channel configuration " @@ -94,11 +93,11 @@ static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out) init_put_bits(&pb, pce_data, MAX_PCE_SIZE); pce_size = ff_copy_pce_data(&pb, &gb) / 8; flush_put_bits(&pb); - in->size -= get_bits_count(&gb)/8; - in->data += get_bits_count(&gb)/8; + pkt->size -= get_bits_count(&gb)/8; + pkt->data += get_bits_count(&gb)/8; } - extradata = av_packet_new_side_data(in, AV_PKT_DATA_NEW_EXTRADATA, + extradata = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, 2 + pce_size); if (!extradata) { ret = AVERROR(ENOMEM); @@ -120,17 +119,13 @@ static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out) ctx->first_frame_done = 1; } -finish: - av_packet_move_ref(out, in); - av_packet_free(&in); - return 0; packet_too_small: av_log(bsfc, AV_LOG_ERROR, "Input packet too small\n"); ret = AVERROR_INVALIDDATA; fail: - av_packet_free(&in); + av_packet_unref(pkt); return ret; } From 840f5b3e5ba12b26f53bf8539cb5f0f14c4a6d40 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Wed, 14 Mar 2018 13:42:19 +0800 Subject: [PATCH 2170/2557] lavc/h264_metadata_bsf: support dump options. Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- libavcodec/h264_metadata_bsf.c | 66 +++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index da37115b5d098..3dc4affddd4d6 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -591,82 +591,92 @@ static void h264_metadata_close(AVBSFContext *bsf) } #define OFFSET(x) offsetof(H264MetadataContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) static const AVOption h264_metadata_options[] = { { "aud", "Access Unit Delimiter NAL units", OFFSET(aud), AV_OPT_TYPE_INT, - { .i64 = PASS }, PASS, REMOVE, 0, "aud" }, - { "pass", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PASS }, .unit = "aud" }, - { "insert", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = INSERT }, .unit = "aud" }, - { "remove", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE }, .unit = "aud" }, + { .i64 = PASS }, PASS, REMOVE, FLAGS, "aud" }, + { "pass", NULL, 0, AV_OPT_TYPE_CONST, + { .i64 = PASS }, .flags = FLAGS, .unit = "aud" }, + { "insert", NULL, 0, AV_OPT_TYPE_CONST, + { .i64 = INSERT }, .flags = FLAGS, .unit = "aud" }, + { "remove", NULL, 0, AV_OPT_TYPE_CONST, + { .i64 = REMOVE }, .flags = FLAGS, .unit = "aud" }, { "sample_aspect_ratio", "Set sample aspect ratio (table E-1)", OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, - { .dbl = 0.0 }, 0, 65535 }, + { .dbl = 0.0 }, 0, 65535, FLAGS }, { "video_format", "Set video format (table E-2)", OFFSET(video_format), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 7 }, + { .i64 = -1 }, -1, 7, FLAGS}, { "video_full_range_flag", "Set video full range flag", OFFSET(video_full_range_flag), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 1 }, + { .i64 = -1 }, -1, 1, FLAGS }, { "colour_primaries", "Set colour primaries (table E-3)", OFFSET(colour_primaries), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 255 }, + { .i64 = -1 }, -1, 255, FLAGS }, { "transfer_characteristics", "Set transfer characteristics (table E-4)", OFFSET(transfer_characteristics), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 255 }, + { .i64 = -1 }, -1, 255, FLAGS }, { "matrix_coefficients", "Set matrix coefficients (table E-5)", OFFSET(matrix_coefficients), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 255 }, + { .i64 = -1 }, -1, 255, FLAGS }, { "chroma_sample_loc_type", "Set chroma sample location type (figure E-1)", OFFSET(chroma_sample_loc_type), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 6 }, + { .i64 = -1 }, -1, 6, FLAGS }, { "tick_rate", "Set VUI tick rate (num_units_in_tick / time_scale)", OFFSET(tick_rate), AV_OPT_TYPE_RATIONAL, - { .dbl = 0.0 }, 0, UINT_MAX }, + { .dbl = 0.0 }, 0, UINT_MAX, FLAGS }, { "fixed_frame_rate_flag", "Set VUI fixed frame rate flag", OFFSET(fixed_frame_rate_flag), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 1 }, + { .i64 = -1 }, -1, 1, FLAGS }, { "crop_left", "Set left border crop offset", OFFSET(crop_left), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, H264_MAX_WIDTH }, + { .i64 = -1 }, -1, H264_MAX_WIDTH, FLAGS }, { "crop_right", "Set right border crop offset", OFFSET(crop_right), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, H264_MAX_WIDTH }, + { .i64 = -1 }, -1, H264_MAX_WIDTH, FLAGS }, { "crop_top", "Set top border crop offset", OFFSET(crop_top), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, H264_MAX_HEIGHT }, + { .i64 = -1 }, -1, H264_MAX_HEIGHT, FLAGS }, { "crop_bottom", "Set bottom border crop offset", OFFSET(crop_bottom), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, H264_MAX_HEIGHT }, + { .i64 = -1 }, -1, H264_MAX_HEIGHT, FLAGS }, { "sei_user_data", "Insert SEI user data (UUID+string)", - OFFSET(sei_user_data), AV_OPT_TYPE_STRING, { .str = NULL } }, + OFFSET(sei_user_data), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, { "delete_filler", "Delete all filler (both NAL and SEI)", - OFFSET(delete_filler), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1 }, + OFFSET(delete_filler), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS}, { "display_orientation", "Display orientation SEI", OFFSET(display_orientation), AV_OPT_TYPE_INT, - { .i64 = PASS }, PASS, EXTRACT, 0, "disp_or" }, - { "pass", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PASS }, .unit = "disp_or" }, - { "insert", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = INSERT }, .unit = "disp_or" }, - { "remove", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE }, .unit = "disp_or" }, - { "extract", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = EXTRACT }, .unit = "disp_or" }, + { .i64 = PASS }, PASS, EXTRACT, FLAGS, "disp_or" }, + { "pass", NULL, 0, AV_OPT_TYPE_CONST, + { .i64 = PASS }, .flags = FLAGS, .unit = "disp_or" }, + { "insert", NULL, 0, AV_OPT_TYPE_CONST, + { .i64 = INSERT }, .flags = FLAGS, .unit = "disp_or" }, + { "remove", NULL, 0, AV_OPT_TYPE_CONST, + { .i64 = REMOVE }, .flags = FLAGS, .unit = "disp_or" }, + { "extract", NULL, 0, AV_OPT_TYPE_CONST, + { .i64 = EXTRACT }, .flags = FLAGS, .unit = "disp_or" }, { "rotate", "Set rotation in display orientation SEI (anticlockwise angle in degrees)", OFFSET(rotate), AV_OPT_TYPE_DOUBLE, - { .dbl = NAN }, -360.0, +360.0 }, + { .dbl = NAN }, -360.0, +360.0, FLAGS }, { "flip", "Set flip in display orientation SEI", OFFSET(flip), AV_OPT_TYPE_FLAGS, - { .i64 = 0 }, 0, FLIP_HORIZONTAL | FLIP_VERTICAL, .unit ="flip" }, + { .i64 = 0 }, 0, FLIP_HORIZONTAL | FLIP_VERTICAL, FLAGS, "flip" }, { "horizontal", "Set hor_flip", - 0, AV_OPT_TYPE_CONST, { .i64 = FLIP_HORIZONTAL }, .unit ="flip" }, + 0, AV_OPT_TYPE_CONST, + { .i64 = FLIP_HORIZONTAL }, .flags = FLAGS, .unit = "flip" }, { "vertical", "Set ver_flip", - 0, AV_OPT_TYPE_CONST, { .i64 = FLIP_VERTICAL }, .unit ="flip" }, + 0, AV_OPT_TYPE_CONST, + { .i64 = FLIP_VERTICAL }, .flags = FLAGS, .unit = "flip" }, { NULL } }; From 2a103e12ba901af519d77562c09694264e2277d4 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Wed, 14 Mar 2018 13:42:28 +0800 Subject: [PATCH 2171/2557] lavc/h265_metadata_bsf: support dump options. Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- libavcodec/h265_metadata_bsf.c | 38 +++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/libavcodec/h265_metadata_bsf.c b/libavcodec/h265_metadata_bsf.c index 2398ee95c51db..8759e410f321d 100644 --- a/libavcodec/h265_metadata_bsf.c +++ b/libavcodec/h265_metadata_bsf.c @@ -379,59 +379,63 @@ static void h265_metadata_close(AVBSFContext *bsf) } #define OFFSET(x) offsetof(H265MetadataContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) static const AVOption h265_metadata_options[] = { { "aud", "Access Unit Delimiter NAL units", OFFSET(aud), AV_OPT_TYPE_INT, - { .i64 = PASS }, PASS, REMOVE, 0, "aud" }, - { "pass", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PASS }, .unit = "aud" }, - { "insert", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = INSERT }, .unit = "aud" }, - { "remove", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE }, .unit = "aud" }, + { .i64 = PASS }, PASS, REMOVE, FLAGS, "aud" }, + { "pass", NULL, 0, AV_OPT_TYPE_CONST, + { .i64 = PASS }, .flags = FLAGS, .unit = "aud" }, + { "insert", NULL, 0, AV_OPT_TYPE_CONST, + { .i64 = INSERT }, .flags = FLAGS, .unit = "aud" }, + { "remove", NULL, 0, AV_OPT_TYPE_CONST, + { .i64 = REMOVE }, .flags = FLAGS, .unit = "aud" }, { "sample_aspect_ratio", "Set sample aspect ratio (table E-1)", OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, - { .dbl = 0.0 }, 0, 65535 }, + { .dbl = 0.0 }, 0, 65535, FLAGS }, { "video_format", "Set video format (table E-2)", OFFSET(video_format), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 7 }, + { .i64 = -1 }, -1, 7, FLAGS }, { "video_full_range_flag", "Set video full range flag", OFFSET(video_full_range_flag), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 1 }, + { .i64 = -1 }, -1, 1, FLAGS }, { "colour_primaries", "Set colour primaries (table E-3)", OFFSET(colour_primaries), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 255 }, + { .i64 = -1 }, -1, 255, FLAGS }, { "transfer_characteristics", "Set transfer characteristics (table E-4)", OFFSET(transfer_characteristics), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 255 }, + { .i64 = -1 }, -1, 255, FLAGS }, { "matrix_coefficients", "Set matrix coefficients (table E-5)", OFFSET(matrix_coefficients), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 255 }, + { .i64 = -1 }, -1, 255, FLAGS }, { "chroma_sample_loc_type", "Set chroma sample location type (figure E-1)", OFFSET(chroma_sample_loc_type), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 6 }, + { .i64 = -1 }, -1, 6, FLAGS }, { "tick_rate", "Set VPS and VUI tick rate (num_units_in_tick / time_scale)", OFFSET(tick_rate), AV_OPT_TYPE_RATIONAL, - { .dbl = 0.0 }, 0, UINT_MAX }, + { .dbl = 0.0 }, 0, UINT_MAX, FLAGS }, { "num_ticks_poc_diff_one", "Set VPS and VUI number of ticks per POC increment", OFFSET(num_ticks_poc_diff_one), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, INT_MAX }, + { .i64 = -1 }, -1, INT_MAX, FLAGS }, { "crop_left", "Set left border crop offset", OFFSET(crop_left), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, HEVC_MAX_WIDTH }, + { .i64 = -1 }, -1, HEVC_MAX_WIDTH, FLAGS }, { "crop_right", "Set right border crop offset", OFFSET(crop_right), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, HEVC_MAX_WIDTH }, + { .i64 = -1 }, -1, HEVC_MAX_WIDTH, FLAGS }, { "crop_top", "Set top border crop offset", OFFSET(crop_top), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, HEVC_MAX_HEIGHT }, + { .i64 = -1 }, -1, HEVC_MAX_HEIGHT, FLAGS }, { "crop_bottom", "Set bottom border crop offset", OFFSET(crop_bottom), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, HEVC_MAX_HEIGHT }, + { .i64 = -1 }, -1, HEVC_MAX_HEIGHT, FLAGS }, { NULL } }; From dd21f02a044703e1473e56fbb61f849b0c8b993a Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Wed, 14 Mar 2018 13:42:37 +0800 Subject: [PATCH 2172/2557] lavc/mpeg2_metadata_bsf: support dump options. Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- libavcodec/mpeg2_metadata_bsf.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libavcodec/mpeg2_metadata_bsf.c b/libavcodec/mpeg2_metadata_bsf.c index 3bb6c1d549ccf..6d5f581ab12e9 100644 --- a/libavcodec/mpeg2_metadata_bsf.c +++ b/libavcodec/mpeg2_metadata_bsf.c @@ -266,27 +266,28 @@ static void mpeg2_metadata_close(AVBSFContext *bsf) } #define OFFSET(x) offsetof(MPEG2MetadataContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) static const AVOption mpeg2_metadata_options[] = { { "display_aspect_ratio", "Set display aspect ratio (table 6-3)", OFFSET(display_aspect_ratio), AV_OPT_TYPE_RATIONAL, - { .dbl = 0.0 }, 0, 65535 }, + { .dbl = 0.0 }, 0, 65535, FLAGS }, { "frame_rate", "Set frame rate", OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, - { .dbl = 0.0 }, 0, UINT_MAX }, + { .dbl = 0.0 }, 0, UINT_MAX, FLAGS }, { "video_format", "Set video format (table 6-6)", OFFSET(video_format), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 7 }, + { .i64 = -1 }, -1, 7, FLAGS }, { "colour_primaries", "Set colour primaries (table 6-7)", OFFSET(colour_primaries), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 255 }, + { .i64 = -1 }, -1, 255, FLAGS }, { "transfer_characteristics", "Set transfer characteristics (table 6-8)", OFFSET(transfer_characteristics), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 255 }, + { .i64 = -1 }, -1, 255, FLAGS }, { "matrix_coefficients", "Set matrix coefficients (table 6-9)", OFFSET(matrix_coefficients), AV_OPT_TYPE_INT, - { .i64 = -1 }, -1, 255 }, + { .i64 = -1 }, -1, 255, FLAGS }, { NULL } }; From d8ca7a7e700bc3b092bd9564d9dea73b5f0899cf Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 18 Mar 2018 19:12:39 -0300 Subject: [PATCH 2173/2557] configure: add const_nan dependency to h264_metadata_bsf Fixes compilation with some compilers. Reviewed-by: jkqxz Signed-off-by: James Almer --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index d5ed95b7690d4..6b27f571c6323 100755 --- a/configure +++ b/configure @@ -2920,6 +2920,7 @@ vc1_parser_select="vc1dsp" # bitstream_filters aac_adtstoasc_bsf_select="adts_header" filter_units_bsf_select="cbs" +h264_metadata_bsf_deps="const_nan" h264_metadata_bsf_select="cbs_h264" h264_redundant_pps_bsf_select="cbs_h264" hevc_metadata_bsf_select="cbs_h265" From e5b4cd4c4a9c98787b94ce33e268a61df9cf1587 Mon Sep 17 00:00:00 2001 From: Yingming Fan Date: Thu, 8 Mar 2018 15:56:56 +0800 Subject: [PATCH 2174/2557] checkasm/hevc_idct : update test bit depth from 8 9 and 10 to 8 10 and 12 Signed-off-by: James Almer --- tests/checkasm/hevc_idct.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/checkasm/hevc_idct.c b/tests/checkasm/hevc_idct.c index eea712101d3d7..c20111c2df9ae 100644 --- a/tests/checkasm/hevc_idct.c +++ b/tests/checkasm/hevc_idct.c @@ -87,7 +87,7 @@ void checkasm_check_hevc_idct(void) { int bit_depth; - for (bit_depth = 8; bit_depth <= 10; bit_depth++) { + for (bit_depth = 8; bit_depth <= 12; bit_depth += 2) { HEVCDSPContext h; ff_hevc_dsp_init(&h, bit_depth); @@ -95,7 +95,7 @@ void checkasm_check_hevc_idct(void) } report("idct_dc"); - for (bit_depth = 8; bit_depth <= 10; bit_depth++) { + for (bit_depth = 8; bit_depth <= 12; bit_depth += 2) { HEVCDSPContext h; ff_hevc_dsp_init(&h, bit_depth); From 1c49365c62f417a9e7ed764ac4dd940a2ce8b08d Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 19 Mar 2018 23:12:01 +0000 Subject: [PATCH 2175/2557] h264_metadata: Fix memory leak on multiple display orientation messages Fixes CID #1430176. --- libavcodec/h264_metadata_bsf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 3dc4affddd4d6..e1f0c43b7169a 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -437,6 +437,10 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) 180.0 / 65536.0); av_display_matrix_flip(matrix, disp->hor_flip, disp->ver_flip); + // If there are multiple display orientation messages in an + // access unit then ignore all but the last one. + av_freep(&displaymatrix_side_data); + displaymatrix_side_data = (uint8_t*)matrix; displaymatrix_side_data_size = 9 * sizeof(int32_t); } From cbbefc05b1b894fd858ba4da983cbf713f4f4421 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Fri, 16 Mar 2018 19:54:03 +0100 Subject: [PATCH 2176/2557] lavfi/deshake: Check alignment before calling asm init function. Do this for every frame to make sure dynamic filters do not cause crashes. Fixes ticket #7078. --- libavfilter/vf_deshake.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_deshake.c b/libavfilter/vf_deshake.c index fb4eb355b834e..55ce5e18a1cdc 100644 --- a/libavfilter/vf_deshake.c +++ b/libavfilter/vf_deshake.c @@ -342,10 +342,6 @@ static av_cold int init(AVFilterContext *ctx) { DeshakeContext *deshake = ctx->priv; - deshake->sad = av_pixelutils_get_sad_fn(4, 4, 1, deshake); // 16x16, 2nd source unaligned - if (!deshake->sad) - return AVERROR(EINVAL); - deshake->refcount = 20; // XXX: add to options? deshake->blocksize /= 2; deshake->blocksize = av_clip(deshake->blocksize, 4, 128); @@ -424,6 +420,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); const int chroma_width = AV_CEIL_RSHIFT(link->w, desc->log2_chroma_w); const int chroma_height = AV_CEIL_RSHIFT(link->h, desc->log2_chroma_h); + int aligned; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { @@ -432,6 +429,11 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) } av_frame_copy_props(out, in); + aligned = !((intptr_t)in->data[0] & 15 | in->linesize[0] & 15); + deshake->sad = av_pixelutils_get_sad_fn(4, 4, aligned, deshake); // 16x16, 2nd source unaligned + if (!deshake->sad) + return AVERROR(EINVAL); + if (deshake->cx < 0 || deshake->cy < 0 || deshake->cw < 0 || deshake->ch < 0) { // Find the most likely global motion for the current frame find_motion(deshake, (deshake->ref == NULL) ? in->data[0] : deshake->ref->data[0], in->data[0], link->w, link->h, in->linesize[0], &t); From e4eaaf7bf6930cd0c9a15631dfee0e235f327ba9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 16 Mar 2018 18:58:04 -0300 Subject: [PATCH 2177/2557] avcodec/vp9_superframe_split: move the reference in the bsf internal buffer There's no need to allocate a new packet for it. Signed-off-by: James Almer --- libavcodec/vp9_superframe_split_bsf.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/libavcodec/vp9_superframe_split_bsf.c b/libavcodec/vp9_superframe_split_bsf.c index 0d2523ebf7580..7b6fa385549df 100644 --- a/libavcodec/vp9_superframe_split_bsf.c +++ b/libavcodec/vp9_superframe_split_bsf.c @@ -30,7 +30,7 @@ #include "get_bits.h" typedef struct VP9SFSplitContext { - AVPacket *buffer_pkt; + AVPacket buffer_pkt; int nb_frames; int next_frame; @@ -43,13 +43,13 @@ static int vp9_superframe_split_filter(AVBSFContext *ctx, AVPacket *out) VP9SFSplitContext *s = ctx->priv_data; AVPacket *in; int i, j, ret, marker; - int is_superframe = !!s->buffer_pkt; + int is_superframe = !!s->buffer_pkt.data; - if (!s->buffer_pkt) { - ret = ff_bsf_get_packet(ctx, &s->buffer_pkt); + if (!s->buffer_pkt.data) { + ret = ff_bsf_get_packet_ref(ctx, &s->buffer_pkt); if (ret < 0) return ret; - in = s->buffer_pkt; + in = &s->buffer_pkt; marker = in->data[in->size - 1]; if ((marker & 0xe0) == 0xc0) { @@ -90,7 +90,7 @@ static int vp9_superframe_split_filter(AVBSFContext *ctx, AVPacket *out) GetBitContext gb; int profile, invisible = 0; - ret = av_packet_ref(out, s->buffer_pkt); + ret = av_packet_ref(out, &s->buffer_pkt); if (ret < 0) goto fail; @@ -101,7 +101,7 @@ static int vp9_superframe_split_filter(AVBSFContext *ctx, AVPacket *out) s->next_frame++; if (s->next_frame >= s->nb_frames) - av_packet_free(&s->buffer_pkt); + av_packet_unref(&s->buffer_pkt); ret = init_get_bits8(&gb, out->data, out->size); if (ret < 0) @@ -121,20 +121,19 @@ static int vp9_superframe_split_filter(AVBSFContext *ctx, AVPacket *out) out->pts = AV_NOPTS_VALUE; } else { - av_packet_move_ref(out, s->buffer_pkt); - av_packet_free(&s->buffer_pkt); + av_packet_move_ref(out, &s->buffer_pkt); } return 0; fail: - av_packet_free(&s->buffer_pkt); + av_packet_unref(&s->buffer_pkt); return ret; } static void vp9_superframe_split_uninit(AVBSFContext *ctx) { VP9SFSplitContext *s = ctx->priv_data; - av_packet_free(&s->buffer_pkt); + av_packet_unref(&s->buffer_pkt); } const AVBitStreamFilter ff_vp9_superframe_split_bsf = { From f18f9734694ea0761f94d57685f342b690d563b0 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 19 Mar 2018 00:21:19 -0300 Subject: [PATCH 2178/2557] avcodec/mp3_header_decompress: don't free the user provided packet on error It's owned by the caller. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavcodec/mp3_header_decompress_bsf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mp3_header_decompress_bsf.c b/libavcodec/mp3_header_decompress_bsf.c index 22c1ef0220efe..294858953cbce 100644 --- a/libavcodec/mp3_header_decompress_bsf.c +++ b/libavcodec/mp3_header_decompress_bsf.c @@ -87,7 +87,7 @@ static int mp3_header_decompress(AVBSFContext *ctx, AVPacket *out) goto fail; ret = av_packet_copy_props(out, in); if (ret < 0) { - av_packet_free(&out); + av_packet_unref(out); goto fail; } memcpy(out->data + frame_size - buf_size, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE); From bd60116794b4baaf9a6fedfc68cb1ac4a383bb2d Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 18 Mar 2018 23:25:32 -0300 Subject: [PATCH 2179/2557] avcodec/mpeg4_unpack_bframes: reduce code duplication Also fixes one potential leak of side data in out if the av_packet_from_data() call fails. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavcodec/mpeg4_unpack_bframes_bsf.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libavcodec/mpeg4_unpack_bframes_bsf.c b/libavcodec/mpeg4_unpack_bframes_bsf.c index e227f58ec6df6..ba970794c5b0f 100644 --- a/libavcodec/mpeg4_unpack_bframes_bsf.c +++ b/libavcodec/mpeg4_unpack_bframes_bsf.c @@ -108,8 +108,8 @@ static int mpeg4_unpack_bframes_filter(AVBSFContext *ctx, AVPacket *out) s->b_frame_buf = create_new_buffer(in->data + pos_vop2, s->b_frame_buf_size); if (!s->b_frame_buf) { s->b_frame_buf_size = 0; - av_packet_free(&in); - return AVERROR(ENOMEM); + ret = AVERROR(ENOMEM); + goto fail; } } @@ -122,14 +122,12 @@ static int mpeg4_unpack_bframes_filter(AVBSFContext *ctx, AVPacket *out) /* use frame from BSFContext */ ret = av_packet_copy_props(out, in); if (ret < 0) { - av_packet_free(&in); - return ret; + goto fail; } ret = av_packet_from_data(out, s->b_frame_buf, s->b_frame_buf_size); if (ret < 0) { - av_packet_free(&in); - return ret; + goto fail; } if (in->size <= MAX_NVOP_SIZE) { /* N-VOP */ @@ -142,9 +140,8 @@ static int mpeg4_unpack_bframes_filter(AVBSFContext *ctx, AVPacket *out) s->b_frame_buf = create_new_buffer(in->data, in->size); if (!s->b_frame_buf) { s->b_frame_buf_size = 0; - av_packet_unref(out); - av_packet_free(&in); - return AVERROR(ENOMEM); + ret = AVERROR(ENOMEM); + goto fail; } } } else if (nb_vop >= 2) { @@ -161,9 +158,12 @@ static int mpeg4_unpack_bframes_filter(AVBSFContext *ctx, AVPacket *out) av_packet_move_ref(out, in); } +fail: + if (ret < 0) + av_packet_unref(out); av_packet_free(&in); - return 0; + return ret; } static int mpeg4_unpack_bframes_init(AVBSFContext *ctx) From 039be6a23f4399a6a020a03be68e4c7cd5aaed2b Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Mar 2018 00:55:26 -0300 Subject: [PATCH 2180/2557] avcodec/h264_metadata: fix memory leak in case of output packet creation failure Some function calls may fail after the output packet is initialized. Reviewed-by: jkqxz Signed-off-by: James Almer --- libavcodec/h264_metadata_bsf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index e1f0c43b7169a..27053dbdcfa4b 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -225,7 +225,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) err = ff_bsf_get_packet(bsf, &in); if (err < 0) - goto fail; + return err; err = ff_cbs_read_packet(ctx->cbc, au, in); if (err < 0) { @@ -545,6 +545,8 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) ff_cbs_fragment_uninit(ctx->cbc, au); av_freep(&displaymatrix_side_data); + if (err < 0) + av_packet_unref(out); av_packet_free(&in); return err; From ae36d6cdde0799099dee0397427438bfc86bc1d9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Mar 2018 00:55:27 -0300 Subject: [PATCH 2181/2557] avcodec/h265_metadata: fix memory leak in case of output packet creation failure Some function calls may fail after the output packet is initialized. Reviewed-by: jkqxz Signed-off-by: James Almer --- libavcodec/h265_metadata_bsf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/h265_metadata_bsf.c b/libavcodec/h265_metadata_bsf.c index 8759e410f321d..26eb2d05d071b 100644 --- a/libavcodec/h265_metadata_bsf.c +++ b/libavcodec/h265_metadata_bsf.c @@ -239,7 +239,7 @@ static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *out) err = ff_bsf_get_packet(bsf, &in); if (err < 0) - goto fail; + return err; err = ff_cbs_read_packet(ctx->cbc, au, in); if (err < 0) { @@ -324,6 +324,8 @@ static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *out) fail: ff_cbs_fragment_uninit(ctx->cbc, au); + if (err < 0) + av_packet_unref(out); av_packet_free(&in); return err; From 2aac5ad2f72cf9a1f024187b78f949c5613ceacd Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Mar 2018 00:55:28 -0300 Subject: [PATCH 2182/2557] avcodec/mpeg2_metadata: unref output packet on failure Move the check and unref call to the end to be consistent with other bsfs. Reviewed-by: jkqxz Signed-off-by: James Almer --- libavcodec/mpeg2_metadata_bsf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/mpeg2_metadata_bsf.c b/libavcodec/mpeg2_metadata_bsf.c index 6d5f581ab12e9..e787cb37824ee 100644 --- a/libavcodec/mpeg2_metadata_bsf.c +++ b/libavcodec/mpeg2_metadata_bsf.c @@ -188,7 +188,7 @@ static int mpeg2_metadata_filter(AVBSFContext *bsf, AVPacket *out) err = ff_bsf_get_packet(bsf, &in); if (err < 0) - goto fail; + return err; err = ff_cbs_read_packet(ctx->cbc, frag, in); if (err < 0) { @@ -209,15 +209,15 @@ static int mpeg2_metadata_filter(AVBSFContext *bsf, AVPacket *out) } err = av_packet_copy_props(out, in); - if (err < 0) { - av_packet_unref(out); + if (err < 0) goto fail; - } err = 0; fail: ff_cbs_fragment_uninit(ctx->cbc, frag); + if (err < 0) + av_packet_unref(out); av_packet_free(&in); return err; From 8ad83044b47a2544907562f5e8fd11dd1a62ef82 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Thu, 15 Mar 2018 16:45:51 +0530 Subject: [PATCH 2183/2557] ffmpeg.c - drain all decoded frames during stream_loop flush When a decoded stream is being looped, after each post-EOF rewind, decoders are flushed in seek_to_start(). This only drains 1 frame, and thus the output has a few frames missing at the tail of each iteration except the last. With this patch, process_input is looped till process_input_packet reaches EOF. Fixes #7081 Signed-off-by: Michael Niedermayer --- fftools/ffmpeg.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index ee7258fcd1f65..3c18e0671340b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -4170,12 +4170,6 @@ static int seek_to_start(InputFile *ifile, AVFormatContext *is) ist = input_streams[ifile->ist_index + i]; avctx = ist->dec_ctx; - // flush decoders - if (ist->decoding_needed) { - process_input_packet(ist, NULL, 1); - avcodec_flush_buffers(avctx); - } - /* duration is the length of the last frame in a stream * when audio stream is present we don't care about * last video frame length because it's not defined exactly */ @@ -4244,6 +4238,17 @@ static int process_input(int file_index) return ret; } if (ret < 0 && ifile->loop) { + AVCodecContext *avctx; + for (i = 0; i < ifile->nb_streams; i++) { + ist = input_streams[ifile->ist_index + i]; + avctx = ist->dec_ctx; + if (ist->decoding_needed) { + ret = process_input_packet(ist, NULL, 1); + if (ret>0) + return 0; + avcodec_flush_buffers(avctx); + } + } ret = seek_to_start(ifile, is); if (ret < 0) av_log(NULL, AV_LOG_WARNING, "Seek to start failed.\n"); From 81b0d591d690f518c01c45d7ce20fdca1de80d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Heusipp?= Date: Wed, 21 Feb 2018 12:11:47 +0100 Subject: [PATCH 2184/2557] avformat/libopenmpt: Update file extensions list for libopenmpt 0.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Heusipp Reviewed-by: Josh de Kock Signed-off-by: Michael Niedermayer --- libavformat/libopenmpt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/libopenmpt.c b/libavformat/libopenmpt.c index 30c3d6e646f01..5efbdc4273393 100644 --- a/libavformat/libopenmpt.c +++ b/libavformat/libopenmpt.c @@ -234,5 +234,9 @@ AVInputFormat ff_libopenmpt_demuxer = { .read_close = read_close_openmpt, .read_seek = read_seek_openmpt, .priv_class = &class_openmpt, - .extensions = "669,amf,ams,dbm,digi,dmf,dsm,far,gdm,imf,it,j2b,m15,mdl,med,mmcmp,mms,mo3,mod,mptm,mt2,mtm,nst,okt,plm,ppm,psm,pt36,ptm,s3m,sfx,sfx2,stk,stm,ult,umx,wow,xm,xpk", +#if OPENMPT_API_VERSION_AT_LEAST(0,3,0) + .extensions = "669,amf,ams,dbm,digi,dmf,dsm,dtm,far,gdm,ice,imf,it,j2b,m15,mdl,med,mmcmp,mms,mo3,mod,mptm,mt2,mtm,nst,okt,plm,ppm,psm,pt36,ptm,s3m,sfx,sfx2,st26,stk,stm,stp,ult,umx,wow,xm,xpk", +#else + .extensions = "669,amf,ams,dbm,digi,dmf,dsm,far,gdm,ice,imf,it,j2b,m15,mdl,med,mmcmp,mms,mo3,mod,mptm,mt2,mtm,nst,okt,plm,ppm,psm,pt36,ptm,s3m,sfx,sfx2,st26,stk,stm,ult,umx,wow,xm,xpk", +#endif }; From f6ea397d0ae4e4188e90deecbcffd1cf5419c110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Heusipp?= Date: Wed, 21 Feb 2018 12:11:48 +0100 Subject: [PATCH 2185/2557] avformat/libopenmpt: Probe file format from file data if possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building with libopenmpt 0.3, use the libopenmpt file header probing functions for probing. libopenmpt probing functions are allocation-free and designed to be as fast as possible. For libopenmpt 0.2, or when libopenmpt 0.3 file header probing cannot probe successfully due to too small probe buffer, test the filename against the file extensions supported by the libopenmpt library that is actually linked, instead of relying on a hard-coded file extension list. File extension testing is also allocation-free and designed to be fast in libopenmpt. Avoiding a hard-coded file extension list is useful because later libopenmpt versions will likely add support for more module file formats. libopenmpt file header probing is tested regularly against the FATE suite and other diverse file collections by libopenmpt upstream in order to avoid false positives. FATE passes with './configure --enable-libopenmpt' as well as with './configure --enable-libopenmpt --enable-libmodplug'. libopenmpt probing adds about 5%..10% cpu time (depending on precise usage pattern and host CPU and compiler version used for libopenmpt) compared to all current internal FFmpeg probing functions combined in tools/probetest for all of its module formats combined (currently 41 modules formats in libopenmpt 0.3.4 and 234 file formats in FFmpeg). Signed-off-by: Jörn Heusipp Reviewed-by: Josh de Kock Signed-off-by: Michael Niedermayer --- libavformat/libopenmpt.c | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/libavformat/libopenmpt.c b/libavformat/libopenmpt.c index 5efbdc4273393..0fff702a36f46 100644 --- a/libavformat/libopenmpt.c +++ b/libavformat/libopenmpt.c @@ -218,6 +218,62 @@ static int read_seek_openmpt(AVFormatContext *s, int stream_idx, int64_t ts, int return 0; } +static int probe_openmpt_extension(AVProbeData *p) +{ + const char *ext; + if (p->filename) { + ext = strrchr(p->filename, '.'); + if (ext && strlen(ext + 1) > 0) { + ext++; /* skip '.' */ + if (openmpt_is_extension_supported(ext) == 1) + return AVPROBE_SCORE_EXTENSION; + } + } + return 0; +} + +static int read_probe_openmpt(AVProbeData *p) +{ +#if OPENMPT_API_VERSION_AT_LEAST(0,3,0) + int probe_result; + if (p->buf && p->buf_size > 0) { + probe_result = openmpt_probe_file_header_without_filesize( + OPENMPT_PROBE_FILE_HEADER_FLAGS_DEFAULT, + p->buf, p->buf_size, + &openmpt_logfunc, NULL, NULL, NULL, NULL, NULL); + if (probe_result == OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS) { + /* As probing here relies on code external to FFmpeg, do not return + * AVPROBE_SCORE_MAX in order to reduce the impact in the rare + * cases of false positives. + */ + return AVPROBE_SCORE_MIME + 1; + } else if (probe_result == OPENMPT_PROBE_FILE_HEADER_RESULT_WANTMOREDATA) { + if (probe_openmpt_extension(p) > 0) { + return AVPROBE_SCORE_RETRY; + } else { + if (p->buf_size >= openmpt_probe_file_header_get_recommended_size()) { + /* We have already received the recommended amount of data + * and still cannot decide. Return a rather low score. + */ + return AVPROBE_SCORE_RETRY / 2; + } else { + /* The file extension is unknown and we have very few data + * bytes available. libopenmpt cannot decide anything here, + * and returning any score > 0 would result in successfull + * probing of random data. + */ + return 0; + } + } + } else if (probe_result == OPENMPT_PROBE_FILE_HEADER_RESULT_FAILURE) { + return 0; + } + } +#endif + /* for older libopenmpt, fall back to file extension probing */ + return probe_openmpt_extension(p); +} + static const AVClass class_openmpt = { .class_name = "libopenmpt", .item_name = av_default_item_name, @@ -229,6 +285,7 @@ AVInputFormat ff_libopenmpt_demuxer = { .name = "libopenmpt", .long_name = NULL_IF_CONFIG_SMALL("Tracker formats (libopenmpt)"), .priv_data_size = sizeof(OpenMPTContext), + .read_probe = read_probe_openmpt, .read_header = read_header_openmpt, .read_packet = read_packet_openmpt, .read_close = read_close_openmpt, From 9e67447a4ffacf28af8bace33faf3ea432ddc43e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 16 Mar 2018 19:53:36 +0100 Subject: [PATCH 2186/2557] avformat/mov: Check STSC and remove invalid entries Fixes assertion failure Fixes: crbug 822547, crbug 822666 and crbug 823009 Affects: aark15sd_9A62E2FA.mp4 Found-by: ClusterFuzz Reviewed-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index b7f9c0cdd1827..33126781a00c7 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2630,6 +2630,21 @@ static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom) } sc->stsc_count = i; + for (i = sc->stsc_count - 1; i < UINT_MAX; i--) { + if ((i+1 < sc->stsc_count && sc->stsc_data[i].first >= sc->stsc_data[i+1].first) || + (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) || + sc->stsc_data[i].first < 1 || + sc->stsc_data[i].count < 1 || + sc->stsc_data[i].id < 1) { + av_log(c->fc, AV_LOG_WARNING, "STSC entry %d is invalid (first=%d count=%d id=%d)\n", i, sc->stsc_data[i].first, sc->stsc_data[i].count, sc->stsc_data[i].id); + if (i+1 >= sc->stsc_count || sc->stsc_data[i+1].first < 2) + return AVERROR_INVALIDDATA; + // We replace this entry by the next valid + sc->stsc_data[i].first = sc->stsc_data[i+1].first - 1; + sc->stsc_data[i].count = sc->stsc_data[i+1].count; + sc->stsc_data[i].id = sc->stsc_data[i+1].id; + } + } if (pb->eof_reached) { av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted STSC atom\n"); @@ -4119,6 +4134,11 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) st->index); return 0; } + if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) { + av_log(c->fc, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n", + st->index); + return AVERROR_INVALIDDATA; + } fix_timescale(c, sc); From 2ddc6b439226a7dffb740d6e50bdd835a27d10ea Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 19 Mar 2018 16:29:45 -0700 Subject: [PATCH 2187/2557] avcodec/mediacodecdec: propagate SAR to h/w frames Allows consumers who are converting hardware buffers to OpenGL textures to render the frames at the intended display resolution. Signed-off-by: Aman Gupta Signed-off-by: Derek Buitenhuis --- libavcodec/mediacodecdec_common.c | 11 +++++++++++ libavcodec/mediacodecdec_common.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index 635ee73486d15..e31adb487c964 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -205,6 +205,7 @@ static int mediacodec_wrap_hw_buffer(AVCodecContext *avctx, frame->width = avctx->width; frame->height = avctx->height; frame->format = avctx->pix_fmt; + frame->sample_aspect_ratio = avctx->sample_aspect_ratio; if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) { frame->pts = av_rescale_q(info->presentationTimeUs, @@ -414,6 +415,16 @@ static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecConte width = s->crop_right + 1 - s->crop_left; height = s->crop_bottom + 1 - s->crop_top; + AMEDIAFORMAT_GET_INT32(s->display_width, "display-width", 0); + AMEDIAFORMAT_GET_INT32(s->display_height, "display-height", 0); + + if (s->display_width && s->display_height) { + AVRational sar = av_div_q( + (AVRational){ s->display_width, s->display_height }, + (AVRational){ width, height }); + ff_set_sar(avctx, sar); + } + av_log(avctx, AV_LOG_INFO, "Output crop parameters top=%d bottom=%d left=%d right=%d, " "resulting dimensions width=%d height=%d\n", diff --git a/libavcodec/mediacodecdec_common.h b/libavcodec/mediacodecdec_common.h index 4f3b4f9fa58b7..023d4c5fa738a 100644 --- a/libavcodec/mediacodecdec_common.h +++ b/libavcodec/mediacodecdec_common.h @@ -61,6 +61,8 @@ typedef struct MediaCodecDecContext { int crop_bottom; int crop_left; int crop_right; + int display_width; + int display_height; uint64_t output_buffer_count; From 72bb955625e8cf03095a4e53a68daf5ad8e739e4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Mar 2018 15:37:32 -0300 Subject: [PATCH 2188/2557] avutil/integer: move the test to the corresponding subdirectory And actually enable it. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavutil/Makefile | 1 + libavutil/integer.c | 38 ------------------------------ libavutil/tests/integer.c | 49 +++++++++++++++++++++++++++++++++++++++ tests/fate/libavutil.mak | 5 ++++ 4 files changed, 55 insertions(+), 38 deletions(-) create mode 100644 libavutil/tests/integer.c diff --git a/libavutil/Makefile b/libavutil/Makefile index d7474f59e4859..17ec1f1aa94eb 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -204,6 +204,7 @@ TESTPROGS = adler32 \ fifo \ hash \ hmac \ + integer \ imgutils \ lfg \ lls \ diff --git a/libavutil/integer.c b/libavutil/integer.c index 6d6855fa1b9e3..890e314dced6d 100644 --- a/libavutil/integer.c +++ b/libavutil/integer.c @@ -164,41 +164,3 @@ int64_t av_i2int(AVInteger a){ } return out; } - -#ifdef TEST - -const uint8_t ff_log2_tab[256]={ - 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 -}; - -int main(void){ - int64_t a,b; - - for(a=7; a<256*256*256; a+=13215){ - for(b=3; b<256*256*256; b+=27118){ - AVInteger ai= av_int2i(a); - AVInteger bi= av_int2i(b); - - av_assert0(av_i2int(ai) == a); - av_assert0(av_i2int(bi) == b); - av_assert0(av_i2int(av_add_i(ai,bi)) == a+b); - av_assert0(av_i2int(av_sub_i(ai,bi)) == a-b); - av_assert0(av_i2int(av_mul_i(ai,bi)) == a*b); - av_assert0(av_i2int(av_shr_i(ai, 9)) == a>>9); - av_assert0(av_i2int(av_shr_i(ai,-9)) == a<<9); - av_assert0(av_i2int(av_shr_i(ai, 17)) == a>>17); - av_assert0(av_i2int(av_shr_i(ai,-17)) == a<<17); - av_assert0(av_log2_i(ai) == av_log2(a)); - av_assert0(av_i2int(av_div_i(ai,bi)) == a/b); - } - } - return 0; -} -#endif diff --git a/libavutil/tests/integer.c b/libavutil/tests/integer.c new file mode 100644 index 0000000000000..d2c8f2a903de0 --- /dev/null +++ b/libavutil/tests/integer.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/avassert.h" +#include "libavutil/integer.h" +#include "libavutil/intmath.h" + +int main(void){ + int64_t a,b; + + for(a=7; a<256*256*256; a+=13215){ + for(b=3; b<256*256*256; b+=27118){ + AVInteger ai= av_int2i(a); + AVInteger bi= av_int2i(b); + + av_assert0(av_i2int(ai) == a); + av_assert0(av_i2int(bi) == b); + av_assert0(av_i2int(av_add_i(ai,bi)) == a+b); + av_assert0(av_i2int(av_sub_i(ai,bi)) == a-b); + av_assert0(av_i2int(av_mul_i(ai,bi)) == a*b); + av_assert0(av_i2int(av_shr_i(ai, 9)) == a>>9); + av_assert0(av_i2int(av_shr_i(ai,-9)) == a<<9); + av_assert0(av_i2int(av_shr_i(ai, 17)) == a>>17); + av_assert0(av_i2int(av_shr_i(ai,-17)) == a<<17); + av_assert0(av_log2_i(ai) == av_log2(a)); + av_assert0(av_i2int(av_div_i(ai,bi)) == a/b); + } + } + return 0; +} diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak index 2ec5650c0f8fd..9b32d880f516a 100644 --- a/tests/fate/libavutil.mak +++ b/tests/fate/libavutil.mak @@ -90,6 +90,11 @@ FATE_LIBAVUTIL += fate-imgutils fate-imgutils: libavutil/tests/imgutils$(EXESUF) fate-imgutils: CMD = run libavutil/tests/imgutils +FATE_LIBAVUTIL += fate-integer +fate-integer: libavutil/tests/integer$(EXESUF) +fate-integer: CMD = run libavutil/tests/integer +fate-integer: CMP = null + FATE_LIBAVUTIL += fate-lfg fate-lfg: libavutil/tests/lfg$(EXESUF) fate-lfg: CMD = run libavutil/tests/lfg From 7e0dc7210bed69106632540367544381a565fa4d Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 21 Mar 2018 01:38:34 -0300 Subject: [PATCH 2189/2557] avcodec/vp9_superframe_split: fix memory leak in case of output packet creation failure Some function calls may fail after the output packet is initialized. Signed-off-by: James Almer --- libavcodec/vp9_superframe_split_bsf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/vp9_superframe_split_bsf.c b/libavcodec/vp9_superframe_split_bsf.c index 7b6fa385549df..9c4aa33dc1b42 100644 --- a/libavcodec/vp9_superframe_split_bsf.c +++ b/libavcodec/vp9_superframe_split_bsf.c @@ -126,6 +126,8 @@ static int vp9_superframe_split_filter(AVBSFContext *ctx, AVPacket *out) return 0; fail: + if (ret < 0) + av_packet_unref(out); av_packet_unref(&s->buffer_pkt); return ret; } From 86499771d1228d8303c8eb6509e20c0caaa02da5 Mon Sep 17 00:00:00 2001 From: Ruiling Song Date: Tue, 6 Mar 2018 10:35:56 +0800 Subject: [PATCH 2190/2557] qsv: align surface width/height to 16. Per MediaSDK documentation, it requires width/height to 16 alignment. Without this patch, hwupload pipeline may fail if 16 alignment is not met. Although this patch also apply 16 alignment to qsv encoder/decoder, it will not bring any side-effect to them as they are already aligned. Signed-off-by: Ruiling Song Signed-off-by: Luca Barbato --- libavutil/hwcontext_qsv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 73b5f2467c8e2..f5d78d0595ddc 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -234,8 +234,8 @@ static int qsv_init_child_ctx(AVHWFramesContext *ctx) child_frames_ctx->format = device_priv->child_pix_fmt; child_frames_ctx->sw_format = ctx->sw_format; child_frames_ctx->initial_pool_size = ctx->initial_pool_size; - child_frames_ctx->width = ctx->width; - child_frames_ctx->height = ctx->height; + child_frames_ctx->width = FFALIGN(ctx->width, 16); + child_frames_ctx->height = FFALIGN(ctx->height, 16); #if CONFIG_DXVA2 if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { @@ -307,9 +307,9 @@ static int qsv_init_surface(AVHWFramesContext *ctx, mfxFrameSurface1 *surf) surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV444; surf->Info.FourCC = fourcc; - surf->Info.Width = ctx->width; + surf->Info.Width = FFALIGN(ctx->width, 16); surf->Info.CropW = ctx->width; - surf->Info.Height = ctx->height; + surf->Info.Height = FFALIGN(ctx->height, 16); surf->Info.CropH = ctx->height; surf->Info.FrameRateExtN = 25; surf->Info.FrameRateExtD = 1; From caef95737e20039c4e5654e3b3f006fa3ed8aa4d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 21 Mar 2018 11:34:11 +0100 Subject: [PATCH 2191/2557] avfilter/vf_waveform: add xflat mode Also use macros for xflat and aflat mode. Signed-off-by: Paul B Mahol --- doc/filters.texi | 3 + libavfilter/vf_waveform.c | 558 +++++++++++++++++++++----------------- 2 files changed, 307 insertions(+), 254 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index bd43a7ac6e16f..a3ccb218b29fb 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16491,6 +16491,9 @@ Luma and chroma combined together. @item aflat Similar as above, but shows difference between blue and red chroma. +@item xflat +Similar as above, but use different colors. + @item chroma Displays only chroma. diff --git a/libavfilter/vf_waveform.c b/libavfilter/vf_waveform.c index 02a7046f33d43..44c787fb3d0fe 100644 --- a/libavfilter/vf_waveform.c +++ b/libavfilter/vf_waveform.c @@ -36,6 +36,7 @@ enum FilterType { CHROMA, COLOR, ACOLOR, + XFLAT, NB_FILTERS }; @@ -135,6 +136,7 @@ static const AVOption waveform_options[] = { { "chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64=CHROMA}, 0, 0, FLAGS, "filter" }, { "color", NULL, 0, AV_OPT_TYPE_CONST, {.i64=COLOR}, 0, 0, FLAGS, "filter" }, { "acolor", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ACOLOR}, 0, 0, FLAGS, "filter" }, + { "xflat", NULL, 0, AV_OPT_TYPE_CONST, {.i64=XFLAT}, 0, 0, FLAGS, "filter" }, { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "graticule" }, { "g", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "graticule" }, { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "graticule" }, @@ -291,6 +293,7 @@ static int query_formats(AVFilterContext *ctx) switch (s->filter) { case LOWPASS: in_pix_fmts = in_lowpass_pix_fmts; break; case CHROMA: + case XFLAT: case AFLAT: case FLAT: in_pix_fmts = in_flat_pix_fmts; break; case ACOLOR: @@ -619,6 +622,22 @@ static void update(uint8_t *target, int max, int intensity) *target = 255; } +static void update_cr(uint8_t *target, int unused, int intensity) +{ + if (*target - intensity > 0) + *target -= intensity; + else + *target = 0; +} + +static void update16_cr(uint16_t *target, int unused, int intensity, int limit) +{ + if (*target - intensity > 0) + *target -= intensity; + else + *target = 0; +} + static av_always_inline void lowpass16(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, @@ -1014,256 +1033,276 @@ static av_always_inline void flat(WaveformContext *s, envelope(s, out, plane, (plane + 1) % s->ncomp, column ? offset_x : offset_y); } -static av_always_inline void aflat16(WaveformContext *s, - AVFrame *in, AVFrame *out, - int component, int intensity, - int offset_y, int offset_x, - int column, int mirror) -{ - const int plane = s->desc->comp[component].plane; - const int c0_linesize = in->linesize[ plane + 0 ] / 2; - const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2; - const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2; - const int c0_shift_w = s->shift_w[ component + 0 ]; - const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; - const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; - const int c0_shift_h = s->shift_h[ component + 0 ]; - const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; - const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; - const int d0_linesize = out->linesize[ plane + 0 ] / 2; - const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2; - const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2; - const int limit = s->max - 1; - const int max = limit - intensity; - const int mid = s->max / 2; - const int src_h = in->height; - const int src_w = in->width; - int x, y; - - if (column) { - const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); - const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); - const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); - - for (x = 0; x < src_w; x++) { - const uint16_t *c0_data = (uint16_t *)in->data[plane + 0]; - const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp]; - const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp]; - uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x; - uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; - uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; - uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); - uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data); - uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); - uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data); - uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); - uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data); - - for (y = 0; y < src_h; y++) { - const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + mid; - const int c1 = FFMIN(c1_data[x >> c1_shift_w], limit) - mid; - const int c2 = FFMIN(c2_data[x >> c2_shift_w], limit) - mid; - uint16_t *target; - - target = d0 + x + d0_signed_linesize * c0; - update16(target, max, intensity, limit); - - target = d1 + x + d1_signed_linesize * (c0 + c1); - update16(target, max, intensity, limit); - - target = d2 + x + d2_signed_linesize * (c0 + c2); - update16(target, max, intensity, limit); - - if (!c0_shift_h || (y & c0_shift_h)) - c0_data += c0_linesize; - if (!c1_shift_h || (y & c1_shift_h)) - c1_data += c1_linesize; - if (!c2_shift_h || (y & c2_shift_h)) - c2_data += c2_linesize; - d0_data += d0_linesize; - d1_data += d1_linesize; - d2_data += d2_linesize; - } - } - } else { - const uint16_t *c0_data = (uint16_t *)in->data[plane]; - const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp]; - const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp]; - uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x; - uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; - uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; - - if (mirror) { - d0_data += s->size - 1; - d1_data += s->size - 1; - d2_data += s->size - 1; - } - - for (y = 0; y < src_h; y++) { - for (x = 0; x < src_w; x++) { - const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + mid; - const int c1 = FFMIN(c1_data[x >> c1_shift_w], limit) - mid; - const int c2 = FFMIN(c2_data[x >> c2_shift_w], limit) - mid; - uint16_t *target; - - if (mirror) { - target = d0_data - c0; - update16(target, max, intensity, limit); - target = d1_data - (c0 + c1); - update16(target, max, intensity, limit); - target = d2_data - (c0 + c2); - update16(target, max, intensity, limit); - } else { - target = d0_data + c0; - update16(target, max, intensity, limit); - target = d1_data + (c0 + c1); - update16(target, max, intensity, limit); - target = d2_data + (c0 + c2); - update16(target, max, intensity, limit); - } - } - - if (!c0_shift_h || (y & c0_shift_h)) - c0_data += c0_linesize; - if (!c1_shift_h || (y & c1_shift_h)) - c1_data += c1_linesize; - if (!c2_shift_h || (y & c2_shift_h)) - c2_data += c2_linesize; - d0_data += d0_linesize; - d1_data += d1_linesize; - d2_data += d2_linesize; - } - } - - envelope16(s, out, plane, (plane + 0) % s->ncomp, column ? offset_x : offset_y); - envelope16(s, out, plane, (plane + 1) % s->ncomp, column ? offset_x : offset_y); - envelope16(s, out, plane, (plane + 2) % s->ncomp, column ? offset_x : offset_y); +#define AFLAT16(name, update_cr, column, mirror) \ +static av_always_inline void name (WaveformContext *s, \ + AVFrame *in, AVFrame *out, \ + int component, int intensity, \ + int offset_y, int offset_x, \ + int unused1, int unused2) \ +{ \ + const int plane = s->desc->comp[component].plane; \ + const int c0_linesize = in->linesize[ plane + 0 ] / 2; \ + const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2; \ + const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2; \ + const int c0_shift_w = s->shift_w[ component + 0 ]; \ + const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; \ + const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; \ + const int c0_shift_h = s->shift_h[ component + 0 ]; \ + const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; \ + const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; \ + const int d0_linesize = out->linesize[ plane + 0 ] / 2; \ + const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2; \ + const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2; \ + const int limit = s->max - 1; \ + const int max = limit - intensity; \ + const int mid = s->max / 2; \ + const int src_h = in->height; \ + const int src_w = in->width; \ + int x, y; \ + \ + if (column) { \ + const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); \ + const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); \ + const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); \ + \ + for (x = 0; x < src_w; x++) { \ + const uint16_t *c0_data = (uint16_t *)in->data[plane + 0]; \ + const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp]; \ + const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp]; \ + uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x; \ + uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; \ + uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; \ + uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); \ + uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data); \ + uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); \ + uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data); \ + uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); \ + uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data); \ + \ + for (y = 0; y < src_h; y++) { \ + const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + mid; \ + const int c1 = FFMIN(c1_data[x >> c1_shift_w], limit) - mid; \ + const int c2 = FFMIN(c2_data[x >> c2_shift_w], limit) - mid; \ + uint16_t *target; \ + \ + target = d0 + x + d0_signed_linesize * c0; \ + update16(target, max, intensity, limit); \ + \ + target = d1 + x + d1_signed_linesize * (c0 + c1); \ + update16(target, max, intensity, limit); \ + \ + target = d2 + x + d2_signed_linesize * (c0 + c2); \ + update_cr(target, max, intensity, limit); \ + \ + if (!c0_shift_h || (y & c0_shift_h)) \ + c0_data += c0_linesize; \ + if (!c1_shift_h || (y & c1_shift_h)) \ + c1_data += c1_linesize; \ + if (!c2_shift_h || (y & c2_shift_h)) \ + c2_data += c2_linesize; \ + d0_data += d0_linesize; \ + d1_data += d1_linesize; \ + d2_data += d2_linesize; \ + } \ + } \ + } else { \ + const uint16_t *c0_data = (uint16_t *)in->data[plane]; \ + const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp]; \ + const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp]; \ + uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x; \ + uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; \ + uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; \ + \ + if (mirror) { \ + d0_data += s->size - 1; \ + d1_data += s->size - 1; \ + d2_data += s->size - 1; \ + } \ + \ + for (y = 0; y < src_h; y++) { \ + for (x = 0; x < src_w; x++) { \ + const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + mid; \ + const int c1 = FFMIN(c1_data[x >> c1_shift_w], limit) - mid; \ + const int c2 = FFMIN(c2_data[x >> c2_shift_w], limit) - mid; \ + uint16_t *target; \ + \ + if (mirror) { \ + target = d0_data - c0; \ + update16(target, max, intensity, limit); \ + target = d1_data - (c0 + c1); \ + update16(target, max, intensity, limit); \ + target = d2_data - (c0 + c2); \ + update_cr(target, max, intensity, limit); \ + } else { \ + target = d0_data + c0; \ + update16(target, max, intensity, limit); \ + target = d1_data + (c0 + c1); \ + update16(target, max, intensity, limit); \ + target = d2_data + (c0 + c2); \ + update_cr(target, max, intensity, limit); \ + } \ + } \ + \ + if (!c0_shift_h || (y & c0_shift_h)) \ + c0_data += c0_linesize; \ + if (!c1_shift_h || (y & c1_shift_h)) \ + c1_data += c1_linesize; \ + if (!c2_shift_h || (y & c2_shift_h)) \ + c2_data += c2_linesize; \ + d0_data += d0_linesize; \ + d1_data += d1_linesize; \ + d2_data += d2_linesize; \ + } \ + } \ + \ + envelope16(s, out, plane, (plane + 0) % s->ncomp, column ? offset_x : offset_y); \ + envelope16(s, out, plane, (plane + 1) % s->ncomp, column ? offset_x : offset_y); \ + envelope16(s, out, plane, (plane + 2) % s->ncomp, column ? offset_x : offset_y); \ } -static av_always_inline void aflat(WaveformContext *s, - AVFrame *in, AVFrame *out, - int component, int intensity, - int offset_y, int offset_x, - int column, int mirror) -{ - const int plane = s->desc->comp[component].plane; - const int c0_linesize = in->linesize[ plane + 0 ]; - const int c1_linesize = in->linesize[(plane + 1) % s->ncomp]; - const int c2_linesize = in->linesize[(plane + 2) % s->ncomp]; - const int c0_shift_w = s->shift_w[ component + 0 ]; - const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; - const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; - const int c0_shift_h = s->shift_h[ component + 0 ]; - const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; - const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; - const int d0_linesize = out->linesize[ plane + 0 ]; - const int d1_linesize = out->linesize[(plane + 1) % s->ncomp]; - const int d2_linesize = out->linesize[(plane + 2) % s->ncomp]; - const int max = 255 - intensity; - const int src_h = in->height; - const int src_w = in->width; - int x, y; - - if (column) { - const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); - const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); - const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); - - for (x = 0; x < src_w; x++) { - const uint8_t *c0_data = in->data[plane + 0]; - const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp]; - const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp]; - uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; - uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; - uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; - uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); - uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data); - uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); - uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data); - uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); - uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data); - - for (y = 0; y < src_h; y++) { - const int c0 = c0_data[x >> c0_shift_w] + 128; - const int c1 = c1_data[x >> c1_shift_w] - 128; - const int c2 = c2_data[x >> c2_shift_w] - 128; - uint8_t *target; - - target = d0 + x + d0_signed_linesize * c0; - update(target, max, intensity); - - target = d1 + x + d1_signed_linesize * (c0 + c1); - update(target, max, intensity); - - target = d2 + x + d2_signed_linesize * (c0 + c2); - update(target, max, intensity); - - if (!c0_shift_h || (y & c0_shift_h)) - c0_data += c0_linesize; - if (!c1_shift_h || (y & c1_shift_h)) - c1_data += c1_linesize; - if (!c1_shift_h || (y & c1_shift_h)) - c2_data += c1_linesize; - d0_data += d0_linesize; - d1_data += d1_linesize; - d2_data += d2_linesize; - } - } - } else { - const uint8_t *c0_data = in->data[plane]; - const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp]; - const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp]; - uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; - uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; - uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; - - if (mirror) { - d0_data += s->size - 1; - d1_data += s->size - 1; - d2_data += s->size - 1; - } - - for (y = 0; y < src_h; y++) { - for (x = 0; x < src_w; x++) { - const int c0 = c0_data[x >> c0_shift_w] + 128; - const int c1 = c1_data[x >> c1_shift_w] - 128; - const int c2 = c2_data[x >> c2_shift_w] - 128; - uint8_t *target; - - if (mirror) { - target = d0_data - c0; - update(target, max, intensity); - target = d1_data - (c0 + c1); - update(target, max, intensity); - target = d2_data - (c0 + c2); - update(target, max, intensity); - } else { - target = d0_data + c0; - update(target, max, intensity); - target = d1_data + (c0 + c1); - update(target, max, intensity); - target = d2_data + (c0 + c2); - update(target, max, intensity); - } - } - - if (!c0_shift_h || (y & c0_shift_h)) - c0_data += c0_linesize; - if (!c1_shift_h || (y & c1_shift_h)) - c1_data += c1_linesize; - if (!c2_shift_h || (y & c2_shift_h)) - c2_data += c2_linesize; - d0_data += d0_linesize; - d1_data += d1_linesize; - d2_data += d2_linesize; - } - } - - envelope(s, out, plane, (plane + 0) % s->ncomp, column ? offset_x : offset_y); - envelope(s, out, plane, (plane + 1) % s->ncomp, column ? offset_x : offset_y); - envelope(s, out, plane, (plane + 2) % s->ncomp, column ? offset_x : offset_y); +#define AFLAT(name, update_cr, column, mirror) \ +static av_always_inline void name(WaveformContext *s, \ + AVFrame *in, AVFrame *out, \ + int component, int intensity, \ + int offset_y, int offset_x, \ + int unused1, int unused2) \ +{ \ + const int plane = s->desc->comp[component].plane; \ + const int c0_linesize = in->linesize[ plane + 0 ]; \ + const int c1_linesize = in->linesize[(plane + 1) % s->ncomp]; \ + const int c2_linesize = in->linesize[(plane + 2) % s->ncomp]; \ + const int c0_shift_w = s->shift_w[ component + 0 ]; \ + const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; \ + const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; \ + const int c0_shift_h = s->shift_h[ component + 0 ]; \ + const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; \ + const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; \ + const int d0_linesize = out->linesize[ plane + 0 ]; \ + const int d1_linesize = out->linesize[(plane + 1) % s->ncomp]; \ + const int d2_linesize = out->linesize[(plane + 2) % s->ncomp]; \ + const int max = 255 - intensity; \ + const int src_h = in->height; \ + const int src_w = in->width; \ + int x, y; \ + \ + if (column) { \ + const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); \ + const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); \ + const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); \ + \ + for (x = 0; x < src_w; x++) { \ + const uint8_t *c0_data = in->data[plane + 0]; \ + const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp]; \ + const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp]; \ + uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; \ + uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; \ + uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; \ + uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); \ + uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data); \ + uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); \ + uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data); \ + uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); \ + uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data); \ + \ + for (y = 0; y < src_h; y++) { \ + const int c0 = c0_data[x >> c0_shift_w] + 128; \ + const int c1 = c1_data[x >> c1_shift_w] - 128; \ + const int c2 = c2_data[x >> c2_shift_w] - 128; \ + uint8_t *target; \ + \ + target = d0 + x + d0_signed_linesize * c0; \ + update(target, max, intensity); \ + \ + target = d1 + x + d1_signed_linesize * (c0 + c1); \ + update(target, max, intensity); \ + \ + target = d2 + x + d2_signed_linesize * (c0 + c2); \ + update_cr(target, max, intensity); \ + \ + if (!c0_shift_h || (y & c0_shift_h)) \ + c0_data += c0_linesize; \ + if (!c1_shift_h || (y & c1_shift_h)) \ + c1_data += c1_linesize; \ + if (!c1_shift_h || (y & c1_shift_h)) \ + c2_data += c1_linesize; \ + d0_data += d0_linesize; \ + d1_data += d1_linesize; \ + d2_data += d2_linesize; \ + } \ + } \ + } else { \ + const uint8_t *c0_data = in->data[plane]; \ + const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp]; \ + const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp]; \ + uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; \ + uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; \ + uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; \ + \ + if (mirror) { \ + d0_data += s->size - 1; \ + d1_data += s->size - 1; \ + d2_data += s->size - 1; \ + } \ + \ + for (y = 0; y < src_h; y++) { \ + for (x = 0; x < src_w; x++) { \ + const int c0 = c0_data[x >> c0_shift_w] + 128; \ + const int c1 = c1_data[x >> c1_shift_w] - 128; \ + const int c2 = c2_data[x >> c2_shift_w] - 128; \ + uint8_t *target; \ + \ + if (mirror) { \ + target = d0_data - c0; \ + update(target, max, intensity); \ + target = d1_data - (c0 + c1); \ + update(target, max, intensity); \ + target = d2_data - (c0 + c2); \ + update_cr(target, max, intensity); \ + } else { \ + target = d0_data + c0; \ + update(target, max, intensity); \ + target = d1_data + (c0 + c1); \ + update(target, max, intensity); \ + target = d2_data + (c0 + c2); \ + update_cr(target, max, intensity); \ + } \ + } \ + \ + if (!c0_shift_h || (y & c0_shift_h)) \ + c0_data += c0_linesize; \ + if (!c1_shift_h || (y & c1_shift_h)) \ + c1_data += c1_linesize; \ + if (!c2_shift_h || (y & c2_shift_h)) \ + c2_data += c2_linesize; \ + d0_data += d0_linesize; \ + d1_data += d1_linesize; \ + d2_data += d2_linesize; \ + } \ + } \ + \ + envelope(s, out, plane, (plane + 0) % s->ncomp, column ? offset_x : offset_y); \ + envelope(s, out, plane, (plane + 1) % s->ncomp, column ? offset_x : offset_y); \ + envelope(s, out, plane, (plane + 2) % s->ncomp, column ? offset_x : offset_y); \ } +AFLAT16(aflat16_row, update16, 0, 0) +AFLAT16(aflat16_row_mirror, update16, 0, 1) +AFLAT16(aflat16_column, update16, 1, 0) +AFLAT16(aflat16_column_mirror, update16, 1, 1) +AFLAT16(xflat16_row, update16_cr, 0, 0) +AFLAT16(xflat16_row_mirror, update16_cr, 0, 1) +AFLAT16(xflat16_column, update16_cr, 1, 0) +AFLAT16(xflat16_column_mirror, update16_cr, 1, 1) + +AFLAT(aflat_row, update, 0, 0) +AFLAT(aflat_row_mirror, update, 0, 1) +AFLAT(aflat_column, update, 1, 0) +AFLAT(aflat_column_mirror, update, 1, 1) +AFLAT(xflat_row, update_cr, 0, 0) +AFLAT(xflat_row_mirror, update_cr, 0, 1) +AFLAT(xflat_column, update_cr, 1, 0) +AFLAT(xflat_column_mirror, update_cr, 1, 1) + static av_always_inline void chroma16(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, @@ -2481,6 +2520,7 @@ static int config_input(AVFilterLink *inlink) s->graticulef = graticule_none; switch (s->filter) { + case XFLAT: case AFLAT: s->size = 256 * 2; break; case FLAT: s->size = 256 * 3; break; default: s->size = 256; break; @@ -2504,14 +2544,14 @@ static int config_input(AVFilterLink *inlink) case 0x1011: case 0x0111: case 0x0011: s->waveform = flat16; break; - case 0x1102: - case 0x1002: - case 0x0102: - case 0x0002: s->waveform = aflat; break; - case 0x1112: - case 0x1012: - case 0x0112: - case 0x0012: s->waveform = aflat16; break; + case 0x1102: s->waveform = aflat_column_mirror; break; + case 0x1002: s->waveform = aflat_row_mirror; break; + case 0x0102: s->waveform = aflat_column; break; + case 0x0002: s->waveform = aflat_row; break; + case 0x1112: s->waveform = aflat16_column_mirror; break; + case 0x1012: s->waveform = aflat16_row_mirror; break; + case 0x0112: s->waveform = aflat16_column; break; + case 0x0012: s->waveform = aflat16_row; break; case 0x1103: case 0x1003: case 0x0103: @@ -2536,6 +2576,14 @@ static int config_input(AVFilterLink *inlink) case 0x1015: case 0x0115: case 0x0015: s->waveform = acolor16; break; + case 0x1106: s->waveform = xflat_column_mirror; break; + case 0x1006: s->waveform = xflat_row_mirror; break; + case 0x0106: s->waveform = xflat_column; break; + case 0x0006: s->waveform = xflat_row; break; + case 0x1116: s->waveform = xflat16_column_mirror; break; + case 0x1016: s->waveform = xflat16_row_mirror; break; + case 0x0116: s->waveform = xflat16_column; break; + case 0x0016: s->waveform = xflat16_row; break; } switch (s->filter) { @@ -2544,6 +2592,7 @@ static int config_input(AVFilterLink *inlink) case ACOLOR: case CHROMA: case AFLAT: + case XFLAT: case FLAT: if (s->graticule && s->mode == 1) s->graticulef = s->bits > 8 ? graticule16_green_column : graticule_green_column; @@ -2611,6 +2660,7 @@ static int config_input(AVFilterLink *inlink) break; } break; + case XFLAT: case AFLAT: switch (s->scale) { case DIGITAL: From 36cf3eb76a72058ea2d61c3d66e40d6929ca44d5 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 21 Mar 2018 12:20:24 +0100 Subject: [PATCH 2192/2557] avfilter/vf_waveform: add orange graticule Signed-off-by: Paul B Mahol --- doc/filters.texi | 3 +++ libavfilter/vf_waveform.c | 47 ++++++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index a3ccb218b29fb..aa7d4fc2d9144 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16513,6 +16513,9 @@ Do not display graticule. @item green Display green graticule showing legal broadcast ranges. + +@item orange +Display orange graticule showing legal broadcast ranges. @end table @item opacity, o diff --git a/libavfilter/vf_waveform.c b/libavfilter/vf_waveform.c index 44c787fb3d0fe..428147c607c78 100644 --- a/libavfilter/vf_waveform.c +++ b/libavfilter/vf_waveform.c @@ -90,6 +90,7 @@ typedef struct WaveformContext { int max; int size; int scale; + uint8_t grat_yuva_color[4]; int shift_w[4], shift_h[4]; GraticuleLines *glines; int nb_glines; @@ -137,10 +138,11 @@ static const AVOption waveform_options[] = { { "color", NULL, 0, AV_OPT_TYPE_CONST, {.i64=COLOR}, 0, 0, FLAGS, "filter" }, { "acolor", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ACOLOR}, 0, 0, FLAGS, "filter" }, { "xflat", NULL, 0, AV_OPT_TYPE_CONST, {.i64=XFLAT}, 0, 0, FLAGS, "filter" }, - { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "graticule" }, - { "g", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "graticule" }, - { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "graticule" }, - { "green", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "graticule" }, + { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule" }, + { "g", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "graticule" }, + { "green", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "graticule" }, + { "orange", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "graticule" }, { "opacity", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, { "o", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, { "flags", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 3, FLAGS, "flags" }, @@ -1878,7 +1880,6 @@ static av_always_inline void acolor(WaveformContext *s, } static const uint8_t black_yuva_color[4] = { 0, 127, 127, 255 }; -static const uint8_t green_yuva_color[4] = { 255, 0, 0, 255 }; static const uint8_t black_gbrp_color[4] = { 0, 0, 0, 255 }; static const GraticuleLines aflat_digital8[] = { @@ -2339,7 +2340,7 @@ static void graticule_none(WaveformContext *s, AVFrame *out) { } -static void graticule_green_row(WaveformContext *s, AVFrame *out) +static void graticule_row(WaveformContext *s, AVFrame *out) { const int step = (s->flags & 2) + 1; const float o1 = s->opacity; @@ -2353,7 +2354,7 @@ static void graticule_green_row(WaveformContext *s, AVFrame *out) k++; for (p = 0; p < s->ncomp; p++) { - const int v = green_yuva_color[p]; + const int v = s->grat_yuva_color[p]; for (l = 0; l < s->nb_glines; l++) { const uint16_t pos = s->glines[l].line[c].pos; int x = offset_x + (s->mirror ? s->size - 1 - pos : pos); @@ -2371,7 +2372,7 @@ static void graticule_green_row(WaveformContext *s, AVFrame *out) if (x < 0) x = 4; - draw_vtext(out, x, offset_y + 2, o1, o2, name, green_yuva_color); + draw_vtext(out, x, offset_y + 2, o1, o2, name, s->grat_yuva_color); } offset_x += s->size * (s->display == STACK); @@ -2379,12 +2380,12 @@ static void graticule_green_row(WaveformContext *s, AVFrame *out) } } -static void graticule16_green_row(WaveformContext *s, AVFrame *out) +static void graticule16_row(WaveformContext *s, AVFrame *out) { const int step = (s->flags & 2) + 1; const float o1 = s->opacity; const float o2 = 1. - o1; - const int mult = s->size / 256; + const int mult = s->max / 256; const int height = s->display == PARADE ? out->height / s->acomp : out->height; int k = 0, c, p, l, offset_x = 0, offset_y = 0; @@ -2394,7 +2395,7 @@ static void graticule16_green_row(WaveformContext *s, AVFrame *out) k++; for (p = 0; p < s->ncomp; p++) { - const int v = green_yuva_color[p] * mult; + const int v = s->grat_yuva_color[p] * mult; for (l = 0; l < s->nb_glines ; l++) { const uint16_t pos = s->glines[l].line[c].pos; int x = offset_x + (s->mirror ? s->size - 1 - pos : pos); @@ -2412,7 +2413,7 @@ static void graticule16_green_row(WaveformContext *s, AVFrame *out) if (x < 0) x = 4; - draw_vtext16(out, x, offset_y + 2, mult, o1, o2, name, green_yuva_color); + draw_vtext16(out, x, offset_y + 2, mult, o1, o2, name, s->grat_yuva_color); } offset_x += s->size * (s->display == STACK); @@ -2420,7 +2421,7 @@ static void graticule16_green_row(WaveformContext *s, AVFrame *out) } } -static void graticule_green_column(WaveformContext *s, AVFrame *out) +static void graticule_column(WaveformContext *s, AVFrame *out) { const int step = (s->flags & 2) + 1; const float o1 = s->opacity; @@ -2434,7 +2435,7 @@ static void graticule_green_column(WaveformContext *s, AVFrame *out) k++; for (p = 0; p < s->ncomp; p++) { - const int v = green_yuva_color[p]; + const int v = s->grat_yuva_color[p]; for (l = 0; l < s->nb_glines ; l++) { const uint16_t pos = s->glines[l].line[c].pos; int y = offset_y + (s->mirror ? s->size - 1 - pos : pos); @@ -2452,7 +2453,7 @@ static void graticule_green_column(WaveformContext *s, AVFrame *out) if (y < 0) y = 4; - draw_htext(out, 2 + offset_x, y, o1, o2, name, green_yuva_color); + draw_htext(out, 2 + offset_x, y, o1, o2, name, s->grat_yuva_color); } offset_y += s->size * (s->display == STACK); @@ -2460,12 +2461,12 @@ static void graticule_green_column(WaveformContext *s, AVFrame *out) } } -static void graticule16_green_column(WaveformContext *s, AVFrame *out) +static void graticule16_column(WaveformContext *s, AVFrame *out) { const int step = (s->flags & 2) + 1; const float o1 = s->opacity; const float o2 = 1. - o1; - const int mult = s->size / 256; + const int mult = s->max / 256; const int width = s->display == PARADE ? out->width / s->acomp : out->width; int k = 0, c, p, l, offset_x = 0, offset_y = 0; @@ -2475,7 +2476,7 @@ static void graticule16_green_column(WaveformContext *s, AVFrame *out) k++; for (p = 0; p < s->ncomp; p++) { - const int v = green_yuva_color[p] * mult; + const int v = s->grat_yuva_color[p] * mult; for (l = 0; l < s->nb_glines ; l++) { const uint16_t pos = s->glines[l].line[c].pos; int y = offset_y + (s->mirror ? s->size - 1 - pos : pos); @@ -2493,7 +2494,7 @@ static void graticule16_green_column(WaveformContext *s, AVFrame *out) if (y < 0) y = 4; - draw_htext16(out, 2 + offset_x, y, mult, o1, o2, name, green_yuva_color); + draw_htext16(out, 2 + offset_x, y, mult, o1, o2, name, s->grat_yuva_color); } offset_y += s->size * (s->display == STACK); @@ -2586,6 +2587,10 @@ static int config_input(AVFilterLink *inlink) case 0x0016: s->waveform = xflat16_row; break; } + s->grat_yuva_color[0] = 255; + s->grat_yuva_color[2] = s->graticule == 2 ? 255 : 0; + s->grat_yuva_color[3] = 255; + switch (s->filter) { case LOWPASS: case COLOR: @@ -2595,9 +2600,9 @@ static int config_input(AVFilterLink *inlink) case XFLAT: case FLAT: if (s->graticule && s->mode == 1) - s->graticulef = s->bits > 8 ? graticule16_green_column : graticule_green_column; + s->graticulef = s->bits > 8 ? graticule16_column : graticule_column; else if (s->graticule && s->mode == 0) - s->graticulef = s->bits > 8 ? graticule16_green_row : graticule_green_row; + s->graticulef = s->bits > 8 ? graticule16_row : graticule_row; break; } From 1b45e6db22d979baa410645a1d5ab575175f1eb7 Mon Sep 17 00:00:00 2001 From: Bela Bodecs Date: Tue, 20 Mar 2018 23:24:11 +0100 Subject: [PATCH 2193/2557] avformat/unix: fix handling of EOF in case of SOCK_STREAM. When recv() returns 0 in case of SOCK_STREAM type, it means EOF and with this patch returns value accordingly. Signed-off-by: Bela Bodecs --- libavformat/unix.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/unix.c b/libavformat/unix.c index 4f01d14a938e2..38016dbafea43 100644 --- a/libavformat/unix.c +++ b/libavformat/unix.c @@ -111,6 +111,8 @@ static int unix_read(URLContext *h, uint8_t *buf, int size) return ret; } ret = recv(s->fd, buf, size, 0); + if (!ret && s->type == SOCK_STREAM) + return AVERROR_EOF; return ret < 0 ? ff_neterrno() : ret; } From a4726288f8c14fecb8e0e2b36acc6c595dfa3b03 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Thu, 8 Mar 2018 14:01:48 +0800 Subject: [PATCH 2194/2557] lavc/dump_extradata_bsf: support dump options. support dump bit stream filter options Signed-off-by: Jun Zhao Signed-off-by: James Almer --- libavcodec/dump_extradata_bsf.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libavcodec/dump_extradata_bsf.c b/libavcodec/dump_extradata_bsf.c index fa7bc86e1911c..081ae5aa08b61 100644 --- a/libavcodec/dump_extradata_bsf.c +++ b/libavcodec/dump_extradata_bsf.c @@ -78,13 +78,14 @@ static int dump_extradata(AVBSFContext *ctx, AVPacket *out) } #define OFFSET(x) offsetof(DumpExtradataContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) static const AVOption options[] = { { "freq", "When do dump extradata", OFFSET(freq), AV_OPT_TYPE_INT, - { .i64 = DUMP_FREQ_KEYFRAME }, DUMP_FREQ_KEYFRAME, DUMP_FREQ_ALL, 0, "freq" }, - { "k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_KEYFRAME }, .unit = "freq" }, - { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_KEYFRAME }, .unit = "freq" }, - { "e", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_ALL }, .unit = "freq" }, - { "all", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_ALL }, .unit = "freq" }, + { .i64 = DUMP_FREQ_KEYFRAME }, DUMP_FREQ_KEYFRAME, DUMP_FREQ_ALL, FLAGS, "freq" }, + { "k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_KEYFRAME }, .flags = FLAGS, .unit = "freq" }, + { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_KEYFRAME }, .flags = FLAGS, .unit = "freq" }, + { "e", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_ALL }, .flags = FLAGS, .unit = "freq" }, + { "all", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_ALL }, .flags = FLAGS, .unit = "freq" }, { NULL }, }; From b8e406c01a75904e84c743a35ac4c2f28de4a625 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Thu, 8 Mar 2018 14:57:47 +0800 Subject: [PATCH 2195/2557] lavc/noise_bsf: support dump options. support dump bit stream filter options. Signed-off-by: Jun Zhao Signed-off-by: James Almer --- libavcodec/noise_bsf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/noise_bsf.c b/libavcodec/noise_bsf.c index 84b94032ad3f3..6bb89507fcb21 100644 --- a/libavcodec/noise_bsf.c +++ b/libavcodec/noise_bsf.c @@ -78,9 +78,10 @@ static int noise(AVBSFContext *ctx, AVPacket *out) } #define OFFSET(x) offsetof(NoiseContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_BSF_PARAM) static const AVOption options[] = { - { "amount", NULL, OFFSET(amount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX }, - { "dropamount", NULL, OFFSET(dropamount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX }, + { "amount", NULL, OFFSET(amount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { "dropamount", NULL, OFFSET(dropamount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, { NULL }, }; From 28aaed773712d170e13f35658aac685dd8b7db44 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Thu, 8 Mar 2018 15:00:27 +0800 Subject: [PATCH 2196/2557] lavc/remove_extradata_bsf: support dump options. support dump bit stream filter options Signed-off-by: Jun Zhao Signed-off-by: James Almer --- libavcodec/remove_extradata_bsf.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libavcodec/remove_extradata_bsf.c b/libavcodec/remove_extradata_bsf.c index d74391e547ab9..b762079e05b3d 100644 --- a/libavcodec/remove_extradata_bsf.c +++ b/libavcodec/remove_extradata_bsf.c @@ -90,12 +90,13 @@ static void remove_extradata_close(AVBSFContext *ctx) } #define OFFSET(x) offsetof(RemoveExtradataContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) static const AVOption options[] = { - { "freq", NULL, OFFSET(freq), AV_OPT_TYPE_INT, { .i64 = REMOVE_FREQ_KEYFRAME }, REMOVE_FREQ_KEYFRAME, REMOVE_FREQ_NONKEYFRAME, 0, "freq" }, - { "k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_NONKEYFRAME }, .unit = "freq" }, - { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_KEYFRAME }, .unit = "freq" }, - { "e", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_ALL }, .unit = "freq" }, - { "all", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_ALL }, .unit = "freq" }, + { "freq", NULL, OFFSET(freq), AV_OPT_TYPE_INT, { .i64 = REMOVE_FREQ_KEYFRAME }, REMOVE_FREQ_KEYFRAME, REMOVE_FREQ_NONKEYFRAME, FLAGS, "freq" }, + { "k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_NONKEYFRAME }, .flags = FLAGS, .unit = "freq" }, + { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_KEYFRAME }, .flags = FLAGS, .unit = "freq" }, + { "e", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_ALL }, .flags = FLAGS, .unit = "freq" }, + { "all", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_ALL }, .flags = FLAGS, .unit = "freq" }, { NULL }, }; From f14ca600015d234f383e9ea5ba5c9f9830271cb3 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 19 Mar 2018 12:39:08 -0300 Subject: [PATCH 2197/2557] avcodec/avpacket: add av_packet_make_writable() Useful as well to quickly make a packet reference counted when it isn't already so. Signed-off-by: James Almer --- doc/APIchanges | 3 +++ libavcodec/avcodec.h | 11 +++++++++++ libavcodec/avpacket.c | 24 ++++++++++++++++++++++++ libavcodec/version.h | 2 +- 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 4c0ee7147a15a..d410bcdd75629 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-03-21 - xxxxxxx - lavc 58.15.100 - avcodec.h + Add av_packet_make_writable(). + 2018-03-18 - xxxxxxx - lavu 56.11.100 - frame.h Add AV_FRAME_DATA_QP_TABLE_PROPERTIES and AV_FRAME_DATA_QP_TABLE_DATA. diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index a8322fb62a2f2..a78017f1fbd4b 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -4518,6 +4518,17 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src); */ int av_packet_copy_props(AVPacket *dst, const AVPacket *src); +/** + * Create a writable reference for the data described by a given packet, + * avoiding data copy if possible. + * + * @param pkt Packet whose data should be made writable. + * + * @return 0 on success, a negative AVERROR on failure. On failure, the + * packet is unchanged. + */ +int av_packet_make_writable(AVPacket *pkt); + /** * Convert valid timing fields (timestamps / durations) in a packet from one * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index fe8113ab76455..0693ca6f62f58 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -652,6 +652,30 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src) src->size = 0; } +int av_packet_make_writable(AVPacket *pkt) +{ + AVBufferRef *buf = NULL; + int ret; + + if (pkt->buf && av_buffer_is_writable(pkt->buf)) + return 0; + + if (!pkt->data) + return AVERROR(EINVAL); + + ret = packet_alloc(&buf, pkt->size); + if (ret < 0) + return ret; + if (pkt->size) + memcpy(buf->data, pkt->data, pkt->size); + + av_buffer_unref(&pkt->buf); + pkt->buf = buf; + pkt->data = buf->data; + + return 0; +} + void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb) { if (pkt->pts != AV_NOPTS_VALUE) diff --git a/libavcodec/version.h b/libavcodec/version.h index ed34095c77675..a5b7f752d1666 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 14 +#define LIBAVCODEC_VERSION_MINOR 15 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From ead257db560ae0c66c4e834a743f2148e6718f04 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 21 Mar 2018 22:09:45 -0300 Subject: [PATCH 2198/2557] cmdutils: print supported codecs in show_help_bsf() Tested-by: Jun Zhao Signed-off-by: James Almer --- fftools/cmdutils.c | 2 ++ fftools/cmdutils.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 708a849f5189b..c0ddf0b287a9f 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1907,6 +1907,8 @@ static void show_help_bsf(const char *name) } printf("Bit stream filter %s\n", bsf->name); + PRINT_CODEC_SUPPORTED(bsf, codec_ids, enum AVCodecID, "codecs", + AV_CODEC_ID_NONE, GET_CODEC_NAME); if (bsf->priv_class) show_help_children(bsf->priv_class, AV_OPT_FLAG_BSF_PARAM); } diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 87244891d4fac..6e2e0a2acbc84 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -625,6 +625,9 @@ void *grow_array(void *array, int elem_size, int *size, int new_size); #define GET_PIX_FMT_NAME(pix_fmt)\ const char *name = av_get_pix_fmt_name(pix_fmt); +#define GET_CODEC_NAME(id)\ + const char *name = avcodec_descriptor_get(id)->name; + #define GET_SAMPLE_FMT_NAME(sample_fmt)\ const char *name = av_get_sample_fmt_name(sample_fmt) From ed0e0fe1021148007010a4d23017263599a52d82 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 22 Mar 2018 01:19:13 -0300 Subject: [PATCH 2199/2557] changelog: add missing line for filter_units bsf Signed-off-by: James Almer --- Changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog b/Changelog index 7969b414c4777..30a8978db48d3 100644 --- a/Changelog +++ b/Changelog @@ -47,6 +47,7 @@ version : - native SBC encoder and decoder - drmeter audio filter - hapqa_extract bitstream filter +- filter_units bitstream filter version 3.4: From 59347c2474801fda88c9a231b888c354362641b6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 22 Mar 2018 01:40:02 -0300 Subject: [PATCH 2200/2557] avcodec/dxva2_vc1: add missing frame_params callback to vc1_d3d11va2 hwaccel Fixes ticket #7096 Reviewed-by: wm4 Signed-off-by: James Almer --- libavcodec/dxva2_vc1.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c index f22c73cd1ebaf..06f1083b3afd1 100644 --- a/libavcodec/dxva2_vc1.c +++ b/libavcodec/dxva2_vc1.c @@ -473,6 +473,7 @@ const AVHWAccel ff_vc1_d3d11va2_hwaccel = { .start_frame = dxva2_vc1_start_frame, .decode_slice = dxva2_vc1_decode_slice, .end_frame = dxva2_vc1_end_frame, + .frame_params = ff_dxva2_common_frame_params, .frame_priv_data_size = sizeof(struct dxva2_picture_context), .priv_data_size = sizeof(FFDXVASharedContext), }; From c64c97b972c7325a71440a352a7d541a8c92b2da Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Thu, 22 Mar 2018 15:03:37 +0530 Subject: [PATCH 2201/2557] lavc/cfhd: add alpha decompanding in rgba12 Alpha decompanding curve added to post process the decoded alpha channel. Fixes ticket #6265. --- libavcodec/cfhd.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libavcodec/cfhd.c b/libavcodec/cfhd.c index fd5555834bb98..e35732df45b86 100644 --- a/libavcodec/cfhd.c +++ b/libavcodec/cfhd.c @@ -37,6 +37,9 @@ #include "thread.h" #include "cfhd.h" +#define ALPHA_COMPAND_DC_OFFSET 256 +#define ALPHA_COMPAND_GAIN 9400 + enum CFHDParam { ChannelCount = 12, SubbandCount = 14, @@ -94,6 +97,20 @@ static inline int dequant_and_decompand(int level, int quantisation) FFSIGN(level) * quantisation; } +static inline void process_alpha(int16_t *alpha, int width) +{ + int i, channel; + for (i = 0; i < width; i++) { + channel = alpha[i]; + channel -= ALPHA_COMPAND_DC_OFFSET; + channel <<= 3; + channel *= ALPHA_COMPAND_GAIN; + channel >>= 16; + channel = av_clip_uintp2(channel, 12); + alpha[i] = channel; + } +} + static inline void filter(int16_t *output, ptrdiff_t out_stride, int16_t *low, ptrdiff_t low_stride, int16_t *high, ptrdiff_t high_stride, @@ -792,6 +809,8 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame, high = s->plane[plane].l_h[7]; for (i = 0; i < lowpass_height * 2; i++) { horiz_filter_clip(dst, low, high, lowpass_width, s->bpc); + if (act_plane == 3) + process_alpha(dst, lowpass_width * 2); low += lowpass_width; high += lowpass_width; dst += pic->linesize[act_plane] / 2; From 65616bc191b110af6a81aa38b1d15aa9879d8cbc Mon Sep 17 00:00:00 2001 From: Courtland Idstrom Date: Mon, 19 Mar 2018 14:11:37 -0700 Subject: [PATCH 2202/2557] lavf/movenc: write track title metadata for mov files Track title (atom 'name') is a well defined user data atom for mov files. Existing code (for mp4) only writes title metadata if present. Relevant reference docs: https://developer.apple.com/library/content/documentation/QuickTime/Reference/QTRef_AtomsResources/Content/QTRef_AtomsResources4.html#//apple_ref/doc/uid/TP40004285-DontLinkChapterID_1--udta- https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-63839 --- libavformat/movenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index d681d519e6b4d..ef668eccd5003 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -3024,7 +3024,7 @@ static int mov_write_track_udta_tag(AVIOContext *pb, MOVMuxContext *mov, if (ret < 0) return ret; - if (mov->mode & MODE_MP4) + if (mov->mode & (MODE_MP4|MODE_MOV)) mov_write_track_metadata(pb_buf, st, "name", "title"); if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) { From 4f2ff3a53e170d77e1dd231d7246a74e186011c9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 21 Mar 2018 22:37:46 -0300 Subject: [PATCH 2203/2557] avcodec/mpeg4_unpack_bframes: make sure the packet is writable when data needs to be changed Nothing currently guarantees that the packet passed to the bsf will be writable. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavcodec/mpeg4_unpack_bframes_bsf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/mpeg4_unpack_bframes_bsf.c b/libavcodec/mpeg4_unpack_bframes_bsf.c index ba970794c5b0f..3a0ba105f532e 100644 --- a/libavcodec/mpeg4_unpack_bframes_bsf.c +++ b/libavcodec/mpeg4_unpack_bframes_bsf.c @@ -149,6 +149,9 @@ static int mpeg4_unpack_bframes_filter(AVBSFContext *ctx, AVPacket *out) av_packet_move_ref(out, in); out->size = pos_vop2; } else if (pos_p >= 0) { + ret = av_packet_make_writable(in); + if (ret < 0) + goto fail; av_log(ctx, AV_LOG_DEBUG, "Updating DivX userdata (remove trailing 'p').\n"); av_packet_move_ref(out, in); /* remove 'p' (packed) from the end of the (DivX) userdata string */ From 016d40011ac2815157fc11f6dda2f9bfb520ecfe Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 10 Mar 2018 19:57:35 -0300 Subject: [PATCH 2204/2557] avcodec/extract_extradata: don't uninitialize the H2645Packet on every processed packet Based on hevc_parser code. This prevents repeated unnecessary allocations and frees on every packet processed by the bsf. Reviewed-by: Jun Zhao Signed-off-by: James Almer --- libavcodec/extract_extradata_bsf.c | 33 +++++++++++++++++------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c index 82632c5b57769..082b3e749bc80 100644 --- a/libavcodec/extract_extradata_bsf.c +++ b/libavcodec/extract_extradata_bsf.c @@ -36,6 +36,9 @@ typedef struct ExtractExtradataContext { int (*extract)(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size); + /* H264/HEVC specifc fields */ + H2645Packet h2645_pkt; + /* AVOptions */ int remove; } ExtractExtradataContext; @@ -61,7 +64,6 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, ExtractExtradataContext *s = ctx->priv_data; - H2645Packet h2645_pkt = { 0 }; int extradata_size = 0, filtered_size = 0; const int *extradata_nal_types; int nb_extradata_nal_types; @@ -75,13 +77,13 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_h264); } - ret = ff_h2645_packet_split(&h2645_pkt, pkt->data, pkt->size, + ret = ff_h2645_packet_split(&s->h2645_pkt, pkt->data, pkt->size, ctx, 0, 0, ctx->par_in->codec_id, 1); if (ret < 0) - goto fail; + return ret; - for (i = 0; i < h2645_pkt.nb_nals; i++) { - H2645NAL *nal = &h2645_pkt.nals[i]; + for (i = 0; i < s->h2645_pkt.nb_nals; i++) { + H2645NAL *nal = &s->h2645_pkt.nals[i]; if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { extradata_size += nal->raw_size + 3; if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { @@ -104,8 +106,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, if (s->remove) { filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!filtered_buf) { - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); @@ -115,16 +116,15 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!extradata) { av_buffer_unref(&filtered_buf); - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } memset(extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); *data = extradata; *size = extradata_size; - for (i = 0; i < h2645_pkt.nb_nals; i++) { - H2645NAL *nal = &h2645_pkt.nals[i]; + for (i = 0; i < s->h2645_pkt.nb_nals; i++) { + H2645NAL *nal = &s->h2645_pkt.nals[i]; if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { AV_WB24(extradata, 1); // startcode @@ -145,9 +145,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, } } -fail: - ff_h2645_packet_uninit(&h2645_pkt); - return ret; + return 0; } static int extract_extradata_vc1(AVBSFContext *ctx, AVPacket *pkt, @@ -310,6 +308,12 @@ static int extract_extradata_filter(AVBSFContext *ctx, AVPacket *pkt) return ret; } +static void extract_extradata_close(AVBSFContext *ctx) +{ + ExtractExtradataContext *s = ctx->priv_data; + ff_h2645_packet_uninit(&s->h2645_pkt); +} + static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_CAVS, AV_CODEC_ID_H264, @@ -343,4 +347,5 @@ const AVBitStreamFilter ff_extract_extradata_bsf = { .priv_class = &extract_extradata_class, .init = extract_extradata_init, .filter = extract_extradata_filter, + .close = extract_extradata_close, }; From b78d55b2e63e410abe744932fda9358633743a9e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 22 Mar 2018 23:08:33 +0100 Subject: [PATCH 2205/2557] avfilter/avf_showvolume: add background opacity option This makes output more visible when overlayed. Signed-off-by: Paul B Mahol --- doc/filters.texi | 5 ++++- libavfilter/avf_showvolume.c | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index aa7d4fc2d9144..d6ea56b851717 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19941,8 +19941,11 @@ Set orientation, can be @code{horizontal} or @code{vertical}, default is @code{horizontal}. @item s -Set step size, allowed range s [0, 5]. Default is 0, which means +Set step size, allowed range is [0, 5]. Default is 0, which means step is disabled. + +@item p +Set background opacity, allowed range is [0, 1]. Default is 0. @end table @section showwaves diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index 897e5709b8566..9b836b9ad62c6 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -43,6 +43,7 @@ typedef struct ShowVolumeContext { char *color; int orientation; int step; + float bgopacity; AVFrame *out; AVExpr *c_expr; @@ -69,6 +70,7 @@ static const AVOption showvolume_options[] = { { "h", "horizontal", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "orientation" }, { "v", "vertical", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "orientation" }, { "s", "set step size", OFFSET(step), AV_OPT_TYPE_INT, {.i64=0}, 0, 5, FLAGS }, + { "p", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, FLAGS }, { NULL } }; @@ -224,18 +226,25 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) return AVERROR(ENOMEM); } - for (i = 0; i < outlink->h; i++) - memset(s->out->data[0] + i * s->out->linesize[0], 0, outlink->w * 4); + for (i = 0; i < outlink->h; i++) { + uint32_t *dst = (uint32_t *)(s->out->data[0] + i * s->out->linesize[0]); + const uint32_t bg = (uint32_t)(s->bgopacity * 255) << 24; + + for (j = 0; j < outlink->w; j++) + AV_WN32A(dst + j, bg); + } } s->out->pts = insamples->pts; for (j = 0; j < outlink->h; j++) { uint8_t *dst = s->out->data[0] + j * s->out->linesize[0]; + const uint32_t alpha = s->bgopacity * 255; + for (k = 0; k < outlink->w; k++) { dst[k * 4 + 0] = FFMAX(dst[k * 4 + 0] * s->f, 0); dst[k * 4 + 1] = FFMAX(dst[k * 4 + 1] * s->f, 0); dst[k * 4 + 2] = FFMAX(dst[k * 4 + 2] * s->f, 0); - dst[k * 4 + 3] = FFMAX(dst[k * 4 + 3] * s->f, 0); + dst[k * 4 + 3] = FFMAX(dst[k * 4 + 3] * s->f, alpha); } } From 2a1542d105dc3161516e34eef77bcd64aa72cab4 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 19 Mar 2018 22:52:30 +0000 Subject: [PATCH 2206/2557] lavfi/opencl: Derive global work size from plane image sizes Add a new function to find the global work size given the output image and the required block alignment, then use it in the overlay, program and unsharp filters. Fixes the overlay and unsharp filters applying the kernel to locations outside the frame when subsampled planes are present. --- libavfilter/opencl.c | 64 +++++++++++++++++++++++++++++++++ libavfilter/opencl.h | 8 +++++ libavfilter/vf_overlay_opencl.c | 6 ++-- libavfilter/vf_program_opencl.c | 8 ++--- libavfilter/vf_unsharp_opencl.c | 16 ++++----- 5 files changed, 87 insertions(+), 15 deletions(-) diff --git a/libavfilter/opencl.c b/libavfilter/opencl.c index 37afc41f8b25a..ae61667380a64 100644 --- a/libavfilter/opencl.c +++ b/libavfilter/opencl.c @@ -22,6 +22,7 @@ #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_opencl.h" #include "libavutil/mem.h" +#include "libavutil/pixdesc.h" #include "avfilter.h" #include "formats.h" @@ -276,3 +277,66 @@ int ff_opencl_filter_load_program_from_file(AVFilterContext *avctx, av_freep(&src); return err; } + +int ff_opencl_filter_work_size_from_image(AVFilterContext *avctx, + size_t *work_size, + AVFrame *frame, int plane, + int block_alignment) +{ + cl_mem image; + cl_mem_object_type type; + size_t width, height; + cl_int cle; + + if (frame->format != AV_PIX_FMT_OPENCL) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame format %s, " + "opencl required.\n", av_get_pix_fmt_name(frame->format)); + return AVERROR(EINVAL); + } + + image = (cl_mem)frame->data[plane]; + if (!image) { + av_log(avctx, AV_LOG_ERROR, "Plane %d required but not set.\n", + plane); + return AVERROR(EINVAL); + } + + cle = clGetMemObjectInfo(image, CL_MEM_TYPE, sizeof(type), + &type, NULL); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query object type of " + "plane %d: %d.\n", plane, cle); + return AVERROR_UNKNOWN; + } + if (type != CL_MEM_OBJECT_IMAGE2D) { + av_log(avctx, AV_LOG_ERROR, "Plane %d is not a 2D image.\n", + plane); + return AVERROR(EINVAL); + } + + cle = clGetImageInfo(image, CL_IMAGE_WIDTH, sizeof(size_t), + &width, NULL); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query plane %d width: %d.\n", + plane, cle); + return AVERROR_UNKNOWN; + } + + cle = clGetImageInfo(image, CL_IMAGE_HEIGHT, sizeof(size_t), + &height, NULL); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query plane %d height: %d.\n", + plane, cle); + return AVERROR_UNKNOWN; + } + + if (block_alignment) { + width = FFALIGN(width, block_alignment); + height = FFALIGN(height, block_alignment); + } + + work_size[0] = width; + work_size[1] = height; + + return 0; +} diff --git a/libavfilter/opencl.h b/libavfilter/opencl.h index 4d740c18abaec..45fe2a2e27ce6 100644 --- a/libavfilter/opencl.h +++ b/libavfilter/opencl.h @@ -84,4 +84,12 @@ int ff_opencl_filter_load_program(AVFilterContext *avctx, int ff_opencl_filter_load_program_from_file(AVFilterContext *avctx, const char *filename); +/** + * Find the work size needed needed for a given plane of an image. + */ +int ff_opencl_filter_work_size_from_image(AVFilterContext *avctx, + size_t *work_size, + AVFrame *frame, int plane, + int block_alignment); + #endif /* AVFILTER_OPENCL_H */ diff --git a/libavfilter/vf_overlay_opencl.c b/libavfilter/vf_overlay_opencl.c index ee8381dfee2df..16e10f43717c5 100644 --- a/libavfilter/vf_overlay_opencl.c +++ b/libavfilter/vf_overlay_opencl.c @@ -216,8 +216,10 @@ static int overlay_opencl_blend(FFFrameSync *fs) goto fail_kernel_arg; } - global_work[0] = output->width; - global_work[1] = output->height; + err = ff_opencl_filter_work_size_from_image(avctx, global_work, + output, plane, 0); + if (err < 0) + goto fail; cle = clEnqueueNDRangeKernel(ctx->command_queue, ctx->kernel, 2, NULL, global_work, NULL, 0, NULL, NULL); diff --git a/libavfilter/vf_program_opencl.c b/libavfilter/vf_program_opencl.c index 4ee9668236c24..0bcf188ac799b 100644 --- a/libavfilter/vf_program_opencl.c +++ b/libavfilter/vf_program_opencl.c @@ -142,10 +142,10 @@ static int program_opencl_run(AVFilterContext *avctx) } } - cle = clGetImageInfo(dst, CL_IMAGE_WIDTH, sizeof(size_t), - &global_work[0], NULL); - cle = clGetImageInfo(dst, CL_IMAGE_HEIGHT, sizeof(size_t), - &global_work[1], NULL); + err = ff_opencl_filter_work_size_from_image(avctx, global_work, + output, plane, 0); + if (err < 0) + goto fail; av_log(avctx, AV_LOG_DEBUG, "Run kernel on plane %d " "(%zux%zu).\n", plane, global_work[0], global_work[1]); diff --git a/libavfilter/vf_unsharp_opencl.c b/libavfilter/vf_unsharp_opencl.c index 6a453c014bbe8..19c91857cb719 100644 --- a/libavfilter/vf_unsharp_opencl.c +++ b/libavfilter/vf_unsharp_opencl.c @@ -320,15 +320,13 @@ static int unsharp_opencl_filter_frame(AVFilterLink *inlink, AVFrame *input) } } - if (ctx->global) { - global_work[0] = output->width; - global_work[1] = output->height; - } else { - global_work[0] = FFALIGN(output->width, 16); - global_work[1] = FFALIGN(output->height, 16); - local_work[0] = 16; - local_work[1] = 16; - } + err = ff_opencl_filter_work_size_from_image(avctx, global_work, output, p, + ctx->global ? 0 : 16); + if (err < 0) + goto fail; + + local_work[0] = 16; + local_work[1] = 16; av_log(avctx, AV_LOG_DEBUG, "Run kernel on plane %d " "(%"SIZE_SPECIFIER"x%"SIZE_SPECIFIER").\n", From 0568af521ef3eed3e811fb4bebff050b559dbf53 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 19 Mar 2018 22:52:51 +0000 Subject: [PATCH 2207/2557] lavfi/opencl: Avoid deprecation warnings when built with post-1.2 headers The intended target is OpenCL 1.2, so disable warnings for APIs deprecated after that. This primarily applies to clCreateCommandQueue(), we can't use the replacement clCreateCommandQueueWithProperties() because it was introduced in OpenCL 2.0. Also remove some unnecessary includes from overlay and program filters so that the define is available at the right moment. --- libavfilter/opencl.h | 6 ++++++ libavfilter/vf_overlay_opencl.c | 8 +------- libavfilter/vf_program_opencl.c | 6 +----- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/libavfilter/opencl.h b/libavfilter/opencl.h index 45fe2a2e27ce6..c0a45197853bc 100644 --- a/libavfilter/opencl.h +++ b/libavfilter/opencl.h @@ -19,6 +19,12 @@ #ifndef AVFILTER_OPENCL_H #define AVFILTER_OPENCL_H +// The intended target is OpenCL 1.2, so disable warnings for APIs +// deprecated after that. This primarily applies to clCreateCommandQueue(), +// we can't use the replacement clCreateCommandQueueWithProperties() because +// it was introduced in OpenCL 2.0. +#define CL_USE_DEPRECATED_OPENCL_1_2_APIS + #include "libavutil/buffer.h" #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_opencl.h" diff --git a/libavfilter/vf_overlay_opencl.c b/libavfilter/vf_overlay_opencl.c index 16e10f43717c5..b43050df583b1 100644 --- a/libavfilter/vf_overlay_opencl.c +++ b/libavfilter/vf_overlay_opencl.c @@ -16,16 +16,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/avassert.h" -#include "libavutil/buffer.h" -#include "libavutil/common.h" -#include "libavutil/hwcontext.h" -#include "libavutil/hwcontext_opencl.h" #include "libavutil/log.h" -#include "libavutil/mathematics.h" #include "libavutil/mem.h" -#include "libavutil/pixdesc.h" #include "libavutil/opt.h" +#include "libavutil/pixdesc.h" #include "avfilter.h" #include "framesync.h" diff --git a/libavfilter/vf_program_opencl.c b/libavfilter/vf_program_opencl.c index 0bcf188ac799b..a0027923fb2b0 100644 --- a/libavfilter/vf_program_opencl.c +++ b/libavfilter/vf_program_opencl.c @@ -17,14 +17,10 @@ */ #include "libavutil/avstring.h" -#include "libavutil/buffer.h" -#include "libavutil/common.h" -#include "libavutil/hwcontext.h" -#include "libavutil/hwcontext_opencl.h" #include "libavutil/log.h" #include "libavutil/mem.h" -#include "libavutil/pixdesc.h" #include "libavutil/opt.h" +#include "libavutil/pixdesc.h" #include "avfilter.h" #include "framesync.h" From 9313422dfc8d13fdd7d58e9ed04dfff61d26b7f2 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 19 Mar 2018 22:53:11 +0000 Subject: [PATCH 2208/2557] hwcontext_opencl: Avoid deprecation warnings when built with post-1.2 headers Matching the previous commit. This is not applied to the installed header because it could incorrectly suppress the warning inside user programs. --- libavutil/hwcontext_opencl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index a725a491e25f6..f1d9d80f07de1 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define CL_USE_DEPRECATED_OPENCL_1_2_APIS + #include #include "config.h" From 6135c958cd3c8e503ebd59996b7b31b844ac9cb9 Mon Sep 17 00:00:00 2001 From: drfer3 Date: Mon, 19 Mar 2018 13:30:23 +1100 Subject: [PATCH 2209/2557] lavfi: Add OpenCL avgblur filter Behaves like the existing avgblur filter, except working on OpenCL hardware frames. Takes exactly the same options. Signed-off-by: Mark Thompson --- configure | 1 + libavfilter/Makefile | 2 + libavfilter/allfilters.c | 1 + libavfilter/opencl/avgblur.cl | 60 ++++++ libavfilter/opencl_source.h | 1 + libavfilter/vf_avgblur_opencl.c | 328 ++++++++++++++++++++++++++++++++ 6 files changed, 393 insertions(+) create mode 100644 libavfilter/opencl/avgblur.cl create mode 100644 libavfilter/vf_avgblur_opencl.c diff --git a/configure b/configure index 6b27f571c6323..9bcd81438c162 100755 --- a/configure +++ b/configure @@ -3228,6 +3228,7 @@ aresample_filter_deps="swresample" ass_filter_deps="libass" atempo_filter_deps="avcodec" atempo_filter_select="rdft" +avgblur_opencl_filter_deps="opencl" azmq_filter_deps="libzmq" blackframe_filter_deps="gpl" boxblur_filter_deps="gpl" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index fc16512e2c3eb..1043b41d8070a 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -139,6 +139,8 @@ OBJS-$(CONFIG_ALPHAMERGE_FILTER) += vf_alphamerge.o OBJS-$(CONFIG_ASS_FILTER) += vf_subtitles.o OBJS-$(CONFIG_ATADENOISE_FILTER) += vf_atadenoise.o OBJS-$(CONFIG_AVGBLUR_FILTER) += vf_avgblur.o +OBJS-$(CONFIG_AVGBLUR_OPENCL_FILTER) += vf_avgblur_opencl.o opencl.o \ + opencl/avgblur.o OBJS-$(CONFIG_BBOX_FILTER) += bbox.o vf_bbox.o OBJS-$(CONFIG_BENCH_FILTER) += f_bench.o OBJS-$(CONFIG_BITPLANENOISE_FILTER) += vf_bitplanenoise.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index cc423af7381a5..3f67e321bf33f 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -149,6 +149,7 @@ static void register_all(void) REGISTER_FILTER(ASS, ass, vf); REGISTER_FILTER(ATADENOISE, atadenoise, vf); REGISTER_FILTER(AVGBLUR, avgblur, vf); + REGISTER_FILTER(AVGBLUR_OPENCL, avgblur_opencl, vf); REGISTER_FILTER(BBOX, bbox, vf); REGISTER_FILTER(BENCH, bench, vf); REGISTER_FILTER(BITPLANENOISE, bitplanenoise, vf); diff --git a/libavfilter/opencl/avgblur.cl b/libavfilter/opencl/avgblur.cl new file mode 100644 index 0000000000000..6a8d70df93017 --- /dev/null +++ b/libavfilter/opencl/avgblur.cl @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 Dylan Fernando + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +__kernel void avgblur_horiz(__write_only image2d_t dst, + __read_only image2d_t src, + int rad) +{ + const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_NEAREST); + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + int2 size = (int2)(get_global_size(0), get_global_size(1)); + + int count = 0; + float4 acc = (float4)(0,0,0,0); + + for (int xx = max(0, loc.x - rad); xx < min(loc.x + rad + 1, size.x); xx++) { + count++; + acc += read_imagef(src, sampler, (int2)(xx, loc.y)); + } + + write_imagef(dst, loc, acc / count); +} + +__kernel void avgblur_vert(__write_only image2d_t dst, + __read_only image2d_t src, + int radv) +{ + const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_NEAREST); + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + int2 size = (int2)(get_global_size(0), get_global_size(1)); + + int count = 0; + float4 acc = (float4)(0,0,0,0); + + for (int yy = max(0, loc.y - radv); yy < min(loc.y + radv + 1, size.y); yy++) { + count++; + acc += read_imagef(src, sampler, (int2)(loc.x, yy)); + } + + write_imagef(dst, loc, acc / count); +} diff --git a/libavfilter/opencl_source.h b/libavfilter/opencl_source.h index 23cdfc6ac9e37..02bc1723b0925 100644 --- a/libavfilter/opencl_source.h +++ b/libavfilter/opencl_source.h @@ -19,6 +19,7 @@ #ifndef AVFILTER_OPENCL_SOURCE_H #define AVFILTER_OPENCL_SOURCE_H +extern const char *ff_opencl_source_avgblur; extern const char *ff_opencl_source_overlay; extern const char *ff_opencl_source_unsharp; diff --git a/libavfilter/vf_avgblur_opencl.c b/libavfilter/vf_avgblur_opencl.c new file mode 100644 index 0000000000000..5ee66c0ba21a1 --- /dev/null +++ b/libavfilter/vf_avgblur_opencl.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2018 Dylan Fernando + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "internal.h" +#include "opencl.h" +#include "opencl_source.h" +#include "video.h" + + +typedef struct AverageBlurOpenCLContext { + OpenCLFilterContext ocf; + + int initialised; + cl_kernel kernel_horiz; + cl_kernel kernel_vert; + cl_command_queue command_queue; + + int radius; + int radiusV; + int planes; + +} AverageBlurOpenCLContext; + + +static int avgblur_opencl_init(AVFilterContext *avctx) +{ + AverageBlurOpenCLContext *ctx = avctx->priv; + cl_int cle; + int err; + + err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_avgblur, 1); + if (err < 0) + goto fail; + + ctx->command_queue = clCreateCommandQueue(ctx->ocf.hwctx->context, + ctx->ocf.hwctx->device_id, + 0, &cle); + if (!ctx->command_queue) { + av_log(avctx, AV_LOG_ERROR, "Failed to create OpenCL " + "command queue: %d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + + ctx->kernel_horiz = clCreateKernel(ctx->ocf.program,"avgblur_horiz", &cle); + if (!ctx->kernel_horiz) { + av_log(avctx, AV_LOG_ERROR, "Failed to create kernel: %d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + + ctx->kernel_vert = clCreateKernel(ctx->ocf.program,"avgblur_vert", &cle); + if (!ctx->kernel_vert) { + av_log(avctx, AV_LOG_ERROR, "Failed to create kernel: %d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + + if (ctx->radiusV <= 0) { + ctx->radiusV = ctx->radius; + } + + ctx->initialised = 1; + return 0; + +fail: + if (ctx->command_queue) + clReleaseCommandQueue(ctx->command_queue); + if (ctx->kernel_horiz) + clReleaseKernel(ctx->kernel_horiz); + if (ctx->kernel_vert) + clReleaseKernel(ctx->kernel_vert); + return err; +} + +static int avgblur_opencl_filter_frame(AVFilterLink *inlink, AVFrame *input) +{ + AVFilterContext *avctx = inlink->dst; + AVFilterLink *outlink = avctx->outputs[0]; + AverageBlurOpenCLContext *ctx = avctx->priv; + AVFrame *output = NULL; + AVFrame *intermediate = NULL; + cl_int cle; + size_t global_work[2]; + cl_mem src, dst, inter; + int err, p, radius_x, radius_y; + + av_log(ctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(input->format), + input->width, input->height, input->pts); + + if (!input->hw_frames_ctx) + return AVERROR(EINVAL); + + if (!ctx->initialised) { + err = avgblur_opencl_init(avctx); + if (err < 0) + goto fail; + + } + + output = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!output) { + err = AVERROR(ENOMEM); + goto fail; + } + + intermediate = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!intermediate) { + err = AVERROR(ENOMEM); + goto fail; + } + + for (p = 0; p < FF_ARRAY_ELEMS(output->data); p++) { + src = (cl_mem) input->data[p]; + dst = (cl_mem)output->data[p]; + inter = (cl_mem) intermediate->data[p]; + + if (!dst) + break; + + radius_x = ctx->radius; + radius_y = ctx->radiusV; + + if (!(ctx->planes & (1 << p))) { + radius_x = 0; + radius_y = 0; + } + + cle = clSetKernelArg(ctx->kernel_horiz, 0, sizeof(cl_mem), &inter); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "destination image argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel_horiz, 1, sizeof(cl_mem), &src); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "source image argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel_horiz, 2, sizeof(cl_int), &radius_x); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "sizeX argument: %d.\n", cle); + goto fail; + } + + global_work[0] = output->width; + global_work[1] = output->height; + + av_log(avctx, AV_LOG_DEBUG, "Run kernel on plane %d " + "(%"SIZE_SPECIFIER"x%"SIZE_SPECIFIER").\n", + p, global_work[0], global_work[1]); + + cle = clEnqueueNDRangeKernel(ctx->command_queue, ctx->kernel_horiz, 2, NULL, + global_work, NULL, + 0, NULL, NULL); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to enqueue kernel: %d.\n", + cle); + err = AVERROR(EIO); + goto fail; + } + + cle = clSetKernelArg(ctx->kernel_vert, 0, sizeof(cl_mem), &dst); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "destination image argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel_vert, 1, sizeof(cl_mem), &inter); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "source image argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel_vert, 2, sizeof(cl_int), &radius_y); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "sizeY argument: %d.\n", cle); + goto fail; + } + + global_work[0] = output->width; + global_work[1] = output->height; + + av_log(avctx, AV_LOG_DEBUG, "Run kernel on plane %d " + "(%"SIZE_SPECIFIER"x%"SIZE_SPECIFIER").\n", + p, global_work[0], global_work[1]); + + cle = clEnqueueNDRangeKernel(ctx->command_queue, ctx->kernel_vert, 2, NULL, + global_work, NULL, + 0, NULL, NULL); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to enqueue kernel: %d.\n", + cle); + err = AVERROR(EIO); + goto fail; + } + + } + + cle = clFinish(ctx->command_queue); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to finish command queue: %d.\n", + cle); + err = AVERROR(EIO); + goto fail; + } + + err = av_frame_copy_props(output, input); + if (err < 0) + goto fail; + + av_frame_free(&input); + av_frame_free(&intermediate); + + av_log(ctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(output->format), + output->width, output->height, output->pts); + + return ff_filter_frame(outlink, output); + +fail: + clFinish(ctx->command_queue); + av_frame_free(&input); + av_frame_free(&output); + av_frame_free(&intermediate); + return err; +} + +static av_cold void avgblur_opencl_uninit(AVFilterContext *avctx) +{ + AverageBlurOpenCLContext *ctx = avctx->priv; + cl_int cle; + + + if (ctx->kernel_horiz) { + cle = clReleaseKernel(ctx->kernel_horiz); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "kernel: %d.\n", cle); + } + + if (ctx->kernel_vert) { + cle = clReleaseKernel(ctx->kernel_vert); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "kernel: %d.\n", cle); + } + + if (ctx->command_queue) { + cle = clReleaseCommandQueue(ctx->command_queue); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "command queue: %d.\n", cle); + } + + ff_opencl_filter_uninit(avctx); +} + +#define OFFSET(x) offsetof(AverageBlurOpenCLContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption avgblur_opencl_options[] = { + { "sizeX", "set horizontal size", OFFSET(radius), AV_OPT_TYPE_INT, {.i64=1}, 1, 1024, FLAGS }, + { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, FLAGS }, + { "sizeY", "set vertical size", OFFSET(radiusV), AV_OPT_TYPE_INT, {.i64=0}, 0, 1024, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(avgblur_opencl); + +static const AVFilterPad avgblur_opencl_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &avgblur_opencl_filter_frame, + .config_props = &ff_opencl_filter_config_input, + }, + { NULL } +}; + +static const AVFilterPad avgblur_opencl_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_opencl_filter_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_avgblur_opencl = { + .name = "avgblur_opencl", + .description = NULL_IF_CONFIG_SMALL("Apply average blur filter"), + .priv_size = sizeof(AverageBlurOpenCLContext), + .priv_class = &avgblur_opencl_class, + .init = &ff_opencl_filter_init, + .uninit = &avgblur_opencl_uninit, + .query_formats = &ff_opencl_filter_query_formats, + .inputs = avgblur_opencl_inputs, + .outputs = avgblur_opencl_outputs, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From f86e8c91d020d05c584d53d7033fe6d05a16aef1 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 21 Mar 2018 21:13:16 +0000 Subject: [PATCH 2210/2557] hwcontext_drm: Clarify value for unknown format modifiers --- libavutil/hwcontext_drm.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h index 2e225451e1158..42709f215ef9a 100644 --- a/libavutil/hwcontext_drm.h +++ b/libavutil/hwcontext_drm.h @@ -58,6 +58,9 @@ typedef struct AVDRMObjectDescriptor { size_t size; /** * Format modifier applied to the object (DRM_FORMAT_MOD_*). + * + * If the format modifier is unknown then this should be set to + * DRM_FORMAT_MOD_INVALID. */ uint64_t format_modifier; } AVDRMObjectDescriptor; From c6bbb8cca7fa72bb26d2000453460a6344f425a1 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Mar 2018 21:12:29 +0000 Subject: [PATCH 2211/2557] hwcontext_vaapi: Add support for legacy DRM mapping The old vaAcquireBufferHandle() API works in fewer cases and provides less information than the current vaExportSurfaceHandle(), but it exists on older versions and is already used by the OpenCL code. --- libavutil/hwcontext_vaapi.c | 194 +++++++++++++++++++++++++++++++++--- 1 file changed, 182 insertions(+), 12 deletions(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 3797005433a62..998e954c44fab 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -28,6 +28,9 @@ #if CONFIG_LIBDRM # include # include +# ifndef DRM_FORMAT_MOD_INVALID +# define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1) +# endif #endif #include @@ -1071,8 +1074,9 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, return 0; } -static void vaapi_unmap_to_drm(AVHWFramesContext *dst_fc, - HWMapDescriptor *hwmap) +#if VA_CHECK_VERSION(1, 1, 0) +static void vaapi_unmap_to_drm_esh(AVHWFramesContext *hwfc, + HWMapDescriptor *hwmap) { AVDRMFrameDescriptor *drm_desc = hwmap->priv; int i; @@ -1083,10 +1087,9 @@ static void vaapi_unmap_to_drm(AVHWFramesContext *dst_fc, av_freep(&drm_desc); } -static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, - const AVFrame *src, int flags) +static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) { -#if VA_CHECK_VERSION(1, 1, 0) AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; VASurfaceID surface_id; VAStatus vas; @@ -1138,7 +1141,7 @@ static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, } err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, - &vaapi_unmap_to_drm, drm_desc); + &vaapi_unmap_to_drm_esh, drm_desc); if (err < 0) goto fail; @@ -1153,15 +1156,182 @@ static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, close(va_desc.objects[i].fd); av_freep(&drm_desc); return err; -#else - // Older versions without vaExportSurfaceHandle() are not supported - - // in theory this is possible with a combination of vaDeriveImage() - // and vaAcquireBufferHandle(), but it doesn't carry enough metadata - // to actually use the result in a generic way. - return AVERROR(ENOSYS); +} #endif + +typedef struct VAAPIDRMImageBufferMapping { + VAImage image; + VABufferInfo buffer_info; + + AVDRMFrameDescriptor drm_desc; +} VAAPIDRMImageBufferMapping; + +static void vaapi_unmap_to_drm_abh(AVHWFramesContext *hwfc, + HWMapDescriptor *hwmap) +{ + AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; + VAAPIDRMImageBufferMapping *mapping = hwmap->priv; + VASurfaceID surface_id; + VAStatus vas; + + surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3]; + av_log(hwfc, AV_LOG_DEBUG, "Unmap VAAPI surface %#x from DRM.\n", + surface_id); + + // DRM PRIME file descriptors are closed by vaReleaseBufferHandle(), + // so we shouldn't close them separately. + + vas = vaReleaseBufferHandle(hwctx->display, mapping->image.buf); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to release buffer " + "handle of image %#x (derived from surface %#x): " + "%d (%s).\n", mapping->image.buf, surface_id, + vas, vaErrorStr(vas)); + } + + vas = vaDestroyImage(hwctx->display, mapping->image.image_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image " + "derived from surface %#x: %d (%s).\n", + surface_id, vas, vaErrorStr(vas)); + } + + av_free(mapping); } + +static int vaapi_map_to_drm_abh(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ + AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; + VAAPIDRMImageBufferMapping *mapping = NULL; + VASurfaceID surface_id; + VAStatus vas; + int err, i, p; + + surface_id = (VASurfaceID)(uintptr_t)src->data[3]; + av_log(hwfc, AV_LOG_DEBUG, "Map VAAPI surface %#x to DRM.\n", + surface_id); + + mapping = av_mallocz(sizeof(*mapping)); + if (!mapping) + return AVERROR(ENOMEM); + + vas = vaDeriveImage(hwctx->display, surface_id, + &mapping->image); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from " + "surface %#x: %d (%s).\n", + surface_id, vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) { + if (vaapi_drm_format_map[i].va_fourcc == + mapping->image.format.fourcc) + break; + } + if (i >= FF_ARRAY_ELEMS(vaapi_drm_format_map)) { + av_log(hwfc, AV_LOG_ERROR, "No matching DRM format for " + "VAAPI format %#x.\n", mapping->image.format.fourcc); + err = AVERROR(EINVAL); + goto fail_derived; + } + + mapping->buffer_info.mem_type = + VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; + + mapping->drm_desc.nb_layers = + vaapi_drm_format_map[i].nb_layer_formats; + if (mapping->drm_desc.nb_layers > 1) { + if (mapping->drm_desc.nb_layers != mapping->image.num_planes) { + av_log(hwfc, AV_LOG_ERROR, "Image properties do not match " + "expected format: got %d planes, but expected %d.\n", + mapping->image.num_planes, mapping->drm_desc.nb_layers); + err = AVERROR(EINVAL); + goto fail_derived; + } + + for(p = 0; p < mapping->drm_desc.nb_layers; p++) { + mapping->drm_desc.layers[p] = (AVDRMLayerDescriptor) { + .format = vaapi_drm_format_map[i].layer_formats[p], + .nb_planes = 1, + .planes[0] = { + .object_index = 0, + .offset = mapping->image.offsets[p], + .pitch = mapping->image.pitches[p], + }, + }; + } + } else { + mapping->drm_desc.layers[0].format = + vaapi_drm_format_map[i].layer_formats[0]; + mapping->drm_desc.layers[0].nb_planes = mapping->image.num_planes; + for (p = 0; p < mapping->image.num_planes; p++) { + mapping->drm_desc.layers[0].planes[p] = (AVDRMPlaneDescriptor) { + .object_index = 0, + .offset = mapping->image.offsets[p], + .pitch = mapping->image.pitches[p], + }; + } + } + + vas = vaAcquireBufferHandle(hwctx->display, mapping->image.buf, + &mapping->buffer_info); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to get buffer " + "handle from image %#x (derived from surface %#x): " + "%d (%s).\n", mapping->image.buf, surface_id, + vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail_derived; + } + + av_log(hwfc, AV_LOG_DEBUG, "DRM PRIME fd is %ld.\n", + mapping->buffer_info.handle); + + mapping->drm_desc.nb_objects = 1; + mapping->drm_desc.objects[0] = (AVDRMObjectDescriptor) { + .fd = mapping->buffer_info.handle, + .size = mapping->image.data_size, + // There is no way to get the format modifier with this API. + .format_modifier = DRM_FORMAT_MOD_INVALID, + }; + + err = ff_hwframe_map_create(src->hw_frames_ctx, + dst, src, &vaapi_unmap_to_drm_abh, + mapping); + if (err < 0) + goto fail_mapped; + + dst->data[0] = (uint8_t*)&mapping->drm_desc; + dst->width = src->width; + dst->height = src->height; + + return 0; + +fail_mapped: + vaReleaseBufferHandle(hwctx->display, mapping->image.buf); +fail_derived: + vaDestroyImage(hwctx->display, mapping->image.image_id); +fail: + av_freep(&mapping); + return err; +} + +static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ +#if VA_CHECK_VERSION(1, 1, 0) + int err; + err = vaapi_map_to_drm_esh(hwfc, dst, src, flags); + if (err != AVERROR(ENOSYS)) + return err; #endif + return vaapi_map_to_drm_abh(hwfc, dst, src, flags); +} + +#endif /* CONFIG_LIBDRM */ static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) From ca9f13bbce4836f44fbc18bb30a350fea4075e08 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Mar 2018 21:25:46 +0000 Subject: [PATCH 2212/2557] hwcontext_vaapi: Pass correct read/write flags when exporting surfaces --- libavutil/hwcontext_vaapi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 998e954c44fab..53a5b02822efd 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -1095,15 +1095,20 @@ static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst, VAStatus vas; VADRMPRIMESurfaceDescriptor va_desc; AVDRMFrameDescriptor *drm_desc = NULL; + uint32_t export_flags; int err, i, j; surface_id = (VASurfaceID)(uintptr_t)src->data[3]; + export_flags = VA_EXPORT_SURFACE_SEPARATE_LAYERS; + if (flags & AV_HWFRAME_MAP_READ) + export_flags |= VA_EXPORT_SURFACE_READ_ONLY; + if (flags & AV_HWFRAME_MAP_WRITE) + export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY; + vas = vaExportSurfaceHandle(hwctx->display, surface_id, VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, - VA_EXPORT_SURFACE_READ_ONLY | - VA_EXPORT_SURFACE_SEPARATE_LAYERS, - &va_desc); + export_flags, &va_desc); if (vas != VA_STATUS_SUCCESS) { if (vas == VA_STATUS_ERROR_UNIMPLEMENTED) return AVERROR(ENOSYS); From ac993e73decab3dd5828b37bb1d5d8514c0d247a Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 11 Mar 2018 21:19:20 +0000 Subject: [PATCH 2213/2557] hwcontext_opencl: Add support for mapping DRM objects to Beignet Also use that to support mapping VAAPI to Beignet. --- configure | 16 ++- libavutil/hwcontext_opencl.c | 265 +++++++++++++++++------------------ 2 files changed, 139 insertions(+), 142 deletions(-) diff --git a/configure b/configure index 9bcd81438c162..cc3edeb80f0a1 100755 --- a/configure +++ b/configure @@ -2156,6 +2156,7 @@ HAVE_LIST=" makeinfo_html opencl_d3d11 opencl_drm_arm + opencl_drm_beignet opencl_dxva2 opencl_vaapi_beignet opencl_vaapi_intel_media @@ -6241,9 +6242,15 @@ enabled vaapi && enabled vaapi && check_cpp_condition vaapi_1 "va/va.h" "VA_CHECK_VERSION(1, 0, 0)" -if enabled_all opencl vaapi ; then +if enabled_all opencl libdrm ; then check_type "CL/cl_intel.h" "clCreateImageFromFdINTEL_fn" && - enable opencl_vaapi_beignet + enable opencl_drm_beignet + check_func_headers "CL/cl_ext.h" clImportMemoryARM && + enable opencl_drm_arm +fi + +if enabled_all opencl vaapi ; then + enabled opencl_drm_beignet && enable opencl_vaapi_beignet if enabled libmfx ; then check_type "CL/cl.h CL/va_ext.h" "clCreateFromVA_APIMediaSurfaceINTEL_fn" && enable opencl_vaapi_intel_media @@ -6260,11 +6267,6 @@ if enabled_all opencl d3d11va ; then enable opencl_d3d11 fi -if enabled_all opencl libdrm ; then - check_func_headers "CL/cl_ext.h" clImportMemoryARM && - enable opencl_drm_arm -fi - enabled vdpau && check_cpp_condition vdpau vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index f1d9d80f07de1..43b5c5ae0cbd1 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -39,6 +39,12 @@ #include "hwcontext_vaapi.h" #endif +#if HAVE_OPENCL_DRM_BEIGNET +#include +#include +#include "hwcontext_drm.h" +#endif + #if HAVE_OPENCL_VAAPI_INTEL_MEDIA #include #include @@ -76,9 +82,9 @@ typedef struct OpenCLDeviceContext { cl_platform_id platform_id; // Platform/device-specific functions. -#if HAVE_OPENCL_VAAPI_BEIGNET - int vaapi_mapping_usable; - clCreateImageFromFdINTEL_fn clCreateImageFromFdINTEL; +#if HAVE_OPENCL_DRM_BEIGNET + int beignet_drm_mapping_usable; + clCreateImageFromFdINTEL_fn clCreateImageFromFdINTEL; #endif #if HAVE_OPENCL_VAAPI_INTEL_MEDIA @@ -687,19 +693,19 @@ static int opencl_device_init(AVHWDeviceContext *hwdev) } \ } while (0) -#if HAVE_OPENCL_VAAPI_BEIGNET +#if HAVE_OPENCL_DRM_BEIGNET { int fail = 0; CL_FUNC(clCreateImageFromFdINTEL, - "Intel DRM to OpenCL image mapping"); + "Beignet DRM to OpenCL image mapping"); if (fail) { - av_log(hwdev, AV_LOG_WARNING, "VAAPI to OpenCL mapping " - "not usable.\n"); - priv->vaapi_mapping_usable = 0; + av_log(hwdev, AV_LOG_WARNING, "Beignet DRM to OpenCL " + "mapping not usable.\n"); + priv->beignet_drm_mapping_usable = 0; } else { - priv->vaapi_mapping_usable = 1; + priv->beignet_drm_mapping_usable = 1; } } #endif @@ -1189,7 +1195,8 @@ static int opencl_device_derive(AVHWDeviceContext *hwdev, int err; switch (src_ctx->type) { -#if HAVE_OPENCL_VAAPI_BEIGNET +#if HAVE_OPENCL_DRM_BEIGNET + case AV_HWDEVICE_TYPE_DRM: case AV_HWDEVICE_TYPE_VAAPI: { // Surface mapping works via DRM PRIME fds with no special @@ -2030,175 +2037,152 @@ static int opencl_map_frame(AVHWFramesContext *hwfc, AVFrame *dst, return err; } -#if HAVE_OPENCL_VAAPI_BEIGNET +#if HAVE_OPENCL_DRM_BEIGNET -typedef struct VAAPItoOpenCLMapping { - VAImage va_image; - VABufferInfo va_buffer_info; +typedef struct DRMBeignetToOpenCLMapping { + AVFrame *drm_frame; + AVDRMFrameDescriptor *drm_desc; AVOpenCLFrameDescriptor frame; -} VAAPItoOpenCLMapping; +} DRMBeignetToOpenCLMapping; -static void opencl_unmap_from_vaapi(AVHWFramesContext *src_fc, - HWMapDescriptor *hwmap) +static void opencl_unmap_from_drm_beignet(AVHWFramesContext *dst_fc, + HWMapDescriptor *hwmap) { - VAAPItoOpenCLMapping *mapping = hwmap->priv; - AVVAAPIDeviceContext *src_dev = src_fc->device_ctx->hwctx; - VASurfaceID surface_id; - VAStatus vas; + DRMBeignetToOpenCLMapping *mapping = hwmap->priv; cl_int cle; int i; - surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3]; - av_log(src_fc, AV_LOG_DEBUG, "Unmap VAAPI surface %#x from OpenCL.\n", - surface_id); - for (i = 0; i < mapping->frame.nb_planes; i++) { cle = clReleaseMemObject(mapping->frame.planes[i]); if (cle != CL_SUCCESS) { - av_log(src_fc, AV_LOG_ERROR, "Failed to release CL " - "buffer of plane %d of VA image %#x (derived " - "from surface %#x): %d.\n", i, - mapping->va_image.buf, surface_id, cle); + av_log(dst_fc, AV_LOG_ERROR, "Failed to release CL image " + "of plane %d of DRM frame: %d.\n", i, cle); } } - vas = vaReleaseBufferHandle(src_dev->display, - mapping->va_image.buf); - if (vas != VA_STATUS_SUCCESS) { - av_log(src_fc, AV_LOG_ERROR, "Failed to release buffer " - "handle of image %#x (derived from surface %#x): " - "%d (%s).\n", mapping->va_image.buf, surface_id, - vas, vaErrorStr(vas)); - } - - vas = vaDestroyImage(src_dev->display, - mapping->va_image.image_id); - if (vas != VA_STATUS_SUCCESS) { - av_log(src_fc, AV_LOG_ERROR, "Failed to destroy image " - "derived from surface %#x: %d (%s).\n", - surface_id, vas, vaErrorStr(vas)); - } - av_free(mapping); } -static int opencl_map_from_vaapi(AVHWFramesContext *dst_fc, AVFrame *dst, - const AVFrame *src, int flags) +static int opencl_map_from_drm_beignet(AVHWFramesContext *dst_fc, + AVFrame *dst, const AVFrame *src, + int flags) { - AVHWFramesContext *src_fc = - (AVHWFramesContext*)src->hw_frames_ctx->data; - AVVAAPIDeviceContext *src_dev = src_fc->device_ctx->hwctx; - AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; - OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv; - VAAPItoOpenCLMapping *mapping = NULL; - VASurfaceID surface_id; - VAStatus vas; + AVOpenCLDeviceContext *hwctx = dst_fc->device_ctx->hwctx; + OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv; + DRMBeignetToOpenCLMapping *mapping; + const AVDRMFrameDescriptor *desc; cl_int cle; - int err, p; + int err, i, j, p; - surface_id = (VASurfaceID)(uintptr_t)src->data[3]; - av_log(src_fc, AV_LOG_DEBUG, "Map VAAPI surface %#x to OpenCL.\n", - surface_id); + desc = (const AVDRMFrameDescriptor*)src->data[0]; mapping = av_mallocz(sizeof(*mapping)); if (!mapping) return AVERROR(ENOMEM); - vas = vaDeriveImage(src_dev->display, surface_id, - &mapping->va_image); - if (vas != VA_STATUS_SUCCESS) { - av_log(src_fc, AV_LOG_ERROR, "Failed to derive image from " - "surface %#x: %d (%s).\n", - surface_id, vas, vaErrorStr(vas)); - err = AVERROR(EIO); - goto fail; - } - - mapping->va_buffer_info.mem_type = - VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; - - vas = vaAcquireBufferHandle(src_dev->display, - mapping->va_image.buf, - &mapping->va_buffer_info); - if (vas != VA_STATUS_SUCCESS) { - av_log(src_fc, AV_LOG_ERROR, "Failed to get buffer " - "handle from image %#x (derived from surface %#x): " - "%d (%s).\n", mapping->va_image.buf, surface_id, - vas, vaErrorStr(vas)); - vaDestroyImage(src_dev->display, mapping->va_image.buf); - err = AVERROR(EIO); - goto fail_derived; - } - - av_log(dst_fc, AV_LOG_DEBUG, "DRM PRIME fd is %ld.\n", - mapping->va_buffer_info.handle); + p = 0; + for (i = 0; i < desc->nb_layers; i++) { + const AVDRMLayerDescriptor *layer = &desc->layers[i]; + for (j = 0; j < layer->nb_planes; j++) { + const AVDRMPlaneDescriptor *plane = &layer->planes[j]; + const AVDRMObjectDescriptor *object = + &desc->objects[plane->object_index]; + + cl_import_image_info_intel image_info = { + .fd = object->fd, + .size = object->size, + .type = CL_MEM_OBJECT_IMAGE2D, + .offset = plane->offset, + .row_pitch = plane->pitch, + }; + cl_image_desc image_desc; - mapping->frame.nb_planes = mapping->va_image.num_planes; - for (p = 0; p < mapping->frame.nb_planes; p++) { - cl_import_image_info_intel image_info = { - .fd = mapping->va_buffer_info.handle, - .size = mapping->va_buffer_info.mem_size, - .type = CL_MEM_OBJECT_IMAGE2D, - .offset = mapping->va_image.offsets[p], - .row_pitch = mapping->va_image.pitches[p], - }; - cl_image_desc image_desc; + err = opencl_get_plane_format(dst_fc->sw_format, p, + src->width, src->height, + &image_info.fmt, + &image_desc); + if (err < 0) { + av_log(dst_fc, AV_LOG_ERROR, "DRM frame layer %d " + "plane %d is not representable in OpenCL: %d.\n", + i, j, err); + goto fail; + } + image_info.width = image_desc.image_width; + image_info.height = image_desc.image_height; + + mapping->frame.planes[p] = + priv->clCreateImageFromFdINTEL(hwctx->context, + &image_info, &cle); + if (!mapping->frame.planes[p]) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL image " + "from layer %d plane %d of DRM frame: %d.\n", + i, j, cle); + err = AVERROR(EIO); + goto fail; + } - err = opencl_get_plane_format(src_fc->sw_format, p, - mapping->va_image.width, - mapping->va_image.height, - &image_info.fmt, - &image_desc); - if (err < 0) { - av_log(dst_fc, AV_LOG_ERROR, "VA %#x (derived from " - "surface %#x) has invalid parameters: %d.\n", - mapping->va_image.buf, surface_id, err); - goto fail_mapped; + dst->data[p] = (uint8_t*)mapping->frame.planes[p]; + mapping->frame.nb_planes = ++p; } - image_info.width = image_desc.image_width; - image_info.height = image_desc.image_height; - - mapping->frame.planes[p] = - priv->clCreateImageFromFdINTEL(dst_dev->context, - &image_info, &cle); - if (!mapping->frame.planes[p]) { - av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL image " - "from plane %d of VA image %#x (derived from " - "surface %#x): %d.\n", p, - mapping->va_image.buf, surface_id, cle); - err = AVERROR(EIO); - goto fail_mapped; - } - - dst->data[p] = (uint8_t*)mapping->frame.planes[p]; } - err = ff_hwframe_map_create(src->hw_frames_ctx, - dst, src, &opencl_unmap_from_vaapi, + err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, + &opencl_unmap_from_drm_beignet, mapping); if (err < 0) - goto fail_mapped; + goto fail; dst->width = src->width; dst->height = src->height; return 0; -fail_mapped: +fail: for (p = 0; p < mapping->frame.nb_planes; p++) { if (mapping->frame.planes[p]) clReleaseMemObject(mapping->frame.planes[p]); } - vaReleaseBufferHandle(src_dev->display, mapping->va_image.buf); -fail_derived: - vaDestroyImage(src_dev->display, mapping->va_image.image_id); + av_free(mapping); + return err; +} + +#if HAVE_OPENCL_VAAPI_BEIGNET + +static int opencl_map_from_vaapi(AVHWFramesContext *dst_fc, + AVFrame *dst, const AVFrame *src, + int flags) +{ + HWMapDescriptor *hwmap; + AVFrame *tmp; + int err; + + tmp = av_frame_alloc(); + if (!tmp) + return AVERROR(ENOMEM); + + tmp->format = AV_PIX_FMT_DRM_PRIME; + + err = av_hwframe_map(tmp, src, flags); + if (err < 0) + goto fail; + + err = opencl_map_from_drm_beignet(dst_fc, dst, tmp, flags); + if (err < 0) + goto fail; + + // Adjust the map descriptor so that unmap works correctly. + hwmap = (HWMapDescriptor*)dst->buf[0]->data; + av_frame_unref(hwmap->source); + err = av_frame_ref(hwmap->source, src); + fail: - av_freep(&mapping); + av_frame_free(&tmp); return err; } -#endif +#endif /* HAVE_OPENCL_VAAPI_BEIGNET */ +#endif /* HAVE_OPENCL_DRM_BEIGNET */ static inline cl_mem_flags opencl_mem_flags_for_mapping(int map_flags) { @@ -2828,9 +2812,14 @@ static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst, OpenCLDeviceContext *priv = hwfc->device_ctx->internal->priv; av_assert0(dst->format == AV_PIX_FMT_OPENCL); switch (src->format) { +#if HAVE_OPENCL_DRM_BEIGNET + case AV_PIX_FMT_DRM_PRIME: + if (priv->beignet_drm_mapping_usable) + return opencl_map_from_drm_beignet(hwfc, dst, src, flags); +#endif #if HAVE_OPENCL_VAAPI_BEIGNET case AV_PIX_FMT_VAAPI: - if (priv->vaapi_mapping_usable) + if (priv->beignet_drm_mapping_usable) return opencl_map_from_vaapi(hwfc, dst, src, flags); #endif #if HAVE_OPENCL_VAAPI_INTEL_MEDIA @@ -2863,9 +2852,15 @@ static int opencl_frames_derive_to(AVHWFramesContext *dst_fc, { OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv; switch (src_fc->device_ctx->type) { +#if HAVE_OPENCL_DRM_BEIGNET + case AV_HWDEVICE_TYPE_DRM: + if (!priv->beignet_drm_mapping_usable) + return AVERROR(ENOSYS); + break; +#endif #if HAVE_OPENCL_VAAPI_BEIGNET case AV_HWDEVICE_TYPE_VAAPI: - if (!priv->vaapi_mapping_usable) + if (!priv->beignet_drm_mapping_usable) return AVERROR(ENOSYS); break; #endif From abf35afb6f70f2b1fdf99ce48112ad314bd8ca0f Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 14 Feb 2018 21:48:44 +0000 Subject: [PATCH 2214/2557] vf_scale_vaapi: Apply cropping rectangle to input --- libavfilter/vf_scale_vaapi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c index c19e23ccd0201..d6529d5235a66 100644 --- a/libavfilter/vf_scale_vaapi.c +++ b/libavfilter/vf_scale_vaapi.c @@ -100,13 +100,13 @@ static int scale_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) memset(¶ms, 0, sizeof(params)); - // If there were top/left cropping, it could be taken into - // account here. input_region = (VARectangle) { - .x = 0, - .y = 0, - .width = input_frame->width, - .height = input_frame->height, + .x = input_frame->crop_left, + .y = input_frame->crop_top, + .width = input_frame->width - + (input_frame->crop_left + input_frame->crop_right), + .height = input_frame->height - + (input_frame->crop_top + input_frame->crop_bottom), }; params.surface = input_surface; From 4e1307c0f76d015941a1217bcd44a20f25e04fad Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 20 Mar 2018 18:02:26 +0100 Subject: [PATCH 2215/2557] avfilter/af_channelsplit: add channels option So user can pick which channels to extract. Signed-off-by: Paul B Mahol --- doc/filters.texi | 18 ++++++++++++++++ libavfilter/af_channelsplit.c | 39 +++++++++++++++++++++++++++++------ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index d6ea56b851717..870c50441b5cd 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2208,8 +2208,17 @@ It accepts the following parameters: @table @option @item channel_layout The channel layout of the input stream. The default is "stereo". +@item channels +A channel layout describing the channels to be extracted as separate output streams +or "all" to extract each input channel as a separate stream. The default is "all". + +Choosing channels not present in channel layout in the input will result in an error. @end table +@subsection Examples + +@itemize +@item For example, assuming a stereo input MP3 file, @example ffmpeg -i in.mp3 -filter_complex channelsplit out.mkv @@ -2217,6 +2226,7 @@ ffmpeg -i in.mp3 -filter_complex channelsplit out.mkv will create an output Matroska file with two audio streams, one containing only the left channel and the other the right channel. +@item Split a 5.1 WAV file into per-channel files: @example ffmpeg -i in.wav -filter_complex @@ -2226,6 +2236,14 @@ front_center.wav -map '[LFE]' lfe.wav -map '[SL]' side_left.wav -map '[SR]' side_right.wav @end example +@item +Extract only LFE from a 5.1 WAV file: +@example +ffmpeg -i in.wav -filter_complex 'channelsplit=channel_layout=5.1:channels=LFE[LFE]' +-map '[LFE]' lfe.wav +@end example +@end itemize + @section chorus Add a chorus effect to the audio. diff --git a/libavfilter/af_channelsplit.c b/libavfilter/af_channelsplit.c index 8c6b00fe4f507..821bb73801414 100644 --- a/libavfilter/af_channelsplit.c +++ b/libavfilter/af_channelsplit.c @@ -38,6 +38,9 @@ typedef struct ChannelSplitContext { uint64_t channel_layout; char *channel_layout_str; + char *channels_str; + + int map[64]; } ChannelSplitContext; #define OFFSET(x) offsetof(ChannelSplitContext, x) @@ -45,6 +48,7 @@ typedef struct ChannelSplitContext { #define F AV_OPT_FLAG_FILTERING_PARAM static const AVOption channelsplit_options[] = { { "channel_layout", "Input channel layout.", OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, { .str = "stereo" }, .flags = A|F }, + { "channels", "Channels to extract.", OFFSET(channels_str), AV_OPT_TYPE_STRING, { .str = "all" }, .flags = A|F }, { NULL } }; @@ -53,8 +57,9 @@ AVFILTER_DEFINE_CLASS(channelsplit); static av_cold int init(AVFilterContext *ctx) { ChannelSplitContext *s = ctx->priv; + uint64_t channel_layout; int nb_channels; - int ret = 0, i; + int all = 0, ret = 0, i; if (!(s->channel_layout = av_get_channel_layout(s->channel_layout_str))) { av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout '%s'.\n", @@ -63,14 +68,35 @@ static av_cold int init(AVFilterContext *ctx) goto fail; } - nb_channels = av_get_channel_layout_nb_channels(s->channel_layout); + + if (!strcmp(s->channels_str, "all")) { + nb_channels = av_get_channel_layout_nb_channels(s->channel_layout); + channel_layout = s->channel_layout; + all = 1; + } else { + if ((ret = av_get_extended_channel_layout(s->channels_str, &channel_layout, &nb_channels)) < 0) + return ret; + } + for (i = 0; i < nb_channels; i++) { - uint64_t channel = av_channel_layout_extract_channel(s->channel_layout, i); + uint64_t channel = av_channel_layout_extract_channel(channel_layout, i); AVFilterPad pad = { 0 }; pad.type = AVMEDIA_TYPE_AUDIO; pad.name = av_get_channel_name(channel); + if (all) { + s->map[i] = i; + } else { + if ((ret = av_get_channel_layout_channel_index(s->channel_layout, channel)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Channel name '%s' not present in channel layout '%s'.\n", + av_get_channel_name(channel), s->channel_layout_str); + return ret; + } + + s->map[i] = ret; + } + if ((ret = ff_insert_outpad(ctx, i, &pad)) < 0) { return ret; } @@ -96,7 +122,7 @@ static int query_formats(AVFilterContext *ctx) for (i = 0; i < ctx->nb_outputs; i++) { AVFilterChannelLayouts *out_layouts = NULL; - uint64_t channel = av_channel_layout_extract_channel(s->channel_layout, i); + uint64_t channel = av_channel_layout_extract_channel(s->channel_layout, s->map[i]); if ((ret = ff_add_channel_layout(&out_layouts, channel)) < 0 || (ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->in_channel_layouts)) < 0) @@ -109,6 +135,7 @@ static int query_formats(AVFilterContext *ctx) static int filter_frame(AVFilterLink *inlink, AVFrame *buf) { AVFilterContext *ctx = inlink->dst; + ChannelSplitContext *s = ctx->priv; int i, ret = 0; for (i = 0; i < ctx->nb_outputs; i++) { @@ -119,9 +146,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) break; } - buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[i]; + buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[s->map[i]]; buf_out->channel_layout = - av_channel_layout_extract_channel(buf->channel_layout, i); + av_channel_layout_extract_channel(buf->channel_layout, s->map[i]); buf_out->channels = 1; ret = ff_filter_frame(ctx->outputs[i], buf_out); From fe0fdc51b56e061ee00ef237c218e18b99468878 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 23 Mar 2018 16:21:38 +0100 Subject: [PATCH 2216/2557] avfilter/vf_convolution: disable fast path if rdiv/bias are different from defaults Signed-off-by: Paul B Mahol --- libavfilter/vf_convolution.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavfilter/vf_convolution.c b/libavfilter/vf_convolution.c index d7f8bf8a65102..ce09e338cc5b1 100644 --- a/libavfilter/vf_convolution.c +++ b/libavfilter/vf_convolution.c @@ -997,6 +997,9 @@ static av_cold int init(AVFilterContext *ctx) } else { return AVERROR(EINVAL); } + + if (s->copy[i] && (s->rdiv[i] != 1. || s->bias[i] != 0.)) + s->copy[i] = 0; } } else if (!strcmp(ctx->filter->name, "prewitt")) { for (i = 0; i < 4; i++) { From a8c2d375ca68b7f001564ced14d8ac0757f53a29 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 23 Mar 2018 19:02:51 +0100 Subject: [PATCH 2217/2557] avfilter/avf_showwaves: add draw mode which controls how single sample is drawn Signed-off-by: Paul B Mahol --- doc/filters.texi | 14 +++++ libavfilter/avf_showwaves.c | 119 ++++++++++++++++++++++++++++++------ 2 files changed, 115 insertions(+), 18 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 870c50441b5cd..421b5f6cd215a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -20033,6 +20033,20 @@ Cubic root. @end table Default is linear. + +@item draw +Set the draw mode. This is mostly useful to set for high @var{n}. + +Available values are: +@table @samp +@item scale +Scale pixel values for each drawn sample. + +@item full +Draw every sample directly. +@end table + +Default vlaue is @code{scale}. @end table @subsection Examples diff --git a/libavfilter/avf_showwaves.c b/libavfilter/avf_showwaves.c index 0866967984673..bb7f4ea87e046 100644 --- a/libavfilter/avf_showwaves.c +++ b/libavfilter/avf_showwaves.c @@ -50,6 +50,12 @@ enum ShowWavesScale { SCALE_NB, }; +enum ShowWavesDrawMode { + DRAW_SCALE, + DRAW_FULL, + DRAW_NB, +}; + struct frame_node { AVFrame *frame; struct frame_node *next; @@ -68,6 +74,7 @@ typedef struct ShowWavesContext { int sample_count_mod; int mode; ///< ShowWavesMode int scale; ///< ShowWavesScale + int draw_mode; ///< ShowWavesDrawMode int split_channels; uint8_t *fg; @@ -104,6 +111,9 @@ static const AVOption showwaves_options[] = { { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=SCALE_LOG}, .flags=FLAGS, .unit="scale"}, { "sqrt", "square root", 0, AV_OPT_TYPE_CONST, {.i64=SCALE_SQRT}, .flags=FLAGS, .unit="scale"}, { "cbrt", "cubic root", 0, AV_OPT_TYPE_CONST, {.i64=SCALE_CBRT}, .flags=FLAGS, .unit="scale"}, + { "draw", "set draw mode", OFFSET(draw_mode), AV_OPT_TYPE_INT, {.i64 = DRAW_SCALE}, 0, DRAW_NB-1, FLAGS, .unit="draw" }, + { "scale", "scale pixel values for each drawn sample", 0, AV_OPT_TYPE_CONST, {.i64=DRAW_SCALE}, .flags=FLAGS, .unit="draw"}, + { "full", "draw every pixel for sample directly", 0, AV_OPT_TYPE_CONST, {.i64=DRAW_FULL}, .flags=FLAGS, .unit="draw"}, { NULL } }; @@ -202,9 +212,9 @@ static int get_cbrt_h2(int16_t sample, int height) return cbrt(FFABS(sample)) * height / cbrt(INT16_MAX); } -static void draw_sample_point_rgba(uint8_t *buf, int height, int linesize, - int16_t *prev_y, - const uint8_t color[4], int h) +static void draw_sample_point_rgba_scale(uint8_t *buf, int height, int linesize, + int16_t *prev_y, + const uint8_t color[4], int h) { if (h >= 0 && h < height) { buf[h * linesize + 0] += color[0]; @@ -214,9 +224,21 @@ static void draw_sample_point_rgba(uint8_t *buf, int height, int linesize, } } -static void draw_sample_line_rgba(uint8_t *buf, int height, int linesize, - int16_t *prev_y, - const uint8_t color[4], int h) +static void draw_sample_point_rgba_full(uint8_t *buf, int height, int linesize, + int16_t *prev_y, + const uint8_t color[4], int h) +{ + if (h >= 0 && h < height) { + buf[h * linesize + 0] = color[0]; + buf[h * linesize + 1] = color[1]; + buf[h * linesize + 2] = color[2]; + buf[h * linesize + 3] = color[3]; + } +} + +static void draw_sample_line_rgba_scale(uint8_t *buf, int height, int linesize, + int16_t *prev_y, + const uint8_t color[4], int h) { int k; int start = height/2; @@ -231,9 +253,26 @@ static void draw_sample_line_rgba(uint8_t *buf, int height, int linesize, } } -static void draw_sample_p2p_rgba(uint8_t *buf, int height, int linesize, - int16_t *prev_y, - const uint8_t color[4], int h) +static void draw_sample_line_rgba_full(uint8_t *buf, int height, int linesize, + int16_t *prev_y, + const uint8_t color[4], int h) +{ + int k; + int start = height/2; + int end = av_clip(h, 0, height-1); + if (start > end) + FFSWAP(int16_t, start, end); + for (k = start; k < end; k++) { + buf[k * linesize + 0] = color[0]; + buf[k * linesize + 1] = color[1]; + buf[k * linesize + 2] = color[2]; + buf[k * linesize + 3] = color[3]; + } +} + +static void draw_sample_p2p_rgba_scale(uint8_t *buf, int height, int linesize, + int16_t *prev_y, + const uint8_t color[4], int h) { int k; if (h >= 0 && h < height) { @@ -257,9 +296,35 @@ static void draw_sample_p2p_rgba(uint8_t *buf, int height, int linesize, *prev_y = h; } -static void draw_sample_cline_rgba(uint8_t *buf, int height, int linesize, - int16_t *prev_y, - const uint8_t color[4], int h) +static void draw_sample_p2p_rgba_full(uint8_t *buf, int height, int linesize, + int16_t *prev_y, + const uint8_t color[4], int h) +{ + int k; + if (h >= 0 && h < height) { + buf[h * linesize + 0] = color[0]; + buf[h * linesize + 1] = color[1]; + buf[h * linesize + 2] = color[2]; + buf[h * linesize + 3] = color[3]; + if (*prev_y && h != *prev_y) { + int start = *prev_y; + int end = av_clip(h, 0, height-1); + if (start > end) + FFSWAP(int16_t, start, end); + for (k = start + 1; k < end; k++) { + buf[k * linesize + 0] = color[0]; + buf[k * linesize + 1] = color[1]; + buf[k * linesize + 2] = color[2]; + buf[k * linesize + 3] = color[3]; + } + } + } + *prev_y = h; +} + +static void draw_sample_cline_rgba_scale(uint8_t *buf, int height, int linesize, + int16_t *prev_y, + const uint8_t color[4], int h) { int k; const int start = (height - h) / 2; @@ -271,6 +336,20 @@ static void draw_sample_cline_rgba(uint8_t *buf, int height, int linesize, buf[k * linesize + 3] += color[3]; } } + static void draw_sample_cline_rgba_full(uint8_t *buf, int height, int linesize, + int16_t *prev_y, + const uint8_t color[4], int h) +{ + int k; + const int start = (height - h) / 2; + const int end = start + h; + for (k = start; k < end; k++) { + buf[k * linesize + 0] = color[0]; + buf[k * linesize + 1] = color[1]; + buf[k * linesize + 2] = color[2]; + buf[k * linesize + 3] = color[3]; + } +} static void draw_sample_point_gray(uint8_t *buf, int height, int linesize, int16_t *prev_y, @@ -368,10 +447,10 @@ static int config_output(AVFilterLink *outlink) break; case AV_PIX_FMT_RGBA: switch (showwaves->mode) { - case MODE_POINT: showwaves->draw_sample = draw_sample_point_rgba; break; - case MODE_LINE: showwaves->draw_sample = draw_sample_line_rgba; break; - case MODE_P2P: showwaves->draw_sample = draw_sample_p2p_rgba; break; - case MODE_CENTERED_LINE: showwaves->draw_sample = draw_sample_cline_rgba; break; + case MODE_POINT: showwaves->draw_sample = showwaves->draw_mode == DRAW_SCALE ? draw_sample_point_rgba_scale : draw_sample_point_rgba_full; break; + case MODE_LINE: showwaves->draw_sample = showwaves->draw_mode == DRAW_SCALE ? draw_sample_line_rgba_scale : draw_sample_line_rgba_full; break; + case MODE_P2P: showwaves->draw_sample = showwaves->draw_mode == DRAW_SCALE ? draw_sample_p2p_rgba_scale : draw_sample_p2p_rgba_full; break; + case MODE_CENTERED_LINE: showwaves->draw_sample = showwaves->draw_mode == DRAW_SCALE ? draw_sample_cline_rgba_scale : draw_sample_cline_rgba_full; break; default: return AVERROR_BUG; } @@ -430,8 +509,12 @@ static int config_output(AVFilterLink *outlink) if (!colors) return AVERROR(ENOMEM); - /* multiplication factor, pre-computed to avoid in-loop divisions */ - x = 255 / ((showwaves->split_channels ? 1 : nb_channels) * showwaves->n); + if (showwaves->draw_mode == DRAW_SCALE) { + /* multiplication factor, pre-computed to avoid in-loop divisions */ + x = 255 / ((showwaves->split_channels ? 1 : nb_channels) * showwaves->n); + } else { + x = 255; + } if (outlink->format == AV_PIX_FMT_RGBA) { uint8_t fg[4] = { 0xff, 0xff, 0xff, 0xff }; From 74c6a6d3735f79671b177a0e0c6f2db696c2a6d2 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 23 Mar 2018 19:21:52 +0100 Subject: [PATCH 2218/2557] doc/filters: itemize channelmap examples Signed-off-by: Paul B Mahol --- doc/filters.texi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 421b5f6cd215a..e684e490f0ccd 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2188,6 +2188,10 @@ The channel layout of the output stream. If no mapping is present, the filter will implicitly map input channels to output channels, preserving indices. +@subsection Examples + +@itemize +@item For example, assuming a 5.1+downmix input MOV file, @example ffmpeg -i in.mov -filter 'channelmap=map=DL-FL|DR-FR' out.wav @@ -2195,10 +2199,12 @@ ffmpeg -i in.mov -filter 'channelmap=map=DL-FL|DR-FR' out.wav will create an output WAV file tagged as stereo from the downmix channels of the input. +@item To fix a 5.1 WAV improperly encoded in AAC's native channel order @example ffmpeg -i in.wav -filter 'channelmap=1|2|0|5|3|4:5.1' out.wav @end example +@end itemize @section channelsplit From 3e3d56776166b7529df7cc37d48a5d2a2596050b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 23 Mar 2018 22:53:13 +0100 Subject: [PATCH 2219/2557] avfilter/avf_showvolume: implement basic rms metering mode Signed-off-by: Paul B Mahol --- doc/filters.texi | 4 +++ libavfilter/avf_showvolume.c | 50 +++++++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index e684e490f0ccd..1620ae1cfa7bd 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19970,6 +19970,10 @@ step is disabled. @item p Set background opacity, allowed range is [0, 1]. Default is 0. + +@item m +Set metering mode, can be peak: @code{p} or rms: @code{r}, +default is @code{p}. @end table @section showwaves diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index 9b836b9ad62c6..af8ac1da6c164 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -44,6 +44,7 @@ typedef struct ShowVolumeContext { int orientation; int step; float bgopacity; + int mode; AVFrame *out; AVExpr *c_expr; @@ -51,6 +52,10 @@ typedef struct ShowVolumeContext { int draw_volume; double *values; uint32_t *color_lut; + float *max; + float rms_factor; + + void (*meter)(float *src, int nb_samples, float *max, float factor); } ShowVolumeContext; #define OFFSET(x) offsetof(ShowVolumeContext, x) @@ -71,6 +76,9 @@ static const AVOption showvolume_options[] = { { "v", "vertical", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "orientation" }, { "s", "set step size", OFFSET(step), AV_OPT_TYPE_INT, {.i64=0}, 0, 5, FLAGS }, { "p", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, FLAGS }, + { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "mode" }, + { "p", "peak", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, + { "r", "rms", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" }, { NULL } }; @@ -120,6 +128,23 @@ static int query_formats(AVFilterContext *ctx) return 0; } +static void find_peak(float *src, int nb_samples, float *peak, float factor) +{ + int i; + + *peak = 0; + for (i = 0; i < nb_samples; i++) + *peak = FFMAX(*peak, FFABS(src[i])); +} + +static void find_rms(float *src, int nb_samples, float *rms, float factor) +{ + int i; + + for (i = 0; i < nb_samples; i++) + *rms += factor * (src[i] * src[i] - *rms); +} + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -138,6 +163,18 @@ static int config_input(AVFilterLink *inlink) if (!s->color_lut) return AVERROR(ENOMEM); + s->max = av_calloc(inlink->channels, sizeof(*s->max)); + if (!s->max) + return AVERROR(ENOMEM); + + s->rms_factor = 10000. / inlink->sample_rate; + + switch (s->mode) { + case 0: s->meter = find_peak; break; + case 1: s->meter = find_rms; break; + default: return AVERROR_BUG; + } + return 0; } @@ -252,10 +289,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) for (c = 0; c < inlink->channels; c++) { float *src = (float *)insamples->extended_data[c]; uint32_t *lut = s->color_lut + s->w * c; - float max = 0; + float max; - for (i = 0; i < insamples->nb_samples; i++) - max = FFMAX(max, src[i]); + s->meter(src, insamples->nb_samples, &s->max[c], s->rms_factor); + max = s->max[c]; s->values[c * VAR_VARS_NB + VAR_VOLUME] = 20.0 * log10(max); max = av_clipf(max, 0, 1); @@ -280,10 +317,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) for (c = 0; c < inlink->channels; c++) { float *src = (float *)insamples->extended_data[c]; uint32_t *lut = s->color_lut + s->w * c; - float max = 0; + float max; - for (i = 0; i < insamples->nb_samples; i++) - max = FFMAX(max, src[i]); + s->meter(src, insamples->nb_samples, &s->max[c], s->rms_factor); + max = s->max[c]; s->values[c * VAR_VARS_NB + VAR_VOLUME] = 20.0 * log10(max); max = av_clipf(max, 0, 1); @@ -339,6 +376,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_expr_free(s->c_expr); av_freep(&s->values); av_freep(&s->color_lut); + av_freep(&s->max); } static const AVFilterPad showvolume_inputs[] = { From f5ceb15bb692d5121a976c3638811b96fc14f85f Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 21 Mar 2018 11:27:49 -0300 Subject: [PATCH 2220/2557] ffmpeg: remove dead call to av_parser_change() It's been a noop for years, and it's been argued that in-band headers should not be forcedly removed without the user's explicit request. Also, as the FIXME line stated, this is a job for a bitstream filter like extract_extradata, remove_extradata, dump_extradata, and filter_units. Signed-off-by: James Almer --- fftools/ffmpeg.c | 44 ++++---------------------------------------- fftools/ffmpeg.h | 3 --- 2 files changed, 4 insertions(+), 43 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 3c18e0671340b..ec9ce29097457 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -551,9 +551,6 @@ static void ffmpeg_cleanup(int ret) av_frame_free(&ost->last_frame); av_dict_free(&ost->encoder_opts); - av_parser_close(ost->parser); - avcodec_free_context(&ost->parser_avctx); - av_freep(&ost->forced_keyframes); av_expr_free(ost->forced_keyframes_pexpr); av_freep(&ost->avfilter); @@ -2051,30 +2048,10 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); opkt.flags = pkt->flags; - // FIXME remove the following 2 lines they shall be replaced by the bitstream filters - if ( ost->st->codecpar->codec_id != AV_CODEC_ID_H264 - && ost->st->codecpar->codec_id != AV_CODEC_ID_MPEG1VIDEO - && ost->st->codecpar->codec_id != AV_CODEC_ID_MPEG2VIDEO - && ost->st->codecpar->codec_id != AV_CODEC_ID_VC1 - ) { - int ret = av_parser_change(ost->parser, ost->parser_avctx, - &opkt.data, &opkt.size, - pkt->data, pkt->size, - pkt->flags & AV_PKT_FLAG_KEY); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "av_parser_change failed: %s\n", - av_err2str(ret)); - exit_program(1); - } - if (ret) { - opkt.buf = av_buffer_create(opkt.data, opkt.size, av_buffer_default_free, NULL, 0); - if (!opkt.buf) - exit_program(1); - } - } else { - opkt.data = pkt->data; - opkt.size = pkt->size; - } + + opkt.data = pkt->data; + opkt.size = pkt->size; + av_copy_packet_side_data(&opkt, pkt); output_packet(of, &opkt, ost, 0); @@ -3124,11 +3101,6 @@ static int init_output_stream_streamcopy(OutputStream *ost) av_display_rotation_set((int32_t *)sd, -ost->rotate_override_value); } - ost->parser = av_parser_init(par_dst->codec_id); - ost->parser_avctx = avcodec_alloc_context3(NULL); - if (!ost->parser_avctx) - return AVERROR(ENOMEM); - switch (par_dst->codec_type) { case AVMEDIA_TYPE_AUDIO: if (audio_volume != 256) { @@ -3569,14 +3541,6 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len) ret = init_output_stream_streamcopy(ost); if (ret < 0) return ret; - - /* - * FIXME: will the codec context used by the parser during streamcopy - * This should go away with the new parser API. - */ - ret = avcodec_parameters_to_context(ost->parser_avctx, ost->st->codecpar); - if (ret < 0) - return ret; } // parse user provided disposition, and update stream values diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 8195f73e8b25e..d44b7a5c72a52 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -526,9 +526,6 @@ typedef struct OutputStream { int keep_pix_fmt; - AVCodecParserContext *parser; - AVCodecContext *parser_avctx; - /* stats */ // combined size of all the packets written uint64_t data_size; From 231a73308f183484317c3fdfe098f543cd401898 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 21 Mar 2018 11:43:04 -0300 Subject: [PATCH 2221/2557] ffmpeg: pass reference counted packet on codec copy when possible Should prevent unnecessary copy of data in cases where new references to the packet are created within the muxer or a bitstream filter. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- fftools/ffmpeg.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index ec9ce29097457..1b2e37b8d808a 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2049,6 +2049,11 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt.flags = pkt->flags; + if (pkt->buf) { + opkt.buf = av_buffer_ref(pkt->buf); + if (!opkt.buf) + exit_program(1); + } opkt.data = pkt->data; opkt.size = pkt->size; From ed1f08bfb5500340463e630290360609a90d2886 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 23 Mar 2018 18:16:11 -0300 Subject: [PATCH 2222/2557] avcodec/bsf: make sure the AVBSFInternal stored packet is reference counted Some bitstream filters may buffer said packet in their own contexts for latter use. The documentation for av_bsf_send_packet() doesn't forbid feeding it non-reference counted packets, which depending on the way said packets were internally buffered by the bsf it may result in the data described in them becoming invalid or unavailable at any time. This was the case with vp9_superframe after commit e1bc3f4396, which was then promptly fixed in 37f4a093f7 and 7a02b364b6. It is still the case even today with vp9_reorder_raw. With this change the bitstream filters will not have to worry how to store or consume the packets fed to them. Reviewed-by: wm4 Signed-off-by: James Almer --- libavcodec/bsf.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libavcodec/bsf.c b/libavcodec/bsf.c index 38b423101c361..05a44e2e31cc0 100644 --- a/libavcodec/bsf.c +++ b/libavcodec/bsf.c @@ -188,7 +188,15 @@ int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt) ctx->internal->buffer_pkt->side_data_elems) return AVERROR(EAGAIN); - av_packet_move_ref(ctx->internal->buffer_pkt, pkt); + if (pkt->buf) { + av_packet_move_ref(ctx->internal->buffer_pkt, pkt); + } else { + int ret = av_packet_ref(ctx->internal->buffer_pkt, pkt); + + if (ret < 0) + return ret; + av_packet_unref(pkt); + } return 0; } From dc99ee6b08e54de13b4c82ff265609b6ab83e3d8 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 20 Mar 2018 01:19:19 -0300 Subject: [PATCH 2223/2557] avcodec/noise_bsf: move the reference in the bsf internal buffer There's no need to allocate a new packet for it. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavcodec/noise_bsf.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/libavcodec/noise_bsf.c b/libavcodec/noise_bsf.c index 6bb89507fcb21..d79f63b77797e 100644 --- a/libavcodec/noise_bsf.c +++ b/libavcodec/noise_bsf.c @@ -35,45 +35,38 @@ typedef struct NoiseContext { unsigned int state; } NoiseContext; -static int noise(AVBSFContext *ctx, AVPacket *out) +static int noise(AVBSFContext *ctx, AVPacket *pkt) { NoiseContext *s = ctx->priv_data; - AVPacket *in; int amount = s->amount > 0 ? s->amount : (s->state % 10001 + 1); int i, ret = 0; if (amount <= 0) return AVERROR(EINVAL); - ret = ff_bsf_get_packet(ctx, &in); + ret = ff_bsf_get_packet_ref(ctx, pkt); if (ret < 0) return ret; if (s->dropamount > 0 && s->state % s->dropamount == 0) { s->state++; - av_packet_free(&in); + av_packet_unref(pkt); return AVERROR(EAGAIN); } - ret = av_new_packet(out, in->size); + ret = av_packet_make_writable(pkt); if (ret < 0) goto fail; - ret = av_packet_copy_props(out, in); - if (ret < 0) - goto fail; - - memcpy(out->data, in->data, in->size); - - for (i = 0; i < out->size; i++) { - s->state += out->data[i] + 1; + for (i = 0; i < pkt->size; i++) { + s->state += pkt->data[i] + 1; if (s->state % amount == 0) - out->data[i] = s->state; + pkt->data[i] = s->state; } fail: if (ret < 0) - av_packet_unref(out); - av_packet_free(&in); + av_packet_unref(pkt); + return ret; } From 829aebf95d44c1e850fd31692a273e6c6ab8161a Mon Sep 17 00:00:00 2001 From: Sasi Inguva Date: Wed, 21 Mar 2018 13:36:38 -0700 Subject: [PATCH 2224/2557] lavf/utils.c: Don't compute start_time from DISCARD packets for video. Signed-off-by: Sasi Inguva Signed-off-by: Michael Niedermayer --- libavformat/utils.c | 4 +++- tests/fate/mov.mak | 10 +++++++- tests/ref/fate/mov-neg-firstpts-discard | 3 +++ .../ref/fate/mov-neg-firstpts-discard-frames | 24 +++++++++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 tests/ref/fate/mov-neg-firstpts-discard create mode 100644 tests/ref/fate/mov-neg-firstpts-discard-frames diff --git a/libavformat/utils.c b/libavformat/utils.c index 4d0b56c2a82af..f13c8208b118d 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1158,7 +1158,9 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, } if (st->start_time == AV_NOPTS_VALUE) { - st->start_time = pts; + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || !(pkt->flags & AV_PKT_FLAG_DISCARD)) { + st->start_time = pts; + } if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate) st->start_time += av_rescale_q(st->skip_samples, (AVRational){1, st->codecpar->sample_rate}, st->time_base); } diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 64f92e9488aa1..9d7d62a023238 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -13,8 +13,10 @@ FATE_MOV = fate-mov-3elist \ fate-mov-elst-ends-betn-b-and-i \ fate-mov-frag-overlap \ fate-mov-bbi-elst-starts-b \ + fate-mov-neg-firstpts-discard-frames \ -FATE_MOV_FFPROBE = fate-mov-aac-2048-priming \ +FATE_MOV_FFPROBE = fate-mov-neg-firstpts-discard \ + fate-mov-aac-2048-priming \ fate-mov-zombie \ fate-mov-init-nonkeyframe \ fate-mov-displaymatrix \ @@ -72,6 +74,12 @@ fate-mov-frag-overlap: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/frag_overlap.mp4 # GOP structure : B B I in presentation order. fate-mov-bbi-elst-starts-b: CMD = framemd5 -flags +bitexact -acodec aac_fixed -i $(TARGET_SAMPLES)/h264/twofields_packet.mp4 +# Makes sure that the stream start_time is not negative when the first packet is a DISCARD packet with negative timestamp. +fate-mov-neg-firstpts-discard: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=start_time -bitexact $(TARGET_SAMPLES)/mov/mov_neg_first_pts_discard.mov + +# Makes sure that expected frames are generated for mov_neg_first_pts_discard.mov with -vsync 1 +fate-mov-neg-firstpts-discard-frames: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/mov/mov_neg_first_pts_discard.mov -vsync 1 + fate-mov-aac-2048-priming: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_packets -print_format compact $(TARGET_SAMPLES)/mov/aac-2048-priming.mov fate-mov-zombie: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_streams -show_packets -show_frames -bitexact -print_format compact $(TARGET_SAMPLES)/mov/white_zombie_scrunch-part.mov diff --git a/tests/ref/fate/mov-neg-firstpts-discard b/tests/ref/fate/mov-neg-firstpts-discard new file mode 100644 index 0000000000000..7c982d3ffebb0 --- /dev/null +++ b/tests/ref/fate/mov-neg-firstpts-discard @@ -0,0 +1,3 @@ +[STREAM] +start_time=N/A +[/STREAM] diff --git a/tests/ref/fate/mov-neg-firstpts-discard-frames b/tests/ref/fate/mov-neg-firstpts-discard-frames new file mode 100644 index 0000000000000..81b59b384b8a0 --- /dev/null +++ b/tests/ref/fate/mov-neg-firstpts-discard-frames @@ -0,0 +1,24 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#tb 0: 1/30 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 115200, 1e55263b359b4c99c3463655a1120f11 +0, 1, 1, 1, 115200, ce33efea81064e7c23deb57dc4c21995 +0, 2, 2, 1, 115200, 42234f25d6191ab13c3676a7937c921b +0, 3, 3, 1, 115200, eab2ccb227c66cba4c9feb8cdbf28ef8 +0, 4, 4, 1, 115200, c8816e0b151b2c892163e35086918520 +0, 5, 5, 1, 115200, c633f5604c8651165d551ee88fb4cd92 +0, 6, 6, 1, 115200, 5f3f8530d720fef3ac4c937e7f488ea7 +0, 7, 7, 1, 115200, be24a583909ca92008b642f39be02685 +0, 8, 8, 1, 115200, 83872a6e5c3369fe76f684de31bd9a36 +0, 9, 9, 1, 115200, 4629d6eb656883b337e8e0b381f2db8d +0, 10, 10, 1, 115200, f6bec55bc026440d23a44b948900e785 +0, 11, 11, 1, 115200, 7e12e8113916305c79e5d08354acc9ae +0, 12, 12, 1, 115200, d315c0093536642d340ea50de3b2bfbb +0, 13, 13, 1, 115200, 3d12b24aaed72bfada4a1a3e5e02945a +0, 14, 14, 1, 115200, 070d6b8935c11304d8f9520c4401a130 From db2a7c947ec28b0a04a4e5193c9b0d33de823fbb Mon Sep 17 00:00:00 2001 From: Jacob Trimble Date: Tue, 5 Dec 2017 14:52:22 -0800 Subject: [PATCH 2225/2557] avcodec/avcodec.h: Add encryption info side data. This new side-data will contain info on how a packet is encrypted. This allows the app to handle packet decryption. Signed-off-by: Jacob Trimble Signed-off-by: Michael Niedermayer --- doc/APIchanges | 4 + libavcodec/avcodec.h | 13 ++ libavutil/Makefile | 2 + libavutil/encryption_info.c | 295 ++++++++++++++++++++++++++++++++++++ libavutil/encryption_info.h | 200 ++++++++++++++++++++++++ libavutil/version.h | 2 +- 6 files changed, 515 insertions(+), 1 deletion(-) create mode 100644 libavutil/encryption_info.c create mode 100644 libavutil/encryption_info.h diff --git a/doc/APIchanges b/doc/APIchanges index d410bcdd75629..a099afd9bc81b 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-xx-xx - xxxxxxx - lavu 56.8.100 - encryption_info.h + Add AVEncryptionInitInfo and AVEncryptionInfo structures to hold new side-data + for encryption info. + 2018-03-21 - xxxxxxx - lavc 58.15.100 - avcodec.h Add av_packet_make_writable(). diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index a78017f1fbd4b..495242faf04e8 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1344,6 +1344,19 @@ enum AVPacketSideDataType { */ AV_PKT_DATA_A53_CC, + /** + * This side data is encryption initialization data. + * The format is not part of ABI, use av_encryption_init_info_* methods to + * access. + */ + AV_PKT_DATA_ENCRYPTION_INIT_INFO, + + /** + * This side data contains encryption info for how to decrypt the packet. + * The format is not part of ABI, use av_encryption_info_* methods to access. + */ + AV_PKT_DATA_ENCRYPTION_INFO, + /** * The number of side data types. * This is not part of the public API/ABI in the sense that it may diff --git a/libavutil/Makefile b/libavutil/Makefile index 17ec1f1aa94eb..a63ba523c9ecc 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -24,6 +24,7 @@ HEADERS = adler32.h \ dict.h \ display.h \ downmix_info.h \ + encryption_info.h \ error.h \ eval.h \ fifo.h \ @@ -107,6 +108,7 @@ OBJS = adler32.o \ dict.o \ display.o \ downmix_info.o \ + encryption_info.o \ error.o \ eval.o \ fifo.o \ diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c new file mode 100644 index 0000000000000..20a752d6b4ab2 --- /dev/null +++ b/libavutil/encryption_info.c @@ -0,0 +1,295 @@ +/** + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "encryption_info.h" +#include "mem.h" +#include "intreadwrite.h" + +#define FF_ENCRYPTION_INFO_EXTRA 24 + +// The format of the AVEncryptionInfo side data: +// u32be scheme +// u32be crypt_byte_block +// u32be skip_byte_block +// u32be key_id_size +// u32be iv_size +// u32be subsample_count +// u8[key_id_size] key_id +// u8[iv_size] iv +// { +// u32be bytes_of_clear_data +// u32be bytes_of_protected_data +// }[subsample_count] + +AVEncryptionInfo *av_encryption_info_alloc(uint32_t subsample_count, uint32_t key_id_size, uint32_t iv_size) +{ + AVEncryptionInfo *info; + + info = av_mallocz(sizeof(*info)); + if (!info) + return NULL; + + info->key_id = av_mallocz(key_id_size); + info->key_id_size = key_id_size; + info->iv = av_mallocz(iv_size); + info->iv_size = iv_size; + info->subsamples = av_mallocz_array(subsample_count, sizeof(*info->subsamples)); + info->subsample_count = subsample_count; + + // Allow info->subsamples to be NULL if there are no subsamples. + if (!info->key_id || !info->iv || (!info->subsamples && subsample_count)) { + av_encryption_info_free(info); + return NULL; + } + + return info; +} + +AVEncryptionInfo *av_encryption_info_clone(const AVEncryptionInfo *info) +{ + AVEncryptionInfo *ret; + + ret = av_encryption_info_alloc(info->subsample_count, info->key_id_size, info->iv_size); + if (!ret) + return NULL; + + ret->scheme = info->scheme; + ret->crypt_byte_block = info->crypt_byte_block; + ret->skip_byte_block = info->skip_byte_block; + memcpy(ret->iv, info->iv, info->iv_size); + memcpy(ret->key_id, info->key_id, info->key_id_size); + memcpy(ret->subsamples, info->subsamples, sizeof(*info->subsamples) * info->subsample_count); + return ret; +} + +void av_encryption_info_free(AVEncryptionInfo *info) +{ + if (info) { + av_free(info->key_id); + av_free(info->iv); + av_free(info->subsamples); + av_free(info); + } +} + +AVEncryptionInfo *av_encryption_info_get_side_data(const uint8_t* buffer, size_t size) +{ + AVEncryptionInfo *info; + uint64_t key_id_size, iv_size, subsample_count, i; + + if (!buffer || size < FF_ENCRYPTION_INFO_EXTRA) + return NULL; + + key_id_size = AV_RB32(buffer + 12); + iv_size = AV_RB32(buffer + 16); + subsample_count = AV_RB32(buffer + 20); + + if (size < FF_ENCRYPTION_INFO_EXTRA + key_id_size + iv_size + subsample_count * 8) + return NULL; + + info = av_encryption_info_alloc(subsample_count, key_id_size, iv_size); + if (!info) + return NULL; + + info->scheme = AV_RB32(buffer); + info->crypt_byte_block = AV_RB32(buffer + 4); + info->skip_byte_block = AV_RB32(buffer + 8); + memcpy(info->key_id, buffer + 24, key_id_size); + memcpy(info->iv, buffer + key_id_size + 24, iv_size); + + buffer += key_id_size + iv_size + 24; + for (i = 0; i < subsample_count; i++) { + info->subsamples[i].bytes_of_clear_data = AV_RB32(buffer); + info->subsamples[i].bytes_of_protected_data = AV_RB32(buffer + 4); + buffer += 8; + } + + return info; +} + +uint8_t *av_encryption_info_add_side_data(const AVEncryptionInfo *info, size_t *size) +{ + uint8_t *buffer, *cur_buffer; + uint32_t i; + + if (UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA < info->key_id_size || + UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size < info->iv_size || + (UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size - info->iv_size) / 8 < info->subsample_count) { + return NULL; + } + + *size = FF_ENCRYPTION_INFO_EXTRA + info->key_id_size + info->iv_size + + (info->subsample_count * 8); + cur_buffer = buffer = av_malloc(*size); + if (!buffer) + return NULL; + + AV_WB32(cur_buffer, info->scheme); + AV_WB32(cur_buffer + 4, info->crypt_byte_block); + AV_WB32(cur_buffer + 8, info->skip_byte_block); + AV_WB32(cur_buffer + 12, info->key_id_size); + AV_WB32(cur_buffer + 16, info->iv_size); + AV_WB32(cur_buffer + 20, info->subsample_count); + cur_buffer += 24; + memcpy(cur_buffer, info->key_id, info->key_id_size); + cur_buffer += info->key_id_size; + memcpy(cur_buffer, info->iv, info->iv_size); + cur_buffer += info->iv_size; + for (i = 0; i < info->subsample_count; i++) { + AV_WB32(cur_buffer, info->subsamples[i].bytes_of_clear_data); + AV_WB32(cur_buffer + 4, info->subsamples[i].bytes_of_protected_data); + cur_buffer += 8; + } + + return buffer; +} + +// The format of the AVEncryptionInitInfo side data: +// u32be system_id_size +// u32be num_key_ids +// u32be key_id_size +// u32be data_size +// u8[system_id_size] system_id +// u8[key_id_size][num_key_id] key_ids +// u8[data_size] data + +#define FF_ENCRYPTION_INIT_INFO_EXTRA 16 + +AVEncryptionInitInfo *av_encryption_init_info_alloc( + uint32_t system_id_size, uint32_t num_key_ids, uint32_t key_id_size, uint32_t data_size) +{ + AVEncryptionInitInfo *info; + uint32_t i; + + info = av_mallocz(sizeof(*info)); + if (!info) + return NULL; + + info->system_id = av_mallocz(system_id_size); + info->system_id_size = system_id_size; + info->key_ids = key_id_size ? av_mallocz_array(num_key_ids, sizeof(*info->key_ids)) : NULL; + info->num_key_ids = num_key_ids; + info->key_id_size = key_id_size; + info->data = av_mallocz(data_size); + info->data_size = data_size; + + // Allow pointers to be NULL if the size is 0. + if ((!info->system_id && system_id_size) || (!info->data && data_size) || + (!info->key_ids && num_key_ids && key_id_size)) { + av_encryption_init_info_free(info); + return NULL; + } + + if (key_id_size) { + for (i = 0; i < num_key_ids; i++) { + info->key_ids[i] = av_mallocz(key_id_size); + if (!info->key_ids[i]) { + av_encryption_init_info_free(info); + return NULL; + } + } + } + + return info; +} + +void av_encryption_init_info_free(AVEncryptionInitInfo *info) +{ + uint32_t i; + if (info) { + for (i = 0; i < info->num_key_ids; i++) { + av_free(info->key_ids[i]); + } + av_free(info->system_id); + av_free(info->key_ids); + av_free(info->data); + av_free(info); + } +} + +AVEncryptionInitInfo *av_encryption_init_info_get_side_data( + const uint8_t *side_data, size_t side_data_size) +{ + AVEncryptionInitInfo *info; + uint64_t system_id_size, num_key_ids, key_id_size, data_size, i; + + if (!side_data || side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA) + return NULL; + + system_id_size = AV_RB32(side_data); + num_key_ids = AV_RB32(side_data + 4); + key_id_size = AV_RB32(side_data + 8); + data_size = AV_RB32(side_data + 12); + + // UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX + if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size) + return NULL; + + info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size); + if (!info) + return NULL; + + memcpy(info->system_id, side_data + 16, system_id_size); + side_data += system_id_size + 16; + for (i = 0; i < num_key_ids; i++) { + memcpy(info->key_ids[i], side_data, key_id_size); + side_data += key_id_size; + } + memcpy(info->data, side_data, data_size); + + return info; +} + +uint8_t *av_encryption_init_info_add_side_data(const AVEncryptionInitInfo *info, size_t *side_data_size) +{ + uint8_t *buffer, *cur_buffer; + uint32_t i, max_size; + + if (UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA < info->system_id_size || + UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA - info->system_id_size < info->data_size) { + return NULL; + } + + if (info->num_key_ids) { + max_size = UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA - info->system_id_size - info->data_size; + if (max_size / info->num_key_ids < info->key_id_size) + return NULL; + } + + *side_data_size = FF_ENCRYPTION_INIT_INFO_EXTRA + info->system_id_size + + info->data_size + (info->num_key_ids * info->key_id_size); + cur_buffer = buffer = av_malloc(*side_data_size); + if (!buffer) + return NULL; + + AV_WB32(cur_buffer, info->system_id_size); + AV_WB32(cur_buffer + 4, info->num_key_ids); + AV_WB32(cur_buffer + 8, info->key_id_size); + AV_WB32(cur_buffer + 12, info->data_size); + cur_buffer += 16; + + memcpy(cur_buffer, info->system_id, info->system_id_size); + cur_buffer += info->system_id_size; + for (i = 0; i < info->num_key_ids; i++) { + memcpy(cur_buffer, info->key_ids[i], info->key_id_size); + cur_buffer += info->key_id_size; + } + memcpy(cur_buffer, info->data, info->data_size); + + return buffer; +} diff --git a/libavutil/encryption_info.h b/libavutil/encryption_info.h new file mode 100644 index 0000000000000..47dc3a35cacce --- /dev/null +++ b/libavutil/encryption_info.h @@ -0,0 +1,200 @@ +/** + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_ENCRYPTION_INFO_H +#define AVUTIL_ENCRYPTION_INFO_H + +#include +#include + +typedef struct AVSubsampleEncryptionInfo { + /** The number of bytes that are clear. */ + unsigned int bytes_of_clear_data; + + /** + * The number of bytes that are protected. If using pattern encryption, + * the pattern applies to only the protected bytes; if not using pattern + * encryption, all these bytes are encrypted. + */ + unsigned int bytes_of_protected_data; +} AVSubsampleEncryptionInfo; + +/** + * This describes encryption info for a packet. This contains frame-specific + * info for how to decrypt the packet before passing it to the decoder. + * + * The size of this struct is not part of the public ABI. + */ +typedef struct AVEncryptionInfo { + /** The fourcc encryption scheme. */ + uint32_t scheme; + + /** + * Only used for pattern encryption. This is the number of 16-byte blocks + * that are encrypted. + */ + uint32_t crypt_byte_block; + + /** + * Only used for pattern encryption. This is the number of 16-byte blocks + * that are clear. + */ + uint32_t skip_byte_block; + + /** + * The ID of the key used to encrypt the packet. This should always be + * 16 bytes long, but may be changed in the future. + */ + uint8_t *key_id; + uint32_t key_id_size; + + /** + * The initialization vector. This may have been zero-filled to be the + * correct block size. This should always be 16 bytes long, but may be + * changed in the future. + */ + uint8_t *iv; + uint32_t iv_size; + + /** + * An array of subsample encryption info specifying how parts of the sample + * are encrypted. If there are no subsamples, then the whole sample is + * encrypted. + */ + AVSubsampleEncryptionInfo *subsamples; + uint32_t subsample_count; +} AVEncryptionInfo; + +/** + * This describes info used to initialize an encryption key system. + * + * The size of this struct is not part of the public ABI. + */ +typedef struct AVEncryptionInitInfo { + /** + * A unique identifier for the key system this is for, can be NULL if it + * is not known. This should always be 16 bytes, but may change in the + * future. + */ + uint8_t* system_id; + uint32_t system_id_size; + + /** + * An array of key IDs this initialization data is for. All IDs are the + * same length. Can be NULL if there are no known key IDs. + */ + uint8_t** key_ids; + /** The number of key IDs. */ + uint32_t num_key_ids; + /** + * The number of bytes in each key ID. This should always be 16, but may + * change in the future. + */ + uint32_t key_id_size; + + /** + * Key-system specific initialization data. This data is copied directly + * from the file and the format depends on the specific key system. This + * can be NULL if there is no initialization data; in that case, there + * will be at least one key ID. + */ + uint8_t* data; + uint32_t data_size; +} AVEncryptionInitInfo; + +/** + * Allocates an AVEncryptionInfo structure and sub-pointers to hold the given + * number of subsamples. This will allocate pointers for the key ID, IV, + * and subsample entries, set the size members, and zero-initialize the rest. + * + * @param subsample_count The number of subsamples. + * @param key_id_size The number of bytes in the key ID, should be 16. + * @param key_id_size The number of bytes in the IV, should be 16. + * + * @return The new AVEncryptionInfo structure, or NULL on error. + */ +AVEncryptionInfo *av_encryption_info_alloc(uint32_t subsample_count, uint32_t key_id_size, uint32_t iv_size); + +/** + * Allocates an AVEncryptionInfo structure with a copy of the given data. + * @return The new AVEncryptionInfo structure, or NULL on error. + */ +AVEncryptionInfo *av_encryption_info_clone(const AVEncryptionInfo *info); + +/** + * Frees the given encryption info object. This MUST NOT be used to free the + * side-data data pointer, that should use normal side-data methods. + */ +void av_encryption_info_free(AVEncryptionInfo *info); + +/** + * Creates a copy of the AVEncryptionInfo that is contained in the given side + * data. The resulting object should be passed to av_encryption_info_free() + * when done. + * + * @return The new AVEncryptionInfo structure, or NULL on error. + */ +AVEncryptionInfo *av_encryption_info_get_side_data(const uint8_t *side_data, size_t side_data_size); + +/** + * Allocates and initializes side data that holds a copy of the given encryption + * info. The resulting pointer should be either freed using av_free or given + * to av_packet_add_side_data(). + * + * @return The new side-data pointer, or NULL. + */ +uint8_t *av_encryption_info_add_side_data( + const AVEncryptionInfo *info, size_t *side_data_size); + + +/** + * Allocates an AVEncryptionInitInfo structure and sub-pointers to hold the + * given sizes. This will allocate pointers and set all the fields. + * + * @return The new AVEncryptionInitInfo structure, or NULL on error. + */ +AVEncryptionInitInfo *av_encryption_init_info_alloc( + uint32_t system_id_size, uint32_t num_key_ids, uint32_t key_id_size, uint32_t data_size); + +/** + * Frees the given encryption init info object. This MUST NOT be used to free + * the side-data data pointer, that should use normal side-data methods. + */ +void av_encryption_init_info_free(AVEncryptionInitInfo* info); + +/** + * Creates a copy of the AVEncryptionInitInfo that is contained in the given + * side data. The resulting object should be passed to + * av_encryption_init_info_free() when done. + * + * @return The new AVEncryptionInitInfo structure, or NULL on error. + */ +AVEncryptionInitInfo *av_encryption_init_info_get_side_data( + const uint8_t* side_data, size_t side_data_size); + +/** + * Allocates and initializes side data that holds a copy of the given encryption + * init info. The resulting pointer should be either freed using av_free or + * given to av_packet_add_side_data(). + * + * @return The new side-data pointer, or NULL. + */ +uint8_t *av_encryption_init_info_add_side_data( + const AVEncryptionInitInfo *info, size_t *side_data_size); + +#endif /* AVUTIL_ENCRYPTION_INFO_H */ diff --git a/libavutil/version.h b/libavutil/version.h index d166bb30e7c53..d3dd2df544afc 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 11 +#define LIBAVUTIL_VERSION_MINOR 12 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 823362782c4b119f64dfdb5d1348d24b3f64bc3e Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 23 Mar 2018 22:19:42 -0300 Subject: [PATCH 2226/2557] Revert "avcodec/vp9_superframe_bsf: cache packets by creating new references rather than moving them" This reverts commit 7a02b364b68c0bf7f065f5c217fae458f0efdb8d. The packet fetched by ff_bsf_get_packet() and ff_bsf_get_packet_ref() is now guaranteed to be reference counted. Reviewed-by: wm4 Signed-off-by: James Almer --- libavcodec/vp9_superframe_bsf.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavcodec/vp9_superframe_bsf.c b/libavcodec/vp9_superframe_bsf.c index 2ea49c672da1e..52569ab097afa 100644 --- a/libavcodec/vp9_superframe_bsf.c +++ b/libavcodec/vp9_superframe_bsf.c @@ -147,9 +147,7 @@ static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out) goto done; } - res = av_packet_ref(s->cache[s->n_cache++], in); - if (res < 0) - goto done; + av_packet_move_ref(s->cache[s->n_cache++], in); if (invisible) { res = AVERROR(EAGAIN); From 923a324174c2d943b8d21d0b77fc0d0c847abca0 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 24 Mar 2018 20:16:11 +0100 Subject: [PATCH 2227/2557] swscale/rgb : add X86 SIMD (SSSE3) for shuffle_bytes_2103 and shuffle_bytes_0321 --- libswscale/x86/Makefile | 1 + libswscale/x86/rgb2rgb.c | 10 ++++- libswscale/x86/rgb_2_rgb.asm | 80 ++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 libswscale/x86/rgb_2_rgb.asm diff --git a/libswscale/x86/Makefile b/libswscale/x86/Makefile index b50c7f265a666..f317d5dd9bf7a 100644 --- a/libswscale/x86/Makefile +++ b/libswscale/x86/Makefile @@ -11,3 +11,4 @@ OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o X86ASM-OBJS += x86/input.o \ x86/output.o \ x86/scale.o \ + x86/rgb_2_rgb.o \ diff --git a/libswscale/x86/rgb2rgb.c b/libswscale/x86/rgb2rgb.c index ffd12e16094c4..5caabf03ed031 100644 --- a/libswscale/x86/rgb2rgb.c +++ b/libswscale/x86/rgb2rgb.c @@ -144,11 +144,14 @@ DECLARE_ALIGNED(8, extern const uint64_t, ff_bgr2UVOffset); #endif /* HAVE_INLINE_ASM */ +void ff_shuffle_bytes_2103_ssse3(const uint8_t *src, uint8_t *dst, int src_size); +void ff_shuffle_bytes_0321_ssse3(const uint8_t *src, uint8_t *dst, int src_size); + av_cold void rgb2rgb_init_x86(void) { -#if HAVE_INLINE_ASM int cpu_flags = av_get_cpu_flags(); +#if HAVE_INLINE_ASM if (INLINE_MMX(cpu_flags)) rgb2rgb_init_mmx(); if (INLINE_AMD3DNOW(cpu_flags)) @@ -160,4 +163,9 @@ av_cold void rgb2rgb_init_x86(void) if (INLINE_AVX(cpu_flags)) rgb2rgb_init_avx(); #endif /* HAVE_INLINE_ASM */ + + if (EXTERNAL_SSSE3(cpu_flags)) { + shuffle_bytes_0321 = ff_shuffle_bytes_0321_ssse3; + shuffle_bytes_2103 = ff_shuffle_bytes_2103_ssse3; + } } diff --git a/libswscale/x86/rgb_2_rgb.asm b/libswscale/x86/rgb_2_rgb.asm new file mode 100644 index 0000000000000..e4104d9be2879 --- /dev/null +++ b/libswscale/x86/rgb_2_rgb.asm @@ -0,0 +1,80 @@ +;****************************************************************************** +;* Copyright Nick Kurshev +;* Copyright Michael (michaelni@gmx.at) +;* Copyright 2018 Jokyo Images +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +pb_shuffle2103: db 2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15 +pb_shuffle0321: db 0, 3, 2, 1, 4, 7, 6, 5, 8, 11, 10, 9, 12, 15, 14, 13 + +SECTION .text + +;------------------------------------------------------------------------------ +; shuffle_bytes_## (const uint8_t *src, uint8_t *dst, int src_size) +;------------------------------------------------------------------------------ +; %1-4 index shuffle +%macro SHUFFLE_BYTES 4 +cglobal shuffle_bytes_%1%2%3%4, 3, 5, 2, src, dst, w, tmp, x + VBROADCASTI128 m0, [pb_shuffle%1%2%3%4] + movsxdifnidn wq, wd + mov xq, wq + + add srcq, wq + add dstq, wq + neg wq + +;calc scalar loop + and xq, mmsize-4 + je .loop_simd + +.loop_scalar: + mov tmpb, [srcq + wq + %1] + mov [dstq+wq + 0], tmpb + mov tmpb, [srcq + wq + %2] + mov [dstq+wq + 1], tmpb + mov tmpb, [srcq + wq + %3] + mov [dstq+wq + 2], tmpb + mov tmpb, [srcq + wq + %4] + mov [dstq+wq + 3], tmpb + add wq, 4 + sub xq, 4 + jg .loop_scalar + +;check if src_size < mmsize +cmp wq, 0 +jge .end + +.loop_simd: + movu m1, [srcq+wq] + pshufb m1, m0 + movu [dstq+wq], m1 + add wq, mmsize + jl .loop_simd + +.end: + RET +%endmacro + +INIT_XMM ssse3 +SHUFFLE_BYTES 2, 1, 0, 3 +SHUFFLE_BYTES 0, 3, 2, 1 From d4f6640855faf57da1ccc3cade356975fcb00207 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 24 Mar 2018 20:17:32 +0100 Subject: [PATCH 2228/2557] swscale/rgb : move shuffle func shuffle_bytes_1230, shuffle_bytes_3012, shuffle_bytes_3210 in order to add SIMD --- libswscale/rgb2rgb.c | 23 ++++------------------- libswscale/rgb2rgb.h | 6 +++--- libswscale/rgb2rgb_template.c | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/libswscale/rgb2rgb.c b/libswscale/rgb2rgb.c index 04b7908b5e7a9..eab8e6aebb370 100644 --- a/libswscale/rgb2rgb.c +++ b/libswscale/rgb2rgb.c @@ -53,6 +53,10 @@ void (*rgb15to32)(const uint8_t *src, uint8_t *dst, int src_size); void (*shuffle_bytes_0321)(const uint8_t *src, uint8_t *dst, int src_size); void (*shuffle_bytes_2103)(const uint8_t *src, uint8_t *dst, int src_size); +void (*shuffle_bytes_1230)(const uint8_t *src, uint8_t *dst, int src_size); +void (*shuffle_bytes_3012)(const uint8_t *src, uint8_t *dst, int src_size); +void (*shuffle_bytes_3210)(const uint8_t *src, uint8_t *dst, int src_size); + void (*yv12toyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst, @@ -319,25 +323,6 @@ void rgb12tobgr12(const uint8_t *src, uint8_t *dst, int src_size) } } - -#define DEFINE_SHUFFLE_BYTES(a, b, c, d) \ -void shuffle_bytes_ ## a ## b ## c ## d(const uint8_t *src, \ - uint8_t *dst, int src_size) \ -{ \ - int i; \ - \ - for (i = 0; i < src_size; i += 4) { \ - dst[i + 0] = src[i + a]; \ - dst[i + 1] = src[i + b]; \ - dst[i + 2] = src[i + c]; \ - dst[i + 3] = src[i + d]; \ - } \ -} - -DEFINE_SHUFFLE_BYTES(1, 2, 3, 0) -DEFINE_SHUFFLE_BYTES(3, 0, 1, 2) -DEFINE_SHUFFLE_BYTES(3, 2, 1, 0) - #define DEFINE_RGB48TOBGR48(need_bswap, swap) \ void rgb48tobgr48_ ## need_bswap(const uint8_t *src, \ uint8_t *dst, int src_size) \ diff --git a/libswscale/rgb2rgb.h b/libswscale/rgb2rgb.h index 6994839299da3..08de5465980ad 100644 --- a/libswscale/rgb2rgb.h +++ b/libswscale/rgb2rgb.h @@ -76,9 +76,9 @@ void rgb15tobgr15(const uint8_t *src, uint8_t *dst, int src_size); void rgb12tobgr12(const uint8_t *src, uint8_t *dst, int src_size); void rgb12to15(const uint8_t *src, uint8_t *dst, int src_size); -void shuffle_bytes_1230(const uint8_t *src, uint8_t *dst, int src_size); -void shuffle_bytes_3012(const uint8_t *src, uint8_t *dst, int src_size); -void shuffle_bytes_3210(const uint8_t *src, uint8_t *dst, int src_size); +extern void (*shuffle_bytes_1230)(const uint8_t *src, uint8_t *dst, int src_size); +extern void (*shuffle_bytes_3012)(const uint8_t *src, uint8_t *dst, int src_size); +extern void (*shuffle_bytes_3210)(const uint8_t *src, uint8_t *dst, int src_size); void ff_rgb24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst, int width, int height, int lumStride, diff --git a/libswscale/rgb2rgb_template.c b/libswscale/rgb2rgb_template.c index 499d25b26d8c8..fb7d663ccc593 100644 --- a/libswscale/rgb2rgb_template.c +++ b/libswscale/rgb2rgb_template.c @@ -342,6 +342,24 @@ static inline void shuffle_bytes_0321_c(const uint8_t *src, uint8_t *dst, } } +#define DEFINE_SHUFFLE_BYTES(name, a, b, c, d) \ +static void shuffle_bytes_##name (const uint8_t *src, \ + uint8_t *dst, int src_size) \ +{ \ + int i; \ + \ + for (i = 0; i < src_size; i += 4) { \ + dst[i + 0] = src[i + a]; \ + dst[i + 1] = src[i + b]; \ + dst[i + 2] = src[i + c]; \ + dst[i + 3] = src[i + d]; \ + } \ +} + +DEFINE_SHUFFLE_BYTES(1230_c, 1, 2, 3, 0) +DEFINE_SHUFFLE_BYTES(3012_c, 3, 0, 1, 2) +DEFINE_SHUFFLE_BYTES(3210_c, 3, 2, 1, 0) + static inline void rgb24tobgr24_c(const uint8_t *src, uint8_t *dst, int src_size) { unsigned i; @@ -949,6 +967,9 @@ static av_cold void rgb2rgb_init_c(void) #else shuffle_bytes_0321 = shuffle_bytes_0321_c; shuffle_bytes_2103 = shuffle_bytes_2103_c; + shuffle_bytes_1230 = shuffle_bytes_1230_c; + shuffle_bytes_3012 = shuffle_bytes_3012_c; + shuffle_bytes_3210 = shuffle_bytes_3210_c; #endif rgb32tobgr16 = rgb32tobgr16_c; rgb32tobgr15 = rgb32tobgr15_c; From 1ba5ca2d721ebb8b80cd3c389854905e59fc7dfd Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 24 Mar 2018 20:18:05 +0100 Subject: [PATCH 2229/2557] swscale/rgb : add X86 SIMD (SSSE3), for shuffle_bytes_1230, shuffle_bytes_3012, shuffle_bytes_3210 --- libswscale/x86/rgb2rgb.c | 6 ++++++ libswscale/x86/rgb_2_rgb.asm | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/libswscale/x86/rgb2rgb.c b/libswscale/x86/rgb2rgb.c index 5caabf03ed031..e5f318a72c205 100644 --- a/libswscale/x86/rgb2rgb.c +++ b/libswscale/x86/rgb2rgb.c @@ -146,6 +146,9 @@ DECLARE_ALIGNED(8, extern const uint64_t, ff_bgr2UVOffset); void ff_shuffle_bytes_2103_ssse3(const uint8_t *src, uint8_t *dst, int src_size); void ff_shuffle_bytes_0321_ssse3(const uint8_t *src, uint8_t *dst, int src_size); +void ff_shuffle_bytes_1230_ssse3(const uint8_t *src, uint8_t *dst, int src_size); +void ff_shuffle_bytes_3012_ssse3(const uint8_t *src, uint8_t *dst, int src_size); +void ff_shuffle_bytes_3210_ssse3(const uint8_t *src, uint8_t *dst, int src_size); av_cold void rgb2rgb_init_x86(void) { @@ -167,5 +170,8 @@ av_cold void rgb2rgb_init_x86(void) if (EXTERNAL_SSSE3(cpu_flags)) { shuffle_bytes_0321 = ff_shuffle_bytes_0321_ssse3; shuffle_bytes_2103 = ff_shuffle_bytes_2103_ssse3; + shuffle_bytes_1230 = ff_shuffle_bytes_1230_ssse3; + shuffle_bytes_3012 = ff_shuffle_bytes_3012_ssse3; + shuffle_bytes_3210 = ff_shuffle_bytes_3210_ssse3; } } diff --git a/libswscale/x86/rgb_2_rgb.asm b/libswscale/x86/rgb_2_rgb.asm index e4104d9be2879..db45e313d82cd 100644 --- a/libswscale/x86/rgb_2_rgb.asm +++ b/libswscale/x86/rgb_2_rgb.asm @@ -26,6 +26,9 @@ SECTION_RODATA pb_shuffle2103: db 2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15 pb_shuffle0321: db 0, 3, 2, 1, 4, 7, 6, 5, 8, 11, 10, 9, 12, 15, 14, 13 +pb_shuffle1230: db 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12 +pb_shuffle3012: db 3, 0, 1, 2, 7, 4, 5, 6, 11, 8, 9, 10, 15, 12, 13, 14 +pb_shuffle3210: db 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 SECTION .text @@ -78,3 +81,6 @@ jge .end INIT_XMM ssse3 SHUFFLE_BYTES 2, 1, 0, 3 SHUFFLE_BYTES 0, 3, 2, 1 +SHUFFLE_BYTES 1, 2, 3, 0 +SHUFFLE_BYTES 3, 0, 1, 2 +SHUFFLE_BYTES 3, 2, 1, 0 From a9a7ed4f27d036a7719a46f3020a8faac96d0ffb Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 24 Mar 2018 20:19:00 +0100 Subject: [PATCH 2230/2557] checkasm/swscale : add test for rgb shuffle_bytes func --- tests/checkasm/Makefile | 6 +++ tests/checkasm/checkasm.c | 3 ++ tests/checkasm/checkasm.h | 1 + tests/checkasm/sw_rgb.c | 85 +++++++++++++++++++++++++++++++++++++++ tests/fate/checkasm.mak | 1 + 5 files changed, 96 insertions(+) create mode 100644 tests/checkasm/sw_rgb.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 0520e264e2a80..97fbf59636bca 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -38,6 +38,12 @@ AVFILTEROBJS-$(CONFIG_THRESHOLD_FILTER) += vf_threshold.o CHECKASMOBJS-$(CONFIG_AVFILTER) += $(AVFILTEROBJS-yes) +# swscale tests +SWSCALEOBJS += sw_rgb.o + +CHECKASMOBJS-$(CONFIG_SWSCALE) += $(SWSCALEOBJS) + +# libavutil tests AVUTILOBJS += fixed_dsp.o AVUTILOBJS += float_dsp.o diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index fe81d139c6250..20ce56932fe5d 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -163,6 +163,9 @@ static const struct { { "vf_threshold", checkasm_check_vf_threshold }, #endif #endif +#if CONFIG_SWSCALE + { "sw_rgb", checkasm_check_sw_rgb }, +#endif #if CONFIG_AVUTIL { "fixed_dsp", checkasm_check_fixed_dsp }, { "float_dsp", checkasm_check_float_dsp }, diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 8b9d96bc1525b..dcab74de06019 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -65,6 +65,7 @@ void checkasm_check_llviddspenc(void); void checkasm_check_pixblockdsp(void); void checkasm_check_sbrdsp(void); void checkasm_check_synth_filter(void); +void checkasm_check_sw_rgb(void); void checkasm_check_utvideodsp(void); void checkasm_check_v210enc(void); void checkasm_check_vf_hflip(void); diff --git a/tests/checkasm/sw_rgb.c b/tests/checkasm/sw_rgb.c new file mode 100644 index 0000000000000..8fc2cfee9e4ba --- /dev/null +++ b/tests/checkasm/sw_rgb.c @@ -0,0 +1,85 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" + +#include "libswscale/rgb2rgb.h" + +#include "checkasm.h" + +#define randomize_buffers(buf, size) \ + do { \ + int j; \ + for (j = 0; j < size; j+=4) \ + AV_WN32(buf + j, rnd()); \ + } while (0) + +static const uint8_t width[] = {12, 16, 20, 32, 36, 128}; + +#define MAX_STRIDE 128 + +static void check_shuffle_bytes(void * func, const char * report) +{ + int i; + LOCAL_ALIGNED_32(uint8_t, src0, [MAX_STRIDE]); + LOCAL_ALIGNED_32(uint8_t, src1, [MAX_STRIDE]); + LOCAL_ALIGNED_32(uint8_t, dst0, [MAX_STRIDE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [MAX_STRIDE]); + + declare_func_emms(AV_CPU_FLAG_MMX, void, const uint8_t *src, uint8_t *dst, int src_size); + + memset(dst0, 0, MAX_STRIDE); + memset(dst1, 0, MAX_STRIDE); + randomize_buffers(src0, MAX_STRIDE); + memcpy(src1, src0, MAX_STRIDE); + + if (check_func(func, "%s", report)) { + for (i = 0; i < 6; i ++) { + call_ref(src0, dst0, width[i]); + call_new(src1, dst1, width[i]); + if (memcmp(dst0, dst1, MAX_STRIDE)) + fail(); + } + bench_new(src0, dst0, width[5]); + } +} + +void checkasm_check_sw_rgb(void) +{ + ff_sws_rgb2rgb_init(); + + check_shuffle_bytes(shuffle_bytes_2103, "shuffle_bytes_2103"); + report("shuffle_bytes_2103"); + + check_shuffle_bytes(shuffle_bytes_0321, "shuffle_bytes_0321"); + report("shuffle_bytes_0321"); + + check_shuffle_bytes(shuffle_bytes_1230, "shuffle_bytes_1230"); + report("shuffle_bytes_1230"); + + check_shuffle_bytes(shuffle_bytes_3012, "shuffle_bytes_3012"); + report("shuffle_bytes_3012"); + + check_shuffle_bytes(shuffle_bytes_3210, "shuffle_bytes_3210"); + report("shuffle_bytes_3210"); +} diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index cf62f9b1190f5..a722b4a9172f7 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -21,6 +21,7 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp \ fate-checkasm-pixblockdsp \ fate-checkasm-sbrdsp \ fate-checkasm-synth_filter \ + fate-checkasm-sw_rgb \ fate-checkasm-v210enc \ fate-checkasm-vf_blend \ fate-checkasm-vf_colorspace \ From 5f6126ea7f31db38a796ea5533a06b6526e13ecf Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 24 Mar 2018 20:20:04 +0100 Subject: [PATCH 2231/2557] swscale/rgb2rgb : cosmetic, move shuffle_bytes func declaration move shuffle_bytes_1230, 3012, 3210 with the other shuffle_byte declaration --- libswscale/rgb2rgb.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libswscale/rgb2rgb.h b/libswscale/rgb2rgb.h index 08de5465980ad..3569254df93ac 100644 --- a/libswscale/rgb2rgb.h +++ b/libswscale/rgb2rgb.h @@ -52,6 +52,9 @@ extern void (*rgb32tobgr15)(const uint8_t *src, uint8_t *dst, int src_size); extern void (*shuffle_bytes_0321)(const uint8_t *src, uint8_t *dst, int src_size); extern void (*shuffle_bytes_2103)(const uint8_t *src, uint8_t *dst, int src_size); +extern void (*shuffle_bytes_1230)(const uint8_t *src, uint8_t *dst, int src_size); +extern void (*shuffle_bytes_3012)(const uint8_t *src, uint8_t *dst, int src_size); +extern void (*shuffle_bytes_3210)(const uint8_t *src, uint8_t *dst, int src_size); void rgb64tobgr48_nobswap(const uint8_t *src, uint8_t *dst, int src_size); void rgb64tobgr48_bswap(const uint8_t *src, uint8_t *dst, int src_size); @@ -76,10 +79,6 @@ void rgb15tobgr15(const uint8_t *src, uint8_t *dst, int src_size); void rgb12tobgr12(const uint8_t *src, uint8_t *dst, int src_size); void rgb12to15(const uint8_t *src, uint8_t *dst, int src_size); -extern void (*shuffle_bytes_1230)(const uint8_t *src, uint8_t *dst, int src_size); -extern void (*shuffle_bytes_3012)(const uint8_t *src, uint8_t *dst, int src_size); -extern void (*shuffle_bytes_3210)(const uint8_t *src, uint8_t *dst, int src_size); - void ff_rgb24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst, int width, int height, int lumStride, int chromStride, int srcStride, int32_t *rgb2yuv); From 87455b78cc5191d59394f27751da85d588f05d07 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 17 Mar 2018 12:41:15 +0100 Subject: [PATCH 2232/2557] avdevice/decklink: fix leak when listing devices and there is no memory Fixes Coverity CID 1419523. Signed-off-by: Marton Balint --- libavdevice/decklink_common.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp index da414ed5f8b81..b889033cf8ea7 100644 --- a/libavdevice/decklink_common.cpp +++ b/libavdevice/decklink_common.cpp @@ -322,21 +322,14 @@ int ff_decklink_list_devices(AVFormatContext *avctx, ret = AVERROR(ENOMEM); goto next; } - new_device->device_name = av_strdup(displayName); - if (!new_device->device_name) { - ret = AVERROR(ENOMEM); - goto next; - } + new_device->device_name = av_strdup(displayName); new_device->device_description = av_strdup(displayName); - if (!new_device->device_description) { - av_freep(&new_device->device_name); - ret = AVERROR(ENOMEM); - goto next; - } - if ((ret = av_dynarray_add_nofree(&device_list->devices, - &device_list->nb_devices, new_device)) < 0) { + if (!new_device->device_name || + !new_device->device_description || + av_dynarray_add_nofree(&device_list->devices, &device_list->nb_devices, new_device) < 0) { + ret = AVERROR(ENOMEM); av_freep(&new_device->device_name); av_freep(&new_device->device_description); av_freep(&new_device); From 5b31dd1c6b1e35d91ce068d6cd20eb4a3d3faa38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Fri, 23 Mar 2018 14:41:28 +0200 Subject: [PATCH 2233/2557] avformat/hlsenc: use stream's maximum bit rate as fall-back advertised rate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enables having proper bit rate values being written into the master playlist in case of hard-constrained VBR where the maximum bit rate utilized is known before hand. Does the same thing as movenc.c, for example. Signed-off-by: Jan Ekström --- libavformat/hlsenc.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index b7c6fbde6ae76..34fa848466c5a 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1174,6 +1174,21 @@ static int get_relative_url(const char *master_url, const char *media_url, return 0; } +static int64_t get_stream_bit_rate(AVStream *stream) { + AVCPBProperties *props = (AVCPBProperties*)av_stream_get_side_data( + stream, + AV_PKT_DATA_CPB_PROPERTIES, + NULL + ); + + if (stream->codecpar->bit_rate) + return stream->codecpar->bit_rate; + else if (props) + return props->max_bitrate; + + return 0; +} + static int create_master_playlist(AVFormatContext *s, VariantStream * const input_vs) { @@ -1300,9 +1315,9 @@ static int create_master_playlist(AVFormatContext *s, bandwidth = 0; if (vid_st) - bandwidth += vid_st->codecpar->bit_rate; + bandwidth += get_stream_bit_rate(vid_st); if (aud_st) - bandwidth += aud_st->codecpar->bit_rate; + bandwidth += get_stream_bit_rate(aud_st); bandwidth += bandwidth / 10; ccgroup = NULL; From b7d0d912ef9b60eae962e4622d72860af31a8b00 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 24 Mar 2018 13:37:00 +0100 Subject: [PATCH 2234/2557] avcodec: add a subcharenc mode that disables UTF-8 check This is for applications which want to explicitly check for invalid UTF-8 manually, and take actions that are better than dropping invalid subtitles silently. (It's pretty much silent because sporadic avcodec error messages are so common that you can't reasonably display them in a prominent and meaningful way in a application GUI.) --- doc/APIchanges | 3 +++ libavcodec/avcodec.h | 1 + libavcodec/decode.c | 3 ++- libavcodec/options_table.h | 1 + libavcodec/version.h | 2 +- 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index a099afd9bc81b..95b5cd772ff4b 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-03-xx - xxxxxxx - lavc 58.16.100 - avcodec.h + Add FF_SUB_CHARENC_MODE_IGNORE. + 2018-xx-xx - xxxxxxx - lavu 56.8.100 - encryption_info.h Add AVEncryptionInitInfo and AVEncryptionInfo structures to hold new side-data for encryption info. diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 495242faf04e8..50c34dbff9123 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3092,6 +3092,7 @@ typedef struct AVCodecContext { #define FF_SUB_CHARENC_MODE_DO_NOTHING -1 ///< do nothing (demuxer outputs a stream supposed to be already in UTF-8, or the codec is bitmap for instance) #define FF_SUB_CHARENC_MODE_AUTOMATIC 0 ///< libavcodec will select the mode itself #define FF_SUB_CHARENC_MODE_PRE_DECODER 1 ///< the AVPacket data needs to be recoded to UTF-8 before being fed to the decoder, requires iconv +#define FF_SUB_CHARENC_MODE_IGNORE 2 ///< neither convert the subtitles, nor check them for valid UTF-8 /** * Skip processing alpha if supported by codec. diff --git a/libavcodec/decode.c b/libavcodec/decode.c index ea2168ad0cc70..40c8a8855c0f5 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1057,7 +1057,8 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, sub->format = 1; for (i = 0; i < sub->num_rects; i++) { - if (sub->rects[i]->ass && !utf8_check(sub->rects[i]->ass)) { + if (avctx->sub_charenc_mode != FF_SUB_CHARENC_MODE_IGNORE && + sub->rects[i]->ass && !utf8_check(sub->rects[i]->ass)) { av_log(avctx, AV_LOG_ERROR, "Invalid UTF-8 in decoded subtitles text; " "maybe missing -sub_charenc option\n"); diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 5a5eae65fba41..099261e1684aa 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -447,6 +447,7 @@ static const AVOption avcodec_options[] = { {"do_nothing", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_DO_NOTHING}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, {"auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_AUTOMATIC}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, {"pre_decoder", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_PRE_DECODER}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, +{"ignore", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_IGNORE}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, #if FF_API_ASS_TIMING {"sub_text_format", "set decoded text subtitle format", OFFSET(sub_text_format), AV_OPT_TYPE_INT, {.i64 = FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS}, 0, 1, S|D, "sub_text_format"}, #else diff --git a/libavcodec/version.h b/libavcodec/version.h index a5b7f752d1666..8ac4626da79a4 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 15 +#define LIBAVCODEC_VERSION_MINOR 16 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From b0644c3e1a96397ee5e2448c542fa4c3bc319537 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 24 Mar 2018 15:41:54 +0100 Subject: [PATCH 2235/2557] movtextdec: fix handling of UTF-8 subtitles Subtitles which contained styled UTF-8 subtitles (i.e. not just 7 bit ASCII characters) were not handled correctly. The spec mandates that styling start/end ranges are in "characters". It's not quite clear what a "character" is supposed to be, but maybe they mean unicode codepoints. FFmpeg's decoder treated the style ranges as byte idexes, which could lead to UTF-8 sequences being broken, and the common code dropping the whole subtitle line. Change this and count the codepoint instead. This also means that even if this is somehow wrong, the decoder won't break UTF-8 sequences anymore. The sample which led me to investigate this now appears to work correctly. --- libavcodec/movtextdec.c | 50 ++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index bd19577724e23..89ac791602c65 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -326,9 +326,24 @@ static const Box box_types[] = { const static size_t box_count = FF_ARRAY_ELEMS(box_types); +// Return byte length of the UTF-8 sequence starting at text[0]. 0 on error. +static int get_utf8_length_at(const char *text, const char *text_end) +{ + const char *start = text; + int err = 0; + uint32_t c; + GET_UTF8(c, text < text_end ? (uint8_t)*text++ : (err = 1, 0), goto error;); + if (err) + goto error; + return text - start; +error: + return 0; +} + static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, - MovTextContext *m) + AVCodecContext *avctx) { + MovTextContext *m = avctx->priv_data; int i = 0; int j = 0; int text_pos = 0; @@ -342,6 +357,8 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, } while (text < text_end) { + int len; + if (m->box_flags & STYL_BOX) { for (i = 0; i < m->style_entries; i++) { if (m->s[i]->style_flag && text_pos == m->s[i]->style_end) { @@ -388,17 +405,24 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, } } - switch (*text) { - case '\r': - break; - case '\n': - av_bprintf(buf, "\\N"); - break; - default: - av_bprint_chars(buf, *text, 1); - break; + len = get_utf8_length_at(text, text_end); + if (len < 1) { + av_log(avctx, AV_LOG_ERROR, "invalid UTF-8 byte in subtitle\n"); + len = 1; + } + for (i = 0; i < len; i++) { + switch (*text) { + case '\r': + break; + case '\n': + av_bprintf(buf, "\\N"); + break; + default: + av_bprint_chars(buf, *text, 1); + break; + } + text++; } - text++; text_pos++; } @@ -507,10 +531,10 @@ static int mov_text_decode_frame(AVCodecContext *avctx, } m->tracksize = m->tracksize + tsmb_size; } - text_to_ass(&buf, ptr, end, m); + text_to_ass(&buf, ptr, end, avctx); mov_text_cleanup(m); } else - text_to_ass(&buf, ptr, end, m); + text_to_ass(&buf, ptr, end, avctx); ret = ff_ass_add_rect(sub, buf.str, m->readorder++, 0, NULL, NULL); av_bprint_finalize(&buf, NULL); From 261171d084bc89313c1fb9ace643243959aeef9f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 25 Mar 2018 23:10:59 +0200 Subject: [PATCH 2236/2557] doc/filter.texi: fix some spotted typos Signed-off-by: Paul B Mahol --- doc/filters.texi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 1620ae1cfa7bd..5c119c015194a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -509,7 +509,7 @@ An Anti-Aliasing setting is able to produce "softer" crushing sounds. Another feature of this filter is the logarithmic mode. This setting switches from linear distances between bits to logarithmic ones. The result is a much more "natural" sounding crusher which doesn't gate low -signals for example. The human ear has a logarithmic perception, too +signals for example. The human ear has a logarithmic perception, so this kind of crushing is much more pleasant. Logarithmic crushing is also able to get anti-aliased. @@ -3606,7 +3606,7 @@ lv2=p=http\\\\://calf.sourceforge.net/plugins/BassEnhancer:c=amount=2 @end example @item -Apply bass vinyl plugin from Calf: +Apply vinyl plugin from Calf: @example lv2=p=http\\\\://calf.sourceforge.net/plugins/Vinyl:c=drone=0.2|aging=0.5 @end example @@ -20056,7 +20056,7 @@ Scale pixel values for each drawn sample. Draw every sample directly. @end table -Default vlaue is @code{scale}. +Default value is @code{scale}. @end table @subsection Examples From 78f8036c9c1f7375a0ff8aefe2030f160dbedf36 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 25 Mar 2018 23:26:26 +0200 Subject: [PATCH 2237/2557] avfilter/af_mcompand: make error message more helpful Signed-off-by: Paul B Mahol --- libavfilter/af_mcompand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_mcompand.c b/libavfilter/af_mcompand.c index 02f987a6a8630..f142573beabdd 100644 --- a/libavfilter/af_mcompand.c +++ b/libavfilter/af_mcompand.c @@ -456,7 +456,7 @@ static int config_output(AVFilterLink *outlink) new_nb_items += sscanf(tstr2, "%lf", &s->bands[i].topfreq) == 1; if (s->bands[i].topfreq < 0 || s->bands[i].topfreq >= outlink->sample_rate / 2) { - av_log(ctx, AV_LOG_ERROR, "crossover_frequency should be >=0 and lower than half of sample rate\n"); + av_log(ctx, AV_LOG_ERROR, "crossover_frequency: %f, should be >=0 and lower than half of sample rate: %d.\n", s->bands[i].topfreq, outlink->sample_rate / 2); uninit(ctx); return AVERROR(EINVAL); } From e529fe7633762cb26a665fb6dee3be29b15285cc Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 24 Mar 2018 01:38:53 +0100 Subject: [PATCH 2238/2557] avcodec/get_bits: Make sure the input bitstream with padding can be addressed Signed-off-by: Michael Niedermayer --- libavcodec/get_bits.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 0c7f5ff0c6011..d7cf2863783b0 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -32,6 +32,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/log.h" #include "libavutil/avassert.h" +#include "avcodec.h" #include "mathops.h" #include "vlc.h" @@ -428,7 +429,7 @@ static inline int init_get_bits(GetBitContext *s, const uint8_t *buffer, int buffer_size; int ret = 0; - if (bit_size >= INT_MAX - 7 || bit_size < 0 || !buffer) { + if (bit_size >= INT_MAX - FFMAX(7, AV_INPUT_BUFFER_PADDING_SIZE*8) || bit_size < 0 || !buffer) { bit_size = 0; buffer = NULL; ret = AVERROR_INVALIDDATA; From eb60b9d3aaaa42265fb1960be6fff6383cfdbf37 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 3 Feb 2018 21:36:22 +0100 Subject: [PATCH 2239/2557] avformat/mov: Move +1 in check to avoid hypothetical overflow in add_ctts_entry() Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 33126781a00c7..cb6f3a45de218 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3256,7 +3256,7 @@ static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, uns FFMAX(min_size_needed, 2 * (*allocated_size)) : min_size_needed; - if((unsigned)(*ctts_count) + 1 >= UINT_MAX / sizeof(MOVStts)) + if((unsigned)(*ctts_count) >= UINT_MAX / sizeof(MOVStts) - 1) return -1; ctts_buf_new = av_fast_realloc(*ctts_data, allocated_size, requested_size); From db772308941a2a338c7809f90d347219a6a93074 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 10 Mar 2018 18:03:09 +0100 Subject: [PATCH 2240/2557] avcodec/mpeg4videodec: Use more specific error codes Forward error codes where possible. Signed-off-by: Michael Niedermayer --- libavcodec/mpeg4video.h | 4 +- libavcodec/mpeg4videodec.c | 100 +++++++++++++++++++------------------ 2 files changed, 53 insertions(+), 51 deletions(-) diff --git a/libavcodec/mpeg4video.h b/libavcodec/mpeg4video.h index 0ba502d50bdd5..6672c6dd66dbd 100644 --- a/libavcodec/mpeg4video.h +++ b/libavcodec/mpeg4video.h @@ -239,12 +239,12 @@ static inline int ff_mpeg4_pred_dc(MpegEncContext *s, int n, int level, if (level < 0) { av_log(s->avctx, AV_LOG_ERROR, "dc<0 at %dx%d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } if (level > 2048 + scale) { av_log(s->avctx, AV_LOG_ERROR, "dc overflow at %dx%d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } } if (level < 0) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 19210d97fe665..a1117dc272d76 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -448,7 +448,7 @@ int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx) /* is there enough space left for a video packet + header */ if (get_bits_count(&s->gb) > s->gb.size_in_bits - 20) - return -1; + return AVERROR_INVALIDDATA; for (len = 0; len < 32; len++) if (get_bits1(&s->gb)) @@ -456,7 +456,7 @@ int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx) if (len != ff_mpeg4_get_video_packet_prefix_length(s)) { av_log(s->avctx, AV_LOG_ERROR, "marker does not match f_code\n"); - return -1; + return AVERROR_INVALIDDATA; } if (ctx->shape != RECT_SHAPE) { @@ -468,7 +468,7 @@ int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx) if (mb_num >= s->mb_num || !mb_num) { av_log(s->avctx, AV_LOG_ERROR, "illegal mb_num in video packet (%d %d) \n", mb_num, s->mb_num); - return -1; + return AVERROR_INVALIDDATA; } s->mb_x = mb_num % s->mb_width; @@ -597,7 +597,7 @@ static inline int mpeg4_decode_dc(MpegEncContext *s, int n, int *dir_ptr) if (code < 0 || code > 9 /* && s->nbit < 9 */) { av_log(s->avctx, AV_LOG_ERROR, "illegal dc vlc\n"); - return -1; + return AVERROR_INVALIDDATA; } if (code == 0) { @@ -620,7 +620,7 @@ static inline int mpeg4_decode_dc(MpegEncContext *s, int n, int *dir_ptr) if (get_bits1(&s->gb) == 0) { /* marker */ if (s->avctx->err_recognition & (AV_EF_BITSTREAM|AV_EF_COMPLIANT)) { av_log(s->avctx, AV_LOG_ERROR, "dc marker bit missing\n"); - return -1; + return AVERROR_INVALIDDATA; } } } @@ -664,7 +664,7 @@ static int mpeg4_decode_partition_a(Mpeg4DecContext *ctx) if (cbpc < 0) { av_log(s->avctx, AV_LOG_ERROR, "mcbpc corrupted at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } } while (cbpc == 8); @@ -684,7 +684,7 @@ static int mpeg4_decode_partition_a(Mpeg4DecContext *ctx) if (dc < 0) { av_log(s->avctx, AV_LOG_ERROR, "DC corrupted at %d %d\n", s->mb_x, s->mb_y); - return -1; + return dc; } dir <<= 1; if (dc_pred_dir) @@ -736,7 +736,7 @@ static int mpeg4_decode_partition_a(Mpeg4DecContext *ctx) if (cbpc < 0) { av_log(s->avctx, AV_LOG_ERROR, "mcbpc corrupted at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } if (cbpc == 20) goto try_again; @@ -774,11 +774,11 @@ static int mpeg4_decode_partition_a(Mpeg4DecContext *ctx) if (!s->mcsel) { mx = ff_h263_decode_motion(s, pred_x, s->f_code); if (mx >= 0xffff) - return -1; + return AVERROR_INVALIDDATA; my = ff_h263_decode_motion(s, pred_y, s->f_code); if (my >= 0xffff) - return -1; + return AVERROR_INVALIDDATA; s->current_picture.mb_type[xy] = MB_TYPE_16x16 | MB_TYPE_L0; } else { @@ -805,11 +805,11 @@ static int mpeg4_decode_partition_a(Mpeg4DecContext *ctx) int16_t *mot_val = ff_h263_pred_motion(s, i, 0, &pred_x, &pred_y); mx = ff_h263_decode_motion(s, pred_x, s->f_code); if (mx >= 0xffff) - return -1; + return AVERROR_INVALIDDATA; my = ff_h263_decode_motion(s, pred_y, s->f_code); if (my >= 0xffff) - return -1; + return AVERROR_INVALIDDATA; mot_val[0] = mx; mot_val[1] = my; } @@ -850,7 +850,7 @@ static int mpeg4_decode_partition_b(MpegEncContext *s, int mb_count) if (cbpy < 0) { av_log(s->avctx, AV_LOG_ERROR, "cbpy corrupted at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } s->cbp_table[xy] |= cbpy << 2; @@ -865,7 +865,7 @@ static int mpeg4_decode_partition_b(MpegEncContext *s, int mb_count) if (cbpy < 0) { av_log(s->avctx, AV_LOG_ERROR, "I cbpy corrupted at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } if (s->cbp_table[xy] & 8) @@ -878,7 +878,7 @@ static int mpeg4_decode_partition_b(MpegEncContext *s, int mb_count) if (dc < 0) { av_log(s->avctx, AV_LOG_ERROR, "DC corrupted at %d %d\n", s->mb_x, s->mb_y); - return -1; + return dc; } dir <<= 1; if (dc_pred_dir) @@ -897,7 +897,7 @@ static int mpeg4_decode_partition_b(MpegEncContext *s, int mb_count) if (cbpy < 0) { av_log(s->avctx, AV_LOG_ERROR, "P cbpy corrupted at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } if (s->cbp_table[xy] & 8) @@ -924,6 +924,7 @@ int ff_mpeg4_decode_partitions(Mpeg4DecContext *ctx) { MpegEncContext *s = &ctx->m; int mb_num; + int ret; const int part_a_error = s->pict_type == AV_PICTURE_TYPE_I ? (ER_DC_ERROR | ER_MV_ERROR) : ER_MV_ERROR; const int part_a_end = s->pict_type == AV_PICTURE_TYPE_I ? (ER_DC_END | ER_MV_END) : ER_MV_END; @@ -931,14 +932,14 @@ int ff_mpeg4_decode_partitions(Mpeg4DecContext *ctx) if (mb_num <= 0) { ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, part_a_error); - return -1; + return mb_num ? mb_num : AVERROR_INVALIDDATA; } if (s->resync_mb_x + s->resync_mb_y * s->mb_width + mb_num > s->mb_num) { av_log(s->avctx, AV_LOG_ERROR, "slice below monitor ...\n"); ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, part_a_error); - return -1; + return AVERROR_INVALIDDATA; } s->mb_num_left = mb_num; @@ -950,7 +951,7 @@ int ff_mpeg4_decode_partitions(Mpeg4DecContext *ctx) av_log(s->avctx, AV_LOG_ERROR, "marker missing after first I partition at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } } else { while (show_bits(&s->gb, 10) == 1) @@ -959,17 +960,18 @@ int ff_mpeg4_decode_partitions(Mpeg4DecContext *ctx) av_log(s->avctx, AV_LOG_ERROR, "marker missing after first P partition at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } } ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x - 1, s->mb_y, part_a_end); - if (mpeg4_decode_partition_b(s, mb_num) < 0) { + ret = mpeg4_decode_partition_b(s, mb_num); + if (ret < 0) { if (s->pict_type == AV_PICTURE_TYPE_P) ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_DC_ERROR); - return -1; + return ret; } else { if (s->pict_type == AV_PICTURE_TYPE_P) ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, @@ -1008,7 +1010,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, } else { level = mpeg4_decode_dc(s, n, &dc_pred_dir); if (level < 0) - return -1; + return level; } block[0] = level; i = 0; @@ -1076,7 +1078,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, if (SHOW_UBITS(re, &s->gb, 1) == 0) { av_log(s->avctx, AV_LOG_ERROR, "1. marker bit missing in rvlc esc\n"); - return -1; + return AVERROR_INVALIDDATA; } SKIP_CACHE(re, &s->gb, 1); @@ -1089,7 +1091,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, if (SHOW_UBITS(re, &s->gb, 1) == 0) { av_log(s->avctx, AV_LOG_ERROR, "2. marker bit missing in rvlc esc\n"); - return -1; + return AVERROR_INVALIDDATA; } SKIP_CACHE(re, &s->gb, 1); @@ -1098,7 +1100,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, if (SHOW_UBITS(re, &s->gb, 5) != 0x10) { av_log(s->avctx, AV_LOG_ERROR, "reverse esc missing\n"); - return -1; + return AVERROR_INVALIDDATA; } SKIP_CACHE(re, &s->gb, 5); @@ -1134,7 +1136,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, av_log(s->avctx, AV_LOG_ERROR, "1. marker bit missing in 3. esc\n"); if (!(s->avctx->err_recognition & AV_EF_IGNORE_ERR)) - return -1; + return AVERROR_INVALIDDATA; } SKIP_CACHE(re, &s->gb, 1); @@ -1145,7 +1147,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, av_log(s->avctx, AV_LOG_ERROR, "2. marker bit missing in 3. esc\n"); if (!(s->avctx->err_recognition & AV_EF_IGNORE_ERR)) - return -1; + return AVERROR_INVALIDDATA; } SKIP_COUNTER(re, &s->gb, 1 + 12 + 1); @@ -1158,16 +1160,16 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, const int run1= run - rl->max_run[last][abs_level] - 1; if (abs_level <= rl->max_level[last][run]) { av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, vlc encoding possible\n"); - return -1; + return AVERROR_INVALIDDATA; } if (s->error_recognition > FF_ER_COMPLIANT) { if (abs_level <= rl->max_level[last][run]*2) { av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, esc 1 encoding possible\n"); - return -1; + return AVERROR_INVALIDDATA; } if (run1 >= 0 && abs_level <= rl->max_level[last][run1]) { av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, esc 2 encoding possible\n"); - return -1; + return AVERROR_INVALIDDATA; } } } @@ -1184,7 +1186,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, av_log(s->avctx, AV_LOG_ERROR, "|level| overflow in 3. esc, qp=%d\n", s->qscale); - return -1; + return AVERROR_INVALIDDATA; } } level = level < 0 ? -2048 : 2047; @@ -1222,7 +1224,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, if (i & (~63)) { av_log(s->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } block[scan_table[i]] = level; @@ -1319,7 +1321,7 @@ static int mpeg4_decode_partitioned_mb(MpegEncContext *s, int16_t block[6][64]) av_log(s->avctx, AV_LOG_ERROR, "texture corrupted at %d %d %d\n", s->mb_x, s->mb_y, s->mb_intra); - return -1; + return AVERROR_INVALIDDATA; } cbp += cbp; } @@ -1387,7 +1389,7 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) if (cbpc < 0) { av_log(s->avctx, AV_LOG_ERROR, "mcbpc damaged at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } } while (cbpc == 20); @@ -1443,11 +1445,11 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) for (i = 0; i < 2; i++) { mx = ff_h263_decode_motion(s, pred_x, s->f_code); if (mx >= 0xffff) - return -1; + return AVERROR_INVALIDDATA; my = ff_h263_decode_motion(s, pred_y / 2, s->f_code); if (my >= 0xffff) - return -1; + return AVERROR_INVALIDDATA; s->mv[0][i][0] = mx; s->mv[0][i][1] = my; @@ -1460,12 +1462,12 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) mx = ff_h263_decode_motion(s, pred_x, s->f_code); if (mx >= 0xffff) - return -1; + return AVERROR_INVALIDDATA; my = ff_h263_decode_motion(s, pred_y, s->f_code); if (my >= 0xffff) - return -1; + return AVERROR_INVALIDDATA; s->mv[0][0][0] = mx; s->mv[0][0][1] = my; } @@ -1476,11 +1478,11 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) mot_val = ff_h263_pred_motion(s, i, 0, &pred_x, &pred_y); mx = ff_h263_decode_motion(s, pred_x, s->f_code); if (mx >= 0xffff) - return -1; + return AVERROR_INVALIDDATA; my = ff_h263_decode_motion(s, pred_y, s->f_code); if (my >= 0xffff) - return -1; + return AVERROR_INVALIDDATA; s->mv[0][i][0] = mx; s->mv[0][i][1] = my; mot_val[0] = mx; @@ -1536,7 +1538,7 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) mb_type = get_vlc2(&s->gb, mb_type_b_vlc.table, MB_TYPE_B_VLC_BITS, 1); if (mb_type < 0) { av_log(s->avctx, AV_LOG_ERROR, "illegal MB_type\n"); - return -1; + return AVERROR_INVALIDDATA; } mb_type = mb_type_b_map[mb_type]; if (modb2) { @@ -1647,7 +1649,7 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) if (cbpc < 0) { av_log(s->avctx, AV_LOG_ERROR, "I cbpc damaged at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } } while (cbpc == 8); @@ -1665,7 +1667,7 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) if (cbpy < 0) { av_log(s->avctx, AV_LOG_ERROR, "I cbpy damaged at %d %d\n", s->mb_x, s->mb_y); - return -1; + return AVERROR_INVALIDDATA; } cbp = (cbpc & 3) | (cbpy << 2); @@ -1681,7 +1683,7 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) /* decode each block */ for (i = 0; i < 6; i++) { if (mpeg4_decode_block(ctx, block[i], i, cbp & 32, 1, 0) < 0) - return -1; + return AVERROR_INVALIDDATA; cbp += cbp; } goto end; @@ -1690,7 +1692,7 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) /* decode each block */ for (i = 0; i < 6; i++) { if (mpeg4_decode_block(ctx, block[i], i, cbp & 32, 0, 0) < 0) - return -1; + return AVERROR_INVALIDDATA; cbp += cbp; } @@ -1700,7 +1702,7 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) int next = mpeg4_is_resync(ctx); if (next) { if (s->mb_x + s->mb_y*s->mb_width + 1 > next && (s->avctx->err_recognition & AV_EF_AGGRESSIVE)) { - return -1; + return AVERROR_INVALIDDATA; } else if (s->mb_x + s->mb_y*s->mb_width + 1 >= next) return SLICE_END; @@ -1727,7 +1729,7 @@ static int mpeg4_decode_gop_header(MpegEncContext *s, GetBitContext *gb) if (!show_bits(gb, 23)) { av_log(s->avctx, AV_LOG_WARNING, "GOP header invalid\n"); - return -1; + return AVERROR_INVALIDDATA; } hours = get_bits(gb, 5); @@ -2636,7 +2638,7 @@ int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb) av_log(s->avctx, AV_LOG_VERBOSE, "frame skip %d\n", gb->size_in_bits); return FRAME_SKIPPED; // divx bug } else - return -1; // end of stream + return AVERROR_INVALIDDATA; // end of stream } /* use the bits after the test */ From 3eff98c9278804b4b664bad3853e5e60184c6a54 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 26 Mar 2018 00:52:39 -0300 Subject: [PATCH 2241/2557] avformat/rtpenc_chain: use the proper function to free AVFormatContext Fixes ticket #7075 Signed-off-by: James Almer --- libavformat/rtpenc_chain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/rtpenc_chain.c b/libavformat/rtpenc_chain.c index f768fb002ebcb..e69fdc27cfb7f 100644 --- a/libavformat/rtpenc_chain.c +++ b/libavformat/rtpenc_chain.c @@ -101,7 +101,7 @@ int ff_rtp_chain_mux_open(AVFormatContext **out, AVFormatContext *s, return 0; fail: - av_free(rtpctx); + avformat_free_context(rtpctx); if (handle) ffurl_close(handle); return ret; From 3c245707bd48291af544683bc875e531dd83d5d1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 26 Mar 2018 12:51:25 -0300 Subject: [PATCH 2242/2557] avcodec/avdct: use the proper function to free AVCodecContext Fixes ticket #7074 Signed-off-by: James Almer --- libavcodec/avdct.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/avdct.c b/libavcodec/avdct.c index 860f86595d3ce..47e5f7134ea26 100644 --- a/libavcodec/avdct.c +++ b/libavcodec/avdct.c @@ -123,8 +123,7 @@ int avcodec_dct_init(AVDCT *dsp) } #endif - avcodec_close(avctx); - av_free(avctx); + avcodec_free_context(&avctx); return 0; } From 5292e97c42b05db7ad4e51c1ea756b12fdf721ff Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 9 Mar 2018 17:19:15 +0100 Subject: [PATCH 2243/2557] configure: Document available options for the --toolchain parameter --- configure | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure b/configure index 78a2065208de9..d8c3b555cc4ed 100755 --- a/configure +++ b/configure @@ -260,6 +260,10 @@ Toolchain options: --target-path=DIR path to view of build directory on target --target-samples=DIR path to samples directory on target --toolchain=NAME set tool defaults according to NAME + (gcc-asan, clang-asan, gcc-msan, clang-msan, + gcc-tsan, clang-tsan, gcc-usan, clang-usan, + valgrind-massif, valgrind-memcheck, + msvc, icl, gcov, llvm-cov, hardened) --nm=NM use nm tool --ar=AR use archive tool AR [$ar_default] --as=AS use assembler AS [$as_default] From b9ea301e02472d0982b0fa0f80294bd95885bde8 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 9 Mar 2018 17:28:51 +0100 Subject: [PATCH 2244/2557] configure: Use a more sensible suffix for x86 assembly tempfiles --- configure | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index d8c3b555cc4ed..2dc7dd3f8c2a7 100755 --- a/configure +++ b/configure @@ -846,10 +846,10 @@ check_insn(){ test_x86asm(){ log test_x86asm "$@" - echo "$1" > $TMPS - log_file $TMPS + echo "$1" > $TMPASM + log_file $TMPASM shift 1 - test_cmd $x86asmexe $X86ASMFLAGS "$@" -o $TMPO $TMPS + test_cmd $x86asmexe $X86ASMFLAGS "$@" -o $TMPO $TMPASM } ld_o(){ From 17ee5b0c13bc17465b71bc9ca1cde9f0eed8b3ff Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 14 Mar 2018 14:47:43 +0100 Subject: [PATCH 2245/2557] configure: Use indirection for the -o assembler flag also for x86asm Similar indirections are used for the -o compiler/assembler flag to account for differences in compiler/assembler syntax. For x86asm half the infrastructure for doing the same currently exists unused. Finish and use that infrastructure for consistency. --- configure | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 2dc7dd3f8c2a7..844c3beb07acb 100755 --- a/configure +++ b/configure @@ -844,12 +844,16 @@ check_insn(){ check_as ${1}_external "$2" } +x86asm_o(){ + eval printf '%s\\n' $X86ASM_O +} + test_x86asm(){ log test_x86asm "$@" echo "$1" > $TMPASM log_file $TMPASM shift 1 - test_cmd $x86asmexe $X86ASMFLAGS "$@" -o $TMPO $TMPASM + test_cmd $x86asmexe $X86ASMFLAGS "$@" $(x86asm_o $TMPO) $TMPASM } ld_o(){ From 8c7554e6a9b126bd6ee5bf80dae9e11e056db2f1 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 21 Oct 2017 01:07:34 +0200 Subject: [PATCH 2246/2557] configure: Add check_x86asm() helper function to simplify some expressions --- configure | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/configure b/configure index 844c3beb07acb..4e6b880b14add 100755 --- a/configure +++ b/configure @@ -808,6 +808,18 @@ test_as(){ test_cmd $as $CPPFLAGS $ASFLAGS "$@" $AS_C $(as_o $TMPO) $TMPS } +x86asm_o(){ + eval printf '%s\\n' $X86ASM_O +} + +test_x86asm(){ + log test_x86asm "$@" + echo "$1" > $TMPASM + log_file $TMPASM + shift + test_cmd $x86asmexe $X86ASMFLAGS "$@" $(x86asm_o $TMPO) $TMPASM +} + check_cmd(){ log check_cmd "$@" cmd=$1 @@ -844,16 +856,12 @@ check_insn(){ check_as ${1}_external "$2" } -x86asm_o(){ - eval printf '%s\\n' $X86ASM_O -} - -test_x86asm(){ - log test_x86asm "$@" - echo "$1" > $TMPASM - log_file $TMPASM - shift 1 - test_cmd $x86asmexe $X86ASMFLAGS "$@" $(x86asm_o $TMPO) $TMPASM +check_x86asm(){ + log check_x86asm "$@" + name=$1 + shift + disable $name + test_x86asm "$@" && enable $name } ld_o(){ @@ -4425,7 +4433,7 @@ EOF X86ASMDEP='$(DEPX86ASM) $(X86ASMFLAGS) -M $(X86ASM_O) $< > $(@:.o=.d)' X86ASM_DEPFLAGS= fi - test_x86asm "movbe ecx, [5]" && enable x86asm + check_x86asm x86asm "movbe ecx, [5]" } if ! disabled_any asm mmx x86asm; then @@ -4441,11 +4449,11 @@ EOF elf*) enabled debug && append X86ASMFLAGS $x86asm_debug ;; esac - test_x86asm "vextracti128 xmm0, ymm0, 0" || disable avx2_external - test_x86asm "vpmacsdd xmm0, xmm1, xmm2, xmm3" || disable xop_external - test_x86asm "vfmadd132ps ymm0, ymm1, ymm2" || disable fma3_external - test_x86asm "vfmaddps ymm0, ymm1, ymm2, ymm3" || disable fma4_external - test_x86asm "CPU amdnop" || disable cpunop + check_x86asm avx2_external "vextracti128 xmm0, ymm0, 0" + check_x86asm xop_external "vpmacsdd xmm0, xmm1, xmm2, xmm3" + check_x86asm fma3_external "vfmadd132ps ymm0, ymm1, ymm2" + check_x86asm fma4_external "vfmaddps ymm0, ymm1, ymm2, ymm3" + check_x86asm cpunop "CPU amdnop" fi case "$cpu" in From 434b44cd6fb4bb9a2bf2bb29ef55ce1a315314b8 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Thu, 8 Mar 2018 15:42:32 +0100 Subject: [PATCH 2247/2557] configure: Simplify vararg check --- configure | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 4e6b880b14add..4128ce3c860d8 100755 --- a/configure +++ b/configure @@ -4240,12 +4240,11 @@ od -t x1 $TMPO | grep -q '42 *49 *47 *45' && enable bigendian check_gas() { log "check_gas using '$as' as AS" # :vararg is used on aarch64, arm and ppc altivec - test_as < Date: Wed, 21 Mar 2018 18:59:33 +0530 Subject: [PATCH 2248/2557] avformat/segafilm - fix keyframe detection and set packet flags Streams from a Segafilm cpk file can't be streamcopied because keyframe flag isn't correctly set in stream index and said flag is never conveyed to the packet Fixes #7091 Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/segafilm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/segafilm.c b/libavformat/segafilm.c index 1fdef50cc75d7..4c0cca0140156 100644 --- a/libavformat/segafilm.c +++ b/libavformat/segafilm.c @@ -239,7 +239,7 @@ static int film_read_header(AVFormatContext *s) } else { film->sample_table[i].stream = film->video_stream_index; film->sample_table[i].pts = AV_RB32(&scratch[8]) & 0x7FFFFFFF; - film->sample_table[i].keyframe = (scratch[8] & 0x80) ? 0 : 1; + film->sample_table[i].keyframe = (scratch[8] & 0x80) ? AVINDEX_KEYFRAME : 0; video_frame_counter++; if (film->video_type) av_add_index_entry(s->streams[film->video_stream_index], @@ -286,6 +286,7 @@ static int film_read_packet(AVFormatContext *s, pkt->stream_index = sample->stream; pkt->pts = sample->pts; + pkt->flags |= sample->keyframe ? AV_PKT_FLAG_KEY : 0; film->current_sample++; From 9f17875134754eef899aefd30500904635edec9e Mon Sep 17 00:00:00 2001 From: Danil Iashchenko Date: Sat, 24 Mar 2018 18:57:43 +0300 Subject: [PATCH 2249/2557] libavfilter: Add OpenCL convolution filter Behaves like existing convolution filter. Signed-off-by: Mark Thompson --- configure | 1 + libavfilter/Makefile | 2 + libavfilter/allfilters.c | 1 + libavfilter/opencl/convolution.cl | 45 ++++ libavfilter/opencl_source.h | 1 + libavfilter/vf_convolution_opencl.c | 368 ++++++++++++++++++++++++++++ 6 files changed, 418 insertions(+) create mode 100644 libavfilter/opencl/convolution.cl create mode 100644 libavfilter/vf_convolution_opencl.c diff --git a/configure b/configure index cc3edeb80f0a1..5ccf3cee7f762 100755 --- a/configure +++ b/configure @@ -3235,6 +3235,7 @@ blackframe_filter_deps="gpl" boxblur_filter_deps="gpl" bs2b_filter_deps="libbs2b" colormatrix_filter_deps="gpl" +convolution_opencl_filter_deps="opencl" convolve_filter_deps="avcodec" convolve_filter_select="fft" coreimage_filter_deps="coreimage appkit" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 1043b41d8070a..a90ca30ad7ac2 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -159,6 +159,8 @@ OBJS-$(CONFIG_COLORLEVELS_FILTER) += vf_colorlevels.o OBJS-$(CONFIG_COLORMATRIX_FILTER) += vf_colormatrix.o OBJS-$(CONFIG_COLORSPACE_FILTER) += vf_colorspace.o colorspacedsp.o OBJS-$(CONFIG_CONVOLUTION_FILTER) += vf_convolution.o +OBJS-$(CONFIG_CONVOLUTION_OPENCL_FILTER) += vf_convolution_opencl.o opencl.o \ + opencl/convolution.o OBJS-$(CONFIG_CONVOLVE_FILTER) += vf_convolve.o framesync.o OBJS-$(CONFIG_COPY_FILTER) += vf_copy.o OBJS-$(CONFIG_COREIMAGE_FILTER) += vf_coreimage.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 3f67e321bf33f..1cf13409ca372 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -168,6 +168,7 @@ static void register_all(void) REGISTER_FILTER(COLORMATRIX, colormatrix, vf); REGISTER_FILTER(COLORSPACE, colorspace, vf); REGISTER_FILTER(CONVOLUTION, convolution, vf); + REGISTER_FILTER(CONVOLUTION_OPENCL, convolution_opencl, vf); REGISTER_FILTER(CONVOLVE, convolve, vf); REGISTER_FILTER(COPY, copy, vf); REGISTER_FILTER(COREIMAGE, coreimage, vf); diff --git a/libavfilter/opencl/convolution.cl b/libavfilter/opencl/convolution.cl new file mode 100644 index 0000000000000..03ef4eff1bc72 --- /dev/null +++ b/libavfilter/opencl/convolution.cl @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018 Danil Iashchenko + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +__kernel void convolution_global(__write_only image2d_t dst, + __read_only image2d_t src, + int coef_matrix_dim, + __constant float *coef_matrix, + float div, + float bias) +{ + const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_ADDRESS_CLAMP_TO_EDGE | + CLK_FILTER_NEAREST); + + const int half_matrix_dim = (coef_matrix_dim / 2); + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + float4 convPix = (float4)(0.0f, 0.0f, 0.0f, 0.0f); + + for (int conv_i = -half_matrix_dim; conv_i <= half_matrix_dim; conv_i++) { + for (int conv_j = -half_matrix_dim; conv_j <= half_matrix_dim; conv_j++) { + float4 px = read_imagef(src, sampler, loc + (int2)(conv_j, conv_i)); + convPix += px * coef_matrix[(conv_i + half_matrix_dim) * coef_matrix_dim + + (conv_j + half_matrix_dim)]; + } + } + float4 dstPix = convPix * div + bias; + write_imagef(dst, loc, dstPix); +} diff --git a/libavfilter/opencl_source.h b/libavfilter/opencl_source.h index 02bc1723b0925..4bb996924e4ac 100644 --- a/libavfilter/opencl_source.h +++ b/libavfilter/opencl_source.h @@ -20,6 +20,7 @@ #define AVFILTER_OPENCL_SOURCE_H extern const char *ff_opencl_source_avgblur; +extern const char *ff_opencl_source_convolution; extern const char *ff_opencl_source_overlay; extern const char *ff_opencl_source_unsharp; diff --git a/libavfilter/vf_convolution_opencl.c b/libavfilter/vf_convolution_opencl.c new file mode 100644 index 0000000000000..2df51e05340b0 --- /dev/null +++ b/libavfilter/vf_convolution_opencl.c @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2018 Danil Iashchenko + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/avstring.h" + + +#include "avfilter.h" +#include "internal.h" +#include "opencl.h" +#include "opencl_source.h" +#include "video.h" + +typedef struct ConvolutionOpenCLContext { + OpenCLFilterContext ocf; + + int initialised; + cl_kernel kernel; + cl_command_queue command_queue; + + char *matrix_str[4]; + + cl_mem matrix[4]; + cl_int matrix_sizes[4]; + cl_int dims[4]; + cl_float rdivs[4]; + cl_float biases[4]; + +} ConvolutionOpenCLContext; + + +static int convolution_opencl_init(AVFilterContext *avctx) +{ + ConvolutionOpenCLContext *ctx = avctx->priv; + cl_int cle; + int err; + + err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_convolution, 1); + if (err < 0) + goto fail; + + ctx->command_queue = clCreateCommandQueue(ctx->ocf.hwctx->context, + ctx->ocf.hwctx->device_id, + 0, &cle); + if (!ctx->command_queue) { + av_log(avctx, AV_LOG_ERROR, "Failed to create OpenCL " + "command queue: %d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + + ctx->kernel = clCreateKernel(ctx->ocf.program, "convolution_global", &cle); + if (!ctx->kernel) { + av_log(avctx, AV_LOG_ERROR, "Failed to create kernel: %d.\n", cle); + err = AVERROR(EIO); + goto fail; + } + + ctx->initialised = 1; + return 0; + +fail: + if (ctx->command_queue) + clReleaseCommandQueue(ctx->command_queue); + if (ctx->kernel) + clReleaseKernel(ctx->kernel); + return err; +} + + + +static int convolution_opencl_make_filter_params(AVFilterContext *avctx) +{ + ConvolutionOpenCLContext *ctx = avctx->priv; + float *matrix = NULL; + size_t matrix_bytes; + cl_mem buffer; + cl_int cle; + int i, j; + int sscanf_err; + char *p, *arg, *saveptr = NULL; + float input_matrix[4][49]; + + for (i = 0; i < 4; i++) { + ctx->biases[i] = ctx->biases[i] / 255.0; + } + + for (i = 0; i < 4; i++) { + p = ctx->matrix_str[i]; + while (ctx->matrix_sizes[i] < 49) { + arg = av_strtok(p, " ", &saveptr); + if (!arg) { + break; + } + p = NULL; + sscanf_err = sscanf(arg, "%f", &input_matrix[i][ctx->matrix_sizes[i]]); + if (sscanf_err != 1) { + av_log(ctx, AV_LOG_ERROR, "Matrix is sequence of 9, 25 or 49 signed numbers\n"); + return AVERROR(EINVAL); + } + ctx->matrix_sizes[i]++; + } + if (ctx->matrix_sizes[i] == 9) { + ctx->dims[i] = 3; + } else if (ctx->matrix_sizes[i] == 25) { + ctx->dims[i] = 5; + } else if (ctx->matrix_sizes[i] == 49) { + ctx->dims[i] = 7; + } else { + av_log(ctx, AV_LOG_ERROR, "Invalid matrix size:%d\n", ctx->matrix_sizes[i]); + return AVERROR(EINVAL); + } + + } + + for (j = 0; j < 4; j++) { + matrix_bytes = sizeof(float)*ctx->matrix_sizes[j]; + matrix = av_malloc(matrix_bytes); + if (!matrix) { + av_freep(&matrix); + return AVERROR(ENOMEM); + } + + for (i = 0; i < ctx->matrix_sizes[j]; i++) + matrix[i] = input_matrix[j][i]; + + buffer = clCreateBuffer(ctx->ocf.hwctx->context, + CL_MEM_READ_ONLY | + CL_MEM_COPY_HOST_PTR | + CL_MEM_HOST_NO_ACCESS, + matrix_bytes, matrix, &cle); + if (!buffer) { + av_log(avctx, AV_LOG_ERROR, "Failed to create matrix buffer: " + "%d.\n", cle); + av_freep(&matrix); + return AVERROR(EIO); + } + ctx->matrix[j] = buffer; + av_freep(&matrix); + } + + return 0; +} + +static int convolution_opencl_filter_frame(AVFilterLink *inlink, AVFrame *input) +{ + AVFilterContext *avctx = inlink->dst; + AVFilterLink *outlink = avctx->outputs[0]; + ConvolutionOpenCLContext *ctx = avctx->priv; + AVFrame *output = NULL; + cl_int cle; + size_t global_work[2]; + cl_mem src, dst; + int err, p; + + av_log(ctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(input->format), + input->width, input->height, input->pts); + + if (!input->hw_frames_ctx) + return AVERROR(EINVAL); + + if (!ctx->initialised) { + err = convolution_opencl_init(avctx); + if (err < 0) + goto fail; + + err = convolution_opencl_make_filter_params(avctx); + if (err < 0) + goto fail; + } + + output = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!output) { + err = AVERROR(ENOMEM); + goto fail; + } + + for (p = 0; p < FF_ARRAY_ELEMS(output->data); p++) { + src = (cl_mem) input->data[p]; + dst = (cl_mem)output->data[p]; + + if (!dst) + break; + + cle = clSetKernelArg(ctx->kernel, 0, sizeof(cl_mem), &dst); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "destination image argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel, 1, sizeof(cl_mem), &src); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "source image argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel, 2, sizeof(cl_int), &ctx->dims[p]); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "matrix size argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel, 3, sizeof(cl_mem), &ctx->matrix[p]); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "matrix argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel, 4, sizeof(cl_float), &ctx->rdivs[p]); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "rdiv argument: %d.\n", cle); + goto fail; + } + cle = clSetKernelArg(ctx->kernel, 5, sizeof(cl_float), &ctx->biases[p]); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " + "bias argument: %d.\n", cle); + goto fail; + } + + + err = ff_opencl_filter_work_size_from_image(avctx, global_work, output, p, 0); + if (err < 0) + goto fail; + + av_log(avctx, AV_LOG_DEBUG, "Run kernel on plane %d " + "(%"SIZE_SPECIFIER"x%"SIZE_SPECIFIER").\n", + p, global_work[0], global_work[1]); + + cle = clEnqueueNDRangeKernel(ctx->command_queue, ctx->kernel, 2, NULL, + global_work, NULL, + 0, NULL, NULL); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to enqueue kernel: %d.\n", + cle); + err = AVERROR(EIO); + goto fail; + } + } + + cle = clFinish(ctx->command_queue); + if (cle != CL_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to finish command queue: %d.\n", + cle); + err = AVERROR(EIO); + goto fail; + } + + err = av_frame_copy_props(output, input); + if (err < 0) + goto fail; + + av_frame_free(&input); + + av_log(ctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(output->format), + output->width, output->height, output->pts); + + return ff_filter_frame(outlink, output); + +fail: + clFinish(ctx->command_queue); + av_frame_free(&input); + av_frame_free(&output); + return err; +} + +static av_cold void convolution_opencl_uninit(AVFilterContext *avctx) +{ + ConvolutionOpenCLContext *ctx = avctx->priv; + cl_int cle; + int i; + + for (i = 0; i < 4; i++) { + clReleaseMemObject(ctx->matrix[i]); + } + + if (ctx->kernel) { + cle = clReleaseKernel(ctx->kernel); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "kernel: %d.\n", cle); + } + + if (ctx->command_queue) { + cle = clReleaseCommandQueue(ctx->command_queue); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "command queue: %d.\n", cle); + } + + ff_opencl_filter_uninit(avctx); +} + +#define OFFSET(x) offsetof(ConvolutionOpenCLContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption convolution_opencl_options[] = { + { "0m", "set matrix for 2nd plane", OFFSET(matrix_str[0]), AV_OPT_TYPE_STRING, {.str="0 0 0 0 1 0 0 0 0"}, 0, 0, FLAGS }, + { "1m", "set matrix for 2nd plane", OFFSET(matrix_str[1]), AV_OPT_TYPE_STRING, {.str="0 0 0 0 1 0 0 0 0"}, 0, 0, FLAGS }, + { "2m", "set matrix for 3rd plane", OFFSET(matrix_str[2]), AV_OPT_TYPE_STRING, {.str="0 0 0 0 1 0 0 0 0"}, 0, 0, FLAGS }, + { "3m", "set matrix for 4th plane", OFFSET(matrix_str[3]), AV_OPT_TYPE_STRING, {.str="0 0 0 0 1 0 0 0 0"}, 0, 0, FLAGS }, + { "0rdiv", "set rdiv for 1nd plane", OFFSET(rdivs[0]), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, INT_MAX, FLAGS}, + { "1rdiv", "set rdiv for 2nd plane", OFFSET(rdivs[1]), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, INT_MAX, FLAGS}, + { "2rdiv", "set rdiv for 3rd plane", OFFSET(rdivs[2]), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, INT_MAX, FLAGS}, + { "3rdiv", "set rdiv for 4th plane", OFFSET(rdivs[3]), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, INT_MAX, FLAGS}, + { "0bias", "set bias for 1st plane", OFFSET(biases[0]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS}, + { "1bias", "set bias for 2nd plane", OFFSET(biases[1]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS}, + { "2bias", "set bias for 3rd plane", OFFSET(biases[2]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS}, + { "3bias", "set bias for 4th plane", OFFSET(biases[3]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS}, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(convolution_opencl); + +static const AVFilterPad convolution_opencl_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &convolution_opencl_filter_frame, + .config_props = &ff_opencl_filter_config_input, + }, + { NULL } +}; + +static const AVFilterPad convolution_opencl_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_opencl_filter_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_convolution_opencl = { + .name = "convolution_opencl", + .description = NULL_IF_CONFIG_SMALL("Apply convolution mask to input video"), + .priv_size = sizeof(ConvolutionOpenCLContext), + .priv_class = &convolution_opencl_class, + .init = &ff_opencl_filter_init, + .uninit = &convolution_opencl_uninit, + .query_formats = &ff_opencl_filter_query_formats, + .inputs = convolution_opencl_inputs, + .outputs = convolution_opencl_outputs, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; From 213839edffbf3982570e4e06ca713f8547dd336a Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 24 Mar 2018 13:56:16 +0000 Subject: [PATCH 2250/2557] vf_avgblur_opencl: Don't run kernel on pixels outside the image The output frame size is larger than the image containing a subsampled plane - use the actual size of the image being written rather than the dimensions of the intended output frame. Reviewed-by: Dylan Fernando --- libavfilter/vf_avgblur_opencl.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_avgblur_opencl.c b/libavfilter/vf_avgblur_opencl.c index 5ee66c0ba21a1..3a5b4a28ca521 100644 --- a/libavfilter/vf_avgblur_opencl.c +++ b/libavfilter/vf_avgblur_opencl.c @@ -170,8 +170,10 @@ static int avgblur_opencl_filter_frame(AVFilterLink *inlink, AVFrame *input) goto fail; } - global_work[0] = output->width; - global_work[1] = output->height; + err = ff_opencl_filter_work_size_from_image(avctx, global_work, + intermediate, p, 0); + if (err < 0) + goto fail; av_log(avctx, AV_LOG_DEBUG, "Run kernel on plane %d " "(%"SIZE_SPECIFIER"x%"SIZE_SPECIFIER").\n", @@ -206,8 +208,10 @@ static int avgblur_opencl_filter_frame(AVFilterLink *inlink, AVFrame *input) goto fail; } - global_work[0] = output->width; - global_work[1] = output->height; + err = ff_opencl_filter_work_size_from_image(avctx, global_work, + output, p, 0); + if (err < 0) + goto fail; av_log(avctx, AV_LOG_DEBUG, "Run kernel on plane %d " "(%"SIZE_SPECIFIER"x%"SIZE_SPECIFIER").\n", From 29c663d50cbf590e9d225ace2d36a80fb8cbd8d3 Mon Sep 17 00:00:00 2001 From: drfer3 Date: Mon, 26 Mar 2018 11:08:03 +1100 Subject: [PATCH 2251/2557] avfilter/vf_avgblur_opencl: fix error when clSetKernelArg fails Fixes Coverity CID 1430382. --- libavfilter/vf_avgblur_opencl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavfilter/vf_avgblur_opencl.c b/libavfilter/vf_avgblur_opencl.c index 3a5b4a28ca521..48cebb5887039 100644 --- a/libavfilter/vf_avgblur_opencl.c +++ b/libavfilter/vf_avgblur_opencl.c @@ -155,18 +155,21 @@ static int avgblur_opencl_filter_frame(AVFilterLink *inlink, AVFrame *input) if (cle != CL_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " "destination image argument: %d.\n", cle); + err = AVERROR_UNKNOWN; goto fail; } cle = clSetKernelArg(ctx->kernel_horiz, 1, sizeof(cl_mem), &src); if (cle != CL_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " "source image argument: %d.\n", cle); + err = AVERROR_UNKNOWN; goto fail; } cle = clSetKernelArg(ctx->kernel_horiz, 2, sizeof(cl_int), &radius_x); if (cle != CL_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " "sizeX argument: %d.\n", cle); + err = AVERROR_UNKNOWN; goto fail; } @@ -193,18 +196,21 @@ static int avgblur_opencl_filter_frame(AVFilterLink *inlink, AVFrame *input) if (cle != CL_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " "destination image argument: %d.\n", cle); + err = AVERROR_UNKNOWN; goto fail; } cle = clSetKernelArg(ctx->kernel_vert, 1, sizeof(cl_mem), &inter); if (cle != CL_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " "source image argument: %d.\n", cle); + err = AVERROR_UNKNOWN; goto fail; } cle = clSetKernelArg(ctx->kernel_vert, 2, sizeof(cl_int), &radius_y); if (cle != CL_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " "sizeY argument: %d.\n", cle); + err = AVERROR_UNKNOWN; goto fail; } From ac6e27d74f6a413d400c228b0eb2d3af32c1ea76 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 26 Mar 2018 08:22:07 +0800 Subject: [PATCH 2252/2557] kmsgrab: add category for kmsgrab Makes kmsgrab visible in "ffmpeg -devices". Signed-off-by: Jun Zhao Signed-off-by: Mark Thompson --- libavdevice/kmsgrab.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavdevice/kmsgrab.c b/libavdevice/kmsgrab.c index 6a6de09c3763b..d0de774871cb4 100644 --- a/libavdevice/kmsgrab.c +++ b/libavdevice/kmsgrab.c @@ -451,6 +451,7 @@ static const AVClass kmsgrab_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, }; AVInputFormat ff_kmsgrab_demuxer = { From 3914c8e0e6bac4ce3b3573c6fd3098e2aa4c9ff5 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Mon, 26 Mar 2018 20:32:00 +0800 Subject: [PATCH 2253/2557] avformat/hlsenc: initialize saveptrs av_strtok calls strspn on a non-NULL *saveptr, so not NULL initializing it is an issue. Fixes CID #1428568 Reviewed-by: Karthick Jeyapal Signed-off-by: Steven Liu Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 34fa848466c5a..2a54b4342e5b3 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1888,7 +1888,8 @@ static int parse_cc_stream_mapstring(AVFormatContext *s) { HLSContext *hls = s->priv_data; int nb_ccstreams; - char *p, *q, *saveptr1, *saveptr2, *ccstr, *keyval; + char *p, *q, *ccstr, *keyval; + char *saveptr1 = NULL, *saveptr2 = NULL; const char *val; ClosedCaptionsStream *ccs; From 2124a97a4998413c7e81539b16b01ef6ac570ea9 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 13 Mar 2018 11:03:11 +0100 Subject: [PATCH 2254/2557] configure: Drop unused helper function test_cflags_cpp() --- configure | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/configure b/configure index 4128ce3c860d8..90fb6f07ca72f 100755 --- a/configure +++ b/configure @@ -1042,19 +1042,6 @@ check_cpp_condition(){ test_cpp_condition "$@" && enable $name } -test_cflags_cpp(){ - log test_cflags_cpp "$@" - flags=$1 - condition=$2 - shift 2 - set -- $($cflags_filter "$flags") - test_cpp "$@" < Date: Sun, 25 Mar 2018 21:23:54 -0300 Subject: [PATCH 2255/2557] avcodec/avpacket: remove unnecessary check in av_packet_make_writable() Zero sized packets are already handled below in the function. This is more in line with av_packet_ref(). Signed-off-by: James Almer --- libavcodec/avpacket.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index 0693ca6f62f58..09934819613d7 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -660,9 +660,6 @@ int av_packet_make_writable(AVPacket *pkt) if (pkt->buf && av_buffer_is_writable(pkt->buf)) return 0; - if (!pkt->data) - return AVERROR(EINVAL); - ret = packet_alloc(&buf, pkt->size); if (ret < 0) return ret; From 95e33ea5659980b2915202882e9e82f912addc3f Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 27 Mar 2018 14:58:36 -0300 Subject: [PATCH 2256/2557] doc/APIchanges: fix lavu version for the AVEncryptionInfo addition Signed-off-by: James Almer --- doc/APIchanges | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 95b5cd772ff4b..83c7a40a557ac 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -18,7 +18,7 @@ API changes, most recent first: 2018-03-xx - xxxxxxx - lavc 58.16.100 - avcodec.h Add FF_SUB_CHARENC_MODE_IGNORE. -2018-xx-xx - xxxxxxx - lavu 56.8.100 - encryption_info.h +2018-03-23 - xxxxxxx - lavu 56.12.100 - encryption_info.h Add AVEncryptionInitInfo and AVEncryptionInfo structures to hold new side-data for encryption info. From 49a0b3f6bc963583a490c3397f2055365b4d821e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 25 Mar 2018 20:21:37 +0200 Subject: [PATCH 2257/2557] doc/examples/hw_decode: Remove useless NULL check Reviewed-by: Jun Zhao Signed-off-by: Michael Niedermayer --- doc/examples/hw_decode.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/examples/hw_decode.c b/doc/examples/hw_decode.c index 14fe08b374f9e..74a0ca32db0f0 100644 --- a/doc/examples/hw_decode.c +++ b/doc/examples/hw_decode.c @@ -138,8 +138,7 @@ static int decode_write(AVCodecContext *avctx, AVPacket *packet) fail: av_frame_free(&frame); av_frame_free(&sw_frame); - if (buffer) - av_freep(&buffer); + av_freep(&buffer); if (ret < 0) return ret; } From b3e9f3f5f52d2c769e0cb6ab1676e16c858e19b3 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 25 Mar 2018 20:21:38 +0200 Subject: [PATCH 2258/2557] doc/examples/hw_decode: Remove logically dead code in decode_write() Fixes CID1415951 Reviewed-by: Jun Zhao Signed-off-by: Michael Niedermayer --- doc/examples/hw_decode.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/examples/hw_decode.c b/doc/examples/hw_decode.c index 74a0ca32db0f0..77ae8df35b5af 100644 --- a/doc/examples/hw_decode.c +++ b/doc/examples/hw_decode.c @@ -86,7 +86,7 @@ static int decode_write(AVCodecContext *avctx, AVPacket *packet) return ret; } - while (ret >= 0) { + while (1) { if (!(frame = av_frame_alloc()) || !(sw_frame = av_frame_alloc())) { fprintf(stderr, "Can not alloc frame\n"); ret = AVERROR(ENOMEM); @@ -142,8 +142,6 @@ static int decode_write(AVCodecContext *avctx, AVPacket *packet) if (ret < 0) return ret; } - - return 0; } int main(int argc, char *argv[]) From 44000b7744a0a3c425bc6d8d924b4efa866aad39 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 27 Mar 2018 00:04:32 +0100 Subject: [PATCH 2259/2557] hwcontext_d3d11: Fix crash with valid adapter but no device This crash was introduced by 8bbf2dacbfb4ead1535dea411035994f507f517d, which could incorrectly overwrite the failure result from creating the device. Fixes ticket #7108. Reviewed-by: wm4 --- libavutil/hwcontext_d3d11va.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 960883c9d8a81..d39fdd3fc85a9 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -556,8 +556,6 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, } } - hr = mD3D11CreateDevice(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0, - D3D11_SDK_VERSION, &device_hwctx->device, NULL, NULL); if (pAdapter) { DXGI_ADAPTER_DESC2 desc; hr = IDXGIAdapter2_GetDesc(pAdapter, &desc); @@ -565,8 +563,12 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, av_log(ctx, AV_LOG_INFO, "Using device %04x:%04x (%ls).\n", desc.VendorId, desc.DeviceId, desc.Description); } - IDXGIAdapter_Release(pAdapter); } + + hr = mD3D11CreateDevice(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0, + D3D11_SDK_VERSION, &device_hwctx->device, NULL, NULL); + if (pAdapter) + IDXGIAdapter_Release(pAdapter); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device (%lx)\n", (long)hr); return AVERROR_UNKNOWN; From 10d008f0fd9e713e290f626300d66382ad786c49 Mon Sep 17 00:00:00 2001 From: sanilraut Date: Wed, 28 Mar 2018 19:52:27 +0800 Subject: [PATCH 2260/2557] avformat/dashdec: Support signaling of last segment number Last segment indicated by mpd is not parsed. Example stream: http://dash.akamaized.net/dash264/TestCasesIOP41/LastSegmentNumber/1/manifest_last_segment_num.mpd This patch supports parsing of Supplemental Descriptor with @schemeIdUri set to http://dashif.org/guide- lines/last-segment-number with the @value set to the last segment number. Reviewed-by: Steven Liu --- libavformat/dashdec.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 7b79b93c2412c..8bfde4dbce3a9 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -805,7 +805,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr fragment_template_node, xmlNodePtr content_component_node, xmlNodePtr adaptionset_baseurl_node, - xmlNodePtr adaptionset_segmentlist_node) + xmlNodePtr adaptionset_segmentlist_node, + xmlNodePtr adaptionset_supplementalproperty_node) { int32_t ret = 0; int32_t audio_rep_idx = 0; @@ -825,6 +826,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, char *timescale_val = NULL; char *initialization_val = NULL; char *media_val = NULL; + char *val = NULL; xmlNodePtr baseurl_nodes[4]; xmlNodePtr representation_node = node; char *rep_id_val = xmlGetProp(representation_node, "id"); @@ -920,6 +922,17 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, rep->first_seq_no = (int64_t) strtoll(startnumber_val, NULL, 10); xmlFree(startnumber_val); } + if (adaptionset_supplementalproperty_node) { + if (!av_strcasecmp(xmlGetProp(adaptionset_supplementalproperty_node,"schemeIdUri"), "http://dashif.org/guidelines/last-segment-number")) { + val = xmlGetProp(adaptionset_supplementalproperty_node,"value"); + if (!val) { + av_log(s, AV_LOG_ERROR, "Missing value attribute in adaptionset_supplementalproperty_node\n"); + } else { + rep->last_seq_no =(int64_t) strtoll(val, NULL, 10) - 1; + xmlFree(val); + } + } + } fragment_timeline_node = find_child_node_by_name(representation_segmenttemplate_node, "SegmentTimeline"); @@ -1054,6 +1067,7 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, xmlNodePtr content_component_node = NULL; xmlNodePtr adaptionset_baseurl_node = NULL; xmlNodePtr adaptionset_segmentlist_node = NULL; + xmlNodePtr adaptionset_supplementalproperty_node = NULL; xmlNodePtr node = NULL; node = xmlFirstElementChild(adaptionset_node); @@ -1066,6 +1080,8 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, adaptionset_baseurl_node = node; } else if (!av_strcasecmp(node->name, (const char *)"SegmentList")) { adaptionset_segmentlist_node = node; + } else if (!av_strcasecmp(node->name, (const char *)"SupplementalProperty")) { + adaptionset_supplementalproperty_node = node; } else if (!av_strcasecmp(node->name, (const char *)"Representation")) { ret = parse_manifest_representation(s, url, node, adaptionset_node, @@ -1076,7 +1092,8 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, fragment_template_node, content_component_node, adaptionset_baseurl_node, - adaptionset_segmentlist_node); + adaptionset_segmentlist_node, + adaptionset_supplementalproperty_node); if (ret < 0) { return ret; } @@ -1819,7 +1836,10 @@ static int open_demux_for_component(AVFormatContext *s, struct representation *p pls->parent = s; pls->cur_seq_no = calc_cur_seg_no(s, pls); - pls->last_seq_no = calc_max_seg_no(pls, s->priv_data); + + if (!pls->last_seq_no) { + pls->last_seq_no = calc_max_seg_no(pls, s->priv_data); + } ret = reopen_demux_for_component(s, pls); if (ret < 0) { From a2fc8dbae85339d1b418d296f2982b6c04c53c57 Mon Sep 17 00:00:00 2001 From: Sven Dueking Date: Mon, 26 Mar 2018 11:37:49 -0400 Subject: [PATCH 2261/2557] Add Haivision SRT protocol The protocol requires libsrt (https://github.com/Haivision/srt) to be installed Signed-off-by: Sven Dueking Signed-off-by: Luca Barbato --- Changelog | 1 + configure | 5 + doc/protocols.texi | 140 +++++++++++ libavformat/Makefile | 3 + libavformat/libsrt.c | 546 ++++++++++++++++++++++++++++++++++++++++ libavformat/protocols.c | 1 + 6 files changed, 696 insertions(+) create mode 100644 libavformat/libsrt.c diff --git a/Changelog b/Changelog index 0d20cd47df849..53562a1aa0e88 100644 --- a/Changelog +++ b/Changelog @@ -21,6 +21,7 @@ version : - NVIDIA CUVID-accelerated H.264 and HEVC decoding - Intel QSV-accelerated overlay filter - AV1 Support through libaom +- Haivision SRT protocol via libsrt version 12: diff --git a/configure b/configure index 90fb6f07ca72f..7612a6052c0bd 100755 --- a/configure +++ b/configure @@ -213,6 +213,7 @@ External library support: --enable-libschroedinger Dirac video encoding/decoding --enable-libsnappy snappy compression --enable-libspeex Speex audio encoding/decoding + --enable-libsrt Haivision SRT protocol --enable-libtheora Theora video encoding/decoding --enable-libtwolame MP2 audio encoding --enable-libvo-aacenc AAC audio encoding @@ -1374,6 +1375,7 @@ EXTERNAL_LIBRARY_LIST=" libschroedinger libsnappy libspeex + libsrt libtheora libtwolame libvorbis @@ -2525,6 +2527,8 @@ librtmpt_protocol_deps="librtmp" librtmpte_protocol_deps="librtmp" mmsh_protocol_select="http_protocol" mmst_protocol_select="network" +libsrt_protocol_deps="libsrt" +libsrt_protocol_select="network" rtmp_protocol_conflict="librtmp_protocol" rtmp_protocol_select="tcp_protocol" rtmp_protocol_suggest="zlib" @@ -4674,6 +4678,7 @@ enabled librtmp && require_pkg_config librtmp librtmp librtmp/rtmp.h R enabled libschroedinger && require_pkg_config libschroedinger schroedinger-1.0 schroedinger/schro.h schro_init enabled libsnappy && require libsnappy snappy-c.h snappy_compress -lsnappy enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init +enabled libsrt && require_pkg_config libsrt "srt >= 1.2.0" srt/srt.h srt_socket enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame enabled libvo_aacenc && require libvo_aacenc vo-aacenc/voAAC.h voGetAACEncAPI -lvo-aacenc diff --git a/doc/protocols.texi b/doc/protocols.texi index c136c74e41eac..e2d06a067535d 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -655,6 +655,146 @@ To play back the first stream announced on one the default IPv6 SAP multicast ad avplay sap://[ff0e::2:7ffe] @end example +@section srt + +Haivision Secure Reliable Transport Protocol via libsrt. + +The supported syntax for a SRT URL is: +@example +srt://@var{hostname}:@var{port}[?@var{options}] +@end example + +@var{options} contains a list of &-separated options of the form +@var{key}=@var{val}. + +or + +@example +@var{options} srt://@var{hostname}:@var{port} +@end example + +@var{options} contains a list of '-@var{key} @var{val}' +options. + +This protocol accepts the following options. + +@table @option +@item connect_timeout +Connection timeout; SRT cannot connect for RTT > 1500 msec +(2 handshake exchanges) with the default connect timeout of +3 seconds. This option applies to the caller and rendezvous +connection modes. The connect timeout is 10 times the value +set for the rendezvous mode (which can be used as a +workaround for this connection problem with earlier versions). + +@item ffs=@var{bytes} +Flight Flag Size (Window Size), in bytes. FFS is actually an +internal parameter and you should set it to not less than +@option{recv_buffer_size} and @option{mss}. The default value +is relatively large, therefore unless you set a very large receiver buffer, +you do not need to change this option. Default value is 25600. + +@item inputbw=@var{bytes/seconds} +Sender nominal input rate, in bytes per seconds. Used along with +@option{oheadbw}, when @option{maxbw} is set to relative (0), to +calculate maximum sending rate when recovery packets are sent +along with the main media stream: +@option{inputbw} * (100 + @option{oheadbw}) / 100 +if @option{inputbw} is not set while @option{maxbw} is set to +relative (0), the actual input rate is evaluated inside +the library. Default value is 0. + +@item iptos=@var{tos} +IP Type of Service. Applies to sender only. Default value is 0xB8. + +@item ipttl=@var{ttl} +IP Time To Live. Applies to sender only. Default value is 64. + +@item listen_timeout +Set socket listen timeout. + +@item maxbw=@var{bytes/seconds} +Maximum sending bandwidth, in bytes per seconds. +-1 infinite (CSRTCC limit is 30mbps) +0 relative to input rate (see @option{inputbw}) +>0 absolute limit value +Default value is 0 (relative) + +@item mode=@var{caller|listener|rendezvous} +Connection mode. +@option{caller} opens client connection. +@option{listener} starts server to listen for incoming connections. +@option{rendezvous} use Rendez-Vous connection mode. +Default value is caller. + +@item mss=@var{bytes} +Maximum Segment Size, in bytes. Used for buffer allocation +and rate calculation using a packet counter assuming fully +filled packets. The smallest MSS between the peers is +used. This is 1500 by default in the overall internet. +This is the maximum size of the UDP packet and can be +only decreased, unless you have some unusual dedicated +network settings. Default value is 1500. + +@item nakreport=@var{1|0} +If set to 1, Receiver will send `UMSG_LOSSREPORT` messages +periodically until a lost packet is retransmitted or +intentionally dropped. Default value is 1. + +@item oheadbw=@var{percents} +Recovery bandwidth overhead above input rate, in percents. +See @option{inputbw}. Default value is 25%. + +@item passphrase=@var{string} +HaiCrypt Encryption/Decryption Passphrase string, length +from 10 to 79 characters. The passphrase is the shared +secret between the sender and the receiver. It is used +to generate the Key Encrypting Key using PBKDF2 +(Password-Based Key Derivation Function). It is used +only if @option{pbkeylen} is non-zero. It is used on +the receiver only if the received data is encrypted. +The configured passphrase cannot be recovered (write-only). + +@item pbkeylen=@var{bytes} +Sender encryption key length, in bytes. +Only can be set to 0, 16, 24 and 32. +Enable sender encryption if not 0. +Not required on receiver (set to 0), +key size obtained from sender in HaiCrypt handshake. +Default value is 0. + +@item recv_buffer_size=@var{bytes} +Set receive buffer size, expressed in bytes. + +@item send_buffer_size=@var{bytes} +Set send buffer size, expressed in bytes. + +@item rw_timeout +Set raise error timeout for read/write optations. + +This option is only relevant in read mode: +if no data arrived in more than this time +interval, raise error. + +@item tlpktdrop=@var{1|0} +Too-late Packet Drop. When enabled on receiver, it skips +missing packets that have not been delivered in time and +delivers the following packets to the application when +their time-to-play has come. It also sends a fake ACK to +the sender. When enabled on sender and enabled on the +receiving peer, the sender drops the older packets that +have no chance of being delivered in time. It was +automatically enabled in the sender if the receiver +supports it. + +@item tsbpddelay +Timestamp-based Packet Delivery Delay. +Used to absorb burst of missed packet retransmission. + +@end table + +For more information see: @url{https://github.com/Haivision/srt}. + @section tcp Transmission Control Protocol. diff --git a/libavformat/Makefile b/libavformat/Makefile index 2c1c0f6d7fc91..96085d20c6057 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -414,6 +414,9 @@ OBJS-$(CONFIG_TLS_PROTOCOL) += tls.o $(TLS-OBJS-yes) OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o OBJS-$(CONFIG_UNIX_PROTOCOL) += unix.o +# external libraries +OBJS-$(CONFIG_LIBSRT_PROTOCOL) += libsrt.o + SKIPHEADERS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh.h SKIPHEADERS-$(CONFIG_NETWORK) += network.h rtsp.h diff --git a/libavformat/libsrt.c b/libavformat/libsrt.c new file mode 100644 index 0000000000000..3e50dab64fc60 --- /dev/null +++ b/libavformat/libsrt.c @@ -0,0 +1,546 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Haivision Open SRT (Secure Reliable Transport) protocol + */ + +#include + +#include "libavutil/avassert.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "libavutil/time.h" + +#include "avformat.h" +#include "internal.h" +#include "network.h" +#include "os_support.h" +#include "url.h" + +enum SRTMode { + SRT_MODE_CALLER = 0, + SRT_MODE_LISTENER = 1, + SRT_MODE_RENDEZVOUS = 2 +}; + +typedef struct SRTContext { + const AVClass *class; + int fd; + int eid; + int64_t rw_timeout; + int64_t listen_timeout; + int recv_buffer_size; + int send_buffer_size; + + int64_t maxbw; + int pbkeylen; + char *passphrase; + int mss; + int ffs; + int ipttl; + int iptos; + int64_t inputbw; + int oheadbw; + int64_t tsbpddelay; + int tlpktdrop; + int nakreport; + int64_t connect_timeout; + enum SRTMode mode; +} SRTContext; + +#define D AV_OPT_FLAG_DECODING_PARAM +#define E AV_OPT_FLAG_ENCODING_PARAM +#define OFFSET(x) offsetof(SRTContext, x) +static const AVOption libsrt_options[] = { + { "rw_timeout", "Timeout of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "listen_timeout", "Connection awaiting timeout", OFFSET(listen_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "send_buffer_size", "Socket send buffer size (in bytes)", OFFSET(send_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "recv_buffer_size", "Socket receive buffer size (in bytes)", OFFSET(recv_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "maxbw", "Maximum bandwidth (bytes per second) that the connection can use", OFFSET(maxbw), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "pbkeylen", "Crypto key len in bytes {16,24,32} Default: 16 (128-bit)", OFFSET(pbkeylen), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 32, .flags = D|E }, + { "passphrase", "Crypto PBKDF2 Passphrase size[0,10..64] 0:disable crypto", OFFSET(passphrase), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, + { "mss", "The Maximum Segment Size", OFFSET(mss), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1500, .flags = D|E }, + { "ffs", "Flight flag size (window size) (in bytes)", OFFSET(ffs), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "ipttl", "IP Time To Live", OFFSET(ipttl), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, .flags = D|E }, + { "iptos", "IP Type of Service", OFFSET(iptos), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, .flags = D|E }, + { "inputbw", "Estimated input stream rate", OFFSET(inputbw), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "oheadbw", "MaxBW ceiling based on % over input stream rate", OFFSET(oheadbw), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 100, .flags = D|E }, + { "tsbpddelay", "TsbPd receiver delay to absorb burst of missed packet retransmission", OFFSET(tsbpddelay), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "tlpktdrop", "Enable receiver pkt drop", OFFSET(tlpktdrop), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, .flags = D|E }, + { "nakreport", "Enable receiver to send periodic NAK reports", OFFSET(nakreport), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, .flags = D|E }, + { "connect_timeout", "Connect timeout. Caller default: 3000, rendezvous (x 10)", OFFSET(connect_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "mode", "Connection mode (caller, listener, rendezvous)", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = SRT_MODE_CALLER }, SRT_MODE_CALLER, SRT_MODE_RENDEZVOUS, .flags = D|E, "mode" }, + { "caller", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = SRT_MODE_CALLER }, INT_MIN, INT_MAX, .flags = D|E, "mode" }, + { "listener", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = SRT_MODE_LISTENER }, INT_MIN, INT_MAX, .flags = D|E, "mode" }, + { "rendezvous", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = SRT_MODE_RENDEZVOUS }, INT_MIN, INT_MAX, .flags = D|E, "mode" }, + { NULL } +}; + +static int libsrt_neterrno(URLContext *h) +{ + int err = srt_getlasterror(NULL); + av_log(h, AV_LOG_ERROR, "%s\n", srt_getlasterror_str()); + if (err == SRT_EASYNCRCV) + return AVERROR(EAGAIN); + return AVERROR_UNKNOWN; +} + +static int libsrt_socket_nonblock(int socket, int enable) +{ + int ret = srt_setsockopt(socket, 0, SRTO_SNDSYN, &enable, sizeof(enable)); + if (ret < 0) + return ret; + return srt_setsockopt(socket, 0, SRTO_RCVSYN, &enable, sizeof(enable)); +} + +static int libsrt_network_wait_fd(URLContext *h, int eid, int fd, int write) +{ + int ret, len = 1; + int modes = write ? SRT_EPOLL_OUT : SRT_EPOLL_IN; + SRTSOCKET ready[1]; + + if (srt_epoll_add_usock(eid, fd, &modes) < 0) + return libsrt_neterrno(h); + if (write) { + ret = srt_epoll_wait(eid, 0, 0, ready, &len, POLLING_TIME, 0, 0, 0, 0); + } else { + ret = srt_epoll_wait(eid, ready, &len, 0, 0, POLLING_TIME, 0, 0, 0, 0); + } + if (ret < 0) { + if (srt_getlasterror(NULL) == SRT_ETIMEOUT) + ret = AVERROR(EAGAIN); + else + ret = libsrt_neterrno(h); + } else { + ret = 0; + } + if (srt_epoll_remove_usock(eid, fd) < 0) + return libsrt_neterrno(h); + return ret; +} + +/* TODO de-duplicate code from ff_network_wait_fd_timeout() */ + +static int libsrt_network_wait_fd_timeout(URLContext *h, int eid, int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb) +{ + int ret; + int64_t wait_start = 0; + + while (1) { + if (ff_check_interrupt(int_cb)) + return AVERROR_EXIT; + ret = libsrt_network_wait_fd(h, eid, fd, write); + if (ret != AVERROR(EAGAIN)) + return ret; + if (timeout > 0) { + if (!wait_start) + wait_start = av_gettime_relative(); + else if (av_gettime_relative() - wait_start > timeout) + return AVERROR(ETIMEDOUT); + } + } +} + +static int libsrt_listen(int eid, int fd, const struct sockaddr *addr, socklen_t addrlen, URLContext *h, int timeout) +{ + int ret; + int reuse = 1; + if (srt_setsockopt(fd, SOL_SOCKET, SRTO_REUSEADDR, &reuse, sizeof(reuse))) { + av_log(h, AV_LOG_WARNING, "setsockopt(SRTO_REUSEADDR) failed\n"); + } + ret = srt_bind(fd, addr, addrlen); + if (ret) + return libsrt_neterrno(h); + + ret = srt_listen(fd, 1); + if (ret) + return libsrt_neterrno(h); + + while ((ret = libsrt_network_wait_fd_timeout(h, eid, fd, 1, timeout, &h->interrupt_callback))) { + switch (ret) { + case AVERROR(ETIMEDOUT): + continue; + default: + return ret; + } + } + + ret = srt_accept(fd, NULL, NULL); + if (ret < 0) + return libsrt_neterrno(h); + if (libsrt_socket_nonblock(ret, 1) < 0) + av_log(h, AV_LOG_DEBUG, "libsrt_socket_nonblock failed\n"); + + return ret; +} + +static int libsrt_listen_connect(int eid, int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h, int will_try_next) +{ + int ret; + + if (libsrt_socket_nonblock(fd, 1) < 0) + av_log(h, AV_LOG_DEBUG, "ff_socket_nonblock failed\n"); + + while ((ret = srt_connect(fd, addr, addrlen))) { + ret = libsrt_neterrno(h); + switch (ret) { + case AVERROR(EINTR): + if (ff_check_interrupt(&h->interrupt_callback)) + return AVERROR_EXIT; + continue; + case AVERROR(EINPROGRESS): + case AVERROR(EAGAIN): + ret = libsrt_network_wait_fd_timeout(h, eid, fd, 1, timeout, &h->interrupt_callback); + if (ret < 0) + return ret; + ret = srt_getlasterror(NULL); + srt_clearlasterror(); + if (ret != 0) { + char buf[128]; + ret = AVERROR(ret); + av_strerror(ret, buf, sizeof(buf)); + if (will_try_next) + av_log(h, AV_LOG_WARNING, + "Connection to %s failed (%s), trying next address\n", + h->filename, buf); + else + av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n", + h->filename, buf); + } + default: + return ret; + } + } + return ret; +} + +static int libsrt_setsockopt(URLContext *h, int fd, SRT_SOCKOPT optname, const char * optnamestr, const void * optval, int optlen) +{ + if (srt_setsockopt(fd, 0, optname, optval, optlen) < 0) { + av_log(h, AV_LOG_ERROR, "failed to set option %s on socket: %s\n", optnamestr, srt_getlasterror_str()); + return AVERROR(EIO); + } + return 0; +} + +/* - The "POST" options can be altered any time on a connected socket. + They MAY have also some meaning when set prior to connecting; such + option is SRTO_RCVSYN, which makes connect/accept call asynchronous. + Because of that this option is treated special way in this app. */ +static int libsrt_set_options_post(URLContext *h, int fd) +{ + SRTContext *s = h->priv_data; + + if ((s->inputbw >= 0 && libsrt_setsockopt(h, fd, SRTO_INPUTBW, "SRTO_INPUTBW", &s->inputbw, sizeof(s->inputbw)) < 0) || + (s->oheadbw >= 0 && libsrt_setsockopt(h, fd, SRTO_OHEADBW, "SRTO_OHEADBW", &s->oheadbw, sizeof(s->oheadbw)) < 0)) { + return AVERROR(EIO); + } + return 0; +} + +/* - The "PRE" options must be set prior to connecting and can't be altered + on a connected socket, however if set on a listening socket, they are + derived by accept-ed socket. */ +static int libsrt_set_options_pre(URLContext *h, int fd) +{ + SRTContext *s = h->priv_data; + int yes = 1; + int tsbpddelay = s->tsbpddelay / 1000; + int connect_timeout = s->connect_timeout; + + if ((s->mode == SRT_MODE_RENDEZVOUS && libsrt_setsockopt(h, fd, SRTO_RENDEZVOUS, "SRTO_RENDEZVOUS", &yes, sizeof(yes)) < 0) || + (s->maxbw >= 0 && libsrt_setsockopt(h, fd, SRTO_MAXBW, "SRTO_MAXBW", &s->maxbw, sizeof(s->maxbw)) < 0) || + (s->pbkeylen >= 0 && libsrt_setsockopt(h, fd, SRTO_PBKEYLEN, "SRTO_PBKEYLEN", &s->pbkeylen, sizeof(s->pbkeylen)) < 0) || + (s->passphrase && libsrt_setsockopt(h, fd, SRTO_PASSPHRASE, "SRTO_PASSPHRASE", &s->passphrase, sizeof(s->passphrase)) < 0) || + (s->mss >= 0 && libsrt_setsockopt(h, fd, SRTO_MSS, "SRTO_MMS", &s->mss, sizeof(s->mss)) < 0) || + (s->ffs >= 0 && libsrt_setsockopt(h, fd, SRTO_FC, "SRTO_FC", &s->ffs, sizeof(s->ffs)) < 0) || + (s->ipttl >= 0 && libsrt_setsockopt(h, fd, SRTO_IPTTL, "SRTO_UPTTL", &s->ipttl, sizeof(s->ipttl)) < 0) || + (s->iptos >= 0 && libsrt_setsockopt(h, fd, SRTO_IPTOS, "SRTO_IPTOS", &s->iptos, sizeof(s->iptos)) < 0) || + (tsbpddelay >= 0 && libsrt_setsockopt(h, fd, SRTO_TSBPDDELAY, "SRTO_TSBPDELAY", &tsbpddelay, sizeof(tsbpddelay)) < 0) || + (s->tlpktdrop >= 0 && libsrt_setsockopt(h, fd, SRTO_TLPKTDROP, "SRTO_TLPKDROP", &s->tlpktdrop, sizeof(s->tlpktdrop)) < 0) || + (s->nakreport >= 0 && libsrt_setsockopt(h, fd, SRTO_NAKREPORT, "SRTO_NAKREPORT", &s->nakreport, sizeof(s->nakreport)) < 0) || + (connect_timeout >= 0 && libsrt_setsockopt(h, fd, SRTO_CONNTIMEO, "SRTO_CONNTIMEO", &connect_timeout, sizeof(connect_timeout)) <0 )) { + return AVERROR(EIO); + } + return 0; +} + + +static int libsrt_setup(URLContext *h, const char *uri, int flags) +{ + struct addrinfo hints = { 0 }, *ai, *cur_ai; + int port, fd = -1; + SRTContext *s = h->priv_data; + const char *p; + char buf[256]; + int ret; + char hostname[1024],proto[1024],path[1024]; + char portstr[10]; + int open_timeout = 5000000; + int eid; + + eid = srt_epoll_create(); + if (eid < 0) + return libsrt_neterrno(h); + s->eid = eid; + + av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), + &port, path, sizeof(path), uri); + if (strcmp(proto, "srt")) + return AVERROR(EINVAL); + if (port <= 0 || port >= 65536) { + av_log(h, AV_LOG_ERROR, "Port missing in uri\n"); + return AVERROR(EINVAL); + } + p = strchr(uri, '?'); + if (p) { + if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { + s->rw_timeout = strtol(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "listen_timeout", p)) { + s->listen_timeout = strtol(buf, NULL, 10); + } + } + if (s->rw_timeout >= 0) { + open_timeout = h->rw_timeout = s->rw_timeout; + } + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + snprintf(portstr, sizeof(portstr), "%d", port); + if (s->mode == SRT_MODE_LISTENER) + hints.ai_flags |= AI_PASSIVE; + ret = getaddrinfo(hostname[0] ? hostname : NULL, portstr, &hints, &ai); + if (ret) { + av_log(h, AV_LOG_ERROR, + "Failed to resolve hostname %s: %s\n", + hostname, gai_strerror(ret)); + return AVERROR(EIO); + } + + cur_ai = ai; + + restart: + + fd = srt_socket(cur_ai->ai_family, cur_ai->ai_socktype, 0); + if (fd < 0) { + ret = libsrt_neterrno(h); + goto fail; + } + + if ((ret = libsrt_set_options_pre(h, fd)) < 0) { + goto fail; + } + + /* Set the socket's send or receive buffer sizes, if specified. + If unspecified or setting fails, system default is used. */ + if (s->recv_buffer_size > 0) { + srt_setsockopt(fd, SOL_SOCKET, SRTO_UDP_RCVBUF, &s->recv_buffer_size, sizeof (s->recv_buffer_size)); + } + if (s->send_buffer_size > 0) { + srt_setsockopt(fd, SOL_SOCKET, SRTO_UDP_SNDBUF, &s->send_buffer_size, sizeof (s->send_buffer_size)); + } + if (s->mode == SRT_MODE_LISTENER) { + // multi-client + if ((ret = libsrt_listen(s->eid, fd, cur_ai->ai_addr, cur_ai->ai_addrlen, h, open_timeout / 1000)) < 0) + goto fail1; + fd = ret; + } else { + if (s->mode == SRT_MODE_RENDEZVOUS) { + ret = srt_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); + if (ret) + goto fail1; + } + + if ((ret = libsrt_listen_connect(s->eid, fd, cur_ai->ai_addr, cur_ai->ai_addrlen, + open_timeout / 1000, h, !!cur_ai->ai_next)) < 0) { + if (ret == AVERROR_EXIT) + goto fail1; + else + goto fail; + } + } + if ((ret = libsrt_set_options_post(h, fd)) < 0) { + goto fail; + } + + h->is_streamed = 1; + s->fd = fd; + + freeaddrinfo(ai); + return 0; + + fail: + if (cur_ai->ai_next) { + /* Retry with the next sockaddr */ + cur_ai = cur_ai->ai_next; + if (fd >= 0) + srt_close(fd); + ret = 0; + goto restart; + } + fail1: + if (fd >= 0) + srt_close(fd); + freeaddrinfo(ai); + return ret; +} + +static int libsrt_open(URLContext *h, const char *uri, int flags) +{ + SRTContext *s = h->priv_data; + const char * p; + char buf[256]; + + if (srt_startup() < 0) { + return AVERROR_UNKNOWN; + } + + /* SRT options (srt/srt.h) */ + p = strchr(uri, '?'); + if (p) { + if (av_find_info_tag(buf, sizeof(buf), "maxbw", p)) { + s->maxbw = strtoll(buf, NULL, 0); + } + if (av_find_info_tag(buf, sizeof(buf), "pbkeylen", p)) { + s->pbkeylen = strtol(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "passphrase", p)) { + s->passphrase = av_strndup(buf, strlen(buf)); + } + if (av_find_info_tag(buf, sizeof(buf), "mss", p)) { + s->mss = strtol(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "ffs", p)) { + s->ffs = strtol(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "ipttl", p)) { + s->ipttl = strtol(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "iptos", p)) { + s->iptos = strtol(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "inputbw", p)) { + s->inputbw = strtoll(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "oheadbw", p)) { + s->oheadbw = strtoll(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "tsbpddelay", p)) { + s->tsbpddelay = strtol(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "tlpktdrop", p)) { + s->tlpktdrop = strtol(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "nakreport", p)) { + s->nakreport = strtol(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "connect_timeout", p)) { + s->connect_timeout = strtol(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "mode", p)) { + if (!strcmp(buf, "caller")) { + s->mode = SRT_MODE_CALLER; + } else if (!strcmp(buf, "listener")) { + s->mode = SRT_MODE_LISTENER; + } else if (!strcmp(buf, "rendezvous")) { + s->mode = SRT_MODE_RENDEZVOUS; + } else { + return AVERROR(EIO); + } + } + } + return libsrt_setup(h, uri, flags); +} + +static int libsrt_read(URLContext *h, uint8_t *buf, int size) +{ + SRTContext *s = h->priv_data; + int ret; + + if (!(h->flags & AVIO_FLAG_NONBLOCK)) { + ret = libsrt_network_wait_fd_timeout(h, s->eid, s->fd, 0, h->rw_timeout, &h->interrupt_callback); + if (ret) + return ret; + } + + ret = srt_recvmsg(s->fd, buf, size); + if (ret < 0) { + ret = libsrt_neterrno(h); + } + + return ret; +} + +static int libsrt_write(URLContext *h, const uint8_t *buf, int size) +{ + SRTContext *s = h->priv_data; + int ret; + + if (!(h->flags & AVIO_FLAG_NONBLOCK)) { + ret = libsrt_network_wait_fd_timeout(h, s->eid, s->fd, 1, h->rw_timeout, &h->interrupt_callback); + if (ret) + return ret; + } + + ret = srt_sendmsg(s->fd, buf, size, -1, 0); + if (ret < 0) { + ret = libsrt_neterrno(h); + } + + return ret; +} + +static int libsrt_close(URLContext *h) +{ + SRTContext *s = h->priv_data; + + srt_close(s->fd); + + srt_epoll_release(s->eid); + + srt_cleanup(); + + return 0; +} + +static int libsrt_get_file_handle(URLContext *h) +{ + SRTContext *s = h->priv_data; + return s->fd; +} + +static const AVClass libsrt_class = { + .class_name = "libsrt", + .item_name = av_default_item_name, + .option = libsrt_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const URLProtocol ff_libsrt_protocol = { + .name = "srt", + .url_open = libsrt_open, + .url_read = libsrt_read, + .url_write = libsrt_write, + .url_close = libsrt_close, + .url_get_file_handle = libsrt_get_file_handle, + .priv_data_size = sizeof(SRTContext), + .flags = URL_PROTOCOL_FLAG_NETWORK, + .priv_data_class = &libsrt_class, +}; diff --git a/libavformat/protocols.c b/libavformat/protocols.c index 8ea5c0e75765a..15b9ed736d06c 100644 --- a/libavformat/protocols.c +++ b/libavformat/protocols.c @@ -56,6 +56,7 @@ extern const URLProtocol ff_librtmpe_protocol; extern const URLProtocol ff_librtmps_protocol; extern const URLProtocol ff_librtmpt_protocol; extern const URLProtocol ff_librtmpte_protocol; +extern const URLProtocol ff_libsrt_protocol; #include "libavformat/protocol_list.c" From 60c9a2553041152a32e7093756f728898593a585 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 18 Mar 2018 18:04:13 +0100 Subject: [PATCH 2262/2557] ffmpeg: fallback to codecpar parameters on input filter eof Fixes ticket #6854 and the following simpler case: ffmpeg -f lavfi -i testsrc=d=1 -f lavfi -i testsrc=d=0 -filter_complex overlay -f null none Signed-off-by: Marton Balint --- fftools/ffmpeg.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 1b2e37b8d808a..b72884673d423 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1829,6 +1829,19 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti print_final_stats(total_size); } +static void ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par) +{ + // We never got any input. Set a fake format, which will + // come from libavformat. + ifilter->format = par->format; + ifilter->sample_rate = par->sample_rate; + ifilter->channels = par->channels; + ifilter->channel_layout = par->channel_layout; + ifilter->width = par->width; + ifilter->height = par->height; + ifilter->sample_aspect_ratio = par->sample_aspect_ratio; +} + static void flush_encoders(void) { int i, ret; @@ -1855,18 +1868,8 @@ static void flush_encoders(void) int x; for (x = 0; x < fg->nb_inputs; x++) { InputFilter *ifilter = fg->inputs[x]; - if (ifilter->format < 0) { - AVCodecParameters *par = ifilter->ist->st->codecpar; - // We never got any input. Set a fake format, which will - // come from libavformat. - ifilter->format = par->format; - ifilter->sample_rate = par->sample_rate; - ifilter->channels = par->channels; - ifilter->channel_layout = par->channel_layout; - ifilter->width = par->width; - ifilter->height = par->height; - ifilter->sample_aspect_ratio = par->sample_aspect_ratio; - } + if (ifilter->format < 0) + ifilter_parameters_from_codecpar(ifilter, ifilter->ist->st->codecpar); } if (!ifilter_has_all_input_formats(fg)) @@ -2196,6 +2199,12 @@ static int ifilter_send_eof(InputFilter *ifilter, int64_t pts) } else { // the filtergraph was never configured FilterGraph *fg = ifilter->graph; + if (ifilter->format < 0) + ifilter_parameters_from_codecpar(ifilter, ifilter->ist->st->codecpar); + if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { + av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index); + return AVERROR_INVALIDDATA; + } for (i = 0; i < fg->nb_inputs; i++) if (!fg->inputs[i]->eof) break; From 0031eab61c82af7fca3aff4ced82c6ab9eb4e786 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 18 Mar 2018 18:34:23 +0100 Subject: [PATCH 2263/2557] ffmpeg: do not finish output streams manually on eof even if no input is provided The generic code should be able to finish the streams just fine initializing and flushing the filters and codecs properly. Fixes the following command: ffmpeg -f lavfi -i "testsrc=d=0.1[out0];aevalsrc=0:d=0[out1]" -af apad -shortest -f framecrc - Signed-off-by: Marton Balint --- fftools/ffmpeg.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index b72884673d423..4fcce8e2040a4 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2188,7 +2188,7 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) static int ifilter_send_eof(InputFilter *ifilter, int64_t pts) { - int i, j, ret; + int ret; ifilter->eof = 1; @@ -2205,16 +2205,6 @@ static int ifilter_send_eof(InputFilter *ifilter, int64_t pts) av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index); return AVERROR_INVALIDDATA; } - for (i = 0; i < fg->nb_inputs; i++) - if (!fg->inputs[i]->eof) - break; - if (i == fg->nb_inputs) { - // All the input streams have finished without the filtergraph - // ever being configured. - // Mark the output streams as finished. - for (j = 0; j < fg->nb_outputs; j++) - finish_output_stream(fg->outputs[j]->ost); - } } return 0; From 084ef7d7d542e238e56afd2ee8e64fe46d37104e Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 24 Mar 2018 22:57:34 +0100 Subject: [PATCH 2264/2557] avfilter/af_pan: reject expressions referencing the same channel multiple times Fixes parsing of expressions like c0=c0+c0 or c0=c0|c0=c1. Previously no error was thrown and for input channels, only the last gain factor was used, for output channels the source channel gains were combined. Signed-off-by: Marton Balint --- libavfilter/af_pan.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libavfilter/af_pan.c b/libavfilter/af_pan.c index d8a63a7952254..34e522c9d4eb2 100644 --- a/libavfilter/af_pan.c +++ b/libavfilter/af_pan.c @@ -104,6 +104,7 @@ static av_cold int init(AVFilterContext *ctx) char *arg, *arg0, *tokenizer, *args = av_strdup(pan->args); int out_ch_id, in_ch_id, len, named, ret, sign = 1; int nb_in_channels[2] = { 0, 0 }; // number of unnamed and named input channels + int used_out_ch[MAX_CHANNELS] = {0}; double gain; if (!pan->args) { @@ -127,6 +128,7 @@ static av_cold int init(AVFilterContext *ctx) /* parse channel specifications */ while ((arg = arg0 = av_strtok(NULL, "|", &tokenizer))) { + int used_in_ch[MAX_CHANNELS] = {0}; /* channel name */ if (parse_channel_name(&arg, &out_ch_id, &named)) { av_log(ctx, AV_LOG_ERROR, @@ -153,6 +155,13 @@ static av_cold int init(AVFilterContext *ctx) ret = AVERROR(EINVAL); goto fail; } + if (used_out_ch[out_ch_id]) { + av_log(ctx, AV_LOG_ERROR, + "Can not reference out channel %d twice\n", out_ch_id); + ret = AVERROR(EINVAL); + goto fail; + } + used_out_ch[out_ch_id] = 1; skip_spaces(&arg); if (*arg == '=') { arg++; @@ -184,6 +193,13 @@ static av_cold int init(AVFilterContext *ctx) ret = AVERROR(EINVAL); goto fail; } + if (used_in_ch[in_ch_id]) { + av_log(ctx, AV_LOG_ERROR, + "Can not reference in channel %d twice\n", in_ch_id); + ret = AVERROR(EINVAL); + goto fail; + } + used_in_ch[in_ch_id] = 1; pan->gain[out_ch_id][in_ch_id] = sign * gain; skip_spaces(&arg); if (!*arg) From 5c75438b893539dd17998c489fb4c540fc5a6e48 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 29 Mar 2018 01:07:24 +0200 Subject: [PATCH 2265/2557] avcodec/tableprint_vlc: Fix build failure with --enable-hardcoded-tables Found-by: James Almer Signed-off-by: Michael Niedermayer --- libavcodec/tableprint_vlc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/tableprint_vlc.h b/libavcodec/tableprint_vlc.h index 675251a836654..3004be3f9c859 100644 --- a/libavcodec/tableprint_vlc.h +++ b/libavcodec/tableprint_vlc.h @@ -35,6 +35,7 @@ #define av_freep(p) while(0) #define AVCODEC_AVCODEC_H #define AVCODEC_INTERNAL_H +#define AV_INPUT_BUFFER_PADDING_SIZE 64 // the value does not matter for this #include "tableprint.h" #include "get_bits.h" #include "mathtables.c" From d039d7d4a4a56861e210761902bcf0617e0800fa Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 28 Mar 2018 21:29:15 -0300 Subject: [PATCH 2266/2557] avcodec/libaomdec: remove references to yuv440p pixfmt While the enums are defined in the libaom headers, it's not officially supported. Signed-off-by: James Almer --- libavcodec/libaomdec.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index 5158ea8d76a30..29f0afd2ac445 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -102,9 +102,6 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) case AOM_IMG_FMT_I422: avctx->pix_fmt = AV_PIX_FMT_YUV422P; return 0; - case AOM_IMG_FMT_I440: - avctx->pix_fmt = AV_PIX_FMT_YUV440P; - return 0; case AOM_IMG_FMT_I444: avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? AV_PIX_FMT_GBRP : AV_PIX_FMT_YUV444P; @@ -135,19 +132,6 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) } else { return AVERROR_INVALIDDATA; } - case AOM_IMG_FMT_I44016: - if (img->bit_depth == 8) { - avctx->pix_fmt = AV_PIX_FMT_YUV440P; - return 0; - } else if (img->bit_depth == 10) { - avctx->pix_fmt = AV_PIX_FMT_YUV440P10; - return 0; - } else if (img->bit_depth == 12) { - avctx->pix_fmt = AV_PIX_FMT_YUV440P12; - return 0; - } else { - return AVERROR_INVALIDDATA; - } case AOM_IMG_FMT_I44416: if (img->bit_depth == 8) { avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? From c0f0c9f5318786904bc87f9278868ff3c3a7802d Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 28 Mar 2018 23:28:34 -0300 Subject: [PATCH 2267/2557] avcode/profiles: add AV1 profiles Signed-off-by: James Almer --- libavcodec/codec_desc.c | 1 + libavcodec/libaomdec.c | 14 ++++++++++++++ libavcodec/libaomenc.c | 2 ++ libavcodec/profiles.c | 7 +++++++ libavcodec/profiles.h | 1 + 5 files changed, 25 insertions(+) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index da7c0871a279e..79552a910d647 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1602,6 +1602,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "av1", .long_name = NULL_IF_CONFIG_SMALL("Alliance for Open Media AV1"), .props = AV_CODEC_PROP_LOSSY, + .profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), }, { .id = AV_CODEC_ID_BITPACKED, diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index 29f0afd2ac445..05e476c342448 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -31,6 +31,7 @@ #include "avcodec.h" #include "internal.h" +#include "profiles.h" typedef struct AV1DecodeContext { struct aom_codec_ctx decoder; @@ -98,23 +99,29 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) switch (img->fmt) { case AOM_IMG_FMT_I420: avctx->pix_fmt = AV_PIX_FMT_YUV420P; + avctx->profile = FF_PROFILE_AV1_MAIN; return 0; case AOM_IMG_FMT_I422: avctx->pix_fmt = AV_PIX_FMT_YUV422P; + avctx->profile = FF_PROFILE_AV1_PROFESSIONAL; return 0; case AOM_IMG_FMT_I444: avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? AV_PIX_FMT_GBRP : AV_PIX_FMT_YUV444P; + avctx->profile = FF_PROFILE_AV1_HIGH; return 0; case AOM_IMG_FMT_I42016: if (img->bit_depth == 8) { avctx->pix_fmt = AV_PIX_FMT_YUV420P; + avctx->profile = FF_PROFILE_AV1_MAIN; return 0; } else if (img->bit_depth == 10) { avctx->pix_fmt = AV_PIX_FMT_YUV420P10; + avctx->profile = FF_PROFILE_AV1_MAIN; return 0; } else if (img->bit_depth == 12) { avctx->pix_fmt = AV_PIX_FMT_YUV420P12; + avctx->profile = FF_PROFILE_AV1_PROFESSIONAL; return 0; } else { return AVERROR_INVALIDDATA; @@ -122,12 +129,15 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) case AOM_IMG_FMT_I42216: if (img->bit_depth == 8) { avctx->pix_fmt = AV_PIX_FMT_YUV422P; + avctx->profile = FF_PROFILE_AV1_PROFESSIONAL; return 0; } else if (img->bit_depth == 10) { avctx->pix_fmt = AV_PIX_FMT_YUV422P10; + avctx->profile = FF_PROFILE_AV1_PROFESSIONAL; return 0; } else if (img->bit_depth == 12) { avctx->pix_fmt = AV_PIX_FMT_YUV422P12; + avctx->profile = FF_PROFILE_AV1_PROFESSIONAL; return 0; } else { return AVERROR_INVALIDDATA; @@ -136,14 +146,17 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) if (img->bit_depth == 8) { avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? AV_PIX_FMT_GBRP : AV_PIX_FMT_YUV444P; + avctx->profile = FF_PROFILE_AV1_HIGH; return 0; } else if (img->bit_depth == 10) { avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? AV_PIX_FMT_GBRP10 : AV_PIX_FMT_YUV444P10; + avctx->profile = FF_PROFILE_AV1_HIGH; return 0; } else if (img->bit_depth == 12) { avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? AV_PIX_FMT_GBRP12 : AV_PIX_FMT_YUV444P12; + avctx->profile = FF_PROFILE_AV1_PROFESSIONAL; return 0; } else { return AVERROR_INVALIDDATA; @@ -229,5 +242,6 @@ AVCodec ff_libaom_av1_decoder = { .close = aom_free, .decode = aom_decode, .capabilities = AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_DR1, + .profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), .wrapper_name = "libaom", }; diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index a80bcbf522a9c..e5665cb5faad7 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -35,6 +35,7 @@ #include "avcodec.h" #include "internal.h" +#include "profiles.h" /* * Portion of struct aom_codec_cx_pkt from aom_encoder.h. @@ -735,6 +736,7 @@ AVCodec ff_libaom_av1_encoder = { .encode2 = aom_encode, .close = aom_free, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_EXPERIMENTAL, + .profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), .priv_class = &class_aom, .defaults = defaults, .init_static_data = av1_init_static, diff --git a/libavcodec/profiles.c b/libavcodec/profiles.c index 721587b3a6a00..d7dc960f36bb5 100644 --- a/libavcodec/profiles.c +++ b/libavcodec/profiles.c @@ -140,6 +140,13 @@ const AVProfile ff_vp9_profiles[] = { { FF_PROFILE_UNKNOWN }, }; +const AVProfile ff_av1_profiles[] = { + { FF_PROFILE_AV1_MAIN, "Main" }, + { FF_PROFILE_AV1_HIGH, "High" }, + { FF_PROFILE_AV1_PROFESSIONAL, "Professional" }, + { FF_PROFILE_UNKNOWN }, +}; + const AVProfile ff_sbc_profiles[] = { { FF_PROFILE_SBC_MSBC, "mSBC" }, { FF_PROFILE_UNKNOWN }, diff --git a/libavcodec/profiles.h b/libavcodec/profiles.h index 3783c10c397f7..9d7e211e15da3 100644 --- a/libavcodec/profiles.h +++ b/libavcodec/profiles.h @@ -31,6 +31,7 @@ extern const AVProfile ff_mpeg2_video_profiles[]; extern const AVProfile ff_mpeg4_video_profiles[]; extern const AVProfile ff_vc1_profiles[]; extern const AVProfile ff_vp9_profiles[]; +extern const AVProfile ff_av1_profiles[]; extern const AVProfile ff_sbc_profiles[]; #endif /* AVCODEC_PROFILES_H */ From 88e9b616b94a6d0aea020ea63a36e222e4e7ee18 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Mar 2018 00:36:51 -0300 Subject: [PATCH 2268/2557] libavcodec/libaomdec: use the matrix coefficients value from aom_image "color_space" is no longer a sytax element in libaom. Signed-off-by: James Almer --- libavcodec/libaomdec.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index 05e476c342448..1d077e035e397 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -85,16 +85,11 @@ static void image_copy_16_to_8(AVFrame *pic, struct aom_image *img) // returns 0 on success, AVERROR_INVALIDDATA otherwise static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) { - static const enum AVColorSpace colorspaces[10] = { - AVCOL_SPC_UNSPECIFIED, AVCOL_SPC_BT470BG, AVCOL_SPC_BT709, AVCOL_SPC_SMPTE170M, - AVCOL_SPC_SMPTE240M, AVCOL_SPC_BT2020_NCL, AVCOL_SPC_BT2020_CL, AVCOL_SPC_RGB, - AVCOL_SPC_ICTCP, AVCOL_SPC_RESERVED - }; static const enum AVColorRange color_ranges[] = { AVCOL_RANGE_MPEG, AVCOL_RANGE_JPEG }; avctx->color_range = color_ranges[img->range]; - avctx->colorspace = colorspaces[img->cs]; + avctx->colorspace = img->mc; switch (img->fmt) { case AOM_IMG_FMT_I420: From 416d354a576d0f3f25ef86a1891d2a9930683018 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Mar 2018 00:51:48 -0300 Subject: [PATCH 2269/2557] libavcodec/libaomenc: fix size specifier in an av_log call Signed-off-by: James Almer --- libavcodec/libaomenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index e5665cb5faad7..c424f14824177 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -110,7 +110,7 @@ static av_cold void dump_enc_cfg(AVCodecContext *avctx, width, "g_pass:", cfg->g_pass, width, "g_lag_in_frames:", cfg->g_lag_in_frames); av_log(avctx, level, "rate control settings\n" - " %*s%u\n %*s%d\n %*s%p("SIZE_SPECIFIER")\n %*s%u\n", + " %*s%u\n %*s%d\n %*s%p(%"SIZE_SPECIFIER")\n %*s%u\n", width, "rc_dropframe_thresh:", cfg->rc_dropframe_thresh, width, "rc_end_usage:", cfg->rc_end_usage, width, "rc_twopass_stats_in:", cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz, From 97de37da9c2973eea98e805b1f04920c9e00c374 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Mar 2018 01:03:14 -0300 Subject: [PATCH 2270/2557] libavcodec/libaomdec: add support for transfer characteristics and color primaries Signed-off-by: James Almer --- libavcodec/libaomdec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index 1d077e035e397..1352b421d9c26 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -89,7 +89,9 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) AVCOL_RANGE_MPEG, AVCOL_RANGE_JPEG }; avctx->color_range = color_ranges[img->range]; + avctx->color_primaries = img->cp; avctx->colorspace = img->mc; + avctx->color_trc = img->tc; switch (img->fmt) { case AOM_IMG_FMT_I420: From e5819fa62930966e6fb905cef21c985b91631d87 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Mar 2018 01:03:24 -0300 Subject: [PATCH 2271/2557] libavcodec/libaomenc: add support for transfer characteristics and color primaries Signed-off-by: James Almer --- libavcodec/libaomenc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index c424f14824177..7aac019b5bbca 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -74,6 +74,9 @@ static const char *const ctlidstr[] = { [AOME_SET_ENABLEAUTOALTREF] = "AOME_SET_ENABLEAUTOALTREF", [AOME_SET_STATIC_THRESHOLD] = "AOME_SET_STATIC_THRESHOLD", [AV1E_SET_COLOR_RANGE] = "AV1E_SET_COLOR_RANGE", + [AV1E_SET_COLOR_PRIMARIES] = "AV1E_SET_COLOR_PRIMARIES", + [AV1E_SET_MATRIX_COEFFICIENTS] = "AV1E_SET_MATRIX_COEFFICIENTS", + [AV1E_SET_TRANSFER_CHARACTERISTICS] = "AV1E_SET_TRANSFER_CHARACTERISTICS", }; static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc) @@ -449,6 +452,9 @@ static av_cold int aom_init(AVCodecContext *avctx, if (ctx->crf >= 0) codecctl_int(avctx, AOME_SET_CQ_LEVEL, ctx->crf); + codecctl_int(avctx, AV1E_SET_COLOR_PRIMARIES, avctx->color_primaries); + codecctl_int(avctx, AV1E_SET_MATRIX_COEFFICIENTS, avctx->colorspace); + codecctl_int(avctx, AV1E_SET_TRANSFER_CHARACTERISTICS, avctx->color_trc); set_color_range(avctx); // provide dummy value to initialize wrapper, values will be updated each _encode() From ae9297097696f3d06417a6e8a5368d5f38a6edb4 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 26 Mar 2018 13:47:29 +0200 Subject: [PATCH 2272/2557] avcodec/eac3: add support for dependent stream Signed-off-by: Paul B Mahol --- Changelog | 1 + libavcodec/aac_ac3_parser.c | 9 +- libavcodec/ac3_parser.c | 2 +- libavcodec/ac3dec.c | 179 +++++++++++++++++++++++++++++------- libavcodec/ac3dec.h | 10 +- libavcodec/eac3dec.c | 11 +-- tests/ref/fate/ts-demux | 2 +- tests/ref/seek/lavf-rm | 6 +- 8 files changed, 167 insertions(+), 53 deletions(-) diff --git a/Changelog b/Changelog index 08a1e7f9a40f2..41a18056dd4a0 100644 --- a/Changelog +++ b/Changelog @@ -49,6 +49,7 @@ version : - hapqa_extract bitstream filter - filter_units bitstream filter - AV1 Support through libaom +- E-AC-3 dependent frames support version 3.4: diff --git a/libavcodec/aac_ac3_parser.c b/libavcodec/aac_ac3_parser.c index 4e834b4424e78..019074b0dd43a 100644 --- a/libavcodec/aac_ac3_parser.c +++ b/libavcodec/aac_ac3_parser.c @@ -86,13 +86,16 @@ int ff_aac_ac3_parse(AVCodecParserContext *s1, the frame). */ if (avctx->codec_id != AV_CODEC_ID_AAC) { avctx->sample_rate = s->sample_rate; - avctx->channels = s->channels; - avctx->channel_layout = s->channel_layout; + if (avctx->codec_id != AV_CODEC_ID_EAC3) { + avctx->channels = s->channels; + avctx->channel_layout = s->channel_layout; + } s1->duration = s->samples; avctx->audio_service_type = s->service_type; } - avctx->bit_rate = s->bit_rate; + if (avctx->codec_id != AV_CODEC_ID_EAC3) + avctx->bit_rate = s->bit_rate; } return i; diff --git a/libavcodec/ac3_parser.c b/libavcodec/ac3_parser.c index 1015245a90d7a..f4618bf215ee4 100644 --- a/libavcodec/ac3_parser.c +++ b/libavcodec/ac3_parser.c @@ -218,8 +218,8 @@ static int ac3_sync(uint64_t state, AACAC3ParseContext *hdr_info, else if (hdr_info->codec_id == AV_CODEC_ID_NONE) hdr_info->codec_id = AV_CODEC_ID_AC3; - *need_next_header = (hdr.frame_type != EAC3_FRAME_TYPE_AC3_CONVERT); *new_frame_start = (hdr.frame_type != EAC3_FRAME_TYPE_DEPENDENT); + *need_next_header = *new_frame_start || (hdr.frame_type != EAC3_FRAME_TYPE_AC3_CONVERT); return hdr.frame_size; } diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index 244a18323f8bf..ac5c6d636a855 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -106,6 +106,25 @@ static const uint8_t ac3_default_coeffs[8][5][2] = { { { 2, 7 }, { 5, 5 }, { 7, 2 }, { 6, 7 }, { 7, 6 }, }, }; +static const uint64_t custom_channel_map_locations[16][2] = { + { 1, AV_CH_FRONT_LEFT }, + { 1, AV_CH_FRONT_CENTER }, + { 1, AV_CH_FRONT_RIGHT }, + { 1, AV_CH_SIDE_LEFT }, + { 1, AV_CH_SIDE_RIGHT }, + { 0, AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER }, + { 0, AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT }, + { 0, AV_CH_BACK_CENTER }, + { 0, AV_CH_TOP_CENTER }, + { 0, AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT }, + { 0, AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT }, + { 0, AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT}, + { 0, AV_CH_TOP_FRONT_CENTER }, + { 0, AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT }, + { 0, AV_CH_LOW_FREQUENCY_2 }, + { 1, AV_CH_LOW_FREQUENCY }, +}; + /** * Symmetrical Dequantization * reference: Section 7.3.3 Expansion of Mantissas for Symmetrical Quantization @@ -317,6 +336,7 @@ static int parse_frame_header(AC3DecodeContext *s) s->fbw_channels = s->channels - s->lfe_on; s->lfe_ch = s->fbw_channels + 1; s->frame_size = hdr.frame_size; + s->superframe_size += hdr.frame_size; s->preferred_downmix = AC3_DMIXMOD_NOTINDICATED; s->center_mix_level = hdr.center_mix_level; s->center_mix_level_ltrt = 4; // -3.0dB @@ -683,7 +703,7 @@ static void do_rematrixing(AC3DecodeContext *s) * Convert frequency domain coefficients to time-domain audio samples. * reference: Section 7.9.4 Transformation Equations */ -static inline void do_imdct(AC3DecodeContext *s, int channels) +static inline void do_imdct(AC3DecodeContext *s, int channels, int offset) { int ch; @@ -695,25 +715,25 @@ static inline void do_imdct(AC3DecodeContext *s, int channels) x[i] = s->transform_coeffs[ch][2 * i]; s->imdct_256.imdct_half(&s->imdct_256, s->tmp_output, x); #if USE_FIXED - s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1], + s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1 + offset], s->tmp_output, s->window, 128, 8); #else - s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1], + s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1 + offset], s->tmp_output, s->window, 128); #endif for (i = 0; i < 128; i++) x[i] = s->transform_coeffs[ch][2 * i + 1]; - s->imdct_256.imdct_half(&s->imdct_256, s->delay[ch - 1], x); + s->imdct_256.imdct_half(&s->imdct_256, s->delay[ch - 1 + offset], x); } else { s->imdct_512.imdct_half(&s->imdct_512, s->tmp_output, s->transform_coeffs[ch]); #if USE_FIXED - s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1], + s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1 + offset], s->tmp_output, s->window, 128, 8); #else - s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1], + s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1 + offset], s->tmp_output, s->window, 128); #endif - memcpy(s->delay[ch - 1], s->tmp_output + 128, 128 * sizeof(FFTSample)); + memcpy(s->delay[ch - 1 + offset], s->tmp_output + 128, 128 * sizeof(FFTSample)); } } } @@ -1063,7 +1083,7 @@ static inline int coupling_coordinates(AC3DecodeContext *s, int blk) /** * Decode a single audio block from the AC-3 bitstream. */ -static int decode_audio_block(AC3DecodeContext *s, int blk) +static int decode_audio_block(AC3DecodeContext *s, int blk, int offset) { int fbw_channels = s->fbw_channels; int channel_mode = s->channel_mode; @@ -1426,7 +1446,7 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) ac3_upmix_delay(s); } - do_imdct(s, s->channels); + do_imdct(s, s->channels, offset); if (downmix_output) { #if USE_FIXED @@ -1449,7 +1469,7 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) s->out_channels, s->fbw_channels, 128); } - do_imdct(s, s->out_channels); + do_imdct(s, s->out_channels, offset); } return 0; @@ -1463,14 +1483,19 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, { AVFrame *frame = data; const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; + int buf_size, full_buf_size = avpkt->size; AC3DecodeContext *s = avctx->priv_data; - int blk, ch, err, ret; + int blk, ch, err, offset, ret; + int got_independent_frame = 0; const uint8_t *channel_map; + uint8_t extended_channel_map[AC3_MAX_CHANNELS * 2]; const SHORTFLOAT *output[AC3_MAX_CHANNELS]; enum AVMatrixEncoding matrix_encoding; AVDownmixInfo *downmix_info; + s->superframe_size = 0; + + buf_size = full_buf_size; /* copy input buffer to decoder context to avoid reading past the end of the buffer, which can be caused by a damaged input stream. */ if (buf_size >= 2 && AV_RB16(buf) == 0x770B) { @@ -1488,6 +1513,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, av_lfg_init_from_data(&s->dith_state, s->input_buffer, FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE)); buf = s->input_buffer; +dependent_frame: /* initialize the GetBitContext with the start of valid AC-3 Frame */ if ((ret = init_get_bits8(&s->gbc, buf, buf_size)) < 0) return ret; @@ -1511,11 +1537,11 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, break; case AAC_AC3_PARSE_ERROR_FRAME_TYPE: /* skip frame if CRC is ok. otherwise use error concealment. */ - /* TODO: add support for substreams and dependent frames */ - if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT || s->substreamid) { + /* TODO: add support for substreams */ + if (s->substreamid) { av_log(avctx, AV_LOG_DEBUG, - "unsupported frame type %d: skipping frame\n", - s->frame_type); + "unsupported substream %d: skipping frame\n", + s->substreamid); *got_frame_ptr = 0; return buf_size; } else { @@ -1546,10 +1572,10 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, } } - /* if frame is ok, set audio parameters */ - if (!err) { - avctx->sample_rate = s->sample_rate; - avctx->bit_rate = s->bit_rate; + if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT && !got_independent_frame) { + av_log(avctx, AV_LOG_WARNING, "Ignoring dependent frame without independent frame.\n"); + *got_frame_ptr = 0; + return FFMIN(full_buf_size, s->frame_size); } /* channel config */ @@ -1594,29 +1620,25 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, if (s->bitstream_mode == 0x7 && s->channels > 1) avctx->audio_service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE; - /* get output buffer */ - frame->nb_samples = s->num_blocks * AC3_BLOCK_SIZE; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; - /* decode the audio blocks */ channel_map = ff_ac3_dec_channel_map[s->output_mode & ~AC3_OUTPUT_LFEON][s->lfe_on]; + offset = s->frame_type == EAC3_FRAME_TYPE_DEPENDENT ? AC3_MAX_CHANNELS : 0; for (ch = 0; ch < AC3_MAX_CHANNELS; ch++) { - output[ch] = s->output[ch]; - s->outptr[ch] = s->output[ch]; + output[ch] = s->output[ch + offset]; + s->outptr[ch] = s->output[ch + offset]; } for (ch = 0; ch < s->channels; ch++) { if (ch < s->out_channels) - s->outptr[channel_map[ch]] = (SHORTFLOAT *)frame->data[ch]; + s->outptr[channel_map[ch]] = s->output_buffer[ch + offset]; } for (blk = 0; blk < s->num_blocks; blk++) { - if (!err && decode_audio_block(s, blk)) { + if (!err && decode_audio_block(s, blk, offset)) { av_log(avctx, AV_LOG_ERROR, "error decoding the audio block\n"); err = 1; } if (err) for (ch = 0; ch < s->out_channels; ch++) - memcpy(((SHORTFLOAT*)frame->data[ch]) + AC3_BLOCK_SIZE*blk, output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT)); + memcpy(s->output_buffer[ch + offset] + AC3_BLOCK_SIZE*blk, output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT)); for (ch = 0; ch < s->out_channels; ch++) output[ch] = s->outptr[channel_map[ch]]; for (ch = 0; ch < s->out_channels; ch++) { @@ -1625,11 +1647,100 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, } } - frame->decode_error_flags = err ? FF_DECODE_ERROR_INVALID_BITSTREAM : 0; - /* keep last block for error concealment in next frame */ for (ch = 0; ch < s->out_channels; ch++) - memcpy(s->output[ch], output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT)); + memcpy(s->output[ch + offset], output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT)); + + /* check if there is dependent frame */ + if (buf_size > s->frame_size) { + AC3HeaderInfo hdr; + int err; + + if ((ret = init_get_bits8(&s->gbc, buf + s->frame_size, buf_size - s->frame_size)) < 0) + return ret; + + err = ff_ac3_parse_header(&s->gbc, &hdr); + if (err) + return err; + + if (hdr.frame_type == EAC3_FRAME_TYPE_DEPENDENT) { + if (hdr.num_blocks != s->num_blocks || s->sample_rate != hdr.sample_rate) { + av_log(avctx, AV_LOG_WARNING, "Ignoring non-compatible dependent frame.\n"); + } else { + buf += s->frame_size; + buf_size -= s->frame_size; + s->prev_output_mode = s->output_mode; + s->prev_bit_rate = s->bit_rate; + got_independent_frame = 1; + goto dependent_frame; + } + } + } + + frame->decode_error_flags = err ? FF_DECODE_ERROR_INVALID_BITSTREAM : 0; + + /* if frame is ok, set audio parameters */ + if (!err) { + avctx->sample_rate = s->sample_rate; + avctx->bit_rate = s->bit_rate + s->prev_bit_rate; + } + + for (ch = 0; ch < 16; ch++) + extended_channel_map[ch] = ch; + + if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) { + uint64_t ich_layout = avpriv_ac3_channel_layout_tab[s->prev_output_mode & ~AC3_OUTPUT_LFEON]; + uint64_t channel_layout; + int extend = 0; + + if (s->prev_output_mode & AC3_OUTPUT_LFEON) + ich_layout |= AV_CH_LOW_FREQUENCY; + + channel_layout = ich_layout; + for (ch = 0; ch < 16; ch++) { + if (s->channel_map & (1 << (15 - ch))) { + channel_layout |= custom_channel_map_locations[ch][1]; + } + } + + avctx->channel_layout = channel_layout; + avctx->channels = av_get_channel_layout_nb_channels(channel_layout); + + for (ch = 0; ch < 16; ch++) { + if (s->channel_map & (1 << (15 - ch))) { + if (custom_channel_map_locations[ch][0]) { + int index = av_get_channel_layout_channel_index(channel_layout, + custom_channel_map_locations[ch][1]); + if (index < 0) + return AVERROR_INVALIDDATA; + extended_channel_map[index] = offset + channel_map[extend++]; + } else { + int i; + + for (i = 0; i < 64; i++) { + if ((1LL << i) & custom_channel_map_locations[ch][1]) { + int index = av_get_channel_layout_channel_index(channel_layout, + 1LL << i); + if (index < 0) + return AVERROR_INVALIDDATA; + extended_channel_map[index] = offset + channel_map[extend++]; + } + } + } + } + } + } + + /* get output buffer */ + frame->nb_samples = s->num_blocks * AC3_BLOCK_SIZE; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + for (ch = 0; ch < avctx->channels; ch++) { + int map = extended_channel_map[ch]; + memcpy((SHORTFLOAT *)frame->data[ch], s->output_buffer[map], + s->num_blocks * AC3_BLOCK_SIZE * sizeof(SHORTFLOAT)); + } /* * AVMatrixEncoding @@ -1689,7 +1800,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, *got_frame_ptr = 1; - return FFMIN(buf_size, s->frame_size); + return FFMIN(full_buf_size, s->superframe_size); } /** diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h index aa4cf04f8a94e..ae5ef4bbc9c39 100644 --- a/libavcodec/ac3dec.h +++ b/libavcodec/ac3dec.h @@ -76,6 +76,7 @@ typedef struct AC3DecodeContext { ///@{ int frame_type; ///< frame type (strmtyp) int substreamid; ///< substream identification + int superframe_size; ///< current superframe size, in bytes int frame_size; ///< current frame size, in bytes int bit_rate; ///< stream bit rate, in bits-per-second int sample_rate; ///< sample frequency, in Hz @@ -87,7 +88,7 @@ typedef struct AC3DecodeContext { int dialog_normalization[2]; ///< dialog level in dBFS (dialnorm) int compression_exists[2]; ///< compression field is valid for frame (compre) int compression_gain[2]; ///< gain to apply for heavy compression (compr) - int channel_map; ///< custom channel map + int channel_map; ///< custom channel map (chanmap) int preferred_downmix; ///< Preferred 2-channel downmix mode (dmixmod) int center_mix_level; ///< Center mix level index int center_mix_level_ltrt; ///< Center mix level index for Lt/Rt (ltrtcmixlev) @@ -164,7 +165,9 @@ typedef struct AC3DecodeContext { SHORTFLOAT *downmix_coeffs[2]; ///< stereo downmix coefficients int downmixed; ///< indicates if coeffs are currently downmixed int output_mode; ///< output channel configuration + int prev_output_mode; ///< output channel configuration for previous frame int out_channels; ///< number of output channels + int prev_bit_rate; ///< stream bit rate, in bits-per-second for previous frame ///@} ///@name Dynamic range @@ -239,11 +242,12 @@ typedef struct AC3DecodeContext { ///@name Aligned arrays DECLARE_ALIGNED(16, int, fixed_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< fixed-point transform coefficients DECLARE_ALIGNED(32, INTFLOAT, transform_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< transform coefficients - DECLARE_ALIGNED(32, INTFLOAT, delay)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< delay - added to the next block + DECLARE_ALIGNED(32, INTFLOAT, delay)[2 * AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< delay - added to the next block DECLARE_ALIGNED(32, INTFLOAT, window)[AC3_BLOCK_SIZE]; ///< window coefficients DECLARE_ALIGNED(32, INTFLOAT, tmp_output)[AC3_BLOCK_SIZE]; ///< temporary storage for output before windowing - DECLARE_ALIGNED(32, SHORTFLOAT, output)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct transform and windowing + DECLARE_ALIGNED(32, SHORTFLOAT, output)[2 * AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct transform and windowing DECLARE_ALIGNED(32, uint8_t, input_buffer)[AC3_FRAME_BUFFER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; ///< temp buffer to prevent overread + DECLARE_ALIGNED(32, SHORTFLOAT, output_buffer)[2 * AC3_MAX_CHANNELS][AC3_BLOCK_SIZE * 6]; ///< final output buffer ///@} } AC3DecodeContext; diff --git a/libavcodec/eac3dec.c b/libavcodec/eac3dec.c index 6f6309f179c33..fe97d2903261b 100644 --- a/libavcodec/eac3dec.c +++ b/libavcodec/eac3dec.c @@ -303,13 +303,7 @@ static int ff_eac3_parse_header(AC3DecodeContext *s) /* An E-AC-3 stream can have multiple independent streams which the application can select from. each independent stream can also contain dependent streams which are used to add or replace channels. */ - if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) { - if (!s->eac3_frame_dependent_found) { - s->eac3_frame_dependent_found = 1; - avpriv_request_sample(s->avctx, "Dependent substream decoding"); - } - return AAC_AC3_PARSE_ERROR_FRAME_TYPE; - } else if (s->frame_type == EAC3_FRAME_TYPE_RESERVED) { + if (s->frame_type == EAC3_FRAME_TYPE_RESERVED) { av_log(s->avctx, AV_LOG_ERROR, "Reserved frame type\n"); return AAC_AC3_PARSE_ERROR_FRAME_TYPE; } @@ -355,7 +349,8 @@ static int ff_eac3_parse_header(AC3DecodeContext *s) /* dependent stream channel map */ if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) { if (get_bits1(gbc)) { - skip_bits(gbc, 16); // skip custom channel map + s->channel_map = get_bits(gbc, 16); + av_log(s->avctx, AV_LOG_DEBUG, "channel_map: %0X\n", s->channel_map); } } diff --git a/tests/ref/fate/ts-demux b/tests/ref/fate/ts-demux index e2931af427326..eb13ecc6840f9 100644 --- a/tests/ref/fate/ts-demux +++ b/tests/ref/fate/ts-demux @@ -13,7 +13,7 @@ 1, 0, 0, 2880, 1536, 0x773ffeea, S=1, 1, 0x00bd00bd 1, 2880, 2880, 2880, 1536, 0x6dc10748 1, 5760, 5760, 2880, 1536, 0xbab5129c -1, 8640, 8640, 2880, 1536, 0x602f034b +1, 8640, 8640, 2880, 1536, 0x602f034b, S=1, 1, 0x00bd00bd 1, 11520, 11520, 2880, 906, 0x69cdcbcd 0, 32037, 36541, 1501, 114336, 0x37a215a8, S=1, 1, 0x00e000e0 0, 33538, 33538, 1501, 12560, 0xb559a3d4, F=0x0, S=1, 1, 0x00e000e0 diff --git a/tests/ref/seek/lavf-rm b/tests/ref/seek/lavf-rm index 4b1917300e604..756e157fb3e5a 100644 --- a/tests/ref/seek/lavf-rm +++ b/tests/ref/seek/lavf-rm @@ -1,4 +1,4 @@ -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 395 size: 278 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 696 size: 31082 ret: 0 st:-1 flags:0 ts:-1.000000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 696 size: 31082 ret: 0 st:-1 flags:1 ts: 1.894167 @@ -20,7 +20,7 @@ ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 314992 size: 31143 ret: 0 st: 0 flags:1 ts: 1.048000 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 314992 size: 31143 ret: 0 st: 1 flags:0 ts:-0.058000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 395 size: 278 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 696 size: 31082 ret: 0 st: 1 flags:1 ts: 2.836000 ret: 0 st: 1 flags:1 dts: 0.975000 pts: 0.975000 pos: 346138 size: 278 ret: 0 st:-1 flags:0 ts: 1.730004 @@ -34,7 +34,7 @@ ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 314992 size: 31143 ret: 0 st: 1 flags:0 ts: 1.307000 ret: 0 st: 1 flags:1 dts: 0.975000 pts: 0.975000 pos: 346138 size: 278 ret: 0 st: 1 flags:1 ts: 0.201000 -ret: 0 st: 1 flags:1 dts: 0.174000 pts: 0.174000 pos: 78977 size: 278 +ret: 0 st: 0 flags:0 dts: 0.200000 pts: 0.200000 pos: 79274 size: 11400 ret: 0 st:-1 flags:0 ts:-0.904994 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 696 size: 31082 ret: 0 st:-1 flags:1 ts: 1.989173 From 2974b2556b2dae1347c9bee2ddc11c0d101a6d79 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 27 Mar 2018 16:47:24 +0200 Subject: [PATCH 2273/2557] avcodec: add eac3_core bitstream filter Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/bitstream_filters.texi | 4 ++ libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/eac3_core_bsf.c | 86 ++++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+) create mode 100644 libavcodec/eac3_core_bsf.c diff --git a/Changelog b/Changelog index 41a18056dd4a0..2869dce386960 100644 --- a/Changelog +++ b/Changelog @@ -50,6 +50,7 @@ version : - filter_units bitstream filter - AV1 Support through libaom - E-AC-3 dependent frames support +- bitstream filter for extracting E-AC-3 core version 3.4: diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 982e3edac8f10..7322af6550d5c 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -75,6 +75,10 @@ the header stored in extradata to the key packets: ffmpeg -i INPUT -map 0 -flags:v +global_header -c:v libx264 -bsf:v dump_extra out.ts @end example +@section eac3_core + +Extract the core from a E-AC-3 stream, dropping extra channels. + @section extract_extradata Extract the in-band extradata. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 404047d335652..4b8ad121dbeb6 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1043,6 +1043,7 @@ OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o mpeg4audio.o OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o OBJS-$(CONFIG_DCA_CORE_BSF) += dca_core_bsf.o +OBJS-$(CONFIG_EAC3_CORE_BSF) += eac3_core_bsf.o OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \ h2645_parse.o OBJS-$(CONFIG_FILTER_UNITS_BSF) += filter_units_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 12211225bb52f..18b698a85fc4a 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -28,6 +28,7 @@ extern const AVBitStreamFilter ff_aac_adtstoasc_bsf; extern const AVBitStreamFilter ff_chomp_bsf; extern const AVBitStreamFilter ff_dump_extradata_bsf; extern const AVBitStreamFilter ff_dca_core_bsf; +extern const AVBitStreamFilter ff_eac3_core_bsf; extern const AVBitStreamFilter ff_extract_extradata_bsf; extern const AVBitStreamFilter ff_filter_units_bsf; extern const AVBitStreamFilter ff_h264_metadata_bsf; diff --git a/libavcodec/eac3_core_bsf.c b/libavcodec/eac3_core_bsf.c new file mode 100644 index 0000000000000..3e4dc2e2a234c --- /dev/null +++ b/libavcodec/eac3_core_bsf.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "bsf.h" +#include "get_bits.h" +#include "ac3_parser_internal.h" + +static int eac3_core_filter(AVBSFContext *ctx, AVPacket *pkt) +{ + AC3HeaderInfo hdr; + GetBitContext gbc; + int ret; + + ret = ff_bsf_get_packet_ref(ctx, pkt); + if (ret < 0) + return ret; + ret = init_get_bits8(&gbc, pkt->data, pkt->size); + if (ret < 0) + goto fail; + + ret = ff_ac3_parse_header(&gbc, &hdr); + if (ret < 0) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + if (hdr.frame_type == EAC3_FRAME_TYPE_INDEPENDENT || + hdr.frame_type == EAC3_FRAME_TYPE_AC3_CONVERT) { + pkt->size = FFMIN(hdr.frame_size, pkt->size); + } else if (hdr.frame_type == EAC3_FRAME_TYPE_DEPENDENT && pkt->size > hdr.frame_size) { + AC3HeaderInfo hdr2; + + ret = init_get_bits8(&gbc, pkt->data + hdr.frame_size, pkt->size - hdr.frame_size); + if (ret < 0) + goto fail; + + ret = ff_ac3_parse_header(&gbc, &hdr2); + if (ret < 0) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + if (hdr2.frame_type == EAC3_FRAME_TYPE_INDEPENDENT || + hdr2.frame_type == EAC3_FRAME_TYPE_AC3_CONVERT) { + pkt->size -= hdr.frame_size; + pkt->data += hdr.frame_size; + } else { + pkt->size = 0; + } + } else { + pkt->size = 0; + } + + return 0; +fail: + av_packet_unref(pkt); + return ret; +} + +static const enum AVCodecID codec_ids[] = { + AV_CODEC_ID_EAC3, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_eac3_core_bsf = { + .name = "eac3_core", + .filter = eac3_core_filter, + .codec_ids = codec_ids, +}; From ae1a8b06907e53f2defea2b9d1844b50715db03f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 29 Mar 2018 10:31:45 +0200 Subject: [PATCH 2274/2557] doc/general.texi: fix warning Signed-off-by: Paul B Mahol --- doc/general.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/general.texi b/doc/general.texi index 00d5d684cecdc..41c6a59e99529 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -17,7 +17,7 @@ for more formats. None of them are used by default, their use has to be explicitly requested by passing the appropriate flags to @command{./configure}. -+@section Alliance for Open Media libaom +@section Alliance for Open Media libaom FFmpeg can make use of the libaom library for AV1 decoding. From 95e47654bce3f76360db2bbd9f34929a3434920a Mon Sep 17 00:00:00 2001 From: Nicolas Gaullier Date: Mon, 19 Feb 2018 14:15:30 +0100 Subject: [PATCH 2275/2557] lavfi/silencedetect: Add mono mode In mono mode, silence is detected in any single channel instead of all of them simultaneously --- libavfilter/af_silencedetect.c | 78 ++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 27 deletions(-) diff --git a/libavfilter/af_silencedetect.c b/libavfilter/af_silencedetect.c index b048d63738643..c53b9d9218c89 100644 --- a/libavfilter/af_silencedetect.c +++ b/libavfilter/af_silencedetect.c @@ -36,8 +36,10 @@ typedef struct SilenceDetectContext { const AVClass *class; double noise; ///< noise amplitude ratio double duration; ///< minimum duration of silence until notification - int64_t nb_null_samples; ///< current number of continuous zero samples - int64_t start; ///< if silence is detected, this value contains the time of the first zero sample + int mono; ///< mono mode : check each channel separately (default = check when ALL channels are silent) + int independant_channels; ///< number of entries in following arrays (always 1 in mono mode) + int64_t *nb_null_samples; ///< (array) current number of continuous zero samples + int64_t *start; ///< (array) if silence is detected, this value contains the time of the first zero sample int last_sample_rate; ///< last sample rate to check for sample rate changes void (*silencedetect)(struct SilenceDetectContext *s, AVFrame *insamples, @@ -52,44 +54,55 @@ static const AVOption silencedetect_options[] = { { "noise", "set noise tolerance", OFFSET(noise), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0, DBL_MAX, FLAGS }, { "d", "set minimum duration in seconds", OFFSET(duration), AV_OPT_TYPE_DOUBLE, {.dbl=2.}, 0, 24*60*60, FLAGS }, { "duration", "set minimum duration in seconds", OFFSET(duration), AV_OPT_TYPE_DOUBLE, {.dbl=2.}, 0, 24*60*60, FLAGS }, + { "mono", "check each channel separately", OFFSET(mono), AV_OPT_TYPE_BOOL, {.i64=0.}, 0, 1, FLAGS }, { NULL } }; AVFILTER_DEFINE_CLASS(silencedetect); -static char *get_metadata_val(AVFrame *insamples, const char *key) +static void set_meta(AVFrame *insamples, int channel, const char *key, char *value) { - AVDictionaryEntry *e = av_dict_get(insamples->metadata, key, NULL, 0); - return e && e->value ? e->value : NULL; -} + char key2[128]; + if (channel) + snprintf(key2, sizeof(key2), "lavfi.%s.%d", key, channel); + else + snprintf(key2, sizeof(key2), "lavfi.%s", key); + av_dict_set(&insamples->metadata, key2, value, 0); +} static av_always_inline void update(SilenceDetectContext *s, AVFrame *insamples, - int is_silence, int64_t nb_samples_notify, + int is_silence, int current_sample, int64_t nb_samples_notify, AVRational time_base) { + int channel = current_sample % s->independant_channels; if (is_silence) { - if (!s->start) { - s->nb_null_samples++; - if (s->nb_null_samples >= nb_samples_notify) { - s->start = insamples->pts - (int64_t)(s->duration / av_q2d(time_base) + .5); - av_dict_set(&insamples->metadata, "lavfi.silence_start", - av_ts2timestr(s->start, &time_base), 0); + if (!s->start[channel]) { + s->nb_null_samples[channel]++; + if (s->nb_null_samples[channel] >= nb_samples_notify) { + s->start[channel] = insamples->pts - (int64_t)(s->duration / av_q2d(time_base) + .5); + set_meta(insamples, s->mono ? channel + 1 : 0, "silence_start", + av_ts2timestr(s->start[channel], &time_base)); + if (s->mono) + av_log(s, AV_LOG_INFO, "channel: %d | ", channel); av_log(s, AV_LOG_INFO, "silence_start: %s\n", - get_metadata_val(insamples, "lavfi.silence_start")); + av_ts2timestr(s->start[channel], &time_base)); } } } else { - if (s->start) { - av_dict_set(&insamples->metadata, "lavfi.silence_end", - av_ts2timestr(insamples->pts, &time_base), 0); - av_dict_set(&insamples->metadata, "lavfi.silence_duration", - av_ts2timestr(insamples->pts - s->start, &time_base), 0); - av_log(s, AV_LOG_INFO, - "silence_end: %s | silence_duration: %s\n", - get_metadata_val(insamples, "lavfi.silence_end"), - get_metadata_val(insamples, "lavfi.silence_duration")); + if (s->start[channel]) { + int64_t end_pts = insamples->pts; + int64_t duration_ts = end_pts - s->start[channel]; + set_meta(insamples, s->mono ? channel + 1 : 0, "silence_end", + av_ts2timestr(end_pts, &time_base)); + set_meta(insamples, s->mono ? channel + 1 : 0, "silence_duration", + av_ts2timestr(duration_ts, &time_base)); + if (s->mono) + av_log(s, AV_LOG_INFO, "channel: %d | ", channel); + av_log(s, AV_LOG_INFO, "silence_end: %s | silence_duration: %s\n", + av_ts2timestr(end_pts, &time_base), + av_ts2timestr(duration_ts, &time_base)); } - s->nb_null_samples = s->start = 0; + s->nb_null_samples[channel] = s->start[channel] = 0; } } @@ -103,7 +116,7 @@ static void silencedetect_##name(SilenceDetectContext *s, AVFrame *insamples, int i; \ \ for (i = 0; i < nb_samples; i++, p++) \ - update(s, insamples, *p < noise && *p > -noise, \ + update(s, insamples, *p < noise && *p > -noise, i, \ nb_samples_notify, time_base); \ } @@ -117,6 +130,14 @@ static int config_input(AVFilterLink *inlink) AVFilterContext *ctx = inlink->dst; SilenceDetectContext *s = ctx->priv; + s->independant_channels = s->mono ? inlink->channels : 1; + s->nb_null_samples = av_mallocz_array(sizeof(*s->nb_null_samples), s->independant_channels); + if (!s->nb_null_samples) + return AVERROR(ENOMEM); + s->start = av_mallocz_array(sizeof(*s->start), s->independant_channels); + if (!s->start) + return AVERROR(ENOMEM); + switch (inlink->format) { case AV_SAMPLE_FMT_DBL: s->silencedetect = silencedetect_dbl; break; case AV_SAMPLE_FMT_FLT: s->silencedetect = silencedetect_flt; break; @@ -139,11 +160,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) const int nb_channels = inlink->channels; const int srate = inlink->sample_rate; const int nb_samples = insamples->nb_samples * nb_channels; - const int64_t nb_samples_notify = srate * s->duration * nb_channels; + const int64_t nb_samples_notify = srate * s->duration * (s->mono ? 1 : nb_channels); + int c; // scale number of null samples to the new sample rate if (s->last_sample_rate && s->last_sample_rate != srate) - s->nb_null_samples = srate * s->nb_null_samples / s->last_sample_rate; + for (c = 0; c < s->independant_channels; c++) { + s->nb_null_samples[c] = srate * s->nb_null_samples[c] / s->last_sample_rate; + } s->last_sample_rate = srate; // TODO: document metadata From 3deb17f9fb4779a9f2ccb73d182dedb943eaa791 Mon Sep 17 00:00:00 2001 From: Nicolas Gaullier Date: Mon, 19 Feb 2018 14:15:42 +0100 Subject: [PATCH 2276/2557] lavfi/silencedetect: Fix when silence_start=0 0 is a valid value for silence_start --- libavfilter/af_silencedetect.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libavfilter/af_silencedetect.c b/libavfilter/af_silencedetect.c index c53b9d9218c89..b4184c2486acf 100644 --- a/libavfilter/af_silencedetect.c +++ b/libavfilter/af_silencedetect.c @@ -39,7 +39,7 @@ typedef struct SilenceDetectContext { int mono; ///< mono mode : check each channel separately (default = check when ALL channels are silent) int independant_channels; ///< number of entries in following arrays (always 1 in mono mode) int64_t *nb_null_samples; ///< (array) current number of continuous zero samples - int64_t *start; ///< (array) if silence is detected, this value contains the time of the first zero sample + int64_t *start; ///< (array) if silence is detected, this value contains the time of the first zero sample (default/unset = INT64_MIN) int last_sample_rate; ///< last sample rate to check for sample rate changes void (*silencedetect)(struct SilenceDetectContext *s, AVFrame *insamples, @@ -76,7 +76,7 @@ static av_always_inline void update(SilenceDetectContext *s, AVFrame *insamples, { int channel = current_sample % s->independant_channels; if (is_silence) { - if (!s->start[channel]) { + if (s->start[channel] == INT64_MIN) { s->nb_null_samples[channel]++; if (s->nb_null_samples[channel] >= nb_samples_notify) { s->start[channel] = insamples->pts - (int64_t)(s->duration / av_q2d(time_base) + .5); @@ -89,7 +89,7 @@ static av_always_inline void update(SilenceDetectContext *s, AVFrame *insamples, } } } else { - if (s->start[channel]) { + if (s->start[channel] > INT64_MIN) { int64_t end_pts = insamples->pts; int64_t duration_ts = end_pts - s->start[channel]; set_meta(insamples, s->mono ? channel + 1 : 0, "silence_end", @@ -102,7 +102,8 @@ static av_always_inline void update(SilenceDetectContext *s, AVFrame *insamples, av_ts2timestr(end_pts, &time_base), av_ts2timestr(duration_ts, &time_base)); } - s->nb_null_samples[channel] = s->start[channel] = 0; + s->nb_null_samples[channel] = 0; + s->start[channel] = INT64_MIN; } } @@ -129,14 +130,17 @@ static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; SilenceDetectContext *s = ctx->priv; + int c; s->independant_channels = s->mono ? inlink->channels : 1; s->nb_null_samples = av_mallocz_array(sizeof(*s->nb_null_samples), s->independant_channels); if (!s->nb_null_samples) return AVERROR(ENOMEM); - s->start = av_mallocz_array(sizeof(*s->start), s->independant_channels); + s->start = av_malloc_array(sizeof(*s->start), s->independant_channels); if (!s->start) return AVERROR(ENOMEM); + for (c = 0; c < s->independant_channels; c++) + s->start[c] = INT64_MIN; switch (inlink->format) { case AV_SAMPLE_FMT_DBL: s->silencedetect = silencedetect_dbl; break; From cd4756a558195752abd1118953224d34e64b5243 Mon Sep 17 00:00:00 2001 From: Nicolas Gaullier Date: Mon, 19 Feb 2018 14:15:54 +0100 Subject: [PATCH 2277/2557] lavfi/silencedetect: Update test parameters Set relevant filter parameters such that the result can easily be checked with a waveform editor. In particular, it makes it clear the silence_start is not accurate in the current code. --- tests/fate/filter-video.mak | 3 +- tests/ref/fate/filter-metadata-silencedetect | 54 ++++++++++---------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 07572143a8257..0127f9bd138d7 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -730,7 +730,8 @@ fate-filter-metadata-cropdetect: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags SILENCEDETECT_DEPS = FFPROBE AVDEVICE LAVFI_INDEV AMOVIE_FILTER AMR_DEMUXER AMRWB_DECODER SILENCEDETECT_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(SILENCEDETECT_DEPS)) += fate-filter-metadata-silencedetect fate-filter-metadata-silencedetect: SRC = $(TARGET_SAMPLES)/amrwb/seed-12k65.awb -fate-filter-metadata-silencedetect: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',silencedetect=d=-20dB" +fate-filter-metadata-silencedetect: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',silencedetect=n=-42dB:d=.3" + EBUR128_METADATA_DEPS = FFPROBE AVDEVICE LAVFI_INDEV AMOVIE_FILTER FLAC_DEMUXER FLAC_DECODER EBUR128_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(EBUR128_METADATA_DEPS)) += fate-filter-metadata-ebur128 diff --git a/tests/ref/fate/filter-metadata-silencedetect b/tests/ref/fate/filter-metadata-silencedetect index 4161287e6c05f..d1d6f67dc059b 100644 --- a/tests/ref/fate/filter-metadata-silencedetect +++ b/tests/ref/fate/filter-metadata-silencedetect @@ -4,20 +4,20 @@ pkt_pts=640 pkt_pts=960 pkt_pts=1280 pkt_pts=1600 -pkt_pts=1920|tag:lavfi.silence_start=0.02 +pkt_pts=1920 pkt_pts=2240 -pkt_pts=2560|tag:lavfi.silence_end=0.16|tag:lavfi.silence_duration=0.14 +pkt_pts=2560 pkt_pts=2880 pkt_pts=3200 pkt_pts=3520 pkt_pts=3840 pkt_pts=4160 -pkt_pts=4480 +pkt_pts=4480|tag:lavfi.silence_start=-0.02 pkt_pts=4800 pkt_pts=5120 pkt_pts=5440 -pkt_pts=5760|tag:lavfi.silence_start=0.26|tag:lavfi.silence_end=0.36|tag:lavfi.silence_duration=0.1 -pkt_pts=6080 +pkt_pts=5760 +pkt_pts=6080|tag:lavfi.silence_end=0.38|tag:lavfi.silence_duration=0.4 pkt_pts=6400 pkt_pts=6720 pkt_pts=7040 @@ -67,12 +67,12 @@ pkt_pts=20800 pkt_pts=21120 pkt_pts=21440 pkt_pts=21760 -pkt_pts=22080|tag:lavfi.silence_start=1.28 +pkt_pts=22080 pkt_pts=22400 pkt_pts=22720 pkt_pts=23040 pkt_pts=23360 -pkt_pts=23680 +pkt_pts=23680|tag:lavfi.silence_start=1.18 pkt_pts=24000 pkt_pts=24320 pkt_pts=24640 @@ -97,7 +97,7 @@ pkt_pts=30400 pkt_pts=30720 pkt_pts=31040 pkt_pts=31360 -pkt_pts=31680|tag:lavfi.silence_end=1.98|tag:lavfi.silence_duration=0.7 +pkt_pts=31680|tag:lavfi.silence_end=1.98|tag:lavfi.silence_duration=0.8 pkt_pts=32000 pkt_pts=32320 pkt_pts=32640 @@ -160,10 +160,10 @@ pkt_pts=50560 pkt_pts=50880 pkt_pts=51200 pkt_pts=51520 -pkt_pts=51840 +pkt_pts=51840|tag:lavfi.silence_start=2.94 pkt_pts=52160 pkt_pts=52480 -pkt_pts=52800|tag:lavfi.silence_start=3.2 +pkt_pts=52800 pkt_pts=53120 pkt_pts=53440 pkt_pts=53760 @@ -193,10 +193,10 @@ pkt_pts=61120 pkt_pts=61440 pkt_pts=61760 pkt_pts=62080 -pkt_pts=62400|tag:lavfi.silence_end=3.9|tag:lavfi.silence_duration=0.7 +pkt_pts=62400 pkt_pts=62720 pkt_pts=63040 -pkt_pts=63360 +pkt_pts=63360|tag:lavfi.silence_end=3.96|tag:lavfi.silence_duration=1.02 pkt_pts=63680 pkt_pts=64000 pkt_pts=64320 @@ -248,9 +248,9 @@ pkt_pts=78720 pkt_pts=79040 pkt_pts=79360 pkt_pts=79680 -pkt_pts=80000|tag:lavfi.silence_start=4.9 +pkt_pts=80000 pkt_pts=80320 -pkt_pts=80640 +pkt_pts=80640|tag:lavfi.silence_start=4.74 pkt_pts=80960 pkt_pts=81280 pkt_pts=81600 @@ -270,7 +270,7 @@ pkt_pts=85760 pkt_pts=86080 pkt_pts=86400 pkt_pts=86720 -pkt_pts=87040|tag:lavfi.silence_end=5.44|tag:lavfi.silence_duration=0.54 +pkt_pts=87040|tag:lavfi.silence_end=5.44|tag:lavfi.silence_duration=0.7 pkt_pts=87360 pkt_pts=87680 pkt_pts=88000 @@ -325,8 +325,8 @@ pkt_pts=103360 pkt_pts=103680 pkt_pts=104000 pkt_pts=104320 -pkt_pts=104640|tag:lavfi.silence_start=6.44 -pkt_pts=104960 +pkt_pts=104640 +pkt_pts=104960|tag:lavfi.silence_start=6.26 pkt_pts=105280 pkt_pts=105600 pkt_pts=105920 @@ -361,8 +361,8 @@ pkt_pts=114880 pkt_pts=115200 pkt_pts=115520 pkt_pts=115840 -pkt_pts=116160|tag:lavfi.silence_end=7.26|tag:lavfi.silence_duration=0.82 -pkt_pts=116480 +pkt_pts=116160 +pkt_pts=116480|tag:lavfi.silence_end=7.28|tag:lavfi.silence_duration=1.02 pkt_pts=116800 pkt_pts=117120 pkt_pts=117440 @@ -425,19 +425,19 @@ pkt_pts=135360 pkt_pts=135680 pkt_pts=136000 pkt_pts=136320 -pkt_pts=136640 +pkt_pts=136640|tag:lavfi.silence_start=8.24 pkt_pts=136960 pkt_pts=137280 -pkt_pts=137600|tag:lavfi.silence_start=8.5 +pkt_pts=137600 pkt_pts=137920 pkt_pts=138240 pkt_pts=138560 -pkt_pts=138880|tag:lavfi.silence_end=8.68|tag:lavfi.silence_duration=0.18 +pkt_pts=138880 pkt_pts=139200 pkt_pts=139520 pkt_pts=139840 pkt_pts=140160 -pkt_pts=140480|tag:lavfi.silence_start=8.68 +pkt_pts=140480 pkt_pts=140800 pkt_pts=141120 pkt_pts=141440 @@ -447,12 +447,12 @@ pkt_pts=142400 pkt_pts=142720 pkt_pts=143040 pkt_pts=143360 -pkt_pts=143680|tag:lavfi.silence_end=8.98|tag:lavfi.silence_duration=0.3 +pkt_pts=143680 pkt_pts=144000 pkt_pts=144320 pkt_pts=144640 pkt_pts=144960 -pkt_pts=145280 +pkt_pts=145280|tag:lavfi.silence_end=9.08|tag:lavfi.silence_duration=0.84 pkt_pts=145600 pkt_pts=145920 pkt_pts=146240 @@ -503,8 +503,8 @@ pkt_pts=160320 pkt_pts=160640 pkt_pts=160960 pkt_pts=161280 -pkt_pts=161600|tag:lavfi.silence_start=10 -pkt_pts=161920 +pkt_pts=161600 +pkt_pts=161920|tag:lavfi.silence_start=9.82 pkt_pts=162240 pkt_pts=162560 pkt_pts=162880 From 56b2731aae33ea63bad06bca0a28569399be96ca Mon Sep 17 00:00:00 2001 From: Nicolas Gaullier Date: Mon, 19 Feb 2018 14:16:04 +0100 Subject: [PATCH 2278/2557] lavfi/silencedetect: Fix silence_start accuracy --- libavfilter/af_silencedetect.c | 7 ++++-- tests/ref/fate/filter-metadata-silencedetect | 26 ++++++++++---------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/libavfilter/af_silencedetect.c b/libavfilter/af_silencedetect.c index b4184c2486acf..749c3fbcb7ac1 100644 --- a/libavfilter/af_silencedetect.c +++ b/libavfilter/af_silencedetect.c @@ -37,6 +37,7 @@ typedef struct SilenceDetectContext { double noise; ///< noise amplitude ratio double duration; ///< minimum duration of silence until notification int mono; ///< mono mode : check each channel separately (default = check when ALL channels are silent) + int channels; ///< number of channels int independant_channels; ///< number of entries in following arrays (always 1 in mono mode) int64_t *nb_null_samples; ///< (array) current number of continuous zero samples int64_t *start; ///< (array) if silence is detected, this value contains the time of the first zero sample (default/unset = INT64_MIN) @@ -79,7 +80,8 @@ static av_always_inline void update(SilenceDetectContext *s, AVFrame *insamples, if (s->start[channel] == INT64_MIN) { s->nb_null_samples[channel]++; if (s->nb_null_samples[channel] >= nb_samples_notify) { - s->start[channel] = insamples->pts - (int64_t)(s->duration / av_q2d(time_base) + .5); + s->start[channel] = insamples->pts + av_rescale_q(current_sample / s->channels + 1 - nb_samples_notify * s->independant_channels / s->channels, + (AVRational){ 1, s->last_sample_rate }, time_base); set_meta(insamples, s->mono ? channel + 1 : 0, "silence_start", av_ts2timestr(s->start[channel], &time_base)); if (s->mono) @@ -132,7 +134,8 @@ static int config_input(AVFilterLink *inlink) SilenceDetectContext *s = ctx->priv; int c; - s->independant_channels = s->mono ? inlink->channels : 1; + s->channels = inlink->channels; + s->independant_channels = s->mono ? s->channels : 1; s->nb_null_samples = av_mallocz_array(sizeof(*s->nb_null_samples), s->independant_channels); if (!s->nb_null_samples) return AVERROR(ENOMEM); diff --git a/tests/ref/fate/filter-metadata-silencedetect b/tests/ref/fate/filter-metadata-silencedetect index d1d6f67dc059b..917b836250e9b 100644 --- a/tests/ref/fate/filter-metadata-silencedetect +++ b/tests/ref/fate/filter-metadata-silencedetect @@ -12,12 +12,12 @@ pkt_pts=3200 pkt_pts=3520 pkt_pts=3840 pkt_pts=4160 -pkt_pts=4480|tag:lavfi.silence_start=-0.02 +pkt_pts=4480|tag:lavfi.silence_start=0 pkt_pts=4800 pkt_pts=5120 pkt_pts=5440 pkt_pts=5760 -pkt_pts=6080|tag:lavfi.silence_end=0.38|tag:lavfi.silence_duration=0.4 +pkt_pts=6080|tag:lavfi.silence_end=0.38|tag:lavfi.silence_duration=0.38 pkt_pts=6400 pkt_pts=6720 pkt_pts=7040 @@ -72,7 +72,7 @@ pkt_pts=22400 pkt_pts=22720 pkt_pts=23040 pkt_pts=23360 -pkt_pts=23680|tag:lavfi.silence_start=1.18 +pkt_pts=23680|tag:lavfi.silence_start=1.18756 pkt_pts=24000 pkt_pts=24320 pkt_pts=24640 @@ -97,7 +97,7 @@ pkt_pts=30400 pkt_pts=30720 pkt_pts=31040 pkt_pts=31360 -pkt_pts=31680|tag:lavfi.silence_end=1.98|tag:lavfi.silence_duration=0.8 +pkt_pts=31680|tag:lavfi.silence_end=1.98|tag:lavfi.silence_duration=0.792438 pkt_pts=32000 pkt_pts=32320 pkt_pts=32640 @@ -160,7 +160,7 @@ pkt_pts=50560 pkt_pts=50880 pkt_pts=51200 pkt_pts=51520 -pkt_pts=51840|tag:lavfi.silence_start=2.94 +pkt_pts=51840|tag:lavfi.silence_start=2.945 pkt_pts=52160 pkt_pts=52480 pkt_pts=52800 @@ -196,7 +196,7 @@ pkt_pts=62080 pkt_pts=62400 pkt_pts=62720 pkt_pts=63040 -pkt_pts=63360|tag:lavfi.silence_end=3.96|tag:lavfi.silence_duration=1.02 +pkt_pts=63360|tag:lavfi.silence_end=3.96|tag:lavfi.silence_duration=1.015 pkt_pts=63680 pkt_pts=64000 pkt_pts=64320 @@ -250,7 +250,7 @@ pkt_pts=79360 pkt_pts=79680 pkt_pts=80000 pkt_pts=80320 -pkt_pts=80640|tag:lavfi.silence_start=4.74 +pkt_pts=80640|tag:lavfi.silence_start=4.75662 pkt_pts=80960 pkt_pts=81280 pkt_pts=81600 @@ -270,7 +270,7 @@ pkt_pts=85760 pkt_pts=86080 pkt_pts=86400 pkt_pts=86720 -pkt_pts=87040|tag:lavfi.silence_end=5.44|tag:lavfi.silence_duration=0.7 +pkt_pts=87040|tag:lavfi.silence_end=5.44|tag:lavfi.silence_duration=0.683375 pkt_pts=87360 pkt_pts=87680 pkt_pts=88000 @@ -326,7 +326,7 @@ pkt_pts=103680 pkt_pts=104000 pkt_pts=104320 pkt_pts=104640 -pkt_pts=104960|tag:lavfi.silence_start=6.26 +pkt_pts=104960|tag:lavfi.silence_start=6.27319 pkt_pts=105280 pkt_pts=105600 pkt_pts=105920 @@ -362,7 +362,7 @@ pkt_pts=115200 pkt_pts=115520 pkt_pts=115840 pkt_pts=116160 -pkt_pts=116480|tag:lavfi.silence_end=7.28|tag:lavfi.silence_duration=1.02 +pkt_pts=116480|tag:lavfi.silence_end=7.28|tag:lavfi.silence_duration=1.00681 pkt_pts=116800 pkt_pts=117120 pkt_pts=117440 @@ -425,7 +425,7 @@ pkt_pts=135360 pkt_pts=135680 pkt_pts=136000 pkt_pts=136320 -pkt_pts=136640|tag:lavfi.silence_start=8.24 +pkt_pts=136640|tag:lavfi.silence_start=8.25106 pkt_pts=136960 pkt_pts=137280 pkt_pts=137600 @@ -452,7 +452,7 @@ pkt_pts=144000 pkt_pts=144320 pkt_pts=144640 pkt_pts=144960 -pkt_pts=145280|tag:lavfi.silence_end=9.08|tag:lavfi.silence_duration=0.84 +pkt_pts=145280|tag:lavfi.silence_end=9.08|tag:lavfi.silence_duration=0.828937 pkt_pts=145600 pkt_pts=145920 pkt_pts=146240 @@ -504,7 +504,7 @@ pkt_pts=160640 pkt_pts=160960 pkt_pts=161280 pkt_pts=161600 -pkt_pts=161920|tag:lavfi.silence_start=9.82 +pkt_pts=161920|tag:lavfi.silence_start=9.83881 pkt_pts=162240 pkt_pts=162560 pkt_pts=162880 From 5170ab20e1f5278cc024a04e348828e38db3f361 Mon Sep 17 00:00:00 2001 From: Nicolas Gaullier Date: Mon, 19 Feb 2018 14:16:17 +0100 Subject: [PATCH 2279/2557] lavfi/silencedetect: Fix silence_end accuracy --- libavfilter/af_silencedetect.c | 3 ++- tests/ref/fate/filter-metadata-silencedetect | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libavfilter/af_silencedetect.c b/libavfilter/af_silencedetect.c index 749c3fbcb7ac1..8973049fe5e94 100644 --- a/libavfilter/af_silencedetect.c +++ b/libavfilter/af_silencedetect.c @@ -92,7 +92,8 @@ static av_always_inline void update(SilenceDetectContext *s, AVFrame *insamples, } } else { if (s->start[channel] > INT64_MIN) { - int64_t end_pts = insamples->pts; + int64_t end_pts = insamples->pts + av_rescale_q(current_sample / s->channels, + (AVRational){ 1, s->last_sample_rate }, time_base); int64_t duration_ts = end_pts - s->start[channel]; set_meta(insamples, s->mono ? channel + 1 : 0, "silence_end", av_ts2timestr(end_pts, &time_base)); diff --git a/tests/ref/fate/filter-metadata-silencedetect b/tests/ref/fate/filter-metadata-silencedetect index 917b836250e9b..e4be2ffac788e 100644 --- a/tests/ref/fate/filter-metadata-silencedetect +++ b/tests/ref/fate/filter-metadata-silencedetect @@ -17,7 +17,7 @@ pkt_pts=4800 pkt_pts=5120 pkt_pts=5440 pkt_pts=5760 -pkt_pts=6080|tag:lavfi.silence_end=0.38|tag:lavfi.silence_duration=0.38 +pkt_pts=6080|tag:lavfi.silence_end=0.384813|tag:lavfi.silence_duration=0.384813 pkt_pts=6400 pkt_pts=6720 pkt_pts=7040 @@ -97,7 +97,7 @@ pkt_pts=30400 pkt_pts=30720 pkt_pts=31040 pkt_pts=31360 -pkt_pts=31680|tag:lavfi.silence_end=1.98|tag:lavfi.silence_duration=0.792438 +pkt_pts=31680|tag:lavfi.silence_end=1.99538|tag:lavfi.silence_duration=0.807813 pkt_pts=32000 pkt_pts=32320 pkt_pts=32640 @@ -196,7 +196,7 @@ pkt_pts=62080 pkt_pts=62400 pkt_pts=62720 pkt_pts=63040 -pkt_pts=63360|tag:lavfi.silence_end=3.96|tag:lavfi.silence_duration=1.015 +pkt_pts=63360|tag:lavfi.silence_end=3.97138|tag:lavfi.silence_duration=1.02638 pkt_pts=63680 pkt_pts=64000 pkt_pts=64320 @@ -270,7 +270,7 @@ pkt_pts=85760 pkt_pts=86080 pkt_pts=86400 pkt_pts=86720 -pkt_pts=87040|tag:lavfi.silence_end=5.44|tag:lavfi.silence_duration=0.683375 +pkt_pts=87040|tag:lavfi.silence_end=5.45|tag:lavfi.silence_duration=0.693375 pkt_pts=87360 pkt_pts=87680 pkt_pts=88000 @@ -362,7 +362,7 @@ pkt_pts=115200 pkt_pts=115520 pkt_pts=115840 pkt_pts=116160 -pkt_pts=116480|tag:lavfi.silence_end=7.28|tag:lavfi.silence_duration=1.00681 +pkt_pts=116480|tag:lavfi.silence_end=7.28569|tag:lavfi.silence_duration=1.0125 pkt_pts=116800 pkt_pts=117120 pkt_pts=117440 @@ -452,7 +452,7 @@ pkt_pts=144000 pkt_pts=144320 pkt_pts=144640 pkt_pts=144960 -pkt_pts=145280|tag:lavfi.silence_end=9.08|tag:lavfi.silence_duration=0.828937 +pkt_pts=145280|tag:lavfi.silence_end=9.08156|tag:lavfi.silence_duration=0.8305 pkt_pts=145600 pkt_pts=145920 pkt_pts=146240 From 759381d96b221abb663627dc25135b76d8c2106a Mon Sep 17 00:00:00 2001 From: Nicolas Gaullier Date: Mon, 19 Feb 2018 14:16:30 +0100 Subject: [PATCH 2280/2557] lavfi/silencedetect: Fix missing log at eos Fixes ticket #6968 --- libavfilter/af_silencedetect.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/libavfilter/af_silencedetect.c b/libavfilter/af_silencedetect.c index 8973049fe5e94..6e321a5d9717f 100644 --- a/libavfilter/af_silencedetect.c +++ b/libavfilter/af_silencedetect.c @@ -41,7 +41,9 @@ typedef struct SilenceDetectContext { int independant_channels; ///< number of entries in following arrays (always 1 in mono mode) int64_t *nb_null_samples; ///< (array) current number of continuous zero samples int64_t *start; ///< (array) if silence is detected, this value contains the time of the first zero sample (default/unset = INT64_MIN) + int64_t frame_end; ///< pts of the end of the current frame (used to compute duration of silence at EOS) int last_sample_rate; ///< last sample rate to check for sample rate changes + AVRational time_base; ///< time_base void (*silencedetect)(struct SilenceDetectContext *s, AVFrame *insamples, int nb_samples, int64_t nb_samples_notify, @@ -92,13 +94,16 @@ static av_always_inline void update(SilenceDetectContext *s, AVFrame *insamples, } } else { if (s->start[channel] > INT64_MIN) { - int64_t end_pts = insamples->pts + av_rescale_q(current_sample / s->channels, - (AVRational){ 1, s->last_sample_rate }, time_base); + int64_t end_pts = insamples ? insamples->pts + av_rescale_q(current_sample / s->channels, + (AVRational){ 1, s->last_sample_rate }, time_base) + : s->frame_end; int64_t duration_ts = end_pts - s->start[channel]; - set_meta(insamples, s->mono ? channel + 1 : 0, "silence_end", - av_ts2timestr(end_pts, &time_base)); - set_meta(insamples, s->mono ? channel + 1 : 0, "silence_duration", - av_ts2timestr(duration_ts, &time_base)); + if (insamples) { + set_meta(insamples, s->mono ? channel + 1 : 0, "silence_end", + av_ts2timestr(end_pts, &time_base)); + set_meta(insamples, s->mono ? channel + 1 : 0, "silence_duration", + av_ts2timestr(duration_ts, &time_base)); + } if (s->mono) av_log(s, AV_LOG_INFO, "channel: %d | ", channel); av_log(s, AV_LOG_INFO, "silence_end: %s | silence_duration: %s\n", @@ -177,6 +182,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) s->nb_null_samples[c] = srate * s->nb_null_samples[c] / s->last_sample_rate; } s->last_sample_rate = srate; + s->time_base = inlink->time_base; + s->frame_end = insamples->pts + av_rescale_q(insamples->nb_samples, + (AVRational){ 1, s->last_sample_rate }, inlink->time_base); // TODO: document metadata s->silencedetect(s, insamples, nb_samples, nb_samples_notify, @@ -218,6 +226,18 @@ static int query_formats(AVFilterContext *ctx) return ff_set_common_samplerates(ctx, formats); } +static av_cold void uninit(AVFilterContext *ctx) +{ + SilenceDetectContext *s = ctx->priv; + int c; + + for (c = 0; c < s->independant_channels; c++) + if (s->start[c] > INT64_MIN) + update(s, NULL, 0, c, 0, s->time_base); + av_freep(&s->nb_null_samples); + av_freep(&s->start); +} + static const AVFilterPad silencedetect_inputs[] = { { .name = "default", @@ -241,6 +261,7 @@ AVFilter ff_af_silencedetect = { .description = NULL_IF_CONFIG_SMALL("Detect silence."), .priv_size = sizeof(SilenceDetectContext), .query_formats = query_formats, + .uninit = uninit, .inputs = silencedetect_inputs, .outputs = silencedetect_outputs, .priv_class = &silencedetect_class, From f6171471e6cfbd472f7ab71c12aa87510a07d4fd Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Mar 2018 13:02:56 -0300 Subject: [PATCH 2281/2557] avcodec: rename the AV1 profiles Use the proper names instead of numbers Signed-off-by: James Almer --- libavcodec/avcodec.h | 6 +++--- libavcodec/libaomenc.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index ac0915328ca9c..eb234a40d6a59 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2551,9 +2551,9 @@ typedef struct AVCodecContext { #define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3 #define FF_PROFILE_HEVC_REXT 4 -#define FF_PROFILE_AV1_0 0 -#define FF_PROFILE_AV1_1 1 -#define FF_PROFILE_AV1_2 2 +#define FF_PROFILE_AV1_MAIN 0 +#define FF_PROFILE_AV1_HIGH 1 +#define FF_PROFILE_AV1_PROFESSIONAL 2 /** * level diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index 94b3ddd326551..a2a2c3994b097 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -302,13 +302,13 @@ static av_cold int aom_init(AVCodecContext *avctx) if (avctx->profile != FF_PROFILE_UNKNOWN) enccfg.g_profile = avctx->profile; else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) - avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_0; + avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_MAIN; else { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); if (desc->comp[0].depth < 12) - avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_1; + avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_HIGH; else - avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_2; + avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_PROFESSIONAL; } From ea3320bb828553182fb34e164826f95df5743522 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Mar 2018 13:03:04 -0300 Subject: [PATCH 2282/2557] libaomenc: fix profile setting Main Profile is yuv420p 8 and 10 bit High Profile is yuv444p 8 and 10 bit Professional Profile is yuv422p 8, 10, and 12 bit, plus every other pixfmt at 12 bit Signed-off-by: James Almer --- libavcodec/libaomenc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index a2a2c3994b097..9807bd5adb30b 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -301,14 +301,14 @@ static av_cold int aom_init(AVCodecContext *avctx) * quality. */ if (avctx->profile != FF_PROFILE_UNKNOWN) enccfg.g_profile = avctx->profile; - else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) + else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P || + avctx->pix_fmt == AV_PIX_FMT_YUV420P10) avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_MAIN; + else if (avctx->pix_fmt == AV_PIX_FMT_YUV444P || + avctx->pix_fmt == AV_PIX_FMT_YUV444P10) + avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_HIGH; else { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); - if (desc->comp[0].depth < 12) - avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_HIGH; - else - avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_PROFESSIONAL; + avctx->profile = enccfg.g_profile = FF_PROFILE_AV1_PROFESSIONAL; } From a8a751ce9aaad4f466ccd9b0852709e063c2ba74 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 29 Mar 2018 20:46:36 +0200 Subject: [PATCH 2283/2557] avformat/mpc8: do not return error on stream end Signed-off-by: Paul B Mahol --- libavformat/mpc8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mpc8.c b/libavformat/mpc8.c index f280faa5ccd0b..79e5f6a9ab648 100644 --- a/libavformat/mpc8.c +++ b/libavformat/mpc8.c @@ -297,7 +297,7 @@ static int mpc8_read_packet(AVFormatContext *s, AVPacket *pkt) return 0; } if(tag == TAG_STREAMEND) - return AVERROR(EIO); + return AVERROR_EOF; mpc8_handle_chunk(s, tag, pos, size); } return AVERROR_EOF; From 25abaf3545f071ae137cfb66f03a2ae181bc28cd Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Mar 2018 16:18:27 -0300 Subject: [PATCH 2284/2557] avcodec/libaomenc: minor cosmetics Signed-off-by: James Almer --- libavcodec/libaomenc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index 7aac019b5bbca..f075bf4de7969 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -344,8 +344,7 @@ static av_cold int aom_init(AVCodecContext *avctx, if (avctx->bit_rate) { enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000, AV_ROUND_NEAR_INF); - } else if (enccfg.rc_end_usage == AOM_Q) { - } else { + } else if (enccfg.rc_end_usage != AOM_Q) { if (enccfg.rc_end_usage == AOM_CQ) { enccfg.rc_target_bitrate = 1000000; } else { @@ -361,8 +360,7 @@ static av_cold int aom_init(AVCodecContext *avctx, if (avctx->qmax >= 0) enccfg.rc_max_quantizer = avctx->qmax; - if (enccfg.rc_end_usage == AOM_CQ || enccfg.rc_end_usage == AOM_Q - ) { + if (enccfg.rc_end_usage == AOM_CQ || enccfg.rc_end_usage == AOM_Q) { if (ctx->crf < enccfg.rc_min_quantizer || ctx->crf > enccfg.rc_max_quantizer) { av_log(avctx, AV_LOG_ERROR, "CQ level %d must be between minimum and maximum quantizer value (%d-%d)\n", From ea15915b2dc5aaa80c91879fbd183475a7e66e54 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 25 Mar 2018 01:51:28 +0100 Subject: [PATCH 2285/2557] avcodec/wmalosslessdec: Fix null pointer dereference in decode_frame() Fixes: 2018_03_23_poc.wav Found-by: GwanYeong Kim Signed-off-by: Michael Niedermayer --- libavcodec/wmalosslessdec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index 59e89295867e2..eb1db615ae180 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -1256,7 +1256,9 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, (frame_size = show_bits(gb, s->log2_frame_size)) && frame_size <= remaining_bits(s, gb)) { save_bits(s, gb, frame_size, 0); - s->packet_done = !decode_frame(s); + + if (!s->packet_loss) + s->packet_done = !decode_frame(s); } else if (!s->len_prefix && s->num_saved_bits > get_bits_count(&s->gb)) { /* when the frames do not have a length prefix, we don't know the From c42c99c3e5ac4f5fe55e06d5cbdfe8a83beed0e8 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 29 Mar 2018 22:35:33 -0300 Subject: [PATCH 2286/2557] avcodec/libaomenc: use av_assert0() Signed-off-by: James Almer --- libavcodec/libaomenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index f075bf4de7969..8ebdcc20e3ef2 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -27,6 +27,7 @@ #include #include +#include "libavutil/avassert.h" #include "libavutil/base64.h" #include "libavutil/common.h" #include "libavutil/mathematics.h" @@ -546,7 +547,7 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out) /* avoid storing the frame when the list is empty and we haven't yet * provided a frame for output */ - assert(!ctx->coded_frame_list); + av_assert0(!ctx->coded_frame_list); cx_pktcpy(&cx_frame, pkt); size = storeframe(avctx, &cx_frame, pkt_out); if (size < 0) From af043b839c38e850af1184fd6be691f8475c048e Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Tue, 27 Mar 2018 19:55:24 -0700 Subject: [PATCH 2287/2557] movtextenc: fix handling of utf-8 subtitles See the earlier fix for movtextdec for details. The equivalent bug is present on the encoder side as well. We need to track the text length in 'characters' (which seems to really mean codepoints) to ensure that styles are applied across the correct ranges. --- libavcodec/movtextenc.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c index d795e317c3f9e..c19ef384bcf92 100644 --- a/libavcodec/movtextenc.c +++ b/libavcodec/movtextenc.c @@ -72,6 +72,7 @@ typedef struct { uint8_t style_fontsize; uint32_t style_color; uint16_t text_pos; + uint16_t byte_count; } MovTextContext; typedef struct { @@ -304,11 +305,34 @@ static void mov_text_color_cb(void *priv, unsigned int color, unsigned int color */ } +static uint16_t utf8_strlen(const char *text, int len) +{ + uint16_t i = 0, ret = 0; + while (i < len) { + char c = text[i]; + if ((c & 0x80) == 0) + i += 1; + else if ((c & 0xE0) == 0xC0) + i += 2; + else if ((c & 0xF0) == 0xE0) + i += 3; + else if ((c & 0xF8) == 0xF0) + i += 4; + else + return 0; + ret++; + } + return ret; +} + static void mov_text_text_cb(void *priv, const char *text, int len) { + uint16_t utf8_len = utf8_strlen(text, len); MovTextContext *s = priv; av_bprint_append_data(&s->buffer, text, len); - s->text_pos += len; + // If it's not utf-8, just use the byte length + s->text_pos += utf8_len ? utf8_len : len; + s->byte_count += len; } static void mov_text_new_line_cb(void *priv, int forced) @@ -316,6 +340,7 @@ static void mov_text_new_line_cb(void *priv, int forced) MovTextContext *s = priv; av_bprint_append_data(&s->buffer, "\n", 1); s->text_pos += 1; + s->byte_count += 1; } static const ASSCodesCallbacks mov_text_callbacks = { @@ -333,6 +358,7 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, int i, length; size_t j; + s->byte_count = 0; s->text_pos = 0; s->count = 0; s->box_flags = 0; @@ -368,7 +394,7 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, } } - AV_WB16(buf, s->text_pos); + AV_WB16(buf, s->byte_count); buf += 2; if (!av_bprint_is_complete(&s->buffer)) { From 91bb871376730a2394ed0ae1a3fd4295977002d3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 29 Mar 2018 21:36:56 +0200 Subject: [PATCH 2288/2557] avcodec/mpc8: check for overread first Signed-off-by: Paul B Mahol --- libavcodec/mpc8.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/mpc8.c b/libavcodec/mpc8.c index 80e0e9e68df89..355a9d2f3fb54 100644 --- a/libavcodec/mpc8.c +++ b/libavcodec/mpc8.c @@ -419,11 +419,11 @@ static int mpc8_decode_frame(AVCodecContext * avctx, void *data, c->last_bits_used = get_bits_count(gb); if(c->cur_frame >= c->frames) c->cur_frame = 0; - if(c->cur_frame == 0 && get_bits_left(gb) < 8) {// we have only padding left - c->last_bits_used = buf_size << 3; - } else if (get_bits_left(gb) < 0) { + if (get_bits_left(gb) < 0) { av_log(avctx, AV_LOG_ERROR, "Overread %d\n", -get_bits_left(gb)); c->last_bits_used = buf_size << 3; + } else if (c->cur_frame == 0 && get_bits_left(gb) < 8) {// we have only padding left + c->last_bits_used = buf_size << 3; } *got_frame_ptr = 1; From e744281c49496b0e0a357e9f84c37fbf99215e20 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Thu, 29 Mar 2018 09:24:34 +0200 Subject: [PATCH 2289/2557] configure: Revert some incorrect uses of check_cc() --- configure | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/configure b/configure index 7612a6052c0bd..77754d0f51252 100755 --- a/configure +++ b/configure @@ -4846,7 +4846,9 @@ check_disable_warning_headers -Wno-unused-variable check_objcflags -fobjc-arc && enable objc_arc -check_cc blocks_extension "" "void (^block)(void)" +test_cc < Date: Fri, 30 Mar 2018 10:14:48 +0200 Subject: [PATCH 2290/2557] avcodec/ac3: fix out of array access introduced previously Signed-off-by: Paul B Mahol --- libavcodec/ac3.h | 1 + libavcodec/ac3dec.c | 10 +++++----- libavcodec/ac3dec.h | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libavcodec/ac3.h b/libavcodec/ac3.h index 5c9c37727e7df..f8f6a81f45105 100644 --- a/libavcodec/ac3.h +++ b/libavcodec/ac3.h @@ -28,6 +28,7 @@ #define AVCODEC_AC3_H #define AC3_MAX_CODED_FRAME_SIZE 3840 /* in bytes */ +#define EAC3_MAX_CHANNELS 16 /**< maximum number of channels in EAC3 */ #define AC3_MAX_CHANNELS 7 /**< maximum number of channels, including coupling channel */ #define CPL_CH 0 /**< coupling channel index */ diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index ac5c6d636a855..b14d2e74ace8d 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -1488,7 +1488,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int blk, ch, err, offset, ret; int got_independent_frame = 0; const uint8_t *channel_map; - uint8_t extended_channel_map[AC3_MAX_CHANNELS * 2]; + uint8_t extended_channel_map[EAC3_MAX_CHANNELS]; const SHORTFLOAT *output[AC3_MAX_CHANNELS]; enum AVMatrixEncoding matrix_encoding; AVDownmixInfo *downmix_info; @@ -1685,7 +1685,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, avctx->bit_rate = s->bit_rate + s->prev_bit_rate; } - for (ch = 0; ch < 16; ch++) + for (ch = 0; ch < EAC3_MAX_CHANNELS; ch++) extended_channel_map[ch] = ch; if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) { @@ -1698,7 +1698,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, channel_layout = ich_layout; for (ch = 0; ch < 16; ch++) { - if (s->channel_map & (1 << (15 - ch))) { + if (s->channel_map & (1 << (EAC3_MAX_CHANNELS - ch - 1))) { channel_layout |= custom_channel_map_locations[ch][1]; } } @@ -1706,8 +1706,8 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, avctx->channel_layout = channel_layout; avctx->channels = av_get_channel_layout_nb_channels(channel_layout); - for (ch = 0; ch < 16; ch++) { - if (s->channel_map & (1 << (15 - ch))) { + for (ch = 0; ch < EAC3_MAX_CHANNELS; ch++) { + if (s->channel_map & (1 << (EAC3_MAX_CHANNELS - ch - 1))) { if (custom_channel_map_locations[ch][0]) { int index = av_get_channel_layout_channel_index(channel_layout, custom_channel_map_locations[ch][1]); diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h index ae5ef4bbc9c39..ce1434b55c9d9 100644 --- a/libavcodec/ac3dec.h +++ b/libavcodec/ac3dec.h @@ -242,12 +242,12 @@ typedef struct AC3DecodeContext { ///@name Aligned arrays DECLARE_ALIGNED(16, int, fixed_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< fixed-point transform coefficients DECLARE_ALIGNED(32, INTFLOAT, transform_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< transform coefficients - DECLARE_ALIGNED(32, INTFLOAT, delay)[2 * AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< delay - added to the next block + DECLARE_ALIGNED(32, INTFLOAT, delay)[EAC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< delay - added to the next block DECLARE_ALIGNED(32, INTFLOAT, window)[AC3_BLOCK_SIZE]; ///< window coefficients DECLARE_ALIGNED(32, INTFLOAT, tmp_output)[AC3_BLOCK_SIZE]; ///< temporary storage for output before windowing - DECLARE_ALIGNED(32, SHORTFLOAT, output)[2 * AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct transform and windowing + DECLARE_ALIGNED(32, SHORTFLOAT, output)[EAC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct transform and windowing DECLARE_ALIGNED(32, uint8_t, input_buffer)[AC3_FRAME_BUFFER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; ///< temp buffer to prevent overread - DECLARE_ALIGNED(32, SHORTFLOAT, output_buffer)[2 * AC3_MAX_CHANNELS][AC3_BLOCK_SIZE * 6]; ///< final output buffer + DECLARE_ALIGNED(32, SHORTFLOAT, output_buffer)[EAC3_MAX_CHANNELS][AC3_BLOCK_SIZE * 6]; ///< final output buffer ///@} } AC3DecodeContext; From 9b22417de680fcae289eb4d0e036bc09912902eb Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 29 Mar 2018 11:10:20 +0200 Subject: [PATCH 2291/2557] fate: add eac3_core bitstream filter test Signed-off-by: Paul B Mahol --- tests/fate/ac3.mak | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/fate/ac3.mak b/tests/fate/ac3.mak index 76be2e869a3e7..26d2bf3e1cd89 100644 --- a/tests/fate/ac3.mak +++ b/tests/fate/ac3.mak @@ -88,6 +88,11 @@ fate-ac3-fixed-encode: CMD = md5 -i $(SRC) -c ac3_fixed -ab 128k -f ac3 -flags + fate-ac3-fixed-encode: CMP = oneline fate-ac3-fixed-encode: REF = a1d1fc116463b771abf5aef7ed37d7b1 +FATE_EAC3-$(call ALLYES, EAC3_DEMUXER EAC3_MUXER EAC3_CORE_BSF) += fate-eac3-core-bsf +fate-eac3-core-bsf: CMD = md5pipe -i $(TARGET_SAMPLES)/eac3/the_great_wall_7.1.eac3 -c:a copy -bsf:a eac3_core -fflags +bitexact -f eac3 +fate-eac3-core-bsf: CMP = oneline +fate-eac3-core-bsf: REF = b704bf851e99b7442e9bed368b60e6ca + FATE_SAMPLES_AVCONV += $(FATE_AC3-yes) $(FATE_EAC3-yes) fate-ac3: $(FATE_AC3-yes) $(FATE_EAC3-yes) From 11f8f9547dbfdd181fed6ffa8270d8c80ae69ef5 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Fri, 30 Mar 2018 12:01:58 +0200 Subject: [PATCH 2292/2557] fftools/ffmpeg: Remove an unused variable. Fixes a warning: fftools/ffmpeg.c:2201:22: warning: unused variable 'fg' --- fftools/ffmpeg.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 4fcce8e2040a4..4724f62fff450 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2198,7 +2198,6 @@ static int ifilter_send_eof(InputFilter *ifilter, int64_t pts) return ret; } else { // the filtergraph was never configured - FilterGraph *fg = ifilter->graph; if (ifilter->format < 0) ifilter_parameters_from_codecpar(ifilter, ifilter->ist->st->codecpar); if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { From cc402282551d493829455fd097890cc6e2bc556a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 30 Mar 2018 12:32:00 +0200 Subject: [PATCH 2293/2557] avcodec/mpc8: check for overread earlier and abort decoding frame Signed-off-by: Paul B Mahol --- libavcodec/mpc8.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/mpc8.c b/libavcodec/mpc8.c index 355a9d2f3fb54..6347e1f691dab 100644 --- a/libavcodec/mpc8.c +++ b/libavcodec/mpc8.c @@ -273,6 +273,11 @@ static int mpc8_decode_frame(AVCodecContext * avctx, void *data, if(maxband > 32) maxband -= 33; } + if (get_bits_left(gb) < 0) { + *got_frame_ptr = 0; + return buf_size; + } + if(maxband > c->maxbands + 1) { av_log(avctx, AV_LOG_ERROR, "maxband %d too large\n",maxband); return AVERROR_INVALIDDATA; From e30a37e95e43148f7a7d907736aaaad5bbead95e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 30 Mar 2018 12:34:05 +0200 Subject: [PATCH 2294/2557] avcodec/mpc8: get frame output buffer right before it is actually needed Signed-off-by: Paul B Mahol --- libavcodec/mpc8.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libavcodec/mpc8.c b/libavcodec/mpc8.c index 6347e1f691dab..3be2f79a5a1a7 100644 --- a/libavcodec/mpc8.c +++ b/libavcodec/mpc8.c @@ -250,11 +250,6 @@ static int mpc8_decode_frame(AVCodecContext * avctx, void *data, int maxband, keyframe; int last[2]; - /* get output buffer */ - frame->nb_samples = MPC_FRAME_SIZE; - if ((res = ff_get_buffer(avctx, frame, 0)) < 0) - return res; - keyframe = c->cur_frame == 0; if(keyframe){ @@ -415,6 +410,10 @@ static int mpc8_decode_frame(AVCodecContext * avctx, void *data, } } + frame->nb_samples = MPC_FRAME_SIZE; + if ((res = ff_get_buffer(avctx, frame, 0)) < 0) + return res; + ff_mpc_dequantize_and_synth(c, maxband - 1, (int16_t **)frame->extended_data, avctx->channels); From ab05d3934de8e932dbd77979a687e6598e67535c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 30 Mar 2018 12:31:09 +0300 Subject: [PATCH 2295/2557] arm: vc1dsp: Add commas between macro arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When targeting darwin, clang requires commas between arguments, while the no-comma form is allowed for other targets. Since Xcode 9.3, the bundled clang supports altmacro and doesn't require using gas-preprocessor any longer. Signed-off-by: Martin Storsjö --- libavcodec/arm/vc1dsp_neon.S | 94 ++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/libavcodec/arm/vc1dsp_neon.S b/libavcodec/arm/vc1dsp_neon.S index ff88fe23c7307..71cc3f4413d4d 100644 --- a/libavcodec/arm/vc1dsp_neon.S +++ b/libavcodec/arm/vc1dsp_neon.S @@ -410,13 +410,13 @@ function ff_vc1_inv_trans_8x8_neon, export=1 @ src[48] q14 @ src[56] q15 - vc1_inv_trans_8x8_helper add=4 add1beforeshift=0 rshift=3 + vc1_inv_trans_8x8_helper add=4, add1beforeshift=0, rshift=3 @ Transpose result matrix of 8x8 swap4 d17, d19, d21, d23, d24, d26, d28, d30 transpose16_4x4 q8, q9, q10, q11, q12, q13, q14, q15 - vc1_inv_trans_8x8_helper add=64 add1beforeshift=1 rshift=7 + vc1_inv_trans_8x8_helper add=64, add1beforeshift=1, rshift=7 vst1.64 {q8-q9}, [r0,:128]! vst1.64 {q10-q11}, [r0,:128]! @@ -431,7 +431,7 @@ function ff_vc1_inv_trans_8x4_neon, export=1 vld1.64 {q0-q1}, [r2,:128]! @ load 8 * 4 * 2 = 64 bytes / 16 bytes per quad = 4 quad registers vld1.64 {q2-q3}, [r2,:128] - transpose16 q0 q1 q2 q3 @ transpose rows to columns + transpose16 q0, q1, q2, q3 @ transpose rows to columns @ At this point: @ src[0] d0 @@ -443,7 +443,7 @@ function ff_vc1_inv_trans_8x4_neon, export=1 @ src[6] d5 @ src[7] d7 - vc1_inv_trans_8x4_helper add=4 add1beforeshift=0 rshift=3 + vc1_inv_trans_8x4_helper add=4, add1beforeshift=0, rshift=3 @ Move output to more standardized registers vmov d0, d16 @@ -465,7 +465,7 @@ function ff_vc1_inv_trans_8x4_neon, export=1 @ dst[6] d5 @ dst[7] d7 - transpose16 q0 q1 q2 q3 @ turn columns into rows + transpose16 q0, q1, q2, q3 @ turn columns into rows @ At this point: @ row[0] q0 @@ -473,7 +473,7 @@ function ff_vc1_inv_trans_8x4_neon, export=1 @ row[2] q2 @ row[3] q3 - vc1_inv_trans_4x8_helper add=64 rshift=7 + vc1_inv_trans_4x8_helper add=64, rshift=7 @ At this point: @ line[0].l d0 @@ -523,7 +523,7 @@ function ff_vc1_inv_trans_4x8_neon, export=1 vld4.16 {d1[2], d3[2], d5[2], d7[2]}, [r2,:64], r12 vld4.16 {d1[3], d3[3], d5[3], d7[3]}, [r2,:64] - vc1_inv_trans_4x8_helper add=4 rshift=3 + vc1_inv_trans_4x8_helper add=4, rshift=3 @ At this point: @ dst[0] = q0 @@ -531,9 +531,9 @@ function ff_vc1_inv_trans_4x8_neon, export=1 @ dst[2] = q2 @ dst[3] = q3 - transpose16 q0 q1 q2 q3 @ Transpose rows (registers) into columns + transpose16 q0, q1, q2, q3 @ Transpose rows (registers) into columns - vc1_inv_trans_8x4_helper add=64 add1beforeshift=1 rshift=7 + vc1_inv_trans_8x4_helper add=64, add1beforeshift=1, rshift=7 vld1.32 {d28[]}, [r0,:32], r1 @ read dest vld1.32 {d28[1]}, [r0,:32], r1 @@ -611,7 +611,7 @@ function ff_vc1_inv_trans_4x4_neon, export=1 @ src[2] = d1 @ src[3] = d3 - vc1_inv_trans_4x4_helper add=4 rshift=3 @ compute t1, t2, t3, t4 and combine them into dst[0-3] + vc1_inv_trans_4x4_helper add=4, rshift=3 @ compute t1, t2, t3, t4 and combine them into dst[0-3] @ At this point: @ dst[0] = d0 @@ -619,7 +619,7 @@ function ff_vc1_inv_trans_4x4_neon, export=1 @ dst[2] = d1 @ dst[3] = d2 - transpose16 d0 d3 d1 d2 @ Transpose rows (registers) into columns + transpose16 d0, d3, d1, d2 @ Transpose rows (registers) into columns @ At this point: @ src[0] = d0 @@ -635,7 +635,7 @@ function ff_vc1_inv_trans_4x4_neon, export=1 @ src[16] = d1 @ src[24] = d3 - vc1_inv_trans_4x4_helper add=64 rshift=7 @ compute t1, t2, t3, t4 and combine them into dst[0-3] + vc1_inv_trans_4x4_helper add=64, rshift=7 @ compute t1, t2, t3, t4 and combine them into dst[0-3] @ At this point: @ line[0] = d0 @@ -665,26 +665,26 @@ endfunc @ The absolute value of multiplication constants from vc1_mspel_filter and vc1_mspel_{ver,hor}_filter_16bits. @ The sign is embedded in the code below that carries out the multiplication (mspel_filter{,.16}). -#define MSPEL_MODE_1_MUL_CONSTANTS 4 53 18 3 -#define MSPEL_MODE_2_MUL_CONSTANTS 1 9 9 1 -#define MSPEL_MODE_3_MUL_CONSTANTS 3 18 53 4 +#define MSPEL_MODE_1_MUL_CONSTANTS 4, 53, 18, 3 +#define MSPEL_MODE_2_MUL_CONSTANTS 1, 9, 9, 1 +#define MSPEL_MODE_3_MUL_CONSTANTS 3, 18, 53, 4 @ These constants are from reading the source code of vc1_mspel_mc and determining the value that @ is added to `rnd` to result in the variable `r`, and the value of the variable `shift`. -#define MSPEL_MODES_11_ADDSHIFT_CONSTANTS 15 5 -#define MSPEL_MODES_12_ADDSHIFT_CONSTANTS 3 3 -#define MSPEL_MODES_13_ADDSHIFT_CONSTANTS 15 5 +#define MSPEL_MODES_11_ADDSHIFT_CONSTANTS 15, 5 +#define MSPEL_MODES_12_ADDSHIFT_CONSTANTS 3, 3 +#define MSPEL_MODES_13_ADDSHIFT_CONSTANTS 15, 5 #define MSPEL_MODES_21_ADDSHIFT_CONSTANTS MSPEL_MODES_12_ADDSHIFT_CONSTANTS -#define MSPEL_MODES_22_ADDSHIFT_CONSTANTS 0 1 -#define MSPEL_MODES_23_ADDSHIFT_CONSTANTS 3 3 +#define MSPEL_MODES_22_ADDSHIFT_CONSTANTS 0, 1 +#define MSPEL_MODES_23_ADDSHIFT_CONSTANTS 3, 3 #define MSPEL_MODES_31_ADDSHIFT_CONSTANTS MSPEL_MODES_13_ADDSHIFT_CONSTANTS #define MSPEL_MODES_32_ADDSHIFT_CONSTANTS MSPEL_MODES_23_ADDSHIFT_CONSTANTS -#define MSPEL_MODES_33_ADDSHIFT_CONSTANTS 15 5 +#define MSPEL_MODES_33_ADDSHIFT_CONSTANTS 15, 5 @ The addition and shift constants from vc1_mspel_filter. -#define MSPEL_MODE_1_ADDSHIFT_CONSTANTS 32 6 -#define MSPEL_MODE_2_ADDSHIFT_CONSTANTS 8 4 -#define MSPEL_MODE_3_ADDSHIFT_CONSTANTS 32 6 +#define MSPEL_MODE_1_ADDSHIFT_CONSTANTS 32, 6 +#define MSPEL_MODE_2_ADDSHIFT_CONSTANTS 8, 4 +#define MSPEL_MODE_3_ADDSHIFT_CONSTANTS 32, 6 @ Setup constants in registers for a subsequent use of mspel_filter{,.16}. .macro mspel_constants typesize reg_a reg_b reg_c reg_d filter_a filter_b filter_c filter_d reg_add filter_add_register @@ -818,7 +818,7 @@ T mov sp, r4 sub r1, r1, r2 @ r1 = &src[-stride] @ slide back @ Do vertical filtering from src into tmp - mspel_constants i8 d28 d29 d30 d31 \filter_v_a \filter_v_b \filter_v_c \filter_v_d q13 r3 + mspel_constants i8, d28, d29, d30, d31, \filter_v_a, \filter_v_b, \filter_v_c, \filter_v_d, q13, r3 vld1.64 {d0,d1}, [r1], r2 vld1.64 {d2,d3}, [r1], r2 @@ -828,23 +828,23 @@ T mov sp, r4 subs r12, r12, #4 vld1.64 {d6,d7}, [r1], r2 - mspel_filter q11 q11 d0 d2 d4 d6 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0 - mspel_filter q12 q12 d1 d3 d5 d7 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0 + mspel_filter q11, q11, d0, d2, d4, d6, \filter_v_a, \filter_v_b, \filter_v_c, \filter_v_d, d28, d29, d30, d31, q13, \filter_shift, narrow=0 + mspel_filter q12, q12, d1, d3, d5, d7, \filter_v_a, \filter_v_b, \filter_v_c, \filter_v_d, d28, d29, d30, d31, q13, \filter_shift, narrow=0 vst1.64 {q11,q12}, [r4,:128]! @ store and increment vld1.64 {d0,d1}, [r1], r2 - mspel_filter q11 q11 d2 d4 d6 d0 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0 - mspel_filter q12 q12 d3 d5 d7 d1 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0 + mspel_filter q11, q11, d2, d4, d6, d0, \filter_v_a, \filter_v_b, \filter_v_c, \filter_v_d, d28, d29, d30, d31, q13, \filter_shift, narrow=0 + mspel_filter q12, q12, d3, d5, d7, d1, \filter_v_a, \filter_v_b, \filter_v_c, \filter_v_d, d28, d29, d30, d31, q13, \filter_shift, narrow=0 vst1.64 {q11,q12}, [r4,:128]! @ store and increment vld1.64 {d2,d3}, [r1], r2 - mspel_filter q11 q11 d4 d6 d0 d2 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0 - mspel_filter q12 q12 d5 d7 d1 d3 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0 + mspel_filter q11, q11, d4, d6, d0, d2, \filter_v_a, \filter_v_b, \filter_v_c, \filter_v_d, d28, d29, d30, d31, q13, \filter_shift, narrow=0 + mspel_filter q12, q12, d5, d7, d1, d3, \filter_v_a, \filter_v_b, \filter_v_c, \filter_v_d, d28, d29, d30, d31, q13, \filter_shift, narrow=0 vst1.64 {q11,q12}, [r4,:128]! @ store and increment vld1.64 {d4,d5}, [r1], r2 - mspel_filter q11 q11 d6 d0 d2 d4 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0 - mspel_filter q12 q12 d7 d1 d3 d5 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0 + mspel_filter q11, q11, d6, d0, d2, d4, \filter_v_a, \filter_v_b, \filter_v_c, \filter_v_d, d28, d29, d30, d31, q13, \filter_shift, narrow=0 + mspel_filter q12, q12, d7, d1, d3, d5, \filter_v_a, \filter_v_b, \filter_v_c, \filter_v_d, d28, d29, d30, d31, q13, \filter_shift, narrow=0 vst1.64 {q11,q12}, [r4,:128]! @ store and increment bne 1b @@ -854,7 +854,7 @@ T mov sp, r4 mov r4, sp @ r4 = tmp @ Do horizontal filtering from temp to dst - mspel_constants i16 d28 d29 d30 d31 \filter_h_a \filter_h_b \filter_h_c \filter_h_d q13 r3 + mspel_constants i16, d28, d29, d30, d31, \filter_h_a, \filter_h_b, \filter_h_c, \filter_h_d, q13, r3 2: subs r12, r12, #1 @@ -864,7 +864,7 @@ T mov sp, r4 vext.16 q3, q0, q1, #3 vext.16 q1, q0, q1, #1 @ do last because it writes to q1 which is read by the other vext instructions - mspel_filter.16 q11 q12 d22 d23 d21 d0 d1 d2 d3 d4 d5 d6 d7 \filter_h_a \filter_h_b \filter_h_c \filter_h_d d28 d29 d30 d31 q13 7 + mspel_filter.16 q11, q12, d22, d23, d21, d0, d1, d2, d3, d4, d5, d6, d7, \filter_h_a, \filter_h_b, \filter_h_c, \filter_h_d, d28, d29, d30, d31, q13, 7 vst1.64 {d21}, [r0,:64], r2 @ store and increment dst @@ -877,9 +877,9 @@ endfunc @ Use C preprocessor and assembler macros to expand to functions for horizontal and vertical filtering. #define PUT_VC1_MSPEL_MC_HV(hmode, vmode) \ - put_vc1_mspel_mc_hv hmode vmode \ - MSPEL_MODE_ ## hmode ## _MUL_CONSTANTS \ - MSPEL_MODE_ ## vmode ## _MUL_CONSTANTS \ + put_vc1_mspel_mc_hv hmode, vmode, \ + MSPEL_MODE_ ## hmode ## _MUL_CONSTANTS, \ + MSPEL_MODE_ ## vmode ## _MUL_CONSTANTS, \ MSPEL_MODES_ ## hmode ## vmode ## _ADDSHIFT_CONSTANTS PUT_VC1_MSPEL_MC_HV(1, 1) @@ -900,7 +900,7 @@ function ff_put_vc1_mspel_mc\hmode\()0_neon, export=1 mov r12, #8 @ loop counter sub r1, r1, #1 @ slide back, using immediate - mspel_constants i8 d28 d29 d30 d31 \filter_a \filter_b \filter_c \filter_d q13 r3 + mspel_constants i8, d28, d29, d30, d31, \filter_a, \filter_b, \filter_c, \filter_d, q13, r3 1: subs r12, r12, #1 @@ -910,7 +910,7 @@ function ff_put_vc1_mspel_mc\hmode\()0_neon, export=1 vext.8 d3, d0, d1, #3 vext.8 d1, d0, d1, #1 @ do last because it writes to d1 which is read by the other vext instructions - mspel_filter q11 d21 d0 d1 d2 d3 \filter_a \filter_b \filter_c \filter_d d28 d29 d30 d31 q13 \filter_shift + mspel_filter q11, d21, d0, d1, d2, d3, \filter_a, \filter_b, \filter_c, \filter_d, d28, d29, d30, d31, q13, \filter_shift vst1.64 {d21}, [r0,:64], r2 @ store and increment dst @@ -922,7 +922,7 @@ endfunc @ Use C preprocessor and assembler macros to expand to functions for horizontal only filtering. #define PUT_VC1_MSPEL_MC_H_ONLY(hmode) \ - put_vc1_mspel_mc_h_only hmode MSPEL_MODE_ ## hmode ## _MUL_CONSTANTS MSPEL_MODE_ ## hmode ## _ADDSHIFT_CONSTANTS + put_vc1_mspel_mc_h_only hmode, MSPEL_MODE_ ## hmode ## _MUL_CONSTANTS, MSPEL_MODE_ ## hmode ## _ADDSHIFT_CONSTANTS PUT_VC1_MSPEL_MC_H_ONLY(1) PUT_VC1_MSPEL_MC_H_ONLY(2) @@ -937,7 +937,7 @@ function ff_put_vc1_mspel_mc0\vmode\()_neon, export=1 mov r12, #8 @ loop counter sub r1, r1, r2 @ r1 = &src[-stride] @ slide back - mspel_constants i8 d28 d29 d30 d31 \filter_a \filter_b \filter_c \filter_d q13 r3 + mspel_constants i8, d28, d29, d30, d31, \filter_a, \filter_b, \filter_c, \filter_d, q13, r3 vld1.64 {d0}, [r1], r2 @ d0 = src[-stride] vld1.64 {d1}, [r1], r2 @ d1 = src[0] @@ -947,19 +947,19 @@ function ff_put_vc1_mspel_mc0\vmode\()_neon, export=1 subs r12, r12, #4 vld1.64 {d3}, [r1], r2 @ d3 = src[stride * 2] - mspel_filter q11 d21 d0 d1 d2 d3 \filter_a \filter_b \filter_c \filter_d d28 d29 d30 d31 q13 \filter_shift + mspel_filter q11, d21, d0, d1, d2, d3, \filter_a, \filter_b, \filter_c, \filter_d, d28, d29, d30, d31, q13, \filter_shift vst1.64 {d21}, [r0,:64], r2 @ store and increment dst vld1.64 {d0}, [r1], r2 @ d0 = next line - mspel_filter q11 d21 d1 d2 d3 d0 \filter_a \filter_b \filter_c \filter_d d28 d29 d30 d31 q13 \filter_shift + mspel_filter q11, d21, d1, d2, d3, d0, \filter_a, \filter_b, \filter_c, \filter_d, d28, d29, d30, d31, q13, \filter_shift vst1.64 {d21}, [r0,:64], r2 @ store and increment dst vld1.64 {d1}, [r1], r2 @ d1 = next line - mspel_filter q11 d21 d2 d3 d0 d1 \filter_a \filter_b \filter_c \filter_d d28 d29 d30 d31 q13 \filter_shift + mspel_filter q11, d21, d2, d3, d0, d1, \filter_a, \filter_b, \filter_c, \filter_d, d28, d29, d30, d31, q13, \filter_shift vst1.64 {d21}, [r0,:64], r2 @ store and increment dst vld1.64 {d2}, [r1], r2 @ d2 = next line - mspel_filter q11 d21 d3 d0 d1 d2 \filter_a \filter_b \filter_c \filter_d d28 d29 d30 d31 q13 \filter_shift + mspel_filter q11, d21, d3, d0, d1, d2, \filter_a, \filter_b, \filter_c, \filter_d, d28, d29, d30, d31, q13, \filter_shift vst1.64 {d21}, [r0,:64], r2 @ store and increment dst bne 1b @@ -970,7 +970,7 @@ endfunc @ Use C preprocessor and assembler macros to expand to functions for vertical only filtering. #define PUT_VC1_MSPEL_MC_V_ONLY(vmode) \ - put_vc1_mspel_mc_v_only vmode MSPEL_MODE_ ## vmode ## _MUL_CONSTANTS MSPEL_MODE_ ## vmode ## _ADDSHIFT_CONSTANTS + put_vc1_mspel_mc_v_only vmode, MSPEL_MODE_ ## vmode ## _MUL_CONSTANTS, MSPEL_MODE_ ## vmode ## _ADDSHIFT_CONSTANTS PUT_VC1_MSPEL_MC_V_ONLY(1) PUT_VC1_MSPEL_MC_V_ONLY(2) From 3a7b4ae62c798edbd82bcd8fef863c74ed2acd4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 30 Mar 2018 12:33:46 +0300 Subject: [PATCH 2296/2557] arm: Produce .const_data instead of .section .rodata for Mach-O MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the same combination of .section directives as used in aarch64/asm.S. Since Xcode 9.3, the bundled clang supports altmacro and doesn't require using gas-preprocessor any longer. Signed-off-by: Martin Storsjö --- libavutil/arm/asm.S | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavutil/arm/asm.S b/libavutil/arm/asm.S index 08574852b58d6..e7eea0271f9ec 100644 --- a/libavutil/arm/asm.S +++ b/libavutil/arm/asm.S @@ -111,11 +111,17 @@ FUNC .func \name ELF .size \name, . - \name .purgem endconst .endm -.if HAVE_SECTION_DATA_REL_RO && \relocate +#if HAVE_SECTION_DATA_REL_RO +.if \relocate .section .data.rel.ro .else .section .rodata .endif +#elif !defined(__MACH__) + .section .rodata +#else + .const_data +#endif .align \align \name: .endm From 53937c437105853d0c8dd9292a16096e7e621fb2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 30 Mar 2018 14:05:10 -0300 Subject: [PATCH 2297/2557] fate: add test for eac3 dependant stream Signed-off-by: James Almer --- tests/fate/ac3.mak | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/fate/ac3.mak b/tests/fate/ac3.mak index 26d2bf3e1cd89..bb02d3829d307 100644 --- a/tests/fate/ac3.mak +++ b/tests/fate/ac3.mak @@ -60,6 +60,10 @@ FATE_EAC3 += fate-eac3-4 fate-eac3-4: CMD = pcm -i $(TARGET_SAMPLES)/eac3/serenity_english_5.1_1536_small.eac3 fate-eac3-4: REF = $(SAMPLES)/eac3/serenity_english_5.1_1536_small_v2.pcm +FATE_EAC3 += fate-eac3-5 +fate-eac3-5: CMD = pcm -i $(TARGET_SAMPLES)/eac3/the_great_wall_7.1.eac3 +fate-eac3-5: REF = $(SAMPLES)/eac3/the_great_wall_7.1.pcm + $(FATE_AC3) $(FATE_EAC3): CMP = oneoff FATE_AC3-$(call DEMDEC, AC3, AC3) += $(FATE_AC3) From cdd6a525e4922b20c26c47de5da6d191f9b1b52e Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Fri, 30 Mar 2018 19:19:09 +0530 Subject: [PATCH 2298/2557] doc/encoders: list missing options for x265 Add entries for crf and profile in libx265 section Signed-off-by: Lou Logan --- doc/encoders.texi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index f25d47e272015..7b095754d1d98 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -2159,6 +2159,12 @@ Set the x265 preset. @item tune Set the x265 tune parameter. +@item profile +Set profile restrictions. + +@item crf +Set the quality for constant quality mode. + @item forced-idr Normally, when forcing a I-frame type, the encoder can select any type of I-frame. This option forces it to choose an IDR-frame. From 34304677c05be782964b9fb704b13c01e19c9c80 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Fri, 30 Mar 2018 21:13:27 +0200 Subject: [PATCH 2299/2557] avfilter/showvolume : add comment for orientation condition --- libavfilter/avf_showvolume.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index af8ac1da6c164..ab1fb619b9ceb 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -222,7 +222,7 @@ static void drawtext(AVFrame *pic, int x, int y, const char *txt, int o) for (i = 0; txt[i]; i++) { int char_y, mask; - if (o) { + if (o) { /* vertical orientation */ for (char_y = font_height - 1; char_y >= 0; char_y--) { uint8_t *p = pic->data[0] + (y + i * 10) * pic->linesize[0] + x * 4; for (mask = 0x80; mask; mask >>= 1) { @@ -231,7 +231,7 @@ static void drawtext(AVFrame *pic, int x, int y, const char *txt, int o) p += pic->linesize[0]; } } - } else { + } else { /* horizontal orientation */ uint8_t *p = pic->data[0] + y * pic->linesize[0] + (x + i * 8) * 4; for (char_y = 0; char_y < font_height; char_y++) { for (mask = 0x80; mask; mask >>= 1) { @@ -285,7 +285,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } } - if (s->orientation) { + if (s->orientation) { /* vertical */ for (c = 0; c < inlink->channels; c++) { float *src = (float *)insamples->extended_data[c]; uint32_t *lut = s->color_lut + s->w * c; @@ -313,7 +313,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) drawtext(s->out, c * (s->h + s->b) + (s->h - 10) / 2, outlink->h - 35, channel_name, 1); } } - } else { + } else { /* horizontal */ for (c = 0; c < inlink->channels; c++) { float *src = (float *)insamples->extended_data[c]; uint32_t *lut = s->color_lut + s->w * c; From 25b22666a3c05ae15a5d6cc3b0be5c8b034f00f6 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Fri, 30 Mar 2018 21:15:56 +0200 Subject: [PATCH 2300/2557] avfilter/showvolume : calculate fade only if fade < 1. --- libavfilter/avf_showvolume.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index ab1fb619b9ceb..db16733202cc3 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -273,6 +273,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } s->out->pts = insamples->pts; + if (s->f < 1.) { for (j = 0; j < outlink->h; j++) { uint8_t *dst = s->out->data[0] + j * s->out->linesize[0]; const uint32_t alpha = s->bgopacity * 255; @@ -284,6 +285,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) dst[k * 4 + 3] = FFMAX(dst[k * 4 + 3] * s->f, alpha); } } + } if (s->orientation) { /* vertical */ for (c = 0; c < inlink->channels; c++) { From 328df2f71234aa817e2279ec9fdadb81dca0b149 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Fri, 30 Mar 2018 21:16:47 +0200 Subject: [PATCH 2301/2557] avfilter/showvolume : indent after prev commit --- libavfilter/avf_showvolume.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index db16733202cc3..6c47cce19f519 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -274,18 +274,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) s->out->pts = insamples->pts; if (s->f < 1.) { - for (j = 0; j < outlink->h; j++) { - uint8_t *dst = s->out->data[0] + j * s->out->linesize[0]; - const uint32_t alpha = s->bgopacity * 255; - - for (k = 0; k < outlink->w; k++) { - dst[k * 4 + 0] = FFMAX(dst[k * 4 + 0] * s->f, 0); - dst[k * 4 + 1] = FFMAX(dst[k * 4 + 1] * s->f, 0); - dst[k * 4 + 2] = FFMAX(dst[k * 4 + 2] * s->f, 0); - dst[k * 4 + 3] = FFMAX(dst[k * 4 + 3] * s->f, alpha); + for (j = 0; j < outlink->h; j++) { + uint8_t *dst = s->out->data[0] + j * s->out->linesize[0]; + const uint32_t alpha = s->bgopacity * 255; + + for (k = 0; k < outlink->w; k++) { + dst[k * 4 + 0] = FFMAX(dst[k * 4 + 0] * s->f, 0); + dst[k * 4 + 1] = FFMAX(dst[k * 4 + 1] * s->f, 0); + dst[k * 4 + 2] = FFMAX(dst[k * 4 + 2] * s->f, 0); + dst[k * 4 + 3] = FFMAX(dst[k * 4 + 3] * s->f, alpha); + } } } - } if (s->orientation) { /* vertical */ for (c = 0; c < inlink->channels; c++) { From e8d785035320453b52f915bce083afd4109ab92c Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Fri, 30 Mar 2018 22:42:42 +0200 Subject: [PATCH 2302/2557] doc/avfilter/showvolume : fix doc for orientation param possible value are h or v. --- doc/filters.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 5c119c015194a..c05b12849f9c1 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19961,8 +19961,8 @@ If set, displays channel names. Default is enabled. If set, displays volume values. Default is enabled. @item o -Set orientation, can be @code{horizontal} or @code{vertical}, -default is @code{horizontal}. +Set orientation, can be horizontal: @code{h} or vertical: @code{v}, +default is @code{h}. @item s Set step size, allowed range is [0, 5]. Default is 0, which means From 0c25caa4708cc3a89a9ee9666d0257e6dc6a1573 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 31 Mar 2018 09:26:37 +0200 Subject: [PATCH 2303/2557] avfilter/avf_showvolume: let fade be also exactly 0 Signed-off-by: Paul B Mahol --- doc/filters.texi | 2 +- libavfilter/avf_showvolume.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index c05b12849f9c1..bf2b94e240924 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19936,7 +19936,7 @@ Set channel width, allowed range is [80, 8192]. Default is 400. Set channel height, allowed range is [1, 900]. Default is 20. @item f -Set fade, allowed range is [0.001, 1]. Default is 0.95. +Set fade, allowed range is [0, 1]. Default is 0.95. @item c Set volume color expression. diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index 6c47cce19f519..267020e163f74 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -67,7 +67,7 @@ static const AVOption showvolume_options[] = { { "b", "set border width", OFFSET(b), AV_OPT_TYPE_INT, {.i64=1}, 0, 5, FLAGS }, { "w", "set channel width", OFFSET(w), AV_OPT_TYPE_INT, {.i64=400}, 80, 8192, FLAGS }, { "h", "set channel height", OFFSET(h), AV_OPT_TYPE_INT, {.i64=20}, 1, 900, FLAGS }, - { "f", "set fade", OFFSET(f), AV_OPT_TYPE_DOUBLE, {.dbl=0.95}, 0.001, 1, FLAGS }, + { "f", "set fade", OFFSET(f), AV_OPT_TYPE_DOUBLE, {.dbl=0.95}, 0, 1, FLAGS }, { "c", "set volume color expression", OFFSET(color), AV_OPT_TYPE_STRING, {.str="PEAK*255+floor((1-PEAK)*255)*256+0xff000000"}, 0, 0, FLAGS }, { "t", "display channel names", OFFSET(draw_text), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, { "v", "display volume value", OFFSET(draw_volume), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, From f33f728470434a9981a53d7560d67657b93d1e26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 31 Mar 2018 21:54:32 +0300 Subject: [PATCH 2304/2557] arm: swscale: Only compile the rgb2yuv asm if .dn aliases are supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vanilla clang supports altmacro since clang 5.0, and thus doesn't require gas-preprocessor for building the arm assembly any longer. However, the built-in assembler doesn't support .dn directives. This readds checks that were removed in d7320ca3ed10f0d, when the last usage of .dn directives within libav were removed. Alternatively, the assembly could be rewritten to not use the .dn directive, making it available to clang users. Signed-off-by: Martin Storsjö --- configure | 2 ++ libswscale/arm/rgb2yuv_neon_16.S | 3 +++ libswscale/arm/rgb2yuv_neon_32.S | 3 +++ libswscale/arm/swscale_unscaled.c | 6 ++++++ 4 files changed, 14 insertions(+) diff --git a/configure b/configure index 99570a1415c11..81fb3fbf75f06 100755 --- a/configure +++ b/configure @@ -2149,6 +2149,7 @@ SYSTEM_LIBRARIES=" TOOLCHAIN_FEATURES=" as_arch_directive + as_dn_directive as_fpu_directive as_func as_object_arch @@ -5530,6 +5531,7 @@ EOF check_inline_asm asm_mod_q '"add r0, %Q0, %R0" :: "r"((long long)0)' check_as as_arch_directive ".arch armv7-a" + check_as as_dn_directive "ra .dn d0.i16" check_as as_fpu_directive ".fpu neon" # llvm's integrated assembler supports .object_arch from llvm 3.5 diff --git a/libswscale/arm/rgb2yuv_neon_16.S b/libswscale/arm/rgb2yuv_neon_16.S index 601bc9a9b7c42..ad7e679ca910d 100644 --- a/libswscale/arm/rgb2yuv_neon_16.S +++ b/libswscale/arm/rgb2yuv_neon_16.S @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" +#if HAVE_AS_DN_DIRECTIVE #include "rgb2yuv_neon_common.S" /* downsampled R16G16B16 x8 */ @@ -78,3 +80,4 @@ alias_qw c8x8x2, q10 .endm loop_420sp rgbx, nv12, init, kernel_420_16x2, 16 +#endif diff --git a/libswscale/arm/rgb2yuv_neon_32.S b/libswscale/arm/rgb2yuv_neon_32.S index f51a5f149f046..4fd0f64a09e97 100644 --- a/libswscale/arm/rgb2yuv_neon_32.S +++ b/libswscale/arm/rgb2yuv_neon_32.S @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" +#if HAVE_AS_DN_DIRECTIVE #include "rgb2yuv_neon_common.S" /* downsampled R16G16B16 x8 */ @@ -117,3 +119,4 @@ alias_qw c8x8x2, q10 loop_420sp rgbx, nv12, init, kernel_420_16x2, 32 +#endif diff --git a/libswscale/arm/swscale_unscaled.c b/libswscale/arm/swscale_unscaled.c index e1597ab42dfcd..e41f294eacc10 100644 --- a/libswscale/arm/swscale_unscaled.c +++ b/libswscale/arm/swscale_unscaled.c @@ -23,6 +23,7 @@ #include "libswscale/swscale_internal.h" #include "libavutil/arm/cpu.h" +#if HAVE_AS_DN_DIRECTIVE extern void rgbx_to_nv12_neon_32(const uint8_t *src, uint8_t *y, uint8_t *chroma, int width, int height, int y_stride, int c_stride, int src_stride, @@ -178,3 +179,8 @@ void ff_get_unscaled_swscale_arm(SwsContext *c) if (have_neon(cpu_flags)) get_unscaled_swscale_neon(c); } +#else +void ff_get_unscaled_swscale_arm(SwsContext *c) +{ +} +#endif From 6660bc034d212dc8fb01715d6bf3a6d3866e9715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 31 Mar 2018 21:54:41 +0300 Subject: [PATCH 2305/2557] arm: hevcdsp: Avoid using macro expansion counters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clang supports the macro expansion counter (used for making unique labels within macro expansions), but not when targeting darwin. Convert uses of the counter into normal local labels, as used elsewhere. Since Xcode 9.3, the bundled clang supports altmacro and doesn't require using gas-preprocessor any longer. Signed-off-by: Martin Storsjö --- libavcodec/arm/hevcdsp_deblock_neon.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/arm/hevcdsp_deblock_neon.S b/libavcodec/arm/hevcdsp_deblock_neon.S index 166bddb104f18..7cb7487ef6105 100644 --- a/libavcodec/arm/hevcdsp_deblock_neon.S +++ b/libavcodec/arm/hevcdsp_deblock_neon.S @@ -152,7 +152,7 @@ and r9, r8, r7 cmp r9, #0 - beq weakfilter_\@ + beq 1f vadd.i16 q2, q11, q12 vadd.i16 q4, q9, q8 @@ -210,11 +210,11 @@ vbit q13, q3, q5 vbit q14, q2, q5 -weakfilter_\@: +1: mvn r8, r8 and r9, r8, r7 cmp r9, #0 - beq ready_\@ + beq 2f vdup.16 q4, r2 @@ -275,7 +275,7 @@ weakfilter_\@: vbit q11, q0, q5 vbit q12, q4, q5 -ready_\@: +2: vqmovun.s16 d16, q8 vqmovun.s16 d18, q9 vqmovun.s16 d20, q10 From 5f83935de4ef1e32d22f90016b9ddebc1e56153f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 31 Mar 2018 21:54:46 +0300 Subject: [PATCH 2306/2557] arm: hevcdsp: Add commas between macro arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When targeting darwin, clang requires commas between arguments, while the no-comma form is allowed for other targets. Since Xcode 9.3, the bundled clang supports altmacro and doesn't require using gas-preprocessor any longer. Signed-off-by: Martin Storsjö --- libavcodec/arm/hevcdsp_qpel_neon.S | 36 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/libavcodec/arm/hevcdsp_qpel_neon.S b/libavcodec/arm/hevcdsp_qpel_neon.S index 86f92cf75a31a..caa6efa7664b1 100644 --- a/libavcodec/arm/hevcdsp_qpel_neon.S +++ b/libavcodec/arm/hevcdsp_qpel_neon.S @@ -667,76 +667,76 @@ endfunc function ff_hevc_put_qpel_h1v1_neon_8, export=1 - hevc_put_qpel_hXvY_neon_8 qpel_filter_1 qpel_filter_1_32b + hevc_put_qpel_hXvY_neon_8 qpel_filter_1, qpel_filter_1_32b endfunc function ff_hevc_put_qpel_h2v1_neon_8, export=1 - hevc_put_qpel_hXvY_neon_8 qpel_filter_2 qpel_filter_1_32b + hevc_put_qpel_hXvY_neon_8 qpel_filter_2, qpel_filter_1_32b endfunc function ff_hevc_put_qpel_h3v1_neon_8, export=1 - hevc_put_qpel_hXvY_neon_8 qpel_filter_3 qpel_filter_1_32b + hevc_put_qpel_hXvY_neon_8 qpel_filter_3, qpel_filter_1_32b endfunc function ff_hevc_put_qpel_h1v2_neon_8, export=1 - hevc_put_qpel_hXvY_neon_8 qpel_filter_1 qpel_filter_2_32b + hevc_put_qpel_hXvY_neon_8 qpel_filter_1, qpel_filter_2_32b endfunc function ff_hevc_put_qpel_h2v2_neon_8, export=1 - hevc_put_qpel_hXvY_neon_8 qpel_filter_2 qpel_filter_2_32b + hevc_put_qpel_hXvY_neon_8 qpel_filter_2, qpel_filter_2_32b endfunc function ff_hevc_put_qpel_h3v2_neon_8, export=1 - hevc_put_qpel_hXvY_neon_8 qpel_filter_3 qpel_filter_2_32b + hevc_put_qpel_hXvY_neon_8 qpel_filter_3, qpel_filter_2_32b endfunc function ff_hevc_put_qpel_h1v3_neon_8, export=1 - hevc_put_qpel_hXvY_neon_8 qpel_filter_1 qpel_filter_3_32b + hevc_put_qpel_hXvY_neon_8 qpel_filter_1, qpel_filter_3_32b endfunc function ff_hevc_put_qpel_h2v3_neon_8, export=1 - hevc_put_qpel_hXvY_neon_8 qpel_filter_2 qpel_filter_3_32b + hevc_put_qpel_hXvY_neon_8 qpel_filter_2, qpel_filter_3_32b endfunc function ff_hevc_put_qpel_h3v3_neon_8, export=1 - hevc_put_qpel_hXvY_neon_8 qpel_filter_3 qpel_filter_3_32b + hevc_put_qpel_hXvY_neon_8 qpel_filter_3, qpel_filter_3_32b endfunc function ff_hevc_put_qpel_uw_h1v1_neon_8, export=1 - hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_1 qpel_filter_1_32b + hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_1, qpel_filter_1_32b endfunc function ff_hevc_put_qpel_uw_h2v1_neon_8, export=1 - hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_2 qpel_filter_1_32b + hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_2, qpel_filter_1_32b endfunc function ff_hevc_put_qpel_uw_h3v1_neon_8, export=1 - hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_3 qpel_filter_1_32b + hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_3, qpel_filter_1_32b endfunc function ff_hevc_put_qpel_uw_h1v2_neon_8, export=1 - hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_1 qpel_filter_2_32b + hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_1, qpel_filter_2_32b endfunc function ff_hevc_put_qpel_uw_h2v2_neon_8, export=1 - hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_2 qpel_filter_2_32b + hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_2, qpel_filter_2_32b endfunc function ff_hevc_put_qpel_uw_h3v2_neon_8, export=1 - hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_3 qpel_filter_2_32b + hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_3, qpel_filter_2_32b endfunc function ff_hevc_put_qpel_uw_h1v3_neon_8, export=1 - hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_1 qpel_filter_3_32b + hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_1, qpel_filter_3_32b endfunc function ff_hevc_put_qpel_uw_h2v3_neon_8, export=1 - hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_2 qpel_filter_3_32b + hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_2, qpel_filter_3_32b endfunc function ff_hevc_put_qpel_uw_h3v3_neon_8, export=1 - hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_3 qpel_filter_3_32b + hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_3, qpel_filter_3_32b endfunc .macro init_put_pixels From cda43940da872ebc15bc1f676fe81b544196446d Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Sat, 17 Mar 2018 21:34:18 +0000 Subject: [PATCH 2307/2557] checkasm/Makefile: add EXTRALIBS-libavformat Signed-off-by: Josh de Kock --- tests/checkasm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 97fbf59636bca..0233d2f98927d 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -67,7 +67,7 @@ tests/checkasm/checkasm.o: CFLAGS += -Umain CHECKASM := tests/checkasm/checkasm$(EXESUF) $(CHECKASM): $(CHECKASMOBJS) $(FF_STATIC_DEP_LIBS) - $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(CHECKASMOBJS) $(FF_STATIC_DEP_LIBS) $(EXTRALIBS-avcodec) $(EXTRALIBS-avfilter) $(EXTRALIBS-avutil) $(EXTRALIBS-swresample) $(EXTRALIBS) + $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(CHECKASMOBJS) $(FF_STATIC_DEP_LIBS) $(EXTRALIBS-avcodec) $(EXTRALIBS-avfilter) $(EXTRALIBS-avformat) $(EXTRALIBS-avutil) $(EXTRALIBS-swresample) $(EXTRALIBS) checkasm: $(CHECKASM) From 8f1382f80e0d4184c54c14afdda6482f050fbba7 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Sun, 18 Feb 2018 17:20:26 +0000 Subject: [PATCH 2308/2557] lavfi: add new iteration API Signed-off-by: Josh de Kock --- configure | 29 +- doc/APIchanges | 4 + doc/writing_filters.txt | 6 +- libavfilter/allfilters.c | 825 +++++++++++++++++++++------------------ libavfilter/avfilter.c | 50 +-- libavfilter/avfilter.h | 29 +- libavfilter/version.h | 3 + 7 files changed, 490 insertions(+), 456 deletions(-) diff --git a/configure b/configure index 81fb3fbf75f06..6ef3d8abef2b2 100755 --- a/configure +++ b/configure @@ -3622,15 +3622,6 @@ for v in "$@"; do FFMPEG_CONFIGURATION="${FFMPEG_CONFIGURATION# } ${l}${r}" done -find_things(){ - thing=$1 - pattern=$2 - file=$source_path/$3 - sed -n "s/^[^#]*$pattern.*([^,]*, *\([^,]*\)\(,.*\)*).*/\1_$thing/p" "$file" -} - -FILTER_LIST=$(find_things filter FILTER libavfilter/allfilters.c) - find_things_extern(){ thing=$1 pattern=$2 @@ -3639,6 +3630,13 @@ find_things_extern(){ sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$out/p" "$file" } +find_filters_extern(){ + file=$source_path/$1 + #sed -n "s/^extern AVFilter ff_\([avfsinkrc]\{2,5\}\)_\(\w\+\);/\2_filter/p" $file + sed -E -n "s/^extern AVFilter ff_([avfsinkrc]{2,5})_([a-zA-Z0-9_]+);/\2_filter/p" $file +} + +FILTER_LIST=$(find_filters_extern libavfilter/allfilters.c) OUTDEV_LIST=$(find_things_extern muxer AVOutputFormat libavdevice/alldevices.c outdev) INDEV_LIST=$(find_things_extern demuxer AVInputFormat libavdevice/alldevices.c indev) MUXER_LIST=$(find_things_extern muxer AVOutputFormat libavformat/allformats.c) @@ -7157,6 +7155,10 @@ echo "#endif /* AVUTIL_AVCONFIG_H */" >> $TMPH cp_if_changed $TMPH libavutil/avconfig.h +full_filter_name(){ + sed -n "s/^extern AVFilter ff_\([avfsinkrc]\{2,5\}\)_$1;/\1_$1/p" $source_path/libavfilter/allfilters.c +} + # generate the lists of enabled components print_enabled_components(){ file=$1 @@ -7167,6 +7169,9 @@ print_enabled_components(){ for c in $*; do if enabled $c; then case $name in + filter_list) + c=$(full_filter_name $(remove_suffix _filter $c)) + ;; indev_list) c=$(add_suffix _demuxer $(remove_suffix _indev $c)) ;; @@ -7177,10 +7182,16 @@ print_enabled_components(){ printf " &ff_%s,\n" $c >> $TMPH fi done + if [ "$name" == "filter_list" ]; then + for c in asrc_abuffer vsrc_buffer asink_abuffer vsink_buffer; do + printf " &ff_%s,\n" $c >> $TMPH + done + fi echo " NULL };" >> $TMPH cp_if_changed $TMPH $file } +print_enabled_components libavfilter/filter_list.c AVFilter filter_list $FILTER_LIST print_enabled_components libavcodec/codec_list.c AVCodec codec_list $CODEC_LIST print_enabled_components libavcodec/parser_list.c AVCodecParser parser_list $PARSER_LIST print_enabled_components libavcodec/bsf_list.c AVBitStreamFilter bitstream_filters $BSF_LIST diff --git a/doc/APIchanges b/doc/APIchanges index 83c7a40a557ac..dbc4617f8d4ea 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-xx-xx - xxxxxxx - lavc 7.13.100 - avcodec.h + Deprecate use of avfilter_register(), avfilter_register_all(), + avfilter_next(). Add av_filter_iterate(). + 2018-03-xx - xxxxxxx - lavc 58.16.100 - avcodec.h Add FF_SUB_CHARENC_MODE_IGNORE. diff --git a/doc/writing_filters.txt b/doc/writing_filters.txt index 5cd4ecd6a4b01..98b9c6f3d29f1 100644 --- a/doc/writing_filters.txt +++ b/doc/writing_filters.txt @@ -31,10 +31,8 @@ If everything went right, you should get a foobar.png with Lena edge-detected. That's it, your new playground is ready. Some little details about what's going on: -libavfilter/allfilters.c:avfilter_register_all() is called at runtime to create -a list of the available filters, but it's important to know that this file is -also parsed by the configure script, which in turn will define variables for -the build system and the C: +libavfilter/allfilters.c:this file is parsed by the configure script, which in turn +will define variables for the build system and the C: --- after running configure --- diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 1cf13409ca372..6eac828616f76 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -23,411 +23,456 @@ #include "avfilter.h" #include "config.h" +extern AVFilter ff_af_abench; +extern AVFilter ff_af_acompressor; +extern AVFilter ff_af_acontrast; +extern AVFilter ff_af_acopy; +extern AVFilter ff_af_acrossfade; +extern AVFilter ff_af_acrusher; +extern AVFilter ff_af_adelay; +extern AVFilter ff_af_aecho; +extern AVFilter ff_af_aemphasis; +extern AVFilter ff_af_aeval; +extern AVFilter ff_af_afade; +extern AVFilter ff_af_afftfilt; +extern AVFilter ff_af_afir; +extern AVFilter ff_af_aformat; +extern AVFilter ff_af_agate; +extern AVFilter ff_af_aiir; +extern AVFilter ff_af_ainterleave; +extern AVFilter ff_af_alimiter; +extern AVFilter ff_af_allpass; +extern AVFilter ff_af_aloop; +extern AVFilter ff_af_amerge; +extern AVFilter ff_af_ametadata; +extern AVFilter ff_af_amix; +extern AVFilter ff_af_anequalizer; +extern AVFilter ff_af_anull; +extern AVFilter ff_af_apad; +extern AVFilter ff_af_aperms; +extern AVFilter ff_af_aphaser; +extern AVFilter ff_af_apulsator; +extern AVFilter ff_af_arealtime; +extern AVFilter ff_af_aresample; +extern AVFilter ff_af_areverse; +extern AVFilter ff_af_aselect; +extern AVFilter ff_af_asendcmd; +extern AVFilter ff_af_asetnsamples; +extern AVFilter ff_af_asetpts; +extern AVFilter ff_af_asetrate; +extern AVFilter ff_af_asettb; +extern AVFilter ff_af_ashowinfo; +extern AVFilter ff_af_asidedata; +extern AVFilter ff_af_asplit; +extern AVFilter ff_af_astats; +extern AVFilter ff_af_astreamselect; +extern AVFilter ff_af_atempo; +extern AVFilter ff_af_atrim; +extern AVFilter ff_af_azmq; +extern AVFilter ff_af_bandpass; +extern AVFilter ff_af_bandreject; +extern AVFilter ff_af_bass; +extern AVFilter ff_af_biquad; +extern AVFilter ff_af_bs2b; +extern AVFilter ff_af_channelmap; +extern AVFilter ff_af_channelsplit; +extern AVFilter ff_af_chorus; +extern AVFilter ff_af_compand; +extern AVFilter ff_af_compensationdelay; +extern AVFilter ff_af_crossfeed; +extern AVFilter ff_af_crystalizer; +extern AVFilter ff_af_dcshift; +extern AVFilter ff_af_drmeter; +extern AVFilter ff_af_dynaudnorm; +extern AVFilter ff_af_earwax; +extern AVFilter ff_af_ebur128; +extern AVFilter ff_af_equalizer; +extern AVFilter ff_af_extrastereo; +extern AVFilter ff_af_firequalizer; +extern AVFilter ff_af_flanger; +extern AVFilter ff_af_haas; +extern AVFilter ff_af_hdcd; +extern AVFilter ff_af_headphone; +extern AVFilter ff_af_highpass; +extern AVFilter ff_af_join; +extern AVFilter ff_af_ladspa; +extern AVFilter ff_af_loudnorm; +extern AVFilter ff_af_lowpass; +extern AVFilter ff_af_lv2; +extern AVFilter ff_af_mcompand; +extern AVFilter ff_af_pan; +extern AVFilter ff_af_replaygain; +extern AVFilter ff_af_resample; +extern AVFilter ff_af_rubberband; +extern AVFilter ff_af_sidechaincompress; +extern AVFilter ff_af_sidechaingate; +extern AVFilter ff_af_silencedetect; +extern AVFilter ff_af_silenceremove; +extern AVFilter ff_af_sofalizer; +extern AVFilter ff_af_stereotools; +extern AVFilter ff_af_stereowiden; +extern AVFilter ff_af_superequalizer; +extern AVFilter ff_af_surround; +extern AVFilter ff_af_treble; +extern AVFilter ff_af_tremolo; +extern AVFilter ff_af_vibrato; +extern AVFilter ff_af_volume; +extern AVFilter ff_af_volumedetect; -#define REGISTER_FILTER(X, x, y) \ - { \ - extern AVFilter ff_##y##_##x; \ - if (CONFIG_##X##_FILTER) \ - avfilter_register(&ff_##y##_##x); \ - } +extern AVFilter ff_asrc_aevalsrc; +extern AVFilter ff_asrc_anoisesrc; +extern AVFilter ff_asrc_anullsrc; +extern AVFilter ff_asrc_flite; +extern AVFilter ff_asrc_hilbert; +extern AVFilter ff_asrc_sine; -#define REGISTER_FILTER_UNCONDITIONAL(x) \ - { \ - extern AVFilter ff_##x; \ - avfilter_register(&ff_##x); \ - } +extern AVFilter ff_asink_anullsink; + +extern AVFilter ff_vf_alphaextract; +extern AVFilter ff_vf_alphamerge; +extern AVFilter ff_vf_ass; +extern AVFilter ff_vf_atadenoise; +extern AVFilter ff_vf_avgblur; +extern AVFilter ff_vf_avgblur_opencl; +extern AVFilter ff_vf_bbox; +extern AVFilter ff_vf_bench; +extern AVFilter ff_vf_bitplanenoise; +extern AVFilter ff_vf_blackdetect; +extern AVFilter ff_vf_blackframe; +extern AVFilter ff_vf_blend; +extern AVFilter ff_vf_boxblur; +extern AVFilter ff_vf_bwdif; +extern AVFilter ff_vf_chromakey; +extern AVFilter ff_vf_ciescope; +extern AVFilter ff_vf_codecview; +extern AVFilter ff_vf_colorbalance; +extern AVFilter ff_vf_colorchannelmixer; +extern AVFilter ff_vf_colorkey; +extern AVFilter ff_vf_colorlevels; +extern AVFilter ff_vf_colormatrix; +extern AVFilter ff_vf_colorspace; +extern AVFilter ff_vf_convolution; +extern AVFilter ff_vf_convolution_opencl; +extern AVFilter ff_vf_convolve; +extern AVFilter ff_vf_copy; +extern AVFilter ff_vf_coreimage; +extern AVFilter ff_vf_cover_rect; +extern AVFilter ff_vf_crop; +extern AVFilter ff_vf_cropdetect; +extern AVFilter ff_vf_curves; +extern AVFilter ff_vf_datascope; +extern AVFilter ff_vf_dctdnoiz; +extern AVFilter ff_vf_deband; +extern AVFilter ff_vf_decimate; +extern AVFilter ff_vf_deconvolve; +extern AVFilter ff_vf_deflate; +extern AVFilter ff_vf_deflicker; +extern AVFilter ff_vf_deinterlace_qsv; +extern AVFilter ff_vf_deinterlace_vaapi; +extern AVFilter ff_vf_dejudder; +extern AVFilter ff_vf_delogo; +extern AVFilter ff_vf_denoise_vaapi; +extern AVFilter ff_vf_deshake; +extern AVFilter ff_vf_despill; +extern AVFilter ff_vf_detelecine; +extern AVFilter ff_vf_dilation; +extern AVFilter ff_vf_displace; +extern AVFilter ff_vf_doubleweave; +extern AVFilter ff_vf_drawbox; +extern AVFilter ff_vf_drawgraph; +extern AVFilter ff_vf_drawgrid; +extern AVFilter ff_vf_drawtext; +extern AVFilter ff_vf_edgedetect; +extern AVFilter ff_vf_elbg; +extern AVFilter ff_vf_entropy; +extern AVFilter ff_vf_eq; +extern AVFilter ff_vf_erosion; +extern AVFilter ff_vf_extractplanes; +extern AVFilter ff_vf_fade; +extern AVFilter ff_vf_fftfilt; +extern AVFilter ff_vf_field; +extern AVFilter ff_vf_fieldhint; +extern AVFilter ff_vf_fieldmatch; +extern AVFilter ff_vf_fieldorder; +extern AVFilter ff_vf_fillborders; +extern AVFilter ff_vf_find_rect; +extern AVFilter ff_vf_floodfill; +extern AVFilter ff_vf_format; +extern AVFilter ff_vf_fps; +extern AVFilter ff_vf_framepack; +extern AVFilter ff_vf_framerate; +extern AVFilter ff_vf_framestep; +extern AVFilter ff_vf_frei0r; +extern AVFilter ff_vf_fspp; +extern AVFilter ff_vf_gblur; +extern AVFilter ff_vf_geq; +extern AVFilter ff_vf_gradfun; +extern AVFilter ff_vf_haldclut; +extern AVFilter ff_vf_hflip; +extern AVFilter ff_vf_histeq; +extern AVFilter ff_vf_histogram; +extern AVFilter ff_vf_hqdn3d; +extern AVFilter ff_vf_hqx; +extern AVFilter ff_vf_hstack; +extern AVFilter ff_vf_hue; +extern AVFilter ff_vf_hwdownload; +extern AVFilter ff_vf_hwmap; +extern AVFilter ff_vf_hwupload; +extern AVFilter ff_vf_hwupload_cuda; +extern AVFilter ff_vf_hysteresis; +extern AVFilter ff_vf_idet; +extern AVFilter ff_vf_il; +extern AVFilter ff_vf_inflate; +extern AVFilter ff_vf_interlace; +extern AVFilter ff_vf_interleave; +extern AVFilter ff_vf_kerndeint; +extern AVFilter ff_vf_lenscorrection; +extern AVFilter ff_vf_libvmaf; +extern AVFilter ff_vf_limiter; +extern AVFilter ff_vf_loop; +extern AVFilter ff_vf_lumakey; +extern AVFilter ff_vf_lut; +extern AVFilter ff_vf_lut2; +extern AVFilter ff_vf_lut3d; +extern AVFilter ff_vf_lutrgb; +extern AVFilter ff_vf_lutyuv; +extern AVFilter ff_vf_maskedclamp; +extern AVFilter ff_vf_maskedmerge; +extern AVFilter ff_vf_mcdeint; +extern AVFilter ff_vf_mergeplanes; +extern AVFilter ff_vf_mestimate; +extern AVFilter ff_vf_metadata; +extern AVFilter ff_vf_midequalizer; +extern AVFilter ff_vf_minterpolate; +extern AVFilter ff_vf_mix; +extern AVFilter ff_vf_mpdecimate; +extern AVFilter ff_vf_negate; +extern AVFilter ff_vf_nlmeans; +extern AVFilter ff_vf_nnedi; +extern AVFilter ff_vf_noformat; +extern AVFilter ff_vf_noise; +extern AVFilter ff_vf_normalize; +extern AVFilter ff_vf_null; +extern AVFilter ff_vf_ocr; +extern AVFilter ff_vf_ocv; +extern AVFilter ff_vf_oscilloscope; +extern AVFilter ff_vf_overlay; +extern AVFilter ff_vf_overlay_opencl; +extern AVFilter ff_vf_overlay_qsv; +extern AVFilter ff_vf_owdenoise; +extern AVFilter ff_vf_pad; +extern AVFilter ff_vf_palettegen; +extern AVFilter ff_vf_paletteuse; +extern AVFilter ff_vf_perms; +extern AVFilter ff_vf_perspective; +extern AVFilter ff_vf_phase; +extern AVFilter ff_vf_pixdesctest; +extern AVFilter ff_vf_pixscope; +extern AVFilter ff_vf_pp; +extern AVFilter ff_vf_pp7; +extern AVFilter ff_vf_premultiply; +extern AVFilter ff_vf_prewitt; +extern AVFilter ff_vf_procamp_vaapi; +extern AVFilter ff_vf_program_opencl; +extern AVFilter ff_vf_pseudocolor; +extern AVFilter ff_vf_psnr; +extern AVFilter ff_vf_pullup; +extern AVFilter ff_vf_qp; +extern AVFilter ff_vf_random; +extern AVFilter ff_vf_readeia608; +extern AVFilter ff_vf_readvitc; +extern AVFilter ff_vf_realtime; +extern AVFilter ff_vf_remap; +extern AVFilter ff_vf_removegrain; +extern AVFilter ff_vf_removelogo; +extern AVFilter ff_vf_repeatfields; +extern AVFilter ff_vf_reverse; +extern AVFilter ff_vf_roberts; +extern AVFilter ff_vf_rotate; +extern AVFilter ff_vf_sab; +extern AVFilter ff_vf_scale; +extern AVFilter ff_vf_scale_cuda; +extern AVFilter ff_vf_scale_npp; +extern AVFilter ff_vf_scale_qsv; +extern AVFilter ff_vf_scale_vaapi; +extern AVFilter ff_vf_scale2ref; +extern AVFilter ff_vf_select; +extern AVFilter ff_vf_selectivecolor; +extern AVFilter ff_vf_sendcmd; +extern AVFilter ff_vf_separatefields; +extern AVFilter ff_vf_setdar; +extern AVFilter ff_vf_setfield; +extern AVFilter ff_vf_setpts; +extern AVFilter ff_vf_setrange; +extern AVFilter ff_vf_setsar; +extern AVFilter ff_vf_settb; +extern AVFilter ff_vf_sharpness_vaapi; +extern AVFilter ff_vf_showinfo; +extern AVFilter ff_vf_showpalette; +extern AVFilter ff_vf_shuffleframes; +extern AVFilter ff_vf_shuffleplanes; +extern AVFilter ff_vf_sidedata; +extern AVFilter ff_vf_signalstats; +extern AVFilter ff_vf_signature; +extern AVFilter ff_vf_smartblur; +extern AVFilter ff_vf_sobel; +extern AVFilter ff_vf_split; +extern AVFilter ff_vf_spp; +extern AVFilter ff_vf_ssim; +extern AVFilter ff_vf_stereo3d; +extern AVFilter ff_vf_streamselect; +extern AVFilter ff_vf_subtitles; +extern AVFilter ff_vf_super2xsai; +extern AVFilter ff_vf_swaprect; +extern AVFilter ff_vf_swapuv; +extern AVFilter ff_vf_tblend; +extern AVFilter ff_vf_telecine; +extern AVFilter ff_vf_threshold; +extern AVFilter ff_vf_thumbnail; +extern AVFilter ff_vf_thumbnail_cuda; +extern AVFilter ff_vf_tile; +extern AVFilter ff_vf_tinterlace; +extern AVFilter ff_vf_tlut2; +extern AVFilter ff_vf_tonemap; +extern AVFilter ff_vf_transpose; +extern AVFilter ff_vf_trim; +extern AVFilter ff_vf_unpremultiply; +extern AVFilter ff_vf_unsharp; +extern AVFilter ff_vf_unsharp_opencl; +extern AVFilter ff_vf_uspp; +extern AVFilter ff_vf_vaguedenoiser; +extern AVFilter ff_vf_vectorscope; +extern AVFilter ff_vf_vflip; +extern AVFilter ff_vf_vidstabdetect; +extern AVFilter ff_vf_vidstabtransform; +extern AVFilter ff_vf_vignette; +extern AVFilter ff_vf_vmafmotion; +extern AVFilter ff_vf_vpp_qsv; +extern AVFilter ff_vf_vstack; +extern AVFilter ff_vf_w3fdif; +extern AVFilter ff_vf_waveform; +extern AVFilter ff_vf_weave; +extern AVFilter ff_vf_xbr; +extern AVFilter ff_vf_yadif; +extern AVFilter ff_vf_zmq; +extern AVFilter ff_vf_zoompan; +extern AVFilter ff_vf_zscale; + +extern AVFilter ff_vsrc_allrgb; +extern AVFilter ff_vsrc_allyuv; +extern AVFilter ff_vsrc_cellauto; +extern AVFilter ff_vsrc_color; +extern AVFilter ff_vsrc_coreimagesrc; +extern AVFilter ff_vsrc_frei0r_src; +extern AVFilter ff_vsrc_haldclutsrc; +extern AVFilter ff_vsrc_life; +extern AVFilter ff_vsrc_mandelbrot; +extern AVFilter ff_vsrc_mptestsrc; +extern AVFilter ff_vsrc_nullsrc; +extern AVFilter ff_vsrc_openclsrc; +extern AVFilter ff_vsrc_rgbtestsrc; +extern AVFilter ff_vsrc_smptebars; +extern AVFilter ff_vsrc_smptehdbars; +extern AVFilter ff_vsrc_testsrc; +extern AVFilter ff_vsrc_testsrc2; +extern AVFilter ff_vsrc_yuvtestsrc; + +extern AVFilter ff_vsink_nullsink; + +/* multimedia filters */ +extern AVFilter ff_avf_abitscope; +extern AVFilter ff_avf_adrawgraph; +extern AVFilter ff_avf_ahistogram; +extern AVFilter ff_avf_aphasemeter; +extern AVFilter ff_avf_avectorscope; +extern AVFilter ff_avf_concat; +extern AVFilter ff_avf_showcqt; +extern AVFilter ff_avf_showfreqs; +extern AVFilter ff_avf_showspectrum; +extern AVFilter ff_avf_showspectrumpic; +extern AVFilter ff_avf_showvolume; +extern AVFilter ff_avf_showwaves; +extern AVFilter ff_avf_showwavespic; +extern AVFilter ff_vaf_spectrumsynth; -static void register_all(void) +/* multimedia sources */ +extern AVFilter ff_avsrc_amovie; +extern AVFilter ff_avsrc_movie; + +/* those filters are part of public or internal API, + * they are formatted to not be found by the grep + * as they are manually added again (due to their 'names' + * being the same while having different 'types'). */ +extern AVFilter ff_asrc_abuffer; +extern AVFilter ff_vsrc_buffer; +extern AVFilter ff_asink_abuffer; +extern AVFilter ff_vsink_buffer; +extern AVFilter ff_af_afifo; +extern AVFilter ff_vf_fifo; + +#include "libavfilter/filter_list.c" + + +const AVFilter *av_filter_iterate(void **opaque) { - REGISTER_FILTER(ABENCH, abench, af); - REGISTER_FILTER(ACOMPRESSOR, acompressor, af); - REGISTER_FILTER(ACONTRAST, acontrast, af); - REGISTER_FILTER(ACOPY, acopy, af); - REGISTER_FILTER(ACROSSFADE, acrossfade, af); - REGISTER_FILTER(ACRUSHER, acrusher, af); - REGISTER_FILTER(ADELAY, adelay, af); - REGISTER_FILTER(AECHO, aecho, af); - REGISTER_FILTER(AEMPHASIS, aemphasis, af); - REGISTER_FILTER(AEVAL, aeval, af); - REGISTER_FILTER(AFADE, afade, af); - REGISTER_FILTER(AFFTFILT, afftfilt, af); - REGISTER_FILTER(AFIR, afir, af); - REGISTER_FILTER(AFORMAT, aformat, af); - REGISTER_FILTER(AGATE, agate, af); - REGISTER_FILTER(AIIR, aiir, af); - REGISTER_FILTER(AINTERLEAVE, ainterleave, af); - REGISTER_FILTER(ALIMITER, alimiter, af); - REGISTER_FILTER(ALLPASS, allpass, af); - REGISTER_FILTER(ALOOP, aloop, af); - REGISTER_FILTER(AMERGE, amerge, af); - REGISTER_FILTER(AMETADATA, ametadata, af); - REGISTER_FILTER(AMIX, amix, af); - REGISTER_FILTER(ANEQUALIZER, anequalizer, af); - REGISTER_FILTER(ANULL, anull, af); - REGISTER_FILTER(APAD, apad, af); - REGISTER_FILTER(APERMS, aperms, af); - REGISTER_FILTER(APHASER, aphaser, af); - REGISTER_FILTER(APULSATOR, apulsator, af); - REGISTER_FILTER(AREALTIME, arealtime, af); - REGISTER_FILTER(ARESAMPLE, aresample, af); - REGISTER_FILTER(AREVERSE, areverse, af); - REGISTER_FILTER(ASELECT, aselect, af); - REGISTER_FILTER(ASENDCMD, asendcmd, af); - REGISTER_FILTER(ASETNSAMPLES, asetnsamples, af); - REGISTER_FILTER(ASETPTS, asetpts, af); - REGISTER_FILTER(ASETRATE, asetrate, af); - REGISTER_FILTER(ASETTB, asettb, af); - REGISTER_FILTER(ASHOWINFO, ashowinfo, af); - REGISTER_FILTER(ASIDEDATA, asidedata, af); - REGISTER_FILTER(ASPLIT, asplit, af); - REGISTER_FILTER(ASTATS, astats, af); - REGISTER_FILTER(ASTREAMSELECT, astreamselect, af); - REGISTER_FILTER(ATEMPO, atempo, af); - REGISTER_FILTER(ATRIM, atrim, af); - REGISTER_FILTER(AZMQ, azmq, af); - REGISTER_FILTER(BANDPASS, bandpass, af); - REGISTER_FILTER(BANDREJECT, bandreject, af); - REGISTER_FILTER(BASS, bass, af); - REGISTER_FILTER(BIQUAD, biquad, af); - REGISTER_FILTER(BS2B, bs2b, af); - REGISTER_FILTER(CHANNELMAP, channelmap, af); - REGISTER_FILTER(CHANNELSPLIT, channelsplit, af); - REGISTER_FILTER(CHORUS, chorus, af); - REGISTER_FILTER(COMPAND, compand, af); - REGISTER_FILTER(COMPENSATIONDELAY, compensationdelay, af); - REGISTER_FILTER(CROSSFEED, crossfeed, af); - REGISTER_FILTER(CRYSTALIZER, crystalizer, af); - REGISTER_FILTER(DCSHIFT, dcshift, af); - REGISTER_FILTER(DRMETER, drmeter, af); - REGISTER_FILTER(DYNAUDNORM, dynaudnorm, af); - REGISTER_FILTER(EARWAX, earwax, af); - REGISTER_FILTER(EBUR128, ebur128, af); - REGISTER_FILTER(EQUALIZER, equalizer, af); - REGISTER_FILTER(EXTRASTEREO, extrastereo, af); - REGISTER_FILTER(FIREQUALIZER, firequalizer, af); - REGISTER_FILTER(FLANGER, flanger, af); - REGISTER_FILTER(HAAS, haas, af); - REGISTER_FILTER(HDCD, hdcd, af); - REGISTER_FILTER(HEADPHONE, headphone, af); - REGISTER_FILTER(HIGHPASS, highpass, af); - REGISTER_FILTER(JOIN, join, af); - REGISTER_FILTER(LADSPA, ladspa, af); - REGISTER_FILTER(LOUDNORM, loudnorm, af); - REGISTER_FILTER(LOWPASS, lowpass, af); - REGISTER_FILTER(LV2, lv2, af); - REGISTER_FILTER(MCOMPAND, mcompand, af); - REGISTER_FILTER(PAN, pan, af); - REGISTER_FILTER(REPLAYGAIN, replaygain, af); - REGISTER_FILTER(RESAMPLE, resample, af); - REGISTER_FILTER(RUBBERBAND, rubberband, af); - REGISTER_FILTER(SIDECHAINCOMPRESS, sidechaincompress, af); - REGISTER_FILTER(SIDECHAINGATE, sidechaingate, af); - REGISTER_FILTER(SILENCEDETECT, silencedetect, af); - REGISTER_FILTER(SILENCEREMOVE, silenceremove, af); - REGISTER_FILTER(SOFALIZER, sofalizer, af); - REGISTER_FILTER(STEREOTOOLS, stereotools, af); - REGISTER_FILTER(STEREOWIDEN, stereowiden, af); - REGISTER_FILTER(SUPEREQUALIZER, superequalizer, af); - REGISTER_FILTER(SURROUND, surround, af); - REGISTER_FILTER(TREBLE, treble, af); - REGISTER_FILTER(TREMOLO, tremolo, af); - REGISTER_FILTER(VIBRATO, vibrato, af); - REGISTER_FILTER(VOLUME, volume, af); - REGISTER_FILTER(VOLUMEDETECT, volumedetect, af); + uintptr_t i = (uintptr_t)*opaque; + const AVFilter *f = filter_list[i]; + + if (f) + *opaque = (void*)(i + 1); - REGISTER_FILTER(AEVALSRC, aevalsrc, asrc); - REGISTER_FILTER(ANOISESRC, anoisesrc, asrc); - REGISTER_FILTER(ANULLSRC, anullsrc, asrc); - REGISTER_FILTER(FLITE, flite, asrc); - REGISTER_FILTER(HILBERT, hilbert, asrc); - REGISTER_FILTER(SINE, sine, asrc); + return f; +} - REGISTER_FILTER(ANULLSINK, anullsink, asink); +const AVFilter *avfilter_get_by_name(const char *name) +{ + const AVFilter *f = NULL; + void *opaque = 0; - REGISTER_FILTER(ALPHAEXTRACT, alphaextract, vf); - REGISTER_FILTER(ALPHAMERGE, alphamerge, vf); - REGISTER_FILTER(ASS, ass, vf); - REGISTER_FILTER(ATADENOISE, atadenoise, vf); - REGISTER_FILTER(AVGBLUR, avgblur, vf); - REGISTER_FILTER(AVGBLUR_OPENCL, avgblur_opencl, vf); - REGISTER_FILTER(BBOX, bbox, vf); - REGISTER_FILTER(BENCH, bench, vf); - REGISTER_FILTER(BITPLANENOISE, bitplanenoise, vf); - REGISTER_FILTER(BLACKDETECT, blackdetect, vf); - REGISTER_FILTER(BLACKFRAME, blackframe, vf); - REGISTER_FILTER(BLEND, blend, vf); - REGISTER_FILTER(BOXBLUR, boxblur, vf); - REGISTER_FILTER(BWDIF, bwdif, vf); - REGISTER_FILTER(CHROMAKEY, chromakey, vf); - REGISTER_FILTER(CIESCOPE, ciescope, vf); - REGISTER_FILTER(CODECVIEW, codecview, vf); - REGISTER_FILTER(COLORBALANCE, colorbalance, vf); - REGISTER_FILTER(COLORCHANNELMIXER, colorchannelmixer, vf); - REGISTER_FILTER(COLORKEY, colorkey, vf); - REGISTER_FILTER(COLORLEVELS, colorlevels, vf); - REGISTER_FILTER(COLORMATRIX, colormatrix, vf); - REGISTER_FILTER(COLORSPACE, colorspace, vf); - REGISTER_FILTER(CONVOLUTION, convolution, vf); - REGISTER_FILTER(CONVOLUTION_OPENCL, convolution_opencl, vf); - REGISTER_FILTER(CONVOLVE, convolve, vf); - REGISTER_FILTER(COPY, copy, vf); - REGISTER_FILTER(COREIMAGE, coreimage, vf); - REGISTER_FILTER(COVER_RECT, cover_rect, vf); - REGISTER_FILTER(CROP, crop, vf); - REGISTER_FILTER(CROPDETECT, cropdetect, vf); - REGISTER_FILTER(CURVES, curves, vf); - REGISTER_FILTER(DATASCOPE, datascope, vf); - REGISTER_FILTER(DCTDNOIZ, dctdnoiz, vf); - REGISTER_FILTER(DEBAND, deband, vf); - REGISTER_FILTER(DECIMATE, decimate, vf); - REGISTER_FILTER(DECONVOLVE, deconvolve, vf); - REGISTER_FILTER(DEFLATE, deflate, vf); - REGISTER_FILTER(DEFLICKER, deflicker, vf); - REGISTER_FILTER(DEINTERLACE_QSV,deinterlace_qsv,vf); - REGISTER_FILTER(DEINTERLACE_VAAPI, deinterlace_vaapi, vf); - REGISTER_FILTER(DEJUDDER, dejudder, vf); - REGISTER_FILTER(DELOGO, delogo, vf); - REGISTER_FILTER(DENOISE_VAAPI, denoise_vaapi, vf); - REGISTER_FILTER(DESHAKE, deshake, vf); - REGISTER_FILTER(DESPILL, despill, vf); - REGISTER_FILTER(DETELECINE, detelecine, vf); - REGISTER_FILTER(DILATION, dilation, vf); - REGISTER_FILTER(DISPLACE, displace, vf); - REGISTER_FILTER(DOUBLEWEAVE, doubleweave, vf); - REGISTER_FILTER(DRAWBOX, drawbox, vf); - REGISTER_FILTER(DRAWGRAPH, drawgraph, vf); - REGISTER_FILTER(DRAWGRID, drawgrid, vf); - REGISTER_FILTER(DRAWTEXT, drawtext, vf); - REGISTER_FILTER(EDGEDETECT, edgedetect, vf); - REGISTER_FILTER(ELBG, elbg, vf); - REGISTER_FILTER(ENTROPY, entropy, vf); - REGISTER_FILTER(EQ, eq, vf); - REGISTER_FILTER(EROSION, erosion, vf); - REGISTER_FILTER(EXTRACTPLANES, extractplanes, vf); - REGISTER_FILTER(FADE, fade, vf); - REGISTER_FILTER(FFTFILT, fftfilt, vf); - REGISTER_FILTER(FIELD, field, vf); - REGISTER_FILTER(FIELDHINT, fieldhint, vf); - REGISTER_FILTER(FIELDMATCH, fieldmatch, vf); - REGISTER_FILTER(FIELDORDER, fieldorder, vf); - REGISTER_FILTER(FILLBORDERS, fillborders, vf); - REGISTER_FILTER(FIND_RECT, find_rect, vf); - REGISTER_FILTER(FLOODFILL, floodfill, vf); - REGISTER_FILTER(FORMAT, format, vf); - REGISTER_FILTER(FPS, fps, vf); - REGISTER_FILTER(FRAMEPACK, framepack, vf); - REGISTER_FILTER(FRAMERATE, framerate, vf); - REGISTER_FILTER(FRAMESTEP, framestep, vf); - REGISTER_FILTER(FREI0R, frei0r, vf); - REGISTER_FILTER(FSPP, fspp, vf); - REGISTER_FILTER(GBLUR, gblur, vf); - REGISTER_FILTER(GEQ, geq, vf); - REGISTER_FILTER(GRADFUN, gradfun, vf); - REGISTER_FILTER(HALDCLUT, haldclut, vf); - REGISTER_FILTER(HFLIP, hflip, vf); - REGISTER_FILTER(HISTEQ, histeq, vf); - REGISTER_FILTER(HISTOGRAM, histogram, vf); - REGISTER_FILTER(HQDN3D, hqdn3d, vf); - REGISTER_FILTER(HQX, hqx, vf); - REGISTER_FILTER(HSTACK, hstack, vf); - REGISTER_FILTER(HUE, hue, vf); - REGISTER_FILTER(HWDOWNLOAD, hwdownload, vf); - REGISTER_FILTER(HWMAP, hwmap, vf); - REGISTER_FILTER(HWUPLOAD, hwupload, vf); - REGISTER_FILTER(HWUPLOAD_CUDA, hwupload_cuda, vf); - REGISTER_FILTER(HYSTERESIS, hysteresis, vf); - REGISTER_FILTER(IDET, idet, vf); - REGISTER_FILTER(IL, il, vf); - REGISTER_FILTER(INFLATE, inflate, vf); - REGISTER_FILTER(INTERLACE, interlace, vf); - REGISTER_FILTER(INTERLEAVE, interleave, vf); - REGISTER_FILTER(KERNDEINT, kerndeint, vf); - REGISTER_FILTER(LENSCORRECTION, lenscorrection, vf); - REGISTER_FILTER(LIBVMAF, libvmaf, vf); - REGISTER_FILTER(LIMITER, limiter, vf); - REGISTER_FILTER(LOOP, loop, vf); - REGISTER_FILTER(LUMAKEY, lumakey, vf); - REGISTER_FILTER(LUT, lut, vf); - REGISTER_FILTER(LUT2, lut2, vf); - REGISTER_FILTER(LUT3D, lut3d, vf); - REGISTER_FILTER(LUTRGB, lutrgb, vf); - REGISTER_FILTER(LUTYUV, lutyuv, vf); - REGISTER_FILTER(MASKEDCLAMP, maskedclamp, vf); - REGISTER_FILTER(MASKEDMERGE, maskedmerge, vf); - REGISTER_FILTER(MCDEINT, mcdeint, vf); - REGISTER_FILTER(MERGEPLANES, mergeplanes, vf); - REGISTER_FILTER(MESTIMATE, mestimate, vf); - REGISTER_FILTER(METADATA, metadata, vf); - REGISTER_FILTER(MIDEQUALIZER, midequalizer, vf); - REGISTER_FILTER(MINTERPOLATE, minterpolate, vf); - REGISTER_FILTER(MIX, mix, vf); - REGISTER_FILTER(MPDECIMATE, mpdecimate, vf); - REGISTER_FILTER(NEGATE, negate, vf); - REGISTER_FILTER(NLMEANS, nlmeans, vf); - REGISTER_FILTER(NNEDI, nnedi, vf); - REGISTER_FILTER(NOFORMAT, noformat, vf); - REGISTER_FILTER(NOISE, noise, vf); - REGISTER_FILTER(NORMALIZE, normalize, vf); - REGISTER_FILTER(NULL, null, vf); - REGISTER_FILTER(OCR, ocr, vf); - REGISTER_FILTER(OCV, ocv, vf); - REGISTER_FILTER(OSCILLOSCOPE, oscilloscope, vf); - REGISTER_FILTER(OVERLAY, overlay, vf); - REGISTER_FILTER(OVERLAY_OPENCL, overlay_opencl, vf); - REGISTER_FILTER(OVERLAY_QSV, overlay_qsv, vf); - REGISTER_FILTER(OWDENOISE, owdenoise, vf); - REGISTER_FILTER(PAD, pad, vf); - REGISTER_FILTER(PALETTEGEN, palettegen, vf); - REGISTER_FILTER(PALETTEUSE, paletteuse, vf); - REGISTER_FILTER(PERMS, perms, vf); - REGISTER_FILTER(PERSPECTIVE, perspective, vf); - REGISTER_FILTER(PHASE, phase, vf); - REGISTER_FILTER(PIXDESCTEST, pixdesctest, vf); - REGISTER_FILTER(PIXSCOPE, pixscope, vf); - REGISTER_FILTER(PP, pp, vf); - REGISTER_FILTER(PP7, pp7, vf); - REGISTER_FILTER(PREMULTIPLY, premultiply, vf); - REGISTER_FILTER(PREWITT, prewitt, vf); - REGISTER_FILTER(PROCAMP_VAAPI, procamp_vaapi, vf); - REGISTER_FILTER(PROGRAM_OPENCL, program_opencl, vf); - REGISTER_FILTER(PSEUDOCOLOR, pseudocolor, vf); - REGISTER_FILTER(PSNR, psnr, vf); - REGISTER_FILTER(PULLUP, pullup, vf); - REGISTER_FILTER(QP, qp, vf); - REGISTER_FILTER(RANDOM, random, vf); - REGISTER_FILTER(READEIA608, readeia608, vf); - REGISTER_FILTER(READVITC, readvitc, vf); - REGISTER_FILTER(REALTIME, realtime, vf); - REGISTER_FILTER(REMAP, remap, vf); - REGISTER_FILTER(REMOVEGRAIN, removegrain, vf); - REGISTER_FILTER(REMOVELOGO, removelogo, vf); - REGISTER_FILTER(REPEATFIELDS, repeatfields, vf); - REGISTER_FILTER(REVERSE, reverse, vf); - REGISTER_FILTER(ROBERTS, roberts, vf); - REGISTER_FILTER(ROTATE, rotate, vf); - REGISTER_FILTER(SAB, sab, vf); - REGISTER_FILTER(SCALE, scale, vf); - REGISTER_FILTER(SCALE_CUDA, scale_cuda, vf); - REGISTER_FILTER(SCALE_NPP, scale_npp, vf); - REGISTER_FILTER(SCALE_QSV, scale_qsv, vf); - REGISTER_FILTER(SCALE_VAAPI, scale_vaapi, vf); - REGISTER_FILTER(SCALE2REF, scale2ref, vf); - REGISTER_FILTER(SELECT, select, vf); - REGISTER_FILTER(SELECTIVECOLOR, selectivecolor, vf); - REGISTER_FILTER(SENDCMD, sendcmd, vf); - REGISTER_FILTER(SEPARATEFIELDS, separatefields, vf); - REGISTER_FILTER(SETDAR, setdar, vf); - REGISTER_FILTER(SETFIELD, setfield, vf); - REGISTER_FILTER(SETPTS, setpts, vf); - REGISTER_FILTER(SETRANGE, setrange, vf); - REGISTER_FILTER(SETSAR, setsar, vf); - REGISTER_FILTER(SETTB, settb, vf); - REGISTER_FILTER(SHARPNESS_VAAPI, sharpness_vaapi, vf); - REGISTER_FILTER(SHOWINFO, showinfo, vf); - REGISTER_FILTER(SHOWPALETTE, showpalette, vf); - REGISTER_FILTER(SHUFFLEFRAMES, shuffleframes, vf); - REGISTER_FILTER(SHUFFLEPLANES, shuffleplanes, vf); - REGISTER_FILTER(SIDEDATA, sidedata, vf); - REGISTER_FILTER(SIGNALSTATS, signalstats, vf); - REGISTER_FILTER(SIGNATURE, signature, vf); - REGISTER_FILTER(SMARTBLUR, smartblur, vf); - REGISTER_FILTER(SOBEL, sobel, vf); - REGISTER_FILTER(SPLIT, split, vf); - REGISTER_FILTER(SPP, spp, vf); - REGISTER_FILTER(SSIM, ssim, vf); - REGISTER_FILTER(STEREO3D, stereo3d, vf); - REGISTER_FILTER(STREAMSELECT, streamselect, vf); - REGISTER_FILTER(SUBTITLES, subtitles, vf); - REGISTER_FILTER(SUPER2XSAI, super2xsai, vf); - REGISTER_FILTER(SWAPRECT, swaprect, vf); - REGISTER_FILTER(SWAPUV, swapuv, vf); - REGISTER_FILTER(TBLEND, tblend, vf); - REGISTER_FILTER(TELECINE, telecine, vf); - REGISTER_FILTER(THRESHOLD, threshold, vf); - REGISTER_FILTER(THUMBNAIL, thumbnail, vf); - REGISTER_FILTER(THUMBNAIL_CUDA, thumbnail_cuda, vf); - REGISTER_FILTER(TILE, tile, vf); - REGISTER_FILTER(TINTERLACE, tinterlace, vf); - REGISTER_FILTER(TLUT2, tlut2, vf); - REGISTER_FILTER(TONEMAP, tonemap, vf); - REGISTER_FILTER(TRANSPOSE, transpose, vf); - REGISTER_FILTER(TRIM, trim, vf); - REGISTER_FILTER(UNPREMULTIPLY, unpremultiply, vf); - REGISTER_FILTER(UNSHARP, unsharp, vf); - REGISTER_FILTER(UNSHARP_OPENCL, unsharp_opencl, vf); - REGISTER_FILTER(USPP, uspp, vf); - REGISTER_FILTER(VAGUEDENOISER, vaguedenoiser, vf); - REGISTER_FILTER(VECTORSCOPE, vectorscope, vf); - REGISTER_FILTER(VFLIP, vflip, vf); - REGISTER_FILTER(VIDSTABDETECT, vidstabdetect, vf); - REGISTER_FILTER(VIDSTABTRANSFORM, vidstabtransform, vf); - REGISTER_FILTER(VIGNETTE, vignette, vf); - REGISTER_FILTER(VMAFMOTION, vmafmotion, vf); - REGISTER_FILTER(VPP_QSV, vpp_qsv, vf); - REGISTER_FILTER(VSTACK, vstack, vf); - REGISTER_FILTER(W3FDIF, w3fdif, vf); - REGISTER_FILTER(WAVEFORM, waveform, vf); - REGISTER_FILTER(WEAVE, weave, vf); - REGISTER_FILTER(XBR, xbr, vf); - REGISTER_FILTER(YADIF, yadif, vf); - REGISTER_FILTER(ZMQ, zmq, vf); - REGISTER_FILTER(ZOOMPAN, zoompan, vf); - REGISTER_FILTER(ZSCALE, zscale, vf); + if (!name) + return NULL; - REGISTER_FILTER(ALLRGB, allrgb, vsrc); - REGISTER_FILTER(ALLYUV, allyuv, vsrc); - REGISTER_FILTER(CELLAUTO, cellauto, vsrc); - REGISTER_FILTER(COLOR, color, vsrc); - REGISTER_FILTER(COREIMAGESRC, coreimagesrc, vsrc); - REGISTER_FILTER(FREI0R, frei0r_src, vsrc); - REGISTER_FILTER(HALDCLUTSRC, haldclutsrc, vsrc); - REGISTER_FILTER(LIFE, life, vsrc); - REGISTER_FILTER(MANDELBROT, mandelbrot, vsrc); - REGISTER_FILTER(MPTESTSRC, mptestsrc, vsrc); - REGISTER_FILTER(NULLSRC, nullsrc, vsrc); - REGISTER_FILTER(OPENCLSRC, openclsrc, vsrc); - REGISTER_FILTER(RGBTESTSRC, rgbtestsrc, vsrc); - REGISTER_FILTER(SMPTEBARS, smptebars, vsrc); - REGISTER_FILTER(SMPTEHDBARS, smptehdbars, vsrc); - REGISTER_FILTER(TESTSRC, testsrc, vsrc); - REGISTER_FILTER(TESTSRC2, testsrc2, vsrc); - REGISTER_FILTER(YUVTESTSRC, yuvtestsrc, vsrc); + while ((f = av_filter_iterate(&opaque))) + if (!strcmp(f->name, name)) + return (AVFilter *)f; - REGISTER_FILTER(NULLSINK, nullsink, vsink); + return NULL; +} - /* multimedia filters */ - REGISTER_FILTER(ABITSCOPE, abitscope, avf); - REGISTER_FILTER(ADRAWGRAPH, adrawgraph, avf); - REGISTER_FILTER(AHISTOGRAM, ahistogram, avf); - REGISTER_FILTER(APHASEMETER, aphasemeter, avf); - REGISTER_FILTER(AVECTORSCOPE, avectorscope, avf); - REGISTER_FILTER(CONCAT, concat, avf); - REGISTER_FILTER(SHOWCQT, showcqt, avf); - REGISTER_FILTER(SHOWFREQS, showfreqs, avf); - REGISTER_FILTER(SHOWSPECTRUM, showspectrum, avf); - REGISTER_FILTER(SHOWSPECTRUMPIC, showspectrumpic, avf); - REGISTER_FILTER(SHOWVOLUME, showvolume, avf); - REGISTER_FILTER(SHOWWAVES, showwaves, avf); - REGISTER_FILTER(SHOWWAVESPIC, showwavespic, avf); - REGISTER_FILTER(SPECTRUMSYNTH, spectrumsynth, vaf); - /* multimedia sources */ - REGISTER_FILTER(AMOVIE, amovie, avsrc); - REGISTER_FILTER(MOVIE, movie, avsrc); +#if FF_API_NEXT +FF_DISABLE_DEPRECATION_WARNINGS +static AVOnce av_filter_next_init = AV_ONCE_INIT; - /* those filters are part of public or internal API => registered - * unconditionally */ - REGISTER_FILTER_UNCONDITIONAL(asrc_abuffer); - REGISTER_FILTER_UNCONDITIONAL(vsrc_buffer); - REGISTER_FILTER_UNCONDITIONAL(asink_abuffer); - REGISTER_FILTER_UNCONDITIONAL(vsink_buffer); - REGISTER_FILTER_UNCONDITIONAL(af_afifo); - REGISTER_FILTER_UNCONDITIONAL(vf_fifo); +static void av_filter_init_next(void) +{ + AVFilter *prev = NULL, *p; + void *i = 0; + while ((p = (AVFilter*)av_filter_iterate(&i))) { + if (prev) + prev->next = p; + prev = p; + } } void avfilter_register_all(void) { - static AVOnce control = AV_ONCE_INIT; + ff_thread_once(&av_filter_next_init, av_filter_init_next); +} + +int avfilter_register(AVFilter *filter) +{ + ff_thread_once(&av_filter_next_init, av_filter_init_next); + + return 0; +} + +const AVFilter *avfilter_next(const AVFilter *prev) +{ + ff_thread_once(&av_filter_next_init, av_filter_init_next); - ff_thread_once(&control, register_all); + return prev ? prev->next : filter_list[0]; } + +FF_ENABLE_DEPRECATION_WARNINGS +#endif diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 7553f7c36a22f..ed8161136c272 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -575,51 +575,6 @@ int avfilter_process_command(AVFilterContext *filter, const char *cmd, const cha return AVERROR(ENOSYS); } -static AVFilter *first_filter; -static AVFilter **last_filter = &first_filter; - -const AVFilter *avfilter_get_by_name(const char *name) -{ - const AVFilter *f = NULL; - - if (!name) - return NULL; - - while ((f = avfilter_next(f))) - if (!strcmp(f->name, name)) - return (AVFilter *)f; - - return NULL; -} - -static AVMutex filter_register_mutex = AV_MUTEX_INITIALIZER; - -int avfilter_register(AVFilter *filter) -{ - AVFilter **f; - - /* the filter must select generic or internal exclusively */ - av_assert0((filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE) != AVFILTER_FLAG_SUPPORT_TIMELINE); - - ff_mutex_lock(&filter_register_mutex); - f = last_filter; - - while (*f) - f = &(*f)->next; - *f = filter; - filter->next = NULL; - last_filter = &filter->next; - - ff_mutex_unlock(&filter_register_mutex); - - return 0; -} - -const AVFilter *avfilter_next(const AVFilter *prev) -{ - return prev ? prev->next : first_filter; -} - int avfilter_pad_count(const AVFilterPad *pads) { int count; @@ -648,10 +603,11 @@ static void *filter_child_next(void *obj, void *prev) static const AVClass *filter_child_class_next(const AVClass *prev) { + void *opaque = NULL; const AVFilter *f = NULL; /* find the filter that corresponds to prev */ - while (prev && (f = avfilter_next(f))) + while (prev && (f = av_filter_iterate(&opaque))) if (f->priv_class == prev) break; @@ -660,7 +616,7 @@ static const AVClass *filter_child_class_next(const AVClass *prev) return NULL; /* find next filter with specific options */ - while ((f = avfilter_next(f))) + while ((f = av_filter_iterate(&opaque))) if (f->priv_class) return f->priv_class; diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 2d1195eeeb7aa..9d70e7118beea 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -697,7 +697,20 @@ int avfilter_config_links(AVFilterContext *filter); */ int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags); +/** + * Iterate over all registered filters. + * + * @param opaque a pointer where libavfilter will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered filter or NULL when the iteration is + * finished + */ +const AVFilter *av_filter_iterate(void **opaque); + +#if FF_API_NEXT /** Initialize the filter system. Register all builtin filters. */ +attribute_deprecated void avfilter_register_all(void); /** @@ -710,8 +723,18 @@ void avfilter_register_all(void); * @return 0 if the registration was successful, a negative value * otherwise */ +attribute_deprecated int avfilter_register(AVFilter *filter); +/** + * Iterate over all registered filters. + * @return If prev is non-NULL, next registered filter after prev or NULL if + * prev is the last filter. If prev is NULL, return the first registered filter. + */ +attribute_deprecated +const AVFilter *avfilter_next(const AVFilter *prev); +#endif + /** * Get a filter definition matching the given name. * @@ -721,12 +744,6 @@ int avfilter_register(AVFilter *filter); */ const AVFilter *avfilter_get_by_name(const char *name); -/** - * Iterate over all registered filters. - * @return If prev is non-NULL, next registered filter after prev or NULL if - * prev is the last filter. If prev is NULL, return the first registered filter. - */ -const AVFilter *avfilter_next(const AVFilter *prev); /** * Initialize a filter with the supplied parameters. diff --git a/libavfilter/version.h b/libavfilter/version.h index babb4187b4199..8d77a500bf1ac 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -58,5 +58,8 @@ #ifndef FF_API_FILTER_GET_SET #define FF_API_FILTER_GET_SET (LIBAVFILTER_VERSION_MAJOR < 8) #endif +#ifndef FF_API_NEXT +#define FF_API_NEXT (LIBAVFILTER_VERSION_MAJOR < 8) +#endif #endif /* AVFILTER_VERSION_H */ From d8ae40611bc01257776b71f20d774eb720151906 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Fri, 23 Mar 2018 10:16:15 +0000 Subject: [PATCH 2309/2557] Revert "lavd: add new API for iterating input and output devices" This reverts commit 0fd475704e871ef3a535947596a012894bae3cbd. Revert "lavd: fix iterating of input and output devices" This reverts commit ce1d77a5e7cebce11074bf6f9e38ad6da37338ff. Signed-off-by: Josh de Kock --- Makefile | 3 +- configure | 23 +++-- doc/APIchanges | 5 -- libavdevice/.gitignore | 2 - libavdevice/alldevices.c | 179 ++++++++++----------------------------- libavdevice/avdevice.c | 46 ++++++++++ libavdevice/avdevice.h | 28 ------ libavdevice/version.h | 4 - libavformat/allformats.c | 42 +-------- libavformat/format.c | 8 -- libavformat/internal.h | 7 -- 11 files changed, 103 insertions(+), 244 deletions(-) delete mode 100644 libavdevice/.gitignore diff --git a/Makefile b/Makefile index bb93b69f8910d..0cd0a1d6f2d55 100644 --- a/Makefile +++ b/Makefile @@ -144,8 +144,7 @@ distclean:: clean version.h libavutil/ffversion.h libavcodec/codec_names.h \ libavcodec/bsf_list.c libavformat/protocol_list.c \ libavcodec/codec_list.c libavcodec/parser_list.c \ - libavformat/muxer_list.c libavformat/demuxer_list.c \ - libavdevice/indev_list.c libavdevice/outdev_list.c + libavformat/muxer_list.c libavformat/demuxer_list.c ifeq ($(SRC_LINK),src) $(RM) src endif diff --git a/configure b/configure index 6ef3d8abef2b2..b57e3d709ae75 100755 --- a/configure +++ b/configure @@ -3622,12 +3622,21 @@ for v in "$@"; do FFMPEG_CONFIGURATION="${FFMPEG_CONFIGURATION# } ${l}${r}" done +find_things(){ + thing=$1 + pattern=$2 + file=$source_path/$3 + sed -n "s/^[^#]*$pattern.*([^,]*, *\([^,]*\)\(,.*\)*).*/\1_$thing/p" "$file" +} + +OUTDEV_LIST=$(find_things outdev OUTDEV libavdevice/alldevices.c) +INDEV_LIST=$(find_things indev _IN libavdevice/alldevices.c) + find_things_extern(){ thing=$1 pattern=$2 file=$source_path/$3 - out=${4:-$thing} - sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$out/p" "$file" + sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" "$file" } find_filters_extern(){ @@ -3637,8 +3646,6 @@ find_filters_extern(){ } FILTER_LIST=$(find_filters_extern libavfilter/allfilters.c) -OUTDEV_LIST=$(find_things_extern muxer AVOutputFormat libavdevice/alldevices.c outdev) -INDEV_LIST=$(find_things_extern demuxer AVInputFormat libavdevice/alldevices.c indev) MUXER_LIST=$(find_things_extern muxer AVOutputFormat libavformat/allformats.c) DEMUXER_LIST=$(find_things_extern demuxer AVInputFormat libavformat/allformats.c) ENCODER_LIST=$(find_things_extern encoder AVCodec libavcodec/allcodecs.c) @@ -7172,12 +7179,6 @@ print_enabled_components(){ filter_list) c=$(full_filter_name $(remove_suffix _filter $c)) ;; - indev_list) - c=$(add_suffix _demuxer $(remove_suffix _indev $c)) - ;; - outdev_list) - c=$(add_suffix _muxer $(remove_suffix _outdev $c)) - ;; esac printf " &ff_%s,\n" $c >> $TMPH fi @@ -7195,8 +7196,6 @@ print_enabled_components libavfilter/filter_list.c AVFilter filter_list $FILTER_ print_enabled_components libavcodec/codec_list.c AVCodec codec_list $CODEC_LIST print_enabled_components libavcodec/parser_list.c AVCodecParser parser_list $PARSER_LIST print_enabled_components libavcodec/bsf_list.c AVBitStreamFilter bitstream_filters $BSF_LIST -print_enabled_components libavdevice/indev_list.c AVInputFormat indev_list $INDEV_LIST -print_enabled_components libavdevice/outdev_list.c AVOutputFormat outdev_list $OUTDEV_LIST print_enabled_components libavformat/demuxer_list.c AVInputFormat demuxer_list $DEMUXER_LIST print_enabled_components libavformat/muxer_list.c AVOutputFormat muxer_list $MUXER_LIST print_enabled_components libavformat/protocol_list.c URLProtocol url_protocols $PROTOCOL_LIST diff --git a/doc/APIchanges b/doc/APIchanges index dbc4617f8d4ea..235868b22a088 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -56,11 +56,6 @@ API changes, most recent first: 2018-02-xx - xxxxxxx - lavc 58.11.100 - avcodec.h Add AVCodecContext.extra_hw_frames. -2018-02-06 - 0fd475704e - lavd 58.1.100 - avdevice.h - Deprecate use of av_input_audio_device_next(), av_input_video_device_next(), - av_output_audio_device_next(), av_output_video_device_next(). - Add av_indev_iterate(), and av_outdev_iterate(). - 2018-xx-xx - xxxxxxx - lavf 58.9.100 - avformat.h Deprecate use of av_register_input_format(), av_register_output_format(), av_register_all(), av_iformat_next(), av_oformat_next(). diff --git a/libavdevice/.gitignore b/libavdevice/.gitignore deleted file mode 100644 index 08ac3eb86a81f..0000000000000 --- a/libavdevice/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/indev_list.c -/outdev_list.c diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index 39993354bc428..b767b6a718821 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -22,150 +22,57 @@ #include "libavutil/thread.h" #include "avdevice.h" -#if FF_API_NEXT -#include "libavformat/internal.h" -#endif - -/* devices */ -extern AVInputFormat ff_alsa_demuxer; -extern AVOutputFormat ff_alsa_muxer; -extern AVInputFormat ff_android_camera_demuxer; -extern AVInputFormat ff_avfoundation_demuxer; -extern AVInputFormat ff_bktr_demuxer; -extern AVOutputFormat ff_caca_muxer; -extern AVInputFormat ff_decklink_demuxer; -extern AVOutputFormat ff_decklink_muxer; -extern AVInputFormat ff_libndi_newtek_demuxer; -extern AVOutputFormat ff_libndi_newtek_muxer; -extern AVInputFormat ff_dshow_demuxer; -extern AVInputFormat ff_fbdev_demuxer; -extern AVOutputFormat ff_fbdev_muxer; -extern AVInputFormat ff_gdigrab_demuxer; -extern AVInputFormat ff_iec61883_demuxer; -extern AVInputFormat ff_jack_demuxer; -extern AVInputFormat ff_kmsgrab_demuxer; -extern AVInputFormat ff_lavfi_demuxer; -extern AVInputFormat ff_openal_demuxer; -extern AVOutputFormat ff_opengl_muxer; -extern AVInputFormat ff_oss_demuxer; -extern AVOutputFormat ff_oss_muxer; -extern AVInputFormat ff_pulse_demuxer; -extern AVOutputFormat ff_pulse_muxer; -extern AVOutputFormat ff_sdl2_muxer; -extern AVInputFormat ff_sndio_demuxer; -extern AVOutputFormat ff_sndio_muxer; -extern AVInputFormat ff_v4l2_demuxer; -extern AVOutputFormat ff_v4l2_muxer; -extern AVInputFormat ff_vfwcap_demuxer; -extern AVInputFormat ff_xcbgrab_demuxer; -extern AVOutputFormat ff_xv_muxer; - -/* external libraries */ -extern AVInputFormat ff_libcdio_demuxer; -extern AVInputFormat ff_libdc1394_demuxer; - -#include "libavdevice/outdev_list.c" -#include "libavdevice/indev_list.c" - -const AVOutputFormat *av_outdev_iterate(void **opaque) -{ - uintptr_t i = (uintptr_t)*opaque; - const AVOutputFormat *f = outdev_list[i]; - - if (f) - *opaque = (void*)(i + 1); - return f; -} - -const AVInputFormat *av_indev_iterate(void **opaque) -{ - uintptr_t i = (uintptr_t)*opaque; - const AVInputFormat *f = indev_list[i]; - - if (f) - *opaque = (void*)(i + 1); - return f; -} - -#if FF_API_NEXT -FF_DISABLE_DEPRECATION_WARNINGS -static AVOnce av_device_next_init = AV_ONCE_INIT; - -static void av_device_init_next(void) -{ - AVOutputFormat *prevout = NULL, *out; - AVInputFormat *previn = NULL, *in; - void *i = 0; - - while ((out = (AVOutputFormat*)av_outdev_iterate(&i))) { - if (prevout) - prevout->next = out; - prevout = out; +#define REGISTER_OUTDEV(X, x) \ + { \ + extern AVOutputFormat ff_##x##_muxer; \ + if (CONFIG_##X##_OUTDEV) \ + av_register_output_format(&ff_##x##_muxer); \ } - i = 0; - while ((in = (AVInputFormat*)av_indev_iterate(&i))) { - if (previn) - previn->next = in; - previn = in; +#define REGISTER_INDEV(X, x) \ + { \ + extern AVInputFormat ff_##x##_demuxer; \ + if (CONFIG_##X##_INDEV) \ + av_register_input_format(&ff_##x##_demuxer); \ } - avpriv_register_devices(outdev_list, indev_list); -} - -void avdevice_register_all(void) -{ - ff_thread_once(&av_device_next_init, av_device_init_next); -} - -static void *device_next(void *prev, int output, - AVClassCategory c1, AVClassCategory c2) -{ - const AVClass *pc; - AVClassCategory category = AV_CLASS_CATEGORY_NA; - - ff_thread_once(&av_device_next_init, av_device_init_next); - - do { - if (output) { - if (!(prev = prev ? ((AVOutputFormat *)prev)->next : (void*)outdev_list[0])) - break; - pc = ((AVOutputFormat *)prev)->priv_class; - } else { - if (!(prev = prev ? ((AVInputFormat *)prev)->next : (void*)indev_list[0])) - break; - pc = ((AVInputFormat *)prev)->priv_class; - } - if (!pc) - continue; - category = pc->category; - } while (category != c1 && category != c2); - return prev; -} - -AVInputFormat *av_input_audio_device_next(AVInputFormat *d) -{ - return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, - AV_CLASS_CATEGORY_DEVICE_INPUT); -} +#define REGISTER_INOUTDEV(X, x) REGISTER_OUTDEV(X, x); REGISTER_INDEV(X, x) -AVInputFormat *av_input_video_device_next(AVInputFormat *d) +static void register_all(void) { - return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, - AV_CLASS_CATEGORY_DEVICE_INPUT); + /* devices */ + REGISTER_INOUTDEV(ALSA, alsa); + REGISTER_INDEV (AVFOUNDATION, avfoundation); + REGISTER_INDEV (BKTR, bktr); + REGISTER_OUTDEV (CACA, caca); + REGISTER_INOUTDEV(DECKLINK, decklink); + REGISTER_INOUTDEV(LIBNDI_NEWTEK, libndi_newtek); + REGISTER_INDEV (DSHOW, dshow); + REGISTER_INOUTDEV(FBDEV, fbdev); + REGISTER_INDEV (GDIGRAB, gdigrab); + REGISTER_INDEV (IEC61883, iec61883); + REGISTER_INDEV (JACK, jack); + REGISTER_INDEV (KMSGRAB, kmsgrab); + REGISTER_INDEV (LAVFI, lavfi); + REGISTER_INDEV (OPENAL, openal); + REGISTER_OUTDEV (OPENGL, opengl); + REGISTER_INOUTDEV(OSS, oss); + REGISTER_INOUTDEV(PULSE, pulse); + REGISTER_OUTDEV (SDL2, sdl2); + REGISTER_INOUTDEV(SNDIO, sndio); + REGISTER_INOUTDEV(V4L2, v4l2); + REGISTER_INDEV (VFWCAP, vfwcap); + REGISTER_INDEV (XCBGRAB, xcbgrab); + REGISTER_OUTDEV (XV, xv); + + /* external libraries */ + REGISTER_INDEV (LIBCDIO, libcdio); + REGISTER_INDEV (LIBDC1394, libdc1394); } -AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d) +void avdevice_register_all(void) { - return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, - AV_CLASS_CATEGORY_DEVICE_OUTPUT); -} + static AVOnce control = AV_ONCE_INIT; -AVOutputFormat *av_output_video_device_next(AVOutputFormat *d) -{ - return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, - AV_CLASS_CATEGORY_DEVICE_OUTPUT); + ff_thread_once(&control, register_all); } -FF_DISABLE_DEPRECATION_WARNINGS -#endif - diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c index a42d3498b56d5..72e1b67887f9b 100644 --- a/libavdevice/avdevice.c +++ b/libavdevice/avdevice.c @@ -78,6 +78,52 @@ const char * avdevice_license(void) return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; } +static void *device_next(void *prev, int output, + AVClassCategory c1, AVClassCategory c2) +{ + const AVClass *pc; + AVClassCategory category = AV_CLASS_CATEGORY_NA; + do { + if (output) { + if (!(prev = av_oformat_next(prev))) + break; + pc = ((AVOutputFormat *)prev)->priv_class; + } else { + if (!(prev = av_iformat_next(prev))) + break; + pc = ((AVInputFormat *)prev)->priv_class; + } + if (!pc) + continue; + category = pc->category; + } while (category != c1 && category != c2); + return prev; +} + +AVInputFormat *av_input_audio_device_next(AVInputFormat *d) +{ + return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT); +} + +AVInputFormat *av_input_video_device_next(AVInputFormat *d) +{ + return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT); +} + +AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d) +{ + return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT); +} + +AVOutputFormat *av_output_video_device_next(AVOutputFormat *d) +{ + return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT); +} + int avdevice_app_to_dev_control_message(struct AVFormatContext *s, enum AVAppToDevMessageType type, void *data, size_t data_size) { diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h index dd6ad9365e231..ee9462480e2cd 100644 --- a/libavdevice/avdevice.h +++ b/libavdevice/avdevice.h @@ -65,29 +65,6 @@ const char *avdevice_configuration(void); */ const char *avdevice_license(void); -/** - * Iterate over all registered output devices. - * - * @param opaque a pointer where libavdevice will store the iteration state. Must - * point to NULL to start the iteration. - * - * @return the next registered output device or NULL when the iteration is - * finished - */ -const AVOutputFormat *av_outdev_iterate(void **opaque); - -/** - * Iterate over all registered input devices. - * - * @param opaque a pointer where libavdevice will store the iteration state. Must - * point to NULL to start the iteration. - * - * @return the next registered input device or NULL when the iteration is - * finished - */ -const AVInputFormat *av_indev_iterate(void **opaque); - -#if FF_API_NEXT /** * Initialize libavdevice and register all the input and output devices. */ @@ -100,7 +77,6 @@ void avdevice_register_all(void); * if d is non-NULL, returns the next registered input audio/video device after d * or NULL if d is the last one. */ -attribute_deprecated AVInputFormat *av_input_audio_device_next(AVInputFormat *d); /** @@ -110,7 +86,6 @@ AVInputFormat *av_input_audio_device_next(AVInputFormat *d); * if d is non-NULL, returns the next registered input audio/video device after d * or NULL if d is the last one. */ -attribute_deprecated AVInputFormat *av_input_video_device_next(AVInputFormat *d); /** @@ -120,7 +95,6 @@ AVInputFormat *av_input_video_device_next(AVInputFormat *d); * if d is non-NULL, returns the next registered output audio/video device after d * or NULL if d is the last one. */ -attribute_deprecated AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d); /** @@ -130,9 +104,7 @@ AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d); * if d is non-NULL, returns the next registered output audio/video device after d * or NULL if d is the last one. */ -attribute_deprecated AVOutputFormat *av_output_video_device_next(AVOutputFormat *d); -#endif typedef struct AVDeviceRect { int x; /**< x coordinate of top left corner */ diff --git a/libavdevice/version.h b/libavdevice/version.h index 80285a2611dc4..d605427bcb4cf 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -47,8 +47,4 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_NEXT -#define FF_API_NEXT (LIBAVDEVICE_VERSION_MAJOR < 59) -#endif - #endif /* AVDEVICE_VERSION_H */ diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 9dc5ce8a767b2..e748faf4e60a1 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -25,9 +25,6 @@ #include "rdt.h" #include "url.h" #include "version.h" -#if FF_API_NEXT -#include "internal.h" -#endif /* (de)muxers */ extern AVOutputFormat ff_a64_muxer; @@ -491,7 +488,6 @@ const AVOutputFormat *av_muxer_iterate(void **opaque) { uintptr_t i = (uintptr_t)*opaque; const AVOutputFormat *f = muxer_list[i]; - if (f) *opaque = (void*)(i + 1); return f; @@ -510,9 +506,6 @@ const AVInputFormat *av_demuxer_iterate(void **opaque){ FF_DISABLE_DEPRECATION_WARNINGS static AVOnce av_format_next_init = AV_ONCE_INIT; -static const AVInputFormat * const *indev_list = NULL; -static const AVOutputFormat * const *outdev_list = NULL; - static void av_format_init_next(void) { AVOutputFormat *prevout = NULL, *out; @@ -525,61 +518,30 @@ static void av_format_init_next(void) prevout = out; } - if (outdev_list) { - for (int j = 0; (out = (AVOutputFormat*)outdev_list[j]); j++) { - if (prevout) - prevout->next = out; - prevout = out; - } - } - i = 0; while ((in = (AVInputFormat*)av_demuxer_iterate(&i))) { if (previn) previn->next = in; previn = in; } - - if (indev_list) { - for (int j = 0; (in = (AVInputFormat*)indev_list[j]); j++) { - if (previn) - previn->next = in; - previn = in; - } - } - -} - -void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]) -{ - static AVMutex avpriv_register_devices_mutex = AV_MUTEX_INITIALIZER; - ff_mutex_lock(&avpriv_register_devices_mutex); - outdev_list = o; - indev_list = i; - av_format_init_next(); - ff_mutex_unlock(&avpriv_register_devices_mutex); } AVInputFormat *av_iformat_next(const AVInputFormat *f) { ff_thread_once(&av_format_next_init, av_format_init_next); - if (f) return f->next; else - /* If there are no demuxers but input devices, then return the first input device. - * This will still return null if both there are both no demuxers or input devices. */ - return demuxer_list[0] ? (AVInputFormat*)demuxer_list[0] : (indev_list ? (AVInputFormat*)indev_list[0] : NULL); + return demuxer_list[0]; } AVOutputFormat *av_oformat_next(const AVOutputFormat *f) { ff_thread_once(&av_format_next_init, av_format_init_next); - if (f) return f->next; else - return muxer_list[0] ? (AVOutputFormat*)muxer_list[0] : (outdev_list ? (AVOutputFormat*)outdev_list[0] : NULL); + return muxer_list[0]; } void av_register_all(void) diff --git a/libavformat/format.c b/libavformat/format.c index 75951938cf054..123f5faf6c8bb 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -129,18 +129,10 @@ enum AVCodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name, AVInputFormat *av_find_input_format(const char *short_name) { AVInputFormat *fmt = NULL; -#if FF_API_NEXT -FF_DISABLE_DEPRECATION_WARNINGS - while ((fmt = av_iformat_next(fmt))) - if (av_match_name(short_name, fmt->name)) - return fmt; -FF_ENABLE_DEPRECATION_WARNINGS -#else void *i = 0; while ((fmt = av_demuxer_iterate(&i))) if (av_match_name(short_name, fmt->name)) return fmt; -#endif return NULL; } diff --git a/libavformat/internal.h b/libavformat/internal.h index a020b1b417d5c..619063097f813 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -731,11 +731,4 @@ int ff_unlock_avformat(void); */ void ff_format_set_url(AVFormatContext *s, char *url); -#if FF_API_NEXT -/** - * Register devices in deprecated format linked list. - */ -void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]); -#endif - #endif /* AVFORMAT_INTERNAL_H */ From 65452bcd6416bf94193664a45816a055d2ff15b0 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Fri, 23 Mar 2018 20:38:25 +0000 Subject: [PATCH 2310/2557] lavd: remove linked lists Signed-off-by: Josh de Kock --- configure | 23 ++++++----- libavdevice/alldevices.c | 87 ++++++++++++++++++---------------------- libavformat/allformats.c | 78 ++++++++++++++++++++++++++++++----- libavformat/avformat.h | 2 + 4 files changed, 120 insertions(+), 70 deletions(-) diff --git a/configure b/configure index b57e3d709ae75..3ae3ae3e36c86 100755 --- a/configure +++ b/configure @@ -3622,21 +3622,12 @@ for v in "$@"; do FFMPEG_CONFIGURATION="${FFMPEG_CONFIGURATION# } ${l}${r}" done -find_things(){ - thing=$1 - pattern=$2 - file=$source_path/$3 - sed -n "s/^[^#]*$pattern.*([^,]*, *\([^,]*\)\(,.*\)*).*/\1_$thing/p" "$file" -} - -OUTDEV_LIST=$(find_things outdev OUTDEV libavdevice/alldevices.c) -INDEV_LIST=$(find_things indev _IN libavdevice/alldevices.c) - find_things_extern(){ thing=$1 pattern=$2 file=$source_path/$3 - sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" "$file" + out=${4:-$thing} + sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$out/p" "$file" } find_filters_extern(){ @@ -3646,6 +3637,8 @@ find_filters_extern(){ } FILTER_LIST=$(find_filters_extern libavfilter/allfilters.c) +OUTDEV_LIST=$(find_things_extern muxer AVOutputFormat libavdevice/alldevices.c outdev) +INDEV_LIST=$(find_things_extern demuxer AVInputFormat libavdevice/alldevices.c indev) MUXER_LIST=$(find_things_extern muxer AVOutputFormat libavformat/allformats.c) DEMUXER_LIST=$(find_things_extern demuxer AVInputFormat libavformat/allformats.c) ENCODER_LIST=$(find_things_extern encoder AVCodec libavcodec/allcodecs.c) @@ -7179,6 +7172,12 @@ print_enabled_components(){ filter_list) c=$(full_filter_name $(remove_suffix _filter $c)) ;; + indev_list) + c=$(add_suffix _demuxer $(remove_suffix _indev $c)) + ;; + outdev_list) + c=$(add_suffix _muxer $(remove_suffix _outdev $c)) + ;; esac printf " &ff_%s,\n" $c >> $TMPH fi @@ -7198,6 +7197,8 @@ print_enabled_components libavcodec/parser_list.c AVCodecParser parser_list $PAR print_enabled_components libavcodec/bsf_list.c AVBitStreamFilter bitstream_filters $BSF_LIST print_enabled_components libavformat/demuxer_list.c AVInputFormat demuxer_list $DEMUXER_LIST print_enabled_components libavformat/muxer_list.c AVOutputFormat muxer_list $MUXER_LIST +print_enabled_components libavdevice/indev_list.c AVInputFormat indev_list $INDEV_LIST +print_enabled_components libavdevice/outdev_list.c AVOutputFormat outdev_list $OUTDEV_LIST print_enabled_components libavformat/protocol_list.c URLProtocol url_protocols $PROTOCOL_LIST # Settings for pkg-config files diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index b767b6a718821..ebf95f8a81fec 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -22,57 +22,48 @@ #include "libavutil/thread.h" #include "avdevice.h" -#define REGISTER_OUTDEV(X, x) \ - { \ - extern AVOutputFormat ff_##x##_muxer; \ - if (CONFIG_##X##_OUTDEV) \ - av_register_output_format(&ff_##x##_muxer); \ - } +/* devices */ +extern AVInputFormat ff_alsa_demuxer; +extern AVOutputFormat ff_alsa_muxer; +extern AVInputFormat ff_android_camera_demuxer; +extern AVInputFormat ff_avfoundation_demuxer; +extern AVInputFormat ff_bktr_demuxer; +extern AVOutputFormat ff_caca_muxer; +extern AVInputFormat ff_decklink_demuxer; +extern AVOutputFormat ff_decklink_muxer; +extern AVInputFormat ff_libndi_newtek_demuxer; +extern AVOutputFormat ff_libndi_newtek_muxer; +extern AVInputFormat ff_dshow_demuxer; +extern AVInputFormat ff_fbdev_demuxer; +extern AVOutputFormat ff_fbdev_muxer; +extern AVInputFormat ff_gdigrab_demuxer; +extern AVInputFormat ff_iec61883_demuxer; +extern AVInputFormat ff_jack_demuxer; +extern AVInputFormat ff_kmsgrab_demuxer; +extern AVInputFormat ff_lavfi_demuxer; +extern AVInputFormat ff_openal_demuxer; +extern AVOutputFormat ff_opengl_muxer; +extern AVInputFormat ff_oss_demuxer; +extern AVOutputFormat ff_oss_muxer; +extern AVInputFormat ff_pulse_demuxer; +extern AVOutputFormat ff_pulse_muxer; +extern AVOutputFormat ff_sdl2_muxer; +extern AVInputFormat ff_sndio_demuxer; +extern AVOutputFormat ff_sndio_muxer; +extern AVInputFormat ff_v4l2_demuxer; +extern AVOutputFormat ff_v4l2_muxer; +extern AVInputFormat ff_vfwcap_demuxer; +extern AVInputFormat ff_xcbgrab_demuxer; +extern AVOutputFormat ff_xv_muxer; -#define REGISTER_INDEV(X, x) \ - { \ - extern AVInputFormat ff_##x##_demuxer; \ - if (CONFIG_##X##_INDEV) \ - av_register_input_format(&ff_##x##_demuxer); \ - } +/* external libraries */ +extern AVInputFormat ff_libcdio_demuxer; +extern AVInputFormat ff_libdc1394_demuxer; -#define REGISTER_INOUTDEV(X, x) REGISTER_OUTDEV(X, x); REGISTER_INDEV(X, x) - -static void register_all(void) -{ - /* devices */ - REGISTER_INOUTDEV(ALSA, alsa); - REGISTER_INDEV (AVFOUNDATION, avfoundation); - REGISTER_INDEV (BKTR, bktr); - REGISTER_OUTDEV (CACA, caca); - REGISTER_INOUTDEV(DECKLINK, decklink); - REGISTER_INOUTDEV(LIBNDI_NEWTEK, libndi_newtek); - REGISTER_INDEV (DSHOW, dshow); - REGISTER_INOUTDEV(FBDEV, fbdev); - REGISTER_INDEV (GDIGRAB, gdigrab); - REGISTER_INDEV (IEC61883, iec61883); - REGISTER_INDEV (JACK, jack); - REGISTER_INDEV (KMSGRAB, kmsgrab); - REGISTER_INDEV (LAVFI, lavfi); - REGISTER_INDEV (OPENAL, openal); - REGISTER_OUTDEV (OPENGL, opengl); - REGISTER_INOUTDEV(OSS, oss); - REGISTER_INOUTDEV(PULSE, pulse); - REGISTER_OUTDEV (SDL2, sdl2); - REGISTER_INOUTDEV(SNDIO, sndio); - REGISTER_INOUTDEV(V4L2, v4l2); - REGISTER_INDEV (VFWCAP, vfwcap); - REGISTER_INDEV (XCBGRAB, xcbgrab); - REGISTER_OUTDEV (XV, xv); - - /* external libraries */ - REGISTER_INDEV (LIBCDIO, libcdio); - REGISTER_INDEV (LIBDC1394, libdc1394); -} +#include "libavdevice/outdev_list.c" +#include "libavdevice/indev_list.c" void avdevice_register_all(void) { - static AVOnce control = AV_ONCE_INIT; - - ff_thread_once(&control, register_all); + avpriv_register_devices(outdev_list, indev_list); } diff --git a/libavformat/allformats.c b/libavformat/allformats.c index e748faf4e60a1..2a20548c95e6f 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -484,24 +484,45 @@ extern AVInputFormat ff_libopenmpt_demuxer; #include "libavformat/muxer_list.c" #include "libavformat/demuxer_list.c" +static const AVInputFormat * const *indev_list = NULL; +static const AVOutputFormat * const *outdev_list = NULL; + const AVOutputFormat *av_muxer_iterate(void **opaque) { + static const uintptr_t size = sizeof(muxer_list)/sizeof(muxer_list[0]) - 1; uintptr_t i = (uintptr_t)*opaque; - const AVOutputFormat *f = muxer_list[i]; + const AVOutputFormat *f = NULL; + + if (i < size - 1) { + f = muxer_list[i]; + } else if (indev_list) { + f = outdev_list[i - size]; + } + if (f) *opaque = (void*)(i + 1); return f; } -const AVInputFormat *av_demuxer_iterate(void **opaque){ +const AVInputFormat *av_demuxer_iterate(void **opaque) +{ + static const uintptr_t size = sizeof(demuxer_list)/sizeof(demuxer_list[0]) - 1; uintptr_t i = (uintptr_t)*opaque; - const AVInputFormat *f = demuxer_list[i]; + const AVInputFormat *f = NULL; + + if (i < size) { + f = demuxer_list[i]; + } else if (outdev_list) { + f = indev_list[i - size]; + } if (f) *opaque = (void*)(i + 1); return f; } +static AVMutex avpriv_register_devices_mutex = AV_MUTEX_INITIALIZER; + #if FF_API_NEXT FF_DISABLE_DEPRECATION_WARNINGS static AVOnce av_format_next_init = AV_ONCE_INIT; @@ -510,38 +531,62 @@ static void av_format_init_next(void) { AVOutputFormat *prevout = NULL, *out; AVInputFormat *previn = NULL, *in; - void *i = 0; - while ((out = (AVOutputFormat*)av_muxer_iterate(&i))) { + ff_mutex_lock(&avpriv_register_devices_mutex); + + for (int i = 0; (out = (AVOutputFormat*)muxer_list[i]); i++) { if (prevout) prevout->next = out; prevout = out; } - i = 0; - while ((in = (AVInputFormat*)av_demuxer_iterate(&i))) { + if (outdev_list) { + for (int i = 0; (out = (AVOutputFormat*)outdev_list[i]); i++) { + if (prevout) + prevout->next = out; + prevout = out; + } + } + + for (int i = 0; (in = (AVInputFormat*)demuxer_list[i]); i++) { if (previn) previn->next = in; previn = in; } + + if (indev_list) { + for (int i = 0; (in = (AVInputFormat*)indev_list[i]); i++) { + if (previn) + previn->next = in; + previn = in; + } + } + + ff_mutex_unlock(&avpriv_register_devices_mutex); } AVInputFormat *av_iformat_next(const AVInputFormat *f) { ff_thread_once(&av_format_next_init, av_format_init_next); + if (f) return f->next; - else - return demuxer_list[0]; + else { + void *opaque = NULL; + return (AVInputFormat *)av_demuxer_iterate(&opaque); + } } AVOutputFormat *av_oformat_next(const AVOutputFormat *f) { ff_thread_once(&av_format_next_init, av_format_init_next); + if (f) return f->next; - else - return muxer_list[0]; + else { + void *opaque = NULL; + return (AVOutputFormat *)av_muxer_iterate(&opaque); + } } void av_register_all(void) @@ -560,3 +605,14 @@ void av_register_output_format(AVOutputFormat *format) } FF_ENABLE_DEPRECATION_WARNINGS #endif + +void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]) +{ + ff_mutex_lock(&avpriv_register_devices_mutex); + outdev_list = o; + indev_list = i; + ff_mutex_unlock(&avpriv_register_devices_mutex); +#if FF_API_NEXT + av_format_init_next(); +#endif +} diff --git a/libavformat/avformat.h b/libavformat/avformat.h index a2fe7c6bb2caf..ec4e5f45f5133 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -3060,6 +3060,8 @@ int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, */ AVRational av_stream_get_codec_timebase(const AVStream *st); + +void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]); /** * @} */ From 22381906f3fd414d5c87593960903a1bf7797ee2 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Fri, 23 Mar 2018 20:38:32 +0000 Subject: [PATCH 2311/2557] cmdutils: use new APIs Signed-off-by: Josh de Kock --- fftools/cmdutils.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index c0ddf0b287a9f..a6cf002fd0aa6 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1259,8 +1259,10 @@ static int is_device(const AVClass *avclass) static int show_formats_devices(void *optctx, const char *opt, const char *arg, int device_only, int muxdemuxers) { - AVInputFormat *ifmt = NULL; - AVOutputFormat *ofmt = NULL; + void *ifmt_opaque = NULL; + const AVInputFormat *ifmt = NULL; + void *ofmt_opaque = NULL; + const AVOutputFormat *ofmt = NULL; const char *last_name; int is_dev; @@ -1276,7 +1278,8 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg, const char *long_name = NULL; if (muxdemuxers !=SHOW_DEMUXERS) { - while ((ofmt = av_oformat_next(ofmt))) { + ifmt_opaque = NULL; + while ((ofmt = av_muxer_iterate(&ofmt_opaque))) { is_dev = is_device(ofmt->priv_class); if (!is_dev && device_only) continue; @@ -1289,7 +1292,8 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg, } } if (muxdemuxers != SHOW_MUXERS) { - while ((ifmt = av_iformat_next(ifmt))) { + ofmt_opaque = NULL; + while ((ifmt = av_demuxer_iterate(&ifmt_opaque))) { is_dev = is_device(ifmt->priv_class); if (!is_dev && device_only) continue; @@ -1629,6 +1633,7 @@ int show_filters(void *optctx, const char *opt, const char *arg) #if CONFIG_AVFILTER const AVFilter *filter = NULL; char descr[64], *descr_cur; + void *opaque = NULL; int i, j; const AVFilterPad *pad; @@ -1640,7 +1645,7 @@ int show_filters(void *optctx, const char *opt, const char *arg) " V = Video input/output\n" " N = Dynamic number and/or type of input/output\n" " | = Source or sink filter\n"); - while ((filter = avfilter_next(filter))) { + while ((filter = av_filter_iterate(&opaque))) { descr_cur = descr; for (i = 0; i < 2; i++) { if (i) { From 8247e0304ed5fa862e8ea30867ebc6e0b30d2fab Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 1 Apr 2018 02:34:28 +0200 Subject: [PATCH 2312/2557] configure: fix build regression since 8f1382f80e0d4184c54c14afdda6482f050fbba7 --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 3ae3ae3e36c86..08d6fc59837fc 100755 --- a/configure +++ b/configure @@ -7182,7 +7182,7 @@ print_enabled_components(){ printf " &ff_%s,\n" $c >> $TMPH fi done - if [ "$name" == "filter_list" ]; then + if [ "$name" = "filter_list" ]; then for c in asrc_abuffer vsrc_buffer asink_abuffer vsink_buffer; do printf " &ff_%s,\n" $c >> $TMPH done From 8c980b1c92bbc98ed12b6a43269572aaacf31426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Thu, 29 Mar 2018 15:59:33 +0300 Subject: [PATCH 2313/2557] avformat/mov: parse multiple iTunes cover images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Multiple cover images are supported by having multiple data atoms inside the covr atom. AtomicParsley and mutagen amongst others support and document this construct. Signed-off-by: Timo Teräs Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index cb6f3a45de218..e7c32e6148062 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -412,7 +412,11 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) int ret = mov_read_covr(c, pb, data_type, str_size); if (ret < 0) { av_log(c->fc, AV_LOG_ERROR, "Error parsing cover art.\n"); + return ret; } + atom.size -= str_size; + if (atom.size > 8) + goto retry; return ret; } else if (!key && c->found_hdlr_mdta && c->meta_keys) { uint32_t index = AV_RB32(&atom.type); From 47b7c68ae54560e2308bdb6be4fb076c73b93081 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 31 Mar 2018 03:10:43 +0200 Subject: [PATCH 2314/2557] avcodec/utvideodec: Set pro flag based on fourcc This avoids mixing 8bit variants with pro and 10bit with non pro mode. Fixes: out of array read Fixes: poc_03_30.avi Found-by: GwanYeong Kim Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer --- libavcodec/utvideodec.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 086129d094755..82cb038ccd9f8 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -949,14 +949,17 @@ static av_cold int decode_init(AVCodecContext *avctx) break; case MKTAG('U', 'Q', 'Y', '2'): c->planes = 3; + c->pro = 1; avctx->pix_fmt = AV_PIX_FMT_YUV422P10; break; case MKTAG('U', 'Q', 'R', 'G'): c->planes = 3; + c->pro = 1; avctx->pix_fmt = AV_PIX_FMT_GBRP10; break; case MKTAG('U', 'Q', 'R', 'A'): c->planes = 4; + c->pro = 1; avctx->pix_fmt = AV_PIX_FMT_GBRAP10; break; case MKTAG('U', 'L', 'H', '0'): @@ -1031,7 +1034,7 @@ static av_cold int decode_init(AVCodecContext *avctx) if (c->compression != 2) avpriv_request_sample(avctx, "Unknown compression type"); c->slices = avctx->extradata[9] + 1; - } else if (avctx->extradata_size >= 16) { + } else if (!c->pro && avctx->extradata_size >= 16) { av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", avctx->extradata[3], avctx->extradata[2], avctx->extradata[1], avctx->extradata[0]); @@ -1046,14 +1049,13 @@ static av_cold int decode_init(AVCodecContext *avctx) c->slices = (c->flags >> 24) + 1; c->compression = c->flags & 1; c->interlaced = c->flags & 0x800; - } else if (avctx->extradata_size == 8) { + } else if (c->pro && avctx->extradata_size == 8) { av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", avctx->extradata[3], avctx->extradata[2], avctx->extradata[1], avctx->extradata[0]); av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", AV_RB32(avctx->extradata + 4)); c->interlaced = 0; - c->pro = 1; c->frame_info_size = 4; } else { av_log(avctx, AV_LOG_ERROR, From 35eeff30caf34df835206f1c12bcf4b7c2bd6758 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 30 Mar 2018 02:16:31 +0200 Subject: [PATCH 2315/2557] avfilter/vf_signature: use av_strlcpy() Fixes: out of array access Found-by: Kira Signed-off-by: Michael Niedermayer --- libavfilter/vf_signature.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_signature.c b/libavfilter/vf_signature.c index f0078ba1a6eb1..d07b213f3125a 100644 --- a/libavfilter/vf_signature.c +++ b/libavfilter/vf_signature.c @@ -576,7 +576,8 @@ static int export(AVFilterContext *ctx, StreamContext *sc, int input) /* error already handled */ av_assert0(av_get_frame_filename(filename, sizeof(filename), sic->filename, input) == 0); } else { - strcpy(filename, sic->filename); + if (av_strlcpy(filename, sic->filename, sizeof(filename)) >= sizeof(filename)) + return AVERROR(EINVAL); } if (sic->format == FORMAT_XML) { return xml_export(ctx, sc, filename); From be502ec6cde004e1fa05643282939bf3a1507922 Mon Sep 17 00:00:00 2001 From: enctac Date: Mon, 26 Mar 2018 01:44:49 +0900 Subject: [PATCH 2316/2557] vf_libvmaf: Fix memory leak Fixes ticket #6967 --- libavfilter/vf_libvmaf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavfilter/vf_libvmaf.c b/libavfilter/vf_libvmaf.c index dfe474c40cb2a..42c6b66b69a53 100644 --- a/libavfilter/vf_libvmaf.c +++ b/libavfilter/vf_libvmaf.c @@ -130,6 +130,8 @@ FRAMESYNC_DEFINE_CLASS(libvmaf, LIBVMAFContext, fs); \ ret = !s->frame_set; \ \ + av_frame_unref(s->gref); \ + av_frame_unref(s->gmain); \ s->frame_set = 0; \ \ pthread_cond_signal(&s->cond); \ From e760c12aeef608aa8b416664687b9aca3a2c6f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Sat, 31 Mar 2018 19:39:07 +0300 Subject: [PATCH 2317/2557] ffmpeg: prevent premature EOF in sub2video with nullptr AVSubtitles With certain types of input and the filter chain getting re-initialized or re-configured, multiple nullptr AVSubtitles can get pushed into sub2video_update() in a row from sub2video_heartbeat. This causes end_pts, and on the next round pts, to become INT64_MAX, latter of which signals EOF in framesync, leading to complete loss of subtitles from that point on. Thus, check that the sub2video.end_pts is smaller than INT64_MAX in a similar fashion to sub2video_flush before sending out the nullptr AVSubtitle. This keeps premature EOFs from happening in framesync and the subtitle overlay is kept past the filter chain re-initializations/configurations. --- fftools/ffmpeg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 4724f62fff450..d3bc382dec11a 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -285,7 +285,8 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts) /* do not send the heartbeat frame if the subtitle is already ahead */ if (pts2 <= ist2->sub2video.last_pts) continue; - if (pts2 >= ist2->sub2video.end_pts || !ist2->sub2video.frame->data[0]) + if (pts2 >= ist2->sub2video.end_pts || + (!ist2->sub2video.frame->data[0] && ist2->sub2video.end_pts < INT64_MAX)) sub2video_update(ist2, NULL); for (j = 0, nb_reqs = 0; j < ist2->nb_filters; j++) nb_reqs += av_buffersrc_get_nb_failed_requests(ist2->filters[j]->filter); From a1b91b0cc28ac9d7ca77f21a3010233edeee457c Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 31 Mar 2018 23:57:09 +0100 Subject: [PATCH 2318/2557] lavc: prefer the mp3float decoder to the mp3 decoder On modern x86 systems its around 2x faster. For systems without FPUs it'll be slower, but our policy is to prefer floating point implementations and to let users decide what's best (or just not compile them on systems without FPUs). Signed-off-by: Rostislav Pehlivanov --- libavcodec/allcodecs.c | 6 ++--- tests/fate/gapless.mak | 2 +- tests/ref/fate/exif-image-embedded | 42 +++++++++++++++--------------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 059445000da6e..4d4ef530e4f3b 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -432,12 +432,12 @@ extern AVCodec ff_mp2_encoder; extern AVCodec ff_mp2_decoder; extern AVCodec ff_mp2float_decoder; extern AVCodec ff_mp2fixed_encoder; -extern AVCodec ff_mp3_decoder; extern AVCodec ff_mp3float_decoder; -extern AVCodec ff_mp3adu_decoder; +extern AVCodec ff_mp3_decoder; extern AVCodec ff_mp3adufloat_decoder; -extern AVCodec ff_mp3on4_decoder; +extern AVCodec ff_mp3adu_decoder; extern AVCodec ff_mp3on4float_decoder; +extern AVCodec ff_mp3on4_decoder; extern AVCodec ff_mpc7_decoder; extern AVCodec ff_mpc8_decoder; extern AVCodec ff_nellymoser_encoder; diff --git a/tests/fate/gapless.mak b/tests/fate/gapless.mak index 0253b9ec61ee5..91fddb4130a2f 100644 --- a/tests/fate/gapless.mak +++ b/tests/fate/gapless.mak @@ -1,5 +1,5 @@ FATE_GAPLESS-$(CONFIG_MP3_DEMUXER) += fate-gapless-mp3 -fate-gapless-mp3: CMD = gapless $(TARGET_SAMPLES)/gapless/gapless.mp3 +fate-gapless-mp3: CMD = gapless $(TARGET_SAMPLES)/gapless/gapless.mp3 "-c:a mp3" FATE_GAPLESS-$(CONFIG_MP3_DEMUXER) += fate-audiomatch-square-mp3 fate-audiomatch-square-mp3: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/square3.mp3 $(TARGET_SAMPLES)/audiomatch/square3.wav diff --git a/tests/ref/fate/exif-image-embedded b/tests/ref/fate/exif-image-embedded index 0b640767a88e3..392c145efb9e7 100644 --- a/tests/ref/fate/exif-image-embedded +++ b/tests/ref/fate/exif-image-embedded @@ -50,7 +50,7 @@ pkt_duration=15040 pkt_duration_time=0.001066 pkt_pos=16292 pkt_size=417 -sample_fmt=s16p +sample_fmt=fltp nb_samples=47 channels=2 channel_layout=stereo @@ -69,7 +69,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=16709 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -88,7 +88,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=17127 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -107,7 +107,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=17545 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -126,7 +126,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=17963 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -145,7 +145,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=18381 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -164,7 +164,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=18799 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -183,7 +183,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=19217 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -202,7 +202,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=19635 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -221,7 +221,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=20053 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -240,7 +240,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=20471 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -259,7 +259,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=20889 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -278,7 +278,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=21307 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -297,7 +297,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=21725 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -316,7 +316,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=22143 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -335,7 +335,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=22561 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -354,7 +354,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=22979 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -373,7 +373,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=23397 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -392,7 +392,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=23815 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -411,7 +411,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=24233 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo @@ -430,7 +430,7 @@ pkt_duration=368640 pkt_duration_time=0.026122 pkt_pos=24651 pkt_size=418 -sample_fmt=s16p +sample_fmt=fltp nb_samples=1152 channels=2 channel_layout=stereo From 4152413dde1cf851c4556459e3e1b3a5669f3a5e Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 31 Mar 2018 15:50:19 +0200 Subject: [PATCH 2319/2557] avfilter/showvolume : move clear picture part to a func and use it if fade == 0. --- libavfilter/avf_showvolume.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index 267020e163f74..92dfc2443572d 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -245,13 +245,24 @@ static void drawtext(AVFrame *pic, int x, int y, const char *txt, int o) } } +static void clear_picture(ShowVolumeContext *s, AVFilterLink *outlink) { + int i, j; + const uint32_t bg = (uint32_t)(s->bgopacity * 255) << 24; + + for (i = 0; i < outlink->h; i++) { + uint32_t *dst = (uint32_t *)(s->out->data[0] + i * s->out->linesize[0]); + for (j = 0; j < outlink->w; j++) + AV_WN32A(dst + j, bg); + } +} + static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; ShowVolumeContext *s = ctx->priv; const int step = s->step; - int c, i, j, k; + int c, j, k; AVFrame *out; if (!s->out || s->out->width != outlink->w || @@ -262,18 +273,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) av_frame_free(&insamples); return AVERROR(ENOMEM); } - - for (i = 0; i < outlink->h; i++) { - uint32_t *dst = (uint32_t *)(s->out->data[0] + i * s->out->linesize[0]); - const uint32_t bg = (uint32_t)(s->bgopacity * 255) << 24; - - for (j = 0; j < outlink->w; j++) - AV_WN32A(dst + j, bg); - } + clear_picture(s, outlink); } s->out->pts = insamples->pts; - if (s->f < 1.) { + if ((s->f < 1.) && (s->f > 0.)) { for (j = 0; j < outlink->h; j++) { uint8_t *dst = s->out->data[0] + j * s->out->linesize[0]; const uint32_t alpha = s->bgopacity * 255; @@ -285,6 +289,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) dst[k * 4 + 3] = FFMAX(dst[k * 4 + 3] * s->f, alpha); } } + } else if (s->f == 0.) { + clear_picture(s, outlink); } if (s->orientation) { /* vertical */ From e4cfb2c669993f01011e940de30e5da11a191b01 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 31 Mar 2018 15:50:53 +0200 Subject: [PATCH 2320/2557] avfilter/showvolume : move width test for draw volume to the start of the loop --- libavfilter/avf_showvolume.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index 92dfc2443572d..4f31cebc7b6d9 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -358,18 +358,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) return AVERROR(ENOMEM); av_frame_make_writable(out); - for (c = 0; c < inlink->channels && s->draw_volume; c++) { + for (c = 0; c < inlink->channels && s->h >= 8 && s->draw_volume; c++) { char buf[16]; if (s->orientation) { - if (s->h >= 8) { snprintf(buf, sizeof(buf), "%.2f", s->values[c * VAR_VARS_NB + VAR_VOLUME]); drawtext(out, c * (s->h + s->b) + (s->h - 8) / 2, 2, buf, 1); - } } else { - if (s->h >= 8) { + snprintf(buf, sizeof(buf), "%.2f", s->values[c * VAR_VARS_NB + VAR_VOLUME]); drawtext(out, FFMAX(0, s->w - 8 * (int)strlen(buf)), c * (s->h + s->b) + (s->h - 8) / 2, buf, 0); - } } } From 78b6887da3b926db7df64807ef6f3026136921fc Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 31 Mar 2018 15:51:18 +0200 Subject: [PATCH 2321/2557] avfilter/showvolume : indent after prev commit and add comment --- libavfilter/avf_showvolume.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index 4f31cebc7b6d9..7fe39168555b6 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -358,15 +358,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) return AVERROR(ENOMEM); av_frame_make_writable(out); + /* draw volume level */ for (c = 0; c < inlink->channels && s->h >= 8 && s->draw_volume; c++) { char buf[16]; - if (s->orientation) { - snprintf(buf, sizeof(buf), "%.2f", s->values[c * VAR_VARS_NB + VAR_VOLUME]); - drawtext(out, c * (s->h + s->b) + (s->h - 8) / 2, 2, buf, 1); - } else { - snprintf(buf, sizeof(buf), "%.2f", s->values[c * VAR_VARS_NB + VAR_VOLUME]); - drawtext(out, FFMAX(0, s->w - 8 * (int)strlen(buf)), c * (s->h + s->b) + (s->h - 8) / 2, buf, 0); + if (s->orientation) { /* vertical */ + snprintf(buf, sizeof(buf), "%.2f", s->values[c * VAR_VARS_NB + VAR_VOLUME]); + drawtext(out, c * (s->h + s->b) + (s->h - 8) / 2, 2, buf, 1); + } else { /* horizontal */ + snprintf(buf, sizeof(buf), "%.2f", s->values[c * VAR_VARS_NB + VAR_VOLUME]); + drawtext(out, FFMAX(0, s->w - 8 * (int)strlen(buf)), c * (s->h + s->b) + (s->h - 8) / 2, buf, 0); } } From 354b26a3945eadd4ed8fcd801dfefad2566241de Mon Sep 17 00:00:00 2001 From: heimdallr Date: Sat, 31 Mar 2018 19:37:23 +0700 Subject: [PATCH 2322/2557] avcodec/imgconvert: Fix loss mask bug in avcodec_find_best_pix_fmt_of_list() example: AVPixelFormat pixFmts[] = { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA }; int loss = 0; AVPixelFormat best = avcodec_find_best_pix_fmt_of_list(pixFmts, AV_PIX_FMT_BGRA, 1, &loss); best is AV_PIX_FMT_RGB24. But AV_PIX_FMT_RGBA is better. Signed-off-by: Michael Niedermayer --- libavcodec/imgconvert.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c index 1547f18966e09..7b0005b308fd1 100644 --- a/libavcodec/imgconvert.c +++ b/libavcodec/imgconvert.c @@ -69,10 +69,14 @@ enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *p int i; enum AVPixelFormat best = AV_PIX_FMT_NONE; + int loss; - for(i=0; pix_fmt_list[i] != AV_PIX_FMT_NONE; i++) - best = avcodec_find_best_pix_fmt_of_2(best, pix_fmt_list[i], src_pix_fmt, has_alpha, loss_ptr); + for (i=0; pix_fmt_list[i] != AV_PIX_FMT_NONE; i++) { + loss = *loss_ptr; + best = avcodec_find_best_pix_fmt_of_2(best, pix_fmt_list[i], src_pix_fmt, has_alpha, &loss); + } + *loss_ptr = loss; return best; } From 8dff6c2844965473ec37a32c136887efe5e622b9 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 29 Mar 2018 13:54:51 +0200 Subject: [PATCH 2323/2557] avfilter/af_amix: add weights option Signed-off-by: Paul B Mahol --- doc/filters.texi | 3 +++ libavfilter/af_amix.c | 55 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index bf2b94e240924..7538ab3273664 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1350,6 +1350,9 @@ The duration of the first input. The transition time, in seconds, for volume renormalization when an input stream ends. The default value is 2 seconds. +@item weights +Specify weight of each input audio stream as sequence. +Each weight is separated by space. By default all inputs have same weight. @end table @section anequalizer diff --git a/libavfilter/af_amix.c b/libavfilter/af_amix.c index ec764375c0b6a..46f1bf63d790d 100644 --- a/libavfilter/af_amix.c +++ b/libavfilter/af_amix.c @@ -162,6 +162,7 @@ typedef struct MixContext { int active_inputs; /**< number of input currently active */ int duration_mode; /**< mode for determining duration */ float dropout_transition; /**< transition time when an input drops out */ + char *weights_str; /**< string for custom weights for every input */ int nb_channels; /**< number of channels */ int sample_rate; /**< sample rate */ @@ -169,7 +170,9 @@ typedef struct MixContext { AVAudioFifo **fifos; /**< audio fifo for each input */ uint8_t *input_state; /**< current state of each input */ float *input_scale; /**< mixing scale factor for each input */ - float scale_norm; /**< normalization factor for all inputs */ + float *weights; /**< custom weights for every input */ + float weight_sum; /**< sum of custom weights for every input */ + float *scale_norm; /**< normalization factor for every input */ int64_t next_pts; /**< calculated pts for next output frame */ FrameList *frame_list; /**< list of frame info for the first input */ } MixContext; @@ -188,6 +191,8 @@ static const AVOption amix_options[] = { { "dropout_transition", "Transition time, in seconds, for volume " "renormalization when an input stream ends.", OFFSET(dropout_transition), AV_OPT_TYPE_FLOAT, { .dbl = 2.0 }, 0, INT_MAX, A|F }, + { "weights", "Set weight for each input.", + OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, A|F }, { NULL } }; @@ -202,16 +207,26 @@ AVFILTER_DEFINE_CLASS(amix); */ static void calculate_scales(MixContext *s, int nb_samples) { + float weight_sum = 0.f; int i; - if (s->scale_norm > s->active_inputs) { - s->scale_norm -= nb_samples / (s->dropout_transition * s->sample_rate); - s->scale_norm = FFMAX(s->scale_norm, s->active_inputs); + for (i = 0; i < s->nb_inputs; i++) + if (s->input_state[i] & INPUT_ON) + weight_sum += s->weights[i]; + + for (i = 0; i < s->nb_inputs; i++) { + if (s->input_state[i] & INPUT_ON) { + if (s->scale_norm[i] > weight_sum / s->weights[i]) { + s->scale_norm[i] -= ((s->weight_sum / s->weights[i]) / s->nb_inputs) * + nb_samples / (s->dropout_transition * s->sample_rate); + s->scale_norm[i] = FFMAX(s->scale_norm[i], weight_sum / s->weights[i]); + } + } } for (i = 0; i < s->nb_inputs; i++) { if (s->input_state[i] & INPUT_ON) - s->input_scale[i] = 1.0f / s->scale_norm; + s->input_scale[i] = 1.0f / s->scale_norm[i]; else s->input_scale[i] = 0.0f; } @@ -251,9 +266,11 @@ static int config_output(AVFilterLink *outlink) s->active_inputs = s->nb_inputs; s->input_scale = av_mallocz_array(s->nb_inputs, sizeof(*s->input_scale)); - if (!s->input_scale) + s->scale_norm = av_mallocz_array(s->nb_inputs, sizeof(*s->scale_norm)); + if (!s->input_scale || !s->scale_norm) return AVERROR(ENOMEM); - s->scale_norm = s->active_inputs; + for (i = 0; i < s->nb_inputs; i++) + s->scale_norm[i] = s->weight_sum / s->weights[i]; calculate_scales(s, 0); av_get_channel_layout_string(buf, sizeof(buf), -1, outlink->channel_layout); @@ -487,6 +504,8 @@ static int activate(AVFilterContext *ctx) static av_cold int init(AVFilterContext *ctx) { MixContext *s = ctx->priv; + char *p, *arg, *saveptr = NULL; + float last_weight = 1.f; int i, ret; for (i = 0; i < s->nb_inputs; i++) { @@ -507,6 +526,26 @@ static av_cold int init(AVFilterContext *ctx) if (!s->fdsp) return AVERROR(ENOMEM); + s->weights = av_mallocz_array(s->nb_inputs, sizeof(*s->weights)); + if (!s->weights) + return AVERROR(ENOMEM); + + p = s->weights_str; + for (i = 0; i < s->nb_inputs; i++) { + if (!(arg = av_strtok(p, " ", &saveptr))) + break; + + p = NULL; + sscanf(arg, "%f", &last_weight); + s->weights[i] = last_weight; + s->weight_sum += last_weight; + } + + for (; i < s->nb_inputs; i++) { + s->weights[i] = last_weight; + s->weight_sum += last_weight; + } + return 0; } @@ -524,6 +563,8 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->frame_list); av_freep(&s->input_state); av_freep(&s->input_scale); + av_freep(&s->scale_norm); + av_freep(&s->weights); av_freep(&s->fdsp); for (i = 0; i < ctx->nb_inputs; i++) From 52e97814a18f62e4be7cc5d509ff9025f23ef2be Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 30 Mar 2018 16:06:55 +0200 Subject: [PATCH 2324/2557] avformat/mpeg: fix PCM-DVD mis-detection as MLP Fixes #6563. Signed-off-by: Paul B Mahol --- libavformat/mpeg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index abdc6a937cb9e..69d4a9d8ac5f2 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -568,7 +568,7 @@ static int mpegps_read_packet(AVFormatContext *s, codec_id = AV_CODEC_ID_DTS; } else if (startcode >= 0xa0 && startcode <= 0xaf) { type = AVMEDIA_TYPE_AUDIO; - if (lpcm_header_len == 6 || startcode == 0xa1) { + if (lpcm_header_len >= 6 && startcode == 0xa1) { codec_id = AV_CODEC_ID_MLP; } else { codec_id = AV_CODEC_ID_PCM_DVD; From 7643e27528047f02dd1a2ae61332308d2e22196d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 30 Mar 2018 18:44:34 +0200 Subject: [PATCH 2325/2557] avformat/mpeg: fix detection and demuxing of raw AC3 in mpegps Fixes #4889. Signed-off-by: Paul B Mahol --- libavformat/mpeg.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index 69d4a9d8ac5f2..e3dd404677d4c 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -20,6 +20,7 @@ */ #include "avformat.h" +#include "avio_internal.h" #include "internal.h" #include "mpeg.h" @@ -128,6 +129,7 @@ typedef struct MpegDemuxContext { int sofdec; int dvd; int imkh_cctv; + int raw_ac3; #if CONFIG_VOBSUB_DEMUXER AVFormatContext *sub_ctx; FFDemuxSubtitlesQueue q[32]; @@ -442,8 +444,21 @@ static int mpegps_read_pes_header(AVFormatContext *s, } if (startcode == PRIVATE_STREAM_1) { + int ret = ffio_ensure_seekback(s->pb, 2); + + if (ret < 0) + return ret; + startcode = avio_r8(s->pb); - len--; + if (startcode == 0x0b && avio_r8(s->pb) == 0x77) { + startcode = 0x80; + m->raw_ac3 = 1; + avio_skip(s->pb, -2); + } else { + m->raw_ac3 = 0; + avio_skip(s->pb, -1); + len--; + } } if (len < 0) goto error_redo; @@ -486,14 +501,16 @@ static int mpegps_read_packet(AVFormatContext *s, if (len < 4) goto skip; - /* audio: skip header */ - avio_r8(s->pb); - lpcm_header_len = avio_rb16(s->pb); - len -= 3; - if (startcode >= 0xb0 && startcode <= 0xbf) { - /* MLP/TrueHD audio has a 4-byte header */ + if (!m->raw_ac3) { + /* audio: skip header */ avio_r8(s->pb); - len--; + lpcm_header_len = avio_rb16(s->pb); + len -= 3; + if (startcode >= 0xb0 && startcode <= 0xbf) { + /* MLP/TrueHD audio has a 4-byte header */ + avio_r8(s->pb); + len--; + } } } From 1f7705e5b16d83d2ac4bfc48c7b8d6a34bfef20a Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 1 Apr 2018 20:58:48 +0200 Subject: [PATCH 2326/2557] avformat/mpeg: fix logic failure Signed-off-by: Paul B Mahol --- libavformat/mpeg.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index e3dd404677d4c..0c507e9f01f46 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -450,13 +450,14 @@ static int mpegps_read_pes_header(AVFormatContext *s, return ret; startcode = avio_r8(s->pb); - if (startcode == 0x0b && avio_r8(s->pb) == 0x77) { - startcode = 0x80; - m->raw_ac3 = 1; - avio_skip(s->pb, -2); + m->raw_ac3 = 0; + if (startcode == 0x0b) { + if (avio_r8(s->pb) == 0x77) { + startcode = 0x80; + m->raw_ac3 = 1; + avio_skip(s->pb, -2); + } } else { - m->raw_ac3 = 0; - avio_skip(s->pb, -1); len--; } } From 0995641202741e56874d468fbdacf2f8728535a2 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 1 Apr 2018 21:08:16 +0200 Subject: [PATCH 2327/2557] avformat/mpeg: add missing check Signed-off-by: Paul B Mahol --- libavformat/mpeg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index 0c507e9f01f46..8ae4740920b8a 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -456,6 +456,8 @@ static int mpegps_read_pes_header(AVFormatContext *s, startcode = 0x80; m->raw_ac3 = 1; avio_skip(s->pb, -2); + } else { + avio_skip(s->pb, -1); } } else { len--; From 42d26145e9561d0e7cc700b79be9e34caf449ecc Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Sun, 1 Apr 2018 00:20:59 +0100 Subject: [PATCH 2328/2557] lavf: move avpriv function definition to internal.h Signed-off-by: Josh de Kock --- libavdevice/alldevices.c | 1 + libavformat/allformats.c | 1 + libavformat/avformat.h | 2 -- libavformat/internal.h | 1 + 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index ebf95f8a81fec..adde749ce1302 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -20,6 +20,7 @@ #include "config.h" #include "libavutil/thread.h" +#include "libavformat/internal.h" #include "avdevice.h" /* devices */ diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 2a20548c95e6f..7ade03fc5d416 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -20,6 +20,7 @@ */ #include "libavutil/thread.h" +#include "libavformat/internal.h" #include "avformat.h" #include "rtp.h" #include "rdt.h" diff --git a/libavformat/avformat.h b/libavformat/avformat.h index ec4e5f45f5133..a2fe7c6bb2caf 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -3060,8 +3060,6 @@ int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, */ AVRational av_stream_get_codec_timebase(const AVStream *st); - -void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]); /** * @} */ diff --git a/libavformat/internal.h b/libavformat/internal.h index 619063097f813..23eb7e8a7c516 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -731,4 +731,5 @@ int ff_unlock_avformat(void); */ void ff_format_set_url(AVFormatContext *s, char *url); +void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]); #endif /* AVFORMAT_INTERNAL_H */ From db85d657faabf8e5ce7690ddbe6325ec430c61e7 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Sun, 1 Apr 2018 03:07:11 +0100 Subject: [PATCH 2329/2557] lavf/allformats: remove left-over index decrement Signed-off-by: Josh de Kock --- libavformat/allformats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 7ade03fc5d416..d8d733735a33b 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -494,7 +494,7 @@ const AVOutputFormat *av_muxer_iterate(void **opaque) uintptr_t i = (uintptr_t)*opaque; const AVOutputFormat *f = NULL; - if (i < size - 1) { + if (i < size) { f = muxer_list[i]; } else if (indev_list) { f = outdev_list[i - size]; From 9b125826ed7eda54387c06469c081229b222ee59 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Sun, 1 Apr 2018 22:29:46 +0800 Subject: [PATCH 2330/2557] cmdutils: fix new API break the "ffmpeg -muxers/demuxers" fix commit 2238190 break the "ffmpeg -muxers/demuxers". Signed-off-by: Jun Zhao Signed-off-by: Josh de Kock --- fftools/cmdutils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index a6cf002fd0aa6..1001f362999a1 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1278,7 +1278,7 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg, const char *long_name = NULL; if (muxdemuxers !=SHOW_DEMUXERS) { - ifmt_opaque = NULL; + ofmt_opaque = NULL; while ((ofmt = av_muxer_iterate(&ofmt_opaque))) { is_dev = is_device(ofmt->priv_class); if (!is_dev && device_only) @@ -1292,7 +1292,7 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg, } } if (muxdemuxers != SHOW_MUXERS) { - ofmt_opaque = NULL; + ifmt_opaque = NULL; while ((ifmt = av_demuxer_iterate(&ifmt_opaque))) { is_dev = is_device(ifmt->priv_class); if (!is_dev && device_only) From ef06ed5b185dc619d9bf94d3d1284b410e25ea6b Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 1 Apr 2018 22:50:34 -0300 Subject: [PATCH 2331/2557] libaom: remove references to yuv440p pixfmt Support for it was apparently never in the codebase, and the enum values were recently removed from the public headers [1] Fixes build with latest libaom build. [1] https://aomedia.googlesource.com/aom/+/2e3cd5c5c30fa02134681cda900c32486807af3f Signed-off-by: James Almer --- libavcodec/libaom.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavcodec/libaom.c b/libavcodec/libaom.c index 220b1bd245b6b..f083129f4b8d3 100644 --- a/libavcodec/libaom.c +++ b/libavcodec/libaom.c @@ -68,8 +68,6 @@ enum AVPixelFormat ff_aom_imgfmt_to_pixfmt(aom_img_fmt_t img, int depth) return AV_PIX_FMT_YUV444P; case AOM_IMG_FMT_444A: return AV_PIX_FMT_YUVA444P; - case AOM_IMG_FMT_I440: - return AV_PIX_FMT_YUV440P; HIGH_DEPTH(420) HIGH_DEPTH(422) HIGH_DEPTH(444) @@ -113,8 +111,6 @@ aom_img_fmt_t ff_aom_pixfmt_to_imgfmt(enum AVPixelFormat pix) return AOM_IMG_FMT_I444; case AV_PIX_FMT_YUVA444P: return AOM_IMG_FMT_444A; - case AV_PIX_FMT_YUV440P: - return AOM_IMG_FMT_I440; case AV_PIX_FMT_YUV420P10: return AOM_IMG_FMT_I42016; case AV_PIX_FMT_YUV422P10: From f1805d160d66442567094fc84d3063ad42458809 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 1 Apr 2018 23:19:02 -0300 Subject: [PATCH 2332/2557] avfilter: bump version for the latest API change And fix the entry in doc/APIchanges Signed-off-by: James Almer --- doc/APIchanges | 2 +- libavfilter/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 235868b22a088..adc8b1d0c8a1c 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,7 +15,7 @@ libavutil: 2017-10-21 API changes, most recent first: -2018-xx-xx - xxxxxxx - lavc 7.13.100 - avcodec.h +2018-xx-xx - xxxxxxx - lavfi 7.14.100 - avfilter.h Deprecate use of avfilter_register(), avfilter_register_all(), avfilter_next(). Add av_filter_iterate(). diff --git a/libavfilter/version.h b/libavfilter/version.h index 8d77a500bf1ac..d9b49ea744751 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 13 +#define LIBAVFILTER_VERSION_MINOR 14 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ From 85bf89885a97c18bfaf9dbe30321af9a58a1444d Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Sun, 1 Apr 2018 00:19:49 +0100 Subject: [PATCH 2333/2557] Revert "avformat/format: temporarily use old next api" This reverts commit 909e00ae816df9b6a05b1c4d0cafb794d4d0ca28. There is no need to use the old API anymore as the new API now behaves in the same way (treating devices as formats when loaded). Signed-off-by: Josh de Kock --- libavformat/format.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/libavformat/format.c b/libavformat/format.c index 123f5faf6c8bb..1b2ce22e25500 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -51,10 +51,9 @@ int av_match_ext(const char *filename, const char *extensions) AVOutputFormat *av_guess_format(const char *short_name, const char *filename, const char *mime_type) { - AVOutputFormat *fmt = NULL, *fmt_found; -#if !FF_API_NEXT + const AVOutputFormat *fmt = NULL; + AVOutputFormat *fmt_found = NULL; void *i = 0; -#endif int score_max, score; /* specific test for image sequences */ @@ -66,15 +65,8 @@ AVOutputFormat *av_guess_format(const char *short_name, const char *filename, } #endif /* Find the proper file type. */ - fmt_found = NULL; score_max = 0; -#if FF_API_NEXT -FF_DISABLE_DEPRECATION_WARNINGS - while ((fmt = av_oformat_next(fmt))) -#else - while ((fmt = av_muxer_iterate(&i))) -#endif - { + while ((fmt = av_muxer_iterate(&i))) { score = 0; if (fmt->name && short_name && av_match_name(short_name, fmt->name)) score += 100; @@ -86,12 +78,9 @@ FF_DISABLE_DEPRECATION_WARNINGS } if (score > score_max) { score_max = score; - fmt_found = fmt; + fmt_found = (AVOutputFormat*)fmt; } } -#if FF_API_NEXT -FF_ENABLE_DEPRECATION_WARNINGS -#endif return fmt_found; } From d1221f335183a07dae761551188677551e5ba792 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Sun, 1 Apr 2018 03:17:07 +0100 Subject: [PATCH 2334/2557] lavf/format: use const AVInputFormat for iteration Signed-off-by: Josh de Kock --- libavformat/format.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavformat/format.c b/libavformat/format.c index 1b2ce22e25500..1c66afb7e6d55 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -117,11 +117,11 @@ enum AVCodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name, AVInputFormat *av_find_input_format(const char *short_name) { - AVInputFormat *fmt = NULL; + const AVInputFormat *fmt = NULL; void *i = 0; while ((fmt = av_demuxer_iterate(&i))) if (av_match_name(short_name, fmt->name)) - return fmt; + return (AVInputFormat*)fmt; return NULL; } @@ -129,7 +129,8 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score_ret) { AVProbeData lpd = *pd; - AVInputFormat *fmt1 = NULL, *fmt; + const AVInputFormat *fmt1 = NULL; + AVInputFormat *fmt = NULL; int score, score_max = 0; void *i = 0; const static uint8_t zerobuffer[AVPROBE_PADDING_SIZE]; @@ -156,7 +157,6 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, nodat = ID3_GREATER_PROBE; } - fmt = NULL; while ((fmt1 = av_demuxer_iterate(&i))) { if (!is_opened == !(fmt1->flags & AVFMT_NOFILE) && strcmp(fmt1->name, "image2")) continue; @@ -191,7 +191,7 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, } if (score > score_max) { score_max = score; - fmt = fmt1; + fmt = (AVInputFormat*)fmt1; } else if (score == score_max) fmt = NULL; } From 89029bd2c7f385c078fba8f2a8c19229833caa13 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Sun, 18 Feb 2018 17:54:23 +0000 Subject: [PATCH 2335/2557] lav*,tests: remove several register_all calls avdevice_register_all() is still required to register devices into lavf (this is required due to lavd being somewhat of a hack). Signed-off-by: Josh de Kock --- doc/examples/filter_audio.c | 2 -- doc/examples/filtering_audio.c | 2 -- doc/examples/filtering_video.c | 2 -- doc/examples/transcoding.c | 2 -- fftools/ffmpeg.c | 3 --- fftools/ffplay.c | 4 ---- fftools/ffprobe.c | 1 - libavcodec/tests/utils.c | 1 - libavdevice/lavfi.c | 2 -- libavfilter/lavfutils.c | 2 -- libavfilter/src_movie.c | 2 -- libavfilter/tests/filtfmts.c | 2 -- libavformat/tests/movenc.c | 2 -- libavformat/tests/seek.c | 3 --- tests/api/api-band-test.c | 2 -- tests/api/api-codec-param-test.c | 2 -- tests/api/api-flac-test.c | 2 -- tests/api/api-h264-test.c | 2 -- tests/api/api-seek-test.c | 2 -- tools/aviocat.c | 1 - tools/enum_options.c | 2 -- tools/graph2dot.c | 2 -- tools/ismindex.c | 2 -- tools/pktdumper.c | 3 --- tools/probetest.c | 3 --- tools/seek_print.c | 1 - tools/sidxindex.c | 2 -- tools/uncoded_frame.c | 2 -- 28 files changed, 58 deletions(-) diff --git a/doc/examples/filter_audio.c b/doc/examples/filter_audio.c index 7467c21c30bf9..1611e3d952e5b 100644 --- a/doc/examples/filter_audio.c +++ b/doc/examples/filter_audio.c @@ -289,8 +289,6 @@ int main(int argc, char *argv[]) return 1; } - avfilter_register_all(); - /* Allocate the frame we will be using to store the data. */ frame = av_frame_alloc(); if (!frame) { diff --git a/doc/examples/filtering_audio.c b/doc/examples/filtering_audio.c index 73a00e814c1ab..b109dbcb96d70 100644 --- a/doc/examples/filtering_audio.c +++ b/doc/examples/filtering_audio.c @@ -228,8 +228,6 @@ int main(int argc, char **argv) exit(1); } - avfilter_register_all(); - if ((ret = open_input_file(argv[1])) < 0) goto end; if ((ret = init_filters(filter_descr)) < 0) diff --git a/doc/examples/filtering_video.c b/doc/examples/filtering_video.c index 01d6644620be6..ed4e7bbd81d2d 100644 --- a/doc/examples/filtering_video.c +++ b/doc/examples/filtering_video.c @@ -222,8 +222,6 @@ int main(int argc, char **argv) exit(1); } - avfilter_register_all(); - if ((ret = open_input_file(argv[1])) < 0) goto end; if ((ret = init_filters(filter_descr)) < 0) diff --git a/doc/examples/transcoding.c b/doc/examples/transcoding.c index ed1fd6411bfd1..a83fa3a185817 100644 --- a/doc/examples/transcoding.c +++ b/doc/examples/transcoding.c @@ -517,8 +517,6 @@ int main(int argc, char **argv) return 1; } - avfilter_register_all(); - if ((ret = open_input_file(argv[1])) < 0) goto end; if ((ret = open_output_file(argv[2])) < 0) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index d3bc382dec11a..2f8a5ace568ea 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -4776,12 +4776,9 @@ int main(int argc, char **argv) argv++; } - avcodec_register_all(); #if CONFIG_AVDEVICE avdevice_register_all(); #endif - avfilter_register_all(); - av_register_all(); avformat_network_init(); show_banner(argc, argv, options); diff --git a/fftools/ffplay.c b/fftools/ffplay.c index f2028d4b13df9..bc9ddb8885c9e 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -3655,10 +3655,6 @@ int main(int argc, char **argv) #if CONFIG_AVDEVICE avdevice_register_all(); #endif -#if CONFIG_AVFILTER - avfilter_register_all(); -#endif - av_register_all(); avformat_network_init(); init_opts(); diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index a4ac6972a215a..2582649fd3061 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -3567,7 +3567,6 @@ int main(int argc, char **argv) options = real_options; parse_loglevel(argc, argv, options); - av_register_all(); avformat_network_init(); init_opts(); #if CONFIG_AVDEVICE diff --git a/libavcodec/tests/utils.c b/libavcodec/tests/utils.c index e2891fb389fdf..f6ba7fe66e3f9 100644 --- a/libavcodec/tests/utils.c +++ b/libavcodec/tests/utils.c @@ -21,7 +21,6 @@ int main(void){ AVCodec *codec = NULL; int ret = 0; - avcodec_register_all(); while (codec = av_codec_next(codec)) { if (av_codec_is_encoder(codec)) { diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index 6f2ae958dcbf7..ca8f05f3f7236 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -130,8 +130,6 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) if (!pix_fmts) FAIL(AVERROR(ENOMEM)); - avfilter_register_all(); - buffersink = avfilter_get_by_name("buffersink"); abuffersink = avfilter_get_by_name("abuffersink"); diff --git a/libavfilter/lavfutils.c b/libavfilter/lavfutils.c index b6319cf02758a..db4b69b9f36d0 100644 --- a/libavfilter/lavfutils.c +++ b/libavfilter/lavfutils.c @@ -37,8 +37,6 @@ int ff_load_image(uint8_t *data[4], int linesize[4], av_init_packet(&pkt); - av_register_all(); - iformat = av_find_input_format("image2pipe"); if ((ret = avformat_open_input(&format_ctx, filename, iformat, NULL)) < 0) { av_log(log_ctx, AV_LOG_ERROR, diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c index 258ba504a5717..bcabfcc4c295e 100644 --- a/libavfilter/src_movie.c +++ b/libavfilter/src_movie.c @@ -239,8 +239,6 @@ static av_cold int movie_common_init(AVFilterContext *ctx) return AVERROR_PATCHWELCOME; } - av_register_all(); - // Try to find the movie format (container) iformat = movie->format_name ? av_find_input_format(movie->format_name) : NULL; diff --git a/libavfilter/tests/filtfmts.c b/libavfilter/tests/filtfmts.c index 72b860ae5b5b4..a958621f1c2cd 100644 --- a/libavfilter/tests/filtfmts.c +++ b/libavfilter/tests/filtfmts.c @@ -97,8 +97,6 @@ int main(int argc, char **argv) if (!graph_ctx) return 1; - avfilter_register_all(); - /* get a corresponding filter and open it */ if (!(filter = avfilter_get_by_name(filter_name))) { fprintf(stderr, "Unrecognized filter with name '%s'\n", filter_name); diff --git a/libavformat/tests/movenc.c b/libavformat/tests/movenc.c index ad6c92a94c96c..1d15d97ad92df 100644 --- a/libavformat/tests/movenc.c +++ b/libavformat/tests/movenc.c @@ -379,8 +379,6 @@ int main(int argc, char **argv) } } - av_register_all(); - md5 = av_md5_alloc(); if (!md5) return 1; diff --git a/libavformat/tests/seek.c b/libavformat/tests/seek.c index 7ed56ba4ef980..e0067a64fc371 100644 --- a/libavformat/tests/seek.c +++ b/libavformat/tests/seek.c @@ -91,9 +91,6 @@ int main(int argc, char **argv) av_dict_set(&format_opts, "channels", "1", 0); av_dict_set(&format_opts, "sample_rate", "22050", 0); - /* initialize libavcodec, and register all codecs and formats */ - av_register_all(); - if (argc < 2) { printf("usage: %s input_file\n" "\n", argv[0]); diff --git a/tests/api/api-band-test.c b/tests/api/api-band-test.c index 5ccba4f766555..a84f6b7e5560d 100644 --- a/tests/api/api-band-test.c +++ b/tests/api/api-band-test.c @@ -214,8 +214,6 @@ int main(int argc, char **argv) return 1; } - av_register_all(); - if (video_decode(argv[1]) != 0) return 1; diff --git a/tests/api/api-codec-param-test.c b/tests/api/api-codec-param-test.c index 377a5e9c793ef..0868322cb4b91 100644 --- a/tests/api/api-codec-param-test.c +++ b/tests/api/api-codec-param-test.c @@ -231,8 +231,6 @@ int main(int argc, char* argv[]) AVFormatContext *fmt_ctx = NULL; AVFormatContext *fmt_ctx_no_decode = NULL; - av_register_all(); - if (argc < 2) { av_log(NULL, AV_LOG_ERROR, "Usage: %s \n", argv[0]); return -1; diff --git a/tests/api/api-flac-test.c b/tests/api/api-flac-test.c index c5a37f03e11e7..2e9081266f829 100644 --- a/tests/api/api-flac-test.c +++ b/tests/api/api-flac-test.c @@ -245,8 +245,6 @@ int main(void) int sample_rates[] = {8000, 44100, 48000, 192000}; int cl, sr; - avcodec_register_all(); - enc = avcodec_find_encoder(AV_CODEC_ID_FLAC); if (!enc) { av_log(NULL, AV_LOG_ERROR, "Can't find encoder\n"); diff --git a/tests/api/api-h264-test.c b/tests/api/api-h264-test.c index 52282e0007458..66669fa0c353c 100644 --- a/tests/api/api-h264-test.c +++ b/tests/api/api-h264-test.c @@ -158,8 +158,6 @@ int main(int argc, char **argv) return 1; } - av_register_all(); - if (video_decode_example(argv[1]) != 0) return 1; diff --git a/tests/api/api-seek-test.c b/tests/api/api-seek-test.c index 2b32cb9e4f382..d0531a2f731f8 100644 --- a/tests/api/api-seek-test.c +++ b/tests/api/api-seek-test.c @@ -279,8 +279,6 @@ int main(int argc, char **argv) return 1; } - av_register_all(); - if (seek_test(argv[1], argv[2], argv[3]) != 0) return 1; diff --git a/tools/aviocat.c b/tools/aviocat.c index 28529b06d6a99..2aa08b92ed988 100644 --- a/tools/aviocat.c +++ b/tools/aviocat.c @@ -42,7 +42,6 @@ int main(int argc, char **argv) AVDictionary *in_opts = NULL; AVDictionary *out_opts = NULL; - av_register_all(); avformat_network_init(); for (i = 1; i < argc; i++) { diff --git a/tools/enum_options.c b/tools/enum_options.c index c2a295cad62e4..77e1f9f799d98 100644 --- a/tools/enum_options.c +++ b/tools/enum_options.c @@ -130,8 +130,6 @@ int main(int argc, char **argv) if (argc < 2) print_usage(); - av_register_all(); - if (!strcmp(argv[1], "format")) show_format_opts(); else if (!strcmp(argv[1], "codec")) diff --git a/tools/graph2dot.c b/tools/graph2dot.c index 21d0795e88184..d5c1e4e3c7920 100644 --- a/tools/graph2dot.c +++ b/tools/graph2dot.c @@ -189,8 +189,6 @@ int main(int argc, char **argv) *p = '\0'; } - avfilter_register_all(); - if (avfilter_graph_parse(graph, graph_string, NULL, NULL, NULL) < 0) { fprintf(stderr, "Failed to parse the graph description\n"); return 1; diff --git a/tools/ismindex.c b/tools/ismindex.c index 0254a98ff71ec..7601f62e06ff5 100644 --- a/tools/ismindex.c +++ b/tools/ismindex.c @@ -791,8 +791,6 @@ int main(int argc, char **argv) int split = 0, ismf = 0, i; struct Tracks tracks = { 0, .video_track = -1, .audio_track = -1 }; - av_register_all(); - for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-n")) { basename = argv[i + 1]; diff --git a/tools/pktdumper.c b/tools/pktdumper.c index 6516ad3a225d5..16a965b75697b 100644 --- a/tools/pktdumper.c +++ b/tools/pktdumper.c @@ -89,9 +89,6 @@ int main(int argc, char **argv) strcat(fntemplate, PKTFILESUFF); printf("FNTEMPLATE: '%s'\n", fntemplate); - // register all file formats - av_register_all(); - err = avformat_open_input(&fctx, argv[1], NULL, NULL); if (err < 0) { fprintf(stderr, "cannot open input: error %d\n", err); diff --git a/tools/probetest.c b/tools/probetest.c index 74045eb4985e2..2c6c1de246393 100644 --- a/tools/probetest.c +++ b/tools/probetest.c @@ -124,9 +124,6 @@ int main(int argc, char **argv) return 1; } - avcodec_register_all(); - av_register_all(); - av_lfg_init(&state, 0xdeadbeef); pd.buf = NULL; diff --git a/tools/seek_print.c b/tools/seek_print.c index de876b487c581..9280421741de8 100644 --- a/tools/seek_print.c +++ b/tools/seek_print.c @@ -65,7 +65,6 @@ int main(int argc, char **argv) argv++; argc--; - av_register_all(); if ((ret = avformat_open_input(&avf, filename, NULL, NULL)) < 0) { fprintf(stderr, "%s: %s\n", filename, av_err2str(ret)); return 1; diff --git a/tools/sidxindex.c b/tools/sidxindex.c index be284610d563f..a4f95515e4f06 100644 --- a/tools/sidxindex.c +++ b/tools/sidxindex.c @@ -363,8 +363,6 @@ int main(int argc, char **argv) struct Tracks tracks = { 0 }; int i; - av_register_all(); - for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-out")) { out = argv[i + 1]; diff --git a/tools/uncoded_frame.c b/tools/uncoded_frame.c index 3aaa4b6897544..3f850d344d746 100644 --- a/tools/uncoded_frame.c +++ b/tools/uncoded_frame.c @@ -62,9 +62,7 @@ int main(int argc, char **argv) out_dev_name = argv + 2; nb_out_dev = argc - 2; - av_register_all(); avdevice_register_all(); - avfilter_register_all(); /* Create input graph */ if (!(in_graph = avfilter_graph_alloc())) { From e0f32286861ddf7666ba92297686fa216d65968e Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Sun, 18 Mar 2018 15:31:20 +0000 Subject: [PATCH 2336/2557] lavf/img2dec: use new iteration API Signed-off-by: Josh de Kock --- libavformat/img2dec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c index f3f52c83b355a..ffbc9a66d8231 100644 --- a/libavformat/img2dec.c +++ b/libavformat/img2dec.c @@ -323,7 +323,8 @@ int ff_img_read_header(AVFormatContext *s1) if (s1->pb) { int probe_buffer_size = 2048; uint8_t *probe_buffer = av_realloc(NULL, probe_buffer_size + AVPROBE_PADDING_SIZE); - AVInputFormat *fmt = NULL; + const AVInputFormat *fmt = NULL; + void *fmt_iter = NULL; AVProbeData pd = { 0 }; if (!probe_buffer) @@ -340,7 +341,7 @@ int ff_img_read_header(AVFormatContext *s1) pd.buf_size = probe_buffer_size; pd.filename = s1->url; - while ((fmt = av_iformat_next(fmt))) { + while ((fmt = av_demuxer_iterate(&fmt_iter))) { if (fmt->read_header != ff_img_read_header || !fmt->read_probe || (fmt->flags & AVFMT_NOFILE) || From 860086ee168866c8b7cdb5c1c13ac962c5f3efc4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 24 Mar 2018 19:18:59 -0300 Subject: [PATCH 2337/2557] avcodec/avpacket: add av_packet_make_refcounted() It works as a drop in replacement for the deprecated av_dup_packet(), to ensure a packet is reference counted. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- doc/APIchanges | 3 +++ libavcodec/avcodec.h | 18 +++++++++++++++++- libavcodec/avpacket.c | 18 ++++++++++++++++++ libavcodec/version.h | 2 +- 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index adc8b1d0c8a1c..121fbee9ceb07 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-04-01 - xxxxxxx - lavc 58.17.100 - avcodec.h + Add av_packet_make_refcounted(). + 2018-xx-xx - xxxxxxx - lavfi 7.14.100 - avfilter.h Deprecate use of avfilter_register(), avfilter_register_all(), avfilter_next(). Add av_filter_iterate(). diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 3306910dd2f4f..fb0c6fae70b33 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -4365,7 +4365,7 @@ int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size); * @warning This is a hack - the packet memory allocation stuff is broken. The * packet is allocated if it was not really allocated. * - * @deprecated Use av_packet_ref + * @deprecated Use av_packet_ref or av_packet_make_refcounted */ attribute_deprecated int av_dup_packet(AVPacket *pkt); @@ -4536,6 +4536,22 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src); */ int av_packet_copy_props(AVPacket *dst, const AVPacket *src); +/** + * Ensure the data described by a given packet is reference counted. + * + * @note This function does not ensure that the reference will be writable. + * Use av_packet_make_writable instead for that purpose. + * + * @see av_packet_ref + * @see av_packet_make_writable + * + * @param pkt packet whose data should be made reference counted. + * + * @return 0 on success, a negative AVERROR on error. On failure, the + * packet is unchanged. + */ +int av_packet_make_refcounted(AVPacket *pkt); + /** * Create a writable reference for the data described by a given packet, * avoiding data copy if possible. diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index 09934819613d7..99a0c1383bd1b 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -652,6 +652,24 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src) src->size = 0; } +int av_packet_make_refcounted(AVPacket *pkt) +{ + int ret; + + if (pkt->buf) + return 0; + + ret = packet_alloc(&pkt->buf, pkt->size); + if (ret < 0) + return ret; + if (pkt->size) + memcpy(pkt->buf->data, pkt->data, pkt->size); + + pkt->data = pkt->buf->data; + + return 0; +} + int av_packet_make_writable(AVPacket *pkt) { AVBufferRef *buf = NULL; diff --git a/libavcodec/version.h b/libavcodec/version.h index 8ac4626da79a4..e59215dfed1ea 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 16 +#define LIBAVCODEC_VERSION_MINOR 17 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From de0526070eb173b86e85c87b5d45b042a7590202 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 24 Mar 2018 22:27:05 -0300 Subject: [PATCH 2338/2557] avcodec/frame_thread_encoder: remove usage of av_dup_packet() Signed-off-by: James Almer --- libavcodec/frame_thread_encoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/frame_thread_encoder.c b/libavcodec/frame_thread_encoder.c index 215aee9fc06f6..5ff3f7863cb03 100644 --- a/libavcodec/frame_thread_encoder.c +++ b/libavcodec/frame_thread_encoder.c @@ -92,7 +92,7 @@ static void * attribute_align_arg worker(void *v){ pthread_mutex_unlock(&c->buffer_mutex); av_frame_free(&frame); if(got_packet) { - int ret2 = av_dup_packet(pkt); + int ret2 = av_packet_make_refcounted(pkt); if (ret >= 0 && ret2 < 0) ret = ret2; } else { From e61d8b82a2ca866582454c6c90ffad664e2bb5e1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 24 Mar 2018 21:58:56 -0300 Subject: [PATCH 2339/2557] avcodec/encode: use av_packet_make_refcounted to ensure packets are ref counted Simplifies code. Signed-off-by: James Almer --- libavcodec/encode.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 71b1b14afc029..d9761515aa84e 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -223,12 +223,9 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, avpkt->buf = user_pkt.buf; avpkt->data = user_pkt.data; } else if (!avpkt->buf) { - AVPacket tmp = { 0 }; - ret = av_packet_ref(&tmp, avpkt); - av_packet_unref(avpkt); + ret = av_packet_make_refcounted(avpkt); if (ret < 0) goto end; - *avpkt = tmp; } } @@ -318,12 +315,9 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, avpkt->buf = user_pkt.buf; avpkt->data = user_pkt.data; } else if (!avpkt->buf) { - AVPacket tmp = { 0 }; - ret = av_packet_ref(&tmp, avpkt); - av_packet_unref(avpkt); + ret = av_packet_make_refcounted(avpkt); if (ret < 0) return ret; - *avpkt = tmp; } } From 38fa61b94766fc21bf32a279c77fc4084b30de1c Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 24 Mar 2018 22:28:42 -0300 Subject: [PATCH 2340/2557] avdevice/decklink_dec: use av_packet_make_refcounted to ensure packets are ref counted Partially reverts commit e91f0c4f8b, simplifying code. Signed-off-by: James Almer --- libavdevice/decklink_dec.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 28a748a28f8ff..e97a4402ea319 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -464,24 +464,22 @@ static unsigned long long avpacket_queue_size(AVPacketQueue *q) static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) { AVPacketList *pkt1; - int ret; // Drop Packet if queue size is > maximum queue size if (avpacket_queue_size(q) > (uint64_t)q->max_q_size) { av_log(q->avctx, AV_LOG_WARNING, "Decklink input buffer overrun!\n"); return -1; } - - pkt1 = (AVPacketList *)av_mallocz(sizeof(AVPacketList)); - if (!pkt1) { + /* ensure the packet is reference counted */ + if (av_packet_make_refcounted(pkt) < 0) { return -1; } - ret = av_packet_ref(&pkt1->pkt, pkt); - av_packet_unref(pkt); - if (ret < 0) { - av_free(pkt1); + + pkt1 = (AVPacketList *)av_malloc(sizeof(AVPacketList)); + if (!pkt1) { return -1; } + av_packet_move_ref(&pkt1->pkt, pkt); pkt1->next = NULL; pthread_mutex_lock(&q->mutex); From 265ec55983bf3b981190b564925a609d53391aa5 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 25 Mar 2018 00:23:58 -0300 Subject: [PATCH 2341/2557] avcodec/bsf: use av_packet_make_refcounted to ensure packets are ref counted Simplifies code. Signed-off-by: James Almer --- libavcodec/bsf.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/libavcodec/bsf.c b/libavcodec/bsf.c index 05a44e2e31cc0..bd611ea16b0e7 100644 --- a/libavcodec/bsf.c +++ b/libavcodec/bsf.c @@ -174,6 +174,8 @@ int av_bsf_init(AVBSFContext *ctx) int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt) { + int ret; + if (!pkt || (!pkt->data && !pkt->side_data_elems)) { ctx->internal->eof = 1; return 0; @@ -188,15 +190,10 @@ int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt) ctx->internal->buffer_pkt->side_data_elems) return AVERROR(EAGAIN); - if (pkt->buf) { - av_packet_move_ref(ctx->internal->buffer_pkt, pkt); - } else { - int ret = av_packet_ref(ctx->internal->buffer_pkt, pkt); - - if (ret < 0) - return ret; - av_packet_unref(pkt); - } + ret = av_packet_make_refcounted(pkt); + if (ret < 0) + return ret; + av_packet_move_ref(ctx->internal->buffer_pkt, pkt); return 0; } From 02ae52db87270715bb81ddb912a2e3968e973d1f Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 24 Mar 2018 22:33:32 -0300 Subject: [PATCH 2342/2557] avformat/utils: use av_packet_make_refcounted to ensure packets are ref counted Simplifies code, while also fixing a potential leak of side data in pkt. Signed-off-by: James Almer --- libavformat/utils.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index f13c8208b118d..39a36a5ac4388 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -867,13 +867,9 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) continue; } - if (!pkt->buf) { - AVPacket tmp = { 0 }; - err = av_packet_ref(&tmp, pkt); - if (err < 0) - return err; - *pkt = tmp; - } + err = av_packet_make_refcounted(pkt); + if (err < 0) + return err; if ((s->flags & AVFMT_FLAG_DISCARD_CORRUPT) && (pkt->flags & AV_PKT_FLAG_CORRUPT)) { From 22a878ecd1c1d67ea985e998d9c0493795b86427 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 2 Apr 2018 08:59:20 +0200 Subject: [PATCH 2343/2557] avcodec/scpr: check for possible out of array access Signed-off-by: Paul B Mahol --- libavcodec/scpr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/scpr.c b/libavcodec/scpr.c index ad6073dbf0118..3c797d55f5267 100644 --- a/libavcodec/scpr.c +++ b/libavcodec/scpr.c @@ -211,6 +211,10 @@ static int decode_value(SCPRContext *s, unsigned *cnt, unsigned maxc, unsigned s break; c++; } + + if (c >= maxc) + return AVERROR_INVALIDDATA; + if ((ret = s->decode(gb, rc, cumfr, cnt_c, totfr)) < 0) return ret; From 699fa8f382704acdbdf720042dd7b21df2eb7558 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Wed, 27 Dec 2017 01:08:39 +0000 Subject: [PATCH 2344/2557] simple_idct: Template functions to support an input bitdepth parameter --- libavcodec/bit_depth_template.c | 17 +++++++++++- libavcodec/idctdsp.c | 18 ++++++------- libavcodec/me_cmp.c | 2 +- libavcodec/simple_idct.c | 15 ++++++++--- libavcodec/simple_idct.h | 24 ++++++++++------- libavcodec/simple_idct_template.c | 44 ++++++++++++++++++++----------- libavcodec/tests/dct.c | 6 ++--- libavcodec/vc1.c | 4 +-- 8 files changed, 86 insertions(+), 44 deletions(-) diff --git a/libavcodec/bit_depth_template.c b/libavcodec/bit_depth_template.c index 80184892f5a64..d44d47ea456be 100644 --- a/libavcodec/bit_depth_template.c +++ b/libavcodec/bit_depth_template.c @@ -29,6 +29,7 @@ # undef pixel2 # undef pixel4 # undef dctcoef +# undef idctin # undef INIT_CLIP # undef no_rnd_avg_pixel4 # undef rnd_avg_pixel4 @@ -53,6 +54,16 @@ # define pixel4 uint64_t # define dctcoef int32_t +#ifdef IN_IDCT_DEPTH +#if IN_IDCT_DEPTH == 32 +# define idctin int32_t +#else +# define idctin int16_t +#endif +#else +# define idctin int16_t +#endif + # define INIT_CLIP # define no_rnd_avg_pixel4 no_rnd_avg64 # define rnd_avg_pixel4 rnd_avg64 @@ -71,6 +82,7 @@ # define pixel2 uint16_t # define pixel4 uint32_t # define dctcoef int16_t +# define idctin int16_t # define INIT_CLIP # define no_rnd_avg_pixel4 no_rnd_avg32 @@ -87,7 +99,10 @@ # define CLIP(a) av_clip_uint8(a) #endif -#define FUNC3(a, b, c) a ## _ ## b ## c +#define FUNC3(a, b, c) a ## _ ## b ## c #define FUNC2(a, b, c) FUNC3(a, b, c) #define FUNC(a) FUNC2(a, BIT_DEPTH,) #define FUNCC(a) FUNC2(a, BIT_DEPTH, _c) +#define FUNC4(a, b, c) a ## _int ## b ## _ ## c ## bit +#define FUNC5(a, b, c) FUNC4(a, b, c) +#define FUNC6(a) FUNC5(a, IN_IDCT_DEPTH, BIT_DEPTH) diff --git a/libavcodec/idctdsp.c b/libavcodec/idctdsp.c index 0122d29efa325..1de372d2b9e26 100644 --- a/libavcodec/idctdsp.c +++ b/libavcodec/idctdsp.c @@ -256,14 +256,14 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) c->perm_type = FF_IDCT_PERM_NONE; } else { if (avctx->bits_per_raw_sample == 10 || avctx->bits_per_raw_sample == 9) { - c->idct_put = ff_simple_idct_put_10; - c->idct_add = ff_simple_idct_add_10; - c->idct = ff_simple_idct_10; + c->idct_put = ff_simple_idct_put_int16_10bit; + c->idct_add = ff_simple_idct_add_int16_10bit; + c->idct = ff_simple_idct_int16_10bit; c->perm_type = FF_IDCT_PERM_NONE; } else if (avctx->bits_per_raw_sample == 12) { - c->idct_put = ff_simple_idct_put_12; - c->idct_add = ff_simple_idct_add_12; - c->idct = ff_simple_idct_12; + c->idct_put = ff_simple_idct_put_int16_12bit; + c->idct_add = ff_simple_idct_add_int16_12bit; + c->idct = ff_simple_idct_int16_12bit; c->perm_type = FF_IDCT_PERM_NONE; } else { if (avctx->idct_algo == FF_IDCT_INT) { @@ -280,9 +280,9 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) #endif /* CONFIG_FAANIDCT */ } else { // accurate/default /* Be sure FF_IDCT_NONE will select this one, since it uses FF_IDCT_PERM_NONE */ - c->idct_put = ff_simple_idct_put_8; - c->idct_add = ff_simple_idct_add_8; - c->idct = ff_simple_idct_8; + c->idct_put = ff_simple_idct_put_int16_8bit; + c->idct_add = ff_simple_idct_add_int16_8bit; + c->idct = ff_simple_idct_int16_8bit; c->perm_type = FF_IDCT_PERM_NONE; } } diff --git a/libavcodec/me_cmp.c b/libavcodec/me_cmp.c index 465d3ccb2af16..ae248c52f82a5 100644 --- a/libavcodec/me_cmp.c +++ b/libavcodec/me_cmp.c @@ -755,7 +755,7 @@ static int quant_psnr8x8_c(MpegEncContext *s, uint8_t *src1, s->block_last_index[0 /* FIXME */] = s->fast_dct_quantize(s, temp, 0 /* FIXME */, s->qscale, &i); s->dct_unquantize_inter(s, temp, 0, s->qscale); - ff_simple_idct_8(temp); // FIXME + ff_simple_idct_int16_8bit(temp); // FIXME for (i = 0; i < 64; i++) sum += (temp[i] - bak[i]) * (temp[i] - bak[i]); diff --git a/libavcodec/simple_idct.c b/libavcodec/simple_idct.c index 1d05b2fe08cb8..78b29c0fe3e03 100644 --- a/libavcodec/simple_idct.c +++ b/libavcodec/simple_idct.c @@ -30,6 +30,8 @@ #include "mathops.h" #include "simple_idct.h" +#define IN_IDCT_DEPTH 16 + #define BIT_DEPTH 8 #include "simple_idct_template.c" #undef BIT_DEPTH @@ -46,6 +48,13 @@ #define BIT_DEPTH 12 #include "simple_idct_template.c" #undef BIT_DEPTH +#undef IN_IDCT_DEPTH + +#define IN_IDCT_DEPTH 32 +#define BIT_DEPTH 10 +#include "simple_idct_template.c" +#undef BIT_DEPTH +#undef IN_IDCT_DEPTH /* 2x4x8 idct */ @@ -115,7 +124,7 @@ void ff_simple_idct248_put(uint8_t *dest, ptrdiff_t line_size, int16_t *block) /* IDCT8 on each line */ for(i=0; i<8; i++) { - idctRowCondDC_8(block + i*8, 0); + idctRowCondDC_int16_8bit(block + i*8, 0); } /* IDCT4 and store */ @@ -188,7 +197,7 @@ void ff_simple_idct84_add(uint8_t *dest, ptrdiff_t line_size, int16_t *block) /* IDCT8 on each line */ for(i=0; i<4; i++) { - idctRowCondDC_8(block + i*8, 0); + idctRowCondDC_int16_8bit(block + i*8, 0); } /* IDCT4 and store */ @@ -208,7 +217,7 @@ void ff_simple_idct48_add(uint8_t *dest, ptrdiff_t line_size, int16_t *block) /* IDCT8 and store */ for(i=0; i<4; i++){ - idctSparseColAdd_8(dest + i, line_size, block + i); + idctSparseColAdd_int16_8bit(dest + i, line_size, block + i); } } diff --git a/libavcodec/simple_idct.h b/libavcodec/simple_idct.h index 2a5e1d7f6dab8..39df2308caa5a 100644 --- a/libavcodec/simple_idct.h +++ b/libavcodec/simple_idct.h @@ -31,20 +31,24 @@ #include #include -void ff_simple_idct_put_8(uint8_t *dest, ptrdiff_t line_size, int16_t *block); -void ff_simple_idct_add_8(uint8_t *dest, ptrdiff_t line_size, int16_t *block); -void ff_simple_idct_8(int16_t *block); +void ff_simple_idct_put_int16_8bit(uint8_t *dest, ptrdiff_t line_size, int16_t *block); +void ff_simple_idct_add_int16_8bit(uint8_t *dest, ptrdiff_t line_size, int16_t *block); +void ff_simple_idct_int16_8bit(int16_t *block); -void ff_simple_idct_put_10(uint8_t *dest, ptrdiff_t line_size, int16_t *block); -void ff_simple_idct_add_10(uint8_t *dest, ptrdiff_t line_size, int16_t *block); -void ff_simple_idct_10(int16_t *block); +void ff_simple_idct_put_int16_10bit(uint8_t *dest, ptrdiff_t line_size, int16_t *block); +void ff_simple_idct_add_int16_10bit(uint8_t *dest, ptrdiff_t line_size, int16_t *block); +void ff_simple_idct_int16_10bit(int16_t *block); -void ff_simple_idct_put_12(uint8_t *dest, ptrdiff_t line_size, int16_t *block); -void ff_simple_idct_add_12(uint8_t *dest, ptrdiff_t line_size, int16_t *block); -void ff_simple_idct_12(int16_t *block); +void ff_simple_idct_put_int32_10bit(uint8_t *dest, ptrdiff_t line_size, int16_t *block); +void ff_simple_idct_add_int32_10bit(uint8_t *dest, ptrdiff_t line_size, int16_t *block); +void ff_simple_idct_int32_10bit(int16_t *block); + +void ff_simple_idct_put_int16_12bit(uint8_t *dest, ptrdiff_t line_size, int16_t *block); +void ff_simple_idct_add_int16_12bit(uint8_t *dest, ptrdiff_t line_size, int16_t *block); +void ff_simple_idct_int16_12bit(int16_t *block); /** - * Special version of ff_simple_idct_10() which does dequantization + * Special version of ff_simple_idct_int16_10bit() which does dequantization * and scales by a factor of 2 more between the two IDCTs to account * for larger scale of input coefficients. */ diff --git a/libavcodec/simple_idct_template.c b/libavcodec/simple_idct_template.c index f532313441c05..904263fc7142a 100644 --- a/libavcodec/simple_idct_template.c +++ b/libavcodec/simple_idct_template.c @@ -77,6 +77,10 @@ #define ROW_SHIFT 13 #define COL_SHIFT 18 #define DC_SHIFT 1 +# elif IN_IDCT_DEPTH == 32 +#define ROW_SHIFT 13 +#define COL_SHIFT 21 +#define DC_SHIFT 2 # else #define ROW_SHIFT 12 #define COL_SHIFT 19 @@ -109,11 +113,13 @@ #ifdef EXTRA_SHIFT static inline void FUNC(idctRowCondDC_extrashift)(int16_t *row, int extra_shift) #else -static inline void FUNC(idctRowCondDC)(int16_t *row, int extra_shift) +static inline void FUNC6(idctRowCondDC)(idctin *row, int extra_shift) #endif { SUINT a0, a1, a2, a3, b0, b1, b2, b3; +// TODO: Add DC-only support for int32_t input +#if IN_IDCT_DEPTH == 16 #if HAVE_FAST_64BIT #define ROW0_MASK (0xffffLL << 48 * HAVE_BIGENDIAN) if (((AV_RN64A(row) & ~ROW0_MASK) | AV_RN64A(row+4)) == 0) { @@ -147,6 +153,7 @@ static inline void FUNC(idctRowCondDC)(int16_t *row, int extra_shift) AV_WN32A(row+6, temp); return; } +#endif #endif a0 = (W4 * row[0]) + (1 << (ROW_SHIFT + extra_shift - 1)); @@ -168,7 +175,11 @@ static inline void FUNC(idctRowCondDC)(int16_t *row, int extra_shift) b3 = MUL(W7, row[1]); MAC(b3, -W5, row[3]); +#if IN_IDCT_DEPTH == 32 + if (AV_RN64A(row + 4) | AV_RN64A(row + 6)) { +#else if (AV_RN64A(row + 4)) { +#endif a0 += W4*row[4] + W6*row[6]; a1 += - W4*row[4] - W2*row[6]; a2 += - W4*row[4] + W2*row[6]; @@ -250,8 +261,8 @@ static inline void FUNC(idctRowCondDC)(int16_t *row, int extra_shift) #ifdef EXTRA_SHIFT static inline void FUNC(idctSparseCol_extrashift)(int16_t *col) #else -static inline void FUNC(idctSparseColPut)(pixel *dest, ptrdiff_t line_size, - int16_t *col) +static inline void FUNC6(idctSparseColPut)(pixel *dest, ptrdiff_t line_size, + idctin *col) { SUINT a0, a1, a2, a3, b0, b1, b2, b3; @@ -274,8 +285,8 @@ static inline void FUNC(idctSparseColPut)(pixel *dest, ptrdiff_t line_size, dest[0] = av_clip_pixel((int)(a0 - b0) >> COL_SHIFT); } -static inline void FUNC(idctSparseColAdd)(pixel *dest, ptrdiff_t line_size, - int16_t *col) +static inline void FUNC6(idctSparseColAdd)(pixel *dest, ptrdiff_t line_size, + idctin *col) { int a0, a1, a2, a3, b0, b1, b2, b3; @@ -298,7 +309,7 @@ static inline void FUNC(idctSparseColAdd)(pixel *dest, ptrdiff_t line_size, dest[0] = av_clip_pixel(dest[0] + ((a0 - b0) >> COL_SHIFT)); } -static inline void FUNC(idctSparseCol)(int16_t *col) +static inline void FUNC6(idctSparseCol)(idctin *col) #endif { int a0, a1, a2, a3, b0, b1, b2, b3; @@ -316,21 +327,23 @@ static inline void FUNC(idctSparseCol)(int16_t *col) } #ifndef EXTRA_SHIFT -void FUNC(ff_simple_idct_put)(uint8_t *dest_, ptrdiff_t line_size, int16_t *block) +void FUNC6(ff_simple_idct_put)(uint8_t *dest_, ptrdiff_t line_size, int16_t *block_) { + idctin *block = (idctin *)block_; pixel *dest = (pixel *)dest_; int i; line_size /= sizeof(pixel); for (i = 0; i < 8; i++) - FUNC(idctRowCondDC)(block + i*8, 0); + FUNC6(idctRowCondDC)(block + i*8, 0); for (i = 0; i < 8; i++) - FUNC(idctSparseColPut)(dest + i, line_size, block + i); + FUNC6(idctSparseColPut)(dest + i, line_size, block + i); } -void FUNC(ff_simple_idct_add)(uint8_t *dest_, ptrdiff_t line_size, int16_t *block) +#if IN_IDCT_DEPTH == 16 +void FUNC6(ff_simple_idct_add)(uint8_t *dest_, ptrdiff_t line_size, int16_t *block) { pixel *dest = (pixel *)dest_; int i; @@ -338,20 +351,21 @@ void FUNC(ff_simple_idct_add)(uint8_t *dest_, ptrdiff_t line_size, int16_t *bloc line_size /= sizeof(pixel); for (i = 0; i < 8; i++) - FUNC(idctRowCondDC)(block + i*8, 0); + FUNC6(idctRowCondDC)(block + i*8, 0); for (i = 0; i < 8; i++) - FUNC(idctSparseColAdd)(dest + i, line_size, block + i); + FUNC6(idctSparseColAdd)(dest + i, line_size, block + i); } -void FUNC(ff_simple_idct)(int16_t *block) +void FUNC6(ff_simple_idct)(int16_t *block) { int i; for (i = 0; i < 8; i++) - FUNC(idctRowCondDC)(block + i*8, 0); + FUNC6(idctRowCondDC)(block + i*8, 0); for (i = 0; i < 8; i++) - FUNC(idctSparseCol)(block + i); + FUNC6(idctSparseCol)(block + i); } #endif +#endif diff --git a/libavcodec/tests/dct.c b/libavcodec/tests/dct.c index b44c66f427494..e8fa4a3cc1a40 100644 --- a/libavcodec/tests/dct.c +++ b/libavcodec/tests/dct.c @@ -82,9 +82,9 @@ static void ff_prores_idct_wrap(int16_t *dst){ static const struct algo idct_tab[] = { { "REF-DBL", ff_ref_idct, FF_IDCT_PERM_NONE }, { "INT", ff_j_rev_dct, FF_IDCT_PERM_LIBMPEG2 }, - { "SIMPLE-C", ff_simple_idct_8, FF_IDCT_PERM_NONE }, - { "SIMPLE-C10", ff_simple_idct_10, FF_IDCT_PERM_NONE }, - { "SIMPLE-C12", ff_simple_idct_12, FF_IDCT_PERM_NONE, 0, 1 }, + { "SIMPLE-C", ff_simple_idct_int16_8bit, FF_IDCT_PERM_NONE }, + { "SIMPLE-C10", ff_simple_idct_int16_10bit, FF_IDCT_PERM_NONE }, + { "SIMPLE-C12", ff_simple_idct_int16_12bit, FF_IDCT_PERM_NONE, 0, 1 }, { "PR-C", ff_prores_idct_wrap, FF_IDCT_PERM_NONE, 0, 1 }, #if CONFIG_FAANIDCT { "FAANI", ff_faanidct, FF_IDCT_PERM_NONE }, diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c index 2b9f8db3ee977..e7625070f7982 100644 --- a/libavcodec/vc1.c +++ b/libavcodec/vc1.c @@ -314,11 +314,11 @@ int ff_vc1_decode_sequence_header(AVCodecContext *avctx, VC1Context *v, GetBitCo v->multires = get_bits1(gb); v->res_fasttx = get_bits1(gb); if (!v->res_fasttx) { - v->vc1dsp.vc1_inv_trans_8x8 = ff_simple_idct_8; + v->vc1dsp.vc1_inv_trans_8x8 = ff_simple_idct_int16_8bit; v->vc1dsp.vc1_inv_trans_8x4 = ff_simple_idct84_add; v->vc1dsp.vc1_inv_trans_4x8 = ff_simple_idct48_add; v->vc1dsp.vc1_inv_trans_4x4 = ff_simple_idct44_add; - v->vc1dsp.vc1_inv_trans_8x8_dc = ff_simple_idct_add_8; + v->vc1dsp.vc1_inv_trans_8x8_dc = ff_simple_idct_add_int16_8bit; v->vc1dsp.vc1_inv_trans_8x4_dc = ff_simple_idct84_add; v->vc1dsp.vc1_inv_trans_4x8_dc = ff_simple_idct48_add; v->vc1dsp.vc1_inv_trans_4x4_dc = ff_simple_idct44_add; From f9d3841ae6147eaa51c57c574cd81e9ce9566e3a Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Fri, 29 Dec 2017 15:42:14 +0000 Subject: [PATCH 2345/2557] mpeg4video: Add support for MPEG-4 Simple Studio Profile. This is a profile supporting > 8-bit video and has a higher quality DCT --- libavcodec/error_resilience.c | 3 +- libavcodec/h263dec.c | 11 + libavcodec/idctdsp.c | 12 +- libavcodec/ituh263dec.c | 17 +- libavcodec/mpeg12dec.c | 18 +- libavcodec/mpeg4data.h | 116 ++++++++ libavcodec/mpeg4video.h | 17 ++ libavcodec/mpeg4videodec.c | 536 +++++++++++++++++++++++++++++++++- libavcodec/mpegvideo.c | 52 +++- libavcodec/mpegvideo.h | 26 +- libavcodec/x86/idctdsp_init.c | 1 + 11 files changed, 763 insertions(+), 46 deletions(-) diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index 55f77961c51ea..25e54a535b720 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -814,7 +814,8 @@ static int er_supported(ERContext *s) { if(s->avctx->hwaccel && s->avctx->hwaccel->decode_slice || !s->cur_pic.f || - s->cur_pic.field_picture + s->cur_pic.field_picture || + s->avctx->profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO ) return 0; return 1; diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 5608b6324564f..484bf39578a0f 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -47,6 +47,12 @@ static enum AVPixelFormat h263_get_format(AVCodecContext *avctx) { + /* MPEG-4 Studio Profile only, not supported by hardware */ + if (avctx->bits_per_raw_sample > 8) { + av_assert1(avctx->profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO); + return avctx->pix_fmt; + } + if (avctx->codec->id == AV_CODEC_ID_MSS2) return AV_PIX_FMT_YUV420P; @@ -197,6 +203,11 @@ static int decode_slice(MpegEncContext *s) ff_set_qscale(s, s->qscale); + if (s->studio_profile) { + if ((ret = ff_mpeg4_decode_studio_slice_header(s->avctx->priv_data)) < 0) + return ret; + } + if (s->avctx->hwaccel) { const uint8_t *start = s->gb.buffer + get_bits_count(&s->gb) / 8; ret = s->avctx->hwaccel->decode_slice(s->avctx, start, s->gb.buffer_end - start); diff --git a/libavcodec/idctdsp.c b/libavcodec/idctdsp.c index 1de372d2b9e26..662033bd78076 100644 --- a/libavcodec/idctdsp.c +++ b/libavcodec/idctdsp.c @@ -256,9 +256,15 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) c->perm_type = FF_IDCT_PERM_NONE; } else { if (avctx->bits_per_raw_sample == 10 || avctx->bits_per_raw_sample == 9) { - c->idct_put = ff_simple_idct_put_int16_10bit; - c->idct_add = ff_simple_idct_add_int16_10bit; - c->idct = ff_simple_idct_int16_10bit; + /* 10-bit MPEG-4 Simple Studio Profile requires a higher precision IDCT + However, it only uses idct_put */ + if (avctx->codec_id == AV_CODEC_ID_MPEG4 && avctx->profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO) + c->idct_put = ff_simple_idct_put_int32_10bit; + else { + c->idct_put = ff_simple_idct_put_int16_10bit; + c->idct_add = ff_simple_idct_add_int16_10bit; + c->idct = ff_simple_idct_int16_10bit; + } c->perm_type = FF_IDCT_PERM_NONE; } else if (avctx->bits_per_raw_sample == 12) { c->idct_put = ff_simple_idct_put_int16_12bit; diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c index fc95a532ce794..1b57e53cad9ff 100644 --- a/libavcodec/ituh263dec.c +++ b/libavcodec/ituh263dec.c @@ -207,12 +207,27 @@ static int h263_decode_gob_header(MpegEncContext *s) } /** - * Decode the group of blocks / video packet header. + * Decode the group of blocks / video packet header / slice header (MPEG-4 Studio). * @return bit position of the resync_marker, or <0 if none was found */ int ff_h263_resync(MpegEncContext *s){ int left, pos, ret; + /* In MPEG-4 studio mode look for a new slice startcode + * and decode slice header */ + if(s->codec_id==AV_CODEC_ID_MPEG4 && s->studio_profile) { + align_get_bits(&s->gb); + + while (get_bits_left(&s->gb) >= 32 && show_bits_long(&s->gb, 32) != SLICE_START_CODE) { + get_bits(&s->gb, 8); + } + + if (show_bits_long(&s->gb, 32) == SLICE_START_CODE) + return get_bits_count(&s->gb); + else + return -1; + } + if(s->codec_id==AV_CODEC_ID_MPEG4){ skip_bits1(&s->gb); align_get_bits(&s->gb); diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 9e076e89daa73..83e537884b694 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -649,16 +649,6 @@ static inline int get_dmv(MpegEncContext *s) return 0; } -static inline int get_qscale(MpegEncContext *s) -{ - int qscale = get_bits(&s->gb, 5); - if (s->q_scale_type) - return ff_mpeg2_non_linear_qscale[qscale]; - else - return qscale << 1; -} - - /* motion type (for MPEG-2) */ #define MT_FIELD 1 #define MT_FRAME 2 @@ -751,7 +741,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) s->interlaced_dct = get_bits1(&s->gb); if (IS_QUANT(mb_type)) - s->qscale = get_qscale(s); + s->qscale = mpeg_get_qscale(s); if (s->concealment_motion_vectors) { /* just parse them */ @@ -819,7 +809,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) } if (IS_QUANT(mb_type)) - s->qscale = get_qscale(s); + s->qscale = mpeg_get_qscale(s); s->last_mv[0][0][0] = 0; s->last_mv[0][0][1] = 0; @@ -840,7 +830,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) } if (IS_QUANT(mb_type)) - s->qscale = get_qscale(s); + s->qscale = mpeg_get_qscale(s); /* motion vectors */ s->mv_dir = (mb_type >> 13) & 3; @@ -1728,7 +1718,7 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y, ff_mpeg1_clean_buffers(s); s->interlaced_dct = 0; - s->qscale = get_qscale(s); + s->qscale = mpeg_get_qscale(s); if (s->qscale == 0) { av_log(s->avctx, AV_LOG_ERROR, "qscale == 0\n"); diff --git a/libavcodec/mpeg4data.h b/libavcodec/mpeg4data.h index b7c3faba0d6dc..4756e9ea1d2b4 100644 --- a/libavcodec/mpeg4data.h +++ b/libavcodec/mpeg4data.h @@ -373,4 +373,120 @@ const uint8_t ff_mpeg4_dc_threshold[8]={ 99, 13, 15, 17, 19, 21, 23, 0 }; +/* Note these are different in studio mode */ +const uint16_t ff_mpeg4_studio_dc_luma[19][2]={ + {0x0e, 6}, {0x06, 5}, {0x00, 4}, {0x02, 4}, + {0x07, 3}, {0x05, 3}, {0x03, 3}, {0x02, 3}, + {0x04, 3}, {0x06, 3}, {0x01, 4}, {0x1e, 7}, + {0x3e, 8}, {0x7e, 9}, {0xfe, 10}, {0x1fe, 11}, + {0x3fe, 12}, {0x7fe, 13}, {0x7ff, 13} +}; + +const uint16_t ff_mpeg4_studio_dc_chroma[19][2]={ + {0x00, 4}, {0x02, 4}, {0x07, 3}, {0x05, 3}, + {0x03, 3}, {0x02, 3}, {0x04, 3}, {0x06, 3}, + {0x01, 4}, {0x06, 5}, {0x0e, 6}, {0x1e, 7}, + {0x3e, 8}, {0x7e, 9}, {0xfe, 10}, {0x1fe, 11}, + {0x3fe, 12}, {0x7fe, 13}, {0x7ff, 13} +}; + +const uint16_t ff_mpeg4_studio_intra[12][22][2]={ + { + {0x05, 4}, {0x04, 4}, {0x05, 7}, {0x09, 9}, + {0x21, 11}, {0x41, 12}, {0x81, 13}, {0x03, 4}, + {0x03, 5}, {0x05, 6}, {0x04, 7}, {0x03, 7}, + {0x05, 8}, {0x03, 2}, {0x05, 3}, {0x04, 3}, + {0x03, 3}, {0x02, 4}, {0x04, 6}, {0x03, 6}, + {0x11, 10}, {0x80, 13} + }, + { + {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, + {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, + {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, + {0x00, 0}, {0x00, 0}, {0x01, 1}, {0x01, 2}, + {0x01, 3}, {0x01, 4}, {0x01, 5}, {0x03, 7}, + {0x05, 8}, {0x04, 8} + }, + { + {0x05, 3}, {0x03, 5}, {0x02, 5}, {0x03, 7}, + {0x09, 9}, {0x103, 14}, {0x102, 14}, {0x04, 3}, + {0x03, 3}, {0x03, 4}, {0x02, 4}, {0x03, 6}, + {0x11, 10}, {0x03, 2}, {0x02, 3}, {0x02, 6}, + {0x05, 8}, {0x21, 11}, {0x83, 13}, {0x101, 14}, + {0x201, 15}, {0x82, 13} + }, + { + {0x05, 5}, {0x05, 4}, {0x04, 5}, {0x03, 6}, + {0x09, 9}, {0x83, 13}, {0x82, 13}, {0x03, 3}, + {0x04, 4}, {0x03, 4}, {0x03, 5}, {0x05, 8}, + {0x81, 13}, {0x03, 2}, {0x02, 2}, {0x02, 5}, + {0x02, 6}, {0x03, 7}, {0x11, 10}, {0x43, 12}, + {0x80, 13}, {0x42, 12} + }, + { + {0x05, 7}, {0x03, 4}, {0x03, 5}, {0x04, 7}, + {0x09, 9}, {0x83, 13}, {0x101, 14}, {0x03, 3}, + {0x02, 4}, {0x05, 6}, {0x03, 7}, {0x11, 10}, + {0x201, 15}, {0x03, 2}, {0x02, 2}, {0x02, 3}, + {0x04, 6}, {0x03, 6}, {0x05, 8}, {0x21, 11}, + {0x82, 13}, {0x81, 13} + }, + { + {0x13, 10}, {0x03, 5}, {0x05, 7}, {0x12, 10}, + {0x43, 12}, {0x83, 13}, {0x82, 13}, {0x02, 5}, + {0x04, 7}, {0x05, 8}, {0x23, 11}, {0x81, 13}, + {0x101, 14}, {0x03, 2}, {0x02, 2}, {0x01, 2}, + {0x01, 3}, {0x03, 6}, {0x03, 7}, {0x22, 11}, + {0x201, 15}, {0x42, 12} + }, + { + {0x23, 11}, {0x01, 4}, {0x07, 8}, {0x13, 10}, + {0x22, 11}, {0x103, 14}, {0x102, 14}, {0x03, 6}, + {0x06, 8}, {0x12, 10}, {0x43, 12}, {0x101, 14}, + {0x201, 15}, {0x03, 3}, {0x02, 3}, {0x03, 2}, + {0x02, 2}, {0x01, 3}, {0x02, 6}, {0x05, 8}, + {0x42, 12}, {0x41, 12} + }, + { + {0x0b, 9}, {0x03, 5}, {0x07, 8}, {0x07, 7}, + {0x06, 7}, {0x23, 11}, {0x41, 12}, {0x05, 7}, + {0x06, 8}, {0x0a, 9}, {0x13, 10}, {0x22, 11}, + {0x40, 12}, {0x03, 4}, {0x02, 4}, {0x03, 2}, + {0x02, 2}, {0x01, 2}, {0x02, 5}, {0x04, 7}, + {0x12, 10}, {0x21, 11} + }, + { + {0x15, 10}, {0x03, 6}, {0x14, 10}, {0x23, 11}, + {0x07, 8}, {0x43, 12}, {0x81, 13}, {0x06, 8}, + {0x0b, 9}, {0x13, 10}, {0x12, 10}, {0x42, 12}, + {0x80, 13}, {0x01, 4}, {0x03, 3}, {0x02, 3}, + {0x03, 2}, {0x02, 2}, {0x01, 3}, {0x02, 6}, + {0x22, 11}, {0x41, 12} + }, + { + {0x43, 12}, {0x05, 6}, {0x07, 8}, {0x04, 6}, + {0x03, 6}, {0x13, 10}, {0x42, 12}, {0x05, 7}, + {0x04, 7}, {0x06, 8}, {0x12, 10}, {0x41, 12}, + {0x40, 12}, {0x03, 5}, {0x03, 4}, {0x03, 3}, + {0x02, 3}, {0x03, 2}, {0x02, 2}, {0x02, 4}, + {0x05, 8}, {0x11, 10} + }, + { + {0x83, 13}, {0x05, 7}, {0x07, 8}, {0x03, 4}, + {0x21, 11}, {0x82, 13}, {0x81, 13}, {0x04, 7}, + {0x06, 8}, {0x0b, 9}, {0x0a, 9}, {0x11, 10}, + {0x80, 13}, {0x03, 5}, {0x02, 5}, {0x02, 4}, + {0x03, 3}, {0x02, 3}, {0x03, 2}, {0x02, 2}, + {0x03, 6}, {0x09, 9} + }, + { + {0x13, 10}, {0x03, 5}, {0x03, 6}, {0x0d, 9}, + {0x0c, 9}, {0x21, 11}, {0x20, 11}, {0x02, 5}, + {0x02, 6}, {0x07, 8}, {0x0b, 9}, {0x12, 10}, + {0x11, 10}, {0x05, 3}, {0x04, 3}, {0x05, 4}, + {0x04, 4}, {0x03, 4}, {0x02, 4}, {0x03, 3}, + {0x03, 2}, {0x0a, 9} + } +}; + #endif /* AVCODEC_MPEG4DATA_H */ diff --git a/libavcodec/mpeg4video.h b/libavcodec/mpeg4video.h index 6672c6dd66dbd..f9747928877ec 100644 --- a/libavcodec/mpeg4video.h +++ b/libavcodec/mpeg4video.h @@ -61,6 +61,10 @@ #define GOP_STARTCODE 0x1B3 #define VISUAL_OBJ_STARTCODE 0x1B5 #define VOP_STARTCODE 0x1B6 +#define SLICE_STARTCODE 0x1B7 +#define EXT_STARTCODE 0x1B8 + +#define QUANT_MATRIX_EXT_ID 0x3 /* smaller packets likely don't contain a real frame */ #define MAX_NVOP_SIZE 19 @@ -108,8 +112,16 @@ typedef struct Mpeg4DecContext { int cplx_estimation_trash_i; int cplx_estimation_trash_p; int cplx_estimation_trash_b; + + VLC studio_intra_tab[12]; + VLC studio_luma_dc; + VLC studio_chroma_dc; + + int rgb; } Mpeg4DecContext; +static const uint8_t mpeg4_block_count[4] = {0, 6, 8, 12}; + /* dc encoding for MPEG-4 */ extern const uint8_t ff_mpeg4_DCtab_lum[13][2]; extern const uint8_t ff_mpeg4_DCtab_chrom[13][2]; @@ -137,6 +149,10 @@ extern const uint16_t ff_mpeg4_resync_prefix[8]; extern const uint8_t ff_mpeg4_dc_threshold[8]; +extern const uint16_t ff_mpeg4_studio_dc_luma[19][2]; +extern const uint16_t ff_mpeg4_studio_dc_chroma[19][2]; +extern const uint16_t ff_mpeg4_studio_intra[12][22][2]; + void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y); @@ -155,6 +171,7 @@ void ff_clean_mpeg4_qscales(MpegEncContext *s); int ff_mpeg4_decode_partitions(Mpeg4DecContext *ctx); int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s); int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx); +int ff_mpeg4_decode_studio_slice_header(Mpeg4DecContext *ctx); void ff_mpeg4_init_direct_mv(MpegEncContext *s); void ff_mpeg4videodec_static_init(void); int ff_mpeg4_workaround_bugs(AVCodecContext *avctx); diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index a1117dc272d76..f53bd03bf127a 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -44,6 +44,7 @@ #define SPRITE_TRAJ_VLC_BITS 6 #define DC_VLC_BITS 9 #define MB_TYPE_B_VLC_BITS 4 +#define STUDIO_INTRA_BITS 9 static VLC dc_lum, dc_chrom; static VLC sprite_trajectory; @@ -528,6 +529,55 @@ int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx) return 0; } +static void reset_studio_dc_predictors(MpegEncContext *s) +{ + /* Reset DC Predictors */ + s->last_dc[0] = + s->last_dc[1] = + s->last_dc[2] = 1 << (s->avctx->bits_per_raw_sample + s->dct_precision + s->intra_dc_precision - 1); +} + +/** + * Decode the next video packet. + * @return <0 if something went wrong + */ +int ff_mpeg4_decode_studio_slice_header(Mpeg4DecContext *ctx) +{ + MpegEncContext *s = &ctx->m; + GetBitContext *gb = &s->gb; + unsigned vlc_len; + uint16_t mb_num; + + if (get_bits_left(gb) >= 32 && get_bits_long(gb, 32) == SLICE_START_CODE) { + vlc_len = av_log2(s->mb_width * s->mb_height) + 1; + mb_num = get_bits(gb, vlc_len); + + if (mb_num >= s->mb_num) + return AVERROR_INVALIDDATA; + + s->mb_x = mb_num % s->mb_width; + s->mb_y = mb_num / s->mb_width; + + if (ctx->shape != BIN_ONLY_SHAPE) + s->qscale = mpeg_get_qscale(s); + + if (get_bits1(gb)) { /* slice_extension_flag */ + skip_bits1(gb); /* intra_slice */ + skip_bits1(gb); /* slice_VOP_id_enable */ + skip_bits(gb, 6); /* slice_VOP_id */ + while (get_bits1(gb)) /* extra_bit_slice */ + skip_bits(gb, 8); /* extra_information_slice */ + } + + reset_studio_dc_predictors(s); + } + else { + return AVERROR_INVALIDDATA; + } + + return 0; +} + /** * Get the average motion vector for a GMC MB. * @param n either 0 for the x component or 1 for y @@ -1723,6 +1773,189 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) return SLICE_OK; } +/* As per spec, studio start code search isn't the same as the old type of start code */ +static void next_start_code_studio(GetBitContext *gb) +{ + align_get_bits(gb); + + while (get_bits_left(gb) >= 24 && show_bits_long(gb, 24) != 0x1) { + get_bits(gb, 8); + } +} + +/* additional_code, vlc index */ +static const uint8_t ac_state_tab[22][2] = +{ + {0, 0}, + {0, 1}, + {1, 1}, + {2, 1}, + {3, 1}, + {4, 1}, + {5, 1}, + {1, 2}, + {2, 2}, + {3, 2}, + {4, 2}, + {5, 2}, + {6, 2}, + {1, 3}, + {2, 4}, + {3, 5}, + {4, 6}, + {5, 7}, + {6, 8}, + {7, 9}, + {8, 10}, + {0, 11} +}; + +static int mpeg4_decode_studio_block(MpegEncContext *s, int32_t block[64], int n) +{ + Mpeg4DecContext *ctx = s->avctx->priv_data; + + int cc, dct_dc_size, dct_diff, code, j, idx = 1, group = 0, run = 0, + additional_code_len, sign, mismatch; + VLC *cur_vlc = &ctx->studio_intra_tab[0]; + uint8_t *const scantable = s->intra_scantable.permutated; + const uint16_t *quant_matrix; + uint32_t flc; + const int min = -1 * (1 << (s->avctx->bits_per_raw_sample + 6)); + const int max = ((1 << (s->avctx->bits_per_raw_sample + 6)) - 1); + + mismatch = 1; + + memset(block, 0, 64 * sizeof(int32_t)); + + if (n < 4) { + cc = 0; + dct_dc_size = get_vlc2(&s->gb, ctx->studio_luma_dc.table, STUDIO_INTRA_BITS, 2); + quant_matrix = s->intra_matrix; + } else { + cc = (n & 1) + 1; + if (ctx->rgb) + dct_dc_size = get_vlc2(&s->gb, ctx->studio_luma_dc.table, STUDIO_INTRA_BITS, 2); + else + dct_dc_size = get_vlc2(&s->gb, ctx->studio_chroma_dc.table, STUDIO_INTRA_BITS, 2); + quant_matrix = s->chroma_intra_matrix; + } + + if (dct_dc_size < 0) { + av_log(s->avctx, AV_LOG_ERROR, "illegal dct_dc_size vlc\n"); + return AVERROR_INVALIDDATA; + } else if (dct_dc_size == 0) { + dct_diff = 0; + } else { + dct_diff = get_xbits(&s->gb, dct_dc_size); + + if (dct_dc_size > 8) { + if(!check_marker(s->avctx, &s->gb, "dct_dc_size > 8")) + return AVERROR_INVALIDDATA; + } + + } + + s->last_dc[cc] += dct_diff; + + if (s->mpeg_quant) + block[0] = s->last_dc[cc] * (8 >> s->intra_dc_precision); + else + block[0] = s->last_dc[cc] * (8 >> s->intra_dc_precision) * (8 >> s->dct_precision); + /* TODO: support mpeg_quant for AC coefficients */ + + block[0] = av_clip(block[0], min, max); + mismatch ^= block[0]; + + /* AC Coefficients */ + while (1) { + group = get_vlc2(&s->gb, cur_vlc->table, STUDIO_INTRA_BITS, 2); + + if (group < 0) { + av_log(s->avctx, AV_LOG_ERROR, "illegal ac coefficient group vlc\n"); + return AVERROR_INVALIDDATA; + } + + additional_code_len = ac_state_tab[group][0]; + cur_vlc = &ctx->studio_intra_tab[ac_state_tab[group][1]]; + + if (group == 0) { + /* End of Block */ + break; + } else if (group >= 1 && group <= 6) { + /* Zero run length (Table B.47) */ + run = 1 << additional_code_len; + if (additional_code_len) + run += get_bits(&s->gb, additional_code_len); + idx += run; + continue; + } else if (group >= 7 && group <= 12) { + /* Zero run length and +/-1 level (Table B.48) */ + code = get_bits(&s->gb, additional_code_len); + sign = code & 1; + code >>= 1; + run = (1 << (additional_code_len - 1)) + code; + idx += run; + j = scantable[idx++]; + block[j] = sign ? 1 : -1; + } else if (group >= 13 && group <= 20) { + /* Level value (Table B.49) */ + j = scantable[idx++]; + block[j] = get_xbits(&s->gb, additional_code_len); + } else if (group == 21) { + /* Escape */ + j = scantable[idx++]; + additional_code_len = s->avctx->bits_per_raw_sample + s->dct_precision + 4; + flc = get_bits(&s->gb, additional_code_len); + if (flc >> (additional_code_len-1)) + block[j] = -1 * (( flc ^ ((1 << additional_code_len) -1)) + 1); + else + block[j] = flc; + } + block[j] = ((8 * 2 * block[j] * quant_matrix[j] * s->qscale) >> s->dct_precision) / 32; + block[j] = av_clip(block[j], min, max); + mismatch ^= block[j]; + } + + block[63] ^= mismatch & 1; + + return 0; +} + +static int mpeg4_decode_studio_mb(MpegEncContext *s, int16_t block_[12][64]) +{ + int i; + + /* StudioMacroblock */ + /* Assumes I-VOP */ + s->mb_intra = 1; + if (get_bits1(&s->gb)) { /* compression_mode */ + /* DCT */ + /* macroblock_type, 1 or 2-bit VLC */ + if (!get_bits1(&s->gb)) { + skip_bits1(&s->gb); + s->qscale = mpeg_get_qscale(s); + } + + for (i = 0; i < mpeg4_block_count[s->chroma_format]; i++) { + if (mpeg4_decode_studio_block(s, (*s->block32)[i], i) < 0) + return AVERROR_INVALIDDATA; + } + } else { + /* DPCM */ + check_marker(s->avctx, &s->gb, "DPCM block start"); + avpriv_request_sample(s->avctx, "DPCM encoded block"); + next_start_code_studio(&s->gb); + return SLICE_ERROR; + } + + if (get_bits_left(&s->gb) >= 24 && show_bits(&s->gb, 23) == 0) { + next_start_code_studio(&s->gb); + return SLICE_END; + } + + return SLICE_OK; +} + static int mpeg4_decode_gop_header(MpegEncContext *s, GetBitContext *gb) { int hours, minutes, seconds; @@ -1791,6 +2024,23 @@ static int mpeg4_decode_visual_object(MpegEncContext *s, GetBitContext *gb) return 0; } +static void mpeg4_load_default_matrices(MpegEncContext *s) +{ + int i, v; + + /* load default matrices */ + for (i = 0; i < 64; i++) { + int j = s->idsp.idct_permutation[i]; + v = ff_mpeg4_default_intra_matrix[i]; + s->intra_matrix[j] = v; + s->chroma_intra_matrix[j] = v; + + v = ff_mpeg4_default_non_intra_matrix[i]; + s->inter_matrix[j] = v; + s->chroma_inter_matrix[j] = v; + } +} + static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) { MpegEncContext *s = &ctx->m; @@ -1954,17 +2204,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) if ((s->mpeg_quant = get_bits1(gb))) { /* vol_quant_type */ int i, v; - /* load default matrixes */ - for (i = 0; i < 64; i++) { - int j = s->idsp.idct_permutation[i]; - v = ff_mpeg4_default_intra_matrix[i]; - s->intra_matrix[j] = v; - s->chroma_intra_matrix[j] = v; - - v = ff_mpeg4_default_non_intra_matrix[i]; - s->inter_matrix[j] = v; - s->chroma_inter_matrix[j] = v; - } + mpeg4_load_default_matrices(s); /* load custom intra matrix */ if (get_bits1(gb)) { @@ -2608,6 +2848,232 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) return 0; } +static void read_quant_matrix_ext(MpegEncContext *s, GetBitContext *gb) +{ + int i, j, v; + + if (get_bits1(gb)) { + /* intra_quantiser_matrix */ + for (i = 0; i < 64; i++) { + v = get_bits(gb, 8); + j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; + s->intra_matrix[j] = v; + s->chroma_intra_matrix[j] = v; + } + } + + if (get_bits1(gb)) { + /* non_intra_quantiser_matrix */ + for (i = 0; i < 64; i++) { + get_bits(gb, 8); + } + } + + if (get_bits1(gb)) { + /* chroma_intra_quantiser_matrix */ + for (i = 0; i < 64; i++) { + v = get_bits(gb, 8); + j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; + s->chroma_intra_matrix[j] = v; + } + } + + if (get_bits1(gb)) { + /* chroma_non_intra_quantiser_matrix */ + for (i = 0; i < 64; i++) { + get_bits(gb, 8); + } + } + + next_start_code_studio(gb); +} + +static void extension_and_user_data(MpegEncContext *s, GetBitContext *gb, int id) +{ + uint32_t startcode; + uint8_t extension_type; + + startcode = show_bits_long(gb, 32); + if (startcode == USER_DATA_STARTCODE || startcode == EXT_STARTCODE) { + + if ((id == 2 || id == 4) && startcode == EXT_STARTCODE) { + skip_bits_long(gb, 32); + extension_type = get_bits(gb, 4); + if (extension_type == QUANT_MATRIX_EXT_ID) + read_quant_matrix_ext(s, gb); + } + } +} + +static void decode_smpte_tc(Mpeg4DecContext *ctx, GetBitContext *gb) +{ + MpegEncContext *s = &ctx->m; + + skip_bits(gb, 16); /* Time_code[63..48] */ + check_marker(s->avctx, gb, "after Time_code[63..48]"); + skip_bits(gb, 16); /* Time_code[47..32] */ + check_marker(s->avctx, gb, "after Time_code[47..32]"); + skip_bits(gb, 16); /* Time_code[31..16] */ + check_marker(s->avctx, gb, "after Time_code[31..16]"); + skip_bits(gb, 16); /* Time_code[15..0] */ + check_marker(s->avctx, gb, "after Time_code[15..0]"); + skip_bits(gb, 4); /* reserved_bits */ +} + +/** + * Decode the next studio vop header. + * @return <0 if something went wrong + */ +static int decode_studio_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) +{ + MpegEncContext *s = &ctx->m; + + if (get_bits_left(gb) <= 32) + return 0; + + if (get_bits_long(gb, 32) != VOP_STARTCODE) + return AVERROR_INVALIDDATA; + + s->decode_mb = mpeg4_decode_studio_mb; + + decode_smpte_tc(ctx, gb); + + skip_bits(gb, 10); /* temporal_reference */ + skip_bits(gb, 2); /* vop_structure */ + s->pict_type = get_bits(gb, 2) + AV_PICTURE_TYPE_I; /* vop_coding_type */ + if (get_bits1(gb)) { /* vop_coded */ + skip_bits1(gb); /* top_field_first */ + skip_bits1(gb); /* repeat_first_field */ + s->progressive_frame = get_bits1(gb) ^ 1; /* progressive_frame */ + } + + if (s->pict_type == AV_PICTURE_TYPE_I) { + if (get_bits1(gb)) + reset_studio_dc_predictors(s); + } + + if (ctx->shape != BIN_ONLY_SHAPE) { + s->alternate_scan = get_bits1(gb); + s->frame_pred_frame_dct = get_bits1(gb); + s->dct_precision = get_bits(gb, 2); + s->intra_dc_precision = get_bits(gb, 2); + s->q_scale_type = get_bits1(gb); + } + + if (s->alternate_scan) { + ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); + } else { + ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_zigzag_direct); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, ff_alternate_horizontal_scan); + ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); + } + + mpeg4_load_default_matrices(s); + + next_start_code_studio(gb); + extension_and_user_data(s, gb, 4); + + return 0; +} + +static int decode_studiovisualobject(Mpeg4DecContext *ctx, GetBitContext *gb) +{ + uint32_t startcode; + MpegEncContext *s = &ctx->m; + int visual_object_type, width, height; + + startcode = get_bits_long(gb, 32); + + /* StudioVisualObject() */ + if (startcode == VISUAL_OBJ_STARTCODE) { + skip_bits(gb, 4); /* visual_object_verid */ + visual_object_type = get_bits(gb, 4); + + next_start_code_studio(gb); + extension_and_user_data(s, gb, 1); + + if (visual_object_type == VOT_VIDEO_ID) { + /* StudioVideoObjectLayer */ + skip_bits_long(gb, 32); /* video_object_start_code */ + skip_bits_long(gb, 32); /* video_object_layer_start_code */ + skip_bits1(gb); /* random_accessible_vol */ + skip_bits(gb, 8); /* video_object_type_indication */ + skip_bits(gb, 4); /* video_object_layer_verid */ + ctx->shape = get_bits(gb, 2); /* video_object_layer_shape */ + skip_bits(gb, 4); /* video_object_layer_shape_extension */ + skip_bits1(gb); /* progressive_sequence */ + if (ctx->shape != BIN_ONLY_SHAPE) { + ctx->rgb = get_bits1(gb); /* rgb_components */ + s->chroma_format = get_bits(gb, 2); /* chroma_format */ + if (!s->chroma_format) { + av_log(s->avctx, AV_LOG_ERROR, "illegal chroma format\n"); + return AVERROR_INVALIDDATA; + } + + s->avctx->bits_per_raw_sample = get_bits(gb, 4); /* bit_depth */ + if (s->avctx->bits_per_raw_sample == 10) { + if (ctx->rgb) { + s->avctx->pix_fmt = AV_PIX_FMT_GBRP10; + } + else { + s->avctx->pix_fmt = s->chroma_format == CHROMA_422 ? AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_YUV444P10; + } + } + else { + avpriv_request_sample(s->avctx, "MPEG-4 Studio profile bit-depth %u", s->avctx->bits_per_raw_sample); + return AVERROR_PATCHWELCOME; + } + } + if (ctx->shape == RECT_SHAPE) { + check_marker(s->avctx, gb, "before video_object_layer_width"); + width = get_bits(gb, 14); /* video_object_layer_width */ + check_marker(s->avctx, gb, "before video_object_layer_height"); + height = get_bits(gb, 14); /* video_object_layer_height */ + check_marker(s->avctx, gb, "after video_object_layer_height"); + + /* Do the same check as non-studio profile */ + if (width && height) { + if (s->width && s->height && + (s->width != width || s->height != height)) + s->context_reinit = 1; + s->width = width; + s->height = height; + } + } + s->aspect_ratio_info = get_bits(gb, 4); + if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) { + s->avctx->sample_aspect_ratio.num = get_bits(gb, 8); // par_width + s->avctx->sample_aspect_ratio.den = get_bits(gb, 8); // par_height + } else { + s->avctx->sample_aspect_ratio = ff_h263_pixel_aspect[s->aspect_ratio_info]; + } + skip_bits(gb, 4); /* frame_rate_code */ + skip_bits(gb, 15); /* first_half_bit_rate */ + check_marker(s->avctx, gb, "after first_half_bit_rate"); + skip_bits(gb, 15); /* latter_half_bit_rate */ + check_marker(s->avctx, gb, "after latter_half_bit_rate"); + skip_bits(gb, 15); /* first_half_vbv_buffer_size */ + check_marker(s->avctx, gb, "after first_half_vbv_buffer_size"); + skip_bits(gb, 3); /* latter_half_vbv_buffer_size */ + skip_bits(gb, 11); /* first_half_vbv_buffer_size */ + check_marker(s->avctx, gb, "after first_half_vbv_buffer_size"); + skip_bits(gb, 15); /* latter_half_vbv_occupancy */ + check_marker(s->avctx, gb, "after latter_half_vbv_occupancy"); + s->low_delay = get_bits1(gb); + s->mpeg_quant = get_bits1(gb); /* mpeg2_stream */ + + next_start_code_studio(gb); + extension_and_user_data(s, gb, 2); + } + } + + return 0; +} + /** * Decode MPEG-4 headers. * @return <0 if no VOP found (or a damaged one) @@ -2721,6 +3187,16 @@ int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb) mpeg4_decode_gop_header(s, gb); } else if (startcode == VOS_STARTCODE) { mpeg4_decode_profile_level(s, gb); + if (s->avctx->profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO && + (s->avctx->level > 0 && s->avctx->level < 9)) { + s->studio_profile = 1; + next_start_code_studio(gb); + extension_and_user_data(s, gb, 0); + + if ((ret = decode_studiovisualobject(ctx, gb)) < 0) + return ret; + break; + } } else if (startcode == VISUAL_OBJ_STARTCODE) { mpeg4_decode_visual_object(s, gb); } else if (startcode == VOP_STARTCODE) { @@ -2736,7 +3212,10 @@ int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb) s->low_delay = 1; s->avctx->has_b_frames = !s->low_delay; - return decode_vop_header(ctx, gb); + if (s->studio_profile) + return decode_studio_vop_header(ctx, gb); + else + return decode_vop_header(ctx, gb); } av_cold void ff_mpeg4videodec_static_init(void) { @@ -2836,6 +3315,37 @@ static int mpeg4_update_thread_context(AVCodecContext *dst, } #endif +static av_cold int init_studio_vlcs(Mpeg4DecContext *ctx) +{ + int i, ret; + + for (i = 0; i < 12; i++) { + ret = init_vlc(&ctx->studio_intra_tab[i], STUDIO_INTRA_BITS, 22, + &ff_mpeg4_studio_intra[i][0][1], 4, 2, + &ff_mpeg4_studio_intra[i][0][0], 4, 2, + 0); + + if (ret < 0) + return ret; + } + + ret = init_vlc(&ctx->studio_luma_dc, STUDIO_INTRA_BITS, 19, + &ff_mpeg4_studio_dc_luma[0][1], 4, 2, + &ff_mpeg4_studio_dc_luma[0][0], 4, 2, + 0); + if (ret < 0) + return ret; + + ret = init_vlc(&ctx->studio_chroma_dc, STUDIO_INTRA_BITS, 19, + &ff_mpeg4_studio_dc_chroma[0][1], 4, 2, + &ff_mpeg4_studio_dc_chroma[0][0], 4, 2, + 0); + if (ret < 0) + return ret; + + return 0; +} + static av_cold int decode_init(AVCodecContext *avctx) { Mpeg4DecContext *ctx = avctx->priv_data; @@ -2851,6 +3361,8 @@ static av_cold int decode_init(AVCodecContext *avctx) return ret; ff_mpeg4videodec_static_init(); + if ((ret = init_studio_vlcs(ctx)) < 0) + return ret; s->h263_pred = 1; s->low_delay = 0; /* default, might be overridden in the vol header during header parsing */ diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 18c3a87edaa13..45ea0f09e9cb1 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -386,6 +386,9 @@ static int init_duplicate_context(MpegEncContext *s) for (i = 0; i < 12; i++) { s->pblocks[i] = &s->block[i]; } + + FF_ALLOCZ_OR_GOTO(s->avctx, s->block32, sizeof(*s->block32), fail) + if (s->avctx->codec_tag == AV_RL32("VCR2")) { // exchange uv FFSWAP(void *, s->pblocks[4], s->pblocks[5]); @@ -421,6 +424,7 @@ static void free_duplicate_context(MpegEncContext *s) av_freep(&s->me.map); av_freep(&s->me.score_map); av_freep(&s->blocks); + av_freep(&s->block32); av_freep(&s->ac_val_base); s->block = NULL; } @@ -438,6 +442,7 @@ static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src) COPY(me.score_map); COPY(blocks); COPY(block); + COPY(block32); COPY(start_mb_y); COPY(end_mb_y); COPY(me.map_generation); @@ -811,6 +816,7 @@ static void clear_context(MpegEncContext *s) s->dct_error_sum = NULL; s->block = NULL; s->blocks = NULL; + s->block32 = NULL; memset(s->pblocks, 0, sizeof(s->pblocks)); s->ac_val_base = NULL; s->ac_val[0] = @@ -2120,8 +2126,31 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], ff_wmv2_add_mb(s, block, dest_y, dest_cb, dest_cr); } } else { + /* Only MPEG-4 Simple Studio Profile is supported in > 8-bit mode. + TODO: Integrate 10-bit properly into mpegvideo.c so that ER works properly */ + if (s->avctx->bits_per_raw_sample > 8){ + const int act_block_size = block_size * 2; + s->idsp.idct_put(dest_y, dct_linesize, (int16_t*)(*s->block32)[0]); + s->idsp.idct_put(dest_y + act_block_size, dct_linesize, (int16_t*)(*s->block32)[1]); + s->idsp.idct_put(dest_y + dct_offset, dct_linesize, (int16_t*)(*s->block32)[2]); + s->idsp.idct_put(dest_y + dct_offset + act_block_size, dct_linesize, (int16_t*)(*s->block32)[3]); + + dct_linesize = uvlinesize << s->interlaced_dct; + dct_offset = s->interlaced_dct ? uvlinesize : uvlinesize*block_size; + + s->idsp.idct_put(dest_cb, dct_linesize, (int16_t*)(*s->block32)[4]); + s->idsp.idct_put(dest_cr, dct_linesize, (int16_t*)(*s->block32)[5]); + s->idsp.idct_put(dest_cb + dct_offset, dct_linesize, (int16_t*)(*s->block32)[6]); + s->idsp.idct_put(dest_cr + dct_offset, dct_linesize, (int16_t*)(*s->block32)[7]); + if(!s->chroma_x_shift){//Chroma444 + s->idsp.idct_put(dest_cb + act_block_size, dct_linesize, (int16_t*)(*s->block32)[8]); + s->idsp.idct_put(dest_cr + act_block_size, dct_linesize, (int16_t*)(*s->block32)[9]); + s->idsp.idct_put(dest_cb + act_block_size + dct_offset, dct_linesize, (int16_t*)(*s->block32)[10]); + s->idsp.idct_put(dest_cr + act_block_size + dct_offset, dct_linesize, (int16_t*)(*s->block32)[11]); + } + } /* dct only in intra block */ - if(s->encoding || !(s->codec_id==AV_CODEC_ID_MPEG1VIDEO || s->codec_id==AV_CODEC_ID_MPEG2VIDEO)){ + else if(s->encoding || !(s->codec_id==AV_CODEC_ID_MPEG1VIDEO || s->codec_id==AV_CODEC_ID_MPEG2VIDEO)){ put_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale); put_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale); put_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize, s->qscale); @@ -2202,7 +2231,8 @@ void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h) void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename const int linesize = s->current_picture.f->linesize[0]; //not s->linesize as this would be wrong for field pics const int uvlinesize = s->current_picture.f->linesize[1]; - const int mb_size= 4 - s->avctx->lowres; + const int width_of_mb = (4 + (s->avctx->bits_per_raw_sample > 8)) - s->avctx->lowres; + const int height_of_mb = 4 - s->avctx->lowres; s->block_index[0]= s->b8_stride*(s->mb_y*2 ) - 2 + s->mb_x*2; s->block_index[1]= s->b8_stride*(s->mb_y*2 ) - 1 + s->mb_x*2; @@ -2212,20 +2242,20 @@ void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename s->block_index[5]= s->mb_stride*(s->mb_y + s->mb_height + 2) + s->b8_stride*s->mb_height*2 + s->mb_x - 1; //block_index is not used by mpeg2, so it is not affected by chroma_format - s->dest[0] = s->current_picture.f->data[0] + (int)((s->mb_x - 1U) << mb_size); - s->dest[1] = s->current_picture.f->data[1] + (int)((s->mb_x - 1U) << (mb_size - s->chroma_x_shift)); - s->dest[2] = s->current_picture.f->data[2] + (int)((s->mb_x - 1U) << (mb_size - s->chroma_x_shift)); + s->dest[0] = s->current_picture.f->data[0] + (int)((s->mb_x - 1U) << width_of_mb); + s->dest[1] = s->current_picture.f->data[1] + (int)((s->mb_x - 1U) << (width_of_mb - s->chroma_x_shift)); + s->dest[2] = s->current_picture.f->data[2] + (int)((s->mb_x - 1U) << (width_of_mb - s->chroma_x_shift)); if(!(s->pict_type==AV_PICTURE_TYPE_B && s->avctx->draw_horiz_band && s->picture_structure==PICT_FRAME)) { if(s->picture_structure==PICT_FRAME){ - s->dest[0] += s->mb_y * linesize << mb_size; - s->dest[1] += s->mb_y * uvlinesize << (mb_size - s->chroma_y_shift); - s->dest[2] += s->mb_y * uvlinesize << (mb_size - s->chroma_y_shift); + s->dest[0] += s->mb_y * linesize << height_of_mb; + s->dest[1] += s->mb_y * uvlinesize << (height_of_mb - s->chroma_y_shift); + s->dest[2] += s->mb_y * uvlinesize << (height_of_mb - s->chroma_y_shift); }else{ - s->dest[0] += (s->mb_y>>1) * linesize << mb_size; - s->dest[1] += (s->mb_y>>1) * uvlinesize << (mb_size - s->chroma_y_shift); - s->dest[2] += (s->mb_y>>1) * uvlinesize << (mb_size - s->chroma_y_shift); + s->dest[0] += (s->mb_y>>1) * linesize << height_of_mb; + s->dest[1] += (s->mb_y>>1) * uvlinesize << (height_of_mb - s->chroma_y_shift); + s->dest[2] += (s->mb_y>>1) * uvlinesize << (height_of_mb - s->chroma_y_shift); av_assert1((s->mb_y&1) == (s->picture_structure == PICT_BOTTOM_FIELD)); } } diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index e800e4a3b8d08..541909cbb185a 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -45,6 +45,7 @@ #include "mpegpicture.h" #include "mpegvideodsp.h" #include "mpegvideoencdsp.h" +#include "mpegvideodata.h" #include "pixblockdsp.h" #include "put_bits.h" #include "ratecontrol.h" @@ -71,6 +72,8 @@ #define SLICE_MAX_START_CODE 0x000001af #define EXT_START_CODE 0x000001b5 #define USER_START_CODE 0x000001b2 +#define SLICE_START_CODE 0x000001b7 + /** * MpegEncContext. @@ -378,6 +381,8 @@ typedef struct MpegEncContext { int custom_pcf; /* MPEG-4 specific */ + int studio_profile; + int dct_precision; ///< number of bits to represent the fractional part of time (encoder only) int time_increment_bits; int last_time_base; @@ -501,7 +506,10 @@ typedef struct MpegEncContext { int16_t (*block)[64]; ///< points to one of the following blocks int16_t (*blocks)[12][64]; // for HQ mode we need to keep the best block - int (*decode_mb)(struct MpegEncContext *s, int16_t block[6][64]); // used by some codecs to avoid a switch() + int (*decode_mb)(struct MpegEncContext *s, int16_t block[12][64]); // used by some codecs to avoid a switch() + + int32_t (*block32)[12][64]; + #define SLICE_OK 0 #define SLICE_ERROR -1 #define SLICE_END -2 ///> s->avctx->lowres; + const int bytes_per_pixel = 1 + (s->avctx->bits_per_raw_sample > 8); + const int block_size= (8*bytes_per_pixel) >> s->avctx->lowres; s->block_index[0]+=2; s->block_index[1]+=2; @@ -738,8 +747,8 @@ static inline void ff_update_block_index(MpegEncContext *s){ s->block_index[4]++; s->block_index[5]++; s->dest[0]+= 2*block_size; - s->dest[1]+= block_size; - s->dest[2]+= block_size; + s->dest[1]+= (2 >> s->chroma_x_shift) * block_size; + s->dest[2]+= (2 >> s->chroma_x_shift) * block_size; } static inline int get_bits_diff(MpegEncContext *s){ @@ -751,4 +760,13 @@ static inline int get_bits_diff(MpegEncContext *s){ return bits - last; } +static inline int mpeg_get_qscale(MpegEncContext *s) +{ + int qscale = get_bits(&s->gb, 5); + if (s->q_scale_type) + return ff_mpeg2_non_linear_qscale[qscale]; + else + return qscale << 1; +} + #endif /* AVCODEC_MPEGVIDEO_H */ diff --git a/libavcodec/x86/idctdsp_init.c b/libavcodec/x86/idctdsp_init.c index 162560d4114d7..9103b92ce7aea 100644 --- a/libavcodec/x86/idctdsp_init.c +++ b/libavcodec/x86/idctdsp_init.c @@ -123,6 +123,7 @@ av_cold void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx, } if (avctx->bits_per_raw_sample == 10 && + avctx->codec_id != AV_CODEC_ID_MPEG4 && (avctx->idct_algo == FF_IDCT_AUTO || avctx->idct_algo == FF_IDCT_SIMPLEAUTO || avctx->idct_algo == FF_IDCT_SIMPLE)) { From 324954cf960eb098929f4c610f60f5e1547609f6 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 2 Apr 2018 16:03:03 +0200 Subject: [PATCH 2346/2557] avcodec/scpr: fix decoding of prev+top-topleft prediction in keyframes Signed-off-by: Paul B Mahol --- libavcodec/scpr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/scpr.c b/libavcodec/scpr.c index 3c797d55f5267..72f59d5917142 100644 --- a/libavcodec/scpr.c +++ b/libavcodec/scpr.c @@ -446,13 +446,13 @@ static int decompress_i(AVCodecContext *avctx, uint32_t *dst, int linesize) } r = odst[(ly * linesize + lx) * 4] + - odst[((y * linesize + x) + off - z) * 4 + 4] - + odst[((y * linesize + x) + off) * 4 + 4] - odst[((y * linesize + x) + off - z) * 4]; g = odst[(ly * linesize + lx) * 4 + 1] + - odst[((y * linesize + x) + off - z) * 4 + 5] - + odst[((y * linesize + x) + off) * 4 + 5] - odst[((y * linesize + x) + off - z) * 4 + 1]; b = odst[(ly * linesize + lx) * 4 + 2] + - odst[((y * linesize + x) + off - z) * 4 + 6] - + odst[((y * linesize + x) + off) * 4 + 6] - odst[((y * linesize + x) + off - z) * 4 + 2]; clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF); dst[y * linesize + x] = clr; From 5710fdaeae09529282862c984317bd9347d0865d Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 30 Mar 2018 21:08:47 +0200 Subject: [PATCH 2347/2557] avcodec/aic: fix decoding of videos which height is not multiple of 16 Fate output changes and under close inspection looks more correct. Fixes #6187. Signed-off-by: Paul B Mahol --- libavcodec/aic.c | 14 ++++- tests/ref/fate/aic | 30 +++++----- tests/ref/fate/aic-oddsize | 114 ++++++++++++++++++------------------- 3 files changed, 84 insertions(+), 74 deletions(-) diff --git a/libavcodec/aic.c b/libavcodec/aic.c index 67d78c5ddd260..9c6f806655e3e 100644 --- a/libavcodec/aic.c +++ b/libavcodec/aic.c @@ -308,6 +308,8 @@ static int aic_decode_slice(AICContext *ctx, int mb_x, int mb_y, GetBitContext gb; int ret, i, mb, blk; int slice_width = FFMIN(ctx->slice_width, ctx->mb_width - mb_x); + int last_row = mb_y && mb_y == ctx->mb_height - 1; + int y_pos, c_pos; uint8_t *Y, *C[2]; uint8_t *dst; int16_t *base_y = ctx->data_ptr[COEFF_LUMA]; @@ -316,10 +318,18 @@ static int aic_decode_slice(AICContext *ctx, int mb_x, int mb_y, int16_t *ext_c = ctx->data_ptr[COEFF_CHROMA_EXT]; const int ystride = ctx->frame->linesize[0]; - Y = ctx->frame->data[0] + mb_x * 16 + mb_y * 16 * ystride; + if (last_row) { + y_pos = (ctx->avctx->height - 16); + c_pos = ((ctx->avctx->height+1)/2 - 8); + } else { + y_pos = mb_y * 16; + c_pos = mb_y * 8; + } + + Y = ctx->frame->data[0] + mb_x * 16 + y_pos * ystride; for (i = 0; i < 2; i++) C[i] = ctx->frame->data[i + 1] + mb_x * 8 - + mb_y * 8 * ctx->frame->linesize[i + 1]; + + c_pos * ctx->frame->linesize[i + 1]; init_get_bits(&gb, src, src_size * 8); memset(ctx->slice_data, 0, diff --git a/tests/ref/fate/aic b/tests/ref/fate/aic index 1f50350b967f1..244ea259677b2 100644 --- a/tests/ref/fate/aic +++ b/tests/ref/fate/aic @@ -3,18 +3,18 @@ #codec_id 0: rawvideo #dimensions 0: 1440x1080 #sar 0: 4/3 -0, 0, 0, 1, 2332800, 0xd941b42f -0, 1, 1, 1, 2332800, 0xd941b42f -0, 2, 2, 1, 2332800, 0xae0f5983 -0, 3, 3, 1, 2332800, 0x51cfc127 -0, 4, 4, 1, 2332800, 0x24d40447 -0, 5, 5, 1, 2332800, 0x858a9f51 -0, 6, 6, 1, 2332800, 0x533b48e8 -0, 7, 7, 1, 2332800, 0x2fd73267 -0, 8, 8, 1, 2332800, 0x153566c7 -0, 9, 9, 1, 2332800, 0xa1c49c45 -0, 10, 10, 1, 2332800, 0xb966e25a -0, 11, 11, 1, 2332800, 0xd0ce5985 -0, 12, 12, 1, 2332800, 0x0029a52e -0, 13, 13, 1, 2332800, 0x893116c5 -0, 14, 14, 1, 2332800, 0x073d2491 +0, 0, 0, 1, 2332800, 0xc22b8485 +0, 1, 1, 1, 2332800, 0xc22b8485 +0, 2, 2, 1, 2332800, 0xe0c21bd8 +0, 3, 3, 1, 2332800, 0x3e1a8fa0 +0, 4, 4, 1, 2332800, 0xbcb3f235 +0, 5, 5, 1, 2332800, 0x1a7cabd6 +0, 6, 6, 1, 2332800, 0xc0136ba8 +0, 7, 7, 1, 2332800, 0x295e59a6 +0, 8, 8, 1, 2332800, 0xf9c09288 +0, 9, 9, 1, 2332800, 0x0518cc8f +0, 10, 10, 1, 2332800, 0x9ad3068e +0, 11, 11, 1, 2332800, 0x5a8b7af1 +0, 12, 12, 1, 2332800, 0x7b35a8fa +0, 13, 13, 1, 2332800, 0xbe5801eb +0, 14, 14, 1, 2332800, 0x31ca019f diff --git a/tests/ref/fate/aic-oddsize b/tests/ref/fate/aic-oddsize index 3763e32b2cb29..be4346a20436e 100644 --- a/tests/ref/fate/aic-oddsize +++ b/tests/ref/fate/aic-oddsize @@ -3,60 +3,60 @@ #codec_id 0: rawvideo #dimensions 0: 481x241 #sar 0: 0/1 -0, 0, 0, 1, 174243, 0xa40491e1 -0, 1, 1, 1, 174243, 0xa12cbb56 -0, 2, 2, 1, 174243, 0xa12cbb56 -0, 3, 3, 1, 174243, 0xa12cbb56 -0, 4, 4, 1, 174243, 0xa12cbb56 -0, 5, 5, 1, 174243, 0xa12cbb56 -0, 6, 6, 1, 174243, 0xa12cbb56 -0, 7, 7, 1, 174243, 0xa12cbb56 -0, 8, 8, 1, 174243, 0xa12cbb56 -0, 9, 9, 1, 174243, 0x4e7b7299 -0, 10, 10, 1, 174243, 0x31573b99 -0, 11, 11, 1, 174243, 0x013397b6 -0, 12, 12, 1, 174243, 0xdd988ab8 -0, 13, 13, 1, 174243, 0xd6d96b1e -0, 14, 14, 1, 174243, 0xd6d96b1e -0, 15, 15, 1, 174243, 0xd6d96b1e -0, 16, 16, 1, 174243, 0x111627d3 -0, 17, 17, 1, 174243, 0x284d9ab7 -0, 18, 18, 1, 174243, 0xa348c492 -0, 19, 19, 1, 174243, 0xa348c492 -0, 20, 20, 1, 174243, 0xa348c492 -0, 21, 21, 1, 174243, 0xa348c492 -0, 22, 22, 1, 174243, 0x2d22c3b8 -0, 23, 23, 1, 174243, 0x2d22c3b8 -0, 24, 24, 1, 174243, 0x2d22c3b8 -0, 25, 25, 1, 174243, 0x2d22c3b8 -0, 26, 26, 1, 174243, 0xa6d7c890 -0, 27, 27, 1, 174243, 0x8068bfbb -0, 28, 28, 1, 174243, 0x420ae647 -0, 29, 29, 1, 174243, 0xc5467756 -0, 30, 30, 1, 174243, 0x238a13dd -0, 31, 31, 1, 174243, 0x5bab75dc -0, 32, 32, 1, 174243, 0x14d7f61f -0, 33, 33, 1, 174243, 0x2e1d334f -0, 34, 34, 1, 174243, 0xeade7dc0 -0, 35, 35, 1, 174243, 0xeade7dc0 -0, 36, 36, 1, 174243, 0xeade7dc0 -0, 37, 37, 1, 174243, 0xeade7dc0 -0, 38, 38, 1, 174243, 0x088c7ef9 -0, 39, 39, 1, 174243, 0x70a3554e -0, 40, 40, 1, 174243, 0x0753d1d4 -0, 41, 41, 1, 174243, 0x8266bd6d -0, 42, 42, 1, 174243, 0x4ce3cda9 -0, 43, 43, 1, 174243, 0x4ce3cda9 -0, 44, 44, 1, 174243, 0x4ce3cda9 -0, 45, 45, 1, 174243, 0x4ce3cda9 -0, 46, 46, 1, 174243, 0xe5f7cd98 -0, 47, 47, 1, 174243, 0xe5f7cd98 -0, 48, 48, 1, 174243, 0xe5f7cd98 -0, 49, 49, 1, 174243, 0xe5f7cd98 -0, 50, 50, 1, 174243, 0x78c5cdb7 -0, 51, 51, 1, 174243, 0x78c5cdb7 -0, 52, 52, 1, 174243, 0x78c5cdb7 -0, 53, 53, 1, 174243, 0xce7ccd92 -0, 54, 54, 1, 174243, 0xce7ccd92 -0, 55, 55, 1, 174243, 0xce7ccd92 -0, 56, 56, 1, 174243, 0xce7ccd92 +0, 0, 0, 1, 174243, 0x15ab835b +0, 1, 1, 1, 174243, 0x12d3acd0 +0, 2, 2, 1, 174243, 0x12d3acd0 +0, 3, 3, 1, 174243, 0x12d3acd0 +0, 4, 4, 1, 174243, 0x12d3acd0 +0, 5, 5, 1, 174243, 0x12d3acd0 +0, 6, 6, 1, 174243, 0x12d3acd0 +0, 7, 7, 1, 174243, 0x12d3acd0 +0, 8, 8, 1, 174243, 0x12d3acd0 +0, 9, 9, 1, 174243, 0xb21561b4 +0, 10, 10, 1, 174243, 0x49343b5b +0, 11, 11, 1, 174243, 0x9bd65f49 +0, 12, 12, 1, 174243, 0xed3b9960 +0, 13, 13, 1, 174243, 0x14f70294 +0, 14, 14, 1, 174243, 0x14f70294 +0, 15, 15, 1, 174243, 0x14f70294 +0, 16, 16, 1, 174243, 0x92ac2316 +0, 17, 17, 1, 174243, 0x12729ac0 +0, 18, 18, 1, 174243, 0x6db0bfbd +0, 19, 19, 1, 174243, 0x6db0bfbd +0, 20, 20, 1, 174243, 0x6db0bfbd +0, 21, 21, 1, 174243, 0x6db0bfbd +0, 22, 22, 1, 174243, 0xd66cbef7 +0, 23, 23, 1, 174243, 0xd66cbef7 +0, 24, 24, 1, 174243, 0xd66cbef7 +0, 25, 25, 1, 174243, 0xd66cbef7 +0, 26, 26, 1, 174243, 0x3314c3d3 +0, 27, 27, 1, 174243, 0x34efb358 +0, 28, 28, 1, 174243, 0x7307d8c8 +0, 29, 29, 1, 174243, 0x80b57ea1 +0, 30, 30, 1, 174243, 0xb0b51bf9 +0, 31, 31, 1, 174243, 0x60c07516 +0, 32, 32, 1, 174243, 0xcc35033f +0, 33, 33, 1, 174243, 0x2bf12dc4 +0, 34, 34, 1, 174243, 0xf3025eb7 +0, 35, 35, 1, 174243, 0xf3025eb7 +0, 36, 36, 1, 174243, 0xf3025eb7 +0, 37, 37, 1, 174243, 0xf3025eb7 +0, 38, 38, 1, 174243, 0x06e761b3 +0, 39, 39, 1, 174243, 0xa21152fb +0, 40, 40, 1, 174243, 0xd6dcc575 +0, 41, 41, 1, 174243, 0xd6ceb82a +0, 42, 42, 1, 174243, 0x20efc206 +0, 43, 43, 1, 174243, 0x20efc206 +0, 44, 44, 1, 174243, 0x20efc206 +0, 45, 45, 1, 174243, 0x20efc206 +0, 46, 46, 1, 174243, 0xba03c1f5 +0, 47, 47, 1, 174243, 0xba03c1f5 +0, 48, 48, 1, 174243, 0xba03c1f5 +0, 49, 49, 1, 174243, 0xba03c1f5 +0, 50, 50, 1, 174243, 0x4cd1c214 +0, 51, 51, 1, 174243, 0x4cd1c214 +0, 52, 52, 1, 174243, 0x4cd1c214 +0, 53, 53, 1, 174243, 0xa288c1ef +0, 54, 54, 1, 174243, 0xa288c1ef +0, 55, 55, 1, 174243, 0xa288c1ef +0, 56, 56, 1, 174243, 0xa288c1ef From 37d472a906bd9112225129fc35d9c94ae2ee9c3e Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 25 Mar 2018 22:19:28 +0200 Subject: [PATCH 2348/2557] avformat/concatdec: only set output stream index before returning packet Fixes ticket #6434. Reviewed-by: Nicolas George Signed-off-by: Marton Balint --- libavformat/concatdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 8fff9cc2cbca8..bbe13136fa297 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -603,7 +603,6 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt) av_packet_unref(pkt); continue; } - pkt->stream_index = cs->out_stream_index; break; } if ((ret = filter_packet(avf, cs, pkt))) @@ -646,6 +645,7 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt) } } + pkt->stream_index = cs->out_stream_index; return ret; } From 46129b40446a802b0b5da4797709f552b68b48f5 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 2 Apr 2018 22:09:59 +0200 Subject: [PATCH 2349/2557] avformat/rmdec: make use of avio_get_str() Also do not set empty metadata. Signed-off-by: Paul B Mahol --- libavformat/rmdec.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index fea71a2fc9715..ac61723c66acc 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -70,16 +70,10 @@ static int rm_read_close(AVFormatContext *s); static inline void get_strl(AVIOContext *pb, char *buf, int buf_size, int len) { - int i; - char *q, r; + int read = avio_get_str(pb, len, buf, buf_size); - q = buf; - for(i=0;i 0) *q = '\0'; + if (read > 0) + avio_skip(pb, len - read); } static void get_str8(AVIOContext *pb, char *buf, int buf_size) @@ -105,8 +99,10 @@ static void rm_read_metadata(AVFormatContext *s, AVIOContext *pb, int wide) for (i=0; imetadata, ff_rm_metadata[i], buf, 0); + if (len > 0) { + get_strl(pb, buf, sizeof(buf), len); + av_dict_set(&s->metadata, ff_rm_metadata[i], buf, 0); + } } } From 877aff2beacbb3c238d23be9606467ca661e0609 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 2 Apr 2018 16:44:05 -0300 Subject: [PATCH 2350/2557] avcodec/libaomenc: remove references to gbrp pixfmt Support for this needs testing, so remove for now. Signed-off-by: James Almer --- libavcodec/libaomenc.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index 8ebdcc20e3ef2..41b05dc1c0508 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -220,7 +220,6 @@ static int set_pix_fmt(AVCodecContext *avctx, aom_codec_caps_t codec_caps, enccfg->g_profile = FF_PROFILE_AV1_PROFESSIONAL; *img_fmt = AOM_IMG_FMT_I422; return 0; - case AV_PIX_FMT_GBRP: case AV_PIX_FMT_YUV444P: enccfg->g_profile = FF_PROFILE_AV1_HIGH; *img_fmt = AOM_IMG_FMT_I444; @@ -248,14 +247,11 @@ static int set_pix_fmt(AVCodecContext *avctx, aom_codec_caps_t codec_caps, return 0; } break; - case AV_PIX_FMT_GBRP10: - case AV_PIX_FMT_GBRP12: case AV_PIX_FMT_YUV444P10: case AV_PIX_FMT_YUV444P12: if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH) { enccfg->g_bit_depth = enccfg->g_input_bit_depth = - avctx->pix_fmt == AV_PIX_FMT_YUV444P10 || - avctx->pix_fmt == AV_PIX_FMT_GBRP10 ? 10 : 12; + avctx->pix_fmt == AV_PIX_FMT_YUV444P10 ? 10 : 12; enccfg->g_profile = enccfg->g_bit_depth == 10 ? FF_PROFILE_AV1_HIGH : FF_PROFILE_AV1_PROFESSIONAL; *img_fmt = AOM_IMG_FMT_I44416; @@ -661,7 +657,6 @@ static const enum AVPixelFormat av1_pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, - AV_PIX_FMT_GBRP, AV_PIX_FMT_NONE }; @@ -675,9 +670,6 @@ static const enum AVPixelFormat av1_pix_fmts_highbd[] = { AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, - AV_PIX_FMT_GBRP, - AV_PIX_FMT_GBRP10, - AV_PIX_FMT_GBRP12, AV_PIX_FMT_NONE }; From 4897c80cc6eb50357503d5ced4b2443b39fa4263 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 2 Apr 2018 16:44:18 -0300 Subject: [PATCH 2351/2557] avcodec/libaomdec: remove references to gbrp pixfmt Support for this needs testing, so remove for now. Signed-off-by: James Almer --- libavcodec/libaomdec.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index 1352b421d9c26..a9fd6215fcb9b 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -103,8 +103,7 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) avctx->profile = FF_PROFILE_AV1_PROFESSIONAL; return 0; case AOM_IMG_FMT_I444: - avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? - AV_PIX_FMT_GBRP : AV_PIX_FMT_YUV444P; + avctx->pix_fmt = AV_PIX_FMT_YUV444P; avctx->profile = FF_PROFILE_AV1_HIGH; return 0; case AOM_IMG_FMT_I42016: @@ -141,18 +140,15 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) } case AOM_IMG_FMT_I44416: if (img->bit_depth == 8) { - avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? - AV_PIX_FMT_GBRP : AV_PIX_FMT_YUV444P; + avctx->pix_fmt = AV_PIX_FMT_YUV444P; avctx->profile = FF_PROFILE_AV1_HIGH; return 0; } else if (img->bit_depth == 10) { - avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? - AV_PIX_FMT_GBRP10 : AV_PIX_FMT_YUV444P10; + avctx->pix_fmt = AV_PIX_FMT_YUV444P10; avctx->profile = FF_PROFILE_AV1_HIGH; return 0; } else if (img->bit_depth == 12) { - avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? - AV_PIX_FMT_GBRP12 : AV_PIX_FMT_YUV444P12; + avctx->pix_fmt = AV_PIX_FMT_YUV444P12; avctx->profile = FF_PROFILE_AV1_PROFESSIONAL; return 0; } else { From c6c20249e724e1db37af72815742c0cd520d4756 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Sun, 1 Apr 2018 15:53:11 +0800 Subject: [PATCH 2352/2557] avformat/options_table: Change the seek2any location in opt table. Change the seek2any location in avformat_options to make code more readable. Signed-off-by: Jun Zhao Signed-off-by: Michael Niedermayer --- libavformat/options_table.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/options_table.h b/libavformat/options_table.h index b8fa47c6fd335..7c4d84798e1af 100644 --- a/libavformat/options_table.h +++ b/libavformat/options_table.h @@ -54,10 +54,10 @@ static const AVOption avformat_options[] = { {"fastseek", "fast but inaccurate seeks", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_FAST_SEEK }, INT_MIN, INT_MAX, D, "fflags"}, {"latm", "enable RTP MP4A-LATM payload", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_MP4A_LATM }, INT_MIN, INT_MAX, E, "fflags"}, {"nobuffer", "reduce the latency introduced by optional buffering", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOBUFFER }, 0, INT_MAX, D, "fflags"}, -{"seek2any", "allow seeking to non-keyframes on demuxer level when supported", OFFSET(seek2any), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, D}, {"bitexact", "do not write random/volatile data", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_BITEXACT }, 0, 0, E, "fflags" }, {"shortest", "stop muxing with the shortest stream", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_SHORTEST }, 0, 0, E, "fflags" }, {"autobsf", "add needed bsfs automatically", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_AUTO_BSF }, 0, 0, E, "fflags" }, +{"seek2any", "allow seeking to non-keyframes on demuxer level when supported", OFFSET(seek2any), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, D}, {"analyzeduration", "specify how many microseconds are analyzed to probe the input", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, D}, {"cryptokey", "decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D}, {"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), AV_OPT_TYPE_INT, {.i64 = 1<<20 }, 0, INT_MAX, D}, From d52be5d4e91871a22dac70af3e0ab429e95a2d10 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 12 Mar 2018 00:05:04 +0100 Subject: [PATCH 2353/2557] avcodec/cscd: Error out when LZ* decompression fails Fixes: Timeout Fixes: 6304/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_CSCD_fuzzer-5754772461191168 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/cscd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/cscd.c b/libavcodec/cscd.c index 9e1dec9d967f7..35c4ee08c3528 100644 --- a/libavcodec/cscd.c +++ b/libavcodec/cscd.c @@ -81,15 +81,19 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, switch ((buf[0] >> 1) & 7) { case 0: { // lzo compression int outlen = c->decomp_size, inlen = buf_size - 2; - if (av_lzo1x_decode(c->decomp_buf, &outlen, &buf[2], &inlen)) + if (av_lzo1x_decode(c->decomp_buf, &outlen, &buf[2], &inlen)) { av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n"); + return AVERROR_INVALIDDATA; + } break; } case 1: { // zlib compression #if CONFIG_ZLIB unsigned long dlen = c->decomp_size; - if (uncompress(c->decomp_buf, &dlen, &buf[2], buf_size - 2) != Z_OK) + if (uncompress(c->decomp_buf, &dlen, &buf[2], buf_size - 2) != Z_OK) { av_log(avctx, AV_LOG_ERROR, "error during zlib decompression\n"); + return AVERROR_INVALIDDATA; + } break; #else av_log(avctx, AV_LOG_ERROR, "compiled without zlib support\n"); From 197a4e8feed45b2e5868760240e83636818f32a9 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 31 Mar 2018 21:19:19 +0200 Subject: [PATCH 2354/2557] avcodec/aacdec_fixed: Fix integer overflow in apply_independent_coupling_fixed() I was not able to reproduce this, this fix is based on just the fuzzer log. Fixes: 4959/clusterfuzz-testcase-minimized-6035350934781952 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/aacdec_fixed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c index f96999efb41ae..5c3613e06ce63 100644 --- a/libavcodec/aacdec_fixed.c +++ b/libavcodec/aacdec_fixed.c @@ -417,7 +417,7 @@ static void apply_independent_coupling_fixed(AACContext *ac, int i, c, shift, round, tmp; const int gain = cce->coup.gain[index][0]; const int *src = cce->ch[0].ret; - int *dest = target->ret; + unsigned int *dest = target->ret; const int len = 1024 << (ac->oc[1].m4ac.sbr == 1); c = cce_scale_fixed[gain & 7]; From 4b736bc921ed96ad6d312ce0cbe0de29b9e3fe81 Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Tue, 3 Apr 2018 08:54:10 +0200 Subject: [PATCH 2355/2557] fftools/cmdutils: add support for level flag in loglevel option parser Allows to manage the AV_LOG_PRINT_LEVEL flag as a prefix to the loglevel option value, similar to the existing AV_LOG_SKIP_REPEATE flag. Adds support for setting flags relative to the existing value by using a +/- prefix. Previous version reviewed-by: Michael Niedermayer Signed-off-by: Tobias Rapp --- fftools/cmdutils.c | 65 +++++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 1001f362999a1..8ffc9d240bfaf 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -881,28 +881,54 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg) { "debug" , AV_LOG_DEBUG }, { "trace" , AV_LOG_TRACE }, }; + const char *token; char *tail; - int level; - int flags; - int i; - - flags = av_log_get_flags(); - tail = strstr(arg, "repeat"); - if (tail) - flags &= ~AV_LOG_SKIP_REPEATED; - else - flags |= AV_LOG_SKIP_REPEATED; - - av_log_set_flags(flags); - if (tail == arg) - arg += 6 + (arg[6]=='+'); - if(tail && !*arg) - return 0; + int flags = av_log_get_flags(); + int level = av_log_get_level(); + int cmd, i = 0; + + av_assert0(arg); + while (*arg) { + token = arg; + if (*token == '+' || *token == '-') { + cmd = *token++; + } else { + cmd = 0; + } + if (!i && !cmd) { + flags = 0; /* missing relative prefix, build absolute value */ + } + if (!strncmp(token, "repeat", 6)) { + if (cmd == '-') { + flags |= AV_LOG_SKIP_REPEATED; + } else { + flags &= ~AV_LOG_SKIP_REPEATED; + } + arg = token + 6; + } else if (!strncmp(token, "level", 5)) { + if (cmd == '-') { + flags &= ~AV_LOG_PRINT_LEVEL; + } else { + flags |= AV_LOG_PRINT_LEVEL; + } + arg = token + 5; + } else { + break; + } + i++; + } + if (!*arg) { + goto end; + } else if (*arg == '+') { + arg++; + } else if (!i) { + flags = av_log_get_flags(); /* level value without prefix, reset flags */ + } for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) { if (!strcmp(log_levels[i].name, arg)) { - av_log_set_level(log_levels[i].level); - return 0; + level = log_levels[i].level; + goto end; } } @@ -914,6 +940,9 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg) av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name); exit_program(1); } + +end: + av_log_set_flags(flags); av_log_set_level(level); return 0; } From 8c2c97403baf95d0facb53f03e468f023eb943e1 Mon Sep 17 00:00:00 2001 From: Simon Thelen Date: Tue, 3 Apr 2018 14:41:33 +0200 Subject: [PATCH 2356/2557] avcodec/imgconvert: fix possible null pointer dereference regression since 354b26a3945eadd4ed8fcd801dfefad2566241de --- libavcodec/imgconvert.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c index 7b0005b308fd1..1fd636c83d8ef 100644 --- a/libavcodec/imgconvert.c +++ b/libavcodec/imgconvert.c @@ -72,11 +72,12 @@ enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *p int loss; for (i=0; pix_fmt_list[i] != AV_PIX_FMT_NONE; i++) { - loss = *loss_ptr; + loss = loss_ptr ? *loss_ptr : 0; best = avcodec_find_best_pix_fmt_of_2(best, pix_fmt_list[i], src_pix_fmt, has_alpha, &loss); } - *loss_ptr = loss; + if (loss_ptr) + *loss_ptr = loss; return best; } From a8745869946d6a5da3cbb1dfcb1a9d3109c49dc1 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 31 Mar 2018 11:48:30 +0200 Subject: [PATCH 2357/2557] avcodec/clearvideo: add inter-frame decoding Signed-off-by: Paul B Mahol --- libavcodec/clearvideo.c | 719 ++++++++++++-- libavcodec/clearvideodata.h | 1829 +++++++++++++++++++++++++++++++++++ 2 files changed, 2443 insertions(+), 105 deletions(-) create mode 100644 libavcodec/clearvideodata.h diff --git a/libavcodec/clearvideo.c b/libavcodec/clearvideo.c index 2c06b79fd5673..269370ee6543c 100644 --- a/libavcodec/clearvideo.c +++ b/libavcodec/clearvideo.c @@ -1,6 +1,6 @@ /* * ClearVideo decoder - * Copyright (c) 2012 Konstantin Shishkov + * Copyright (c) 2012-2018 Konstantin Shishkov * * This file is part of FFmpeg. * @@ -29,107 +29,55 @@ #include "get_bits.h" #include "idctdsp.h" #include "internal.h" - -#define NUM_DC_CODES 127 -#define NUM_AC_CODES 103 - -static const uint8_t clv_dc_codes[NUM_DC_CODES] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x07, 0x0B, - 0x0C, 0x08, 0x08, 0x09, 0x04, 0x06, 0x07, 0x05, - 0x04, 0x05, 0x04, 0x06, 0x05, 0x06, 0x07, 0x05, - 0x06, 0x07, 0x06, 0x07, 0x08, 0x06, 0x07, 0x08, - 0x09, 0x0A, 0x0B, 0x07, 0x08, 0x09, 0x07, 0x08, - 0x06, 0x07, 0x08, 0x06, 0x04, 0x05, 0x02, 0x01, - 0x03, 0x06, 0x07, 0x07, 0x09, 0x0A, 0x0B, 0x09, - 0x0A, 0x0B, 0x0A, 0x0B, 0x0C, 0x0D, 0x0C, 0x09, - 0x0D, 0x0A, 0x0B, 0x08, 0x09, 0x0A, 0x0B, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x06, 0x07, 0x06, 0x08, - 0x07, 0x09, 0x0A, 0x0B, 0x09, 0x0A, 0x0B, 0x0C, - 0x14, 0x0D, 0x0D, 0x0E, 0x0F, 0x15, 0x15, 0x16, - 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, - 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, -}; - -static const uint8_t clv_dc_bits[NUM_DC_CODES] = { - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 21, 22, 22, 19, 20, - 20, 19, 18, 18, 15, 17, 17, 16, - 14, 15, 12, 13, 14, 14, 14, 12, - 12, 12, 11, 11, 11, 10, 10, 10, - 10, 10, 10, 9, 9, 9, 8, 8, - 7, 7, 7, 6, 5, 5, 3, 1, - 3, 5, 5, 6, 7, 7, 7, 8, - 8, 8, 9, 9, 9, 9, 10, 11, - 10, 11, 11, 12, 12, 12, 12, 13, - 14, 14, 14, 14, 15, 15, 16, 17, - 16, 17, 18, 18, 19, 19, 19, 19, - 21, 19, 20, 19, 19, 21, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, -}; - -static const uint16_t clv_ac_syms[NUM_AC_CODES] = { - 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, - 0x0009, 0x000A, 0x000B, 0x000C, 0x0011, 0x0012, 0x0013, 0x0014, - 0x0015, 0x0016, 0x0021, 0x0022, 0x0023, 0x0024, 0x0031, 0x0032, - 0x0033, 0x0041, 0x0042, 0x0043, 0x0051, 0x0052, 0x0053, 0x0061, - 0x0062, 0x0063, 0x0071, 0x0072, 0x0081, 0x0082, 0x0091, 0x0092, - 0x00A1, 0x00A2, 0x00B1, 0x00C1, 0x00D1, 0x00E1, 0x00F1, 0x0101, - 0x0111, 0x0121, 0x0131, 0x0141, 0x0151, 0x0161, 0x0171, 0x0181, - 0x0191, 0x01A1, 0x1001, 0x1002, 0x1003, 0x1011, 0x1012, 0x1021, - 0x1031, 0x1041, 0x1051, 0x1061, 0x1071, 0x1081, 0x1091, 0x10A1, - 0x10B1, 0x10C1, 0x10D1, 0x10E1, 0x10F1, 0x1101, 0x1111, 0x1121, - 0x1131, 0x1141, 0x1151, 0x1161, 0x1171, 0x1181, 0x1191, 0x11A1, - 0x11B1, 0x11C1, 0x11D1, 0x11E1, 0x11F1, 0x1201, 0x1211, 0x1221, - 0x1231, 0x1241, 0x1251, 0x1261, 0x1271, 0x1281, 0x1BFF, -}; - -static const uint8_t clv_ac_codes[NUM_AC_CODES] = { - 0x02, 0x0F, 0x15, 0x17, 0x1F, 0x25, 0x24, 0x21, - 0x20, 0x07, 0x06, 0x20, 0x06, 0x14, 0x1E, 0x0F, - 0x21, 0x50, 0x0E, 0x1D, 0x0E, 0x51, 0x0D, 0x23, - 0x0D, 0x0C, 0x22, 0x52, 0x0B, 0x0C, 0x53, 0x13, - 0x0B, 0x54, 0x12, 0x0A, 0x11, 0x09, 0x10, 0x08, - 0x16, 0x55, 0x15, 0x14, 0x1C, 0x1B, 0x21, 0x20, - 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x22, 0x23, - 0x56, 0x57, 0x07, 0x19, 0x05, 0x0F, 0x04, 0x0E, - 0x0D, 0x0C, 0x13, 0x12, 0x11, 0x10, 0x1A, 0x19, - 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x18, 0x17, - 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x07, 0x06, - 0x05, 0x04, 0x24, 0x25, 0x26, 0x27, 0x58, 0x59, - 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x03, -}; - -static const uint8_t clv_ac_bits[NUM_AC_CODES] = { - 2, 4, 6, 7, 8, 9, 9, 10, - 10, 11, 11, 11, 3, 6, 8, 10, - 11, 12, 4, 8, 10, 12, 5, 9, - 10, 5, 9, 12, 5, 10, 12, 6, - 10, 12, 6, 10, 6, 10, 6, 10, - 7, 12, 7, 7, 8, 8, 9, 9, - 9, 9, 9, 9, 9, 9, 11, 11, - 12, 12, 4, 9, 11, 6, 11, 6, - 6, 6, 7, 7, 7, 7, 8, 8, - 8, 8, 8, 8, 8, 8, 9, 9, - 9, 9, 9, 9, 9, 9, 10, 10, - 10, 10, 11, 11, 11, 11, 12, 12, - 12, 12, 12, 12, 12, 12, 7, -}; +#include "mathops.h" +#include "clearvideodata.h" + +typedef struct LevelCodes { + uint16_t mv_esc; + uint16_t bias_esc; + VLC flags_cb; + VLC mv_cb; + VLC bias_cb; +} LevelCodes; + +typedef struct MV { + int16_t x, y; +} MV; + +static const MV zero_mv = { 0 }; + +typedef struct MVInfo { + int mb_w; + int mb_h; + int mb_size; + int mb_stride; + int top; + MV *mv; +} MVInfo; + +typedef struct TileInfo { + uint16_t flags; + int16_t bias; + MV mv; + struct TileInfo *child[4]; +} TileInfo; typedef struct CLVContext { AVCodecContext *avctx; IDCTDSPContext idsp; AVFrame *pic; + AVFrame *prev; GetBitContext gb; int mb_width, mb_height; + int pmb_width, pmb_height; + MVInfo mvi; + int tile_size; + int tile_shift; VLC dc_vlc, ac_vlc; + LevelCodes ylev[4], ulev[3], vlev[3]; int luma_dc_quant, chroma_dc_quant, ac_quant; DECLARE_ALIGNED(16, int16_t, block)[64]; int top_dc[3], left_dc[4]; - int iframes_warning; } CLVContext; static inline int decode_block(CLVContext *ctx, int16_t *blk, int has_ac, @@ -271,6 +219,282 @@ static int decode_mb(CLVContext *c, int x, int y) return 0; } +static int copy_block(AVCodecContext *avctx, AVFrame *dst, AVFrame *src, + int plane, int x, int y, int dx, int dy, int size) +{ + int shift = plane > 0; + int sx = x + dx; + int sy = y + dy; + int sstride, dstride, soff, doff; + uint8_t *sbuf, *dbuf; + int i; + + if (x < 0 || sx < 0 || y < 0 || sy < 0 || + x + size > avctx->coded_width >> shift || + y + size > avctx->coded_height >> shift || + sx + size > avctx->coded_width >> shift || + sy + size > avctx->coded_height >> shift) + return AVERROR_INVALIDDATA; + + sstride = src->linesize[plane]; + dstride = dst->linesize[plane]; + soff = sx + sy * sstride; + sbuf = src->data[plane]; + doff = x + y * dstride; + dbuf = dst->data[plane]; + + for (i = 0; i < size; i++) { + uint8_t *dptr = &dbuf[doff]; + uint8_t *sptr = &sbuf[soff]; + + memcpy(dptr, sptr, size); + doff += dstride; + soff += sstride; + } + + return 0; +} + +static int copyadd_block(AVCodecContext *avctx, AVFrame *dst, AVFrame *src, + int plane, int x, int y, int dx, int dy, int size, int bias) +{ + int shift = plane > 0; + int sx = x + dx; + int sy = y + dy; + int sstride = src->linesize[plane]; + int dstride = dst->linesize[plane]; + int soff = sx + sy * sstride; + uint8_t *sbuf = src->data[plane]; + int doff = x + y * dstride; + uint8_t *dbuf = dst->data[plane]; + int i, j; + + if (x < 0 || sx < 0 || y < 0 || sy < 0 || + x + size > avctx->coded_width >> shift || + y + size > avctx->coded_height >> shift || + sx + size > avctx->coded_width >> shift || + sy + size > avctx->coded_height >> shift) + return AVERROR_INVALIDDATA; + + for (j = 0; j < size; j++) { + uint8_t *dptr = &dbuf[doff]; + uint8_t *sptr = &sbuf[soff]; + + for (i = 0; i < size; i++) { + int val = sptr[i] + bias; + + dptr[i] = av_clip_uint8(val); + } + + doff += dstride; + soff += sstride; + } + + return 0; +} + +static MV mvi_predict(MVInfo *mvi, int mb_x, int mb_y, MV diff) +{ + MV res, pred_mv; + + if (mvi->top) { + if (mb_x > 0) { + pred_mv = mvi->mv[mvi->mb_stride + mb_x - 1]; + } else { + pred_mv = zero_mv; + } + } else if ((mb_x == 0) || (mb_x == mvi->mb_w - 1)) { + pred_mv = mvi->mv[mb_x]; + } else { + MV A = mvi->mv[mvi->mb_stride + mb_x - 1]; + MV B = mvi->mv[ mb_x ]; + MV C = mvi->mv[ mb_x + 1]; + pred_mv.x = mid_pred(A.x, B.x, C.x); + pred_mv.y = mid_pred(A.y, B.y, C.y); + } + + res = pred_mv; + + int left_mv = -((mb_x * mvi->mb_size)); + int right_mv = ((mvi->mb_w - mb_x - 1) * mvi->mb_size); + if (res.x < left_mv) { + res.x = left_mv; + } + if (res.x > right_mv) { + res.x = right_mv; + } + int top_mv = -((mb_y * mvi->mb_size)); + int bot_mv = ((mvi->mb_h - mb_y - 1) * mvi->mb_size); + if (res.y < top_mv) { + res.y = top_mv; + } + if (res.y > bot_mv) { + res.y = bot_mv; + } + + mvi->mv[mvi->mb_stride + mb_x].x = res.x + diff.x; + mvi->mv[mvi->mb_stride + mb_x].y = res.y + diff.y; + + return res; +} + +static void mvi_reset(MVInfo *mvi, int mb_w, int mb_h, int mb_size) +{ + mvi->top = 1; + mvi->mb_w = mb_w; + mvi->mb_h = mb_h; + mvi->mb_size = mb_size; + mvi->mb_stride = mb_w; + memset(mvi->mv, 0, sizeof(MV) * mvi->mb_stride * 2); +} + +static void mvi_update_row(MVInfo *mvi) +{ + int i; + + mvi->top = 0; + for (i = 0 ; i < mvi->mb_stride; i++) { + mvi->mv[i] = mvi->mv[mvi->mb_stride + i]; + } +} + +static TileInfo* decode_tile_info(GetBitContext *gb, LevelCodes *lc, int level) +{ + TileInfo *ti; + int i, flags = 0; + int16_t bias = 0; + MV mv = { 0 }; + + if (lc[level].flags_cb.table) { + flags = get_vlc2(gb, lc[level].flags_cb.table, lc[level].flags_cb.bits, 2); + } + + if (lc[level].mv_cb.table) { + uint16_t mv_code = get_vlc2(gb, lc[level].mv_cb.table, lc[level].mv_cb.bits, 3); + + if (mv_code != lc[level].mv_esc) { + mv.x = (int8_t)(mv_code & 0xff); + mv.y = (int8_t)(mv_code >> 8); + } else { + mv.x = get_sbits(gb, 8); + mv.y = get_sbits(gb, 8); + } + } + + if (lc[level].bias_cb.table) { + uint16_t bias_val = get_vlc2(gb, lc[level].bias_cb.table, lc[level].bias_cb.bits, 2); + + if (bias_val != lc[level].bias_esc) { + bias = (int16_t)(bias_val); + } else { + bias = get_sbits(gb, 16); + } + } + + ti = av_calloc(1, sizeof(*ti)); + if (!ti) + return NULL; + + ti->flags = flags; + ti->mv = mv; + ti->bias = bias; + + if (ti->flags) { + for (i = 0; i < 4; i++) { + if (ti->flags & (1 << i)) { + TileInfo *subti = decode_tile_info(gb, lc, level + 1); + ti->child[i] = subti; + } + } + } + + return ti; +} + +static int tile_do_block(AVCodecContext *avctx, AVFrame *dst, AVFrame *src, + int plane, int x, int y, int dx, int dy, int size, int bias) +{ + int ret; + + if (!bias) { + ret = copy_block(avctx, dst, src, plane, x, y, dx, dy, size); + } else { + ret = copyadd_block(avctx, dst, src, plane, x, y, dx, dy, size, bias); + } + + return ret; +} + +static int restore_tree(AVCodecContext *avctx, AVFrame *dst, AVFrame *src, + int plane, int x, int y, int size, + TileInfo *tile, MV root_mv) +{ + int ret; + MV mv; + + mv.x = root_mv.x + tile->mv.x; + mv.y = root_mv.y + tile->mv.y; + + if (!tile->flags) { + ret = tile_do_block(avctx, dst, src, plane, x, y, mv.x, mv.y, size, tile->bias); + } else { + int i, hsize = size >> 1; + + for (i = 0; i < 4; i++) { + int xoff = (i & 2) == 0 ? 0 : hsize; + int yoff = (i & 1) == 0 ? 0 : hsize; + + if (tile->child[i]) { + ret = restore_tree(avctx, dst, src, plane, x + xoff, y + yoff, hsize, tile->child[i], root_mv); + av_freep(&tile->child[i]); + } else { + ret = tile_do_block(avctx, dst, src, plane, x + xoff, y + yoff, mv.x, mv.y, hsize, tile->bias); + } + } + } + + return ret; +} + +static void extend_edges(AVFrame *buf, int tile_size) +{ + int comp, i, j; + + for (comp = 0; comp < 3; comp++) { + int shift = comp > 0; + int w = buf->width >> shift; + int h = buf->height >> shift; + int size = comp == 0 ? tile_size : tile_size >> 1; + int stride = buf->linesize[comp]; + uint8_t *framebuf = buf->data[comp]; + + int right = size - (w & (size - 1)); + int bottom = size - (h & (size - 1)); + + if ((right == size) && (bottom == size)) { + return; + } + if (right != size) { + int off = w; + for (j = 0; j < h; j++) { + for (i = 0; i < right; i++) { + framebuf[off + i] = 0x80; + } + off += stride; + } + } + if (bottom != size) { + int off = h * stride; + for (j = 0; j < bottom; j++) { + for (i = 0; i < stride; i++) { + framebuf[off + i] = 0x80; + } + off += stride; + } + } + } +} + static int clv_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { @@ -290,7 +514,13 @@ static int clv_decode_frame(AVCodecContext *avctx, void *data, frame_type = bytestream2_get_byte(&gb); - if (frame_type & 0x2) { + if ((frame_type & 0x7f) == 0x30) { + if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) + return ret; + + c->pic->key_frame = 0; + c->pic->pict_type = AV_PICTURE_TYPE_P; + } else if (frame_type & 0x2) { if (buf_size < c->mb_width * c->mb_height) { av_log(avctx, AV_LOG_ERROR, "Packet too small\n"); return AVERROR_INVALIDDATA; @@ -299,9 +529,8 @@ static int clv_decode_frame(AVCodecContext *avctx, void *data, if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) return ret; - c->pic->key_frame = frame_type & 0x20 ? 1 : 0; - c->pic->pict_type = frame_type & 0x20 ? AV_PICTURE_TYPE_I - : AV_PICTURE_TYPE_P; + c->pic->key_frame = 1; + c->pic->pict_type = AV_PICTURE_TYPE_I; bytestream2_get_be32(&gb); // frame size; c->ac_quant = bytestream2_get_byte(&gb); @@ -324,34 +553,133 @@ static int clv_decode_frame(AVCodecContext *avctx, void *data, mb_ret = ret; } } + extend_edges(c->pic, c->tile_size); + } else { + int plane; - if ((ret = av_frame_ref(data, c->pic)) < 0) + if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) return ret; - *got_frame = 1; - } else { - if (!c->iframes_warning) - avpriv_report_missing_feature(avctx, "Non-I-frames in Clearvideo"); - c->iframes_warning = 1; - return AVERROR_PATCHWELCOME; + ret = av_frame_copy(c->pic, c->prev); + if (ret < 0) + return ret; + + if ((ret = init_get_bits8(&c->gb, buf + bytestream2_tell(&gb), + buf_size - bytestream2_tell(&gb))) < 0) + return ret; + + mvi_reset(&c->mvi, c->pmb_width, c->pmb_height, 1 << c->tile_shift); + + for (j = 0; j < c->pmb_height; j++) { + for (i = 0; i < c->pmb_width; i++) { + if (get_bits1(&c->gb)) { + MV mv = mvi_predict(&c->mvi, i, j, zero_mv); + + for (plane = 0; plane < 3; plane++) { + int16_t x = plane == 0 ? i << c->tile_shift : i << (c->tile_shift - 1); + int16_t y = plane == 0 ? j << c->tile_shift : j << (c->tile_shift - 1); + int16_t size = plane == 0 ? 1 << c->tile_shift : 1 << (c->tile_shift - 1); + int16_t mx = plane == 0 ? mv.x : mv.x / 2; + int16_t my = plane == 0 ? mv.y : mv.y / 2; + + ret = copy_block(avctx, c->pic, c->prev, plane, x, y, mx, my, size); + if (ret < 0) + mb_ret = ret; + } + } else { + int x = i << c->tile_shift; + int y = j << c->tile_shift; + int size = 1 << c->tile_shift; + TileInfo *tile; + MV mv, cmv; + + tile = decode_tile_info(&c->gb, c->ylev, 0); + if (!tile) + return AVERROR(ENOMEM); + mv = mvi_predict(&c->mvi, i, j, tile->mv); + ret = restore_tree(avctx, c->pic, c->prev, 0, x, y, size, tile, mv); + if (ret < 0) + mb_ret = ret; + x = i << (c->tile_shift - 1); + y = j << (c->tile_shift - 1); + size = 1 << (c->tile_shift - 1); + cmv.x = mv.x + tile->mv.x; + cmv.y = mv.y + tile->mv.y; + cmv.x /= 2; + cmv.y /= 2; + av_freep(&tile); + tile = decode_tile_info(&c->gb, c->ulev, 0); + if (!tile) + return AVERROR(ENOMEM); + ret = restore_tree(avctx, c->pic, c->prev, 1, x, y, size, tile, cmv); + if (ret < 0) + mb_ret = ret; + av_freep(&tile); + tile = decode_tile_info(&c->gb, c->vlev, 0); + if (!tile) + return AVERROR(ENOMEM); + ret = restore_tree(avctx, c->pic, c->prev, 2, x, y, size, tile, cmv); + if (ret < 0) + mb_ret = ret; + av_freep(&tile); + } + } + mvi_update_row(&c->mvi); + } + extend_edges(c->pic, c->tile_size); + + c->pic->key_frame = 0; + c->pic->pict_type = AV_PICTURE_TYPE_P; } + if ((ret = av_frame_ref(data, c->pic)) < 0) + return ret; + + FFSWAP(AVFrame *, c->pic, c->prev); + + *got_frame = 1; + return mb_ret < 0 ? mb_ret : buf_size; } static av_cold int clv_decode_init(AVCodecContext *avctx) { CLVContext *const c = avctx->priv_data; - int ret; + int ret, w, h; + + if (avctx->extradata_size == 110) { + c->tile_size = AV_RL32(&avctx->extradata[94]); + } else if (avctx->extradata_size == 150) { + c->tile_size = AV_RB32(&avctx->extradata[134]); + } else { + av_log(avctx, AV_LOG_ERROR, "Unsupported extradata size: %d\n", avctx->extradata_size); + return AVERROR_INVALIDDATA; + } + + c->tile_shift = av_log2(c->tile_size); + if (1 << c->tile_shift != c->tile_size) { + av_log(avctx, AV_LOG_ERROR, "Tile size: %d, is not power of 2.\n", c->tile_size); + return AVERROR_INVALIDDATA; + } avctx->pix_fmt = AV_PIX_FMT_YUV420P; + w = avctx->width; + h = avctx->height; + ret = ff_set_dimensions(avctx, FFALIGN(w, 1 << c->tile_shift), FFALIGN(h, 1 << c->tile_shift)); + if (ret < 0) + return ret; + avctx->width = w; + avctx->height = h; c->avctx = avctx; c->mb_width = FFALIGN(avctx->width, 16) >> 4; c->mb_height = FFALIGN(avctx->height, 16) >> 4; - c->iframes_warning = 0; + c->pmb_width = (w + c->tile_size - 1) >> c->tile_shift; + c->pmb_height = (h + c->tile_size - 1) >> c->tile_shift; c->pic = av_frame_alloc(); - if (!c->pic) + c->prev = av_frame_alloc(); + c->mvi.mv = av_calloc(c->pmb_width * 2, sizeof(*c->mvi.mv)); + if (!c->pic || !c->prev || !c->mvi.mv) return AVERROR(ENOMEM); ff_idctdsp_init(&c->idsp, avctx); @@ -371,17 +699,198 @@ static av_cold int clv_decode_init(AVCodecContext *avctx) return ret; } + ret = init_vlc(&c->ylev[0].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsy_0_bits), + clv_flagsy_0_bits, 1, 1, + clv_flagsy_0_codes, 2, 2, 0); + if (ret) + return ret; + + ret = init_vlc(&c->ylev[1].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsy_1_bits), + clv_flagsy_1_bits, 1, 1, + clv_flagsy_1_codes, 2, 2, 0); + if (ret) + return ret; + + ret = init_vlc(&c->ylev[2].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsy_2_bits), + clv_flagsy_2_bits, 1, 1, + clv_flagsy_2_codes, 2, 2, 0); + if (ret) + return ret; + + ret = init_vlc(&c->ulev[0].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsu_0_bits), + clv_flagsu_0_bits, 1, 1, + clv_flagsu_0_codes, 2, 2, 0); + if (ret) + return ret; + + ret = init_vlc(&c->ulev[1].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsu_1_bits), + clv_flagsu_1_bits, 1, 1, + clv_flagsu_1_codes, 2, 2, 0); + if (ret) + return ret; + + ret = init_vlc(&c->vlev[0].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsv_0_bits), + clv_flagsv_0_bits, 1, 1, + clv_flagsv_0_codes, 2, 2, 0); + if (ret) + return ret; + + ret = init_vlc(&c->vlev[1].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsv_1_bits), + clv_flagsv_1_bits, 1, 1, + clv_flagsv_1_codes, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->ylev[0].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvy_0_bits), + clv_mvy_0_bits, 1, 1, + clv_mvy_0_codes, 2, 2, + clv_mvy_0_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->ylev[1].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvy_1_bits), + clv_mvy_1_bits, 1, 1, + clv_mvy_1_codes, 2, 2, + clv_mvy_1_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->ylev[2].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvy_2_bits), + clv_mvy_2_bits, 1, 1, + clv_mvy_2_codes, 2, 2, + clv_mvy_2_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->ylev[3].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvy_3_bits), + clv_mvy_3_bits, 1, 1, + clv_mvy_3_codes, 2, 2, + clv_mvy_3_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->ulev[1].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvu_1_bits), + clv_mvu_1_bits, 1, 1, + clv_mvu_1_codes, 2, 2, + clv_mvu_1_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->ulev[2].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvu_2_bits), + clv_mvu_2_bits, 1, 1, + clv_mvu_2_codes, 2, 2, + clv_mvu_2_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->vlev[1].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvv_1_bits), + clv_mvv_1_bits, 1, 1, + clv_mvv_1_codes, 2, 2, + clv_mvv_1_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->vlev[2].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvv_2_bits), + clv_mvv_2_bits, 1, 1, + clv_mvv_2_codes, 2, 2, + clv_mvv_2_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->ylev[1].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasy_1_bits), + clv_biasy_1_bits, 1, 1, + clv_biasy_1_codes, 2, 2, + clv_biasy_1_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->ylev[2].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasy_2_bits), + clv_biasy_2_bits, 1, 1, + clv_biasy_2_codes, 2, 2, + clv_biasy_2_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->ylev[3].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasy_3_bits), + clv_biasy_3_bits, 1, 1, + clv_biasy_3_codes, 2, 2, + clv_biasy_3_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->ulev[1].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasu_1_bits), + clv_biasu_1_bits, 1, 1, + clv_biasu_1_codes, 2, 2, + clv_biasu_1_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->ulev[2].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasu_2_bits), + clv_biasu_2_bits, 1, 1, + clv_biasu_2_codes, 2, 2, + clv_biasu_2_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->vlev[1].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasv_1_bits), + clv_biasv_1_bits, 1, 1, + clv_biasv_1_codes, 2, 2, + clv_biasv_1_syms, 2, 2, 0); + if (ret) + return ret; + + ret = ff_init_vlc_sparse(&c->vlev[2].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasv_2_bits), + clv_biasv_2_bits, 1, 1, + clv_biasv_2_codes, 2, 2, + clv_biasv_2_syms, 2, 2, 0); + if (ret) + return ret; + + c->ylev[0].mv_esc = 0x0909; + c->ylev[1].mv_esc = 0x0A0A; + c->ylev[2].mv_esc = 0x1010; + c->ylev[3].mv_esc = 0x1313; + c->ulev[1].mv_esc = 0x0808; + c->ulev[2].mv_esc = 0x0B0B; + c->vlev[1].mv_esc = 0x0808; + c->vlev[2].mv_esc = 0x0B0B; + + c->ylev[1].bias_esc = 0x100; + c->ylev[2].bias_esc = 0x100; + c->ylev[3].bias_esc = 0x100; + c->ulev[1].bias_esc = 0x100; + c->ulev[2].bias_esc = 0x100; + c->vlev[1].bias_esc = 0x100; + c->vlev[2].bias_esc = 0x100; + return 0; } static av_cold int clv_decode_end(AVCodecContext *avctx) { CLVContext *const c = avctx->priv_data; + int i; + av_frame_free(&c->prev); av_frame_free(&c->pic); + av_freep(&c->mvi.mv); + ff_free_vlc(&c->dc_vlc); ff_free_vlc(&c->ac_vlc); + for (i = 0; i < 4; i++) { + ff_free_vlc(&c->ylev[i].mv_cb); + ff_free_vlc(&c->ylev[i].flags_cb); + ff_free_vlc(&c->ylev[i].bias_cb); + } + for (i = 0; i < 3; i++) { + ff_free_vlc(&c->ulev[i].mv_cb); + ff_free_vlc(&c->ulev[i].flags_cb); + ff_free_vlc(&c->ulev[i].bias_cb); + ff_free_vlc(&c->vlev[i].mv_cb); + ff_free_vlc(&c->vlev[i].flags_cb); + ff_free_vlc(&c->vlev[i].bias_cb); + } return 0; } diff --git a/libavcodec/clearvideodata.h b/libavcodec/clearvideodata.h new file mode 100644 index 0000000000000..157397d9877db --- /dev/null +++ b/libavcodec/clearvideodata.h @@ -0,0 +1,1829 @@ +/* + * ClearVideo decoder + * Copyright (c) 2012-2018 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/common.h" + +#define NUM_DC_CODES 127 +#define NUM_AC_CODES 103 + +static const uint8_t clv_dc_codes[NUM_DC_CODES] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x07, 0x0B, + 0x0C, 0x08, 0x08, 0x09, 0x04, 0x06, 0x07, 0x05, + 0x04, 0x05, 0x04, 0x06, 0x05, 0x06, 0x07, 0x05, + 0x06, 0x07, 0x06, 0x07, 0x08, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x07, 0x08, 0x09, 0x07, 0x08, + 0x06, 0x07, 0x08, 0x06, 0x04, 0x05, 0x02, 0x01, + 0x03, 0x06, 0x07, 0x07, 0x09, 0x0A, 0x0B, 0x09, + 0x0A, 0x0B, 0x0A, 0x0B, 0x0C, 0x0D, 0x0C, 0x09, + 0x0D, 0x0A, 0x0B, 0x08, 0x09, 0x0A, 0x0B, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x06, 0x07, 0x06, 0x08, + 0x07, 0x09, 0x0A, 0x0B, 0x09, 0x0A, 0x0B, 0x0C, + 0x14, 0x0D, 0x0D, 0x0E, 0x0F, 0x15, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, + 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, +}; + +static const uint8_t clv_dc_bits[NUM_DC_CODES] = { + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 21, 22, 22, 19, 20, + 20, 19, 18, 18, 15, 17, 17, 16, + 14, 15, 12, 13, 14, 14, 14, 12, + 12, 12, 11, 11, 11, 10, 10, 10, + 10, 10, 10, 9, 9, 9, 8, 8, + 7, 7, 7, 6, 5, 5, 3, 1, + 3, 5, 5, 6, 7, 7, 7, 8, + 8, 8, 9, 9, 9, 9, 10, 11, + 10, 11, 11, 12, 12, 12, 12, 13, + 14, 14, 14, 14, 15, 15, 16, 17, + 16, 17, 18, 18, 19, 19, 19, 19, + 21, 19, 20, 19, 19, 21, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, +}; + +static const uint16_t clv_ac_syms[NUM_AC_CODES] = { + 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, + 0x0009, 0x000A, 0x000B, 0x000C, 0x0011, 0x0012, 0x0013, 0x0014, + 0x0015, 0x0016, 0x0021, 0x0022, 0x0023, 0x0024, 0x0031, 0x0032, + 0x0033, 0x0041, 0x0042, 0x0043, 0x0051, 0x0052, 0x0053, 0x0061, + 0x0062, 0x0063, 0x0071, 0x0072, 0x0081, 0x0082, 0x0091, 0x0092, + 0x00A1, 0x00A2, 0x00B1, 0x00C1, 0x00D1, 0x00E1, 0x00F1, 0x0101, + 0x0111, 0x0121, 0x0131, 0x0141, 0x0151, 0x0161, 0x0171, 0x0181, + 0x0191, 0x01A1, 0x1001, 0x1002, 0x1003, 0x1011, 0x1012, 0x1021, + 0x1031, 0x1041, 0x1051, 0x1061, 0x1071, 0x1081, 0x1091, 0x10A1, + 0x10B1, 0x10C1, 0x10D1, 0x10E1, 0x10F1, 0x1101, 0x1111, 0x1121, + 0x1131, 0x1141, 0x1151, 0x1161, 0x1171, 0x1181, 0x1191, 0x11A1, + 0x11B1, 0x11C1, 0x11D1, 0x11E1, 0x11F1, 0x1201, 0x1211, 0x1221, + 0x1231, 0x1241, 0x1251, 0x1261, 0x1271, 0x1281, 0x1BFF, +}; + +static const uint8_t clv_ac_codes[NUM_AC_CODES] = { + 0x02, 0x0F, 0x15, 0x17, 0x1F, 0x25, 0x24, 0x21, + 0x20, 0x07, 0x06, 0x20, 0x06, 0x14, 0x1E, 0x0F, + 0x21, 0x50, 0x0E, 0x1D, 0x0E, 0x51, 0x0D, 0x23, + 0x0D, 0x0C, 0x22, 0x52, 0x0B, 0x0C, 0x53, 0x13, + 0x0B, 0x54, 0x12, 0x0A, 0x11, 0x09, 0x10, 0x08, + 0x16, 0x55, 0x15, 0x14, 0x1C, 0x1B, 0x21, 0x20, + 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x22, 0x23, + 0x56, 0x57, 0x07, 0x19, 0x05, 0x0F, 0x04, 0x0E, + 0x0D, 0x0C, 0x13, 0x12, 0x11, 0x10, 0x1A, 0x19, + 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x18, 0x17, + 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x07, 0x06, + 0x05, 0x04, 0x24, 0x25, 0x26, 0x27, 0x58, 0x59, + 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x03, +}; + +static const uint8_t clv_ac_bits[NUM_AC_CODES] = { + 2, 4, 6, 7, 8, 9, 9, 10, + 10, 11, 11, 11, 3, 6, 8, 10, + 11, 12, 4, 8, 10, 12, 5, 9, + 10, 5, 9, 12, 5, 10, 12, 6, + 10, 12, 6, 10, 6, 10, 6, 10, + 7, 12, 7, 7, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 11, 11, + 12, 12, 4, 9, 11, 6, 11, 6, + 6, 6, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 10, 10, + 10, 10, 11, 11, 11, 11, 12, 12, + 12, 12, 12, 12, 12, 12, 7, +}; + +static const uint8_t clv_flagsy_0_bits[] = { + 3, 4, 4, 4, 4, 4, 6, 5, 4, 7, 4, 5, 4, 7, 5, 2, +}; + +static const uint16_t clv_flagsy_0_codes[] = { + 0x0002, 0x0009, 0x000B, 0x0006, 0x000C, 0x0007, 0x003E, 0x001C, + 0x000D, 0x007E, 0x000A, 0x001D, 0x0008, 0x007F, 0x001E, 0x0000, +}; + +static const uint8_t clv_flagsy_1_bits[] = { + 2, 4, 4, 3, 4, 4, 7, 6, 4, 6, 4, 6, 4, 8, 8, 3, +}; + +static const uint16_t clv_flagsy_1_codes[] = { + 0x0000, 0x000A, 0x000C, 0x0003, 0x000B, 0x0009, 0x007E, 0x003D, + 0x000D, 0x003E, 0x000E, 0x003C, 0x0008, 0x00FE, 0x00FF, 0x0002, +}; + +static const uint8_t clv_flagsy_2_bits[] = { + 1, 4, 4, 4, 4, 5, 7, 5, 4, 6, 5, 8, 4, 9, 10, 10, +}; + +static const uint16_t clv_flagsy_2_codes[] = { + 0x0000, 0x000C, 0x000B, 0x0008, 0x000A, 0x001C, 0x007E, 0x001D, + 0x000D, 0x003E, 0x001E, 0x00FE, 0x0009, 0x01FE, 0x03FE, 0x03FF, +}; + +static const uint8_t clv_flagsu_0_bits[] = { + 1, 4, 4, 4, 5, 5, 9, 7, 5, 9, 4, 7, 4, 8, 7, 4, +}; + +static const uint16_t clv_flagsu_0_codes[] = { + 0x0000, 0x000B, 0x000D, 0x0009, 0x001D, 0x001C, 0x01FF, 0x007D, + 0x001E, 0x01FE, 0x000C, 0x007C, 0x000A, 0x00FE, 0x007E, 0x0008, +}; + +static const uint8_t clv_flagsu_1_bits[] = { + 1, 4, 4, 4, 4, 4, 8, 6, 4, 8, 5, 8, 4, 10, 9, 10, +}; + +static const uint16_t clv_flagsu_1_codes[] = { + 0x0000, 0x000C, 0x0008, 0x000A, 0x000B, 0x000E, 0x00FD, 0x003E, + 0x000D, 0x00FC, 0x001E, 0x00FE, 0x0009, 0x03FE, 0x01FE, 0x03FF, +}; + +static const uint8_t clv_flagsv_0_bits[] = { + 1, 4, 5, 4, 5, 5, 8, 10, 5, 9, 5, 6, 4, 10, 7, 3, +}; + +static const uint16_t clv_flagsv_0_codes[] = { + 0x0000, 0x000A, 0x001B, 0x000C, 0x001E, 0x001C, 0x00FE, 0x03FE, + 0x001D, 0x01FE, 0x001A, 0x003E, 0x000B, 0x03FF, 0x007E, 0x0004, +}; + +static const uint8_t clv_flagsv_1_bits[] = { + 1, 4, 4, 4, 4, 5, 8, 6, 3, 7, 5, 10, 5, 11, 9, 11, +}; + +static const uint16_t clv_flagsv_1_codes[] = { + 0x0000, 0x000D, 0x000C, 0x000A, 0x000B, 0x001D, 0x00FE, 0x003E, + 0x0004, 0x007E, 0x001E, 0x03FE, 0x001C, 0x07FE, 0x01FE, 0x07FF, +}; + +static const uint8_t clv_mvy_0_bits[] = { + 16, 14, 13, 13, 13, 12, 11, 11, 9, 11, 11, 12, 13, 13, 13, 14, + 16, 15, 14, 14, 14, 13, 13, 12, 10, 7, 10, 12, 13, 13, 14, 14, + 14, 15, 15, 14, 14, 14, 13, 13, 11, 10, 7, 10, 11, 13, 13, 14, + 14, 14, 15, 15, 14, 14, 13, 13, 12, 11, 10, 7, 10, 11, 12, 13, + 13, 14, 14, 15, 16, 15, 14, 12, 12, 12, 11, 10, 6, 10, 11, 12, + 12, 12, 14, 15, 16, 15, 14, 13, 13, 12, 11, 10, 9, 6, 9, 10, + 11, 12, 13, 13, 14, 15, 14, 14, 13, 12, 12, 11, 10, 8, 6, 8, + 10, 11, 12, 12, 13, 14, 14, 14, 13, 13, 13, 11, 11, 9, 7, 4, + 7, 9, 11, 11, 12, 13, 13, 14, 11, 10, 10, 9, 9, 8, 7, 5, + 1, 5, 7, 8, 9, 9, 10, 10, 11, 14, 13, 13, 12, 11, 11, 9, + 7, 4, 7, 9, 11, 11, 13, 13, 13, 14, 14, 14, 13, 12, 12, 11, + 10, 8, 6, 8, 10, 11, 12, 12, 13, 14, 14, 15, 14, 13, 13, 12, + 11, 10, 9, 7, 9, 10, 11, 12, 13, 13, 14, 15, 16, 15, 14, 12, + 12, 12, 11, 10, 6, 10, 11, 12, 12, 12, 14, 15, 16, 15, 14, 14, + 13, 13, 12, 11, 10, 7, 10, 11, 12, 13, 13, 14, 14, 15, 15, 14, + 14, 14, 13, 13, 11, 10, 7, 10, 11, 13, 13, 14, 14, 14, 15, 15, + 14, 14, 14, 13, 13, 12, 10, 7, 10, 12, 13, 13, 14, 14, 14, 15, + 16, 14, 13, 13, 13, 12, 11, 11, 9, 11, 11, 12, 13, 13, 13, 14, + 16, 6, +}; + +static const uint16_t clv_mvy_0_codes[] = { + 0xFFFD, 0x3FE5, 0x1FD8, 0x1FC4, 0x1FBC, 0x0FCB, 0x07CF, 0x07C4, + 0x01D7, 0x07C6, 0x07CE, 0x0FCA, 0x1FBD, 0x1FC2, 0x1FD9, 0x3FE4, + 0xFFFE, 0x7FF0, 0x3FEF, 0x3FD2, 0x3FC9, 0x1FCC, 0x1FC0, 0x0FB6, + 0x03D6, 0x0070, 0x03D7, 0x0FB7, 0x1FC1, 0x1FCD, 0x3FCB, 0x3FD0, + 0x3FED, 0x7FF2, 0x7FFB, 0x3FDC, 0x3FD9, 0x3FD4, 0x1FB6, 0x1FAE, + 0x07C0, 0x03BC, 0x006D, 0x03BD, 0x07C1, 0x1FAF, 0x1FB7, 0x3FD1, + 0x3FDB, 0x3FDF, 0x7FF9, 0x7FEE, 0x3FF0, 0x3FC7, 0x1FC9, 0x1FA7, + 0x0FAD, 0x07D2, 0x03CE, 0x006C, 0x03CF, 0x07D0, 0x0FAF, 0x1FA6, + 0x1FC6, 0x3FC4, 0x3FF1, 0x7FED, 0xFFFB, 0x7FF6, 0x3FE6, 0x0FCC, + 0x0FC4, 0x0FB0, 0x07B0, 0x03C6, 0x0031, 0x03C7, 0x07B1, 0x0FB1, + 0x0FC5, 0x0FCD, 0x3FEA, 0x7FF7, 0xFFF9, 0x7FE9, 0x3FCE, 0x1FCF, + 0x1FB2, 0x0FB8, 0x07BC, 0x03D0, 0x01DA, 0x002F, 0x01DB, 0x03D1, + 0x07BE, 0x0FBA, 0x1FB4, 0x1FD0, 0x3FCD, 0x7FEB, 0x3FE1, 0x3FC1, + 0x1FD3, 0x0FC3, 0x0FBE, 0x07B6, 0x03C4, 0x00E4, 0x002D, 0x00E5, + 0x03C5, 0x07B7, 0x0FBF, 0x0FC1, 0x1FD2, 0x3FC3, 0x3FE2, 0x3FBF, + 0x1FDB, 0x1FAD, 0x1FA5, 0x07CB, 0x07BB, 0x01D5, 0x0068, 0x0008, + 0x0065, 0x01D2, 0x07B8, 0x07C8, 0x0FD0, 0x1FAA, 0x1FDA, 0x3FBC, + 0x07D4, 0x03CA, 0x03C0, 0x01D8, 0x01D0, 0x00E6, 0x0069, 0x0014, + 0x0000, 0x0015, 0x006A, 0x00E7, 0x01D1, 0x01D9, 0x03C1, 0x03CB, + 0x07D5, 0x3FBE, 0x1FDC, 0x1FAB, 0x0FD1, 0x07C9, 0x07B9, 0x01D3, + 0x0066, 0x0009, 0x0067, 0x01D4, 0x07BA, 0x07CA, 0x1FA4, 0x1FAC, + 0x1FDD, 0x3FBD, 0x3FE0, 0x3FC0, 0x1FD5, 0x0FC0, 0x0FBC, 0x07B4, + 0x03C2, 0x00E2, 0x002C, 0x00E3, 0x03C3, 0x07B5, 0x0FBD, 0x0FC2, + 0x1FD7, 0x3FC2, 0x3FE3, 0x7FEA, 0x3FCC, 0x1FCE, 0x1FB3, 0x0FB9, + 0x07BD, 0x03D2, 0x01DC, 0x0064, 0x01DD, 0x03D3, 0x07BF, 0x0FBB, + 0x1FB5, 0x1FD1, 0x3FCF, 0x7FE8, 0xFFFA, 0x7FF4, 0x3FEB, 0x0FCE, + 0x0FC6, 0x0FB2, 0x07B2, 0x03C8, 0x0030, 0x03C9, 0x07B3, 0x0FB3, + 0x0FC7, 0x0FCF, 0x3FE9, 0x7FF5, 0xFFF8, 0x7FF3, 0x3FF3, 0x3FC6, + 0x1FC8, 0x1FA8, 0x0FAC, 0x07D1, 0x03CC, 0x006B, 0x03CD, 0x07D3, + 0x0FAE, 0x1FA9, 0x1FC7, 0x3FC5, 0x3FF2, 0x7FEC, 0x7FFA, 0x3FDE, + 0x3FDA, 0x3FD7, 0x1FB9, 0x1FB0, 0x07C2, 0x03BE, 0x006E, 0x03BF, + 0x07C3, 0x1FB1, 0x1FB8, 0x3FD3, 0x3FD8, 0x3FDD, 0x7FF8, 0x7FEF, + 0x3FEE, 0x3FD6, 0x3FC8, 0x1FCB, 0x1FBE, 0x0FB5, 0x03D4, 0x006F, + 0x03D5, 0x0FB4, 0x1FBF, 0x1FCA, 0x3FCA, 0x3FD5, 0x3FEC, 0x7FF1, + 0xFFFF, 0x3FE8, 0x1FD4, 0x1FC5, 0x1FBA, 0x0FC9, 0x07CD, 0x07C7, + 0x01D6, 0x07C5, 0x07CC, 0x0FC8, 0x1FBB, 0x1FC3, 0x1FD6, 0x3FE7, + 0xFFFC, 0x002E, +}; + +static const uint16_t clv_mvy_0_syms[] = { + 0xF8F8, 0xF9F8, 0xFAF8, 0xFBF8, 0xFCF8, 0xFDF8, 0xFEF8, 0xFFF8, + 0x00F8, 0x01F8, 0x02F8, 0x03F8, 0x04F8, 0x05F8, 0x06F8, 0x07F8, + 0x08F8, 0xF8F9, 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, + 0xFFF9, 0x00F9, 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, + 0x07F9, 0x08F9, 0xF8FA, 0xF9FA, 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, + 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, 0x02FA, 0x03FA, 0x04FA, 0x05FA, + 0x06FA, 0x07FA, 0x08FA, 0xF8FB, 0xF9FB, 0xFAFB, 0xFBFB, 0xFCFB, + 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, 0x03FB, 0x04FB, + 0x05FB, 0x06FB, 0x07FB, 0x08FB, 0xF8FC, 0xF9FC, 0xFAFC, 0xFBFC, + 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, 0x00FC, 0x01FC, 0x02FC, 0x03FC, + 0x04FC, 0x05FC, 0x06FC, 0x07FC, 0x08FC, 0xF8FD, 0xF9FD, 0xFAFD, + 0xFBFD, 0xFCFD, 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, + 0x03FD, 0x04FD, 0x05FD, 0x06FD, 0x07FD, 0x08FD, 0xF8FE, 0xF9FE, + 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, + 0x02FE, 0x03FE, 0x04FE, 0x05FE, 0x06FE, 0x07FE, 0x08FE, 0xF8FF, + 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, 0xFFFF, 0x00FF, + 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, 0x07FF, 0x08FF, + 0xF800, 0xF900, 0xFA00, 0xFB00, 0xFC00, 0xFD00, 0xFE00, 0xFF00, + 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, + 0x0800, 0xF801, 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, + 0xFF01, 0x0001, 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, + 0x0701, 0x0801, 0xF802, 0xF902, 0xFA02, 0xFB02, 0xFC02, 0xFD02, + 0xFE02, 0xFF02, 0x0002, 0x0102, 0x0202, 0x0302, 0x0402, 0x0502, + 0x0602, 0x0702, 0x0802, 0xF803, 0xF903, 0xFA03, 0xFB03, 0xFC03, + 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, 0x0303, 0x0403, + 0x0503, 0x0603, 0x0703, 0x0803, 0xF804, 0xF904, 0xFA04, 0xFB04, + 0xFC04, 0xFD04, 0xFE04, 0xFF04, 0x0004, 0x0104, 0x0204, 0x0304, + 0x0404, 0x0504, 0x0604, 0x0704, 0x0804, 0xF805, 0xF905, 0xFA05, + 0xFB05, 0xFC05, 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, + 0x0305, 0x0405, 0x0505, 0x0605, 0x0705, 0x0805, 0xF806, 0xF906, + 0xFA06, 0xFB06, 0xFC06, 0xFD06, 0xFE06, 0xFF06, 0x0006, 0x0106, + 0x0206, 0x0306, 0x0406, 0x0506, 0x0606, 0x0706, 0x0806, 0xF807, + 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, 0xFF07, 0x0007, + 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, 0x0707, 0x0807, + 0xF808, 0xF908, 0xFA08, 0xFB08, 0xFC08, 0xFD08, 0xFE08, 0xFF08, + 0x0008, 0x0108, 0x0208, 0x0308, 0x0408, 0x0508, 0x0608, 0x0708, + 0x0808, 0x0909, +}; + +static const uint8_t clv_mvy_1_bits[] = { + 15, 15, 15, 15, 14, 14, 13, 13, 11, 9, 11, 13, 13, 14, 14, 15, + 15, 15, 15, 15, 14, 14, 13, 13, 12, 12, 12, 10, 9, 10, 12, 12, + 12, 13, 13, 14, 14, 15, 15, 15, 14, 14, 13, 13, 13, 12, 11, 8, + 11, 12, 13, 13, 13, 14, 14, 15, 15, 14, 14, 14, 14, 13, 12, 12, + 12, 10, 8, 10, 12, 12, 12, 13, 14, 14, 14, 14, 15, 14, 14, 13, + 13, 12, 12, 11, 10, 8, 10, 11, 12, 12, 13, 13, 14, 14, 15, 14, + 14, 13, 13, 13, 12, 12, 11, 9, 7, 9, 11, 12, 12, 13, 13, 13, + 14, 14, 14, 14, 13, 13, 13, 12, 11, 10, 9, 7, 9, 10, 11, 12, + 13, 13, 13, 14, 14, 14, 13, 13, 12, 12, 11, 11, 10, 8, 7, 8, + 10, 11, 11, 12, 12, 13, 13, 14, 13, 13, 13, 12, 11, 11, 10, 9, + 6, 4, 6, 9, 10, 11, 12, 12, 13, 13, 13, 12, 11, 10, 10, 10, + 9, 9, 7, 5, 1, 5, 7, 9, 9, 10, 10, 10, 11, 12, 13, 13, + 13, 12, 11, 11, 10, 9, 6, 4, 6, 9, 10, 11, 11, 12, 13, 13, + 13, 14, 13, 13, 12, 12, 11, 11, 10, 8, 7, 8, 10, 11, 11, 12, + 12, 13, 13, 14, 14, 14, 13, 13, 13, 12, 11, 10, 9, 7, 9, 10, + 11, 12, 13, 13, 13, 14, 14, 14, 14, 13, 13, 13, 12, 12, 11, 9, + 7, 9, 11, 12, 12, 13, 13, 13, 14, 14, 15, 14, 14, 13, 13, 12, + 12, 11, 10, 8, 10, 11, 12, 12, 13, 13, 14, 14, 15, 14, 14, 14, + 14, 13, 12, 12, 12, 10, 8, 10, 12, 12, 12, 13, 14, 14, 14, 14, + 15, 15, 14, 14, 13, 13, 13, 12, 11, 8, 11, 12, 13, 13, 13, 14, + 14, 15, 15, 15, 14, 14, 13, 13, 12, 12, 12, 10, 9, 10, 12, 12, + 12, 13, 13, 14, 14, 15, 15, 15, 15, 15, 14, 14, 13, 13, 11, 9, + 11, 13, 13, 14, 14, 15, 15, 15, 15, 5, +}; + +static const uint16_t clv_mvy_1_codes[] = { + 0x7FF9, 0x7FF6, 0x7FEB, 0x7FE3, 0x3FCF, 0x3FB3, 0x1FBD, 0x1FA1, + 0x07AD, 0x01CE, 0x07AF, 0x1FA0, 0x1FBB, 0x3FB0, 0x3FCC, 0x7FE2, + 0x7FE9, 0x7FF4, 0x7FFB, 0x7FF1, 0x3FE7, 0x3FBD, 0x1FA5, 0x1F9B, + 0x0FB4, 0x0FAF, 0x0FAA, 0x03CC, 0x01CD, 0x03CD, 0x0FAB, 0x0FAD, + 0x0FB1, 0x1F9C, 0x1FA3, 0x3FBE, 0x3FE6, 0x7FF0, 0x7FFC, 0x7FE5, + 0x3FB5, 0x3FAE, 0x1FB4, 0x1FAA, 0x1F97, 0x0F85, 0x07A2, 0x00DD, + 0x07A3, 0x0F86, 0x1F99, 0x1FAD, 0x1FB2, 0x3FAC, 0x3FB7, 0x7FE4, + 0x7FFD, 0x3FEA, 0x3FD8, 0x3FC3, 0x3FBB, 0x1FC9, 0x0FBC, 0x0F97, + 0x0F8F, 0x03B8, 0x00DA, 0x03B9, 0x0F90, 0x0F98, 0x0FB9, 0x1FC6, + 0x3FBA, 0x3FC0, 0x3FD9, 0x3FEB, 0x7FEF, 0x3FEE, 0x3FD7, 0x1FC3, + 0x1F96, 0x0FC0, 0x0FA8, 0x07AA, 0x03BE, 0x00D9, 0x03BF, 0x07AB, + 0x0FA7, 0x0FBF, 0x1F98, 0x1FC5, 0x3FD6, 0x3FEF, 0x7FEE, 0x3FDC, + 0x3FCA, 0x1FBF, 0x1F8B, 0x1F87, 0x0FA2, 0x0F94, 0x07A5, 0x01D4, + 0x0069, 0x01D5, 0x07A6, 0x0F95, 0x0FA3, 0x1F89, 0x1F8D, 0x1FC0, + 0x3FC6, 0x3FDE, 0x3FE0, 0x3FD3, 0x1FB8, 0x1F8F, 0x1F84, 0x0F89, + 0x07BC, 0x03C6, 0x01C6, 0x0067, 0x01C7, 0x03C7, 0x07BD, 0x0F87, + 0x1F82, 0x1F8A, 0x1FB6, 0x3FD1, 0x3FE2, 0x3FC5, 0x1FCE, 0x1FAE, + 0x0FB5, 0x0F8B, 0x07B4, 0x07B0, 0x03B4, 0x00DE, 0x0064, 0x00DF, + 0x03B5, 0x07B1, 0x07B5, 0x0F8C, 0x0FB6, 0x1FAF, 0x1FD1, 0x3FCB, + 0x1FD3, 0x1FCC, 0x1FA7, 0x0F9B, 0x07BE, 0x079C, 0x03C0, 0x01C8, + 0x002E, 0x0008, 0x002F, 0x01C9, 0x03C1, 0x079D, 0x0F82, 0x0F9A, + 0x1FA9, 0x1FCA, 0x1FD4, 0x0F9F, 0x07B6, 0x03C8, 0x03B2, 0x03B0, + 0x01D6, 0x01D0, 0x006A, 0x0014, 0x0000, 0x0015, 0x006B, 0x01D1, + 0x01D7, 0x03B1, 0x03B3, 0x03C9, 0x07B7, 0x0FA0, 0x1FD5, 0x1FCB, + 0x1FAB, 0x0F9C, 0x07BF, 0x079E, 0x03C2, 0x01CA, 0x0030, 0x0009, + 0x0031, 0x01CB, 0x03C3, 0x079F, 0x07C0, 0x0F9D, 0x1FAC, 0x1FCD, + 0x1FD2, 0x3FC8, 0x1FD0, 0x1FB0, 0x0FB7, 0x0F8D, 0x07B8, 0x07B2, + 0x03B6, 0x00E0, 0x0065, 0x00E1, 0x03B7, 0x07B3, 0x07B9, 0x0F8E, + 0x0FB8, 0x1FB1, 0x1FCF, 0x3FC9, 0x3FE1, 0x3FD2, 0x1FB7, 0x1F8E, + 0x1F83, 0x0F88, 0x07BA, 0x03C4, 0x01C4, 0x0066, 0x01C5, 0x03C5, + 0x07BB, 0x0F8A, 0x1F85, 0x1F90, 0x1FB9, 0x3FD0, 0x3FE3, 0x3FDD, + 0x3FC7, 0x1FC1, 0x1F91, 0x1F88, 0x0FA4, 0x0F96, 0x07A7, 0x01D2, + 0x0068, 0x01D3, 0x07A4, 0x0F93, 0x0FA1, 0x1F86, 0x1F8C, 0x1FBE, + 0x3FC4, 0x3FDF, 0x7FED, 0x3FEC, 0x3FD4, 0x1FC4, 0x1F92, 0x0FBD, + 0x0FA5, 0x07A8, 0x03BC, 0x00D8, 0x03BD, 0x07A9, 0x0FA6, 0x0FBE, + 0x1F93, 0x1FC2, 0x3FD5, 0x3FED, 0x7FEC, 0x3FE8, 0x3FDB, 0x3FC1, + 0x3FB9, 0x1FC7, 0x0FBA, 0x0F9E, 0x0F91, 0x03BA, 0x00DB, 0x03BB, + 0x0F92, 0x0F99, 0x0FBB, 0x1FC8, 0x3FB8, 0x3FC2, 0x3FDA, 0x3FE9, + 0x7FFF, 0x7FE7, 0x3FB6, 0x3FAF, 0x1FB3, 0x1FA6, 0x1F94, 0x0F83, + 0x07A0, 0x00DC, 0x07A1, 0x0F84, 0x1F95, 0x1FA8, 0x1FB5, 0x3FAD, + 0x3FB4, 0x7FE6, 0x7FFE, 0x7FF3, 0x3FE5, 0x3FBC, 0x1FA4, 0x1F9D, + 0x0FB2, 0x0FAE, 0x0FA9, 0x03CA, 0x01CC, 0x03CB, 0x0FAC, 0x0FB0, + 0x0FB3, 0x1F9A, 0x1FA2, 0x3FBF, 0x3FE4, 0x7FF2, 0x7FF8, 0x7FF5, + 0x7FEA, 0x7FE0, 0x3FCD, 0x3FB1, 0x1FBA, 0x1F9F, 0x07AE, 0x01CF, + 0x07AC, 0x1F9E, 0x1FBC, 0x3FB2, 0x3FCE, 0x7FE1, 0x7FE8, 0x7FF7, + 0x7FFA, 0x0016, +}; + +static const uint16_t clv_mvy_1_syms[] = { + 0xF7F7, 0xF8F7, 0xF9F7, 0xFAF7, 0xFBF7, 0xFCF7, 0xFDF7, 0xFEF7, + 0xFFF7, 0x00F7, 0x01F7, 0x02F7, 0x03F7, 0x04F7, 0x05F7, 0x06F7, + 0x07F7, 0x08F7, 0x09F7, 0xF7F8, 0xF8F8, 0xF9F8, 0xFAF8, 0xFBF8, + 0xFCF8, 0xFDF8, 0xFEF8, 0xFFF8, 0x00F8, 0x01F8, 0x02F8, 0x03F8, + 0x04F8, 0x05F8, 0x06F8, 0x07F8, 0x08F8, 0x09F8, 0xF7F9, 0xF8F9, + 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, 0xFFF9, 0x00F9, + 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, 0x07F9, 0x08F9, + 0x09F9, 0xF7FA, 0xF8FA, 0xF9FA, 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, + 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, 0x02FA, 0x03FA, 0x04FA, 0x05FA, + 0x06FA, 0x07FA, 0x08FA, 0x09FA, 0xF7FB, 0xF8FB, 0xF9FB, 0xFAFB, + 0xFBFB, 0xFCFB, 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, + 0x03FB, 0x04FB, 0x05FB, 0x06FB, 0x07FB, 0x08FB, 0x09FB, 0xF7FC, + 0xF8FC, 0xF9FC, 0xFAFC, 0xFBFC, 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, + 0x00FC, 0x01FC, 0x02FC, 0x03FC, 0x04FC, 0x05FC, 0x06FC, 0x07FC, + 0x08FC, 0x09FC, 0xF7FD, 0xF8FD, 0xF9FD, 0xFAFD, 0xFBFD, 0xFCFD, + 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, 0x03FD, 0x04FD, + 0x05FD, 0x06FD, 0x07FD, 0x08FD, 0x09FD, 0xF7FE, 0xF8FE, 0xF9FE, + 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, + 0x02FE, 0x03FE, 0x04FE, 0x05FE, 0x06FE, 0x07FE, 0x08FE, 0x09FE, + 0xF7FF, 0xF8FF, 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, + 0xFFFF, 0x00FF, 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, + 0x07FF, 0x08FF, 0x09FF, 0xF700, 0xF800, 0xF900, 0xFA00, 0xFB00, + 0xFC00, 0xFD00, 0xFE00, 0xFF00, 0x0000, 0x0100, 0x0200, 0x0300, + 0x0400, 0x0500, 0x0600, 0x0700, 0x0800, 0x0900, 0xF701, 0xF801, + 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, 0xFF01, 0x0001, + 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, 0x0701, 0x0801, + 0x0901, 0xF702, 0xF802, 0xF902, 0xFA02, 0xFB02, 0xFC02, 0xFD02, + 0xFE02, 0xFF02, 0x0002, 0x0102, 0x0202, 0x0302, 0x0402, 0x0502, + 0x0602, 0x0702, 0x0802, 0x0902, 0xF703, 0xF803, 0xF903, 0xFA03, + 0xFB03, 0xFC03, 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, + 0x0303, 0x0403, 0x0503, 0x0603, 0x0703, 0x0803, 0x0903, 0xF704, + 0xF804, 0xF904, 0xFA04, 0xFB04, 0xFC04, 0xFD04, 0xFE04, 0xFF04, + 0x0004, 0x0104, 0x0204, 0x0304, 0x0404, 0x0504, 0x0604, 0x0704, + 0x0804, 0x0904, 0xF705, 0xF805, 0xF905, 0xFA05, 0xFB05, 0xFC05, + 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, 0x0305, 0x0405, + 0x0505, 0x0605, 0x0705, 0x0805, 0x0905, 0xF706, 0xF806, 0xF906, + 0xFA06, 0xFB06, 0xFC06, 0xFD06, 0xFE06, 0xFF06, 0x0006, 0x0106, + 0x0206, 0x0306, 0x0406, 0x0506, 0x0606, 0x0706, 0x0806, 0x0906, + 0xF707, 0xF807, 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, + 0xFF07, 0x0007, 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, + 0x0707, 0x0807, 0x0907, 0xF708, 0xF808, 0xF908, 0xFA08, 0xFB08, + 0xFC08, 0xFD08, 0xFE08, 0xFF08, 0x0008, 0x0108, 0x0208, 0x0308, + 0x0408, 0x0508, 0x0608, 0x0708, 0x0808, 0x0908, 0xF709, 0xF809, + 0xF909, 0xFA09, 0xFB09, 0xFC09, 0xFD09, 0xFE09, 0xFF09, 0x0009, + 0x0109, 0x0209, 0x0309, 0x0409, 0x0509, 0x0609, 0x0709, 0x0809, + 0x0909, 0x0A0A, +}; + +static const uint8_t clv_mvy_2_bits[] = { + 16, 16, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, 12, 11, + 12, 13, 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, + 15, 15, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13, 13, 11, 10, 11, + 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 15, + 15, 15, 15, 14, 14, 14, 14, 14, 14, 13, 13, 13, 11, 10, 11, 13, + 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 15, 15, + 15, 14, 14, 14, 14, 14, 14, 13, 13, 13, 12, 11, 9, 11, 12, 13, + 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, 15, 16, 16, 15, 15, 14, + 14, 13, 13, 13, 13, 13, 13, 13, 12, 11, 11, 9, 11, 11, 12, 13, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 15, 16, 16, 15, 15, 15, 14, + 13, 13, 13, 13, 13, 13, 13, 12, 11, 11, 9, 11, 11, 12, 13, 13, + 13, 13, 13, 13, 13, 14, 15, 15, 15, 16, 16, 15, 15, 15, 15, 14, + 14, 13, 13, 13, 12, 12, 12, 11, 11, 9, 11, 11, 12, 12, 12, 13, + 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 15, 15, 14, 14, 14, 13, + 13, 13, 12, 12, 12, 12, 11, 10, 8, 10, 11, 12, 12, 12, 12, 13, + 13, 13, 14, 14, 14, 15, 15, 16, 16, 15, 14, 14, 14, 13, 13, 13, + 13, 12, 12, 12, 11, 11, 10, 8, 10, 11, 11, 12, 12, 12, 13, 13, + 13, 13, 14, 14, 14, 15, 16, 15, 15, 14, 14, 13, 13, 13, 13, 13, + 12, 12, 12, 11, 10, 9, 8, 9, 10, 11, 12, 12, 12, 13, 13, 13, + 13, 13, 14, 14, 15, 15, 15, 15, 14, 14, 13, 13, 13, 13, 13, 12, + 12, 11, 11, 10, 10, 7, 10, 10, 11, 11, 12, 12, 13, 13, 13, 13, + 13, 14, 14, 15, 15, 14, 14, 14, 14, 13, 13, 12, 12, 12, 12, 12, + 11, 11, 10, 9, 7, 9, 10, 11, 11, 12, 12, 12, 12, 12, 13, 13, + 14, 14, 14, 14, 15, 13, 13, 13, 13, 13, 12, 12, 12, 11, 11, 11, + 11, 10, 8, 7, 8, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 13, + 13, 13, 15, 14, 14, 14, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, + 9, 8, 6, 8, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 14, + 14, 14, 16, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 9, 9, 8, + 6, 4, 6, 8, 9, 9, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, + 16, 12, 12, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 8, 7, 4, + 2, 4, 7, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, + 16, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 9, 9, 8, 6, 4, + 6, 8, 9, 9, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 16, 14, + 14, 14, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 9, 8, 6, 8, + 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 13, + 13, 13, 13, 13, 12, 12, 12, 11, 11, 11, 11, 10, 8, 7, 8, 10, + 11, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 13, 15, 14, 14, 14, + 14, 13, 13, 12, 12, 12, 12, 12, 11, 11, 10, 9, 7, 9, 10, 11, + 11, 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 14, 14, + 13, 13, 13, 13, 13, 12, 12, 11, 11, 10, 10, 7, 10, 10, 11, 11, + 12, 12, 13, 13, 13, 13, 13, 14, 14, 15, 15, 15, 15, 14, 14, 13, + 13, 13, 13, 13, 12, 12, 12, 11, 10, 9, 8, 9, 10, 11, 12, 12, + 12, 13, 13, 13, 13, 13, 14, 14, 15, 15, 16, 15, 14, 14, 14, 13, + 13, 13, 13, 12, 12, 12, 11, 11, 10, 8, 10, 11, 11, 12, 12, 12, + 13, 13, 13, 13, 14, 14, 14, 15, 16, 16, 15, 15, 14, 14, 14, 13, + 13, 13, 12, 12, 12, 12, 11, 10, 8, 10, 11, 12, 12, 12, 12, 13, + 13, 13, 14, 14, 14, 15, 15, 16, 16, 15, 15, 15, 15, 14, 14, 13, + 13, 13, 12, 12, 12, 11, 11, 9, 11, 11, 12, 12, 12, 13, 13, 13, + 14, 14, 15, 15, 15, 15, 16, 16, 15, 15, 15, 14, 13, 13, 13, 13, + 13, 13, 13, 12, 11, 11, 9, 11, 11, 12, 13, 13, 13, 13, 13, 13, + 13, 14, 15, 15, 15, 16, 16, 15, 15, 14, 14, 13, 13, 13, 13, 13, + 13, 13, 12, 11, 11, 9, 11, 11, 12, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 15, 16, 16, 15, 15, 15, 14, 14, 14, 14, 14, 14, 13, + 13, 13, 12, 11, 9, 11, 12, 13, 13, 13, 14, 14, 14, 14, 14, 14, + 15, 15, 15, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 13, + 13, 13, 11, 10, 11, 13, 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, + 15, 15, 16, 16, 15, 15, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13, + 13, 12, 10, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, + 15, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, + 12, 11, 12, 13, 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 16, + 16, 7, +}; + +static const uint16_t clv_mvy_2_codes[] = { + 0xFFF5, 0xFFD8, 0x7FE6, 0x7FB9, 0x7FB5, 0x7FB0, 0x7FA0, 0x7F99, + 0x7F93, 0x3FAA, 0x3F9B, 0x3F52, 0x1F76, 0x1EF5, 0x0F0B, 0x06F0, + 0x0F08, 0x1EF0, 0x1F75, 0x3F53, 0x3F9A, 0x3FA8, 0x7F94, 0x7F98, + 0x7F9E, 0x7FAE, 0x7FAF, 0x7FB7, 0x7FE9, 0xFFDB, 0xFFF6, 0xFFFD, + 0x7FD9, 0x7FCC, 0x7FC6, 0x7F9C, 0x7F80, 0x3FA5, 0x3F80, 0x3F6A, + 0x3F31, 0x1F54, 0x1F40, 0x1F11, 0x1F05, 0x075E, 0x0360, 0x075F, + 0x1F07, 0x1F12, 0x1F43, 0x1F56, 0x3F33, 0x3F68, 0x3F83, 0x3FA6, + 0x7F7F, 0x7F9A, 0x7FC9, 0x7FCA, 0x7FDB, 0xFFF8, 0xFFEC, 0x7FDE, + 0x7FE2, 0x7FA6, 0x7F6F, 0x3FA1, 0x3F8D, 0x3F5C, 0x3F39, 0x3F21, + 0x3F18, 0x1F58, 0x1F1E, 0x1EF1, 0x0740, 0x035A, 0x0741, 0x1EF2, + 0x1F1F, 0x1F5A, 0x3F19, 0x3F22, 0x3F3B, 0x3F5E, 0x3F8E, 0x3FA3, + 0x7F6B, 0x7FA2, 0x7FE3, 0x7FE1, 0xFFEE, 0xFFFC, 0x7FC3, 0x7FBC, + 0x7F71, 0x3F96, 0x3F86, 0x3F7A, 0x3F72, 0x3F59, 0x3F46, 0x1F0A, + 0x1EFD, 0x1ED0, 0x0F02, 0x0712, 0x019F, 0x0713, 0x0F03, 0x1ED3, + 0x1EFF, 0x1F09, 0x3F4A, 0x3F5A, 0x3F76, 0x3F7B, 0x3F87, 0x3F97, + 0x7F73, 0x7FBB, 0x7FBF, 0xFFFB, 0xFFEB, 0x7F88, 0x7F5C, 0x3F7C, + 0x3F3C, 0x1F60, 0x1F4C, 0x1F14, 0x1F0C, 0x1F00, 0x1EF9, 0x1ED8, + 0x0F42, 0x075A, 0x0714, 0x0186, 0x0715, 0x075B, 0x0F43, 0x1EDA, + 0x1EFA, 0x1F01, 0x1F0E, 0x1F15, 0x1F4D, 0x1F62, 0x3F3D, 0x3F7D, + 0x3FAC, 0x7F86, 0xFFE8, 0xFFE7, 0x7FA7, 0x7F8C, 0x7F68, 0x3F9C, + 0x1F7C, 0x1F6C, 0x1F69, 0x1EEC, 0x1EE4, 0x1ED5, 0x1ECD, 0x0EF0, + 0x0752, 0x06F6, 0x018C, 0x06F7, 0x0753, 0x0EF1, 0x1ECE, 0x1ED6, + 0x1EE5, 0x1EED, 0x1F6A, 0x1F6E, 0x1F7D, 0x3F9F, 0x7F66, 0x7F8A, + 0x7FA5, 0xFFE6, 0xFFDC, 0x7FDA, 0x7FC0, 0x7FAC, 0x7F61, 0x3F42, + 0x3F0E, 0x1F45, 0x1F2C, 0x1ECA, 0x0F27, 0x0EF6, 0x0EEE, 0x072E, + 0x06F4, 0x0185, 0x06F5, 0x072F, 0x0EEF, 0x0EF7, 0x0F28, 0x1ECB, + 0x1F2F, 0x1F46, 0x3F0F, 0x3F40, 0x7F5F, 0x7FB4, 0x7FC2, 0x7FDC, + 0xFFDA, 0xFFE0, 0x7F72, 0x7F63, 0x3F70, 0x3F1C, 0x3F16, 0x1F82, + 0x1EE2, 0x1EB2, 0x0F4C, 0x0EFC, 0x0EE0, 0x0ED3, 0x0722, 0x036C, + 0x00BF, 0x036D, 0x0723, 0x0ECC, 0x0EE1, 0x0EFF, 0x0F4D, 0x1EB3, + 0x1EE3, 0x1F83, 0x3F17, 0x3F1F, 0x3F75, 0x7F65, 0x7F70, 0xFFE2, + 0xFFD7, 0x7F76, 0x3F2B, 0x3F13, 0x3F0A, 0x1F33, 0x1F23, 0x1EB4, + 0x1EA0, 0x0F46, 0x0F32, 0x0F1A, 0x0756, 0x0728, 0x0356, 0x00B0, + 0x0357, 0x0729, 0x0757, 0x0F1B, 0x0F33, 0x0F47, 0x1EA1, 0x1EB5, + 0x1F20, 0x1F30, 0x3F08, 0x3F10, 0x3F28, 0x7F77, 0xFFD5, 0x7FD5, + 0x7FD1, 0x3F5D, 0x3F25, 0x1F34, 0x1F24, 0x1EE8, 0x1EBC, 0x1EA8, + 0x0F3A, 0x0F2E, 0x0EE2, 0x071C, 0x0374, 0x01A0, 0x00AE, 0x01A1, + 0x0375, 0x071D, 0x0EE3, 0x0F2F, 0x0F3C, 0x1EA9, 0x1EBD, 0x1EE9, + 0x1F25, 0x1F36, 0x3F24, 0x3F61, 0x7FCE, 0x7FD2, 0x7F91, 0x7F7D, + 0x3F6C, 0x3F34, 0x1F72, 0x1F61, 0x1EDD, 0x1EC5, 0x1EA5, 0x0F05, + 0x0ED6, 0x0750, 0x073E, 0x0368, 0x034A, 0x0052, 0x034B, 0x0369, + 0x073F, 0x0751, 0x0ED7, 0x0F07, 0x1EA7, 0x1EC7, 0x1EDF, 0x1F65, + 0x1F70, 0x3F36, 0x3F6F, 0x7F7C, 0x7F8F, 0x3F90, 0x3F66, 0x3F58, + 0x3F4E, 0x1F48, 0x1EBB, 0x0F40, 0x0F18, 0x0F10, 0x0EDA, 0x0ECF, + 0x0732, 0x0704, 0x0354, 0x0190, 0x004F, 0x0191, 0x0355, 0x0705, + 0x0733, 0x0ED0, 0x0EDB, 0x0F11, 0x0F19, 0x0F41, 0x1EB8, 0x1F4B, + 0x3F4F, 0x3F55, 0x3F65, 0x3F92, 0x7F85, 0x1F51, 0x1F39, 0x1F2B, + 0x1F18, 0x1EC2, 0x0F38, 0x0F14, 0x0ECA, 0x074C, 0x0736, 0x0700, + 0x06FC, 0x0350, 0x00BA, 0x004D, 0x00BB, 0x0351, 0x06FD, 0x0701, + 0x0737, 0x074D, 0x0ECB, 0x0F15, 0x0F39, 0x1EC3, 0x1F1B, 0x1F2E, + 0x1F3A, 0x1F53, 0x7F82, 0x3F8A, 0x3F47, 0x3F2E, 0x1F5E, 0x1E9E, + 0x0F24, 0x0F20, 0x0EC6, 0x0746, 0x0726, 0x070E, 0x0370, 0x035E, + 0x018A, 0x00AC, 0x0021, 0x00AD, 0x018B, 0x035F, 0x0371, 0x070F, + 0x0727, 0x0747, 0x0EC7, 0x0F21, 0x0F25, 0x1E9F, 0x1F5F, 0x3F2D, + 0x3F48, 0x3F8B, 0xFFF1, 0x1F78, 0x1F3D, 0x1EAD, 0x0F2B, 0x0EF9, + 0x0EE9, 0x0739, 0x0719, 0x0709, 0x0363, 0x019B, 0x0195, 0x00B3, + 0x0023, 0x0005, 0x0024, 0x00B4, 0x0196, 0x019C, 0x0364, 0x070A, + 0x071A, 0x073A, 0x0EEA, 0x0EFA, 0x0F2C, 0x1EAE, 0x1F3E, 0x1F79, + 0xFFF0, 0x0F0C, 0x0EE6, 0x0EDC, 0x0EC2, 0x0748, 0x0706, 0x0372, + 0x034C, 0x0198, 0x0192, 0x00C0, 0x00BC, 0x00B6, 0x0053, 0x0006, + 0x0000, 0x0007, 0x0054, 0x00B7, 0x00BD, 0x00C1, 0x0193, 0x0199, + 0x034D, 0x0373, 0x0707, 0x0749, 0x0EC3, 0x0EDD, 0x0EE7, 0x0F0D, + 0xFFF2, 0x1F7A, 0x1F3F, 0x1EAF, 0x0F2D, 0x0EFB, 0x0EEB, 0x073B, + 0x071B, 0x070B, 0x0365, 0x019D, 0x0197, 0x00B5, 0x0025, 0x0004, + 0x0022, 0x00B2, 0x0194, 0x019A, 0x0362, 0x0708, 0x0718, 0x0738, + 0x0EE8, 0x0EF8, 0x0F2A, 0x1EAC, 0x1F3C, 0x1F7B, 0xFFF3, 0x3F89, + 0x3F44, 0x3F2F, 0x1F5C, 0x1E9C, 0x0F22, 0x0F1E, 0x0EC4, 0x0744, + 0x0724, 0x070C, 0x036E, 0x035C, 0x0188, 0x00AA, 0x0020, 0x00AB, + 0x0189, 0x035D, 0x036F, 0x070D, 0x0725, 0x0745, 0x0EC5, 0x0F1F, + 0x0F23, 0x1E9D, 0x1F5D, 0x3F2C, 0x3F45, 0x3F88, 0x7F81, 0x1F52, + 0x1F38, 0x1F28, 0x1F19, 0x1EC0, 0x0F36, 0x0F12, 0x0EC8, 0x074A, + 0x0734, 0x06FE, 0x06FA, 0x034E, 0x00B8, 0x004C, 0x00B9, 0x034F, + 0x06FB, 0x06FF, 0x0735, 0x074B, 0x0EC9, 0x0F13, 0x0F37, 0x1EC1, + 0x1F1A, 0x1F29, 0x1F3B, 0x1F50, 0x7F84, 0x3F91, 0x3F64, 0x3F54, + 0x3F4C, 0x1F49, 0x1EB9, 0x0F3B, 0x0F16, 0x0F0E, 0x0ED8, 0x0ECD, + 0x0730, 0x0702, 0x0352, 0x018E, 0x004E, 0x018F, 0x0353, 0x0703, + 0x0731, 0x0ECE, 0x0ED9, 0x0F0F, 0x0F17, 0x0F3D, 0x1EBA, 0x1F4A, + 0x3F4D, 0x3F51, 0x3F67, 0x3F93, 0x7F90, 0x7F7A, 0x3F6E, 0x3F37, + 0x1F71, 0x1F63, 0x1EDC, 0x1EC4, 0x1EA4, 0x0F04, 0x0ED4, 0x074E, + 0x073C, 0x0366, 0x0348, 0x0051, 0x0349, 0x0367, 0x073D, 0x074F, + 0x0ED5, 0x0F06, 0x1EA6, 0x1EC6, 0x1EDE, 0x1F64, 0x1F73, 0x3F35, + 0x3F6D, 0x7F7B, 0x7F8E, 0x7FD4, 0x7FD0, 0x3F5F, 0x3F26, 0x1F35, + 0x1F27, 0x1EEA, 0x1EBE, 0x1EAA, 0x0F3E, 0x0F30, 0x0EE4, 0x071E, + 0x0376, 0x01A2, 0x00AF, 0x01A3, 0x0377, 0x071F, 0x0EE5, 0x0F31, + 0x0F3F, 0x1EAB, 0x1EBF, 0x1EEB, 0x1F26, 0x1F37, 0x3F27, 0x3F62, + 0x7FCF, 0x7FD3, 0xFFD4, 0x7F78, 0x3F29, 0x3F11, 0x3F0B, 0x1F32, + 0x1F22, 0x1EB6, 0x1EA2, 0x0F48, 0x0F34, 0x0F1C, 0x0758, 0x072A, + 0x0358, 0x00B1, 0x0359, 0x072B, 0x0759, 0x0F1D, 0x0F35, 0x0F49, + 0x1EA3, 0x1EB7, 0x1F21, 0x1F31, 0x3F09, 0x3F12, 0x3F2A, 0x7F79, + 0xFFD6, 0xFFE1, 0x7F6D, 0x7F64, 0x3F73, 0x3F1D, 0x3F14, 0x1F81, + 0x1EE0, 0x1EB0, 0x0F4A, 0x0EFD, 0x0EDE, 0x0ED1, 0x0720, 0x036A, + 0x00BE, 0x036B, 0x0721, 0x0ED2, 0x0EDF, 0x0EFE, 0x0F4B, 0x1EB1, + 0x1EE1, 0x1F7E, 0x3F15, 0x3F1E, 0x3F74, 0x7F62, 0x7F75, 0xFFE3, + 0xFFDE, 0x7FDD, 0x7FBE, 0x7FB3, 0x7F60, 0x3F43, 0x3F0C, 0x1F47, + 0x1F2D, 0x1EC8, 0x0F26, 0x0EF4, 0x0EEC, 0x072C, 0x06F2, 0x0184, + 0x06F3, 0x072D, 0x0EED, 0x0EF5, 0x0F29, 0x1EC9, 0x1F2A, 0x1F44, + 0x3F0D, 0x3F41, 0x7F5E, 0x7FB1, 0x7FC1, 0x7FD7, 0xFFDF, 0xFFEA, + 0x7FA3, 0x7F8B, 0x7F69, 0x3F9E, 0x1F7F, 0x1F6D, 0x1F6B, 0x1EEE, + 0x1EE6, 0x1ED4, 0x1ECF, 0x0EF2, 0x0754, 0x06F8, 0x018D, 0x06F9, + 0x0755, 0x0EF3, 0x1ECC, 0x1ED7, 0x1EE7, 0x1EEF, 0x1F68, 0x1F6F, + 0x1F80, 0x3F9D, 0x7F67, 0x7F8D, 0x7FA8, 0xFFE9, 0xFFE5, 0x7F89, + 0x7F5D, 0x3F7F, 0x3F3F, 0x1F67, 0x1F4F, 0x1F17, 0x1F0F, 0x1F02, + 0x1EFB, 0x1ED9, 0x0F45, 0x075C, 0x0716, 0x0187, 0x0717, 0x075D, + 0x0F44, 0x1EDB, 0x1EF8, 0x1F03, 0x1F0D, 0x1F16, 0x1F4E, 0x1F66, + 0x3F3E, 0x3F7E, 0x3FAD, 0x7F87, 0xFFE4, 0xFFF9, 0x7FC4, 0x7FBA, + 0x7F6E, 0x3F95, 0x3F85, 0x3F78, 0x3F77, 0x3F5B, 0x3F49, 0x1F08, + 0x1EFE, 0x1ED2, 0x0F01, 0x0710, 0x019E, 0x0711, 0x0F00, 0x1ED1, + 0x1EFC, 0x1F0B, 0x3F4B, 0x3F57, 0x3F71, 0x3F79, 0x3F84, 0x3F94, + 0x7F74, 0x7FBD, 0x7FC5, 0xFFFE, 0xFFED, 0x7FE0, 0x7FDF, 0x7FA4, + 0x7F6A, 0x3FA0, 0x3F8F, 0x3F63, 0x3F3A, 0x3F23, 0x3F1A, 0x1F59, + 0x1F1D, 0x1EF3, 0x0743, 0x035B, 0x0742, 0x1EF7, 0x1F1C, 0x1F5B, + 0x3F1B, 0x3F20, 0x3F38, 0x3F60, 0x3F8C, 0x3FA2, 0x7F6C, 0x7FA9, + 0x7FE5, 0x7FE4, 0xFFEF, 0xFFFF, 0x7FD6, 0x7FCB, 0x7FC7, 0x7F9B, + 0x7F83, 0x3FA4, 0x3F81, 0x3F69, 0x3F30, 0x1F57, 0x1F41, 0x1F13, + 0x1F06, 0x0EC0, 0x0361, 0x0EC1, 0x1F04, 0x1F10, 0x1F42, 0x1F55, + 0x3F32, 0x3F6B, 0x3F82, 0x3FA7, 0x7F7E, 0x7F9D, 0x7FC8, 0x7FCD, + 0x7FD8, 0xFFFA, 0xFFF7, 0xFFD9, 0x7FE8, 0x7FB6, 0x7FAB, 0x7FAA, + 0x7FA1, 0x7F96, 0x7F95, 0x3FAB, 0x3F98, 0x3F50, 0x1F77, 0x1EF4, + 0x0F0A, 0x06F1, 0x0F09, 0x1EF6, 0x1F74, 0x3F56, 0x3F99, 0x3FA9, + 0x7F92, 0x7F97, 0x7F9F, 0x7FAD, 0x7FB2, 0x7FB8, 0x7FE7, 0xFFDD, + 0xFFF4, 0x0050, +}; + +static const uint16_t clv_mvy_2_syms[] = { + 0xF1F1, 0xF2F1, 0xF3F1, 0xF4F1, 0xF5F1, 0xF6F1, 0xF7F1, 0xF8F1, + 0xF9F1, 0xFAF1, 0xFBF1, 0xFCF1, 0xFDF1, 0xFEF1, 0xFFF1, 0x00F1, + 0x01F1, 0x02F1, 0x03F1, 0x04F1, 0x05F1, 0x06F1, 0x07F1, 0x08F1, + 0x09F1, 0x0AF1, 0x0BF1, 0x0CF1, 0x0DF1, 0x0EF1, 0x0FF1, 0xF1F2, + 0xF2F2, 0xF3F2, 0xF4F2, 0xF5F2, 0xF6F2, 0xF7F2, 0xF8F2, 0xF9F2, + 0xFAF2, 0xFBF2, 0xFCF2, 0xFDF2, 0xFEF2, 0xFFF2, 0x00F2, 0x01F2, + 0x02F2, 0x03F2, 0x04F2, 0x05F2, 0x06F2, 0x07F2, 0x08F2, 0x09F2, + 0x0AF2, 0x0BF2, 0x0CF2, 0x0DF2, 0x0EF2, 0x0FF2, 0xF1F3, 0xF2F3, + 0xF3F3, 0xF4F3, 0xF5F3, 0xF6F3, 0xF7F3, 0xF8F3, 0xF9F3, 0xFAF3, + 0xFBF3, 0xFCF3, 0xFDF3, 0xFEF3, 0xFFF3, 0x00F3, 0x01F3, 0x02F3, + 0x03F3, 0x04F3, 0x05F3, 0x06F3, 0x07F3, 0x08F3, 0x09F3, 0x0AF3, + 0x0BF3, 0x0CF3, 0x0DF3, 0x0EF3, 0x0FF3, 0xF1F4, 0xF2F4, 0xF3F4, + 0xF4F4, 0xF5F4, 0xF6F4, 0xF7F4, 0xF8F4, 0xF9F4, 0xFAF4, 0xFBF4, + 0xFCF4, 0xFDF4, 0xFEF4, 0xFFF4, 0x00F4, 0x01F4, 0x02F4, 0x03F4, + 0x04F4, 0x05F4, 0x06F4, 0x07F4, 0x08F4, 0x09F4, 0x0AF4, 0x0BF4, + 0x0CF4, 0x0DF4, 0x0EF4, 0x0FF4, 0xF1F5, 0xF2F5, 0xF3F5, 0xF4F5, + 0xF5F5, 0xF6F5, 0xF7F5, 0xF8F5, 0xF9F5, 0xFAF5, 0xFBF5, 0xFCF5, + 0xFDF5, 0xFEF5, 0xFFF5, 0x00F5, 0x01F5, 0x02F5, 0x03F5, 0x04F5, + 0x05F5, 0x06F5, 0x07F5, 0x08F5, 0x09F5, 0x0AF5, 0x0BF5, 0x0CF5, + 0x0DF5, 0x0EF5, 0x0FF5, 0xF1F6, 0xF2F6, 0xF3F6, 0xF4F6, 0xF5F6, + 0xF6F6, 0xF7F6, 0xF8F6, 0xF9F6, 0xFAF6, 0xFBF6, 0xFCF6, 0xFDF6, + 0xFEF6, 0xFFF6, 0x00F6, 0x01F6, 0x02F6, 0x03F6, 0x04F6, 0x05F6, + 0x06F6, 0x07F6, 0x08F6, 0x09F6, 0x0AF6, 0x0BF6, 0x0CF6, 0x0DF6, + 0x0EF6, 0x0FF6, 0xF1F7, 0xF2F7, 0xF3F7, 0xF4F7, 0xF5F7, 0xF6F7, + 0xF7F7, 0xF8F7, 0xF9F7, 0xFAF7, 0xFBF7, 0xFCF7, 0xFDF7, 0xFEF7, + 0xFFF7, 0x00F7, 0x01F7, 0x02F7, 0x03F7, 0x04F7, 0x05F7, 0x06F7, + 0x07F7, 0x08F7, 0x09F7, 0x0AF7, 0x0BF7, 0x0CF7, 0x0DF7, 0x0EF7, + 0x0FF7, 0xF1F8, 0xF2F8, 0xF3F8, 0xF4F8, 0xF5F8, 0xF6F8, 0xF7F8, + 0xF8F8, 0xF9F8, 0xFAF8, 0xFBF8, 0xFCF8, 0xFDF8, 0xFEF8, 0xFFF8, + 0x00F8, 0x01F8, 0x02F8, 0x03F8, 0x04F8, 0x05F8, 0x06F8, 0x07F8, + 0x08F8, 0x09F8, 0x0AF8, 0x0BF8, 0x0CF8, 0x0DF8, 0x0EF8, 0x0FF8, + 0xF1F9, 0xF2F9, 0xF3F9, 0xF4F9, 0xF5F9, 0xF6F9, 0xF7F9, 0xF8F9, + 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, 0xFFF9, 0x00F9, + 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, 0x07F9, 0x08F9, + 0x09F9, 0x0AF9, 0x0BF9, 0x0CF9, 0x0DF9, 0x0EF9, 0x0FF9, 0xF1FA, + 0xF2FA, 0xF3FA, 0xF4FA, 0xF5FA, 0xF6FA, 0xF7FA, 0xF8FA, 0xF9FA, + 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, + 0x02FA, 0x03FA, 0x04FA, 0x05FA, 0x06FA, 0x07FA, 0x08FA, 0x09FA, + 0x0AFA, 0x0BFA, 0x0CFA, 0x0DFA, 0x0EFA, 0x0FFA, 0xF1FB, 0xF2FB, + 0xF3FB, 0xF4FB, 0xF5FB, 0xF6FB, 0xF7FB, 0xF8FB, 0xF9FB, 0xFAFB, + 0xFBFB, 0xFCFB, 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, + 0x03FB, 0x04FB, 0x05FB, 0x06FB, 0x07FB, 0x08FB, 0x09FB, 0x0AFB, + 0x0BFB, 0x0CFB, 0x0DFB, 0x0EFB, 0x0FFB, 0xF1FC, 0xF2FC, 0xF3FC, + 0xF4FC, 0xF5FC, 0xF6FC, 0xF7FC, 0xF8FC, 0xF9FC, 0xFAFC, 0xFBFC, + 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, 0x00FC, 0x01FC, 0x02FC, 0x03FC, + 0x04FC, 0x05FC, 0x06FC, 0x07FC, 0x08FC, 0x09FC, 0x0AFC, 0x0BFC, + 0x0CFC, 0x0DFC, 0x0EFC, 0x0FFC, 0xF1FD, 0xF2FD, 0xF3FD, 0xF4FD, + 0xF5FD, 0xF6FD, 0xF7FD, 0xF8FD, 0xF9FD, 0xFAFD, 0xFBFD, 0xFCFD, + 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, 0x03FD, 0x04FD, + 0x05FD, 0x06FD, 0x07FD, 0x08FD, 0x09FD, 0x0AFD, 0x0BFD, 0x0CFD, + 0x0DFD, 0x0EFD, 0x0FFD, 0xF1FE, 0xF2FE, 0xF3FE, 0xF4FE, 0xF5FE, + 0xF6FE, 0xF7FE, 0xF8FE, 0xF9FE, 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, + 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, 0x02FE, 0x03FE, 0x04FE, 0x05FE, + 0x06FE, 0x07FE, 0x08FE, 0x09FE, 0x0AFE, 0x0BFE, 0x0CFE, 0x0DFE, + 0x0EFE, 0x0FFE, 0xF1FF, 0xF2FF, 0xF3FF, 0xF4FF, 0xF5FF, 0xF6FF, + 0xF7FF, 0xF8FF, 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, + 0xFFFF, 0x00FF, 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, + 0x07FF, 0x08FF, 0x09FF, 0x0AFF, 0x0BFF, 0x0CFF, 0x0DFF, 0x0EFF, + 0x0FFF, 0xF100, 0xF200, 0xF300, 0xF400, 0xF500, 0xF600, 0xF700, + 0xF800, 0xF900, 0xFA00, 0xFB00, 0xFC00, 0xFD00, 0xFE00, 0xFF00, + 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, + 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, 0x0F00, + 0xF101, 0xF201, 0xF301, 0xF401, 0xF501, 0xF601, 0xF701, 0xF801, + 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, 0xFF01, 0x0001, + 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, 0x0701, 0x0801, + 0x0901, 0x0A01, 0x0B01, 0x0C01, 0x0D01, 0x0E01, 0x0F01, 0xF102, + 0xF202, 0xF302, 0xF402, 0xF502, 0xF602, 0xF702, 0xF802, 0xF902, + 0xFA02, 0xFB02, 0xFC02, 0xFD02, 0xFE02, 0xFF02, 0x0002, 0x0102, + 0x0202, 0x0302, 0x0402, 0x0502, 0x0602, 0x0702, 0x0802, 0x0902, + 0x0A02, 0x0B02, 0x0C02, 0x0D02, 0x0E02, 0x0F02, 0xF103, 0xF203, + 0xF303, 0xF403, 0xF503, 0xF603, 0xF703, 0xF803, 0xF903, 0xFA03, + 0xFB03, 0xFC03, 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, + 0x0303, 0x0403, 0x0503, 0x0603, 0x0703, 0x0803, 0x0903, 0x0A03, + 0x0B03, 0x0C03, 0x0D03, 0x0E03, 0x0F03, 0xF104, 0xF204, 0xF304, + 0xF404, 0xF504, 0xF604, 0xF704, 0xF804, 0xF904, 0xFA04, 0xFB04, + 0xFC04, 0xFD04, 0xFE04, 0xFF04, 0x0004, 0x0104, 0x0204, 0x0304, + 0x0404, 0x0504, 0x0604, 0x0704, 0x0804, 0x0904, 0x0A04, 0x0B04, + 0x0C04, 0x0D04, 0x0E04, 0x0F04, 0xF105, 0xF205, 0xF305, 0xF405, + 0xF505, 0xF605, 0xF705, 0xF805, 0xF905, 0xFA05, 0xFB05, 0xFC05, + 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, 0x0305, 0x0405, + 0x0505, 0x0605, 0x0705, 0x0805, 0x0905, 0x0A05, 0x0B05, 0x0C05, + 0x0D05, 0x0E05, 0x0F05, 0xF106, 0xF206, 0xF306, 0xF406, 0xF506, + 0xF606, 0xF706, 0xF806, 0xF906, 0xFA06, 0xFB06, 0xFC06, 0xFD06, + 0xFE06, 0xFF06, 0x0006, 0x0106, 0x0206, 0x0306, 0x0406, 0x0506, + 0x0606, 0x0706, 0x0806, 0x0906, 0x0A06, 0x0B06, 0x0C06, 0x0D06, + 0x0E06, 0x0F06, 0xF107, 0xF207, 0xF307, 0xF407, 0xF507, 0xF607, + 0xF707, 0xF807, 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, + 0xFF07, 0x0007, 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, + 0x0707, 0x0807, 0x0907, 0x0A07, 0x0B07, 0x0C07, 0x0D07, 0x0E07, + 0x0F07, 0xF108, 0xF208, 0xF308, 0xF408, 0xF508, 0xF608, 0xF708, + 0xF808, 0xF908, 0xFA08, 0xFB08, 0xFC08, 0xFD08, 0xFE08, 0xFF08, + 0x0008, 0x0108, 0x0208, 0x0308, 0x0408, 0x0508, 0x0608, 0x0708, + 0x0808, 0x0908, 0x0A08, 0x0B08, 0x0C08, 0x0D08, 0x0E08, 0x0F08, + 0xF109, 0xF209, 0xF309, 0xF409, 0xF509, 0xF609, 0xF709, 0xF809, + 0xF909, 0xFA09, 0xFB09, 0xFC09, 0xFD09, 0xFE09, 0xFF09, 0x0009, + 0x0109, 0x0209, 0x0309, 0x0409, 0x0509, 0x0609, 0x0709, 0x0809, + 0x0909, 0x0A09, 0x0B09, 0x0C09, 0x0D09, 0x0E09, 0x0F09, 0xF10A, + 0xF20A, 0xF30A, 0xF40A, 0xF50A, 0xF60A, 0xF70A, 0xF80A, 0xF90A, + 0xFA0A, 0xFB0A, 0xFC0A, 0xFD0A, 0xFE0A, 0xFF0A, 0x000A, 0x010A, + 0x020A, 0x030A, 0x040A, 0x050A, 0x060A, 0x070A, 0x080A, 0x090A, + 0x0A0A, 0x0B0A, 0x0C0A, 0x0D0A, 0x0E0A, 0x0F0A, 0xF10B, 0xF20B, + 0xF30B, 0xF40B, 0xF50B, 0xF60B, 0xF70B, 0xF80B, 0xF90B, 0xFA0B, + 0xFB0B, 0xFC0B, 0xFD0B, 0xFE0B, 0xFF0B, 0x000B, 0x010B, 0x020B, + 0x030B, 0x040B, 0x050B, 0x060B, 0x070B, 0x080B, 0x090B, 0x0A0B, + 0x0B0B, 0x0C0B, 0x0D0B, 0x0E0B, 0x0F0B, 0xF10C, 0xF20C, 0xF30C, + 0xF40C, 0xF50C, 0xF60C, 0xF70C, 0xF80C, 0xF90C, 0xFA0C, 0xFB0C, + 0xFC0C, 0xFD0C, 0xFE0C, 0xFF0C, 0x000C, 0x010C, 0x020C, 0x030C, + 0x040C, 0x050C, 0x060C, 0x070C, 0x080C, 0x090C, 0x0A0C, 0x0B0C, + 0x0C0C, 0x0D0C, 0x0E0C, 0x0F0C, 0xF10D, 0xF20D, 0xF30D, 0xF40D, + 0xF50D, 0xF60D, 0xF70D, 0xF80D, 0xF90D, 0xFA0D, 0xFB0D, 0xFC0D, + 0xFD0D, 0xFE0D, 0xFF0D, 0x000D, 0x010D, 0x020D, 0x030D, 0x040D, + 0x050D, 0x060D, 0x070D, 0x080D, 0x090D, 0x0A0D, 0x0B0D, 0x0C0D, + 0x0D0D, 0x0E0D, 0x0F0D, 0xF10E, 0xF20E, 0xF30E, 0xF40E, 0xF50E, + 0xF60E, 0xF70E, 0xF80E, 0xF90E, 0xFA0E, 0xFB0E, 0xFC0E, 0xFD0E, + 0xFE0E, 0xFF0E, 0x000E, 0x010E, 0x020E, 0x030E, 0x040E, 0x050E, + 0x060E, 0x070E, 0x080E, 0x090E, 0x0A0E, 0x0B0E, 0x0C0E, 0x0D0E, + 0x0E0E, 0x0F0E, 0xF10F, 0xF20F, 0xF30F, 0xF40F, 0xF50F, 0xF60F, + 0xF70F, 0xF80F, 0xF90F, 0xFA0F, 0xFB0F, 0xFC0F, 0xFD0F, 0xFE0F, + 0xFF0F, 0x000F, 0x010F, 0x020F, 0x030F, 0x040F, 0x050F, 0x060F, + 0x070F, 0x080F, 0x090F, 0x0A0F, 0x0B0F, 0x0C0F, 0x0D0F, 0x0E0F, + 0x0F0F, 0x1010, +}; + +static const uint8_t clv_mvy_3_bits[] = { + 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 13, + 13, 12, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, + 15, 15, 14, 14, 14, 13, 12, 11, 12, 13, 14, 14, 14, 15, 15, 15, + 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, + 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 12, 11, 12, 14, 14, + 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, + 16, 16, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, + 12, 11, 12, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, + 15, 16, 16, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 13, 13, 12, 10, 12, 13, 13, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 15, 15, 15, 15, + 14, 14, 14, 14, 13, 13, 13, 13, 13, 12, 12, 10, 12, 12, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 15, 15, + 15, 15, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 11, + 10, 11, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, + 12, 12, 12, 11, 10, 9, 10, 11, 12, 12, 12, 12, 12, 13, 13, 13, + 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, + 12, 12, 12, 12, 12, 12, 12, 11, 11, 10, 9, 10, 11, 11, 12, 12, + 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 15, 16, 15, 15, + 15, 15, 14, 14, 13, 13, 12, 12, 12, 12, 12, 11, 11, 11, 10, 9, + 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 14, 14, 15, 15, 15, + 15, 16, 15, 15, 14, 14, 14, 14, 14, 13, 13, 12, 12, 12, 12, 12, + 11, 11, 11, 10, 9, 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, + 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, 12, + 12, 12, 12, 12, 12, 11, 11, 11, 10, 8, 10, 11, 11, 11, 12, 12, + 12, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 15, 15, 15, 14, 14, + 14, 14, 13, 13, 12, 12, 12, 12, 12, 11, 11, 11, 10, 10, 8, 10, + 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, + 15, 15, 14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, + 10, 10, 9, 7, 9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, + 13, 14, 14, 14, 14, 15, 15, 14, 14, 14, 14, 13, 13, 13, 12, 12, + 12, 12, 11, 11, 11, 10, 10, 9, 7, 9, 10, 10, 11, 11, 11, 12, + 12, 12, 12, 13, 13, 13, 14, 14, 14, 14, 15, 15, 14, 14, 14, 14, + 13, 13, 12, 12, 12, 12, 11, 11, 11, 11, 10, 9, 9, 7, 9, 9, + 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, + 15, 14, 14, 14, 13, 13, 13, 13, 12, 11, 11, 11, 11, 10, 10, 10, + 9, 8, 6, 8, 9, 10, 10, 10, 11, 11, 11, 11, 12, 13, 13, 13, + 13, 14, 14, 14, 15, 15, 14, 14, 14, 13, 13, 12, 12, 11, 11, 11, + 11, 10, 10, 9, 9, 8, 6, 4, 6, 8, 9, 9, 10, 10, 11, 11, + 11, 11, 12, 12, 13, 13, 14, 14, 14, 15, 13, 13, 13, 12, 12, 12, + 12, 11, 10, 10, 10, 10, 9, 9, 8, 8, 7, 5, 2, 5, 7, 8, + 8, 9, 9, 10, 10, 10, 10, 11, 12, 12, 12, 12, 13, 13, 13, 15, + 14, 14, 14, 13, 13, 12, 12, 11, 11, 11, 11, 10, 10, 9, 9, 8, + 6, 4, 6, 8, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 13, 13, + 14, 14, 14, 15, 15, 14, 14, 14, 13, 13, 13, 13, 12, 11, 11, 11, + 11, 10, 10, 10, 9, 8, 6, 8, 9, 10, 10, 10, 11, 11, 11, 11, + 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, 14, 14, 14, 14, 13, 13, + 12, 12, 12, 12, 11, 11, 11, 11, 10, 9, 9, 7, 9, 9, 10, 11, + 11, 11, 11, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 14, + 14, 14, 14, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, 10, 10, 9, + 7, 9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14, 14, + 14, 14, 15, 15, 14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 12, 11, + 11, 11, 10, 10, 9, 7, 9, 10, 10, 11, 11, 11, 12, 12, 12, 12, + 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 14, 14, 14, 14, 13, 13, + 12, 12, 12, 12, 12, 11, 11, 11, 10, 10, 8, 10, 10, 11, 11, 11, + 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, + 14, 14, 14, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 10, 8, + 10, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 15, + 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 12, 12, 12, 12, 12, + 11, 11, 11, 10, 9, 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, + 14, 14, 14, 14, 14, 15, 15, 16, 15, 15, 15, 15, 14, 14, 13, 13, + 12, 12, 12, 12, 12, 11, 11, 11, 10, 9, 10, 11, 11, 11, 12, 12, + 12, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 15, 15, 15, 14, + 14, 14, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 10, 9, 10, + 11, 11, 12, 12, 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, + 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, 12, + 12, 11, 10, 9, 10, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, + 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, + 13, 13, 13, 13, 13, 13, 13, 11, 10, 11, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 15, 15, + 15, 15, 14, 14, 14, 14, 13, 13, 13, 13, 13, 12, 12, 10, 12, 12, + 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, + 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, + 13, 12, 10, 12, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, + 15, 15, 15, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 14, + 14, 14, 14, 14, 13, 13, 12, 11, 12, 13, 13, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 15, 15, 15, + 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 12, 11, 12, 14, 14, + 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, + 12, 11, 12, 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, + 15, 14, 14, 13, 13, 12, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, + 15, 15, 16, 16, 16, 16, 16, 16, 16, 7, +}; + +static const uint16_t clv_mvy_3_codes[] = { + 0xFFF6, 0xFFEE, 0xFFDC, 0xFFD7, 0xFFB4, 0xFFAA, 0xFFA0, 0x7FCC, + 0x7F8E, 0x7F7B, 0x7F77, 0x7F13, 0x7F11, 0x3F56, 0x3F48, 0x1F16, + 0x1E94, 0x0F28, 0x06F0, 0x0F2A, 0x1E96, 0x1F1C, 0x3F46, 0x3F58, + 0x7F15, 0x7F0E, 0x7F76, 0x7F80, 0x7F90, 0x7FC8, 0xFFA2, 0xFFA7, + 0xFFB5, 0xFFD8, 0xFFDD, 0xFFEC, 0xFFF5, 0xFFF1, 0xFFEA, 0xFFE4, + 0xFFD1, 0xFFC1, 0xFFA8, 0x7F70, 0x7F5C, 0x7F44, 0x7F40, 0x7F2A, + 0x7F16, 0x7EDF, 0x3ED6, 0x3ECA, 0x3ECC, 0x1EB5, 0x0EDE, 0x06D3, + 0x0EDF, 0x1EB6, 0x3ECE, 0x3ED0, 0x3ED8, 0x7EE5, 0x7F19, 0x7F31, + 0x7F3E, 0x7F45, 0x7F5B, 0x7F6F, 0xFFA9, 0xFFC0, 0xFFCE, 0xFFE5, + 0xFFE8, 0xFFF2, 0xFFFE, 0xFFE2, 0xFFBE, 0x7FBB, 0x7F75, 0x7F6B, + 0x7F58, 0x7EF9, 0x7EDC, 0x3F68, 0x3F27, 0x3F28, 0x3EDF, 0x3ED2, + 0x3EC1, 0x3EA6, 0x3E87, 0x0F0F, 0x06B3, 0x0F10, 0x3E89, 0x3EA8, + 0x3EC3, 0x3ED5, 0x3EE0, 0x3F2B, 0x3F26, 0x3F67, 0x7EDA, 0x7EFB, + 0x7F56, 0x7F6A, 0x7F72, 0x7FC1, 0xFFBC, 0xFFE0, 0xFFFF, 0xFFF8, + 0xFFD3, 0xFFB9, 0x7FAC, 0x7F94, 0x7F8B, 0x7F62, 0x7F4A, 0x7F05, + 0x7EEE, 0x3F44, 0x3EA4, 0x3E78, 0x3E6F, 0x3E54, 0x1EEF, 0x1EA9, + 0x0ED4, 0x06A8, 0x0ED5, 0x1EA8, 0x1EEC, 0x3E51, 0x3E69, 0x3E75, + 0x3EA3, 0x3F43, 0x7EF1, 0x7F04, 0x7F4B, 0x7F5D, 0x7F89, 0x7F95, + 0x7FAA, 0xFFBB, 0xFFC8, 0xFFF9, 0xFFD9, 0xFFCA, 0x7FC3, 0x7F8C, + 0x7F38, 0x7F02, 0x3F5A, 0x3F4A, 0x3F30, 0x3EFF, 0x3EF4, 0x3EE9, + 0x3E95, 0x3E73, 0x3E43, 0x1F08, 0x1E81, 0x0E84, 0x0349, 0x0E85, + 0x1E82, 0x1F07, 0x3E45, 0x3E74, 0x3E96, 0x3EEA, 0x3EF1, 0x3F00, + 0x3F32, 0x3F4F, 0x3F5C, 0x7F01, 0x7F3B, 0x7F8D, 0x7FC2, 0xFFCF, + 0xFFD6, 0xFFC7, 0xFFB1, 0xFFA6, 0x7FA1, 0x7F2F, 0x7F24, 0x7F0A, + 0x3EF6, 0x3E97, 0x3E83, 0x3E7F, 0x1F04, 0x1EE1, 0x1ECB, 0x1EAE, + 0x1E7E, 0x0EBA, 0x0E8C, 0x0333, 0x0E8D, 0x0EBB, 0x1E7F, 0x1EAF, + 0x1ECC, 0x1EE2, 0x1F05, 0x3E80, 0x3E84, 0x3E98, 0x3EF9, 0x7F06, + 0x7F1B, 0x7F2D, 0x7F9F, 0xFFAF, 0xFFB0, 0xFFC6, 0x7FB5, 0x7FB1, + 0x7F36, 0x7F25, 0x3F63, 0x3F3A, 0x3F1B, 0x3EBB, 0x3E63, 0x3E5B, + 0x3E40, 0x1F14, 0x1EF5, 0x1EEB, 0x1EBE, 0x1E92, 0x1E6A, 0x070C, + 0x032D, 0x070D, 0x1E6B, 0x1E93, 0x1EBF, 0x1EE8, 0x1EF3, 0x1F15, + 0x3E3F, 0x3E5C, 0x3E64, 0x3EB9, 0x3F1C, 0x3F3C, 0x3F62, 0x7F22, + 0x7F39, 0x7FAF, 0x7FAE, 0x7FC6, 0x7F7F, 0x7F53, 0x7F32, 0x3F66, + 0x3EF0, 0x3E65, 0x1EDA, 0x1ED3, 0x1E98, 0x1E74, 0x0F20, 0x0F1D, + 0x0EEA, 0x0EA9, 0x0E70, 0x0718, 0x033E, 0x0179, 0x033F, 0x0719, + 0x0E71, 0x0EAB, 0x0EE9, 0x0F1F, 0x0F22, 0x1E76, 0x1E9B, 0x1ED5, + 0x1EDD, 0x3E68, 0x3EF3, 0x3F6C, 0x7F33, 0x7F4E, 0x7F7D, 0x7FCB, + 0x7FBD, 0x7F21, 0x7EF6, 0x3F0C, 0x3EBE, 0x3EAE, 0x1EA3, 0x1E85, + 0x0F0C, 0x0F06, 0x0EEE, 0x0EE6, 0x0ECA, 0x0EA2, 0x0E78, 0x0720, + 0x06BA, 0x0326, 0x015D, 0x0327, 0x06BB, 0x0721, 0x0E79, 0x0EA3, + 0x0ECB, 0x0EE7, 0x0EEF, 0x0F07, 0x0F0D, 0x1E86, 0x1EA4, 0x3EAF, + 0x3EBF, 0x3F0A, 0x7EF8, 0x7F1E, 0x7FBF, 0xFF9F, 0x7FB3, 0x7F96, + 0x7F0B, 0x7EF5, 0x3E85, 0x3E4E, 0x1EB3, 0x1E6E, 0x0F2D, 0x0EBD, + 0x0E97, 0x0E93, 0x0E86, 0x071A, 0x06E4, 0x06BC, 0x0338, 0x015A, + 0x0339, 0x06BD, 0x06E5, 0x071B, 0x0E87, 0x0E94, 0x0E98, 0x0EBE, + 0x0F2E, 0x1E6F, 0x1EB4, 0x3E4F, 0x3E88, 0x7EF4, 0x7F07, 0x7F99, + 0x7FB7, 0xFF9D, 0x7FA8, 0x7EEB, 0x3F5D, 0x3EB2, 0x3EAA, 0x3E5D, + 0x3E49, 0x1EFE, 0x1E89, 0x0F16, 0x0F12, 0x0EE0, 0x0E7A, 0x0E6A, + 0x070E, 0x06FA, 0x06B4, 0x0314, 0x0158, 0x0315, 0x06B5, 0x06FB, + 0x070F, 0x0E6B, 0x0E7B, 0x0EE1, 0x0F13, 0x0F17, 0x1E8A, 0x1EFF, + 0x3E4A, 0x3E5E, 0x3EAB, 0x3EB3, 0x3F59, 0x7EEC, 0x7FA2, 0x7F82, + 0x7F5E, 0x7F28, 0x3EDA, 0x3EC9, 0x3E7A, 0x1ED6, 0x1ECE, 0x0EFC, + 0x0EF0, 0x0E9A, 0x0E7E, 0x0E66, 0x0E5E, 0x0722, 0x06C0, 0x06A0, + 0x02FA, 0x00A8, 0x02FB, 0x06A1, 0x06C1, 0x0723, 0x0E5F, 0x0E67, + 0x0E7F, 0x0E9B, 0x0EF1, 0x0EFD, 0x1ECF, 0x1ED7, 0x3E79, 0x3ECD, + 0x3EDB, 0x7F26, 0x7F5A, 0x7F83, 0x7F54, 0x7EE8, 0x3F54, 0x3F0E, + 0x3EFB, 0x3E47, 0x1EC1, 0x1EB9, 0x0EF9, 0x0EF3, 0x0EC1, 0x0E8F, + 0x0E74, 0x0714, 0x06F4, 0x06B0, 0x0336, 0x030A, 0x009F, 0x030B, + 0x0337, 0x06B1, 0x06F5, 0x0715, 0x0E75, 0x0E91, 0x0EC3, 0x0EF6, + 0x0EFB, 0x1EBB, 0x1EC3, 0x3E41, 0x3EF8, 0x3F10, 0x3F4D, 0x7EE9, + 0x7F52, 0x7F9A, 0x3F3F, 0x3F1F, 0x3F03, 0x3EA0, 0x1F0F, 0x1E72, + 0x1E62, 0x0EDA, 0x0ED2, 0x0EB2, 0x0E64, 0x0708, 0x06EA, 0x06DA, + 0x0346, 0x032A, 0x0176, 0x004B, 0x0177, 0x032B, 0x0347, 0x06DB, + 0x06EB, 0x0709, 0x0E65, 0x0EB3, 0x0ED3, 0x0EDB, 0x1E63, 0x1E6C, + 0x1F0E, 0x3E9E, 0x3F01, 0x3F1D, 0x3F3D, 0x7F9B, 0x7EDE, 0x3F36, + 0x3F2E, 0x3F07, 0x3E99, 0x1F0D, 0x1EA1, 0x1E8C, 0x0EB4, 0x0EAC, + 0x0E5A, 0x0E50, 0x0702, 0x06D4, 0x06C6, 0x032E, 0x0310, 0x0162, + 0x0046, 0x0163, 0x0311, 0x032F, 0x06C7, 0x06D5, 0x0703, 0x0E51, + 0x0E5B, 0x0EAD, 0x0EB5, 0x1E8F, 0x1EA7, 0x1F0C, 0x3E9A, 0x3F02, + 0x3F2D, 0x3F35, 0x7EE0, 0x7F66, 0x3F11, 0x3EE1, 0x3EBC, 0x3E56, + 0x1EC4, 0x1E64, 0x0F04, 0x0EC7, 0x0E56, 0x0E4C, 0x06EC, 0x06DC, + 0x069C, 0x0694, 0x0320, 0x016C, 0x0154, 0x0044, 0x0155, 0x016D, + 0x0321, 0x0695, 0x069D, 0x06DD, 0x06ED, 0x0E4D, 0x0E57, 0x0EC4, + 0x0F05, 0x1E65, 0x1EC5, 0x3E55, 0x3EB7, 0x3EE3, 0x3F13, 0x7F67, + 0x7FA7, 0x3F49, 0x3F22, 0x3EE5, 0x1EF6, 0x1EE5, 0x1E9C, 0x1E78, + 0x0EA4, 0x06F6, 0x06DE, 0x06CE, 0x06AA, 0x0340, 0x0318, 0x02FE, + 0x015E, 0x009A, 0x001C, 0x009B, 0x015F, 0x02FF, 0x0319, 0x0341, + 0x06AB, 0x06CF, 0x06DF, 0x06F7, 0x0EA5, 0x1E79, 0x1E9D, 0x1EE7, + 0x1EF7, 0x3EE6, 0x3F23, 0x3F4B, 0x7FA3, 0x7F49, 0x3F14, 0x3E8D, + 0x3E6B, 0x1F17, 0x1EF8, 0x0F24, 0x0ECC, 0x06FE, 0x06CA, 0x06A4, + 0x0698, 0x030C, 0x0302, 0x0170, 0x0168, 0x00A0, 0x001E, 0x0004, + 0x001F, 0x00A1, 0x0169, 0x0171, 0x0303, 0x030D, 0x0699, 0x06A5, + 0x06CB, 0x06FF, 0x0ECD, 0x0F25, 0x1EF9, 0x1F18, 0x3E6C, 0x3E8E, + 0x3F15, 0x7F46, 0x1EF0, 0x1EDE, 0x1EC8, 0x0F1A, 0x0F00, 0x0E9E, + 0x0E54, 0x06C4, 0x031E, 0x031C, 0x0306, 0x02F8, 0x017A, 0x0166, + 0x00A6, 0x00A4, 0x0048, 0x000C, 0x0000, 0x000D, 0x0049, 0x00A5, + 0x00A7, 0x0167, 0x017B, 0x02F9, 0x0307, 0x031D, 0x031F, 0x06C5, + 0x0E55, 0x0E9F, 0x0F01, 0x0F1B, 0x1EC9, 0x1EDF, 0x1EF1, 0x7F47, + 0x3F12, 0x3E8F, 0x3E6D, 0x1F1B, 0x1EFA, 0x0F26, 0x0ECE, 0x0700, + 0x06CC, 0x06A6, 0x069A, 0x030E, 0x0304, 0x0172, 0x016A, 0x00A2, + 0x0020, 0x0005, 0x0021, 0x00A3, 0x016B, 0x0173, 0x0305, 0x030F, + 0x069B, 0x06A7, 0x06CD, 0x0701, 0x0ECF, 0x0F27, 0x1EFB, 0x1F1D, + 0x3E6E, 0x3E90, 0x3F17, 0x7F48, 0x7FA9, 0x3F50, 0x3F24, 0x3EE7, + 0x1EFC, 0x1EE9, 0x1E9E, 0x1E7A, 0x0EA6, 0x06F8, 0x06E0, 0x06D0, + 0x06AC, 0x0342, 0x031A, 0x0300, 0x0160, 0x009C, 0x001D, 0x009D, + 0x0161, 0x0301, 0x031B, 0x0343, 0x06AD, 0x06D1, 0x06E1, 0x06F9, + 0x0EA7, 0x1E7B, 0x1E9F, 0x1EEA, 0x1EFD, 0x3EE8, 0x3F21, 0x3F52, + 0x7F9E, 0x7F68, 0x3F16, 0x3EE2, 0x3EBA, 0x3E57, 0x1EC6, 0x1E66, + 0x0F08, 0x0EC5, 0x0E58, 0x0E4E, 0x06EE, 0x06E2, 0x069E, 0x0696, + 0x0322, 0x016E, 0x0156, 0x0045, 0x0157, 0x016F, 0x0323, 0x0697, + 0x069F, 0x06E3, 0x06EF, 0x0E4F, 0x0E59, 0x0EC6, 0x0F09, 0x1E67, + 0x1EC7, 0x3E58, 0x3EB8, 0x3EE4, 0x3F18, 0x7F69, 0x7EE2, 0x3F38, + 0x3F33, 0x3F04, 0x3E9C, 0x1F0A, 0x1EA5, 0x1E8D, 0x0EB6, 0x0EAE, + 0x0E5C, 0x0E52, 0x0704, 0x06D6, 0x06C8, 0x0330, 0x0312, 0x0164, + 0x0047, 0x0165, 0x0313, 0x0331, 0x06C9, 0x06D7, 0x0705, 0x0E53, + 0x0E5D, 0x0EAF, 0x0EB7, 0x1E8E, 0x1EA6, 0x1F0B, 0x3E9B, 0x3F05, + 0x3F31, 0x3F39, 0x7EE1, 0x7F9C, 0x3F40, 0x3F1E, 0x3F06, 0x3E9D, + 0x1F10, 0x1E70, 0x1E60, 0x0ED8, 0x0ED0, 0x0EB0, 0x0E62, 0x0706, + 0x06E8, 0x06D8, 0x0344, 0x0328, 0x0174, 0x004A, 0x0175, 0x0329, + 0x0345, 0x06D9, 0x06E9, 0x0707, 0x0E63, 0x0EB1, 0x0ED1, 0x0ED9, + 0x1E61, 0x1E71, 0x1F11, 0x3E9F, 0x3F08, 0x3F20, 0x3F3E, 0x7F9D, + 0x7F4F, 0x7EE6, 0x3F53, 0x3F0D, 0x3EFA, 0x3E46, 0x1EC0, 0x1EB8, + 0x0EF8, 0x0EF2, 0x0EC0, 0x0E8E, 0x0E72, 0x0712, 0x06F2, 0x06AE, + 0x0334, 0x0308, 0x009E, 0x0309, 0x0335, 0x06AF, 0x06F3, 0x0713, + 0x0E73, 0x0E90, 0x0EC2, 0x0EF4, 0x0EFA, 0x1EBA, 0x1EC2, 0x3E48, + 0x3EFC, 0x3F0B, 0x3F51, 0x7EE7, 0x7F51, 0x7F84, 0x7F61, 0x7F27, + 0x3EDC, 0x3EC5, 0x3E7C, 0x1ED8, 0x1ED0, 0x0EFE, 0x0EF5, 0x0E9C, + 0x0E80, 0x0E68, 0x0E60, 0x0724, 0x06C2, 0x06A2, 0x02FC, 0x00A9, + 0x02FD, 0x06A3, 0x06C3, 0x0725, 0x0E61, 0x0E69, 0x0E81, 0x0E9D, + 0x0EF7, 0x0EFF, 0x1ED1, 0x1ED9, 0x3E7B, 0x3ECF, 0x3ED9, 0x7F29, + 0x7F65, 0x7F85, 0x7FA0, 0x7EEA, 0x3F60, 0x3EB4, 0x3EAC, 0x3E5F, + 0x3E4B, 0x1F00, 0x1E8B, 0x0F18, 0x0F14, 0x0EE2, 0x0E7C, 0x0E6C, + 0x0710, 0x06FC, 0x06B6, 0x0316, 0x0159, 0x0317, 0x06B7, 0x06FD, + 0x0711, 0x0E6D, 0x0E7D, 0x0EE3, 0x0F15, 0x0F19, 0x1E88, 0x1F01, + 0x3E4C, 0x3E60, 0x3EA9, 0x3EB1, 0x3F5B, 0x7EED, 0x7FA5, 0xFF9E, + 0x7FBE, 0x7F98, 0x7F0D, 0x7EF3, 0x3E8C, 0x3E50, 0x1EB7, 0x1E73, + 0x0F2F, 0x0EBF, 0x0E99, 0x0E95, 0x0E88, 0x071C, 0x06E6, 0x06BE, + 0x033A, 0x015B, 0x033B, 0x06BF, 0x06E7, 0x071D, 0x0E89, 0x0E92, + 0x0E96, 0x0EBC, 0x0F2C, 0x1E6D, 0x1EB0, 0x3E4D, 0x3E8B, 0x7EF2, + 0x7F08, 0x7F97, 0x7FB0, 0xFF9C, 0x7FB2, 0x7F23, 0x7EFA, 0x3F0F, + 0x3EBD, 0x3EAD, 0x1EA0, 0x1E87, 0x0F0A, 0x0F02, 0x0EED, 0x0EE4, + 0x0EC8, 0x0EA0, 0x0E76, 0x071E, 0x06B8, 0x0324, 0x015C, 0x0325, + 0x06B9, 0x071F, 0x0E77, 0x0EA1, 0x0EC9, 0x0EE5, 0x0EEC, 0x0F03, + 0x0F0B, 0x1E84, 0x1EA2, 0x3EB0, 0x3EC4, 0x3F09, 0x7EF7, 0x7F1D, + 0x7FBC, 0x7FCD, 0x7F81, 0x7F50, 0x7F34, 0x3F65, 0x3EED, 0x3E67, + 0x1EDB, 0x1ED2, 0x1E99, 0x1E77, 0x0F21, 0x0F1C, 0x0EE8, 0x0EA8, + 0x0E6E, 0x0716, 0x033C, 0x0178, 0x033D, 0x0717, 0x0E6F, 0x0EAA, + 0x0EEB, 0x0F1E, 0x0F23, 0x1E75, 0x1E9A, 0x1ED4, 0x1EDC, 0x3E66, + 0x3EEE, 0x3F6B, 0x7F35, 0x7F55, 0x7F7A, 0x7FCA, 0x7FB6, 0x7FB8, + 0x7F37, 0x7F1F, 0x3F61, 0x3F37, 0x3F1A, 0x3EB5, 0x3E62, 0x3E5A, + 0x1F1E, 0x1F13, 0x1EF2, 0x1EE6, 0x1EBC, 0x1E91, 0x1E68, 0x070A, + 0x032C, 0x070B, 0x1E69, 0x1E90, 0x1EBD, 0x1EE4, 0x1EF4, 0x1F12, + 0x3E3E, 0x3E59, 0x3E61, 0x3EB6, 0x3F19, 0x3F3B, 0x3F64, 0x7F1C, + 0x7F3D, 0x7FB4, 0x7FB9, 0xFFC5, 0xFFB6, 0xFFAD, 0x7FA4, 0x7F2C, + 0x7F20, 0x7F09, 0x3EF5, 0x3E93, 0x3E82, 0x3E7E, 0x1F02, 0x1EE3, + 0x1ECA, 0x1EAD, 0x1E7C, 0x0EB8, 0x0E8A, 0x0332, 0x0E8B, 0x0EB9, + 0x1E7D, 0x1EAC, 0x1ECD, 0x1EE0, 0x1F03, 0x3E7D, 0x3E81, 0x3E91, + 0x3EF7, 0x7F0C, 0x7F1A, 0x7F2E, 0x7FA6, 0xFFA4, 0xFFB7, 0xFFC4, + 0xFFD4, 0xFFCC, 0x7FC5, 0x7F8A, 0x7F3C, 0x7EFF, 0x3F5E, 0x3F4E, + 0x3F2F, 0x3EFD, 0x3EEF, 0x3EEB, 0x3E92, 0x3E71, 0x3E42, 0x1F09, + 0x1E83, 0x0E82, 0x0348, 0x0E83, 0x1E80, 0x1F06, 0x3E44, 0x3E72, + 0x3E94, 0x3EEC, 0x3EF2, 0x3EFE, 0x3F34, 0x3F4C, 0x3F5F, 0x7EFE, + 0x7F3A, 0x7F86, 0x7FC4, 0xFFD2, 0xFFD5, 0xFFFA, 0xFFCD, 0xFFBA, + 0x7FAB, 0x7F92, 0x7F87, 0x7F63, 0x7F4C, 0x7F03, 0x7EF0, 0x3F42, + 0x3EA1, 0x3E76, 0x3E6A, 0x3E52, 0x1EEE, 0x1EAB, 0x0ED6, 0x06A9, + 0x0ED7, 0x1EAA, 0x1EED, 0x3E53, 0x3E70, 0x3E77, 0x3EA2, 0x3F41, + 0x7EEF, 0x7F00, 0x7F4D, 0x7F60, 0x7F88, 0x7F93, 0x7FAD, 0xFFB8, + 0xFFCB, 0xFFFB, 0xFFFC, 0xFFE1, 0xFFBF, 0x7FBA, 0x7F73, 0x7F6C, + 0x7F57, 0x7EFC, 0x7EDD, 0x3F6A, 0x3F2A, 0x3F25, 0x3EDD, 0x3ED3, + 0x3EC2, 0x3EA7, 0x3E86, 0x0F11, 0x06B2, 0x0F0E, 0x3E8A, 0x3EA5, + 0x3EC0, 0x3ED1, 0x3EDE, 0x3F2C, 0x3F29, 0x3F69, 0x7EDB, 0x7EFD, + 0x7F59, 0x7F6D, 0x7F74, 0x7FC0, 0xFFC3, 0xFFE3, 0xFFFD, 0xFFF0, + 0xFFE9, 0xFFE7, 0xFFC9, 0xFFBD, 0xFFAE, 0x7F71, 0x7F5F, 0x7F42, + 0x7F41, 0x7F30, 0x7F17, 0x7EE4, 0x3ED7, 0x3EC7, 0x3ECB, 0x1EB1, + 0x0EDC, 0x06D2, 0x0EDD, 0x1EB2, 0x3EC6, 0x3EC8, 0x3ED4, 0x7EE3, + 0x7F18, 0x7F2B, 0x7F3F, 0x7F43, 0x7F64, 0x7F6E, 0xFFAB, 0xFFC2, + 0xFFD0, 0xFFE6, 0xFFEF, 0xFFF3, 0xFFF7, 0xFFEB, 0xFFDE, 0xFFDA, + 0xFFB3, 0xFFAC, 0xFFA3, 0x7FC9, 0x7F8F, 0x7F7C, 0x7F79, 0x7F0F, + 0x7F10, 0x3F55, 0x3F45, 0x1F1A, 0x1E95, 0x0F2B, 0x06F1, 0x0F29, + 0x1E97, 0x1F19, 0x3F47, 0x3F57, 0x7F14, 0x7F12, 0x7F78, 0x7F7E, + 0x7F91, 0x7FC7, 0xFFA1, 0xFFA5, 0xFFB2, 0xFFDB, 0xFFDF, 0xFFED, + 0xFFF4, 0x004C, +}; + +static const uint16_t clv_mvy_3_syms[] = { + 0xEEEE, 0xEFEE, 0xF0EE, 0xF1EE, 0xF2EE, 0xF3EE, 0xF4EE, 0xF5EE, + 0xF6EE, 0xF7EE, 0xF8EE, 0xF9EE, 0xFAEE, 0xFBEE, 0xFCEE, 0xFDEE, + 0xFEEE, 0xFFEE, 0x00EE, 0x01EE, 0x02EE, 0x03EE, 0x04EE, 0x05EE, + 0x06EE, 0x07EE, 0x08EE, 0x09EE, 0x0AEE, 0x0BEE, 0x0CEE, 0x0DEE, + 0x0EEE, 0x0FEE, 0x10EE, 0x11EE, 0x12EE, 0xEEEF, 0xEFEF, 0xF0EF, + 0xF1EF, 0xF2EF, 0xF3EF, 0xF4EF, 0xF5EF, 0xF6EF, 0xF7EF, 0xF8EF, + 0xF9EF, 0xFAEF, 0xFBEF, 0xFCEF, 0xFDEF, 0xFEEF, 0xFFEF, 0x00EF, + 0x01EF, 0x02EF, 0x03EF, 0x04EF, 0x05EF, 0x06EF, 0x07EF, 0x08EF, + 0x09EF, 0x0AEF, 0x0BEF, 0x0CEF, 0x0DEF, 0x0EEF, 0x0FEF, 0x10EF, + 0x11EF, 0x12EF, 0xEEF0, 0xEFF0, 0xF0F0, 0xF1F0, 0xF2F0, 0xF3F0, + 0xF4F0, 0xF5F0, 0xF6F0, 0xF7F0, 0xF8F0, 0xF9F0, 0xFAF0, 0xFBF0, + 0xFCF0, 0xFDF0, 0xFEF0, 0xFFF0, 0x00F0, 0x01F0, 0x02F0, 0x03F0, + 0x04F0, 0x05F0, 0x06F0, 0x07F0, 0x08F0, 0x09F0, 0x0AF0, 0x0BF0, + 0x0CF0, 0x0DF0, 0x0EF0, 0x0FF0, 0x10F0, 0x11F0, 0x12F0, 0xEEF1, + 0xEFF1, 0xF0F1, 0xF1F1, 0xF2F1, 0xF3F1, 0xF4F1, 0xF5F1, 0xF6F1, + 0xF7F1, 0xF8F1, 0xF9F1, 0xFAF1, 0xFBF1, 0xFCF1, 0xFDF1, 0xFEF1, + 0xFFF1, 0x00F1, 0x01F1, 0x02F1, 0x03F1, 0x04F1, 0x05F1, 0x06F1, + 0x07F1, 0x08F1, 0x09F1, 0x0AF1, 0x0BF1, 0x0CF1, 0x0DF1, 0x0EF1, + 0x0FF1, 0x10F1, 0x11F1, 0x12F1, 0xEEF2, 0xEFF2, 0xF0F2, 0xF1F2, + 0xF2F2, 0xF3F2, 0xF4F2, 0xF5F2, 0xF6F2, 0xF7F2, 0xF8F2, 0xF9F2, + 0xFAF2, 0xFBF2, 0xFCF2, 0xFDF2, 0xFEF2, 0xFFF2, 0x00F2, 0x01F2, + 0x02F2, 0x03F2, 0x04F2, 0x05F2, 0x06F2, 0x07F2, 0x08F2, 0x09F2, + 0x0AF2, 0x0BF2, 0x0CF2, 0x0DF2, 0x0EF2, 0x0FF2, 0x10F2, 0x11F2, + 0x12F2, 0xEEF3, 0xEFF3, 0xF0F3, 0xF1F3, 0xF2F3, 0xF3F3, 0xF4F3, + 0xF5F3, 0xF6F3, 0xF7F3, 0xF8F3, 0xF9F3, 0xFAF3, 0xFBF3, 0xFCF3, + 0xFDF3, 0xFEF3, 0xFFF3, 0x00F3, 0x01F3, 0x02F3, 0x03F3, 0x04F3, + 0x05F3, 0x06F3, 0x07F3, 0x08F3, 0x09F3, 0x0AF3, 0x0BF3, 0x0CF3, + 0x0DF3, 0x0EF3, 0x0FF3, 0x10F3, 0x11F3, 0x12F3, 0xEEF4, 0xEFF4, + 0xF0F4, 0xF1F4, 0xF2F4, 0xF3F4, 0xF4F4, 0xF5F4, 0xF6F4, 0xF7F4, + 0xF8F4, 0xF9F4, 0xFAF4, 0xFBF4, 0xFCF4, 0xFDF4, 0xFEF4, 0xFFF4, + 0x00F4, 0x01F4, 0x02F4, 0x03F4, 0x04F4, 0x05F4, 0x06F4, 0x07F4, + 0x08F4, 0x09F4, 0x0AF4, 0x0BF4, 0x0CF4, 0x0DF4, 0x0EF4, 0x0FF4, + 0x10F4, 0x11F4, 0x12F4, 0xEEF5, 0xEFF5, 0xF0F5, 0xF1F5, 0xF2F5, + 0xF3F5, 0xF4F5, 0xF5F5, 0xF6F5, 0xF7F5, 0xF8F5, 0xF9F5, 0xFAF5, + 0xFBF5, 0xFCF5, 0xFDF5, 0xFEF5, 0xFFF5, 0x00F5, 0x01F5, 0x02F5, + 0x03F5, 0x04F5, 0x05F5, 0x06F5, 0x07F5, 0x08F5, 0x09F5, 0x0AF5, + 0x0BF5, 0x0CF5, 0x0DF5, 0x0EF5, 0x0FF5, 0x10F5, 0x11F5, 0x12F5, + 0xEEF6, 0xEFF6, 0xF0F6, 0xF1F6, 0xF2F6, 0xF3F6, 0xF4F6, 0xF5F6, + 0xF6F6, 0xF7F6, 0xF8F6, 0xF9F6, 0xFAF6, 0xFBF6, 0xFCF6, 0xFDF6, + 0xFEF6, 0xFFF6, 0x00F6, 0x01F6, 0x02F6, 0x03F6, 0x04F6, 0x05F6, + 0x06F6, 0x07F6, 0x08F6, 0x09F6, 0x0AF6, 0x0BF6, 0x0CF6, 0x0DF6, + 0x0EF6, 0x0FF6, 0x10F6, 0x11F6, 0x12F6, 0xEEF7, 0xEFF7, 0xF0F7, + 0xF1F7, 0xF2F7, 0xF3F7, 0xF4F7, 0xF5F7, 0xF6F7, 0xF7F7, 0xF8F7, + 0xF9F7, 0xFAF7, 0xFBF7, 0xFCF7, 0xFDF7, 0xFEF7, 0xFFF7, 0x00F7, + 0x01F7, 0x02F7, 0x03F7, 0x04F7, 0x05F7, 0x06F7, 0x07F7, 0x08F7, + 0x09F7, 0x0AF7, 0x0BF7, 0x0CF7, 0x0DF7, 0x0EF7, 0x0FF7, 0x10F7, + 0x11F7, 0x12F7, 0xEEF8, 0xEFF8, 0xF0F8, 0xF1F8, 0xF2F8, 0xF3F8, + 0xF4F8, 0xF5F8, 0xF6F8, 0xF7F8, 0xF8F8, 0xF9F8, 0xFAF8, 0xFBF8, + 0xFCF8, 0xFDF8, 0xFEF8, 0xFFF8, 0x00F8, 0x01F8, 0x02F8, 0x03F8, + 0x04F8, 0x05F8, 0x06F8, 0x07F8, 0x08F8, 0x09F8, 0x0AF8, 0x0BF8, + 0x0CF8, 0x0DF8, 0x0EF8, 0x0FF8, 0x10F8, 0x11F8, 0x12F8, 0xEEF9, + 0xEFF9, 0xF0F9, 0xF1F9, 0xF2F9, 0xF3F9, 0xF4F9, 0xF5F9, 0xF6F9, + 0xF7F9, 0xF8F9, 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, + 0xFFF9, 0x00F9, 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, + 0x07F9, 0x08F9, 0x09F9, 0x0AF9, 0x0BF9, 0x0CF9, 0x0DF9, 0x0EF9, + 0x0FF9, 0x10F9, 0x11F9, 0x12F9, 0xEEFA, 0xEFFA, 0xF0FA, 0xF1FA, + 0xF2FA, 0xF3FA, 0xF4FA, 0xF5FA, 0xF6FA, 0xF7FA, 0xF8FA, 0xF9FA, + 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, + 0x02FA, 0x03FA, 0x04FA, 0x05FA, 0x06FA, 0x07FA, 0x08FA, 0x09FA, + 0x0AFA, 0x0BFA, 0x0CFA, 0x0DFA, 0x0EFA, 0x0FFA, 0x10FA, 0x11FA, + 0x12FA, 0xEEFB, 0xEFFB, 0xF0FB, 0xF1FB, 0xF2FB, 0xF3FB, 0xF4FB, + 0xF5FB, 0xF6FB, 0xF7FB, 0xF8FB, 0xF9FB, 0xFAFB, 0xFBFB, 0xFCFB, + 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, 0x03FB, 0x04FB, + 0x05FB, 0x06FB, 0x07FB, 0x08FB, 0x09FB, 0x0AFB, 0x0BFB, 0x0CFB, + 0x0DFB, 0x0EFB, 0x0FFB, 0x10FB, 0x11FB, 0x12FB, 0xEEFC, 0xEFFC, + 0xF0FC, 0xF1FC, 0xF2FC, 0xF3FC, 0xF4FC, 0xF5FC, 0xF6FC, 0xF7FC, + 0xF8FC, 0xF9FC, 0xFAFC, 0xFBFC, 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, + 0x00FC, 0x01FC, 0x02FC, 0x03FC, 0x04FC, 0x05FC, 0x06FC, 0x07FC, + 0x08FC, 0x09FC, 0x0AFC, 0x0BFC, 0x0CFC, 0x0DFC, 0x0EFC, 0x0FFC, + 0x10FC, 0x11FC, 0x12FC, 0xEEFD, 0xEFFD, 0xF0FD, 0xF1FD, 0xF2FD, + 0xF3FD, 0xF4FD, 0xF5FD, 0xF6FD, 0xF7FD, 0xF8FD, 0xF9FD, 0xFAFD, + 0xFBFD, 0xFCFD, 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, + 0x03FD, 0x04FD, 0x05FD, 0x06FD, 0x07FD, 0x08FD, 0x09FD, 0x0AFD, + 0x0BFD, 0x0CFD, 0x0DFD, 0x0EFD, 0x0FFD, 0x10FD, 0x11FD, 0x12FD, + 0xEEFE, 0xEFFE, 0xF0FE, 0xF1FE, 0xF2FE, 0xF3FE, 0xF4FE, 0xF5FE, + 0xF6FE, 0xF7FE, 0xF8FE, 0xF9FE, 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, + 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, 0x02FE, 0x03FE, 0x04FE, 0x05FE, + 0x06FE, 0x07FE, 0x08FE, 0x09FE, 0x0AFE, 0x0BFE, 0x0CFE, 0x0DFE, + 0x0EFE, 0x0FFE, 0x10FE, 0x11FE, 0x12FE, 0xEEFF, 0xEFFF, 0xF0FF, + 0xF1FF, 0xF2FF, 0xF3FF, 0xF4FF, 0xF5FF, 0xF6FF, 0xF7FF, 0xF8FF, + 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, 0xFFFF, 0x00FF, + 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, 0x07FF, 0x08FF, + 0x09FF, 0x0AFF, 0x0BFF, 0x0CFF, 0x0DFF, 0x0EFF, 0x0FFF, 0x10FF, + 0x11FF, 0x12FF, 0xEE00, 0xEF00, 0xF000, 0xF100, 0xF200, 0xF300, + 0xF400, 0xF500, 0xF600, 0xF700, 0xF800, 0xF900, 0xFA00, 0xFB00, + 0xFC00, 0xFD00, 0xFE00, 0xFF00, 0x0000, 0x0100, 0x0200, 0x0300, + 0x0400, 0x0500, 0x0600, 0x0700, 0x0800, 0x0900, 0x0A00, 0x0B00, + 0x0C00, 0x0D00, 0x0E00, 0x0F00, 0x1000, 0x1100, 0x1200, 0xEE01, + 0xEF01, 0xF001, 0xF101, 0xF201, 0xF301, 0xF401, 0xF501, 0xF601, + 0xF701, 0xF801, 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, + 0xFF01, 0x0001, 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, + 0x0701, 0x0801, 0x0901, 0x0A01, 0x0B01, 0x0C01, 0x0D01, 0x0E01, + 0x0F01, 0x1001, 0x1101, 0x1201, 0xEE02, 0xEF02, 0xF002, 0xF102, + 0xF202, 0xF302, 0xF402, 0xF502, 0xF602, 0xF702, 0xF802, 0xF902, + 0xFA02, 0xFB02, 0xFC02, 0xFD02, 0xFE02, 0xFF02, 0x0002, 0x0102, + 0x0202, 0x0302, 0x0402, 0x0502, 0x0602, 0x0702, 0x0802, 0x0902, + 0x0A02, 0x0B02, 0x0C02, 0x0D02, 0x0E02, 0x0F02, 0x1002, 0x1102, + 0x1202, 0xEE03, 0xEF03, 0xF003, 0xF103, 0xF203, 0xF303, 0xF403, + 0xF503, 0xF603, 0xF703, 0xF803, 0xF903, 0xFA03, 0xFB03, 0xFC03, + 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, 0x0303, 0x0403, + 0x0503, 0x0603, 0x0703, 0x0803, 0x0903, 0x0A03, 0x0B03, 0x0C03, + 0x0D03, 0x0E03, 0x0F03, 0x1003, 0x1103, 0x1203, 0xEE04, 0xEF04, + 0xF004, 0xF104, 0xF204, 0xF304, 0xF404, 0xF504, 0xF604, 0xF704, + 0xF804, 0xF904, 0xFA04, 0xFB04, 0xFC04, 0xFD04, 0xFE04, 0xFF04, + 0x0004, 0x0104, 0x0204, 0x0304, 0x0404, 0x0504, 0x0604, 0x0704, + 0x0804, 0x0904, 0x0A04, 0x0B04, 0x0C04, 0x0D04, 0x0E04, 0x0F04, + 0x1004, 0x1104, 0x1204, 0xEE05, 0xEF05, 0xF005, 0xF105, 0xF205, + 0xF305, 0xF405, 0xF505, 0xF605, 0xF705, 0xF805, 0xF905, 0xFA05, + 0xFB05, 0xFC05, 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, + 0x0305, 0x0405, 0x0505, 0x0605, 0x0705, 0x0805, 0x0905, 0x0A05, + 0x0B05, 0x0C05, 0x0D05, 0x0E05, 0x0F05, 0x1005, 0x1105, 0x1205, + 0xEE06, 0xEF06, 0xF006, 0xF106, 0xF206, 0xF306, 0xF406, 0xF506, + 0xF606, 0xF706, 0xF806, 0xF906, 0xFA06, 0xFB06, 0xFC06, 0xFD06, + 0xFE06, 0xFF06, 0x0006, 0x0106, 0x0206, 0x0306, 0x0406, 0x0506, + 0x0606, 0x0706, 0x0806, 0x0906, 0x0A06, 0x0B06, 0x0C06, 0x0D06, + 0x0E06, 0x0F06, 0x1006, 0x1106, 0x1206, 0xEE07, 0xEF07, 0xF007, + 0xF107, 0xF207, 0xF307, 0xF407, 0xF507, 0xF607, 0xF707, 0xF807, + 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, 0xFF07, 0x0007, + 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, 0x0707, 0x0807, + 0x0907, 0x0A07, 0x0B07, 0x0C07, 0x0D07, 0x0E07, 0x0F07, 0x1007, + 0x1107, 0x1207, 0xEE08, 0xEF08, 0xF008, 0xF108, 0xF208, 0xF308, + 0xF408, 0xF508, 0xF608, 0xF708, 0xF808, 0xF908, 0xFA08, 0xFB08, + 0xFC08, 0xFD08, 0xFE08, 0xFF08, 0x0008, 0x0108, 0x0208, 0x0308, + 0x0408, 0x0508, 0x0608, 0x0708, 0x0808, 0x0908, 0x0A08, 0x0B08, + 0x0C08, 0x0D08, 0x0E08, 0x0F08, 0x1008, 0x1108, 0x1208, 0xEE09, + 0xEF09, 0xF009, 0xF109, 0xF209, 0xF309, 0xF409, 0xF509, 0xF609, + 0xF709, 0xF809, 0xF909, 0xFA09, 0xFB09, 0xFC09, 0xFD09, 0xFE09, + 0xFF09, 0x0009, 0x0109, 0x0209, 0x0309, 0x0409, 0x0509, 0x0609, + 0x0709, 0x0809, 0x0909, 0x0A09, 0x0B09, 0x0C09, 0x0D09, 0x0E09, + 0x0F09, 0x1009, 0x1109, 0x1209, 0xEE0A, 0xEF0A, 0xF00A, 0xF10A, + 0xF20A, 0xF30A, 0xF40A, 0xF50A, 0xF60A, 0xF70A, 0xF80A, 0xF90A, + 0xFA0A, 0xFB0A, 0xFC0A, 0xFD0A, 0xFE0A, 0xFF0A, 0x000A, 0x010A, + 0x020A, 0x030A, 0x040A, 0x050A, 0x060A, 0x070A, 0x080A, 0x090A, + 0x0A0A, 0x0B0A, 0x0C0A, 0x0D0A, 0x0E0A, 0x0F0A, 0x100A, 0x110A, + 0x120A, 0xEE0B, 0xEF0B, 0xF00B, 0xF10B, 0xF20B, 0xF30B, 0xF40B, + 0xF50B, 0xF60B, 0xF70B, 0xF80B, 0xF90B, 0xFA0B, 0xFB0B, 0xFC0B, + 0xFD0B, 0xFE0B, 0xFF0B, 0x000B, 0x010B, 0x020B, 0x030B, 0x040B, + 0x050B, 0x060B, 0x070B, 0x080B, 0x090B, 0x0A0B, 0x0B0B, 0x0C0B, + 0x0D0B, 0x0E0B, 0x0F0B, 0x100B, 0x110B, 0x120B, 0xEE0C, 0xEF0C, + 0xF00C, 0xF10C, 0xF20C, 0xF30C, 0xF40C, 0xF50C, 0xF60C, 0xF70C, + 0xF80C, 0xF90C, 0xFA0C, 0xFB0C, 0xFC0C, 0xFD0C, 0xFE0C, 0xFF0C, + 0x000C, 0x010C, 0x020C, 0x030C, 0x040C, 0x050C, 0x060C, 0x070C, + 0x080C, 0x090C, 0x0A0C, 0x0B0C, 0x0C0C, 0x0D0C, 0x0E0C, 0x0F0C, + 0x100C, 0x110C, 0x120C, 0xEE0D, 0xEF0D, 0xF00D, 0xF10D, 0xF20D, + 0xF30D, 0xF40D, 0xF50D, 0xF60D, 0xF70D, 0xF80D, 0xF90D, 0xFA0D, + 0xFB0D, 0xFC0D, 0xFD0D, 0xFE0D, 0xFF0D, 0x000D, 0x010D, 0x020D, + 0x030D, 0x040D, 0x050D, 0x060D, 0x070D, 0x080D, 0x090D, 0x0A0D, + 0x0B0D, 0x0C0D, 0x0D0D, 0x0E0D, 0x0F0D, 0x100D, 0x110D, 0x120D, + 0xEE0E, 0xEF0E, 0xF00E, 0xF10E, 0xF20E, 0xF30E, 0xF40E, 0xF50E, + 0xF60E, 0xF70E, 0xF80E, 0xF90E, 0xFA0E, 0xFB0E, 0xFC0E, 0xFD0E, + 0xFE0E, 0xFF0E, 0x000E, 0x010E, 0x020E, 0x030E, 0x040E, 0x050E, + 0x060E, 0x070E, 0x080E, 0x090E, 0x0A0E, 0x0B0E, 0x0C0E, 0x0D0E, + 0x0E0E, 0x0F0E, 0x100E, 0x110E, 0x120E, 0xEE0F, 0xEF0F, 0xF00F, + 0xF10F, 0xF20F, 0xF30F, 0xF40F, 0xF50F, 0xF60F, 0xF70F, 0xF80F, + 0xF90F, 0xFA0F, 0xFB0F, 0xFC0F, 0xFD0F, 0xFE0F, 0xFF0F, 0x000F, + 0x010F, 0x020F, 0x030F, 0x040F, 0x050F, 0x060F, 0x070F, 0x080F, + 0x090F, 0x0A0F, 0x0B0F, 0x0C0F, 0x0D0F, 0x0E0F, 0x0F0F, 0x100F, + 0x110F, 0x120F, 0xEE10, 0xEF10, 0xF010, 0xF110, 0xF210, 0xF310, + 0xF410, 0xF510, 0xF610, 0xF710, 0xF810, 0xF910, 0xFA10, 0xFB10, + 0xFC10, 0xFD10, 0xFE10, 0xFF10, 0x0010, 0x0110, 0x0210, 0x0310, + 0x0410, 0x0510, 0x0610, 0x0710, 0x0810, 0x0910, 0x0A10, 0x0B10, + 0x0C10, 0x0D10, 0x0E10, 0x0F10, 0x1010, 0x1110, 0x1210, 0xEE11, + 0xEF11, 0xF011, 0xF111, 0xF211, 0xF311, 0xF411, 0xF511, 0xF611, + 0xF711, 0xF811, 0xF911, 0xFA11, 0xFB11, 0xFC11, 0xFD11, 0xFE11, + 0xFF11, 0x0011, 0x0111, 0x0211, 0x0311, 0x0411, 0x0511, 0x0611, + 0x0711, 0x0811, 0x0911, 0x0A11, 0x0B11, 0x0C11, 0x0D11, 0x0E11, + 0x0F11, 0x1011, 0x1111, 0x1211, 0xEE12, 0xEF12, 0xF012, 0xF112, + 0xF212, 0xF312, 0xF412, 0xF512, 0xF612, 0xF712, 0xF812, 0xF912, + 0xFA12, 0xFB12, 0xFC12, 0xFD12, 0xFE12, 0xFF12, 0x0012, 0x0112, + 0x0212, 0x0312, 0x0412, 0x0512, 0x0612, 0x0712, 0x0812, 0x0912, + 0x0A12, 0x0B12, 0x0C12, 0x0D12, 0x0E12, 0x0F12, 0x1012, 0x1112, + 0x1212, 0x1313, +}; + +static const uint8_t clv_mvu_1_bits[] = { + 16, 14, 14, 14, 13, 12, 12, 10, 12, 12, 13, 14, 14, 14, 16, 15, + 13, 13, 12, 12, 11, 11, 7, 11, 11, 12, 12, 13, 13, 15, 16, 16, + 16, 13, 12, 10, 10, 6, 10, 10, 12, 13, 16, 16, 16, 14, 14, 11, + 11, 11, 11, 9, 7, 9, 11, 11, 11, 11, 14, 14, 15, 13, 13, 12, + 9, 8, 8, 4, 8, 8, 9, 12, 13, 13, 15, 14, 14, 11, 11, 10, + 9, 8, 4, 8, 9, 10, 11, 12, 14, 14, 12, 12, 11, 10, 10, 8, + 6, 3, 6, 8, 10, 10, 11, 12, 12, 11, 10, 9, 6, 6, 6, 5, + 4, 5, 6, 6, 6, 9, 10, 11, 12, 12, 11, 10, 10, 8, 6, 3, + 6, 7, 10, 10, 11, 12, 12, 14, 14, 11, 11, 10, 9, 8, 4, 8, + 9, 10, 11, 11, 14, 14, 15, 13, 13, 12, 9, 8, 8, 4, 8, 8, + 9, 12, 13, 13, 15, 14, 14, 11, 11, 11, 11, 9, 7, 9, 11, 11, + 11, 11, 14, 14, 16, 16, 16, 13, 12, 10, 10, 6, 10, 10, 12, 13, + 16, 16, 16, 15, 13, 13, 12, 12, 11, 11, 7, 11, 11, 12, 12, 13, + 13, 15, 16, 14, 14, 14, 13, 12, 12, 10, 12, 12, 13, 14, 14, 14, + 16, 7, +}; + +static const uint16_t clv_mvu_1_codes[] = { + 0xFFFC, 0x3FED, 0x3FE5, 0x3FE3, 0x1FD9, 0x0FD9, 0x0FD6, 0x03CE, + 0x0FD3, 0x0FD8, 0x1FD6, 0x3FE0, 0x3FE8, 0x3FEC, 0xFFFE, 0x7FF3, + 0x1FE7, 0x1FDA, 0x0FCF, 0x0FCC, 0x07DD, 0x07CC, 0x006B, 0x07CD, + 0x07DE, 0x0FCE, 0x0FD2, 0x1FDD, 0x1FEC, 0x7FF0, 0xFFF6, 0xFFFA, + 0xFFF2, 0x1FDE, 0x0FDB, 0x03D8, 0x03CA, 0x002E, 0x03CB, 0x03D9, + 0x0FDC, 0x1FDF, 0xFFF3, 0xFFF9, 0xFFF5, 0x3FF3, 0x3FDD, 0x07DA, + 0x07D2, 0x07CA, 0x07C2, 0x01DE, 0x0069, 0x01DF, 0x07C3, 0x07CB, + 0x07D3, 0x07DB, 0x3FDF, 0x3FF6, 0x7FF7, 0x1FED, 0x1FE5, 0x0FDF, + 0x01D8, 0x00E3, 0x00DF, 0x0007, 0x00E0, 0x00E4, 0x01D9, 0x0FE0, + 0x1FE3, 0x1FE9, 0x7FF4, 0x3FF5, 0x3FE7, 0x07E4, 0x07C6, 0x03D2, + 0x01E2, 0x00E9, 0x0006, 0x00EA, 0x01E3, 0x03D3, 0x07C7, 0x0FCA, + 0x3FE9, 0x3FF0, 0x0FE8, 0x0FE5, 0x07D5, 0x03DD, 0x03D5, 0x00DC, + 0x002B, 0x0001, 0x002C, 0x00DD, 0x03D6, 0x03DE, 0x07D6, 0x0FE4, + 0x0FE9, 0x07E0, 0x03C8, 0x01D6, 0x0032, 0x0030, 0x0028, 0x0012, + 0x0004, 0x0013, 0x0029, 0x0031, 0x0033, 0x01D7, 0x03C9, 0x07E1, + 0x0FEA, 0x0FE6, 0x07D7, 0x03DF, 0x03D7, 0x00DE, 0x002D, 0x0000, + 0x002A, 0x006D, 0x03D4, 0x03DC, 0x07D4, 0x0FE3, 0x0FE7, 0x3FF1, + 0x3FE4, 0x07E2, 0x07C4, 0x03D0, 0x01E0, 0x00E7, 0x0005, 0x00E8, + 0x01E1, 0x03D1, 0x07C5, 0x07E3, 0x3FEA, 0x3FF7, 0x7FF6, 0x1FE6, + 0x1FE4, 0x0FE1, 0x01DA, 0x00E5, 0x00E1, 0x0008, 0x00E2, 0x00E6, + 0x01DB, 0x0FE2, 0x1FE2, 0x1FEB, 0x7FF5, 0x3FF4, 0x3FDC, 0x07D9, + 0x07D0, 0x07C8, 0x07C0, 0x01DC, 0x0068, 0x01DD, 0x07C1, 0x07C9, + 0x07D1, 0x07D8, 0x3FDE, 0x3FF2, 0xFFFB, 0xFFF4, 0xFFF0, 0x1FE1, + 0x0FDD, 0x03DA, 0x03CC, 0x002F, 0x03CD, 0x03DB, 0x0FDE, 0x1FE0, + 0xFFF1, 0xFFF7, 0xFFF8, 0x7FF2, 0x1FEA, 0x1FDC, 0x0FD1, 0x0FCD, + 0x07DC, 0x07CF, 0x006C, 0x07CE, 0x07DF, 0x0FCB, 0x0FD0, 0x1FDB, + 0x1FE8, 0x7FF1, 0xFFFD, 0x3FEE, 0x3FEB, 0x3FE1, 0x1FD7, 0x0FD7, + 0x0FD5, 0x03CF, 0x0FD4, 0x0FDA, 0x1FD8, 0x3FE2, 0x3FE6, 0x3FEF, + 0xFFFF, 0x006A, +}; + +static const uint16_t clv_mvu_1_syms[] = { + 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, 0xFFF9, 0x00F9, + 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, 0x07F9, 0xF9FA, + 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, + 0x02FA, 0x03FA, 0x04FA, 0x05FA, 0x06FA, 0x07FA, 0xF9FB, 0xFAFB, + 0xFBFB, 0xFCFB, 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, + 0x03FB, 0x04FB, 0x05FB, 0x06FB, 0x07FB, 0xF9FC, 0xFAFC, 0xFBFC, + 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, 0x00FC, 0x01FC, 0x02FC, 0x03FC, + 0x04FC, 0x05FC, 0x06FC, 0x07FC, 0xF9FD, 0xFAFD, 0xFBFD, 0xFCFD, + 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, 0x03FD, 0x04FD, + 0x05FD, 0x06FD, 0x07FD, 0xF9FE, 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, + 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, 0x02FE, 0x03FE, 0x04FE, 0x05FE, + 0x06FE, 0x07FE, 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, + 0xFFFF, 0x00FF, 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, + 0x07FF, 0xF900, 0xFA00, 0xFB00, 0xFC00, 0xFD00, 0xFE00, 0xFF00, + 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, + 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, 0xFF01, 0x0001, + 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, 0x0701, 0xF902, + 0xFA02, 0xFB02, 0xFC02, 0xFD02, 0xFE02, 0xFF02, 0x0002, 0x0102, + 0x0202, 0x0302, 0x0402, 0x0502, 0x0602, 0x0702, 0xF903, 0xFA03, + 0xFB03, 0xFC03, 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, + 0x0303, 0x0403, 0x0503, 0x0603, 0x0703, 0xF904, 0xFA04, 0xFB04, + 0xFC04, 0xFD04, 0xFE04, 0xFF04, 0x0004, 0x0104, 0x0204, 0x0304, + 0x0404, 0x0504, 0x0604, 0x0704, 0xF905, 0xFA05, 0xFB05, 0xFC05, + 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, 0x0305, 0x0405, + 0x0505, 0x0605, 0x0705, 0xF906, 0xFA06, 0xFB06, 0xFC06, 0xFD06, + 0xFE06, 0xFF06, 0x0006, 0x0106, 0x0206, 0x0306, 0x0406, 0x0506, + 0x0606, 0x0706, 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, + 0xFF07, 0x0007, 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, + 0x0707, 0x0808, +}; + +static const uint8_t clv_mvu_2_bits[] = { + 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 15, 15, + 15, 15, 16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, + 13, 14, 14, 14, 14, 14, 15, 15, 15, 16, 16, 15, 15, 14, 14, 14, + 14, 14, 14, 13, 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, 16, 16, + 15, 15, 14, 13, 13, 13, 13, 13, 12, 12, 12, 13, 13, 13, 13, 13, + 14, 15, 15, 16, 14, 14, 14, 14, 13, 12, 12, 12, 12, 11, 10, 11, + 12, 12, 12, 12, 13, 14, 14, 14, 14, 14, 14, 14, 13, 12, 12, 12, + 12, 11, 10, 9, 10, 11, 12, 12, 12, 12, 13, 14, 14, 14, 15, 14, + 13, 13, 12, 12, 12, 12, 11, 10, 8, 10, 11, 12, 12, 12, 12, 13, + 13, 14, 15, 14, 14, 14, 13, 12, 12, 11, 11, 10, 9, 7, 9, 10, + 11, 11, 12, 12, 13, 14, 14, 14, 14, 14, 13, 12, 12, 11, 11, 10, + 9, 8, 7, 8, 9, 10, 11, 11, 12, 12, 13, 14, 14, 14, 13, 13, + 12, 11, 9, 9, 8, 7, 6, 5, 6, 7, 8, 9, 9, 11, 12, 13, + 13, 14, 14, 13, 13, 13, 11, 11, 10, 8, 7, 4, 1, 4, 7, 8, + 10, 11, 11, 13, 13, 13, 14, 14, 13, 13, 12, 11, 9, 9, 8, 7, + 6, 5, 6, 7, 8, 9, 9, 11, 12, 13, 13, 14, 14, 14, 13, 12, + 11, 11, 11, 9, 9, 8, 7, 8, 9, 10, 11, 11, 12, 12, 13, 14, + 14, 14, 14, 14, 13, 12, 12, 11, 11, 10, 9, 7, 9, 10, 11, 11, + 12, 12, 13, 14, 14, 14, 15, 14, 13, 13, 12, 12, 12, 12, 11, 10, + 9, 10, 11, 12, 12, 12, 12, 13, 13, 14, 15, 14, 14, 14, 13, 12, + 12, 12, 12, 11, 10, 8, 10, 11, 12, 12, 12, 12, 13, 14, 14, 14, + 14, 14, 14, 14, 13, 12, 12, 12, 12, 11, 10, 11, 12, 12, 12, 12, + 13, 14, 14, 14, 14, 16, 15, 15, 14, 13, 13, 13, 13, 13, 12, 12, + 12, 13, 13, 13, 13, 13, 14, 15, 15, 16, 16, 15, 15, 14, 14, 14, + 14, 14, 14, 13, 12, 13, 14, 14, 14, 14, 14, 14, 15, 15, 16, 16, + 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, 14, 14, 14, 14, 14, + 15, 15, 15, 16, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, + 14, 14, 15, 15, 15, 15, 16, 16, 16, 6, +}; + +static const uint16_t clv_mvu_2_codes[] = { + 0xFFF2, 0xFFEF, 0xFFEA, 0x7FEC, 0x7FD5, 0x7FC5, 0x7FCF, 0x3FD3, + 0x3FC9, 0x3FB4, 0x3F72, 0x3FAE, 0x3FDC, 0x3FE1, 0x7FC4, 0x7FC8, + 0x7FD7, 0x7FF0, 0xFFE9, 0xFFEC, 0xFFF8, 0xFFF4, 0x7FF3, 0x7FDE, + 0x7FD3, 0x3FC0, 0x3F99, 0x3FA8, 0x3FAC, 0x3F8E, 0x1FA8, 0x1F79, + 0x1FA2, 0x3F89, 0x3F93, 0x3F95, 0x3F9C, 0x3FB8, 0x7FD2, 0x7FE6, + 0x7FDA, 0xFFF7, 0xFFFE, 0x7FED, 0x7FE2, 0x3FD5, 0x3FD7, 0x3FB3, + 0x3FA2, 0x3F80, 0x3F7A, 0x1F88, 0x1F70, 0x1F8A, 0x3F83, 0x3F84, + 0x3FAA, 0x3FC4, 0x3FDA, 0x3FDF, 0x7FDB, 0x7FE3, 0xFFF1, 0xFFFB, + 0x7FE1, 0x7FC7, 0x3FB0, 0x1FAA, 0x1FAB, 0x1FA3, 0x1F8E, 0x1F81, + 0x0FA7, 0x0F7F, 0x0FA8, 0x1F82, 0x1F8F, 0x1FA4, 0x1FAC, 0x1FAD, + 0x3FB5, 0x7FC6, 0x7FDD, 0xFFF3, 0x3FDD, 0x3FBE, 0x3FB9, 0x3F7C, + 0x1F77, 0x0FB5, 0x0F9D, 0x0F99, 0x0F90, 0x0794, 0x03BE, 0x0795, + 0x0F92, 0x0F9A, 0x0F9E, 0x0FB6, 0x1F78, 0x3F78, 0x3FB2, 0x3FBF, + 0x3FD2, 0x3FA7, 0x3F8C, 0x3F75, 0x1F9E, 0x0F93, 0x0F94, 0x0F7B, + 0x0F73, 0x07B4, 0x03BB, 0x01D9, 0x03BC, 0x07B5, 0x0F74, 0x0F7C, + 0x0F95, 0x0F96, 0x1FA0, 0x3F76, 0x3F8F, 0x3FA5, 0x7FE5, 0x3FC7, + 0x1F95, 0x1F71, 0x0FAB, 0x0FAC, 0x0F9F, 0x0F7D, 0x0796, 0x03BF, + 0x00DE, 0x03C0, 0x0797, 0x0F7E, 0x0FA0, 0x0FAD, 0x0FAE, 0x1F72, + 0x1F97, 0x3FD1, 0x7FD8, 0x3FA9, 0x3FA0, 0x3F6D, 0x1F99, 0x0F87, + 0x0F77, 0x07A8, 0x079C, 0x03C5, 0x01CA, 0x0067, 0x01CB, 0x03C6, + 0x079D, 0x07A9, 0x0F78, 0x0F8A, 0x1F9F, 0x3F6E, 0x3F98, 0x3F9A, + 0x3FCA, 0x3F70, 0x1FAF, 0x0F8D, 0x0F6F, 0x07AC, 0x07A0, 0x03B7, + 0x01CE, 0x00DA, 0x0063, 0x00DB, 0x01CF, 0x03B8, 0x07A1, 0x07AD, + 0x0F70, 0x0F91, 0x1FB2, 0x3F73, 0x3FD6, 0x3F7D, 0x1F91, 0x1F85, + 0x0FA3, 0x07A2, 0x01D4, 0x01D0, 0x00E0, 0x0068, 0x002C, 0x0014, + 0x002D, 0x0069, 0x00E1, 0x01D1, 0x01D5, 0x07A3, 0x0FA4, 0x1F89, + 0x1F92, 0x3F81, 0x3FA6, 0x1F7B, 0x1F7C, 0x1F7D, 0x07B0, 0x07AE, + 0x03C7, 0x00DC, 0x0064, 0x0008, 0x0000, 0x0009, 0x0065, 0x00DD, + 0x03C8, 0x07AF, 0x07B1, 0x1F7E, 0x1F7F, 0x1F80, 0x3F9E, 0x3F85, + 0x1F93, 0x1F8B, 0x0FA5, 0x07A4, 0x01D6, 0x01D2, 0x00E2, 0x006A, + 0x002E, 0x0015, 0x002F, 0x006B, 0x00E3, 0x01D3, 0x01D7, 0x07A5, + 0x0FA6, 0x1F8C, 0x1F94, 0x3F87, 0x3FCE, 0x3F77, 0x1FB4, 0x0F83, + 0x07B6, 0x07AA, 0x079E, 0x01DA, 0x01CC, 0x00D8, 0x0062, 0x00D9, + 0x01CD, 0x03B6, 0x079F, 0x07AB, 0x0F6E, 0x0F84, 0x1FA9, 0x3F6A, + 0x3FCD, 0x3F90, 0x3F92, 0x3F6B, 0x1F96, 0x0F85, 0x0F75, 0x07A6, + 0x079A, 0x03C3, 0x01C8, 0x0066, 0x01C9, 0x03C4, 0x079B, 0x07A7, + 0x0F76, 0x0F86, 0x1F9D, 0x3F6C, 0x3F96, 0x3F97, 0x7FE9, 0x3FD8, + 0x1F98, 0x1F73, 0x0FAF, 0x0FB0, 0x0FA1, 0x0F80, 0x0798, 0x03C1, + 0x01D8, 0x03C2, 0x0799, 0x0F81, 0x0FA2, 0x0FB1, 0x0FB2, 0x1F74, + 0x1F9A, 0x3FE0, 0x7FEE, 0x3F94, 0x3F8B, 0x3F6F, 0x1F9B, 0x0F88, + 0x0F89, 0x0F79, 0x0F71, 0x07B2, 0x03B9, 0x00DF, 0x03BA, 0x07B3, + 0x0F72, 0x0F7A, 0x0F8B, 0x0F8C, 0x1F9C, 0x3F71, 0x3F8A, 0x3F9B, + 0x3FC8, 0x3FBD, 0x3FC5, 0x3F79, 0x1F75, 0x0FB3, 0x0F9C, 0x0F97, + 0x0F8E, 0x0792, 0x03BD, 0x0793, 0x0F8F, 0x0F98, 0x0F9B, 0x0FB4, + 0x1F76, 0x3F82, 0x3FC3, 0x3FBA, 0x3FC6, 0xFFFD, 0x7FDF, 0x7FCC, + 0x3FBB, 0x1FB0, 0x1FAE, 0x1FA1, 0x1F90, 0x1F83, 0x0FAA, 0x0F82, + 0x0FA9, 0x1F84, 0x1F8D, 0x1FA5, 0x1FB1, 0x1FB3, 0x3FC2, 0x7FCA, + 0x7FE8, 0xFFF5, 0xFFFF, 0x7FDC, 0x7FD9, 0x3FCC, 0x3FD9, 0x3FB7, + 0x3F9F, 0x3F7E, 0x3F86, 0x1F86, 0x0FB7, 0x1F87, 0x3F7B, 0x3F7F, + 0x3FA1, 0x3FBC, 0x3FCB, 0x3FD4, 0x7FF1, 0x7FF2, 0xFFFA, 0xFFFC, + 0x7FE4, 0x7FE7, 0x7FD4, 0x3FAF, 0x3FA3, 0x3F91, 0x3F9D, 0x3F88, + 0x1FA6, 0x1F7A, 0x1FA7, 0x3F8D, 0x3FAB, 0x3FAD, 0x3FA4, 0x3FB6, + 0x7FD0, 0x7FE0, 0x7FEB, 0xFFF0, 0xFFF9, 0xFFEB, 0xFFED, 0x7FEA, + 0x7FD6, 0x7FC9, 0x7FCB, 0x3FD0, 0x3FDE, 0x3FB1, 0x3F74, 0x3FC1, + 0x3FCF, 0x3FDB, 0x7FCD, 0x7FCE, 0x7FD1, 0x7FEF, 0xFFE8, 0xFFEE, + 0xFFF6, 0x0030, +}; + +static const uint16_t clv_mvu_2_syms[] = { + 0xF6F6, 0xF7F6, 0xF8F6, 0xF9F6, 0xFAF6, 0xFBF6, 0xFCF6, 0xFDF6, + 0xFEF6, 0xFFF6, 0x00F6, 0x01F6, 0x02F6, 0x03F6, 0x04F6, 0x05F6, + 0x06F6, 0x07F6, 0x08F6, 0x09F6, 0x0AF6, 0xF6F7, 0xF7F7, 0xF8F7, + 0xF9F7, 0xFAF7, 0xFBF7, 0xFCF7, 0xFDF7, 0xFEF7, 0xFFF7, 0x00F7, + 0x01F7, 0x02F7, 0x03F7, 0x04F7, 0x05F7, 0x06F7, 0x07F7, 0x08F7, + 0x09F7, 0x0AF7, 0xF6F8, 0xF7F8, 0xF8F8, 0xF9F8, 0xFAF8, 0xFBF8, + 0xFCF8, 0xFDF8, 0xFEF8, 0xFFF8, 0x00F8, 0x01F8, 0x02F8, 0x03F8, + 0x04F8, 0x05F8, 0x06F8, 0x07F8, 0x08F8, 0x09F8, 0x0AF8, 0xF6F9, + 0xF7F9, 0xF8F9, 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, + 0xFFF9, 0x00F9, 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, + 0x07F9, 0x08F9, 0x09F9, 0x0AF9, 0xF6FA, 0xF7FA, 0xF8FA, 0xF9FA, + 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, + 0x02FA, 0x03FA, 0x04FA, 0x05FA, 0x06FA, 0x07FA, 0x08FA, 0x09FA, + 0x0AFA, 0xF6FB, 0xF7FB, 0xF8FB, 0xF9FB, 0xFAFB, 0xFBFB, 0xFCFB, + 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, 0x03FB, 0x04FB, + 0x05FB, 0x06FB, 0x07FB, 0x08FB, 0x09FB, 0x0AFB, 0xF6FC, 0xF7FC, + 0xF8FC, 0xF9FC, 0xFAFC, 0xFBFC, 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, + 0x00FC, 0x01FC, 0x02FC, 0x03FC, 0x04FC, 0x05FC, 0x06FC, 0x07FC, + 0x08FC, 0x09FC, 0x0AFC, 0xF6FD, 0xF7FD, 0xF8FD, 0xF9FD, 0xFAFD, + 0xFBFD, 0xFCFD, 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, + 0x03FD, 0x04FD, 0x05FD, 0x06FD, 0x07FD, 0x08FD, 0x09FD, 0x0AFD, + 0xF6FE, 0xF7FE, 0xF8FE, 0xF9FE, 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, + 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, 0x02FE, 0x03FE, 0x04FE, 0x05FE, + 0x06FE, 0x07FE, 0x08FE, 0x09FE, 0x0AFE, 0xF6FF, 0xF7FF, 0xF8FF, + 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, 0xFFFF, 0x00FF, + 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, 0x07FF, 0x08FF, + 0x09FF, 0x0AFF, 0xF600, 0xF700, 0xF800, 0xF900, 0xFA00, 0xFB00, + 0xFC00, 0xFD00, 0xFE00, 0xFF00, 0x0000, 0x0100, 0x0200, 0x0300, + 0x0400, 0x0500, 0x0600, 0x0700, 0x0800, 0x0900, 0x0A00, 0xF601, + 0xF701, 0xF801, 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, + 0xFF01, 0x0001, 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, + 0x0701, 0x0801, 0x0901, 0x0A01, 0xF602, 0xF702, 0xF802, 0xF902, + 0xFA02, 0xFB02, 0xFC02, 0xFD02, 0xFE02, 0xFF02, 0x0002, 0x0102, + 0x0202, 0x0302, 0x0402, 0x0502, 0x0602, 0x0702, 0x0802, 0x0902, + 0x0A02, 0xF603, 0xF703, 0xF803, 0xF903, 0xFA03, 0xFB03, 0xFC03, + 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, 0x0303, 0x0403, + 0x0503, 0x0603, 0x0703, 0x0803, 0x0903, 0x0A03, 0xF604, 0xF704, + 0xF804, 0xF904, 0xFA04, 0xFB04, 0xFC04, 0xFD04, 0xFE04, 0xFF04, + 0x0004, 0x0104, 0x0204, 0x0304, 0x0404, 0x0504, 0x0604, 0x0704, + 0x0804, 0x0904, 0x0A04, 0xF605, 0xF705, 0xF805, 0xF905, 0xFA05, + 0xFB05, 0xFC05, 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, + 0x0305, 0x0405, 0x0505, 0x0605, 0x0705, 0x0805, 0x0905, 0x0A05, + 0xF606, 0xF706, 0xF806, 0xF906, 0xFA06, 0xFB06, 0xFC06, 0xFD06, + 0xFE06, 0xFF06, 0x0006, 0x0106, 0x0206, 0x0306, 0x0406, 0x0506, + 0x0606, 0x0706, 0x0806, 0x0906, 0x0A06, 0xF607, 0xF707, 0xF807, + 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, 0xFF07, 0x0007, + 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, 0x0707, 0x0807, + 0x0907, 0x0A07, 0xF608, 0xF708, 0xF808, 0xF908, 0xFA08, 0xFB08, + 0xFC08, 0xFD08, 0xFE08, 0xFF08, 0x0008, 0x0108, 0x0208, 0x0308, + 0x0408, 0x0508, 0x0608, 0x0708, 0x0808, 0x0908, 0x0A08, 0xF609, + 0xF709, 0xF809, 0xF909, 0xFA09, 0xFB09, 0xFC09, 0xFD09, 0xFE09, + 0xFF09, 0x0009, 0x0109, 0x0209, 0x0309, 0x0409, 0x0509, 0x0609, + 0x0709, 0x0809, 0x0909, 0x0A09, 0xF60A, 0xF70A, 0xF80A, 0xF90A, + 0xFA0A, 0xFB0A, 0xFC0A, 0xFD0A, 0xFE0A, 0xFF0A, 0x000A, 0x010A, + 0x020A, 0x030A, 0x040A, 0x050A, 0x060A, 0x070A, 0x080A, 0x090A, + 0x0A0A, 0x0B0B, +}; + +static const uint8_t clv_mvv_1_bits[] = { + 16, 15, 13, 13, 13, 12, 10, 10, 10, 12, 13, 13, 13, 15, 16, 16, + 15, 14, 13, 12, 11, 10, 9, 10, 11, 12, 13, 14, 15, 16, 15, 14, + 13, 13, 11, 10, 10, 5, 10, 10, 11, 13, 13, 14, 15, 12, 12, 12, + 11, 10, 10, 9, 5, 9, 10, 10, 11, 12, 12, 12, 14, 12, 12, 12, + 11, 9, 8, 5, 8, 9, 11, 12, 12, 12, 14, 14, 11, 11, 9, 9, + 9, 7, 5, 7, 9, 9, 9, 11, 11, 14, 13, 12, 11, 10, 10, 8, + 6, 3, 6, 8, 10, 10, 11, 12, 13, 11, 10, 9, 7, 6, 6, 4, + 4, 4, 6, 7, 7, 10, 10, 11, 13, 12, 11, 10, 10, 8, 6, 3, + 6, 8, 10, 10, 11, 12, 13, 14, 11, 11, 9, 9, 9, 7, 5, 7, + 9, 9, 9, 11, 11, 14, 14, 12, 12, 12, 11, 9, 8, 5, 8, 9, + 11, 12, 12, 12, 14, 12, 12, 12, 11, 10, 10, 9, 5, 9, 10, 10, + 11, 12, 12, 12, 15, 14, 13, 13, 11, 10, 10, 5, 10, 10, 11, 13, + 13, 14, 15, 16, 15, 14, 13, 12, 11, 10, 9, 10, 11, 12, 13, 14, + 15, 16, 16, 15, 13, 13, 13, 12, 10, 10, 10, 12, 13, 13, 13, 15, + 16, 7, +}; + +static const uint16_t clv_mvv_1_codes[] = { + 0xFFFD, 0x7FF8, 0x1FF2, 0x1FDC, 0x1FDB, 0x0FD2, 0x03D6, 0x03BF, + 0x03D3, 0x0FD0, 0x1FDA, 0x1FDE, 0x1FF0, 0x7FF9, 0xFFFE, 0xFFFA, + 0x7FFB, 0x3FF3, 0x1FE9, 0x0FD6, 0x07CB, 0x03E1, 0x01C8, 0x03E2, + 0x07CC, 0x0FD9, 0x1FE8, 0x3FF6, 0x7FFA, 0xFFF9, 0x7FF1, 0x3FEE, + 0x1FE4, 0x1FE0, 0x07D4, 0x03DB, 0x03CB, 0x0014, 0x03CC, 0x03DC, + 0x07D6, 0x1FE3, 0x1FE7, 0x3FEC, 0x7FF3, 0x0FEA, 0x0FE0, 0x0FDE, + 0x07DE, 0x03C9, 0x03C3, 0x01DC, 0x0013, 0x01DD, 0x03C4, 0x03CA, + 0x07DF, 0x0FDF, 0x0FE3, 0x0FEB, 0x3FF1, 0x0FE7, 0x0FCF, 0x0FC8, + 0x07D8, 0x01D2, 0x00E0, 0x0010, 0x00E1, 0x01D4, 0x07D9, 0x0FC9, + 0x0FCC, 0x0FE6, 0x3FF5, 0x3FEA, 0x07E2, 0x07D2, 0x01D7, 0x01D0, + 0x01CC, 0x006A, 0x000F, 0x006B, 0x01CD, 0x01D1, 0x01D9, 0x07D3, + 0x07E3, 0x3FEB, 0x1FEE, 0x0FD5, 0x07C7, 0x03D8, 0x03D0, 0x00DD, + 0x002D, 0x0001, 0x002E, 0x00DE, 0x03D1, 0x03D9, 0x07C8, 0x0FD8, + 0x1FEF, 0x07CE, 0x03C5, 0x01DE, 0x006C, 0x0032, 0x0030, 0x0005, + 0x0004, 0x0006, 0x0031, 0x0066, 0x006D, 0x03BE, 0x03C6, 0x07CF, + 0x1FEC, 0x0FDA, 0x07C9, 0x03DA, 0x03D2, 0x00DF, 0x002F, 0x0000, + 0x002C, 0x00DC, 0x03CF, 0x03D7, 0x07C6, 0x0FD4, 0x1FED, 0x3FE9, + 0x07E0, 0x07D0, 0x01D3, 0x01CE, 0x01CA, 0x0068, 0x000E, 0x0069, + 0x01CB, 0x01CF, 0x01D5, 0x07D1, 0x07E1, 0x3FE8, 0x3FF4, 0x0FE4, + 0x0FCD, 0x0FCB, 0x07DA, 0x01D6, 0x00E2, 0x0011, 0x00E3, 0x01D8, + 0x07DB, 0x0FCA, 0x0FCE, 0x0FE5, 0x3FF7, 0x0FE8, 0x0FE1, 0x0FDD, + 0x07DD, 0x03C7, 0x03C1, 0x01DA, 0x0012, 0x01DB, 0x03C2, 0x03C8, + 0x07DC, 0x0FDC, 0x0FE2, 0x0FE9, 0x7FF0, 0x3FEF, 0x1FE5, 0x1FE1, + 0x07D7, 0x03DD, 0x03CD, 0x0015, 0x03CE, 0x03DE, 0x07D5, 0x1FE2, + 0x1FE6, 0x3FED, 0x7FF2, 0xFFF8, 0x7FF4, 0x3FF2, 0x1FEB, 0x0FD7, + 0x07CD, 0x03DF, 0x01C9, 0x03E0, 0x07CA, 0x0FDB, 0x1FEA, 0x3FF0, + 0x7FF5, 0xFFFB, 0xFFFC, 0x7FF6, 0x1FF3, 0x1FDD, 0x1FD9, 0x0FD1, + 0x03D5, 0x03C0, 0x03D4, 0x0FD3, 0x1FD8, 0x1FDF, 0x1FF1, 0x7FF7, + 0xFFFF, 0x0067, +}; + +static const uint16_t clv_mvv_1_syms[] = { + 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, 0xFFF9, 0x00F9, + 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, 0x07F9, 0xF9FA, + 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, + 0x02FA, 0x03FA, 0x04FA, 0x05FA, 0x06FA, 0x07FA, 0xF9FB, 0xFAFB, + 0xFBFB, 0xFCFB, 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, + 0x03FB, 0x04FB, 0x05FB, 0x06FB, 0x07FB, 0xF9FC, 0xFAFC, 0xFBFC, + 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, 0x00FC, 0x01FC, 0x02FC, 0x03FC, + 0x04FC, 0x05FC, 0x06FC, 0x07FC, 0xF9FD, 0xFAFD, 0xFBFD, 0xFCFD, + 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, 0x03FD, 0x04FD, + 0x05FD, 0x06FD, 0x07FD, 0xF9FE, 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, + 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, 0x02FE, 0x03FE, 0x04FE, 0x05FE, + 0x06FE, 0x07FE, 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, + 0xFFFF, 0x00FF, 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, + 0x07FF, 0xF900, 0xFA00, 0xFB00, 0xFC00, 0xFD00, 0xFE00, 0xFF00, + 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, + 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, 0xFF01, 0x0001, + 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, 0x0701, 0xF902, + 0xFA02, 0xFB02, 0xFC02, 0xFD02, 0xFE02, 0xFF02, 0x0002, 0x0102, + 0x0202, 0x0302, 0x0402, 0x0502, 0x0602, 0x0702, 0xF903, 0xFA03, + 0xFB03, 0xFC03, 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, + 0x0303, 0x0403, 0x0503, 0x0603, 0x0703, 0xF904, 0xFA04, 0xFB04, + 0xFC04, 0xFD04, 0xFE04, 0xFF04, 0x0004, 0x0104, 0x0204, 0x0304, + 0x0404, 0x0504, 0x0604, 0x0704, 0xF905, 0xFA05, 0xFB05, 0xFC05, + 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, 0x0305, 0x0405, + 0x0505, 0x0605, 0x0705, 0xF906, 0xFA06, 0xFB06, 0xFC06, 0xFD06, + 0xFE06, 0xFF06, 0x0006, 0x0106, 0x0206, 0x0306, 0x0406, 0x0506, + 0x0606, 0x0706, 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, + 0xFF07, 0x0007, 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, + 0x0707, 0x0808, +}; + +static const uint8_t clv_mvv_2_bits[] = { + 16, 15, 15, 15, 15, 15, 14, 14, 14, 13, 12, 13, 14, 14, 14, 15, + 15, 15, 15, 15, 16, 16, 16, 16, 15, 15, 14, 14, 14, 13, 13, 12, + 12, 13, 14, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 14, 14, 14, + 14, 14, 14, 13, 13, 13, 14, 14, 14, 14, 14, 14, 16, 16, 16, 15, + 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, 13, 13, 13, 13, 14, + 14, 14, 15, 15, 16, 14, 14, 14, 13, 12, 12, 12, 10, 10, 10, 10, + 10, 12, 12, 12, 13, 14, 14, 14, 16, 14, 14, 14, 13, 13, 12, 12, + 12, 10, 10, 7, 10, 10, 12, 12, 12, 13, 13, 14, 14, 14, 14, 14, + 13, 12, 12, 12, 12, 10, 9, 8, 7, 8, 9, 10, 12, 12, 12, 12, + 13, 14, 14, 14, 14, 13, 12, 12, 12, 12, 10, 9, 8, 7, 8, 9, + 10, 12, 12, 12, 12, 13, 14, 14, 14, 14, 13, 13, 12, 12, 11, 10, + 9, 8, 7, 8, 9, 10, 11, 12, 12, 13, 13, 14, 14, 14, 13, 13, + 12, 10, 10, 9, 8, 7, 6, 5, 6, 7, 8, 9, 10, 10, 12, 13, + 13, 14, 13, 13, 13, 13, 11, 10, 9, 8, 7, 5, 1, 5, 7, 8, + 9, 10, 11, 13, 13, 13, 13, 14, 13, 13, 12, 10, 10, 9, 8, 7, + 6, 5, 6, 7, 8, 9, 10, 10, 12, 13, 13, 14, 14, 14, 13, 13, + 12, 12, 11, 9, 9, 8, 7, 8, 9, 9, 11, 12, 12, 13, 13, 14, + 14, 14, 14, 13, 12, 12, 12, 12, 10, 9, 8, 7, 8, 9, 10, 12, + 12, 12, 12, 13, 14, 14, 14, 14, 13, 12, 12, 12, 12, 10, 9, 8, + 7, 8, 9, 10, 12, 12, 12, 12, 13, 14, 14, 14, 14, 14, 13, 13, + 12, 12, 12, 10, 10, 7, 10, 10, 12, 12, 12, 13, 13, 14, 14, 14, + 16, 14, 14, 14, 13, 12, 12, 12, 10, 10, 10, 10, 10, 12, 12, 12, + 13, 14, 14, 14, 16, 15, 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, + 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16, 16, 14, 14, 14, + 14, 14, 14, 13, 13, 13, 14, 14, 14, 14, 14, 14, 16, 16, 16, 16, + 16, 16, 15, 15, 14, 14, 14, 13, 12, 12, 12, 13, 14, 14, 14, 15, + 15, 16, 16, 16, 16, 15, 15, 15, 15, 15, 14, 14, 14, 13, 10, 13, + 14, 14, 14, 15, 15, 15, 15, 15, 16, 6, +}; + +static const uint16_t clv_mvv_2_codes[] = { + 0xFFFF, 0x7FE7, 0x7FD9, 0x7FE6, 0x7FE5, 0x7FCE, 0x3FD6, 0x3FD3, + 0x3F9C, 0x1FB2, 0x0F7A, 0x1FB5, 0x3FA8, 0x3FDD, 0x3FE5, 0x7FD0, + 0x7FEA, 0x7FEC, 0x7FEF, 0x7FDB, 0xFFF3, 0xFFF5, 0xFFE2, 0xFFEB, + 0x7FEB, 0x7FE0, 0x3FA7, 0x3F84, 0x3F79, 0x1FAE, 0x1F70, 0x0F78, + 0x0FAA, 0x1FAA, 0x3F76, 0x3F7E, 0x3FAC, 0x7FE1, 0x7FDD, 0xFFEC, + 0xFFEE, 0xFFF8, 0xFFF9, 0xFFEA, 0xFFE4, 0x3FE1, 0x3FBA, 0x3FC5, + 0x3FB9, 0x3FA1, 0x3FAA, 0x1F8B, 0x1F8D, 0x1F8E, 0x3FA6, 0x3FA9, + 0x3FC4, 0x3FBC, 0x3FC6, 0x3FDB, 0xFFE3, 0xFFE1, 0xFFFB, 0x7FD4, + 0x7FCC, 0x3FCD, 0x3F88, 0x3F7C, 0x1FA1, 0x1FA2, 0x1F95, 0x1F77, + 0x0F95, 0x0F79, 0x0F97, 0x1F78, 0x1F96, 0x1FA3, 0x1FA4, 0x3F7F, + 0x3F8B, 0x3FCB, 0x7FCF, 0x7FD5, 0xFFF6, 0x3FD7, 0x3FE0, 0x3F91, + 0x1F7B, 0x0FB4, 0x0FA5, 0x0FA6, 0x03D5, 0x03CB, 0x03BF, 0x03CC, + 0x03D6, 0x0FA7, 0x0FA8, 0x0FB5, 0x1F7D, 0x3F87, 0x3FD2, 0x3FDF, + 0xFFF0, 0x3F95, 0x3F8A, 0x3F96, 0x1FB7, 0x1F9F, 0x0F9F, 0x0F8F, + 0x0F76, 0x03D1, 0x03BC, 0x0067, 0x03BD, 0x03D2, 0x0F77, 0x0F90, + 0x0FA0, 0x1FA0, 0x1FB9, 0x3F97, 0x3F98, 0x3F99, 0x3FC3, 0x3FAF, + 0x1F81, 0x0FA9, 0x0F91, 0x0F7E, 0x0F68, 0x03B2, 0x01C6, 0x00D4, + 0x0062, 0x00D5, 0x01C7, 0x03B3, 0x0F6A, 0x0F81, 0x0F93, 0x0FAC, + 0x1F83, 0x3FB3, 0x3FB4, 0x3FC7, 0x3FBB, 0x1F86, 0x0FAF, 0x0F98, + 0x0F84, 0x0F6D, 0x03B8, 0x01CC, 0x00DA, 0x0065, 0x00DB, 0x01CD, + 0x03B9, 0x0F6F, 0x0F86, 0x0F9B, 0x0FB1, 0x1F88, 0x3FB8, 0x3FC9, + 0x3FDC, 0x3F80, 0x1FB3, 0x1F93, 0x0F87, 0x0F72, 0x07B0, 0x03B0, + 0x01D4, 0x00E0, 0x0061, 0x00E1, 0x01D5, 0x03B1, 0x07B1, 0x0F73, + 0x0F88, 0x1F94, 0x1FB4, 0x3F81, 0x3FD4, 0x3F9E, 0x1F99, 0x1F73, + 0x0F89, 0x03C4, 0x03C0, 0x01CE, 0x00D0, 0x005C, 0x0028, 0x0010, + 0x0029, 0x005D, 0x00D1, 0x01CF, 0x03C1, 0x03C5, 0x0F8A, 0x1F74, + 0x1F9A, 0x3FA4, 0x1FAC, 0x1F8C, 0x1F7E, 0x1F71, 0x07B2, 0x03CF, + 0x01C4, 0x00DC, 0x005A, 0x0012, 0x0000, 0x0013, 0x005B, 0x00DD, + 0x01C5, 0x03D0, 0x07B3, 0x1F72, 0x1F7F, 0x1F8F, 0x1FAD, 0x3FAB, + 0x1F9B, 0x1F75, 0x0F8B, 0x03C6, 0x03C2, 0x01D0, 0x00D2, 0x005E, + 0x002A, 0x0011, 0x002B, 0x005F, 0x00D3, 0x01D1, 0x03C3, 0x03C7, + 0x0F8C, 0x1F76, 0x1F9C, 0x3FAD, 0x3FCF, 0x3F85, 0x1FBA, 0x1F91, + 0x0F7D, 0x0F70, 0x07AE, 0x01D6, 0x01D2, 0x00DE, 0x0060, 0x00DF, + 0x01D3, 0x01D7, 0x07AF, 0x0F71, 0x0F7F, 0x1F92, 0x1FAF, 0x3F7B, + 0x3FD0, 0x3FC0, 0x3FB1, 0x1F82, 0x0FAB, 0x0F92, 0x0F80, 0x0F69, + 0x03B4, 0x01C8, 0x00D6, 0x0063, 0x00D7, 0x01C9, 0x03B5, 0x0F6B, + 0x0F82, 0x0F94, 0x0FAD, 0x1F84, 0x3FB5, 0x3FC2, 0x3FB6, 0x3FBF, + 0x1F85, 0x0FAE, 0x0F96, 0x0F83, 0x0F6C, 0x03B6, 0x01CA, 0x00D8, + 0x0064, 0x00D9, 0x01CB, 0x03B7, 0x0F6E, 0x0F85, 0x0F99, 0x0FB0, + 0x1F87, 0x3FB0, 0x3FB2, 0x3F93, 0x3F86, 0x3F8E, 0x1FB1, 0x1F9D, + 0x0F9A, 0x0F8D, 0x0F74, 0x03CD, 0x03BA, 0x0066, 0x03BB, 0x03CE, + 0x0F75, 0x0F8E, 0x0F9C, 0x1F9E, 0x1FB0, 0x3F8C, 0x3F94, 0x3F8D, + 0xFFFC, 0x3FCA, 0x3FD5, 0x3F8F, 0x1F79, 0x0FB2, 0x0FA1, 0x0FA2, + 0x03D3, 0x03C9, 0x03BE, 0x03CA, 0x03D4, 0x0FA3, 0x0FA4, 0x0FB3, + 0x1F7A, 0x3F90, 0x3FE3, 0x3FD8, 0xFFF2, 0x7FD7, 0x7FCD, 0x3FE4, + 0x3F92, 0x3F82, 0x1FA6, 0x1FA8, 0x1F98, 0x1F7C, 0x0F9D, 0x0F7B, + 0x0F9E, 0x1F80, 0x1F97, 0x1FA7, 0x1FA5, 0x3F7A, 0x3F89, 0x3FDA, + 0x7FD2, 0x7FD6, 0xFFFE, 0xFFED, 0xFFE8, 0x3FCC, 0x3FBD, 0x3FAE, + 0x3FC1, 0x3F9F, 0x3F9A, 0x1F89, 0x1F90, 0x1F8A, 0x3FA3, 0x3FA0, + 0x3FC8, 0x3FBE, 0x3FB7, 0x3FD1, 0xFFE7, 0xFFE9, 0xFFFD, 0xFFF4, + 0xFFE5, 0xFFEF, 0x7FD8, 0x7FDC, 0x3FA2, 0x3F83, 0x3F78, 0x1FA9, + 0x0FB6, 0x0F7C, 0x0FB7, 0x1FAB, 0x3F77, 0x3F7D, 0x3F9B, 0x7FDE, + 0x7FED, 0xFFE6, 0xFFE0, 0xFFF7, 0xFFF1, 0x7FDA, 0x7FE9, 0x7FE2, + 0x7FE3, 0x7FD1, 0x3FD9, 0x3FE2, 0x3FA5, 0x1FB8, 0x03C8, 0x1FB6, + 0x3F9D, 0x3FDE, 0x3FCE, 0x7FD3, 0x7FEE, 0x7FDF, 0x7FE8, 0x7FE4, + 0xFFFA, 0x002C, +}; + +static const uint16_t clv_mvv_2_syms[] = { + 0xF6F6, 0xF7F6, 0xF8F6, 0xF9F6, 0xFAF6, 0xFBF6, 0xFCF6, 0xFDF6, + 0xFEF6, 0xFFF6, 0x00F6, 0x01F6, 0x02F6, 0x03F6, 0x04F6, 0x05F6, + 0x06F6, 0x07F6, 0x08F6, 0x09F6, 0x0AF6, 0xF6F7, 0xF7F7, 0xF8F7, + 0xF9F7, 0xFAF7, 0xFBF7, 0xFCF7, 0xFDF7, 0xFEF7, 0xFFF7, 0x00F7, + 0x01F7, 0x02F7, 0x03F7, 0x04F7, 0x05F7, 0x06F7, 0x07F7, 0x08F7, + 0x09F7, 0x0AF7, 0xF6F8, 0xF7F8, 0xF8F8, 0xF9F8, 0xFAF8, 0xFBF8, + 0xFCF8, 0xFDF8, 0xFEF8, 0xFFF8, 0x00F8, 0x01F8, 0x02F8, 0x03F8, + 0x04F8, 0x05F8, 0x06F8, 0x07F8, 0x08F8, 0x09F8, 0x0AF8, 0xF6F9, + 0xF7F9, 0xF8F9, 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, + 0xFFF9, 0x00F9, 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, + 0x07F9, 0x08F9, 0x09F9, 0x0AF9, 0xF6FA, 0xF7FA, 0xF8FA, 0xF9FA, + 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, + 0x02FA, 0x03FA, 0x04FA, 0x05FA, 0x06FA, 0x07FA, 0x08FA, 0x09FA, + 0x0AFA, 0xF6FB, 0xF7FB, 0xF8FB, 0xF9FB, 0xFAFB, 0xFBFB, 0xFCFB, + 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, 0x03FB, 0x04FB, + 0x05FB, 0x06FB, 0x07FB, 0x08FB, 0x09FB, 0x0AFB, 0xF6FC, 0xF7FC, + 0xF8FC, 0xF9FC, 0xFAFC, 0xFBFC, 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, + 0x00FC, 0x01FC, 0x02FC, 0x03FC, 0x04FC, 0x05FC, 0x06FC, 0x07FC, + 0x08FC, 0x09FC, 0x0AFC, 0xF6FD, 0xF7FD, 0xF8FD, 0xF9FD, 0xFAFD, + 0xFBFD, 0xFCFD, 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, + 0x03FD, 0x04FD, 0x05FD, 0x06FD, 0x07FD, 0x08FD, 0x09FD, 0x0AFD, + 0xF6FE, 0xF7FE, 0xF8FE, 0xF9FE, 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, + 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, 0x02FE, 0x03FE, 0x04FE, 0x05FE, + 0x06FE, 0x07FE, 0x08FE, 0x09FE, 0x0AFE, 0xF6FF, 0xF7FF, 0xF8FF, + 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, 0xFFFF, 0x00FF, + 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, 0x07FF, 0x08FF, + 0x09FF, 0x0AFF, 0xF600, 0xF700, 0xF800, 0xF900, 0xFA00, 0xFB00, + 0xFC00, 0xFD00, 0xFE00, 0xFF00, 0x0000, 0x0100, 0x0200, 0x0300, + 0x0400, 0x0500, 0x0600, 0x0700, 0x0800, 0x0900, 0x0A00, 0xF601, + 0xF701, 0xF801, 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, + 0xFF01, 0x0001, 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, + 0x0701, 0x0801, 0x0901, 0x0A01, 0xF602, 0xF702, 0xF802, 0xF902, + 0xFA02, 0xFB02, 0xFC02, 0xFD02, 0xFE02, 0xFF02, 0x0002, 0x0102, + 0x0202, 0x0302, 0x0402, 0x0502, 0x0602, 0x0702, 0x0802, 0x0902, + 0x0A02, 0xF603, 0xF703, 0xF803, 0xF903, 0xFA03, 0xFB03, 0xFC03, + 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, 0x0303, 0x0403, + 0x0503, 0x0603, 0x0703, 0x0803, 0x0903, 0x0A03, 0xF604, 0xF704, + 0xF804, 0xF904, 0xFA04, 0xFB04, 0xFC04, 0xFD04, 0xFE04, 0xFF04, + 0x0004, 0x0104, 0x0204, 0x0304, 0x0404, 0x0504, 0x0604, 0x0704, + 0x0804, 0x0904, 0x0A04, 0xF605, 0xF705, 0xF805, 0xF905, 0xFA05, + 0xFB05, 0xFC05, 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, + 0x0305, 0x0405, 0x0505, 0x0605, 0x0705, 0x0805, 0x0905, 0x0A05, + 0xF606, 0xF706, 0xF806, 0xF906, 0xFA06, 0xFB06, 0xFC06, 0xFD06, + 0xFE06, 0xFF06, 0x0006, 0x0106, 0x0206, 0x0306, 0x0406, 0x0506, + 0x0606, 0x0706, 0x0806, 0x0906, 0x0A06, 0xF607, 0xF707, 0xF807, + 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, 0xFF07, 0x0007, + 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, 0x0707, 0x0807, + 0x0907, 0x0A07, 0xF608, 0xF708, 0xF808, 0xF908, 0xFA08, 0xFB08, + 0xFC08, 0xFD08, 0xFE08, 0xFF08, 0x0008, 0x0108, 0x0208, 0x0308, + 0x0408, 0x0508, 0x0608, 0x0708, 0x0808, 0x0908, 0x0A08, 0xF609, + 0xF709, 0xF809, 0xF909, 0xFA09, 0xFB09, 0xFC09, 0xFD09, 0xFE09, + 0xFF09, 0x0009, 0x0109, 0x0209, 0x0309, 0x0409, 0x0509, 0x0609, + 0x0709, 0x0809, 0x0909, 0x0A09, 0xF60A, 0xF70A, 0xF80A, 0xF90A, + 0xFA0A, 0xFB0A, 0xFC0A, 0xFD0A, 0xFE0A, 0xFF0A, 0x000A, 0x010A, + 0x020A, 0x030A, 0x040A, 0x050A, 0x060A, 0x070A, 0x080A, 0x090A, + 0x0A0A, 0x0B0B, +}; + +static const uint8_t clv_biasy_1_bits[] = { + 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, 13, + 13, 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, + 8, 8, 7, 7, 5, 2, 1, 3, 5, 7, 7, 8, 9, 9, 10, 10, + 10, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 16, 12, +}; + +static const uint16_t clv_biasy_1_codes[] = { + 0xFFFE, 0x7FFE, 0x7FFC, 0x7FFA, 0x7FF6, 0x7FF7, 0x7FF3, 0x7FF2, + 0x7FEF, 0x7FEE, 0x3FF5, 0x3FF3, 0x3FF1, 0x1FF7, 0x1FF5, 0x1FF2, + 0x1FF0, 0x1FEE, 0x1FEC, 0x1FEA, 0x1FE8, 0x0FF2, 0x0FF0, 0x0FEE, + 0x0FEB, 0x07F4, 0x07F3, 0x07F1, 0x03F7, 0x03F5, 0x03F3, 0x01F7, + 0x00FA, 0x00F8, 0x007A, 0x0078, 0x001C, 0x0002, 0x0000, 0x0006, + 0x001D, 0x0079, 0x007B, 0x00F9, 0x01F6, 0x01F8, 0x03F2, 0x03F4, + 0x03F6, 0x07F0, 0x07F2, 0x0FEA, 0x0FEC, 0x0FEF, 0x0FF1, 0x0FF3, + 0x1FE9, 0x1FEB, 0x1FED, 0x1FEF, 0x1FF1, 0x1FF3, 0x1FF4, 0x1FF6, + 0x3FF0, 0x3FF2, 0x3FF4, 0x3FF6, 0x7FF0, 0x7FF1, 0x7FF4, 0x7FF8, + 0x7FF5, 0x7FF9, 0x7FFB, 0x7FFD, 0xFFFF, 0x0FED, +}; + +static const uint16_t clv_biasy_1_syms[] = { + 0xFF68, 0xFF6C, 0xFF70, 0xFF74, 0xFF78, 0xFF7C, 0xFF80, 0xFF84, + 0xFF88, 0xFF8C, 0xFF90, 0xFF94, 0xFF98, 0xFF9C, 0xFFA0, 0xFFA4, + 0xFFA8, 0xFFAC, 0xFFB0, 0xFFB4, 0xFFB8, 0xFFBC, 0xFFC0, 0xFFC4, + 0xFFC8, 0xFFCC, 0xFFD0, 0xFFD4, 0xFFD8, 0xFFDC, 0xFFE0, 0xFFE4, + 0xFFE8, 0xFFEC, 0xFFF0, 0xFFF4, 0xFFF8, 0xFFFC, 0x0000, 0x0004, + 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C, 0x0020, 0x0024, + 0x0028, 0x002C, 0x0030, 0x0034, 0x0038, 0x003C, 0x0040, 0x0044, + 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, 0x0060, 0x0064, + 0x0068, 0x006C, 0x0070, 0x0074, 0x0078, 0x007C, 0x0080, 0x0084, + 0x0088, 0x008C, 0x0090, 0x0094, 0x0098, 0x0100, +}; + +static const uint8_t clv_biasy_2_bits[] = { + 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 14, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, 12, 12, 11, + 11, 11, 10, 10, 10, 10, 9, 9, 8, 8, 8, 7, 6, 6, 4, 3, + 1, 3, 4, 6, 6, 7, 8, 8, 8, 9, 9, 10, 10, 10, 10, 11, + 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, + 16, 15, +}; + +static const uint16_t clv_biasy_2_codes[] = { + 0xFFFE, 0xFFFC, 0xFFFA, 0xFFF9, 0xFFF6, 0xFFF5, 0xFFF3, 0x7FF7, + 0x7FF5, 0x7FF1, 0x7FF3, 0x7FF0, 0x7FEE, 0x7FEC, 0x7FE9, 0x7FE6, + 0x7FE4, 0x7FE2, 0x3FEF, 0x3FEE, 0x3FEC, 0x3FEA, 0x1FF2, 0x1FF1, + 0x1FEF, 0x1FED, 0x0FF4, 0x0FF3, 0x0FF1, 0x0FEF, 0x0FED, 0x07F4, + 0x07F3, 0x07F1, 0x03F6, 0x03F4, 0x03F2, 0x03F0, 0x01F6, 0x01F4, + 0x00F8, 0x00F6, 0x00F4, 0x0078, 0x003A, 0x0038, 0x000C, 0x0004, + 0x0000, 0x0005, 0x000D, 0x0039, 0x003B, 0x0079, 0x00F5, 0x00F7, + 0x00F9, 0x01F5, 0x01F7, 0x03F1, 0x03F3, 0x03F5, 0x03F7, 0x07F0, + 0x07F2, 0x07F5, 0x0FEC, 0x0FEE, 0x0FF0, 0x0FF2, 0x0FF5, 0x1FEC, + 0x1FEE, 0x1FF0, 0x1FF3, 0x1FF4, 0x3FEB, 0x3FED, 0x3FF0, 0x7FE3, + 0x7FE5, 0x7FE7, 0x7FEA, 0x7FEB, 0x7FED, 0x7FEF, 0x7FF4, 0x7FF2, + 0x7FF6, 0x7FF8, 0xFFF2, 0xFFF4, 0xFFF7, 0xFFF8, 0xFFFB, 0xFFFD, + 0xFFFF, 0x7FE8, +}; + +static const uint16_t clv_biasy_2_syms[] = { + 0xFF40, 0xFF44, 0xFF48, 0xFF4C, 0xFF50, 0xFF54, 0xFF58, 0xFF5C, + 0xFF60, 0xFF64, 0xFF68, 0xFF6C, 0xFF70, 0xFF74, 0xFF78, 0xFF7C, + 0xFF80, 0xFF84, 0xFF88, 0xFF8C, 0xFF90, 0xFF94, 0xFF98, 0xFF9C, + 0xFFA0, 0xFFA4, 0xFFA8, 0xFFAC, 0xFFB0, 0xFFB4, 0xFFB8, 0xFFBC, + 0xFFC0, 0xFFC4, 0xFFC8, 0xFFCC, 0xFFD0, 0xFFD4, 0xFFD8, 0xFFDC, + 0xFFE0, 0xFFE4, 0xFFE8, 0xFFEC, 0xFFF0, 0xFFF4, 0xFFF8, 0xFFFC, + 0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C, + 0x0020, 0x0024, 0x0028, 0x002C, 0x0030, 0x0034, 0x0038, 0x003C, + 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, + 0x0060, 0x0064, 0x0068, 0x006C, 0x0070, 0x0074, 0x0078, 0x007C, + 0x0080, 0x0084, 0x0088, 0x008C, 0x0090, 0x0094, 0x0098, 0x009C, + 0x00A0, 0x00A4, 0x00A8, 0x00AC, 0x00B0, 0x00B4, 0x00B8, 0x00BC, + 0x00C0, 0x0100, +}; + +static const uint8_t clv_biasy_3_bits[] = { + 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, + 14, 14, 13, 13, 13, 13, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, + 10, 9, 9, 9, 9, 8, 8, 7, 7, 6, 5, 4, 4, 2, 2, 3, + 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, + 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 15, +}; + +static const uint16_t clv_biasy_3_codes[] = { + 0xFFFF, 0xFFFC, 0xFFFA, 0x7FFC, 0x7FF9, 0x7FF6, 0x7FF4, 0x7FF2, + 0x7FF1, 0x7FEF, 0x7FEC, 0x7FEB, 0x7FE9, 0x3FF3, 0x3FF0, 0x3FEE, + 0x3FED, 0x3FEA, 0x1FF3, 0x1FF2, 0x1FF0, 0x1FEE, 0x0FF4, 0x0FF3, + 0x0FF1, 0x07F7, 0x07F5, 0x07F3, 0x07F1, 0x03F7, 0x03F4, 0x03F2, + 0x03F0, 0x01F6, 0x01F4, 0x01F2, 0x01F0, 0x00F6, 0x00F4, 0x0078, + 0x0076, 0x0039, 0x001B, 0x000C, 0x000A, 0x0001, 0x0000, 0x0004, + 0x000B, 0x001A, 0x0038, 0x003A, 0x0077, 0x0079, 0x00F5, 0x00F7, + 0x01F1, 0x01F3, 0x01F5, 0x01F7, 0x03F1, 0x03F3, 0x03F5, 0x03F6, + 0x07F0, 0x07F2, 0x07F4, 0x07F6, 0x0FF0, 0x0FF2, 0x0FF5, 0x0FF6, + 0x1FEF, 0x1FF1, 0x1FF4, 0x3FEB, 0x3FEC, 0x3FEF, 0x3FF1, 0x3FF2, + 0x7FE8, 0x7FEA, 0x7FED, 0x7FEE, 0x7FF0, 0x7FF3, 0x7FF5, 0x7FF7, + 0x7FFA, 0x7FFB, 0xFFFB, 0xFFFD, 0xFFFE, 0x7FF8, +}; + +static const uint16_t clv_biasy_3_syms[] = { + 0xFF48, 0xFF4C, 0xFF50, 0xFF54, 0xFF58, 0xFF5C, 0xFF60, 0xFF64, + 0xFF68, 0xFF6C, 0xFF70, 0xFF74, 0xFF78, 0xFF7C, 0xFF80, 0xFF84, + 0xFF88, 0xFF8C, 0xFF90, 0xFF94, 0xFF98, 0xFF9C, 0xFFA0, 0xFFA4, + 0xFFA8, 0xFFAC, 0xFFB0, 0xFFB4, 0xFFB8, 0xFFBC, 0xFFC0, 0xFFC4, + 0xFFC8, 0xFFCC, 0xFFD0, 0xFFD4, 0xFFD8, 0xFFDC, 0xFFE0, 0xFFE4, + 0xFFE8, 0xFFEC, 0xFFF0, 0xFFF4, 0xFFF8, 0xFFFC, 0x0000, 0x0004, + 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C, 0x0020, 0x0024, + 0x0028, 0x002C, 0x0030, 0x0034, 0x0038, 0x003C, 0x0040, 0x0044, + 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, 0x0060, 0x0064, + 0x0068, 0x006C, 0x0070, 0x0074, 0x0078, 0x007C, 0x0080, 0x0084, + 0x0088, 0x008C, 0x0090, 0x0094, 0x0098, 0x009C, 0x00A0, 0x00A4, + 0x00A8, 0x00AC, 0x00B0, 0x00B4, 0x00B8, 0x0100, +}; + +static const uint8_t clv_biasu_1_bits[] = { + 16, 15, 14, 13, 13, 13, 12, 12, 12, 12, 11, 10, 10, 9, 9, 8, + 7, 6, 5, 2, 1, 3, 5, 7, 7, 8, 9, 9, 10, 10, 11, 12, + 12, 12, 12, 13, 13, 13, 14, 15, 15, 16, +}; + +static const uint16_t clv_biasu_1_codes[] = { + 0xFFFE, 0x7FFC, 0x3FFC, 0x1FFC, 0x1FFA, 0x1FF9, 0x0FFA, 0x0FF7, + 0x0FF8, 0x0FF5, 0x07F8, 0x03FA, 0x03F8, 0x01FA, 0x01F9, 0x00FA, + 0x007B, 0x003C, 0x001C, 0x0002, 0x0000, 0x0006, 0x001D, 0x007A, + 0x007C, 0x00FB, 0x01F8, 0x01FB, 0x03F9, 0x03FB, 0x07F9, 0x0FF4, + 0x0FF6, 0x0FF9, 0x0FFB, 0x1FF8, 0x1FFB, 0x1FFD, 0x3FFD, 0x7FFD, + 0x7FFE, 0xFFFF, +}; + +static const uint16_t clv_biasu_1_syms[] = { + 0xFFB0, 0xFFB4, 0xFFB8, 0xFFBC, 0xFFC0, 0xFFC4, 0xFFC8, 0xFFCC, + 0xFFD0, 0xFFD4, 0xFFD8, 0xFFDC, 0xFFE0, 0xFFE4, 0xFFE8, 0xFFEC, + 0xFFF0, 0xFFF4, 0xFFF8, 0xFFFC, 0x0000, 0x0004, 0x0008, 0x000C, + 0x0010, 0x0014, 0x0018, 0x001C, 0x0020, 0x0024, 0x0028, 0x002C, + 0x0030, 0x0034, 0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, + 0x0050, 0x0100, +}; + +static const uint8_t clv_biasu_2_bits[] = { + 16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 12, 12, 11, 11, 10, + 10, 9, 9, 8, 8, 7, 6, 5, 4, 3, 1, 3, 4, 6, 6, 7, + 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 14, 14, 15, 15, + 15, 16, 16, 16, 16, 14, +}; + +static const uint16_t clv_biasu_2_codes[] = { + 0xFFFC, 0xFFF8, 0xFFFA, 0xFFFD, 0x7FF8, 0x7FFA, 0x7FF7, 0x3FF6, + 0x3FF7, 0x3FF4, 0x1FF9, 0x0FFB, 0x0FF9, 0x07FB, 0x07F9, 0x03FA, + 0x03F8, 0x01FA, 0x01F9, 0x00FB, 0x00F9, 0x007B, 0x003B, 0x001C, + 0x000C, 0x0004, 0x0000, 0x0005, 0x000D, 0x003A, 0x003C, 0x007A, + 0x00F8, 0x00FA, 0x01F8, 0x01FB, 0x03F9, 0x03FB, 0x07F8, 0x07FA, + 0x0FF8, 0x0FFA, 0x1FF8, 0x3FF5, 0x3FF8, 0x3FF9, 0x7FFB, 0x7FF9, + 0x7FF6, 0xFFF9, 0xFFFF, 0xFFFE, 0xFFFB, 0x3FFA, +}; + +static const uint16_t clv_biasu_2_syms[] = { + 0xFF98, 0xFF9C, 0xFFA0, 0xFFA4, 0xFFA8, 0xFFAC, 0xFFB0, 0xFFB4, + 0xFFB8, 0xFFBC, 0xFFC0, 0xFFC4, 0xFFC8, 0xFFCC, 0xFFD0, 0xFFD4, + 0xFFD8, 0xFFDC, 0xFFE0, 0xFFE4, 0xFFE8, 0xFFEC, 0xFFF0, 0xFFF4, + 0xFFF8, 0xFFFC, 0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, + 0x0018, 0x001C, 0x0020, 0x0024, 0x0028, 0x002C, 0x0030, 0x0034, + 0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, + 0x0058, 0x005C, 0x0060, 0x0064, 0x0068, 0x0100, +}; + +static const uint8_t clv_biasv_1_bits[] = { + 16, 15, 14, 14, 14, 13, 13, 13, 12, 12, 11, 11, 10, 10, 9, 8, + 7, 6, 5, 2, 1, 3, 5, 6, 8, 8, 9, 10, 10, 11, 12, 12, + 12, 13, 13, 13, 14, 14, 15, 15, 16, 14, +}; + +static const uint16_t clv_biasv_1_codes[] = { + 0xFFFF, 0x7FFD, 0x3FFD, 0x3FFB, 0x3FF9, 0x1FFB, 0x1FF8, 0x1FF6, + 0x0FFA, 0x0FF8, 0x07FA, 0x07F8, 0x03FA, 0x03F8, 0x01FB, 0x00FB, + 0x007C, 0x003C, 0x001C, 0x0002, 0x0000, 0x0006, 0x001D, 0x003D, + 0x00FA, 0x00FC, 0x01FA, 0x03F9, 0x03FB, 0x07F9, 0x0FF6, 0x0FF7, + 0x0FF9, 0x1FF7, 0x1FF9, 0x1FFA, 0x3FFA, 0x3FFC, 0x7FFC, 0x7FFE, + 0xFFFE, 0x3FF8, +}; + +static const uint16_t clv_biasv_1_syms[] = { + 0xFFB0, 0xFFB4, 0xFFB8, 0xFFBC, 0xFFC0, 0xFFC4, 0xFFC8, 0xFFCC, + 0xFFD0, 0xFFD4, 0xFFD8, 0xFFDC, 0xFFE0, 0xFFE4, 0xFFE8, 0xFFEC, + 0xFFF0, 0xFFF4, 0xFFF8, 0xFFFC, 0x0000, 0x0004, 0x0008, 0x000C, + 0x0010, 0x0014, 0x0018, 0x001C, 0x0020, 0x0024, 0x0028, 0x002C, + 0x0030, 0x0034, 0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, + 0x0050, 0x0100, +}; + +static const uint8_t clv_biasv_2_bits[] = { + 16, 15, 14, 13, 13, 13, 13, 13, 12, 12, 11, 10, 10, 9, 9, 8, + 7, 6, 5, 4, 3, 1, 3, 4, 5, 7, 7, 8, 9, 9, 10, 10, + 10, 12, 12, 13, 13, 13, 13, 13, 14, 16, 15, 15, +}; + +static const uint16_t clv_biasv_2_codes[] = { + 0xFFFE, 0x7FFD, 0x3FFC, 0x1FFC, 0x1FFB, 0x1FF8, 0x1FF7, 0x1FF4, + 0x0FF8, 0x0FF7, 0x07FA, 0x03FB, 0x03F8, 0x01FA, 0x01F9, 0x00FA, + 0x007B, 0x003C, 0x001C, 0x000C, 0x0004, 0x0000, 0x0005, 0x000D, + 0x001D, 0x007A, 0x007C, 0x00FB, 0x01F8, 0x01FB, 0x03F9, 0x03FA, + 0x03FC, 0x0FF6, 0x0FF9, 0x1FF5, 0x1FF9, 0x1FF6, 0x1FFA, 0x1FFD, + 0x3FFD, 0xFFFF, 0x7FFE, 0x7FFC, +}; + +static const uint16_t clv_biasv_2_syms[] = { + 0xFFAC, 0xFFB0, 0xFFB4, 0xFFB8, 0xFFBC, 0xFFC0, 0xFFC4, 0xFFC8, + 0xFFCC, 0xFFD0, 0xFFD4, 0xFFD8, 0xFFDC, 0xFFE0, 0xFFE4, 0xFFE8, + 0xFFEC, 0xFFF0, 0xFFF4, 0xFFF8, 0xFFFC, 0x0000, 0x0004, 0x0008, + 0x000C, 0x0010, 0x0014, 0x0018, 0x001C, 0x0020, 0x0024, 0x0028, + 0x002C, 0x0030, 0x0034, 0x0038, 0x003C, 0x0040, 0x0044, 0x0048, + 0x004C, 0x0050, 0x0054, 0x0100, +}; + + From be3a051ca8fe012e394dfb14f9274b84e0fdd207 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 3 Apr 2018 17:23:36 +0200 Subject: [PATCH 2358/2557] avcodec/sheervideo: move tables to own header Signed-off-by: Paul B Mahol --- libavcodec/sheervideo.c | 1071 +--------------------------------- libavcodec/sheervideodata.h | 1093 +++++++++++++++++++++++++++++++++++ 2 files changed, 1094 insertions(+), 1070 deletions(-) create mode 100644 libavcodec/sheervideodata.h diff --git a/libavcodec/sheervideo.c b/libavcodec/sheervideo.c index 6f99b5c869398..50c3ebcee72a0 100644 --- a/libavcodec/sheervideo.c +++ b/libavcodec/sheervideo.c @@ -28,6 +28,7 @@ #include "get_bits.h" #include "internal.h" #include "thread.h" +#include "sheervideodata.h" typedef struct SheerVideoContext { unsigned format; @@ -36,1076 +37,6 @@ typedef struct SheerVideoContext { void (*decode_frame)(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb); } SheerVideoContext; -static const uint8_t l_r_rgb[256] = { - 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, - 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, - 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 5, 5, 4, 4, 4, -}; - -static const uint8_t l_r_rgbi[256] = { - 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, - 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 4, 4, 4, -}; - -static const uint8_t l_g_rgbi[256] = { - 1, 3, 4, 5, 6, 7, 7, 8, 9, 9, 10, 10, 10, 10, 11, 11, - 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, - 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, - 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, - 11, 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 7, 6, 5, 5, 3, -}; - -static const uint8_t l_g_rgb[256] = { - 2, 2, 4, 4, 6, 7, 9, 9, 10, 11, 11, 11, 12, 12, 12, 13, - 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, - 13, 13, 12, 12, 12, 11, 11, 11, 10, 9, 9, 8, 6, 4, 3, 3, -}; - -static const uint8_t l_y_ybr[256] = { - 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, - 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, - 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, - 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 4, 4, 3, -}; - -static const uint8_t l_u_ybr[256] = { - 1, 2, 4, 6, 9, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, - 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, - 14, 14, 14, 14, 14, 13, 13, 13, 12, 12, 11, 11, 10, 8, 5, 3, -}; - -static const uint8_t l_y_ybyr[256] = { - 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, - 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, - 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 5, 5, 4, 4, 4, -}; - -static const uint8_t l_u_ybyr[256] = { - 1, 2, 4, 6, 8, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, - 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 14, 14, - 14, 14, 13, 13, 13, 12, 12, 11, 11, 10, 10, 9, 8, 7, 6, 3, -}; - -static const uint8_t l_y_byry[256] = { - 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, - 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, - 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, - 11, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, - 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 4, 4, 3, -}; - -static const uint8_t l_u_byry[256] = { - 1, 2, 4, 6, 8, 9, 9, 10, 11, 11, 12, 12, 13, 13, 13, 14, - 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, - 14, 14, 14, 13, 13, 12, 12, 12, 11, 11, 10, 9, 8, 7, 6, 3, -}; - -static const uint8_t l_y_ybr10i[1024] = { - 3, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, -}; - -static const uint8_t l_y_ybr10[1024] = { - 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, - 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, - 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, -}; - -static const uint8_t l_u_ybr10i[1024] = { - 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, - 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 6, 5, 5, 4, 4, 3, -}; - -static const uint8_t l_u_ybr10[1024] = { - 2, 3, 3, 4, 5, 5, 6, 7, 8, 9, 9, 10, 10, 10, 11, 11, - 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12, - 12, 11, 11, 11, 10, 10, 9, 9, 8, 8, 7, 6, 5, 4, 4, 3, -}; - -static const uint8_t l_r_rgbx[1024] = { - 4, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, -}; - -static const uint8_t l_g_rgbx[1024] = { - 3, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, - 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, - 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, - 12, 12, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 9, - 8, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, -}; - -static const uint8_t l_y_yry10[1024] = { - 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, - 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, - 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, -}; - -static const uint8_t l_y_yry10i[1024] = { - 3, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, -}; - -static const uint8_t l_u_yry10[1024] = { - 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10, - 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, - 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, - 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, - 10, 10, 10, 10, 9, 9, 9, 8, 8, 7, 7, 6, 5, 4, 4, 3, -}; - -static const uint8_t l_u_yry10i[1024] = { - 2, 4, 4, 4, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, - 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, - 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, - 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 9, 9, 9, - 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 5, 4, 4, 3, -}; - -static const uint8_t l_y_ybri[256] = { - 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, - 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, - 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 3, -}; - -static const uint8_t l_u_ybri[256] = { - 1, 3, 5, 6, 8, 8, 9, 10, 10, 11, 11, 12, 12, 13, 13, 13, - 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, - 14, 13, 13, 13, 12, 12, 11, 11, 10, 10, 9, 8, 8, 6, 5, 2, -}; - -static const uint8_t l_y_byryi[256] = { - 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, - 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, - 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, - 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, - 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 5, 4, 4, 3, -}; - -static const uint8_t l_u_byryi[256] = { - 1, 3, 4, 6, 6, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, - 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, - 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, - 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, - 12, 11, 11, 11, 10, 10, 10, 9, 9, 8, 8, 7, 7, 5, 4, 3, -}; - -static const uint8_t l_r_rgbxi[1024] = { - 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, - 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, - 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, 4, 4, 4, -}; - -static const uint8_t l_g_rgbxi[1024] = { - 2, 3, 4, 4, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, - 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, - 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, - 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, - 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 4, 4, 3, -}; - static void decode_ca4i(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb) { SheerVideoContext *s = avctx->priv_data; diff --git a/libavcodec/sheervideodata.h b/libavcodec/sheervideodata.h new file mode 100644 index 0000000000000..092ab87e5e511 --- /dev/null +++ b/libavcodec/sheervideodata.h @@ -0,0 +1,1093 @@ +/* + * BitJazz SheerVideo decoder + * Copyright (c) 2016 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +static const uint8_t l_r_rgb[256] = { + 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, + 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, + 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 5, 5, 4, 4, 4, +}; + +static const uint8_t l_r_rgbi[256] = { + 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, + 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 4, 4, 4, +}; + +static const uint8_t l_g_rgbi[256] = { + 1, 3, 4, 5, 6, 7, 7, 8, 9, 9, 10, 10, 10, 10, 11, 11, + 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, + 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, + 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, + 11, 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 7, 6, 5, 5, 3, +}; + +static const uint8_t l_g_rgb[256] = { + 2, 2, 4, 4, 6, 7, 9, 9, 10, 11, 11, 11, 12, 12, 12, 13, + 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, + 13, 13, 12, 12, 12, 11, 11, 11, 10, 9, 9, 8, 6, 4, 3, 3, +}; + +static const uint8_t l_y_ybr[256] = { + 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, + 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 4, 4, 3, +}; + +static const uint8_t l_u_ybr[256] = { + 1, 2, 4, 6, 9, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, + 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, + 14, 14, 14, 14, 14, 13, 13, 13, 12, 12, 11, 11, 10, 8, 5, 3, +}; + +static const uint8_t l_y_ybyr[256] = { + 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, + 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, + 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 5, 5, 4, 4, 4, +}; + +static const uint8_t l_u_ybyr[256] = { + 1, 2, 4, 6, 8, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, + 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 14, 14, + 14, 14, 13, 13, 13, 12, 12, 11, 11, 10, 10, 9, 8, 7, 6, 3, +}; + +static const uint8_t l_y_byry[256] = { + 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, + 11, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, + 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 4, 4, 3, +}; + +static const uint8_t l_u_byry[256] = { + 1, 2, 4, 6, 8, 9, 9, 10, 11, 11, 12, 12, 13, 13, 13, 14, + 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, + 14, 14, 14, 13, 13, 12, 12, 12, 11, 11, 10, 9, 8, 7, 6, 3, +}; + +static const uint8_t l_y_ybr10i[1024] = { + 3, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, +}; + +static const uint8_t l_y_ybr10[1024] = { + 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, + 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, +}; + +static const uint8_t l_u_ybr10i[1024] = { + 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 6, 5, 5, 4, 4, 3, +}; + +static const uint8_t l_u_ybr10[1024] = { + 2, 3, 3, 4, 5, 5, 6, 7, 8, 9, 9, 10, 10, 10, 11, 11, + 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12, + 12, 11, 11, 11, 10, 10, 9, 9, 8, 8, 7, 6, 5, 4, 4, 3, +}; + +static const uint8_t l_r_rgbx[1024] = { + 4, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, +}; + +static const uint8_t l_g_rgbx[1024] = { + 3, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, + 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, + 12, 12, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 9, + 8, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, +}; + +static const uint8_t l_y_yry10[1024] = { + 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, + 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, +}; + +static const uint8_t l_y_yry10i[1024] = { + 3, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, +}; + +static const uint8_t l_u_yry10[1024] = { + 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, + 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, + 10, 10, 10, 10, 9, 9, 9, 8, 8, 7, 7, 6, 5, 4, 4, 3, +}; + +static const uint8_t l_u_yry10i[1024] = { + 2, 4, 4, 4, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, + 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, + 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 9, 9, 9, + 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 5, 4, 4, 3, +}; + +static const uint8_t l_y_ybri[256] = { + 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, + 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 3, +}; + +static const uint8_t l_u_ybri[256] = { + 1, 3, 5, 6, 8, 8, 9, 10, 10, 11, 11, 12, 12, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, + 14, 13, 13, 13, 12, 12, 11, 11, 10, 10, 9, 8, 8, 6, 5, 2, +}; + +static const uint8_t l_y_byryi[256] = { + 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, + 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, + 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 5, 4, 4, 3, +}; + +static const uint8_t l_u_byryi[256] = { + 1, 3, 4, 6, 6, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, + 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, + 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, + 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, + 12, 11, 11, 11, 10, 10, 10, 9, 9, 8, 8, 7, 7, 5, 4, 3, +}; + +static const uint8_t l_r_rgbxi[1024] = { + 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, + 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, 4, 4, 4, +}; + +static const uint8_t l_g_rgbxi[1024] = { + 2, 3, 4, 4, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, + 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, + 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, + 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, + 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 4, 4, 3, +}; + From e53d3348d10feda300a4d906c136a4ce438369eb Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 29 Mar 2018 15:10:15 +0200 Subject: [PATCH 2359/2557] avcodec/xwdenc: do not rely on AV_PIX_FMT_FLAG_PSEUDOPAL palettes This is the only code I found within FFmpeg that still inherently requires AV_PIX_FMT_FLAG_PSEUDOPAL. It's easily changed not to require it. Preparation for the next patch. --- libavcodec/xwdenc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libavcodec/xwdenc.c b/libavcodec/xwdenc.c index 43bca8903322b..81cca6c9636ec 100644 --- a/libavcodec/xwdenc.c +++ b/libavcodec/xwdenc.c @@ -41,6 +41,7 @@ static int xwd_encode_frame(AVCodecContext *avctx, AVPacket *pkt, int i, out_size, ret; uint8_t *ptr, *buf; AVFrame * const p = (AVFrame *)pict; + uint32_t pal[256]; pixdepth = av_get_bits_per_pixel(desc); if (desc->flags & AV_PIX_FMT_FLAG_BE) @@ -180,11 +181,17 @@ static int xwd_encode_frame(AVCodecContext *avctx, AVPacket *pkt, bytestream_put_be32(&buf, 0); // window border width bytestream_put_buffer(&buf, WINDOW_NAME, WINDOW_NAME_SIZE); + if (pix_fmt == AV_PIX_FMT_PAL8) { + memcpy(pal, p->data[1], sizeof(pal)); + } else { + avpriv_set_systematic_pal2(pal, pix_fmt); + } + for (i = 0; i < ncolors; i++) { uint32_t val; uint8_t red, green, blue; - val = AV_RN32A(p->data[1] + i * 4); + val = pal[i]; red = (val >> 16) & 0xFF; green = (val >> 8) & 0xFF; blue = val & 0xFF; From d6fc031caf64eed921bbdef86d79d56bfc2633b0 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 29 Mar 2018 15:18:28 +0200 Subject: [PATCH 2360/2557] avutil/pixdesc: deprecate AV_PIX_FMT_FLAG_PSEUDOPAL PSEUDOPAL pixel formats are not paletted, but carried a palette with the intention of allowing code to treat unpaletted formats as paletted. The palette simply mapped the byte values to the resulting RGB values, making it some sort of LUT for RGB conversion. It was used for 1 byte formats only: RGB4_BYTE, BGR4_BYTE, RGB8, BGR8, GRAY8. The first 4 are awfully obscure, used only by some ancient bitmap formats. The last one, GRAY8, is more common, but its treatment is grossly incorrect. It considers full range GRAY8 only, so GRAY8 coming from typical Y video planes was not mapped to the correct RGB values. This cannot be fixed, because AVFrame.color_range can be freely changed at runtime, and there is nothing to ensure the pseudo palette is updated. Also, nothing actually used the PSEUDOPAL palette data, except xwdenc (trivially changed in the previous commit). All other code had to treat it as a special case, just to ignore or to propagate palette data. In conclusion, this was just a very strange old mechnaism that has no real justification to exist anymore (although it may have been nice and useful in the past). Now it's an artifact that makes the API harder to use: API users who allocate their own pixel data have to be aware that they need to allocate the palette, or FFmpeg will crash on them in _some_ situations. On top of this, there was no API to allocate the pseuo palette outside of av_frame_get_buffer(). This patch not only deprecates AV_PIX_FMT_FLAG_PSEUDOPAL, but also makes the pseudo palette optional. Nothing accesses it anymore, though if it's set, it's propagated. It's still allocated and initialized for compatibility with API users that rely on this feature. But new API users do not need to allocate it. This was an explicit goal of this patch. Most changes replace AV_PIX_FMT_FLAG_PSEUDOPAL with FF_PSEUDOPAL. I first tried #ifdefing all code, but it was a mess. The FF_PSEUDOPAL macro reduces the mess, and still allows defining FF_API_PSEUDOPAL to 0. Passes FATE with FF_API_PSEUDOPAL enabled and disabled. In addition, FATE passes with FF_API_PSEUDOPAL set to 1, but with allocation functions manually changed to not allocating a palette. --- doc/APIchanges | 4 ++++ fftools/ffprobe.c | 2 ++ libavcodec/decode.c | 5 +---- libavcodec/ffv1dec.c | 2 +- libavcodec/rawdec.c | 6 ++++-- libavcodec/smvjpegdec.c | 2 +- libavfilter/drawutils.c | 2 +- libavfilter/framepool.c | 4 ++-- libavfilter/vf_crop.c | 2 +- libavfilter/vf_pixdesctest.c | 2 +- libavfilter/vf_scale.c | 5 ++--- libavfilter/vf_shuffleplanes.c | 2 +- libavutil/frame.c | 4 ++-- libavutil/imgutils.c | 13 +++++++------ libavutil/internal.h | 9 +++++++++ libavutil/pixdesc.c | 10 +++++----- libavutil/pixdesc.h | 8 ++++++++ libavutil/version.h | 5 ++++- libswscale/swscale_internal.h | 14 +++++++++++--- 19 files changed, 67 insertions(+), 34 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 121fbee9ceb07..f6ad2169a2ef7 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-04-03 - xxxxxxx - lavu 56.13.100 - pixdesc.h + Deprecate AV_PIX_FMT_FLAG_PSEUDOPAL and make allocating a pseudo palette + optional for API users (see AV_PIX_FMT_FLAG_PSEUDOPAL doxygen for details). + 2018-04-01 - xxxxxxx - lavc 58.17.100 - avcodec.h Add av_packet_make_refcounted(). diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 2582649fd3061..82dfe4f58ae8f 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -3118,7 +3118,9 @@ static void ffprobe_show_pixel_formats(WriterContext *w) PRINT_PIX_FMT_FLAG(HWACCEL, "hwaccel"); PRINT_PIX_FMT_FLAG(PLANAR, "planar"); PRINT_PIX_FMT_FLAG(RGB, "rgb"); +#if FF_API_PSEUDOPAL PRINT_PIX_FMT_FLAG(PSEUDOPAL, "pseudopal"); +#endif PRINT_PIX_FMT_FLAG(ALPHA, "alpha"); writer_print_section_footer(w); } diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 40c8a8855c0f5..d883a5f9fc7fb 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1614,7 +1614,7 @@ static int video_get_buffer(AVCodecContext *s, AVFrame *pic) pic->linesize[i] = 0; } if (desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) + ((desc->flags & FF_PSEUDOPAL) && pic->data[1])) avpriv_set_systematic_pal2((uint32_t *)pic->data[1], pic->format); if (s->debug & FF_DEBUG_BUFFERS) @@ -1782,9 +1782,6 @@ static void validate_avframe_allocation(AVCodecContext *avctx, AVFrame *frame) for (i = 0; i < num_planes; i++) { av_assert0(frame->data[i]); } - // For now do not enforce anything for palette of pseudopal formats - if (num_planes == 1 && (flags & AV_PIX_FMT_FLAG_PSEUDOPAL)) - num_planes = 2; // For formats without data like hwaccel allow unused pointers to be non-NULL. for (i = num_planes; num_planes > 0 && i < FF_ARRAY_ELEMS(frame->data); i++) { if (frame->data[i]) diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index b4a183c5b7a9d..7658a516850d3 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -950,7 +950,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac } if (desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { + desc->flags & FF_PSEUDOPAL) { dst[1] = p->data[1]; src[1] = f->last_picture.f->data[1]; } diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c index 1893b2644401a..53f5b76e93e7b 100644 --- a/libavcodec/rawdec.c +++ b/libavcodec/rawdec.c @@ -92,12 +92,14 @@ static av_cold int raw_init_decoder(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (desc->flags & (AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_PSEUDOPAL)) { + if (desc->flags & (AV_PIX_FMT_FLAG_PAL | FF_PSEUDOPAL)) { context->palette = av_buffer_alloc(AVPALETTE_SIZE); if (!context->palette) return AVERROR(ENOMEM); +#if FF_API_PSEUDOPAL if (desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) avpriv_set_systematic_pal2((uint32_t*)context->palette->data, avctx->pix_fmt); +#endif else { memset(context->palette->data, 0, AVPALETTE_SIZE); if (avctx->bits_per_coded_sample == 1) @@ -423,7 +425,7 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame, } if ((avctx->pix_fmt == AV_PIX_FMT_PAL8 && buf_size < context->frame_size) || - (desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL)) { + (desc->flags & FF_PSEUDOPAL)) { frame->buf[1] = av_buffer_ref(context->palette); if (!frame->buf[1]) { av_buffer_unref(&frame->buf[0]); diff --git a/libavcodec/smvjpegdec.c b/libavcodec/smvjpegdec.c index 0b05d19f7b026..7ea82ebfeed5e 100644 --- a/libavcodec/smvjpegdec.c +++ b/libavcodec/smvjpegdec.c @@ -71,7 +71,7 @@ static inline void smv_img_pnt(uint8_t *dst_data[4], uint8_t *src_data[4], src_linesizes[i], h, nlines); } if (desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) + desc->flags & FF_PSEUDOPAL) dst_data[1] = src_data[1]; } diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index 17e26c764acc8..db8c7a6226178 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -184,7 +184,7 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) if (!desc || !desc->name) return AVERROR(EINVAL); - if (desc->flags & ~(AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PSEUDOPAL | AV_PIX_FMT_FLAG_ALPHA)) + if (desc->flags & ~(AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | FF_PSEUDOPAL | AV_PIX_FMT_FLAG_ALPHA)) return AVERROR(ENOSYS); if (format == AV_PIX_FMT_P010LE || format == AV_PIX_FMT_P010BE || format == AV_PIX_FMT_P016LE || format == AV_PIX_FMT_P016BE) return AVERROR(ENOSYS); diff --git a/libavfilter/framepool.c b/libavfilter/framepool.c index da2ac5cf69dbc..3b178cebb8173 100644 --- a/libavfilter/framepool.c +++ b/libavfilter/framepool.c @@ -103,7 +103,7 @@ FFFramePool *ff_frame_pool_video_init(AVBufferRef* (*alloc)(int size), } if (desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { + desc->flags & FF_PSEUDOPAL) { pool->pools[1] = av_buffer_pool_init(AVPALETTE_SIZE, alloc); if (!pool->pools[1]) goto fail; @@ -227,7 +227,7 @@ AVFrame *ff_frame_pool_get(FFFramePool *pool) } if (desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { + desc->flags & FF_PSEUDOPAL) { enum AVPixelFormat format = pool->format == AV_PIX_FMT_PAL8 ? AV_PIX_FMT_BGR8 : pool->format; diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c index 0fdc4949e3bd4..84be4c7d0d240 100644 --- a/libavfilter/vf_crop.c +++ b/libavfilter/vf_crop.c @@ -288,7 +288,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame) frame->data[0] += s->y * frame->linesize[0]; frame->data[0] += s->x * s->max_step[0]; - if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL)) { + if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & FF_PSEUDOPAL)) { for (i = 1; i < 3; i ++) { if (frame->data[i]) { frame->data[i] += (s->y >> s->vsub) * frame->linesize[i]; diff --git a/libavfilter/vf_pixdesctest.c b/libavfilter/vf_pixdesctest.c index d6423acb91067..2d0749e20bc0b 100644 --- a/libavfilter/vf_pixdesctest.c +++ b/libavfilter/vf_pixdesctest.c @@ -81,7 +81,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) /* copy palette */ if (priv->pix_desc->flags & AV_PIX_FMT_FLAG_PAL || - priv->pix_desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) + ((priv->pix_desc->flags & FF_PSEUDOPAL) && out->data[1] && in->data[1])) memcpy(out->data[1], in->data[1], AVPALETTE_SIZE); for (c = 0; c < priv->pix_desc->nb_components; c++) { diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 9f45032e85522..f741419e7e23b 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -261,11 +261,10 @@ static int config_props(AVFilterLink *outlink) /* TODO: make algorithm configurable */ - scale->input_is_pal = desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL; + scale->input_is_pal = desc->flags & AV_PIX_FMT_FLAG_PAL; if (outfmt == AV_PIX_FMT_PAL8) outfmt = AV_PIX_FMT_BGR8; scale->output_is_pal = av_pix_fmt_desc_get(outfmt)->flags & AV_PIX_FMT_FLAG_PAL || - av_pix_fmt_desc_get(outfmt)->flags & AV_PIX_FMT_FLAG_PSEUDOPAL; + av_pix_fmt_desc_get(outfmt)->flags & FF_PSEUDOPAL; if (scale->sws) sws_freeContext(scale->sws); diff --git a/libavfilter/vf_shuffleplanes.c b/libavfilter/vf_shuffleplanes.c index 4bc7b79f8743c..32d2d585f3ba3 100644 --- a/libavfilter/vf_shuffleplanes.c +++ b/libavfilter/vf_shuffleplanes.c @@ -69,7 +69,7 @@ static av_cold int shuffleplanes_config_input(AVFilterLink *inlink) } if ((desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) && + desc->flags & FF_PSEUDOPAL) && (i == 1) != (s->map[i] == 1)) { av_log(ctx, AV_LOG_ERROR, "Cannot map between a palette plane and a data plane.\n"); diff --git a/libavutil/frame.c b/libavutil/frame.c index ea13cd3ed61a9..00215ac29a4fd 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -247,7 +247,7 @@ static int get_video_buffer(AVFrame *frame, int align) frame->data[i] = frame->buf[i]->data; } - if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { + if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & FF_PSEUDOPAL) { av_buffer_unref(&frame->buf[1]); frame->buf[1] = av_buffer_alloc(AVPALETTE_SIZE); if (!frame->buf[1]) @@ -848,7 +848,7 @@ static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame, int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0; int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; - if (desc->flags & (AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_PSEUDOPAL) && i == 1) { + if (desc->flags & (AV_PIX_FMT_FLAG_PAL | FF_PSEUDOPAL) && i == 1) { offsets[i] = 0; break; } diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c index 5af4fc20a06a6..4938a7ef6767f 100644 --- a/libavutil/imgutils.c +++ b/libavutil/imgutils.c @@ -125,7 +125,7 @@ int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int hei size[0] = linesizes[0] * height; if (desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { + desc->flags & FF_PSEUDOPAL) { data[1] = ptr + size[0]; /* palette is stored here as 256 32 bits words */ return size[0] + 256 * 4; } @@ -216,7 +216,7 @@ int av_image_alloc(uint8_t *pointers[4], int linesizes[4], av_free(buf); return ret; } - if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { + if (desc->flags & AV_PIX_FMT_FLAG_PAL || (desc->flags & FF_PSEUDOPAL && pointers[1])) { avpriv_set_systematic_pal2((uint32_t*)pointers[1], pix_fmt); if (align < 4) { av_log(NULL, AV_LOG_ERROR, "Formats with a palette require a minimum alignment of 4\n"); @@ -225,7 +225,7 @@ int av_image_alloc(uint8_t *pointers[4], int linesizes[4], } if ((desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) && + desc->flags & FF_PSEUDOPAL) && pointers[1] && pointers[1] - pointers[0] > linesizes[0] * h) { /* zero-initialize the padding before the palette */ memset(pointers[0] + linesizes[0] * h, 0, @@ -354,12 +354,13 @@ static void image_copy(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4], return; if (desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { + desc->flags & FF_PSEUDOPAL) { copy_plane(dst_data[0], dst_linesizes[0], src_data[0], src_linesizes[0], width, height); /* copy the palette */ - memcpy(dst_data[1], src_data[1], 4*256); + if ((desc->flags & AV_PIX_FMT_FLAG_PAL) || (dst_data[1] && src_data[1])) + memcpy(dst_data[1], src_data[1], 4*256); } else { int i, planes_nb = 0; @@ -442,7 +443,7 @@ int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, return ret; // do not include palette for these pseudo-paletted formats - if (desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) + if (desc->flags & FF_PSEUDOPAL) return FFALIGN(width, align) * height; return av_image_fill_arrays(data, linesize, NULL, pix_fmt, diff --git a/libavutil/internal.h b/libavutil/internal.h index c77dfa7d3c2c9..06bd561e82c0c 100644 --- a/libavutil/internal.h +++ b/libavutil/internal.h @@ -360,4 +360,13 @@ void ff_check_pixfmt_descriptors(void); */ int avpriv_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestamp); +// Helper macro for AV_PIX_FMT_FLAG_PSEUDOPAL deprecation. Code inside FFmpeg +// should always use FF_PSEUDOPAL. Once the public API flag gets removed, all +// code using it is dead code. +#if FF_API_PSEUDOPAL +#define FF_PSEUDOPAL AV_PIX_FMT_FLAG_PSEUDOPAL +#else +#define FF_PSEUDOPAL 0 +#endif + #endif /* AVUTIL_INTERNAL_H */ diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index e77d5f44b9cae..8ed52751c1a8b 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -257,7 +257,7 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .comp = { { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ }, - .flags = AV_PIX_FMT_FLAG_PSEUDOPAL, + .flags = FF_PSEUDOPAL, .alias = "gray8,y8", }, [AV_PIX_FMT_MONOWHITE] = { @@ -362,7 +362,7 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { { 0, 1, 0, 3, 3, 0, 2, 1 }, /* G */ { 0, 1, 0, 6, 2, 0, 1, 1 }, /* B */ }, - .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PSEUDOPAL, + .flags = AV_PIX_FMT_FLAG_RGB | FF_PSEUDOPAL, }, [AV_PIX_FMT_BGR4] = { .name = "bgr4", @@ -386,7 +386,7 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { { 0, 1, 0, 1, 2, 0, 1, 1 }, /* G */ { 0, 1, 0, 3, 1, 0, 0, 1 }, /* B */ }, - .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PSEUDOPAL, + .flags = AV_PIX_FMT_FLAG_RGB | FF_PSEUDOPAL, }, [AV_PIX_FMT_RGB8] = { .name = "rgb8", @@ -398,7 +398,7 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { { 0, 1, 0, 3, 3, 0, 2, 1 }, /* G */ { 0, 1, 0, 0, 3, 0, 2, 1 }, /* B */ }, - .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PSEUDOPAL, + .flags = AV_PIX_FMT_FLAG_RGB | FF_PSEUDOPAL, }, [AV_PIX_FMT_RGB4] = { .name = "rgb4", @@ -422,7 +422,7 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { { 0, 1, 0, 1, 2, 0, 1, 1 }, /* G */ { 0, 1, 0, 0, 1, 0, 0, 1 }, /* B */ }, - .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PSEUDOPAL, + .flags = AV_PIX_FMT_FLAG_RGB | FF_PSEUDOPAL, }, [AV_PIX_FMT_NV12] = { .name = "nv12", diff --git a/libavutil/pixdesc.h b/libavutil/pixdesc.h index ea046033a3638..1ab372782ae19 100644 --- a/libavutil/pixdesc.h +++ b/libavutil/pixdesc.h @@ -154,6 +154,14 @@ typedef struct AVPixFmtDescriptor { * in some cases be simpler. Or the data can be interpreted purely based on * the pixel format without using the palette. * An example of a pseudo-paletted format is AV_PIX_FMT_GRAY8 + * + * @deprecated This flag is deprecated, and will be removed. When it is removed, + * the extra palette allocation in AVFrame.data[1] is removed as well. Only + * actual paletted formats (as indicated by AV_PIX_FMT_FLAG_PAL) will have a + * palette. Starting with FFmpeg versions which have this flag deprecated, the + * extra "pseudo" palette is already ignored, and API users are not required to + * allocate a palette for AV_PIX_FMT_FLAG_PSEUDOPAL formats (it was required + * before the deprecation, though). */ #define AV_PIX_FMT_FLAG_PSEUDOPAL (1 << 6) diff --git a/libavutil/version.h b/libavutil/version.h index d3dd2df544afc..d81d51011ba25 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 12 +#define LIBAVUTIL_VERSION_MINOR 13 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ @@ -126,6 +126,9 @@ #ifndef FF_API_FRAME_GET_SET #define FF_API_FRAME_GET_SET (LIBAVUTIL_VERSION_MAJOR < 57) #endif +#ifndef FF_API_PSEUDOPAL +#define FF_API_PSEUDOPAL (LIBAVUTIL_VERSION_MAJOR < 57) +#endif /** diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index c9120d8f5f158..1703856ab2db0 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -806,9 +806,17 @@ static av_always_inline int isPlanarRGB(enum AVPixelFormat pix_fmt) static av_always_inline int usePal(enum AVPixelFormat pix_fmt) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - av_assert0(desc); - return (desc->flags & AV_PIX_FMT_FLAG_PAL) || (desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL); + switch (pix_fmt) { + case AV_PIX_FMT_PAL8: + case AV_PIX_FMT_BGR4_BYTE: + case AV_PIX_FMT_BGR8: + case AV_PIX_FMT_GRAY8: + case AV_PIX_FMT_RGB4_BYTE: + case AV_PIX_FMT_RGB8: + return 1; + default: + return 0; + } } extern const uint64_t ff_dither4[2]; From 673604e0e3b7c7d6a077f61dee322d534ff6eae5 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Tue, 27 Mar 2018 12:53:45 +0530 Subject: [PATCH 2361/2557] lavc/cfhd: fix distortion of lowest 8 lines when height is not multiple of 16 Also update fate reference. Fixes ticket #6675. --- libavcodec/cfhd.c | 5 +++-- tests/ref/fate/cfhd-3 | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/libavcodec/cfhd.c b/libavcodec/cfhd.c index e35732df45b86..f10742f4fac44 100644 --- a/libavcodec/cfhd.c +++ b/libavcodec/cfhd.c @@ -213,13 +213,14 @@ static int alloc_buffers(AVCodecContext *avctx) int width = i ? avctx->width >> chroma_x_shift : avctx->width; int height = i ? avctx->height >> chroma_y_shift : avctx->height; ptrdiff_t stride = FFALIGN(width / 8, 8) * 8; - height = FFALIGN(height / 8, 2) * 8; + if (chroma_y_shift) + height = FFALIGN(height / 8, 2) * 8; s->plane[i].width = width; s->plane[i].height = height; s->plane[i].stride = stride; w8 = FFALIGN(s->plane[i].width / 8, 8); - h8 = FFALIGN(s->plane[i].height / 8, 2); + h8 = height / 8; w4 = w8 * 2; h4 = h8 * 2; w2 = w4 * 2; diff --git a/tests/ref/fate/cfhd-3 b/tests/ref/fate/cfhd-3 index 60e13c64a7378..59fdc9226090d 100644 --- a/tests/ref/fate/cfhd-3 +++ b/tests/ref/fate/cfhd-3 @@ -3,13 +3,13 @@ #codec_id 0: rawvideo #dimensions 0: 496x241 #sar 0: 0/1 -0, 0, 0, 1, 478144, 0x6ed01dcd -0, 1, 1, 1, 478144, 0x6ed01dcd -0, 2, 2, 1, 478144, 0x6ed01dcd -0, 3, 3, 1, 478144, 0xb1b4a74b -0, 4, 4, 1, 478144, 0x94c345c3 -0, 5, 5, 1, 478144, 0x05e0388d -0, 6, 6, 1, 478144, 0xe747476a -0, 7, 7, 1, 478144, 0x8c1561f1 -0, 8, 8, 1, 478144, 0x8c1561f1 -0, 9, 9, 1, 478144, 0x8c1561f1 +0, 0, 0, 1, 478144, 0x48a01dbb +0, 1, 1, 1, 478144, 0x48a01dbb +0, 2, 2, 1, 478144, 0x48a01dbb +0, 3, 3, 1, 478144, 0xb978a72f +0, 4, 4, 1, 478144, 0x7bbb4679 +0, 5, 5, 1, 478144, 0xc3fd3f59 +0, 6, 6, 1, 478144, 0xfd2a4816 +0, 7, 7, 1, 478144, 0x207f65d3 +0, 8, 8, 1, 478144, 0x207f65d3 +0, 9, 9, 1, 478144, 0x207f65d3 From d5343a5005af770b7dfa31e53d41a05041b7f75c Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 3 Apr 2018 15:27:18 -0300 Subject: [PATCH 2362/2557] avcodec/libaomdec: remove duplicate code Signed-off-by: James Almer --- libavcodec/libaomdec.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index a9fd6215fcb9b..fdc53e45209a8 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -95,17 +95,6 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) switch (img->fmt) { case AOM_IMG_FMT_I420: - avctx->pix_fmt = AV_PIX_FMT_YUV420P; - avctx->profile = FF_PROFILE_AV1_MAIN; - return 0; - case AOM_IMG_FMT_I422: - avctx->pix_fmt = AV_PIX_FMT_YUV422P; - avctx->profile = FF_PROFILE_AV1_PROFESSIONAL; - return 0; - case AOM_IMG_FMT_I444: - avctx->pix_fmt = AV_PIX_FMT_YUV444P; - avctx->profile = FF_PROFILE_AV1_HIGH; - return 0; case AOM_IMG_FMT_I42016: if (img->bit_depth == 8) { avctx->pix_fmt = AV_PIX_FMT_YUV420P; @@ -122,6 +111,7 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) } else { return AVERROR_INVALIDDATA; } + case AOM_IMG_FMT_I422: case AOM_IMG_FMT_I42216: if (img->bit_depth == 8) { avctx->pix_fmt = AV_PIX_FMT_YUV422P; @@ -138,6 +128,7 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) } else { return AVERROR_INVALIDDATA; } + case AOM_IMG_FMT_I444: case AOM_IMG_FMT_I44416: if (img->bit_depth == 8) { avctx->pix_fmt = AV_PIX_FMT_YUV444P; From f3fae82042595f6ea31c832df7b8ca2941bb9620 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 3 Apr 2018 15:33:48 -0300 Subject: [PATCH 2363/2557] avcodec/libaomdec: add support for monochrome files All such files are signaled as I42016, as there's no monochrome value in aom_img_fmt_t. Signed-off-by: James Almer --- libavcodec/libaomdec.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index fdc53e45209a8..9991af96c8020 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -61,9 +61,10 @@ static av_cold int aom_init(AVCodecContext *avctx, static void image_copy_16_to_8(AVFrame *pic, struct aom_image *img) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format); int i; - for (i = 0; i < 3; i++) { + for (i = 0; i < desc->nb_components; i++) { int w = img->d_w; int h = img->d_h; int x, y; @@ -97,7 +98,8 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) case AOM_IMG_FMT_I420: case AOM_IMG_FMT_I42016: if (img->bit_depth == 8) { - avctx->pix_fmt = AV_PIX_FMT_YUV420P; + avctx->pix_fmt = img->monochrome ? + AV_PIX_FMT_GRAY8 : AV_PIX_FMT_YUV420P; avctx->profile = FF_PROFILE_AV1_MAIN; return 0; } else if (img->bit_depth == 10) { @@ -114,7 +116,8 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) case AOM_IMG_FMT_I422: case AOM_IMG_FMT_I42216: if (img->bit_depth == 8) { - avctx->pix_fmt = AV_PIX_FMT_YUV422P; + avctx->pix_fmt = img->monochrome ? + AV_PIX_FMT_GRAY10 : AV_PIX_FMT_YUV420P10; avctx->profile = FF_PROFILE_AV1_PROFESSIONAL; return 0; } else if (img->bit_depth == 10) { @@ -131,7 +134,8 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) case AOM_IMG_FMT_I444: case AOM_IMG_FMT_I44416: if (img->bit_depth == 8) { - avctx->pix_fmt = AV_PIX_FMT_YUV444P; + avctx->pix_fmt = img->monochrome ? + AV_PIX_FMT_GRAY12 : AV_PIX_FMT_YUV420P12; avctx->profile = FF_PROFILE_AV1_HIGH; return 0; } else if (img->bit_depth == 10) { From 4d89b5f844b31b5134f4589bd1773173d9412ef5 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 3 Apr 2018 23:31:36 -0300 Subject: [PATCH 2364/2557] avcodec/clearvideo: add missing wrappers to clearvideodata.h Fixes make fate-source Signed-off-by: James Almer --- libavcodec/clearvideodata.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/clearvideodata.h b/libavcodec/clearvideodata.h index 157397d9877db..43d12dee43458 100644 --- a/libavcodec/clearvideodata.h +++ b/libavcodec/clearvideodata.h @@ -19,6 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifndef AVCODEC_CLEARVIDEODATA_H +#define AVCODEC_CLEARVIDEODATA_H + #include "libavutil/common.h" #define NUM_DC_CODES 127 @@ -1826,4 +1829,4 @@ static const uint16_t clv_biasv_2_syms[] = { 0x004C, 0x0050, 0x0054, 0x0100, }; - +#endif /* AVCODEC_CLEARVIDEODATA_H */ From 9df784db6ef3d6a0b49edb78fea873dc3257f1c6 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 3 Apr 2018 23:32:03 -0300 Subject: [PATCH 2365/2557] avcodec/sheervideo: add missing wrappers to sheervideodata.h Fixes make fate-source Signed-off-by: James Almer --- libavcodec/sheervideodata.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/sheervideodata.h b/libavcodec/sheervideodata.h index 092ab87e5e511..0fac25d48c5e1 100644 --- a/libavcodec/sheervideodata.h +++ b/libavcodec/sheervideodata.h @@ -19,6 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifndef AVCODEC_SHEERVIDEODATA_H +#define AVCODEC_SHEERVIDEODATA_H + #include static const uint8_t l_r_rgb[256] = { @@ -1091,3 +1094,4 @@ static const uint8_t l_g_rgbxi[1024] = { 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 4, 4, 3, }; +#endif /* AVCODEC_SHEERVIDEODATA_H */ From 51e3010575ca55ee64ffe3c48087d263e9c1e65f Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Wed, 4 Apr 2018 11:04:56 +0800 Subject: [PATCH 2366/2557] lavf/hls: Remove the dead code in parse_playlist() Signed-off-by: Jun Zhao Reviewed-by: Steven Liu --- libavformat/hls.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index c578bf86e3b8d..ae0545a086745 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -743,7 +743,6 @@ static int parse_playlist(HLSContext *c, const char *url, } if (!in) { -#if 1 AVDictionary *opts = NULL; /* Some HLS servers don't like being sent the range header */ av_dict_set(&opts, "seekable", "0", 0); @@ -766,12 +765,6 @@ static int parse_playlist(HLSContext *c, const char *url, c->playlist_pb = in; else close_in = 1; -#else - ret = open_in(c, &in, url); - if (ret < 0) - return ret; - close_in = 1; -#endif } if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, &new_url) >= 0) From 3a4d74c1fff8a1c2691ebf0532aa283ca9b4d0d9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 27 Mar 2018 19:48:18 -0300 Subject: [PATCH 2367/2557] avformat/utils: make AVPacketList helper functions shared Based on a patch by Luca Barbato. Signed-off-by: James Almer --- libavformat/internal.h | 39 +++++++++++++++++++++++++++++ libavformat/utils.c | 57 ++++++++++++++++++++++++------------------ 2 files changed, 72 insertions(+), 24 deletions(-) diff --git a/libavformat/internal.h b/libavformat/internal.h index 23eb7e8a7c516..c50382ad29f64 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -731,5 +731,44 @@ int ff_unlock_avformat(void); */ void ff_format_set_url(AVFormatContext *s, char *url); +#define FF_PACKETLIST_FLAG_REF_PACKET (1 << 0) /**< Create a new reference for the packet instead of + transferring the ownership of the existing one to the + list. */ + +/** + * Append an AVPacket to the list. + * + * @param head List head element + * @param tail List tail element + * @param pkt The packet being appended + * @param flags Any combination of FF_PACKETLIST_FLAG_* flags + * @return 0 on success, negative AVERROR value on failure. On failure, + the list is unchanged + */ +int ff_packet_list_put(AVPacketList **head, AVPacketList **tail, + AVPacket *pkt, int flags); + +/** + * Remove the oldest AVPacket in the list and return it. + * + * @note The pkt will be overwritten completely. The caller owns the + * packet and must unref it by itself. + * + * @param head List head element + * @param tail List tail element + * @param pkt Pointer to an initialized AVPacket struct + */ +int ff_packet_list_get(AVPacketList **head, AVPacketList **tail, + AVPacket *pkt); + +/** + * Wipe the list and unref all the packets in it. + * + * @param head List head element + * @param tail List tail element + */ +void ff_packet_list_free(AVPacketList **head, AVPacketList **tail); + void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]); + #endif /* AVFORMAT_INTERNAL_H */ diff --git a/libavformat/utils.c b/libavformat/utils.c index 39a36a5ac4388..be9a44f168242 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -444,8 +444,9 @@ static int init_input(AVFormatContext *s, const char *filename, s, 0, s->format_probesize); } -static int add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, - AVPacketList **plast_pktl, int ref) +int ff_packet_list_put(AVPacketList **packet_buffer, + AVPacketList **plast_pktl, + AVPacket *pkt, int flags) { AVPacketList *pktl = av_mallocz(sizeof(AVPacketList)); int ret; @@ -453,12 +454,15 @@ static int add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, if (!pktl) return AVERROR(ENOMEM); - if (ref) { + if (flags & FF_PACKETLIST_FLAG_REF_PACKET) { if ((ret = av_packet_ref(&pktl->pkt, pkt)) < 0) { av_free(pktl); return ret; } } else { + // TODO: Adapt callers in this file so the line below can use + // av_packet_move_ref() to effectively move the reference + // to the list. pktl->pkt = *pkt; } @@ -485,9 +489,10 @@ int avformat_queue_attached_pictures(AVFormatContext *s) continue; } - ret = add_to_pktbuf(&s->internal->raw_packet_buffer, - &s->streams[i]->attached_pic, - &s->internal->raw_packet_buffer_end, 1); + ret = ff_packet_list_put(&s->internal->raw_packet_buffer, + &s->internal->raw_packet_buffer_end, + &s->streams[i]->attached_pic, + FF_PACKETLIST_FLAG_REF_PACKET); if (ret < 0) return ret; } @@ -909,8 +914,9 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) if (!pktl && st->request_probe <= 0) return ret; - err = add_to_pktbuf(&s->internal->raw_packet_buffer, pkt, - &s->internal->raw_packet_buffer_end, 0); + err = ff_packet_list_put(&s->internal->raw_packet_buffer, + &s->internal->raw_packet_buffer_end, + pkt, 0); if (err) return err; s->internal->raw_packet_buffer_remaining_size -= pkt->size; @@ -1408,7 +1414,7 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif } -static void free_packet_buffer(AVPacketList **pkt_buf, AVPacketList **pkt_buf_end) +void ff_packet_list_free(AVPacketList **pkt_buf, AVPacketList **pkt_buf_end) { while (*pkt_buf) { AVPacketList *pktl = *pkt_buf; @@ -1500,8 +1506,9 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) compute_pkt_fields(s, st, st->parser, &out_pkt, next_dts, next_pts); - ret = add_to_pktbuf(&s->internal->parse_queue, &out_pkt, - &s->internal->parse_queue_end, 1); + ret = ff_packet_list_put(&s->internal->parse_queue, + &s->internal->parse_queue_end, + &out_pkt, FF_PACKETLIST_FLAG_REF_PACKET); av_packet_unref(&out_pkt); if (ret < 0) goto fail; @@ -1518,9 +1525,9 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) return ret; } -static int read_from_packet_buffer(AVPacketList **pkt_buffer, - AVPacketList **pkt_buffer_end, - AVPacket *pkt) +int ff_packet_list_get(AVPacketList **pkt_buffer, + AVPacketList **pkt_buffer_end, + AVPacket *pkt) { AVPacketList *pktl; av_assert0(*pkt_buffer); @@ -1666,7 +1673,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } if (!got_packet && s->internal->parse_queue) - ret = read_from_packet_buffer(&s->internal->parse_queue, &s->internal->parse_queue_end, pkt); + ret = ff_packet_list_get(&s->internal->parse_queue, &s->internal->parse_queue_end, pkt); if (ret >= 0) { AVStream *st = s->streams[pkt->stream_index]; @@ -1745,7 +1752,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) if (!genpts) { ret = s->internal->packet_buffer - ? read_from_packet_buffer(&s->internal->packet_buffer, + ? ff_packet_list_get(&s->internal->packet_buffer, &s->internal->packet_buffer_end, pkt) : read_frame_internal(s, pkt); if (ret < 0) @@ -1794,7 +1801,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) st = s->streams[next_pkt->stream_index]; if (!(next_pkt->pts == AV_NOPTS_VALUE && st->discard < AVDISCARD_ALL && next_pkt->dts != AV_NOPTS_VALUE && !eof)) { - ret = read_from_packet_buffer(&s->internal->packet_buffer, + ret = ff_packet_list_get(&s->internal->packet_buffer, &s->internal->packet_buffer_end, pkt); goto return_packet; } @@ -1809,8 +1816,9 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) return ret; } - ret = add_to_pktbuf(&s->internal->packet_buffer, pkt, - &s->internal->packet_buffer_end, 1); + ret = ff_packet_list_put(&s->internal->packet_buffer, + &s->internal->packet_buffer_end, + pkt, FF_PACKETLIST_FLAG_REF_PACKET); av_packet_unref(pkt); if (ret < 0) return ret; @@ -1837,9 +1845,9 @@ static void flush_packet_queue(AVFormatContext *s) { if (!s->internal) return; - free_packet_buffer(&s->internal->parse_queue, &s->internal->parse_queue_end); - free_packet_buffer(&s->internal->packet_buffer, &s->internal->packet_buffer_end); - free_packet_buffer(&s->internal->raw_packet_buffer, &s->internal->raw_packet_buffer_end); + ff_packet_list_free(&s->internal->parse_queue, &s->internal->parse_queue_end); + ff_packet_list_free(&s->internal->packet_buffer, &s->internal->packet_buffer_end); + ff_packet_list_free(&s->internal->raw_packet_buffer, &s->internal->raw_packet_buffer_end); s->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; } @@ -3739,8 +3747,9 @@ FF_ENABLE_DEPRECATION_WARNINGS pkt = &pkt1; if (!(ic->flags & AVFMT_FLAG_NOBUFFER)) { - ret = add_to_pktbuf(&ic->internal->packet_buffer, pkt, - &ic->internal->packet_buffer_end, 0); + ret = ff_packet_list_put(&ic->internal->packet_buffer, + &ic->internal->packet_buffer_end, + pkt, 0); if (ret < 0) goto find_stream_info_err; } From 58ce4fdeaebce5d9837ebc77e1453e7cf3a5bb1d Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 26 Mar 2018 15:02:36 -0300 Subject: [PATCH 2368/2557] avformat/utils: optimize ff_packet_list_free() Don't constantly overwrite the list's head pointer. Signed-off-by: James Almer --- libavformat/utils.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index be9a44f168242..3e482a3bbc18b 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1416,12 +1416,15 @@ FF_ENABLE_DEPRECATION_WARNINGS void ff_packet_list_free(AVPacketList **pkt_buf, AVPacketList **pkt_buf_end) { - while (*pkt_buf) { - AVPacketList *pktl = *pkt_buf; - *pkt_buf = pktl->next; + AVPacketList *tmp = *pkt_buf; + + while (tmp) { + AVPacketList *pktl = tmp; + tmp = pktl->next; av_packet_unref(&pktl->pkt); av_freep(&pktl); } + *pkt_buf = NULL; *pkt_buf_end = NULL; } From 78b96be7580ea0d02f6366414e84cb344a8214ca Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 26 Mar 2018 15:02:37 -0300 Subject: [PATCH 2369/2557] avformat/matroskadec: use AVPacketList to queue packets It's more robust and efficient. Signed-off-by: James Almer --- libavformat/matroskadec.c | 62 +++++++++++++++------------------------ 1 file changed, 23 insertions(+), 39 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 2faaf9dfb8b1b..3e5b537ac430f 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -338,9 +338,8 @@ typedef struct MatroskaDemuxContext { int64_t segment_start; /* the packet queue */ - AVPacket **packets; - int num_packets; - AVPacket *prev_pkt; + AVPacketList *queue; + AVPacketList *queue_end; int done; @@ -2722,11 +2721,11 @@ static int matroska_read_header(AVFormatContext *s) static int matroska_deliver_packet(MatroskaDemuxContext *matroska, AVPacket *pkt) { - if (matroska->num_packets > 0) { + if (matroska->queue) { MatroskaTrack *tracks = matroska->tracks.elem; MatroskaTrack *track; - memcpy(pkt, matroska->packets[0], sizeof(AVPacket)); - av_freep(&matroska->packets[0]); + + ff_packet_list_get(&matroska->queue, &matroska->queue_end, pkt); track = &tracks[pkt->stream_index]; if (track->has_palette) { uint8_t *pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); @@ -2737,20 +2736,6 @@ static int matroska_deliver_packet(MatroskaDemuxContext *matroska, } track->has_palette = 0; } - if (matroska->num_packets > 1) { - void *newpackets; - memmove(&matroska->packets[0], &matroska->packets[1], - (matroska->num_packets - 1) * sizeof(AVPacket *)); - newpackets = av_realloc(matroska->packets, - (matroska->num_packets - 1) * - sizeof(AVPacket *)); - if (newpackets) - matroska->packets = newpackets; - } else { - av_freep(&matroska->packets); - matroska->prev_pkt = NULL; - } - matroska->num_packets--; return 0; } @@ -2762,16 +2747,7 @@ static int matroska_deliver_packet(MatroskaDemuxContext *matroska, */ static void matroska_clear_queue(MatroskaDemuxContext *matroska) { - matroska->prev_pkt = NULL; - if (matroska->packets) { - int n; - for (n = 0; n < matroska->num_packets; n++) { - av_packet_unref(matroska->packets[n]); - av_freep(&matroska->packets[n]); - } - av_freep(&matroska->packets); - matroska->num_packets = 0; - } + ff_packet_list_free(&matroska->queue, &matroska->queue_end); } static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, @@ -2953,7 +2929,11 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, track->audio.buf_timecode = AV_NOPTS_VALUE; pkt->pos = pos; pkt->stream_index = st->index; - dynarray_add(&matroska->packets, &matroska->num_packets, pkt); + ret = ff_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, 0); + if (ret < 0) { + av_packet_free(&pkt); + return AVERROR(ENOMEM); + } } return 0; @@ -3152,8 +3132,11 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, pkt->duration = duration; pkt->pos = pos; - dynarray_add(&matroska->packets, &matroska->num_packets, pkt); - matroska->prev_pkt = pkt; + err = ff_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, 0); + if (err < 0) { + av_packet_free(&pkt); + return AVERROR(ENOMEM); + } return 0; } @@ -3268,8 +3251,11 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif - dynarray_add(&matroska->packets, &matroska->num_packets, pkt); - matroska->prev_pkt = pkt; + res = ff_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, 0); + if (res < 0) { + av_packet_free(&pkt); + return AVERROR(ENOMEM); + } return 0; @@ -3433,7 +3419,6 @@ static int matroska_parse_cluster_incremental(MatroskaDemuxContext *matroska) memset(&matroska->current_cluster, 0, sizeof(MatroskaCluster)); matroska->current_cluster_num_blocks = 0; matroska->current_cluster_pos = avio_tell(matroska->ctx->pb); - matroska->prev_pkt = NULL; /* sizeof the ID which was already read */ if (matroska->current_id) matroska->current_cluster_pos -= 4; @@ -3486,7 +3471,6 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska) if (!matroska->contains_ssa) return matroska_parse_cluster_incremental(matroska); pos = avio_tell(matroska->ctx->pb); - matroska->prev_pkt = NULL; if (matroska->current_id) pos -= 4; /* sizeof the ID which was already read */ res = ebml_parse(matroska, matroska_clusters, &cluster); @@ -3671,10 +3655,10 @@ static int webm_clusters_start_with_keyframe(AVFormatContext *s) matroska->current_id = 0; matroska_clear_queue(matroska); if (matroska_parse_cluster(matroska) < 0 || - matroska->num_packets <= 0) { + !matroska->queue) { break; } - pkt = matroska->packets[0]; + pkt = &matroska->queue->pkt; cluster_pos += cluster_length + 12; // 12 is the offset of the cluster id and length. if (!(pkt->flags & AV_PKT_FLAG_KEY)) { rv = 0; From 15ca8311e68d0a88117bce7e22f4bb423737e3d9 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 26 Mar 2018 15:02:38 -0300 Subject: [PATCH 2370/2557] avformat/ttaenc: use AVPacketList helper functions to queue packets Simplifies code. Signed-off-by: James Almer --- libavformat/ttaenc.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/libavformat/ttaenc.c b/libavformat/ttaenc.c index add15873d048f..d8e1136ead1a2 100644 --- a/libavformat/ttaenc.c +++ b/libavformat/ttaenc.c @@ -91,22 +91,13 @@ static int tta_write_header(AVFormatContext *s) static int tta_write_packet(AVFormatContext *s, AVPacket *pkt) { TTAMuxContext *tta = s->priv_data; - AVPacketList *pktl = av_mallocz(sizeof(*pktl)); int ret; - if (!pktl) - return AVERROR(ENOMEM); - - ret = av_packet_ref(&pktl->pkt, pkt); + ret = ff_packet_list_put(&tta->queue, &tta->queue_end, pkt, + FF_PACKETLIST_FLAG_REF_PACKET); if (ret < 0) { - av_free(pktl); return ret; } - if (tta->queue_end) - tta->queue_end->next = pktl; - else - tta->queue = pktl; - tta->queue_end = pktl; avio_wl32(tta->seek_table, pkt->size); tta->nb_samples += pkt->duration; @@ -131,16 +122,13 @@ static int tta_write_packet(AVFormatContext *s, AVPacket *pkt) static void tta_queue_flush(AVFormatContext *s) { TTAMuxContext *tta = s->priv_data; - AVPacketList *pktl; - - while (pktl = tta->queue) { - AVPacket *pkt = &pktl->pkt; - avio_write(s->pb, pkt->data, pkt->size); - av_packet_unref(pkt); - tta->queue = pktl->next; - av_free(pktl); + AVPacket pkt; + + while (tta->queue) { + ff_packet_list_get(&tta->queue, &tta->queue_end, &pkt); + avio_write(s->pb, pkt.data, pkt.size); + av_packet_unref(&pkt); } - tta->queue_end = NULL; } static int tta_write_trailer(AVFormatContext *s) From d95f15b14d5cf56af4b157423e93609003858c5e Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 26 Mar 2018 15:02:39 -0300 Subject: [PATCH 2371/2557] avformat/mp3enc: use AVPacketList helper functions to queue packets Simplifies code. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/mp3enc.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index 8479e2485bb33..dd662f5473c8b 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -369,20 +369,18 @@ static int mp3_write_audio_packet(AVFormatContext *s, AVPacket *pkt) static int mp3_queue_flush(AVFormatContext *s) { MP3Context *mp3 = s->priv_data; - AVPacketList *pktl; + AVPacket pkt; int ret = 0, write = 1; ff_id3v2_finish(&mp3->id3, s->pb, s->metadata_header_padding); mp3_write_xing(s); - while ((pktl = mp3->queue)) { - if (write && (ret = mp3_write_audio_packet(s, &pktl->pkt)) < 0) + while (mp3->queue) { + ff_packet_list_get(&mp3->queue, &mp3->queue_end, &pkt); + if (write && (ret = mp3_write_audio_packet(s, &pkt)) < 0) write = 0; - av_packet_unref(&pktl->pkt); - mp3->queue = pktl->next; - av_freep(&pktl); + av_packet_unref(&pkt); } - mp3->queue_end = NULL; return ret; } @@ -514,21 +512,14 @@ static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt) if (pkt->stream_index == mp3->audio_stream_idx) { if (mp3->pics_to_write) { /* buffer audio packets until we get all the pictures */ - AVPacketList *pktl = av_mallocz(sizeof(*pktl)); + int ret = ff_packet_list_put(&mp3->queue, &mp3->queue_end, pkt, FF_PACKETLIST_FLAG_REF_PACKET); - if (!pktl || av_packet_ref(&pktl->pkt, pkt) < 0) { - av_freep(&pktl); + if (ret < 0) { av_log(s, AV_LOG_WARNING, "Not enough memory to buffer audio. Skipping picture streams\n"); mp3->pics_to_write = 0; mp3_queue_flush(s); return mp3_write_audio_packet(s, pkt); } - - if (mp3->queue_end) - mp3->queue_end->next = pktl; - else - mp3->queue = pktl; - mp3->queue_end = pktl; } else return mp3_write_audio_packet(s, pkt); } else { From fefe47b70101ea1cb4f7752ede168d883507a5aa Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 4 Apr 2018 00:43:01 -0300 Subject: [PATCH 2372/2557] avcodec/clearvideo: fix mixed code and declarations Signed-off-by: James Almer --- libavcodec/clearvideo.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavcodec/clearvideo.c b/libavcodec/clearvideo.c index 269370ee6543c..9319cac0af2cc 100644 --- a/libavcodec/clearvideo.c +++ b/libavcodec/clearvideo.c @@ -296,6 +296,7 @@ static int copyadd_block(AVCodecContext *avctx, AVFrame *dst, AVFrame *src, static MV mvi_predict(MVInfo *mvi, int mb_x, int mb_y, MV diff) { MV res, pred_mv; + int left_mv, right_mv, top_mv, bot_mv; if (mvi->top) { if (mb_x > 0) { @@ -315,16 +316,16 @@ static MV mvi_predict(MVInfo *mvi, int mb_x, int mb_y, MV diff) res = pred_mv; - int left_mv = -((mb_x * mvi->mb_size)); - int right_mv = ((mvi->mb_w - mb_x - 1) * mvi->mb_size); + left_mv = -((mb_x * mvi->mb_size)); + right_mv = ((mvi->mb_w - mb_x - 1) * mvi->mb_size); if (res.x < left_mv) { res.x = left_mv; } if (res.x > right_mv) { res.x = right_mv; } - int top_mv = -((mb_y * mvi->mb_size)); - int bot_mv = ((mvi->mb_h - mb_y - 1) * mvi->mb_size); + top_mv = -((mb_y * mvi->mb_size)); + bot_mv = ((mvi->mb_h - mb_y - 1) * mvi->mb_size); if (res.y < top_mv) { res.y = top_mv; } From a866cc3ad3fba0b47268f7f5256dde8fc67045c4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 4 Apr 2018 00:43:40 -0300 Subject: [PATCH 2373/2557] avcodec/mpeg4videodec: free studio profile VLCs when closing the decoder Fixes memleaks. Signed-off-by: James Almer --- libavcodec/mpeg4videodec.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index f53bd03bf127a..53ad218cb7add 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -3375,6 +3375,20 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } +static av_cold int decode_end(AVCodecContext *avctx) +{ + Mpeg4DecContext *ctx = avctx->priv_data; + int i; + + for (i = 0; i < 12; i++) + ff_free_vlc(&ctx->studio_intra_tab[i]); + + ff_free_vlc(&ctx->studio_luma_dc); + ff_free_vlc(&ctx->studio_chroma_dc); + + return ff_h263_decode_end(avctx); +} + static const AVOption mpeg4_options[] = { {"quarter_sample", "1/4 subpel MC", offsetof(MpegEncContext, quarter_sample), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, 0}, {"divx_packed", "divx style packed b frames", offsetof(MpegEncContext, divx_packed), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, 0}, @@ -3395,7 +3409,7 @@ AVCodec ff_mpeg4_decoder = { .id = AV_CODEC_ID_MPEG4, .priv_data_size = sizeof(Mpeg4DecContext), .init = decode_init, - .close = ff_h263_decode_end, + .close = decode_end, .decode = ff_h263_decode_frame, .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY | From 2accdd3871a1f8c6ce0cf3f0e89fb04c47cc7148 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 4 Apr 2018 01:47:12 -0300 Subject: [PATCH 2374/2557] avcodec/libaomdec: fix broken pix_fmt changes from the previous commit Signed-off-by: James Almer --- libavcodec/libaomdec.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index 9991af96c8020..6a2de6d47a760 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -103,11 +103,13 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) avctx->profile = FF_PROFILE_AV1_MAIN; return 0; } else if (img->bit_depth == 10) { - avctx->pix_fmt = AV_PIX_FMT_YUV420P10; + avctx->pix_fmt = img->monochrome ? + AV_PIX_FMT_GRAY10 : AV_PIX_FMT_YUV420P10; avctx->profile = FF_PROFILE_AV1_MAIN; return 0; } else if (img->bit_depth == 12) { - avctx->pix_fmt = AV_PIX_FMT_YUV420P12; + avctx->pix_fmt = img->monochrome ? + AV_PIX_FMT_GRAY12 : AV_PIX_FMT_YUV420P12; avctx->profile = FF_PROFILE_AV1_PROFESSIONAL; return 0; } else { @@ -116,8 +118,7 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) case AOM_IMG_FMT_I422: case AOM_IMG_FMT_I42216: if (img->bit_depth == 8) { - avctx->pix_fmt = img->monochrome ? - AV_PIX_FMT_GRAY10 : AV_PIX_FMT_YUV420P10; + avctx->pix_fmt = AV_PIX_FMT_YUV422P; avctx->profile = FF_PROFILE_AV1_PROFESSIONAL; return 0; } else if (img->bit_depth == 10) { @@ -134,8 +135,7 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) case AOM_IMG_FMT_I444: case AOM_IMG_FMT_I44416: if (img->bit_depth == 8) { - avctx->pix_fmt = img->monochrome ? - AV_PIX_FMT_GRAY12 : AV_PIX_FMT_YUV420P12; + avctx->pix_fmt = AV_PIX_FMT_YUV444P; avctx->profile = FF_PROFILE_AV1_HIGH; return 0; } else if (img->bit_depth == 10) { From 2f0e0deadc4ead545c9042ed4c19211a2daa235a Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 4 Apr 2018 10:54:14 -0300 Subject: [PATCH 2375/2557] avformat/matroskadec: address a missing AVPacket free Fixes memleaks. Signed-off-by: James Almer --- libavformat/matroskadec.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 3e5b537ac430f..a616fb3241793 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -3152,7 +3152,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, MatroskaTrackEncoding *encodings = track->encodings.elem; uint8_t *pkt_data = data; int offset = 0, res; - AVPacket *pkt; + AVPacket pktl, *pkt = &pktl; if (encodings && !encodings->type && encodings->scope & 1) { res = matroska_decode_buffer(&pkt_data, &pkt_size, track); @@ -3177,15 +3177,8 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, AV_RB32(&data[4]) != MKBETAG('i', 'c', 'p', 'f')) offset = 8; - pkt = av_mallocz(sizeof(AVPacket)); - if (!pkt) { - if (pkt_data != data) - av_freep(&pkt_data); - return AVERROR(ENOMEM); - } /* XXX: prevent data copy... */ if (av_new_packet(pkt, pkt_size + offset) < 0) { - av_free(pkt); res = AVERROR(ENOMEM); goto fail; } @@ -3210,7 +3203,6 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, additional_size + 8); if (!side_data) { av_packet_unref(pkt); - av_free(pkt); return AVERROR(ENOMEM); } AV_WB64(side_data, additional_id); @@ -3223,7 +3215,6 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, 10); if (!side_data) { av_packet_unref(pkt); - av_free(pkt); return AVERROR(ENOMEM); } discard_padding = av_rescale_q(discard_padding, @@ -3253,7 +3244,7 @@ FF_ENABLE_DEPRECATION_WARNINGS res = ff_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, 0); if (res < 0) { - av_packet_free(&pkt); + av_packet_unref(pkt); return AVERROR(ENOMEM); } From 2f273701119f5ec9534f4327f9f1471728518628 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 4 Apr 2018 11:06:55 -0300 Subject: [PATCH 2376/2557] avcodec/mpeg4videodec: unbreak multithreading decoding Should fix double free related crashes. Signed-off-by: James Almer --- libavcodec/mpeg4videodec.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 53ad218cb7add..32eb3d1ca8d67 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -3380,11 +3380,13 @@ static av_cold int decode_end(AVCodecContext *avctx) Mpeg4DecContext *ctx = avctx->priv_data; int i; - for (i = 0; i < 12; i++) - ff_free_vlc(&ctx->studio_intra_tab[i]); + if (!avctx->internal->is_copy) { + for (i = 0; i < 12; i++) + ff_free_vlc(&ctx->studio_intra_tab[i]); - ff_free_vlc(&ctx->studio_luma_dc); - ff_free_vlc(&ctx->studio_chroma_dc); + ff_free_vlc(&ctx->studio_luma_dc); + ff_free_vlc(&ctx->studio_chroma_dc); + } return ff_h263_decode_end(avctx); } From 4f55b94663cf1eeb00ca23e0fe89766ad081f811 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 4 Apr 2018 13:53:12 -0300 Subject: [PATCH 2377/2557] avformat/matroskadec: address some more missing AVPacket frees Fixes memleaks. Signed-off-by: James Almer --- libavformat/matroskadec.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index a616fb3241793..6156c2f9b4fbd 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -2913,13 +2913,10 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, while (track->audio.pkt_cnt) { int ret; - AVPacket *pkt = av_mallocz(sizeof(AVPacket)); - if (!pkt) - return AVERROR(ENOMEM); + AVPacket pktl, *pkt = &pktl; ret = av_new_packet(pkt, a); if (ret < 0) { - av_free(pkt); return ret; } memcpy(pkt->data, @@ -2931,7 +2928,7 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, pkt->stream_index = st->index; ret = ff_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, 0); if (ret < 0) { - av_packet_free(&pkt); + av_packet_unref(pkt); return AVERROR(ENOMEM); } } @@ -3028,7 +3025,7 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, uint64_t duration, int64_t pos) { - AVPacket *pkt; + AVPacket pktl, *pkt = &pktl; uint8_t *id, *settings, *text, *buf; int id_len, settings_len, text_len; uint8_t *p, *q; @@ -3085,12 +3082,8 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, if (text_len <= 0) return AVERROR_INVALIDDATA; - pkt = av_mallocz(sizeof(*pkt)); - if (!pkt) - return AVERROR(ENOMEM); err = av_new_packet(pkt, text_len); if (err < 0) { - av_free(pkt); return err; } @@ -3102,7 +3095,6 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, id_len); if (!buf) { av_packet_unref(pkt); - av_free(pkt); return AVERROR(ENOMEM); } memcpy(buf, id, id_len); @@ -3114,7 +3106,6 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, settings_len); if (!buf) { av_packet_unref(pkt); - av_free(pkt); return AVERROR(ENOMEM); } memcpy(buf, settings, settings_len); @@ -3134,7 +3125,7 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, err = ff_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, 0); if (err < 0) { - av_packet_free(&pkt); + av_packet_unref(pkt); return AVERROR(ENOMEM); } From 94d831f3886a7d5d207b9224cd52d11e22d0e8f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 2 Apr 2018 11:36:56 +0300 Subject: [PATCH 2378/2557] ffmpeg: allow setting attached_pic disposition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is used to signal that image should be stored in metadata as cover image. Signed-off-by: Timo Teräs Signed-off-by: Michael Niedermayer --- fftools/ffmpeg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 2f8a5ace568ea..4dbe72186df64 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3561,6 +3561,7 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len) { "hearing_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_HEARING_IMPAIRED }, .unit = "flags" }, { "visual_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_VISUAL_IMPAIRED }, .unit = "flags" }, { "clean_effects" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS }, .unit = "flags" }, + { "attached_pic" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ATTACHED_PIC }, .unit = "flags" }, { "captions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS }, .unit = "flags" }, { "descriptions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, .unit = "flags" }, { "dependent" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEPENDENT }, .unit = "flags" }, From 53688b62ca96ad9a3b0e7d201caca61c79a68648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 2 Apr 2018 11:36:57 +0300 Subject: [PATCH 2379/2557] avformat/movenc: add rtp_hinting_needed() helper function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is shared test and this simplifies code a bit. Follow up commit will have additional tests for this function. Signed-off-by: Timo Teräs Signed-off-by: Michael Niedermayer --- libavformat/movenc.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index ef668eccd5003..bd275259ca8ab 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -140,6 +140,13 @@ static int co64_required(const MOVTrack *track) return 0; } +static int rtp_hinting_needed(const AVStream *st) +{ + /* Add hint tracks for each audio and video stream */ + return st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || + st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO; +} + /* Chunk offset atom */ static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track) { @@ -5941,14 +5948,9 @@ static int mov_init(AVFormatContext *s) mov->chapter_track = mov->nb_streams++; if (mov->flags & FF_MOV_FLAG_RTP_HINT) { - /* Add hint tracks for each audio and video stream */ - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || - st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + for (i = 0; i < s->nb_streams; i++) + if (rtp_hinting_needed(s->streams[i])) mov->nb_streams++; - } - } } if ( mov->write_tmcd == -1 && (mov->mode == MODE_MOV || mov->mode == MODE_MP4) @@ -6171,15 +6173,10 @@ static int mov_write_header(AVFormatContext *s) nb_tracks++; if (mov->flags & FF_MOV_FLAG_RTP_HINT) { - /* Add hint tracks for each audio and video stream */ hint_track = nb_tracks; - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || - st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + for (i = 0; i < s->nb_streams; i++) + if (rtp_hinting_needed(s->streams[i])) nb_tracks++; - } - } } if (mov->mode == MODE_MOV || mov->mode == MODE_MP4) @@ -6257,11 +6254,8 @@ static int mov_write_header(AVFormatContext *s) return ret; if (mov->flags & FF_MOV_FLAG_RTP_HINT) { - /* Initialize the hint tracks for each audio and video stream */ for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || - st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (rtp_hinting_needed(s->streams[i])) { if ((ret = ff_mov_init_hinting(s, hint_track, i)) < 0) return ret; hint_track++; From b0958698ea2b976063cb1d683becc213040c709b Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 4 Apr 2018 20:12:41 -0300 Subject: [PATCH 2380/2557] libaom: remove references to RGB pixfmts Support for it was apparently never in the codebase, and the enum values were recently removed from the public headers [1] Fixes build with latest libaom build. [1] https://aomedia.googlesource.com/aom/+/3f29cc20e3a4c348cb41a797c68de856ddb84e12 Signed-off-by: James Almer --- libavcodec/libaom.c | 44 -------------------------------------------- 1 file changed, 44 deletions(-) diff --git a/libavcodec/libaom.c b/libavcodec/libaom.c index f083129f4b8d3..512095b339714 100644 --- a/libavcodec/libaom.c +++ b/libavcodec/libaom.c @@ -38,28 +38,6 @@ case AOM_IMG_FMT_I ## fmt ## 16: \ enum AVPixelFormat ff_aom_imgfmt_to_pixfmt(aom_img_fmt_t img, int depth) { switch (img) { - case AOM_IMG_FMT_RGB24: - return AV_PIX_FMT_RGB24; - case AOM_IMG_FMT_RGB565: - return AV_PIX_FMT_RGB565BE; - case AOM_IMG_FMT_RGB555: - return AV_PIX_FMT_RGB555BE; - case AOM_IMG_FMT_UYVY: - return AV_PIX_FMT_UYVY422; - case AOM_IMG_FMT_YUY2: - return AV_PIX_FMT_YUYV422; - case AOM_IMG_FMT_YVYU: - return AV_PIX_FMT_YVYU422; - case AOM_IMG_FMT_BGR24: - return AV_PIX_FMT_BGR24; - case AOM_IMG_FMT_ARGB: - return AV_PIX_FMT_ARGB; - case AOM_IMG_FMT_ARGB_LE: - return AV_PIX_FMT_BGRA; - case AOM_IMG_FMT_RGB565_LE: - return AV_PIX_FMT_RGB565LE; - case AOM_IMG_FMT_RGB555_LE: - return AV_PIX_FMT_RGB555LE; case AOM_IMG_FMT_I420: return AV_PIX_FMT_YUV420P; case AOM_IMG_FMT_I422: @@ -81,28 +59,6 @@ enum AVPixelFormat ff_aom_imgfmt_to_pixfmt(aom_img_fmt_t img, int depth) aom_img_fmt_t ff_aom_pixfmt_to_imgfmt(enum AVPixelFormat pix) { switch (pix) { - case AV_PIX_FMT_RGB24: - return AOM_IMG_FMT_RGB24; - case AV_PIX_FMT_RGB565BE: - return AOM_IMG_FMT_RGB565; - case AV_PIX_FMT_RGB555BE: - return AOM_IMG_FMT_RGB555; - case AV_PIX_FMT_UYVY422: - return AOM_IMG_FMT_UYVY; - case AV_PIX_FMT_YUYV422: - return AOM_IMG_FMT_YUY2; - case AV_PIX_FMT_YVYU422: - return AOM_IMG_FMT_YVYU; - case AV_PIX_FMT_BGR24: - return AOM_IMG_FMT_BGR24; - case AV_PIX_FMT_ARGB: - return AOM_IMG_FMT_ARGB; - case AV_PIX_FMT_BGRA: - return AOM_IMG_FMT_ARGB_LE; - case AV_PIX_FMT_RGB565LE: - return AOM_IMG_FMT_RGB565_LE; - case AV_PIX_FMT_RGB555LE: - return AOM_IMG_FMT_RGB555_LE; case AV_PIX_FMT_YUV420P: return AOM_IMG_FMT_I420; case AV_PIX_FMT_YUV422P: From 709e0291d659d089527ec7c048f9b2608183df64 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 4 Apr 2018 18:07:03 +0200 Subject: [PATCH 2381/2557] avcodec/decode: fix warning when decoding pseudo paletted formats The pseudo palette allocation is optional now. But if it's still allocated (like the internal get_buffer2 implementation does, for compatibility), it shouldn't print a warning. --- libavcodec/decode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index d883a5f9fc7fb..421a8f1a3570e 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1779,6 +1779,8 @@ static void validate_avframe_allocation(AVCodecContext *avctx, AVFrame *frame) int flags = desc ? desc->flags : 0; if (num_planes == 1 && (flags & AV_PIX_FMT_FLAG_PAL)) num_planes = 2; + if ((flags & FF_PSEUDOPAL) && frame->data[1]) + num_planes = 2; for (i = 0; i < num_planes; i++) { av_assert0(frame->data[i]); } From a2356e509184d79ba477ce774bb7be8b6b66f692 Mon Sep 17 00:00:00 2001 From: Lou Logan Date: Thu, 5 Apr 2018 10:00:42 -0800 Subject: [PATCH 2382/2557] doc/developer: update link to "sign-off" info Found by Hendrik Schreiber. Signed-off-by: Lou Logan --- doc/developer.texi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/developer.texi b/doc/developer.texi index 66b24633063f7..0fc9c3f21c8ba 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -562,9 +562,9 @@ Does @code{make fate} pass with the patch applied? Was the patch generated with git format-patch or send-email? @item -Did you sign off your patch? (git commit -s) -See @url{http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob_plain;f=Documentation/SubmittingPatches} for the meaning -of sign off. +Did you sign-off your patch? (@code{git commit -s}) +See @uref{https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/Documentation/process/submitting-patches.rst, Sign your work} for the meaning +of @dfn{sign-off}. @item Did you provide a clear git commit log message? From b08c132a9c590cf5c3905a48b12527765fc91647 Mon Sep 17 00:00:00 2001 From: Jacob Trimble Date: Wed, 4 Apr 2018 12:30:56 -0700 Subject: [PATCH 2383/2557] avformat/mov: Fix parsing of tfdt when using sample descriptors. Signed-off-by: Jacob Trimble Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index e7c32e6148062..97b1462aabeeb 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4601,7 +4601,7 @@ static int mov_read_tfdt(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR_INVALIDDATA; } sc = st->priv_data; - if (sc->pseudo_stream_id + 1 != frag->stsd_id) + if (sc->pseudo_stream_id + 1 != frag->stsd_id && sc->pseudo_stream_id != -1) return 0; version = avio_r8(pb); avio_rb24(pb); /* flags */ From 67fd8df4197e50720223f9715594a1fa31f48b54 Mon Sep 17 00:00:00 2001 From: Valery Kot Date: Fri, 16 Mar 2018 14:50:34 +0100 Subject: [PATCH 2384/2557] avcodec/openh264enc.c: generate IDR frame in response to I frame pict_type Signed-off-by: Valery Kot --- libavcodec/libopenh264enc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index fdadb101f513a..83c3f0ce208cb 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -246,6 +246,10 @@ static int svc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, sp.iPicWidth = avctx->width; sp.iPicHeight = avctx->height; + if (frame->pict_type == AV_PICTURE_TYPE_I) { + (*s->encoder)->ForceIntraFrame(s->encoder, true); + } + encoded = (*s->encoder)->EncodeFrame(s->encoder, &sp, &fbi); if (encoded != cmResultSuccess) { av_log(avctx, AV_LOG_ERROR, "EncodeFrame failed\n"); From 8eb0bb11083320cc12bcc23104a384984c4a9d64 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 17 Mar 2018 19:24:49 +0100 Subject: [PATCH 2385/2557] avfilter/x86/vf_blend : reorganize DIFFERENCE macro to reduce line duplication between 8bit and 16 bit version --- libavfilter/x86/vf_blend.asm | 38 +++++++++++++++--------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/libavfilter/x86/vf_blend.asm b/libavfilter/x86/vf_blend.asm index 5d9a90919295e..9cd5ee7acbf8a 100644 --- a/libavfilter/x86/vf_blend.asm +++ b/libavfilter/x86/vf_blend.asm @@ -295,8 +295,9 @@ BLEND_INIT %1, 4, %3 BLEND_END %endmacro -%macro DIFFERENCE 1-2 -BLEND_INIT %1, 5, %2 +; %1 name , %2 src (b or w), %3 inter (w or d), %4 (1 if 16bit, not set if 8 bit) +%macro DIFFERENCE 3-4 +BLEND_INIT %1, 5, %4 pxor m2, m2 .nextrow: mov xq, widthq @@ -304,26 +305,19 @@ BLEND_INIT %1, 5, %2 .loop: movu m0, [topq + xq] movu m1, [bottomq + xq] -%if %0 == 2 ; 16 bit - punpckhwd m3, m0, m2 - punpcklwd m0, m2 - punpckhwd m4, m1, m2 - punpcklwd m1, m2 - psubd m0, m1 - psubd m3, m4 + punpckh%2%3 m3, m0, m2 + punpckl%2%3 m0, m2 + punpckh%2%3 m4, m1, m2 + punpckl%2%3 m1, m2 + psub%3 m0, m1 + psub%3 m3, m4 +%if %0 == 4; 16 bit pabsd m0, m0 pabsd m3, m3 - packusdw m0, m3 %else - punpckhbw m3, m0, m2 - punpcklbw m0, m2 - punpckhbw m4, m1, m2 - punpcklbw m1, m2 - psubw m0, m1 - psubw m3, m4 ABS2 m0, m3, m1, m4 - packuswb m0, m3 %endif + packus%3%2 m0, m3 mova [dstq + xq], m0 add xq, mmsize jl .loop @@ -397,7 +391,7 @@ AVERAGE GRAINMERGE HARDMIX PHOENIX phoenix, b -DIFFERENCE difference +DIFFERENCE difference, b, w DIVIDE BLEND_ABS @@ -411,7 +405,7 @@ BLEND_SIMPLE xor_16, xor, 1 %endif INIT_XMM ssse3 -DIFFERENCE difference +DIFFERENCE difference, b, w BLEND_ABS INIT_XMM sse4 @@ -419,7 +413,7 @@ INIT_XMM sse4 BLEND_SIMPLE darken_16, minuw, 1 BLEND_SIMPLE lighten_16, maxuw, 1 PHOENIX phoenix_16, w, 1 -DIFFERENCE difference_16, 1 +DIFFERENCE difference_16, w, d, 1 %endif %if HAVE_AVX2_EXTERNAL @@ -439,7 +433,7 @@ GRAINMERGE HARDMIX PHOENIX phoenix, b -DIFFERENCE difference +DIFFERENCE difference, b, w BLEND_ABS %if ARCH_X86_64 @@ -451,6 +445,6 @@ BLEND_SIMPLE or_16, or, 1 BLEND_SIMPLE subtract_16, subusw, 1 BLEND_SIMPLE xor_16, xor, 1 PHOENIX phoenix_16, w, 1 -DIFFERENCE difference_16, 1 +DIFFERENCE difference_16, w, d, 1 %endif %endif From f3df42e81d367547756e7955e36c8af7c9c18db2 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 17 Mar 2018 19:37:06 +0100 Subject: [PATCH 2386/2557] avfilter/x86/vf_blend : add SIMD for 16 bit version of grainextract grainmerge average extremity negation --- libavfilter/x86/vf_blend.asm | 168 ++++++++++++++++++++------------ libavfilter/x86/vf_blend_init.c | 20 ++++ 2 files changed, 128 insertions(+), 60 deletions(-) diff --git a/libavfilter/x86/vf_blend.asm b/libavfilter/x86/vf_blend.asm index 9cd5ee7acbf8a..251bbb5a1206f 100644 --- a/libavfilter/x86/vf_blend.asm +++ b/libavfilter/x86/vf_blend.asm @@ -27,6 +27,8 @@ SECTION_RODATA ps_255: times 4 dd 255.0 +pd_32768 : times 4 dd 32768 +pd_65535 : times 4 dd 65535 pw_1: times 8 dw 1 pw_128: times 8 dw 128 pw_255: times 8 dw 255 @@ -79,26 +81,33 @@ BLEND_INIT %1, 2, %3 BLEND_END %endmacro -%macro GRAINEXTRACT 0 -BLEND_INIT grainextract, 6 +; %1 name , %2 src (b or w), %3 inter (w or d), %4 (1 if 16bit, not set if 8 bit) +%macro GRAINEXTRACT 3-4 +BLEND_INIT %1, 6, %4 pxor m4, m4 +%if %0 == 4 ; 16 bit + VBROADCASTI128 m5, [pd_32768] +%else VBROADCASTI128 m5, [pw_128] +%endif .nextrow: mov xq, widthq .loop: movu m1, [topq + xq] movu m3, [bottomq + xq] - punpcklbw m0, m1, m4 - punpckhbw m1, m4 - punpcklbw m2, m3, m4 - punpckhbw m3, m4 - paddw m0, m5 - paddw m1, m5 - psubw m0, m2 - psubw m1, m3 + punpckl%2%3 m0, m1, m4 + punpckh%2%3 m1, m4 + punpckl%2%3 m2, m3, m4 + punpckh%2%3 m3, m4 + + padd%3 m0, m5 + padd%3 m1, m5 + psub%3 m0, m2 + psub%3 m1, m3 + + packus%3%2 m0, m1 - packuswb m0, m1 mova [dstq + xq], m0 add xq, mmsize jl .loop @@ -172,8 +181,9 @@ BLEND_INIT screen, 7 BLEND_END %endmacro -%macro AVERAGE 0 -BLEND_INIT average, 3 +;%1 name, %2 (b or w), %3 (set if 16 bit) +%macro AVERAGE 2-3 +BLEND_INIT %1, 3, %3 pcmpeqb m2, m2 .nextrow: @@ -184,7 +194,7 @@ BLEND_INIT average, 3 movu m1, [bottomq + xq] pxor m0, m2 pxor m1, m2 - pavgb m0, m1 + pavg%2 m0, m1 pxor m0, m2 mova [dstq + xq], m0 add xq, mmsize @@ -192,29 +202,34 @@ BLEND_INIT average, 3 BLEND_END %endmacro - -%macro GRAINMERGE 0 -BLEND_INIT grainmerge, 6 +; %1 name , %2 src (b or w), %3 inter (w or d), %4 (1 if 16bit, not set if 8 bit) +%macro GRAINMERGE 3-4 +BLEND_INIT %1, 6, %4 pxor m4, m4 - +%if %0 == 4 ; 16 bit + VBROADCASTI128 m5, [pd_32768] +%else VBROADCASTI128 m5, [pw_128] +%endif .nextrow: mov xq, widthq .loop: movu m1, [topq + xq] movu m3, [bottomq + xq] - punpcklbw m0, m1, m4 - punpckhbw m1, m4 - punpcklbw m2, m3, m4 - punpckhbw m3, m4 - paddw m0, m2 - paddw m1, m3 - psubw m0, m5 - psubw m1, m5 + punpckl%2%3 m0, m1, m4 + punpckh%2%3 m1, m4 + punpckl%2%3 m2, m3, m4 + punpckh%2%3 m3, m4 + + padd%3 m0, m2 + padd%3 m1, m3 + psub%3 m0, m5 + psub%3 m1, m5 + + packus%3%2 m0, m1 - packuswb m0, m1 mova [dstq + xq], m0 add xq, mmsize jl .loop @@ -324,52 +339,73 @@ BLEND_INIT %1, 5, %4 BLEND_END %endmacro -%macro BLEND_ABS 0 -BLEND_INIT extremity, 8 +; %1 name , %2 src (b or w), %3 inter (w or d), %4 (1 if 16bit, not set if 8 bit) +%macro EXTREMITY 3-4 +BLEND_INIT %1, 8, %4 pxor m2, m2 +%if %0 == 4; 16 bit + VBROADCASTI128 m4, [pd_65535] +%else VBROADCASTI128 m4, [pw_255] +%endif .nextrow: mov xq, widthq .loop: movu m0, [topq + xq] movu m1, [bottomq + xq] - punpckhbw m5, m0, m2 - punpcklbw m0, m2 - punpckhbw m6, m1, m2 - punpcklbw m1, m2 - psubw m3, m4, m0 - psubw m7, m4, m5 - psubw m3, m1 - psubw m7, m6 + punpckh%2%3 m5, m0, m2 + punpckl%2%3 m0, m2 + punpckh%2%3 m6, m1, m2 + punpckl%2%3 m1, m2 + psub%3 m3, m4, m0 + psub%3 m7, m4, m5 + psub%3 m3, m1 + psub%3 m7, m6 +%if %0 == 4; 16 bit + pabsd m3, m3 + pabsd m7, m7 +%else ABS2 m3, m7, m1, m6 - packuswb m3, m7 +%endif + packus%3%2 m3, m7 mova [dstq + xq], m3 add xq, mmsize jl .loop BLEND_END +%endmacro -BLEND_INIT negation, 8 +%macro NEGATION 3-4 +BLEND_INIT %1, 8, %4 pxor m2, m2 +%if %0 == 4; 16 bit + VBROADCASTI128 m4, [pd_65535] +%else VBROADCASTI128 m4, [pw_255] +%endif .nextrow: mov xq, widthq .loop: movu m0, [topq + xq] movu m1, [bottomq + xq] - punpckhbw m5, m0, m2 - punpcklbw m0, m2 - punpckhbw m6, m1, m2 - punpcklbw m1, m2 - psubw m3, m4, m0 - psubw m7, m4, m5 - psubw m3, m1 - psubw m7, m6 + punpckh%2%3 m5, m0, m2 + punpckl%2%3 m0, m2 + punpckh%2%3 m6, m1, m2 + punpckl%2%3 m1, m2 + psub%3 m3, m4, m0 + psub%3 m7, m4, m5 + psub%3 m3, m1 + psub%3 m7, m6 +%if %0 == 4; 16 bit + pabsd m3, m3 + pabsd m7, m7 +%else ABS2 m3, m7, m1, m6 - psubw m0, m4, m3 - psubw m1, m4, m7 - packuswb m0, m1 +%endif + psub%3 m0, m4, m3 + psub%3 m1, m4, m7 + packus%3%2 m0, m1 mova [dstq + xq], m0 add xq, mmsize jl .loop @@ -384,17 +420,17 @@ BLEND_SIMPLE addition, addusb BLEND_SIMPLE subtract, subusb BLEND_SIMPLE darken, minub BLEND_SIMPLE lighten, maxub -GRAINEXTRACT +GRAINEXTRACT grainextract, b, w BLEND_MULTIPLY BLEND_SCREEN -AVERAGE -GRAINMERGE +AVERAGE average, b +GRAINMERGE grainmerge, b, w HARDMIX PHOENIX phoenix, b DIFFERENCE difference, b, w DIVIDE - -BLEND_ABS +EXTREMITY extremity, b, w +NEGATION negation, b, w %if ARCH_X86_64 BLEND_SIMPLE addition_16, addusw, 1 @@ -402,18 +438,24 @@ BLEND_SIMPLE and_16, and, 1 BLEND_SIMPLE or_16, or, 1 BLEND_SIMPLE subtract_16, subusw, 1 BLEND_SIMPLE xor_16, xor, 1 +AVERAGE average_16, w, 1 %endif INIT_XMM ssse3 DIFFERENCE difference, b, w -BLEND_ABS +EXTREMITY extremity, b, w +NEGATION negation, b, w INIT_XMM sse4 %if ARCH_X86_64 BLEND_SIMPLE darken_16, minuw, 1 BLEND_SIMPLE lighten_16, maxuw, 1 +GRAINEXTRACT grainextract_16, w, d, 1 +GRAINMERGE grainmerge_16, w, d, 1 PHOENIX phoenix_16, w, 1 DIFFERENCE difference_16, w, d, 1 +EXTREMITY extremity_16, w, d, 1 +NEGATION negation_16, w, d, 1 %endif %if HAVE_AVX2_EXTERNAL @@ -425,16 +467,17 @@ BLEND_SIMPLE addition, addusb BLEND_SIMPLE subtract, subusb BLEND_SIMPLE darken, minub BLEND_SIMPLE lighten, maxub -GRAINEXTRACT +GRAINEXTRACT grainextract, b, w BLEND_MULTIPLY BLEND_SCREEN -AVERAGE -GRAINMERGE +AVERAGE average, b +GRAINMERGE grainmerge, b, w HARDMIX PHOENIX phoenix, b DIFFERENCE difference, b, w -BLEND_ABS +EXTREMITY extremity, b, w +NEGATION negation, b, w %if ARCH_X86_64 BLEND_SIMPLE addition_16, addusw, 1 @@ -444,7 +487,12 @@ BLEND_SIMPLE lighten_16, maxuw, 1 BLEND_SIMPLE or_16, or, 1 BLEND_SIMPLE subtract_16, subusw, 1 BLEND_SIMPLE xor_16, xor, 1 +GRAINEXTRACT grainextract_16, w, d, 1 +AVERAGE average_16, w, 1 +GRAINMERGE grainmerge_16, w, d, 1 PHOENIX phoenix_16, w, 1 DIFFERENCE difference_16, w, d, 1 +EXTREMITY extremity_16, w, d, 1 +NEGATION negation_16, w, d, 1 %endif %endif diff --git a/libavfilter/x86/vf_blend_init.c b/libavfilter/x86/vf_blend_init.c index 0962f6d7fdc4a..acf28559ff7be 100644 --- a/libavfilter/x86/vf_blend_init.c +++ b/libavfilter/x86/vf_blend_init.c @@ -72,12 +72,22 @@ BLEND_FUNC(negation, avx2) #if ARCH_X86_64 BLEND_FUNC(addition_16, sse2) BLEND_FUNC(addition_16, avx2) +BLEND_FUNC(grainmerge_16, sse4) +BLEND_FUNC(grainmerge_16, avx2) +BLEND_FUNC(average_16, sse2) +BLEND_FUNC(average_16, avx2) BLEND_FUNC(and_16, sse2) BLEND_FUNC(and_16, avx2) BLEND_FUNC(darken_16, sse4) BLEND_FUNC(darken_16, avx2) +BLEND_FUNC(grainextract_16, sse4) +BLEND_FUNC(grainextract_16, avx2) BLEND_FUNC(difference_16, sse4) BLEND_FUNC(difference_16, avx2) +BLEND_FUNC(extremity_16, sse4) +BLEND_FUNC(extremity_16, avx2) +BLEND_FUNC(negation_16, sse4) +BLEND_FUNC(negation_16, avx2) BLEND_FUNC(lighten_16, sse4) BLEND_FUNC(lighten_16, avx2) BLEND_FUNC(or_16, sse2) @@ -152,6 +162,7 @@ av_cold void ff_blend_init_x86(FilterParams *param, int is_16bit) switch (param->mode) { case BLEND_ADDITION: param->blend = ff_blend_addition_16_sse2; break; case BLEND_AND: param->blend = ff_blend_and_16_sse2; break; + case BLEND_AVERAGE: param->blend = ff_blend_average_16_sse2; break; case BLEND_OR: param->blend = ff_blend_or_16_sse2; break; case BLEND_SUBTRACT: param->blend = ff_blend_subtract_16_sse2; break; case BLEND_XOR: param->blend = ff_blend_xor_16_sse2; break; @@ -159,8 +170,12 @@ av_cold void ff_blend_init_x86(FilterParams *param, int is_16bit) } if (EXTERNAL_SSE4(cpu_flags) && param->opacity == 1) { switch (param->mode) { + case BLEND_GRAINMERGE: param->blend = ff_blend_grainmerge_16_sse4; break; case BLEND_DARKEN: param->blend = ff_blend_darken_16_sse4; break; + case BLEND_GRAINEXTRACT: param->blend = ff_blend_grainextract_16_sse4; break; case BLEND_DIFFERENCE: param->blend = ff_blend_difference_16_sse4; break; + case BLEND_EXTREMITY: param->blend = ff_blend_extremity_16_sse4; break; + case BLEND_NEGATION: param->blend = ff_blend_negation_16_sse4; break; case BLEND_LIGHTEN: param->blend = ff_blend_lighten_16_sse4; break; case BLEND_PHOENIX: param->blend = ff_blend_phoenix_16_sse4; break; } @@ -168,9 +183,14 @@ av_cold void ff_blend_init_x86(FilterParams *param, int is_16bit) if (EXTERNAL_AVX2_FAST(cpu_flags) && param->opacity == 1) { switch (param->mode) { case BLEND_ADDITION: param->blend = ff_blend_addition_16_avx2; break; + case BLEND_GRAINMERGE: param->blend = ff_blend_grainmerge_16_avx2; break; case BLEND_AND: param->blend = ff_blend_and_16_avx2; break; + case BLEND_AVERAGE: param->blend = ff_blend_average_16_avx2; break; case BLEND_DARKEN: param->blend = ff_blend_darken_16_avx2; break; + case BLEND_GRAINEXTRACT: param->blend = ff_blend_grainextract_16_avx2; break; case BLEND_DIFFERENCE: param->blend = ff_blend_difference_16_avx2; break; + case BLEND_EXTREMITY: param->blend = ff_blend_extremity_16_avx2; break; + case BLEND_NEGATION: param->blend = ff_blend_negation_16_avx2; break; case BLEND_LIGHTEN: param->blend = ff_blend_lighten_16_avx2; break; case BLEND_OR: param->blend = ff_blend_or_16_avx2; break; case BLEND_PHOENIX: param->blend = ff_blend_phoenix_16_avx2; break; From 595505083a0211eab97528331125ad28718e8938 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Sat, 17 Mar 2018 19:37:46 +0100 Subject: [PATCH 2387/2557] checkasm/vf_blend : add test for 16 bit version of grainextract grainmerge average extremity negation --- tests/checkasm/vf_blend.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/checkasm/vf_blend.c b/tests/checkasm/vf_blend.c index 79bdf9f163d65..912f3a2c38b66 100644 --- a/tests/checkasm/vf_blend.c +++ b/tests/checkasm/vf_blend.c @@ -124,9 +124,14 @@ void checkasm_check_blend(void) report("8bit"); check_and_report(addition_16, BLEND_ADDITION, 2) + check_and_report(grainmerge_16, BLEND_GRAINMERGE, 2) check_and_report(and_16, BLEND_AND, 2) + check_and_report(average_16, BLEND_AVERAGE, 2) check_and_report(darken_16, BLEND_DARKEN, 2) + check_and_report(grainextract_16, BLEND_GRAINEXTRACT, 2) check_and_report(difference_16, BLEND_DIFFERENCE, 2) + check_and_report(extremity_16, BLEND_EXTREMITY, 2) + check_and_report(negation_16, BLEND_NEGATION, 2) check_and_report(lighten_16, BLEND_LIGHTEN, 2) check_and_report(or_16, BLEND_OR, 2) check_and_report(phoenix_16, BLEND_PHOENIX, 2) From 1425114af24d8402758ca11f7177d19a7f98df4d Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Thu, 5 Apr 2018 22:04:35 +0200 Subject: [PATCH 2388/2557] avcodec/prores_ks : do not call estimate_alpha at each quantification step also remove unused arg in estimate_alpha_plane Improve quality of Prores 4444 encoding --- libavcodec/proresenc_kostya.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c index 149dc81b3c799..06d5aa31e8431 100644 --- a/libavcodec/proresenc_kostya.c +++ b/libavcodec/proresenc_kostya.c @@ -712,10 +712,9 @@ static int est_alpha_diff(int cur, int prev, int abits) return dbits + 1; } -static int estimate_alpha_plane(ProresContext *ctx, int *error, +static int estimate_alpha_plane(ProresContext *ctx, const uint16_t *src, ptrdiff_t linesize, - int mbs_per_slice, int quant, - int16_t *blocks) + int mbs_per_slice, int16_t *blocks) { const int abits = ctx->alpha_bits; const int mask = (1 << abits) - 1; @@ -725,7 +724,6 @@ static int estimate_alpha_plane(ProresContext *ctx, int *error, int run = 0; int bits; - *error = 0; cur = blocks[idx++]; bits = est_alpha_diff(cur, prev, abits); prev = cur; @@ -774,6 +772,7 @@ static int find_slice_quant(AVCodecContext *avctx, int overquant; uint16_t *qmat; int linesize[4], line_add; + int alpha_bits = 0; if (ctx->pictures_per_frame == 1) line_add = 0; @@ -819,9 +818,12 @@ static int find_slice_quant(AVCodecContext *avctx, td->nodes[trellis_node + q].quant = q; } + if (ctx->alpha_bits) + alpha_bits = estimate_alpha_plane(ctx, src, linesize[3], + mbs_per_slice, td->blocks[3]); // todo: maybe perform coarser quantising to fit into frame size when needed for (q = min_quant; q <= max_quant; q++) { - bits = 0; + bits = alpha_bits; error = 0; for (i = 0; i < ctx->num_planes - !!ctx->alpha_bits; i++) { bits += estimate_slice_plane(ctx, &error, i, @@ -830,9 +832,6 @@ static int find_slice_quant(AVCodecContext *avctx, num_cblocks[i], plane_factor[i], ctx->quants[q], td); } - if (ctx->alpha_bits) - bits += estimate_alpha_plane(ctx, &error, src, linesize[3], - mbs_per_slice, q, td->blocks[3]); if (bits > 65000 * 8) error = SCORE_LIMIT; @@ -845,7 +844,7 @@ static int find_slice_quant(AVCodecContext *avctx, overquant = max_quant; } else { for (q = max_quant + 1; q < 128; q++) { - bits = 0; + bits = alpha_bits; error = 0; if (q < MAX_STORED_Q) { qmat = ctx->quants[q]; @@ -861,9 +860,6 @@ static int find_slice_quant(AVCodecContext *avctx, num_cblocks[i], plane_factor[i], qmat, td); } - if (ctx->alpha_bits) - bits += estimate_alpha_plane(ctx, &error, src, linesize[3], - mbs_per_slice, q, td->blocks[3]); if (bits <= ctx->bits_per_mb * mbs_per_slice) break; } From 187ff5a10864f16b7872eca722e844e8f04ec57b Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Mon, 2 Apr 2018 10:53:30 -0700 Subject: [PATCH 2389/2557] Add Sega FILM muxer Signed-off-by: Josh de Kock --- Changelog | 1 + doc/general.texi | 2 +- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/segafilmenc.c | 398 ++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 6 files changed, 403 insertions(+), 2 deletions(-) create mode 100644 libavformat/segafilmenc.c diff --git a/Changelog b/Changelog index 200866d8738d1..74c410a8e25e6 100644 --- a/Changelog +++ b/Changelog @@ -52,6 +52,7 @@ version : - E-AC-3 dependent frames support - bitstream filter for extracting E-AC-3 core - Haivision SRT protocol via libsrt +- segafilm muxer version 3.4: diff --git a/doc/general.texi b/doc/general.texi index 41c6a59e99529..2583006b14781 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -559,7 +559,7 @@ library: @item SAP @tab X @tab X @item SBG @tab @tab X @item SDP @tab @tab X -@item Sega FILM/CPK @tab @tab X +@item Sega FILM/CPK @tab X @tab X @tab Used in many Sega Saturn console games. @item Silicon Graphics Movie @tab @tab X @item Sierra SOL @tab @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index af0823a7db865..3eeca5091df5c 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -462,6 +462,7 @@ OBJS-$(CONFIG_SDR2_DEMUXER) += sdr2.o OBJS-$(CONFIG_SDS_DEMUXER) += sdsdec.o OBJS-$(CONFIG_SDX_DEMUXER) += sdxdec.o OBJS-$(CONFIG_SEGAFILM_DEMUXER) += segafilm.o +OBJS-$(CONFIG_SEGAFILM_MUXER) += segafilmenc.o OBJS-$(CONFIG_SEGMENT_MUXER) += segment.o OBJS-$(CONFIG_SHORTEN_DEMUXER) += shortendec.o rawdec.o OBJS-$(CONFIG_SIFF_DEMUXER) += siff.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index d8d733735a33b..d582778b3b349 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -362,6 +362,7 @@ extern AVInputFormat ff_sdr2_demuxer; extern AVInputFormat ff_sds_demuxer; extern AVInputFormat ff_sdx_demuxer; extern AVInputFormat ff_segafilm_demuxer; +extern AVOutputFormat ff_segafilm_muxer; extern AVOutputFormat ff_segment_muxer; extern AVOutputFormat ff_stream_segment_muxer; extern AVInputFormat ff_shorten_demuxer; diff --git a/libavformat/segafilmenc.c b/libavformat/segafilmenc.c new file mode 100644 index 0000000000000..86c0ab0d1c4e0 --- /dev/null +++ b/libavformat/segafilmenc.c @@ -0,0 +1,398 @@ +/* + * Sega FILM Format (CPK) Muxer + * Copyright (C) 2003 The FFmpeg project + * Copyright (C) 2018 Misty De Meo + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Sega FILM (.cpk) file muxer + * @author Misty De Meo + * + * @see For more information regarding the Sega FILM file format, visit: + * http://wiki.multimedia.cx/index.php?title=Sega_FILM + */ + +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "internal.h" +#include "avio_internal.h" + +typedef struct FILMPacket { + int audio; + int keyframe; + int32_t pts; + int32_t duration; + int32_t size; + int32_t index; + struct FILMPacket *next; +} FILMPacket; + +typedef struct FILMOutputContext { + const AVClass *class; + int audio_index; + int video_index; + int64_t stab_pos; + FILMPacket *start; + FILMPacket *last; + int64_t packet_count; +} FILMOutputContext; + +static int film_write_packet_to_header(AVFormatContext *format_context, FILMPacket *pkt) +{ + AVIOContext *pb = format_context->pb; + /* The bits in these two 32-bit integers contain info about the contents of this sample */ + int32_t info1 = 0; + int32_t info2 = 0; + + if (pkt->audio) { + /* Always the same, carries no more information than "this is audio" */ + info1 = 0xFFFFFFFF; + info2 = 1; + } else { + info1 = pkt->pts; + info2 = pkt->duration; + /* The top bit being set indicates a key frame */ + if (pkt->keyframe) + info1 |= (1 << 31); + } + + /* Write the 16-byte sample info packet to the STAB chunk in the header */ + avio_wb32(pb, pkt->index); + avio_wb32(pb, pkt->size); + avio_wb32(pb, info1); + avio_wb32(pb, info2); + + return 0; +} + +static int film_write_packet(AVFormatContext *format_context, AVPacket *pkt) +{ + FILMPacket *metadata; + AVIOContext *pb = format_context->pb; + FILMOutputContext *film = format_context->priv_data; + int encoded_buf_size = 0; + enum AVCodecID codec_id; + + /* Track the metadata used to write the header and add it to the linked list */ + metadata = av_mallocz(sizeof(FILMPacket)); + if (!metadata) + return AVERROR(ENOMEM); + metadata->audio = pkt->stream_index == film->audio_index; + metadata->keyframe = pkt->flags & AV_PKT_FLAG_KEY; + metadata->pts = pkt->pts; + metadata->duration = pkt->duration; + metadata->size = pkt->size; + if (film->last == NULL) { + metadata->index = 0; + } else { + metadata->index = film->last->index + film->last->size; + film->last->next = metadata; + } + metadata->next = NULL; + if (film->start == NULL) + film->start = metadata; + film->packet_count++; + film->last = metadata; + + codec_id = format_context->streams[pkt->stream_index]->codecpar->codec_id; + + /* Sega Cinepak has an extra two-byte header; write dummy data there, + * then adjust the cvid header to accommodate for the extra size */ + if (codec_id == AV_CODEC_ID_CINEPAK) { + encoded_buf_size = AV_RB24(&pkt->data[1]); + /* Already Sega Cinepak, so no need to reformat the packets */ + if (encoded_buf_size != pkt->size && (pkt->size % encoded_buf_size) != 0) { + avio_write(pb, pkt->data, pkt->size); + } else { + /* In Sega Cinepak, the reported size in the Cinepak header is + * 8 bytes too short. However, the size in the STAB section of the header + * is correct, taking into account the extra two bytes. */ + AV_WB24(&pkt->data[1], pkt->size - 8 + 2); + metadata->size += 2; + uint8_t padding[2] = {0, 0}; + + avio_write(pb, pkt->data, 10); + avio_write(pb, padding, 2); + avio_write(pb, &pkt->data[10], pkt->size - 10); + } + } else { + /* Other formats can just be written as-is */ + avio_write(pb, pkt->data, pkt->size); + } + + return 0; +} + +static int get_audio_codec_id(enum AVCodecID codec_id) +{ + /* 0 (PCM) and 2 (ADX) are the only known values */ + switch (codec_id) { + case AV_CODEC_ID_PCM_S8_PLANAR: + case AV_CODEC_ID_PCM_S16BE_PLANAR: + return 0; + break; + case AV_CODEC_ID_ADPCM_ADX: + return 2; + break; + default: + return -1; + } +} + +static int film_init(AVFormatContext *format_context) +{ + FILMOutputContext *film = format_context->priv_data; + film->audio_index = -1; + film->video_index = -1; + film->stab_pos = 0; + film->packet_count = 0; + film->start = NULL; + film->last = NULL; + AVStream *audio = NULL; + + for (int i = 0; i < format_context->nb_streams; i++) { + AVStream *st = format_context->streams[i]; + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (film->audio_index > -1) { + av_log(format_context, AV_LOG_ERROR, "Sega FILM allows a maximum of one audio stream.\n"); + return AVERROR(EINVAL); + } + film->audio_index = i; + audio = st; + } + + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + if (film->video_index > -1) { + av_log(format_context, AV_LOG_ERROR, "Sega FILM allows a maximum of one video stream.\n"); + return AVERROR(EINVAL); + } + film->video_index = i; + } + + if (film->video_index == -1) { + av_log(format_context, AV_LOG_ERROR, "No video stream present.\n"); + return AVERROR(EINVAL); + } + } + + if (audio != NULL && get_audio_codec_id(audio->codecpar->codec_id) < 0) { + av_log(format_context, AV_LOG_ERROR, "Incompatible audio stream format.\n"); + return AVERROR(EINVAL); + } + + return 0; +} + +static int shift_data(AVFormatContext *format_context, int64_t shift_size) +{ + int ret = 0; + int64_t pos, pos_end = avio_tell(format_context->pb); + uint8_t *buf, *read_buf[2]; + int read_buf_id = 0; + int read_size[2]; + AVIOContext *read_pb; + + buf = av_malloc(shift_size * 2); + if (!buf) + return AVERROR(ENOMEM); + read_buf[0] = buf; + read_buf[1] = buf + shift_size; + + /* Write the header at the beginning of the file, shifting all content as necessary; + * based on the approach used by MOV faststart. */ + avio_flush(format_context->pb); + ret = format_context->io_open(format_context, &read_pb, format_context->url, AVIO_FLAG_READ, NULL); + if (ret < 0) { + av_log(format_context, AV_LOG_ERROR, "Unable to re-open %s output file to " + "write the header\n", format_context->url); + av_free(buf); + return ret; + } + + /* mark the end of the shift to up to the last data we wrote, and get ready + * for writing */ + pos_end = avio_tell(format_context->pb); + avio_seek(format_context->pb, shift_size, SEEK_SET); + + /* start reading at where the new header will be placed */ + avio_seek(read_pb, 0, SEEK_SET); + pos = avio_tell(read_pb); + +#define READ_BLOCK do { \ + read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], shift_size); \ + read_buf_id ^= 1; \ +} while (0) + + /* shift data by chunk of at most shift_size */ + READ_BLOCK; + do { + int n; + READ_BLOCK; + n = read_size[read_buf_id]; + if (n <= 0) + break; + avio_write(format_context->pb, read_buf[read_buf_id], n); + pos += n; + } while (pos < pos_end); + ff_format_io_close(format_context, &read_pb); + + av_free(buf); + return 0; +} + +static int film_write_header(AVFormatContext *format_context) +{ + int ret = 0; + int64_t sample_table_size, stabsize, headersize; + int8_t audio_codec; + AVIOContext *pb = format_context->pb; + FILMOutputContext *film = format_context->priv_data; + FILMPacket *prev, *packet; + AVStream *audio = NULL; + AVStream *video = NULL; + + /* Calculate how much we need to reserve for the header; + * this is the amount the rest of the data will be shifted up by. */ + sample_table_size = film->packet_count * 16; + stabsize = 16 + sample_table_size; + headersize = 16 + /* FILM header base */ + 32 + /* FDSC chunk */ + stabsize; + + ret = shift_data(format_context, headersize); + if (ret < 0) + return ret; + /* Seek back to the beginning to start writing the header now */ + avio_seek(pb, 0, SEEK_SET); + + if (film->audio_index > -1) + audio = format_context->streams[film->audio_index]; + if (film->video_index > -1) + video = format_context->streams[film->video_index]; + + if (audio != NULL) { + audio_codec = get_audio_codec_id(audio->codecpar->codec_id); + if (audio_codec < 0) { + av_log(format_context, AV_LOG_ERROR, "Incompatible audio stream format.\n"); + return AVERROR(EINVAL); + } + } + + if (video->codecpar->format != AV_PIX_FMT_RGB24) { + av_log(format_context, AV_LOG_ERROR, "Pixel format must be rgb24.\n"); + return AVERROR(EINVAL); + } + + /* First, write the FILM header; this is very simple */ + + ffio_wfourcc(pb, "FILM"); + avio_wb32(pb, 48 + stabsize); + /* This seems to be okay to hardcode, since this muxer targets 1.09 features; + * videos produced by this muxer are readable by 1.08 and lower players. */ + ffio_wfourcc(pb, "1.09"); + /* I have no idea what this field does, might be reserved */ + avio_wb32(pb, 0); + + /* Next write the FDSC (file description) chunk */ + ffio_wfourcc(pb, "FDSC"); + avio_wb32(pb, 0x20); /* Size of FDSC chunk */ + + /* The only two supported codecs; raw video is rare */ + switch (video->codecpar->codec_id) { + case AV_CODEC_ID_CINEPAK: + ffio_wfourcc(pb, "cvid"); + break; + case AV_CODEC_ID_RAWVIDEO: + ffio_wfourcc(pb, "raw "); + break; + default: + av_log(format_context, AV_LOG_ERROR, "Incompatible video stream format.\n"); + return AVERROR(EINVAL); + } + + avio_wb32(pb, video->codecpar->height); + avio_wb32(pb, video->codecpar->width); + avio_w8(pb, 24); /* Bits per pixel - observed to always be 24 */ + + if (audio != NULL) { + avio_w8(pb, audio->codecpar->channels); /* Audio channels */ + avio_w8(pb, audio->codecpar->bits_per_coded_sample); /* Audio bit depth */ + avio_w8(pb, audio_codec); /* Compression - 0 is PCM, 2 is ADX */ + avio_wb16(pb, audio->codecpar->sample_rate); /* Audio sampling rate */ + } else { + /* Set all these fields to 0 if there's no audio */ + avio_w8(pb, 0); + avio_w8(pb, 0); + avio_w8(pb, 0); + avio_wb16(pb, 0); + } + + /* I have no idea what this pair of fields does either, might be reserved */ + avio_wb32(pb, 0); + avio_wb16(pb, 0); + + /* Finally, write the STAB (sample table) chunk */ + ffio_wfourcc(pb, "STAB"); + avio_wb32(pb, 16 + (film->packet_count * 16)); + /* Framerate base frequency. Here we're assuming that the frame rate is even. + * In real world Sega FILM files, there are usually a couple of approaches: + * a) framerate base frequency is the same as the framerate, and ticks + * increment by 1 every frame, or + * b) framerate base frequency is a much larger number, and ticks + * increment by larger steps every frame. + * The latter occurs even in cases where the frame rate is even; for example, in + * Lunar: Silver Star Story, the base frequency is 600 and each frame, the ticks + * are incremented by 25 for an evenly spaced framerate of 24fps. */ + avio_wb32(pb, av_q2d(av_inv_q(video->time_base))); + + avio_wb32(pb, film->packet_count); + + avio_flush(pb); + + /* Finally, write out each packet's data to the header */ + packet = film->start; + while (packet != NULL) { + film_write_packet_to_header(format_context, packet); + prev = packet; + packet = packet->next; + av_freep(&prev); + } + + return 0; +} + +static const AVClass film_muxer_class = { + .class_name = "Sega FILM muxer", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVOutputFormat ff_segafilm_muxer = { + .name = "film_cpk", + .long_name = NULL_IF_CONFIG_SMALL("Sega FILM / CPK"), + .extensions = "cpk", + .priv_data_size = sizeof(FILMOutputContext), + .audio_codec = AV_CODEC_ID_PCM_S16BE_PLANAR, + .video_codec = AV_CODEC_ID_CINEPAK, + .init = film_init, + .write_trailer = film_write_header, + .write_packet = film_write_packet, + .priv_class = &film_muxer_class, +}; diff --git a/libavformat/version.h b/libavformat/version.h index e28a9e7dfec52..b55d51c1b77ba 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 10 +#define LIBAVFORMAT_VERSION_MINOR 11 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From 92fe0bf1e8f83899ae8123bf1adc82dd6211f33a Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Thu, 5 Apr 2018 22:08:50 +0100 Subject: [PATCH 2390/2557] lavfi,lavd: add gitignore for generated static component lists Signed-off-by: Josh de Kock --- libavdevice/.gitignore | 2 ++ libavfilter/.gitignore | 1 + 2 files changed, 3 insertions(+) create mode 100644 libavdevice/.gitignore create mode 100644 libavfilter/.gitignore diff --git a/libavdevice/.gitignore b/libavdevice/.gitignore new file mode 100644 index 0000000000000..08ac3eb86a81f --- /dev/null +++ b/libavdevice/.gitignore @@ -0,0 +1,2 @@ +/indev_list.c +/outdev_list.c diff --git a/libavfilter/.gitignore b/libavfilter/.gitignore new file mode 100644 index 0000000000000..26bddebc933d8 --- /dev/null +++ b/libavfilter/.gitignore @@ -0,0 +1 @@ +/filter_list.c From 233f52fd2534e6844fd5831e3a6c7ca3a1c8fc2d Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Thu, 5 Apr 2018 00:41:55 +0200 Subject: [PATCH 2391/2557] lavf/amr: Stricter heuristic for auto-detection. Fixes ticket #7125. --- libavformat/amr.c | 10 ++++++---- libavformat/version.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libavformat/amr.c b/libavformat/amr.c index 8b4d736d2f900..f954803d4615a 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -178,7 +178,7 @@ AVInputFormat ff_amr_demuxer = { #if CONFIG_AMRNB_DEMUXER static int amrnb_probe(AVProbeData *p) { - int mode, i = 0, valid = 0; + int mode, i = 0, valid = 0, invalid = 0; const uint8_t *b = p->buf; while (i < p->buf_size) { @@ -197,10 +197,11 @@ static int amrnb_probe(AVProbeData *p) } } else { valid = 0; + invalid++; i++; } } - if (valid > 100) + if (valid > 100 && valid > invalid) return AVPROBE_SCORE_EXTENSION / 2 + 1; return 0; } @@ -234,7 +235,7 @@ AVInputFormat ff_amrnb_demuxer = { #if CONFIG_AMRWB_DEMUXER static int amrwb_probe(AVProbeData *p) { - int mode, i = 0, valid = 0; + int mode, i = 0, valid = 0, invalid = 0; const uint8_t *b = p->buf; while (i < p->buf_size) { @@ -253,10 +254,11 @@ static int amrwb_probe(AVProbeData *p) } } else { valid = 0; + invalid++; i++; } } - if (valid > 100) + if (valid > 100 && valid > invalid) return AVPROBE_SCORE_EXTENSION / 2 - 1; return 0; } diff --git a/libavformat/version.h b/libavformat/version.h index b55d51c1b77ba..a96e13bc603e0 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -33,7 +33,7 @@ // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 #define LIBAVFORMAT_VERSION_MINOR 11 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ From e54679b6c1def5a969d4a5c9db63b51efe7106d7 Mon Sep 17 00:00:00 2001 From: Bela Bodecs Date: Tue, 3 Apr 2018 16:18:02 +0200 Subject: [PATCH 2392/2557] doc/filters: some more details and modified example to zmq/azmq Info about default value of bind_address option and its abbreviated version (b). Example modified to have named instanced filter and to show its use. Signed-off-by: Bela Bodecs Signed-off-by: Lou Logan --- doc/filters.texi | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 7538ab3273664..4438386f647e8 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -221,6 +221,7 @@ Here is a BNF description of the filtergraph syntax: @var{FILTERGRAPH} ::= [sws_flags=@var{flags};] @var{FILTERCHAIN} [;@var{FILTERGRAPH}] @end example +@anchor{filtergraph escaping} @section Notes on filtergraph escaping Filtergraph description composition entails several levels of @@ -20270,7 +20271,7 @@ filters in the filtergraph. @code{zmq} and @code{azmq} work as a pass-through filters. @code{zmq} must be inserted between two video filters, @code{azmq} between two -audio filters. +audio filters. Both are capable to send messages to any filter type. To enable these filters you need to install the libzmq library and headers and configure FFmpeg with @code{--enable-libzmq}. @@ -20280,7 +20281,10 @@ For more information about libzmq see: The @code{zmq} and @code{azmq} filters work as a libzmq server, which receives messages sent through a network interface defined by the -@option{bind_address} option. +@option{bind_address} (or the abbreviation "@option{b}") option. +Default value of this option is @file{tcp://localhost:5555}. You may +want to alter this value to your needs, but do not forget to escape any +':' signs (see @ref{filtergraph escaping}). The received message must be in the form: @example @@ -20288,7 +20292,10 @@ The received message must be in the form: @end example @var{TARGET} specifies the target of the command, usually the name of -the filter class or a specific filter instance name. +the filter class or a specific filter instance name. The default +filter instance name uses the pattern @samp{Parsed__}, +but you can override this by using the @samp{filter_name@@id} syntax +(see @ref{Filtergraph syntax}). @var{COMMAND} specifies the name of the command for the target filter. @@ -20310,14 +20317,17 @@ will send a reply to the client, adopting the format: Look at @file{tools/zmqsend} for an example of a zmq client which can be used to send commands processed by these filters. -Consider the following filtergraph generated by @command{ffplay} +Consider the following filtergraph generated by @command{ffplay}. +In this example the last overlay filter has an instance name. All other +filters will have default instance names. + @example ffplay -dumpgraph 1 -f lavfi " color=s=100x100:c=red [l]; color=s=100x100:c=blue [r]; nullsrc=s=200x100, zmq [bg]; -[bg][l] overlay [bg+l]; -[bg+l][r] overlay=x=100 " +[bg][l] overlay [bg+l]; +[bg+l][r] overlay@@my=x=100 " @end example To change the color of the left side of the video, the following @@ -20331,6 +20341,12 @@ To change the right side: echo Parsed_color_1 c pink | tools/zmqsend @end example +To change the position of the right side: +@example +echo overlay@@my x 150 | tools/zmqsend +@end example + + @c man end MULTIMEDIA FILTERS @chapter Multimedia Sources From 2f1963eedc0c59413a03bffd45492741020a1666 Mon Sep 17 00:00:00 2001 From: Lou Logan Date: Thu, 5 Apr 2018 10:10:37 -0800 Subject: [PATCH 2393/2557] doc/developer: remove merge request method of contributing This seems to confuse Github users into thinking that we may accept pull requests. We do not accept pull requests. Sending patches to the ffmpeg-devel mailing list is our preferred method for users to contribute code. Signed-off-by: Lou Logan --- doc/developer.texi | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/developer.texi b/doc/developer.texi index 0fc9c3f21c8ba..a0eeefe242dc4 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -30,13 +30,11 @@ consult @url{https://ffmpeg.org/legal.html}. @chapter Contributing -There are 3 ways by which code gets into FFmpeg. +There are 2 ways by which code gets into FFmpeg: @itemize @bullet -@item Submitting patches to the main developer mailing list. +@item Submitting patches to the ffmpeg-devel mailing list. See @ref{Submitting patches} for details. @item Directly committing changes to the main tree. -@item Committing changes to a git clone, for example on github.com or - gitorious.org. And asking us to merge these changes. @end itemize Whichever way, changes should be reviewed by the maintainer of the code From 647fd4b8292e3bfae30b1086aa842a5ee47ee868 Mon Sep 17 00:00:00 2001 From: Hendrik Schreiber Date: Thu, 5 Apr 2018 13:58:37 +0200 Subject: [PATCH 2394/2557] swresample/swresample: Fix for seg fault in swr_convert_internal() -> sum2_float during dithering. Removed +len1 in call to s->mix_2_1_f() as I found no logical explanation for it. After removal, problem was gone. Signed-off-by: Hendrik Schreiber Signed-off-by: Michael Niedermayer --- libswresample/swresample.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libswresample/swresample.c b/libswresample/swresample.c index f076b6c8cfa59..5bd39caac4dfe 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -678,7 +678,7 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co s->mix_2_1_simd(conv_src->ch[ch], preout->ch[ch], s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.noise_pos, s->native_simd_one, 0, 0, len1); if(out_count != len1) for(ch=0; chch_count; ch++) - s->mix_2_1_f(conv_src->ch[ch] + off, preout->ch[ch] + off, s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.noise_pos + off + len1, s->native_one, 0, 0, out_count - len1); + s->mix_2_1_f(conv_src->ch[ch] + off, preout->ch[ch] + off, s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.noise_pos + off, s->native_one, 0, 0, out_count - len1); } else { for(ch=0; chch_count; ch++) s->mix_2_1_f(conv_src->ch[ch], preout->ch[ch], s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.noise_pos, s->native_one, 0, 0, out_count); From a61886650b598c98b7f8b44b3c186e33873913cd Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 4 Apr 2018 14:12:54 -0300 Subject: [PATCH 2395/2557] avformat/matroskadec: use refcounted buffers in EbmlBin Data in EbmlBin objects is never changed after being read from the input file (save for two specific cases with encoded CodePrivate), so using AVBufferRef we can prevent unnecessary copy of data by instead creating new references to said constant data. Signed-off-by: James Almer --- libavformat/matroskadec.c | 44 +++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 6156c2f9b4fbd..029929a1cb14e 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -104,6 +104,7 @@ typedef struct EbmlList { typedef struct EbmlBin { int size; + AVBufferRef *buf; uint8_t *data; int64_t pos; } EbmlBin; @@ -962,14 +963,19 @@ static int ebml_read_ascii(AVIOContext *pb, int size, char **str) */ static int ebml_read_binary(AVIOContext *pb, int length, EbmlBin *bin) { - av_fast_padded_malloc(&bin->data, &bin->size, length); - if (!bin->data) - return AVERROR(ENOMEM); + int ret; + ret = av_buffer_realloc(&bin->buf, length + AV_INPUT_BUFFER_PADDING_SIZE); + if (ret < 0) + return ret; + memset(bin->buf->data + length, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + bin->data = bin->buf->data; bin->size = length; bin->pos = avio_tell(pb); if (avio_read(pb, bin->data, length) != length) { - av_freep(&bin->data); + av_buffer_unref(&bin->buf); + bin->data = NULL; bin->size = 0; return AVERROR(EIO); } @@ -1252,7 +1258,7 @@ static void ebml_free(EbmlSyntax *syntax, void *data) av_freep(data_off); break; case EBML_BIN: - av_freep(&((EbmlBin *) data_off)->data); + av_buffer_unref(&((EbmlBin *) data_off)->buf); break; case EBML_LEVEL1: case EBML_NEST: @@ -2036,12 +2042,13 @@ static int get_qt_codec(MatroskaTrack *track, uint32_t *fourcc, enum AVCodecID * * by expanding/shifting the data by 4 bytes and storing the data * size at the start. */ if (ff_codec_get_id(codec_tags, AV_RL32(track->codec_priv.data))) { - uint8_t *p = av_realloc(track->codec_priv.data, - track->codec_priv.size + 4); - if (!p) - return AVERROR(ENOMEM); - memmove(p + 4, p, track->codec_priv.size); - track->codec_priv.data = p; + int ret = av_buffer_realloc(&track->codec_priv.buf, + track->codec_priv.size + 4 + AV_INPUT_BUFFER_PADDING_SIZE); + if (ret < 0) + return ret; + + track->codec_priv.data = track->codec_priv.buf->data; + memmove(track->codec_priv.data + 4, track->codec_priv.data, track->codec_priv.size); track->codec_priv.size += 4; AV_WB32(track->codec_priv.data, track->codec_priv.size); } @@ -2162,8 +2169,19 @@ static int matroska_parse_tracks(AVFormatContext *s) "Failed to decode codec private data\n"); } - if (codec_priv != track->codec_priv.data) - av_free(codec_priv); + if (codec_priv != track->codec_priv.data) { + av_buffer_unref(&track->codec_priv.buf); + if (track->codec_priv.data) { + track->codec_priv.buf = av_buffer_create(track->codec_priv.data, + track->codec_priv.size + AV_INPUT_BUFFER_PADDING_SIZE, + NULL, NULL, 0); + if (!track->codec_priv.buf) { + av_freep(&track->codec_priv.data); + track->codec_priv.size = 0; + return AVERROR(ENOMEM); + } + } + } } } From b8e75a2a08b678c7c6259a125acd8fa9565b5e42 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 4 Apr 2018 16:07:36 -0300 Subject: [PATCH 2396/2557] avformat/matroskadec: factor the prores packet parsing code out Simplifies code in matroska_parse_frame(). This is in preparation for the following patch. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/matroskadec.c | 50 +++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 029929a1cb14e..30f0da5bee869 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -3035,6 +3035,29 @@ static int matroska_parse_wavpack(MatroskaTrack *track, uint8_t *src, return ret; } +static int matroska_parse_prores(MatroskaTrack *track, uint8_t *src, + uint8_t **pdst, int *size) +{ + uint8_t *dst = src; + int dstlen = *size; + + if (AV_RB32(&src[4]) != MKBETAG('i', 'c', 'p', 'f')) { + dst = av_malloc(dstlen + 8); + if (!dst) + return AVERROR(ENOMEM); + + AV_WB32(dst, dstlen); + AV_WB32(dst + 4, MKBETAG('i', 'c', 'p', 'f')); + memcpy(dst + 8, src, dstlen); + dstlen += 8; + } + + *pdst = dst; + *size = dstlen; + + return 0; +} + static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, MatroskaTrack *track, AVStream *st, @@ -3160,7 +3183,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, { MatroskaTrackEncoding *encodings = track->encodings.elem; uint8_t *pkt_data = data; - int offset = 0, res; + int res; AVPacket pktl, *pkt = &pktl; if (encodings && !encodings->type && encodings->scope & 1) { @@ -3182,23 +3205,26 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, pkt_data = wv_data; } - if (st->codecpar->codec_id == AV_CODEC_ID_PRORES && - AV_RB32(&data[4]) != MKBETAG('i', 'c', 'p', 'f')) - offset = 8; + if (st->codecpar->codec_id == AV_CODEC_ID_PRORES) { + uint8_t *pr_data; + res = matroska_parse_prores(track, pkt_data, &pr_data, &pkt_size); + if (res < 0) { + av_log(matroska->ctx, AV_LOG_ERROR, + "Error parsing a prores block.\n"); + goto fail; + } + if (pkt_data != data) + av_freep(&pkt_data); + pkt_data = pr_data; + } /* XXX: prevent data copy... */ - if (av_new_packet(pkt, pkt_size + offset) < 0) { + if (av_new_packet(pkt, pkt_size) < 0) { res = AVERROR(ENOMEM); goto fail; } - if (st->codecpar->codec_id == AV_CODEC_ID_PRORES && offset == 8) { - uint8_t *buf = pkt->data; - bytestream_put_be32(&buf, pkt_size); - bytestream_put_be32(&buf, MKBETAG('i', 'c', 'p', 'f')); - } - - memcpy(pkt->data + offset, pkt_data, pkt_size); + memcpy(pkt->data, pkt_data, pkt_size); if (pkt_data != data) av_freep(&pkt_data); From 9703b7d05fc7ab0378808b8d372a9c4a96e97488 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 4 Apr 2018 18:12:53 -0300 Subject: [PATCH 2397/2557] avformat/matroskadec: reference the existing data buffer when creating packets Newly allocated data buffers (wavpack, prores, compressed buffers) are padded to meet the requirements of AVPacket. About 10x speed up in matroska_parse_frame(). Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/matroskadec.c | 45 +++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 30f0da5bee869..1ded431b801cb 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -1367,7 +1367,7 @@ static int matroska_decode_buffer(uint8_t **buf, int *buf_size, return 0; pkt_size = isize + header_size; - pkt_data = av_malloc(pkt_size); + pkt_data = av_malloc(pkt_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!pkt_data) return AVERROR(ENOMEM); @@ -1379,7 +1379,8 @@ static int matroska_decode_buffer(uint8_t **buf, int *buf_size, case MATROSKA_TRACK_ENCODING_COMP_LZO: do { olen = pkt_size *= 3; - newpktdata = av_realloc(pkt_data, pkt_size + AV_LZO_OUTPUT_PADDING); + newpktdata = av_realloc(pkt_data, pkt_size + AV_LZO_OUTPUT_PADDING + + AV_INPUT_BUFFER_PADDING_SIZE); if (!newpktdata) { result = AVERROR(ENOMEM); goto failed; @@ -1404,7 +1405,7 @@ static int matroska_decode_buffer(uint8_t **buf, int *buf_size, zstream.avail_in = isize; do { pkt_size *= 3; - newpktdata = av_realloc(pkt_data, pkt_size); + newpktdata = av_realloc(pkt_data, pkt_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!newpktdata) { inflateEnd(&zstream); result = AVERROR(ENOMEM); @@ -1437,7 +1438,7 @@ static int matroska_decode_buffer(uint8_t **buf, int *buf_size, bzstream.avail_in = isize; do { pkt_size *= 3; - newpktdata = av_realloc(pkt_data, pkt_size); + newpktdata = av_realloc(pkt_data, pkt_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!newpktdata) { BZ2_bzDecompressEnd(&bzstream); result = AVERROR(ENOMEM); @@ -1464,6 +1465,8 @@ static int matroska_decode_buffer(uint8_t **buf, int *buf_size, return AVERROR_INVALIDDATA; } + memset(pkt_data + pkt_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + *buf = pkt_data; *buf_size = pkt_size; return 0; @@ -3001,7 +3004,7 @@ static int matroska_parse_wavpack(MatroskaTrack *track, uint8_t *src, goto fail; } - tmp = av_realloc(dst, dstlen + blocksize + 32); + tmp = av_realloc(dst, dstlen + blocksize + 32 + AV_INPUT_BUFFER_PADDING_SIZE); if (!tmp) { ret = AVERROR(ENOMEM); goto fail; @@ -3025,6 +3028,8 @@ static int matroska_parse_wavpack(MatroskaTrack *track, uint8_t *src, offset += blocksize + 32; } + memset(dst + dstlen, 0, AV_INPUT_BUFFER_PADDING_SIZE); + *pdst = dst; *size = dstlen; @@ -3042,13 +3047,14 @@ static int matroska_parse_prores(MatroskaTrack *track, uint8_t *src, int dstlen = *size; if (AV_RB32(&src[4]) != MKBETAG('i', 'c', 'p', 'f')) { - dst = av_malloc(dstlen + 8); + dst = av_malloc(dstlen + 8 + AV_INPUT_BUFFER_PADDING_SIZE); if (!dst) return AVERROR(ENOMEM); AV_WB32(dst, dstlen); AV_WB32(dst + 4, MKBETAG('i', 'c', 'p', 'f')); memcpy(dst + 8, src, dstlen); + memset(dst + 8 + dstlen, 0, AV_INPUT_BUFFER_PADDING_SIZE); dstlen += 8; } @@ -3175,7 +3181,7 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, static int matroska_parse_frame(MatroskaDemuxContext *matroska, MatroskaTrack *track, AVStream *st, - uint8_t *data, int pkt_size, + AVBufferRef *buf, uint8_t *data, int pkt_size, uint64_t timecode, uint64_t lace_duration, int64_t pos, int is_keyframe, uint8_t *additional, uint64_t additional_id, int additional_size, @@ -3218,17 +3224,20 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, pkt_data = pr_data; } - /* XXX: prevent data copy... */ - if (av_new_packet(pkt, pkt_size) < 0) { + av_init_packet(pkt); + if (pkt_data != data) + pkt->buf = av_buffer_create(pkt_data, pkt_size + AV_INPUT_BUFFER_PADDING_SIZE, + NULL, NULL, 0); + else + pkt->buf = av_buffer_ref(buf); + + if (!pkt->buf) { res = AVERROR(ENOMEM); goto fail; } - memcpy(pkt->data, pkt_data, pkt_size); - - if (pkt_data != data) - av_freep(&pkt_data); - + pkt->data = pkt_data; + pkt->size = pkt_size; pkt->flags = is_keyframe; pkt->stream_index = st->index; @@ -3291,7 +3300,7 @@ FF_ENABLE_DEPRECATION_WARNINGS return res; } -static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, +static int matroska_parse_block(MatroskaDemuxContext *matroska, AVBufferRef *buf, uint8_t *data, int size, int64_t pos, uint64_t cluster_time, uint64_t block_duration, int is_keyframe, uint8_t *additional, uint64_t additional_id, int additional_size, @@ -3409,7 +3418,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, if (res) goto end; } else { - res = matroska_parse_frame(matroska, track, st, data, lace_size[n], + res = matroska_parse_frame(matroska, track, st, buf, data, lace_size[n], timecode, lace_duration, pos, !n ? is_keyframe : 0, additional, additional_id, additional_size, @@ -3472,7 +3481,7 @@ static int matroska_parse_cluster_incremental(MatroskaDemuxContext *matroska) blocks[i].additional.data : NULL; if (!blocks[i].non_simple) blocks[i].duration = 0; - res = matroska_parse_block(matroska, blocks[i].bin.data, + res = matroska_parse_block(matroska, blocks[i].bin.buf, blocks[i].bin.data, blocks[i].bin.size, blocks[i].bin.pos, matroska->current_cluster.timecode, blocks[i].duration, is_keyframe, @@ -3505,7 +3514,7 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska) for (i = 0; i < blocks_list->nb_elem; i++) if (blocks[i].bin.size > 0 && blocks[i].bin.data) { int is_keyframe = blocks[i].non_simple ? blocks[i].reference == INT64_MIN : -1; - res = matroska_parse_block(matroska, blocks[i].bin.data, + res = matroska_parse_block(matroska, blocks[i].bin.buf, blocks[i].bin.data, blocks[i].bin.size, blocks[i].bin.pos, cluster.timecode, blocks[i].duration, is_keyframe, NULL, 0, 0, pos, From 6261ef425128093609af2a0ce7505f72492e45bf Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 23 Mar 2018 18:58:33 +0100 Subject: [PATCH 2398/2557] avcodec/get_bits: Document skip_bits_long() Found-by: Kieran Signed-off-by: Michael Niedermayer --- libavcodec/get_bits.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index d7cf2863783b0..56ef5f0cbe197 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -202,6 +202,13 @@ static inline int get_bits_count(const GetBitContext *s) return s->index; } +/** + * Skips the specified number of bits. + * @param n the number of bits to skip, + * For the UNCHECKED_BITSTREAM_READER this must not cause the distance + * from the start to overflow int32_t. Staying within the bitstream + padding + * is sufficient, too. + */ static inline void skip_bits_long(GetBitContext *s, int n) { #if UNCHECKED_BITSTREAM_READER From 6cd81d68c5e4b0ff00288970c4151ff4031c0ea9 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 2 Apr 2018 20:01:07 +0200 Subject: [PATCH 2399/2557] libavcodec/rv34: error out earlier on missing references Fixes visual corruption on seeking Fixes: downloadTest_clip_24M.rmvb Signed-off-by: Michael Niedermayer --- libavcodec/rv34.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c index f1495fb5a8f8e..d171e6e1bdef2 100644 --- a/libavcodec/rv34.c +++ b/libavcodec/rv34.c @@ -1585,7 +1585,7 @@ int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecConte // Do no call ff_mpeg_update_thread_context on a partially initialized // decoder context. - if (!s1->linesize) + if (!s1->context_initialized) return 0; return ff_mpeg_update_thread_context(dst, src); @@ -1733,6 +1733,8 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, if ((err = rv34_decoder_realloc(r)) < 0) return err; } + if (faulty_b) + return AVERROR_INVALIDDATA; s->pict_type = si.type ? si.type : AV_PICTURE_TYPE_I; if (ff_mpv_frame_start(s, s->avctx) < 0) return -1; @@ -1786,8 +1788,6 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, "multithreading mode (start MB is %d).\n", si.start); return AVERROR_INVALIDDATA; } - if (faulty_b) - return AVERROR_INVALIDDATA; for(i = 0; i < slice_count; i++){ int offset = get_slice_offset(avctx, slices_hdr, i , slice_count, buf_size); From 916632dfbb0a987118b4d193c5cec54eba57a267 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Sat, 7 Apr 2018 21:30:45 +0200 Subject: [PATCH 2400/2557] lavc/clearvideo: Allow decoding without extradata. --- libavcodec/clearvideo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/clearvideo.c b/libavcodec/clearvideo.c index 9319cac0af2cc..6061cb571ea20 100644 --- a/libavcodec/clearvideo.c +++ b/libavcodec/clearvideo.c @@ -652,6 +652,8 @@ static av_cold int clv_decode_init(AVCodecContext *avctx) c->tile_size = AV_RL32(&avctx->extradata[94]); } else if (avctx->extradata_size == 150) { c->tile_size = AV_RB32(&avctx->extradata[134]); + } else if (!avctx->extradata_size) { + c->tile_size = 16; } else { av_log(avctx, AV_LOG_ERROR, "Unsupported extradata size: %d\n", avctx->extradata_size); return AVERROR_INVALIDDATA; From c837918f50a7bbd6150afd340857ea43fe4717c7 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 7 Apr 2018 21:55:06 +0200 Subject: [PATCH 2401/2557] avcodec/aacsbr_fixed: Fix integer overflow in sbr_hf_assemble() Fixes: runtime error: signed integer overflow: 2052929346 + 204817098 cannot be represented in type 'int' This was missed in b1bef755f617af9685b592d866b3eb7f3c4b02b1 Fixes: 5275/clusterfuzz-testcase-minimized-5367635958038528 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/aacsbr_fixed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/aacsbr_fixed.c b/libavcodec/aacsbr_fixed.c index eeada0b9f2b7e..59cbba10fffdf 100644 --- a/libavcodec/aacsbr_fixed.c +++ b/libavcodec/aacsbr_fixed.c @@ -567,7 +567,7 @@ static void sbr_hf_assemble(int Y1[38][64][2], int idx = indexsine&1; int A = (1-((indexsine+(kx & 1))&2)); int B = (A^(-idx)) + idx; - int *out = &Y1[i][kx][idx]; + unsigned *out = &Y1[i][kx][idx]; int shift; unsigned round; From 52ed83fa1a7f5170447eff6fad0b6c57119596e9 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Wed, 4 Apr 2018 17:51:29 +0800 Subject: [PATCH 2402/2557] lavc/qsvdec: expose frame pic_type and key_frame MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently pict_type and key_frame are unset. Add an extra param to fetch the picture type from qsv decoder The judgement “key frame is equal to IDR frame” only suitable for H264. For HEVC, all IRAP frames are key frames, and other codecs have no IDR frame. Signed-off-by: ChaoX A Liu Signed-off-by: Zhong Li Signed-off-by: Maxym Dmytrychenko --- libavcodec/qsv.c | 24 ++++++++++++++++++++++++ libavcodec/qsv_internal.h | 3 +++ libavcodec/qsvdec.c | 9 +++++++++ 3 files changed, 36 insertions(+) diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index e78633d62abe6..e578ab15f56da 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -195,6 +195,30 @@ int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame) return AVERROR_BUG; } +enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type) +{ + enum AVPictureType type; + switch (mfx_pic_type & 0x7) { + case MFX_FRAMETYPE_I: + if (mfx_pic_type & MFX_FRAMETYPE_S) + type = AV_PICTURE_TYPE_SI; + else + type = AV_PICTURE_TYPE_I; + break; + case MFX_FRAMETYPE_B: + type = AV_PICTURE_TYPE_B; + break; + case MFX_FRAMETYPE_P: + if (mfx_pic_type & MFX_FRAMETYPE_S) + type = AV_PICTURE_TYPE_SP; + else + type = AV_PICTURE_TYPE_P; + break; + } + + return type; +} + static int qsv_load_plugins(mfxSession session, const char *load_plugins, void *logctx) { diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index 975c8de44164f..07ddc5904464e 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -48,6 +48,8 @@ typedef struct QSVMid { typedef struct QSVFrame { AVFrame *frame; mfxFrameSurface1 surface; + mfxExtDecodedFrameInfo dec_info; + mfxExtBuffer *ext_param; int queued; int used; @@ -83,6 +85,7 @@ int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id); int ff_qsv_profile_to_mfx(enum AVCodecID codec_id, int profile); int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc); +enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type); int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, const char *load_plugins); diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index f31172de29a3a..c1b6238cfb76b 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -232,6 +232,11 @@ static int alloc_frame(AVCodecContext *avctx, QSVContext *q, QSVFrame *frame) frame->surface.Data.MemId = &q->frames_ctx.mids[ret]; } + frame->surface.Data.ExtParam = &frame->ext_param; + frame->surface.Data.NumExtParam = 1; + frame->ext_param = (mfxExtBuffer*)&frame->dec_info; + frame->dec_info.Header.BufferId = MFX_EXTBUFF_DECODED_FRAME_INFO; + frame->dec_info.Header.BufferSz = sizeof(frame->dec_info); frame->used = 1; @@ -416,6 +421,10 @@ FF_ENABLE_DEPRECATION_WARNINGS outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF; frame->interlaced_frame = !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE); + frame->pict_type = ff_qsv_map_pictype(out_frame->dec_info.FrameType); + //Key frame is IDR frame is only suitable for H264. For HEVC, IRAPs are key frames. + if (avctx->codec_id == AV_CODEC_ID_H264) + frame->key_frame = !!(out_frame->dec_info.FrameType & MFX_FRAMETYPE_IDR); /* update the surface properties */ if (avctx->pix_fmt == AV_PIX_FMT_QSV) From 29a8ed766354c45c9be4b8512c5b2eb25a450cdc Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Wed, 4 Apr 2018 17:51:30 +0800 Subject: [PATCH 2403/2557] lavf/qsvvpp: bypass vpp if not needed. Currently vpp pipeline is always created, even for the unnecessary cases such as setting the option "vpp_qsv=w=1280:h=720" for an input with native resolution 1280x720. Thus introduces unnecessary performance dropping, so bypass vpp if not needed. Signed-off-by: Zhong Li Signed-off-by: Maxym Dmytrychenko --- libavfilter/vf_vpp_qsv.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 610e821c1a720..568dee5d2904e 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -27,6 +27,7 @@ #include "libavutil/eval.h" #include "libavutil/avassert.h" #include "libavutil/pixdesc.h" +#include "libavutil/mathematics.h" #include "formats.h" #include "internal.h" @@ -249,6 +250,7 @@ static int config_output(AVFilterLink *outlink) QSVVPPParam param = { NULL }; QSVVPPCrop crop = { 0 }; mfxExtBuffer *ext_buf[ENH_FILTERS_COUNT]; + AVFilterLink *inlink = ctx->inputs[0]; outlink->w = vpp->out_width; outlink->h = vpp->out_height; @@ -320,14 +322,34 @@ static int config_output(AVFilterLink *outlink) param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->procamp_conf; } - return ff_qsvvpp_create(ctx, &vpp->qsv, ¶m); + if (vpp->use_frc || vpp->use_crop || vpp->deinterlace || vpp->denoise || + vpp->detail || vpp->procamp || inlink->w != outlink->w || inlink->h != outlink->h) + return ff_qsvvpp_create(ctx, &vpp->qsv, ¶m); + else { + av_log(ctx, AV_LOG_VERBOSE, "qsv vpp pass through mode.\n"); + if (inlink->hw_frames_ctx) + outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); + } + + return 0; } static int filter_frame(AVFilterLink *inlink, AVFrame *picref) { - VPPContext *vpp = inlink->dst->priv; + int ret = 0; + AVFilterContext *ctx = inlink->dst; + VPPContext *vpp = inlink->dst->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + if (vpp->qsv) + ret = ff_qsvvpp_filter_frame(vpp->qsv, inlink, picref); + else { + if (picref->pts != AV_NOPTS_VALUE) + picref->pts = av_rescale_q(picref->pts, inlink->time_base, outlink->time_base); + ret = ff_filter_frame(outlink, picref); + } - return ff_qsvvpp_filter_frame(vpp->qsv, inlink, picref); + return ret; } static int query_formats(AVFilterContext *ctx) From cca5e4f040971db6de0bfe6968f00c021d8a9c42 Mon Sep 17 00:00:00 2001 From: Maxym Dmytrychenko Date: Mon, 2 Apr 2018 15:17:23 +0200 Subject: [PATCH 2404/2557] qsv: adding Multi Frame Encode support Starting from API 1.25 helps to improve performance of the simultaneous encode, 1:N scenario, like: ./avconv -y -hwaccel qsv -c:v h264_qsv -r 30000/1001 -i ~/bbb_sunflower_1080p_60fps_normal.mp4 -vframes 600 -an \ -filter_complex "split=2[s1][s2]; [s1]scale_qsv=1280:720[o1]; [s2]scale_qsv=960:540[o2]" \ -map [o1] -c:v h264_qsv -b:v 3200k -minrate 3200k -maxrate 3200k -f rawvideo /tmp/3200a.264 \ -map [o2] -c:v h264_qsv -b:v 1750k -minrate 1750k -maxrate 1750k -f rawvideo /tmp/1750a.264 Signed-off-by: Maxym Dmytrychenko --- libavcodec/qsv.c | 10 ++++++---- libavcodec/qsv_internal.h | 4 ++++ libavcodec/qsvenc.c | 16 +++++++++++++++- libavcodec/qsvenc.h | 12 ++++++++++-- libavcodec/qsvenc_h264.c | 4 ++++ libavfilter/qsvvpp.c | 9 ++++++--- libavfilter/qsvvpp.h | 8 ++++++++ libavfilter/vf_deinterlace_qsv.c | 7 +++++++ libavfilter/vf_scale_qsv.c | 7 +++++++ libavutil/hwcontext_qsv.c | 5 +++++ 10 files changed, 72 insertions(+), 10 deletions(-) diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index e578ab15f56da..a9b3c59f3ae87 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -617,10 +617,12 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, "Error setting a HW handle"); } - err = MFXJoinSession(parent_session, session); - if (err != MFX_ERR_NONE) - return ff_qsv_print_error(avctx, err, - "Error joining session"); + if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) { + err = MFXJoinSession(parent_session, session); + if (err != MFX_ERR_NONE) + return ff_qsv_print_error(avctx, err, + "Error joining session"); + } ret = qsv_load_plugins(session, load_plugins, avctx); if (ret < 0) { diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index 07ddc5904464e..3cd8f1872b2de 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -36,6 +36,10 @@ (MFX_VERSION_MAJOR > (MAJOR) || \ MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR)) +#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR) \ + (MFX_VERSION.Major > (MAJOR)) || \ + (MFX_VERSION.Major == (MAJOR) && MFX_VERSION.Minor >= (MINOR)) + typedef struct QSVMid { AVBufferRef *hw_frames_ref; mfxHDL handle; diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index f6b1a0d6760d6..a8b446c5bd911 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -135,7 +135,7 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, #if QSV_HAVE_CO2 mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[1]; #endif -#if QSV_HAVE_CO3 +#if QSV_HAVE_CO3 && QSV_HAVE_QVBR mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2]; #endif @@ -656,6 +656,20 @@ FF_ENABLE_DEPRECATION_WARNINGS q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco2; } +#endif +#if QSV_HAVE_MF + if (avctx->codec_id == AV_CODEC_ID_H264) { + mfxVersion ver; + ret = MFXQueryVersion(q->session,&ver); + if (ret >= MFX_ERR_NONE && QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) { + q->extmfp.Header.BufferId = MFX_EXTBUFF_MULTI_FRAME_PARAM; + q->extmfp.Header.BufferSz = sizeof(q->extmfp); + + q->extmfp.MFMode = q->mfmode; + av_log(avctx,AV_LOG_VERBOSE,"MFMode:%d\n", q->extmfp.MFMode); + q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extmfp; + } + } #endif } diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index ab55795950c80..a7fc57bb48b85 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -50,11 +50,13 @@ #define QSV_HAVE_ICQ QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_VCM QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_QVBR QSV_VERSION_ATLEAST(1, 11) +#define QSV_HAVE_MF 0 #else #define QSV_HAVE_AVBR 0 #define QSV_HAVE_ICQ 0 #define QSV_HAVE_VCM 0 #define QSV_HAVE_QVBR 0 +#define QSV_HAVE_MF QSV_VERSION_ATLEAST(1, 25) #endif #if !QSV_HAVE_LA_DS @@ -109,12 +111,15 @@ typedef struct QSVEncContext { #if QSV_HAVE_CO2 mfxExtCodingOption2 extco2; #endif - +#if QSV_HAVE_MF + mfxExtMultiFrameParam extmfp; + mfxExtMultiFrameControl extmfc; +#endif mfxExtOpaqueSurfaceAlloc opaque_alloc; mfxFrameSurface1 **opaque_surfaces; AVBufferRef *opaque_alloc_buf; - mfxExtBuffer *extparam_internal[2 + QSV_HAVE_CO2]; + mfxExtBuffer *extparam_internal[2 + QSV_HAVE_CO2 + (QSV_HAVE_MF * 2)]; int nb_extparam_internal; mfxExtBuffer **extparam; @@ -156,6 +161,9 @@ typedef struct QSVEncContext { int int_ref_qp_delta; int recovery_point_sei; +#if QSV_HAVE_MF + int mfmode; +#endif char *load_plugins; } QSVEncContext; diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index 634a7d3f9199b..ae00ff8d54650 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -93,6 +93,10 @@ static const AVOption options[] = { { "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, +#if QSV_HAVE_MF + { "mfmode", "Multi-Frame Mode", OFFSET(qsv.mfmode), AV_OPT_TYPE_INT, { .i64 = MFX_MF_AUTO }, 0, INT_MAX, VE }, +#endif + { NULL }, }; diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index a96cfa65ded94..f704517aee103 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -515,9 +515,12 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s) if (ret != MFX_ERR_NONE) return AVERROR_UNKNOWN; } - ret = MFXJoinSession(device_hwctx->session, s->session); - if (ret != MFX_ERR_NONE) - return AVERROR_UNKNOWN; + + if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) { + ret = MFXJoinSession(device_hwctx->session, s->session); + if (ret != MFX_ERR_NONE) + return AVERROR_UNKNOWN; + } if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) { s->opaque_alloc.In.Surfaces = s->surface_ptrs_in; diff --git a/libavfilter/qsvvpp.h b/libavfilter/qsvvpp.h index 082c0a8994fda..d25ea69e5c0eb 100644 --- a/libavfilter/qsvvpp.h +++ b/libavfilter/qsvvpp.h @@ -31,6 +31,14 @@ #define FF_INLINK_IDX(link) ((int)((link)->dstpad - (link)->dst->input_pads)) #define FF_OUTLINK_IDX(link) ((int)((link)->srcpad - (link)->src->output_pads)) +#define QSV_VERSION_ATLEAST(MAJOR, MINOR) \ + (MFX_VERSION_MAJOR > (MAJOR) || \ + MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR)) + +#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR) \ + (MFX_VERSION.Major > (MAJOR)) || \ + (MFX_VERSION.Major == (MAJOR) && MFX_VERSION.Minor >= (MINOR)) + typedef struct QSVVPPContext QSVVPPContext; typedef struct QSVVPPCrop { diff --git a/libavfilter/vf_deinterlace_qsv.c b/libavfilter/vf_deinterlace_qsv.c index 2360491d3f794..bb26a4dbfef68 100644 --- a/libavfilter/vf_deinterlace_qsv.c +++ b/libavfilter/vf_deinterlace_qsv.c @@ -35,6 +35,7 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/time.h" +#include "libavfilter/qsvvpp.h" #include "avfilter.h" #include "formats.h" @@ -214,6 +215,12 @@ static int init_out_session(AVFilterContext *ctx) return AVERROR_UNKNOWN; } + if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) { + err = MFXJoinSession(device_hwctx->session, s->session); + if (err != MFX_ERR_NONE) + return AVERROR_UNKNOWN; + } + memset(&par, 0, sizeof(par)); s->deint_conf.Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING; diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c index c568e962599d1..381844cdc4a73 100644 --- a/libavfilter/vf_scale_qsv.c +++ b/libavfilter/vf_scale_qsv.c @@ -36,6 +36,7 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/time.h" +#include "libavfilter/qsvvpp.h" #include "avfilter.h" #include "formats.h" @@ -313,6 +314,12 @@ static int init_out_session(AVFilterContext *ctx) return AVERROR_UNKNOWN; } + if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) { + err = MFXJoinSession(device_hwctx->session, s->session); + if (err != MFX_ERR_NONE) + return AVERROR_UNKNOWN; + } + memset(&par, 0, sizeof(par)); if (opaque) { diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index f5d78d0595ddc..b3eb4a3ea6580 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -1058,6 +1058,11 @@ static int qsv_device_derive_from_child(AVHWDeviceContext *ctx, goto fail; } + ret = MFXQueryVersion(hwctx->session,&ver); + if (ret == MFX_ERR_NONE) { + av_log(ctx, AV_LOG_VERBOSE, "MFX compile/runtime API: %d.%d/%d.%d\n", + MFX_VERSION_MAJOR, MFX_VERSION_MINOR, ver.Major, ver.Minor); + } return 0; fail: From 54307b35311e9a871b3d8ecb2b2eecfc16de0163 Mon Sep 17 00:00:00 2001 From: Zhong Li Date: Sat, 7 Apr 2018 19:38:55 +0200 Subject: [PATCH 2405/2557] lavc/qsvdec: set complete_frame flags for progressive picture Set the flag MFX_BITSTREAM_COMPLETE_FRAME when it is a progressive picture. This can fix vc1 decoding segment fault issues because can't set the start code correctly. See: ./avconv -hwaccel qsv -c:v vc1_qsv -i /fate-suite/vc1/SA00040.vc1 -vf "hwdownload, format=nv12" -f rawvideo /dev/null v2: fix some h264 interlaced clips regression a. field_order of some h264 interlaced video (e.g: cama3_vtc_b.avc) is marked as AV_FIELD_UNKNOWN in h264_parser.c. This is not a completed frames. So only set the MFX_BITSTREAM_COMPLETE_FRAME when it is progressive. b. some clips have both progressive and interlaced frames (e.g.CAPAMA3_Sand_F.264), the parsed field_order maybe changed druing the decoding progress. This patch has been verified for other codecs(mpeg2/hevc/vp8). Signed-off-by: Zhong Li Signed-off-by: Maxym Dmytrychenko --- libavcodec/qsvdec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index c1b6238cfb76b..31cce2d83895d 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -323,6 +323,8 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, bs.DataLength = avpkt->size; bs.MaxLength = bs.DataLength; bs.TimeStamp = avpkt->pts; + if (avctx->field_order == AV_FIELD_PROGRESSIVE) + bs.DataFlag |= MFX_BITSTREAM_COMPLETE_FRAME; } sync = av_mallocz(sizeof(*sync)); @@ -516,6 +518,7 @@ int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, pkt->data, pkt->size, pkt->pts, pkt->dts, pkt->pos); + avctx->field_order = q->parser->field_order; /* TODO: flush delayed frames on reinit */ if (q->parser->format != q->orig_pix_fmt || FFALIGN(q->parser->coded_width, 16) != FFALIGN(avctx->coded_width, 16) || @@ -540,7 +543,6 @@ int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, avctx->height = q->parser->height; avctx->coded_width = FFALIGN(q->parser->coded_width, 16); avctx->coded_height = FFALIGN(q->parser->coded_height, 16); - avctx->field_order = q->parser->field_order; avctx->level = q->avctx_internal->level; avctx->profile = q->avctx_internal->profile; From 249aca8f98ff7fb09c12ea68e23c862c62203b95 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 8 Apr 2018 03:29:44 +0200 Subject: [PATCH 2406/2557] avcodec/movtextdec: Check style_start/end Limits based on 3GPP TS 26.245 V14.0.0 Fixes: Timeout Fixes: 6377/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MOVTEXT_fuzzer-5175929115508736 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Philip Langdale Signed-off-by: Michael Niedermayer --- libavcodec/movtextdec.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index 89ac791602c65..c38c5edce6783 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -299,6 +299,14 @@ static int decode_styl(const uint8_t *tsmb, MovTextContext *m, AVPacket *avpkt) m->s_temp->style_start = AV_RB16(tsmb); tsmb += 2; m->s_temp->style_end = AV_RB16(tsmb); + + if ( m->s_temp->style_end < m->s_temp->style_start + || (m->count_s && m->s_temp->style_start < m->s[m->count_s - 1]->style_end)) { + av_freep(&m->s_temp); + mov_text_cleanup(m); + return AVERROR(ENOMEM); + } + tsmb += 2; m->s_temp->style_fontID = AV_RB16(tsmb); tsmb += 2; From 3b2fd960481d90d0788e1958a2b1469ac55ba3c5 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Tue, 27 Mar 2018 20:43:06 +0800 Subject: [PATCH 2407/2557] avcodec/arm/hevcdsp_sao : add NEON optimization for sao Signed-off-by: Meng Wang Reviewed-by: Shengbin Meng Signed-off-by: Michael Niedermayer --- libavcodec/arm/Makefile | 3 +- libavcodec/arm/hevcdsp_init_neon.c | 59 ++++++++++ libavcodec/arm/hevcdsp_sao_neon.S | 181 +++++++++++++++++++++++++++++ 3 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 libavcodec/arm/hevcdsp_sao_neon.S diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile index fd2401f4e5c9e..e656011c3c52f 100644 --- a/libavcodec/arm/Makefile +++ b/libavcodec/arm/Makefile @@ -138,7 +138,8 @@ NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/synth_filter_neon.o NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_neon.o \ arm/hevcdsp_deblock_neon.o \ arm/hevcdsp_idct_neon.o \ - arm/hevcdsp_qpel_neon.o + arm/hevcdsp_qpel_neon.o \ + arm/hevcdsp_sao_neon.o NEON-OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_neon.o NEON-OBJS-$(CONFIG_RV40_DECODER) += arm/rv34dsp_neon.o \ arm/rv40dsp_neon.o diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c index a4628d2a93ff1..201a088dac056 100644 --- a/libavcodec/arm/hevcdsp_init_neon.c +++ b/libavcodec/arm/hevcdsp_init_neon.c @@ -21,8 +21,16 @@ #include "libavutil/attributes.h" #include "libavutil/arm/cpu.h" #include "libavcodec/hevcdsp.h" +#include "libavcodec/avcodec.h" #include "hevcdsp_arm.h" +void ff_hevc_sao_band_filter_neon_8_wrapper(uint8_t *_dst, uint8_t *_src, + ptrdiff_t stride_dst, ptrdiff_t stride_src, + int16_t *sao_offset_val, int sao_left_class, + int width, int height); +void ff_hevc_sao_edge_filter_neon_8_wrapper(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *sao_offset_val, + int eo, int width, int height); + void ff_hevc_v_loop_filter_luma_neon(uint8_t *_pix, ptrdiff_t _stride, int _beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q); void ff_hevc_h_loop_filter_luma_neon(uint8_t *_pix, ptrdiff_t _stride, int _beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q); void ff_hevc_v_loop_filter_chroma_neon(uint8_t *_pix, ptrdiff_t _stride, int *_tc, uint8_t *_no_p, uint8_t *_no_q); @@ -142,6 +150,47 @@ QPEL_FUNC_UW(ff_hevc_put_qpel_uw_h3v2_neon_8); QPEL_FUNC_UW(ff_hevc_put_qpel_uw_h3v3_neon_8); #undef QPEL_FUNC_UW +void ff_hevc_sao_band_filter_neon_8(uint8_t *dst, uint8_t *src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int width, int height, int16_t *offset_table); + +void ff_hevc_sao_band_filter_neon_8_wrapper(uint8_t *_dst, uint8_t *_src, + ptrdiff_t stride_dst, ptrdiff_t stride_src, + int16_t *sao_offset_val, int sao_left_class, + int width, int height) { + uint8_t *dst = _dst; + uint8_t *src = _src; + int16_t offset_table[32] = {0}; + int k; + + for (k = 0; k < 4; k++) { + offset_table[(k + sao_left_class) & 31] = sao_offset_val[k + 1]; + } + + ff_hevc_sao_band_filter_neon_8(dst, src, stride_dst, stride_src, width, height, offset_table); +} + +void ff_hevc_sao_edge_filter_neon_8(uint8_t *dst, uint8_t *src, ptrdiff_t stride_dst, ptrdiff_t stride_src, int width, int height, + int a_stride, int b_stride, int16_t *sao_offset_val, uint8_t *edge_idx); + +void ff_hevc_sao_edge_filter_neon_8_wrapper(uint8_t *_dst, uint8_t *_src, ptrdiff_t stride_dst, int16_t *sao_offset_val, + int eo, int width, int height) { + static uint8_t edge_idx[] = { 1, 2, 0, 3, 4 }; + static const int8_t pos[4][2][2] = { + { { -1, 0 }, { 1, 0 } }, // horizontal + { { 0, -1 }, { 0, 1 } }, // vertical + { { -1, -1 }, { 1, 1 } }, // 45 degree + { { 1, -1 }, { -1, 1 } }, // 135 degree + }; + uint8_t *dst = _dst; + uint8_t *src = _src; + int a_stride, b_stride; + ptrdiff_t stride_src = (2*MAX_PB_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); + + a_stride = pos[eo][0][0] + pos[eo][0][1] * stride_src; + b_stride = pos[eo][1][0] + pos[eo][1][1] * stride_src; + + ff_hevc_sao_edge_filter_neon_8(dst, src, stride_dst, stride_src, width, height, a_stride, b_stride, sao_offset_val, edge_idx); +} + void ff_hevc_put_qpel_neon_wrapper(int16_t *dst, uint8_t *src, ptrdiff_t srcstride, int height, intptr_t mx, intptr_t my, int width) { @@ -168,6 +217,16 @@ av_cold void ff_hevc_dsp_init_neon(HEVCDSPContext *c, const int bit_depth) c->hevc_h_loop_filter_luma = ff_hevc_h_loop_filter_luma_neon; c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_neon; c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_neon; + c->sao_band_filter[0] = ff_hevc_sao_band_filter_neon_8_wrapper; + c->sao_band_filter[1] = ff_hevc_sao_band_filter_neon_8_wrapper; + c->sao_band_filter[2] = ff_hevc_sao_band_filter_neon_8_wrapper; + c->sao_band_filter[3] = ff_hevc_sao_band_filter_neon_8_wrapper; + c->sao_band_filter[4] = ff_hevc_sao_band_filter_neon_8_wrapper; + c->sao_edge_filter[0] = ff_hevc_sao_edge_filter_neon_8_wrapper; + c->sao_edge_filter[1] = ff_hevc_sao_edge_filter_neon_8_wrapper; + c->sao_edge_filter[2] = ff_hevc_sao_edge_filter_neon_8_wrapper; + c->sao_edge_filter[3] = ff_hevc_sao_edge_filter_neon_8_wrapper; + c->sao_edge_filter[4] = ff_hevc_sao_edge_filter_neon_8_wrapper; c->add_residual[0] = ff_hevc_add_residual_4x4_8_neon; c->add_residual[1] = ff_hevc_add_residual_8x8_8_neon; c->add_residual[2] = ff_hevc_add_residual_16x16_8_neon; diff --git a/libavcodec/arm/hevcdsp_sao_neon.S b/libavcodec/arm/hevcdsp_sao_neon.S new file mode 100644 index 0000000000000..347167951b7ec --- /dev/null +++ b/libavcodec/arm/hevcdsp_sao_neon.S @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2017 Meng Wang + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "libavutil/arm/asm.S" +#include "neon.S" + +function ff_hevc_sao_band_filter_neon_8, export=1 + push {r4-r10} + ldr r5, [sp, #28] // width + ldr r4, [sp, #32] // height + ldr r8, [sp, #36] // offset_table + vpush {d8-d15} + mov r12, r4 // r12 = height + mov r6, r0 // r6 = r0 = dst + mov r7, r1 // r7 = r1 = src + vldm r8, {q0-q3} + vmov.u16 q15, #1 + vmov.u8 q14, #32 +0: pld [r1] + vld1.8 {d16}, [r1], r3 + cmp r5, #4 + beq 4f +8: subs r4, #1 + vshr.u8 d17, d16, #3 // index = [src>>3] + vshll.u8 q9, d17, #1 // lowIndex = 2*index + vadd.u16 q11, q9, q15 // highIndex = (2*index+1) << 8 + vshl.u16 q10, q11, #8 // q10: highIndex; q9: lowIndex; + vadd.u16 q10, q9 // combine high and low index; + // Look-up Table Round 1; index range: 0-15 + vtbx.8 d24, {q0-q1}, d20 + vtbx.8 d25, {q0-q1}, d21 + // Look-up Table Round 2; index range: 16-31 + vsub.u8 q10, q14 // Look-up with 8bit + vtbx.8 d24, {q2-q3}, d20 + vtbx.8 d25, {q2-q3}, d21 + vaddw.u8 q13, q12, d16 + vqmovun.s16 d8, q13 + vst1.8 d8, [r0], r2 + vld1.8 {d16}, [r1], r3 + bne 8b + subs r5, #8 + beq 99f + mov r4, r12 + add r6, #8 + mov r0, r6 + add r7, #8 + mov r1, r7 + b 0b +4: subs r4, #1 + vshr.u8 d17, d16, #3 // src>>3 + vshll.u8 q9, d17, #1 // lowIndex = 2*index + vadd.u16 q11, q9, q15 // highIndex = (2*index+1) << 8 + vshl.u16 q10, q11, #8 // q10: highIndex; q9: lowIndex; + vadd.u16 q10, q9 // combine high and low index; + // Look-up Table Round 1; index range: 0-15 + vtbx.8 d24, {q0-q1}, d20 + vtbx.8 d25, {q0-q1}, d21 + // Look-up Table Round 2; index range: 16-32 + vsub.u8 q10, q14 // Look-up with 8bit + vtbx.8 d24, {q2-q3}, d20 + vtbx.8 d25, {q2-q3}, d21 + vaddw.u8 q13, q12, d16 + vqmovun.s16 d14, q13 + vst1.32 d14[0], [r0], r2 + vld1.32 {d16[0]}, [r1], r3 + bne 4b + b 99f +99: + vpop {d8-d15} + pop {r4-r10} + bx lr +endfunc + +function ff_hevc_sao_edge_filter_neon_8, export=1 + push {r4-r11} + ldr r5, [sp, #32] // width + ldr r4, [sp, #36] // height + ldr r8, [sp, #40] // a_stride + ldr r9, [sp, #44] // b_stride + ldr r10, [sp, #48] // sao_offset_val + ldr r11, [sp, #52] // edge_idx + vpush {d8-d15} + mov r12, r4 // r12 = height + mov r6, r0 // r6 = r0 = dst + mov r7, r1 // r7 = r1 = src + vld1.8 {d0}, [r11] // edge_idx tabel load in d0 5x8bit + vld1.16 {q1}, [r10] // sao_offset_val table load in q1, 5x16bit + vmov.u8 d1, #2 + vmov.u16 q2, #1 +0: mov r10, r1 + add r10, r8 // src[x + a_stride] + mov r11, r1 + add r11, r9 // src[x + b_stride] + pld [r1] + vld1.8 {d16}, [r1], r3 // src[x] 8x8bit + vld1.8 {d17}, [r10], r3 // src[x + a_stride] + vld1.8 {d18}, [r11], r3 // src[x + b_stride] + cmp r5, #4 + beq 4f +8: subs r4, #1 + vcgt.u8 d8, d16, d17 + vshr.u8 d9, d8, #7 + vclt.u8 d8, d16, d17 + vadd.u8 d8, d9 // diff0 + vcgt.u8 d10, d16, d18 + vshr.u8 d11, d10, #7 + vclt.u8 d10, d16, d18 + vadd.u8 d10, d11 // diff1 + vadd.s8 d8, d10 + vadd.s8 d8, d1 + vtbx.8 d9, {d0}, d8 // offset_val + vshll.u8 q6, d9, #1 // lowIndex + vadd.u16 q7, q6, q2 + vshl.u16 q10, q7, #8 // highIndex + vadd.u16 q10, q6 // combine lowIndex and highIndex, offset_val + vtbx.8 d22, {q1}, d20 + vtbx.8 d23, {q1}, d21 + vaddw.u8 q12, q11, d16 + vqmovun.s16 d26, q12 + vst1.8 d26, [r0], r2 + vld1.8 {d16}, [r1], r3 // src[x] 8x8bit + vld1.8 {d17}, [r10], r3 // src[x + a_stride] + vld1.8 {d18}, [r11], r3 // src[x + b_stride] + bne 8b + subs r5, #8 + beq 99f + mov r4, r12 + add r6, #8 + mov r0, r6 + add r7, #8 + mov r1, r7 + b 0b +4: subs r4, #1 + vcgt.u8 d8, d16, d17 + vshr.u8 d9, d8, #7 + vclt.u8 d8, d16, d17 + vadd.u8 d8, d9 // diff0 + vcgt.u8 d10, d16, d18 + vshr.u8 d11, d10, #7 + vclt.u8 d10, d16, d18 + vadd.u8 d10, d11 // diff1 + vadd.s8 d8, d10 + vadd.s8 d8, d1 + vtbx.8 d9, {d0}, d8 // offset_val + vshll.u8 q6, d9, #1 // lowIndex + vadd.u16 q7, q6, q2 + vshl.u16 q10, q7, #8 // highIndex + vadd.u16 q10, q6 // combine lowIndex and highIndex, offset_val + vtbx.8 d22, {q1}, d20 + vtbx.8 d23, {q1}, d21 + vaddw.u8 q12, q11, d16 + vqmovun.s16 d26, q12 + vst1.32 d26[0], [r0], r2 + vld1.32 {d16[0]}, [r1], r3 + vld1.32 {d17[0]}, [r10], r3 // src[x + a_stride] + vld1.32 {d18[0]}, [r11], r3 // src[x + b_stride] + bne 4b + b 99f +99: + vpop {d8-d15} + pop {r4-r11} + bx lr +endfunc From f821b2ea276ebe7ecd854fbef9e3acd691bbf074 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 4 Apr 2018 17:29:34 +0200 Subject: [PATCH 2408/2557] avprobe: Support printing strings with empty keys --- avtools/avprobe.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/avtools/avprobe.c b/avtools/avprobe.c index a9ca1934ca574..d6809042f786f 100644 --- a/avtools/avprobe.c +++ b/avtools/avprobe.c @@ -235,10 +235,14 @@ static void ini_print_integer(const char *key, int64_t value) static void ini_print_string(const char *key, const char *value) { - ini_escape_print(key); - avio_printf(probe_out, "="); - ini_escape_print(value); - avio_w8(probe_out, '\n'); + if (key) { + ini_escape_print(key); + avio_printf(probe_out, "=%s\n", value); + } else { + if (octx.prefix[octx.level -1].nb_elems) + avio_printf(probe_out, ","); + avio_printf(probe_out, "%s", value); + } } /* @@ -329,14 +333,24 @@ static void json_escape_print(const char *s) static void json_print_string(const char *key, const char *value) { - if (octx.prefix[octx.level -1].nb_elems) - avio_printf(probe_out, ",\n"); - AVP_INDENT(); - avio_w8(probe_out, '\"'); - json_escape_print(key); - avio_printf(probe_out, "\" : \""); - json_escape_print(value); - avio_w8(probe_out, '\"'); + if (key) { + if (octx.prefix[octx.level -1].nb_elems) + avio_printf(probe_out, ",\n"); + AVP_INDENT(); + avio_w8(probe_out, '\"'); + json_escape_print(key); + avio_printf(probe_out, "\" : \""); + json_escape_print(value); + avio_w8(probe_out, '\"'); + } else { + if (octx.prefix[octx.level -1].nb_elems) + avio_printf(probe_out, ", "); + else + AVP_INDENT(); + avio_w8(probe_out, '\"'); + json_escape_print(value); + avio_w8(probe_out, '\"'); + } } /* From cc06f7bd10c236539b4f6f87b795c459dd873770 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Fri, 16 Mar 2018 11:34:25 -0400 Subject: [PATCH 2409/2557] libx265: Support tiny video sizes Where tiny is less than the default CTU size. Signed-off-by: Vittorio Giovara --- libavcodec/libx265.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index fd5452193b9d9..8f1d60b4e5ba7 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -122,6 +122,17 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) ctx->params->sourceHeight = avctx->height; ctx->params->bEnablePsnr = !!(avctx->flags & AV_CODEC_FLAG_PSNR); + /* Tune the CTU size based on input resolution. */ + if (ctx->params->sourceWidth < 64 || ctx->params->sourceHeight < 64) + ctx->params->maxCUSize = 32; + if (ctx->params->sourceWidth < 32 || ctx->params->sourceHeight < 32) + ctx->params->maxCUSize = 16; + if (ctx->params->sourceWidth < 16 || ctx->params->sourceHeight < 16) { + av_log(avctx, AV_LOG_ERROR, "Image size is too small (%dx%d).\n", + ctx->params->sourceWidth, ctx->params->sourceHeight); + return AVERROR(EINVAL); + } + if ((avctx->color_primaries <= AVCOL_PRI_BT2020 && avctx->color_primaries != AVCOL_PRI_UNSPECIFIED) || (avctx->color_trc <= AVCOL_TRC_BT2020_12 && From c31f6b1d61759436ef50c094e7f4c8005e97614a Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 4 Apr 2018 17:29:35 +0200 Subject: [PATCH 2410/2557] avprobe: Print a user-friendly version of the display matrix Shift fixed point numbers to be actual decimal numbers. --- avtools/avprobe.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/avtools/avprobe.c b/avtools/avprobe.c index d6809042f786f..0ea9ff46fdfeb 100644 --- a/avtools/avprobe.c +++ b/avtools/avprobe.c @@ -131,6 +131,7 @@ typedef struct PrintContext { static AVIOContext *probe_out = NULL; static PrintContext octx; #define AVP_INDENT() avio_printf(probe_out, "%*c", octx.level * 2, ' ') +#define CONV_FP(x,fp) ((double) (x)) / (1 << fp) /* * Default format, INI @@ -816,6 +817,15 @@ static void show_stream(InputFile *ifile, InputStream *ist) for (j = 0; j < 9; j++) probe_int(NULL, ((int32_t *)sd->data)[j]); probe_array_footer("matrix", 1); + probe_array_header("matrix_str", 1); + for (j = 0; j < 9; j++) { + char buf[32]; + int fp = (j == 2 || j == 5 || j == 8) ? 30 : 16; + int32_t val = ((int32_t *)sd->data)[j]; + value_string(buf, sizeof(buf), CONV_FP(val, fp), ""); + probe_str(NULL, buf); + } + probe_array_footer("matrix_str", 1); probe_int("rotation", av_display_rotation_get((int32_t *)sd->data)); probe_object_footer("displaymatrix"); From c7ab6aff66cba2f265f656ce8d56aa428d4ada76 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 21 Dec 2017 20:23:14 +0100 Subject: [PATCH 2411/2557] w32pthreads: always use Vista+ API, drop XP support This removes the XP compatibility code, and switches entirely to SRW locks, which are available starting at Windows Vista. This removes CRITICAL_SECTION use, which allows us to add PTHREAD_MUTEX_INITIALIZER, which will be useful later. Windows XP is hereby not a supported build target anymore. Signed-off-by: Diego Biurrun --- Changelog | 2 + compat/w32pthreads.h | 269 ++----------------------------------- configure | 19 +-- libavcodec/pthread_frame.c | 4 - libavcodec/pthread_slice.c | 4 - libavfilter/pthread.c | 4 - 6 files changed, 23 insertions(+), 279 deletions(-) diff --git a/Changelog b/Changelog index 53562a1aa0e88..35b6c066a7078 100644 --- a/Changelog +++ b/Changelog @@ -22,6 +22,8 @@ version : - Intel QSV-accelerated overlay filter - AV1 Support through libaom - Haivision SRT protocol via libsrt +- Dropped support for building for Windows XP. The minimum supported Windows + version is Windows Vista. version 12: diff --git a/compat/w32pthreads.h b/compat/w32pthreads.h index f38f767d8fb45..c5699830e2b36 100644 --- a/compat/w32pthreads.h +++ b/compat/w32pthreads.h @@ -39,11 +39,6 @@ #include #include -#if _WIN32_WINNT < 0x0600 && defined(__MINGW32__) -#undef MemoryBarrier -#define MemoryBarrier __sync_synchronize -#endif - #include "libavutil/attributes.h" #include "libavutil/internal.h" #include "libavutil/mem.h" @@ -55,24 +50,15 @@ typedef struct pthread_t { void *ret; } pthread_t; -/* the conditional variable api for windows 6.0+ uses critical sections and - * not mutexes */ -typedef CRITICAL_SECTION pthread_mutex_t; - -/* This is the CONDITION_VARIABLE typedef for using Windows' native - * conditional variables on kernels 6.0+. */ -#if HAVE_CONDITION_VARIABLE_PTR +/* use lightweight mutex/condition variable API for Windows Vista and later */ +typedef SRWLOCK pthread_mutex_t; typedef CONDITION_VARIABLE pthread_cond_t; -#else -typedef struct pthread_cond_t { - void *Ptr; -} pthread_cond_t; -#endif -#if _WIN32_WINNT >= 0x0600 +#define PTHREAD_MUTEX_INITIALIZER SRWLOCK_INIT +#define PTHREAD_COND_INITIALIZER CONDITION_VARIABLE_INIT + #define InitializeCriticalSection(x) InitializeCriticalSectionEx(x, 0, 0) #define WaitForSingleObject(a, b) WaitForSingleObjectEx(a, b, FALSE) -#endif static av_unused unsigned __stdcall attribute_align_arg win32thread_worker(void *arg) { @@ -103,26 +89,25 @@ static av_unused void pthread_join(pthread_t thread, void **value_ptr) static inline int pthread_mutex_init(pthread_mutex_t *m, void* attr) { - InitializeCriticalSection(m); + InitializeSRWLock(m); return 0; } static inline int pthread_mutex_destroy(pthread_mutex_t *m) { - DeleteCriticalSection(m); + /* Unlocked SWR locks use no resources */ return 0; } static inline int pthread_mutex_lock(pthread_mutex_t *m) { - EnterCriticalSection(m); + AcquireSRWLockExclusive(m); return 0; } static inline int pthread_mutex_unlock(pthread_mutex_t *m) { - LeaveCriticalSection(m); + ReleaseSRWLockExclusive(m); return 0; } -#if _WIN32_WINNT >= 0x0600 typedef INIT_ONCE pthread_once_t; #define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT @@ -155,7 +140,7 @@ static inline void pthread_cond_broadcast(pthread_cond_t *cond) static inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { - SleepConditionVariableCS(cond, mutex, INFINITE); + SleepConditionVariableSRW(cond, mutex, INFINITE, 0); return 0; } @@ -164,238 +149,4 @@ static inline void pthread_cond_signal(pthread_cond_t *cond) WakeConditionVariable(cond); } -#else // _WIN32_WINNT < 0x0600 - -/* atomic init state of dynamically loaded functions */ -static LONG w32thread_init_state = 0; -static av_unused void w32thread_init(void); - -/* for pre-Windows 6.0 platforms, define INIT_ONCE struct, - * compatible to the one used in the native API */ - -typedef union pthread_once_t { - void * Ptr; ///< For the Windows 6.0+ native functions - LONG state; ///< For the pre-Windows 6.0 compat code -} pthread_once_t; - -#define PTHREAD_ONCE_INIT {0} - -/* function pointers to init once API on windows 6.0+ kernels */ -static BOOL (WINAPI *initonce_begin)(pthread_once_t *lpInitOnce, DWORD dwFlags, BOOL *fPending, void **lpContext); -static BOOL (WINAPI *initonce_complete)(pthread_once_t *lpInitOnce, DWORD dwFlags, void *lpContext); - -/* pre-Windows 6.0 compat using a spin-lock */ -static inline void w32thread_once_fallback(LONG volatile *state, void (*init_routine)(void)) -{ - switch (InterlockedCompareExchange(state, 1, 0)) { - /* Initial run */ - case 0: - init_routine(); - InterlockedExchange(state, 2); - break; - /* Another thread is running init */ - case 1: - while (1) { - MemoryBarrier(); - if (*state == 2) - break; - Sleep(0); - } - break; - /* Initialization complete */ - case 2: - break; - } -} - -static av_unused int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) -{ - w32thread_once_fallback(&w32thread_init_state, w32thread_init); - - /* Use native functions on Windows 6.0+ */ - if (initonce_begin && initonce_complete) { - BOOL pending = FALSE; - initonce_begin(once_control, 0, &pending, NULL); - if (pending) - init_routine(); - initonce_complete(once_control, 0, NULL); - return 0; - } - - w32thread_once_fallback(&once_control->state, init_routine); - return 0; -} - -/* for pre-Windows 6.0 platforms we need to define and use our own condition - * variable and api */ - -typedef struct win32_cond_t { - pthread_mutex_t mtx_broadcast; - pthread_mutex_t mtx_waiter_count; - volatile int waiter_count; - HANDLE semaphore; - HANDLE waiters_done; - volatile int is_broadcast; -} win32_cond_t; - -/* function pointers to conditional variable API on windows 6.0+ kernels */ -static void (WINAPI *cond_broadcast)(pthread_cond_t *cond); -static void (WINAPI *cond_init)(pthread_cond_t *cond); -static void (WINAPI *cond_signal)(pthread_cond_t *cond); -static BOOL (WINAPI *cond_wait)(pthread_cond_t *cond, pthread_mutex_t *mutex, - DWORD milliseconds); - -static av_unused void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr) -{ - win32_cond_t *win32_cond = NULL; - - w32thread_once_fallback(&w32thread_init_state, w32thread_init); - - if (cond_init) { - cond_init(cond); - return; - } - - /* non native condition variables */ - win32_cond = av_mallocz(sizeof(win32_cond_t)); - if (!win32_cond) - return; - cond->Ptr = win32_cond; - win32_cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); - if (!win32_cond->semaphore) - return; - win32_cond->waiters_done = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!win32_cond->waiters_done) - return; - - pthread_mutex_init(&win32_cond->mtx_waiter_count, NULL); - pthread_mutex_init(&win32_cond->mtx_broadcast, NULL); -} - -static av_unused void pthread_cond_destroy(pthread_cond_t *cond) -{ - win32_cond_t *win32_cond = cond->Ptr; - /* native condition variables do not destroy */ - if (cond_init) - return; - - /* non native condition variables */ - CloseHandle(win32_cond->semaphore); - CloseHandle(win32_cond->waiters_done); - pthread_mutex_destroy(&win32_cond->mtx_waiter_count); - pthread_mutex_destroy(&win32_cond->mtx_broadcast); - av_freep(&win32_cond); - cond->Ptr = NULL; -} - -static av_unused void pthread_cond_broadcast(pthread_cond_t *cond) -{ - win32_cond_t *win32_cond = cond->Ptr; - int have_waiter; - - if (cond_broadcast) { - cond_broadcast(cond); - return; - } - - /* non native condition variables */ - pthread_mutex_lock(&win32_cond->mtx_broadcast); - pthread_mutex_lock(&win32_cond->mtx_waiter_count); - have_waiter = 0; - - if (win32_cond->waiter_count) { - win32_cond->is_broadcast = 1; - have_waiter = 1; - } - - if (have_waiter) { - ReleaseSemaphore(win32_cond->semaphore, win32_cond->waiter_count, NULL); - pthread_mutex_unlock(&win32_cond->mtx_waiter_count); - WaitForSingleObject(win32_cond->waiters_done, INFINITE); - ResetEvent(win32_cond->waiters_done); - win32_cond->is_broadcast = 0; - } else - pthread_mutex_unlock(&win32_cond->mtx_waiter_count); - pthread_mutex_unlock(&win32_cond->mtx_broadcast); -} - -static av_unused int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) -{ - win32_cond_t *win32_cond = cond->Ptr; - int last_waiter; - if (cond_wait) { - cond_wait(cond, mutex, INFINITE); - return 0; - } - - /* non native condition variables */ - pthread_mutex_lock(&win32_cond->mtx_broadcast); - pthread_mutex_lock(&win32_cond->mtx_waiter_count); - win32_cond->waiter_count++; - pthread_mutex_unlock(&win32_cond->mtx_waiter_count); - pthread_mutex_unlock(&win32_cond->mtx_broadcast); - - // unlock the external mutex - pthread_mutex_unlock(mutex); - WaitForSingleObject(win32_cond->semaphore, INFINITE); - - pthread_mutex_lock(&win32_cond->mtx_waiter_count); - win32_cond->waiter_count--; - last_waiter = !win32_cond->waiter_count || !win32_cond->is_broadcast; - pthread_mutex_unlock(&win32_cond->mtx_waiter_count); - - if (last_waiter) - SetEvent(win32_cond->waiters_done); - - // lock the external mutex - return pthread_mutex_lock(mutex); -} - -static av_unused void pthread_cond_signal(pthread_cond_t *cond) -{ - win32_cond_t *win32_cond = cond->Ptr; - int have_waiter; - if (cond_signal) { - cond_signal(cond); - return; - } - - pthread_mutex_lock(&win32_cond->mtx_broadcast); - - /* non-native condition variables */ - pthread_mutex_lock(&win32_cond->mtx_waiter_count); - have_waiter = win32_cond->waiter_count; - pthread_mutex_unlock(&win32_cond->mtx_waiter_count); - - if (have_waiter) { - ReleaseSemaphore(win32_cond->semaphore, 1, NULL); - WaitForSingleObject(win32_cond->waiters_done, INFINITE); - ResetEvent(win32_cond->waiters_done); - } - - pthread_mutex_unlock(&win32_cond->mtx_broadcast); -} -#endif - -static av_unused void w32thread_init(void) -{ -#if _WIN32_WINNT < 0x0600 - HANDLE kernel_dll = GetModuleHandle(TEXT("kernel32.dll")); - /* if one is available, then they should all be available */ - cond_init = (void (WINAPI*)(pthread_cond_t *)) - GetProcAddress(kernel_dll, "InitializeConditionVariable"); - cond_broadcast = (void (WINAPI*)(pthread_cond_t *)) - GetProcAddress(kernel_dll, "WakeAllConditionVariable"); - cond_signal = (void (WINAPI*)(pthread_cond_t *)) - GetProcAddress(kernel_dll, "WakeConditionVariable"); - cond_wait = (BOOL (WINAPI*)(pthread_cond_t *, pthread_mutex_t *, DWORD)) - GetProcAddress(kernel_dll, "SleepConditionVariableCS"); - initonce_begin = (BOOL (WINAPI*)(pthread_once_t *, DWORD, BOOL *, void **)) - GetProcAddress(kernel_dll, "InitOnceBeginInitialize"); - initonce_complete = (BOOL (WINAPI*)(pthread_once_t *, DWORD, void *)) - GetProcAddress(kernel_dll, "InitOnceComplete"); -#endif - -} - #endif /* LIBAV_COMPAT_W32PTHREADS_H */ diff --git a/configure b/configure index 77754d0f51252..3c7b6a0981d24 100755 --- a/configure +++ b/configure @@ -1732,7 +1732,6 @@ TOOLCHAIN_FEATURES=" " TYPES_LIST=" - CONDITION_VARIABLE_Ptr CUVIDDECODECREATEINFO_bitDepthMinus8 socklen_t struct_addrinfo @@ -2002,7 +2001,7 @@ atomics_gcc_if="sync_val_compare_and_swap" atomics_suncc_if="atomic_cas_ptr machine_rw_barrier" atomics_win32_if="MemoryBarrier" atomics_native_if_any="$ATOMICS_LIST" -w32threads_deps="atomics_native" +w32threads_deps="atomics_native CONDITION_VARIABLE" threads_if_any="$THREADS_LIST" # subsystems @@ -4103,12 +4102,16 @@ probe_libc(){ elif test_${pfx}cpp_condition newlib.h "defined _NEWLIB_VERSION"; then eval ${pfx}libc_type=newlib add_${pfx}cppflags -U__STRICT_ANSI__ -D_XOPEN_SOURCE=600 + test_${pfx}cpp_condition windows.h "!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600" && + add_${pfx}cppflags -D_WIN32_WINNT=0x0600 # MinGW64 is backwards compatible with MinGW32, so check for it first. elif test_${pfx}cpp_condition _mingw.h "defined __MINGW64_VERSION_MAJOR"; then eval ${pfx}libc_type=mingw64 add_${pfx}cppflags -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO=1 eval test \$${pfx_no_}cc_type = "gcc" && add_${pfx}cppflags -D__printf__=__gnu_printf__ + test_${pfx}cpp_condition windows.h "!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600" && + add_${pfx}cppflags -D_WIN32_WINNT=0x0600 elif test_${pfx}cpp_condition _mingw.h "defined __MINGW_VERSION" || test_${pfx}cpp_condition _mingw.h "defined __MINGW32_VERSION"; then eval ${pfx}libc_type=mingw32 @@ -4118,8 +4121,8 @@ probe_libc(){ add_${pfx}cppflags -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO=1 test_${pfx}cpp_condition _mingw.h "__MSVCRT_VERSION__ < 0x0700" && add_${pfx}cppflags -D__MSVCRT_VERSION__=0x0700 - test_${pfx}cpp_condition windows.h "defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0502" && - add_${pfx}cppflags -D_WIN32_WINNT=0x0502 + test_${pfx}cpp_condition windows.h "!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600" && + add_${pfx}cppflags -D_WIN32_WINNT=0x0600 eval test \$${pfx_no_}cc_type = "gcc" && add_${pfx}cppflags -D__printf__=__gnu_printf__ elif test_${pfx}cpp_condition crtversion.h "defined _VC_CRT_MAJOR_VERSION"; then @@ -4139,14 +4142,14 @@ probe_libc(){ # 0x601 by default unless something else is set by the user. # This can easily lead to us detecting functions only present # in such new versions and producing binaries requiring windows 7.0. - # Therefore explicitly set the default to XP unless the user has + # Therefore explicitly set the default to Vista unless the user has # set something else on the command line. # Don't do this if WINAPI_FAMILY is set and is set to a non-desktop # family. For these cases, configure is free to use any functions # found in the SDK headers by default. (Alternatively, we could force # _WIN32_WINNT to 0x0602 in that case.) test_${pfx}cpp_condition stdlib.h "defined(_WIN32_WINNT)" || - { test_${pfx}cpp < #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) @@ -4553,7 +4556,6 @@ check_func_headers windows.h MapViewOfFile check_func_headers windows.h SetConsoleTextAttribute check_func_headers windows.h Sleep check_func_headers windows.h VirtualAlloc -check_struct windows.h "CONDITION_VARIABLE" Ptr check_header direct.h check_header dxgidebug.h @@ -4605,7 +4607,8 @@ check_type "va/va.h va/va_enc_vp9.h" "VAEncPictureParameterBufferVP9" check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC" if ! disabled w32threads && ! enabled pthreads; then - check_lib w32threads "windows.h process.h" _beginthreadex + check_lib w32threads "windows.h process.h" _beginthreadex && + check_type "windows.h" CONDITION_VARIABLE fi # check for some common methods of building with pthread support diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index a72391ba36749..338b008f6ffd3 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -658,10 +658,6 @@ int ff_frame_thread_init(AVCodecContext *avctx) FrameThreadContext *fctx; int i, err = 0; -#if HAVE_W32THREADS - w32thread_init(); -#endif - if (!thread_count) { int nb_cpus = av_cpu_count(); av_log(avctx, AV_LOG_DEBUG, "detected %d logical cores\n", nb_cpus); diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c index d7c73f08840fc..d4af37b3f4acf 100644 --- a/libavcodec/pthread_slice.c +++ b/libavcodec/pthread_slice.c @@ -169,10 +169,6 @@ int ff_slice_thread_init(AVCodecContext *avctx) SliceThreadContext *c; int thread_count = avctx->thread_count; -#if HAVE_W32THREADS - w32thread_init(); -#endif - if (!thread_count) { int nb_cpus = av_cpu_count(); av_log(avctx, AV_LOG_DEBUG, "detected %d logical cores\n", nb_cpus); diff --git a/libavfilter/pthread.c b/libavfilter/pthread.c index 2ebcc9753a516..1e6d1039e3171 100644 --- a/libavfilter/pthread.c +++ b/libavfilter/pthread.c @@ -200,10 +200,6 @@ int ff_graph_thread_init(AVFilterGraph *graph) { int ret; -#if HAVE_W32THREADS - w32thread_init(); -#endif - if (graph->nb_threads == 1) { graph->thread_type = 0; return 0; From 8f144d9e3d5cb2ca92e5bdf7cc9f72effa1bd2ce Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 2 Apr 2018 01:06:18 +0200 Subject: [PATCH 2412/2557] Drop Windows XP support remnants --- libavcodec/dxva2_h264.c | 6 +----- libavcodec/dxva2_hevc.c | 6 +----- libavcodec/dxva2_mpeg2.c | 7 ++----- libavcodec/dxva2_vc1.c | 6 +----- libavutil/hwcontext_d3d11va.c | 9 +-------- libavutil/hwcontext_dxva2.c | 4 ---- 6 files changed, 6 insertions(+), 32 deletions(-) diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c index 50e7863bf2bba..790e4a214b075 100644 --- a/libavcodec/dxva2_h264.c +++ b/libavcodec/dxva2_h264.c @@ -20,16 +20,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "dxva2_internal.h" #include "h264dec.h" #include "h264data.h" #include "h264_ps.h" #include "mpegutils.h" -// The headers above may include w32threads.h, which uses the original -// _WIN32_WINNT define, while dxva2_internal.h redefines it to target a -// potentially newer version. -#include "dxva2_internal.h" - struct dxva2_picture_context { DXVA_PicParams_H264 pp; DXVA_Qmatrix_H264 qm; diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c index 02d3b9b1526eb..d2d80802a21e5 100644 --- a/libavcodec/dxva2_hevc.c +++ b/libavcodec/dxva2_hevc.c @@ -22,14 +22,10 @@ #include "libavutil/avassert.h" +#include "dxva2_internal.h" #include "hevc_data.h" #include "hevcdec.h" -// The headers above may include w32threads.h, which uses the original -// _WIN32_WINNT define, while dxva2_internal.h redefines it to target a -// potentially newer version. -#include "dxva2_internal.h" - #define MAX_SLICES 256 struct hevc_dxva2_picture_context { diff --git a/libavcodec/dxva2_mpeg2.c b/libavcodec/dxva2_mpeg2.c index 6e5dff308fa9e..5cc8128100b33 100644 --- a/libavcodec/dxva2_mpeg2.c +++ b/libavcodec/dxva2_mpeg2.c @@ -21,13 +21,10 @@ */ #include "libavutil/log.h" -#include "mpegutils.h" -#include "mpegvideo.h" -// The headers above may include w32threads.h, which uses the original -// _WIN32_WINNT define, while dxva2_internal.h redefines it to target a -// potentially newer version. #include "dxva2_internal.h" +#include "mpegutils.h" +#include "mpegvideo.h" #define MAX_SLICES 1024 struct dxva2_picture_context { diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c index 247ea47825259..fc09f88f05444 100644 --- a/libavcodec/dxva2_vc1.c +++ b/libavcodec/dxva2_vc1.c @@ -20,15 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "dxva2_internal.h" #include "mpegutils.h" #include "vc1.h" #include "vc1data.h" -// The headers above may include w32threads.h, which uses the original -// _WIN32_WINNT define, while dxva2_internal.h redefines it to target a -// potentially newer version. -#include "dxva2_internal.h" - struct dxva2_picture_context { DXVA_PictureParameters pp; DXVA_SliceInfo si; diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 0a8cc5bc21f84..6488fc2203276 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -20,14 +20,6 @@ #include -// Include thread.h before redefining _WIN32_WINNT, to get -// the right implementation for AVOnce -#include "thread.h" - -#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600 -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 -#endif #define COBJMACROS #include @@ -46,6 +38,7 @@ #include "imgutils.h" #include "pixdesc.h" #include "pixfmt.h" +#include "thread.h" typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory); diff --git a/libavutil/hwcontext_dxva2.c b/libavutil/hwcontext_dxva2.c index d1b19ab237faa..bf9a3a9c11376 100644 --- a/libavutil/hwcontext_dxva2.c +++ b/libavutil/hwcontext_dxva2.c @@ -18,10 +18,6 @@ #include -#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600 -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 -#endif #define DXVA2API_USE_BITFIELDS #define COBJMACROS From 4d1d7263d8ff32e67710b41f24fe485818c87211 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 10 Apr 2018 00:50:01 +0200 Subject: [PATCH 2413/2557] lavf/segafilmenc: Do not mix variable declaration and code. Fixes two warnings: ISO C90 forbids mixed declarations and code --- libavformat/segafilmenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/segafilmenc.c b/libavformat/segafilmenc.c index 86c0ab0d1c4e0..5b0d7e69e87a4 100644 --- a/libavformat/segafilmenc.c +++ b/libavformat/segafilmenc.c @@ -121,12 +121,12 @@ static int film_write_packet(AVFormatContext *format_context, AVPacket *pkt) if (encoded_buf_size != pkt->size && (pkt->size % encoded_buf_size) != 0) { avio_write(pb, pkt->data, pkt->size); } else { + uint8_t padding[2] = {0, 0}; /* In Sega Cinepak, the reported size in the Cinepak header is * 8 bytes too short. However, the size in the STAB section of the header * is correct, taking into account the extra two bytes. */ AV_WB24(&pkt->data[1], pkt->size - 8 + 2); metadata->size += 2; - uint8_t padding[2] = {0, 0}; avio_write(pb, pkt->data, 10); avio_write(pb, padding, 2); @@ -158,6 +158,7 @@ static int get_audio_codec_id(enum AVCodecID codec_id) static int film_init(AVFormatContext *format_context) { + AVStream *audio = NULL; FILMOutputContext *film = format_context->priv_data; film->audio_index = -1; film->video_index = -1; @@ -165,7 +166,6 @@ static int film_init(AVFormatContext *format_context) film->packet_count = 0; film->start = NULL; film->last = NULL; - AVStream *audio = NULL; for (int i = 0; i < format_context->nb_streams; i++) { AVStream *st = format_context->streams[i]; From 3fbe4a043cbe656301be9d066b3ac9a7034d1fc9 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Mon, 9 Apr 2018 14:28:06 +0530 Subject: [PATCH 2414/2557] doc/filters: correct range for length in astats filter Signed-off-by: Michael Niedermayer --- doc/filters.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index 4438386f647e8..b78e05a3291be 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1750,7 +1750,7 @@ It accepts the following option: @table @option @item length Short window length in seconds, used for peak and trough RMS measurement. -Default is @code{0.05} (50 milliseconds). Allowed range is @code{[0.1 - 10]}. +Default is @code{0.05} (50 milliseconds). Allowed range is @code{[0.01 - 10]}. @item metadata From 3b350528d252b16f9f1860fe5a83aca814ae2b14 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Tue, 3 Apr 2018 07:14:46 +0800 Subject: [PATCH 2415/2557] MAINTAINERS: add myself to the general developers list Signed-off-by: Jun Zhao Signed-off-by: Michael Niedermayer --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3c54ad6781f70..5c7bf4726f98e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -552,6 +552,7 @@ Ivan Uskov James Darnley Jan Ekström Joakim Plate +Jun Zhao Kieran Kunhya Kirill Gavrilov Martin Storsjö From d64183ea5da9c5248578d0bc4ffcbeddfc6c3555 Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Sun, 8 Apr 2018 18:27:25 -0700 Subject: [PATCH 2416/2557] Sega FILM: set dts and duration when demuxing Reviewed-by: Kyle Swanson Signed-off-by: Michael Niedermayer --- libavformat/segafilm.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libavformat/segafilm.c b/libavformat/segafilm.c index 4c0cca0140156..e72c26b144904 100644 --- a/libavformat/segafilm.c +++ b/libavformat/segafilm.c @@ -270,6 +270,8 @@ static int film_read_packet(AVFormatContext *s, FilmDemuxContext *film = s->priv_data; AVIOContext *pb = s->pb; film_sample *sample; + film_sample *next_sample = NULL; + int next_sample_id; int ret = 0; if (film->current_sample >= film->sample_count) @@ -277,6 +279,20 @@ static int film_read_packet(AVFormatContext *s, sample = &film->sample_table[film->current_sample]; + /* Find the next sample from the same stream, assuming there is one; + * this is used to calculate the duration below */ + next_sample_id = film->current_sample + 1; + while (next_sample == NULL) { + if (next_sample_id >= film->sample_count) + break; + + next_sample = &film->sample_table[next_sample_id]; + if (next_sample->stream != sample->stream) { + next_sample = NULL; + next_sample_id++; + } + } + /* position the stream (will probably be there anyway) */ avio_seek(pb, sample->sample_offset, SEEK_SET); @@ -285,8 +301,11 @@ static int film_read_packet(AVFormatContext *s, ret = AVERROR(EIO); pkt->stream_index = sample->stream; + pkt->dts = sample->pts; pkt->pts = sample->pts; pkt->flags |= sample->keyframe ? AV_PKT_FLAG_KEY : 0; + if (next_sample != NULL) + pkt->duration = next_sample->pts - sample->pts; film->current_sample++; From 4c0798578cab410b4ad9c27bc47b5e09c9a66aba Mon Sep 17 00:00:00 2001 From: Rodger Combs Date: Wed, 28 Mar 2018 23:19:28 -0500 Subject: [PATCH 2417/2557] lavc/videotoolbox: fix failure to decode PAFF Signed-off-by: Aman Gupta --- libavcodec/videotoolbox.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index f82c31c5df653..57b6698e1b949 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -326,11 +326,8 @@ static int videotoolbox_set_frame(AVCodecContext *avctx, AVFrame *frame) CVPixelBufferRef *ref = (CVPixelBufferRef *)frame->buf[0]->data; - if (*ref) { - av_log(avctx, AV_LOG_ERROR, "videotoolbox: frame already set?\n"); - av_frame_unref(frame); - return AVERROR_EXTERNAL; - } + if (*ref) + CVPixelBufferRelease(*ref); *ref = vtctx->frame; vtctx->frame = NULL; From 05f1a3face140373ae658ab1abd6bacc841a770d Mon Sep 17 00:00:00 2001 From: Alexander Kravchenko Date: Mon, 9 Apr 2018 19:48:33 +0300 Subject: [PATCH 2418/2557] lavc/amfenc: Retain a reference to D3D frames used as input during the encoding process Fixes ticket #6990. Tested-by: James Almer Reviewed-by: Mark Thompson --- libavcodec/amfenc.c | 95 ++++++++++++++++++++++++++++++++++++++++++++- libavcodec/amfenc.h | 3 ++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index 89a10ff253ee4..b9418b679161f 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -157,6 +157,9 @@ static int amf_init_context(AVCodecContext *avctx) AmfContext *ctx = avctx->priv_data; AMF_RESULT res = AMF_OK; + ctx->hwsurfaces_in_queue = 0; + ctx->hwsurfaces_in_queue_max = 16; + // configure AMF logger // the return of these functions indicates old state and do not affect behaviour ctx->trace->pVtbl->EnableWriter(ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, ctx->log_to_dbg != 0 ); @@ -187,6 +190,8 @@ static int amf_init_context(AVCodecContext *avctx) if (!ctx->hw_frames_ctx) { return AVERROR(ENOMEM); } + if (device_ctx->initial_pool_size > 0) + ctx->hwsurfaces_in_queue_max = device_ctx->initial_pool_size - 1; } else { if(res == AMF_NOT_SUPPORTED) av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n"); @@ -443,6 +448,75 @@ int ff_amf_encode_init(AVCodecContext *avctx) return ret; } +static AMF_RESULT amf_set_property_buffer(AMFSurface *object, const wchar_t *name, AMFBuffer *val) +{ + AMF_RESULT res; + AMFVariantStruct var; + res = AMFVariantInit(&var); + if (res == AMF_OK) { + AMFGuid guid_AMFInterface = IID_AMFInterface(); + AMFInterface *amf_interface; + res = val->pVtbl->QueryInterface(val, &guid_AMFInterface, (void**)&amf_interface); + + if (res == AMF_OK) { + res = AMFVariantAssignInterface(&var, amf_interface); + amf_interface->pVtbl->Release(amf_interface); + } + if (res == AMF_OK) { + res = object->pVtbl->SetProperty(object, name, var); + } + AMFVariantClear(&var); + } + return res; +} + +static AMF_RESULT amf_get_property_buffer(AMFData *object, const wchar_t *name, AMFBuffer **val) +{ + AMF_RESULT res; + AMFVariantStruct var; + res = AMFVariantInit(&var); + if (res == AMF_OK) { + res = object->pVtbl->GetProperty(object, name, &var); + if (res == AMF_OK) { + if (var.type == AMF_VARIANT_INTERFACE) { + AMFGuid guid_AMFBuffer = IID_AMFBuffer(); + AMFInterface *amf_interface = AMFVariantInterface(&var); + res = amf_interface->pVtbl->QueryInterface(amf_interface, &guid_AMFBuffer, (void**)val); + } else { + res = AMF_INVALID_DATA_TYPE; + } + } + AMFVariantClear(&var); + } + return res; +} + +static AMFBuffer *amf_create_buffer_with_frame_ref(const AVFrame *frame, AMFContext *context) +{ + AVFrame *frame_ref; + AMFBuffer *frame_ref_storage_buffer = NULL; + AMF_RESULT res; + + res = context->pVtbl->AllocBuffer(context, AMF_MEMORY_HOST, sizeof(frame_ref), &frame_ref_storage_buffer); + if (res == AMF_OK) { + frame_ref = av_frame_clone(frame); + if (frame_ref) { + memcpy(frame_ref_storage_buffer->pVtbl->GetNative(frame_ref_storage_buffer), &frame_ref, sizeof(frame_ref)); + } else { + frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer); + frame_ref_storage_buffer = NULL; + } + } + return frame_ref_storage_buffer; +} + +static void amf_release_buffer_with_frame_ref(AMFBuffer *frame_ref_storage_buffer) +{ + AVFrame *av_frame_ref; + memcpy(&av_frame_ref, frame_ref_storage_buffer->pVtbl->GetNative(frame_ref_storage_buffer), sizeof(av_frame_ref)); + av_frame_free(&av_frame_ref); + frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer); +} int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame) { @@ -484,6 +558,8 @@ int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame) (ctx->hw_device_ctx && ((AVHWFramesContext*)frame->hw_frames_ctx->data)->device_ctx == (AVHWDeviceContext*)ctx->hw_device_ctx->data) )) { + AMFBuffer *frame_ref_storage_buffer; + #if CONFIG_D3D11VA static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } }; ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // actual texture @@ -496,6 +572,14 @@ int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame) // input HW surfaces can be vertically aligned by 16; tell AMF the real size surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height); #endif + + frame_ref_storage_buffer = amf_create_buffer_with_frame_ref(frame, ctx->context); + AMF_RETURN_IF_FALSE(ctx, frame_ref_storage_buffer != NULL, AVERROR(ENOMEM), "create_buffer_with_frame_ref() returned NULL\n"); + + res = amf_set_property_buffer(surface, L"av_frame_ref", frame_ref_storage_buffer); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SetProperty failed for \"av_frame_ref\" with error %d\n", res); + ctx->hwsurfaces_in_queue++; + frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer); } else { res = ctx->context->pVtbl->AllocSurface(ctx->context, AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res); @@ -560,6 +644,15 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) ret = amf_copy_buffer(avctx, avpkt, buffer); buffer->pVtbl->Release(buffer); + + if (data->pVtbl->HasProperty(data, L"av_frame_ref")) { + AMFBuffer *frame_ref_storage_buffer; + res = amf_get_property_buffer(data, L"av_frame_ref", &frame_ref_storage_buffer); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetProperty failed for \"av_frame_ref\" with error %d\n", res); + amf_release_buffer_with_frame_ref(frame_ref_storage_buffer); + ctx->hwsurfaces_in_queue--; + } + data->pVtbl->Release(data); AMF_RETURN_IF_FALSE(ctx, ret >= 0, ret, "amf_copy_buffer() failed with error %d\n", ret); @@ -589,7 +682,7 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed drain submission got AMF_INPUT_FULL- should not happen\n"); } } - } else if (ctx->delayed_surface != NULL || ctx->delayed_drain || (ctx->eof && res_query != AMF_EOF)) { + } else if (ctx->delayed_surface != NULL || ctx->delayed_drain || (ctx->eof && res_query != AMF_EOF) || (ctx->hwsurfaces_in_queue >= ctx->hwsurfaces_in_queue_max)) { block_and_wait = 1; av_usleep(1000); // wait and poll again } diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h index 84f0aad2fa4f9..b1361842bd655 100644 --- a/libavcodec/amfenc.h +++ b/libavcodec/amfenc.h @@ -62,6 +62,9 @@ typedef struct AmfContext { AVBufferRef *hw_device_ctx; ///< pointer to HW accelerator (decoder) AVBufferRef *hw_frames_ctx; ///< pointer to HW accelerator (frame allocator) + int hwsurfaces_in_queue; + int hwsurfaces_in_queue_max; + // helpers to handle async calls int delayed_drain; AMFSurface *delayed_surface; From 234a5e08313c6b8b0774796dfa1f285a3f877d14 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 8 Apr 2018 13:30:19 -0300 Subject: [PATCH 2419/2557] configure: check that the required header for Linux Perf is available Should fix compilation on targets like some old Android NDK versions. Signed-off-by: James Almer --- configure | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure b/configure index 08d6fc59837fc..4ea30762f48bc 100755 --- a/configure +++ b/configure @@ -2016,6 +2016,7 @@ HEADERS_LIST=" ES2_gl_h gsm_h io_h + linux_perf_event_h machine_ioctl_bt848_h machine_ioctl_meteor_h malloc_h @@ -2478,6 +2479,7 @@ simd_align_32_if_any="avx" simd_align_64_if_any="avx512" # system capabilities +linux_perf_deps="linux_perf_event_h" symver_if_any="symver_asm_label symver_gnu_asm" valgrind_backtrace_conflict="optimizations" valgrind_backtrace_deps="valgrind_valgrind_h" @@ -5800,6 +5802,7 @@ check_header dxgidebug.h check_header dxva.h check_header dxva2api.h -D_WIN32_WINNT=0x0600 check_header io.h +check_header linux/perf_event.h check_header libcrystalhd/libcrystalhd_if.h check_header malloc.h check_header net/udplite.h From aea610b0d6497886860a894eb76a6cc7788c0fcd Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 8 Apr 2018 14:00:47 -0300 Subject: [PATCH 2420/2557] configure: check for INIT_ONCE before enabling w32threads Should fix compilation wiht some old mingw-w64 builds that don't seem to define it. Signed-off-by: James Almer --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 4ea30762f48bc..8e6713d0b2729 100755 --- a/configure +++ b/configure @@ -5886,6 +5886,7 @@ check_cpp_condition winrt windows.h "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_D if ! disabled w32threads && ! enabled pthreads; then check_func_headers "windows.h process.h" _beginthreadex && check_type "windows.h" CONDITION_VARIABLE && + check_type "windows.h" INIT_ONCE && enable w32threads || disable w32threads if ! enabled w32threads && enabled winrt; then check_func_headers "windows.h" CreateThread && From e43e97f0e0f0596b56ceb2f887fe7414f202f081 Mon Sep 17 00:00:00 2001 From: Matt Wolenetz Date: Tue, 10 Apr 2018 13:59:25 -0700 Subject: [PATCH 2421/2557] lavc/libopusdec: Allow avcodec_open2 to call .close If there is a decoder initialization failure detected in avcodec_open2 after .init is called, allow graceful decoder .close to prevent leaking libopus decoder allocations. BUG=828526 Signed-off-by: Michael Niedermayer --- libavcodec/libopusdec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c index 3d2ee5b61b21b..2a97811d187cf 100644 --- a/libavcodec/libopusdec.c +++ b/libavcodec/libopusdec.c @@ -160,7 +160,10 @@ static av_cold int libopus_decode_close(AVCodecContext *avc) { struct libopus_context *opus = avc->priv_data; - opus_multistream_decoder_destroy(opus->dec); + if (opus->dec) { + opus_multistream_decoder_destroy(opus->dec); + opus->dec = NULL; + } return 0; } @@ -252,6 +255,7 @@ AVCodec ff_libopus_decoder = { .decode = libopus_decode, .flush = libopus_flush, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, From 62c1cfcc35a7772d9634fb9d2d1e74952843c108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Tue, 3 Apr 2018 09:05:18 +0300 Subject: [PATCH 2422/2557] avformat/movenc: use correct iTunes copyright atom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support for writing copyright metadata was added in commit bed4fc54c9 for 3GP, MOV and iTunes metadata. 3GP and MOV cases are formally specified. However, iTunes format does not have specification, and it seems to have been assumed that it would use the same atom as MOV (both being Apple formats). However, Apple uses 'cprt' atom for iTunes metadata (do note that the iTunes 'cprt' encoding is generic iTunes ItemList atom, not the 3GP 'cprt' encoding. These are also inside different parent atoms). Most references trying to document iTunes atoms mention only the 'cprt' tag. See: - http://atomicparsley.sourceforge.net/mpeg-4files.html - http://mutagen.readthedocs.io/en/latest/api/mp4.html Same applies to other software supporting this tag. Most of them encode and decode only the 'cprt' atom. ffmpeg mov demuxer supports both atoms in this context. There are few pieces of other software that support similarly both 'cprt' and the incorrect '\251cpy' atom in this context. I believe they do it in order to read the ffmpeg encoded incorrect copyright atom. In light of the above this changes the copyright atom to 'cprt' as it seems to be supported univerally and is the correct atom to use. Signed-off-by: Timo Teräs Signed-off-by: Michael Niedermayer --- libavformat/movenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index bd275259ca8ab..d03d7906a170f 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -3439,7 +3439,7 @@ static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov, } mov_write_string_metadata(s, pb, "\251cmt", "comment" , 1); mov_write_string_metadata(s, pb, "\251gen", "genre" , 1); - mov_write_string_metadata(s, pb, "\251cpy", "copyright", 1); + mov_write_string_metadata(s, pb, "cprt", "copyright", 1); mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1); mov_write_string_metadata(s, pb, "\251lyr", "lyrics" , 1); mov_write_string_metadata(s, pb, "desc", "description",1); From 9825f77ac7ab102783aad4d2e0c42584a0dde466 Mon Sep 17 00:00:00 2001 From: Bela Bodecs Date: Wed, 11 Apr 2018 11:15:54 +0800 Subject: [PATCH 2423/2557] avformat/hlsenc: fix handling of delete_segments when %v is present When var_stream_map option is used, %v must appear either in segment name template or in the directory path. This latter case currently is not handled and delete_segments flag of hls_flags is broken now. This patch fix this. The root cause of the bug was that HLSSegment struct only stores the final filename part, but not the final directory path. Most of the cases, final path info is unneded, It only necessary when you want to delete old segments (e.g in case of live streaming). Without variant streams it was unnecessary to store the final directory path, because all segment were stored into the same directory. But introducing %v in directory names either require to store the final directory path into HLSSegment or associate segments with their variant streams to be able deleting them later. I have choosen the second solution and introduced a variant index data member into the segment struct. Signed-off-by: Bela Bodecs Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 2a54b4342e5b3..8eb84212a0843 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -75,6 +75,7 @@ typedef struct HLSSegment { int discont; int64_t pos; int64_t size; + unsigned var_stream_idx; char key_uri[LINE_BUFFER_SIZE + 1]; char iv_string[KEYSIZE*2 + 1]; @@ -106,6 +107,7 @@ typedef enum { } SegmentType; typedef struct VariantStream { + unsigned var_stream_idx; unsigned number; int64_t sequence; AVOutputFormat *oformat; @@ -478,9 +480,23 @@ static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, } p = (char *)av_basename(dirname); *p = '\0'; + } while (segment) { + char * r_dirname = dirname; + + /* if %v is present in the file's directory */ + if (av_stristr(dirname, "%v")) { + + if (replace_int_data_in_filename(&r_dirname, dirname, 'v', segment->var_stream_idx) < 1) { + ret = AVERROR(EINVAL); + goto fail; + } + av_free(dirname); + dirname = r_dirname; + } + av_log(hls, AV_LOG_DEBUG, "deleting old segment %s\n", segment->filename); path_size = (hls->use_localtime_mkdir ? 0 : strlen(dirname)) + strlen(segment->filename) + 1; @@ -965,6 +981,7 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, if (!en) return AVERROR(ENOMEM); + en->var_stream_idx = vs->var_stream_idx; ret = sls_flags_filename_process(s, hls, vs, en, duration, pos, size); if (ret < 0) { return ret; @@ -1824,9 +1841,11 @@ static int parse_variant_stream_mapstring(AVFormatContext *s) while (varstr = av_strtok(p, " \t", &saveptr1)) { p = NULL; - if (nb_varstreams < hls->nb_varstreams) - vs = &(hls->var_streams[nb_varstreams++]); - else + if (nb_varstreams < hls->nb_varstreams) { + vs = &(hls->var_streams[nb_varstreams]); + vs->var_stream_idx = nb_varstreams; + nb_varstreams++; + } else return AVERROR(EINVAL); q = varstr; @@ -1984,6 +2003,7 @@ static int update_variant_stream_info(AVFormatContext *s) { if (!hls->var_streams) return AVERROR(ENOMEM); + hls->var_streams[0].var_stream_idx = 0; hls->var_streams[0].nb_streams = s->nb_streams; hls->var_streams[0].streams = av_mallocz(sizeof(AVStream *) * hls->var_streams[0].nb_streams); From 3e9d676192fc6ef719a904f8a2d114efec03d7c1 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Tue, 3 Apr 2018 12:35:27 +0200 Subject: [PATCH 2424/2557] spdifenc: support ac3 core+eac3 dependent streams Such streams are found on Blu-ray, and identified as EAC3 type in avformat, while the bitstream of the core stream is actually a pure AC3 frame. Adjust the parsing accordingly, since AC3 frames always hold 6 blocks and the numblkscod syntax element is not present. --- libavformat/spdifenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/spdifenc.c b/libavformat/spdifenc.c index 3a50aebbefd42..9514ff8e10e35 100644 --- a/libavformat/spdifenc.c +++ b/libavformat/spdifenc.c @@ -118,7 +118,8 @@ static int spdif_header_eac3(AVFormatContext *s, AVPacket *pkt) static const uint8_t eac3_repeat[4] = {6, 3, 2, 1}; int repeat = 1; - if ((pkt->data[4] & 0xc0) != 0xc0) /* fscod */ + int bsid = pkt->data[5] >> 3; + if (bsid > 10 && (pkt->data[4] & 0xc0) != 0xc0) /* fscod */ repeat = eac3_repeat[(pkt->data[4] & 0x30) >> 4]; /* numblkscod */ ctx->hd_buf = av_fast_realloc(ctx->hd_buf, &ctx->hd_buf_size, ctx->hd_buf_filled + pkt->size); From 86e9dba8fa5be26e10a096b675616b9ddb950031 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Wed, 11 Apr 2018 14:22:20 +0200 Subject: [PATCH 2425/2557] avcodec/nvenc: add support for B frames as ref --- libavcodec/nvenc.c | 20 ++++++++++++++++++++ libavcodec/nvenc.h | 7 +++++++ libavcodec/nvenc_h264.c | 11 +++++++++++ 3 files changed, 38 insertions(+) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 1f601a63bda17..e2d1100cc805b 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -370,6 +370,22 @@ static int nvenc_check_capabilities(AVCodecContext *avctx) return AVERROR(ENOSYS); } +#ifdef NVENC_HAVE_BFRAME_REF_MODE + ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_BFRAME_REF_MODE); + if (ctx->b_ref_mode == NV_ENC_BFRAME_REF_MODE_EACH && ret != 1) { + av_log(avctx, AV_LOG_VERBOSE, "Each B frame as reference is not supported\n"); + return AVERROR(ENOSYS); + } else if (ctx->b_ref_mode != NV_ENC_BFRAME_REF_MODE_DISABLED && ret == 0) { + av_log(avctx, AV_LOG_VERBOSE, "B frames as references are not supported\n"); + return AVERROR(ENOSYS); + } +#else + if (ctx->b_ref_mode != 0) { + av_log(avctx, AV_LOG_VERBOSE, "B frames as references need SDK 8.1 at build time\n"); + return AVERROR(ENOSYS); + } +#endif + return 0; } @@ -988,6 +1004,10 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx) if (ctx->coder >= 0) h264->entropyCodingMode = ctx->coder; +#ifdef NVENC_HAVE_BFRAME_REF_MODE + h264->useBFramesAsRef = ctx->b_ref_mode; +#endif + return 0; } diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index bff25dfc3ca12..2d6e781739336 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -40,6 +40,12 @@ typedef void ID3D11Device; #define RC_MODE_DEPRECATED 0x800000 #define RCD(rc_mode) ((rc_mode) | RC_MODE_DEPRECATED) +// SDK 8.1 compile time feature checks +#if NVENCAPI_VERSION >= 0x01000008 +#define NVENC_HAVE_BFRAME_REF_MODE +#define NVENC_HAVE_QP_MAP_MODE +#endif + typedef struct NvencSurface { NV_ENC_INPUT_PTR input_surface; @@ -174,6 +180,7 @@ typedef struct NvencContext int cqp; int weighted_pred; int coder; + int b_ref_mode; } NvencContext; int ff_nvenc_encode_init(AVCodecContext *avctx); diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index bc7bbcddeb73b..d446f9b33cc1c 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -126,6 +126,17 @@ static const AVOption options[] = { { "cavlc", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_ENTROPY_CODING_MODE_CAVLC }, 0, 0, VE, "coder" }, { "ac", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_ENTROPY_CODING_MODE_CABAC }, 0, 0, VE, "coder" }, { "vlc", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_ENTROPY_CODING_MODE_CAVLC }, 0, 0, VE, "coder" }, +#ifdef NVENC_HAVE_BFRAME_REF_MODE + { "b_ref_mode", "Use B frames as references", OFFSET(b_ref_mode), AV_OPT_TYPE_INT, { .i64 = NV_ENC_BFRAME_REF_MODE_DISABLED }, NV_ENC_BFRAME_REF_MODE_DISABLED, NV_ENC_BFRAME_REF_MODE_MIDDLE, VE, "b_ref_mode" }, + { "disabled", "B frames will not be used for reference", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_BFRAME_REF_MODE_DISABLED }, 0, 0, VE, "b_ref_mode" }, + { "each", "Each B frame will be used for reference", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_BFRAME_REF_MODE_EACH }, 0, 0, VE, "b_ref_mode" }, + { "middle", "Only (number of B frames)/2 will be used for reference", 0,AV_OPT_TYPE_CONST, { .i64 = NV_ENC_BFRAME_REF_MODE_MIDDLE }, 0, 0, VE, "b_ref_mode" }, +#else + { "b_ref_mode", "(not supported)", OFFSET(b_ref_mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE, "b_ref_mode" }, + { "disabled", "", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "b_ref_mode" }, + { "each", "", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, VE, "b_ref_mode" }, + { "middle", "", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, VE, "b_ref_mode" }, +#endif { NULL } }; From 2108a6736f505d05f38932d57e8d9cfe8a7f7c81 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Wed, 11 Apr 2018 14:28:36 +0200 Subject: [PATCH 2426/2557] avcodec/nvenc: update required driver versions for nvenc --- libavcodec/nvenc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index e2d1100cc805b..9d07c260d0351 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -119,10 +119,18 @@ static int nvenc_print_error(void *log_ctx, NVENCSTATUS err, static void nvenc_print_driver_requirement(AVCodecContext *avctx, int level) { -#if defined(_WIN32) || defined(__CYGWIN__) - const char *minver = "378.66"; +#if NVENCAPI_VERSION >= 0x01000008 +# if defined(_WIN32) || defined(__CYGWIN__) + const char *minver = "390.77"; +# else + const char *minver = "390.25"; +# endif #else +# if defined(_WIN32) || defined(__CYGWIN__) + const char *minver = "378.66"; +# else const char *minver = "378.13"; +# endif #endif av_log(avctx, level, "The minimum required Nvidia driver for nvenc is %s or newer\n", minver); } From 19128408ac3ab6524a9a519c12acef457baef2b9 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Tue, 10 Apr 2018 10:17:52 -0700 Subject: [PATCH 2427/2557] avcodec/mpegpicture: fix "stride changed" failures in gray mode Before adding uvlinesize check, I was seeing failures decoding some video with ffmpeg compiled with --enable-gray and using AV_CODEC_FLAG_GRAY. [mpeg2video @ 0x7fa193818c00] get_buffer() failed (stride changed: linesize=1280/1280 uvlinesize=0/640) [mpeg2video @ 0x7fa193818c00] get_buffer() failed (stride changed: linesize=1280/1280 uvlinesize=0/640) Signed-off-by: Michael Niedermayer --- libavcodec/mpegpicture.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavcodec/mpegpicture.c b/libavcodec/mpegpicture.c index 2be670cdbc230..c0e06900fe2a7 100644 --- a/libavcodec/mpegpicture.c +++ b/libavcodec/mpegpicture.c @@ -148,10 +148,12 @@ static int alloc_frame_buffer(AVCodecContext *avctx, Picture *pic, } } - if (linesize && (linesize != pic->f->linesize[0] || - uvlinesize != pic->f->linesize[1])) { + if ((linesize && linesize != pic->f->linesize[0]) || + (uvlinesize && uvlinesize != pic->f->linesize[1])) { av_log(avctx, AV_LOG_ERROR, - "get_buffer() failed (stride changed)\n"); + "get_buffer() failed (stride changed: linesize=%d/%d uvlinesize=%d/%d)\n", + linesize, pic->f->linesize[0], + uvlinesize, pic->f->linesize[1]); ff_mpeg_unref_picture(avctx, pic); return -1; } From b5c877a55415fc914acf996c8975a7b4e8b50a51 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Thu, 12 Apr 2018 02:30:21 +0200 Subject: [PATCH 2428/2557] configure: Disable direct stripping for AIX. AIX strip doesn't know the option -o. --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 8e6713d0b2729..1e192f87808e1 100755 --- a/configure +++ b/configure @@ -5009,6 +5009,7 @@ case $target_os in add_cppflags '-I\$(SRC_PATH)/compat/aix' enabled shared && add_ldflags -Wl,-brtl arflags='-Xany -r -c' + striptype="" ;; android) disable symver From b5788e70255a8dbbd4a816f06a39a81dca4b2fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Martinez?= Date: Tue, 10 Apr 2018 18:20:23 +0200 Subject: [PATCH 2429/2557] avcodec/dpx: Support for RGB 12-bit packed decoding Limited to widths multiple of 8 (RGB) due to lack of test files for such corner case This partially fixes ticket #5639 Signed-off-by: Michael Niedermayer --- libavcodec/dpx.c | 67 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/libavcodec/dpx.c b/libavcodec/dpx.c index 1aa2cbd1c8aca..026fb10e902b0 100644 --- a/libavcodec/dpx.c +++ b/libavcodec/dpx.c @@ -65,6 +65,38 @@ static uint16_t read10in32(const uint8_t **ptr, uint32_t * lbuf, return *lbuf & 0x3FF; } +static uint16_t read12in32(const uint8_t **ptr, uint32_t * lbuf, + int * n_datum, int is_big) +{ + if (*n_datum) + (*n_datum)--; + else { + *lbuf = read32(ptr, is_big); + *n_datum = 7; + } + + switch (*n_datum){ + case 7: return *lbuf & 0xFFF; + case 6: return (*lbuf >> 12) & 0xFFF; + case 5: { + uint32_t c = *lbuf >> 24; + *lbuf = read32(ptr, is_big); + c |= *lbuf << 8; + return c & 0xFFF; + } + case 4: return (*lbuf >> 4) & 0xFFF; + case 3: return (*lbuf >> 16) & 0xFFF; + case 2: { + uint32_t c = *lbuf >> 28; + *lbuf = read32(ptr, is_big); + c |= *lbuf << 4; + return c & 0xFFF; + } + case 1: return (*lbuf >> 8) & 0xFFF; + default: return *lbuf >> 20; + } +} + static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, @@ -201,10 +233,27 @@ static int decode_frame(AVCodecContext *avctx, break; case 12: if (!packing) { - av_log(avctx, AV_LOG_ERROR, "Packing to 16bit required\n"); - return -1; + int tested = 0; + if (descriptor == 50 && endian && (avctx->width%8) == 0) { // Little endian and widths not a multiple of 8 need tests + tested = 1; + } + if (!tested) { + av_log(avctx, AV_LOG_ERROR, "Packing to 16bit required\n"); + return -1; + } + } + stride = avctx->width * elements; + if (packing) { + stride *= 2; + } else { + stride *= 3; + if (stride % 8) { + stride /= 8; + stride++; + stride *= 8; + } + stride /= 2; } - stride = 2 * avctx->width * elements; break; case 16: stride = 2 * avctx->width * elements; @@ -349,6 +398,7 @@ static int decode_frame(AVCodecContext *avctx, (uint16_t*)ptr[2], (uint16_t*)ptr[3]}; for (y = 0; y < avctx->width; y++) { + if (packing) { if (elements >= 3) *dst[2]++ = read16(&buf, endian) >> 4; *dst[0] = read16(&buf, endian) >> 4; @@ -357,6 +407,17 @@ static int decode_frame(AVCodecContext *avctx, *dst[1]++ = read16(&buf, endian) >> 4; if (elements == 4) *dst[3]++ = read16(&buf, endian) >> 4; + } else { + *dst[2]++ = read12in32(&buf, &rgbBuffer, + &n_datum, endian); + *dst[0]++ = read12in32(&buf, &rgbBuffer, + &n_datum, endian); + *dst[1]++ = read12in32(&buf, &rgbBuffer, + &n_datum, endian); + if (elements == 4) + *dst[3]++ = read12in32(&buf, &rgbBuffer, + &n_datum, endian); + } } for (i = 0; i < elements; i++) ptr[i] += p->linesize[i]; From a26c9fdd1b4c047d6c89e29774928fd7bf347e8b Mon Sep 17 00:00:00 2001 From: Mattias Amnefelt Date: Mon, 2 Apr 2018 11:30:40 +0200 Subject: [PATCH 2430/2557] libavformat/aac: Parse all ID3 tags present between ADTS frames Some ADTS streams can have multiple ID3 tags between frames. This change parses all of them, rather than just the first one. Signed-off-by: Mattias Amnefelt Signed-off-by: Michael Niedermayer --- libavformat/aacdec.c | 14 +- tests/fate/demux.mak | 3 +- tests/ref/fate/adts-id3v2-two-tags-demux | 475 +++++++++++++++++++++++ 3 files changed, 486 insertions(+), 6 deletions(-) create mode 100644 tests/ref/fate/adts-id3v2-two-tags-demux diff --git a/libavformat/aacdec.c b/libavformat/aacdec.c index 5ec706bdc7a9e..685458b9114d0 100644 --- a/libavformat/aacdec.c +++ b/libavformat/aacdec.c @@ -154,11 +154,15 @@ static int adts_aac_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret, fsize; - ret = av_get_packet(s->pb, pkt, FFMAX(ID3v2_HEADER_SIZE, ADTS_HEADER_SIZE)); - - if (ret >= ID3v2_HEADER_SIZE && ff_id3v2_match(pkt->data, ID3v2_DEFAULT_MAGIC)) { - if ((ret = handle_id3(s, pkt)) >= 0) - ret = av_get_packet(s->pb, pkt, ADTS_HEADER_SIZE); + // Parse all the ID3 headers between frames + while (1) { + ret = av_get_packet(s->pb, pkt, FFMAX(ID3v2_HEADER_SIZE, ADTS_HEADER_SIZE)); + if (ret >= ID3v2_HEADER_SIZE && ff_id3v2_match(pkt->data, ID3v2_DEFAULT_MAGIC)) { + if ((ret = handle_id3(s, pkt)) >= 0) { + continue; + } + } + break; } if (ret < 0) diff --git a/tests/fate/demux.mak b/tests/fate/demux.mak index 306904b9dec57..ef9e677821a82 100644 --- a/tests/fate/demux.mak +++ b/tests/fate/demux.mak @@ -1,10 +1,11 @@ FATE_SAMPLES_DEMUX-$(call DEMDEC, AVI, FRAPS) += fate-avio-direct fate-avio-direct: CMD = framecrc -avioflags direct -i $(TARGET_SAMPLES)/fraps/fraps-v5-bouncing-balls-partial.avi -avioflags direct -FATE_SAMPLES_DEMUX-$(call DEMDEC, AAC, AAC) += fate-adts-demux fate-adts-id3v1-demux fate-adts-id3v2-demux +FATE_SAMPLES_DEMUX-$(call DEMDEC, AAC, AAC) += fate-adts-demux fate-adts-id3v1-demux fate-adts-id3v2-demux fate-adts-id3v2-two-tags-demux fate-adts-demux: CMD = crc -i $(TARGET_SAMPLES)/aac/ct_faac-adts.aac -c:a copy fate-adts-id3v1-demux: CMD = framecrc -f aac -i $(TARGET_SAMPLES)/aac/id3v1.aac -c:a copy fate-adts-id3v2-demux: CMD = framecrc -f aac -i $(TARGET_SAMPLES)/aac/id3v2.aac -c:a copy +fate-adts-id3v2-two-tags-demux: CMD = framecrc -i $(TARGET_SAMPLES)/aac/id3v2_two_tags.aac -c:a copy FATE_SAMPLES_DEMUX-$(CONFIG_AEA_DEMUXER) += fate-aea-demux fate-aea-demux: CMD = crc -i $(TARGET_SAMPLES)/aea/chirp.aea -c:a copy diff --git a/tests/ref/fate/adts-id3v2-two-tags-demux b/tests/ref/fate/adts-id3v2-two-tags-demux new file mode 100644 index 0000000000000..4fffd2e7675c9 --- /dev/null +++ b/tests/ref/fate/adts-id3v2-two-tags-demux @@ -0,0 +1,475 @@ +#tb 0: 1/28224000 +#media_type 0: audio +#codec_id 0: aac +#sample_rate 0: 48000 +#channel_layout 0: 4 +#channel_layout_name 0: mono +0, 0, 0, 602112, 128, 0x23291993 +0, 602112, 602112, 602112, 128, 0x23291993 +0, 1204224, 1204224, 602112, 128, 0x23291993 +0, 1806336, 1806336, 602112, 128, 0x23291993 +0, 2408448, 2408448, 602112, 128, 0x23291993 +0, 3010560, 3010560, 602112, 128, 0x23291993 +0, 3612672, 3612672, 602112, 128, 0x23291993 +0, 4214784, 4214784, 602112, 128, 0x23291993 +0, 4816896, 4816896, 602112, 128, 0x23291993 +0, 5419008, 5419008, 602112, 128, 0x23291993 +0, 6021120, 6021120, 602112, 128, 0x23291993 +0, 6623232, 6623232, 602112, 128, 0x23291993 +0, 7225344, 7225344, 602112, 128, 0x23291993 +0, 7827456, 7827456, 602112, 128, 0x23291993 +0, 8429568, 8429568, 602112, 128, 0x23291993 +0, 9031680, 9031680, 602112, 128, 0x23291993 +0, 9633792, 9633792, 602112, 128, 0x23291993 +0, 10235904, 10235904, 602112, 128, 0x23291993 +0, 10838016, 10838016, 602112, 128, 0x23291993 +0, 11440128, 11440128, 602112, 128, 0x23291993 +0, 12042240, 12042240, 602112, 128, 0x23291993 +0, 12644352, 12644352, 602112, 128, 0x23291993 +0, 13246464, 13246464, 602112, 128, 0x23291993 +0, 13848576, 13848576, 602112, 128, 0x23291993 +0, 14450688, 14450688, 602112, 128, 0x23291993 +0, 15052800, 15052800, 602112, 128, 0x23291993 +0, 15654912, 15654912, 602112, 128, 0x23291993 +0, 16257024, 16257024, 602112, 128, 0x23291993 +0, 16859136, 16859136, 602112, 128, 0x23291993 +0, 17461248, 17461248, 602112, 128, 0x23291993 +0, 18063360, 18063360, 602112, 128, 0x23291993 +0, 18665472, 18665472, 602112, 128, 0x23291993 +0, 19267584, 19267584, 602112, 128, 0x23291993 +0, 19869696, 19869696, 602112, 128, 0x23291993 +0, 20471808, 20471808, 602112, 128, 0x23291993 +0, 21073920, 21073920, 602112, 128, 0x23291993 +0, 21676032, 21676032, 602112, 128, 0x23291993 +0, 22278144, 22278144, 602112, 128, 0x23291993 +0, 22880256, 22880256, 602112, 128, 0x23291993 +0, 23482368, 23482368, 602112, 128, 0x23291993 +0, 24084480, 24084480, 602112, 128, 0x23291993 +0, 24686592, 24686592, 602112, 128, 0x23291993 +0, 25288704, 25288704, 602112, 128, 0x23291993 +0, 25890816, 25890816, 602112, 128, 0x23291993 +0, 26492928, 26492928, 602112, 128, 0x23291993 +0, 27095040, 27095040, 602112, 128, 0x23291993 +0, 27697152, 27697152, 602112, 128, 0x23291993 +0, 28299264, 28299264, 602112, 128, 0x23291993 +0, 28901376, 28901376, 602112, 128, 0x23291993 +0, 29503488, 29503488, 602112, 128, 0x23291993 +0, 30105600, 30105600, 602112, 128, 0x23291993 +0, 30707712, 30707712, 602112, 128, 0x23291993 +0, 31309824, 31309824, 602112, 128, 0x23291993 +0, 31911936, 31911936, 602112, 128, 0x23291993 +0, 32514048, 32514048, 602112, 128, 0x23291993 +0, 33116160, 33116160, 602112, 128, 0x23291993 +0, 33718272, 33718272, 602112, 128, 0x23291993 +0, 34320384, 34320384, 602112, 128, 0x23291993 +0, 34922496, 34922496, 602112, 128, 0x23291993 +0, 35524608, 35524608, 602112, 128, 0x23291993 +0, 36126720, 36126720, 602112, 128, 0x23291993 +0, 36728832, 36728832, 602112, 128, 0x23291993 +0, 37330944, 37330944, 602112, 128, 0x23291993 +0, 37933056, 37933056, 602112, 128, 0x23291993 +0, 38535168, 38535168, 602112, 128, 0x23291993 +0, 39137280, 39137280, 602112, 128, 0x23291993 +0, 39739392, 39739392, 602112, 128, 0x23291993 +0, 40341504, 40341504, 602112, 128, 0x23291993 +0, 40943616, 40943616, 602112, 128, 0x23291993 +0, 41545728, 41545728, 602112, 128, 0x23291993 +0, 42147840, 42147840, 602112, 128, 0x23291993 +0, 42749952, 42749952, 602112, 128, 0x23291993 +0, 43352064, 43352064, 602112, 128, 0x23291993 +0, 43954176, 43954176, 602112, 128, 0x23291993 +0, 44556288, 44556288, 602112, 128, 0x23291993 +0, 45158400, 45158400, 602112, 128, 0x23291993 +0, 45760512, 45760512, 602112, 128, 0x23291993 +0, 46362624, 46362624, 602112, 128, 0x23291993 +0, 46964736, 46964736, 602112, 128, 0x23291993 +0, 47566848, 47566848, 602112, 128, 0x23291993 +0, 48168960, 48168960, 602112, 128, 0x23291993 +0, 48771072, 48771072, 602112, 128, 0x23291993 +0, 49373184, 49373184, 602112, 128, 0x23291993 +0, 49975296, 49975296, 602112, 128, 0x23291993 +0, 50577408, 50577408, 602112, 128, 0x23291993 +0, 51179520, 51179520, 602112, 128, 0x23291993 +0, 51781632, 51781632, 602112, 128, 0x23291993 +0, 52383744, 52383744, 602112, 128, 0x23291993 +0, 52985856, 52985856, 602112, 128, 0x23291993 +0, 53587968, 53587968, 602112, 128, 0x23291993 +0, 54190080, 54190080, 602112, 128, 0x23291993 +0, 54792192, 54792192, 602112, 128, 0x23291993 +0, 55394304, 55394304, 602112, 128, 0x23291993 +0, 55996416, 55996416, 602112, 128, 0x23291993 +0, 56598528, 56598528, 602112, 128, 0x23291993 +0, 57200640, 57200640, 602112, 128, 0x23291993 +0, 57802752, 57802752, 602112, 128, 0x23291993 +0, 58404864, 58404864, 602112, 128, 0x23291993 +0, 59006976, 59006976, 602112, 128, 0x23291993 +0, 59609088, 59609088, 602112, 128, 0x23291993 +0, 60211200, 60211200, 602112, 128, 0x23291993 +0, 60813312, 60813312, 602112, 128, 0x23291993 +0, 61415424, 61415424, 602112, 128, 0x23291993 +0, 62017536, 62017536, 602112, 128, 0x23291993 +0, 62619648, 62619648, 602112, 128, 0x23291993 +0, 63221760, 63221760, 602112, 128, 0x23291993 +0, 63823872, 63823872, 602112, 128, 0x23291993 +0, 64425984, 64425984, 602112, 128, 0x23291993 +0, 65028096, 65028096, 602112, 128, 0x23291993 +0, 65630208, 65630208, 602112, 128, 0x23291993 +0, 66232320, 66232320, 602112, 128, 0x23291993 +0, 66834432, 66834432, 602112, 128, 0x23291993 +0, 67436544, 67436544, 602112, 128, 0x23291993 +0, 68038656, 68038656, 602112, 128, 0x23291993 +0, 68640768, 68640768, 602112, 128, 0x23291993 +0, 69242880, 69242880, 602112, 128, 0x23291993 +0, 69844992, 69844992, 602112, 128, 0x23291993 +0, 70447104, 70447104, 602112, 128, 0x23291993 +0, 71049216, 71049216, 602112, 128, 0x23291993 +0, 71651328, 71651328, 602112, 128, 0x23291993 +0, 72253440, 72253440, 602112, 128, 0x23291993 +0, 72855552, 72855552, 602112, 128, 0x23291993 +0, 73457664, 73457664, 602112, 128, 0x23291993 +0, 74059776, 74059776, 602112, 128, 0x23291993 +0, 74661888, 74661888, 602112, 128, 0x23291993 +0, 75264000, 75264000, 602112, 128, 0x23291993 +0, 75866112, 75866112, 602112, 128, 0x23291993 +0, 76468224, 76468224, 602112, 128, 0x23291993 +0, 77070336, 77070336, 602112, 128, 0x23291993 +0, 77672448, 77672448, 602112, 128, 0x23291993 +0, 78274560, 78274560, 602112, 128, 0x23291993 +0, 78876672, 78876672, 602112, 128, 0x23291993 +0, 79478784, 79478784, 602112, 128, 0x23291993 +0, 80080896, 80080896, 602112, 128, 0x23291993 +0, 80683008, 80683008, 602112, 128, 0x23291993 +0, 81285120, 81285120, 602112, 128, 0x23291993 +0, 81887232, 81887232, 602112, 128, 0x23291993 +0, 82489344, 82489344, 602112, 128, 0x23291993 +0, 83091456, 83091456, 602112, 128, 0x23291993 +0, 83693568, 83693568, 602112, 128, 0x23291993 +0, 84295680, 84295680, 602112, 128, 0x23291993 +0, 84897792, 84897792, 602112, 128, 0x23291993 +0, 85499904, 85499904, 602112, 128, 0x23291993 +0, 86102016, 86102016, 602112, 128, 0x23291993 +0, 86704128, 86704128, 602112, 128, 0x23291993 +0, 87306240, 87306240, 602112, 128, 0x23291993 +0, 87908352, 87908352, 602112, 128, 0x23291993 +0, 88510464, 88510464, 602112, 128, 0x23291993 +0, 89112576, 89112576, 602112, 128, 0x23291993 +0, 89714688, 89714688, 602112, 128, 0x23291993 +0, 90316800, 90316800, 602112, 128, 0x23291993 +0, 90918912, 90918912, 602112, 128, 0x23291993 +0, 91521024, 91521024, 602112, 128, 0x23291993 +0, 92123136, 92123136, 602112, 128, 0x23291993 +0, 92725248, 92725248, 602112, 128, 0x23291993 +0, 93327360, 93327360, 602112, 128, 0x23291993 +0, 93929472, 93929472, 602112, 128, 0x23291993 +0, 94531584, 94531584, 602112, 128, 0x23291993 +0, 95133696, 95133696, 602112, 128, 0x23291993 +0, 95735808, 95735808, 602112, 128, 0x23291993 +0, 96337920, 96337920, 602112, 128, 0x23291993 +0, 96940032, 96940032, 602112, 128, 0x23291993 +0, 97542144, 97542144, 602112, 128, 0x23291993 +0, 98144256, 98144256, 602112, 128, 0x23291993 +0, 98746368, 98746368, 602112, 128, 0x23291993 +0, 99348480, 99348480, 602112, 128, 0x23291993 +0, 99950592, 99950592, 602112, 128, 0x23291993 +0, 100552704, 100552704, 602112, 128, 0x23291993 +0, 101154816, 101154816, 602112, 128, 0x23291993 +0, 101756928, 101756928, 602112, 128, 0x23291993 +0, 102359040, 102359040, 602112, 128, 0x23291993 +0, 102961152, 102961152, 602112, 128, 0x23291993 +0, 103563264, 103563264, 602112, 128, 0x23291993 +0, 104165376, 104165376, 602112, 128, 0x23291993 +0, 104767488, 104767488, 602112, 128, 0x23291993 +0, 105369600, 105369600, 602112, 128, 0x23291993 +0, 105971712, 105971712, 602112, 128, 0x23291993 +0, 106573824, 106573824, 602112, 128, 0x23291993 +0, 107175936, 107175936, 602112, 128, 0x23291993 +0, 107778048, 107778048, 602112, 128, 0x23291993 +0, 108380160, 108380160, 602112, 128, 0x23291993 +0, 108982272, 108982272, 602112, 128, 0x23291993 +0, 109584384, 109584384, 602112, 128, 0x23291993 +0, 110186496, 110186496, 602112, 128, 0x23291993 +0, 110788608, 110788608, 602112, 128, 0x23291993 +0, 111390720, 111390720, 602112, 128, 0x23291993 +0, 111992832, 111992832, 602112, 128, 0x23291993 +0, 112594944, 112594944, 602112, 128, 0x23291993 +0, 113197056, 113197056, 602112, 128, 0x23291993 +0, 113799168, 113799168, 602112, 128, 0x23291993 +0, 114401280, 114401280, 602112, 128, 0x23291993 +0, 115003392, 115003392, 602112, 128, 0x23291993 +0, 115605504, 115605504, 602112, 128, 0x23291993 +0, 116207616, 116207616, 602112, 128, 0x23291993 +0, 116809728, 116809728, 602112, 128, 0x23291993 +0, 117411840, 117411840, 602112, 128, 0x23291993 +0, 118013952, 118013952, 602112, 128, 0x23291993 +0, 118616064, 118616064, 602112, 128, 0x23291993 +0, 119218176, 119218176, 602112, 128, 0x23291993 +0, 119820288, 119820288, 602112, 128, 0x23291993 +0, 120422400, 120422400, 602112, 128, 0x23291993 +0, 121024512, 121024512, 602112, 128, 0x23291993 +0, 121626624, 121626624, 602112, 128, 0x23291993 +0, 122228736, 122228736, 602112, 128, 0x23291993 +0, 122830848, 122830848, 602112, 128, 0x23291993 +0, 123432960, 123432960, 602112, 128, 0x23291993 +0, 124035072, 124035072, 602112, 128, 0x23291993 +0, 124637184, 124637184, 602112, 128, 0x23291993 +0, 125239296, 125239296, 602112, 128, 0x23291993 +0, 125841408, 125841408, 602112, 128, 0x23291993 +0, 126443520, 126443520, 602112, 128, 0x23291993 +0, 127045632, 127045632, 602112, 128, 0x23291993 +0, 127647744, 127647744, 602112, 128, 0x23291993 +0, 128249856, 128249856, 602112, 128, 0x23291993 +0, 128851968, 128851968, 602112, 128, 0x23291993 +0, 129454080, 129454080, 602112, 128, 0x23291993 +0, 130056192, 130056192, 602112, 128, 0x23291993 +0, 130658304, 130658304, 602112, 128, 0x23291993 +0, 131260416, 131260416, 602112, 128, 0x23291993 +0, 131862528, 131862528, 602112, 128, 0x23291993 +0, 132464640, 132464640, 602112, 128, 0x23291993 +0, 133066752, 133066752, 602112, 128, 0x23291993 +0, 133668864, 133668864, 602112, 128, 0x23291993 +0, 134270976, 134270976, 602112, 128, 0x23291993 +0, 134873088, 134873088, 602112, 128, 0x23291993 +0, 135475200, 135475200, 602112, 128, 0x23291993 +0, 136077312, 136077312, 602112, 128, 0x23291993 +0, 136679424, 136679424, 602112, 128, 0x23291993 +0, 137281536, 137281536, 602112, 128, 0x23291993 +0, 137883648, 137883648, 602112, 128, 0x23291993 +0, 138485760, 138485760, 602112, 128, 0x23291993 +0, 139087872, 139087872, 602112, 128, 0x23291993 +0, 139689984, 139689984, 602112, 128, 0x23291993 +0, 140292096, 140292096, 602112, 128, 0x23291993 +0, 140894208, 140894208, 602112, 128, 0x23291993 +0, 141496320, 141496320, 602112, 128, 0x23291993 +0, 142098432, 142098432, 602112, 128, 0x23291993 +0, 142700544, 142700544, 602112, 128, 0x23291993 +0, 143302656, 143302656, 602112, 128, 0x23291993 +0, 143904768, 143904768, 602112, 128, 0x23291993 +0, 144506880, 144506880, 602112, 128, 0x23291993 +0, 145108992, 145108992, 602112, 128, 0x23291993 +0, 145711104, 145711104, 602112, 128, 0x23291993 +0, 146313216, 146313216, 602112, 128, 0x23291993 +0, 146915328, 146915328, 602112, 128, 0x23291993 +0, 147517440, 147517440, 602112, 128, 0x23291993 +0, 148119552, 148119552, 602112, 128, 0x23291993 +0, 148721664, 148721664, 602112, 128, 0x23291993 +0, 149323776, 149323776, 602112, 128, 0x23291993 +0, 149925888, 149925888, 602112, 128, 0x23291993 +0, 150528000, 150528000, 602112, 128, 0x23291993 +0, 151130112, 151130112, 602112, 128, 0x23291993 +0, 151732224, 151732224, 602112, 128, 0x23291993 +0, 152334336, 152334336, 602112, 128, 0x23291993 +0, 152936448, 152936448, 602112, 128, 0x23291993 +0, 153538560, 153538560, 602112, 128, 0x23291993 +0, 154140672, 154140672, 602112, 128, 0x23291993 +0, 154742784, 154742784, 602112, 128, 0x23291993 +0, 155344896, 155344896, 602112, 128, 0x23291993 +0, 155947008, 155947008, 602112, 128, 0x23291993 +0, 156549120, 156549120, 602112, 128, 0x23291993 +0, 157151232, 157151232, 602112, 128, 0x23291993 +0, 157753344, 157753344, 602112, 128, 0x23291993 +0, 158355456, 158355456, 602112, 128, 0x23291993 +0, 158957568, 158957568, 602112, 128, 0x23291993 +0, 159559680, 159559680, 602112, 128, 0x23291993 +0, 160161792, 160161792, 602112, 128, 0x23291993 +0, 160763904, 160763904, 602112, 128, 0x23291993 +0, 161366016, 161366016, 602112, 128, 0x23291993 +0, 161968128, 161968128, 602112, 128, 0x23291993 +0, 162570240, 162570240, 602112, 128, 0x23291993 +0, 163172352, 163172352, 602112, 128, 0x23291993 +0, 163774464, 163774464, 602112, 128, 0x23291993 +0, 164376576, 164376576, 602112, 128, 0x23291993 +0, 164978688, 164978688, 602112, 128, 0x23291993 +0, 165580800, 165580800, 602112, 128, 0x23291993 +0, 166182912, 166182912, 602112, 128, 0x23291993 +0, 166785024, 166785024, 602112, 128, 0x23291993 +0, 167387136, 167387136, 602112, 128, 0x23291993 +0, 167989248, 167989248, 602112, 128, 0x23291993 +0, 168591360, 168591360, 602112, 128, 0x23291993 +0, 169193472, 169193472, 602112, 128, 0x23291993 +0, 169795584, 169795584, 602112, 128, 0x23291993 +0, 170397696, 170397696, 602112, 128, 0x23291993 +0, 170999808, 170999808, 602112, 128, 0x23291993 +0, 171601920, 171601920, 602112, 128, 0x23291993 +0, 172204032, 172204032, 602112, 128, 0x23291993 +0, 172806144, 172806144, 602112, 128, 0x23291993 +0, 173408256, 173408256, 602112, 128, 0x23291993 +0, 174010368, 174010368, 602112, 128, 0x23291993 +0, 174612480, 174612480, 602112, 128, 0x23291993 +0, 175214592, 175214592, 602112, 128, 0x23291993 +0, 175816704, 175816704, 602112, 128, 0x23291993 +0, 176418816, 176418816, 602112, 128, 0x23291993 +0, 177020928, 177020928, 602112, 128, 0x23291993 +0, 177623040, 177623040, 602112, 128, 0x23291993 +0, 178225152, 178225152, 602112, 128, 0x23291993 +0, 178827264, 178827264, 602112, 128, 0x23291993 +0, 179429376, 179429376, 602112, 128, 0x23291993 +0, 180031488, 180031488, 602112, 128, 0x23291993 +0, 180633600, 180633600, 602112, 128, 0x23291993 +0, 181235712, 181235712, 602112, 128, 0x23291993 +0, 181837824, 181837824, 602112, 128, 0x23291993 +0, 182439936, 182439936, 602112, 128, 0x23291993 +0, 183042048, 183042048, 602112, 128, 0x23291993 +0, 183644160, 183644160, 602112, 128, 0x23291993 +0, 184246272, 184246272, 602112, 128, 0x23291993 +0, 184848384, 184848384, 602112, 128, 0x23291993 +0, 185450496, 185450496, 602112, 128, 0x23291993 +0, 186052608, 186052608, 602112, 128, 0x23291993 +0, 186654720, 186654720, 602112, 128, 0x23291993 +0, 187256832, 187256832, 602112, 128, 0x23291993 +0, 187858944, 187858944, 602112, 128, 0x23291993 +0, 188461056, 188461056, 602112, 128, 0x23291993 +0, 189063168, 189063168, 602112, 128, 0x23291993 +0, 189665280, 189665280, 602112, 128, 0x23291993 +0, 190267392, 190267392, 602112, 128, 0x23291993 +0, 190869504, 190869504, 602112, 128, 0x23291993 +0, 191471616, 191471616, 602112, 128, 0x23291993 +0, 192073728, 192073728, 602112, 128, 0x23291993 +0, 192675840, 192675840, 602112, 128, 0x23291993 +0, 193277952, 193277952, 602112, 128, 0x23291993 +0, 193880064, 193880064, 602112, 128, 0x23291993 +0, 194482176, 194482176, 602112, 128, 0x23291993 +0, 195084288, 195084288, 602112, 128, 0x23291993 +0, 195686400, 195686400, 602112, 128, 0x23291993 +0, 196288512, 196288512, 602112, 128, 0x23291993 +0, 196890624, 196890624, 602112, 128, 0x23291993 +0, 197492736, 197492736, 602112, 128, 0x23291993 +0, 198094848, 198094848, 602112, 128, 0x23291993 +0, 198696960, 198696960, 602112, 128, 0x23291993 +0, 199299072, 199299072, 602112, 128, 0x23291993 +0, 199901184, 199901184, 602112, 128, 0x23291993 +0, 200503296, 200503296, 602112, 128, 0x23291993 +0, 201105408, 201105408, 602112, 128, 0x23291993 +0, 201707520, 201707520, 602112, 128, 0x23291993 +0, 202309632, 202309632, 602112, 128, 0x23291993 +0, 202911744, 202911744, 602112, 128, 0x23291993 +0, 203513856, 203513856, 602112, 128, 0x23291993 +0, 204115968, 204115968, 602112, 128, 0x23291993 +0, 204718080, 204718080, 602112, 128, 0x23291993 +0, 205320192, 205320192, 602112, 128, 0x23291993 +0, 205922304, 205922304, 602112, 128, 0x23291993 +0, 206524416, 206524416, 602112, 128, 0x23291993 +0, 207126528, 207126528, 602112, 128, 0x23291993 +0, 207728640, 207728640, 602112, 128, 0x23291993 +0, 208330752, 208330752, 602112, 128, 0x23291993 +0, 208932864, 208932864, 602112, 128, 0x23291993 +0, 209534976, 209534976, 602112, 128, 0x23291993 +0, 210137088, 210137088, 602112, 128, 0x23291993 +0, 210739200, 210739200, 602112, 128, 0x23291993 +0, 211341312, 211341312, 602112, 128, 0x23291993 +0, 211943424, 211943424, 602112, 128, 0x23291993 +0, 212545536, 212545536, 602112, 128, 0x23291993 +0, 213147648, 213147648, 602112, 128, 0x23291993 +0, 213749760, 213749760, 602112, 128, 0x23291993 +0, 214351872, 214351872, 602112, 128, 0x23291993 +0, 214953984, 214953984, 602112, 128, 0x23291993 +0, 215556096, 215556096, 602112, 128, 0x23291993 +0, 216158208, 216158208, 602112, 128, 0x23291993 +0, 216760320, 216760320, 602112, 128, 0x23291993 +0, 217362432, 217362432, 602112, 128, 0x23291993 +0, 217964544, 217964544, 602112, 128, 0x23291993 +0, 218566656, 218566656, 602112, 128, 0x23291993 +0, 219168768, 219168768, 602112, 128, 0x23291993 +0, 219770880, 219770880, 602112, 128, 0x23291993 +0, 220372992, 220372992, 602112, 128, 0x23291993 +0, 220975104, 220975104, 602112, 128, 0x23291993 +0, 221577216, 221577216, 602112, 128, 0x23291993 +0, 222179328, 222179328, 602112, 128, 0x23291993 +0, 222781440, 222781440, 602112, 128, 0x23291993 +0, 223383552, 223383552, 602112, 128, 0x23291993 +0, 223985664, 223985664, 602112, 128, 0x23291993 +0, 224587776, 224587776, 602112, 128, 0x23291993 +0, 225189888, 225189888, 602112, 128, 0x23291993 +0, 225792000, 225792000, 602112, 128, 0x23291993 +0, 226394112, 226394112, 602112, 128, 0x23291993 +0, 226996224, 226996224, 602112, 128, 0x23291993 +0, 227598336, 227598336, 602112, 128, 0x23291993 +0, 228200448, 228200448, 602112, 128, 0x23291993 +0, 228802560, 228802560, 602112, 128, 0x23291993 +0, 229404672, 229404672, 602112, 128, 0x23291993 +0, 230006784, 230006784, 602112, 128, 0x23291993 +0, 230608896, 230608896, 602112, 128, 0x23291993 +0, 231211008, 231211008, 602112, 128, 0x23291993 +0, 231813120, 231813120, 602112, 128, 0x23291993 +0, 232415232, 232415232, 602112, 128, 0x23291993 +0, 233017344, 233017344, 602112, 128, 0x23291993 +0, 233619456, 233619456, 602112, 128, 0x23291993 +0, 234221568, 234221568, 602112, 128, 0x23291993 +0, 234823680, 234823680, 602112, 128, 0x23291993 +0, 235425792, 235425792, 602112, 128, 0x23291993 +0, 236027904, 236027904, 602112, 128, 0x23291993 +0, 236630016, 236630016, 602112, 128, 0x23291993 +0, 237232128, 237232128, 602112, 128, 0x23291993 +0, 237834240, 237834240, 602112, 128, 0x23291993 +0, 238436352, 238436352, 602112, 128, 0x23291993 +0, 239038464, 239038464, 602112, 128, 0x23291993 +0, 239640576, 239640576, 602112, 128, 0x23291993 +0, 240242688, 240242688, 602112, 128, 0x23291993 +0, 240844800, 240844800, 602112, 128, 0x23291993 +0, 241446912, 241446912, 602112, 128, 0x23291993 +0, 242049024, 242049024, 602112, 128, 0x23291993 +0, 242651136, 242651136, 602112, 128, 0x23291993 +0, 243253248, 243253248, 602112, 128, 0x23291993 +0, 243855360, 243855360, 602112, 128, 0x23291993 +0, 244457472, 244457472, 602112, 128, 0x23291993 +0, 245059584, 245059584, 602112, 128, 0x23291993 +0, 245661696, 245661696, 602112, 128, 0x23291993 +0, 246263808, 246263808, 602112, 128, 0x23291993 +0, 246865920, 246865920, 602112, 128, 0x23291993 +0, 247468032, 247468032, 602112, 128, 0x23291993 +0, 248070144, 248070144, 602112, 128, 0x23291993 +0, 248672256, 248672256, 602112, 128, 0x23291993 +0, 249274368, 249274368, 602112, 128, 0x23291993 +0, 249876480, 249876480, 602112, 128, 0x23291993 +0, 250478592, 250478592, 602112, 128, 0x23291993 +0, 251080704, 251080704, 602112, 128, 0x23291993 +0, 251682816, 251682816, 602112, 128, 0x23291993 +0, 252284928, 252284928, 602112, 128, 0x23291993 +0, 252887040, 252887040, 602112, 128, 0x23291993 +0, 253489152, 253489152, 602112, 128, 0x23291993 +0, 254091264, 254091264, 602112, 128, 0x23291993 +0, 254693376, 254693376, 602112, 128, 0x23291993 +0, 255295488, 255295488, 602112, 128, 0x23291993 +0, 255897600, 255897600, 602112, 128, 0x23291993 +0, 256499712, 256499712, 602112, 128, 0x23291993 +0, 257101824, 257101824, 602112, 128, 0x23291993 +0, 257703936, 257703936, 602112, 128, 0x23291993 +0, 258306048, 258306048, 602112, 128, 0x23291993 +0, 258908160, 258908160, 602112, 128, 0x23291993 +0, 259510272, 259510272, 602112, 128, 0x23291993 +0, 260112384, 260112384, 602112, 128, 0x23291993 +0, 260714496, 260714496, 602112, 128, 0x23291993 +0, 261316608, 261316608, 602112, 128, 0x23291993 +0, 261918720, 261918720, 602112, 128, 0x23291993 +0, 262520832, 262520832, 602112, 128, 0x23291993 +0, 263122944, 263122944, 602112, 128, 0x23291993 +0, 263725056, 263725056, 602112, 128, 0x23291993 +0, 264327168, 264327168, 602112, 128, 0x23291993 +0, 264929280, 264929280, 602112, 128, 0x23291993 +0, 265531392, 265531392, 602112, 128, 0x23291993 +0, 266133504, 266133504, 602112, 128, 0x23291993 +0, 266735616, 266735616, 602112, 128, 0x23291993 +0, 267337728, 267337728, 602112, 128, 0x23291993 +0, 267939840, 267939840, 602112, 128, 0x23291993 +0, 268541952, 268541952, 602112, 128, 0x23291993 +0, 269144064, 269144064, 602112, 128, 0x23291993 +0, 269746176, 269746176, 602112, 128, 0x23291993 +0, 270348288, 270348288, 602112, 128, 0x23291993 +0, 270950400, 270950400, 602112, 128, 0x23291993 +0, 271552512, 271552512, 602112, 128, 0x23291993 +0, 272154624, 272154624, 602112, 128, 0x23291993 +0, 272756736, 272756736, 602112, 128, 0x23291993 +0, 273358848, 273358848, 602112, 128, 0x23291993 +0, 273960960, 273960960, 602112, 128, 0x23291993 +0, 274563072, 274563072, 602112, 128, 0x23291993 +0, 275165184, 275165184, 602112, 128, 0x23291993 +0, 275767296, 275767296, 602112, 128, 0x23291993 +0, 276369408, 276369408, 602112, 128, 0x23291993 +0, 276971520, 276971520, 602112, 128, 0x23291993 +0, 277573632, 277573632, 602112, 128, 0x23291993 +0, 278175744, 278175744, 602112, 128, 0x23291993 +0, 278777856, 278777856, 602112, 128, 0x23291993 +0, 279379968, 279379968, 602112, 128, 0x23291993 +0, 279982080, 279982080, 602112, 128, 0x23291993 +0, 280584192, 280584192, 602112, 128, 0x23291993 +0, 281186304, 281186304, 602112, 128, 0x23291993 +0, 281788416, 281788416, 602112, 128, 0x23291993 From bc62d20dc415caf949b6452b2707b9eba78cb098 Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Tue, 3 Apr 2018 09:24:21 +0200 Subject: [PATCH 2431/2557] doc: update loglevel option documentation Updates documentation after the changes to loglevel flag prefix parsing in 4b736bc921ed96ad6d312ce0cbe0de29b9e3fe81. Signed-off-by: Tobias Rapp --- doc/fftools-common-opts.texi | 37 ++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/doc/fftools-common-opts.texi b/doc/fftools-common-opts.texi index 185ec218d5a18..7787e11cda7c3 100644 --- a/doc/fftools-common-opts.texi +++ b/doc/fftools-common-opts.texi @@ -168,14 +168,24 @@ The returned list cannot be assumed to be always complete. ffmpeg -sinks pulse,server=192.168.0.4 @end example -@item -loglevel [repeat+]@var{loglevel} | -v [repeat+]@var{loglevel} -Set the logging level used by the library. -Adding "repeat+" indicates that repeated log output should not be compressed -to the first line and the "Last message repeated n times" line will be -omitted. "repeat" can also be used alone. -If "repeat" is used alone, and with no prior loglevel set, the default -loglevel will be used. If multiple loglevel parameters are given, using -'repeat' will not change the loglevel. +@item -loglevel [@var{flags}+]@var{loglevel} | -v [@var{flags}+]@var{loglevel} +Set logging level and flags used by the library. + +The optional @var{flags} prefix can consist of the following values: +@table @samp +@item repeat +Indicates that repeated log output should not be compressed to the first line +and the "Last message repeated n times" line will be omitted. +@item level +Indicates that log output should add a @code{[level]} prefix to each message +line. This can be used as an alternative to log coloring, e.g. when dumping the +log to file. +@end table +Flags can also be used alone by adding a '+'/'-' prefix to set/reset a single +flag without affecting other @var{flags} or changing @var{loglevel}. When +setting both @var{flags} and @var{loglevel}, a '+' separator is expected +between the last @var{flags} value and before @var{loglevel}. + @var{loglevel} is a string or a number containing one of the following values: @table @samp @item quiet, -8 @@ -201,6 +211,17 @@ Show everything, including debugging information. @item trace, 56 @end table +For example to enable repeated log output, add the @code{level} prefix, and set +@var{loglevel} to @code{verbose}: +@example +ffmpeg -loglevel repeat+level+verbose -i input output +@end example +Another example that enables repeated log output without affecting current +state of @code{level} prefix flag or @var{loglevel}: +@example +ffmpeg [...] -loglevel +repeat +@end example + By default the program logs to stderr. If coloring is supported by the terminal, colors are used to mark errors and warnings. Log coloring can be disabled setting the environment variable From cdd107b96586916508f8665b08be7de54d9633cf Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 9 Apr 2018 23:05:42 +0800 Subject: [PATCH 2432/2557] lavf/aviobuf: add ff_get_chomp_line Same as ff_get_line but strip the white-space characters in the string tail. Signed-off-by: Jun Zhao --- libavformat/aviobuf.c | 8 ++++++++ libavformat/internal.h | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 95b33644784c0..e752d0e1a659b 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -823,6 +823,14 @@ int ff_get_line(AVIOContext *s, char *buf, int maxlen) return i; } +int ff_get_chomp_line(AVIOContext *s, char *buf, int maxlen) +{ + int len = ff_get_line(s, buf, maxlen); + while (len > 0 && av_isspace(buf[len - 1])) + buf[--len] = '\0'; + return len; +} + int64_t ff_read_line_to_bprint(AVIOContext *s, AVBPrint *bp) { int len, end; diff --git a/libavformat/internal.h b/libavformat/internal.h index c50382ad29f64..3582682925023 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -299,6 +299,16 @@ void ff_put_v(AVIOContext *bc, uint64_t val); */ int ff_get_line(AVIOContext *s, char *buf, int maxlen); +/** + * Same as ff_get_line but strip the white-space characters in the text tail + * + * @param s the read-only AVIOContext + * @param buf buffer to store the read line + * @param maxlen size of the buffer + * @return the length of the string written in the buffer + */ +int ff_get_chomp_line(AVIOContext *s, char *buf, int maxlen); + /** * Read a whole line of text from AVIOContext to an AVBPrint buffer. Stop * reading after reaching a \\r, a \\n, a \\r\\n, a \\0 or EOF. The line From 0e49118271ce0a3e8911200824032508b5a7de16 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 9 Apr 2018 23:11:02 +0800 Subject: [PATCH 2433/2557] lavf/hls: use ff_get_chomp_line Signed-off-by: Jun Zhao --- libavformat/hls.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index ae0545a086745..1257cd101ca74 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -216,14 +216,6 @@ typedef struct HLSContext { AVIOContext *playlist_pb; } HLSContext; -static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) -{ - int len = ff_get_line(s, buf, maxlen); - while (len > 0 && av_isspace(buf[len - 1])) - buf[--len] = '\0'; - return len; -} - static void free_segment_list(struct playlist *pls) { int i; @@ -770,7 +762,7 @@ static int parse_playlist(HLSContext *c, const char *url, if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, &new_url) >= 0) url = new_url; - read_chomp_line(in, line, sizeof(line)); + ff_get_chomp_line(in, line, sizeof(line)); if (strcmp(line, "#EXTM3U")) { ret = AVERROR_INVALIDDATA; goto fail; @@ -782,7 +774,7 @@ static int parse_playlist(HLSContext *c, const char *url, pls->type = PLS_TYPE_UNSPECIFIED; } while (!avio_feof(in)) { - read_chomp_line(in, line, sizeof(line)); + ff_get_chomp_line(in, line, sizeof(line)); if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) { is_variant = 1; memset(&variant_info, 0, sizeof(variant_info)); From f1ccb4dbcf0b878120ba3990476ce7059ead2d74 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 9 Apr 2018 23:12:16 +0800 Subject: [PATCH 2434/2557] lavf/hlsenc: use ff_get_chomp_line Signed-off-by: Jun Zhao --- libavformat/hlsenc.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 8eb84212a0843..01a06d8b263b2 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -696,14 +696,6 @@ static int hls_encryption_start(AVFormatContext *s) return 0; } -static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) -{ - int len = ff_get_line(s, buf, maxlen); - while (len > 0 && av_isspace(buf[len - 1])) - buf[--len] = '\0'; - return len; -} - static int hls_mux_init(AVFormatContext *s, VariantStream *vs) { AVDictionary *options = NULL; @@ -1072,7 +1064,7 @@ static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs s->protocol_whitelist, s->protocol_blacklist)) < 0) return ret; - read_chomp_line(in, line, sizeof(line)); + ff_get_chomp_line(in, line, sizeof(line)); if (strcmp(line, "#EXTM3U")) { ret = AVERROR_INVALIDDATA; goto fail; @@ -1080,7 +1072,7 @@ static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs vs->discontinuity = 0; while (!avio_feof(in)) { - read_chomp_line(in, line, sizeof(line)); + ff_get_chomp_line(in, line, sizeof(line)); if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) { int64_t tmp_sequence = strtoll(ptr, NULL, 10); if (tmp_sequence < vs->sequence) From 52623bc26fc49a1335a7ba4aab6ddb2b6588c105 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Mon, 9 Apr 2018 23:13:03 +0800 Subject: [PATCH 2435/2557] lavf/hlsproto: use ff_get_chomp_line Signed-off-by: Jun Zhao --- libavformat/hlsproto.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/libavformat/hlsproto.c b/libavformat/hlsproto.c index 2b19ed0cf67a8..e7ef2d88ea8d0 100644 --- a/libavformat/hlsproto.c +++ b/libavformat/hlsproto.c @@ -69,14 +69,6 @@ typedef struct HLSContext { int64_t last_load_time; } HLSContext; -static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) -{ - int len = ff_get_line(s, buf, maxlen); - while (len > 0 && av_isspace(buf[len - 1])) - buf[--len] = '\0'; - return len; -} - static void free_segment_list(HLSContext *s) { int i; @@ -122,7 +114,7 @@ static int parse_playlist(URLContext *h, const char *url) h->protocol_whitelist, h->protocol_blacklist)) < 0) return ret; - read_chomp_line(in, line, sizeof(line)); + ff_get_chomp_line(in, line, sizeof(line)); if (strcmp(line, "#EXTM3U")) { ret = AVERROR_INVALIDDATA; goto fail; @@ -131,7 +123,7 @@ static int parse_playlist(URLContext *h, const char *url) free_segment_list(s); s->finished = 0; while (!avio_feof(in)) { - read_chomp_line(in, line, sizeof(line)); + ff_get_chomp_line(in, line, sizeof(line)); if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) { struct variant_info info = {{0}}; is_variant = 1; From 4d544f608608f69e68136b8333d3649866e2a7ed Mon Sep 17 00:00:00 2001 From: Lou Logan Date: Thu, 12 Apr 2018 12:44:49 -0800 Subject: [PATCH 2436/2557] doc/filters: fix lenscorrection k1 & k2 typo 0 means no correction, not 0.5. Also document ranges and defaults for options. Signed-off-by: Lou Logan --- doc/filters.texi | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index b78e05a3291be..09b07d2a4a4a3 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -10373,15 +10373,17 @@ The filter accepts the following options: @item cx Relative x-coordinate of the focal point of the image, and thereby the center of the distortion. This value has a range [0,1] and is expressed as fractions of the image -width. +width. Default is 0.5. @item cy Relative y-coordinate of the focal point of the image, and thereby the center of the distortion. This value has a range [0,1] and is expressed as fractions of the image -height. +height. Default is 0.5. @item k1 -Coefficient of the quadratic correction term. 0.5 means no correction. +Coefficient of the quadratic correction term. This value has a range [-1,1]. 0 means +no correction. Default is 0. @item k2 -Coefficient of the double quadratic correction term. 0.5 means no correction. +Coefficient of the double quadratic correction term. This value has a range [-1,1]. +0 means no correction. Default is 0. @end table The formula that generates the correction is: From 37d0213968a2b58499f52dfe09c8d7a27d4c5a86 Mon Sep 17 00:00:00 2001 From: Bela Bodecs Date: Sun, 1 Apr 2018 23:29:14 +0200 Subject: [PATCH 2437/2557] avformat/utils: Stream specifier enhancement Currently when specifying the program id you can only decide to select all stream of the specified program (e.g. p:103 will select all streams of program 103) or narrow the selection to a specific stream sub index (e.g. p:145:1 will select 2nd stream of program 145.) But you can not specify like all audio streams of program 145 or 3rd video stream of program 311. In some case, mainly working with multiprogram mpeg-ts containers as input, this feature would be handy. This patch makes it possible to narrow the stream selection among streams of the specified program by stream type and optionally its index. Handled types: a, v, s, d. Examples: p:601:a will select all audio streams of program 601, p:603:a:1 will select 2nd audio streams of program 603, p:604:v:0 will select first video stream of program 604. Signed-off-by: Bela Bodecs Signed-off-by: Michael Niedermayer --- doc/fftools-common-opts.texi | 10 ++++-- libavformat/utils.c | 65 +++++++++++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/doc/fftools-common-opts.texi b/doc/fftools-common-opts.texi index 7787e11cda7c3..79feb39ca7188 100644 --- a/doc/fftools-common-opts.texi +++ b/doc/fftools-common-opts.texi @@ -42,10 +42,14 @@ streams, 'V' only matches video streams which are not attached pictures, video thumbnails or cover arts. If @var{stream_index} is given, then it matches stream number @var{stream_index} of this type. Otherwise, it matches all streams of this type. -@item p:@var{program_id}[:@var{stream_index}] -If @var{stream_index} is given, then it matches the stream with number @var{stream_index} +@item p:@var{program_id}[:@var{stream_index}] or p:@var{program_id}[:@var{stream_type}[:@var{stream_index}]] +In first version, if @var{stream_index} is given, then it matches the stream with number @var{stream_index} in the program with the id @var{program_id}. Otherwise, it matches all streams in the -program. +program. In the latter version, @var{stream_type} is one of following: 'v' for video, 'a' for audio, 's' +for subtitle, 'd' for data. If @var{stream_index} is also given, then it matches +stream number @var{stream_index} of this type in the program with the id @var{program_id}. +Otherwise, if only @var{stream_type} is given, it matches all +streams of this type in the program with the id @var{program_id}. @item #@var{stream_id} or i:@var{stream_id} Match the stream by stream id (e.g. PID in MPEG-TS container). @item m:@var{key}[:@var{value}] diff --git a/libavformat/utils.c b/libavformat/utils.c index 3e482a3bbc18b..cc35998336751 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -5070,11 +5070,66 @@ FF_ENABLE_DEPRECATION_WARNINGS if (s->programs[i]->id != prog_id) continue; - if (*endptr++ == ':') { - int stream_idx = strtol(endptr, NULL, 0); - return stream_idx >= 0 && - stream_idx < s->programs[i]->nb_stream_indexes && - st->index == s->programs[i]->stream_index[stream_idx]; + if (*endptr++ == ':') { // p::.... + if ( *endptr == 'a' || *endptr == 'v' || + *endptr == 's' || *endptr == 'd') { // p::[:] + enum AVMediaType type; + + switch (*endptr++) { + case 'v': type = AVMEDIA_TYPE_VIDEO; break; + case 'a': type = AVMEDIA_TYPE_AUDIO; break; + case 's': type = AVMEDIA_TYPE_SUBTITLE; break; + case 'd': type = AVMEDIA_TYPE_DATA; break; + default: av_assert0(0); + } + if (*endptr++ == ':') { // p::: + int stream_idx = strtol(endptr, NULL, 0), type_counter = 0; + for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) { + int stream_index = s->programs[i]->stream_index[j]; + if (st->index == s->programs[i]->stream_index[j]) { +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + return type_counter == stream_idx && + (type == st->codecpar->codec_type || + type == st->codec->codec_type); +FF_ENABLE_DEPRECATION_WARNINGS +#else + return type_counter == stream_idx && + type == st->codecpar->codec_type; +#endif + } +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + if (type == s->streams[stream_index]->codecpar->codec_type || + type == s->streams[stream_index]->codec->codec_type) + type_counter++; +FF_ENABLE_DEPRECATION_WARNINGS +#else + if (type == s->streams[stream_index]->codecpar->codec_type) + type_counter++; +#endif + } + return 0; + } else { // p:: + for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) + if (st->index == s->programs[i]->stream_index[j]) { +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + return type == st->codecpar->codec_type || + type == st->codec->codec_type; +FF_ENABLE_DEPRECATION_WARNINGS +#else + return type == st->codecpar->codec_type; +#endif + } + return 0; + } + } else { // p:: + int stream_idx = strtol(endptr, NULL, 0); + return stream_idx >= 0 && + stream_idx < s->programs[i]->nb_stream_indexes && + st->index == s->programs[i]->stream_index[stream_idx]; + } } for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) From a06175d7392326201a131fc09b3ea52617f310df Mon Sep 17 00:00:00 2001 From: Bela Bodecs Date: Wed, 11 Apr 2018 22:33:02 +0200 Subject: [PATCH 2438/2557] fate: to test program sub stream selection by its type in mpegts Signed-off-by: Bela Bodecs Signed-off-by: Michael Niedermayer --- tests/fate/mpegts.mak | 6 ++++++ tests/ref/fate/mpegts-probe-program | 8 ++++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/ref/fate/mpegts-probe-program diff --git a/tests/fate/mpegts.mak b/tests/fate/mpegts.mak index bb0d9d98a7761..2b128492e0ab0 100644 --- a/tests/fate/mpegts.mak +++ b/tests/fate/mpegts.mak @@ -9,6 +9,12 @@ FATE_MPEGTS_PROBE-$(call DEMDEC, MPEGTS, HEVC, AAC_LATM) += fate-mpegts-probe-la fate-mpegts-probe-latm: SRC = $(TARGET_SAMPLES)/mpegts/loewe.ts fate-mpegts-probe-latm: CMD = run $(PROBE_CODEC_NAME_COMMAND) -i "$(SRC)" + +FATE_MPEGTS_PROBE-$(call DEMDEC, MPEGTS, HEVC, AAC_LATM) += fate-mpegts-probe-program +fate-mpegts-probe-program: SRC = $(TARGET_SAMPLES)/mpegts/loewe.ts +fate-mpegts-probe-program: CMD = run $(PROBE_CODEC_NAME_COMMAND) -select_streams p:769:v:0 -i "$(SRC)" + + FATE_SAMPLES_FFPROBE += $(FATE_MPEGTS_PROBE-yes) fate-mpegts: $(FATE_MPEGTS_PROBE-yes) diff --git a/tests/ref/fate/mpegts-probe-program b/tests/ref/fate/mpegts-probe-program new file mode 100644 index 0000000000000..bb1012c8c7d04 --- /dev/null +++ b/tests/ref/fate/mpegts-probe-program @@ -0,0 +1,8 @@ +[PROGRAM] +[STREAM] +codec_name=hevc +[/STREAM] +[/PROGRAM] +[STREAM] +codec_name=hevc +[/STREAM] From 0a8133119ca5d087c7c7140d100406ff84c477ee Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 6 Apr 2018 23:56:57 +0200 Subject: [PATCH 2439/2557] avformat/mov: Fix extradata memleak Fixes: crbug 822705 Reported-by: Matt Wolenetz Reviewed-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavformat/mov.c b/libavformat/mov.c index 97b1462aabeeb..1340bf3913a69 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2592,6 +2592,12 @@ static int mov_read_stsd(MOVContext *c, AVIOContext *pb, MOVAtom atom) return mov_finalize_stsd_codec(c, pb, st, sc); fail: + if (sc->extradata) { + int j; + for (j = 0; j < sc->stsd_count; j++) + av_freep(&sc->extradata[j]); + } + av_freep(&sc->extradata); av_freep(&sc->extradata_size); return ret; From 8c02cd8ca097871dcd00cf8e08ce51660873f405 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 7 Apr 2018 00:34:25 +0200 Subject: [PATCH 2440/2557] avcodec/h264_slice: Fix integer overflow with last_poc Fixes: signed integer overflow: 2147483646 - -2816 cannot be represented in type 'int' Fixes: crbug 823145 Reported-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavcodec/h264_slice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 90e05ed8f1021..d71ddbe9ba48e 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1316,7 +1316,7 @@ static int h264_select_output_frame(H264Context *h) } out_of_order = MAX_DELAYED_PIC_COUNT - i; if( cur->f->pict_type == AV_PICTURE_TYPE_B - || (h->last_pocs[MAX_DELAYED_PIC_COUNT-2] > INT_MIN && h->last_pocs[MAX_DELAYED_PIC_COUNT-1] - h->last_pocs[MAX_DELAYED_PIC_COUNT-2] > 2)) + || (h->last_pocs[MAX_DELAYED_PIC_COUNT-2] > INT_MIN && h->last_pocs[MAX_DELAYED_PIC_COUNT-1] - (int64_t)h->last_pocs[MAX_DELAYED_PIC_COUNT-2] > 2)) out_of_order = FFMAX(out_of_order, 1); if (out_of_order == MAX_DELAYED_PIC_COUNT) { av_log(h->avctx, AV_LOG_VERBOSE, "Invalid POC %d<%d\n", cur->poc, h->last_pocs[0]); From 8d381b57fd9d17fb5c3a851ca46c738b3afc33a2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 10 Apr 2018 16:12:15 +0200 Subject: [PATCH 2441/2557] avcodec/mjpegdec: Check input buffer size. Fixes: Timeout Fixes: 6381/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_JPEGLS_fuzzer-5665032743419904 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/mjpegdec.c | 4 ++++ libavcodec/mjpegdec.h | 1 + 2 files changed, 5 insertions(+) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index beef174618fbf..22ca69f84127f 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -335,6 +335,8 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) av_log(s->avctx, AV_LOG_DEBUG, "sof0: picture: %dx%d\n", width, height); if (av_image_check_size(width, height, 0, s->avctx) < 0) return AVERROR_INVALIDDATA; + if (s->buf_size && (width + 7) / 8 * ((height + 7) / 8) > s->buf_size * 4LL) + return AVERROR_INVALIDDATA; nb_components = get_bits(&s->gb, 8); if (nb_components <= 0 || @@ -2247,6 +2249,8 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, int ret = 0; int is16bit; + s->buf_size = buf_size; + av_dict_free(&s->exif_metadata); av_freep(&s->stereo3d); s->adobe_transform = -1; diff --git a/libavcodec/mjpegdec.h b/libavcodec/mjpegdec.h index ff301bcb93799..653fe7cae6eec 100644 --- a/libavcodec/mjpegdec.h +++ b/libavcodec/mjpegdec.h @@ -47,6 +47,7 @@ typedef struct MJpegDecodeContext { AVClass *class; AVCodecContext *avctx; GetBitContext gb; + int buf_size; int start_code; /* current start code */ int buffer_size; From 9e406326687b5342dc9caffd4f5f1b03ac4bf26b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 20 Dec 2017 14:15:02 +0100 Subject: [PATCH 2442/2557] avfilter: add vfrdet filter Signed-off-by: Paul B Mahol --- Changelog | 1 + doc/filters.texi | 11 ++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- libavfilter/vf_vfrdet.c | 111 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_vfrdet.c diff --git a/Changelog b/Changelog index 74c410a8e25e6..7df4513e2da33 100644 --- a/Changelog +++ b/Changelog @@ -53,6 +53,7 @@ version : - bitstream filter for extracting E-AC-3 core - Haivision SRT protocol via libsrt - segafilm muxer +- vfrdet filter version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index 09b07d2a4a4a3..30060ce9182c6 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16248,6 +16248,17 @@ For example, to vertically flip a video with @command{ffmpeg}: ffmpeg -i in.avi -vf "vflip" out.avi @end example +@section vfrdet + +Detect variable frame rate video. + +This filter tries to detect if the input is variable or constant frame rate. + +At end it will output number of frames detected as having variable delta pts, +and ones with constant delta pts. +If there was frames with variable delta, than it will also show min and max delta +encountered. + @anchor{vignette} @section vignette diff --git a/libavfilter/Makefile b/libavfilter/Makefile index a90ca30ad7ac2..3a9fb02556440 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -353,6 +353,7 @@ OBJS-$(CONFIG_USPP_FILTER) += vf_uspp.o OBJS-$(CONFIG_VAGUEDENOISER_FILTER) += vf_vaguedenoiser.o OBJS-$(CONFIG_VECTORSCOPE_FILTER) += vf_vectorscope.o OBJS-$(CONFIG_VFLIP_FILTER) += vf_vflip.o +OBJS-$(CONFIG_VFRDET_FILTER) += vf_vfrdet.o OBJS-$(CONFIG_VIDSTABDETECT_FILTER) += vidstabutils.o vf_vidstabdetect.o OBJS-$(CONFIG_VIDSTABTRANSFORM_FILTER) += vidstabutils.o vf_vidstabtransform.o OBJS-$(CONFIG_VIGNETTE_FILTER) += vf_vignette.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 6eac828616f76..68b299202719a 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -343,6 +343,7 @@ extern AVFilter ff_vf_uspp; extern AVFilter ff_vf_vaguedenoiser; extern AVFilter ff_vf_vectorscope; extern AVFilter ff_vf_vflip; +extern AVFilter ff_vf_vfrdet; extern AVFilter ff_vf_vidstabdetect; extern AVFilter ff_vf_vidstabtransform; extern AVFilter ff_vf_vignette; diff --git a/libavfilter/version.h b/libavfilter/version.h index d9b49ea744751..f2937225f512d 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 14 +#define LIBAVFILTER_VERSION_MINOR 15 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_vfrdet.c b/libavfilter/vf_vfrdet.c new file mode 100644 index 0000000000000..cac96e29a2cf7 --- /dev/null +++ b/libavfilter/vf_vfrdet.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2017 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/common.h" +#include "libavutil/opt.h" +#include "internal.h" + +typedef struct VFRDETContext { + const AVClass *class; + + int64_t prev_pts; + int64_t delta; + int64_t min_delta; + int64_t max_delta; + + uint64_t vfr; + uint64_t cfr; +} VFRDETContext; + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + VFRDETContext *s = ctx->priv; + + if (s->prev_pts != AV_NOPTS_VALUE) { + int64_t delta = in->pts - s->prev_pts; + + if (s->delta == AV_NOPTS_VALUE) { + s->delta = delta; + } + + if (s->delta != delta) { + s->vfr++; + s->delta = delta; + s->min_delta = FFMIN(delta, s->min_delta); + s->max_delta = FFMAX(delta, s->max_delta); + } else { + s->cfr++; + } + } + + s->prev_pts = in->pts; + + return ff_filter_frame(ctx->outputs[0], in); +} + +static av_cold int init(AVFilterContext *ctx) +{ + VFRDETContext *s = ctx->priv; + + s->prev_pts = AV_NOPTS_VALUE; + s->delta = AV_NOPTS_VALUE; + s->min_delta = INT64_MAX; + s->max_delta = INT64_MIN; + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + VFRDETContext *s = ctx->priv; + + av_log(ctx, AV_LOG_INFO, "VFR:%f (%"PRIu64"/%"PRIu64")", s->vfr / (float)(s->vfr + s->cfr), s->vfr, s->cfr); + if (s->vfr) + av_log(ctx, AV_LOG_INFO, " min: %"PRId64" max: %"PRId64")", s->min_delta, s->max_delta); + av_log(ctx, AV_LOG_INFO, "\n"); +} + +static const AVFilterPad vfrdet_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad vfrdet_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_vfrdet = { + .name = "vfrdet", + .description = NULL_IF_CONFIG_SMALL("Variable frame rate detect filter."), + .priv_size = sizeof(VFRDETContext), + .init = init, + .uninit = uninit, + .inputs = vfrdet_inputs, + .outputs = vfrdet_outputs, +}; From 9e857aa00e1035f25b220f51f46e06148b9ae4f9 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Wed, 11 Apr 2018 13:47:27 +0200 Subject: [PATCH 2443/2557] avcodec/nvdec_hevc: add support for new extended sps/pps flags from SDK 8.1 --- libavcodec/hevc_ps.c | 5 ++--- libavcodec/hevc_ps.h | 1 + libavcodec/nvdec_hevc.c | 6 ++++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 1f18d0335b9f5..f877fa572c8c0 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1100,7 +1100,6 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, skip_bits(gb, 7); //sps_extension_7bits = get_bits(gb, 7); if (sps_extension_flag[0]) { int extended_precision_processing_flag; - int high_precision_offsets_enabled_flag; int cabac_bypass_alignment_enabled_flag; sps->transform_skip_rotation_enabled_flag = get_bits1(gb); @@ -1115,8 +1114,8 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, "extended_precision_processing_flag not yet implemented\n"); sps->intra_smoothing_disabled_flag = get_bits1(gb); - high_precision_offsets_enabled_flag = get_bits1(gb); - if (high_precision_offsets_enabled_flag) + sps->high_precision_offsets_enabled_flag = get_bits1(gb); + if (sps->high_precision_offsets_enabled_flag) av_log(avctx, AV_LOG_WARNING, "high_precision_offsets_enabled_flag not yet implemented\n"); diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index 9873754389cc5..1fbda199e3fe8 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -289,6 +289,7 @@ typedef struct HEVCSPS { int implicit_rdpcm_enabled_flag; int explicit_rdpcm_enabled_flag; int intra_smoothing_disabled_flag; + int high_precision_offsets_enabled_flag; int persistent_rice_adaptation_enabled_flag; ///< coded frame dimension in various units diff --git a/libavcodec/nvdec_hevc.c b/libavcodec/nvdec_hevc.c index 58f3fa9b45adb..ba54d210e820a 100644 --- a/libavcodec/nvdec_hevc.c +++ b/libavcodec/nvdec_hevc.c @@ -107,6 +107,12 @@ static int nvdec_hevc_start_frame(AVCodecContext *avctx, .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size, .pcm_sample_bit_depth_luma_minus1 = sps->pcm_enabled_flag ? sps->pcm.bit_depth - 1 : 0, .pcm_sample_bit_depth_chroma_minus1 = sps->pcm_enabled_flag ? sps->pcm.bit_depth_chroma - 1 : 0, +#if defined(NVDECAPI_VERSION) && NVDECAPI_VERSION >= 0x01000008 + .log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size - 2, + .log2_sao_offset_scale_luma = pps->log2_sao_offset_scale_luma, + .log2_sao_offset_scale_chroma = pps->log2_sao_offset_scale_chroma, + .high_precision_offsets_enabled_flag = sps->high_precision_offsets_enabled_flag, +#endif .pcm_loop_filter_disabled_flag = sps->pcm.loop_filter_disable_flag, .strong_intra_smoothing_enabled_flag = sps->sps_strong_intra_smoothing_enable_flag, .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra, From 987026adda79be4bbc541e12c5c6796b43f84bc1 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 13 Apr 2018 15:39:49 +0800 Subject: [PATCH 2444/2557] avformat/hlsenc: add option hls_delete_threshold When using hls_list_size with hls_flags delete_segments, currently hls_list_size * 2 +- segments remain on disk. With this new option, the amount of disk space used can be controlled by the user. fix ticket: #7131 Signed-off-by: Steven Liu Signed-off-by: Aman Gupta --- doc/muxers.texi | 6 ++++++ libavformat/hlsenc.c | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/doc/muxers.texi b/doc/muxers.texi index cb75c261c5582..f288764a23e75 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -513,6 +513,12 @@ Segment will be cut on the next key frame after this time has passed. Set the maximum number of playlist entries. If set to 0 the list file will contain all the segments. Default value is 5. +@item hls_delete_threshold @var{size} +Set the number of unreferenced segments to keep on disk before @code{hls_flags delete_segments} +deletes them. Increase this to allow continue clients to download segments which +were recently referenced in the playlist. Default value is 1, meaning segments older than +@code{hls_list_size+1} will be deleted. + @item hls_ts_options @var{options_list} Set output format options using a :-separated list of key=value parameters. Values containing @code{:} special characters must be diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 01a06d8b263b2..c7540166ab89c 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -173,6 +173,7 @@ typedef struct HLSContext { float time; // Set by a private option. float init_time; // Set by a private option. int max_nb_segments; // Set by a private option. + int hls_delete_threshold; // Set by a private option. #if FF_API_HLS_WRAP int wrap; // Set by a private option. #endif @@ -445,6 +446,7 @@ static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, HLSSegment *segment, *previous_segment = NULL; float playlist_duration = 0.0f; int ret = 0, path_size, sub_path_size; + int segment_cnt = 0; char *dirname = NULL, *p, *sub_path; char *path = NULL; AVDictionary *options = NULL; @@ -458,14 +460,20 @@ static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, } segment = vs->old_segments; + segment_cnt = 0; while (segment) { playlist_duration -= segment->duration; previous_segment = segment; segment = previous_segment->next; + segment_cnt++; if (playlist_duration <= -previous_segment->duration) { previous_segment->next = NULL; break; } + if (segment_cnt >= hls->hls_delete_threshold) { + previous_segment->next = NULL; + break; + } } if (segment && !hls->use_localtime_mkdir) { @@ -2791,6 +2799,7 @@ static const AVOption options[] = { {"hls_time", "set segment length in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E}, {"hls_init_time", "set segment length in seconds at init list", OFFSET(init_time), AV_OPT_TYPE_FLOAT, {.dbl = 0}, 0, FLT_MAX, E}, {"hls_list_size", "set maximum number of playlist entries", OFFSET(max_nb_segments), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E}, + {"hls_delete_threshold", "set number of unreferenced segments to keep before deleting", OFFSET(hls_delete_threshold), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, E}, {"hls_ts_options","set hls mpegts list of options for the container format used for hls", OFFSET(format_options_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"hls_vtt_options","set hls vtt list of options for the container format used for hls", OFFSET(vtt_format_options_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, #if FF_API_HLS_WRAP From 9f3902f107343f2690dce7ac7fef7c66887692b1 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Fri, 13 Apr 2018 09:36:49 +0200 Subject: [PATCH 2445/2557] avcodec/nv{enc,dec}: use sane version checking macro For some odd reason, the Nvidia version macros puts the minor version in the msb, so comparing against it is impossible. --- libavcodec/nvdec.h | 9 +++++++++ libavcodec/nvdec_hevc.c | 2 +- libavcodec/nvenc.c | 2 +- libavcodec/nvenc.h | 5 ++++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libavcodec/nvdec.h b/libavcodec/nvdec.h index 90578d5a1c4ee..85a0fcf7259cb 100644 --- a/libavcodec/nvdec.h +++ b/libavcodec/nvdec.h @@ -32,6 +32,15 @@ #include "avcodec.h" +#if defined(NVDECAPI_MAJOR_VERSION) && defined(NVDECAPI_MINOR_VERSION) +# define NVDECAPI_CHECK_VERSION(major, minor) \ + ((major) < NVDECAPI_MAJOR_VERSION || ((major) == NVDECAPI_MAJOR_VERSION && (minor) <= NVDECAPI_MINOR_VERSION)) +#else +/* version macros were added in SDK 8.1 ffnvcodec */ +# define NVDECAPI_CHECK_VERSION(major, minor) \ + ((major) < 8 || ((major) == 8 && (minor) <= 0)) +#endif + typedef struct NVDECFrame { unsigned int idx; AVBufferRef *idx_ref; diff --git a/libavcodec/nvdec_hevc.c b/libavcodec/nvdec_hevc.c index ba54d210e820a..e89256d75a911 100644 --- a/libavcodec/nvdec_hevc.c +++ b/libavcodec/nvdec_hevc.c @@ -107,7 +107,7 @@ static int nvdec_hevc_start_frame(AVCodecContext *avctx, .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size, .pcm_sample_bit_depth_luma_minus1 = sps->pcm_enabled_flag ? sps->pcm.bit_depth - 1 : 0, .pcm_sample_bit_depth_chroma_minus1 = sps->pcm_enabled_flag ? sps->pcm.bit_depth_chroma - 1 : 0, -#if defined(NVDECAPI_VERSION) && NVDECAPI_VERSION >= 0x01000008 +#if NVDECAPI_CHECK_VERSION(8, 1) .log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size - 2, .log2_sao_offset_scale_luma = pps->log2_sao_offset_scale_luma, .log2_sao_offset_scale_chroma = pps->log2_sao_offset_scale_chroma, diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 9d07c260d0351..c14112c3663dc 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -119,7 +119,7 @@ static int nvenc_print_error(void *log_ctx, NVENCSTATUS err, static void nvenc_print_driver_requirement(AVCodecContext *avctx, int level) { -#if NVENCAPI_VERSION >= 0x01000008 +#if NVENCAPI_CHECK_VERSION(8, 1) # if defined(_WIN32) || defined(__CYGWIN__) const char *minver = "390.77"; # else diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 2d6e781739336..c7506d6a1526f 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -40,8 +40,11 @@ typedef void ID3D11Device; #define RC_MODE_DEPRECATED 0x800000 #define RCD(rc_mode) ((rc_mode) | RC_MODE_DEPRECATED) +#define NVENCAPI_CHECK_VERSION(major, minor) \ + ((major) < NVENCAPI_MAJOR_VERSION || ((major) == NVENCAPI_MAJOR_VERSION && (minor) <= NVENCAPI_MINOR_VERSION)) + // SDK 8.1 compile time feature checks -#if NVENCAPI_VERSION >= 0x01000008 +#if NVENCAPI_CHECK_VERSION(8, 1) #define NVENC_HAVE_BFRAME_REF_MODE #define NVENC_HAVE_QP_MAP_MODE #endif From b4159d959394db8be59c8b2c68e4bea227fc069d Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 11 Apr 2018 13:59:36 +0200 Subject: [PATCH 2446/2557] avcodec/dxva2: add VP9 10-bit Profile2 mode mappings --- libavcodec/dxva2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index 6d831599afd9f..32416112bfd9c 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -44,6 +44,7 @@ DEFINE_GUID(ff_DXVA2_ModeVC1_D2010, 0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x0 DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main, 0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0); DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main10,0x107af0e0, 0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13); DEFINE_GUID(ff_DXVA2_ModeVP9_VLD_Profile0,0x463707f8,0xa1d0,0x4585,0x87,0x6d,0x83,0xaa,0x6d,0x60,0xb8,0x9e); +DEFINE_GUID(ff_DXVA2_ModeVP9_VLD_10bit_Profile2,0xa4c749ef,0x6ecf,0x48aa,0x84,0x48,0x50,0xa7,0xa1,0x16,0x5f,0xf7); DEFINE_GUID(ff_DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); DEFINE_GUID(ff_GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00); DEFINE_GUID(ff_IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02); @@ -67,6 +68,10 @@ static const int prof_hevc_main[] = {FF_PROFILE_HEVC_MAIN, FF_PROFILE_UNKNOWN}; static const int prof_hevc_main10[] = {FF_PROFILE_HEVC_MAIN_10, FF_PROFILE_UNKNOWN}; +static const int prof_vp9_profile0[] = {FF_PROFILE_VP9_0, + FF_PROFILE_UNKNOWN}; +static const int prof_vp9_profile2[] = {FF_PROFILE_VP9_2, + FF_PROFILE_UNKNOWN}; static const dxva_mode dxva_modes[] = { /* MPEG-2 */ @@ -90,7 +95,8 @@ static const dxva_mode dxva_modes[] = { { &ff_DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC, prof_hevc_main }, /* VP8/9 */ - { &ff_DXVA2_ModeVP9_VLD_Profile0,AV_CODEC_ID_VP9 }, + { &ff_DXVA2_ModeVP9_VLD_Profile0, AV_CODEC_ID_VP9, prof_vp9_profile0 }, + { &ff_DXVA2_ModeVP9_VLD_10bit_Profile2, AV_CODEC_ID_VP9, prof_vp9_profile2 }, { NULL, 0 }, }; From 7e20c8f5ebe96de94694be10e24b791e1ed4ea2d Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Mon, 29 May 2017 12:09:47 +0200 Subject: [PATCH 2447/2557] avcodec/vp9: add profile 2 10-bit DXVA2/D3D11 decoding support Fixes trac ticket #7099. --- libavcodec/vp9.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index 0fac638ec943d..b1178c9c0cb0c 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -188,6 +188,7 @@ static int update_size(AVCodecContext *avctx, int w, int h) switch (s->pix_fmt) { case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV420P10: #if CONFIG_VP9_DXVA2_HWACCEL *fmtp++ = AV_PIX_FMT_DXVA2_VLD; #endif @@ -202,7 +203,6 @@ static int update_size(AVCodecContext *avctx, int w, int h) *fmtp++ = AV_PIX_FMT_VAAPI; #endif break; - case AV_PIX_FMT_YUV420P10: case AV_PIX_FMT_YUV420P12: #if CONFIG_VP9_NVDEC_HWACCEL *fmtp++ = AV_PIX_FMT_CUDA; From 4078291d32c210e4ccd8b97c7cd95c87fda42108 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 13 Apr 2018 13:33:44 +0200 Subject: [PATCH 2448/2557] avcodec/magicyuvenc: mark as experimental Signed-off-by: Paul B Mahol --- libavcodec/magicyuvenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/magicyuvenc.c b/libavcodec/magicyuvenc.c index c784221e1cf07..bbfb8d0c6cf35 100644 --- a/libavcodec/magicyuvenc.c +++ b/libavcodec/magicyuvenc.c @@ -549,7 +549,7 @@ AVCodec ff_magicyuv_encoder = { .init = magy_encode_init, .close = magy_encode_close, .encode2 = magy_encode_frame, - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY | AV_CODEC_CAP_EXPERIMENTAL, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_GRAY8, From e7a2f1f8d8350a768ca88b61303449433962b52d Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 7 Apr 2018 18:52:02 -0300 Subject: [PATCH 2449/2557] configure: disable direct stripping in OpenBSD It appears strip -o creates new files without preserving permissions from the source binary, resulting in non executable files. Signed-off-by: James Almer --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 1e192f87808e1..c935d87b81dd7 100755 --- a/configure +++ b/configure @@ -5048,6 +5048,7 @@ case $target_os in ;; openbsd|bitrig) disable symver + striptype="" SHFLAGS='-shared' SLIB_INSTALL_NAME='$(SLIBNAME).$(LIBMAJOR).$(LIBMINOR)' SLIB_INSTALL_LINKS= From 876f9ac9a682fc2a3b05d2fe35354d717ae39dc3 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 13 Apr 2018 11:04:40 -0300 Subject: [PATCH 2450/2557] configure: make the C11 atomics check more robust C11 atomics allow direct access. This check should prevent the usage of bogus stdatomic.h available on some systems. Signed-off-by: James Almer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index c935d87b81dd7..73857f4511b19 100755 --- a/configure +++ b/configure @@ -5825,7 +5825,7 @@ check_header asm/types.h # it seems there are versions of clang in some distros that try to use the # gcc headers, which explodes for stdatomic # so we also check that atomics actually work here -check_builtin stdatomic stdatomic.h "atomic_int foo, bar = ATOMIC_VAR_INIT(-1); atomic_store(&foo, 0)" +check_builtin stdatomic stdatomic.h "atomic_int foo, bar = ATOMIC_VAR_INIT(-1); atomic_store(&foo, 0); foo += bar" check_lib advapi32 "windows.h" RegCloseKey -ladvapi32 check_lib ole32 "windows.h" CoTaskMemFree -lole32 From 6b28e551d00912e0efeda8536039f8204752a684 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Wed, 11 Apr 2018 21:46:03 +0530 Subject: [PATCH 2451/2557] MAINTAINERS: add myself to documentation section Signed-off-by: Lou Logan --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 5c7bf4726f98e..b61856243cc10 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -39,7 +39,7 @@ QuickTime faststart: Miscellaneous Areas =================== -documentation Stefano Sabatini, Mike Melanson, Timothy Gu, Lou Logan +documentation Stefano Sabatini, Mike Melanson, Timothy Gu, Lou Logan, Gyan Doshi project server Árpád Gereöffy, Michael Niedermayer, Reimar Doeffinger, Alexander Strasser, Nikolay Aleksandrov presets Robert Swain metadata subsystem Aurelien Jacobs From 3e1204b94d1ab586e4a5b1fc7c51559bc2447dcd Mon Sep 17 00:00:00 2001 From: Bela Bodecs Date: Fri, 13 Apr 2018 12:11:32 +0200 Subject: [PATCH 2452/2557] avformat/utils: Stream specifier enhancement 2. In some cases, mainly working with multiprogram mpeg-ts containers as input, it would be handy to select sub stream of a specific program by their metadata. This patch makes it possible to narrow the stream selection among streams of the specified program by stream metadata. Examples: p:601:m:language:hun will select all sub streams of program with id 601 where sub streams have metadata key named 'language' with value 'hun'. p:602:m:guide will select all sub streams of program with id 602 where sub streams have metadata key named 'guide'. Signed-off-by: Bela Bodecs Signed-off-by: Michael Niedermayer --- doc/fftools-common-opts.texi | 10 ++++++++-- libavformat/utils.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/doc/fftools-common-opts.texi b/doc/fftools-common-opts.texi index 79feb39ca7188..84705c0b68a19 100644 --- a/doc/fftools-common-opts.texi +++ b/doc/fftools-common-opts.texi @@ -42,14 +42,20 @@ streams, 'V' only matches video streams which are not attached pictures, video thumbnails or cover arts. If @var{stream_index} is given, then it matches stream number @var{stream_index} of this type. Otherwise, it matches all streams of this type. -@item p:@var{program_id}[:@var{stream_index}] or p:@var{program_id}[:@var{stream_type}[:@var{stream_index}]] +@item p:@var{program_id}[:@var{stream_index}] or p:@var{program_id}[:@var{stream_type}[:@var{stream_index}]] or +p:@var{program_id}:m:@var{key}[:@var{value}] In first version, if @var{stream_index} is given, then it matches the stream with number @var{stream_index} in the program with the id @var{program_id}. Otherwise, it matches all streams in the -program. In the latter version, @var{stream_type} is one of following: 'v' for video, 'a' for audio, 's' +program. In the second version, @var{stream_type} is one of following: 'v' for video, 'a' for audio, 's' for subtitle, 'd' for data. If @var{stream_index} is also given, then it matches stream number @var{stream_index} of this type in the program with the id @var{program_id}. Otherwise, if only @var{stream_type} is given, it matches all streams of this type in the program with the id @var{program_id}. +In the third version matches streams in the program with the id @var{program_id} with the metadata +tag @var{key} having the specified value. If +@var{value} is not given, matches streams that contain the given tag with any +value. + @item #@var{stream_id} or i:@var{stream_id} Match the stream by stream id (e.g. PID in MPEG-TS container). @item m:@var{key}[:@var{value}] diff --git a/libavformat/utils.c b/libavformat/utils.c index cc35998336751..84b926dc5a8af 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -5124,6 +5124,34 @@ FF_ENABLE_DEPRECATION_WARNINGS } return 0; } + + } else if ( *endptr == 'm') { // p::m: + AVDictionaryEntry *tag; + char *key, *val; + int ret = 0; + + if (*(++endptr) != ':') { + av_log(s, AV_LOG_ERROR, "Invalid stream specifier syntax, missing ':' sign after :m.\n"); + return AVERROR(EINVAL); + } + + val = strchr(++endptr, ':'); + key = val ? av_strndup(endptr, val - endptr) : av_strdup(endptr); + if (!key) + return AVERROR(ENOMEM); + + for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) + if (st->index == s->programs[i]->stream_index[j]) { + tag = av_dict_get(st->metadata, key, NULL, 0); + if (tag && (!val || !strcmp(tag->value, val + 1))) + ret = 1; + + break; + } + + av_freep(&key); + return ret; + } else { // p:: int stream_idx = strtol(endptr, NULL, 0); return stream_idx >= 0 && From 5c62a3dbda151e5a184fc29b4c7079cf8415b7e8 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 13 Apr 2018 15:50:54 +0200 Subject: [PATCH 2453/2557] tests/fate/filter-video: Use a bitexact/lossless input sample for fate-filter-metadata-silencedetect Signed-off-by: Michael Niedermayer --- tests/fate/filter-video.mak | 7 +- tests/ref/fate/filter-metadata-silencedetect | 520 +------------------ 2 files changed, 13 insertions(+), 514 deletions(-) diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 0127f9bd138d7..17d6363678358 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -727,11 +727,10 @@ FATE_METADATA_FILTER-$(call ALLYES, $(CROPDETECT_DEPS)) += fate-filter-metadata- fate-filter-metadata-cropdetect: SRC = $(TARGET_SAMPLES)/filter/cropdetect.mp4 fate-filter-metadata-cropdetect: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;movie='$(SRC)',cropdetect=max_outliers=3" -SILENCEDETECT_DEPS = FFPROBE AVDEVICE LAVFI_INDEV AMOVIE_FILTER AMR_DEMUXER AMRWB_DECODER SILENCEDETECT_FILTER +SILENCEDETECT_DEPS = FFPROBE AVDEVICE LAVFI_INDEV AMOVIE_FILTER TTA_DEMUXER TTA_DECODER SILENCEDETECT_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(SILENCEDETECT_DEPS)) += fate-filter-metadata-silencedetect -fate-filter-metadata-silencedetect: SRC = $(TARGET_SAMPLES)/amrwb/seed-12k65.awb -fate-filter-metadata-silencedetect: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',silencedetect=n=-42dB:d=.3" - +fate-filter-metadata-silencedetect: SRC = $(TARGET_SAMPLES)/lossless-audio/inside.tta +fate-filter-metadata-silencedetect: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',silencedetect=n=-33.5dB:d=.2" EBUR128_METADATA_DEPS = FFPROBE AVDEVICE LAVFI_INDEV AMOVIE_FILTER FLAC_DEMUXER FLAC_DECODER EBUR128_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(EBUR128_METADATA_DEPS)) += fate-filter-metadata-ebur128 diff --git a/tests/ref/fate/filter-metadata-silencedetect b/tests/ref/fate/filter-metadata-silencedetect index e4be2ffac788e..16a9d07692514 100644 --- a/tests/ref/fate/filter-metadata-silencedetect +++ b/tests/ref/fate/filter-metadata-silencedetect @@ -1,512 +1,12 @@ -pkt_pts=0 -pkt_pts=320 -pkt_pts=640 -pkt_pts=960 -pkt_pts=1280 -pkt_pts=1600 -pkt_pts=1920 -pkt_pts=2240 -pkt_pts=2560 -pkt_pts=2880 -pkt_pts=3200 -pkt_pts=3520 -pkt_pts=3840 -pkt_pts=4160 -pkt_pts=4480|tag:lavfi.silence_start=0 -pkt_pts=4800 -pkt_pts=5120 -pkt_pts=5440 -pkt_pts=5760 -pkt_pts=6080|tag:lavfi.silence_end=0.384813|tag:lavfi.silence_duration=0.384813 -pkt_pts=6400 -pkt_pts=6720 -pkt_pts=7040 -pkt_pts=7360 -pkt_pts=7680 -pkt_pts=8000 -pkt_pts=8320 -pkt_pts=8640 -pkt_pts=8960 -pkt_pts=9280 -pkt_pts=9600 -pkt_pts=9920 -pkt_pts=10240 -pkt_pts=10560 -pkt_pts=10880 -pkt_pts=11200 -pkt_pts=11520 -pkt_pts=11840 -pkt_pts=12160 -pkt_pts=12480 -pkt_pts=12800 -pkt_pts=13120 -pkt_pts=13440 -pkt_pts=13760 -pkt_pts=14080 -pkt_pts=14400 -pkt_pts=14720 -pkt_pts=15040 -pkt_pts=15360 -pkt_pts=15680 -pkt_pts=16000 -pkt_pts=16320 -pkt_pts=16640 -pkt_pts=16960 -pkt_pts=17280 -pkt_pts=17600 -pkt_pts=17920 -pkt_pts=18240 -pkt_pts=18560 -pkt_pts=18880 -pkt_pts=19200 -pkt_pts=19520 -pkt_pts=19840 -pkt_pts=20160 -pkt_pts=20480 -pkt_pts=20800 -pkt_pts=21120 -pkt_pts=21440 -pkt_pts=21760 -pkt_pts=22080 -pkt_pts=22400 -pkt_pts=22720 -pkt_pts=23040 -pkt_pts=23360 -pkt_pts=23680|tag:lavfi.silence_start=1.18756 -pkt_pts=24000 -pkt_pts=24320 -pkt_pts=24640 -pkt_pts=24960 -pkt_pts=25280 -pkt_pts=25600 -pkt_pts=25920 -pkt_pts=26240 -pkt_pts=26560 -pkt_pts=26880 -pkt_pts=27200 -pkt_pts=27520 -pkt_pts=27840 -pkt_pts=28160 -pkt_pts=28480 -pkt_pts=28800 -pkt_pts=29120 -pkt_pts=29440 -pkt_pts=29760 -pkt_pts=30080 -pkt_pts=30400 -pkt_pts=30720 -pkt_pts=31040 -pkt_pts=31360 -pkt_pts=31680|tag:lavfi.silence_end=1.99538|tag:lavfi.silence_duration=0.807813 -pkt_pts=32000 -pkt_pts=32320 -pkt_pts=32640 -pkt_pts=32960 -pkt_pts=33280 -pkt_pts=33600 -pkt_pts=33920 -pkt_pts=34240 -pkt_pts=34560 -pkt_pts=34880 -pkt_pts=35200 -pkt_pts=35520 -pkt_pts=35840 -pkt_pts=36160 -pkt_pts=36480 -pkt_pts=36800 -pkt_pts=37120 -pkt_pts=37440 -pkt_pts=37760 -pkt_pts=38080 -pkt_pts=38400 -pkt_pts=38720 -pkt_pts=39040 -pkt_pts=39360 -pkt_pts=39680 -pkt_pts=40000 -pkt_pts=40320 -pkt_pts=40640 -pkt_pts=40960 -pkt_pts=41280 -pkt_pts=41600 -pkt_pts=41920 -pkt_pts=42240 -pkt_pts=42560 -pkt_pts=42880 -pkt_pts=43200 -pkt_pts=43520 -pkt_pts=43840 -pkt_pts=44160 -pkt_pts=44480 -pkt_pts=44800 -pkt_pts=45120 -pkt_pts=45440 -pkt_pts=45760 -pkt_pts=46080 -pkt_pts=46400 -pkt_pts=46720 -pkt_pts=47040 -pkt_pts=47360 -pkt_pts=47680 -pkt_pts=48000 -pkt_pts=48320 -pkt_pts=48640 -pkt_pts=48960 -pkt_pts=49280 -pkt_pts=49600 -pkt_pts=49920 -pkt_pts=50240 -pkt_pts=50560 -pkt_pts=50880 -pkt_pts=51200 -pkt_pts=51520 -pkt_pts=51840|tag:lavfi.silence_start=2.945 -pkt_pts=52160 -pkt_pts=52480 -pkt_pts=52800 -pkt_pts=53120 -pkt_pts=53440 -pkt_pts=53760 -pkt_pts=54080 -pkt_pts=54400 -pkt_pts=54720 -pkt_pts=55040 -pkt_pts=55360 -pkt_pts=55680 -pkt_pts=56000 -pkt_pts=56320 -pkt_pts=56640 -pkt_pts=56960 -pkt_pts=57280 -pkt_pts=57600 -pkt_pts=57920 -pkt_pts=58240 -pkt_pts=58560 -pkt_pts=58880 -pkt_pts=59200 -pkt_pts=59520 -pkt_pts=59840 -pkt_pts=60160 -pkt_pts=60480 -pkt_pts=60800 -pkt_pts=61120 -pkt_pts=61440 -pkt_pts=61760 -pkt_pts=62080 -pkt_pts=62400 -pkt_pts=62720 -pkt_pts=63040 -pkt_pts=63360|tag:lavfi.silence_end=3.97138|tag:lavfi.silence_duration=1.02638 -pkt_pts=63680 -pkt_pts=64000 -pkt_pts=64320 -pkt_pts=64640 -pkt_pts=64960 -pkt_pts=65280 -pkt_pts=65600 -pkt_pts=65920 -pkt_pts=66240 -pkt_pts=66560 -pkt_pts=66880 -pkt_pts=67200 -pkt_pts=67520 -pkt_pts=67840 -pkt_pts=68160 -pkt_pts=68480 -pkt_pts=68800 -pkt_pts=69120 -pkt_pts=69440 -pkt_pts=69760 -pkt_pts=70080 -pkt_pts=70400 -pkt_pts=70720 -pkt_pts=71040 -pkt_pts=71360 -pkt_pts=71680 -pkt_pts=72000 -pkt_pts=72320 -pkt_pts=72640 -pkt_pts=72960 -pkt_pts=73280 -pkt_pts=73600 -pkt_pts=73920 -pkt_pts=74240 -pkt_pts=74560 -pkt_pts=74880 -pkt_pts=75200 -pkt_pts=75520 -pkt_pts=75840 -pkt_pts=76160 -pkt_pts=76480 -pkt_pts=76800 -pkt_pts=77120 -pkt_pts=77440 -pkt_pts=77760 -pkt_pts=78080 -pkt_pts=78400 -pkt_pts=78720 -pkt_pts=79040 -pkt_pts=79360 -pkt_pts=79680 -pkt_pts=80000 -pkt_pts=80320 -pkt_pts=80640|tag:lavfi.silence_start=4.75662 -pkt_pts=80960 -pkt_pts=81280 -pkt_pts=81600 -pkt_pts=81920 -pkt_pts=82240 -pkt_pts=82560 -pkt_pts=82880 -pkt_pts=83200 -pkt_pts=83520 -pkt_pts=83840 -pkt_pts=84160 -pkt_pts=84480 -pkt_pts=84800 -pkt_pts=85120 -pkt_pts=85440 -pkt_pts=85760 -pkt_pts=86080 -pkt_pts=86400 -pkt_pts=86720 -pkt_pts=87040|tag:lavfi.silence_end=5.45|tag:lavfi.silence_duration=0.693375 -pkt_pts=87360 -pkt_pts=87680 -pkt_pts=88000 -pkt_pts=88320 -pkt_pts=88640 -pkt_pts=88960 -pkt_pts=89280 -pkt_pts=89600 -pkt_pts=89920 -pkt_pts=90240 -pkt_pts=90560 -pkt_pts=90880 -pkt_pts=91200 -pkt_pts=91520 -pkt_pts=91840 +pkt_pts=0|tag:lavfi.silence_duration=0.523107|tag:lavfi.silence_end=0.690023|tag:lavfi.silence_start=0.736417 +pkt_pts=46080|tag:lavfi.silence_start=1.27626|tag:lavfi.silence_end=1.80751|tag:lavfi.silence_duration=0.531247 pkt_pts=92160 -pkt_pts=92480 -pkt_pts=92800 -pkt_pts=93120 -pkt_pts=93440 -pkt_pts=93760 -pkt_pts=94080 -pkt_pts=94400 -pkt_pts=94720 -pkt_pts=95040 -pkt_pts=95360 -pkt_pts=95680 -pkt_pts=96000 -pkt_pts=96320 -pkt_pts=96640 -pkt_pts=96960 -pkt_pts=97280 -pkt_pts=97600 -pkt_pts=97920 -pkt_pts=98240 -pkt_pts=98560 -pkt_pts=98880 -pkt_pts=99200 -pkt_pts=99520 -pkt_pts=99840 -pkt_pts=100160 -pkt_pts=100480 -pkt_pts=100800 -pkt_pts=101120 -pkt_pts=101440 -pkt_pts=101760 -pkt_pts=102080 -pkt_pts=102400 -pkt_pts=102720 -pkt_pts=103040 -pkt_pts=103360 -pkt_pts=103680 -pkt_pts=104000 -pkt_pts=104320 -pkt_pts=104640 -pkt_pts=104960|tag:lavfi.silence_start=6.27319 -pkt_pts=105280 -pkt_pts=105600 -pkt_pts=105920 -pkt_pts=106240 -pkt_pts=106560 -pkt_pts=106880 -pkt_pts=107200 -pkt_pts=107520 -pkt_pts=107840 -pkt_pts=108160 -pkt_pts=108480 -pkt_pts=108800 -pkt_pts=109120 -pkt_pts=109440 -pkt_pts=109760 -pkt_pts=110080 -pkt_pts=110400 -pkt_pts=110720 -pkt_pts=111040 -pkt_pts=111360 -pkt_pts=111680 -pkt_pts=112000 -pkt_pts=112320 -pkt_pts=112640 -pkt_pts=112960 -pkt_pts=113280 -pkt_pts=113600 -pkt_pts=113920 -pkt_pts=114240 -pkt_pts=114560 -pkt_pts=114880 -pkt_pts=115200 -pkt_pts=115520 -pkt_pts=115840 -pkt_pts=116160 -pkt_pts=116480|tag:lavfi.silence_end=7.28569|tag:lavfi.silence_duration=1.0125 -pkt_pts=116800 -pkt_pts=117120 -pkt_pts=117440 -pkt_pts=117760 -pkt_pts=118080 -pkt_pts=118400 -pkt_pts=118720 -pkt_pts=119040 -pkt_pts=119360 -pkt_pts=119680 -pkt_pts=120000 -pkt_pts=120320 -pkt_pts=120640 -pkt_pts=120960 -pkt_pts=121280 -pkt_pts=121600 -pkt_pts=121920 -pkt_pts=122240 -pkt_pts=122560 -pkt_pts=122880 -pkt_pts=123200 -pkt_pts=123520 -pkt_pts=123840 -pkt_pts=124160 -pkt_pts=124480 -pkt_pts=124800 -pkt_pts=125120 -pkt_pts=125440 -pkt_pts=125760 -pkt_pts=126080 -pkt_pts=126400 -pkt_pts=126720 -pkt_pts=127040 -pkt_pts=127360 -pkt_pts=127680 -pkt_pts=128000 -pkt_pts=128320 -pkt_pts=128640 -pkt_pts=128960 -pkt_pts=129280 -pkt_pts=129600 -pkt_pts=129920 -pkt_pts=130240 -pkt_pts=130560 -pkt_pts=130880 -pkt_pts=131200 -pkt_pts=131520 -pkt_pts=131840 -pkt_pts=132160 -pkt_pts=132480 -pkt_pts=132800 -pkt_pts=133120 -pkt_pts=133440 -pkt_pts=133760 -pkt_pts=134080 -pkt_pts=134400 -pkt_pts=134720 -pkt_pts=135040 -pkt_pts=135360 -pkt_pts=135680 -pkt_pts=136000 -pkt_pts=136320 -pkt_pts=136640|tag:lavfi.silence_start=8.25106 -pkt_pts=136960 -pkt_pts=137280 -pkt_pts=137600 -pkt_pts=137920 pkt_pts=138240 -pkt_pts=138560 -pkt_pts=138880 -pkt_pts=139200 -pkt_pts=139520 -pkt_pts=139840 -pkt_pts=140160 -pkt_pts=140480 -pkt_pts=140800 -pkt_pts=141120 -pkt_pts=141440 -pkt_pts=141760 -pkt_pts=142080 -pkt_pts=142400 -pkt_pts=142720 -pkt_pts=143040 -pkt_pts=143360 -pkt_pts=143680 -pkt_pts=144000 -pkt_pts=144320 -pkt_pts=144640 -pkt_pts=144960 -pkt_pts=145280|tag:lavfi.silence_end=9.08156|tag:lavfi.silence_duration=0.8305 -pkt_pts=145600 -pkt_pts=145920 -pkt_pts=146240 -pkt_pts=146560 -pkt_pts=146880 -pkt_pts=147200 -pkt_pts=147520 -pkt_pts=147840 -pkt_pts=148160 -pkt_pts=148480 -pkt_pts=148800 -pkt_pts=149120 -pkt_pts=149440 -pkt_pts=149760 -pkt_pts=150080 -pkt_pts=150400 -pkt_pts=150720 -pkt_pts=151040 -pkt_pts=151360 -pkt_pts=151680 -pkt_pts=152000 -pkt_pts=152320 -pkt_pts=152640 -pkt_pts=152960 -pkt_pts=153280 -pkt_pts=153600 -pkt_pts=153920 -pkt_pts=154240 -pkt_pts=154560 -pkt_pts=154880 -pkt_pts=155200 -pkt_pts=155520 -pkt_pts=155840 -pkt_pts=156160 -pkt_pts=156480 -pkt_pts=156800 -pkt_pts=157120 -pkt_pts=157440 -pkt_pts=157760 -pkt_pts=158080 -pkt_pts=158400 -pkt_pts=158720 -pkt_pts=159040 -pkt_pts=159360 -pkt_pts=159680 -pkt_pts=160000 -pkt_pts=160320 -pkt_pts=160640 -pkt_pts=160960 -pkt_pts=161280 -pkt_pts=161600 -pkt_pts=161920|tag:lavfi.silence_start=9.83881 -pkt_pts=162240 -pkt_pts=162560 -pkt_pts=162880 -pkt_pts=163200 -pkt_pts=163520 +pkt_pts=184320 +pkt_pts=230400 +pkt_pts=276480 +pkt_pts=322560 +pkt_pts=368640 +pkt_pts=414720 +pkt_pts=460800 +pkt_pts=506880 From c48ceff786bdc96fdc64417118c457d03bd19871 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 11 Apr 2018 18:55:57 +0200 Subject: [PATCH 2454/2557] avformat/utils: Fix integer overflow in end time calculation in update_stream_timings() Fixes: crbug 829153 Reported-by: Matt Wolenetz Reviewed-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavformat/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index 84b926dc5a8af..69f9653190e43 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2648,7 +2648,7 @@ static void update_stream_timings(AVFormatContext *ic) else if (start_time > start_time_text) av_log(ic, AV_LOG_VERBOSE, "Ignoring outlier non primary stream starttime %f\n", start_time_text / (float)AV_TIME_BASE); - if (end_time == INT64_MIN || (end_time < end_time_text && end_time_text - end_time < AV_TIME_BASE)) { + if (end_time == INT64_MIN || (end_time < end_time_text && end_time_text - (uint64_t)end_time < AV_TIME_BASE)) { end_time = end_time_text; } else if (end_time < end_time_text) { av_log(ic, AV_LOG_VERBOSE, "Ignoring outlier non primary stream endtime %f\n", end_time_text / (float)AV_TIME_BASE); From f6304af2341d0cee51c2116766622e3ac567b7a0 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 10 Apr 2018 22:24:03 +0200 Subject: [PATCH 2455/2557] avcodec/truemotion2: Propagate out of bounds error from GET_TOK() Fixes: Timeout Fixes: 6389/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TRUEMOTION2_fuzzer-5695918121680896 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/truemotion2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/truemotion2.c b/libavcodec/truemotion2.c index 97c38f7f088d2..f7dbe047c78a8 100644 --- a/libavcodec/truemotion2.c +++ b/libavcodec/truemotion2.c @@ -63,6 +63,7 @@ typedef struct TM2Context { AVFrame *pic; GetBitContext gb; + int error; BswapDSPContext bdsp; uint8_t *buffer; @@ -398,6 +399,7 @@ static inline int GET_TOK(TM2Context *ctx,int type) { if (ctx->tok_ptrs[type] >= ctx->tok_lens[type]) { av_log(ctx->avctx, AV_LOG_ERROR, "Read token from stream %i out of bounds (%i>=%i)\n", type, ctx->tok_ptrs[type], ctx->tok_lens[type]); + ctx->error = 1; return 0; } if (type <= TM2_MOT) { @@ -809,6 +811,8 @@ static int tm2_decode_blocks(TM2Context *ctx, AVFrame *p) default: av_log(ctx->avctx, AV_LOG_ERROR, "Skipping unknown block type %i\n", type); } + if (ctx->error) + return AVERROR_INVALIDDATA; } } @@ -889,6 +893,8 @@ static int decode_frame(AVCodecContext *avctx, int offset = TM2_HEADER_SIZE; int i, t, ret; + l->error = 0; + av_fast_padded_malloc(&l->buffer, &l->buffer_size, buf_size); if (!l->buffer) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n"); From 544324827e0131e43af1a54fb790a48a25fd7ba4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 11 Apr 2018 19:50:52 +0200 Subject: [PATCH 2456/2557] avcodec/utils: Enforce minimum width also for VP5/6 Fixes: out of array access Fixes: poc_0411 Found-by: GwanYeong Kim Tested-by: GwanYeong Kim Signed-off-by: Michael Niedermayer --- libavcodec/utils.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 8c7d056da6454..59d41ccbb64db 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -312,7 +312,10 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, *width = FFALIGN(*width, w_align); *height = FFALIGN(*height, h_align); - if (s->codec_id == AV_CODEC_ID_H264 || s->lowres) { + if (s->codec_id == AV_CODEC_ID_H264 || s->lowres || + s->codec_id == AV_CODEC_ID_VP5 || s->codec_id == AV_CODEC_ID_VP6 || + s->codec_id == AV_CODEC_ID_VP6F || s->codec_id == AV_CODEC_ID_VP6A + ) { // some of the optimized chroma MC reads one line too much // which is also done in mpeg decoders with lowres > 0 *height += 2; From 37d46dc21d708192b12aa13617ebe6a117b07363 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 13 Apr 2018 11:38:48 +0200 Subject: [PATCH 2457/2557] avformat/utils: Check cur_dts in update_initial_timestamps() more Fixes: runtime error: signed integer overflow: 18133149658382192 - -9223090561878065151 cannot be represented in type 'long long' Fixes: crbug 831552 Reported-by: Matt Wolenetz Reviewed-by: Matt Wolenetz Signed-off-by: Michael Niedermayer --- libavformat/utils.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/utils.c b/libavformat/utils.c index 69f9653190e43..733c6d65dc4ed 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1129,6 +1129,7 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, if (st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE || st->cur_dts == AV_NOPTS_VALUE || + st->cur_dts < INT_MIN + RELATIVE_TS_BASE || is_relative(dts)) return; From 23e994ca496c51f67d764ffa48be715c877883e5 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 12 Apr 2018 00:06:30 -0300 Subject: [PATCH 2458/2557] avformat/utils: use the existing packet reference when parsing complete frames If the parser returns full frames, then the output pointer retured by av_parser_parse2() is guaranteed to point to data contained in the input packet's buffer. Create a new reference to said buffer in that case, to avoid unnecessary data copy when queueing the packet later in the function. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- libavformat/utils.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index 733c6d65dc4ed..f2f2cc4239079 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1472,6 +1472,22 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) if (!out_pkt.size) continue; + if (pkt->buf && out_pkt.data == pkt->data) { + /* reference pkt->buf only when out_pkt.data is guaranteed to point + * to data in it and not in the parser's internal buffer. */ + /* XXX: Ensure this is the case with all parsers when st->parser->flags + * is PARSER_FLAG_COMPLETE_FRAMES and check for that instead? */ + out_pkt.buf = av_buffer_ref(pkt->buf); + if (!out_pkt.buf) { + ret = AVERROR(ENOMEM); + goto fail; + } + } else { + ret = av_packet_make_refcounted(&out_pkt); + if (ret < 0) + goto fail; + } + if (pkt->side_data) { out_pkt.side_data = pkt->side_data; out_pkt.side_data_elems = pkt->side_data_elems; @@ -1512,10 +1528,11 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) ret = ff_packet_list_put(&s->internal->parse_queue, &s->internal->parse_queue_end, - &out_pkt, FF_PACKETLIST_FLAG_REF_PACKET); - av_packet_unref(&out_pkt); - if (ret < 0) + &out_pkt, 0); + if (ret < 0) { + av_packet_unref(&out_pkt); goto fail; + } } /* end of the stream => close and free the parser */ From 18d6ff2b42c120f1b388c472366b0275ddf9629a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 13 Apr 2018 02:34:01 +0200 Subject: [PATCH 2459/2557] tests/checkasm/checkasm: Provide verbose failure information on float_near_abs_eps() failures This will make understanding failures and adjusting EPS easier Signed-off-by: Michael Niedermayer --- tests/checkasm/checkasm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 20ce56932fe5d..ba1d1d0253d2b 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -294,8 +294,12 @@ int float_near_ulp_array(const float *a, const float *b, unsigned max_ulp, int float_near_abs_eps(float a, float b, float eps) { float abs_diff = fabsf(a - b); + if (abs_diff < eps) + return 1; - return abs_diff < eps; + fprintf(stderr, "test failed comparing %g with %g (abs diff=%g with EPS=%g)\n", a, b, abs_diff, eps); + + return 0; } int float_near_abs_eps_array(const float *a, const float *b, float eps, From 2b0f821f51d10ade2fa6d3efc33b09e594d0fcac Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 14 Apr 2018 17:25:06 +0200 Subject: [PATCH 2460/2557] avfilter/af_headphone: improve performance and reduce latency Remove not needed code. Signed-off-by: Paul B Mahol --- doc/filters.texi | 4 ++++ libavfilter/af_headphone.c | 14 ++------------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 30060ce9182c6..18a6da155c9a6 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -3175,6 +3175,10 @@ Default is @var{freq}. @item lfe Set custom gain for LFE channels. Value is in dB. Default is 0. + +@item size +Set size of frame in number of samples which will be processed at once. +Default value is @var{1024}. Allowed range is from 1024 to 96000. @end table @subsection Examples diff --git a/libavfilter/af_headphone.c b/libavfilter/af_headphone.c index 2188f7ab24f56..974445e15ccec 100644 --- a/libavfilter/af_headphone.c +++ b/libavfilter/af_headphone.c @@ -404,7 +404,7 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) int i, j; s->buffer_length = 1 << (32 - ff_clz(s->ir_len)); - s->n_fft = n_fft = 1 << (32 - ff_clz(s->ir_len + inlink->sample_rate)); + s->n_fft = n_fft = 1 << (32 - ff_clz(s->ir_len + s->size)); if (s->type == FREQUENCY_DOMAIN) { fft_in_l = av_calloc(n_fft, sizeof(*fft_in_l)); @@ -650,12 +650,6 @@ static int config_input(AVFilterLink *inlink) AVFilterContext *ctx = inlink->dst; HeadphoneContext *s = ctx->priv; - if (s->type == FREQUENCY_DOMAIN) { - inlink->partial_buf_size = - inlink->min_samples = - inlink->max_samples = inlink->sample_rate; - } - if (s->nb_irs < inlink->channels) { av_log(ctx, AV_LOG_ERROR, "Number of inputs must be >= %d.\n", inlink->channels + 1); return AVERROR(EINVAL); @@ -719,11 +713,6 @@ static int config_output(AVFilterLink *outlink) AVFilterLink *inlink = ctx->inputs[0]; int i; - if (s->type == TIME_DOMAIN) - s->size = 1024; - else - s->size = inlink->sample_rate; - for (i = 0; i < s->nb_inputs; i++) { s->in[i].fifo = av_audio_fifo_alloc(ctx->inputs[i]->format, ctx->inputs[i]->channels, 1024); if (!s->in[i].fifo) @@ -798,6 +787,7 @@ static const AVOption headphone_options[] = { { "type", "set processing", OFFSET(type), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, .flags = FLAGS, "type" }, { "time", "time domain", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, .flags = FLAGS, "type" }, { "freq", "frequency domain", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, .flags = FLAGS, "type" }, + { "size", "set frame size", OFFSET(size), AV_OPT_TYPE_INT, {.i64=1024},1024,96000, .flags = FLAGS }, { NULL } }; From 01170e9db0715123ada6114a8189858a43f81caf Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 14 Apr 2018 17:49:54 +0200 Subject: [PATCH 2461/2557] avfilter/af_headphone: fix flushing Signed-off-by: Paul B Mahol --- libavfilter/af_headphone.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libavfilter/af_headphone.c b/libavfilter/af_headphone.c index 974445e15ccec..57cca1a4f6c8d 100644 --- a/libavfilter/af_headphone.c +++ b/libavfilter/af_headphone.c @@ -742,7 +742,20 @@ static int request_frame(AVFilterLink *outlink) s->eof_hrirs = 1; } } - return ff_request_frame(ctx->inputs[0]); + + ret = ff_request_frame(ctx->inputs[0]); + if (ret == AVERROR_EOF && av_audio_fifo_size(s->in[0].fifo) > 0 && s->have_hrirs) { + AVFrame *in = ff_get_audio_buffer(outlink, s->size); + + ret = av_audio_fifo_write(s->in[0].fifo, (void **)in->extended_data, + in->nb_samples); + if (ret < 0) + return ret; + ret = headphone_frame(s, outlink); + av_audio_fifo_drain(s->in[0].fifo, av_audio_fifo_size(s->in[0].fifo)); + } + + return ret; } static av_cold void uninit(AVFilterContext *ctx) From 8daca7697b7d8d6b9997757be70604fe17c647f3 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 14 Apr 2018 18:38:54 +0200 Subject: [PATCH 2462/2557] avfilter/af_headphone: do not output invalid samples when flushing Signed-off-by: Paul B Mahol --- libavfilter/af_headphone.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/libavfilter/af_headphone.c b/libavfilter/af_headphone.c index 57cca1a4f6c8d..edb1fac70f189 100644 --- a/libavfilter/af_headphone.c +++ b/libavfilter/af_headphone.c @@ -349,7 +349,7 @@ static int read_ir(AVFilterLink *inlink, AVFrame *frame) return 0; } -static int headphone_frame(HeadphoneContext *s, AVFilterLink *outlink) +static int headphone_frame(HeadphoneContext *s, AVFilterLink *outlink, int max_nb_samples) { AVFilterContext *ctx = outlink->src; AVFrame *in = s->in[0].frame; @@ -383,6 +383,7 @@ static int headphone_frame(HeadphoneContext *s, AVFilterLink *outlink) n_clippings[0] + n_clippings[1], out->nb_samples * 2); } + out->nb_samples = max_nb_samples; return ff_filter_frame(outlink, out); } @@ -593,7 +594,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->have_hrirs) { while (av_audio_fifo_size(s->in[0].fifo) >= s->size) { - ret = headphone_frame(s, outlink); + ret = headphone_frame(s, outlink, s->size); if (ret < 0) return ret; } @@ -745,13 +746,20 @@ static int request_frame(AVFilterLink *outlink) ret = ff_request_frame(ctx->inputs[0]); if (ret == AVERROR_EOF && av_audio_fifo_size(s->in[0].fifo) > 0 && s->have_hrirs) { - AVFrame *in = ff_get_audio_buffer(outlink, s->size); + int nb_samples = av_audio_fifo_size(s->in[0].fifo); + AVFrame *in = ff_get_audio_buffer(outlink, s->size - nb_samples); + + av_samples_set_silence(in->extended_data, 0, + in->nb_samples, + outlink->channels, + outlink->format); ret = av_audio_fifo_write(s->in[0].fifo, (void **)in->extended_data, in->nb_samples); if (ret < 0) return ret; - ret = headphone_frame(s, outlink); + ret = headphone_frame(s, outlink, nb_samples); + av_audio_fifo_drain(s->in[0].fifo, av_audio_fifo_size(s->in[0].fifo)); } From a56580b117362bf1b082cbbd6e3e573380c3aff8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 14 Apr 2018 19:42:16 +0200 Subject: [PATCH 2463/2557] avfilter/af_headphone: fix memory leak and overread Signed-off-by: Paul B Mahol --- libavfilter/af_headphone.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavfilter/af_headphone.c b/libavfilter/af_headphone.c index edb1fac70f189..8b34609a2f3d6 100644 --- a/libavfilter/af_headphone.c +++ b/libavfilter/af_headphone.c @@ -747,15 +747,19 @@ static int request_frame(AVFilterLink *outlink) ret = ff_request_frame(ctx->inputs[0]); if (ret == AVERROR_EOF && av_audio_fifo_size(s->in[0].fifo) > 0 && s->have_hrirs) { int nb_samples = av_audio_fifo_size(s->in[0].fifo); - AVFrame *in = ff_get_audio_buffer(outlink, s->size - nb_samples); + AVFrame *in = ff_get_audio_buffer(ctx->inputs[0], s->size - nb_samples); + + if (!in) + return AVERROR(ENOMEM); av_samples_set_silence(in->extended_data, 0, in->nb_samples, - outlink->channels, - outlink->format); + in->channels, + in->format); ret = av_audio_fifo_write(s->in[0].fifo, (void **)in->extended_data, in->nb_samples); + av_frame_free(&in); if (ret < 0) return ret; ret = headphone_frame(s, outlink, nb_samples); From aedbf1640ced8fc09dc980ead2a387a59d8f7f68 Mon Sep 17 00:00:00 2001 From: Steve Lhomme Date: Tue, 3 Apr 2018 11:44:25 +0200 Subject: [PATCH 2464/2557] avutil/random_seed: use bcrypt instead of the old wincrypt API Remove the wincrypt API calls since we don't support XP anymore and bcrypt is available since Vista, even on Windows Store builds. Reviewed-by: Michael Niedermayer Signed-off-by: James Almer --- configure | 6 +++--- libavutil/random_seed.c | 19 ++++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/configure b/configure index 73857f4511b19..36e425be62aa9 100755 --- a/configure +++ b/configure @@ -2142,10 +2142,10 @@ SYSTEM_FUNCS=" " SYSTEM_LIBRARIES=" + bcrypt vaapi_drm vaapi_x11 vdpau_x11 - wincrypt " TOOLCHAIN_FEATURES=" @@ -3445,7 +3445,7 @@ avformat_deps="avcodec avutil" avformat_suggest="libm network zlib" avresample_deps="avutil" avresample_suggest="libm" -avutil_suggest="clock_gettime ffnvcodec libm libdrm libmfx opencl user32 vaapi videotoolbox corefoundation corevideo coremedia wincrypt" +avutil_suggest="clock_gettime ffnvcodec libm libdrm libmfx opencl user32 vaapi videotoolbox corefoundation corevideo coremedia bcrypt" postproc_deps="avutil gpl" postproc_suggest="libm" swresample_deps="avutil" @@ -5828,9 +5828,9 @@ check_header asm/types.h check_builtin stdatomic stdatomic.h "atomic_int foo, bar = ATOMIC_VAR_INIT(-1); atomic_store(&foo, 0); foo += bar" check_lib advapi32 "windows.h" RegCloseKey -ladvapi32 +check_lib bcrypt "windows.h bcrypt.h" BCryptGenRandom -lbcrypt check_lib ole32 "windows.h" CoTaskMemFree -lole32 check_lib shell32 "windows.h shellapi.h" CommandLineToArgvW -lshell32 -check_lib wincrypt "windows.h wincrypt.h" CryptGenRandom -ladvapi32 check_lib psapi "windows.h psapi.h" GetProcessMemoryInfo -lpsapi check_lib android android/native_window.h ANativeWindow_acquire -landroid diff --git a/libavutil/random_seed.c b/libavutil/random_seed.c index 881c23c8c81c2..70dc509d2fde6 100644 --- a/libavutil/random_seed.c +++ b/libavutil/random_seed.c @@ -26,9 +26,9 @@ #if HAVE_IO_H #include #endif -#if HAVE_WINCRYPT +#if HAVE_BCRYPT #include -#include +#include #endif #include #include @@ -121,13 +121,14 @@ uint32_t av_get_random_seed(void) { uint32_t seed; -#if HAVE_WINCRYPT - HCRYPTPROV provider; - if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { - BOOL ret = CryptGenRandom(provider, sizeof(seed), (PBYTE) &seed); - CryptReleaseContext(provider, 0); - if (ret) +#if HAVE_BCRYPT + BCRYPT_ALG_HANDLE algo_handle; + NTSTATUS ret = BCryptOpenAlgorithmProvider(&algo_handle, BCRYPT_RNG_ALGORITHM, + MS_PRIMITIVE_PROVIDER, 0); + if (BCRYPT_SUCCESS(ret)) { + NTSTATUS ret = BCryptGenRandom(algo_handle, (UCHAR*)&seed, sizeof(seed), 0); + BCryptCloseAlgorithmProvider(algo_handle, 0); + if (BCRYPT_SUCCESS(ret)) return seed; } #endif From 250792be5e905cbcfd0b4858e57de9b007e74e44 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 5 Apr 2018 16:44:28 +0200 Subject: [PATCH 2465/2557] avcodec/dxv: add support for "high" quality mode Signed-off-by: Paul B Mahol --- libavcodec/dxv.c | 815 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 780 insertions(+), 35 deletions(-) diff --git a/libavcodec/dxv.c b/libavcodec/dxv.c index 529e2112589e3..08aca73b1fd8b 100644 --- a/libavcodec/dxv.c +++ b/libavcodec/dxv.c @@ -1,6 +1,7 @@ /* * Resolume DXV decoder * Copyright (C) 2015 Vittorio Giovara + * Copyright (C) 2018 Paul B Mahol * * This file is part of FFmpeg. * @@ -23,6 +24,7 @@ #include "libavutil/imgutils.h" +#include "mathops.h" #include "avcodec.h" #include "bytestream.h" #include "internal.h" @@ -34,50 +36,211 @@ typedef struct DXVContext { TextureDSPContext texdsp; GetByteContext gbc; - uint8_t *tex_data; // Compressed texture - int tex_rat; // Compression ratio - int tex_step; // Distance between blocks - int64_t tex_size; // Texture size + uint8_t *tex_data; // Compressed texture + uint8_t *ctex_data; // Compressed texture + int tex_rat; // Compression ratio + int tex_step; // Distance between blocks + int ctex_step; // Distance between blocks + int64_t tex_size; // Texture size + int64_t ctex_size; // Texture size /* Optimal number of slices for parallel decoding */ int slice_count; + uint8_t *op_data[4]; // Opcodes + int64_t op_size[4]; // Opcodes size + + int texture_block_w; + int texture_block_h; + + int ctexture_block_w; + int ctexture_block_h; + /* Pointer to the selected decompression function */ int (*tex_funct)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + int (*tex_funct_planar[2])(uint8_t *plane0, ptrdiff_t stride0, + uint8_t *plane1, ptrdiff_t stride1, + const uint8_t *block); } DXVContext; +static void decompress_indices(uint8_t *dst, const uint8_t *src) +{ + int block, i; + + for (block = 0; block < 2; block++) { + int tmp = AV_RL24(src); + + /* Unpack 8x3 bit from last 3 byte block */ + for (i = 0; i < 8; i++) + dst[i] = (tmp >> (i * 3)) & 0x7; + + src += 3; + dst += 8; + } +} + +static int extract_component(int yo0, int yo1, int code) +{ + int yo; + + if (yo0 == yo1) { + yo = yo0; + } else if (code == 0) { + yo = yo0; + } else if (code == 1) { + yo = yo1; + } else { + if (yo0 > yo1) { + yo = (uint8_t) (((8 - code) * yo0 + + (code - 1) * yo1) / 7); + } else { + if (code == 6) { + yo = 0; + } else if (code == 7) { + yo = 255; + } else { + yo = (uint8_t) (((6 - code) * yo0 + + (code - 1) * yo1) / 5); + } + } + } + + return yo; +} + +static int cocg_block(uint8_t *plane0, ptrdiff_t stride0, + uint8_t *plane1, ptrdiff_t stride1, + const uint8_t *block) +{ + uint8_t co_indices[16]; + uint8_t cg_indices[16]; + uint8_t co0 = *(block); + uint8_t co1 = *(block + 1); + uint8_t cg0 = *(block + 8); + uint8_t cg1 = *(block + 9); + int x, y; + + decompress_indices(co_indices, block + 2); + decompress_indices(cg_indices, block + 10); + + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + int co_code = co_indices[x + y * 4]; + int cg_code = cg_indices[x + y * 4]; + + plane0[x] = extract_component(cg0, cg1, cg_code); + plane1[x] = extract_component(co0, co1, co_code); + } + plane0 += stride0; + plane1 += stride1; + } + + return 16; +} + +static void yao_subblock(uint8_t *dst, uint8_t *yo_indices, + ptrdiff_t stride, const uint8_t *block) +{ + uint8_t yo0 = *(block); + uint8_t yo1 = *(block + 1); + int x, y; + + decompress_indices(yo_indices, block + 2); + + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + int yo_code = yo_indices[x + y * 4]; + + dst[x] = extract_component(yo0, yo1, yo_code); + } + dst += stride; + } +} + +static int yo_block(uint8_t *dst, ptrdiff_t stride, + uint8_t *unused0, ptrdiff_t unused1, + const uint8_t *block) +{ + uint8_t yo_indices[16]; + + yao_subblock(dst, yo_indices, stride, block); + yao_subblock(dst + 4, yo_indices, stride, block + 8); + yao_subblock(dst + 8, yo_indices, stride, block + 16); + yao_subblock(dst + 12, yo_indices, stride, block + 24); + + return 32; +} + +static int yao_block(uint8_t *plane0, ptrdiff_t stride0, + uint8_t *plane3, ptrdiff_t stride1, + const uint8_t *block) +{ + uint8_t yo_indices[16]; + uint8_t a_indices[16]; + + yao_subblock(plane0, yo_indices, stride0, block); + yao_subblock(plane3, a_indices, stride1, block + 8); + yao_subblock(plane0 + 4, yo_indices, stride0, block + 16); + yao_subblock(plane3 + 4, a_indices, stride1, block + 24); + yao_subblock(plane0 + 8, yo_indices, stride0, block + 32); + yao_subblock(plane3 + 8, a_indices, stride1, block + 40); + yao_subblock(plane0 + 12, yo_indices, stride0, block + 48); + yao_subblock(plane3 + 12, a_indices, stride1, block + 56); + + return 64; +} + static int decompress_texture_thread(AVCodecContext *avctx, void *arg, int slice, int thread_nb) { DXVContext *ctx = avctx->priv_data; AVFrame *frame = arg; const uint8_t *d = ctx->tex_data; - int w_block = avctx->coded_width / TEXTURE_BLOCK_W; - int h_block = avctx->coded_height / TEXTURE_BLOCK_H; + int w_block = avctx->coded_width / ctx->texture_block_w; + int h_block = avctx->coded_height / ctx->texture_block_h; int x, y; int start_slice, end_slice; - int base_blocks_per_slice = h_block / ctx->slice_count; - int remainder_blocks = h_block % ctx->slice_count; - - /* When the frame height (in blocks) doesn't divide evenly between the - * number of slices, spread the remaining blocks evenly between the first - * operations */ - start_slice = slice * base_blocks_per_slice; - /* Add any extra blocks (one per slice) that have been added - * before this slice */ - start_slice += FFMIN(slice, remainder_blocks); - - end_slice = start_slice + base_blocks_per_slice; - /* Add an extra block if there are remainder blocks to be accounted for */ - if (slice < remainder_blocks) - end_slice++; - - for (y = start_slice; y < end_slice; y++) { - uint8_t *p = frame->data[0] + y * frame->linesize[0] * TEXTURE_BLOCK_H; - int off = y * w_block; - for (x = 0; x < w_block; x++) { - ctx->tex_funct(p + x * 16, frame->linesize[0], - d + (off + x) * ctx->tex_step); + + start_slice = h_block * slice / ctx->slice_count; + end_slice = h_block * (slice + 1) / ctx->slice_count; + + if (ctx->tex_funct) { + for (y = start_slice; y < end_slice; y++) { + uint8_t *p = frame->data[0] + y * frame->linesize[0] * ctx->texture_block_h; + int off = y * w_block; + for (x = 0; x < w_block; x++) { + ctx->tex_funct(p + x * 4 * ctx->texture_block_w, frame->linesize[0], + d + (off + x) * ctx->tex_step); + } + } + } else { + const uint8_t *c = ctx->ctex_data; + + for (y = start_slice; y < end_slice; y++) { + uint8_t *p0 = frame->data[0] + y * frame->linesize[0] * ctx->texture_block_h; + uint8_t *p3 = ctx->tex_step != 64 ? NULL : frame->data[3] + y * frame->linesize[3] * ctx->texture_block_h; + int off = y * w_block; + for (x = 0; x < w_block; x++) { + ctx->tex_funct_planar[0](p0 + x * ctx->texture_block_w, frame->linesize[0], + p3 != NULL ? p3 + x * ctx->texture_block_w : NULL, frame->linesize[3], + d + (off + x) * ctx->tex_step); + } + } + + w_block = (avctx->coded_width / 2) / ctx->ctexture_block_w; + h_block = (avctx->coded_height / 2) / ctx->ctexture_block_h; + start_slice = h_block * slice / ctx->slice_count; + end_slice = h_block * (slice + 1) / ctx->slice_count; + + for (y = start_slice; y < end_slice; y++) { + uint8_t *p0 = frame->data[1] + y * frame->linesize[1] * ctx->ctexture_block_h; + uint8_t *p1 = frame->data[2] + y * frame->linesize[2] * ctx->ctexture_block_h; + int off = y * w_block; + for (x = 0; x < w_block; x++) { + ctx->tex_funct_planar[1](p0 + x * ctx->ctexture_block_w, frame->linesize[1], + p1 + x * ctx->ctexture_block_w, frame->linesize[2], + c + (off + x) * ctx->ctex_step); + } } } @@ -169,6 +332,529 @@ static int dxv_decompress_dxt1(AVCodecContext *avctx) return 0; } +typedef struct OpcodeTable { + int16_t next; + uint8_t val1; + uint8_t val2; +} OpcodeTable; + +static int fill_ltable(GetByteContext *gb, uint32_t *table, int *nb_elements) +{ + unsigned half = 512, bits = 1023, left = 1024, input, mask; + int value, counter = 0, rshift = 10, lshift = 30; + + mask = bytestream2_get_le32(gb) >> 2; + while (left) { + if (counter >= 256) + return AVERROR_INVALIDDATA; + value = bits & mask; + left -= bits & mask; + mask >>= rshift; + lshift -= rshift; + table[counter++] = value; + if (lshift < 16) { + if (bytestream2_get_bytes_left(gb) <= 0) + return AVERROR_INVALIDDATA; + + input = bytestream2_get_le16(gb); + mask += input << lshift; + lshift += 16; + } + if (left < half) { + half >>= 1; + bits >>= 1; + rshift--; + } + } + + for (; !table[counter - 1]; counter--) + if (counter <= 0) + return AVERROR_INVALIDDATA; + + *nb_elements = counter; + + if (counter < 256) + memset(&table[counter], 0, 4 * (256 - counter)); + + if (lshift >= 16) + bytestream2_seek(gb, -2, SEEK_CUR); + + return 0; +} + +static int fill_optable(unsigned *table0, OpcodeTable *table1, int nb_elements) +{ + unsigned table2[256] = { 0 }; + unsigned x = 0; + int val0, val1, i, j = 2, k = 0; + + table2[0] = table0[0]; + for (i = 0; i < nb_elements - 1; i++, table2[i] = val0) { + val0 = table0[i + 1] + table2[i]; + } + + if (!table2[0]) { + do { + k++; + } while (!table2[k]); + } + + j = 2; + for (i = 1024; i > 0; i--) { + for (table1[x].val1 = k; k < 256 && j > table2[k]; k++); + x = (x - 383) & 0x3FF; + j++; + } + + if (nb_elements > 0) + memcpy(&table2[0], table0, 4 * nb_elements); + + for (i = 0; i < 1024; i++) { + val0 = table1[i].val1; + val1 = table2[val0]; + table2[val0]++; + x = 31 - ff_clz(val1); + if (x > 10) + return AVERROR_INVALIDDATA; + table1[i].val2 = 10 - x; + table1[i].next = (val1 << table1[i].val2) - 1024; + } + + return 0; +} + +static int get_opcodes(GetByteContext *gb, uint32_t *table, uint8_t *dst, int op_size, int nb_elements) +{ + OpcodeTable optable[1024]; + int sum, x, val, lshift, rshift, ret, size_in_bits, i, idx; + unsigned endoffset, newoffset, offset; + unsigned next; + uint8_t *src = (uint8_t *)gb->buffer; + + ret = fill_optable(table, optable, nb_elements); + if (ret < 0) + return ret; + + size_in_bits = bytestream2_get_le32(gb); + endoffset = ((size_in_bits + 7) >> 3) - 4; + if (endoffset <= 0 || bytestream2_get_bytes_left(gb) < endoffset) + return AVERROR_INVALIDDATA; + + offset = endoffset; + next = AV_RL32(src + endoffset); + rshift = (((size_in_bits & 0xFF) - 1) & 7) + 15; + lshift = 32 - rshift; + idx = (next >> rshift) & 0x3FF; + for (i = 0; i < op_size; i++) { + dst[i] = optable[idx].val1; + val = optable[idx].val2; + sum = val + lshift; + x = (next << lshift) >> 1 >> (31 - val); + newoffset = offset - (sum >> 3); + lshift = sum & 7; + idx = x + optable[idx].next; + offset = newoffset; + if (offset > endoffset) + return AVERROR_INVALIDDATA; + next = AV_RL32(src + offset); + } + + bytestream2_skip(gb, (size_in_bits + 7 >> 3) - 4); + + return 0; +} + +static int dxv_decompress_opcodes(GetByteContext *gb, void *dstp, size_t op_size) +{ + int pos = bytestream2_tell(gb); + int flag = bytestream2_peek_byte(gb); + + if ((flag & 3) == 0) { + bytestream2_skip(gb, 1); + bytestream2_get_buffer(gb, dstp, op_size); + } else if ((flag & 3) == 1) { + bytestream2_skip(gb, 1); + memset(dstp, bytestream2_get_byte(gb), op_size); + } else { + uint32_t table[256]; + int ret, elements = 0; + + ret = fill_ltable(gb, table, &elements); + if (ret < 0) + return ret; + ret = get_opcodes(gb, table, dstp, op_size, elements); + if (ret < 0) + return ret; + } + return bytestream2_tell(gb) - pos; +} + +static int dxv_decompress_cgo(DXVContext *ctx, GetByteContext *gb, + uint8_t *tex_data, int tex_size, + uint8_t *op_data, int *oindex, + int op_size, + uint8_t **dstp, int *statep, + uint8_t **tab0, uint8_t **tab1, + int offset) +{ + uint8_t *dst = *dstp; + uint8_t *tptr0, *tptr1, *tptr3; + int oi = *oindex; + int state = *statep; + int opcode, v, vv; + + if (state <= 0) { + if (oi >= op_size) + return AVERROR_INVALIDDATA; + opcode = op_data[oi++]; + if (!opcode) { + v = bytestream2_get_byte(gb); + if (v == 255) { + do { + if (bytestream2_get_bytes_left(gb) <= 0) + return AVERROR_INVALIDDATA; + opcode = bytestream2_get_le16(gb); + v += opcode; + } while (opcode == 0xFFFF); + } + AV_WL32(dst, AV_RL32(dst - (8 + offset))); + AV_WL32(dst + 4, AV_RL32(dst - (4 + offset))); + state = v + 4; + goto done; + } + + switch (opcode) { + case 1: + AV_WL32(dst, AV_RL32(dst - (8 + offset))); + AV_WL32(dst + 4, AV_RL32(dst - (4 + offset))); + break; + case 2: + vv = (8 + offset) * (bytestream2_get_le16(gb) + 1); + if (vv < 0 || vv > dst - tex_data) + return AVERROR_INVALIDDATA; + tptr0 = dst - vv; + v = AV_RL32(tptr0); + AV_WL32(dst, AV_RL32(tptr0)); + AV_WL32(dst + 4, AV_RL32(tptr0 + 4)); + tab0[0x9E3779B1 * (uint16_t)v >> 24] = dst; + tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2; + break; + case 3: + AV_WL32(dst, bytestream2_get_le32(gb)); + AV_WL32(dst + 4, bytestream2_get_le32(gb)); + tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst; + tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2; + break; + case 4: + tptr3 = tab1[bytestream2_get_byte(gb)]; + if (!tptr3) + return AVERROR_INVALIDDATA; + AV_WL16(dst, bytestream2_get_le16(gb)); + AV_WL16(dst + 2, AV_RL16(tptr3)); + dst[4] = tptr3[2]; + AV_WL16(dst + 5, bytestream2_get_le16(gb)); + dst[7] = bytestream2_get_byte(gb); + tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst; + break; + case 5: + tptr3 = tab1[bytestream2_get_byte(gb)]; + if (!tptr3) + return AVERROR_INVALIDDATA; + AV_WL16(dst, bytestream2_get_le16(gb)); + AV_WL16(dst + 2, bytestream2_get_le16(gb)); + dst[4] = bytestream2_get_byte(gb); + AV_WL16(dst + 5, AV_RL16(tptr3)); + dst[7] = tptr3[2]; + tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst; + tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2; + break; + case 6: + tptr0 = tab1[bytestream2_get_byte(gb)]; + if (!tptr0) + return AVERROR_INVALIDDATA; + tptr1 = tab1[bytestream2_get_byte(gb)]; + if (!tptr1) + return AVERROR_INVALIDDATA; + AV_WL16(dst, bytestream2_get_le16(gb)); + AV_WL16(dst + 2, AV_RL16(tptr0)); + dst[4] = tptr0[2]; + AV_WL16(dst + 5, AV_RL16(tptr1)); + dst[7] = tptr1[2]; + tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst; + break; + case 7: + v = (8 + offset) * (bytestream2_get_le16(gb) + 1); + if (v < 0 || v > dst - tex_data) + return AVERROR_INVALIDDATA; + tptr0 = dst - v; + AV_WL16(dst, bytestream2_get_le16(gb)); + AV_WL16(dst + 2, AV_RL16(tptr0 + 2)); + AV_WL32(dst + 4, AV_RL32(tptr0 + 4)); + tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst; + tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2; + break; + case 8: + tptr1 = tab0[bytestream2_get_byte(gb)]; + if (!tptr1) + return AVERROR_INVALIDDATA; + AV_WL16(dst, AV_RL16(tptr1)); + AV_WL16(dst + 2, bytestream2_get_le16(gb)); + AV_WL32(dst + 4, bytestream2_get_le32(gb)); + tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2; + break; + case 9: + tptr1 = tab0[bytestream2_get_byte(gb)]; + if (!tptr1) + return AVERROR_INVALIDDATA; + tptr3 = tab1[bytestream2_get_byte(gb)]; + if (!tptr3) + return AVERROR_INVALIDDATA; + AV_WL16(dst, AV_RL16(tptr1)); + AV_WL16(dst + 2, AV_RL16(tptr3)); + dst[4] = tptr3[2]; + AV_WL16(dst + 5, bytestream2_get_le16(gb)); + dst[7] = bytestream2_get_byte(gb); + tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2; + break; + case 10: + tptr1 = tab0[bytestream2_get_byte(gb)]; + if (!tptr1) + return AVERROR_INVALIDDATA; + tptr3 = tab1[bytestream2_get_byte(gb)]; + if (!tptr3) + return AVERROR_INVALIDDATA; + AV_WL16(dst, AV_RL16(tptr1)); + AV_WL16(dst + 2, bytestream2_get_le16(gb)); + dst[4] = bytestream2_get_byte(gb); + AV_WL16(dst + 5, AV_RL16(tptr3)); + dst[7] = tptr3[2]; + tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2; + break; + case 11: + tptr0 = tab0[bytestream2_get_byte(gb)]; + if (!tptr0) + return AVERROR_INVALIDDATA; + tptr3 = tab1[bytestream2_get_byte(gb)]; + if (!tptr3) + return AVERROR_INVALIDDATA; + tptr1 = tab1[bytestream2_get_byte(gb)]; + if (!tptr1) + return AVERROR_INVALIDDATA; + AV_WL16(dst, AV_RL16(tptr0)); + AV_WL16(dst + 2, AV_RL16(tptr3)); + dst[4] = tptr3[2]; + AV_WL16(dst + 5, AV_RL16(tptr1)); + dst[7] = tptr1[2]; + break; + case 12: + tptr1 = tab0[bytestream2_get_byte(gb)]; + if (!tptr1) + return AVERROR_INVALIDDATA; + v = (8 + offset) * (bytestream2_get_le16(gb) + 1); + if (v < 0 || v > dst - tex_data) + return AVERROR_INVALIDDATA; + tptr0 = dst - v; + AV_WL16(dst, AV_RL16(tptr1)); + AV_WL16(dst + 2, AV_RL16(tptr0 + 2)); + AV_WL32(dst + 4, AV_RL32(tptr0 + 4)); + tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2; + break; + case 13: + AV_WL16(dst, AV_RL16(dst - (8 + offset))); + AV_WL16(dst + 2, bytestream2_get_le16(gb)); + AV_WL32(dst + 4, bytestream2_get_le32(gb)); + tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2; + break; + case 14: + tptr3 = tab1[bytestream2_get_byte(gb)]; + if (!tptr3) + return AVERROR_INVALIDDATA; + AV_WL16(dst, AV_RL16(dst - (8 + offset))); + AV_WL16(dst + 2, AV_RL16(tptr3)); + dst[4] = tptr3[2]; + AV_WL16(dst + 5, bytestream2_get_le16(gb)); + dst[7] = bytestream2_get_byte(gb); + tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2; + break; + case 15: + tptr3 = tab1[bytestream2_get_byte(gb)]; + if (!tptr3) + return AVERROR_INVALIDDATA; + AV_WL16(dst, AV_RL16(dst - (8 + offset))); + AV_WL16(dst + 2, bytestream2_get_le16(gb)); + dst[4] = bytestream2_get_byte(gb); + AV_WL16(dst + 5, AV_RL16(tptr3)); + dst[7] = tptr3[2]; + tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2; + break; + case 16: + tptr3 = tab1[bytestream2_get_byte(gb)]; + if (!tptr3) + return AVERROR_INVALIDDATA; + tptr1 = tab1[bytestream2_get_byte(gb)]; + if (!tptr1) + return AVERROR_INVALIDDATA; + AV_WL16(dst, AV_RL16(dst - (8 + offset))); + AV_WL16(dst + 2, AV_RL16(tptr3)); + dst[4] = tptr3[2]; + AV_WL16(dst + 5, AV_RL16(tptr1)); + dst[7] = tptr1[2]; + break; + case 17: + v = (8 + offset) * (bytestream2_get_le16(gb) + 1); + if (v < 0 || v > dst - tex_data) + return AVERROR_INVALIDDATA; + AV_WL16(dst, AV_RL16(dst - (8 + offset))); + AV_WL16(dst + 2, AV_RL16(&dst[-v + 2])); + AV_WL32(dst + 4, AV_RL32(&dst[-v + 4])); + tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFFu) >> 24] = dst + 2; + break; + default: + break; + } + } else { +done: + AV_WL32(dst, AV_RL32(dst - (8 + offset))); + AV_WL32(dst + 4, AV_RL32(dst - (4 + offset))); + state--; + } + if (dst - tex_data + 8 > tex_size) + return AVERROR_INVALIDDATA; + dst += 8; + + *oindex = oi; + *dstp = dst; + *statep = state; + + return 0; +} + +static int dxv_decompress_cocg(DXVContext *ctx, GetByteContext *gb, + uint8_t *tex_data, int tex_size, + uint8_t *op_data0, uint8_t *op_data1, + int max_op_size0, int max_op_size1) +{ + uint8_t *dst, *tab2[256] = { 0 }, *tab0[256] = { 0 }, *tab3[256] = { 0 }, *tab1[256] = { 0 }; + int op_offset = bytestream2_get_le32(gb); + unsigned op_size0 = bytestream2_get_le32(gb); + unsigned op_size1 = bytestream2_get_le32(gb); + int data_start = bytestream2_tell(gb); + int skip0, skip1, oi0 = 0, oi1 = 0; + int ret, state0 = 0, state1 = 0; + + dst = tex_data; + bytestream2_skip(gb, op_offset - 12); + if (op_size0 > max_op_size0) + return AVERROR_INVALIDDATA; + skip0 = dxv_decompress_opcodes(gb, op_data0, op_size0); + if (skip0 < 0) + return skip0; + bytestream2_seek(gb, data_start + op_offset + skip0 - 12, SEEK_SET); + if (op_size1 > max_op_size1) + return AVERROR_INVALIDDATA; + skip1 = dxv_decompress_opcodes(gb, op_data1, op_size1); + if (skip1 < 0) + return skip1; + bytestream2_seek(gb, data_start, SEEK_SET); + + AV_WL32(dst, bytestream2_get_le32(gb)); + AV_WL32(dst + 4, bytestream2_get_le32(gb)); + AV_WL32(dst + 8, bytestream2_get_le32(gb)); + AV_WL32(dst + 12, bytestream2_get_le32(gb)); + + tab0[0x9E3779B1 * AV_RL16(dst) >> 24] = dst; + tab1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFF) >> 24] = dst + 2; + tab2[0x9E3779B1 * AV_RL16(dst + 8) >> 24] = dst + 8; + tab3[0x9E3779B1 * (AV_RL32(dst + 10) & 0xFFFFFF) >> 24] = dst + 10; + dst += 16; + while (dst + 10 < tex_data + tex_size) { + ret = dxv_decompress_cgo(ctx, gb, tex_data, tex_size, op_data0, &oi0, op_size0, + &dst, &state0, tab0, tab1, 8); + if (ret < 0) + return ret; + ret = dxv_decompress_cgo(ctx, gb, tex_data, tex_size, op_data1, &oi1, op_size1, + &dst, &state1, tab2, tab3, 8); + if (ret < 0) + return ret; + } + + bytestream2_seek(gb, data_start + op_offset + skip0 + skip1 - 12, SEEK_SET); + + return 0; +} + +static int dxv_decompress_yo(DXVContext *ctx, GetByteContext *gb, + uint8_t *tex_data, int tex_size, + uint8_t *op_data, int max_op_size) +{ + int op_offset = bytestream2_get_le32(gb); + unsigned op_size = bytestream2_get_le32(gb); + int data_start = bytestream2_tell(gb); + uint8_t *dst, *table0[256] = { 0 }, *table1[256] = { 0 }; + int ret, state = 0, skip, oi = 0, v, vv; + + dst = tex_data; + bytestream2_skip(gb, op_offset - 8); + if (op_size > max_op_size) + return AVERROR_INVALIDDATA; + skip = dxv_decompress_opcodes(gb, op_data, op_size); + if (skip < 0) + return skip; + bytestream2_seek(gb, data_start, SEEK_SET); + + v = bytestream2_get_le32(gb); + AV_WL32(dst, v); + vv = bytestream2_get_le32(gb); + table0[0x9E3779B1 * (uint16_t)v >> 24] = dst; + AV_WL32(dst + 4, vv); + table1[0x9E3779B1 * (AV_RL32(dst + 2) & 0xFFFFFF) >> 24] = dst + 2; + dst += 8; + + while (dst < tex_data + tex_size) { + ret = dxv_decompress_cgo(ctx, gb, tex_data, tex_size, op_data, &oi, op_size, + &dst, &state, table0, table1, 0); + if (ret < 0) + return ret; + } + + bytestream2_seek(gb, data_start + op_offset + skip - 8, SEEK_SET); + + return 0; +} + +static int dxv_decompress_ycg6(AVCodecContext *avctx) +{ + DXVContext *ctx = avctx->priv_data; + GetByteContext *gb = &ctx->gbc; + int ret; + + ret = dxv_decompress_yo(ctx, gb, ctx->tex_data, ctx->tex_size, + ctx->op_data[0], ctx->op_size[0]); + if (ret < 0) + return ret; + + return dxv_decompress_cocg(ctx, gb, ctx->ctex_data, ctx->ctex_size, + ctx->op_data[1], ctx->op_data[2], + ctx->op_size[1], ctx->op_size[2]); +} + +static int dxv_decompress_yg10(AVCodecContext *avctx) +{ + DXVContext *ctx = avctx->priv_data; + GetByteContext *gb = &ctx->gbc; + int ret; + + ret = dxv_decompress_cocg(ctx, gb, ctx->tex_data, ctx->tex_size, + ctx->op_data[0], ctx->op_data[3], + ctx->op_size[0], ctx->op_size[3]); + if (ret < 0) + return ret; + + return dxv_decompress_cocg(ctx, gb, ctx->ctex_data, ctx->ctex_size, + ctx->op_data[1], ctx->op_data[2], + ctx->op_size[1], ctx->op_size[2]); +} + static int dxv_decompress_dxt5(AVCodecContext *avctx) { DXVContext *ctx = avctx->priv_data; @@ -359,6 +1045,12 @@ static int dxv_decode(AVCodecContext *avctx, void *data, bytestream2_init(gbc, avpkt->data, avpkt->size); + ctx->texture_block_h = 4; + ctx->texture_block_w = 4; + + avctx->pix_fmt = AV_PIX_FMT_RGBA; + avctx->colorspace = AVCOL_SPC_RGB; + tag = bytestream2_get_le32(gbc); switch (tag) { case MKBETAG('D', 'X', 'T', '1'): @@ -378,9 +1070,39 @@ static int dxv_decode(AVCodecContext *avctx, void *data, msgtext = "DXT5"; break; case MKBETAG('Y', 'C', 'G', '6'): + decompress_tex = dxv_decompress_ycg6; + ctx->tex_funct_planar[0] = yo_block; + ctx->tex_funct_planar[1] = cocg_block; + ctx->tex_rat = 8; + ctx->tex_step = 32; + ctx->ctex_step = 16; + msgcomp = "YOCOCG6"; + msgtext = "YCG6"; + ctx->ctex_size = avctx->coded_width * avctx->coded_height / 4; + ctx->texture_block_h = 4; + ctx->texture_block_w = 16; + ctx->ctexture_block_h = 4; + ctx->ctexture_block_w = 4; + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + avctx->colorspace = AVCOL_SPC_YCOCG; + break; case MKBETAG('Y', 'G', '1', '0'): - avpriv_report_missing_feature(avctx, "Tag 0x%08"PRIX32, tag); - return AVERROR_PATCHWELCOME; + decompress_tex = dxv_decompress_yg10; + ctx->tex_funct_planar[0] = yao_block; + ctx->tex_funct_planar[1] = cocg_block; + ctx->tex_rat = 4; + ctx->tex_step = 64; + ctx->ctex_step = 16; + msgcomp = "YAOCOCG10"; + msgtext = "YG10"; + ctx->ctex_size = avctx->coded_width * avctx->coded_height / 4; + ctx->texture_block_h = 4; + ctx->texture_block_w = 16; + ctx->ctexture_block_h = 4; + ctx->ctexture_block_w = 4; + avctx->pix_fmt = AV_PIX_FMT_YUVA420P; + avctx->colorspace = AVCOL_SPC_YCOCG; + break; default: /* Old version does not have a real header, just size and type. */ size = tag & 0x00FFFFFF; @@ -413,6 +1135,10 @@ static int dxv_decode(AVCodecContext *avctx, void *data, break; } + ctx->slice_count = av_clip(avctx->thread_count, 1, + avctx->coded_height / FFMAX(ctx->texture_block_h, + ctx->ctexture_block_h)); + /* New header is 12 bytes long. */ if (!old_type) { version_major = bytestream2_get_byte(gbc) - 1; @@ -440,10 +1166,28 @@ static int dxv_decode(AVCodecContext *avctx, void *data, } ctx->tex_size = avctx->coded_width * avctx->coded_height * 4 / ctx->tex_rat; - ret = av_reallocp(&ctx->tex_data, ctx->tex_size); + ret = av_reallocp(&ctx->tex_data, ctx->tex_size + AV_INPUT_BUFFER_PADDING_SIZE); if (ret < 0) return ret; + if (ctx->ctex_size) { + int i; + + ctx->op_size[0] = avctx->coded_width * avctx->coded_height / 16; + ctx->op_size[1] = avctx->coded_width * avctx->coded_height / 32; + ctx->op_size[2] = avctx->coded_width * avctx->coded_height / 32; + ctx->op_size[3] = avctx->coded_width * avctx->coded_height / 16; + + ret = av_reallocp(&ctx->ctex_data, ctx->ctex_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (ret < 0) + return ret; + for (i = 0; i < 4; i++) { + ret = av_reallocp(&ctx->op_data[i], ctx->op_size[i]); + if (ret < 0) + return ret; + } + } + /* Decompress texture out of the intermediate compression. */ ret = decompress_tex(avctx); if (ret < 0) @@ -482,10 +1226,6 @@ static int dxv_init(AVCodecContext *avctx) avctx->coded_height = FFALIGN(avctx->height, 16); ff_texturedsp_init(&ctx->texdsp); - avctx->pix_fmt = AV_PIX_FMT_RGBA; - - ctx->slice_count = av_clip(avctx->thread_count, 1, - avctx->coded_height / TEXTURE_BLOCK_H); return 0; } @@ -495,6 +1235,11 @@ static int dxv_close(AVCodecContext *avctx) DXVContext *ctx = avctx->priv_data; av_freep(&ctx->tex_data); + av_freep(&ctx->ctex_data); + av_freep(&ctx->op_data[0]); + av_freep(&ctx->op_data[1]); + av_freep(&ctx->op_data[2]); + av_freep(&ctx->op_data[3]); return 0; } From 8df8a9299364016027825a67534b93cd2b6af473 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 5 Apr 2018 17:09:35 +0200 Subject: [PATCH 2466/2557] avcodec/aac_ac3_parser: account for data already in the parsing buffer If a frame starts very close to a packet boundary, the start code may already have been added to the parsing buffer, indicated by a small negative value of "i", while the header is still being tracked in the "state" variable. Reduce the remaining size accordingly, otherwise trying to find the next frame could skip over the frame header and lump two frames together as one. --- libavcodec/aac_ac3_parser.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/aac_ac3_parser.c b/libavcodec/aac_ac3_parser.c index 019074b0dd43a..54e459844f141 100644 --- a/libavcodec/aac_ac3_parser.c +++ b/libavcodec/aac_ac3_parser.c @@ -60,6 +60,9 @@ int ff_aac_ac3_parse(AVCodecParserContext *s1, s->remaining_size += i; goto get_next; } + else if (i < 0) { + s->remaining_size += i; + } } } } From 955fa237f495e3077996c1d282b4ace2a9ad6c15 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Fri, 13 Apr 2018 19:39:24 +0200 Subject: [PATCH 2467/2557] avcodec/nvdec: correctly set intra_pic_flag for h264/hevc --- libavcodec/nvdec_h264.c | 8 +++++++- libavcodec/nvdec_hevc.c | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libavcodec/nvdec_h264.c b/libavcodec/nvdec_h264.c index 35f54f2ed5f2a..25b30329d0eff 100644 --- a/libavcodec/nvdec_h264.c +++ b/libavcodec/nvdec_h264.c @@ -74,7 +74,7 @@ static int nvdec_h264_start_frame(AVCodecContext *avctx, .bottom_field_flag = h->picture_structure == PICT_BOTTOM_FIELD, .second_field = FIELD_PICTURE(h) && !h->first_field, .ref_pic_flag = h->nal_ref_idc != 0, - .intra_pic_flag = 0, + .intra_pic_flag = 1, .CodecSpecific.h264 = { .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4, @@ -132,6 +132,9 @@ static int nvdec_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + CUVIDPICPARAMS *pp = &ctx->pic_params; + const H264Context *h = avctx->priv_data; + const H264SliceContext *sl = &h->slice_ctx[0]; void *tmp; tmp = av_fast_realloc(ctx->bitstream, &ctx->bitstream_allocated, @@ -152,6 +155,9 @@ static int nvdec_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, ctx->bitstream_len += size + 3; ctx->nb_slices++; + if (sl->slice_type != AV_PICTURE_TYPE_I && sl->slice_type != AV_PICTURE_TYPE_SI) + pp->intra_pic_flag = 0; + return 0; } diff --git a/libavcodec/nvdec_hevc.c b/libavcodec/nvdec_hevc.c index e89256d75a911..008963130b018 100644 --- a/libavcodec/nvdec_hevc.c +++ b/libavcodec/nvdec_hevc.c @@ -93,7 +93,7 @@ static int nvdec_hevc_start_frame(AVCodecContext *avctx, .FrameHeightInMbs = sps->height / 16, .CurrPicIdx = cf->idx, .ref_pic_flag = 1, - .intra_pic_flag = 0, + .intra_pic_flag = IS_IRAP(s), .CodecSpecific.hevc = { .pic_width_in_luma_samples = sps->width, From 3e003a985f4b07d8685a2f251f5090f11abdfc06 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 15 Apr 2018 12:48:12 +0200 Subject: [PATCH 2468/2557] avfilter/af_headphone: add single hrir multichannel stream mode Signed-off-by: Paul B Mahol --- doc/filters.texi | 19 ++++ libavfilter/af_headphone.c | 185 ++++++++++++++++++++++++++----------- 2 files changed, 150 insertions(+), 54 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 18a6da155c9a6..40083dd080623 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -3179,6 +3179,17 @@ Set custom gain for LFE channels. Value is in dB. Default is 0. @item size Set size of frame in number of samples which will be processed at once. Default value is @var{1024}. Allowed range is from 1024 to 96000. + +@item hrir +Set format of hrir stream. +Default value is @var{stereo}. Alternative value is @var{multich}. +If value is set to @var{stereo}, number of additional streams should +be greater or equal to number of input channels in first input stream. +Also each additional stream should have stereo number of channels. +If value is set to @var{multich}, number of additional streams should +be exactly one. Also number of input channels of additional stream +should be equal or greater than twice number of channels of first input +stream. @end table @subsection Examples @@ -3192,6 +3203,14 @@ The files give coefficients for each position of virtual loudspeaker: ffmpeg -i input.wav -lavfi-complex "amovie=azi_270_ele_0_DFC.wav[sr],amovie=azi_90_ele_0_DFC.wav[sl],amovie=azi_225_ele_0_DFC.wav[br],amovie=azi_135_ele_0_DFC.wav[bl],amovie=azi_0_ele_0_DFC.wav,asplit[fc][lfe],amovie=azi_35_ele_0_DFC.wav[fl],amovie=azi_325_ele_0_DFC.wav[fr],[a:0][fl][fr][fc][lfe][bl][br][sl][sr]headphone=FL|FR|FC|LFE|BL|BR|SL|SR" output.wav @end example + +@item +Full example using wav files as coefficients with amovie filters for 7.1 downmix, +but now in @var{multich} @var{hrir} format. +@example +ffmpeg -i input.wav -lavfi-complex "amovie=minp.wav[hrirs],[a:0][hrirs]headphone=map=FL|FR|FC|LFE|BL|BR|SL|SR:hrir=multich" +output.wav +@end example @end itemize @section highpass diff --git a/libavfilter/af_headphone.c b/libavfilter/af_headphone.c index 8b34609a2f3d6..a71ed336d88c0 100644 --- a/libavfilter/af_headphone.c +++ b/libavfilter/af_headphone.c @@ -35,6 +35,9 @@ #define TIME_DOMAIN 0 #define FREQUENCY_DOMAIN 1 +#define HRIR_STEREO 0 +#define HRIR_MULTI 1 + typedef struct HeadphoneContext { const AVClass *class; @@ -64,6 +67,7 @@ typedef struct HeadphoneContext { int buffer_length; int n_fft; int size; + int hrir_fmt; int *delay[2]; float *data_ir[2]; @@ -130,14 +134,18 @@ static void parse_map(AVFilterContext *ctx) char buf[8]; p = NULL; - if (parse_channel_name(s, s->nb_inputs - 1, &arg, &out_ch_id, buf)) { + if (parse_channel_name(s, s->nb_irs, &arg, &out_ch_id, buf)) { av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", buf); continue; } - s->mapping[s->nb_inputs - 1] = out_ch_id; - s->nb_inputs++; + s->mapping[s->nb_irs] = out_ch_id; + s->nb_irs++; } - s->nb_irs = s->nb_inputs - 1; + + if (s->hrir_fmt == HRIR_MULTI) + s->nb_inputs = 2; + else + s->nb_inputs = s->nb_irs + 1; av_free(args); } @@ -402,7 +410,7 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) float *data_ir_r = NULL; int offset = 0, ret = 0; int n_fft; - int i, j; + int i, j, k; s->buffer_length = 1 << (32 - ff_clz(s->ir_len)); s->n_fft = n_fft = 1 << (32 - ff_clz(s->ir_len + s->size)); @@ -433,8 +441,8 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) s->data_ir[0] = av_calloc(FFALIGN(s->ir_len, 16), sizeof(float) * s->nb_irs); s->data_ir[1] = av_calloc(FFALIGN(s->ir_len, 16), sizeof(float) * s->nb_irs); - s->delay[0] = av_malloc_array(s->nb_irs, sizeof(float)); - s->delay[1] = av_malloc_array(s->nb_irs, sizeof(float)); + s->delay[0] = av_calloc(s->nb_irs, sizeof(float)); + s->delay[1] = av_calloc(s->nb_irs, sizeof(float)); if (s->type == TIME_DOMAIN) { s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels); @@ -442,8 +450,8 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) } else { s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float)); s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float)); - s->temp_fft[0] = av_malloc_array(s->n_fft, sizeof(FFTComplex)); - s->temp_fft[1] = av_malloc_array(s->n_fft, sizeof(FFTComplex)); + s->temp_fft[0] = av_calloc(s->n_fft, sizeof(FFTComplex)); + s->temp_fft[1] = av_calloc(s->n_fft, sizeof(FFTComplex)); if (!s->temp_fft[0] || !s->temp_fft[1]) { ret = AVERROR(ENOMEM); goto fail; @@ -461,7 +469,7 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) ret = AVERROR(ENOMEM); goto fail; } - for (i = 0; i < s->nb_irs; i++) { + for (i = 0; i < s->nb_inputs - 1; i++) { s->in[i + 1].frame = ff_get_audio_buffer(ctx->inputs[i + 1], s->ir_len); if (!s->in[i + 1].frame) { ret = AVERROR(ENOMEM); @@ -480,59 +488,106 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) goto fail; } } else { - data_hrtf_l = av_malloc_array(n_fft, sizeof(*data_hrtf_l) * nb_irs); - data_hrtf_r = av_malloc_array(n_fft, sizeof(*data_hrtf_r) * nb_irs); + data_hrtf_l = av_calloc(n_fft, sizeof(*data_hrtf_l) * nb_irs); + data_hrtf_r = av_calloc(n_fft, sizeof(*data_hrtf_r) * nb_irs); if (!data_hrtf_r || !data_hrtf_l) { ret = AVERROR(ENOMEM); goto fail; } } - for (i = 0; i < s->nb_irs; i++) { + for (i = 0; i < s->nb_inputs - 1; i++) { int len = s->in[i + 1].ir_len; int delay_l = s->in[i + 1].delay_l; int delay_r = s->in[i + 1].delay_r; - int idx = -1; float *ptr; - for (j = 0; j < inlink->channels; j++) { - if (s->mapping[i] < 0) { - continue; - } - - if ((av_channel_layout_extract_channel(inlink->channel_layout, j)) == (1LL << s->mapping[i])) { - idx = j; - break; - } - } - if (idx == -1) - continue; - av_audio_fifo_read(s->in[i + 1].fifo, (void **)s->in[i + 1].frame->extended_data, len); ptr = (float *)s->in[i + 1].frame->extended_data[0]; - if (s->type == TIME_DOMAIN) { - offset = idx * FFALIGN(len, 16); - for (j = 0; j < len; j++) { - data_ir_l[offset + j] = ptr[len * 2 - j * 2 - 2] * gain_lin; - data_ir_r[offset + j] = ptr[len * 2 - j * 2 - 1] * gain_lin; - } - } else { - memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l)); - memset(fft_in_r, 0, n_fft * sizeof(*fft_in_r)); + if (s->hrir_fmt == HRIR_STEREO) { + int idx = -1; + + for (j = 0; j < inlink->channels; j++) { + if (s->mapping[i] < 0) { + continue; + } - offset = idx * n_fft; - for (j = 0; j < len; j++) { - fft_in_l[delay_l + j].re = ptr[j * 2 ] * gain_lin; - fft_in_r[delay_r + j].re = ptr[j * 2 + 1] * gain_lin; + if ((av_channel_layout_extract_channel(inlink->channel_layout, j)) == (1LL << s->mapping[i])) { + idx = i; + break; + } } - av_fft_permute(s->fft[0], fft_in_l); - av_fft_calc(s->fft[0], fft_in_l); - memcpy(data_hrtf_l + offset, fft_in_l, n_fft * sizeof(*fft_in_l)); - av_fft_permute(s->fft[0], fft_in_r); - av_fft_calc(s->fft[0], fft_in_r); - memcpy(data_hrtf_r + offset, fft_in_r, n_fft * sizeof(*fft_in_r)); + if (idx == -1) + continue; + if (s->type == TIME_DOMAIN) { + offset = idx * FFALIGN(len, 16); + for (j = 0; j < len; j++) { + data_ir_l[offset + j] = ptr[len * 2 - j * 2 - 2] * gain_lin; + data_ir_r[offset + j] = ptr[len * 2 - j * 2 - 1] * gain_lin; + } + } else { + memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l)); + memset(fft_in_r, 0, n_fft * sizeof(*fft_in_r)); + + offset = idx * n_fft; + for (j = 0; j < len; j++) { + fft_in_l[delay_l + j].re = ptr[j * 2 ] * gain_lin; + fft_in_r[delay_r + j].re = ptr[j * 2 + 1] * gain_lin; + } + + av_fft_permute(s->fft[0], fft_in_l); + av_fft_calc(s->fft[0], fft_in_l); + memcpy(data_hrtf_l + offset, fft_in_l, n_fft * sizeof(*fft_in_l)); + av_fft_permute(s->fft[0], fft_in_r); + av_fft_calc(s->fft[0], fft_in_r); + memcpy(data_hrtf_r + offset, fft_in_r, n_fft * sizeof(*fft_in_r)); + } + } else { + int I, N = ctx->inputs[1]->channels; + + for (k = 0; k < N / 2; k++) { + int idx = -1; + + for (j = 0; j < inlink->channels; j++) { + if (s->mapping[k] < 0) { + continue; + } + + if ((av_channel_layout_extract_channel(inlink->channel_layout, j)) == (1LL << s->mapping[k])) { + idx = k; + break; + } + } + if (idx == -1) + continue; + + I = idx * 2; + if (s->type == TIME_DOMAIN) { + offset = idx * FFALIGN(len, 16); + for (j = 0; j < len; j++) { + data_ir_l[offset + j] = ptr[len * 2 - j * 2 - 2] * gain_lin; + data_ir_r[offset + j] = ptr[len * 2 - j * 2 - 1] * gain_lin; + } + } else { + memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l)); + memset(fft_in_r, 0, n_fft * sizeof(*fft_in_r)); + + offset = idx * n_fft; + for (j = 0; j < len; j++) { + fft_in_l[delay_l + j].re = ptr[j * N + I ] * gain_lin; + fft_in_r[delay_r + j].re = ptr[j * N + I + 1] * gain_lin; + } + + av_fft_permute(s->fft[0], fft_in_l); + av_fft_calc(s->fft[0], fft_in_l); + memcpy(data_hrtf_l + offset, fft_in_l, n_fft * sizeof(*fft_in_l)); + av_fft_permute(s->fft[0], fft_in_r); + av_fft_calc(s->fft[0], fft_in_r); + memcpy(data_hrtf_r + offset, fft_in_r, n_fft * sizeof(*fft_in_r)); + } + } } } @@ -540,8 +595,8 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) memcpy(s->data_ir[0], data_ir_l, sizeof(float) * nb_irs * FFALIGN(ir_len, 16)); memcpy(s->data_ir[1], data_ir_r, sizeof(float) * nb_irs * FFALIGN(ir_len, 16)); } else { - s->data_hrtf[0] = av_malloc_array(n_fft * s->nb_irs, sizeof(FFTComplex)); - s->data_hrtf[1] = av_malloc_array(n_fft * s->nb_irs, sizeof(FFTComplex)); + s->data_hrtf[0] = av_calloc(n_fft * s->nb_irs, sizeof(FFTComplex)); + s->data_hrtf[1] = av_calloc(n_fft * s->nb_irs, sizeof(FFTComplex)); if (!s->data_hrtf[0] || !s->data_hrtf[1]) { ret = AVERROR(ENOMEM); goto fail; @@ -608,6 +663,8 @@ static int query_formats(AVFilterContext *ctx) struct HeadphoneContext *s = ctx->priv; AVFilterFormats *formats = NULL; AVFilterChannelLayouts *layouts = NULL; + AVFilterChannelLayouts *stereo_layout = NULL; + AVFilterChannelLayouts *hrir_layouts = NULL; int ret, i; ret = ff_add_format(&formats, AV_SAMPLE_FMT_FLT); @@ -625,18 +682,26 @@ static int query_formats(AVFilterContext *ctx) if (ret) return ret; - layouts = NULL; - ret = ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO); + ret = ff_add_channel_layout(&stereo_layout, AV_CH_LAYOUT_STEREO); if (ret) return ret; - for (i = 1; i < s->nb_inputs; i++) { - ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->out_channel_layouts); + if (s->hrir_fmt == HRIR_MULTI) { + hrir_layouts = ff_all_channel_counts(); + if (!hrir_layouts) + ret = AVERROR(ENOMEM); + ret = ff_channel_layouts_ref(hrir_layouts, &ctx->inputs[1]->out_channel_layouts); if (ret) return ret; + } else { + for (i = 1; i < s->nb_inputs; i++) { + ret = ff_channel_layouts_ref(stereo_layout, &ctx->inputs[i]->out_channel_layouts); + if (ret) + return ret; + } } - ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts); + ret = ff_channel_layouts_ref(stereo_layout, &ctx->outputs[0]->in_channel_layouts); if (ret) return ret; @@ -652,7 +717,7 @@ static int config_input(AVFilterLink *inlink) HeadphoneContext *s = ctx->priv; if (s->nb_irs < inlink->channels) { - av_log(ctx, AV_LOG_ERROR, "Number of inputs must be >= %d.\n", inlink->channels + 1); + av_log(ctx, AV_LOG_ERROR, "Number of HRIRs must be >= %d.\n", inlink->channels); return AVERROR(EINVAL); } @@ -714,6 +779,15 @@ static int config_output(AVFilterLink *outlink) AVFilterLink *inlink = ctx->inputs[0]; int i; + if (s->hrir_fmt == HRIR_MULTI) { + AVFilterLink *hrir_link = ctx->inputs[1]; + + if (hrir_link->channels < inlink->channels * 2) { + av_log(ctx, AV_LOG_ERROR, "Number of channels in HRIR stream must be >= %d.\n", inlink->channels * 2); + return AVERROR(EINVAL); + } + } + for (i = 0; i < s->nb_inputs; i++) { s->in[i].fifo = av_audio_fifo_alloc(ctx->inputs[i]->format, ctx->inputs[i]->channels, 1024); if (!s->in[i].fifo) @@ -813,6 +887,9 @@ static const AVOption headphone_options[] = { { "time", "time domain", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, .flags = FLAGS, "type" }, { "freq", "frequency domain", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, .flags = FLAGS, "type" }, { "size", "set frame size", OFFSET(size), AV_OPT_TYPE_INT, {.i64=1024},1024,96000, .flags = FLAGS }, + { "hrir", "set hrir format", OFFSET(hrir_fmt), AV_OPT_TYPE_INT, {.i64=HRIR_STEREO}, 0, 1, .flags = FLAGS, "hrir" }, + { "stereo", "hrir files have exactly 2 channels", 0, AV_OPT_TYPE_CONST, {.i64=HRIR_STEREO}, 0, 0, .flags = FLAGS, "hrir" }, + { "multich", "single multichannel hrir file", 0, AV_OPT_TYPE_CONST, {.i64=HRIR_MULTI}, 0, 0, .flags = FLAGS, "hrir" }, { NULL } }; From 9fd11e51882aad9000943a9962d10880cae6667a Mon Sep 17 00:00:00 2001 From: Alexander Bilyak Date: Thu, 1 Feb 2018 11:52:24 +0100 Subject: [PATCH 2469/2557] configure: fix clang-cl detection When using clang-cl it expects parameters passed in MSVC-style, so appropriate toolchain should be selected. As soon as both clang and clang-cl report themselfs as "clang" with -v option the only chance to detect clang-cl is passing -? option to both which is valid for clang-cl.exe and not for clang.exe. Reviewed-by: Dale Curtis Signed-off-by: Michael Niedermayer --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 36e425be62aa9..a6f32f8d9abf2 100755 --- a/configure +++ b/configure @@ -4339,7 +4339,7 @@ probe_cc(){ _depflags='-MMD' _cflags_speed='-O3' _cflags_size='-Os' - elif $_cc -v 2>&1 | grep -q clang; then + elif $_cc -v 2>&1 | grep -q clang && ! $_cc -? > /dev/null 2>&1; then _type=clang _ident=$($_cc --version 2>/dev/null | head -n1) _depflags='-MMD -MF $(@:.o=.d) -MT $@' @@ -4410,7 +4410,7 @@ probe_cc(){ _flags_filter=msvc_flags _ld_lib='lib%.a' _ld_path='-libpath:' - elif $_cc -nologo- 2>&1 | grep -q Microsoft; then + elif $_cc -nologo- 2>&1 | grep -q Microsoft || $_cc -v 2>&1 | grep -q clang && $_cc -? > /dev/null 2>&1; then _type=msvc _ident=$($_cc 2>&1 | head -n1 | tr -d '\r') _DEPCMD='$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< 2>&1 | awk '\''/including/ { sub(/^.*file: */, ""); gsub(/\\/, "/"); if (!match($$0, / /)) print "$@:", $$0 }'\'' > $(@:.o=.d)' From ff1be6c9a694ee019608288fd25f1c869f7f51b7 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 14 Apr 2018 15:45:55 +0100 Subject: [PATCH 2470/2557] amfenc: Fail to open if the user-supplied device is not usable If the user supplies a device or frames context then it is an error not to use it; this is consistent with other hardware components. Also factorise out the D3D11 initialisation and improve error messages. --- libavcodec/amfenc.c | 130 +++++++++++++++++++++++++++----------------- 1 file changed, 81 insertions(+), 49 deletions(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index b9418b679161f..8a9d6884a4634 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -152,10 +152,30 @@ static int amf_load_library(AVCodecContext *avctx) return 0; } +#if CONFIG_D3D11VA +static int amf_init_from_d3d11_device(AVCodecContext *avctx, AVD3D11VADeviceContext *hwctx) +{ + AmfContext *ctx = avctx->priv_data; + AMF_RESULT res; + + res = ctx->context->pVtbl->InitDX11(ctx->context, hwctx->device, AMF_DX11_1); + if (res != AMF_OK) { + if (res == AMF_NOT_SUPPORTED) + av_log(avctx, AV_LOG_ERROR, "AMF via D3D11 is not supported on the given device.\n"); + else + av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on the given D3D11 device: %d.\n", res); + return AVERROR(ENODEV); + } + + return 0; +} +#endif + static int amf_init_context(AVCodecContext *avctx) { - AmfContext *ctx = avctx->priv_data; - AMF_RESULT res = AMF_OK; + AmfContext *ctx = avctx->priv_data; + AMF_RESULT res; + av_unused int ret; ctx->hwsurfaces_in_queue = 0; ctx->hwsurfaces_in_queue_max = 16; @@ -176,59 +196,71 @@ static int amf_init_context(AVCodecContext *avctx) res = ctx->factory->pVtbl->CreateContext(ctx->factory, &ctx->context); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext() failed with error %d\n", res); - // try to reuse existing DX device -#if CONFIG_D3D11VA + + // If a device was passed to the encoder, try to initialise from that. if (avctx->hw_frames_ctx) { - AVHWFramesContext *device_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - if (device_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { - if (amf_av_to_amf_format(device_ctx->sw_format) != AMF_SURFACE_UNKNOWN) { - if (device_ctx->device_ctx->hwctx) { - AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->device_ctx->hwctx; - res = ctx->context->pVtbl->InitDX11(ctx->context, device_d3d11->device, AMF_DX11_1); - if (res == AMF_OK) { - ctx->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx); - if (!ctx->hw_frames_ctx) { - return AVERROR(ENOMEM); - } - if (device_ctx->initial_pool_size > 0) - ctx->hwsurfaces_in_queue_max = device_ctx->initial_pool_size - 1; - } else { - if(res == AMF_NOT_SUPPORTED) - av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n"); - else - av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has non-AMD device, switching to default\n"); - } - } - } else { - av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has format not uspported by AMF, switching to default\n"); - } + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + + if (amf_av_to_amf_format(frames_ctx->sw_format) == AMF_SURFACE_UNKNOWN) { + av_log(avctx, AV_LOG_ERROR, "Format of input frames context (%s) is not supported by AMF.\n", + av_get_pix_fmt_name(frames_ctx->sw_format)); + return AVERROR(EINVAL); } - } else if (avctx->hw_device_ctx) { - AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data); - if (device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { - if (device_ctx->hwctx) { - AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->hwctx; - res = ctx->context->pVtbl->InitDX11(ctx->context, device_d3d11->device, AMF_DX11_1); - if (res == AMF_OK) { - ctx->hw_device_ctx = av_buffer_ref(avctx->hw_device_ctx); - if (!ctx->hw_device_ctx) { - return AVERROR(ENOMEM); - } - } else { - if (res == AMF_NOT_SUPPORTED) - av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n"); - else - av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has non-AMD device, switching to default\n"); - } - } + + switch (frames_ctx->device_ctx->type) { +#if CONFIG_D3D11VA + case AV_HWDEVICE_TYPE_D3D11VA: + ret = amf_init_from_d3d11_device(avctx, frames_ctx->device_ctx->hwctx); + if (ret < 0) + return ret; + break; +#endif + default: + av_log(avctx, AV_LOG_ERROR, "AMF initialisation from a %s frames context is not supported.\n", + av_hwdevice_get_type_name(frames_ctx->device_ctx->type)); + return AVERROR(ENOSYS); } - } + + ctx->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx); + if (!ctx->hw_frames_ctx) + return AVERROR(ENOMEM); + + if (frames_ctx->initial_pool_size > 0) + ctx->hwsurfaces_in_queue_max = frames_ctx->initial_pool_size - 1; + + } else if (avctx->hw_device_ctx) { + AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)avctx->hw_device_ctx->data; + + switch (device_ctx->type) { +#if CONFIG_D3D11VA + case AV_HWDEVICE_TYPE_D3D11VA: + ret = amf_init_from_d3d11_device(avctx, device_ctx->hwctx); + if (ret < 0) + return ret; + break; #endif - if (!ctx->hw_frames_ctx && !ctx->hw_device_ctx) { + default: + av_log(avctx, AV_LOG_ERROR, "AMF initialisation from a %s device is not supported.\n", + av_hwdevice_get_type_name(device_ctx->type)); + return AVERROR(ENOSYS); + } + + ctx->hw_device_ctx = av_buffer_ref(avctx->hw_device_ctx); + if (!ctx->hw_device_ctx) + return AVERROR(ENOMEM); + + } else { res = ctx->context->pVtbl->InitDX11(ctx->context, NULL, AMF_DX11_1); - if (res != AMF_OK) { + if (res == AMF_OK) { + av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D11.\n"); + } else { res = ctx->context->pVtbl->InitDX9(ctx->context, NULL); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "InitDX9() failed with error %d\n", res); + if (res == AMF_OK) { + av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D9.\n"); + } else { + av_log(avctx, AV_LOG_ERROR, "AMF initialisation failed via D3D9: error %d.\n", res); + return AVERROR(ENOSYS); + } } } return 0; From 73ed6fa9d77da8cd4f34742dd0f56e64aa714786 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 14 Apr 2018 15:46:00 +0100 Subject: [PATCH 2471/2557] amfenc: Do not automatically download/upload unknown hardware input frames Supplying a hardware input frame which is not in the input hardware frames context is not allowed by the API, so additional code to handle it is not necessary. Further, handling it automatically results in very low performance - it is more appropriate to fail immediately so that the user can fix their incorrect setup. --- libavcodec/amfenc.c | 88 ++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 53 deletions(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index 8a9d6884a4634..65a8e0a85323e 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -71,14 +71,6 @@ static const FormatMap format_map[] = { AV_PIX_FMT_D3D11, AMF_SURFACE_NV12 }, }; - -static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - return desc->flags & AV_PIX_FMT_FLAG_HWACCEL; -} - - static enum AMF_SURFACE_FORMAT amf_av_to_amf_format(enum AVPixelFormat fmt) { int i; @@ -337,32 +329,14 @@ int av_cold ff_amf_encode_close(AVCodecContext *avctx) static int amf_copy_surface(AVCodecContext *avctx, const AVFrame *frame, AMFSurface* surface) { - AVFrame *sw_frame = NULL; AMFPlane *plane = NULL; uint8_t *dst_data[4]; int dst_linesize[4]; - int ret = 0; int planes; int i; - if (frame->hw_frames_ctx && is_hwaccel_pix_fmt(frame->format)) { - if (!(sw_frame = av_frame_alloc())) { - av_log(avctx, AV_LOG_ERROR, "Can not alloc frame\n"); - ret = AVERROR(ENOMEM); - goto fail; - } - if ((ret = av_hwframe_transfer_data(sw_frame, frame, 0)) < 0) { - av_log(avctx, AV_LOG_ERROR, "Error transferring the data to system memory\n"); - goto fail; - } - frame = sw_frame; - } - planes = (int)surface->pVtbl->GetPlanesCount(surface); - if (planes > amf_countof(dst_data)) { - av_log(avctx, AV_LOG_ERROR, "Invalid number of planes %d in surface\n", planes); - ret = AVERROR(EINVAL); - goto fail; - } + planes = surface->pVtbl->GetPlanesCount(surface); + av_assert0(planes < FF_ARRAY_ELEMS(dst_data)); for (i = 0; i < planes; i++) { plane = surface->pVtbl->GetPlaneAt(surface, i); @@ -373,11 +347,7 @@ static int amf_copy_surface(AVCodecContext *avctx, const AVFrame *frame, (const uint8_t**)frame->data, frame->linesize, frame->format, avctx->width, avctx->height); -fail: - if (sw_frame) { - av_frame_free(&sw_frame); - } - return ret; + return 0; } static inline int timestamp_queue_enqueue(AVCodecContext *avctx, int64_t timestamp) @@ -579,31 +549,46 @@ int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame) return AVERROR_EOF; } } else { // submit frame + int hw_surface = 0; + if (ctx->delayed_surface != NULL) { return AVERROR(EAGAIN); // should not happen when called from ffmpeg, other clients may resubmit } // prepare surface from frame - if (frame->hw_frames_ctx && ( // HW frame detected - // check if the same hw_frames_ctx as used in initialization - (ctx->hw_frames_ctx && frame->hw_frames_ctx->data == ctx->hw_frames_ctx->data) || - // check if the same hw_device_ctx as used in initialization - (ctx->hw_device_ctx && ((AVHWFramesContext*)frame->hw_frames_ctx->data)->device_ctx == - (AVHWDeviceContext*)ctx->hw_device_ctx->data) - )) { - AMFBuffer *frame_ref_storage_buffer; - + switch (frame->format) { #if CONFIG_D3D11VA - static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } }; - ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // actual texture - int index = (int)(size_t)frame->data[1]; // index is a slice in texture array is - set to tell AMF which slice to use - texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID, sizeof(index), &index); + case AV_PIX_FMT_D3D11: + { + static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } }; + ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // actual texture + int index = (intptr_t)frame->data[1]; // index is a slice in texture array is - set to tell AMF which slice to use - res = ctx->context->pVtbl->CreateSurfaceFromDX11Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed with error %d\n", res); + av_assert0(frame->hw_frames_ctx && ctx->hw_frames_ctx && + frame->hw_frames_ctx->data == ctx->hw_frames_ctx->data); + + texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID, sizeof(index), &index); + + res = ctx->context->pVtbl->CreateSurfaceFromDX11Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed with error %d\n", res); + + hw_surface = 1; + } + break; +#endif + default: + { + res = ctx->context->pVtbl->AllocSurface(ctx->context, AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res); + amf_copy_surface(avctx, frame, surface); + } + break; + } + + if (hw_surface) { + AMFBuffer *frame_ref_storage_buffer; // input HW surfaces can be vertically aligned by 16; tell AMF the real size surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height); -#endif frame_ref_storage_buffer = amf_create_buffer_with_frame_ref(frame, ctx->context); AMF_RETURN_IF_FALSE(ctx, frame_ref_storage_buffer != NULL, AVERROR(ENOMEM), "create_buffer_with_frame_ref() returned NULL\n"); @@ -612,11 +597,8 @@ int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame) AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SetProperty failed for \"av_frame_ref\" with error %d\n", res); ctx->hwsurfaces_in_queue++; frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer); - } else { - res = ctx->context->pVtbl->AllocSurface(ctx->context, AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res); - amf_copy_surface(avctx, frame, surface); } + surface->pVtbl->SetPts(surface, frame->pts); AMF_ASSIGN_PROPERTY_INT64(res, surface, PTS_PROP, frame->pts); From ab7eed13a789b3f709a8964b0337bc69f152a9d7 Mon Sep 17 00:00:00 2001 From: Alexander Kravchenko Date: Sat, 14 Apr 2018 15:46:05 +0100 Subject: [PATCH 2472/2557] amfenc: Ensure that the software format of hardware frames is valid Signed-off-by: Mark Thompson --- libavcodec/amfenc.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index 65a8e0a85323e..1ac4ebf45687d 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -68,7 +68,6 @@ static const FormatMap format_map[] = { AV_PIX_FMT_GRAY8, AMF_SURFACE_GRAY8 }, { AV_PIX_FMT_YUV420P, AMF_SURFACE_YUV420P }, { AV_PIX_FMT_YUYV422, AMF_SURFACE_YUY2 }, - { AV_PIX_FMT_D3D11, AMF_SURFACE_NV12 }, }; static enum AMF_SURFACE_FORMAT amf_av_to_amf_format(enum AVPixelFormat fmt) @@ -263,6 +262,7 @@ static int amf_init_encoder(AVCodecContext *avctx) AmfContext *ctx = avctx->priv_data; const wchar_t *codec_id = NULL; AMF_RESULT res = AMF_OK; + enum AVPixelFormat pix_fmt; switch (avctx->codec->id) { case AV_CODEC_ID_H264: @@ -276,8 +276,14 @@ static int amf_init_encoder(AVCodecContext *avctx) } AMF_RETURN_IF_FALSE(ctx, codec_id != NULL, AVERROR(EINVAL), "Codec %d is not supported\n", avctx->codec->id); - ctx->format = amf_av_to_amf_format(avctx->pix_fmt); - AMF_RETURN_IF_FALSE(ctx, ctx->format != AMF_SURFACE_UNKNOWN, AVERROR(EINVAL), "Format %d is not supported\n", avctx->pix_fmt); + if (ctx->hw_frames_ctx) + pix_fmt = ((AVHWFramesContext*)ctx->hw_frames_ctx->data)->sw_format; + else + pix_fmt = avctx->pix_fmt; + + ctx->format = amf_av_to_amf_format(pix_fmt); + AMF_RETURN_IF_FALSE(ctx, ctx->format != AMF_SURFACE_UNKNOWN, AVERROR(EINVAL), + "Format %s is not supported\n", av_get_pix_fmt_name(pix_fmt)); res = ctx->factory->pVtbl->CreateComponent(ctx->factory, ctx->context, codec_id, &ctx->encoder); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_ENCODER_NOT_FOUND, "CreateComponent(%ls) failed with error %d\n", codec_id, res); From 2c6ca2b54968ad3d2c947cdc16f92b6867f29f3a Mon Sep 17 00:00:00 2001 From: Alexander Kravchenko Date: Sat, 14 Apr 2018 15:46:10 +0100 Subject: [PATCH 2473/2557] amfenc: Add DXVA2 hardware frame input support Adds support for AMF initialisation from a DXVA2 (Direct3D9) device, and then allows passing DXVA2 surfaces into an AMF encoder. Signed-off-by: Mark Thompson --- libavcodec/amfenc.c | 79 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index 1ac4ebf45687d..2a8c76069b62b 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -24,6 +24,10 @@ #if CONFIG_D3D11VA #include "libavutil/hwcontext_d3d11va.h" #endif +#if CONFIG_DXVA2 +#define COBJMACROS +#include "libavutil/hwcontext_dxva2.h" +#endif #include "libavutil/mem.h" #include "libavutil/pixdesc.h" #include "libavutil/time.h" @@ -50,6 +54,9 @@ const enum AVPixelFormat ff_amf_pix_fmts[] = { AV_PIX_FMT_YUV420P, #if CONFIG_D3D11VA AV_PIX_FMT_D3D11, +#endif +#if CONFIG_DXVA2 + AV_PIX_FMT_DXVA2_VLD, #endif AV_PIX_FMT_NONE }; @@ -162,6 +169,52 @@ static int amf_init_from_d3d11_device(AVCodecContext *avctx, AVD3D11VADeviceCont } #endif +#if CONFIG_DXVA2 +static int amf_init_from_dxva2_device(AVCodecContext *avctx, AVDXVA2DeviceContext *hwctx) +{ + AmfContext *ctx = avctx->priv_data; + HANDLE device_handle; + IDirect3DDevice9 *device; + HRESULT hr; + AMF_RESULT res; + int ret; + + hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &device_handle); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "Failed to open device handle for Direct3D9 device: %lx.\n", (unsigned long)hr); + return AVERROR_EXTERNAL; + } + + hr = IDirect3DDeviceManager9_LockDevice(hwctx->devmgr, device_handle, &device, FALSE); + if (SUCCEEDED(hr)) { + IDirect3DDeviceManager9_UnlockDevice(hwctx->devmgr, device_handle, FALSE); + ret = 0; + } else { + av_log(avctx, AV_LOG_ERROR, "Failed to lock device handle for Direct3D9 device: %lx.\n", (unsigned long)hr); + ret = AVERROR_EXTERNAL; + } + + IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->devmgr, device_handle); + + if (ret < 0) + return ret; + + res = ctx->context->pVtbl->InitDX9(ctx->context, device); + + IDirect3DDevice9_Release(device); + + if (res != AMF_OK) { + if (res == AMF_NOT_SUPPORTED) + av_log(avctx, AV_LOG_ERROR, "AMF via D3D9 is not supported on the given device.\n"); + else + av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on given D3D9 device: %d.\n", res); + return AVERROR(ENODEV); + } + + return 0; +} +#endif + static int amf_init_context(AVCodecContext *avctx) { AmfContext *ctx = avctx->priv_data; @@ -205,6 +258,13 @@ static int amf_init_context(AVCodecContext *avctx) if (ret < 0) return ret; break; +#endif +#if CONFIG_DXVA2 + case AV_HWDEVICE_TYPE_DXVA2: + ret = amf_init_from_dxva2_device(avctx, frames_ctx->device_ctx->hwctx); + if (ret < 0) + return ret; + break; #endif default: av_log(avctx, AV_LOG_ERROR, "AMF initialisation from a %s frames context is not supported.\n", @@ -229,6 +289,13 @@ static int amf_init_context(AVCodecContext *avctx) if (ret < 0) return ret; break; +#endif +#if CONFIG_DXVA2 + case AV_HWDEVICE_TYPE_DXVA2: + ret = amf_init_from_dxva2_device(avctx, device_ctx->hwctx); + if (ret < 0) + return ret; + break; #endif default: av_log(avctx, AV_LOG_ERROR, "AMF initialisation from a %s device is not supported.\n", @@ -580,6 +647,18 @@ int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame) hw_surface = 1; } break; +#endif +#if CONFIG_DXVA2 + case AV_PIX_FMT_DXVA2_VLD: + { + IDirect3DSurface9 *texture = (IDirect3DSurface9 *)frame->data[3]; // actual texture + + res = ctx->context->pVtbl->CreateSurfaceFromDX9Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX9Native() failed with error %d\n", res); + + hw_surface = 1; + } + break; #endif default: { From edecd723f3e4528d5153a00b92343041367fbe06 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sat, 14 Apr 2018 15:46:15 +0100 Subject: [PATCH 2474/2557] amfenc: Remove spurious initialisations Also minor cosmetics. --- libavcodec/amfenc.c | 76 +++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 47 deletions(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index 2a8c76069b62b..384d8efc92cf8 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -107,16 +107,11 @@ static AMFTraceWriterVtbl tracer_vtbl = static int amf_load_library(AVCodecContext *avctx) { - AmfContext *ctx = avctx->priv_data; - AMFInit_Fn init_fun = NULL; - AMFQueryVersion_Fn version_fun = NULL; - AMF_RESULT res = AMF_OK; + AmfContext *ctx = avctx->priv_data; + AMFInit_Fn init_fun; + AMFQueryVersion_Fn version_fun; + AMF_RESULT res; - ctx->eof = 0; - ctx->delayed_drain = 0; - ctx->hw_frames_ctx = NULL; - ctx->hw_device_ctx = NULL; - ctx->delayed_surface = NULL; ctx->delayed_frame = av_frame_alloc(); if (!ctx->delayed_frame) { return AVERROR(ENOMEM); @@ -326,10 +321,10 @@ static int amf_init_context(AVCodecContext *avctx) static int amf_init_encoder(AVCodecContext *avctx) { - AmfContext *ctx = avctx->priv_data; - const wchar_t *codec_id = NULL; - AMF_RESULT res = AMF_OK; - enum AVPixelFormat pix_fmt; + AmfContext *ctx = avctx->priv_data; + const wchar_t *codec_id = NULL; + AMF_RESULT res; + enum AVPixelFormat pix_fmt; switch (avctx->codec->id) { case AV_CODEC_ID_H264: @@ -360,9 +355,9 @@ static int amf_init_encoder(AVCodecContext *avctx) int av_cold ff_amf_encode_close(AVCodecContext *avctx) { - AmfContext *ctx = avctx->priv_data; - if (ctx->delayed_surface) - { + AmfContext *ctx = avctx->priv_data; + + if (ctx->delayed_surface) { ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface); ctx->delayed_surface = NULL; } @@ -402,11 +397,11 @@ int av_cold ff_amf_encode_close(AVCodecContext *avctx) static int amf_copy_surface(AVCodecContext *avctx, const AVFrame *frame, AMFSurface* surface) { - AMFPlane *plane = NULL; - uint8_t *dst_data[4]; - int dst_linesize[4]; - int planes; - int i; + AMFPlane *plane; + uint8_t *dst_data[4]; + int dst_linesize[4]; + int planes; + int i; planes = surface->pVtbl->GetPlanesCount(surface); av_assert0(planes < FF_ARRAY_ELEMS(dst_data)); @@ -437,11 +432,11 @@ static inline int timestamp_queue_enqueue(AVCodecContext *avctx, int64_t timesta static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buffer) { - AmfContext *ctx = avctx->priv_data; - int ret; - AMFVariantStruct var = {0}; - int64_t timestamp = AV_NOPTS_VALUE; - int64_t size = buffer->pVtbl->GetSize(buffer); + AmfContext *ctx = avctx->priv_data; + int ret; + AMFVariantStruct var = {0}; + int64_t timestamp = AV_NOPTS_VALUE; + int64_t size = buffer->pVtbl->GetSize(buffer); if ((ret = ff_alloc_packet2(avctx, pkt, size, 0)) < 0) { return ret; @@ -497,20 +492,7 @@ static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buff // amfenc API implementation int ff_amf_encode_init(AVCodecContext *avctx) { - AmfContext *ctx = avctx->priv_data; - int ret; - - ctx->factory = NULL; - ctx->debug = NULL; - ctx->trace = NULL; - ctx->context = NULL; - ctx->encoder = NULL; - ctx->library = NULL; - ctx->version = 0; - ctx->eof = 0; - ctx->format = 0; - ctx->tracer.vtbl = NULL; - ctx->tracer.avctx = NULL; + int ret; if ((ret = amf_load_library(avctx)) == 0) { if ((ret = amf_init_context(avctx)) == 0) { @@ -587,18 +569,18 @@ static AMFBuffer *amf_create_buffer_with_frame_ref(const AVFrame *frame, AMFCont static void amf_release_buffer_with_frame_ref(AMFBuffer *frame_ref_storage_buffer) { - AVFrame *av_frame_ref; - memcpy(&av_frame_ref, frame_ref_storage_buffer->pVtbl->GetNative(frame_ref_storage_buffer), sizeof(av_frame_ref)); - av_frame_free(&av_frame_ref); + AVFrame *frame_ref; + memcpy(&frame_ref, frame_ref_storage_buffer->pVtbl->GetNative(frame_ref_storage_buffer), sizeof(frame_ref)); + av_frame_free(&frame_ref); frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer); } int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame) { - AMF_RESULT res = AMF_OK; - AmfContext *ctx = avctx->priv_data; - AMFSurface *surface = NULL; - int ret; + AmfContext *ctx = avctx->priv_data; + AMFSurface *surface; + AMF_RESULT res; + int ret; if (!ctx->encoder) return AVERROR(EINVAL); From 783df2eb59ca2347af89e3eca3aef2ff12779178 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 16 Apr 2018 14:35:14 +0800 Subject: [PATCH 2475/2557] avformat/hlsenc: avformat/hlsenc: add error message for encrypt fmp4 mode and refine the warning message when use both hls_key_info_file and hls_enc Reviewed-by: Gyan Doshi Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index c7540166ab89c..c27a66ea795b0 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1591,9 +1591,14 @@ static int hls_start(AVFormatContext *s, VariantStream *vs) } if (c->key_info_file || c->encrypt) { + if (c->segment_type == SEGMENT_TYPE_FMP4) { + av_log(s, AV_LOG_ERROR, "Encrypted fmp4 not yet supported\n"); + return AVERROR_PATCHWELCOME; + } + if (c->key_info_file && c->encrypt) { av_log(s, AV_LOG_WARNING, "Cannot use both -hls_key_info_file and -hls_enc," - " will use -hls_key_info_file priority\n"); + " ignoring -hls_enc\n"); } if (!c->encrypt_started || (c->flags & HLS_PERIODIC_REKEY)) { From e1c8bd2389d62b584d68486908b1d6351c027f41 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 16 Apr 2018 09:31:11 +0200 Subject: [PATCH 2476/2557] avfilter/af_headphone: fix type=time with hrir=multich Signed-off-by: Paul B Mahol --- libavfilter/af_headphone.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/af_headphone.c b/libavfilter/af_headphone.c index a71ed336d88c0..79101322189c4 100644 --- a/libavfilter/af_headphone.c +++ b/libavfilter/af_headphone.c @@ -567,8 +567,8 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) if (s->type == TIME_DOMAIN) { offset = idx * FFALIGN(len, 16); for (j = 0; j < len; j++) { - data_ir_l[offset + j] = ptr[len * 2 - j * 2 - 2] * gain_lin; - data_ir_r[offset + j] = ptr[len * 2 - j * 2 - 1] * gain_lin; + data_ir_l[offset + j] = ptr[len * N - j * N - N + I ] * gain_lin; + data_ir_r[offset + j] = ptr[len * N - j * N - N + I + 1] * gain_lin; } } else { memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l)); From cb2f52b6a70971c902ea2aaa989d141973472125 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 16 Apr 2018 11:31:43 +0200 Subject: [PATCH 2477/2557] avfilter/showvolume : add display scale option linear (current behaviour) or log display (more close to classic audio meter) --- doc/filters.texi | 4 ++++ libavfilter/avf_showvolume.c | 28 +++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 40083dd080623..d95b377bd73f3 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -20014,6 +20014,10 @@ Set background opacity, allowed range is [0, 1]. Default is 0. @item m Set metering mode, can be peak: @code{p} or rms: @code{r}, default is @code{p}. + +@item ds +Set display scale, can be linear: @code{lin} or log: @code{log}, +default is @code{lin}. @end table @section showwaves diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index 7fe39168555b6..da8b4088bdfbc 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -33,6 +33,7 @@ static const char *const var_names[] = { "VOLUME", "CHANNEL", "PEAK", NULL }; enum { VAR_VOLUME, VAR_CHANNEL, VAR_PEAK, VAR_VARS_NB }; +enum DisplayScale { LINEAR, LOG, NB_DISPLAY_SCALE }; typedef struct ShowVolumeContext { const AVClass *class; @@ -54,6 +55,7 @@ typedef struct ShowVolumeContext { uint32_t *color_lut; float *max; float rms_factor; + int display_scale; void (*meter)(float *src, int nb_samples, float *max, float factor); } ShowVolumeContext; @@ -79,6 +81,9 @@ static const AVOption showvolume_options[] = { { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "mode" }, { "p", "peak", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, { "r", "rms", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" }, + { "ds", "set display scale", OFFSET(display_scale), AV_OPT_TYPE_INT, {.i64=LINEAR}, LINEAR, NB_DISPLAY_SCALE - 1, FLAGS, "display_scale" }, + { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=LINEAR}, 0, 0, FLAGS, "display_scale" }, + { "log", "log", 0, AV_OPT_TYPE_CONST, {.i64=LOG}, 0, 0, FLAGS, "display_scale" }, { NULL } }; @@ -256,13 +261,28 @@ static void clear_picture(ShowVolumeContext *s, AVFilterLink *outlink) { } } +static inline int calc_max_draw(ShowVolumeContext *s, AVFilterLink *outlink, float max) +{ + float max_val; + if (s->display_scale == LINEAR) { + max_val = max; + } else { /* log */ + max_val = av_clipf(0.21 * log10(max) + 1, 0, 1); + } + if (s->orientation) { /* vertical */ + return outlink->h - outlink->h * max_val; + } else { /* horizontal */ + return s->w * max_val; + } +} + static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; ShowVolumeContext *s = ctx->priv; const int step = s->step; - int c, j, k; + int c, j, k, max_draw; AVFrame *out; if (!s->out || s->out->width != outlink->w || @@ -304,8 +324,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) s->values[c * VAR_VARS_NB + VAR_VOLUME] = 20.0 * log10(max); max = av_clipf(max, 0, 1); + max_draw = calc_max_draw(s, outlink, max); - for (j = outlink->h - outlink->h * max; j < s->w; j++) { + for (j = max_draw; j < s->w; j++) { uint8_t *dst = s->out->data[0] + j * s->out->linesize[0] + c * (s->b + s->h) * 4; for (k = 0; k < s->h; k++) { AV_WN32A(&dst[k * 4], lut[s->w - j - 1]); @@ -332,11 +353,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) s->values[c * VAR_VARS_NB + VAR_VOLUME] = 20.0 * log10(max); max = av_clipf(max, 0, 1); + max_draw = calc_max_draw(s, outlink, max); for (j = 0; j < s->h; j++) { uint8_t *dst = s->out->data[0] + (c * s->h + c * s->b + j) * s->out->linesize[0]; - for (k = 0; k < s->w * max; k++) { + for (k = 0; k < max_draw; k++) { AV_WN32A(dst + k * 4, lut[k]); if (k & step) k += step; From fd10a6e2f21f9cadc44a0415e204ea82940cd089 Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 16 Apr 2018 11:32:48 +0200 Subject: [PATCH 2478/2557] avfilter/showvolume : add persistent max display draw a color line for the max level in the given duration --- doc/filters.texi | 10 +++++++ libavfilter/avf_showvolume.c | 52 ++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index d95b377bd73f3..f267d26b9db40 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -20018,6 +20018,16 @@ default is @code{p}. @item ds Set display scale, can be linear: @code{lin} or log: @code{log}, default is @code{lin}. + +@item dm +In second. +If set to > 0., display a line for the max level +in the previous seconds. +default is disabled: @code{0.} + +@item dmc +The color of the max line. Use when @code{dm} option is set to > 0. +default is: @code{orange} @end table @section showwaves diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index da8b4088bdfbc..fe8a95a07ba73 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -57,6 +57,12 @@ typedef struct ShowVolumeContext { float rms_factor; int display_scale; + double draw_persistent_duration; /* in second */ + uint8_t persistant_max_rgba[4]; + int persistent_max_frames; /* number of frames to check max value */ + float *max_persistent; /* max value for draw_persistent_max for each channel */ + int *nb_frames_max_display; /* number of frame for each channel, for displaying the max value */ + void (*meter)(float *src, int nb_samples, float *max, float factor); } ShowVolumeContext; @@ -73,6 +79,8 @@ static const AVOption showvolume_options[] = { { "c", "set volume color expression", OFFSET(color), AV_OPT_TYPE_STRING, {.str="PEAK*255+floor((1-PEAK)*255)*256+0xff000000"}, 0, 0, FLAGS }, { "t", "display channel names", OFFSET(draw_text), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, { "v", "display volume value", OFFSET(draw_volume), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, + { "dm", "duration for max value display", OFFSET(draw_persistent_duration), AV_OPT_TYPE_DOUBLE, {.dbl=0.}, 0, 9000, FLAGS}, + { "dmc","set color of the max value line", OFFSET(persistant_max_rgba), AV_OPT_TYPE_COLOR, {.str = "orange"}, CHAR_MIN, CHAR_MAX, FLAGS }, { "o", "set orientation", OFFSET(orientation), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "orientation" }, { "h", "horizontal", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "orientation" }, { "v", "vertical", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "orientation" }, @@ -180,6 +188,11 @@ static int config_input(AVFilterLink *inlink) default: return AVERROR_BUG; } + if (s->draw_persistent_duration > 0.) { + s->persistent_max_frames = (int) FFMAX(av_q2d(s->frame_rate) * s->draw_persistent_duration, 1.); + s->max_persistent = av_calloc(inlink->channels * s->persistent_max_frames, sizeof(*s->max_persistent)); + s->nb_frames_max_display = av_calloc(inlink->channels * s->persistent_max_frames, sizeof(*s->nb_frames_max_display)); + } return 0; } @@ -276,6 +289,33 @@ static inline int calc_max_draw(ShowVolumeContext *s, AVFilterLink *outlink, flo } } +static inline void calc_persistent_max(ShowVolumeContext *s, float max, int channel) +{ + /* update max value for persistent max display */ + if ((max >= s->max_persistent[channel]) || (s->nb_frames_max_display[channel] >= s->persistent_max_frames)) { /* update max value for display */ + s->max_persistent[channel] = max; + s->nb_frames_max_display[channel] = 0; + } else { + s->nb_frames_max_display[channel] += 1; /* incremente display frame count */ + } +} + +static inline void draw_max_line(ShowVolumeContext *s, int max_draw, int channel) +{ + int k; + if (s->orientation) { /* vertical */ + uint8_t *dst = s->out->data[0] + max_draw * s->out->linesize[0] + channel * (s->b + s->h) * 4; + for (k = 0; k < s->h; k++) { + memcpy(dst + k * 4, s->persistant_max_rgba, sizeof(s->persistant_max_rgba)); + } + } else { /* horizontal */ + for (k = 0; k < s->h; k++) { + uint8_t *dst = s->out->data[0] + (channel * s->h + channel * s->b + k) * s->out->linesize[0]; + memcpy(dst + max_draw * 4, s->persistant_max_rgba, sizeof(s->persistant_max_rgba)); + } + } +} + static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) { AVFilterContext *ctx = inlink->dst; @@ -341,6 +381,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) continue; drawtext(s->out, c * (s->h + s->b) + (s->h - 10) / 2, outlink->h - 35, channel_name, 1); } + + if (s->draw_persistent_duration > 0.) { + calc_persistent_max(s, max, c); + max_draw = FFMAX(0, calc_max_draw(s, outlink, s->max_persistent[c]) - 1); + draw_max_line(s, max_draw, c); + } } } else { /* horizontal */ for (c = 0; c < inlink->channels; c++) { @@ -371,6 +417,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) continue; drawtext(s->out, 2, c * (s->h + s->b) + (s->h - 8) / 2, channel_name, 0); } + + if (s->draw_persistent_duration > 0.) { + calc_persistent_max(s, max, c); + max_draw = FFMAX(0, calc_max_draw(s, outlink, s->max_persistent[c]) - 1); + draw_max_line(s, max_draw, c); + } } } From 56315df32c489676c3add6c1305c53cfeaae6f2c Mon Sep 17 00:00:00 2001 From: Martin Vignali Date: Mon, 16 Apr 2018 11:33:14 +0200 Subject: [PATCH 2479/2557] avfilter/showvolume : cosmetic move bracket after func declaration to a new line --- libavfilter/avf_showvolume.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index fe8a95a07ba73..6b553c4eba774 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -263,7 +263,8 @@ static void drawtext(AVFrame *pic, int x, int y, const char *txt, int o) } } -static void clear_picture(ShowVolumeContext *s, AVFilterLink *outlink) { +static void clear_picture(ShowVolumeContext *s, AVFilterLink *outlink) +{ int i, j; const uint32_t bg = (uint32_t)(s->bgopacity * 255) << 24; From e8be46dfe059eb0b9372a66eb738b6c77c342802 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 16 Apr 2018 12:06:47 +0200 Subject: [PATCH 2480/2557] doc/APIchanges: Fill in missing stuff Signed-off-by: Michael Niedermayer --- doc/APIchanges | 66 +++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index f6ad2169a2ef7..deee636abadbd 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,98 +15,98 @@ libavutil: 2017-10-21 API changes, most recent first: -2018-04-03 - xxxxxxx - lavu 56.13.100 - pixdesc.h +2018-04-03 - d6fc031caf - lavu 56.13.100 - pixdesc.h Deprecate AV_PIX_FMT_FLAG_PSEUDOPAL and make allocating a pseudo palette optional for API users (see AV_PIX_FMT_FLAG_PSEUDOPAL doxygen for details). -2018-04-01 - xxxxxxx - lavc 58.17.100 - avcodec.h +2018-04-01 - 860086ee16 - lavc 58.17.100 - avcodec.h Add av_packet_make_refcounted(). -2018-xx-xx - xxxxxxx - lavfi 7.14.100 - avfilter.h +2018-04-01 - f1805d160d - lavfi 7.14.100 - avfilter.h Deprecate use of avfilter_register(), avfilter_register_all(), avfilter_next(). Add av_filter_iterate(). -2018-03-xx - xxxxxxx - lavc 58.16.100 - avcodec.h +2018-03-25 - b7d0d912ef - lavc 58.16.100 - avcodec.h Add FF_SUB_CHARENC_MODE_IGNORE. -2018-03-23 - xxxxxxx - lavu 56.12.100 - encryption_info.h +2018-03-23 - db2a7c947e - lavu 56.12.100 - encryption_info.h Add AVEncryptionInitInfo and AVEncryptionInfo structures to hold new side-data for encryption info. -2018-03-21 - xxxxxxx - lavc 58.15.100 - avcodec.h +2018-03-21 - f14ca60001 - lavc 58.15.100 - avcodec.h Add av_packet_make_writable(). -2018-03-18 - xxxxxxx - lavu 56.11.100 - frame.h +2018-03-18 - 4b86ac27a0 - lavu 56.11.100 - frame.h Add AV_FRAME_DATA_QP_TABLE_PROPERTIES and AV_FRAME_DATA_QP_TABLE_DATA. 2018-03-15 - e0e72539cf - lavu 56.10.100 - opt.h Add AV_OPT_FLAG_BSF_PARAM -2018-03-07 - xxxxxxx - lavu 56.9.100 - crc.h +2018-03-07 - 950170bd3b - lavu 56.9.100 - crc.h Add AV_CRC_8_EBU crc variant. -2018-03-xx - xxxxxxx - lavc 58.14.100 - mediacodec.h +2018-03-07 - 2a0eb86857 - lavc 58.14.100 - mediacodec.h Change the default behavior of avcodec_flush() on mediacodec video decoders. To restore the previous behavior, use the new delay_flush=1 option. -2018-03-xx - xxxxxxx - lavu 56.8.100 - frame.h +2018-03-01 - 6731f60598 - lavu 56.8.100 - frame.h Add av_frame_new_side_data_from_buf(). -2018-02-xx - xxxxxxx +2018-02-15 - 8a8d0b319a Change av_ripemd_update(), av_murmur3_update() and av_hash_update() length parameter type to size_t at next major bump. -2018-02-xx - xxxxxxx - lavfi 7.12.100 - avfilter.h +2018-02-12 - bcab11a1a2 - lavfi 7.12.100 - avfilter.h Add AVFilterContext.extra_hw_frames. -2018-02-xx - xxxxxxx - lavc 58.11.100 - avcodec.h +2018-02-12 - d23fff0d8a - lavc 58.11.100 - avcodec.h Add AVCodecContext.extra_hw_frames. -2018-xx-xx - xxxxxxx - lavf 58.9.100 - avformat.h +2018-02-06 - 0694d87024 - lavf 58.9.100 - avformat.h Deprecate use of av_register_input_format(), av_register_output_format(), av_register_all(), av_iformat_next(), av_oformat_next(). Add av_demuxer_iterate(), and av_muxer_iterate(). -2018-xx-xx - xxxxxxx - lavc 58.10.100 - avcodec.h +2018-02-06 - 36c85d6e77 - lavc 58.10.100 - avcodec.h Deprecate use of avcodec_register(), avcodec_register_all(), av_codec_next(), av_register_codec_parser(), and av_parser_next(). Add av_codec_iterate() and av_parser_iterate(). -2018-02-xx - xxxxxxx - lavf 58.8.100 - avformat.h +2018-02-04 - ff46124b0d - lavf 58.8.100 - avformat.h Deprecate the current names of the RTSP "timeout", "stimeout", "user-agent" options. Introduce "listen_timeout" as replacement for the current "timeout" option, and "user_agent" as replacement for "user-agent". Once the deprecation is over, the old "timeout" option will be removed, and "stimeout" will be renamed to "stimeout" (the "timeout" option will essentially change semantics). -2018-01-xx - xxxxxxx - lavf 58.7.100 - avformat.h +2018-01-28 - ea3672b7d6 - lavf 58.7.100 - avformat.h Deprecate AVFormatContext filename field which had limited length, use the new dynamically allocated url field instead. -2018-01-xx - xxxxxxx - lavf 58.7.100 - avformat.h +2018-01-28 - ea3672b7d6 - lavf 58.7.100 - avformat.h Add url field to AVFormatContext and add ff_format_set_url helper function. -2018-01-xx - xxxxxxx - lavf 58.6.100 - avformat.h +2018-01-27 - 6194d7e564 - lavf 58.6.100 - avformat.h Add AVFMTCTX_UNSEEKABLE (for HLS demuxer). -2018-xx-xx - xxxxxxx - lavu 56.9.100 - aes_ctr.h +2018-01-23 - 9f07cf7c00 - lavu 56.9.100 - aes_ctr.h Add method to set the 16-byte IV. -2018-01-xx - xxxxxxx - lavf 58.5.100 - avformat.h +2018-01-16 - 631c56a8e4 - lavf 58.5.100 - avformat.h Explicitly make avformat_network_init() and avformat_network_deinit() optional. If these are not called, network initialization and deinitialization is automatic, and unlike in older versions, fully supported, unless libavformat is linked to ancient GnuTLS and OpenSSL. -2018-01-xx - xxxxxxx - lavf 58.4.100 - avformat.h +2018-01-16 - 6512ff72f9 - lavf 58.4.100 - avformat.h Deprecate AVStream.recommended_encoder_configuration. It was useful only for FFserver, which has been removed. -2018-01-xx - xxxxxxx - lavfi 7.11.101 - avfilter.h +2018-01-05 - 798dcf2432 - lavfi 7.11.101 - avfilter.h Deprecate avfilter_link_get_channels(). Use av_buffersink_get_channels(). -2017-xx-xx - xxxxxxx - lavr 4.0.0 - avresample.h +2017-01-04 - c29038f304 - lavr 4.0.0 - avresample.h Deprecate the entire library. Merged years ago to provide compatibility with Libav, it remained unmaintained by the FFmpeg project and duplicated functionality provided by libswresample. @@ -115,36 +115,36 @@ API changes, most recent first: Users of this library are asked to migrate to libswresample, which, as well as providing more functionality, is faster and has higher accuracy. -2017-xx-xx - xxxxxxx - lavc 58.9.100 - avcodec.h +2017-12-26 - a04c2c707d - lavc 58.9.100 - avcodec.h Deprecate av_lockmgr_register(). You need to build FFmpeg with threading support enabled to get basic thread-safety (which is the default build configuration). -2017-12-xx - xxxxxxx - lavu 56.7.100 - cpu.h +2017-12-24 - 8b81eabe57 - lavu 56.7.100 - cpu.h AVX-512 flags added. -2017-xx-xx - xxxxxxx - lavc 58.8.100 - avcodec.h +2017-12-16 - 8bf4e6d3ce - lavc 58.8.100 - avcodec.h The MediaCodec decoders now support AVCodecContext.hw_device_ctx. -2017-xx-xx - xxxxxxx - lavu 56.6.100 - hwcontext.h hwcontext_mediacodec.h +2017-12-16 - e4d9f05ca7 - lavu 56.6.100 - hwcontext.h hwcontext_mediacodec.h Add AV_HWDEVICE_TYPE_MEDIACODEC and a new installed header with MediaCodec-specific hwcontext definitions. -2017-xx-xx - xxxxxxc - lavc 58.7.100 - avcodec.h +2017-12-14 - b945fed629 - lavc 58.7.100 - avcodec.h Add AV_CODEC_CAP_HARDWARE, AV_CODEC_CAP_HYBRID, and AVCodec.wrapper_name, and mark all AVCodecs accordingly. -2017-xx-xx - xxxxxxx - lavu 56.4.100 / 56.7.0 - stereo3d.h +2017-11-29 - d268094f88 - lavu 56.4.100 / 56.7.0 - stereo3d.h Add view field to AVStereo3D structure and AVStereo3DView enum. -2017-xx-xx - xxxxxxx - lavc 58.6.100 - avcodec.h +2017-11-26 - 3a71bcc213 - lavc 58.6.100 - avcodec.h Add const to AVCodecContext.hwaccel. -2017-11-xx - xxxxxxx - lavc 58.5.100 - avcodec.h +2017-11-26 - 3536a3efb9 - lavc 58.5.100 - avcodec.h Deprecate user visibility of the AVHWAccel structure and the functions av_register_hwaccel() and av_hwaccel_next(). -2017-11-xx - xxxxxxx - lavc 58.4.100 - avcodec.h +2017-11-26 - 24cc0a53e9 - lavc 58.4.100 - avcodec.h Add AVCodecHWConfig and avcodec_get_hw_config(). 2017-11-22 - 3650cb2dfa - lavu 56.3.100 - opencl.h From 1b7b7c6a62229cf6f8b0545782ca5c7d36cbd8b2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 16 Apr 2018 12:21:39 +0200 Subject: [PATCH 2481/2557] doc/APIchanges: Add 4.0 cut point Signed-off-by: Michael Niedermayer --- doc/APIchanges | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/APIchanges b/doc/APIchanges index deee636abadbd..2deef49edb642 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,8 @@ libavutil: 2017-10-21 API changes, most recent first: +-------- 8< --------- FFmpeg 4.0 was cut here -------- 8< --------- + 2018-04-03 - d6fc031caf - lavu 56.13.100 - pixdesc.h Deprecate AV_PIX_FMT_FLAG_PSEUDOPAL and make allocating a pseudo palette optional for API users (see AV_PIX_FMT_FLAG_PSEUDOPAL doxygen for details). From 7e3a070d9aac3ccdd1a5ee9ba08508811ad5202f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 16 Apr 2018 11:47:03 +0200 Subject: [PATCH 2482/2557] Bump minor versions for branching release/4.0 Signed-off-by: Michael Niedermayer --- libavcodec/version.h | 2 +- libavdevice/version.h | 2 +- libavfilter/version.h | 2 +- libavformat/version.h | 4 ++-- libavutil/version.h | 2 +- libpostproc/version.h | 2 +- libswresample/version.h | 4 ++-- libswscale/version.h | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index e59215dfed1ea..6895f1a461e31 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 17 +#define LIBAVCODEC_VERSION_MINOR 18 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavdevice/version.h b/libavdevice/version.h index d605427bcb4cf..dbfbfd069a53c 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVDEVICE_VERSION_MAJOR 58 -#define LIBAVDEVICE_VERSION_MINOR 2 +#define LIBAVDEVICE_VERSION_MINOR 3 #define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ diff --git a/libavfilter/version.h b/libavfilter/version.h index f2937225f512d..87468df539980 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 15 +#define LIBAVFILTER_VERSION_MINOR 16 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavformat/version.h b/libavformat/version.h index a96e13bc603e0..a0a26d536e4c3 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,8 +32,8 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 11 -#define LIBAVFORMAT_VERSION_MICRO 101 +#define LIBAVFORMAT_VERSION_MINOR 12 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ diff --git a/libavutil/version.h b/libavutil/version.h index d81d51011ba25..3a63e6355f84a 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 13 +#define LIBAVUTIL_VERSION_MINOR 14 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libpostproc/version.h b/libpostproc/version.h index 79eea7c248a08..c6772055afb8d 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -29,7 +29,7 @@ #include "libavutil/avutil.h" #define LIBPOSTPROC_VERSION_MAJOR 55 -#define LIBPOSTPROC_VERSION_MINOR 0 +#define LIBPOSTPROC_VERSION_MINOR 1 #define LIBPOSTPROC_VERSION_MICRO 100 #define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \ diff --git a/libswresample/version.h b/libswresample/version.h index 2640b10675948..efc462f46d5b6 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -29,8 +29,8 @@ #include "libavutil/avutil.h" #define LIBSWRESAMPLE_VERSION_MAJOR 3 -#define LIBSWRESAMPLE_VERSION_MINOR 0 -#define LIBSWRESAMPLE_VERSION_MICRO 101 +#define LIBSWRESAMPLE_VERSION_MINOR 1 +#define LIBSWRESAMPLE_VERSION_MICRO 100 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ LIBSWRESAMPLE_VERSION_MINOR, \ diff --git a/libswscale/version.h b/libswscale/version.h index edc133b2339e5..6d80527509fbd 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -27,8 +27,8 @@ #include "libavutil/version.h" #define LIBSWSCALE_VERSION_MAJOR 5 -#define LIBSWSCALE_VERSION_MINOR 0 -#define LIBSWSCALE_VERSION_MICRO 102 +#define LIBSWSCALE_VERSION_MINOR 1 +#define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ LIBSWSCALE_VERSION_MINOR, \ From 0564e8ee499533f204a838da58c139c9f0d2a384 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 12 Apr 2017 02:26:45 +0200 Subject: [PATCH 2483/2557] add release notes based on release 3.4 Name suggestion was from Kieran (cherry picked from commit b1ec41a64f2def0ce7d5b2b35d9ef478a4a35d26) Signed-off-by: Michael Niedermayer --- RELEASE_NOTES | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 RELEASE_NOTES diff --git a/RELEASE_NOTES b/RELEASE_NOTES new file mode 100644 index 0000000000000..7129a9d669a1d --- /dev/null +++ b/RELEASE_NOTES @@ -0,0 +1,15 @@ + + ┌───────────────────────────────────┐ + │ RELEASE NOTES for FFmpeg 4.0 "Wu" │ + └───────────────────────────────────┘ + + The FFmpeg Project proudly presents FFmpeg 4.0 "Wu", about 6 + months after the release of FFmpeg 3.4. + + A complete Changelog is available at the root of the project, and the + complete Git history on https://git.ffmpeg.org/gitweb/ffmpeg.git + + We hope you will like this release as much as we enjoyed working on it, and + as usual, if you have any questions about it, or any FFmpeg related topic, + feel free to join us on the #ffmpeg IRC channel (on irc.freenode.net) or ask + on the mailing-lists. From b42e135614df4b1f4cec312f7b3125a245b12b3a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 16 Apr 2018 12:42:29 +0200 Subject: [PATCH 2484/2557] Update bunch of versions to 4.0 Signed-off-by: Michael Niedermayer --- RELEASE | 2 +- doc/Doxyfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASE b/RELEASE index 9b601acc0df29..5186d07068cfe 100644 --- a/RELEASE +++ b/RELEASE @@ -1 +1 @@ -3.4.git +4.0 diff --git a/doc/Doxyfile b/doc/Doxyfile index 0891899505ce1..ccec314d3e40d 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = FFmpeg # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = +PROJECT_NUMBER = 4.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 From b6ec1812403547ba10dfb4c6be5ac276d19f4328 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 15 Apr 2018 20:33:37 -0300 Subject: [PATCH 2485/2557] configure: extend the check for bcrypt Some old mingw-w64 builds seem to provide an incomplete implementation of the API. Add an extra check to make sure it's disabled for those. Signed-off-by: James Almer (cherry picked from commit c04609eefce0183d460430f5014f7f8948170770) --- configure | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure b/configure index a6f32f8d9abf2..323a7dc0f6ff6 100755 --- a/configure +++ b/configure @@ -5828,7 +5828,8 @@ check_header asm/types.h check_builtin stdatomic stdatomic.h "atomic_int foo, bar = ATOMIC_VAR_INIT(-1); atomic_store(&foo, 0); foo += bar" check_lib advapi32 "windows.h" RegCloseKey -ladvapi32 -check_lib bcrypt "windows.h bcrypt.h" BCryptGenRandom -lbcrypt +check_lib bcrypt "windows.h bcrypt.h" BCryptGenRandom -lbcrypt && + check_cpp_condition bcrypt bcrypt.h "defined BCRYPT_RNG_ALGORITHM" check_lib ole32 "windows.h" CoTaskMemFree -lole32 check_lib shell32 "windows.h shellapi.h" CommandLineToArgvW -lshell32 check_lib psapi "windows.h psapi.h" GetProcessMemoryInfo -lpsapi From 6c95a26c1a5fd046d0479f9bcdc6e61b3b8d1adb Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 15 Apr 2018 21:33:44 -0300 Subject: [PATCH 2486/2557] avformat/movenc: forbid muxing AV1 streams until the spec is finished This prevents creating potentially broken files, as both the AV1 and the AV1 in ISOMBFF specs are unfinished. Signed-off-by: James Almer (cherry picked from commit 62bdbb5ce0c54b9f73c9b2580467ab1e6d76b70b) --- libavformat/movenc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index d03d7906a170f..dc5c842cb85a7 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -6081,6 +6081,10 @@ static int mov_init(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "VP9 only supported in MP4.\n"); return AVERROR(EINVAL); } + } else if (track->par->codec_id == AV_CODEC_ID_AV1) { + /* spec is not finished, so forbid for now */ + av_log(s, AV_LOG_ERROR, "AV1 muxing is currently not supported.\n"); + return AVERROR_PATCHWELCOME; } else if (track->par->codec_id == AV_CODEC_ID_VP8) { /* altref frames handling is not defined in the spec as of version v1.0, * so just forbid muxing VP8 streams altogether until a new version does */ From 9ef90ff0a2bf1684752ac81e527981f4a2219c13 Mon Sep 17 00:00:00 2001 From: Rodger Combs Date: Wed, 4 Apr 2018 01:17:24 -0300 Subject: [PATCH 2487/2557] avformat/flacenc: support writing attached pictures Usage of packet queueing API and some cleaning done by the committer. Signed-off-by: James Almer (cherry picked from commit 00d8598eba2e8dce31af250d6ecaec37254475aa) --- libavformat/flacenc.c | 278 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 242 insertions(+), 36 deletions(-) diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index b894f9ef614cb..3179f259e5d56 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -21,10 +21,13 @@ #include "libavutil/channel_layout.h" #include "libavutil/opt.h" +#include "libavutil/pixdesc.h" #include "libavcodec/flac.h" #include "avformat.h" #include "avio_internal.h" #include "flacenc.h" +#include "id3v2.h" +#include "internal.h" #include "vorbiscomment.h" #include "libavcodec/bytestream.h" @@ -33,8 +36,15 @@ typedef struct FlacMuxerContext { const AVClass *class; int write_header; + int audio_stream_idx; + int waiting_pics; + /* audio packets are queued here until we get all the attached pictures */ + AVPacketList *queue, *queue_end; + /* updated streaminfo sent by the encoder at the end */ uint8_t *streaminfo; + + unsigned attached_types; } FlacMuxerContext; static int flac_write_block_padding(AVIOContext *pb, unsigned int n_padding_bytes, @@ -74,31 +84,163 @@ static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m, return 0; } -static int flac_write_header(struct AVFormatContext *s) +static int flac_write_picture(struct AVFormatContext *s, AVPacket *pkt) { - int ret; - int padding = s->metadata_header_padding; - AVCodecParameters *par = s->streams[0]->codecpar; - FlacMuxerContext *c = s->priv_data; - - if (!c->write_header) + FlacMuxerContext *c = s->priv_data; + AVIOContext *pb = s->pb; + const AVPixFmtDescriptor *pixdesc; + const CodecMime *mime = ff_id3v2_mime_tags; + AVDictionaryEntry *e; + const char *mimetype = NULL, *desc = ""; + const AVStream *st = s->streams[pkt->stream_index]; + int i, mimelen, desclen, type = 0; + + if (!pkt->data) return 0; - if (s->nb_streams > 1) { - av_log(s, AV_LOG_ERROR, "only one stream is supported\n"); + while (mime->id != AV_CODEC_ID_NONE) { + if (mime->id == st->codecpar->codec_id) { + mimetype = mime->str; + break; + } + mime++; + } + if (!mimetype) { + av_log(s, AV_LOG_ERROR, "No mimetype is known for stream %d, cannot " + "write an attached picture.\n", st->index); + return AVERROR(EINVAL); + } + mimelen = strlen(mimetype); + + /* get the picture type */ + e = av_dict_get(st->metadata, "comment", NULL, 0); + for (i = 0; e && i < FF_ARRAY_ELEMS(ff_id3v2_picture_types); i++) { + if (!av_strcasecmp(e->value, ff_id3v2_picture_types[i])) { + type = i; + break; + } + } + + if ((c->attached_types & (1 << type)) & 0x6) { + av_log(s, AV_LOG_ERROR, "Duplicate attachment for type '%s'\n", ff_id3v2_picture_types[type]); return AVERROR(EINVAL); } - if (par->codec_id != AV_CODEC_ID_FLAC) { - av_log(s, AV_LOG_ERROR, "unsupported codec\n"); + + if (type == 1 && (st->codecpar->codec_id != AV_CODEC_ID_PNG || + st->codecpar->width != 32 || + st->codecpar->height != 32)) { + av_log(s, AV_LOG_ERROR, "File icon attachment must be a 32x32 PNG"); return AVERROR(EINVAL); } + c->attached_types |= (1 << type); + + /* get the description */ + if ((e = av_dict_get(st->metadata, "title", NULL, 0))) + desc = e->value; + desclen = strlen(desc); + + avio_w8(pb, 0x06); + avio_wb24(pb, 4 + 4 + mimelen + 4 + desclen + 4 + 4 + 4 + 4 + 4 + pkt->size); + + avio_wb32(pb, type); + + avio_wb32(pb, mimelen); + avio_write(pb, mimetype, mimelen); + + avio_wb32(pb, desclen); + avio_write(pb, desc, desclen); + + avio_wb32(pb, st->codecpar->width); + avio_wb32(pb, st->codecpar->height); + if ((pixdesc = av_pix_fmt_desc_get(st->codecpar->format))) + avio_wb32(pb, av_get_bits_per_pixel(pixdesc)); + else + avio_wb32(pb, 0); + avio_wb32(pb, 0); + + avio_wb32(pb, pkt->size); + avio_write(pb, pkt->data, pkt->size); + return 0; +} + +static int flac_finish_header(struct AVFormatContext *s) +{ + int i, ret, padding = s->metadata_header_padding; if (padding < 0) padding = 8192; /* The FLAC specification states that 24 bits are used to represent the * size of a metadata block so we must clip this value to 2^24-1. */ padding = av_clip_uintp2(padding, 24); + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + AVPacket *pkt = st->priv_data; + if (!pkt) + continue; + ret = flac_write_picture(s, pkt); + av_packet_unref(pkt); + if (ret < 0 && (s->error_recognition & AV_EF_EXPLODE)) + return ret; + } + + ret = flac_write_block_comment(s->pb, &s->metadata, !padding, + s->flags & AVFMT_FLAG_BITEXACT); + if (ret) + return ret; + + /* The command line flac encoder defaults to placing a seekpoint + * every 10s. So one might add padding to allow that later + * but there seems to be no simple way to get the duration here. + * So just add the amount requested by the user. */ + if (padding) + flac_write_block_padding(s->pb, padding, 1); + + return 0; +} + +static int flac_write_header(struct AVFormatContext *s) +{ + AVCodecParameters *par; + FlacMuxerContext *c = s->priv_data; + int ret, i; + + c->audio_stream_idx = -1; + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (c->audio_stream_idx >= 0 || st->codecpar->codec_id != AV_CODEC_ID_FLAC) { + av_log(s, AV_LOG_ERROR, "Invalid audio stream. Exactly one FLAC " + "audio stream is required.\n"); + return AVERROR(EINVAL); + } + par = s->streams[i]->codecpar; + c->audio_stream_idx = i; + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + if (!(st->disposition & AV_DISPOSITION_ATTACHED_PIC)) { + av_log(s, AV_LOG_WARNING, "Video stream #%d is not an attached picture. Ignoring\n", i); + continue; + } else if (st->codecpar->codec_id == AV_CODEC_ID_GIF) { + av_log(s, AV_LOG_ERROR, "GIF image support is not implemented.\n"); + return AVERROR_PATCHWELCOME; + } else if (!c->write_header) { + av_log(s, AV_LOG_ERROR, "Can't write attached pictures without a header.\n"); + return AVERROR(EINVAL); + } + c->waiting_pics++; + } else { + av_log(s, AV_LOG_ERROR, "Only audio streams and pictures are allowed in FLAC.\n"); + return AVERROR(EINVAL); + } + } + if (c->audio_stream_idx < 0) { + av_log(s, AV_LOG_ERROR, "No audio stream present.\n"); + return AVERROR(EINVAL); + } + + if (!c->write_header) + return 0; + ret = ff_flac_write_header(s->pb, par->extradata, par->extradata_size, 0); if (ret) @@ -121,18 +263,51 @@ static int flac_write_header(struct AVFormatContext *s) } } - ret = flac_write_block_comment(s->pb, &s->metadata, !padding, - s->flags & AVFMT_FLAG_BITEXACT); - if (ret) - return ret; + if (!c->waiting_pics) + ret = flac_finish_header(s); - /* The command line flac encoder defaults to placing a seekpoint - * every 10s. So one might add padding to allow that later - * but there seems to be no simple way to get the duration here. - * So just add the amount requested by the user. */ - if (padding) - flac_write_block_padding(s->pb, padding, 1); + return ret; +} + +static int flac_write_audio_packet(struct AVFormatContext *s, AVPacket *pkt) +{ + FlacMuxerContext *c = s->priv_data; + uint8_t *streaminfo; + int streaminfo_size; + + /* check for updated streaminfo */ + streaminfo = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, + &streaminfo_size); + if (streaminfo && streaminfo_size == FLAC_STREAMINFO_SIZE) { + av_freep(&c->streaminfo); + + c->streaminfo = av_malloc(FLAC_STREAMINFO_SIZE); + if (!c->streaminfo) + return AVERROR(ENOMEM); + memcpy(c->streaminfo, streaminfo, FLAC_STREAMINFO_SIZE); + } + if (pkt->size) + avio_write(s->pb, pkt->data, pkt->size); + return 0; +} + +static int flac_queue_flush(AVFormatContext *s) +{ + FlacMuxerContext *c = s->priv_data; + AVPacket pkt; + int ret, write = 1; + + ret = flac_finish_header(s); + if (ret < 0) + write = 0; + + while (c->queue) { + ff_packet_list_get(&c->queue, &c->queue_end, &pkt); + if (write && (ret = flac_write_audio_packet(s, &pkt)) < 0) + write = 0; + av_packet_unref(&pkt); + } return ret; } @@ -142,7 +317,13 @@ static int flac_write_trailer(struct AVFormatContext *s) int64_t file_size; FlacMuxerContext *c = s->priv_data; uint8_t *streaminfo = c->streaminfo ? c->streaminfo : - s->streams[0]->codecpar->extradata; + s->streams[c->audio_stream_idx]->codecpar->extradata; + + if (c->waiting_pics) { + av_log(s, AV_LOG_WARNING, "No packets were sent for some of the " + "attached pictures.\n"); + flac_queue_flush(s); + } if (!c->write_header || !streaminfo) return 0; @@ -166,23 +347,48 @@ static int flac_write_trailer(struct AVFormatContext *s) static int flac_write_packet(struct AVFormatContext *s, AVPacket *pkt) { FlacMuxerContext *c = s->priv_data; - uint8_t *streaminfo; - int streaminfo_size; + int ret; - /* check for updated streaminfo */ - streaminfo = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, - &streaminfo_size); - if (streaminfo && streaminfo_size == FLAC_STREAMINFO_SIZE) { - av_freep(&c->streaminfo); + if (pkt->stream_index == c->audio_stream_idx) { + if (c->waiting_pics) { + /* buffer audio packets until we get all the pictures */ + ret = ff_packet_list_put(&c->queue, &c->queue_end, pkt, FF_PACKETLIST_FLAG_REF_PACKET); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Out of memory in packet queue; skipping attached pictures\n"); + c->waiting_pics = 0; + ret = flac_queue_flush(s); + if (ret < 0) + return ret; + return flac_write_audio_packet(s, pkt); + } + } else + return flac_write_audio_packet(s, pkt); + } else { + AVStream *st = s->streams[pkt->stream_index]; - c->streaminfo = av_malloc(FLAC_STREAMINFO_SIZE); - if (!c->streaminfo) - return AVERROR(ENOMEM); - memcpy(c->streaminfo, streaminfo, FLAC_STREAMINFO_SIZE); + if (!c->waiting_pics || + !(st->disposition & AV_DISPOSITION_ATTACHED_PIC)) + return 0; + + /* warn only once for each stream */ + if (st->nb_frames == 1) { + av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d," + " ignoring.\n", pkt->stream_index); + } + if (st->nb_frames >= 1) + return 0; + + st->priv_data = av_packet_clone(pkt); + if (!st->priv_data) + av_log(s, AV_LOG_ERROR, "Out of memory queueing an attached picture; skipping\n"); + c->waiting_pics--; + + /* flush the buffered audio packets */ + if (!c->waiting_pics && + (ret = flac_queue_flush(s)) < 0) + return ret; } - if (pkt->size) - avio_write(s->pb, pkt->data, pkt->size); return 0; } @@ -205,7 +411,7 @@ AVOutputFormat ff_flac_muxer = { .mime_type = "audio/x-flac", .extensions = "flac", .audio_codec = AV_CODEC_ID_FLAC, - .video_codec = AV_CODEC_ID_NONE, + .video_codec = AV_CODEC_ID_PNG, .write_header = flac_write_header, .write_packet = flac_write_packet, .write_trailer = flac_write_trailer, From 7e11a861755dfa37043c0a9fc800cf7db3f4f7da Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 16 Apr 2018 12:44:35 -0300 Subject: [PATCH 2488/2557] avformat/flacenc: add flac_init() Signed-off-by: James Almer (cherry picked from commit 6838359448faeceb4830e7a1cf3ca6e36fb7e4a7) --- libavformat/flacenc.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index 3179f259e5d56..617bccdc84a88 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -199,11 +199,11 @@ static int flac_finish_header(struct AVFormatContext *s) return 0; } -static int flac_write_header(struct AVFormatContext *s) +static int flac_init(struct AVFormatContext *s) { AVCodecParameters *par; FlacMuxerContext *c = s->priv_data; - int ret, i; + int i; c->audio_stream_idx = -1; for (i = 0; i < s->nb_streams; i++) { @@ -238,14 +238,6 @@ static int flac_write_header(struct AVFormatContext *s) return AVERROR(EINVAL); } - if (!c->write_header) - return 0; - - ret = ff_flac_write_header(s->pb, par->extradata, - par->extradata_size, 0); - if (ret) - return ret; - /* add the channel layout tag */ if (par->channel_layout && !(par->channel_layout & ~0x3ffffULL) && @@ -263,6 +255,23 @@ static int flac_write_header(struct AVFormatContext *s) } } + return 0; +} + +static int flac_write_header(struct AVFormatContext *s) +{ + FlacMuxerContext *c = s->priv_data; + AVCodecParameters *par = s->streams[c->audio_stream_idx]->codecpar; + int ret; + + if (!c->write_header) + return 0; + + ret = ff_flac_write_header(s->pb, par->extradata, + par->extradata_size, 0); + if (ret < 0) + return ret; + if (!c->waiting_pics) ret = flac_finish_header(s); @@ -412,6 +421,7 @@ AVOutputFormat ff_flac_muxer = { .extensions = "flac", .audio_codec = AV_CODEC_ID_FLAC, .video_codec = AV_CODEC_ID_PNG, + .init = flac_init, .write_header = flac_write_header, .write_packet = flac_write_packet, .write_trailer = flac_write_trailer, From 9c787a21ce91349a97dd87b108839b1d13035cbd Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Mon, 16 Apr 2018 22:35:23 +0200 Subject: [PATCH 2489/2557] configure: add nvcc to CMDLINE_SET This was somehow forgotten and nobody noticed until now. --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 323a7dc0f6ff6..535a59b7376c5 100755 --- a/configure +++ b/configure @@ -2372,6 +2372,7 @@ CMDLINE_SET=" malloc_prefix nm optflags + nvcc nvccflags pkg_config pkg_config_flags From de253343c151e0ba752f91088ab1aa87f50e1590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Thu, 12 Apr 2018 11:07:36 +0300 Subject: [PATCH 2490/2557] ffprobe: report unavailable SAR correctly in stream info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit av_guess_sample_aspect_ratio() will return undefined or missing value as {0,1}. This fixes show_stream() to check numerator to display 'N/A' when appropriate. show_frame() does this already correctly. Signed-off-by: Timo Teräs (cherry picked from commit c663dce031b3973e37c83ae1818f1484e1cf482c) --- fftools/ffprobe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 82dfe4f58ae8f..8b2a18b6b12b0 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -2521,7 +2521,7 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id #endif print_int("has_b_frames", par->video_delay); sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL); - if (sar.den) { + if (sar.num) { print_q("sample_aspect_ratio", sar, ':'); av_reduce(&dar.num, &dar.den, par->width * sar.num, From ca85c3cd7d645f2568ebf28d3ddf436cbeb1743e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Sat, 14 Apr 2018 21:32:11 +0300 Subject: [PATCH 2491/2557] avformat/movenc: support writing iTunes cover image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes https://trac.ffmpeg.org/ticket/2798 This makes movenc handle AV_DISPOSITION_ATTACHED_PIC and write the associated pictures in iTunes cover atom. This corresponds to how 'mov' demuxer parses and exposes the cover images when reading. Most of the existing track handling loops properly ignore these 'virtual streams' as MOVTrack->entry is never incremented for them. However, additional tests are added as needed to ignore them. Tested to produce valid output with: ffmpeg -i movie.mp4 -i thumb.jpg -disposition:v:1 attached_pic \ -map 0 -map 1 -c copy movie-with-cover.mp4 The cover image is also copied correctly with: ffmpeg -i movie-with-cover.mp4 -map 0 -c copy out.mp4 AtomicParseley says that the attached_pic stream is properly not visible in the main tracks of the file. Signed-off-by: Timo Teräs (cherry picked from commit 9af71b326fda1c6f32a26d465f7740110113e759) --- libavformat/movenc.c | 88 +++++++++++++++++++++++++++++++++++++++++--- libavformat/movenc.h | 1 + 2 files changed, 84 insertions(+), 5 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index dc5c842cb85a7..0b44fd66ea1f3 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -142,7 +142,9 @@ static int co64_required(const MOVTrack *track) static int rtp_hinting_needed(const AVStream *st) { - /* Add hint tracks for each audio and video stream */ + /* Add hint tracks for each real audio and video stream */ + if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) + return 0; return st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO; } @@ -3420,6 +3422,51 @@ static int mov_write_int8_metadata(AVFormatContext *s, AVIOContext *pb, return size; } +static int mov_write_covr(AVIOContext *pb, AVFormatContext *s) +{ + MOVMuxContext *mov = s->priv_data; + int64_t pos = 0; + int i, type; + + for (i = 0; i < s->nb_streams; i++) { + MOVTrack *trk = &mov->tracks[i]; + AVStream *st = s->streams[i]; + + if (!(st->disposition & AV_DISPOSITION_ATTACHED_PIC) || + trk->cover_image.size <= 0) + continue; + + switch (st->codecpar->codec_id) { + case AV_CODEC_ID_MJPEG: + type = 0xD; + break; + case AV_CODEC_ID_PNG: + type = 0xE; + break; + case AV_CODEC_ID_BMP: + type = 0x1B; + break; + default: + av_log(s, AV_LOG_ERROR, "unsupported codec_id (0x%x) for cover", + st->codecpar->codec_id); + continue; + } + + if (!pos) { + pos = avio_tell(pb); + avio_wb32(pb, 0); + ffio_wfourcc(pb, "covr"); + } + avio_wb32(pb, 16 + trk->cover_image.size); + ffio_wfourcc(pb, "data"); + avio_wb32(pb, type); + avio_wb32(pb , 0); + avio_write(pb, trk->cover_image.data, trk->cover_image.size); + } + + return pos ? update_size(pb, pos) : 0; +} + /* iTunes meta data list */ static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s) @@ -3454,6 +3501,7 @@ static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov, mov_write_int8_metadata (s, pb, "hdvd", "hd_video", 1); mov_write_int8_metadata (s, pb, "pgap", "gapless_playback",1); mov_write_int8_metadata (s, pb, "cpil", "compilation", 1); + mov_write_covr(pb, s); mov_write_trkn_tag(pb, mov, s, 0); // track number mov_write_trkn_tag(pb, mov, s, 1); // disc number mov_write_tmpo_tag(pb, s); @@ -3951,6 +3999,8 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormat } else { continue; } + if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) + continue; props = (AVCPBProperties*)av_stream_get_side_data(track->st, AV_PKT_DATA_CPB_PROPERTIES, NULL); @@ -4564,6 +4614,8 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; + if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) + continue; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) has_video = 1; if (st->codecpar->codec_id == AV_CODEC_ID_H264) @@ -4712,6 +4764,8 @@ static int mov_write_identification(AVIOContext *pb, AVFormatContext *s) int video_streams_nb = 0, audio_streams_nb = 0, other_streams_nb = 0; for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; + if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) + continue; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) video_streams_nb++; else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) @@ -4901,7 +4955,8 @@ static int mov_flush_fragment(AVFormatContext *s, int force) int buf_size, moov_size; for (i = 0; i < mov->nb_streams; i++) - if (!mov->tracks[i].entry) + if (!mov->tracks[i].entry && + (i >= s->nb_streams || !(s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC))) break; /* Don't write the initial moov unless all tracks have data */ if (i < mov->nb_streams && !force) @@ -5480,13 +5535,34 @@ static int mov_write_subtitle_end_packet(AVFormatContext *s, static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) { + MOVMuxContext *mov = s->priv_data; + MOVTrack *trk; + AVStream *st; + if (!pkt) { mov_flush_fragment(s, 1); return 1; + } + + st = s->streams[pkt->stream_index]; + trk = &mov->tracks[pkt->stream_index]; + + if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) { + int ret; + + if (st->nb_frames >= 1) { + if (st->nb_frames == 1) + av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d," + " ignoring.\n", pkt->stream_index); + return 0; + } + + if ((ret = av_packet_ref(&trk->cover_image, pkt)) < 0) + return ret; + + return 0; } else { int i; - MOVMuxContext *mov = s->priv_data; - MOVTrack *trk = &mov->tracks[pkt->stream_index]; if (!pkt->size) return mov_write_single_packet(s, pkt); /* Passthrough. */ @@ -5733,7 +5809,8 @@ static void enable_tracks(AVFormatContext *s) AVStream *st = s->streams[i]; if (st->codecpar->codec_type <= AVMEDIA_TYPE_UNKNOWN || - st->codecpar->codec_type >= AVMEDIA_TYPE_NB) + st->codecpar->codec_type >= AVMEDIA_TYPE_NB || + st->disposition & AV_DISPOSITION_ATTACHED_PIC) continue; if (first[st->codecpar->codec_type] < 0) @@ -5776,6 +5853,7 @@ static void mov_free(AVFormatContext *s) av_freep(&mov->tracks[i].par); av_freep(&mov->tracks[i].cluster); av_freep(&mov->tracks[i].frag_info); + av_packet_unref(&mov->tracks[i].cover_image); if (mov->tracks[i].vos_len) av_freep(&mov->tracks[i].vos_data); diff --git a/libavformat/movenc.h b/libavformat/movenc.h index ca2a9c97226b8..c9b4072fb9d11 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -132,6 +132,7 @@ typedef struct MOVTrack { uint32_t default_size; HintSampleQueue sample_queue; + AVPacket cover_image; AVIOContext *mdat_buf; int64_t data_offset; From d52676da38025b78ca332e0a3d7bdb8e6fb2150d Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 18 Apr 2018 15:19:40 -0300 Subject: [PATCH 2492/2557] avdevice/iec61883: return reference counted packets Fixes part of ticket #7146, dealing with leaks of packet data since commit 87c88122703f2befcf96383d05bdf14373c22df9. Signed-off-by: James Almer (cherry picked from commit b8629654c6460a28c507f816a977914e3a6f2520) --- libavdevice/iec61883.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/libavdevice/iec61883.c b/libavdevice/iec61883.c index 7d4d37847cba7..b09929eb56e1b 100644 --- a/libavdevice/iec61883.c +++ b/libavdevice/iec61883.c @@ -118,7 +118,7 @@ static int iec61883_callback(unsigned char *data, int length, goto exit; } - packet->buf = av_malloc(length); + packet->buf = av_malloc(length + AV_INPUT_BUFFER_PADDING_SIZE); if (!packet->buf) { av_free(packet); ret = -1; @@ -127,6 +127,7 @@ static int iec61883_callback(unsigned char *data, int length, packet->len = length; memcpy(packet->buf, data, length); + memset(packet->buf + length, 0, AV_INPUT_BUFFER_PADDING_SIZE); if (dv->queue_first) { dv->queue_last->next = packet; @@ -200,13 +201,21 @@ static int iec61883_parse_queue_dv(struct iec61883_data *dv, AVPacket *pkt) size = avpriv_dv_produce_packet(dv->dv_demux, pkt, packet->buf, packet->len, -1); dv->queue_first = packet->next; + if (size < 0) + av_free(packet->buf); av_free(packet); dv->packets--; - if (size > 0) - return size; + if (size < 0) + return -1; - return -1; + if (av_packet_from_data(pkt, pkt->data, pkt->size) < 0) { + av_freep(&pkt->data); + av_packet_unref(pkt); + return -1; + } + + return size; } static int iec61883_parse_queue_hdv(struct iec61883_data *dv, AVPacket *pkt) From d9e9e97e5f477f6cb42d916f41b436d269cb71c8 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 18 Apr 2018 15:32:10 -0300 Subject: [PATCH 2493/2557] avdevice/iec61883: free the private context at the end Fixes part of ticket #7146. Signed-off-by: James Almer (cherry picked from commit 5079e96bcc7aaa9cae82a58397ce986e124028e4) --- libavdevice/iec61883.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavdevice/iec61883.c b/libavdevice/iec61883.c index b09929eb56e1b..dcf755392675a 100644 --- a/libavdevice/iec61883.c +++ b/libavdevice/iec61883.c @@ -463,6 +463,7 @@ static int iec61883_close(AVFormatContext *context) } else { iec61883_dv_fb_stop(dv->iec61883_dv); iec61883_dv_fb_close(dv->iec61883_dv); + av_freep(&dv->dv_demux); } while (dv->queue_first) { DVPacket *packet = dv->queue_first; From a73b464118a71483241d3120c05e2b3bd871bb44 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 18 Apr 2018 16:33:13 +0200 Subject: [PATCH 2494/2557] configure: fix clang-cl check in the MSVC section Without properly grouping the checks, the second test would execute for MSVC cl.exe, which results in configure getting stuck since cl.exe -? is an interactive paginated help screen, waiting for input. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 535a59b7376c5..dee507cb6ae29 100755 --- a/configure +++ b/configure @@ -4411,7 +4411,7 @@ probe_cc(){ _flags_filter=msvc_flags _ld_lib='lib%.a' _ld_path='-libpath:' - elif $_cc -nologo- 2>&1 | grep -q Microsoft || $_cc -v 2>&1 | grep -q clang && $_cc -? > /dev/null 2>&1; then + elif $_cc -nologo- 2>&1 | grep -q Microsoft || { $_cc -v 2>&1 | grep -q clang && $_cc -? > /dev/null 2>&1; }; then _type=msvc _ident=$($_cc 2>&1 | head -n1 | tr -d '\r') _DEPCMD='$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< 2>&1 | awk '\''/including/ { sub(/^.*file: */, ""); gsub(/\\/, "/"); if (!match($$0, / /)) print "$@:", $$0 }'\'' > $(@:.o=.d)' From 0b6de235b98ca3076e85adebc922b25df79080b7 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 18 Apr 2018 14:09:19 +0200 Subject: [PATCH 2495/2557] avformat/tls_schannel: fix handling of EOF after avio changes (cherry picked from commit 5c6365af454fb24f20d753ed99dd8e2b60e85035) --- libavformat/tls_schannel.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavformat/tls_schannel.c b/libavformat/tls_schannel.c index 9a6e0c92e37af..f41b007773f17 100644 --- a/libavformat/tls_schannel.c +++ b/libavformat/tls_schannel.c @@ -413,11 +413,13 @@ static int tls_read(URLContext *h, uint8_t *buf, int len) ret = ffurl_read(s->tcp, c->enc_buf + c->enc_buf_offset, c->enc_buf_size - c->enc_buf_offset); - if (ret < 0) { + if (ret == AVERROR_EOF) { + c->connection_closed = 1; + ret = 0; + } else if (ret < 0) { av_log(h, AV_LOG_ERROR, "Unable to read from socket\n"); return ret; - } else if (ret == 0) - c->connection_closed = 1; + } c->enc_buf_offset += ret; } @@ -515,7 +517,7 @@ static int tls_read(URLContext *h, uint8_t *buf, int len) if (ret == 0 && !c->connection_closed) ret = AVERROR(EAGAIN); - return ret < 0 ? ret : 0; + return ret < 0 ? ret : AVERROR_EOF; } static int tls_write(URLContext *h, const uint8_t *buf, int len) From 9b7111424797e458aa51f7569dc132d44b18fd79 Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Wed, 11 Apr 2018 10:28:56 +0200 Subject: [PATCH 2496/2557] avcodec/mediacodecdec_common: make stride and slice-height non-mandatory fields Fixes decoding on the Samsung Chromebook Pro which do not set the codec output format stride and slice-height fields. (cherry picked from commit 67d0911f27e29d551865dbca3af5c49abe029885) --- libavcodec/mediacodecdec_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index e31adb487c964..e59cf19aad8a0 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -385,10 +385,10 @@ static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecConte AMEDIAFORMAT_GET_INT32(s->width, "width", 1); AMEDIAFORMAT_GET_INT32(s->height, "height", 1); - AMEDIAFORMAT_GET_INT32(s->stride, "stride", 1); + AMEDIAFORMAT_GET_INT32(s->stride, "stride", 0); s->stride = s->stride > 0 ? s->stride : s->width; - AMEDIAFORMAT_GET_INT32(s->slice_height, "slice-height", 1); + AMEDIAFORMAT_GET_INT32(s->slice_height, "slice-height", 0); s->slice_height = s->slice_height > 0 ? s->slice_height : s->height; if (strstr(s->codec_name, "OMX.Nvidia.")) { From 860293a9a29b7b22d87cc68680bc20f0ad770283 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 16 Apr 2018 18:23:12 +0200 Subject: [PATCH 2497/2557] doc/APIchanges: Fix typos in hashes Thanks-to: Moritz Barsnick for finding the correct ones Signed-off-by: Michael Niedermayer (cherry picked from commit ec8a5262b03f85158d722dbc8b8f30cb6bd67e0f) Signed-off-by: Michael Niedermayer --- doc/APIchanges | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 2deef49edb642..4f6ac2a031f0e 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -889,7 +889,7 @@ API changes, most recent first: Add av_opt_get_dict_val/set_dict_val with AV_OPT_TYPE_DICT to support dictionary types being set as options. -2014-08-13 - afbd4b8 - lavf 56.01.0 - avformat.h +2014-08-13 - afbd4b7e09 - lavf 56.01.0 - avformat.h Add AVFormatContext.event_flags and AVStream.event_flags for signaling to the user when events happen in the file/stream. @@ -906,7 +906,7 @@ API changes, most recent first: 2014-08-08 - 5c3c671 - lavf 55.53.100 - avio.h Add avio_feof() and deprecate url_feof(). -2014-08-07 - bb78903 - lsws 2.1.3 - swscale.h +2014-08-07 - bb789016d4 - lsws 2.1.3 - swscale.h sws_getContext is not going to be removed in the future. 2014-08-07 - a561662 / ad1ee5f - lavc 55.73.101 / 55.57.3 - avcodec.h From ef99025603913c3dcd6c716f308b83cbf7077ef7 Mon Sep 17 00:00:00 2001 From: Rahul Chaudhry Date: Wed, 18 Apr 2018 16:29:39 -0700 Subject: [PATCH 2498/2557] swresample/arm: remove unintentional relocation. Branch to global symbol results in reference to PLT, and when compiling for THUMB-2 - in a R_ARM_THM_JUMP19 relocation. Some linkers don't support this relocation (ld.gold), while others can end up truncating the relocation to fit (ld.bfd). Convert this branch through PLT into a direct branch that the assembler can resolve locally. See https://github.com/android-ndk/ndk/issues/337 for background. The current workaround is to disable neon during gstreamer build, which is not optimal and can be reverted after this patch: https://github.com/freedesktop/gstreamer-cerbero/commit/41556c415739fbc3a72c7eaee7e70a565b719b2f Signed-off-by: Michael Niedermayer (cherry picked from commit b22db4f465c9adb2cf1489e04f7b65ef6bb55b8b) Signed-off-by: Michael Niedermayer --- libswresample/arm/audio_convert_neon.S | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libswresample/arm/audio_convert_neon.S b/libswresample/arm/audio_convert_neon.S index 1f88316ddec83..7729514701d3a 100644 --- a/libswresample/arm/audio_convert_neon.S +++ b/libswresample/arm/audio_convert_neon.S @@ -22,6 +22,7 @@ #include "libavutil/arm/asm.S" function swri_oldapi_conv_flt_to_s16_neon, export=1 +_swri_oldapi_conv_flt_to_s16_neon: subs r2, r2, #8 vld1.32 {q0}, [r1,:128]! vcvt.s32.f32 q8, q0, #31 @@ -66,6 +67,7 @@ function swri_oldapi_conv_flt_to_s16_neon, export=1 endfunc function swri_oldapi_conv_fltp_to_s16_2ch_neon, export=1 +_swri_oldapi_conv_fltp_to_s16_2ch_neon: ldm r1, {r1, r3} subs r2, r2, #8 vld1.32 {q0}, [r1,:128]! @@ -133,8 +135,8 @@ function swri_oldapi_conv_fltp_to_s16_nch_neon, export=1 cmp r3, #2 itt lt ldrlt r1, [r1] - blt X(swri_oldapi_conv_flt_to_s16_neon) - beq X(swri_oldapi_conv_fltp_to_s16_2ch_neon) + blt _swri_oldapi_conv_flt_to_s16_neon + beq _swri_oldapi_conv_fltp_to_s16_2ch_neon push {r4-r8, lr} cmp r3, #4 From df56bc18efd2afb10e1751e6be1f731d3da54786 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 17 Apr 2018 02:13:42 +0200 Subject: [PATCH 2499/2557] avcodec/cinepak: move some checks prior to frame allocation Speeds up decoding from 8 to 3 seconds for 6302/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_CINEPAK_fuzzer-5626371985375232 Fixes: Timeout Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 2324ef1ff32e5effd6f295bca80580ae4816be0b) Signed-off-by: Michael Niedermayer --- libavcodec/cinepak.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/libavcodec/cinepak.c b/libavcodec/cinepak.c index 89e940ae0dfbd..ba0589582fe59 100644 --- a/libavcodec/cinepak.c +++ b/libavcodec/cinepak.c @@ -315,14 +315,11 @@ static int cinepak_decode_strip (CinepakContext *s, return AVERROR_INVALIDDATA; } -static int cinepak_decode (CinepakContext *s) +static int cinepak_predecode_check (CinepakContext *s) { - const uint8_t *eod = (s->data + s->size); - int i, result, strip_size, frame_flags, num_strips; - int y0 = 0; + int num_strips; int encoded_buf_size; - frame_flags = s->data[0]; num_strips = AV_RB16 (&s->data[8]); encoded_buf_size = AV_RB24(&s->data[1]); @@ -353,6 +350,21 @@ static int cinepak_decode (CinepakContext *s) s->sega_film_skip_bytes = 0; } + if (s->size < 10 + s->sega_film_skip_bytes + num_strips * 12) + return AVERROR_INVALIDDATA; + + return 0; +} + +static int cinepak_decode (CinepakContext *s) +{ + const uint8_t *eod = (s->data + s->size); + int i, result, strip_size, frame_flags, num_strips; + int y0 = 0; + + frame_flags = s->data[0]; + num_strips = AV_RB16 (&s->data[8]); + s->data += 10 + s->sega_film_skip_bytes; num_strips = FFMIN(num_strips, MAX_STRIPS); @@ -439,6 +451,11 @@ static int cinepak_decode_frame(AVCodecContext *avctx, if (s->size < 10) return AVERROR_INVALIDDATA; + if ((ret = cinepak_predecode_check(s)) < 0) { + av_log(avctx, AV_LOG_ERROR, "cinepak_predecode_check failed\n"); + return ret; + } + if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) return ret; From ecb375684d7b5a29ee208977259ffd65b951015f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 17 Apr 2018 02:13:43 +0200 Subject: [PATCH 2500/2557] avcodec/cinepak: Skip empty frames Speeds up decoding from 3 to 0.1 seconds for 6302/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_CINEPAK_fuzzer-5626371985375232 Fixes: Timeout Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 9033920bec9ccf17de205fc17c2b330906b200f5) Signed-off-by: Michael Niedermayer --- libavcodec/cinepak.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/cinepak.c b/libavcodec/cinepak.c index ba0589582fe59..9b0077402f063 100644 --- a/libavcodec/cinepak.c +++ b/libavcodec/cinepak.c @@ -444,6 +444,7 @@ static int cinepak_decode_frame(AVCodecContext *avctx, const uint8_t *buf = avpkt->data; int ret = 0, buf_size = avpkt->size; CinepakContext *s = avctx->priv_data; + int num_strips; s->data = buf; s->size = buf_size; @@ -451,6 +452,12 @@ static int cinepak_decode_frame(AVCodecContext *avctx, if (s->size < 10) return AVERROR_INVALIDDATA; + num_strips = AV_RB16 (&s->data[8]); + + //Empty frame, do not waste time + if (!num_strips && (!s->palette_video || !av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL))) + return buf_size; + if ((ret = cinepak_predecode_check(s)) < 0) { av_log(avctx, AV_LOG_ERROR, "cinepak_predecode_check failed\n"); return ret; From 5888679ae331fe122b4ab3cffb78f032cde96049 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 16 Apr 2018 22:04:53 +0200 Subject: [PATCH 2501/2557] avcodec/dfa: Check dimension against maximum The headers from where the dimensions are read in actual files are limited to 16bit per component. Fixes: Timeout Fixes: 6305/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_DFA_fuzzer-4824270749302784 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 9d5a4fcfbb51edc871bdb1c67a88223cbfb1c0e4) Signed-off-by: Michael Niedermayer --- libavcodec/dfa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/dfa.c b/libavcodec/dfa.c index 536040d65c9b8..970175fb73468 100644 --- a/libavcodec/dfa.c +++ b/libavcodec/dfa.c @@ -41,7 +41,7 @@ static av_cold int dfa_decode_init(AVCodecContext *avctx) avctx->pix_fmt = AV_PIX_FMT_PAL8; - if (!avctx->width || !avctx->height) + if (!avctx->width || !avctx->height || FFMAX(avctx->width, avctx->height) >= (1<<16)) return AVERROR_INVALIDDATA; av_assert0(av_image_check_size(avctx->width, avctx->height, 0, avctx) >= 0); From bfe61bbd0076499f82b580557bb1f355f36c9c37 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 16 Apr 2018 22:28:23 +0200 Subject: [PATCH 2502/2557] avcodec/dsicinvideo: Propagate errors from cin_decode_rle() Signed-off-by: Michael Niedermayer (cherry picked from commit 942217b153a9bff2d17463957abd772fcd72b400) Signed-off-by: Michael Niedermayer --- libavcodec/dsicinvideo.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/libavcodec/dsicinvideo.c b/libavcodec/dsicinvideo.c index f95cbc74a0743..add7afa383170 100644 --- a/libavcodec/dsicinvideo.c +++ b/libavcodec/dsicinvideo.c @@ -226,27 +226,35 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, * surface.width = surface.pitch */ switch (bitmap_frame_type) { case 9: - cin_decode_rle(buf, bitmap_frame_size, + res = cin_decode_rle(buf, bitmap_frame_size, cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); + if (res < 0) + return res; break; case 34: - cin_decode_rle(buf, bitmap_frame_size, + res = cin_decode_rle(buf, bitmap_frame_size, cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); + if (res < 0) + return res; cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP], cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); break; case 35: bitmap_frame_size = cin_decode_huffman(buf, bitmap_frame_size, cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size); - cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size, + res = cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size, cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); + if (res < 0) + return res; break; case 36: bitmap_frame_size = cin_decode_huffman(buf, bitmap_frame_size, cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size); - cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size, + res = cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size, cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); + if (res < 0) + return res; cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP], cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); break; From 66bdf8f145937576eb8b2c3a73dcbbd1846eb048 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 16 Apr 2018 22:29:09 +0200 Subject: [PATCH 2503/2557] avcodec/dsicinvideo: Fail if there is only a small fraction of the data available that comprises a full frame Fixes: Timeout Fixes: 6306/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_DSICINVIDEO_fuzzer-5079253549842432 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 5549488bbf3a23c0fb9833cefc6354f97055dd96) Signed-off-by: Michael Niedermayer --- libavcodec/dsicinvideo.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/dsicinvideo.c b/libavcodec/dsicinvideo.c index add7afa383170..aa080417d25f1 100644 --- a/libavcodec/dsicinvideo.c +++ b/libavcodec/dsicinvideo.c @@ -158,6 +158,9 @@ static int cin_decode_lzss(const unsigned char *src, int src_size, } } + if (dst_end - dst > dst_size - dst_size/10) + return AVERROR_INVALIDDATA; + return 0; } @@ -184,6 +187,10 @@ static int cin_decode_rle(const unsigned char *src, int src_size, } dst += len; } + + if (dst_end - dst > dst_size - dst_size/10) + return AVERROR_INVALIDDATA; + return 0; } From bc2ceeb3ac346ada448f3c9b89b4aecb084571f5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 19 Apr 2018 23:28:26 +0200 Subject: [PATCH 2504/2557] avcodec/opusenc_psy: Fix warning: ISO C90 forbids mixed declarations and code Signed-off-by: Michael Niedermayer (cherry picked from commit f8b17fe33233237eea304d4fb0636539a131c1b2) Signed-off-by: Michael Niedermayer --- libavcodec/opusenc_psy.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavcodec/opusenc_psy.c b/libavcodec/opusenc_psy.c index 8aded2140de15..5a50db942f731 100644 --- a/libavcodec/opusenc_psy.c +++ b/libavcodec/opusenc_psy.c @@ -399,13 +399,12 @@ static void celt_search_for_intensity(OpusPsyContext *s, CeltFrame *f) { int i, best_band = CELT_MAX_BANDS - 1; float dist, best_dist = FLT_MAX; + /* TODO: fix, make some heuristic up here using the lambda value */ + float end_band = 0; if (s->avctx->channels < 2) return; - /* TODO: fix, make some heuristic up here using the lambda value */ - float end_band = 0; - for (i = f->end_band; i >= end_band; i--) { f->intensity_stereo = i; bands_dist(s, f, &dist); From e36830c6959d286f5d55d374119a4a30ca8fad83 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 19 Apr 2018 23:32:07 +0200 Subject: [PATCH 2505/2557] avcodec/sbc: Fix non static function prefix Signed-off-by: Michael Niedermayer (cherry picked from commit 9f1b99e7d076c9de1fefe971f1c70c96ebcf071b) Signed-off-by: Michael Niedermayer --- libavcodec/sbc.c | 2 +- libavcodec/sbc.h | 2 +- libavcodec/sbcdec.c | 2 +- libavcodec/sbcenc.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/sbc.c b/libavcodec/sbc.c index f7dba79f4fe90..b43b66e3f5192 100644 --- a/libavcodec/sbc.c +++ b/libavcodec/sbc.c @@ -52,7 +52,7 @@ static const int sbc_offset8[4][8] = { /* * Calculates the CRC-8 of the first len bits in data */ -uint8_t sbc_crc8(const AVCRC *ctx, const uint8_t *data, size_t len) +uint8_t ff_sbc_crc8(const AVCRC *ctx, const uint8_t *data, size_t len) { size_t byte_length = len >> 3; int bit_length = len & 7; diff --git a/libavcodec/sbc.h b/libavcodec/sbc.h index 405fadc3a6205..de9c8d9aed352 100644 --- a/libavcodec/sbc.h +++ b/libavcodec/sbc.h @@ -112,7 +112,7 @@ struct sbc_frame { const AVCRC *crc_ctx; }; -uint8_t sbc_crc8(const AVCRC *crc_ctx, const uint8_t *data, size_t len); +uint8_t ff_sbc_crc8(const AVCRC *crc_ctx, const uint8_t *data, size_t len); void ff_sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8]); #endif /* AVCODEC_SBC_H */ diff --git a/libavcodec/sbcdec.c b/libavcodec/sbcdec.c index be703382ff5d3..546b38c106860 100644 --- a/libavcodec/sbcdec.c +++ b/libavcodec/sbcdec.c @@ -147,7 +147,7 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, } } - if (data[3] != sbc_crc8(frame->crc_ctx, crc_header, crc_pos)) + if (data[3] != ff_sbc_crc8(frame->crc_ctx, crc_header, crc_pos)) return -3; ff_sbc_calculate_bits(frame, bits); diff --git a/libavcodec/sbcenc.c b/libavcodec/sbcenc.c index a0064c0e8c722..e2929e22ac52e 100644 --- a/libavcodec/sbcenc.c +++ b/libavcodec/sbcenc.c @@ -156,7 +156,7 @@ static size_t sbc_pack_frame(AVPacket *avpkt, struct sbc_frame *frame, if (crc_pos % 8) crc_header[crc_pos >> 3] <<= 8 - (crc_pos % 8); - avpkt->data[3] = sbc_crc8(frame->crc_ctx, crc_header, crc_pos); + avpkt->data[3] = ff_sbc_crc8(frame->crc_ctx, crc_header, crc_pos); ff_sbc_calculate_bits(frame, bits); From 8b019be79b6b32aa664ca042eb8cbd226b6433fe Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 19 Apr 2018 23:34:11 +0200 Subject: [PATCH 2506/2557] avcodec/sheervideodata: Fix libavutil include Signed-off-by: Michael Niedermayer (cherry picked from commit 3dfe3436ac78607d7baf6f1f7f48691343d9d929) Signed-off-by: Michael Niedermayer --- libavcodec/sheervideodata.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/sheervideodata.h b/libavcodec/sheervideodata.h index 0fac25d48c5e1..3b6e2f6591256 100644 --- a/libavcodec/sheervideodata.h +++ b/libavcodec/sheervideodata.h @@ -22,7 +22,7 @@ #ifndef AVCODEC_SHEERVIDEODATA_H #define AVCODEC_SHEERVIDEODATA_H -#include +#include "libavutil/common.h" static const uint8_t l_r_rgb[256] = { 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, From 5cc6370a1501ea6dbad13be0f4aa181fdb5c6660 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 19 Apr 2018 23:44:13 +0200 Subject: [PATCH 2507/2557] avcodec: Fix AVClass .version Signed-off-by: Michael Niedermayer (cherry picked from commit c0bce367e4932f0fb09195e6978ac1a5a60480a4) Signed-off-by: Michael Niedermayer --- libavcodec/dump_extradata_bsf.c | 2 +- libavcodec/hapqa_extract_bsf.c | 2 +- libavcodec/mediacodec_wrapper.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/dump_extradata_bsf.c b/libavcodec/dump_extradata_bsf.c index 081ae5aa08b61..98703749f7570 100644 --- a/libavcodec/dump_extradata_bsf.c +++ b/libavcodec/dump_extradata_bsf.c @@ -93,7 +93,7 @@ static const AVClass dump_extradata_class = { .class_name = "dump_extradata bsf", .item_name = av_default_item_name, .option = options, - .version = LIBAVUTIL_VERSION_MAJOR, + .version = LIBAVUTIL_VERSION_INT, }; const AVBitStreamFilter ff_dump_extradata_bsf = { diff --git a/libavcodec/hapqa_extract_bsf.c b/libavcodec/hapqa_extract_bsf.c index 167d22d06ea21..5c22184813ddf 100644 --- a/libavcodec/hapqa_extract_bsf.c +++ b/libavcodec/hapqa_extract_bsf.c @@ -122,7 +122,7 @@ static const AVClass hapqa_extract_class = { .class_name = "hapqa_extract_bsf", .item_name = av_default_item_name, .option = options, - .version = LIBAVUTIL_VERSION_MAJOR, + .version = LIBAVUTIL_VERSION_INT, }; const AVBitStreamFilter ff_hapqa_extract_bsf = { diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c index 11d7f665c77c4..9bf96e9383678 100644 --- a/libavcodec/mediacodec_wrapper.c +++ b/libavcodec/mediacodec_wrapper.c @@ -156,7 +156,7 @@ static const struct FFJniField jni_amediaformat_mapping[] = { static const AVClass amediaformat_class = { .class_name = "amediaformat", .item_name = av_default_item_name, - .version = LIBAVCODEC_VERSION_INT, + .version = LIBAVUTIL_VERSION_INT, }; struct FFAMediaFormat { @@ -268,7 +268,7 @@ static const struct FFJniField jni_amediacodec_mapping[] = { static const AVClass amediacodec_class = { .class_name = "amediacodec", .item_name = av_default_item_name, - .version = LIBAVCODEC_VERSION_INT, + .version = LIBAVUTIL_VERSION_INT, }; struct FFAMediaCodec { From b2b7cb0f606ced3b705f0cef5f5ba0cdda784adf Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 19 Apr 2018 23:44:33 +0200 Subject: [PATCH 2508/2557] avdevice/android_camera: Fix AVClass.version Signed-off-by: Michael Niedermayer (cherry picked from commit 13b77af2f0b56d6c87bb147947337981c21f4245) Signed-off-by: Michael Niedermayer --- libavdevice/android_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/android_camera.c b/libavdevice/android_camera.c index ff6caaa55e3d9..4a956a7f526a2 100644 --- a/libavdevice/android_camera.c +++ b/libavdevice/android_camera.c @@ -855,7 +855,7 @@ static const AVClass android_camera_class = { .class_name = "android_camera indev", .item_name = av_default_item_name, .option = options, - .version = LIBAVDEVICE_VERSION_INT, + .version = LIBAVUTIL_VERSION_INT, .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, }; From b9b3ef4f5a51a020911d6fb2b1dc672d4c0a769f Mon Sep 17 00:00:00 2001 From: Stephan Holljes Date: Fri, 12 Jan 2018 19:16:29 +0100 Subject: [PATCH 2509/2557] lavf/http.c: Free allocated client URLContext in case of error. Signed-off-by: Stephan Holljes Signed-off-by: Michael Niedermayer (cherry picked from commit 7b6b8c92652d6683d97515352e4a9a4147b7da7c) Signed-off-by: Michael Niedermayer --- libavformat/http.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index 983034f0830f9..4fdb2f13f2be6 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -576,7 +576,11 @@ static int http_accept(URLContext *s, URLContext **c) goto fail; cc->hd = cl; cc->is_multi_client = 1; + return 0; fail: + if (c) { + ffurl_closep(c); + } return ret; } From ace829cb45cff530b8a0aed6adf18f329d7a98f6 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 20 Apr 2018 01:54:19 +0200 Subject: [PATCH 2510/2557] Changelog: replace by 4.0 Signed-off-by: Michael Niedermayer --- Changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 7df4513e2da33..cc61b80958fb5 100644 --- a/Changelog +++ b/Changelog @@ -1,7 +1,7 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. -version : +version 4.0: - Bitstream filters for editing metadata in H.264, HEVC and MPEG-2 streams - Dropped support for OpenJPEG versions 2.0 and below. Using OpenJPEG now requires 2.1 (or later) and pkg-config. From f31df61d748124788c8172c74797ba564639bf6c Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 1 Jul 2013 20:43:11 +0800 Subject: [PATCH 2511/2557] .gitignore: ignore DS_Store --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0e57cb0b4c4c4..bd0b923fbc2b4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.DS_Store *.a *.o *.o.* From 7b68edbffd6e70d752d698db7e04192ae4866718 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 14 Jan 2015 17:41:59 +0800 Subject: [PATCH 2512/2557] avformat/Makefile: install avc.h and avc.o --- libavformat/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/Makefile b/libavformat/Makefile index 3eeca5091df5c..9042ccecc53f7 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -4,6 +4,7 @@ DESC = FFmpeg container format library HEADERS = avformat.h \ avio.h \ version.h \ + avc.h \ OBJS = allformats.o \ avio.o \ @@ -23,6 +24,7 @@ OBJS = allformats.o \ sdp.o \ url.o \ utils.o \ + avc.o \ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o From ba00a629fa145251761d25a7136a8f9b5fe1749f Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 27 Aug 2015 17:07:14 +0800 Subject: [PATCH 2513/2557] avformat/Makefile: install url.h --- libavformat/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/Makefile b/libavformat/Makefile index 9042ccecc53f7..0f64793e46b2d 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -5,6 +5,7 @@ HEADERS = avformat.h \ avio.h \ version.h \ avc.h \ + url.h \ OBJS = allformats.o \ avio.o \ From aff8207fde442be867c3879f36168ecb48ba18b4 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 1 Sep 2015 17:46:28 +0800 Subject: [PATCH 2514/2557] avformat/Makefile: install internal.h --- libavformat/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/Makefile b/libavformat/Makefile index 0f64793e46b2d..e74a275f5617d 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -6,6 +6,7 @@ HEADERS = avformat.h \ version.h \ avc.h \ url.h \ + internal.h \ OBJS = allformats.o \ avio.o \ From 249ceb62c614b0f56186b22f6c65f751e6c25484 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sat, 10 Oct 2015 14:17:30 +0800 Subject: [PATCH 2515/2557] avutil/Makefile: install thread.h --- libavutil/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/Makefile b/libavutil/Makefile index a63ba523c9ecc..8889719e2d08c 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -78,6 +78,7 @@ HEADERS = adler32.h \ version.h \ xtea.h \ tea.h \ + thread.h \ HEADERS-$(CONFIG_LZO) += lzo.h From e2855cf6e11065cd9c9ddd8959115a7b45e399ca Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 3 Jul 2013 21:46:17 +0800 Subject: [PATCH 2516/2557] avformat/hls: parse #EXT-X-MEDIA-SEQUENCE only once --- libavformat/hls.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 1257cd101ca74..c98ec437e87b8 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -733,6 +733,7 @@ static int parse_playlist(HLSContext *c, const char *url, in = NULL; } } + int start_seq_no = -1; if (!in) { AVDictionary *opts = NULL; @@ -809,7 +810,11 @@ static int parse_playlist(HLSContext *c, const char *url, ret = ensure_playlist(c, &pls, url); if (ret < 0) goto fail; - pls->start_seq_no = atoi(ptr); + /* Some buggy HLS servers write #EXT-X-MEDIA-SEQUENCE more than once */ + if (start_seq_no < 0) { + start_seq_no = atoi(ptr); + pls->start_seq_no = start_seq_no; + } } else if (av_strstart(line, "#EXT-X-PLAYLIST-TYPE:", &ptr)) { ret = ensure_playlist(c, &pls, url); if (ret < 0) From af28d8bf24e0b4cfb9ba68628050bead143a356a Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 3 Jul 2013 21:51:19 +0800 Subject: [PATCH 2517/2557] avformat/http: read exact bytes at end of stream to avoid being blocked --- libavformat/http.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libavformat/http.c b/libavformat/http.c index 4fdb2f13f2be6..bb1c3bc456627 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -1391,7 +1391,15 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size) uint64_t target_end = s->end_off ? s->end_off : s->filesize; if ((!s->willclose || s->chunksize == UINT64_MAX) && s->off >= target_end) return AVERROR_EOF; - len = ffurl_read(s->hd, buf, size); + + len = size; + if (s->filesize > 0 && s->filesize != UINT64_MAX && s->filesize != 2147483647) { + int64_t unread = s->filesize - s->off; + if (len > unread) + len = (int)unread; + } + if (len > 0) + len = ffurl_read(s->hd, buf, len); if (!len && (!s->willclose || s->chunksize == UINT64_MAX) && s->off < target_end) { av_log(h, AV_LOG_ERROR, "Stream ends prematurely at %"PRIu64", should be %"PRIu64"\n", From a3150f5e59800482aca4c47752c46a974437bd6d Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 4 Jul 2013 12:02:06 +0800 Subject: [PATCH 2518/2557] avformat/mov: prefer nearest sample as next sample --- libavformat/mov.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 1340bf3913a69..21c8ac3b9f101 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -6953,8 +6953,13 @@ static int mov_read_header(AVFormatContext *s) static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st) { AVIndexEntry *sample = NULL; + AVIndexEntry *best_dts_sample = NULL; + AVIndexEntry *best_pos_sample = NULL; + AVStream *best_dts_stream = NULL; + AVStream *best_pos_stream = NULL; int64_t best_dts = INT64_MAX; int i; + int64_t pos = avio_tell(s->pb); for (i = 0; i < s->nb_streams; i++) { AVStream *avst = s->streams[i]; MOVStreamContext *msc = avst->priv_data; @@ -6962,17 +6967,36 @@ static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st) AVIndexEntry *current_sample = &avst->index_entries[msc->current_sample]; int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale); av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts); - if (!sample || (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && current_sample->pos < sample->pos) || + if (!best_dts_sample || (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && current_sample->pos < best_dts_sample->pos) || ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && - ((FFABS(best_dts - dts) <= AV_TIME_BASE && current_sample->pos < sample->pos) || + ((FFABS(best_dts - dts) <= AV_TIME_BASE && current_sample->pos < best_dts_sample->pos) || (FFABS(best_dts - dts) > AV_TIME_BASE && dts < best_dts)))))) { - sample = current_sample; + /* find best dts sample */ + best_dts_sample = current_sample; best_dts = dts; - *st = avst; + best_dts_stream = avst; + } + if (current_sample->pos >= pos && + (!best_pos_sample || current_sample->pos < best_pos_sample->pos)) { + /* find nearest sample to avoid seek around */ + best_pos_sample = current_sample; + best_pos_stream = avst; } } } + + if (best_dts_sample && best_dts_sample != best_pos_sample && + (!best_pos_sample || + best_dts_sample->pos < pos || + best_dts_sample->pos > pos + 1024 * 1024)) { + sample = best_dts_sample; + *st = best_dts_stream; + } else { + sample = best_pos_sample; + *st = best_pos_stream; + } + return sample; } From e814be4fc15c0662890e756cdc451db3314c3af8 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 4 Jul 2013 12:12:06 +0800 Subject: [PATCH 2519/2557] avformat/http: try to fix missing Content-Range --- libavformat/http.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index bb1c3bc456627..fd488b650ed8d 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -1163,6 +1163,7 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, char headers[HTTP_HEADERS_SIZE] = ""; char *authstr = NULL, *proxyauthstr = NULL; uint64_t off = s->off; + uint64_t filesize = s->filesize; int len = 0; const char *method; int send_expect_100 = 0; @@ -1330,6 +1331,15 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, if (*new_location) s->off = off; + /* Some buggy servers may missing 'Content-Range' header for range request */ + if (off > 0 && s->off <= 0 && (off + s->filesize == filesize)) { + av_log(NULL, AV_LOG_WARNING, + "try to fix missing 'Content-Range' at server side (%"PRId64",%"PRId64") => (%"PRId64",%"PRId64")", + s->off, s->filesize, off, filesize); + s->off = off; + s->filesize = filesize; + } + err = (off == s->off) ? 0 : -1; done: av_freep(&authstr); From 1493a0089278854050482a79cdb7325194bee303 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 6 Aug 2013 19:09:17 +0800 Subject: [PATCH 2520/2557] avformat/hls: fix duration --- libavformat/hls.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index c98ec437e87b8..a59082d467c23 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -2,6 +2,7 @@ * Apple HTTP Live Streaming demuxer * Copyright (c) 2010 Martin Storsjo * Copyright (c) 2013 Anssi Hannula + * Copyright (c) 2011 Cedirc Fung (wolfplanet@gmail.com) * * This file is part of FFmpeg. * @@ -66,7 +67,9 @@ enum KeyType { }; struct segment { + int64_t previous_duration; int64_t duration; + int64_t start_time; int64_t url_offset; int64_t size; char *url; @@ -704,7 +707,7 @@ static int parse_playlist(HLSContext *c, const char *url, struct playlist *pls, AVIOContext *in) { int ret = 0, is_segment = 0, is_variant = 0; - int64_t duration = 0; + int64_t duration = 0, previous_duration1 = 0, previous_duration = 0, total_duration = 0; enum KeyType key_type = KEY_NONE; uint8_t iv[16] = ""; int has_iv = 0; @@ -834,6 +837,8 @@ static int parse_playlist(HLSContext *c, const char *url, } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) { if (pls) pls->finished = 1; + } else if (av_strstart(line, "#EXT-X-DISCONTINUITY", &ptr)) { + previous_duration = previous_duration1; } else if (av_strstart(line, "#EXTINF:", &ptr)) { is_segment = 1; duration = atof(ptr) * AV_TIME_BASE; @@ -866,6 +871,10 @@ static int parse_playlist(HLSContext *c, const char *url, ret = AVERROR(ENOMEM); goto fail; } + previous_duration1 += duration; + seg->previous_duration = previous_duration; + seg->start_time = total_duration; + total_duration += duration; seg->duration = duration; seg->key_type = key_type; if (has_iv) { @@ -2216,6 +2225,28 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) } } + if (c->playlists[minplaylist]->finished) { + struct playlist *pls = c->playlists[minplaylist]; + int seq_no = pls->cur_seq_no - pls->start_seq_no; + if (seq_no < pls->n_segments && s->streams[pkt->stream_index]) { + struct segment *seg = pls->segments[seq_no]; + int64_t pred = av_rescale_q(seg->previous_duration, + AV_TIME_BASE_Q, + s->streams[pkt->stream_index]->time_base); + int64_t max_ts = av_rescale_q(seg->start_time + seg->duration, + AV_TIME_BASE_Q, + s->streams[pkt->stream_index]->time_base); + /* EXTINF duration is not precise enough */ + max_ts += 2 * AV_TIME_BASE; + if (s->start_time > 0) { + max_ts += av_rescale_q(s->start_time, + AV_TIME_BASE_Q, + s->streams[pkt->stream_index]->time_base); + } + if (pkt->dts != AV_NOPTS_VALUE && pkt->dts + pred < max_ts) pkt->dts += pred; + if (pkt->pts != AV_NOPTS_VALUE && pkt->pts + pred < max_ts) pkt->pts += pred; + } + } return 0; } return AVERROR_EOF; From 228d5d5f521bda22267f9ce1aa10fcbfb347abfb Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 12 Feb 2015 14:30:36 +0800 Subject: [PATCH 2521/2557] lavf/avformat: add support for passing options to nested input --- libavformat/avformat.h | 5 +++++ libavformat/utils.c | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index a2fe7c6bb2caf..fe7dc5adf5b01 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -702,6 +702,11 @@ typedef struct AVInputFormat { */ int (*read_header)(struct AVFormatContext *); + /** + * Used by format which open further nested input. + */ + int (*read_header2)(struct AVFormatContext *, AVDictionary **options); + /** * Read one packet and put it in 'pkt'. pts and flags are also * set. 'avformat_new_stream' can be called only if the flag diff --git a/libavformat/utils.c b/libavformat/utils.c index f2f2cc4239079..12cf4bdd9499c 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -540,6 +540,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVFormatContext *s = *ps; int i, ret = 0; AVDictionary *tmp = NULL; + AVDictionary *tmp2 = NULL; ID3v2ExtraMeta *id3v2_extra_meta = NULL; if (!s && !(s = avformat_alloc_context())) @@ -627,9 +628,16 @@ FF_ENABLE_DEPRECATION_WARNINGS ff_id3v2_read_dict(s->pb, &s->internal->id3v2_meta, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); - if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header) - if ((ret = s->iformat->read_header(s)) < 0) + if (!(s->flags&AVFMT_FLAG_PRIV_OPT)) { + if (s->iformat->read_header2) { + if (options) + av_dict_copy(&tmp2, *options, 0); + + if ((ret = s->iformat->read_header2(s, &tmp2)) < 0) + goto fail; + } else if (s->iformat->read_header && (ret = s->iformat->read_header(s)) < 0) goto fail; + } if (!s->metadata) { s->metadata = s->internal->id3v2_meta; @@ -674,6 +682,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if (options) { av_dict_free(options); *options = tmp; + av_dict_free(&tmp2); } *ps = s; return 0; @@ -681,6 +690,7 @@ FF_ENABLE_DEPRECATION_WARNINGS fail: ff_id3v2_free_extra_meta(&id3v2_extra_meta); av_dict_free(&tmp); + av_dict_free(&tmp2); if (s->pb && !(s->flags & AVFMT_FLAG_CUSTOM_IO)) avio_closep(&s->pb); avformat_free_context(s); From b66d20012ac3deaef76ea1b2943cdd08ea442d9e Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 12 Feb 2015 16:27:49 +0800 Subject: [PATCH 2522/2557] lavf/concatdec: pass options to nested input --- libavformat/concatdec.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index bbe13136fa297..9fa3c5fb96527 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -65,6 +65,7 @@ typedef struct { ConcatMatchMode stream_match_mode; unsigned auto_convert; int segment_time_metadata; + AVDictionary *options; } ConcatContext; static int concat_probe(AVProbeData *probe) @@ -319,6 +320,7 @@ static int open_file(AVFormatContext *avf, unsigned fileno) ConcatContext *cat = avf->priv_data; ConcatFile *file = &cat->files[fileno]; int ret; + AVDictionary *tmp = NULL; if (cat->avf) avformat_close_input(&cat->avf); @@ -380,11 +382,12 @@ static int concat_read_close(AVFormatContext *avf) } if (cat->avf) avformat_close_input(&cat->avf); + av_dict_free(&cat->options); av_freep(&cat->files); return 0; } -static int concat_read_header(AVFormatContext *avf) +static int concat_read_header(AVFormatContext *avf, AVDictionary **options) { ConcatContext *cat = avf->priv_data; AVBPrint bp; @@ -394,6 +397,9 @@ static int concat_read_header(AVFormatContext *avf) ConcatFile *file = NULL; int64_t ret, time = 0; + if (options && *options) + av_dict_copy(&cat->options, *options, 0); + av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); while ((ret = ff_read_line_to_bprint_overwrite(avf->pb, &bp)) >= 0) { @@ -775,7 +781,7 @@ AVInputFormat ff_concat_demuxer = { .long_name = NULL_IF_CONFIG_SMALL("Virtual concatenation script"), .priv_data_size = sizeof(ConcatContext), .read_probe = concat_probe, - .read_header = concat_read_header, + .read_header2 = concat_read_header, .read_packet = concat_read_packet, .read_close = concat_read_close, .read_seek2 = concat_seek, From cc6599744a1a812ce9c93151a3acbbbfea28f478 Mon Sep 17 00:00:00 2001 From: bbcallen Date: Tue, 4 Mar 2014 14:15:58 +0800 Subject: [PATCH 2523/2557] avformat/concatdec: close previous segment only after new segment is open successfully Later call to concat_read_packet could cause NULL pointer access. avformat/concatdec: fix merge conflict in open_file --- libavformat/concatdec.c | 58 ++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 9fa3c5fb96527..cadece60d1195 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -66,6 +66,7 @@ typedef struct { unsigned auto_convert; int segment_time_metadata; AVDictionary *options; + int error; } ConcatContext; static int concat_probe(AVProbeData *probe) @@ -319,28 +320,39 @@ static int open_file(AVFormatContext *avf, unsigned fileno) { ConcatContext *cat = avf->priv_data; ConcatFile *file = &cat->files[fileno]; + AVFormatContext *new_avf = NULL; int ret; AVDictionary *tmp = NULL; - if (cat->avf) - avformat_close_input(&cat->avf); - - cat->avf = avformat_alloc_context(); - if (!cat->avf) + new_avf = avformat_alloc_context(); + if (!new_avf) return AVERROR(ENOMEM); - cat->avf->flags |= avf->flags & ~AVFMT_FLAG_CUSTOM_IO; - cat->avf->interrupt_callback = avf->interrupt_callback; + new_avf->flags |= avf->flags & ~AVFMT_FLAG_CUSTOM_IO; + new_avf->interrupt_callback = avf->interrupt_callback; - if ((ret = ff_copy_whiteblacklists(cat->avf, avf)) < 0) + if ((ret = ff_copy_whiteblacklists(new_avf, avf)) < 0) return ret; - if ((ret = avformat_open_input(&cat->avf, file->url, NULL, NULL)) < 0 || - (ret = avformat_find_stream_info(cat->avf, NULL)) < 0) { + if (cat->options) + av_dict_copy(&tmp, cat->options, 0); + + ret = avformat_open_input(&new_avf, file->url, NULL, &tmp); + av_dict_free(&tmp); + if (ret < 0 || + (ret = avformat_find_stream_info(new_avf, NULL)) < 0) { av_log(avf, AV_LOG_ERROR, "Impossible to open '%s'\n", file->url); - avformat_close_input(&cat->avf); + avformat_close_input(&new_avf); return ret; } + + if (!new_avf) + return 0; + + if (cat->avf) + avformat_close_input(&cat->avf); + + cat->avf = new_avf; cat->cur_file = file; if (file->start_time == AV_NOPTS_VALUE) file->start_time = !fileno ? 0 : @@ -571,6 +583,7 @@ static int packet_after_outpoint(ConcatContext *cat, AVPacket *pkt) return 0; } +#define CONCAT_MAX_OPEN_TRY 3 static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt) { ConcatContext *cat = avf->priv_data; @@ -578,6 +591,12 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt) int64_t delta; ConcatStream *cs; AVStream *st; + int try_counter = 0; + + if (cat->error) { + ret = cat->error; + return ret; + } if (cat->eof) return AVERROR_EOF; @@ -589,7 +608,7 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt) ret = av_read_frame(cat->avf, pkt); if (ret == AVERROR_EOF) { if ((ret = open_next_file(avf)) < 0) - return ret; + goto open_fail; continue; } if (ret < 0) @@ -601,7 +620,7 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt) if (packet_after_outpoint(cat, pkt)) { av_packet_unref(pkt); if ((ret = open_next_file(avf)) < 0) - return ret; + goto open_fail; continue; } cs = &cat->cur_file->streams[pkt->stream_index]; @@ -610,6 +629,16 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt) continue; } break; +open_fail: + ++try_counter; + if (try_counter > CONCAT_MAX_OPEN_TRY) { + cat->error = ret; + if (avf->pb && ret != AVERROR_EOF) + avf->pb->error = ret; + return AVERROR_EOF; + } + + av_log(avf, AV_LOG_WARNING, "open_next_file() failed (%d)\n", try_counter); } if ((ret = filter_packet(avf, cs, pkt))) return ret; @@ -734,6 +763,9 @@ static int concat_seek(AVFormatContext *avf, int stream, AVFormatContext *cur_avf_saved = cat->avf; int ret; + /* reset error/complete state */ + cat->error = 0; + if (!cat->seekable) return AVERROR(ESPIPE); /* XXX: can we use it? */ if (flags & (AVSEEK_FLAG_BYTE | AVSEEK_FLAG_FRAME)) From 4925cc58d4cec6f0abb0e128ba9b56b9c5595a14 Mon Sep 17 00:00:00 2001 From: Ming Hu Date: Thu, 24 Mar 2016 13:09:36 +0800 Subject: [PATCH 2524/2557] avformat/concat: expose a flag to indicate source switch Signed-off-by: xinzhengzhang --- libavcodec/avcodec.h | 1 + libavformat/concatdec.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index fb0c6fae70b33..0c1eefe6ba99a 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1480,6 +1480,7 @@ typedef struct AVPacket { */ #define AV_PKT_FLAG_DISPOSABLE 0x0010 +#define AV_PKT_FLAG_NEW_SEG 0x8000 ///< The packet is the first packet from a source in concat enum AVSideDataParamChangeFlags { AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index cadece60d1195..5e1f061fefee8 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -592,6 +592,7 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt) ConcatStream *cs; AVStream *st; int try_counter = 0; + int is_new_st = 0; if (cat->error) { ret = cat->error; @@ -607,12 +608,17 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt) while (1) { ret = av_read_frame(cat->avf, pkt); if (ret == AVERROR_EOF) { + is_new_st = 1; if ((ret = open_next_file(avf)) < 0) goto open_fail; continue; } if (ret < 0) return ret; + if (is_new_st) { + pkt->flags |= AV_PKT_FLAG_NEW_SEG; + is_new_st = 0; + } if ((ret = match_streams(avf)) < 0) { av_packet_unref(pkt); return ret; From be5b679a6eb1252d20ea5e33ba2f35c127515652 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 21 Apr 2015 17:47:26 +0800 Subject: [PATCH 2525/2557] Revert "Fix url_feof() for file appendings." This reverts commit 3bd624b4ee355328382295af411f5343b1329f43. avio_feof() could reset eof_reached which is not expected. --- libavformat/aviobuf.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index e752d0e1a659b..e5a44c3f3e24b 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -359,10 +359,6 @@ int avio_feof(AVIOContext *s) { if(!s) return 0; - if(s->eof_reached){ - s->eof_reached=0; - fill_buffer(s); - } return s->eof_reached; } From b37af09eaaadd68c124a194b3a4f8a2ea4228a02 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 13 May 2015 15:13:16 +0800 Subject: [PATCH 2526/2557] avformat/concatdec: pass out io error --- libavformat/concatdec.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 5e1f061fefee8..258b4ccc7a07c 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -613,8 +613,11 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt) goto open_fail; continue; } - if (ret < 0) + if (ret < 0) { + if (avf->pb && cat->avf->pb) + avf->pb->error = cat->avf->pb->error; return ret; + } if (is_new_st) { pkt->flags |= AV_PKT_FLAG_NEW_SEG; is_new_st = 0; From 13d14f6c0f7c24b233f491b07a2581289f32474d Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 31 Aug 2015 18:22:32 +0800 Subject: [PATCH 2527/2557] avformat/http: add option http-tcp-hook --- libavformat/http.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/http.c b/libavformat/http.c index fd488b650ed8d..6c1f20694c56d 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -125,6 +125,7 @@ typedef struct HTTPContext { int is_multi_client; HandshakeState handshake_step; int is_connected_server; + char *tcp_hook; } HTTPContext; #define OFFSET(x) offsetof(HTTPContext, x) @@ -167,6 +168,7 @@ static const AVOption options[] = { { "listen", "listen on HTTP", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, D | E }, { "resource", "The resource requested by a client", OFFSET(resource), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, { "reply_code", "The http status code to return to a client", OFFSET(reply_code), AV_OPT_TYPE_INT, { .i64 = 200}, INT_MIN, 599, E}, + { "http-tcp-hook", "hook protocol on tcp", OFFSET(tcp_hook), AV_OPT_TYPE_STRING, { .str = "tcp" }, 0, 0, D | E }, { NULL } }; @@ -196,6 +198,8 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options) int port, use_proxy, err, location_changed = 0; HTTPContext *s = h->priv_data; + lower_proto = s->tcp_hook; + av_url_split(proto, sizeof(proto), auth, sizeof(auth), hostname, sizeof(hostname), &port, path1, sizeof(path1), s->location); @@ -1825,7 +1829,7 @@ static int http_proxy_open(URLContext *h, const char *uri, int flags) if (*path == '/') path++; - ff_url_join(lower_url, sizeof(lower_url), "tcp", NULL, hostname, port, + ff_url_join(lower_url, sizeof(lower_url), s->tcp_hook, NULL, hostname, port, NULL); redo: ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE, From 78dea8093eb51c9a7636b4e8b41a785d22bc4942 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 29 Dec 2015 12:10:40 +0800 Subject: [PATCH 2528/2557] avformat/concatdec: fetch bit_rate from internal format --- libavformat/concatdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 258b4ccc7a07c..ae9ca3369474e 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -352,6 +352,7 @@ static int open_file(AVFormatContext *avf, unsigned fileno) if (cat->avf) avformat_close_input(&cat->avf); + avf->bit_rate = new_avf->bit_rate; cat->avf = new_avf; cat->cur_file = file; if (file->start_time == AV_NOPTS_VALUE) From ff3bfb9072af0fe419a19bcb5b46fc40ad29819a Mon Sep 17 00:00:00 2001 From: Xinzheng Zhang Date: Thu, 11 Aug 2016 12:41:39 +0800 Subject: [PATCH 2529/2557] avformat/ijkutils: add dummy for replacing ijk protocol --- libavformat/Makefile | 1 + libavformat/ijkutils.c | 66 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 libavformat/ijkutils.c diff --git a/libavformat/Makefile b/libavformat/Makefile index e74a275f5617d..b60a7b513f9c9 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -27,6 +27,7 @@ OBJS = allformats.o \ url.o \ utils.o \ avc.o \ + ijkutils.o \ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o diff --git a/libavformat/ijkutils.c b/libavformat/ijkutils.c new file mode 100644 index 0000000000000..59aa7c6d3ad0a --- /dev/null +++ b/libavformat/ijkutils.c @@ -0,0 +1,66 @@ +/* + * utils.c + * + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2013 Zhang Rui + * + * This file is part of ijkPlayer. + * + * ijkPlayer is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * ijkPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with ijkPlayer; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "url.h" + + +#define IJK_FF_PROTOCOL(x) \ +extern URLProtocol ff_##x##_protocol; \ +int ijkav_register_##x##_protocol(URLProtocol *protocol, int protocol_size); \ +int ijkav_register_##x##_protocol(URLProtocol *protocol, int protocol_size) \ +{ \ + if (protocol_size != sizeof(URLProtocol)) { \ + av_log(NULL, AV_LOG_ERROR, "ijkav_register_##x##_protocol: ABI mismatch.\n"); \ + return -1; \ + } \ + memcpy(&ff_##x##_protocol, protocol, protocol_size); \ + return 0; \ +} + +#define IJK_DUMMY_PROTOCOL(x) \ +IJK_FF_PROTOCOL(x); \ +static const AVClass ijk_##x##_context_class = { \ + .class_name = #x, \ + .item_name = av_default_item_name, \ + .version = LIBAVUTIL_VERSION_INT, \ + }; \ + \ +URLProtocol ff_##x##_protocol = { \ + .name = #x, \ + .url_open2 = ijkdummy_open, \ + .priv_data_size = 1, \ + .priv_data_class = &ijk_##x##_context_class, \ +}; + +static int ijkdummy_open(URLContext *h, const char *arg, int flags, AVDictionary **options) +{ + return -1; +} + +IJK_FF_PROTOCOL(async); +IJK_DUMMY_PROTOCOL(ijkmediadatasource); +IJK_DUMMY_PROTOCOL(ijkhttphook); +IJK_DUMMY_PROTOCOL(ijklongurl); +IJK_DUMMY_PROTOCOL(ijksegment); +IJK_DUMMY_PROTOCOL(ijktcphook); From a32ed354b3a158d9e7fbeedaa5aaa1fd4ffeb454 Mon Sep 17 00:00:00 2001 From: Xinzheng Zhang Date: Thu, 11 Aug 2016 12:42:25 +0800 Subject: [PATCH 2530/2557] avformat/protocols: add stub for custom protocol --- libavformat/protocols.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavformat/protocols.c b/libavformat/protocols.c index ad95659795e4f..7e1aed6004651 100644 --- a/libavformat/protocols.c +++ b/libavformat/protocols.c @@ -39,6 +39,11 @@ extern const URLProtocol ff_http_protocol; extern const URLProtocol ff_httpproxy_protocol; extern const URLProtocol ff_https_protocol; extern const URLProtocol ff_icecast_protocol; +extern const URLProtocol ff_ijkhttphook_protocol; +extern const URLProtocol ff_ijklongurl_protocol; +extern const URLProtocol ff_ijkmediadatasource_protocol; +extern const URLProtocol ff_ijksegment_protocol; +extern const URLProtocol ff_ijktcphook_protocol; extern const URLProtocol ff_mmsh_protocol; extern const URLProtocol ff_mmst_protocol; extern const URLProtocol ff_md5_protocol; From 03f5736e00ab65825b197bb69840a928c010dfc5 Mon Sep 17 00:00:00 2001 From: xinzhengzhang Date: Thu, 24 Mar 2016 15:13:39 +0800 Subject: [PATCH 2531/2557] avutil/application: support low level event callback --- libavutil/Makefile | 2 + libavutil/application.c | 214 ++++++++++++++++++++++++++++++++++++++++ libavutil/application.h | 120 ++++++++++++++++++++++ 3 files changed, 336 insertions(+) create mode 100644 libavutil/application.c create mode 100644 libavutil/application.h diff --git a/libavutil/Makefile b/libavutil/Makefile index 8889719e2d08c..6e52439cb695f 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -4,6 +4,7 @@ DESC = FFmpeg utility library HEADERS = adler32.h \ aes.h \ aes_ctr.h \ + application.h \ attributes.h \ audio_fifo.h \ avassert.h \ @@ -93,6 +94,7 @@ BUILT_HEADERS = avconfig.h \ OBJS = adler32.o \ aes.o \ aes_ctr.o \ + application.o \ audio_fifo.o \ avstring.o \ base64.o \ diff --git a/libavutil/application.c b/libavutil/application.c new file mode 100644 index 0000000000000..2626742a0b291 --- /dev/null +++ b/libavutil/application.c @@ -0,0 +1,214 @@ +/* + * copyright (c) 2016 Zhang Rui + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "application.h" +#include "libavformat/network.h" +#include "libavutil/avstring.h" + +void av_application_on_io_traffic(AVApplicationContext *h, AVAppIOTraffic *event); + +int av_application_alloc(AVApplicationContext **ph, void *opaque) +{ + AVApplicationContext *h = NULL; + + h = av_mallocz(sizeof(AVApplicationContext)); + if (!h) + return AVERROR(ENOMEM); + + h->opaque = opaque; + + *ph = h; + return 0; +} + +int av_application_open(AVApplicationContext **ph, void *opaque) +{ + int ret = av_application_alloc(ph, opaque); + if (ret) + return ret; + + return 0; +} + +void av_application_close(AVApplicationContext *h) +{ + av_free(h); +} + +void av_application_closep(AVApplicationContext **ph) +{ + if (!ph || !*ph) + return; + + av_application_close(*ph); + *ph = NULL; +} + +void av_application_on_http_event(AVApplicationContext *h, int event_type, AVAppHttpEvent *event) +{ + if (h && h->func_on_app_event) + h->func_on_app_event(h, event_type, (void *)event, sizeof(AVAppHttpEvent)); +} + +void av_application_will_http_open(AVApplicationContext *h, void *obj, const char *url) +{ + AVAppHttpEvent event = {0}; + + if (!h || !obj || !url) + return; + + event.obj = obj; + av_strlcpy(event.url, url, sizeof(event.url)); + + av_application_on_http_event(h, AVAPP_EVENT_WILL_HTTP_OPEN, &event); +} + +void av_application_did_http_open(AVApplicationContext *h, void *obj, const char *url, int error, int http_code) +{ + AVAppHttpEvent event = {0}; + + if (!h || !obj || !url) + return; + + event.obj = obj; + av_strlcpy(event.url, url, sizeof(event.url)); + event.error = error; + event.http_code = http_code; + + av_application_on_http_event(h, AVAPP_EVENT_DID_HTTP_OPEN, &event); +} + +void av_application_will_http_seek(AVApplicationContext *h, void *obj, const char *url, int64_t offset) +{ + AVAppHttpEvent event = {0}; + + if (!h || !obj || !url) + return; + + event.obj = obj; + event.offset = offset; + av_strlcpy(event.url, url, sizeof(event.url)); + + av_application_on_http_event(h, AVAPP_EVENT_WILL_HTTP_SEEK, &event); +} + +void av_application_did_http_seek(AVApplicationContext *h, void *obj, const char *url, int64_t offset, int error, int http_code) +{ + AVAppHttpEvent event = {0}; + + if (!h || !obj || !url) + return; + + event.obj = obj; + event.offset = offset; + av_strlcpy(event.url, url, sizeof(event.url)); + event.error = error; + event.http_code = http_code; + + av_application_on_http_event(h, AVAPP_EVENT_DID_HTTP_SEEK, &event); +} + +void av_application_on_io_traffic(AVApplicationContext *h, AVAppIOTraffic *event) +{ + if (h && h->func_on_app_event) + h->func_on_app_event(h, AVAPP_EVENT_IO_TRAFFIC, (void *)event, sizeof(AVAppIOTraffic)); +} + +int av_application_on_io_control(AVApplicationContext *h, int event_type, AVAppIOControl *control) +{ + if (h && h->func_on_app_event) + return h->func_on_app_event(h, event_type, (void *)control, sizeof(AVAppIOControl)); + return 0; +} + +int av_application_on_tcp_will_open(AVApplicationContext *h) +{ + if (h && h->func_on_app_event) { + AVAppTcpIOControl control = {0}; + return h->func_on_app_event(h, AVAPP_CTRL_WILL_TCP_OPEN, (void *)&control, sizeof(AVAppTcpIOControl)); + } + return 0; +} + +// only callback returns error +int av_application_on_tcp_did_open(AVApplicationContext *h, int error, int fd) +{ + struct sockaddr_storage so_stg; + int ret = 0; + socklen_t so_len = sizeof(so_stg); + int so_family; + AVAppTcpIOControl control = {0}; + char *so_ip_name = control.ip; + + if (!h || !h->func_on_app_event || fd <= 0) + return 0; + + ret = getpeername(fd, (struct sockaddr *)&so_stg, &so_len); + if (ret) + return 0; + control.error = error; + control.fd = fd; + + so_family = ((struct sockaddr*)&so_stg)->sa_family; + switch (so_family) { + case AF_INET: { + struct sockaddr_in* in4 = (struct sockaddr_in*)&so_stg; + if (inet_ntop(AF_INET, &(in4->sin_addr), so_ip_name, sizeof(control.ip))) { + control.family = AF_INET; + control.port = in4->sin_port; + } + break; + } + case AF_INET6: { + struct sockaddr_in6* in6 = (struct sockaddr_in6*)&so_stg; + if (inet_ntop(AF_INET6, &(in6->sin6_addr), so_ip_name, sizeof(control.ip))) { + control.family = AF_INET6; + control.port = in6->sin6_port; + } + break; + } + } + + return h->func_on_app_event(h, AVAPP_CTRL_DID_TCP_OPEN, (void *)&control, sizeof(AVAppTcpIOControl)); +} + +void av_application_on_async_statistic(AVApplicationContext *h, AVAppAsyncStatistic *statistic) +{ + if (h && h->func_on_app_event) + h->func_on_app_event(h, AVAPP_EVENT_ASYNC_STATISTIC, (void *)statistic, sizeof(AVAppAsyncStatistic)); +} + +void av_application_on_async_read_speed(AVApplicationContext *h, AVAppAsyncReadSpeed *speed) +{ + if (h && h->func_on_app_event) + h->func_on_app_event(h, AVAPP_EVENT_ASYNC_READ_SPEED, (void *)speed, sizeof(AVAppAsyncReadSpeed)); +} + +void av_application_did_io_tcp_read(AVApplicationContext *h, void *obj, int bytes) +{ + AVAppIOTraffic event = {0}; + if (!h || !obj || bytes <= 0) + return; + + event.obj = obj; + event.bytes = bytes; + + av_application_on_io_traffic(h, &event); +} diff --git a/libavutil/application.h b/libavutil/application.h new file mode 100644 index 0000000000000..a33b272fdd5c4 --- /dev/null +++ b/libavutil/application.h @@ -0,0 +1,120 @@ +/* + * copyright (c) 2016 Zhang Rui + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_APPLICATION_H +#define AVUTIL_APPLICATION_H + +#include "libavutil/log.h" + +#define AVAPP_EVENT_WILL_HTTP_OPEN 1 //AVAppHttpEvent +#define AVAPP_EVENT_DID_HTTP_OPEN 2 //AVAppHttpEvent +#define AVAPP_EVENT_WILL_HTTP_SEEK 3 //AVAppHttpEvent +#define AVAPP_EVENT_DID_HTTP_SEEK 4 //AVAppHttpEvent + +#define AVAPP_EVENT_ASYNC_STATISTIC 0x11000 //AVAppAsyncStatistic +#define AVAPP_EVENT_ASYNC_READ_SPEED 0x11001 //AVAppAsyncReadSpeed +#define AVAPP_EVENT_IO_TRAFFIC 0x12204 //AVAppIOTraffic + +#define AVAPP_CTRL_WILL_TCP_OPEN 0x20001 //AVAppTcpIOControl +#define AVAPP_CTRL_DID_TCP_OPEN 0x20002 //AVAppTcpIOControl + +#define AVAPP_CTRL_WILL_HTTP_OPEN 0x20003 //AVAppIOControl +#define AVAPP_CTRL_WILL_LIVE_OPEN 0x20005 //AVAppIOControl + +#define AVAPP_CTRL_WILL_CONCAT_SEGMENT_OPEN 0x20007 //AVAppIOControl + +typedef struct AVAppIOControl { + size_t size; + char url[4096]; /* in, out */ + int segment_index; /* in, default = 0 */ + int retry_counter; /* in */ + + int is_handled; /* out, default = false */ + int is_url_changed; /* out, default = false */ +} AVAppIOControl; + +typedef struct AVAppTcpIOControl { + int error; + int family; + char ip[96]; + int port; + int fd; +} AVAppTcpIOControl; + +typedef struct AVAppAsyncStatistic { + size_t size; + int64_t buf_backwards; + int64_t buf_forwards; + int64_t buf_capacity; +} AVAppAsyncStatistic; + +typedef struct AVAppAsyncReadSpeed { + size_t size; + int is_full_speed; + int64_t io_bytes; + int64_t elapsed_milli; +} AVAppAsyncReadSpeed; + +typedef struct AVAppHttpEvent +{ + void *obj; + char url[4096]; + int64_t offset; + int error; + int http_code; +} AVAppHttpEvent; + +typedef struct AVAppIOTraffic +{ + void *obj; + int bytes; +} AVAppIOTraffic; + +typedef struct AVApplicationContext AVApplicationContext; +struct AVApplicationContext { + const AVClass *av_class; /**< information for av_log(). Set by av_application_open(). */ + void *opaque; /**< user data. */ + + int (*func_on_app_event)(AVApplicationContext *h, int event_type ,void *obj, size_t size); +}; + +int av_application_alloc(AVApplicationContext **ph, void *opaque); +int av_application_open(AVApplicationContext **ph, void *opaque); +void av_application_close(AVApplicationContext *h); +void av_application_closep(AVApplicationContext **ph); + +void av_application_on_http_event(AVApplicationContext *h, int event_type, AVAppHttpEvent *event); +void av_application_will_http_open(AVApplicationContext *h, void *obj, const char *url); +void av_application_did_http_open(AVApplicationContext *h, void *obj, const char *url, int error, int http_code); +void av_application_will_http_seek(AVApplicationContext *h, void *obj, const char *url, int64_t offset); +void av_application_did_http_seek(AVApplicationContext *h, void *obj, const char *url, int64_t offset, int error, int http_code); + +void av_application_did_io_tcp_read(AVApplicationContext *h, void *obj, int bytes); + +int av_application_on_io_control(AVApplicationContext *h, int event_type, AVAppIOControl *control); + +int av_application_on_tcp_will_open(AVApplicationContext *h); +int av_application_on_tcp_did_open(AVApplicationContext *h, int error, int fd); + +void av_application_on_async_statistic(AVApplicationContext *h, AVAppAsyncStatistic *statistic); +void av_application_on_async_read_speed(AVApplicationContext *h, AVAppAsyncReadSpeed *speed); + + +#endif /* AVUTIL_APPLICATION_H */ From b9094fc391c6c6f500317ac65893db797263bc62 Mon Sep 17 00:00:00 2001 From: Xinzheng Zhang Date: Thu, 11 Aug 2016 12:46:16 +0800 Subject: [PATCH 2532/2557] avformat/tcp: apply control event in application --- libavformat/tcp.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index 8773493df1efe..6a75dae3a0f66 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -23,6 +23,7 @@ #include "libavutil/parseutils.h" #include "libavutil/opt.h" #include "libavutil/time.h" +#include "libavutil/application.h" #include "internal.h" #include "network.h" @@ -42,6 +43,8 @@ typedef struct TCPContext { int recv_buffer_size; int send_buffer_size; int tcp_nodelay; + int64_t app_ctx_intptr; + AVApplicationContext *app_ctx; } TCPContext; #define OFFSET(x) offsetof(TCPContext, x) @@ -54,6 +57,7 @@ static const AVOption options[] = { { "send_buffer_size", "Socket send buffer size (in bytes)", OFFSET(send_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "recv_buffer_size", "Socket receive buffer size (in bytes)", OFFSET(recv_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "tcp_nodelay", "Use TCP_NODELAY to disable nagle's algorithm", OFFSET(tcp_nodelay), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E }, + { "ijkapplication", "AVApplicationContext", OFFSET(app_ctx_intptr), AV_OPT_TYPE_INT64, { .i64 = 0 }, INT64_MIN, INT64_MAX, .flags = D }, { NULL } }; @@ -76,6 +80,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) char hostname[1024],proto[1024],path[1024]; char portstr[10]; s->open_timeout = 5000000; + s->app_ctx = (AVApplicationContext *)(intptr_t)s->app_ctx_intptr; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); @@ -166,13 +171,26 @@ static int tcp_open(URLContext *h, const char *uri, int flags) // Socket descriptor already closed here. Safe to overwrite to client one. fd = ret; } else { + ret = av_application_on_tcp_will_open(s->app_ctx); + if (ret) { + av_log(NULL, AV_LOG_WARNING, "terminated by application in AVAPP_CTRL_WILL_TCP_OPEN"); + goto fail1; + } + if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, s->open_timeout / 1000, h, !!cur_ai->ai_next)) < 0) { - + if (av_application_on_tcp_did_open(s->app_ctx, ret, fd)) + goto fail1; if (ret == AVERROR_EXIT) goto fail1; else goto fail; + } else { + ret = av_application_on_tcp_did_open(s->app_ctx, 0, fd); + if (ret) { + av_log(NULL, AV_LOG_WARNING, "terminated by application in AVAPP_CTRL_DID_TCP_OPEN"); + goto fail1; + } } } @@ -227,6 +245,8 @@ static int tcp_read(URLContext *h, uint8_t *buf, int size) ret = recv(s->fd, buf, size, 0); if (ret == 0) return AVERROR_EOF; + if (ret > 0) + av_application_did_io_tcp_read(s->app_ctx, (void*)h, ret); return ret < 0 ? ff_neterrno() : ret; } From 3437494a18a07679a45b6eee79369bdd97ca9527 Mon Sep 17 00:00:00 2001 From: Xinzheng Zhang Date: Thu, 11 Aug 2016 12:47:52 +0800 Subject: [PATCH 2533/2557] avformat/http: apply control event in application --- libavformat/http.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index 6c1f20694c56d..3fb9ba0d1fa60 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -30,6 +30,7 @@ #include "libavutil/opt.h" #include "libavutil/time.h" #include "libavutil/parseutils.h" +#include "libavutil/application.h" #include "avformat.h" #include "http.h" @@ -126,6 +127,8 @@ typedef struct HTTPContext { HandshakeState handshake_step; int is_connected_server; char *tcp_hook; + int64_t app_ctx_intptr; + AVApplicationContext *app_ctx; } HTTPContext; #define OFFSET(x) offsetof(HTTPContext, x) @@ -169,6 +172,7 @@ static const AVOption options[] = { { "resource", "The resource requested by a client", OFFSET(resource), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, { "reply_code", "The http status code to return to a client", OFFSET(reply_code), AV_OPT_TYPE_INT, { .i64 = 200}, INT_MIN, 599, E}, { "http-tcp-hook", "hook protocol on tcp", OFFSET(tcp_hook), AV_OPT_TYPE_STRING, { .str = "tcp" }, 0, 0, D | E }, + { "ijkapplication", "AVApplicationContext", OFFSET(app_ctx_intptr), AV_OPT_TYPE_INT64, { .i64 = 0 }, INT64_MIN, INT64_MAX, .flags = D }, { NULL } }; @@ -196,6 +200,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options) char path1[MAX_URL_SIZE]; char buf[1024], urlbuf[MAX_URL_SIZE]; int port, use_proxy, err, location_changed = 0; + char prev_location[4096]; HTTPContext *s = h->priv_data; lower_proto = s->tcp_hook; @@ -236,6 +241,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options) ff_url_join(buf, sizeof(buf), lower_proto, NULL, hostname, port, NULL); if (!s->hd) { + av_dict_set_int(options, "ijkapplication", (int64_t)(intptr_t)s->app_ctx, 0); err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE, &h->interrupt_callback, options, h->protocol_whitelist, h->protocol_blacklist, h); @@ -243,6 +249,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options) return err; } + av_strlcpy(prev_location, s->location, sizeof(prev_location)); err = http_connect(h, path, local_path, hoststr, auth, proxyauth, &location_changed); if (err < 0) @@ -529,6 +536,8 @@ static int http_open(URLContext *h, const char *uri, int flags, HTTPContext *s = h->priv_data; int ret; + s->app_ctx = (AVApplicationContext *)(intptr_t)s->app_ctx_intptr; + if( s->seekable == 1 ) h->is_streamed = 0; else @@ -558,7 +567,9 @@ static int http_open(URLContext *h, const char *uri, int flags, if (s->listen) { return http_listen(h, uri, flags, options); } + av_application_will_http_open(s->app_ctx, (void*)h, uri); ret = http_open_cnx(h, options); + av_application_did_http_open(s->app_ctx, (void*)h, uri, ret, s->http_code); if (ret < 0) av_dict_free(&s->chained_options); return ret; @@ -1716,7 +1727,9 @@ static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int fo s->hd = NULL; /* if it fails, continue on old connection */ + av_application_will_http_seek(s->app_ctx, (void*)h, s->location, off); if ((ret = http_open_cnx(h, &options)) < 0) { + av_application_did_http_seek(s->app_ctx, (void*)h, s->location, off, ret, s->http_code); av_dict_free(&options); memcpy(s->buffer, old_buf, old_buf_size); s->buf_ptr = s->buffer; @@ -1725,6 +1738,7 @@ static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int fo s->off = old_off; return ret; } + av_application_did_http_seek(s->app_ctx, (void*)h, s->location, off, ret, s->http_code); av_dict_free(&options); ffurl_close(old_hd); return off; @@ -1817,6 +1831,8 @@ static int http_proxy_open(URLContext *h, const char *uri, int flags) char *authstr; int new_loc; + s->app_ctx = (AVApplicationContext *)(intptr_t)s->app_ctx_intptr; + if( s->seekable == 1 ) h->is_streamed = 0; else From ef82880612dd8bcd4e4fd5a5937aea75a9e2065b Mon Sep 17 00:00:00 2001 From: Xinzheng Zhang Date: Mon, 1 Aug 2016 10:34:16 +0800 Subject: [PATCH 2534/2557] avformat/async: remove const for ff_async_protocol --- libavformat/async.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/async.c b/libavformat/async.c index 54dbd2312a24c..bdbb42fa2b426 100644 --- a/libavformat/async.c +++ b/libavformat/async.c @@ -479,7 +479,7 @@ static const AVClass async_context_class = { .version = LIBAVUTIL_VERSION_INT, }; -const URLProtocol ff_async_protocol = { +URLProtocol ff_async_protocol = { .name = "async", .url_open2 = async_open, .url_read = async_read, From 2813c50b0c57ef9ff135d7d9e216d540c5c17937 Mon Sep 17 00:00:00 2001 From: Xinzheng Zhang Date: Tue, 28 Jun 2016 20:07:11 +0800 Subject: [PATCH 2535/2557] avformat/tcp: support timeout for getaddrinfo --- libavformat/tcp.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index 6a75dae3a0f66..5750e8e589d74 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -32,6 +32,9 @@ #if HAVE_POLL_H #include #endif +#if HAVE_PTHREADS +#include +#endif typedef struct TCPContext { const AVClass *class; @@ -44,6 +47,9 @@ typedef struct TCPContext { int send_buffer_size; int tcp_nodelay; int64_t app_ctx_intptr; + + int addrinfo_timeout; + AVApplicationContext *app_ctx; } TCPContext; @@ -58,6 +64,8 @@ static const AVOption options[] = { { "recv_buffer_size", "Socket receive buffer size (in bytes)", OFFSET(recv_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "tcp_nodelay", "Use TCP_NODELAY to disable nagle's algorithm", OFFSET(tcp_nodelay), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E }, { "ijkapplication", "AVApplicationContext", OFFSET(app_ctx_intptr), AV_OPT_TYPE_INT64, { .i64 = 0 }, INT64_MIN, INT64_MAX, .flags = D }, + + { "addrinfo_timeout", "set timeout (in microseconds) for getaddrinfo()", OFFSET(addrinfo_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { NULL } }; @@ -68,6 +76,221 @@ static const AVClass tcp_class = { .version = LIBAVUTIL_VERSION_INT, }; +#ifdef HAVE_PTHREADS + +typedef struct TCPAddrinfoRequest +{ + AVBufferRef *buffer; + + pthread_mutex_t mutex; + pthread_cond_t cond; + + AVIOInterruptCB interrupt_callback; + + char *hostname; + char *servname; + struct addrinfo hints; + struct addrinfo *res; + + volatile int finished; + int last_error; +} TCPAddrinfoRequest; + +static void tcp_getaddrinfo_request_free(TCPAddrinfoRequest *req) +{ + av_assert0(req); + if (req->res) { + freeaddrinfo(req->res); + req->res = NULL; + } + + av_freep(&req->servname); + av_freep(&req->hostname); + pthread_cond_destroy(&req->cond); + pthread_mutex_destroy(&req->mutex); + av_freep(&req); +} + +static void tcp_getaddrinfo_request_free_buffer(void *opaque, uint8_t *data) +{ + av_assert0(opaque); + TCPAddrinfoRequest *req = (TCPAddrinfoRequest *)opaque; + tcp_getaddrinfo_request_free(req); +} + +static int tcp_getaddrinfo_request_create(TCPAddrinfoRequest **request, + const char *hostname, + const char *servname, + const struct addrinfo *hints, + const AVIOInterruptCB *int_cb) +{ + TCPAddrinfoRequest *req = (TCPAddrinfoRequest *) av_mallocz(sizeof(TCPAddrinfoRequest)); + if (!req) + return AVERROR(ENOMEM); + + if (pthread_mutex_init(&req->mutex, NULL)) { + av_freep(&req); + return AVERROR(ENOMEM); + } + + if (pthread_cond_init(&req->cond, NULL)) { + pthread_mutex_destroy(&req->mutex); + av_freep(&req); + return AVERROR(ENOMEM); + } + + if (int_cb) + req->interrupt_callback = *int_cb; + + if (hostname) { + req->hostname = av_strdup(hostname); + if (!req->hostname) + goto fail; + } + + if (servname) { + req->servname = av_strdup(servname); + if (!req->hostname) + goto fail; + } + + if (hints) { + req->hints.ai_family = hints->ai_family; + req->hints.ai_socktype = hints->ai_socktype; + req->hints.ai_protocol = hints->ai_protocol; + req->hints.ai_flags = hints->ai_flags; + } + + req->buffer = av_buffer_create(NULL, 0, tcp_getaddrinfo_request_free_buffer, req, 0); + if (!req->buffer) + goto fail; + + *request = req; + return 0; +fail: + tcp_getaddrinfo_request_free(req); + return AVERROR(ENOMEM); +} + +static void *tcp_getaddrinfo_worker(void *arg) +{ + TCPAddrinfoRequest *req = arg; + + getaddrinfo(req->hostname, req->servname, &req->hints, &req->res); + pthread_mutex_lock(&req->mutex); + req->finished = 1; + pthread_cond_signal(&req->cond); + pthread_mutex_unlock(&req->mutex); + av_buffer_unref(&req->buffer); + return NULL; +} + +static void *tcp_getaddrinfo_one_by_one_worker(void *arg) +{ + struct addrinfo *temp_addrinfo = NULL; + struct addrinfo *cur = NULL; + int ret = EAI_FAIL; + int i = 0; + int option_length = 0; + + pthread_mutex_lock(&req->mutex); + req->finished = 1; + pthread_cond_signal(&req->cond); + pthread_mutex_unlock(&req->mutex); + av_buffer_unref(&req->buffer); + return NULL; +} + +int ijk_tcp_getaddrinfo_nonblock(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res, + int64_t timeout, + const AVIOInterruptCB *int_cb) +{ + int ret; + int64_t start; + int64_t now; + AVBufferRef *req_ref = NULL; + TCPAddrinfoRequest *req = NULL; + pthread_t work_thread; + + if (hostname && !hostname[0]) + hostname = NULL; + + if (timeout <= 0) + return getaddrinfo(hostname, servname, hints, res); + + ret = tcp_getaddrinfo_request_create(&req, hostname, servname, hints, int_cb); + if (ret) + goto fail; + + req_ref = av_buffer_ref(req->buffer); + if (req_ref == NULL) { + ret = AVERROR(ENOMEM); + goto fail; + } + + /* FIXME: using a thread pool would be better. */ + ret = pthread_create(&work_thread, NULL, tcp_getaddrinfo_worker, req); + if (ret) { + ret = AVERROR(ret); + goto fail; + } + + pthread_detach(work_thread); + + start = av_gettime(); + now = start; + + pthread_mutex_lock(&req->mutex); + while (1) { + int64_t wait_time = now + 100000; + struct timespec tv = { .tv_sec = wait_time / 1000000, + .tv_nsec = (wait_time % 1000000) * 1000 }; + + if (req->finished || (start + timeout < now)) { + if (req->res) { + ret = 0; + *res = req->res; + req->res = NULL; + } else { + ret = req->last_error ? req->last_error : AVERROR_EXIT; + } + break; + } +#if defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC) + ret = pthread_cond_timedwait_monotonic_np(&req->cond, &req->mutex, &tv); +#else + ret = pthread_cond_timedwait(&req->cond, &req->mutex, &tv); +#endif + if (ret != 0 && ret != ETIMEDOUT) { + av_log(NULL, AV_LOG_ERROR, "pthread_cond_timedwait failed: %d\n", ret); + ret = AVERROR_EXIT; + break; + } + + if (ff_check_interrupt(&req->interrupt_callback)) { + ret = AVERROR_EXIT; + break; + } + + now = av_gettime(); + } + pthread_mutex_unlock(&req->mutex); +fail: + av_buffer_unref(&req_ref); + return ret; +} + +#else +int ijk_tcp_getaddrinfo_nonblock(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res, + int64_t timeout, + const AVIOInterruptCB *int_cb) +{ + return getaddrinfo(hostname, servname, hints, res); +} +#endif + /* return non zero if error */ static int tcp_open(URLContext *h, const char *uri, int flags) { @@ -115,10 +338,17 @@ static int tcp_open(URLContext *h, const char *uri, int flags) snprintf(portstr, sizeof(portstr), "%d", port); if (s->listen) hints.ai_flags |= AI_PASSIVE; +#ifdef HAVE_PTHREADS + ret = ijk_tcp_getaddrinfo_nonblock(hostname, portstr, &hints, &ai, s->addrinfo_timeout, &h->interrupt_callback); +#else + if (s->addrinfo_timeout > 0) + av_log(h, AV_LOG_WARNING, "Ignore addrinfo_timeout without pthreads support.\n") if (!hostname[0]) ret = getaddrinfo(NULL, portstr, &hints, &ai); else ret = getaddrinfo(hostname, portstr, &hints, &ai); +#endif + if (ret) { av_log(h, AV_LOG_ERROR, "Failed to resolve hostname %s: %s\n", From 2e86e36ac929aa0cba43f6eb96720423c1a2348e Mon Sep 17 00:00:00 2001 From: Xinzheng Zhang Date: Thu, 11 Aug 2016 14:48:44 +0800 Subject: [PATCH 2536/2557] avformat/tcp: add one_by_one option for getaddrinfo() --- libavformat/tcp.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index 5750e8e589d74..a0c8c302c6966 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -48,6 +48,7 @@ typedef struct TCPContext { int tcp_nodelay; int64_t app_ctx_intptr; + int addrinfo_one_by_one; int addrinfo_timeout; AVApplicationContext *app_ctx; @@ -65,6 +66,7 @@ static const AVOption options[] = { { "tcp_nodelay", "Use TCP_NODELAY to disable nagle's algorithm", OFFSET(tcp_nodelay), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E }, { "ijkapplication", "AVApplicationContext", OFFSET(app_ctx_intptr), AV_OPT_TYPE_INT64, { .i64 = 0 }, INT64_MIN, INT64_MAX, .flags = D }, + { "addrinfo_one_by_one", "parse addrinfo one by one in getaddrinfo()", OFFSET(addrinfo_one_by_one), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = D|E }, { "addrinfo_timeout", "set timeout (in microseconds) for getaddrinfo()", OFFSET(addrinfo_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { NULL } }; @@ -193,6 +195,31 @@ static void *tcp_getaddrinfo_one_by_one_worker(void *arg) int i = 0; int option_length = 0; + TCPAddrinfoRequest *req = (TCPAddrinfoRequest *)arg; + + int family_option[2] = {AF_INET, AF_INET6}; + + option_length = sizeof(family_option) / sizeof(family_option[0]); + + for (; i < option_length; ++i) { + struct addrinfo *hint = &req->hints; + hint->ai_family = family_option[i]; + ret = getaddrinfo(req->hostname, req->servname, hint, &temp_addrinfo); + if (ret) { + req->last_error = ret; + continue; + } + pthread_mutex_lock(&req->mutex); + if (!req->res) { + req->res = temp_addrinfo; + } else { + cur = req->res; + while (cur->ai_next) + cur = cur->ai_next; + cur->ai_next = temp_addrinfo; + } + pthread_mutex_unlock(&req->mutex); + } pthread_mutex_lock(&req->mutex); req->finished = 1; pthread_cond_signal(&req->cond); @@ -204,7 +231,7 @@ static void *tcp_getaddrinfo_one_by_one_worker(void *arg) int ijk_tcp_getaddrinfo_nonblock(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res, int64_t timeout, - const AVIOInterruptCB *int_cb) + const AVIOInterruptCB *int_cb, int one_by_one) { int ret; int64_t start; @@ -230,7 +257,11 @@ int ijk_tcp_getaddrinfo_nonblock(const char *hostname, const char *servname, } /* FIXME: using a thread pool would be better. */ - ret = pthread_create(&work_thread, NULL, tcp_getaddrinfo_worker, req); + if (one_by_one) + ret = pthread_create(&work_thread, NULL, tcp_getaddrinfo_one_by_one_worker, req); + else + ret = pthread_create(&work_thread, NULL, tcp_getaddrinfo_worker, req); + if (ret) { ret = AVERROR(ret); goto fail; @@ -339,7 +370,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) if (s->listen) hints.ai_flags |= AI_PASSIVE; #ifdef HAVE_PTHREADS - ret = ijk_tcp_getaddrinfo_nonblock(hostname, portstr, &hints, &ai, s->addrinfo_timeout, &h->interrupt_callback); + ret = ijk_tcp_getaddrinfo_nonblock(hostname, portstr, &hints, &ai, s->addrinfo_timeout, &h->interrupt_callback, s->addrinfo_one_by_one); #else if (s->addrinfo_timeout > 0) av_log(h, AV_LOG_WARNING, "Ignore addrinfo_timeout without pthreads support.\n") From 6196df63658cf97e860d187ac2fa002f2bebb855 Mon Sep 17 00:00:00 2001 From: Xinzheng Zhang Date: Thu, 11 Aug 2016 14:49:00 +0800 Subject: [PATCH 2537/2557] avformat/tcp: export ijk_tcp_getaddrinfo_nonblock --- libavformat/tcp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index a0c8c302c6966..fd080c7e5680d 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -78,6 +78,10 @@ static const AVClass tcp_class = { .version = LIBAVUTIL_VERSION_INT, }; +int ijk_tcp_getaddrinfo_nonblock(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res, + int64_t timeout, + const AVIOInterruptCB *int_cb, int one_by_one); #ifdef HAVE_PTHREADS typedef struct TCPAddrinfoRequest From 5632307aa76c891e2a6e89b6fc036f4fd624e519 Mon Sep 17 00:00:00 2001 From: raymondzheng Date: Tue, 10 Jan 2017 16:53:45 +0800 Subject: [PATCH 2538/2557] avformat/hls: pass down av options --- libavformat/hls.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index a59082d467c23..a66ea3d31c998 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -633,6 +633,7 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, av_dict_copy(&tmp, opts, 0); av_dict_copy(&tmp, opts2, 0); + av_dict_set(&tmp, "seekable", "1", 0); if (av_strstart(url, "crypto", NULL)) { if (url[6] == '+' || url[6] == ':') @@ -1793,7 +1794,7 @@ static int hls_close(AVFormatContext *s) return 0; } -static int hls_read_header(AVFormatContext *s) +static int hls_read_header(AVFormatContext *s, AVDictionary **options) { void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb; HLSContext *c = s->priv_data; @@ -1808,6 +1809,9 @@ static int hls_read_header(AVFormatContext *s) c->first_timestamp = AV_NOPTS_VALUE; c->cur_timestamp = AV_NOPTS_VALUE; + if (options && *options) + av_dict_copy(&c->avio_opts, *options, 0); + if (u) { // get the previous user agent & set back to null if string size is zero update_options(&c->user_agent, "user_agent", u); @@ -2383,7 +2387,7 @@ AVInputFormat ff_hls_demuxer = { .priv_data_size = sizeof(HLSContext), .flags = AVFMT_NOGENSEARCH, .read_probe = hls_probe, - .read_header = hls_read_header, + .read_header2 = hls_read_header, .read_packet = hls_read_packet, .read_close = hls_close, .read_seek = hls_read_seek, From 9241b389ce45281f0537308041541b18b7700811 Mon Sep 17 00:00:00 2001 From: raymondzheng Date: Fri, 23 Dec 2016 12:28:56 +0800 Subject: [PATCH 2539/2557] avformat/protocols: add ijkio --- libavformat/concatdec.c | 1 + libavformat/ijkutils.c | 1 + libavformat/protocols.c | 1 + 3 files changed, 3 insertions(+) diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index ae9ca3369474e..2c9d53c0352ea 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -337,6 +337,7 @@ static int open_file(AVFormatContext *avf, unsigned fileno) if (cat->options) av_dict_copy(&tmp, cat->options, 0); + av_dict_set_int(&tmp, "cur_file_no", fileno, 0); ret = avformat_open_input(&new_avf, file->url, NULL, &tmp); av_dict_free(&tmp); if (ret < 0 || diff --git a/libavformat/ijkutils.c b/libavformat/ijkutils.c index 59aa7c6d3ad0a..3b883fd6f4833 100644 --- a/libavformat/ijkutils.c +++ b/libavformat/ijkutils.c @@ -64,3 +64,4 @@ IJK_DUMMY_PROTOCOL(ijkhttphook); IJK_DUMMY_PROTOCOL(ijklongurl); IJK_DUMMY_PROTOCOL(ijksegment); IJK_DUMMY_PROTOCOL(ijktcphook); +IJK_DUMMY_PROTOCOL(ijkio); diff --git a/libavformat/protocols.c b/libavformat/protocols.c index 7e1aed6004651..6ea2b38ae98fd 100644 --- a/libavformat/protocols.c +++ b/libavformat/protocols.c @@ -44,6 +44,7 @@ extern const URLProtocol ff_ijklongurl_protocol; extern const URLProtocol ff_ijkmediadatasource_protocol; extern const URLProtocol ff_ijksegment_protocol; extern const URLProtocol ff_ijktcphook_protocol; +extern const URLProtocol ff_ijkio_protocol; extern const URLProtocol ff_mmsh_protocol; extern const URLProtocol ff_mmst_protocol; extern const URLProtocol ff_md5_protocol; From f4bc0317aa74adc6e2524c354951c6974af87c80 Mon Sep 17 00:00:00 2001 From: raymondzheng Date: Fri, 24 Mar 2017 11:52:00 +0800 Subject: [PATCH 2540/2557] avformat/tcp: support option rw_timeout and connect_timeout --- libavformat/tcp.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index fd080c7e5680d..94f9c5c859e4e 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -60,6 +60,7 @@ typedef struct TCPContext { static const AVOption options[] = { { "listen", "Listen for incoming connections", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, .flags = D|E }, { "timeout", "set timeout (in microseconds) of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "connect_timeout", "set connect timeout (in microseconds) of socket", OFFSET(open_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "listen_timeout", "Connection awaiting timeout (in milliseconds)", OFFSET(listen_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "send_buffer_size", "Socket send buffer size (in bytes)", OFFSET(send_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "recv_buffer_size", "Socket receive buffer size (in bytes)", OFFSET(recv_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, @@ -337,7 +338,11 @@ static int tcp_open(URLContext *h, const char *uri, int flags) int ret; char hostname[1024],proto[1024],path[1024]; char portstr[10]; - s->open_timeout = 5000000; + + if (s->open_timeout < 0) { + s->open_timeout = 15000000; + } + s->app_ctx = (AVApplicationContext *)(intptr_t)s->app_ctx_intptr; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), @@ -359,15 +364,18 @@ static int tcp_open(URLContext *h, const char *uri, int flags) } if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { s->rw_timeout = strtol(buf, NULL, 10); + if (s->rw_timeout >= 0) { + s->open_timeout = s->rw_timeout; + } } if (av_find_info_tag(buf, sizeof(buf), "listen_timeout", p)) { s->listen_timeout = strtol(buf, NULL, 10); } } - if (s->rw_timeout >= 0) { - s->open_timeout = - h->rw_timeout = s->rw_timeout; + if (s->rw_timeout >= 0 ) { + h->rw_timeout = s->rw_timeout; } + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); From dc46625d34c3572880d0939652f9085e7a21ac5d Mon Sep 17 00:00:00 2001 From: raymondzheng Date: Fri, 12 May 2017 12:21:37 +0800 Subject: [PATCH 2541/2557] avformat/pipe: enable seekable --- libavformat/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/file.c b/libavformat/file.c index 1d321c42050e3..dabecf59ca7e1 100644 --- a/libavformat/file.c +++ b/libavformat/file.c @@ -386,7 +386,7 @@ static int pipe_open(URLContext *h, const char *filename, int flags) setmode(fd, O_BINARY); #endif c->fd = fd; - h->is_streamed = 1; + h->is_streamed = 0; return 0; } @@ -395,6 +395,7 @@ const URLProtocol ff_pipe_protocol = { .url_open = pipe_open, .url_read = file_read, .url_write = file_write, + .url_seek = file_seek, .url_get_file_handle = file_get_handle, .url_check = file_check, .priv_data_size = sizeof(FileContext), From debff0dca7f7c55b938f6f1ad3e74c1c6aa9d0f0 Mon Sep 17 00:00:00 2001 From: raymondzheng Date: Mon, 10 Jul 2017 18:50:38 +0800 Subject: [PATCH 2542/2557] avformat/utils: support don't get real frame rate --- libavformat/concatdec.c | 11 +++++++++++ libavformat/utils.c | 14 ++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 2c9d53c0352ea..6da37ea6f4b05 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -323,6 +323,8 @@ static int open_file(AVFormatContext *avf, unsigned fileno) AVFormatContext *new_avf = NULL; int ret; AVDictionary *tmp = NULL; + AVDictionaryEntry *t = NULL; + int fps_flag = 0; new_avf = avformat_alloc_context(); if (!new_avf) @@ -338,6 +340,15 @@ static int open_file(AVFormatContext *avf, unsigned fileno) av_dict_copy(&tmp, cat->options, 0); av_dict_set_int(&tmp, "cur_file_no", fileno, 0); + + t = av_dict_get(tmp, "skip-calc-frame-rate", NULL, AV_DICT_MATCH_CASE); + if (t) { + fps_flag = (int) strtol(t->value, NULL, 10); + if (fps_flag > 0) { + av_dict_set_int(&new_avf->metadata, "skip-calc-frame-rate", fps_flag, 0); + } + } + ret = avformat_open_input(&new_avf, file->url, NULL, &tmp); av_dict_free(&tmp); if (ret < 0 || diff --git a/libavformat/utils.c b/libavformat/utils.c index 12cf4bdd9499c..a960ecea0e621 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -3697,6 +3697,20 @@ FF_ENABLE_DEPRECATION_WARNINGS st = ic->streams[i]; if (!has_codec_parameters(st, NULL)) break; + + if (ic->metadata) { + AVDictionaryEntry *t = av_dict_get(ic->metadata, "skip-calc-frame-rate", NULL, AV_DICT_MATCH_CASE); + if (t) { + int fps_flag = (int) strtol(t->value, NULL, 10); + if (!st->r_frame_rate.num && st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0 && fps_flag > 0) { + int avg_fps = st->avg_frame_rate.num / st->avg_frame_rate.den; + if (avg_fps > 0 && avg_fps <= 120) { + st->r_frame_rate.num = st->avg_frame_rate.num; + st->r_frame_rate.den = st->avg_frame_rate.den; + } + } + } + } /* If the timebase is coarse (like the usual millisecond precision * of mkv), we need to analyze more frames to reliably arrive at * the correct fps. */ From 071175acfd7e0a6e83dec21918c0b9da4605db16 Mon Sep 17 00:00:00 2001 From: raymondzheng Date: Fri, 11 Aug 2017 18:58:55 +0800 Subject: [PATCH 2543/2557] libavformat/tcp: support dns cache --- libavformat/tcp.c | 75 +++++++++---- libavutil/Makefile | 2 + libavutil/application.c | 23 ++-- libavutil/application.h | 2 +- libavutil/dns_cache.c | 229 ++++++++++++++++++++++++++++++++++++++++ libavutil/dns_cache.h | 38 +++++++ 6 files changed, 338 insertions(+), 31 deletions(-) create mode 100644 libavutil/dns_cache.c create mode 100644 libavutil/dns_cache.h diff --git a/libavformat/tcp.c b/libavformat/tcp.c index 94f9c5c859e4e..d5678d6fb54e7 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -24,6 +24,7 @@ #include "libavutil/opt.h" #include "libavutil/time.h" #include "libavutil/application.h" +#include "libavutil/dns_cache.h" #include "internal.h" #include "network.h" @@ -50,6 +51,8 @@ typedef struct TCPContext { int addrinfo_one_by_one; int addrinfo_timeout; + int64_t dns_cache_timeout; + int dns_cache_clear; AVApplicationContext *app_ctx; } TCPContext; @@ -69,6 +72,8 @@ static const AVOption options[] = { { "addrinfo_one_by_one", "parse addrinfo one by one in getaddrinfo()", OFFSET(addrinfo_one_by_one), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = D|E }, { "addrinfo_timeout", "set timeout (in microseconds) for getaddrinfo()", OFFSET(addrinfo_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "dns_cache_timeout", "dns cache TTL (in microseconds)", OFFSET(dns_cache_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "dns_cache_clear", "clear dns cache", OFFSET(dns_cache_clear), AV_OPT_TYPE_INT, { .i64 = 0}, -1, INT_MAX, .flags = D|E }, { NULL } }; @@ -338,6 +343,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags) int ret; char hostname[1024],proto[1024],path[1024]; char portstr[10]; + char hostname_bak[1024] = {0}; + AVAppTcpIOControl control = {0}; + DnsCacheEntry *dns_entry = NULL; if (s->open_timeout < 0) { s->open_timeout = 15000000; @@ -381,25 +389,41 @@ static int tcp_open(URLContext *h, const char *uri, int flags) snprintf(portstr, sizeof(portstr), "%d", port); if (s->listen) hints.ai_flags |= AI_PASSIVE; + + if (s->dns_cache_timeout > 0) { + memcpy(hostname_bak, hostname, 1024); + if (s->dns_cache_clear) { + av_log(NULL, AV_LOG_INFO, "will delete cache entry, hostname = %s\n", hostname); + remove_dns_cache_entry(hostname); + } else { + dns_entry = get_dns_cache_reference(hostname); + } + } + + if (!dns_entry) { #ifdef HAVE_PTHREADS - ret = ijk_tcp_getaddrinfo_nonblock(hostname, portstr, &hints, &ai, s->addrinfo_timeout, &h->interrupt_callback, s->addrinfo_one_by_one); + ret = ijk_tcp_getaddrinfo_nonblock(hostname, portstr, &hints, &ai, s->addrinfo_timeout, &h->interrupt_callback, s->addrinfo_one_by_one); #else - if (s->addrinfo_timeout > 0) - av_log(h, AV_LOG_WARNING, "Ignore addrinfo_timeout without pthreads support.\n") - if (!hostname[0]) - ret = getaddrinfo(NULL, portstr, &hints, &ai); - else - ret = getaddrinfo(hostname, portstr, &hints, &ai); + if (s->addrinfo_timeout > 0) + av_log(h, AV_LOG_WARNING, "Ignore addrinfo_timeout without pthreads support.\n"); + if (!hostname[0]) + ret = getaddrinfo(NULL, portstr, &hints, &ai); + else + ret = getaddrinfo(hostname, portstr, &hints, &ai); #endif - if (ret) { - av_log(h, AV_LOG_ERROR, - "Failed to resolve hostname %s: %s\n", - hostname, gai_strerror(ret)); - return AVERROR(EIO); - } + if (ret) { + av_log(h, AV_LOG_ERROR, + "Failed to resolve hostname %s: %s\n", + hostname, gai_strerror(ret)); + return AVERROR(EIO); + } - cur_ai = ai; + cur_ai = ai; + } else { + av_log(NULL, AV_LOG_INFO, "Hit DNS cache hostname = %s\n", hostname); + cur_ai = dns_entry->res; + } restart: #if HAVE_STRUCT_SOCKADDR_IN6 @@ -452,17 +476,20 @@ static int tcp_open(URLContext *h, const char *uri, int flags) if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, s->open_timeout / 1000, h, !!cur_ai->ai_next)) < 0) { - if (av_application_on_tcp_did_open(s->app_ctx, ret, fd)) + if (av_application_on_tcp_did_open(s->app_ctx, ret, fd, &control)) goto fail1; if (ret == AVERROR_EXIT) goto fail1; else goto fail; } else { - ret = av_application_on_tcp_did_open(s->app_ctx, 0, fd); + ret = av_application_on_tcp_did_open(s->app_ctx, 0, fd, &control); if (ret) { av_log(NULL, AV_LOG_WARNING, "terminated by application in AVAPP_CTRL_DID_TCP_OPEN"); goto fail1; + } else if (!dns_entry && strcmp(control.ip, hostname_bak)) { + add_dns_cache_entry(hostname_bak, cur_ai, s->dns_cache_timeout); + av_log(NULL, AV_LOG_INFO, "Add dns cache hostname = %s, ip = %s\n", hostname_bak , control.ip); } } } @@ -470,7 +497,11 @@ static int tcp_open(URLContext *h, const char *uri, int flags) h->is_streamed = 1; s->fd = fd; - freeaddrinfo(ai); + if (dns_entry) { + release_dns_cache_reference(hostname_bak, &dns_entry); + } else { + freeaddrinfo(ai); + } return 0; fail: @@ -485,7 +516,15 @@ static int tcp_open(URLContext *h, const char *uri, int flags) fail1: if (fd >= 0) closesocket(fd); - freeaddrinfo(ai); + + if (dns_entry) { + av_log(NULL, AV_LOG_ERROR, "Hit dns cache but connect fail hostname = %s, ip = %s\n", hostname , control.ip); + release_dns_cache_reference(hostname_bak, &dns_entry); + remove_dns_cache_entry(hostname_bak); + } else { + freeaddrinfo(ai); + } + return ret; } diff --git a/libavutil/Makefile b/libavutil/Makefile index 6e52439cb695f..f4b03c6160651 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -26,6 +26,7 @@ HEADERS = adler32.h \ display.h \ downmix_info.h \ encryption_info.h \ + dns_cache.h \ error.h \ eval.h \ fifo.h \ @@ -112,6 +113,7 @@ OBJS = adler32.o \ display.o \ downmix_info.o \ encryption_info.o \ + dns_cache.o \ error.o \ eval.o \ fifo.o \ diff --git a/libavutil/application.c b/libavutil/application.c index 2626742a0b291..3a4ec85071815 100644 --- a/libavutil/application.c +++ b/libavutil/application.c @@ -148,14 +148,13 @@ int av_application_on_tcp_will_open(AVApplicationContext *h) } // only callback returns error -int av_application_on_tcp_did_open(AVApplicationContext *h, int error, int fd) +int av_application_on_tcp_did_open(AVApplicationContext *h, int error, int fd, AVAppTcpIOControl *control) { struct sockaddr_storage so_stg; int ret = 0; socklen_t so_len = sizeof(so_stg); int so_family; - AVAppTcpIOControl control = {0}; - char *so_ip_name = control.ip; + char *so_ip_name = control->ip; if (!h || !h->func_on_app_event || fd <= 0) return 0; @@ -163,30 +162,30 @@ int av_application_on_tcp_did_open(AVApplicationContext *h, int error, int fd) ret = getpeername(fd, (struct sockaddr *)&so_stg, &so_len); if (ret) return 0; - control.error = error; - control.fd = fd; + control->error = error; + control->fd = fd; so_family = ((struct sockaddr*)&so_stg)->sa_family; switch (so_family) { case AF_INET: { struct sockaddr_in* in4 = (struct sockaddr_in*)&so_stg; - if (inet_ntop(AF_INET, &(in4->sin_addr), so_ip_name, sizeof(control.ip))) { - control.family = AF_INET; - control.port = in4->sin_port; + if (inet_ntop(AF_INET, &(in4->sin_addr), so_ip_name, sizeof(control->ip))) { + control->family = AF_INET; + control->port = in4->sin_port; } break; } case AF_INET6: { struct sockaddr_in6* in6 = (struct sockaddr_in6*)&so_stg; - if (inet_ntop(AF_INET6, &(in6->sin6_addr), so_ip_name, sizeof(control.ip))) { - control.family = AF_INET6; - control.port = in6->sin6_port; + if (inet_ntop(AF_INET6, &(in6->sin6_addr), so_ip_name, sizeof(control->ip))) { + control->family = AF_INET6; + control->port = in6->sin6_port; } break; } } - return h->func_on_app_event(h, AVAPP_CTRL_DID_TCP_OPEN, (void *)&control, sizeof(AVAppTcpIOControl)); + return h->func_on_app_event(h, AVAPP_CTRL_DID_TCP_OPEN, (void *)control, sizeof(AVAppTcpIOControl)); } void av_application_on_async_statistic(AVApplicationContext *h, AVAppAsyncStatistic *statistic) diff --git a/libavutil/application.h b/libavutil/application.h index a33b272fdd5c4..9e2c1f5b1aadb 100644 --- a/libavutil/application.h +++ b/libavutil/application.h @@ -111,7 +111,7 @@ void av_application_did_io_tcp_read(AVApplicationContext *h, void *obj, int byte int av_application_on_io_control(AVApplicationContext *h, int event_type, AVAppIOControl *control); int av_application_on_tcp_will_open(AVApplicationContext *h); -int av_application_on_tcp_did_open(AVApplicationContext *h, int error, int fd); +int av_application_on_tcp_did_open(AVApplicationContext *h, int error, int fd, AVAppTcpIOControl *control); void av_application_on_async_statistic(AVApplicationContext *h, AVAppAsyncStatistic *statistic); void av_application_on_async_read_speed(AVApplicationContext *h, AVAppAsyncReadSpeed *speed); diff --git a/libavutil/dns_cache.c b/libavutil/dns_cache.c new file mode 100644 index 0000000000000..c70540146e814 --- /dev/null +++ b/libavutil/dns_cache.c @@ -0,0 +1,229 @@ +/* + * copyright (c) 2017 Raymond Zheng + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/dns_cache.h" +#include "libavutil/time.h" +#include "libavformat/network.h" + +#if HAVE_PTHREADS +#include +#endif + +typedef struct DnsCacheContext DnsCacheContext; +typedef struct DnsCacheContext { + AVDictionary *dns_dictionary; + pthread_mutex_t dns_dictionary_mutex; + int initialized; +} DnsCacheContext; + +static DnsCacheContext *context = NULL; +static pthread_once_t key_once = PTHREAD_ONCE_INIT; + +static void inner_init(void) { + int ret = 0; + context = (DnsCacheContext *) av_mallocz(sizeof(DnsCacheContext)); + if (context) { + ret = pthread_mutex_init(&context->dns_dictionary_mutex, NULL); + if (!ret) { + context->initialized = 1; + } else { + av_freep(&context); + } + } +} + +static void free_private_addrinfo(struct addrinfo **p_ai) { + struct addrinfo *ai = *p_ai; + + if (ai) { + if (ai->ai_addr) { + av_freep(&ai->ai_addr); + } + av_freep(p_ai); + } +} + +static int inner_remove_dns_cache(char *hostname, DnsCacheEntry *dns_cache_entry) { + if (context && dns_cache_entry) { + if (dns_cache_entry->ref_count == 0) { + av_dict_set_int(&context->dns_dictionary, hostname, 0, 0); + free_private_addrinfo(&dns_cache_entry->res); + av_freep(&dns_cache_entry); + } else { + dns_cache_entry->delete_flag = 1; + } + } + + return 0; +} + +static DnsCacheEntry *new_dns_cache_entry(char *hostname, struct addrinfo *cur_ai, int64_t timeout) { + DnsCacheEntry *new_entry = NULL; + int64_t cur_time = av_gettime_relative(); + + if (cur_time < 0) { + goto fail; + } + + new_entry = (DnsCacheEntry *) av_mallocz(sizeof(struct DnsCacheEntry)); + if (!new_entry) { + goto fail; + } + + new_entry->res = (struct addrinfo *) av_mallocz(sizeof(struct addrinfo)); + if (!new_entry->res) { + av_freep(&new_entry); + goto fail; + } + + memcpy(new_entry->res, cur_ai, sizeof(struct addrinfo)); + + new_entry->res->ai_addr = (struct sockaddr *) av_mallocz(sizeof(struct sockaddr)); + if (!new_entry->res->ai_addr) { + av_freep(&new_entry->res); + av_freep(&new_entry); + goto fail; + } + + memcpy(new_entry->res->ai_addr, cur_ai->ai_addr, sizeof(struct sockaddr)); + new_entry->res->ai_canonname = NULL; + new_entry->res->ai_next = NULL; + new_entry->ref_count = 0; + new_entry->delete_flag = 0; + new_entry->expired_time = cur_time + timeout * 1000; + + return new_entry; + +fail: + return NULL; +} + +DnsCacheEntry *get_dns_cache_reference(char *hostname) { + AVDictionaryEntry *elem = NULL; + DnsCacheEntry *dns_cache_entry = NULL; + int64_t cur_time = av_gettime_relative(); + + if (cur_time < 0 || !hostname || strlen(hostname) == 0) { + return NULL; + } + + if (!context || !context->initialized) { +#if HAVE_PTHREADS + pthread_once(&key_once, inner_init); +#endif + } + + if (context && context->initialized) { + pthread_mutex_lock(&context->dns_dictionary_mutex); + elem = av_dict_get(context->dns_dictionary, hostname, NULL, AV_DICT_MATCH_CASE); + if (elem) { + dns_cache_entry = (DnsCacheEntry *) (intptr_t) strtoll(elem->value, NULL, 10); + if (dns_cache_entry) { + if (dns_cache_entry->expired_time < cur_time) { + inner_remove_dns_cache(hostname, dns_cache_entry); + dns_cache_entry = NULL; + } else { + dns_cache_entry->ref_count++; + } + } + } + pthread_mutex_unlock(&context->dns_dictionary_mutex); + } + + return dns_cache_entry; +} + +int release_dns_cache_reference(char *hostname, DnsCacheEntry **p_entry) { + DnsCacheEntry *entry = *p_entry; + + if (!hostname || strlen(hostname) == 0) { + return -1; + } + + if (context && context->initialized && entry) { + pthread_mutex_lock(&context->dns_dictionary_mutex); + entry->ref_count--; + if (entry->delete_flag && entry->ref_count == 0) { + inner_remove_dns_cache(hostname, entry); + entry = NULL; + } + pthread_mutex_unlock(&context->dns_dictionary_mutex); + } + return 0; +} + +int remove_dns_cache_entry(char *hostname) { + AVDictionaryEntry *elem = NULL; + DnsCacheEntry *dns_cache_entry = NULL; + + if (!hostname || strlen(hostname) == 0) { + return -1; + } + + if (context && context->initialized) { + pthread_mutex_lock(&context->dns_dictionary_mutex); + elem = av_dict_get(context->dns_dictionary, hostname, NULL, AV_DICT_MATCH_CASE); + if (elem) { + dns_cache_entry = (DnsCacheEntry *) (intptr_t) strtoll(elem->value, NULL, 10); + if (dns_cache_entry) { + inner_remove_dns_cache(hostname, dns_cache_entry); + } + } + pthread_mutex_unlock(&context->dns_dictionary_mutex); + } + + return 0; +} + +int add_dns_cache_entry(char *hostname, struct addrinfo *cur_ai, int64_t timeout) { + DnsCacheEntry *new_entry = NULL; + DnsCacheEntry *old_entry = NULL; + AVDictionaryEntry *elem = NULL; + + if (!hostname || strlen(hostname) == 0 || timeout <= 0) { + goto fail; + } + + if (cur_ai == NULL || cur_ai->ai_addr == NULL) { + goto fail; + } + + if (context && context->initialized) { + pthread_mutex_lock(&context->dns_dictionary_mutex); + elem = av_dict_get(context->dns_dictionary, hostname, NULL, AV_DICT_MATCH_CASE); + if (elem) { + old_entry = (DnsCacheEntry *) (intptr_t) strtoll(elem->value, NULL, 10); + if (old_entry) { + pthread_mutex_unlock(&context->dns_dictionary_mutex); + goto fail; + } + } + new_entry = new_dns_cache_entry(hostname, cur_ai, timeout); + if (new_entry) { + av_dict_set_int(&context->dns_dictionary, hostname, (int64_t) (intptr_t) new_entry, 0); + } + pthread_mutex_unlock(&context->dns_dictionary_mutex); + + return 0; + } + +fail: + return -1; +} diff --git a/libavutil/dns_cache.h b/libavutil/dns_cache.h new file mode 100644 index 0000000000000..a2ed92e6f54a8 --- /dev/null +++ b/libavutil/dns_cache.h @@ -0,0 +1,38 @@ +/* + * copyright (c) 2017 Raymond Zheng + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_DNS_CACHE_H +#define AVUTIL_DNS_CACHE_H + +#include "libavutil/log.h" + +typedef struct DnsCacheEntry { + volatile int ref_count; + volatile int delete_flag; + int64_t expired_time; + struct addrinfo *res; // construct by private function, not support ai_next and ai_canonname, can only be released using free_private_addrinfo +} DnsCacheEntry; + +DnsCacheEntry *get_dns_cache_reference(char *hostname); +int release_dns_cache_reference(char *hostname, DnsCacheEntry **p_entry); +int remove_dns_cache_entry(char *hostname); +int add_dns_cache_entry(char *hostname, struct addrinfo *cur_ai, int64_t timeout); + +#endif /* AVUTIL_DNS_CACHE_H */ From 4ed7a52042c3c25fe75de9d881c4f8f44b35ef62 Mon Sep 17 00:00:00 2001 From: raymondzheng Date: Tue, 29 Aug 2017 11:49:05 +0800 Subject: [PATCH 2544/2557] libavformat/flv: support HEVC --- libavformat/flv.h | 1 + libavformat/flvdec.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libavformat/flv.h b/libavformat/flv.h index df5ce3d17f8c7..97324cca46d5a 100644 --- a/libavformat/flv.h +++ b/libavformat/flv.h @@ -109,6 +109,7 @@ enum { FLV_CODECID_H264 = 7, FLV_CODECID_REALH263= 8, FLV_CODECID_MPEG4 = 9, + FLV_CODECID_HEVC = 12, }; enum { diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 34c3e08bad23d..10c16e9c93fc6 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -291,6 +291,8 @@ static int flv_same_video_codec(AVCodecParameters *vpar, int flags) return vpar->codec_id == AV_CODEC_ID_VP6A; case FLV_CODECID_H264: return vpar->codec_id == AV_CODEC_ID_H264; + case FLV_CODECID_HEVC: + return vpar->codec_id == AV_CODEC_ID_HEVC; default: return vpar->codec_tag == flv_codecid; } @@ -331,6 +333,11 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, } ret = 1; // 1 byte body size adjustment for flv_read_packet() break; + case FLV_CODECID_HEVC: + par->codec_id = AV_CODEC_ID_HEVC; + vstream->need_parsing = AVSTREAM_PARSE_NONE; + ret = 3; // not 4, reading packet type will consume one byte + break; case FLV_CODECID_H264: par->codec_id = AV_CODEC_ID_H264; vstream->need_parsing = AVSTREAM_PARSE_HEADERS; @@ -1151,7 +1158,8 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) if (st->codecpar->codec_id == AV_CODEC_ID_AAC || st->codecpar->codec_id == AV_CODEC_ID_H264 || - st->codecpar->codec_id == AV_CODEC_ID_MPEG4) { + st->codecpar->codec_id == AV_CODEC_ID_MPEG4 || + st->codecpar->codec_id == AV_CODEC_ID_HEVC) { int type = avio_r8(s->pb); size--; @@ -1160,7 +1168,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) goto leave; } - if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4) { + if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4 || st->codecpar->codec_id == AV_CODEC_ID_HEVC) { // sign extension int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000; pts = dts + cts; @@ -1176,7 +1184,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) } } if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC || - st->codecpar->codec_id == AV_CODEC_ID_H264)) { + st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC)) { AVDictionaryEntry *t; if (st->codecpar->extradata) { From e902c77f0e8b7244237fb22854ed97974b7fd8e8 Mon Sep 17 00:00:00 2001 From: raymondzheng Date: Fri, 22 Dec 2017 18:58:45 +0800 Subject: [PATCH 2545/2557] avformat/tcp: support tcp fastopen --- libavformat/http.c | 1 + libavformat/network.c | 46 +++++++++ libavformat/network.h | 5 + libavformat/tcp.c | 222 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 274 insertions(+) diff --git a/libavformat/http.c b/libavformat/http.c index 3fb9ba0d1fa60..8fe2fced1a3c1 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -215,6 +215,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options) proxy_path && av_strstart(proxy_path, "http://", NULL); if (!strcmp(proto, "https")) { + av_dict_set_int(options, "fastopen", 0, 0); lower_proto = "tls"; use_proxy = 0; if (port < 0) diff --git a/libavformat/network.c b/libavformat/network.c index d5c82e9ab9ba8..f44b1245b3289 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -293,6 +293,52 @@ int ff_listen_connect(int fd, const struct sockaddr *addr, return ret; } +int ff_sendto(int fd, const char *msg, int msg_len, int flag, + const struct sockaddr *addr, + socklen_t addrlen, int timeout, URLContext *h, + int will_try_next) +{ + struct pollfd p = {fd, POLLOUT, 0}; + int ret; + socklen_t optlen; + + if (ff_socket_nonblock(fd, 1) < 0) + av_log(NULL, AV_LOG_INFO, "ff_socket_nonblock failed\n"); + + while ((ret = sendto(fd, msg, msg_len, flag, addr, addrlen)) < 0) { + ret = ff_neterrno(); + switch (ret) { + case AVERROR(EINTR): + if (ff_check_interrupt(&h->interrupt_callback)) + return AVERROR_EXIT; + continue; + case AVERROR(EINPROGRESS): + case AVERROR(EAGAIN): + ret = ff_poll_interrupt(&p, 1, timeout, &h->interrupt_callback); + if (ret < 0) + return ret; + optlen = sizeof(ret); + if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) + ret = AVUNERROR(ff_neterrno()); + if (ret != 0) { + char errbuf[100]; + ret = AVERROR(ret); + av_strerror(ret, errbuf, sizeof(errbuf)); + if (will_try_next) + av_log(h, AV_LOG_WARNING, + "Connection to %s failed (%s), trying next address\n", + h->filename, errbuf); + else + av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n", + h->filename, errbuf); + } + default: + return ret; + } + } + return ret; +} + static int match_host_pattern(const char *pattern, const char *hostname) { int len_p, len_h; diff --git a/libavformat/network.h b/libavformat/network.h index e3fda4d5e2da1..a9abd0eed0235 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -300,6 +300,11 @@ int ff_listen_connect(int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h, int will_try_next); +int ff_sendto(int fd, const char *msg, int msg_len, int flag, + const struct sockaddr *addr, + socklen_t addrlen, int timeout, URLContext *h, + int will_try_next); + int ff_http_match_no_proxy(const char *no_proxy, const char *hostname); int ff_socket(int domain, int type, int protocol); diff --git a/libavformat/tcp.c b/libavformat/tcp.c index d5678d6fb54e7..9cc55562933fc 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -55,8 +55,14 @@ typedef struct TCPContext { int dns_cache_clear; AVApplicationContext *app_ctx; + char uri[1024]; + int fastopen; + int tcp_connected; + int fastopen_success; } TCPContext; +#define FAST_OPEN_FLAG 0x20000000 + #define OFFSET(x) offsetof(TCPContext, x) #define D AV_OPT_FLAG_DECODING_PARAM #define E AV_OPT_FLAG_ENCODING_PARAM @@ -74,6 +80,7 @@ static const AVOption options[] = { { "addrinfo_timeout", "set timeout (in microseconds) for getaddrinfo()", OFFSET(addrinfo_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "dns_cache_timeout", "dns cache TTL (in microseconds)", OFFSET(dns_cache_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, { "dns_cache_clear", "clear dns cache", OFFSET(dns_cache_clear), AV_OPT_TYPE_INT, { .i64 = 0}, -1, INT_MAX, .flags = D|E }, + { "fastopen", "enable fastopen", OFFSET(fastopen), AV_OPT_TYPE_INT, { .i64 = 0}, 0, INT_MAX, .flags = D|E }, { NULL } }; @@ -353,6 +360,12 @@ static int tcp_open(URLContext *h, const char *uri, int flags) s->app_ctx = (AVApplicationContext *)(intptr_t)s->app_ctx_intptr; + if (s->fastopen) { + s->tcp_connected = 0; + strcpy(s->uri, uri); + return 0; + } + av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (strcmp(proto, "tcp")) @@ -528,6 +541,196 @@ static int tcp_open(URLContext *h, const char *uri, int flags) return ret; } +/* return non zero if error */ +static int tcp_fast_open(URLContext *h, const char *http_request, const char *uri, int flags) +{ + struct addrinfo hints = { 0 }, *ai, *cur_ai; + int port, fd = -1; + TCPContext *s = h->priv_data; + const char *p; + char buf[256]; + int ret; + char hostname[1024],proto[1024],path[1024]; + char portstr[10]; + char hostname_bak[1024] = {0}; + AVAppTcpIOControl control = {0}; + DnsCacheEntry *dns_entry = NULL; + av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), + &port, path, sizeof(path), uri); + if (strcmp(proto, "tcp")) + return AVERROR(EINVAL); + if (port <= 0 || port >= 65536) { + av_log(h, AV_LOG_ERROR, "Port missing in uri\n"); + return AVERROR(EINVAL); + } + p = strchr(uri, '?'); + + if (p) { + if (av_find_info_tag(buf, sizeof(buf), "listen", p)) { + char *endptr = NULL; + s->listen = strtol(buf, &endptr, 10); + /* assume if no digits were found it is a request to enable it */ + if (buf == endptr) + s->listen = 1; + } + if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { + s->rw_timeout = strtol(buf, NULL, 10); + if (s->rw_timeout >= 0) { + s->open_timeout = s->rw_timeout; + } + } + if (av_find_info_tag(buf, sizeof(buf), "listen_timeout", p)) { + s->listen_timeout = strtol(buf, NULL, 10); + } + } + if (s->rw_timeout >= 0 ) { + h->rw_timeout = s->rw_timeout; + } + + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + snprintf(portstr, sizeof(portstr), "%d", port); + if (s->listen) + hints.ai_flags |= AI_PASSIVE; + + if (s->dns_cache_timeout > 0) { + memcpy(hostname_bak, hostname, 1024); + if (s->dns_cache_clear) { + av_log(NULL, AV_LOG_INFO, "will delete cache entry, hostname = %s\n", hostname); + remove_dns_cache_entry(hostname); + } else { + dns_entry = get_dns_cache_reference(hostname); + } + } + + if (!dns_entry) { +#ifdef HAVE_PTHREADS + ret = ijk_tcp_getaddrinfo_nonblock(hostname, portstr, &hints, &ai, s->addrinfo_timeout, &h->interrupt_callback, s->addrinfo_one_by_one); +#else + if (s->addrinfo_timeout > 0) + av_log(h, AV_LOG_WARNING, "Ignore addrinfo_timeout without pthreads support.\n"); + if (!hostname[0]) + ret = getaddrinfo(NULL, portstr, &hints, &ai); + else + ret = getaddrinfo(hostname, portstr, &hints, &ai); +#endif + + if (ret) { + av_log(h, AV_LOG_ERROR, + "Failed to resolve hostname %s: %s\n", + hostname, gai_strerror(ret)); + return AVERROR(EIO); + } + + cur_ai = ai; + } else { + av_log(NULL, AV_LOG_INFO, "Hit DNS cache hostname = %s\n", hostname); + cur_ai = dns_entry->res; + } + + restart: +#if HAVE_STRUCT_SOCKADDR_IN6 + // workaround for IOS9 getaddrinfo in IPv6 only network use hardcode IPv4 address can not resolve port number. + if (cur_ai->ai_family == AF_INET6){ + struct sockaddr_in6 * sockaddr_v6 = (struct sockaddr_in6 *)cur_ai->ai_addr; + if (!sockaddr_v6->sin6_port){ + sockaddr_v6->sin6_port = htons(port); + } + } +#endif + fd = ff_socket(cur_ai->ai_family, + cur_ai->ai_socktype, + cur_ai->ai_protocol); + if (fd < 0) { + ret = ff_neterrno(); + goto fail; + } + /* Set the socket's send or receive buffer sizes, if specified. + If unspecified or setting fails, system default is used. */ + if (s->recv_buffer_size > 0) { + setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &s->recv_buffer_size, sizeof (s->recv_buffer_size)); + } + if (s->send_buffer_size > 0) { + setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &s->send_buffer_size, sizeof (s->send_buffer_size)); + } + if (s->listen == 2) { + // multi-client + if ((ret = ff_listen(fd, cur_ai->ai_addr, cur_ai->ai_addrlen)) < 0) + goto fail1; + } else if (s->listen == 1) { + // single client + if ((ret = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, + s->listen_timeout, h)) < 0) + goto fail1; + // Socket descriptor already closed here. Safe to overwrite to client one. + fd = ret; + } else { + ret = av_application_on_tcp_will_open(s->app_ctx); + if (ret) { + av_log(NULL, AV_LOG_WARNING, "terminated by application in AVAPP_CTRL_WILL_TCP_OPEN"); + goto fail1; + } + + if ((ret = ff_sendto(fd, http_request, strlen(http_request), FAST_OPEN_FLAG, + cur_ai->ai_addr, cur_ai->ai_addrlen, s->open_timeout / 1000, h, !!cur_ai->ai_next)) < 0) { + s->fastopen_success = 0; + if (av_application_on_tcp_did_open(s->app_ctx, ret, fd, &control)) + goto fail1; + if (ret == AVERROR_EXIT) + goto fail1; + else + goto fail; + } else { + if (ret == 0) { + s->fastopen_success = 0; + } else { + s->fastopen_success = 1; + } + ret = av_application_on_tcp_did_open(s->app_ctx, 0, fd, &control); + if (ret) { + av_log(NULL, AV_LOG_WARNING, "terminated by application in AVAPP_CTRL_DID_TCP_OPEN"); + goto fail1; + } else if (!dns_entry && strcmp(control.ip, hostname_bak)) { + add_dns_cache_entry(hostname_bak, cur_ai, s->dns_cache_timeout); + av_log(NULL, AV_LOG_INFO, "Add dns cache hostname = %s, ip = %s\n", hostname_bak , control.ip); + } + } + } + + h->is_streamed = 1; + s->fd = fd; + + if (dns_entry) { + release_dns_cache_reference(hostname_bak, &dns_entry); + } else { + freeaddrinfo(ai); + } + return 0; + + fail: + if (cur_ai->ai_next) { + /* Retry with the next sockaddr */ + cur_ai = cur_ai->ai_next; + if (fd >= 0) + closesocket(fd); + ret = 0; + goto restart; + } + fail1: + if (fd >= 0) + closesocket(fd); + + if (dns_entry) { + av_log(NULL, AV_LOG_ERROR, "Hit dns cache but connect fail hostname = %s, ip = %s\n", hostname , control.ip); + release_dns_cache_reference(hostname_bak, &dns_entry); + remove_dns_cache_entry(hostname_bak); + } else { + freeaddrinfo(ai); + } + + return ret; +} + static int tcp_accept(URLContext *s, URLContext **c) { TCPContext *sc = s->priv_data; @@ -572,6 +775,25 @@ static int tcp_write(URLContext *h, const uint8_t *buf, int size) if (ret) return ret; } + + if (s->fastopen && !s->tcp_connected && av_stristart(buf, "GET", NULL)) { + ret = tcp_fast_open(h, buf, s->uri, 0); + if (!ret) { + s->tcp_connected = 1; + if (!s->fastopen_success) { + ret = send(s->fd, buf, size, MSG_NOSIGNAL); + if (ret > 0) { + s->fastopen_success = 1; + } + return ret < 0 ? ff_neterrno() : ret; + } + return ret; + } else { + av_log(NULL, AV_LOG_WARNING, "tcp_fast_open is error ret = %d\n", ret); + return ret; + } + } + ret = send(s->fd, buf, size, MSG_NOSIGNAL); return ret < 0 ? ff_neterrno() : ret; } From 0351b8cde75e2405227193ba6834c653a85141f9 Mon Sep 17 00:00:00 2001 From: Wu Zhiqiang Date: Fri, 15 Jun 2018 17:00:00 +0800 Subject: [PATCH 2546/2557] lavf/hls: fix seek problem --- libavformat/hls.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index a66ea3d31c998..a663922fc9e19 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -2106,6 +2106,7 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) * stream */ if (pls->needed && !pls->pkt.data) { while (1) { + int64_t pkt_ts; int64_t ts_diff; AVRational tb; ret = av_read_frame(pls->ctx, &pls->pkt); @@ -2121,10 +2122,16 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) fill_timing_for_id3_timestamped_stream(pls); } - if (c->first_timestamp == AV_NOPTS_VALUE && - pls->pkt.dts != AV_NOPTS_VALUE) - c->first_timestamp = av_rescale_q(pls->pkt.dts, - get_timebase(pls), AV_TIME_BASE_Q); + if (pls->pkt.pts != AV_NOPTS_VALUE) + pkt_ts = pls->pkt.pts; + else if (pls->pkt.dts != AV_NOPTS_VALUE) + pkt_ts = pls->pkt.dts; + else + pkt_ts = AV_NOPTS_VALUE; + + + c->first_timestamp = s->start_time != AV_NOPTS_VALUE ? s->start_time : 0; + } if (pls->seek_timestamp == AV_NOPTS_VALUE) @@ -2133,15 +2140,16 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) if (pls->seek_stream_index < 0 || pls->seek_stream_index == pls->pkt.stream_index) { - if (pls->pkt.dts == AV_NOPTS_VALUE) { + if (pkt_ts == AV_NOPTS_VALUE) { pls->seek_timestamp = AV_NOPTS_VALUE; break; } tb = get_timebase(pls); - ts_diff = av_rescale_rnd(pls->pkt.dts, AV_TIME_BASE, + ts_diff = av_rescale_rnd(pkt_ts, AV_TIME_BASE, tb.den, AV_ROUND_DOWN) - pls->seek_timestamp; + if (ts_diff >= 0 && (pls->seek_flags & AVSEEK_FLAG_ANY || pls->pkt.flags & AV_PKT_FLAG_KEY)) { pls->seek_timestamp = AV_NOPTS_VALUE; From 77b2d49da0f2e83f9b854102dabfa0cda26c15c5 Mon Sep 17 00:00:00 2001 From: raymondzheng Date: Wed, 3 Jan 2018 17:39:13 +0800 Subject: [PATCH 2547/2557] avformat/http: add filesize report --- libavformat/http.c | 2 +- libavutil/application.c | 3 ++- libavutil/application.h | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libavformat/http.c b/libavformat/http.c index 8fe2fced1a3c1..aea6b57402bbf 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -570,7 +570,7 @@ static int http_open(URLContext *h, const char *uri, int flags, } av_application_will_http_open(s->app_ctx, (void*)h, uri); ret = http_open_cnx(h, options); - av_application_did_http_open(s->app_ctx, (void*)h, uri, ret, s->http_code); + av_application_did_http_open(s->app_ctx, (void*)h, uri, ret, s->http_code, s->filesize); if (ret < 0) av_dict_free(&s->chained_options); return ret; diff --git a/libavutil/application.c b/libavutil/application.c index 3a4ec85071815..99751876bd631 100644 --- a/libavutil/application.c +++ b/libavutil/application.c @@ -80,7 +80,7 @@ void av_application_will_http_open(AVApplicationContext *h, void *obj, const cha av_application_on_http_event(h, AVAPP_EVENT_WILL_HTTP_OPEN, &event); } -void av_application_did_http_open(AVApplicationContext *h, void *obj, const char *url, int error, int http_code) +void av_application_did_http_open(AVApplicationContext *h, void *obj, const char *url, int error, int http_code, int64_t filesize) { AVAppHttpEvent event = {0}; @@ -91,6 +91,7 @@ void av_application_did_http_open(AVApplicationContext *h, void *obj, const char av_strlcpy(event.url, url, sizeof(event.url)); event.error = error; event.http_code = http_code; + event.filesize = filesize; av_application_on_http_event(h, AVAPP_EVENT_DID_HTTP_OPEN, &event); } diff --git a/libavutil/application.h b/libavutil/application.h index 9e2c1f5b1aadb..72fe902789913 100644 --- a/libavutil/application.h +++ b/libavutil/application.h @@ -79,6 +79,7 @@ typedef struct AVAppHttpEvent int64_t offset; int error; int http_code; + int64_t filesize; } AVAppHttpEvent; typedef struct AVAppIOTraffic @@ -102,7 +103,7 @@ void av_application_closep(AVApplicationContext **ph); void av_application_on_http_event(AVApplicationContext *h, int event_type, AVAppHttpEvent *event); void av_application_will_http_open(AVApplicationContext *h, void *obj, const char *url); -void av_application_did_http_open(AVApplicationContext *h, void *obj, const char *url, int error, int http_code); +void av_application_did_http_open(AVApplicationContext *h, void *obj, const char *url, int error, int http_code, int64_t filesize); void av_application_will_http_seek(AVApplicationContext *h, void *obj, const char *url, int64_t offset); void av_application_did_http_seek(AVApplicationContext *h, void *obj, const char *url, int64_t offset, int error, int http_code); From a819a1e74ead4032eac968ab661de653be8cda7b Mon Sep 17 00:00:00 2001 From: raymondzheng Date: Fri, 23 Feb 2018 17:30:50 +0800 Subject: [PATCH 2548/2557] lavu/dict: fix crash when key is null --- libavutil/dict.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/dict.c b/libavutil/dict.c index 0ea71386e5aea..521d49f2f4078 100644 --- a/libavutil/dict.c +++ b/libavutil/dict.c @@ -42,7 +42,7 @@ AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key, { unsigned int i, j; - if (!m) + if (!m || !key) return NULL; if (prev) From 57aac86fe91f381cbe165e6ab70dad335c1b4f2c Mon Sep 17 00:00:00 2001 From: raymondzheng Date: Fri, 23 Feb 2018 17:32:44 +0800 Subject: [PATCH 2549/2557] libavformat/tcp: differentiate varieties of timeout events --- libavformat/tcp.c | 15 +++++++++++++-- libavutil/error.h | 4 ++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index 9cc55562933fc..54701021bca1a 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -489,6 +489,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags) if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, s->open_timeout / 1000, h, !!cur_ai->ai_next)) < 0) { + if (ret == AVERROR(ETIMEDOUT)) { + ret = AVERROR_TCP_CONNECT_TIMEOUT; + } if (av_application_on_tcp_did_open(s->app_ctx, ret, fd, &control)) goto fail1; if (ret == AVERROR_EXIT) @@ -754,8 +757,12 @@ static int tcp_read(URLContext *h, uint8_t *buf, int size) if (!(h->flags & AVIO_FLAG_NONBLOCK)) { ret = ff_network_wait_fd_timeout(s->fd, 0, h->rw_timeout, &h->interrupt_callback); - if (ret) + if (ret) { + if (ret == AVERROR(ETIMEDOUT)) { + ret = AVERROR_TCP_READ_TIMEOUT; + } return ret; + } } ret = recv(s->fd, buf, size, 0); if (ret == 0) @@ -772,8 +779,12 @@ static int tcp_write(URLContext *h, const uint8_t *buf, int size) if (!(h->flags & AVIO_FLAG_NONBLOCK)) { ret = ff_network_wait_fd_timeout(s->fd, 1, h->rw_timeout, &h->interrupt_callback); - if (ret) + if (ret) { + if (ret == AVERROR(ETIMEDOUT)) { + ret = AVERROR_TCP_WRITE_TIMEOUT; + } return ret; + } } if (s->fastopen && !s->tcp_connected && av_stristart(buf, "GET", NULL)) { diff --git a/libavutil/error.h b/libavutil/error.h index 71df4da353b9c..6b44d2cd22f3b 100644 --- a/libavutil/error.h +++ b/libavutil/error.h @@ -82,6 +82,10 @@ #define AV_ERROR_MAX_STRING_SIZE 64 +#define AVERROR_TCP_CONNECT_TIMEOUT -1001 +#define AVERROR_TCP_READ_TIMEOUT -1002 +#define AVERROR_TCP_WRITE_TIMEOUT -1003 + /** * Put a description of the AVERROR code errnum in errbuf. * In case of failure the global variable errno is set to indicate the From e51ca9353c7cc6247361c1f424e62e27cc93613a Mon Sep 17 00:00:00 2001 From: wuzhiqiang Date: Mon, 5 Mar 2018 11:31:32 +0800 Subject: [PATCH 2550/2557] lavf/hls: add segment io protocol option --- libavformat/hls.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index a663922fc9e19..db40420bddafe 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -217,6 +217,8 @@ typedef struct HLSContext { int http_persistent; int http_multiple; AVIOContext *playlist_pb; + int hls_io_protocol_enable; + char * hls_io_protocol; } HLSContext; static void free_segment_list(struct playlist *pls) @@ -657,6 +659,8 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, } } else if (av_strstart(proto_name, "http", NULL)) { is_http = 1; + } else if (c->hls_io_protocol_enable) { + ; } else return AVERROR_INVALIDDATA; @@ -714,6 +718,7 @@ static int parse_playlist(HLSContext *c, const char *url, int has_iv = 0; char key[MAX_URL_SIZE] = ""; char line[MAX_URL_SIZE]; + char io_url[MAX_URL_SIZE] = ""; const char *ptr; int close_in = 0; int64_t seg_offset = 0; @@ -741,6 +746,9 @@ static int parse_playlist(HLSContext *c, const char *url, if (!in) { AVDictionary *opts = NULL; + + av_dict_copy(&opts, c->avio_opts, 0); + /* Some HLS servers don't like being sent the range header */ av_dict_set(&opts, "seekable", "0", 0); @@ -899,7 +907,22 @@ static int parse_playlist(HLSContext *c, const char *url, } ff_make_absolute_url(tmp_str, sizeof(tmp_str), url, line); - seg->url = av_strdup(tmp_str); + + if (c->hls_io_protocol_enable) { + char * url_start = NULL; + if (c->hls_io_protocol) { + strcpy(io_url, c->hls_io_protocol); + } else if ((url_start = strstr(url,"http://")) || + (url_start = strstr(url,"https://"))) { + strncpy(io_url, url, url_start - url); + } + av_strlcat(io_url, tmp_str, sizeof(io_url)); + seg->url = av_strdup(io_url); + memset(io_url, 0, sizeof(io_url)); + } else { + seg->url = av_strdup(tmp_str); + } + if (!seg->url) { av_free(seg->key); av_free(seg); @@ -1474,7 +1497,13 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) av_log(v->parent, AV_LOG_WARNING, "Failed to open segment %d of playlist %d\n", v->cur_seq_no, v->index); - v->cur_seq_no += 1; + + if (c->hls_io_protocol_enable && (parse_playlist(c, v->url, v, NULL)) < 0) { + av_log(NULL, AV_LOG_INFO, "Failed to reload playlist %d\n", + v->index); + } else { + v->cur_seq_no += 1; + } goto reload; } just_opened = 1; @@ -2111,8 +2140,15 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) AVRational tb; ret = av_read_frame(pls->ctx, &pls->pkt); if (ret < 0) { - if (!avio_feof(&pls->pb) && ret != AVERROR_EOF) + //when error occur try to renew m3u8 + if (c->hls_io_protocol_enable && (parse_playlist(c, pls->url, pls, NULL)) < 0) { + av_log(NULL, AV_LOG_INFO, "Failed to reload playlist %d\n", + pls->index); + } + + if (!avio_feof(&pls->pb) && ret != AVERROR_EOF) { return ret; + } reset_packet(&pls->pkt); break; } else { @@ -2378,6 +2414,10 @@ static const AVOption hls_options[] = { OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, {"http_multiple", "Use multiple HTTP connections for fetching segments", OFFSET(http_multiple), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, FLAGS}, + {"hls_io_protocol", "force segment io protocol", + OFFSET(hls_io_protocol), AV_OPT_TYPE_STRING, {.str= NULL}, 0, 0, FLAGS}, + {"hls_io_protocol_enable", "enable auto copy segment io protocol from playlist", + OFFSET(hls_io_protocol_enable), AV_OPT_TYPE_BOOL, {.i64= 0}, 0, 1, FLAGS}, {NULL} }; From 5d39ac622f503b59fab1cc42ed14c8e3865b3b5f Mon Sep 17 00:00:00 2001 From: Wu Zhiqiang Date: Fri, 15 Jun 2018 17:10:13 +0800 Subject: [PATCH 2551/2557] lavf/utils: find stream info without decoding --- libavcodec/h264_ps.c | 8 +++--- libavformat/concatdec.c | 15 +++++++++++ libavformat/isom.h | 2 ++ libavformat/mov.c | 16 +++++++++++- libavformat/utils.c | 57 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 5 deletions(-) diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index 8d1ef831fadff..15fb8b6265482 100644 --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -469,7 +469,7 @@ int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx, } sps->ref_frame_count = get_ue_golomb_31(gb); - if (avctx->codec_tag == MKTAG('S', 'M', 'V', '2')) + if (avctx && avctx->codec_tag == MKTAG('S', 'M', 'V', '2')) sps->ref_frame_count = FFMAX(2, sps->ref_frame_count); if (sps->ref_frame_count > MAX_DELAYED_PIC_COUNT) { av_log(avctx, AV_LOG_ERROR, @@ -517,7 +517,7 @@ int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx, int width = 16 * sps->mb_width; int height = 16 * sps->mb_height; - if (avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) { + if (avctx && avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) { av_log(avctx, AV_LOG_DEBUG, "discarding sps cropping, original " "values are l:%d r:%d t:%d b:%d\n", crop_left, crop_right, crop_top, crop_bottom); @@ -588,7 +588,7 @@ int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx, if (!sps->sar.den) sps->sar.den = 1; - if (avctx->debug & FF_DEBUG_PICT_INFO) { + if (avctx && avctx->debug & FF_DEBUG_PICT_INFO) { static const char csp[4][5] = { "Gray", "420", "422", "444" }; av_log(avctx, AV_LOG_DEBUG, "sps:%u profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%u/%u/%u/%u %s %s %"PRId32"/%"PRId32" b%d reo:%d\n", @@ -838,7 +838,7 @@ int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avct if (pps->chroma_qp_index_offset[0] != pps->chroma_qp_index_offset[1]) pps->chroma_qp_diff = 1; - if (avctx->debug & FF_DEBUG_PICT_INFO) { + if (avctx && avctx->debug & FF_DEBUG_PICT_INFO) { av_log(avctx, AV_LOG_DEBUG, "pps:%u sps:%u %s slice_groups:%d ref:%u/%u %s qp:%d/%d/%d/%d %s %s %s %s\n", pps_id, pps->sps_id, diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 6da37ea6f4b05..f05e935cb0691 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -331,6 +331,12 @@ static int open_file(AVFormatContext *avf, unsigned fileno) return AVERROR(ENOMEM); new_avf->flags |= avf->flags & ~AVFMT_FLAG_CUSTOM_IO; + +#ifdef FF_API_LAVF_KEEPSIDE_FLAG + if (avf->flags & AVFMT_FLAG_KEEP_SIDE_DATA) { + new_avf->flags |= AVFMT_FLAG_KEEP_SIDE_DATA; + } +#endif new_avf->interrupt_callback = avf->interrupt_callback; if ((ret = ff_copy_whiteblacklists(new_avf, avf)) < 0) @@ -349,6 +355,15 @@ static int open_file(AVFormatContext *avf, unsigned fileno) } } + t = av_dict_get(tmp, "nb-streams", NULL, AV_DICT_MATCH_CASE); + if (t) { + int nb_streams = (int) strtol(t->value, NULL, 10); + if (nb_streams > 0) { + av_dict_set_int(&new_avf->metadata, "nb-streams", nb_streams, 0); + av_dict_set_int(&cat->options, "nb-streams", 0, 0); + } + } + ret = avformat_open_input(&new_avf, file->url, NULL, &tmp); av_dict_free(&tmp); if (ret < 0 || diff --git a/libavformat/isom.h b/libavformat/isom.h index 4da34142f0669..bff5622dfb3b8 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -274,6 +274,8 @@ typedef struct MOVContext { uint8_t *decryption_key; int decryption_key_len; int enable_drefs; + int allow_multi_extradata; + int has_extradata; int32_t movie_display_matrix[3][3]; ///< display matrix from mvhd } MOVContext; diff --git a/libavformat/mov.c b/libavformat/mov.c index 21c8ac3b9f101..01b315ce8cdcf 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1892,8 +1892,14 @@ static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (type == MKTAG('f','i','e','l') && size == atom.size) return mov_read_default(c, pb, atom); } + c->has_extradata = 1; if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) { - av_log(c, AV_LOG_WARNING, "ignoring multiple glbl\n"); + if (c->allow_multi_extradata) { + av_log(c, AV_LOG_WARNING, "found multiple glbl\n"); + } else { + av_log(c, AV_LOG_WARNING, "ignoring multiple glbl\n"); + return 0; + } return 0; } av_freep(&st->codecpar->extradata); @@ -7186,6 +7192,12 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) return ret; } } + if (mov->allow_multi_extradata && mov->has_extradata) { + mov->has_extradata = 0; + ret = mov_change_extradata(sc, pkt); + if (ret < 0) + return ret; + } if (mov->aax_mode) aax_filter(pkt->data, pkt->size, mov); @@ -7367,6 +7379,8 @@ static const AVOption mov_options[] = { { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, + {"allow_multi_extradata", "", OFFSET(allow_multi_extradata), AV_OPT_TYPE_BOOL, {.i64 = 0}, + 0, 1, FLAGS}, { NULL }, }; diff --git a/libavformat/utils.c b/libavformat/utils.c index a960ecea0e621..9252af01ea2a6 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -3575,6 +3575,63 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) int eof_reached = 0; int *missing_streams = av_opt_ptr(ic->iformat->priv_class, ic->priv_data, "missing_streams"); + AVDictionaryEntry *t; + + t = av_dict_get(ic->metadata, "nb-streams", NULL, AV_DICT_MATCH_CASE); + if (t) { + int nb_streams = (int) strtol(t->value, NULL, 10); + if (nb_streams > 0) { + int64_t read_size = 0; + int found_all_streams = 0; + while (!found_all_streams) { + if (read_size >= probesize) { + av_log(NULL, AV_LOG_INFO, "probe fail\n"); + return ic->nb_streams; + } + + ret = read_frame_internal(ic, &pkt1); + if (ret == AVERROR(EAGAIN)) + continue; + if (ret < 0) { + /* EOF or error*/ + eof_reached = 1; + break; + } + pkt = &pkt1; + + if (!(ic->streams[pkt->stream_index]->disposition & AV_DISPOSITION_ATTACHED_PIC)) + read_size += pkt->size; + + if (!(ic->flags & AVFMT_FLAG_NOBUFFER)) { + ret = add_to_pktbuf(&ic->internal->packet_buffer, pkt, + &ic->internal->packet_buffer_end, 0); + if (ret < 0) + return ret; + } + + for(i = 0; i < ic->nb_streams; i++) { + int64_t cur_start_time = AV_NOPTS_VALUE; + if (ic->streams[i]->start_time != AV_NOPTS_VALUE) { + cur_start_time = av_rescale_q(ic->streams[i]->start_time, + ic->streams[i]->time_base, + AV_TIME_BASE_Q); + } + if (cur_start_time != AV_NOPTS_VALUE && + (ic->start_time == AV_NOPTS_VALUE || ic->start_time > cur_start_time)){ + ic->start_time = cur_start_time; + } + } + + if (ic->nb_streams >= nb_streams && ic->start_time != AV_NOPTS_VALUE) { + av_log(NULL, AV_LOG_INFO, "probe pass\n"); + found_all_streams = 1; + } + } + av_dict_set_int(&ic->metadata, "nb-streams", 0, 0); + return ret < 0 ? ret : ic->nb_streams; + } + } + flush_codecs = probesize > 0; av_opt_set(ic, "skip_clear", "1", AV_OPT_SEARCH_CHILDREN); From 26d5b04553ac5995fea72e1fe60464ba01892462 Mon Sep 17 00:00:00 2001 From: raymondzheng Date: Tue, 12 Jun 2018 17:37:06 +0800 Subject: [PATCH 2552/2557] avformat/tcp: dns-cache use uri key --- libavformat/tcp.c | 52 +++++++++++++++++++++---------------------- libavutil/dns_cache.c | 38 +++++++++++++++---------------- libavutil/dns_cache.h | 8 +++---- 3 files changed, 48 insertions(+), 50 deletions(-) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index 54701021bca1a..d6ce413235fbe 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -78,7 +78,7 @@ static const AVOption options[] = { { "addrinfo_one_by_one", "parse addrinfo one by one in getaddrinfo()", OFFSET(addrinfo_one_by_one), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = D|E }, { "addrinfo_timeout", "set timeout (in microseconds) for getaddrinfo()", OFFSET(addrinfo_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, - { "dns_cache_timeout", "dns cache TTL (in microseconds)", OFFSET(dns_cache_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "dns_cache_timeout", "dns cache TTL (in microseconds)", OFFSET(dns_cache_timeout), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT64_MAX, .flags = D|E }, { "dns_cache_clear", "clear dns cache", OFFSET(dns_cache_clear), AV_OPT_TYPE_INT, { .i64 = 0}, -1, INT_MAX, .flags = D|E }, { "fastopen", "enable fastopen", OFFSET(fastopen), AV_OPT_TYPE_INT, { .i64 = 0}, 0, INT_MAX, .flags = D|E }, { NULL } @@ -350,7 +350,6 @@ static int tcp_open(URLContext *h, const char *uri, int flags) int ret; char hostname[1024],proto[1024],path[1024]; char portstr[10]; - char hostname_bak[1024] = {0}; AVAppTcpIOControl control = {0}; DnsCacheEntry *dns_entry = NULL; @@ -404,12 +403,11 @@ static int tcp_open(URLContext *h, const char *uri, int flags) hints.ai_flags |= AI_PASSIVE; if (s->dns_cache_timeout > 0) { - memcpy(hostname_bak, hostname, 1024); if (s->dns_cache_clear) { - av_log(NULL, AV_LOG_INFO, "will delete cache entry, hostname = %s\n", hostname); - remove_dns_cache_entry(hostname); + av_log(NULL, AV_LOG_INFO, "will delete dns cache entry, uri = %s\n", uri); + remove_dns_cache_entry(uri); } else { - dns_entry = get_dns_cache_reference(hostname); + dns_entry = get_dns_cache_reference(uri); } } @@ -434,7 +432,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) cur_ai = ai; } else { - av_log(NULL, AV_LOG_INFO, "Hit DNS cache hostname = %s\n", hostname); + av_log(NULL, AV_LOG_INFO, "hit dns cache uri = %s\n", uri); cur_ai = dns_entry->res; } @@ -503,10 +501,11 @@ static int tcp_open(URLContext *h, const char *uri, int flags) if (ret) { av_log(NULL, AV_LOG_WARNING, "terminated by application in AVAPP_CTRL_DID_TCP_OPEN"); goto fail1; - } else if (!dns_entry && strcmp(control.ip, hostname_bak)) { - add_dns_cache_entry(hostname_bak, cur_ai, s->dns_cache_timeout); - av_log(NULL, AV_LOG_INFO, "Add dns cache hostname = %s, ip = %s\n", hostname_bak , control.ip); + } else if (!dns_entry && !strstr(uri, control.ip) && s->dns_cache_timeout > 0) { + add_dns_cache_entry(uri, cur_ai, s->dns_cache_timeout); + av_log(NULL, AV_LOG_INFO, "add dns cache uri = %s, ip = %s\n", uri , control.ip); } + av_log(NULL, AV_LOG_INFO, "tcp did open uri = %s, ip = %s\n", uri , control.ip); } } @@ -514,7 +513,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) s->fd = fd; if (dns_entry) { - release_dns_cache_reference(hostname_bak, &dns_entry); + release_dns_cache_reference(uri, &dns_entry); } else { freeaddrinfo(ai); } @@ -534,9 +533,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags) closesocket(fd); if (dns_entry) { - av_log(NULL, AV_LOG_ERROR, "Hit dns cache but connect fail hostname = %s, ip = %s\n", hostname , control.ip); - release_dns_cache_reference(hostname_bak, &dns_entry); - remove_dns_cache_entry(hostname_bak); + av_log(NULL, AV_LOG_ERROR, "hit dns cache but connect fail uri = %s, ip = %s\n", uri , control.ip); + release_dns_cache_reference(uri, &dns_entry); + remove_dns_cache_entry(uri); } else { freeaddrinfo(ai); } @@ -555,7 +554,6 @@ static int tcp_fast_open(URLContext *h, const char *http_request, const char *ur int ret; char hostname[1024],proto[1024],path[1024]; char portstr[10]; - char hostname_bak[1024] = {0}; AVAppTcpIOControl control = {0}; DnsCacheEntry *dns_entry = NULL; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), @@ -597,12 +595,11 @@ static int tcp_fast_open(URLContext *h, const char *http_request, const char *ur hints.ai_flags |= AI_PASSIVE; if (s->dns_cache_timeout > 0) { - memcpy(hostname_bak, hostname, 1024); if (s->dns_cache_clear) { - av_log(NULL, AV_LOG_INFO, "will delete cache entry, hostname = %s\n", hostname); - remove_dns_cache_entry(hostname); + av_log(NULL, AV_LOG_INFO, "will delete dns cache entry, uri = %s\n", uri); + remove_dns_cache_entry(uri); } else { - dns_entry = get_dns_cache_reference(hostname); + dns_entry = get_dns_cache_reference(uri); } } @@ -627,7 +624,7 @@ static int tcp_fast_open(URLContext *h, const char *http_request, const char *ur cur_ai = ai; } else { - av_log(NULL, AV_LOG_INFO, "Hit DNS cache hostname = %s\n", hostname); + av_log(NULL, AV_LOG_INFO, "hit dns cache uri = %s\n", uri); cur_ai = dns_entry->res; } @@ -693,10 +690,11 @@ static int tcp_fast_open(URLContext *h, const char *http_request, const char *ur if (ret) { av_log(NULL, AV_LOG_WARNING, "terminated by application in AVAPP_CTRL_DID_TCP_OPEN"); goto fail1; - } else if (!dns_entry && strcmp(control.ip, hostname_bak)) { - add_dns_cache_entry(hostname_bak, cur_ai, s->dns_cache_timeout); - av_log(NULL, AV_LOG_INFO, "Add dns cache hostname = %s, ip = %s\n", hostname_bak , control.ip); + } else if (!dns_entry && !strstr(uri, control.ip) && s->dns_cache_timeout > 0) { + add_dns_cache_entry(uri, cur_ai, s->dns_cache_timeout); + av_log(NULL, AV_LOG_INFO, "add dns cache uri = %s, ip = %s\n", uri , control.ip); } + av_log(NULL, AV_LOG_INFO, "tcp did open uri = %s, ip = %s\n", uri , control.ip); } } @@ -704,7 +702,7 @@ static int tcp_fast_open(URLContext *h, const char *http_request, const char *ur s->fd = fd; if (dns_entry) { - release_dns_cache_reference(hostname_bak, &dns_entry); + release_dns_cache_reference(uri, &dns_entry); } else { freeaddrinfo(ai); } @@ -724,9 +722,9 @@ static int tcp_fast_open(URLContext *h, const char *http_request, const char *ur closesocket(fd); if (dns_entry) { - av_log(NULL, AV_LOG_ERROR, "Hit dns cache but connect fail hostname = %s, ip = %s\n", hostname , control.ip); - release_dns_cache_reference(hostname_bak, &dns_entry); - remove_dns_cache_entry(hostname_bak); + av_log(NULL, AV_LOG_ERROR, "hit dns cache but connect fail uri = %s, ip = %s\n", uri , control.ip); + release_dns_cache_reference(uri, &dns_entry); + remove_dns_cache_entry(uri); } else { freeaddrinfo(ai); } diff --git a/libavutil/dns_cache.c b/libavutil/dns_cache.c index c70540146e814..5135c0a5ce604 100644 --- a/libavutil/dns_cache.c +++ b/libavutil/dns_cache.c @@ -60,10 +60,10 @@ static void free_private_addrinfo(struct addrinfo **p_ai) { } } -static int inner_remove_dns_cache(char *hostname, DnsCacheEntry *dns_cache_entry) { +static int inner_remove_dns_cache(const char *uri, DnsCacheEntry *dns_cache_entry) { if (context && dns_cache_entry) { if (dns_cache_entry->ref_count == 0) { - av_dict_set_int(&context->dns_dictionary, hostname, 0, 0); + av_dict_set_int(&context->dns_dictionary, uri, 0, 0); free_private_addrinfo(&dns_cache_entry->res); av_freep(&dns_cache_entry); } else { @@ -74,7 +74,7 @@ static int inner_remove_dns_cache(char *hostname, DnsCacheEntry *dns_cache_entry return 0; } -static DnsCacheEntry *new_dns_cache_entry(char *hostname, struct addrinfo *cur_ai, int64_t timeout) { +static DnsCacheEntry *new_dns_cache_entry(const char *uri, struct addrinfo *cur_ai, int64_t timeout) { DnsCacheEntry *new_entry = NULL; int64_t cur_time = av_gettime_relative(); @@ -115,12 +115,12 @@ static DnsCacheEntry *new_dns_cache_entry(char *hostname, struct addrinfo *cur_a return NULL; } -DnsCacheEntry *get_dns_cache_reference(char *hostname) { +DnsCacheEntry *get_dns_cache_reference(const char *uri) { AVDictionaryEntry *elem = NULL; DnsCacheEntry *dns_cache_entry = NULL; int64_t cur_time = av_gettime_relative(); - if (cur_time < 0 || !hostname || strlen(hostname) == 0) { + if (cur_time < 0 || !uri || strlen(uri) == 0) { return NULL; } @@ -132,12 +132,12 @@ DnsCacheEntry *get_dns_cache_reference(char *hostname) { if (context && context->initialized) { pthread_mutex_lock(&context->dns_dictionary_mutex); - elem = av_dict_get(context->dns_dictionary, hostname, NULL, AV_DICT_MATCH_CASE); + elem = av_dict_get(context->dns_dictionary, uri, NULL, AV_DICT_MATCH_CASE); if (elem) { dns_cache_entry = (DnsCacheEntry *) (intptr_t) strtoll(elem->value, NULL, 10); if (dns_cache_entry) { if (dns_cache_entry->expired_time < cur_time) { - inner_remove_dns_cache(hostname, dns_cache_entry); + inner_remove_dns_cache(uri, dns_cache_entry); dns_cache_entry = NULL; } else { dns_cache_entry->ref_count++; @@ -150,10 +150,10 @@ DnsCacheEntry *get_dns_cache_reference(char *hostname) { return dns_cache_entry; } -int release_dns_cache_reference(char *hostname, DnsCacheEntry **p_entry) { +int release_dns_cache_reference(const char *uri, DnsCacheEntry **p_entry) { DnsCacheEntry *entry = *p_entry; - if (!hostname || strlen(hostname) == 0) { + if (!uri || strlen(uri) == 0) { return -1; } @@ -161,7 +161,7 @@ int release_dns_cache_reference(char *hostname, DnsCacheEntry **p_entry) { pthread_mutex_lock(&context->dns_dictionary_mutex); entry->ref_count--; if (entry->delete_flag && entry->ref_count == 0) { - inner_remove_dns_cache(hostname, entry); + inner_remove_dns_cache(uri, entry); entry = NULL; } pthread_mutex_unlock(&context->dns_dictionary_mutex); @@ -169,21 +169,21 @@ int release_dns_cache_reference(char *hostname, DnsCacheEntry **p_entry) { return 0; } -int remove_dns_cache_entry(char *hostname) { +int remove_dns_cache_entry(const char *uri) { AVDictionaryEntry *elem = NULL; DnsCacheEntry *dns_cache_entry = NULL; - if (!hostname || strlen(hostname) == 0) { + if (!uri || strlen(uri) == 0) { return -1; } if (context && context->initialized) { pthread_mutex_lock(&context->dns_dictionary_mutex); - elem = av_dict_get(context->dns_dictionary, hostname, NULL, AV_DICT_MATCH_CASE); + elem = av_dict_get(context->dns_dictionary, uri, NULL, AV_DICT_MATCH_CASE); if (elem) { dns_cache_entry = (DnsCacheEntry *) (intptr_t) strtoll(elem->value, NULL, 10); if (dns_cache_entry) { - inner_remove_dns_cache(hostname, dns_cache_entry); + inner_remove_dns_cache(uri, dns_cache_entry); } } pthread_mutex_unlock(&context->dns_dictionary_mutex); @@ -192,12 +192,12 @@ int remove_dns_cache_entry(char *hostname) { return 0; } -int add_dns_cache_entry(char *hostname, struct addrinfo *cur_ai, int64_t timeout) { +int add_dns_cache_entry(const char *uri, struct addrinfo *cur_ai, int64_t timeout) { DnsCacheEntry *new_entry = NULL; DnsCacheEntry *old_entry = NULL; AVDictionaryEntry *elem = NULL; - if (!hostname || strlen(hostname) == 0 || timeout <= 0) { + if (!uri || strlen(uri) == 0 || timeout <= 0) { goto fail; } @@ -207,7 +207,7 @@ int add_dns_cache_entry(char *hostname, struct addrinfo *cur_ai, int64_t timeout if (context && context->initialized) { pthread_mutex_lock(&context->dns_dictionary_mutex); - elem = av_dict_get(context->dns_dictionary, hostname, NULL, AV_DICT_MATCH_CASE); + elem = av_dict_get(context->dns_dictionary, uri, NULL, AV_DICT_MATCH_CASE); if (elem) { old_entry = (DnsCacheEntry *) (intptr_t) strtoll(elem->value, NULL, 10); if (old_entry) { @@ -215,9 +215,9 @@ int add_dns_cache_entry(char *hostname, struct addrinfo *cur_ai, int64_t timeout goto fail; } } - new_entry = new_dns_cache_entry(hostname, cur_ai, timeout); + new_entry = new_dns_cache_entry(uri, cur_ai, timeout); if (new_entry) { - av_dict_set_int(&context->dns_dictionary, hostname, (int64_t) (intptr_t) new_entry, 0); + av_dict_set_int(&context->dns_dictionary, uri, (int64_t) (intptr_t) new_entry, 0); } pthread_mutex_unlock(&context->dns_dictionary_mutex); diff --git a/libavutil/dns_cache.h b/libavutil/dns_cache.h index a2ed92e6f54a8..69b47bbc43772 100644 --- a/libavutil/dns_cache.h +++ b/libavutil/dns_cache.h @@ -30,9 +30,9 @@ typedef struct DnsCacheEntry { struct addrinfo *res; // construct by private function, not support ai_next and ai_canonname, can only be released using free_private_addrinfo } DnsCacheEntry; -DnsCacheEntry *get_dns_cache_reference(char *hostname); -int release_dns_cache_reference(char *hostname, DnsCacheEntry **p_entry); -int remove_dns_cache_entry(char *hostname); -int add_dns_cache_entry(char *hostname, struct addrinfo *cur_ai, int64_t timeout); +DnsCacheEntry *get_dns_cache_reference(const char *uri); +int release_dns_cache_reference(const char *uri, DnsCacheEntry **p_entry); +int remove_dns_cache_entry(const char *uri); +int add_dns_cache_entry(const char *uri, struct addrinfo *cur_ai, int64_t timeout); #endif /* AVUTIL_DNS_CACHE_H */ From 8e2b6e7a431e18b4ff8e18102959938168278067 Mon Sep 17 00:00:00 2001 From: wuzhiqiang Date: Tue, 19 Jun 2018 10:53:30 +0800 Subject: [PATCH 2553/2557] lavf/utils: fix compile error --- libavformat/utils.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index 9252af01ea2a6..dfbfb0a8d6436 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -3603,8 +3603,9 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) read_size += pkt->size; if (!(ic->flags & AVFMT_FLAG_NOBUFFER)) { - ret = add_to_pktbuf(&ic->internal->packet_buffer, pkt, - &ic->internal->packet_buffer_end, 0); + ret = ff_packet_list_put(&ic->internal->raw_packet_buffer, + &ic->internal->raw_packet_buffer_end, + pkt,0); if (ret < 0) return ret; } From db3cb6ff0961db6e1264d801b13ead791d186b2b Mon Sep 17 00:00:00 2001 From: wuzhiqiang Date: Thu, 21 Jun 2018 13:29:51 +0800 Subject: [PATCH 2554/2557] Revert "libavformat: not treat 0 as EOF" This reverts commit 858db4b01fa2b55ee55056c033054ca54ac9b0fd. --- libavformat/avio.c | 6 ++---- libavformat/aviobuf.c | 24 +++++++++++++----------- libavformat/cache.c | 4 ++-- libavformat/concat.c | 9 ++++----- libavformat/http.c | 10 +--------- 5 files changed, 22 insertions(+), 31 deletions(-) diff --git a/libavformat/avio.c b/libavformat/avio.c index 63e82872f7ce0..eff98e9ef40a5 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -391,10 +391,8 @@ static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf, } av_usleep(1000); } - } else if (ret == AVERROR_EOF) - return (len > 0) ? len : AVERROR_EOF; - else if (ret < 0) - return ret; + } else if (ret < 1) + return (ret < 0 && ret != AVERROR_EOF) ? ret : len; if (ret) { fast_retries = FFMAX(fast_retries, 2); wait_since = 0; diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index e5a44c3f3e24b..52620c1a92c3d 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -578,14 +578,16 @@ static void fill_buffer(AVIOContext *s) len = s->orig_buffer_size; } - len = read_packet_wrapper(s, dst, len); - if (len == AVERROR_EOF) { + if (s->read_packet) + len = s->read_packet(s->opaque, dst, len); + else + len = 0; + if (len <= 0) { /* do not modify buffer if EOF reached so that a seek back can be done without rereading data */ s->eof_reached = 1; - } else if (len < 0) { - s->eof_reached = 1; - s->error= len; + if (len < 0) + s->error = len; } else { s->pos += len; s->buf_ptr = dst; @@ -651,15 +653,15 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size) if (len == 0 || s->write_flag) { if((s->direct || size > s->buffer_size) && !s->update_checksum) { // bypass the buffer and read data directly into buf - len = read_packet_wrapper(s, buf, size); - if (len == AVERROR_EOF) { + if(s->read_packet) + len = s->read_packet(s->opaque, buf, size); + + if (len <= 0) { /* do not modify buffer if EOF reached so that a seek back can be done without rereading data */ s->eof_reached = 1; - break; - } else if (len < 0) { - s->eof_reached = 1; - s->error= len; + if(len<0) + s->error= len; break; } else { s->pos += len; diff --git a/libavformat/cache.c b/libavformat/cache.c index 66bbbf54c9abf..6aabca2e7835a 100644 --- a/libavformat/cache.c +++ b/libavformat/cache.c @@ -201,7 +201,7 @@ static int cache_read(URLContext *h, unsigned char *buf, int size) } r = ffurl_read(c->inner, buf, size); - if (r == AVERROR_EOF && size>0) { + if (r == 0 && size>0) { c->is_true_eof = 1; av_assert0(c->end >= c->logical_pos); } @@ -263,7 +263,7 @@ static int64_t cache_seek(URLContext *h, int64_t pos, int whence) if (whence == SEEK_SET) size = FFMIN(sizeof(tmp), pos - c->logical_pos); ret = cache_read(h, tmp, size); - if (ret == AVERROR_EOF && whence == SEEK_END) { + if (ret == 0 && whence == SEEK_END) { av_assert0(c->is_true_eof); goto resolve_eof; } diff --git a/libavformat/concat.c b/libavformat/concat.c index 19c83c309acff..46b520fe80443 100644 --- a/libavformat/concat.c +++ b/libavformat/concat.c @@ -135,20 +135,19 @@ static int concat_read(URLContext *h, unsigned char *buf, int size) while (size > 0) { result = ffurl_read(nodes[i].uc, buf, size); - if (result == AVERROR_EOF) { + if (result < 0) + return total ? total : result; + if (!result) { if (i + 1 == data->length || ffurl_seek(nodes[++i].uc, 0, SEEK_SET) < 0) break; - result = 0; } - if (result < 0) - return total ? total : result; total += result; buf += result; size -= result; } data->current = i; - return total ? total : result; + return total; } static int64_t concat_seek(URLContext *h, int64_t pos, int whence) diff --git a/libavformat/http.c b/libavformat/http.c index aea6b57402bbf..01535169db245 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -1387,16 +1387,8 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size) "Chunked encoding data size: %"PRIu64"\n", s->chunksize); - if (!s->chunksize && s->multiple_requests) { - http_get_line(s, line, sizeof(line)); // read empty chunk - s->chunkend = 1; + if (!s->chunksize) return 0; - } - else if (!s->chunksize) { - av_log(h, AV_LOG_DEBUG, "Last chunk received, closing conn\n"); - ffurl_closep(&s->hd); - return 0; - } else if (s->chunksize == UINT64_MAX) { av_log(h, AV_LOG_ERROR, "Invalid chunk size %"PRIu64"\n", s->chunksize); From 4498d1edc1d718e1d1dd5a1ca68d89da23167d70 Mon Sep 17 00:00:00 2001 From: wuzhiqiang Date: Thu, 21 Jun 2018 18:38:59 +0800 Subject: [PATCH 2555/2557] lavf/utils: add register demuxer method --- libavformat/allformats.c | 1 + libavformat/ijkutils.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/libavformat/allformats.c b/libavformat/allformats.c index d582778b3b349..5362b2e099148 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -452,6 +452,7 @@ extern AVInputFormat ff_xwma_demuxer; extern AVInputFormat ff_yop_demuxer; extern AVInputFormat ff_yuv4mpegpipe_demuxer; extern AVOutputFormat ff_yuv4mpegpipe_muxer; +extern AVInputFormat ff_ijklivehook_demuxer; /* image demuxers */ extern AVInputFormat ff_image_bmp_pipe_demuxer; extern AVInputFormat ff_image_dds_pipe_demuxer; diff --git a/libavformat/ijkutils.c b/libavformat/ijkutils.c index 3b883fd6f4833..d3b6de44373dd 100644 --- a/libavformat/ijkutils.c +++ b/libavformat/ijkutils.c @@ -23,6 +23,7 @@ #include #include "url.h" +#include "avformat.h" #define IJK_FF_PROTOCOL(x) \ @@ -65,3 +66,32 @@ IJK_DUMMY_PROTOCOL(ijklongurl); IJK_DUMMY_PROTOCOL(ijksegment); IJK_DUMMY_PROTOCOL(ijktcphook); IJK_DUMMY_PROTOCOL(ijkio); + +#define IJK_FF_DEMUXER(x) \ +extern AVInputFormat ff_##x##_demuxer; \ +int ijkav_register_##x##_demuxer(AVInputFormat *demuxer, int demuxer_size); \ +int ijkav_register_##x##_demuxer(AVInputFormat *demuxer, int demuxer_size) \ +{ \ + if (demuxer_size != sizeof(AVInputFormat)) { \ + av_log(NULL, AV_LOG_ERROR, "ijkav_register_##x##_demuxer: ABI mismatch.\n"); \ + return -1; \ + } \ + memcpy(&ff_##x##_demuxer, demuxer, demuxer_size); \ + return 0; \ +} + +#define IJK_DUMMY_DEMUXER(x) \ +IJK_FF_DEMUXER(x); \ +static const AVClass ijk_##x##_demuxer_class = { \ + .class_name = #x, \ + .item_name = av_default_item_name, \ + .version = LIBAVUTIL_VERSION_INT, \ + }; \ + \ +AVInputFormat ff_##x##_demuxer = { \ + .name = #x, \ + .priv_data_size = 1, \ + .priv_class = &ijk_##x##_demuxer_class, \ +}; + +IJK_DUMMY_DEMUXER(ijklivehook); From ab5142d62b168d4189d36b00f9ef8378968666b8 Mon Sep 17 00:00:00 2001 From: yangdan07 Date: Thu, 3 Sep 2020 17:23:34 +0800 Subject: [PATCH 2556/2557] feat(libavformat/makefile): add the ffmpeg interface for las demo --- libavformat/Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavformat/Makefile b/libavformat/Makefile index b60a7b513f9c9..dd88765801400 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -7,6 +7,11 @@ HEADERS = avformat.h \ avc.h \ url.h \ internal.h \ + avio_internal.h \ + flv.h \ + id3v2.h \ + os_support.h \ + metadata.h \ OBJS = allformats.o \ avio.o \ From f4e792b8e33e62268e41d71a6935058cbd7859ba Mon Sep 17 00:00:00 2001 From: johnwenjunwu Date: Tue, 20 Apr 2021 18:26:18 +0800 Subject: [PATCH 2557/2557] lavf/utils: register ijklas demuxer --- libavformat/allformats.c | 1 + libavformat/ijkutils.c | 1 + 2 files changed, 2 insertions(+) diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 5362b2e099148..2e733d9282f53 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -453,6 +453,7 @@ extern AVInputFormat ff_yop_demuxer; extern AVInputFormat ff_yuv4mpegpipe_demuxer; extern AVOutputFormat ff_yuv4mpegpipe_muxer; extern AVInputFormat ff_ijklivehook_demuxer; +extern AVInputFormat ff_ijklas_demuxer; /* image demuxers */ extern AVInputFormat ff_image_bmp_pipe_demuxer; extern AVInputFormat ff_image_dds_pipe_demuxer; diff --git a/libavformat/ijkutils.c b/libavformat/ijkutils.c index d3b6de44373dd..c6d013486d2e1 100644 --- a/libavformat/ijkutils.c +++ b/libavformat/ijkutils.c @@ -95,3 +95,4 @@ AVInputFormat ff_##x##_demuxer = { \ }; IJK_DUMMY_DEMUXER(ijklivehook); +IJK_DUMMY_DEMUXER(ijklas);